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 <n...@opencloud.tech>
Co-authored-by: Ben Pfaff <b...@ovn.org>
---
 NEWS                       |  1 +
 lib/stp.c                  | 98 ++++++++++++++++++++++++++++++++++++++++++++++
 vswitchd/ovs-vswitchd.8.in |  4 ++
 3 files changed, 103 insertions(+)

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]"
-- 
1.8.3.1



_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to