2 * Licensed under the Apache License, Version 2.0 (the "License");
3 * you may not use this file except in compliance with the License.
4 * You may obtain a copy of the License at:
6 * http://www.apache.org/licenses/LICENSE-2.0
8 * Unless required by applicable law or agreed to in writing, software
9 * distributed under the License is distributed on an "AS IS" BASIS,
10 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 * See the License for the specific language governing permissions and
12 * limitations under the License.
22 #include "command-line.h"
23 #include "db-ctl-base.h"
25 #include "fatal-signal.h"
27 #include "ovn/lib/ovn-nb-idl.h"
29 #include "poll-loop.h"
33 #include "stream-ssl.h"
38 #include "openvswitch/vlog.h"
40 VLOG_DEFINE_THIS_MODULE(nbctl);
42 /* --db: The database server to contact. */
43 static const char *db;
45 /* --oneline: Write each command's output as a single line? */
48 /* --dry-run: Do not commit any changes. */
51 /* --timeout: Time to wait for a connection to 'db'. */
54 /* Format for table output. */
55 static struct table_style table_style = TABLE_STYLE_DEFAULT;
57 /* The IDL we're using and the current transaction, if any.
58 * This is for use by nbctl_exit() only, to allow it to clean up.
59 * Other code should use its context arguments. */
60 static struct ovsdb_idl *the_idl;
61 static struct ovsdb_idl_txn *the_idl_txn;
62 OVS_NO_RETURN static void nbctl_exit(int status);
64 static void nbctl_cmd_init(void);
65 OVS_NO_RETURN static void usage(void);
66 static void parse_options(int argc, char *argv[], struct shash *local_options);
67 static const char *nbctl_default_db(void);
68 static void run_prerequisites(struct ctl_command[], size_t n_commands,
70 static bool do_nbctl(const char *args, struct ctl_command *, size_t n,
74 main(int argc, char *argv[])
76 struct ovsdb_idl *idl;
77 struct ctl_command *commands;
78 struct shash local_options;
83 set_program_name(argv[0]);
84 fatal_ignore_sigpipe();
85 vlog_set_levels(NULL, VLF_CONSOLE, VLL_WARN);
86 vlog_set_levels_from_string_assert("reconnect:warn");
91 /* Log our arguments. This is often valuable for debugging systems. */
92 args = process_escape_args(argv);
93 VLOG(ctl_might_write_to_db(argv) ? VLL_INFO : VLL_DBG,
94 "Called as %s", args);
96 /* Parse command line. */
97 shash_init(&local_options);
98 parse_options(argc, argv, &local_options);
99 commands = ctl_parse_commands(argc - optind, argv + optind, &local_options,
106 /* Initialize IDL. */
107 idl = the_idl = ovsdb_idl_create(db, &nbrec_idl_class, true, false);
108 run_prerequisites(commands, n_commands, idl);
110 /* Execute the commands.
112 * 'seqno' is the database sequence number for which we last tried to
113 * execute our transaction. There's no point in trying to commit more than
114 * once for any given sequence number, because if the transaction fails
115 * it's because the database changed and we need to obtain an up-to-date
116 * view of the database before we try the transaction again. */
117 seqno = ovsdb_idl_get_seqno(idl);
120 if (!ovsdb_idl_is_alive(idl)) {
121 int retval = ovsdb_idl_get_last_error(idl);
122 ctl_fatal("%s: database connection failed (%s)",
123 db, ovs_retval_to_string(retval));
126 if (seqno != ovsdb_idl_get_seqno(idl)) {
127 seqno = ovsdb_idl_get_seqno(idl);
128 if (do_nbctl(args, commands, n_commands, idl)) {
134 if (seqno == ovsdb_idl_get_seqno(idl)) {
142 nbctl_default_db(void)
146 def = getenv("OVN_NB_DB");
148 def = xasprintf("unix:%s/ovnnb_db.sock", ovs_rundir());
155 parse_options(int argc, char *argv[], struct shash *local_options)
158 OPT_DB = UCHAR_MAX + 1,
168 static const struct option global_long_options[] = {
169 {"db", required_argument, NULL, OPT_DB},
170 {"no-syslog", no_argument, NULL, OPT_NO_SYSLOG},
171 {"dry-run", no_argument, NULL, OPT_DRY_RUN},
172 {"oneline", no_argument, NULL, OPT_ONELINE},
173 {"timeout", required_argument, NULL, 't'},
174 {"help", no_argument, NULL, 'h'},
175 {"commands", no_argument, NULL, OPT_COMMANDS},
176 {"options", no_argument, NULL, OPT_OPTIONS},
177 {"version", no_argument, NULL, 'V'},
179 STREAM_SSL_LONG_OPTIONS,
183 const int n_global_long_options = ARRAY_SIZE(global_long_options) - 1;
184 char *tmp, *short_options;
186 struct option *options;
187 size_t allocated_options;
191 tmp = ovs_cmdl_long_options_to_short_options(global_long_options);
192 short_options = xasprintf("+%s", tmp);
195 /* We want to parse both global and command-specific options here, but
196 * getopt_long() isn't too convenient for the job. We copy our global
197 * options into a dynamic array, then append all of the command-specific
199 options = xmemdup(global_long_options, sizeof global_long_options);
200 allocated_options = ARRAY_SIZE(global_long_options);
201 n_options = n_global_long_options;
202 ctl_add_cmd_options(&options, &n_options, &allocated_options, OPT_LOCAL);
203 table_style.format = TF_LIST;
209 c = getopt_long(argc, argv, short_options, options, &idx);
224 vlog_set_levels(&this_module, VLF_SYSLOG, VLL_WARN);
232 if (shash_find(local_options, options[idx].name)) {
233 ctl_fatal("'%s' option specified multiple times",
236 shash_add_nocopy(local_options,
237 xasprintf("--%s", options[idx].name),
238 optarg ? xstrdup(optarg) : NULL);
246 ctl_print_commands();
249 ctl_print_options(global_long_options);
252 ovs_print_version(0, 0);
253 printf("DB Schema %s\n", nbrec_get_db_version());
257 timeout = strtoul(optarg, NULL, 10);
259 ctl_fatal("value %s on -t or --timeout is invalid", optarg);
264 TABLE_OPTION_HANDLERS(&table_style)
265 STREAM_SSL_OPTION_HANDLERS
277 db = nbctl_default_db();
280 for (i = n_global_long_options; options[i].name; i++) {
281 free(CONST_CAST(char *, options[i].name));
290 %s: OVN northbound DB management utility\n\
291 usage: %s [OPTIONS] COMMAND [ARG...]\n\
294 show print overview of database contents\n\
295 show LSWITCH print overview of database contents for LSWITCH\n\
296 show ROUTER print overview of database contents for ROUTER\n\
298 Logical switch commands:\n\
299 lswitch-add [LSWITCH] create a logical switch named LSWITCH\n\
300 lswitch-del LSWITCH delete LSWITCH and all its ports\n\
301 lswitch-list print the names of all logical switches\n\
304 acl-add LSWITCH DIRECTION PRIORITY MATCH ACTION [log]\n\
305 add an ACL to LSWITCH\n\
306 acl-del LSWITCH [DIRECTION [PRIORITY MATCH]]\n\
307 remove ACLs from LSWITCH\n\
308 acl-list LSWITCH print ACLs for LSWITCH\n\
310 Logical switch port commands:\n\
311 lsp-add LSWITCH PORT add logical port PORT on LSWITCH\n\
312 lsp-add LSWITCH PORT PARENT TAG\n\
313 add logical port PORT on LSWITCH with PARENT\n\
315 lsp-del PORT delete PORT from its attached switch\n\
316 lsp-list LSWITCH print the names of all logical ports on LSWITCH\n\
317 lsp-get-parent PORT get the parent of PORT if set\n\
318 lsp-get-tag PORT get the PORT's tag if set\n\
319 lsp-set-addresses PORT [ADDRESS]...\n\
320 set MAC or MAC+IP addresses for PORT.\n\
321 lsp-get-addresses PORT get a list of MAC addresses on PORT\n\
322 lsp-set-port-security PORT [ADDRS]...\n\
323 set port security addresses for PORT.\n\
324 lsp-get-port-security PORT get PORT's port security addresses\n\
325 lsp-get-up PORT get state of PORT ('up' or 'down')\n\
326 lsp-set-enabled PORT STATE\n\
327 set administrative state PORT\n\
328 ('enabled' or 'disabled')\n\
329 lsp-get-enabled PORT get administrative state PORT\n\
330 ('enabled' or 'disabled')\n\
331 lsp-set-type PORT TYPE set the type for PORT\n\
332 lsp-get-type PORT get the type for PORT\n\
333 lsp-set-options PORT KEY=VALUE [KEY=VALUE]...\n\
334 set options related to the type of PORT\n\
335 lsp-get-options PORT get the type specific options for PORT\n\
337 Logical router commands:\n\
338 lr-add [ROUTER] create a logical router named ROUTER\n\
339 lr-del ROUTER delete ROUTER and all its ports\n\
340 lr-list print the names of all logical routers\n\
342 Logical router port commands:\n\
343 lrp-add ROUTER PORT MAC NETWORK [PEER]\n\
344 add logical port PORT on ROUTER\n\
345 lrp-del PORT delete PORT from its attached router\n\
346 lrp-list ROUTER print the names of all ports on ROUTER\n\
347 lrp-set-enabled PORT STATE\n\
348 set administrative state PORT\n\
349 ('enabled' or 'disabled')\n\
350 lrp-get-enabled PORT get administrative state PORT\n\
351 ('enabled' or 'disabled')\n\
354 lr-route-add ROUTER PREFIX NEXTHOP [PORT]\n\
355 add a route to ROUTER\n\
356 lr-route-del ROUTER [PREFIX]\n\
357 remove routes from ROUTER\n\
358 lr-route-list ROUTER print routes for ROUTER\n\
363 --db=DATABASE connect to DATABASE\n\
365 -t, --timeout=SECS wait at most SECS seconds\n\
366 --dry-run do not commit changes to database\n\
367 --oneline print exactly one line of output per command\n",
368 program_name, program_name, ctl_get_db_cmd_usage(), nbctl_default_db());
371 --no-syslog equivalent to --verbose=nbctl:syslog:warn\n");
374 -h, --help display this help message\n\
375 -V, --version display version information\n");
380 /* Find a logical router given its id. */
381 static const struct nbrec_logical_router *
382 lr_by_name_or_uuid(struct ctl_context *ctx, const char *id,
385 const struct nbrec_logical_router *lr = NULL;
386 bool is_uuid = false;
389 if (uuid_from_string(&lr_uuid, id)) {
391 lr = nbrec_logical_router_get_for_uuid(ctx->idl, &lr_uuid);
395 const struct nbrec_logical_router *iter;
397 NBREC_LOGICAL_ROUTER_FOR_EACH(iter, ctx->idl) {
398 if (strcmp(iter->name, id)) {
402 ctl_fatal("Multiple logical routers named '%s'. "
409 if (!lr && must_exist) {
410 ctl_fatal("%s: router %s not found", id, is_uuid ? "UUID" : "name");
416 static const struct nbrec_logical_switch *
417 lswitch_by_name_or_uuid(struct ctl_context *ctx, const char *id,
420 const struct nbrec_logical_switch *lswitch = NULL;
422 struct uuid lswitch_uuid;
423 bool is_uuid = uuid_from_string(&lswitch_uuid, id);
425 lswitch = nbrec_logical_switch_get_for_uuid(ctx->idl, &lswitch_uuid);
429 const struct nbrec_logical_switch *iter;
431 NBREC_LOGICAL_SWITCH_FOR_EACH(iter, ctx->idl) {
432 if (strcmp(iter->name, id)) {
436 ctl_fatal("Multiple logical switches named '%s'. "
443 if (!lswitch && must_exist) {
444 ctl_fatal("%s: lswitch %s not found", id, is_uuid ? "UUID" : "name");
450 /* Given pointer to logical router, this routine prints the router
453 print_lr(const struct nbrec_logical_router *lr, struct ds *s)
455 ds_put_format(s, " router "UUID_FMT" (%s)\n",
456 UUID_ARGS(&lr->header_.uuid), lr->name);
458 for (size_t i = 0; i < lr->n_ports; i++) {
459 const struct nbrec_logical_router_port *lrp = lr->ports[i];
460 ds_put_format(s, " port %s\n", lrp->name);
462 ds_put_cstr(s, " mac: ");
463 ds_put_format(s, "\"%s\"", lrp->mac);
465 ds_put_format(s, "\n");
470 print_lswitch(const struct nbrec_logical_switch *lswitch, struct ds *s)
472 ds_put_format(s, " lswitch "UUID_FMT" (%s)\n",
473 UUID_ARGS(&lswitch->header_.uuid), lswitch->name);
475 for (size_t i = 0; i < lswitch->n_ports; i++) {
476 const struct nbrec_logical_switch_port *lsp = lswitch->ports[i];
478 ds_put_format(s, " port %s\n", lsp->name);
479 if (lsp->parent_name) {
480 ds_put_format(s, " parent: %s\n", lsp->parent_name);
483 ds_put_format(s, " tag: %"PRIu64"\n", lsp->tag[0]);
485 if (lsp->n_addresses) {
486 ds_put_cstr(s, " addresses: [");
487 for (size_t j = 0; j < lsp->n_addresses; j++) {
488 ds_put_format(s, "%s\"%s\"",
492 ds_put_cstr(s, "]\n");
498 nbctl_show(struct ctl_context *ctx)
500 const struct nbrec_logical_switch *lswitch;
502 if (ctx->argc == 2) {
503 lswitch = lswitch_by_name_or_uuid(ctx, ctx->argv[1], false);
505 print_lswitch(lswitch, &ctx->output);
508 NBREC_LOGICAL_SWITCH_FOR_EACH(lswitch, ctx->idl) {
509 print_lswitch(lswitch, &ctx->output);
512 const struct nbrec_logical_router *lr;
514 if (ctx->argc == 2) {
515 lr = lr_by_name_or_uuid(ctx, ctx->argv[1], false);
517 print_lr(lr, &ctx->output);
520 NBREC_LOGICAL_ROUTER_FOR_EACH(lr, ctx->idl) {
521 print_lr(lr, &ctx->output);
527 nbctl_lswitch_add(struct ctl_context *ctx)
529 const char *lswitch_name = ctx->argc == 2 ? ctx->argv[1] : NULL;
531 bool may_exist = shash_find(&ctx->options, "--may-exist") != NULL;
532 bool add_duplicate = shash_find(&ctx->options, "--add-duplicate") != NULL;
533 if (may_exist && add_duplicate) {
534 ctl_fatal("--may-exist and --add-duplicate may not be used together");
538 if (!add_duplicate) {
539 const struct nbrec_logical_switch *lswitch;
540 NBREC_LOGICAL_SWITCH_FOR_EACH (lswitch, ctx->idl) {
541 if (!strcmp(lswitch->name, lswitch_name)) {
545 ctl_fatal("%s: an lswitch with this name already exists",
550 } else if (may_exist) {
551 ctl_fatal("--may-exist requires specifying a name");
552 } else if (add_duplicate) {
553 ctl_fatal("--add-duplicate requires specifying a name");
556 struct nbrec_logical_switch *lswitch;
557 lswitch = nbrec_logical_switch_insert(ctx->txn);
559 nbrec_logical_switch_set_name(lswitch, lswitch_name);
564 nbctl_lswitch_del(struct ctl_context *ctx)
566 bool must_exist = !shash_find(&ctx->options, "--if-exists");
567 const char *id = ctx->argv[1];
568 const struct nbrec_logical_switch *lswitch;
570 lswitch = lswitch_by_name_or_uuid(ctx, id, must_exist);
575 nbrec_logical_switch_delete(lswitch);
579 nbctl_lswitch_list(struct ctl_context *ctx)
581 const struct nbrec_logical_switch *lswitch;
582 struct smap lswitches;
584 smap_init(&lswitches);
585 NBREC_LOGICAL_SWITCH_FOR_EACH(lswitch, ctx->idl) {
586 smap_add_format(&lswitches, lswitch->name, UUID_FMT " (%s)",
587 UUID_ARGS(&lswitch->header_.uuid), lswitch->name);
589 const struct smap_node **nodes = smap_sort(&lswitches);
590 for (size_t i = 0; i < smap_count(&lswitches); i++) {
591 const struct smap_node *node = nodes[i];
592 ds_put_format(&ctx->output, "%s\n", node->value);
594 smap_destroy(&lswitches);
598 static const struct nbrec_logical_switch_port *
599 lsp_by_name_or_uuid(struct ctl_context *ctx, const char *id,
602 const struct nbrec_logical_switch_port *lsp = NULL;
604 struct uuid lsp_uuid;
605 bool is_uuid = uuid_from_string(&lsp_uuid, id);
607 lsp = nbrec_logical_switch_port_get_for_uuid(ctx->idl, &lsp_uuid);
611 NBREC_LOGICAL_SWITCH_PORT_FOR_EACH(lsp, ctx->idl) {
612 if (!strcmp(lsp->name, id)) {
618 if (!lsp && must_exist) {
619 ctl_fatal("%s: port %s not found", id, is_uuid ? "UUID" : "name");
625 /* Returns the lswitch that contains 'lsp'. */
626 static const struct nbrec_logical_switch *
627 lsp_to_lswitch(const struct ovsdb_idl *idl,
628 const struct nbrec_logical_switch_port *lsp)
630 const struct nbrec_logical_switch *lswitch;
631 NBREC_LOGICAL_SWITCH_FOR_EACH (lswitch, idl) {
632 for (size_t i = 0; i < lswitch->n_ports; i++) {
633 if (lswitch->ports[i] == lsp) {
639 /* Can't happen because of the database schema */
640 ctl_fatal("logical port %s is not part of any logical switch",
645 lswitch_get_name(const struct nbrec_logical_switch *lswitch,
646 char uuid_s[UUID_LEN + 1], size_t uuid_s_size)
648 if (lswitch->name[0]) {
649 return lswitch->name;
651 snprintf(uuid_s, uuid_s_size, UUID_FMT, UUID_ARGS(&lswitch->header_.uuid));
656 nbctl_lsp_add(struct ctl_context *ctx)
658 bool may_exist = shash_find(&ctx->options, "--may-exist") != NULL;
660 const struct nbrec_logical_switch *lswitch;
661 lswitch = lswitch_by_name_or_uuid(ctx, ctx->argv[1], true);
663 const char *parent_name;
665 if (ctx->argc == 3) {
668 } else if (ctx->argc == 5) {
670 parent_name = ctx->argv[3];
671 if (!ovs_scan(ctx->argv[4], "%"SCNd64, &tag)
672 || tag < 0 || tag > 4095) {
673 ctl_fatal("%s: invalid tag", ctx->argv[4]);
676 ctl_fatal("lsp-add with parent must also specify a tag");
679 const char *lsp_name = ctx->argv[2];
680 const struct nbrec_logical_switch_port *lsp;
681 lsp = lsp_by_name_or_uuid(ctx, lsp_name, false);
684 ctl_fatal("%s: a port with this name already exists",
688 const struct nbrec_logical_switch *lsw;
689 lsw = lsp_to_lswitch(ctx->idl, lsp);
690 if (lsw != lswitch) {
691 char uuid_s[UUID_LEN + 1];
692 ctl_fatal("%s: port already exists but in lswitch %s", lsp_name,
693 lswitch_get_name(lsw, uuid_s, sizeof uuid_s));
697 if (!lsp->parent_name) {
698 ctl_fatal("%s: port already exists but has no parent",
700 } else if (strcmp(parent_name, lsp->parent_name)) {
701 ctl_fatal("%s: port already exists with different parent %s",
702 lsp_name, lsp->parent_name);
706 ctl_fatal("%s: port already exists but has no tag",
708 } else if (lsp->tag[0] != tag) {
709 ctl_fatal("%s: port already exists with different "
710 "tag %"PRId64, lsp_name, lsp->tag[0]);
713 if (lsp->parent_name) {
714 ctl_fatal("%s: port already exists but has parent %s",
715 lsp_name, lsp->parent_name);
722 /* Create the logical port. */
723 lsp = nbrec_logical_switch_port_insert(ctx->txn);
724 nbrec_logical_switch_port_set_name(lsp, lsp_name);
726 nbrec_logical_switch_port_set_parent_name(lsp, parent_name);
727 nbrec_logical_switch_port_set_tag(lsp, &tag, 1);
730 /* Insert the logical port into the logical switch. */
731 nbrec_logical_switch_verify_ports(lswitch);
732 struct nbrec_logical_switch_port **new_ports = xmalloc(sizeof *new_ports *
733 (lswitch->n_ports + 1));
734 memcpy(new_ports, lswitch->ports, sizeof *new_ports * lswitch->n_ports);
735 new_ports[lswitch->n_ports] = CONST_CAST(struct nbrec_logical_switch_port *,
737 nbrec_logical_switch_set_ports(lswitch, new_ports, lswitch->n_ports + 1);
741 /* Removes logical switch port 'lswitch->ports[idx]'. */
743 remove_lsp(const struct nbrec_logical_switch *lswitch, size_t idx)
745 const struct nbrec_logical_switch_port *lsp = lswitch->ports[idx];
747 /* First remove 'lsp' from the array of ports. This is what will
748 * actually cause the logical port to be deleted when the transaction is
749 * sent to the database server (due to garbage collection). */
750 struct nbrec_logical_switch_port **new_ports
751 = xmemdup(lswitch->ports, sizeof *new_ports * lswitch->n_ports);
752 new_ports[idx] = new_ports[lswitch->n_ports - 1];
753 nbrec_logical_switch_verify_ports(lswitch);
754 nbrec_logical_switch_set_ports(lswitch, new_ports, lswitch->n_ports - 1);
757 /* Delete 'lsp' from the IDL. This won't have a real effect on the
758 * database server (the IDL will suppress it in fact) but it means that it
759 * won't show up when we iterate with NBREC_LOGICAL_SWITCH_PORT_FOR_EACH
761 nbrec_logical_switch_port_delete(lsp);
765 nbctl_lsp_del(struct ctl_context *ctx)
767 bool must_exist = !shash_find(&ctx->options, "--if-exists");
768 const struct nbrec_logical_switch_port *lsp;
770 lsp = lsp_by_name_or_uuid(ctx, ctx->argv[1], must_exist);
775 /* Find the switch that contains 'lsp', then delete it. */
776 const struct nbrec_logical_switch *lswitch;
777 NBREC_LOGICAL_SWITCH_FOR_EACH (lswitch, ctx->idl) {
778 for (size_t i = 0; i < lswitch->n_ports; i++) {
779 if (lswitch->ports[i] == lsp) {
780 remove_lsp(lswitch, i);
786 /* Can't happen because of the database schema. */
787 ctl_fatal("logical port %s is not part of any logical switch",
792 nbctl_lsp_list(struct ctl_context *ctx)
794 const char *id = ctx->argv[1];
795 const struct nbrec_logical_switch *lswitch;
799 lswitch = lswitch_by_name_or_uuid(ctx, id, true);
802 for (i = 0; i < lswitch->n_ports; i++) {
803 const struct nbrec_logical_switch_port *lsp = lswitch->ports[i];
804 smap_add_format(&lsps, lsp->name, UUID_FMT " (%s)",
805 UUID_ARGS(&lsp->header_.uuid), lsp->name);
807 const struct smap_node **nodes = smap_sort(&lsps);
808 for (i = 0; i < smap_count(&lsps); i++) {
809 const struct smap_node *node = nodes[i];
810 ds_put_format(&ctx->output, "%s\n", node->value);
817 nbctl_lsp_get_parent(struct ctl_context *ctx)
819 const struct nbrec_logical_switch_port *lsp;
821 lsp = lsp_by_name_or_uuid(ctx, ctx->argv[1], true);
822 if (lsp->parent_name) {
823 ds_put_format(&ctx->output, "%s\n", lsp->parent_name);
828 nbctl_lsp_get_tag(struct ctl_context *ctx)
830 const struct nbrec_logical_switch_port *lsp;
832 lsp = lsp_by_name_or_uuid(ctx, ctx->argv[1], true);
833 if (lsp->n_tag > 0) {
834 ds_put_format(&ctx->output, "%"PRId64"\n", lsp->tag[0]);
839 nbctl_lsp_set_addresses(struct ctl_context *ctx)
841 const char *id = ctx->argv[1];
842 const struct nbrec_logical_switch_port *lsp;
844 lsp = lsp_by_name_or_uuid(ctx, id, true);
847 for (i = 2; i < ctx->argc; i++) {
850 if (strcmp(ctx->argv[i], "unknown")
851 && !ovs_scan(ctx->argv[i], ETH_ADDR_SCAN_FMT,
852 ETH_ADDR_SCAN_ARGS(ea))) {
853 ctl_fatal("%s: Invalid address format. See ovn-nb(5). "
854 "Hint: An Ethernet address must be "
855 "listed before an IP address, together as a single "
856 "argument.", ctx->argv[i]);
860 nbrec_logical_switch_port_set_addresses(lsp,
861 (const char **) ctx->argv + 2, ctx->argc - 2);
865 nbctl_lsp_get_addresses(struct ctl_context *ctx)
867 const char *id = ctx->argv[1];
868 const struct nbrec_logical_switch_port *lsp;
869 struct svec addresses;
873 lsp = lsp_by_name_or_uuid(ctx, id, true);
875 svec_init(&addresses);
876 for (i = 0; i < lsp->n_addresses; i++) {
877 svec_add(&addresses, lsp->addresses[i]);
879 svec_sort(&addresses);
880 SVEC_FOR_EACH(i, mac, &addresses) {
881 ds_put_format(&ctx->output, "%s\n", mac);
883 svec_destroy(&addresses);
887 nbctl_lsp_set_port_security(struct ctl_context *ctx)
889 const char *id = ctx->argv[1];
890 const struct nbrec_logical_switch_port *lsp;
892 lsp = lsp_by_name_or_uuid(ctx, id, true);
893 nbrec_logical_switch_port_set_port_security(lsp,
894 (const char **) ctx->argv + 2, ctx->argc - 2);
898 nbctl_lsp_get_port_security(struct ctl_context *ctx)
900 const char *id = ctx->argv[1];
901 const struct nbrec_logical_switch_port *lsp;
906 lsp = lsp_by_name_or_uuid(ctx, id, true);
908 for (i = 0; i < lsp->n_port_security; i++) {
909 svec_add(&addrs, lsp->port_security[i]);
912 SVEC_FOR_EACH(i, addr, &addrs) {
913 ds_put_format(&ctx->output, "%s\n", addr);
915 svec_destroy(&addrs);
919 nbctl_lsp_get_up(struct ctl_context *ctx)
921 const char *id = ctx->argv[1];
922 const struct nbrec_logical_switch_port *lsp;
924 lsp = lsp_by_name_or_uuid(ctx, id, true);
925 ds_put_format(&ctx->output,
926 "%s\n", (lsp->up && *lsp->up) ? "up" : "down");
930 parse_enabled(const char *state)
932 if (!strcasecmp(state, "enabled")) {
934 } else if (!strcasecmp(state, "disabled")) {
937 ctl_fatal("%s: state must be \"enabled\" or \"disabled\"", state);
942 nbctl_lsp_set_enabled(struct ctl_context *ctx)
944 const char *id = ctx->argv[1];
945 const char *state = ctx->argv[2];
946 const struct nbrec_logical_switch_port *lsp;
948 lsp = lsp_by_name_or_uuid(ctx, id, true);
949 bool enabled = parse_enabled(state);
950 nbrec_logical_switch_port_set_enabled(lsp, &enabled, 1);
954 nbctl_lsp_get_enabled(struct ctl_context *ctx)
956 const char *id = ctx->argv[1];
957 const struct nbrec_logical_switch_port *lsp;
959 lsp = lsp_by_name_or_uuid(ctx, id, true);
960 ds_put_format(&ctx->output, "%s\n",
961 !lsp->enabled || *lsp->enabled ? "enabled" : "disabled");
965 nbctl_lsp_set_type(struct ctl_context *ctx)
967 const char *id = ctx->argv[1];
968 const char *type = ctx->argv[2];
969 const struct nbrec_logical_switch_port *lsp;
971 lsp = lsp_by_name_or_uuid(ctx, id, true);
972 nbrec_logical_switch_port_set_type(lsp, type);
976 nbctl_lsp_get_type(struct ctl_context *ctx)
978 const char *id = ctx->argv[1];
979 const struct nbrec_logical_switch_port *lsp;
981 lsp = lsp_by_name_or_uuid(ctx, id, true);
982 ds_put_format(&ctx->output, "%s\n", lsp->type);
986 nbctl_lsp_set_options(struct ctl_context *ctx)
988 const char *id = ctx->argv[1];
989 const struct nbrec_logical_switch_port *lsp;
991 struct smap options = SMAP_INITIALIZER(&options);
993 lsp = lsp_by_name_or_uuid(ctx, id, true);
994 for (i = 2; i < ctx->argc; i++) {
996 value = xstrdup(ctx->argv[i]);
997 key = strsep(&value, "=");
999 smap_add(&options, key, value);
1004 nbrec_logical_switch_port_set_options(lsp, &options);
1006 smap_destroy(&options);
1010 nbctl_lsp_get_options(struct ctl_context *ctx)
1012 const char *id = ctx->argv[1];
1013 const struct nbrec_logical_switch_port *lsp;
1014 struct smap_node *node;
1016 lsp = lsp_by_name_or_uuid(ctx, id, true);
1017 SMAP_FOR_EACH(node, &lsp->options) {
1018 ds_put_format(&ctx->output, "%s=%s\n", node->key, node->value);
1028 dir_encode(const char *dir)
1030 if (!strcmp(dir, "from-lport")) {
1031 return DIR_FROM_LPORT;
1032 } else if (!strcmp(dir, "to-lport")) {
1033 return DIR_TO_LPORT;
1040 acl_cmp(const void *acl1_, const void *acl2_)
1042 const struct nbrec_acl *const *acl1p = acl1_;
1043 const struct nbrec_acl *const *acl2p = acl2_;
1044 const struct nbrec_acl *acl1 = *acl1p;
1045 const struct nbrec_acl *acl2 = *acl2p;
1047 int dir1 = dir_encode(acl1->direction);
1048 int dir2 = dir_encode(acl2->direction);
1051 return dir1 < dir2 ? -1 : 1;
1052 } else if (acl1->priority != acl2->priority) {
1053 return acl1->priority > acl2->priority ? -1 : 1;
1055 return strcmp(acl1->match, acl2->match);
1060 nbctl_acl_list(struct ctl_context *ctx)
1062 const struct nbrec_logical_switch *lswitch;
1063 const struct nbrec_acl **acls;
1066 lswitch = lswitch_by_name_or_uuid(ctx, ctx->argv[1], true);
1068 acls = xmalloc(sizeof *acls * lswitch->n_acls);
1069 for (i = 0; i < lswitch->n_acls; i++) {
1070 acls[i] = lswitch->acls[i];
1073 qsort(acls, lswitch->n_acls, sizeof *acls, acl_cmp);
1075 for (i = 0; i < lswitch->n_acls; i++) {
1076 const struct nbrec_acl *acl = acls[i];
1077 ds_put_format(&ctx->output, "%10s %5"PRId64" (%s) %s%s\n",
1078 acl->direction, acl->priority,
1079 acl->match, acl->action, acl->log ? " log" : "");
1086 parse_direction(const char *arg)
1088 /* Validate direction. Only require the first letter. */
1089 if (arg[0] == 't') {
1091 } else if (arg[0] == 'f') {
1092 return "from-lport";
1094 ctl_fatal("%s: direction must be \"to-lport\" or \"from-lport\"", arg);
1099 parse_priority(const char *arg)
1101 /* Validate priority. */
1103 if (!ovs_scan(arg, "%"SCNd64, &priority)
1104 || priority < 0 || priority > 32767) {
1105 ctl_fatal("%s: priority must in range 0...32767", arg);
1111 nbctl_acl_add(struct ctl_context *ctx)
1113 const struct nbrec_logical_switch *lswitch;
1114 const char *action = ctx->argv[5];
1116 lswitch = lswitch_by_name_or_uuid(ctx, ctx->argv[1], true);
1118 const char *direction = parse_direction(ctx->argv[2]);
1119 int64_t priority = parse_priority(ctx->argv[3]);
1121 /* Validate action. */
1122 if (strcmp(action, "allow") && strcmp(action, "allow-related")
1123 && strcmp(action, "drop") && strcmp(action, "reject")) {
1124 ctl_fatal("%s: action must be one of \"allow\", \"allow-related\", "
1125 "\"drop\", and \"reject\"", action);
1129 /* Create the acl. */
1130 struct nbrec_acl *acl = nbrec_acl_insert(ctx->txn);
1131 nbrec_acl_set_priority(acl, priority);
1132 nbrec_acl_set_direction(acl, direction);
1133 nbrec_acl_set_match(acl, ctx->argv[4]);
1134 nbrec_acl_set_action(acl, action);
1135 if (shash_find(&ctx->options, "--log") != NULL) {
1136 nbrec_acl_set_log(acl, true);
1139 /* Insert the acl into the logical switch. */
1140 nbrec_logical_switch_verify_acls(lswitch);
1141 struct nbrec_acl **new_acls = xmalloc(sizeof *new_acls *
1142 (lswitch->n_acls + 1));
1143 memcpy(new_acls, lswitch->acls, sizeof *new_acls * lswitch->n_acls);
1144 new_acls[lswitch->n_acls] = acl;
1145 nbrec_logical_switch_set_acls(lswitch, new_acls, lswitch->n_acls + 1);
1150 nbctl_acl_del(struct ctl_context *ctx)
1152 const struct nbrec_logical_switch *lswitch;
1153 lswitch = lswitch_by_name_or_uuid(ctx, ctx->argv[1], true);
1155 if (ctx->argc != 2 && ctx->argc != 3 && ctx->argc != 5) {
1156 ctl_fatal("cannot specify priority without match");
1159 if (ctx->argc == 2) {
1160 /* If direction, priority, and match are not specified, delete
1162 nbrec_logical_switch_verify_acls(lswitch);
1163 nbrec_logical_switch_set_acls(lswitch, NULL, 0);
1167 const char *direction = parse_direction(ctx->argv[2]);
1169 /* If priority and match are not specified, delete all ACLs with the
1170 * specified direction. */
1171 if (ctx->argc == 3) {
1172 struct nbrec_acl **new_acls
1173 = xmalloc(sizeof *new_acls * lswitch->n_acls);
1176 for (size_t i = 0; i < lswitch->n_acls; i++) {
1177 if (strcmp(direction, lswitch->acls[i]->direction)) {
1178 new_acls[n_acls++] = lswitch->acls[i];
1182 nbrec_logical_switch_verify_acls(lswitch);
1183 nbrec_logical_switch_set_acls(lswitch, new_acls, n_acls);
1188 int64_t priority = parse_priority(ctx->argv[3]);
1190 /* Remove the matching rule. */
1191 for (size_t i = 0; i < lswitch->n_acls; i++) {
1192 struct nbrec_acl *acl = lswitch->acls[i];
1194 if (priority == acl->priority && !strcmp(ctx->argv[4], acl->match) &&
1195 !strcmp(direction, acl->direction)) {
1196 struct nbrec_acl **new_acls
1197 = xmemdup(lswitch->acls, sizeof *new_acls * lswitch->n_acls);
1198 new_acls[i] = lswitch->acls[lswitch->n_acls - 1];
1199 nbrec_logical_switch_verify_acls(lswitch);
1200 nbrec_logical_switch_set_acls(lswitch, new_acls,
1201 lswitch->n_acls - 1);
1209 nbctl_lr_add(struct ctl_context *ctx)
1211 const char *lr_name = ctx->argc == 2 ? ctx->argv[1] : NULL;
1213 bool may_exist = shash_find(&ctx->options, "--may-exist") != NULL;
1214 bool add_duplicate = shash_find(&ctx->options, "--add-duplicate") != NULL;
1215 if (may_exist && add_duplicate) {
1216 ctl_fatal("--may-exist and --add-duplicate may not be used together");
1220 if (!add_duplicate) {
1221 const struct nbrec_logical_router *lr;
1222 NBREC_LOGICAL_ROUTER_FOR_EACH (lr, ctx->idl) {
1223 if (!strcmp(lr->name, lr_name)) {
1227 ctl_fatal("%s: a router with this name already exists",
1232 } else if (may_exist) {
1233 ctl_fatal("--may-exist requires specifying a name");
1234 } else if (add_duplicate) {
1235 ctl_fatal("--add-duplicate requires specifying a name");
1238 struct nbrec_logical_router *lr;
1239 lr = nbrec_logical_router_insert(ctx->txn);
1241 nbrec_logical_router_set_name(lr, lr_name);
1246 nbctl_lr_del(struct ctl_context *ctx)
1248 bool must_exist = !shash_find(&ctx->options, "--if-exists");
1249 const char *id = ctx->argv[1];
1250 const struct nbrec_logical_router *lr;
1252 lr = lr_by_name_or_uuid(ctx, id, must_exist);
1257 nbrec_logical_router_delete(lr);
1261 nbctl_lr_list(struct ctl_context *ctx)
1263 const struct nbrec_logical_router *lr;
1267 NBREC_LOGICAL_ROUTER_FOR_EACH(lr, ctx->idl) {
1268 smap_add_format(&lrs, lr->name, UUID_FMT " (%s)",
1269 UUID_ARGS(&lr->header_.uuid), lr->name);
1271 const struct smap_node **nodes = smap_sort(&lrs);
1272 for (size_t i = 0; i < smap_count(&lrs); i++) {
1273 const struct smap_node *node = nodes[i];
1274 ds_put_format(&ctx->output, "%s\n", node->value);
1280 /* The caller must free the returned string. */
1282 normalize_ipv4_prefix(ovs_be32 ipv4, unsigned int plen)
1284 ovs_be32 network = ipv4 & be32_prefix_mask(plen);
1286 return xasprintf(IP_FMT, IP_ARGS(network));
1288 return xasprintf(IP_FMT"/%d", IP_ARGS(network), plen);
1292 /* The caller must free the returned string. */
1294 normalize_ipv6_prefix(struct in6_addr ipv6, unsigned int plen)
1296 char network_s[INET6_ADDRSTRLEN];
1298 struct in6_addr mask = ipv6_create_mask(plen);
1299 struct in6_addr network = ipv6_addr_bitand(&ipv6, &mask);
1301 inet_ntop(AF_INET6, &network, network_s, INET6_ADDRSTRLEN);
1303 return xasprintf("%s", network_s);
1305 return xasprintf("%s/%d", network_s, plen);
1309 /* The caller must free the returned string. */
1311 normalize_prefix_str(const char *orig_prefix)
1317 error = ip_parse_cidr(orig_prefix, &ipv4, &plen);
1319 return normalize_ipv4_prefix(ipv4, plen);
1321 struct in6_addr ipv6;
1324 error = ipv6_parse_cidr(orig_prefix, &ipv6, &plen);
1329 return normalize_ipv6_prefix(ipv6, plen);
1334 nbctl_lr_route_add(struct ctl_context *ctx)
1336 const struct nbrec_logical_router *lr;
1337 lr = lr_by_name_or_uuid(ctx, ctx->argv[1], true);
1338 char *prefix, *next_hop;
1340 prefix = normalize_prefix_str(ctx->argv[2]);
1342 ctl_fatal("bad prefix argument: %s", ctx->argv[2]);
1345 next_hop = normalize_prefix_str(ctx->argv[3]);
1347 ctl_fatal("bad next hop argument: %s", ctx->argv[3]);
1350 if (strchr(prefix, '.')) {
1352 if (!ip_parse(ctx->argv[3], &hop_ipv4)) {
1353 ctl_fatal("bad IPv4 nexthop argument: %s", ctx->argv[3]);
1356 struct in6_addr hop_ipv6;
1357 if (!ipv6_parse(ctx->argv[3], &hop_ipv6)) {
1358 ctl_fatal("bad IPv6 nexthop argument: %s", ctx->argv[3]);
1362 bool may_exist = shash_find(&ctx->options, "--may-exist") != NULL;
1363 for (int i = 0; i < lr->n_static_routes; i++) {
1364 const struct nbrec_logical_router_static_route *route
1365 = lr->static_routes[i];
1368 rt_prefix = normalize_prefix_str(lr->static_routes[i]->ip_prefix);
1370 /* Ignore existing prefix we couldn't parse. */
1374 if (strcmp(rt_prefix, prefix)) {
1380 ctl_fatal("duplicate prefix: %s", prefix);
1383 /* Update the next hop for an existing route. */
1384 nbrec_logical_router_verify_static_routes(lr);
1385 nbrec_logical_router_static_route_verify_ip_prefix(route);
1386 nbrec_logical_router_static_route_verify_nexthop(route);
1387 nbrec_logical_router_static_route_set_ip_prefix(route, prefix);
1388 nbrec_logical_router_static_route_set_nexthop(route, next_hop);
1395 struct nbrec_logical_router_static_route *route;
1396 route = nbrec_logical_router_static_route_insert(ctx->txn);
1397 nbrec_logical_router_static_route_set_ip_prefix(route, prefix);
1398 nbrec_logical_router_static_route_set_nexthop(route, next_hop);
1399 if (ctx->argc == 5) {
1400 nbrec_logical_router_static_route_set_output_port(route, ctx->argv[4]);
1403 nbrec_logical_router_verify_static_routes(lr);
1404 struct nbrec_logical_router_static_route **new_routes
1405 = xmalloc(sizeof *new_routes * (lr->n_static_routes + 1));
1406 memcpy(new_routes, lr->static_routes,
1407 sizeof *new_routes * lr->n_static_routes);
1408 new_routes[lr->n_static_routes] = route;
1409 nbrec_logical_router_set_static_routes(lr, new_routes,
1410 lr->n_static_routes + 1);
1417 nbctl_lr_route_del(struct ctl_context *ctx)
1419 const struct nbrec_logical_router *lr;
1420 lr = lr_by_name_or_uuid(ctx, ctx->argv[1], true);
1422 if (ctx->argc == 2) {
1423 /* If a prefix is not specified, delete all routes. */
1424 nbrec_logical_router_set_static_routes(lr, NULL, 0);
1428 char *prefix = normalize_prefix_str(ctx->argv[2]);
1430 ctl_fatal("bad prefix argument: %s", ctx->argv[2]);
1433 for (int i = 0; i < lr->n_static_routes; i++) {
1434 char *rt_prefix = normalize_prefix_str(lr->static_routes[i]->ip_prefix);
1436 /* Ignore existing prefix we couldn't parse. */
1440 if (!strcmp(prefix, rt_prefix)) {
1441 struct nbrec_logical_router_static_route **new_routes
1442 = xmemdup(lr->static_routes,
1443 sizeof *new_routes * lr->n_static_routes);
1445 new_routes[i] = lr->static_routes[lr->n_static_routes - 1];
1446 nbrec_logical_router_verify_static_routes(lr);
1447 nbrec_logical_router_set_static_routes(lr, new_routes,
1448 lr->n_static_routes - 1);
1457 if (!shash_find(&ctx->options, "--if-exists")) {
1458 ctl_fatal("no matching prefix: %s", prefix);
1463 static const struct nbrec_logical_router_port *
1464 lrp_by_name_or_uuid(struct ctl_context *ctx, const char *id, bool must_exist)
1466 const struct nbrec_logical_router_port *lrp = NULL;
1468 struct uuid lrp_uuid;
1469 bool is_uuid = uuid_from_string(&lrp_uuid, id);
1471 lrp = nbrec_logical_router_port_get_for_uuid(ctx->idl, &lrp_uuid);
1475 NBREC_LOGICAL_ROUTER_PORT_FOR_EACH(lrp, ctx->idl) {
1476 if (!strcmp(lrp->name, id)) {
1482 if (!lrp && must_exist) {
1483 ctl_fatal("%s: port %s not found", id, is_uuid ? "UUID" : "name");
1489 /* Returns the logical router that contains 'lrp'. */
1490 static const struct nbrec_logical_router *
1491 lrp_to_lr(const struct ovsdb_idl *idl,
1492 const struct nbrec_logical_router_port *lrp)
1494 const struct nbrec_logical_router *lr;
1495 NBREC_LOGICAL_ROUTER_FOR_EACH (lr, idl) {
1496 for (size_t i = 0; i < lr->n_ports; i++) {
1497 if (lr->ports[i] == lrp) {
1503 /* Can't happen because of the database schema */
1504 ctl_fatal("port %s is not part of any logical router",
1509 lr_get_name(const struct nbrec_logical_router *lr, char uuid_s[UUID_LEN + 1],
1515 snprintf(uuid_s, uuid_s_size, UUID_FMT, UUID_ARGS(&lr->header_.uuid));
1520 nbctl_lrp_add(struct ctl_context *ctx)
1522 bool may_exist = shash_find(&ctx->options, "--may-exist") != NULL;
1524 const struct nbrec_logical_router *lr;
1525 lr = lr_by_name_or_uuid(ctx, ctx->argv[1], true);
1527 const char *lrp_name = ctx->argv[2];
1528 const char *mac = ctx->argv[3];
1529 const char *network = ctx->argv[4];
1530 const char *peer = (ctx->argc == 6) ? ctx->argv[5] : NULL;
1532 const struct nbrec_logical_router_port *lrp;
1533 lrp = lrp_by_name_or_uuid(ctx, lrp_name, false);
1536 ctl_fatal("%s: a port with this name already exists",
1540 const struct nbrec_logical_router *bound_lr;
1541 bound_lr = lrp_to_lr(ctx->idl, lrp);
1542 if (bound_lr != lr) {
1543 char uuid_s[UUID_LEN + 1];
1544 ctl_fatal("%s: port already exists but in router %s", lrp_name,
1545 lr_get_name(bound_lr, uuid_s, sizeof uuid_s));
1548 if (strcmp(mac, lrp->mac)) {
1549 ctl_fatal("%s: port already exists with mac %s", lrp_name,
1553 if (strcmp(network, lrp->network)) {
1554 ctl_fatal("%s: port already exists with network %s", lrp_name,
1558 if ((!peer != !lrp->peer) ||
1559 (lrp->peer && strcmp(peer, lrp->peer))) {
1560 ctl_fatal("%s: port already exists with mismatching peer",
1568 if (!ovs_scan(mac, ETH_ADDR_SCAN_FMT, ETH_ADDR_SCAN_ARGS(ea))) {
1569 ctl_fatal("%s: invalid mac address.", mac);
1574 char *error = ip_parse_cidr(network, &ipv4, &plen);
1577 struct in6_addr ipv6;
1578 error = ipv6_parse_cidr(network, &ipv6, &plen);
1581 ctl_fatal("%s: invalid network address.", network);
1585 /* Create the logical port. */
1586 lrp = nbrec_logical_router_port_insert(ctx->txn);
1587 nbrec_logical_router_port_set_name(lrp, lrp_name);
1588 nbrec_logical_router_port_set_mac(lrp, mac);
1589 nbrec_logical_router_port_set_network(lrp, network);
1591 nbrec_logical_router_port_set_peer(lrp, peer);
1594 /* Insert the logical port into the logical router. */
1595 nbrec_logical_router_verify_ports(lr);
1596 struct nbrec_logical_router_port **new_ports = xmalloc(sizeof *new_ports *
1598 memcpy(new_ports, lr->ports, sizeof *new_ports * lr->n_ports);
1599 new_ports[lr->n_ports] = CONST_CAST(struct nbrec_logical_router_port *,
1601 nbrec_logical_router_set_ports(lr, new_ports, lr->n_ports + 1);
1605 /* Removes logical router port 'lr->ports[idx]'. */
1607 remove_lrp(const struct nbrec_logical_router *lr, size_t idx)
1609 const struct nbrec_logical_router_port *lrp = lr->ports[idx];
1611 /* First remove 'lrp' from the array of ports. This is what will
1612 * actually cause the logical port to be deleted when the transaction is
1613 * sent to the database server (due to garbage collection). */
1614 struct nbrec_logical_router_port **new_ports
1615 = xmemdup(lr->ports, sizeof *new_ports * lr->n_ports);
1616 new_ports[idx] = new_ports[lr->n_ports - 1];
1617 nbrec_logical_router_verify_ports(lr);
1618 nbrec_logical_router_set_ports(lr, new_ports, lr->n_ports - 1);
1621 /* Delete 'lrp' from the IDL. This won't have a real effect on
1622 * the database server (the IDL will suppress it in fact) but it
1623 * means that it won't show up when we iterate with
1624 * NBREC_LOGICAL_ROUTER_PORT_FOR_EACH later. */
1625 nbrec_logical_router_port_delete(lrp);
1629 nbctl_lrp_del(struct ctl_context *ctx)
1631 bool must_exist = !shash_find(&ctx->options, "--if-exists");
1632 const struct nbrec_logical_router_port *lrp;
1634 lrp = lrp_by_name_or_uuid(ctx, ctx->argv[1], must_exist);
1639 /* Find the router that contains 'lrp', then delete it. */
1640 const struct nbrec_logical_router *lr;
1641 NBREC_LOGICAL_ROUTER_FOR_EACH (lr, ctx->idl) {
1642 for (size_t i = 0; i < lr->n_ports; i++) {
1643 if (lr->ports[i] == lrp) {
1650 /* Can't happen because of the database schema. */
1651 ctl_fatal("logical port %s is not part of any logical router",
1655 /* Print a list of logical router ports. */
1657 nbctl_lrp_list(struct ctl_context *ctx)
1659 const char *id = ctx->argv[1];
1660 const struct nbrec_logical_router *lr;
1664 lr = lr_by_name_or_uuid(ctx, id, true);
1667 for (i = 0; i < lr->n_ports; i++) {
1668 const struct nbrec_logical_router_port *lrp = lr->ports[i];
1669 smap_add_format(&lrps, lrp->name, UUID_FMT " (%s)",
1670 UUID_ARGS(&lrp->header_.uuid), lrp->name);
1672 const struct smap_node **nodes = smap_sort(&lrps);
1673 for (i = 0; i < smap_count(&lrps); i++) {
1674 const struct smap_node *node = nodes[i];
1675 ds_put_format(&ctx->output, "%s\n", node->value);
1677 smap_destroy(&lrps);
1681 /* Set the logical router port admin-enabled state. */
1683 nbctl_lrp_set_enabled(struct ctl_context *ctx)
1685 const char *id = ctx->argv[1];
1686 const char *state = ctx->argv[2];
1687 const struct nbrec_logical_router_port *lrp;
1689 lrp = lrp_by_name_or_uuid(ctx, id, true);
1694 bool enabled = parse_enabled(state);
1695 nbrec_logical_router_port_set_enabled(lrp, &enabled, 1);
1698 /* Print admin-enabled state for logical router port. */
1700 nbctl_lrp_get_enabled(struct ctl_context *ctx)
1702 const char *id = ctx->argv[1];
1703 const struct nbrec_logical_router_port *lrp;
1705 lrp = lrp_by_name_or_uuid(ctx, id, true);
1710 ds_put_format(&ctx->output, "%s\n",
1712 *lrp->enabled ? "enabled" : "disabled");
1718 const struct nbrec_logical_router_static_route *route;
1722 ipv4_route_cmp(const void *route1_, const void *route2_)
1724 const struct ipv4_route *route1p = route1_;
1725 const struct ipv4_route *route2p = route2_;
1727 if (route1p->plen != route2p->plen) {
1728 return route1p->plen > route2p->plen ? -1 : 1;
1729 } else if (route1p->addr != route2p->addr) {
1730 return ntohl(route1p->addr) < ntohl(route2p->addr) ? -1 : 1;
1738 struct in6_addr addr;
1739 const struct nbrec_logical_router_static_route *route;
1743 ipv6_route_cmp(const void *route1_, const void *route2_)
1745 const struct ipv6_route *route1p = route1_;
1746 const struct ipv6_route *route2p = route2_;
1748 if (route1p->plen != route2p->plen) {
1749 return route1p->plen > route2p->plen ? -1 : 1;
1751 return memcmp(&route1p->addr, &route2p->addr, sizeof(route1p->addr));
1755 print_route(const struct nbrec_logical_router_static_route *route, struct ds *s)
1758 char *prefix = normalize_prefix_str(route->ip_prefix);
1759 char *next_hop = normalize_prefix_str(route->nexthop);
1760 ds_put_format(s, "%25s %25s", prefix, next_hop);
1764 if (route->output_port) {
1765 ds_put_format(s, " %s", route->output_port);
1767 ds_put_char(s, '\n');
1771 nbctl_lr_route_list(struct ctl_context *ctx)
1773 const struct nbrec_logical_router *lr;
1774 struct ipv4_route *ipv4_routes;
1775 struct ipv6_route *ipv6_routes;
1776 size_t n_ipv4_routes = 0;
1777 size_t n_ipv6_routes = 0;
1779 lr = lr_by_name_or_uuid(ctx, ctx->argv[1], true);
1781 ipv4_routes = xmalloc(sizeof *ipv4_routes * lr->n_static_routes);
1782 ipv6_routes = xmalloc(sizeof *ipv6_routes * lr->n_static_routes);
1784 for (int i = 0; i < lr->n_static_routes; i++) {
1785 const struct nbrec_logical_router_static_route *route
1786 = lr->static_routes[i];
1791 error = ip_parse_cidr(route->ip_prefix, &ipv4, &plen);
1793 ipv4_routes[n_ipv4_routes].plen = plen;
1794 ipv4_routes[n_ipv4_routes].addr = ipv4;
1795 ipv4_routes[n_ipv4_routes].route = route;
1800 struct in6_addr ipv6;
1801 if (!ipv6_parse_cidr(route->ip_prefix, &ipv6, &plen)) {
1802 ipv6_routes[n_ipv6_routes].plen = plen;
1803 ipv6_routes[n_ipv6_routes].addr = ipv6;
1804 ipv6_routes[n_ipv6_routes].route = route;
1807 /* Invalid prefix. */
1808 VLOG_WARN("router "UUID_FMT" (%s) has invalid prefix: %s",
1809 UUID_ARGS(&lr->header_.uuid), lr->name,
1817 qsort(ipv4_routes, n_ipv4_routes, sizeof *ipv4_routes, ipv4_route_cmp);
1818 qsort(ipv6_routes, n_ipv6_routes, sizeof *ipv6_routes, ipv6_route_cmp);
1820 if (n_ipv4_routes) {
1821 ds_put_cstr(&ctx->output, "IPv4 Routes\n");
1823 for (int i = 0; i < n_ipv4_routes; i++) {
1824 print_route(ipv4_routes[i].route, &ctx->output);
1827 if (n_ipv6_routes) {
1828 ds_put_format(&ctx->output, "%sIPv6 Routes\n",
1829 n_ipv4_routes ? "\n" : "");
1831 for (int i = 0; i < n_ipv6_routes; i++) {
1832 print_route(ipv6_routes[i].route, &ctx->output);
1839 static const struct ctl_table_class tables[] = {
1840 {&nbrec_table_logical_switch,
1841 {{&nbrec_table_logical_switch, &nbrec_logical_switch_col_name, NULL},
1842 {NULL, NULL, NULL}}},
1844 {&nbrec_table_logical_switch_port,
1845 {{&nbrec_table_logical_switch_port, &nbrec_logical_switch_port_col_name,
1847 {NULL, NULL, NULL}}},
1850 {{NULL, NULL, NULL},
1851 {NULL, NULL, NULL}}},
1853 {&nbrec_table_logical_router,
1854 {{&nbrec_table_logical_router, &nbrec_logical_router_col_name, NULL},
1855 {NULL, NULL, NULL}}},
1857 {&nbrec_table_logical_router_port,
1858 {{&nbrec_table_logical_router_port, &nbrec_logical_router_port_col_name,
1860 {NULL, NULL, NULL}}},
1862 {&nbrec_table_logical_router_static_route,
1863 {{&nbrec_table_logical_router_static_route, NULL,
1865 {NULL, NULL, NULL}}},
1867 {NULL, {{NULL, NULL, NULL}, {NULL, NULL, NULL}}}
1871 run_prerequisites(struct ctl_command *commands, size_t n_commands,
1872 struct ovsdb_idl *idl)
1874 struct ctl_command *c;
1876 for (c = commands; c < &commands[n_commands]; c++) {
1877 if (c->syntax->prerequisites) {
1878 struct ctl_context ctx;
1880 ds_init(&c->output);
1883 ctl_context_init(&ctx, c, idl, NULL, NULL, NULL);
1884 (c->syntax->prerequisites)(&ctx);
1885 ctl_context_done(&ctx, c);
1887 ovs_assert(!c->output.string);
1888 ovs_assert(!c->table);
1894 do_nbctl(const char *args, struct ctl_command *commands, size_t n_commands,
1895 struct ovsdb_idl *idl)
1897 struct ovsdb_idl_txn *txn;
1898 enum ovsdb_idl_txn_status status;
1899 struct ovsdb_symbol_table *symtab;
1900 struct ctl_context ctx;
1901 struct ctl_command *c;
1902 struct shash_node *node;
1905 txn = the_idl_txn = ovsdb_idl_txn_create(idl);
1907 ovsdb_idl_txn_set_dry_run(txn);
1910 ovsdb_idl_txn_add_comment(txn, "ovs-nbctl: %s", args);
1912 symtab = ovsdb_symbol_table_create();
1913 for (c = commands; c < &commands[n_commands]; c++) {
1914 ds_init(&c->output);
1917 ctl_context_init(&ctx, NULL, idl, txn, symtab, NULL);
1918 for (c = commands; c < &commands[n_commands]; c++) {
1919 ctl_context_init_command(&ctx, c);
1920 if (c->syntax->run) {
1921 (c->syntax->run)(&ctx);
1923 ctl_context_done_command(&ctx, c);
1925 if (ctx.try_again) {
1926 ctl_context_done(&ctx, NULL);
1930 ctl_context_done(&ctx, NULL);
1932 SHASH_FOR_EACH (node, &symtab->sh) {
1933 struct ovsdb_symbol *symbol = node->data;
1934 if (!symbol->created) {
1935 ctl_fatal("row id \"%s\" is referenced but never created (e.g. "
1936 "with \"-- --id=%s create ...\")",
1937 node->name, node->name);
1939 if (!symbol->strong_ref) {
1940 if (!symbol->weak_ref) {
1941 VLOG_WARN("row id \"%s\" was created but no reference to it "
1942 "was inserted, so it will not actually appear in "
1943 "the database", node->name);
1945 VLOG_WARN("row id \"%s\" was created but only a weak "
1946 "reference to it was inserted, so it will not "
1947 "actually appear in the database", node->name);
1952 status = ovsdb_idl_txn_commit_block(txn);
1953 if (status == TXN_UNCHANGED || status == TXN_SUCCESS) {
1954 for (c = commands; c < &commands[n_commands]; c++) {
1955 if (c->syntax->postprocess) {
1956 ctl_context_init(&ctx, c, idl, txn, symtab, NULL);
1957 (c->syntax->postprocess)(&ctx);
1958 ctl_context_done(&ctx, c);
1962 error = xstrdup(ovsdb_idl_txn_get_error(txn));
1965 case TXN_UNCOMMITTED:
1966 case TXN_INCOMPLETE:
1970 /* Should not happen--we never call ovsdb_idl_txn_abort(). */
1971 ctl_fatal("transaction aborted");
1981 ctl_fatal("transaction error: %s", error);
1983 case TXN_NOT_LOCKED:
1984 /* Should not happen--we never call ovsdb_idl_set_lock(). */
1985 ctl_fatal("database not locked");
1992 ovsdb_symbol_table_destroy(symtab);
1994 for (c = commands; c < &commands[n_commands]; c++) {
1995 struct ds *ds = &c->output;
1998 table_print(c->table, &table_style);
1999 } else if (oneline) {
2003 for (j = 0; j < ds->length; j++) {
2004 int ch = ds->string[j];
2007 fputs("\\n", stdout);
2011 fputs("\\\\", stdout);
2020 fputs(ds_cstr(ds), stdout);
2022 ds_destroy(&c->output);
2023 table_destroy(c->table);
2026 shash_destroy_free_data(&c->options);
2029 ovsdb_idl_txn_destroy(txn);
2030 ovsdb_idl_destroy(idl);
2035 /* Our transaction needs to be rerun, or a prerequisite was not met. Free
2036 * resources and return so that the caller can try again. */
2038 ovsdb_idl_txn_abort(txn);
2039 ovsdb_idl_txn_destroy(txn);
2042 ovsdb_symbol_table_destroy(symtab);
2043 for (c = commands; c < &commands[n_commands]; c++) {
2044 ds_destroy(&c->output);
2045 table_destroy(c->table);
2052 /* Frees the current transaction and the underlying IDL and then calls
2055 * Freeing the transaction and the IDL is not strictly necessary, but it makes
2056 * for a clean memory leak report from valgrind in the normal case. That makes
2057 * it easier to notice real memory leaks. */
2059 nbctl_exit(int status)
2062 ovsdb_idl_txn_abort(the_idl_txn);
2063 ovsdb_idl_txn_destroy(the_idl_txn);
2065 ovsdb_idl_destroy(the_idl);
2069 static const struct ctl_command_syntax nbctl_commands[] = {
2070 { "show", 0, 1, "[LSWITCH]", NULL, nbctl_show, NULL, "", RO },
2072 /* lswitch commands. */
2073 { "lswitch-add", 0, 1, "[LSWITCH]", NULL, nbctl_lswitch_add,
2074 NULL, "--may-exist,--add-duplicate", RW },
2075 { "lswitch-del", 1, 1, "LSWITCH", NULL, nbctl_lswitch_del,
2076 NULL, "--if-exists", RW },
2077 { "lswitch-list", 0, 0, "", NULL, nbctl_lswitch_list, NULL, "", RO },
2080 { "acl-add", 5, 5, "LSWITCH DIRECTION PRIORITY MATCH ACTION", NULL,
2081 nbctl_acl_add, NULL, "--log", RW },
2082 { "acl-del", 1, 4, "LSWITCH [DIRECTION [PRIORITY MATCH]]", NULL,
2083 nbctl_acl_del, NULL, "", RW },
2084 { "acl-list", 1, 1, "LSWITCH", NULL, nbctl_acl_list, NULL, "", RO },
2086 /* logical switch port commands. */
2087 { "lsp-add", 2, 4, "LSWITCH PORT [PARENT] [TAG]", NULL, nbctl_lsp_add,
2088 NULL, "--may-exist", RW },
2089 { "lsp-del", 1, 1, "PORT", NULL, nbctl_lsp_del, NULL, "--if-exists", RW },
2090 { "lsp-list", 1, 1, "LSWITCH", NULL, nbctl_lsp_list, NULL, "", RO },
2091 { "lsp-get-parent", 1, 1, "PORT", NULL, nbctl_lsp_get_parent, NULL,
2093 { "lsp-get-tag", 1, 1, "PORT", NULL, nbctl_lsp_get_tag, NULL, "", RO },
2094 { "lsp-set-addresses", 1, INT_MAX, "PORT [ADDRESS]...", NULL,
2095 nbctl_lsp_set_addresses, NULL, "", RW },
2096 { "lsp-get-addresses", 1, 1, "PORT", NULL, nbctl_lsp_get_addresses, NULL,
2098 { "lsp-set-port-security", 0, INT_MAX, "PORT [ADDRS]...", NULL,
2099 nbctl_lsp_set_port_security, NULL, "", RW },
2100 { "lsp-get-port-security", 1, 1, "PORT", NULL,
2101 nbctl_lsp_get_port_security, NULL, "", RO },
2102 { "lsp-get-up", 1, 1, "PORT", NULL, nbctl_lsp_get_up, NULL, "", RO },
2103 { "lsp-set-enabled", 2, 2, "PORT STATE", NULL, nbctl_lsp_set_enabled,
2105 { "lsp-get-enabled", 1, 1, "PORT", NULL, nbctl_lsp_get_enabled, NULL,
2107 { "lsp-set-type", 2, 2, "PORT TYPE", NULL, nbctl_lsp_set_type, NULL,
2109 { "lsp-get-type", 1, 1, "PORT", NULL, nbctl_lsp_get_type, NULL, "", RO },
2110 { "lsp-set-options", 1, INT_MAX, "PORT KEY=VALUE [KEY=VALUE]...", NULL,
2111 nbctl_lsp_set_options, NULL, "", RW },
2112 { "lsp-get-options", 1, 1, "PORT", NULL, nbctl_lsp_get_options, NULL,
2115 /* logical router commands. */
2116 { "lr-add", 0, 1, "[ROUTER]", NULL, nbctl_lr_add, NULL,
2117 "--may-exist,--add-duplicate", RW },
2118 { "lr-del", 1, 1, "ROUTER", NULL, nbctl_lr_del, NULL, "--if-exists", RW },
2119 { "lr-list", 0, 0, "", NULL, nbctl_lr_list, NULL, "", RO },
2121 /* logical router port commands. */
2122 { "lrp-add", 4, 5, "ROUTER PORT MAC NETWORK [PEER]", NULL, nbctl_lrp_add,
2123 NULL, "--may-exist", RW },
2124 { "lrp-del", 1, 1, "LPORT", NULL, nbctl_lrp_del, NULL, "--if-exists", RW },
2125 { "lrp-list", 1, 1, "ROUTER", NULL, nbctl_lrp_list, NULL, "", RO },
2126 { "lrp-set-enabled", 2, 2, "PORT STATE", NULL, nbctl_lrp_set_enabled,
2128 { "lrp-get-enabled", 1, 1, "PORT", NULL, nbctl_lrp_get_enabled,
2131 /* logical router route commands. */
2132 { "lr-route-add", 3, 4, "ROUTER PREFIX NEXTHOP [PORT]", NULL,
2133 nbctl_lr_route_add, NULL, "--may-exist", RW },
2134 { "lr-route-del", 1, 2, "ROUTER [PREFIX]", NULL, nbctl_lr_route_del,
2135 NULL, "--if-exists", RW },
2136 { "lr-route-list", 1, 1, "ROUTER", NULL, nbctl_lr_route_list, NULL,
2139 {NULL, 0, 0, NULL, NULL, NULL, NULL, "", RO},
2142 /* Registers nbctl and common db commands. */
2144 nbctl_cmd_init(void)
2146 ctl_init(tables, NULL, nbctl_exit);
2147 ctl_register_commands(nbctl_commands);