Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 25 May 2015 16:37:42 +0000 (UTC)
From:      Adrian Chadd <adrian@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r283535 - in head/sys: dev/ath dev/wi net80211
Message-ID:  <201505251637.t4PGbgoh024594@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: adrian
Date: Mon May 25 16:37:41 2015
New Revision: 283535
URL: https://svnweb.freebsd.org/changeset/base/283535

Log:
  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.

Modified:
  head/sys/dev/ath/if_ath_rx.c
  head/sys/dev/ath/if_ath_rx.h
  head/sys/dev/ath/if_athvar.h
  head/sys/dev/wi/if_wi.c
  head/sys/dev/wi/if_wivar.h
  head/sys/net80211/ieee80211.c
  head/sys/net80211/ieee80211_adhoc.c
  head/sys/net80211/ieee80211_hostap.c
  head/sys/net80211/ieee80211_input.c
  head/sys/net80211/ieee80211_input.h
  head/sys/net80211/ieee80211_mesh.c
  head/sys/net80211/ieee80211_monitor.c
  head/sys/net80211/ieee80211_proto.h
  head/sys/net80211/ieee80211_sta.c
  head/sys/net80211/ieee80211_tdma.c
  head/sys/net80211/ieee80211_tdma.h
  head/sys/net80211/ieee80211_var.h
  head/sys/net80211/ieee80211_wds.c

Modified: head/sys/dev/ath/if_ath_rx.c
==============================================================================
--- head/sys/dev/ath/if_ath_rx.c	Mon May 25 15:18:32 2015	(r283534)
+++ head/sys/dev/ath/if_ath_rx.c	Mon May 25 16:37:41 2015	(r283535)
@@ -327,7 +327,7 @@ ath_legacy_rxbuf_init(struct ath_softc *
  */
 void
 ath_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m,
-	int subtype, int rssi, int nf)
+	int subtype, const struct ieee80211_rx_stats *rxs, int rssi, int nf)
 {
 	struct ieee80211vap *vap = ni->ni_vap;
 	struct ath_softc *sc = vap->iv_ic->ic_ifp->if_softc;
@@ -353,7 +353,7 @@ ath_recv_mgmt(struct ieee80211_node *ni,
 	 * Call up first so subsequent work can use information
 	 * potentially stored in the node (e.g. for ibss merge).
 	 */
-	ATH_VAP(vap)->av_recv_mgmt(ni, m, subtype, rssi, nf);
+	ATH_VAP(vap)->av_recv_mgmt(ni, m, subtype, rxs, rssi, nf);
 	switch (subtype) {
 	case IEEE80211_FC0_SUBTYPE_BEACON:
 		/* update rssi statistics for use by the hal */

Modified: head/sys/dev/ath/if_ath_rx.h
==============================================================================
--- head/sys/dev/ath/if_ath_rx.h	Mon May 25 15:18:32 2015	(r283534)
+++ head/sys/dev/ath/if_ath_rx.h	Mon May 25 16:37:41 2015	(r283535)
@@ -33,7 +33,8 @@
 
 extern	u_int32_t ath_calcrxfilter(struct ath_softc *sc);
 extern	void ath_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m,
-	    int subtype, int rssi, int nf);
+	    int subtype, const struct ieee80211_rx_stats *rxs,
+	    int rssi, int nf);
 
 #define	ath_stoprecv(_sc, _dodelay)		\
 	    (_sc)->sc_rx.recv_stop((_sc), (_dodelay))

Modified: head/sys/dev/ath/if_athvar.h
==============================================================================
--- head/sys/dev/ath/if_athvar.h	Mon May 25 15:18:32 2015	(r283534)
+++ head/sys/dev/ath/if_athvar.h	Mon May 25 16:37:41 2015	(r283535)
@@ -481,7 +481,8 @@ struct ath_vap {
 	struct ath_txq	av_mcastq;	/* buffered mcast s/w queue */
 
 	void		(*av_recv_mgmt)(struct ieee80211_node *,
-				struct mbuf *, int, int, int);
+				struct mbuf *, int,
+				const struct ieee80211_rx_stats *, int, int);
 	int		(*av_newstate)(struct ieee80211vap *,
 				enum ieee80211_state, int);
 	void		(*av_bmiss)(struct ieee80211vap *);

Modified: head/sys/dev/wi/if_wi.c
==============================================================================
--- head/sys/dev/wi/if_wi.c	Mon May 25 15:18:32 2015	(r283534)
+++ head/sys/dev/wi/if_wi.c	Mon May 25 16:37:41 2015	(r283535)
@@ -127,7 +127,8 @@ static int  wi_newstate_sta(struct ieee8
 static int  wi_newstate_hostap(struct ieee80211vap *, enum ieee80211_state,
 		int);
 static void wi_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m,
-		int subtype, int rssi, int nf);
+		int subtype, const struct ieee80211_rx_stats *rxs,
+		int rssi, int nf);
 static int  wi_reset(struct wi_softc *);
 static void wi_watchdog(void *);
 static int  wi_ioctl(struct ifnet *, u_long, caddr_t);
