如何找出网络接口丢弃数据包的原因?

Huy*_*ens 22 networking linux kernel

在 Linux 上有没有办法获取有关数据包被丢弃的各种原因的统计信息?

在多个服务器上的所有网络接口 (openSUSE 12.3) 上,ifconfignetstat -i在接收时报告丢弃的数据包。当我执行 a 时tcpdump,丢弃的数据包数量停止增加,这意味着接口队列未满并丢弃数据。所以一定有其他原因导致这种情况发生(例如,接收到多播 pkts 而接口不是该多播组的一部分)。

我在哪里可以找到此类信息?(/proc?/sys?一些日志?)

统计示例(/sys/class/net/<dev>/statistics 和 ethtool 输出的合并):

alloc_rx_buff_failed: 0
collisions: 0
dropped_smbus: 0
multicast: 1644
rx_align_errors: 0
rx_broadcast: 23626
rx_bytes: 1897203
rx_compressed: 0
rx_crc_errors: 0
rx_csum_offload_errors: 0
rx_csum_offload_good: 0
rx_dropped: 4738
rx_errors: 0
rx_fifo_errors: 0
rx_flow_control_xoff: 0
rx_flow_control_xon: 0
rx_frame_errors: 0
rx_length_errors: 0
rx_long_byte_count: 1998731
rx_long_length_errors: 0
rx_missed_errors: 0
rx_multicast: 1644
rx_no_buffer_count: 0
rx_over_errors: 0
rx_packets: 25382
rx_short_length_errors: 0
rx_smbus: 0
tx_aborted_errors: 0
tx_abort_late_coll: 0
tx_broadcast: 7
tx_bytes: 11300
tx_carrier_errors: 0
tx_compressed: 0
tx_deferred_ok: 0
tx_dropped: 0
tx_errors: 0
tx_fifo_errors: 0
tx_flow_control_xoff: 0
tx_flow_control_xon: 0
tx_heartbeat_errors: 0
tx_multicast: 43
tx_multi_coll_ok: 0
tx_packets: 63
tx_restart_queue: 0
tx_single_coll_ok: 0
tx_smbus: 0
tx_tcp_seg_failed: 0
tx_tcp_seg_good: 0
tx_timeout_count: 0
tx_window_errors: 0
Run Code Online (Sandbox Code Playgroud)

mr.*_*tic 25

尝试/sys/class/net/eth0/statistics/ (即对于eth0),它并不完美,但它可以通过传输/接收和载波、窗口、FIFO、CRC、帧、长度(以及更多)类型的错误来分解错误。

netstat丢弃与“忽略”不同,显示接口级别的统计信息,被更高级别(第 3 层,IP 堆栈)忽略的多播数据包不会显示为丢弃(尽管它可能在某些情况下显示为“已过滤”)网卡统计)。各种卸载功能可能会使统计数据有些复杂。

如果您有ethtool以下条件,您可以获得更多统计信息:

# ethtool -S eth0
 rx_packets: 60666755
 tx_packets: 2206194
 rx_bytes: 6630349870
 tx_bytes: 815877983
 rx_broadcast: 58230114
 tx_broadcast: 9307
 rx_multicast: 8406
 tx_multicast: 17
 rx_errors: 0
 tx_errors: 0
 tx_dropped: 0
 multicast: 8406
 collisions: 0
 rx_length_errors: 0
 rx_over_errors: 0
 rx_crc_errors: 0
 rx_frame_errors: 0
 rx_no_buffer_count: 0
 rx_missed_errors: 0
 tx_aborted_errors: 0
 tx_carrier_errors: 0
 tx_fifo_errors: 0
 tx_heartbeat_errors: 0
 [...]
Run Code Online (Sandbox Code Playgroud)

某些统计信息取决于 NIC 驱动程序,其确切含义也将如此。以上来自英特尔e1000。查看了少数驱动程序后,有些驱动程序收集的统计数据比其他驱动程序多得多(ethtool 可用的统计数据往往保存在单独的源文件中,例如drivers/net/ethernet/intel/e1000/e1000_ethtool.c,如果您需要翻找的话)。

ethtool -i eth0将显示驱动程序的详细信息,输出lspci -v应该更详细,但也有点混乱。


更新tg3.c函数中tg3_rx(),只有一个地方看起来可能带有 a tp->rx_dropped++但是代码中到处都是gotos,因此除了显而易见的原因之外,还有其他几个原因,即任何带有goto drop_it 或 的原因goto drop_it_no_recycle。(请注意,丢弃计数器是由驱动程序维护的少数几个之一,其余由设备本身维护。)

我必须提供的驱动程序源是 3.123。我最好的猜测是这段代码:

           if (len > (tp->dev->mtu + ETH_HLEN) &&
                skb->protocol != htons(ETH_P_8021Q)) {
                    dev_kfree_skb(skb);
                    goto drop_it_no_recycle;
            }
Run Code Online (Sandbox Code Playgroud)

检查 MTU,可能的原因是巨型帧或稍大的以太网帧以允许封装。我无法解释为什么tcpdump可能会改变行为,改变接口 MTU 是未知的。另请注意,tcpdump如果启用了TSO / LRO,您可能会“看到”大于 MTU 的数据包(解释)。

  • 如果 `tg3` 是一个模块并且你*真的*想深入了解它,你可以使用类似 `printk()` 的 `netdev_info()` 来记录一些事件,代码中已经有一些实例供你使用复印。参见 `include/linux/skbuff.h` 了解 `sk_buff` 结构(不适合胆小的人)。在`tg3_rx()`中的相关地方撒一些调用,重建并重新加载模块,然后等待...... (2认同)