linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/28] wifi: further MLO work
@ 2022-10-05 13:00 Johannes Berg
  2022-10-05 13:00 ` [PATCH 01/28] wifi: mac80211: add pointer from link STA to STA Johannes Berg
                   ` (27 more replies)
  0 siblings, 28 replies; 34+ messages in thread
From: Johannes Berg @ 2022-10-05 13:00 UTC (permalink / raw)
  To: linux-wireless

Hi,

Sorry for the long wait. Here (and in the wireless-next tree's
mld branch) is the next set of patches. I've thrown in some
additional patches from our tree just in case something here
has a dependency on it.

This includes (stack) fixes from the interop testing, but more
work will be needed towards the next one.

johannes



^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH 01/28] wifi: mac80211: add pointer from link STA to STA
  2022-10-05 13:00 [PATCH 00/28] wifi: further MLO work Johannes Berg
@ 2022-10-05 13:00 ` Johannes Berg
  2022-10-05 13:00 ` [PATCH 02/28] wifi: mac80211: add API to show the link STAs in debugfs Johannes Berg
                   ` (26 subsequent siblings)
  27 siblings, 0 replies; 34+ messages in thread
From: Johannes Berg @ 2022-10-05 13:00 UTC (permalink / raw)
  To: linux-wireless; +Cc: Benjamin Berg

From: Benjamin Berg <benjamin.berg@intel.com>

While often not needed, this considerably simplifies going from a link
to the STA. This helps in cases such as debugfs where a single pointer
should allow accessing a specific link and the STA.

Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 include/net/mac80211.h  | 3 +++
 net/mac80211/sta_info.c | 1 +
 2 files changed, 4 insertions(+)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index ac2bad57933f..7778a92d9582 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -2176,6 +2176,7 @@ struct ieee80211_sta_aggregates {
  * All link specific info for a STA link for a non MLD STA(single)
  * or a MLD STA(multiple entries) are stored here.
  *
+ * @sta: reference to owning STA
  * @addr: MAC address of the Link STA. For non-MLO STA this is same as the addr
  *	in ieee80211_sta. For MLO Link STA this addr can be same or different
  *	from addr in ieee80211_sta (representing MLD STA addr)
@@ -2196,6 +2197,8 @@ struct ieee80211_sta_aggregates {
  *
  */
 struct ieee80211_link_sta {
+	struct ieee80211_sta *sta;
+
 	u8 addr[ETH_ALEN];
 	u8 link_id;
 	enum ieee80211_smps_mode smps_mode;
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index cebfd148bb40..71b1488bd390 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -511,6 +511,7 @@ static void sta_info_add_link(struct sta_info *sta,
 	link_info->sta = sta;
 	link_info->link_id = link_id;
 	link_info->pub = link_sta;
+	link_info->pub->sta = &sta->sta;
 	link_sta->link_id = link_id;
 	rcu_assign_pointer(sta->link[link_id], link_info);
 	rcu_assign_pointer(sta->sta.link[link_id], link_sta);
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 02/28] wifi: mac80211: add API to show the link STAs in debugfs
  2022-10-05 13:00 [PATCH 00/28] wifi: further MLO work Johannes Berg
  2022-10-05 13:00 ` [PATCH 01/28] wifi: mac80211: add pointer from link STA to STA Johannes Berg
@ 2022-10-05 13:00 ` Johannes Berg
  2022-10-05 13:00 ` [PATCH 03/28] wifi: mac80211: include link address " Johannes Berg
                   ` (25 subsequent siblings)
  27 siblings, 0 replies; 34+ messages in thread
From: Johannes Berg @ 2022-10-05 13:00 UTC (permalink / raw)
  To: linux-wireless; +Cc: Benjamin Berg

From: Benjamin Berg <benjamin.berg@intel.com>

Create debugfs data per-link. For drivers, there is a new operation
link_sta_add_debugfs which will always be called.

For non-MLO, the station directory will be used directly rather than
creating a corresponding subdirectory. As such, non-MLO drivers can
simply continue to create the data from sta_debugfs_add.

Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 include/net/mac80211.h     |  11 ++++
 net/mac80211/debugfs_sta.c | 127 ++++++++++++++++++++++++++++++-------
 net/mac80211/debugfs_sta.h |   9 +++
 net/mac80211/driver-ops.c  |  27 +++++++-
 net/mac80211/driver-ops.h  |  16 +++++
 net/mac80211/sta_info.c    |  25 ++++++++
 net/mac80211/sta_info.h    |   5 ++
 7 files changed, 197 insertions(+), 23 deletions(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 7778a92d9582..c413050ec8dd 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -3790,6 +3790,13 @@ struct ieee80211_prep_tx_info {
  *	should be within a CONFIG_MAC80211_DEBUGFS conditional. This
  *	callback can sleep.
  *
+ * @link_sta_add_debugfs: Drivers can use this callback to add debugfs files
+ *	when a link is added to a mac80211 station. This callback
+ *	should be within a CPTCFG_MAC80211_DEBUGFS conditional. This
+ *	callback can sleep.
+ *	For non-MLO the callback will be called once for the deflink with the
+ *	station's directory rather than a separate subdirectory.
+ *
  * @sta_notify: Notifies low level driver about power state transition of an
  *	associated station, AP,  IBSS/WDS/mesh peer etc. For a VIF operating
  *	in AP mode, this callback will not be called when the flag
@@ -4260,6 +4267,10 @@ struct ieee80211_ops {
 				struct ieee80211_vif *vif,
 				struct ieee80211_sta *sta,
 				struct dentry *dir);
+	void (*link_sta_add_debugfs)(struct ieee80211_hw *hw,
+				     struct ieee80211_vif *vif,
+				     struct ieee80211_link_sta *link_sta,
+				     struct dentry *dir);
 #endif
 	void (*sta_notify)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 			enum sta_notify_cmd, struct ieee80211_sta *sta);
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c
index d3397c1248d3..68c07d4b95a5 100644
--- a/net/mac80211/debugfs_sta.c
+++ b/net/mac80211/debugfs_sta.c
@@ -5,7 +5,7 @@
  * Copyright 2007	Johannes Berg <johannes@sipsolutions.net>
  * Copyright 2013-2014  Intel Mobile Communications GmbH
  * Copyright(c) 2016 Intel Deutschland GmbH
- * Copyright (C) 2018 - 2021 Intel Corporation
+ * Copyright (C) 2018 - 2022 Intel Corporation
  */
 
 #include <linux/debugfs.h>
@@ -435,8 +435,16 @@ static ssize_t sta_agg_status_write(struct file *file, const char __user *userbu
 }
 STA_OPS_RW(agg_status);
 
-static ssize_t sta_ht_capa_read(struct file *file, char __user *userbuf,
-				size_t count, loff_t *ppos)
+/* link sta attributes */
+#define LINK_STA_OPS(name)						\
+static const struct file_operations link_sta_ ##name## _ops = {		\
+	.read = link_sta_##name##_read,					\
+	.open = simple_open,						\
+	.llseek = generic_file_llseek,					\
+}
+
+static ssize_t link_sta_ht_capa_read(struct file *file, char __user *userbuf,
+				     size_t count, loff_t *ppos)
 {
 #define PRINT_HT_CAP(_cond, _str) \
 	do { \
@@ -446,8 +454,8 @@ static ssize_t sta_ht_capa_read(struct file *file, char __user *userbuf,
 	char *buf, *p;
 	int i;
 	ssize_t bufsz = 512;
-	struct sta_info *sta = file->private_data;
-	struct ieee80211_sta_ht_cap *htc = &sta->sta.deflink.ht_cap;
+	struct link_sta_info *link_sta = file->private_data;
+	struct ieee80211_sta_ht_cap *htc = &link_sta->pub->ht_cap;
 	ssize_t ret;
 
 	buf = kzalloc(bufsz, GFP_KERNEL);
@@ -524,14 +532,14 @@ static ssize_t sta_ht_capa_read(struct file *file, char __user *userbuf,
 	kfree(buf);
 	return ret;
 }
-STA_OPS(ht_capa);
+LINK_STA_OPS(ht_capa);
 
-static ssize_t sta_vht_capa_read(struct file *file, char __user *userbuf,
-				 size_t count, loff_t *ppos)
+static ssize_t link_sta_vht_capa_read(struct file *file, char __user *userbuf,
+				      size_t count, loff_t *ppos)
 {
 	char *buf, *p;
-	struct sta_info *sta = file->private_data;
-	struct ieee80211_sta_vht_cap *vhtc = &sta->sta.deflink.vht_cap;
+	struct link_sta_info *link_sta = file->private_data;
+	struct ieee80211_sta_vht_cap *vhtc = &link_sta->pub->vht_cap;
 	ssize_t ret;
 	ssize_t bufsz = 512;
 
@@ -638,15 +646,15 @@ static ssize_t sta_vht_capa_read(struct file *file, char __user *userbuf,
 	kfree(buf);
 	return ret;
 }
-STA_OPS(vht_capa);
+LINK_STA_OPS(vht_capa);
 
-static ssize_t sta_he_capa_read(struct file *file, char __user *userbuf,
-				size_t count, loff_t *ppos)
+static ssize_t link_sta_he_capa_read(struct file *file, char __user *userbuf,
+				     size_t count, loff_t *ppos)
 {
 	char *buf, *p;
 	size_t buf_sz = PAGE_SIZE;
-	struct sta_info *sta = file->private_data;
-	struct ieee80211_sta_he_cap *hec = &sta->sta.deflink.he_cap;
+	struct link_sta_info *link_sta = file->private_data;
+	struct ieee80211_sta_he_cap *hec = &link_sta->pub->he_cap;
 	struct ieee80211_he_mcs_nss_supp *nss = &hec->he_mcs_nss_supp;
 	u8 ppe_size;
 	u8 *cap;
@@ -1011,7 +1019,7 @@ static ssize_t sta_he_capa_read(struct file *file, char __user *userbuf,
 	kfree(buf);
 	return ret;
 }
-STA_OPS(he_capa);
+LINK_STA_OPS(he_capa);
 
 #define DEBUGFS_ADD(name) \
 	debugfs_create_file(#name, 0400, \
@@ -1048,12 +1056,7 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta)
 	DEBUGFS_ADD(num_ps_buf_frames);
 	DEBUGFS_ADD(last_seq_ctrl);
 	DEBUGFS_ADD(agg_status);
-	DEBUGFS_ADD(ht_capa);
-	DEBUGFS_ADD(vht_capa);
-	DEBUGFS_ADD(he_capa);
-
-	DEBUGFS_ADD_COUNTER(rx_duplicates, deflink.rx_stats.num_duplicates);
-	DEBUGFS_ADD_COUNTER(rx_fragments, deflink.rx_stats.fragments);
+	/* FIXME: Kept here as the statistics are only done on the deflink */
 	DEBUGFS_ADD_COUNTER(tx_filtered, deflink.status_stats.filtered);
 
 	if (local->ops->wake_tx_queue) {
@@ -1076,3 +1079,83 @@ void ieee80211_sta_debugfs_remove(struct sta_info *sta)
 	debugfs_remove_recursive(sta->debugfs_dir);
 	sta->debugfs_dir = NULL;
 }
+
+#undef DEBUGFS_ADD
+#undef DEBUGFS_ADD_COUNTER
+
+#define DEBUGFS_ADD(name) \
+	debugfs_create_file(#name, 0400, \
+		link_sta->debugfs_dir, link_sta, &link_sta_ ##name## _ops)
+#define DEBUGFS_ADD_COUNTER(name, field)				\
+	debugfs_create_ulong(#name, 0400, link_sta->debugfs_dir, &link_sta->field)
+
+void ieee80211_link_sta_debugfs_add(struct link_sta_info *link_sta)
+{
+	if (WARN_ON(!link_sta->sta->debugfs_dir))
+		return;
+
+	/* For non-MLO, leave the files in the main directory. */
+	if (link_sta->sta->sta.valid_links) {
+		char link_dir_name[10];
+
+		snprintf(link_dir_name, sizeof(link_dir_name),
+			 "link-%d", link_sta->link_id);
+
+		link_sta->debugfs_dir =
+			debugfs_create_dir(link_dir_name,
+					   link_sta->sta->debugfs_dir);
+	} else {
+		if (WARN_ON(link_sta != &link_sta->sta->deflink))
+			return;
+
+		link_sta->debugfs_dir = link_sta->sta->debugfs_dir;
+	}
+
+	DEBUGFS_ADD(ht_capa);
+	DEBUGFS_ADD(vht_capa);
+	DEBUGFS_ADD(he_capa);
+
+	DEBUGFS_ADD_COUNTER(rx_duplicates, rx_stats.num_duplicates);
+	DEBUGFS_ADD_COUNTER(rx_fragments, rx_stats.fragments);
+}
+
+void ieee80211_link_sta_debugfs_remove(struct link_sta_info *link_sta)
+{
+	if (!link_sta->debugfs_dir || !link_sta->sta->debugfs_dir) {
+		link_sta->debugfs_dir = NULL;
+		return;
+	}
+
+	if (link_sta->debugfs_dir == link_sta->sta->debugfs_dir) {
+		WARN_ON(link_sta != &link_sta->sta->deflink);
+		link_sta->sta->debugfs_dir = NULL;
+		return;
+	}
+
+	debugfs_remove_recursive(link_sta->debugfs_dir);
+	link_sta->debugfs_dir = NULL;
+}
+
+void ieee80211_link_sta_debugfs_drv_add(struct link_sta_info *link_sta)
+{
+	if (WARN_ON(!link_sta->debugfs_dir))
+		return;
+
+	drv_link_sta_add_debugfs(link_sta->sta->local, link_sta->sta->sdata,
+				 link_sta->pub, link_sta->debugfs_dir);
+}
+
+void ieee80211_link_sta_debugfs_drv_remove(struct link_sta_info *link_sta)
+{
+	if (!link_sta->debugfs_dir)
+		return;
+
+	if (WARN_ON(link_sta->debugfs_dir == link_sta->sta->debugfs_dir))
+		return;
+
+	/* Recreate the directory excluding the driver data */
+	debugfs_remove_recursive(link_sta->debugfs_dir);
+	link_sta->debugfs_dir = NULL;
+
+	ieee80211_link_sta_debugfs_add(link_sta);
+}
diff --git a/net/mac80211/debugfs_sta.h b/net/mac80211/debugfs_sta.h
index d2e7c27ad6d1..fcc0939685c5 100644
--- a/net/mac80211/debugfs_sta.h
+++ b/net/mac80211/debugfs_sta.h
@@ -7,9 +7,18 @@
 #ifdef CONFIG_MAC80211_DEBUGFS
 void ieee80211_sta_debugfs_add(struct sta_info *sta);
 void ieee80211_sta_debugfs_remove(struct sta_info *sta);
+
+void ieee80211_link_sta_debugfs_add(struct link_sta_info *link_sta);
+void ieee80211_link_sta_debugfs_remove(struct link_sta_info *link_sta);
+
+void ieee80211_link_sta_debugfs_drv_add(struct link_sta_info *link_sta);
+void ieee80211_link_sta_debugfs_drv_remove(struct link_sta_info *link_sta);
 #else
 static inline void ieee80211_sta_debugfs_add(struct sta_info *sta) {}
 static inline void ieee80211_sta_debugfs_remove(struct sta_info *sta) {}
+
+static inline void ieee80211_link_sta_debugfs_drv_add(struct link_sta_info *link_sta) {}
+static inline void ieee80211_link_sta_debugfs_drv_remove(struct link_sta_info *link_sta) {}
 #endif
 
 #endif /* __MAC80211_DEBUGFS_STA_H */
diff --git a/net/mac80211/driver-ops.c b/net/mac80211/driver-ops.c
index 5392ffa18270..d737db4e07e2 100644
--- a/net/mac80211/driver-ops.c
+++ b/net/mac80211/driver-ops.c
@@ -7,6 +7,7 @@
 #include "ieee80211_i.h"
 #include "trace.h"
 #include "driver-ops.h"
+#include "debugfs_sta.h"
 
 int drv_start(struct ieee80211_local *local)
 {
@@ -497,6 +498,11 @@ int drv_change_sta_links(struct ieee80211_local *local,
 			 struct ieee80211_sta *sta,
 			 u16 old_links, u16 new_links)
 {
+	struct sta_info *info = container_of(sta, struct sta_info, sta);
+	struct link_sta_info *link_sta;
+	unsigned long links_to_add;
+	unsigned long links_to_rem;
+	unsigned int link_id;
 	int ret = -EOPNOTSUPP;
 
 	might_sleep();
@@ -510,11 +516,30 @@ int drv_change_sta_links(struct ieee80211_local *local,
 	if (old_links == new_links)
 		return 0;
 
+	links_to_add = ~old_links & new_links;
+	links_to_rem = old_links & ~new_links;
+
+	for_each_set_bit(link_id, &links_to_rem, IEEE80211_MLD_MAX_NUM_LINKS) {
+		link_sta = rcu_dereference_protected(info->link[link_id],
+						     lockdep_is_held(&local->sta_mtx));
+
+		ieee80211_link_sta_debugfs_drv_remove(link_sta);
+	}
+
 	trace_drv_change_sta_links(local, sdata, sta, old_links, new_links);
 	if (local->ops->change_sta_links)
 		ret = local->ops->change_sta_links(&local->hw, &sdata->vif, sta,
 						   old_links, new_links);
 	trace_drv_return_int(local, ret);
 
-	return ret;
+	if (ret)
+		return ret;
+
+	for_each_set_bit(link_id, &links_to_add, IEEE80211_MLD_MAX_NUM_LINKS) {
+		link_sta = rcu_dereference_protected(info->link[link_id],
+						     lockdep_is_held(&local->sta_mtx));
+		ieee80211_link_sta_debugfs_drv_add(link_sta);
+	}
+
+	return 0;
 }
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index 81e40b0a3b16..809bad53e15b 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -480,6 +480,22 @@ static inline void drv_sta_add_debugfs(struct ieee80211_local *local,
 		local->ops->sta_add_debugfs(&local->hw, &sdata->vif,
 					    sta, dir);
 }
+
+static inline void drv_link_sta_add_debugfs(struct ieee80211_local *local,
+					    struct ieee80211_sub_if_data *sdata,
+					    struct ieee80211_link_sta *link_sta,
+					    struct dentry *dir)
+{
+	might_sleep();
+
+	sdata = get_bss_sdata(sdata);
+	if (!check_sdata_in_driver(sdata))
+		return;
+
+	if (local->ops->link_sta_add_debugfs)
+		local->ops->link_sta_add_debugfs(&local->hw, &sdata->vif,
+						 link_sta, dir);
+}
 #endif
 
 static inline void drv_sta_pre_rcu_remove(struct ieee80211_local *local,
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 71b1488bd390..e6beaea4075e 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -366,6 +366,9 @@ static void sta_remove_link(struct sta_info *sta, unsigned int link_id,
 	if (unhash)
 		link_sta_info_hash_del(sta->local, link_sta);
 
+	if (test_sta_flag(sta, WLAN_STA_INSERTED))
+		ieee80211_link_sta_debugfs_remove(link_sta);
+
 	if (link_sta != &sta->deflink)
 		alloc = container_of(link_sta, typeof(*alloc), info);
 
@@ -875,6 +878,26 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU)
 
 	ieee80211_sta_debugfs_add(sta);
 	rate_control_add_sta_debugfs(sta);
+	if (sta->sta.valid_links) {
+		int i;
+
+		for (i = 0; i < ARRAY_SIZE(sta->link); i++) {
+			struct link_sta_info *link_sta;
+
+			link_sta = rcu_dereference_protected(sta->link[i],
+							     lockdep_is_held(&local->sta_mtx));
+
+			if (!link_sta)
+				continue;
+
+			ieee80211_link_sta_debugfs_add(link_sta);
+			if (sdata->vif.active_links & BIT(i))
+				ieee80211_link_sta_debugfs_drv_add(link_sta);
+		}
+	} else {
+		ieee80211_link_sta_debugfs_add(&sta->deflink);
+		ieee80211_link_sta_debugfs_drv_add(&sta->deflink);
+	}
 
 	sinfo->generation = local->sta_generation;
 	cfg80211_new_sta(sdata->dev, sta->sta.addr, sinfo, GFP_KERNEL);
@@ -2824,6 +2847,8 @@ int ieee80211_sta_allocate_link(struct sta_info *sta, unsigned int link_id)
 
 	sta_info_add_link(sta, link_id, &alloc->info, &alloc->sta);
 
+	ieee80211_link_sta_debugfs_add(&alloc->info);
+
 	return 0;
 }
 
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 2517ea714dc4..6e672bf9c79d 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -513,6 +513,7 @@ struct ieee80211_fragment_cache {
  * @status_stats.avg_ack_signal: average ACK signal
  * @cur_max_bandwidth: maximum bandwidth to use for TX to the station,
  *	taken from HT/VHT capabilities or VHT operating mode notification
+ * @debugfs_dir: debug filesystem directory dentry
  * @pub: public (driver visible) link STA data
  * TODO Move other link params from sta_info as required for MLD operation
  */
@@ -560,6 +561,10 @@ struct link_sta_info {
 
 	enum ieee80211_sta_rx_bandwidth cur_max_bandwidth;
 
+#ifdef CONFIG_MAC80211_DEBUGFS
+	struct dentry *debugfs_dir;
+#endif
+
 	struct ieee80211_link_sta *pub;
 };
 
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 03/28] wifi: mac80211: include link address in debugfs
  2022-10-05 13:00 [PATCH 00/28] wifi: further MLO work Johannes Berg
  2022-10-05 13:00 ` [PATCH 01/28] wifi: mac80211: add pointer from link STA to STA Johannes Berg
  2022-10-05 13:00 ` [PATCH 02/28] wifi: mac80211: add API to show the link STAs in debugfs Johannes Berg
@ 2022-10-05 13:00 ` Johannes Berg
  2022-10-05 13:00 ` [PATCH 04/28] wifi: mac80211: recalc station aggregate data during link switch Johannes Berg
                   ` (24 subsequent siblings)
  27 siblings, 0 replies; 34+ messages in thread
