Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1/* SPDX-License-Identifier: GPL-2.0-only */
2/*
3 * IEEE 802.11 S1G definitions
4 *
5 * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
6 * <jkmaline@cc.hut.fi>
7 * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
8 * Copyright (c) 2005, Devicescape Software, Inc.
9 * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
10 * Copyright (c) 2013 - 2014 Intel Mobile Communications GmbH
11 * Copyright (c) 2016 - 2017 Intel Deutschland GmbH
12 * Copyright (c) 2018 - 2025 Intel Corporation
13 */
14
15#ifndef LINUX_IEEE80211_S1G_H
16#define LINUX_IEEE80211_S1G_H
17
18#include <linux/types.h>
19#include <linux/if_ether.h>
20
21/* bits unique to S1G beacon frame control */
22#define IEEE80211_S1G_BCN_NEXT_TBTT 0x100
23#define IEEE80211_S1G_BCN_CSSID 0x200
24#define IEEE80211_S1G_BCN_ANO 0x400
25
26/* see 802.11ah-2016 9.9 NDP CMAC frames */
27#define IEEE80211_S1G_1MHZ_NDP_BITS 25
28#define IEEE80211_S1G_1MHZ_NDP_BYTES 4
29#define IEEE80211_S1G_2MHZ_NDP_BITS 37
30#define IEEE80211_S1G_2MHZ_NDP_BYTES 5
31
32/**
33 * ieee80211_is_s1g_beacon - check if IEEE80211_FTYPE_EXT &&
34 * IEEE80211_STYPE_S1G_BEACON
35 * @fc: frame control bytes in little-endian byteorder
36 * Return: whether or not the frame is an S1G beacon
37 */
38static inline bool ieee80211_is_s1g_beacon(__le16 fc)
39{
40 return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE |
41 IEEE80211_FCTL_STYPE)) ==
42 cpu_to_le16(IEEE80211_FTYPE_EXT | IEEE80211_STYPE_S1G_BEACON);
43}
44
45/**
46 * ieee80211_s1g_has_next_tbtt - check if IEEE80211_S1G_BCN_NEXT_TBTT
47 * @fc: frame control bytes in little-endian byteorder
48 * Return: whether or not the frame contains the variable-length
49 * next TBTT field
50 */
51static inline bool ieee80211_s1g_has_next_tbtt(__le16 fc)
52{
53 return ieee80211_is_s1g_beacon(fc) &&
54 (fc & cpu_to_le16(IEEE80211_S1G_BCN_NEXT_TBTT));
55}
56
57/**
58 * ieee80211_s1g_has_ano - check if IEEE80211_S1G_BCN_ANO
59 * @fc: frame control bytes in little-endian byteorder
60 * Return: whether or not the frame contains the variable-length
61 * ANO field
62 */
63static inline bool ieee80211_s1g_has_ano(__le16 fc)
64{
65 return ieee80211_is_s1g_beacon(fc) &&
66 (fc & cpu_to_le16(IEEE80211_S1G_BCN_ANO));
67}
68
69/**
70 * ieee80211_s1g_has_cssid - check if IEEE80211_S1G_BCN_CSSID
71 * @fc: frame control bytes in little-endian byteorder
72 * Return: whether or not the frame contains the variable-length
73 * compressed SSID field
74 */
75static inline bool ieee80211_s1g_has_cssid(__le16 fc)
76{
77 return ieee80211_is_s1g_beacon(fc) &&
78 (fc & cpu_to_le16(IEEE80211_S1G_BCN_CSSID));
79}
80
81/**
82 * enum ieee80211_s1g_chanwidth - S1G channel widths
83 * These are defined in IEEE802.11-2016ah Table 10-20
84 * as BSS Channel Width
85 *
86 * @IEEE80211_S1G_CHANWIDTH_1MHZ: 1MHz operating channel
87 * @IEEE80211_S1G_CHANWIDTH_2MHZ: 2MHz operating channel
88 * @IEEE80211_S1G_CHANWIDTH_4MHZ: 4MHz operating channel
89 * @IEEE80211_S1G_CHANWIDTH_8MHZ: 8MHz operating channel
90 * @IEEE80211_S1G_CHANWIDTH_16MHZ: 16MHz operating channel
91 */
92enum ieee80211_s1g_chanwidth {
93 IEEE80211_S1G_CHANWIDTH_1MHZ = 0,
94 IEEE80211_S1G_CHANWIDTH_2MHZ = 1,
95 IEEE80211_S1G_CHANWIDTH_4MHZ = 3,
96 IEEE80211_S1G_CHANWIDTH_8MHZ = 7,
97 IEEE80211_S1G_CHANWIDTH_16MHZ = 15,
98};
99
100/**
101 * enum ieee80211_s1g_pri_chanwidth - S1G primary channel widths
102 * described in IEEE80211-2024 Table 10-39.
103 *
104 * @IEEE80211_S1G_PRI_CHANWIDTH_2MHZ: 2MHz primary channel
105 * @IEEE80211_S1G_PRI_CHANWIDTH_1MHZ: 1MHz primary channel
106 */
107enum ieee80211_s1g_pri_chanwidth {
108 IEEE80211_S1G_PRI_CHANWIDTH_2MHZ = 0,
109 IEEE80211_S1G_PRI_CHANWIDTH_1MHZ = 1,
110};
111
112/**
113 * struct ieee80211_s1g_bcn_compat_ie - S1G Beacon Compatibility element
114 * @compat_info: Compatibility Information
115 * @beacon_int: Beacon Interval
116 * @tsf_completion: TSF Completion
117 *
118 * This structure represents the payload of the "S1G Beacon
119 * Compatibility element" as described in IEEE Std 802.11-2020 section
120 * 9.4.2.196.
121 */
122struct ieee80211_s1g_bcn_compat_ie {
123 __le16 compat_info;
124 __le16 beacon_int;
125 __le32 tsf_completion;
126} __packed;
127
128/**
129 * struct ieee80211_s1g_oper_ie - S1G Operation element
130 * @ch_width: S1G Operation Information Channel Width
131 * @oper_class: S1G Operation Information Operating Class
132 * @primary_ch: S1G Operation Information Primary Channel Number
133 * @oper_ch: S1G Operation Information Channel Center Frequency
134 * @basic_mcs_nss: Basic S1G-MCS and NSS Set
135 *
136 * This structure represents the payload of the "S1G Operation
137 * element" as described in IEEE Std 802.11-2020 section 9.4.2.212.
138 */
139struct ieee80211_s1g_oper_ie {
140 u8 ch_width;
141 u8 oper_class;
142 u8 primary_ch;
143 u8 oper_ch;
144 __le16 basic_mcs_nss;
145} __packed;
146
147/**
148 * struct ieee80211_aid_response_ie - AID Response element
149 * @aid: AID/Group AID
150 * @switch_count: AID Switch Count
151 * @response_int: AID Response Interval
152 *
153 * This structure represents the payload of the "AID Response element"
154 * as described in IEEE Std 802.11-2020 section 9.4.2.194.
155 */
156struct ieee80211_aid_response_ie {
157 __le16 aid;
158 u8 switch_count;
159 __le16 response_int;
160} __packed;
161
162struct ieee80211_s1g_cap {
163 u8 capab_info[10];
164 u8 supp_mcs_nss[5];
165} __packed;
166
167/**
168 * ieee80211_s1g_optional_len - determine length of optional S1G beacon fields
169 * @fc: frame control bytes in little-endian byteorder
170 * Return: total length in bytes of the optional fixed-length fields
171 *
172 * S1G beacons may contain up to three optional fixed-length fields that
173 * precede the variable-length elements. Whether these fields are present
174 * is indicated by flags in the frame control field.
175 *
176 * From IEEE 802.11-2024 section 9.3.4.3:
177 * - Next TBTT field may be 0 or 3 bytes
178 * - Short SSID field may be 0 or 4 bytes
179 * - Access Network Options (ANO) field may be 0 or 1 byte
180 */
181static inline size_t
182ieee80211_s1g_optional_len(__le16 fc)
183{
184 size_t len = 0;
185
186 if (ieee80211_s1g_has_next_tbtt(fc))
187 len += 3;
188
189 if (ieee80211_s1g_has_cssid(fc))
190 len += 4;
191
192 if (ieee80211_s1g_has_ano(fc))
193 len += 1;
194
195 return len;
196}
197
198/* S1G Capabilities Information field */
199#define IEEE80211_S1G_CAPABILITY_LEN 15
200
201#define S1G_CAP0_S1G_LONG BIT(0)
202#define S1G_CAP0_SGI_1MHZ BIT(1)
203#define S1G_CAP0_SGI_2MHZ BIT(2)
204#define S1G_CAP0_SGI_4MHZ BIT(3)
205#define S1G_CAP0_SGI_8MHZ BIT(4)
206#define S1G_CAP0_SGI_16MHZ BIT(5)
207#define S1G_CAP0_SUPP_CH_WIDTH GENMASK(7, 6)
208
209#define S1G_SUPP_CH_WIDTH_2 0
210#define S1G_SUPP_CH_WIDTH_4 1
211#define S1G_SUPP_CH_WIDTH_8 2
212#define S1G_SUPP_CH_WIDTH_16 3
213#define S1G_SUPP_CH_WIDTH_MAX(cap) ((1 << FIELD_GET(S1G_CAP0_SUPP_CH_WIDTH, \
214 cap[0])) << 1)
215
216#define S1G_CAP1_RX_LDPC BIT(0)
217#define S1G_CAP1_TX_STBC BIT(1)
218#define S1G_CAP1_RX_STBC BIT(2)
219#define S1G_CAP1_SU_BFER BIT(3)
220#define S1G_CAP1_SU_BFEE BIT(4)
221#define S1G_CAP1_BFEE_STS GENMASK(7, 5)
222
223#define S1G_CAP2_SOUNDING_DIMENSIONS GENMASK(2, 0)
224#define S1G_CAP2_MU_BFER BIT(3)
225#define S1G_CAP2_MU_BFEE BIT(4)
226#define S1G_CAP2_PLUS_HTC_VHT BIT(5)
227#define S1G_CAP2_TRAVELING_PILOT GENMASK(7, 6)
228
229#define S1G_CAP3_RD_RESPONDER BIT(0)
230#define S1G_CAP3_HT_DELAYED_BA BIT(1)
231#define S1G_CAP3_MAX_MPDU_LEN BIT(2)
232#define S1G_CAP3_MAX_AMPDU_LEN_EXP GENMASK(4, 3)
233#define S1G_CAP3_MIN_MPDU_START GENMASK(7, 5)
234
235#define S1G_CAP4_UPLINK_SYNC BIT(0)
236#define S1G_CAP4_DYNAMIC_AID BIT(1)
237#define S1G_CAP4_BAT BIT(2)
238#define S1G_CAP4_TIME_ADE BIT(3)
239#define S1G_CAP4_NON_TIM BIT(4)
240#define S1G_CAP4_GROUP_AID BIT(5)
241#define S1G_CAP4_STA_TYPE GENMASK(7, 6)
242
243#define S1G_CAP5_CENT_AUTH_CONTROL BIT(0)
244#define S1G_CAP5_DIST_AUTH_CONTROL BIT(1)
245#define S1G_CAP5_AMSDU BIT(2)
246#define S1G_CAP5_AMPDU BIT(3)
247#define S1G_CAP5_ASYMMETRIC_BA BIT(4)
248#define S1G_CAP5_FLOW_CONTROL BIT(5)
249#define S1G_CAP5_SECTORIZED_BEAM GENMASK(7, 6)
250
251#define S1G_CAP6_OBSS_MITIGATION BIT(0)
252#define S1G_CAP6_FRAGMENT_BA BIT(1)
253#define S1G_CAP6_NDP_PS_POLL BIT(2)
254#define S1G_CAP6_RAW_OPERATION BIT(3)
255#define S1G_CAP6_PAGE_SLICING BIT(4)
256#define S1G_CAP6_TXOP_SHARING_IMP_ACK BIT(5)
257#define S1G_CAP6_VHT_LINK_ADAPT GENMASK(7, 6)
258
259#define S1G_CAP7_TACK_AS_PS_POLL BIT(0)
260#define S1G_CAP7_DUP_1MHZ BIT(1)
261#define S1G_CAP7_MCS_NEGOTIATION BIT(2)
262#define S1G_CAP7_1MHZ_CTL_RESPONSE_PREAMBLE BIT(3)
263#define S1G_CAP7_NDP_BFING_REPORT_POLL BIT(4)
264#define S1G_CAP7_UNSOLICITED_DYN_AID BIT(5)
265#define S1G_CAP7_SECTOR_TRAINING_OPERATION BIT(6)
266#define S1G_CAP7_TEMP_PS_MODE_SWITCH BIT(7)
267
268#define S1G_CAP8_TWT_GROUPING BIT(0)
269#define S1G_CAP8_BDT BIT(1)
270#define S1G_CAP8_COLOR GENMASK(4, 2)
271#define S1G_CAP8_TWT_REQUEST BIT(5)
272#define S1G_CAP8_TWT_RESPOND BIT(6)
273#define S1G_CAP8_PV1_FRAME BIT(7)
274
275#define S1G_CAP9_LINK_ADAPT_PER_CONTROL_RESPONSE BIT(0)
276
277#define S1G_OPER_CH_WIDTH_PRIMARY BIT(0)
278#define S1G_OPER_CH_WIDTH_OPER GENMASK(4, 1)
279#define S1G_OPER_CH_PRIMARY_LOCATION BIT(5)
280
281#define S1G_2M_PRIMARY_LOCATION_LOWER 0
282#define S1G_2M_PRIMARY_LOCATION_UPPER 1
283
284#define LISTEN_INT_USF GENMASK(15, 14)
285#define LISTEN_INT_UI GENMASK(13, 0)
286
287#define IEEE80211_MAX_USF FIELD_MAX(LISTEN_INT_USF)
288#define IEEE80211_MAX_UI FIELD_MAX(LISTEN_INT_UI)
289
290/* S1G encoding types */
291#define IEEE80211_S1G_TIM_ENC_MODE_BLOCK 0
292#define IEEE80211_S1G_TIM_ENC_MODE_SINGLE 1
293#define IEEE80211_S1G_TIM_ENC_MODE_OLB 2
294
295enum ieee80211_s1g_actioncode {
296 WLAN_S1G_AID_SWITCH_REQUEST,
297 WLAN_S1G_AID_SWITCH_RESPONSE,
298 WLAN_S1G_SYNC_CONTROL,
299 WLAN_S1G_STA_INFO_ANNOUNCE,
300 WLAN_S1G_EDCA_PARAM_SET,
301 WLAN_S1G_EL_OPERATION,
302 WLAN_S1G_TWT_SETUP,
303 WLAN_S1G_TWT_TEARDOWN,
304 WLAN_S1G_SECT_GROUP_ID_LIST,
305 WLAN_S1G_SECT_ID_FEEDBACK,
306 WLAN_S1G_TWT_INFORMATION = 11,
307};
308
309/**
310 * ieee80211_is_s1g_short_beacon - check if frame is an S1G short beacon
311 * @fc: frame control bytes in little-endian byteorder
312 * @variable: pointer to the beacon frame elements
313 * @variable_len: length of the frame elements
314 * Return: whether or not the frame is an S1G short beacon. As per
315 * IEEE80211-2024 11.1.3.10.1, The S1G beacon compatibility element shall
316 * always be present as the first element in beacon frames generated at a
317 * TBTT (Target Beacon Transmission Time), so any frame not containing
318 * this element must have been generated at a TSBTT (Target Short Beacon
319 * Transmission Time) that is not a TBTT. Additionally, short beacons are
320 * prohibited from containing the S1G beacon compatibility element as per
321 * IEEE80211-2024 9.3.4.3 Table 9-76, so if we have an S1G beacon with
322 * either no elements or the first element is not the beacon compatibility
323 * element, we have a short beacon.
324 */
325static inline bool ieee80211_is_s1g_short_beacon(__le16 fc, const u8 *variable,
326 size_t variable_len)
327{
328 if (!ieee80211_is_s1g_beacon(fc))
329 return false;
330
331 /*
332 * If the frame does not contain at least 1 element (this is perfectly
333 * valid in a short beacon) and is an S1G beacon, we have a short
334 * beacon.
335 */
336 if (variable_len < 2)
337 return true;
338
339 return variable[0] != WLAN_EID_S1G_BCN_COMPAT;
340}
341
342struct s1g_tim_aid {
343 u16 aid;
344 u8 target_blk; /* Target block index */
345 u8 target_subblk; /* Target subblock index */
346 u8 target_subblk_bit; /* Target subblock bit */
347};
348
349struct s1g_tim_enc_block {
350 u8 enc_mode;
351 bool inverse;
352 const u8 *ptr;
353 u8 len;
354
355 /*
356 * For an OLB encoded block that spans multiple blocks, this
357 * is the offset into the span described by that encoded block.
358 */
359 u8 olb_blk_offset;
360};
361
362/*
363 * Helper routines to quickly extract the length of an encoded block. Validation
364 * is also performed to ensure the length extracted lies within the TIM.
365 */
366
367static inline int ieee80211_s1g_len_bitmap(const u8 *ptr, const u8 *end)
368{
369 u8 blkmap;
370 u8 n_subblks;
371
372 if (ptr >= end)
373 return -EINVAL;
374
375 blkmap = *ptr;
376 n_subblks = hweight8(blkmap);
377
378 if (ptr + 1 + n_subblks > end)
379 return -EINVAL;
380
381 return 1 + n_subblks;
382}
383
384static inline int ieee80211_s1g_len_single(const u8 *ptr, const u8 *end)
385{
386 return (ptr + 1 > end) ? -EINVAL : 1;
387}
388
389static inline int ieee80211_s1g_len_olb(const u8 *ptr, const u8 *end)
390{
391 if (ptr >= end)
392 return -EINVAL;
393
394 return (ptr + 1 + *ptr > end) ? -EINVAL : 1 + *ptr;
395}
396
397/*
398 * Enumerate all encoded blocks until we find the encoded block that describes
399 * our target AID. OLB is a special case as a single encoded block can describe
400 * multiple blocks as a single encoded block.
401 */
402static inline int ieee80211_s1g_find_target_block(struct s1g_tim_enc_block *enc,
403 const struct s1g_tim_aid *aid,
404 const u8 *ptr, const u8 *end)
405{
406 /* need at least block-control octet */
407 while (ptr + 1 <= end) {
408 u8 ctrl = *ptr++;
409 u8 mode = ctrl & 0x03;
410 bool contains, inverse = ctrl & BIT(2);
411 u8 span, blk_off = ctrl >> 3;
412 int len;
413
414 switch (mode) {
415 case IEEE80211_S1G_TIM_ENC_MODE_BLOCK:
416 len = ieee80211_s1g_len_bitmap(ptr, end);
417 contains = blk_off == aid->target_blk;
418 break;
419 case IEEE80211_S1G_TIM_ENC_MODE_SINGLE:
420 len = ieee80211_s1g_len_single(ptr, end);
421 contains = blk_off == aid->target_blk;
422 break;
423 case IEEE80211_S1G_TIM_ENC_MODE_OLB:
424 len = ieee80211_s1g_len_olb(ptr, end);
425 /*
426 * An OLB encoded block can describe more then one
427 * block, meaning an encoded OLB block can span more
428 * then a single block.
429 */
430 if (len > 0) {
431 /* Minus one for the length octet */
432 span = DIV_ROUND_UP(len - 1, 8);
433 /*
434 * Check if our target block lies within the
435 * block span described by this encoded block.
436 */
437 contains = (aid->target_blk >= blk_off) &&
438 (aid->target_blk < blk_off + span);
439 }
440 break;
441 default:
442 return -EOPNOTSUPP;
443 }
444
445 if (len < 0)
446 return len;
447
448 if (contains) {
449 enc->enc_mode = mode;
450 enc->inverse = inverse;
451 enc->ptr = ptr;
452 enc->len = (u8)len;
453 enc->olb_blk_offset = blk_off;
454 return 0;
455 }
456
457 ptr += len;
458 }
459
460 return -ENOENT;
461}
462
463static inline bool ieee80211_s1g_parse_bitmap(struct s1g_tim_enc_block *enc,
464 struct s1g_tim_aid *aid)
465{
466 const u8 *ptr = enc->ptr;
467 u8 blkmap = *ptr++;
468
469 /*
470 * If our block bitmap does not contain a set bit that corresponds
471 * to our AID, it could mean a variety of things depending on if
472 * the encoding mode is inverted or not.
473 *
474 * 1. If inverted, it means the entire subblock is present and hence
475 * our AID has been set.
476 * 2. If not inverted, it means our subblock is not present and hence
477 * it is all zero meaning our AID is not set.
478 */
479 if (!(blkmap & BIT(aid->target_subblk)))
480 return enc->inverse;
481
482 /*
483 * Increment ptr by the number of set subblocks that appear before our
484 * target subblock. If our target subblock is 0, do nothing as ptr
485 * already points to our target subblock.
486 */
487 if (aid->target_subblk)
488 ptr += hweight8(blkmap & GENMASK(aid->target_subblk - 1, 0));
489
490 return !!(*ptr & BIT(aid->target_subblk_bit)) ^ enc->inverse;
491}
492
493static inline bool ieee80211_s1g_parse_single(struct s1g_tim_enc_block *enc,
494 struct s1g_tim_aid *aid)
495{
496 /*
497 * Single AID mode describes, as the name suggests, a single AID
498 * within the block described by the encoded block. The octet
499 * contains the 6 LSBs of the AID described in the block. The other
500 * 2 bits are reserved. When inversed, every single AID described
501 * by the current block have buffered traffic except for the AID
502 * described in the single AID octet.
503 */
504 return ((*enc->ptr & 0x3f) == (aid->aid & 0x3f)) ^ enc->inverse;
505}
506
507static inline bool ieee80211_s1g_parse_olb(struct s1g_tim_enc_block *enc,
508 struct s1g_tim_aid *aid)
509{
510 const u8 *ptr = enc->ptr;
511 u8 blk_len = *ptr++;
512 /*
513 * Given an OLB encoded block that describes multiple blocks,
514 * calculate the offset into the span. Then calculate the
515 * subblock location normally.
516 */
517 u16 span_offset = aid->target_blk - enc->olb_blk_offset;
518 u16 subblk_idx = span_offset * 8 + aid->target_subblk;
519
520 if (subblk_idx >= blk_len)
521 return enc->inverse;
522
523 return !!(ptr[subblk_idx] & BIT(aid->target_subblk_bit)) ^ enc->inverse;
524}
525
526/*
527 * An S1G PVB has 3 non optional encoding types, each that can be inverted.
528 * An S1G PVB is constructed with zero or more encoded block subfields. Each
529 * encoded block represents a single "block" of AIDs (64), and each encoded
530 * block can contain one of the 3 encoding types alongside a single bit for
531 * whether the bits should be inverted.
532 *
533 * As the standard makes no guarantee about the ordering of encoded blocks,
534 * we must parse every encoded block in the worst case scenario given an
535 * AID that lies within the last block.
536 */
537static inline bool ieee80211_s1g_check_tim(const struct ieee80211_tim_ie *tim,
538 u8 tim_len, u16 aid)
539{
540 int err;
541 struct s1g_tim_aid target_aid;
542 struct s1g_tim_enc_block enc_blk;
543
544 if (tim_len < 3)
545 return false;
546
547 target_aid.aid = aid;
548 target_aid.target_blk = (aid >> 6) & 0x1f;
549 target_aid.target_subblk = (aid >> 3) & 0x7;
550 target_aid.target_subblk_bit = aid & 0x7;
551
552 /*
553 * Find our AIDs target encoded block and fill &enc_blk with the
554 * encoded blocks information. If no entry is found or an error
555 * occurs return false.
556 */
557 err = ieee80211_s1g_find_target_block(&enc_blk, &target_aid,
558 tim->virtual_map,
559 (const u8 *)tim + tim_len + 2);
560 if (err)
561 return false;
562
563 switch (enc_blk.enc_mode) {
564 case IEEE80211_S1G_TIM_ENC_MODE_BLOCK:
565 return ieee80211_s1g_parse_bitmap(&enc_blk, &target_aid);
566 case IEEE80211_S1G_TIM_ENC_MODE_SINGLE:
567 return ieee80211_s1g_parse_single(&enc_blk, &target_aid);
568 case IEEE80211_S1G_TIM_ENC_MODE_OLB:
569 return ieee80211_s1g_parse_olb(&enc_blk, &target_aid);
570 default:
571 return false;
572 }
573}
574
575#endif /* LINUX_IEEE80211_H */