[PATCH v4 05/20] nl80211: Factor out global event BSS lookup and add PD wdev event routing
Kavita Kavita
kavita.kavita at oss.qualcomm.com
Fri May 22 18:23:37 PDT 2026
From: Veerendranath Jakkam <vjakkam at qti.qualcomm.com>
Introduce nl80211_get_event_bss() to centralize BSS selection for
process_global_event(). The helper performs an exact ifindex match
first, then checks if the wdev_id matches the active PD wdev so that
events arriving on the PD wdev are delivered to pd_bss which is not
part of the regular BSS list, and finally falls back to the existing
bridge/wiphy/wdev matching rules. The wiphy_idx fallback applies only
when wdev_id is not set so that wdev-specific events match exclusively
by exact wdev_id.
wdev_id is set during creation for wdev-only interfaces (P2P Device,
NAN, PD). For netdev interfaces it is not set via if_add_wdevid, so
fetch it from the kernel via GET_INTERFACE and store it in the BSS.
This ensures events that carry NL80211_ATTR_WDEV without
NL80211_ATTR_IFINDEX are routed by exact wdev_id match.
Signed-off-by: Veerendranath Jakkam <vjakkam at qti.qualcomm.com>
---
src/drivers/driver_nl80211.c | 31 ++++++++++
src/drivers/driver_nl80211_event.c | 94 ++++++++++++++++--------------
2 files changed, 81 insertions(+), 44 deletions(-)
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 53e24262b..a8c4c61a3 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -891,6 +891,8 @@ struct wiphy_idx_data {
enum nl80211_iftype nlmode;
u8 *macaddr;
u8 use_4addr;
+ u64 wdev_id;
+ int wdev_id_set;
};
@@ -916,6 +918,11 @@ static int netdev_info_handler(struct nl_msg *msg, void *arg)
if (tb[NL80211_ATTR_4ADDR])
info->use_4addr = nla_get_u8(tb[NL80211_ATTR_4ADDR]);
+ if (tb[NL80211_ATTR_WDEV]) {
+ info->wdev_id = nla_get_u64(tb[NL80211_ATTR_WDEV]);
+ info->wdev_id_set = 1;
+ }
+
return NL_SKIP;
}
@@ -3599,6 +3606,30 @@ wpa_driver_nl80211_finish_drv_init(struct i802_bss *bss, const u8 *set_addr,
bss->wdev_id = drv->global->if_add_wdevid;
bss->wdev_id_set = drv->global->if_add_wdevid_set;
+ /*
+ * wdev_id is set for wdev-only interfaces during creation. For netdev
+ * interfaces it is not set, so fetch it via GET_INTERFACE to allow
+ * event routing by exact wdev_id match.
+ */
+ if (!bss->wdev_id_set) {
+ struct nl_msg *msg;
+ struct wiphy_idx_data info;
+
+ os_memset(&info, 0, sizeof(info));
+ msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_GET_INTERFACE);
+ if (msg &&
+ send_and_recv_resp(drv, msg, netdev_info_handler,
+ &info) == 0 &&
+ info.wdev_id_set) {
+ bss->wdev_id = info.wdev_id;
+ bss->wdev_id_set = 1;
+ wpa_printf(MSG_DEBUG,
+ "nl80211: %s wdev_id=0x%llx",
+ bss->ifname,
+ (unsigned long long) bss->wdev_id);
+ }
+ }
+
bss->if_dynamic = drv->ifindex == drv->global->if_add_ifindex;
bss->if_dynamic = bss->if_dynamic || drv->global->if_add_wdevid_set;
if (first)
diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c
index f1a71bf96..b51ba9449 100644
--- a/src/drivers/driver_nl80211_event.c
+++ b/src/drivers/driver_nl80211_event.c
@@ -4856,13 +4856,51 @@ static bool nl80211_drv_in_list(struct nl80211_global *global,
}
+static struct i802_bss *
+nl80211_get_event_bss(struct wpa_driver_nl80211_data *drv, int ifidx,
+ int wiphy_idx_rx, int wiphy_idx_set,
+ u64 wdev_id, int wdev_id_set)
+{
+ struct i802_bss *bss;
+ int wiphy_idx = -1;
+
+ if (ifidx != -1) {
+ for (bss = drv->first_bss; bss; bss = bss->next) {
+ if (ifidx == bss->ifindex)
+ return bss;
+ }
+ }
+
+#ifdef CONFIG_PR
+ if (wdev_id_set && drv->pd_bss && drv->pd_bss->wdev_id_set &&
+ wdev_id == drv->pd_bss->wdev_id)
+ return drv->pd_bss;
+#endif /* CONFIG_PR */
+
+ for (bss = drv->first_bss; bss; bss = bss->next) {
+ if (wiphy_idx_set)
+ wiphy_idx = nl80211_get_wiphy_index(bss);
+ if ((ifidx == -1 && !wiphy_idx_set && !wdev_id_set) ||
+ (bss->br_ifindex > 0 &&
+ nl80211_has_ifidx(drv, bss->br_ifindex, ifidx)) ||
+ (!wdev_id_set && wiphy_idx_set &&
+ wiphy_idx == wiphy_idx_rx) ||
+ (wdev_id_set && bss->wdev_id_set &&
+ wdev_id == bss->wdev_id))
+ return bss;
+ }
+
+ return NULL;
+}
+
+
int process_global_event(struct nl_msg *msg, void *arg)
{
struct nl80211_global *global = arg;
struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
struct nlattr *tb[NL80211_ATTR_MAX + 1];
struct wpa_driver_nl80211_data *drv, *tmp;
- int ifidx = -1, wiphy_idx = -1, wiphy_idx_rx = -1;
+ int ifidx = -1, wiphy_idx_rx = -1;
struct i802_bss *bss;
u64 wdev_id = 0;
int wdev_id_set = 0;
@@ -4915,50 +4953,18 @@ int process_global_event(struct nl_msg *msg, void *arg)
struct wpa_driver_nl80211_data, list) {
unsigned int unique_drv_id = drv->unique_drv_id;
- /* First pass: Check for exact ifindex match for events directed
- * to a specific interface to avoid incorrect selection based on
- * matching rules for bridged interfaces. */
- if (ifidx != -1) {
- for (bss = drv->first_bss; bss; bss = bss->next) {
- if (ifidx == bss->ifindex) {
- do_process_drv_event(bss, gnlh->cmd,
- tb);
- return NL_SKIP;
- }
- }
- }
+ bss = nl80211_get_event_bss(drv, ifidx, wiphy_idx_rx,
+ wiphy_idx_set, wdev_id,
+ wdev_id_set);
+ if (!bss)
+ continue;
- /* Second pass: Check all other conditions including bridge */
- for (bss = drv->first_bss; bss; bss = bss->next) {
- if (wiphy_idx_set)
- wiphy_idx = nl80211_get_wiphy_index(bss);
- if ((ifidx == -1 && !wiphy_idx_set && !wdev_id_set) ||
- (bss->br_ifindex > 0 &&
- nl80211_has_ifidx(drv, bss->br_ifindex, ifidx)) ||
- (wiphy_idx_set && wiphy_idx == wiphy_idx_rx) ||
- (wdev_id_set && bss->wdev_id_set &&
- wdev_id == bss->wdev_id)) {
- processed = true;
- do_process_drv_event(bss, gnlh->cmd, tb);
- /* There are two types of events that may need
- * to be delivered to multiple interfaces:
- * 1. Events for a wiphy, as it can have
- * multiple interfaces.
- * 2. "Global" events, like
- * NL80211_CMD_REG_CHANGE.
- *
- * Terminate early only if the event is directed
- * to a specific interface or wdev. */
- if (ifidx != -1 || wdev_id_set)
- return NL_SKIP;
- /* The driver instance could have been removed,
- * e.g., due to NL80211_CMD_RADAR_DETECT event,
- * so need to stop the loop if that has
- * happened. */
- if (!nl80211_drv_in_list(global, unique_drv_id))
- break;
- }
- }
+ processed = true;
+ do_process_drv_event(bss, gnlh->cmd, tb);
+ if (ifidx != -1 || wdev_id_set)
+ return NL_SKIP;
+ if (!nl80211_drv_in_list(global, unique_drv_id))
+ break;
}
if (processed)
--
2.34.1
More information about the Hostap
mailing list