ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

A-MSDU与A-MPDU详解:Wi-Fi帧聚合如何决定无线吞吐上限

A-MSDU与A-MPDU详解:Wi-Fi帧聚合如何决定无线吞吐上限 做无线性能优化或者排查 Wi-Fi 吞吐问题时A-MSDU 和 A-MPDU 这两个词基本绕不开。不管你是做网卡驱动、路由器固件还是写产品测试用例只要想弄明白“为什么 Wi-Fi 实际速度总是到不了空口速率”最终都会撞到这两种帧聚合机制。我之前也经常把这两个缩写搞混后来专门花时间翻协议、抓空口报文、对比不同芯片厂商的行为才算把整个链路理清楚。这篇文章就是一份整理笔记把我认为最核心、最容易踩坑的地方讲明白适合做无线协议开发、WLAN 嵌入式调试以及想深入理解 Wi-Fi 性能为什么上不去的朋友直接参考。1. 为什么帧聚合能让无线吞吐提升几个档次很多测试报告里写“连接速率 866Mbps”但实际 TCP 下载带宽只有 400Mbps 上下新手容易以为是信号问题或者测试环境有干扰其实更大概率是帧聚合没有生效或者聚合深度不够。在 802.11 协议里每一次空口传输都要付出大量固定开销这些开销不会因为你传的包小就打折帧聚合的意义就是把这些固定成本摊到尽可能多的数据上。1.1 每个无线帧背后都要付出那么多固定开销先看一个最普通的 802.11 数据帧传输过程。发送端要先等信道空闲经过 DIFS/AIFS 和随机退避才能开始发数据。这个退避时间在竞争激烈的时候可能长达几百微秒它跟你要传的数据大小几乎没有关系。接着发送端要加物理层前缀也就是前导码和 PLCP 头802.11n 之后还分 L-LTF、HT-LTF 这些训练序列。这些物理层内容虽然不属于 MAC 帧但它占用的空中时间非常可观动辄十几二十微秒。然后才是真正的 MAC 帧数据传完之后接收端还要回一个 ACKACK 本身也要等 SIFS、加前导码又得几十微秒。把这些加起来你会发现一个 1500 字节的数据帧真正花在 MAC 载荷上的时间可能只占整个传输时间的一半左右另一半全被前导、退避、ACK、帧间隔这些“路费”吃掉了。如果是 100 字节的小包比如 VoIP 语音包或者游戏心跳包那数据载荷占比更低可能 80% 以上的时间都耗在固定开销上效率惨不忍睹。帧聚合的思路特别直白既然每次传数据都要付一次“路费”那能不能把很多个数据包塞进同一趟运输里让路费只付一次在 802.11n 开始引入的 A-MSDU 和 A-MPDU就是干这件事的两种不同方案。理解这一点后面看协议细节就不会晕。1.2 单帧发送的浪费到底有多大我用一个比较粗糙但直观的估算来说明。假设环境里一个 1500 字节的帧从开始竞争信道到收完 ACK总共占用大约 250 到 300 微秒的空中时间。其中 MAC 数据载荷本身按常见 MCS 速率算可能只需要 100 多微秒其余全是固定开销。如果能把 8 个这样的以太网帧合成一次发送数据部分变成 12000 字节但前导、退避、ACK 这些固定开销不会同比例增加整体传输时间可能只要原来的三到四倍。折合下来每一帧的平均成本大幅下降有效吞吐自然就上去了。这也是为什么 802.11ac/ax 要把聚合长度做得越来越大因为物理层速率越高固定开销的占比越夸张不聚合就完全跑不出应有的带宽。理解了这层背景接下来单独看 A-MSDU 和 A-MPDU 就会很顺。2. A-MSDU在 MAC 层“并包”的高效玩法A-MSDU 全称是 Aggregated MSDU也就是把多个 MSDU 聚合成一个 MPDU。先明确一个概念对绝大多数普通用户和设备来说MSDU 可以近似理解成一个以太网帧或者说一个完整的 IP 包及其链路层头。A-MSDU 做的事情是把本来要分别封装成多个 802.11 数据帧的内容合并到一个帧体里只占用一套 MAC 头和一个 FCS。2.1 A-MSDU 到底怎么组包一个 A-MSDU 的结构可以看成若干个子帧按顺序拼在一起。每个子帧由三部分组成6 字节目的地址 DA、6 字节源地址 SA、2 字节长度字段后面跟着实际数据载荷。这个子帧头跟以太网帧头非常像只是把以太网类型字段换成了长度字段因为真正区分上层协议的字段会在每个 MSDU 内部保留。为了保证接收方能按 4 字节边界去解析每个子帧在数据后面需要补 Pad也就是填充字节。最后一个子帧是否填充标准里没有强制不同厂商实现会有差异。抓包的时候你会在一个 A-MSDU 帧里看到多个 DA/SA/长度组合每个组合后面都跟着一段报文这就是典型的“大包裹里套小包”。这些 MSDU 在进入无线链路之前就被合并成了一个 MPDU因此整个包只有一个 802.11 MAC 头只有一个序列号也只有一个 FCS 校验值。接收方收到后在 MAC 层完成校验然后把子帧依次剥离出来还原成多个 MSDU 交给上层协议栈或者桥接转发。2.2 长度上限、填充和加密兼容性A-MSDU 的长度不是无限制的协议里对不同模式给出过明确约束。802.11n 早期设备常见的是 3839 字节上限能力协商里如果支持“Max A-MSDU 7935”就可以用到 7935 字节到了 802.11ac 时代VHT 设备基本强制要求支持 7935 字节。这个上限叫 Max A-MSDU length它决定了单个 MPDU 里最多能装多少 MSDU 数据。我经常在实测里看到一个 7935 字节的 A-MSDU如果上层是 1500 字节的以太网帧最多也只能塞 5 个因为 5 个 1500 字节已经是 7500 字节加上子帧头和填充就逼近上限。如果 MTU 改成 9000 字节的巨型帧那 A-MSDU 能装的子帧数量就更少。还有一个非常重要但容易被忽略的问题加密兼容性。A-MSDU 的合并发生在 MSDU 层次一个 MPDU 里包含的多个 MSDU 在加密时会当成一个整体来处理。标准里明确不推荐甚至禁止在 TKIP/WEP 这类老式安全协议下使用 A-MSDU因为 TKIP 的 MIC 校验和 ICV 机制在子帧粒度上无法有效工作。实践中一般只有 WPA2/WPA3 的 AES-CCMP/GCMP 模式才能放心开启 A-MSDU遇到老式 AP 或终端很多时候聚合会悄悄降级成单独发送。2.3 什么时候适合用 A-MSDUA-MSDU 的优点很明显减少 MAC 头数量减少 FCS 数量也减少了上层的包数量在高吞吐、低干扰、信号质量好的场景里效率非常高。很多 TCP 下载场景吞吐上不去往往就是 A-MSDU 没开或者长度限制太小。但它也有明显的“软肋”一个 MPDU 里的任意一个子帧出错整个 A-MSDU 都会被 FCS 校验拒绝接收方没法只要求重传其中某一个子帧。这意味着信道质量差、重传较多的时候A-MSDU 会把错误放大一个比特错了五个包一起重来。所以我在环境干扰较大的项目里反而会建议适当减小 A-MSDU 上限或者干脆用 A-MPDU 来替代道理就在这。3. A-MPDU把完整数据帧串成一条超长流水线A-MPDU 全称是 Aggregated MPDU跟 A-MSDU 思路完全不同。它不是在 MPDU 内部合并多个 MSDU而是把多个完整的 MPDU 串在一起装进同一个 PPDU 里发送。每一个 MPDU 仍然是独立的数据单元有自己的 MAC 头、自己的 FCS甚至自己的序列号。3.1 A-MPDU 的组成和传输单元A-MPDU 的基本单元叫 A-MPDU Subframe结构是4 字节 MPDU Delimiter 加一个完整 MPDU再根据对齐要求补 Pad。MPDU Delimiter 里包含了 MPDU 长度、CRC 等信息关键作用是让接收方在解析流式数据的时候能准确找到每个 MPDU 的边界。因为每个 MPDU 都带着独立 FCS接收端可以单独判断哪一个 MPDU 对、哪一个错。这意味着发送端不需要因为一个坏包就把整包数据全部重传它可以只把那些接收失败的 MPDU 找出来重新发送。这一点的实战价值极大尤其在高密度、多干扰的真实网络里。长度方面802.11n 的 A-MPDU 最大可以达到 65535 字节约 64KB802.11ac 把上限进一步提升到 1048575 字节差不多 1MB802.11ax 延续了毫秒级长包的设计理念在特定参数配置下可以做到接近 1MB 的聚合长度。相比 A-MSDU 的那几 KB 上限A-MPDU 的吞吐潜力明显更大。3.2 Block Ack 机制是 A-MPDU 的灵魂A-MPDU 能工作离不开 802.11n 引入的 Block Ack 机制。如果接收端每个 MPDU 都单独回一个 ACK那聚合就失去意义了因为 ACK 这部分的固定开销又会回来。所以协议定为发送端一次性发送多个 MPDU接收端收到后通过 Block Ack 帧统一回复确认消息。Block Ack 里有一个起始序列号和一个位图位图的每一位对应一个 MPDU 的接收状态。比较常见的 64 位位图可以覆盖 64 个 MPDU也就是说发送端最多可以一次发 64 个 MPDU 而不用等 ACK。到了 802.11ax 时代Block Ack 还能扩展到 256 位覆盖更多 MPDU进一步提高链路利用率。这个机制我习惯比喻成“批量签收”快递员一次送十个包裹收货人收完以后在一张清单上勾选哪些收到、哪些破损快递员下次只补送破损的。A-MSDU 相当于把十个包裹捆成一个超级大盒子一旦盒子破了里面所有东西都要重新装一遍A-MPDU 则是一串独立的盒子谁坏补谁效率高得多。3.3 A-MPDU 的优势与代价最直接的优势就是吞吐量高而且在大带宽高 MCS 场景下尤其明显。物理层速率越高单帧传输的时间越短固定开销占比越大如果不靠 A-MPDU 把几十个帧打包发一次空口速率再高也发挥不出来。代价方面一是协议实现复杂度高发送端要维护 Block Ack 窗口、序列号状态、重传队列接收端要分配缓存来暂存乱序的 MPDU。二是 A-MPDU 要求双方都支持 IEEE 802.11e/WMM 的 QoS 数据帧因为 Block Ack 是绑定 TID 队列的。所以很多设备如果关闭了 WMMA-MPDU 就很难正常工作吞吐直接掉一大截。三是 A-MPDU 的子帧之间有 Delimiter 和填充字节的额外开销虽然很小但在子帧数量非常多的时候也不是完全忽略不计。4. A-MSDU 和 A-MPDU 的配合、区别与取舍很多人把这两个东西搞混其实只要记住它们在协议栈里所处的层次不同就不会乱。A-MSDU 在把数据封装成 MAC 帧之前做合并它改变的是 MPDU 的内部内容A-MPDU 在 MAC 帧做完之后再合并它改变的是物理层发送时的整体结构。在常见数据路径上一个包往往是先看能不能做 A-MSDU然后在发送队列里再按 A-MPDU 聚合到一起。4.1 两种聚合在协议栈中处于不同位置从处理流程看上层下来的多个 MSDU 先经过 A-MSDU 合并形成一个更大的 MPDU 载荷然后这个 MPDU 交给发送队列等待和其他 MPDU 一起组成 A-MPDU。也就是说A-MSDU 和 A-MPDU 可以同时存在也可以独立存在。实际抓包最常见的是 A-MPDU 里包含若干个 MPDU其中部分 MPDU 内部又带着 A-MSDU 子帧形成“双层聚合”。我在调试时会特别留意这个嵌套关系因为这直接关系到抓包工具怎么解码。Wireshark 在识别到 A-MPDU 时会展开出多个 MPDU如果某个 MPDU 内部还带 A-MSDU又会把它标记成“Aggregated MSDU”下面再拆出多个子帧。看到这种展开结构基本可以确认无线驱动同时在用两种聚合。4.2 重传粒度、加密方式和兼容性差异重传粒度是两者最核心的行为差异。A-MSDU 的 FCS 是整个 MPDU 级别的里面的子帧没有独立校验所以任何一个子帧坏掉整个 A-MSDU 都要重传。A-MPDU 的每个 MPDU 有独立 FCSBlock Ack 能精确指出哪个 MPDU 出错发送端可以只重传那个 MPDU。加密方面A-MSDU 对加密方式敏感TKIP/WEP 下基本不可用AES 下才能正常发挥A-MPDU 因为每个 MPDU 都是完整 MAC 帧对加密方式没那么挑剔WPA2/WPA3 下都能很好配合。兼容性上A-MSDU 出现更早802.11n 之前就有类似思路但真正大规模标准化还是从 HT 开始A-MPDU 则是 802.11n 才有的关键新特性和 Block Ack 强绑定。4.3 一张表看明白两者区别对比维度A-MSDUA-MPDU工作层次把多个 MSDU 合并成一个 MPDU把多个 MPDU 合并进一个 PPDU最小校验单位一个 MPDU 共用一个 FCS每个 MPDU 各有独立 FCS重传粒度一个子帧出错整个 A-MSDU 重传单个 MPDU 出错按位图选择性重传典型长度上限3839 / 7935 字节64KB / 到 1MB 级别ACK 机制普通 ACK 或随上层 A-MPDU 一起 Block AckBlock Ack 位图确认对加密的偏好AES-CCMP/GCMP 下正常TKIP/WEP 受限对 WPA2/WPA3 兼容性好解析复杂度子帧头需要按 DA/SA/Length 重新拼装MPDU Delimiter 负责边界定位抗误码能力较弱坏一比特影响整包较强坏一个 MPDU 不影响其他这张表不是要说明谁比谁高级而是强调二者解决的不是同一个问题。A-MSDU 更省 MAC 头开销A-MPDU 更省物理层和竞争开销同时也更抗错误。真实产品里两者通常是同时开启的关键是怎么根据场景调整各自的参数上限。5. 驱动参数、报文观察和实用配置技巧理论讲完接下来聊实操。很多开发者配置聚合时会遇到“明明代码里开了 A-MPDU为什么实际抓包看不到长包”的问题。我总结下来先确认长度上限再确认加密和 QoS最后用抓包工具验证这个顺序最省时间。5.1 长度上限在不同 802.11 协议版本之间的变化802.11n 时代A-MSDU 的 Max 大小由 HT Capabilities 里的 Maximum A-MSDU Length 字段决定0 表示 3839 字节1 表示 7935 字节。A-MPDU 的长度上限则由 Maximum A-MPDU Length Exponent 决定常见配置是 65535 字节。到 802.11acVHT Capabilities 基本把 A-MSDU 上限固定成 7935 字节A-MPDU 最大值提升到 1048575 字节。802.11ax 延续了这些设计同时对多用户场景下的资源块分配更加灵活但 A-MSDU 本身没有突破 7935 这个经典上限。实际开发时除了看标准定义更要看芯片厂商的驱动能力。有些低端 WiFi 芯片为了省内存A-MPDU 接收缓冲只做到 16KB 或者 32KB那么即使对端宣称支持 64KB协商结果也会被拉低。我建议在驱动日志里强制打印协商后的 AMPDU 长度和 AMSDU 长度不要只看能力位。5.2 如何确认自己的网卡/AP 真的开了聚合在 Linux 环境下可以用 iw 命令查看 station 的信息。传统做法是执行iw dev wlan0 station dump能看到当前连接速率、信号强度、重传计数等信息。部分内核版本和驱动还会列出rx_ampdu、tx_ampdu之类的统计或者给出当前协商的 MCS、带宽和短 GI 状态。如果没有这些聚合统计那就用最基础的办法抓包。把无线网卡切到 monitor 模式用 tcpdump 或者 Wireshark 抓空口帧然后展开 802.11 MAC 层看是否存在Aggregation相关字段。如果是 A-MPDU你会看到多个 MPDU 被封装在一个 PPDU 里Wireshark 一般会标记为A-MPDU或者展开成多个子帧如果是 A-MSDU则可以在 MPDU 的 Frame Body 中看到多个 DA/SA/Length 子头。还有一种旁路验证方法就是同一测试条件下人为关闭聚合后再测吞吐。如果聚合生效开启前后的 TCP/UDP 吞吐应该明显不同尤其是 MTU 1500、单流 TCP 场景关闭聚合经常直接腰斩。5.3 实际调优时的一些经验第一WMM/QoS 必须开。A-MPDU 和 Block Ack 依赖 QoS 数据帧的 TID 队列很多老 AP 默认关闭 WMM这时候聚合能力再强也白搭。第二不要盲目追求最大聚合长度。A-MSDU 开 7935 在高清视频传输和 TCP 下载里收益很明显但在误码率高的环境里反而会把吞吐打下来建议配合空口重传率一起判断。第三上层协议栈的接收卸载能力也要跟上比如 GRO/LRO 这类大包合并机制如果没开CPU 会被大量小包中断拖垮即便无线侧聚合了上层也会拆散处理。实际调优可以先固定在其他参数上做实验比如调 MCS、关闭低速率抑制再观察聚合的有效负载比例。经验来看空口速率越高、信道越干净聚合长度越值得拉满信道嘈杂、重传率超过 5% 时适度降低 A-MSDU 长度反而更稳。6. 常见问题与排障实录最后整理一些我在项目中真正遇到的典型问题每个问题后面都附排查思路方便你直接对照。6.1 抓包看到很多“Sequence 跳变”是不是聚合导致很多新人在空口抓包里看到 Sequence number 突然从 100 跳到 200以为丢包了。这里要分清楚A-MPDU 聚合本身会产生连续序列号但接收方用 Block Ack 回复的时候中间的 MPDU 如果出错发送端会把窗口里的包重传重传包里有些可能是老包序列号看起来就会乱。排查时要配合 FCS 状态和重传标志一起看。如果 FCS 错误率高说明链路质量问题不是协议 bug如果 FCS 正常但序列号频繁跳变再检查是不是驱动把 A-MSDU 子帧当成独立 MPDU 处理了。不同抓包软件对 A-MSDU 的解析方式差异很大我建议先在无干扰的实验室环境下抓一包标准长帧做参考。6.2 开启聚合后吞吐量反而下降这是最常碰到的“反直觉”问题。现象是配置了很大的 A-MPDU 和 A-MSDU 长度结果 iperf 测速不升反降。最常见的原因有两个一是空口误码率高长聚合包一旦出错重传代价远大于短包整个链路陷入重传风暴二是接收端内存不足驱动把缓冲区调小了无法缓存 64 个 MPDU 的乱序数据导致接收窗口频繁停滞。排查步骤如下先在近距离、无干扰环境下测速排除信道因素。然后用工具看驱动日志里的 AMPDU 接收失败计数和 BA 超时次数。如果错误计数很高优先降低聚合长度或者尝试关闭 A-MSDU如果超时次数高重点看接收端缓冲区配置和 CPU 负载。还有一个容易忽略的点老版本驱动对 802.11ac 的 1MB A-MPDU 支持不完整强行开启反而会触发 bug建议升级驱动或者把长度限制在 64KB 级别。6.3 各场景下聚合行为速查场景A-MSDU 建议A-MPDU 建议近距离 TCP 大流量下载开启7935 字节开满64KB/1MB 配合 Block Ack远距离或穿墙环境降低至 3839 甚至关闭保持但降低聚合帧数语音小包、实时交互不建议追求高聚合少量聚合即可优先保证时延视频流并发开启但按客户端能力协商开满并配合 QoS 队列老式设备兼容测试按 802.11n 下限配置与 Block Ack 窗口一起验证这张表不是硬性规范而是给一个排查方向。无线环境变化太快每种场景还要结合具体设备去验证。我自己做项目时会先在产测固件里把聚合参数做成可配置项用一份脚本循环切换不同组合再对比每个组合下的吞吐、时延和重传率最后选一组最平衡的参数固化进默认配置。回到开头的问题为什么实际吞吐总到不了空口速率答案往往不在物理层而在帧聚合。把 A-MSDU 和 A-MPDU 的层次关系、重传机制、加密兼容性吃透调试 Wi-Fi 性能就会多一条非常清晰的思路。尤其要注意聚合不是越猛越好它更像一把双刃剑在好信道上如虎添翼在差信道上也可能放大错误。后来我做任何无线性能优化第一件事就是把聚合参数、WMM 开关、加密方式这三样确认清楚基本能避开大半潜在的“玄学”问题。
返回列表