On 7/23/25 3:12 PM, Dima Chumak via dev wrote: > Add a new command `ovs-appctl ovs/router/rule/show` for printing OVS > internal routing rules database: > > ovs-appctl ovs/router/rule/show
The 'ovs/router' prefix is mentioned in many places in this patch, while it should be 'ovs/route'. > 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); PRIu32 > + 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); PRIu8 > + } > + } 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); PRIu32 > + } > + } > +} > + > +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. It's not 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 It feels like this system test doesn't belong to this patch. It should be in patch 3, but we had no commands available there, so it may be better to split it into its own patch. _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev