原文:https://dev.to/gde/the-cable-buys-headroom-91-of-a-usb-20-bus-36-of-a-thunderbolt-one-563n(作者 @xbill)

本文完整记录了一次 USB 网络共享(tethering)的故障排查:一部标称 10 Gb/s 的手机,USB 链路却怎么也协商不到 USB 2.0 以上的速率。为了揪出原因,前后花了两天,试了四根线缆、三个物理接口。
USB 链路速率是由主机、线缆、设备三方自动协商的,最终生效的是三方都能支持的最慢一档。线缆是这场协商里货真价实的参与方,一根 USB 2.0 线缆无论如何也投不出高于 480 Mbps 的票,而且无论在哪里,都不会有任何提示告诉你这件事发生过。网络共享照常建立,DHCP 正常工作,流量正常流动,而链路已经被掐在两端所能提供速率的五分之一。
换对线缆买到的并不是速度,而是余量(headroom),而且差距一点都不含糊:这份日志里表现最好的一次 USB 2.0 传输,用掉了该总线实际可用承载能力的 91%;同样的链路换上 SuperSpeed 线缆后,只占 3.6%。
下文的每一条命令,你都可以直接拿去在自己的网络共享上运行;每一个数字,都出自这个仓库里的实测记录:
https://github.com/xbill9/tether
症状
仓库里保存了 45 条测量记录,覆盖四家厂商的 14 部手机,每条记录都是一次完整测试——三次顺序单流传输、一次四流并行测试、外加一次 ping——对端固定,传输大小固定为 8 MB。
这 45 条记录里,有 41 条的枚举速率是 480 Mbps。十四部手机、三种驱动、两家运营商、三个物理插口,整整两天,没有出现过一次 USB 3.0 协商。
最扎眼的“当事机”是一台 iPhone 17 Pro,它的 BOS 描述符可毫不掩饰自己的本事:
bcdUSB 2.10 SuperSpeed USB Device Capability: wSpeedsSupported 0x000e -> Full, High, SuperSpeed (5Gbps) SuperSpeedPlus USB Device Capability: bmSublinkSpeedAttr[0] 10Gb/s Symmetric RX SuperSpeedPlus bmSublinkSpeedAttr[1] 10Gb/s Symmetric TX SuperSpeedPlus
一台宣告 10 Gb/s 能力的设备,枚举速率却停在 480 Mbps——差了大约二十一倍。这种量级的落差,足以让你放下吞吐量测试,转头去读 sysfs 了。
总线速率是协商出来的,链路上每一环都有投票权
USB 链路速率不是手机的属性,也不是笔记本的属性。每次连接时,它都要在主机控制器、线缆、设备三方之间协商,训练达成的速率就是三方都能跑的最快模式。这条链路上任何一环是 USB 2.0,整条链路就会以 480 Mbps 建立。
在这场投票里,线缆是真正的参与者,不是一根被动的导线。SuperSpeed 要靠两对额外的差分线来承载,而 USB 2.0 线缆在物理上根本没有这两对线——它只有 D+/D-,仅此而已。把它接在一部 10 Gb/s 手机和一个 10 Gb/s 接口之间,两端就会协商降到 High Speed,然后一切完美工作。
而且没有任何东西会告诉你。没有报错,没有 dmesg 警告,没有降级模式指示,没有任何一行输出写着“是线缆把你限住了”。唯一的证据是 sysfs 里的一个数字——你得自己主动去读——旁边还有第二个数字,写着设备当初报出的能力:
speed(/sys/bus/usb/devices/<dev>/speed):三方协商达成的速率- BOS 描述符(
lsusb -v -d <vid>:<pid>):设备报出的能力
这两个数字之间的差距,就是线缆投出的那一票。下文第 1、2 步读的就是这两个数字,之后的每一步,都是在收窄范围,查出到底是哪位参与者投了低速票。
动手前,你手头应该有这些
- 一部通过 USB 做网络共享、并且握着默认路由的手机——先确认这一点,否则你测的会是 Wi-Fi
usbutils提供的lsusb,以及iproute2提供的ip- 对
/sys/bus/usb/devices和/sys/class/net的读取权限,不需要 root - 其他一切具备路由能力的接口全部 down。只要 Wi-Fi 还开着,
curl就会从它上面成功跑完,结果看起来会像一次网络共享测量
下面这些诊断步骤不会经过蜂窝链路传输哪怕一个字节。这一点在这里很重要:在本仓库跑一次完整测量大约要消耗 56 MB 按量计费的流量,而第 1 步到第 4 步的全部操作都是零流量。
第 1 步 — 先读总线速率
这是唯一一个一旦跳过、后续所有结论都会作废的读数。一根只能充电的线或者 USB 2.0 的线,会悄无声息地把总线封顶在 480 Mbps,而且任何地方都不会报错。
# 找到 tether 接口及其对应的 USB 设备 for i in /sys/class/net/*/device/driver; do ifn=$(basename $(dirname $(dirname $i))) drv=$(basename $(readlink -f $i)) case $drv in cdc_ncm|rndis_host|ipheth) echo "$ifn $drv";; esac done
enxb65575abcda3 ipheth
然后从接口一路回溯到 USB 设备,读出它训练完成的速率:
dev=$(basename $(readlink -f /sys/class/net/enxb65575abcda3/device/..)) cat /sys/bus/usb/devices/$dev/speed
480
480 是 USB 2.0,5000 是 USB 3.0 Gen 1,10000 是 Gen 2。与此同时,/sys/class/net/<if>/speed 给出协商出来的链路速率——不过要注意,ipheth 在那里会返回 EINVAL、什么都不报告,所以在 iPhone 上这个字段在每条记录里都是空白。
第 2 步 — 问一问设备本身具备什么能力
只有知道了设备在协商中拿出了什么,480 这个读数才有意义。
lsusb -v -d 05ac:12a8 2>/dev/null | grep -A3 "SuperSpeed"
本文开头的那段描述符就是这条命令的输出。设备能力是对照组。 对比一下 iPhone 16e——它是在这份日志里最快一次测试的八分钟前测的:它完全没有宣告任何 SuperSpeed 能力,所以它的 480 是它自己的上限,世上任何一根线都改变不了。
单单这一个区分,就把「链路中某个环节投了 480」和「手机本身投了 480」分开了,而且读取它不花任何成本。如果设备提供 SuperSpeed 而链路却训练在 High Speed,那么责任就在另外两个参与者身上——而参与者总共也就那两个。
第 3 步 — 找出所有端口,而不只是显眼的那些
之所以专门有这一步,是因为这次排查在写下来的记录里已经错了两次。
在现代笔记本上,显而易见的做法是枚举 Type-C 连接器,因为内核在启动时会把每个连接器绑定到它的 USB 端口:
dmesg | grep "typec port"
typec port0: bound usb3-port1 (ops connector_ops [usbcore]) typec port0: bound usb4-port1 (ops connector_ops [usbcore]) typec port1: bound usb3-port2 (ops connector_ops [usbcore]) typec port1: bound usb2-port1 (ops connector_ops [usbcore])
对照 lspci 来读,这就是这台机器 USB-C 的完整地图:
port0:USB 2.0 半边是3-1,SuperSpeed 半边是4-1(10 Gb/s),控制器是00:14.0Alder Lake PCHport1:USB 2.0 半边是3-2,SuperSpeed 半边是2-1(20 Gb/s),控制器是 `00:0d.0` Thunderbolt 4
这份清单本身是对的。但从它得出的结论——「这台机器上没有没试过的端口了」——是错的,代价大约是一个小时。
`/sys/class/typec` 只枚举 Type-C 连接器。 Type-A 插座没有 Power Delivery,因此没有连接器对象,不可能出现在那里。这台机器还有第三个对外插座,是这张地图看不见的。
改从端口列表里的 hotplug 条目来盘点端口:
for p in /sys/bus/usb/devices/usb*/*/usb*-port*; do [ "$(cat $p/connect_type 2>/dev/null)" = "hotplug" ] || continue peer="-"; [ -L "$p/peer" ] && peer=$(basename "$(readlink -f "$p/peer")") echo "$(basename $p) peer=$peer location=$(cat $p/location)" done | sort
usb3-port3 peer=usb4-port2 location=0x80000301 usb4-port2 peer=usb3-port3 location=0x80000301
usb3-port3 就是那个 USB-A 插座。它的 peer 是挂在另一个集线器上的一个 10 Gb/s 端口,而两者相同的 location 是内核在说:「这两个条目是笔记本侧面同一个物理孔的两半」。
这个 peer 关系是整场排查中最有用的一行,至于原因,马上就会清楚。
第 4 步 — 直接问线缆,然后看着它拒绝回答
一根电子标记(electronically marked)的 USB-C 线会通过 Power Delivery 宣告自己的数据能力,Linux 把它暴露成一个 portN-cable 设备,带一个装有 PD VDO 的 identity/ 目录。USB-C 规范要求速率超过 USB 2.0 的无源线缆带 e-marker,但不要求 USB 2.0 线带。所以缺 e-marker 会是真实证据。
ls /sys/class/typec/ cat /sys/class/typec/port0-partner/usb_power_delivery_revision
port0 port0-partner port1 usb_power_delivery_revision 0.0
这里没有 cable 节点,而这并不是关于线缆的证据。 协议栈根本没有暴露任何 VDO 数据:连着的 partner——手机本身——的 identity/ 目录是空的,报告的 PD 版本为 0.0。一个连手机的 PD 身份都不肯显示的协议栈,从一开始就不可能显示线缆的。
这一点之所以值得了解,恰恰是因为它看起来本应有效。在一台确实会报告线缆身份的主机上,这一条 cat 就是全部答案。而在这里,它是沉默,不是发现;要是把它当成发现,就等于在毫无证据的情况下给线缆定了罪。
追查
既然线缆信息无从读取,剩下的唯一手段就是替换法。一个下午,四条线,三个插口:
- 第 1 轮:无标识 C to C 线,插
3-2(Thunderbolt 4 口),总线 480 - 第 1b 轮:同一条线,插
3-1(另一个 Type-C 口),总线 480 - 第 2 轮:C to C 第二条线,插
3-1,总线 480 - 第 3 轮:C to C 第三条线,插
3-1,总线 480 - 第 4 轮:无标识 A to C 线,插
3-3(USB-A 口),总线 480
每一轮都是零 USB 错误、零断流。主机上有两个 SuperSpeed 根集线器,都完成了枚举,都闲着,而且谁都没见过任何设备。
一个诱人的解读是:连续四次阴性,就是指向主机的证据在累积。并不是。那四条线里,没有一条是已知带有 SuperSpeed 线对的。无标识的 C to C 线——就是随手机或充电器盒装附赠的那种——从构造上讲绝大多数就是 USB 2.0。四条全是 USB 2.0,这不是一个需要解释的巧合,而是意料之中的结果。
四个未知数,约等于同一个结果重复四次,而不是四次独立测试。
藏在中间的陷阱
这一段是整场排查里最值得偷师的部分,因为它跟 USB 毫无关系。
上面每一轮都测了吞吐量,而且数值动得厉害:
- 12:40(线 1):单流 96 / 103 / 103 Mbps;四流聚合 178 Mbps;RTT 平均 38.0 ms,mdev 6.7 ms
- 13:15(线 2):单流 56 / 36 / 21 Mbps;四流聚合 73 Mbps;RTT 平均 103.6 ms,mdev 110.3 ms
- 13:19(线 2,稳定后):单流 64 / 57 / 59 Mbps;四流聚合 85 Mbps;RTT 平均 54.2 ms,mdev 30.9 ms
- 13:26(线 3):单流 55 / 25 / 68 Mbps;四流聚合 101 Mbps;RTT 平均 45.9 ms,mdev 9.3 ms
- 14:07(线 4):单流 76 / 58 / 61 Mbps;四流聚合 130 Mbps;RTT 平均 52.1 ms,mdev 12.1 ms
连续四次换线,聚合吞吐一路爬升:73 → 85 → 101 → 130。每条新线看起来都比前一条更好。
但这些没有一条是线缆效应。整个下午,运营商网络一直在从一次低谷中恢复,而每次换线恰好都撞上了恢复过程中的某一级台阶。真正变化的是时间这个变量;线缆从头到尾没变过。USB 错误计数全程为零,而一条能把吞吐拖低 60% 的线缆,不可能不在这些计数器里留下痕迹。
由此沉淀出两条规则,如今都已写进仓库的方法论:
- 单流测试要记录三次,绝不要只记一次。这份日志里有一台手机,三次连续的完全相同传输分别跑出了 15、44 和 116 Mbps。任何单个数字都是对这条链路的谎言。
- 硬件改动的 A/B 对照要拿时间当基准,而不是拿前一个小时的读数当基准。如果无法交错测试,就不要归因。
那条真正管用的线
第二天,一条新的 USB-A 转 USB-C 线——大约 15 美元,专门买来当一条已知支持 SuperSpeed 的线,而不是再添一条未知数。
480 -> 5000
iPhone 完成了 SuperSpeed 链路训练,在 sysfs 里挪到了另一个集线器下,出现在 4-2,而不是之前每一轮的 3-x。这看起来像是换了端口,其实不是:
usb4-port2 peer=usb3-port3 location=0x80000301
4-2 对应 usb4-port2,它的 peer 是 usb3-port3——正是前一天测出 480 的那个 USB-A 插口,位置码也相同。设备之所以换了集线器,只是因为它开始训练 SuperSpeed,而在这台主机上,一次成功的 5 Gb/s 协商就该是这个样子。在这里,插口是对照组;唯一真正变过的变量,只有线缆。
同一根新线、同一个插口、同一份 DHCP 租约,一台 Pixel 9a 从另一侧证实了这个结论:
- 2026-09-05(旧线):总线速度 480 Mbps,协商链路 425 Mbps
- 2026-09-06(15 美元的线):总线速度 5000 Mbps,协商链路 3750 Mbps
两台手机,一次换线,那个吞掉了一整个下午的问题有了答案:那些无标识线就是 USB 2.0 线。
这条线缆解锁了什么:余量
总线读数是标题上的数字,它真正买到的是余量(headroom),而这个数字才能说明这一切到底值不值 15 美元。
仓库里有一个诊断常量:480 Mbps 的 USB 2.0 总线扣除协议开销后,实际批量吞吐按 300 Mbps 计。把日志里每一趟测试按其所在总线的占比来度量,结论相当扎眼:
- 日志中最佳的 USB 2.0 趟次:480 Mbps 总线,4 流聚合 273 Mbps,占原始带宽 56.9%,占可用带宽 91%
- Anker USB-A 转 USB-C,BBR:5000 Mbps 总线,4 流聚合 365.185 Mbps,占 7.3%
- 同一插口,CUBIC:5000 Mbps 总线,4 流聚合 370.695 Mbps,占 7.4%
- Thunderbolt 线缆:10000 Mbps 总线,4 流聚合 361.330 Mbps,占 3.6%
- Thunderbolt,BBR:10000 Mbps 总线,4 流聚合 317.250 Mbps,占 3.2%
91% 对 3.6% 就是全部论点,而这两个百分比的分母值得点明,免得对比被误读。91% 是 273 Mbps 相对 480 Mbps 总线的 300 Mbps 可用带宽;3.6% 是 361.330 相对 10000 Mbps 的原始带宽,因为仓库并没有对 SuperSpeed 总线实测过可用上限,凭空造一个比口径不一致更糟。如果按原始对原始来比,就是 56.9% 对 3.6%——十六倍而不是二十五倍,但无论哪种算法,结论都一样。
总线占比全程都是纯算术——每条记录的 4 流聚合除以它自己的 `bus_speed_mbps`,所以 273/480 = 56.9%,365.185/5000 = 7.3%。91% 那个数是 273 相对 300 Mbps 的可用上限,而不是原始的 480。
在 USB 2.0 上,45 条记录里最好的一趟已经用掉了总线可用容量的 91%。一点余量都不剩了。480 时代的每一趟好成绩都是顶在天花板上跑出来的,而那些没顶到天花板的趟次,则是被运营商压住了。
在 SuperSpeed 上,同一条链路只占总线的大约 7%。线缆本身没有让任何东西变快;它只是把天花板从“刚好贴着流量”挪到了“流量上方十四倍”的位置,于是网络共享链路现在可以放开手脚,接住无线电在任何一晚给出的任何速度——要知道这条链路自己在几分钟内的波动就能超过 4 倍。
其中还有四项测量直接越过了 300 Mbps 这条线:
- 480 时代最佳聚合(45 条记录):273 Mbps —— 否,为可用容量的 91%
- 4 流聚合,USB-C 插口:370.695 Mbps —— 是
- 4 流聚合,Anker 线缆(BBR):365.185 Mbps —— 是
- 4 流聚合,Thunderbolt:361.330 Mbps —— 是
- 单次 32 MB 传输,USB-C 插口:351.1 Mbps —— 是
这些数字在 USB 2.0 总线上根本达不到。不是“会慢一些”——是达不到。它们中的每一个,都需要一根能把票投给 SuperSpeed 的线缆。
为什么聚合值才是关键测试
上面两组数据里真正干活的是四流这个数字,值得说清楚为什么,而不是把它当成对单流数字的一次复核。
单流对四流聚合,是唯一能把“运营商慢”和“这台机器上有什么东西在崩”区分开的对比。如果四条流合起来比一条流快得多,说明广域路径还有余量,问题出在本机;如果不是,那就根本没有余量可挖。
Anker 线缆的 BBR 趟次是一个干净的现成例子。单流跑出 134.930 / 113.576 / 123.229 Mbps——离散幅度 1.19 倍——而对应的四流聚合为 365.185 Mbps,是单流均值的 2.95 倍。
把这两个数字放在一起读,链路就自己把自己说明白了。四条流拿到了接近单流三倍的吞吐,说明广域路径明显还有这么多可给,本机也没有任何东西在崩:1.19 倍的离散幅度加上零错误、零丢包,意味着没有无线损耗会被拥塞控制误读。在这个读数里,天花板不在这台机器上——这正是你想要的状态:网络共享链路已经不碍事,剩下的唯一变量就是无线电。
反过来的读数才是最容易坑人的。当聚合值只是压在单流数字上时,说明四条流没有找到任何额外空间,这时在主机上做再多调优,也变不出本就不存在的余量。
在把任何问题归咎于硬件之前,先看聚合值。正是这个读数在告诉你:答案到底在不在链路的你这一侧。
链路最终跑出了什么
总线这个变量排除之后,我分两个晚上、用两根线和两个主机控制器,在这台手机上完成了三组测试:
第一组:Thunderbolt 口,CUBIC
- 总线速度:10000 Mbps
- 单流(Mbps):151.036 / 119.931 / 147.540
- 四流聚合:361.330
- RTT 平均:27.268 ms
- RTT 平均偏差(mdev):2.272 ms
第二组:USB-C 母座,CUBIC
- 总线速度:5000 Mbps
- 单流(Mbps):134.856 / 143.749 / 129.250
- 四流聚合:370.695
- RTT 平均:29.601 ms
- RTT 平均偏差(mdev):7.171 ms
第三组:Anker 线,BBR
- 总线速度:5000 Mbps
- 单流(Mbps):134.930 / 113.576 / 123.229
- 四流聚合:365.185
- RTT 平均:36.715 ms
- RTT 平均偏差(mdev):5.597 ms
三个聚合成绩彼此相差不到 3%——361.330、370.695、365.185——而它们横跨两根不同的线、两个主机控制器、两种拥塞控制算法,总线速度还相差一倍。这些变量没有一个能撼动这个数字。链路稳定落在 365 Mbps 附近,底下是什么硬件已经无关紧要——这就是「有余量」的样子。
RTT 也随之到位:Thunderbolt 那组平均 27.268 ms,mdev 只有 2.272 ms,是整份日志里抖动最平的一组。
BBR 那组值得列出来,还有第二个理由。早期所有 SuperSpeed 测试跑的都是 cubic,而 480 时代的记录跑的是 bbr,也就是说总线和拥塞控制一直绑在一起变,功劳没法单独归给谁。这次在同一个端口、同一条总线上对齐条件后:BBR 拿到 365.185,CUBIC 拿到 370.695——差距只有几个百分点,BBR 的 mdev 还略低一点。支撑这些数字的,是总线。
带宽余量买一次就够,然后收手
注意上面第三组数据:从 Thunderbolt 口换回普通 USB-C 母座,总线速度砍半,却分毫未损——370.695 Mbps 对 361.330 Mbps。按算术算,361 Mbps 的流量在 10000 Mbps 的总线上只占约 3.6%,在 5000 Mbps 的总线上占 7.4%,两者的余量都大得离谱。把一条本来就闲置的天花板再翻倍,收益严格为零——在 USB 网络共享这个场景里,Gen 2 不值得追。
所以这条规则范围很窄,成本也很低:
- 一根确认过的好线,然后就停。四根无标识的线投出了四张一模一样的 480 票;一根标称合格的线在两台不同手机、同一个母座上跑出了 5000,其他条件一字未改。
- 调任何东西之前,先读总线速度。
cat /sys/bus/usb/devices/<dev>/speed是免费的;在一台支持 SuperSpeed 的手机上读到 480,就意味着无论你之后再修什么,真实吞吐都会被封顶在大约 300 Mbps。 - 不要买你够不着的上限。在这条链路上,5000 和 10000 反复测出了同样的结果。实践中余量是二元的:要么够用,要么不够。
- 别指望接口自己告诉你真相。四根失败的线里有两根两端都是 USB-C,插在 Thunderbolt 4 口上,手机也标称 10 Gb/s——这条链路上所有看得见的部分都显得正常。
这一切有一个局限,而且它正在靠测量、而不是靠争论去补上。300 Mbps 这个数字是项目代码仓库里的诊断常数,所以上面的说法属于边界论证,而不是受控 A/B 实验——到目前为止,还没有哪一轮测试把快链路换回 USB 2.0 的线上,去实测那要付出多少代价。这个受控复测已经排上日程,它正是这篇文章最想拿到的数字。
还有一个坑:传输块大小
测快链路的时候,单流数字停在 140 Mbps 附近,而四流聚合是 361——这是运营商对单条流分别整形的经典形状,当时的记录也是按这个结论写的。
但它是错的,而这次纠错值得单独写一段。
在同一条连接上,单个 32 MB 传输跑出了 332.3 Mbps——一条流就基本打平了整个四流聚合。所以差距出在固定的 8 MB 传输块大小上,而不是链路本身。只是,第一个想证明这点的尝试同样不受控:拟合模型预测 20 MB 时能到 267 Mbps,实测却只有 73.0 Mbps——因为这条链路自己就能在相邻两次传输之间塌缩 4.8 倍。
最终定案的设计是六次传输,8 MB 与 32 MB 交替进行,整轮只跨 3.89 秒,让链路波动没机会在两种大小之间分出厚薄:
- 第 1 次:8 MB,0.418 s,153.3 Mbps
- 第 2 次:32 MB,0.722 s,354.6 Mbps
- 第 3 次:8 MB,0.438 s,146.1 Mbps
- 第 4 次:32 MB,0.701 s,365.1 Mbps
- 第 5 次:8 MB,0.362 s,176.9 Mbps
- 第 6 次:32 MB,0.699 s,366.3 Mbps
8 MB 平均 158.75 Mbps,32 MB 平均 361.96 Mbps,比值 2.28 倍。每一次 32 MB 都压过紧挨着它的 8 MB,两组数据完全不重叠——最快的 8 MB(176.9)低于最慢的 32 MB(354.6)。
机制层面仍是悬案。对这些耗时做固定成本拟合,得到 637 Mbps 的渐近线和 0.305 s 的启动开销;按这条链路 29.6 ms 的 RTT 折算约是 10 个往返,而按教科书慢启动,爬到约 503 KB 的带宽时延积大约只需要 6 个。这里面一定藏着超出教科书慢启动的东西,但六次传输说不清那是什么。
和线缆是同一种失败模式,只是高了一层。一个测量工具给出的数字描述的是工具自身,而不是链路;唯一的出路,是把两种条件交错放进一个短到其他一切都来不及变化的窗口里。
速查表
这两个脚本都收录在仓库里,直接运行即可,不需要任何参数:
bin/tether-bus-check # 下面所有检测项,外加一个结论。不消耗蜂窝数据 bin/tether-report # 完整诊断清单。不消耗蜂窝数据 bin/tether-report --measure # 标准测速跑一轮。约消耗 56 MB 计费流量 bin/tether-interleave # 在链路波动下对两种传输大小做 A/B 对比
tether-bus-check 会读取协商两侧的信息,并指出是哪一方投出了低速票。tether-interleave 就是上一节那个设计——让两种传输大小背靠背交替进行,使链路漂移对两者的影响均等——并且它会在真正花掉流量之前,先打印出这笔开销。
各项单独的读数命令,如果你更愿意手动执行:
# 1. 哪个接口是网络共享口,用的什么驱动
for i in /sys/class/net/*/device/driver; do
ifn=$(basename $(dirname $(dirname $i)))
case $(basename $(readlink -f $i)) in
cdc_ncm|rndis_host|ipheth) echo "$ifn $(basename $(readlink -f $i))";; esac
done
# 2. 它是否持有默认路由(否则你接下来测的可能就是 Wi-Fi)
ip route show default
# 3. 最关键的读数 - 480 / 5000 / 10000
dev=$(basename $(readlink -f /sys/class/net/<if>/device/..))
cat /sys/bus/usb/devices/$dev/speed
# 4. 设备还有更快的可能吗?若没有 SuperSpeed 能力,到此为止
lsusb -v -d <vid>:<pid> 2>/dev/null | grep -A3 SuperSpeed
# 5. 所有外部端口,包括 /sys/class/typec 看不到的那些
for p in /sys/bus/usb/devices/usb*/*/usb*-port*; do
[ "$(cat $p/connect_type 2>/dev/null)" = hotplug ] || continue
peer="-"; [ -L "$p/peer" ] && peer=$(basename "$(readlink -f "$p/peer")")
echo "$(basename $p) peer=$peer location=$(cat $p/location)"
done | sort
# 6. 错误与丢包 - 非零值指向线缆或供电问题,而不是配置
ip -s link show <if>
第 1 到 6 步都不消耗蜂窝数据。等这些命令告诉你自己面对的是什么之后,再去跑传输测试。
总结
本文的目标是弄清楚:一部宣传 10 Gb/s 的手机,为什么换任何线缆、任何端口都协商不出高于 USB 2.0 的速度,以及把它修好值不值得。解题的关键,是把链路速率当作一场三方协商,并读出协商的两侧——链路实际达成的速率,对比设备宣称能提供的速率——然后去读端口 peer 映射表而不是 Type-C 连接器列表,这样就能固定同一个物理插口、只更换线缆。实测结果如下:
- 一根 15 美元的线缆把总线从 480 拉到了 5000 Mbps,在两部手机、同一个物理插口上得到验证,并确认此前四根无标识线缆投的都是 480 票。
- Pixel 9a 的协商链路从 425 提升到 3750 Mbps,8.8 倍,插口和 DHCP 租约保持不变。
- 带宽余量从占用 91% 降到约占用 7%。 45 条记录中最快的 USB 2.0 轮次,用掉了该总线可用承载量的 91%;而最好的几轮 SuperSpeed 只用掉各自总线的 7.3% 和 7.4%。
- 四组聚合成绩突破了 300 Mbps——370.695、365.185 和 361.330,外加一次 351.1 Mbps 的单次 32 MB 传输——没有一项是 USB 2.0 总线所能达到的。
- 5000 和 10000 Mbps 的总线实测成绩相当——370.695 对 361.330——所以一旦上限已经越过流量需求,再高的上限也换不来任何收益。
- 四根线缆和三个端口曾带来表面上的 73 → 130 Mbps 提升,而这完全是运营商网络在恢复,全程为零的 USB 错误计数也说明了这一点。
适用范围:一台主机、两部 AT&T 网络的手机、一个物理位置,测量于 2026-09-05 与 2026-09-06,固定端点、固定 8 MB 传输大小,共 45 条记录。最早的几轮 SuperSpeed 测试在换总线的同时也动了拥塞控制——2026-09-05 的记录跑的是 bbr,这几轮跑的是 cubic;这个混杂变量后来在 2026-09-08 用匹配的 BBR 轮次补上了——同一端口、同一总线,聚合 365.185 Mbps,对 CUBIC 轮的 370.695——因此 SuperSpeed 数据依托的是总线,而不是拥塞控制。300 Mbps 的 USB 2.0 批量传输上限是该仓库自带的诊断常数,并非在这台主机上实测得到的数值,所以「快速成绩在旧线缆上无法达到」这一论断属于边界推断;目前还没有对照实验把快速链路接回 USB 2.0 线缆,这项复测已排上日程。carrier.network 在 iOS 上无法获取,因此各轮次之间的运营商网络状况无法直接读出,只能从 RTT 推断。
用一套固定清单来诊断 USB 网络共享的策略,在循序渐进的分步验证中得到了印证。
原文:https://dev.to/gde/the-cable-buys-headroom-91-of-a-usb-20-bus-36-of-a-thunderbolt-one-563n(作者 @xbill)




