Date: Mon, 8 Nov 2004 19:07:22 GMT From: Sam Leffler <sam@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 64628 for review Message-ID: <200411081907.iA8J7MMM045141@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=64628 Change 64628 by sam@sam_ebb on 2004/11/08 19:07:05 checkpoint node table rewrite; works for station mode Affected files ... .. //depot/projects/wifi/sys/dev/ath/if_ath.c#13 edit .. //depot/projects/wifi/sys/dev/ath/if_athvar.h#5 edit .. //depot/projects/wifi/sys/dev/awi/awi.c#3 edit .. //depot/projects/wifi/sys/dev/wi/if_wi.c#4 edit .. //depot/projects/wifi/sys/net80211/ieee80211.c#3 edit .. //depot/projects/wifi/sys/net80211/ieee80211_freebsd.h#3 edit .. //depot/projects/wifi/sys/net80211/ieee80211_input.c#10 edit .. //depot/projects/wifi/sys/net80211/ieee80211_ioctl.c#10 edit .. //depot/projects/wifi/sys/net80211/ieee80211_node.c#8 edit .. //depot/projects/wifi/sys/net80211/ieee80211_node.h#7 edit .. //depot/projects/wifi/sys/net80211/ieee80211_output.c#7 edit .. //depot/projects/wifi/sys/net80211/ieee80211_proto.c#4 edit .. //depot/projects/wifi/sys/net80211/ieee80211_var.h#6 edit Differences ... ==== //depot/projects/wifi/sys/dev/ath/if_ath.c#13 (text+ko) ==== @@ -124,12 +124,9 @@ static void ath_beacon_config(struct ath_softc *); static int ath_desc_alloc(struct ath_softc *); static void ath_desc_free(struct ath_softc *); -static struct ieee80211_node *ath_node_alloc(struct ieee80211com *); -static void ath_node_cleanup(struct ieee80211com *, struct ieee80211_node*); -static void ath_node_copy(struct ieee80211com *, - struct ieee80211_node *, const struct ieee80211_node *); -static u_int8_t ath_node_getrssi(struct ieee80211com *, - struct ieee80211_node *); +static struct ieee80211_node *ath_node_alloc(struct ieee80211_node_table *); +static void ath_node_free(struct ieee80211_node *); +static u_int8_t ath_node_getrssi(const struct ieee80211_node *); static int ath_rxbuf_init(struct ath_softc *, struct ath_buf *); static void ath_recv_mgmt(struct ieee80211com *ic, struct mbuf *m, struct ieee80211_node *ni, @@ -509,10 +506,8 @@ ieee80211_ifattach(ic); /* override default methods */ ic->ic_node_alloc = ath_node_alloc; - sc->sc_node_cleanup = ic->ic_node_cleanup; - ic->ic_node_cleanup = ath_node_cleanup; - sc->sc_node_copy = ic->ic_node_copy; - ic->ic_node_copy = ath_node_copy; + sc->sc_node_free = ic->ic_node_free; + ic->ic_node_free = ath_node_free; ic->ic_node_getrssi = ath_node_getrssi; sc->sc_recv_mgmt = ic->ic_recv_mgmt; ic->ic_recv_mgmt = ath_recv_mgmt; @@ -1087,8 +1082,8 @@ STAILQ_INSERT_TAIL(&sc->sc_txbuf, bf, bf_list); ATH_TXBUF_UNLOCK(sc); ifp->if_oerrors++; - if (ni && ni != ic->ic_bss) - ieee80211_free_node(ic, ni); + if (ni != NULL) + ieee80211_free_node(ni); continue; } @@ -2038,8 +2033,9 @@ } static struct ieee80211_node * -ath_node_alloc(struct ieee80211com *ic) +ath_node_alloc(struct ieee80211_node_table *nt) { + struct ieee80211com *ic = nt->nt_ic; struct ath_softc *sc = ic->ic_ifp->if_softc; const size_t space = sizeof(struct ath_node) + sc->sc_rc->arc_space; struct ath_node *an; @@ -2072,57 +2068,39 @@ ATH_TXQ_LOCK(txq); STAILQ_FOREACH(bf, &txq->axq_q, bf_list) { if (bf->bf_node == ni) { - bf->bf_node = NULL; - if (ni != ic->ic_bss) - /* NB: cannot use ieee80211_unref_node */ - ieee80211_node_decref(ni); + /* NB: this clears the pointer too */ + ieee80211_unref_node(&bf->bf_node); } } ATH_TXQ_UNLOCK(txq); } static void -ath_node_cleanup(struct ieee80211com *ic, struct ieee80211_node *ni) +ath_node_free(struct ieee80211_node *ni) { + struct ieee80211com *ic = ni->ni_ic; struct ath_softc *sc = ic->ic_ifp->if_softc; int i; DPRINTF(sc, ATH_DEBUG_NODE, "%s: ni %p\n", __func__, ni); + /* XXX can this happen since refcnt must be zero for us to be called? */ for (i = 0; i < HAL_NUM_TX_QUEUES; i++) if (ATH_TXQ_SETUP(sc, i)) ath_tx_cleanq(ic, &sc->sc_txq[i], ni); ath_rate_node_cleanup(sc, ATH_NODE(ni)); - sc->sc_node_cleanup(ic, ni); + sc->sc_node_free(ni); } -static void -ath_node_copy(struct ieee80211com *ic, - struct ieee80211_node *dst, const struct ieee80211_node *src) -{ - struct ath_softc *sc = ic->ic_ifp->if_softc; - const struct ath_node *an = (const struct ath_node *)src; - - DPRINTF(sc, ATH_DEBUG_NODE, "%s: dst %p src %p\n", __func__, dst, src); - - /* - * NB: Must copy first so the cleanup done by node_copy is - * done before we copy bits around below. - */ - sc->sc_node_copy(ic, dst, src); - memcpy(&dst[1], &src[1], - sizeof(struct ath_node) - sizeof(struct ieee80211_node)); - ath_rate_node_copy(sc, ATH_NODE(dst), an); -} - static u_int8_t -ath_node_getrssi(struct ieee80211com *ic, struct ieee80211_node *ni) +ath_node_getrssi(const struct ieee80211_node *ni) { #define HAL_EP_RND(x, mul) \ ((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul)) + u_int32_t avgrssi = ATH_NODE_CONST(ni)->an_avgrssi; int32_t rssi; - rssi = HAL_EP_RND(ATH_NODE(ni)->an_avgrssi, HAL_RSSI_EP_MULTIPLIER); + rssi = HAL_EP_RND(avgrssi, HAL_RSSI_EP_MULTIPLIER); /* NB: theoretically we shouldn't need this, but be paranoid */ return rssi < 0 ? 0 : rssi > 127 ? 127 : rssi; #undef HAL_EP_RND @@ -2245,8 +2223,6 @@ #define PA2DESC(_sc, _pa) \ ((struct ath_desc *)((caddr_t)(_sc)->sc_desc + \ ((_pa) - (_sc)->sc_desc_paddr))) -#define IS_CTL(wh) \ - ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_CTL) struct ath_softc *sc = arg; struct ath_buf *bf; struct ieee80211com *ic = &sc->sc_ic; @@ -2432,24 +2408,10 @@ /* * Locate the node for sender, track state, and then * pass the (referenced) node up to the 802.11 layer - * for its use. We are required to pass some node so - * we fall back to ic_bss when this frame is from an - * unknown sender. The 802.11 layer knows this means the - * sender wasn't in the node table and acts accordingly. - * Note also that by convention we do not reference - * count ic_bss, only other nodes (ic_bss is never free'd). + * for its use. */ - if (ic->ic_opmode != IEEE80211_M_STA) { - struct ieee80211_frame_min *wh = - mtod(m, struct ieee80211_frame_min *); - if (IS_CTL(wh)) - ni = ieee80211_find_node(ic, wh->i_addr1); - else - ni = ieee80211_find_node(ic, wh->i_addr2); - if (ni == NULL) - ni = ic->ic_bss; - } else - ni = ic->ic_bss; + ni = ieee80211_find_rxnode(ic, + mtod(m, const struct ieee80211_frame_min *)); /* * Track rx rssi and do any rx antenna management. @@ -2479,8 +2441,7 @@ /* * Reclaim node reference. */ - if (ni != ic->ic_bss) - ieee80211_free_node(ic, ni); + ieee80211_free_node(ni); rx_next: STAILQ_INSERT_TAIL(&sc->sc_rxbuf, bf, bf_list); } while (ath_rxbuf_init(sc, bf) == 0); @@ -2489,7 +2450,6 @@ ath_hal_rxmonitor(ah, &ATH_NODE(ic->ic_bss)->an_halstats); NET_UNLOCK_GIANT(); /* XXX */ -#undef IS_CTL #undef PA2DESC } @@ -2980,7 +2940,6 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) { - struct ieee80211com *ic = &sc->sc_ic; struct ath_hal *ah = sc->sc_ah; struct ath_buf *bf; struct ath_desc *ds; @@ -3050,8 +3009,7 @@ * this is a DEAUTH message that was sent and the * node was timed out due to inactivity. */ - if (ni != ic->ic_bss) - ieee80211_free_node(ic, ni); + ieee80211_free_node(ni); } bus_dmamap_sync(sc->sc_dmat, bf->bf_dmamap, BUS_DMASYNC_POSTWRITE); @@ -3135,7 +3093,6 @@ ath_tx_draintxq(struct ath_softc *sc, struct ath_txq *txq) { struct ath_hal *ah = sc->sc_ah; - struct ieee80211com *ic = &sc->sc_ic; struct ieee80211_node *ni; struct ath_buf *bf; @@ -3163,11 +3120,11 @@ bf->bf_m = NULL; ni = bf->bf_node; bf->bf_node = NULL; - if (ni != NULL && ni != ic->ic_bss) { + if (ni != NULL) { /* * Reclaim node reference. */ - ieee80211_free_node(ic, ni); + ieee80211_free_node(ni); } ATH_TXBUF_LOCK(sc); STAILQ_INSERT_TAIL(&sc->sc_txbuf, bf, bf_list); ==== //depot/projects/wifi/sys/dev/ath/if_athvar.h#5 (text+ko) ==== @@ -67,6 +67,7 @@ /* variable-length rate control state follows */ }; #define ATH_NODE(ni) ((struct ath_node *)(ni)) +#define ATH_NODE_CONST(ni) ((const struct ath_node *)(ni)) #define ATH_RSSI_LPF_LEN 10 #define ATH_RSSI_DUMMY_MARKER 0x127 @@ -140,11 +141,7 @@ int, int, u_int32_t); int (*sc_newstate)(struct ieee80211com *, enum ieee80211_state, int); - void (*sc_node_cleanup)(struct ieee80211com *, - struct ieee80211_node *); - void (*sc_node_copy)(struct ieee80211com *, - struct ieee80211_node *, - const struct ieee80211_node *); + void (*sc_node_free)(struct ieee80211_node *); device_t sc_dev; bus_space_tag_t sc_st; /* bus space tag */ bus_space_handle_t sc_sh; /* bus space handle */ ==== //depot/projects/wifi/sys/dev/awi/awi.c#3 (text+ko) ==== @@ -663,7 +663,7 @@ ni->ni_intval = ic->ic_lintval; ni->ni_rssi = 0; ni->ni_rstamp = 0; - memset(ni->ni_tstamp, 0, sizeof(ni->ni_tstamp)); + memset(&ni->ni_tstamp, 0, sizeof(ni->ni_tstamp)); ni->ni_rates = ic->ic_sup_rates[ieee80211_chan2mode(ic, ni->ni_chan)]; IEEE80211_ADDR_COPY(ni->ni_macaddr, ic->ic_myaddr); @@ -802,7 +802,7 @@ ifp->if_oerrors++; continue; } - if (ni != NULL && ni != ic->ic_bss) + if (ni != NULL) ieee80211_free_node(ic, ni); wh = mtod(m0, struct ieee80211_frame *); if (!IEEE80211_IS_MULTICAST(wh->i_addr1) && @@ -826,7 +826,7 @@ k = ieee80211_crypto_encap(ic, ni, m0); if (k == NULL) { - if (ni && ni != ic->ic_bss) + if (ni != NULL) ieee80211_free_node(ic, ni); continue; } @@ -1175,7 +1175,6 @@ { struct ieee80211com *ic = &sc->sc_ic; struct ifnet *ifp = &sc->sc_if; - struct ieee80211_frame *wh; struct ieee80211_node *ni; u_int8_t state, rate, rssi; u_int16_t len; @@ -1220,33 +1219,16 @@ sc->sc_adhoc_ap) m = awi_ether_modcap(sc, m); else - m = m_pullup(m, sizeof(*wh)); + m = m_pullup(m, + sizeof(struct ieee80211_frame_min)); if (m == NULL) { ifp->if_ierrors++; goto rx_next; } - wh = mtod(m, struct ieee80211_frame *); -#ifdef __NetBSD__ - ni = ieee80211_find_rxnode(ic, wh); -#else - if (ic->ic_opmode != IEEE80211_M_STA) { - ni = ieee80211_find_node(ic, - wh->i_addr2); - if (ni == NULL) - ni = ic->ic_bss; - } else - ni = ic->ic_bss; -#endif + ni = ieee80211_find_rxnode(ic, + mtod(m, struct ieee80211_frame_min *)); ieee80211_input(ic, m, ni, rssi, rstamp); - /* - * The frame may have caused the - * node to be marked for reclamation - * (e.g. in response to a DEAUTH - * message) so use free_node here - * instead of unref_node. - */ - if (ni != ic->ic_bss) - ieee80211_free_node(ic, ni); + ieee80211_free_node(ic, ni); } else sc->sc_rxpend = m; rx_next: @@ -2048,14 +2030,14 @@ awi_write_2(sc, AWI_CA_SYNC_DWELL, 0); } if (ic->ic_flags & IEEE80211_F_SIBSS) { - memset(ni->ni_tstamp, 0, sizeof(ni->ni_tstamp)); + memset(&ni->ni_tstamp, 0, sizeof(ni->ni_tstamp)); ni->ni_rstamp = 0; awi_write_1(sc, AWI_CA_SYNC_STARTBSS, 1); } else awi_write_1(sc, AWI_CA_SYNC_STARTBSS, 0); awi_write_2(sc, AWI_CA_SYNC_MBZ, 0); awi_write_bytes(sc, AWI_CA_SYNC_TIMESTAMP, - ni->ni_tstamp, 8); + ni->ni_tstamp.data, 8); awi_write_4(sc, AWI_CA_SYNC_REFTIME, ni->ni_rstamp); sc->sc_cur_chan = ieee80211_chan2ieee(ic, ni->ni_chan); if ((error = awi_cmd(sc, AWI_CMD_SYNC, AWI_NOWAIT)) ==== //depot/projects/wifi/sys/dev/wi/if_wi.c#4 (text+ko) ==== @@ -941,8 +941,8 @@ k = ieee80211_crypto_encap(ic, ni, m0); if (k == NULL) { - if (ni && ni != ic->ic_bss) - ieee80211_free_node(ic, ni); + if (ni != NULL) + ieee80211_free_node(ni); continue; } if (k->wk_flags & IEEE80211_KEY_SWCRYPT) @@ -967,8 +967,8 @@ error = wi_write_bap(sc, fid, 0, &frmhdr, sizeof(frmhdr)) != 0 || wi_mwrite_bap(sc, fid, off, m0, m0->m_pkthdr.len) != 0; m_freem(m0); - if (ni && ni != ic->ic_bss) - ieee80211_free_node(ic, ni); + if (ni != NULL) + ieee80211_free_node(ni); if (error) { ifp->if_oerrors++; continue; @@ -1513,16 +1513,9 @@ /* * Locate the node for sender, track state, and * then pass this node (referenced) up to the 802.11 - * layer for its use. We are required to pass - * something so we fallback to ic_bss when this frame - * is from an unknown sender. + * layer for its use. */ - if (ic->ic_opmode != IEEE80211_M_STA) { - ni = ieee80211_find_node(ic, wh->i_addr2); - if (ni == NULL) - ni = ic->ic_bss; - } else - ni = ic->ic_bss; + ni = ieee80211_find_rxnode(ic, wh); /* * Send frame up for processing. */ @@ -1532,8 +1525,7 @@ * reclamation (e.g. in response to a DEAUTH message) * so use free_node here instead of unref_node. */ - if (ni != ic->ic_bss) - ieee80211_free_node(ic, ni); + ieee80211_free_node(ni); } static void ==== //depot/projects/wifi/sys/net80211/ieee80211.c#3 (text+ko) ==== @@ -653,15 +653,26 @@ void ieee80211_watchdog(struct ieee80211com *ic) { + struct ieee80211_node_table *nt; + int need_inact_timer = 0; if (ic->ic_state != IEEE80211_S_INIT) { if (ic->ic_mgt_timer && --ic->ic_mgt_timer == 0) ieee80211_new_state(ic, IEEE80211_S_SCAN, 0); - if (ic->ic_inact_timer && --ic->ic_inact_timer == 0) - ieee80211_timeout_nodes(ic); + nt = &ic->ic_scan; + if (nt->nt_inact_timer) { + if (--nt->nt_inact_timer == 0) + nt->nt_timeout(nt); + need_inact_timer += nt->nt_inact_timer; + } + nt = ic->ic_sta; + if (nt != NULL && nt->nt_inact_timer) { + if (--nt->nt_inact_timer == 0) + nt->nt_timeout(nt); + need_inact_timer += nt->nt_inact_timer; + } } - - if (ic->ic_mgt_timer != 0 || ic->ic_inact_timer != 0) + if (ic->ic_mgt_timer != 0 || need_inact_timer) ic->ic_ifp->if_timer = 1; } ==== //depot/projects/wifi/sys/net80211/ieee80211_freebsd.h#3 (text+ko) ==== @@ -33,13 +33,13 @@ * Node locking definitions. */ typedef struct mtx ieee80211_node_lock_t; -#define IEEE80211_NODE_LOCK_INIT(_ic, _name) \ - mtx_init(&(_ic)->ic_nodelock, _name, "802.11 node table", MTX_DEF) -#define IEEE80211_NODE_LOCK_DESTROY(_ic) mtx_destroy(&(_ic)->ic_nodelock) -#define IEEE80211_NODE_LOCK(_ic) mtx_lock(&(_ic)->ic_nodelock) -#define IEEE80211_NODE_UNLOCK(_ic) mtx_unlock(&(_ic)->ic_nodelock) -#define IEEE80211_NODE_LOCK_ASSERT(_ic) \ - mtx_assert(&(_ic)->ic_nodelock, MA_OWNED) +#define IEEE80211_NODE_LOCK_INIT(_nt, _name) \ + mtx_init(&(_nt)->nt_nodelock, _name, "802.11 node table", MTX_DEF) +#define IEEE80211_NODE_LOCK_DESTROY(_nt) mtx_destroy(&(_nt)->nt_nodelock) +#define IEEE80211_NODE_LOCK(_nt) mtx_lock(&(_nt)->nt_nodelock) +#define IEEE80211_NODE_UNLOCK(_nt) mtx_unlock(&(_nt)->nt_nodelock) +#define IEEE80211_NODE_LOCK_ASSERT(_nt) \ + mtx_assert(&(_nt)->nt_nodelock, MA_OWNED) /* * 802.1x MAC ACL database locking definitions. ==== //depot/projects/wifi/sys/net80211/ieee80211_input.c#10 (text+ko) ==== @@ -246,7 +246,7 @@ if ((wh->i_fc[1] & IEEE80211_FC1_PWR_MGT) == 0) { /* turn off power save mode, dequeue stored packets */ ni->ni_flags &= ~IEEE80211_NODE_PWR_MGT; - (*ic->ic_set_tim)(ic, ni->ni_associd, 0); + ic->ic_set_tim(ic, ni->ni_associd, 0); while (!_IF_QLEN(&ni->ni_savedq) != 0) { struct mbuf *m0; _IF_DEQUEUE(&ni->ni_savedq, m0); @@ -351,12 +351,12 @@ "[%s] discard data from unknown src\n", ether_sprintf(wh->i_addr2)); /* NB: caller deals with reference */ - ni = ieee80211_dup_bss(ic, wh->i_addr2); + ni = ieee80211_dup_bss(ic->ic_sta, wh->i_addr2); if (ni != NULL) { IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_DEAUTH, IEEE80211_REASON_NOT_AUTHED); - ieee80211_free_node(ic, ni); + ieee80211_free_node(ni); } ic->ic_stats.is_rx_notassoc++; goto err; @@ -502,14 +502,16 @@ /* XXX this dups work done in ieee80211_encap */ /* check if destination is associated */ struct ieee80211_node *ni1 = - ieee80211_find_node(ic, eh->ether_dhost); + ieee80211_find_node(ic->ic_sta, + eh->ether_dhost); if (ni1 != NULL) { + /* XXX check if authorized */ if (ni1->ni_associd != 0) { m1 = m; m = NULL; } /* XXX statistic? */ - ieee80211_free_node(ic, ni1); + ieee80211_free_node(ni1); } } if (m1 != NULL) { @@ -648,10 +650,23 @@ /* * Remove frag to insure it doesn't get reaped by timer. */ - IEEE80211_NODE_LOCK(ic); + if (ni->ni_table == NULL) { + /* + * Should never happen. If the node is orphaned (not in + * the table) then input packets should not reach here. + * Otherwise, a concurrent request that yanks the table + * should be blocked by other interlocking and/or by first + * shutting the driver down. Regardless, be defensive + * here and just bail + */ + /* XXX need msg+stat */ + m_freem(m); + return NULL; + } + IEEE80211_NODE_LOCK(ni->ni_table); mfrag = ni->ni_rxfrag[0]; ni->ni_rxfrag[0] = NULL; - IEEE80211_NODE_UNLOCK(ic); + IEEE80211_NODE_UNLOCK(ni->ni_table); /* * Validate new fragment is in order and @@ -860,7 +875,7 @@ } /* always accept open authentication requests */ if (ni == ic->ic_bss) { - ni = ieee80211_dup_bss(ic, wh->i_addr2); + ni = ieee80211_dup_bss(ic->ic_sta, wh->i_addr2); if (ni == NULL) return; allocbs = 1; @@ -1006,7 +1021,7 @@ switch (seq) { case IEEE80211_AUTH_SHARED_REQUEST: if (ni == ic->ic_bss) { - ni = ieee80211_dup_bss(ic, wh->i_addr2); + ni = ieee80211_dup_bss(ic->ic_sta, wh->i_addr2); if (ni == NULL) { /* NB: no way to return an error */ return; @@ -1583,7 +1598,7 @@ #define ISREASSOC(_st) ((_st) == IEEE80211_FC0_SUBTYPE_REASSOC_RESP) struct ieee80211_frame *wh; u_int8_t *frm, *efrm; - u_int8_t *ssid, *rates, *xrates, *wpa; + u_int8_t *ssid, *rates, *xrates, *wpa, *wme; int reassoc, resp, allocbs; wh = mtod(m0, struct ieee80211_frame *); @@ -1592,7 +1607,7 @@ switch (subtype) { case IEEE80211_FC0_SUBTYPE_PROBE_RESP: case IEEE80211_FC0_SUBTYPE_BEACON: { - u_int8_t *tstamp, *country, *wpa, *wme; + u_int8_t *tstamp, *country; u_int8_t chan, bchan, fhindex, erp; u_int16_t capinfo, bintval, timoff; u_int16_t fhdwell; @@ -1779,57 +1794,51 @@ ni->ni_capinfo = capinfo; /* XXX statistic */ } + ni->ni_inact = ic->ic_inact_run; return; } - /* - * Use mac and channel for lookup so we collect all - * potential AP's when scanning. Otherwise we may - * see the same AP on multiple channels and will only - * record the last one. We could filter APs here based - * on rssi, etc. but leave that to the end of the scan - * so we can keep the selection criteria in one spot. - * This may result in a bloat of the scanned AP list but - * it shouldn't be too much. - */ - ni = ieee80211_find_node_with_channel(ic, wh->i_addr2, - &ic->ic_channels[chan]); - if (ni == NULL) { + if (ni == ic->ic_bss) { #ifdef IEEE80211_DEBUG if (ieee80211_msg_scan(ic)) dump_probe_beacon(subtype, 1, wh->i_addr2, chan, bchan, capinfo, bintval, erp, ssid, country); #endif - ni = ieee80211_dup_bss(ic, wh->i_addr2); + ni = ieee80211_dup_bss(&ic->ic_scan, wh->i_addr2); if (ni == NULL) return; ni->ni_esslen = ssid[1]; memset(ni->ni_essid, 0, sizeof(ni->ni_essid)); memcpy(ni->ni_essid, ssid + 2, ssid[1]); - } else if (ssid[1] != 0 && - (ISPROBE(subtype) || ni->ni_esslen == 0)) { - /* - * Update ESSID at probe response to adopt hidden AP by - * Lucent/Cisco, which announces null ESSID in beacon. - */ - ni->ni_esslen = ssid[1]; - memset(ni->ni_essid, 0, sizeof(ni->ni_essid)); - memcpy(ni->ni_essid, ssid + 2, ssid[1]); + } else { + ni->ni_inact = ic->ic_inact_run; /* XXX? */ + if (ssid[1] != 0 && + (ISPROBE(subtype) || ni->ni_esslen == 0)) { + /* + * Update ESSID at probe response to adopt + * hidden AP by Lucent/Cisco, which announces + * null ESSID in beacon. + */ #ifdef IEEE80211_DEBUG - if (ieee80211_msg_scan(ic) || ieee80211_msg_debug(ic)) - dump_probe_beacon(subtype, 0, - wh->i_addr2, chan, bchan, capinfo, - bintval, erp, ssid, country); + if (ieee80211_msg_scan(ic) || + ieee80211_msg_debug(ic)) + dump_probe_beacon(subtype, 0, + wh->i_addr2, chan, bchan, capinfo, + bintval, erp, ssid, country); #endif + ni->ni_esslen = ssid[1]; + memset(ni->ni_essid, 0, sizeof(ni->ni_essid)); + memcpy(ni->ni_essid, ssid + 2, ssid[1]); + } } + ni->ni_scangen = ic->ic_scan.nt_scangen; IEEE80211_ADDR_COPY(ni->ni_bssid, wh->i_addr3); ni->ni_rssi = rssi; ni->ni_rstamp = rstamp; memcpy(ni->ni_tstamp.data, tstamp, sizeof(ni->ni_tstamp)); ni->ni_intval = bintval; ni->ni_capinfo = capinfo; - /* XXX validate channel # */ ni->ni_chan = &ic->ic_channels[chan]; ni->ni_fhdwell = fhdwell; ni->ni_fhindex = fhindex; @@ -1851,25 +1860,6 @@ ieee80211_saveie(&ni->ni_wpa_ie, wpa); /* NB: must be after ni_chan is setup */ ieee80211_setup_rates(ic, ni, rates, xrates, IEEE80211_F_DOSORT); - ieee80211_unref_node(&ni); /* NB: do not free */ -#if 0 - if (ic->ic_state == IEEE80211_S_SCAN) - ieee80211_unref_node(&ni); /* NB: do not free */ - else if (ic->ic_opmode == IEEE80211_M_IBSS && - allocbs && isprobe) { - /* - * Fake an association so the driver can setup it's - * private state. The rate set has been setup above; - * there is no handshake as in ap/station operation. - */ - if (ic->ic_newassoc) - (*ic->ic_newassoc)(ic, ni, 1); - /* NB: hold reference */ - } else { - /* XXX optimize to avoid work done above */ - ieee80211_free_node(ic, ni); - } -#endif break; } @@ -1908,7 +1898,7 @@ IEEE80211_VERIFY_SSID(ic->ic_bss, ssid, "probe"); if (ni == ic->ic_bss) { - ni = ieee80211_dup_bss(ic, wh->i_addr2); + ni = ieee80211_dup_bss(ic->ic_sta, wh->i_addr2); if (ni == NULL) return; IEEE80211_DPRINTF(ic, IEEE80211_MSG_ASSOC, @@ -1926,21 +1916,12 @@ IEEE80211_DPRINTF(ic, IEEE80211_MSG_XRATE, "%s: rate negotiation failed: %s\n", __func__,ether_sprintf(wh->i_addr2)); + if (allocbs) /* reclaim immediately */ + ieee80211_free_node(ni); } else { IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_PROBE_RESP, 0); } - if (allocbs) { - /* - * When operating in ibss mode we hold the node but - * with a zero reference count; this is the current - * convention (XXX). For other cases we do nothing - * as the node is created with a short inactivity - * timer (may want to shorten it further here). - */ - if (ic->ic_opmode == IEEE80211_M_IBSS) - ieee80211_unref_node(&ni); - } break; } @@ -2050,7 +2031,7 @@ bintval = le16toh(*(u_int16_t *)frm); frm += 2; if (reassoc) frm += 6; /* ignore current AP info */ - ssid = rates = xrates = wpa = NULL; + ssid = rates = xrates = wpa = wme = NULL; while (frm < efrm) { switch (*frm) { case IEEE80211_ELEMID_SSID: @@ -2070,7 +2051,8 @@ if (iswpaoui(frm)) { if (ic->ic_flags & IEEE80211_F_WPA1) wpa = frm; - } + } else if (iswmeoui(frm)) + wme = frm; /* XXX Atheros OUI support */ break; } @@ -2086,12 +2068,12 @@ "%s: deny %sassoc from %s, not authenticated\n", __func__, reassoc ? "reassoc" : "assoc", ether_sprintf(wh->i_addr2)); - ni = ieee80211_dup_bss(ic, wh->i_addr2); + ni = ieee80211_dup_bss(ic->ic_sta, wh->i_addr2); if (ni != NULL) { IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_DEAUTH, IEEE80211_REASON_ASSOC_NOT_AUTHED); - ieee80211_free_node(ic, ni); + ieee80211_free_node(ni); } ic->ic_stats.is_rx_assoc_notauth++; return; @@ -2180,6 +2162,28 @@ */ ni->ni_rsn = rsn; ieee80211_saveie(&ni->ni_wpa_ie, wpa); + } else if (ni->ni_wpa_ie != NULL) { + /* + * Flush any state from a previous association. + */ + FREE(ni->ni_wpa_ie, M_DEVBUF); + ni->ni_wpa_ie = NULL; + } + if (wme != NULL) { + /* + * Record WME parameters for station, mark node + * as capable of QoS and record information + * element for applications that require it. + */ + ieee80211_saveie(&ni->ni_wpa_ie, wpa); + ni->ni_flags |= IEEE80211_NODE_QOS; + } else if (ni->ni_wme_ie != NULL) { + /* + * Flush any state from a previous association. + */ + FREE(ni->ni_wme_ie, M_DEVBUF); + ni->ni_wme_ie = NULL; + ni->ni_flags &= ~IEEE80211_NODE_QOS; } ieee80211_node_join(ic, ni, resp); break; @@ -2187,7 +2191,6 @@ case IEEE80211_FC0_SUBTYPE_ASSOC_RESP: case IEEE80211_FC0_SUBTYPE_REASSOC_RESP: { - u_int8_t *wme; u_int16_t capinfo, associd; u_int16_t status; @@ -2225,7 +2228,7 @@ associd = le16toh(*(u_int16_t *)frm); frm += 2; - rates = xrates = wme = NULL; + rates = xrates = wpa = wme = NULL; while (frm < efrm) { switch (*frm) { case IEEE80211_ELEMID_RATES: @@ -2300,6 +2303,7 @@ ic->ic_flags&IEEE80211_F_USEPROT ? ", protection" : "", ni->ni_flags & IEEE80211_NODE_QOS ? ", QoS" : "" ); + ni->ni_inact = ic->ic_inact_run; ieee80211_new_state(ic, IEEE80211_S_RUN, subtype); break; } @@ -2321,6 +2325,7 @@ IEEE80211_NODE_STAT(ni, rx_deauth); switch (ic->ic_opmode) { case IEEE80211_M_STA: + ni->ni_inact = ic->ic_inact_run; ieee80211_new_state(ic, IEEE80211_S_AUTH, wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK); break; @@ -2358,6 +2363,7 @@ IEEE80211_NODE_STAT(ni, rx_disassoc); switch (ic->ic_opmode) { case IEEE80211_M_STA: + ni->ni_inact = ic->ic_inact_run; ieee80211_new_state(ic, IEEE80211_S_ASSOC, wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK); break; @@ -2423,6 +2429,7 @@ /* XXX statistic */ return; } + ni->ni_inact = ic->ic_inact_run; /* Okay, take the first queued packet and put it out... */ _IF_DEQUEUE(&ni->ni_savedq, m); @@ -2439,7 +2446,7 @@ */ if (_IF_QLEN(&ni->ni_savedq) == 0) { if (ic->ic_set_tim) - (*ic->ic_set_tim)(ic, ni->ni_associd, 0); + ic->ic_set_tim(ic, ni->ni_associd, 0); } else { wh = mtod(m, struct ieee80211_frame_min *); wh->i_fc[1] |= IEEE80211_FC1_MORE_DATA; ==== //depot/projects/wifi/sys/net80211/ieee80211_ioctl.c#10 (text+ko) ==== @@ -87,6 +87,7 @@ struct wi_req wreq; struct wi_ltv_keys *keys; struct wi_apinfo *ap; + struct ieee80211_node_table *nt; struct ieee80211_node *ni; struct ieee80211_rateset *rs; struct wi_sigcache wsc; @@ -158,7 +159,7 @@ break; case WI_RID_COMMS_QUALITY: wreq.wi_val[0] = 0; /* quality */ - wreq.wi_val[1] = htole16(ic->ic_node_getrssi(ic, ic->ic_bss)); + wreq.wi_val[1] = htole16(ic->ic_node_getrssi(ic->ic_bss)); wreq.wi_val[2] = 0; /* noise */ wreq.wi_len = 3; break; @@ -266,19 +267,18 @@ /* XXX: should be implemented in lower drivers */ break; case WI_RID_READ_APS: - if (ic->ic_opmode != IEEE80211_M_HOSTAP) { - /* - * Don't return results until active scan completes. - */ - if (ic->ic_state == IEEE80211_S_SCAN && - (ic->ic_flags & IEEE80211_F_ASCAN)) { - error = EINPROGRESS; - break; - } + /* + * Don't return results until active scan completes. + */ + if (ic->ic_state == IEEE80211_S_SCAN && + (ic->ic_flags & IEEE80211_F_ASCAN)) { + error = EINPROGRESS; + break; } i = 0; ap = (void *)((char *)wreq.wi_val + sizeof(i)); - TAILQ_FOREACH(ni, &ic->ic_node, ni_list) { + nt = &ic->ic_scan; + TAILQ_FOREACH(ni, &nt->nt_node, ni_list) { if ((caddr_t)(ap + 1) > (caddr_t)(&wreq + 1)) break; memset(ap, 0, sizeof(*ap)); @@ -296,7 +296,7 @@ ni->ni_esslen); } ap->channel = ieee80211_chan2ieee(ic, ni->ni_chan); - ap->signal = ic->ic_node_getrssi(ic, ni); + ap->signal = ic->ic_node_getrssi(ni); ap->capinfo = ni->ni_capinfo; ap->interval = ni->ni_intval; rs = &ni->ni_rates; @@ -317,8 +317,7 @@ wreq.wi_len = sizeof(u_int16_t) / 2; break; case WI_RID_SCAN_RES: /* compatibility interface */ - if (ic->ic_opmode != IEEE80211_M_HOSTAP && - ic->ic_state == IEEE80211_S_SCAN && + if (ic->ic_state == IEEE80211_S_SCAN && (ic->ic_flags & IEEE80211_F_ASCAN)) { error = EINPROGRESS; break; @@ -327,12 +326,13 @@ p2 = (struct wi_scan_p2_hdr *)wreq.wi_val; res = (void *)&p2[1]; i = 0; - TAILQ_FOREACH(ni, &ic->ic_node, ni_list) { + nt = &ic->ic_scan; + TAILQ_FOREACH(ni, &nt->nt_node, ni_list) { if ((caddr_t)(res + 1) > (caddr_t)(&wreq + 1)) break; res->wi_chan = ieee80211_chan2ieee(ic, ni->ni_chan); res->wi_noise = 0; - res->wi_signal = ic->ic_node_getrssi(ic, ni); + res->wi_signal = ic->ic_node_getrssi(ni); IEEE80211_ADDR_COPY(res->wi_bssid, ni->ni_bssid); res->wi_interval = ni->ni_intval; res->wi_capinfo = ni->ni_capinfo; @@ -353,12 +353,13 @@ break; case WI_RID_READ_CACHE: i = 0; - TAILQ_FOREACH(ni, &ic->ic_node, ni_list) { + nt = &ic->ic_scan; + TAILQ_FOREACH(ni, &nt->nt_node, ni_list) { if (i == (WI_MAX_DATALEN/sizeof(struct wi_sigcache))-1) break; IEEE80211_ADDR_COPY(wsc.macsrc, ni->ni_macaddr); memset(&wsc.ipsrc, 0, sizeof(wsc.ipsrc)); - wsc.signal = ic->ic_node_getrssi(ic, ni); + wsc.signal = ic->ic_node_getrssi(ni); wsc.noise = 0; wsc.quality = 0; memcpy((caddr_t)wreq.wi_val + sizeof(wsc) * i, @@ -827,7 +828,9 @@ return error; kid = ik.ik_keyix; if (kid == IEEE80211_KEYIX_NONE) { - ni = ieee80211_find_node(ic, ik.ik_macaddr); + if (ic->ic_sta == NULL) + return EINVAL; + ni = ieee80211_find_node(ic->ic_sta, ik.ik_macaddr); if (ni == NULL) return EINVAL; /* XXX */ wk = &ni->ni_ucastkey; @@ -861,7 +864,7 @@ memset(ik.ik_keydata, 0, sizeof(ik.ik_keydata)); } if (ni != NULL) - ieee80211_free_node(ic, ni); + ieee80211_free_node(ni); return copyout(&ik, ireq->i_data, sizeof(ik)); } @@ -900,7 +903,9 @@ error = copyin(ireq->i_data, wpaie.wpa_macaddr, IEEE80211_ADDR_LEN); if (error != 0) return error; - ni = ieee80211_find_node(ic, wpaie.wpa_macaddr); + if (ic->ic_sta == NULL) + return EINVAL; + ni = ieee80211_find_node(ic->ic_sta, wpaie.wpa_macaddr); if (ni == NULL) return EINVAL; /* XXX */ memset(wpaie.wpa_ie, 0, sizeof(wpaie.wpa_ie)); @@ -910,7 +915,7 @@ ielen = sizeof(wpaie.wpa_ie); memcpy(wpaie.wpa_ie, ni->ni_wpa_ie, ielen); } - ieee80211_free_node(ic, ni); + ieee80211_free_node(ni); if (ireq->i_len > sizeof(wpaie)) ireq->i_len = sizeof(wpaie); return copyout(&wpaie, ireq->i_data, ireq->i_len); @@ -929,7 +934,9 @@ error = copyin(ireq->i_data, macaddr, IEEE80211_ADDR_LEN); if (error != 0) return error; - ni = ieee80211_find_node(ic, macaddr); + if (ic->ic_sta == NULL) + return EINVAL; + ni = ieee80211_find_node(ic->ic_sta, macaddr); if (ni == NULL) return EINVAL; /* XXX */ if (ireq->i_len > sizeof(struct ieee80211req_sta_stats)) @@ -937,7 +944,7 @@ /* NB: copy out only the statistics */ error = copyout(&ni->ni_stats, (u_int8_t *) ireq->i_data + off, ireq->i_len - off); - ieee80211_free_node(ic, ni); + ieee80211_free_node(ni); return error; } @@ -949,18 +956,17 @@ char data[512]; } u; struct ieee80211req_scan_result *sr = &u.res; + struct ieee80211_node_table *nt; >>> TRUNCATED FOR MAIL (1000 lines) <<<
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200411081907.iA8J7MMM045141>