diff options
Diffstat (limited to 'net/bridge/br_stp_if.c')
-rw-r--r-- | net/bridge/br_stp_if.c | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c index a285897a2fb4..1c1806d7c489 100644 --- a/net/bridge/br_stp_if.c +++ b/net/bridge/br_stp_if.c | |||
@@ -123,6 +123,62 @@ void br_stp_disable_port(struct net_bridge_port *p) | |||
123 | br_become_root_bridge(br); | 123 | br_become_root_bridge(br); |
124 | } | 124 | } |
125 | 125 | ||
126 | static void br_stp_start(struct net_bridge *br) | ||
127 | { | ||
128 | int r; | ||
129 | char *argv[] = { BR_STP_PROG, br->dev->name, "start", NULL }; | ||
130 | char *envp[] = { NULL }; | ||
131 | |||
132 | r = call_usermodehelper(BR_STP_PROG, argv, envp, 1); | ||
133 | if (r == 0) { | ||
134 | br->stp_enabled = BR_USER_STP; | ||
135 | printk(KERN_INFO "%s: userspace STP started\n", br->dev->name); | ||
136 | } else { | ||
137 | br->stp_enabled = BR_KERNEL_STP; | ||
138 | printk(KERN_INFO "%s: starting userspace STP failed, " | ||
139 | "staring kernel STP\n", br->dev->name); | ||
140 | |||
141 | /* To start timers on any ports left in blocking */ | ||
142 | spin_lock_bh(&br->lock); | ||
143 | br_port_state_selection(br); | ||
144 | spin_unlock_bh(&br->lock); | ||
145 | } | ||
146 | } | ||
147 | |||
148 | static void br_stp_stop(struct net_bridge *br) | ||
149 | { | ||
150 | int r; | ||
151 | char *argv[] = { BR_STP_PROG, br->dev->name, "stop", NULL }; | ||
152 | char *envp[] = { NULL }; | ||
153 | |||
154 | if (br->stp_enabled == BR_USER_STP) { | ||
155 | r = call_usermodehelper(BR_STP_PROG, argv, envp, 1); | ||
156 | printk(KERN_INFO "%s: userspace STP stopped, return code %d\n", | ||
157 | br->dev->name, r); | ||
158 | |||
159 | |||
160 | /* To start timers on any ports left in blocking */ | ||
161 | spin_lock_bh(&br->lock); | ||
162 | br_port_state_selection(br); | ||
163 | spin_unlock_bh(&br->lock); | ||
164 | } | ||
165 | |||
166 | br->stp_enabled = BR_NO_STP; | ||
167 | } | ||
168 | |||
169 | void br_stp_set_enabled(struct net_bridge *br, unsigned long val) | ||
170 | { | ||
171 | ASSERT_RTNL(); | ||
172 | |||
173 | if (val) { | ||
174 | if (br->stp_enabled == BR_NO_STP) | ||
175 | br_stp_start(br); | ||
176 | } else { | ||
177 | if (br->stp_enabled != BR_NO_STP) | ||
178 | br_stp_stop(br); | ||
179 | } | ||
180 | } | ||
181 | |||
126 | /* called under bridge lock */ | 182 | /* called under bridge lock */ |
127 | void br_stp_change_bridge_id(struct net_bridge *br, const unsigned char *addr) | 183 | void br_stp_change_bridge_id(struct net_bridge *br, const unsigned char *addr) |
128 | { | 184 | { |