diff options
author | Renato Botelho <renato@netgate.com> | 2016-02-22 14:40:56 -0300 |
---|---|---|
committer | Renato Botelho <renato@netgate.com> | 2016-02-22 14:40:56 -0300 |
commit | 0a3437aa52c010dc2ab10b9778a383fef436382c (patch) | |
tree | b2f879569f9d9deb23e4d7accb103d30a64e1527 /sys/net80211 | |
parent | 6a0f7868a911546f7be04cc546e99cc803686af3 (diff) | |
download | FreeBSD-src-0a3437aa52c010dc2ab10b9778a383fef436382c.zip FreeBSD-src-0a3437aa52c010dc2ab10b9778a383fef436382c.tar.gz |
Revert "Importing pfSense patches net80211HEAD.tgz and conf.file.ieee80211.diff"
This reverts commit 6ee75bdd7bf7c20359dd6e38c243586cb062edea.
Diffstat (limited to 'sys/net80211')
40 files changed, 843 insertions, 1564 deletions
diff --git a/sys/net80211/ieee80211.c b/sys/net80211/ieee80211.c index 2fa7e9a..db505ab 100644 --- a/sys/net80211/ieee80211.c +++ b/sys/net80211/ieee80211.c @@ -39,7 +39,6 @@ __FBSDID("$FreeBSD$"); #include <sys/socket.h> #include <net/if.h> -#include <net/if_var.h> #include <net/if_dl.h> #include <net/if_media.h> #include <net/if_types.h> @@ -238,7 +237,7 @@ static int null_transmit(struct ifnet *ifp, struct mbuf *m) { m_freem(m); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; return EACCES; /* XXX EIO/EPERM? */ } @@ -570,9 +569,15 @@ ieee80211_vap_attach(struct ieee80211vap *vap, ifp->if_baudrate = IF_Mbps(maxrate); ether_ifattach(ifp, vap->iv_myaddr); - /* hook output method setup by ether_ifattach */ - vap->iv_output = ifp->if_output; - ifp->if_output = ieee80211_output; + if (vap->iv_opmode == IEEE80211_M_MONITOR) { + /* NB: disallow transmit */ + ifp->if_transmit = null_transmit; + ifp->if_output = null_output; + } else { + /* hook output method setup by ether_ifattach */ + vap->iv_output = ifp->if_output; + ifp->if_output = ieee80211_output; + } /* NB: if_mtu set by ether_ifattach to ETHERMTU */ IEEE80211_LOCK(ic); @@ -1402,8 +1407,7 @@ ieee80211_media_status(struct ifnet *ifp, struct ifmediareq *imr) * rate only when running; otherwise we may have a mismatch * in which case the rate will not be convertible. */ - if (vap->iv_state == IEEE80211_S_RUN || - vap->iv_state == IEEE80211_S_SLEEP) { + if (vap->iv_state == IEEE80211_S_RUN) { imr->ifm_status |= IFM_ACTIVE; mode = ieee80211_chan2mode(ic->ic_curchan); } else @@ -1747,23 +1751,3 @@ ieee80211_mac_hash(const struct ieee80211com *ic, return c; } #undef mix - -char -ieee80211_channel_type_char(const struct ieee80211_channel *c) -{ - if (IEEE80211_IS_CHAN_ST(c)) - return 'S'; - if (IEEE80211_IS_CHAN_108A(c)) - return 'T'; - if (IEEE80211_IS_CHAN_108G(c)) - return 'G'; - if (IEEE80211_IS_CHAN_HT(c)) - return 'n'; - if (IEEE80211_IS_CHAN_A(c)) - return 'a'; - if (IEEE80211_IS_CHAN_ANYG(c)) - return 'g'; - if (IEEE80211_IS_CHAN_B(c)) - return 'b'; - return 'f'; -} diff --git a/sys/net80211/ieee80211.h b/sys/net80211/ieee80211.h index 8e586bd..9b005f3 100644 --- a/sys/net80211/ieee80211.h +++ b/sys/net80211/ieee80211.h @@ -169,11 +169,6 @@ struct ieee80211_qosframe_addr4 { #define IEEE80211_FC1_PROTECTED 0x40 #define IEEE80211_FC1_ORDER 0x80 -#define IEEE80211_HAS_SEQ(type, subtype) \ - ((type) != IEEE80211_FC0_TYPE_CTL && \ - !((type) == IEEE80211_FC0_TYPE_DATA && \ - ((subtype) & IEEE80211_FC0_SUBTYPE_QOS_NULL) == \ - IEEE80211_FC0_SUBTYPE_QOS_NULL)) #define IEEE80211_SEQ_FRAG_MASK 0x000f #define IEEE80211_SEQ_FRAG_SHIFT 0 #define IEEE80211_SEQ_SEQ_MASK 0xfff0 diff --git a/sys/net80211/ieee80211_action.c b/sys/net80211/ieee80211_action.c index e37863e..a36df7c 100644 --- a/sys/net80211/ieee80211_action.c +++ b/sys/net80211/ieee80211_action.c @@ -42,7 +42,6 @@ __FBSDID("$FreeBSD$"); #include <sys/socket.h> #include <net/if.h> -#include <net/if_var.h> #include <net/if_media.h> #include <net/ethernet.h> diff --git a/sys/net80211/ieee80211_adhoc.c b/sys/net80211/ieee80211_adhoc.c index 0d761c4..e9e0d30 100644 --- a/sys/net80211/ieee80211_adhoc.c +++ b/sys/net80211/ieee80211_adhoc.c @@ -48,7 +48,6 @@ __FBSDID("$FreeBSD$"); #include <sys/sysctl.h> #include <net/if.h> -#include <net/if_var.h> #include <net/if_media.h> #include <net/if_llc.h> #include <net/ethernet.h> @@ -229,8 +228,6 @@ adhoc_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) } #endif break; - case IEEE80211_S_RUN: /* IBSS merge */ - break; default: goto invalid; } @@ -291,6 +288,7 @@ doprint(struct ieee80211vap *vap, int subtype) static int adhoc_input(struct ieee80211_node *ni, struct mbuf *m, int rssi, int nf) { +#define HAS_SEQ(type) ((type & 0x4) == 0) struct ieee80211vap *vap = ni->ni_vap; struct ieee80211com *ic = ni->ni_ic; struct ifnet *ifp = vap->iv_ifp; @@ -370,10 +368,7 @@ adhoc_input(struct ieee80211_node *ni, struct mbuf *m, int rssi, int nf) /* * Validate the bssid. */ - if (!(type == IEEE80211_FC0_TYPE_MGT && - (subtype == IEEE80211_FC0_SUBTYPE_BEACON || - subtype == IEEE80211_FC0_SUBTYPE_PROBE_RESP)) && - !IEEE80211_ADDR_EQ(bssid, vap->iv_bss->ni_bssid) && + if (!IEEE80211_ADDR_EQ(bssid, vap->iv_bss->ni_bssid) && !IEEE80211_ADDR_EQ(bssid, ifp->if_broadcastaddr)) { /* not interested in */ IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT, @@ -413,8 +408,7 @@ adhoc_input(struct ieee80211_node *ni, struct mbuf *m, int rssi, int nf) } IEEE80211_RSSI_LPF(ni->ni_avgrssi, rssi); ni->ni_noise = nf; - if (IEEE80211_HAS_SEQ(type, subtype) && - IEEE80211_ADDR_EQ(wh->i_addr2, ni->ni_macaddr)) { + if (HAS_SEQ(type)) { uint8_t tid = ieee80211_gettid(wh); if (IEEE80211_QOS_HAS_SEQ(wh) && TID_TO_WME_AC(tid) >= WME_AC_VI) @@ -658,7 +652,7 @@ adhoc_input(struct ieee80211_node *ni, struct mbuf *m, int rssi, int nf) break; } err: - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + ifp->if_ierrors++; out: if (m != NULL) { if (need_tap && ieee80211_radiotap_active_vap(vap)) @@ -735,8 +729,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, - subtype, rssi, nf); + ieee80211_add_scan(vap, &scan, wh, subtype, rssi, nf); return; } if (scan.capinfo & IEEE80211_CAPINFO_IBSS) { diff --git a/sys/net80211/ieee80211_ageq.c b/sys/net80211/ieee80211_ageq.c index b650136..018ddc2 100644 --- a/sys/net80211/ieee80211_ageq.c +++ b/sys/net80211/ieee80211_ageq.c @@ -38,7 +38,6 @@ __FBSDID("$FreeBSD$"); #include <sys/socket.h> #include <net/if.h> -#include <net/if_var.h> #include <net/if_media.h> #include <net/ethernet.h> diff --git a/sys/net80211/ieee80211_alq.c b/sys/net80211/ieee80211_alq.c index a52103a..e651574 100644 --- a/sys/net80211/ieee80211_alq.c +++ b/sys/net80211/ieee80211_alq.c @@ -53,8 +53,10 @@ __FBSDID("$FreeBSD$"); #include <net/if.h> #include <net/if_var.h> +#include <net/if_dl.h> +#include <net/if_clone.h> #include <net/if_media.h> -#include <net/ethernet.h> +#include <net/if_types.h> #include <net80211/ieee80211_var.h> #include <net80211/ieee80211_freebsd.h> diff --git a/sys/net80211/ieee80211_amrr.c b/sys/net80211/ieee80211_amrr.c index b1d92c8..003b4bc 100644 --- a/sys/net80211/ieee80211_amrr.c +++ b/sys/net80211/ieee80211_amrr.c @@ -38,9 +38,7 @@ __FBSDID("$FreeBSD$"); #include <sys/sysctl.h> #include <net/if.h> -#include <net/if_var.h> #include <net/if_media.h> -#include <net/ethernet.h> #ifdef INET #include <netinet/in.h> @@ -131,12 +129,6 @@ amrr_deinit(struct ieee80211vap *vap) free(vap->iv_rs, M_80211_RATECTL); } -/* - * Return whether 11n rates are possible. - * - * Some 11n devices may return HT information but no HT rates. - * Thus, we shouldn't treat them as an 11n node. - */ static int amrr_node_is_11n(struct ieee80211_node *ni) { @@ -145,8 +137,6 @@ amrr_node_is_11n(struct ieee80211_node *ni) return (0); if (ni->ni_chan == IEEE80211_CHAN_ANYC) return (0); - if (IEEE80211_IS_CHAN_HT(ni->ni_chan) && ni->ni_htrates.rs_nrates == 0) - return (0); return (IEEE80211_IS_CHAN_HT(ni->ni_chan)); } @@ -195,18 +185,17 @@ amrr_node_init(struct ieee80211_node *ni) rate &= IEEE80211_RATE_VAL; /* pick initial rate from the rateset - HT or otherwise */ - /* Pick something low that's likely to succeed */ for (amn->amn_rix = rs->rs_nrates - 1; amn->amn_rix > 0; amn->amn_rix--) { /* legacy - anything < 36mbit, stop searching */ - /* 11n - stop at MCS4 */ - if (amrr_node_is_11n(ni)) { - if ((rs->rs_rates[amn->amn_rix] & 0x1f) < 4) - break; - } else if ((rs->rs_rates[amn->amn_rix] & IEEE80211_RATE_VAL) <= 72) + /* 11n - stop at MCS4 / MCS12 / MCS28 */ + if (amrr_node_is_11n(ni) && + (rs->rs_rates[amn->amn_rix] & 0x7) < 4) + break; + else if ((rs->rs_rates[amn->amn_rix] & IEEE80211_RATE_VAL) <= 72) break; + rate = rs->rs_rates[amn->amn_rix] & IEEE80211_RATE_VAL; } - rate = rs->rs_rates[amn->amn_rix] & IEEE80211_RATE_VAL; /* if the rate is an 11n rate, ensure the MCS bit is set */ if (amrr_node_is_11n(ni)) diff --git a/sys/net80211/ieee80211_ddb.c b/sys/net80211/ieee80211_ddb.c index 74e82e5..6f7dabf 100644 --- a/sys/net80211/ieee80211_ddb.c +++ b/sys/net80211/ieee80211_ddb.c @@ -39,7 +39,6 @@ __FBSDID("$FreeBSD$"); #include <sys/socket.h> #include <net/if.h> -#include <net/if_var.h> #include <net/if_dl.h> #include <net/if_media.h> #include <net/if_types.h> diff --git a/sys/net80211/ieee80211_dfs.c b/sys/net80211/ieee80211_dfs.c index 5fa9ba4..82e525d 100644 --- a/sys/net80211/ieee80211_dfs.c +++ b/sys/net80211/ieee80211_dfs.c @@ -48,9 +48,7 @@ __FBSDID("$FreeBSD$"); #include <sys/sysctl.h> #include <net/if.h> -#include <net/if_var.h> #include <net/if_media.h> -#include <net/ethernet.h> #include <net80211/ieee80211_var.h> diff --git a/sys/net80211/ieee80211_freebsd.c b/sys/net80211/ieee80211_freebsd.c index 0822058..8c97f1e 100644 --- a/sys/net80211/ieee80211_freebsd.c +++ b/sys/net80211/ieee80211_freebsd.c @@ -44,7 +44,6 @@ __FBSDID("$FreeBSD$"); #include <net/bpf.h> #include <net/if.h> -#include <net/if_var.h> #include <net/if_dl.h> #include <net/if_clone.h> #include <net/if_media.h> @@ -420,7 +419,7 @@ ieee80211_getmgtframe(uint8_t **frm, int headroom, int pktlen) * frames which all fit in MHLEN. */ if (m != NULL) - M_ALIGN(m, len); + MH_ALIGN(m, len); } else { m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); if (m != NULL) @@ -873,8 +872,14 @@ wlan_modevent(module_t mod, int type, void *unused) printf("wlan: <802.11 Link Layer>\n"); wlan_bpfevent = EVENTHANDLER_REGISTER(bpf_track, bpf_track, 0, EVENTHANDLER_PRI_ANY); + if (wlan_bpfevent == NULL) + return ENOMEM; wlan_ifllevent = EVENTHANDLER_REGISTER(iflladdr_event, wlan_iflladdr, NULL, EVENTHANDLER_PRI_ANY); + if (wlan_ifllevent == NULL) { + EVENTHANDLER_DEREGISTER(bpf_track, wlan_bpfevent); + return ENOMEM; + } #if __FreeBSD_version >= 1000020 wlan_cloner = if_clone_simple(wlanname, wlan_clone_create, wlan_clone_destroy, 0); diff --git a/sys/net80211/ieee80211_freebsd.h b/sys/net80211/ieee80211_freebsd.h index aa21f3b..711bac3 100644 --- a/sys/net80211/ieee80211_freebsd.h +++ b/sys/net80211/ieee80211_freebsd.h @@ -355,8 +355,8 @@ wlan_##name##_modevent(module_t mod, int type, void *unused) \ case MOD_UNLOAD: \ case MOD_QUIESCE: \ if (nrefs) { \ - printf("wlan_" #name ": still in use " \ - "(%u dynamic refs)\n", nrefs); \ + printf("wlan_##name: still in use (%u dynamic refs)\n",\ + nrefs); \ return EBUSY; \ } \ if (type == MOD_UNLOAD) { \ diff --git a/sys/net80211/ieee80211_hostap.c b/sys/net80211/ieee80211_hostap.c index a625b4e..832a8b0 100644 --- a/sys/net80211/ieee80211_hostap.c +++ b/sys/net80211/ieee80211_hostap.c @@ -48,7 +48,6 @@ __FBSDID("$FreeBSD$"); #include <sys/sysctl.h> #include <net/if.h> -#include <net/if_var.h> #include <net/if_media.h> #include <net/if_llc.h> #include <net/ethernet.h> @@ -368,7 +367,7 @@ hostap_deliver_data(struct ieee80211vap *vap, /* * Do accounting. */ - if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1); + ifp->if_ipackets++; IEEE80211_NODE_STAT(ni, rx_data); IEEE80211_NODE_STAT_ADD(ni, rx_bytes, m->m_pkthdr.len); if (ETHER_IS_MULTICAST(eh->ether_dhost)) { @@ -384,7 +383,7 @@ hostap_deliver_data(struct ieee80211vap *vap, if (m->m_flags & M_MCAST) { mcopy = m_dup(m, M_NOWAIT); if (mcopy == NULL) - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; else mcopy->m_flags |= M_MCAST; } else { @@ -422,7 +421,7 @@ hostap_deliver_data(struct ieee80211vap *vap, if (err) { /* NB: IFQ_HANDOFF reclaims mcopy */ } else { - if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); + ifp->if_opackets++; } } } @@ -478,6 +477,7 @@ doprint(struct ieee80211vap *vap, int subtype) static int hostap_input(struct ieee80211_node *ni, struct mbuf *m, int rssi, int nf) { +#define HAS_SEQ(type) ((type & 0x4) == 0) struct ieee80211vap *vap = ni->ni_vap; struct ieee80211com *ic = ni->ni_ic; struct ifnet *ifp = vap->iv_ifp; @@ -570,7 +570,7 @@ hostap_input(struct ieee80211_node *ni, struct mbuf *m, int rssi, int nf) IEEE80211_RSSI_LPF(ni->ni_avgrssi, rssi); ni->ni_noise = nf; - if (IEEE80211_HAS_SEQ(type, subtype)) { + if (HAS_SEQ(type)) { uint8_t tid = ieee80211_gettid(wh); if (IEEE80211_QOS_HAS_SEQ(wh) && TID_TO_WME_AC(tid) >= WME_AC_VI) @@ -908,7 +908,7 @@ hostap_input(struct ieee80211_node *ni, struct mbuf *m, int rssi, int nf) break; } err: - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + ifp->if_ierrors++; out: if (m != NULL) { if (need_tap && ieee80211_radiotap_active_vap(vap)) @@ -1736,8 +1736,7 @@ hostap_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, - subtype, rssi, nf); + ieee80211_add_scan(vap, &scan, wh, subtype, rssi, nf); return; } /* diff --git a/sys/net80211/ieee80211_ht.c b/sys/net80211/ieee80211_ht.c index 618252f..16135e1 100644 --- a/sys/net80211/ieee80211_ht.c +++ b/sys/net80211/ieee80211_ht.c @@ -43,7 +43,6 @@ __FBSDID("$FreeBSD$"); #include <sys/socket.h> #include <net/if.h> -#include <net/if_var.h> #include <net/if_media.h> #include <net/ethernet.h> @@ -1047,7 +1046,6 @@ ieee80211_ht_node_init(struct ieee80211_node *ni) tap = &ni->ni_tx_ampdu[tid]; tap->txa_tid = tid; tap->txa_ni = ni; - tap->txa_lastsample = ticks; /* NB: further initialization deferred */ } ni->ni_flags |= IEEE80211_NODE_HT | IEEE80211_NODE_AMPDU; @@ -1217,7 +1215,6 @@ ieee80211_ht_wds_init(struct ieee80211_node *ni) for (tid = 0; tid < WME_NUM_TID; tid++) { tap = &ni->ni_tx_ampdu[tid]; tap->txa_tid = tid; - tap->txa_lastsample = ticks; } /* NB: AMPDU tx/rx governed by IEEE80211_FHT_AMPDU_{TX,RX} */ ni->ni_flags |= IEEE80211_NODE_HT | IEEE80211_NODE_AMPDU; @@ -1693,7 +1690,6 @@ ampdu_tx_setup(struct ieee80211_tx_ampdu *tap) { callout_init(&tap->txa_timer, CALLOUT_MPSAFE); tap->txa_flags |= IEEE80211_AGGR_SETUP; - tap->txa_lastsample = ticks; } static void @@ -1721,12 +1717,8 @@ ampdu_tx_stop(struct ieee80211_tx_ampdu *tap) */ bar_stop_timer(tap); - /* - * Reset packet estimate. - */ - tap->txa_lastsample = ticks; + tap->txa_lastsample = 0; tap->txa_avgpps = 0; - /* NB: clearing NAK means we may re-send ADDBA */ tap->txa_flags &= ~(IEEE80211_AGGR_SETUP | IEEE80211_AGGR_NAK); } @@ -2662,24 +2654,10 @@ ieee80211_add_htcap_body(uint8_t *frm, struct ieee80211_node *ni) caps |= IEEE80211_HTCAP_CHWIDTH40; else caps &= ~IEEE80211_HTCAP_CHWIDTH40; - - /* Start by using the advertised settings */ + /* use advertised setting (XXX locally constraint) */ rxmax = MS(ni->ni_htparam, IEEE80211_HTCAP_MAXRXAMPDU); density = MS(ni->ni_htparam, IEEE80211_HTCAP_MPDUDENSITY); - /* Cap at VAP rxmax */ - if (rxmax > vap->iv_ampdu_rxmax) - rxmax = vap->iv_ampdu_rxmax; - - /* - * If the VAP ampdu density value greater, use that. - * - * (Larger density value == larger minimum gap between A-MPDU - * subframes.) - */ - if (vap->iv_ampdu_density > density) - density = vap->iv_ampdu_density; - /* * NB: Hardware might support HT40 on some but not all * channels. We can't determine this earlier because only @@ -2696,12 +2674,9 @@ ieee80211_add_htcap_body(uint8_t *frm, struct ieee80211_node *ni) caps |= IEEE80211_HTCAP_CHWIDTH40; else caps &= ~IEEE80211_HTCAP_CHWIDTH40; - - /* XXX TODO should it start by using advertised settings? */ rxmax = vap->iv_ampdu_rxmax; density = vap->iv_ampdu_density; } - /* adjust short GI based on channel and config */ if ((vap->iv_flags_ht & IEEE80211_FHT_SHORTGI20) == 0) caps &= ~IEEE80211_HTCAP_SHORTGI20; diff --git a/sys/net80211/ieee80211_input.c b/sys/net80211/ieee80211_input.c index a0f737d..5e95646 100644 --- a/sys/net80211/ieee80211_input.c +++ b/sys/net80211/ieee80211_input.c @@ -40,7 +40,6 @@ __FBSDID("$FreeBSD$"); #include <net/ethernet.h> #include <net/if.h> -#include <net/if_var.h> #include <net/if_llc.h> #include <net/if_media.h> #include <net/if_vlan_var.h> @@ -261,7 +260,7 @@ ieee80211_deliver_data(struct ieee80211vap *vap, /* * Do accounting. */ - if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1); + ifp->if_ipackets++; IEEE80211_NODE_STAT(ni, rx_data); IEEE80211_NODE_STAT_ADD(ni, rx_bytes, m->m_pkthdr.len); if (ETHER_IS_MULTICAST(eh->ether_dhost)) { diff --git a/sys/net80211/ieee80211_input.h b/sys/net80211/ieee80211_input.h index f3d569e..b90f46a 100644 --- a/sys/net80211/ieee80211_input.h +++ b/sys/net80211/ieee80211_input.h @@ -168,22 +168,19 @@ ieee80211_check_rxseq(struct ieee80211_node *ni, struct ieee80211_frame *wh) { #define SEQ_LEQ(a,b) ((int)((a)-(b)) <= 0) #define SEQ_EQ(a,b) ((int)((a)-(b)) == 0) +#define HAS_SEQ(type) ((type & 0x4) == 0) #define SEQNO(a) ((a) >> IEEE80211_SEQ_SEQ_SHIFT) #define FRAGNO(a) ((a) & IEEE80211_SEQ_FRAG_MASK) uint16_t rxseq; - uint8_t type, subtype; + uint8_t type; uint8_t tid; struct ieee80211_rx_ampdu *rap; rxseq = le16toh(*(uint16_t *)wh->i_seq); type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; - subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK; - /* - * Types with no sequence number (or QoS (+)Null frames) - * are always treated valid. - */ - if (! IEEE80211_HAS_SEQ(type, subtype)) + /* Types with no sequence number are always treated valid */ + if (! HAS_SEQ(type)) return 1; tid = ieee80211_gettid(wh); @@ -238,6 +235,7 @@ ieee80211_check_rxseq(struct ieee80211_node *ni, struct ieee80211_frame *wh) return 1; #undef SEQ_LEQ #undef SEQ_EQ +#undef HAS_SEQ #undef SEQNO #undef FRAGNO } diff --git a/sys/net80211/ieee80211_ioctl.c b/sys/net80211/ieee80211_ioctl.c index 2798d80..6b668cb 100644 --- a/sys/net80211/ieee80211_ioctl.c +++ b/sys/net80211/ieee80211_ioctl.c @@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$"); */ #include "opt_inet.h" +#include "opt_ipx.h" #include "opt_wlan.h" #include <sys/endian.h> @@ -43,7 +44,6 @@ __FBSDID("$FreeBSD$"); #include <sys/systm.h> #include <net/if.h> -#include <net/if_var.h> #include <net/if_dl.h> #include <net/if_media.h> #include <net/ethernet.h> @@ -53,6 +53,11 @@ __FBSDID("$FreeBSD$"); #include <netinet/if_ether.h> #endif +#ifdef IPX +#include <netipx/ipx.h> +#include <netipx/ipx_if.h> +#endif + #include <net80211/ieee80211_var.h> #include <net80211/ieee80211_ioctl.h> #include <net80211/ieee80211_regdomain.h> @@ -602,7 +607,7 @@ ieee80211_ioctl_getcurchan(struct ieee80211vap *vap, struct ieee80211req *ireq) * in use. When in RUN state report the vap-specific channel. * Otherwise return curchan. */ - if (vap->iv_state == IEEE80211_S_RUN || vap->iv_state == IEEE80211_S_SLEEP) + if (vap->iv_state == IEEE80211_S_RUN) c = vap->iv_bss->ni_chan; else c = ic->ic_curchan; @@ -920,7 +925,7 @@ ieee80211_ioctl_get80211(struct ieee80211vap *vap, u_long cmd, case IEEE80211_IOC_BSSID: if (ireq->i_len != IEEE80211_ADDR_LEN) return EINVAL; - if (vap->iv_state == IEEE80211_S_RUN || vap->iv_state == IEEE80211_S_SLEEP) { + if (vap->iv_state == IEEE80211_S_RUN) { error = copyout(vap->iv_opmode == IEEE80211_M_WDS ? vap->iv_bss->ni_macaddr : vap->iv_bss->ni_bssid, ireq->i_data, ireq->i_len); @@ -1026,7 +1031,7 @@ ieee80211_ioctl_get80211(struct ieee80211vap *vap, u_long cmd, case IEEE80211_IOC_AMPDU_LIMIT: if (vap->iv_opmode == IEEE80211_M_HOSTAP) ireq->i_val = vap->iv_ampdu_rxmax; - else if (vap->iv_state == IEEE80211_S_RUN || vap->iv_state == IEEE80211_S_SLEEP) + else if (vap->iv_state == IEEE80211_S_RUN) ireq->i_val = MS(vap->iv_bss->ni_htparam, IEEE80211_HTCAP_MAXRXAMPDU); else @@ -1034,7 +1039,7 @@ ieee80211_ioctl_get80211(struct ieee80211vap *vap, u_long cmd, break; case IEEE80211_IOC_AMPDU_DENSITY: if (vap->iv_opmode == IEEE80211_M_STA && - (vap->iv_state == IEEE80211_S_RUN || vap->iv_state == IEEE80211_S_SLEEP)) + vap->iv_state == IEEE80211_S_RUN) ireq->i_val = MS(vap->iv_bss->ni_htparam, IEEE80211_HTCAP_MPDUDENSITY); else @@ -1108,7 +1113,7 @@ ieee80211_ioctl_get80211(struct ieee80211vap *vap, u_long cmd, break; case IEEE80211_IOC_SMPS: if (vap->iv_opmode == IEEE80211_M_STA && - (vap->iv_state == IEEE80211_S_RUN || vap->iv_state == IEEE80211_S_SLEEP)) { + vap->iv_state == IEEE80211_S_RUN) { if (vap->iv_bss->ni_flags & IEEE80211_NODE_MIMO_RTS) ireq->i_val = IEEE80211_HTCAP_SMPS_DYNAMIC; else if (vap->iv_bss->ni_flags & IEEE80211_NODE_MIMO_PS) @@ -1120,7 +1125,7 @@ ieee80211_ioctl_get80211(struct ieee80211vap *vap, u_long cmd, break; case IEEE80211_IOC_RIFS: if (vap->iv_opmode == IEEE80211_M_STA && - (vap->iv_state == IEEE80211_S_RUN || vap->iv_state == IEEE80211_S_SLEEP)) + vap->iv_state == IEEE80211_S_RUN) ireq->i_val = (vap->iv_bss->ni_flags & IEEE80211_NODE_RIFS) != 0; else @@ -1949,7 +1954,7 @@ setcurchan(struct ieee80211vap *vap, struct ieee80211_channel *c) if (IEEE80211_IS_CHAN_NOADHOC(c)) return EINVAL; } - if ((vap->iv_state == IEEE80211_S_RUN || vap->iv_state == IEEE80211_S_SLEEP) && + if (vap->iv_state == IEEE80211_S_RUN && vap->iv_bss->ni_chan == c) return 0; /* NB: nothing to do */ } @@ -3414,6 +3419,24 @@ ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) arp_ifinit(ifp, ifa); break; #endif +#ifdef IPX + /* + * XXX - This code is probably wrong, + * but has been copied many times. + */ + case AF_IPX: { + struct ipx_addr *ina = &(IA_SIPX(ifa)->sipx_addr); + + if (ipx_nullhost(*ina)) + ina->x_host = *(union ipx_host *) + IF_LLADDR(ifp); + else + bcopy((caddr_t) ina->x_host.c_host, + (caddr_t) IF_LLADDR(ifp), + ETHER_ADDR_LEN); + /* fall thru... */ + } +#endif default: if ((ifp->if_flags & IFF_UP) == 0) { ifp->if_flags |= IFF_UP; diff --git a/sys/net80211/ieee80211_mesh.c b/sys/net80211/ieee80211_mesh.c index 24969a2..a06b241 100644 --- a/sys/net80211/ieee80211_mesh.c +++ b/sys/net80211/ieee80211_mesh.c @@ -54,7 +54,6 @@ __FBSDID("$FreeBSD$"); #include <net/bpf.h> #include <net/if.h> -#include <net/if_var.h> #include <net/if_media.h> #include <net/if_llc.h> #include <net/ethernet.h> @@ -1047,7 +1046,7 @@ mesh_transmit_to_gate(struct ieee80211vap *vap, struct mbuf *m, ni = ieee80211_mesh_find_txnode(vap, rt_gate->rt_dest); if (ni == NULL) { - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; m_freem(m); return; } @@ -1183,7 +1182,7 @@ mesh_forward(struct ieee80211vap *vap, struct mbuf *m, IEEE80211_NOTE_FRAME(vap, IEEE80211_MSG_MESH, wh, "%s", "frame not fwd'd, cannot dup"); vap->iv_stats.is_mesh_fwd_nobuf++; - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; return; } mcopy = m_pullup(mcopy, ieee80211_hdrspace(ic, wh) + @@ -1192,7 +1191,7 @@ mesh_forward(struct ieee80211vap *vap, struct mbuf *m, IEEE80211_NOTE_FRAME(vap, IEEE80211_MSG_MESH, wh, "%s", "frame not fwd'd, too short"); vap->iv_stats.is_mesh_fwd_tooshort++; - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; m_freem(mcopy); return; } @@ -1250,7 +1249,7 @@ mesh_forward(struct ieee80211vap *vap, struct mbuf *m, /* NB: IFQ_HANDOFF reclaims mbuf */ ieee80211_free_node(ni); } else { - if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); + ifp->if_opackets++; } } @@ -1844,7 +1843,7 @@ mesh_input(struct ieee80211_node *ni, struct mbuf *m, int rssi, int nf) break; } err: - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + ifp->if_ierrors++; out: if (m != NULL) { if (need_tap && ieee80211_radiotap_active_vap(vap)) @@ -1906,7 +1905,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, &scan, wh, subtype, rssi, nf); return; } @@ -2693,7 +2692,7 @@ mesh_send_action(struct ieee80211_node *ni, return EIO; /* XXX */ } - M_PREPEND(m, sizeof(struct ieee80211_frame), M_NOWAIT); + M_PREPEND(m, sizeof(struct ieee80211_frame), M_DONTWAIT); if (m == NULL) { ieee80211_free_node(ni); return ENOMEM; @@ -3334,7 +3333,7 @@ mesh_airtime_calc(struct ieee80211_node *ni) /* Error rate in percentage */ /* XXX assuming small failures are ok */ errrate = (((ifp->if_oerrors + - ifp->if_ierrors) / 100) << M_BITS) / 100; + ifp->if_ierrors) / 100) << M_BITS) / 100; res = (overhead + (nbits / rate)) * ((1 << S_FACTOR) / ((1 << M_BITS) - errrate)); diff --git a/sys/net80211/ieee80211_monitor.c b/sys/net80211/ieee80211_monitor.c index 8909339..e324081 100644 --- a/sys/net80211/ieee80211_monitor.c +++ b/sys/net80211/ieee80211_monitor.c @@ -48,7 +48,6 @@ __FBSDID("$FreeBSD$"); #include <sys/sysctl.h> #include <net/if.h> -#include <net/if_var.h> #include <net/if_media.h> #include <net/if_llc.h> #include <net/ethernet.h> @@ -130,7 +129,7 @@ monitor_input(struct ieee80211_node *ni, struct mbuf *m, int rssi, int nf) struct ieee80211vap *vap = ni->ni_vap; struct ifnet *ifp = vap->iv_ifp; - if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1); + ifp->if_ipackets++; if (ieee80211_radiotap_active_vap(vap)) ieee80211_radiotap_rx(vap, m); diff --git a/sys/net80211/ieee80211_node.c b/sys/net80211/ieee80211_node.c index c84f9a8..4169255 100644 --- a/sys/net80211/ieee80211_node.c +++ b/sys/net80211/ieee80211_node.c @@ -38,7 +38,6 @@ __FBSDID("$FreeBSD$"); #include <sys/socket.h> #include <net/if.h> -#include <net/if_var.h> #include <net/if_media.h> #include <net/ethernet.h> @@ -93,8 +92,6 @@ static void node_getmimoinfo(const struct ieee80211_node *, static void _ieee80211_free_node(struct ieee80211_node *); -static void node_reclaim(struct ieee80211_node_table *nt, - struct ieee80211_node *ni); static void ieee80211_node_table_init(struct ieee80211com *ic, struct ieee80211_node_table *nt, const char *name, int inact, int keymaxix); @@ -721,15 +718,9 @@ ieee80211_sta_join1(struct ieee80211_node *selbs) IEEE80211_ADDR_EQ(obss->ni_macaddr, selbs->ni_macaddr)); vap->iv_bss = selbs; /* NB: caller assumed to bump refcnt */ if (obss != NULL) { - struct ieee80211_node_table *nt = obss->ni_table; - copy_bss(selbs, obss); ieee80211_node_decref(obss); /* iv_bss reference */ - - IEEE80211_NODE_LOCK(nt); - node_reclaim(nt, obss); /* station table reference */ - IEEE80211_NODE_UNLOCK(nt); - + ieee80211_free_node(obss); /* station table reference */ obss = NULL; /* NB: guard against later use */ } @@ -879,7 +870,7 @@ ieee80211_sta_leave(struct ieee80211_node *ni) void ieee80211_node_deauth(struct ieee80211_node *ni, int reason) { - /* NB: bump the refcnt to be sure temporary nodes are not reclaimed */ + /* NB: bump the refcnt to be sure temporay nodes are not reclaimed */ ieee80211_ref_node(ni); if (ni->ni_associd != 0) IEEE80211_SEND_MGMT(ni, IEEE80211_FC0_SUBTYPE_DEAUTH, reason); @@ -1757,28 +1748,6 @@ _ieee80211_free_node(struct ieee80211_node *ni) ni->ni_ic->ic_node_free(ni); } -/* - * Clear any entry in the unicast key mapping table. - */ -static int -node_clear_keyixmap(struct ieee80211_node_table *nt, struct ieee80211_node *ni) -{ - ieee80211_keyix keyix; - - keyix = ni->ni_ucastkey.wk_rxkeyix; - if (nt->nt_keyixmap != NULL && keyix < nt->nt_keyixmax && - nt->nt_keyixmap[keyix] == ni) { - IEEE80211_DPRINTF(ni->ni_vap, IEEE80211_MSG_NODE, - "%s: %p<%s> clear key map entry %u\n", - __func__, ni, ether_sprintf(ni->ni_macaddr), keyix); - nt->nt_keyixmap[keyix] = NULL; - ieee80211_node_decref(ni); - return 1; - } - - return 0; -} - void #ifdef IEEE80211_DEBUG_REFCNT ieee80211_free_node_debug(struct ieee80211_node *ni, const char *func, int line) @@ -1800,9 +1769,24 @@ ieee80211_free_node(struct ieee80211_node *ni) * Last reference, reclaim state. */ _ieee80211_free_node(ni); - } else if (ieee80211_node_refcnt(ni) == 1) - if (node_clear_keyixmap(nt, ni)) + } else if (ieee80211_node_refcnt(ni) == 1 && + nt->nt_keyixmap != NULL) { + ieee80211_keyix keyix; + /* + * Check for a last reference in the key mapping table. + */ + keyix = ni->ni_ucastkey.wk_rxkeyix; + if (keyix < nt->nt_keyixmax && + nt->nt_keyixmap[keyix] == ni) { + IEEE80211_DPRINTF(ni->ni_vap, + IEEE80211_MSG_NODE, + "%s: %p<%s> clear key map entry", __func__, + ni, ether_sprintf(ni->ni_macaddr)); + nt->nt_keyixmap[keyix] = NULL; + ieee80211_node_decref(ni); /* XXX needed? */ _ieee80211_free_node(ni); + } + } IEEE80211_NODE_UNLOCK(nt); } else { if (ieee80211_node_dectestref(ni)) @@ -1870,6 +1854,7 @@ ieee80211_node_delucastkey(struct ieee80211_node *ni) static void node_reclaim(struct ieee80211_node_table *nt, struct ieee80211_node *ni) { + ieee80211_keyix keyix; IEEE80211_NODE_LOCK_ASSERT(nt); @@ -1884,7 +1869,15 @@ node_reclaim(struct ieee80211_node_table *nt, struct ieee80211_node *ni) * table. We cannot depend on the mapping table entry * being cleared because the node may not be free'd. */ - (void)node_clear_keyixmap(nt, ni); + keyix = ni->ni_ucastkey.wk_rxkeyix; + if (nt->nt_keyixmap != NULL && keyix < nt->nt_keyixmax && + nt->nt_keyixmap[keyix] == ni) { + IEEE80211_DPRINTF(ni->ni_vap, IEEE80211_MSG_NODE, + "%s: %p<%s> clear key map entry %u\n", + __func__, ni, ether_sprintf(ni->ni_macaddr), keyix); + nt->nt_keyixmap[keyix] = NULL; + ieee80211_node_decref(ni); /* NB: don't need free */ + } if (!ieee80211_node_dectestref(ni)) { /* * Other references are present, just remove the diff --git a/sys/net80211/ieee80211_output.c b/sys/net80211/ieee80211_output.c index 2158bee..9247e0e 100644 --- a/sys/net80211/ieee80211_output.c +++ b/sys/net80211/ieee80211_output.c @@ -42,7 +42,6 @@ __FBSDID("$FreeBSD$"); #include <net/bpf.h> #include <net/ethernet.h> #include <net/if.h> -#include <net/if_var.h> #include <net/if_llc.h> #include <net/if_media.h> #include <net/if_vlan_var.h> @@ -158,7 +157,7 @@ ieee80211_vap_pkt_send_dest(struct ieee80211vap *vap, struct mbuf *m, ni->ni_macaddr, NULL, "%s", "classification failure"); vap->iv_stats.is_tx_classify++; - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; m_freem(m); ieee80211_free_node(ni); @@ -255,7 +254,7 @@ ieee80211_vap_pkt_send_dest(struct ieee80211vap *vap, struct mbuf *m, ieee80211_free_node(ni); if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); } else { - if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); + ifp->if_opackets++; if_inc_counter(ifp, IFCOUNTER_OMCASTS, mcast); if_inc_counter(ifp, IFCOUNTER_OBYTES, len); } @@ -305,7 +304,7 @@ ieee80211_start_pkt(struct ieee80211vap *vap, struct mbuf *m) IEEE80211_DPRINTF(vap, IEEE80211_MSG_OUTPUT, "discard frame, %s\n", "m_pullup failed"); vap->iv_stats.is_tx_nobuf++; /* XXX */ - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; return (ENOBUFS); } eh = mtod(m, struct ether_header *); @@ -339,7 +338,7 @@ ieee80211_start_pkt(struct ieee80211vap *vap, struct mbuf *m) ni = ieee80211_find_txnode(vap, eh->ether_dhost); if (ni == NULL) { /* NB: ieee80211_find_txnode does stat+msg */ - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; m_freem(m); /* XXX better status? */ return (ENOBUFS); @@ -351,7 +350,7 @@ ieee80211_start_pkt(struct ieee80211vap *vap, struct mbuf *m) "sta not associated (type 0x%04x)", htons(eh->ether_type)); vap->iv_stats.is_tx_notassoc++; - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; m_freem(m); ieee80211_free_node(ni); /* XXX better status? */ @@ -370,7 +369,7 @@ ieee80211_start_pkt(struct ieee80211vap *vap, struct mbuf *m) eh->ether_dhost, NULL, "%s", "proxy not enabled"); vap->iv_stats.is_mesh_notproxy++; - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; m_freem(m); /* XXX better status? */ return (ENOBUFS); @@ -387,7 +386,7 @@ ieee80211_start_pkt(struct ieee80211vap *vap, struct mbuf *m) * NB: ieee80211_mesh_discover holds/disposes * frame (e.g. queueing on path discovery). */ - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; /* XXX better status? */ return (ENOBUFS); } @@ -397,20 +396,6 @@ ieee80211_start_pkt(struct ieee80211vap *vap, struct mbuf *m) /* * We've resolved the sender, so attempt to transmit it. */ - - if (vap->iv_state == IEEE80211_S_SLEEP) { - /* - * In power save; queue frame and then wakeup device - * for transmit. - */ - ic->ic_lastdata = ticks; - if (ieee80211_pwrsave(ni, m) != 0) - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); - ieee80211_free_node(ni); - ieee80211_new_state(vap, IEEE80211_S_RUN, 0); - return (0); - } - if (ieee80211_vap_pkt_send_dest(vap, m, ni) != 0) return (ENOBUFS); return (0); @@ -441,19 +426,24 @@ ieee80211_vap_transmit(struct ifnet *ifp, struct mbuf *m) if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); return (ENETDOWN); } - + if (vap->iv_state == IEEE80211_S_SLEEP) { + /* + * In power save, wakeup device for transmit. + */ + ieee80211_new_state(vap, IEEE80211_S_RUN, 0); + m_freem(m); + return (0); + } /* * No data frames go out unless we're running. * Note in particular this covers CAC and CSA * states (though maybe we should check muting * for CSA). */ - if (vap->iv_state != IEEE80211_S_RUN && - vap->iv_state != IEEE80211_S_SLEEP) { + if (vap->iv_state != IEEE80211_S_RUN) { IEEE80211_LOCK(ic); /* re-check under the com lock to avoid races */ - if (vap->iv_state != IEEE80211_S_RUN && - vap->iv_state != IEEE80211_S_SLEEP) { + if (vap->iv_state != IEEE80211_S_RUN) { IEEE80211_DPRINTF(vap, IEEE80211_MSG_OUTPUT, "%s: ignore queue, in %s state\n", __func__, ieee80211_state_name[vap->iv_state]); @@ -494,13 +484,6 @@ ieee80211_vap_qflush(struct ifnet *ifp) /* * 802.11 raw output routine. - * - * XXX TODO: this (and other send routines) should correctly - * XXX keep the pwr mgmt bit set if it decides to call into the - * XXX driver to send a frame whilst the state is SLEEP. - * - * Otherwise the peer may decide that we're awake and flood us - * with traffic we are still too asleep to receive! */ int ieee80211_raw_output(struct ieee80211vap *vap, struct ieee80211_node *ni, @@ -617,7 +600,7 @@ ieee80211_output(struct ifnet *ifp, struct mbuf *m, if (ieee80211_classify(ni, m)) senderr(EIO); /* XXX */ - if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); + ifp->if_opackets++; IEEE80211_NODE_STAT(ni, tx_data); if (IEEE80211_IS_MULTICAST(wh->i_addr1)) { IEEE80211_NODE_STAT(ni, tx_mcast); @@ -645,7 +628,7 @@ bad: m_freem(m); if (ni != NULL) ieee80211_free_node(ni); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; return error; #undef senderr } @@ -739,12 +722,7 @@ ieee80211_send_setup( if (tid != IEEE80211_NONQOS_TID && IEEE80211_AMPDU_RUNNING(tap)) m->m_flags |= M_AMPDU_MPDU; else { - if (IEEE80211_HAS_SEQ(type & IEEE80211_FC0_TYPE_MASK, - type & IEEE80211_FC0_SUBTYPE_MASK)) - seqno = ni->ni_txseqs[tid]++; - else - seqno = 0; - + seqno = ni->ni_txseqs[tid]++; *(uint16_t *)&wh->i_seq[0] = htole16(seqno << IEEE80211_SEQ_SEQ_SHIFT); M_SEQNO_SET(m, seqno); @@ -1716,7 +1694,7 @@ ieee80211_add_xrates(uint8_t *frm, const struct ieee80211_rateset *rs) /* * Add an ssid element to a frame. */ -uint8_t * +static uint8_t * ieee80211_add_ssid(uint8_t *frm, const uint8_t *ssid, u_int len) { *frm++ = IEEE80211_ELEMID_SSID; @@ -2336,33 +2314,18 @@ ieee80211_send_mgmt(struct ieee80211_node *ni, int type, int arg) ic->ic_curchan); frm = ieee80211_add_supportedchannels(frm, ic); } - - /* - * Check the channel - we may be using an 11n NIC with an - * 11n capable station, but we're configured to be an 11b - * channel. - */ if ((vap->iv_flags_ht & IEEE80211_FHT_HT) && - IEEE80211_IS_CHAN_HT(ni->ni_chan) && ni->ni_ies.htcap_ie != NULL && - ni->ni_ies.htcap_ie[0] == IEEE80211_ELEMID_HTCAP) { + ni->ni_ies.htcap_ie[0] == IEEE80211_ELEMID_HTCAP) frm = ieee80211_add_htcap(frm, ni); - } frm = ieee80211_add_wpa(frm, vap); if ((ic->ic_flags & IEEE80211_F_WME) && ni->ni_ies.wme_ie != NULL) frm = ieee80211_add_wme_info(frm, &ic->ic_wme); - - /* - * Same deal - only send HT info if we're on an 11n - * capable channel. - */ if ((vap->iv_flags_ht & IEEE80211_FHT_HT) && - IEEE80211_IS_CHAN_HT(ni->ni_chan) && ni->ni_ies.htcap_ie != NULL && - ni->ni_ies.htcap_ie[0] == IEEE80211_ELEMID_VENDOR) { + ni->ni_ies.htcap_ie[0] == IEEE80211_ELEMID_VENDOR) frm = ieee80211_add_htcap_vendor(frm, ni); - } #ifdef IEEE80211_SUPPORT_SUPERG if (IEEE80211_ATH_CAP(vap, ni, IEEE80211_F_ATHEROS)) { frm = ieee80211_add_ath(frm, diff --git a/sys/net80211/ieee80211_phy.c b/sys/net80211/ieee80211_phy.c index 4242ac0..923266c 100644 --- a/sys/net80211/ieee80211_phy.c +++ b/sys/net80211/ieee80211_phy.c @@ -35,16 +35,12 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> #include <sys/kernel.h> #include <sys/systm.h> -#include <sys/malloc.h> #include <sys/socket.h> #include <net/if.h> #include <net/if_media.h> -#include <net/ethernet.h> -#include <net/route.h> - #include <net80211/ieee80211_var.h> #include <net80211/ieee80211_phy.h> diff --git a/sys/net80211/ieee80211_power.c b/sys/net80211/ieee80211_power.c index 812cd70..4542ec5 100644 --- a/sys/net80211/ieee80211_power.c +++ b/sys/net80211/ieee80211_power.c @@ -38,7 +38,6 @@ __FBSDID("$FreeBSD$"); #include <sys/socket.h> #include <net/if.h> -#include <net/if_var.h> #include <net/if_media.h> #include <net/ethernet.h> @@ -555,108 +554,3 @@ ieee80211_sta_pwrsave(struct ieee80211vap *vap, int enable) ieee80211_send_nulldata(ieee80211_ref_node(ni)); } } - -/* - * Handle being notified that we have data available for us in a TIM/ATIM. - * - * This may schedule a transition from _SLEEP -> _RUN if it's appropriate. - * - * In STA mode, we may have put to sleep during scan and need to be dragged - * back out of powersave mode. - */ -void -ieee80211_sta_tim_notify(struct ieee80211vap *vap, int set) -{ - struct ieee80211com *ic = vap->iv_ic; - - /* - * Schedule the driver state change. It'll happen at some point soon. - * Since the hardware shouldn't know that we're running just yet - * (and thus tell the peer that we're awake before we actually wake - * up said hardware), we leave the actual node state transition - * up to the transition to RUN. - * - * XXX TODO: verify that the transition to RUN will wake up the - * BSS node! - */ - IEEE80211_LOCK(vap->iv_ic); - if (set == 1 && vap->iv_state == IEEE80211_S_SLEEP) { - ieee80211_new_state_locked(vap, IEEE80211_S_RUN, 0); - IEEE80211_DPRINTF(vap, IEEE80211_MSG_POWER, - "%s: TIM=%d; wakeup\n", __func__, set); - } else if ((set == 1) && (ic->ic_flags_ext & IEEE80211_FEXT_BGSCAN)) { - /* - * XXX only do this if we're in RUN state? - */ - IEEE80211_DPRINTF(vap, IEEE80211_MSG_POWER, - "%s: wake up from bgscan vap sleep\n", - __func__); - /* - * We may be in BGSCAN mode - this means the VAP is is in STA - * mode powersave. If it is, we need to wake it up so we - * can process outbound traffic. - */ - vap->iv_sta_ps(vap, 0); - } - IEEE80211_UNLOCK(vap->iv_ic); -} - -/* - * Timer check on whether the VAP has had any transmit activity. - * - * This may schedule a transition from _RUN -> _SLEEP if it's appropriate. - */ -void -ieee80211_sta_ps_timer_check(struct ieee80211vap *vap) -{ - struct ieee80211com *ic = vap->iv_ic; - - /* XXX lock assert */ - - /* For no, only do this in STA mode */ - if (! (vap->iv_caps & IEEE80211_C_SWSLEEP)) - goto out; - - if (vap->iv_opmode != IEEE80211_M_STA) - goto out; - - /* If we're not at run state, bail */ - if (vap->iv_state != IEEE80211_S_RUN) - goto out; - - IEEE80211_DPRINTF(vap, IEEE80211_MSG_POWER, - "%s: lastdata=%llu, ticks=%llu\n", - __func__, (unsigned long long) ic->ic_lastdata, - (unsigned long long) ticks); - - /* If powersave is disabled on the VAP, don't bother */ - if (! (vap->iv_flags & IEEE80211_F_PMGTON)) - goto out; - - /* If we've done any data within our idle interval, bail */ - /* XXX hard-coded to one second for now, ew! */ - if (time_after(ic->ic_lastdata + 500, ticks)) - goto out; - - /* - * Signify we're going into power save and transition the - * node to powersave. - */ - if ((vap->iv_bss->ni_flags & IEEE80211_NODE_PWR_MGT) == 0) - vap->iv_sta_ps(vap, 1); - - /* - * XXX The driver has to handle the fact that we're going - * to sleep but frames may still be transmitted; - * hopefully it and/or us will do the right thing and mark any - * transmitted frames with PWRMGT set to 1. - */ - ieee80211_new_state_locked(vap, IEEE80211_S_SLEEP, 0); - - IEEE80211_DPRINTF(vap, IEEE80211_MSG_POWER, - "%s: time delta=%d msec\n", __func__, - (int) ticks_to_msecs(ticks - ic->ic_lastdata)); - -out: - return; -} diff --git a/sys/net80211/ieee80211_power.h b/sys/net80211/ieee80211_power.h index d9bbaa5..55270d2 100644 --- a/sys/net80211/ieee80211_power.h +++ b/sys/net80211/ieee80211_power.h @@ -79,9 +79,6 @@ int ieee80211_node_psq_age(struct ieee80211_node *); int ieee80211_pwrsave(struct ieee80211_node *, struct mbuf *); void ieee80211_node_pwrsave(struct ieee80211_node *, int enable); void ieee80211_sta_pwrsave(struct ieee80211vap *, int enable); -void ieee80211_sta_tim_notify(struct ieee80211vap *vap, int set); -void ieee80211_sta_ps_timer_check(struct ieee80211vap *vap); -/* XXX what's this? */ void ieee80211_power_poll(struct ieee80211com *); #endif /* _NET80211_IEEE80211_POWER_H_ */ diff --git a/sys/net80211/ieee80211_proto.c b/sys/net80211/ieee80211_proto.c index 2f84769..6f75130 100644 --- a/sys/net80211/ieee80211_proto.c +++ b/sys/net80211/ieee80211_proto.c @@ -42,7 +42,6 @@ __FBSDID("$FreeBSD$"); #include <sys/sockio.h> #include <net/if.h> -#include <net/if_var.h> #include <net/if_media.h> #include <net/ethernet.h> /* XXX for ether_sprintf */ diff --git a/sys/net80211/ieee80211_proto.h b/sys/net80211/ieee80211_proto.h index 3b46ac4..8df5116 100644 --- a/sys/net80211/ieee80211_proto.h +++ b/sys/net80211/ieee80211_proto.h @@ -149,7 +149,6 @@ struct mbuf *ieee80211_alloc_cts(struct ieee80211com *, uint8_t *ieee80211_add_rates(uint8_t *, const struct ieee80211_rateset *); uint8_t *ieee80211_add_xrates(uint8_t *, const struct ieee80211_rateset *); -uint8_t *ieee80211_add_ssid(uint8_t *, const uint8_t *, u_int); uint8_t *ieee80211_add_wpa(uint8_t *, const struct ieee80211vap *); uint8_t *ieee80211_add_rsn(uint8_t *, const struct ieee80211vap *); uint8_t *ieee80211_add_qos(uint8_t *, const struct ieee80211_node *); diff --git a/sys/net80211/ieee80211_radiotap.c b/sys/net80211/ieee80211_radiotap.c index 5638f52..f06f7e0 100644 --- a/sys/net80211/ieee80211_radiotap.c +++ b/sys/net80211/ieee80211_radiotap.c @@ -42,10 +42,8 @@ __FBSDID("$FreeBSD$"); #include <net/bpf.h> #include <net/if.h> -#include <net/if_var.h> #include <net/if_llc.h> #include <net/if_media.h> -#include <net/ethernet.h> #include <net80211/ieee80211_var.h> diff --git a/sys/net80211/ieee80211_ratectl.c b/sys/net80211/ieee80211_ratectl.c index 3eff898..0ad46bd3 100644 --- a/sys/net80211/ieee80211_ratectl.c +++ b/sys/net80211/ieee80211_ratectl.c @@ -30,12 +30,9 @@ __FBSDID("$FreeBSD$"); #include <sys/kernel.h> #include <sys/systm.h> #include <sys/socket.h> -#include <sys/malloc.h> #include <net/if.h> #include <net/if_media.h> -#include <net/ethernet.h> -#include <net/route.h> #include <net80211/ieee80211_var.h> #include <net80211/ieee80211_ratectl.h> diff --git a/sys/net80211/ieee80211_ratectl.h b/sys/net80211/ieee80211_ratectl.h index 5603509..be81781 100644 --- a/sys/net80211/ieee80211_ratectl.h +++ b/sys/net80211/ieee80211_ratectl.h @@ -62,13 +62,13 @@ void ieee80211_ratectl_set(struct ieee80211vap *, int); MALLOC_DECLARE(M_80211_RATECTL); -static __inline void +static void __inline ieee80211_ratectl_deinit(struct ieee80211vap *vap) { vap->iv_rate->ir_deinit(vap); } -static __inline void +static void __inline ieee80211_ratectl_node_init(struct ieee80211_node *ni) { const struct ieee80211vap *vap = ni->ni_vap; @@ -76,7 +76,7 @@ ieee80211_ratectl_node_init(struct ieee80211_node *ni) vap->iv_rate->ir_node_init(ni); } -static __inline void +static void __inline ieee80211_ratectl_node_deinit(struct ieee80211_node *ni) { const struct ieee80211vap *vap = ni->ni_vap; @@ -92,14 +92,14 @@ ieee80211_ratectl_rate(struct ieee80211_node *ni, void *arg, uint32_t iarg) return vap->iv_rate->ir_rate(ni, arg, iarg); } -static __inline void +static void __inline ieee80211_ratectl_tx_complete(const struct ieee80211vap *vap, const struct ieee80211_node *ni, int status, void *arg1, void *arg2) { vap->iv_rate->ir_tx_complete(vap, ni, status, arg1, arg2); } -static __inline void +static void __inline ieee80211_ratectl_tx_update(const struct ieee80211vap *vap, const struct ieee80211_node *ni, void *arg1, void *arg2, void *arg3) { @@ -108,7 +108,7 @@ ieee80211_ratectl_tx_update(const struct ieee80211vap *vap, vap->iv_rate->ir_tx_update(vap, ni, arg1, arg2, arg3); } -static __inline void +static void __inline ieee80211_ratectl_setinterval(const struct ieee80211vap *vap, int msecs) { if (vap->iv_rate->ir_setinterval == NULL) diff --git a/sys/net80211/ieee80211_ratectl_none.c b/sys/net80211/ieee80211_ratectl_none.c index a0056f3..0edec44 100644 --- a/sys/net80211/ieee80211_ratectl_none.c +++ b/sys/net80211/ieee80211_ratectl_none.c @@ -29,16 +29,13 @@ __FBSDID("$FreeBSD$"); #include "opt_wlan.h" #include <sys/param.h> -#include <sys/systm.h> #include <sys/kernel.h> -#include <sys/malloc.h> #include <sys/module.h> #include <sys/socket.h> #include <sys/sysctl.h> #include <net/if.h> #include <net/if_media.h> -#include <net/ethernet.h> #ifdef INET #include <netinet/in.h> diff --git a/sys/net80211/ieee80211_regdomain.c b/sys/net80211/ieee80211_regdomain.c index ed7f422..6bc5e0d 100644 --- a/sys/net80211/ieee80211_regdomain.c +++ b/sys/net80211/ieee80211_regdomain.c @@ -34,14 +34,11 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> -#include <sys/malloc.h> #include <sys/socket.h> #include <net/if.h> -#include <net/if_var.h> #include <net/if_media.h> -#include <net/ethernet.h> #include <net80211/ieee80211_var.h> #include <net80211/ieee80211_regdomain.h> diff --git a/sys/net80211/ieee80211_rssadapt.c b/sys/net80211/ieee80211_rssadapt.c index f230f60..aaf4057 100644 --- a/sys/net80211/ieee80211_rssadapt.c +++ b/sys/net80211/ieee80211_rssadapt.c @@ -33,17 +33,13 @@ #include "opt_wlan.h" #include <sys/param.h> -#include <sys/systm.h> #include <sys/kernel.h> -#include <sys/malloc.h> #include <sys/module.h> #include <sys/socket.h> #include <sys/sysctl.h> #include <net/if.h> -#include <net/if_var.h> #include <net/if_media.h> -#include <net/ethernet.h> #include <net80211/ieee80211_var.h> #include <net80211/ieee80211_rssadapt.h> diff --git a/sys/net80211/ieee80211_scan.c b/sys/net80211/ieee80211_scan.c index 6c950d6..3a8c24d 100644 --- a/sys/net80211/ieee80211_scan.c +++ b/sys/net80211/ieee80211_scan.c @@ -40,17 +40,41 @@ __FBSDID("$FreeBSD$"); #include <sys/socket.h> #include <net/if.h> -#include <net/if_var.h> #include <net/if_media.h> #include <net/ethernet.h> #include <net80211/ieee80211_var.h> -/* XXX until it's implemented as attach ops */ -#include <net80211/ieee80211_scan_sw.h> - #include <net/bpf.h> +struct scan_state { + struct ieee80211_scan_state base; /* public state */ + + u_int ss_iflags; /* flags used internally */ +#define ISCAN_MINDWELL 0x0001 /* min dwell time reached */ +#define ISCAN_DISCARD 0x0002 /* discard rx'd frames */ +#define ISCAN_CANCEL 0x0004 /* cancel current scan */ +#define ISCAN_ABORT 0x0008 /* end the scan immediately */ + unsigned long ss_chanmindwell; /* min dwell on curchan */ + unsigned long ss_scanend; /* time scan must stop */ + u_int ss_duration; /* duration for next scan */ + struct task ss_scan_task; /* scan execution */ + struct cv ss_scan_cv; /* scan signal */ + struct callout ss_scan_timer; /* scan timer */ +}; +#define SCAN_PRIVATE(ss) ((struct scan_state *) ss) + +/* + * Amount of time to go off-channel during a background + * scan. This value should be large enough to catch most + * ap's but short enough that we can return on-channel + * before our listen interval expires. + * + * XXX tunable + * XXX check against configured listen interval + */ +#define IEEE80211_SCAN_OFFCHANNEL msecs_to_ticks(150) + /* * Roaming-related defaults. RSSI thresholds are as returned by the * driver (.5dBm). Transmit rate thresholds are IEEE rate codes (i.e @@ -68,32 +92,55 @@ __FBSDID("$FreeBSD$"); #define ROAM_RATE_QUARTER_DEFAULT 2*3 /* quarter-width 11a/g bss */ #define ROAM_MCS_11N_DEFAULT (1 | IEEE80211_RATE_MCS) /* 11n bss */ +static void scan_curchan(struct ieee80211_scan_state *, unsigned long); +static void scan_mindwell(struct ieee80211_scan_state *); +static void scan_signal(void *); +static void scan_task(void *, int); + +MALLOC_DEFINE(M_80211_SCAN, "80211scan", "802.11 scan state"); + void ieee80211_scan_attach(struct ieee80211com *ic) { + struct scan_state *ss; - /* - * For now, the swscan module does both the - * allocation (so it can pad it) and sets up the net80211 - * bits. - * - * I'll split this stuff later. - */ - ieee80211_swscan_attach(ic); + ss = (struct scan_state *) malloc(sizeof(struct scan_state), + M_80211_SCAN, M_NOWAIT | M_ZERO); + if (ss == NULL) { + ic->ic_scan = NULL; + return; + } + callout_init_mtx(&ss->ss_scan_timer, IEEE80211_LOCK_OBJ(ic), 0); + cv_init(&ss->ss_scan_cv, "scan"); + TASK_INIT(&ss->ss_scan_task, 0, scan_task, ss); + ic->ic_scan = &ss->base; + ss->base.ss_ic = ic; + + ic->ic_scan_curchan = scan_curchan; + ic->ic_scan_mindwell = scan_mindwell; } void ieee80211_scan_detach(struct ieee80211com *ic) { + struct ieee80211_scan_state *ss = ic->ic_scan; - /* - * Ideally we'd do the ss_ops detach call here; - * but then ieee80211_swscan_detach would need - * to be split in two. - * - * I'll do that later. - */ - ieee80211_swscan_detach(ic); + if (ss != NULL) { + IEEE80211_LOCK(ic); + SCAN_PRIVATE(ss)->ss_iflags |= ISCAN_ABORT; + scan_signal(ss); + IEEE80211_UNLOCK(ic); + ieee80211_draintask(ic, &SCAN_PRIVATE(ss)->ss_scan_task); + callout_drain(&SCAN_PRIVATE(ss)->ss_scan_timer); + KASSERT((ic->ic_flags & IEEE80211_F_SCAN) == 0, + ("scan still running")); + if (ss->ss_ops != NULL) { + ss->ss_ops->scan_detach(ss); + ss->ss_ops = NULL; + } + ic->ic_scan = NULL; + free(SCAN_PRIVATE(ss), M_80211_SCAN); + } } static const struct ieee80211_roamparam defroam[IEEE80211_MODE_MAX] = { @@ -128,8 +175,6 @@ ieee80211_scan_vattach(struct ieee80211vap *vap) vap->iv_roaming = IEEE80211_ROAMING_AUTO; memcpy(vap->iv_roamparms, defroam, sizeof(defroam)); - - ieee80211_swscan_vattach(vap); } void @@ -140,10 +185,11 @@ ieee80211_scan_vdetach(struct ieee80211vap *vap) IEEE80211_LOCK(ic); ss = ic->ic_scan; - - ieee80211_swscan_vdetach(vap); - if (ss != NULL && ss->ss_vap == vap) { + if (ic->ic_flags & IEEE80211_F_SCAN) { + SCAN_PRIVATE(ss)->ss_iflags |= ISCAN_ABORT; + scan_signal(ss); + } if (ss->ss_ops != NULL) { ss->ss_ops->scan_detach(ss); ss->ss_ops = NULL; @@ -214,8 +260,8 @@ ieee80211_scanner_unregister_all(const struct ieee80211_scanner *scan) * ensure later callbacks find ss_ops set to properly * reflect current operating mode. */ -void -ieee80211_scan_update_locked(struct ieee80211vap *vap, +static void +scan_update_locked(struct ieee80211vap *vap, const struct ieee80211_scanner *scan) { struct ieee80211com *ic = vap->iv_ic; @@ -260,6 +306,26 @@ ieee80211_scan_update_locked(struct ieee80211vap *vap, } } +static char +channel_type(const struct ieee80211_channel *c) +{ + if (IEEE80211_IS_CHAN_ST(c)) + return 'S'; + if (IEEE80211_IS_CHAN_108A(c)) + return 'T'; + if (IEEE80211_IS_CHAN_108G(c)) + return 'G'; + if (IEEE80211_IS_CHAN_HT(c)) + return 'n'; + if (IEEE80211_IS_CHAN_A(c)) + return 'a'; + if (IEEE80211_IS_CHAN_ANYG(c)) + return 'g'; + if (IEEE80211_IS_CHAN_B(c)) + return 'b'; + return 'f'; +} + void ieee80211_scan_dump_channels(const struct ieee80211_scan_state *ss) { @@ -272,14 +338,14 @@ ieee80211_scan_dump_channels(const struct ieee80211_scan_state *ss) const struct ieee80211_channel *c = ss->ss_chans[i]; printf("%s%u%c", sep, ieee80211_chan2ieee(ic, c), - ieee80211_channel_type_char(c)); + channel_type(c)); sep = ", "; } } #ifdef IEEE80211_DEBUG -void -ieee80211_scan_dump(struct ieee80211_scan_state *ss) +static void +scan_dump(struct ieee80211_scan_state *ss) { struct ieee80211vap *vap = ss->ss_vap; @@ -290,8 +356,8 @@ ieee80211_scan_dump(struct ieee80211_scan_state *ss) } #endif /* IEEE80211_DEBUG */ -void -ieee80211_scan_copy_ssid(struct ieee80211vap *vap, struct ieee80211_scan_state *ss, +static void +copy_ssid(struct ieee80211vap *vap, struct ieee80211_scan_state *ss, int nssid, const struct ieee80211_scan_ssid ssids[]) { if (nssid > IEEE80211_SCAN_MAX_SSID) { @@ -308,12 +374,86 @@ ieee80211_scan_copy_ssid(struct ieee80211vap *vap, struct ieee80211_scan_state * /* * Start a scan unless one is already going. */ +static int +start_scan_locked(const struct ieee80211_scanner *scan, + struct ieee80211vap *vap, int flags, u_int duration, + u_int mindwell, u_int maxdwell, + u_int nssid, const struct ieee80211_scan_ssid ssids[]) +{ + struct ieee80211com *ic = vap->iv_ic; + struct ieee80211_scan_state *ss = ic->ic_scan; + + IEEE80211_LOCK_ASSERT(ic); + + if (ic->ic_flags & IEEE80211_F_CSAPENDING) { + IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, + "%s: scan inhibited by pending channel change\n", __func__); + } else if ((ic->ic_flags & IEEE80211_F_SCAN) == 0) { + IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, + "%s: %s scan, duration %u mindwell %u maxdwell %u, desired mode %s, %s%s%s%s%s%s\n" + , __func__ + , flags & IEEE80211_SCAN_ACTIVE ? "active" : "passive" + , duration, mindwell, maxdwell + , ieee80211_phymode_name[vap->iv_des_mode] + , flags & IEEE80211_SCAN_FLUSH ? "flush" : "append" + , flags & IEEE80211_SCAN_NOPICK ? ", nopick" : "" + , flags & IEEE80211_SCAN_NOJOIN ? ", nojoin" : "" + , flags & IEEE80211_SCAN_NOBCAST ? ", nobcast" : "" + , flags & IEEE80211_SCAN_PICK1ST ? ", pick1st" : "" + , flags & IEEE80211_SCAN_ONCE ? ", once" : "" + ); + + scan_update_locked(vap, scan); + if (ss->ss_ops != NULL) { + if ((flags & IEEE80211_SCAN_NOSSID) == 0) + copy_ssid(vap, ss, nssid, ssids); + + /* NB: top 4 bits for internal use */ + ss->ss_flags = flags & 0xfff; + if (ss->ss_flags & IEEE80211_SCAN_ACTIVE) + vap->iv_stats.is_scan_active++; + else + vap->iv_stats.is_scan_passive++; + if (flags & IEEE80211_SCAN_FLUSH) + ss->ss_ops->scan_flush(ss); + if (flags & IEEE80211_SCAN_BGSCAN) + ic->ic_flags_ext |= IEEE80211_FEXT_BGSCAN; + + /* NB: flush frames rx'd before 1st channel change */ + SCAN_PRIVATE(ss)->ss_iflags |= ISCAN_DISCARD; + SCAN_PRIVATE(ss)->ss_duration = duration; + ss->ss_next = 0; + ss->ss_mindwell = mindwell; + ss->ss_maxdwell = maxdwell; + /* NB: scan_start must be before the scan runtask */ + ss->ss_ops->scan_start(ss, vap); +#ifdef IEEE80211_DEBUG + if (ieee80211_msg_scan(vap)) + scan_dump(ss); +#endif /* IEEE80211_DEBUG */ + ic->ic_flags |= IEEE80211_F_SCAN; + ieee80211_runtask(ic, &SCAN_PRIVATE(ss)->ss_scan_task); + } + return 1; + } else { + IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, + "%s: %s scan already in progress\n", __func__, + ss->ss_flags & IEEE80211_SCAN_ACTIVE ? "active" : "passive"); + } + return 0; +} + +/* + * Start a scan unless one is already going. + */ int ieee80211_start_scan(struct ieee80211vap *vap, int flags, u_int duration, u_int mindwell, u_int maxdwell, u_int nssid, const struct ieee80211_scan_ssid ssids[]) { + struct ieee80211com *ic = vap->iv_ic; const struct ieee80211_scanner *scan; + int result; scan = ieee80211_scanner_get(vap->iv_opmode); if (scan == NULL) { @@ -324,9 +464,12 @@ ieee80211_start_scan(struct ieee80211vap *vap, int flags, return 0; } - /* XXX ops */ - return ieee80211_swscan_start_scan(scan, vap, flags, duration, + IEEE80211_LOCK(ic); + result = start_scan_locked(scan, vap, flags, duration, mindwell, maxdwell, nssid, ssids); + IEEE80211_UNLOCK(ic); + + return result; } /* @@ -373,19 +516,49 @@ ieee80211_check_scan(struct ieee80211vap *vap, int flags, /* XXX re-use cache contents? e.g. adhoc<->sta */ flags |= IEEE80211_SCAN_FLUSH; } - - /* - * XXX TODO: separate things out a bit better. - * XXX TODO: ops - */ - ieee80211_scan_update_locked(vap, scan); - - result = ieee80211_swscan_check_scan(scan, vap, flags, duration, + scan_update_locked(vap, scan); + if (ss->ss_ops != NULL) { + /* XXX verify ss_ops matches vap->iv_opmode */ + if ((flags & IEEE80211_SCAN_NOSSID) == 0) { + /* + * Update the ssid list and mark flags so if + * we call start_scan it doesn't duplicate work. + */ + copy_ssid(vap, ss, nssid, ssids); + flags |= IEEE80211_SCAN_NOSSID; + } + if ((ic->ic_flags & IEEE80211_F_SCAN) == 0 && + (flags & IEEE80211_SCAN_FLUSH) == 0 && + time_before(ticks, ic->ic_lastscan + vap->iv_scanvalid)) { + /* + * We're not currently scanning and the cache is + * deemed hot enough to consult. Lock out others + * by marking IEEE80211_F_SCAN while we decide if + * something is already in the scan cache we can + * use. Also discard any frames that might come + * in while temporarily marked as scanning. + */ + SCAN_PRIVATE(ss)->ss_iflags |= ISCAN_DISCARD; + ic->ic_flags |= IEEE80211_F_SCAN; + + /* NB: need to use supplied flags in check */ + ss->ss_flags = flags & 0xff; + result = ss->ss_ops->scan_end(ss, vap); + + ic->ic_flags &= ~IEEE80211_F_SCAN; + SCAN_PRIVATE(ss)->ss_iflags &= ~ISCAN_DISCARD; + if (result) { + ieee80211_notify_scan_done(vap); + IEEE80211_UNLOCK(ic); + return 1; + } + } + } + result = start_scan_locked(scan, vap, flags, duration, mindwell, maxdwell, nssid, ssids); - IEEE80211_UNLOCK(ic); - return (result); + return result; } /* @@ -408,10 +581,10 @@ ieee80211_check_scan_current(struct ieee80211vap *vap) int ieee80211_bg_scan(struct ieee80211vap *vap, int flags) { + struct ieee80211com *ic = vap->iv_ic; + struct ieee80211_scan_state *ss = ic->ic_scan; const struct ieee80211_scanner *scan; - // IEEE80211_UNLOCK_ASSERT(sc); - scan = ieee80211_scanner_get(vap->iv_opmode); if (scan == NULL) { IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, @@ -421,14 +594,84 @@ ieee80211_bg_scan(struct ieee80211vap *vap, int flags) return 0; } - /* - * XXX TODO: pull apart the bgscan logic into whatever - * belongs here and whatever belongs in the software - * scanner. - * - * XXX TODO: ops - */ - return (ieee80211_swscan_bg_scan(scan, vap, flags)); + IEEE80211_LOCK(ic); + if ((ic->ic_flags & IEEE80211_F_SCAN) == 0) { + u_int duration; + /* + * Go off-channel for a fixed interval that is large + * enough to catch most ap's but short enough that + * we can return on-channel before our listen interval + * expires. + */ + duration = IEEE80211_SCAN_OFFCHANNEL; + + IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, + "%s: %s scan, ticks %u duration %lu\n", __func__, + ss->ss_flags & IEEE80211_SCAN_ACTIVE ? "active" : "passive", + ticks, duration); + + scan_update_locked(vap, scan); + if (ss->ss_ops != NULL) { + ss->ss_vap = vap; + /* + * A background scan does not select a new sta; it + * just refreshes the scan cache. Also, indicate + * the scan logic should follow the beacon schedule: + * we go off-channel and scan for a while, then + * return to the bss channel to receive a beacon, + * then go off-channel again. All during this time + * we notify the ap we're in power save mode. When + * the scan is complete we leave power save mode. + * If any beacon indicates there are frames pending + * for us then we drop out of power save mode + * (and background scan) automatically by way of the + * usual sta power save logic. + */ + ss->ss_flags |= IEEE80211_SCAN_NOPICK + | IEEE80211_SCAN_BGSCAN + | flags + ; + /* if previous scan completed, restart */ + if (ss->ss_next >= ss->ss_last) { + if (ss->ss_flags & IEEE80211_SCAN_ACTIVE) + vap->iv_stats.is_scan_active++; + else + vap->iv_stats.is_scan_passive++; + /* + * NB: beware of the scan cache being flushed; + * if the channel list is empty use the + * scan_start method to populate it. + */ + ss->ss_next = 0; + if (ss->ss_last != 0) + ss->ss_ops->scan_restart(ss, vap); + else { + ss->ss_ops->scan_start(ss, vap); +#ifdef IEEE80211_DEBUG + if (ieee80211_msg_scan(vap)) + scan_dump(ss); +#endif /* IEEE80211_DEBUG */ + } + } + /* NB: flush frames rx'd before 1st channel change */ + SCAN_PRIVATE(ss)->ss_iflags |= ISCAN_DISCARD; + SCAN_PRIVATE(ss)->ss_duration = duration; + ss->ss_maxdwell = duration; + ic->ic_flags |= IEEE80211_F_SCAN; + ic->ic_flags_ext |= IEEE80211_FEXT_BGSCAN; + ieee80211_runtask(ic, &SCAN_PRIVATE(ss)->ss_scan_task); + } else { + /* XXX msg+stat */ + } + } else { + IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, + "%s: %s scan already in progress\n", __func__, + ss->ss_flags & IEEE80211_SCAN_ACTIVE ? "active" : "passive"); + } + IEEE80211_UNLOCK(ic); + + /* NB: racey, does it matter? */ + return (ic->ic_flags & IEEE80211_F_SCAN); } /* @@ -437,9 +680,25 @@ ieee80211_bg_scan(struct ieee80211vap *vap, int flags) void ieee80211_cancel_scan(struct ieee80211vap *vap) { + struct ieee80211com *ic = vap->iv_ic; + struct ieee80211_scan_state *ss = ic->ic_scan; - /* XXX TODO: ops */ - ieee80211_swscan_cancel_scan(vap); + IEEE80211_LOCK(ic); + if ((ic->ic_flags & IEEE80211_F_SCAN) && + ss->ss_vap == vap && + (SCAN_PRIVATE(ss)->ss_iflags & ISCAN_CANCEL) == 0) { + IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, + "%s: cancel %s scan\n", __func__, + ss->ss_flags & IEEE80211_SCAN_ACTIVE ? + "active" : "passive"); + + /* clear bg scan NOPICK and mark cancel request */ + ss->ss_flags &= ~IEEE80211_SCAN_NOPICK; + SCAN_PRIVATE(ss)->ss_iflags |= ISCAN_CANCEL; + /* wake up the scan task */ + scan_signal(ss); + } + IEEE80211_UNLOCK(ic); } /* @@ -448,9 +707,24 @@ ieee80211_cancel_scan(struct ieee80211vap *vap) void ieee80211_cancel_anyscan(struct ieee80211vap *vap) { + struct ieee80211com *ic = vap->iv_ic; + struct ieee80211_scan_state *ss = ic->ic_scan; - /* XXX TODO: ops */ - ieee80211_swscan_cancel_anyscan(vap); + IEEE80211_LOCK(ic); + if ((ic->ic_flags & IEEE80211_F_SCAN) && + (SCAN_PRIVATE(ss)->ss_iflags & ISCAN_CANCEL) == 0) { + IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, + "%s: cancel %s scan\n", __func__, + ss->ss_flags & IEEE80211_SCAN_ACTIVE ? + "active" : "passive"); + + /* clear bg scan NOPICK and mark cancel request */ + ss->ss_flags &= ~IEEE80211_SCAN_NOPICK; + SCAN_PRIVATE(ss)->ss_iflags |= ISCAN_CANCEL; + /* wake up the scan task */ + scan_signal(ss); + } + IEEE80211_UNLOCK(ic); } /* @@ -460,9 +734,13 @@ ieee80211_cancel_anyscan(struct ieee80211vap *vap) void ieee80211_scan_next(struct ieee80211vap *vap) { + struct ieee80211com *ic = vap->iv_ic; + struct ieee80211_scan_state *ss = ic->ic_scan; - /* XXX TODO: ops */ - ieee80211_swscan_scan_next(vap); + /* wake up the scan task */ + IEEE80211_LOCK(ic); + scan_signal(ss); + IEEE80211_UNLOCK(ic); } /* @@ -475,15 +753,10 @@ ieee80211_scan_done(struct ieee80211vap *vap) struct ieee80211com *ic = vap->iv_ic; struct ieee80211_scan_state *ss; - IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, "%s: called\n", __func__); - IEEE80211_LOCK(ic); ss = ic->ic_scan; ss->ss_next = ss->ss_last; /* all channels are complete */ - - /* XXX TODO: ops */ - ieee80211_swscan_scan_done(vap); - + scan_signal(ss); IEEE80211_UNLOCK(ic); } @@ -498,14 +771,293 @@ void ieee80211_probe_curchan(struct ieee80211vap *vap, int force) { struct ieee80211com *ic = vap->iv_ic; + struct ieee80211_scan_state *ss = ic->ic_scan; + struct ifnet *ifp = vap->iv_ifp; + int i; if ((ic->ic_curchan->ic_flags & IEEE80211_CHAN_PASSIVE) && !force) { ic->ic_flags_ext |= IEEE80211_FEXT_PROBECHAN; return; } + /* + * Send directed probe requests followed by any + * broadcast probe request. + * XXX remove dependence on ic/vap->iv_bss + */ + for (i = 0; i < ss->ss_nssid; i++) + ieee80211_send_probereq(vap->iv_bss, + vap->iv_myaddr, ifp->if_broadcastaddr, + ifp->if_broadcastaddr, + ss->ss_ssid[i].ssid, ss->ss_ssid[i].len); + if ((ss->ss_flags & IEEE80211_SCAN_NOBCAST) == 0) + ieee80211_send_probereq(vap->iv_bss, + vap->iv_myaddr, ifp->if_broadcastaddr, + ifp->if_broadcastaddr, + "", 0); +} + +/* + * Scan curchan. If this is an active scan and the channel + * is not marked passive then send probe request frame(s). + * Arrange for the channel change after maxdwell ticks. + */ +static void +scan_curchan(struct ieee80211_scan_state *ss, unsigned long maxdwell) +{ + struct ieee80211vap *vap = ss->ss_vap; + + IEEE80211_LOCK(vap->iv_ic); + if (ss->ss_flags & IEEE80211_SCAN_ACTIVE) + ieee80211_probe_curchan(vap, 0); + callout_reset(&SCAN_PRIVATE(ss)->ss_scan_timer, + maxdwell, scan_signal, ss); + IEEE80211_UNLOCK(vap->iv_ic); +} + +static void +scan_signal(void *arg) +{ + struct ieee80211_scan_state *ss = (struct ieee80211_scan_state *) arg; + + IEEE80211_LOCK_ASSERT(ss->ss_ic); + + cv_signal(&SCAN_PRIVATE(ss)->ss_scan_cv); +} + +/* + * Handle mindwell requirements completed; initiate a channel + * change to the next channel asap. + */ +static void +scan_mindwell(struct ieee80211_scan_state *ss) +{ + struct ieee80211com *ic = ss->ss_ic; + + IEEE80211_LOCK(ic); + scan_signal(ss); + IEEE80211_UNLOCK(ic); +} + +static void +scan_task(void *arg, int pending) +{ +#define ISCAN_REP (ISCAN_MINDWELL | ISCAN_DISCARD) + struct ieee80211_scan_state *ss = (struct ieee80211_scan_state *) arg; + struct ieee80211vap *vap = ss->ss_vap; + struct ieee80211com *ic = ss->ss_ic; + struct ieee80211_channel *chan; + unsigned long maxdwell, scanend; + int scandone = 0; + + IEEE80211_LOCK(ic); + if (vap == NULL || (ic->ic_flags & IEEE80211_F_SCAN) == 0 || + (SCAN_PRIVATE(ss)->ss_iflags & ISCAN_ABORT)) { + /* Cancelled before we started */ + goto done; + } + + if (ss->ss_next == ss->ss_last) { + IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, + "%s: no channels to scan\n", __func__); + scandone = 1; + goto done; + } + + if (vap->iv_opmode == IEEE80211_M_STA && + vap->iv_state == IEEE80211_S_RUN) { + if ((vap->iv_bss->ni_flags & IEEE80211_NODE_PWR_MGT) == 0) { + /* Enable station power save mode */ + vap->iv_sta_ps(vap, 1); + /* + * Use an 1ms delay so the null data frame has a chance + * to go out. + * XXX Should use M_TXCB mechanism to eliminate this. + */ + cv_timedwait(&SCAN_PRIVATE(ss)->ss_scan_cv, + IEEE80211_LOCK_OBJ(ic), hz / 1000); + if (SCAN_PRIVATE(ss)->ss_iflags & ISCAN_ABORT) + goto done; + } + } + + scanend = ticks + SCAN_PRIVATE(ss)->ss_duration; + IEEE80211_UNLOCK(ic); + ic->ic_scan_start(ic); /* notify driver */ + IEEE80211_LOCK(ic); + + for (;;) { + scandone = (ss->ss_next >= ss->ss_last) || + (SCAN_PRIVATE(ss)->ss_iflags & ISCAN_CANCEL) != 0; + if (scandone || (ss->ss_flags & IEEE80211_SCAN_GOTPICK) || + (SCAN_PRIVATE(ss)->ss_iflags & ISCAN_ABORT) || + time_after(ticks + ss->ss_mindwell, scanend)) + break; + + chan = ss->ss_chans[ss->ss_next++]; + + /* + * Watch for truncation due to the scan end time. + */ + if (time_after(ticks + ss->ss_maxdwell, scanend)) + maxdwell = scanend - ticks; + else + maxdwell = ss->ss_maxdwell; + + IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, + "%s: chan %3d%c -> %3d%c [%s, dwell min %lums max %lums]\n", + __func__, + ieee80211_chan2ieee(ic, ic->ic_curchan), + channel_type(ic->ic_curchan), + ieee80211_chan2ieee(ic, chan), channel_type(chan), + (ss->ss_flags & IEEE80211_SCAN_ACTIVE) && + (chan->ic_flags & IEEE80211_CHAN_PASSIVE) == 0 ? + "active" : "passive", + ticks_to_msecs(ss->ss_mindwell), ticks_to_msecs(maxdwell)); + + /* + * Potentially change channel and phy mode. + */ + ic->ic_curchan = chan; + ic->ic_rt = ieee80211_get_ratetable(chan); + IEEE80211_UNLOCK(ic); + /* + * Perform the channel change and scan unlocked so the driver + * may sleep. Once set_channel returns the hardware has + * completed the channel change. + */ + ic->ic_set_channel(ic); + ieee80211_radiotap_chan_change(ic); + + /* + * Scan curchan. Drivers for "intelligent hardware" + * override ic_scan_curchan to tell the device to do + * the work. Otherwise we manage the work outselves; + * sending a probe request (as needed), and arming the + * timeout to switch channels after maxdwell ticks. + * + * scan_curchan should only pause for the time required to + * prepare/initiate the hardware for the scan (if at all), the + * below condvar is used to sleep for the channels dwell time + * and allows it to be signalled for abort. + */ + ic->ic_scan_curchan(ss, maxdwell); + IEEE80211_LOCK(ic); + + SCAN_PRIVATE(ss)->ss_chanmindwell = ticks + ss->ss_mindwell; + /* clear mindwell lock and initial channel change flush */ + SCAN_PRIVATE(ss)->ss_iflags &= ~ISCAN_REP; + + if ((SCAN_PRIVATE(ss)->ss_iflags & (ISCAN_CANCEL|ISCAN_ABORT))) + continue; + + /* Wait to be signalled to scan the next channel */ + cv_wait(&SCAN_PRIVATE(ss)->ss_scan_cv, IEEE80211_LOCK_OBJ(ic)); + } + if (SCAN_PRIVATE(ss)->ss_iflags & ISCAN_ABORT) + goto done; + + IEEE80211_UNLOCK(ic); + ic->ic_scan_end(ic); /* notify driver */ + IEEE80211_LOCK(ic); + + /* + * Since a cancellation may have occured during one of the + * driver calls (whilst unlocked), update scandone. + */ + if (scandone == 0 && + ((SCAN_PRIVATE(ss)->ss_iflags & ISCAN_CANCEL) != 0)) { + /* XXX printf? */ + if_printf(vap->iv_ifp, + "%s: OOPS! scan cancelled during driver call!\n", + __func__); + } + scandone |= ((SCAN_PRIVATE(ss)->ss_iflags & ISCAN_CANCEL) != 0); + + /* + * Record scan complete time. Note that we also do + * this when canceled so any background scan will + * not be restarted for a while. + */ + if (scandone) + ic->ic_lastscan = ticks; + /* return to the bss channel */ + if (ic->ic_bsschan != IEEE80211_CHAN_ANYC && + ic->ic_curchan != ic->ic_bsschan) { + ieee80211_setupcurchan(ic, ic->ic_bsschan); + IEEE80211_UNLOCK(ic); + ic->ic_set_channel(ic); + ieee80211_radiotap_chan_change(ic); + IEEE80211_LOCK(ic); + } + /* clear internal flags and any indication of a pick */ + SCAN_PRIVATE(ss)->ss_iflags &= ~ISCAN_REP; + ss->ss_flags &= ~IEEE80211_SCAN_GOTPICK; + + /* + * If not canceled and scan completed, do post-processing. + * If the callback function returns 0, then it wants to + * continue/restart scanning. Unfortunately we needed to + * notify the driver to end the scan above to avoid having + * rx frames alter the scan candidate list. + */ + if ((SCAN_PRIVATE(ss)->ss_iflags & ISCAN_CANCEL) == 0 && + !ss->ss_ops->scan_end(ss, vap) && + (ss->ss_flags & IEEE80211_SCAN_ONCE) == 0 && + time_before(ticks + ss->ss_mindwell, scanend)) { + IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, + "%s: done, restart " + "[ticks %u, dwell min %lu scanend %lu]\n", + __func__, + ticks, ss->ss_mindwell, scanend); + ss->ss_next = 0; /* reset to begining */ + if (ss->ss_flags & IEEE80211_SCAN_ACTIVE) + vap->iv_stats.is_scan_active++; + else + vap->iv_stats.is_scan_passive++; + + ss->ss_ops->scan_restart(ss, vap); /* XXX? */ + ieee80211_runtask(ic, &SCAN_PRIVATE(ss)->ss_scan_task); + IEEE80211_UNLOCK(ic); + return; + } + + /* past here, scandone is ``true'' if not in bg mode */ + if ((ss->ss_flags & IEEE80211_SCAN_BGSCAN) == 0) + scandone = 1; + + IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, + "%s: %s, [ticks %u, dwell min %lu scanend %lu]\n", + __func__, scandone ? "done" : "stopped", + ticks, ss->ss_mindwell, scanend); - /* XXX TODO: ops */ - ieee80211_swscan_probe_curchan(vap, force); + /* + * Clear the SCAN bit first in case frames are + * pending on the station power save queue. If + * we defer this then the dispatch of the frames + * may generate a request to cancel scanning. + */ +done: + ic->ic_flags &= ~IEEE80211_F_SCAN; + /* + * Drop out of power save mode when a scan has + * completed. If this scan was prematurely terminated + * because it is a background scan then don't notify + * the ap; we'll either return to scanning after we + * receive the beacon frame or we'll drop out of power + * save mode because the beacon indicates we have frames + * waiting for us. + */ + if (scandone) { + vap->iv_sta_ps(vap, 0); + if (ss->ss_next >= ss->ss_last) { + ieee80211_notify_scan_done(vap); + ic->ic_flags_ext &= ~IEEE80211_FEXT_BGSCAN; + } + } + SCAN_PRIVATE(ss)->ss_iflags &= ~(ISCAN_CANCEL|ISCAN_ABORT); + ss->ss_flags &= ~(IEEE80211_SCAN_ONCE | IEEE80211_SCAN_PICK1ST); + IEEE80211_UNLOCK(ic); +#undef ISCAN_REP } #ifdef IEEE80211_DEBUG @@ -534,8 +1086,8 @@ dump_country(const uint8_t *ie) printf("]"); } -void -ieee80211_scan_dump_probe_beacon(uint8_t subtype, int isnew, +static void +dump_probe_beacon(uint8_t subtype, int isnew, const uint8_t mac[IEEE80211_ADDR_LEN], const struct ieee80211_scanparams *sp, int rssi) { @@ -562,14 +1114,49 @@ ieee80211_scan_dump_probe_beacon(uint8_t subtype, int isnew, */ void ieee80211_add_scan(struct ieee80211vap *vap, - struct ieee80211_channel *curchan, const struct ieee80211_scanparams *sp, const struct ieee80211_frame *wh, int subtype, int rssi, int noise) { + struct ieee80211com *ic = vap->iv_ic; + struct ieee80211_scan_state *ss = ic->ic_scan; - return (ieee80211_swscan_add_scan(vap, curchan, sp, wh, subtype, - rssi, noise)); + /* XXX locking */ + /* + * Frames received during startup are discarded to avoid + * using scan state setup on the initial entry to the timer + * callback. This can occur because the device may enable + * rx prior to our doing the initial channel change in the + * timer routine. + */ + if (SCAN_PRIVATE(ss)->ss_iflags & ISCAN_DISCARD) + return; +#ifdef IEEE80211_DEBUG + if (ieee80211_msg_scan(vap) && (ic->ic_flags & IEEE80211_F_SCAN)) + dump_probe_beacon(subtype, 1, wh->i_addr2, sp, rssi); +#endif + if (ss->ss_ops != NULL && + ss->ss_ops->scan_add(ss, sp, wh, subtype, rssi, noise)) { + /* + * If we've reached the min dwell time terminate + * the timer so we'll switch to the next channel. + */ + if ((SCAN_PRIVATE(ss)->ss_iflags & ISCAN_MINDWELL) == 0 && + time_after_eq(ticks, SCAN_PRIVATE(ss)->ss_chanmindwell)) { + IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, + "%s: chan %3d%c min dwell met (%u > %lu)\n", + __func__, + ieee80211_chan2ieee(ic, ic->ic_curchan), + channel_type(ic->ic_curchan), + ticks, SCAN_PRIVATE(ss)->ss_chanmindwell); + SCAN_PRIVATE(ss)->ss_iflags |= ISCAN_MINDWELL; + /* + * NB: trigger at next clock tick or wait for the + * hardware. + */ + ic->ic_scan_mindwell(ss); + } + } } /* diff --git a/sys/net80211/ieee80211_scan.h b/sys/net80211/ieee80211_scan.h index 8b54186..3f13e17 100644 --- a/sys/net80211/ieee80211_scan.h +++ b/sys/net80211/ieee80211_scan.h @@ -148,7 +148,6 @@ struct ieee80211_channel *ieee80211_scan_pickchannel(struct ieee80211com *, int) struct ieee80211_scanparams; void ieee80211_add_scan(struct ieee80211vap *, - struct ieee80211_channel *, const struct ieee80211_scanparams *, const struct ieee80211_frame *, int subtype, int rssi, int noise); @@ -274,7 +273,6 @@ struct ieee80211_scanner { struct ieee80211_scan_state *, int); /* add an entry to the cache */ int (*scan_add)(struct ieee80211_scan_state *, - struct ieee80211_channel *, const struct ieee80211_scanparams *, const struct ieee80211_frame *, int subtype, int rssi, int noise); @@ -301,14 +299,4 @@ void ieee80211_scanner_unregister(enum ieee80211_opmode, const struct ieee80211_scanner *); void ieee80211_scanner_unregister_all(const struct ieee80211_scanner *); const struct ieee80211_scanner *ieee80211_scanner_get(enum ieee80211_opmode); -void ieee80211_scan_update_locked(struct ieee80211vap *vap, - const struct ieee80211_scanner *scan); -void ieee80211_scan_copy_ssid(struct ieee80211vap *vap, - struct ieee80211_scan_state *ss, - int nssid, const struct ieee80211_scan_ssid ssids[]); -void ieee80211_scan_dump_probe_beacon(uint8_t subtype, int isnew, - const uint8_t mac[IEEE80211_ADDR_LEN], - const struct ieee80211_scanparams *sp, int rssi); -void ieee80211_scan_dump(struct ieee80211_scan_state *ss); - #endif /* _NET80211_IEEE80211_SCAN_H_ */ diff --git a/sys/net80211/ieee80211_scan_sta.c b/sys/net80211/ieee80211_scan_sta.c index 1fb45b0..c791ea1 100644 --- a/sys/net80211/ieee80211_scan_sta.c +++ b/sys/net80211/ieee80211_scan_sta.c @@ -39,7 +39,6 @@ __FBSDID("$FreeBSD$"); #include <sys/socket.h> #include <net/if.h> -#include <net/if_var.h> #include <net/if_media.h> #include <net/ethernet.h> @@ -228,7 +227,6 @@ sta_flush_table(struct sta_table *st) */ static int sta_add(struct ieee80211_scan_state *ss, - struct ieee80211_channel *curchan, const struct ieee80211_scanparams *sp, const struct ieee80211_frame *wh, int subtype, int rssi, int noise) @@ -311,15 +309,15 @@ found: * IEEE80211_BPARSE_OFFCHAN. */ c = ieee80211_find_channel_byieee(ic, sp->chan, - curchan->ic_flags); + ic->ic_curchan->ic_flags); if (c != NULL) { ise->se_chan = c; } else if (ise->se_chan == NULL) { /* should not happen, pick something */ - ise->se_chan = curchan; + ise->se_chan = ic->ic_curchan; } } else - ise->se_chan = curchan; + ise->se_chan = ic->ic_curchan; if (IEEE80211_IS_CHAN_HT(ise->se_chan) && sp->htcap == NULL) { /* Demote legacy networks to a non-HT channel. */ c = ieee80211_find_channel(ic, ise->se_chan->ic_freq, @@ -601,12 +599,10 @@ makescanlist(struct ieee80211_scan_state *ss, struct ieee80211vap *vap, * so if the desired mode is 11g, then use * the 11b channel list but upgrade the mode. */ - if (vap->iv_des_mode == IEEE80211_MODE_11G) { - if (mode == IEEE80211_MODE_11G) /* Skip the G check */ - continue; - else if (mode == IEEE80211_MODE_11B) - mode = IEEE80211_MODE_11G; /* upgrade */ - } + if (vap->iv_des_mode != IEEE80211_MODE_11G || + mode != IEEE80211_MODE_11B) + continue; + mode = IEEE80211_MODE_11G; /* upgrade */ } } else { /* @@ -736,7 +732,7 @@ sta_cancel(struct ieee80211_scan_state *ss, struct ieee80211vap *vap) return 0; } -/* unaligned little endian access */ +/* unalligned little endian access */ #define LE_READ_2(p) \ ((uint16_t) \ ((((const uint8_t *)(p))[0] ) | \ diff --git a/sys/net80211/ieee80211_scan_sw.c b/sys/net80211/ieee80211_scan_sw.c deleted file mode 100644 index 70b4673..0000000 --- a/sys/net80211/ieee80211_scan_sw.c +++ /dev/null @@ -1,948 +0,0 @@ -/*- - * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -/* - * IEEE 802.11 scanning support. - */ -#include "opt_wlan.h" - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/proc.h> -#include <sys/kernel.h> -#include <sys/condvar.h> - -#include <sys/socket.h> - -#include <net/if.h> -#include <net/if_var.h> -#include <net/if_media.h> -#include <net/ethernet.h> - -#include <net80211/ieee80211_var.h> - -#include <net80211/ieee80211_scan_sw.h> - -#include <net/bpf.h> - -struct scan_state { - struct ieee80211_scan_state base; /* public state */ - - u_int ss_iflags; /* flags used internally */ -#define ISCAN_MINDWELL 0x0001 /* min dwell time reached */ -#define ISCAN_DISCARD 0x0002 /* discard rx'd frames */ -#define ISCAN_CANCEL 0x0004 /* cancel current scan */ -#define ISCAN_ABORT 0x0008 /* end the scan immediately */ - unsigned long ss_chanmindwell; /* min dwell on curchan */ - unsigned long ss_scanend; /* time scan must stop */ - u_int ss_duration; /* duration for next scan */ - struct task ss_scan_task; /* scan execution */ - struct cv ss_scan_cv; /* scan signal */ - struct callout ss_scan_timer; /* scan timer */ -}; -#define SCAN_PRIVATE(ss) ((struct scan_state *) ss) - -/* - * Amount of time to go off-channel during a background - * scan. This value should be large enough to catch most - * ap's but short enough that we can return on-channel - * before our listen interval expires. - * - * XXX tunable - * XXX check against configured listen interval - */ -#define IEEE80211_SCAN_OFFCHANNEL msecs_to_ticks(150) - -/* - * Roaming-related defaults. RSSI thresholds are as returned by the - * driver (.5dBm). Transmit rate thresholds are IEEE rate codes (i.e - * .5M units) or MCS. - */ -/* rssi thresholds */ -#define ROAM_RSSI_11A_DEFAULT 14 /* 11a bss */ -#define ROAM_RSSI_11B_DEFAULT 14 /* 11b bss */ -#define ROAM_RSSI_11BONLY_DEFAULT 14 /* 11b-only bss */ -/* transmit rate thresholds */ -#define ROAM_RATE_11A_DEFAULT 2*12 /* 11a bss */ -#define ROAM_RATE_11B_DEFAULT 2*5 /* 11b bss */ -#define ROAM_RATE_11BONLY_DEFAULT 2*1 /* 11b-only bss */ -#define ROAM_RATE_HALF_DEFAULT 2*6 /* half-width 11a/g bss */ -#define ROAM_RATE_QUARTER_DEFAULT 2*3 /* quarter-width 11a/g bss */ -#define ROAM_MCS_11N_DEFAULT (1 | IEEE80211_RATE_MCS) /* 11n bss */ - -static void scan_curchan(struct ieee80211_scan_state *, unsigned long); -static void scan_mindwell(struct ieee80211_scan_state *); -static void scan_signal(void *); -static void scan_task(void *, int); - -MALLOC_DEFINE(M_80211_SCAN, "80211scan", "802.11 scan state"); - -void -ieee80211_swscan_attach(struct ieee80211com *ic) -{ - struct scan_state *ss; - - ss = (struct scan_state *) malloc(sizeof(struct scan_state), - M_80211_SCAN, M_NOWAIT | M_ZERO); - if (ss == NULL) { - ic->ic_scan = NULL; - return; - } - callout_init_mtx(&ss->ss_scan_timer, IEEE80211_LOCK_OBJ(ic), 0); - cv_init(&ss->ss_scan_cv, "scan"); - TASK_INIT(&ss->ss_scan_task, 0, scan_task, ss); - - ic->ic_scan = &ss->base; - ss->base.ss_ic = ic; - - ic->ic_scan_curchan = scan_curchan; - ic->ic_scan_mindwell = scan_mindwell; - - /* - * TODO: all of the non-vap scan calls should be methods! - */ -} - -void -ieee80211_swscan_detach(struct ieee80211com *ic) -{ - struct ieee80211_scan_state *ss = ic->ic_scan; - - if (ss != NULL) { - IEEE80211_LOCK(ic); - SCAN_PRIVATE(ss)->ss_iflags |= ISCAN_ABORT; - scan_signal(ss); - IEEE80211_UNLOCK(ic); - ieee80211_draintask(ic, &SCAN_PRIVATE(ss)->ss_scan_task); - callout_drain(&SCAN_PRIVATE(ss)->ss_scan_timer); - KASSERT((ic->ic_flags & IEEE80211_F_SCAN) == 0, - ("scan still running")); - - /* - * For now, do the ss_ops detach here rather - * than ieee80211_scan_detach(). - * - * I'll figure out how to cleanly split things up - * at a later date. - */ - if (ss->ss_ops != NULL) { - ss->ss_ops->scan_detach(ss); - ss->ss_ops = NULL; - } - ic->ic_scan = NULL; - free(SCAN_PRIVATE(ss), M_80211_SCAN); - } -} - -void -ieee80211_swscan_vattach(struct ieee80211vap *vap) -{ - /* nothing to do for now */ - /* - * TODO: all of the vap scan calls should be methods! - */ - -} - -void -ieee80211_swscan_vdetach(struct ieee80211vap *vap) -{ - struct ieee80211com *ic = vap->iv_ic; - struct ieee80211_scan_state *ss; - - IEEE80211_LOCK_ASSERT(ic); - ss = ic->ic_scan; - if (ss != NULL && ss->ss_vap == vap) { - if (ic->ic_flags & IEEE80211_F_SCAN) { - SCAN_PRIVATE(ss)->ss_iflags |= ISCAN_ABORT; - scan_signal(ss); - } - } -} - -void -ieee80211_swscan_set_scan_duration(struct ieee80211vap *vap, u_int duration) -{ - struct ieee80211com *ic = vap->iv_ic; - struct ieee80211_scan_state *ss = ic->ic_scan; - - IEEE80211_LOCK_ASSERT(ic); - - /* NB: flush frames rx'd before 1st channel change */ - SCAN_PRIVATE(ss)->ss_iflags |= ISCAN_DISCARD; - SCAN_PRIVATE(ss)->ss_duration = duration; -} - -void -ieee80211_swscan_run_scan_task(struct ieee80211vap *vap) -{ - struct ieee80211com *ic = vap->iv_ic; - struct ieee80211_scan_state *ss = ic->ic_scan; - - IEEE80211_LOCK_ASSERT(ic); - - ieee80211_runtask(ic, &SCAN_PRIVATE(ss)->ss_scan_task); -} - -/* - * Start a scan unless one is already going. - */ -static int -ieee80211_swscan_start_scan_locked(const struct ieee80211_scanner *scan, - struct ieee80211vap *vap, int flags, u_int duration, - u_int mindwell, u_int maxdwell, - u_int nssid, const struct ieee80211_scan_ssid ssids[]) -{ - struct ieee80211com *ic = vap->iv_ic; - struct ieee80211_scan_state *ss = ic->ic_scan; - - IEEE80211_LOCK_ASSERT(ic); - - if (ic->ic_flags & IEEE80211_F_CSAPENDING) { - IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, - "%s: scan inhibited by pending channel change\n", __func__); - } else if ((ic->ic_flags & IEEE80211_F_SCAN) == 0) { - IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, - "%s: %s scan, duration %u mindwell %u maxdwell %u, desired mode %s, %s%s%s%s%s%s\n" - , __func__ - , flags & IEEE80211_SCAN_ACTIVE ? "active" : "passive" - , duration, mindwell, maxdwell - , ieee80211_phymode_name[vap->iv_des_mode] - , flags & IEEE80211_SCAN_FLUSH ? "flush" : "append" - , flags & IEEE80211_SCAN_NOPICK ? ", nopick" : "" - , flags & IEEE80211_SCAN_NOJOIN ? ", nojoin" : "" - , flags & IEEE80211_SCAN_NOBCAST ? ", nobcast" : "" - , flags & IEEE80211_SCAN_PICK1ST ? ", pick1st" : "" - , flags & IEEE80211_SCAN_ONCE ? ", once" : "" - ); - - ieee80211_scan_update_locked(vap, scan); - if (ss->ss_ops != NULL) { - if ((flags & IEEE80211_SCAN_NOSSID) == 0) - ieee80211_scan_copy_ssid(vap, ss, nssid, ssids); - - /* NB: top 4 bits for internal use */ - ss->ss_flags = flags & 0xfff; - if (ss->ss_flags & IEEE80211_SCAN_ACTIVE) - vap->iv_stats.is_scan_active++; - else - vap->iv_stats.is_scan_passive++; - if (flags & IEEE80211_SCAN_FLUSH) - ss->ss_ops->scan_flush(ss); - if (flags & IEEE80211_SCAN_BGSCAN) - ic->ic_flags_ext |= IEEE80211_FEXT_BGSCAN; - - /* Set duration for this particular scan */ - ieee80211_swscan_set_scan_duration(vap, duration); - - ss->ss_next = 0; - ss->ss_mindwell = mindwell; - ss->ss_maxdwell = maxdwell; - /* NB: scan_start must be before the scan runtask */ - ss->ss_ops->scan_start(ss, vap); -#ifdef IEEE80211_DEBUG - if (ieee80211_msg_scan(vap)) - ieee80211_scan_dump(ss); -#endif /* IEEE80211_DEBUG */ - ic->ic_flags |= IEEE80211_F_SCAN; - - /* Start scan task */ - ieee80211_swscan_run_scan_task(vap); - } - return 1; - } else { - IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, - "%s: %s scan already in progress\n", __func__, - ss->ss_flags & IEEE80211_SCAN_ACTIVE ? "active" : "passive"); - } - return 0; -} - - -/* - * Start a scan unless one is already going. - * - * Called without the comlock held; grab the comlock as appropriate. - */ -int -ieee80211_swscan_start_scan(const struct ieee80211_scanner *scan, - struct ieee80211vap *vap, int flags, - u_int duration, u_int mindwell, u_int maxdwell, - u_int nssid, const struct ieee80211_scan_ssid ssids[]) -{ - struct ieee80211com *ic = vap->iv_ic; - int result; - - IEEE80211_UNLOCK_ASSERT(ic); - - IEEE80211_LOCK(ic); - result = ieee80211_swscan_start_scan_locked(scan, vap, flags, duration, - mindwell, maxdwell, nssid, ssids); - IEEE80211_UNLOCK(ic); - - return result; -} - -/* - * Check the scan cache for an ap/channel to use; if that - * fails then kick off a new scan. - * - * Called with the comlock held. - * - * XXX TODO: split out! - */ -int -ieee80211_swscan_check_scan(const struct ieee80211_scanner *scan, - struct ieee80211vap *vap, int flags, - u_int duration, u_int mindwell, u_int maxdwell, - u_int nssid, const struct ieee80211_scan_ssid ssids[]) -{ - struct ieee80211com *ic = vap->iv_ic; - struct ieee80211_scan_state *ss = ic->ic_scan; - int result; - - IEEE80211_LOCK_ASSERT(ic); - - if (ss->ss_ops != NULL) { - /* XXX verify ss_ops matches vap->iv_opmode */ - if ((flags & IEEE80211_SCAN_NOSSID) == 0) { - /* - * Update the ssid list and mark flags so if - * we call start_scan it doesn't duplicate work. - */ - ieee80211_scan_copy_ssid(vap, ss, nssid, ssids); - flags |= IEEE80211_SCAN_NOSSID; - } - if ((ic->ic_flags & IEEE80211_F_SCAN) == 0 && - (flags & IEEE80211_SCAN_FLUSH) == 0 && - time_before(ticks, ic->ic_lastscan + vap->iv_scanvalid)) { - /* - * We're not currently scanning and the cache is - * deemed hot enough to consult. Lock out others - * by marking IEEE80211_F_SCAN while we decide if - * something is already in the scan cache we can - * use. Also discard any frames that might come - * in while temporarily marked as scanning. - */ - SCAN_PRIVATE(ss)->ss_iflags |= ISCAN_DISCARD; - ic->ic_flags |= IEEE80211_F_SCAN; - - /* NB: need to use supplied flags in check */ - ss->ss_flags = flags & 0xff; - result = ss->ss_ops->scan_end(ss, vap); - - ic->ic_flags &= ~IEEE80211_F_SCAN; - SCAN_PRIVATE(ss)->ss_iflags &= ~ISCAN_DISCARD; - if (result) { - ieee80211_notify_scan_done(vap); - return 1; - } - } - } - result = ieee80211_swscan_start_scan_locked(scan, vap, flags, duration, - mindwell, maxdwell, nssid, ssids); - - return result; -} - -/* - * Restart a previous scan. If the previous scan completed - * then we start again using the existing channel list. - */ -int -ieee80211_swscan_bg_scan(const struct ieee80211_scanner *scan, - struct ieee80211vap *vap, int flags) -{ - struct ieee80211com *ic = vap->iv_ic; - struct ieee80211_scan_state *ss = ic->ic_scan; - - /* XXX assert unlocked? */ - // IEEE80211_UNLOCK_ASSERT(ic); - - IEEE80211_LOCK(ic); - if ((ic->ic_flags & IEEE80211_F_SCAN) == 0) { - u_int duration; - /* - * Go off-channel for a fixed interval that is large - * enough to catch most ap's but short enough that - * we can return on-channel before our listen interval - * expires. - */ - duration = IEEE80211_SCAN_OFFCHANNEL; - - IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, - "%s: %s scan, ticks %u duration %lu\n", __func__, - ss->ss_flags & IEEE80211_SCAN_ACTIVE ? "active" : "passive", - ticks, duration); - - ieee80211_scan_update_locked(vap, scan); - if (ss->ss_ops != NULL) { - ss->ss_vap = vap; - /* - * A background scan does not select a new sta; it - * just refreshes the scan cache. Also, indicate - * the scan logic should follow the beacon schedule: - * we go off-channel and scan for a while, then - * return to the bss channel to receive a beacon, - * then go off-channel again. All during this time - * we notify the ap we're in power save mode. When - * the scan is complete we leave power save mode. - * If any beacon indicates there are frames pending - * for us then we drop out of power save mode - * (and background scan) automatically by way of the - * usual sta power save logic. - */ - ss->ss_flags |= IEEE80211_SCAN_NOPICK - | IEEE80211_SCAN_BGSCAN - | flags - ; - /* if previous scan completed, restart */ - if (ss->ss_next >= ss->ss_last) { - if (ss->ss_flags & IEEE80211_SCAN_ACTIVE) - vap->iv_stats.is_scan_active++; - else - vap->iv_stats.is_scan_passive++; - /* - * NB: beware of the scan cache being flushed; - * if the channel list is empty use the - * scan_start method to populate it. - */ - ss->ss_next = 0; - if (ss->ss_last != 0) - ss->ss_ops->scan_restart(ss, vap); - else { - ss->ss_ops->scan_start(ss, vap); -#ifdef IEEE80211_DEBUG - if (ieee80211_msg_scan(vap)) - ieee80211_scan_dump(ss); -#endif /* IEEE80211_DEBUG */ - } - } - ieee80211_swscan_set_scan_duration(vap, duration); - ss->ss_maxdwell = duration; - ic->ic_flags |= IEEE80211_F_SCAN; - ic->ic_flags_ext |= IEEE80211_FEXT_BGSCAN; - ieee80211_runtask(ic, &SCAN_PRIVATE(ss)->ss_scan_task); - } else { - /* XXX msg+stat */ - } - } else { - IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, - "%s: %s scan already in progress\n", __func__, - ss->ss_flags & IEEE80211_SCAN_ACTIVE ? "active" : "passive"); - } - IEEE80211_UNLOCK(ic); - - /* NB: racey, does it matter? */ - return (ic->ic_flags & IEEE80211_F_SCAN); -} - -/* - * Cancel any scan currently going on for the specified vap. - */ -void -ieee80211_swscan_cancel_scan(struct ieee80211vap *vap) -{ - struct ieee80211com *ic = vap->iv_ic; - struct ieee80211_scan_state *ss = ic->ic_scan; - - IEEE80211_LOCK(ic); - if ((ic->ic_flags & IEEE80211_F_SCAN) && - ss->ss_vap == vap && - (SCAN_PRIVATE(ss)->ss_iflags & ISCAN_CANCEL) == 0) { - IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, - "%s: cancel %s scan\n", __func__, - ss->ss_flags & IEEE80211_SCAN_ACTIVE ? - "active" : "passive"); - - /* clear bg scan NOPICK and mark cancel request */ - ss->ss_flags &= ~IEEE80211_SCAN_NOPICK; - SCAN_PRIVATE(ss)->ss_iflags |= ISCAN_CANCEL; - /* wake up the scan task */ - scan_signal(ss); - } else { - IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, - "%s: called; F_SCAN=%d, vap=%s, CANCEL=%d\n", - __func__, - !! (ic->ic_flags & IEEE80211_F_SCAN), - (ss->ss_vap == vap ? "match" : "nomatch"), - !! (SCAN_PRIVATE(ss)->ss_iflags & ISCAN_CANCEL)); - } - IEEE80211_UNLOCK(ic); -} - -/* - * Cancel any scan currently going on. - */ -void -ieee80211_swscan_cancel_anyscan(struct ieee80211vap *vap) -{ - struct ieee80211com *ic = vap->iv_ic; - struct ieee80211_scan_state *ss = ic->ic_scan; - - IEEE80211_LOCK(ic); - if ((ic->ic_flags & IEEE80211_F_SCAN) && - (SCAN_PRIVATE(ss)->ss_iflags & ISCAN_CANCEL) == 0) { - IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, - "%s: cancel %s scan\n", __func__, - ss->ss_flags & IEEE80211_SCAN_ACTIVE ? - "active" : "passive"); - - /* clear bg scan NOPICK and mark cancel request */ - ss->ss_flags &= ~IEEE80211_SCAN_NOPICK; - SCAN_PRIVATE(ss)->ss_iflags |= ISCAN_CANCEL; - /* wake up the scan task */ - scan_signal(ss); - } else { - IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, - "%s: called; F_SCAN=%d, vap=%s, CANCEL=%d\n", - __func__, - !! (ic->ic_flags & IEEE80211_F_SCAN), - (ss->ss_vap == vap ? "match" : "nomatch"), - !! (SCAN_PRIVATE(ss)->ss_iflags & ISCAN_CANCEL)); - } - IEEE80211_UNLOCK(ic); -} - -/* - * Public access to scan_next for drivers that manage - * scanning themselves (e.g. for firmware-based devices). - */ -void -ieee80211_swscan_scan_next(struct ieee80211vap *vap) -{ - struct ieee80211com *ic = vap->iv_ic; - struct ieee80211_scan_state *ss = ic->ic_scan; - - IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, "%s: called\n", __func__); - - /* wake up the scan task */ - IEEE80211_LOCK(ic); - scan_signal(ss); - IEEE80211_UNLOCK(ic); -} - -/* - * Public access to scan_next for drivers that are not able to scan single - * channels (e.g. for firmware-based devices). - */ -void -ieee80211_swscan_scan_done(struct ieee80211vap *vap) -{ - struct ieee80211com *ic = vap->iv_ic; - struct ieee80211_scan_state *ss; - - IEEE80211_LOCK_ASSERT(ic); - - ss = ic->ic_scan; - scan_signal(ss); -} - -/* - * Probe the curent channel, if allowed, while scanning. - * If the channel is not marked passive-only then send - * a probe request immediately. Otherwise mark state and - * listen for beacons on the channel; if we receive something - * then we'll transmit a probe request. - */ -void -ieee80211_swscan_probe_curchan(struct ieee80211vap *vap, int force) -{ - struct ieee80211com *ic = vap->iv_ic; - struct ieee80211_scan_state *ss = ic->ic_scan; - struct ifnet *ifp = vap->iv_ifp; - int i; - - /* - * Send directed probe requests followed by any - * broadcast probe request. - * XXX remove dependence on ic/vap->iv_bss - */ - for (i = 0; i < ss->ss_nssid; i++) - ieee80211_send_probereq(vap->iv_bss, - vap->iv_myaddr, ifp->if_broadcastaddr, - ifp->if_broadcastaddr, - ss->ss_ssid[i].ssid, ss->ss_ssid[i].len); - if ((ss->ss_flags & IEEE80211_SCAN_NOBCAST) == 0) - ieee80211_send_probereq(vap->iv_bss, - vap->iv_myaddr, ifp->if_broadcastaddr, - ifp->if_broadcastaddr, - "", 0); -} - -/* - * Scan curchan. If this is an active scan and the channel - * is not marked passive then send probe request frame(s). - * Arrange for the channel change after maxdwell ticks. - */ -static void -scan_curchan(struct ieee80211_scan_state *ss, unsigned long maxdwell) -{ - struct ieee80211vap *vap = ss->ss_vap; - - IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, - "%s: calling; maxdwell=%lu\n", - __func__, - maxdwell); - IEEE80211_LOCK(vap->iv_ic); - if (ss->ss_flags & IEEE80211_SCAN_ACTIVE) - ieee80211_probe_curchan(vap, 0); - callout_reset(&SCAN_PRIVATE(ss)->ss_scan_timer, - maxdwell, scan_signal, ss); - IEEE80211_UNLOCK(vap->iv_ic); -} - -static void -scan_signal(void *arg) -{ - struct ieee80211_scan_state *ss = (struct ieee80211_scan_state *) arg; - - IEEE80211_LOCK_ASSERT(ss->ss_ic); - cv_signal(&SCAN_PRIVATE(ss)->ss_scan_cv); -} - -/* - * Handle mindwell requirements completed; initiate a channel - * change to the next channel asap. - */ -static void -scan_mindwell(struct ieee80211_scan_state *ss) -{ - struct ieee80211com *ic = ss->ss_ic; - - IEEE80211_DPRINTF(ss->ss_vap, IEEE80211_MSG_SCAN, "%s: called\n", __func__); - - IEEE80211_LOCK(ic); - scan_signal(ss); - IEEE80211_UNLOCK(ic); -} - -static void -scan_task(void *arg, int pending) -{ -#define ISCAN_REP (ISCAN_MINDWELL | ISCAN_DISCARD) - struct ieee80211_scan_state *ss = (struct ieee80211_scan_state *) arg; - struct ieee80211vap *vap = ss->ss_vap; - struct ieee80211com *ic = ss->ss_ic; - struct ieee80211_channel *chan; - unsigned long maxdwell, scanend; - int scandone = 0; - - IEEE80211_LOCK(ic); - if (vap == NULL || (ic->ic_flags & IEEE80211_F_SCAN) == 0 || - (SCAN_PRIVATE(ss)->ss_iflags & ISCAN_ABORT)) { - /* Cancelled before we started */ - goto done; - } - - if (ss->ss_next == ss->ss_last) { - IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, - "%s: no channels to scan\n", __func__); - scandone = 1; - goto done; - } - - if (vap->iv_opmode == IEEE80211_M_STA && - vap->iv_state == IEEE80211_S_RUN) { - if ((vap->iv_bss->ni_flags & IEEE80211_NODE_PWR_MGT) == 0) { - /* Enable station power save mode */ - vap->iv_sta_ps(vap, 1); - /* - * Use an 1ms delay so the null data frame has a chance - * to go out. - * XXX Should use M_TXCB mechanism to eliminate this. - */ - cv_timedwait(&SCAN_PRIVATE(ss)->ss_scan_cv, - IEEE80211_LOCK_OBJ(ic), hz / 1000); - if (SCAN_PRIVATE(ss)->ss_iflags & ISCAN_ABORT) - goto done; - } - } - - scanend = ticks + SCAN_PRIVATE(ss)->ss_duration; - - /* XXX scan state can change! Re-validate scan state! */ - - IEEE80211_UNLOCK(ic); - ic->ic_scan_start(ic); /* notify driver */ - IEEE80211_LOCK(ic); - - for (;;) { - - scandone = (ss->ss_next >= ss->ss_last) || - (SCAN_PRIVATE(ss)->ss_iflags & ISCAN_CANCEL) != 0; - - IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, - "%s: loop start; scandone=%d\n", - __func__, - scandone); - - if (scandone || (ss->ss_flags & IEEE80211_SCAN_GOTPICK) || - (SCAN_PRIVATE(ss)->ss_iflags & ISCAN_ABORT) || - time_after(ticks + ss->ss_mindwell, scanend)) - break; - - chan = ss->ss_chans[ss->ss_next++]; - - /* - * Watch for truncation due to the scan end time. - */ - if (time_after(ticks + ss->ss_maxdwell, scanend)) - maxdwell = scanend - ticks; - else - maxdwell = ss->ss_maxdwell; - - IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, - "%s: chan %3d%c -> %3d%c [%s, dwell min %lums max %lums]\n", - __func__, - ieee80211_chan2ieee(ic, ic->ic_curchan), - ieee80211_channel_type_char(ic->ic_curchan), - ieee80211_chan2ieee(ic, chan), - ieee80211_channel_type_char(chan), - (ss->ss_flags & IEEE80211_SCAN_ACTIVE) && - (chan->ic_flags & IEEE80211_CHAN_PASSIVE) == 0 ? - "active" : "passive", - ticks_to_msecs(ss->ss_mindwell), ticks_to_msecs(maxdwell)); - - /* - * Potentially change channel and phy mode. - */ - ic->ic_curchan = chan; - ic->ic_rt = ieee80211_get_ratetable(chan); - IEEE80211_UNLOCK(ic); - /* - * Perform the channel change and scan unlocked so the driver - * may sleep. Once set_channel returns the hardware has - * completed the channel change. - */ - ic->ic_set_channel(ic); - ieee80211_radiotap_chan_change(ic); - - /* - * Scan curchan. Drivers for "intelligent hardware" - * override ic_scan_curchan to tell the device to do - * the work. Otherwise we manage the work outselves; - * sending a probe request (as needed), and arming the - * timeout to switch channels after maxdwell ticks. - * - * scan_curchan should only pause for the time required to - * prepare/initiate the hardware for the scan (if at all), the - * below condvar is used to sleep for the channels dwell time - * and allows it to be signalled for abort. - */ - ic->ic_scan_curchan(ss, maxdwell); - IEEE80211_LOCK(ic); - - /* XXX scan state can change! Re-validate scan state! */ - - SCAN_PRIVATE(ss)->ss_chanmindwell = ticks + ss->ss_mindwell; - /* clear mindwell lock and initial channel change flush */ - SCAN_PRIVATE(ss)->ss_iflags &= ~ISCAN_REP; - - if ((SCAN_PRIVATE(ss)->ss_iflags & (ISCAN_CANCEL|ISCAN_ABORT))) - continue; - - IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, "%s: waiting\n", __func__); - /* Wait to be signalled to scan the next channel */ - cv_wait(&SCAN_PRIVATE(ss)->ss_scan_cv, IEEE80211_LOCK_OBJ(ic)); - } - - IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, "%s: out\n", __func__); - - if (SCAN_PRIVATE(ss)->ss_iflags & ISCAN_ABORT) - goto done; - - IEEE80211_UNLOCK(ic); - ic->ic_scan_end(ic); /* notify driver */ - IEEE80211_LOCK(ic); - /* XXX scan state can change! Re-validate scan state! */ - - /* - * Since a cancellation may have occured during one of the - * driver calls (whilst unlocked), update scandone. - */ - if (scandone == 0 && - ((SCAN_PRIVATE(ss)->ss_iflags & ISCAN_CANCEL) != 0)) { - /* XXX printf? */ - if_printf(vap->iv_ifp, - "%s: OOPS! scan cancelled during driver call (1)!\n", - __func__); - scandone = 1; - } - - /* - * Record scan complete time. Note that we also do - * this when canceled so any background scan will - * not be restarted for a while. - */ - if (scandone) - ic->ic_lastscan = ticks; - /* return to the bss channel */ - if (ic->ic_bsschan != IEEE80211_CHAN_ANYC && - ic->ic_curchan != ic->ic_bsschan) { - ieee80211_setupcurchan(ic, ic->ic_bsschan); - IEEE80211_UNLOCK(ic); - ic->ic_set_channel(ic); - ieee80211_radiotap_chan_change(ic); - IEEE80211_LOCK(ic); - } - /* clear internal flags and any indication of a pick */ - SCAN_PRIVATE(ss)->ss_iflags &= ~ISCAN_REP; - ss->ss_flags &= ~IEEE80211_SCAN_GOTPICK; - - /* - * If not canceled and scan completed, do post-processing. - * If the callback function returns 0, then it wants to - * continue/restart scanning. Unfortunately we needed to - * notify the driver to end the scan above to avoid having - * rx frames alter the scan candidate list. - */ - if ((SCAN_PRIVATE(ss)->ss_iflags & ISCAN_CANCEL) == 0 && - !ss->ss_ops->scan_end(ss, vap) && - (ss->ss_flags & IEEE80211_SCAN_ONCE) == 0 && - time_before(ticks + ss->ss_mindwell, scanend)) { - IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, - "%s: done, restart " - "[ticks %u, dwell min %lu scanend %lu]\n", - __func__, - ticks, ss->ss_mindwell, scanend); - ss->ss_next = 0; /* reset to begining */ - if (ss->ss_flags & IEEE80211_SCAN_ACTIVE) - vap->iv_stats.is_scan_active++; - else - vap->iv_stats.is_scan_passive++; - - ss->ss_ops->scan_restart(ss, vap); /* XXX? */ - ieee80211_runtask(ic, &SCAN_PRIVATE(ss)->ss_scan_task); - IEEE80211_UNLOCK(ic); - return; - } - - /* past here, scandone is ``true'' if not in bg mode */ - if ((ss->ss_flags & IEEE80211_SCAN_BGSCAN) == 0) - scandone = 1; - - IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, - "%s: %s, [ticks %u, dwell min %lu scanend %lu]\n", - __func__, scandone ? "done" : "stopped", - ticks, ss->ss_mindwell, scanend); - - /* - * Since a cancellation may have occured during one of the - * driver calls (whilst unlocked), update scandone. - */ - if (scandone == 0 && - ((SCAN_PRIVATE(ss)->ss_iflags & ISCAN_CANCEL) != 0)) { - /* XXX printf? */ - if_printf(vap->iv_ifp, - "%s: OOPS! scan cancelled during driver call (2)!\n", - __func__); - scandone = 1; - } - - /* - * Clear the SCAN bit first in case frames are - * pending on the station power save queue. If - * we defer this then the dispatch of the frames - * may generate a request to cancel scanning. - */ -done: - ic->ic_flags &= ~IEEE80211_F_SCAN; - /* - * Drop out of power save mode when a scan has - * completed. If this scan was prematurely terminated - * because it is a background scan then don't notify - * the ap; we'll either return to scanning after we - * receive the beacon frame or we'll drop out of power - * save mode because the beacon indicates we have frames - * waiting for us. - */ - if (scandone) { - vap->iv_sta_ps(vap, 0); - if (ss->ss_next >= ss->ss_last) { - ieee80211_notify_scan_done(vap); - ic->ic_flags_ext &= ~IEEE80211_FEXT_BGSCAN; - } - } - SCAN_PRIVATE(ss)->ss_iflags &= ~(ISCAN_CANCEL|ISCAN_ABORT); - ss->ss_flags &= ~(IEEE80211_SCAN_ONCE | IEEE80211_SCAN_PICK1ST); - IEEE80211_UNLOCK(ic); -#undef ISCAN_REP -} - -/* - * Process a beacon or probe response frame. - */ -void -ieee80211_swscan_add_scan(struct ieee80211vap *vap, - struct ieee80211_channel *curchan, - const struct ieee80211_scanparams *sp, - const struct ieee80211_frame *wh, - int subtype, int rssi, int noise) -{ - struct ieee80211com *ic = vap->iv_ic; - struct ieee80211_scan_state *ss = ic->ic_scan; - - /* XXX locking */ - /* - * Frames received during startup are discarded to avoid - * using scan state setup on the initial entry to the timer - * callback. This can occur because the device may enable - * rx prior to our doing the initial channel change in the - * timer routine. - */ - if (SCAN_PRIVATE(ss)->ss_iflags & ISCAN_DISCARD) - return; -#ifdef IEEE80211_DEBUG - if (ieee80211_msg_scan(vap) && (ic->ic_flags & IEEE80211_F_SCAN)) - ieee80211_scan_dump_probe_beacon(subtype, 1, wh->i_addr2, sp, rssi); -#endif - if (ss->ss_ops != NULL && - ss->ss_ops->scan_add(ss, curchan, sp, wh, subtype, rssi, noise)) { - /* - * If we've reached the min dwell time terminate - * the timer so we'll switch to the next channel. - */ - if ((SCAN_PRIVATE(ss)->ss_iflags & ISCAN_MINDWELL) == 0 && - time_after_eq(ticks, SCAN_PRIVATE(ss)->ss_chanmindwell)) { - IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, - "%s: chan %3d%c min dwell met (%u > %lu)\n", - __func__, - ieee80211_chan2ieee(ic, ic->ic_curchan), - ieee80211_channel_type_char(ic->ic_curchan), - ticks, SCAN_PRIVATE(ss)->ss_chanmindwell); - SCAN_PRIVATE(ss)->ss_iflags |= ISCAN_MINDWELL; - /* - * NB: trigger at next clock tick or wait for the - * hardware. - */ - ic->ic_scan_mindwell(ss); - } - } -} - diff --git a/sys/net80211/ieee80211_scan_sw.h b/sys/net80211/ieee80211_scan_sw.h deleted file mode 100644 index 7bb0cc3..0000000 --- a/sys/net80211/ieee80211_scan_sw.h +++ /dev/null @@ -1,61 +0,0 @@ -/*- - * Copyright (c) 2015 Adrian Chadd <adrian@FreeBSD.org> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ - */ -#ifndef __NET80211_IEEE80211_SCAN_SW_H__ -#define __NET80211_IEEE80211_SCAN_SW_H__ - -extern void ieee80211_swscan_attach(struct ieee80211com *ic); -extern void ieee80211_swscan_detach(struct ieee80211com *ic); - -extern void ieee80211_swscan_vattach(struct ieee80211vap *vap); -extern void ieee80211_swscan_vdetach(struct ieee80211vap *vap); - -extern int ieee80211_swscan_start_scan(const struct ieee80211_scanner *scan, - struct ieee80211vap *vap, int flags, - u_int duration, u_int mindwell, u_int maxdwell, - u_int nssid, const struct ieee80211_scan_ssid ssids[]); -extern void ieee80211_swscan_set_scan_duration(struct ieee80211vap *vap, - u_int duration); -extern void ieee80211_swscan_run_scan_task(struct ieee80211vap *vap); -extern int ieee80211_swscan_check_scan(const struct ieee80211_scanner *scan, - struct ieee80211vap *vap, int flags, - u_int duration, u_int mindwell, u_int maxdwell, - u_int nssid, const struct ieee80211_scan_ssid ssids[]); -extern int ieee80211_swscan_bg_scan(const struct ieee80211_scanner *scan, - struct ieee80211vap *vap, int flags); -extern void ieee80211_swscan_cancel_scan(struct ieee80211vap *vap); -extern void ieee80211_swscan_cancel_anyscan(struct ieee80211vap *vap); -extern void ieee80211_swscan_scan_next(struct ieee80211vap *vap); -extern void ieee80211_swscan_scan_done(struct ieee80211vap *vap); -extern void ieee80211_swscan_probe_curchan(struct ieee80211vap *vap, - int force); -extern void ieee80211_swscan_add_scan(struct ieee80211vap *vap, - struct ieee80211_channel *curchan, - const struct ieee80211_scanparams *sp, - const struct ieee80211_frame *wh, - int subtype, int rssi, int noise); - -#endif /* __NET80211_IEEE80211_SCAN_SW_H__ */ diff --git a/sys/net80211/ieee80211_sta.c b/sys/net80211/ieee80211_sta.c index 267ad11..8685e4b 100644 --- a/sys/net80211/ieee80211_sta.c +++ b/sys/net80211/ieee80211_sta.c @@ -234,7 +234,6 @@ sta_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) switch (ostate) { case IEEE80211_S_SLEEP: /* XXX wakeup */ - /* XXX driver hook to wakeup the hardware? */ case IEEE80211_S_RUN: IEEE80211_SEND_MGMT(ni, IEEE80211_FC0_SUBTYPE_DISASSOC, @@ -300,18 +299,12 @@ sta_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) if (vap->iv_roaming == IEEE80211_ROAMING_AUTO) ieee80211_check_scan_current(vap); break; - case IEEE80211_S_SLEEP: /* beacon miss */ - /* - * XXX if in sleep we need to wakeup the hardware. - */ - /* FALLTHROUGH */ case IEEE80211_S_RUN: /* beacon miss */ /* * Beacon miss. Notify user space and if not * under control of a user application (roaming * manual) kick off a scan to re-connect. */ - ieee80211_sta_leave(ni); if (vap->iv_roaming == IEEE80211_ROAMING_AUTO) ieee80211_check_scan_current(vap); @@ -410,7 +403,6 @@ sta_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) arg == IEEE80211_FC0_SUBTYPE_ASSOC_RESP); break; case IEEE80211_S_SLEEP: - /* Wake up from sleep */ vap->iv_sta_ps(vap, 0); break; default: @@ -438,11 +430,9 @@ sta_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) ieee80211_node_authorize(ni); /* * Fake association when joining an existing bss. - * - * Don't do this if we're doing SLEEP->RUN. */ - if (ic->ic_newassoc != NULL && ostate != IEEE80211_S_SLEEP) - ic->ic_newassoc(vap->iv_bss, (ostate != IEEE80211_S_RUN)); + if (ic->ic_newassoc != NULL) + ic->ic_newassoc(vap->iv_bss, ostate != IEEE80211_S_RUN); break; case IEEE80211_S_CSA: if (ostate != IEEE80211_S_RUN) @@ -527,6 +517,7 @@ doprint(struct ieee80211vap *vap, int subtype) static int sta_input(struct ieee80211_node *ni, struct mbuf *m, int rssi, int nf) { +#define HAS_SEQ(type) ((type & 0x4) == 0) struct ieee80211vap *vap = ni->ni_vap; struct ieee80211com *ic = ni->ni_ic; struct ifnet *ifp = vap->iv_ifp; @@ -622,8 +613,7 @@ sta_input(struct ieee80211_node *ni, struct mbuf *m, int rssi, int nf) IEEE80211_RSSI_LPF(ni->ni_avgrssi, rssi); ni->ni_noise = nf; - if ( IEEE80211_HAS_SEQ(type, subtype) && - !IEEE80211_IS_MULTICAST(wh->i_addr1)) { + if (HAS_SEQ(type) && !IEEE80211_IS_MULTICAST(wh->i_addr1)) { uint8_t tid = ieee80211_gettid(wh); if (IEEE80211_QOS_HAS_SEQ(wh) && TID_TO_WME_AC(tid) >= WME_AC_VI) @@ -938,7 +928,7 @@ sta_input(struct ieee80211_node *ni, struct mbuf *m, int rssi, int nf) break; } err: - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + ifp->if_ierrors++; out: if (m != NULL) { if (need_tap && ieee80211_radiotap_active_vap(vap)) @@ -1322,7 +1312,6 @@ sta_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0, vap->iv_stats.is_beacon_bad++; return; } - /* * Count frame now that we know it's to be processed. */ @@ -1392,66 +1381,25 @@ sta_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0, } if (scan.quiet) ic->ic_set_quiet(ni, scan.quiet); - if (scan.tim != NULL) { struct ieee80211_tim_ie *tim = (struct ieee80211_tim_ie *) scan.tim; - /* - * XXX Check/debug this code; see if it's about - * the right time to force the VAP awake if we - * receive a frame destined for us? - */ +#if 0 int aid = IEEE80211_AID(ni->ni_associd); int ix = aid / NBBY; int min = tim->tim_bitctl &~ 1; int max = tim->tim_len + min - 4; - int tim_ucast = 0, tim_mcast = 0; - - /* - * Only do this for unicast traffic in the TIM - * The multicast traffic notification for - * the scan notification stuff should occur - * differently. - */ - if (min <= ix && ix <= max && - isset(tim->tim_bitmap - min, aid)) { - tim_ucast = 1; - } - - /* - * Do a separate notification - * for the multicast bit being set. - */ - if (tim->tim_bitctl & 1) { - tim_mcast = 1; - } - - /* - * If the TIM indicates there's traffic for - * us then get us out of STA mode powersave. - */ - if (tim_ucast == 1) { - - /* - * Wake us out of SLEEP state if we're - * in it; and if we're doing bgscan - * then wake us out of STA powersave. - */ - ieee80211_sta_tim_notify(vap, 1); - - /* - * This is preventing us from - * continuing a bgscan; because it - * tricks the contbgscan() - * routine to think there's always - * traffic for us. - * - * I think we need both an RX and - * TX ic_lastdata field. + if ((tim->tim_bitctl&1) || + (min <= ix && ix <= max && + isset(tim->tim_bitmap - min, aid))) { + /* + * XXX Do not let bg scan kick off + * we are expecting data. */ ic->ic_lastdata = ticks; + vap->iv_sta_ps(vap, 0); } - +#endif ni->ni_dtim_count = tim->tim_count; ni->ni_dtim_period = tim->tim_period; } @@ -1484,8 +1432,8 @@ 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, - &scan, wh, subtype, rssi, nf); + ieee80211_add_scan(vap, &scan, wh, + subtype, rssi, nf); } else if (contbgscan(vap)) { ieee80211_bg_scan(vap, 0); } else if (startbgscan(vap)) { @@ -1498,14 +1446,6 @@ sta_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0, } /* - * Put the station to sleep if we haven't seen - * traffic in a while. - */ - IEEE80211_LOCK(ic); - ieee80211_sta_ps_timer_check(vap); - IEEE80211_UNLOCK(ic); - - /* * If we've had a channel width change (eg HT20<->HT40) * then schedule a delayed driver notification. */ @@ -1529,8 +1469,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, - subtype, rssi, nf); + ieee80211_add_scan(vap, &scan, wh, subtype, rssi, nf); return; } break; diff --git a/sys/net80211/ieee80211_superg.c b/sys/net80211/ieee80211_superg.c index 81a4b43..461b5a1 100644 --- a/sys/net80211/ieee80211_superg.c +++ b/sys/net80211/ieee80211_superg.c @@ -38,12 +38,11 @@ __FBSDID("$FreeBSD$"); #include <sys/socket.h> +#include <net/bpf.h> +#include <net/ethernet.h> #include <net/if.h> -#include <net/if_var.h> #include <net/if_llc.h> #include <net/if_media.h> -#include <net/bpf.h> -#include <net/ethernet.h> #include <net80211/ieee80211_var.h> #include <net80211/ieee80211_input.h> @@ -480,7 +479,7 @@ ff_transmit(struct ieee80211_node *ni, struct mbuf *m) /* NB: IFQ_HANDOFF reclaims mbuf */ ieee80211_free_node(ni); } else { - if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); + ifp->if_opackets++; } } else ieee80211_free_node(ni); diff --git a/sys/net80211/ieee80211_var.h b/sys/net80211/ieee80211_var.h index 4710697..174fabc 100644 --- a/sys/net80211/ieee80211_var.h +++ b/sys/net80211/ieee80211_var.h @@ -629,7 +629,6 @@ MALLOC_DECLARE(M_80211_VAP); #define IEEE80211_C_MONITOR 0x00010000 /* CAPABILITY: monitor mode */ #define IEEE80211_C_DFS 0x00020000 /* CAPABILITY: DFS/radar avail*/ #define IEEE80211_C_MBSS 0x00040000 /* CAPABILITY: MBSS available */ -#define IEEE80211_C_SWSLEEP 0x00080000 /* CAPABILITY: do sleep here */ /* 0x7c0000 available */ #define IEEE80211_C_WPA1 0x00800000 /* CAPABILITY: WPA1 avail */ #define IEEE80211_C_WPA2 0x01000000 /* CAPABILITY: WPA2 avail */ @@ -711,7 +710,6 @@ 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 *, const uint8_t addr[IEEE80211_ADDR_LEN]); -char ieee80211_channel_type_char(const struct ieee80211_channel *c); void ieee80211_radiotap_attach(struct ieee80211com *, struct ieee80211_radiotap_header *th, int tlen, diff --git a/sys/net80211/ieee80211_wds.c b/sys/net80211/ieee80211_wds.c index fc77259..d95b45f 100644 --- a/sys/net80211/ieee80211_wds.c +++ b/sys/net80211/ieee80211_wds.c @@ -48,7 +48,6 @@ __FBSDID("$FreeBSD$"); #include <sys/sysctl.h> #include <net/if.h> -#include <net/if_var.h> #include <net/if_media.h> #include <net/if_llc.h> #include <net/ethernet.h> @@ -258,14 +257,14 @@ ieee80211_dwds_mcast(struct ieee80211vap *vap0, struct mbuf *m) */ mcopy = m_copypacket(m, M_NOWAIT); if (mcopy == NULL) { - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; /* XXX stat + msg */ continue; } ni = ieee80211_find_txnode(vap, eh->ether_dhost); if (ni == NULL) { /* NB: ieee80211_find_txnode does stat+msg */ - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; m_freem(mcopy); continue; } @@ -276,7 +275,7 @@ ieee80211_dwds_mcast(struct ieee80211vap *vap0, struct mbuf *m) eh->ether_dhost, NULL, "%s", "classification failure"); vap->iv_stats.is_tx_classify++; - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; m_freem(mcopy); ieee80211_free_node(ni); continue; @@ -299,10 +298,10 @@ ieee80211_dwds_mcast(struct ieee80211vap *vap0, struct mbuf *m) err = ieee80211_parent_xmitpkt(ic, mcopy); if (err) { /* NB: IFQ_HANDOFF reclaims mbuf */ - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; ieee80211_free_node(ni); } else { - if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); + ifp->if_opackets++; if_inc_counter(ifp, IFCOUNTER_OMCASTS, 1); if_inc_counter(ifp, IFCOUNTER_OBYTES, m->m_pkthdr.len); @@ -410,6 +409,7 @@ wds_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) static int wds_input(struct ieee80211_node *ni, struct mbuf *m, int rssi, int nf) { +#define HAS_SEQ(type) ((type & 0x4) == 0) struct ieee80211vap *vap = ni->ni_vap; struct ieee80211com *ic = ni->ni_ic; struct ifnet *ifp = vap->iv_ifp; @@ -491,7 +491,7 @@ wds_input(struct ieee80211_node *ni, struct mbuf *m, int rssi, int nf) } IEEE80211_RSSI_LPF(ni->ni_avgrssi, rssi); ni->ni_noise = nf; - if (IEEE80211_HAS_SEQ(type, subtype)) { + if (HAS_SEQ(type)) { uint8_t tid = ieee80211_gettid(wh); if (IEEE80211_QOS_HAS_SEQ(wh) && TID_TO_WME_AC(tid) >= WME_AC_VI) @@ -733,7 +733,7 @@ wds_input(struct ieee80211_node *ni, struct mbuf *m, int rssi, int nf) break; } err: - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + ifp->if_ierrors++; out: if (m != NULL) { if (need_tap && ieee80211_radiotap_active_vap(vap)) |