svn commit: r306590 - head/sys/net80211

Andriy Voskoboinyk avos at FreeBSD.org
Sun Oct 2 19:39:25 UTC 2016


Author: avos
Date: Sun Oct  2 19:39:23 2016
New Revision: 306590
URL: https://svnweb.freebsd.org/changeset/base/306590

Log:
  net80211: add one-vap version of ieee80211_iterate_nodes()
  
  - Add a counter into 'struct ieee80211_node_table' to save current number
  of allocated nodes.
  (allows to remove array overflow checking in ieee80211_iterate_nodes()).
  - Add ieee80211_iterate_nodes_vap() function; unlike non-vap version,
  it iterates on nodes for specified vap only.
  
  In addition to the above:
  - Remove ieee80211_iterate_nt(); it is not used by drivers / net80211
  outside ieee80211_iterate_nodes() function + cannot be separated due
  to structural changes in code.
  
  Since size of 'struct ieee80211_node_table' (part of ieee80211com,
  which is a part of driver's softc) is changed all wireless drivers /
  kernel need to be recompiled.
  
  Tested with wpi(4), STA mode.
  
  Reviewed by:	adrian
  Differential Revision:	https://reviews.freebsd.org/D7996

Modified:
  head/sys/net80211/ieee80211_node.c
  head/sys/net80211/ieee80211_node.h

Modified: head/sys/net80211/ieee80211_node.c
==============================================================================
--- head/sys/net80211/ieee80211_node.c	Sun Oct  2 17:36:55 2016	(r306589)
+++ head/sys/net80211/ieee80211_node.c	Sun Oct  2 19:39:23 2016	(r306590)
@@ -1214,13 +1214,44 @@ node_getmimoinfo(const struct ieee80211_
 	/* XXX EVM? */
 }
 
+static void
+ieee80211_add_node_nt(struct ieee80211_node_table *nt,
+    struct ieee80211_node *ni)
+{
+	struct ieee80211com *ic = nt->nt_ic;
+	int hash;
+
+	IEEE80211_NODE_LOCK_ASSERT(nt);
+
+	hash = IEEE80211_NODE_HASH(ic, ni->ni_macaddr);
+	(void) ic;	/* XXX IEEE80211_NODE_HASH */
+	TAILQ_INSERT_TAIL(&nt->nt_node, ni, ni_list);
+	LIST_INSERT_HEAD(&nt->nt_hash[hash], ni, ni_hash);
+	nt->nt_count++;
+	ni->ni_table = nt;
+}
+
+static void
+ieee80211_del_node_nt(struct ieee80211_node_table *nt,
+    struct ieee80211_node *ni)
+{
+
+	IEEE80211_NODE_LOCK_ASSERT(nt);
+
+	TAILQ_REMOVE(&nt->nt_node, ni, ni_list);
+	LIST_REMOVE(ni, ni_hash);
+	nt->nt_count--;
+	KASSERT(nt->nt_count >= 0,
+	    ("nt_count is negative (%d)!\n", nt->nt_count));
+	ni->ni_table = NULL;
+}
+
 struct ieee80211_node *
 ieee80211_alloc_node(struct ieee80211_node_table *nt,
 	struct ieee80211vap *vap, const uint8_t macaddr[IEEE80211_ADDR_LEN])
 {
 	struct ieee80211com *ic = nt->nt_ic;
 	struct ieee80211_node *ni;
-	int hash;
 
 	ni = ic->ic_node_alloc(vap, macaddr);
 	if (ni == NULL) {
@@ -1233,7 +1264,6 @@ ieee80211_alloc_node(struct ieee80211_no
 		ether_sprintf(macaddr), nt->nt_name);
 
 	IEEE80211_ADDR_COPY(ni->ni_macaddr, macaddr);
-	hash = IEEE80211_NODE_HASH(ic, macaddr);
 	ieee80211_node_initref(ni);		/* mark referenced */
 	ni->ni_chan = IEEE80211_CHAN_ANYC;
 	ni->ni_authmode = IEEE80211_AUTH_OPEN;
@@ -1250,9 +1280,7 @@ ieee80211_alloc_node(struct ieee80211_no
 		ieee80211_mesh_node_init(vap, ni);
 #endif
 	IEEE80211_NODE_LOCK(nt);
-	TAILQ_INSERT_TAIL(&nt->nt_node, ni, ni_list);
-	LIST_INSERT_HEAD(&nt->nt_hash[hash], ni, ni_hash);
-	ni->ni_table = nt;
+	ieee80211_add_node_nt(nt, ni);
 	ni->ni_vap = vap;
 	ni->ni_ic = ic;
 	IEEE80211_NODE_UNLOCK(nt);
@@ -1815,10 +1843,8 @@ _ieee80211_free_node(struct ieee80211_no
 		if (vap->iv_aid_bitmap != NULL)
 			IEEE80211_AID_CLR(vap, ni->ni_associd);
 	}
-	if (nt != NULL) {
-		TAILQ_REMOVE(&nt->nt_node, ni, ni_list);
-		LIST_REMOVE(ni, ni_hash);
-	}
+	if (nt != NULL)
+		ieee80211_del_node_nt(nt, ni);
 	ni->ni_ic->ic_node_free(ni);
 }
 
@@ -1957,9 +1983,7 @@ node_reclaim(struct ieee80211_node_table
 		 * the references are dropped storage will be
 		 * reclaimed.
 		 */
-		TAILQ_REMOVE(&nt->nt_node, ni, ni_list);
-		LIST_REMOVE(ni, ni_hash);
-		ni->ni_table = NULL;		/* clear reference */
+		ieee80211_del_node_nt(nt, ni);
 	} else
 		_ieee80211_free_node(ni);
 }
@@ -1977,6 +2001,7 @@ ieee80211_node_table_init(struct ieee802
 	nt->nt_ic = ic;
 	IEEE80211_NODE_LOCK_INIT(nt, ic->ic_name);
 	TAILQ_INIT(&nt->nt_node);
+	nt->nt_count = 0;
 	nt->nt_name = name;
 	nt->nt_inact_init = inact;
 	nt->nt_keyixmax = keyixmax;
@@ -2261,117 +2286,68 @@ ieee80211_node_timeout(void *arg)
 }
 
 /*
- * Iterate over the node table and return an array of ref'ed nodes.
- *
- * This is separated out from calling the actual node function so that
- * no LORs will occur.
- *
- * If there are too many nodes (ie, the number of nodes doesn't fit
- * within 'max_aid' entries) then the node references will be freed
- * and an error will be returned.
- *
- * The responsibility of allocating and freeing "ni_arr" is up to
- * the caller.
+ * The same as ieee80211_iterate_nodes(), but for one vap only.
  */
 int
-ieee80211_iterate_nt(struct ieee80211_node_table *nt,
-    struct ieee80211_node **ni_arr, uint16_t max_aid)
+ieee80211_iterate_nodes_vap(struct ieee80211_node_table *nt,
+    struct ieee80211vap *vap, ieee80211_iter_func *f, void *arg)
 {
-	int i, j, ret;
+	struct ieee80211_node **ni_arr;
 	struct ieee80211_node *ni;
+	size_t size;
+	int count, i;
 
+	/*
+	 * Iterate over the node table and save an array of ref'ed nodes.
+	 *
+	 * This is separated out from calling the actual node function so that
+	 * no LORs will occur.
+	 */
 	IEEE80211_NODE_LOCK(nt);
+	count = nt->nt_count;
+	size = count * sizeof(struct ieee80211_node *);
+	ni_arr = (struct ieee80211_node **) IEEE80211_MALLOC(size, M_80211_NODE,
+	    IEEE80211_M_NOWAIT | IEEE80211_M_ZERO);
+	if (ni_arr == NULL) {
+		IEEE80211_NODE_UNLOCK(nt);
+		return (ENOMEM);
+	}
 
-	i = ret = 0;
+	i = 0;
 	TAILQ_FOREACH(ni, &nt->nt_node, ni_list) {
-		if (i >= max_aid) {
-			ret = E2BIG;
-			ic_printf(nt->nt_ic, "Node array overflow: max=%u",
-			    max_aid);
-			break;
-		}
+		if (vap != NULL && ni->ni_vap != vap)
+			continue;
+		KASSERT(i < count,
+		    ("node array overflow (vap %p, i %d, count %d)\n",
+		    vap, i, count));
 		ni_arr[i] = ieee80211_ref_node(ni);
 		i++;
 	}
-
-	/*
-	 * It's safe to unlock here.
-	 *
-	 * If we're successful, the list is returned.
-	 * If we're unsuccessful, the list is ignored
-	 * and we remove our references.
-	 *
-	 * This avoids any potential LOR with
-	 * ieee80211_free_node().
-	 */
 	IEEE80211_NODE_UNLOCK(nt);
 
-	/*
-	 * If ret is non-zero, we hit some kind of error.
-	 * Rather than walking some nodes, we'll walk none
-	 * of them.
-	 */
-	if (ret) {
-		for (j = 0; j < i; j++) {
-			/* ieee80211_free_node() locks by itself */
-			ieee80211_free_node(ni_arr[j]);
-		}
+	for (i = 0; i < count; i++) {
+		if (ni_arr[i] == NULL)	/* end of the list */
+			break;
+		(*f)(arg, ni_arr[i]);
+		/* ieee80211_free_node() locks by itself */
+		ieee80211_free_node(ni_arr[i]);
 	}
 
-	return (ret);
+	IEEE80211_FREE(ni_arr, M_80211_NODE);
+
+	return (0);
 }
 
 /*
  * Just a wrapper, so we don't have to change every ieee80211_iterate_nodes()
  * reference in the source.
- *
- * Note that this fetches 'max_aid' from the first VAP, rather than finding
- * the largest max_aid from all VAPs.
  */
 void
 ieee80211_iterate_nodes(struct ieee80211_node_table *nt,
 	ieee80211_iter_func *f, void *arg)
 {
-	struct ieee80211_node **ni_arr;
-	size_t size;
-	int i;
-	uint16_t max_aid;
-	struct ieee80211vap *vap;
-
-	/* Overdoing it default */
-	max_aid = IEEE80211_AID_MAX;
-
-	/* Handle the case of there being no vaps just yet */
-	vap = TAILQ_FIRST(&nt->nt_ic->ic_vaps);
-	if (vap != NULL)
-		max_aid = vap->iv_max_aid;
-
-	size = max_aid * sizeof(struct ieee80211_node *);
-	ni_arr = (struct ieee80211_node **) IEEE80211_MALLOC(size, M_80211_NODE,
-	    IEEE80211_M_NOWAIT | IEEE80211_M_ZERO);
-	if (ni_arr == NULL)
-		return;
-
-	/*
-	 * If this fails, the node table won't have any
-	 * valid entries - ieee80211_iterate_nt() frees
-	 * the references to them.  So don't try walking
-	 * the table; just skip to the end and free the
-	 * temporary memory.
-	 */
-	if (ieee80211_iterate_nt(nt, ni_arr, max_aid) != 0)
-		goto done;
-
-	for (i = 0; i < max_aid; i++) {
-		if (ni_arr[i] == NULL)	/* end of the list */
-			break;
-		(*f)(arg, ni_arr[i]);
-		/* ieee80211_free_node() locks by itself */
-		ieee80211_free_node(ni_arr[i]);
-	}
-
-done:
-	IEEE80211_FREE(ni_arr, M_80211_NODE);
+	/* XXX no way to pass error to the caller. */
+	(void) ieee80211_iterate_nodes_vap(nt, NULL, f, arg);
 }
 
 void

Modified: head/sys/net80211/ieee80211_node.h
==============================================================================
--- head/sys/net80211/ieee80211_node.h	Sun Oct  2 17:36:55 2016	(r306589)
+++ head/sys/net80211/ieee80211_node.h	Sun Oct  2 19:39:23 2016	(r306590)
@@ -359,6 +359,7 @@ struct ieee80211_node_table {
 	ieee80211_node_lock_t	nt_nodelock;	/* on node table */
 	TAILQ_HEAD(, ieee80211_node) nt_node;	/* information of all nodes */
 	LIST_HEAD(, ieee80211_node) nt_hash[IEEE80211_NODE_HASHSIZE];
+	int			nt_count;	/* number of nodes */
 	struct ieee80211_node	**nt_keyixmap;	/* key ix -> node map */
 	int			nt_keyixmax;	/* keyixmap size */
 	const char		*nt_name;	/* table name for debug msgs */
@@ -444,8 +445,8 @@ int	ieee80211_node_delucastkey(struct ie
 void	ieee80211_node_timeout(void *arg);
 
 typedef void ieee80211_iter_func(void *, struct ieee80211_node *);
-int	ieee80211_iterate_nt(struct ieee80211_node_table *,
-		struct ieee80211_node **, uint16_t);
+int	ieee80211_iterate_nodes_vap(struct ieee80211_node_table *,
+		struct ieee80211vap *, ieee80211_iter_func *, void *);
 void	ieee80211_iterate_nodes(struct ieee80211_node_table *,
 		ieee80211_iter_func *, void *);
 


More information about the svn-src-head mailing list