[ovs-dev] [PATCH V4] add lrouter and lrport related commands to ovn-nbctl
nghosh at us.ibm.com
nghosh at us.ibm.com
Fri Apr 22 22:29:02 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.
Signed-off-by: Nirapada Ghosh <nghosh at us.ibm.com>
---
diff --git a/ovn/utilities/ovn-nbctl.8.xml b/ovn/utilities/ovn-nbctl.8.xml
index 3b337dd..a6894e6 100644
--- a/ovn/utilities/ovn-nbctl.8.xml
+++ b/ovn/utilities/ovn-nbctl.8.xml
@@ -12,14 +12,36 @@
<h1>General Commands</h1>
<dl>
- <dt><code>show [<var>lswitch</var>]</code></dt>
+ <dt><code>show [<var>lswitch</var> | <var>lrouter</var>]</code></dt>
<dd>
Prints a brief overview of the database contents. If
<var>lswitch</var> is provided, only records related to that
- logical switch are shown.
+ logical switch are shown. If
+ <var>lrouter</var> is provided, only records related to that
+ logical router are shown.
</dd>
</dl>
+ <h1>Logical Router Commands</h1>
+
+ <dl>
+ <dt><code>lrouter-add</code> [<var>lrouter</var>]</dt> <dd>
+ Creates a new logical lrouter named <var>lrouter</var>. If
+ <var>lrouter</var> is not provided, the lrouter will not have a
+ name so other commands must refer to this router by its UUID.
+ Initially the router will have no ports.
+ </dd>
+
+ <dt><code>lrouter-del</code> <var>lrouter</var></dt>
+ <dd>
+ Deletes <var>lrouter</var>.
+ </dd>
+
+ <dt><code>lrouter-list</code></dt>
+ <dd>
+ Lists all existing logical routers on standard output, one per line.
+ </dd>
+ </dl>
<h1>Logical Switch Commands</h1>
<dl>
@@ -67,7 +89,57 @@
Lists the ACLs on <var>lswitch</var>.
</dd>
</dl>
+ <h1>Logical Router Port Commands</h1>
+ <dl>
+ <dt><code>lrport-add</code> <var>lrouter</var> <var>lrport</var></dt>
+ <dd>
+ Creates on <var>lrouter</var> a new logical router port named
+ <var>lrport</var>.
+ </dd>
+ <dt><code>lrport-del</code> <var>lrport</var></dt>
+ <dd>
+ Deletes <var>lrport</var>.
+ </dd>
+
+ <dt><code>lrport-list</code> <var>lrouter</var></dt>
+ <dd>
+ Lists all the logical router ports within <var>lrouter</var> on
+ standard output, one per line.
+ </dd>
+
+ <dt><code>lrport-set-mac-address</code> <var>lrport</var>
+ <var>address</var>...</dt>
+ <dd>
+ Sets the address associated with <var>lrport</var> to
+ <var>address</var>. <var>address</var> 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 <code>unknown</code> is also valid.
+ </dd>
+
+ <dt><code>lrport-get-mac-address</code> <var>lrport</var></dt>
+ <dd>
+ Lists the mac address associated with <var>lrport</var> on standard
+ output.
+ </dd>
+
+ <dt><code>lrport-set-enabled</code> <var>lrport</var>
+ <var>state</var></dt>
+ <dd>
+ Set the administrative state of <var>lrport</var>,
+ either <code>enabled</code> or <code>disabled</code>.
+ When a port is disabled, no traffic is allowed into
+ or out of the port.
+ </dd>
+
+ <dt><code>lrport-get-enabled</code> <var>lrport</var></dt>
+ <dd>
+ Prints the administrative state of <var>lrport</var>,
+ either <code>enabled</code> or <code>disabled</code>.
+ </dd>
+
+ </dl>
<h1>Logical Port Commands</h1>
<dl>
<dt><code>lport-add</code> <var>lswitch</var> <var>lport</var></dt>
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