diff options
-rw-r--r-- | sys/dev/ath/if_ath_rx.c | 4 | ||||
-rw-r--r-- | sys/dev/ath/if_ath_rx.h | 3 | ||||
-rw-r--r-- | sys/dev/ath/if_athvar.h | 3 | ||||
-rw-r--r-- | sys/dev/wi/if_wi.c | 7 | ||||
-rw-r--r-- | sys/dev/wi/if_wivar.h | 2 | ||||
-rw-r--r-- | sys/net80211/ieee80211.c | 69 | ||||
-rw-r--r-- | sys/net80211/ieee80211_adhoc.c | 29 | ||||
-rw-r--r-- | sys/net80211/ieee80211_hostap.c | 13 | ||||
-rw-r--r-- | sys/net80211/ieee80211_input.c | 10 | ||||
-rw-r--r-- | sys/net80211/ieee80211_input.h | 1 | ||||
-rw-r--r-- | sys/net80211/ieee80211_mesh.c | 23 | ||||
-rw-r--r-- | sys/net80211/ieee80211_monitor.c | 5 | ||||
-rw-r--r-- | sys/net80211/ieee80211_proto.h | 7 | ||||
-rw-r--r-- | sys/net80211/ieee80211_sta.c | 31 | ||||
-rw-r--r-- | sys/net80211/ieee80211_tdma.c | 9 | ||||
-rw-r--r-- | sys/net80211/ieee80211_tdma.h | 3 | ||||
-rw-r--r-- | sys/net80211/ieee80211_var.h | 10 | ||||
-rw-r--r-- | sys/net80211/ieee80211_wds.c | 16 |
18 files changed, 185 insertions, 60 deletions
diff --git a/sys/dev/ath/if_ath_rx.c b/sys/dev/ath/if_ath_rx.c index bed94887c988..07a4abee3458 100644 --- a/sys/dev/ath/if_ath_rx.c +++ b/sys/dev/ath/if_ath_rx.c @@ -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 */ diff --git a/sys/dev/ath/if_ath_rx.h b/sys/dev/ath/if_ath_rx.h index f831148bfd25..62be699f752b 100644 --- a/sys/dev/ath/if_ath_rx.h +++ b/sys/dev/ath/if_ath_rx.h @@ -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)) diff --git a/sys/dev/ath/if_athvar.h b/sys/dev/ath/if_athvar.h index e888ca2ee9ed..5c5e6cd3d287 100644 --- a/sys/dev/ath/if_athvar.h +++ b/sys/dev/ath/if_athvar.h @@ -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 *); diff --git a/sys/dev/wi/if_wi.c b/sys/dev/wi/if_wi.c index 3978224c5400..8f793c578387 100644 --- a/sys/dev/wi/if_wi.c +++ b/sys/dev/wi/if_wi.c @@ -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 diff --git a/sys/dev/wi/if_wivar.h b/sys/dev/wi/if_wivar.h index 99b866daf10f..f163744ef834 100644 --- a/sys/dev/wi/if_wivar.h +++ b/sys/dev/wi/if_wivar.h @@ -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); }; 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) { diff --git a/sys/net80211/ieee80211_adhoc.c b/sys/net80211/ieee80211_adhoc.c index 0d761c4af985..d31ad9be0de6 100644 --- a/sys/net80211/ieee80211_adhoc.c +++ b/sys/net80211/ieee80211_adhoc.c @@ -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) { diff --git a/sys/net80211/ieee80211_hostap.c b/sys/net80211/ieee80211_hostap.c index a625b4e95a22..f96fb2cb225a 100644 --- a/sys/net80211/ieee80211_hostap.c +++ b/sys/net80211/ieee80211_hostap.c @@ -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. diff --git a/sys/net80211/ieee80211_input.c b/sys/net80211/ieee80211_input.c index a0f737dc2036..9f3fad30f70a 100644 --- a/sys/net80211/ieee80211_input.c +++ b/sys/net80211/ieee80211_input.c @@ -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; } diff --git a/sys/net80211/ieee80211_input.h b/sys/net80211/ieee80211_input.h index f3d569efd582..72fd25b4ffc9 100644 --- a/sys/net80211/ieee80211_input.h +++ b/sys/net80211/ieee80211_input.h @@ -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_ */ diff --git a/sys/net80211/ieee80211_mesh.c b/sys/net80211/ieee80211_mesh.c index 5ffd50bc7ade..225a5079ce0c 100644 --- a/sys/net80211/ieee80211_mesh.c +++ b/sys/net80211/ieee80211_mesh.c @@ -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 @@ 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, 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; } diff --git a/sys/net80211/ieee80211_monitor.c b/sys/net80211/ieee80211_monitor.c index 8909339bde29..e0778461fd42 100644 --- a/sys/net80211/ieee80211_monitor.c +++ b/sys/net80211/ieee80211_monitor.c @@ -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; diff --git a/sys/net80211/ieee80211_proto.h b/sys/net80211/ieee80211_proto.h index 3b46ac4b1ecd..74cdbc5da75e 100644 --- a/sys/net80211/ieee80211_proto.h +++ b/sys/net80211/ieee80211_proto.h @@ -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 *, diff --git a/sys/net80211/ieee80211_sta.c b/sys/net80211/ieee80211_sta.c index 267ad1149d73..424aac8fa69a 100644 --- a/sys/net80211/ieee80211_sta.c +++ b/sys/net80211/ieee80211_sta.c @@ -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; } diff --git a/sys/net80211/ieee80211_tdma.c b/sys/net80211/ieee80211_tdma.c index 08acc3897c51..d9ee46445971 100644 --- a/sys/net80211/ieee80211_tdma.c +++ b/sys/net80211/ieee80211_tdma.c @@ -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); } /* diff --git a/sys/net80211/ieee80211_tdma.h b/sys/net80211/ieee80211_tdma.h index 2fe591f73e3e..76b9ed1c3b00 100644 --- a/sys/net80211/ieee80211_tdma.h +++ b/sys/net80211/ieee80211_tdma.h @@ -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 *); }; diff --git a/sys/net80211/ieee80211_var.h b/sys/net80211/ieee80211_var.h index e7d2f91c8ce2..4c9fbf3d8d21 100644 --- a/sys/net80211/ieee80211_var.h +++ b/sys/net80211/ieee80211_var.h @@ -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 *, diff --git a/sys/net80211/ieee80211_wds.c b/sys/net80211/ieee80211_wds.c index fc7725948b84..1d3f30a7a48e 100644 --- a/sys/net80211/ieee80211_wds.c +++ b/sys/net80211/ieee80211_wds.c @@ -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 @@ 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; |