I’d like to see one of the existing RSTP test cases modified to use this new 
feature.

One more comment below,

  Jarno


> On Mar 31, 2017, at 8:11 PM, nickcooper-zhangtonghao <n...@opencloud.tech> 
> wrote:
> 
> 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 <n...@opencloud.tech>
> ---
> NEWS                       |   4 +-
> lib/rstp.c                 | 113 +++++++++++++++++++++++++++++++++++++++++++--
> lib/rstp.h                 |   2 +-
> vswitchd/ovs-vswitchd.8.in |  11 ++++-
> 4 files changed, 123 insertions(+), 7 deletions(-)
> 
> diff --git a/NEWS b/NEWS
> index 00c9106..a28b8da 100644
> --- a/NEWS
> +++ b/NEWS
> @@ -15,7 +15,9 @@ 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)).
> +   - STP/RSTP
> +     * Add the command 'ovs-appctl stp/show' and 'ovs-appctl rstp/show'
> +       (see ovs-vswitchd(8)).
> 
> v2.7.0 - 21 Feb 2017
> ---------------------
> diff --git a/lib/rstp.c b/lib/rstp.c
> index b942f6e..7a4f1ea 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)
> @@ -208,9 +212,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)
> @@ -246,6 +247,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);
>     }
> }
> @@ -1398,7 +1401,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)
>     OVS_EXCLUDED(rstp_mutex)
> {
>     struct rstp_port *p;
> @@ -1545,3 +1548,105 @@ 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);

‘port_name’ is initialized as NULL in patch 5/6. Is it possible that it is 
still NULL when this function is called?

> +            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 fa67e3c..75c7d37 100644
> --- a/lib/rstp.h
> +++ b/lib/rstp.h
> @@ -201,7 +201,7 @@ uint16_t rstp_get_designated_port_id(const struct rstp *)
>     OVS_EXCLUDED(rstp_mutex);
> uint16_t rstp_get_bridge_port_id(const struct rstp *)
>     OVS_EXCLUDED(rstp_mutex);
> -struct rstp_port * rstp_get_root_port(struct rstp *)
> +struct rstp_port * rstp_get_root_port(const struct rstp *)
>     OVS_EXCLUDED(rstp_mutex);
> rstp_identifier rstp_get_designated_root(const struct rstp *)
>     OVS_EXCLUDED(rstp_mutex);
> diff --git a/vswitchd/ovs-vswitchd.8.in b/vswitchd/ovs-vswitchd.8.in
> index 8496aa6..7bbec05 100644
> --- a/vswitchd/ovs-vswitchd.8.in
> +++ b/vswitchd/ovs-vswitchd.8.in
> @@ -138,12 +138,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]"
> -- 
> 1.8.3.1
> 
> 
> 
> _______________________________________________
> dev mailing list
> d...@openvswitch.org
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev

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

Reply via email to