* [PATCH net-next 0/4] Bridge IGMP cleanup and fixes
@ 2010-04-28 1:01 Stephen Hemminger
2010-04-28 1:01 ` [PATCH net-next 1/4] bridge: simplify multicast_add_router Stephen Hemminger
` (4 more replies)
0 siblings, 5 replies; 8+ messages in thread
From: Stephen Hemminger @ 2010-04-28 1:01 UTC (permalink / raw)
To: David S. Miller, Herbert Xu; +Cc: netdev
--
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH net-next 1/4] bridge: simplify multicast_add_router
2010-04-28 1:01 [PATCH net-next 0/4] Bridge IGMP cleanup and fixes Stephen Hemminger
@ 2010-04-28 1:01 ` Stephen Hemminger
2010-04-28 1:01 ` [PATCH net-next 2/4] bridge: multicast flood Stephen Hemminger
` (3 subsequent siblings)
4 siblings, 0 replies; 8+ messages in thread
From: Stephen Hemminger @ 2010-04-28 1:01 UTC (permalink / raw)
To: David S. Miller, Herbert Xu; +Cc: netdev
[-- Attachment #1: br-mcast-list2.patch --]
[-- Type: text/plain, Size: 1172 bytes --]
By coding slightly differently, there are only two cases
to deal with: add at head and add after previous entry.
Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
--- a/net/bridge/br_multicast.c 2010-04-27 17:02:06.720839467 -0700
+++ b/net/bridge/br_multicast.c 2010-04-27 17:11:06.518933878 -0700
@@ -1039,22 +1039,25 @@ static int br_ip6_multicast_mld2_report(
}
#endif
+/*
+ * Add port to rotuer_list
+ * list is maintained ordered by pointer value
+ * and locked by br->multicast_lock and RCU
+ */
static void br_multicast_add_router(struct net_bridge *br,
struct net_bridge_port *port)
{
struct net_bridge_port *p;
- struct hlist_node *n, *last = NULL;
+ struct hlist_node *n, *slot = NULL;
hlist_for_each_entry(p, n, &br->router_list, rlist) {
- if ((unsigned long) port >= (unsigned long) p) {
- hlist_add_before_rcu(n, &port->rlist);
- return;
- }
- last = n;
+ if ((unsigned long) port >= (unsigned long) p)
+ break;
+ slot = n;
}
- if (last)
- hlist_add_after_rcu(last, &port->rlist);
+ if (slot)
+ hlist_add_after_rcu(slot, &port->rlist);
else
hlist_add_head_rcu(&port->rlist, &br->router_list);
}
--
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH net-next 2/4] bridge: multicast flood
2010-04-28 1:01 [PATCH net-next 0/4] Bridge IGMP cleanup and fixes Stephen Hemminger
2010-04-28 1:01 ` [PATCH net-next 1/4] bridge: simplify multicast_add_router Stephen Hemminger
@ 2010-04-28 1:01 ` Stephen Hemminger
2010-04-28 1:01 ` [PATCH net-next 3/4] bridge: multicast port group RCU fix Stephen Hemminger
` (2 subsequent siblings)
4 siblings, 0 replies; 8+ messages in thread
From: Stephen Hemminger @ 2010-04-28 1:01 UTC (permalink / raw)
To: David S. Miller, Herbert Xu; +Cc: netdev
[-- Attachment #1: br-router-list-rcu.patch --]
[-- Type: text/plain, Size: 786 bytes --]
Fix unsafe usage of RCU. Would never work on Alpha SMP because
of lack of rcu_dereference()
Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
--- a/net/bridge/br_forward.c 2010-04-27 17:11:52.008626080 -0700
+++ b/net/bridge/br_forward.c 2010-04-27 17:23:46.388602995 -0700
@@ -216,7 +216,7 @@ static void br_multicast_flood(struct ne
prev = NULL;
- rp = br->router_list.first;
+ rp = rcu_dereference(br->router_list.first);
p = mdst ? mdst->ports : NULL;
while (p || rp) {
lport = p ? p->port : NULL;
@@ -233,7 +233,7 @@ static void br_multicast_flood(struct ne
if ((unsigned long)lport >= (unsigned long)port)
p = p->next;
if ((unsigned long)rport >= (unsigned long)port)
- rp = rp->next;
+ rp = rcu_dereference(rp->next);
}
if (!prev)
--
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH net-next 3/4] bridge: multicast port group RCU fix
2010-04-28 1:01 [PATCH net-next 0/4] Bridge IGMP cleanup and fixes Stephen Hemminger
2010-04-28 1:01 ` [PATCH net-next 1/4] bridge: simplify multicast_add_router Stephen Hemminger
2010-04-28 1:01 ` [PATCH net-next 2/4] bridge: multicast flood Stephen Hemminger
@ 2010-04-28 1:01 ` Stephen Hemminger
2010-04-28 3:07 ` Herbert Xu
2010-04-28 1:01 ` [PATCH net-next 4/4] bridge: multicast_flood cleanup Stephen Hemminger
2010-04-28 1:14 ` [PATCH net-next 0/4] Bridge IGMP cleanup and fixes David Miller
4 siblings, 1 reply; 8+ messages in thread
From: Stephen Hemminger @ 2010-04-28 1:01 UTC (permalink / raw)
To: David S. Miller, Herbert Xu; +Cc: netdev
[-- Attachment #1: br-portlist-rcu.patch --]
[-- Type: text/plain, Size: 1463 bytes --]
The recently introduced bridge mulitcast port group list was only
partially using RCU correctly. It was missing rcu_dereference()
and missing the necessary barrier on deletion.
The code should have used one of the standard list methods (list or hlist)
instead of open coding a RCU based link list.
Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
--- a/net/bridge/br_forward.c 2010-04-27 17:51:27.909588950 -0700
+++ b/net/bridge/br_forward.c 2010-04-27 17:53:18.790721091 -0700
@@ -217,7 +217,7 @@ static void br_multicast_flood(struct ne
prev = NULL;
rp = rcu_dereference(br->router_list.first);
- p = mdst ? mdst->ports : NULL;
+ p = mdst ? rcu_dereference(mdst->ports) : NULL;
while (p || rp) {
lport = p ? p->port : NULL;
rport = rp ? hlist_entry(rp, struct net_bridge_port, rlist) :
@@ -231,7 +231,7 @@ static void br_multicast_flood(struct ne
goto out;
if ((unsigned long)lport >= (unsigned long)port)
- p = p->next;
+ p = rcu_dereference(p->next);
if ((unsigned long)rport >= (unsigned long)port)
rp = rcu_dereference(rp->next);
}
--- a/net/bridge/br_multicast.c 2010-04-27 17:51:31.509593914 -0700
+++ b/net/bridge/br_multicast.c 2010-04-27 17:52:48.209243982 -0700
@@ -259,7 +259,7 @@ static void br_multicast_del_pg(struct n
if (p != pg)
continue;
- *pp = p->next;
+ rcu_assign_pointer(*pp, p->next);
hlist_del_init(&p->mglist);
del_timer(&p->timer);
del_timer(&p->query_timer);
--
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH net-next 4/4] bridge: multicast_flood cleanup
2010-04-28 1:01 [PATCH net-next 0/4] Bridge IGMP cleanup and fixes Stephen Hemminger
` (2 preceding siblings ...)
2010-04-28 1:01 ` [PATCH net-next 3/4] bridge: multicast port group RCU fix Stephen Hemminger
@ 2010-04-28 1:01 ` Stephen Hemminger
2010-04-28 1:14 ` [PATCH net-next 0/4] Bridge IGMP cleanup and fixes David Miller
4 siblings, 0 replies; 8+ messages in thread
From: Stephen Hemminger @ 2010-04-28 1:01 UTC (permalink / raw)
To: David S. Miller, Herbert Xu; +Cc: netdev
[-- Attachment #1: br-flood-clean.patch --]
[-- Type: text/plain, Size: 958 bytes --]
Move some declarations around to make it clearer which variables
are being used inside loop.
Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
--- a/net/bridge/br_forward.c 2010-04-27 17:58:25.739592056 -0700
+++ b/net/bridge/br_forward.c 2010-04-27 17:59:17.182654034 -0700
@@ -208,17 +208,15 @@ static void br_multicast_flood(struct ne
{
struct net_device *dev = BR_INPUT_SKB_CB(skb)->brdev;
struct net_bridge *br = netdev_priv(dev);
- struct net_bridge_port *port;
- struct net_bridge_port *lport, *rport;
- struct net_bridge_port *prev;
+ struct net_bridge_port *prev = NULL;
struct net_bridge_port_group *p;
struct hlist_node *rp;
- prev = NULL;
-
rp = rcu_dereference(br->router_list.first);
p = mdst ? rcu_dereference(mdst->ports) : NULL;
while (p || rp) {
+ struct net_bridge_port *port, *lport, *rport;
+
lport = p ? p->port : NULL;
rport = rp ? hlist_entry(rp, struct net_bridge_port, rlist) :
NULL;
--
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH net-next 0/4] Bridge IGMP cleanup and fixes
2010-04-28 1:01 [PATCH net-next 0/4] Bridge IGMP cleanup and fixes Stephen Hemminger
` (3 preceding siblings ...)
2010-04-28 1:01 ` [PATCH net-next 4/4] bridge: multicast_flood cleanup Stephen Hemminger
@ 2010-04-28 1:14 ` David Miller
4 siblings, 0 replies; 8+ messages in thread
From: David Miller @ 2010-04-28 1:14 UTC (permalink / raw)
To: shemminger; +Cc: herbert, netdev
All looks good, I'll apply to net-next-2.6 and build test.
Thanks Stephen.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH net-next 3/4] bridge: multicast port group RCU fix
2010-04-28 1:01 ` [PATCH net-next 3/4] bridge: multicast port group RCU fix Stephen Hemminger
@ 2010-04-28 3:07 ` Herbert Xu
2010-04-28 3:47 ` Stephen Hemminger
0 siblings, 1 reply; 8+ messages in thread
From: Herbert Xu @ 2010-04-28 3:07 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: David S. Miller, netdev
On Tue, Apr 27, 2010 at 06:01:06PM -0700, Stephen Hemminger wrote:
> The recently introduced bridge mulitcast port group list was only
> partially using RCU correctly. It was missing rcu_dereference()
> and missing the necessary barrier on deletion.
>
> The code should have used one of the standard list methods (list or hlist)
> instead of open coding a RCU based link list.
>
> Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
>
> --- a/net/bridge/br_forward.c 2010-04-27 17:51:27.909588950 -0700
> +++ b/net/bridge/br_forward.c 2010-04-27 17:53:18.790721091 -0700
> @@ -217,7 +217,7 @@ static void br_multicast_flood(struct ne
> prev = NULL;
>
> rp = rcu_dereference(br->router_list.first);
> - p = mdst ? mdst->ports : NULL;
> + p = mdst ? rcu_dereference(mdst->ports) : NULL;
> while (p || rp) {
> lport = p ? p->port : NULL;
> rport = rp ? hlist_entry(rp, struct net_bridge_port, rlist) :
> @@ -231,7 +231,7 @@ static void br_multicast_flood(struct ne
> goto out;
>
> if ((unsigned long)lport >= (unsigned long)port)
> - p = p->next;
> + p = rcu_dereference(p->next);
> if ((unsigned long)rport >= (unsigned long)port)
> rp = rcu_dereference(rp->next);
> }
Thanks for catching this!
> --- a/net/bridge/br_multicast.c 2010-04-27 17:51:31.509593914 -0700
> +++ b/net/bridge/br_multicast.c 2010-04-27 17:52:48.209243982 -0700
> @@ -259,7 +259,7 @@ static void br_multicast_del_pg(struct n
> if (p != pg)
> continue;
>
> - *pp = p->next;
> + rcu_assign_pointer(*pp, p->next);
But this is bogus. br_multicast_del_pg is removing an entry from
the RCU list.
You only need write barriers when you're putting a new entry in
it, and only if there is no other barrier between the code filling
in the new entry and the line adding it to the RCU list.
Cheers,
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH net-next 3/4] bridge: multicast port group RCU fix
2010-04-28 3:07 ` Herbert Xu
@ 2010-04-28 3:47 ` Stephen Hemminger
0 siblings, 0 replies; 8+ messages in thread
From: Stephen Hemminger @ 2010-04-28 3:47 UTC (permalink / raw)
To: Herbert Xu; +Cc: David S. Miller, netdev
On Wed, 28 Apr 2010 11:07:09 +0800
Herbert Xu <herbert@gondor.apana.org.au> wrote:
> On Tue, Apr 27, 2010 at 06:01:06PM -0700, Stephen Hemminger wrote:
> > The recently introduced bridge mulitcast port group list was only
> > partially using RCU correctly. It was missing rcu_dereference()
> > and missing the necessary barrier on deletion.
> >
> > The code should have used one of the standard list methods (list or hlist)
> > instead of open coding a RCU based link list.
> >
> > Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
> >
> > --- a/net/bridge/br_forward.c 2010-04-27 17:51:27.909588950 -0700
> > +++ b/net/bridge/br_forward.c 2010-04-27 17:53:18.790721091 -0700
> > @@ -217,7 +217,7 @@ static void br_multicast_flood(struct ne
> > prev = NULL;
> >
> > rp = rcu_dereference(br->router_list.first);
> > - p = mdst ? mdst->ports : NULL;
> > + p = mdst ? rcu_dereference(mdst->ports) : NULL;
> > while (p || rp) {
> > lport = p ? p->port : NULL;
> > rport = rp ? hlist_entry(rp, struct net_bridge_port, rlist) :
> > @@ -231,7 +231,7 @@ static void br_multicast_flood(struct ne
> > goto out;
> >
> > if ((unsigned long)lport >= (unsigned long)port)
> > - p = p->next;
> > + p = rcu_dereference(p->next);
> > if ((unsigned long)rport >= (unsigned long)port)
> > rp = rcu_dereference(rp->next);
> > }
>
> Thanks for catching this!
>
> > --- a/net/bridge/br_multicast.c 2010-04-27 17:51:31.509593914 -0700
> > +++ b/net/bridge/br_multicast.c 2010-04-27 17:52:48.209243982 -0700
> > @@ -259,7 +259,7 @@ static void br_multicast_del_pg(struct n
> > if (p != pg)
> > continue;
> >
> > - *pp = p->next;
> > + rcu_assign_pointer(*pp, p->next);
>
> But this is bogus. br_multicast_del_pg is removing an entry from
> the RCU list.
>
> You only need write barriers when you're putting a new entry in
> it, and only if there is no other barrier between the code filling
> in the new entry and the line adding it to the RCU list.
Yeah, it is extra barrier (one more reason to stick to hlist_del_rcu)
--
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2010-04-28 3:47 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-04-28 1:01 [PATCH net-next 0/4] Bridge IGMP cleanup and fixes Stephen Hemminger
2010-04-28 1:01 ` [PATCH net-next 1/4] bridge: simplify multicast_add_router Stephen Hemminger
2010-04-28 1:01 ` [PATCH net-next 2/4] bridge: multicast flood Stephen Hemminger
2010-04-28 1:01 ` [PATCH net-next 3/4] bridge: multicast port group RCU fix Stephen Hemminger
2010-04-28 3:07 ` Herbert Xu
2010-04-28 3:47 ` Stephen Hemminger
2010-04-28 1:01 ` [PATCH net-next 4/4] bridge: multicast_flood cleanup Stephen Hemminger
2010-04-28 1:14 ` [PATCH net-next 0/4] Bridge IGMP cleanup and fixes David Miller
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).