All of lore.kernel.org
 help / color / mirror / Atom feed
* [Bridge] Learning BPDU source MACs in BLOCKING state => loss of IP connectivity
@ 2008-01-26 16:56 Oleg Serditov
  2008-01-26 17:28 ` Stephen Hemminger
  0 siblings, 1 reply; 2+ messages in thread
From: Oleg Serditov @ 2008-01-26 16:56 UTC (permalink / raw)
  To: bridge

Hello to all.

I'm running 2.6.12, uClinux distribution for the Blackfin processor. I
am experiencing a problem which prevents two boxes connected by a pair
of links from being able to ping each other.

The  network  setup  described  below  is presumably rather common - I
don't do anything special.

The problem arises when you have specific combination of interface MAC
addresses  (and/or  STP  bridge  priorities,  port priorities and link
costs;  if  you're  unlucky  enough,  like  in  my  case, standard STP
settings will do).

I've  read the list archive carefully, and searched the Web, wondering
if  this problem was solved in more recent kernels, but didn't find an
answer. So, please, don't blame me too much if I'll tell you something
already well known :)

The  network consists of two uClinux boxes. The boxes are connected by
two   links  to  provide  failover.  Each  of  them  has  two  network
interfaces,  grouped into a bridge. The bridges have IP addresses from
the  same  subnet,  so they should be able to ping each other. And, of
course, they run STP.

 Box 1                         Box 2

 ----- eth1               eth1 -----
|     |--------Link 1---------|     |
|     |--------Link 2---------|     |
 ----- eth2               eth2 -----

  br1                           br2
10.0.0.1                      10.0.0.2


Let's  assume  Box  1 is elected as the root bridge, and Box 2 has its
eth2  in  BLOCKING  state.  Then br2 shouldn't learn any MAC addresses
from eth2, as proposed by the IEEE Std 802.1D-2004:

> Clause 7.8 The Learning Process
> 
> The Learning Process shall create or update a Dynamic Filtering Entry
> (7.9, 7.9.2) in the Filtering Database, associating the MAC Address in
> the source address field of the frame with the receiving Port, if and
> only if
> a) The receiving Port is in the Learning State or the
> Forwarding State (7.4), and
<other conditions follow, ANDed together>

But,  in my case, it isn't so: "brctl showmacs br2" on Box 2 shows two
permanent  entries  for  the  addresses of local eth1 and eth2 and two
dynamic  entries  for  remote  eth1  and eth2, which are updated every
HELLO_TIME.  Note that if br1 floods non-STP frames (ARP requests, for
example)  out  of its ports, the source addresses get learned by br2's
ports as expected (i.e., by eth1 and not eth2 which is BLOCKING).

Let's  assume  that the MAC address of br1's eth2 is less than that of
eth1.  Then br1 will get its MAC address from eth2 (which is connected
to the link that is seen as BLOCKING by br2, remember?)

Now we've got a problem.

Symptoms.

I'm able to ping Box 2 from Box 1, but, when pinging Box 1 from Box 2,
I  get  packet  losses  about  90%  (for  the  default HELLO_TIME of 2
seconds).

Cause, as it is seen by me.

1) Consider the case when I ping Box 2 from Box 1 (successfully).
a) Box 1 floods an ARP request; Box 2 sees it on its eth1, learns that
the  source is connected to eth1 and unicasts a reply; br1 learns that
br2's MAC address is connected to eth1.
b) ICMP echo request is unicast by br1 through eth1.
c) br2  again  learns that br1's MAC address is connected to eth1 and
unicasts an echo reply.
d) Repeat b) and c) as needed.
All works OK.

2) I ping Box 1 from Box 2.
a) br2  floods  an  ARP  request  (but  its  eth2  is BLOCKING, so it
broadcasts  the request out of eth1); br1 learns that br2 is connected
to eth1 and unicasts a reply; br2 learns about br1 on eth1.
b) br2 unicasts an echo request through eth1 and gets a reply.
c) From  now, b) should have been repeated as many times as needed...
but  as  soon  as  the hello timer of br1 expires, it will send a BPDU
through  eth2.  Then  br2  (incorrectly) assumes that now br1's MAC is
connected  to eth2, which is BLOCKING. So br1 becomes unreachable, and
the following echo requests can't be sent.
d) After  some  time passes, br2 succeeds in sending up to HELLO_TIME
more pings. Maybe it is caused by NUD subsystem, which eventually ARPs
for br2's address to check if it is still can be reached? Flushing the
ARP cache of Box 2 also returns us to the step a).

Note  that  the situation doesn't depend on br2's MAC address (I mean,
is  it  equal  to  its  eth1's  or  eth2's address). However, if br1's
address equals to the address of its eth1, pinging is possible in both
directions, as expected.

I'd  like  to know if the problem is specific to the kernel version or
distribution  I'm  running. Any comments or suggestions will be highly
appreciated. Thanks.

-- 
Best regards,
Oleg


^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [Bridge] Learning BPDU source MACs in BLOCKING state => loss of IP connectivity
  2008-01-26 16:56 [Bridge] Learning BPDU source MACs in BLOCKING state => loss of IP connectivity Oleg Serditov
@ 2008-01-26 17:28 ` Stephen Hemminger
  0 siblings, 0 replies; 2+ messages in thread
