summaryrefslogtreecommitdiff
path: root/sys/net80211
diff options
context:
space:
mode:
authorStefan Sperling <stsp@cvs.openbsd.org>2022-03-20 12:01:59 +0000
committerStefan Sperling <stsp@cvs.openbsd.org>2022-03-20 12:01:59 +0000
commit424bafeee6cdf0c7b8cad002411e5d9efad0ac85 (patch)
tree8fa476396947559a660fb1e68f28c792043fc6b2 /sys/net80211
parent8b7cfdd9f0073651f6759f7a077c8c9593cf76f8 (diff)
Introduce an alternative mechanism for wifi drivers to communicate
the channel on which a frame was received. ieee80211_inputm() was expecting that ic->ic_bss->ni_chan would correspond to the channel which is currently being scanned. This dates back to older devices which are manually tuned to the next channel by the driver during SCAN->SCAN state transitions. However, this approach is very awkward for drivers which scan across a whole range of channels in firmware. Such drivers had an ugly workaround in place which tweaked ni_chan for each received frame. Introduce a channel number field in the Rx info struct which drivers can use to indicate the channel on which a frame was received. If this field is set, net80211 will use it instead of using the current channel of ic_bss. Use this new mechanism in all affected drivers. Tested by jmc@, sthen@, and myself on iwm(4) and iwx(4). Changes to iwn(4) and bwfm(4) are the same mechanical changes to get rid of the ni_chan tweak, and are therefore expected to work. ok sthen@ dlg@
Diffstat (limited to 'sys/net80211')
-rw-r--r--sys/net80211/ieee80211_input.c20
-rw-r--r--sys/net80211/ieee80211_node.h3
2 files changed, 14 insertions, 9 deletions
diff --git a/sys/net80211/ieee80211_input.c b/sys/net80211/ieee80211_input.c
index 5b060797db5..212209fb7e3 100644
--- a/sys/net80211/ieee80211_input.c
+++ b/sys/net80211/ieee80211_input.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ieee80211_input.c,v 1.246 2022/03/20 07:50:32 stsp Exp $ */
+/* $OpenBSD: ieee80211_input.c,v 1.247 2022/03/20 12:01:58 stsp Exp $ */
/*-
* Copyright (c) 2001 Atsushi Onoe
@@ -1648,7 +1648,10 @@ ieee80211_recv_probe_resp(struct ieee80211com *ic, struct mbuf *m,
ssid = rates = xrates = edcaie = wmmie = rsnie = wpaie = tim = NULL;
htcaps = htop = vhtcaps = vhtop = NULL;
- bchan = ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan);
+ if (rxi->rxi_chan)
+ bchan = rxi->rxi_chan;
+ else
+ bchan = ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan);
chan = bchan;
erp = 0;
while (frm + 2 <= efrm) {
@@ -1744,9 +1747,10 @@ ieee80211_recv_probe_resp(struct ieee80211com *ic, struct mbuf *m,
ic->ic_stats.is_rx_badchan++;
return;
}
- if ((ic->ic_state != IEEE80211_S_SCAN ||
+ if ((rxi->rxi_chan != 0 && chan != rxi->rxi_chan) ||
+ ((ic->ic_state != IEEE80211_S_SCAN ||
!(ic->ic_caps & IEEE80211_C_SCANALL)) &&
- chan != bchan) {
+ chan != bchan)) {
/*
* Frame was received on a channel different from the
* one indicated in the DS params element id;
@@ -1783,11 +1787,13 @@ ieee80211_recv_probe_resp(struct ieee80211com *ic, struct mbuf *m,
} else
is_new = 0;
+ ni->ni_chan = &ic->ic_channels[chan];
+
if (htcaps)
ieee80211_setup_htcaps(ni, htcaps + 2, htcaps[1]);
if (htop && !ieee80211_setup_htop(ni, htop + 2, htop[1], 1))
htop = NULL; /* invalid HTOP */
- if (htcaps && vhtcaps && IEEE80211_IS_CHAN_5GHZ(ic->ic_bss->ni_chan)) {
+ if (htcaps && vhtcaps && IEEE80211_IS_CHAN_5GHZ(ni->ni_chan)) {
ieee80211_setup_vhtcaps(ni, vhtcaps + 2, vhtcaps[1]);
if (vhtop && !ieee80211_setup_vhtop(ni, vhtop + 2, vhtop[1], 1))
vhtop = NULL; /* invalid VHTOP */
@@ -1984,8 +1990,6 @@ ieee80211_recv_probe_resp(struct ieee80211com *ic, struct mbuf *m,
memcpy(ni->ni_essid, &ssid[2], ssid[1]);
}
IEEE80211_ADDR_COPY(ni->ni_bssid, wh->i_addr3);
- /* XXX validate channel # */
- ni->ni_chan = &ic->ic_channels[chan];
if (ic->ic_state == IEEE80211_S_SCAN &&
IEEE80211_IS_CHAN_5GHZ(ni->ni_chan)) {
/*
@@ -2645,7 +2649,7 @@ ieee80211_recv_assoc_resp(struct ieee80211com *ic, struct mbuf *m,
ieee80211_setup_htop(ni, htop + 2, htop[1], 0);
ieee80211_ht_negotiate(ic, ni);
- if (htcaps && vhtcaps && IEEE80211_IS_CHAN_5GHZ(ic->ic_bss->ni_chan)) {
+ if (htcaps && vhtcaps && IEEE80211_IS_CHAN_5GHZ(ni->ni_chan)) {
ieee80211_setup_vhtcaps(ni, vhtcaps + 2, vhtcaps[1]);
if (vhtop && !ieee80211_setup_vhtop(ni, vhtop + 2, vhtop[1], 1))
vhtop = NULL; /* invalid VHTOP */
diff --git a/sys/net80211/ieee80211_node.h b/sys/net80211/ieee80211_node.h
index d03d25669b6..6a9fd5f3d51 100644
--- a/sys/net80211/ieee80211_node.h
+++ b/sys/net80211/ieee80211_node.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ieee80211_node.h,v 1.93 2022/03/19 10:25:09 stsp Exp $ */
+/* $OpenBSD: ieee80211_node.h,v 1.94 2022/03/20 12:01:58 stsp Exp $ */
/* $NetBSD: ieee80211_node.h,v 1.9 2004/04/30 22:57:32 dyoung Exp $ */
/*-
@@ -192,6 +192,7 @@ struct ieee80211_rxinfo {
u_int32_t rxi_flags;
u_int32_t rxi_tstamp;
int rxi_rssi;
+ uint8_t rxi_chan;
};
#define IEEE80211_RXI_HWDEC 0x00000001
#define IEEE80211_RXI_AMPDU_DONE 0x00000002