[ovs-dev] [PATCH V3] add lrouter and lrport related commands to ovn-nbctl

nghosh at us.ibm.com nghosh at us.ibm.com
Mon Apr 18 17:04:11 UTC 2016


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 <lrouter> -- 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.

Author: Nirapada Ghosh <nghosh at us.ibm.com>
Date: Fri, 8 Apr 2016 18:44:21 -0700
Signed-off-by: Nirapada Ghosh <nghosh at us.ibm.com>

---
diff --git a/ovn/utilities/ovn-nbctl.c b/ovn/utilities/ovn-nbctl.c
index bdad368..6d18005 100644
--- a/ovn/utilities/ovn-nbctl.c
+++ b/ovn/utilities/ovn-nbctl.c
@@ -290,12 +290,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\
@@ -303,6 +309,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\
@@ -349,8 +368,49 @@ Other options:\n\
     exit(EXIT_SUCCESS);
 }
 
+
+/* Following function finds out the lrouter given it's id. */
+static const struct nbrec_logical_router *
+lrouter_by_name_or_uuid(struct ctl_context *ctx, const char *id, bool silent)
+{
+    const struct nbrec_logical_router *lrouter = NULL;
+    bool is_uuid = false;
+    bool duplicate = 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) {
+                VLOG_WARN("There is more than one logical router named '%s'. "
+                        "Use a UUID.", id);
+                lrouter = NULL;
+                duplicate = true;
+                break;
+            }
+            lrouter = iter;
+        }
+    }
+
+    if (!lrouter && !duplicate && !silent) {
+        VLOG_WARN("lrouter not found for %s: '%s'",
+                is_uuid ? "UUID" : "name", id);
+    }
+
+    return lrouter;
+}
 static const struct nbrec_logical_switch *
-lswitch_by_name_or_uuid(struct ctl_context *ctx, const char *id)
+lswitch_by_name_or_uuid(struct ctl_context *ctx, const char *id, bool silent)
 {
     const struct nbrec_logical_switch *lswitch = NULL;
     bool is_uuid = false;
@@ -381,7 +441,7 @@ lswitch_by_name_or_uuid(struct ctl_context *ctx, const char *id)
         }
     }
 
-    if (!lswitch && !duplicate) {
+    if (!lswitch && !duplicate && !silent) {
         VLOG_WARN("lswitch not found for %s: '%s'",
                 is_uuid ? "UUID" : "name", id);
     }
@@ -389,6 +449,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)
 {
@@ -423,7 +501,7 @@ nbctl_show(struct ctl_context *ctx)
     const struct nbrec_logical_switch *lswitch;
 
     if (ctx->argc == 2) {
-        lswitch = lswitch_by_name_or_uuid(ctx, ctx->argv[1]);
+        lswitch = lswitch_by_name_or_uuid(ctx, ctx->argv[1], true);
         if (lswitch) {
             print_lswitch(lswitch, &ctx->output);
         }
@@ -432,6 +510,66 @@ 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], true);
+        if (lrouter) {
+            print_lrouter(lrouter, &ctx->output);
+        }
+    } else {
+        NBREC_LOGICAL_ROUTER_FOR_EACH(lrouter, ctx->idl) {
+            print_lrouter(lrouter, &ctx->output);
+        }
+    }
+}
+
+/* Following function adds a lrouter to NB */
+static void
+nbctl_lrouter_add(struct ctl_context *ctx)
+{
+    struct nbrec_logical_router *lrouter;
+
+    lrouter = nbrec_logical_router_insert(ctx->txn);
+    if (ctx->argc == 2) {
+        nbrec_logical_router_set_name(lrouter, ctx->argv[1]);
+    }
+}
+
+/* Following function deletes a lrouter from NB */
+static void
+nbctl_lrouter_del(struct ctl_context *ctx)
+{
+    const char *id = ctx->argv[1];
+    const struct nbrec_logical_router *lrouter;
+
+    lrouter = lrouter_by_name_or_uuid(ctx, id, false);
+    if (!lrouter) {
+        return;
+    }
+
+    nbrec_logical_router_delete(lrouter);
+}
+
+/* Following function prints list of lrouters in NB */
+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
@@ -451,7 +589,7 @@ nbctl_lswitch_del(struct ctl_context *ctx)
     const char *id = ctx->argv[1];
     const struct nbrec_logical_switch *lswitch;
 
