我有一个非常简单的拓扑,其中路由器r1发送 ICMP“回显请求”消息至r2具有 2000 字节有效负载和路由器r2使用 ICMP“回显回复”消息回复这些消息:
路由器 Gi0/0/0 接口的 MTU 为 9000 字节。如图所示,这两个路由器之间还有一个被动网络分路器,它将流量镜像到 bond0 接口个人电脑。当 bond0(以及 eth2 和 eth3)的 MTU 小于线路上包含 ICMP 消息的以太网帧时,则数据包捕获实用程序如tcp转储或者沙克只能看到 ICMP 消息的部分有效负载部分。例如,我们可以说r1发送填充有 0xabcd 数据的 ICMP 消息,然后数据包捕获实用程序在 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 */
是什么导致了这种行为?
答案1
确实,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
rx_urb_size
据我所知,cdc_ether 不会自行设置。
我假设 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