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