bridge: add support for user mode STP
This patchset based on work by Aji_Srinivas@emc.com provides allows spanning tree to be controled from userspace. Like hotplug, it uses call_usermodehelper when spanning tree is enabled so there is no visible API change. If call to start usermode STP fails it falls back to existing kernel STP. Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org>
This commit is contained in:
committed by
David S. Miller
parent
9cf637473c
commit
9cde070874
@@ -123,6 +123,62 @@ void br_stp_disable_port(struct net_bridge_port *p)
|
||||
br_become_root_bridge(br);
|
||||
}
|
||||
|
||||
static void br_stp_start(struct net_bridge *br)
|
||||
{
|
||||
int r;
|
||||
char *argv[] = { BR_STP_PROG, br->dev->name, "start", NULL };
|
||||
char *envp[] = { NULL };
|
||||
|
||||
r = call_usermodehelper(BR_STP_PROG, argv, envp, 1);
|
||||
if (r == 0) {
|
||||
br->stp_enabled = BR_USER_STP;
|
||||
printk(KERN_INFO "%s: userspace STP started\n", br->dev->name);
|
||||
} else {
|
||||
br->stp_enabled = BR_KERNEL_STP;
|
||||
printk(KERN_INFO "%s: starting userspace STP failed, "
|
||||
"staring kernel STP\n", br->dev->name);
|
||||
|
||||
/* To start timers on any ports left in blocking */
|
||||
spin_lock_bh(&br->lock);
|
||||
br_port_state_selection(br);
|
||||
spin_unlock_bh(&br->lock);
|
||||
}
|
||||
}
|
||||
|
||||
static void br_stp_stop(struct net_bridge *br)
|
||||
{
|
||||
int r;
|
||||
char *argv[] = { BR_STP_PROG, br->dev->name, "stop", NULL };
|
||||
char *envp[] = { NULL };
|
||||
|
||||
if (br->stp_enabled == BR_USER_STP) {
|
||||
r = call_usermodehelper(BR_STP_PROG, argv, envp, 1);
|
||||
printk(KERN_INFO "%s: userspace STP stopped, return code %d\n",
|
||||
br->dev->name, r);
|
||||
|
||||
|
||||
/* To start timers on any ports left in blocking */
|
||||
spin_lock_bh(&br->lock);
|
||||
br_port_state_selection(br);
|
||||
spin_unlock_bh(&br->lock);
|
||||
}
|
||||
|
||||
br->stp_enabled = BR_NO_STP;
|
||||
}
|
||||
|
||||
void br_stp_set_enabled(struct net_bridge *br, unsigned long val)
|
||||
{
|
||||
ASSERT_RTNL();
|
||||
|
||||
if (val) {
|
||||
if (br->stp_enabled == BR_NO_STP)
|
||||
br_stp_start(br);
|
||||
} else {
|
||||
if (br->stp_enabled != BR_NO_STP)
|
||||
br_stp_stop(br);
|
||||
}
|
||||
}
|
||||
|
||||
/* called under bridge lock */
|
||||
void br_stp_change_bridge_id(struct net_bridge *br, const unsigned char *addr)
|
||||
{
|
||||
|
Reference in New Issue
Block a user