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 <quic_alokad@quicinc.com> Signed-off-by: Ramanathan Choodamani <quic_rchoodam@quicinc.com>
This commit is contained in:
parent
7618269ec6
commit
46a5d989d4
4 changed files with 100 additions and 9 deletions
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in a new issue