X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=net%2Fbridge%2Fbr_notify.c;h=f8fb49e34764e86cc8884c32b2ee924d512b3365;hb=c7b5ebbddf7bcd3651947760f423e3783bbe6573;hp=594bb5bca5d7f46725634c82025fa5ff5c7aee59;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/net/bridge/br_notify.c b/net/bridge/br_notify.c index 594bb5bca..f8fb49e34 100644 --- a/net/bridge/br_notify.c +++ b/net/bridge/br_notify.c @@ -19,32 +19,50 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, void *ptr); -struct notifier_block br_device_notifier = -{ +struct notifier_block br_device_notifier = { .notifier_call = br_device_event }; +/* + * Handle changes in state of network devices enslaved to a bridge. + * + * Note: don't care about up/down if bridge itself is down, because + * port state is checked when bridge is brought up. + */ static int br_device_event(struct notifier_block *unused, unsigned long event, void *ptr) { - struct net_device *dev; - struct net_bridge_port *p; + struct net_device *dev = ptr; + struct net_bridge_port *p = dev->br_port; struct net_bridge *br; - dev = ptr; - p = dev->br_port; - + /* not a port of a bridge */ if (p == NULL) return NOTIFY_DONE; br = p->br; spin_lock_bh(&br->lock); - switch (event) - { + switch (event) { + case NETDEV_CHANGEMTU: + dev_set_mtu(br->dev, br_min_mtu(br)); + break; + case NETDEV_CHANGEADDR: br_fdb_changeaddr(p, dev->dev_addr); - if (br->dev->flags & IFF_UP) - br_stp_recalculate_bridge_id(br); + br_stp_recalculate_bridge_id(br); + break; + + case NETDEV_CHANGE: /* device is up but carrier changed */ + if (!(br->dev->flags & IFF_UP)) + break; + + if (netif_carrier_ok(dev)) { + if (p->state == BR_STATE_DISABLED) + br_stp_enable_port(p); + } else { + if (p->state != BR_STATE_DISABLED) + br_stp_disable_port(p); + } break; case NETDEV_DOWN: @@ -53,15 +71,17 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, v break; case NETDEV_UP: - if (br->dev->flags & IFF_UP) + if (netif_carrier_ok(dev) && (br->dev->flags & IFF_UP)) br_stp_enable_port(p); break; case NETDEV_UNREGISTER: + spin_unlock_bh(&br->lock); br_del_if(br, dev); - break; - } + goto done; + } spin_unlock_bh(&br->lock); + done: return NOTIFY_DONE; }