diff options
author | Stefan Sperling <stsp@cvs.openbsd.org> | 2022-03-20 12:01:59 +0000 |
---|---|---|
committer | Stefan Sperling <stsp@cvs.openbsd.org> | 2022-03-20 12:01:59 +0000 |
commit | 424bafeee6cdf0c7b8cad002411e5d9efad0ac85 (patch) | |
tree | 8fa476396947559a660fb1e68f28c792043fc6b2 /sys/net80211 | |
parent | 8b7cfdd9f0073651f6759f7a077c8c9593cf76f8 (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.c | 20 | ||||
-rw-r--r-- | sys/net80211/ieee80211_node.h | 3 |
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 |