☰
比丢包率更准:TcpQuality如何用bpftrace追踪TCP重传并量化真实网络损耗
2026/10/17 6:33:00 网站建设 项目流程

【免费下载链接】TcpQuality

项目地址:https://gitcode.com/gh_mirrors/tc/TcpQuality
点击查看免费下载

测网速时,ping 丢包率常常是 0%,但真实业务却卡顿——问题在于 ICMP 小包与 TCP 大流量的路径、优先级都不同。TcpQuality 是一款 Linux TCP 质量检测脚本,它借助 bpftrace 在内核级钩住tcp_retransmit_skb事件,逐段记录真实重传并去重计数,把"这条链路到底丢了多少 TCP 数据段"量化成可对比的指标,比传统丢包率更贴近用户真实体感。

为什么"丢包率"经常会骗人

很多运维工具用 ping 或 mtr 判断网络质量,但这类探测存在明显偏差:

  • 协议不同:ping 发的是 ICMP 小包,而你的业务走的是 TCP 443 大流量,部分运营商会对其做不同的 QoS 调度;
  • 包长不同:小探针包容易"挤"进队列,大包却容易触发队列丢弃;
  • 口径不同:ICMP 丢包按"往返失败"计,一次抖动就可能丢一个 ping,而 TCP 一次丢包会触发整段重传,两者的量级完全不可比。

换句话说,ping 显示 0% 丢包 ≠ 你的 TCP 流量没有丢包。真正反映链路损耗的,是"有多少 TCP 数据段被迫重传了至少一次"。

核心原理:bpftrace 内核级追踪重传

TcpQuality 的关键在于直接用 bpftrace 在内核里抓"重传"这个动作本身。核心脚本是 tcpquality-retrans-seq.bt,它挂载在内核 tracepointtcp:tcp_retransmit_skb上:

tracepoint:tcp:tcp_retransmit_skb /args->dport == 443/ { if (args->skbaddr != 0) { $skb = (uint64)args->skbaddr; $seq = *(uint32 *)($skb + 40); $end_seq = *(uint32 *)($skb + 44); ... } }

它只关注443 端口的 TCP 重传事件,从重传 skb 中读出该数据段的seq/end_seq(序列号区间),连同目标地址、socket 指针一起输出。这样每一个"被重传的数据段"都有了一份内核级证据,而不是靠事后估算。

一个细节很见功力:同一个数据段可能被重传多次(RTO 退避后反复发)。TcpQuality 在用户态以skaddr + seq + end_seq组合去重,保证一个数据段无论重传几次,只计一次——这正是"唯一重传段占比"比裸重传次数更能反映真实损耗的原因。

双保险设计:seq 主探针 + skb 兜底

不同内核的 BTF 信息可用性不同,直接读 TCP 控制块可能在某些内核上失败。TcpQuality 为此准备了两级探针:

探针文件去重键适用场景
seq 主探针tcpquality-retrans-seq.btsocket + seq + end_seq内核 BTF 可读,精度最高
skb 兜底探针tcpquality-retrans-skb.btsocket + skb 指针无 BTF TCP 类型的内核

启动逻辑在 runTcpQuality-core.sh 的speedtest_retrans_trace_start中:优先尝试 seq 探针,失败则自动切换 skb 兜底方案;两者都不可用时才放弃追踪,绝不输出一个虚假的"0 重传"结果。脚本注释里还特别提醒 shell 侧校验器要拒绝零序列号记录,防止内核布局差异污染数据。

与 TCP_INFO 交叉验证,结果更可信

只靠 tracepoint 还不够,TcpQuality 还引入第二数据源做交叉验证:tcpquality-tcpinfo.c。

这是一个轻量级 LD_PRELOAD 库,会拦截测速进程(curl)的connect/close调用:

  1. 只跟踪目标 IP 的 443 连接;
  2. 连接关闭时用getsockopt(TCP_INFO)读取该 socket 的权威统计:tcpi_total_retrans(累计重传次数)、tcpi_data_segs_out(发出数据段数)、tcpi_bytes_retrans(重传字节数);
  3. 写入快照文件供主脚本解析。

若系统没有预编译库,主脚本会自动降级为用ss -tinp解析同等信息(见 runTcpQuality-core.sh 的speedtest_tcp_info_ss_snapshot)。最终报告里,bpftrace 的"唯一重传段数"必须落在 TCP_INFO 累计重传数的合理范围内才会被采纳(runTcpQuality-core.sh),两套独立数据互相印证,结果可靠性远高于单一来源。

如何跑起来:一行命令测出真实损耗

TcpQuality 默认检测全国三网运营商节点,入口脚本为 runTcpQuality.sh。国内环境一行即可运行:

bash <(curl -fsSL https://tcpquality.ibsgss.uk/run)

常用参数(完整列表见 README.md):

  • --all:完整检测 IPv4/IPv6、CERNET/CERNET2、国际互联和单线程测速;
  • --speedtest:TCP 质量探测后追加单线程测速(重传追踪就工作在这一阶段);
  • -p NUM:并行节点数,范围 1-31,默认 16;
  • --province bj等:只测指定省份。

测速阶段的完整流水线是:启动 bpftrace 探针 → 启动 TCP_INFO 监控 → 发起 curl 下载/上传 → 停止探针 → 去重计数并交叉校验。整套编排集中在 runTcpQuality-core.sh 中,你无需关心任何细节,报告会自动呈现每个节点的延迟、重传数与重传占比。

你最终会得到什么

跑完后,每个节点会得到一组远比"丢包率 0%"有信息量的指标:

  • 唯一重传段占比:真正发生过至少一次重传的数据段比例,直接量化链路损耗;
  • 累计重传数与重传字节数:来自 TCP_INFO 的 socket 级口径;
  • 单线程测速速率:在锁定 TOS 计数、排除干扰流量后的干净速率;
  • 分方向(下载/上传)、分地址族(IPv4/IPv6)的对比,帮助定位是回程质量差还是国际互联抖动。

小结

🔍 TcpQuality 的思路很清晰:既然 ICMP 丢包率不能代表 TCP 真实损耗,那就回到内核本身,用 bpftrace 逐个追踪重传数据段、用 seq 去重计数,再叠加 TCP_INFO 交叉验证。对需要评估线路质量的站长和运维来说,这套"重传追踪 + 多源校验"的方法,比任何单一 ping 指标都更接近用户的真实体感。

项目采用 GPL-3.0-only 授权,详见 LICENSE。

【免费下载链接】TcpQuality

项目地址:https://gitcode.com/gh_mirrors/tc/TcpQuality
点击查看免费下载
上一篇:还在为 .qmc0、.ncm 打不开发愁?三分钟学会用 Unlock Music 免费解锁加密音乐
下一篇:三步为整张专辑配齐歌词:163MusicLyrics批量获取LRC歌词的完整上手指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询