[PATCH 2/7] nl80211: Add NAN Instant Communication (IC) support

Andrei Otcheretianski andrei.otcheretianski at intel.com
Thu Oct 8 09:54:33 PDT 2026


From: Ilan Peer <ilan.peer at intel.com>

Parse the NL80211_NAN_CAPA_INSTANT_COMM driver capability and, when
Instant Communication is enabled, set NL80211_NAN_CONF_INSTANT_COMM
in the NAN configuration.

Since the kernel requires that when Instant Communication is set, a
discovery beacon interval has to be explicitly configured, validate
it.

The kernel would also reject the configuration if Instant
Communication is not supported, so validate the driver capability as
well.

Subscribe to beacon frames on the NAN interface so NAN DE could
process NAN beacons while in instant communication mode.

Signed-off-by: Ilan Peer <ilan.peer at intel.com>
---
 src/drivers/driver_nl80211.c      | 82 ++++++++++++++++++++++++++++++-
 src/drivers/driver_nl80211.h      |  1 +
 src/drivers/driver_nl80211_capa.c |  8 +++
 3 files changed, 90 insertions(+), 1 deletion(-)

diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index d5506ad6ba..e2029c2a97 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -3242,6 +3242,9 @@ static void nl80211_mgmt_unsubscribe(struct i802_bss *bss, const char *reason)
 	wpa_printf(MSG_DEBUG, "nl80211: Unsubscribe mgmt frames handle %p "
 		   "(%s)", bss->nl_mgmt, reason);
 	nl80211_destroy_eloop_handle(&bss->nl_mgmt, 0);
+#ifdef CONFIG_NAN
+	bss->drv->nan_beacons_registered = 0;
+#endif /* CONFIG_NAN */
 
 	nl80211_put_wiphy_data_ap(bss);
 }
@@ -15856,6 +15859,37 @@ wpa_driver_get_multi_hw_info(void *priv, unsigned int *num_multi_hws)
 
 #ifdef CONFIG_NAN
 