-    lswitch = lswitch_by_name_or_uuid(ctx, id);
+    lswitch = lswitch_by_name_or_uuid(ctx, id, false);
     if (!lswitch) {
         return;
     }
@@ -479,6 +617,37 @@ nbctl_lswitch_list(struct ctl_context *ctx)
     free(nodes);
 }
 
+
+/* Following function finds out the lrport given it's id. */
+static const struct nbrec_logical_router_port *
+lrport_by_name_or_uuid(struct ctl_context *ctx, const char *id)
+{
+    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) {
+        VLOG_WARN("lrport not found for %s: '%s'",
+                is_uuid ? "UUID" : "name", id);
+    }
+
+    return lrport;
+}
+
 static const struct nbrec_logical_port *
 lport_by_name_or_uuid(struct ctl_context *ctx, const char *id)
 {
@@ -514,7 +683,7 @@ nbctl_lport_add(struct ctl_context *ctx)
     const struct nbrec_logical_switch *lswitch;
     int64_t tag;
 
-    lswitch = lswitch_by_name_or_uuid(ctx, ctx->argv[1]);
+    lswitch = lswitch_by_name_or_uuid(ctx, ctx->argv[1], false);
     if (!lswitch) {
         return;
     }
@@ -551,6 +720,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)
@@ -606,7 +795,7 @@ nbctl_lport_list(struct ctl_context *ctx)
     struct smap lports;
     size_t i;
 
-    lswitch = lswitch_by_name_or_uuid(ctx, id);
+    lswitch = lswitch_by_name_or_uuid(ctx, id, false);
     if (!lswitch) {
         return;
     }
@@ -656,6 +845,32 @@ nbctl_lport_get_tag(struct ctl_context *ctx)
     }
 }
 
+/* Following function sets 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);
+    if (!lrport) {
+        return;
+    }
+    if (ctx->argc != 3) {
+        VLOG_ERR("Invalid usage");
+        return;
+    }
+
+    if (strcmp(ctx->argv[2], "unknown")
+        && !ovs_scan(ctx->argv[2], ETH_ADDR_SCAN_FMT,
+                     ETH_ADDR_SCAN_ARGS(ea))) {
+        VLOG_ERR("Invalid MAC address format, See ovn-nb(5)");
+        return;
+    }
+
+    nbrec_logical_router_port_set_mac(lrport, ctx->argv[2]);
+}
 static void
 nbctl_lport_set_addresses(struct ctl_context *ctx)
 {
@@ -686,6 +901,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);
+    if (!lrport) {
+        return;
+    }
+    ds_put_format(&ctx->output, "%s\n", lrport->mac);
+}
+
 static void
 nbctl_lport_get_addresses(struct ctl_context *ctx)
 {
@@ -766,6 +995,29 @@ nbctl_lport_get_up(struct ctl_context *ctx)
                   "%s\n", (lport->up && *lport->up) ? "up" : "down");
 }
 
+/* Following function sets the lrport to admin-enabled. */
+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);
+    if (!lrport) {
+        return;
+    }
+
+    if (!strcasecmp(state, "enabled")) {
+        bool enabled = true;
+        nbrec_logical_router_port_set_enabled(lrport, &enabled, 1);
+    } else if (!strcasecmp(state, "disabled")) {
+        bool enabled = false;
+        nbrec_logical_router_port_set_enabled(lrport, &enabled, 1);
+    } else {
+        VLOG_ERR("Invalid state '%s' provided to lport-set-enabled", state);
+    }
+}
 static void
 nbctl_lport_set_enabled(struct ctl_context *ctx)
 {
@@ -789,6 +1041,22 @@ nbctl_lport_set_enabled(struct ctl_context *ctx)
     }
 }
 