From: Johannes Berg @ 2022-10-05 13:00 UTC (permalink / raw)
  To: linux-wireless; +Cc: Benjamin Berg

From: Benjamin Berg <benjamin.berg@intel.com>

Add the link address to the per-link information, but only if we are
using MLO.

Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/debugfs_sta.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c
index 68c07d4b95a5..0d8ff0303028 100644
--- a/net/mac80211/debugfs_sta.c
+++ b/net/mac80211/debugfs_sta.c
@@ -443,6 +443,19 @@ static const struct file_operations link_sta_ ##name## _ops = {		\
 	.llseek = generic_file_llseek,					\
 }
 
+static ssize_t link_sta_addr_read(struct file *file, char __user *userbuf,
+				  size_t count, loff_t *ppos)
+{
+	struct link_sta_info *link_sta = file->private_data;
+	u8 mac[3 * ETH_ALEN + 1];
+
+	snprintf(mac, sizeof(mac), "%pM\n", link_sta->pub->addr);
+
+	return simple_read_from_buffer(userbuf, count, ppos, mac, 3 * ETH_ALEN);
+}
+
+LINK_STA_OPS(addr);
+
 static ssize_t link_sta_ht_capa_read(struct file *file, char __user *userbuf,
 				     size_t count, loff_t *ppos)
 {
@@ -1104,6 +1117,8 @@ void ieee80211_link_sta_debugfs_add(struct link_sta_info *link_sta)
 		link_sta->debugfs_dir =
 			debugfs_create_dir(link_dir_name,
 					   link_sta->sta->debugfs_dir);
+
+		DEBUGFS_ADD(addr);
 	} else {
 		if (WARN_ON(link_sta != &link_sta->sta->deflink))
 			return;
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 04/28] wifi: mac80211: recalc station aggregate data during link switch
  2022-10-05 13:00 [PATCH 00/28] wifi: further MLO work Johannes Berg
                   ` (2 preceding siblings ...)
  2022-10-05 13:00 ` [PATCH 03/28] wifi: mac80211: include link address " Johannes Berg
