From owner-svn-src-all@freebsd.org Sun Oct 2 19:39:24 2016 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id DE7FEAF227A; Sun, 2 Oct 2016 19:39:24 +0000 (UTC) (envelope-from avos@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id B9B656D0; Sun, 2 Oct 2016 19:39:24 +0000 (UTC) (envelope-from avos@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id u92JdNq2022462; Sun, 2 Oct 2016 19:39:23 GMT (envelope-from avos@FreeBSD.org) Received: (from avos@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id u92JdNeb022460; Sun, 2 Oct 2016 19:39:23 GMT (envelope-from avos@FreeBSD.org) Message-Id: <201610021939.u92JdNeb022460@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: avos set sender to avos@FreeBSD.org using -f From: Andriy Voskoboinyk Date: Sun, 2 Oct 2016 19:39:23 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r306590 - head/sys/net80211 X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 02 Oct 2016 19:39:25 -0000 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 *);