1 Some changes have been made to RSTPLIB version rsttplib.1.1.0.2 for use in this
2 program. The changes are given in the following diff.
3 The changes fall into 3 categories:
5 1. Changes to support dynamic addition and deletion of bridge ports.
6 2. Changes to support multiple bridges.
7 3. Fixes to protocol part based on 802.1w conformance testing results.
10 diff -Naur rstplib.1.1.02/base.h rstplib/base.h
11 --- rstplib.1.1.02/base.h 2002-01-20 00:33:22.000000000 -0800
12 +++ rstplib/base.h 2006-10-26 13:43:15.000000000 -0700
14 CHOOSE(STP_Imlicite_Instance_Create_Failed), \
15 CHOOSE(STP_Small_Bridge_Priority), \
16 CHOOSE(STP_Large_Bridge_Priority), \
17 + CHOOSE(STP_Bridge_Priority_Not_A_Multiple_Of_4096), \
18 CHOOSE(STP_Small_Hello_Time), \
19 CHOOSE(STP_Large_Hello_Time), \
20 CHOOSE(STP_Small_Max_Age), \
22 CHOOSE(STP_Large_Forward_Delay), \
23 CHOOSE(STP_Forward_Delay_And_Max_Age_Are_Inconsistent),\
24 CHOOSE(STP_Hello_Time_And_Max_Age_Are_Inconsistent), \
25 + CHOOSE(STP_Small_Port_Priority), \
26 + CHOOSE(STP_Large_Port_Priority), \
27 + CHOOSE(STP_Port_Priority_Not_A_Multiple_Of_16), \
28 + CHOOSE(STP_Large_Port_PCost), \
29 CHOOSE(STP_Vlan_Had_Not_Yet_Been_Created), \
30 CHOOSE(STP_Port_Is_Absent_In_The_Vlan), \
31 CHOOSE(STP_Big_len8023_Format), \
34 /* for debug trace messages */
37 +#ifdef __LINUX__USE_PRINTF_FOR_STRACE
38 extern char* sprint_time_stump (void);
39 #define stp_trace(F, B...) printf("%s:" F "\n", sprint_time_stump(), ##B)
41 -extern ULONG stp_trace (const char* fmt, ...);
42 +extern void stp_trace (const char* fmt, ...);
45 #endif /* _STP_BASE_H__ */
46 diff -Naur rstplib.1.1.02/pcost.c rstplib/pcost.c
47 --- rstplib.1.1.02/pcost.c 2002-01-20 00:34:09.000000000 -0800
48 +++ rstplib/pcost.c 2006-10-20 16:04:16.000000000 -0700
53 -updPortPathCost (STATE_MACH_T *this)
54 +updPortPathCost (PORT_T *port)
56 + port->reselect = True;
57 + port->selected = False;
65 - updPortPathCost (this);
66 + updPortPathCost (port);
70 diff -Naur rstplib.1.1.02/port.c rstplib/port.c
71 --- rstplib.1.1.02/port.c 2002-01-20 00:34:10.000000000 -0800
72 +++ rstplib/port.c 2006-10-20 16:04:16.000000000 -0700
76 STP_copy_times (&this->designTimes, &stpm->rootTimes);
85 diff -Naur rstplib.1.1.02/portinfo.c rstplib/portinfo.c
86 --- rstplib.1.1.02/portinfo.c 2002-01-20 00:34:10.000000000 -0800
87 +++ rstplib/portinfo.c 2006-10-20 16:04:16.000000000 -0700
90 if (BPDU_RSTP == port->msgBpduType) {
91 port->msgPortRole = (port->msgFlags & PORT_ROLE_MASK) >> PORT_ROLE_OFFS;
93 + if (RSTP_PORT_ROLE_UNKN == port->msgPortRole) {
94 + port->msgBpduVersion = FORCE_STP_COMPAT;
95 + port->msgBpduType = BPDU_CONFIG_TYPE;
100 if (RSTP_PORT_ROLE_DESGN == port->msgPortRole ||
101 @@ -109,10 +115,14 @@
105 - if (RSTP_PORT_ROLE_ROOT == port->msgBpduType &&
106 + if (RSTP_PORT_ROLE_ROOT == port->msgPortRole &&
107 port->operPointToPointMac &&
108 + ! STP_VECT_compare_bridge_id (&port->msgPrio.root_bridge,
109 + &port->portPrio.root_bridge) &&
110 + port->msgPrio.root_path_cost == port->portPrio.root_path_cost &&
111 ! STP_VECT_compare_bridge_id (&port->msgPrio.design_bridge,
112 &port->portPrio.design_bridge) &&
113 + port->msgPrio.design_port == port->portPrio.design_port &&
114 AGREEMENT_BIT & port->msgFlags) {
117 diff -Naur rstplib.1.1.02/stp_in.c rstplib/stp_in.c
118 --- rstplib.1.1.02/stp_in.c 2002-01-20 00:34:13.000000000 -0800
119 +++ rstplib/stp_in.c 2006-10-20 16:04:16.000000000 -0700
121 return STP_Large_Bridge_Priority;
124 + if (uid_cfg->bridge_priority & ~MASK_BR_PRIO) {
125 + stp_trace ("%d bridge_priority must be a multiple of 4096", (int) uid_cfg->bridge_priority);
126 + return STP_Bridge_Priority_Not_A_Multiple_Of_4096;
129 if (uid_cfg->hello_time < MIN_BR_HELLOT) {
130 stp_trace ("%d hello_time small", (int) uid_cfg->hello_time);
131 return STP_Small_Hello_Time;
138 STP_IN_set_port_cfg (IN int vlan_id, IN UID_STP_PORT_CFG_T* uid_cfg)
141 +STP_IN_set_port_cfg (int vlan_id, int port_index, UID_STP_PORT_CFG_T* uid_cfg)
144 register STPM_T* this;
145 register PORT_T* port;
146 @@ -831,12 +841,21 @@
147 return STP_Vlan_Had_Not_Yet_Been_Created;
151 for (port_no = 1; port_no <= max_port; port_no++) {
152 if (! BitmapGetBit(&uid_cfg->port_bmp, port_no - 1)) continue;
154 + port_no = port_index;
158 port = _stpapi_port_find (this, port_no);
159 if (! port) {/* port is absent in the stpm :( */
163 + return STP_Port_Is_Absent_In_The_Vlan;
167 if (PT_CFG_MCHECK & uid_cfg->field_mask) {
168 @@ -845,10 +864,18 @@
171 if (PT_CFG_COST & uid_cfg->field_mask) {
172 + if (uid_cfg->admin_port_path_cost > MAX_PORT_PCOST)
173 + return STP_Large_Port_PCost;
174 port->adminPCost = uid_cfg->admin_port_path_cost;
177 if (PT_CFG_PRIO & uid_cfg->field_mask) {
178 + if (uid_cfg->port_priority < MIN_PORT_PRIO)
179 + return STP_Small_Port_Priority;
180 + if (uid_cfg->port_priority > MAX_PORT_PRIO)
181 + return STP_Large_Port_Priority;
182 + if (uid_cfg->port_priority & ~MASK_PORT_PRIO)
183 + return STP_Port_Priority_Not_A_Multiple_Of_16;
184 port->port_id = (uid_cfg->port_priority << 8) + port_no;
187 @@ -955,3 +982,114 @@
188 return rstp_error_names[rstp_err_no];
191 +/*---------------- Dynamic port create / delete ------------------*/
193 +int STP_IN_port_create(int vlan_id, int port_index)
195 + register STPM_T* this;
197 + this = stpapi_stpm_find (vlan_id);
199 + if (! this) { /* can't create stpm :( */
200 + return STP_Vlan_Had_Not_Yet_Been_Created;
203 + PORT_T *port = STP_port_create (this, port_index);
205 + /* can't add port :( */
206 + stp_trace ("can't create port %d", (int) port_index);
207 + return STP_Cannot_Create_Instance_For_Port;
209 + STP_port_init(port, this, True);
211 + STP_compute_bridge_id(this);
212 + STP_stpm_update_after_bridge_management (this);
213 + STP_stpm_update (this);
217 +int STP_IN_port_delete(int vlan_id, int port_index)
219 + register STPM_T* this;
222 + this = stpapi_stpm_find (vlan_id);
224 + if (! this) { /* can't find stpm :( */
225 + return STP_Vlan_Had_Not_Yet_Been_Created;
228 + port = _stpapi_port_find (this, port_index);
230 + return STP_Port_Is_Absent_In_The_Vlan;
233 + STP_port_delete (port);
235 + STP_compute_bridge_id(this);
236 + STP_stpm_update_after_bridge_management (this);
237 + STP_stpm_update (this);
242 +/*--- For multiple STP instances - non multithread use ---*/
250 + int max_port; /* Remove this */
255 +struct stp_instance *STP_IN_instance_create(void)
257 + struct stp_instance *p;
258 + p = malloc(sizeof(*p));
262 + p->dbg_rstp_deny = 0;
264 + p->max_port = 1024;
265 + p->tev = RSTP_EVENT_LAST_DUMMY;
270 +void STP_IN_instance_begin(struct stp_instance *p)
272 + bridges = p->bridges;
274 + dbg_rstp_deny = p->dbg_rstp_deny;
276 + max_port = p->max_port;
281 +void STP_IN_instance_end(struct stp_instance *p)
283 + p->bridges = bridges;
285 + p->dbg_rstp_deny = dbg_rstp_deny;
287 + p->max_port = max_port;
292 +void STP_IN_instance_delete(struct stp_instance *p)
294 + STP_IN_instance_begin(p);
295 + STP_IN_delete_all();
296 + STP_IN_instance_end(p);
302 diff -Naur rstplib.1.1.02/stp_in.h rstplib/stp_in.h
303 --- rstplib.1.1.02/stp_in.h 2002-01-20 00:33:52.000000000 -0800
304 +++ rstplib/stp_in.h 2006-10-20 16:04:16.000000000 -0700
306 #define DEF_BR_PRIO 32768
307 #define MIN_BR_PRIO 0
308 #define MAX_BR_PRIO 61440
309 +#define MASK_BR_PRIO 0xf000
311 #define DEF_BR_HELLOT 2
312 #define MIN_BR_HELLOT 1
314 #define DEF_PORT_PRIO 128
315 #define MIN_PORT_PRIO 0
316 #define MAX_PORT_PRIO 240 /* in steps of 16 */
317 +#define MASK_PORT_PRIO 0xf0
319 #define DEF_ADMIN_NON_STP False
320 #define DEF_ADMIN_EDGE True
321 #define DEF_LINK_DELAY 3 /* see edge.c */
322 #define DEF_P2P P2P_AUTO
324 +#define MAX_PORT_PCOST 200000000
326 /* Section 1: Create/Delete/Start/Stop the RSTP instance */
328 void /* init the engine */
331 STP_IN_delete_all (void);
333 +/* Port create/delete */
335 +int STP_IN_port_create(int vlan_id, int port_index);
337 +int STP_IN_port_delete(int vlan_id, int port_index);
339 /* Section 2. "Get" management */
344 UID_STP_CFG_T* uid_cfg);
348 STP_IN_set_port_cfg (int vlan_id,
349 UID_STP_PORT_CFG_T* uid_cfg);
352 +STP_IN_set_port_cfg (int vlan_id, int port_index,
353 + UID_STP_PORT_CFG_T* uid_cfg);
357 int STP_IN_dbg_set_port_trace (char* mach_name, int enadis,
359 STP_IN_rx_bpdu (int vlan_id, int port_index, BPDU_T* bpdu, size_t len);
362 +/*--- For multiple STP instances - non multithread use ---*/
364 +struct stp_instance;
365 +/* Create struct to hold STP instance state and initialize it.
366 + A copy of all global state in the library. */
367 +struct stp_instance *STP_IN_instance_create(void);
368 +/* Set context from this STP instance */
369 +void STP_IN_instance_begin(struct stp_instance *p);
370 +/* Save context back to this STP instance */
371 +void STP_IN_instance_end(struct stp_instance *p);
372 +/* Delete this STP instance */
373 +void STP_IN_instance_delete(struct stp_instance *p);
375 #ifdef _STP_MACHINE_H__
376 /* Inner usage definitions & functions */
378 diff -Naur rstplib.1.1.02/stp_state.h rstplib/stp_state.h
379 --- rstplib.1.1.02/stp_state.h 1969-12-31 16:00:00.000000000 -0800
380 +++ rstplib/stp_state.h 2006-10-20 16:04:16.000000000 -0700
382 +#ifndef _STP_STATE_H__
383 +#define _STP_STATE_H__
389 diff -Naur rstplib.1.1.02/stpm.c rstplib/stpm.c
390 --- rstplib.1.1.02/stpm.c 2002-01-20 00:34:14.000000000 -0800
391 +++ rstplib/stpm.c 2006-10-30 19:21:51.000000000 -0800
394 #include "stp_to.h" /* for STP_OUT_flush_lt */
396 -static STPM_T *bridges = NULL;
397 +/*static*/ STPM_T *bridges = NULL;
399 +/* We can flush learned fdb by port, so set this in stpm.c and topoch.c */
400 +/* This doesn't seem to solve the topology change problems. Don't use it yet */
401 +//#define STRONGLY_SPEC_802_1W
404 _stp_stpm_init_machine (STATE_MACH_T* this)
407 register PORT_T* port;
410 if (! this->ports) { /* there are not any ports :( */
411 return STP_There_Are_No_Ports;
415 if (! STP_compute_bridge_id (this)) {/* can't compute bridge id ? :( */
416 return STP_Cannot_Compute_Bridge_Prio;
417 @@ -289,19 +295,16 @@
418 STP_compute_bridge_id (STPM_T* this)
420 register PORT_T* port;
421 - register PORT_T* min_num_port;
422 - int port_index = 0;
423 + unsigned char old[6], new[6];
424 + memset(&old, 0xff, sizeof(old));
426 for (port = this->ports; port; port = port->next) {
427 - if (! port_index || port->port_index < port_index) {
428 - min_num_port = port;
429 - port_index = port->port_index;
431 + STP_OUT_get_port_mac (port->port_index, new);
432 + if (memcmp(new, old, sizeof(old)) < 0)
433 + memcpy(old, new, sizeof(old));
436 - if (! min_num_port) return NULL; /* IMHO, it may not be */
438 - STP_OUT_get_port_mac (min_num_port->port_index, this->BrId.addr);
439 + memcpy(this->BrId.addr, old, sizeof(old));
443 diff -Naur rstplib.1.1.02/stpm.h rstplib/stpm.h
444 --- rstplib.1.1.02/stpm.h 2002-01-20 00:33:54.000000000 -0800
445 +++ rstplib/stpm.h 2006-10-20 16:04:16.000000000 -0700
448 STP_stpm_get_the_list (void);
450 +extern STPM_T *bridges;
453 STP_stpm_update_after_bridge_management (STPM_T* this);
455 diff -Naur rstplib.1.1.02/stpmgmt.c rstplib/stpmgmt.c
456 --- rstplib.1.1.02/stpmgmt.c 2002-01-20 00:34:14.000000000 -0800
457 +++ rstplib/stpmgmt.c 2006-10-20 16:04:16.000000000 -0700
459 this->BrTimes.ForwardDelay = init_cfg.forward_delay;
460 this->ForceVersion = (PROTOCOL_VERSION_T) init_cfg.force_version;
464 + if (this->admin_state != STP_ENABLED)
465 + err_code = STP_stpm_enable(this, STP_ENABLED);
468 RSTP_CRITICAL_PATH_END;
470 @@ -145,10 +150,11 @@
472 STP_IN_delete_all (void)
474 - register STPM_T* stpm;
475 + register STPM_T* stpm, *next;
477 RSTP_CRITICAL_PATH_START;
478 - for (stpm = STP_stpm_get_the_list (); stpm; stpm = stpm->next) {
479 + for (stpm = STP_stpm_get_the_list (); stpm; stpm = next) {
481 STP_stpm_enable (stpm, STP_DISABLED);
482 STP_stpm_delete (stpm);
484 diff -Naur rstplib.1.1.02/topoch.c rstplib/topoch.c
485 --- rstplib.1.1.02/topoch.c 2002-01-20 00:34:16.000000000 -0800
486 +++ rstplib/topoch.c 2006-10-30 19:22:01.000000000 -0800
488 #define GET_STATE_NAME STP_topoch_get_state_name
491 +/* We can flush learned fdb by port, so set this in stpm.c and topoch.c */
492 +/* This doesn't seem to solve the topology change problems. Don't use it yet */
493 +//#define STRONGLY_SPEC_802_1W
495 #ifndef STRONGLY_SPEC_802_1W
497 * In many kinds of hardware the function
500 stp_trace("%s (%s, %s, %s, '%s')",
501 "flush", port->port_name, port->owner->name,
502 - LT_FLASH_ONLY_THE_PORT == type ? "this port" : "other ports",
507 bret = STP_OUT_flush_lt (port->port_index, port->owner->vlan_id,
508 LT_FLASH_ONLY_THE_PORT, reason);
514 if (port->sendRSTP && port->operPointToPointMac) {
515 return 2 * port->owner->rootTimes.HelloTime;
518 return port->owner->rootTimes.MaxAge;
520 + return port->owner->rootTimes.MaxAge + port->owner->rootTimes.ForwardDelay;
525 diff -Naur rstplib.1.1.02/transmit.c rstplib/transmit.c
526 --- rstplib.1.1.02/transmit.c 2002-01-20 00:34:17.000000000 -0800
527 +++ rstplib/transmit.c 2006-10-20 16:04:16.000000000 -0700
530 unsigned short len8023;
533 STP_OUT_get_port_mac (port_index, bpdu_packet.mac.src_mac);
535 + /* Don't bother. LLC trasmits with correct source MAC, we don't supply it */
538 bpdu_packet.hdr.bpdu_type = bpdu_type;
539 bpdu_packet.hdr.version = (BPDU_RSTP == bpdu_type) ?
541 len8023 = htons ((unsigned short) (pkt_len + 3));
542 memcpy (&bpdu_packet.eth.len8023, &len8023, 2);
545 if (pkt_len < MIN_FRAME_LENGTH) pkt_len = MIN_FRAME_LENGTH;
547 + /* Don't do this. LLC puts in 802.3 length based on what we transmit */
554 pkt_len = build_bpdu_header (port->port_index,
556 - sizeof (BPDU_HEADER_T) + sizeof (BPDU_BODY_T) + 2);
557 + sizeof (BPDU_HEADER_T) + sizeof (BPDU_BODY_T) + 1);
558 build_config_bpdu (port, False);
560 switch (port->selectedRole) {
564 bpdu_packet.body.flags |= (role << PORT_ROLE_OFFS);
567 + if (port->forwarding)
568 + bpdu_packet.body.flags |= FORWARD_BIT;
569 + if (port->learning)
570 + bpdu_packet.body.flags |= LEARN_BIT;
573 #if 0 /* def STP_DBG */
574 if (port->roletrns->debug)