@@ -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,107 @@ 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)
+{
+ struct eth_addr mac;
+ const uint64_t mac_bits = (UINT64_C(1) << 48) - 1;
+
+ ds_put_format(ds, "\tstp-priority\t%"PRIu32"\n",
+ (uint16_t)(bridge_id >> 48));
+
+ 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%"PRId32"s\n",
+ timer_to_ms(hello_time) / 1000);
+ ds_put_format(ds, "\tstp-max-age\t%"PRId32"s\n",
+ timer_to_ms(max_age) / 1000);
+ ds_put_format(ds, "\tstp-fwd-delay\t%"PRId32"s\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%"PRIu32"\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, "%-6"PRId32, p->path_cost);
+ ds_put_format(ds, "%"PRIu16".%"PRIu16"\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);
+}
The stp/show command will help users and developers 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> --- lib/stp.c | 108 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+)