From patchwork Thu Jun 9 07:12:39 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Justin Pettit X-Patchwork-Id: 632654 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from archives.nicira.com (archives.nicira.com [96.126.127.54]) by ozlabs.org (Postfix) with ESMTP id 3rQGkW034zz9t3Z for ; Thu, 9 Jun 2016 17:13:54 +1000 (AEST) Received: from archives.nicira.com (localhost [127.0.0.1]) by archives.nicira.com (Postfix) with ESMTP id B35D410B26; Thu, 9 Jun 2016 00:13:27 -0700 (PDT) X-Original-To: dev@openvswitch.org Delivered-To: dev@openvswitch.org Received: from mx3v3.cudamail.com (mx3.cudamail.com [64.34.241.5]) by archives.nicira.com (Postfix) with ESMTPS id 3866610B1B for ; Thu, 9 Jun 2016 00:13:26 -0700 (PDT) Received: from bar6.cudamail.com (localhost [127.0.0.1]) by mx3v3.cudamail.com (Postfix) with ESMTPS id 835DD1624B3 for ; Thu, 9 Jun 2016 01:13:25 -0600 (MDT) X-ASG-Debug-ID: 1465456404-0b32374c8bae870001-byXFYA Received: from mx1-pf1.cudamail.com ([192.168.24.1]) by bar6.cudamail.com with ESMTP id JC2g2SbIACGs1qbr (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 09 Jun 2016 01:13:24 -0600 (MDT) X-Barracuda-Envelope-From: jpettit@ovn.org X-Barracuda-RBL-Trusted-Forwarder: 192.168.24.1 Received: from unknown (HELO relay3-d.mail.gandi.net) (217.70.183.195) by mx1-pf1.cudamail.com with ESMTPS (DHE-RSA-AES256-SHA encrypted); 9 Jun 2016 07:13:24 -0000 Received-SPF: pass (mx1-pf1.cudamail.com: SPF record at ovn.org designates 217.70.183.195 as permitted sender) X-Barracuda-Apparent-Source-IP: 217.70.183.195 X-Barracuda-RBL-IP: 217.70.183.195 Received: from mfilter27-d.gandi.net (mfilter27-d.gandi.net [217.70.178.155]) by relay3-d.mail.gandi.net (Postfix) with ESMTP id E7814A80C0 for ; Thu, 9 Jun 2016 09:13:22 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at mfilter27-d.gandi.net Received: from relay3-d.mail.gandi.net ([IPv6:::ffff:217.70.183.195]) by mfilter27-d.gandi.net (mfilter27-d.gandi.net [::ffff:10.0.15.180]) (amavisd-new, port 10024) with ESMTP id nF_PbldAWiIg for ; Thu, 9 Jun 2016 09:13:20 +0200 (CEST) X-Originating-IP: 98.234.50.139 Received: from localhost.localdomain (unknown [98.234.50.139]) (Authenticated sender: jpettit@ovn.org) by relay3-d.mail.gandi.net (Postfix) with ESMTPSA id A99B6A80C8 for ; Thu, 9 Jun 2016 09:13:19 +0200 (CEST) X-CudaMail-Envelope-Sender: jpettit@ovn.org From: Justin Pettit To: dev@openvswitch.org X-CudaMail-Whitelist-To: dev@openvswitch.org X-CudaMail-MID: CM-E1-608001143 X-CudaMail-DTE: 060916 X-CudaMail-Originating-IP: 217.70.183.195 Date: Thu, 9 Jun 2016 00:12:39 -0700 X-ASG-Orig-Subj: [##CM-E1-608001143##][PATCH 5/8] ovn-nbctl: Add static route commands. Message-Id: <1465456362-58140-6-git-send-email-jpettit@ovn.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1465456362-58140-1-git-send-email-jpettit@ovn.org> References: <1465456362-58140-1-git-send-email-jpettit@ovn.org> X-Barracuda-Connect: UNKNOWN[192.168.24.1] X-Barracuda-Start-Time: 1465456404 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://web.cudamail.com:443/cgi-mod/mark.cgi X-ASG-Whitelist: Header =?UTF-8?B?eFwtY3VkYW1haWxcLXdoaXRlbGlzdFwtdG8=?= X-Virus-Scanned: by bsmtpd at cudamail.com X-Barracuda-BRTS-Status: 1 Subject: [ovs-dev] [PATCH 5/8] ovn-nbctl: Add static route commands. X-BeenThere: dev@openvswitch.org X-Mailman-Version: 2.1.16 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: dev-bounces@openvswitch.org Sender: "dev" Signed-off-by: Justin Pettit Acked-by: Ryan Moats --- ovn/utilities/ovn-nbctl.8.xml | 26 +++++ ovn/utilities/ovn-nbctl.c | 214 +++++++++++++++++++++++++++++++++++++++++- tests/ovn-nbctl.at | 78 +++++++++++++++ tests/ovn.at | 41 ++------ 4 files changed, 325 insertions(+), 34 deletions(-) diff --git a/ovn/utilities/ovn-nbctl.8.xml b/ovn/utilities/ovn-nbctl.8.xml index c085274..ba6a1ed 100644 --- a/ovn/utilities/ovn-nbctl.8.xml +++ b/ovn/utilities/ovn-nbctl.8.xml @@ -329,7 +329,33 @@ Prints the administrative state of port, either enabled or disabled. + + +

Logical Route Commands

+ +
+
lr-route-add router prefix nexthop [port]
+
+ Adds the specified route to router. prefix + describes the IP prefix for this route. nexthop + specifies the gateway to use for this route. If port + is specified, packets that match this route will be sent out + that port. +
+
lr-route-del router [prefix]
+
+ Deletes routes from router. If only + router is supplied, all the routes from the logical + router are deleted. If prefix is also specified, + then all the routes that match the prefix will be deleted from + the logical router. +
+ +
lr-route-list router
+
+ Lists the routes on router. +

Database Commands

diff --git a/ovn/utilities/ovn-nbctl.c b/ovn/utilities/ovn-nbctl.c index 493f1e8..eeed70f 100644 --- a/ovn/utilities/ovn-nbctl.c +++ b/ovn/utilities/ovn-nbctl.c @@ -350,6 +350,13 @@ Logical router port commands:\n\ lrp-get-enabled PORT get administrative state PORT\n\ ('enabled' or 'disabled')\n\ \n\ +Route commands:\n\ + lr-route-add ROUTER PREFIX NEXTHOP [PORT]\n\ + add a route to ROUTER\n\ + lr-route-del ROUTER [PREFIX]\n\ + remove routes from ROUTER\n\ + lr-route-list ROUTER print routes for ROUTER\n\ +\n\ %s\ \n\ Options:\n\ @@ -1269,6 +1276,82 @@ nbctl_lr_list(struct ctl_context *ctx) free(nodes); } +static void +nbctl_lr_route_add(struct ctl_context *ctx) +{ + const struct nbrec_logical_router *lr; + lr = lr_by_name_or_uuid(ctx, ctx->argv[1], true); + unsigned int plen; + ovs_be32 ipv4; + char *error; + + error = ip_parse_cidr(ctx->argv[2], &ipv4, &plen); + if (!error) { + if (!ip_parse(ctx->argv[3], &ipv4)) { + ctl_fatal("bad IPv4 nexthop argument: %s", ctx->argv[3]); + } + } else { + free(error); + + struct in6_addr ipv6; + error = ipv6_parse_cidr(ctx->argv[2], &ipv6, &plen); + if (!error) { + if (!ipv6_parse(ctx->argv[3], &ipv6)) { + ctl_fatal("bad IPv6 nexthop argument: %s", ctx->argv[3]); + } + } else { + ctl_fatal("bad prefix argument: %s", error); + } + } + + struct nbrec_logical_router_static_route *route; + route = nbrec_logical_router_static_route_insert(ctx->txn); + nbrec_logical_router_static_route_set_ip_prefix(route, ctx->argv[2]); + nbrec_logical_router_static_route_set_nexthop(route, ctx->argv[3]); + if (ctx->argc == 5) { + nbrec_logical_router_static_route_set_output_port(route, ctx->argv[4]); + } + + nbrec_logical_router_verify_static_routes(lr); + struct nbrec_logical_router_static_route **new_routes + = xmalloc(sizeof *new_routes * (lr->n_static_routes + 1)); + memcpy(new_routes, lr->static_routes, + sizeof *new_routes * lr->n_static_routes); + new_routes[lr->n_static_routes] = route; + nbrec_logical_router_set_static_routes(lr, new_routes, + lr->n_static_routes + 1); + free(new_routes); +} + +static void +nbctl_lr_route_del(struct ctl_context *ctx) +{ + const struct nbrec_logical_router *lr; + lr = lr_by_name_or_uuid(ctx, ctx->argv[1], true); + + if (ctx->argc == 2) { + /* If a prefix is not specified, delete all routes. */ + nbrec_logical_router_verify_static_routes(lr); + nbrec_logical_router_set_static_routes(lr, NULL, 0); + return; + } + + for (int i = 0; i < lr->n_static_routes; i++) { + if (!strcmp(lr->static_routes[i]->ip_prefix, ctx->argv[2])) { + struct nbrec_logical_router_static_route **new_routes + = xmemdup(lr->static_routes, + sizeof *new_routes * lr->n_static_routes); + + new_routes[i] = lr->static_routes[lr->n_static_routes - 1]; + nbrec_logical_router_verify_static_routes(lr); + nbrec_logical_router_set_static_routes(lr, new_routes, + lr->n_static_routes - 1); + free(new_routes); + return; + } + } +} + static const struct nbrec_logical_router_port * lrp_by_name_or_uuid(struct ctl_context *ctx, const char *id, bool must_exist) { @@ -1358,9 +1441,9 @@ nbctl_lrp_add(struct ctl_context *ctx) ctl_fatal("%s: invalid mac address.", ctx->argv[3]); } - ovs_be32 ip; + ovs_be32 ipv4; unsigned int plen; - char *error = ip_parse_cidr(ctx->argv[4], &ip, &plen); + char *error = ip_parse_cidr(ctx->argv[4], &ipv4, &plen); if (error) { free(error); struct in6_addr ipv6; @@ -1501,6 +1584,125 @@ nbctl_lrp_get_enabled(struct ctl_context *ctx) *lrp->enabled ? "enabled" : "disabled"); } +struct ipv4_route { + int plen; + ovs_be32 addr; + const struct nbrec_logical_router_static_route *route; +}; + +static int +ipv4_route_cmp(const void *route1_, const void *route2_) +{ + const struct ipv4_route *route1p = route1_; + const struct ipv4_route *route2p = route2_; + + if (route1p->plen != route2p->plen) { + return route1p->plen > route2p->plen ? -1 : 1; + } else if (route1p->addr != route2p->addr) { + return route1p->addr < route2p->addr ? -1 : 1; + } else { + return 0; + } +} + +struct ipv6_route { + int plen; + struct in6_addr addr; + const struct nbrec_logical_router_static_route *route; +}; + +static int +ipv6_route_cmp(const void *route1_, const void *route2_) +{ + const struct ipv6_route *route1p = route1_; + const struct ipv6_route *route2p = route2_; + + if (route1p->plen != route2p->plen) { + return route1p->plen > route2p->plen ? -1 : 1; + } + return memcmp(&route1p->addr, &route2p->addr, sizeof(route1p->addr)); +} + +static void +nbctl_lr_route_list(struct ctl_context *ctx) +{ + const struct nbrec_logical_router *lr; + struct ipv4_route *ipv4_routes; + struct ipv6_route *ipv6_routes; + size_t n_ipv4_routes = 0; + size_t n_ipv6_routes = 0; + + lr = lr_by_name_or_uuid(ctx, ctx->argv[1], true); + + ipv4_routes = xmalloc(sizeof *ipv4_routes * lr->n_static_routes); + ipv6_routes = xmalloc(sizeof *ipv6_routes * lr->n_static_routes); + + for (int i = 0; i < lr->n_static_routes; i++) { + const struct nbrec_logical_router_static_route *route + = lr->static_routes[i]; + unsigned int plen; + ovs_be32 ipv4; + char *error; + + error = ip_parse_cidr(route->ip_prefix, &ipv4, &plen); + if (!error) { + ipv4_routes[n_ipv4_routes].plen = plen; + ipv4_routes[n_ipv4_routes].addr = ipv4; + ipv4_routes[n_ipv4_routes].route = route; + n_ipv4_routes++; + } else { + free(error); + + struct in6_addr ipv6; + if (!ipv6_parse_cidr(route->ip_prefix, &ipv6, &plen)) { + ipv6_routes[n_ipv6_routes].plen = plen; + ipv6_routes[n_ipv6_routes].addr = ipv6; + ipv6_routes[n_ipv6_routes].route = route; + n_ipv6_routes++; + } else { + /* Invalid prefix. */ + free(error); + continue; + } + } + } + + qsort(ipv4_routes, n_ipv4_routes, sizeof *ipv4_routes, ipv4_route_cmp); + qsort(ipv6_routes, n_ipv6_routes, sizeof *ipv6_routes, ipv6_route_cmp); + + if (n_ipv4_routes) { + ds_put_cstr(&ctx->output, "IPv4 Routes\n"); + } + for (int i = 0; i < n_ipv4_routes; i++) { + const struct nbrec_logical_router_static_route *route + = ipv4_routes[i].route; + ds_put_format(&ctx->output, "%25s %25s", route->ip_prefix, + route->nexthop); + if (route->output_port) { + ds_put_format(&ctx->output, " %s", route->output_port); + } + ds_put_char(&ctx->output, '\n'); + } + + if (n_ipv6_routes) { + ds_put_format(&ctx->output, "%sIPv6 Routes\n", + n_ipv4_routes ? "\n" : ""); + } + for (int i = 0; i < n_ipv6_routes; i++) { + const struct nbrec_logical_router_static_route *route + = ipv6_routes[i].route; + ds_put_format(&ctx->output, "%25s %25s", route->ip_prefix, + route->nexthop); + if (route->output_port) { + ds_put_format(&ctx->output, " %s", route->output_port); + } + ds_put_char(&ctx->output, '\n'); + } + + free(ipv4_routes); + free(ipv6_routes); +} + static const struct ctl_table_class tables[] = { {&nbrec_table_logical_switch, {{&nbrec_table_logical_switch, &nbrec_logical_switch_col_name, NULL}, @@ -1796,6 +1998,14 @@ static const struct ctl_command_syntax nbctl_commands[] = { { "lrp-get-enabled", 1, 1, "PORT", NULL, nbctl_lrp_get_enabled, NULL, "", RO }, + /* logical router route commands. */ + { "lr-route-add", 3, 4, "ROUTER PREFIX NEXTHOP [PORT]", NULL, + nbctl_lr_route_add, NULL, "", RW }, + { "lr-route-del", 1, 2, "ROUTER [PREFIX]", NULL, nbctl_lr_route_del, + NULL, "", RW }, + { "lr-route-list", 1, 1, "ROUTER", NULL, nbctl_lr_route_list, NULL, + "", RO }, + {NULL, 0, 0, NULL, NULL, NULL, NULL, "", RO}, }; diff --git a/tests/ovn-nbctl.at b/tests/ovn-nbctl.at index 2e8fc17..73792b3 100644 --- a/tests/ovn-nbctl.at +++ b/tests/ovn-nbctl.at @@ -351,3 +351,81 @@ AT_CHECK([ovn-nbctl lrp-set-enabled lrp0 xyzzy], [1], [], OVN_NBCTL_TEST_STOP AT_CLEANUP + +dnl --------------------------------------------------------------------- + +AT_SETUP([ovn-nbctl - routes]) +OVN_NBCTL_TEST_START + +AT_CHECK([ovn-nbctl lr-add lr0]) + +dnl Check IPv4 routes +AT_CHECK([ovn-nbctl lr-route-add lr0 0.0.0.0/0 192.168.0.1]) +AT_CHECK([ovn-nbctl lr-route-add lr0 10.0.1.1/24 11.0.1.1 lp0]) +AT_CHECK([ovn-nbctl lr-route-add lr0 10.0.0.1/24 11.0.0.1]) + +AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl +IPv4 Routes + 10.0.0.1/24 11.0.0.1 + 10.0.1.1/24 11.0.1.1 lp0 + 0.0.0.0/0 192.168.0.1 +]) + +AT_CHECK([ovn-nbctl lr-route-del lr0 10.0.1.1/24]) + +AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl +IPv4 Routes + 10.0.0.1/24 11.0.0.1 + 0.0.0.0/0 192.168.0.1 +]) + +AT_CHECK([ovn-nbctl lr-route-del lr0]) +AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl +]) + +dnl Check IPv6 routes +AT_CHECK([ovn-nbctl lr-route-add lr0 ::/0 2001:0db8:0:f101::1]) +AT_CHECK([ovn-nbctl lr-route-add lr0 2001:0db8:0::/64 2001:0db8:0:f102::1 lp0]) +AT_CHECK([ovn-nbctl lr-route-add lr0 2001:0db8:1::/64 2001:0db8:0:f103::1]) + +AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl +IPv6 Routes + 2001:0db8:0::/64 2001:0db8:0:f102::1 lp0 + 2001:0db8:1::/64 2001:0db8:0:f103::1 + ::/0 2001:0db8:0:f101::1 +]) + +AT_CHECK([ovn-nbctl lr-route-del lr0 2001:0db8:0::/64]) + +AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl +IPv6 Routes + 2001:0db8:1::/64 2001:0db8:0:f103::1 + ::/0 2001:0db8:0:f101::1 +]) + +AT_CHECK([ovn-nbctl lr-route-del lr0]) +AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl +]) + +dnl Check IPv4 and IPv6 routes +AT_CHECK([ovn-nbctl lr-route-add lr0 0.0.0.0/0 192.168.0.1]) +AT_CHECK([ovn-nbctl lr-route-add lr0 10.0.1.1/24 11.0.1.1 lp0]) +AT_CHECK([ovn-nbctl lr-route-add lr0 10.0.0.1/24 11.0.0.1]) +AT_CHECK([ovn-nbctl lr-route-add lr0 ::/0 2001:0db8:0:f101::1]) +AT_CHECK([ovn-nbctl lr-route-add lr0 2001:0db8:0::/64 2001:0db8:0:f102::1 lp0]) +AT_CHECK([ovn-nbctl lr-route-add lr0 2001:0db8:1::/64 2001:0db8:0:f103::1]) + +AT_CHECK([ovn-nbctl lr-route-list lr0], [0], [dnl +IPv4 Routes + 10.0.0.1/24 11.0.0.1 + 10.0.1.1/24 11.0.1.1 lp0 + 0.0.0.0/0 192.168.0.1 + +IPv6 Routes + 2001:0db8:0::/64 2001:0db8:0:f102::1 lp0 + 2001:0db8:1::/64 2001:0db8:0:f103::1 + ::/0 2001:0db8:0:f101::1 +]) + +OVN_NBCTL_TEST_STOP +AT_CLEANUP diff --git a/tests/ovn.at b/tests/ovn.at index 0b9d3d1..652f0a6 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -2384,17 +2384,9 @@ ovn-nbctl lrp-add R1 R1_R2 00:00:00:02:03:04 20.0.0.1/24 R2_R1 ovn-nbctl lrp-add R2 R2_R1 00:00:00:02:03:05 20.0.0.2/24 R1_R2 #install static routes -ovn-nbctl -- --id=@lrt create Logical_Router_Static_Route \ -ip_prefix=172.16.1.0/24 nexthop=20.0.0.2 -- add Logical_Router \ -R1 static_routes @lrt - -ovn-nbctl -- --id=@lrt create Logical_Router_Static_Route \ -ip_prefix=172.16.2.0/24 nexthop=20.0.0.2 output_port=R1_R2 -- add Logical_Router \ -R1 static_routes @lrt - -ovn-nbctl -- --id=@lrt create Logical_Router_Static_Route \ -ip_prefix=192.168.1.0/24 nexthop=20.0.0.1 -- add Logical_Router \ -R2 static_routes @lrt +ovn-nbctl lr-route-add R1 172.16.1.0/24 20.0.0.2 +ovn-nbctl lr-route-add R2 172.16.2.0/24 20.0.0.2 R1_R2 +ovn-nbctl lr-route-add R2 192.168.1.0/24 20.0.0.1 # Create logical port foo1 in foo ovn-nbctl lport-add foo foo1 \ @@ -2649,29 +2641,14 @@ ovn-nbctl lport-add join r3-join -- set Logical_port r3-join type=router \ options:router-port=R3_join addresses='"00:00:04:01:02:05"' #install static routes -ovn-nbctl -- --id=@lrt create Logical_Router_Static_Route \ -ip_prefix=172.16.1.0/24 nexthop=20.0.0.2 -- add Logical_Router \ -R1 static_routes @lrt +ovn-nbctl lr-route-add R1 172.16.1.0/24 20.0.0.2 +ovn-nbctl lr-route-add R1 10.32.1.0/24 20.0.0.3 -ovn-nbctl -- --id=@lrt create Logical_Router_Static_Route \ -ip_prefix=10.32.1.0/24 nexthop=20.0.0.3 -- add Logical_Router \ -R1 static_routes @lrt +ovn-nbctl lr-route-add R2 192.168.1.0/24 20.0.0.1 +ovn-nbctl lr-route-add R2 10.32.1.0/24 20.0.0.3 -ovn-nbctl -- --id=@lrt create Logical_Router_Static_Route \ -ip_prefix=192.168.1.0/24 nexthop=20.0.0.1 -- add Logical_Router \ -R2 static_routes @lrt - -ovn-nbctl -- --id=@lrt create Logical_Router_Static_Route \ -ip_prefix=10.32.1.0/24 nexthop=20.0.0.3 -- add Logical_Router \ -R2 static_routes @lrt - -ovn-nbctl -- --id=@lrt create Logical_Router_Static_Route \ -ip_prefix=192.168.1.0/24 nexthop=20.0.0.1 -- add Logical_Router \ -R3 static_routes @lrt - -ovn-nbctl -- --id=@lrt create Logical_Router_Static_Route \ -ip_prefix=172.16.1.0/24 nexthop=20.0.0.2 -- add Logical_Router \ -R3 static_routes @lrt +ovn-nbctl lr-route-add R3 192.168.1.0/24 20.0.0.1 +ovn-nbctl lr-route-add R3 172.16.1.0/24 20.0.0.2 # Create logical port foo1 in foo ovn-nbctl lport-add foo foo1 \