aboutsummaryrefslogtreecommitdiffstats
path: root/net/bridge/br_stp.c
diff options
context:
space:
mode:
authorstephen hemminger <shemminger@vyatta.com>2011-03-07 03:34:06 -0500
committerDavid S. Miller <davem@davemloft.net>2011-03-14 17:29:02 -0400
commit1faa4356a3bd89ea11fb92752d897cff3a20ec0e (patch)
tree31bf972b0ee42105bceb79e09f2a8b82d9d9b942 /net/bridge/br_stp.c
parent942527634e201883b39fe0c97a1e47db7a026f91 (diff)
bridge: control carrier based on ports online
This makes the bridge device behave like a physical device. In earlier releases the bridge always asserted carrier. This changes the behavior so that bridge device carrier is on only if one or more ports are in the forwarding state. This should help IPv6 autoconfiguration, DHCP, and routing daemons. I did brief testing with Network and Virt manager and they seem fine, but since this changes behavior of bridge, it should wait until net-next (2.6.39). Signed-off-by: Stephen Hemminger <shemminger@vyatta.com> Reviewed-by: Nicolas de Pesloüan <nicolas.2p.debian@free.fr> Tested-By: Adam Majer <adamm@zombino.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/bridge/br_stp.c')
-rw-r--r--net/bridge/br_stp.c35
1 files changed, 22 insertions, 13 deletions
diff --git a/net/bridge/br_stp.c b/net/bridge/br_stp.c
index 57186d84d2bd..a5badd0f8226 100644
--- a/net/bridge/br_stp.c
+++ b/net/bridge/br_stp.c
@@ -397,28 +397,37 @@ static void br_make_forwarding(struct net_bridge_port *p)
397void br_port_state_selection(struct net_bridge *br) 397void br_port_state_selection(struct net_bridge *br)
398{ 398{
399 struct net_bridge_port *p; 399 struct net_bridge_port *p;
400 unsigned int liveports = 0;
400 401
401 /* Don't change port states if userspace is handling STP */ 402 /* Don't change port states if userspace is handling STP */
402 if (br->stp_enabled == BR_USER_STP) 403 if (br->stp_enabled == BR_USER_STP)
403 return; 404 return;
404 405
405 list_for_each_entry(p, &br->port_list, list) { 406 list_for_each_entry(p, &br->port_list, list) {
406 if (p->state != BR_STATE_DISABLED) { 407 if (p->state == BR_STATE_DISABLED)
407 if (p->port_no == br->root_port) { 408 continue;
408 p->config_pending = 0; 409
409 p->topology_change_ack = 0; 410 if (p->port_no == br->root_port) {
410 br_make_forwarding(p); 411 p->config_pending = 0;
411 } else if (br_is_designated_port(p)) { 412 p->topology_change_ack = 0;
412 del_timer(&p->message_age_timer); 413 br_make_forwarding(p);
413 br_make_forwarding(p); 414 } else if (br_is_designated_port(p)) {
414 } else { 415 del_timer(&p->message_age_timer);
415 p->config_pending = 0; 416 br_make_forwarding(p);
416 p->topology_change_ack = 0; 417 } else {
417 br_make_blocking(p); 418 p->config_pending = 0;
418 } 419 p->topology_change_ack = 0;
420 br_make_blocking(p);
419 } 421 }
420 422
423 if (p->state == BR_STATE_FORWARDING)
424 ++liveports;
421 } 425 }
426
427 if (liveports == 0)
428 netif_carrier_off(br->dev);
429 else
430 netif_carrier_on(br->dev);
422} 431}
423 432
424/* called under bridge lock */ 433/* called under bridge lock */