客户反馈的故障现象:
某大楼内,有 1 台 MacBook 在信号强度很好的情况下,经常会协商到很低的速率,速度很慢,严重时无法打开网页或发送邮件。该 MacBook 在其他地方(家里或者出差)上网正常。大楼内没有其他用户有类似的投诉。
初步分析:
客户的主诉存在 2 个问题:“协商”和“速率”。
首先,在无线网卡上观察到的“速率”虽然叫做 Data Rate,但实际上是空口带宽。真正的传输速率会受到半双工以及 CSMA/DA 机制的影响,会下降很多。但这不重要,另外一个问题才是关键:Data Rate 其实不是“协商”出来的。
AP 和 STA 会通过 Beacon frame 广播自己所支持的 MCS Set 和帧间隔,然后 会根据自己所接收到的对方的信号强度和 SNR(注意信号传递的方向),自行选择一个最高的 Data Rate。

然后,AP 或者 STA 就会以这个比较高的 Data Rate 发送 QoS Data frame,如果顺利收到 ACK,并且 SNR 没有变化,则继续沿用这个 Data Rate。只有在发生连续的丢包,需要重传 Data frame 的时候,才会向下依次调整 MCS,依次减小 Data Rate。
这个选择 Data Rate 的机制和 TCP 的慢启动机制是相反的。
这种机制会产生一个问题:非对称传输,进而会影响到无线网络的数据传输性能和 STA 的漫游。
通常 AP 的最大发射功率会比较高,在 5GHz 有 23dBm。而无线移动终端的发射功率通常较低,比如 iPhone5 在 UNII-3 信道的发射功率只有 10dBm,是 AP 发射功率的 1/20。所以有时候,STA 侧,观察到信号还是满格的,所以会继续关联在这台 AP 上,并且以较高的 Data Rate 发送 frames。但是在 AP 侧收到的 STA 的信号已经很弱了,无法以较高的 Data Rate 接收 STA 的 frames,所以会发生丢包,并且在重传的过程中降低 Data Rate。

此时,AP 应该将 STA 踢掉,强制 STA reassociation,强制 STA 漫游。那么客户遇到的问题是非对称传输导致的吗?是否是漫游粘滞?
Troubleshooting过程中观察到的故障现象:

分析空口抓包,可以看到确实发生了大量的重传。RTS-->CTS-->QoS Data-->RTS...(no ACK)...
但这个重传并不是非对称传输导致的,因为 STA 的 RSSI 很高。在现场也观察到 STA 确实关联到了最近的 AP。
重传也不是干扰导致的。如果是干扰导致重传,应该所有的 STA 都会受到影响,而不仅仅是这 1 台 MacBook 有问题。事实上,信道利用率并不算高,AP 的并发用户数也不多,在空口抓包时并没有对 MAC 地址做过滤,但抓到的 MAC 却比较少。
不过在重传的过程中,确实如预期的一样在降速。

在重传了十几次之后,AP 给 STA 发送了一个 Block ACK,通知 STA 它已经收到了 SN=1846 和 1847 的 QoS Data frame:

有的时候,STA 在多次重传之后,会发送一个 Block ACK Request。但是奇怪的是,Starting Sequence Number 是错的,数字多了 1 个。比如下面的截图,重传的 Data frame SN=1777,但是 STA 所发出的 BA Req 却将 Starting Sequence Number 设置成了 1778。

然后 AP 回复一个 BA 告诉 STA 它没有收到 SN=1778 的 frame:

STA 要么不发 BAR,如果发了 BAR,Starting SN 都不对。
我们再来看看一个正常的 BA 过程应该是怎样的:

上面是 AP 向 STA 发送 QoS Data frames 的抓包截图。首先,AP 连续发送了多个 Data frame;其次,没有 BA Request;最后,关键的一点,Starting Sequence Number 肯定与 Transmitter 所发送的第 1 个 Data frame SN 相同。在上面的截图中可以看到,AP 本次发送的第 1 个 QoS Data SN=3330,所以 BA Starting SN 也是 3330。
因此可以判断 STA 所发出来的 BA Request 有问题,Starting Sequence Number 都有异常。但是过滤之后发现也有其他的 STA 曾发送过 BAR,而且 Starting Sequence Number 也不正常。
继续观察,发现所有 STA,以及 AP,它们发出来的所有 Data frame 所携带的 QoS Control,都将 ACK Policy 设置成了 Normal ACK:

但所有的 Data frame,又都是 A-MPDU 的一部分:

怎么回事?乱套了?如果真的是乱套了,为什么 AP 和其他 STA 都能正常 BA,只有这台 MacBook 有问题呢?
Block ACK 机制:

BA 机制分为 3 个主要的过程:协商过程,传输过程,以及终止过程。在这个 Case 中,STA 有发出过 ADDBA Request:

