Refresh multicast group membership

9.6k views Asked by At

I have several embedded machines listening and streaming rtp audio data to a multicast group. They are connected to a smart managed switch (Netgear GS108Ev2) which does basic igmp snooping and multicast filtering on its ports, so that the rest of my (W)LAN doesn't get flooded.

At start everything works fine for about 500-520 seconds. After that, they don't receive any more data until they leave and join the group again. I guess the switch is "forgetting" about the join after a timeout.

Is there any way to refresh the group membership, i.e. letting the switch know, that there ist still someone listening, without losing packets?

System info:

Arch: blackfin

# cat /proc/version
Linux version 2.6.28.10-ADI-2009R1-uCBF54x-EMM
(gcc version 4.3.3 (ADI) ) #158 PREEMPT Tue Jun 5 20:05:42 CEST 2012
4

There are 4 answers

2
scai On BEST ANSWER

This is the way multicast / the IGMP protocol works. A client has to join the group periodically by sending a Membership Report or it will be assumed that he has left the group after some short timeout. However, those reports are usually sent only when receiving a Membership Query from the local multicast router. Either your clients don't receive the query or don't respond with a report.

Try to use a tool like wireshark in order to see which IGMP packets are sent through your network.

0
Tony On

If your embedded devices are running linux, you need to turn off the reverse packet filter on them or they won't respond to group membership queries. In that case the upstream switch will assume there is no-one listening to that multicast and switch it off.

0
Martin86 On

I had same problem, multicast on wifi was lost after 260 seconds, I solved it with my application by adding AddSourceMembership on socket.

private void StartListner(IPAddress sourceIp, IPAddress multicastGroupIp, IPAddress localIp, int port)
{
    try
    {
        Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);

        IPEndPoint localEndpoint = new IPEndPoint(localIp, port);
        socket.Bind(localEndpoint);

        byte[] membershipAddresses = new byte[12]; // 3 IPs * 4 bytes (IPv4)
        Buffer.BlockCopy(multicastGroupIp.GetAddressBytes(), 0, membershipAddresses, 0, 4);
        Buffer.BlockCopy(sourceIp.GetAddressBytes(), 0, membershipAddresses, 4, 4);
        Buffer.BlockCopy(localIp.GetAddressBytes(), 0, membershipAddresses, 8, 4);
        socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddSourceMembership, membershipAddresses);

        try
        {
            byte[] b = new byte[1024 * 2];
            int length = socket.Receive(b);
        }
        catch { }
    }
    catch (Exception ex)
    {
        logger.Error("Exception: " + ex);
    }
}
0
Ambroz Bizjak On

You need an IGMP querier to send the Membership Queries, as was already explained by scai.

If you can't configure your router to do that, you can use one of your computers. Seeing how running a full multicast routing daemon would be overkill (and I've never done that), I suggest you try to abuse igmpproxy.

First create a dummy upstream interface (this is not persistent!):

ip tap add dev tap6 mode tap

Write igmpproxy.conf:

# Dummy upstream interface.
phyint tap6 upstream  ratelimit 0  threshold 1

# Local interface.
phyint eth0 downstream  ratelimit 0  threshold 1

# Explicitly disable any other interfaces (yes, it sucks).
phyint NAME disabled
...

Finally start igmpproxy (as root):

igmpproxy -v /path/to/igmpproxy.conf