[RFC PATCH] nl80211: use NL80211_CMD_UPDATE_BEACON if supported
Johannes Berg
johannes at sipsolutions.net
Sun Oct 4 15:21:52 PDT 2026
From: Johannes Berg <johannes.berg at intel.com>
If the driver has NL80211_EXT_FEATURE_UPDATE_BEACON and the
update is only for the beacon or other templates, then use
the feature to update those. This should, in most cases,
not require taking the wiphy mutex in the kernel.
Because config changes aren't supported, track whether or
not HE BSS color is disabled.
Because AKM suites and other old-style attributes aren't
accepted by the new (strict netlink validation) command,
build just a minimal message in this case.
Signed-off-by: Johannes Berg <johannes.berg at intel.com>
---
src/drivers/driver_nl80211.c | 80 ++++++++++++++++++++++++++++++-
src/drivers/driver_nl80211.h | 2 +
src/drivers/driver_nl80211_capa.c | 4 ++
3 files changed, 84 insertions(+), 2 deletions(-)
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index c73ac98470b5..3a31fc722bbc 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -5785,6 +5785,64 @@ static bool nl80211_bss_params_changed(struct i802_link *link,
}
+static struct nl_msg *
+nl80211_update_beacon_msg(struct i802_bss *bss,
+ struct wpa_driver_ap_params *params)
+{
+ struct nl_msg *msg;
+
+ msg = nl80211_bss_msg(bss, 0, NL80211_CMD_UPDATE_BEACON);
+ if (!msg ||
+ nla_put(msg, NL80211_ATTR_BEACON_HEAD, params->head_len,
+ params->head) ||
+ nla_put(msg, NL80211_ATTR_BEACON_TAIL, params->tail_len,
+ params->tail) ||
+ (params->mld_ap &&
+ nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID, params->mld_link_id)) ||
+ (params->proberesp && params->proberesp_len &&
+ nla_put(msg, NL80211_ATTR_PROBE_RESP, params->proberesp_len,
+ params->proberesp)) ||
+ (params->beacon_ies &&
+ nla_put(msg, NL80211_ATTR_IE, wpabuf_len(params->beacon_ies),
+ wpabuf_head(params->beacon_ies))) ||
+ (params->proberesp_ies &&
+ nla_put(msg, NL80211_ATTR_IE_PROBE_RESP,
+ wpabuf_len(params->proberesp_ies),
+ wpabuf_head(params->proberesp_ies))) ||
+ (params->assocresp_ies &&
+ nla_put(msg, NL80211_ATTR_IE_ASSOC_RESP,
+ wpabuf_len(params->assocresp_ies),
+ wpabuf_head(params->assocresp_ies))))
+ goto fail;
+
+#ifdef CONFIG_IEEE80211AX
+ if ((params->ubpr.unsol_bcast_probe_resp_interval &&
+ nl80211_unsol_bcast_probe_resp(bss, msg, ¶ms->ubpr) < 0) ||
+ nl80211_mbssid(msg, ¶ms->mbssid) < 0)
+ goto fail;
+#endif /* CONFIG_IEEE80211AX */
+
+#ifdef CONFIG_IEEE80211BN
+ if (params->uhr_oper &&
+ nla_put(msg, NL80211_ATTR_UHR_OPERATION,
+ /* nl80211 wants it without the extended element header */
+ params->uhr_oper[1] - 1,
+ params->uhr_oper + 3))
+ goto fail;
+#endif /* CONFIG_IEEE80211BN */
+
+#ifdef CONFIG_FILS
+ if (params->fd_max_int && nl80211_fils_discovery(bss, msg, params) < 0)
+ goto fail;
+#endif /* CONFIG_FILS */
+
+ return msg;
+fail:
+ nlmsg_free(msg);
+ return NULL;
+}
+
+
static int wpa_driver_nl80211_set_ap(void *priv,
struct wpa_driver_ap_params *params)
{
@@ -5821,10 +5879,18 @@ static int wpa_driver_nl80211_set_ap(void *priv,
wpa_printf(MSG_DEBUG, "nl80211: Set beacon (beacon_set=%d)",
beacon_set);
- if (beacon_set)
+ if (beacon_set) {
cmd = NL80211_CMD_SET_BEACON;
- else if (!drv->device_ap_sme && !nl80211_get_wiphy_data_ap(bss))
+ /* configuration changes need SET_BEACON */
+ if (drv->update_beacon && !params->ftm_responder &&
+ !!params->he_bss_color_disabled ==
+ link->he_bss_color_disabled) {
+ wpa_printf(MSG_DEBUG, "nl80211: Using UPDATE_BEACON");
+ cmd = NL80211_CMD_UPDATE_BEACON;
+ }
+ } else if (!drv->device_ap_sme && !nl80211_get_wiphy_data_ap(bss)) {
return -ENOBUFS;
+ }
wpa_hexdump(MSG_DEBUG, "nl80211: Beacon head",
params->head, params->head_len);
@@ -5837,6 +5903,14 @@ static int wpa_driver_nl80211_set_ap(void *priv,
wpa_printf(MSG_DEBUG, "nl80211: dtim_period=%d", params->dtim_period);
wpa_printf(MSG_DEBUG, "nl80211: ssid=%s",
wpa_ssid_txt(params->ssid, params->ssid_len));
+
+ if (cmd == NL80211_CMD_UPDATE_BEACON) {
+ msg = nl80211_update_beacon_msg(bss, params);
+ if (!msg)
+ return -ENOBUFS;
+ goto send;
+ }
+
if (!(msg = nl80211_bss_msg(bss, 0, cmd)) ||
nla_put(msg, NL80211_ATTR_BEACON_HEAD, params->head_len,
params->head) ||
@@ -6171,6 +6245,7 @@ static int wpa_driver_nl80211_set_ap(void *priv,
if (nla_put_flag(msg, NL80211_ATTR_SOCKET_OWNER))
goto fail;
+send:
ret = send_and_recv(drv, bss->nl_connect, msg, NULL, NULL, NULL,
NULL, NULL);
if (ret) {
@@ -6178,6 +6253,7 @@ static int wpa_driver_nl80211_set_ap(void *priv,
ret, strerror(-ret));
} else {
link->beacon_set = 1;
+ link->he_bss_color_disabled = !!params->he_bss_color_disabled;
/* avoid kernel overhead if there are no chances */
if (nl80211_bss_params_changed(link, params) ||
cmd != NL80211_CMD_UPDATE_BEACON) {
diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h
index ad3d288d2ad1..9dc5c8b99f6e 100644
--- a/src/drivers/driver_nl80211.h
+++ b/src/drivers/driver_nl80211.h
@@ -75,6 +75,7 @@ struct nl80211_wiphy_data {
struct i802_link {
unsigned int beacon_set:1;
+ unsigned int he_bss_color_disabled:1;
struct {
int cts, preamble, slot, ht_opmode, isolate;
@@ -228,6 +229,7 @@ struct wpa_driver_nl80211_data {
unsigned int qca_ap_allowed_freqs:1;
unsigned int connect_ext_vendor_cmd_avail:1;
unsigned int support_ap_scan:1;
+ unsigned int update_beacon:1;
u8 extra_bss_membership_selectors[8];
diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
index 01c4b32dc786..282553dbafd8 100644
--- a/src/drivers/driver_nl80211_capa.c
+++ b/src/drivers/driver_nl80211_capa.c
@@ -762,6 +762,10 @@ static void wiphy_info_ext_feature_flags(struct wiphy_info_data *info,
if (ext_feature_isset(ext_features, len,
NL80211_EXT_FEATURE_IEEE8021X_AUTH))
capa->flags2 |= WPA_DRIVER_FLAGS2_802_1X_AUTH;
+
+ if (ext_feature_isset(ext_features, len,
+ NL80211_EXT_FEATURE_UPDATE_BEACON))
+ info->drv->update_beacon = 1;
}
--
2.55.0
More information about the Hostap
mailing list