[PATCH 13/18] driver_nl80211: Support NAN set non-evac channels command
Andrei Otcheretianski
andrei.otcheretianski at intel.com
Mon Oct 12 08:46:47 PDT 2026
Add support for the NL80211_CMD_NAN_SET_NON_EVAC_CHANNELS command that
marks a set of NAN channels as non-evacuable.
Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski at intel.com>
---
src/drivers/driver.h | 18 ++++++++++
src/drivers/driver_nl80211.c | 70 ++++++++++++++++++++++++++++++++----
2 files changed, 81 insertions(+), 7 deletions(-)
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index 32fcb4ec81..844b36e884 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -3549,6 +3549,8 @@ struct nan_schedule_config {
* on the channel.
* @rx_nss: Number of spatial streams supported for RX on the
* channel
+ * @no_evacuate: The channel must not be evacuated for concurrent
+ * operations
* @chan_entry: Channel Entry as defined in Wi-Fi Aware spec v4.0,
* Table 100 (Channel Entry format for the NAN Availability
* attribute).
@@ -3564,6 +3566,7 @@ struct nan_schedule_config {
int bandwidth;
struct wpabuf *time_bitmap;
u8 rx_nss;
+ bool no_evacuate;
u8 chan_entry[6];
} channels[MAX_NUM_NAN_SCHEDULE_CHANNELS];
@@ -5993,6 +5996,21 @@ struct wpa_driver_ops {
u16 max_chan_switch_time,
const struct wpabuf *ulw,
struct nan_peer_schedule_config *sched);
+
+ /**
+ * nan_set_non_evac_channels - Set NAN non-evacuable channels
+ * @priv: Private driver interface data
+ * @conf: NAN schedule configuration. Channels whose %no_evacuate flag
+ * is set are reported to the kernel as non-evacuable; the reported
+ * list replaces the previous set of non-evacuable channels.
+ * Returns 0 on success, -1 on failure
+ *
+ * This command sets the list of local schedule channels that must not
+ * be evacuated for concurrent operations. It should be executed on the
+ * NAN device interface after the local schedule has been configured.
+ */
+ int (*nan_set_non_evac_channels)(void *priv,
+ struct nan_schedule_config *conf);
#endif /* CONFIG_NAN */
#ifdef CONFIG_PR
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index e2029c2a97..10c278af52 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -16121,16 +16121,17 @@ static void wpa_driver_nl80211_nan_stop(void *priv)
}
+/* @set_avail_attrs: also encode the availability-specific attributes */
static int
wpa_driver_nl80211_nan_set_channel(struct wpa_driver_nl80211_data *drv,
struct nan_schedule_channel *chan,
- struct nl_msg *msg)
+ struct nl_msg *msg, bool set_avail_attrs)
{
struct nlattr *chan_attr;
enum nl80211_chan_width cw;
chan_attr = nla_nest_start(msg, NL80211_ATTR_NAN_CHANNEL);
- if (!chan)
+ if (!chan_attr)
return -ENOBUFS;
if (nl80211_bw_to_nl(chan->bandwidth, &cw, chan->center_freq2))
@@ -16139,15 +16140,21 @@ wpa_driver_nl80211_nan_set_channel(struct wpa_driver_nl80211_data *drv,
if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, chan->freq) ||
nla_put_u32(msg, NL80211_ATTR_CENTER_FREQ1, chan->center_freq1) ||
nla_put_u32(msg, NL80211_ATTR_CENTER_FREQ2, chan->center_freq2) ||
- nla_put_u32(msg, NL80211_ATTR_CHANNEL_WIDTH, cw) ||
+ nla_put_u32(msg, NL80211_ATTR_CHANNEL_WIDTH, cw)) {
+ wpa_printf(MSG_INFO,
+ "nl80211: NAN: Failed to put channel attributes");
+ return -EINVAL;
+ }
+
+ if (set_avail_attrs &&
nla_put(msg, NL80211_ATTR_NAN_CHANNEL_ENTRY,
sizeof(chan->chan_entry), chan->chan_entry)) {
wpa_printf(MSG_INFO,
- "nl80211: NAN: Failed to put channel attributes");
+ "nl80211: NAN: Failed to put channel entry");
return -EINVAL;
}
- if (chan->rx_nss &&
+ if (set_avail_attrs && chan->rx_nss &&
nla_put_u8(msg, NL80211_ATTR_NAN_RX_NSS, chan->rx_nss)) {
wpa_printf(MSG_INFO,
"nl80211: NAN: Failed to put RX NSS attribute");
@@ -16212,7 +16219,7 @@ wpa_driver_nl80211_nan_set_schedule(struct wpa_driver_nl80211_data *drv,
int ret;
ret = wpa_driver_nl80211_nan_set_channel(
- drv, &sched->channels[i], msg);
+ drv, &sched->channels[i], msg, true);
if (ret)
return ret;
@@ -16280,6 +16287,54 @@ fail:
}
+static int
+wpa_driver_nl80211_nan_set_non_evac_channels(void *priv,
+ struct nan_schedule_config *conf)
+{
+ struct i802_bss *bss = priv;
+ struct wpa_driver_nl80211_data *drv = bss->drv;
+ struct nl_msg *msg;
+ size_t i;
+ int ret;
+
+ if (drv->nlmode != NL80211_IFTYPE_NAN || !drv->nan_started)
+ return -EOPNOTSUPP;
+
+ if (!conf)
+ return -EINVAL;
+
+ msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_NAN_SET_NON_EVAC_CHANNELS);
+ if (!msg) {
+ wpa_printf(MSG_INFO,
+ "nl80211: Failed to alloc NAN non-evac channels command");
+ return -ENOMEM;
+ }
+
+ /* An empty list clears the previous set of non-evacuable channels */
+ for (i = 0; i < conf->num_channels; i++) {
+ if (!conf->channels[i].no_evacuate)
+ continue;
+
+ ret = wpa_driver_nl80211_nan_set_channel(
+ drv, &conf->channels[i], msg, false);
+ if (ret)
+ goto fail;
+ }
+
+ ret = send_and_recv_cmd(bss->drv, msg);
+ if (ret)
+ wpa_printf(MSG_INFO,
+ "nl80211: Failed to send NAN non-evac channels command: %d",
+ ret);
+
+ return ret;
+
+fail:
+ nlmsg_free(msg);
+ return ret;
+}
+
+
static int
wpa_driver_nl80211_nan_config_peer_schedule(
void *priv, const u8 *peer, u16 cdw, u8 sequence_id,
@@ -16369,7 +16424,7 @@ wpa_driver_nl80211_nan_config_peer_schedule(
for (chan_idx = 0; chan_idx < n_channels; chan_idx++) {
ret = wpa_driver_nl80211_nan_set_channel(drv,
channels[chan_idx],
- msg);
+ msg, true);
if (ret)
goto fail;
}
@@ -17082,6 +17137,7 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
.nan_change_config = wpa_driver_nl80211_nan_change_config,
.nan_config_schedule = wpa_driver_nl80211_nan_config_schedule,
.nan_config_peer_schedule = wpa_driver_nl80211_nan_config_peer_schedule,
+ .nan_set_non_evac_channels = wpa_driver_nl80211_nan_set_non_evac_channels,
#endif /* CONFIG_NAN */
#ifdef CONFIG_PR
.pd_start = nl80211_pd_start,
--
2.53.0
More information about the Hostap
mailing list