Extend support for the 6 GHz operating class 137 (320 MHz)

Commit 085a3fc76e ("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>
This commit is contained in:
Ainy Kumari 2024-02-22 09:32:04 +05:30 committed by Jouni Malinen
parent e74d95e0aa
commit 5dabc10185
4 changed files with 84 additions and 4 deletions

View 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:

View 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;
};

View 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)

View 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);