Commit 76b91c32 authored by Nikolay Aleksandrov's avatar Nikolay Aleksandrov Committed by David S. Miller
Browse files

bridge: stp: when using userspace stp stop kernel hello and hold timers



These should be handled only by the respective STP which is in control.
They become problematic for devices with limited resources with many
ports because the hold_timer is per port and fires each second and the
hello timer fires each 2 seconds even though it's global. While in
user-space STP mode these timers are completely unnecessary so it's better
to keep them off.
Also ensure that when the bridge is up these timers are started only when
running with kernel STP.

Signed-off-by: default avatarSatish Ashok <sashok@cumulusnetworks.com>
Signed-off-by: default avatarNikolay Aleksandrov <nikolay@cumulusnetworks.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 158cd4af
Loading
Loading
Loading
Loading
+3 −2
Original line number Original line Diff line number Diff line
@@ -209,6 +209,7 @@ void br_transmit_config(struct net_bridge_port *p)
		br_send_config_bpdu(p, &bpdu);
		br_send_config_bpdu(p, &bpdu);
		p->topology_change_ack = 0;
		p->topology_change_ack = 0;
		p->config_pending = 0;
		p->config_pending = 0;
		if (p->br->stp_enabled == BR_KERNEL_STP)
			mod_timer(&p->hold_timer,
			mod_timer(&p->hold_timer,
				  round_jiffies(jiffies + BR_HOLD_TIME));
				  round_jiffies(jiffies + BR_HOLD_TIME));
	}
	}
+12 −1
Original line number Original line Diff line number Diff line
@@ -48,6 +48,7 @@ void br_stp_enable_bridge(struct net_bridge *br)
	struct net_bridge_port *p;
	struct net_bridge_port *p;


	spin_lock_bh(&br->lock);
	spin_lock_bh(&br->lock);
	if (br->stp_enabled == BR_KERNEL_STP)
		mod_timer(&br->hello_timer, jiffies + br->hello_time);
		mod_timer(&br->hello_timer, jiffies + br->hello_time);
	mod_timer(&br->gc_timer, jiffies + HZ/10);
	mod_timer(&br->gc_timer, jiffies + HZ/10);


@@ -127,6 +128,7 @@ static void br_stp_start(struct net_bridge *br)
	int r;
	int r;
	char *argv[] = { BR_STP_PROG, br->dev->name, "start", NULL };
	char *argv[] = { BR_STP_PROG, br->dev->name, "start", NULL };
	char *envp[] = { NULL };
	char *envp[] = { NULL };
	struct net_bridge_port *p;


	r = call_usermodehelper(BR_STP_PROG, argv, envp, UMH_WAIT_PROC);
	r = call_usermodehelper(BR_STP_PROG, argv, envp, UMH_WAIT_PROC);


@@ -140,6 +142,10 @@ static void br_stp_start(struct net_bridge *br)
	if (r == 0) {
	if (r == 0) {
		br->stp_enabled = BR_USER_STP;
		br->stp_enabled = BR_USER_STP;
		br_debug(br, "userspace STP started\n");
		br_debug(br, "userspace STP started\n");
		/* Stop hello and hold timers */
		del_timer(&br->hello_timer);
		list_for_each_entry(p, &br->port_list, list)
			del_timer(&p->hold_timer);
	} else {
	} else {
		br->stp_enabled = BR_KERNEL_STP;
		br->stp_enabled = BR_KERNEL_STP;
		br_debug(br, "using kernel STP\n");
		br_debug(br, "using kernel STP\n");
@@ -156,12 +162,17 @@ static void br_stp_stop(struct net_bridge *br)
	int r;
	int r;
	char *argv[] = { BR_STP_PROG, br->dev->name, "stop", NULL };
	char *argv[] = { BR_STP_PROG, br->dev->name, "stop", NULL };
	char *envp[] = { NULL };
	char *envp[] = { NULL };
	struct net_bridge_port *p;


	if (br->stp_enabled == BR_USER_STP) {
	if (br->stp_enabled == BR_USER_STP) {
		r = call_usermodehelper(BR_STP_PROG, argv, envp, UMH_WAIT_PROC);
		r = call_usermodehelper(BR_STP_PROG, argv, envp, UMH_WAIT_PROC);
		br_info(br, "userspace STP stopped, return code %d\n", r);
		br_info(br, "userspace STP stopped, return code %d\n", r);


		/* To start timers on any ports left in blocking */
		/* To start timers on any ports left in blocking */
		mod_timer(&br->hello_timer, jiffies + br->hello_time);
		list_for_each_entry(p, &br->port_list, list)
			mod_timer(&p->hold_timer,
				  round_jiffies(jiffies + BR_HOLD_TIME));
		spin_lock_bh(&br->lock);
		spin_lock_bh(&br->lock);
		br_port_state_selection(br);
		br_port_state_selection(br);
		spin_unlock_bh(&br->lock);
		spin_unlock_bh(&br->lock);
+3 −1
Original line number Original line Diff line number Diff line
@@ -40,7 +40,9 @@ static void br_hello_timer_expired(unsigned long arg)
	if (br->dev->flags & IFF_UP) {
	if (br->dev->flags & IFF_UP) {
		br_config_bpdu_generation(br);
		br_config_bpdu_generation(br);


		mod_timer(&br->hello_timer, round_jiffies(jiffies + br->hello_time));
		if (br->stp_enabled != BR_USER_STP)
			mod_timer(&br->hello_timer,
				  round_jiffies(jiffies + br->hello_time));
	}
	}
	spin_unlock(&br->lock);
	spin_unlock(&br->lock);
}
}