]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
EHT: Validate puncturing bitmap
authorAloka Dixit <quic_alokad@quicinc.com>
Tue, 14 Mar 2023 04:59:16 +0000 (21:59 -0700)
committerJouni Malinen <j@w1.fi>
Fri, 17 Mar 2023 16:54:50 +0000 (18:54 +0200)
Validate preamble puncturing bitmap.

Signed-off-by: Aloka Dixit <quic_alokad@quicinc.com>
src/ap/hw_features.c
src/common/hw_features_common.c
src/common/hw_features_common.h

index ed5ff41d3b41e147a37befe10f502a798980284f..842d9f5ba52a966a5e864525f59572869027a94c 100644 (file)
@@ -893,6 +893,55 @@ static int hostapd_is_usable_edmg(struct hostapd_iface *iface)
 }
 
 
+static bool hostapd_is_usable_punct_bitmap(struct hostapd_iface *iface)
+{
+#ifdef CONFIG_IEEE80211BE
+       struct hostapd_config *conf = iface->conf;
+       u8 bw, start_chan;
+
+       if (!conf->punct_bitmap)
+               return true;
+
+       if (!conf->ieee80211be) {
+               wpa_printf(MSG_ERROR,
+                          "Currently RU puncturing is supported only if ieee80211be is enabled");
+               return false;
+       }
+
+       if (iface->freq >= 2412 && iface->freq <= 2484) {
+               wpa_printf(MSG_ERROR,
+                          "RU puncturing not supported in 2.4 GHz");
+               return false;
+       }
+
+       switch (conf->eht_oper_chwidth) {
+       case 0:
+               wpa_printf(MSG_ERROR,
+                          "RU puncturing is supported only in 80 MHz and 160 MHz");
+               return false;
+       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 false;
+       }
+
+       if (!is_punct_bitmap_valid(bw, (conf->channel - start_chan) / 4,
+                                  conf->punct_bitmap)) {
+               wpa_printf(MSG_ERROR, "Invalid puncturing bitmap");
+               return false;
+       }
+#endif /* CONFIG_IEEE80211BE */
+
+       return true;
+}
+
+
 static int hostapd_is_usable_chans(struct hostapd_iface *iface)
 {
        int secondary_freq;
@@ -915,6 +964,9 @@ static int hostapd_is_usable_chans(struct hostapd_iface *iface)
        if (!hostapd_is_usable_edmg(iface))
                return 0;
 
+       if (!hostapd_is_usable_punct_bitmap(iface))
+               return 0;
+
        if (!iface->conf->secondary_channel)
                return 1;
 
index 6646301dfb1ded90bc1492e3dcacd1a4e5c24288..584c6d2750f6428ccd985d39c162d48e3b9ae383 100644 (file)
@@ -876,3 +876,70 @@ int chan_pri_allowed(const struct hostapd_channel_data *chan)
        return !(chan->flag & HOSTAPD_CHAN_DISABLED) &&
                (chan->allowed_bw & HOSTAPD_CHAN_WIDTH_20);
 }
+
+
+/* IEEE P802.11be/D3.0, Table 36-30 - Definition of the Punctured Channel
+ * Information field in the U-SIG for an EHT MU PPDU using non-OFDMA
+ * transmissions */
+static const u16 punct_bitmap_80[] = { 0xF, 0xE, 0xD, 0xB, 0x7 };
+static const u16 punct_bitmap_160[] = {
+       0xFF, 0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF,
+       0x7F, 0xFC, 0xF3, 0xCF, 0x3F
+};
+static const u16 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_punct_bitmap_valid(u16 bw, u16 pri_ch_bit_pos, u16 punct_bitmap)
+{
+       u8 i, count;
+       u16 bitmap;
+       const u16 *valid_bitmaps;
+
+       if (!punct_bitmap) /* All channels active */
+               return true;
+
+       bitmap = ~punct_bitmap;
+
+       switch (bw) {
+       case 80:
+               bitmap &= 0xF;
+               valid_bitmaps = punct_bitmap_80;
+               count = ARRAY_SIZE(punct_bitmap_80);
+               break;
+
+       case 160:
+               bitmap &= 0xFF;
+               valid_bitmaps = punct_bitmap_160;
+               count = ARRAY_SIZE(punct_bitmap_160);
+               break;
+
+       case 320:
+               bitmap &= 0xFFFF;
+               valid_bitmaps = punct_bitmap_320;
+               count = ARRAY_SIZE(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;
+       }
+
+       for (i = 0; i < count; i++) {
+               if (valid_bitmaps[i] == bitmap)
+                       return true;
+       }
+
+       return false;
+}
index d8ca16867808a6586eb86c7c33798101541585c3..82e02823829e586bd103ea416c2e45089373dc59 100644 (file)
@@ -54,5 +54,6 @@ 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_punct_bitmap_valid(u16 bw, u16 pri_ch_bit_pos, u16 punct_bitmap);
 
 #endif /* HW_FEATURES_COMMON_H */