From 7377742385c93887bc125cecc21204387112517d Mon Sep 17 00:00:00 2001 From: Balamurugan Mahalingam Date: Tue, 16 Aug 2022 17:53:38 -0700 Subject: [PATCH] hostapd: Update 11be EHT elements to Draft 2.0 version Update the EHT operations elements to Draft 2.0 and fix interop issues with stations Signed-off-by: Balamurugan Mahalingam --- hostapd/config_file.c | 2 ++ src/ap/ap_config.h | 9 +++++++++ src/ap/beacon.c | 5 +++++ src/ap/ctrl_iface_ap.c | 6 ++++-- src/ap/ieee802_11.c | 2 ++ src/ap/ieee802_11_eht.c | 34 ++++++++++++++++++++++++++++------ src/common/ieee802_11_defs.h | 35 +++++++++++++++++++++++------------ wpa_supplicant/mesh_mpm.c | 10 +++++----- 8 files changed, 78 insertions(+), 25 deletions(-) diff --git a/hostapd/config_file.c b/hostapd/config_file.c index 501d30c..d896d67 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -4689,6 +4689,8 @@ static int hostapd_config_fill(struct hostapd_config *conf, conf->eht_oper_chwidth = atoi(pos); } else if (os_strcmp(buf, "eht_oper_centr_freq_seg0_idx") == 0) { conf->eht_oper_centr_freq_seg0_idx = atoi(pos); + } else if (os_strcmp(buf, "eht_oper_centr_freq_seg1_idx") == 0) { + conf->eht_oper_centr_freq_seg1_idx = atoi(pos); } else if (os_strcmp(buf, "eht_su_beamformer") == 0) { conf->eht_phy_capab.su_beamformer = atoi(pos); } else if (os_strcmp(buf, "eht_su_beamformee") == 0) { diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index f6d1d56..83ba76c 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -1144,6 +1144,7 @@ struct hostapd_config { #ifdef CONFIG_IEEE80211BE u8 eht_oper_chwidth; u8 eht_oper_centr_freq_seg0_idx; + u8 eht_oper_centr_freq_seg1_idx; struct eht_phy_capabilities_info eht_phy_capab; #endif /* CONFIG_IEEE80211BE */ @@ -1227,6 +1228,10 @@ hostapd_set_oper_centr_freq_seg0_idx(struct hostapd_config *conf, static inline u8 hostapd_get_oper_centr_freq_seg1_idx(struct hostapd_config *conf) { +#ifdef CONFIG_IEEE80211BE + if (conf->ieee80211be) + return conf->eht_oper_centr_freq_seg1_idx; +#endif /* CONFIG_IEEE80211BE */ #ifdef CONFIG_IEEE80211AX if (conf->ieee80211ax) return conf->he_oper_centr_freq_seg1_idx; @@ -1238,6 +1243,10 @@ static inline void hostapd_set_oper_centr_freq_seg1_idx(struct hostapd_config *conf, u8 oper_centr_freq_seg1_idx) { +#ifdef CONFIG_IEEE80211BE + if (conf->ieee80211be) + conf->eht_oper_centr_freq_seg1_idx = oper_centr_freq_seg1_idx; +#endif /* CONFIG_IEEE80211BE */ #ifdef CONFIG_IEEE80211AX if (conf->ieee80211ax) conf->he_oper_centr_freq_seg1_idx = oper_centr_freq_seg1_idx; diff --git a/src/ap/beacon.c b/src/ap/beacon.c index 023729c..9536e76 100644 --- a/src/ap/beacon.c +++ b/src/ap/beacon.c @@ -643,6 +643,9 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd, if (hapd->iconf->ieee80211be && !hapd->conf->disable_11be) { buflen += hostapd_eid_eht_capab_len(hapd, IEEE80211_MODE_AP); buflen += (3 + sizeof(struct ieee80211_eht_operation)); + if (hapd->iconf->ru_punct_bitmap) + buflen += DISABLED_SUBCHANNEL_BITMAP_BYTES_SIZE; + } #endif /* CONFIG_IEEE80211BE */ @@ -1759,6 +1762,8 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd, if (hapd->iconf->ieee80211be && !hapd->conf->disable_11be) { tail_len += hostapd_eid_eht_capab_len(hapd, IEEE80211_MODE_AP); tail_len += (3 + sizeof(struct ieee80211_eht_operation)); + if (hapd->iconf->ru_punct_bitmap) + tail_len += DISABLED_SUBCHANNEL_BITMAP_BYTES_SIZE; } #endif /* CONFIG_IEEE80211BE */ diff --git a/src/ap/ctrl_iface_ap.c b/src/ap/ctrl_iface_ap.c index 62db273..b697ad2 100644 --- a/src/ap/ctrl_iface_ap.c +++ b/src/ap/ctrl_iface_ap.c @@ -1065,9 +1065,11 @@ int hostapd_ctrl_iface_status(struct hostapd_data *hapd, char *buf, if (iface->conf->ieee80211be && !hapd->conf->disable_11be) { ret = os_snprintf(buf + len, buflen - len, "eht_oper_chwidth=%d\n" - "eht_oper_centr_freq_seg0_idx=%d\n", + "eht_oper_centr_freq_seg0_idx=%d\n" + "eht_oper_centr_freq_seg1_idx=%d\n", iface->conf->eht_oper_chwidth, - iface->conf->eht_oper_centr_freq_seg0_idx); + iface->conf->eht_oper_centr_freq_seg0_idx, + iface->conf->eht_oper_centr_freq_seg1_idx); if (os_snprintf_error(buflen - len, ret)) return len; len += ret; diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index b4efc17..8a6fed8 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -5106,6 +5106,8 @@ static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta, if (hapd->iconf->ieee80211be && !hapd->conf->disable_11be) { buflen += hostapd_eid_eht_capab_len(hapd, IEEE80211_MODE_AP); buflen += (3 + sizeof(struct ieee80211_eht_operation)); + if (hapd->iconf->ru_punct_bitmap) + buflen += DISABLED_SUBCHANNEL_BITMAP_BYTES_SIZE; } #endif /* CONFIG_IEEE80211BE */ diff --git a/src/ap/ieee802_11_eht.c b/src/ap/ieee802_11_eht.c index c7586ec..f54fee3 100644 --- a/src/ap/ieee802_11_eht.c +++ b/src/ap/ieee802_11_eht.c @@ -174,6 +174,7 @@ u8 * hostapd_eid_eht_operation(struct hostapd_data *hapd, u8 *eid, { struct hostapd_hw_modes *mode; struct ieee80211_eht_operation *oper; + struct eht_capabilities *eht_cap; u8 *pos = eid, oper_size = 0, chwidth; mode = hapd->iface->current_mode; @@ -185,15 +186,26 @@ u8 * hostapd_eid_eht_operation(struct hostapd_data *hapd, u8 *eid, oper_size = sizeof(struct ieee80211_eht_operation); *pos++ = WLAN_EID_EXTENSION; - *pos++ = 1 + oper_size; + + if (hapd->iconf->ru_punct_bitmap) + *pos++ = 1 + oper_size + DISABLED_SUBCHANNEL_BITMAP_BYTES_SIZE; + else + *pos++ = 1 + oper_size; + *pos++ = WLAN_EID_EXT_EHT_OPERATION; oper = (struct ieee80211_eht_operation *) pos; os_memset(oper, 0, sizeof(*oper)); - oper->ccfs = hostapd_get_oper_centr_freq_seg0_idx(hapd->iconf); - if (!oper->ccfs) - oper->ccfs = hapd->iconf->channel; + eht_cap = &mode->eht_capab[opmode]; + oper->ehtop_params |= EHTOP_PARAMS_EHTOP_INFORMATION_PRESENT; + oper->ccfs0 = hostapd_get_oper_centr_freq_seg0_idx(hapd->iconf); + oper->ccfs1 = hostapd_get_oper_centr_freq_seg1_idx(hapd->iconf); + memcpy(&oper->mcs_nss_supported, &eht_cap->mcs, + EHT_PHYCAP_MCS_NSS_LEN_20MHZ_ONLY); + + if (!oper->ccfs0) + oper->ccfs0 = hapd->iconf->channel; if (is_6ghz_op_class(hapd->iconf->op_class)) chwidth = op_class_to_ch_width(hapd->iconf->op_class); @@ -209,6 +221,14 @@ u8 * hostapd_eid_eht_operation(struct hostapd_data *hapd, u8 *eid, switch (chwidth) { case CHANWIDTH_320MHZ: oper->width = EHT_OPERATION_CHANNEL_WIDTH_320MHZ; + if (!oper->ccfs1) { + /* CCFS0 points to center channel frequency in config */ + oper->ccfs1 = oper->ccfs0; + if (hapd->iconf->channel < oper->ccfs0) + oper->ccfs0 = oper->ccfs1 - 16; + else + oper->ccfs0 = oper->ccfs1 + 16; + } break; case CHANWIDTH_160MHZ: oper->width = EHT_OPERATION_CHANNEL_WIDTH_160MHZ; @@ -246,8 +266,10 @@ u8 * hostapd_eid_eht_operation(struct hostapd_data *hapd, u8 *eid, } if (hapd->iconf->ru_punct_bitmap) { - oper->disable_sub_chan_bitmap_present = 1; - oper->disabled_subchannel_bitmap = host_to_le16(hapd->iconf->ru_punct_bitmap); + oper->ehtop_params |= EHTOP_PARAMS_DISABLED_SUBCHANNEL_BITMAP_PRESENT; + oper->disabled_subchannel_bitmap[0] = + host_to_le16(hapd->iconf->ru_punct_bitmap); + pos += DISABLED_SUBCHANNEL_BITMAP_BYTES_SIZE; } pos += oper_size; diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h index 752f65f..766ec1d 100644 --- a/src/common/ieee802_11_defs.h +++ b/src/common/ieee802_11_defs.h @@ -2462,28 +2462,39 @@ struct ieee80211_eht_capabilities { u8 optional[71]; } STRUCT_PACKED; -#define EHT_OPERATION_CCFS_SHIFT 4 /* * struct ieee80211_eht_operation - eht operation element * * This structure is the "EHT Operation Element" fields as - * described in P802.11be_D1.4 section 9.4.2.311 - * - * FIXME: The spec is unclear how big the fields are, and doesn't - * indicate the "Disabled Subchannel Bitmap Present" in the - * structure (Figure 9-1002a) at all ... + * described in P802.11be_D2.0 section 9.4.2.311 */ + +#define EHTOP_PARAMS_EHTOP_INFORMATION_PRESENT BIT(0) +#define EHTOP_PARAMS_DISABLED_SUBCHANNEL_BITMAP_PRESENT BIT(1) +#define EHTOP_PARAMS_EHT_DEFAULT_PE_DURATION BIT(2) +#define EHTOP_PARAMS_GROUP_ADDRESSED_BU_INDICATION_LIMIT BIT(3) +#define EHTOP_PARAMS_GROUP_ADDRESSED_BU_INDICATION_EXPONENT BIT(4) + +#define DISABLED_SUBCHANNEL_BITMAP_BYTES_SIZE 2 + +struct ieee80211_eht_mcs_nss_set { + u8 max_tx_mcs_nss_0_7; + u8 max_tx_mcs_nss_8_9; + u8 max_tx_mcs_nss_10_11; + u8 max_tx_mcs_nss_12_13; +} STRUCT_PACKED; + struct ieee80211_eht_operation { + u8 ehtop_params; + struct ieee80211_eht_mcs_nss_set mcs_nss_supported; u8 width:3, reserved:5; - u8 ccfs; - u8 disable_sub_chan_bitmap_present:1, - reserved2:7; - le16 disabled_subchannel_bitmap; - - /* Add puncture pattern here when supported */ + u8 ccfs0; + u8 ccfs1; + le16 disabled_subchannel_bitmap[0]; } STRUCT_PACKED; + #define EHT_OPERATION_CHANNEL_WIDTH_20MHZ 0 #define EHT_OPERATION_CHANNEL_WIDTH_40MHZ 1 #define EHT_OPERATION_CHANNEL_WIDTH_80MHZ 2 diff --git a/wpa_supplicant/mesh_mpm.c b/wpa_supplicant/mesh_mpm.c index b527a77..c56801f 100644 --- a/wpa_supplicant/mesh_mpm.c +++ b/wpa_supplicant/mesh_mpm.c @@ -820,28 +820,28 @@ static struct sta_info * mesh_mpm_add_peer(struct wpa_supplicant *wpa_s, eht_oper_ie = (struct ieee80211_eht_operation *)elems->eht_operation; if (eht_oper_ie->width >= EHT_OPERATION_CHANNEL_WIDTH_80MHZ && - eht_oper_ie->disable_sub_chan_bitmap_present && + eht_oper_ie->ehtop_params & EHTOP_PARAMS_DISABLED_SUBCHANNEL_BITMAP_PRESENT && eht_oper_ie->disabled_subchannel_bitmap) { - params.ru_punct_bitmap = eht_oper_ie->disabled_subchannel_bitmap; + params.ru_punct_bitmap = eht_oper_ie->disabled_subchannel_bitmap[0]; /* Validate Peer's puncture bitmap and reset if invalid */ switch (eht_oper_ie->width) { case EHT_OPERATION_CHANNEL_WIDTH_80MHZ: bw = 80; - start_chan = eht_oper_ie->ccfs - 6; + start_chan = eht_oper_ie->ccfs0 - 6; if (!is_ru_punct_bitmap_valid(bw, (pri_chan - start_chan) / 4, params.ru_punct_bitmap, 0)) params.ru_punct_bitmap = 0; break; case EHT_OPERATION_CHANNEL_WIDTH_160MHZ: bw = 160; - start_chan = eht_oper_ie->ccfs - 14; + start_chan = eht_oper_ie->ccfs0 - 14; if (!is_ru_punct_bitmap_valid(bw, (pri_chan - start_chan) / 4, params.ru_punct_bitmap, 0)) params.ru_punct_bitmap = 0; break; case EHT_OPERATION_CHANNEL_WIDTH_320MHZ: bw = 320; - start_chan = eht_oper_ie->ccfs - 30; + start_chan = eht_oper_ie->ccfs0 - 30; if (!is_ru_punct_bitmap_valid(bw, (pri_chan - start_chan) / 4, params.ru_punct_bitmap, 0)) params.ru_punct_bitmap = 0; -- 2.17.1