Skip site navigation (1)Skip section navigation (2)
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>