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@
-/* $OpenBSD: bwfm.c,v 1.101 2022/03/06 18:52:47 kettenis Exp $ */
+/* $OpenBSD: bwfm.c,v 1.102 2022/03/20 12:01:58 stsp Exp $ */
/*
* Copyright (c) 2010-2016 Broadcom Corporation
* Copyright (c) 2016,2017 Patrick Wildt <patrick@blueri.se>
struct ieee80211_frame *wh;
struct ieee80211_node *ni;
struct ieee80211_rxinfo rxi;
- struct ieee80211_channel *bss_chan;
- uint8_t saved_bssid[IEEE80211_ADDR_LEN] = { 0 };
struct mbuf *m;
uint32_t pktlen, ieslen;
uint16_t iesoff;
/* Finalize mbuf. */
m->m_pkthdr.len = m->m_len = pktlen;
ni = ieee80211_find_rxnode(ic, wh);
- if (ni == ic->ic_bss) {
- /*
- * We may switch ic_bss's channel during scans.
- * Record the current channel so we can restore it later.
- */
- bss_chan = ni->ni_chan;
- IEEE80211_ADDR_COPY(&saved_bssid, ni->ni_macaddr);
- }
/* Channel mask equals IEEE80211_CHAN_MAX */
chanidx = bwfm_spec2chan(sc, letoh32(bss->chanspec));
- ni->ni_chan = &ic->ic_channels[chanidx];
/* Supply RSSI */
rxi.rxi_flags = 0;
rxi.rxi_rssi = (int16_t)letoh16(bss->rssi);
rxi.rxi_tstamp = 0;
+ rxi.rxi_chan = chanidx;
ieee80211_input(ifp, m, ni, &rxi);
- /*
- * ieee80211_input() might have changed our BSS.
- * Restore ic_bss's channel if we are still in the same BSS.
- */
- if (ni == ic->ic_bss && IEEE80211_ADDR_EQ(saved_bssid, ni->ni_macaddr))
- ni->ni_chan = bss_chan;
/* Node is no longer needed. */
ieee80211_release_node(ic, ni);
}
-/* $OpenBSD: if_iwm.c,v 1.398 2022/03/20 11:59:39 stsp Exp $ */
+/* $OpenBSD: if_iwm.c,v 1.399 2022/03/20 12:01:58 stsp Exp $ */
/*
* Copyright (c) 2014, 2016 genua gmbh <info@genua.de>
struct ifnet *ifp = IC2IFP(ic);
struct ieee80211_frame *wh;
struct ieee80211_node *ni;
- struct ieee80211_channel *bss_chan;
- uint8_t saved_bssid[IEEE80211_ADDR_LEN] = { 0 };
if (chanidx < 0 || chanidx >= nitems(ic->ic_channels))
chanidx = ieee80211_chan2ieee(ic, ic->ic_ibss_chan);
wh = mtod(m, struct ieee80211_frame *);
ni = ieee80211_find_rxnode(ic, wh);
- if (ni == ic->ic_bss) {
- /*
- * We may switch ic_bss's channel during scans.
- * Record the current channel so we can restore it later.
- */
- bss_chan = ni->ni_chan;
- IEEE80211_ADDR_COPY(&saved_bssid, ni->ni_macaddr);
- }
- ni->ni_chan = &ic->ic_channels[chanidx];
-
if ((rxi->rxi_flags & IEEE80211_RXI_HWDEC) &&
iwm_ccmp_decap(sc, m, ni, rxi) != 0) {
ifp->if_ierrors++;
}
#endif
ieee80211_inputm(IC2IFP(ic), m, ni, rxi, ml);
- /*
- * ieee80211_inputm() might have changed our BSS.
- * Restore ic_bss's channel if we are still in the same BSS.
- */
- if (ni == ic->ic_bss && IEEE80211_ADDR_EQ(saved_bssid, ni->ni_macaddr))
- ni->ni_chan = bss_chan;
ieee80211_release_node(ic, ni);
}
rxi.rxi_rssi = rssi;
rxi.rxi_tstamp = device_timestamp;
+ rxi.rxi_chan = chanidx;
iwm_rx_frame(sc, m, chanidx, rx_pkt_status,
(phy_flags & IWM_PHY_INFO_FLAG_SHPREAMBLE),
rxi.rxi_rssi = rssi;
rxi.rxi_tstamp = le64toh(desc->v1.tsf_on_air_rise);
+ rxi.rxi_chan = chanidx;
if (iwm_rx_reorder(sc, m, chanidx, desc,
(phy_info & IWM_RX_MPDU_PHY_SHORT_PREAMBLE),
-/* $OpenBSD: if_iwn.c,v 1.256 2022/03/11 18:00:45 mpi Exp $ */
+/* $OpenBSD: if_iwn.c,v 1.257 2022/03/20 12:01:58 stsp Exp $ */
/*-
* Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>
struct ieee80211_frame *wh;
struct ieee80211_rxinfo rxi;
struct ieee80211_node *ni;
- struct ieee80211_channel *bss_chan = NULL;
- uint8_t saved_bssid[IEEE80211_ADDR_LEN] = { 0 };
struct mbuf *m, *m1;
struct iwn_rx_stat *stat;
caddr_t head;
if (chan > IEEE80211_CHAN_MAX)
chan = IEEE80211_CHAN_MAX;
- /* Fix current channel. */
- if (ni == ic->ic_bss) {
- /*
- * We may switch ic_bss's channel during scans.
- * Record the current channel so we can restore it later.
- */
- bss_chan = ni->ni_chan;
- IEEE80211_ADDR_COPY(&saved_bssid, ni->ni_macaddr);
- }
- ni->ni_chan = &ic->ic_channels[chan];
-
#if NBPFILTER > 0
if (sc->sc_drvbpf != NULL) {
struct iwn_rx_radiotap_header *tap = &sc->sc_rxtap;
/* Send the frame to the 802.11 layer. */
rxi.rxi_rssi = rssi;
rxi.rxi_tstamp = 0; /* unused */
+ rxi.rxi_chan = chan;
ieee80211_inputm(ifp, m, ni, &rxi, ml);
- /*
- * ieee80211_inputm() might have changed our BSS.
- * Restore ic_bss's channel if we are still in the same BSS.
- */
- if (ni == ic->ic_bss && IEEE80211_ADDR_EQ(saved_bssid, ni->ni_macaddr))
- ni->ni_chan = bss_chan;
-
/* Node is no longer needed. */
ieee80211_release_node(ic, ni);
}
-/* $OpenBSD: if_iwx.c,v 1.139 2022/03/20 11:59:39 stsp Exp $ */
+/* $OpenBSD: if_iwx.c,v 1.140 2022/03/20 12:01:58 stsp Exp $ */
/*
* Copyright (c) 2014, 2016 genua gmbh <info@genua.de>
struct ifnet *ifp = IC2IFP(ic);
struct ieee80211_frame *wh;
struct ieee80211_node *ni;
- struct ieee80211_channel *bss_chan;
- uint8_t saved_bssid[IEEE80211_ADDR_LEN] = { 0 };
if (chanidx < 0 || chanidx >= nitems(ic->ic_channels))
chanidx = ieee80211_chan2ieee(ic, ic->ic_ibss_chan);
wh = mtod(m, struct ieee80211_frame *);
ni = ieee80211_find_rxnode(ic, wh);
- if (ni == ic->ic_bss) {
- /*
- * We may switch ic_bss's channel during scans.
- * Record the current channel so we can restore it later.
- */
- bss_chan = ni->ni_chan;
- IEEE80211_ADDR_COPY(&saved_bssid, ni->ni_macaddr);
- }
- ni->ni_chan = &ic->ic_channels[chanidx];
-
if ((rxi->rxi_flags & IEEE80211_RXI_HWDEC) &&
iwx_ccmp_decap(sc, m, ni, rxi) != 0) {
ifp->if_ierrors++;
}
#endif
ieee80211_inputm(IC2IFP(ic), m, ni, rxi, ml);
- /*
- * ieee80211_inputm() might have changed our BSS.
- * Restore ic_bss's channel if we are still in the same BSS.
- */
- if (ni == ic->ic_bss && IEEE80211_ADDR_EQ(saved_bssid, ni->ni_macaddr))
- ni->ni_chan = bss_chan;
ieee80211_release_node(ic, ni);
}
rxi.rxi_rssi = rssi;
rxi.rxi_tstamp = le64toh(desc->v1.tsf_on_air_rise);
+ rxi.rxi_chan = chanidx;
if (iwx_rx_reorder(sc, m, chanidx, desc,
(phy_info & IWX_RX_MPDU_PHY_SHORT_PREAMBLE),
-/* $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
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) {
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;
} 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 */
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)) {
/*
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 */
-/* $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 $ */
/*-
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