[Bridge] Re: [Patch] [2.6.7] Bridge - Fix BPDU message_age

Stephen Hemminger shemminger at osdl.org
Thu Jun 24 09:54:43 PDT 2004


On Thu, 24 Jun 2004 15:02:26 +0530
"Kishore A K" <kishoreak at myw.ltindia.com> wrote:

> Hi Stephen,
> 
> >>First, we shouldn't send out the config info if our info about the root is too old.
> 
> Thats why I had introduced the check "if (bpdu.message_age < br->max_age)".
> The purpose of maintaining the message_age parameter is to enable a bridge to 
> discard information whose age exceeds Max Age. So I think this would be the right 
> way of doing it. You may refer the section "8.6.1.3.3 step 3" in the IEEE 802.1D spec. 
> Above that I really did not get the logic behind doing "if (age < stp_t_to_jiffies(2))".
> Pls clarify.
> 
> >>Second, since the time values in the BPDU are scaled from jiffies to 1/256 sec later
> >>in the send process, need to increment age by the appropriate value.
> 
> I had completely forgotten about this. However, the purpose of doing the increment is to 
> avoid underestimating the age, which is very unlikely to happen. Anyway this can be easily 
> done by incrementing the age by a factor ( (1 * HZ)>>8) instead of 1.
> 
> >>+		long age = (long) root->message_age_timer.expires
> >>+			- (long)jiffies;

> "message_age_timer.expires - jiffies" does not give the message age. Instead it gives
> the time left before the message age timer expires. Whereas Message age is the time
> elapsed since the generation of the configuration BPDU by the root. So the right way
> of getting the message age according to me would be 
> 
> message_age = max_age - (message_age_timer.expires - jiffies) + (HZ>>8)
> 
> Pls correct me if I am wrong here.

Doesn't work if HZ == 100 because then 100 >> 8 = 0.  

Here is an alternative that pushes the increment and message_age < max_age
check down into the send_config_bpdu routine where the conversion to (1/256) ticks
has already taken place.

diff -Nru a/net/bridge/br_private_stp.h b/net/bridge/br_private_stp.h
--- a/net/bridge/br_private_stp.h	2004-06-24 09:52:25 -07:00
+++ b/net/bridge/br_private_stp.h	2004-06-24 09:52:25 -07:00
@@ -52,7 +52,7 @@
 extern void br_topology_change_detection(struct net_bridge *br);
 
 /* br_stp_bpdu.c */
-extern void br_send_config_bpdu(struct net_bridge_port *, struct br_config_bpdu *);
+extern int br_send_config_bpdu(struct net_bridge_port *, struct br_config_bpdu *);
 extern void br_send_tcn_bpdu(struct net_bridge_port *);
 
 #endif
diff -Nru a/net/bridge/br_stp.c b/net/bridge/br_stp.c
--- a/net/bridge/br_stp.c	2004-06-24 09:52:25 -07:00
+++ b/net/bridge/br_stp.c	2004-06-24 09:52:25 -07:00
@@ -157,24 +157,25 @@
 	bpdu.root_path_cost = br->root_path_cost;
 	bpdu.bridge_id = br->bridge_id;
 	bpdu.port_id = p->port_id;
-	bpdu.message_age = 0;
-	if (!br_is_root_bridge(br)) {
+
+	if (br_is_root_bridge(br)) 
+		bpdu.message_age = 0;
+	else {
 		struct net_bridge_port *root
 			= br_get_port(br, br->root_port);
-		bpdu.max_age = root->message_age_timer.expires - jiffies;
-
-		if (bpdu.max_age <= 0) bpdu.max_age = 1;
+		bpdu.message_age = br->max_age 
+			- (root->message_age_timer.expires - jiffies);
 	}
+
 	bpdu.max_age = br->max_age;
 	bpdu.hello_time = br->hello_time;
 	bpdu.forward_delay = br->forward_delay;
 
-	br_send_config_bpdu(p, &bpdu);
-
-	p->topology_change_ack = 0;
-	p->config_pending = 0;
-	
-	mod_timer(&p->hold_timer, jiffies + BR_HOLD_TIME);
+	if (br_send_config_bpdu(p, &bpdu)) {
+		p->topology_change_ack = 0;
+		p->config_pending = 0;
+		mod_timer(&p->hold_timer, jiffies + BR_HOLD_TIME);
+	}
 }
 
 /* called under bridge lock */
diff -Nru a/net/bridge/br_stp_bpdu.c b/net/bridge/br_stp_bpdu.c
--- a/net/bridge/br_stp_bpdu.c	2004-06-24 09:52:25 -07:00
+++ b/net/bridge/br_stp_bpdu.c	2004-06-24 09:52:25 -07:00
@@ -72,9 +72,10 @@
 }
 
 /* called under bridge lock */
-void br_send_config_bpdu(struct net_bridge_port *p, struct br_config_bpdu *bpdu)
+int br_send_config_bpdu(struct net_bridge_port *p, struct br_config_bpdu *bpdu)
 {
 	unsigned char buf[38];
+	u16 max_age;
 
 	buf[0] = 0x42;
 	buf[1] = 0x42;
@@ -108,12 +109,26 @@
 	buf[28] = (bpdu->port_id >> 8) & 0xFF;
 	buf[29] = bpdu->port_id & 0xFF;
 
-	br_set_ticks(buf+30, bpdu->message_age);
-	br_set_ticks(buf+32, bpdu->max_age);
+	max_age = JIFFIES_TO_TICKS(bpdu->max_age);
+	if (bpdu->message_age) {
+		u16 age = JIFFIES_TO_TICKS(bpdu->message_age)+1;
+		if (age >= max_age)
+			return 0;
+		buf[30] = (age >> 8) & 0xFF;
+		buf[31] = age & 0xFF;
+	} else {
+		buf[30] = 0;
+		buf[31] = 0;
+	}
+
+	buf[32] = (max_age >> 8) & 0xFF;
+	buf[33] = max_age & 0xFF;
+
 	br_set_ticks(buf+34, bpdu->hello_time);
 	br_set_ticks(buf+36, bpdu->forward_delay);
 
 	br_send_bpdu(p, buf, 38);
+	return 0;
 }
 
 /* called under bridge lock */



More information about the Bridge mailing list