From patchwork Fri May 19 07:20:41 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: nickcooper-zhangtonghao X-Patchwork-Id: 764472 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3wTfcF55Tqz9s5L for ; Fri, 19 May 2017 17:21:17 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id EB10BB2B; Fri, 19 May 2017 07:21:13 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp2.linuxfoundation.org (smtp2.linux-foundation.org [172.17.192.36]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 73C7995E for ; Fri, 19 May 2017 07:21:12 +0000 (UTC) X-Greylist: from auto-whitelisted by SQLgrey-1.7.6 Received: from smtpbgsg2.qq.com (smtpbgsg2.qq.com [54.254.200.128]) by smtp2.linuxfoundation.org (Postfix) with ESMTPS id CE88E1E471 for ; Fri, 19 May 2017 07:21:10 +0000 (UTC) X-QQ-mid: bizesmtp13t1495178465tzbxik91 Received: from local.opencloud.tech.localdomai (unknown [106.120.127.10]) by esmtp4.qq.com (ESMTP) with id ; Fri, 19 May 2017 15:21:04 +0800 (CST) X-QQ-SSF: 01100000002000F0FG90B00A0000000 X-QQ-FEAT: UwW+5R6BrEN2uBGO60obkGyniuULiNpEuPms9cwEdw2DKeK28C3bWKkN6khZI z41LGVhFk+uszeM/AjX00Ra3X9U+/4cpws7hxDumZ4UI8tfwlmHOIXj3X8NW5bo6w4Fzxfm cxVrmSbroJQoqCci0EWFjhPt+T38mwOTpqpQD0y7eN85QExEAm1EPhD7VH5UwvzZEdd6ufU hG1Ng+1X5PJrqCz35jFVEYUP55unHHL+VO771df1qD7EI+X7gazD/DIBXaaAn4lxplSXq+B xD5oGMpEYjQqoWI7c35YO018M= X-QQ-GoodBg: 0 From: nickcooper-zhangtonghao To: dev@openvswitch.org Date: Fri, 19 May 2017 00:20:41 -0700 Message-Id: <1495178443-102536-3-git-send-email-nic@opencloud.tech> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1495178443-102536-1-git-send-email-nic@opencloud.tech> References: <1495178443-102536-1-git-send-email-nic@opencloud.tech> X-QQ-SENDSIZE: 520 X-QQ-Bgrelay: 1 X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp2.linux-foundation.org Subject: [ovs-dev] [PATCH v3 3/5] rstp: Add the 'ovs-appctl rstp/show' command. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org The rstp/show command will help users and developers to get more details about rstp. This patch works together with the previous patches. Signed-off-by: nickcooper-zhangtonghao --- NEWS | 3 +- lib/rstp.c | 114 +++++++++++++++++++++++++++++++++++++++++++-- lib/rstp.h | 2 +- vswitchd/ovs-vswitchd.8.in | 11 ++++- 4 files changed, 123 insertions(+), 7 deletions(-) diff --git a/NEWS b/NEWS index 7a2b185..4576408 100644 --- a/NEWS +++ b/NEWS @@ -28,7 +28,8 @@ Post-v2.7.0 abbreviated to 4 hex digits. * "ovn-sbctl lflow-list" can now print OpenFlow flows that correspond to logical flows. - - Add the command 'ovs-appctl stp/show' (see ovs-vswitchd(8)). + - Add the command 'ovs-appctl stp/show' and 'ovs-appctl rstp/show' + (see ovs-vswitchd(8)). - OpenFlow: * All features required by OpenFlow 1.4 are now implemented, so ovs-vswitchd now enables OpenFlow 1.4 by default (in addition to diff --git a/lib/rstp.c b/lib/rstp.c index 48df7ad..095e01f 100644 --- a/lib/rstp.c +++ b/lib/rstp.c @@ -120,6 +120,10 @@ static void rstp_port_set_mcheck__(struct rstp_port *, bool mcheck) OVS_REQUIRES(rstp_mutex); static void reinitialize_port__(struct rstp_port *p) OVS_REQUIRES(rstp_mutex); +static void rstp_unixctl_tcn(struct unixctl_conn *, int argc, + const char *argv[], void *aux); +static void rstp_unixctl_show(struct unixctl_conn *, int argc, + const char *argv[], void *aux); const char * rstp_state_name(enum rstp_state state) @@ -205,9 +209,6 @@ rstp_port_get_number(const struct rstp_port *p) return number; } -static void rstp_unixctl_tcn(struct unixctl_conn *, int argc, - const char *argv[], void *aux); - /* Decrements the State Machines' timers. */ void rstp_tick_timers(struct rstp *rstp) @@ -240,6 +241,8 @@ rstp_init(void) unixctl_command_register("rstp/tcn", "[bridge]", 0, 1, rstp_unixctl_tcn, NULL); + unixctl_command_register("rstp/show", "[bridge]", 0, 1, + rstp_unixctl_show, NULL); ovsthread_once_done(&once); } } @@ -1367,7 +1370,7 @@ rstp_get_designated_root(const struct rstp *rstp) * there is no such port. */ struct rstp_port * -rstp_get_root_port(struct rstp *rstp) +rstp_get_root_port(const struct rstp *rstp) { struct rstp_port *p; @@ -1506,3 +1509,106 @@ rstp_unixctl_tcn(struct unixctl_conn *conn, int argc, out: ovs_mutex_unlock(&rstp_mutex); } + +static void +rstp_bridge_id_details(struct ds *ds, const rstp_identifier bridge_id, + const uint16_t hello_time, const uint16_t max_age, + const uint16_t forward_delay) + OVS_REQUIRES(rstp_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%"PRIu16"s\n", hello_time); + ds_put_format(ds, "\tstp-max-age\t%"PRIu16"s\n", max_age); + ds_put_format(ds, "\tstp-fwd-delay\t%"PRIu16"s\n", forward_delay); +} + +static void +rstp_print_details(struct ds *ds, const struct rstp *rstp) + OVS_REQUIRES(rstp_mutex) +{ + ds_put_format(ds, "---- %s ----\n", rstp->name); + ds_put_cstr(ds, "Root ID:\n"); + + bool is_root = rstp_is_root_bridge(rstp); + struct rstp_port *p = rstp_get_root_port(rstp); + + rstp_identifier bridge_id = + is_root ? rstp->bridge_identifier : rstp_get_root_id(rstp); + uint16_t hello_time = + is_root ? rstp->bridge_hello_time : p->designated_times.hello_time; + uint16_t max_age = + is_root ? rstp->bridge_max_age : p->designated_times.max_age; + uint16_t forward_delay = + is_root ? rstp->bridge_forward_delay : p->designated_times.forward_delay; + + rstp_bridge_id_details(ds, bridge_id, hello_time, max_age, forward_delay); + if (is_root) { + ds_put_cstr(ds, "\tThis bridge is the root\n"); + } else { + ds_put_format(ds, "\troot-port\t%s\n", p->port_name); + ds_put_format(ds, "\troot-path-cost\t%u\n", + rstp_get_root_path_cost(rstp)); + } + ds_put_cstr(ds, "\n"); + + ds_put_cstr(ds, "Bridge ID:\n"); + rstp_bridge_id_details(ds, rstp->bridge_identifier, + rstp->bridge_hello_time, + rstp->bridge_max_age, + rstp->bridge_forward_delay); + ds_put_cstr(ds, "\n"); + + ds_put_format(ds, "\t%-11.10s%-11.10s%-11.10s%-9.8s%-8.7s\n", + "Interface", "Role", "State", "Cost", "Pri.Nbr"); + ds_put_cstr(ds, "\t---------- ---------- ---------- -------- -------\n"); + HMAP_FOR_EACH (p, node, &rstp->ports) { + if (p->rstp_state != RSTP_DISABLED) { + ds_put_format(ds, "\t%-11.10s", + p->port_name ? p->port_name : "null"); + ds_put_format(ds, "%-11.10s", rstp_port_role_name(p->role)); + ds_put_format(ds, "%-11.10s", rstp_state_name(p->rstp_state)); + ds_put_format(ds, "%-9d", p->port_path_cost); + ds_put_format(ds, "%d.%d\n", p->priority, p->port_number); + } + } + + ds_put_cstr(ds, "\n"); +} + +static void +rstp_unixctl_show(struct unixctl_conn *conn, int argc, + const char *argv[], void *aux OVS_UNUSED) + OVS_EXCLUDED(rstp_mutex) +{ + struct ds ds = DS_EMPTY_INITIALIZER; + + ovs_mutex_lock(&rstp_mutex); + if (argc > 1) { + struct rstp *rstp = rstp_find(argv[1]); + + if (!rstp) { + unixctl_command_reply_error(conn, "No such RSTP object"); + goto out; + } + + rstp_print_details(&ds, rstp); + } else { + struct rstp *rstp; + + LIST_FOR_EACH (rstp, node, all_rstps) { + rstp_print_details(&ds, rstp); + } + } + + unixctl_command_reply(conn, ds_cstr(&ds)); + ds_destroy(&ds); + +out: + ovs_mutex_unlock(&rstp_mutex); +} diff --git a/lib/rstp.h b/lib/rstp.h index b6f9089..15b1f14 100644 --- a/lib/rstp.h +++ b/lib/rstp.h @@ -180,7 +180,7 @@ rstp_identifier rstp_get_designated_id(const struct rstp *); uint32_t rstp_get_root_path_cost(const struct rstp *); uint16_t rstp_get_designated_port_id(const struct rstp *); uint16_t rstp_get_bridge_port_id(const struct rstp *); -struct rstp_port * rstp_get_root_port(struct rstp *); +struct rstp_port * rstp_get_root_port(const struct rstp *); rstp_identifier rstp_get_designated_root(const struct rstp *); bool rstp_is_root_bridge(const struct rstp *); diff --git a/vswitchd/ovs-vswitchd.8.in b/vswitchd/ovs-vswitchd.8.in index be7bd66..9178737 100644 --- a/vswitchd/ovs-vswitchd.8.in +++ b/vswitchd/ovs-vswitchd.8.in @@ -141,12 +141,21 @@ interfaces if none is given) to be \fIstatus\fR. \fIstatus\fR can be .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 +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. +.IP "\fBrstp/tcn\fR [\fIbridge\fR]" +Forces a topology change event on \fIbridge\fR if it's running RSTP. 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 "\fBrstp/show\fR [\fIbridge\fR]" +Displays detailed information about rapid spanning tree on the \fIbridge\fR. +If \fIbridge\fR is not specified, then displays detailed information about all +bridges with RSTP enabled. .SS "BRIDGE COMMANDS" These commands manage bridges. .IP "\fBfdb/flush\fR [\fIbridge\fR]"