aboutsummaryrefslogtreecommitdiffstats
path: root/net
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
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')
-rw-r--r--net/bridge/br_device.c4
-rw-r--r--net/bridge/br_stp.c35
-rw-r--r--net/bridge/br_stp_timer.c1
3 files changed, 27 insertions, 13 deletions
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index 1461b19efd38..21e5901186ea 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -78,6 +78,8 @@ static int br_dev_open(struct net_device *dev)
78{ 78{
79 struct net_bridge *br = netdev_priv(dev); 79 struct net_bridge *br = netdev_priv(dev);
80 80
81 netif_carrier_off(dev);
82
81 br_features_recompute(br); 83 br_features_recompute(br);
82 netif_start_queue(dev); 84 netif_start_queue(dev);
83 br_stp_enable_bridge(br); 85 br_stp_enable_bridge(br);
@@ -94,6 +96,8 @@ static int br_dev_stop(struct net_device *dev)
94{ 96{
95 struct net_bridge *br = netdev_priv(dev); 97 struct net_bridge *br = netdev_priv(dev);
96 98
99 netif_carrier_off(dev);
100
97 br_stp_disable_bridge(br); 101 br_stp_disable_bridge(br);
98 br_multicast_stop(br); 102 br_multicast_stop(br);
99 103
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 */
diff --git a/net/bridge/br_stp_timer.c b/net/bridge/br_stp_timer.c
index 7b22456023c5..3e965140051e 100644
--- a/net/bridge/br_stp_timer.c
+++ b/net/bridge/br_stp_timer.c
@@ -94,6 +94,7 @@ static void br_forward_delay_timer_expired(unsigned long arg)
94 p->state = BR_STATE_FORWARDING; 94 p->state = BR_STATE_FORWARDING;
95 if (br_is_designated_for_some_port(br)) 95 if (br_is_designated_for_some_port(br))
96 br_topology_change_detection(br); 96 br_topology_change_detection(br);
97 netif_carrier_on(br->dev);
97 } 98 }
98 br_log_state(p); 99 br_log_state(p);
99 spin_unlock(&br->lock); 100 spin_unlock(&br->lock);