Skip to content

Commit 0d2ab3a

Browse files
blogicjmberg-intel
authored andcommitted
nl80211: add support for BSS coloring
This patch adds support for BSS color collisions to the wireless subsystem. Add the required functionality to nl80211 that will notify about color collisions, triggering the color change and notifying when it is completed. Co-developed-by: Lorenzo Bianconi <[email protected]> Signed-off-by: Lorenzo Bianconi <[email protected]> Signed-off-by: John Crispin <[email protected]> Link: https://lore.kernel.org/r/500b3582aec8fe2c42ef46f3117b148cb7cbceb5.1625247619.git.lorenzo@kernel.org [remove unnecessary NULL initialisation] Signed-off-by: Johannes Berg <[email protected]>
1 parent 8c89f7b commit 0d2ab3a

File tree

5 files changed

+351
-0
lines changed

5 files changed

+351
-0
lines changed

include/net/cfg80211.h

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1252,6 +1252,27 @@ struct cfg80211_csa_settings {
12521252
u8 count;
12531253
};
12541254

1255+
/**
1256+
* struct cfg80211_color_change_settings - color change settings
1257+
*
1258+
* Used for bss color change
1259+
*
1260+
* @beacon_color_change: beacon data while performing the color countdown
1261+
* @counter_offsets_beacon: offsets of the counters within the beacon (tail)
1262+
* @counter_offsets_presp: offsets of the counters within the probe response
1263+
* @beacon_next: beacon data to be used after the color change
1264+
* @count: number of beacons until the color change
1265+
* @color: the color used after the change
1266+
*/
1267+
struct cfg80211_color_change_settings {
1268+
struct cfg80211_beacon_data beacon_color_change;
1269+
u16 counter_offset_beacon;
1270+
u16 counter_offset_presp;
1271+
struct cfg80211_beacon_data beacon_next;
1272+
u8 count;
1273+
u8 color;
1274+
};
1275+
12551276
/**
12561277
* struct iface_combination_params - input parameters for interface combinations
12571278
*
@@ -3995,6 +4016,8 @@ struct mgmt_frame_regs {
39954016
* given TIDs. This callback may sleep.
39964017
*
39974018
* @set_sar_specs: Update the SAR (TX power) settings.
4019+
*
4020+
* @color_change: Initiate a color change.
39984021
*/
39994022
struct cfg80211_ops {
40004023
int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -4322,6 +4345,9 @@ struct cfg80211_ops {
43224345
const u8 *peer, u8 tids);
43234346
int (*set_sar_specs)(struct wiphy *wiphy,
43244347
struct cfg80211_sar_specs *sar);
4348+
int (*color_change)(struct wiphy *wiphy,
4349+
struct net_device *dev,
4350+
struct cfg80211_color_change_settings *params);
43254351
};
43264352

43274353
/*
@@ -8218,4 +8244,70 @@ void cfg80211_update_owe_info_event(struct net_device *netdev,
82188244
*/
82198245
void cfg80211_bss_flush(struct wiphy *wiphy);
82208246

8247+
/**
8248+
* cfg80211_bss_color_notify - notify about bss color event
8249+
* @dev: network device
8250+
* @gfp: allocation flags
8251+
* @cmd: the actual event we want to notify
8252+
* @count: the number of TBTTs until the color change happens
8253+
* @color_bitmap: representations of the colors that the local BSS is aware of
8254+
*/
8255+
int cfg80211_bss_color_notify(struct net_device *dev, gfp_t gfp,
8256+
enum nl80211_commands cmd, u8 count,
8257+
u64 color_bitmap);
8258+
8259+
/**
8260+
* cfg80211_obss_color_collision_notify - notify about bss color collision
8261+
* @dev: network device
8262+
* @color_bitmap: representations of the colors that the local BSS is aware of
8263+
*/
8264+
static inline int cfg80211_obss_color_collision_notify(struct net_device *dev,
8265+
u64 color_bitmap)
8266+
{
8267+
return cfg80211_bss_color_notify(dev, GFP_KERNEL,
8268+
NL80211_CMD_OBSS_COLOR_COLLISION,
8269+
0, color_bitmap);
8270+
}
8271+
8272+
/**
8273+
* cfg80211_color_change_started_notify - notify color change start
8274+
* @dev: the device on which the color is switched
8275+
* @count: the number of TBTTs until the color change happens
8276+
*
8277+
* Inform the userspace about the color change that has started.
8278+
*/
8279+
static inline int cfg80211_color_change_started_notify(struct net_device *dev,
8280+
u8 count)
8281+
{
8282+
return cfg80211_bss_color_notify(dev, GFP_KERNEL,
8283+
NL80211_CMD_COLOR_CHANGE_STARTED,
8284+
count, 0);
8285+
}
8286+
8287+
/**
8288+
* cfg80211_color_change_aborted_notify - notify color change abort
8289+
* @dev: the device on which the color is switched
8290+
*
8291+
* Inform the userspace about the color change that has aborted.
8292+
*/
8293+
static inline int cfg80211_color_change_aborted_notify(struct net_device *dev)
8294+
{
8295+
return cfg80211_bss_color_notify(dev, GFP_KERNEL,
8296+
NL80211_CMD_COLOR_CHANGE_ABORTED,
8297+
0, 0);
8298+
}
8299+
8300+
/**
8301+
* cfg80211_color_change_notify - notify color change completion
8302+
* @dev: the device on which the color was switched
8303+
*
8304+
* Inform the userspace about the color change that has completed.
8305+
*/
8306+
static inline int cfg80211_color_change_notify(struct net_device *dev)
8307+
{
8308+
return cfg80211_bss_color_notify(dev, GFP_KERNEL,
8309+
NL80211_CMD_COLOR_CHANGE_COMPLETED,
8310+
0, 0);
8311+
}
8312+
82218313
#endif /* __NET_CFG80211_H */

