From fe4a02e4fa6be030a0478f6b01b0d4b6ab9b808f Mon Sep 17 00:00:00 2001 From: Ethan Jackson Date: Fri, 13 Jan 2012 18:49:36 -0800 Subject: [PATCH] stp: Allow manual topology change events. 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 --- lib/stp.c | 54 ++++++++++++++++++++++++++++++++++++++ lib/stp.h | 1 + vswitchd/bridge.c | 1 + vswitchd/ovs-vswitchd.8.in | 5 ++++ 4 files changed, 61 insertions(+) diff --git a/lib/stp.c b/lib/stp.c index f7fe53cc9..ba273061f 100644 --- 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++; } + +/* 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"); +} diff --git a/lib/stp.h b/lib/stp.h index f321dec9c..8ce093e29 100644 --- 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), diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c index c40bcb5f1..06e9088e2 100644 --- a/vswitchd/bridge.c +++ b/vswitchd/bridge.c @@ -319,6 +319,7 @@ bridge_init(const char *remote) lacp_init(); bond_init(); cfm_init(); + stp_init(); } void diff --git a/vswitchd/ovs-vswitchd.8.in b/vswitchd/ovs-vswitchd.8.in index 4fa707b1c..01dfcdfe1 100644 --- a/vswitchd/ovs-vswitchd.8.in +++ b/vswitchd/ovs-vswitchd.8.in @@ -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]" -- 2.45.2