@@ -804,7 +805,7 @@ wi_scan_end(struct ieee80211com *ic)
 
 static void
 wi_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m,
-	int subtype, int rssi, int nf)
+	int subtype, const struct ieee80211_rx_stats *rxs, int rssi, int nf)
 {
 	struct ieee80211vap *vap = ni->ni_vap;
 
@@ -815,7 +816,7 @@ wi_recv_mgmt(struct ieee80211_node *ni, 
 		/* NB: filter frames that trigger state changes */
 		return;
 	}
-	WI_VAP(vap)->wv_recv_mgmt(ni, m, subtype, rssi, nf);
+	WI_VAP(vap)->wv_recv_mgmt(ni, m, subtype, rxs, rssi, nf);
 }
 
 static int

Modified: head/sys/dev/wi/if_wivar.h
==============================================================================
--- head/sys/dev/wi/if_wivar.h	Mon May 25 15:18:32 2015	(r283534)
+++ head/sys/dev/wi/if_wivar.h	Mon May 25 16:37:41 2015	(r283535)
@@ -61,7 +61,7 @@ struct wi_vap {
 	struct ieee80211_beacon_offsets	wv_bo;
 
 	void		(*wv_recv_mgmt)(struct ieee80211_node *, struct mbuf *,
-			    int, int, int);
+			    int, const struct ieee80211_rx_stats *rxs, int, int);
 	int		(*wv_newstate)(struct ieee80211vap *,
 			    enum ieee80211_state, int);
 };

Modified: head/sys/net80211/ieee80211.c
==============================================================================
--- head/sys/net80211/ieee80211.c	Mon May 25 15:18:32 2015	(r283534)
+++ head/sys/net80211/ieee80211.c	Mon May 25 16:37:41 2015	(r283535)
@@ -1005,6 +1005,75 @@ ieee80211_find_channel_byieee(struct iee
 	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)
 {

Modified: head/sys/net80211/ieee80211_adhoc.c
==============================================================================
--- head/sys/net80211/ieee80211_adhoc.c	Mon May 25 15:18:32 2015	(r283534)
+++ head/sys/net80211/ieee80211_adhoc.c	Mon May 25 16:37:41 2015	(r283535)
@@ -70,11 +70,12 @@ __FBSDID("$FreeBSD$");
 
 static	void adhoc_vattach(struct ieee80211vap *);
 static	int adhoc_newstate(struct ieee80211vap *, enum ieee80211_state, int);
-static int adhoc_input(struct ieee80211_node *, struct mbuf *, int, int);
+static int adhoc_input(struct ieee80211_node *, struct mbuf *,
+	    const struct ieee80211_rx_stats *, int, int);
 static void adhoc_recv_mgmt(struct ieee80211_node *, struct mbuf *,
-	int subtype, int, int);
+	int subtype, const struct ieee80211_rx_stats *, int, int);
 static void ahdemo_recv_mgmt(struct ieee80211_node *, struct mbuf *,
-	int subtype, int, int);
+	    int subtype, const struct ieee80211_rx_stats *rxs, int, int);
 static void adhoc_recv_ctl(struct ieee80211_node *, struct mbuf *, int subtype);
 
 void
