Bug 248512 - MCAST_LEAVE_GROUP/IP_DROP_MEMBERSHIP broken in 12.x
Summary: MCAST_LEAVE_GROUP/IP_DROP_MEMBERSHIP broken in 12.x
Status: Closed DUPLICATE of bug 246629
Alias: None
Product: Base System
Classification: Unclassified
Component: kern (show other bugs)
Version: 12.1-STABLE
Hardware: Any Any
: --- Affects Many People
Assignee: Bjoern A. Zeeb
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2020-08-07 10:28 UTC by Sietse
Modified: 2020-09-07 09:59 UTC (History)
3 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Sietse 2020-08-07 10:28:36 UTC
It seems that multicast is seriously broken in FreeBSD 12.x groups are joined, but never left, even after closing socket / exiting application. This is causing serioud bandwith issues with for instance IPTV, as streams keep running. Even downing / upping interfaces group membership is retained. Issue is seen since upgrading from 11.4 to version 12.1p7, and still present in p8.

On FreeBSD 12, MC groups are joined correctly:
[root@freebsd /usr/home/sietse]# ifmcstat
vmx0:
        inet 10.0.20.123
        igmpv3 rv 2 qi 125 qri 10 uri 3
                group 225.0.71.1 mode exclude
                        mcast-macaddr 01:00:5e:00:47:01
                group 239.255.255.253 mode exclude
                        mcast-macaddr 01:00:5e:7f:ff:fd
                group 239.255.255.250 mode exclude
                        mcast-macaddr 01:00:5e:7f:ff:fa
                group 224.0.0.1 mode exclude
                        mcast-macaddr 01:00:5e:00:00:01
vmx1:
        inet 10.0.22.122
        igmpv2
                group 224.0.0.22 mode undefined
                        mcast-macaddr 01:00:5e:00:00:16
                group 224.0.0.2 mode undefined
                        mcast-macaddr 01:00:5e:00:00:02
                group 224.0.0.1 mode exclude
                        mcast-macaddr 01:00:5e:00:00:01
vmx2:
        inet 192.168.1.123
        igmpv3 rv 2 qi 125 qri 100 uri 3
                group 224.0.0.22 mode undefined
                        mcast-macaddr 01:00:5e:00:00:16
                group 224.0.0.2 mode undefined
                        mcast-macaddr 01:00:5e:00:00:02
                group 224.0.0.1 mode exclude
                        mcast-macaddr 01:00:5e:00:00:01


But after issueing MC_LEAVE_GROUP/IP_DROP_MEMBERSHIP or exiting process / closing FD group membership remains:
[root@freebsd /usr/home/sietse]# ifmcstat
vmx0:
        inet 10.0.20.123
        igmpv3 rv 2 qi 125 qri 10 uri 3
                group 225.0.71.1 mode exclude
                        mcast-macaddr 01:00:5e:00:47:01
                group 239.255.255.253 mode exclude
                        mcast-macaddr 01:00:5e:7f:ff:fd
                group 239.255.255.250 mode exclude
                        mcast-macaddr 01:00:5e:7f:ff:fa
                group 224.0.0.1 mode exclude
                        mcast-macaddr 01:00:5e:00:00:01
vmx1:
        inet 10.0.22.122
        igmpv2
                group 224.0.0.22 mode undefined
                        mcast-macaddr 01:00:5e:00:00:16
                group 224.0.0.2 mode undefined
                        mcast-macaddr 01:00:5e:00:00:02
                group 224.0.0.1 mode exclude
                        mcast-macaddr 01:00:5e:00:00:01
vmx2:
        inet 192.168.1.123
        igmpv3 rv 2 qi 125 qri 100 uri 3
                group 224.0.0.22 mode undefined
                        mcast-macaddr 01:00:5e:00:00:16
                group 224.0.0.2 mode undefined
                        mcast-macaddr 01:00:5e:00:00:02
                group 224.0.0.1 mode exclude
                        mcast-macaddr 01:00:5e:00:00:01

On FREEBSD 11 / Linux group membership is dropped correctly after MC_LEAVE_GROUP:
[root@freebsd-test2 /usr/home/sietse/igmpproxy]# ifmcstat
vmx0:
        inet 10.0.20.201
        igmpv3 rv 2 qi 125 qri 10 uri 3
                group 224.0.0.1 mode exclude
                        mcast-macaddr 01:00:5e:00:00:01
vmx1:
        inet 10.0.22.201
        igmpv2
                group 224.0.0.1 mode exclude
                        mcast-macaddr 01:00:5e:00:00:01
vmx2:
        inet 192.168.1.127
        igmpv2
                group 224.0.0.1 mode exclude
                        mcast-macaddr 01:00:5e:00:00:01

Code of application leading up to this issue:
void openUdpSocket(uint32_t PeerInAdr, uint16_t PeerPort) {
    struct sockaddr_in SockAdr;

    if ((udpSock = socket(AF_INET, SOCK_RAW, IPPROTO_IGMP)) < 0) {
        my_log(LOG_ERR, errno, "UDP socket open");
    }

    memset(&SockAdr, 0, sizeof(SockAdr));
    SockAdr.sin_family      = AF_INET;
    SockAdr.sin_port        = htons(PeerPort);
    SockAdr.sin_addr.s_addr = htonl(PeerInAdr);

    if (bind(udpSock, (struct sockaddr *)&SockAdr, sizeof(SockAdr))) {
        my_log(LOG_ERR, errno, "UDP socket bind");
    }
}

