From 016e46846db5decbe6337500230cb56fd4b1bdf7 Mon Sep 17 00:00:00 2001 From: Alex Wang Date: Wed, 12 Aug 2015 21:29:06 -0700 Subject: [PATCH] db-ctl-base: Allow print rows that weak reference to table in 'cmd_show_table'. Sometimes, it is desirable to print the table with weak reference to the table specified in 'struct cmd_show_table'. For example the Port_Binding table rows in OVN_Southbound database that refer to the same Chassis table row can be printed under the same chassis entry in 'ovn-sbctl show' output. To achieve it, this commit adds a new struct in 'struct cmd_show_table' that allows users to print a table with weak reference to 'table' specified in 'struct cmd_show_table'. The 'ovn-sbctl' which now prints the Port_Binding entries with Chassis table, is the first user of this new feature. Requested-by: Justin Pettit Signed-off-by: Alex Wang Acked-by: Justin Pettit --- lib/db-ctl-base.c | 43 +++++++++++++++++++++++++++++++++++++++ lib/db-ctl-base.h | 17 ++++++++++++++++ ovn/utilities/ovn-sbctl.c | 10 ++++++--- tests/ovn-sbctl.at | 24 ++++++++++++++++++++++ utilities/ovs-vsctl.c | 20 +++++++++++------- vtep/vtep-ctl.c | 17 ++++++++++------ 6 files changed, 115 insertions(+), 16 deletions(-) diff --git a/lib/db-ctl-base.c b/lib/db-ctl-base.c index 3028c09cc..b018bad1d 100644 --- a/lib/db-ctl-base.c +++ b/lib/db-ctl-base.c @@ -1620,6 +1620,15 @@ pre_cmd_show(struct ctl_context *ctx) ovsdb_idl_add_column(ctx->idl, column); } } + if (show->wref_table.table) { + ovsdb_idl_add_table(ctx->idl, show->wref_table.table); + } + if (show->wref_table.name_column) { + ovsdb_idl_add_column(ctx->idl, show->wref_table.name_column); + } + if (show->wref_table.wref_column) { + ovsdb_idl_add_column(ctx->idl, show->wref_table.wref_column); + } } } @@ -1649,6 +1658,39 @@ cmd_show_find_table_by_name(const char *name) return NULL; } +/* Prints table entries that weak reference the 'cur_row'. */ +static void +cmd_show_weak_ref(struct ctl_context *ctx, const struct cmd_show_table *show, + const struct ovsdb_idl_row *cur_row, int level) +{ + const struct ovsdb_idl_row *row_wref; + const struct ovsdb_idl_table_class *table = show->wref_table.table; + const struct ovsdb_idl_column *name_column + = show->wref_table.name_column; + const struct ovsdb_idl_column *wref_column + = show->wref_table.wref_column; + + if (!table || !name_column || !wref_column) { + return; + } + + for (row_wref = ovsdb_idl_first_row(ctx->idl, table); row_wref; + row_wref = ovsdb_idl_next_row(row_wref)) { + const struct ovsdb_datum *wref_datum + = ovsdb_idl_read(row_wref, wref_column); + /* If weak reference refers to the 'cur_row', prints it. */ + if (wref_datum->n + && uuid_equals(&cur_row->uuid, &wref_datum->keys[0].uuid)) { + const struct ovsdb_datum *name_datum + = ovsdb_idl_read(row_wref, name_column); + ds_put_char_multiple(&ctx->output, ' ', (level + 1) * 4); + ds_put_format(&ctx->output, "%s ", table->name); + ovsdb_datum_to_string(name_datum, &name_column->type, &ctx->output); + ds_put_char(&ctx->output, '\n'); + } + } +} + /* 'shown' records the tables that has been displayed by the current * command to avoid duplicated prints. */ @@ -1753,6 +1795,7 @@ cmd_show_row(struct ctl_context *ctx, const struct ovsdb_idl_row *row, ds_put_char(&ctx->output, '\n'); } } + cmd_show_weak_ref(ctx, show, row, level); sset_find_and_delete_assert(shown, show->table->name); } diff --git a/lib/db-ctl-base.h b/lib/db-ctl-base.h index 00e86f8b8..bada320b3 100644 --- a/lib/db-ctl-base.h +++ b/lib/db-ctl-base.h @@ -148,6 +148,17 @@ struct ctl_command *ctl_parse_commands(int argc, char *argv[], struct shash *local_options, size_t *n_commandsp); +/* Sometimes, it is desirable to print the table with weak reference to + * rows in a 'cmd_show_table' table. In that case, the 'weak_ref_table' + * should be used and user must define all variables. */ +struct weak_ref_table { + const struct ovsdb_idl_table_class *table; + const struct ovsdb_idl_column *name_column; + /* This colum must be a weak reference to the owning + * 'struct cmd_show_table''s table row. */ + const struct ovsdb_idl_column *wref_column; +}; + /* This struct is for organizing the 'show' command output where: * * - 'table' is the table to show. @@ -157,11 +168,17 @@ struct ctl_command *ctl_parse_commands(int argc, char *argv[], * * - 'columns[]' allows user to specify the print of additional columns * in 'table'. + * + * - if 'wref_table' is populated, print 'wref_table.name_column' for + * each row in table 'wref_table.table' that has a reference to 'table' + * in 'wref_table.wref_column'. Every field must be populated. + * * */ struct cmd_show_table { const struct ovsdb_idl_table_class *table; const struct ovsdb_idl_column *name_column; const struct ovsdb_idl_column *columns[3]; /* Seems like a good number. */ + const struct weak_ref_table wref_table; }; diff --git a/ovn/utilities/ovn-sbctl.c b/ovn/utilities/ovn-sbctl.c index 06bc0cac0..8887c95c3 100644 --- a/ovn/utilities/ovn-sbctl.c +++ b/ovn/utilities/ovn-sbctl.c @@ -489,15 +489,19 @@ static struct cmd_show_table cmd_show_tables[] = { &sbrec_chassis_col_name, {&sbrec_chassis_col_encaps, NULL, - NULL}}, + NULL}, + {&sbrec_table_port_binding, + &sbrec_port_binding_col_logical_port, + &sbrec_port_binding_col_chassis}}, {&sbrec_table_encap, &sbrec_encap_col_type, {&sbrec_encap_col_ip, &sbrec_encap_col_options, - NULL}}, + NULL}, + {NULL, NULL, NULL}}, - {NULL, NULL, {NULL, NULL, NULL}}, + {NULL, NULL, {NULL, NULL, NULL}, {NULL, NULL, NULL}}, }; static void diff --git a/tests/ovn-sbctl.at b/tests/ovn-sbctl.at index 6bda181eb..16968fd06 100644 --- a/tests/ovn-sbctl.at +++ b/tests/ovn-sbctl.at @@ -48,6 +48,30 @@ AT_CHECK([ovn-sbctl show], [0], [dnl Chassis "ch0" Encap stt ip: "1.2.3.5" + Port_Binding "vif0" +]) + +# adds another 'vif1' +AT_CHECK([ovn-nbctl lport-add br-test vif1]) +AT_CHECK([ovn-nbctl lport-set-macs vif1 f0:ab:cd:ef:01:03]) +AT_CHECK([ovn-sbctl lport-bind vif1 ch0]) + +AT_CHECK([ovn-sbctl show | sed 's/vif[[0-9]]/vif/'], [0], [dnl +Chassis "ch0" + Encap stt + ip: "1.2.3.5" + Port_Binding "vif" + Port_Binding "vif" +]) + +# deletes 'vif1' +AT_CHECK([ovn-nbctl lport-del vif1]) + +AT_CHECK([ovn-sbctl show], [0], [dnl +Chassis "ch0" + Encap stt + ip: "1.2.3.5" + Port_Binding "vif0" ]) uuid=$(ovn-sbctl --columns=_uuid list Chassis ch0 | cut -d ':' -f2 | tr -d ' ') diff --git a/utilities/ovs-vsctl.c b/utilities/ovs-vsctl.c index c3b8a38d7..e28634a07 100644 --- a/utilities/ovs-vsctl.c +++ b/utilities/ovs-vsctl.c @@ -980,45 +980,51 @@ static struct cmd_show_table cmd_show_tables[] = { NULL, {&ovsrec_open_vswitch_col_manager_options, &ovsrec_open_vswitch_col_bridges, - &ovsrec_open_vswitch_col_ovs_version} + &ovsrec_open_vswitch_col_ovs_version}, + {NULL, NULL, NULL} }, {&ovsrec_table_bridge, &ovsrec_bridge_col_name, {&ovsrec_bridge_col_controller, &ovsrec_bridge_col_fail_mode, - &ovsrec_bridge_col_ports} + &ovsrec_bridge_col_ports}, + {NULL, NULL, NULL} }, {&ovsrec_table_port, &ovsrec_port_col_name, {&ovsrec_port_col_tag, &ovsrec_port_col_trunks, - &ovsrec_port_col_interfaces} + &ovsrec_port_col_interfaces}, + {NULL, NULL, NULL} }, {&ovsrec_table_interface, &ovsrec_interface_col_name, {&ovsrec_interface_col_type, &ovsrec_interface_col_options, - &ovsrec_interface_col_error} + &ovsrec_interface_col_error}, + {NULL, NULL, NULL} }, {&ovsrec_table_controller, &ovsrec_controller_col_target, {&ovsrec_controller_col_is_connected, NULL, - NULL} + NULL}, + {NULL, NULL, NULL} }, {&ovsrec_table_manager, &ovsrec_manager_col_target, {&ovsrec_manager_col_is_connected, NULL, - NULL} + NULL}, + {NULL, NULL, NULL} }, - {NULL, NULL, {NULL, NULL, NULL}} + {NULL, NULL, {NULL, NULL, NULL}, {NULL, NULL, NULL}} }; static void diff --git a/vtep/vtep-ctl.c b/vtep/vtep-ctl.c index 37a78a1d1..82b87f4a8 100644 --- a/vtep/vtep-ctl.c +++ b/vtep/vtep-ctl.c @@ -369,38 +369,43 @@ static struct cmd_show_table cmd_show_tables[] = { NULL, {&vteprec_global_col_managers, &vteprec_global_col_switches, - NULL} + NULL}, + {NULL, NULL, NULL} }, {&vteprec_table_manager, &vteprec_manager_col_target, {&vteprec_manager_col_is_connected, NULL, - NULL} + NULL}, + {NULL, NULL, NULL} }, {&vteprec_table_physical_switch, &vteprec_physical_switch_col_name, {&vteprec_physical_switch_col_management_ips, &vteprec_physical_switch_col_tunnel_ips, - &vteprec_physical_switch_col_ports} + &vteprec_physical_switch_col_ports}, + {NULL, NULL, NULL} }, {&vteprec_table_physical_port, &vteprec_physical_port_col_name, {&vteprec_physical_port_col_vlan_bindings, NULL, - NULL} + NULL}, + {NULL, NULL, NULL} }, {&vteprec_table_logical_switch, &vteprec_logical_switch_col_name, {NULL, NULL, - NULL} + NULL}, + {NULL, NULL, NULL} }, - {NULL, NULL, {NULL, NULL, NULL}} + {NULL, NULL, {NULL, NULL, NULL}, {NULL, NULL, NULL}} }; /* vtep-ctl specific context. Inherits the 'struct ctl_context' as base. */ -- 2.20.1