Some changes have been made to RSTPLIB version rsttplib.1.1.0.2 for use in this
program. The changes are given in the following diff.
The changes fall into 3 categories:

1. Changes to support dynamic addition and deletion of bridge ports.
2. Changes to support multiple bridges.
3. Fixes to protocol part based on 802.1w conformance testing results.


diff -Naur rstplib.1.1.02/base.h rstplib/base.h
--- rstplib.1.1.02/base.h	2002-01-20 00:33:22.000000000 -0800
+++ rstplib/base.h	2006-10-26 13:43:15.000000000 -0700
@@ -75,6 +75,7 @@
   CHOOSE(STP_Imlicite_Instance_Create_Failed),          \
   CHOOSE(STP_Small_Bridge_Priority),                    \
   CHOOSE(STP_Large_Bridge_Priority),                    \
+  CHOOSE(STP_Bridge_Priority_Not_A_Multiple_Of_4096),   \
   CHOOSE(STP_Small_Hello_Time),                         \
   CHOOSE(STP_Large_Hello_Time),                         \
   CHOOSE(STP_Small_Max_Age),                            \
@@ -83,6 +84,10 @@
   CHOOSE(STP_Large_Forward_Delay),                      \
   CHOOSE(STP_Forward_Delay_And_Max_Age_Are_Inconsistent),\
   CHOOSE(STP_Hello_Time_And_Max_Age_Are_Inconsistent),  \
+  CHOOSE(STP_Small_Port_Priority),                      \
+  CHOOSE(STP_Large_Port_Priority),                      \
+  CHOOSE(STP_Port_Priority_Not_A_Multiple_Of_16),       \
+  CHOOSE(STP_Large_Port_PCost),                         \
   CHOOSE(STP_Vlan_Had_Not_Yet_Been_Created),            \
   CHOOSE(STP_Port_Is_Absent_In_The_Vlan),               \
   CHOOSE(STP_Big_len8023_Format),                       \
@@ -176,11 +181,11 @@
 
 /* for debug trace messages */
 
-#ifdef __LINUX__
+#ifdef __LINUX__USE_PRINTF_FOR_STRACE
 extern char* sprint_time_stump (void);
 #define stp_trace(F, B...) printf("%s:" F "\n", sprint_time_stump(), ##B)
 #else
-extern ULONG stp_trace (const char* fmt, ...);
+extern void stp_trace (const char* fmt, ...);
 #endif
 
 #endif /*  _STP_BASE_H__ */
diff -Naur rstplib.1.1.02/pcost.c rstplib/pcost.c
--- rstplib.1.1.02/pcost.c	2002-01-20 00:34:09.000000000 -0800
+++ rstplib/pcost.c	2006-10-20 16:04:16.000000000 -0700
@@ -70,8 +70,10 @@
 }
 
 static void
-updPortPathCost (STATE_MACH_T *this)
+updPortPathCost (PORT_T *port)
 {
+  port->reselect = True;
+  port->selected = False;
 }
 
 void
@@ -97,7 +99,7 @@
       port->usedSpeed = -1;
       break;
     case STABLE:
-      updPortPathCost (this);
+      updPortPathCost (port);
       break;
   }
 }
diff -Naur rstplib.1.1.02/port.c rstplib/port.c
--- rstplib.1.1.02/port.c	2002-01-20 00:34:10.000000000 -0800
+++ rstplib/port.c	2006-10-20 16:04:16.000000000 -0700
@@ -139,10 +139,10 @@
                    this->port_id,
                    this->port_id);
     STP_copy_times (&this->designTimes, &stpm->rootTimes);
+    this->fdWhile = 0;
   }
 
   /* reset timers */
-  this->fdWhile =
   this->helloWhen =
   this->mdelayWhile =
   this->rbWhile =
diff -Naur rstplib.1.1.02/portinfo.c rstplib/portinfo.c
--- rstplib.1.1.02/portinfo.c	2002-01-20 00:34:10.000000000 -0800
+++ rstplib/portinfo.c	2006-10-20 16:04:16.000000000 -0700
@@ -75,6 +75,12 @@
 
   if (BPDU_RSTP == port->msgBpduType) {
     port->msgPortRole = (port->msgFlags & PORT_ROLE_MASK) >> PORT_ROLE_OFFS;
+#ifndef ORIG
+    if (RSTP_PORT_ROLE_UNKN == port->msgPortRole) {
+      port->msgBpduVersion = FORCE_STP_COMPAT;
+      port->msgBpduType = BPDU_CONFIG_TYPE;
+    }
+#endif
   }
 
   if (RSTP_PORT_ROLE_DESGN == port->msgPortRole ||
@@ -109,10 +115,14 @@
     }
   }
 
-  if (RSTP_PORT_ROLE_ROOT == port->msgBpduType                    &&
+  if (RSTP_PORT_ROLE_ROOT == port->msgPortRole                    &&
       port->operPointToPointMac                                   &&
+      ! STP_VECT_compare_bridge_id (&port->msgPrio.root_bridge,
+                                    &port->portPrio.root_bridge) &&
+      port->msgPrio.root_path_cost == port->portPrio.root_path_cost &&
       ! STP_VECT_compare_bridge_id (&port->msgPrio.design_bridge,
                                     &port->portPrio.design_bridge) &&
+      port->msgPrio.design_port == port->portPrio.design_port &&
       AGREEMENT_BIT & port->msgFlags) {
 #ifdef STP_DBG
     if (this->debug) {
diff -Naur rstplib.1.1.02/stp_in.c rstplib/stp_in.c
--- rstplib.1.1.02/stp_in.c	2002-01-20 00:34:13.000000000 -0800
+++ rstplib/stp_in.c	2006-10-20 16:04:16.000000000 -0700
@@ -170,6 +170,11 @@
     return STP_Large_Bridge_Priority;
   }
 
+  if (uid_cfg->bridge_priority & ~MASK_BR_PRIO) {
+    stp_trace ("%d bridge_priority must be a multiple of 4096", (int) uid_cfg->bridge_priority);
+    return STP_Bridge_Priority_Not_A_Multiple_Of_4096;
+  }
+
   if (uid_cfg->hello_time < MIN_BR_HELLOT) {
     stp_trace ("%d hello_time small", (int) uid_cfg->hello_time);
     return STP_Small_Hello_Time;
@@ -815,8 +820,13 @@
   return 0;
 }
 
+#ifdef ORIG
 int
 STP_IN_set_port_cfg (IN int vlan_id, IN UID_STP_PORT_CFG_T* uid_cfg)
+#else
+int
+STP_IN_set_port_cfg (int vlan_id, int port_index, UID_STP_PORT_CFG_T* uid_cfg)
+#endif
 {
   register STPM_T* this;
   register PORT_T* port;
@@ -831,12 +841,21 @@
     return STP_Vlan_Had_Not_Yet_Been_Created;
   }
 
+#ifdef ORIG
   for (port_no = 1; port_no <= max_port; port_no++) {
     if (! BitmapGetBit(&uid_cfg->port_bmp, port_no - 1)) continue;
+#else
+  port_no = port_index;
+  {
+#endif
   
     port = _stpapi_port_find (this, port_no);
     if (! port) {/* port is absent in the stpm :( */
+#ifdef ORIG
       continue;
+#else
+      return STP_Port_Is_Absent_In_The_Vlan;
+#endif
     }
 
     if (PT_CFG_MCHECK & uid_cfg->field_mask) {
@@ -845,10 +864,18 @@
     }
 
     if (PT_CFG_COST & uid_cfg->field_mask) {
+      if (uid_cfg->admin_port_path_cost > MAX_PORT_PCOST)
+        return STP_Large_Port_PCost;
       port->adminPCost = uid_cfg->admin_port_path_cost;
     }
   
     if (PT_CFG_PRIO & uid_cfg->field_mask) {
+      if (uid_cfg->port_priority < MIN_PORT_PRIO)
+        return STP_Small_Port_Priority;
+      if (uid_cfg->port_priority > MAX_PORT_PRIO)
+        return STP_Large_Port_Priority;
+      if (uid_cfg->port_priority & ~MASK_PORT_PRIO)
+        return STP_Port_Priority_Not_A_Multiple_Of_16;
       port->port_id = (uid_cfg->port_priority << 8) + port_no;
     }
   
@@ -955,3 +982,114 @@
   return rstp_error_names[rstp_err_no];
 }
 
+/*---------------- Dynamic port create / delete ------------------*/
+
+int STP_IN_port_create(int vlan_id, int port_index)
+{
+  register STPM_T* this;
+
+  this = stpapi_stpm_find (vlan_id);
+
+  if (! this) { /* can't create stpm :( */
+    return STP_Vlan_Had_Not_Yet_Been_Created;
+  }
+
+  PORT_T *port = STP_port_create (this, port_index);
+  if (! port) {
+    /* can't add port :( */
+    stp_trace ("can't create port %d", (int) port_index);
+    return STP_Cannot_Create_Instance_For_Port;
+  }
+  STP_port_init(port, this, True);
+
+  STP_compute_bridge_id(this);
+  STP_stpm_update_after_bridge_management (this);
+  STP_stpm_update (this);
+  return 0;
+}
+
+int STP_IN_port_delete(int vlan_id, int port_index)
+{
+  register STPM_T* this;
+  PORT_T *port;
+
+  this = stpapi_stpm_find (vlan_id);
+
+  if (! this) { /* can't find stpm :( */
+    return STP_Vlan_Had_Not_Yet_Been_Created;
+  }
+
+  port = _stpapi_port_find (this, port_index);
+  if (! port) {
+    return STP_Port_Is_Absent_In_The_Vlan;
+  }
+  
+  STP_port_delete (port);
+
+  STP_compute_bridge_id(this);
+  STP_stpm_update_after_bridge_management (this);
+  STP_stpm_update (this);
+  return 0;
+}
+
+
+/*--- For multiple STP instances - non multithread use ---*/
+
+struct stp_instance
+{
+  STPM_T *bridges;
+#ifdef STP_DBG
+  int dbg_rstp_deny;
+#endif
+  int max_port; /* Remove this */
+  int nev;
+  RSTP_EVENT_T tev;
+};
+
+struct stp_instance *STP_IN_instance_create(void)
+{
+  struct stp_instance *p;
+  p = malloc(sizeof(*p));
+  if (!p) return p;
+  p->bridges = NULL;
+#ifdef STP_DBG  
+  p->dbg_rstp_deny = 0;
+#endif
+  p->max_port = 1024;
+  p->tev = RSTP_EVENT_LAST_DUMMY;
+  p->nev = 0;
+  return p;
+}
+
+void STP_IN_instance_begin(struct stp_instance *p)
+{
+  bridges = p->bridges;
+#ifdef STP_DBG  
+  dbg_rstp_deny = p->dbg_rstp_deny;
+#endif
+  max_port = p->max_port;
+  tev = p->tev;
+  nev = p->nev;
+}
+
+void STP_IN_instance_end(struct stp_instance *p)
+{
+  p->bridges = bridges;
+#ifdef STP_DBG  
+  p->dbg_rstp_deny = dbg_rstp_deny;
+#endif
+  p->max_port = max_port;
+  p->tev = tev;
+  p->nev = nev;
+}
+
+void STP_IN_instance_delete(struct stp_instance *p)
+{
+  STP_IN_instance_begin(p);
+  STP_IN_delete_all();
+  STP_IN_instance_end(p);
+  free(p);
+}
+
+  
+  
diff -Naur rstplib.1.1.02/stp_in.h rstplib/stp_in.h
--- rstplib.1.1.02/stp_in.h	2002-01-20 00:33:52.000000000 -0800
+++ rstplib/stp_in.h	2006-10-20 16:04:16.000000000 -0700
@@ -56,6 +56,7 @@
 #define DEF_BR_PRIO 32768
 #define MIN_BR_PRIO 0
 #define MAX_BR_PRIO 61440
+#define MASK_BR_PRIO 0xf000
 
 #define DEF_BR_HELLOT   2
 #define MIN_BR_HELLOT   1
@@ -76,12 +77,15 @@
 #define DEF_PORT_PRIO   128
 #define MIN_PORT_PRIO   0
 #define MAX_PORT_PRIO   240 /* in steps of 16 */
+#define MASK_PORT_PRIO  0xf0
 
 #define DEF_ADMIN_NON_STP   False
 #define DEF_ADMIN_EDGE      True
 #define DEF_LINK_DELAY      3 /* see edge.c */
 #define DEF_P2P         P2P_AUTO
 
+#define MAX_PORT_PCOST 200000000
+
 /* Section 1: Create/Delete/Start/Stop the RSTP instance */
 
 void /* init the engine */
@@ -101,6 +105,12 @@
 int
 STP_IN_delete_all (void);
 
+/* Port create/delete */
+
+int STP_IN_port_create(int vlan_id, int port_index);
+
+int STP_IN_port_delete(int vlan_id, int port_index);
+
 /* Section 2. "Get" management */
 
 Bool
@@ -136,9 +146,15 @@
                      BITMAP_T* port_bmp,
                      UID_STP_CFG_T* uid_cfg);
 
+#ifdef ORIG
 int
 STP_IN_set_port_cfg (int vlan_id,
                      UID_STP_PORT_CFG_T* uid_cfg);
+#else
+int
+STP_IN_set_port_cfg (int vlan_id, int port_index,
+                     UID_STP_PORT_CFG_T* uid_cfg);
+#endif
 
 #ifdef STP_DBG
 int STP_IN_dbg_set_port_trace (char* mach_name, int enadis,
@@ -168,6 +184,19 @@
 STP_IN_rx_bpdu (int vlan_id, int port_index, BPDU_T* bpdu, size_t len);
 #endif
 
+/*--- For multiple STP instances - non multithread use ---*/
+
+struct stp_instance;
+/* Create struct to hold STP instance state and initialize it.
+   A copy of all global state in the library. */
+struct stp_instance *STP_IN_instance_create(void);
+/* Set context from this STP instance */
+void STP_IN_instance_begin(struct stp_instance *p);
+/* Save context back to this STP instance */
+void STP_IN_instance_end(struct stp_instance *p);
+/* Delete this STP instance */
+void STP_IN_instance_delete(struct stp_instance *p);
+
 #ifdef _STP_MACHINE_H__
 /* Inner usage definitions & functions */
 
diff -Naur rstplib.1.1.02/stp_state.h rstplib/stp_state.h
--- rstplib.1.1.02/stp_state.h	1969-12-31 16:00:00.000000000 -0800
+++ rstplib/stp_state.h	2006-10-20 16:04:16.000000000 -0700
@@ -0,0 +1,7 @@
+#ifndef _STP_STATE_H__
+#define _STP_STATE_H__
+
+
+
+
+#endif
diff -Naur rstplib.1.1.02/stpm.c rstplib/stpm.c
--- rstplib.1.1.02/stpm.c	2002-01-20 00:34:14.000000000 -0800
+++ rstplib/stpm.c	2006-10-30 19:21:51.000000000 -0800
@@ -26,7 +26,11 @@
 #include "stpm.h"
 #include "stp_to.h" /* for STP_OUT_flush_lt */
 
-static STPM_T *bridges = NULL;
+/*static*/ STPM_T *bridges = NULL;
+
+/* We can flush learned fdb by port, so set this in stpm.c and topoch.c  */
+/* This doesn't seem to solve the topology change problems. Don't use it yet */
+//#define STRONGLY_SPEC_802_1W
 
 static int
 _stp_stpm_init_machine (STATE_MACH_T* this)
@@ -217,9 +221,11 @@
 {
   register PORT_T* port;
 
+#ifdef ORIG
   if (! this->ports) { /* there are not any ports :( */
     return STP_There_Are_No_Ports;
   }
+#endif
 
   if (! STP_compute_bridge_id (this)) {/* can't compute bridge id ? :( */
     return STP_Cannot_Compute_Bridge_Prio;
@@ -289,19 +295,16 @@
 STP_compute_bridge_id (STPM_T* this)
 {
   register PORT_T* port;
-  register PORT_T* min_num_port;
-  int              port_index = 0;
+  unsigned char old[6], new[6];
+  memset(&old, 0xff, sizeof(old));
 
   for (port = this->ports; port; port = port->next) {
-    if (! port_index || port->port_index < port_index) {
-      min_num_port = port;
-      port_index = port->port_index;
-    }
+    STP_OUT_get_port_mac (port->port_index, new);
+    if (memcmp(new, old, sizeof(old)) < 0)
+      memcpy(old, new, sizeof(old));
   }
 
-  if (! min_num_port) return NULL; /* IMHO, it may not be */
-
-  STP_OUT_get_port_mac (min_num_port->port_index, this->BrId.addr);
+  memcpy(this->BrId.addr, old, sizeof(old));
 
   return &this->BrId;
 }
diff -Naur rstplib.1.1.02/stpm.h rstplib/stpm.h
--- rstplib.1.1.02/stpm.h	2002-01-20 00:33:54.000000000 -0800
+++ rstplib/stpm.h	2006-10-20 16:04:16.000000000 -0700
@@ -103,6 +103,8 @@
 STPM_T *
 STP_stpm_get_the_list (void);
 
+extern STPM_T *bridges;
+
 void
 STP_stpm_update_after_bridge_management (STPM_T* this);
 
diff -Naur rstplib.1.1.02/stpmgmt.c rstplib/stpmgmt.c
--- rstplib.1.1.02/stpmgmt.c	2002-01-20 00:34:14.000000000 -0800
+++ rstplib/stpmgmt.c	2006-10-20 16:04:16.000000000 -0700
@@ -50,6 +50,11 @@
     this->BrTimes.ForwardDelay = init_cfg.forward_delay;
     this->ForceVersion = (PROTOCOL_VERSION_T) init_cfg.force_version;
   }
+#ifdef ORIG
+#else
+  if (this->admin_state != STP_ENABLED)
+    err_code = STP_stpm_enable(this, STP_ENABLED);
+#endif
 
   RSTP_CRITICAL_PATH_END;
   return err_code;  
@@ -145,10 +150,11 @@
 int
 STP_IN_delete_all (void)
 {
-  register STPM_T* stpm;
+  register STPM_T* stpm, *next;
 
   RSTP_CRITICAL_PATH_START;
-  for (stpm = STP_stpm_get_the_list (); stpm; stpm = stpm->next) {
+  for (stpm = STP_stpm_get_the_list (); stpm; stpm = next) {
+    next = stpm->next;
     STP_stpm_enable (stpm, STP_DISABLED);
     STP_stpm_delete (stpm);
   }
diff -Naur rstplib.1.1.02/topoch.c rstplib/topoch.c
--- rstplib.1.1.02/topoch.c	2002-01-20 00:34:16.000000000 -0800
+++ rstplib/topoch.c	2006-10-30 19:22:01.000000000 -0800
@@ -40,6 +40,10 @@
 #define GET_STATE_NAME STP_topoch_get_state_name
 #include "choose.h"
 
+/* We can flush learned fdb by port, so set this in stpm.c and topoch.c  */
+/* This doesn't seem to solve the topology change problems. Don't use it yet */
+//#define STRONGLY_SPEC_802_1W
+
 #ifndef STRONGLY_SPEC_802_1W
 /* 
  * In many kinds of hardware the function
@@ -61,12 +65,13 @@
   if (this->debug) {
     stp_trace("%s (%s, %s, %s, '%s')",
         "flush", port->port_name, port->owner->name,
-        LT_FLASH_ONLY_THE_PORT == type ? "this port" : "other ports",
+        "this port",
         reason);
   }
 
   bret = STP_OUT_flush_lt (port->port_index, port->owner->vlan_id,
                            LT_FLASH_ONLY_THE_PORT, reason);
+  return bret;
 }
 #endif
 
@@ -103,7 +108,11 @@
   if (port->sendRSTP && port->operPointToPointMac) {
     return 2 * port->owner->rootTimes.HelloTime;
   }
+#ifdef ORIG
   return port->owner->rootTimes.MaxAge;
+#else
+  return port->owner->rootTimes.MaxAge + port->owner->rootTimes.ForwardDelay;
+#endif
 }
 
 void
diff -Naur rstplib.1.1.02/transmit.c rstplib/transmit.c
--- rstplib.1.1.02/transmit.c	2002-01-20 00:34:17.000000000 -0800
+++ rstplib/transmit.c	2006-10-20 16:04:16.000000000 -0700
@@ -99,7 +99,11 @@
 {
   unsigned short len8023;
 
+#ifdef ORIG
   STP_OUT_get_port_mac (port_index, bpdu_packet.mac.src_mac);
+#else
+  /* Don't bother. LLC trasmits with correct source MAC, we don't supply it */
+#endif
 
   bpdu_packet.hdr.bpdu_type = bpdu_type;
   bpdu_packet.hdr.version = (BPDU_RSTP == bpdu_type) ?
@@ -110,7 +114,11 @@
   len8023 = htons ((unsigned short) (pkt_len + 3));
   memcpy (&bpdu_packet.eth.len8023, &len8023, 2); 
 
+#ifdef ORIG
   if (pkt_len < MIN_FRAME_LENGTH) pkt_len = MIN_FRAME_LENGTH;
+#else
+  /* Don't do this. LLC puts in 802.3 length based on what we transmit */
+#endif
   return pkt_len;
 }
 
@@ -235,7 +243,7 @@
 
   pkt_len = build_bpdu_header (port->port_index,
                                BPDU_RSTP,
-                               sizeof (BPDU_HEADER_T) + sizeof (BPDU_BODY_T) + 2);
+                               sizeof (BPDU_HEADER_T) + sizeof (BPDU_BODY_T) + 1);
   build_config_bpdu (port, False);
 
   switch (port->selectedRole) {
@@ -258,7 +266,12 @@
   }
 
   bpdu_packet.body.flags |= (role << PORT_ROLE_OFFS);
-
+#ifndef ORIG
+  if (port->forwarding)
+    bpdu_packet.body.flags |= FORWARD_BIT;
+  if (port->learning)
+    bpdu_packet.body.flags |= LEARN_BIT;
+#endif
   if (port->synced) {
 #if 0 /* def STP_DBG */
     if (port->roletrns->debug)
