Linux内核不通过多播UDP数据包

最近我已经build立了一个新的Ubuntu Server 10.04,并且注意到我的UDP服务器即使在join多播组后也不能看到发送到接口的任何多播数据。 我已经在另外两台Ubuntu 8.04.4 LTS机器上设置了完全相同的设置,join同一个多播组后,没有问题。

以太网卡是Broadcom的netXtreme II BCM5709,使用的驱动程序是:

b $ ethtool -i eth1 driver: bnx2 version: 2.0.2 firmware-version: 5.0.11 NCSI 2.0.5 bus-info: 0000:01:00.1 

我正在使用smcroute来pipe理我的多播注册。

 b$ smcroute -d b$ smcroute -j eth1 233.37.54.71 

join集团后,maddr显示新添加的注册。

 b$ ip maddr 1: lo inet 224.0.0.1 inet6 ff02::1 2: eth0 link 33:33:ff:40:c6:ad link 01:00:5e:00:00:01 link 33:33:00:00:00:01 inet 224.0.0.1 inet6 ff02::1:ff40:c6ad inet6 ff02::1 3: eth1 link 01:00:5e:25:36:47 link 01:00:5e:25:36:3e link 01:00:5e:25:36:3d link 33:33:ff:40:c6:af link 01:00:5e:00:00:01 link 33:33:00:00:00:01 inet 233.37.54.71 <------- McastGroup. inet 224.0.0.1 inet6 ff02::1:ff40:c6af inet6 ff02::1 

到目前为止,我可以看到我正在接收这个多播组的数据。

 b$ sudo tcpdump -i eth1 -s 65534 host 233.37.54.71 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on eth1, link-type EN10MB (Ethernet), capture size 65534 bytes 09:30:09.924337 IP 192.164.1.120.58848 > 233.37.54.71.15572: UDP, length 212 09:30:09.947547 IP 192.164.1.120.58848 > 233.37.54.71.15572: UDP, length 212 09:30:10.108378 IP 192.164.1.120.58866 > 233.37.54.71.15574: UDP, length 268 09:30:10.196841 IP 192.164.1.120.58848 > 233.37.54.71.15572: UDP, length 212 ... 

我也可以确认接口正在接收mcast数据包。

 b $ ethtool -S eth1 | grep mcast_pack rx_mcast_packets: 103998 tx_mcast_packets: 33 

现在是这个问题。 当我尝试使用简单的ruby UDP服务器捕获stream量时,我收到零数据! 这是一个简单的服务器,读取端口15572上发送的数据并打印前两个字符。 这适用于两个8.04.4 Ubuntu服务器,但不是10.04服务器。

 require 'socket' s = UDPSocket.new s.bind("", 15572) 5.times do text, sender = s.recvfrom(2) puts text end 

如果我发送一个ruby制作的UDP数据包给本地主机,服务器接收它并打印出前两个字符。 所以我知道上面的服务器工作正常。

 irb(main):001:0> require 'socket' => true irb(main):002:0> s = UDPSocket.new => #<UDPSocket:0x7f3ccd6615f0> irb(main):003:0> s.send("I2 XXX", 0, 'localhost', 15572) 

当我检查协议统计数据时,我发现InMcastPkts没有增加。 而在同一networking上的其他8.04服务器上,在10秒内收到几千个数据包。

 b $ netstat -sgu ; sleep 10 ; netstat -sgu IcmpMsg: InType3: 11 OutType3: 11 Udp: 446 packets received 4 packets to unknown port received. 0 packet receive errors 461 packets sent UdpLite: IpExt: InMcastPkts: 4654 <--------- Same as below OutMcastPkts: 3426 InBcastPkts: 9854 InOctets: -1691733021 OutOctets: 51187936 InMcastOctets: 145207 OutMcastOctets: 109680 InBcastOctets: 1246341 IcmpMsg: InType3: 11 OutType3: 11 Udp: 446 packets received 4 packets to unknown port received. 0 packet receive errors 461 packets sent UdpLite: IpExt: InMcastPkts: 4656 <-------------- Same as above OutMcastPkts: 3427 InBcastPkts: 9854 InOctets: -1690886265 OutOctets: 51188788 InMcastOctets: 145267 OutMcastOctets: 109712 InBcastOctets: 1246341 

如果我尝试强制接口进入promisc模式没有任何改变。

在这一点上,我卡住了。 我已经确认内核configuration启用了多播。 也许还有其他的configuration选项,我应该检查?

 b $ grep CONFIG_IP_MULTICAST /boot/config-2.6.32-23-server CONFIG_IP_MULTICAST=y 

任何想从哪里去这里?

在我们的例子中,我们的问题是通过sysctl参数解决的,与Maciej不同。

请注意,我不会说OP(buecking),我来这个post是因为这个问题与基本的细节有关(用户空间没有组播stream量)。

我们有一个应用程序,可以从通常直接连接到接收服务器接口的设备读取发送到四个多播地址的数据,以及每个多播地址的唯一端口。

我们试图在客户网站上部署这个软件,当它神秘失败,没有任何已知的原因。 试图debugging这个软件导致检查每一个系统调用,最终他们都告诉我们同样的事情:

我们的软件要求数据,操作系统从不提供任何数据。