@@ -289,7 +290,8 @@ doprint(struct ieee80211vap *vap, int su
  * by the 802.11 layer.
  */
 static int
-adhoc_input(struct ieee80211_node *ni, struct mbuf *m, int rssi, int nf)
+adhoc_input(struct ieee80211_node *ni, struct mbuf *m,
+    const struct ieee80211_rx_stats *rxs, int rssi, int nf)
 {
 	struct ieee80211vap *vap = ni->ni_vap;
 	struct ieee80211com *ic = ni->ni_ic;
@@ -642,7 +644,7 @@ adhoc_input(struct ieee80211_node *ni, s
 			vap->iv_stats.is_rx_mgtdiscard++; /* XXX */
 			goto out;
 		}
-		vap->iv_recv_mgmt(ni, m, subtype, rssi, nf);
+		vap->iv_recv_mgmt(ni, m, subtype, rxs, rssi, nf);
 		goto out;
 
 	case IEEE80211_FC0_TYPE_CTL:
@@ -687,10 +689,11 @@ is11bclient(const uint8_t *rates, const 
 
 static void
 adhoc_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0,
-	int subtype, int rssi, int nf)
+	int subtype, const struct ieee80211_rx_stats *rxs, int rssi, int nf)
 {
 	struct ieee80211vap *vap = ni->ni_vap;
 	struct ieee80211com *ic = ni->ni_ic;
+	struct ieee80211_channel *rxchan = ic->ic_curchan;
 	struct ieee80211_frame *wh;
 	uint8_t *frm, *efrm, *sfrm;
 	uint8_t *ssid, *rates, *xrates;
@@ -705,11 +708,17 @@ adhoc_recv_mgmt(struct ieee80211_node *n
 	case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
 	case IEEE80211_FC0_SUBTYPE_BEACON: {
 		struct ieee80211_scanparams scan;
+		struct ieee80211_channel *c;
 		/*
 		 * We process beacon/probe response
 		 * frames to discover neighbors.
 		 */ 
-		if (ieee80211_parse_beacon(ni, m0, &scan) != 0)
+		if (rxs != NULL) {
+			c = ieee80211_lookup_channel_rxstatus(vap, rxs);
+			if (c != NULL)
+				rxchan = c;
+		}
+		if (ieee80211_parse_beacon(ni, m0, rxchan, &scan) != 0)
 			return;
 		/*
 		 * Count frame now that we know it's to be processed.
@@ -735,7 +744,7 @@ adhoc_recv_mgmt(struct ieee80211_node *n
 				ieee80211_probe_curchan(vap, 1);
 				ic->ic_flags_ext &= ~IEEE80211_FEXT_PROBECHAN;
 			}
-			ieee80211_add_scan(vap, ic->ic_curchan, &scan, wh,
+			ieee80211_add_scan(vap, rxchan, &scan, wh,
 			    subtype, rssi, nf);
 			return;
 		}
@@ -911,7 +920,7 @@ adhoc_recv_mgmt(struct ieee80211_node *n
 
 static void
 ahdemo_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0,
-	int subtype, int rssi, int nf)
+	int subtype, const struct ieee80211_rx_stats *rxs, int rssi, int nf)
 {
 	struct ieee80211vap *vap = ni->ni_vap;
 	struct ieee80211com *ic = ni->ni_ic;
@@ -922,7 +931,7 @@ ahdemo_recv_mgmt(struct ieee80211_node *
 	 * a site-survey.
 	 */
 	if (ic->ic_flags & IEEE80211_F_SCAN)
-		adhoc_recv_mgmt(ni, m0, subtype, rssi, nf);
+		adhoc_recv_mgmt(ni, m0, subtype, rxs, rssi, nf);
 	else {
 		wh = mtod(m0, struct ieee80211_frame *);
 		switch (subtype) {

Modified: head/sys/net80211/ieee80211_hostap.c
==============================================================================
--- head/sys/net80211/ieee80211_hostap.c	Mon May 25 15:18:32 2015	(r283534)
+++ head/sys/net80211/ieee80211_hostap.c	Mon May 25 16:37:41 2015	(r283535)
@@ -68,11 +68,12 @@ __FBSDID("$FreeBSD$");
 static	void hostap_vattach(struct ieee80211vap *);
 static	int hostap_newstate(struct ieee80211vap *, enum ieee80211_state, int);
 static	int hostap_input(struct ieee80211_node *ni, struct mbuf *m,
+	    const struct ieee80211_rx_stats *,
 	    int rssi, int nf);
 static void hostap_deliver_data(struct ieee80211vap *,
 	    struct ieee80211_node *, struct mbuf *);
 static void hostap_recv_mgmt(struct ieee80211_node *, struct mbuf *,
-	    int subtype, int rssi, int nf);
+	    int subtype, const struct ieee80211_rx_stats *rxs, int rssi, int nf);
 static void hostap_recv_ctl(struct ieee80211_node *, struct mbuf *, int);
 
 void
@@ -476,7 +477,8 @@ doprint(struct ieee80211vap *vap, int su
  * by the 802.11 layer.
  */
 static int
-hostap_input(struct ieee80211_node *ni, struct mbuf *m, int rssi, int nf)
+hostap_input(struct ieee80211_node *ni, struct mbuf *m,
+    const struct ieee80211_rx_stats *rxs, int rssi, int nf)
 {
 	struct ieee80211vap *vap = ni->ni_vap;
 	struct ieee80211com *ic = ni->ni_ic;
@@ -893,7 +895,7 @@ hostap_input(struct ieee80211_node *ni, 
 		if (ieee80211_radiotap_active_vap(vap))
 			ieee80211_radiotap_rx(vap, m);
 		need_tap = 0;
-		vap->iv_recv_mgmt(ni, m, subtype, rssi, nf);
+		vap->iv_recv_mgmt(ni, m, subtype, rxs, rssi, nf);
 		goto out;
 
 	case IEEE80211_FC0_TYPE_CTL:
@@ -1681,7 +1683,7 @@ is11bclient(const uint8_t *rates, const 
 
 static void
 hostap_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0,
-	int subtype, int rssi, int nf)
+	int subtype, const struct ieee80211_rx_stats *rxs, int rssi, int nf)
 {
 	struct ieee80211vap *vap = ni->ni_vap;
 	struct ieee80211com *ic = ni->ni_ic;
@@ -1709,7 +1711,8 @@ hostap_recv_mgmt(struct ieee80211_node *
 			return;
 		}
 		/* NB: accept off-channel frames */
-		if (ieee80211_parse_beacon(ni, m0, &scan) &~ IEEE80211_BPARSE_OFFCHAN)
+		/* XXX TODO: use rxstatus to determine off-channel details */
+		if (ieee80211_parse_beacon(ni, m0, ic->ic_curchan, &scan) &~ IEEE80211_BPARSE_OFFCHAN)
 			return;
 		/*
 		 * Count frame now that we know it's to be processed.

Modified: head/sys/net80211/ieee80211_input.c
==============================================================================
--- head/sys/net80211/ieee80211_input.c	Mon May 25 15:18:32 2015	(r283534)
+++ head/sys/net80211/ieee80211_input.c	Mon May 25 16:37:41 2015	(r283535)
@@ -88,7 +88,8 @@ ieee80211_input_mimo(struct ieee80211_no
 {
 	/* XXX should assert IEEE80211_R_NF and IEEE80211_R_RSSI are set */
 	ieee80211_process_mimo(ni, rx);
-	return ieee80211_input(ni, m, rx->rssi, rx->nf);
+	//return ieee80211_input(ni, m, rx->rssi, rx->nf);
+	return ni->ni_vap->iv_input(ni, m, rx, rx->rssi, rx->nf);
 }
 
 int
@@ -468,7 +469,7 @@ ieee80211_alloc_challenge(struct ieee802
  */
 int
 ieee80211_parse_beacon(struct ieee80211_node *ni, struct mbuf *m,
-	struct ieee80211_scanparams *scan)
+	struct ieee80211_channel *rxchan, struct ieee80211_scanparams *scan)
 {
 	struct ieee80211vap *vap = ni->ni_vap;
 	struct ieee80211com *ic = ni->ni_ic;
@@ -505,7 +506,7 @@ ieee80211_parse_beacon(struct ieee80211_
 	scan->tstamp  = frm;				frm += 8;
 	scan->bintval = le16toh(*(uint16_t *)frm);	frm += 2;
 	scan->capinfo = le16toh(*(uint16_t *)frm);	frm += 2;
-	scan->bchan = ieee80211_chan2ieee(ic, ic->ic_curchan);
+	scan->bchan = ieee80211_chan2ieee(ic, rxchan);
 	scan->chan = scan->bchan;
 	scan->ies = frm;
 	scan->ies_len = efrm - frm;
@@ -648,7 +649,8 @@ ieee80211_parse_beacon(struct ieee80211_
 		 */
 		IEEE80211_DISCARD(vap,
 		    IEEE80211_MSG_ELEMID | IEEE80211_MSG_INPUT,
-		    wh, NULL, "for off-channel %u", scan->chan);
+		    wh, NULL, "for off-channel %u (bchan=%u)",
+		    scan->chan, scan->bchan);
 		vap->iv_stats.is_rx_chanmismatch++;
 		scan->status |= IEEE80211_BPARSE_OFFCHAN;
 	}

Modified: head/sys/net80211/ieee80211_input.h
==============================================================================
--- head/sys/net80211/ieee80211_input.h	Mon May 25 15:18:32 2015	(r283534)
+++ head/sys/net80211/ieee80211_input.h	Mon May 25 16:37:41 2015	(r283535)
@@ -255,6 +255,7 @@ void ieee80211_send_error(struct ieee802
 		const uint8_t mac[IEEE80211_ADDR_LEN], int subtype, int arg);
 int	ieee80211_alloc_challenge(struct ieee80211_node *);
 int	ieee80211_parse_beacon(struct ieee80211_node *, struct mbuf *,
+		struct ieee80211_channel *,
 		struct ieee80211_scanparams *);
 int	ieee80211_parse_action(struct ieee80211_node *, struct mbuf *);
 #endif /* _NET80211_IEEE80211_INPUT_H_ */

Modified: head/sys/net80211/ieee80211_mesh.c
==============================================================================
--- head/sys/net80211/ieee80211_mesh.c	Mon May 25 15:18:32 2015	(r283534)
+++ head/sys/net80211/ieee80211_mesh.c	Mon May 25 16:37:41 2015	(r283535)
@@ -85,9 +85,10 @@ static void	mesh_transmit_to_gate(struct
 		    struct ieee80211_mesh_route *);
 static void	mesh_forward(struct ieee80211vap *, struct mbuf *,
 		    const struct ieee80211_meshcntl *);
-static int	mesh_input(struct ieee80211_node *, struct mbuf *, int, int);
+static int	mesh_input(struct ieee80211_node *, struct mbuf *,
+		    const struct ieee80211_rx_stats *rxs, int, int);
 static void	mesh_recv_mgmt(struct ieee80211_node *, struct mbuf *, int,
-		    int, int);
+		    const struct ieee80211_rx_stats *rxs, int, int);
 static void	mesh_recv_ctl(struct ieee80211_node *, struct mbuf *, int);
 static void	mesh_peer_timeout_setup(struct ieee80211_node *);
 static void	mesh_peer_timeout_backoff(struct ieee80211_node *);
@@ -1532,7 +1533,8 @@ mesh_recv_group_data(struct ieee80211vap
 }
 
 static int
-mesh_input(struct ieee80211_node *ni, struct mbuf *m, int rssi, int nf)
+mesh_input(struct ieee80211_node *ni, struct mbuf *m,
+    const struct ieee80211_rx_stats *rxs, int rssi, int nf)
 {
 #define	HAS_SEQ(type)	((type & 0x4) == 0)
 #define	MC01(mc)	((const struct ieee80211_meshcntl_ae01 *)mc)
@@ -1831,7 +1833,7 @@ mesh_input(struct ieee80211_node *ni, st
 			vap->iv_stats.is_rx_mgtdiscard++; /* XXX */
 			goto out;
 		}
-		vap->iv_recv_mgmt(ni, m, subtype, rssi, nf);
+		vap->iv_recv_mgmt(ni, m, subtype, rxs, rssi, nf);
 		goto out;
 	case IEEE80211_FC0_TYPE_CTL:
 		vap->iv_stats.is_rx_ctl++;
@@ -1859,11 +1861,12 @@ out:
 
 static void
 mesh_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0, int subtype,
-    int rssi, int nf)
+    const struct ieee80211_rx_stats *rxs, int rssi, int nf)
 {
 	struct ieee80211vap *vap = ni->ni_vap;
 	struct ieee80211_mesh_state *ms = vap->iv_mesh;
 	struct ieee80211com *ic = ni->ni_ic;
+	struct ieee80211_channel *rxchan = ic->ic_curchan;
 	struct ieee80211_frame *wh;
 	struct ieee80211_mesh_route *rt;
 	uint8_t *frm, *efrm;
@@ -1876,11 +1879,17 @@ mesh_recv_mgmt(struct ieee80211_node *ni
 	case IEEE80211_FC0_SUBTYPE_BEACON:
 	{
 		struct ieee80211_scanparams scan;
+		struct ieee80211_channel *c;
 		/*
 		 * We process beacon/probe response
 		 * frames to discover neighbors.
 		 */
-		if (ieee80211_parse_beacon(ni, m0, &scan) != 0)
+		if (rxs != NULL) {
+			c = ieee80211_lookup_channel_rxstatus(vap, rxs);
+			if (c != NULL)
+				rxchan = c;
+		}
+		if (ieee80211_parse_beacon(ni, m0, rxchan, &scan) != 0)
 			return;
 		/*
 		 * Count frame now that we know it's to be processed.
@@ -1906,7 +1915,7 @@ mesh_recv_mgmt(struct ieee80211_node *ni
 				ieee80211_probe_curchan(vap, 1);
 				ic->ic_flags_ext &= ~IEEE80211_FEXT_PROBECHAN;
 			}
-			ieee80211_add_scan(vap, ic->ic_curchan, &scan, wh,
+			ieee80211_add_scan(vap, rxchan, &scan, wh,
 			    subtype, rssi, nf);
 			return;
 		}

Modified: head/sys/net80211/ieee80211_monitor.c
==============================================================================
--- head/sys/net80211/ieee80211_monitor.c	Mon May 25 15:18:32 2015	(r283534)
+++ head/sys/net80211/ieee80211_monitor.c	Mon May 25 16:37:41 2015	(r283535)
@@ -61,7 +61,7 @@ __FBSDID("$FreeBSD$");
 static void monitor_vattach(struct ieee80211vap *);
 static int monitor_newstate(struct ieee80211vap *, enum ieee80211_state, int);
 static int monitor_input(struct ieee80211_node *ni, struct mbuf *m,
-	int rssi, int nf);
+	const struct ieee80211_rx_stats *rxs, int rssi, int nf);
 
 void
 ieee80211_monitor_attach(struct ieee80211com *ic)
@@ -125,7 +125,8 @@ monitor_newstate(struct ieee80211vap *va
  * Process a received frame in monitor mode.
  */
 static int
-monitor_input(struct ieee80211_node *ni, struct mbuf *m, int rssi, int nf)
+monitor_input(struct ieee80211_node *ni, struct mbuf *m,
+    const struct ieee80211_rx_stats *rxs, int rssi, int nf)
 {
 	struct ieee80211vap *vap = ni->ni_vap;
 	struct ifnet *ifp = vap->iv_ifp;

Modified: head/sys/net80211/ieee80211_proto.h
==============================================================================
--- head/sys/net80211/ieee80211_proto.h	Mon May 25 15:18:32 2015	(r283534)
+++ head/sys/net80211/ieee80211_proto.h	Mon May 25 16:37:41 2015	(r283535)
@@ -68,6 +68,9 @@ void	ieee80211_syncflag_ext(struct ieee8
 #define	IEEE80211_R_C_RSSI	0x0000010	/* per-chain RSSI value valid */
 #define	IEEE80211_R_C_EVM	0x0000020	/* per-chain EVM valid */
 #define	IEEE80211_R_C_HT40	0x0000040	/* RX'ed packet is 40mhz, pilots 4,5 valid */
+#define	IEEE80211_R_FREQ	0x0000080	/* Freq value populated, MHz */
+#define	IEEE80211_R_IEEE	0x0000100	/* IEEE value populated */
+#define	IEEE80211_R_BAND	0x0000200	/* Frequency band populated */
 
 struct ieee80211_rx_stats {
 	uint32_t r_flags;		/* IEEE80211_R_* flags */
@@ -80,10 +83,12 @@ struct ieee80211_rx_stats {
 	uint8_t rssi;			/* global RSSI */
 	uint8_t evm[IEEE80211_MAX_CHAINS][IEEE80211_MAX_EVM_PILOTS];
 					/* per-chain, per-pilot EVM values */
+	uint16_t c_freq;
+	uint8_t c_ieee;
 };
 
 #define	ieee80211_input(ni, m, rssi, nf) \
-	((ni)->ni_vap->iv_input(ni, m, rssi, nf))
+	((ni)->ni_vap->iv_input(ni, m, NULL, rssi, nf))
 int	ieee80211_input_all(struct ieee80211com *, struct mbuf *, int, int);
 
 int	ieee80211_input_mimo(struct ieee80211_node *, struct mbuf *,

Modified: head/sys/net80211/ieee80211_sta.c
==============================================================================
--- head/sys/net80211/ieee80211_sta.c	Mon May 25 15:18:32 2015	(r283534)
+++ head/sys/net80211/ieee80211_sta.c	Mon May 25 16:37:41 2015	(r283535)
@@ -70,9 +70,10 @@ __FBSDID("$FreeBSD$");
 static	void sta_vattach(struct ieee80211vap *);
 static	void sta_beacon_miss(struct ieee80211vap *);
 static	int sta_newstate(struct ieee80211vap *, enum ieee80211_state, int);
-static	int sta_input(struct ieee80211_node *, struct mbuf *, int, int);
+static	int sta_input(struct ieee80211_node *, struct mbuf *,
+	    const struct ieee80211_rx_stats *, int, int);
 static void sta_recv_mgmt(struct ieee80211_node *, struct mbuf *,
-	    int subtype, int rssi, int nf);
+	    int subtype, const struct ieee80211_rx_stats *, int rssi, int nf);
 static void sta_recv_ctl(struct ieee80211_node *, struct mbuf *, int subtype);
 
 void
@@ -525,7 +526,8 @@ doprint(struct ieee80211vap *vap, int su
  * by the 802.11 layer.
  */
 static int
-sta_input(struct ieee80211_node *ni, struct mbuf *m, int rssi, int nf)
+sta_input(struct ieee80211_node *ni, struct mbuf *m,
+    const struct ieee80211_rx_stats *rxs, int rssi, int nf)
 {
 	struct ieee80211vap *vap = ni->ni_vap;
 	struct ieee80211com *ic = ni->ni_ic;
@@ -922,7 +924,7 @@ sta_input(struct ieee80211_node *ni, str
 			wh = mtod(m, struct ieee80211_frame *);
 			wh->i_fc[1] &= ~IEEE80211_FC1_PROTECTED;
 		}
-		vap->iv_recv_mgmt(ni, m, subtype, rssi, nf);
+		vap->iv_recv_mgmt(ni, m, subtype, rxs, rssi, nf);
 		goto out;
 
 	case IEEE80211_FC0_TYPE_CTL:
@@ -1285,13 +1287,15 @@ startbgscan(struct ieee80211vap *vap)
 }
 
 static void
-sta_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0,
-	int subtype, int rssi, int nf)
+sta_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0, int subtype,
+    const struct ieee80211_rx_stats *rxs,
+    int rssi, int nf)
 {
 #define	ISPROBE(_st)	((_st) == IEEE80211_FC0_SUBTYPE_PROBE_RESP)
 #define	ISREASSOC(_st)	((_st) == IEEE80211_FC0_SUBTYPE_REASSOC_RESP)
 	struct ieee80211vap *vap = ni->ni_vap;
 	struct ieee80211com *ic = ni->ni_ic;
+	struct ieee80211_channel *rxchan = ic->ic_curchan;
 	struct ieee80211_frame *wh;
 	uint8_t *frm, *efrm;
 	uint8_t *rates, *xrates, *wme, *htcap, *htinfo;
@@ -1305,6 +1309,7 @@ sta_recv_mgmt(struct ieee80211_node *ni,
 	case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
 	case IEEE80211_FC0_SUBTYPE_BEACON: {
 		struct ieee80211_scanparams scan;
+		struct ieee80211_channel *c;
 		/*
 		 * We process beacon/probe response frames:
 		 *    o when scanning, or
@@ -1316,8 +1321,16 @@ sta_recv_mgmt(struct ieee80211_node *ni,
 			vap->iv_stats.is_rx_mgtdiscard++;
 			return;
 		}
+
+		/* Override RX channel as appropriate */
+		if (rxs != NULL) {
+			c = ieee80211_lookup_channel_rxstatus(vap, rxs);
+			if (c != NULL)
+				rxchan = c;
+		}
+
 		/* XXX probe response in sta mode when !scanning? */
-		if (ieee80211_parse_beacon(ni, m0, &scan) != 0) {
+		if (ieee80211_parse_beacon(ni, m0, rxchan, &scan) != 0) {
 			if (! (ic->ic_flags & IEEE80211_F_SCAN))
 				vap->iv_stats.is_beacon_bad++;
 			return;
@@ -1484,7 +1497,7 @@ sta_recv_mgmt(struct ieee80211_node *ni,
 			 * our ap.
 			 */
 			if (ic->ic_flags & IEEE80211_F_SCAN) {
-				ieee80211_add_scan(vap, ic->ic_curchan,
+				ieee80211_add_scan(vap, rxchan,
 				    &scan, wh, subtype, rssi, nf);
 			} else if (contbgscan(vap)) {
 				ieee80211_bg_scan(vap, 0);
@@ -1529,7 +1542,7 @@ sta_recv_mgmt(struct ieee80211_node *ni,
 				ieee80211_probe_curchan(vap, 1);
 				ic->ic_flags_ext &= ~IEEE80211_FEXT_PROBECHAN;
 			}
-			ieee80211_add_scan(vap, ic->ic_curchan, &scan, wh,
+			ieee80211_add_scan(vap, rxchan, &scan, wh,
 			    subtype, rssi, nf);
 			return;
 		}

Modified: head/sys/net80211/ieee80211_tdma.c
==============================================================================
--- head/sys/net80211/ieee80211_tdma.c	Mon May 25 15:18:32 2015	(r283534)
+++ head/sys/net80211/ieee80211_tdma.c	Mon May 25 16:37:41 2015	(r283535)
@@ -115,7 +115,7 @@ static void tdma_vdetach(struct ieee8021
 static int tdma_newstate(struct ieee80211vap *, enum ieee80211_state, int);
 static void tdma_beacon_miss(struct ieee80211vap *vap);
 static void tdma_recv_mgmt(struct ieee80211_node *, struct mbuf *,
-	int subtype, int rssi, int nf);
+	int subtype, const struct ieee80211_rx_stats *rxs, int rssi, int nf);
 static int tdma_update(struct ieee80211vap *vap,
 	const struct ieee80211_tdma_param *tdma, struct ieee80211_node *ni,
 	int pickslot);
@@ -320,7 +320,7 @@ tdma_beacon_miss(struct ieee80211vap *va
 
 static void
 tdma_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0,
-	int subtype, int rssi, int nf)
+	int subtype, const struct ieee80211_rx_stats *rxs, int rssi, int nf)
 {
 	struct ieee80211com *ic = ni->ni_ic;
 	struct ieee80211vap *vap = ni->ni_vap;
@@ -331,7 +331,8 @@ tdma_recv_mgmt(struct ieee80211_node *ni
 		struct ieee80211_frame *wh = mtod(m0, struct ieee80211_frame *);
 		struct ieee80211_scanparams scan;
 
-		if (ieee80211_parse_beacon(ni, m0, &scan) != 0)
+		/* XXX TODO: use rxstatus to determine off-channel beacons */
+		if (ieee80211_parse_beacon(ni, m0, ic->ic_curchan, &scan) != 0)
 			return;
 		if (scan.tdma == NULL) {
 			/*
@@ -391,7 +392,7 @@ tdma_recv_mgmt(struct ieee80211_node *ni
 		 *     2x parsing of the frame but should happen infrequently
 		 */
 	}
-	ts->tdma_recv_mgmt(ni, m0, subtype, rssi, nf);
+	ts->tdma_recv_mgmt(ni, m0, subtype, rxs, rssi, nf);
 }
 
 /*

Modified: head/sys/net80211/ieee80211_tdma.h
==============================================================================
--- head/sys/net80211/ieee80211_tdma.h	Mon May 25 15:18:32 2015	(r283534)
+++ head/sys/net80211/ieee80211_tdma.h	Mon May 25 16:37:41 2015	(r283535)
@@ -81,7 +81,8 @@ struct ieee80211_tdma_state {
 	int	(*tdma_newstate)(struct ieee80211vap *, enum ieee80211_state,
 		    int arg);
 	void	(*tdma_recv_mgmt)(struct ieee80211_node *,
-		    struct mbuf *, int, int, int);
+		    struct mbuf *, int,
+		    const struct ieee80211_rx_stats *rxs, int, int);
 	void	(*tdma_opdetach)(struct ieee80211vap *);
 };
  

Modified: head/sys/net80211/ieee80211_var.h
==============================================================================
--- head/sys/net80211/ieee80211_var.h	Mon May 25 15:18:32 2015	(r283534)
+++ head/sys/net80211/ieee80211_var.h	Mon May 25 16:37:41 2015	(r283535)
@@ -468,9 +468,13 @@ struct ieee80211vap {
 	void			(*iv_opdetach)(struct ieee80211vap *);
 	/* receive processing */
 	int			(*iv_input)(struct ieee80211_node *,
-				    struct mbuf *, int, int);
+				    struct mbuf *,
+				    const struct ieee80211_rx_stats *,
+				    int, int);
 	void			(*iv_recv_mgmt)(struct ieee80211_node *,
-				    struct mbuf *, int, int, int);
+				    struct mbuf *, int,
+				    const struct ieee80211_rx_stats *,
+				    int, int);
 	void			(*iv_recv_ctl)(struct ieee80211_node *,
 				    struct mbuf *, int);
 	void			(*iv_deliver_data)(struct ieee80211vap *,
@@ -710,6 +714,8 @@ struct ieee80211_channel *ieee80211_find
 		int freq, int flags);
 struct ieee80211_channel *ieee80211_find_channel_byieee(struct ieee80211com *,
 		int ieee, int flags);
+struct ieee80211_channel *ieee80211_lookup_channel_rxstatus(struct ieee80211vap *,
+		const struct ieee80211_rx_stats *);
 int	ieee80211_setmode(struct ieee80211com *, enum ieee80211_phymode);
 enum ieee80211_phymode ieee80211_chan2mode(const struct ieee80211_channel *);
 uint32_t ieee80211_mac_hash(const struct ieee80211com *,

Modified: head/sys/net80211/ieee80211_wds.c
==============================================================================
--- head/sys/net80211/ieee80211_wds.c	Mon May 25 15:18:32 2015	(r283534)
+++ head/sys/net80211/ieee80211_wds.c	Mon May 25 16:37:41 2015	(r283535)
@@ -64,9 +64,10 @@ __FBSDID("$FreeBSD$");
 
 static void wds_vattach(struct ieee80211vap *);
 static int wds_newstate(struct ieee80211vap *, enum ieee80211_state, int);
-static	int wds_input(struct ieee80211_node *ni, struct mbuf *m, int, int);
-static void wds_recv_mgmt(struct ieee80211_node *, struct mbuf *,
-	    int subtype, int, int);
+static	int wds_input(struct ieee80211_node *ni, struct mbuf *m,
+	    const struct ieee80211_rx_stats *rxs, int, int);
+static void wds_recv_mgmt(struct ieee80211_node *, struct mbuf *, int subtype,
+	const struct ieee80211_rx_stats *, int, int);
 
 void
 ieee80211_wds_attach(struct ieee80211com *ic)
@@ -408,7 +409,8 @@ wds_newstate(struct ieee80211vap *vap, e
  * by the 802.11 layer.
  */
 static int
-wds_input(struct ieee80211_node *ni, struct mbuf *m, int rssi, int nf)
+wds_input(struct ieee80211_node *ni, struct mbuf *m,
+    const struct ieee80211_rx_stats *rxs, int rssi, int nf)
 {
 	struct ieee80211vap *vap = ni->ni_vap;
 	struct ieee80211com *ic = ni->ni_ic;
@@ -718,7 +720,7 @@ wds_input(struct ieee80211_node *ni, str
 			vap->iv_stats.is_rx_mgtdiscard++; /* XXX */
 			goto out;
 		}
-		vap->iv_recv_mgmt(ni, m, subtype, rssi, nf);
+		vap->iv_recv_mgmt(ni, m, subtype, rxs, rssi, nf);
 		goto out;
 
 	case IEEE80211_FC0_TYPE_CTL:
@@ -744,8 +746,8 @@ out:
 }
 
 static void
-wds_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0,
-	int subtype, int rssi, int nf)
+wds_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0, int subtype,
+    const struct ieee80211_rx_stats *rxs, int rssi, int nf)
 {
 	struct ieee80211vap *vap = ni->ni_vap;
 	struct ieee80211com *ic = ni->ni_ic;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201505251637.t4PGbgoh024594>