Skip to content

Commit 065563b

Browse files
Veerendranath Jakkamjmberg-intel
authored andcommitted
wifi: cfg80211/nl80211: Add support to indicate STA MLD setup links removal
STA MLD setup links may get removed if AP MLD remove the corresponding affiliated APs with Multi-Link reconfiguration as described in P802.11be_D3.0, section 35.3.6.2.2 Removing affiliated APs. Currently, there is no support to notify such operation to cfg80211 and userspace. Add support for the drivers to indicate STA MLD setup links removal to cfg80211 and notify the same to userspace. Upon receiving such indication from the driver, clear the MLO links information of the removed links in the WDEV. Signed-off-by: Veerendranath Jakkam <[email protected]> Link: https://lore.kernel.org/r/[email protected] [rename function and attribute, fix kernel-doc] Signed-off-by: Johannes Berg <[email protected]>
1 parent a0ed501 commit 065563b

File tree

6 files changed

+121
-0
lines changed

6 files changed

+121
-0
lines changed

include/net/cfg80211.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9205,4 +9205,17 @@ static inline int cfg80211_color_change_notify(struct net_device *dev)
92059205
bool cfg80211_valid_disable_subchannel_bitmap(u16 *bitmap,
92069206
const struct cfg80211_chan_def *chandef);
92079207

9208+
/**
9209+
* cfg80211_links_removed - Notify about removed STA MLD setup links.
9210+
* @dev: network device.
9211+
* @link_mask: BIT mask of removed STA MLD setup link IDs.
9212+
*
9213+
* Inform cfg80211 and the userspace about removed STA MLD setup links due to
9214+
* AP MLD removing the corresponding affiliated APs with Multi-Link
9215+
* reconfiguration. Note that it's not valid to remove all links, in this
9216+
* case disconnect instead.
9217+
* Also note that the wdev mutex must be held.
9218+
*/
9219+
void cfg80211_links_removed(struct net_device *dev, u16 link_mask);
9220+
92089221
#endif /* __NET_CFG80211_H */

