I am new to the Linux kernel and 80211 subsystem. For some reason I decided to dynamically set the WMM parameters (e.g. contention window min/max value, AIFSN) for a specific access category (AC) as defined in IEEE 802.11e. I am using OpenWRT release 23.05 (kernel version 5.15.134) running on a Xiaomi AX3600 router with Qualcomm Atheros IPQ8074 WiFi chipset. The 80211 subsystem is backported from version 6.1.14 and I am using ath11k as the WiFi dirver.
So far I have found function ieee80211_set_txq_params in net/mac80211/cfg.c, which calls ieee80211_ops->conf_tx registered by the driver to set the WMM parameters. I exported this function and write a kernel module to call this function like this:
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;
}
This module seems to work fine. But my question is, is there any way to GET the params of a specific AC so I can confirm my new settings come to work? I use a sniffer to capture on-air frames transmitted by my AP (more specifically, the "phy1-ap0" interface or net device). In beacon frames, I find "Tag: Vendor Specific: Microsoft Corp.: WMM/WME: Parameter Element" field as follows:
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
The WMM parameters are still the default value. More importantly, even if I directly change function ieee80211_set_wmm_default, which sets the default WMM params when a new interface is up. The WMM parameters still do not change in the beacon frames. So I guess this field in beacon frames cannot reflect the actual WMM parameters in the driver. Is my guess correct? If so, is there any way to confirm my WMM settings work?
Everything as described above