tcpdump无法直接统计udp丢包率,需结合增大缓冲区抓包、/proc/net/snmp中rcvbuferrors/noports指标分析、应用层序列号检测及iptables/rss/缓冲区等干扰排查来间接定位丢包环节。

在Linux环境下,tcpdump本身无法直接统计UDP报文丢失率,因为它只负责抓包,不参与收发过程,也无法感知内核接收队列溢出、网卡丢包等底层丢失事件。但可以通过组合tcpdump抓包 + 系统指标分析 + 应用层配合,间接定位和估算UDP丢包环节。以下为实用、可落地的排查与监控方案:
一、用tcpdump捕获目标UDP端口流量并校验完整性
确保抓包不丢帧是前提。默认情况下,tcpdump可能因缓冲区不足而丢包(尤其高吞吐场景):
- 使用
-B参数增大内核缓冲区(如-B 4096表示4MB) - 加
-n -q减少解析开销,避免DNS反查和详细协议解析 - 限定抓包数量或时间,防止磁盘写满,例如:
tcpdump -i eth0 -B 4096 -n -q udp port 5060 -c 10000 -w sip.pcap - 抓包结束后检查是否发生自身丢包:
tcpdump -r sip.pcap 2>&1 | grep "packets dropped"—— 若显示非0,说明tcpdump已漏抓,结果不可信
二、同步采集系统级UDP丢包指标
内核通过/proc/net/snmp和/proc/net/netstat暴露UDP收发统计,重点关注“RcvbufErrors”和“NoPorts”:
-
RcvbufErrors:表示因套接字接收缓冲区满导致的丢包(应用未及时recv) -
NoPorts:表示目的端口无监听进程,内核直接丢弃(常见于服务未启动或端口错配) - 实时查看命令:
watch -n 1 'grep -A1 \"Udp:\" /proc/net/snmp | tail -1'
输出形如:Udp: InDatagrams NoPorts InErrors OutDatagrams RcvbufErrors SndbufErrors - 对比抓包计数与
InDatagrams增量:若后者远大于前者,说明丢包发生在tcpdump之前(网卡驱动、防火墙、内核早期丢弃)
三、结合应用日志与序列号检测真实业务丢包
UDP本身无重传机制,需依赖上层协议(如RTP、自定义协议)携带序列号。这是定位“业务层丢包”的关键:
- 若应用协议含递增序列号(如RTP的sequence number),可用tshark快速分析丢包位置:
tshark -r sip.pcap -Y "udp.port==5060" -T fields -e rtp.seq | sort -n | awk '{if(NR>1 && $1!=prev+1) print "Gap at", prev, "→", $1} {prev=$1}' - 若无序列号,可在发送端打时间戳+序号(如每包加8字节头:uint32_t seq + uint32_t ts),接收端比对
- 注意:仅靠tcpdump看到的包不等于应用成功读取——还需检查应用是否调用
recv()失败、返回0或EAGAIN/EWOULDBLOCK
四、排除常见干扰因素
很多“疑似丢包”实为环境配置问题:
-
iptables/nftables规则静默丢弃UDP包:运行
sudo iptables -L -v -n -t filter和sudo nft list ruleset检查是否有DROP/REJECT规则匹配目标端口 -
网卡RSS或中断绑定不均:多队列网卡下,若所有UDP流被哈希到同一CPU队列,可能造成该核软中断过载丢包;可用
ethtool -x eth0查看RFS分布,用sudo ethtool -X eth0 equal 8均衡队列 -
UDP接收缓冲区过小:检查并调大:
sysctl net.core.rmem_max(最大值)sysctl net.core.rmem_default(默认值)
对单个socket,应用应调用setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size))











