Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 27 Jan 2008 20:39:09 GMT
From:      Sam Leffler <sam@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 134238 for review
Message-ID:  <200801272039.m0RKd9NT038592@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=134238

Change 134238 by sam@sam_ebb on 2008/01/27 20:38:25

	Reclaim old bss directly when re-joining a bss (or similar); the
	old bss node has refcnt 2 (1 for the sta table and 1 for the old
	ref in ivs_bss) but we were only free'ing the iv_bss reference.
	We need to explicitly purge the sta table reference; do this with
	a new ieee80211_node_reclaim routine.

Affected files ...

.. //depot/projects/vap/sys/net80211/ieee80211_node.c#23 edit

Differences ...

==== //depot/projects/vap/sys/net80211/ieee80211_node.c#23 (text+ko) ====

@@ -82,6 +82,7 @@
 	int inact, int keymaxix);
 static void ieee80211_node_table_reset(struct ieee80211_node_table *,
 	struct ieee80211vap *);
+static void ieee80211_node_reclaim(struct ieee80211_node *);
 static void ieee80211_node_table_cleanup(struct ieee80211_node_table *nt);
 static void ieee80211_erp_timeout(struct ieee80211com *);
 
@@ -600,7 +601,8 @@
 	vap->iv_bss = selbs;		/* NB: caller assumed to bump refcnt */
 	if (obss != NULL) {
 		copy_bss(selbs, obss);
-		ieee80211_free_node(obss);
+		ieee80211_node_reclaim(obss);
+		obss = NULL;		/* NB: guard against later use */
 	}
 
 	/*
@@ -1544,6 +1546,65 @@
 }
 
 /*
+ * Reclaim a (bss) node.  Decrement the refcnt and reclaim
+ * the node if the only other reference to it is in the sta
+ * table.  This is effectively ieee80211_free_node followed
+ * by node_reclaim when the refcnt is 1 (after the free).
+ */
+static void
+ieee80211_node_reclaim(struct ieee80211_node *ni)
+{
+	struct ieee80211_node_table *nt = ni->ni_table;
+
+	KASSERT(nt != NULL, ("reclaim node not in table"));
+
+#ifdef IEEE80211_DEBUG_REFCNT
+	IEEE80211_DPRINTF(ni->ni_vap, IEEE80211_MSG_NODE,
+		"%s (%s:%u) %p<%s> refcnt %d\n", __func__, func, line, ni,
+		 ether_sprintf(ni->ni_macaddr), ieee80211_node_refcnt(ni)-1);
+#endif
+	IEEE80211_NODE_LOCK(nt);
+	if (ieee80211_node_dectestref(ni)) {
+		/*
+		 * Last reference, reclaim state.
+		 */
+		_ieee80211_free_node(ni);
+		nt = NULL;
+	} 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);
+			nt = NULL;
+		}
+	}
+	if (nt != NULL && ieee80211_node_refcnt(ni) == 1) {
+		/*
+		 * Last reference is in the sta table; complete
+		 * the reclaim.  This handles bss nodes being
+		 * recycled: the node has two references, one for
+		 * iv_bss and one for the table.  After dropping
+		 * the iv_bss ref above we need to reclaim the sta
+		 * table reference.
+		 */
+		ieee80211_node_decref(ni);	/* NB: be pendantic */
+		_ieee80211_free_node(ni);
+	}
+	IEEE80211_NODE_UNLOCK(nt);
+}
+
+/*
  * Node table support.
  */
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200801272039.m0RKd9NT038592>