[ovs-dev,2/2] stp: Add the 'ovs-appctl stp/show' command.

Submitted by nickcooper-zhangtonghao on March 18, 2017, 8:13 a.m.

Details

Message ID 1489824836-32780-2-git-send-email-nic@opencloud.tech
State Accepted
Headers show

Commit Message

nickcooper-zhangtonghao March 18, 2017, 8:13 a.m.
The stp/show command will help users and developers to
get more details about stp. This patch works together with
the previous patch "stp: Change the api for next patch."

Signed-off-by: nickcooper-zhangtonghao <nic@opencloud.tech>
Co-authored-by: Ben Pfaff <blp@ovn.org>
---
 NEWS                       |  1 +
 lib/stp.c                  | 98 ++++++++++++++++++++++++++++++++++++++++++++++
 vswitchd/ovs-vswitchd.8.in |  4 ++
 3 files changed, 103 insertions(+)

Comments

Ben Pfaff March 20, 2017, 5:28 p.m.
On Sat, Mar 18, 2017 at 01:13:56AM -0700, nickcooper-zhangtonghao wrote:
> The stp/show command will help users and developers to
> get more details about stp. This patch works together with
> the previous patch "stp: Change the api for next patch."
> 
> Signed-off-by: nickcooper-zhangtonghao <nic@opencloud.tech>
> Co-authored-by: Ben Pfaff <blp@ovn.org>

Thanks for these patches!  I applied both of these to master.

Patch hide | download patch | download mbox

diff --git a/NEWS b/NEWS
index e2e456a..00c9106 100644
--- a/NEWS
+++ b/NEWS
@@ -15,6 +15,7 @@  Post-v2.7.0
      "dot1q-tunnel" port VLAN mode.
    - OVN:
      * Make the DHCPv4 router setting optional.
+   - Add the command 'ovs-appctl stp/show' (see ovs-vswitchd(8)).
 
 v2.7.0 - 21 Feb 2017
 ---------------------
diff --git a/lib/stp.c b/lib/stp.c
index b7ddc39..952d3ce 100644
--- a/lib/stp.c
+++ b/lib/stp.c
@@ -236,6 +236,8 @@  static void stp_send_bpdu(struct stp_port *, const void *, size_t)
     OVS_REQUIRES(mutex);
 static void stp_unixctl_tcn(struct unixctl_conn *, int argc,
                             const char *argv[], void *aux);
+static void stp_unixctl_show(struct unixctl_conn *, int argc,
+                             const char *argv[], void *aux);
 
 void
 stp_init(void)
@@ -251,6 +253,8 @@  stp_init(void)
 
         unixctl_command_register("stp/tcn", "[bridge]", 0, 1, stp_unixctl_tcn,
                                  NULL);
+        unixctl_command_register("stp/show", "[bridge]", 0, 1,
+                                 stp_unixctl_show, NULL);
         ovsthread_once_done(&once);
     }
 }
@@ -1634,3 +1638,97 @@  stp_unixctl_tcn(struct unixctl_conn *conn, int argc,
 out:
     ovs_mutex_unlock(&mutex);
 }
