[PATCH 69/97] wpa_supplicant: Request a deferred NAN schedule if there are active NDPs
Andrei Otcheretianski
andrei.otcheretianski at intel.com
Tue Apr 28 13:06:10 PDT 2026
From: Avraham Stern <avraham.stern at intel.com>
When a new NAN schedule is configured and there are active NDPs,
request a deferred schedule. When a deferred NAN schedule
is requested, the previous schedule will still be used (e.g. when
advertising the device availability) until the driver notifies that
the new schedule is applied. Handling this notification will be added
in a later patch.
Signed-off-by: Avraham Stern <avraham.stern at intel.com>
---
wpa_supplicant/nan_supplicant.c | 110 ++++++++++++++++++------------
wpa_supplicant/wpa_supplicant_i.h | 4 ++
2 files changed, 70 insertions(+), 44 deletions(-)
diff --git a/wpa_supplicant/nan_supplicant.c b/wpa_supplicant/nan_supplicant.c
index f54304345b..116189fc91 100644
--- a/wpa_supplicant/nan_supplicant.c
+++ b/wpa_supplicant/nan_supplicant.c
@@ -1466,6 +1466,8 @@ void wpas_nan_deinit(struct wpa_supplicant *wpa_s)
os_free(wpa_s->nan_disallowed_freqs.range);
os_memset(&wpa_s->nan_disallowed_freqs, 0,
sizeof(wpa_s->nan_disallowed_freqs));
+ clear_sched_config(&wpa_s->nan_sched_update.sched);
+
wpa_s->nan = NULL;
}
@@ -1890,7 +1892,7 @@ static void wpas_nan_fill_ndp_schedule(struct wpa_supplicant *wpa_s,
* If no bitmaps provided - clear the map */
int wpas_nan_sched_config_map(struct wpa_supplicant *wpa_s, const char *cmd)
{
- struct nan_schedule_config sched_cfg;
+ struct nan_schedule_config *sched_cfg = &wpa_s->nan_sched_update.sched;
struct nan_schedule_config old_sched_cfg;
struct nan_schedule sched;
char *token, *context = NULL;
@@ -1904,6 +1906,12 @@ int wpas_nan_sched_config_map(struct wpa_supplicant *wpa_s, const char *cmd)
if (!wpas_nan_ndp_allowed(wpa_s))
return -1;
+ if (sched_cfg->deferred) {
+ wpa_printf(MSG_DEBUG,
+ "NAN: Previous schedule update is still pending");
+ return -1;
+ }
+
if (os_strncmp(cmd, "map_id=", 7) != 0) {
wpa_printf(MSG_INFO, "NAN: Invalid schedule map format");
return -1;
@@ -1933,14 +1941,14 @@ int wpas_nan_sched_config_map(struct wpa_supplicant *wpa_s, const char *cmd)
expected_bitmap_len = (wpa_s->nan_capa.schedule_period /
wpa_s->nan_capa.slot_duration + 7) / 8;
- os_memset(&sched_cfg, 0, sizeof(sched_cfg));
+ os_memset(sched_cfg, 0, sizeof(*sched_cfg));
pos = os_strchr(cmd + 7, ' ');
if (!pos) {
clear_sched_config(&wpa_s->nan_sched[map_id - 1]);
wpa_printf(MSG_INFO,
"NAN: Missing freq:timebitmap pairs - cleanup schedule");
- return wpa_drv_nan_config_schedule(wpa_s, map_id, &sched_cfg);
+ return wpa_drv_nan_config_schedule(wpa_s, map_id, sched_cfg);
}
shared_freqs = os_calloc(wpa_s->num_multichan_concurrent,
@@ -1969,7 +1977,7 @@ int wpas_nan_sched_config_map(struct wpa_supplicant *wpa_s, const char *cmd)
/* Parse freq:timebitmap pairs */
pos++;
while ((token = str_token(pos, " ", &context))) {
- int j, i = sched_cfg.num_channels;;
+ int j, i = sched_cfg->num_channels;
struct bitfield *bf_chan = NULL;
char *colon = os_strchr(token, ':');
struct nan_sched_chan chan;
@@ -1988,67 +1996,68 @@ int wpas_nan_sched_config_map(struct wpa_supplicant *wpa_s, const char *cmd)
goto out;
}
- sched_cfg.channels[i].freq = atoi(token);
- if (sched_cfg.channels[i].freq <= 0) {
+ sched_cfg->channels[i].freq = atoi(token);
+ if (sched_cfg->channels[i].freq <= 0) {
wpa_printf(MSG_INFO, "NAN: Invalid frequency %d",
- sched_cfg.channels[i].freq);
+ sched_cfg->channels[i].freq);
goto out;
}
for (j = 0; j < i; j++) {
- if (sched_cfg.channels[j].freq ==
- sched_cfg.channels[i].freq) {
+ if (sched_cfg->channels[j].freq ==
+ sched_cfg->channels[i].freq) {
wpa_printf(MSG_INFO,
"NAN: Duplicate frequency %d",
- sched_cfg.channels[i].freq);
+ sched_cfg->channels[i].freq);
goto out;
}
}
if (wpas_nan_select_channel_params(
- wpa_s, sched_cfg.channels[i].freq,
- &sched_cfg.channels[i].center_freq1,
- &sched_cfg.channels[i].center_freq2,
- &sched_cfg.channels[i].bandwidth)) {
+ wpa_s, sched_cfg->channels[i].freq,
+ &sched_cfg->channels[i].center_freq1,
+ &sched_cfg->channels[i].center_freq2,
+ &sched_cfg->channels[i].bandwidth)) {
wpa_printf(MSG_INFO,
"NAN: Failed to select channel params for freq %d",
- sched_cfg.channels[i].freq);
+ sched_cfg->channels[i].freq);
goto out;
}
if (!int_array_includes(shared_freqs,
- sched_cfg.channels[i].freq)) {
+ sched_cfg->channels[i].freq)) {
if (!unused_freqs_count) {
wpa_printf(MSG_INFO,
"NAN: No unused radio frequency available for freq %d",
- sched_cfg.channels[i].freq);
+ sched_cfg->channels[i].freq);
goto out;
}
unused_freqs_count--;
}
- sched_cfg.channels[i].time_bitmap = wpabuf_parse_bin(colon + 1);
- if (!sched_cfg.channels[i].time_bitmap) {
+ sched_cfg->channels[i].time_bitmap =
+ wpabuf_parse_bin(colon + 1);
+ if (!sched_cfg->channels[i].time_bitmap) {
wpa_printf(MSG_INFO, "NAN: Invalid time bitmap");
goto out;
}
- sched_cfg.num_channels++;
+ sched_cfg->num_channels++;
- if (wpabuf_len(sched_cfg.channels[i].time_bitmap) !=
+ if (wpabuf_len(sched_cfg->channels[i].time_bitmap) !=
expected_bitmap_len) {
wpa_printf(MSG_INFO,
"NAN: Invalid bitmap length (%zu) for period=%d, slot length=%d",
- wpabuf_len(sched_cfg.channels[i].time_bitmap),
+ wpabuf_len(sched_cfg->channels[i].time_bitmap),
wpa_s->nan_capa.schedule_period,
wpa_s->nan_capa.slot_duration);
goto out;
}
bf_chan = bitfield_alloc_data(
- wpabuf_head(sched_cfg.channels[i].time_bitmap),
- wpabuf_len(sched_cfg.channels[i].time_bitmap));
+ wpabuf_head(sched_cfg->channels[i].time_bitmap),
+ wpabuf_len(sched_cfg->channels[i].time_bitmap));
if (!bf_chan) {
wpa_printf(MSG_INFO,
"NAN: Failed to allocate bitfield for channel schedule");
@@ -2058,34 +2067,34 @@ int wpas_nan_sched_config_map(struct wpa_supplicant *wpa_s, const char *cmd)
if (bitfield_intersects(bf_total, bf_chan)) {
wpa_printf(MSG_INFO,
"NAN: Overlapping time bitmap detected for freq %d",
- sched_cfg.channels[i].freq);
+ sched_cfg->channels[i].freq);
bitfield_free(bf_chan);
goto out;
}
/* Extract RX NSS from upper nibble of num_antennas */
- sched_cfg.channels[i].rx_nss =
+ sched_cfg->channels[i].rx_nss =
(wpa_s->nan_capa.num_antennas >> 4) & 0x0f;
bitfield_union_in_place(bf_total, bf_chan);
bitfield_free(bf_chan);
- chan.freq = sched_cfg.channels[i].freq;
- chan.center_freq1 = sched_cfg.channels[i].center_freq1;
- chan.center_freq2 = sched_cfg.channels[i].center_freq2;
- chan.bandwidth = sched_cfg.channels[i].bandwidth;
+ chan.freq = sched_cfg->channels[i].freq;
+ chan.center_freq1 = sched_cfg->channels[i].center_freq1;
+ chan.center_freq2 = sched_cfg->channels[i].center_freq2;
+ chan.bandwidth = sched_cfg->channels[i].bandwidth;
chan_entry = (struct nan_chan_entry *)
- &sched_cfg.channels[i].chan_entry;
+ &sched_cfg->channels[i].chan_entry;
if (nan_get_chan_entry(wpa_s->nan, &chan, chan_entry)) {
wpa_printf(MSG_INFO,
"NAN: Failed to get channel entry for freq %d",
- sched_cfg.channels[i].freq);
+ sched_cfg->channels[i].freq);
goto out;
}
}
- sched_cfg.avail_attr = wpabuf_alloc(NAN_AVAIL_ATTR_MAX_LEN);
- if (!sched_cfg.avail_attr) {
+ sched_cfg->avail_attr = wpabuf_alloc(NAN_AVAIL_ATTR_MAX_LEN);
+ if (!sched_cfg->avail_attr) {
wpa_printf(MSG_INFO,
"NAN: Failed to allocate memory for Availability attribute");
ret = -1;
@@ -2096,26 +2105,34 @@ int wpas_nan_sched_config_map(struct wpa_supplicant *wpa_s, const char *cmd)
os_memcpy(&old_sched_cfg, &wpa_s->nan_sched[map_id - 1],
sizeof(old_sched_cfg));
- os_memcpy(&wpa_s->nan_sched[map_id - 1], &sched_cfg, sizeof(sched_cfg));
+ os_memcpy(&wpa_s->nan_sched[map_id - 1], sched_cfg, sizeof(*sched_cfg));
wpas_nan_fill_ndp_schedule(wpa_s, &sched);
ret = nan_convert_sched_to_avail_attrs(wpa_s->nan,
wpa_s->schedule_sequence_id + 1,
BIT(map_id),
sched.n_chans, sched.chans,
- sched_cfg.avail_attr,
+ sched_cfg->avail_attr,
false);
+
+ /* Restore previous schedule configuration */
+ os_memcpy(&wpa_s->nan_sched[map_id - 1], &old_sched_cfg,
+ sizeof(old_sched_cfg));
if (ret < 0) {
wpa_printf(MSG_INFO,
"NAN: Failed to convert schedule to Availability Attributes for map_id %d",
map_id);
- os_memcpy(&wpa_s->nan_sched[map_id - 1], &old_sched_cfg,
- sizeof(old_sched_cfg));
goto out;
}
- nan_dump_sched_config("NAN: Set schedule config", &sched_cfg);
- ret = wpa_drv_nan_config_schedule(wpa_s, map_id, &sched_cfg);
+ if (nan_has_active_ndp(wpa_s->nan)) {
+ wpa_printf(MSG_DEBUG, "NAN: Set schedule config as deferred");
+ sched_cfg->deferred = true;
+ wpa_s->nan_sched_update.map_id = map_id;
+ }
+
+ nan_dump_sched_config("NAN: Set schedule config", sched_cfg);
+ ret = wpa_drv_nan_config_schedule(wpa_s, map_id, sched_cfg);
if (ret < 0) {
wpa_printf(MSG_INFO,
"NAN: Failed to configure NAN schedule map_id %d",
@@ -2125,14 +2142,19 @@ int wpas_nan_sched_config_map(struct wpa_supplicant *wpa_s, const char *cmd)
goto out;
}
- /* Free the old schedule and keep the new one (already stored) */
- wpa_s->schedule_sequence_id++;
- clear_sched_config(&old_sched_cfg);
+ if (!sched_cfg->deferred) {
+ /* Store the configured schedule */
+ wpa_s->schedule_sequence_id++;
+ clear_sched_config(&wpa_s->nan_sched[map_id - 1]);
+ os_memcpy(&wpa_s->nan_sched[map_id - 1], sched_cfg,
+ sizeof(*sched_cfg));
+ os_memset(sched_cfg, 0, sizeof(*sched_cfg));
+ }
out:
os_free(bf_total);
os_free(shared_freqs);
if (ret)
- clear_sched_config(&sched_cfg);
+ clear_sched_config(sched_cfg);
return ret;
}
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index 17a55f0db7..45a70fbead 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -1736,6 +1736,10 @@ struct wpa_supplicant {
u8 schedule_sequence_id;
struct nan_schedule_config nan_sched[MAX_NAN_RADIOS];
u16 nan_supported_csids;
+ struct nan_schedule_update {
+ struct nan_schedule_config sched;
+ u8 map_id;
+ } nan_sched_update;
struct wpa_freq_range_list nan_disallowed_freqs;
u16 nan_max_bw;
unsigned int nan_ndi_ndp_refcount; /* Active NDP count on this NDI */
--
2.53.0
More information about the Hostap
mailing list