1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
|
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* IEEE 802.11 UHR definitions
*
* Copyright (c) 2025-2026 Intel Corporation
*/
#ifndef LINUX_IEEE80211_UHR_H
#define LINUX_IEEE80211_UHR_H
#include <linux/types.h>
#include <linux/if_ether.h>
#define IEEE80211_UHR_OPER_PARAMS_DPS_ENA 0x0001
#define IEEE80211_UHR_OPER_PARAMS_NPCA_ENA 0x0002
#define IEEE80211_UHR_OPER_PARAMS_PEDCA_ENA 0x0004
#define IEEE80211_UHR_OPER_PARAMS_DBE_ENA 0x0008
struct ieee80211_uhr_operation {
__le16 params;
u8 basic_mcs_nss_set[4];
u8 variable[];
} __packed;
#define IEEE80211_UHR_NPCA_PARAMS_PRIMARY_CHAN_OFFS 0x0000000F
#define IEEE80211_UHR_NPCA_PARAMS_MIN_DUR_THRESH 0x000000F0
#define IEEE80211_UHR_NPCA_PARAMS_SWITCH_DELAY 0x00003F00
#define IEEE80211_UHR_NPCA_PARAMS_SWITCH_BACK_DELAY 0x000FC000
#define IEEE80211_UHR_NPCA_PARAMS_INIT_QSRC 0x00300000
#define IEEE80211_UHR_NPCA_PARAMS_MOPLEN 0x00400000
#define IEEE80211_UHR_NPCA_PARAMS_DIS_SUBCH_BMAP_PRES 0x00800000
/**
* struct ieee80211_uhr_npca_info - npca operation information
*
* This structure is the "NPCA Operation Parameters field format" of "UHR
* Operation Element" fields as described in P802.11bn_D1.3
* subclause 9.4.2.353. See Figure 9-aa4.
*
* Refer to IEEE80211_UHR_NPCA*
* @params:
* NPCA Primary Channel - NPCA primary channel
* NPCA_Min Duration Threshold - Minimum duration of inter-BSS activity
* NPCA Switching Delay -
* Time needed by an NPCA AP to switch from the
* BSS primary channel to the NPCA primary channel
* in the unit of 4 µs.
* NPCA Switching Back Delay -
* Time to switch from the NPCA primary channel
* to the BSS primary channel in the unit of 4 µs.
* NPCA Initial QSRC -
* Initialize the EDCAF QSRC[AC] variables
* when an NPCA STA in the BSS
* switches to NPCA operation.
* NPCA MOPLEN -
* Indicates which conditions can be used to
* initiate an NPCA operation,
* 1 -> both PHYLEN NPCA operation and MOPLEN
* NPCA operation are
* permitted in the BSS
* 0 -> only PHYLEN NPCA operation is allowed in the BSS.
* NPCA Disabled Subchannel Bitmap Present -
* Indicates whether the NPCA Disabled Subchannel
* Bitmap field is present. A 1 in this field indicates that
* the NPCA Disabled Subchannel Bitmap field is present
* @dis_subch_bmap:
* A bit in the bitmap that lies within the BSS bandwidth is set
* to 1 to indicate that the corresponding 20 MHz subchannel is
* punctured and is set to 0 to indicate that the corresponding
* 20 MHz subchannel is not punctured. A bit in the bitmap that
* falls outside of the BSS bandwidth is reserved. This field is
* present when the value of the NPCA Disabled Subchannel Bitmap
* Field Present field is equal to 1, and not present, otherwise
*/
struct ieee80211_uhr_npca_info {
__le32 params;
__le16 dis_subch_bmap[];
} __packed;
#define IEEE80211_UHR_DPS_PADDING_DELAY 0x0000003F
#define IEEE80211_UHR_DPS_TRANSITION_DELAY 0x00003F00
#define IEEE80211_UHR_DPS_ICF_REQUIRED 0x00010000
#define IEEE80211_UHR_DPS_PARAMETERIZED_FLAG 0x00020000
#define IEEE80211_UHR_DPS_LC_MODE_BW 0x001C0000
#define IEEE80211_UHR_DPS_LC_MODE_NSS 0x01E00000
#define IEEE80211_UHR_DPS_LC_MODE_MCS 0x1E000000
#define IEEE80211_UHR_DPS_MOBILE_AP_DPS_STATIC_HCM 0x20000000
/**
* struct ieee80211_uhr_dps_info - DPS operation information
*
* This structure is the "DPS Operation Parameter field" of "UHR
* Operation Element" fields as described in P802.11bn_D1.3
* subclause 9.4.1.87. See Figure 9-207u.
*
* Refer to IEEE80211_UHR_DPS*
* @params:
* DPS Padding Delay -
* Indicates the minimum MAC padding
* duration that is required by a DPS STA
* in an ICF to cause the STA to transition
* from the lower capability mode to the
* higher capability mode. The DPS Padding
* Delay field is in units of 4 µs.
* DPS Transition Delay -
* Indicates the amount of time required by a
* DPS STA to transition from the higher
* capability mode to the lower capability
* mode. The DPS Transition Delay field is in
* units of 4 µs.
* ICF Required -
* Indicates when the DPS assisting STA needs
* to transmit an ICF frame to the peer DPS STA
* before performing the frame exchanges with
* the peer DPS STA in a TXOP.
* 1 -> indicates that the transmission of the
* ICF frame to the peer DPS STA prior to
* any frame exchange is needed.
* 0 -> ICF transmission before the frame
* exchanges with the peer DPS STA is only
* needed if the frame exchange is performed
* in the HC mode.
* Parameterized Flag -
* 0 -> indicates that only 20 MHz, 1 SS,
* non-HT PPDU format with the data
* rate of 6, 12, and 24 Mb/s as the
* default mode are supported by the
* DPS STA in the LC mode
* 1 -> indicates that a bandwidth up to the
* bandwidth indicated in the LC Mode
* Bandwidth field, a number of spatial
* streams up to the NSS indicated in
* the LC Mode Nss field, and an MCS up
* to the MCS indicated in the LC Mode
* MCS fields are supported by the DPS
* STA in the LC mode as the
* parameterized mode.
* LC Mode Bandwidth -
* Indicates the maximum bandwidth supported
* by the STA in the LC mode.
* LC Mode NSS -
* Indicates the maximum number of the spatial
* streams supported by the STA in the LC mode.
* LC Mode MCS -
* Indicates the highest MCS supported by the STA
* in the LC mode.
* Mobile AP DPS Static HCM -
* 1 -> indicates that it will remain in the DPS high
* capability mode until the next TBTT on that
* link.
* 0 -> otherwise.
*/
struct ieee80211_uhr_dps_info {
__le32 params;
} __packed;
#define IEEE80211_UHR_DBE_OPER_BANDWIDTH 0x07
#define IEEE80211_UHR_DBE_OPER_DIS_SUBCHANNEL_BITMAP_PRES 0x08
/**
* enum ieee80211_uhr_dbe_oper_bw - DBE Operational Bandwidth
*
* Encoding for the DBE Operational Bandwidth field in the UHR Operation
* element (DBE Operation Parameters).
*
* @IEEE80211_UHR_DBE_OPER_BW_40: 40 MHz operational DBE bandwidth
* @IEEE80211_UHR_DBE_OPER_BW_80: 80 MHz operational DBE bandwidth
* @IEEE80211_UHR_DBE_OPER_BW_160: 160 MHz operational DBE bandwidth
* @IEEE80211_UHR_DBE_OPER_BW_320_1: 320-1 MHz operational DBE bandwidth
* @IEEE80211_UHR_DBE_OPER_BW_320_2: 320-2 MHz operational DBE bandwidth
*/
enum ieee80211_uhr_dbe_oper_bw {
IEEE80211_UHR_DBE_OPER_BW_40 = 1,
IEEE80211_UHR_DBE_OPER_BW_80 = 2,
IEEE80211_UHR_DBE_OPER_BW_160 = 3,
IEEE80211_UHR_DBE_OPER_BW_320_1 = 4,
IEEE80211_UHR_DBE_OPER_BW_320_2 = 5,
};
/**
* struct ieee80211_uhr_dbe_info - DBE operation information
*
* This structure is the "DBE Operation Parameters field" of
* "UHR Operation Element" fields as described in P802.11bn_D1.3
* subclause 9.4.2.353. See Figure 9-aa6.
*
* Refer to IEEE80211_UHR_DBE_OPER*
* @params:
* B0-B2 - DBE Operational Bandwidth field, see
* "enum ieee80211_uhr_dbe_oper_bw" for values.
* Value 0 is reserved.
* Value 1 indicates 40 MHz operational DBE bandwidth.
* Value 2 indicates 80 MHz operational DBE bandwidth.
* Value 3 indicates 160 MHz operational DBE bandwidth.
* Value 4 indicates 320-1 MHz operational DBE bandwidth.
* Value 5 indicates 320-2 MHz operational DBE bandwidth.
* Values 6 to 7 are reserved.
* B3 - DBE Disabled Subchannel Bitmap Present.
* @dis_subch_bmap: DBE Disabled Subchannel Bitmap field is set to indicate
* disabled 20 MHz subchannels within the DBE Bandwidth.
*/
struct ieee80211_uhr_dbe_info {
u8 params;
__le16 dis_subch_bmap[];
} __packed;
#define IEEE80211_UHR_P_EDCA_ECWMIN 0x0F
#define IEEE80211_UHR_P_EDCA_ECWMAX 0xF0
#define IEEE80211_UHR_P_EDCA_AIFSN 0x000F
#define IEEE80211_UHR_P_EDCA_CW_DS 0x0030
#define IEEE80211_UHR_P_EDCA_PSRC_THRESHOLD 0x01C0
#define IEEE80211_UHR_P_EDCA_QSRC_THRESHOLD 0x0600
/**
* struct ieee80211_uhr_p_edca_info - P-EDCA operation information
*
* This structure is the "P-EDCA Operation Parameters field" of
* "UHR Operation Element" fields as described in P802.11bn_D1.3
* subclause 9.4.2.353. See Figure 9-aa5.
*
* Refer to IEEE80211_UHR_P_EDCA*
* @p_edca_ec: P-EDCA ECWmin and ECWmax.
* These fields indicate the CWmin and CWmax values used by a
* P-EDCA STA during P-EDCA contention.
* @params: AIFSN, CW DS, PSRC threshold, and QSRC threshold.
* - The AIFSN field indicates the AIFSN value used by a P-EDCA STA
* during P-EDCA contention.
* - The CW DS field indicates the value used for randomization of the
* transmission slot of the DS-CTS frame. The value 3 is reserved.
* The value 0 indicates that randomization is not enabled.
* - The P-EDCA PSRC threshold field indicates the maximum number of
* allowed consecutive DS-CTS transmissions. The value 0 and values
* greater than 4 are reserved.
* - The P-EDCA QSRC threshold field indicates the value of the
* QSRC[AC_VO] counter required to start P-EDCA contention. The
* value 0 is reserved.
*/
struct ieee80211_uhr_p_edca_info {
u8 p_edca_ec;
__le16 params;
} __packed;
static inline bool ieee80211_uhr_oper_size_ok(const u8 *data, u8 len,
bool beacon)
{
const struct ieee80211_uhr_operation *oper = (const void *)data;
u8 needed = sizeof(*oper);
if (len < needed)
return false;
/* nothing else present in beacons */
if (beacon)
return true;
/* DPS Operation Parameters (fixed 4 bytes) */
if (oper->params & cpu_to_le16(IEEE80211_UHR_OPER_PARAMS_DPS_ENA)) {
needed += sizeof(struct ieee80211_uhr_dps_info);
if (len < needed)
return false;
}
/* NPCA Operation Parameters (fixed 4 bytes + optional 2 bytes) */
if (oper->params & cpu_to_le16(IEEE80211_UHR_OPER_PARAMS_NPCA_ENA)) {
const struct ieee80211_uhr_npca_info *npca =
(const void *)(data + needed);
needed += sizeof(*npca);
if (len < needed)
return false;
if (npca->params &
cpu_to_le32(IEEE80211_UHR_NPCA_PARAMS_DIS_SUBCH_BMAP_PRES)) {
needed += sizeof(npca->dis_subch_bmap[0]);
if (len < needed)
return false;
}
}
/* P-EDCA Operation Parameters (fixed 3 bytes) */
if (oper->params & cpu_to_le16(IEEE80211_UHR_OPER_PARAMS_PEDCA_ENA)) {
needed += sizeof(struct ieee80211_uhr_p_edca_info);
if (len < needed)
return false;
}
/* DBE Operation Parameters (fixed 1 byte + optional 2 bytes) */
if (oper->params & cpu_to_le16(IEEE80211_UHR_OPER_PARAMS_DBE_ENA)) {
const struct ieee80211_uhr_dbe_info *dbe =
(const void *)(data + needed);
needed += sizeof(*dbe);
if (len < needed)
return false;
if (dbe->params &
IEEE80211_UHR_DBE_OPER_DIS_SUBCHANNEL_BITMAP_PRES) {
needed += sizeof(dbe->dis_subch_bmap[0]);
if (len < needed)
return false;
}
}
return len >= needed;
}
/*
* Note: cannot call this on the element coming from a beacon,
* must ensure ieee80211_uhr_oper_size_ok(..., false) first
*/
static inline const struct ieee80211_uhr_npca_info *
ieee80211_uhr_npca_info(const struct ieee80211_uhr_operation *oper)
{
const u8 *pos = oper->variable;
if (!(oper->params & cpu_to_le16(IEEE80211_UHR_OPER_PARAMS_NPCA_ENA)))
return NULL;
if (oper->params & cpu_to_le16(IEEE80211_UHR_OPER_PARAMS_DPS_ENA))
pos += sizeof(struct ieee80211_uhr_dps_info);
return (const void *)pos;
}
static inline const __le16 *
ieee80211_uhr_npca_dis_subch_bitmap(const struct ieee80211_uhr_operation *oper)
{
const struct ieee80211_uhr_npca_info *npca;
npca = ieee80211_uhr_npca_info(oper);
if (!npca)
return NULL;
if (!(npca->params & cpu_to_le32(IEEE80211_UHR_NPCA_PARAMS_DIS_SUBCH_BMAP_PRES)))
return NULL;
return npca->dis_subch_bmap;
}
#define IEEE80211_UHR_MAC_CAP0_DPS_SUPP 0x01
#define IEEE80211_UHR_MAC_CAP0_DPS_ASSIST_SUPP 0x02
#define IEEE80211_UHR_MAC_CAP0_DPS_AP_STATIC_HCM_SUPP 0x04
#define IEEE80211_UHR_MAC_CAP0_NPCA_SUPP 0x10
#define IEEE80211_UHR_MAC_CAP0_ENH_BSR_SUPP 0x20
#define IEEE80211_UHR_MAC_CAP0_ADD_MAP_TID_SUPP 0x40
#define IEEE80211_UHR_MAC_CAP0_EOTSP_SUPP 0x80
#define IEEE80211_UHR_MAC_CAP1_DSO_SUPP 0x01
#define IEEE80211_UHR_MAC_CAP1_PEDCA_SUPP 0x02
#define IEEE80211_UHR_MAC_CAP1_DBE_SUPP 0x04
#define IEEE80211_UHR_MAC_CAP1_UL_LLI_SUPP 0x08
#define IEEE80211_UHR_MAC_CAP1_P2P_LLI_SUPP 0x10
#define IEEE80211_UHR_MAC_CAP1_PUO_SUPP 0x20
#define IEEE80211_UHR_MAC_CAP1_AP_PUO_SUPP 0x40
#define IEEE80211_UHR_MAC_CAP1_DUO_SUPP 0x80
#define IEEE80211_UHR_MAC_CAP2_OMC_UL_MU_DIS_RX_SUPP 0x01
#define IEEE80211_UHR_MAC_CAP2_AOM_SUPP 0x02
#define IEEE80211_UHR_MAC_CAP2_IFCS_LOC_SUPP 0x04
#define IEEE80211_UHR_MAC_CAP2_UHR_TRS_SUPP 0x08
#define IEEE80211_UHR_MAC_CAP2_TXSPG_SUPP 0x10
#define IEEE80211_UHR_MAC_CAP2_TXOP_RET_IN_TXSPG 0x20
#define IEEE80211_UHR_MAC_CAP2_UHR_OM_PU_TO_LOW 0xC0
#define IEEE80211_UHR_MAC_CAP3_UHR_OM_PU_TO_HIGH 0x03
#define IEEE80211_UHR_MAC_CAP3_PARAM_UPD_ADV_NOTIF_INTV 0x1C
#define IEEE80211_UHR_MAC_CAP3_UPD_IND_TIM_INTV_LOW 0xE0
#define IEEE80211_UHR_MAC_CAP4_UPD_IND_TIM_INTV_HIGH 0x03
#define IEEE80211_UHR_MAC_CAP4_BOUNDED_ESS 0x04
#define IEEE80211_UHR_MAC_CAP4_BTM_ASSURANCE 0x08
#define IEEE80211_UHR_MAC_CAP4_CO_BF_SUPP 0x10
#define IEEE80211_UHR_MAC_CAP_DBE_MAX_BW 0x07
#define IEEE80211_UHR_MAC_CAP_DBE_EHT_MCS_MAP_160_PRES 0x08
#define IEEE80211_UHR_MAC_CAP_DBE_EHT_MCS_MAP_320_PRES 0x10
/**
* enum ieee80211_uhr_dbe_max_supported_bw - DBE Maximum Supported Bandwidth
*
* As per spec P802.11bn_D1.3 "Table 9-bb5—Encoding of the DBE Maximum
* Supported Bandwidth field".
*
* @IEEE80211_UHR_DBE_MAX_BW_40: Indicates 40 MHz DBE max supported bw
* @IEEE80211_UHR_DBE_MAX_BW_80: Indicates 80 MHz DBE max supported bw
* @IEEE80211_UHR_DBE_MAX_BW_160: Indicates 160 MHz DBE max supported bw
* @IEEE80211_UHR_DBE_MAX_BW_320: Indicates 320 MHz DBE max supported bw
*/
enum ieee80211_uhr_dbe_max_supported_bw {
IEEE80211_UHR_DBE_MAX_BW_40 = 1,
IEEE80211_UHR_DBE_MAX_BW_80 = 2,
IEEE80211_UHR_DBE_MAX_BW_160 = 3,
IEEE80211_UHR_DBE_MAX_BW_320 = 4,
};
struct ieee80211_uhr_cap_mac {
u8 mac_cap[5];
} __packed;
struct ieee80211_uhr_cap {
struct ieee80211_uhr_cap_mac mac;
/* DBE, PHY capabilities */
u8 variable[];
} __packed;
#define IEEE80211_UHR_PHY_CAP_MAX_NSS_RX_SND_NDP_LE80 0x01
#define IEEE80211_UHR_PHY_CAP_MAX_NSS_RX_DL_MU_LE80 0x02
#define IEEE80211_UHR_PHY_CAP_MAX_NSS_RX_SND_NDP_160 0x04
#define IEEE80211_UHR_PHY_CAP_MAX_NSS_RX_DL_MU_160 0x08
#define IEEE80211_UHR_PHY_CAP_MAX_NSS_RX_SND_NDP_320 0x10
#define IEEE80211_UHR_PHY_CAP_MAX_NSS_RX_DL_MU_320 0x20
#define IEEE80211_UHR_PHY_CAP_ELR_RX 0x40
#define IEEE80211_UHR_PHY_CAP_ELR_TX 0x80
struct ieee80211_uhr_cap_phy {
u8 cap;
} __packed;
static inline bool ieee80211_uhr_capa_size_ok(const u8 *data, u8 len,
bool from_ap)
{
const struct ieee80211_uhr_cap *cap = (const void *)data;
size_t needed = sizeof(*cap) + sizeof(struct ieee80211_uhr_cap_phy);
if (len < needed)
return false;
/*
* A non-AP STA does not include the DBE Capability Parameters field
* in the UHR MAC Capabilities Information field.
*/
if (from_ap && cap->mac.mac_cap[1] & IEEE80211_UHR_MAC_CAP1_DBE_SUPP) {
u8 dbe;
needed += 1;
if (len < needed)
return false;
dbe = cap->variable[0];
if (dbe & IEEE80211_UHR_MAC_CAP_DBE_EHT_MCS_MAP_160_PRES)
needed += 3;
if (dbe & IEEE80211_UHR_MAC_CAP_DBE_EHT_MCS_MAP_320_PRES)
needed += 3;
}
return len >= needed;
}
static inline const struct ieee80211_uhr_cap_phy *
ieee80211_uhr_phy_cap(const struct ieee80211_uhr_cap *cap, bool from_ap)
{
u8 offs = 0;
if (from_ap && cap->mac.mac_cap[1] & IEEE80211_UHR_MAC_CAP1_DBE_SUPP) {
u8 dbe = cap->variable[0];
offs += 1;
if (dbe & IEEE80211_UHR_MAC_CAP_DBE_EHT_MCS_MAP_160_PRES)
offs += 3;
if (dbe & IEEE80211_UHR_MAC_CAP_DBE_EHT_MCS_MAP_320_PRES)
offs += 3;
}
return (const void *)&cap->variable[offs];
}
#define IEEE80211_SMD_INFO_CAPA_DL_DATA_FWD 0x01
#define IEEE80211_SMD_INFO_CAPA_MAX_NUM_PREP 0x0E
#define IEEE80211_SMD_INFO_CAPA_TYPE 0x10
#define IEEE80211_SMD_INFO_CAPA_PTK_PER_AP_MLD 0x20
struct ieee80211_smd_info {
u8 id[ETH_ALEN];
u8 capa;
__le16 timeout;
} __packed;
#endif /* LINUX_IEEE80211_UHR_H */
|