PERFORCE change 64628 for review

Sam Leffler sam at FreeBSD.org
Mon Nov 8 11:07:24 PST 2004


http://perforce.freebsd.org/chv.cgi?CH=64628

Change 64628 by sam at 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) <<<


More information about the p4-projects mailing list