From 7127583dc930bda49c8c33de781b9609e4c7381a Mon Sep 17 00:00:00 2001 From: Nirapada Ghosh Date: Fri, 3 Jun 2016 11:48:49 -0700 Subject: [PATCH] ovn-nbctl: Add lrouter and lrport related commands. ovn-nbctl provides a shortcut to perform commands related lswitch, lport and such but it doesn't have similar commands related to logical routers and logical router ports. Also, 'ovn-nbctl show' is supposed to show an overview of database contents, which means it should show the routers as well. "ovn-nbctl show LSWITCH" shows the switch details, similarly "ovn-nbctl show LROUTER" should show the router details too. This patch takes care of all of these. Modifications; 1) ovn-nbctl show -- will now show lrouters as well 2) ovn-nbctl show -- will show the router now New commands added: 3) ovn-nbctl lrouter-add [LROUTER] 4) ovn-nbctl lrouter-del LROUTER 5) ovn-nbctl lrouter-list 6) lrport-add LROUTER LRPORT 7) lrport-del LRPORT 8) lrport-list LROUTER 9) lrport-set-mac-address LRPORT [ADDRESS] 10) lrport-get-mac-address LRPORT 11) lrport-set-enabled LRPORT STATE 12) lrport-get-enabled LRPORT Unit test cases have been added to test all of these modifications and additions. Signed-off-by: Nirapada Ghosh [blp@ovn.org added features to match the lswitch and lport commands] Co-authored-by: Ben Pfaff Signed-off-by: Ben Pfaff --- ovn/utilities/ovn-nbctl.8.xml | 100 +++++++- ovn/utilities/ovn-nbctl.c | 454 +++++++++++++++++++++++++++++++++- tests/ovn-nbctl.at | 143 ++++++++++- 3 files changed, 685 insertions(+), 12 deletions(-) diff --git a/ovn/utilities/ovn-nbctl.8.xml b/ovn/utilities/ovn-nbctl.8.xml index 8375ab7cd..f5920363b 100644 --- a/ovn/utilities/ovn-nbctl.8.xml +++ b/ovn/utilities/ovn-nbctl.8.xml @@ -12,14 +12,50 @@

General Commands

-
show [lswitch]
+
show [lswitch | lrouter]
Prints a brief overview of the database contents. If lswitch is provided, only records related to that - logical switch are shown. + logical switch are shown. If + lrouter is provided, only records related to that + logical router are shown.
+

Logical Router Commands

+ +
+
[--may-exist | --add-duplicate] lrouter-add lrouter
+
+

+ Creates a new logical router named lrouter, which + initially has no router ports. +

+ +

+ The OVN northbound database schema does not require logical router + names to be unique, but the whole point to the names is to provide an + easy way for humans to refer to the routers, making duplicate names + unhelpful. Thus, without any options, this command regards it as an + error if lrouter is a duplicate name. With + --may-exist, adding a duplicate name succeeds but does + not create a new logical router. With --add-duplicate, + the command really creates a new logical router with a duplicate + name. It is an error to specify both options. +

+
+ +
[--if-exists] lrouter-del lrouter
+
+ Deletes lrouter. It is an error if lrouter does + not exist, unless --if-exists is specified. +
+ +
lrouter-list
+
+ Lists all existing logical routers on standard output, one per line. +
+

Logical Switch Commands

@@ -91,7 +127,67 @@ Lists the ACLs on lswitch.
+

Logical Router Port Commands

+
+
[--may-exist] lrport-add lrouter lrport
+
+

+ Creates on lrouter a new logical router port named + lrport. +

+ +

+ It is an error if a logical router port named lrport + already exists, unless --may-exist is specified. + Regardless of --may-exist, it is an error if the + existing router port is in some logical router other than + lrouter. +