@ 2022-10-05 13:00 ` Johannes Berg
  2022-10-05 13:00 ` [PATCH 05/28] wifi: cfg80211: support reporting failed links Johannes Berg
                   ` (23 subsequent siblings)
  27 siblings, 0 replies; 34+ messages in thread
From: Johannes Berg @ 2022-10-05 13:00 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

During link switching, the active links change, so we need to
recalculate the aggregate data in the stations.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/link.c     | 17 +++++++++++++++++
 net/mac80211/sta_info.c | 33 ++++++++++++++++++++++++---------
 net/mac80211/sta_info.h |  2 ++
 3 files changed, 43 insertions(+), 9 deletions(-)

diff --git a/net/mac80211/link.c b/net/mac80211/link.c
index e309708abae8..d1f5a9f7c647 100644
--- a/net/mac80211/link.c
+++ b/net/mac80211/link.c
@@ -357,6 +357,11 @@ static int _ieee80211_set_active_links(struct ieee80211_sub_if_data *sdata,
 	list_for_each_entry(sta, &local->sta_list, list) {
 		if (sdata != sta->sdata)
 			continue;
+
+		/* this is very temporary, but do it anyway */
+		__ieee80211_sta_recalc_aggregates(sta,
+						  old_active | active_links);
+
 		ret = drv_change_sta_links(local, sdata, &sta->sta,
 					   old_active,
 					   old_active | active_links);
@@ -369,10 +374,22 @@ static int _ieee80211_set_active_links(struct ieee80211_sub_if_data *sdata,
 	list_for_each_entry(sta, &local->sta_list, list) {
 		if (sdata != sta->sdata)
 			continue;
+
+		__ieee80211_sta_recalc_aggregates(sta, active_links);
+
 		ret = drv_change_sta_links(local, sdata, &sta->sta,
 					   old_active | active_links,
 					   active_links);
 		WARN_ON_ONCE(ret);
+
+		/*
+		 * Do it again, just in case - the driver might very
+		 * well have called ieee80211_sta_recalc_aggregates()
+		 * from there when filling in the new links, which
+		 * would set it wrong since the vif's active links are
+		 * not switched yet...
+		 */
+		__ieee80211_sta_recalc_aggregates(sta, active_links);
 	}
 
 	for_each_set_bit(link_id, &add, IEEE80211_MLD_MAX_NUM_LINKS) {
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index e6beaea4075e..2bb6a71c72ef 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -2151,22 +2151,30 @@ void ieee80211_sta_register_airtime(struct ieee80211_sta *pubsta, u8 tid,
 }
 EXPORT_SYMBOL(ieee80211_sta_register_airtime);
 
-void ieee80211_sta_recalc_aggregates(struct ieee80211_sta *pubsta)
+void __ieee80211_sta_recalc_aggregates(struct sta_info *sta, u16 active_links)
 {
-	struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
-	struct ieee80211_link_sta *link_sta;
-	int link_id, i;
 	bool first = true;
+	int link_id;
 
-	if (!pubsta->valid_links || !pubsta->mlo) {
-		pubsta->cur = &pubsta->deflink.agg;
+	if (!sta->sta.valid_links || !sta->sta.mlo) {
+		sta->sta.cur = &sta->sta.deflink.agg;
 		return;
 	}
 
 	rcu_read_lock();
-	for_each_sta_active_link(&sta->sdata->vif, pubsta, link_sta, link_id) {
+	for (link_id = 0; link_id < ARRAY_SIZE((sta)->link); link_id++) {
+		struct ieee80211_link_sta *link_sta;
+		int i;
+
+		if (!(active_links & BIT(link_id)))
+			continue;
+
+		link_sta = rcu_dereference(sta->sta.link[link_id]);
+		if (!link_sta)
+			continue;
+
 		if (first) {
-			sta->cur = pubsta->deflink.agg;
+			sta->cur = sta->sta.deflink.agg;
 			first = false;
 			continue;
 		}
@@ -2185,7 +2193,14 @@ void ieee80211_sta_recalc_aggregates(struct ieee80211_sta *pubsta)
 	}
 	rcu_read_unlock();
 
-	pubsta->cur = &sta->cur;
+	sta->sta.cur = &sta->cur;
+}
+
+void ieee80211_sta_recalc_aggregates(struct ieee80211_sta *pubsta)
+{
+	struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
+
+	__ieee80211_sta_recalc_aggregates(sta, sta->sdata->vif.active_links);
 }
 EXPORT_SYMBOL(ieee80211_sta_recalc_aggregates);
 
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 6e672bf9c79d..69820b551668 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -927,6 +927,8 @@ void ieee80211_sta_set_max_amsdu_subframes(struct sta_info *sta,
 					   const u8 *ext_capab,
 					   unsigned int ext_capab_len);
 
+void __ieee80211_sta_recalc_aggregates(struct sta_info *sta, u16 active_links);
+
 enum sta_stats_type {
 	STA_STATS_RATE_TYPE_INVALID = 0,
 	STA_STATS_RATE_TYPE_LEGACY,
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 05/28] wifi: cfg80211: support reporting failed links
  2022-10-05 13:00 [PATCH 00/28] wifi: further MLO work Johannes Berg
                   ` (3 preceding siblings ...)
  2022-10-05 13:00 ` [PATCH 04/28] wifi: mac80211: recalc station aggregate data during link switch Johannes Berg
@ 2022-10-05 13:00 ` Johannes Berg
  2022-10-06 10:49   ` Veerendranath Jakkam
  2022-10-05 13:00 ` [PATCH 06/28] wifi: ieee80211: Support validating ML station profile length Johannes Berg
                   ` (22 subsequent siblings)
  27 siblings, 1 reply; 34+ messages in thread
From: Johannes Berg @ 2022-10-05 13:00 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

For assoc and connect result APIs, support reporting
failed links; they should still come with the BSS
pointer in the case of assoc, so they're released
correctly. In the case of connect result, this is
optional.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 include/net/cfg80211.h |  7 +++++++
 net/wireless/mlme.c    |  4 ++++
 net/wireless/nl80211.c |  5 ++++-
 net/wireless/sme.c     | 14 ++++++++++++++
 4 files changed, 29 insertions(+), 1 deletion(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index e09ff87146c1..4d35a4234417 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -6933,6 +6933,8 @@ void cfg80211_auth_timeout(struct net_device *dev, const u8 *addr);
  * @ap_mld_addr: AP MLD address (in case of MLO)
  * @links: per-link information indexed by link ID, use links[0] for
  *	non-MLO connections
+ * @links.status: Set this (along with a BSS pointer) for links that
+ *	were rejected by the AP.
  */
 struct cfg80211_rx_assoc_resp {
 	const u8 *buf;
@@ -6944,6 +6946,7 @@ struct cfg80211_rx_assoc_resp {
 	struct {
 		const u8 *addr;
 		struct cfg80211_bss *bss;
+		u16 status;
 	} links[IEEE80211_MLD_MAX_NUM_LINKS];
 };
 
@@ -7454,6 +7457,9 @@ struct cfg80211_fils_resp_params {
  *	if the bss is expired during the connection, esp. for those drivers
  *	implementing connect op. Only one parameter among @bssid and @bss needs
  *	to be specified.
+ * @links.status: per-link status code, to report a status code that's not
+ *	%WLAN_STATUS_SUCCESS for a given link, it must also be in the
+ *	@valid_links bitmap and may have a BSS pointer (which is then released)
  */
 struct cfg80211_connect_resp_params {
 	int status;
@@ -7470,6 +7476,7 @@ struct cfg80211_connect_resp_params {
 		const u8 *addr;
 		const u8 *bssid;
 		struct cfg80211_bss *bss;
+		u16 status;
 	} links[IEEE80211_MLD_MAX_NUM_LINKS];
 };
 
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index 581df7f4c524..58e1fb18f85a 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -42,6 +42,10 @@ void cfg80211_rx_assoc_resp(struct net_device *dev,
 	unsigned int link_id;
 
 	for (link_id = 0; link_id < ARRAY_SIZE(data->links); link_id++) {
+		cr.links[link_id].status = data->links[link_id].status;
+		WARN_ON_ONCE(cr.links[link_id].status != WLAN_STATUS_SUCCESS &&
+			     (!cr.ap_mld_addr || !cr.links[link_id].bss));
+
 		cr.links[link_id].bss = data->links[link_id].bss;
 		if (!cr.links[link_id].bss)
 			continue;
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 8ff8b1c040f0..ad7393cd3d18 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -17745,6 +17745,7 @@ void nl80211_send_connect_result(struct cfg80211_registered_device *rdev,
 			link_info_size += (cr->links[link].bssid ||
 					   cr->links[link].bss) ?
 					  nla_total_size(ETH_ALEN) : 0;
+			link_info_size += nla_total_size(sizeof(u16));
 		}
 	}
 
@@ -17813,7 +17814,9 @@ void nl80211_send_connect_result(struct cfg80211_registered_device *rdev,
 			     nla_put(msg, NL80211_ATTR_BSSID, ETH_ALEN, bssid)) ||
 			    (cr->links[link].addr &&
 			     nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN,
-				     cr->links[link].addr)))
+				     cr->links[link].addr)) ||
+			    nla_put_u16(msg, NL80211_ATTR_STATUS_CODE,
+					cr->links[link].status))
 				goto nla_put_failure;
 
 			nla_nest_end(msg, nested_mlo_links);
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index d513536617bd..f94497e9db43 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -793,6 +793,10 @@ void __cfg80211_connect_result(struct net_device *dev,
 		}
 
 		for_each_valid_link(cr, link) {
+			/* don't do extra lookups for failures */
+			if (cr->links[link].status != WLAN_STATUS_SUCCESS)
+				continue;
+
 			if (cr->links[link].bss)
 				continue;
 
@@ -829,6 +833,16 @@ void __cfg80211_connect_result(struct net_device *dev,
 	}
 
 	memset(wdev->links, 0, sizeof(wdev->links));
+	for_each_valid_link(cr, link) {
+		if (cr->links[link].status == WLAN_STATUS_SUCCESS)
+			continue;
+		cr->valid_links &= ~BIT(link);
+		/* don't require bss pointer for failed links */
+		if (!cr->links[link].bss)
+			continue;
+		cfg80211_unhold_bss(bss_from_pub(cr->links[link].bss));
+		cfg80211_put_bss(wdev->wiphy, cr->links[link].bss);
+	}
 	wdev->valid_links = cr->valid_links;
 	for_each_valid_link(cr, link)
 		wdev->links[link].client.current_bss =
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 06/28] wifi: ieee80211: Support validating ML station profile length
  2022-10-05 13:00 [PATCH 00/28] wifi: further MLO work Johannes Berg
                   ` (4 preceding siblings ...)
  2022-10-05 13:00 ` [PATCH 05/28] wifi: cfg80211: support reporting failed links Johannes Berg
@ 2022-10-05 13:00 ` Johannes Berg
  2022-10-05 13:00 ` [PATCH 07/28] wifi: cfg80211/mac80211: Fix ML element common size calculation Johannes Berg
                   ` (21 subsequent siblings)
  27 siblings, 0 replies; 34+ messages in thread
From: Johannes Berg @ 2022-10-05 13:00 UTC (permalink / raw)
  To: linux-wireless; +Cc: Ilan Peer

From: Ilan Peer <ilan.peer@intel.com>

Add a function to validate EHT Multi-Link per station profile length.

Signed-off-by: Ilan Peer <ilan.peer@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 include/linux/ieee80211.h | 40 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 40 insertions(+)

diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index 79690938d9a2..bdf668f9dace 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -4685,6 +4685,46 @@ struct ieee80211_mle_per_sta_profile {
 	u8 variable[];
 } __packed;
 
+/**
+ * ieee80211_mle_sta_prof_size_ok - validate multi-link element sta profile size
+ * @data: pointer to the sub element data
+ * @len: length of the containing sub element
+ */
+static inline bool ieee80211_mle_sta_prof_size_ok(const u8 *data, size_t len)
+{
+	const struct ieee80211_mle_per_sta_profile *prof = (const void *)data;
+	u16 control;
+	u8 fixed = sizeof(*prof);
+	u8 info_len = 1;
+
+	if (len < fixed)
+		return false;
+
+	control = le16_to_cpu(prof->control);
+
+	if (control & IEEE80211_MLE_STA_CONTROL_STA_MAC_ADDR_PRESENT)
+		info_len += 6;
+	if (control & IEEE80211_MLE_STA_CONTROL_BEACON_INT_PRESENT)
+		info_len += 2;
+	if (control & IEEE80211_MLE_STA_CONTROL_TSF_OFFS_PRESENT)
+		info_len += 8;
+	if (control & IEEE80211_MLE_STA_CONTROL_DTIM_INFO_PRESENT)
+		info_len += 2;
+	if (control & IEEE80211_MLE_STA_CONTROL_BSS_PARAM_CHANGE_CNT_PRESENT)
+		info_len += 1;
+
+	if (control & IEEE80211_MLE_STA_CONTROL_COMPLETE_PROFILE &&
+	    control & IEEE80211_MLE_STA_CONTROL_NSTR_BITMAP_SIZE) {
+		if (control & IEEE80211_MLE_STA_CONTROL_NSTR_BITMAP_SIZE)
+			info_len += 2;
+		else
+			info_len += 1;
+	}
+
+	return prof->sta_info_len >= info_len &&
+	       fixed + prof->sta_info_len <= len;
+}
+
 #define for_each_mle_subelement(_elem, _data, _len)			\
 	if (ieee80211_mle_size_ok(_data, _len))				\
 		for_each_element(_elem,					\
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 07/28] wifi: cfg80211/mac80211: Fix ML element common size calculation
  2022-10-05 13:00 [PATCH 00/28] wifi: further MLO work Johannes Berg
                   ` (5 preceding siblings ...)
  2022-10-05 13:00 ` [PATCH 06/28] wifi: ieee80211: Support validating ML station profile length Johannes Berg
@ 2022-10-05 13:00 ` Johannes Berg
  2022-10-05 13:00 ` [PATCH 08/28] wifi: cfg80211/mac80211: Fix ML element common size validation Johannes Berg
                   ` (20 subsequent siblings)
  27 siblings, 0 replies; 34+ messages in thread
From: Johannes Berg @ 2022-10-05 13:00 UTC (permalink / raw)
  To: linux-wireless; +Cc: Ilan Peer

From: Ilan Peer <ilan.peer@intel.com>

The common size is part of the length in the data
so don't add it again.

Signed-off-by: Ilan Peer <ilan.peer@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 include/linux/ieee80211.h | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index bdf668f9dace..442b13333da8 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -4573,18 +4573,17 @@ static inline u8 ieee80211_mle_common_size(const u8 *data)
 
 	switch (u16_get_bits(control, IEEE80211_ML_CONTROL_TYPE)) {
 	case IEEE80211_ML_CONTROL_TYPE_BASIC:
-		common += sizeof(struct ieee80211_mle_basic_common_info);
-		break;
 	case IEEE80211_ML_CONTROL_TYPE_PREQ:
-		common += sizeof(struct ieee80211_mle_preq_common_info);
+	case IEEE80211_ML_CONTROL_TYPE_TDLS:
+		/*
+		 * The length is the first octet pointed by mle->variable so no
+		 * need to add anything
+		 */
 		break;
 	case IEEE80211_ML_CONTROL_TYPE_RECONF:
 		if (control & IEEE80211_MLC_RECONF_PRES_MLD_MAC_ADDR)
 			common += ETH_ALEN;
 		return common;
-	case IEEE80211_ML_CONTROL_TYPE_TDLS:
-		common += sizeof(struct ieee80211_mle_tdls_common_info);
-		break;
 	case IEEE80211_ML_CONTROL_TYPE_PRIO_ACCESS:
 		if (control & IEEE80211_MLC_PRIO_ACCESS_PRES_AP_MLD_MAC_ADDR)
 			common += ETH_ALEN;
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 08/28] wifi: cfg80211/mac80211: Fix ML element common size validation
  2022-10-05 13:00 [PATCH 00/28] wifi: further MLO work Johannes Berg
                   ` (6 preceding siblings ...)
  2022-10-05 13:00 ` [PATCH 07/28] wifi: cfg80211/mac80211: Fix ML element common size calculation Johannes Berg
@ 2022-10-05 13:00 ` Johannes Berg
  2022-10-05 13:00 ` [PATCH 09/28] wifi: mac80211: Parse station profile from association response Johannes Berg
                   ` (19 subsequent siblings)
  27 siblings, 0 replies; 34+ messages in thread
From: Johannes Berg @ 2022-10-05 13:00 UTC (permalink / raw)
  To: linux-wireless; +Cc: Ilan Peer

From: Ilan Peer <ilan.peer@intel.com>

The Multi-Link element can be fragmented, thus its size can exceed 254.
Thus, modify ieee80211_mle_size_ok() to use 'size_t len' instead of
'u8 len'.

Signed-off-by: Ilan Peer <ilan.peer@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 include/linux/ieee80211.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index 442b13333da8..b935a85b2f44 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -4601,7 +4601,7 @@ static inline u8 ieee80211_mle_common_size(const u8 *data)
  * @data: pointer to the element data
  * @len: length of the containing element
  */
