[PATCH 5/6] wpa_supplicant: preserve freq_khz metadata
James Ewing
james at teledatics.com
Tue Sep 30 12:13:29 PDT 2025
Keep the kHz-level channel information that the driver now reports by
storing freq_khz/freq_offset in the BSS cache, IBSS frequency selection,
and association parameters. Expose the new fields via the CTRL interface
so downstream tooling can verify S1G chandefs end-to-end.
Tested: tests/hwsim/run_s1g_smoke.sh
Signed-off-by: James Ewing <james at teledatics.com>
---
wpa_supplicant/bss.c | 4 ++++
wpa_supplicant/bss.h | 4 ++++
wpa_supplicant/ctrl_iface.c | 14 ++++++++++++++
wpa_supplicant/scan.c | 32 +++++++++++++++++++------------
wpa_supplicant/wpa_supplicant.c | 9 +++++++++
wpa_supplicant/wpa_supplicant_i.h | 2 ++
6 files changed, 53 insertions(+), 12 deletions(-)
diff --git a/wpa_supplicant/bss.c b/wpa_supplicant/bss.c
index 58adaf744..8937dc516 100644
--- a/wpa_supplicant/bss.c
+++ b/wpa_supplicant/bss.c
@@ -384,6 +384,10 @@ static void wpa_bss_copy_res(struct wpa_bss *dst,
struct wpa_scan_res *src,
dst->flags = src->flags;
os_memcpy(dst->bssid, src->bssid, ETH_ALEN);
dst->freq = src->freq;
+ dst->freq_khz = src->freq_khz;
+ if (!dst->freq_khz && src->freq > 0)
+ dst->freq_khz = src->freq * 1000;
+ dst->freq_offset = src->freq_offset;
dst->max_cw = src->max_cw;
dst->beacon_int = src->beacon_int;
dst->caps = src->caps;
diff --git a/wpa_supplicant/bss.h b/wpa_supplicant/bss.h
index 74ef3c858..b78759942 100644
--- a/wpa_supplicant/bss.h
+++ b/wpa_supplicant/bss.h
@@ -93,6 +93,10 @@ struct wpa_bss {
size_t ssid_len;
/** Frequency of the channel in MHz (e.g., 2412 = channel 1) */
int freq;
+ /** Frequency in kHz when provided by the driver (0 if unknown) */
+ unsigned int freq_khz;
+ /** Frequency offset in kHz relative to @freq */
+ unsigned int freq_offset;
/** The max channel width supported by both the AP and the STA */
enum chan_width max_cw;
/** Beacon interval in TUs (host byte order) */
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index ebcc5d7ee..d27f9cac0 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -5387,6 +5387,20 @@ static int print_bss_info(struct wpa_supplicant
*wpa_s, struct wpa_bss *bss,
if (os_snprintf_error(end - pos, ret))
return 0;
pos += ret;
+ if (bss->freq_khz) {
+ ret = os_snprintf(pos, end - pos, "freq_khz=%u\n",
+ bss->freq_khz);
+ if (os_snprintf_error(end - pos, ret))
+ return 0;
+ pos += ret;
+ }
+ if (bss->freq_offset) {
+ ret = os_snprintf(pos, end - pos, "freq_offset=%u\n",
+ bss->freq_offset);
+ if (os_snprintf_error(end - pos, ret))
+ return 0;
+ pos += ret;
+ }
}
if (mask & WPA_BSS_MASK_BEACON_INT) {
diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c
index a4824678d..d1132163c 100644
--- a/wpa_supplicant/scan.c
+++ b/wpa_supplicant/scan.c
@@ -3303,9 +3303,11 @@ unsigned int wpas_get_est_tpt(const struct
wpa_supplicant *wpa_s,
(IS_2P4GHZ(freq) ?
HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_IN_2G :
HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G)) && ht40) {
- if (*max_cw == CHAN_WIDTH_UNKNOWN ||
- *max_cw < CHAN_WIDTH_40)
- *max_cw = CHAN_WIDTH_40;
+ if (*max_cw == CHAN_WIDTH_UNKNOWN ||
+ channel_width_to_int(*max_cw) <
+ channel_width_to_int(CHAN_WIDTH_40)) {
+ *max_cw = CHAN_WIDTH_40;
+ }
adjusted_snr = snr + wpas_channel_width_rssi_bump(
ies, ies_len, CHAN_WIDTH_40);
tmp = max_he_eht_rate(he40_table, adjusted_snr,
@@ -3317,9 +3319,11 @@ unsigned int wpas_get_est_tpt(const struct
wpa_supplicant *wpa_s,
if (!IS_2P4GHZ(freq) &&
(cw & HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G) &&
(!IS_5GHZ(freq) || vht80)) {
- if (*max_cw == CHAN_WIDTH_UNKNOWN ||
- *max_cw < CHAN_WIDTH_80)
- *max_cw = CHAN_WIDTH_80;
+ if (*max_cw == CHAN_WIDTH_UNKNOWN ||
+ channel_width_to_int(*max_cw) <
+ channel_width_to_int(CHAN_WIDTH_80)) {
+ *max_cw = CHAN_WIDTH_80;
+ }
adjusted_snr = snr + wpas_channel_width_rssi_bump(
ies, ies_len, CHAN_WIDTH_80);
@@ -3341,9 +3345,11 @@ unsigned int wpas_get_est_tpt(const struct
wpa_supplicant *wpa_s,
(cw & (HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G |
HE_PHYCAP_CHANNEL_WIDTH_SET_80PLUS80MHZ_IN_5G)) &&
(!IS_5GHZ(freq) || vht160)) {
- if (*max_cw == CHAN_WIDTH_UNKNOWN ||
- *max_cw < CHAN_WIDTH_160)
- *max_cw = CHAN_WIDTH_160;
+ if (*max_cw == CHAN_WIDTH_UNKNOWN ||
+ channel_width_to_int(*max_cw) <
+ channel_width_to_int(CHAN_WIDTH_160)) {
+ *max_cw = CHAN_WIDTH_160;
+ }
adjusted_snr = snr + wpas_channel_width_rssi_bump(
ies, ies_len, CHAN_WIDTH_160);
@@ -3368,9 +3374,11 @@ unsigned int wpas_get_est_tpt(const struct
wpa_supplicant *wpa_s,
if (is_6ghz_freq(freq) &&
(eht->phy_cap[EHT_PHYCAP_320MHZ_IN_6GHZ_SUPPORT_IDX] &
EHT_PHYCAP_320MHZ_IN_6GHZ_SUPPORT_MASK)) {
- if (*max_cw == CHAN_WIDTH_UNKNOWN ||
- *max_cw < CHAN_WIDTH_320)
- *max_cw = CHAN_WIDTH_320;
+ if (*max_cw == CHAN_WIDTH_UNKNOWN ||
+ channel_width_to_int(*max_cw) <
+ channel_width_to_int(CHAN_WIDTH_320)) {
+ *max_cw = CHAN_WIDTH_320;
+ }
adjusted_snr = snr + wpas_channel_width_rssi_bump(
ies, ies_len, CHAN_WIDTH_320);
diff --git a/wpa_supplicant/wpa_supplicant.c
b/wpa_supplicant/wpa_supplicant.c
index d45002fd9..1928c476e 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -3469,6 +3469,8 @@ void ibss_mesh_setup_freq(struct wpa_supplicant
*wpa_s,
bool is_6ghz, is_24ghz;
freq->freq = ssid->frequency;
+ freq->freq_khz = freq->freq > 0 ? freq->freq * 1000 : 0;
+ freq->freq_offset = 0;
if (ssid->mode == WPAS_MODE_IBSS && !ssid->fixed_freq) {
struct wpa_bss *bss = ibss_find_existing_bss(wpa_s, ssid);
@@ -3478,6 +3480,9 @@ void ibss_mesh_setup_freq(struct wpa_supplicant
*wpa_s,
"IBSS already found in scan results, adjust control
freq: %d",
bss->freq);
freq->freq = bss->freq;
+ freq->freq_khz = bss->freq_khz ? bss->freq_khz :
+ (bss->freq > 0 ? bss->freq * 1000 : 0);
+ freq->freq_offset = bss->freq_offset;
obss_scan = 0;
}
}
@@ -4640,6 +4645,10 @@ static void wpas_start_assoc_cb(struct
wpa_radio_work *work, int deinit)
wpa_s->key_mgmt == WPA_KEY_MGMT_WPS);
params.bssid = bss->bssid;
params.freq.freq = bss->freq;
+ params.freq.freq_khz = bss->freq_khz;
+ if (!params.freq.freq_khz && bss->freq > 0)
+ params.freq.freq_khz = bss->freq * 1000;
+ params.freq.freq_offset = bss->freq_offset;
}
params.bssid_hint = bss->bssid;
params.freq_hint = bss->freq;
diff --git a/wpa_supplicant/wpa_supplicant_i.h
b/wpa_supplicant/wpa_supplicant_i.h
index e7675a4ab..d1c41fdcc 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -1003,6 +1003,8 @@ struct wpa_supplicant {
u8 ssid[SSID_MAX_LEN];
size_t ssid_len;
int freq;
+ unsigned int freq_khz;
+ unsigned int freq_offset;
u8 assoc_req_ie[1500];
size_t assoc_req_ie_len;
int mfp;
--
2.43.0
More information about the Hostap
mailing list