1/* 2 * Device event handling 3 * Linux ethernet bridge 4 * 5 * Authors: 6 * Lennert Buytenhek <buytenh@gnu.org> 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License 10 * as published by the Free Software Foundation; either version 11 * 2 of the License, or (at your option) any later version. 12 */ 13 14#include <linux/kernel.h> 15#include <linux/rtnetlink.h> 16#include <net/net_namespace.h> 17 18#include "br_private.h" 19 20static int br_device_event(struct notifier_block *unused, unsigned long event, void *ptr); 21 22struct notifier_block br_device_notifier = { 23 .notifier_call = br_device_event 24}; 25 26/* 27 * Handle changes in state of network devices enslaved to a bridge. 28 * 29 * Note: don't care about up/down if bridge itself is down, because 30 * port state is checked when bridge is brought up. 31 */ 32static int br_device_event(struct notifier_block *unused, unsigned long event, void *ptr) 33{ 34 struct net_device *dev = ptr; 35 struct net_bridge_port *p = br_port_get(dev); 36 struct net_bridge *br; 37 int err; 38 39 /* not a port of a bridge */ 40 if (!br_port_exists(dev)) 41 return NOTIFY_DONE; 42 43 p = br_port_get(dev); 44 br = p->br; 45 46 switch (event) { 47 case NETDEV_CHANGEMTU: 48 dev_set_mtu(br->dev, br_min_mtu(br)); 49 break; 50 51 case NETDEV_CHANGEADDR: 52 spin_lock_bh(&br->lock); 53 br_fdb_changeaddr(p, dev->dev_addr); 54 br_stp_recalculate_bridge_id(br); 55 spin_unlock_bh(&br->lock); 56 break; 57 58 case NETDEV_CHANGE: 59 br_port_carrier_check(p); 60 break; 61 62 case NETDEV_FEAT_CHANGE: 63 spin_lock_bh(&br->lock); 64 if (netif_running(br->dev)) 65 br_features_recompute(br); 66 spin_unlock_bh(&br->lock); 67 break; 68 69 case NETDEV_DOWN: 70 spin_lock_bh(&br->lock); 71 if (br->dev->flags & IFF_UP) 72 br_stp_disable_port(p); 73 spin_unlock_bh(&br->lock); 74 break; 75 76 case NETDEV_UP: 77 if (netif_carrier_ok(dev) && (br->dev->flags & IFF_UP)) { 78 spin_lock_bh(&br->lock); 79 br_stp_enable_port(p); 80 spin_unlock_bh(&br->lock); 81 } 82 break; 83 84 case NETDEV_UNREGISTER: 85 br_del_if(br, dev); 86 break; 87 88 case NETDEV_CHANGENAME: 89 err = br_sysfs_renameif(p); 90 if (err) 91 return notifier_from_errno(err); 92 break; 93 94 case NETDEV_PRE_TYPE_CHANGE: 95 /* Forbid underlaying device to change its type. */ 96 return NOTIFY_BAD; 97 } 98 99 /* Events that may cause spanning tree to refresh */ 100 if (event == NETDEV_CHANGEADDR || event == NETDEV_UP || 101 event == NETDEV_CHANGE || event == NETDEV_DOWN) 102 br_ifinfo_notify(RTM_NEWLINK, p); 103 104 return NOTIFY_DONE; 105} 106