Just to clarify: 1) Most of these commands can be achieved through other ovn-nbctl commands [e.g "ovn-nbctl create Logical_router .." will do the same thing as what "ovn-nbctl lrouter-add" does. But the same is true for other existing commands like "ovn-nbctl lport-add". These commands are added as "shortcuts" to achieve the same thing as what the longer version of the commands do. 2) Commands like "set-enabled" or "get-enabled" on a logical router port are added just to add a shortcut to be able to get/set the field in database, such commands are added for all the fields in that table as a matter of fact. They were not added with some specific requirement in mind. 3) I am working on adding some test cases for the commands I added, will submit it as soon as they are ready.
Thanks, Nirapada "dev" <dev-boun...@openvswitch.org> wrote on 04/08/2016 10:48:33 PM: > From: Nirapada Ghosh/San Jose/IBM@IBMUS > To: dev@openvswitch.org > Date: 04/08/2016 10:48 PM > Subject: [ovs-dev] [PATCH v1] Add logical-router and logical-router- > port related commands to ovn-nbctl > Sent by: "dev" <dev-boun...@openvswitch.org> > > 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 forLSWITCH\n\ > + show LROUTER print overview of database contents forLROUTER\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 }, > > _______________________________________________ > dev mailing list > dev@openvswitch.org > http://openvswitch.org/mailman/listinfo/dev _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev