tcpdump 可通过 tcp[12] & 64 != 0 过滤含 ecn-echo(ece)标志的 tcp ack 报文,需先启用内核 ecn(net.ipv4.tcp_ecn=1),确认三次握手协商成功,并结合 ip 头 tos 字段(0x03 表示 ce)及发送方 cwnd 变化验证拥塞响应效果。

直接用 tcpdump 捕获并识别 ECN-Echo(ECE)标志位的 TCP 报文,是验证和分析显式拥塞通知机制是否生效的关键操作。ECN-Echo 出现在接收方发给发送方的 ACK 报文中,表示“我收到了带 CE 标记的数据包”,属于 TCP 头部的控制标志位之一(与 SYN、ACK、FIN 同级),需结合 TCP 标志过滤和十六进制解析才能准确识别。
确认系统已启用 ECN 并产生 ECE 流量
ECN 需两端(客户端 + 服务器)及中间网络设备共同支持才可能触发 ECE。先检查本地内核是否开启 ECN:
-
查看当前设置:
sysctl net.ipv4.tcp_ecn—— 返回1表示启用(推荐值),0或2则不启用或仅用于协商 -
临时启用:
sudo sysctl -w net.ipv4.tcp_ecn=1 -
确认连接实际协商了 ECN:抓包后观察三次握手的 SYN/SYN-ACK 是否携带 ECN 标志(TCP 头部中 CWR 和 ECE 位在 SYN 阶段应为 0,但 IP 头部 ToS 字节后两位应为
10表示 ECN-Capable Transport)
用 tcpdump 过滤含 ECE 标志的 TCP ACK 报文
TCP 标志位共 6 位(URG、ACK、PSH、RST、SYN、FIN),ECE 和 CWR 是额外定义在 TCP 头部的两个独立标志位(RFC 3168),不在标准 tcpdump 的 tcp[tcpflags] 简写中,必须用偏移+掩码方式匹配:
-
捕获所有含 ECE 标志的 TCP 包(即接收方回传的拥塞通知):
sudo tcpdump -i any 'tcp[12] & 64 != 0' -nn -vv
说明:tcp[12]指 TCP 头部第 13 字节(从 0 开始计),其中第 6 位(bit 6,值为 64)即 ECE 位;& 64 != 0表示该位被置 1 -
进一步限定为纯 ACK(不含数据)且含 ECE:
sudo tcpdump -i any 'tcp[12] & 64 != 0 and tcp[tcpflags] & tcp-ack != 0 and tcp[tcpflags] & tcp-push == 0' -nn
可排除携带 PSH 的干扰包,聚焦典型拥塞响应
验证报文内容并关联拥塞行为
捕获到 ECE 报文后,需结合上下文判断是否真实反映拥塞管理效果:
-
看前序数据包是否带 CE 标记:在同一流中向上追溯,找目的 IP 相同、源端口/目标端口匹配的前一个 TCP 数据包,用
tcpdump -xx查其 IP 头部第 2 字节(ToS 字段)——若值为0x03(二进制00000011),末两位11表示 CE(Congestion Experienced) -
看后续发送速率变化:ECE 报文发出后,观察发送方是否降低 cwnd(可用
ss -i实时查 socket 拥塞窗口)、是否减少重传、RTT 是否趋于稳定——这需要配合ss -i src :port或/proc/net/snmp中 TCP 统计项交叉验证 -
对比无 ECN 场景:关闭
net.ipv4.tcp_ecn后复现相同负载,观察丢包率、重传次数、应用层延迟是否明显升高
实用技巧与避坑提醒
ECN 抓包易因细节忽略而误判:
- 混杂模式不是必须,但建议加
-p关闭以避免干扰;用-s 128足够捕获 IP+TCP 头部(含标志位),无需全包 - ECE 只出现在 ACK 报文,不会出现在 SYN、FIN 或纯数据包中;CWR(Congestion Window Reduced)则出现在发送方收到 ECE 后的下一个数据包中,可用
tcp[12] & 128 != 0过滤 - 部分老旧中间设备会清除 ECN 位,导致 ECE 不出现——此时抓包看到的是丢包而非标记,说明 ECN 未端到端贯通
- Wireshark 中显示为
[ECN Echo],但 tcpdump 不自动解析,必须靠字节偏移判断