-static inline bool ieee80211_mle_size_ok(const u8 *data, u8 len)
+static inline bool ieee80211_mle_size_ok(const u8 *data, size_t len)
 {
 	const struct ieee80211_multi_link_elem *mle = (const void *)data;
 	u8 fixed = sizeof(*mle);
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 09/28] wifi: mac80211: Parse station profile from association response
  2022-10-05 13:00 [PATCH 00/28] wifi: further MLO work Johannes Berg
                   ` (7 preceding siblings ...)
  2022-10-05 13:00 ` [PATCH 08/28] wifi: cfg80211/mac80211: Fix ML element common size validation Johannes Berg
@ 2022-10-05 13:00 ` Johannes Berg
  2022-10-05 13:00 ` [PATCH 10/28] wifi: mac80211: Process association status for affiliated links Johannes Berg
                   ` (18 subsequent siblings)
  27 siblings, 0 replies; 34+ messages in thread
From: Johannes Berg @ 2022-10-05 13:00 UTC (permalink / raw)
  To: linux-wireless; +Cc: Ilan Peer

From: Ilan Peer <ilan.peer@intel.com>

When processing an association response frame for a Multi-Link
connection, extract the per station profile for each additional
link, and use it for parsing the link elements.

As the Multi-Link element might be fragmented, add support for
reassembling a fragmented element. To simplify memory management
logic, extend 'struct ieee802_11_elems' to hold a scratch buffer,
which is used for the defragmentation. Once an element is
reconstructed in the scratch area, point the corresponding element
pointer to it. Currently only defragmentation of Multi-Link element
and the contained per-STA profile subelement is supported.

Signed-off-by: Ilan Peer <ilan.peer@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 include/linux/ieee80211.h  |   1 +
 net/mac80211/ieee80211_i.h |  26 ++++++-
 net/mac80211/mlme.c        |  17 ++++-
 net/mac80211/util.c        | 150 ++++++++++++++++++++++++++++++++++++-
 4 files changed, 188 insertions(+), 6 deletions(-)

diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index b935a85b2f44..f51e939f28f2 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -4666,6 +4666,7 @@ static inline bool ieee80211_mle_size_ok(const u8 *data, size_t len)
 
 enum ieee80211_mle_subelems {
 	IEEE80211_MLE_SUBELEM_PER_STA_PROFILE		= 0,
+	IEEE80211_MLE_SUBELEM_FRAGMENT		        = 254,
 };
 
 #define IEEE80211_MLE_STA_CONTROL_LINK_ID			0x000f
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 4e1d4c339f2d..5dcbc8de53fd 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1707,8 +1707,27 @@ struct ieee802_11_elems {
 	u8 tx_pwr_env_num;
 	u8 eht_cap_len;
 
+	/* mult-link element can be de-fragmented and thus u8 is not sufficient */
+	size_t multi_link_len;
+
+	/*
+	 * store the per station profile pointer and length in case that the
+	 * parsing also handled Multi-Link element parsing for a specific link
+	 * ID.
+	 */
+	struct ieee80211_mle_per_sta_profile *prof;
+	size_t sta_prof_len;
+
 	/* whether a parse error occurred while retrieving these elements */
 	bool parse_error;
+
+	/*
+	 * scratch buffer that can be used for various element parsing related
+	 * tasks, e.g., element de-fragmentation etc.
+	 */
+	size_t scratch_len;
+	u8 *scratch_pos;
+	u8 scratch[];
 };
 
 static inline struct ieee80211_local *hw_to_local(
@@ -2197,9 +2216,13 @@ static inline void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata,
  *	represent a non-transmitting BSS in which case the data
  *	for that non-transmitting BSS is returned
  * @link_id: the link ID to parse elements for, if a STA profile
- *	is present in the multi-link element, or -1 to ignore
+ *	is present in the multi-link element, or -1 to ignore;
+ *	note that the code currently assumes parsing an association
+ *	(or re-association) response frame if this is given
  * @from_ap: frame is received from an AP (currently used only
  *	for EHT capabilities parsing)
+ * @scratch_len: if non zero, specifies the requested length of the scratch
+ *      buffer; otherwise, 'len' is used.
  */
 struct ieee80211_elems_parse_params {
 	const u8 *start;
@@ -2210,6 +2233,7 @@ struct ieee80211_elems_parse_params {
 	struct cfg80211_bss *bss;
 	int link_id;
 	bool from_ap;
+	size_t scratch_len;
 };
 
 struct ieee802_11_elems *
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 54b8d5065bbd..a7e06c8ddaf3 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -3923,11 +3923,12 @@ static bool ieee80211_assoc_config_link(struct ieee80211_link_data *link,
 	struct ieee80211_mgd_assoc_data *assoc_data = sdata->u.mgd.assoc_data;
 	struct ieee80211_bss_conf *bss_conf = link->conf;
 	struct ieee80211_local *local = sdata->local;
+	unsigned int link_id = link->link_id;
 	struct ieee80211_elems_parse_params parse_params = {
 		.start = elem_start,
 		.len = elem_len,
 		.bss = cbss,
-		.link_id = link == &sdata->deflink ? -1 : link->link_id,
+		.link_id = link_id == assoc_data->assoc_link_id ? -1 : link_id,
 		.from_ap = true,
 	};
 	bool is_6ghz = cbss->channel->band == NL80211_BAND_6GHZ;
@@ -3942,8 +3943,18 @@ static bool ieee80211_assoc_config_link(struct ieee80211_link_data *link,
 	if (!elems)
 		return false;
 
-	/* FIXME: use from STA profile element after parsing that */
-	capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info);
+	if (link_id == assoc_data->assoc_link_id) {
+		capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info);
+	} else if (!elems->prof) {
+		ret = false;
+		goto out;
+	} else {
+		const u8 *ptr = elems->prof->variable +
+				elems->prof->sta_info_len - 1;
+
+		/* FIXME: need to also handle the status code */
+		capab_info = get_unaligned_le16(ptr);
+	}
 
 	if (!is_s1g && !elems->supp_rates) {
 		sdata_info(sdata, "no SuppRates element in AssocResp\n");
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index bf7461c41bef..40b75fa82b15 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1026,8 +1026,10 @@ ieee80211_parse_extension_element(u32 *crc,
 			elems->eht_operation = data;
 		break;
 	case WLAN_EID_EXT_EHT_MULTI_LINK:
-		if (ieee80211_mle_size_ok(data, len))
+		if (ieee80211_mle_size_ok(data, len)) {
 			elems->multi_link = (void *)data;
+			elems->multi_link_len = len;
+		}
 		break;
 	}
 }
@@ -1497,6 +1499,145 @@ static size_t ieee802_11_find_bssid_profile(const u8 *start, size_t len,
 	return found ? profile_len : 0;
 }
 
+static void ieee80211_defragment_element(struct ieee802_11_elems *elems,
+					 void **elem_ptr, size_t *len,
+					 size_t total_len, u8 frag_id)
+{
+	u8 *data = *elem_ptr, *pos, *start;
+	const struct element *elem;
+
+	/*
+	 * Since 'data' points to the data of the element, not the element
+	 * itself, allow 254 in case it was an extended element where the
+	 * extended ID isn't part of the data we see here and thus not part of
+	 * 'len' either.
+	 */
+	if (!data || (*len != 254 && *len != 255))
+		return;
+
+	start = elems->scratch_pos;
+
+	if (WARN_ON(*len > (elems->scratch + elems->scratch_len -
+			    elems->scratch_pos)))
+		return;
+
+	memcpy(elems->scratch_pos, data, *len);
+	elems->scratch_pos += *len;
+
+	pos = data + *len;
+	total_len -= *len;
+	for_each_element(elem, pos, total_len) {
+		if (elem->id != frag_id)
+			break;
+
+		if (WARN_ON(elem->datalen >
+			    (elems->scratch + elems->scratch_len -
+			     elems->scratch_pos)))
+			return;
+
+		memcpy(elems->scratch_pos, elem->data, elem->datalen);
+		elems->scratch_pos += elem->datalen;
+
+		*len += elem->datalen;
+	}
+
+	*elem_ptr = start;
+}
+
+static void ieee80211_mle_get_sta_prof(struct ieee802_11_elems *elems,
+				       u8 link_id)
+{
+	const struct ieee80211_multi_link_elem *ml = elems->multi_link;
+	size_t ml_len = elems->multi_link_len;
+	const struct element *sub;
+
+	if (!ml || !ml_len)
+		return;
+
+	if (le16_get_bits(ml->control, IEEE80211_ML_CONTROL_TYPE) !=
+	    IEEE80211_ML_CONTROL_TYPE_BASIC)
+		return;
+
+	for_each_mle_subelement(sub, (u8 *)ml, ml_len) {
+		struct ieee80211_mle_per_sta_profile *prof = (void *)sub->data;
+		u16 control;
+
+		if (sub->id != IEEE80211_MLE_SUBELEM_PER_STA_PROFILE)
+			continue;
+
+		if (!ieee80211_mle_sta_prof_size_ok(sub->data, sub->datalen))
+			return;
+
+		control = le16_to_cpu(prof->control);
+
+		if (link_id != u16_get_bits(control,
+					    IEEE80211_MLE_STA_CONTROL_LINK_ID))
+			continue;
+
+		if (!(control & IEEE80211_MLE_STA_CONTROL_COMPLETE_PROFILE))
+			return;
+
+		elems->prof = prof;
+		elems->sta_prof_len = sub->datalen;
+
+		/* the sub element can be fragmented */
+		ieee80211_defragment_element(elems, (void **)&elems->prof,
+					     &elems->sta_prof_len,
+					     ml_len - (sub->data - (u8 *)ml),
+					     IEEE80211_MLE_SUBELEM_FRAGMENT);
+		return;
+	}
+}
+
+static void ieee80211_mle_parse_link(struct ieee802_11_elems *elems,
+				     struct ieee80211_elems_parse_params *params)
+{
+	struct ieee80211_mle_per_sta_profile *prof;
+	struct ieee80211_elems_parse_params sub = {
+		.action = params->action,
+		.from_ap = params->from_ap,
+		.link_id = -1,
+	};
+	const struct element *non_inherit = NULL;
+	const u8 *end;
+
+	if (params->link_id == -1)
+		return;
+
+	ieee80211_defragment_element(elems, (void **)&elems->multi_link,
+				     &elems->multi_link_len,
+				     elems->total_len - ((u8 *)elems->multi_link -
+							 elems->ie_start),
+				     WLAN_EID_FRAGMENT);
+
+	ieee80211_mle_get_sta_prof(elems, params->link_id);
+	prof = elems->prof;
+
+	if (!prof)
+		return;
+
+	/* check if we have the 4 bytes for the fixed part in assoc response */
+	if (elems->sta_prof_len < sizeof(*prof) + prof->sta_info_len - 1 + 4) {
+		elems->prof = NULL;
+		elems->sta_prof_len = 0;
+		return;
+	}
+
+	/*
+	 * Skip the capability information and the status code that are expected
+	 * as part of the station profile in association response frames. Note
+	 * the -1 is because the 'sta_info_len' is accounted to as part of the
+	 * per-STA profile, but not part of the 'u8 variable[]' portion.
+	 */
+	sub.start = prof->variable + prof->sta_info_len - 1 + 4;
+	end = (const u8 *)prof + elems->sta_prof_len;
+	sub.len = end - sub.start;
+
+	non_inherit = cfg80211_find_ext_elem(WLAN_EID_EXT_NON_INHERITANCE,
+					     sub.start, sub.len);
+	_ieee802_11_parse_elems_full(&sub, elems, non_inherit);
+}
+
 struct ieee802_11_elems *
 ieee802_11_parse_elems_full(struct ieee80211_elems_parse_params *params)
 {
@@ -1504,12 +1645,15 @@ ieee802_11_parse_elems_full(struct ieee80211_elems_parse_params *params)
 	const struct element *non_inherit = NULL;
 	u8 *nontransmitted_profile;
 	int nontransmitted_profile_len = 0;
+	size_t scratch_len = params->scratch_len ?: 2 * params->len;
 
-	elems = kzalloc(sizeof(*elems), GFP_ATOMIC);
+	elems = kzalloc(sizeof(*elems) + scratch_len, GFP_ATOMIC);
 	if (!elems)
 		return NULL;
 	elems->ie_start = params->start;
 	elems->total_len = params->len;
+	elems->scratch_len = scratch_len;
+	elems->scratch_pos = elems->scratch;
 
 	nontransmitted_profile = kmalloc(params->len, GFP_ATOMIC);
 	if (nontransmitted_profile) {
@@ -1537,6 +1681,8 @@ ieee802_11_parse_elems_full(struct ieee80211_elems_parse_params *params)
 		_ieee802_11_parse_elems_full(&sub, elems, NULL);
 	}
 
+	ieee80211_mle_parse_link(elems, params);
+
 	if (elems->tim && !elems->parse_error) {
 		const struct ieee80211_tim_ie *tim_ie = elems->tim;
 
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 10/28] wifi: mac80211: Process association status for affiliated links
  2022-10-05 13:00 [PATCH 00/28] wifi: further MLO work Johannes Berg
                   ` (8 preceding siblings ...)
  2022-10-05 13:00 ` [PATCH 09/28] wifi: mac80211: Parse station profile from association response Johannes Berg
@ 2022-10-05 13:00 ` Johannes Berg
  2022-10-05 13:00 ` [PATCH 11/28] wifi: mac80211: wme: use ap_addr instead of deflink BSSID Johannes Berg
                   ` (17 subsequent siblings)
  27 siblings, 0 replies; 34+ messages in thread
From: Johannes Berg @ 2022-10-05 13:00 UTC (permalink / raw)
  To: linux-wireless; +Cc: Ilan Peer

From: Ilan Peer <ilan.peer@intel.com>

In case the AP returned a non success status for one of the links,
do not activate the link.

Signed-off-by: Ilan Peer <ilan.peer@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/ieee80211_i.h |  2 ++
 net/mac80211/mlme.c        | 40 +++++++++++++++++++++++++++++++++-----
 2 files changed, 37 insertions(+), 5 deletions(-)

diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 5dcbc8de53fd..517a50abdb09 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -412,6 +412,8 @@ struct ieee80211_mgd_assoc_data {
 		u8 *elems; /* pointing to inside ie[] below */
 
 		ieee80211_conn_flags_t conn_flags;
+
+		u16 status;
 	} link[IEEE80211_MLD_MAX_NUM_LINKS];
 
 	u8 ap_addr[ETH_ALEN] __aligned(2);
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index a7e06c8ddaf3..2e4bb75c68c0 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -2754,7 +2754,8 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
 		struct cfg80211_bss *cbss = assoc_data->link[link_id].bss;
 		struct ieee80211_link_data *link;
 
-		if (!cbss)
+		if (!cbss ||
+		    assoc_data->link[link_id].status != WLAN_STATUS_SUCCESS)
 			continue;
 
 		link = sdata_dereference(sdata->link[link_id], sdata);
@@ -2782,7 +2783,8 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
 			struct ieee80211_link_data *link;
 			struct cfg80211_bss *cbss = assoc_data->link[link_id].bss;
 
-			if (!cbss)
+			if (!cbss ||
+			    assoc_data->link[link_id].status != WLAN_STATUS_SUCCESS)
 				continue;
 
 			link = sdata_dereference(sdata->link[link_id], sdata);
@@ -3945,6 +3947,12 @@ static bool ieee80211_assoc_config_link(struct ieee80211_link_data *link,
 
 	if (link_id == assoc_data->assoc_link_id) {
 		capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info);
+
+		/*
+		 * we should not get to this flow unless the association was
+		 * successful, so set the status directly to success
+		 */
+		assoc_data->link[link_id].status = WLAN_STATUS_SUCCESS;
 	} else if (!elems->prof) {
 		ret = false;
 		goto out;
@@ -3952,8 +3960,19 @@ static bool ieee80211_assoc_config_link(struct ieee80211_link_data *link,
 		const u8 *ptr = elems->prof->variable +
 				elems->prof->sta_info_len - 1;
 
-		/* FIXME: need to also handle the status code */
+		/*
+		 * During parsing, we validated that these fields exist,
+		 * otherwise elems->prof would have been set to NULL.
+		 */
 		capab_info = get_unaligned_le16(ptr);
+		assoc_data->link[link_id].status = get_unaligned_le16(ptr + 2);
+
+		if (assoc_data->link[link_id].status != WLAN_STATUS_SUCCESS) {
+			link_info(link, "association response status code=%u\n",
+				  assoc_data->link[link_id].status);
+			ret = true;
+			goto out;
+		}
 	}
 
 	if (!is_s1g && !elems->supp_rates) {
@@ -4874,6 +4893,7 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
 	unsigned int link_id;
 	struct sta_info *sta;
 	u64 changed[IEEE80211_MLD_MAX_NUM_LINKS] = {};
+	u16 valid_links = 0;
 	int err;
 
 	mutex_lock(&sdata->local->sta_mtx);
@@ -4886,8 +4906,6 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
 		goto out_err;
 
 	if (sdata->vif.valid_links) {
-		u16 valid_links = 0;
-
 		for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) {
 			if (!assoc_data->link[link_id].bss)
 				continue;
@@ -4957,6 +4975,12 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
 						 &changed[link_id]))
 			goto out_err;
 
+		if (assoc_data->link[link_id].status != WLAN_STATUS_SUCCESS) {
+			valid_links &= ~BIT(link_id);
+			ieee80211_sta_remove_link(sta, link_id);
+			continue;
+		}
+
 		if (link_id != assoc_data->assoc_link_id) {
 			err = ieee80211_sta_activate_link(sta, link_id);
 			if (err)
@@ -4964,6 +4988,9 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
 		}
 	}
 
+	/* links might have changed due to rejected ones, set them again */
+	ieee80211_vif_set_links(sdata, valid_links);
+
 	rate_control_rate_init(sta);
 
 	if (ifmgd->flags & IEEE80211_STA_MFP_ENABLED) {
@@ -5197,10 +5224,13 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
 		link = sdata_dereference(sdata->link[link_id], sdata);
 		if (!link)
 			continue;
+
 		if (!assoc_data->link[link_id].bss)
 			continue;
+
 		resp.links[link_id].bss = assoc_data->link[link_id].bss;
 		resp.links[link_id].addr = link->conf->addr;
+		resp.links[link_id].status = assoc_data->link[link_id].status;
 
 		/* get uapsd queues configuration - same for all links */
 		resp.uapsd_queues = 0;
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 11/28] wifi: mac80211: wme: use ap_addr instead of deflink BSSID
  2022-10-05 13:00 [PATCH 00/28] wifi: further MLO work Johannes Berg
                   ` (9 preceding siblings ...)
  2022-10-05 13:00 ` [PATCH 10/28] wifi: mac80211: Process association status for affiliated links Johannes Berg
@ 2022-10-05 13:00 ` Johannes Berg
  2022-10-05 13:00 ` [PATCH 12/28] wifi: mac80211: transmit AddBA with MLD address Johannes Berg
                   ` (16 subsequent siblings)
  27 siblings, 0 replies; 34+ messages in thread
From: Johannes Berg @ 2022-10-05 13:00 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

We use this to look up the destination station, so it
needs to be the MLD address of the AP for an MLO; use
ap_addr instead of the BSSID.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/wme.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c
index ecc1de2e68a5..9fab97f6fbea 100644
--- a/net/mac80211/wme.c
+++ b/net/mac80211/wme.c
@@ -211,7 +211,7 @@ u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
 		if (sta)
 			break;
 
-		ra = sdata->deflink.u.mgd.bssid;
+		ra = sdata->vif.cfg.ap_addr;
 		break;
 	case NL80211_IFTYPE_ADHOC:
 		ra = skb->data;
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 12/28] wifi: mac80211: transmit AddBA with MLD address
  2022-10-05 13:00 [PATCH 00/28] wifi: further MLO work Johannes Berg
                   ` (10 preceding siblings ...)
  2022-10-05 13:00 ` [PATCH 11/28] wifi: mac80211: wme: use ap_addr instead of deflink BSSID Johannes Berg
@ 2022-10-05 13:00 ` Johannes Berg
  2022-10-05 13:00 ` [PATCH 13/28] wifi: nl80211: use link ID in NL80211_CMD_SET_BSS Johannes Berg
                   ` (15 subsequent siblings)
  27 siblings, 0 replies; 34+ messages in thread
From: Johannes Berg @ 2022-10-05 13:00 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

This management frame is intended for the MLD so we
treat it in mac80211 as MLD addressed as well, and
should therefore use the MLD address of the AP for
the BSSID field in the frame, address translation
applies.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/agg-tx.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c
index 07c892aa8c73..9c40f8d3bce8 100644
--- a/net/mac80211/agg-tx.c
+++ b/net/mac80211/agg-tx.c
@@ -82,7 +82,7 @@ static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata,
 	    sdata->vif.type == NL80211_IFTYPE_MESH_POINT)
 		memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
 	else if (sdata->vif.type == NL80211_IFTYPE_STATION)
-		memcpy(mgmt->bssid, sdata->deflink.u.mgd.bssid, ETH_ALEN);
+		memcpy(mgmt->bssid, sdata->vif.cfg.ap_addr, ETH_ALEN);
 	else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
 		memcpy(mgmt->bssid, sdata->u.ibss.bssid, ETH_ALEN);
 
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 13/28] wifi: nl80211: use link ID in NL80211_CMD_SET_BSS
  2022-10-05 13:00 [PATCH 00/28] wifi: further MLO work Johannes Berg
                   ` (11 preceding siblings ...)
  2022-10-05 13:00 ` [PATCH 12/28] wifi: mac80211: transmit AddBA with MLD address Johannes Berg
@ 2022-10-05 13:00 ` Johannes Berg
  2022-10-05 13:00 ` [PATCH 14/28] wifi: mac80211: use link_id in ieee80211_change_bss() Johannes Berg
                   ` (14 subsequent siblings)
  27 siblings, 0 replies; 34+ messages in thread
From: Johannes Berg @ 2022-10-05 13:00 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

We clearly need the link ID here, to know the right BSS
to configure. Use/require it.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 include/net/cfg80211.h | 2 ++
 net/wireless/nl80211.c | 4 +++-
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 4d35a4234417..659dd1bee70f 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -2105,6 +2105,7 @@ struct mpath_info {
  *
  * Used to change BSS parameters (mainly for AP mode).
  *
+ * @link_id: link_id or -1 for non-MLD
  * @use_cts_prot: Whether to use CTS protection
  *	(0 = no, 1 = yes, -1 = do not change)
  * @use_short_preamble: Whether the use of short preambles is allowed
@@ -2122,6 +2123,7 @@ struct mpath_info {
  * @p2p_opp_ps: P2P opportunistic PS (-1 = no change)
  */
 struct bss_parameters {
+	int link_id;
 	int use_cts_prot;
 	int use_short_preamble;
 	int use_short_slot_time;
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index ad7393cd3d18..1d0277758d0e 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -7780,6 +7780,7 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info)
 	int err;
 
 	memset(&params, 0, sizeof(params));
+	params.link_id = nl80211_link_id_or_invalid(info->attrs);
 	/* default to not changing parameters */
 	params.use_cts_prot = -1;
 	params.use_short_preamble = -1;
@@ -16564,7 +16565,8 @@ static const struct genl_small_ops nl80211_small_ops[] = {
 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
 		.doit = nl80211_set_bss,
 		.flags = GENL_UNS_ADMIN_PERM,
-		.internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
+		.internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
+					 NL80211_FLAG_MLO_VALID_LINK_ID),
 	},
 	{
 		.cmd = NL80211_CMD_GET_REG,
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 14/28] wifi: mac80211: use link_id in ieee80211_change_bss()
  2022-10-05 13:00 [PATCH 00/28] wifi: further MLO work Johannes Berg
                   ` (12 preceding siblings ...)
  2022-10-05 13:00 ` [PATCH 13/28] wifi: nl80211: use link ID in NL80211_CMD_SET_BSS Johannes Berg
@ 2022-10-05 13:00 ` Johannes Berg
  2022-10-05 13:00 ` [PATCH 15/28] wifi: mac80211: advertise TWT requester only with HW support Johannes Berg
                   ` (13 subsequent siblings)
  27 siblings, 0 replies; 34+ messages in thread
From: Johannes Berg @ 2022-10-05 13:00 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

