From: Stefan Sperling Subject: fix 802.11 mode selection in ieee80211_node_join_bss() To: tech@openbsd.org Date: Fri, 25 Jul 2025 11:19:16 +0200 When we are joining a new BSS (i.e. a new access point) while roaming, we might have to switch bands from 2 GHz to 5 GHz or vice-versa. This works, but there is a cosmetic wrinkle where the wrong mode will be displayed in ifconfig. For example, starting out on a 2 GHz AP in 11g mode: media: IEEE802.11 autoselect (DS1 mode 11g) status: active ieee80211: join ... chan 13 Then roaming to a 5 GHz AP, we switch to the 5GHz channel but the mode displayed is still "11g": media: IEEE802.11 autoselect (OFDM48 mode 11g) status: active ieee80211: join ... chan 64 The bug is in ieee80211_node_join_bss(), where ieee80211_chan2mode() is used to select the new mode. This function does not actually change the mode if ic_curmode is currently set to anything other than AUTO (which is bad and should probably be fixed in a similar way as below, but I do not want to change chan2mode's parameters and audit and adjust all its callers right now). The patch below fixes this by selecting the new mode correctly based on the new AP's channel, and the AP's support of 11g vs. 11b on 2 GHz. Now we switch into the correct mode when roaming with qwx: media: IEEE802.11 autoselect (OFDM48 mode 11a) status: active ieee80211: join ... chan 64 This issue didn't stand out on intel drivers because if the AP uses 11n or 11ac then this bug is masked by switching mode again to 11n or 11ac after association. ok? M sys/net80211/ieee80211_node.c | 7+ 3- 1 file changed, 7 insertions(+), 3 deletions(-) commit - d64e5fcced832f2a47ed1896e35987cba9887e42 commit + 72dcd758474af3c9b355067a177acaf1811ad6c7 blob - c6ca10f5df7c13a01d8cddd8f552e3abf2b41184 blob + 41dfa6f1dc184b2959babd49eface11c548e38b0 --- sys/net80211/ieee80211_node.c +++ sys/net80211/ieee80211_node.c @@ -1303,7 +1303,13 @@ ieee80211_node_join_bss(struct ieee80211com *ic, struc uint32_t assoc_fail = 0; /* Reinitialize media mode and channels if needed. */ - mode = ieee80211_chan2mode(ic, selbs->ni_chan); + if (IEEE80211_IS_CHAN_5GHZ(selbs->ni_chan)) + mode = IEEE80211_MODE_11A; + else if (ieee80211_iserp_sta(selbs)) + mode = IEEE80211_MODE_11G; + else + mode = IEEE80211_MODE_11B; + if (mode != ic->ic_curmode) ieee80211_setmode(ic, mode); @@ -1317,8 +1323,6 @@ ieee80211_node_join_bss(struct ieee80211com *ic, struc ni = ic->ic_bss; ni->ni_assoc_fail |= assoc_fail; - ic->ic_curmode = ieee80211_chan2mode(ic, ni->ni_chan); - /* Make sure we send valid rates in an association request. */ if (ic->ic_opmode == IEEE80211_M_STA) ieee80211_fix_rate(ic, ni,