aboutsummaryrefslogtreecommitdiff
path: root/sys/net80211/ieee80211.c
diff options
context:
space:
mode:
authorAdrian Chadd <adrian@FreeBSD.org>2015-05-25 16:37:41 +0000
committerAdrian Chadd <adrian@FreeBSD.org>2015-05-25 16:37:41 +0000
commitc79f192c095af3284e59367e99632020e445ddd1 (patch)
tree9a3a82a41771917c3bdebe5b898d1691fa14c9d8 /sys/net80211/ieee80211.c
parent9dbbcd5d9acab5697a8107690f553d70f197f2b7 (diff)
downloadsrc-c79f192c095af3284e59367e99632020e445ddd1.tar.gz
src-c79f192c095af3284e59367e99632020e445ddd1.zip
Begin plumbing ieee80211_rx_stats through the receive path.
Smart NICs with firmware (eg wpi, iwn, the new atheros parts, the intel 7260 series, etc) support doing a lot of things in firmware. This includes but isn't limited to things like scanning, sending probe requests and receiving probe responses. However, net80211 doesn't know about any of this - it still drives the whole scan/probe infrastructure itself. In order to move towards suppoting smart NICs, the receive path needs to know about the channel/details for each received packet. In at least the iwn and 7260 firmware (and I believe wpi, but I haven't tried it yet) it will do the scanning, power-save and off-channel buffering for you - all you need to do is handle receiving beacons and probe responses on channels that aren't what you're currently on. However the whole receive path is peppered with ic->ic_curchan and manual scan/powersave handling. The beacon parsing code also checks ic->ic_curchan to determine if the received beacon is on the correct channel or not.[1] So: * add freq/ieee values to ieee80211_rx_stats; * change ieee80211_parse_beacon() to accept the 'current' channel as an argument; * modify the iv_input() and iv_recv_mgmt() methods to include the rx_stats; * add a new method - ieee80211_lookup_channel_rxstats() - that looks up a channel based on the contents of ieee80211_rx_stats; * if it exists, use it in the mgmt path to switch the current channel (which still defaults to ic->ic_curchan) over to something determined by rx_stats. This is enough to kick-start scan offload support in the Intel 7260 driver that Rui/I are working on. It also is a good start for scan offload support for a handful of existing NICs (wpi, iwn, some USB parts) and it'll very likely dramatically improve stability/performance there. It's not the whole thing - notably, we don't need to do powersave, we should not scan all channels, and we should leave probe request sending to the firmware and not do it ourselves. But, this allows for continued development on the above features whilst actually having a somewhat working NIC. TODO: * Finish tidying up how the net80211 input path works. Right now ieee80211_input / ieee80211_input_all act as the top-level that everything feeds into; it should change so the MIMO input routines are those and the legacy routines are phased out. * The band selection should be done by the driver, not by the net80211 layer. * ieee80211_lookup_channel_rxstats() only determines 11b or 11g channels for now - this is enough for scanning, but not 100% true in all cases. If we ever need to handle off-channel scan support for things like static-40MHz or static-80MHz, or turbo-G, or half/quarter rates, then we should extend this. [1] This is a side effect of frequency-hopping and CCK modes - you can receive beacons when you think you're on a different channel. In particular, CCK (which is used by the low 11b rates, eg beacons!) is decodable from adjacent channels - just at a low SNR. FH is a side effect of having the hardware/firmware do the frequency hopping - it may pick up beacons transmitted from other FH networks that are in a different phase of hopping frequencies.
Notes
Notes: svn path=/head/; revision=283535
Diffstat (limited to 'sys/net80211/ieee80211.c')
-rw-r--r--sys/net80211/ieee80211.c69
1 files changed, 69 insertions, 0 deletions
diff --git a/sys/net80211/ieee80211.c b/sys/net80211/ieee80211.c
index 6609f46929b3..8596ce1d3056 100644
--- a/sys/net80211/ieee80211.c
+++ b/sys/net80211/ieee80211.c
@@ -1005,6 +1005,75 @@ ieee80211_find_channel_byieee(struct ieee80211com *ic, int ieee, int flags)
return NULL;
}
+/*
+ * Lookup a channel suitable for the given rx status.
+ *
+ * This is used to find a channel for a frame (eg beacon, probe
+ * response) based purely on the received PHY information.
+ *
+ * For now it tries to do it based on R_FREQ / R_IEEE.
+ * This is enough for 11bg and 11a (and thus 11ng/11na)
+ * but it will not be enough for GSM, PSB channels and the
+ * like. It also doesn't know about legacy-turbog and
+ * legacy-turbo modes, which some offload NICs actually
+ * support in weird ways.
+ *
+ * Takes the ic and rxstatus; returns the channel or NULL
+ * if not found.
+ *
+ * XXX TODO: Add support for that when the need arises.
+ */
+struct ieee80211_channel *
+ieee80211_lookup_channel_rxstatus(struct ieee80211vap *vap,
+ const struct ieee80211_rx_stats *rxs)
+{
+ struct ieee80211com *ic = vap->iv_ic;
+ uint32_t flags;
+ struct ieee80211_channel *c;
+
+ if (rxs == NULL)
+ return (NULL);
+
+ /*
+ * Strictly speaking we only use freq for now,
+ * however later on we may wish to just store
+ * the ieee for verification.
+ */
+ if ((rxs->r_flags & IEEE80211_R_FREQ) == 0)
+ return (NULL);
+ if ((rxs->r_flags & IEEE80211_R_IEEE) == 0)
+ return (NULL);
+
+ /*
+ * If the rx status contains a valid ieee/freq, then
+ * ensure we populate the correct channel information
+ * in rxchan before passing it up to the scan infrastructure.
+ * Offload NICs will pass up beacons from all channels
+ * during background scans.
+ */
+
+ /* Determine a band */
+ /* XXX should be done by the driver? */
+ if (rxs->c_freq < 3000) {
+ flags = IEEE80211_CHAN_B;
+ } else {
+ flags = IEEE80211_CHAN_A;
+ }
+
+ /* Channel lookup */
+ c = ieee80211_find_channel(ic, rxs->c_freq, flags);
+
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_INPUT,
+ "%s: freq=%d, ieee=%d, flags=0x%08x; c=%p\n",
+ __func__,
+ (int) rxs->c_freq,
+ (int) rxs->c_ieee,
+ flags,
+ c);
+
+ return (c);
+}
+
static void
addmedia(struct ifmedia *media, int caps, int addsta, int mode, int mword)
{