• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6.36/net/bridge/
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