mt76: update to version 2022-12-01
[openwrt/staging/wigyori.git] / package / kernel / mac80211 / patches / subsys / 313-v5.16-nl80211-MBSSID-and-EMA-support-in-AP-mode.patch
1 From: John Crispin <john@phrozen.org>
2 Date: Wed, 15 Sep 2021 19:54:34 -0700
3 Subject: [PATCH] nl80211: MBSSID and EMA support in AP mode
4
5 Add new attributes to configure support for multiple BSSID
6 and advanced multi-BSSID advertisements (EMA) in AP mode.
7
8 - NL80211_ATTR_MBSSID_CONFIG used for per interface configuration.
9 - NL80211_ATTR_MBSSID_ELEMS used to MBSSID elements for beacons.
10
11 Memory for the elements is allocated dynamically. This change frees
12 the memory in existing functions which call nl80211_parse_beacon(),
13 a comment is added to indicate the new references to do the same.
14
15 Signed-off-by: John Crispin <john@phrozen.org>
16 Co-developed-by: Aloka Dixit <alokad@codeaurora.org>
17 Signed-off-by: Aloka Dixit <alokad@codeaurora.org>
18 Link: https://lore.kernel.org/r/20210916025437.29138-2-alokad@codeaurora.org
19 [don't leave ERR_PTR hanging around]
20 Signed-off-by: Johannes Berg <johannes.berg@intel.com>
21 ---
22
23 --- a/include/net/cfg80211.h
24 +++ b/include/net/cfg80211.h
25 @@ -1046,6 +1046,36 @@ struct cfg80211_crypto_settings {
26 };
27
28 /**
29 + * struct cfg80211_mbssid_config - AP settings for multi bssid
30 + *
31 + * @tx_wdev: pointer to the transmitted interface in the MBSSID set
32 + * @index: index of this AP in the multi bssid group.
33 + * @ema: set to true if the beacons should be sent out in EMA mode.
34 + */
35 +struct cfg80211_mbssid_config {
36 + struct wireless_dev *tx_wdev;
37 + u8 index;
38 + bool ema;
39 +};
40 +
41 +/**
42 + * struct cfg80211_mbssid_elems - Multiple BSSID elements
43 + *
44 + * @cnt: Number of elements in array %elems.
45 + *
46 + * @elem: Array of multiple BSSID element(s) to be added into Beacon frames.
47 + * @elem.data: Data for multiple BSSID elements.
48 + * @elem.len: Length of data.
49 + */
50 +struct cfg80211_mbssid_elems {
51 + u8 cnt;
52 + struct {
53 + const u8 *data;
54 + size_t len;
55 + } elem[];
56 +};
57 +
58 +/**
59 * struct cfg80211_beacon_data - beacon data
60 * @head: head portion of beacon (before TIM IE)
61 * or %NULL if not changed
62 @@ -1063,6 +1093,7 @@ struct cfg80211_crypto_settings {
63 * @assocresp_ies_len: length of assocresp_ies in octets
64 * @probe_resp_len: length of probe response template (@probe_resp)
65 * @probe_resp: probe response template (AP mode only)
66 + * @mbssid_ies: multiple BSSID elements
67 * @ftm_responder: enable FTM responder functionality; -1 for no change
68 * (which also implies no change in LCI/civic location data)
69 * @lci: Measurement Report element content, starting with Measurement Token
70 @@ -1080,6 +1111,7 @@ struct cfg80211_beacon_data {
71 const u8 *probe_resp;
72 const u8 *lci;
73 const u8 *civicloc;
74 + struct cfg80211_mbssid_elems *mbssid_ies;
75 s8 ftm_responder;
76
77 size_t head_len, tail_len;
78 @@ -1194,6 +1226,7 @@ enum cfg80211_ap_settings_flags {
79 * @he_oper: HE operation IE (or %NULL if HE isn't enabled)
80 * @fils_discovery: FILS discovery transmission parameters
81 * @unsol_bcast_probe_resp: Unsolicited broadcast probe response parameters
82 + * @mbssid_config: AP settings for multiple bssid
83 */
84 struct cfg80211_ap_settings {
85 struct cfg80211_chan_def chandef;
86 @@ -1226,6 +1259,7 @@ struct cfg80211_ap_settings {
87 struct cfg80211_he_bss_color he_bss_color;
88 struct cfg80211_fils_discovery fils_discovery;
89 struct cfg80211_unsol_bcast_probe_resp unsol_bcast_probe_resp;
90 + struct cfg80211_mbssid_config mbssid_config;
91 };
92
93 /**
94 @@ -4986,6 +5020,13 @@ struct wiphy_iftype_akm_suites {
95 * %NL80211_TID_CONFIG_ATTR_RETRY_LONG attributes
96 * @sar_capa: SAR control capabilities
97 * @rfkill: a pointer to the rfkill structure
98 + *
99 + * @mbssid_max_interfaces: maximum number of interfaces supported by the driver
100 + * in a multiple BSSID set. This field must be set to a non-zero value
101 + * by the driver to advertise MBSSID support.
102 + * @mbssid_max_ema_profile_periodicity: maximum profile periodicity supported by
103 + * the driver. Setting this field to a non-zero value indicates that the
104 + * driver supports enhanced multi-BSSID advertisements (EMA AP).
105 */
106 struct wiphy {
107 struct mutex mtx;
108 @@ -5133,6 +5174,9 @@ struct wiphy {
109
110 struct rfkill *rfkill;
111
112 + u8 mbssid_max_interfaces;
113 + u8 ema_max_profile_periodicity;
114 +
115 char priv[] __aligned(NETDEV_ALIGN);
116 };
117
118 --- a/include/uapi/linux/nl80211.h
119 +++ b/include/uapi/linux/nl80211.h
120 @@ -337,7 +337,10 @@
121 * @NL80211_CMD_DEL_INTERFACE: Virtual interface was deleted, has attributes
122 * %NL80211_ATTR_IFINDEX and %NL80211_ATTR_WIPHY. Can also be sent from
123 * userspace to request deletion of a virtual interface, then requires
124 - * attribute %NL80211_ATTR_IFINDEX.
125 + * attribute %NL80211_ATTR_IFINDEX. If multiple BSSID advertisements are
126 + * enabled using %NL80211_ATTR_MBSSID_CONFIG, %NL80211_ATTR_MBSSID_ELEMS,
127 + * and if this command is used for the transmitting interface, then all
128 + * the non-transmitting interfaces are deleted as well.
129 *
130 * @NL80211_CMD_GET_KEY: Get sequence counter information for a key specified
131 * by %NL80211_ATTR_KEY_IDX and/or %NL80211_ATTR_MAC.
132 @@ -2593,6 +2596,18 @@ enum nl80211_commands {
133 * @NL80211_ATTR_COLOR_CHANGE_ELEMS: Nested set of attributes containing the IE
134 * information for the time while performing a color switch.
135 *
136 + * @NL80211_ATTR_MBSSID_CONFIG: Nested attribute for multiple BSSID
137 + * advertisements (MBSSID) parameters in AP mode.
138 + * Kernel uses this attribute to indicate the driver's support for MBSSID
139 + * and enhanced multi-BSSID advertisements (EMA AP) to the userspace.
140 + * Userspace should use this attribute to configure per interface MBSSID
141 + * parameters.
142 + * See &enum nl80211_mbssid_config_attributes for details.
143 + *
144 + * @NL80211_ATTR_MBSSID_ELEMS: Nested parameter to pass multiple BSSID elements.
145 + * Mandatory parameter for the transmitting interface to enable MBSSID.
146 + * Optional for the non-transmitting interfaces.
147 + *
148 * @NUM_NL80211_ATTR: total number of nl80211_attrs available
149 * @NL80211_ATTR_MAX: highest attribute number currently defined
150 * @__NL80211_ATTR_AFTER_LAST: internal use
151 @@ -3096,6 +3111,9 @@ enum nl80211_attrs {
152 NL80211_ATTR_COLOR_CHANGE_COLOR,
153 NL80211_ATTR_COLOR_CHANGE_ELEMS,
154
155 + NL80211_ATTR_MBSSID_CONFIG,
156 + NL80211_ATTR_MBSSID_ELEMS,
157 +
158 /* add attributes here, update the policy in nl80211.c */
159
160 __NL80211_ATTR_AFTER_LAST,
161 @@ -7349,4 +7367,60 @@ enum nl80211_sar_specs_attrs {
162 NL80211_SAR_ATTR_SPECS_MAX = __NL80211_SAR_ATTR_SPECS_LAST - 1,
163 };
164
165 +/**
166 + * enum nl80211_mbssid_config_attributes - multiple BSSID (MBSSID) and enhanced
167 + * multi-BSSID advertisements (EMA) in AP mode.
168 + * Kernel uses some of these attributes to advertise driver's support for
169 + * MBSSID and EMA.
170 + * Remaining attributes should be used by the userspace to configure the
171 + * features.
172 + *
173 + * @__NL80211_MBSSID_CONFIG_ATTR_INVALID: Invalid
174 + *
175 + * @NL80211_MBSSID_CONFIG_ATTR_MAX_INTERFACES: Used by the kernel to advertise
176 + * the maximum number of MBSSID interfaces supported by the driver.
177 + * Driver should indicate MBSSID support by setting
178 + * wiphy->mbssid_max_interfaces to a value more than or equal to 2.
179 + *
180 + * @NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY: Used by the kernel
181 + * to advertise the maximum profile periodicity supported by the driver
182 + * if EMA is enabled. Driver should indicate EMA support to the userspace
183 + * by setting wiphy->mbssid_max_ema_profile_periodicity to
184 + * a non-zero value.
185 + *
186 + * @NL80211_MBSSID_CONFIG_ATTR_INDEX: Mandatory parameter to pass the index of
187 + * this BSS (u8) in the multiple BSSID set.
188 + * Value must be set to 0 for the transmitting interface and non-zero for
189 + * all non-transmitting interfaces. The userspace will be responsible
190 + * for using unique indices for the interfaces.
191 + * Range: 0 to wiphy->mbssid_max_interfaces-1.
192 + *
193 + * @NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX: Mandatory parameter for
194 + * a non-transmitted profile which provides the interface index (u32) of
195 + * the transmitted profile. The value must match one of the interface
196 + * indices advertised by the kernel. Optional if the interface being set up
197 + * is the transmitting one, however, if provided then the value must match
198 + * the interface index of the same.
199 + *
200 + * @NL80211_MBSSID_CONFIG_ATTR_EMA: Flag used to enable EMA AP feature.
201 + * Setting this flag is permitted only if the driver advertises EMA support
202 + * by setting wiphy->mbssid_max_ema_profile_periodicity to non-zero.
203 + *
204 + * @__NL80211_MBSSID_CONFIG_ATTR_LAST: Internal
205 + * @NL80211_MBSSID_CONFIG_ATTR_MAX: highest attribute
206 + */
207 +enum nl80211_mbssid_config_attributes {
208 + __NL80211_MBSSID_CONFIG_ATTR_INVALID,
209 +
210 + NL80211_MBSSID_CONFIG_ATTR_MAX_INTERFACES,
211 + NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY,
212 + NL80211_MBSSID_CONFIG_ATTR_INDEX,
213 + NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX,
214 + NL80211_MBSSID_CONFIG_ATTR_EMA,
215 +
216 + /* keep last */
217 + __NL80211_MBSSID_CONFIG_ATTR_LAST,
218 + NL80211_MBSSID_CONFIG_ATTR_MAX = __NL80211_MBSSID_CONFIG_ATTR_LAST - 1,
219 +};
220 +
221 #endif /* __LINUX_NL80211_H */
222 --- a/net/wireless/nl80211.c
223 +++ b/net/wireless/nl80211.c
224 @@ -442,6 +442,16 @@ sar_policy[NL80211_SAR_ATTR_MAX + 1] = {
225 [NL80211_SAR_ATTR_SPECS] = NLA_POLICY_NESTED_ARRAY(sar_specs_policy),
226 };
227
228 +static const struct nla_policy
229 +nl80211_mbssid_config_policy[NL80211_MBSSID_CONFIG_ATTR_MAX + 1] = {
230 + [NL80211_MBSSID_CONFIG_ATTR_MAX_INTERFACES] = NLA_POLICY_MIN(NLA_U8, 2),
231 + [NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY] =
232 + NLA_POLICY_MIN(NLA_U8, 1),
233 + [NL80211_MBSSID_CONFIG_ATTR_INDEX] = { .type = NLA_U8 },
234 + [NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX] = { .type = NLA_U32 },
235 + [NL80211_MBSSID_CONFIG_ATTR_EMA] = { .type = NLA_FLAG },
236 +};
237 +
238 static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
239 [0] = { .strict_start_type = NL80211_ATTR_HE_OBSS_PD },
240 [NL80211_ATTR_WIPHY] = { .type = NLA_U32 },
241 @@ -788,6 +798,9 @@ static const struct nla_policy nl80211_p
242 [NL80211_ATTR_COLOR_CHANGE_COUNT] = { .type = NLA_U8 },
243 [NL80211_ATTR_COLOR_CHANGE_COLOR] = { .type = NLA_U8 },
244 [NL80211_ATTR_COLOR_CHANGE_ELEMS] = NLA_POLICY_NESTED(nl80211_policy),
245 + [NL80211_ATTR_MBSSID_CONFIG] =
246 + NLA_POLICY_NESTED(nl80211_mbssid_config_policy),
247 + [NL80211_ATTR_MBSSID_ELEMS] = { .type = NLA_NESTED },
248 };
249
250 /* policy for the key attributes */
251 @@ -2236,6 +2249,35 @@ fail:
252 return -ENOBUFS;
253 }
254
255 +static int nl80211_put_mbssid_support(struct wiphy *wiphy, struct sk_buff *msg)
256 +{
257 + struct nlattr *config;
258 +
259 + if (!wiphy->mbssid_max_interfaces)
260 + return 0;
261 +
262 + config = nla_nest_start(msg, NL80211_ATTR_MBSSID_CONFIG);
263 + if (!config)
264 + return -ENOBUFS;
265 +
266 + if (nla_put_u8(msg, NL80211_MBSSID_CONFIG_ATTR_MAX_INTERFACES,
267 + wiphy->mbssid_max_interfaces))
268 + goto fail;
269 +
270 + if (wiphy->ema_max_profile_periodicity &&
271 + nla_put_u8(msg,
272 + NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY,
273 + wiphy->ema_max_profile_periodicity))
274 + goto fail;
275 +
276 + nla_nest_end(msg, config);
277 + return 0;
278 +
279 +fail:
280 + nla_nest_cancel(msg, config);
281 + return -ENOBUFS;
282 +}
283 +
284 struct nl80211_dump_wiphy_state {
285 s64 filter_wiphy;
286 long start;
287 @@ -2821,6 +2863,9 @@ static int nl80211_send_wiphy(struct cfg
288 if (nl80211_put_sar_specs(rdev, msg))
289 goto nla_put_failure;
290
291 + if (nl80211_put_mbssid_support(&rdev->wiphy, msg))
292 + goto nla_put_failure;
293 +
294 /* done */
295 state->split_start = 0;
296 break;
297 @@ -5020,6 +5065,96 @@ static int validate_beacon_tx_rate(struc
298 return 0;
299 }
300
301 +static int nl80211_parse_mbssid_config(struct wiphy *wiphy,
302 + struct net_device *dev,
303 + struct nlattr *attrs,
304 + struct cfg80211_mbssid_config *config,
305 + u8 num_elems)
306 +{
307 + struct nlattr *tb[NL80211_MBSSID_CONFIG_ATTR_MAX + 1];
308 +
309 + if (!wiphy->mbssid_max_interfaces)
310 + return -EOPNOTSUPP;
311 +
312 + if (nla_parse_nested(tb, NL80211_MBSSID_CONFIG_ATTR_MAX, attrs, NULL,
313 + NULL) ||
314 + !tb[NL80211_MBSSID_CONFIG_ATTR_INDEX])
315 + return -EINVAL;
316 +
317 + config->ema = nla_get_flag(tb[NL80211_MBSSID_CONFIG_ATTR_EMA]);
318 + if (config->ema) {
319 + if (!wiphy->ema_max_profile_periodicity)
320 + return -EOPNOTSUPP;
321 +
322 + if (num_elems > wiphy->ema_max_profile_periodicity)
323 + return -EINVAL;
324 + }
325 +
326 + config->index = nla_get_u8(tb[NL80211_MBSSID_CONFIG_ATTR_INDEX]);
327 + if (config->index >= wiphy->mbssid_max_interfaces ||
328 + (!config->index && !num_elems))
329 + return -EINVAL;
330 +
331 + if (tb[NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX]) {
332 + u32 tx_ifindex =
333 + nla_get_u32(tb[NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX]);
334 +
335 + if ((!config->index && tx_ifindex != dev->ifindex) ||
336 + (config->index && tx_ifindex == dev->ifindex))
337 + return -EINVAL;
338 +
339 + if (tx_ifindex != dev->ifindex) {
340 + struct net_device *tx_netdev =
341 + dev_get_by_index(wiphy_net(wiphy), tx_ifindex);
342 +
343 + if (!tx_netdev || !tx_netdev->ieee80211_ptr ||
344 + tx_netdev->ieee80211_ptr->wiphy != wiphy ||
345 + tx_netdev->ieee80211_ptr->iftype !=
346 + NL80211_IFTYPE_AP) {
347 + dev_put(tx_netdev);
348 + return -EINVAL;
349 + }
350 +
351 + config->tx_wdev = tx_netdev->ieee80211_ptr;
352 + } else {
353 + config->tx_wdev = dev->ieee80211_ptr;
354 + }
355 + } else if (!config->index) {
356 + config->tx_wdev = dev->ieee80211_ptr;
357 + } else {
358 + return -EINVAL;
359 + }
360 +
361 + return 0;
362 +}
363 +
364 +static struct cfg80211_mbssid_elems *
365 +nl80211_parse_mbssid_elems(struct wiphy *wiphy, struct nlattr *attrs)
366 +{
367 + struct nlattr *nl_elems;
368 + struct cfg80211_mbssid_elems *elems;
369 + int rem_elems;
370 + u8 i = 0, num_elems = 0;
371 +
372 + if (!wiphy->mbssid_max_interfaces)
373 + return ERR_PTR(-EINVAL);
374 +
375 + nla_for_each_nested(nl_elems, attrs, rem_elems)
376 + num_elems++;
377 +
378 + elems = kzalloc(struct_size(elems, elem, num_elems), GFP_KERNEL);
379 + if (!elems)
380 + return ERR_PTR(-ENOMEM);
381 +
382 + nla_for_each_nested(nl_elems, attrs, rem_elems) {
383 + elems->elem[i].data = nla_data(nl_elems);
384 + elems->elem[i].len = nla_len(nl_elems);
385 + i++;
386 + }
387 + elems->cnt = num_elems;
388 + return elems;
389 +}
390 +
391 static int nl80211_parse_beacon(struct cfg80211_registered_device *rdev,
392 struct nlattr *attrs[],
393 struct cfg80211_beacon_data *bcn)
394 @@ -5100,6 +5235,17 @@ static int nl80211_parse_beacon(struct c
395 bcn->ftm_responder = -1;
396 }
397
398 + if (attrs[NL80211_ATTR_MBSSID_ELEMS]) {
399 + struct cfg80211_mbssid_elems *mbssid =
400 + nl80211_parse_mbssid_elems(&rdev->wiphy,
401 + attrs[NL80211_ATTR_MBSSID_ELEMS]);
402 +
403 + if (IS_ERR(mbssid))
404 + return PTR_ERR(mbssid);
405 +
406 + bcn->mbssid_ies = mbssid;
407 + }
408 +
409 return 0;
410 }
411
412 @@ -5556,6 +5702,17 @@ static int nl80211_start_ap(struct sk_bu
413 goto out;
414 }
415
416 + if (info->attrs[NL80211_ATTR_MBSSID_CONFIG]) {
417 + err = nl80211_parse_mbssid_config(&rdev->wiphy, dev,
418 + info->attrs[NL80211_ATTR_MBSSID_CONFIG],
419 + &params.mbssid_config,
420 + params.beacon.mbssid_ies ?
421 + params.beacon.mbssid_ies->cnt :
422 + 0);
423 + if (err)
424 + goto out;
425 + }
426 +
427 nl80211_calculate_ap_params(&params);
428
429 if (info->attrs[NL80211_ATTR_EXTERNAL_AUTH_SUPPORT])
430 @@ -5577,6 +5734,11 @@ static int nl80211_start_ap(struct sk_bu
431
432 out:
433 kfree(params.acl);
434 + kfree(params.beacon.mbssid_ies);
435 + if (params.mbssid_config.tx_wdev &&
436 + params.mbssid_config.tx_wdev->netdev &&
437 + params.mbssid_config.tx_wdev->netdev != dev)
438 + dev_put(params.mbssid_config.tx_wdev->netdev);
439
440 return err;
441 }
442 @@ -5601,12 +5763,14 @@ static int nl80211_set_beacon(struct sk_
443
444 err = nl80211_parse_beacon(rdev, info->attrs, &params);
445 if (err)
446 - return err;
447 + goto out;
448
449 wdev_lock(wdev);
450 err = rdev_change_beacon(rdev, dev, &params);
451 wdev_unlock(wdev);
452
453 +out:
454 + kfree(params.mbssid_ies);
455 return err;
456 }
457
458 @@ -9283,12 +9447,14 @@ static int nl80211_channel_switch(struct
459
460 err = nl80211_parse_beacon(rdev, info->attrs, &params.beacon_after);
461 if (err)
462 - return err;
463 + goto free;
464
465 csa_attrs = kcalloc(NL80211_ATTR_MAX + 1, sizeof(*csa_attrs),
466 GFP_KERNEL);
467 - if (!csa_attrs)
468 - return -ENOMEM;
469 + if (!csa_attrs) {
470 + err = -ENOMEM;
471 + goto free;
472 + }
473
474 err = nla_parse_nested_deprecated(csa_attrs, NL80211_ATTR_MAX,
475 info->attrs[NL80211_ATTR_CSA_IES],
476 @@ -9407,6 +9573,8 @@ skip_beacons:
477 wdev_unlock(wdev);
478
479 free:
480 + kfree(params.beacon_after.mbssid_ies);
481 + kfree(params.beacon_csa.mbssid_ies);
482 kfree(csa_attrs);
483 return err;
484 }
485 @@ -14959,6 +15127,8 @@ static int nl80211_color_change(struct s
486 wdev_unlock(wdev);
487
488 out:
489 + kfree(params.beacon_next.mbssid_ies);
490 + kfree(params.beacon_color_change.mbssid_ies);
491 kfree(tb);
492 return err;
493 }