From 36f232bca2db8ecee2d337dc176d56ce9490e5c2 Mon Sep 17 00:00:00 2001 From: Venkata Anil Date: Tue, 18 Jul 2017 11:35:45 +0530 Subject: [PATCH] ovn: l3ha, CLI for logical router port gateway chassis This change adds commands to set, get and delete gateway chassis for logical router port. Signed-off-by: Venkata Anil Kommaddi Signed-off-by: Russell Bryant --- ovn/utilities/ovn-nbctl.8.xml | 23 +++++ ovn/utilities/ovn-nbctl.c | 186 ++++++++++++++++++++++++++++++++++ tests/ovn-nbctl.at | 55 ++++++++++ 3 files changed, 264 insertions(+) diff --git a/ovn/utilities/ovn-nbctl.8.xml b/ovn/utilities/ovn-nbctl.8.xml index 15012af6b58..f4fc6cfa689 100644 --- a/ovn/utilities/ovn-nbctl.8.xml +++ b/ovn/utilities/ovn-nbctl.8.xml @@ -389,6 +389,29 @@ Prints the administrative state of port, either enabled or disabled. + +
lrp-set-gateway-chassis port + chassis [priority]
+
+ Set gateway chassis for port. chassis + is the name of the chassis. This creates a gateway chassis entry + in Gateway_Chassis table. It won't check if chassis really exists + in OVN_Southbound database. Priority will be set to 0 + if priority is not provided by user. priority + must be between 0 and 32767, inclusive. +
+
lrp-del-gateway-chassis port + chassis
+
+ Deletes gateway chassis from port. It is an error if + gateway chassis with chassis for port does + not exist. +
+
lrp-get-gateway-chassis port
+
+ Lists all the gateway chassis with priority within port on + standard output, one per line, ordered based on priority. +

Logical Router Static Route Commands

