[openwrt/openwrt] hostapd: preserve vif radio mask for extra bss interfaces

LEDE Commits lede-commits at lists.infradead.org
Mon Jun 23 02:23:34 PDT 2025


nbd pushed a commit to openwrt/openwrt.git, branch main:
https://git.openwrt.org/f940f7c1ac85b07374bf7801e5a7f551a67521ff

commit f940f7c1ac85b07374bf7801e5a7f551a67521ff
Author: Felix Fietkau <nbd at nbd.name>
AuthorDate: Mon Jun 23 11:21:48 2025 +0200

    hostapd: preserve vif radio mask for extra bss interfaces
    
    Fixes status information and scanning on extra BSS interfaces when operating
    on multi-radio devices.
    
    Reported-by: Chad Monroe <chad.monroe at adtran.com>
    Signed-off-by: Felix Fietkau <nbd at nbd.name>
---
 .../hostapd/patches/370-preserve_radio_mask.patch  | 158 +++++++++++++++++++++
 .../patches/463-add-mcast_rate-to-11s.patch        |   4 +-
 .../hostapd/patches/601-ucode_support.patch        |  20 +--
 .../services/hostapd/patches/740-snoop_iface.patch |   4 +-
 ...Implement-APuP-Access-Point-Micro-Peering.patch |   2 +-
 5 files changed, 173 insertions(+), 15 deletions(-)

diff --git a/package/network/services/hostapd/patches/370-preserve_radio_mask.patch b/package/network/services/hostapd/patches/370-preserve_radio_mask.patch
new file mode 100644
index 0000000000..77bcfa8dbb
--- /dev/null
+++ b/package/network/services/hostapd/patches/370-preserve_radio_mask.patch
@@ -0,0 +1,158 @@
+--- a/src/drivers/driver_nl80211.h
++++ b/src/drivers/driver_nl80211.h
+@@ -77,6 +77,7 @@ struct i802_bss {
+ 	u64 wdev_id;
+ 	char ifname[IFNAMSIZ + 1];
+ 	char brname[IFNAMSIZ];
++	u32 radio_mask;
+ 	unsigned int added_if_into_bridge:1;
+ 	unsigned int already_in_bridge:1;
+ 	unsigned int added_bridge:1;
+@@ -325,7 +326,7 @@ send_and_recv_resp(struct wpa_driver_nl8
+ 
+ int nl80211_create_iface(struct wpa_driver_nl80211_data *drv,
+ 			 const char *ifname, enum nl80211_iftype iftype,
+-			 const u8 *addr, int wds,
++			 const u8 *addr, int wds, u32 radio_mask,
+ 			 int (*handler)(struct nl_msg *, void *),
+ 			 void *arg, int use_existing);
+ void nl80211_remove_iface(struct wpa_driver_nl80211_data *drv, int ifidx);
+--- a/src/drivers/driver_nl80211.c
++++ b/src/drivers/driver_nl80211.c
+@@ -755,6 +755,7 @@ struct wiphy_idx_data {
+ 	enum nl80211_iftype nlmode;
+ 	u8 *macaddr;
+ 	u8 use_4addr;
++	u32 radio_mask;
+ };
+ 
+ 
+@@ -780,6 +781,9 @@ static int netdev_info_handler(struct nl
+ 	if (tb[NL80211_ATTR_4ADDR])
+ 		info->use_4addr = nla_get_u8(tb[NL80211_ATTR_4ADDR]);
+ 
++	if (tb[NL80211_ATTR_VIF_RADIO_MASK])
++		info->radio_mask = nla_get_u32(tb[NL80211_ATTR_VIF_RADIO_MASK]);
++
+ 	return NL_SKIP;
+ }
+ 
+@@ -846,6 +850,20 @@ static int nl80211_get_4addr(struct i802
+ }
+ 
+ 
++static u32 nl80211_get_radio_mask(struct i802_bss *bss)
++{
++	struct nl_msg *msg;
++	struct wiphy_idx_data data = {
++		.radio_mask = 0,
++	};
++
++	if (!(msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_GET_INTERFACE)) ||
++	    send_and_recv_resp(bss->drv, msg, netdev_info_handler, &data))
++		return 0;
++	return data.radio_mask;
++}
++
++
+ static int nl80211_register_beacons(struct wpa_driver_nl80211_data *drv,
+ 				    struct nl80211_wiphy_data *w)
+ {
+@@ -6171,7 +6189,7 @@ const char * nl80211_iftype_str(enum nl8
+ static int nl80211_create_iface_once(struct wpa_driver_nl80211_data *drv,
+ 				     const char *ifname,
+ 				     enum nl80211_iftype iftype,
+-				     const u8 *addr, int wds,
++				     const u8 *addr, int wds, u32 radio_mask,
+ 				     int (*handler)(struct nl_msg *, void *),
+ 				     void *arg)
+ {
+@@ -6191,6 +6209,10 @@ static int nl80211_create_iface_once(str
+ 	if (wds && nla_put_u8(msg, NL80211_ATTR_4ADDR, wds))
+ 		goto fail;
+ 
++	if (radio_mask &&
++	    nla_put_u32(msg, NL80211_ATTR_VIF_RADIO_MASK, radio_mask))
++		goto fail;
++
+ 	/*
+ 	 * Tell cfg80211 that the interface belongs to the socket that created
+ 	 * it, and the interface should be deleted when the socket is closed.
+@@ -6246,14 +6268,14 @@ static int nl80211_create_iface_once(str
+ 
+ int nl80211_create_iface(struct wpa_driver_nl80211_data *drv,
+ 			 const char *ifname, enum nl80211_iftype iftype,
+-			 const u8 *addr, int wds,
++			 const u8 *addr, int wds, u32 radio_mask,
+ 			 int (*handler)(struct nl_msg *, void *),
+ 			 void *arg, int use_existing)
+ {
+ 	int ret;
+ 
+-	ret = nl80211_create_iface_once(drv, ifname, iftype, addr, wds, handler,
+-					arg);
++	ret = nl80211_create_iface_once(drv, ifname, iftype, addr, wds, radio_mask,
++					handler, arg);
+ 
+ 	/* if error occurred and interface exists already */
+ 	if (ret < 0 && if_nametoindex(ifname)) {
+@@ -6279,7 +6301,7 @@ int nl80211_create_iface(struct wpa_driv
+ 
+ 		/* Try to create the interface again */
+ 		ret = nl80211_create_iface_once(drv, ifname, iftype, addr,
+-						wds, handler, arg);
++						wds, radio_mask, handler, arg);
+ 	}
+ 
+ 	if (ret >= 0 && is_p2p_net_interface(iftype)) {
+@@ -8619,8 +8641,8 @@ static int i802_set_wds_sta(void *priv,
+ 		if (!if_nametoindex(name)) {
+ 			if (nl80211_create_iface(drv, name,
+ 						 NL80211_IFTYPE_AP_VLAN,
+-						 bss->addr, 1, NULL, NULL, 0) <
+-			    0)
++						 bss->addr, 1, bss->radio_mask,
++						 NULL, NULL, 0) < 0)
+ 				return -1;
+ 
+ 			if (bridge_ifname)
+@@ -8991,7 +9013,8 @@ static int wpa_driver_nl80211_if_add(voi
+ 
+ 		os_memset(&p2pdev_info, 0, sizeof(p2pdev_info));
+ 		ifidx = nl80211_create_iface(drv, ifname, nlmode, addr,
+-					     0, nl80211_wdev_handler,
++					     0, bss->radio_mask,
++					     nl80211_wdev_handler,
+ 					     &p2pdev_info, use_existing);
+ 		if (!p2pdev_info.wdev_id_set || ifidx != 0) {
+ 			wpa_printf(MSG_ERROR, "nl80211: Failed to create a P2P Device interface %s",
+@@ -9008,7 +9031,8 @@ static int wpa_driver_nl80211_if_add(voi
+ 			   (long long unsigned int) p2pdev_info.wdev_id);
+ 	} else {
+ 		ifidx = nl80211_create_iface(drv, ifname, nlmode, addr,
+-					     0, NULL, NULL, use_existing);
++					     0, bss->radio_mask,
++					     NULL, NULL, use_existing);
+ 		if (use_existing && ifidx == -ENFILE) {
+ 			added = 0;
+ 			ifidx = if_nametoindex(ifname);
+@@ -9103,6 +9127,8 @@ static int wpa_driver_nl80211_if_add(voi
+ 			*drv_priv = new_bss;
+ 		nl80211_init_bss(new_bss);
+ 
++		new_bss->radio_mask = nl80211_get_radio_mask(new_bss);
++
+ 		/* Set interface mode to NL80211_IFTYPE_AP */
+ 		if (nl80211_set_mode(new_bss, nlmode))
+ 			return -1;
+--- a/src/drivers/driver_nl80211_monitor.c
++++ b/src/drivers/driver_nl80211_monitor.c
+@@ -98,7 +98,7 @@ static int nl80211_create_monitor_interf
+ 	buf[IFNAMSIZ - 1] = '\0';
+ 
+ 	*ifidx = nl80211_create_iface(drv, buf, NL80211_IFTYPE_MONITOR, NULL,
+-				      0, NULL, NULL, 0);
++				      0, 0, NULL, NULL, 0);
+ 
+ 	if (*ifidx < 0)
+ 		return -1;
diff --git a/package/network/services/hostapd/patches/463-add-mcast_rate-to-11s.patch b/package/network/services/hostapd/patches/463-add-mcast_rate-to-11s.patch
index 917b4ac3b6..262c398015 100644
--- a/package/network/services/hostapd/patches/463-add-mcast_rate-to-11s.patch
+++ b/package/network/services/hostapd/patches/463-add-mcast_rate-to-11s.patch
@@ -29,7 +29,7 @@ Tested-by: Simon Wunderlich <simon.wunderlich at openmesh.com>
  struct wpa_driver_set_key_params {
 --- a/src/drivers/driver_nl80211.c
 +++ b/src/drivers/driver_nl80211.c
-@@ -12269,6 +12269,18 @@ static int nl80211_put_mesh_id(struct nl
+@@ -12295,6 +12295,18 @@ static int nl80211_put_mesh_id(struct nl
  }
  
  
@@ -48,7 +48,7 @@ Tested-by: Simon Wunderlich <simon.wunderlich at openmesh.com>
  static int nl80211_put_mesh_config(struct nl_msg *msg,
  				   struct wpa_driver_mesh_bss_params *params)
  {
-@@ -12330,6 +12342,7 @@ static int nl80211_join_mesh(struct i802
+@@ -12356,6 +12368,7 @@ static int nl80211_join_mesh(struct i802
  	    nl80211_put_basic_rates(msg, params->basic_rates) ||
  	    nl80211_put_mesh_id(msg, params->meshid, params->meshid_len) ||
  	    nl80211_put_beacon_int(msg, params->beacon_int) ||
diff --git a/package/network/services/hostapd/patches/601-ucode_support.patch b/package/network/services/hostapd/patches/601-ucode_support.patch
index 7bf464f2d9..865a01cc98 100644
--- a/package/network/services/hostapd/patches/601-ucode_support.patch
+++ b/package/network/services/hostapd/patches/601-ucode_support.patch
@@ -322,7 +322,7 @@ as adding/removing interfaces.
  	nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err);
  	nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err.err);
  	if (ack_handler_custom) {
-@@ -955,6 +973,7 @@ nl80211_get_wiphy_data_ap(struct i802_bs
+@@ -973,6 +991,7 @@ nl80211_get_wiphy_data_ap(struct i802_bs
  			os_free(w);
  			return NULL;
  		}
@@ -330,7 +330,7 @@ as adding/removing interfaces.
  		nl_cb_set(w->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM,
  			  no_seq_check, NULL);
  		nl_cb_set(w->nl_cb, NL_CB_VALID, NL_CB_CUSTOM,
-@@ -1370,7 +1389,7 @@ static void wpa_driver_nl80211_event_rtm
+@@ -1388,7 +1407,7 @@ static void wpa_driver_nl80211_event_rtm
  		}
  		wpa_printf(MSG_DEBUG, "nl80211: Interface down (%s/%s)",
  			   namebuf, ifname);
@@ -339,7 +339,7 @@ as adding/removing interfaces.
  			wpa_printf(MSG_DEBUG,
  				   "nl80211: Not the main interface (%s) - do not indicate interface down",
  				   drv->first_bss->ifname);
-@@ -1406,7 +1425,7 @@ static void wpa_driver_nl80211_event_rtm
+@@ -1424,7 +1443,7 @@ static void wpa_driver_nl80211_event_rtm
  		}
  		wpa_printf(MSG_DEBUG, "nl80211: Interface up (%s/%s)",
  			   namebuf, ifname);
@@ -348,7 +348,7 @@ as adding/removing interfaces.
  			wpa_printf(MSG_DEBUG,
  				   "nl80211: Not the main interface (%s) - do not indicate interface up",
  				   drv->first_bss->ifname);
-@@ -2052,6 +2071,7 @@ static int wpa_driver_nl80211_init_nl_gl
+@@ -2070,6 +2089,7 @@ static int wpa_driver_nl80211_init_nl_gl
  	genl_family_put(family);
  	nl_cache_free(cache);
  
@@ -356,7 +356,7 @@ as adding/removing interfaces.
  	nl_cb_set(global->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM,
  		  no_seq_check, NULL);
  	nl_cb_set(global->nl_cb, NL_CB_VALID, NL_CB_CUSTOM,
-@@ -2222,6 +2242,7 @@ static int nl80211_init_bss(struct i802_
+@@ -2240,6 +2260,7 @@ static int nl80211_init_bss(struct i802_
  	if (!bss->nl_cb)
  		return -1;
  
@@ -364,7 +364,7 @@ as adding/removing interfaces.
  	nl_cb_set(bss->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM,
  		  no_seq_check, NULL);
  	nl_cb_set(bss->nl_cb, NL_CB_VALID, NL_CB_CUSTOM,
-@@ -8763,6 +8784,7 @@ static void *i802_init(struct hostapd_da
+@@ -8785,6 +8806,7 @@ static void *i802_init(struct hostapd_da
  	char master_ifname[IFNAMSIZ];
  	int ifindex, br_ifindex = 0;
  	int br_added = 0;
@@ -372,7 +372,7 @@ as adding/removing interfaces.
  
  	bss = wpa_driver_nl80211_drv_init(hapd, params->ifname,
  					  params->global_priv, 1,
-@@ -8823,21 +8845,17 @@ static void *i802_init(struct hostapd_da
+@@ -8845,21 +8867,17 @@ static void *i802_init(struct hostapd_da
  	    (params->num_bridge == 0 || !params->bridge[0]))
  		add_ifidx(drv, br_ifindex, drv->ifindex);
  
@@ -404,7 +404,7 @@ as adding/removing interfaces.
  	}
  
  	if (drv->capa.flags2 & WPA_DRIVER_FLAGS2_CONTROL_PORT_RX) {
-@@ -9210,6 +9228,50 @@ static int wpa_driver_nl80211_if_remove(
+@@ -9236,6 +9254,50 @@ static int wpa_driver_nl80211_if_remove(
  	return 0;
  }
  
@@ -455,7 +455,7 @@ as adding/removing interfaces.
  
  static int cookie_handler(struct nl_msg *msg, void *arg)
  {
-@@ -11088,6 +11150,37 @@ static bool nl80211_is_drv_shared(void *
+@@ -11114,6 +11176,37 @@ static bool nl80211_is_drv_shared(void *
  #endif /* CONFIG_IEEE80211BE */
  
  
@@ -493,7 +493,7 @@ as adding/removing interfaces.
  static int driver_nl80211_send_mlme(void *priv, const u8 *data,
  				    size_t data_len, int noack,
  				    unsigned int freq,
-@@ -14813,6 +14906,8 @@ const struct wpa_driver_ops wpa_driver_n
+@@ -14839,6 +14932,8 @@ const struct wpa_driver_ops wpa_driver_n
  	.set_acl = wpa_driver_nl80211_set_acl,
  	.if_add = wpa_driver_nl80211_if_add,
  	.if_remove = driver_nl80211_if_remove,
diff --git a/package/network/services/hostapd/patches/740-snoop_iface.patch b/package/network/services/hostapd/patches/740-snoop_iface.patch
index 1933247f8c..6dc62a5328 100644
--- a/package/network/services/hostapd/patches/740-snoop_iface.patch
+++ b/package/network/services/hostapd/patches/740-snoop_iface.patch
@@ -123,7 +123,7 @@ untagged DHCP packets
  	 * get_wowlan - Get wake-on-wireless status
 --- a/src/drivers/driver_nl80211.c
 +++ b/src/drivers/driver_nl80211.c
-@@ -12789,7 +12789,7 @@ static const char * drv_br_net_param_str
+@@ -12815,7 +12815,7 @@ static const char * drv_br_net_param_str
  
  
  static int wpa_driver_br_set_net_param(void *priv, enum drv_br_net_param param,
@@ -132,7 +132,7 @@ untagged DHCP packets
  {
  	struct i802_bss *bss = priv;
  	char path[128];
-@@ -12815,8 +12815,11 @@ static int wpa_driver_br_set_net_param(v
+@@ -12841,8 +12841,11 @@ static int wpa_driver_br_set_net_param(v
  			return -EINVAL;
  	}
  
diff --git a/package/network/services/hostapd/patches/780-Implement-APuP-Access-Point-Micro-Peering.patch b/package/network/services/hostapd/patches/780-Implement-APuP-Access-Point-Micro-Peering.patch
index 72c48a3d00..5f50f46869 100644
--- a/package/network/services/hostapd/patches/780-Implement-APuP-Access-Point-Micro-Peering.patch
+++ b/package/network/services/hostapd/patches/780-Implement-APuP-Access-Point-Micro-Peering.patch
@@ -429,7 +429,7 @@ Hotfix-by: Sebastian Gottschall https://github.com/mirror/dd-wrt/commit/0c3001a6
  	 * send_action - Transmit an Action frame
 --- a/src/drivers/driver_nl80211.c
 +++ b/src/drivers/driver_nl80211.c
-@@ -8615,25 +8615,15 @@ static int have_ifidx(struct wpa_driver_
+@@ -8637,25 +8637,15 @@ static int have_ifidx(struct wpa_driver_
  
  
  static int i802_set_wds_sta(void *priv, const u8 *addr, int aid, int val,




More information about the lede-commits mailing list