Date: Tue, 14 Aug 2012 19:55:11 -0400 From: Kim Culhan <w8hdkim@gmail.com> To: FreeBSD-gnats-submit@freebsd.org, freebsd-bugs@freebsd.org Subject: Re: conf/170098: virtual access points with Atheros ath driver Message-ID: <CAKZxVQVcziYO_iDYka=Or3QHCUrs-ViDsCUNDhm2HDrx5tQPnQ@mail.gmail.com> In-Reply-To: <201207232230.q6NMUCAG081854@freefall.freebsd.org> References: <201207232227.q6NMRxWG014709@red.freebsd.org> <201207232230.q6NMUCAG081854@freefall.freebsd.org>
index | next in thread | previous in thread | raw e-mail
[-- Attachment #1 --] On Mon, Jul 23, 2012 at 6:30 PM, <FreeBSD-gnats-submit@freebsd.org> wrote: > Thank you very much for your problem report. > It has the internal identification `conf/170098'. > The individual assigned to look at your > report is: freebsd-bugs. > > You can access the state of your problem report at any time > via this link: > > http://www.freebsd.org/cgi/query-pr.cgi?pr=170098 > >>Category: conf >>Responsible: freebsd-bugs >>Synopsis: virtual access points with Atheros ath driver >>Arrival-Date: Mon Jul 23 22:30:12 UTC 2012 This has been fixed by the attached 2 patches, which are applied to -HEAD in order. Thanks muchly to PseudoCylon for his work, this has taken a while but the difficult solutions are that way. thanks -kim [-- Attachment #2 --] diff --git a/ieee80211_node.c b/ieee80211_node.c index a609cb1..a15fc91 100644 --- a/ieee80211_node.c +++ b/ieee80211_node.c @@ -2160,18 +2160,19 @@ ieee80211_node_timeout(void *arg) * May directly be called and do customized iterate functions. * Only requirement is to decrement each node's ref count. */ -void +int ieee80211_iterate_nt(struct ieee80211_node_table *nt, struct ieee80211_node **ni_arr, uint16_t max_aid) { struct ieee80211_node *ni; u_int gen; - int i = 0; + int i, ret; IEEE80211_NODE_ITERATE_LOCK(nt); IEEE80211_NODE_LOCK(nt); gen = ++nt->nt_scangen; + i = ret = 0; restart: TAILQ_FOREACH(ni, &nt->nt_node, ni_list) { @@ -2179,6 +2180,7 @@ restart: continue; if (i >= max_aid) { + ret = E2BIG; if_printf(nt->nt_ic->ic_ifp, "Node array overflow: max=%u", max_aid); break; @@ -2189,8 +2191,21 @@ restart: goto restart; } + if (ret) { + nt->nt_scangen--; + for (i = 0; i < max_aid; i++) { + ni = *(ni_arr + i); + ni->ni_scangen--; + /* node lock is recursive */ + ieee80211_free_node(ni); + } + free(ni_arr, M_80211_NODE); + } + IEEE80211_NODE_UNLOCK(nt); IEEE80211_NODE_ITERATE_UNLOCK(nt); + + return (ret); } /* @@ -2214,7 +2229,8 @@ ieee80211_iterate_nodes(struct ieee80211_node_table *nt, if (ni_arr == NULL) return; - ieee80211_iterate_nt(nt, ni_arr, max_aid); + if (!ieee80211_iterate_nt(nt, ni_arr, max_aid)) + return; for (i = 0; i < max_aid; i++) { ni = *(ni_arr + i); diff --git a/ieee80211_node.h b/ieee80211_node.h index 1fbc892..48eae2d 100644 --- a/ieee80211_node.h +++ b/ieee80211_node.h @@ -438,7 +438,7 @@ int ieee80211_node_delucastkey(struct ieee80211_node *); void ieee80211_node_timeout(void *arg); typedef void ieee80211_iter_func(void *, struct ieee80211_node *); -void ieee80211_iterate_nt(struct ieee80211_node_table *, +int ieee80211_iterate_nt(struct ieee80211_node_table *, struct ieee80211_node **, uint16_t); void ieee80211_iterate_nodes(struct ieee80211_node_table *, ieee80211_iter_func *, void *); [-- Attachment #3 --] diff --git a/ieee80211_node.c b/ieee80211_node.c index 861fa85..a609cb1 100644 --- a/ieee80211_node.c +++ b/ieee80211_node.c @@ -2156,32 +2156,79 @@ ieee80211_node_timeout(void *arg) ieee80211_node_timeout, ic); } +/* + * May directly be called and do customized iterate functions. + * Only requirement is to decrement each node's ref count. + */ void -ieee80211_iterate_nodes(struct ieee80211_node_table *nt, - ieee80211_iter_func *f, void *arg) +ieee80211_iterate_nt(struct ieee80211_node_table *nt, + struct ieee80211_node **ni_arr, uint16_t max_aid) { struct ieee80211_node *ni; u_int gen; + int i = 0; IEEE80211_NODE_ITERATE_LOCK(nt); + IEEE80211_NODE_LOCK(nt); + gen = ++nt->nt_scangen; + restart: - IEEE80211_NODE_LOCK(nt); TAILQ_FOREACH(ni, &nt->nt_node, ni_list) { - if (ni->ni_scangen != gen) { - ni->ni_scangen = gen; - (void) ieee80211_ref_node(ni); - IEEE80211_NODE_UNLOCK(nt); - (*f)(arg, ni); - ieee80211_free_node(ni); - goto restart; + if (ni->ni_scangen == gen) + continue; + + if (i >= max_aid) { + if_printf(nt->nt_ic->ic_ifp, + "Node array overflow: max=%u", max_aid); + break; } + + ni->ni_scangen = gen; + (*(ni_arr + i++)) = ieee80211_ref_node(ni); + goto restart; } - IEEE80211_NODE_UNLOCK(nt); + IEEE80211_NODE_UNLOCK(nt); IEEE80211_NODE_ITERATE_UNLOCK(nt); } +/* + * Just a wrapper, so we don't have to change every ieee80211_iterate_nodes() + * reference in the source. + */ +void +ieee80211_iterate_nodes(struct ieee80211_node_table *nt, + ieee80211_iter_func *f, void *arg) +{ + struct ieee80211_node **ni_arr; + struct ieee80211_node *ni; + unsigned long size; + int i; + uint16_t max_aid; + + max_aid = TAILQ_FIRST(&nt->nt_ic->ic_vaps)->iv_max_aid; + size = max_aid * sizeof(*ni_arr); + ni_arr = (struct ieee80211_node **)malloc(size, M_80211_NODE, + M_NOWAIT | M_ZERO); + if (ni_arr == NULL) + return; + + ieee80211_iterate_nt(nt, ni_arr, max_aid); + + for (i = 0; i < max_aid; i++) { + ni = *(ni_arr + i); + if (ni == NULL) /* end of the list */ + break; + + (*f)(arg, ni); + /* ieee80211_free_node() locks by itself */ + ieee80211_free_node(ni); + } + + free(ni_arr, M_80211_NODE); +} + void ieee80211_dump_node(struct ieee80211_node_table *nt, struct ieee80211_node *ni) { diff --git a/ieee80211_node.h b/ieee80211_node.h index 83b108b..1fbc892 100644 --- a/ieee80211_node.h +++ b/ieee80211_node.h @@ -438,6 +438,8 @@ int ieee80211_node_delucastkey(struct ieee80211_node *); void ieee80211_node_timeout(void *arg); typedef void ieee80211_iter_func(void *, struct ieee80211_node *); +void ieee80211_iterate_nt(struct ieee80211_node_table *, + struct ieee80211_node **, uint16_t); void ieee80211_iterate_nodes(struct ieee80211_node_table *, ieee80211_iter_func *, void *);help
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CAKZxVQVcziYO_iDYka=Or3QHCUrs-ViDsCUNDhm2HDrx5tQPnQ>