+/* Following function prints admin-enabled state. */
+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);
+    if (!lrport) {
+        return;
+    }
+
+    ds_put_format(&ctx->output, "%s\n",
+                  !lrport->enabled ||
+                  *lrport->enabled ? "enabled" : "disabled");
+}
 static void
 nbctl_lport_get_enabled(struct ctl_context *ctx)
 {
@@ -922,7 +1190,7 @@ nbctl_acl_list(struct ctl_context *ctx)
     const struct nbrec_acl **acls;
     size_t i;
 
-    lswitch = lswitch_by_name_or_uuid(ctx, ctx->argv[1]);
+    lswitch = lswitch_by_name_or_uuid(ctx, ctx->argv[1], false);
     if (!lswitch) {
         return;
     }
@@ -951,7 +1219,7 @@ nbctl_acl_add(struct ctl_context *ctx)
     const char *direction;
     int64_t priority;
 
-    lswitch = lswitch_by_name_or_uuid(ctx, ctx->argv[1]);
+    lswitch = lswitch_by_name_or_uuid(ctx, ctx->argv[1], false);
     if (!lswitch) {
         return;
     }
@@ -1007,7 +1275,7 @@ nbctl_acl_del(struct ctl_context *ctx)
     const char *direction;
     int64_t priority = 0;
 
-    lswitch = lswitch_by_name_or_uuid(ctx, ctx->argv[1]);
+    lswitch = lswitch_by_name_or_uuid(ctx, ctx->argv[1], false);
     if (!lswitch) {
         return;
     }
@@ -1302,6 +1570,92 @@ nbctl_exit(int status)
     exit(status);
 }
 
