[RFC v2 91/99] NAN: Configure peer NMI station and schedule
Andrei Otcheretianski
andrei.otcheretianski at intel.com
Tue Dec 23 03:52:35 PST 2025
Add a new callback for peer schedule configuration and call it during
NDL establishment (as peer schedule may change while NDL is being
negotiated).
Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski at intel.com>
---
src/nan/nan.c | 78 ++++++++++++++++++++++++++++++++++++--
src/nan/nan.h | 20 ++++++++++
src/nan/nan_i.h | 2 +
src/nan/nan_module_tests.c | 45 ++++++++++++++++++++--
src/nan/nan_ndl.c | 7 ++++
5 files changed, 145 insertions(+), 7 deletions(-)
diff --git a/src/nan/nan.c b/src/nan/nan.c
index d64ae71aee..8703572794 100644
--- a/src/nan/nan.c
+++ b/src/nan/nan.c
@@ -1141,7 +1141,8 @@ static bool nan_ndp_supported(struct nan_data *nan)
if (nan->cfg->ndp_action_notif && nan->cfg->ndp_connected &&
nan->cfg->ndp_disconnected &&
nan->cfg->send_naf && nan->cfg->get_chans &&
- nan->cfg->is_valid_publish_id)
+ nan->cfg->is_valid_publish_id &&
+ nan->cfg->set_peer_schedule)
return true;
wpa_printf(MSG_DEBUG, "NAN: NDP operations are not supported");
@@ -1149,6 +1150,56 @@ static bool nan_ndp_supported(struct nan_data *nan)
}
+static void nan_peer_get_committed_avail(struct nan_data *nan,
+ struct nan_peer *peer,
+ struct nan_peer_schedule *sched);
+
+
+static int nan_configure_peer_schedule(struct nan_data *nan,
+ struct nan_peer *peer)
+{
+ int ret;
+ struct nan_dev_capa_entry *cur;
+ struct nan_device_capabilities *capa = NULL;
+ struct nan_peer_schedule sched;
+
+ wpa_printf(MSG_DEBUG, "NAN: Configure peer schedule");
+
+ dl_list_for_each(cur, &peer->info.dev_capa,
+ struct nan_dev_capa_entry, list) {
+ /*
+ * Take the first one, as both CDW and channel switch time are
+ * identical across all attributes
+ */
+ capa = &cur->capa;
+ break;
+ }
+
+ if (!capa) {
+ wpa_printf(MSG_DEBUG,
+ "NAN: Cannot configure peer NMI STA - no device capabilities");
+ return -1;
+ }
+
+ os_memset(&sched, 0, sizeof(sched));
+ nan_peer_get_committed_avail(nan, peer, &sched);
+
+ ret = nan->cfg->set_peer_schedule(nan->cfg->cb_ctx, peer->nmi_addr,
+ !peer->configured, capa->cdw_info,
+ peer->info.seq_id,
+ capa->channel_switch_time, &sched,
+ NULL);
+ if (ret) {
+ wpa_printf(MSG_DEBUG,
+ "NAN: Failed to set peer schedule");
+ return ret;
+ }
+
+ peer->configured = true;
+ return 0;
+}
+
+
static void nan_peer_state_timeout(void *eloop_ctx, void *timeout_ctx)
{
struct nan_data *nan = eloop_ctx;
@@ -1381,8 +1432,8 @@ static int nan_action_rx_ndp(struct nan_data *nan, struct nan_peer *peer,
if (peer->ndp_setup.state == NAN_NDP_STATE_DONE &&
peer->ndl->state == NAN_NDL_STATE_DONE) {
wpa_printf(MSG_DEBUG, "NAN: NAF: NDP setup done");
-
- if (nan_ndp_connected(nan, peer))
+ if (nan_configure_peer_schedule(nan, peer) ||
+ nan_ndp_connected(nan, peer))
nan_ndp_disconnected(nan, peer,
NAN_REASON_UNSPECIFIED_REASON);
return 0;
@@ -1561,7 +1612,8 @@ int nan_tx_status(struct nan_data *nan, const u8 *dst, const u8 *data,
peer->ndl->state == NAN_NDL_STATE_DONE) {
wpa_printf(MSG_DEBUG, "NAN: TX status: NDP setup done");
- if (nan_ndp_connected(nan, peer))
+ if (nan_configure_peer_schedule(nan, peer) ||
+ nan_ndp_connected(nan, peer))
nan_ndp_disconnected(nan, peer,
NAN_REASON_UNSPECIFIED_REASON);
}
@@ -1601,6 +1653,12 @@ int nan_handle_ndp_setup(struct nan_data *nan, struct nan_ndp_params *params)
naf_oui = NAN_SUBTYPE_DATA_PATH_REQUEST;
timeout = NAN_NDP_SETUP_TIMEOUT_LONG;
+ ret = nan_configure_peer_schedule(nan, peer);
+ if (ret) {
+ nan_ndp_setup_stop(nan, peer);
+ return ret;
+ }
+
break;
case NAN_NDP_ACTION_RESP:
/*
@@ -1616,6 +1674,12 @@ int nan_handle_ndp_setup(struct nan_data *nan, struct nan_ndp_params *params)
if (peer->ndp_setup.status != NAN_NDP_STATUS_REJECTED) {
ret = nan_ndl_setup(nan, peer, params);
+ if (!ret) {
+ ret = nan_configure_peer_schedule(nan, peer);
+ if (ret)
+ peer->ndl->send_naf_on_error = 1;
+ }
+
if (ret) {
if (peer->ndl && peer->ndl->send_naf_on_error) {
nan_ndp_setup_failure(nan, peer,
@@ -1635,6 +1699,12 @@ int nan_handle_ndp_setup(struct nan_data *nan, struct nan_ndp_params *params)
break;
case NAN_NDP_ACTION_CONF:
ret = nan_ndl_setup(nan, peer, params);
+ if (!ret) {
+ ret = nan_configure_peer_schedule(nan, peer);
+ if (ret)
+ peer->ndl->send_naf_on_error = 1;
+ }
+
if (ret) {
if (peer->ndl && peer->ndl->send_naf_on_error) {
nan_ndp_setup_failure(nan, peer,
diff --git a/src/nan/nan.h b/src/nan/nan.h
index 40d870e46c..14b8525ca7 100644
--- a/src/nan/nan.h
+++ b/src/nan/nan.h
@@ -501,6 +501,26 @@ struct nan_config {
* instance ID
*/
bool (*is_valid_publish_id)(void *ctx, u8 instance_id, u8 *service_id);
+
+ /**
+ * set_peer_schedule - Configure peer schedule
+ *
+ * @ctx: Callback context from cb_ctx
+ * @nmi_addr: NAN Management Interface address of the peer
+ * @new_sta: Indicates whether this is a new STA (true) or an existing
+ * STA that is being re-configured (false).
+ * @cdw: Committed DW information (from device capabilities)
+ * @sequence_id: Schedule sequence ID
+ * @max_channel_switch_time: Maximum channel switch time
+ * @sched: Peer schedule information; can be NULL
+ * @ulw_elems: ULW elements buffer; can be NULL
+ * Returns: 0 on success, -1 on failure
+ */
+ int (*set_peer_schedule)(void *ctx, const u8 *nmi_addr, bool new_sta,
+ u16 cdw, u8 sequence_id,
+ u16 max_channel_switch_time,
+ const struct nan_peer_schedule *sched,
+ const struct wpabuf *ulw_elems);
};
struct nan_data * nan_init(const struct nan_config *cfg);
diff --git a/src/nan/nan_i.h b/src/nan/nan_i.h
index fec1f6cfcd..aa34b6658f 100644
--- a/src/nan/nan_i.h
+++ b/src/nan/nan_i.h
@@ -403,6 +403,7 @@ struct nan_ndl {
* struct nan_peer - Represents a known NAN peer
* @list: List node for linking peers.
* @nmi_addr: NAN MAC address of the peer.
+ * @configured: Indicates if the peer has been configured to the device.
* @last_seen: Timestamp of the last time this peer was seen.
* @info: Information about the peer.
* @ndps: List of NDPs associated with this peer.
@@ -413,6 +414,7 @@ struct nan_ndl {
struct nan_peer {
struct dl_list list;
u8 nmi_addr[ETH_ALEN];
+ bool configured;
struct os_reltime last_seen;
struct nan_peer_info info;
diff --git a/src/nan/nan_module_tests.c b/src/nan/nan_module_tests.c
index 164982b5d3..7d86ffaebc 100644
--- a/src/nan/nan_module_tests.c
+++ b/src/nan/nan_module_tests.c
@@ -863,6 +863,28 @@ static bool nan_test_is_valid_publish_id_cb(void *ctx, u8 instance_id,
return true;
}
+/*
+ * nan_test_set_peer_schedule_cb - Set peer schedule callback
+ *
+ * @ctx: Pointer to &struct nan_device
+ * @sched: Pointer to &struct nan_peer_schedule to be filled
+ */
+static int
+nan_test_set_peer_schedule_cb(void *ctx, const u8 *nmi_addr, bool new_sta,
+ u16 cdw, u8 sequence_id,
+ u16 max_channel_switch_time,
+ const struct nan_peer_schedule *sched,
+ const struct wpabuf *ulw_elems)
+{
+ struct nan_device *dev = (struct nan_device *)ctx;
+
+ DEV_NOT_INIT_ERR(dev);
+
+ wpa_printf(MSG_INFO, "%s: %s: Enter", dev->name, __func__);
+ wpa_printf(MSG_INFO, "%s: nmi_addr=" MACSTR " new_sta=%d cdw=%u sequence_id=%u max_channel_switch_time=%u",
+ dev->name, MAC2STR(nmi_addr), new_sta, cdw, sequence_id, max_channel_switch_time);
+ return 0;
+}
/*
* nan_test_dev_init - Initialize a test device instance
@@ -885,6 +907,7 @@ static int nan_test_dev_init(struct nan_device *dev)
nan.send_naf = nan_test_send_naf_cb;
nan.get_chans = nan_test_get_chans_cb;
nan.is_valid_publish_id = nan_test_is_valid_publish_id_cb;
+ nan.set_peer_schedule = nan_test_set_peer_schedule_cb;
/* Awake on every DW on 2 GHz and 5 GHz */
nan.dev_capa.cdw_info = 0x9;
@@ -982,7 +1005,23 @@ nan_test_setup_devices(struct nan_test_global *global,
.master_pref = 2,
.dual_band = 1,
};
- const u8 pot_avail[] = {
+ /*
+ * Device attributes containing:
+ * 1. Device capability attribute (ID=0x0F, len=10):
+ * - map_id=0
+ * - cdw_info=0x0009 (awake on every DW on 2G and 5G)
+ * - supported_bands=0x07 (2G, 5G, 6G)
+ * - op_mode=0x01
+ * - n_antennas=0x22
+ * - channel_switch_time=0x000a (10)
+ * - capa=0x00
+ * 2. Availability attribute (ID=0x12, len=12)
+ */
+ const u8 attrs[] = {
+ /* Device capability attribute */
+ 0x0f, 0x09, 0x00, 0x00, 0x09, 0x00, 0x07, 0x01,
+ 0x22, 0x0a, 0x00, 0x00,
+ /* Availability attribute */
0x12, 0x0c, 0x00, 0x01, 0x20, 0x00, 0x07, 0x00,
0x1a, 0x00, 0x11, 0x51, 0xff, 0x07, 0x00,
};
@@ -1001,8 +1040,8 @@ nan_test_setup_devices(struct nan_test_global *global,
if (!sub)
goto fail;
- nan_add_peer(pub->nan, sub_nmi, pot_avail, sizeof(pot_avail));
- nan_add_peer(sub->nan, pub_nmi, pot_avail, sizeof(pot_avail));
+ nan_add_peer(pub->nan, sub_nmi, attrs, sizeof(attrs));
+ nan_add_peer(sub->nan, pub_nmi, attrs, sizeof(attrs));
wpa_printf(MSG_INFO, "\n%s: Done\n", __func__);
return sub;
diff --git a/src/nan/nan_ndl.c b/src/nan/nan_ndl.c
index 4609ba65b8..8fb7cd7405 100644
--- a/src/nan/nan_ndl.c
+++ b/src/nan/nan_ndl.c
@@ -118,6 +118,13 @@ static void nan_ndl_clear(struct nan_data *nan, struct nan_peer *peer)
MAC2STR(peer->nmi_addr),
nan_ndl_state_str(peer->ndl->state), peer->ndl->state);
+ if (peer->configured) {
+ nan->cfg->set_peer_schedule(nan->cfg->cb_ctx, peer->nmi_addr,
+ false, 0, 0, 0, NULL,
+ NULL);
+ peer->configured = false;
+ }
+
os_free(ndl->ndc_sched);
ndl->ndc_sched = NULL;
ndl->ndc_sched_len = 0;
--
2.49.0
More information about the Hostap
mailing list