- Don't apply endian conversions to flags, which are 8 bits.
    - Use #defines for default times for use outside library.
    - Clarify our behavior when in STP_DISABLED state.
    - Add "aux" member to STP port struct to be able to refer back to
      the owning port.
    - Define macros to print STP bridge and port ids.
    - New helper function to get port id.
    - New helper function to convert speed to cost.
    - New functions to describe current role of port.
---
 lib/stp.c |   95 ++++++++++++++++++++++++++++++++++++++++++++++++++++---------
 lib/stp.h |   41 +++++++++++++++++++++++++-
 2 files changed, 120 insertions(+), 16 deletions(-)

diff --git a/lib/stp.c b/lib/stp.c
index f58d640..d67cd0e 100644
--- a/lib/stp.c
+++ b/lib/stp.c
@@ -77,6 +77,7 @@ struct stp_timer {
 
 struct stp_port {
     struct stp *stp;
+    void *aux;                      /* Auxiliary data the user may retrieve. */
     int port_id;                    /* 8.5.5.1: Unique port identifier. */
     enum stp_state state;           /* 8.5.5.2: Current state. */
     int path_cost;                  /* 8.5.5.3: Cost of tx/rx on this port. */
@@ -223,9 +224,9 @@ stp_create(const char *name, stp_identifier bridge_id,
         stp->bridge_id |= (uint64_t) STP_DEFAULT_BRIDGE_PRIORITY << 48;
     }
 
-    stp->rq_max_age = 6000;
-    stp->rq_hello_time = 2000;
-    stp->rq_forward_delay = 4000;
+    stp->rq_max_age = STP_DEFAULT_MAX_AGE;
+    stp->rq_hello_time = STP_DEFAULT_HELLO_TIME;
+    stp->rq_forward_delay = STP_DEFAULT_FWD_DELAY;
     stp_update_bridge_timers(stp);
     stp->max_age = stp->bridge_max_age;
     stp->hello_time = stp->bridge_hello_time;
@@ -526,6 +527,23 @@ stp_learn_in_state(enum stp_state state)
     return (state & (STP_DISABLED | STP_LEARNING | STP_FORWARDING)) != 0;
 }
 
+/* Returns the name for the given 'role' (for use in debugging and log
+ * messages). */
+const char *
+stp_role_name(enum stp_role role)
+{
+    switch (role) {
+    case STP_ROLE_ROOT:
+        return "root";
+    case STP_ROLE_DESIGNATED:
+        return "designated";
+    case STP_ROLE_ALTERNATE:
+        return "alternate";
+    default:
+        NOT_REACHED();
+    }
+}
+
 /* Notifies the STP entity that bridge protocol data unit 'bpdu', which is
  * 'bpdu_size' bytes in length, was received on port 'p'.
  *
@@ -589,6 +607,24 @@ stp_port_get_stp(struct stp_port *p)
     return p->stp;
 }
 
+/* Sets the 'aux' member of 'p'.
+ *
+ * The 'aux' member will be reset to NULL when stp_port_disable() is
+ * called or stp_port_enable() is called when the port is in a Disabled
+ * state. */
+void
+stp_port_set_aux(struct stp_port *p, void *aux)
+{
+    p->aux = aux;
+}
+
+/* Returns the 'aux' member of 'p'. */
+void *
+stp_port_get_aux(struct stp_port *p)
+{
+    return p->aux;
+}
+
 /* Returns the index of port 'p' within its bridge. */
 int
 stp_port_no(const struct stp_port *p)
@@ -598,6 +634,13 @@ stp_port_no(const struct stp_port *p)
     return p - stp->ports;
 }
 
+/* Returns the port ID for 'p'. */
+int
+stp_port_get_id(const struct stp_port *p)
+{
+    return p->port_id;
+}
+
 /* Returns the state of port 'p'. */
 enum stp_state
 stp_port_get_state(const struct stp_port *p)
@@ -605,6 +648,21 @@ stp_port_get_state(const struct stp_port *p)
     return p->state;
 }
 
+/* Returns the role of port 'p'. */
+enum stp_role
+stp_port_get_role(const struct stp_port *p)
+{
+    struct stp_port *root_port = stp_get_root_port(p->stp);
+
+    if (root_port && root_port->port_id == p->port_id) {
+        return STP_ROLE_ROOT;
+    } else if (stp_is_designated_port(p)) {
+        return STP_ROLE_DESIGNATED;
+    } else {
+        return STP_ROLE_ALTERNATE;
+    }
+}
+
 /* Disables STP on port 'p'. */
 void
 stp_port_disable(struct stp_port *p)