+/* Following function prints the 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, false);
+    if (!lrouter) {
+        return;
+    }
+
+    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);
+}
+
+/* Following function adds an lrport to the lrouter. */
+static void
+nbctl_lrport_add(struct ctl_context *ctx)
+{
+    struct nbrec_logical_router_port *lport;
+    const struct nbrec_logical_router *lrouter;
+
+    lrouter = lrouter_by_name_or_uuid(ctx, ctx->argv[1], false);
+    if (!lrouter) {
+        return;
+    }
+
+    if (ctx->argc != 3) {
+        VLOG_WARN("Invalid arguments to lrport-add.");
+        return;
+    }
+
+    /* Create the logical router port. */
+    lport = nbrec_logical_router_port_insert(ctx->txn);
+    nbrec_logical_router_port_set_name(lport, 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] = lport;
+    nbrec_logical_router_set_ports(lrouter, new_ports, lrouter->n_ports + 1);
+    free(new_ports);
+}
+
+/* Following function deletes the lrport from lrouter. */
+static void
+nbctl_lrport_del(struct ctl_context *ctx)
+{
+    const struct nbrec_logical_router_port *lrport;
+
+    lrport = lrport_by_name_or_uuid(ctx, ctx->argv[1]);
+    if (!lrport) {
+        return;
+    }
+
+    /* Find the router that contains 'lport', 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;
+            }
+        }
+    }
+
+    VLOG_WARN("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 },
 
@@ -1312,6 +1666,13 @@ static const struct ctl_command_syntax nbctl_commands[] = {
       NULL, "", RW },
     { "lswitch-list", 0, 0, "", NULL, nbctl_lswitch_list, NULL, "", RO },
 
+    /* lrouter commands. */
+    { "lrouter-add", 0, 1, "[LROUTER]", NULL, nbctl_lrouter_add,
+      NULL, "", RW },
+    { "lrouter-del", 1, 1, "LROUTER", NULL, nbctl_lrouter_del,
+      NULL, "", 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 },
@@ -1319,6 +1680,20 @@ 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, 4, "LROUTER LRPORT ", NULL, nbctl_lrport_add,
+      NULL, "", 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, INT_MAX, "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, "", RW },
diff --git a/tests/ovn-nbctl.at b/tests/ovn-nbctl.at
index 85f8974..f4d009b 100644
--- a/tests/ovn-nbctl.at
+++ b/tests/ovn-nbctl.at
@@ -170,3 +170,72 @@ from-lport   200 (ip) drop
 
 OVN_NBCTL_TEST_STOP
 AT_CLEANUP
+
+dnl ---------------------------------------------------------------------
+
+AT_SETUP([ovn-nbctl - new commands ])
+OVN_NBCTL_TEST_START
+dnl create a lswitch
+AT_CHECK([ovn-nbctl lswitch-add ls0])
+dnl create a lrouter
+AT_CHECK([ovn-nbctl lrouter-add lr0])
+dnl show command shows both lswitch and lrouter
+AT_CHECK([ovn-nbctl show | ${PERL} $srcdir/uuidfilt.pl], [0], [dnl
+    lswitch <0> (ls0)
+    lrouter <1> (lr0)
+])
+dnl add another lrouter
+AT_CHECK([ovn-nbctl lrouter-add lr1])
+dnl show <lrouter> to show a specific lrouter
+AT_CHECK([ovn-nbctl show lr0 | ${PERL} $srcdir/uuidfilt.pl], [0], [dnl
+    lrouter <0> (lr0)
+])
+dnl lrouter-list shows all lrouters
+AT_CHECK([ovn-nbctl lrouter-list | ${PERL} $srcdir/uuidfilt.pl], [0], [dnl
+<0> (lr0)
+<1> (lr1)
+])
+dnl delete lrouter and check the list is correct
+AT_CHECK([ovn-nbctl lrouter-del lr1])
+AT_CHECK([ovn-nbctl lrouter-list | ${PERL} $srcdir/uuidfilt.pl], [0], [dnl
+<0> (lr0)
+])
+dnl add two lrport
+AT_CHECK([ovn-nbctl lrport-add lr0 lrport0])
+AT_CHECK([ovn-nbctl lrport-add lr0 lrport1])
+dnl check lrport-list is correct
+AT_CHECK([ovn-nbctl lrport-list lr0 | ${PERL} $srcdir/uuidfilt.pl], [0], [dnl
+<0> (lrport0)
+<1> (lrport1)
+])
+dnl delete lrport
+AT_CHECK([ovn-nbctl lrport-del lrport1])
+dnl verify deletion
+AT_CHECK([ovn-nbctl lrport-list lr0 | ${PERL} $srcdir/uuidfilt.pl], [0], [dnl
+<0> (lrport0)
+])
+dnl check lrport mac is uninitialzed
+AT_CHECK([ovn-nbctl show lr0 | ${PERL} $srcdir/uuidfilt.pl], [0], [dnl
+    lrouter <0> (lr0)
+        lrport lrport0
+            mac: ""
+])
+dnl set lrport mac
+AT_CHECK([ovn-nbctl lrport-set-mac-address lrport0 "aa:bb:cc:dd:ee:ff"])
+dnl get lrport mac
+AT_CHECK([ovn-nbctl lrport-get-mac-address lrport0 | ${PERL} $srcdir/uuidfilt.pl], [0], [dnl
+aa:bb:cc:dd:ee:ff
+])
+dnl get lrport enabled state (default:true)
+AT_CHECK([ovn-nbctl lrport-get-enabled lrport0 | ${PERL} $srcdir/uuidfilt.pl], [0], [dnl
+enabled
+])
+dnl disable admin state of lrport
+AT_CHECK([ovn-nbctl lrport-set-enabled lrport0 disabled])
+dnl verify lrport state
+AT_CHECK([ovn-nbctl lrport-get-enabled lrport0 | ${PERL} $srcdir/uuidfilt.pl], [0], [dnl
+disabled
+])
+
+OVN_NBCTL_TEST_STOP
+AT_CLEANUP




More information about the dev mailing list