Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9cde0708 authored by Stephen Hemminger's avatar Stephen Hemminger Committed by David S. Miller
Browse files

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: default avatarStephen Hemminger <shemminger@linux-foundation.org>
parent 9cf63747
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -203,7 +203,7 @@ static struct net_device *new_bridge_dev(const char *name)
	memcpy(br->group_addr, br_group_address, ETH_ALEN);

	br->feature_mask = dev->features;
	br->stp_enabled = 0;
	br->stp_enabled = BR_NO_STP;
	br->designated_root = br->bridge_id;
	br->root_path_cost = 0;
	br->root_port = 0;
+3 −2
Original line number Diff line number Diff line
@@ -137,7 +137,8 @@ static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
		b.topology_change = br->topology_change;
		b.topology_change_detected = br->topology_change_detected;
		b.root_port = br->root_port;
		b.stp_enabled = br->stp_enabled;

		b.stp_enabled = (br->stp_enabled != BR_NO_STP);
		b.ageing_time = jiffies_to_clock_t(br->ageing_time);
		b.hello_timer_value = br_timer_value(&br->hello_timer);
		b.tcn_timer_value = br_timer_value(&br->tcn_timer);
@@ -251,7 +252,7 @@ static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
		if (!capable(CAP_NET_ADMIN))
			return -EPERM;

		br->stp_enabled = args[1]?1:0;
		br_stp_set_enabled(br, args[1]);
		return 0;

	case BRCTL_SET_BRIDGE_PRIORITY:
+1 −1
Original line number Diff line number Diff line
@@ -165,7 +165,7 @@ static int br_rtm_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
		return -EINVAL;

	/* if kernel STP is running, don't allow changes */
	if (p->br->stp_enabled)
	if (p->br->stp_enabled == BR_KERNEL_STP)
		return -EBUSY;

	if (!netif_running(dev) ||
+12 −3
Original line number Diff line number Diff line
@@ -26,7 +26,10 @@
#define BR_PORT_BITS	10
#define BR_MAX_PORTS	(1<<BR_PORT_BITS)

#define BR_VERSION	"2.2"
#define BR_VERSION	"2.3"

/* Path to usermode spanning tree program */
#define BR_STP_PROG	"/sbin/bridge-stp"

typedef struct bridge_id bridge_id;
typedef struct mac_addr mac_addr;
@@ -107,7 +110,13 @@ struct net_bridge

	u8				group_addr[ETH_ALEN];
	u16				root_port;
	unsigned char			stp_enabled;

	enum {
		BR_NO_STP, 		/* no spanning tree */
		BR_KERNEL_STP,		/* old STP in kernel */
		BR_USER_STP,		/* new RSTP in userspace */
	} stp_enabled;

	unsigned char			topology_change;
	unsigned char			topology_change_detected;

@@ -127,7 +136,6 @@ static inline int br_is_root_bridge(const struct net_bridge *br)
	return !memcmp(&br->bridge_id, &br->designated_root, 8);
}


/* br_device.c */
extern void br_dev_setup(struct net_device *dev);
extern int br_dev_xmit(struct sk_buff *skb, struct net_device *dev);
@@ -209,6 +217,7 @@ extern void br_become_designated_port(struct net_bridge_port *p);
/* br_stp_if.c */
extern void br_stp_enable_bridge(struct net_bridge *br);
extern void br_stp_disable_bridge(struct net_bridge *br);
extern void br_stp_set_enabled(struct net_bridge *br, unsigned long val);
extern void br_stp_enable_port(struct net_bridge_port *p);
extern void br_stp_disable_port(struct net_bridge_port *p);
extern void br_stp_recalculate_bridge_id(struct net_bridge *br);
+7 −3
Original line number Diff line number Diff line
@@ -370,11 +370,11 @@ static void br_make_blocking(struct net_bridge_port *p)
static void br_make_forwarding(struct net_bridge_port *p)
{
	if (p->state == BR_STATE_BLOCKING) {
		if (p->br->stp_enabled) {
		if (p->br->stp_enabled == BR_KERNEL_STP)
			p->state = BR_STATE_LISTENING;
		} else {
		else
			p->state = BR_STATE_LEARNING;
		}

		br_log_state(p);
		mod_timer(&p->forward_delay_timer, jiffies + p->br->forward_delay);	}
}
@@ -384,6 +384,10 @@ void br_port_state_selection(struct net_bridge *br)
{
	struct net_bridge_port *p;

	/* Don't change port states if userspace is handling STP */
	if (br->stp_enabled == BR_USER_STP)
		return;

	list_for_each_entry(p, &br->port_list, list) {
		if (p->state != BR_STATE_DISABLED) {
			if (p->port_no == br->root_port) {
Loading