We should set the parameters here per link, except
unfortunately ap_isolate, but we can't really change
that anymore so it'll remain a quirk in the API in
that you need to change it on one of the valid links
and it'll apply to all.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/cfg.c | 40 +++++++++++++++++++++-------------------
 1 file changed, 21 insertions(+), 19 deletions(-)

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 687b4c878d4a..ef5700eac05c 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2554,47 +2554,50 @@ static int ieee80211_change_bss(struct wiphy *wiphy,
 				struct bss_parameters *params)
 {
 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	struct ieee80211_link_data *link;
 	struct ieee80211_supported_band *sband;
 	u32 changed = 0;
 
-	if (!sdata_dereference(sdata->deflink.u.ap.beacon, sdata))
+	link = ieee80211_link_or_deflink(sdata, params->link_id, true);
+	if (IS_ERR(link))
+		return PTR_ERR(link);
+
+	if (!sdata_dereference(link->u.ap.beacon, sdata))
 		return -ENOENT;
 
-	sband = ieee80211_get_sband(sdata);
+	sband = ieee80211_get_link_sband(link);
 	if (!sband)
 		return -EINVAL;
 
 	if (params->use_cts_prot >= 0) {
-		sdata->vif.bss_conf.use_cts_prot = params->use_cts_prot;
+		link->conf->use_cts_prot = params->use_cts_prot;
 		changed |= BSS_CHANGED_ERP_CTS_PROT;
 	}
 	if (params->use_short_preamble >= 0) {
-		sdata->vif.bss_conf.use_short_preamble =
-			params->use_short_preamble;
+		link->conf->use_short_preamble = params->use_short_preamble;
 		changed |= BSS_CHANGED_ERP_PREAMBLE;
 	}
 
-	if (!sdata->vif.bss_conf.use_short_slot &&
+	if (!link->conf->use_short_slot &&
 	    (sband->band == NL80211_BAND_5GHZ ||
 	     sband->band == NL80211_BAND_6GHZ)) {
-		sdata->vif.bss_conf.use_short_slot = true;
+		link->conf->use_short_slot = true;
 		changed |= BSS_CHANGED_ERP_SLOT;
 	}
 
 	if (params->use_short_slot_time >= 0) {
-		sdata->vif.bss_conf.use_short_slot =
-			params->use_short_slot_time;
+		link->conf->use_short_slot = params->use_short_slot_time;
 		changed |= BSS_CHANGED_ERP_SLOT;
 	}
 
 	if (params->basic_rates) {
-		ieee80211_parse_bitrates(sdata->vif.bss_conf.chandef.width,
+		ieee80211_parse_bitrates(link->conf->chandef.width,
 					 wiphy->bands[sband->band],
 					 params->basic_rates,
 					 params->basic_rates_len,
-					 &sdata->vif.bss_conf.basic_rates);
+					 &link->conf->basic_rates);
 		changed |= BSS_CHANGED_BASIC_RATES;
-		ieee80211_check_rate_mask(&sdata->deflink);
+		ieee80211_check_rate_mask(link);
 	}
 
 	if (params->ap_isolate >= 0) {
@@ -2606,30 +2609,29 @@ static int ieee80211_change_bss(struct wiphy *wiphy,
 	}
 
 	if (params->ht_opmode >= 0) {
-		sdata->vif.bss_conf.ht_operation_mode =
-			(u16) params->ht_opmode;
+		link->conf->ht_operation_mode = (u16)params->ht_opmode;
 		changed |= BSS_CHANGED_HT;
 	}
 
 	if (params->p2p_ctwindow >= 0) {
-		sdata->vif.bss_conf.p2p_noa_attr.oppps_ctwindow &=
+		link->conf->p2p_noa_attr.oppps_ctwindow &=
 					~IEEE80211_P2P_OPPPS_CTWINDOW_MASK;
-		sdata->vif.bss_conf.p2p_noa_attr.oppps_ctwindow |=
+		link->conf->p2p_noa_attr.oppps_ctwindow |=
 			params->p2p_ctwindow & IEEE80211_P2P_OPPPS_CTWINDOW_MASK;
 		changed |= BSS_CHANGED_P2P_PS;
 	}
 
 	if (params->p2p_opp_ps > 0) {
-		sdata->vif.bss_conf.p2p_noa_attr.oppps_ctwindow |=
+		link->conf->p2p_noa_attr.oppps_ctwindow |=
 					IEEE80211_P2P_OPPPS_ENABLE_BIT;
 		changed |= BSS_CHANGED_P2P_PS;
 	} else if (params->p2p_opp_ps == 0) {
-		sdata->vif.bss_conf.p2p_noa_attr.oppps_ctwindow &=
+		link->conf->p2p_noa_attr.oppps_ctwindow &=
 					~IEEE80211_P2P_OPPPS_ENABLE_BIT;
 		changed |= BSS_CHANGED_P2P_PS;
 	}
 
-	ieee80211_link_info_change_notify(sdata, &sdata->deflink, changed);
+	ieee80211_link_info_change_notify(sdata, link, changed);
 
 	return 0;
 }
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 15/28] wifi: mac80211: advertise TWT requester only with HW support
  2022-10-05 13:00 [PATCH 00/28] wifi: further MLO work Johannes Berg
                   ` (13 preceding siblings ...)
  2022-10-05 13:00 ` [PATCH 14/28] wifi: mac80211: use link_id in ieee80211_change_bss() Johannes Berg
@ 2022-10-05 13:00 ` Johannes Berg
  2022-10-05 13:00 ` [PATCH 16/28] wifi: mac80211: set internal scan request BSSID Johannes Berg
                   ` (12 subsequent siblings)
  27 siblings, 0 replies; 34+ messages in thread
From: Johannes Berg @ 2022-10-05 13:00 UTC (permalink / raw)
  To: linux-wireless; +Cc: Haim Dreyfuss

From: Haim Dreyfuss <haim.dreyfuss@intel.com>

Currently, we rely only on the AP capability. If the AP supports
TWT responder we will advertise TWT requester even if the driver
or HW doesn't support it. This this by checking the HW capability.

Signed-off-by: Haim Dreyfuss <haim.dreyfuss@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/mlme.c | 30 ++++++++++++++++++++++++------
 1 file changed, 24 insertions(+), 6 deletions(-)

diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 2e4bb75c68c0..b6f378e7edea 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -3870,9 +3870,15 @@ static void ieee80211_get_rates(struct ieee80211_supported_band *sband,
 	}
 }
 
-static bool ieee80211_twt_req_supported(const struct link_sta_info *link_sta,
+static bool ieee80211_twt_req_supported(struct ieee80211_sub_if_data *sdata,
+					struct ieee80211_supported_band *sband,
+					const struct link_sta_info *link_sta,
 					const struct ieee802_11_elems *elems)
 {
+	const struct ieee80211_sta_he_cap *own_he_cap =
+		ieee80211_get_he_iftype_cap(sband,
+					    ieee80211_vif_type_p2p(&sdata->vif));
+
 	if (elems->ext_capab_len < 10)
 		return false;
 
@@ -3880,14 +3886,19 @@ static bool ieee80211_twt_req_supported(const struct link_sta_info *link_sta,
 		return false;
 
 	return link_sta->pub->he_cap.he_cap_elem.mac_cap_info[0] &
-		IEEE80211_HE_MAC_CAP0_TWT_RES;
+		IEEE80211_HE_MAC_CAP0_TWT_RES &&
+		own_he_cap &&
+		(own_he_cap->he_cap_elem.mac_cap_info[0] &
+			IEEE80211_HE_MAC_CAP0_TWT_REQ);
 }
 
-static int ieee80211_recalc_twt_req(struct ieee80211_link_data *link,
+static int ieee80211_recalc_twt_req(struct ieee80211_sub_if_data *sdata,
+				    struct ieee80211_supported_band *sband,
+				    struct ieee80211_link_data *link,
 				    struct link_sta_info *link_sta,
 				    struct ieee802_11_elems *elems)
 {
-	bool twt = ieee80211_twt_req_supported(link_sta, elems);
+	bool twt = ieee80211_twt_req_supported(sdata, sband, link_sta, elems);
 
 	if (link->conf->twt_requester != twt) {
 		link->conf->twt_requester = twt;
@@ -4129,7 +4140,8 @@ static bool ieee80211_assoc_config_link(struct ieee80211_link_data *link,
 		else
 			bss_conf->twt_protected = false;
 
-		*changed |= ieee80211_recalc_twt_req(link, link_sta, elems);
+		*changed |= ieee80211_recalc_twt_req(sdata, sband, link,
+						     link_sta, elems);
 
 		if (elems->eht_operation && elems->eht_cap &&
 		    !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_EHT)) {
@@ -5472,6 +5484,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_link_data *link,
 	struct ieee802_11_elems *elems;
 	struct ieee80211_local *local = sdata->local;
 	struct ieee80211_chanctx_conf *chanctx_conf;
+	struct ieee80211_supported_band *sband;
 	struct ieee80211_channel *chan;
 	struct link_sta_info *link_sta;
 	struct sta_info *sta;
@@ -5734,7 +5747,12 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_link_data *link,
 		goto free;
 	}
 
-	changed |= ieee80211_recalc_twt_req(link, link_sta, elems);
+	if (WARN_ON(!link->conf->chandef.chan))
+		goto free;
+
+	sband = local->hw.wiphy->bands[link->conf->chandef.chan->band];
+
+	changed |= ieee80211_recalc_twt_req(sdata, sband, link, link_sta, elems);
 
 	if (ieee80211_config_bw(link, elems->ht_cap_elem,
 				elems->vht_cap_elem, elems->ht_operation,
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 16/28] wifi: mac80211: set internal scan request BSSID
  2022-10-05 13:00 [PATCH 00/28] wifi: further MLO work Johannes Berg
                   ` (14 preceding siblings ...)
  2022-10-05 13:00 ` [PATCH 15/28] wifi: mac80211: advertise TWT requester only with HW support Johannes Berg
@ 2022-10-05 13:00 ` Johannes Berg
  2022-10-05 13:00 ` [PATCH 17/28] wifi: mac80211: fix AddBA response addressing Johannes Berg
                   ` (11 subsequent siblings)
  27 siblings, 0 replies; 34+ messages in thread
From: Johannes Berg @ 2022-10-05 13:00 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

If any driver relies entirely on the scan request BSSID,
then that would be wrong for internal scans. Initialize
it to the broadcast address since we don't otherwise use
the field.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/main.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 46f3eddc2388..25e72812000e 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -1155,6 +1155,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
 	if (!local->int_scan_req)
 		return -ENOMEM;
 
+	eth_broadcast_addr(local->int_scan_req->bssid);
+
 	for (band = 0; band < NUM_NL80211_BANDS; band++) {
 		if (!local->hw.wiphy->bands[band])
 			continue;
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 17/28] wifi: mac80211: fix AddBA response addressing
  2022-10-05 13:00 [PATCH 00/28] wifi: further MLO work Johannes Berg
                   ` (15 preceding siblings ...)
  2022-10-05 13:00 ` [PATCH 16/28] wifi: mac80211: set internal scan request BSSID Johannes Berg
@ 2022-10-05 13:00 ` Johannes Berg
  2022-10-05 13:00 ` [PATCH 18/28] wifi: mac80211: add RCU _check() link access variants Johannes Berg
                   ` (10 subsequent siblings)
  27 siblings, 0 replies; 34+ messages in thread
From: Johannes Berg @ 2022-10-05 13:00 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

Since this frame is addressed from/to an MLD, it should be
built with the correct AP MLD address (in station mode) to
be encrypted properly.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/agg-rx.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c
index 9414d3bbd65f..eaef88a603e5 100644
--- a/net/mac80211/agg-rx.c
+++ b/net/mac80211/agg-rx.c
@@ -242,7 +242,7 @@ static void ieee80211_send_addba_resp(struct sta_info *sta, u8 *da, u16 tid,
 	    sdata->vif.type == NL80211_IFTYPE_MESH_POINT)
 		memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
 	else if (sdata->vif.type == NL80211_IFTYPE_STATION)
-		memcpy(mgmt->bssid, sdata->deflink.u.mgd.bssid, ETH_ALEN);
+		memcpy(mgmt->bssid, sdata->vif.cfg.ap_addr, ETH_ALEN);
 	else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
 		memcpy(mgmt->bssid, sdata->u.ibss.bssid, ETH_ALEN);
 
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 18/28] wifi: mac80211: add RCU _check() link access variants
  2022-10-05 13:00 [PATCH 00/28] wifi: further MLO work Johannes Berg
                   ` (16 preceding siblings ...)
  2022-10-05 13:00 ` [PATCH 17/28] wifi: mac80211: fix AddBA response addressing Johannes Berg
@ 2022-10-05 13:00 ` Johannes Berg
  2022-10-05 13:00 ` [PATCH 19/28] wifi: fix multi-link element subelement iteration Johannes Berg
                   ` (9 subsequent siblings)
  27 siblings, 0 replies; 34+ messages in thread
From: Johannes Berg @ 2022-10-05 13:00 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

We might sometimes need to use RCU and locking in the same code
path, so add the two variants link_conf_dereference_check() and
link_sta_dereference_check().

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 include/net/mac80211.h | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index c413050ec8dd..cda4584dfd51 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -1915,6 +1915,10 @@ static inline bool lockdep_vif_mutex_held(struct ieee80211_vif *vif)
 	rcu_dereference_protected((vif)->link_conf[link_id],	\
 				  lockdep_vif_mutex_held(vif))
 
+#define link_conf_dereference_check(vif, link_id)		\
+	rcu_dereference_check((vif)->link_conf[link_id],	\
+			      lockdep_vif_mutex_held(vif))
+
 /**
  * enum ieee80211_key_flags - key flags
  *
@@ -2311,6 +2315,10 @@ static inline bool lockdep_sta_mutex_held(struct ieee80211_sta *pubsta)
 	rcu_dereference_protected((sta)->link[link_id],		\
 				  lockdep_sta_mutex_held(sta))
 
+#define link_sta_dereference_check(sta, link_id)		\
+	rcu_dereference_check((sta)->link[link_id],		\
+			      lockdep_sta_mutex_held(sta))
+
 #define for_each_sta_active_link(vif, sta, link_sta, link_id)			\
 	for (link_id = 0; link_id < ARRAY_SIZE((sta)->link); link_id++)		\
 		if ((!(vif)->active_links ||					\
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 19/28] wifi: fix multi-link element subelement iteration
  2022-10-05 13:00 [PATCH 00/28] wifi: further MLO work Johannes Berg
                   ` (17 preceding siblings ...)
  2022-10-05 13:00 ` [PATCH 18/28] wifi: mac80211: add RCU _check() link access variants Johannes Berg
@ 2022-10-05 13:00 ` Johannes Berg
  2022-10-05 13:00 ` [PATCH 20/28] wifi: mac80211: mlme: fix null-ptr deref on failed assoc Johannes Berg
                   ` (8 subsequent siblings)
  27 siblings, 0 replies; 34+ messages in thread
From: Johannes Berg @ 2022-10-05 13:00 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

The subelements obviously start after the common data, including
the common multi-link element structure definition itself. This
bug was possibly just hidden by the higher bits of the control
being set to 0, so the iteration just found one bogus element
and most of the code could continue anyway.

Fixes: 0f48b8b88aa9 ("wifi: ieee80211: add definitions for multi-link element")
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 include/linux/ieee80211.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index f51e939f28f2..6252f02f38b7 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -4593,7 +4593,7 @@ static inline u8 ieee80211_mle_common_size(const u8 *data)
 		return 0;
 	}
 
-	return common + mle->variable[0];
+	return sizeof(*mle) + common + mle->variable[0];
 }
 
 /**
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 20/28] wifi: mac80211: mlme: fix null-ptr deref on failed assoc
  2022-10-05 13:00 [PATCH 00/28] wifi: further MLO work Johannes Berg
                   ` (18 preceding siblings ...)
  2022-10-05 13:00 ` [PATCH 19/28] wifi: fix multi-link element subelement iteration Johannes Berg
@ 2022-10-05 13:00 ` Johannes Berg
  2022-10-05 13:00 ` [PATCH 21/28] wifi: mac80211: check link ID in auth/assoc continuation Johannes Berg
                   ` (7 subsequent siblings)
  27 siblings, 0 replies; 34+ messages in thread
From: Johannes Berg @ 2022-10-05 13:00 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

If association to an AP without a link 0 fails, then we crash in
tracing because it assumes that either ap_mld_addr or link 0 BSS
is valid, since we clear sdata->vif.valid_links and then don't
add the ap_mld_addr to the struct.

Since we clear also sdata->vif.cfg.ap_addr, keep a local copy of
it and assign it earlier, before clearing valid_links, to fix
this.

Fixes: 81151ce462e5 ("wifi: mac80211: support MLO authentication/association with one link")
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/mlme.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index b6f378e7edea..1ad0bf3bfcae 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -5082,6 +5082,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
 	struct cfg80211_rx_assoc_resp resp = {
 		.uapsd_queues = -1,
 	};
+	u8 ap_mld_addr[ETH_ALEN] __aligned(2);
 	unsigned int link_id;
 
 	sdata_assert_lock(sdata);
@@ -5251,6 +5252,11 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
 				resp.uapsd_queues |= ieee80211_ac_to_qos_mask[ac];
 	}
 
+	if (sdata->vif.valid_links) {
+		ether_addr_copy(ap_mld_addr, sdata->vif.cfg.ap_addr);
+		resp.ap_mld_addr = ap_mld_addr;
+	}
+
 	ieee80211_destroy_assoc_data(sdata,
 				     status_code == WLAN_STATUS_SUCCESS ?
 					ASSOC_SUCCESS :
@@ -5260,8 +5266,6 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
 	resp.len = len;
 	resp.req_ies = ifmgd->assoc_req_ies;
 	resp.req_ies_len = ifmgd->assoc_req_ies_len;
-	if (sdata->vif.valid_links)
-		resp.ap_mld_addr = sdata->vif.cfg.ap_addr;
 	cfg80211_rx_assoc_resp(sdata->dev, &resp);
 notify_driver:
 	drv_mgd_complete_tx(sdata->local, sdata, &info);
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 21/28] wifi: mac80211: check link ID in auth/assoc continuation
  2022-10-05 13:00 [PATCH 00/28] wifi: further MLO work Johannes Berg
                   ` (19 preceding siblings ...)
  2022-10-05 13:00 ` [PATCH 20/28] wifi: mac80211: mlme: fix null-ptr deref on failed assoc Johannes Berg
@ 2022-10-05 13:00 ` Johannes Berg
  2022-10-05 13:00 ` [PATCH 22/28] wifi: mac80211: mlme: mark assoc link in output Johannes Berg
                   ` (6 subsequent siblings)
  27 siblings, 0 replies; 34+ messages in thread
From: Johannes Berg @ 2022-10-05 13:00 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

Ensure that the link ID matches in auth/assoc continuation,
otherwise we need to reset all the data.

Fixes: 81151ce462e5 ("wifi: mac80211: support MLO authentication/association with one link")
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/ieee80211_i.h | 1 +
 net/mac80211/mlme.c        | 7 +++++--
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 517a50abdb09..b704656027db 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -390,6 +390,7 @@ struct ieee80211_mgd_auth_data {
 	bool done, waiting;
 	bool peer_confirmed;
 	bool timeout_started;
+	int link_id;
 
 	u8 ap_addr[ETH_ALEN] __aligned(2);
 
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 1ad0bf3bfcae..c46f355265ee 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -6702,6 +6702,7 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
 	       req->ap_mld_addr ?: req->bss->bssid,
 	       ETH_ALEN);
 	auth_data->bss = req->bss;
+	auth_data->link_id = req->link_id;
 
 	if (req->auth_data_len >= 4) {
 		if (req->auth_type == NL80211_AUTHTYPE_SAE) {
@@ -6720,7 +6721,8 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
 	 * removal and re-addition of the STA entry in
 	 * ieee80211_prep_connection().
 	 */
-	cont_auth = ifmgd->auth_data && req->bss == ifmgd->auth_data->bss;
+	cont_auth = ifmgd->auth_data && req->bss == ifmgd->auth_data->bss &&
+		    ifmgd->auth_data->link_id == req->link_id;
 
 	if (req->ie && req->ie_len) {
 		memcpy(&auth_data->data[auth_data->data_len],
@@ -7044,7 +7046,8 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
 
 		/* keep sta info, bssid if matching */
 		match = ether_addr_equal(ifmgd->auth_data->ap_addr,
-					 assoc_data->ap_addr);
+					 assoc_data->ap_addr) &&
+			ifmgd->auth_data->link_id == req->link_id;
 		ieee80211_destroy_auth_data(sdata, match);
 	}
 
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 22/28] wifi: mac80211: mlme: mark assoc link in output
  2022-10-05 13:00 [PATCH 00/28] wifi: further MLO work Johannes Berg
                   ` (20 preceding siblings ...)
  2022-10-05 13:00 ` [PATCH 21/28] wifi: mac80211: check link ID in auth/assoc continuation Johannes Berg