@@ -623,6 +681,7 @@ stp_port_disable(struct stp_port *p)
         if (stp_is_root_bridge(stp) && !root) {
             stp_become_root_bridge(stp);
         }
+        p->aux = NULL;
     }
 }
 
@@ -656,6 +715,19 @@ stp_port_set_priority(struct stp_port *p, uint8_t 
new_priority)
     }
 }
 
+/* Convert 'speed' (measured in Mb/s) into the path cost. */
+uint16_t
+stp_convert_speed_to_cost(unsigned int speed)
+{
+    return speed >= 10000 ? 2  /* 10 Gb/s. */
+           : speed >= 1000 ? 4 /* 1 Gb/s. */
+           : speed >= 100 ? 19 /* 100 Mb/s. */
+           : speed >= 16 ? 62  /* 16 Mb/s. */
+           : speed >= 10 ? 100 /* 10 Mb/s. */
+           : speed >= 4 ? 250  /* 4 Mb/s. */
+           : 19;             /* 100 Mb/s (guess). */
+}
+
 /* Sets the path cost of port 'p' to 'path_cost'.  Lower values are generally
  * used to indicate faster links.  Use stp_port_set_speed() to automatically
  * generate a default path cost from a link speed. */
@@ -674,13 +746,7 @@ stp_port_set_path_cost(struct stp_port *p, uint16_t 
path_cost)
 void
 stp_port_set_speed(struct stp_port *p, unsigned int speed)
 {
-    stp_port_set_path_cost(p, (speed >= 10000 ? 2  /* 10 Gb/s. */
-                               : speed >= 1000 ? 4 /* 1 Gb/s. */
-                               : speed >= 100 ? 19 /* 100 Mb/s. */
-                               : speed >= 16 ? 62  /* 16 Mb/s. */
-                               : speed >= 10 ? 100 /* 10 Mb/s. */
-                               : speed >= 4 ? 250  /* 4 Mb/s. */
-                               : 19));             /* 100 Mb/s (guess). */
+    stp_port_set_path_cost(p, stp_convert_speed_to_cost(speed));
 }
 
 /* Enables topology change detection on port 'p'. */
@@ -715,10 +781,10 @@ stp_transmit_config(struct stp_port *p)
         config.header.bpdu_type = STP_TYPE_CONFIG;
         config.flags = 0;
         if (p->topology_change_ack) {
-            config.flags |= htons(STP_CONFIG_TOPOLOGY_CHANGE_ACK);
+            config.flags |= STP_CONFIG_TOPOLOGY_CHANGE_ACK;
         }
         if (stp->topology_change) {
-            config.flags |= htons(STP_CONFIG_TOPOLOGY_CHANGE);
+            config.flags |= STP_CONFIG_TOPOLOGY_CHANGE;
         }
         config.root_id = htonll(stp->designated_root);
         config.root_path_cost = htonl(stp->root_path_cost);
@@ -776,7 +842,7 @@ stp_record_config_timeout_values(struct stp *stp,
     stp->max_age = ntohs(config->max_age);
     stp->hello_time = ntohs(config->hello_time);
     stp->forward_delay = ntohs(config->forward_delay);
-    stp->topology_change = config->flags & htons(STP_CONFIG_TOPOLOGY_CHANGE);
+    stp->topology_change = config->flags & STP_CONFIG_TOPOLOGY_CHANGE;
 }
 
 static bool
