[PATCH 02/18] NAN: Factor out conversion of a channel entry to a channel
Andrei Otcheretianski
andrei.otcheretianski at intel.com
Mon Oct 12 08:46:36 PDT 2026
Deriving the channel that a peer advertises in an availability attribute
is not trivial: for an operating class of 80 MHz or more the channel
bitmap points at the center of the primary segment, so the control
channel has to be taken from the primary channel bitmap.
This was open coded in nan_peer_get_committed_avail_add(), while
nan_get_control_channel() held a partial copy of the same arithmetic.
Move it to nan_chan_entry_to_sched_chan() and use it in both places, so
that there is a single place that knows how a channel entry maps to a
channel.
This is not a pure refactor, as unifying the two copies also changes
behaviour:
- Operating class 130 (80+80 MHz) is now rejected. Both callers used
to accept it, but neither filled the secondary segment, so the entry
became a bogus 160 MHz channel without a center_freq2. The auxiliary
channel bitmap is not parsed either, so reject it until 80+80 is
actually supported.
- The frequency returned by ieee80211_chan_to_freq() is validated,
instead of storing a negative frequency.
- nan_avail_entries_to_bf() no longer compares the encoded fields
before falling back to the control channel. That comparison used the
little endian channel bitmap as if it was in host order and byte
swapped the one octet primary channel bitmap. Comparing the control
channel covers it anyway, so an entry that cannot be converted is now
skipped instead of being matched by its raw fields.
Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski at intel.com>
---
src/nan/nan.c | 74 +++------------------------
src/nan/nan_i.h | 3 ++
src/nan/nan_util.c | 125 ++++++++++++++++++++++++---------------------
3 files changed, 76 insertions(+), 126 deletions(-)
diff --git a/src/nan/nan.c b/src/nan/nan.c
index 275d5fd233..ef35646782 100644
--- a/src/nan/nan.c
+++ b/src/nan/nan.c
@@ -3228,13 +3228,9 @@ nan_peer_get_committed_avail_add(const struct nan_data *nan,
struct nan_map *map;
struct nan_map_chan *chan;
struct nan_sched_chan schan;
- const struct oper_class_map *op;
- u8 chan_id;
bool committed;
- int freq, bw, center_freq1, center_freq2, idx;
u8 i;
const struct nan_band_chan *band_chan;
- const struct nan_chan_entry *bc_chan;
if (avail->type != NAN_AVAIL_ENTRY_CTRL_TYPE_COMMITTED &&
avail->type != NAN_AVAIL_ENTRY_CTRL_TYPE_COND)
@@ -3252,64 +3248,13 @@ nan_peer_get_committed_avail_add(const struct nan_data *nan,
}
band_chan = &avail->band_chan[0];
- bc_chan = &band_chan->u.chan;
- /* Get all the channel parameters */
- op = get_oper_class(NULL, band_chan->u.chan.op_class);
- if (!op) {
- wpa_printf(MSG_DEBUG, "NAN: Unknown operating class %u",
- band_chan->u.chan.op_class);
+ if (nan_chan_entry_to_sched_chan(nan, &band_chan->u.chan, &schan))
return;
- }
-
- idx = ffs(le_to_host16(bc_chan->chan_bitmap)) - 1;
- if (idx < 0) {
- wpa_printf(MSG_DEBUG,
- "NAN: No channel found in chan_bitmap 0x%04x for oper_class %u",
- le_to_host16(bc_chan->chan_bitmap),
- bc_chan->op_class);
- return;
- }
-
- chan_id = op_class_idx_to_chan(op, idx);
- if (!chan_id) {
- wpa_printf(MSG_DEBUG,
- "NAN: No channel found for oper_class %u idx %u",
- bc_chan->op_class, idx);
- return;
- }
-
- freq = ieee80211_chan_to_freq(NULL, bc_chan->op_class, chan_id);
- bw = oper_class_bw_to_int(op);
-
- center_freq2 = 0;
- if (op->op_class < 128) {
- center_freq1 = ieee80211_get_center_freq(freq, op->bw);
- } else if (op->op_class > 130) {
- wpa_printf(MSG_DEBUG, "NAN: Missing support for op_class %u",
- op->op_class);
- return;
- } else {
- idx = ffs(bc_chan->pri_chan_bitmap) - 1;
- if (idx < 0) {
- wpa_printf(MSG_DEBUG,
- "NAN: No primary channel found in pri_chan_bitmap 0x%04x",
- le_to_host16(bc_chan->pri_chan_bitmap));
- return;
- }
-
- center_freq1 = freq;
- if (op->bw == BW80 || op->bw == BW80P80)
- freq = freq - 30 + idx * 20;
- else if (op->bw == BW160)
- freq = freq - 70 + idx * 20;
-
- /* TODO: Missing support for 80 + 80 */
- }
/* Skip channels that are not in local schedule */
if (local_sched &&
- !nan_peer_channel_in_local_sched(nan, freq, local_sched))
+ !nan_peer_channel_in_local_sched(nan, schan.freq, local_sched))
return;
/* Assume committed for conditional slots if setup is done */
@@ -3335,17 +3280,15 @@ nan_peer_get_committed_avail_add(const struct nan_data *nan,
map->map_id = avail->map_id;
- os_memset(&schan, 0, sizeof(schan));
-
/* Find channel entry if already exists */
for (i = 0; i < map->n_chans; i++) {
if (map->chans[i].committed != committed)
return;
- if (map->chans[i].chan.freq == freq &&
- map->chans[i].chan.bandwidth == bw &&
- map->chans[i].chan.center_freq1 == center_freq1 &&
- map->chans[i].chan.center_freq2 == center_freq2)
+ if (map->chans[i].chan.freq == schan.freq &&
+ map->chans[i].chan.bandwidth == schan.bandwidth &&
+ map->chans[i].chan.center_freq1 == schan.center_freq1 &&
+ map->chans[i].chan.center_freq2 == schan.center_freq2)
break;
}
@@ -3362,10 +3305,7 @@ nan_peer_get_committed_avail_add(const struct nan_data *nan,
chan->committed = committed;
chan->rx_nss = avail->rx_nss;
- chan->chan.freq = freq;
- chan->chan.bandwidth = bw;
- chan->chan.center_freq1 = center_freq1;
- chan->chan.center_freq2 = center_freq2;
+ chan->chan = schan;
os_memcpy(&chan->tbm, &avail->tbm, sizeof(avail->tbm));
}
diff --git a/src/nan/nan_i.h b/src/nan/nan_i.h
index 18db961980..4b4deca0dd 100644
--- a/src/nan/nan_i.h
+++ b/src/nan/nan_i.h
@@ -802,6 +802,9 @@ int nan_convert_chan_sched_to_bf(struct nan_data *nan,
u8 *op_class, u16 *cbm, u16 *pcbm);
int nan_get_chan_bm(struct nan_data *nan, const struct nan_sched_chan *chan,
u8 *op_class, u16 *chan_bm, u16 *pri_chan_bm);
+int nan_chan_entry_to_sched_chan(const struct nan_data *nan,
+ const struct nan_chan_entry *entry,
+ struct nan_sched_chan *chan);
int nan_add_avail_attrs(struct nan_data *nan, u8 sequence_id,
u32 map_ids_bitmap, u8 type_for_conditional,
size_t n_chans, struct nan_chan_schedule *chans,
diff --git a/src/nan/nan_util.c b/src/nan/nan_util.c
index 8086bcf74c..95410cd91e 100644
--- a/src/nan/nan_util.c
+++ b/src/nan/nan_util.c
@@ -1534,21 +1534,33 @@ bool nan_sched_bf_covered_by_avail_entries_and_chan(
}
-static int nan_get_control_channel(struct nan_data *nan, u8 op_class,
- u16 cbm, u16 pri_cbm)
+/**
+ * nan_chan_entry_to_sched_chan - Convert a channel entry to a channel
+ * @nan: NAN module context from nan_init()
+ * @entry: Channel entry as carried in an availability attribute
+ * @chan: On success holds the channel
+ * Returns: 0 on success; -1 if the entry cannot be represented as a channel
+ */
+int nan_chan_entry_to_sched_chan(const struct nan_data *nan,
+ const struct nan_chan_entry *entry,
+ struct nan_sched_chan *chan)
{
- const struct oper_class_map *op = get_oper_class(NULL, op_class);
- int freq = 0, idx;
+ const struct oper_class_map *op;
+ int freq, idx;
u8 chan_id;
- if (!op || op_class > 130)
+ op = get_oper_class(NULL, entry->op_class);
+ if (!op) {
+ wpa_printf(MSG_DEBUG, "NAN: Unknown operating class %u",
+ entry->op_class);
return -1;
+ }
- idx = ffs(cbm) - 1;
+ idx = ffs(le_to_host16(entry->chan_bitmap)) - 1;
if (idx < 0) {
wpa_printf(MSG_DEBUG,
"NAN: No channel found in chan_bitmap 0x%04x for oper_class %u",
- cbm, op_class);
+ le_to_host16(entry->chan_bitmap), entry->op_class);
return -1;
}
@@ -1556,39 +1568,45 @@ static int nan_get_control_channel(struct nan_data *nan, u8 op_class,
if (!chan_id) {
wpa_printf(MSG_DEBUG,
"NAN: No channel found for oper_class %u idx %u",
- op_class, idx);
+ entry->op_class, idx);
return -1;
}
- freq = ieee80211_chan_to_freq(NULL, op_class, chan_id);
-
- /*
- * For operating classes with bandwidth < 80 MHz, the frequency is the
- * control channel frequency. For operating classes with
- * bandwidth >= 80 MHz, the frequency is the center frequency of the
- * primary segment, so we need to derive the control channel frequency
- * from the primary channel bitmap.
- */
- if (op->bw == BW20 || op->bw == BW40 ||
- op->bw == BW40PLUS || op->bw == BW40MINUS)
- return freq;
-
- if (!pri_cbm) {
+ freq = ieee80211_chan_to_freq(NULL, entry->op_class, chan_id);
+ if (freq < 0) {
wpa_printf(MSG_DEBUG,
- "NAN: No primary channel bitmap provided for oper_class %u",
- op_class);
+ "NAN: No frequency for oper_class %u chan %u",
+ entry->op_class, chan_id);
return -1;
}
- idx = ffs(pri_cbm) - 1;
+ os_memset(chan, 0, sizeof(*chan));
+ chan->bandwidth = oper_class_bw_to_int(op);
- if (op->bw == BW80 || op->bw == BW80P80)
- return freq - 30 + idx * 20;
+ if (op->op_class < 128) {
+ chan->center_freq1 = ieee80211_get_center_freq(freq, op->bw);
+ } else if (op->op_class >= 130) {
+ wpa_printf(MSG_DEBUG, "NAN: Missing support for op_class %u",
+ op->op_class);
+ return -1;
+ } else {
+ idx = ffs(entry->pri_chan_bitmap) - 1;
+ if (idx < 0) {
+ wpa_printf(MSG_DEBUG,
+ "NAN: No primary channel found in pri_chan_bitmap 0x%02x",
+ entry->pri_chan_bitmap);
+ return -1;
+ }
- if (op->bw == BW160)
- return freq - 70 + idx * 20;
+ chan->center_freq1 = freq;
+ if (op->bw == BW80)
+ freq = freq - 30 + idx * 20;
+ else if (op->bw == BW160)
+ freq = freq - 70 + idx * 20;
+ }
- return -1;
+ chan->freq = freq;
+ return 0;
}
@@ -1603,16 +1621,29 @@ static int nan_get_control_channel(struct nan_data *nan, u8 op_class,
* @pri_cbm: Primary channel bitmap to match against
* Returns: NULL on error or no match; otherwise returns a bitfield describing
* all the available slots.
+ *
+ * Entries are matched by their control channel, so a peer that describes the
+ * same channel with a different bandwidth still matches.
*/
struct bitfield * nan_avail_entries_to_bf(struct nan_data *nan,
const struct dl_list *avail_entries,
u8 op_class, u16 cbm, u16 pri_cbm)
{
+ const struct nan_chan_entry entry = {
+ .op_class = op_class,
+ .chan_bitmap = host_to_le16(cbm),
+ .pri_chan_bitmap = pri_cbm & 0xff,
+ };
struct nan_avail_entry *avail;
struct bitfield *res_bf = NULL;
+ struct nan_sched_chan chan;
+
+ if (nan_chan_entry_to_sched_chan(nan, &entry, &chan))
+ return NULL;
dl_list_for_each(avail, avail_entries, struct nan_avail_entry,
list) {
+ struct nan_sched_chan avail_chan;
struct bitfield *avail_bf;
/* Schedule can only be covered by committed/conditional. */
@@ -1628,35 +1659,11 @@ struct bitfield * nan_avail_entries_to_bf(struct nan_data *nan,
avail->band_chan_type != NAN_TYPE_CHANNEL)
continue;
- /*
- * Check that the availability entry channel matches. If it does
- * not match, check if the channels are compatible, i.e., have
- * the same control channel.
- */
- if (avail->band_chan[0].u.chan.op_class != op_class ||
- avail->band_chan[0].u.chan.chan_bitmap != cbm ||
- avail->band_chan[0].u.chan.pri_chan_bitmap != pri_cbm) {
- int freq1, freq2;
- u16 chan_bitmap, pri_chan_bitmap;
-
- freq1 = nan_get_control_channel(nan, op_class,
- cbm, pri_cbm);
-
- chan_bitmap = le_to_host16(
- avail->band_chan[0].u.chan.chan_bitmap);
- pri_chan_bitmap = le_to_host16(
- avail->band_chan[0].u.chan.pri_chan_bitmap);
- freq2 = nan_get_control_channel(
- nan, avail->band_chan[0].u.chan.op_class,
- chan_bitmap, pri_chan_bitmap);
-
- if (freq2 == -1 || freq1 != freq2)
- continue;
-
- wpa_printf(MSG_DEBUG,
- "NAN: Availability entry channel is compatible. Control channel freq=%d MHz",
- freq1);
- }
+ if (nan_chan_entry_to_sched_chan(nan,
+ &avail->band_chan[0].u.chan,
+ &avail_chan) ||
+ avail_chan.freq != chan.freq)
+ continue;
/* Convert the availability entry to a bitfield */
avail_bf = nan_tbm_to_bf(nan, &avail->tbm);
--
2.53.0
More information about the Hostap
mailing list