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

nghosh at us.ibm.com nghosh at us.ibm.com
Mon Apr 18 16:55:59 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 router
and logical router port. Also, 'nbctl showi' is supposed to show an
overview of database contents, which means it should show the routers
as well. "show LSWITCH" shows the switch details, similarly "show LROUTER"
should show the router details too. This patch takes care of all of these.
Unit test cases have been added to test all of these modifications and 
additions.

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

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