[RFC 2/8] nl80211: introduce freq_offset support
Lachlan Hodges
lachlan.hodges at morsemicro.com
Wed May 27 23:38:51 PDT 2026
Introduce the ability to handle S1G channels by introducing the
`freq_offset` parameter to the nl80211 driver to handle S1G channels.
Signed-off-by: Lachlan Hodges <lachlan.hodges at morsemicro.com>
---
src/drivers/driver_nl80211.c | 106 ++++++++++++++++++++---------
src/drivers/driver_nl80211.h | 3 +
src/drivers/driver_nl80211_capa.c | 30 +++++---
src/drivers/driver_nl80211_event.c | 26 ++++---
src/drivers/driver_nl80211_scan.c | 34 ++++++---
5 files changed, 141 insertions(+), 58 deletions(-)
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index f79558911feb..df82c1b670e3 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -169,7 +169,8 @@ wpa_driver_nl80211_finish_drv_init(struct i802_bss *bss,
const char *driver_params,
enum wpa_p2p_mode p2p_mode);
static int nl80211_send_frame_cmd(struct i802_bss *bss,
- unsigned int freq, unsigned int wait,
+ unsigned int freq, unsigned int freq_offset,
+ unsigned int wait,
const u8 *buf, size_t buf_len,
int save_cookie, int no_cck, int no_ack,
int offchanok, const u16 *csa_offs,
@@ -1715,6 +1716,7 @@ static void wpa_driver_nl80211_event_rtm_dellink(void *ctx,
struct nl80211_get_assoc_freq_arg {
struct wpa_driver_nl80211_data *drv;
unsigned int assoc_freq;
+ unsigned int assoc_freq_offset;
unsigned int ibss_freq;
u8 assoc_bssid[ETH_ALEN];
u8 assoc_ssid[SSID_MAX_LEN];
@@ -1766,8 +1768,12 @@ static int nl80211_get_assoc_freq_handler(struct nl_msg *msg, void *arg)
if (!drv->sta_mlo_info.valid_links ||
drv->sta_mlo_info.assoc_link_id == link_id) {
ctx->assoc_freq = freq;
- wpa_printf(MSG_DEBUG, "nl80211: Associated on %u MHz",
- ctx->assoc_freq);
+ if (bss[NL80211_BSS_FREQUENCY_OFFSET])
+ ctx->assoc_freq_offset =
+ nla_get_u32(bss[NL80211_BSS_FREQUENCY_OFFSET]);
+
+ wpa_printf(MSG_DEBUG, "nl80211: Associated on %u.%u MHz",
+ ctx->assoc_freq, ctx->assoc_freq_offset);
}
}
if (status == NL80211_BSS_STATUS_IBSS_JOINED &&
@@ -1879,10 +1885,13 @@ try_again:
if (ret == 0) {
unsigned int freq = drv->nlmode == NL80211_IFTYPE_ADHOC ?
arg.ibss_freq : arg.assoc_freq;
+ unsigned int freq_offset = arg.assoc_freq_offset;
wpa_printf(MSG_DEBUG, "nl80211: Operating frequency for the "
- "associated BSS from scan results: %u MHz", freq);
- if (freq)
+ "associated BSS from scan results: %u MHz offset: %d KHz", freq, freq_offset);
+ if (freq) {
drv->assoc_freq = freq;
+ drv->assoc_freq_offset = freq_offset;
+ }
if (drv->sta_mlo_info.valid_links) {
int i;
@@ -4673,11 +4682,17 @@ retry:
if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, params->bssid))
goto fail;
}
- if (params->freq) {
- wpa_printf(MSG_DEBUG, " * freq=%d", params->freq);
+ if(params->freq){
+ wpa_printf(MSG_DEBUG, " * freq=%d MHz", params->freq);
if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, params->freq))
goto fail;
}
+ if (params->freq_offset) {
+ wpa_printf(MSG_DEBUG, " * freq_offset=%d KHz", params->freq_offset);
+ if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ_OFFSET,
+ params->freq_offset))
+ goto fail;
+ }
if (params->ssid) {
wpa_printf(MSG_DEBUG, " * SSID=%s",
wpa_ssid_txt(params->ssid, params->ssid_len));
@@ -4873,14 +4888,14 @@ u8 nl80211_get_link_id_from_link(struct i802_bss *bss, struct i802_link *link)
}
-static void nl80211_link_set_freq(struct i802_bss *bss, s8 link_id, int freq)
+static void nl80211_link_set_freq(struct i802_bss *bss, s8 link_id, int freq, int freq_offset)
{
struct i802_link *link = nl80211_get_link(bss, link_id);
link->freq = freq;
+ link->freq_offset = freq_offset;
}
-
static int nl80211_get_link_freq(struct i802_bss *bss, const u8 *addr,
bool bss_freq_debug)
{
@@ -4906,8 +4921,8 @@ static int nl80211_get_link_freq(struct i802_bss *bss, const u8 *addr,
static int wpa_driver_nl80211_send_mlme(struct i802_bss *bss, const u8 *data,
size_t data_len, int noack,
- unsigned int freq, int no_cck,
- int offchanok,
+ unsigned int freq, unsigned int freq_offset,
+ int no_cck, int offchanok,
unsigned int wait_time,
const u16 *csa_offs,
size_t csa_offs_len, int no_encrypt,
@@ -4953,9 +4968,10 @@ static int wpa_driver_nl80211_send_mlme(struct i802_bss *bss, const u8 *data,
* of wpa_supplicant.
*/
if (freq == 0) {
- wpa_printf(MSG_DEBUG, "nl80211: Use last_mgmt_freq=%d",
- drv->last_mgmt_freq);
+ wpa_printf(MSG_DEBUG, "nl80211: Use last_mgmt_freq=%d last_mgmt_freq_offset=%d",
+ drv->last_mgmt_freq, drv->last_mgmt_freq_offset);
freq = drv->last_mgmt_freq;
+ freq_offset = drv->last_mgmt_freq_offset;
}
wait_time = 0;
use_cookie = 0;
@@ -4967,9 +4983,13 @@ static int wpa_driver_nl80211_send_mlme(struct i802_bss *bss, const u8 *data,
if (drv->device_ap_sme && is_ap_interface(drv->nlmode)) {
unsigned int link_freq = nl80211_get_link_freq(bss, mgmt->sa,
!freq);
+ /* S1G is exempt from MLO so will always be default link */
+ unsigned int link_freq_offset = bss->flink->freq_offset;
- if (!freq)
+ if (!freq) {
freq = link_freq;
+ freq_offset = link_freq_offset;
+ }
if (freq == link_freq)
wait_time = 0;
@@ -4986,9 +5006,10 @@ static int wpa_driver_nl80211_send_mlme(struct i802_bss *bss, const u8 *data,
(drv->capa.flags & WPA_DRIVER_FLAGS_SAE) &&
!(drv->capa.flags & WPA_DRIVER_FLAGS_SME)) {
freq = nl80211_get_assoc_freq(drv);
+ freq_offset = drv->assoc_freq_offset;
wpa_printf(MSG_DEBUG,
- "nl80211: send_mlme - Use assoc_freq=%u for external auth",
- freq);
+ "nl80211: send_mlme - Use assoc_freq=%u assoc_freq_offset=%u for external auth",
+ freq, freq_offset);
}
/* Allow off channel for PASN authentication */
@@ -5021,9 +5042,10 @@ static int wpa_driver_nl80211_send_mlme(struct i802_bss *bss, const u8 *data,
freq);
}
if (freq == 0) {
- wpa_printf(MSG_DEBUG, "nl80211: send_mlme - Use bss->freq=%u",
- link->freq);
+ wpa_printf(MSG_DEBUG, "nl80211: send_mlme - Use bss->freq=%u bss->freq_offset=%u",
+ link->freq, link->freq_offset);
freq = link->freq;
+ freq_offset = link->freq_offset;
}
if ((noack || WLAN_FC_GET_TYPE(fc) != WLAN_FC_TYPE_MGMT ||
@@ -5041,7 +5063,7 @@ send_frame_cmd:
#endif /* CONFIG_TESTING_OPTIONS */
wpa_printf(MSG_DEBUG, "nl80211: send_mlme -> send_frame_cmd");
- res = nl80211_send_frame_cmd(bss, freq, wait_time, data, data_len,
+ res = nl80211_send_frame_cmd(bss, freq, freq_offset, wait_time, data, data_len,
use_cookie, no_cck, noack, offchanok,
csa_offs, csa_offs_len, link_id);
if (!res)
@@ -5636,6 +5658,9 @@ static int nl80211_put_freq_params(struct nl_msg *msg,
wpa_printf(MSG_DEBUG, " * freq=%d", freq->freq);
if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq->freq))
return -ENOBUFS;
+ wpa_printf(MSG_DEBUG, " * freq_offset=%d", freq->freq_offset);
+ if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ_OFFSET, freq->freq_offset))
+ return -ENOBUFS;
wpa_printf(MSG_DEBUG, " * eht_enabled=%d", freq->eht_enabled);
wpa_printf(MSG_DEBUG, " * he_enabled=%d", freq->he_enabled);
@@ -5799,7 +5824,8 @@ static int wpa_driver_nl80211_set_ap(void *priv,
nl80211_link_set_freq(bss,
params->mld_ap ? params->mld_link_id :
NL80211_DRV_LINK_ID_NA,
- params->freq->freq);
+ params->freq->freq,
+ params->freq->freq_offset);
if (params->mld_ap) {
wpa_printf(MSG_DEBUG, "nl80211: link_id=%u",
@@ -6167,10 +6193,10 @@ static int nl80211_set_channel(struct i802_bss *bss,
int ret;
wpa_printf(MSG_DEBUG,
- "nl80211: Set freq %d (ht_enabled=%d, vht_enabled=%d, he_enabled=%d, eht_enabled=%d, bandwidth=%d MHz, cf1=%d MHz, cf2=%d MHz)",
- freq->freq, freq->ht_enabled, freq->vht_enabled,
+ "nl80211: Set freq %d offset %d (ht_enabled=%d, vht_enabled=%d, he_enabled=%d, eht_enabled=%d, , bandwidth=%d MHz, cf1=%d MHz, cf1_offset=%d KHz cf2=%d MHz)",
+ freq->freq, freq->freq_offset, freq->ht_enabled, freq->vht_enabled,
freq->he_enabled, freq->eht_enabled, freq->bandwidth,
- freq->center_freq1, freq->center_freq2);
+ freq->center_freq1, freq->center_freq1_offset, freq->center_freq2);
msg = nl80211_bss_msg(bss, 0, set_chan ? NL80211_CMD_SET_CHANNEL :
NL80211_CMD_SET_WIPHY);
@@ -6191,7 +6217,7 @@ static int nl80211_set_channel(struct i802_bss *bss,
ret = send_and_recv_cmd(drv, msg);
if (ret == 0) {
- nl80211_link_set_freq(bss, freq->link_id, freq->freq);
+ nl80211_link_set_freq(bss, freq->link_id, freq->freq, freq->freq_offset);
return 0;
}
wpa_printf(MSG_DEBUG, "nl80211: Failed to set channel (freq=%d): "
@@ -7534,6 +7560,16 @@ static int nl80211_connect_common(struct wpa_driver_nl80211_data *drv,
}
drv->assoc_freq = params->freq.freq;
+
+ if (params->freq.freq_offset && !params->mld_params.mld_addr) {
+ wpa_printf(MSG_DEBUG, " * freq_offset=%d",
+ params->freq.freq_offset);
+ if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ_OFFSET,
+ params->freq.freq_offset))
+ return -1;
+
+ drv->assoc_freq_offset = params->freq.freq_offset;
+ }
}
if (params->freq_hint) {
@@ -9141,7 +9177,7 @@ static int i802_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr,
return wpa_driver_nl80211_send_mlme(bss, (u8 *) &mgmt,
IEEE80211_HDRLEN +
sizeof(mgmt.u.deauth), 0, 0, 0, 0,
- 0, NULL, 0, 0, link_id);
+ 0, 0, NULL, 0, 0, link_id);
}
@@ -9168,7 +9204,7 @@ static int i802_sta_disassoc(void *priv, const u8 *own_addr, const u8 *addr,
return wpa_driver_nl80211_send_mlme(bss, (u8 *) &mgmt,
IEEE80211_HDRLEN +
sizeof(mgmt.u.disassoc), 0, 0, 0, 0,
- 0, NULL, 0, 0, link_id);
+ 0, 0, NULL, 0, 0, link_id);
}
@@ -9927,7 +9963,8 @@ static int cookie_handler(struct nl_msg *msg, void *arg)
static int nl80211_send_frame_cmd(struct i802_bss *bss,
- unsigned int freq, unsigned int wait,
+ unsigned int freq, unsigned int freq_offset,
+ unsigned int wait,
const u8 *buf, size_t buf_len,
int save_cookie, int no_cck, int no_ack,
int offchanok, const u16 *csa_offs,
@@ -9938,15 +9975,16 @@ static int nl80211_send_frame_cmd(struct i802_bss *bss,
u64 cookie;
int ret = -1;
- wpa_printf(MSG_MSGDUMP, "nl80211: CMD_FRAME freq=%u wait=%u no_cck=%d "
+ wpa_printf(MSG_MSGDUMP, "nl80211: CMD_FRAME freq=%u freq_offset=%u wait=%u no_cck=%d "
"no_ack=%d offchanok=%d",
- freq, wait, no_cck, no_ack, offchanok);
+ freq, freq_offset, wait, no_cck, no_ack, offchanok);
wpa_hexdump(MSG_MSGDUMP, "CMD_FRAME", buf, buf_len);
if (!(msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_FRAME)) ||
((link_id != NL80211_DRV_LINK_ID_NA) &&
nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID, link_id)) ||
(freq && nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq)) ||
+ (freq_offset && nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ_OFFSET, freq_offset)) ||
(wait && nla_put_u32(msg, NL80211_ATTR_DURATION, wait)) ||
(offchanok && ((drv->capa.flags & WPA_DRIVER_FLAGS_OFFCHANNEL_TX) ||
drv->test_use_roc_tx) &&
@@ -10079,11 +10117,11 @@ static int wpa_driver_nl80211_send_action(struct i802_bss *bss,
if (is_ap_interface(drv->nlmode))
ret = wpa_driver_nl80211_send_mlme(bss, buf, 24 + data_len,
- 0, freq, no_cck, offchanok,
+ 0, freq, 0, no_cck, offchanok,
wait_time, NULL, 0, 0,
link_id);
else
- ret = nl80211_send_frame_cmd(bss, freq, wait_time, buf,
+ ret = nl80211_send_frame_cmd(bss, freq, 0, wait_time, buf,
24 + data_len, 1, no_cck, 0,
offchanok, NULL, 0, link_id);
@@ -11353,7 +11391,7 @@ static void nl80211_send_null_frame(struct i802_bss *bss, const u8 *own_addr,
os_memcpy(nulldata.hdr.IEEE80211_SA_FROMDS, own_addr, ETH_ALEN);
if (wpa_driver_nl80211_send_mlme(bss, (u8 *) &nulldata, size, 0, 0, 0,
- 0, 0, NULL, 0, 0, -1) < 0)
+ 0, 0, 0, NULL, 0, 0, -1) < 0)
wpa_printf(MSG_DEBUG, "nl80211_send_null_frame: Failed to "
"send poll frame");
}
@@ -11477,7 +11515,7 @@ static int nl80211_start_radar_detection(void *priv,
ret = send_and_recv_cmd(drv, msg);
if (ret == 0) {
- nl80211_link_set_freq(bss, freq->link_id, freq->freq);
+ nl80211_link_set_freq(bss, freq->link_id, freq->freq, 0);
return 0;
}
@@ -11857,7 +11895,7 @@ static int driver_nl80211_send_mlme(void *priv, const u8 *data,
{
struct i802_bss *bss = priv;
return wpa_driver_nl80211_send_mlme(bss, data, data_len, noack,
- freq, 0, 0, wait, csa_offs,
+ freq, freq_offset, 0, 0, wait, csa_offs,
csa_offs_len, no_encrypt, link_id);
}
diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h
index 9c871ce18e63..14c3a542ecae 100644
--- a/src/drivers/driver_nl80211.h
+++ b/src/drivers/driver_nl80211.h
@@ -75,6 +75,7 @@ struct i802_link {
unsigned int beacon_set:1;
int freq;
+ int freq_offset;
int bandwidth;
u8 addr[ETH_ALEN];
void *ctx;
@@ -173,6 +174,7 @@ struct wpa_driver_nl80211_data {
enum nl80211_iftype nlmode;
enum nl80211_iftype ap_scan_as_station;
unsigned int assoc_freq;
+ unsigned int assoc_freq_offset;
unsigned int disabled_11b_rates:1;
unsigned int pending_remain_on_chan:1;
@@ -236,6 +238,7 @@ struct wpa_driver_nl80211_data {
int eapol_tx_link_id;
unsigned int last_mgmt_freq;
+ unsigned int last_mgmt_freq_offset;
struct wpa_driver_scan_filter *filter_ssids;
size_t num_filter_ssids;
diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
index 66ccbbb3719c..e423eeeb4528 100644
--- a/src/drivers/driver_nl80211_capa.c
+++ b/src/drivers/driver_nl80211_capa.c
@@ -2171,6 +2171,7 @@ static void phy_info_freq(struct hostapd_hw_modes *mode,
os_memset(chan, 0, sizeof(*chan));
chan->freq = nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_FREQ]);
+ chan->freq_offset = nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_OFFSET]);
chan->flag = 0;
chan->allowed_bw = ~0;
chan->dfs_cac_ms = 0;
@@ -3152,14 +3153,27 @@ static void nl80211_dump_chan_list(struct wpa_driver_nl80211_data *drv,
drv->uses_6ghz = true;
if (chan->freq >= 900 && chan->freq < 1000)
drv->uses_s1g = true;
- res = os_snprintf(pos, end - pos, " %d%s%s%s",
- chan->freq,
- (chan->flag & HOSTAPD_CHAN_DISABLED) ?
- "[DISABLED]" : "",
- (chan->flag & HOSTAPD_CHAN_NO_IR) ?
- "[NO_IR]" : "",
- (chan->flag & HOSTAPD_CHAN_RADAR) ?
- "[RADAR]" : "");
+
+ if (drv->uses_s1g) {
+ /* For S1G, print frequency in KHz */
+ res = os_snprintf(pos, end - pos, " %d%s%s",
+ MHZ_TO_KHZ(chan->freq) + chan->freq_offset,
+ (chan->flag & HOSTAPD_CHAN_DISABLED) ?
+ "[DISABLED]" : "",
+ (chan->flag & HOSTAPD_CHAN_NO_IR) ?
+ "[NO_IR]" : "");
+ } else {
+ /* For normal operation, print frequency in MHz */
+ res = os_snprintf(pos, end - pos, " %d%s%s%s",
+ chan->freq,
+ (chan->flag & HOSTAPD_CHAN_DISABLED) ?
+ "[DISABLED]" : "",
+ (chan->flag & HOSTAPD_CHAN_NO_IR) ?
+ "[NO_IR]" : "",
+ (chan->flag & HOSTAPD_CHAN_RADAR) ?
+ "[RADAR]" : "");
+ }
+
if (os_snprintf_error(end - pos, res))
break;
pos += res;
diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c
index 1097c08b4e90..28e8a7123af6 100644
--- a/src/drivers/driver_nl80211_event.c
+++ b/src/drivers/driver_nl80211_event.c
@@ -1114,7 +1114,9 @@ static void mlme_event_connect(struct wpa_driver_nl80211_data *drv,
}
event.assoc_info.freq = nl80211_get_assoc_freq(drv);
+ event.assoc_info.freq_offset = drv->assoc_freq_offset;
drv->first_bss->flink->freq = drv->assoc_freq;
+ drv->first_bss->flink->freq_offset = drv->assoc_freq_offset;
if ((!ssid || ssid[1] == 0 || ssid[1] > 32) &&
(ssid_len = nl80211_get_assoc_ssid(drv, drv->ssid)) > 0) {
@@ -1424,8 +1426,8 @@ static void mlme_timeout_event(struct wpa_driver_nl80211_data *drv,
static void mlme_event_mgmt(struct i802_bss *bss,
- struct nlattr *freq, struct nlattr *sig,
- const u8 *frame, size_t len,
+ struct nlattr *freq, struct nlattr *freq_offset,
+ struct nlattr *sig, const u8 *frame, size_t len,
int link_id)
{
struct wpa_driver_nl80211_data *drv = bss->drv;
@@ -1434,6 +1436,7 @@ static void mlme_event_mgmt(struct i802_bss *bss,
u16 fc, stype;
int ssi_signal = 0;
int rx_freq = 0;
+ int rx_freq_offset = 0;
wpa_printf(MSG_MSGDUMP, "nl80211: Frame event");
mgmt = (const struct ieee80211_mgmt *) frame;
@@ -1451,13 +1454,15 @@ static void mlme_event_mgmt(struct i802_bss *bss,
os_memset(&event, 0, sizeof(event));
if (freq) {
event.rx_mgmt.freq = nla_get_u32(freq);
+ event.rx_mgmt.freq_offset = nla_get_u32(freq_offset);
rx_freq = drv->last_mgmt_freq = event.rx_mgmt.freq;
+ rx_freq_offset = drv->last_mgmt_freq_offset = event.rx_mgmt.freq_offset;
}
wpa_printf(MSG_DEBUG,
"nl80211: RX frame da=" MACSTR " sa=" MACSTR " bssid=" MACSTR
- " freq=%d ssi_signal=%d fc=0x%x seq_ctrl=0x%x stype=%u (%s) len=%u",
+ " freq=%d freq_offset=%d ssi_signal=%d fc=0x%x seq_ctrl=0x%x stype=%u (%s) len=%u",
MAC2STR(mgmt->da), MAC2STR(mgmt->sa), MAC2STR(mgmt->bssid),
- rx_freq, ssi_signal, fc,
+ rx_freq, rx_freq_offset, ssi_signal, fc,
le_to_host16(mgmt->seq_ctrl), stype, fc2str(fc),
(unsigned int) len);
event.rx_mgmt.frame = frame;
@@ -1842,7 +1847,8 @@ nl80211_get_link_id_by_freq(struct i802_bss *bss, unsigned int freq)
static void mlme_event(struct i802_bss *bss,
enum nl80211_commands cmd, struct nlattr *frame,
struct nlattr *addr, struct nlattr *timed_out,
- struct nlattr *freq, struct nlattr *ack,
+ struct nlattr *freq, struct nlattr *freq_offset,
+ struct nlattr *ack,
struct nlattr *cookie, struct nlattr *sig,
struct nlattr *wmm, struct nlattr *req_ie,
struct nlattr *link)
@@ -1959,7 +1965,7 @@ static void mlme_event(struct i802_bss *bss,
nla_data(frame), nla_len(frame));
break;
case NL80211_CMD_FRAME:
- mlme_event_mgmt(bss, freq, sig, nla_data(frame),
+ mlme_event_mgmt(bss, freq, freq_offset, sig, nla_data(frame),
nla_len(frame), link_id);
break;
case NL80211_CMD_FRAME_TX_STATUS:
@@ -4933,7 +4939,9 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd,
case NL80211_CMD_UNPROT_DISASSOCIATE:
mlme_event(bss, cmd, tb[NL80211_ATTR_FRAME],
tb[NL80211_ATTR_MAC], tb[NL80211_ATTR_TIMED_OUT],
- tb[NL80211_ATTR_WIPHY_FREQ], tb[NL80211_ATTR_ACK],
+ tb[NL80211_ATTR_WIPHY_FREQ],
+ tb[NL80211_ATTR_WIPHY_FREQ_OFFSET],
+ tb[NL80211_ATTR_ACK],
tb[NL80211_ATTR_COOKIE],
tb[NL80211_ATTR_RX_SIGNAL_DBM],
tb[NL80211_ATTR_STA_WME],
@@ -5326,7 +5334,9 @@ int process_bss_event(struct nl_msg *msg, void *arg)
case NL80211_CMD_FRAME_TX_STATUS:
mlme_event(bss, gnlh->cmd, tb[NL80211_ATTR_FRAME],
tb[NL80211_ATTR_MAC], tb[NL80211_ATTR_TIMED_OUT],
- tb[NL80211_ATTR_WIPHY_FREQ], tb[NL80211_ATTR_ACK],
+ tb[NL80211_ATTR_WIPHY_FREQ],
+ tb[NL80211_ATTR_WIPHY_FREQ_OFFSET],
+ tb[NL80211_ATTR_ACK],
tb[NL80211_ATTR_COOKIE],
tb[NL80211_ATTR_RX_SIGNAL_DBM],
tb[NL80211_ATTR_STA_WME], NULL,
diff --git a/src/drivers/driver_nl80211_scan.c b/src/drivers/driver_nl80211_scan.c
index b44f0a1d5b5a..6328d33dbfbb 100644
--- a/src/drivers/driver_nl80211_scan.c
+++ b/src/drivers/driver_nl80211_scan.c
@@ -251,16 +251,31 @@ nl80211_scan_common(struct i802_bss *bss, u8 cmd,
if (params->freqs) {
struct nlattr *freqs;
- freqs = nla_nest_start(msg, NL80211_ATTR_SCAN_FREQUENCIES);
- if (freqs == NULL)
- goto fail;
- for (i = 0; params->freqs[i]; i++) {
- wpa_printf(MSG_MSGDUMP, "nl80211: Scan frequency %u "
- "MHz", params->freqs[i]);
- if (nla_put_u32(msg, i + 1, params->freqs[i]))
+
+ i = 0;
+ if (params->freq_offset) {
+ freqs = nla_nest_start(msg, NL80211_ATTR_SCAN_FREQ_KHZ);
+ if (freqs == NULL)
goto fail;
+ for (; params->freqs[i]; i++) {
+ wpa_printf(MSG_MSGDUMP, "nl80211: Scan frequency %u "
+ "KHz", MHZ_TO_KHZ(params->freqs[i]) + params->freq_offset);
+ if (nla_put_u32(msg, i + 1, MHZ_TO_KHZ(params->freqs[i]) + params->freq_offset))
+ goto fail;
+ }
+ nla_nest_end(msg, freqs);
+ } else {
+ freqs = nla_nest_start(msg, NL80211_ATTR_SCAN_FREQUENCIES);
+ if (freqs == NULL)
+ goto fail;
+ for (; params->freqs[i]; i++) {
+ wpa_printf(MSG_MSGDUMP, "nl80211: Scan frequency %u "
+ "MHz", params->freqs[i]);
+ if (nla_put_u32(msg, i + 1, params->freqs[i]))
+ goto fail;
+ }
+ nla_nest_end(msg, freqs);
}
- nla_nest_end(msg, freqs);
}
os_free(drv->filter_ssids);
@@ -788,6 +803,7 @@ nl80211_parse_bss_info(struct wpa_driver_nl80211_data *drv,
[NL80211_BSS_PARENT_TSF] = { .type = NLA_U64 },
[NL80211_BSS_PARENT_BSSID] = { .type = NLA_UNSPEC },
[NL80211_BSS_LAST_SEEN_BOOTTIME] = { .type = NLA_U64 },
+ [NL80211_BSS_FREQUENCY_OFFSET] = { .type = NLA_U32 },
};
struct wpa_scan_res *r;
const u8 *ie, *beacon_ie;
@@ -831,6 +847,8 @@ nl80211_parse_bss_info(struct wpa_driver_nl80211_data *drv,
ETH_ALEN);
if (bss[NL80211_BSS_FREQUENCY])
r->freq = nla_get_u32(bss[NL80211_BSS_FREQUENCY]);
+ if (bss[NL80211_BSS_FREQUENCY_OFFSET])
+ r->freq_offset = nla_get_u32(bss[NL80211_BSS_FREQUENCY_OFFSET]);
if (bss[NL80211_BSS_BEACON_INTERVAL])
r->beacon_int = nla_get_u16(bss[NL80211_BSS_BEACON_INTERVAL]);
if (bss[NL80211_BSS_CAPABILITY])
--
2.43.0
More information about the Hostap
mailing list