當介面 MTU 小於分接幀時,部分可見分接乙太網幀
我有以下非常簡單的拓撲,其中路由器r1向r2發送具有 2000 字節有效負載的 ICMP“迴聲請求”消息,路由器r2使用 ICMP“迴聲回复”消息回复這些消息:
路由器 Gi0/0/0 介面具有 9000 字節 MTU。如圖所示,這兩個路由器之間還有一個被動網路分路器,它將流量鏡像到PC中的 bond0 介面。當bond0(以及eth2 和eth3)的MTU 小於有線網路上包含ICMP 消息的乙太網幀時,tcpdump或tshark等數據包擷取實用程序只能看到ICMP 消息的部分有效負載部分。例如,假設r1發送用 0xabcd 數據填充的 ICMP 消息,然後在****PC中的 bond0、eth2 或 eth3 介面上偵聽的數據包擷取實用程序會看到以下數據:
0x0000: abcd abcd abcd abcd abcd abcd abcd abcd ................ 0x0010: abcd abcd abcd abcd abcd abcd abcd abcd ................ 0x0020: abcd abcd abcd abcd abcd abcd abcd abcd ................ 0x0030: abcd abcd abcd abcd abcd abcd abcd abcd ................ 0x0040: abcd abcd abcd abcd abcd abcd abcd abcd ................ /* further data removed for brevity */
是什麼導致了這種行為?
確實,
usbnet
似乎是最有可能的罪魁禍首。/* rx and tx sides can use different message sizes; * bind() should set rx_urb_size in that case. */ dev->hard_mtu = net->mtu + net->hard_header_len; net->netdev_ops = &usbnet_netdev_ops; net->watchdog_timeo = TX_TIMEOUT_JIFFIES; net->ethtool_ops = &usbnet_ethtool_ops; // allow device-specific bind/init procedures // NOTE net->name still not usable ... if (info->bind) { status = info->bind (dev, udev); ... } .... if (!dev->rx_urb_size) dev->rx_urb_size = dev->hard_mtu;
http://lxr.free-electrons.com/source/drivers/net/usb/usbnet.c?v=4.4#L1661
據我所知, cdc_ether 不會自行設置
rx_urb_size
。我假設 URB 大小被傳遞給 USB 控制器,並且乙太網框架的頭部被砍掉以適應(不要問我為什麼不是另一端)。我的意思是,希望您的實驗不會導致硬體在分配的緩衝區之外進行 DMA :)。
ndo_change_mtu
甚至 cdc_ether 確實設置了 rx_urb_size,在 usbnet 的回調中有這個奇怪的位。如果將 mtu 設置為最大值,它看起來最終可能會與 mtu 掛鉤。老實說,我不知道這是如何工作的,乍一看它看起來很奇怪。
if (dev->rx_urb_size == old_hard_mtu) { dev->rx_urb_size = dev->hard_mtu;
http://lxr.free-electrons.com/source/drivers/net/usb/usbnet.c?v=4.4#L393