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.
This commit is contained in:
parent
375c3709be
commit
7eab7c352d
@ -327,7 +327,7 @@ ath_legacy_rxbuf_init(struct ath_softc *sc, struct ath_buf *bf)
|
||||
*/
|
||||
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, struct mbuf *m,
|
||||
* 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 */
|
||||
|
@ -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))
|
||||
|
@ -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 *);
|
||||
|
@ -127,7 +127,8 @@ static int wi_newstate_sta(struct ieee80211vap *, enum ieee80211_state, int);
|
||||
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, struct mbuf *m,
|
||||
/* 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
|
||||
|
@ -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);
|
||||
};
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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 subtype)
|
||||
* 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, struct mbuf *m, int rssi, int nf)
|
||||
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 uint8_t *xrates)
|
||||
|
||||
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 *ni, struct mbuf *m0,
|
||||
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 *ni, struct mbuf *m0,
|
||||
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 *ni, struct mbuf *m0,
|
||||
|
||||
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 *ni, struct mbuf *m0,
|
||||
* 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) {
|
||||
|
@ -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 subtype)
|
||||
* 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, struct mbuf *m, int rssi, int nf)
|
||||
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 uint8_t *xrates)
|
||||
|
||||
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 *ni, struct mbuf *m0,
|
||||
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.
|
||||
|
@ -88,7 +88,8 @@ ieee80211_input_mimo(struct ieee80211_node *ni, struct mbuf *m,
|
||||
{
|
||||
/* 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 ieee80211_node *ni)
|
||||
*/
|
||||
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_node *ni, struct mbuf *m,
|
||||
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_node *ni, struct mbuf *m,
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
@ -255,6 +255,7 @@ void ieee80211_send_error(struct ieee80211_node *,
|
||||
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_ */
|
||||
|
@ -85,9 +85,10 @@ static void mesh_transmit_to_gate(struct ieee80211vap *, struct mbuf *,
|
||||
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 *vap, struct mbuf *m,
|
||||
}
|
||||
|
||||
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, struct mbuf *m, int rssi, int nf)
|
||||
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 @@ mesh_input(struct ieee80211_node *ni, struct mbuf *m, int rssi, int nf)
|
||||
|
||||
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, struct mbuf *m0, int subtype,
|
||||
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, struct mbuf *m0, int subtype,
|
||||
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;
|
||||
}
|
||||
|
@ -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 *vap, enum ieee80211_state nstate, int arg)
|
||||
* 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;
|
||||
|
@ -68,6 +68,9 @@ void ieee80211_syncflag_ext(struct ieee80211vap *, int flag);
|
||||
#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 *,
|
||||
|
@ -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 subtype)
|
||||
* 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, struct mbuf *m, int rssi, int nf)
|
||||
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, struct mbuf *m0,
|
||||
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, struct mbuf *m0,
|
||||
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, struct mbuf *m0,
|
||||
* 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, struct mbuf *m0,
|
||||
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;
|
||||
}
|
||||
|
@ -115,7 +115,7 @@ static void tdma_vdetach(struct ieee80211vap *vap);
|
||||
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 *vap)
|
||||
|
||||
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 mbuf *m0,
|
||||
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, struct mbuf *m0,
|
||||
* 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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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 *);
|
||||
};
|
||||
|
||||
|
@ -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_channel(struct ieee80211com *,
|
||||
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 *,
|
||||
|
@ -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, enum ieee80211_state nstate, int arg)
|
||||
* 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, struct mbuf *m, int rssi, int nf)
|
||||
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 @@ wds_input(struct ieee80211_node *ni, struct mbuf *m, int rssi, int nf)
|
||||
}
|
||||
|
||||
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;
|
||||
|
Loading…
Reference in New Issue
Block a user