[PATCH] nl80211: skip unnecessary netlink calls

Johannes Berg johannes at sipsolutions.net
Sun Oct 4 15:19:56 PDT 2026


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

Currently SET_BSS and SET_MULTICAST_TO_UNICAST are sent after each
beacon update, but they need the wiphy mutex in the kernel and that
can cause undesired latency.

Cache the last values and don't send the commands if they don't
change anything.

Signed-off-by: Johannes Berg <johannes.berg at intel.com>
---
 src/drivers/driver_nl80211.c | 58 +++++++++++++++++++++++++++++++-----
 src/drivers/driver_nl80211.h |  7 +++++
 2 files changed, 58 insertions(+), 7 deletions(-)

diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index c6578cb86495..c73ac98470b5 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -5747,6 +5747,44 @@ static int nl80211_put_freq_params(struct nl_msg *msg,
 }
 
 
+static bool nl80211_bss_params_changed(struct i802_link *link,
+				       const struct wpa_driver_ap_params *params)
+{
+	u8 rates[NL80211_MAX_SUPP_RATES];
+	int len = -1;
+	bool changed;
+
+	if (params->basic_rates) {
+		for (len = 0;
+		     len < NL80211_MAX_SUPP_RATES &&
+			params->basic_rates[len] > 0;
+		     len++)
+			rates[len] = params->basic_rates[len] / 5;
+	}
+
+	changed = link->last_bss.cts != params->cts_protect ||
+		  link->last_bss.preamble != params->preamble ||
+		  link->last_bss.slot != params->short_slot_time ||
+		  link->last_bss.ht_opmode != params->ht_opmode ||
+		  link->last_bss.isolate != params->isolate ||
+		  link->last_bss.multicast_to_unicast != params->multicast_to_unicast ||
+		  link->last_bss.basic_rates_len != len ||
+		  (len > 0 && os_memcmp(link->last_bss.basic_rates, rates, len));
+
+	link->last_bss.cts = params->cts_protect;
+	link->last_bss.preamble = params->preamble;
+	link->last_bss.slot = params->short_slot_time;
+	link->last_bss.ht_opmode = params->ht_opmode;
+	link->last_bss.isolate = params->isolate;
+	link->last_bss.multicast_to_unicast = params->multicast_to_unicast;
+	link->last_bss.basic_rates_len = len;
+	if (len > 0)
+		os_memcpy(link->last_bss.basic_rates, rates, len);
+
+	return changed;
+}
+
+
 static int wpa_driver_nl80211_set_ap(void *priv,
 				     struct wpa_driver_ap_params *params)
 {
@@ -6140,13 +6178,19 @@ static int wpa_driver_nl80211_set_ap(void *priv,
 			   ret, strerror(-ret));
 	} else {
 		link->beacon_set = 1;
-		nl80211_set_bss(bss, params->cts_protect, params->preamble,
-				params->short_slot_time, params->ht_opmode,
-				params->isolate, params->basic_rates,
-				params->mld_ap ? params->mld_link_id :
-				NL80211_DRV_LINK_ID_NA);
-		nl80211_set_multicast_to_unicast(bss,
-						 params->multicast_to_unicast);
+		/* avoid kernel overhead if there are no chances */
+		if (nl80211_bss_params_changed(link, params) ||
+		    cmd != NL80211_CMD_UPDATE_BEACON) {
+			nl80211_set_bss(bss, params->cts_protect,
+					params->preamble,
+					params->short_slot_time,
+					params->ht_opmode, params->isolate,
+					params->basic_rates,
+					params->mld_ap ? params->mld_link_id :
+					NL80211_DRV_LINK_ID_NA);
+			nl80211_set_multicast_to_unicast(
+				bss, params->multicast_to_unicast);
+		}
 		if (beacon_set && params->freq &&
 		    params->freq->bandwidth != link->bandwidth) {
 			wpa_printf(MSG_DEBUG,
diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h
index 53faf2ef8be5..ad3d288d2ad1 100644
--- a/src/drivers/driver_nl80211.h
+++ b/src/drivers/driver_nl80211.h
@@ -76,6 +76,13 @@ struct nl80211_wiphy_data {
 struct i802_link {
 	unsigned int beacon_set:1;
 
+	struct {
+		int cts, preamble, slot, ht_opmode, isolate;
+		int multicast_to_unicast;
+		u8 basic_rates[NL80211_MAX_SUPP_RATES];
+		int basic_rates_len; /* -1 if not given */
+	} last_bss;
+
 	int freq;
 	int bandwidth;
 	u8 addr[ETH_ALEN];
-- 
2.55.0




More information about the Hostap mailing list