aboutsummaryrefslogtreecommitdiffstats
path: root/net/bridge/br_stp_if.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/bridge/br_stp_if.c')
-rw-r--r--net/bridge/br_stp_if.c59
1 files changed, 56 insertions, 3 deletions
diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c
index a285897a2fb4..3e246b37020e 100644
--- a/net/bridge/br_stp_if.c
+++ b/net/bridge/br_stp_if.c
@@ -87,7 +87,6 @@ void br_stp_disable_bridge(struct net_bridge *br)
87void br_stp_enable_port(struct net_bridge_port *p) 87void br_stp_enable_port(struct net_bridge_port *p)
88{ 88{
89 br_init_port(p); 89 br_init_port(p);
90 br_ifinfo_notify(RTM_NEWLINK, p);
91 br_port_state_selection(p->br); 90 br_port_state_selection(p->br);
92} 91}
93 92
@@ -101,8 +100,6 @@ void br_stp_disable_port(struct net_bridge_port *p)
101 printk(KERN_INFO "%s: port %i(%s) entering %s state\n", 100 printk(KERN_INFO "%s: port %i(%s) entering %s state\n",
102 br->dev->name, p->port_no, p->dev->name, "disabled"); 101 br->dev->name, p->port_no, p->dev->name, "disabled");
103 102
104 br_ifinfo_notify(RTM_DELLINK, p);
105
106 wasroot = br_is_root_bridge(br); 103 wasroot = br_is_root_bridge(br);
107 br_become_designated_port(p); 104 br_become_designated_port(p);
108 p->state = BR_STATE_DISABLED; 105 p->state = BR_STATE_DISABLED;
@@ -123,6 +120,62 @@ void br_stp_disable_port(struct net_bridge_port *p)
123 br_become_root_bridge(br); 120 br_become_root_bridge(br);
124} 121}
125 122
123static void br_stp_start(struct net_bridge *br)
124{
125 int r;
126 char *argv[] = { BR_STP_PROG, br->dev->name, "start", NULL };
127 char *envp[] = { NULL };
128
129 r = call_usermodehelper(BR_STP_PROG, argv, envp, 1);
130 if (r == 0) {
131 br->stp_enabled = BR_USER_STP;
132 printk(KERN_INFO "%s: userspace STP started\n", br->dev->name);
133 } else {
134 br->stp_enabled = BR_KERNEL_STP;
135 printk(KERN_INFO "%s: starting userspace STP failed, "
136 "staring kernel STP\n", br->dev->name);
137
138 /* To start timers on any ports left in blocking */
139 spin_lock_bh(&br->lock);
140 br_port_state_selection(br);
141 spin_unlock_bh(&br->lock);
142 }
143}
144
145static void br_stp_stop(struct net_bridge *br)
146{
147 int r;
148 char *argv[] = { BR_STP_PROG, br->dev->name, "stop", NULL };
149 char *envp[] = { NULL };
150
151 if (br->stp_enabled == BR_USER_STP) {
152 r = call_usermodehelper(BR_STP_PROG, argv, envp, 1);
153 printk(KERN_INFO "%s: userspace STP stopped, return code %d\n",
154 br->dev->name, r);
155
156
157 /* To start timers on any ports left in blocking */
158 spin_lock_bh(&br->lock);
159 br_port_state_selection(br);
160 spin_unlock_bh(&br->lock);
161 }
162
163 br->stp_enabled = BR_NO_STP;
164}
165
166void br_stp_set_enabled(struct net_bridge *br, unsigned long val)
167{
168 ASSERT_RTNL();
169
170 if (val) {
171 if (br->stp_enabled == BR_NO_STP)
172 br_stp_start(br);
173 } else {
174 if (br->stp_enabled != BR_NO_STP)
175 br_stp_stop(br);
176 }
177}
178
126/* called under bridge lock */ 179/* called under bridge lock */
127void br_stp_change_bridge_id(struct net_bridge *br, const unsigned char *addr) 180void br_stp_change_bridge_id(struct net_bridge *br, const unsigned char *addr)
128{ 181{