Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 17 Dec 2019 07:26:53 +0000
From:      bugzilla-noreply@freebsd.org
To:        bugs@FreeBSD.org
Subject:   [Bug 242677] multicast: setsockopt(...IP_DROP_MEMBERSHIP...) doesn't lead to sending IGMP packet.
Message-ID:  <bug-242677-227@https.bugs.freebsd.org/bugzilla/>

next in thread | raw e-mail | index | archive | help
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=3D242677

            Bug ID: 242677
           Summary: multicast: setsockopt(...IP_DROP_MEMBERSHIP...)
                    doesn't lead to sending IGMP packet.
           Product: Base System
           Version: CURRENT
          Hardware: Any
                OS: Any
            Status: New
          Severity: Affects Many People
          Priority: ---
         Component: kern
          Assignee: bugs@FreeBSD.org
          Reporter: aleksandr.fedorov@itglobal.com
 Attachment #210002 text/plain
         mime type:

Created attachment 210002
  --> https://bugs.freebsd.org/bugzilla/attachment.cgi?id=3D210002&action=
=3Dedit
Test code.

Revision 355322 fixes multicast in case of closing the socket.

But the problem remains if you try to exit the multicast group before closi=
ng
the socket.

If you run test code from attachment.
#./mcasttest
Add membership
igb1:
        inet 192.168.1.55
        igmpv3 rv 2 qi 125 qri 10 uri 3
                group 239.0.0.5 mode exclude
                        mcast-macaddr 01:00:5e:00:00:05
                group 224.0.0.1 mode exclude
                        mcast-macaddr 01:00:5e:00:00:01
Drop membership
igb1:
        inet 192.168.1.55
        igmpv3 rv 2 qi 125 qri 10 uri 3
                group 224.0.0.1 mode exclude
                        mcast-macaddr 01:00:5e:00:00:01
Add membership
igb1:
        inet 192.168.1.55
        igmpv3 rv 2 qi 125 qri 10 uri 3
                group 239.0.0.5 mode exclude
                        mcast-macaddr 01:00:5e:00:00:05
                group 224.0.0.1 mode exclude
                        mcast-macaddr 01:00:5e:00:00:01
Drop membership
igb1:
        inet 192.168.1.55
        igmpv3 rv 2 qi 125 qri 10 uri 3
                group 224.0.0.1 mode exclude
                        mcast-macaddr 01:00:5e:00:00:01


As you can see, the ADD/DROP membership to/from the group is successful.

But, there are no IGMP leave packets on igb1:
# tcpdump -i igb1 -vvv
tcpdump: listening on igb1, link-type EN10MB (Ethernet), capture size 262144
bytes
08:14:31.403346 ARP, Ethernet (len 6), IPv4 (len 4), Request who-has
192.168.1.55 tell 192.168.1.55, length 28
08:14:33.678193 IP (tos 0xc0, ttl 1, id 0, offset 0, flags [DF], proto IGMP
(2), length 40, options (RA))
    192.168.1.55 > igmp.mcast.net: igmp v3 report, 1 group record(s) [gaddr
239.0.0.5 to_ex { }]
08:14:34.526191 IP (tos 0xc0, ttl 1, id 0, offset 0, flags [DF], proto IGMP
(2), length 40, options (RA))
    192.168.1.55 > igmp.mcast.net: igmp v3 report, 1 group record(s) [gaddr
239.0.0.5 to_ex { }]
08:14:37.905173 IP (tos 0xc0, ttl 1, id 0, offset 0, flags [DF], proto IGMP
(2), length 40, options (RA))
    192.168.1.55 > igmp.mcast.net: igmp v3 report, 1 group record(s) [gaddr
239.0.0.5 to_ex { }]
08:14:39.177149 IP (tos 0xc0, ttl 1, id 0, offset 0, flags [DF], proto IGMP
(2), length 40, options (RA))
    192.168.1.55 > igmp.mcast.net: igmp v3 report, 1 group record(s) [gaddr
239.0.0.5 to_ex { }]

It seems that the function inp_leave_group() is broken:

2409            if (is_final) {
2410                    ip_mfilter_remove(&imo->imo_head, imf);

(1) For IP_DROP_MEMBERSHIP is_final is true. Mark socket-layer filter set as
INCLUDE {} at t1.

2411                    imf_leave(imf);
2412            } else {
2413                    if (imf->imf_st[0] =3D=3D MCAST_EXCLUDE) {
2414                            error =3D EADDRNOTAVAIL;
2415                            goto out_inp_locked;
2416                    }
2417                    ims =3D imo_match_source(imf, &ssa->sa);
2418                    if (ims =3D=3D NULL) {
2419                            CTR3(KTR_IGMPV3, "%s: source 0x%08x %sprese=
nt",
2420                                __func__, ntohl(ssa->sin.sin_addr.s_add=
r),
"not ");
2421                            error =3D EADDRNOTAVAIL;
2422                            goto out_inp_locked;
2423                    }
2424                    CTR2(KTR_IGMPV3, "%s: %s source", __func__, "block"=
);
2425                    error =3D imf_prune(imf, &ssa->sin);
2426                    if (error) {
2427                            CTR1(KTR_IGMPV3, "%s: merge imf state faile=
d",
2428                                __func__);
2429                            goto out_inp_locked;
2430                    }
2431            }
2432=20=20=20=20
....

(2) Commit and reap socket filter deltas.

