mac80211: Update to version 5.14.13-1
[openwrt/staging/stintel.git] / package / kernel / mac80211 / patches / subsys / 387-nl80211-add-support-for-BSS-coloring.patch
1 From 0d2ab3aea50bb02ff0c9c3d53c7b2b4b21cdd59d Mon Sep 17 00:00:00 2001
2 From: John Crispin <john@phrozen.org>
3 Date: Fri, 2 Jul 2021 19:44:07 +0200
4 Subject: [PATCH] nl80211: add support for BSS coloring
5
6 This patch adds support for BSS color collisions to the wireless subsystem.
7 Add the required functionality to nl80211 that will notify about color
8 collisions, triggering the color change and notifying when it is completed.
9
10 Co-developed-by: Lorenzo Bianconi <lorenzo@kernel.org>
11 Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
12 Signed-off-by: John Crispin <john@phrozen.org>
13 Link: https://lore.kernel.org/r/500b3582aec8fe2c42ef46f3117b148cb7cbceb5.1625247619.git.lorenzo@kernel.org
14 [remove unnecessary NULL initialisation]
15 Signed-off-by: Johannes Berg <johannes.berg@intel.com>
16 ---
17 include/net/cfg80211.h | 92 ++++++++++++++++++++
18 include/uapi/linux/nl80211.h | 43 ++++++++++
19 net/wireless/nl80211.c | 157 +++++++++++++++++++++++++++++++++++
20 net/wireless/rdev-ops.h | 13 +++
21 net/wireless/trace.h | 46 ++++++++++
22 5 files changed, 351 insertions(+)
23
24 --- a/include/net/cfg80211.h
25 +++ b/include/net/cfg80211.h
26 @@ -1258,6 +1258,27 @@ struct cfg80211_csa_settings {
27 };
28
29 /**
30 + * struct cfg80211_color_change_settings - color change settings
31 + *
32 + * Used for bss color change
33 + *
34 + * @beacon_color_change: beacon data while performing the color countdown
35 + * @counter_offsets_beacon: offsets of the counters within the beacon (tail)
36 + * @counter_offsets_presp: offsets of the counters within the probe response
37 + * @beacon_next: beacon data to be used after the color change
38 + * @count: number of beacons until the color change
39 + * @color: the color used after the change
40 + */
41 +struct cfg80211_color_change_settings {
42 + struct cfg80211_beacon_data beacon_color_change;
43 + u16 counter_offset_beacon;
44 + u16 counter_offset_presp;
45 + struct cfg80211_beacon_data beacon_next;
46 + u8 count;
47 + u8 color;
48 +};
49 +
50 +/**
51 * struct iface_combination_params - input parameters for interface combinations
52 *
53 * Used to pass interface combination parameters
54 @@ -4000,6 +4021,8 @@ struct mgmt_frame_regs {
55 * given TIDs. This callback may sleep.
56 *
57 * @set_sar_specs: Update the SAR (TX power) settings.
58 + *
59 + * @color_change: Initiate a color change.
60 */
61 struct cfg80211_ops {
62 int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
63 @@ -4327,6 +4350,9 @@ struct cfg80211_ops {
64 const u8 *peer, u8 tids);
65 int (*set_sar_specs)(struct wiphy *wiphy,
66 struct cfg80211_sar_specs *sar);
67 + int (*color_change)(struct wiphy *wiphy,
68 + struct net_device *dev,
69 + struct cfg80211_color_change_settings *params);
70 };
71
72 /*
73 @@ -8226,4 +8252,70 @@ void cfg80211_update_owe_info_event(stru
74 */
75 void cfg80211_bss_flush(struct wiphy *wiphy);
76
77 +/**
78 + * cfg80211_bss_color_notify - notify about bss color event
79 + * @dev: network device
80 + * @gfp: allocation flags
81 + * @cmd: the actual event we want to notify
82 + * @count: the number of TBTTs until the color change happens
83 + * @color_bitmap: representations of the colors that the local BSS is aware of
84 + */
85 +int cfg80211_bss_color_notify(struct net_device *dev, gfp_t gfp,
86 + enum nl80211_commands cmd, u8 count,
87 + u64 color_bitmap);
88 +
89 +/**
90 + * cfg80211_obss_color_collision_notify - notify about bss color collision
91 + * @dev: network device
92 + * @color_bitmap: representations of the colors that the local BSS is aware of
93 + */
94 +static inline int cfg80211_obss_color_collision_notify(struct net_device *dev,
95 + u64 color_bitmap)
96 +{
97 + return cfg80211_bss_color_notify(dev, GFP_KERNEL,
98 + NL80211_CMD_OBSS_COLOR_COLLISION,
99 + 0, color_bitmap);
100 +}
101 +
102 +/**
103 + * cfg80211_color_change_started_notify - notify color change start
104 + * @dev: the device on which the color is switched
105 + * @count: the number of TBTTs until the color change happens
106 + *
107 + * Inform the userspace about the color change that has started.
108 + */
109 +static inline int cfg80211_color_change_started_notify(struct net_device *dev,
110 + u8 count)
111 +{
112 + return cfg80211_bss_color_notify(dev, GFP_KERNEL,
113 + NL80211_CMD_COLOR_CHANGE_STARTED,
114 + count, 0);
115 +}
116 +
117 +/**
118 + * cfg80211_color_change_aborted_notify - notify color change abort
119 + * @dev: the device on which the color is switched
120 + *
121 + * Inform the userspace about the color change that has aborted.
122 + */
123 +static inline int cfg80211_color_change_aborted_notify(struct net_device *dev)
124 +{
125 + return cfg80211_bss_color_notify(dev, GFP_KERNEL,
126 + NL80211_CMD_COLOR_CHANGE_ABORTED,
127 + 0, 0);
128 +}
129 +
130 +/**
131 + * cfg80211_color_change_notify - notify color change completion
132 + * @dev: the device on which the color was switched
133 + *
134 + * Inform the userspace about the color change that has completed.
135 + */
136 +static inline int cfg80211_color_change_notify(struct net_device *dev)
137 +{
138 + return cfg80211_bss_color_notify(dev, GFP_KERNEL,
139 + NL80211_CMD_COLOR_CHANGE_COMPLETED,
140 + 0, 0);
141 +}
142 +
143 #endif /* __NET_CFG80211_H */
144 --- a/include/uapi/linux/nl80211.h
145 +++ b/include/uapi/linux/nl80211.h
146 @@ -1185,6 +1185,21 @@
147 * passed using %NL80211_ATTR_SAR_SPEC. %NL80211_ATTR_WIPHY is used to
148 * specify the wiphy index to be applied to.
149 *
150 + * @NL80211_CMD_OBSS_COLOR_COLLISION: This notification is sent out whenever
151 + * mac80211/drv detects a bss color collision.
152 + *
153 + * @NL80211_CMD_COLOR_CHANGE_REQUEST: This command is used to indicate that
154 + * userspace wants to change the BSS color.
155 + *
156 + * @NL80211_CMD_COLOR_CHANGE_STARTED: Notify userland, that a color change has
157 + * started
158 + *
159 + * @NL80211_CMD_COLOR_CHANGE_ABORTED: Notify userland, that the color change has
160 + * been aborted
161 + *
162 + * @NL80211_CMD_COLOR_CHANGE_COMPLETED: Notify userland that the color change
163 + * has completed
164 + *
165 * @NL80211_CMD_MAX: highest used command number
166 * @__NL80211_CMD_AFTER_LAST: internal use
167 */
168 @@ -1417,6 +1432,14 @@ enum nl80211_commands {
169
170 NL80211_CMD_SET_SAR_SPECS,
171
172 + NL80211_CMD_OBSS_COLOR_COLLISION,
173 +
174 + NL80211_CMD_COLOR_CHANGE_REQUEST,
175 +
176 + NL80211_CMD_COLOR_CHANGE_STARTED,
177 + NL80211_CMD_COLOR_CHANGE_ABORTED,
178 + NL80211_CMD_COLOR_CHANGE_COMPLETED,
179 +
180 /* add new commands above here */
181
182 /* used to define NL80211_CMD_MAX below */
183 @@ -2560,6 +2583,16 @@ enum nl80211_commands {
184 * disassoc events to indicate that an immediate reconnect to the AP
185 * is desired.
186 *
187 + * @NL80211_ATTR_OBSS_COLOR_BITMAP: bitmap of the u64 BSS colors for the
188 + * %NL80211_CMD_OBSS_COLOR_COLLISION event.
189 + *
190 + * @NL80211_ATTR_COLOR_CHANGE_COUNT: u8 attribute specifying the number of TBTT's
191 + * until the color switch event.
192 + * @NL80211_ATTR_COLOR_CHANGE_COLOR: u8 attribute specifying the color that we are
193 + * switching to
194 + * @NL80211_ATTR_COLOR_CHANGE_ELEMS: Nested set of attributes containing the IE
195 + * information for the time while performing a color switch.
196 + *
197 * @NUM_NL80211_ATTR: total number of nl80211_attrs available
198 * @NL80211_ATTR_MAX: highest attribute number currently defined
199 * @__NL80211_ATTR_AFTER_LAST: internal use
200 @@ -3057,6 +3090,12 @@ enum nl80211_attrs {
201
202 NL80211_ATTR_DISABLE_HE,
203
204 + NL80211_ATTR_OBSS_COLOR_BITMAP,
205 +
206 + NL80211_ATTR_COLOR_CHANGE_COUNT,
207 + NL80211_ATTR_COLOR_CHANGE_COLOR,
208 + NL80211_ATTR_COLOR_CHANGE_ELEMS,
209 +
210 /* add attributes here, update the policy in nl80211.c */
211
212 __NL80211_ATTR_AFTER_LAST,
213 @@ -5953,6 +5992,9 @@ enum nl80211_feature_flags {
214 * frame protection for all management frames exchanged during the
215 * negotiation and range measurement procedure.
216 *
217 + * @NL80211_EXT_FEATURE_BSS_COLOR: The driver supports BSS color collision
218 + * detection and change announcemnts.
219 + *
220 * @NUM_NL80211_EXT_FEATURES: number of extended features.
221 * @MAX_NL80211_EXT_FEATURES: highest extended feature index.
222 */
223 @@ -6017,6 +6059,7 @@ enum nl80211_ext_feature_index {
224 NL80211_EXT_FEATURE_SECURE_LTF,
225 NL80211_EXT_FEATURE_SECURE_RTT,
226 NL80211_EXT_FEATURE_PROT_RANGE_NEGO_AND_MEASURE,
227 + NL80211_EXT_FEATURE_BSS_COLOR,
228
229 /* add new features before the definition below */
230 NUM_NL80211_EXT_FEATURES,
231 --- a/net/wireless/nl80211.c
232 +++ b/net/wireless/nl80211.c
233 @@ -776,6 +776,10 @@ static const struct nla_policy nl80211_p
234 [NL80211_ATTR_RECONNECT_REQUESTED] = { .type = NLA_REJECT },
235 [NL80211_ATTR_SAR_SPEC] = NLA_POLICY_NESTED(sar_policy),
236 [NL80211_ATTR_DISABLE_HE] = { .type = NLA_FLAG },
237 + [NL80211_ATTR_OBSS_COLOR_BITMAP] = { .type = NLA_U64 },
238 + [NL80211_ATTR_COLOR_CHANGE_COUNT] = { .type = NLA_U8 },
239 + [NL80211_ATTR_COLOR_CHANGE_COLOR] = { .type = NLA_U8 },
240 + [NL80211_ATTR_COLOR_CHANGE_ELEMS] = NLA_POLICY_NESTED(nl80211_policy),
241 };
242
243 /* policy for the key attributes */
244 @@ -14823,6 +14827,106 @@ bad_tid_conf:
245 return ret;
246 }
247
248 +static int nl80211_color_change(struct sk_buff *skb, struct genl_info *info)
249 +{
250 + struct cfg80211_registered_device *rdev = info->user_ptr[0];
251 + struct cfg80211_color_change_settings params = {};
252 + struct net_device *dev = info->user_ptr[1];
253 + struct wireless_dev *wdev = dev->ieee80211_ptr;
254 + struct nlattr **tb;
255 + u16 offset;
256 + int err;
257 +
258 + if (!rdev->ops->color_change)
259 + return -EOPNOTSUPP;
260 +
261 + if (!wiphy_ext_feature_isset(&rdev->wiphy,
262 + NL80211_EXT_FEATURE_BSS_COLOR))
263 + return -EOPNOTSUPP;
264 +
265 + if (wdev->iftype != NL80211_IFTYPE_AP)
266 + return -EOPNOTSUPP;
267 +
268 + if (!info->attrs[NL80211_ATTR_COLOR_CHANGE_COUNT] ||
269 + !info->attrs[NL80211_ATTR_COLOR_CHANGE_COLOR] ||
270 + !info->attrs[NL80211_ATTR_COLOR_CHANGE_ELEMS])
271 + return -EINVAL;
272 +
273 + params.count = nla_get_u8(info->attrs[NL80211_ATTR_COLOR_CHANGE_COUNT]);
274 + params.color = nla_get_u8(info->attrs[NL80211_ATTR_COLOR_CHANGE_COLOR]);
275 +
276 + err = nl80211_parse_beacon(rdev, info->attrs, &params.beacon_next);
277 + if (err)
278 + return err;
279 +
280 + tb = kcalloc(NL80211_ATTR_MAX + 1, sizeof(*tb), GFP_KERNEL);
281 + if (!tb)
282 + return -ENOMEM;
283 +
284 + err = nla_parse_nested(tb, NL80211_ATTR_MAX,
285 + info->attrs[NL80211_ATTR_COLOR_CHANGE_ELEMS],
286 + nl80211_policy, info->extack);
287 + if (err)
288 + goto out;
289 +
290 + err = nl80211_parse_beacon(rdev, tb, &params.beacon_color_change);
291 + if (err)
292 + goto out;
293 +
294 + if (!tb[NL80211_ATTR_CNTDWN_OFFS_BEACON]) {
295 + err = -EINVAL;
296 + goto out;
297 + }
298 +
299 + if (nla_len(tb[NL80211_ATTR_CNTDWN_OFFS_BEACON]) != sizeof(u16)) {
300 + err = -EINVAL;
301 + goto out;
302 + }
303 +
304 + offset = nla_get_u16(tb[NL80211_ATTR_CNTDWN_OFFS_BEACON]);
305 + if (offset >= params.beacon_color_change.tail_len) {
306 + err = -EINVAL;
307 + goto out;
308 + }
309 +
310 + if (params.beacon_color_change.tail[offset] != params.count) {
311 + err = -EINVAL;
312 + goto out;
313 + }
314 +
315 + params.counter_offset_beacon = offset;
316 +
317 + if (tb[NL80211_ATTR_CNTDWN_OFFS_PRESP]) {
318 + if (nla_len(tb[NL80211_ATTR_CNTDWN_OFFS_PRESP]) !=
319 + sizeof(u16)) {
320 + err = -EINVAL;
321 + goto out;
322 + }
323 +
324 + offset = nla_get_u16(tb[NL80211_ATTR_CNTDWN_OFFS_PRESP]);
325 + if (offset >= params.beacon_color_change.probe_resp_len) {
326 + err = -EINVAL;
327 + goto out;
328 + }
329 +
330 + if (params.beacon_color_change.probe_resp[offset] !=
331 + params.count) {
332 + err = -EINVAL;
333 + goto out;
334 + }
335 +
336 + params.counter_offset_presp = offset;
337 + }
338 +
339 + wdev_lock(wdev);
340 + err = rdev_color_change(rdev, dev, &params);
341 + wdev_unlock(wdev);
342 +
343 +out:
344 + kfree(tb);
345 + return err;
346 +}
347 +
348 #define NL80211_FLAG_NEED_WIPHY 0x01
349 #define NL80211_FLAG_NEED_NETDEV 0x02
350 #define NL80211_FLAG_NEED_RTNL 0x04
351 @@ -15823,6 +15927,14 @@ static const struct genl_small_ops nl802
352 .internal_flags = NL80211_FLAG_NEED_WIPHY |
353 NL80211_FLAG_NEED_RTNL,
354 },
355 + {
356 + .cmd = NL80211_CMD_COLOR_CHANGE_REQUEST,
357 + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
358 + .doit = nl80211_color_change,
359 + .flags = GENL_UNS_ADMIN_PERM,
360 + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
361 + NL80211_FLAG_NEED_RTNL,
362 + },
363 };
364
365 static struct genl_family nl80211_fam __genl_ro_after_init = {
366 @@ -17454,6 +17566,51 @@ void cfg80211_ch_switch_started_notify(s
367 }
368 EXPORT_SYMBOL(cfg80211_ch_switch_started_notify);
369
370 +int cfg80211_bss_color_notify(struct net_device *dev, gfp_t gfp,
371 + enum nl80211_commands cmd, u8 count,
372 + u64 color_bitmap)
373 +{
374 + struct wireless_dev *wdev = dev->ieee80211_ptr;
375 + struct wiphy *wiphy = wdev->wiphy;
376 + struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
377 + struct sk_buff *msg;
378 + void *hdr;
379 +
380 + ASSERT_WDEV_LOCK(wdev);
381 +
382 + trace_cfg80211_bss_color_notify(dev, cmd, count, color_bitmap);
383 +
384 + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
385 + if (!msg)
386 + return -ENOMEM;
387 +
388 + hdr = nl80211hdr_put(msg, 0, 0, 0, cmd);
389 + if (!hdr)
390 + goto nla_put_failure;
391 +
392 + if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex))
393 + goto nla_put_failure;
394 +
395 + if (cmd == NL80211_CMD_COLOR_CHANGE_STARTED &&
396 + nla_put_u32(msg, NL80211_ATTR_COLOR_CHANGE_COUNT, count))
397 + goto nla_put_failure;
398 +
399 + if (cmd == NL80211_CMD_OBSS_COLOR_COLLISION &&
400 + nla_put_u64_64bit(msg, NL80211_ATTR_OBSS_COLOR_BITMAP,
401 + color_bitmap, NL80211_ATTR_PAD))
402 + goto nla_put_failure;
403 +
404 + genlmsg_end(msg, hdr);
405 +
406 + return genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy),
407 + msg, 0, NL80211_MCGRP_MLME, gfp);
408 +
409 +nla_put_failure:
410 + nlmsg_free(msg);
411 + return -EINVAL;
412 +}
413 +EXPORT_SYMBOL(cfg80211_bss_color_notify);
414 +
415 void
416 nl80211_radar_notify(struct cfg80211_registered_device *rdev,
417 const struct cfg80211_chan_def *chandef,
418 --- a/net/wireless/rdev-ops.h
419 +++ b/net/wireless/rdev-ops.h
420 @@ -1368,4 +1368,17 @@ static inline int rdev_set_sar_specs(str
421 return ret;
422 }
423
424 +static inline int rdev_color_change(struct cfg80211_registered_device *rdev,
425 + struct net_device *dev,
426 + struct cfg80211_color_change_settings *params)
427 +{
428 + int ret;
429 +
430 + trace_rdev_color_change(&rdev->wiphy, dev, params);
431 + ret = rdev->ops->color_change(&rdev->wiphy, dev, params);
432 + trace_rdev_return_int(&rdev->wiphy, ret);
433 +
434 + return ret;
435 +}
436 +
437 #endif /* __CFG80211_RDEV_OPS */
438 --- a/net/wireless/trace.h
439 +++ b/net/wireless/trace.h
440 @@ -3597,6 +3597,52 @@ TRACE_EVENT(rdev_set_sar_specs,
441 WIPHY_PR_ARG, __entry->type, __entry->num)
442 );
443
444 +TRACE_EVENT(rdev_color_change,
445 + TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
446 + struct cfg80211_color_change_settings *params),
447 + TP_ARGS(wiphy, netdev, params),
448 + TP_STRUCT__entry(
449 + WIPHY_ENTRY
450 + NETDEV_ENTRY
451 + __field(u8, count)
452 + __field(u16, bcn_ofs)
453 + __field(u16, pres_ofs)
454 + ),
455 + TP_fast_assign(
456 + WIPHY_ASSIGN;
457 + NETDEV_ASSIGN;
458 + __entry->count = params->count;
459 + __entry->bcn_ofs = params->counter_offset_beacon;
460 + __entry->pres_ofs = params->counter_offset_presp;
461 + ),
462 + TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT
463 + ", count: %u",
464 + WIPHY_PR_ARG, NETDEV_PR_ARG,
465 + __entry->count)
466 +);
467 +
468 +TRACE_EVENT(cfg80211_bss_color_notify,
469 + TP_PROTO(struct net_device *netdev,
470 + enum nl80211_commands cmd,
471 + u8 count, u64 color_bitmap),
472 + TP_ARGS(netdev, cmd, count, color_bitmap),
473 + TP_STRUCT__entry(
474 + NETDEV_ENTRY
475 + __field(enum nl80211_bss_scan_width, cmd)
476 + __field(u8, count)
477 + __field(u64, color_bitmap)
478 + ),
479 + TP_fast_assign(
480 + NETDEV_ASSIGN;
481 + __entry->cmd = cmd;
482 + __entry->count = count;
483 + __entry->color_bitmap = color_bitmap;
484 + ),
485 + TP_printk(NETDEV_PR_FMT ", cmd: %x, count: %u, bitmap: %llx",
486 + NETDEV_PR_ARG, __entry->cmd, __entry->count,
487 + __entry->color_bitmap)
488 +);
489 +
490 #endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */
491
492 #undef TRACE_INCLUDE_PATH