组播数据包计数器递增,tcpdump显示到达盒/特定接口的stream量,但我们无法做任何事情。 SELinux被禁用,iptables正在运行,但在任何表中都没有规则。

被绊倒了,我们是。

我们在随机抽取时,开始考虑sysctl处理的内核参数,但没有logging的特性或者特别相关,或者如果他们必须处理多播stream量,那么它们就被启用了。 噢,ifconfig确实在function列(up,broadcast,running,multicast)中列出了“MULTICAST”。 出于好奇,我们查看了/etc/sysctl.conf 。 你看,这个顾客的基本形象在底部增加了几条额外的线条。

在我们的例子中,客户已经设置了net.ipv4.all.rp_filter = 1 。 rp_filter是pathpathfilter,据我所知,它拒绝所有不可能到达此框的stream量。 networking子网跳,想到源IP被欺骗。

那么,这台服务器在192.168.1 / 24子网上,组播stream量的设备源IP地址是在10. *networking中的某个地方。 因此,filter阻止了服务器对stream量做任何有意义的事情。

客户批准的一些调整; net.ipv4.eth0.rp_filter = 1net.ipv4.eth1.rp_filter = 0 ,我们正在愉快地运行。

TL / DR还要确保你的组播不是来自一个VLAN。 tcpdump -e将帮助确定他们是否做。

平心而论,有人应该build立一个可以阻止组播到达用户区的事物清单。 我一直在挣扎几天,自然没有什么能在网上find的。

我不仅可以看到tcpdump的数据包,还可以接收其他多播包,对于其他制作者,只是在不同的接口上。 我最终用来testing是否可以接收多播的命令是:

 $ GRP=224.xxx # set me to the group $ PORT=yyyy # set me to the receiving port $ IFACE=mmmm # set me to the name or IP address of the interface $ strace -f socat - UDP4-DATAGRAM:$GRP:$PORT,ip-add-membership=$GRP:$IFACE,bind=0.0.0.0:$PORT,multicast-loop=0 

这里strace的原因是我实际上不能让socat把数据包打印到stdout,但是在strace输出中,你可以清楚地看到socat是否从绑定的套接字接收到实际的数据(否则它会静音的初始select呼叫)

  • rp_filter sysctl – 不适用,系统在同一个IPnetworking上(我把它们全部设置为0 ,现在看起来1是默认设置,至less对于Ubuntu来说)。
  • 防火墙/等 – 接收系统是防火墙免费的(我不认为数据包会出现在tcpdump,如果他们被防火墙,但我想这是可能的,如果防火墙是有趣的)
  • IP /多播路由和多个接口 – 我明确join了正确的接口上的组
  • 古怪的networking硬件 – 这是我的最后的手段,但改变一些笔记本电脑到英特尔国家联盟没有帮助。 这是关于我开始咀嚼我的胳膊的地方,并且把这张贴在SE上。
  • 在我的情况下,问题是由生产这些组播数据包的专用硬件使用VLAN。 要查看这是否是您的问题,请确保将-e标志包含在tcpdump ,然后检查vlan标记。 在userland能够获取这些数据包之前,需要将接口configuration成正确的vlan。 对我来说,赠品实际上是多播生产者不会ping,但甚至不会进入ARPcaching,但我可以清楚地看到ARP答复。

要使它与VLAN一起运行, 该链接可能有助于configuration多播路由。 (可惜我是新来的,所以声誉不允许我添加一个答案,所以这个编辑。)

这是我做的(如果需要,使用sudo):

 ip link add link eth0 name eth0_100 type vlan id 100 ip addr add 192.168.100.2/24 brd 192.168.100.255 dev eth0_100 ip link set dev eth0_100 up ip maddr add 01:00:5e:01:01:01 dev eth0_100 route -n add -net 224.0.0.0 netmask 240.0.0.0 dev eth0_100 

这样,如果为vlan id为100的vlanstream量创build一个额外的接口,vlan ip可能是不必要的。 然后为新接口configuration组播地址(01:00:5e:01:01:01是239.1.1.1的链路层地址),并且所有到来的组播stream量都绑定到eth0_100。 我也做了上述答案中的所有可能的步骤(检查iptables,rp_filter等)。

你可能想尝试看看这些设置:

PROC

 echo "0" > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts 

sysctl.conf的

 sed -i -e 's|^net.ipv4.icmp_echo_ignore_broadcasts =.*|net.ipv4.icmp_echo_ignore_broadcasts = 0|g' /etc/sysctl.conf 

这些已经被用来在RHEL中启用多播。

您可能要确保您的防火墙允许mutlicaststream量; 再次与RHEL我启用了以下内容:

 # allow anything in on multicast addresses -A INPUT -s 224.0.0.0/4 -j ACCEPT -A INPUT -p igmp -d 224.0.0.0/4 -j ACCEPT # needed for multicast ping responses -A INPUT -p icmp --icmp-type 0 -j ACCEPT 

你使用的是pipe理型交换机吗? 有些可以select防止“广播风暴”或其他多播问题,这将导致他们阻止某些types的数据包。 我build议看看你的交换机文档。

 s.bind("", 15572) 

对“”? 为什么不使用多播IP地址绑定?