X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=net%2Fbridge%2Fbr_notify.c;h=d0702fbcb21de7373e97402b26388d772e7ac0b4;hb=9bf4aaab3e101692164d49b7ca357651eb691cb6;hp=c59335e3b49b126ca6f52f6fc9960d5dbb6a00b7;hpb=db216c3d5e4c040e557a50f8f5d35d5c415e8c1c;p=linux-2.6.git diff --git a/net/bridge/br_notify.c b/net/bridge/br_notify.c index c59335e3b..d0702fbcb 100644 --- a/net/bridge/br_notify.c +++ b/net/bridge/br_notify.c @@ -19,54 +19,67 @@ 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) { + case NETDEV_CHANGEMTU: + dev_set_mtu(br->dev, br_min_mtu(br)); + break; + case NETDEV_CHANGEADDR: - spin_lock_bh(&br->lock); br_fdb_changeaddr(p, dev->dev_addr); - if (br->dev->flags & IFF_UP) - br_stp_recalculate_bridge_id(br); - spin_unlock_bh(&br->lock); + 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: - if (br->dev->flags & IFF_UP) { - spin_lock_bh(&br->lock); + if (br->dev->flags & IFF_UP) br_stp_disable_port(p); - spin_unlock_bh(&br->lock); - } break; case NETDEV_UP: - if (br->dev->flags & IFF_UP) { - spin_lock_bh(&br->lock); + if (netif_carrier_ok(dev) && (br->dev->flags & IFF_UP)) br_stp_enable_port(p); - spin_unlock_bh(&br->lock); - } break; case NETDEV_UNREGISTER: br_del_if(br, dev); break; - } + } + spin_unlock_bh(&br->lock); return NOTIFY_DONE; }