diff mbox series

[18/22] hostapd: MLO: send link id during flushing stations

Message ID 20240328181652.2956122-19-quic_adisi@quicinc.com
State Accepted
Headers show
Series [01/22] hostapd: MLO: fix for_each_mld_link macro | expand

Commit Message

Aditya Kumar Singh March 28, 2024, 6:16 p.m. UTC
Currently, whenever a BSS is set up, it sends flush all stations via
command - NL80211_CMD_DEL_STATION on its interface. However, in case
of MLO, station could have been connected to other links by the time
this link is coming up. Since there is no link id currently being
passed, all those stations entries are also removed in the driver which is
wrong.

Hence add change to send link id along with the command during MLO so that
the driver can use this link id and flush only those stations which are
using the passed link id as one of its links.

Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
---
 src/ap/ap_drv_ops.c          | 10 +++++++++-
 src/drivers/driver.h         |  4 +++-
 src/drivers/driver_atheros.c |  2 +-
 src/drivers/driver_bsd.c     |  2 +-
 src/drivers/driver_hostap.c  |  2 +-
 src/drivers/driver_nl80211.c | 17 ++++++++++++++---
 6 files changed, 29 insertions(+), 8 deletions(-)
diff mbox series

Patch

diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
index 0d493b837c9b..32722084da68 100644
--- a/src/ap/ap_drv_ops.c
+++ b/src/ap/ap_drv_ops.c
@@ -624,9 +624,17 @@  int hostapd_get_seqnum(const char *ifname, struct hostapd_data *hapd,
 
 int hostapd_flush(struct hostapd_data *hapd)
 {
+	int link_id = -1;
+
 	if (hapd->driver == NULL || hapd->driver->flush == NULL)
 		return 0;
-	return hapd->driver->flush(hapd->drv_priv);
+
+#ifdef CONFIG_IEEE80211BE
+	if (hapd->conf && hapd->conf->mld_ap)
+		link_id = hapd->mld_link_id;
+#endif /* CONFIG_IEEE80211BE */
+
+	return hapd->driver->flush(hapd->drv_priv, link_id);
 }
 
 
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index a7455ef6e430..e672a1787d86 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -3578,13 +3578,15 @@  struct wpa_driver_ops {
 	/**
 	 * flush - Flush all association stations (AP only)
 	 * @priv: Private driver interface data
+	 * @link_id: In case of MLO, valid link_id on which all associated stations
+	 *	     will be flushed. -1 otherwise.
 	 * Returns: 0 on success, -1 on failure
 	 *
 	 * This function requests the driver to disassociate all associated
 	 * stations. This function does not need to be implemented if the
 	 * driver does not process association frames internally.
 	 */
-	int (*flush)(void *priv);
+	int (*flush)(void *priv, int link_id);
 
 	/**
 	 * set_generic_elem - Add IEs into Beacon/Probe Response frames (AP)
diff --git a/src/drivers/driver_atheros.c b/src/drivers/driver_atheros.c
index ae7f0e535c67..71863306afad 100644
--- a/src/drivers/driver_atheros.c
+++ b/src/drivers/driver_atheros.c
@@ -632,7 +632,7 @@  atheros_get_seqnum(const char *ifname, void *priv, const u8 *addr, int idx,
 
 
 static int
-atheros_flush(void *priv)
+atheros_flush(void *priv, int link_id)
 {
 	u8 allsta[IEEE80211_ADDR_LEN];
 	os_memset(allsta, 0xff, IEEE80211_ADDR_LEN);
diff --git a/src/drivers/driver_bsd.c b/src/drivers/driver_bsd.c
index 850637f0db2e..82d8a0186c57 100644
--- a/src/drivers/driver_bsd.c
+++ b/src/drivers/driver_bsd.c
@@ -946,7 +946,7 @@  bsd_get_seqnum(const char *ifname, void *priv, const u8 *addr, int idx,
 
 
 static int
-bsd_flush(void *priv)
+bsd_flush(void *priv, int link_id)
 {
 	u8 allsta[IEEE80211_ADDR_LEN];
 
diff --git a/src/drivers/driver_hostap.c b/src/drivers/driver_hostap.c
index d3520aacc988..3aa5860bc433 100644
--- a/src/drivers/driver_hostap.c
+++ b/src/drivers/driver_hostap.c
@@ -572,7 +572,7 @@  static int hostap_set_ssid(void *priv, const u8 *buf, int len)
 }
 
 
-static int hostap_flush(void *priv)
+static int hostap_flush(void *priv, int link_id)
 {
 	struct hostap_driver_data *drv = priv;
 	struct prism2_hostapd_param param;
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index e5fa22b59f67..9ac621ae60b5 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -7729,25 +7729,36 @@  static int i802_set_frag(void *priv, int frag)
 }
 
 
-static int i802_flush(void *priv)
+static int i802_flush(void *priv, int link_id)
 {
 	struct i802_bss *bss = priv;
 	struct nl_msg *msg;
 	int res;
 
-	wpa_printf(MSG_DEBUG, "nl80211: flush -> DEL_STATION %s (all)",
-		   bss->ifname);
+	if (link_id == NL80211_DRV_LINK_ID_NA)
+		wpa_printf(MSG_DEBUG, "nl80211: flush -> DEL_STATION %s (all)",
+			   bss->ifname);
+	else
+		wpa_printf(MSG_DEBUG, "nl80211: flush -> DEL_STATION %s (with link %d)",
+			   bss->ifname, link_id);
 
 	/*
 	 * XXX: FIX! this needs to flush all VLANs too
 	 */
 	msg = nl80211_bss_msg(bss, 0, NL80211_CMD_DEL_STATION);
+	if (link_id >= 0 && (bss->valid_links & BIT(link_id)) &&
+	    nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID, link_id))
+		goto fail;
+
 	res = send_and_recv_cmd(bss->drv, msg);
 	if (res) {
 		wpa_printf(MSG_DEBUG, "nl80211: Station flush failed: ret=%d "
 			   "(%s)", res, strerror(-res));
 	}
 	return res;
+fail:
+	nlmsg_free(msg);
+	return -1;
 }