]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
Extend support for the 6 GHz operating class 137 (320 MHz)
authorAiny Kumari <quic_ainykuma@quicinc.com>
Thu, 22 Feb 2024 04:02:04 +0000 (09:32 +0530)
committerJouni Malinen <j@w1.fi>
Mon, 4 Mar 2024 17:20:03 +0000 (19:20 +0200)
Commit 085a3fc76e6b ("EHT: Add 320 channel width support") added this in
various places, but it did not cover everything. Extend this support to
be more complete. In particular, this allows wpa_supplicant to report
the operating class 137 in the Supported Operating Classes element and
to use it when processing beacon requests.

Signed-off-by: Ainy Kumari <quic_ainykuma@quicinc.com>
src/common/ieee802_11_common.c
src/common/ieee802_11_common.h
wpa_supplicant/op_classes.c
wpa_supplicant/rrm.c

index 85d4b720e2208a797f3810d7b56e520542145192..081723f7ca1cbd4fd6f2d9c474582492c821b023 100644 (file)
@@ -2416,6 +2416,9 @@ const struct oper_class_map global_op_class[] = {
        { HOSTAPD_MODE_IEEE80211A, 135, 1, 233, 16, BW80P80, NO_P2P_SUPP },
        { HOSTAPD_MODE_IEEE80211A, 136, 2, 2, 4, BW20, NO_P2P_SUPP },
 
+       /* IEEE P802.11be/D5.0, Table E-4 (Global operating classes) */
+       { HOSTAPD_MODE_IEEE80211A, 137, 31, 191, 32, BW320, NO_P2P_SUPP },
+
        /*
         * IEEE Std 802.11ad-2012 and P802.ay/D5.0 60 GHz operating classes.
         * Class 180 has the legacy channels 1-6. Classes 181-183 include
@@ -2737,6 +2740,8 @@ int oper_class_bw_to_int(const struct oper_class_map *map)
        case BW80P80:
        case BW160:
                return 160;
+       case BW320:
+               return 320;
        case BW2160:
                return 2160;
        default:
index 38cc091746e18b562e571b03bd559032f6539644..24be71b456a7684c174f99e9631a797a8ddb0304 100644 (file)
@@ -253,7 +253,7 @@ struct oper_class_map {
        u8 max_chan;
        u8 inc;
        enum { BW20, BW40PLUS, BW40MINUS, BW40, BW80, BW2160, BW160, BW80P80,
-              BW4320, BW6480, BW8640} bw;
+              BW320, BW4320, BW6480, BW8640} bw;
        enum { P2P_SUPP, NO_P2P_SUPP } p2p;
 };
 
index b4ad3caef6087701875e37dbea7ae8846207027a..d5742de7b3581265c4bb2372e27a310526fbd613 100644 (file)
@@ -22,13 +22,12 @@ static enum chan_allowed allow_channel(struct hostapd_hw_modes *mode,
                                       unsigned int *flags)
 {
        int i;
-       bool is_6ghz = op_class >= 131 && op_class <= 136;
+       bool is_6ghz = is_6ghz_op_class(op_class);
 
        for (i = 0; i < mode->num_channels; i++) {
                bool chan_is_6ghz;
 
-               chan_is_6ghz = mode->channels[i].freq >= 5935 &&
-                       mode->channels[i].freq <= 7115;
+               chan_is_6ghz = is_6ghz_freq(mode->channels[i].freq);
                if (is_6ghz == chan_is_6ghz && mode->channels[i].chan == chan)
                        break;
        }
@@ -187,6 +186,69 @@ static enum chan_allowed verify_160mhz(struct hostapd_hw_modes *mode,
 }
 
 
+static int get_center_320mhz(struct hostapd_hw_modes *mode, u8 channel,
+                            const u8 *center_channels, size_t num_chan)
+{
+       unsigned int i;
+
+       if (mode->mode != HOSTAPD_MODE_IEEE80211A || !mode->is_6ghz)
+               return 0;
+
+       for (i = 0; i < num_chan; i++) {
+               /*
+               * In 320 MHz, the bandwidth "spans" 60 channels (e.g., 65-125),
+               * so the center channel is 30 channels away from the start/end.
+               */
+               if (channel >= center_channels[i] - 30 &&
+                   channel <= center_channels[i] + 30)
+                       return center_channels[i];
+       }
+
+       return 0;
+}
+
+
+static enum chan_allowed verify_320mhz(struct hostapd_hw_modes *mode,
+                                      u8 op_class, u8 channel)
+{
+       u8 center_chan;
+       unsigned int i;
+       bool no_ir = false;
+       const u8 *center_channels;
+       size_t num_chan;
+       const u8 center_channels_6ghz[] = { 31, 63, 95, 127, 159, 191 };
+
+       center_channels = center_channels_6ghz;
+       num_chan = ARRAY_SIZE(center_channels_6ghz);
+
+       center_chan = get_center_320mhz(mode, channel, center_channels,
+                                       num_chan);
+       if (!center_chan)
+               return NOT_ALLOWED;
+
+       /* Check all the channels are available */
+       for (i = 0; i < 16; i++) {
+               unsigned int flags;
+               u8 adj_chan = center_chan - 30 + i * 4;
+
+               if (allow_channel(mode, op_class, adj_chan, &flags) ==
+                   NOT_ALLOWED)
+                       return NOT_ALLOWED;
+
+               if (!(flags & HOSTAPD_CHAN_EHT_320MHZ_SUBCHANNEL))
+                       return NOT_ALLOWED;
+
+               if (flags & HOSTAPD_CHAN_NO_IR)
+                       no_ir = true;
+       }
+
+       if (no_ir)
+               return NO_IR;
+
+       return ALLOWED;
+}
+
+
 enum chan_allowed verify_channel(struct hostapd_hw_modes *mode, u8 op_class,
                                 u8 channel, u8 bw)
 {
@@ -228,6 +290,13 @@ enum chan_allowed verify_channel(struct hostapd_hw_modes *mode, u8 op_class,
                 * result and use only the 80 MHz specific version.
                 */
                res2 = res = verify_80mhz(mode, op_class, channel);
+       } else if (bw == BW320) {
+               /*
+                * channel is a center channel and as such, not necessarily a
+                * valid 20 MHz channels. Override earlier allow_channel()
+                * result and use only the 320 MHz specific version.
+                */
+               res2= res = verify_320mhz(mode, op_class, channel);
        }
 
        if (res == NOT_ALLOWED || res2 == NOT_ALLOWED)
index 9673b29de02727b9cb81fc42e3f3abb982958470..2ec43105ceec5c5af09f9e898b64ded07d98bdd6 100644 (file)
@@ -515,6 +515,8 @@ static int * wpas_add_channels(const struct oper_class_map *op,
                num_primary_channels = 4;
        else if (op->bw == BW160)
                num_primary_channels = 8;
+       else if (op->bw == BW320)
+               num_primary_channels = 16;
        else
                num_primary_channels = 1;
 
@@ -561,6 +563,7 @@ static int * wpas_op_class_freqs(const struct oper_class_map *op,
        u8 channels_80mhz_6ghz[] = { 7, 23, 39, 55, 71, 87, 103, 119, 135, 151,
                                     167, 183, 199, 215 };
        u8 channels_160mhz_6ghz[] = { 15, 47, 79, 111, 143, 175, 207 };
+       u8 channels_320mhz_6ghz[] = { 31, 63, 95, 127, 159, 191 };
        const u8 *channels = NULL;
        size_t num_chan = 0;
        bool is_6ghz = is_6ghz_op_class(op->op_class);
@@ -579,6 +582,9 @@ static int * wpas_op_class_freqs(const struct oper_class_map *op,
                        channels_160mhz_5ghz;
                num_chan =  is_6ghz ? ARRAY_SIZE(channels_160mhz_6ghz) :
                        ARRAY_SIZE(channels_160mhz_5ghz);
+       } else if (op->bw == BW320) {
+               channels = channels_320mhz_6ghz;
+               num_chan = ARRAY_SIZE(channels_320mhz_6ghz);
        }
 
        return wpas_add_channels(op, mode, channels, num_chan);