AP 也回复了 ADDBA Response:

在接下来的数据传输过程就不太正常了。BlockAckReq 要么没有,要么其所携带的 Starting SN 有些不对。ACK Policy 又都是 Normal ACK,而不是 Block ACK。如果 Receiver 看到了 Normal ACK,就应该立即回应一个普通的 ACK。但显然 AP 并没有立即回复普通的 ACK 给 MacBook。
但其他 STA,包括 AP 在内,也都将 ACK Policy 设置成了 Normal ACK 啊!还是那句话,同样的条件下,为什么其他 STA 都能正常 BA,只有这 1 台 MacBook 不能正常 BA 呢?
这说明 Normal ACK 是符合 BA 机制的,“异常的” Starting SN 应该也是正常的。
原来从 802.11n 开始,为了提升传输性能,对 MAC 层的传输机制做了一些改变:增加了 Aggregate MPDU,通过将多个 MPDU 聚合在一起,减少 MPDU 前导码和 Header 所造成的开销。另外一个重要的改变是 Implicit BAR 机制。
传统的 802.11e 所定义的 Block ACK 机制要求 Transmitter 在发送完最后一个 Data frame 之后,需要发送一个 BAR 给 Receiver,然后 Receiver 会回应一个 BA。如果没有正常出现 BAR 或者 BA,BA 机制就会被 Tear Down。在这种传统的 BA 机制中,BAR 就会造成额外的开销。
802.11n 引入了隐性 BAR 机制,将所有的 Data frame 的 ACK Policy 都设置成 “Normal ACK”。Receiver 看到 Normal ACK 之后就相当于看到了 BAR,然后就会回应 BA,而不再需要等待 Transmitter 发送 BAR frame。
所以从 802.11n 开始,一个正常的完整的 BA 传输过程就是下面这样:

这又引出一个问题:既然所有的 Data frame 都是 Normal ACK,Receiver 应该怎样确定它所收到的 Data frame 是最后一个 Data?
我没有找到这样的资料,但是经过对比 AP 和其他正常的 STA 所发出的 最后一个 Data frame 和其他 Data frame,我发现在 Payload 字段长度相同的情况下,最后一个 Data frame 的长度多了 4 个字节 —— 只有最后一个 Data frame 携带了 SSI Signal:

但如果只是通过这个 SSI Signal 的字段,来判断是否是最后一个 Data frame,我觉得应该不符合程序员的思维方式。所以我又发现了最后一个 Data frame 做具备的另外一个特点:

最后一个 Data frame,除了携带 RSSI 之外,A-MPDU flags 的值是 0x0000,Last subframe of this A-MPDU is known: False。
而在前面的那些 Data frame,A-MPDU flags 的值是 0x0004,Last subframe of this A-MPDU is known: True。
Implicit BAR 并不意味着完全不需要 BAR 了。当 Transmitter 需要重置 Data frame 的 Sequence Number 时,就发送一个 BAR,其所携带的 Starting Sequence Number 就是 Transmitter 接下来所要使用的 SN。这也解释了为什么 MacBook 所发送的 BAR 有问题。
结论:
现在我们回过头来再去观察故障 MacBook 所发出的 Data frame。从 MacBook 的行为可以看出来,它在发送 Data frame 之后,它在等待 BA 却没有收到,所以才会重传。使用 wlan.fc.type eq 2 过滤这台 MacBook 的 Data frame,发现几乎所有的 Data frame 都将 A-MPDU flags 设置成了 0x0000 —— 它确实表明了自己是最后一个 Data frame。但换句话说,这台 MacBook 也几乎没有尝试去使用块传输。
另外一个特征是,绝大多数的 Data frame 长度都很小。
当然,严格地讲,这两个特征也算不上异常,是因是果很难说的清楚。但有时候 Data frame 虽然把 A-MPDU flags 设置为 0x0000,却没有携带 RSSI。这就不正常了。

考虑到上万台 STA 只有这 1 台 MacBook 间歇性地传输异常,所以只能得出一个没有可靠证据支撑的,令人丧气的结论:问题出在 MacBook 上面。之前也曾出现过同样的用户投诉,最后找不到原因就更换了 MacBook 的主板(为了换网卡)。到现在为止几个月了一直使用正常。
另外也很难解释为什么这台 MacBook 在家里或者出差在外就没有问题。不过我发现了另外一个有些类似的 Case,STA 是一台三星手机,重传的方向相反,是 AP 向 STA 发送 Data frame 一直重传。这台三星手机在其他地方也都使用正常。至于最后的结论嘛,自己去看吧:
https://github.com/iwaxx/blog/issues/5
如果您对这个 Case 有什么看法,欢迎留言或私信给我。




