[Bug 248512] MCAST_LEAVE_GROUP/IP_DROP_MEMBERSHIP broken in 12.x

bugzilla-noreply at freebsd.org bugzilla-noreply at freebsd.org
Fri Aug 7 10:28:37 UTC 2020


https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=248512

            Bug ID: 248512
           Summary: MCAST_LEAVE_GROUP/IP_DROP_MEMBERSHIP broken in 12.x
           Product: Base System
           Version: 12.1-STABLE
          Hardware: Any
                OS: Any
            Status: New
          Severity: Affects Many People
          Priority: ---
         Component: kern
          Assignee: bugs at FreeBSD.org
          Reporter: sietse at wizdom.nu

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 at 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 at 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 at 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.
}

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


More information about the freebsd-bugs mailing list