@ 2022-10-05 13:00 ` Johannes Berg
  2022-10-05 13:00 ` [PATCH 23/28] wifi: mac80211: change AddBA deny error message Johannes Berg
                   ` (5 subsequent siblings)
  27 siblings, 0 replies; 34+ messages in thread
From: Johannes Berg @ 2022-10-05 13:00 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

It's useful to know which link was used for the association,
mark it when printing the links.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/mlme.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index c46f355265ee..50a376f86ec2 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -4946,9 +4946,11 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
 
 		if (sdata->vif.valid_links)
 			link_info(link,
-				  "local address %pM, AP link address %pM\n",
+				  "local address %pM, AP link address %pM%s\n",
 				  link->conf->addr,
-				  assoc_data->link[link_id].bss->bssid);
+				  assoc_data->link[link_id].bss->bssid,
+				  link_id == assoc_data->assoc_link_id ?
+					" (assoc)" : "");
 
 		link_sta = rcu_dereference_protected(sta->link[link_id],
 						     lockdep_is_held(&local->sta_mtx));
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 23/28] wifi: mac80211: change AddBA deny error message
  2022-10-05 13:00 [PATCH 00/28] wifi: further MLO work Johannes Berg
                   ` (21 preceding siblings ...)
  2022-10-05 13:00 ` [PATCH 22/28] wifi: mac80211: mlme: mark assoc link in output Johannes Berg
@ 2022-10-05 13:00 ` Johannes Berg
  2022-10-05 13:00 ` [PATCH 24/28] wifi: mac80211: don't clear DTIM period after setting it Johannes Berg
                   ` (4 subsequent siblings)
  27 siblings, 0 replies; 34+ messages in thread
From: Johannes Berg @ 2022-10-05 13:00 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

If the station has no HT, we deny the aggregation session
but the error message talks about QoS; change it to say HT
instead.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/agg-rx.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c
index eaef88a603e5..f8bec5ee5b44 100644
--- a/net/mac80211/agg-rx.c
+++ b/net/mac80211/agg-rx.c
@@ -299,7 +299,7 @@ void ___ieee80211_start_rx_ba_session(struct sta_info *sta,
 	if (!sta->sta.deflink.ht_cap.ht_supported &&
 	    sta->sdata->vif.bss_conf.chandef.chan->band != NL80211_BAND_6GHZ) {
 		ht_dbg(sta->sdata,
-		       "STA %pM erroneously requests BA session on tid %d w/o QoS\n",
+		       "STA %pM erroneously requests BA session on tid %d w/o HT\n",
 		       sta->sta.addr, tid);
 		/* send a response anyway, it's an error case if we get here */
 		goto end;
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 24/28] wifi: mac80211: don't clear DTIM period after setting it
  2022-10-05 13:00 [PATCH 00/28] wifi: further MLO work Johannes Berg
                   ` (22 preceding siblings ...)
  2022-10-05 13:00 ` [PATCH 23/28] wifi: mac80211: change AddBA deny error message Johannes Berg
@ 2022-10-05 13:00 ` Johannes Berg
  2022-10-05 13:00 ` [PATCH 25/28] wifi: mac80211: prohibit IEEE80211_HT_CAP_DELAY_BA with MLO Johannes Berg
                   ` (3 subsequent siblings)
  27 siblings, 0 replies; 34+ messages in thread
From: Johannes Berg @ 2022-10-05 13:00 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

Fix the code that sets the DTIM period to always propagate it
into link->conf->dtim_period and not overwrite it, while still
preferring to set it from the beacon data if available.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/mlme.c | 25 ++++++++++++-------------
 1 file changed, 12 insertions(+), 13 deletions(-)

diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 50a376f86ec2..a651d3ffd8e6 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -2717,18 +2717,10 @@ static u32 ieee80211_link_set_associated(struct ieee80211_link_data *link,
 	}
 
 	if (link->u.mgd.have_beacon) {
-		/*
-		 * If the AP is buggy we may get here with no DTIM period
-		 * known, so assume it's 1 which is the only safe assumption
-		 * in that case, although if the TIM IE is broken powersave
-		 * probably just won't work at all.
-		 */
-		bss_conf->dtim_period = link->u.mgd.dtim_period ?: 1;
 		bss_conf->beacon_rate = bss->beacon_rate;
 		changed |= BSS_CHANGED_BEACON_INFO;
 	} else {
 		bss_conf->beacon_rate = NULL;
-		bss_conf->dtim_period = 0;
 	}
 
 	/* Tell the driver to monitor connection quality (if supported) */
@@ -4934,10 +4926,11 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
 	}
 
 	for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) {
+		struct cfg80211_bss *cbss = assoc_data->link[link_id].bss;
 		struct ieee80211_link_data *link;
 		struct link_sta_info *link_sta;
 
-		if (!assoc_data->link[link_id].bss)
+		if (!cbss)
 			continue;
 
 		link = sdata_dereference(sdata->link[link_id], sdata);
@@ -4957,19 +4950,25 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
 		if (WARN_ON(!link_sta))
 			goto out_err;
 
-		if (link_id != assoc_data->assoc_link_id) {
-			struct cfg80211_bss *cbss = assoc_data->link[link_id].bss;
+		if (!link->u.mgd.have_beacon) {
 			const struct cfg80211_bss_ies *ies;
 
 			rcu_read_lock();
-			ies = rcu_dereference(cbss->ies);
+			ies = rcu_dereference(cbss->beacon_ies);
+			if (ies)
+				link->u.mgd.have_beacon = true;
+			else
+				ies = rcu_dereference(cbss->ies);
 			ieee80211_get_dtim(ies,
 					   &link->conf->sync_dtim_count,
 					   &link->u.mgd.dtim_period);
-			link->conf->dtim_period = link->u.mgd.dtim_period ?: 1;
 			link->conf->beacon_int = cbss->beacon_interval;
 			rcu_read_unlock();
+		}
 
+		link->conf->dtim_period = link->u.mgd.dtim_period ?: 1;
+
+		if (link_id != assoc_data->assoc_link_id) {
 			err = ieee80211_prep_channel(sdata, link, cbss,
 						     &link->u.mgd.conn_flags);
 			if (err) {
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 25/28] wifi: mac80211: prohibit IEEE80211_HT_CAP_DELAY_BA with MLO
  2022-10-05 13:00 [PATCH 00/28] wifi: further MLO work Johannes Berg
                   ` (23 preceding siblings ...)
  2022-10-05 13:00 ` [PATCH 24/28] wifi: mac80211: don't clear DTIM period after setting it Johannes Berg
@ 2022-10-05 13:00 ` Johannes Berg
  2022-10-05 13:00 ` [PATCH 26/28] wifi: mac80211: agg-rx: avoid band check Johannes Berg
                   ` (2 subsequent siblings)
  27 siblings, 0 replies; 34+ messages in thread
From: Johannes Berg @ 2022-10-05 13:00 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

This won't work right at least with the code as it is, so
at least for now just assume it's never set for MLO. It may
very well never change, almost no drivers support it.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/main.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 25e72812000e..425793dd7c9c 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -1087,6 +1087,16 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
 
 		channels += sband->n_channels;
 
+		/*
+		 * Due to the way the aggregation code handles this and it
+		 * being an HT capability, we can't really support delayed
+		 * BA in MLO (yet).
+		 */
+		if (WARN_ON(sband->ht_cap.ht_supported &&
+			    (sband->ht_cap.cap & IEEE80211_HT_CAP_DELAY_BA) &&
+			    hw->wiphy->flags & WIPHY_FLAG_SUPPORTS_MLO))
+			return -EINVAL;
+
 		if (max_bitrates < sband->n_bitrates)
 			max_bitrates = sband->n_bitrates;
 		supp_ht = supp_ht || sband->ht_cap.ht_supported;
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 26/28] wifi: mac80211: agg-rx: avoid band check
  2022-10-05 13:00 [PATCH 00/28] wifi: further MLO work Johannes Berg
                   ` (24 preceding siblings ...)
  2022-10-05 13:00 ` [PATCH 25/28] wifi: mac80211: prohibit IEEE80211_HT_CAP_DELAY_BA with MLO Johannes Berg
