Linux 80211子系统如何获取WiFi CW参数及验证WMM设置生效?
我是Linux内核与80211子系统的新手,希望动态设置IEEE 802.11e定义的特定访问类别(AC)的WMM参数(如竞争窗口最小值/最大值、AIFSN)。使用环境如下:
- 路由器:小米AX3600
- 系统:OpenWRT 23.05(内核版本5.15.134)
- WiFi芯片:高通Atheros IPQ8074
- 80211子系统:从6.1.14版本回传
- WiFi驱动:ath11k
目前已找到net/mac80211/cfg.c中的ieee80211_set_txq_params函数,该函数会调用驱动注册的ieee80211_ops->conf_tx设置WMM参数。我导出了该函数并编写内核模块调用它,代码如下:
static int __init cw_adapt_init(void) { struct net_device* netdev = NULL; struct wiphy* wiphy = NULL; struct wireless_dev* wdev = NULL; struct ieee80211_txq_params txq_params; char* ifname = "phy1-ap0"; int result = 0; netdev = dev_get_by_name(&init_net, ifname); if (!netdev) { pr_warn("can not find wifi device: %s\n", ifname); goto out; } wdev = netdev->ieee80211_ptr; if (!wdev) { pr_warn("can not get wdev\n"); goto out; } wiphy = wdev->wiphy; if (!wiphy) { pr_warn("can not get wiphy\n"); goto out; } if (!netif_running(netdev)) { pr_warn("netdev is not running\n"); goto out; } wiphy_lock(wiphy); wdev_lock(wdev); txq_params.ac = NL80211_AC_BK; // trying to set txq params of BK as same as VI txq_params.link_id = -1; // introduced in kernel 6.x to support MLD, not used in my router txq_params.txop = 94; txq_params.cwmin = 7; txq_params.cwmax = 15; txq_params.aifs = 2; result = ieee80211_set_txq_params(wiphy, netdev, &txq_params); if (result) { pr_warn("set txq params failed for ac %d: %d\n", txq_params.ac, result); } wdev_unlock(wdev); wiphy_unlock(wiphy); out: return 0; }
模块运行无报错,但存在以下疑问:
- 是否有方法获取特定AC的当前参数,确认新设置已生效?
- 抓包发现Beacon帧中的WMM参数仍为默认值,即使修改
ieee80211_set_wmm_default函数也无变化。猜测Beacon帧中的该字段无法反映驱动实际WMM参数,是否正确?如果正确,有什么方法验证WMM设置已生效?
抓包得到的Beacon帧WMM参数片段:
Tag: Vendor Specific: Microsoft Corp.: WMM/WME: Parameter Element Tag Number: Vendor Specific (221) Tag length: 24 OUI: 00:50:f2 (Microsoft Corp.) Vendor Specific OUI Type: 2 Type: WMM/WME (0x02) WME Subtype: Parameter Element (1) WME Version: 1 WME QoS Info: 0x81 1... .... = U-APSD: Enabled .... 0001 = Parameter Set Count: 0x1 .000 .... = Reserved: 0x0 Reserved: 00 Ac Parameters ACI 0 (Best Effort), ACM no, AIFSN 3, ECWmin/max 4/10 (CWmin/max 15/1023), TXOP 0 ACI / AIFSN Field: 0x03 ECW: 0xa4 TXOP Limit: 0 Ac Parameters ACI 1 (Background), ACM no, AIFSN 7, ECWmin/max 4/10 (CWmin/max 15/1023), TXOP 0 ACI / AIFSN Field: 0x27 ECW: 0xa4 TXOP Limit: 0 Ac Parameters ACI 2 (Video), ACM no, AIFSN 2, ECWmin/max 3/4 (CWmin/max 7/15), TXOP 94 ACI / AIFSN Field: 0x42 ECW: 0x43 TXOP Limit: 94 Ac Parameters ACI 3 (Voice), ACM no, AIFSN 2, ECWmin/max 2/3 (CWmin/max 3/7), TXOP 47 ACI / AIFSN Field: 0x62 ECW: 0x32 TXOP Limit: 47
关于Beacon帧WMM参数的猜测验证
你的猜测是正确的。Beacon帧中的WMM参数属于网络侧对外广播的协商参数,用于告知STA(客户端)AP支持的WMM能力范围,一旦AP启动后,该字段通常不会随驱动内部参数的动态修改而更新——除非主动触发Beacon帧内容的重新生成与广播。
mac80211中,Beacon帧的WMM参数是在接口初始化时基于默认WMM配置生成的,之后动态修改驱动内部的TXQ参数不会自动同步到Beacon的广播内容里。修改ieee80211_set_wmm_default后需要重启AP接口才能让Beacon参数更新,但这也只是修改了初始广播值,无法反映后续的动态调整。
获取当前AC参数的方法
1. 内核debugfs接口查看
mac80211提供了debugfs接口可以查看每个AC的当前参数,路径通常是/sys/kernel/debug/ieee80211/<wiphyX>/netdev:<ifname>/txqueues。
进入对应目录后,每个AC(如ac_bk、ac_be、ac_vi、ac_vo)都有单独的子目录,里面的文件会记录当前的cwmin、cwmax、aifs、txop等参数。例如:
cat /sys/kernel/debug/ieee80211/phy1/netdev:phy1-ap0/txqueues/ac_bk/cwmin
如果系统未挂载debugfs,先执行:
mount -t debugfs none /sys/kernel/debug
2. 内核模块中添加参数读取逻辑
可以在模块中添加读取逻辑,通过访问struct ieee80211_sub_if_data中的txq_params数组获取当前参数。示例代码片段:
#include <net/mac80211.h> // 获取netdev后执行: struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(netdev); struct ieee80211_txq_params *params = &sdata->txq_params[NL80211_AC_BK]; pr_info("BK AC current params: cwmin=%d, cwmax=%d, aifs=%d, txop=%d\n", params->cwmin, params->cwmax, params->aifs, params->txop);
注意需要确保CONFIG_MAC80211_DEBUGFS已开启,且代码需在mac80211上下文允许范围内访问这些结构体。
验证WMM设置生效的方法
1. 驱动侧日志打印
修改ath11k驱动的conf_tx函数(通常在ath11k/mac.c中),添加日志打印,确认驱动是否接收到mac80211传递的新参数,并且是否成功配置到硬件中。例如:
int ath11k_mac_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u16 queue, const struct ieee80211_txq_params *params) { // 原代码逻辑... pr_debug("ath11k: set AC %d params: cwmin=%d, cwmax=%d, aifs=%d, txop=%d\n", queue, params->cwmin, params->cwmax, params->aifs, params->txop); // 原代码逻辑... }
重新编译驱动后加载,通过dmesg查看日志,确认参数是否被正确接收并配置。
2. 空口性能测试
通过实际流量测试验证参数变化带来的性能差异:
- 用
iperf3等工具发送BK类别的流量(可通过tc qdisc或应用层标记DSCP值映射到BK AC) - 对比修改参数前后的吞吐量、延迟、丢包率:如果把BK参数改成和VI一致,理论上BK流量的优先级会提升,延迟降低,吞吐量上升
- 使用
tcpdump或wireshark捕获空口帧,观察BK类别的帧在竞争信道时的行为变化(比如退避次数减少)
3. 硬件寄存器读取(高级)
如果熟悉IPQ8074的硬件手册,可通过内核模块读取WiFi芯片中对应AC的配置寄存器,直接确认硬件是否应用了新的参数。这种方法需要芯片技术文档支持,适合深度调试。
内容的提问来源于stack exchange,提问作者Yuhan Zhou

