Tap

當介面 MTU 小於分接幀時,部分可見分接乙太網幀

  • March 9, 2016

我有以下非常簡單的拓撲,其中路由器r1r2發送具有 2000 字節有效負載的 ICMP“迴聲請求”消息,路由器r2使用 ICMP“迴聲回复”消息回复這些消息:

被動網路分接頭設置

路由器 Gi0/0/0 介面具有 9000 字節 MTU。如圖所示,這兩個路由器之間還有一個被動網路分路器,它將流量鏡像到PC中的 bond0 介面。當bond0(以及eth2 和eth3)的MTU 小於有線網路上包含ICMP 消息的乙太網幀時,tcpdumptshark等數據包擷取實用程序只能看到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

引用自:https://unix.stackexchange.com/questions/267122