Linux核心不通過多播UDP數據包
最近我設置了一個新的 Ubuntu Server 10.04 並註意到我的 UDP 伺服器不再能夠看到任何發送到介面的多播數據,即使在加入多播組之後也是如此。我在另外兩台 Ubuntu 8.04.4 LTS 機器上進行了完全相同的設置,並且在加入同一個多播組後接收數據沒有問題。
乙太網卡是 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 來管理我的多播註冊。
b$ smcroute -d b$ smcroute -j eth1 233.37.54.71
加入組後 ip 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 伺服器擷取流量時,我收到零數據!這是一個簡單的伺服器,它讀取埠 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
如果我向 localhost 發送一個用 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 沒有增加。而在同一網路上的其他 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
如果我嘗試強制介面進入混雜模式,則沒有任何變化。
在這一點上,我被困住了。我已經確認核心配置已啟用多播。也許我應該檢查其他配置選項?
b $ grep CONFIG_IP_MULTICAST /boot/config-2.6.32-23-server CONFIG_IP_MULTICAST=y
關於從這裡去哪裡的任何想法?
在我們的例子中,我們的問題是通過 sysctl 參數解決的,它與 Maciej 不同。
請注意,我不代表 OP(buecking),我之所以發表這篇文章是因為問題與基本細節相關(使用者空間中沒有多播流量)。
我們有一個應用程序,它從(通常)直接連接到接收伺服器上的介面的設備讀取發送到四個多播地址的數據,以及每個多播地址的唯一埠。
我們試圖在客戶站點上部署此軟體時,它莫名其妙地失敗了,原因不明。調試此軟體的嘗試導致檢查每個系統呼叫,最終他們都告訴我們同樣的事情:
我們的軟體要求提供數據,而作業系統從不提供任何數據。
多播數據包計數器增加,tcpdump 顯示流量到達盒子/特定介面,但我們無能為力。SELinux 被禁用,iptables 正在執行,但在任何表中都沒有規則。
難住了,我們。
在隨機探索中,我們開始考慮 sysctl 處理的核心參數,但沒有任何記錄的功能特別相關,或者如果它們與多播流量有關,它們被啟用。哦,ifconfig 確實在功能行中列出了“MULTICAST”(啟動、廣播、執行、多播)。出於好奇,我們看了看
/etc/sysctl.conf
。‘瞧,這個客戶的基本圖像在底部添加了幾行額外的行。在我們的例子中,客戶設置了
net.ipv4.all.rp_filter = 1
. rp_filter 是路由路徑過濾器,它(據我了解)拒絕所有可能無法到達此框的流量。網路子網跳躍,認為源IP被欺騙。好吧,該伺服器位於 192.168.1/24 子網中,並且設備的多播流量源 IP 地址位於 10.* 網路中的某個位置。因此,過濾器阻止伺服器對流量做任何有意義的事情。
客戶批准的一些調整;
net.ipv4.eth0.rp_filter = 1
我們跑net.ipv4.eth1.rp_filter = 0
得很開心。