Is there any way to get the WiFi contention window (CW) min and max value in Linux 80211 subsystem?

16 views Asked by At

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

0

There are 0 answers