diff mbox series

[3/4] nl82011: support frequency offset

Message ID 20200618061534.29646-4-thomas@adapt-ip.com
State Changes Requested
Headers show
Series convert internal units to KHz | expand

Commit Message

Thomas Pedersen June 18, 2020, 6:15 a.m. UTC
nl80211 recently gained the ability to accept a KHz offset
to a frequency otherwise specified in MHz. Since the
internal hostap units are now KHz, we can support this by
supplying the KHz frequency modulo 1000.

Signed-off-by: Thomas Pedersen <thomas@adapt-ip.com>
---
 src/drivers/driver_nl80211.c       | 10 ++++++++++
 src/drivers/driver_nl80211_capa.c  |  3 +++
 src/drivers/driver_nl80211_event.c | 22 ++++++++++++++--------
 src/drivers/driver_nl80211_scan.c  |  3 +++
 4 files changed, 30 insertions(+), 8 deletions(-)
diff mbox series

Patch

diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 7329e60403d5..7873654369f7 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -3667,6 +3667,9 @@  retry:
 		wpa_printf(MSG_DEBUG, "  * freq=%g", PR_KHZ(params->freq));
 		if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, MHZ(params->freq)))
 			goto fail;
+		if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ_OFFSET,
+				params->freq % 1000))
+			goto fail;
 	}
 	if (params->ssid) {
 		wpa_printf(MSG_DEBUG, "  * SSID=%s",
@@ -4550,6 +4553,8 @@  static int nl80211_put_freq_params(struct nl_msg *msg, const u64 flags,
 	wpa_printf(MSG_DEBUG, "  * freq=%g", PR_KHZ(freq->freq));
 	if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, MHZ(freq->freq)))
 		return -ENOBUFS;
+	if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ_OFFSET, freq->freq % 1000))
+		return -ENOBUFS;
 
 	wpa_printf(MSG_DEBUG, "  * he_enabled=%d", freq->he_enabled);
 	wpa_printf(MSG_DEBUG, "  * vht_enabled=%d", freq->vht_enabled);
@@ -5742,6 +5747,9 @@  static int nl80211_connect_common(struct wpa_driver_nl80211_data *drv,
 		if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ,
 				MHZ(params->freq.freq)))
 			return -1;
+		if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ_OFFSET,
+				params->freq.freq % 1000))
+			return -1;
 		drv->assoc_freq = params->freq.freq;
 	} else
 		drv->assoc_freq = 0;
@@ -7733,6 +7741,8 @@  static int nl80211_send_frame_cmd(struct i802_bss *bss,
 	if (!(msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_FRAME)) ||
 	    (freq && nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ,
 				 MHZ(freq))) ||
+	    (freq && nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ_OFFSET,
+				 freq % 1000)) ||
 	    (wait && nla_put_u32(msg, NL80211_ATTR_DURATION, wait)) ||
 	    (offchanok && ((drv->capa.flags & WPA_DRIVER_FLAGS_OFFCHANNEL_TX) ||
 			   drv->test_use_roc_tx) &&
diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
index f26bd45df6f9..f84a9988623d 100644
--- a/src/drivers/driver_nl80211_capa.c
+++ b/src/drivers/driver_nl80211_capa.c
@@ -1506,6 +1506,9 @@  static void phy_info_freq(struct hostapd_hw_modes *mode,
 	chan->allowed_bw = ~0;
 	chan->dfs_cac_ms = 0;
 
+	if (tb_freq[NL80211_FREQUENCY_ATTR_OFFSET])
+		chan->freq += nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_OFFSET]);
+
 	if (ieee80211_freq_to_chan(chan->freq, &channel) != NUM_HOSTAPD_MODES)
 		chan->chan = channel;
 	else
diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c
index 430bf7ddbb79..e02533fe8107 100644
--- a/src/drivers/driver_nl80211_event.c
+++ b/src/drivers/driver_nl80211_event.c
@@ -635,8 +635,7 @@  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,
+static void mlme_event_mgmt(struct i802_bss *bss, u32 freq, struct nlattr *sig,
 			    const u8 *frame, size_t len)
 {
 	struct wpa_driver_nl80211_data *drv = bss->drv;
@@ -660,10 +659,8 @@  static void mlme_event_mgmt(struct i802_bss *bss,
 		ssi_signal = (s32) nla_get_u32(sig);
 
 	os_memset(&event, 0, sizeof(event));
-	if (freq) {
-		event.rx_mgmt.freq = KHZ(nla_get_u32(freq));
-		rx_freq = drv->last_mgmt_freq = event.rx_mgmt.freq;
-	}
+	event.rx_mgmt.freq = freq;
+	rx_freq = drv->last_mgmt_freq = event.rx_mgmt.freq;
 	wpa_printf(MSG_DEBUG,
 		   "nl80211: RX frame da=" MACSTR " sa=" MACSTR " bssid=" MACSTR
 		   " freq=%g ssi_signal=%d fc=0x%x seq_ctrl=0x%x stype=%u (%s) len=%u",
@@ -914,11 +911,13 @@  static void mlme_event_unprot_beacon(struct wpa_driver_nl80211_data *drv,
 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 wpa_driver_nl80211_data *drv = bss->drv;
+	u32 frequency = 0;
 	const u8 *data;
 	size_t len;
 
@@ -934,6 +933,11 @@  static void mlme_event(struct i802_bss *bss,
 		return;
 	}
 
+	if (freq)
+		frequency = KHZ(nla_get_u32(freq));
+	if (freq_offset)
+		frequency += nla_get_u32(freq_offset);
+
 	data = nla_data(frame);
 	len = nla_len(frame);
 	if (len < 4 + 2 * ETH_ALEN) {
@@ -977,7 +981,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, frequency, sig, nla_data(frame),
 				nla_len(frame));
 		break;
 	case NL80211_CMD_FRAME_TX_STATUS:
@@ -2661,6 +2665,7 @@  static void do_process_drv_event(struct i802_bss *bss, int cmd,
 		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_WIPHY_FREQ_OFFSET],
 			   tb[NL80211_ATTR_ACK],
 			   tb[NL80211_ATTR_COOKIE],
 			   tb[NL80211_ATTR_RX_SIGNAL_DBM],
@@ -2856,6 +2861,7 @@  int process_bss_event(struct nl_msg *msg, void *arg)
 		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_WIPHY_FREQ_OFFSET],
 			   tb[NL80211_ATTR_ACK],
 			   tb[NL80211_ATTR_COOKIE],
 			   tb[NL80211_ATTR_RX_SIGNAL_DBM],
diff --git a/src/drivers/driver_nl80211_scan.c b/src/drivers/driver_nl80211_scan.c
index 44c6a8ef312e..fad5234b7c6b 100644
--- a/src/drivers/driver_nl80211_scan.c
+++ b/src/drivers/driver_nl80211_scan.c
@@ -703,6 +703,7 @@  nl80211_parse_bss_info(struct wpa_driver_nl80211_data *drv,
 	static struct nla_policy bss_policy[NL80211_BSS_MAX + 1] = {
 		[NL80211_BSS_BSSID] = { .type = NLA_UNSPEC },
 		[NL80211_BSS_FREQUENCY] = { .type = NLA_U32 },
+		[NL80211_BSS_FREQUENCY_OFFSET] = { .type = NLA_U32 },
 		[NL80211_BSS_TSF] = { .type = NLA_U64 },
 		[NL80211_BSS_BEACON_INTERVAL] = { .type = NLA_U16 },
 		[NL80211_BSS_CAPABILITY] = { .type = NLA_U16 },
@@ -755,6 +756,8 @@  nl80211_parse_bss_info(struct wpa_driver_nl80211_data *drv,
 			  ETH_ALEN);
 	if (bss[NL80211_BSS_FREQUENCY])
 		r->freq = KHZ(nla_get_u32(bss[NL80211_BSS_FREQUENCY]));
+	if (bss[NL80211_BSS_FREQUENCY_OFFSET])
+		r->freq += 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])