stp: Allow manual topology change events.
authorEthan Jackson <ethan@nicira.com>
Sat, 14 Jan 2012 02:49:36 +0000 (18:49 -0800)
committerEthan Jackson <ethan@nicira.com>
Wed, 25 Jan 2012 21:11:07 +0000 (13:11 -0800)
Users may want to force the network to flush its MAC tables by
manually triggering a topology change event due to some event in
the system.

Signed-off-by: Ethan Jackson <ethan@nicira.com>
lib/stp.c
lib/stp.h
vswitchd/bridge.c
vswitchd/ovs-vswitchd.8.in

index f7fe53cc9fe93e07a49bcfeb9dbbdc8b9e3095b5..ba273061f0a84b994c3b8b412285b5bc45d0b7ec 100644 (file)
--- a/lib/stp.c
+++ b/lib/stp.c
@@ -29,6 +29,7 @@
 #include "byte-order.h"
 #include "ofpbuf.h"
 #include "packets.h"
+#include "unixctl.h"
 #include "util.h"
 #include "vlog.h"
 
@@ -101,6 +102,8 @@ struct stp_port {
 };
 
 struct stp {
+    struct list node;               /* Node in all_stps list. */
+
     /* Static bridge data. */
     char *name;                     /* Human-readable name for log messages. */
     stp_identifier bridge_id;       /* 8.5.3.7: This bridge. */
@@ -137,6 +140,8 @@ struct stp {
     void *aux;
 };
 
+static struct list all_stps = LIST_INITIALIZER(&all_stps);
+
 #define FOR_EACH_ENABLED_PORT(PORT, STP)                        \
     for ((PORT) = stp_next_enabled_port((STP), (STP)->ports);   \
          (PORT);                                                \
@@ -199,6 +204,15 @@ static void stp_stop_timer(struct stp_timer *);
 static bool stp_timer_expired(struct stp_timer *, int elapsed, int timeout);
 
 static void stp_send_bpdu(struct stp_port *, const void *, size_t);
+static void stp_unixctl_tcn(struct unixctl_conn *, int argc,
+                            const char *argv[], void *aux);
+
+void
+stp_init(void)
+{
+    unixctl_command_register("stp/tcn", "[bridge]", 0, 1, stp_unixctl_tcn,
+                             NULL);
+}
 
 /* Creates and returns a new STP instance that initially has no ports enabled.
  *
@@ -256,6 +270,7 @@ stp_create(const char *name, stp_identifier bridge_id,
         p->path_cost = 19;      /* Recommended default for 100 Mb/s link. */
         stp_initialize_port(p, STP_DISABLED);
     }
+    list_push_back(&all_stps, &stp->node);
     return stp;
 }
 
@@ -264,6 +279,7 @@ void
 stp_destroy(struct stp *stp)
 {
     if (stp) {
+        list_remove(&stp->node);
         free(stp->name);
         free(stp);
     }
@@ -1328,3 +1344,41 @@ stp_send_bpdu(struct stp_port *p, const void *bpdu, size_t bpdu_size)
     p->stp->send_bpdu(pkt, stp_port_no(p), p->stp->aux);
     p->tx_count++;
 }
+\f
+/* Unixctl. */
+
+static struct stp *
+stp_find(const char *name)
+{
+    struct stp *stp;
+
+    LIST_FOR_EACH (stp, node, &all_stps) {
+        if (!strcmp(stp->name, name)) {
+            return stp;
+        }
+    }
+    return NULL;
+}
+
+static void
+stp_unixctl_tcn(struct unixctl_conn *conn, int argc,
+                const char *argv[], void *aux OVS_UNUSED)
+{
+    if (argc > 1) {
+        struct stp *stp = stp_find(argv[1]);
+
+        if (!stp) {
+            unixctl_command_reply(conn, 501, "no such stp object");
+            return;
+        }
+        stp_topology_change_detection(stp);
+    } else {
+        struct stp *stp;
+
+        LIST_FOR_EACH (stp, node, &all_stps) {
+            stp_topology_change_detection(stp);
+        }
+    }
+
+    unixctl_command_reply(conn, 200, "OK");
+}
index f321dec9cd3bb2ce760ebf5f7f7fd2eed492303c..8ce093e296c61ad5ea9505870cc8753417a24648 100644 (file)
--- a/lib/stp.h
+++ b/lib/stp.h
@@ -55,6 +55,7 @@ typedef uint64_t stp_identifier;
 
 /* Basic STP functionality. */
 #define STP_MAX_PORTS 255
+void stp_init(void);
 struct stp *stp_create(const char *name, stp_identifier bridge_id,
                        void (*send_bpdu)(struct ofpbuf *bpdu, int port_no,
                                          void *aux),
index c40bcb5f1fe6f7f9c9ce4d05258208c75cf3cffd..06e9088e2f4f2e6fce66665dcaa80adde75804b6 100644 (file)
@@ -319,6 +319,7 @@ bridge_init(const char *remote)
     lacp_init();
     bond_init();
     cfm_init();
+    stp_init();
 }
 
 void
index 4fa707b1cb41f803c232571982f44ee10ddd03ec..01dfcdfe1da053a42ff82cf74a6600339013f4a3 100644 (file)
@@ -118,6 +118,11 @@ Displays detailed information about Connectivity Fault Management
 configured on \fIinterface\fR.  If \fIinterface\fR is not specified,
 then displays detailed information about all interfaces with CFM
 enabled.
+.IP "\fBstp/tcn\fR [\fIbridge\fR]"
+Forces a topology change event on \fIbridge\fR if it's running STP.  This
+may cause it to send Topology Change Notifications to its peers and flush
+its MAC table..  If no \fIbridge\fR is given, forces a topology change
+event on all bridges.
 .SS "BRIDGE COMMANDS"
 These commands manage bridges.
 .IP "\fBfdb/flush\fR [\fIbridge\fR]"