2023-06-18 18:51:35

by Greenman, Gregory

[permalink] [raw]
Subject: [PATCH 01/20] wifi: cfg80211: Support changes in AP MLD link state change

From: Ilan Peer <[email protected]>

Add support for the low level driver to indicate about the
removal of connection links that were removed by the AP MLD.

Propagate this information to user space so it could act
accordingly.

Signed-off-by: Ilan Peer <[email protected]>
Signed-off-by: Gregory Greenman <[email protected]>
---
include/net/cfg80211.h | 14 ++++++++++++
include/uapi/linux/nl80211.h | 3 +++
net/wireless/nl80211.c | 43 ++++++++++++++++++++++++++++++++++++
net/wireless/trace.h | 16 ++++++++++++++
4 files changed, 76 insertions(+)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 9972de114d73..9eba57d35e98 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -8359,6 +8359,20 @@ void cfg80211_cqm_txe_notify(struct net_device *dev, const u8 *peer,
*/
void cfg80211_cqm_beacon_loss_notify(struct net_device *dev, gfp_t gfp);

+/**
+ * cfg80211_cqm_links_state_change_notify - inform CQM of change in AP MLD
+ * links
+ *
+ * @dev: network device
+ * @removed_links: bitmap of links on which connection was removed due to links
+ * being removed by the AP MLD.
+ *
+ * Caller must acquire wdev_lock, therefore must only be called from sleepable
+ * driver context!
+ */
+void cfg80211_cqm_links_state_change_notify(struct net_device *dev,
+ u16 removed_links);
+
/**
* __cfg80211_radar_event - radar detection event
* @wiphy: the wiphy
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 03939bdb0e48..fece687054ef 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -5350,6 +5350,8 @@ enum nl80211_ps_state {
* loss event
* @NL80211_ATTR_CQM_RSSI_LEVEL: the RSSI value in dBm that triggered the
* RSSI threshold event.
+ * @NL80211_ATTR_CQM_REMOVED_LINKS: bitmap of links on which connection was
+ * removed due to links being removed by the AP MLD.
* @__NL80211_ATTR_CQM_AFTER_LAST: internal
* @NL80211_ATTR_CQM_MAX: highest key attribute
*/
@@ -5364,6 +5366,7 @@ enum nl80211_attr_cqm {
NL80211_ATTR_CQM_TXE_INTVL,
NL80211_ATTR_CQM_BEACON_LOSS_EVENT,
NL80211_ATTR_CQM_RSSI_LEVEL,
+ NL80211_ATTR_CQM_REMOVED_LINKS,

/* keep last */
__NL80211_ATTR_CQM_AFTER_LAST,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 7b547aeb52f1..a85256a3e063 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -19108,6 +19108,49 @@ void cfg80211_cqm_beacon_loss_notify(struct net_device *dev, gfp_t gfp)
}
EXPORT_SYMBOL(cfg80211_cqm_beacon_loss_notify);

+void cfg80211_cqm_links_state_change_notify(struct net_device *dev,
+ u16 removed_links)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct sk_buff *msg;
+ unsigned long removed = removed_links;
+ u8 link_id;
+
+ ASSERT_WDEV_LOCK(wdev);
+
+ trace_cfg80211_cqm_links_state_change_notify(dev, removed_links);
+
+ if (!removed_links)
+ return;
+
+ WARN_ON((wdev->valid_links & removed_links) != removed_links);
+ wdev->valid_links &= ~removed_links;
+
+ for_each_set_bit(link_id, &removed, IEEE80211_MLD_MAX_NUM_LINKS) {
+ if (!wdev->links[link_id].client.current_bss)
+ continue;
+
+ cfg80211_unhold_bss(wdev->links[link_id].client.current_bss);
+ cfg80211_put_bss(wdev->wiphy,
+ &wdev->links[link_id].client.current_bss->pub);
+ wdev->links[link_id].client.current_bss = NULL;
+ }
+
+ msg = cfg80211_prepare_cqm(dev, NULL, GFP_KERNEL);
+ if (!msg)
+ return;
+
+ if (nla_put_u16(msg, NL80211_ATTR_CQM_REMOVED_LINKS, removed_links))
+ goto nla_put_failure;
+
+ cfg80211_send_cqm(msg, GFP_KERNEL);
+ return;
+
+ nla_put_failure:
+ nlmsg_free(msg);
+}
+EXPORT_SYMBOL(cfg80211_cqm_links_state_change_notify);
+
static void nl80211_gtk_rekey_notify(struct cfg80211_registered_device *rdev,
struct net_device *netdev, const u8 *bssid,
const u8 *replay_ctr, gfp_t gfp)
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index e63990b81249..facea3aba60f 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -3966,6 +3966,22 @@ TRACE_EVENT(rdev_set_hw_timestamp,
__entry->enable)
);

+TRACE_EVENT(cfg80211_cqm_links_state_change_notify,
+ TP_PROTO(struct net_device *netdev,
+ u16 removed_links),
+ TP_ARGS(netdev, removed_links),
+ TP_STRUCT__entry(
+ NETDEV_ENTRY
+ __field(u16, removed_links)
+ ),
+ TP_fast_assign(
+ NETDEV_ASSIGN;
+ __entry->removed_links = removed_links;
+ ),
+ TP_printk(NETDEV_PR_FMT ", removed_links=0x%x",
+ NETDEV_PR_ARG, __entry->removed_links)
+);
+
#endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */

#undef TRACE_INCLUDE_PATH
--
2.38.1