/**
*   Common function for joining or leaving a MCast group.
*/
static void joinleave(int Cmd, struct IfDesc *IfDp, uint32_t mcastaddr) {
    const char *CmdSt = Cmd == 'j' ? "join" : "leave";
    struct group_req GrpReq;
#ifdef __linux__
    struct sockaddr_in Grp = { AF_INET, 0, mcastaddr };
#else
    struct sockaddr_in Grp = { sizeof(struct sockaddr_in), AF_INET, 0, mcastaddr };
#endif

    GrpReq.gr_interface = IfDp ? if_nametoindex(IfDp->Name) : 0;
    memcpy(&GrpReq.gr_group, &Grp, sizeof(Grp));

    my_log(LOG_NOTICE, 0, "%sMcGroup: %s on %s", CmdSt, inetFmt(Grp.sin_addr.s_addr, s1), IfDp->Name);

    if (setsockopt(udpSock, IPPROTO_IP, Cmd == 'j' ? MCAST_JOIN_GROUP : MCAST_LEAVE_GROUP, &GrpReq, sizeof(GrpReq))) {
        int mcastGroupExceeded = (Cmd == 'j' && errno == ENOBUFS);
        my_log(LOG_WARNING, errno, "MCAST_%s_GROUP failed", Cmd == 'j' ? "JOIN" : "LEAVE");
        if (mcastGroupExceeded) {
            my_log(LOG_WARNING, 0, "Maximum number of multicast groups were exceeded");
#ifdef __linux__
            my_log(LOG_WARNING, 0, "Check settings of '/sbin/sysctl net.ipv4.igmp_max_memberships'");
#endif
        }
    }
}

Application contains a thorough cleanup routing on exit
static void igmpProxyCleanUp(void) {
    my_log( LOG_DEBUG, 0, "clean handler called" );

    freeQueriers();         // Free all group queriers.
    timer_freeQueue();      // Free all timeouts.
    clearRoutes(NULL,NULL); // Remove all routes and leave all groups.
    freeIfDescP(0);         // Free IfDesc table.
    freeConfig(0);          // Free config.
    freeVifDescVc();        // Free VifDesc table.
    disableMRouter();       // Disable the MRouter API.
    free(recv_buf);         // Free receive buffer.
    free(send_buf);         // Free send buffer.
    close(udpSock);         // Close UDP Socket.
}
Comment 1 Bjoern A. Zeeb freebsd_committer 2020-08-07 11:40:31 UTC
This seems to be what was fixed with PR 246629?

If you have the ability to test [1] (or based on the description feel that this might indeed be fixed) can you please report back if it is fixed?


[1] A 12.1-STABLE snapshot from https://www.freebsd.org/snapshots/   ; please note that this will get you off the release and freebsd-update track.
Comment 2 Bjoern A. Zeeb freebsd_committer 2020-08-07 11:41:28 UTC
I'll take this so I can track it and possibly closed as duplicate; depending on what I hear back the next weeks.
Comment 3 Sietse 2020-08-07 12:55:14 UTC
Thanks, issue indeed no longer exists in latest snapshot:

[root@freebsd /usr/home/sietse/igmpproxy]# uname -a
FreeBSD freebsd 12.1-STABLE FreeBSD 12.1-STABLE r363918 GENERIC  amd64

After shutdown:
[root@freebsd /usr/home/sietse/igmpproxy]# ifmcstat
vmx0:
        inet 10.0.20.200
        igmpv3 rv 2 qi 125 qri 10 uri 3
                group 224.0.0.1 mode exclude
                        mcast-macaddr 01:00:5e:00:00:01
vmx1:
        inet 10.0.22.122
        igmpv2
                group 224.0.0.1 mode exclude
                        mcast-macaddr 01:00:5e:00:00:01
vmx2:
        inet 192.168.1.200
        igmpv3 rv 3 qi 0 qri 10 uri 3
                group 224.0.0.1 mode exclude
                        mcast-macaddr 01:00:5e:00:00:01
lo0:
        inet 127.0.0.1
        igmpv3 rv 2 qi 125 qri 10 uri 3
                group 224.0.0.1 mode exclude
        inet6 fe80::1%lo0 scopeid 0x4
        mldv2 flags=2<USEALLOW> rv 2 qi 125 qri 10 uri 3
                group ff01::1%lo0 scopeid 0x4 mode exclude
                group ff02::2:2eb7:74fa%lo0 scopeid 0x4 mode exclude
                group ff02::2:ff2e:b774%lo0 scopeid 0x4 mode exclude
                group ff02::1%lo0 scopeid 0x4 mode exclude
                group ff02::1:ff00:1%lo0 scopeid 0x4 mode exclude
Comment 4 Bjoern A. Zeeb freebsd_committer 2020-08-07 13:05:59 UTC
Thank you for testing so quickly and reporting back! Happy it works now.

*** This bug has been marked as a duplicate of bug 246629 ***