include/uapi/linux/nl80211.h

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1185,6 +1185,21 @@
11851185
* passed using %NL80211_ATTR_SAR_SPEC. %NL80211_ATTR_WIPHY is used to
11861186
* specify the wiphy index to be applied to.
11871187
*
1188+
* @NL80211_CMD_OBSS_COLOR_COLLISION: This notification is sent out whenever
1189+
* mac80211/drv detects a bss color collision.
1190+
*
1191+
* @NL80211_CMD_COLOR_CHANGE_REQUEST: This command is used to indicate that
1192+
* userspace wants to change the BSS color.
1193+
*
1194+
* @NL80211_CMD_COLOR_CHANGE_STARTED: Notify userland, that a color change has
1195+
* started
1196+
*
1197+
* @NL80211_CMD_COLOR_CHANGE_ABORTED: Notify userland, that the color change has
1198+
* been aborted
1199+
*
1200+
* @NL80211_CMD_COLOR_CHANGE_COMPLETED: Notify userland that the color change
1201+
* has completed
1202+
*
11881203
* @NL80211_CMD_MAX: highest used command number
11891204
* @__NL80211_CMD_AFTER_LAST: internal use
11901205
*/
@@ -1417,6 +1432,14 @@ enum nl80211_commands {
14171432

14181433
NL80211_CMD_SET_SAR_SPECS,
14191434

1435+
NL80211_CMD_OBSS_COLOR_COLLISION,
1436+
1437+
NL80211_CMD_COLOR_CHANGE_REQUEST,
1438+
1439+
NL80211_CMD_COLOR_CHANGE_STARTED,
1440+
NL80211_CMD_COLOR_CHANGE_ABORTED,
1441+
NL80211_CMD_COLOR_CHANGE_COMPLETED,
1442+
14201443
/* add new commands above here */
14211444

14221445
/* used to define NL80211_CMD_MAX below */
@@ -2560,6 +2583,16 @@ enum nl80211_commands {
25602583
* disassoc events to indicate that an immediate reconnect to the AP
25612584
* is desired.
25622585
*
2586+
* @NL80211_ATTR_OBSS_COLOR_BITMAP: bitmap of the u64 BSS colors for the
2587+
* %NL80211_CMD_OBSS_COLOR_COLLISION event.
2588+
*
2589+
* @NL80211_ATTR_COLOR_CHANGE_COUNT: u8 attribute specifying the number of TBTT's
2590+
* until the color switch event.
2591+
* @NL80211_ATTR_COLOR_CHANGE_COLOR: u8 attribute specifying the color that we are
2592+
* switching to
2593+
* @NL80211_ATTR_COLOR_CHANGE_ELEMS: Nested set of attributes containing the IE
2594+
* information for the time while performing a color switch.
2595+
*
25632596
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
25642597
* @NL80211_ATTR_MAX: highest attribute number currently defined
25652598
* @__NL80211_ATTR_AFTER_LAST: internal use
@@ -3057,6 +3090,12 @@ enum nl80211_attrs {
30573090

30583091
NL80211_ATTR_DISABLE_HE,
30593092

3093+
NL80211_ATTR_OBSS_COLOR_BITMAP,
3094+
3095+
NL80211_ATTR_COLOR_CHANGE_COUNT,
3096+
NL80211_ATTR_COLOR_CHANGE_COLOR,
3097+
NL80211_ATTR_COLOR_CHANGE_ELEMS,
3098+
30603099
/* add attributes here, update the policy in nl80211.c */
30613100

30623101
__NL80211_ATTR_AFTER_LAST,
@@ -5953,6 +5992,9 @@ enum nl80211_feature_flags {
59535992
* frame protection for all management frames exchanged during the
59545993
* negotiation and range measurement procedure.
59555994
*
5995+
* @NL80211_EXT_FEATURE_BSS_COLOR: The driver supports BSS color collision
5996+
* detection and change announcemnts.
5997+
*
59565998
* @NUM_NL80211_EXT_FEATURES: number of extended features.
59575999
* @MAX_NL80211_EXT_FEATURES: highest extended feature index.
59586000
*/
@@ -6017,6 +6059,7 @@ enum nl80211_ext_feature_index {
60176059
NL80211_EXT_FEATURE_SECURE_LTF,
60186060
NL80211_EXT_FEATURE_SECURE_RTT,
60196061
NL80211_EXT_FEATURE_PROT_RANGE_NEGO_AND_MEASURE,
6062+
NL80211_EXT_FEATURE_BSS_COLOR,
60206063

60216064
/* add new features before the definition below */
60226065
NUM_NL80211_EXT_FEATURES,

net/wireless/nl80211.c

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -759,6 +759,10 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
759759
[NL80211_ATTR_RECONNECT_REQUESTED] = { .type = NLA_REJECT },
760760
[NL80211_ATTR_SAR_SPEC] = NLA_POLICY_NESTED(sar_policy),
761761
[NL80211_ATTR_DISABLE_HE] = { .type = NLA_FLAG },
762+
[NL80211_ATTR_OBSS_COLOR_BITMAP] = { .type = NLA_U64 },
763+
[NL80211_ATTR_COLOR_CHANGE_COUNT] = { .type = NLA_U8 },
764+
[NL80211_ATTR_COLOR_CHANGE_COLOR] = { .type = NLA_U8 },
765+
[NL80211_ATTR_COLOR_CHANGE_ELEMS] = NLA_POLICY_NESTED(nl80211_policy),
762766
};
763767

764768
/* policy for the key attributes */
@@ -14800,6 +14804,106 @@ static int nl80211_set_tid_config(struct sk_buff *skb,
1480014804
return ret;
1480114805
}
1480214806

14807+
static int nl80211_color_change(struct sk_buff *skb, struct genl_info *info)
14808+
{
14809+
struct cfg80211_registered_device *rdev = info->user_ptr[0];
14810+
struct cfg80211_color_change_settings params = {};
14811+
struct net_device *dev = info->user_ptr[1];
14812+
struct wireless_dev *wdev = dev->ieee80211_ptr;
14813+
struct nlattr **tb;
14814+
u16 offset;
14815+
int err;
14816+
14817+
if (!rdev->ops->color_change)
14818+
return -EOPNOTSUPP;
14819+
14820+
if (!wiphy_ext_feature_isset(&rdev->wiphy,
14821+
NL80211_EXT_FEATURE_BSS_COLOR))
14822+
return -EOPNOTSUPP;
14823+
14824+
if (wdev->iftype != NL80211_IFTYPE_AP)
14825+
return -EOPNOTSUPP;
14826+
14827+
if (!info->attrs[NL80211_ATTR_COLOR_CHANGE_COUNT] ||
14828+
!info->attrs[NL80211_ATTR_COLOR_CHANGE_COLOR] ||
14829+
!info->attrs[NL80211_ATTR_COLOR_CHANGE_ELEMS])
14830+
return -EINVAL;
14831+
14832+
params.count = nla_get_u8(info->attrs[NL80211_ATTR_COLOR_CHANGE_COUNT]);
14833+
params.color = nla_get_u8(info->attrs[NL80211_ATTR_COLOR_CHANGE_COLOR]);
14834+
14835+
err = nl80211_parse_beacon(rdev, info->attrs, &params.beacon_next);
14836+
if (err)
14837+
return err;
14838+
14839+
tb = kcalloc(NL80211_ATTR_MAX + 1, sizeof(*tb), GFP_KERNEL);
14840+
if (!tb)
14841+
return -ENOMEM;
14842+
14843+
err = nla_parse_nested(tb, NL80211_ATTR_MAX,
14844+
info->attrs[NL80211_ATTR_COLOR_CHANGE_ELEMS],
14845+
nl80211_policy, info->extack);
14846+
if (err)
14847+
goto out;
14848+
14849+
err = nl80211_parse_beacon(rdev, tb, &params.beacon_color_change);
14850+
if (err)
14851+
goto out;
14852+
14853+
if (!tb[NL80211_ATTR_CNTDWN_OFFS_BEACON]) {
14854+
err = -EINVAL;
14855+
goto out;
14856+
}
14857+
14858+
if (nla_len(tb[NL80211_ATTR_CNTDWN_OFFS_BEACON]) != sizeof(u16)) {
14859+
err = -EINVAL;
14860+
goto out;
14861+
}
14862+
14863+
offset = nla_get_u16(tb[NL80211_ATTR_CNTDWN_OFFS_BEACON]);
14864+
if (offset >= params.beacon_color_change.tail_len) {
14865+
err = -EINVAL;
14866+
goto out;
14867+
}
14868+
14869+
if (params.beacon_color_change.tail[offset] != params.count) {
14870+
err = -EINVAL;
14871+
goto out;
14872+
}
14873+
14874+
params.counter_offset_beacon = offset;
14875+
14876+
if (tb[NL80211_ATTR_CNTDWN_OFFS_PRESP]) {
14877+
if (nla_len(tb[NL80211_ATTR_CNTDWN_OFFS_PRESP]) !=
14878+
sizeof(u16)) {
14879+
err = -EINVAL;
14880+
goto out;
14881+
}
14882+
14883+
offset = nla_get_u16(tb[NL80211_ATTR_CNTDWN_OFFS_PRESP]);
14884+
if (offset >= params.beacon_color_change.probe_resp_len) {
14885+
err = -EINVAL;
14886+
goto out;
14887+
}
14888+
14889+
if (params.beacon_color_change.probe_resp[offset] !=
14890+
params.count) {
14891+
err = -EINVAL;
14892+
goto out;
14893+
}
14894+
14895+
params.counter_offset_presp = offset;
14896+
}
14897+
14898+
wdev_lock(wdev);
14899+
err = rdev_color_change(rdev, dev, &params);
14900+
wdev_unlock(wdev);
14901+
14902+
out:
14903+
kfree(tb);
14904+
return err;
14905+
}
14906+
1480314907
#define NL80211_FLAG_NEED_WIPHY 0x01
1480414908
#define NL80211_FLAG_NEED_NETDEV 0x02
1480514909
#define NL80211_FLAG_NEED_RTNL 0x04
@@ -15795,6 +15899,14 @@ static const struct genl_small_ops nl80211_small_ops[] = {
1579515899
.internal_flags = NL80211_FLAG_NEED_WIPHY |
1579615900
NL80211_FLAG_NEED_RTNL,
1579715901
},
15902+
{
15903+
.cmd = NL80211_CMD_COLOR_CHANGE_REQUEST,
15904+
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
15905+
.doit = nl80211_color_change,
15906+
.flags = GENL_UNS_ADMIN_PERM,
15907+
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
15908+
NL80211_FLAG_NEED_RTNL,
15909+
},
1579815910
};
1579915911

1580015912
static struct genl_family nl80211_fam __ro_after_init = {
@@ -17424,6 +17536,51 @@ void cfg80211_ch_switch_started_notify(struct net_device *dev,
1742417536
}
1742517537
EXPORT_SYMBOL(cfg80211_ch_switch_started_notify);
1742617538

17539+
int cfg80211_bss_color_notify(struct net_device *dev, gfp_t gfp,
17540+
enum nl80211_commands cmd, u8 count,
17541+
u64 color_bitmap)
17542+
{
17543+
struct wireless_dev *wdev = dev->ieee80211_ptr;
17544+
struct wiphy *wiphy = wdev->wiphy;
17545+
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
17546+
struct sk_buff *msg;
17547+
void *hdr;
17548+
17549+
ASSERT_WDEV_LOCK(wdev);
17550+
17551+
trace_cfg80211_bss_color_notify(dev, cmd, count, color_bitmap);
17552+
17553+
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
17554+
if (!msg)
17555+
return -ENOMEM;
17556+
17557+
hdr = nl80211hdr_put(msg, 0, 0, 0, cmd);
17558+
if (!hdr)
17559+
goto nla_put_failure;
17560+
17561+
if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex))
17562+
goto nla_put_failure;
17563+
17564+
if (cmd == NL80211_CMD_COLOR_CHANGE_STARTED &&
17565+
nla_put_u32(msg, NL80211_ATTR_COLOR_CHANGE_COUNT, count))
17566+
goto nla_put_failure;
17567+
17568+
if (cmd == NL80211_CMD_OBSS_COLOR_COLLISION &&
17569+
nla_put_u64_64bit(msg, NL80211_ATTR_OBSS_COLOR_BITMAP,
17570+
color_bitmap, NL80211_ATTR_PAD))
17571+
goto nla_put_failure;
17572+
17573+
genlmsg_end(msg, hdr);
17574+
17575+
return genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy),
17576+
msg, 0, NL80211_MCGRP_MLME, gfp);
17577+
17578+
nla_put_failure:
17579+
nlmsg_free(msg);
17580+
return -EINVAL;
17581+
}
17582+
EXPORT_SYMBOL(cfg80211_bss_color_notify);
17583+
1742717584
void
1742817585
nl80211_radar_notify(struct cfg80211_registered_device *rdev,
1742917586
const struct cfg80211_chan_def *chandef,

0 commit comments

Comments
 (0)