不能靠drop_monitor查丢包计数,因其仅作事件追踪、不维护累计值、易丢失消息且依赖调试符号;应使用/proc/net/snmp和/proc/net/netstat中持久稳定的原子计数器(如InDiscards、UdpInErrors)进行准确统计。

drop_monitor 是内核模块,不是用户态命令;它本身不提供“计数”接口,只负责在丢包发生时触发事件并通知 dropwatch 这类用户态工具捕获上下文。直接查“内核丢包计数”应绕开 drop_monitor,用更稳定、可量化、无需调试符号的统计源。
为什么不能靠 drop_monitor 查丢包计数
drop_monitor 模块设计目标是**事件追踪**,不是聚合统计:它在内核丢包路径(如 tcp_v4_rcv、ip_rcv_finish)插入 kprobe,每次丢包都发一个 netlink 消息给用户态;但它不维护累计值、不区分丢包类型、不记录时间戳,且默认不输出源 IP/端口等关键字段。一旦消息队列满或用户态进程没及时读取,事件就丢失——这意味着你看到的数字永远小于真实丢包量。
- 必须提前加载模块:
sudo modprobe drop_monitor,否则dropwatch启动即失败 - 依赖完整内核调试符号(
vmlinux),CentOS/RHEL 默认不装,Ubuntu 需额外安装linux-image-extra-$(uname -r) - 高流量下 probe 开销显著,可能加剧丢包,生产环境禁用
真正能查“内核协议栈丢包计数”的标准方式
内核协议栈丢包(即包已进 Ring Buffer,但被 socket 队列满、反向路径过滤、内存不足等丢弃)有明确、持久、无开销的计数器,全部暴露在 /proc/net/snmp 和 /proc/net/netstat 中:
-
cat /proc/net/snmp | grep -A1 "Ip:"→ 看InDiscards:IP 层因 MTU 不匹配、路由失败等丢弃 -
cat /proc/net/snmp | grep -A1 "Icmp:"→ 看InErrors:ICMP 处理异常丢包(如校验错、无效类型) -
cat /proc/net/netstat | grep -A2 "Tcp:"→ 看TcpInCsumErrors、TcpAttemptFails、TcpDrop(部分内核版本支持) -
netstat -s | grep -A5 "Udp:"→ 看UdpInErrors(socket 接收队列满、校验失败等)
这些字段是原子累加的,重启不重置,且与 /proc/net/dev 的 Rx-DRP 语义一致,可安全用于监控告警。
dropwatch 该什么时候用
只有当 ip -s link show eth0 显示 RX: dropped 持续上涨,且 ethtool -S eth0 中 rx_crc_errors/rx_fifo_errors 为 0,同时 netstat -s 的 UdpInErrors/TcpInCsumErrors 也未明显增长时,才说明丢包发生在协议栈深层函数里,此时 dropwatch 才有价值:
- 先运行
dropwatch -l kas看热点丢包函数(例如udp_queue_rcv_one_skb),确认是否集中在某一层 - 再结合
perf probe或systemtap加参数打印上下文(如sk->sk_num,skb->len) - 切勿在没排除物理层和驱动问题前启用——如果
rx_crc_errors > 0,dropwatch捕获的全是“包根本没进协议栈”的假信号
真正难的是区分丢包层级:Ring Buffer 溢出、驱动 FIFO 满、物理链路 CRC 错、协议栈缓冲区满、iptables 丢弃、tc netem 限流……它们共用“dropped”这个词,但修复手段天差地别。盯住 /proc/net/dev 的 Rx-DRP 和 Rx-OVR 差值,比纠结 drop_monitor 是否加载成功实在得多。











