Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
br_notify.c
Go to the documentation of this file.
1 /*
2  * Device event handling
3  * Linux ethernet bridge
4  *
5  * Authors:
6  * Lennert Buytenhek <[email protected]>
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 
20 static int br_device_event(struct notifier_block *unused, unsigned long event, void *ptr);
21 
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  */
32 static 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;
36  struct net_bridge *br;
37  bool changed_addr;
38  int err;
39 
40  /* register of bridge completed, add sysfs entries */
41  if ((dev->priv_flags & IFF_EBRIDGE) && event == NETDEV_REGISTER) {
42  br_sysfs_addbr(dev);
43  return NOTIFY_DONE;
44  }
45 
46  /* not a port of a bridge */
47  p = br_port_get_rtnl(dev);
48  if (!p)
49  return NOTIFY_DONE;
50 
51  br = p->br;
52 
53  switch (event) {
54  case NETDEV_CHANGEMTU:
55  dev_set_mtu(br->dev, br_min_mtu(br));
56  break;
57 
58  case NETDEV_CHANGEADDR:
59  spin_lock_bh(&br->lock);
60  br_fdb_changeaddr(p, dev->dev_addr);
61  changed_addr = br_stp_recalculate_bridge_id(br);
62  spin_unlock_bh(&br->lock);
63 
64  if (changed_addr)
66 
67  break;
68 
69  case NETDEV_CHANGE:
71  break;
72 
73  case NETDEV_FEAT_CHANGE:
75  break;
76 
77  case NETDEV_DOWN:
78  spin_lock_bh(&br->lock);
79  if (br->dev->flags & IFF_UP)
81  spin_unlock_bh(&br->lock);
82  break;
83 
84  case NETDEV_UP:
85  if (netif_carrier_ok(dev) && (br->dev->flags & IFF_UP)) {
86  spin_lock_bh(&br->lock);
88  spin_unlock_bh(&br->lock);
89  }
90  break;
91 
92  case NETDEV_UNREGISTER:
93  br_del_if(br, dev);
94  break;
95 
96  case NETDEV_CHANGENAME:
97  err = br_sysfs_renameif(p);
98  if (err)
99  return notifier_from_errno(err);
100  break;
101 
103  /* Forbid underlaying device to change its type. */
104  return NOTIFY_BAD;
105  }
106 
107  /* Events that may cause spanning tree to refresh */
108  if (event == NETDEV_CHANGEADDR || event == NETDEV_UP ||
109  event == NETDEV_CHANGE || event == NETDEV_DOWN)
111 
112  return NOTIFY_DONE;
113 }