@@ -1004,7 +1070,7 @@ stp_received_config_bpdu(struct stp *stp, struct stp_port 
*p,
             if (p == stp->root_port) {
                 stp_record_config_timeout_values(stp, config);
                 stp_config_bpdu_generation(stp);
-                if (config->flags & htons(STP_CONFIG_TOPOLOGY_CHANGE_ACK)) {
+                if (config->flags & STP_CONFIG_TOPOLOGY_CHANGE_ACK) {
                     stp_topology_change_acknowledged(stp);
                 }
             }
@@ -1111,6 +1177,7 @@ stp_initialize_port(struct stp_port *p, enum stp_state 
state)
     p->topology_change_ack = false;
     p->config_pending = false;
     p->change_detection_enabled = true;
+    p->aux = NULL;
     stp_stop_timer(&p->message_age_timer);
     stp_stop_timer(&p->forward_delay_timer);
     stp_stop_timer(&p->hold_timer);
diff --git a/lib/stp.h b/lib/stp.h
index 3ea1e1c..8dbe41f 100644
--- a/lib/stp.h
+++ b/lib/stp.h
@@ -36,10 +36,28 @@ struct ofpbuf;
 #define STP_DEFAULT_BRIDGE_PRIORITY 32768
 #define STP_DEFAULT_PORT_PRIORITY 128
 
+/* Default time values. */
+#define STP_DEFAULT_MAX_AGE    20000
+#define STP_DEFAULT_HELLO_TIME 2000
+#define STP_DEFAULT_FWD_DELAY  15000
+
 /* Bridge identifier.  Top 16 bits are a priority value (numerically lower
  * values are higher priorities).  Bottom 48 bits are MAC address of bridge. */
 typedef uint64_t stp_identifier;
 
+
+#define STP_ID_FMT                                                    \
+    
"%02"PRIx8"%02"PRIx8".%02"PRIx8"%02"PRIx8"%02"PRIx8"%02"PRIx8"%02"PRIx8"%02"PRIx8
+#define STP_ID_ARGS(stp_id)                                           \
+    (uint8_t)(stp_id >> 56), (uint8_t)(stp_id >> 48),                 \
+    (uint8_t)(stp_id >> 40), (uint8_t)(stp_id >> 32),                 \
+    (uint8_t)(stp_id >> 24), (uint8_t)(stp_id >> 16),                 \
+    (uint8_t)(stp_id >> 8), (uint8_t)(stp_id)
+
+#define STP_PORT_ID_FMT  "%02"PRIx8"%02"PRIx8
+#define STP_PORT_ID_ARGS(stp_port_id)                                 \
+    (uint8_t)(stp_port_id >> 8), (uint8_t)(stp_port_id)
+
 /* Basic STP functionality. */
 #define STP_MAX_PORTS 255
 struct stp *stp_create(const char *name, stp_identifier bridge_id,
@@ -72,9 +90,16 @@ bool stp_get_changed_port(struct stp *, struct stp_port 
**portp);
 /* State of an STP port.
  *
  * A port is in exactly one state at any given time, but distinct bits are used
- * for states to allow testing for more than one state with a bit mask. */
+ * for states to allow testing for more than one state with a bit mask.
+ *
+ * The STP_DISABLED state means that the port is disabled by management.
+ * In our implementation, this state means that the port does not
+ * participate in the spanning tree, but it still forwards traffic as if
+ * it were in the STP_FORWARDING state.  This may be different from
+ * other implementations.
+ */
 enum stp_state {
-    STP_DISABLED = 1 << 0,       /* 8.4.5: Disabled by management. */
+    STP_DISABLED = 1 << 0,       /* 8.4.5: See note above. */
     STP_LISTENING = 1 << 1,      /* 8.4.2: Not learning or relaying frames. */
     STP_LEARNING = 1 << 2,       /* 8.4.3: Learning but not relaying frames. */
     STP_FORWARDING = 1 << 3,     /* 8.4.4: Learning and relaying frames. */
@@ -84,14 +109,26 @@ const char *stp_state_name(enum stp_state);
 bool stp_forward_in_state(enum stp_state);
 bool stp_learn_in_state(enum stp_state);
 
+enum stp_role {
+    STP_ROLE_ROOT,
+    STP_ROLE_DESIGNATED,
+    STP_ROLE_ALTERNATE
+};
+const char *stp_role_name(enum stp_role);
+
 void stp_received_bpdu(struct stp_port *, const void *bpdu, size_t bpdu_size);
 
 struct stp *stp_port_get_stp(struct stp_port *);
+void stp_port_set_aux(struct stp_port *, void *);
+void *stp_port_get_aux(struct stp_port *);
 int stp_port_no(const struct stp_port *);
+int stp_port_get_id(const struct stp_port *);
 enum stp_state stp_port_get_state(const struct stp_port *);
+enum stp_role stp_port_get_role(const struct stp_port *);
 void stp_port_enable(struct stp_port *);
 void stp_port_disable(struct stp_port *);
 void stp_port_set_priority(struct stp_port *, uint8_t new_priority);
+uint16_t stp_convert_speed_to_cost(unsigned int speed);
 void stp_port_set_path_cost(struct stp_port *, uint16_t path_cost);
 void stp_port_set_speed(struct stp_port *, unsigned int speed);
 void stp_port_enable_change_detection(struct stp_port *);
-- 
1.7.1

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to