+
+static void
+stp_bridge_id_details(struct ds *ds, const stp_identifier bridge_id,
+                      const int hello_time, const int max_age,
+                      const int forward_delay)
+    OVS_REQUIRES(mutex)
+{
+    uint16_t priority = bridge_id >> 48;
+    ds_put_format(ds, "\tstp-priority\t%"PRIu16"\n", priority);
+
+    struct eth_addr mac;
+    const uint64_t mac_bits = (UINT64_C(1) << 48) - 1;
+    eth_addr_from_uint64(bridge_id & mac_bits, &mac);
+    ds_put_format(ds, "\tstp-system-id\t"ETH_ADDR_FMT"\n", ETH_ADDR_ARGS(mac));
+    ds_put_format(ds, "\tstp-hello-time\t%ds\n",
+                  timer_to_ms(hello_time) / 1000);
+    ds_put_format(ds, "\tstp-max-age\t%ds\n", timer_to_ms(max_age) / 1000);
+    ds_put_format(ds, "\tstp-fwd-delay\t%ds\n",
+                  timer_to_ms(forward_delay) / 1000);
+}
+
+static void
+stp_print_details(struct ds *ds, const struct stp *stp)
+    OVS_REQUIRES(mutex)
+{
+    const uint16_t port_no_bits = (UINT16_C(1) << 8) - 1;
+
+    ds_put_format(ds, "---- %s ----\n", stp->name);
+    ds_put_cstr(ds, "Root ID:\n");
+
+    stp_bridge_id_details(ds, stp->designated_root, stp->bridge_hello_time,
+                          stp->bridge_max_age, stp->bridge_forward_delay);
+
+    if (stp_is_root_bridge(stp)) {
+        ds_put_cstr(ds, "\tThis bridge is the root\n");
+    } else {
+        ds_put_format(ds, "\troot-port\t%s\n", stp->root_port->port_name);
+        ds_put_format(ds, "\troot-path-cost\t%u\n", stp->root_path_cost);
+    }
+
+    ds_put_cstr(ds, "\n");
+
+    ds_put_cstr(ds, "Bridge ID:\n");
+    stp_bridge_id_details(ds, stp->bridge_id, stp->hello_time,
+                          stp->max_age, stp->forward_delay);
+
+    ds_put_cstr(ds, "\n");
+
+    const struct stp_port *p;
+    ds_put_format(ds, "\t%-11.10s%-11.10s%-11.10s%-6.5s%-8.7s\n",
+                  "Interface", "Role", "State", "Cost", "Pri.Nbr");
+    ds_put_cstr(ds, "\t---------- ---------- ---------- ----- -------\n");
+    FOR_EACH_ENABLED_PORT (p, stp) {
+        ds_put_format(ds, "\t%-11.10s", p->port_name);
+        ds_put_format(ds, "%-11.10s", stp_role_name(stp_port_get_role(p)));
+        ds_put_format(ds, "%-11.10s", stp_state_name(p->state));
+        ds_put_format(ds, "%-6d", p->path_cost);
+        ds_put_format(ds, "%d.%d\n", p->port_id >> 8,
+                      p->port_id & port_no_bits);
+    }
+
+    ds_put_cstr(ds, "\n");
+}
+
+static void
+stp_unixctl_show(struct unixctl_conn *conn, int argc,
+                 const char *argv[], void *aux OVS_UNUSED)
+{
+    struct ds ds = DS_EMPTY_INITIALIZER;
+
+    ovs_mutex_lock(&mutex);
+    if (argc > 1) {
+        struct stp *stp = stp_find(argv[1]);
+
+        if (!stp) {
+            unixctl_command_reply_error(conn, "no such stp object");
+            goto out;
+        }
+
+        stp_print_details(&ds, stp);
+    } else {
+        struct stp *stp;
+
+        LIST_FOR_EACH (stp, node, all_stps) {
+            stp_print_details(&ds, stp);
+        }
+    }
+
+    unixctl_command_reply(conn, ds_cstr(&ds));
+    ds_destroy(&ds);
+
+out:
+    ovs_mutex_unlock(&mutex);
+}
diff --git a/vswitchd/ovs-vswitchd.8.in b/vswitchd/ovs-vswitchd.8.in
index fc19f3b..8496aa6 100644
--- a/vswitchd/ovs-vswitchd.8.in
+++ b/vswitchd/ovs-vswitchd.8.in
@@ -140,6 +140,10 @@  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.
+.IP "\fBstp/show\fR [\fIbridge\fR]"
+Displays detailed information about spanning tree on the \fIbridge\fR.  If
+\fIbridge\fR is not specified, then displays detailed information about all
+bridges with STP enabled.
 .SS "BRIDGE COMMANDS"
 These commands manage bridges.
 .IP "\fBfdb/flush\fR [\fIbridge\fR]"