From: Andrei Otcheretianski Date: Tue, 23 Dec 2025 11:46:08 +0000 (+0200) Subject: NAN: Support synchronized SDF transmissions X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=57b2d28f25ad221e5dc5bca70f81d2169dfb69c6;p=thirdparty%2Fhostap.git NAN: Support synchronized SDF transmissions Handle DW notification and trigger transmission of multicast unsolicited publish or active subscribe frames. Skip USD specific logic for synchronized services. Signed-off-by: Andrei Otcheretianski --- diff --git a/src/common/nan_de.c b/src/common/nan_de.c index e31ab715c..d8d78d035 100644 --- a/src/common/nan_de.c +++ b/src/common/nan_de.c @@ -66,6 +66,7 @@ struct nan_de_service { bool is_p2p; bool is_pr; bool listen_stopped; + bool sync; }; #define NAN_DE_N_MIN 5 @@ -92,6 +93,8 @@ struct nan_de { struct nan_de_cfg cfg; struct os_reltime suspend_cycle_start; + + int dw_freq; }; @@ -376,11 +379,13 @@ static void nan_de_tx_multicast(struct nan_de *de, struct nan_de_service *srv, type = NAN_SRV_CTRL_PUBLISH; - nan_de_check_chan_change(srv); - ms = nan_de_time_to_next_chan_change(srv); - if (ms < 100) - ms = 100; - wait_time = ms; + if (!srv->sync) { + nan_de_check_chan_change(srv); + ms = nan_de_time_to_next_chan_change(srv); + if (ms < 100) + ms = 100; + wait_time = ms; + } } else if (srv->type == NAN_DE_SUBSCRIBE) { type = NAN_SRV_CTRL_SUBSCRIBE; } else { @@ -395,6 +400,17 @@ static void nan_de_tx_multicast(struct nan_de *de, struct nan_de_service *srv, bssid = nan_network_id; } + if (srv->sync) { + if (!de->cluster_id_set || !de->dw_freq) { + wpa_printf(MSG_DEBUG, + "NAN: Cluster ID or DW frequency are not set - skip sync TX"); + return; + } + + wait_time = 0; + bssid = de->cluster_id; + } + nan_de_tx_sdf(de, srv, wait_time, type, network_id, bssid, req_instance_id, srv->ssi); os_get_reltime(&srv->last_multicast); @@ -565,6 +581,9 @@ static void nan_de_start_new_publish_state(struct nan_de *de, { unsigned int n; + if (srv->sync) + return; + if (force_single || !srv->freq_list || srv->freq_list[0] == 0) srv->in_multi_chan = false; else @@ -697,6 +716,9 @@ static void nan_de_timer(void *eloop_ctx, void *timeout_ctx) continue; } + if (srv->sync) + continue; + if (os_reltime_initialized(&srv->next_publish_state) && os_reltime_before(&srv->next_publish_state, &now)) nan_de_start_new_publish_state(de, srv, false); @@ -972,6 +994,10 @@ static void nan_de_rx_publish(struct nan_de *de, struct nan_de_service *srv, enum nan_service_protocol_type srv_proto_type, const u8 *ssi, size_t ssi_len) { + /* Skip USD logic */ + if (srv->sync) + goto send_event; + /* Subscribe function processing of a receive Publish message */ if (!os_reltime_initialized(&srv->first_discovered)) { os_get_reltime(&srv->first_discovered); @@ -993,6 +1019,7 @@ static void nan_de_rx_publish(struct nan_de *de, struct nan_de_service *srv, instance_id); } +send_event: if (de->cb.discovery_result) de->cb.discovery_result( de->cb.ctx, srv->id, srv_proto_type, @@ -1136,12 +1163,12 @@ static void nan_de_rx_subscribe(struct nan_de *de, struct nan_de_service *srv, else if (srv->is_p2p) a3 = de->nmi; - nan_de_tx(de, srv->freq, 100, + nan_de_tx(de, srv->sync ? 0 : srv->freq, srv->sync ? 0 : 100, srv->publish.solicited_multicast ? network_id : peer_addr, de->nmi, a3, buf); wpabuf_free(buf); - if (!srv->is_p2p) + if (!srv->is_p2p && !srv->sync) nan_de_pause_state(srv, peer_addr, instance_id); offload: @@ -1168,7 +1195,7 @@ static void nan_de_rx_follow_up(struct nan_de *de, struct nan_de_service *srv, return; } - if (srv->type == NAN_DE_PUBLISH && !ssi) + if (srv->type == NAN_DE_PUBLISH && !ssi && !srv->sync) nan_de_pause_state(srv, peer_addr, instance_id); os_memcpy(srv->a3, a3, ETH_ALEN); @@ -1444,6 +1471,18 @@ int nan_de_publish(struct nan_de *de, const char *service_name, return -1; } + if (params->sync && !de->cluster_id_set) { + wpa_printf(MSG_DEBUG, + "NAN: Publish() - can't publish sync, cluster id is not set"); + return -1; + } + + if (p2p && params->sync) { + wpa_printf(MSG_DEBUG, + "NAN: Publish() - P2P is not supported with sync"); + return -1; + } + publish_id = nan_de_get_handle(de); if (publish_id < 1) return -1; @@ -1489,6 +1528,8 @@ int nan_de_publish(struct nan_de *de, const char *service_name, goto fail; } + srv->sync = params->sync; + /* Prepare for single and multi-channel states; starting with * single channel */ srv->first_multi_chan = true; @@ -1592,6 +1633,18 @@ int nan_de_subscribe(struct nan_de *de, const char *service_name, return -1; } + if (params->sync && !de->cluster_id_set) { + wpa_printf(MSG_DEBUG, + "NAN: Subscribe() - can't publish sync, cluster id is not set"); + return -1; + } + + if (p2p && params->sync) { + wpa_printf(MSG_DEBUG, + "NAN: Subscribe() - P2P is not supported with sync"); + return -1; + } + subscribe_id = nan_de_get_handle(de); if (subscribe_id < 1) return -1; @@ -1642,6 +1695,7 @@ int nan_de_subscribe(struct nan_de *de, const char *service_name, srv->id = subscribe_id; srv->is_p2p = p2p; srv->is_pr = params->proximity_ranging && params->active; + srv->sync = params->sync; nan_de_add_srv(de, srv); nan_de_run_timer(de); return subscribe_id; @@ -1679,8 +1733,16 @@ int nan_de_transmit(struct nan_de *de, int handle, if (!srv) return -1; + if (srv->sync && !de->cluster_id_set) { + wpa_printf(MSG_DEBUG, + "NAN: Cannot transmit Follow-up, cluster ID not set"); + return -1; + } + if (srv->is_p2p) network_id = p2p_network_id; + else if (srv->sync) + network_id = de->cluster_id; else network_id = nan_network_id; @@ -1752,6 +1814,39 @@ int nan_de_config(struct nan_de *de, struct nan_de_cfg *cfg) } +void nan_de_dw_trigger(struct nan_de *de, int freq) +{ + int i; + struct os_reltime now; + + de->dw_freq = freq; + + if (!de->cluster_id_set) { + wpa_printf(MSG_DEBUG, "NAN: Skip DW, cluster ID not set"); + return; + } + + os_get_reltime(&now); + for (i = 0; i < NAN_DE_MAX_SERVICE; i++) { + struct nan_de_service *srv = de->service[i]; + + if (!srv || !srv->sync) + continue; + + if (nan_de_srv_expired(srv, &now)) { + nan_de_del_srv(de, srv, NAN_DE_REASON_TIMEOUT); + continue; + } + + if ((srv->type == NAN_DE_PUBLISH && + srv->publish.unsolicited) || + (srv->type == NAN_DE_SUBSCRIBE && srv->subscribe.active)) { + nan_de_tx_multicast(de, srv, 0); + } + } +} + + void nan_de_set_cluster_id(struct nan_de *de, const u8 *cluster_id) { if (cluster_id) { diff --git a/src/common/nan_de.h b/src/common/nan_de.h index 3d5d34844..34d811535 100644 --- a/src/common/nan_de.h +++ b/src/common/nan_de.h @@ -118,6 +118,9 @@ struct nan_publish_params { /* Proximity ranging flag */ bool proximity_ranging; + + /* Synchronized discovery */ + bool sync; }; /* Returns -1 on failure or >0 publish_id */ @@ -154,6 +157,9 @@ struct nan_subscribe_params { /* Proximity ranging flag */ bool proximity_ranging; + + /* Synchronized discovery */ + bool sync; }; /* Returns -1 on failure or >0 subscribe_id */ @@ -169,6 +175,7 @@ void nan_de_cancel_subscribe(struct nan_de *de, int subscribe_id); int nan_de_transmit(struct nan_de *de, int handle, const struct wpabuf *ssi, const struct wpabuf *elems, const u8 *peer_addr, u8 req_instance_id); +void nan_de_dw_trigger(struct nan_de *de, int freq); void nan_de_set_cluster_id(struct nan_de *de, const u8 *cluster_id); int nan_de_stop_listen(struct nan_de *de, int handle); diff --git a/wpa_supplicant/nan_supplicant.c b/wpa_supplicant/nan_supplicant.c index cfe417373..b053225fc 100644 --- a/wpa_supplicant/nan_supplicant.c +++ b/wpa_supplicant/nan_supplicant.c @@ -140,6 +140,6 @@ void wpas_nan_next_dw(struct wpa_supplicant *wpa_s, u32 freq) if (!wpas_nan_ready(wpa_s)) return; - /* TODO: Handle DW notification */ wpa_printf(MSG_DEBUG, "NAN: Next DW notification freq=%d", freq); + nan_de_dw_trigger(wpa_s->nan_de, freq); }