* [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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.