ethtool -s 的 drop 字段仅反映硬件和驱动层丢包,不包含内核协议栈丢包;rx_dropped 高而 rx_missed_errors 为 0 时,丢包多发生在内核软中断或 socket 队列等上层环节。

ethtool -S 显示的 drop 字段到底指哪层丢包
ethtool -S 输出里一堆带 drop 的字段(比如 rx_dropped、tx_dropped、rx_missed_errors),但它们不是同一层的丢包,混在一起看会误判。真实链路中,NIC 硬件队列、驱动环形缓冲区、内核协议栈三者各自有丢包点,而 ethtool -S 只反映前两层——也就是硬件和驱动层面的计数。
常见错误现象:看到 rx_dropped 很高,就以为是网卡或线缆问题,结果查了半天物理层,最后发现是 net.core.netdev_max_backlog 太小,导致软中断来不及处理,驱动被迫丢包(这部分计入 rx_dropped,但根源在内核参数)。
-
rx_missed_errors:DMA 写不进 ring buffer,说明驱动收包速度跟不上硬件入包速率,通常伴随rx_dropped上升 -
rx_crc_errors/rx_frame_errors:物理层问题(线缆、光模块、交换机端口),必须结合ethtool eth0查Link detected和Speed -
tx_aborted_errors/tx_carrier_errors:发送失败,多见于双工不匹配或 PHY 异常,不是软件配置能解决的
怎么区分是驱动丢包还是硬件丢包
关键看 rx_dropped 和 rx_missed_errors 是否同步增长。如果 rx_missed_errors 为 0,但 rx_dropped 持续上升,大概率是驱动把包交给了内核,但被内核协议栈(如 net.core.somaxconn 或 socket backlog)丢弃了——这类丢包 ethtool -S 不统计,得看 /proc/net/snmp 里的 TcpExt: 行(如 SyncookiesFailed)或 ss -s。
实操建议:
本书以培养高级网站建设与管理人才为目标,内容循序渐进,由浅入深,通过大量的实例系统全面地介绍了Linux+PHP+MySQL环境下的网络后台开发技术。本书详尽分析了近30个典型案例。包括计数器、网站流量统计、留言板、论坛系统、聊天室、投票与调查、用户管理、新闻发布系统、广告轮播、购物系统等等,力求让读者通过对案例的学习,轻松掌握PHP和MySQL的编程精要,迅速掌握网络后台开发技巧。 本书适
- 先跑
watch -n1 'ethtool -S eth0 | grep -E "(drop|missed|error)"',观察变化频率和幅度 - 同时执行
cat /proc/net/dev,对比rx_dropped(ethtool -S)和rx_dropped(/proc/net/dev 第三列)——后者是内核网络层汇总值,若远大于前者,说明丢包发生在协议栈 - 检查
softirq压力:grep "NET_RX" /proc/softirqs,如果某 CPU 的数值远高于其他核,且rx_dropped在该核绑定的队列上飙升,说明 RSS 队列不均或软中断瓶颈
rx_dropped 高但 rx_missed_errors 为 0 的典型原因
这不是 NIC 故障,而是驱动已成功将包送入内核,但后续环节拒绝接收。最常见的是以下三种情况:
- socket 接收队列满:
net.core.rmem_max设置过小,或应用读取太慢,导致sk_buff在sk_receive_queue积压后被丢弃(计入/proc/net/snmp的TcpExt:ListenOverflows或ListenDrops) - netfilter 规则过多或复杂:特别是
iptables的ip_tables模块在高并发下匹配开销大,触发nf_conntrack表满时,会静默丢包,且不增加ethtool -S计数 - 启用
GRO/LSO但硬件不兼容:某些老网卡开启gro后反而造成校验失败重传,表现为rx_dropped升高但无对应 error 字段,用ethtool -k eth0查当前状态,临时关掉试试:ethtool -K eth0 gro off
排查时最容易忽略的两个点
一是 ethtool -S 的计数器不会自动清零,重启网卡或系统才重置。如果之前出过问题,没清过计数,直接看绝对值会误导判断。每次排查前先执行 ethtool -S eth0 | grep drop 记下初始值,再压测几分钟再比对增量。
二是不同驱动对字段命名不一致。例如 igb 驱动用 rx_drops_lpe 表示 LPE(Large Packet Error)丢包,而 ixgbe 用 rx_lpe;mlx5 则把类似指标放在 rx_out_of_buffer。不查对应驱动文档,只靠字段名猜含义,十有八九误判。