2460            imf_commit(imf);
2461            imf_reap(imf);
2462=20=20=20=20
2463    out_inp_locked:
2464            INP_WUNLOCK(inp);
2465=20=20=20=20
2466            if (is_final && imf) {

2467                    /*
2468                     * Give up the multicast address record to which
2469                     * the membership points.
2470                     */

(3) in_leavegroup_locked() call igmp_change_state(). But, because source fi=
lter
deltas already committed and reaped, the call igmp_change_state() doesn't l=
ead
to IGMP state transition and sending IGMP packets.

2471                    (void) in_leavegroup_locked(imf->imf_inm, imf);
2472                    ip_mfilter_free(imf);
2473            }
2474=20=20=20=20
2475            IN_MULTI_UNLOCK();
2476            return (error);
2477    }

What do you think about move the in_leavegroup_locked() call before commit =
and
reap?
Something like this:

Index: sys/netinet/in_mcast.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- sys/netinet/in_mcast.c      (revision 355800)
+++ sys/netinet/in_mcast.c      (working copy)
@@ -2409,6 +2409,7 @@
        if (is_final) {
                ip_mfilter_remove(&imo->imo_head, imf);
                imf_leave(imf);
+               (void) in_leavegroup_locked(imf->imf_inm, imf);
        } else {
                if (imf->imf_st[0] =3D=3D MCAST_EXCLUDE) {
                        error =3D EADDRNOTAVAIL;
@@ -2468,7 +2469,6 @@
                 * Give up the multicast address record to which
                 * the membership points.
                 */
-               (void) in_leavegroup_locked(imf->imf_inm, imf);
                ip_mfilter_free(imf);
        }

With this patch.

# ./mcasttest
Add membership
igb1:
        inet 192.168.1.55
        igmpv3 rv 2 qi 125 qri 10 uri 3
                group 239.0.0.5 mode exclude
                        mcast-macaddr 01:00:5e:00:00:05
                group 224.0.0.1 mode exclude
                        mcast-macaddr 01:00:5e:00:00:01
Drop membership
igb1:
        inet 192.168.1.55
        igmpv3 rv 2 qi 125 qri 10 uri 3
                group 224.0.0.1 mode exclude
                        mcast-macaddr 01:00:5e:00:00:01
Add membership
igb1:
        inet 192.168.1.55
        igmpv3 rv 2 qi 125 qri 10 uri 3
                group 239.0.0.5 mode exclude
                        mcast-macaddr 01:00:5e:00:00:05
                group 224.0.0.1 mode exclude
                        mcast-macaddr 01:00:5e:00:00:01
Drop membership
igb1:
        inet 192.168.1.55
        igmpv3 rv 2 qi 125 qri 10 uri 3
                group 224.0.0.1 mode exclude
                        mcast-macaddr 01:00:5e:00:00:01

And tcpdump shows:
# tcpdump -i igb1 -vvv
tcpdump: listening on igb1, link-type EN10MB (Ethernet), capture size 262144
bytes
10:19:22.059334 ARP, Ethernet (len 6), IPv4 (len 4), Request who-has
192.168.1.55 tell 192.168.1.55, length 28
10:19:24.232247 IP (tos 0xc0, ttl 1, id 0, offset 0, flags [DF], proto IGMP
(2), length 40, options (RA))
    192.168.1.55 > igmp.mcast.net: igmp v3 report, 1 group record(s) [gaddr
239.0.0.5 to_ex { }]
10:19:24.861942 IP (tos 0xc0, ttl 1, id 0, offset 0, flags [DF], proto IGMP
(2), length 40, options (RA))
    192.168.1.55 > igmp.mcast.net: igmp v3 report, 1 group record(s) [gaddr
239.0.0.5 to_ex { }]
10:19:29.502570 IP (tos 0xc0, ttl 1, id 0, offset 0, flags [DF], proto IGMP
(2), length 40, options (RA))
    192.168.1.55 > igmp.mcast.net: igmp v3 report, 1 group record(s) [gaddr
239.0.0.5 to_in { }]
10:19:31.807624 IP (tos 0xc0, ttl 1, id 0, offset 0, flags [DF], proto IGMP
(2), length 40, options (RA))
    192.168.1.55 > igmp.mcast.net: igmp v3 report, 1 group record(s) [gaddr
239.0.0.5 to_in { }]
10:19:34.747646 IP (tos 0xc0, ttl 1, id 0, offset 0, flags [DF], proto IGMP
(2), length 40, options (RA))
    192.168.1.55 > igmp.mcast.net: igmp v3 report, 1 group record(s) [gaddr
239.0.0.5 to_ex { }]
10:19:35.595604 IP (tos 0xc0, ttl 1, id 0, offset 0, flags [DF], proto IGMP
(2), length 40, options (RA))
    192.168.1.55 > igmp.mcast.net: igmp v3 report, 1 group record(s) [gaddr
239.0.0.5 to_ex { }]
10:19:39.818577 IP (tos 0xc0, ttl 1, id 0, offset 0, flags [DF], proto IGMP
(2), length 40, options (RA))
    192.168.1.55 > igmp.mcast.net: igmp v3 report, 1 group record(s) [gaddr
239.0.0.5 to_in { }]
10:19:40.242591 IP (tos 0xc0, ttl 1, id 0, offset 0, flags [DF], proto IGMP
(2), length 40, options (RA))
    192.168.1.55 > igmp.mcast.net: igmp v3 report, 1 group record(s) [gaddr
239.0.0.5 to_in { }]

--=20
You are receiving this mail because:
You are the assignee for the bug.=



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?bug-242677-227>