[ovs-dev] [PATCH v1] Add logical-router and logical-router-port related commands to ovn-nbctl
nghosh at us.ibm.com
nghosh at us.ibm.com
Sat Apr 9 05:48:33 UTC 2016
This patch introduces the following to ovn-nbctl:
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
diff --git a/ovn/utilities/ovn-nbctl.c b/ovn/utilities/ovn-nbctl.c
index bdad368..ed4916d 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,36 @@ 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 +682,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 +719,28 @@ 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. This won't have a real effect on the
+ * database server (the IDL will suppress it in fact) but it means that it
+ * won't show up when we iterate with NBREC_LOGICAL_ROUTER_PORT_FOR_EACH later. */
+ 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 +796,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 +846,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 +902,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 +996,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 +1042,21 @@ 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 },
More information about the dev
mailing list