ARTICLE DETAIL

资讯详情

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

Wi-Fi聚合机制详解:A-MSDU与A-MPDU原理、区别及调优实战

Wi-Fi聚合机制详解:A-MSDU与A-MPDU原理、区别及调优实战 1. 为什么这两个聚合机制值得你花时间搞清楚做Wi-Fi调试这行当久了你会发现一个特别有意思的现象很多人天天跟速率、吞吐量较劲却讲不清楚802.11n引入的两个“聚合”到底是什么关系、怎么配合。你说他不知道A-MSDU和A-MPDU吧他能背出全称你一问他“这俩到底谁包谁”“为什么聚合之后延迟反而可能变差”“空口抓包怎么看子帧”他就开始含糊了。这篇文章就是干这个用的。我把自己这几年调Wi-Fi、看空口日志、跟吞吐量死磕的经验整理了一遍把A-MSDU和A-MPDU这两个机制从原理到区别、从配置到排查一次性讲明白。不搞那种糊弄人的概念复述直接给能落地的干货。适合谁看三类人一是做无线协议开发的工程师二是做路由器/AP产品测试的QA同学三是搞现场网络优化、天天跟iperf和抓包工具打交道的网工。这篇文章能帮你搞清楚的不是“它们是什么”而是“它们怎么配合”“效率瓶颈卡在哪”“遇到吞吐量上不去怎么排查”。这两个机制说白了就是Wi-Fi传输效率的“打包搬运工”。一个管的是“把多个小包裹合并成一个大包裹再装车”另一个管的是“多辆小车编组成一列火车一起发车”。打包打得好、编组编得顺吞吐量自然蹭蹭往上涨打得不好你空有160MHz频宽和数据流数速率标得再漂亮实际跑起来照样拉胯。2. 从“一份数据怎么从协议栈走到空口”说起2.1 一个帧的完整旅程要理解A-MSDU和A-MPDU不能只盯着MAC层的定义看你得先知道一份数据从系统里出来到真正从天线发出去中间要过几道手。假设你在电脑上下载一个文件这个文件经过TCP/IP协议栈变成一个个TCP段再变成IP包。到了Wi-Fi网卡驱动里这些IP包会被封装成802.11格式的帧。这个“封装”动作在逻辑链路控制层里做了个分层的处理最上层是MSDU也就是协议栈交给MAC层的数据单元本质上就是一个完整的IP包加上LLC头。然后MSDU到了MAC层加上MAC头包含地址、帧控制、序列号这些信息后面再挂个FCS校验尾巴就成了一个MPDU。MPDU是真正要被物理层发送出去的帧单位。到了这一步如果你用的是老一代802.11a/b/g一个MPDU就是一个PPDU物理层发送完一帧再送下一帧每一帧之间还隔着前导码、退避时间、帧间隔这些“路障”效率之低可想而知。802.11n之后事情起了变化。协议栈发现如果一个一个地发送空口开销占了太多时间真正送数据的占比太低。于是就想了个办法能不能把多个步骤合并打包这就引出了A-MSDU和A-MPDU这类聚合机制。2.2 传输效率的拦路虎是什么在讨论聚合之前先明确一个概念Wi-Fi空口传输时间是非常宝贵的。一次成功的帧传输需要消耗的时间包括以下几部分竞争信道用的退避时间、发送请求/清除帧握手的时间、帧前导码和物理层头部、MAC层帧头、有效载荷、帧校验、帧间隔、确认帧的发送时间。你算算这笔账在不聚合的情况下如果一个MSDU只有几百字节那MAC头、前导码、确认帧这些固定开销占的比例就非常高。打个比方你要送100封信每封信单独跑一趟邮局来回路上花的时间远大于投递信本身。聚合的本质就是把“跑趟”的次数压下来一次多拉点东西。A-MSDU解决的是“把信合并成一封大信”的问题——在一个MPDU里塞多个MSDU减少MAC头、FCS的重复开销。A-MPDU解决的是“多辆车编组成一列火车”的问题——把多个MPDU并在一起连续发中间不再等待确认和重竞争信道。3. 先拆A-MSDU把多个上层数据包揉进一个MAC帧3.1 A-MSDU的结构长什么样A-MSDU的全称是Aggregate MAC Service Data Unit聚合MAC服务数据单元。它的核心机制是在逻辑链路层完成聚合把多个MSDU合并成一个更大的“超级MSDU”然后只加一个MAC头和一个FCS尾作为一个整体交给物理层发送。看A-MSDU的帧格式你会发现它内部是由多个子帧Subframe组成的每个子帧包含三部分子帧头14字节、原始MSDU、填充字节为了对齐4字节边界。子帧头里最关键的是目的地址、源地址和长度字段总共14字节。这也是A-MSDU的一个特点它在聚合层保留了每个子帧的地址信息这意味着一个A-MSDU里的多个子帧目的地址可以是同一个也可以是不同地址。具体到发送端的处理流程是这样的驱动从协议栈拿到多个MSDU后先做合法性检查比如每个MSDU的长度不能超过设定的上限然后依次拼装子帧头、MSDU、填充最后统一加MAC头和FCS。这个聚合过程CPU参与度相对低因为不需要做加密、序列号分配这些重活所以A-MSDU的聚合开销主要是在内存拷贝和子帧拼接上。3.2 A-MSDU的边界和政策A-MSDU不是无限聚合的。它有两个硬性约束一个是最大长度限制一个是子帧数量限制。在802.11n时代A-MSDU最大长度常见的有3839字节和7935字节两档。到了802.11ac最大可以扩展到11454字节这个数字很关键它基本对应一个标准MTU 1500的IP包算上封装开销之后恰好能放7到8个全尺寸包。Wi-Fi 6802.11ax延续了Wi-Fi 5的长度限制但在特定场景支持更大的A-MSDU长度。为什么不直接无限制增加A-MSDU长度两个原因。第一一个A-MSDU是一个MPDU这个MPDU一旦在传输中出现比特错误整个A-MSDU就废了重传成本非常高。第二接收端需要用一个缓冲区装下整个A-MSDU做解析缓冲区越大芯片成本和内存占用越高尤其是那些低成本的IoT Wi-Fi芯片根本吃不下大A-MSDU。实际操作中A-MSDU长度上限还得看驱动和硬件支持的“短板效应”。我曾经在一款高通的方案上测试硬件明明支持7935字节的A-MSDU但驱动默认配的是3839字节导致同速率下吞吐量差了一截。如果你在调优的时候发现聚合效率上不去第一件事就去查驱动日志里A-MSDU长度上限的实际配置值。3.3 A-MSDU的坑一个比特错误毁掉一堆包A-MSDU有一个让人头疼的特性它整包只有一个FCS校验。这意味着如果空口传输中出现哪怕1个比特的错误接收端在FCS校验时就会发现整个A-MSDU包损坏然后把这个包含的所有子帧全部丢弃。如果这一个大包里装的是8个IP包那就等于一口气丢了8个包上层的TCP传输层会把这理解为“网络拥塞”触发拥塞窗口减半吞吐量断崖式下跌。这个问题的缓解思路有两个方向。第一A-MSDU不直接走确认重传机制它的重传粒度是一个完整MPDU不是其中某个子帧。第二实际芯片厂商往往会在固件层做一定程度的限制比如在信道质量较差时自动降低A-MSDU长度、减少子帧数量甚至是完全关闭A-MSDU、只保留A-MPDU单体发送。我实测过一个场景在弱信号RSSI在-75dBm以下的角落里跑iperf如果强制开启最大长度的A-MSDU吞吐量会出现周期性“锯齿波”每隔几秒掉到几乎为零再爬升上来。这是因为一次误码导致一个大聚合帧报废TCP拥塞控制被触发恢复过程极其漫长。后来把A-MSDU的长度上限从7935降到3839锯齿波明显平缓。这就是“聚合不是越大越好”的典型例子。4. 再看A-MPDU把多个MPDU编成“列车”发出去4.1 A-MPDU的基本工作流程A-MPDU的全称是Aggregate MAC Protocol Data Unit。不同于A-MSDU的“合并数据单元”A-MPDU走的是另一条路把多个已经完整封装好的MPDU拼接起来作为一个PPDU统一交给物理层发送。这里要特别澄清一个常见误区A-MPDU不是说把多个MPDU变成一个MPDU。每个MPDU仍然是独立的有自己的MAC头、自己的序列号、自己的FCS。物理层发送的时候只是把这一串MPDU“排队”发送中间省略了帧间隔、退避、确认的时间开销真正传输的时候每个MPDU之间只隔一个很短的MPDU分隔符Delimiter。A-MPDU的帧格式比A-MSDU复杂一些。整个A-MPDU由若干MPDU和它们各自的前导分隔符组成每个MPDU之间还有填充字节用来对齐MPDU的30位长度偏移字段。接收端收到A-MPDU后通过分隔符头里的长度信息快速定位每个MPDU的边界然后逐帧校验FCS把坏帧挑出来单独请求重传好帧正常接收。这种“坏帧单独重传、好帧照常收”的机制是A-MPDU跟A-MSDU最大的不同A-MPDU的鲁棒性要强得多一个子帧坏了不影响其他子帧被正确接收和确认。4.2 BA机制A-MPDU的灵魂搭档A-MPDU要是没有Block AckBA块确认机制配合效率反而可能比不聚合还差。试想一下如果发送端一口气发了几十个MPDU按老规矩每个MPDU都要等一个ACK那聚合省下来的时间又全浪费在等ACK上了。802.11n引入了Block Ack机制接收端可以对一个A-MPDU批次统一回复一个BA帧。BA帧里有一个位图每一位对应一个MPDU的接收情况置1表示接收成功置0表示失败。发送端根据BA位图只重传标记为失败的MPDU成功的那些一次性确认完。这是A-MPDU效率的关键保障。BA的协商过程在连接建立时通过ADDBA请求和响应完成。你要注意几个BA参数缓冲区大小Buffer Size表示接收端一次最多缓存多少个MPDU等待重排块确认超时值发送端和接收端的传输方向。这些参数在抓包里都能看到排查聚合问题时是重要切入点。4.3 A-MPDU的最大限制从哪来A-MPDU的聚合数量用802.11协议里的一个参数描述Maximum AMPDU Length Exponent。这个指数值是接收端在能力信息字段里广播的表示它愿意接收的最大A-MPDU长度。以2的指数次方减1得到以字节为单位的长度阈值常见的值在8K、16K、32K、64K、128K、256K、512K之间。这个参数是接收端能力的一个重要信号发送端必须遵守否则会被静默丢弃。注意到了802.11axA-MPDU最大长度扩展到了1MB以上。A-MPDU聚合数量的提升直接影响一个特性在相同速率下A-MPDU聚合得越多吞吐量越能跑满。我在实测高通Wi-Fi 6方案时看到一条80MHz、2x2 MIMO、1024QAM的链路如果A-MPDU最大值能到512KByte单流TCP吞吐可以稳定在1.2Gbps以上如果协商值掉到64KByte同样条件下吞吐只有900Mbps出头。这个差距在Wi-Fi 6的极限速率测试中会被进一步放大。5. 两者到底什么关系——一张表讲透5.1 形态、层级、容错的多维对比很多新手搞混A-MSDU和A-MPDU是因为只看“聚合”两个字没去看它们工作在协议栈的哪一层。我整理了一张表对照着看会清晰很多对比维度A-MSDUA-MPDU全称Aggregate MAC Service Data UnitAggregate MAC Protocol Data Unit聚合层级逻辑链路层/高层MAC上层MAC层聚合对象多个MSDUIP包LLC头多个MPDU完整MAC帧帧结构一个MAC头一个FCS内部分子帧每个MPDU独立MAC头FCS顺序排列确认方式无独立BA作为MPDU整体按普通帧确认配合Block Ack机制做位图批量确认错误容忍差一个比特错误导致整包作废好逐帧校验坏帧单独重传地址字段每个子帧保留源/目的地址每个MPDU有完整MAC头含地址信息对加密影响聚合完成后统一加密每个MPDU单独加密最大长度典型3839/7935字节n/ac64KB~512KBn/ac/ax这张表的关键词是“层级”。A-MSDU是在MSDU这个层面上做聚合把多个数据包合并成一个再送进MAC层A-MPDU是在MPDU层面上做聚合让MAC层一次性发送多个已经封装好的帧。这里要特别提一个很多人问过我的问题“加密对这两种聚合有什么影响”A-MSDU的聚合过程是在打开加密之前完成的多个子帧合在一起后统一加密A-MPDU则是对每个MPDU单独加密。这个差异造成的后果是在抓包工具里看加密帧你能通过A-MPDU分隔符识别每个MPDU的边界而A-MSDU的子帧边界在加密后是无法直接看到的。5.2 两者如何协同工作实际工作流程中A-MSDU和A-MPDU通常不是互斥关系而是先A-MSDU再A-MPDU的“两级流水线”第一步驱动拿到一批上层IP包根据优先级、目的地址等条件做分类把符合条件的多个IP包封装成多个MSDU子帧组成一个A-MSDU。 第二步一个或多个A-MSDU被封装成MPDU加MAC头也可以和那些没经过A-MSDU聚合的普通MPDU混在一起。 第三步多个MPDU带上各自的分隔符拼接成A-MPDU交给物理层发送。 第四步接收端先解析A-MPDU分隔符逐个校验MPDU的FCS通过BA机制确认每个MPDU内部如果是A-MSDU再解析子帧头把多个MSDU还原出来送交高层。两级聚合叠加的效果非常可观如果每个MPDU里装了8个MSDU一个A-MPDU里装了32个MPDU那一个物理层传输里实际包含了256个IP包。空口固定开销被摊薄到了一个极低的水平这就是802.11n之后速率暴涨的部分原因——不只是调制阶数变高传输效率提升也是关键。6. 实操手册从帧格式到吞吐量调试6.1 用Wireshark看聚合效率遇到问题第一件事是抓包。但抓Wi-Fi空口包和抓有线包不太一样你得用支持monitor模式的无线网卡加上合适的抓包软件。抓到包之后最关键的是在Wireshark的过滤栏里看聚合相关信息。我常用的做法是用过滤表达式把A-MPDU的聚合数量拉出来wlan_aggregate是Wireshark里聚合帧的统称展开每一帧能看到包含的MPDU个数wlan.msehdr.present配合wlan.qos.amsdupresent可以判断是否有A-MSDU聚合。实际操作中我会同时开两个窗口看一个看全局吞吐iperf输出一个看Wireshark里的聚合统计。Wireshark“统计”菜单里有“聚合”相关的视图能直接按MPDU数量、A-MSDU子帧数排序。如果发现大量帧的MPDU数量只有几个说明A-MPDU聚合效率极低如果A-MSDU子帧数普遍为1说明上层包合并做得不够。这里分享一个实测案例某款家庭路由器5GHz下行吞吐只能跑到标称值的一半。抓包发现下行方向A-MPDU聚合数量只有两到四帧但A-MSDU聚合在驱动里根本没开启。后来在驱动配置里手动开了A-MSDU并把长度上限调到7935字节吞吐立刻从480Mbps跳到720Mbps。这个案例充分说明两级聚合都得开着才能发挥真正性能。6.2 路由器/AP侧的配置要点不同平台对A-MSDU和A-MPDU的配置方式不同但底层逻辑相通。以常见的开源无线驱动和闭源SDK为例有以下几个参数需要留意第一A-MPDU最大长度指数Max AMPDU Length Exponent。这个值是接收端能力通告发送端据此限制一次发送的A-MPDU总长度。作为AP侧要确保它给STA通告一个足够大的值对于Wi-Fi 5建议至少到7即128KBWi-Fi 6建议直接拉满否则会成为吞吐量瓶颈。第二A-MSDU最大长度。很多驱动里A-MSDU默认是关闭的或者默认长度只有3839字节。如果你的场景以TCP上传下载为主建议在保证信道质量的前提下把这个值调大。第三BA缓冲区大小。接收端BA缓冲区直接决定了它能容忍多少乱序到达的MPDU。如果BA缓冲区太小即便发送端一次发了32个MPDU接收端缓冲不过来也只能丢弃触发重传。第四重传策略。有的方案支持“部分重传”只重传BA位图里标记失败的那几个MPDU有的方案实现粗糙整个A-MPDU重传。后者在丢包率高的环境里性能衰减极其严重。6.3 不同场景下的聚合参数建议聚合参数不是一成不变的要跟随场景动态调整高吞吐室内场景无遮挡、信号强A-MSDU开满、A-MPDU长度拉满、BA开打目标是最大化空口效率。我的经验是这种情况下聚合参数对吞吐影响最大值得反复调。弱信号/高干扰场景远距离、隔墙、人员密集适当降低A-MSDU长度甚至可以关闭A-MSDU只保留A-MPDU。因为弱信号下大包被误码报废的概率急剧上升A-MPDU的逐帧容错优势更值钱。低延迟场景游戏、语音聚合要克制建议限制A-MPDU的最大长度和子帧数。聚合天然引入“攒一批才发”的排队延迟对延迟敏感的业务不友好。Wi-Fi 6里有针对低延迟业务的配置项其中一个思路就是动态降低聚合队列深度。IoT设备场景这类设备通常只支持很短的A-MPDU甚至不支持聚合对它们发送数据时不要使用大聚合否则适配性差、重传多反而拖累整体性能。7. 常见问题与排查技巧实录7.1 吞吐量上不去先查这五个地方我在调试中总结了一套排查顺序按优先级排列如下第一步确认链路速率。速率就上不去聚合再优化也白搭。先看协商速率是不是符合预期排除速率问题再往下走。第二步看A-MPDU实际聚合数。用抓包工具看每帧包含的MPDU数量如果在信号很好时依然只有一两个问题一定出在聚合使能或BA协商失败上。第三步查BA协商是否成功。抓包过滤ADDBA请求和响应确认是否达成一致。如果BA一直协商失败A-MPDU会退化为普通单帧发送模式但速率看起来正常隐蔽性强。第四步看A-MSDU是否生效。典型特征是抓包工具里能看到MPDU里有多个MSDU子帧。如果没生效优先检查驱动模块是否支持、是否被编译进去、默认配置值是不是被改小了。第五步检查加密方式。在WPA2/WPA3加密打开的情况下A-MSDU子帧无法直接看到属于正常现象但A-MPDU的MPDU数量仍然可见。不要因为看不到A-MSDU就误判。7.2 弱信号下吞吐量暴跌的根源弱信号下的吞吐量暴跌很多时候不是调制阶数降级的问题而是聚合效率被误码率打败了。举一个我实际遇到的案例某酒店走廊尽头信号只有-78dBm连接速率是802.11ac的2x2 80MHz协商速率标称有866Mbps。但实际下载速度只有不到50Mbps看起来非常离谱。抓包后发现下行大包1514字节都做了A-MSDU聚合一次A-MPDU里装了十几MPDU每个MPDU又有多个MSDU子帧。信道误码率一高一个A-MSDU整体损坏的概率急剧上升导致TCP同时丢十几个包拥塞窗口从高位直接腰斩恢复过程又慢整体吞吐惨不忍睹。最终解决方式是把这个AP的信号覆盖问题处理掉加装了一个近端AP同时在下行方向上把A-MSDU长度上限从11454降到3839字节。吞吐立竿见影地翻了四倍。这个案例给我们的教训是信号越差越不要迷信大聚合。7.3 从BA位图看丢包分布Block Ack帧里最有价值的信息就是那个位图。我刚才说过位图里每一位对应一个MPDU的接收状态。排查问题的时候BA位图能帮你判断丢包有没有规律性如果位图里失败的位是连续成片出现的说明信道存在持续时间较长的干扰或遮挡建议调整信道或降低带宽。 如果失败的位是分散孤立的说明是随机噪声或隐藏节点冲突可以考虑增大重传次数或开启更稳健的速率自适应。 如果失败的位置集中在聚合帧的后半段可能是发送功率衰减或接收灵敏度边缘问题。 如果某一类特定大小的帧总是失败检查是不是触发了接收端的某些过滤规则。这些判断方法相当实用能帮你快速缩小问题范围。我建议每个做Wi-Fi调优的人都熟悉一下Wireshark里BA帧的位图查看方式大多数人没用过这个功能挺可惜的。7.4 驱动层面的隐藏坑最后再分享几个驱动层面的隐藏坑属于那种“不踩过就不会知道”的知识点。第一个坑不少Wi-Fi驱动默认是根据CPU调度线程来触发聚合的。如果CPU负载高驱动没及时把数据从协议栈搬到固件聚合窗口就会变短聚合数量自然上不去。你在测试中如果发现吞吐间歇性掉坑不妨查一下CPU频率是不是被调成了节能模式。第二个坑很多芯片的A-MPDU聚合队列是有限深度的数据积压过多的极端情况下会触发流控导致吞吐不升反降。这个现象在高负载多用户场景下尤其明显表现为每个用户单独测速正常多用户并发时总吞吐反而下降。排查时可以把每个用户的A-MPDU长度上限往下调往往能改善多用户并发调度效率。第三个坑驱动的A-MSDU封装代码里有些实现会为每个子帧做一次内存拷贝CPU开销显著高于A-MPDU。在低端芯片上开启满长度A-MSDU可能直接把CPU占满性能不升反降。这种情况在低成本路由器上不少见优化思路是降子帧数量或改用A-MPDU单体聚合。第四个坑不同芯片厂商对A-MSDU的填充字节处理不统一。有些芯片严格要求4字节对齐有些则不强制。双方在填充字节上不一致时可能导致接收端解析错位。这种问题排查起来非常隐蔽通常不会在互操作测试中暴露但在异构设备混连环境中确实遇到过。如果你的环境中抓包显示完整帧结构里的子帧长度来回偏差可以优先怀疑这个。8. 一点实战体会关于A-MSDU和A-MPDU我个人在实际操作中最大的一个体会是它们不是“越高越好”的关系而是“按需配置、动态取舍”的关系。很多刚接触无线调试的同事有个习惯拿到一个新设备第一件事就是把所有聚合参数拉满然后跑测速发现效果不好就抱怨设备不行。这样做缺乏对无线信道和上层业务特征的通盘考量。正确思路应该是先明确业务目标要最高吞吐还是最低延迟还是均衡再判断信道环境信号强度、干扰水平、丢包率最后反推该用多长的A-MSDU、多大的A-MPDU、怎样的BA策略。另外这两个机制背后还有一个共通的思考方式空口时间是最稀缺的资源。无线通信的所有优化动作最终都可以归结为“如何把有效数据在更短的空口时间内送出去”。你在配置A-MSDU和A-MPDU时始终带着这个视角去看问题很多选择就不难做了。如果这篇文章讲的内容你还想往深挖我的建议是下一步直接上手抓包找个支持monitor模式的网卡把你手边路由器的空口流量抓下来对照着看A-MPDU的分隔符和BA位图。理论加实践对照着来比看十篇文章都管用。
返回列表