[RFC v2 05/99] NAN: Keep a list of known peers and their attributes

Andrei Otcheretianski andrei.otcheretianski at intel.com
Tue Dec 23 03:51:09 PST 2025


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

Keep a list of known peers as this would be needed to support
future flows, e.g., NAN Data Path establishment.

This patch doesn't process the attributes associated with the
added peer. This would be done in later patches.

Signed-off-by: Ilan Peer <ilan.peer at intel.com>
---
 src/nan/nan.c                   | 101 ++++++++++++++++++++++++++++++++
 src/nan/nan.h                   |   3 +
 src/nan/nan_i.h                 |  23 ++++++++
 wpa_supplicant/nan_supplicant.c |  11 +++-
 4 files changed, 137 insertions(+), 1 deletion(-)

diff --git a/src/nan/nan.c b/src/nan/nan.c
index 0a3e1c8588..6a7e94714e 100644
--- a/src/nan/nan.c
+++ b/src/nan/nan.c
@@ -11,6 +11,7 @@
 #include "nan.h"
 #include "nan_i.h"
 
+#define NAN_MAX_PEERS 32
 
 struct nan_data * nan_init(const struct nan_config *cfg)
 {
@@ -29,12 +30,37 @@ struct nan_data * nan_init(const struct nan_config *cfg)
 		return NULL;
 	}
 
+	dl_list_init(&nan->peer_list);
+
 	wpa_printf(MSG_DEBUG, "NAN: initialized");
 
 	return nan;
 }
 
 
+static void nan_del_peer(struct nan_data *nan, struct nan_peer *peer)
+{
+	if (!peer)
+		return;
+
+	wpa_printf(MSG_DEBUG, "NAN: Removing peer: " MACSTR,
+		   MAC2STR(peer->nmi_addr));
+
+	dl_list_del(&peer->list);
+	os_free(peer);
+}
+
+
+static void nan_peer_clear_all(struct nan_data *nan)
+{
+	struct nan_peer *peer, *n_peer;
+
+	dl_list_for_each_safe(peer, n_peer, &nan->peer_list,
+			      struct nan_peer, list)
+		nan_del_peer(nan, peer);
+}
+
+
 void nan_deinit(struct nan_data *nan)
 {
 	wpa_printf(MSG_DEBUG, "NAN: deinit");
@@ -95,6 +121,7 @@ void nan_flush(struct nan_data *nan)
 	}
 
 	nan->nan_started = 0;
+	nan_peer_clear_all(nan);
 }
 
 
@@ -110,3 +137,77 @@ void nan_stop(struct nan_data *nan)
 	nan_flush(nan);
 	nan->cfg->stop(nan->cfg->cb_ctx);
 }
