From: Peddolla Harshavardhan Reddy Date: Tue, 19 Aug 2025 12:31:16 +0000 (+0530) Subject: PR: Determine channels that are supported to perform ranging X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cfe7a215db0bfbd8264cced659fe59e3914d6459;p=thirdparty%2Fhostap.git PR: Determine channels that are supported to perform ranging Fetch supported channels for ranging and store them in Proximity Ranging global context. This includes channels where Enhanced Distributed channel Access (EDCA-802.11mc) is supported as well channels where Non-Trigger Based (NTB-802.11az) ranging is supported based on the corresponding format and bandwidth. Signed-off-by: Peddolla Harshavardhan Reddy --- diff --git a/src/common/proximity_ranging.h b/src/common/proximity_ranging.h index 6be3c4401..f26952fc2 100644 --- a/src/common/proximity_ranging.h +++ b/src/common/proximity_ranging.h @@ -11,11 +11,85 @@ #include "utils/list.h" +/** + * PR_MAX_OP_CLASSES - Maximum number of operating classes + */ +#define PR_MAX_OP_CLASSES 15 + +/** + * PR_MAX_OP_CLASS_CHANNELS - Maximum number of channels per operating class + */ +#define PR_MAX_OP_CLASS_CHANNELS 60 + /** * PR_MAX_PEER - Maximum number of Proximity Ranging peers that device can store */ #define PR_MAX_PEER 100 +/** + * struct pr_channels - List of supported channels + */ +struct pr_channels { + /** + * struct pr_op_class - Supported operating class + */ + struct pr_op_class { + /** + * op_class - Operating class + */ + u8 op_class; + + /** + * channel - Supported channels + */ + u8 channel[PR_MAX_OP_CLASS_CHANNELS]; + + /** + * channels - Number of channel entries in use + */ + size_t channels; + } op_class[PR_MAX_OP_CLASSES]; + + /** + * op_classes - Number of op_class entries in use + */ + size_t op_classes; +}; + +/** + * Format and Bandwidth values for EDCA based ranging with range of 10-16 + * from IEEE Std 802.11-2024, 9.4.2.166 (FTM Parameters element), Table 9-325 + * (Format And Bandwidth subfield) as specified in Proximity Ranging + * Implementation Considerations for P2P Operation, Draft 1.8, Table 8 + * (Proximity Ranging EDCA Capability Attribute format) for the the Ranging + * Parameters field B0-B3. + */ +enum edca_format_and_bw_value { + EDCA_FORMAT_AND_BW_VHT20 = 10, + EDCA_FORMAT_AND_BW_HT40 = 11, + EDCA_FORMAT_AND_BW_VHT40 = 12, + EDCA_FORMAT_AND_BW_VHT80 = 13, + EDCA_FORMAT_AND_BW_VHT80P80 = 14, + EDCA_FORMAT_AND_BW_VHT160_DUAL_LO = 15, + EDCA_FORMAT_AND_BW_VHT160_SINGLE_LO = 16, +}; + +/** + * Format and Bandwidth values for NTB based ranging as from IEEE Std + * 802.11-2024, 9.4.2.300 (Ranging Parameters element), Table 9-412 (Format And + * Bandwidth subfield) as specified in Proximity Ranging Implementation + * Considerations for P2P Operation, Draft 1.8, Table 9 (Proximity Ranging 11az + * NTB Capability Attribute format) for the Ranging Parameter field B0-B2. + */ +enum ntb_format_and_bw_value { + NTB_FORMAT_AND_BW_HE20 = 0, + NTB_FORMAT_AND_BW_HE40 = 1, + NTB_FORMAT_AND_BW_HE80 = 2, + NTB_FORMAT_AND_BW_HE80P80 = 3, + NTB_FORMAT_AND_BW_HE160_DUAL_LO = 4, + NTB_FORMAT_AND_BW_HE160_SINGLE_LO = 5, +}; + /** * struct pr_device_info - Proximity ranging peer information */ @@ -54,6 +128,8 @@ struct pr_config { u8 max_rx_antenna; + struct pr_channels edca_channels; + bool ntb_ista_support; bool ntb_rsta_support; @@ -78,6 +154,8 @@ struct pr_config { u8 ntb_format_and_bw; + struct pr_channels ntb_channels; + bool support_6ghz; /** diff --git a/wpa_supplicant/pr_supplicant.c b/wpa_supplicant/pr_supplicant.c index f0b00cd04..c8ce63a42 100644 --- a/wpa_supplicant/pr_supplicant.c +++ b/wpa_supplicant/pr_supplicant.c @@ -15,6 +15,229 @@ #include "pr_supplicant.h" +static int wpas_pr_edca_get_bw(enum edca_format_and_bw_value format_and_bw) +{ + switch (format_and_bw) { + case EDCA_FORMAT_AND_BW_VHT20: + return 20; + case EDCA_FORMAT_AND_BW_HT40: + case EDCA_FORMAT_AND_BW_VHT40: + return 40; + case EDCA_FORMAT_AND_BW_VHT80: + return 80; + case EDCA_FORMAT_AND_BW_VHT80P80: + case EDCA_FORMAT_AND_BW_VHT160_DUAL_LO: + case EDCA_FORMAT_AND_BW_VHT160_SINGLE_LO: + return 160; + default: + return 0; + } +} + + +static int wpas_pr_ntb_get_bw(enum ntb_format_and_bw_value format_and_bw) +{ + switch (format_and_bw) { + case NTB_FORMAT_AND_BW_HE20: + return 20; + case NTB_FORMAT_AND_BW_HE40: + return 40; + case NTB_FORMAT_AND_BW_HE80: + return 80; + case NTB_FORMAT_AND_BW_HE80P80: + case NTB_FORMAT_AND_BW_HE160_DUAL_LO: + case NTB_FORMAT_AND_BW_HE160_SINGLE_LO: + return 160; + default: + return 0; + } +} + + +static bool +wpas_pr_edca_is_valid_op_class(enum edca_format_and_bw_value format_and_bw, + const struct oper_class_map *op_class_map) +{ + int bw = 0, op_class_bw = 0; + + if (!op_class_map) + return false; + + op_class_bw = oper_class_bw_to_int(op_class_map); + bw = wpas_pr_edca_get_bw(format_and_bw); + + if (!op_class_bw || !bw) + return false; + + if (format_and_bw <= EDCA_FORMAT_AND_BW_VHT80 && + format_and_bw >= EDCA_FORMAT_AND_BW_VHT20 && + op_class_bw <= bw) + return true; + + if (format_and_bw == EDCA_FORMAT_AND_BW_VHT80P80 && + (op_class_bw < bw || op_class_map->bw == BW80P80)) + return true; + + if ((format_and_bw == EDCA_FORMAT_AND_BW_VHT160_DUAL_LO || + format_and_bw == EDCA_FORMAT_AND_BW_VHT160_SINGLE_LO) && + (op_class_bw < bw || op_class_map->bw == BW160)) + return true; + + return false; +} + + +static bool +wpas_pr_ntb_is_valid_op_class(enum ntb_format_and_bw_value format_and_bw, + const struct oper_class_map *op_class_map) +{ + int bw = 0, op_class_bw = 0; + + if (!op_class_map) + return false; + + op_class_bw = oper_class_bw_to_int(op_class_map); + bw = wpas_pr_ntb_get_bw(format_and_bw); + + if (!op_class_bw || !bw) + return false; + + if (format_and_bw <= NTB_FORMAT_AND_BW_HE80 && + format_and_bw >= NTB_FORMAT_AND_BW_HE20 && + op_class_bw <= bw) + return true; + + if (format_and_bw == NTB_FORMAT_AND_BW_HE80P80 && + (op_class_bw < bw || op_class_map->bw == BW80P80)) + return true; + + if ((format_and_bw == NTB_FORMAT_AND_BW_HE160_DUAL_LO || + format_and_bw == NTB_FORMAT_AND_BW_HE160_SINGLE_LO) && + (op_class_bw < bw || op_class_map->bw == BW160)) + return true; + + return false; +} + + +static void +wpas_pr_setup_edca_channels(struct wpa_supplicant *wpa_s, + struct pr_channels *chan, + enum edca_format_and_bw_value format_and_bw) +{ + struct hostapd_hw_modes *mode; + int cla = 0, i; + + for (i = 0; global_op_class[i].op_class; i++) { + unsigned int ch; + struct pr_op_class *op = NULL; + const struct oper_class_map *o = &global_op_class[i]; + + mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, o->mode, + is_6ghz_op_class(o->op_class)); + if (!mode || is_6ghz_op_class(o->op_class) || + !wpas_pr_edca_is_valid_op_class(format_and_bw, o)) + continue; + + for (ch = o->min_chan; ch <= o->max_chan; ch += o->inc) { + enum chan_allowed res; + + /* Check for non-continuous jump in channel index + * increment. + */ + if (o->op_class >= 128 && o->op_class <= 130 && + ch < 149 && ch + o->inc > 149) + ch = 149; + + res = verify_channel(mode, o->op_class, ch, o->bw); + + if (res == ALLOWED) { + if (!op) { + if (cla == PR_MAX_OP_CLASSES) + continue; + + wpa_printf(MSG_DEBUG, + "PR: Add operating class: %u (EDCA)", + o->op_class); + op = &chan->op_class[cla]; + cla++; + op->op_class = o->op_class; + } + if (op->channels == PR_MAX_OP_CLASS_CHANNELS) + continue; + op->channel[op->channels] = ch; + op->channels++; + } + } + + if (op) + wpa_hexdump(MSG_DEBUG, "PR: Channels (EDCA)", + op->channel, op->channels); + } + + chan->op_classes = cla; +} + + +static void +wpas_pr_setup_ntb_channels(struct wpa_supplicant *wpa_s, + struct pr_channels *chan, + enum ntb_format_and_bw_value format_and_bw, + bool allow_6ghz) +{ + int cla = 0, i; + struct hostapd_hw_modes *mode; + + for (i = 0; global_op_class[i].op_class; i++) { + unsigned int ch; + struct pr_op_class *op = NULL; + const struct oper_class_map *o = &global_op_class[i]; + + mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, o->mode, + is_6ghz_op_class(o->op_class)); + if (!mode || (!allow_6ghz && is_6ghz_op_class(o->op_class)) || + !wpas_pr_ntb_is_valid_op_class(format_and_bw, o)) + continue; + + for (ch = o->min_chan; ch <= o->max_chan; ch += o->inc) { + enum chan_allowed res; + + /* Check for non-continuous jump in channel index + * increment. + */ + if (o->op_class >= 128 && o->op_class <= 130 && + ch < 149 && ch + o->inc > 149) + ch = 149; + + res = verify_channel(mode, o->op_class, ch, o->bw); + + if (res == ALLOWED) { + if (!op) { + if (cla == PR_MAX_OP_CLASSES) + continue; + wpa_printf(MSG_DEBUG, + "PR: Add operating class: %u (NTB)", + o->op_class); + op = &chan->op_class[cla]; + cla++; + op->op_class = o->op_class; + } + if (op->channels == PR_MAX_OP_CLASS_CHANNELS) + continue; + op->channel[op->channels] = ch; + op->channels++; + } + } + if (op) { + wpa_hexdump(MSG_DEBUG, "PR: Channels (NTB)", + op->channel, op->channels); + } + } + + chan->op_classes = cla; +} + + int wpas_pr_init(struct wpa_global *global, struct wpa_supplicant *wpa_s, const struct wpa_driver_capa *capa) { @@ -39,6 +262,9 @@ int wpas_pr_init(struct wpa_global *global, struct wpa_supplicant *wpa_s, pr.max_rx_antenna = capa->max_rx_antenna; pr.max_tx_antenna = capa->max_tx_antenna; + wpas_pr_setup_edca_channels(wpa_s, &pr.edca_channels, + pr.edca_format_and_bw); + pr.ntb_ista_support = wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_NON_TRIGGER_BASED_INITIATOR; pr.ntb_rsta_support = wpa_s->drv_flags2 & @@ -57,6 +283,10 @@ int wpas_pr_init(struct wpa_global *global, struct wpa_supplicant *wpa_s, pr.secure_he_ltf = wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_SEC_LTF_STA; + wpas_pr_setup_ntb_channels(wpa_s, &pr.ntb_channels, + pr.ntb_format_and_bw, + pr.support_6ghz); + if (wpa_s->conf->country[0] && wpa_s->conf->country[1]) { os_memcpy(pr.country, wpa_s->conf->country, 2); pr.country[2] = 0x04;