一次在某栋办公楼里排查无线卡顿,二十几个人同时连着同一台 AP,视频会议一开就花屏。换信道、挪位置、加一台 AP,全都没压住。最后在空口上抓到一串重传帧,才发现问题根本不在信号强弱上——信号强度满格,但每个节点都在抢同一个发送机会,谁抢到算谁的,抢不到就退,退完再抢。这套把混乱变成秩序的东西就是 CSMA/CA,载波侦听多路访问/冲突避免。它是所有 Wi-Fi 网络 MAC 层的地基,也是很多人配置过几十台 AP、却从来没真正搞明白的一层。
这套机制的适用范围比多数人想的要宽。只要介质是"共享的、半双工的、听不到远端"的,就绕不开它:无线局域网、某些工业无线总线、电力线载波、甚至一些水下声通信的设计里,都能看到同一套思路的变体。这篇内容主要面向已经会配 AP、会看信号强度曲线,但对 MAC 层细节一知半解的运维和开发朋友;刚入门的同学也能看懂,我会尽量把每个参数为什么这么定讲清楚。下面从最容易被误解的那个问题开始。
1. 有线那套"边发边听"的做法,搬到射频上会直接失效
很多教材会把 CSMA/CD 和 CSMA/CA 摆在一起对比,一笔带过说"无线不能检测冲突所以改成避免"。这句话没错,但太浅了。真正动手调过无线的人需要知道的是:为什么不能检测,以及这个"不能"到底断绝了哪条路,因为后面所有的设计——帧间间隔、退避、RTS/CTS——都是被这个物理限制逼出来的。
1.1 冲突检测在射频介质上为什么物理不成立
有线以太网用双绞线,收发分离,一根线对发、一根线对收,理论上可以同时进行。而且共享同轴总线时代,每个站点发出去的信号会在总线上叠加,一旦有两个电平叠加,电压幅度会明显超出正常范围,检测到这个异常就说明撞了。这是"边发边听"能成立的物理基础。
射频介质完全不是这么回事。首先,绝大多数无线网卡是半双工的,用同一套射频前端收发,或者即便有独立收发通路,自己发射出去的信号在自己的天线上产生的功率,比从几米外传来的对端信号高出五六十个 dB。这相当于你在一个房间里大喊,然后想听清房间里另一个人是不是也在同时小声说话——自己嗓门盖住了一切。
其次,更关键的一点是:无线链路的冲突是在接收端发生的,不在发送端。A 和 C 两个节点互相听不见,但都在 B 的覆盖范围内。A 和 C 同时发给 B,这两路信号在 B 的天线上叠加,B 收到的帧 FCS 校验失败,这是一次冲突。但 A 这边呢?A 自己发得很顺,它的射频环境里没有任何异常,因为 C 的信号压根到不了 A。A 永远不知道刚才撞了。
注意:这一点直接决定了无线不能做"事后检测",只能做"事前规避"。所有 CSMA/CA 的设计都是从"假设我收不到冲突反馈"这个前提出发的。
1.2 三道闸门:物理侦听、虚拟侦听、随机退避
既然不能事后纠正,那就在发之前把撞的概率压到最低。CSMA/CA 实际上叠了三层判断,任何一层说"忙",都不许发。
第一层是物理载波侦听,也就是 CCA(Clear Channel Assessment)。网卡在发之前先听一段时间,看两个指标:一是能量检测,接收到的能量是否超过某个门限(这个门限通常随发射功率和噪声底动态调整);二是前导码检测,能不能解出合法的 PLCP 前导序列。能量检测会"误报"——微波炉、蓝牙、甚至隔壁的另一个网络,能量够高但不是本网络的信号,也会让它认为信道忙。前导码检测更准,但要等设备把前导解出来才知道,反应慢一点。实际实现里两个是配合用的。
第二层是虚拟载波侦听,靠帧头里的 Duration 字段设置 NAV。这个后面单独讲,它解决的是"我听不见那个节点,但我知道它要占用多久"的问题。
第三层是随机退避。就算信道空闲了,也不是立刻发,而是先抽一个随机数,再等这么多个时隙。这一层是整套机制的灵魂,因为它把"多个节点同时等到空闲"这个几乎必然发生的事件,转化成了一次概率上的分散。
2. 帧间间隔:几十微秒的等待,决定了谁有资格先开口
新手看 802.11 的参数表,最容易忽略的就是 SIFS、DIFS 这些时间值,觉得不过是些几十微秒的小数字。但这些数字之间的关系,恰恰是整优先级体系的骨架。差值只有十几微秒,作用却相当于给不同的帧贴了不同颜色的通行证。
2.1 ACK 凭什么能插所有人的队
一套完整的传输时序是这样的:发送方等 DIFS + 退避,确认信道空闲后发出数据帧;接收方收到后,等 SIFS 立刻回一个 ACK;其它节点在听到数据帧结束后,要等 DIFS 才能开始新一轮竞争。
关键在于 SIFS 比 DIFS 短。以 5GHz 的 OFDM 系统为例,SIFS 是 16 微秒,时隙是 9 微秒,DIFS = SIFS + 2×时隙 = 34 微秒。ACK 在数据帧结束 16 微秒后就发出来了,而旁边那些等着插队的节点要等到 34 微秒才能动。中间这 18 微秒的差距,就是一个"绝对优先窗口"。
这个设计不是偷懒。如果没有这个优先级,ACK 也要去竞争,那么在密集网络里 ACK 被推迟的概率会很高,发送方等不到 ACK 就会超时重传,重传又引发更多竞争,整个网络的效率会雪崩。给 ACK 一个独占的高优先级通道,本质上是把"确认"这个控制回路从数据通路的竞争里摘出来,保证闭环能及时收口。
同样用 SIFS 的还有几种帧:CTS、数据分片后的后续分片、Block ACK、以及 802.11ac 之后的各种响应类控制帧。它们共同的特点都是"必须紧跟在上一帧后面,否则整个握手就断了"。
各类 PHY 的时间参数对照如下,做时延分析或者算理论吞吐时会用到:
| PHY 类型 | 典型频段 | 时隙 | SIFS | DIFS |
|---|---|---|---|---|
| 802.11b (DSSS) | 2.4 GHz | 20 μs | 10 μs | 50 μs |
| 802.11g (ERP-OFDM) | 2.4 GHz | 9 μs / 20 μs | 10 μs | 28 μs / 50 μs |
| 802.11a/n/ac (OFDM) | 5 GHz | 9 μs | 16 μs | 34 μs |
| 802.11n/ac (2.4 GHz) | 2.4 GHz | 20 μs | 10 μs | 50 μs |
| 802.11ax (2.4 GHz) | 2.4 GHz | 13 μs | 16 μs | 42 μs |
单看 DIFS 34 微秒好像很小,但要知道一个 1500 字节的帧在 65 Mbps 下传输时间也就 185 微秒左右。DIFS 占了将近五分之一。高密度场景下,这些固定开销累积起来非常可观。
2.2 EIFS 与 AIFS:出错之后和分业务优先
除了 SIFS 和 DIFS,还有两个经常被忽略的间隔。
EIFS是在收到一个 FCS 校验失败的帧之后使用的。为什么要用更长的间隔?因为发出去的那一帧你解不出来,你不知道它是发给谁的、不知道它什么时候结束——万一它是发给你的,对端正在等你的 ACK 呢?为了让那个可能的 ACK 有机会发出去,你必须多等一段。EIFS 的长度一般是 SIFS + DIFS + 一个 ACK 的传输时间(按最低基础速率算),所以比 DIFS 长不少。
这个机制有个副作用:如果一个网络里有持续的干扰源,节点会频繁进入 EIFS 状态,信道利用率被进一步拉低。现场看到"信号很好但速率上不去",同时抓包发现有周期性 FCS 错误,基本就是这个情况。
AIFS是 802.11e 引入 QoS 之后的东西。它把原来统一的 DIFS 拆成了 AIFS[AC] + 退避,不同的接入类别(Access Category)用不同的 AIFSN 和 CWmin,形成分级:
| 接入类别 | 业务类型 | AIFSN | CWmin | CWmax |
|---|---|---|---|---|
| AC_VO | 语音 | 2 | 3 | 7 |
| AC_VI | 视频 | 2 | 7 | 15 |
| AC_BE | 尽力而为 | 3 | 15 | 1023 |
| AC_BK | 后台 | 7 | 15 | 1023 |
AIFS = SIFS + AIFSN × 时隙。语音的 AIFSN 是 2,视频也是 2,但语音的 CWmin 只有 3,意味着语音的退避窗口平均只有 1.5 个时隙,几乎每次都能抢到最前面。这就是为什么开着视频会议的时候,后台的软件更新会明显变慢——它不是被限速了,是根本抢不到空口。
提示:如果现场遇到语音质量差,先别急着换 AP。查一下是不是有设备把大量流量打进了 AC_VO。有些应用会把所有包都标成高优先级,结果把最该保护的队列给堵死了。
3. 退避计数器:一个随机数撑起了整张无线网的秩序
如果只有帧间间隔,那么当信道从忙变闲的瞬间,所有等待的节点会在同一个微秒同时开口,撞得一塌糊涂。随机退避就是在这中间插入的一段"错峰"。这部分是 CSMA/CA 里最值得深挖的,因为所有性能调优的参数,最后都落在这几个数字上。
3.1 竞争窗口为什么是"翻倍加一"而不是简单翻倍
节点要发帧,先从一个区间 [0, CW] 里均匀随机取一个整数,这个数就是退避时隙数。每过一个空闲时隙减一,减到零就可以发。
初始的 CW 就是 CWmin。如果这一轮撞了(没收到 ACK),CW 按CW ← 2 × CW + 1更新,再重新抽。比如 CWmin 是 15,撞一次变成 31,再撞变成 63,一直到 CWmax(通常是 1023)封顶。成功收到 ACK 之后,CW 复位回 CWmin。
为什么是"乘二加一"而不是直接乘二?因为这样得到的序列是 15、31、63、127、255、511、1023,全是 2ⁿ − 1 的形式,对应的槽数就是 16、32、64、128……正好是 2 的整数次幂。硬件里随机数发生器只要输出 n 位二进制数就能直接映射到 [0, 2ⁿ−1],不需要做取模运算,省资源也省时间。这种"形式服从实现"的细节,标准里到处都是。
CW 复位时机其实是有讲究的。标准允许"成功传输后复位到 CWmin",但如果一个节点一旦成功就一直成功,它会一直用最小的窗口,越抢越快,把其它节点饿死——这就是所谓的捕获效应。在节点数不多的家用场景里这不是问题,但在几十个终端的企业场景下,会让空口时间分布极度不均。有些实现会做"慢速衰减",不那么激进地复位,这是驱动层的实现差异,同一个标准下不同设备的表现可能差很多。
3.2 冻结而不是重抽:这个设计救了低优先级节点
真正体现设计功力的地方在"冻结"机制。当一个节点正在倒计数,突然侦听到信道忙了,它不会把剩余值丢掉重抽,而是把这个数字记下来,等信道再次空闲并经过 DIFS 之后,从上次的剩余值继续往下减。
如果每次被打断都重抽,会出现什么后果?想象一个场景:A 抽到了 100,倒了 50 步被 B 打断;重抽之后又抽到 90,倒到 20 又被 C 打断;再重抽又抽到 80……理论上它可以永远抽到大数,永远发不出去。冻结机制保证了每个节点的退避进度是单调推进的,只要信道最终空出足够长的时间,每个节点都必然能发出去。这是一个公平性的下限保证。
但冻结也有副作用。一个已经倒到只剩 1 步的节点,它在下一次 DIFS 之后立刻就能发;而一个刚抽到 15 的节点要等 15 个时隙。所以在实际空口上,你会看到某些节点连续抢到多次发送机会,而另一些节点长期排队。这不是设备故障,是这套机制的固有行为。
3.3 用一段代码把退避过程跑出来
光看公式不够直观,我写了一段简化模拟,把 n 个节点竞争同一信道的过程跑一遍,统计首轮碰撞率和平均空闲等待。这段代码忽略了传输时间、只算竞争阶段,但对理解窗口大小的影响足够了。
import random import statistics SLOT = 9e-6 # 5GHz OFDM 时隙 CWMIN = 15 CWMAX = 1023 def pick_backoff(cw): """从 [0, cw] 均匀取一个时隙数""" return random.randint(0, cw) def simulate(n_nodes, rounds=20000): cw = {i: CWMIN for i in range(n_nodes)} collisions = 0 wait_slots = [] for _ in range(rounds): bo = {i: pick_backoff(cw[i]) for i in range(n_nodes)} min_val = min(bo.values()) winners = [i for i, v in bo.items() if v == min_val] wait_slots.append(min_val) if len(winners) > 1: # 撞了:所有参与者窗口翻倍 collisions += 1 for i in winners: cw[i] = min(2 * cw[i] + 1, CWMAX) else: # 成功:窗口复位 cw[winners[0]] = CWMIN return collisions / rounds, statistics.mean(wait_slots) for n in (2, 3, 5, 8, 10, 20): rate, avg_wait = simulate(n) print(f"节点数={n:2d} 首轮碰撞率={rate:.3f} 平均等待={avg_wait:.2f} 时隙 " f"({avg_wait * SLOT * 1e6:.1f} us)")我这边跑出来的大致趋势是这样的:两个节点时碰撞率在 6% 上下,五个节点升到 15% 左右,十个节点超过三成,二十个节点已经接近六成。平均等待时隙数倒是一直在 2 到 3 之间——因为只要不撞,最小值总是偏小的。
这组数字说明一个很实际的问题:CWmin 是固定值,节点数一多,碰撞率是指数级上涨的。这也是为什么 802.11ax 引入了 OFDMA 和更细的调度机制——单纯靠加大窗口来降碰撞,代价是平均等待变长,吞吐反而下降。加大窗口只适合"节点多但流量稀疏"的场景,节点多且流量密集时,唯一的出路是减少竞争者的数量,比如多开 AP 分载、限制低速率客户端接入、或者干脆上带调度的方案。
提示:这段代码里的碰撞判定只看"最小值是否唯一"。真实系统里还有捕获效应——如果两个节点的信号强度差 10 dB 以上,强信号那一路可能在接收端仍然能被正确解出,弱的那路才算撞。所以实际碰撞率会比这个模拟低一些,但趋势是一致的。
4. 隐藏终端不是玄学:几何关系与 RTS/CTS 的取舍
聊 CSMA/CA 绕不开隐藏终端,但很多资料把它讲成了一种偶发的、需要特殊条件才触发的异常。实际上在真实的建筑环境里,隔一堵承重墙、绕一个拐角,隐藏关系就成立了,它是常态而不是特例。
4.1 隐藏与暴露:同一枚硬币的两面
隐藏终端的场景很经典:A 和 C 都在 B 的覆盖范围内,但 A 和 C 之间隔得太远互相听不见。A 侦听信道,听不到 C 在发,以为空闲,于是开火;C 也一样。两路信号在 B 处叠加,B 解不出来,A 和 C 都得重传。
这个问题在开放式办公区特别容易发生。中间放一台 AP,两头的工位各自能连上,但两头之间隔了十几米加两道玻璃隔断,互相听不到。于是两边的上行流量频繁互撞,而每个人看自己的信号强度都是满格。
还有一个更容易被忽略的问题叫暴露终端。C 听到了 B 正在发送,于是判断信道忙,不敢发。但 C 其实是想发给 D,C→D 和 B→A 在空间上完全不重叠,本来可以并行。结果 C 白白等着,空口利用率被浪费掉了。
这两种情况的区别很重要:RTS/CTS 只能解决隐藏终端,解决不了暴露终端。有些人看到网络慢就开 RTS,结果在某些拓扑下反而更慢,就是因为场景判断错了。
4.2 NAV 是怎么把"听不见"变成"知道"的
虚拟载波侦听的思路很巧妙:既然我听不到那个远处的节点,那我就让能听到它的人告诉我。
每一帧的 MAC 头里有个 Duration 字段,发送方在这里填入"本次传输还需要占用信道多久",包括数据帧本身、后面的 SIFS、以及 ACK 的时间。任何一个收到这一帧的节点,不管这帧是不是发给自己的,都要把这个值读出来,维护一个叫 NAV 的倒计时器。NAV 大于零期间,物理层就算报告空闲,MAC 层也认为信道忙,不许发起竞争。
这就把"物理上能不能听到"和"逻辑上知不知道有人在用"解耦了。A 听不到 C,但 A 能听到 B,B 在给 C 回 ACK 或者转发的时候会把 Duration 带出来,A 通过 B 的中转知道 C 还要占多久。
RTS/CTS 是把这个机制用得更彻底:A 想发一个大帧,先发一个短的 RTS(20 字节),B 收到后回一个 CTS(14 字节),CTS 里同样带 Duration。所有能听到 B 的节点(包括 A 听不到的 C)都会读到这个 CTS,把自己的 NAV 设上,在接下来的整个数据传输期间闭嘴。冲突被转移到了 RTS 阶段,而 RTS 很短,撞了损失也小。
4.3 RTS 门限:为什么大多数场景应该直接关掉
RTS 听起来很美好,但代价不小。一次 RTS/CTS 握手要消耗:RTS 帧传输时间 + SIFS + CTS 帧传输时间 + SIFS。这两帧都是控制帧,按规定用最低基础速率发(通常是 6 Mbps 或者更低),所以 34 字节加上前导和开销,实际占用空口大约 100 到 200 微秒。
对比一下,一个 1500 字节的数据帧在 300 Mbps 下只要 40 微秒。握手开销比数据传输本身还长四倍。如果每个小包都走 RTS/CTS,吞吐直接掉一大截。
所以设备上都有个RTS Threshold参数,帧长超过这个值才启用 RTS。默认值常见是 2347(等于最大帧长),意思就是"关闭"。这个默认值其实是合理的——在大多数室内场景,隐藏终端问题不严重,握手开销反而更亏。
真正该打开 RTS 的场景有这么几类:
| 场景 | 建议 | 原因 |
|---|---|---|
| 室外点对点桥接 | 开启,门限设 500 左右 | 距离远,隐藏关系必然存在,大帧传输时间长 |
| 大型仓库/厂房 | 开启,门限 1000 左右 | 货架遮挡严重,且经常有移动终端 |
| 高密度会议室 | 谨慎,先测再开 | 节点多,RTS 本身也会互相撞 |
| 普通办公室 | 关闭 | 隐藏关系少,握手开销不划算 |
| 家庭环境 | 关闭 | 节点少,几乎不会有隐藏终端 |
门限的定法有个粗略的算法:让 RTS 的握手时间小于一次碰撞重传的期望损失。假设碰撞后重传一个 1500 字节帧的代价是 T_retry,握手开销是 T_rts,碰撞概率是 p,那么当p × T_retry > T_rts时开 RTS 才划算。现场估 p 最直接的办法是抓包看重传率,超过 15% 就值得考虑。
注意:有些设备把 RTS Threshold 设成 0 表示"全部启用",不是"全部关闭",不同厂商的实现不一样。改之前一定查清楚。
5. 空口抓包:把教科书上的参数在时间轴上看一遍
理论讲再多,不如自己在时间轴上看到一次 SIFS 和 DIFS 的实际间隔。我第一次抓到完整的 Data–SIFS–ACK 序列时,之前看过的那些数字才真正落地。这一节讲具体怎么抓、怎么看。
5.1 环境准备与抓包姿势
普通模式下网卡只会把发给自己的帧交给上层,看不到空口上其他人的交互。必须切到监听模式,让网卡把空中所有能解出来的帧都吐上来。
# 停掉可能抢占网卡的管理进程,然后切监听模式 sudo airmon-ng check kill sudo airmon-ng start wlan0 # 用 tshark 抓,只保留管理帧、控制帧和数据帧的头部 sudo tshark -i wlan0mon \ -f "wlan" \ -w cap.pcapng抓的时候有个坑要注意:不同网卡在监听模式下能提供的 radiotap 信息差异很大。有些网卡不提供每帧的精确时间戳和信道能量,抓出来的数据没法做微秒级的时间差分析。选网卡时优先选那些 radiotap 头信息完整的型号,抓之前先用tshark -I看一眼支持哪些字段。
5.2 从时间戳读出 DIFS 和退避
抓完之后,用显示过滤器把一次完整的交互拎出来:
# 只看 RTS / CTS / ACK / Data 这几种类型 tshark -r cap.pcapng \ -Y "wlan.fc.type_subtype in {0x1b, 0x1c, 0x1d, 0x20, 0x29}" \ -T fields \ -e frame.number \ -e frame.time_relative \ -e wlan.fc.type_subtype \ -e wlan.duration \ -e wlan.fc.retry \ -e radiotap.dbm_antsignal \ -E header=y -E separator=,读出来的表格大概长这样(数值是我在一次实测里摘的,5GHz、802.11ac):
| 帧号 | 相对时间 (s) | 类型 | Duration | Retry | 信号 (dBm) |
|---|---|---|---|---|---|
| 1042 | 0.000000 | Data | 44 | 0 | -52 |
| 1043 | 0.000016 | ACK | 0 | 0 | -58 |
| 1044 | 0.000118 | Data | 44 | 0 | -51 |
第二行时间差 16 微秒,正好是 SIFS,这就是 ACK 插队的证据。第三行和第一行差了 118 微秒,扣掉数据帧本身的传输时间,剩下的就是 DIFS 加上若干个时隙的退避。如果连续抓几十个这样的间隔,你会发现它们的分布不是均匀的——小的间隔出现频率明显更高,这正是随机退避从 [0, CW] 均匀取值后取最小值的统计特征。
5.3 用重传位统计真实的空口健康度
wlan.fc.retry这个字段是判断空口质量最直接的指标。它标记这一帧是不是重传。统计一下重传帧占总数据帧的比例:
tshark -r cap.pcapng -Y "wlan.fc.type_subtype == 0x20" \ -T fields -e wlan.fc.retry | sort | uniq -c如果重传率超过 10%,说明空口竞争或者干扰已经到了影响体验的程度;超过 20% 基本可以确定用户体验会明显下降。这个数字比信号强度有用得多——我见过信号 -45 dBm 但重传率 35% 的网络,原因就是同一信道上有三个 AP 各自带着十几个客户端在抢。
还有一个配合看的指标是帧的速率。如果一个客户端大量使用低速率(比如 6 Mbps)发管理帧和广播帧,它会长时间占用空口,把所有高速率客户端一起拖慢。用wlan_radio.data_rate字段可以统计速率分布,禁用最低几个速率往往能立竿见影地改善密集场景的表现。
6. 现场调优:哪些参数能动,哪些动了容易出事
理解了机制,最后落到实操。这部分是我这些年踩坑攒下来的,有些结论跟直觉是反的。
6.1 高密度场景的瓶颈从来不是信号,是空口时间
新手排查无线问题的第一反应是看信号强度,一看到 -70 dBm 就想着加 AP 或者调功率。但在会议室、报告厅、开放办公区这种场景里,信号通常都够,瓶颈在空口的时间分配上。
空口是一个时分共享的资源,任何一帧的传输都在消耗它,包括你看不见的那些:每秒十个的 Beacon(每个 AP 都在发,不管有没有客户端)、客户端定时发的 Probe Request、ARP 广播、组播视频流(按最低速率发,占用的时间是大速率的几十倍)、以及各种管理帧。
一个直观的估算:一个 1500 字节的广播帧在 6 Mbps 下传输要 2 毫秒,在 300 Mbps 下只要 40 微秒。差了 50 倍。如果一个网络里有大量广播流量,光这一项就能吃掉一半空口。所以做优化的优先级应该是:先减少不必要的广播和组播、禁用低速率、开启组播转单播,再考虑加 AP。
6.2 发射功率调高反而更糟这件事
这是最反直觉的一条。很多人觉得信号弱就把 AP 功率拉满,结果整层楼的客户端都倾向于连到这一台,其它 AP 空着,负载严重不均。更糟的是,功率调高之后,这台 AP 能"听"到更远范围内的其它信号,CCA 判定信道忙的概率上升,它自己反而更抢不到发送机会。
正确的做法往往是降低功率。把 2.4G 的功率压到 10 dBm 左右,让覆盖范围收缩到刚好够用,客户端被迫分散到不同的 AP 上,每台 AP 带的人少了,竞争自然就轻了。这个思路在密集部署里几乎是标准做法,但每次跟人解释都要费一番口舌。
同样逻辑,2.4G 频段尽量只留 1、6、11 三个信道,每个信道上的 AP 数控制在两三个以内。5G 信道多,但也别把所有 AP 都堆在低频段的那几个信道上。
6.3 一张表说清哪些参数值得动
| 参数 | 作用 | 调整建议 | 风险 |
|---|---|---|---|
| CWmin | 决定初始退避窗口 | 高密度场景可适度调大 | 平均等待变长,小包延迟上升 |
| RTS Threshold | 是否启用握手 | 按场景,默认关闭 | 开错场景反而降速 |
| 基础速率集 | 管理帧、控制帧用的速率 | 禁用 1/2/5.5/11 Mbps | 老设备可能连不上 |
| Beacon 间隔 | 信标发送周期 | 100 TU 为标准,可保持 | 调大影响快速漫游 |
| 分片门限 | 大帧是否分片 | 基本不用调,保持最大 | 分片增加开销 |
| 发射功率 | 覆盖范围 | 密集场景适度降低 | 降太多导致边缘掉线 |
| 信道带宽 | 20/40/80/160 MHz | 高密度用 20 或 40 | 带宽越宽,可用信道越少 |
调这些参数有个基本原则:一次只改一个,改完至少观察半小时。无线环境本身波动很大,改了立刻测出来的结果经常是噪声。而且一定要有基线——改之前先抓一段包统计重传率和速率分布,否则改完了根本不知道是好是坏。
6.4 几个我踩过的坑
第一个坑是把 CWmin 调小想提速度。理论上一开始就抽小窗口,抢到信道的概率高,延迟低。实际在二十几个客户端的场景下,碰撞率直接翻倍,重传把省下来的时间全吃回去了,吞吐反而降了 20%。
第二个坑是迷信"关闭 RTS 一定更好"。有一次在一个长条形厂房里,默认配置下远端两个工位的上行速率只有 1 Mbps,开了 RTS(门限 500)之后回到了 60 Mbps。原因是那两端中间隔了一台大型设备,互相完全听不见,隐藏终端问题非常严重。这个案例告诉我,默认值是给通用场景的,具体问题还得具体抓包看。
第三个坑是忽略了自己抓包时引入的干扰。监听模式的网卡本身也在发射(有些驱动在切信道时会有射频活动),加上抓包设备放在 AP 旁边,抓出来的数据里混进了近场信号,干扰判断。后来我把抓包设备放到离 AP 三米以外的地方,数据才干净。
7. 一点个人体会
CSMA/CA 这套机制最值得琢磨的地方,是它用了一堆看起来很笨的办法——等一等、抽个随机数、听不见就让别人替你说——却撑起了全球最普遍的无线接入。它的设计哲学不是把冲突消灭掉,而是承认冲突必然存在,然后让冲突的代价可控。碰撞一次就翻倍窗口,成功了就复位,这套简单的反馈回路在节点数不多的时候表现极好,节点一多就顶不住,于是后人加了 QoS 分级、加了帧聚合、加了 OFDMA 调度。
排查无线问题这些年,我最大的收获是:先看空口,再看信号。把重传率、速率分布、帧间隔这三个东西抓出来看一遍,八成的问题当场就能定位。信号强度那根柱子,反而是最没用的一个指标。