mirror of
https://github.com/Telecominfraproject/wlan-ap.git
synced 2025-12-20 10:51:27 +00:00
761 lines
24 KiB
Diff
761 lines
24 KiB
Diff
From b581d1e5d5ef4adc4d60bca087942cc45fc653f1 Mon Sep 17 00:00:00 2001
|
|
From: Hari Chandrakanthan <quic_haric@quicinc.com>
|
|
Date: Wed, 1 Dec 2021 21:27:36 +0530
|
|
Subject: [PATCH] hostapd : Add support to awgn mitigation for 6Ghz
|
|
|
|
when awgn interference is detected on operating channel,
|
|
AP is supposed to stop transmitting in that channel.
|
|
AP can reduce it's operating bandwidth or
|
|
completely move to another channel based on the
|
|
interference segment.
|
|
|
|
hostapd receives awgn notification through NL80211_CMD_AWGN_DETECT
|
|
cmd and the NL attribute NL80211_ATTR_AWGN_INTERFERENCE_BITMAP
|
|
provides the channel interference information.
|
|
|
|
Eg: For 80Mhz operating bandwidth, the chan bw interference
|
|
bitmap can be as follows.
|
|
segment chan_bw_interference_bitmap
|
|
0 0x01
|
|
1 0x02
|
|
2 0x04
|
|
3 0x08
|
|
|
|
segment 0 - primary 20Mhz
|
|
segment 1 - secondary 20Mhz
|
|
segment 2 - secondary 40Mhz lower
|
|
segment 3 - secondary 40Mhz upper
|
|
|
|
Signed-off-by: Hari Chandrakanthan <quic_haric@quicinc.com>
|
|
---
|
|
hostapd/Makefile | 1 +
|
|
hostapd/config_file.c | 2 +
|
|
src/ap/Makefile | 1 +
|
|
src/ap/ap_config.c | 1 +
|
|
src/ap/ap_config.h | 1 +
|
|
src/ap/drv_callbacks.c | 13 +
|
|
src/ap/interference.c | 393 +++++++++++++++++++++++++++++
|
|
src/ap/interference.h | 41 +++
|
|
src/drivers/driver.h | 13 +
|
|
src/drivers/driver_common.c | 1 +
|
|
src/drivers/driver_nl80211_event.c | 30 +++
|
|
src/drivers/nl80211_copy.h | 16 +-
|
|
wpa_supplicant/Makefile | 1 +
|
|
13 files changed, 513 insertions(+), 1 deletion(-)
|
|
create mode 100644 src/ap/interference.c
|
|
create mode 100644 src/ap/interference.h
|
|
|
|
diff --git a/hostapd/Makefile b/hostapd/Makefile
|
|
index 50f75bf2876a..002d68833c46 100644
|
|
--- a/hostapd/Makefile
|
|
+++ b/hostapd/Makefile
|
|
@@ -1189,6 +1189,7 @@ OBJS += ../src/ap/ap_list.o
|
|
OBJS += ../src/ap/ieee802_11.o
|
|
OBJS += ../src/ap/hw_features.o
|
|
OBJS += ../src/ap/dfs.o
|
|
+OBJS += ../src/ap/interference.o
|
|
CFLAGS += -DNEED_AP_MLME
|
|
endif
|
|
OBJS += ../src/ap/ieee802_11_ht.o
|
|
diff --git a/hostapd/config_file.c b/hostapd/config_file.c
|
|
index afa07ef28f99..9f55bcd6ed2b 100644
|
|
--- a/hostapd/config_file.c
|
|
+++ b/hostapd/config_file.c
|
|
@@ -3564,6 +3564,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
|
return 1;
|
|
}
|
|
bss->unsol_bcast_probe_resp_interval = val;
|
|
+ } else if (os_strcmp(buf, "discard_6g_awgn_event") == 0) {
|
|
+ conf->discard_6g_awgn_event = atoi(pos);
|
|
#endif /* CONFIG_IEEE80211AX */
|
|
} else if (os_strcmp(buf, "max_listen_interval") == 0) {
|
|
bss->max_listen_interval = atoi(pos);
|
|
diff --git a/src/ap/Makefile b/src/ap/Makefile
|
|
index a1e9b7c44d2f..22a21d31eda6 100644
|
|
--- a/src/ap/Makefile
|
|
+++ b/src/ap/Makefile
|
|
@@ -36,6 +36,7 @@ LIB_OBJS= \
|
|
ieee802_11_shared.o \
|
|
ieee802_11_vht.o \
|
|
ieee802_1x.o \
|
|
+ interference.o \
|
|
neighbor_db.o \
|
|
ndisc_snoop.o \
|
|
p2p_hostapd.o \
|
|
diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
|
|
index 9f86a4701ed4..1e27cb3d9416 100644
|
|
--- a/src/ap/ap_config.c
|
|
+++ b/src/ap/ap_config.c
|
|
@@ -281,6 +281,7 @@ struct hostapd_config * hostapd_config_defaults(void)
|
|
conf->he_6ghz_max_ampdu_len_exp = 7;
|
|
conf->he_6ghz_rx_ant_pat = 1;
|
|
conf->he_6ghz_tx_ant_pat = 1;
|
|
+ conf->discard_6g_awgn_event = 0;
|
|
#endif /* CONFIG_IEEE80211AX */
|
|
|
|
/* The third octet of the country string uses an ASCII space character
|
|
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
|
|
index 32107f15bab8..261b1fafd74d 100644
|
|
--- a/src/ap/ap_config.h
|
|
+++ b/src/ap/ap_config.h
|
|
@@ -1095,6 +1095,7 @@ struct hostapd_config {
|
|
#define AP_TYPE_6GHZ_STANDARD_POWER_AP 1
|
|
#define AP_TYPE_6GHZ_VERY_LOW_POWER_AP 2
|
|
u8 he_6ghz_reg_pwr_type;
|
|
+ bool discard_6g_awgn_event;
|
|
#endif /* CONFIG_IEEE80211AX */
|
|
|
|
/* VHT enable/disable config from CHAN_SWITCH */
|
|
diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
|
|
index 2c945b6d3f92..bf143beac9ac 100644
|
|
--- a/src/ap/drv_callbacks.c
|
|
+++ b/src/ap/drv_callbacks.c
|
|
@@ -43,6 +43,7 @@
|
|
#include "dpp_hostapd.h"
|
|
#include "fils_hlp.h"
|
|
#include "neighbor_db.h"
|
|
+#include "interference.h"
|
|
|
|
#ifdef CONFIG_FILS
|
|
void hostapd_notify_assoc_fils_finish(struct hostapd_data *hapd,
|
|
@@ -1700,6 +1701,13 @@ static void hostapd_event_dfs_radar_detected(struct hostapd_data *hapd,
|
|
radar->cf1, radar->cf2);
|
|
}
|
|
|
|
+static void hostapd_event_awgn_detected(struct hostapd_data *hapd,
|
|
+ struct awgn_event *awgn_info)
|
|
+{
|
|
+ hostapd_intf_awgn_detected(hapd->iface, awgn_info->freq, awgn_info->chan_width,
|
|
+ awgn_info->cf1, awgn_info->cf2,
|
|
+ awgn_info->chan_bw_interference_bitmap);
|
|
+}
|
|
|
|
static void hostapd_event_dfs_pre_cac_expired(struct hostapd_data *hapd,
|
|
struct dfs_event *radar)
|
|
@@ -2084,6 +2092,11 @@ void hostapd_wpa_event(void *ctx, enum wpa_event_type event,
|
|
break;
|
|
hostapd_event_dfs_radar_detected(hapd, &data->dfs_event);
|
|
break;
|
|
+ case EVENT_AWGN_DETECTED:
|
|
+ if (!data)
|
|
+ break;
|
|
+ hostapd_event_awgn_detected(hapd, &data->awgn_event);
|
|
+ break;
|
|
case EVENT_DFS_PRE_CAC_EXPIRED:
|
|
if (!data)
|
|
break;
|
|
diff --git a/src/ap/interference.c b/src/ap/interference.c
|
|
new file mode 100644
|
|
index 000000000000..c51a4bfe9e30
|
|
--- /dev/null
|
|
+++ b/src/ap/interference.c
|
|
@@ -0,0 +1,393 @@
|
|
+/*
|
|
+ * AWGN - Additive white Gaussian Noise
|
|
+ * Copyright (c) 2002-2013, Jouni Malinen <j@w1.fi>
|
|
+ * Copyright (c) 2013-2017, Qualcomm Atheros, Inc.
|
|
+ *
|
|
+ * This software may be distributed under the terms of the BSD license.
|
|
+ * See README for more details.
|
|
+ */
|
|
+
|
|
+/*
|
|
+ * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
|
|
+ *
|
|
+ * Redistribution and use in source and binary forms, with or without modification,
|
|
+ * are permitted (subject to the limitations in the disclaimer below) provided that
|
|
+ * the following conditions are met:
|
|
+ * * Redistributions of source code must retain the above copyright notice,
|
|
+ * this list of conditions and the following disclaimer.
|
|
+ * * Redistributions in binary form must reproduce the above copyright notice,
|
|
+ * this list of conditions and the following disclaimer in the documentation and/or
|
|
+ * other materials provided with the distribution.
|
|
+ * * Neither the name of Qualcomm Innovation Center, Inc. nor the names of its contributors
|
|
+ * may be used to endorse or promote products derived from this software without specific
|
|
+ * prior written permission.
|
|
+ * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE.
|
|
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
|
|
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
|
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
|
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
+ */
|
|
+
|
|
+#include "utils/includes.h"
|
|
+
|
|
+#include "utils/common.h"
|
|
+#include "common/ieee802_11_defs.h"
|
|
+#include "common/hw_features_common.h"
|
|
+#include "common/wpa_ctrl.h"
|
|
+#include "hostapd.h"
|
|
+#include "ap_drv_ops.h"
|
|
+#include "drivers/driver.h"
|
|
+#include "beacon.h"
|
|
+#include "eloop.h"
|
|
+#include "hw_features.h"
|
|
+
|
|
+/*
|
|
+ * intf_awgn_chan_range_available - check whether the channel can operate
|
|
+ * in the given bandwidth in 6Ghz
|
|
+ * @first_chan_idx - channel index of the first 20Mhz channel in a segment
|
|
+ * @num_chans - number of 20Mhz channels needed for the operating bandwidth
|
|
+ */
|
|
+static int intf_awgn_chan_range_available(struct hostapd_hw_modes *mode,
|
|
+ int first_chan_idx, int num_chans)
|
|
+{
|
|
+ struct hostapd_channel_data *first_chan = NULL;
|
|
+ int allowed_40_6g[] = {1, 9, 17, 25, 33, 41, 49, 57, 65, 73, 81, 89, 97, 105,
|
|
+ 113, 121, 129, 137, 145, 153, 161, 169, 177, 185, 193,
|
|
+ 201, 209, 217, 225, 233};
|
|
+ int allowed_80_6g[] = {1, 17, 33, 49, 65, 81, 97, 113, 129, 145, 161, 177,
|
|
+ 193, 209};
|
|
+ int allowed_160_6g[] = {1, 33, 65, 97, 129, 161, 193};
|
|
+ int chan_idx_match = 0;
|
|
+ int i;
|
|
+
|
|
+ first_chan = &mode->channels[first_chan_idx];
|
|
+
|
|
+ if (!first_chan || !chan_pri_allowed(first_chan)) {
|
|
+ wpa_printf(MSG_DEBUG, "AWGN: primary channel not allowed");
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ /* 20Mhz channel, so no need to check the range */
|
|
+ if (num_chans == 1)
|
|
+ return 1;
|
|
+
|
|
+ if (num_chans == 2) { /* 40Mhz channel */
|
|
+ for (i = 0; i < ARRAY_SIZE(allowed_40_6g); i++) {
|
|
+ if (first_chan->chan == allowed_40_6g[i]) {
|
|
+ chan_idx_match = 1;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ } else if (num_chans == 4) { /* 80Mhz channel */
|
|
+ for (i = 0; i < ARRAY_SIZE(allowed_80_6g); i++) {
|
|
+ if (first_chan->chan == allowed_80_6g[i]) {
|
|
+ chan_idx_match = 1;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ } else if (num_chans == 8) { /* 160Mhz channel */
|
|
+ for (i = 0; i < ARRAY_SIZE(allowed_160_6g); i++) {
|
|
+ if (first_chan->chan == allowed_160_6g[i]) {
|
|
+ chan_idx_match = 1;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (chan_idx_match == 1)
|
|
+ return 1;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int is_in_chanlist(struct hostapd_iface *iface,
|
|
+ struct hostapd_channel_data *chan)
|
|
+{
|
|
+ if (!iface->conf->acs_ch_list.num)
|
|
+ return 1;
|
|
+
|
|
+ return freq_range_list_includes(&iface->conf->acs_ch_list, chan->chan);
|
|
+}
|
|
+
|
|
+/*
|
|
+ *intf_awgn_find_channel - find the channel that can operate with bandwidth chan_width.
|
|
+ If idx doesn't match with index of any of the existing channel, then the api
|
|
+ returns the total number of available chandefs that supports the provided bandwidth
|
|
+ * @idx - index of the channel
|
|
+ * @chan_width - bandwidth of the channel
|
|
+ */
|
|
+static int intf_awgn_find_channel(struct hostapd_iface *iface,
|
|
+ struct hostapd_channel_data **ret_chan,
|
|
+ int idx, int chan_width)
|
|
+{
|
|
+ struct hostapd_hw_modes *mode = iface->current_mode;
|
|
+ struct hostapd_channel_data *chan;
|
|
+ int i, channel_idx = 0, n_chans;
|
|
+
|
|
+ switch (chan_width) {
|
|
+ case CHAN_WIDTH_20_NOHT:
|
|
+ case CHAN_WIDTH_20:
|
|
+ n_chans = 1;
|
|
+ break;
|
|
+ case CHAN_WIDTH_40:
|
|
+ n_chans = 2;
|
|
+ break;
|
|
+ case CHAN_WIDTH_80:
|
|
+ n_chans = 4;
|
|
+ break;
|
|
+ case CHAN_WIDTH_80P80:
|
|
+ case CHAN_WIDTH_160:
|
|
+ n_chans = 8;
|
|
+ break;
|
|
+ default:
|
|
+ n_chans = 1;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ for (i = 0; i < mode->num_channels; i++) {
|
|
+ chan = &mode->channels[i];
|
|
+
|
|
+ /* Skip incompatible chandefs */
|
|
+ if (!intf_awgn_chan_range_available(mode, i, n_chans)) {
|
|
+ wpa_printf(MSG_DEBUG,
|
|
+ "AWGN: range not available for %d (%d)",
|
|
+ chan->freq, chan->chan);
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ if (!is_in_chanlist(iface, chan)) {
|
|
+ wpa_printf(MSG_DEBUG,
|
|
+ "AWGN: channel %d (%d) not in chanlist",
|
|
+ chan->freq, chan->chan);
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ if (ret_chan && idx == channel_idx) {
|
|
+ wpa_printf(MSG_DEBUG, "AWGN: Selected channel %d (%d)",
|
|
+ chan->freq, chan->chan);
|
|
+ *ret_chan = chan;
|
|
+ return idx;
|
|
+ }
|
|
+
|
|
+ wpa_printf(MSG_DEBUG, "AWGN: Adding channel %d (%d)",
|
|
+ chan->freq, chan->chan);
|
|
+ channel_idx++;
|
|
+ }
|
|
+ return channel_idx;
|
|
+}
|
|
+
|
|
+enum chan_seg {
|
|
+ SEG_PRI20 = 0x1,
|
|
+ SEG_SEC20 = 0x2,
|
|
+ SEG_SEC40_LOWER = 0x4,
|
|
+ SEG_SEC40_UPPER = 0x8,
|
|
+ SEG_SEC40 = 0xC,
|
|
+ SEG_SEC80_LOWER = 0x10,
|
|
+ SEG_SEC80_LOWER_UPPER = 0x20,
|
|
+ SEG_SEC80_UPPER_LOWER = 0x40,
|
|
+ SEG_SEC80_UPPER = 0x80,
|
|
+ SEG_SEC80 = 0xF0,
|
|
+};
|
|
+
|
|
+#define BASE_6G_FREQ 5950
|
|
+
|
|
+int get_centre_freq_6g(int chan_idx, int chan_width, int *centre_freq)
|
|
+{
|
|
+ if (!centre_freq)
|
|
+ return -1;
|
|
+
|
|
+ *centre_freq = 0;
|
|
+
|
|
+ switch (chan_width) {
|
|
+ case CHAN_WIDTH_40:
|
|
+ if (chan_idx >= 1 && chan_idx <= 229)
|
|
+ *centre_freq = ((chan_idx / 8) * 8 + 3) * 5 + BASE_6G_FREQ;
|
|
+ break;
|
|
+ case CHAN_WIDTH_80:
|
|
+ if (chan_idx >= 1 && chan_idx <= 221)
|
|
+ *centre_freq = ((chan_idx / 16) * 16 + 7) * 5 + BASE_6G_FREQ;
|
|
+ break;
|
|
+ case CHAN_WIDTH_160:
|
|
+ if (chan_idx >= 1 && chan_idx <= 221)
|
|
+ *centre_freq = ((chan_idx / 32) * 32 + 15) * 5 + BASE_6G_FREQ;
|
|
+ break;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ if (*centre_freq == 0)
|
|
+ return -1;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * hostapd_intf_awgn_detected - awgn interference is detected in the operating channel.
|
|
+ * The interference channel information is available as a
|
|
+ * bitmap(chan_bw_interference_bitmap). If interference has occurred in the
|
|
+ * primary channel, do a complete channel switch to a different channel else
|
|
+ * reduce the operating bandwidth and continue ap operation in the same channel.
|
|
+ */
|
|
+int hostapd_intf_awgn_detected(struct hostapd_iface *iface, int freq, int chan_width,
|
|
+ int cf1, int cf2, u32 chan_bw_interference_bitmap)
|
|
+{
|
|
+ struct csa_settings settings;
|
|
+ struct hostapd_channel_data *chan_data = NULL;
|
|
+ struct hostapd_channel_data *chan_temp = NULL;
|
|
+ int ret;
|
|
+ unsigned int i;
|
|
+ u32 _rand;
|
|
+ u32 chan_idx;
|
|
+ int num_available_chandefs;
|
|
+ u8 channel_switch = 0;
|
|
+ int new_chan_width;
|
|
+ int new_centre_freq;
|
|
+ struct hostapd_hw_modes *mode = iface->current_mode;
|
|
+
|
|
+ wpa_printf(MSG_DEBUG,
|
|
+ "input freq=%d, chan_width=%d, cf1=%d cf2=%d"
|
|
+ " chan_bw_interference_bitmap=0x%x",
|
|
+ freq,
|
|
+ chan_width,
|
|
+ cf1, cf2, chan_bw_interference_bitmap);
|
|
+
|
|
+ if (iface->conf->discard_6g_awgn_event) {
|
|
+ wpa_printf(MSG_DEBUG, "discard_6g_awgn_event set ignoring"
|
|
+ "AWGN DETECT event from driver");
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ /* check whether interference has occurred in primary 20Mhz channel */
|
|
+ if (!chan_bw_interference_bitmap || (chan_bw_interference_bitmap & SEG_PRI20))
|
|
+ channel_switch = 1;
|
|
+
|
|
+ if (channel_switch) {
|
|
+ /* Find a random channel to be switched */
|
|
+ num_available_chandefs = intf_awgn_find_channel(iface, NULL, 0,
|
|
+ chan_width);
|
|
+ if (num_available_chandefs == 0) {
|
|
+ wpa_printf(MSG_ERROR, "AWGN: no available_chandefs");
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ if (os_get_random((u8 *)&_rand, sizeof(_rand)) < 0) {
|
|
+ wpa_printf(MSG_ERROR, "AWGN: couldn't get random number");
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ chan_idx = _rand % num_available_chandefs;
|
|
+ intf_awgn_find_channel(iface, &chan_data, chan_idx, chan_width);
|
|
+
|
|
+ if (!chan_data) {
|
|
+ wpa_printf(MSG_ERROR, "AWGN: no random channel found, chan idx : %d",
|
|
+ chan_idx);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ if(chan_data->freq == freq) {
|
|
+ /* New random channel is same as operating channel
|
|
+ * so choose another channel
|
|
+ */
|
|
+ chan_data = NULL;
|
|
+ chan_idx = (chan_idx + 1) % num_available_chandefs;
|
|
+ intf_awgn_find_channel(iface, &chan_data, chan_idx, chan_width);
|
|
+ if (!chan_data) {
|
|
+ wpa_printf(MSG_ERROR,
|
|
+ "AWGN: random channel not found, chan idx : %d",
|
|
+ chan_idx);
|
|
+ return 0;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ wpa_printf(MSG_DEBUG, "AWGN: got random channel %d (%d)",
|
|
+ chan_data->freq, chan_data->chan);
|
|
+ new_chan_width = chan_width;
|
|
+ } else {
|
|
+ /* interference is not present in the primary 20Mhz, so reduce bandwidth*/
|
|
+ for (i = 0; i < mode->num_channels; i++) {
|
|
+ chan_temp = &mode->channels[i];
|
|
+ if (chan_temp->freq == freq)
|
|
+ chan_data = chan_temp;
|
|
+ }
|
|
+ if (!chan_data) {
|
|
+ wpa_printf(MSG_ERROR, "AWGN : no channel found");
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ if ((chan_width > CHAN_WIDTH_80) &&
|
|
+ !(chan_bw_interference_bitmap & SEG_SEC40) &&
|
|
+ !(chan_bw_interference_bitmap & SEG_SEC20))
|
|
+ new_chan_width = CHAN_WIDTH_80;
|
|
+ else if (chan_width > CHAN_WIDTH_40 &&
|
|
+ !(chan_bw_interference_bitmap & SEG_SEC20))
|
|
+ new_chan_width = CHAN_WIDTH_40;
|
|
+ else
|
|
+ new_chan_width = CHAN_WIDTH_20;
|
|
+ }
|
|
+
|
|
+ if (new_chan_width > CHAN_WIDTH_20) {
|
|
+ ret = get_centre_freq_6g(chan_data->chan, new_chan_width,
|
|
+ &new_centre_freq);
|
|
+ if (ret) {
|
|
+ wpa_printf(MSG_ERROR,
|
|
+ "AWGN : couldn't find centre freq for chan : %d"
|
|
+ " chan_width : %d", chan_data->chan, new_chan_width);
|
|
+ return 0;
|
|
+ }
|
|
+ } else {
|
|
+ new_centre_freq = chan_data->freq;
|
|
+ }
|
|
+
|
|
+ os_memset(&settings, 0, sizeof(settings));
|
|
+ settings.cs_count = 5;
|
|
+ settings.freq_params.freq = chan_data->freq;
|
|
+
|
|
+ switch (new_chan_width) {
|
|
+ case CHAN_WIDTH_40:
|
|
+ settings.freq_params.bandwidth = 40;
|
|
+ break;
|
|
+ case CHAN_WIDTH_80P80:
|
|
+ case CHAN_WIDTH_80:
|
|
+ settings.freq_params.bandwidth = 80;
|
|
+ break;
|
|
+ case CHAN_WIDTH_160:
|
|
+ settings.freq_params.bandwidth = 160;
|
|
+ break;
|
|
+ default:
|
|
+ settings.freq_params.bandwidth = 20;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ settings.freq_params.center_freq1 = new_centre_freq;
|
|
+ settings.freq_params.ht_enabled = iface->conf->ieee80211n;
|
|
+ settings.freq_params.vht_enabled = iface->conf->ieee80211ac;
|
|
+ settings.freq_params.he_enabled = iface->conf->ieee80211ax;
|
|
+
|
|
+ for (i = 0; i < iface->num_bss; i++) {
|
|
+ /* Save CHAN_SWITCH VHT and HE config */
|
|
+ hostapd_chan_switch_config(iface->bss[i],
|
|
+ &settings.freq_params);
|
|
+
|
|
+ wpa_printf(MSG_DEBUG,
|
|
+ "channel=%u, freq=%d, bw=%d, center_freq1=%d",
|
|
+ settings.freq_params.channel,
|
|
+ settings.freq_params.freq,
|
|
+ settings.freq_params.bandwidth,
|
|
+ settings.freq_params.center_freq1);
|
|
+
|
|
+ ret = hostapd_switch_channel(iface->bss[i], &settings);
|
|
+ if (ret) {
|
|
+ /* FIX: What do we do if CSA fails in the middle of
|
|
+ * submitting multi-BSS CSA requests?
|
|
+ */
|
|
+ return ret;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
diff --git a/src/ap/interference.h b/src/ap/interference.h
|
|
new file mode 100644
|
|
index 000000000000..047818c0b2f6
|
|
--- /dev/null
|
|
+++ b/src/ap/interference.h
|
|
@@ -0,0 +1,41 @@
|
|
+/*
|
|
+ * INTF - Interference
|
|
+ * AWGN - Additive white Gaussian Noise
|
|
+ * Copyright (c) 2002-2013, Jouni Malinen <j@w1.fi>
|
|
+ * Copyright (c) 2013-2017, Qualcomm Atheros, Inc.
|
|
+ *
|
|
+ * This software may be distributed under the terms of the BSD license.
|
|
+ * See README for more details.
|
|
+ */
|
|
+
|
|
+/*
|
|
+ * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
|
|
+ *
|
|
+ * Redistribution and use in source and binary forms, with or without modification,
|
|
+ * are permitted (subject to the limitations in the disclaimer below) provided that
|
|
+ * the following conditions are met:
|
|
+ * * Redistributions of source code must retain the above copyright notice,
|
|
+ * this list of conditions and the following disclaimer.
|
|
+ * * Redistributions in binary form must reproduce the above copyright notice,
|
|
+ * this list of conditions and the following disclaimer in the documentation and/or
|
|
+ * other materials provided with the distribution.
|
|
+ * * Neither the name of Qualcomm Innovation Center, Inc. nor the names of its contributors
|
|
+ * may be used to endorse or promote products derived from this software without specific
|
|
+ * prior written permission.
|
|
+ * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE.
|
|
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
|
|
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
|
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
|
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
+ */
|
|
+
|
|
+int hostapd_intf_awgn_detected(struct hostapd_iface *iface, int freq,
|
|
+ int chan_width,
|
|
+ int cf1, int cf2,
|
|
+ u32 chan_bw_interference_bitmap);
|
|
+
|
|
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
|
|
index 01f1bc4091ab..57cfac622db5 100644
|
|
--- a/src/drivers/driver.h
|
|
+++ b/src/drivers/driver.h
|
|
@@ -5214,6 +5214,7 @@ enum wpa_event_type {
|
|
* EVENT_CCA_NOTIFY - Notification that CCA has completed
|
|
*/
|
|
EVENT_CCA_NOTIFY,
|
|
+ EVENT_AWGN_DETECTED,
|
|
};
|
|
|
|
|
|
@@ -6123,6 +6124,18 @@ union wpa_event_data {
|
|
struct bss_color_collision {
|
|
u64 bitmap;
|
|
} bss_color_collision;
|
|
+
|
|
+ /**
|
|
+ * Data for EVENT_AWGN
|
|
+ */
|
|
+ struct awgn_event {
|
|
+ int freq;
|
|
+ enum chan_width chan_width;
|
|
+ int cf1;
|
|
+ int cf2;
|
|
+ u32 chan_bw_interference_bitmap;
|
|
+ } awgn_event;
|
|
+
|
|
};
|
|
|
|
/**
|
|
diff --git a/src/drivers/driver_common.c b/src/drivers/driver_common.c
|
|
index b06e7062d25c..198c2713b91e 100644
|
|
--- a/src/drivers/driver_common.c
|
|
+++ b/src/drivers/driver_common.c
|
|
@@ -95,6 +95,7 @@ const char * event_to_string(enum wpa_event_type event)
|
|
E2S(CCA_STARTED_NOTIFY);
|
|
E2S(CCA_ABORTED_NOTIFY);
|
|
E2S(CCA_NOTIFY);
|
|
+ E2S(AWGN_DETECTED);
|
|
}
|
|
|
|
return "UNKNOWN";
|
|
diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c
|
|
index 7a357c07340f..9a32b7a0e0ca 100644
|
|
--- a/src/drivers/driver_nl80211_event.c
|
|
+++ b/src/drivers/driver_nl80211_event.c
|
|
@@ -179,6 +179,7 @@ static const char * nl80211_command_to_string(enum nl80211_commands cmd)
|
|
C2S(NL80211_CMD_COLOR_CHANGE_ANNOUNCEMENT_STARTED)
|
|
C2S(NL80211_CMD_COLOR_CHANGE_ANNOUNCEMENT_ABORTED)
|
|
C2S(NL80211_CMD_COLOR_CHANGE_ANNOUNCEMENT_COMPLETED)
|
|
+ C2S(NL80211_CMD_AWGN_DETECT)
|
|
C2S(__NL80211_CMD_AFTER_LAST)
|
|
}
|
|
#undef C2S
|
|
@@ -1856,6 +1857,32 @@ static void nl80211_radar_event(struct wpa_driver_nl80211_data *drv,
|
|
}
|
|
}
|
|
|
|
+static void nl80211_awgn_event(struct wpa_driver_nl80211_data *drv,
|
|
+ struct nlattr **tb)
|
|
+{
|
|
+ union wpa_event_data data;
|
|
+
|
|
+ os_memset(&data, 0, sizeof(data));
|
|
+
|
|
+ if (tb[NL80211_ATTR_WIPHY_FREQ])
|
|
+ data.awgn_event.freq = nla_get_u32(tb[NL80211_ATTR_WIPHY_FREQ]);
|
|
+
|
|
+ if (tb[NL80211_ATTR_CHANNEL_WIDTH])
|
|
+ data.awgn_event.chan_width =
|
|
+ convert2width(nla_get_u32(tb[NL80211_ATTR_CHANNEL_WIDTH]));
|
|
+
|
|
+ if (tb[NL80211_ATTR_CENTER_FREQ1])
|
|
+ data.awgn_event.cf1 = nla_get_u32(tb[NL80211_ATTR_CENTER_FREQ1]);
|
|
+
|
|
+ if (tb[NL80211_ATTR_CENTER_FREQ2])
|
|
+ data.awgn_event.cf2 = nla_get_u32(tb[NL80211_ATTR_CENTER_FREQ2]);
|
|
+
|
|
+ if (tb[NL80211_ATTR_AWGN_INTERFERENCE_BITMAP])
|
|
+ data.awgn_event.chan_bw_interference_bitmap =
|
|
+ nla_get_u32(tb[NL80211_ATTR_AWGN_INTERFERENCE_BITMAP]);
|
|
+
|
|
+ wpa_supplicant_event(drv->ctx, EVENT_AWGN_DETECTED, &data);
|
|
+}
|
|
|
|
static void nl80211_spurious_frame(struct i802_bss *bss, struct nlattr **tb,
|
|
int wds)
|
|
@@ -3198,6 +3225,9 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd,
|
|
mlme_event_color_change_announcement_completed(drv);
|
|
break;
|
|
#endif
|
|
+ case NL80211_CMD_AWGN_DETECT:
|
|
+ nl80211_awgn_event(drv, tb);
|
|
+ break;
|
|
default:
|
|
wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Ignored unknown event "
|
|
"(cmd=%d)", cmd);
|
|
diff --git a/src/drivers/nl80211_copy.h b/src/drivers/nl80211_copy.h
|
|
index 85fe14ba9093..ea5fd565bb43 100644
|
|
--- a/src/drivers/nl80211_copy.h
|
|
+++ b/src/drivers/nl80211_copy.h
|
|
@@ -1190,6 +1190,10 @@
|
|
* were indicated by driver and now need to be reflected in
|
|
* Beacon frame.
|
|
*
|
|
+ * @NL80211_CMD_AWGN_DETECT: Once AWGN interference is detected on the operating
|
|
+ * channel, userspace is notified with the interference bitmap using
|
|
+ * %NL80211_ATTR_AWGN_INTERFERENCE_BITMAP
|
|
+ *
|
|
* @NL80211_CMD_MAX: highest used command number
|
|
* @__NL80211_CMD_AFTER_LAST: internal use
|
|
*/
|
|
@@ -1431,6 +1435,8 @@ enum nl80211_commands {
|
|
NL80211_CMD_COLOR_CHANGE_ANNOUNCEMENT_ABORTED,
|
|
NL80211_CMD_COLOR_CHANGE_ANNOUNCEMENT_COMPLETED,
|
|
|
|
+ NL80211_CMD_AWGN_DETECT,
|
|
+
|
|
NL80211_CMD_SET_FILS_AAD,
|
|
|
|
/* add new commands above here */
|
|
@@ -2583,6 +2589,9 @@ enum nl80211_commands {
|
|
* staggered mode or burst mode in %NL80211_CMD_START_AP from
|
|
* user-space.
|
|
*
|
|
+ * @NL80211_ATTR_AWGN_INTERFERENCE_BITMAP: u32 attribute specifying the
|
|
+ * interference bitmap of operating bandwidth for %NL80211_CMD_AWGN_DETECT
|
|
+ *
|
|
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
|
|
* @NL80211_ATTR_MAX: highest attribute number currently defined
|
|
* @__NL80211_ATTR_AFTER_LAST: internal use
|
|
@@ -2678,7 +2687,6 @@ enum nl80211_attrs {
|
|
|
|
NL80211_ATTR_FREQ_FIXED,
|
|
|
|
-
|
|
NL80211_ATTR_WIPHY_RETRY_SHORT,
|
|
NL80211_ATTR_WIPHY_RETRY_LONG,
|
|
NL80211_ATTR_WIPHY_FRAG_THRESHOLD,
|
|
@@ -3093,6 +3101,12 @@ enum nl80211_attrs {
|
|
|
|
NL80211_ATTR_BEACON_TX_MODE,
|
|
|
|
+ NL80211_ATTR_WIPHY_ANTENNA_GAIN,
|
|
+
|
|
+ NL80211_ATTR_STA_MGMT_RTS_CTS_CONFIG,
|
|
+
|
|
+ NL80211_ATTR_AWGN_INTERFERENCE_BITMAP,
|
|
+
|
|
/* add attributes here, update the policy in nl80211.c */
|
|
|
|
__NL80211_ATTR_AFTER_LAST,
|
|
diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile
|
|
index 9ff1e8d51568..4c6592b62f5b 100644
|
|
--- a/wpa_supplicant/Makefile
|
|
+++ b/wpa_supplicant/Makefile
|
|
@@ -977,6 +977,7 @@ OBJS += ../src/ap/ap_list.o
|
|
OBJS += ../src/ap/ieee802_11.o
|
|
OBJS += ../src/ap/hw_features.o
|
|
OBJS += ../src/ap/dfs.o
|
|
+OBJS += ../src/ap/interference.o
|
|
CFLAGS += -DNEED_AP_MLME
|
|
endif
|
|
ifdef CONFIG_WPS
|
|
--
|
|
2.31.1
|
|
|