@ 2022-10-05 13:00 ` Johannes Berg
  2022-10-05 13:00 ` [PATCH 27/28] wifi: mac80211: remove support for AddBA with fragmentation Johannes Berg
  2022-10-05 13:00 ` [PATCH 28/28] wifi: mac80211: fix ifdef symbol name Johannes Berg
  27 siblings, 0 replies; 34+ messages in thread
From: Johannes Berg @ 2022-10-05 13:00 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

If the deflink of the station is on 6 GHz, then it won't have HT.
If at the same time we're using MLO, then vif.bss_conf isn't used,
and thus vif.bss_conf.chandef.chan is NULL, causing the code to
crash.

Fix this by just checking for both HT and HE, and refusing the
aggregation session if both are not present. This might be a bit
wrong since it would accept an aggregation session from a peer
that has HE but no HT on 2.4 or 5 GHz, but such a peer shouldn't
exist in the first place, and it probably supports aggregation if
it has HE support.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/agg-rx.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c
index f8bec5ee5b44..bd41022f4894 100644
--- a/net/mac80211/agg-rx.c
+++ b/net/mac80211/agg-rx.c
@@ -297,7 +297,7 @@ void ___ieee80211_start_rx_ba_session(struct sta_info *sta,
 	}
 
 	if (!sta->sta.deflink.ht_cap.ht_supported &&
-	    sta->sdata->vif.bss_conf.chandef.chan->band != NL80211_BAND_6GHZ) {
+	    !sta->sta.deflink.he_cap.has_he) {
 		ht_dbg(sta->sdata,
 		       "STA %pM erroneously requests BA session on tid %d w/o HT\n",
 		       sta->sta.addr, tid);
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 27/28] wifi: mac80211: remove support for AddBA with fragmentation
  2022-10-05 13:00 [PATCH 00/28] wifi: further MLO work Johannes Berg
                   ` (25 preceding siblings ...)
  2022-10-05 13:00 ` [PATCH 26/28] wifi: mac80211: agg-rx: avoid band check Johannes Berg
@ 2022-10-05 13:00 ` Johannes Berg
  2022-10-05 13:00 ` [PATCH 28/28] wifi: mac80211: fix ifdef symbol name Johannes Berg
  27 siblings, 0 replies; 34+ messages in thread
From: Johannes Berg @ 2022-10-05 13:00 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

HE added support for dynamic fragmentation inside aggregation
sessions, but no existing driver ever advertises it. Thus,
remove the code for now, it cannot work as-is in MLO. For it
to properly work in MLO, we'd need to validate that the frag
level is identical across all the link bands/iftypes, which
is a good amount of complex code that's just not worth it as
long as no driver has support for it.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/agg-rx.c | 19 -------------------
 1 file changed, 19 deletions(-)

diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c
index bd41022f4894..c6fa53230450 100644
--- a/net/mac80211/agg-rx.c
+++ b/net/mac80211/agg-rx.c
@@ -183,34 +183,15 @@ static void ieee80211_add_addbaext(struct ieee80211_sub_if_data *sdata,
 				   const struct ieee80211_addba_ext_ie *req,
 				   u16 buf_size)
 {
-	struct ieee80211_supported_band *sband;
 	struct ieee80211_addba_ext_ie *resp;
-	const struct ieee80211_sta_he_cap *he_cap;
-	u8 frag_level, cap_frag_level;
 	u8 *pos;
 
-	sband = ieee80211_get_sband(sdata);
-	if (!sband)
-		return;
-	he_cap = ieee80211_get_he_iftype_cap(sband,
-					     ieee80211_vif_type_p2p(&sdata->vif));
-	if (!he_cap)
-		return;
-
 	pos = skb_put_zero(skb, 2 + sizeof(struct ieee80211_addba_ext_ie));
 	*pos++ = WLAN_EID_ADDBA_EXT;
 	*pos++ = sizeof(struct ieee80211_addba_ext_ie);
 	resp = (struct ieee80211_addba_ext_ie *)pos;
 	resp->data = req->data & IEEE80211_ADDBA_EXT_NO_FRAG;
 
-	frag_level = u32_get_bits(req->data,
-				  IEEE80211_ADDBA_EXT_FRAG_LEVEL_MASK);
-	cap_frag_level = u32_get_bits(he_cap->he_cap_elem.mac_cap_info[0],
-				      IEEE80211_HE_MAC_CAP0_DYNAMIC_FRAG_MASK);
-	if (frag_level > cap_frag_level)
-		frag_level = cap_frag_level;
-	resp->data |= u8_encode_bits(frag_level,
-				     IEEE80211_ADDBA_EXT_FRAG_LEVEL_MASK);
 	resp->data |= u8_encode_bits(buf_size >> IEEE80211_ADDBA_EXT_BUF_SIZE_SHIFT,
 				     IEEE80211_ADDBA_EXT_BUF_SIZE_MASK);
 }
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH 28/28] wifi: mac80211: fix ifdef symbol name
  2022-10-05 13:00 [PATCH 00/28] wifi: further MLO work Johannes Berg
                   ` (26 preceding siblings ...)
  2022-10-05 13:00 ` [PATCH 27/28] wifi: mac80211: remove support for AddBA with fragmentation Johannes Berg
@ 2022-10-05 13:00 ` Johannes Berg
  27 siblings, 0 replies; 34+ messages in thread
From: Johannes Berg @ 2022-10-05 13:00 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

This should of course be CONFIG_, not CPTCFG_, which is an
artifact from working with backports.

Fixes: 9dd1953846c7 ("wifi: nl80211/mac80211: clarify link ID in control port TX")
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/tx.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 27c964be102e..d9e7a2ed5d2c 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -2971,7 +2971,7 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,
 
 		if (pre_conf_link_id != link_id &&
 		    link_id != IEEE80211_LINK_UNSPECIFIED) {
-#ifdef CPTCFG_MAC80211_VERBOSE_DEBUG
+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
 			net_info_ratelimited("%s: dropped frame to %pM with bad link ID request (%d vs. %d)\n",
 					     sdata->name, hdr.addr1,
 					     pre_conf_link_id, link_id);
-- 
2.37.3


^ permalink raw reply related	[flat|nested] 34+ messages in thread

* Re: [PATCH 05/28] wifi: cfg80211: support reporting failed links
  2022-10-05 13:00 ` [PATCH 05/28] wifi: cfg80211: support reporting failed links Johannes Berg
@ 2022-10-06 10:49   ` Veerendranath Jakkam
  2022-10-06 10:51     ` Johannes Berg
  0 siblings, 1 reply; 34+ messages in thread
From: Veerendranath Jakkam @ 2022-10-06 10:49 UTC (permalink / raw)
  To: johannes; +Cc: johannes.berg, linux-wireless

I think similar enhancement needed for cfg80211_roamed/NL80211_CMD_ROAM 
also to know accepted and rejected links info during roaming.

- veeru


^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 05/28] wifi: cfg80211: support reporting failed links
  2022-10-06 10:49   ` Veerendranath Jakkam
@ 2022-10-06 10:51     ` Johannes Berg
  2022-10-06 11:09       ` Veerendranath Jakkam
  0 siblings, 1 reply; 34+ messages in thread
From: Johannes Berg @ 2022-10-06 10:51 UTC (permalink / raw)
  To: Veerendranath Jakkam; +Cc: linux-wireless

On Thu, 2022-10-06 at 16:19 +0530, Veerendranath Jakkam wrote:
> I think similar enhancement needed for cfg80211_roamed/NL80211_CMD_ROAM 
> also to know accepted and rejected links info during roaming.
> 

Not sure, in that case we might care only about the successful links
since wpa_s didn't request the others, so maybe it doesn't matter?

In any case, I have no driver I deal with that would ever use this API,
so I can't really do anything about it.

johannes

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 05/28] wifi: cfg80211: support reporting failed links
  2022-10-06 10:51     ` Johannes Berg
@ 2022-10-06 11:09       ` Veerendranath Jakkam
  2022-10-06 11:11         ` Johannes Berg
  0 siblings, 1 reply; 34+ messages in thread
From: Veerendranath Jakkam @ 2022-10-06 11:09 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless


On 10/6/2022 4:21 PM, Johannes Berg wrote:
> On Thu, 2022-10-06 at 16:19 +0530, Veerendranath Jakkam wrote:
>> I think similar enhancement needed for cfg80211_roamed/NL80211_CMD_ROAM
>> also to know accepted and rejected links info during roaming.
>>
> Not sure, in that case we might care only about the successful links
> since wpa_s didn't request the others, so maybe it doesn't matter?

Drivers can offload EAPOL 4WHS to wpa_supplicant during roaming with 
non-FT AKMs. In that case supplicant needs to know rejected links info 
to validate AP's MLO Link KDEs in 3/4 frame.

Ex: Driver handles only re-association request and response frames while 
doing roaming with non-FT AKM then offload 4WHS to wpa_supplicant

>
> In any case, I have no driver I deal with that would ever use this API,
> so I can't really do anything about it.

No problem, I will post the required changes for 
cfg80211_roamed/NL80211_CMD_ROAM path, hope that is fine.

>
> johannes

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 05/28] wifi: cfg80211: support reporting failed links
  2022-10-06 11:09       ` Veerendranath Jakkam
@ 2022-10-06 11:11         ` Johannes Berg
  2022-10-06 14:40           ` Veerendranath Jakkam
  0 siblings, 1 reply; 34+ messages in thread
From: Johannes Berg @ 2022-10-06 11:11 UTC (permalink / raw)
  To: Veerendranath Jakkam; +Cc: linux-wireless

On Thu, 2022-10-06 at 16:39 +0530, Veerendranath Jakkam wrote:
> On 10/6/2022 4:21 PM, Johannes Berg wrote:
> > On Thu, 2022-10-06 at 16:19 +0530, Veerendranath Jakkam wrote:
> > > I think similar enhancement needed for cfg80211_roamed/NL80211_CMD_ROAM
> > > also to know accepted and rejected links info during roaming.
> > > 
> > Not sure, in that case we might care only about the successful links
> > since wpa_s didn't request the others, so maybe it doesn't matter?
> 
> Drivers can offload EAPOL 4WHS to wpa_supplicant during roaming with 
> non-FT AKMs. In that case supplicant needs to know rejected links info 
> to validate AP's MLO Link KDEs in 3/4 frame.
> 
> Ex: Driver handles only re-association request and response frames while 
> doing roaming with non-FT AKM then offload 4WHS to wpa_supplicant
> 

Right, but is there a fundamental difference between

 "hey I roamed to this AP MLD with links 1, 2 and 5"
 (with the right BSSIDs for the links etc.)

and

 "hey I roamed to this AP MLD and I tried links 1, 2, 3, 4, 5 but only
1, 2 and 5 were established"

?

johannes

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH 05/28] wifi: cfg80211: support reporting failed links
  2022-10-06 11:11         ` Johannes Berg
@ 2022-10-06 14:40           ` Veerendranath Jakkam
  0 siblings, 0 replies; 34+ messages in thread
From: Veerendranath Jakkam @ 2022-10-06 14:40 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless


On 10/6/2022 4:41 PM, Johannes Berg wrote:
> Right, but is there a fundamental difference between
>   "hey I roamed to this AP MLD with links 1, 2 and 5"
>   (with the right BSSIDs for the links etc.)
>
> and
>
>   "hey I roamed to this AP MLD and I tried links 1, 2, 3, 4, 5 but only
> 1, 2 and 5 were established"
>
> ?

supplicant must validate MLO Link KDEs(includes RSNE and RSNXE) for all 
the negotiated links but MLO GTK/IGTK/BIGTK only for accepted links 
while processing 3/4 msg.

So, during roaming if EAPOL 4HS is offload to supplicant it should know 
the requested and accepted links information.

non-AP MLD needs to select common AKM across all the links. The MLO Link 
KDEs validation helps to avoid downgrade attacks.

- veeru



^ permalink raw reply	[flat|nested] 34+ messages in thread

end of thread, other threads:[~2022-10-06 14:41 UTC | newest]

Thread overview: 34+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-10-05 13:00 [PATCH 00/28] wifi: further MLO work Johannes Berg
2022-10-05 13:00 ` [PATCH 01/28] wifi: mac80211: add pointer from link STA to STA Johannes Berg
2022-10-05 13:00 ` [PATCH 02/28] wifi: mac80211: add API to show the link STAs in debugfs Johannes Berg
2022-10-05 13:00 ` [PATCH 03/28] wifi: mac80211: include link address " Johannes Berg
2022-10-05 13:00 ` [PATCH 04/28] wifi: mac80211: recalc station aggregate data during link switch Johannes Berg
2022-10-05 13:00 ` [PATCH 05/28] wifi: cfg80211: support reporting failed links Johannes Berg
2022-10-06 10:49   ` Veerendranath Jakkam
2022-10-06 10:51     ` Johannes Berg
2022-10-06 11:09       ` Veerendranath Jakkam
2022-10-06 11:11         ` Johannes Berg
2022-10-06 14:40           ` Veerendranath Jakkam
2022-10-05 13:00 ` [PATCH 06/28] wifi: ieee80211: Support validating ML station profile length Johannes Berg
2022-10-05 13:00 ` [PATCH 07/28] wifi: cfg80211/mac80211: Fix ML element common size calculation Johannes Berg
2022-10-05 13:00 ` [PATCH 08/28] wifi: cfg80211/mac80211: Fix ML element common size validation Johannes Berg
2022-10-05 13:00 ` [PATCH 09/28] wifi: mac80211: Parse station profile from association response Johannes Berg
2022-10-05 13:00 ` [PATCH 10/28] wifi: mac80211: Process association status for affiliated links Johannes Berg
2022-10-05 13:00 ` [PATCH 11/28] wifi: mac80211: wme: use ap_addr instead of deflink BSSID Johannes Berg
2022-10-05 13:00 ` [PATCH 12/28] wifi: mac80211: transmit AddBA with MLD address Johannes Berg
2022-10-05 13:00 ` [PATCH 13/28] wifi: nl80211: use link ID in NL80211_CMD_SET_BSS Johannes Berg
2022-10-05 13:00 ` [PATCH 14/28] wifi: mac80211: use link_id in ieee80211_change_bss() Johannes Berg
2022-10-05 13:00 ` [PATCH 15/28] wifi: mac80211: advertise TWT requester only with HW support Johannes Berg
2022-10-05 13:00 ` [PATCH 16/28] wifi: mac80211: set internal scan request BSSID Johannes Berg
2022-10-05 13:00 ` [PATCH 17/28] wifi: mac80211: fix AddBA response addressing Johannes Berg
2022-10-05 13:00 ` [PATCH 18/28] wifi: mac80211: add RCU _check() link access variants Johannes Berg
2022-10-05 13:00 ` [PATCH 19/28] wifi: fix multi-link element subelement iteration Johannes Berg
2022-10-05 13:00 ` [PATCH 20/28] wifi: mac80211: mlme: fix null-ptr deref on failed assoc Johannes Berg
2022-10-05 13:00 ` [PATCH 21/28] wifi: mac80211: check link ID in auth/assoc continuation Johannes Berg
2022-10-05 13:00 ` [PATCH 22/28] wifi: mac80211: mlme: mark assoc link in output Johannes Berg
2022-10-05 13:00 ` [PATCH 23/28] wifi: mac80211: change AddBA deny error message Johannes Berg
2022-10-05 13:00 ` [PATCH 24/28] wifi: mac80211: don't clear DTIM period after setting it Johannes Berg
2022-10-05 13:00 ` [PATCH 25/28] wifi: mac80211: prohibit IEEE80211_HT_CAP_DELAY_BA with MLO Johannes Berg
2022-10-05 13:00 ` [PATCH 26/28] wifi: mac80211: agg-rx: avoid band check Johannes Berg
2022-10-05 13:00 ` [PATCH 27/28] wifi: mac80211: remove support for AddBA with fragmentation Johannes Berg
2022-10-05 13:00 ` [PATCH 28/28] wifi: mac80211: fix ifdef symbol name Johannes Berg

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).