14

TLDR: Is there a way to use "ip route" to add multicast routes for multiple NICs?

We have software that uses two multicast groups to communicate with two different groups of devices on two separate physical networks. With the exception of this application, devices on one network do not need to communicate across our device to communicate with devices on the other network.

Multicast groups

To do this the software creates two sockets. Each one is bound to the one of the ip addresses of the separate NICS. That socket is then joined to the multicast group that exists on that network, eg socket 1 is bound to 192.168.0.2 and joined to multicast group 233.255.10.1 while socket 2 is bound to 10.57.31.2 and joined to multicast group 239.255.100.1.

We are currently using a bash script (Linux kernel 3.14.39) to set multicast routes on the two network interfaces using route, eg

route add -net 224.0.0.0 netmask 240.0.0.0 eth0
route add -net 224.0.0.0 netmask 240.0.0.0 eth1

and verified via route -n

Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
224.0.0.0       0.0.0.0         240.0.0.0       U     0      0        0 eth0
224.0.0.0       0.0.0.0         240.0.0.0       U     0      0        0 eth1

I recently read that route was deprecated/obsolete and that we should be using ip route instead, eg

ip route add 224.0.0.0/4 dev eth0
ip route add 224.0.0.0/4 dev eth1

Unfortunately, the second call fails with "RTNETLINK answers: File exists" and of course the second route doesn't show up after these calls.

Is there a way to use ip route to add multicast routes to multiple NICs?

I can use /8 as a netmask? eg

ip route add 233.0.0.0/8 dev eth0

and

ip route add 239.0.0.0/8 dev eth1

but this is problematic as the script that does this is not aware of what multicast address is associated with which device and its not always guaranteed to be the same depending on system configuration. Using my first example of route add makes this a non issue.

UPDATES Thanks to an extended discussion with @Ron Maupin, I realized the error was in our code. We were not setting the interface to use for multicasting with IP_MULTICAST_IF. Once I added the setsockopt call to set IP_MULTICAST_IF, I no longer needed to add the routing tables.

struct in_addr multicastInterface = {};
multicastInterface.s_addr = interfaceAddressNetworkOrder;

// Set which outgoing interface to use
int result = setsockopt(m_socket, IPPROTO_IP, IP_MULTICAST_IF, (char*)&multicastInterface, sizeof(struct in_addr));
gnac
  • 243
  • 1
  • 2
  • 7
  • 1
    Multicast isn't routed the same way unicast is. Multicast routing involves PIM, and you need to software to help you do it correctly. – Ron Maupin Nov 10 '16 at 17:33
  • @Ron Maupin, What specific software are you referring to? route and iproute are software programs after all. – gnac Nov 10 '16 at 18:03
  • You need to use something like `mrouted` or `pimd`. Multicast routing is very different than unicast routing, and it needs to respond to IGMP requests. – Ron Maupin Nov 10 '16 at 18:43
  • How is it that our system works using route ... without using mrouted/pimd? – gnac Nov 10 '16 at 19:14
  • You got lucky. Linux doesn't normally handle multicast correctly, but to do it right, you need to understand multicast and configure multicast routing. The router should respond to IGMP. – Ron Maupin Nov 10 '16 at 19:18
  • @gnac, Did you find a solution for your issue? – A R Oct 28 '17 at 00:23

2 Answers2

13

That you have multicast going through your Linux box by using unicast routing is a combination of a couple of lucky circumstances.

Multicast routing is not the same as unicast routing. Unicast routing is based on the face that traffic is sent to a single address, but multicast traffic is sent to a group address that represents hosts which want to subscribe to the multicast group.

Hosts use IGMP to tell a multicast router that they want to join a multicast group, and the multicast router will then start sending multicast traffic for that group to the network of the hosts requesting this.

Modern switches will use IGMP Snooping to determine which switch ports have hosts requesting to join a particular multicast group, and they will only send traffic for that multicast group to the switch ports where the hosts have requested to join the multicast group.

Linux, by itself, doesn't support multicast routing, and you need to add something to the Linux device to support multicast routing. Refer to the diagram below:

enter image description here

When the multicast source starts to send multicast traffic for a multicast group, the switch probably has not seen any IGMP requests to join the multicast group, so the multicast traffic for that group goes nowhere.

When one of the PCs on the same switch wants to join the multicast group, it will send an IGMP Join message, and the switch will snoop on that and send the multicast traffic to the port where the requesting PC is connected.

If a PC on the other side of the Linux router wants to join the multicast group, it is out of luck because the multicast traffic is not flowing to that side of the Linux Router. The Linux Router has not even joined the multicast group, so the switch never sends the multicast traffic to it.

When you run multicast routing on a router, the router will respond to the host IGMP request, and the switch will know that it is a multicast router, and it will send multicast traffic to the switch port where the multicast router is connected. Simplistically, the router will not send the multicast traffic to another interface unless there is an active receiver on another interface (this depends on the multicast version, for instance, PIM-DM will start sending, but back off if no IGMP requests are seen).

With multicast routing enabled on the router, a PC connected to the other interface will send an IGMP Join message, and the Linux Router will begin sending the multicast traffic for the requested group to the interface. The switch will snoop on the request, and it will send multicast traffic to the switch port where the PC that requested to join the multicast group is connected.

It gets more complicated if you need to route throgh multiple routers. IGMP is used between the hosts and the local multicast router. PIM (or some other multicast routing protocol) is used between multicast routers.

This all prevents multicast traffic from going where it is not wanted.

There are add-ons to Linux to aid it in properly handling IGMP and multicast routing.

starblue
  • 123
  • 1
  • 5
Ron Maupin
  • 3,158
  • 1
  • 11
  • 16
  • Thanks for the detailed response. I'm going to update my question to ensure it is clear. Namely, I have a linux device/application that is communicating on two different networks via multicast. It itself is not attempting to route multicast data from one network to the other, but rather publishing and receiving multicast data on two different multicast networks over two different physical interfaces. – gnac Nov 10 '16 at 22:13
  • As I explained, if you end up with a switch that does IGMP snooping, your box that connects the two networks may never even get the multicast in order to route it to the other network. It is not correctly configured, and you are lucky it works, but a simple change can break it. Multicast, like broadcast, is limited to a single broadcast domain (network). Moving traffic from one network to another network is routing , and you are trying to route multicast traffic. – Ron Maupin Nov 10 '16 at 22:15
  • I am not trying to route multicast traffic across my device. I am trying to ensure that the application on my device can communicate with other devices in a multicast group on a specific physical network. If I take away the fact that I'm connecting to two networks, I still need the route add statements or else no multicast traffic is sent of received from my device. – gnac Nov 10 '16 at 22:40
  • Yes, you are routing. That is the very definition of sending traffic from one network to another network. If you had bridged these networks then you would not need to use a `route` or `ip route` command because the traffic would be bridged from one interface to another interface. – Ron Maupin Nov 10 '16 at 22:41
  • but you need to use route even if you are only using one network/interface. – gnac Nov 10 '16 at 22:55
  • You can send multicast traffic out an interface without using `route` or `ip route`. If you have a problem with that, then your multicast source application needs to be fixed. A proper multicast source application will have a way for you to let it know on which interface(s) it should send traffic. This could be with the command line, configuration file, fields in the application, etc. – Ron Maupin Nov 10 '16 at 22:59
  • Let us [continue this discussion in chat](http://chat.stackexchange.com/rooms/48311/discussion-between-gnac-and-ron-maupin). – gnac Nov 10 '16 at 23:08
  • I'm seeing some software is able to emit multicast only on default route interface thus I'm suspecting it's not the answer for real. In despite routing itself (or should we say forwarding?) is being done differently for multicast it doesn't mean multicast announces aren't affected by host's routing table. At least in the cases I'm seeing `route add ` changes the behaviour of sending multicast beyond default route interface only. – poige Nov 08 '19 at 08:42
1

To add multiple routes for a target, you can add the first as you have done, by using ip route add <address> dev <interface>. To add the second you then use ip route append <address> dev <interface2>.

For ipv4 you will need something to manage the IGMP or whichever multicast management protocol you are using. For ipv6 this is baked into the icmpv6 protocol so my understanding is that linux should handle this out of the box for you.

Philip Adler
  • 111
  • 4