diff --git a/ovn/utilities/ovn-nbctl.c b/ovn/utilities/ovn-nbctl.c index 0488318c41b..ce692acb3fb 100644 --- a/ovn/utilities/ovn-nbctl.c +++ b/ovn/utilities/ovn-nbctl.c @@ -376,6 +376,13 @@ Logical router commands:\n\ Logical router port commands:\n\ lrp-add ROUTER PORT MAC NETWORK... [peer=PEER]\n\ add logical port PORT on ROUTER\n\ + lrp-set-gateway-chassis PORT CHASSIS [PRIORITY]\n\ + set gateway chassis for port PORT\n\ + lrp-del-gateway-chassis PORT CHASSIS\n\ + delete gateway chassis from port PORT\n\ + lrp-get-gateway-chassis PORT\n\ + print the names of all gateway chassis on PORT\n\ + with PRIORITY\n\ lrp-del PORT delete PORT from its attached router\n\ lrp-list ROUTER print the names of all ports on ROUTER\n\ lrp-set-enabled PORT STATE\n\ @@ -2528,6 +2535,178 @@ lr_get_name(const struct nbrec_logical_router *lr, char uuid_s[UUID_LEN + 1], return uuid_s; } +static const struct nbrec_gateway_chassis * +gc_by_name_or_uuid(struct ctl_context *ctx, const char *id, bool must_exist) +{ + const struct nbrec_gateway_chassis *gc = NULL; + + struct uuid gc_uuid; + bool is_uuid = uuid_from_string(&gc_uuid, id); + if (is_uuid) { + gc = nbrec_gateway_chassis_get_for_uuid(ctx->idl, &gc_uuid); + } + + if (!gc) { + NBREC_GATEWAY_CHASSIS_FOR_EACH (gc, ctx->idl) { + if (!strcmp(gc->name, id)) { + break; + } + } + } + + if (!gc && must_exist) { + ctl_fatal("%s: gateway chassis %s not found", id, + is_uuid ? "UUID" : "name"); + } + + return gc; +} + +static void +nbctl_lrp_set_gateway_chassis(struct ctl_context *ctx) +{ + char *gc_name; + int64_t priority = 0; + const char *lrp_name = ctx->argv[1]; + const struct nbrec_logical_router_port *lrp; + lrp = lrp_by_name_or_uuid(ctx, lrp_name, true); + if (!lrp) { + ctl_fatal("router port %s is required", lrp_name); + return; + } + + const char *chassis_name = ctx->argv[2]; + if (ctx->argv[3]) { + priority = parse_priority(ctx->argv[3]); + } + + gc_name = xasprintf("%s-%s", lrp_name, chassis_name); + const struct nbrec_gateway_chassis *existing_gc; + existing_gc = gc_by_name_or_uuid(ctx, gc_name, false); + if (existing_gc) { + nbrec_gateway_chassis_set_priority(existing_gc, priority); + free(gc_name); + return; + } + + /* Create the logical gateway chassis. */ + struct nbrec_gateway_chassis *gc + = nbrec_gateway_chassis_insert(ctx->txn); + nbrec_gateway_chassis_set_name(gc, gc_name); + nbrec_gateway_chassis_set_chassis_name(gc, chassis_name); + nbrec_gateway_chassis_set_priority(gc, priority); + + /* Insert the logical gateway chassis into the logical router port. */ + nbrec_logical_router_port_verify_gateway_chassis(lrp); + struct nbrec_gateway_chassis **new_gc = xmalloc( + sizeof *new_gc * (lrp->n_gateway_chassis + 1)); + nullable_memcpy(new_gc, lrp->gateway_chassis, + sizeof *new_gc * lrp->n_gateway_chassis); + new_gc[lrp->n_gateway_chassis] = gc; + nbrec_logical_router_port_set_gateway_chassis( + lrp, new_gc, lrp->n_gateway_chassis + 1); + free(new_gc); + free(gc_name); +} + +/* Removes logical router port 'lrp->gateway_chassis[idx]'. */ +static void +remove_gc(const struct nbrec_logical_router_port *lrp, size_t idx) +{ + const struct nbrec_gateway_chassis *gc = lrp->gateway_chassis[idx]; + + if (lrp->n_gateway_chassis == 1) { + nbrec_logical_router_port_set_gateway_chassis(lrp, NULL, 0); + } else { + /* First remove 'gc' from the array of gateway_chassis. This is what + * will actually cause the gateway chassis to be deleted when the + * transaction is sent to the database server (due to garbage + * collection). */ + struct nbrec_gateway_chassis **new_gc + = xmemdup(lrp->gateway_chassis, + sizeof *new_gc * lrp->n_gateway_chassis); + new_gc[idx] = new_gc[lrp->n_gateway_chassis - 1]; + nbrec_logical_router_port_verify_gateway_chassis(lrp); + nbrec_logical_router_port_set_gateway_chassis( + lrp, new_gc, lrp->n_gateway_chassis - 1); + free(new_gc); + } + + /* Delete 'gc' from the IDL. This won't have a real effect on + * the database server (the IDL will suppress it in fact) but it + * means that it won't show up when we iterate with + * NBREC_GATEWAY_CHASSIS_FOR_EACH later. */ + nbrec_gateway_chassis_delete(gc); +} + +static void +nbctl_lrp_del_gateway_chassis(struct ctl_context *ctx) +{ + const struct nbrec_logical_router_port *lrp; + lrp = lrp_by_name_or_uuid(ctx, ctx->argv[1], true); + if (!lrp) { + return; + } + /* Find the lrp that contains 'gc', then delete it. */ + const char *chassis_name = ctx->argv[2]; + for (size_t i = 0; i < lrp->n_gateway_chassis; i++) { + if (!strncmp(lrp->gateway_chassis[i]->chassis_name, + chassis_name, + strlen(lrp->gateway_chassis[i]->chassis_name))) { + remove_gc(lrp, i); + return; + } + } + + /* Can't happen because of the database schema. */ + ctl_fatal("chassis %s is not added to logical port %s", + chassis_name, ctx->argv[1]); +} + +/* gateway_chassis ordering + * */ +static int +compare_chassis_prio_(const void *gc1_, const void *gc2_) +{ + const struct nbrec_gateway_chassis *const *gc1p = gc1_; + const struct nbrec_gateway_chassis *const *gc2p = gc2_; + const struct nbrec_gateway_chassis *gc1 = *gc1p; + const struct nbrec_gateway_chassis *gc2 = *gc2p; + + int prio_diff = gc2->priority - gc1->priority; + if (!prio_diff) { + return strcmp(gc2->name, gc1->name); + } + return prio_diff; +} + +/* Print a list of gateway chassis. */ +static void +nbctl_lrp_get_gateway_chassis(struct ctl_context *ctx) +{ + const char *id = ctx->argv[1]; + const struct nbrec_logical_router_port *lrp; + const struct nbrec_gateway_chassis **gcs; + size_t i; + + lrp = lrp_by_name_or_uuid(ctx, id, true); + + gcs = xmalloc(sizeof *gcs * lrp->n_gateway_chassis); + for (i = 0; i < lrp->n_gateway_chassis; i++) { + gcs[i] = lrp->gateway_chassis[i]; + } + + qsort(gcs, lrp->n_gateway_chassis, sizeof *gcs, compare_chassis_prio_); + + for (i = 0; i < lrp->n_gateway_chassis; i++) { + const struct nbrec_gateway_chassis *gc = gcs[i]; + ds_put_format(&ctx->output, "%s %5"PRId64"\n", + gc->name, gc->priority); + } + + free(gcs); +} + static void nbctl_lrp_add(struct ctl_context *ctx) { @@ -3413,6 +3592,13 @@ static const struct ctl_command_syntax nbctl_commands[] = { { "lrp-add", 4, INT_MAX, "ROUTER PORT MAC NETWORK... [COLUMN[:KEY]=VALUE]...", NULL, nbctl_lrp_add, NULL, "--may-exist", RW }, + { "lrp-set-gateway-chassis", 2, 3, + "PORT CHASSIS [PRIORITY]", + NULL, nbctl_lrp_set_gateway_chassis, NULL, "--may-exist", RW }, + { "lrp-del-gateway-chassis", 2, 2, "PORT CHASSIS", NULL, + nbctl_lrp_del_gateway_chassis, NULL, "", RW }, + { "lrp-get-gateway-chassis", 1, 1, "PORT", NULL, + nbctl_lrp_get_gateway_chassis, NULL, "", RO }, { "lrp-del", 1, 1, "PORT", NULL, nbctl_lrp_del, NULL, "--if-exists", RW }, { "lrp-list", 1, 1, "ROUTER", NULL, nbctl_lrp_list, NULL, "", RO }, { "lrp-set-enabled", 2, 2, "PORT STATE", NULL, nbctl_lrp_set_enabled, diff --git a/tests/ovn-nbctl.at b/tests/ovn-nbctl.at index 975d7028798..29496c5c73e 100644 --- a/tests/ovn-nbctl.at +++ b/tests/ovn-nbctl.at @@ -756,6 +756,61 @@ AT_CLEANUP dnl --------------------------------------------------------------------- +AT_SETUP([ovn-nbctl - logical router port gateway chassis]) +OVN_NBCTL_TEST_START +AT_CHECK([ovn-nbctl lr-add lr0]) +AT_CHECK([ovn-nbctl lrp-add lr0 lrp0 00:00:00:01:02:03 192.168.1.1/24]) +AT_CHECK([ovn-nbctl lrp-get-gateway-chassis lrp0], [0], []) + +AT_CHECK([ovn-nbctl lrp-set-gateway-chassis lp0 chassis1], [1], [], +[ovn-nbctl: lp0: port name not found +]) + +AT_CHECK([ovn-nbctl lrp-get-gateway-chassis lp0], [1], [], +[ovn-nbctl: lp0: port name not found +]) + +AT_CHECK([ovn-nbctl lrp-del-gateway-chassis lp0 chassis1], [1], [], +[ovn-nbctl: lp0: port name not found +]) + +AT_CHECK([ovn-nbctl lrp-del-gateway-chassis lrp0 chassis1], [1], [], +[ovn-nbctl: chassis chassis1 is not added to logical port lrp0 +]) +AT_CHECK([ovn-nbctl lrp-set-gateway-chassis lrp0 chassis1]) + +AT_CHECK([ovn-nbctl lrp-get-gateway-chassis lrp0], [0], [dnl +lrp0-chassis1 0 +]) +AT_CHECK([ovn-nbctl lrp-set-gateway-chassis lrp0 chassis1 10]) + +AT_CHECK([ovn-nbctl lrp-get-gateway-chassis lrp0], [0], [dnl +lrp0-chassis1 10 +]) +AT_CHECK([ovn-nbctl lrp-set-gateway-chassis lrp0 chassis1 20]) + +AT_CHECK([ovn-nbctl lrp-get-gateway-chassis lrp0], [0], [dnl +lrp0-chassis1 20 +]) +AT_CHECK([ovn-nbctl lrp-set-gateway-chassis lrp0 chassis2 5]) +AT_CHECK([ovn-nbctl lrp-get-gateway-chassis lrp0], [0], [dnl +lrp0-chassis1 20 +lrp0-chassis2 5 +]) + +AT_CHECK([ovn-nbctl lrp-del-gateway-chassis lrp0 chassis1]) +AT_CHECK([ovn-nbctl lrp-get-gateway-chassis lrp0], [0], [dnl +lrp0-chassis2 5 +]) + +AT_CHECK([ovn-nbctl lrp-del-gateway-chassis lrp0 chassis2]) +AT_CHECK([ovn-nbctl lrp-get-gateway-chassis lrp0]) + +OVN_NBCTL_TEST_STOP +AT_CLEANUP + +dnl --------------------------------------------------------------------- + AT_SETUP([ovn-nbctl - logical router port enable and disable]) OVN_NBCTL_TEST_START