RTS/CTS 是 802.11 里很常见的保护机制。很多资料会把它讲成“发送数据前先握手”,这个说法没错,但是排查问题时不够用。
我理解 RTS/CTS 时,更愿意把它看成一个“预约空口时间”的过程:先用很短的控制帧告诉周围设备,后面这段时间我要完成一次数据交换,你们先不要抢信道。
这篇文章按抓包分析的方式整理,不单独背字段,而是重点看这些问题:
- 普通 RTS 里
RA、TA分别代表什么; Duration到底保护了多长时间;- RTS/CTS 和 CTS-to-self 有什么区别;
- ERP Protection 为什么会让 2.4 GHz 网络变慢;
- VHT/HE dynamic bandwidth RTS 为什么可能出现“看起来像组播地址”的
TA; - 现场抓包时应该按什么步骤判断。
先把结论写在前面:普通 RTS 里,TA 通常就是发送方 MAC;但在 VHT/HE dynamic bandwidth RTS 里,TA 可能是 bandwidth signaling TA,不能直接按普通源地址理解。
一、RTS/CTS 解决的是什么问题
802.11 是共享介质。一个 STA 要发送数据,不能只看自己这里信道是不是空闲,还要考虑接收方附近有没有别的设备正在发。
典型隐藏节点场景如下:
STA A 能听到 AP
STA C 能听到 AP
STA A 和 STA C 互相听不到
这时 A 和 C 都觉得信道空闲,同时向 AP 发数据。对 AP 来说,两路信号叠在一起,数据帧就可能解不出来。
RTS/CTS 的基本流程如下:
STA A -> AP RTS
AP -> STA A CTS
STA A -> AP DATA
AP -> STA A ACK
这里真正有用的不只是 RTS,而是 AP 回出来的 CTS。A 附近的隐藏节点未必听得到 A 发出的 RTS,但是只要它能听到 AP 发出的 CTS,就会根据 CTS 里的 Duration 设置 NAV,在预约时间内暂停竞争。
所以 RTS/CTS 不是提高 PHY rate 的机制,它的作用是用额外控制帧开销,换取后续长数据帧少被撞掉。
二、普通 RTS 帧格式
RTS 是 control frame,格式很短:
Frame Control
Duration
RA
TA
FCS
普通 RTS 可以这样理解:
RA = Receiver Address = RTS 接收方 = 后续 DATA 接收方
TA = Transmitter Address = RTS 发送方 = 后续 DATA 发送方
例如一个 STA 准备给 AP 发数据:
RTS.RA = AP MAC
RTS.TA = STA MAC
CTS 更短,只有一个地址字段:
Frame Control
Duration
RA
FCS
在普通 RTS/CTS 交换里,CTS 的 RA 应该等于前一个 RTS 的 TA:
RTS.TA == CTS.RA
这个关系在排查普通 RTS/CTS 时很好用。但是注意,它只适用于普通场景。后面会讲到 VHT/HE dynamic bandwidth RTS,这种情况下 TA 可能不是普通发送方 MAC。
三、Duration 保护的是一段时间
RTS/CTS 的核心不是地址,而是 Duration/NAV。
经典单帧交换如下:
RTS -> SIFS -> CTS -> SIFS -> DATA -> SIFS -> ACK
RTS 发出去之后,后面还要留出 CTS、DATA、ACK 和 3 个 SIFS 的时间,所以常见计算方式是:
RTS Duration = 3*SIFS + T_CTS + T_DATA + T_ACK
CTS 里的 Duration 是剩余时间,可以近似理解为:
CTS Duration = RTS Duration - T_CTS - SIFS
这两个公式只适合最经典的单帧、有 ACK 的交换。如果是下面这些情况,就不能照抄:
- A-MPDU + Block ACK;
- TXOP 内连续发送多帧;
- No Ack policy;
- 分片;
- 管理帧响应;
- 宽带宽 duplicate RTS/CTS;
- 后续 PPDU 时长和普通 DATA/ACK 不一致。
抓包时我一般不只看字段值,还会看后续行为是否对得上:
RTS Duration 太短 -> 旁听 STA 可能提前竞争,DATA/ACK 被打断
RTS Duration 太长 -> 其他 STA 沉默过久,airtime 被浪费
Duration 与后续帧不匹配 -> RTS/CTS 有,但 DATA/ACK 异常或 retry 增多
也就是说,看到 RTS/CTS 不代表保护一定成功,还要看后面的 DATA、ACK、Retry、ACK miss 有没有按预期变化。
四、RTS/CTS 和 CTS-to-self 不一样
CTS-to-self 经常和 RTS/CTS 放在一起讲,但两者的保护范围不一样。
CTS-to-self 是发送方自己发一个 CTS,RA 设置成自己的地址:
发送方 -> 周围 STA CTS-to-self
发送方 -> 接收方 DATA
接收方 -> 发送方 ACK
这样做的好处是开销小,因为省掉了 RTS 和接收方回复 CTS 的过程。它常见于 ERP、HT、VHT 等保护场景。
但是 CTS-to-self 只能影响听得到发送方的设备。如果问题出在接收方附近的隐藏节点,CTS-to-self 不一定能保护住。
RTS/CTS 的区别在于,CTS 是接收方发出来的:
发送方 -> 接收方 RTS
接收方 -> 发送方 CTS
发送方 -> 接收方 DATA
接收方 -> 发送方 ACK
接收方附近的隐藏节点更容易听到这个 CTS,从而设置 NAV。
所以不能简单说“CTS-to-self 是 RTS/CTS 的轻量版”。更准确的说法是:CTS-to-self 开销小,但保护范围偏发送方;RTS/CTS 开销更大,但更容易覆盖接收方附近的隐藏节点。
五、开启 RTS/CTS 不一定提升吞吐
RTS/CTS 是成本和收益的交换。
比较可能有收益的场景:
- hidden node 明显;
- 帧比较大,重传代价高;
- 链路距离远,ACK miss 或 retry 明显;
- mesh、无线桥接、多 AP 重叠环境复杂;
- RTS threshold 只对大帧启用保护。
比较容易变差的场景:
- 小包很多;
- hidden node 不明显;
- basic rate 很低;
- RTS threshold 设置太低;
- 2.4 GHz mixed mode 下保护帧太多。
我一般会同时看下面几组数据:
retry / ACK miss 有没有下降
RTS/CTS airtime 占比有没有过高
端到端吞吐有没有提升
时延和抖动有没有改善
如果只看到“RTS/CTS 开了”,但 retry 没下降、airtime 还被控制帧吃掉很多,那实际体验可能会更差。
六、ERP Protection 里的 RTS/CTS
2.4 GHz 802.11g/ERP 和 802.11b 共存时,AP 可能启用 ERP Protection。
原因是 legacy 802.11b 设备可能不能正确解码 ERP-OFDM 帧,也就拿不到这些帧里的 Duration/NAV。为了避免 legacy 设备打断 OFDM 数据帧,AP 或 STA 会先发 legacy 设备能理解的保护帧。
常见保护方式有两种:
RTS/CTS
CTS-to-self
排查 2.4 GHz 网络突然变慢时,不要只盯着 DATA rate。Beacon 或 Probe Response 里的 ERP Information 很关键:
NonERP_Present = 1 表示 BSS 或邻近环境里存在 non-ERP 影响
Use_Protection = 1 表示 ERP STA 需要使用保护机制
如果抓包里看到大量低速率 RTS/CTS 或 CTS-to-self,就要单独算 protection airtime。用户看到的现象可能是“协商速率看起来不低,但实际吞吐很差”。
七、最容易踩坑的是 bandwidth signaling TA
普通 RTS 里:
TA = 发送方 MAC
这句话大多数时候没问题,但不能无条件套到 VHT/HE dynamic bandwidth operation。
在 VHT/HE dynamic bandwidth 场景下,RTS 可能使用 non-HT PPDU 或 non-HT duplicate PPDU 承载。MAC 帧格式看起来仍然是普通 RTS:
Frame Control
Duration
RA
TA
FCS
但是这里的 TA 可能被设置成 bandwidth signaling TA。
也就是说,这个地址不一定是普通意义上的发送方原始 MAC,而是借用 RTS 的 TA 字段传递带宽相关信息。抓包里就可能看到一个“像组播地址”的 TA。
现场判断时,如果看到下面这些现象,要先停一下,不要直接判驱动填错源 MAC:
RTS.TA 的 Individual/Group bit 被置 1
RTS 使用 non-HT PPDU 或 non-HT duplicate PPDU
场景涉及 VHT/HE dynamic bandwidth
后续 DATA 带宽行为和请求带宽有关
另外,non-HT PPDU 的 scrambler initialization 里也可能带和带宽相关的 TXVECTOR 信息,例如:
CH_BANDWIDTH_IN_NON_HT
DYN_BANDWIDTH_IN_NON_HT
这些信息不在普通 MAC 字段里。不同网卡、驱动、radiotap 暴露能力不一样,Wireshark 里也不一定都能直接看到。
所以更稳的判断方式是:看到 RTS.TA 像组播地址时,先确认 PPDU 类型、是否 VHT/HE dynamic bandwidth、抓包设备覆盖的信道宽度,再看后续 DATA 是否按被确认的带宽发送。
八、Dynamic 和 Static bandwidth 的 CTS 含义
40/80/160 MHz 是由多个 20 MHz 子信道组合出来的。non-HT duplicate RTS/CTS 会在多个 20 MHz 子信道上复制 legacy 可解码的控制帧。
这里要分 dynamic bandwidth 和 static bandwidth。
Dynamic bandwidth 下,发送方可以请求较宽带宽,接收方根据各个 20 MHz 子信道的 CCA/NAV 状态,只确认可用的部分。
例如:
发送方请求 80 MHz
接收方只在 primary 20 MHz 回 CTS
这不一定是错误。它可能表示只有 primary 20 MHz 可用。后续合理行为是降到 20 MHz 发,或者放弃本次发送、重新竞争。
真正不合理的是:
CTS 只确认了 20 MHz
发送方继续按完整 80 MHz 发 DATA
这样 secondary channel 上的 STA 可能没有被 CTS/NAV 压住,后续宽带宽 DATA 就可能和 OBSS 或其他 STA 冲突。
Static bandwidth 更严格。发送方请求 80 MHz static 时,本次受保护发送通常要求完整 80 MHz 条件满足。如果只监听 primary 20 MHz,看到 RTS -> CTS,不能证明完整 80 MHz 保护成功。
CTS 后没有 DATA,也不一定是“AP 没收到 CTS”。可能原因包括:
- secondary 20 MHz 没有对应 duplicate CTS;
- secondary channel CCA busy;
- secondary channel 已有 NAV;
- 发送方没有收到满足 static 带宽要求的有效 CTS;
- 抓包设备没有覆盖实际 DATA 所在的带宽。
九、我会这样分析一段异常抓包
如果现场给我一段抓包,说“RTS/CTS 后面不对”,我会按下面顺序看。
第一步,先确认保护类型:
ordinary RTS/CTS
CTS-to-self
ERP protection
VHT/HE dynamic bandwidth RTS
static duplicate RTS
类型没定之前,不要急着解释 RA、TA、Duration。
第二步,看地址关系:
普通 RTS:
RTS.RA -> 后续 DATA 接收方
RTS.TA -> 后续 DATA 发送方
CTS.RA -> 前一个 RTS.TA
如果 RTS.TA 看起来像组播地址,要优先检查是不是 bandwidth signaling TA。
第三步,看时序:
RTS -> SIFS -> CTS -> SIFS -> DATA -> SIFS -> ACK
异常一般落在这些位置:
RTS 后没有 CTS
CTS 不是 SIFS 后回来
CTS 后没有 DATA
DATA 后 ACK miss
Retry bit 开始堆起来
第四步,看 PHY 和带宽信息:
RTS/CTS rate
basic rate
PPDU 类型
channel width
primary / secondary channel
抓包设备实际覆盖了多少带宽
没有 PHY metadata 时,不要只靠 MAC header 下结论。
十、容易误判的现象
| 现象 | 不能直接下的结论 | 下一步确认 |
|---|---|---|
| RTS.TA 像组播地址 | 驱动填错源 MAC | 先确认是否 VHT/HE dynamic bandwidth RTS,以及是否 bandwidth signaling TA |
| primary 20 MHz 有 RTS/CTS | 80 MHz 保护成功 | 还要确认 secondary 20/40/80 MHz 上的 duplicate RTS/CTS 和 CCA/NAV 条件 |
| CTS 只在 primary 返回 | 接收方行为错误 | dynamic bandwidth 下可能只是确认 20 MHz 可用,后续应降宽或放弃 |
| RTS/CTS 后没有 DATA | AP 一定没收到 CTS | 还要查带宽语义、CCA/NAV、TX abort、抓包覆盖范围 |
| 开启 RTS/CTS 后吞吐下降 | RTS/CTS 无效 | 可能是保护收益小于控制帧 airtime 成本 |
| CTS-to-self 存在 | 等价于 RTS/CTS | CTS-to-self 保护范围偏发送方,不能覆盖所有隐藏节点 |
十一、现场记录模板
真要把问题排清楚,建议每次把这些信息记录下来:
BSS / 设备:
信道 / 带宽:
primary channel:
抓包设备覆盖带宽:20 / 40 / 80 / 160 MHz
RTS 类型:ordinary / dynamic duplicate / static duplicate / CTS-to-self
RTS rate:
CTS rate:
RTS.RA:
RTS.TA:
TA I/G bit:
RTS Duration:
CTS Duration:
CTS 覆盖子信道:
后续 DATA 带宽:
DATA/ACK 是否出现:
Retry / ACK miss:
设备日志:CTS timeout / TX abort / CCA busy / NAV / rate control
结论:
还缺的证据:
十二、来源与核验
本文按公开协议语义和可抓包验证的行为整理,不把无法追溯的经验当结论。
主要参考方向:
- IEEE Std 802.11:RTS/CTS control frame 格式、Duration/NAV、SIFS、RTS threshold、ERP/VHT/HE 相关 MAC/PHY 语义;
- Wireshark / radiotap 抓包字段:RA、TA、Duration、Retry、FCS、channel、rate、channel width、PPDU/PHY metadata;
- 设备侧日志:CTS timeout、TX abort、CCA busy、NAV、rate control、bandwidth decision;
- 实验约束:只监听 primary 20 MHz 的抓包,不能代表完整 40/80/160 MHz 行为。
最后总结
普通 RTS 里,把 TA 当发送方 MAC 没问题;但是这句话必须带条件。
在 VHT/HE dynamic bandwidth RTS 中,TA 可能是 bandwidth signaling TA。抓包看到 I/G bit 置 1 或者 TA 像组播地址时,不要直接判源 MAC 错了,要结合 PPDU 类型、带宽模式和后续 DATA 行为一起看。
RTS/CTS 排障的关键不是背字段,而是先分清场景,再看地址、Duration、时序、PHY metadata 和设备日志。这样结论才不容易跑偏。
回复 / 留言