From 340c9ab10eabb7a962f16cbb0a3abd492942ef57 Mon Sep 17 00:00:00 2001 From: Rameshkumar Sundaram Date: Wed, 25 May 2022 11:32:01 +0530 Subject: [PATCH] wpa_supplicant: add RU puncturing support Retrieve the driver support for RU puncturing which is advertised using the attribute NL80211_ATTR_RU_PUNCT_SUPP_BW. Value indicates the bandwidths in which puncturing is supported - 80 MHz, 160 MHz or 320 MHz. Absence of the attribute or the value 0 means the driver does not support this feature. Add New option 'ru_punct_bitmap' to configure RU puncturing bitmap and pass the configured bitmap to kernel via frequency params during join mesh if driver supports puncturing pattern for configured Bandwidth. Kernel will validate the pattern against spec allowed patterns (IEEE P802.11be/D1.5, Table 36-30) Parse EHT Operational IE of received mesh beacons and validate & and send Peer mesh node's RU puncturing pattern as part of station add command (NL80211_CMD_NEW_STATION). Signed-off-by: Rameshkumar Sundaram --- src/ap/hw_features.c | 9 +++++++++ src/drivers/driver.h | 7 +++++++ src/drivers/driver_nl80211.c | 6 ++++++ wpa_supplicant/ap.c | 5 +++-- wpa_supplicant/config.c | 2 ++ wpa_supplicant/config_file.c | 1 + wpa_supplicant/config_ssid.h | 6 ++++++ wpa_supplicant/mesh.c | 4 ++++ wpa_supplicant/mesh_mpm.c | 41 ++++++++++++++++++++++++++++++++++++++ wpa_supplicant/wpa_supplicant.c | 26 ++++++++++++++++++++++-- wpa_supplicant/wpa_supplicant.conf | 7 +++++++ wpa_supplicant/wpa_supplicant_i.h | 2 ++ 12 files changed, 112 insertions(+), 4 deletions(-) diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c index 1dcd0d0..f66c649 100644 --- a/src/ap/hw_features.c +++ b/src/ap/hw_features.c @@ -949,6 +949,15 @@ static int hostapd_is_usable_ru_punct_bitmap(struct hostapd_iface *iface) return 0; } +#ifdef CONFIG_MESH + if (iface->mconf != NULL) { + wpa_printf(MSG_DEBUG, + "%s: Mesh RU bitmap will be validated in kernel while joining the mesh network", + iface->bss[0]->conf->iface); + return 1; + } +#endif + switch (conf->eht_oper_chwidth) { case 0: wpa_printf(MSG_ERROR, diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 038379b..3c73e68 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -1291,6 +1291,12 @@ struct wpa_driver_associate_params { * Enable 320MHz BW - set it 1 to enable mesh 320MHz 6G */ int enable_320mhz_bw; + + /** + * RU puncturing bitmap - Each bit corresponds to a 20 MHz subchannel, + * lowest bit for the channel with the lowest frequency. + * Bit set to 1 indicates that the subchannel is punctured, otherwise active.*/ + u16 ru_punct_bitmap; }; enum hide_ssid { @@ -2381,6 +2387,7 @@ struct hostapd_sta_add_params { const u8 *supp_oper_classes; size_t supp_oper_classes_len; int support_p2p_ps; + u16 ru_punct_bitmap; }; struct mac_address { diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index a89097d..44b4330 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -5419,6 +5419,12 @@ static int wpa_driver_nl80211_sta_add(void *priv, nla_nest_end(msg, wme); } + if (params->ru_punct_bitmap) { + wpa_printf(MSG_DEBUG, " * eht ru puncturing bitmap=0x%x", params->ru_punct_bitmap); + if (nla_put_u16(msg, NL80211_ATTR_RU_PUNCT_BITMAP, params->ru_punct_bitmap)) + goto fail; + } + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); msg = NULL; if (ret) diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c index 30f33c4..2c55e95 100644 --- a/wpa_supplicant/ap.c +++ b/wpa_supplicant/ap.c @@ -417,9 +417,10 @@ int wpa_supplicant_conf_ap_ht(struct wpa_supplicant *wpa_s, conf->ieee80211ax = 1; if (mode->eht_capab[wpas_mode_to_ieee80211_mode( ssid->mode)].eht_supported && - ssid->eht) + ssid->eht) { conf->ieee80211be = 1; - + conf->ru_punct_bitmap = ssid->ru_punct_bitmap; + } if (mode->vht_capab && ssid->vht) { conf->ieee80211ac = 1; conf->vht_capab |= mode->vht_capab; diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index 502d3d6..f8945ee 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -2813,6 +2813,7 @@ static const struct parse_data ssid_fields[] = { { INT_RANGE(beacon_tx_mode, 1, 2)}, { INT_RANGE(enable_160mhz_bw, 0, 1)}, { INT_RANGE(enable_320mhz_bw, 0, 1)}, + { INT(ru_punct_bitmap) }, }; #undef OFFSET @@ -3330,6 +3331,7 @@ void wpa_config_set_network_defaults(struct wpa_ssid *ssid) ssid->mac_addr = -1; ssid->max_oper_chwidth = DEFAULT_MAX_OPER_CHWIDTH; ssid->beacon_tx_mode = DEFAULT_BEACON_TX_MODE; + ssid->ru_punct_bitmap = 0; } diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c index f47973b..f8a519b 100644 --- a/wpa_supplicant/config_file.c +++ b/wpa_supplicant/config_file.c @@ -894,6 +894,7 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid) INT(beacon_tx_mode); INT(enable_160mhz_bw); INT(enable_320mhz_bw); + INT(ru_punct_bitmap); #undef STR #undef INT #undef INT_DEF diff --git a/wpa_supplicant/config_ssid.h b/wpa_supplicant/config_ssid.h index 1704e0d..fdd40f9 100644 --- a/wpa_supplicant/config_ssid.h +++ b/wpa_supplicant/config_ssid.h @@ -1227,6 +1227,12 @@ struct wpa_ssid { * Enable 320MHz BW - set it 1 to enable mesh 320MHz 6G */ int enable_320mhz_bw; + + /** + * RU puncturing bitmap - Each bit corresponds to a 20 MHz subchannel, + * lowest bit for the channel with the lowest frequency. + * Bit set to 1 indicates that the subchannel is punctured, otherwise active.*/ + u16 ru_punct_bitmap; }; #endif /* CONFIG_SSID_H */ diff --git a/wpa_supplicant/mesh.c b/wpa_supplicant/mesh.c index 0372c08..231065d 100644 --- a/wpa_supplicant/mesh.c +++ b/wpa_supplicant/mesh.c @@ -411,6 +411,7 @@ static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s, ifmsh->num_bss = 1; ifmsh->enable_iface_cb = wpa_supplicant_mesh_enable_iface_cb; ifmsh->disable_iface_cb = wpa_supplicant_mesh_disable_iface_cb; + ifmsh->ru_punct_supp_bw = wpa_s->ru_punct_supp_bw; ifmsh->bss = os_calloc(wpa_s->ifmsh->num_bss, sizeof(struct hostapd_data *)); if (!ifmsh->bss) @@ -493,6 +494,9 @@ static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s, wpa_s->mesh_params->handle_dfs = true; } + if (ssid->eht) + conf->ru_punct_bitmap = freq->ru_punct_bitmap; + bss->iconf = conf; ifmsh->conf = conf; diff --git a/wpa_supplicant/mesh_mpm.c b/wpa_supplicant/mesh_mpm.c index d69af3f..8899434 100644 --- a/wpa_supplicant/mesh_mpm.c +++ b/wpa_supplicant/mesh_mpm.c @@ -728,6 +728,7 @@ static struct sta_info * mesh_mpm_add_peer(struct wpa_supplicant *wpa_s, struct hostapd_data *data = wpa_s->ifmsh->bss[0]; struct sta_info *sta; struct ieee80211_ht_operation *oper; + struct ieee80211_eht_operation *eht_oper_ie; int ret; if (elems->mesh_config_len >= 7 && @@ -811,6 +812,46 @@ static struct sta_info * mesh_mpm_add_peer(struct wpa_supplicant *wpa_s, params.he_6ghz_capab = sta->he_6ghz_capab; params.eht_capab = sta->eht_capab; params.eht_capab_len = sta->eht_capab_len; +#ifdef CONFIG_IEEE80211BE + if (elems->eht_operation && elems->eht_operation_len >= sizeof(*eht_oper_ie)) { + u16 bw = 0; + u16 start_chan = 0; + u16 pri_chan = wpa_s->ifmsh->conf->channel; + + 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->disabled_subchannel_bitmap) { + params.ru_punct_bitmap = eht_oper_ie->disabled_subchannel_bitmap; + /* 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; + 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; + 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; + if (!is_ru_punct_bitmap_valid(bw, (pri_chan - start_chan) / 4, + params.ru_punct_bitmap, 0)) + params.ru_punct_bitmap = 0; + break; + default: + params.ru_punct_bitmap = 0; + } + } + } +#endif /* CONFIG_IEEE80211BE */ params.flags |= WPA_STA_WMM; params.flags_mask |= WPA_STA_AUTHENTICATED; if (conf->security == MESH_CONF_SEC_NONE) { diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 226b1c9..e030f79 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -2904,6 +2904,27 @@ skip_to_6ghz: freq->eht_enabled = 0; } #endif /* CONFIG_EHT_OVERRIDES */ + freq->ru_punct_bitmap = ssid->ru_punct_bitmap; + freq->ru_punct_ofdma = 0; /* Default to disabled for mesh. */ + + if (ssid->ru_punct_bitmap && wpa_s->drv_capa_known) { + switch (chwidth) { + case CHANWIDTH_320MHZ: + break; + case CHANWIDTH_160MHZ: + if (wpa_s->ru_punct_supp_bw == CHANWIDTH_320MHZ) + freq->ru_punct_bitmap = 0; + break; + case CHANWIDTH_80MHZ: + if ((wpa_s->ru_punct_supp_bw == CHANWIDTH_160MHZ) || + (wpa_s->ru_punct_supp_bw == CHANWIDTH_320MHZ)) + freq->ru_punct_bitmap = 0; + break; + default: + freq->ru_punct_bitmap = 0; + } + } + if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq, freq->channel, ssid->enable_edmg, ssid->edmg_channel, freq->ht_enabled, @@ -2918,8 +2939,8 @@ skip_to_6ghz: *freq = vht_freq; - wpa_printf(MSG_DEBUG, "IBSS: VHT setup freq cf1 %d, cf2 %d, bw %d", - freq->center_freq1, freq->center_freq2, freq->bandwidth); + wpa_printf(MSG_DEBUG, "IBSS: VHT setup freq cf1 %d, cf2 %d, bw %d ru_punct_bitmap 0x%x", + freq->center_freq1, freq->center_freq2, freq->bandwidth, freq->ru_punct_bitmap); } @@ -6913,6 +6934,7 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s, wpa_s->num_multichan_concurrent = capa.num_multichan_concurrent; wpa_s->wmm_ac_supported = capa.wmm_ac_supported; + wpa_s->ru_punct_supp_bw = capa.ru_punct_supp_bw; if (capa.mac_addr_rand_scan_supported) wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN; diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf index 162e81d..325a19d 100644 --- a/wpa_supplicant/wpa_supplicant.conf +++ b/wpa_supplicant/wpa_supplicant.conf @@ -1704,6 +1704,13 @@ fast_reauth=1 #Set 1 to enable 160MHz in Mesh mode #enable_160mhz_bw=1 +# RU puncturing bitmap (16 bits) where each bit corresponds to +# a 20 MHz channel in the given bandwidth, bit 0 corresponding to the channel +# with lowest frequency. +# Bit set to 1 indicates that the channel is punctured, otherwise active. +# Default value is 0 indicating that no channel is punctured. +#ru_punct_bitmap=4 + # Example blocks: # Simple case: WPA-PSK, PSK as an ASCII passphrase, allow all valid ciphers diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 7888c3f..f642c68 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -1521,6 +1521,8 @@ struct wpa_supplicant { unsigned int enable_dscp_policy_capa:1; unsigned int connection_dscp:1; unsigned int wait_for_dscp_req:1; + /* Minimum bandwidth the driver supports RU puncturing */ + u8 ru_punct_supp_bw; }; -- 2.7.4