From 710e19ab3a32cb29f833de594b07c7a2639b88b9 Mon Sep 17 00:00:00 2001 From: Aloka Dixit Date: Wed, 22 Dec 2021 14:16:01 -0800 Subject: [PATCH] ru_puncturing: additions to channel switch command Parse the command to retrive the RU puncturing bitmap and if OFDMA patterns shouldbe considered. Signed-off-by: Aloka Dixit --- hostapd/ctrl_iface.c | 37 ++++++++++++++++++++++++++++++ src/ap/ctrl_iface_ap.c | 3 +++ src/ap/drv_callbacks.c | 14 +++++++---- src/ap/hostapd.c | 4 ++++ src/ap/hostapd.h | 1 + src/drivers/driver.h | 2 ++ src/drivers/driver_nl80211.c | 6 +++-- src/drivers/driver_nl80211_event.c | 11 +++++++++ wpa_supplicant/ap.c | 2 +- 9 files changed, 73 insertions(+), 7 deletions(-) diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c index b758c600166f..124ec9b4b8a5 100644 --- a/hostapd/ctrl_iface.c +++ b/hostapd/ctrl_iface.c @@ -33,6 +33,7 @@ #include "common/version.h" #include "common/ieee802_11_defs.h" #include "common/ctrl_iface_common.h" +#include "common/hw_features_common.h" #ifdef CONFIG_DPP #include "common/dpp.h" #endif /* CONFIG_DPP */ @@ -2637,6 +2638,7 @@ static int hostapd_ctrl_register_frame(struct hostapd_data *hapd, static int hostapd_ctrl_check_freq_params(struct hostapd_freq_params *params) { int idx, bw, bw_idx[] = { 20, 40, 80, 160 }; + u32 start_freq; if (is_6ghz_freq(params->freq)) { /* Verify if HE was enabled by user or not. 6 GHz does not @@ -2669,11 +2671,17 @@ static int hostapd_ctrl_check_freq_params(struct hostapd_freq_params *params) if (params->center_freq2 || params->sec_channel_offset) return -1; + + if (params->ru_punct_bitmap) + return -1; break; case 40: if (params->center_freq2 || !params->sec_channel_offset) return -1; + if (params->ru_punct_bitmap) + return -1; + if (!params->center_freq1) break; switch (params->sec_channel_offset) { @@ -2708,6 +2716,9 @@ static int hostapd_ctrl_check_freq_params(struct hostapd_freq_params *params) return -1; } + if (params->center_freq2 && params->ru_punct_bitmap) + return -1; + /* Adjacent and overlapped are not allowed for 80+80 */ if (params->center_freq2 && params->center_freq1 - params->center_freq2 <= 80 && @@ -2742,6 +2753,32 @@ static int hostapd_ctrl_check_freq_params(struct hostapd_freq_params *params) return -1; } + if (!params->ru_punct_bitmap) { + params->ru_punct_ofdma = 0; + return 0; + } + + if (!params->eht_enabled) { + wpa_printf(MSG_ERROR, + "Currently RU puncturing is supported only if EHT is enabled"); + return -1; + } + + if (params->freq >= 2412 && params->freq <= 2484) { + wpa_printf(MSG_ERROR, + "RU puncturing not supported in 2.4 GHz"); + return -1; + } + + start_freq = params->center_freq1 - (params->bandwidth / 2); + if (is_ru_punct_bitmap_valid(params->bandwidth, + (params->freq - start_freq) / 20, + params->ru_punct_bitmap, + params->ru_punct_ofdma) == false) { + wpa_printf(MSG_ERROR, "Invalid RU puncturing bitmap"); + return -1; + } + return 0; } #endif /* NEED_AP_MLME */ diff --git a/src/ap/ctrl_iface_ap.c b/src/ap/ctrl_iface_ap.c index f01cac247293..62db2730bd6f 100644 --- a/src/ap/ctrl_iface_ap.c +++ b/src/ap/ctrl_iface_ap.c @@ -1266,10 +1266,13 @@ int hostapd_parse_csa_settings(const char *pos, SET_CSA_SETTING(center_freq2); SET_CSA_SETTING(bandwidth); SET_CSA_SETTING(sec_channel_offset); + SET_CSA_SETTING(ru_punct_bitmap); settings->freq_params.ht_enabled = !!os_strstr(pos, " ht"); settings->freq_params.vht_enabled = !!os_strstr(pos, " vht"); settings->freq_params.he_enabled = !!os_strstr(pos, " he"); settings->freq_params.eht_enabled = !!os_strstr(pos, " eht"); + settings->freq_params.ru_punct_ofdma = !!os_strstr(pos, + " ru_punct_ofdma"); settings->block_tx = !!os_strstr(pos, " blocktx"); #undef SET_CSA_SETTING diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c index a02d4a9faad5..85636fe111d0 100644 --- a/src/ap/drv_callbacks.c +++ b/src/ap/drv_callbacks.c @@ -872,6 +872,7 @@ void hostapd_event_sta_opmode_changed(struct hostapd_data *hapd, const u8 *addr, void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht, int offset, int width, int cf1, int cf2, + u16 ru_punct_bitmap, u8 ru_punct_ofdma, int finished) { #ifdef NEED_AP_MLME @@ -881,12 +882,13 @@ void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht, hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_INFO, - "driver %s channel switch: freq=%d, ht=%d, vht_ch=0x%x, he_ch=0x%x, eht_ch=0x%x, offset=%d, width=%d (%s), cf1=%d, cf2=%d", + "driver %s channel switch: freq=%d, ht=%d, vht_ch=0x%x, he_ch=0x%x, eht_ch=0x%x, offset=%d, width=%d (%s), cf1=%d, cf2=%d, ru_punct_bitmap=0x%x, ru_punct_ofdma=%u", finished ? "had" : "starting", freq, ht, hapd->iconf->ch_switch_vht_config, hapd->iconf->ch_switch_he_config, hapd->iconf->ch_switch_eht_config, offset, - width, channel_width_to_string(width), cf1, cf2); + width, channel_width_to_string(width), cf1, cf2, + ru_punct_bitmap, ru_punct_ofdma); if (!hapd->iface->current_mode) { hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, @@ -985,6 +987,8 @@ void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht, hostapd_set_oper_centr_freq_seg0_idx(hapd->iconf, seg0_idx); hostapd_set_oper_centr_freq_seg1_idx(hapd->iconf, seg1_idx); hapd->iconf->op_class = op_class; + hapd->iconf->ru_punct_bitmap = ru_punct_bitmap; + hapd->iconf->ru_punct_ofdma = ru_punct_ofdma; if (hapd->iconf->ieee80211ac) { hapd->iconf->vht_capab &= ~VHT_CAP_SUPP_CHAN_WIDTH_MASK; if (chwidth == CHANWIDTH_160MHZ) @@ -999,11 +1003,11 @@ void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht, hapd->iface->num_hw_features); wpa_msg(hapd->msg_ctx, MSG_INFO, - "%sfreq=%d ht_enabled=%d ch_offset=%d ch_width=%s cf1=%d cf2=%d dfs=%d", + "%sfreq=%d ht_enabled=%d ch_offset=%d ch_width=%s cf1=%d cf2=%d dfs=%d ru_punct_bitmap=0x%x ru_punct_ofdma=%u", finished ? WPA_EVENT_CHANNEL_SWITCH : WPA_EVENT_CHANNEL_SWITCH_STARTED, freq, ht, offset, channel_width_to_string(width), - cf1, cf2, is_dfs); + cf1, cf2, is_dfs, ru_punct_bitmap, ru_punct_ofdma); if (!finished) return; @@ -2088,6 +2092,8 @@ void hostapd_wpa_event(void *ctx, enum wpa_event_type event, data->ch_switch.ch_width, data->ch_switch.cf1, data->ch_switch.cf2, + data->ch_switch.ru_punct_bitmap, + data->ch_switch.ru_punct_ofdma, event == EVENT_CH_SWITCH); break; case EVENT_CONNECT_FAILED_REASON: diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c index becb726c760b..176ad60aacb1 100644 --- a/src/ap/hostapd.c +++ b/src/ap/hostapd.c @@ -3577,6 +3577,8 @@ static int hostapd_change_config_freq(struct hostapd_data *hapd, conf->ieee80211n = params->ht_enabled; conf->ieee80211ac = params->vht_enabled; conf->secondary_channel = params->sec_channel_offset; + conf->ru_punct_bitmap = params->ru_punct_bitmap; + conf->ru_punct_ofdma= params->ru_punct_ofdma; ieee80211_freq_to_chan(params->center_freq1, &seg0); ieee80211_freq_to_chan(params->center_freq2, @@ -3790,6 +3792,8 @@ hostapd_switch_channel_fallback(struct hostapd_iface *iface, hostapd_set_oper_centr_freq_seg0_idx(iface->conf, seg0_idx); hostapd_set_oper_centr_freq_seg1_idx(iface->conf, seg1_idx); hostapd_set_oper_chwidth(iface->conf, bw); + iface->conf->ru_punct_bitmap = freq_params->ru_punct_bitmap; + iface->conf->ru_punct_ofdma = freq_params->ru_punct_ofdma; /* * Resetting operating class to avoid referring previous values diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h index 6cdd2c4e77d5..3841f1b4eb4b 100644 --- a/src/ap/hostapd.h +++ b/src/ap/hostapd.h @@ -701,6 +701,7 @@ int hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa, const u8 *da, int ssi_signal); void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht, int offset, int width, int cf1, int cf2, + u16 ru_punct_bitmap, u8 ru_punct_ofdma, int finished); struct survey_results; void hostapd_event_get_survey(struct hostapd_iface *iface, diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 2bed341a60e2..6900d9d39979 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -6086,6 +6086,8 @@ union wpa_event_data { enum chan_width ch_width; int cf1; int cf2; + u16 ru_punct_bitmap; + u8 ru_punct_ofdma; } ch_switch; /** diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 3fbd4eedf0f6..ae8cba4acd5c 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -9996,7 +9996,7 @@ static int nl80211_switch_channel(void *priv, struct csa_settings *settings) int i; wpa_printf(MSG_DEBUG, - "nl80211: Channel switch request (cs_count=%u block_tx=%u freq=%d channel=%d sec_channel_offset=%d width=%d cf1=%d cf2=%d%s%s%s)", + "nl80211: Channel switch request (cs_count=%u block_tx=%u freq=%d channel=%d sec_channel_offset=%d width=%d cf1=%d cf2=%d%s%s%s puncturing bitmap=0x%04x, ru_punct_ofdma=%u)", settings->cs_count, settings->block_tx, settings->freq_params.freq, settings->freq_params.channel, @@ -10006,7 +10006,9 @@ static int nl80211_switch_channel(void *priv, struct csa_settings *settings) settings->freq_params.center_freq2, settings->freq_params.ht_enabled ? " ht" : "", settings->freq_params.vht_enabled ? " vht" : "", - settings->freq_params.he_enabled ? " he" : ""); + settings->freq_params.he_enabled ? " he" : "", + settings->freq_params.ru_punct_bitmap, + settings->freq_params.ru_punct_ofdma); if (!(drv->capa.flags & WPA_DRIVER_FLAGS_AP_CSA)) { wpa_printf(MSG_DEBUG, "nl80211: Driver does not support channel switch command"); diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c index 640b64c9f95c..c0b0efc90d03 100644 --- a/src/drivers/driver_nl80211_event.c +++ b/src/drivers/driver_nl80211_event.c @@ -692,6 +692,8 @@ static void mlme_event_ch_switch(struct wpa_driver_nl80211_data *drv, struct nlattr *ifindex, struct nlattr *freq, struct nlattr *type, struct nlattr *bw, struct nlattr *cf1, struct nlattr *cf2, + struct nlattr *ru_punct_bitmap, + struct nlattr *ru_punct_ofdma, int finished) { struct i802_bss *bss; @@ -753,6 +755,11 @@ static void mlme_event_ch_switch(struct wpa_driver_nl80211_data *drv, data.ch_switch.cf1 = nla_get_u32(cf1); if (cf2) data.ch_switch.cf2 = nla_get_u32(cf2); + if (ru_punct_bitmap) { + data.ch_switch.ru_punct_bitmap = nla_get_u16(ru_punct_bitmap); + if (ru_punct_ofdma) + data.ch_switch.ru_punct_ofdma = nla_get_flag(ru_punct_ofdma); + } if (finished) bss->freq = data.ch_switch.freq; @@ -3110,6 +3117,8 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd, tb[NL80211_ATTR_CHANNEL_WIDTH], tb[NL80211_ATTR_CENTER_FREQ1], tb[NL80211_ATTR_CENTER_FREQ2], + tb[NL80211_ATTR_RU_PUNCT_BITMAP], + tb[NL80211_ATTR_RU_PUNCT_SUPP_HE], 0); break; case NL80211_CMD_CH_SWITCH_NOTIFY: @@ -3120,6 +3129,8 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd, tb[NL80211_ATTR_CHANNEL_WIDTH], tb[NL80211_ATTR_CENTER_FREQ1], tb[NL80211_ATTR_CENTER_FREQ2], + tb[NL80211_ATTR_RU_PUNCT_BITMAP], + tb[NL80211_ATTR_RU_PUNCT_SUPP_HE], 1); break; case NL80211_CMD_DISCONNECT: diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c index a9d995af7719..4bf2af6a5143 100644 --- a/wpa_supplicant/ap.c +++ b/wpa_supplicant/ap.c @@ -1643,7 +1643,7 @@ void wpas_ap_ch_switch(struct wpa_supplicant *wpa_s, int freq, int ht, if (wpa_s->current_ssid) wpa_s->current_ssid->frequency = freq; hostapd_event_ch_switch(iface->bss[0], freq, ht, - offset, width, cf1, cf2, finished); + offset, width, cf1, cf2, 0, 0, finished); } -- 2.31.1