include/uapi/linux/nl80211.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1309,6 +1309,11 @@
13091309
* The number of peers that HW timestamping can be enabled for concurrently
13101310
* is indicated by %NL80211_ATTR_MAX_HW_TIMESTAMP_PEERS.
13111311
*
1312+
* @NL80211_CMD_LINKS_REMOVED: Notify userspace about the removal of STA MLD
1313+
* setup links due to AP MLD removing the corresponding affiliated APs with
1314+
* Multi-Link reconfiguration. %NL80211_ATTR_MLO_LINKS is used to provide
1315+
* information about the removed STA MLD setup links.
1316+
*
13121317
* @NL80211_CMD_MAX: highest used command number
13131318
* @__NL80211_CMD_AFTER_LAST: internal use
13141319
*/
@@ -1562,6 +1567,8 @@ enum nl80211_commands {
15621567

15631568
NL80211_CMD_SET_HW_TIMESTAMP,
15641569

1570+
NL80211_CMD_LINKS_REMOVED,
1571+
15651572
/* add new commands above here */
15661573

15671574
/* used to define NL80211_CMD_MAX below */

net/wireless/core.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -576,5 +576,6 @@ void cfg80211_remove_link(struct wireless_dev *wdev, unsigned int link_id);
576576
void cfg80211_remove_links(struct wireless_dev *wdev);
577577
int cfg80211_remove_virtual_intf(struct cfg80211_registered_device *rdev,
578578
struct wireless_dev *wdev);
579+
void cfg80211_wdev_release_link_bsses(struct wireless_dev *wdev, u16 link_mask);
579580

580581
#endif /* __NET_WIRELESS_CORE_H */

net/wireless/nl80211.c

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18288,6 +18288,76 @@ void nl80211_send_disconnected(struct cfg80211_registered_device *rdev,
1828818288
nlmsg_free(msg);
1828918289
}
1829018290

18291+
void cfg80211_links_removed(struct net_device *dev, u16 link_mask)
18292+
{
18293+
struct wireless_dev *wdev = dev->ieee80211_ptr;
18294+
struct wiphy *wiphy = wdev->wiphy;
18295+
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
18296+
struct sk_buff *msg;
18297+
struct nlattr *links;
18298+
void *hdr;
18299+
18300+
ASSERT_WDEV_LOCK(wdev);
18301+
trace_cfg80211_links_removed(dev, link_mask);
18302+
18303+
if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION &&
18304+
wdev->iftype != NL80211_IFTYPE_P2P_CLIENT))
18305+
return;
18306+
18307+
if (WARN_ON(!wdev->valid_links || !link_mask ||
18308+
(wdev->valid_links & link_mask) != link_mask ||
18309+
wdev->valid_links == link_mask))
18310+
return;
18311+
18312+
cfg80211_wdev_release_link_bsses(wdev, link_mask);
18313+
wdev->valid_links &= ~link_mask;
18314+
18315+
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
18316+
if (!msg)
18317+
return;
18318+
18319+
hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_LINKS_REMOVED);
18320+
if (!hdr) {
18321+
nlmsg_free(msg);
18322+
return;
18323+
}
18324+
18325+
if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
18326+
nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex))
18327+
goto nla_put_failure;
18328+
18329+
links = nla_nest_start(msg, NL80211_ATTR_MLO_LINKS);
18330+
if (!links)
18331+
goto nla_put_failure;
18332+
18333+
while (link_mask) {
18334+
struct nlattr *link;
18335+
int link_id = __ffs(link_mask);
18336+
18337+
link = nla_nest_start(msg, link_id + 1);
18338+
if (!link)
18339+
goto nla_put_failure;
18340+
18341+
if (nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID, link_id))
18342+
goto nla_put_failure;
18343+
18344+
nla_nest_end(msg, link);
18345+
link_mask &= ~(1 << link_id);
18346+
}
18347+
18348+
nla_nest_end(msg, links);
18349+
18350+
genlmsg_end(msg, hdr);
18351+
18352+
genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
18353+
NL80211_MCGRP_MLME, GFP_KERNEL);
18354+
return;
18355+
18356+
nla_put_failure:
18357+
nlmsg_free(msg);
18358+
}
18359+
EXPORT_SYMBOL(cfg80211_links_removed);
18360+
1829118361
void nl80211_send_ibss_bssid(struct cfg80211_registered_device *rdev,
1829218362
struct net_device *netdev, const u8 *bssid,
1829318363
gfp_t gfp)

net/wireless/sme.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,21 @@ static void cfg80211_wdev_release_bsses(struct wireless_dev *wdev)
491491
}
492492
}
493493

494+
void cfg80211_wdev_release_link_bsses(struct wireless_dev *wdev, u16 link_mask)
495+
{
496+
unsigned int link;
497+
498+
for_each_valid_link(wdev, link) {
499+
if (!wdev->links[link].client.current_bss ||
500+
!(link_mask & BIT(link)))
501+
continue;
502+
cfg80211_unhold_bss(wdev->links[link].client.current_bss);
503+
cfg80211_put_bss(wdev->wiphy,
504+
&wdev->links[link].client.current_bss->pub);
505+
wdev->links[link].client.current_bss = NULL;
506+
}
507+
}
508+
494509
static int cfg80211_sme_get_conn_ies(struct wireless_dev *wdev,
495510
const u8 *ies, size_t ies_len,
496511
const u8 **out_ies, size_t *out_ies_len)

net/wireless/trace.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3966,6 +3966,21 @@ TRACE_EVENT(rdev_set_hw_timestamp,
39663966
__entry->enable)
39673967
);
39683968

3969+
TRACE_EVENT(cfg80211_links_removed,
3970+
TP_PROTO(struct net_device *netdev, u16 link_mask),
3971+
TP_ARGS(netdev, link_mask),
3972+
TP_STRUCT__entry(
3973+
NETDEV_ENTRY
3974+
__field(u16, link_mask)
3975+
),
3976+
TP_fast_assign(
3977+
NETDEV_ASSIGN;
3978+
__entry->link_mask = link_mask;
3979+
),
3980+
TP_printk(NETDEV_PR_FMT ", link_mask:%u", NETDEV_PR_ARG,
3981+
__entry->link_mask)
3982+
);
3983+
39693984
#endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */
39703985

39713986
#undef TRACE_INCLUDE_PATH

0 commit comments

Comments
 (0)