Add a new command `ovs-appctl ovs/router/rule/show` for printing OVS internal routing rules database:
ovs-appctl ovs/router/rule/show 32763: from 7.7.7.17 lookup 20 32764: from all lookup 15 32765: from 7.7.7.7 lookup 10 The rules are sorted from the highest priority being the first to the lowest being the last one. Signed-off-by: Dima Chumak <dchu...@nvidia.com> --- Documentation/howto/userspace-tunneling.rst | 4 + NEWS | 1 + lib/ovs-router.c | 93 +++++++++++++++++++++ ofproto/ofproto-tnl-unixctl.man | 4 + tests/ovs-router.at | 16 ++++ tests/system-route.at | 80 ++++++++++++++++++ 6 files changed, 198 insertions(+) diff --git a/Documentation/howto/userspace-tunneling.rst b/Documentation/howto/userspace-tunneling.rst index 1dd34cd2f5e4..e443b85e67c9 100644 --- a/Documentation/howto/userspace-tunneling.rst +++ b/Documentation/howto/userspace-tunneling.rst @@ -207,6 +207,10 @@ To see all routes configured:: $ ovs-appctl ovs/route/show [table=ID|all] +To see all router rules configured:: + + $ ovs-appctl ovs/router/rule/show + To delete route:: $ ovs-appctl ovs/route/del <IP address>/<prefix length> diff --git a/NEWS b/NEWS index 97554be8e6b4..ed32c543559d 100644 --- a/NEWS +++ b/NEWS @@ -26,6 +26,7 @@ v3.6.0 - xx xxx xxxx * 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. + * Added a new sub-command, ovs/router/rule/show, to list OVS router rules. - ovs-vsctl: * Now exits with error code 160 (ERROR_BAD_ARGUMENTS) on Windows and 65 (EX_DATAERR) on other platforms if it fails while waiting for diff --git a/lib/ovs-router.c b/lib/ovs-router.c index eaf688467389..6cbe08625f5f 100644 --- a/lib/ovs-router.c +++ b/lib/ovs-router.c @@ -843,6 +843,97 @@ ovs_router_show(struct unixctl_conn *conn, int argc OVS_UNUSED, } } +static void +ovs_router_rules_show_json(struct json *rule_entries) +{ + struct router_rule *rule; + struct ds ds; + + PVECTOR_FOR_EACH (rule, &rules) { + struct json *entry = json_object_create(); + + json_object_put(entry, "priority", json_integer_create(rule->prio)); + json_object_put(entry, "invert", json_boolean_create(rule->invert)); + json_object_put(entry, "src_len", json_integer_create(rule->src_len)); + json_object_put(entry, "lookup", + json_integer_create(rule->lookup_table)); + + if (rule->src_len) { + ds_init(&ds); + ipv6_format_mapped(&rule->from_addr, &ds); + json_object_put_string(entry, "from", ds_cstr_ro(&ds)); + ds_destroy(&ds); + } else { + json_object_put_string(entry, "from", "all"); + } + + json_array_add(rule_entries, entry); + } +} + +static char * +standard_table_name(uint32_t table) +{ + switch (table) { + case CLS_DEFAULT: + return "default"; + case CLS_MAIN: + return "main"; + case CLS_LOCAL: + return "local"; + } + + return NULL; +} + +static void +ovs_router_rules_show_text(struct ds *ds) +{ + struct router_rule *rule; + + PVECTOR_FOR_EACH (rule, &rules) { + ds_put_format(ds, "%u: ", rule->prio); + if (rule->invert) { + ds_put_format(ds, "not "); + } + ds_put_format(ds, "from "); + if (rule->src_len) { + ipv6_format_mapped(&rule->from_addr, ds); + if (!((IN6_IS_ADDR_V4MAPPED(&rule->from_addr) && + rule->src_len == 32) || rule->src_len == 128)) { + ds_put_format(ds, "/%u ", rule->src_len); + } + } else { + ds_put_cstr(ds, "all"); + } + ds_put_format(ds, " "); + if (route_table_is_standard_id(rule->lookup_table)) { + ds_put_format(ds, "lookup %s\n", + standard_table_name(rule->lookup_table)); + } else { + ds_put_format(ds, "lookup %u\n", rule->lookup_table); + } + } +} + +static void +ovs_router_rules_show(struct unixctl_conn *conn, int argc OVS_UNUSED, + const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED) +{ + if (unixctl_command_get_output_format(conn) == UNIXCTL_OUTPUT_FMT_JSON) { + struct json *entries = json_array_create_empty(); + + ovs_router_rules_show_json(entries); + unixctl_command_reply_json(conn, entries); + } else { + struct ds ds = DS_EMPTY_INITIALIZER; + + ovs_router_rules_show_text(&ds); + unixctl_command_reply(conn, ds_cstr(&ds)); + ds_destroy(&ds); + } +} + static void ovs_router_lookup_cmd(struct unixctl_conn *conn, int argc, const char *argv[], void *aux OVS_UNUSED) @@ -1021,6 +1112,8 @@ ovs_router_init(void) unixctl_command_register("ovs/route/lookup", "ip_addr " "[pkt_mark=mark]", 1, 2, ovs_router_lookup_cmd, NULL); + unixctl_command_register("ovs/route/rule/show", "", 0, 0, + ovs_router_rules_show, NULL); ovsthread_once_done(&once); } } diff --git a/ofproto/ofproto-tnl-unixctl.man b/ofproto/ofproto-tnl-unixctl.man index b9e4d99b2bf8..2ee17ddd4742 100644 --- a/ofproto/ofproto-tnl-unixctl.man +++ b/ofproto/ofproto-tnl-unixctl.man @@ -17,6 +17,10 @@ all routing tables is printed. .IP "\fBovs/route/del ip/plen [pkt_mark=mark]\fR" Delete ip/plen route from OVS routing table. . +.IP "\fBovs/route/rule/show\fR" +Print routing rules in OVS. This includes routing rules cached from the system +routing policy database and user configured routing rules. +. .IP "\fBtnl/neigh/show\fR" .IP "\fBtnl/arp/show\fR" OVS builds ARP cache by snooping are messages. This command shows diff --git a/tests/ovs-router.at b/tests/ovs-router.at index dac096cc1aec..450eebb28fb0 100644 --- a/tests/ovs-router.at +++ b/tests/ovs-router.at @@ -229,3 +229,19 @@ User: 2001:db8:babe::/64 dev br0 GW 2001:db8:cafe::2 SRC 2001:db8:cafe::1 OVS_VSWITCHD_STOP AT_CLEANUP + +AT_SETUP([appctl - route/rule/show]) +AT_KEYWORDS([ovs_router]) +OVS_VSWITCHD_START([add-port br0 p1 -- set Interface p1 type=dummy]) +AT_CHECK([ovs-appctl netdev-dummy/ip4addr br0 192.0.2.1/24], [0], [OK +]) + +dnl Check standard rules exist. +AT_CHECK([ovs-appctl ovs/route/rule/show], [0], [dnl +0: from all lookup local +32766: from all lookup main +32767: from all lookup default +]) + +OVS_VSWITCHD_STOP +AT_CLEANUP diff --git a/tests/system-route.at b/tests/system-route.at index 66bfd0e8ed2e..09b2861443cb 100644 --- a/tests/system-route.at +++ b/tests/system-route.at @@ -332,3 +332,83 @@ AT_CHECK([ovstest test-lib-route-table-dump | \ ]) AT_CLEANUP + +dnl Checks that OVS uses routes from non-standard tables when there is a rule +dnl referencing the table. +AT_SETUP([ovs-route - route tables + rules]) +AT_KEYWORDS([route]) +OVS_TRAFFIC_VSWITCHD_START() + +dnl Create tap port. +on_exit 'ip link del p1-route' +AT_CHECK([ip tuntap add name p1-route mode tap]) +AT_CHECK([ip link set p1-route up]) + +dnl Add ip address. +AT_CHECK([ip addr add 10.0.0.17/24 dev p1-route], [0], [stdout]) + +dnl Add routes to a custom routing table with a source match rule and check +dnl that OVS caches them. +AT_CHECK([ip rule add from 10.0.0.1 lookup 42]) +AT_CHECK([ip rule show | grep -q 'from 10.0.0.1 lookup 42']) + +dnl Give the main thread a chance to act. +AT_CHECK([ovs-appctl revalidator/wait]) +dnl Check that the rule is cached in OVS. +AT_CHECK([ovs-appctl ovs/route/rule/show | grep -q 'lookup 42']) +dnl Check that the route cache is unchanged (because the table has not been +dnl created yet). +AT_CHECK([ovs-appctl ovs/route/show table=42], [2], [], [stderr]) +AT_CHECK([tail -2 stderr], [0], [dnl +Invalid param, table 'table=42' not found +ovs-appctl: ovs-vswitchd: server returned an error +]) + +on_exit 'ip route flush table 42' +AT_CHECK([ip route add 10.0.0.18/32 dev p1-route table 42]) +AT_CHECK([ip route add 10.0.0.19/32 dev p1-route table 42]) +AT_CHECK([ip route show table 42 | grep 'p1-route' | grep -q '10.0.0.18']) +AT_CHECK([ip route show table 42 | grep 'p1-route' | grep -q '10.0.0.19']) + +AT_CHECK([ovs-appctl revalidator/wait]) +dnl Check that OVS learn those routes. +AT_CHECK([ovs-appctl ovs/route/show table=42], [0], [dnl +Route Table #42: +Cached: 10.0.0.18/32 dev p1-route SRC 10.0.0.17 +Cached: 10.0.0.19/32 dev p1-route SRC 10.0.0.17 +]) + +dnl Delete a route from the custom table and check that OVS removes the route +dnl from the cache. +AT_CHECK([ip route del 10.0.0.18/32 dev p1-route table 42]) +OVS_WAIT_UNTIL_EQUAL([ovs-appctl ovs/route/show table=42], [dnl +Route Table #42: +Cached: 10.0.0.19/32 dev p1-route SRC 10.0.0.17]) + +dnl Delete the rule and check that the table no longer exists in the cache. +AT_CHECK([ip rule del from 10.0.0.1 lookup 42]) +dnl Give the main thread a chance to act. +AT_CHECK([ovs-appctl revalidator/wait]) +dnl Check that the cache is still the same. +AT_CHECK([ovs-appctl ovs/route/show table=42], [2], [], [stderr]) +AT_CHECK([tail -2 stderr], [0], [dnl +Invalid param, table 'table=42' not found +ovs-appctl: ovs-vswitchd: server returned an error +]) + +dnl Add a custom table and check that OVS ignores it because no rule is +dnl referencing it. +on_exit 'ip route flush table 43' +AT_CHECK([ip route add 10.0.0.18/32 dev p1-route table 43]) +AT_CHECK([ip route show table 43 | grep 'p1-route' | grep -q '10.0.0.18']) + +AT_CHECK([ovs-appctl revalidator/wait]) +dnl Check that the cache is still the same. +AT_CHECK([ovs-appctl ovs/route/show table=43], [2], [], [stderr]) +AT_CHECK([tail -2 stderr], [0], [dnl +Invalid param, table 'table=43' not found +ovs-appctl: ovs-vswitchd: server returned an error +]) + +OVS_TRAFFIC_VSWITCHD_STOP +AT_CLEANUP -- 2.50.1 _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev