使用 ip route add 为多个接口添加多播路由

使用 ip route add 为多个接口添加多播路由

TLDR:有没有办法使用“ip route”为多个 NIC 添加多播路由?

我们有软件使用两个多播组与两个独立物理网络上的两个不同设备组进行通信。除此应用程序外,一个网络上的设备无需通过我们的设备即可与另一个网络上的设备进行通信。

多播组

为此,软件创建了两个套接字。每个套接字都绑定到单独 NICS 的一个 IP 地址。然后,该套接字加入该网络上存在的多播组,例如,套接字 1 绑定到 192.168.0.2 并加入多播组 233.255.10.1,而套接字 2 绑定到 10.57.31.2 并加入多播组 239.255.100.1。

我们目前正在使用 bash 脚本(Linux 内核 3.14.39)使用路由在两个网络接口上设置多播路由,例如

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

并通过 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

我最近读到,路由已被弃用/过时,我们应该使用 ip 路由,例如

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

不幸的是,第二次调用失败,出现“RTNETLINK 答案:文件存在”,当然这些调用之后第二条路由没有出现。

有没有办法使用 ip route 为多个 NIC 添加多播路由?

我可以使用 /8 作为网络掩码吗?例如

ip route add 233.0.0.0/8 dev eth0

ip route add 239.0.0.0/8 dev eth1

但这是有问题的,因为执行此操作的脚本不知道哪个多播地址与哪个设备相关联,并且根据系统配置,它并不总是保证相同。使用我的第一个路由添加示例可以解决这个问题。

更新 感谢与@Ron Maupin 的深入讨论,我意识到错误出在我们的代码中。我们没有使用 IP_MULTICAST_IF 设置用于多播的接口。一旦我添加了 setsockopt 调用来设置 IP_MULTICAST_IF,我就不再需要添加路由表了。

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));

答案1

通过使用单播路由来实现 Linux 机器上的多播,这是几个幸运情况的结合。

多播路由与单播路由不同。单播路由基于将流量发送到单个地址这一原则,而多播流量则发送到代表想要订阅多播组的主机的组地址。

主机使用 IGMP 告诉多播路由器它们想要加入多播组,然后多播路由器将开始向请求该组的主机的网络发送该组的多播流量。

现代交换机将使用 IGMP Snooping 来确定哪些交换机端口有主机请求加入特定的多播组,并且它们只会将该多播组的流量发送到主机已请求加入多播组的交换机端口。

Linux 本身不支持多播路由,需要在 Linux 设备中添加一些内容来支持多播路由。参见下图:

在此处输入图片描述

当多播源开始为多播组发送多播流量时,交换机可能还没有看到任何加入该多播组的 IGMP 请求,因此该组的多播流量无处可去。

当同一台交换机上的其中一台 PC 想要加入多播组时,它将发送 IGMP 加入消息,交换机将侦听该消息并将多播流量发送到请求 PC 所连接的端口。

如果 Linux 路由器另一侧的 PC 想要加入多播组,它就没那么幸运了,因为多播流量并没有流向 Linux 路由器的那一侧。Linux 路由器甚至还没有加入多播组,因此交换机永远不会向它发送多播流量。

当您在路由器上运行多播路由时,路由器将响应主机 IGMP 请求,交换机将知道它是多播路由器,并将多播流量发送到多播路由器所连接的交换机端口。简单地说,除非另一个接口上有活动的接收器(这取决于多播版本,例如,PIM-DM 将开始发送,但如果没有看到 IGMP 请求,则会退出)。

在路由器上启用多播路由后,连接到另一个接口的 PC 将发送 IGMP 加入消息,Linux 路由器将开始向该接口发送请求组的多播流量。交换机将监听该请求,并将多播流量发送到请求加入多播组的 PC 所连接的交换机端口。

如果需要通过多个路由器进行路由,情况会变得更加复杂。主机和本地多播路由器之间使用 IGMP。多播路由器之间使用 PIM(或其他多播路由协议)。

这一切都是为了防止多播流量流向不想要的地方。

Linux 有一些附加组件可以帮助它正确处理 IGMP 和多播路由。

答案2

要为目标添加多条路线,您可以像之前一样使用 添加第一条路线ip route add <address> dev <interface>。要添加第二条路线,请使用ip route append <address> dev <interface2>

对于 ipv4,您需要一些东西来管理 IGMP 或您正在使用的任何多播管理协议。对于 ipv6,这已嵌入到 icmpv6 协议中,因此我的理解是 linux 应该可以为您立即处理这个问题。

相关内容