+
+
+struct nan_peer * nan_get_peer(struct nan_data *nan, const u8 *addr)
+{
+	struct nan_peer *peer;
+
+	dl_list_for_each(peer, &nan->peer_list, struct nan_peer, list) {
+		if (os_memcmp(peer->nmi_addr, addr, ETH_ALEN) == 0)
+			return peer;
+	}
+
+	return NULL;
+}
+
+
+static struct nan_peer *nan_alloc_peer(struct nan_data *nan)
+{
+	struct nan_peer *peer, *oldest = NULL;
+	size_t count = 0;
+
+	dl_list_for_each(peer, &nan->peer_list, struct nan_peer, list) {
+		count++;
+		if (!oldest ||
+		    os_reltime_before(&peer->last_seen, &oldest->last_seen))
+			oldest = peer;
+	}
+
+	if (count >= NAN_MAX_PEERS && oldest) {
+		wpa_printf(MSG_DEBUG,
+			   "NAN: Remove peer=" MACSTR " to make room",
+			   MAC2STR(oldest->nmi_addr));
+
+		nan_del_peer(nan, oldest);
+	}
+
+	peer = os_zalloc(sizeof(*peer));
+	if (!peer)
+		return NULL;
+
+	dl_list_add(&nan->peer_list, &peer->list);
+	return peer;
+}
+
+
+int nan_add_peer(struct nan_data *nan, const u8 *addr,
+		 const u8 *device_attrs, size_t device_attrs_len)
+{
+	struct nan_peer *peer;
+
+	/* Allow adding peer devices even if NAN was not started, to support
+	 * discovery during USD etc.
+	 */
+	if (!nan)
+		return -1;
+
+	/* TODO: parse the device attributes to update the peer information */
+	if (!device_attrs || !device_attrs_len) {
+		wpa_printf(MSG_DEBUG,
+			   "NAN: Ignore add_peer with no device attributes");
+		return -1;
+	}
+
+	peer = nan_get_peer(nan, addr);
+	if (!peer) {
+		peer = nan_alloc_peer(nan);
+		if (!peer)
+			return -1;
+
+		os_memcpy(peer->nmi_addr, addr, ETH_ALEN);
+	}
+
+	os_get_reltime(&peer->last_seen);
+	return 0;
+}
diff --git a/src/nan/nan.h b/src/nan/nan.h
index 597d510691..d6025a6b09 100644
--- a/src/nan/nan.h
+++ b/src/nan/nan.h
@@ -43,4 +43,7 @@ int nan_update_config(struct nan_data *nan, struct nan_cluster_config *config);
 void nan_stop(struct nan_data *nan);
 void nan_flush(struct nan_data *nan);
 
+int nan_add_peer(struct nan_data *nan, const u8 *addr,
+		 const u8 *device_attrs, size_t device_attrs_len);
+
 #endif /* NAN_H */
diff --git a/src/nan/nan_i.h b/src/nan/nan_i.h
index ade4229f70..1efed82ff5 100644
--- a/src/nan/nan_i.h
+++ b/src/nan/nan_i.h
@@ -9,11 +9,34 @@
 #ifndef NAN_I_H
 #define NAN_I_H
 
+#include "list.h"
+
 struct nan_config;
 
+/**
+ * struct nan_peer - Represents a known NAN peer
+ * @list: List node for linking peers.
+ * @nmi_addr: NAN MAC address of the peer.
+ * @last_seen: Timestamp of the last time this peer was seen.
+ */
+struct nan_peer {
+	struct dl_list list;
+	u8 nmi_addr[ETH_ALEN];
+	struct os_reltime last_seen;
+};
+
+/**
+ * struct nan_data - Internal data structure for NAN
+ *
+ * @cfg: Pointer to the NAN configuration structure.
+ * @nan_started: Flag indicating if NAN has been started.
+ * @peer_list: List of known peers.
+ */
 struct nan_data {
 	struct nan_config *cfg;
 	u8 nan_started:1;
+	struct dl_list peer_list;
 };
 
+struct nan_peer * nan_get_peer(struct nan_data *nan, const u8 *addr);
 #endif
diff --git a/wpa_supplicant/nan_supplicant.c b/wpa_supplicant/nan_supplicant.c
index 56d90b7f1f..ce972a0fdf 100644
--- a/wpa_supplicant/nan_supplicant.c
+++ b/wpa_supplicant/nan_supplicant.c
@@ -675,9 +675,18 @@ void wpas_nan_de_rx_sdf(struct wpa_supplicant *wpa_s, const u8 *src,
 			unsigned int freq, const u8 *buf, size_t len,
 			int rssi)
 {
+	bool store_peer = false;
+
 	if (!wpa_s->nan_de)
 		return;
-	nan_de_rx_sdf(wpa_s->nan_de, src, a3, freq, buf, len, rssi);
+
+	store_peer = nan_de_rx_sdf(wpa_s->nan_de, src, a3, freq, buf,
+				   len, rssi);
+
+	if (!wpas_nan_ready(wpa_s) || !store_peer)
+		return;
+
+	nan_add_peer(wpa_s->nan, src, buf, len);
 }
 
 
-- 
2.49.0




More information about the Hostap mailing list