| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  *	Spanning tree protocol; interface code | 
					
						
							|  |  |  |  *	Linux ethernet bridge | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *	Authors: | 
					
						
							|  |  |  |  *	Lennert Buytenhek		<buytenh@gnu.org> | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *	This program is free software; you can redistribute it and/or | 
					
						
							|  |  |  |  *	modify it under the terms of the GNU General Public License | 
					
						
							|  |  |  |  *	as published by the Free Software Foundation; either version | 
					
						
							|  |  |  |  *	2 of the License, or (at your option) any later version. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <linux/kernel.h>
 | 
					
						
							| 
									
										
										
										
											2011-08-29 17:55:05 -04:00
										 |  |  | #include <linux/kmod.h>
 | 
					
						
							| 
									
										
										
										
											2005-10-25 15:04:59 -07:00
										 |  |  | #include <linux/etherdevice.h>
 | 
					
						
							| 
									
										
										
										
											2006-05-25 16:00:12 -07:00
										 |  |  | #include <linux/rtnetlink.h>
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "br_private.h"
 | 
					
						
							|  |  |  | #include "br_private_stp.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Port id is composed of priority and port number.
 | 
					
						
							| 
									
										
										
										
											2011-04-04 14:03:33 +00:00
										 |  |  |  * NB: some bits of priority are dropped to | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  |  *     make room for more ports. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static inline port_id br_make_port_id(__u8 priority, __u16 port_no) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2007-02-09 23:24:35 +09:00
										 |  |  | 	return ((u16)priority << BR_PORT_BITS) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		| (port_no & ((1<<BR_PORT_BITS)-1)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-04 14:03:33 +00:00
										 |  |  | #define BR_MAX_PORT_PRIORITY ((u16)~0 >> BR_PORT_BITS)
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | /* called under bridge lock */ | 
					
						
							|  |  |  | void br_init_port(struct net_bridge_port *p) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	p->port_id = br_make_port_id(p->priority, p->port_no); | 
					
						
							|  |  |  | 	br_become_designated_port(p); | 
					
						
							|  |  |  | 	p->state = BR_STATE_BLOCKING; | 
					
						
							|  |  |  | 	p->topology_change_ack = 0; | 
					
						
							|  |  |  | 	p->config_pending = 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* called under bridge lock */ | 
					
						
							|  |  |  | void br_stp_enable_bridge(struct net_bridge *br) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct net_bridge_port *p; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	spin_lock_bh(&br->lock); | 
					
						
							|  |  |  | 	mod_timer(&br->hello_timer, jiffies + br->hello_time); | 
					
						
							|  |  |  | 	mod_timer(&br->gc_timer, jiffies + HZ/10); | 
					
						
							| 
									
										
										
										
											2007-02-09 23:24:35 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	br_config_bpdu_generation(br); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	list_for_each_entry(p, &br->port_list, list) { | 
					
						
							| 
									
										
										
										
											2012-12-28 18:15:22 +00:00
										 |  |  | 		if (netif_running(p->dev) && netif_oper_up(p->dev)) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 			br_stp_enable_port(p); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	spin_unlock_bh(&br->lock); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* NO locks held */ | 
					
						
							|  |  |  | void br_stp_disable_bridge(struct net_bridge *br) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct net_bridge_port *p; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-02-15 01:47:48 -08:00
										 |  |  | 	spin_lock_bh(&br->lock); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	list_for_each_entry(p, &br->port_list, list) { | 
					
						
							|  |  |  | 		if (p->state != BR_STATE_DISABLED) | 
					
						
							|  |  |  | 			br_stp_disable_port(p); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	br->topology_change = 0; | 
					
						
							|  |  |  | 	br->topology_change_detected = 0; | 
					
						
							| 
									
										
										
										
											2006-02-15 01:47:48 -08:00
										 |  |  | 	spin_unlock_bh(&br->lock); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	del_timer_sync(&br->hello_timer); | 
					
						
							|  |  |  | 	del_timer_sync(&br->topology_change_timer); | 
					
						
							|  |  |  | 	del_timer_sync(&br->tcn_timer); | 
					
						
							|  |  |  | 	del_timer_sync(&br->gc_timer); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* called under bridge lock */ | 
					
						
							|  |  |  | void br_stp_enable_port(struct net_bridge_port *p) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	br_init_port(p); | 
					
						
							|  |  |  | 	br_port_state_selection(p->br); | 
					
						
							| 
									
										
										
										
											2010-05-10 09:31:09 +00:00
										 |  |  | 	br_log_state(p); | 
					
						
							| 
									
										
										
										
											2011-07-22 07:47:09 +00:00
										 |  |  | 	br_ifinfo_notify(RTM_NEWLINK, p); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* called under bridge lock */ | 
					
						
							|  |  |  | void br_stp_disable_port(struct net_bridge_port *p) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-10 09:31:09 +00:00
										 |  |  | 	struct net_bridge *br = p->br; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	int wasroot; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	wasroot = br_is_root_bridge(br); | 
					
						
							|  |  |  | 	br_become_designated_port(p); | 
					
						
							|  |  |  | 	p->state = BR_STATE_DISABLED; | 
					
						
							|  |  |  | 	p->topology_change_ack = 0; | 
					
						
							|  |  |  | 	p->config_pending = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-06 22:25:22 +00:00
										 |  |  | 	br_log_state(p); | 
					
						
							| 
									
										
										
										
											2011-07-22 07:47:09 +00:00
										 |  |  | 	br_ifinfo_notify(RTM_NEWLINK, p); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	del_timer(&p->message_age_timer); | 
					
						
							|  |  |  | 	del_timer(&p->forward_delay_timer); | 
					
						
							|  |  |  | 	del_timer(&p->hold_timer); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-10-12 14:45:38 -07:00
										 |  |  | 	br_fdb_delete_by_port(br, p, 0); | 
					
						
							| 
									
										
										
										
											2010-02-28 00:49:38 -08:00
										 |  |  | 	br_multicast_disable_port(p); | 
					
						
							| 
									
										
										
										
											2006-10-12 14:45:38 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	br_configuration_update(br); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	br_port_state_selection(br); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (br_is_root_bridge(br) && !wasroot) | 
					
						
							|  |  |  | 		br_become_root_bridge(br); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-03-21 14:22:44 -07:00
										 |  |  | static void br_stp_start(struct net_bridge *br) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int r; | 
					
						
							|  |  |  | 	char *argv[] = { BR_STP_PROG, br->dev->name, "start", NULL }; | 
					
						
							|  |  |  | 	char *envp[] = { NULL }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-07-17 18:37:03 -07:00
										 |  |  | 	r = call_usermodehelper(BR_STP_PROG, argv, envp, UMH_WAIT_PROC); | 
					
						
							| 
									
										
										
										
											2013-09-12 17:12:05 +10:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	spin_lock_bh(&br->lock); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (br->bridge_forward_delay < BR_MIN_FORWARD_DELAY) | 
					
						
							|  |  |  | 		__br_set_forward_delay(br, BR_MIN_FORWARD_DELAY); | 
					
						
							| 
									
										
										
										
											2013-10-15 14:57:45 -04:00
										 |  |  | 	else if (br->bridge_forward_delay > BR_MAX_FORWARD_DELAY) | 
					
						
							| 
									
										
										
										
											2013-09-12 17:12:05 +10:00
										 |  |  | 		__br_set_forward_delay(br, BR_MAX_FORWARD_DELAY); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-03-21 14:22:44 -07:00
										 |  |  | 	if (r == 0) { | 
					
						
							|  |  |  | 		br->stp_enabled = BR_USER_STP; | 
					
						
							| 
									
										
										
										
											2010-05-10 09:31:09 +00:00
										 |  |  | 		br_debug(br, "userspace STP started\n"); | 
					
						
							| 
									
										
										
										
											2007-03-21 14:22:44 -07:00
										 |  |  | 	} else { | 
					
						
							|  |  |  | 		br->stp_enabled = BR_KERNEL_STP; | 
					
						
							| 
									
										
										
										
											2010-05-10 09:31:09 +00:00
										 |  |  | 		br_debug(br, "using kernel STP\n"); | 
					
						
							| 
									
										
										
										
											2007-03-21 14:22:44 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		/* To start timers on any ports left in blocking */ | 
					
						
							|  |  |  | 		br_port_state_selection(br); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2013-09-12 17:12:05 +10:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	spin_unlock_bh(&br->lock); | 
					
						
							| 
									
										
										
										
											2007-03-21 14:22:44 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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) { | 
					
						
							| 
									
										
										
										
											2011-01-03 11:08:58 +00:00
										 |  |  | 		r = call_usermodehelper(BR_STP_PROG, argv, envp, UMH_WAIT_PROC); | 
					
						
							| 
									
										
										
										
											2010-05-10 09:31:09 +00:00
										 |  |  | 		br_info(br, "userspace STP stopped, return code %d\n", r); | 
					
						
							| 
									
										
										
										
											2007-03-21 14:22:44 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		/* 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); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | /* called under bridge lock */ | 
					
						
							| 
									
										
										
										
											2005-12-21 18:51:49 -08:00
										 |  |  | void br_stp_change_bridge_id(struct net_bridge *br, const unsigned char *addr) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
											
												bridge: Convert compare_ether_addr to ether_addr_equal
Use the new bool function ether_addr_equal to add
some clarity and reduce the likelihood for misuse
of compare_ether_addr for sorting.
Done via cocci script:
$ cat compare_ether_addr.cocci
@@
expression a,b;
@@
-	!compare_ether_addr(a, b)
+	ether_addr_equal(a, b)
@@
expression a,b;
@@
-	compare_ether_addr(a, b)
+	!ether_addr_equal(a, b)
@@
expression a,b;
@@
-	!ether_addr_equal(a, b) == 0
+	ether_addr_equal(a, b)
@@
expression a,b;
@@
-	!ether_addr_equal(a, b) != 0
+	!ether_addr_equal(a, b)
@@
expression a,b;
@@
-	ether_addr_equal(a, b) == 0
+	!ether_addr_equal(a, b)
@@
expression a,b;
@@
-	ether_addr_equal(a, b) != 0
+	ether_addr_equal(a, b)
@@
expression a,b;
@@
-	!!ether_addr_equal(a, b)
+	ether_addr_equal(a, b)
Signed-off-by: Joe Perches <joe@perches.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
											
										 
											2012-05-08 18:56:49 +00:00
										 |  |  | 	/* should be aligned on 2 bytes for ether_addr_equal() */ | 
					
						
							| 
									
										
										
										
											2007-04-17 12:31:24 -07:00
										 |  |  | 	unsigned short oldaddr_aligned[ETH_ALEN >> 1]; | 
					
						
							|  |  |  | 	unsigned char *oldaddr = (unsigned char *)oldaddr_aligned; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	struct net_bridge_port *p; | 
					
						
							|  |  |  | 	int wasroot; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	wasroot = br_is_root_bridge(br); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-07 16:48:21 +09:00
										 |  |  | 	br_fdb_change_mac_address(br, addr); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	memcpy(oldaddr, br->bridge_id.addr, ETH_ALEN); | 
					
						
							|  |  |  | 	memcpy(br->bridge_id.addr, addr, ETH_ALEN); | 
					
						
							|  |  |  | 	memcpy(br->dev->dev_addr, addr, ETH_ALEN); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	list_for_each_entry(p, &br->port_list, list) { | 
					
						
							| 
									
										
										
											
												bridge: Convert compare_ether_addr to ether_addr_equal
Use the new bool function ether_addr_equal to add
some clarity and reduce the likelihood for misuse
of compare_ether_addr for sorting.
Done via cocci script:
$ cat compare_ether_addr.cocci
@@
expression a,b;
@@
-	!compare_ether_addr(a, b)
+	ether_addr_equal(a, b)
@@
expression a,b;
@@
-	compare_ether_addr(a, b)
+	!ether_addr_equal(a, b)
@@
expression a,b;
@@
-	!ether_addr_equal(a, b) == 0
+	ether_addr_equal(a, b)
@@
expression a,b;
@@
-	!ether_addr_equal(a, b) != 0
+	!ether_addr_equal(a, b)
@@
expression a,b;
@@
-	ether_addr_equal(a, b) == 0
+	!ether_addr_equal(a, b)
@@
expression a,b;
@@
-	ether_addr_equal(a, b) != 0
+	ether_addr_equal(a, b)
@@
expression a,b;
@@
-	!!ether_addr_equal(a, b)
+	ether_addr_equal(a, b)
Signed-off-by: Joe Perches <joe@perches.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
											
										 
											2012-05-08 18:56:49 +00:00
										 |  |  | 		if (ether_addr_equal(p->designated_bridge.addr, oldaddr)) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 			memcpy(p->designated_bridge.addr, addr, ETH_ALEN); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
											
												bridge: Convert compare_ether_addr to ether_addr_equal
Use the new bool function ether_addr_equal to add
some clarity and reduce the likelihood for misuse
of compare_ether_addr for sorting.
Done via cocci script:
$ cat compare_ether_addr.cocci
@@
expression a,b;
@@
-	!compare_ether_addr(a, b)
+	ether_addr_equal(a, b)
@@
expression a,b;
@@
-	compare_ether_addr(a, b)
+	!ether_addr_equal(a, b)
@@
expression a,b;
@@
-	!ether_addr_equal(a, b) == 0
+	ether_addr_equal(a, b)
@@
expression a,b;
@@
-	!ether_addr_equal(a, b) != 0
+	!ether_addr_equal(a, b)
@@
expression a,b;
@@
-	ether_addr_equal(a, b) == 0
+	!ether_addr_equal(a, b)
@@
expression a,b;
@@
-	ether_addr_equal(a, b) != 0
+	ether_addr_equal(a, b)
@@
expression a,b;
@@
-	!!ether_addr_equal(a, b)
+	ether_addr_equal(a, b)
Signed-off-by: Joe Perches <joe@perches.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
											
										 
											2012-05-08 18:56:49 +00:00
										 |  |  | 		if (ether_addr_equal(p->designated_root.addr, oldaddr)) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 			memcpy(p->designated_root.addr, addr, ETH_ALEN); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	br_configuration_update(br); | 
					
						
							|  |  |  | 	br_port_state_selection(br); | 
					
						
							|  |  |  | 	if (br_is_root_bridge(br) && !wasroot) | 
					
						
							|  |  |  | 		br_become_root_bridge(br); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
											
												bridge: Convert compare_ether_addr to ether_addr_equal
Use the new bool function ether_addr_equal to add
some clarity and reduce the likelihood for misuse
of compare_ether_addr for sorting.
Done via cocci script:
$ cat compare_ether_addr.cocci
@@
expression a,b;
@@
-	!compare_ether_addr(a, b)
+	ether_addr_equal(a, b)
@@
expression a,b;
@@
-	compare_ether_addr(a, b)
+	!ether_addr_equal(a, b)
@@
expression a,b;
@@
-	!ether_addr_equal(a, b) == 0
+	ether_addr_equal(a, b)
@@
expression a,b;
@@
-	!ether_addr_equal(a, b) != 0
+	!ether_addr_equal(a, b)
@@
expression a,b;
@@
-	ether_addr_equal(a, b) == 0
+	!ether_addr_equal(a, b)
@@
expression a,b;
@@
-	ether_addr_equal(a, b) != 0
+	ether_addr_equal(a, b)
@@
expression a,b;
@@
-	!!ether_addr_equal(a, b)
+	ether_addr_equal(a, b)
Signed-off-by: Joe Perches <joe@perches.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
											
										 
											2012-05-08 18:56:49 +00:00
										 |  |  | /* should be aligned on 2 bytes for ether_addr_equal() */ | 
					
						
							| 
									
										
										
										
											2007-04-17 12:31:24 -07:00
										 |  |  | static const unsigned short br_mac_zero_aligned[ETH_ALEN >> 1]; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* called under bridge lock */ | 
					
						
							| 
									
										
										
										
											2011-03-24 13:24:01 +00:00
										 |  |  | bool br_stp_recalculate_bridge_id(struct net_bridge *br) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2007-04-17 12:31:24 -07:00
										 |  |  | 	const unsigned char *br_mac_zero = | 
					
						
							|  |  |  | 			(const unsigned char *)br_mac_zero_aligned; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	const unsigned char *addr = br_mac_zero; | 
					
						
							|  |  |  | 	struct net_bridge_port *p; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-17 16:10:06 -07:00
										 |  |  | 	/* user has chosen a value so keep it */ | 
					
						
							| 
									
										
										
										
											2013-02-10 11:41:01 +00:00
										 |  |  | 	if (br->dev->addr_assign_type == NET_ADDR_SET) | 
					
						
							| 
									
										
										
										
											2011-03-29 06:20:04 +00:00
										 |  |  | 		return false; | 
					
						
							| 
									
										
										
										
											2008-06-17 16:10:06 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	list_for_each_entry(p, &br->port_list, list) { | 
					
						
							|  |  |  | 		if (addr == br_mac_zero || | 
					
						
							| 
									
										
										
										
											2006-01-03 14:35:54 -08:00
										 |  |  | 		    memcmp(p->dev->dev_addr, addr, ETH_ALEN) < 0) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 			addr = p->dev->dev_addr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
											
												bridge: Convert compare_ether_addr to ether_addr_equal
Use the new bool function ether_addr_equal to add
some clarity and reduce the likelihood for misuse
of compare_ether_addr for sorting.
Done via cocci script:
$ cat compare_ether_addr.cocci
@@
expression a,b;
@@
-	!compare_ether_addr(a, b)
+	ether_addr_equal(a, b)
@@
expression a,b;
@@
-	compare_ether_addr(a, b)
+	!ether_addr_equal(a, b)
@@
expression a,b;
@@
-	!ether_addr_equal(a, b) == 0
+	ether_addr_equal(a, b)
@@
expression a,b;
@@
-	!ether_addr_equal(a, b) != 0
+	!ether_addr_equal(a, b)
@@
expression a,b;
@@
-	ether_addr_equal(a, b) == 0
+	!ether_addr_equal(a, b)
@@
expression a,b;
@@
-	ether_addr_equal(a, b) != 0
+	ether_addr_equal(a, b)
@@
expression a,b;
@@
-	!!ether_addr_equal(a, b)
+	ether_addr_equal(a, b)
Signed-off-by: Joe Perches <joe@perches.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
											
										 
											2012-05-08 18:56:49 +00:00
										 |  |  | 	if (ether_addr_equal(br->bridge_id.addr, addr)) | 
					
						
							| 
									
										
										
										
											2011-03-24 13:24:01 +00:00
										 |  |  | 		return false;	/* no change */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	br_stp_change_bridge_id(br, addr); | 
					
						
							|  |  |  | 	return true; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* called under bridge lock */ | 
					
						
							|  |  |  | void br_stp_set_bridge_priority(struct net_bridge *br, u16 newprio) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct net_bridge_port *p; | 
					
						
							|  |  |  | 	int wasroot; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	wasroot = br_is_root_bridge(br); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	list_for_each_entry(p, &br->port_list, list) { | 
					
						
							|  |  |  | 		if (p->state != BR_STATE_DISABLED && | 
					
						
							|  |  |  | 		    br_is_designated_port(p)) { | 
					
						
							|  |  |  | 			p->designated_bridge.prio[0] = (newprio >> 8) & 0xFF; | 
					
						
							|  |  |  | 			p->designated_bridge.prio[1] = newprio & 0xFF; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	br->bridge_id.prio[0] = (newprio >> 8) & 0xFF; | 
					
						
							|  |  |  | 	br->bridge_id.prio[1] = newprio & 0xFF; | 
					
						
							|  |  |  | 	br_configuration_update(br); | 
					
						
							|  |  |  | 	br_port_state_selection(br); | 
					
						
							|  |  |  | 	if (br_is_root_bridge(br) && !wasroot) | 
					
						
							|  |  |  | 		br_become_root_bridge(br); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* called under bridge lock */ | 
					
						
							| 
									
										
										
										
											2011-04-04 14:03:33 +00:00
										 |  |  | int br_stp_set_port_priority(struct net_bridge_port *p, unsigned long newprio) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-04-04 14:03:33 +00:00
										 |  |  | 	port_id new_port_id; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (newprio > BR_MAX_PORT_PRIORITY) | 
					
						
							|  |  |  | 		return -ERANGE; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-04 14:03:33 +00:00
										 |  |  | 	new_port_id = br_make_port_id(newprio, p->port_no); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	if (br_is_designated_port(p)) | 
					
						
							|  |  |  | 		p->designated_port = new_port_id; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	p->port_id = new_port_id; | 
					
						
							|  |  |  | 	p->priority = newprio; | 
					
						
							|  |  |  | 	if (!memcmp(&p->br->bridge_id, &p->designated_bridge, 8) && | 
					
						
							|  |  |  | 	    p->port_id < p->designated_port) { | 
					
						
							|  |  |  | 		br_become_designated_port(p); | 
					
						
							|  |  |  | 		br_port_state_selection(p->br); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-04-04 14:03:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* called under bridge lock */ | 
					
						
							| 
									
										
										
										
											2011-04-04 14:03:33 +00:00
										 |  |  | int br_stp_set_path_cost(struct net_bridge_port *p, unsigned long path_cost) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-04-04 14:03:33 +00:00
										 |  |  | 	if (path_cost < BR_MIN_PATH_COST || | 
					
						
							|  |  |  | 	    path_cost > BR_MAX_PATH_COST) | 
					
						
							|  |  |  | 		return -ERANGE; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-13 14:06:07 +00:00
										 |  |  | 	p->flags |= BR_ADMIN_COST; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	p->path_cost = path_cost; | 
					
						
							|  |  |  | 	br_configuration_update(p->br); | 
					
						
							|  |  |  | 	br_port_state_selection(p->br); | 
					
						
							| 
									
										
										
										
											2011-04-04 14:03:33 +00:00
										 |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ssize_t br_show_bridge_id(char *buf, const struct bridge_id *id) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return sprintf(buf, "%.2x%.2x.%.2x%.2x%.2x%.2x%.2x%.2x\n", | 
					
						
							|  |  |  | 	       id->prio[0], id->prio[1], | 
					
						
							|  |  |  | 	       id->addr[0], id->addr[1], id->addr[2], | 
					
						
							|  |  |  | 	       id->addr[3], id->addr[4], id->addr[5]); | 
					
						
							|  |  |  | } |