wlan-ap-Telecominfraproject/feeds/ipq95xx/hostapd.old/patches/q02-035-ru_puncturing-additions-to-channel-switch-command.patch
John Crispin b9b03a6e38 ipq95xx: add Qualcomm wifi-7 support
Signed-off-by: John Crispin <john@phrozen.org>
2023-04-10 14:25:48 +02:00

311 lines
12 KiB
Diff

From 710e19ab3a32cb29f833de594b07c7a2639b88b9 Mon Sep 17 00:00:00 2001
From: Aloka Dixit <quic_alokad@quicinc.com>
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 <quic_alokad@quicinc.com>
---
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