From: Stephen Hemminger @ 2008-01-26 17:28 UTC (permalink / raw)
  To: Oleg Serditov; +Cc: bridge

On Sat, 26 Jan 2008 22:56:22 +0600
Oleg Serditov <zir@pinta.ws> wrote:

> Hello to all.
> 
> I'm running 2.6.12, uClinux distribution for the Blackfin processor. I
> am experiencing a problem which prevents two boxes connected by a pair
> of links from being able to ping each other.
>

Fixed in 2.6.23.

commit df1c0b8468b34628ed12b103804a4576cd9af8bb
Author: Stephen Hemminger <shemminger@linux-foundation.org>
Date:   Thu Aug 30 22:15:35 2007 -0700

    [BRIDGE]: Packets leaking out of disabled/blocked ports.
    
    This patch fixes some packet leakage in bridge.  The bridging code was
    allowing forward table entries to be generated even if a device was
    being blocked. The fix is to not add forwarding database entries
    unless the port is active.
    
    The bug arose as part of the conversion to processing STP frames
    through normal receive path (in 2.6.17).
    
    Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org>
    Acked-by: John W. Linville <linville@tuxdriver.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
index 69b7097..eb57502 100644
--- a/net/bridge/br_fdb.c
+++ b/net/bridge/br_fdb.c
@@ -384,6 +384,11 @@ void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source,
 	if (hold_time(br) == 0)
 		return;
 
+	/* ignore packets unless we are using this port */
+	if (!(source->state == BR_STATE_LEARNING ||
+	      source->state == BR_STATE_FORWARDING))
+		return;
+
 	fdb = fdb_find(head, addr);
 	if (likely(fdb)) {
 		/* attempt to update an entry for a local interface */
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index 5c18595..6f468fc 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -101,9 +101,8 @@ static int br_handle_local_finish(struct sk_buff *skb)
 {
 	struct net_bridge_port *p = rcu_dereference(skb->dev->br_port);
 
-	if (p && p->state != BR_STATE_DISABLED)
+	if (p)
 		br_fdb_update(p->br, p, eth_hdr(skb)->h_source);
-
 	return 0;	 /* process further */
 }
 



-- 
Stephen Hemminger <stephen.hemminger@vyatta.com>

^ permalink raw reply related	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2008-01-26 17:28 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-01-26 16:56 [Bridge] Learning BPDU source MACs in BLOCKING state => loss of IP connectivity Oleg Serditov
2008-01-26 17:28 ` Stephen Hemminger

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.