mirror of
https://github.com/Telecominfraproject/wlan-ap.git
synced 2025-12-18 01:41:24 +00:00
395 lines
11 KiB
Diff
395 lines
11 KiB
Diff
From 765ef9735ee87ccb8e58df2d7e3cba53851ac8ef Mon Sep 17 00:00:00 2001
|
|
From: Muna Sinada <quic_msinada@quicinc.com>
|
|
Date: Wed, 2 Mar 2022 15:32:49 -0800
|
|
Subject: [PATCH] ru_puncturing: add bitmap to EHT operation element
|
|
|
|
Add RU puncturing bitmap to the EHT operation element.
|
|
Bits set to 1 indicate that the subchannel is punctured, otherwise
|
|
active.
|
|
|
|
Signed-off-by: Muna Sinada <quic_msinada@quicinc.com>
|
|
Signed-off-by: Aloka Dixit <quic_alokad@quicinc.com>
|
|
---
|
|
hostapd/ctrl_iface.c | 36 +++++++++++++
|
|
src/ap/hw_features.c | 64 +++++++++++++++++++++++
|
|
src/ap/ieee802_11.c | 73 ++++++++++++++++++++++++++
|
|
src/ap/ieee802_11.h | 1 +
|
|
src/ap/ieee802_11_eht.c | 27 +++++++++-
|
|
src/ap/ieee802_11_he.c | 16 ++++++
|
|
src/ap/ieee802_11_vht.c | 7 +++
|
|
src/common/hw_features_common.c | 92 +++++++++++++++++++++++++++++++++
|
|
src/common/hw_features_common.h | 2 +
|
|
src/common/ieee802_11_defs.h | 1 +
|
|
10 files changed, 318 insertions(+), 1 deletion(-)
|
|
|
|
--- a/src/ap/hw_features.c
|
|
+++ b/src/ap/hw_features.c
|
|
@@ -898,6 +898,63 @@ static int hostapd_is_usable_edmg(struct
|
|
}
|
|
|
|
|
|
+static int hostapd_is_usable_ru_punct_bitmap(struct hostapd_iface *iface)
|
|
+{
|
|
+ struct hostapd_config *conf = iface->conf;
|
|
+ u8 bw, start_chan;
|
|
+
|
|
+ if (!conf->ru_punct_bitmap) {
|
|
+ conf->ru_punct_ofdma = 0;
|
|
+ return 1;
|
|
+ }
|
|
+
|
|
+#ifdef CONFIG_IEEE80211BE
|
|
+ if (!conf->ieee80211be) {
|
|
+ wpa_printf(MSG_ERROR,
|
|
+ "Currently RU puncturing is supported only if ieee80211be is enabled");
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ if (iface->freq >= 2412 && iface->freq <= 2484) {
|
|
+ wpa_printf(MSG_ERROR,
|
|
+ "RU puncturing not supported in 2.4 GHz");
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ switch (conf->eht_oper_chwidth) {
|
|
+ case 0:
|
|
+ wpa_printf(MSG_ERROR,
|
|
+ "RU puncturing is supported only in 80 MHz and 160 MHz");
|
|
+ return 0;
|
|
+ case 1:
|
|
+ bw = 80;
|
|
+ start_chan = conf->eht_oper_centr_freq_seg0_idx - 6;
|
|
+ break;
|
|
+ case 2:
|
|
+ bw = 160;
|
|
+ start_chan = conf->eht_oper_centr_freq_seg0_idx - 14;
|
|
+ break;
|
|
+ default:
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ if (is_ru_punct_bitmap_valid(bw,
|
|
+ (conf->channel - start_chan) / 4,
|
|
+ conf->ru_punct_bitmap,
|
|
+ conf->ru_punct_ofdma) == false) {
|
|
+ wpa_printf(MSG_ERROR, "Invalid RU puncturing bitmap");
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ return 1;
|
|
+#else
|
|
+ wpa_printf(MSG_ERROR,
|
|
+ "Currently RU puncturing is supported only if ieee80211be is enabled");
|
|
+ return 0;
|
|
+#endif /* CONFIG_IEEE80211BE */
|
|
+}
|
|
+
|
|
+
|
|
static int hostapd_is_usable_chans(struct hostapd_iface *iface)
|
|
{
|
|
int secondary_freq;
|
|
@@ -920,6 +977,9 @@ static int hostapd_is_usable_chans(struc
|
|
if (!hostapd_is_usable_edmg(iface))
|
|
return 0;
|
|
|
|
+ if (!hostapd_is_usable_ru_punct_bitmap(iface))
|
|
+ return 0;
|
|
+
|
|
if (!iface->conf->secondary_channel)
|
|
return 1;
|
|
|
|
--- a/src/ap/ieee802_11.c
|
|
+++ b/src/ap/ieee802_11.c
|
|
@@ -8066,4 +8066,77 @@ u8 * hostapd_eid_mbssid(struct hostapd_d
|
|
return eid;
|
|
}
|
|
|
|
+
|
|
+static void ru_punct_update_bw_80(u8 bitmap, u8 pri_chan, u8 *seg0)
|
|
+{
|
|
+ u8 first_chan = *seg0 - 6, sec_chan;
|
|
+
|
|
+ switch (bitmap) {
|
|
+ case 0x6:
|
|
+ *seg0 = 0;
|
|
+ return;
|
|
+ case 0x8:
|
|
+ case 0x4:
|
|
+ case 0x2:
|
|
+ case 0x1:
|
|
+ case 0xC:
|
|
+ case 0x3:
|
|
+ if (pri_chan < *seg0)
|
|
+ *seg0 -= 4;
|
|
+ else
|
|
+ *seg0 += 4;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ if (pri_chan < *seg0)
|
|
+ sec_chan = pri_chan + 4;
|
|
+ else
|
|
+ sec_chan = pri_chan - 4;
|
|
+
|
|
+ if (bitmap & BIT((sec_chan - first_chan) / 4))
|
|
+ *seg0 = 0;
|
|
+}
|
|
+
|
|
+
|
|
+static void ru_punct_update_bw_160(u8 bitmap, u8 pri_chan, u8 *width, u8 *seg0)
|
|
+{
|
|
+ if (pri_chan < *seg0) {
|
|
+ *seg0 -= 8;
|
|
+ if (bitmap & 0x0F) {
|
|
+ *width = 0;
|
|
+ ru_punct_update_bw_80(bitmap & 0xF,
|
|
+ pri_chan,
|
|
+ seg0);
|
|
+ }
|
|
+ } else {
|
|
+ *seg0 += 8;
|
|
+ if (bitmap & 0xF0) {
|
|
+ *width = 0;
|
|
+ ru_punct_update_bw_80((bitmap & 0xF0) >> 4,
|
|
+ pri_chan,
|
|
+ seg0);
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+
|
|
+void ru_punct_update_bw(u16 bitmap, u8 pri_chan, u8 *width, u8 *seg0, u8 *seg1)
|
|
+{
|
|
+ if (!bitmap || !(*width) || ((*width) == 3))
|
|
+ return;
|
|
+
|
|
+ if (((*width) == 1) && (bitmap & 0xF)) {
|
|
+ *width = 0;
|
|
+ ru_punct_update_bw_80(bitmap & 0xF, pri_chan, seg0);
|
|
+ }
|
|
+
|
|
+ if ((*width) == 2 && (bitmap & 0xFF)) {
|
|
+ *width = 1;
|
|
+ *seg1 = 0;
|
|
+ ru_punct_update_bw_160(bitmap & 0xFF, pri_chan, width, seg0);
|
|
+ }
|
|
+
|
|
+ /* Add for 320 MHz */
|
|
+}
|
|
+
|
|
#endif /* CONFIG_NATIVE_WINDOWS */
|
|
--- a/src/ap/ieee802_11.h
|
|
+++ b/src/ap/ieee802_11.h
|
|
@@ -228,4 +228,5 @@ u8 * hostapd_eid_eht_operation(struct ho
|
|
u16 copy_sta_eht_capab(struct hostapd_data *hapd, struct sta_info *sta,
|
|
enum ieee80211_op_mode opmode, const u8 *he_capab,
|
|
const u8 *eht_capab, size_t eht_capab_len);
|
|
+void ru_punct_update_bw(u16 bitmap, u8 pri_chan, u8 *width, u8 *seg0, u8 *seg1);
|
|
#endif /* IEEE802_11_H */
|
|
--- a/src/ap/ieee802_11_eht.c
|
|
+++ b/src/ap/ieee802_11_eht.c
|
|
@@ -196,17 +196,37 @@ u8 * hostapd_eid_eht_operation(struct ho
|
|
else
|
|
chwidth = hapd->iconf->eht_oper_chwidth;
|
|
|
|
+ if (hapd->iconf->ru_punct_bitmap && !hapd->iface->ru_punct_supp_bw) {
|
|
+ hapd->iconf->ru_punct_bitmap = 0;
|
|
+ wpa_printf(MSG_ERROR,
|
|
+ "Driver does not support RU puncturing. Setting bitmap to 0");
|
|
+ }
|
|
+
|
|
switch (chwidth) {
|
|
case CHANWIDTH_320MHZ:
|
|
oper->width = EHT_OPERATION_CHANNEL_WIDTH_320MHZ;
|
|
break;
|
|
case CHANWIDTH_160MHZ:
|
|
oper->width = EHT_OPERATION_CHANNEL_WIDTH_160MHZ;
|
|
+ if (hapd->iconf->ru_punct_bitmap &&
|
|
+ hapd->iface->ru_punct_supp_bw == CHANWIDTH_320MHZ) {
|
|
+ hapd->iconf->ru_punct_bitmap = 0;
|
|
+ wpa_printf(MSG_ERROR,
|
|
+ "Driver does not support RU puncturing for bandwidths less than 320 MHz. Setting bitmap to 0");
|
|
+ }
|
|
break;
|
|
case CHANWIDTH_80MHZ:
|
|
oper->width = EHT_OPERATION_CHANNEL_WIDTH_80MHZ;
|
|
+ if (hapd->iconf->ru_punct_bitmap &&
|
|
+ ((hapd->iface->ru_punct_supp_bw == CHANWIDTH_160MHZ) ||
|
|
+ (hapd->iface->ru_punct_supp_bw == CHANWIDTH_320MHZ))) {
|
|
+ hapd->iconf->ru_punct_bitmap = 0;
|
|
+ wpa_printf(MSG_ERROR,
|
|
+ "Driver does not support RU puncturing for bandwidths less than 160 MHz. Setting bitmap to 0");
|
|
+ }
|
|
break;
|
|
case CHANWIDTH_USE_HT:
|
|
+ hapd->iconf->ru_punct_bitmap = 0;
|
|
if ((is_6ghz_op_class(hapd->iconf->op_class) &&
|
|
op_class_to_bandwidth(hapd->iconf->op_class) == 40) ||
|
|
hapd->iconf->secondary_channel)
|
|
@@ -216,10 +236,16 @@ u8 * hostapd_eid_eht_operation(struct ho
|
|
|
|
break;
|
|
default:
|
|
+ hapd->iconf->ru_punct_bitmap = 0;
|
|
oper->width = EHT_OPERATION_CHANNEL_WIDTH_20MHZ;
|
|
break;
|
|
}
|
|
|
|
+ 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);
|
|
+ }
|
|
+
|
|
pos += oper_size;
|
|
|
|
return pos;
|
|
--- a/src/ap/ieee802_11_he.c
|
|
+++ b/src/ap/ieee802_11_he.c
|
|
@@ -215,6 +215,22 @@ u8 * hostapd_eid_he_operation(struct hos
|
|
u8 seg0 = hostapd_get_oper_centr_freq_seg0_idx(hapd->iconf);
|
|
u8 seg1 = hostapd_get_oper_centr_freq_seg1_idx(hapd->iconf);
|
|
|
|
+ if (hapd->iconf->ru_punct_bitmap) {
|
|
+ hapd->iconf->he_oper_chwidth =
|
|
+ hostapd_get_oper_chwidth(hapd->iconf);
|
|
+ hapd->iconf->he_oper_centr_freq_seg0_idx = seg0;
|
|
+ hapd->iconf->he_oper_centr_freq_seg1_idx = seg1;
|
|
+
|
|
+ ru_punct_update_bw(hapd->iconf->ru_punct_bitmap,
|
|
+ hapd->iconf->channel,
|
|
+ &hapd->iconf->he_oper_chwidth,
|
|
+ &hapd->iconf->he_oper_centr_freq_seg0_idx,
|
|
+ &hapd->iconf->he_oper_centr_freq_seg1_idx);
|
|
+
|
|
+ seg0 = hapd->iconf->he_oper_centr_freq_seg0_idx;
|
|
+ seg1 = hapd->iconf->he_oper_centr_freq_seg1_idx;
|
|
+ }
|
|
+
|
|
if (!seg0)
|
|
seg0 = hapd->iconf->channel;
|
|
|
|
--- a/src/ap/ieee802_11_vht.c
|
|
+++ b/src/ap/ieee802_11_vht.c
|
|
@@ -98,6 +98,13 @@ u8 * hostapd_eid_vht_operation(struct ho
|
|
oper = (struct ieee80211_vht_operation *) pos;
|
|
os_memset(oper, 0, sizeof(*oper));
|
|
|
|
+ if (hapd->iconf->ru_punct_bitmap)
|
|
+ ru_punct_update_bw(hapd->iconf->ru_punct_bitmap,
|
|
+ hapd->iconf->channel,
|
|
+ &hapd->iconf->vht_oper_chwidth,
|
|
+ &hapd->iconf->vht_oper_centr_freq_seg0_idx,
|
|
+ &hapd->iconf->vht_oper_centr_freq_seg1_idx);
|
|
+
|
|
/*
|
|
* center freq = 5 GHz + (5 * index)
|
|
* So index 42 gives center freq 5.210 GHz
|
|
--- a/src/common/hw_features_common.c
|
|
+++ b/src/common/hw_features_common.c
|
|
@@ -824,3 +824,95 @@ int chan_pri_allowed(const struct hostap
|
|
return !(chan->flag & HOSTAPD_CHAN_DISABLED) &&
|
|
(chan->allowed_bw & HOSTAPD_CHAN_WIDTH_20);
|
|
}
|
|
+
|
|
+
|
|
+/* IEEE P802.11be/D1.31, December 2021, Table 36-30 5-bit punctured channel
|
|
+ * indication for the non-OFDMA case in an EHT MU PPDU
|
|
+ */
|
|
+static const u16 ru_punct_bitmap_80[] = {0xF, 0xE, 0xD, 0xB, 0x7};
|
|
+static const u16 ru_punct_bitmap_160[] = {0xFF, 0xFE, 0xFD, 0xFB, 0xF7, 0xEF,
|
|
+ 0xDF, 0xBF, 0x7F, 0xFC, 0xF3, 0xCF,
|
|
+ 0x3F};
|
|
+static const u16 ru_punct_bitmap_320[] = {0xFFFF, 0xFFFC, 0xFFF3, 0xFFCF,
|
|
+ 0xFF3F, 0xFCFF, 0xF3FF, 0xCFFF,
|
|
+ 0x3FFF, 0xFFF0, 0xFF0F, 0xF0FF,
|
|
+ 0x0FFF, 0xFFC0, 0xFF30, 0xFCF0,
|
|
+ 0xF3F0, 0xCFF0, 0x3FF0, 0x0FFC,
|
|
+ 0x0FF3, 0x0FCF, 0x0F3F, 0x0CFF,
|
|
+ 0x03FF};
|
|
+
|
|
+
|
|
+bool is_ru_punct_bitmap_valid(u16 bw, u16 pri_ch_bit_pos, u16 ru_punct_bitmap,
|
|
+ u8 ru_punct_ofdma)
|
|
+{
|
|
+ u8 i, non_ofdma_bitmap_count, ofdma_block_count = 1;
|
|
+ u16 bitmap;
|
|
+ const u16 *non_ofdma_bitmap;
|
|
+
|
|
+ if (!ru_punct_bitmap) /* All channels active */
|
|
+ return true;
|
|
+
|
|
+ bitmap = ~ru_punct_bitmap;
|
|
+
|
|
+ switch (bw) {
|
|
+ case 80:
|
|
+ bitmap &= 0xF;
|
|
+ non_ofdma_bitmap = &ru_punct_bitmap_80[0];
|
|
+ non_ofdma_bitmap_count = ARRAY_SIZE(ru_punct_bitmap_80);
|
|
+ break;
|
|
+
|
|
+ case 160:
|
|
+ bitmap &= 0xFF;
|
|
+ non_ofdma_bitmap = &ru_punct_bitmap_160[0];
|
|
+ non_ofdma_bitmap_count = ARRAY_SIZE(ru_punct_bitmap_160);
|
|
+ break;
|
|
+
|
|
+ case 320:
|
|
+ bitmap &= 0xFFFF;
|
|
+ non_ofdma_bitmap = &ru_punct_bitmap_320[0];
|
|
+ non_ofdma_bitmap_count = ARRAY_SIZE(ru_punct_bitmap_320);
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ if (!bitmap) /* No channel active */
|
|
+ return false;
|
|
+
|
|
+ if (!(bitmap & BIT(pri_ch_bit_pos))) {
|
|
+ wpa_printf(MSG_DEBUG, "Primary channel cannot be punctured");
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ /* Check for non-OFDMA puncturing patterns */
|
|
+ for (i = 0; i < non_ofdma_bitmap_count; i++)
|
|
+ if (non_ofdma_bitmap[i] == bitmap)
|
|
+ return true;
|
|
+
|
|
+ if (!ru_punct_ofdma)
|
|
+ return false;
|
|
+
|
|
+ /* Check for OFDMA puncturing patterns */
|
|
+ for (i = 0; i < ofdma_block_count; i++) {
|
|
+ switch ((bitmap >> (i * 4)) & 0xF) {
|
|
+ /* IEEE P802.11be/D1.31, December 2021, 36.3.12.11.2 Preamble
|
|
+ * puncturing for PPDUs in an OFDMA transmission
|
|
+ */
|
|
+ case 0xF:
|
|
+ case 0x7:
|
|
+ case 0xB:
|
|
+ case 0xD:
|
|
+ case 0xE:
|
|
+ case 0x3:
|
|
+ case 0xC:
|
|
+ case 0x9:
|
|
+ case 0x0:
|
|
+ break;
|
|
+ default:
|
|
+ return false;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return true;
|
|
+}
|
|
--- a/src/common/hw_features_common.h
|
|
+++ b/src/common/hw_features_common.h
|
|
@@ -55,5 +55,7 @@ u32 num_chan_to_bw(int num_chans);
|
|
int chan_bw_allowed(const struct hostapd_channel_data *chan, u32 bw,
|
|
int ht40_plus, int pri);
|
|
int chan_pri_allowed(const struct hostapd_channel_data *chan);
|
|
+bool is_ru_punct_bitmap_valid(u16 bw, u16 pri_ch_bit_pos, u16 ru_punct_bitmap,
|
|
+ u8 ru_punct_ofdma);
|
|
|
|
#endif /* HW_FEATURES_COMMON_H */
|