+static int nl80211_nan_register_beacons(struct i802_bss *bss)
+{
+	u16 type = (WLAN_FC_TYPE_MGMT << 2) | (WLAN_FC_STYPE_BEACON << 4);
+	struct nl_sock *handle;
+
+	if (bss->drv->nan_beacons_registered)
+		return 0;
+
+	if (!(bss->drv->capa.nan_capa.drv_flags &
+	      WPA_DRIVER_FLAGS_NAN_SUPPORT_USERSPACE_DE))
+		return 0;
+
+	if (!bss->nl_mgmt) {
+		wpa_printf(MSG_DEBUG,
+			   "nl80211: No mgmt frames handle for NAN beacons");
+		return -1;
+	}
+
+	handle = (void *)(((intptr_t)bss->nl_mgmt) ^ ELOOP_SOCKET_INVALID);
+
+	if (nl80211_register_frame(bss, handle, type, NULL, 0, false)) {
+		wpa_printf(MSG_INFO,
+			   "nl80211: Failed to subscribe to NAN beacons");
+		return -1;
+	}
+
+	bss->drv->nan_beacons_registered = 1;
+	return 0;
+}
+
+
 static int nl80211_nan_config(struct i802_bss *bss,
 			      struct wpa_driver_nl80211_data *drv,
 			      const struct nan_cluster_config *params,
@@ -15864,6 +15898,7 @@ static int nl80211_nan_config(struct i802_bss *bss,
 	struct nl_msg *msg;
 	struct nlattr *conf, *bands_conf, *band;
 	u32 bands = 0;
+	int ret;
 
 	if (params->dual_band > 1)
 		return -EINVAL;
@@ -15881,6 +15916,21 @@ static int nl80211_nan_config(struct i802_bss *bss,
 		}
 	}
 
+	if (params->instant_comm) {
+		if (!(drv->capa.nan_capa.drv_flags &
+		      WPA_DRIVER_FLAGS_NAN_SUPPORT_INSTANT_COMM)) {
+			wpa_printf(MSG_INFO,
+				   "nl80211: Driver doesn't support NAN instant communication");
+			return -EINVAL;
+		}
+
+		if (!params->discovery_beacon_interval) {
+			wpa_printf(MSG_INFO,
+				   "nl80211: NAN instant communication requires a discovery beacon interval");
+			return -EINVAL;
+		}
+	}
+
 	msg = nl80211_cmd_msg(bss, 0, cmd);
 	if (!msg || nla_put_u8(msg, NL80211_ATTR_NAN_MASTER_PREF,
 			       params->master_pref) ||
@@ -15926,6 +15976,10 @@ static int nl80211_nan_config(struct i802_bss *bss,
 		       params->discovery_beacon_interval))
 		goto fail;
 
+	if (params->instant_comm &&
+	    nla_put_flag(msg, NL80211_NAN_CONF_INSTANT_COMM))
+		goto fail;
+
 	bands_conf = nla_nest_start(msg, NL80211_NAN_CONF_BAND_CONFIGS);
 	if (!bands_conf)
 		goto fail;
@@ -15985,7 +16039,33 @@ static int nl80211_nan_config(struct i802_bss *bss,
 
 	nla_nest_end(msg, conf);
 
-	return send_and_recv_resp(drv, msg, NULL, NULL);
+	ret = send_and_recv_resp(drv, msg, NULL, NULL);
+	if (ret < 0)
+		return ret;
+
+	/*
+	 * Beacons are needed to support service discovery when Instant
+	 * Communication is enabled.
+	 */
+	if (params->instant_comm && nl80211_nan_register_beacons(bss) < 0) {
+		wpa_printf(MSG_DEBUG,
+			   "nl80211: Failed to register NAN beacons");
+
+		/*
+		 * If this is the first time the kernel is configured, stop NAN.
+		 * Otherwise, the NAN operation would continue with Instant
+		 * communication enabled, but an error would be reported to the
+		 * caller.
+		 */
+		if (!drv->nan_started) {
+			drv->nan_started = 1;
+			nl80211_nan_stop(bss);
+		}
+
+		return -1;
+	}
+
+	return 0;
 fail:
 	nlmsg_free(msg);
 	return -1;
diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h
index d612e6d352..aa73023c75 100644
--- a/src/drivers/driver_nl80211.h
+++ b/src/drivers/driver_nl80211.h
@@ -292,6 +292,7 @@ struct wpa_driver_nl80211_data {
 
 #ifdef CONFIG_NAN
 	unsigned int nan_started:1;
+	unsigned int nan_beacons_registered:1;
 #endif /* CONFIG_NAN */
 #ifdef CONFIG_PR
 	struct i802_bss *pd_bss; /* PD wdev; not in the BSS list */
diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
index 01c4b32dc7..ae38d8317d 100644
--- a/src/drivers/driver_nl80211_capa.c
+++ b/src/drivers/driver_nl80211_capa.c
@@ -994,6 +994,7 @@ static void wiphy_info_nan_capa_handler(struct wpa_driver_capa *capa,
 		nan_capa_policy[NL80211_NAN_CAPABILITIES_MAX + 1] = {
 		[NL80211_NAN_CAPA_CONFIGURABLE_SYNC] = { .type = NLA_FLAG },
 		[NL80211_NAN_CAPA_USERSPACE_DE] = { .type = NLA_FLAG },
+		[NL80211_NAN_CAPA_INSTANT_COMM] = { .type = NLA_FLAG },
 	};
 	struct nlattr *tb_nan_capa[NL80211_NAN_CAPABILITIES_MAX + 1];
 	static struct nla_policy
@@ -1052,6 +1053,13 @@ static void wiphy_info_nan_capa_handler(struct wpa_driver_capa *capa,
 			WPA_DRIVER_FLAGS_NAN_SUPPORT_USERSPACE_DE;
 	}
 
+	if (tb_nan_capa[NL80211_NAN_CAPA_INSTANT_COMM]) {
+		wpa_printf(MSG_DEBUG,
+			   "nl80211: NAN instant communication is supported");
+		capa->nan_capa.drv_flags |=
+			WPA_DRIVER_FLAGS_NAN_SUPPORT_INSTANT_COMM;
+	}
+
 	if (tb_nan_capa[NL80211_NAN_CAPA_MAX_CHANNEL_SWITCH_TIME])
 		capa->nan_capa.max_channel_switch_time =
 			nla_get_u16(tb_nan_capa[NL80211_NAN_CAPA_MAX_CHANNEL_SWITCH_TIME]);
-- 
2.53.0




More information about the Hostap mailing list