我正在尝试从 Centos 8 机器加入 IGMP 多播流,但是在发送 JOIN 后,没有来自交换机的流量。
简单连接:
MUX <-----------> cisco3850 <--------> Centos8
192.168.117.13 192.168.117.21
上游交换机(cisco catalyst 3850)从 MUX 将 MPEG-TS 馈送到 239.1.1.1:4000。
我尝试使用这两种方法socat
以及我自己的程序来打开套接字、加入流并保持套接字打开。两者都发送了相同的 IGMP 加入消息,经 wireshark 确认:
Internet Group Management Protocol
[IGMP Version: 3]
Type: Membership Report (0x22)
Reserved: 00
Checksum: 0xe9fb [correct]
[Checksum Status: Good]
Reserved: 0000
Num Group Records: 1
Group Record : 239.1.1.1 Change To Exclude Mode
Record Type: Change To Exclude Mode (4)
Aux Data Len: 0
Num Src: 0
Multicast Address: 239.1.1.1
使用ip route add
我为接口创建的多播组路由:
224.0.0.0/4 dev eth1 scope link
225.0.0.0/8 dev eth1 scope link
239.0.0.0/8 dev eth1 scope link
并cat /proc/net/igmp
显示该群组已加入:
cat /proc/net/igmp
Idx Device : Count Querier Group Users Timer Reporter
3 eth1 : 2 V3
030101E1 1 0:00000000 0
010000E0 1 0:00000000 0
我怀疑这是交换机的问题,而不是 Linux 的问题,但客户(交换机的所有者)说一切正常。
在 Linux 上我还能做什么来调查/解决这个问题?
如果是交换机的问题,那该怎么办?需要在那里配置什么?(需要向客户解释)
作为参考,我的加入并保持套接字打开的程序如下所示:
// Error checking omitted for brevity
fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes);
memset(&saddr, 0, sizeof(saddr));
saddr.sin_family = PF_INET;
saddr.sin_addr.s_addr = mcastAddr;
saddr.sin_port = htons(port);
bind(fd, (struct sockaddr *)&saddr, sizeof(saddr);
struct ip_mreq mcastReq;
mcastReq.imr_multiaddr.s_addr = mcastAddr;
&mcastReq.imr_interface.s_addr = interfaceAddr;
setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mcastReq, sizeof(mcastReq);
答案1
最后,客户交换机无法/不会激活 IGMPv3,因此我们通过在 下创建一个文件将我们的机器设置为使用 IGMP v2 /etc/sysctl.d
。
然后 JOIN 就可以工作了,但是 Linux 没有响应多播成员资格查询,所以交换机在 1-2 分钟后丢弃了流(即使我们已net.ipv4.conf.default.rp_filter
设置为零。
事实证明,要完全禁用返回路径验证,我们需要将所有设置设置rp_filter
为零(包括明确列出接口)
# Set IGMP Version for eth1
# Set to '2' or '3' depending on what is enabled in the switch
net.ipv4.conf.eth1.force_igmp_version = 2
# Disable source route verification
# In addition to 90-torque.conf, also explicitly set eth1 to ignore
# return path validation
net.ipv4.conf.default.rp_filter = 0
net.ipv4.conf.all.rp_filter = 0
net.ipv4.conf.eth1.rp_filter = 0