uboot-envtools: ramips: add support for ALFA Network AX1800RM
[openwrt/openwrt.git] / package / kernel / mac80211 / patches / subsys / 336-v6.4-wifi-mac80211-generate-EMA-beacons-in-AP-mode.patch
1 From bd54f3c29077f23dad92ef82a78061b40be30c65 Mon Sep 17 00:00:00 2001
2 From: Aloka Dixit <quic_alokad@quicinc.com>
3 Date: Mon, 5 Dec 2022 16:50:37 -0800
4 Subject: [PATCH] wifi: mac80211: generate EMA beacons in AP mode
5
6 Add APIs to generate an array of beacons for an EMA AP (enhanced
7 multiple BSSID advertisements), each including a single MBSSID element.
8 EMA profile periodicity equals the count of elements.
9
10 - ieee80211_beacon_get_template_ema_list() - Generate and return all
11 EMA beacon templates. Drivers must call ieee80211_beacon_free_ema_list()
12 to free the memory. No change in the prototype for the existing API,
13 ieee80211_beacon_get_template(), which should be used for non-EMA AP.
14
15 - ieee80211_beacon_get_template_ema_index() - Generate a beacon which
16 includes the multiple BSSID element at the given index. Drivers can use
17 this function in a loop until NULL is returned which indicates end of
18 available MBSSID elements.
19
20 - ieee80211_beacon_free_ema_list() - free the memory allocated for the
21 list of EMA beacon templates.
22
23 Modify existing functions ieee80211_beacon_get_ap(),
24 ieee80211_get_mbssid_beacon_len() and ieee80211_beacon_add_mbssid()
25 to accept a new parameter for EMA index.
26
27 Signed-off-by: Aloka Dixit <quic_alokad@quicinc.com>
28 Co-developed-by: John Crispin <john@phrozen.org>
29 Signed-off-by: John Crispin <john@phrozen.org>
30 Link: https://lore.kernel.org/r/20221206005040.3177-2-quic_alokad@quicinc.com
31 Signed-off-by: Johannes Berg <johannes.berg@intel.com>
32 ---
33 include/net/mac80211.h | 68 +++++++++++++++++++
34 net/mac80211/cfg.c | 11 +--
35 net/mac80211/ieee80211_i.h | 10 ++-
36 net/mac80211/tx.c | 134 ++++++++++++++++++++++++++++++++++---
37 4 files changed, 205 insertions(+), 18 deletions(-)
38
39 --- a/include/net/mac80211.h
40 +++ b/include/net/mac80211.h
41 @@ -5252,6 +5252,74 @@ ieee80211_beacon_get_template(struct iee
42 unsigned int link_id);
43
44 /**
45 + * ieee80211_beacon_get_template_ema_index - EMA beacon template generation
46 + * @hw: pointer obtained from ieee80211_alloc_hw().
47 + * @vif: &struct ieee80211_vif pointer from the add_interface callback.
48 + * @offs: &struct ieee80211_mutable_offsets pointer to struct that will
49 + * receive the offsets that may be updated by the driver.
50 + * @link_id: the link id to which the beacon belongs (or 0 for a non-MLD AP).
51 + * @ema_index: index of the beacon in the EMA set.
52 + *
53 + * This function follows the same rules as ieee80211_beacon_get_template()
54 + * but returns a beacon template which includes multiple BSSID element at the
55 + * requested index.
56 + *
57 + * Return: The beacon template. %NULL indicates the end of EMA templates.
58 + */
59 +struct sk_buff *
60 +ieee80211_beacon_get_template_ema_index(struct ieee80211_hw *hw,
61 + struct ieee80211_vif *vif,
62 + struct ieee80211_mutable_offsets *offs,
63 + unsigned int link_id, u8 ema_index);
64 +
65 +/**
66 + * struct ieee80211_ema_beacons - List of EMA beacons
67 + * @cnt: count of EMA beacons.
68 + *
69 + * @bcn: array of EMA beacons.
70 + * @bcn.skb: the skb containing this specific beacon
71 + * @bcn.offs: &struct ieee80211_mutable_offsets pointer to struct that will
72 + * receive the offsets that may be updated by the driver.
73 + */
74 +struct ieee80211_ema_beacons {
75 + u8 cnt;
76 + struct {
77 + struct sk_buff *skb;
78 + struct ieee80211_mutable_offsets offs;
79 + } bcn[];
80 +};
81 +
82 +/**
83 + * ieee80211_beacon_get_template_ema_list - EMA beacon template generation
84 + * @hw: pointer obtained from ieee80211_alloc_hw().
85 + * @vif: &struct ieee80211_vif pointer from the add_interface callback.
86 + * @link_id: the link id to which the beacon belongs (or 0 for a non-MLD AP)
87 + *
88 + * This function follows the same rules as ieee80211_beacon_get_template()
89 + * but allocates and returns a pointer to list of all beacon templates required
90 + * to cover all profiles in the multiple BSSID set. Each template includes only
91 + * one multiple BSSID element.
92 + *
93 + * Driver must call ieee80211_beacon_free_ema_list() to free the memory.
94 + *
95 + * Return: EMA beacon templates of type struct ieee80211_ema_beacons *.
96 + * %NULL on error.
97 + */
98 +struct ieee80211_ema_beacons *
99 +ieee80211_beacon_get_template_ema_list(struct ieee80211_hw *hw,
100 + struct ieee80211_vif *vif,
101 + unsigned int link_id);
102 +
103 +/**
104 + * ieee80211_beacon_free_ema_list - free an EMA beacon template list
105 + * @ema_beacons: list of EMA beacons of type &struct ieee80211_ema_beacons pointers.
106 + *
107 + * This function will free a list previously acquired by calling
108 + * ieee80211_beacon_get_template_ema_list()
109 + */
110 +void ieee80211_beacon_free_ema_list(struct ieee80211_ema_beacons *ema_beacons);
111 +
112 +/**
113 * ieee80211_beacon_get_tim - beacon generation function
114 * @hw: pointer obtained from ieee80211_alloc_hw().
115 * @vif: &struct ieee80211_vif pointer from the add_interface callback.
116 --- a/net/mac80211/cfg.c
117 +++ b/net/mac80211/cfg.c
118 @@ -1122,11 +1122,11 @@ static int ieee80211_assign_beacon(struc
119 if (params->mbssid_ies) {
120 mbssid = params->mbssid_ies;
121 size += struct_size(new->mbssid_ies, elem, mbssid->cnt);
122 - size += ieee80211_get_mbssid_beacon_len(mbssid);
123 + size += ieee80211_get_mbssid_beacon_len(mbssid, mbssid->cnt);
124 } else if (old && old->mbssid_ies) {
125 mbssid = old->mbssid_ies;
126 size += struct_size(new->mbssid_ies, elem, mbssid->cnt);
127 - size += ieee80211_get_mbssid_beacon_len(mbssid);
128 + size += ieee80211_get_mbssid_beacon_len(mbssid, mbssid->cnt);
129 }
130
131 new = kzalloc(size, GFP_KERNEL);
132 @@ -3384,8 +3384,11 @@ cfg80211_beacon_dup(struct cfg80211_beac
133
134 len = beacon->head_len + beacon->tail_len + beacon->beacon_ies_len +
135 beacon->proberesp_ies_len + beacon->assocresp_ies_len +
136 - beacon->probe_resp_len + beacon->lci_len + beacon->civicloc_len +
137 - ieee80211_get_mbssid_beacon_len(beacon->mbssid_ies);
138 + beacon->probe_resp_len + beacon->lci_len + beacon->civicloc_len;
139 +
140 + if (beacon->mbssid_ies)
141 + len += ieee80211_get_mbssid_beacon_len(beacon->mbssid_ies,
142 + beacon->mbssid_ies->cnt);
143
144 new_beacon = kzalloc(sizeof(*new_beacon) + len, GFP_KERNEL);
145 if (!new_beacon)
146 --- a/net/mac80211/ieee80211_i.h
147 +++ b/net/mac80211/ieee80211_i.h
148 @@ -1182,13 +1182,17 @@ ieee80211_vif_get_shift(struct ieee80211
149 }
150
151 static inline int
152 -ieee80211_get_mbssid_beacon_len(struct cfg80211_mbssid_elems *elems)
153 +ieee80211_get_mbssid_beacon_len(struct cfg80211_mbssid_elems *elems, u8 i)
154 {
155 - int i, len = 0;
156 + int len = 0;
157
158 - if (!elems)
159 + if (!elems || !elems->cnt || i > elems->cnt)
160 return 0;
161
162 + if (i < elems->cnt)
163 + return elems->elem[i].len;
164 +
165 + /* i == elems->cnt, calculate total length of all MBSSID elements */
166 for (i = 0; i < elems->cnt; i++)
167 len += elems->elem[i].len;
168
169 --- a/net/mac80211/tx.c
170 +++ b/net/mac80211/tx.c
171 @@ -5205,13 +5205,20 @@ ieee80211_beacon_get_finish(struct ieee8
172 }
173
174 static void
175 -ieee80211_beacon_add_mbssid(struct sk_buff *skb, struct beacon_data *beacon)
176 +ieee80211_beacon_add_mbssid(struct sk_buff *skb, struct beacon_data *beacon,
177 + u8 i)
178 {
179 - int i;
180 + if (!beacon->mbssid_ies || !beacon->mbssid_ies->cnt ||
181 + i > beacon->mbssid_ies->cnt)
182 + return;
183
184 - if (!beacon->mbssid_ies)
185 + if (i < beacon->mbssid_ies->cnt) {
186 + skb_put_data(skb, beacon->mbssid_ies->elem[i].data,
187 + beacon->mbssid_ies->elem[i].len);
188 return;
189 + }
190
191 + /* i == beacon->mbssid_ies->cnt, include all MBSSID elements */
192 for (i = 0; i < beacon->mbssid_ies->cnt; i++)
193 skb_put_data(skb, beacon->mbssid_ies->elem[i].data,
194 beacon->mbssid_ies->elem[i].len);
195 @@ -5224,7 +5231,8 @@ ieee80211_beacon_get_ap(struct ieee80211
196 struct ieee80211_mutable_offsets *offs,
197 bool is_template,
198 struct beacon_data *beacon,
199 - struct ieee80211_chanctx_conf *chanctx_conf)
200 + struct ieee80211_chanctx_conf *chanctx_conf,
201 + u8 ema_index)
202 {
203 struct ieee80211_local *local = hw_to_local(hw);
204 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
205 @@ -5243,7 +5251,9 @@ ieee80211_beacon_get_ap(struct ieee80211
206 /* headroom, head length,
207 * tail length, maximum TIM length and multiple BSSID length
208 */
209 - mbssid_len = ieee80211_get_mbssid_beacon_len(beacon->mbssid_ies);
210 + mbssid_len = ieee80211_get_mbssid_beacon_len(beacon->mbssid_ies,
211 + ema_index);
212 +
213 skb = dev_alloc_skb(local->tx_headroom + beacon->head_len +
214 beacon->tail_len + 256 +
215 local->hw.extra_beacon_tailroom + mbssid_len);
216 @@ -5261,7 +5271,7 @@ ieee80211_beacon_get_ap(struct ieee80211
217 offs->cntdwn_counter_offs[0] = beacon->cntdwn_counter_offsets[0];
218
219 if (mbssid_len) {
220 - ieee80211_beacon_add_mbssid(skb, beacon);
221 + ieee80211_beacon_add_mbssid(skb, beacon, ema_index);
222 offs->mbssid_off = skb->len - mbssid_len;
223 }
224
225 @@ -5280,12 +5290,51 @@ ieee80211_beacon_get_ap(struct ieee80211
226 return skb;
227 }
228
229 +static struct ieee80211_ema_beacons *
230 +ieee80211_beacon_get_ap_ema_list(struct ieee80211_hw *hw,
231 + struct ieee80211_vif *vif,
232 + struct ieee80211_link_data *link,
233 + struct ieee80211_mutable_offsets *offs,
234 + bool is_template, struct beacon_data *beacon,
235 + struct ieee80211_chanctx_conf *chanctx_conf)
236 +{
237 + struct ieee80211_ema_beacons *ema = NULL;
238 +
239 + if (!beacon->mbssid_ies || !beacon->mbssid_ies->cnt)
240 + return NULL;
241 +
242 + ema = kzalloc(struct_size(ema, bcn, beacon->mbssid_ies->cnt),
243 + GFP_ATOMIC);
244 + if (!ema)
245 + return NULL;
246 +
247 + for (ema->cnt = 0; ema->cnt < beacon->mbssid_ies->cnt; ema->cnt++) {
248 + ema->bcn[ema->cnt].skb =
249 + ieee80211_beacon_get_ap(hw, vif, link,
250 + &ema->bcn[ema->cnt].offs,
251 + is_template, beacon,
252 + chanctx_conf, ema->cnt);
253 + if (!ema->bcn[ema->cnt].skb)
254 + break;
255 + }
256 +
257 + if (ema->cnt == beacon->mbssid_ies->cnt)
258 + return ema;
259 +
260 + ieee80211_beacon_free_ema_list(ema);
261 + return NULL;
262 +}
263 +
264 +#define IEEE80211_INCLUDE_ALL_MBSSID_ELEMS -1
265 +
266 static struct sk_buff *
267 __ieee80211_beacon_get(struct ieee80211_hw *hw,
268 struct ieee80211_vif *vif,
269 struct ieee80211_mutable_offsets *offs,
270 bool is_template,
271 - unsigned int link_id)
272 + unsigned int link_id,
273 + int ema_index,
274 + struct ieee80211_ema_beacons **ema_beacons)
275 {
276 struct ieee80211_local *local = hw_to_local(hw);
277 struct beacon_data *beacon = NULL;
278 @@ -5314,8 +5363,29 @@ __ieee80211_beacon_get(struct ieee80211_
279 if (!beacon)
280 goto out;
281
282 - skb = ieee80211_beacon_get_ap(hw, vif, link, offs, is_template,
283 - beacon, chanctx_conf);
284 + if (ema_beacons) {
285 + *ema_beacons =
286 + ieee80211_beacon_get_ap_ema_list(hw, vif, link,
287 + offs,
288 + is_template,
289 + beacon,
290 + chanctx_conf);
291 + } else {
292 + if (beacon->mbssid_ies && beacon->mbssid_ies->cnt) {
293 + if (ema_index >= beacon->mbssid_ies->cnt)
294 + goto out; /* End of MBSSID elements */
295 +
296 + if (ema_index <= IEEE80211_INCLUDE_ALL_MBSSID_ELEMS)
297 + ema_index = beacon->mbssid_ies->cnt;
298 + } else {
299 + ema_index = 0;
300 + }
301 +
302 + skb = ieee80211_beacon_get_ap(hw, vif, link, offs,
303 + is_template, beacon,
304 + chanctx_conf,
305 + ema_index);
306 + }
307 } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
308 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
309 struct ieee80211_hdr *hdr;
310 @@ -5403,10 +5473,50 @@ ieee80211_beacon_get_template(struct iee
311 struct ieee80211_mutable_offsets *offs,
312 unsigned int link_id)
313 {
314 - return __ieee80211_beacon_get(hw, vif, offs, true, link_id);
315 + return __ieee80211_beacon_get(hw, vif, offs, true, link_id,
316 + IEEE80211_INCLUDE_ALL_MBSSID_ELEMS, NULL);
317 }
318 EXPORT_SYMBOL(ieee80211_beacon_get_template);
319
320 +struct sk_buff *
321 +ieee80211_beacon_get_template_ema_index(struct ieee80211_hw *hw,
322 + struct ieee80211_vif *vif,
323 + struct ieee80211_mutable_offsets *offs,
324 + unsigned int link_id, u8 ema_index)
325 +{
326 + return __ieee80211_beacon_get(hw, vif, offs, true, link_id, ema_index,
327 + NULL);
328 +}
329 +EXPORT_SYMBOL(ieee80211_beacon_get_template_ema_index);
330 +
331 +void ieee80211_beacon_free_ema_list(struct ieee80211_ema_beacons *ema_beacons)
332 +{
333 + u8 i;
334 +
335 + if (!ema_beacons)
336 + return;
337 +
338 + for (i = 0; i < ema_beacons->cnt; i++)
339 + kfree_skb(ema_beacons->bcn[i].skb);
340 +
341 + kfree(ema_beacons);
342 +}
343 +EXPORT_SYMBOL(ieee80211_beacon_free_ema_list);
344 +
345 +struct ieee80211_ema_beacons *
346 +ieee80211_beacon_get_template_ema_list(struct ieee80211_hw *hw,
347 + struct ieee80211_vif *vif,
348 + unsigned int link_id)
349 +{
350 + struct ieee80211_ema_beacons *ema_beacons = NULL;
351 +
352 + WARN_ON(__ieee80211_beacon_get(hw, vif, NULL, false, link_id, 0,
353 + &ema_beacons));
354 +
355 + return ema_beacons;
356 +}
357 +EXPORT_SYMBOL(ieee80211_beacon_get_template_ema_list);
358 +
359 struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
360 struct ieee80211_vif *vif,
361 u16 *tim_offset, u16 *tim_length,
362 @@ -5414,7 +5524,9 @@ struct sk_buff *ieee80211_beacon_get_tim
363 {
364 struct ieee80211_mutable_offsets offs = {};
365 struct sk_buff *bcn = __ieee80211_beacon_get(hw, vif, &offs, false,
366 - link_id);
367 + link_id,
368 + IEEE80211_INCLUDE_ALL_MBSSID_ELEMS,
369 + NULL);
370 struct sk_buff *copy;
371 int shift;
372