Re: wifi: mac80211: question about 20/40 coex support
From: Alex Gavin
Date: Fri Feb 13 2026 - 17:01:53 EST
On 2/13/26 13:44, Alex Gavin wrote:
> On 2/13/26 01:46, Alexander Wilhelm wrote:
>> On Fri, Feb 13, 2026 at 12:14:16AM -0800, Alex Gavin wrote:
>>> On 2/12/26 23:05, Alexander Wilhelm wrote:
>>>>
>>>> Hello wireless devs,
>>>>
>>>> I am analyzing a wireless management frame taken from the beacon of an
>>>> access point, and in this frame the `20/40 Coexistence Management Support`
>>>> bit is set to 0, indicating that the feature is not supported. See frame
>>>> below:
>>>>
>>>> Frame 2: 217 bytes on wire (1736 bits), 217 bytes captured (1736 bits)
>>>> Radiotap Header v0, Length 26
>>>> 802.11 radio information
>>>> IEEE 802.11 Beacon frame, Flags: ........
>>>> IEEE 802.11 Wireless Management
>>>> Fixed parameters (12 bytes)
>>>> Tagged parameters (155 bytes)
>>>> Tag: SSID parameter set: "SSID"
>>>> Tag: Supported Rates 6(B), 9, 12(B), 18, 24(B), 36, 48, 54, [Mbit/sec]
>>>> Tag: DS Parameter set: Current Channel: 6
>>>> Tag: Traffic Indication Map (TIM): DTIM 0 of 2 bitmap
>>>> Tag: Country Information: Country Code DE, Environment All
>>>> Tag: ERP Information
>>>> Tag: QBSS Load Element 802.11e CCA Version
>>>> Tag: Supported Operating Classes
>>>> Tag: HT Capabilities (802.11n D1.10)
>>>> Tag: HT Information (802.11n D1.10)
>>>> Tag: Extended Capabilities (10 octets)
>>>> Tag Number: Extended Capabilities (127)
>>>> Tag length: 10
>>>> Extended Capabilities: 0x04 (octet 1)
>>>> .... ...0 = 20/40 BSS Coexistence Management Support: Not supported
>>>> .... ..0. = General Link (GLK): 0x0
>>>> .... .1.. = Extended Channel Switching: Supported
>>>> .... 0... = GLK-GCR: 0x0
>>>> ...0 .... = PSMP Capability: Not supported
>>>> ..0. .... = Reserved: 0x0
>>>> .0.. .... = S-PSMP Support: Not supported
>>>> 0... .... = Event: Not supported
>>>> Extended Capabilities: 0x00 (octet 2)
>>>> Extended Capabilities: 0x00 (octet 3)
>>>> Extended Capabilities: 0x02 (octet 4)
>>>> Extended Capabilities: 0x00 (octet 5)
>>>> Extended Capabilities: 0x00 (octet 6)
>>>> Extended Capabilities: 0x01 (octet 7)
>>>> Extended Capabilities: 0x0040 (octets 8 & 9)
>>>> Extended Capabilities: 0x40 (octet 10)
>>>> Tag: Vendor Specific: Microsoft Corp.: WMM/WME: Parameter Element
>>>>
>>>> I reviewed several driver implementations, and none of them seem to
>>>> advertise this capability. I also could not find any definition for this
>>>> bit in `include/linux/ieee80211.h`, unlike many other capability bits that
>>>> are defined (e.g. `WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING` or
>>>> `WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT`). From what I can see, none of the
>>>> `mac80211`‑based drivers appear to support this feature, is that correct?
>>>>
>>>> Additionally, I want to confirm whether my understanding of the feature is
>>>> accurate: the 20/40 Coexistence mechanism implements the “good neighbor”
>>>> policy, meaning that an AP using a 40 MHz channel in the 2.4 GHz band must
>>>> fall back to 20 MHz when it detects an overlapping BSS (OBSS). Is that
>>>> right?
>>>>
>>>> Any clarification would be greatly appreciated.
>>>>
>>>>
>>>> Best regards
>>>> Alexander Wilhelm
>>>>
>>>
>>> From my understanding, this is implemented in userspace (i.e. hostapd), at least in upstream code.
>>
>> I've alredy seen the code in `hostapd` that implements a fallback to 20
>> MHz. But that implementation is based only on scan results, not on 20/40
>> coexistence feautre. Here the snippet from `ieee80211n_check_scan`
>> function:
>>
>> [...]
>> if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A)
>> oper40 = ieee80211n_check_40mhz_5g(iface, scan_res);
>> else
>> oper40 = ieee80211n_check_40mhz_2g4(iface, scan_res);
>> wpa_scan_results_free(scan_res);
>>
>> iface->secondary_ch = iface->conf->secondary_channel;
>> if (!oper40) {
>> wpa_printf(MSG_INFO, "20/40 MHz operation not permitted on "
>> "channel pri=%d sec=%d based on overlapping BSSes",
>> iface->conf->channel,
>> iface->conf->channel +
>> iface->conf->secondary_channel * 4);
>> iface->conf->secondary_channel = 0;
>> if (iface->drv_flags & WPA_DRIVER_FLAGS_HT_2040_COEX) {
>> /*
>> * TODO: Could consider scheduling another scan to check
>> * if channel width can be changed if no coex reports
>> * are received from associating stations.
>> */
>> }
>> }
>> [...]
>
> There are ways the BSS can switch from 40 MHz to 20 MHz operation beyond just scan results.
>
> For example, a newly-associated, 40 MHz intolerant station could cause hostapd to reconfigure to 20
> MHz operation, assuming the WPA_DRIVER_FLAGS_HT_2040_COEX is set by radio driver capabilities.
>
> Directly handling association:
>
> handle_assoc()
> -> update_ht_state()
> -> update_sta_ht()
> -> ht40_intolerant_add()
> -> ieee802_11_set_beacons()
> -> ieee802_11_set_beacon()
> -> __ieee802_11_set_beacon()
> -> ieee802_11_build_ap_params()
> -> hostapd_build_ap_extra_ies()
> -> hostapd_eid_ext_capab()
> -> hostapd_ext_capab_byte()
>
>
> Or from driver callback:
>
> hostapd_notif_assoc()
> -> ht40_intolerant_add()
> -> ieee802_11_set_beacons()
> ...
> -> hostapd_ext_capab_byte()
>
>
> Additionally, receipt of a 20/40 MHz Coex Management Action frame in 'hostapd_2040_coex_action()'
> may trigger the AP to reconfigure to 20 MHz using a similar code path.
>
> For testing, wpa_supplicant supports configuring 40 MHz intolerant stations. See below from its
> config file reference [1]:
>
> # ht40_intolerant: Whether 40 MHz intolerant should be indicated.
> # 0 = 40 MHz tolerant (default)
> # 1 = 40 MHz intolerant
>
> I've uploaded some example hostapd and wpa_supplicant configs here [2], if you'd like something to
> reference or play around with. Associating the intolerant station config should trigger hostapd to
> switch from 40 MHz to 20 MHz with this configuration, assuming radio driver support as mentioned above.
>
> [1] https://git.w1.fi/cgit/hostap/plain/wpa_supplicant/wpa_supplicant.conf
> [2] https://codeberg.org/a-gavin/hostap-confs/src/branch/main/open/20-40MHz-bss-coexistence
Since you mentioned packet capture analysis, to observe a 40 MHz BSS switch to 20 MHz operation, pay
close attention to the HT Operation IE in the Beacon frames.
Assuming you're using Wireshark, you should see the 'HT Operation Information Subset (1 of 3)'
section switch from showing 'Supported channel width: Channel of any width supported' to '20 MHz
channel width only'. I'm sure other programs are similar.
Using the 40 MHz intolerant association example, you should see this switch immediately after
station association.
40 MHz operation:
Tag: HT Operation
Tag Number: HT Operation (61)
Tag length: 22
Primary Channel: 1
HT Operation Information Subset (1 of 3): 0x05
.... ..01 = Secondary channel offset: Secondary channel is above the primary channel (0x1)
.... .1.. = Supported channel width: Channel of any width supported
.... 0... = Reduced Interframe Spacing (RIFS): Prohibited
0000 .... = Reserved: 0x0
HT Operation Information Subset (2 of 3): 0x0000
HT Operation Information Subset (3 of 3): 0x0000
Rx Supported Modulation and Coding Scheme Set: Basic MCS Set
20 MHz operation:
Tag: HT Operation
Tag Number: HT Operation (61)
Tag length: 22
Primary Channel: 1
HT Operation Information Subset (1 of 3): 0x00
.... ..00 = Secondary channel offset: No secondary channel (0x0)
.... .0.. = Supported channel width: 20 MHz channel width only
.... 0... = Reduced Interframe Spacing (RIFS): Prohibited
0000 .... = Reserved: 0x0
HT Operation Information Subset (2 of 3): 0x0000
HT Operation Information Subset (3 of 3): 0x0000
Basic HT-MCS Set: Reserved: 00000000000000000000000000000000
Hope this helps!
>>> In hostapd, the '20/40 BSS Coexistence Management Support' bit you reference is set in the
>>> 'hostapd_ext_capab_byte()' function in 'src/ap/ieee802_11_shared.c' when 'obss_interval' is set in
>>> the AP config file.
>>>
>>> For more information on the 'obss_interval' config item see the following from the hostapd config
>>> reference here [1]:
>>>
>>> # If set non-zero, require stations to perform scans of overlapping
>>> # channels to test for stations which would be affected by 40 MHz traffic.
>>> # This parameter sets the interval in seconds between these scans. Setting this
>>> # to non-zero allows 2.4 GHz band AP to move dynamically to a 40 MHz channel if
>>> # no co-existence issues with neighboring devices are found.
>>> #obss_interval=0
>>
>> Great, I found the the configuration in my `hostapd` version and the code
>> that implements the handling of this kind of management frames. I'll give
>> the configuration option a try.
>>
>>> The following sections from the 802.11 standard may be helpful to understand this topic in more
>>> depth, although I'm sure there's information online that may be easier to digest:
>>>
>>> - 9.4.2.58 20/40 BSS Coexistence element
>>> - 9.4.2.54.2 HT Capability Information field
>>> - 11.15.12 Switching between 40 MHz and 20 MHz
>>>
>>> From 11.15.12:
>>>
>>> TE-B: On any of the channels of the channel set defined in Clause 18, reception of a 20/40 BSS
>>> Coexistence Management, Beacon, Probe Request, or Probe Response frame that contains a value of 1 in
>>> a Forty MHz Intolerant field and that has the Address 1 field equal to the receiving STA’s address
>>> or to a group address, with no further addressing qualifications.
>>
>> Thank you for the support, Alex. The information helps me a lot.
>>
>>
>> Best regards
>> Alexander Wilhelm
>
>