From 89367f0e7b403a89a0e2d139b04617ed610a1bc3 Mon Sep 17 00:00:00 2001 From: lain Date: Sat, 6 Jun 2026 19:31:22 +0300 Subject: [PATCH] Fix AX HE capability advertisement --- itl80211/openbsd/net80211/ieee80211.c | 14 +++++---- itl80211/openbsd/net80211/ieee80211_node.c | 26 ++++++++++++--- itl80211/openbsd/net80211/ieee80211_output.c | 33 +++++--------------- itlwm/ItlNetworkUserClient.cpp | 28 ++++++++++++++++- itlwm/hal_iwx/ItlIwx.cpp | 8 +++-- 5 files changed, 70 insertions(+), 39 deletions(-) diff --git a/itl80211/openbsd/net80211/ieee80211.c b/itl80211/openbsd/net80211/ieee80211.c index d7ec1024a..0d20e6663 100644 --- a/itl80211/openbsd/net80211/ieee80211.c +++ b/itl80211/openbsd/net80211/ieee80211.c @@ -752,12 +752,14 @@ ieee80211_media_change(struct _ifnet *ifp) /* * Committed to changes, install the MCS/rate setting. */ - ic->ic_flags &= ~(IEEE80211_F_HTON | IEEE80211_F_VHTON); + ic->ic_flags &= ~(IEEE80211_F_HTON | IEEE80211_F_VHTON | IEEE80211_F_HEON); ieee80211_configure_ampdu_tx(ic, 0); if ((ic->ic_modecaps & (1 << IEEE80211_MODE_11AX)) && (newphymode == IEEE80211_MODE_AUTO || newphymode == IEEE80211_MODE_11AX)) { - ic->ic_flags |= IEEE80211_F_HEON; + ic->ic_flags |= IEEE80211_F_HTON | IEEE80211_F_HEON; + if (ic->ic_modecaps & (1 << IEEE80211_MODE_11AC)) + ic->ic_flags |= IEEE80211_F_VHTON; ieee80211_configure_ampdu_tx(ic, 1); } else if ((ic->ic_modecaps & (1 << IEEE80211_MODE_11AC)) && (newphymode == IEEE80211_MODE_AUTO || @@ -770,7 +772,7 @@ ieee80211_media_change(struct _ifnet *ifp) ic->ic_flags |= IEEE80211_F_HTON; ieee80211_configure_ampdu_tx(ic, 1); } - if ((ic->ic_flags & (IEEE80211_F_HTON | IEEE80211_F_VHTON)) == 0) { + if ((ic->ic_flags & (IEEE80211_F_HTON | IEEE80211_F_VHTON | IEEE80211_F_HEON)) == 0) { ic->ic_fixed_mcs = -1; if (ic->ic_fixed_rate != i) { ic->ic_fixed_rate = i; /* set fixed tx rate */ @@ -1054,13 +1056,13 @@ const struct ieee80211_he_rateset ieee80211_std_ratesets_11ax[] = { { 12, { 72, 144, 216, 288, 432, 577, 649, 721, 865, 961, 1081, 1201 }, 1 }, /* MCS 0-11 2 SS, 80MHz channel */ - { 12, { 288, 577, 865, 1153, 1729, 2306, 2594, 2882, 3459, 3843, 4324, 4804 }, 2}, + { 12, { 144, 288, 432, 576, 865, 1153, 1297, 1441, 1729, 1922, 2162, 2402 }, 2}, /* MCS 0-11 1 SS, 160MHz channel */ - { 12, { 144, 288, 432, 564, 865, 1152, 1298, 1442, 1730, 1922, 2162, 2402 }, 1 }, + { 12, { 144, 288, 432, 576, 865, 1153, 1297, 1441, 1729, 1922, 2162, 2402 }, 1 }, /* MCS 0-11 2 SS, 160MHz channel */ - { 12, { 576, 1154, 1730, 2306, 3458, 4612, 5188, 5764, 6918, 7686, 8648, 9608 }, 2 }, + { 12, { 288, 576, 865, 1153, 1729, 2306, 2594, 2882, 3459, 3843, 4324, 4804 }, 2 }, }; /* diff --git a/itl80211/openbsd/net80211/ieee80211_node.c b/itl80211/openbsd/net80211/ieee80211_node.c index 000ef1202..f32b1d55a 100644 --- a/itl80211/openbsd/net80211/ieee80211_node.c +++ b/itl80211/openbsd/net80211/ieee80211_node.c @@ -2794,10 +2794,20 @@ ieee80211_setup_hecaps(struct ieee80211_node *ni, const uint8_t *data, uint8_t mcs_nss_size, he_ppe_size, he_total_size; mcs_nss_size = ieee80211_he_mcs_nss_size(he_cap_ie_elem); - he_ppe_size = - ieee80211_he_ppe_size(data[sizeof(ni->ni_he_cap_elem) + - mcs_nss_size], - he_cap_ie_elem->phy_cap_info); + if (len < sizeof(ni->ni_he_cap_elem) + mcs_nss_size) { + return; + } + + he_ppe_size = 0; + if (he_cap_ie_elem->phy_cap_info[6] & + IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT) { + if (len <= sizeof(ni->ni_he_cap_elem) + mcs_nss_size) + return; + he_ppe_size = + ieee80211_he_ppe_size(data[sizeof(ni->ni_he_cap_elem) + + mcs_nss_size], + he_cap_ie_elem->phy_cap_info); + } he_total_size = sizeof(ni->ni_he_cap_elem) + mcs_nss_size + he_ppe_size; @@ -2823,8 +2833,14 @@ ieee80211_setup_heop(struct ieee80211_node *ni, const uint8_t *data, uint8_t len) { struct ieee80211_he_operation *he_op_ie = (struct ieee80211_he_operation *)data; + uint8_t fixed_len = __offsetof(struct ieee80211_he_operation, optional); + uint32_t params; + + if (len < fixed_len) + return 0; - ni->ni_he_oper_params = le32toh(he_op_ie->he_oper_params); + params = le32toh(he_op_ie->he_oper_params); + ni->ni_he_oper_params = params; ni->ni_he_oper_nss_set = le16toh(he_op_ie->he_mcs_nss_set); bzero(&ni->ni_he_optional, sizeof(ni->ni_he_optional)); if (len > __offsetof(struct ieee80211_he_operation, optional)) { diff --git a/itl80211/openbsd/net80211/ieee80211_output.c b/itl80211/openbsd/net80211/ieee80211_output.c index ec8e448a2..126e88aee 100644 --- a/itl80211/openbsd/net80211/ieee80211_output.c +++ b/itl80211/openbsd/net80211/ieee80211_output.c @@ -1260,14 +1260,12 @@ ieee80211_add_vhtcaps(uint8_t *frm, struct ieee80211com *ic) uint8_t * ieee80211_add_hecaps(uint8_t *frm, struct ieee80211com *ic) { - uint8_t nss_size, ie_len; + uint8_t nss_size, ppe_size; uint8_t *orig_pos = frm; nss_size = ieee80211_he_mcs_nss_size(&ic->ic_he_cap_elem); - ie_len = 2 + 1 + - sizeof(ic->ic_he_cap_elem) + nss_size + - ieee80211_he_ppe_size(ic->ic_ppe_thres[0], - ic->ic_he_cap_elem.phy_cap_info); + ppe_size = ieee80211_he_ppe_size(ic->ic_ppe_thres[0], + ic->ic_he_cap_elem.phy_cap_info); *frm++ = IEEE80211_ELEMID_EXTENSION; frm++; /* We'll set the size later below */ @@ -1282,29 +1280,14 @@ ieee80211_add_hecaps(uint8_t *frm, struct ieee80211com *ic) /* Check if PPE Threshold should be present */ if ((ic->ic_he_cap_elem.phy_cap_info[6] & - IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT) == 0) + IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT) == 0) { + orig_pos[1] = (frm - orig_pos) - 2; return frm; - - /* - * Calculate how many PPET16/PPET8 pairs are to come. Algorithm: - * (NSS_M1 + 1) x (num of 1 bits in RU_INDEX_BITMASK) - */ - nss_size = hweight8(ic->ic_ppe_thres[0] & - IEEE80211_PPE_THRES_RU_INDEX_BITMASK_MASK); - - nss_size *= (1 + ((ic->ic_ppe_thres[0] & IEEE80211_PPE_THRES_NSS_MASK) >> - IEEE80211_PPE_THRES_NSS_POS)); - - /* - * Each pair is 6 bits, and we need to add the 7 "header" bits to the - * total size. - */ - nss_size = (nss_size * IEEE80211_PPE_THRES_INFO_PPET_SIZE * 2) + 7; - nss_size = DIV_ROUND_UP(nss_size, 8); + } /* Copy PPE Thresholds */ - memcpy(frm, &ic->ic_ppe_thres, nss_size); - frm += nss_size; + memcpy(frm, &ic->ic_ppe_thres, ppe_size); + frm += ppe_size; orig_pos[1] = (frm - orig_pos) - 2; return frm; diff --git a/itlwm/ItlNetworkUserClient.cpp b/itlwm/ItlNetworkUserClient.cpp index d9e106fbd..8b65d2b67 100644 --- a/itlwm/ItlNetworkUserClient.cpp +++ b/itlwm/ItlNetworkUserClient.cpp @@ -150,7 +150,33 @@ sSTA_INFO(OSObject* target, void* data, bool isSet) st->rssi = -(0 - IWM_MIN_DBM - ic_bss->ni_rssi); st->noise = that->fDriver->fHalService->getDriverInfo()->getBSSNoise(); sgi = ieee80211_node_supports_sgi(ic_bss); - if (ic->ic_curmode == IEEE80211_MODE_11AC) { + if (ic->ic_curmode == IEEE80211_MODE_11AX) { + switch (ic_bss->ni_chw) { + case IEEE80211_CHAN_WIDTH_40: + index = IEEE80211_HE_RATESET_SISO_40; + break; + case IEEE80211_CHAN_WIDTH_80: + index = IEEE80211_HE_RATESET_SISO_80; + break; + case IEEE80211_CHAN_WIDTH_80P80: + case IEEE80211_CHAN_WIDTH_160: + index = IEEE80211_HE_RATESET_SISO_160; + break; + default: + index = IEEE80211_HE_RATESET_SISO; + break; + } + if (ic_bss->ni_rx_nss > 1) + index++; + + const struct ieee80211_he_rateset *rs = &ieee80211_std_ratesets_11ax[index]; + int mcs = ic_bss->ni_txmcs; + if (mcs < 0) + mcs = 0; + else if (mcs >= rs->nrates) + mcs = rs->nrates - 1; + st->rate = rs->rates[mcs] / 2; + } else if (ic->ic_curmode == IEEE80211_MODE_11AC) { if (sgi) { index += 1; } diff --git a/itlwm/hal_iwx/ItlIwx.cpp b/itlwm/hal_iwx/ItlIwx.cpp index 32b59180f..9f7f2a426 100644 --- a/itlwm/hal_iwx/ItlIwx.cpp +++ b/itlwm/hal_iwx/ItlIwx.cpp @@ -4053,7 +4053,7 @@ iwx_setup_he_rates(struct iwx_softc *sc) struct ieee80211com *ic = &sc->sc_ic; /* enable 11ax support */ -// ic->ic_flags |= IEEE80211_F_HEON; + ic->ic_flags |= IEEE80211_F_HEON; ic->ic_he_cap_elem = { .mac_cap_info[0] = @@ -4076,6 +4076,9 @@ iwx_setup_he_rates(struct iwx_softc *sc) IEEE80211_HE_MAC_CAP5_UL_2x996_TONE_RU | IEEE80211_HE_MAC_CAP5_HE_DYNAMIC_SM_PS | IEEE80211_HE_MAC_CAP5_HT_VHT_TRIG_FRAME_RX, + .phy_cap_info[0] = + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G | + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G, .phy_cap_info[1] = IEEE80211_HE_PHY_CAP1_PREAMBLE_PUNC_RX_MASK | IEEE80211_HE_PHY_CAP1_DEVICE_CLASS_A | @@ -4134,7 +4137,8 @@ iwx_setup_he_rates(struct iwx_softc *sc) * PPET8 set to 7 */ uint8_t ppe_thres[] = {0x61, 0x1c, 0xc7, 0x71}; - memcpy(ic->ic_ppe_thres, ppe_thres, sizeof(ic->ic_ppe_thres)); + memset(ic->ic_ppe_thres, 0, sizeof(ic->ic_ppe_thres)); + memcpy(ic->ic_ppe_thres, ppe_thres, sizeof(ppe_thres)); } #define IWX_MAX_RX_BA_SESSIONS 16