Introduce an optional parameter to `ovs-appctl ovs/route/show` for printing non-default routing tables:
ovs-appctl ovs/route/show [table=ID|all] Default usage is unchanged: ovs-appctl ovs/route/show Route Table: Cached: ::1/128 dev lo SRC ::1 Cached: 127.0.0.0/8 dev lo SRC 127.0.0.1 local Cached: 10.7.7.0/24 dev br-phy1 SRC 10.7.7.17 Cached: 0.0.0.0/0 dev eth1 GW 10.0.0.1 SRC 10.0.0.2 New usage with a specific table displays only the routes from that table: ovs-appctl ovs/route/show table=10 Route Table #10: Cached: 10.7.7.0/24 dev br-phy0 SRC 10.7.7.7 Special table 'all' displays all of the routes, the ones which are coming from a non-default table have additional field 'table' displayed: ovs-appctl ovs/route/show table=all Cached: 10.7.7.0/24 dev br-phy1 SRC 10.7.7.17 table 20 Cached: 10.7.7.0/24 dev br-phy0 SRC 10.7.7.7 table 10 Cached: ::1/128 dev lo SRC ::1 Cached: 127.0.0.0/8 dev lo SRC 127.0.0.1 local Cached: 10.7.7.0/24 dev br-phy1 SRC 10.7.7.17 Cached: 0.0.0.0/0 dev eth1 GW 10.0.0.1 SRC 10.0.0.2 Signed-off-by: Dima Chumak <dchu...@nvidia.com> --- NEWS | 2 + lib/ovs-router.c | 110 +++++++++++++++++++++++++++++++++++--------- tests/ovs-router.at | 4 ++ 3 files changed, 93 insertions(+), 23 deletions(-) diff --git a/NEWS b/NEWS index 6e6858c0bca3..5862402c728b 100644 --- a/NEWS +++ b/NEWS @@ -14,6 +14,8 @@ Post-v3.5.0 core file size. - ovs-appctl: * Added JSON output support to the 'ovs/route/show' command. + * 'ovs/route/show': added new option, table=[ID|all], to list routes from + a specific OVS table or all routes from all tables. - SSL/TLS: * Support for deprecated TLSv1 and TLSv1.1 protocols on OpenFlow and database connections is now removed. diff --git a/lib/ovs-router.c b/lib/ovs-router.c index 637920813df6..ec861bf33839 100644 --- a/lib/ovs-router.c +++ b/lib/ovs-router.c @@ -641,22 +641,15 @@ ovs_router_del(struct unixctl_conn *conn, int argc OVS_UNUSED, } static void -ovs_router_show_json(struct json **routes) +ovs_router_show_json(struct json **json_entries, const struct classifier *cls, + uint32_t table) { - int n_rules = classifier_count(&default_cls); - struct json **json_entries = NULL; + int n_rules = classifier_count(cls); + struct ds ds = DS_EMPTY_INITIALIZER; struct ovs_router_entry *rt; - struct ds ds; int i = 0; - if (!n_rules) { - goto out; - } - - json_entries = xmalloc(n_rules * sizeof *json_entries); - ds_init(&ds); - - CLS_FOR_EACH (rt, cr, &default_cls) { + CLS_FOR_EACH (rt, cr, cls) { bool user = rt->priority != rt->plen && !rt->local; uint8_t plen = rt->plen; struct json *json, *nh; @@ -672,6 +665,7 @@ ovs_router_show_json(struct json **routes) plen -= 96; } + json_object_put(json, "table", json_integer_create(table)); json_object_put(json, "user", json_boolean_create(user)); json_object_put(json, "local", json_boolean_create(rt->local)); json_object_put(json, "priority", json_integer_create(rt->priority)); @@ -701,18 +695,23 @@ ovs_router_show_json(struct json **routes) } ds_destroy(&ds); - -out: - *routes = json_array_create(json_entries, i); } static void -ovs_router_show_text(struct ds *ds) +ovs_router_show_text(struct ds *ds, const struct classifier *cls, + uint32_t table, bool show_header) { struct ovs_router_entry *rt; - ds_put_format(ds, "Route Table:\n"); - CLS_FOR_EACH (rt, cr, &default_cls) { + if (show_header) { + if (ovs_router_is_standard_table_id(table)) { + ds_put_format(ds, "Route Table:\n"); + } else { + ds_put_format(ds, "Route Table #%u:\n", table); + } + } + + CLS_FOR_EACH (rt, cr, cls) { uint8_t plen; if (rt->priority == rt->plen || rt->local) { ds_put_format(ds, "Cached: "); @@ -739,6 +738,9 @@ ovs_router_show_text(struct ds *ds) if (rt->local) { ds_put_format(ds, " local"); } + if (!ovs_router_is_standard_table_id(table) && !show_header) { + ds_put_format(ds, " table %u", table); + } ds_put_format(ds, "\n"); } } @@ -747,15 +749,77 @@ static void ovs_router_show(struct unixctl_conn *conn, int argc OVS_UNUSED, const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED) { + struct classifier *cls = &default_cls; + struct ds ds = DS_EMPTY_INITIALIZER; + uint32_t table = CLS_DEFAULT; + + if (argc > 1) { + if (!strcmp(argv[1], "table=all")) { + table = CLS_ALL; + } else if (!ovs_scan(argv[1], "table=%"SCNi32, &table)) { + unixctl_command_reply_error(conn, "Invalid table format"); + return; + } + } + + if (table != CLS_ALL) { + cls = cls_find(table); + if (!cls) { + ds_put_format(&ds, "Invalid param, table '%s' not found", argv[1]); + unixctl_command_reply_error(conn, ds_cstr_ro(&ds)); + ds_destroy(&ds); + return; + } + } + if (unixctl_command_get_output_format(conn) == UNIXCTL_OUTPUT_FMT_JSON) { - struct json *routes; + struct json *routes, **json_entries = NULL; + size_t num_routes = 0; + + if (table == CLS_ALL) { + struct json **cls_entries; + struct clsmap_node *node; + + ovs_mutex_lock(&mutex); + + HMAP_FOR_EACH (node, hash_node, &clsmap) { + num_routes += node->cls.n_rules; + } + + num_routes += default_cls.n_rules; + json_entries = xzalloc(num_routes * sizeof *json_entries); + cls_entries = json_entries; - ovs_router_show_json(&routes); + HMAP_FOR_EACH (node, hash_node, &clsmap) { + ovs_router_show_json(cls_entries, &node->cls, node->table); + cls_entries += node->cls.n_rules; + } + ovs_router_show_json(cls_entries, &default_cls, CLS_DEFAULT); + + ovs_mutex_unlock(&mutex); + } else { + if (cls->n_rules) { + num_routes = cls->n_rules; + json_entries = xmalloc(num_routes * sizeof *json_entries); + ovs_router_show_json(json_entries, cls, table); + } + } + + routes = json_array_create(json_entries, num_routes); unixctl_command_reply_json(conn, routes); } else { - struct ds ds = DS_EMPTY_INITIALIZER; + if (table == CLS_ALL) { + struct clsmap_node *node; - ovs_router_show_text(&ds); + ovs_mutex_lock(&mutex); + HMAP_FOR_EACH (node, hash_node, &clsmap) { + ovs_router_show_text(&ds, &node->cls, node->table, false); + } + ovs_mutex_unlock(&mutex); + ovs_router_show_text(&ds, &default_cls, CLS_DEFAULT, false); + } else { + ovs_router_show_text(&ds, cls, table, true); + } unixctl_command_reply(conn, ds_cstr(&ds)); ds_destroy(&ds); } @@ -895,7 +959,7 @@ ovs_router_init(void) "ip/plen dev [gw] " "[pkt_mark=mark] [src=src_ip]", 2, 5, ovs_router_add, NULL); - unixctl_command_register("ovs/route/show", "", 0, 0, + unixctl_command_register("ovs/route/show", "[table=ID|all]", 0, 1, ovs_router_show, NULL); unixctl_command_register("ovs/route/del", "ip/plen " "[pkt_mark=mark]", 1, 2, ovs_router_del, diff --git a/tests/ovs-router.at b/tests/ovs-router.at index 641b780a582a..dac096cc1aec 100644 --- a/tests/ovs-router.at +++ b/tests/ovs-router.at @@ -39,6 +39,7 @@ AT_CHECK([ovs-appctl --format=json --pretty ovs/route/show], [0], [dnl "prefix": 24, "prefsrc": "2.2.2.2", "priority": 184, + "table": 254, "user": false}, { "dst": "1.1.1.0", @@ -50,6 +51,7 @@ AT_CHECK([ovs-appctl --format=json --pretty ovs/route/show], [0], [dnl "prefix": 24, "prefsrc": "2.2.2.2", "priority": 152, + "table": 254, "user": true}, { "dst": "1.1.2.0", @@ -62,6 +64,7 @@ AT_CHECK([ovs-appctl --format=json --pretty ovs/route/show], [0], [dnl "prefix": 24, "prefsrc": "2.2.2.2", "priority": 152, + "table": 254, "user": true}, { "dst": "2.2.2.3", @@ -73,6 +76,7 @@ AT_CHECK([ovs-appctl --format=json --pretty ovs/route/show], [0], [dnl "prefix": 32, "prefsrc": "2.2.2.2", "priority": 160, + "table": 254, "user": true}]] ]) OVS_VSWITCHD_STOP -- 2.49.0 _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev