From: Aloka Dixit Date: Tue, 14 Mar 2023 04:59:17 +0000 (-0700) Subject: EHT: Downgrade bandwidths for VHT and HE when using puncturing X-Git-Tag: hostap_2_11~1232 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=46a5d989d4c187727c8a07968be8818235e51364;p=thirdparty%2Fhostap.git EHT: Downgrade bandwidths for VHT and HE when using puncturing Legacy modes (VHT, HE) should advertise downgraded bandwidth if RU puncturing is enabled in EHT mode. This is required for the legacy stations which cannot parse the EHT Operation elements hence do not support EHT RU puncturing. Signed-off-by: Aloka Dixit Signed-off-by: Ramanathan Choodamani --- diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index fff557d8e..8304e3c26 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -7027,4 +7027,73 @@ u8 * hostapd_eid_mbssid(struct hostapd_data *hapd, u8 *eid, u8 *end, return eid; } + +static void punct_update_legacy_bw_80(u8 bitmap, u8 pri_chan, u8 *seg0) +{ + u8 first_chan = *seg0 - 6, sec_chan; + + switch (bitmap) { + case 0x6: + *seg0 = 0; + return; + case 0x8: + case 0x4: + case 0x2: + case 0x1: + case 0xC: + case 0x3: + if (pri_chan < *seg0) + *seg0 -= 4; + else + *seg0 += 4; + break; + } + + if (pri_chan < *seg0) + sec_chan = pri_chan + 4; + else + sec_chan = pri_chan - 4; + + if (bitmap & BIT((sec_chan - first_chan) / 4)) + *seg0 = 0; +} + + +static void punct_update_legacy_bw_160(u8 bitmap, u8 pri, + enum oper_chan_width *width, u8 *seg0) +{ + if (pri < *seg0) { + *seg0 -= 8; + if (bitmap & 0x0F) { + *width = 0; + punct_update_legacy_bw_80(bitmap & 0xF, pri, seg0); + } + } else { + *seg0 += 8; + if (bitmap & 0xF0) { + *width = 0; + punct_update_legacy_bw_80((bitmap & 0xF0) >> 4, pri, + seg0); + } + } +} + + +void punct_update_legacy_bw(u16 bitmap, u8 pri, enum oper_chan_width *width, + u8 *seg0, u8 *seg1) +{ + if (*width == CONF_OPER_CHWIDTH_80MHZ && (bitmap & 0xF)) { + *width = CONF_OPER_CHWIDTH_USE_HT; + punct_update_legacy_bw_80(bitmap & 0xF, pri, seg0); + } + + if (*width == CONF_OPER_CHWIDTH_160MHZ && (bitmap & 0xFF)) { + *width = CONF_OPER_CHWIDTH_80MHZ; + *seg1 = 0; + punct_update_legacy_bw_160(bitmap & 0xFF, pri, width, seg0); + } + + /* TODO: 320 MHz */ +} + #endif /* CONFIG_NATIVE_WINDOWS */ diff --git a/src/ap/ieee802_11.h b/src/ap/ieee802_11.h index 5f443fcb8..1e4c843f6 100644 --- a/src/ap/ieee802_11.h +++ b/src/ap/ieee802_11.h @@ -18,6 +18,7 @@ struct ieee80211_vht_capabilities; struct ieee80211_mgmt; struct radius_sta; enum ieee80211_op_mode; +enum oper_chan_width; int ieee802_11_mgmt(struct hostapd_data *hapd, const u8 *buf, size_t len, struct hostapd_frame_info *fi); @@ -222,5 +223,7 @@ u8 * hostapd_eid_mbssid(struct hostapd_data *hapd, u8 *eid, u8 *end, unsigned int frame_stype, u8 elem_count, u8 **elem_offset, const u8 *known_bss, size_t known_bss_len); +void punct_update_legacy_bw(u16 bitmap, u8 pri_chan, + enum oper_chan_width *width, u8 *seg0, u8 *seg1); #endif /* IEEE802_11_H */ diff --git a/src/ap/ieee802_11_he.c b/src/ap/ieee802_11_he.c index 12273c34c..548a44821 100644 --- a/src/ap/ieee802_11_he.c +++ b/src/ap/ieee802_11_he.c @@ -219,10 +219,20 @@ u8 * hostapd_eid_he_operation(struct hostapd_data *hapd, u8 *eid) pos += 6; /* skip the fixed part */ if (is_6ghz_op_class(hapd->iconf->op_class)) { + enum oper_chan_width oper_chwidth = + hostapd_get_oper_chwidth(hapd->iconf); u8 seg0 = hapd->iconf->he_oper_centr_freq_seg0_idx; u8 seg1 = hostapd_get_oper_centr_freq_seg1_idx(hapd->iconf); u8 control; +#ifdef CONFIG_IEEE80211BE + if (hapd->iconf->punct_bitmap) { + punct_update_legacy_bw(hapd->iconf->punct_bitmap, + hapd->iconf->channel, + &oper_chwidth, &seg0, &seg1); + } +#endif /* CONFIG_IEEE80211BE */ + if (!seg0) seg0 = hapd->iconf->channel; @@ -253,7 +263,7 @@ u8 * hostapd_eid_he_operation(struct hostapd_data *hapd, u8 *eid) *pos++ = control; /* Channel Center Freq Seg0/Seg1 */ - if (hapd->iconf->he_oper_chwidth == 2) { + if (oper_chwidth == 2) { /* * Seg 0 indicates the channel center frequency index of * the 160 MHz channel. diff --git a/src/ap/ieee802_11_vht.c b/src/ap/ieee802_11_vht.c index 681b6d78f..db615a38b 100644 --- a/src/ap/ieee802_11_vht.c +++ b/src/ap/ieee802_11_vht.c @@ -75,6 +75,10 @@ u8 * hostapd_eid_vht_operation(struct hostapd_data *hapd, u8 *eid) { struct ieee80211_vht_operation *oper; u8 *pos = eid; + enum oper_chan_width oper_chwidth = + hostapd_get_oper_chwidth(hapd->iconf); + u8 seg0 = hapd->iconf->vht_oper_centr_freq_seg0_idx; + u8 seg1 = hapd->iconf->vht_oper_centr_freq_seg1_idx; if (is_6ghz_op_class(hapd->iconf->op_class)) return eid; @@ -85,18 +89,24 @@ u8 * hostapd_eid_vht_operation(struct hostapd_data *hapd, u8 *eid) oper = (struct ieee80211_vht_operation *) pos; os_memset(oper, 0, sizeof(*oper)); +#ifdef CONFIG_IEEE80211BE + if (hapd->iconf->punct_bitmap) { + punct_update_legacy_bw(hapd->iconf->punct_bitmap, + hapd->iconf->channel, + &oper_chwidth, &seg0, &seg1); + } +#endif /* CONFIG_IEEE80211BE */ + /* * center freq = 5 GHz + (5 * index) * So index 42 gives center freq 5.210 GHz * which is channel 42 in 5G band */ - oper->vht_op_info_chan_center_freq_seg0_idx = - hapd->iconf->vht_oper_centr_freq_seg0_idx; - oper->vht_op_info_chan_center_freq_seg1_idx = - hapd->iconf->vht_oper_centr_freq_seg1_idx; + oper->vht_op_info_chan_center_freq_seg0_idx = seg0; + oper->vht_op_info_chan_center_freq_seg1_idx = seg1; - oper->vht_op_info_chwidth = hapd->iconf->vht_oper_chwidth; - if (hapd->iconf->vht_oper_chwidth == CONF_OPER_CHWIDTH_160MHZ) { + oper->vht_op_info_chwidth = oper_chwidth; + if (oper_chwidth == CONF_OPER_CHWIDTH_160MHZ) { /* * Convert 160 MHz channel width to new style as interop * workaround. @@ -109,8 +119,7 @@ u8 * hostapd_eid_vht_operation(struct hostapd_data *hapd, u8 *eid) oper->vht_op_info_chan_center_freq_seg0_idx -= 8; else oper->vht_op_info_chan_center_freq_seg0_idx += 8; - } else if (hapd->iconf->vht_oper_chwidth == - CONF_OPER_CHWIDTH_80P80MHZ) { + } else if (oper_chwidth == CONF_OPER_CHWIDTH_80P80MHZ) { /* * Convert 80+80 MHz channel width to new style as interop * workaround.