+
+ +
[--if-exists] lrport-del lrport
+
+ Deletes lrport. It is an error if lrport does + not exist, unless --if-exists is specified. +
+ +
lrport-list lrouter
+
+ Lists all the logical router ports within lrouter on + standard output, one per line. +
+
lrport-set-mac-address lrport + address...
+
+ Sets the address associated with lrport to + address. address should be either an + Ethernet address or an Ethernet address followed by an IP address + (separated by a space and quoted to form a single command-line + argument). The special form unknown is also valid. +
+ +
lrport-get-mac-address lrport
+
+ Lists the mac address associated with lrport on standard + output. +
+ +
lrport-set-enabled lrport state
+
+ Set the administrative state of lrport, + either enabled or disabled. + When a port is disabled, no traffic is allowed into + or out of the port. +
+ +
lrport-get-enabled lrport
+
+ Prints the administrative state of lrport, + either enabled or disabled. +
+ +

Logical Port Commands

[--may-exist] lport-add lswitch lport
diff --git a/ovn/utilities/ovn-nbctl.c b/ovn/utilities/ovn-nbctl.c index d267829c3..321040e8c 100644 --- a/ovn/utilities/ovn-nbctl.c +++ b/ovn/utilities/ovn-nbctl.c @@ -293,12 +293,18 @@ usage: %s [OPTIONS] COMMAND [ARG...]\n\ General commands:\n\ show print overview of database contents\n\ show LSWITCH print overview of database contents for LSWITCH\n\ + show LROUTER print overview of database contents for LROUTER\n\ \n\ Logical switch commands:\n\ lswitch-add [LSWITCH] create a logical switch named LSWITCH\n\ lswitch-del LSWITCH delete LSWITCH and all its ports\n\ lswitch-list print the names of all logical switches\n\ \n\ +Logical router commands:\n\ + lrouter-add [LROUTER] create a logical router named LROUTER\n\ + lrouter-del LROUTER delete LROUTER and all its ports\n\ + lrouter-list print the names of all logical routers\n\ +\n\ ACL commands:\n\ acl-add LSWITCH DIRECTION PRIORITY MATCH ACTION [log]\n\ add an ACL to LSWITCH\n\ @@ -306,6 +312,19 @@ ACL commands:\n\ remove ACLs from LSWITCH\n\ acl-list LSWITCH print ACLs for LSWITCH\n\ \n\ +Logical router port commands:\n\ + lrport-add LROUTER LRPORT add logical router port LRPORT to LROUTER\n\ + lrport-del LRPORT delete LRPORT from its attached router\n\ + lrport-list LROUTER print the names of all logical ports on LROUTER\n\ + lrport-set-mac-address LRPORT [ADDRESS]\n\ + set MAC address for LRPORT.\n\ + lrport-get-mac-address LRPORT get MAC addresses on LRPORT\n\ + lrport-set-enabled LRPORT STATE\n\ + set administrative state LRPORT\n\ + ('enabled' or 'disabled')\n\ + lrport-get-enabled LRPORT get administrative state LRPORT\n\ + ('enabled' or 'disabled')\n\ +\n\ Logical port commands:\n\ lport-add LSWITCH LPORT add logical port LPORT on LSWITCH\n\ lport-add LSWITCH LPORT PARENT TAG\n\ @@ -352,6 +371,44 @@ Other options:\n\ exit(EXIT_SUCCESS); } + +/* Find an lrouter given its id. */ +static const struct nbrec_logical_router * +lrouter_by_name_or_uuid(struct ctl_context *ctx, const char *id, + bool must_exist) +{ + const struct nbrec_logical_router *lrouter = NULL; + bool is_uuid = false; + struct uuid lrouter_uuid; + + if (uuid_from_string(&lrouter_uuid, id)) { + is_uuid = true; + lrouter = nbrec_logical_router_get_for_uuid(ctx->idl, + &lrouter_uuid); + } + + if (!lrouter) { + const struct nbrec_logical_router *iter; + + NBREC_LOGICAL_ROUTER_FOR_EACH(iter, ctx->idl) { + if (strcmp(iter->name, id)) { + continue; + } + if (lrouter) { + ctl_fatal("Multiple logical routers named '%s'. " + "Use a UUID.", id); + } + lrouter = iter; + } + } + + if (!lrouter && must_exist) { + ctl_fatal("%s: lrouter %s not found", id, is_uuid ? "UUID" : "name"); + } + + return lrouter; +} + static const struct nbrec_logical_switch * lswitch_by_name_or_uuid(struct ctl_context *ctx, const char *id, bool must_exist) @@ -386,6 +443,24 @@ lswitch_by_name_or_uuid(struct ctl_context *ctx, const char *id, return lswitch; } +/* Given pointer to lrouter, this routine prints the lrouter information. */ +static void +print_lrouter(const struct nbrec_logical_router *lrouter, struct ds *s) +{ + ds_put_format(s, " lrouter "UUID_FMT" (%s)\n", + UUID_ARGS(&lrouter->header_.uuid), lrouter->name); + + for (size_t i = 0; i < lrouter->n_ports; i++) { + const struct nbrec_logical_router_port *lrport = lrouter->ports[i]; + ds_put_format(s, " lrport %s\n", lrport->name); + if (lrport->mac) { + ds_put_cstr(s, " mac: "); + ds_put_format(s, "\"%s\"", lrport->mac); + } + ds_put_format(s, "\n"); + } +} + static void print_lswitch(const struct nbrec_logical_switch *lswitch, struct ds *s) { @@ -429,6 +504,93 @@ nbctl_show(struct ctl_context *ctx) print_lswitch(lswitch, &ctx->output); } } + const struct nbrec_logical_router *lrouter; + + if (ctx->argc == 2) { + lrouter = lrouter_by_name_or_uuid(ctx, ctx->argv[1], false); + if (lrouter) { + print_lrouter(lrouter, &ctx->output); + } + } else { + NBREC_LOGICAL_ROUTER_FOR_EACH(lrouter, ctx->idl) { + print_lrouter(lrouter, &ctx->output); + } + } +} + +/* Add an lrouter. */ +static void +nbctl_lrouter_add(struct ctl_context *ctx) +{ + const char *lrouter_name = ctx->argc == 2 ? ctx->argv[1] : NULL; + + bool may_exist = shash_find(&ctx->options, "--may-exist") != NULL; + bool add_duplicate = shash_find(&ctx->options, "--add-duplicate") != NULL; + if (may_exist && add_duplicate) { + ctl_fatal("--may-exist and --add-duplicate may not be used together"); + } + + if (lrouter_name) { + if (!add_duplicate) { + const struct nbrec_logical_router *lrouter; + NBREC_LOGICAL_ROUTER_FOR_EACH (lrouter, ctx->idl) { + if (!strcmp(lrouter->name, lrouter_name)) { + if (may_exist) { + return; + } + ctl_fatal("%s: an lrouter with this name already exists", + lrouter_name); + } + } + } + } else if (may_exist) { + ctl_fatal("--may-exist requires specifying a name"); + } else if (add_duplicate) { + ctl_fatal("--add-duplicate requires specifying a name"); + } + + struct nbrec_logical_router *lrouter; + lrouter = nbrec_logical_router_insert(ctx->txn); + if (lrouter_name) { + nbrec_logical_router_set_name(lrouter, lrouter_name); + } +} + +/* Delete an lrouter. */ +static void +nbctl_lrouter_del(struct ctl_context *ctx) +{ + bool must_exist = !shash_find(&ctx->options, "--if-exists"); + const char *id = ctx->argv[1]; + const struct nbrec_logical_router *lrouter; + + lrouter = lrouter_by_name_or_uuid(ctx, id, must_exist); + if (!lrouter) { + return; + } + + nbrec_logical_router_delete(lrouter); +} + +/* Print list of lrouters. */ +static void +nbctl_lrouter_list(struct ctl_context *ctx) +{ + const struct nbrec_logical_router *lrouter; + struct smap lrouters; + + smap_init(&lrouters); + NBREC_LOGICAL_ROUTER_FOR_EACH (lrouter, ctx->idl) { + smap_add_format(&lrouters, lrouter->name, UUID_FMT " (%s)", + UUID_ARGS(&lrouter->header_.uuid), lrouter->name); + } + const struct smap_node **nodes = smap_sort(&lrouters); + for (size_t i = 0; i < smap_count(&lrouters); i++) { + const struct smap_node *node = nodes[i]; + ds_put_format(&ctx->output, "%s\n", node->value); + } + smap_destroy(&lrouters); + free(nodes); } static void @@ -503,6 +665,37 @@ nbctl_lswitch_list(struct ctl_context *ctx) free(nodes); } +/* Find the lrport given its id. */ +static const struct nbrec_logical_router_port * +lrport_by_name_or_uuid(struct ctl_context *ctx, const char *id, + bool must_exist) +{ + const struct nbrec_logical_router_port *lrport = NULL; + bool is_uuid = false; + struct uuid lrport_uuid; + + if (uuid_from_string(&lrport_uuid, id)) { + is_uuid = true; + lrport = nbrec_logical_router_port_get_for_uuid(ctx->idl, + &lrport_uuid); + } + + if (!lrport) { + NBREC_LOGICAL_ROUTER_PORT_FOR_EACH(lrport, ctx->idl) { + if (!strcmp(lrport->name, id)) { + break; + } + } + } + + if (!lrport && must_exist) { + ctl_fatal("%s: lrport with this %s not found", + id, is_uuid ? "name" : "UUID"); + } + + return lrport; +} + static const struct nbrec_logical_port * lport_by_name_or_uuid(struct ctl_context *ctx, const char *id, bool must_exist) @@ -549,6 +742,25 @@ lport_to_lswitch(const struct ovsdb_idl *idl, lport->name); } +/* Returns the lrouter that contains 'lport'. */ +static const struct nbrec_logical_router * +lrport_to_lrouter(const struct ovsdb_idl *idl, + const struct nbrec_logical_router_port *lrport) +{ + const struct nbrec_logical_router *lrouter; + NBREC_LOGICAL_ROUTER_FOR_EACH (lrouter, idl) { + for (size_t i = 0; i < lrouter->n_ports; i++) { + if (lrouter->ports[i] == lrport) { + return lrouter; + } + } + } + + /* Can't happen because of the database schema */ + ctl_fatal("logical port %s is not part of any logical router", + lrport->name); +} + static const char * lswitch_get_name(const struct nbrec_logical_switch *lswitch, char uuid_s[UUID_LEN + 1], size_t uuid_s_size) @@ -560,6 +772,17 @@ lswitch_get_name(const struct nbrec_logical_switch *lswitch, return uuid_s; } +static const char * +lrouter_get_name(const struct nbrec_logical_router *lrouter, + char uuid_s[UUID_LEN + 1], size_t uuid_s_size) +{ + if (lrouter->name[0]) { + return lrouter->name; + } + snprintf(uuid_s, uuid_s_size, UUID_FMT, UUID_ARGS(&lrouter->header_.uuid)); + return uuid_s; +} + static void nbctl_lport_add(struct ctl_context *ctx) { @@ -646,6 +869,26 @@ nbctl_lport_add(struct ctl_context *ctx) free(new_ports); } +/* Removes lrport 'lrouter->ports[idx]' from lrouter. */ +static void +remove_lrport(const struct nbrec_logical_router *lrouter, size_t idx) +{ + const struct nbrec_logical_router_port *lrport = lrouter->ports[idx]; + + /* First remove 'lrport' from the array of ports. This is what will + * actually cause the logical port to be deleted when the transaction is + * sent to the database server (due to garbage collection). */ + struct nbrec_logical_router_port **new_ports + = xmemdup(lrouter->ports, sizeof *new_ports * lrouter->n_ports); + new_ports[idx] = new_ports[lrouter->n_ports - 1]; + nbrec_logical_router_verify_ports(lrouter); + nbrec_logical_router_set_ports(lrouter, new_ports, lrouter->n_ports - 1); + free(new_ports); + + /* Delete 'lrport' from the IDL. */ + nbrec_logical_router_port_delete(lrport); +} + /* Removes lport 'lswitch->ports[idx]'. */ static void remove_lport(const struct nbrec_logical_switch *lswitch, size_t idx) @@ -742,6 +985,26 @@ nbctl_lport_get_tag(struct ctl_context *ctx) } } +/* Set the MAC address of lrport. */ +static void +nbctl_lrport_set_mac(struct ctl_context *ctx) +{ + struct eth_addr ea; + const char *id = ctx->argv[1]; + const struct nbrec_logical_router_port *lrport; + + lrport = lrport_by_name_or_uuid(ctx, id, true); + + const char *mac = ctx->argc > 2 ? ctx->argv[2] : ""; + if (mac[0] && !ovs_scan(ctx->argv[2], ETH_ADDR_SCAN_FMT, + ETH_ADDR_SCAN_ARGS(ea))) { + ctl_fatal("%s: invalid MAC address format", mac); + return; + } + + nbrec_logical_router_port_set_mac(lrport, mac); +} + static void nbctl_lport_set_addresses(struct ctl_context *ctx) { @@ -768,6 +1031,20 @@ nbctl_lport_set_addresses(struct ctl_context *ctx) (const char **) ctx->argv + 2, ctx->argc - 2); } +/* Following function prints the mac address of the lrport. */ +static void +nbctl_lrport_get_mac(struct ctl_context *ctx) +{ + const char *id = ctx->argv[1]; + const struct nbrec_logical_router_port *lrport; + + lrport = lrport_by_name_or_uuid(ctx, id, true); + if (!lrport) { + return; + } + ds_put_format(&ctx->output, "%s\n", lrport->mac); +} + static void nbctl_lport_get_addresses(struct ctl_context *ctx) { @@ -833,6 +1110,35 @@ nbctl_lport_get_up(struct ctl_context *ctx) "%s\n", (lport->up && *lport->up) ? "up" : "down"); } +static bool +parse_enabled(const char *state) +{ + if (!strcasecmp(state, "enabled")) { + return true; + } else if (!strcasecmp(state, "disabled")) { + return false; + } else { + ctl_fatal("%s: state must be \"enabled\" or \"disabled\"", state); + } +} + +/* Set the lrport admin-enabled state. */ +static void +nbctl_lrport_set_enabled(struct ctl_context *ctx) +{ + const char *id = ctx->argv[1]; + const char *state = ctx->argv[2]; + const struct nbrec_logical_router_port *lrport; + + lrport = lrport_by_name_or_uuid(ctx, id, true); + if (!lrport) { + return; + } + + bool enabled = parse_enabled(state); + nbrec_logical_router_port_set_enabled(lrport, &enabled, 1); +} + static void nbctl_lport_set_enabled(struct ctl_context *ctx) { @@ -841,16 +1147,25 @@ nbctl_lport_set_enabled(struct ctl_context *ctx) const struct nbrec_logical_port *lport; lport = lport_by_name_or_uuid(ctx, id, true); - if (!strcasecmp(state, "enabled")) { - bool enabled = true; - nbrec_logical_port_set_enabled(lport, &enabled, 1); - } else if (!strcasecmp(state, "disabled")) { - bool enabled = false; - nbrec_logical_port_set_enabled(lport, &enabled, 1); - } else { - ctl_fatal("%s: state must be \"enabled\" or \"disabled\"", - state); + bool enabled = parse_enabled(state); + nbrec_logical_port_set_enabled(lport, &enabled, 1); +} + +/* Print admin-enabled state for lrport. */ +static void +nbctl_lrport_get_enabled(struct ctl_context *ctx) +{ + const char *id = ctx->argv[1]; + const struct nbrec_logical_router_port *lrport; + + lrport = lrport_by_name_or_uuid(ctx, id, true); + if (!lrport) { + return; } + + ds_put_format(&ctx->output, "%s\n", + !lrport->enabled || + *lrport->enabled ? "enabled" : "disabled"); } static void @@ -1336,6 +1651,105 @@ nbctl_exit(int status) exit(status); } +/* Print a list of lrports. */ +static void +nbctl_lrport_list(struct ctl_context *ctx) +{ + const char *id = ctx->argv[1]; + const struct nbrec_logical_router *lrouter; + struct smap lports; + size_t i; + + lrouter = lrouter_by_name_or_uuid(ctx, id, true); + + smap_init(&lports); + for (i = 0; i < lrouter->n_ports; i++) { + const struct nbrec_logical_router_port *lport = lrouter->ports[i]; + smap_add_format(&lports, lport->name, UUID_FMT " (%s)", + UUID_ARGS(&lport->header_.uuid), lport->name); + } + const struct smap_node **nodes = smap_sort(&lports); + for (i = 0; i < smap_count(&lports); i++) { + const struct smap_node *node = nodes[i]; + ds_put_format(&ctx->output, "%s\n", node->value); + } + smap_destroy(&lports); + free(nodes); +} + +/* Add an lrport to the lrouter. */ +static void +nbctl_lrport_add(struct ctl_context *ctx) +{ + bool may_exist = shash_find(&ctx->options, "--may-exist") != NULL; + + const struct nbrec_logical_router *lrouter; + lrouter = lrouter_by_name_or_uuid(ctx, ctx->argv[1], true); + + const char *lrport_name = ctx->argv[2]; + const struct nbrec_logical_router_port *lrport; + + lrport = lrport_by_name_or_uuid(ctx, lrport_name, false); + if (lrport) { + if (!may_exist) { + ctl_fatal("%s: an lrport with this name already exists", + lrport_name); + } + + const struct nbrec_logical_router *lr; + lr = lrport_to_lrouter(ctx->idl, lrport); + if (lr != lrouter) { + char uuid_s[UUID_LEN + 1]; + ctl_fatal("%s: lrport already exists but in lrouter %s", + lrport_name, + lrouter_get_name(lr, uuid_s, sizeof uuid_s)); + } + + return; + } + + /* Create the logical router port. */ + lrport = nbrec_logical_router_port_insert(ctx->txn); + nbrec_logical_router_port_set_name(lrport, ctx->argv[2]); + + /* Insert the logical port into the logical router. */ + nbrec_logical_router_verify_ports(lrouter); + struct nbrec_logical_router_port **new_ports = xmalloc(sizeof *new_ports * + (lrouter->n_ports + 1)); + memcpy(new_ports, lrouter->ports, sizeof *new_ports * lrouter->n_ports); + new_ports[lrouter->n_ports] = CONST_CAST( + struct nbrec_logical_router_port *, lrport); + nbrec_logical_router_set_ports(lrouter, new_ports, lrouter->n_ports + 1); + free(new_ports); +} + +/* Deletes an lrport from an lrouter. */ +static void +nbctl_lrport_del(struct ctl_context *ctx) +{ + bool must_exist = !shash_find(&ctx->options, "--if-exists"); + const struct nbrec_logical_router_port *lrport; + + lrport = lrport_by_name_or_uuid(ctx, ctx->argv[1], must_exist); + if (!lrport) { + return; + } + + /* Find the router that contains 'lrport', then delete it. */ + const struct nbrec_logical_router *lrouter; + NBREC_LOGICAL_ROUTER_FOR_EACH (lrouter, ctx->idl) { + for (size_t i = 0; i < lrouter->n_ports; i++) { + if (lrouter->ports[i] == lrport) { + remove_lrport(lrouter, i); + return; + } + } + } + + ctl_fatal("logical router port %s is not part of any logical router", + ctx->argv[1]); +} + static const struct ctl_command_syntax nbctl_commands[] = { { "show", 0, 1, "[LSWITCH]", NULL, nbctl_show, NULL, "", RO }, @@ -1346,6 +1760,13 @@ static const struct ctl_command_syntax nbctl_commands[] = { NULL, "--if-exists", RW }, { "lswitch-list", 0, 0, "", NULL, nbctl_lswitch_list, NULL, "", RO }, + /* lrouter commands. */ + { "lrouter-add", 0, 1, "[LROUTER]", NULL, nbctl_lrouter_add, + NULL, "--may-exist,--add-duplicate", RW }, + { "lrouter-del", 1, 1, "LROUTER", NULL, nbctl_lrouter_del, + NULL, "--if-exists", RW }, + { "lrouter-list", 0, 0, "", NULL, nbctl_lrouter_list, NULL, "", RO }, + /* acl commands. */ { "acl-add", 5, 5, "LSWITCH DIRECTION PRIORITY MATCH ACTION", NULL, nbctl_acl_add, NULL, "--log", RW }, @@ -1353,6 +1774,21 @@ static const struct ctl_command_syntax nbctl_commands[] = { nbctl_acl_del, NULL, "", RW }, { "acl-list", 1, 1, "LSWITCH", NULL, nbctl_acl_list, NULL, "", RO }, + /* lrport commands. */ + { "lrport-add", 2, 2, "LROUTER LRPORT", NULL, nbctl_lrport_add, + NULL, "--may-exist", RW }, + { "lrport-del", 1, 1, "LRPORT", NULL, nbctl_lrport_del, NULL, "", RO }, + { "lrport-list", 1, 1, "LROUTER", NULL, nbctl_lrport_list, NULL, "", RO }, + { "lrport-set-mac-address", 1, 2, "LRPORT [ADDRESS]", NULL, + nbctl_lrport_set_mac, NULL, "", RW }, + { "lrport-get-mac-address", 1, 1, "LRPORT", NULL, + nbctl_lrport_get_mac, NULL, + "", RO }, + { "lrport-set-enabled", 2, 2, "LRPORT STATE", NULL, + nbctl_lrport_set_enabled, NULL, "", RW }, + { "lrport-get-enabled", 1, 1, "LRPORT", NULL, + nbctl_lrport_get_enabled, NULL, "", RO }, + /* lport commands. */ { "lport-add", 2, 4, "LSWITCH LPORT [PARENT] [TAG]", NULL, nbctl_lport_add, NULL, "--may-exist", RW }, diff --git a/tests/ovn-nbctl.at b/tests/ovn-nbctl.at index 47ec1ef4f..faedf25d7 100644 --- a/tests/ovn-nbctl.at +++ b/tests/ovn-nbctl.at @@ -139,7 +139,7 @@ AT_CLEANUP dnl --------------------------------------------------------------------- -AT_SETUP([ovn-nbctl - addresses]) +AT_SETUP([ovn-nbctl - lport addresses]) OVN_NBCTL_TEST_START AT_CHECK([ovn-nbctl lswitch-add ls0]) @@ -231,3 +231,144 @@ from-lport 200 (ip) drop OVN_NBCTL_TEST_STOP AT_CLEANUP + +dnl --------------------------------------------------------------------- + +AT_SETUP([ovn-nbctl - basic lrouter commands]) +OVN_NBCTL_TEST_START + +AT_CHECK([ovn-nbctl lrouter-add lr0]) +AT_CHECK([ovn-nbctl lrouter-list | ${PERL} $srcdir/uuidfilt.pl], [0], [dnl +<0> (lr0) +]) + +AT_CHECK([ovn-nbctl lrouter-add lr1]) +AT_CHECK([ovn-nbctl lrouter-list | ${PERL} $srcdir/uuidfilt.pl], [0], [dnl +<0> (lr0) +<1> (lr1) +]) + +AT_CHECK([ovn-nbctl lrouter-del lr0]) +AT_CHECK([ovn-nbctl lrouter-list | ${PERL} $srcdir/uuidfilt.pl], [0], [dnl +<0> (lr1) +]) + +AT_CHECK([ovn-nbctl show lr0]) +AT_CHECK([ovn-nbctl lrouter-add lr0]) +AT_CHECK([ovn-nbctl show lr0 | ${PERL} $srcdir/uuidfilt.pl], [0], + [ lrouter <0> (lr0) +]) +AT_CHECK([ovn-nbctl lrouter-add lr0], [1], [], + [ovn-nbctl: lr0: an lrouter with this name already exists +]) +AT_CHECK([ovn-nbctl --may-exist lrouter-add lr0]) +AT_CHECK([ovn-nbctl show lr0 | ${PERL} $srcdir/uuidfilt.pl], [0], + [ lrouter <0> (lr0) +]) +AT_CHECK([ovn-nbctl --add-duplicate lrouter-add lr0]) +AT_CHECK([ovn-nbctl --may-exist --add-duplicate lrouter-add lr0], [1], [], + [ovn-nbctl: --may-exist and --add-duplicate may not be used together +]) +AT_CHECK([ovn-nbctl lrouter-del lr0], [1], [], + [ovn-nbctl: Multiple logical routers named 'lr0'. Use a UUID. +]) + +AT_CHECK([ovn-nbctl lrouter-del lr2], [1], [], + [ovn-nbctl: lr2: lrouter name not found +]) +AT_CHECK([ovn-nbctl --if-exists lrouter-del lr2]) + +AT_CHECK([ovn-nbctl lrouter-add]) +AT_CHECK([ovn-nbctl lrouter-add]) +AT_CHECK([ovn-nbctl --add-duplicate lrouter-add], [1], [], + [ovn-nbctl: --add-duplicate requires specifying a name +]) +AT_CHECK([ovn-nbctl --may-exist lrouter-add], [1], [], + [ovn-nbctl: --may-exist requires specifying a name +]) + +OVN_NBCTL_TEST_STOP +AT_CLEANUP + +dnl --------------------------------------------------------------------- + +AT_SETUP([ovn-nbctl - basic lrport commands]) +OVN_NBCTL_TEST_START + +AT_CHECK([ovn-nbctl lrouter-add lr0]) +AT_CHECK([ovn-nbctl lrport-add lr0 lrp0]) +AT_CHECK([ovn-nbctl lrport-add lr0 lrp0], [1], [], + [ovn-nbctl: lrp0: an lrport with this name already exists +]) +AT_CHECK([ovn-nbctl --may-exist lrport-add lr0 lrp0]) +AT_CHECK([ovn-nbctl lrport-list lr0 | ${PERL} $srcdir/uuidfilt.pl], [0], [dnl +<0> (lrp0) +]) + +AT_CHECK([ovn-nbctl lrport-add lr0 lrp1]) +AT_CHECK([ovn-nbctl lrport-list lr0 | ${PERL} $srcdir/uuidfilt.pl], [0], [dnl +<0> (lrp0) +<1> (lrp1) +]) + +AT_CHECK([ovn-nbctl lrouter-add lr1]) +AT_CHECK([ovn-nbctl lrport-add lr0 lrp1], [1], [], + [ovn-nbctl: lrp1: an lrport with this name already exists +]) +AT_CHECK([ovn-nbctl --may-exist lrport-add lr1 lrp1], [1], [], + [ovn-nbctl: lrp1: lrport already exists but in lrouter lr0 +]) + +AT_CHECK([ovn-nbctl lrport-del lrp1]) +AT_CHECK([ovn-nbctl lrport-list lr0 | ${PERL} $srcdir/uuidfilt.pl], [0], [dnl +<0> (lrp0) +]) + +OVN_NBCTL_TEST_STOP +AT_CLEANUP + +dnl --------------------------------------------------------------------- + +AT_SETUP([ovn-nbctl - lrport addresses]) +OVN_NBCTL_TEST_START + +AT_CHECK([ovn-nbctl lrouter-add lr0]) +AT_CHECK([ovn-nbctl lrport-add lr0 lrp0]) +AT_CHECK([ovn-nbctl lrport-get-mac-address lrp0], [0], [ +]) + +AT_CHECK([ovn-nbctl lrport-set-mac-address lrp0 00:11:22:33:44:55]) +AT_CHECK([ovn-nbctl lrport-get-mac-address lrp0], [0], [00:11:22:33:44:55 +]) + +AT_CHECK([ovn-nbctl lrport-set-mac-address lrp0]) +AT_CHECK([ovn-nbctl lrport-get-mac-address lrp0], [0], [ +]) + +OVN_NBCTL_TEST_STOP +AT_CLEANUP + +dnl --------------------------------------------------------------------- + +AT_SETUP([ovn-nbctl - lrport enable and disable]) +OVN_NBCTL_TEST_START + +AT_CHECK([ovn-nbctl lrouter-add lr0]) +AT_CHECK([ovn-nbctl lrport-add lr0 lrp0]) +AT_CHECK([ovn-nbctl lrport-get-enabled lrp0], [0], [enabled +]) + +AT_CHECK([ovn-nbctl lrport-set-enabled lrp0 disabled]) +AT_CHECK([ovn-nbctl lrport-get-enabled lrp0], [0], [disabled +]) + +AT_CHECK([ovn-nbctl lrport-set-enabled lrp0 enabled]) +AT_CHECK([ovn-nbctl lrport-get-enabled lrp0], [0], [enabled +]) + +AT_CHECK([ovn-nbctl lrport-set-enabled lrp0 xyzzy], [1], [], + [ovn-nbctl: xyzzy: state must be "enabled" or "disabled" +]) + +OVN_NBCTL_TEST_STOP +AT_CLEANUP -- 2.39.5