Introduce an optional parameter to `ovs-appctl ovs/route/lookup` for matching on source IP address.
Signed-off-by: Dima Chumak <dchu...@nvidia.com> --- Documentation/howto/userspace-tunneling.rst | 2 +- NEWS | 2 + lib/ovs-router.c | 47 ++++++++++++++---- ofproto/ofproto-tnl-unixctl.man | 5 ++ tests/system-route.at | 54 +++++++++++++++++++++ 5 files changed, 99 insertions(+), 11 deletions(-) diff --git a/Documentation/howto/userspace-tunneling.rst b/Documentation/howto/userspace-tunneling.rst index 1c7e551e0726..5bebbce69e4a 100644 --- a/Documentation/howto/userspace-tunneling.rst +++ b/Documentation/howto/userspace-tunneling.rst @@ -217,7 +217,7 @@ To delete route:: To look up and display the route for a destination:: - $ ovs-appctl ovs/route/lookup <IP address> + $ ovs-appctl ovs/route/lookup <IP address> [src=IP] ARP ~~~ diff --git a/NEWS b/NEWS index c8f4592a6e2f..a58baa0a8365 100644 --- a/NEWS +++ b/NEWS @@ -29,6 +29,8 @@ v3.6.0 - xx xxx xxxx * Added a new sub-command, ovs/router/rule/show, to list OVS router rules. * 'ovs/route/add' and 'ovs/route/del': added new option, table=ID, to add/delete a route from a specific OVS table. + * 'ovs/route/lookup': added new option, src=IP, to perform lookup with + a specific source IP address. - 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 ba4c43ab1d2e..a3df5c6fc2cc 100644 --- a/lib/ovs-router.c +++ b/lib/ovs-router.c @@ -978,30 +978,57 @@ static void ovs_router_lookup_cmd(struct unixctl_conn *conn, int argc, const char *argv[], void *aux OVS_UNUSED) { - struct in6_addr gw, src = in6addr_any; + struct in6_addr gw, src6 = in6addr_any; + char src6_s[IPV6_SCAN_LEN + 1]; char iface[IFNAMSIZ]; struct in6_addr ip6; unsigned int plen; uint32_t mark = 0; + ovs_be32 src = 0; + bool is_ipv6; ovs_be32 ip; + int i; if (scan_ipv4_route(argv[1], &ip, &plen) && plen == 32) { in6_addr_set_mapped_ipv4(&ip6, ip); - } else if (!(scan_ipv6_route(argv[1], &ip6, &plen) && plen == 128)) { - unixctl_command_reply_error(conn, "Invalid parameters"); + is_ipv6 = false; + } else if (scan_ipv6_route(argv[1], &ip6, &plen) && plen == 128) { + is_ipv6 = true; + } else { + unixctl_command_reply_error(conn, "Invalid 'ip/plen' parameter"); return; } - if (argc > 2) { - if (!ovs_scan(argv[2], "pkt_mark=%"SCNi32, &mark)) { - unixctl_command_reply_error(conn, "Invalid pkt_mark"); - return; + + /* Parse optional parameters. */ + for (i = 2; i < argc; i++) { + if (ovs_scan(argv[i], "pkt_mark=%"SCNi32, &mark)) { + continue; + } + + if (is_ipv6) { + if (ovs_scan(argv[i], "src="IPV6_SCAN_FMT, src6_s) && + ipv6_parse(src6_s, &src6)) { + continue; + } + } else { + if (ovs_scan(argv[i], "src="IP_SCAN_FMT, IP_SCAN_ARGS(&src))) { + continue; + } } + + unixctl_command_reply_error(conn, "Invalid pkt_mark or src"); + return; + } + + if (src) { + in6_addr_set_mapped_ipv4(&src6, src); } - if (ovs_router_lookup(mark, &ip6, iface, &src, &gw)) { + + if (ovs_router_lookup(mark, &ip6, iface, &src6, &gw)) { struct ds ds = DS_EMPTY_INITIALIZER; ds_put_format(&ds, "src "); - ipv6_format_mapped(&src, &ds); + ipv6_format_mapped(&src6, &ds); ds_put_format(&ds, "\ngateway "); ipv6_format_mapped(&gw, &ds); ds_put_format(&ds, "\ndev %s\n", iface); @@ -1150,7 +1177,7 @@ ovs_router_init(void) "[pkt_mark=mark] [table=id]", 1, 3, ovs_router_del, NULL); unixctl_command_register("ovs/route/lookup", "ip_addr " - "[pkt_mark=mark]", 1, 2, + "[pkt_mark=mark] [src=src_ip]", 1, 3, ovs_router_lookup_cmd, NULL); unixctl_command_register("ovs/route/rule/show", "", 0, 0, ovs_router_rules_show, NULL); diff --git a/ofproto/ofproto-tnl-unixctl.man b/ofproto/ofproto-tnl-unixctl.man index 654f405109e6..8e48c0e809ac 100644 --- a/ofproto/ofproto-tnl-unixctl.man +++ b/ofproto/ofproto-tnl-unixctl.man @@ -21,6 +21,11 @@ Delete ip/plen route from OVS routing table. The standard routing table is used by default, or a specific custom table when ID is provided via \fItable\fR parameter. . +.IP "\fBovs/route/lookup \fIip_addr\fB [pkt_mark=\fImark\fB] [src=\fIIP\fB]\fR" +Perform route lookup for specified destination IP address in OVS routing tables +and print the matching route information. The lookup may be more selective when +additional parameters are used: \fIpkt_mark\fR and \fIsrc\fR. +. .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. diff --git a/tests/system-route.at b/tests/system-route.at index 09b2861443cb..7efb50cfbc23 100644 --- a/tests/system-route.at +++ b/tests/system-route.at @@ -412,3 +412,57 @@ ovs-appctl: ovs-vswitchd: server returned an error OVS_TRAFFIC_VSWITCHD_STOP AT_CLEANUP + +dnl Checks that OVS performs route lookup according to rules with src match. +AT_SETUP([ovs-route - route lookup + rules]) +AT_KEYWORDS([route]) +OVS_TRAFFIC_VSWITCHD_START() + +dnl Create tap ports. +on_exit 'ip link del p1-route' +on_exit 'ip link del p2-route' +AT_CHECK([ip tuntap add name p1-route mode tap]) +AT_CHECK([ip tuntap add name p2-route mode tap]) +AT_CHECK([ip link set p1-route up]) +AT_CHECK([ip link set p2-route up]) + +dnl Add ip addresses, they need to be from same subnet so that the main router +dnl table in OVS contains only one of the routes. +AT_CHECK([ip addr add 10.0.0.11/24 dev p1-route], [0], [stdout]) +AT_CHECK([ip addr add 10.0.0.12/24 dev p2-route], [0], [stdout]) +dnl Give the main thread a chance to act. +AT_CHECK([ovs-appctl revalidator/wait]) +dnl Check that OVS learn only one of the routes to the subnet. +AT_CHECK([test `ovs-appctl ovs/route/show | grep -F '10.0.0.0/24' | grep -c 'p1-route'` -eq 0]) +AT_CHECK([ovs-appctl ovs/route/show | grep -F '10.0.0.0/24' | grep -q 'p2-route']) +dnl Check that OVS lookup returns p2-route even for srouce IP of p1-route +dnl internface. +AT_CHECK([ovs-appctl ovs/route/lookup 10.0.0.10 src=10.0.0.11], [0], [src 10.0.0.11 +gateway :: +dev p2-route +]) + +dnl Add rule to use a custom routing table for source IP of p1-route. +on_exit 'ip route flush table 42' +AT_CHECK([ip route add 10.0.0.0/24 dev p1-route table 42]) +AT_CHECK([ip route show table 42 | grep 'p1-route' | grep -Fq '10.0.0.0/24']) +on_exit 'ip rule del from 10.0.0.11 lookup 42' +AT_CHECK([ip rule add from 10.0.0.11 lookup 42]) +AT_CHECK([ip rule show | grep -q 'from 10.0.0.11 lookup 42']) +dnl Give the main thread a chance to act. +AT_CHECK([ovs-appctl revalidator/wait]) +dnl Check that OVS uses custom table for lookup with source IP of p1-route +dnl internface and returns the correct p1-route. +AT_CHECK([ovs-appctl ovs/route/lookup 10.0.0.10 src=10.0.0.11], [0], [src 10.0.0.11 +gateway :: +dev p1-route +]) +dnl Check that OVS uses main table for lookup with other source IP that doesn't +dnl match the rule. +AT_CHECK([ovs-appctl ovs/route/lookup 10.0.0.10 src=10.0.0.12], [0], [src 10.0.0.12 +gateway :: +dev p2-route +]) + +OVS_TRAFFIC_VSWITCHD_STOP +AT_CLEANUP -- 2.50.1 _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev