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"
34 #include "stream-ssl.h"
39 #include "openvswitch/vlog.h"
41 VLOG_DEFINE_THIS_MODULE(nbctl);
43 /* --db: The database server to contact. */
44 static const char *db;
46 /* --oneline: Write each command's output as a single line? */
49 /* --dry-run: Do not commit any changes. */
52 /* --timeout: Time to wait for a connection to 'db'. */
55 /* Format for table output. */
56 static struct table_style table_style = TABLE_STYLE_DEFAULT;
58 /* The IDL we're using and the current transaction, if any.
59 * This is for use by nbctl_exit() only, to allow it to clean up.
60 * Other code should use its context arguments. */
61 static struct ovsdb_idl *the_idl;
62 static struct ovsdb_idl_txn *the_idl_txn;
63 OVS_NO_RETURN static void nbctl_exit(int status);
65 static void nbctl_cmd_init(void);
66 OVS_NO_RETURN static void usage(void);
67 static void parse_options(int argc, char *argv[], struct shash *local_options);
68 static const char *nbctl_default_db(void);
69 static void run_prerequisites(struct ctl_command[], size_t n_commands,
71 static bool do_nbctl(const char *args, struct ctl_command *, size_t n,
75 main(int argc, char *argv[])
77 struct ovsdb_idl *idl;
78 struct ctl_command *commands;
79 struct shash local_options;
84 set_program_name(argv[0]);
85 fatal_ignore_sigpipe();
86 vlog_set_levels(NULL, VLF_CONSOLE, VLL_WARN);
87 vlog_set_levels_from_string_assert("reconnect:warn");
92 /* Log our arguments. This is often valuable for debugging systems. */
93 args = process_escape_args(argv);
94 VLOG(ctl_might_write_to_db(argv) ? VLL_INFO : VLL_DBG,
95 "Called as %s", args);
97 /* Parse command line. */
98 shash_init(&local_options);
99 parse_options(argc, argv, &local_options);
100 commands = ctl_parse_commands(argc - optind, argv + optind, &local_options,
107 /* Initialize IDL. */
108 idl = the_idl = ovsdb_idl_create(db, &nbrec_idl_class, true, false);
109 run_prerequisites(commands, n_commands, idl);
111 /* Execute the commands.
113 * 'seqno' is the database sequence number for which we last tried to
114 * execute our transaction. There's no point in trying to commit more than
115 * once for any given sequence number, because if the transaction fails
116 * it's because the database changed and we need to obtain an up-to-date
117 * view of the database before we try the transaction again. */
118 seqno = ovsdb_idl_get_seqno(idl);
121 if (!ovsdb_idl_is_alive(idl)) {
122 int retval = ovsdb_idl_get_last_error(idl);
123 ctl_fatal("%s: database connection failed (%s)",
124 db, ovs_retval_to_string(retval));
127 if (seqno != ovsdb_idl_get_seqno(idl)) {
128 seqno = ovsdb_idl_get_seqno(idl);
129 if (do_nbctl(args, commands, n_commands, idl)) {
135 if (seqno == ovsdb_idl_get_seqno(idl)) {
143 nbctl_default_db(void)
147 def = getenv("OVN_NB_DB");
149 def = xasprintf("unix:%s/ovnnb_db.sock", ovs_rundir());
156 parse_options(int argc, char *argv[], struct shash *local_options)
159 OPT_DB = UCHAR_MAX + 1,
169 static const struct option global_long_options[] = {
170 {"db", required_argument, NULL, OPT_DB},
171 {"no-syslog", no_argument, NULL, OPT_NO_SYSLOG},
172 {"dry-run", no_argument, NULL, OPT_DRY_RUN},
173 {"oneline", no_argument, NULL, OPT_ONELINE},
174 {"timeout", required_argument, NULL, 't'},
175 {"help", no_argument, NULL, 'h'},
176 {"commands", no_argument, NULL, OPT_COMMANDS},
177 {"options", no_argument, NULL, OPT_OPTIONS},
178 {"version", no_argument, NULL, 'V'},
180 STREAM_SSL_LONG_OPTIONS,
184 const int n_global_long_options = ARRAY_SIZE(global_long_options) - 1;
185 char *tmp, *short_options;
187 struct option *options;
188 size_t allocated_options;
192 tmp = ovs_cmdl_long_options_to_short_options(global_long_options);
193 short_options = xasprintf("+%s", tmp);
196 /* We want to parse both global and command-specific options here, but
197 * getopt_long() isn't too convenient for the job. We copy our global
198 * options into a dynamic array, then append all of the command-specific
200 options = xmemdup(global_long_options, sizeof global_long_options);
201 allocated_options = ARRAY_SIZE(global_long_options);
202 n_options = n_global_long_options;
203 ctl_add_cmd_options(&options, &n_options, &allocated_options, OPT_LOCAL);
204 table_style.format = TF_LIST;
210 c = getopt_long(argc, argv, short_options, options, &idx);
225 vlog_set_levels(&this_module, VLF_SYSLOG, VLL_WARN);
233 if (shash_find(local_options, options[idx].name)) {
234 ctl_fatal("'%s' option specified multiple times",
237 shash_add_nocopy(local_options,
238 xasprintf("--%s", options[idx].name),
239 nullable_xstrdup(optarg));
247 ctl_print_commands();
250 ctl_print_options(global_long_options);
253 ovs_print_version(0, 0);
254 printf("DB Schema %s\n", nbrec_get_db_version());
258 timeout = strtoul(optarg, NULL, 10);
260 ctl_fatal("value %s on -t or --timeout is invalid", optarg);
265 TABLE_OPTION_HANDLERS(&table_style)
266 STREAM_SSL_OPTION_HANDLERS
278 db = nbctl_default_db();
281 for (i = n_global_long_options; options[i].name; i++) {
282 free(CONST_CAST(char *, options[i].name));
291 %s: OVN northbound DB management utility\n\
292 usage: %s [OPTIONS] COMMAND [ARG...]\n\
295 show print overview of database contents\n\
296 show SWITCH print overview of database contents for SWITCH\n\
297 show ROUTER print overview of database contents for ROUTER\n\
299 Logical switch commands:\n\
300 ls-add [SWITCH] create a logical switch named SWITCH\n\
301 ls-del SWITCH delete SWITCH and all its ports\n\
302 ls-list print the names of all logical switches\n\
305 acl-add SWITCH DIRECTION PRIORITY MATCH ACTION [log]\n\
306 add an ACL to SWITCH\n\
307 acl-del SWITCH [DIRECTION [PRIORITY MATCH]]\n\
308 remove ACLs from SWITCH\n\
309 acl-list SWITCH print ACLs for SWITCH\n\
311 Logical switch port commands:\n\
312 lsp-add SWITCH PORT add logical port PORT on SWITCH\n\
313 lsp-add SWITCH PORT PARENT TAG\n\
314 add logical port PORT on SWITCH with PARENT\n\
316 lsp-del PORT delete PORT from its attached switch\n\
317 lsp-list SWITCH print the names of all logical ports on SWITCH\n\
318 lsp-get-parent PORT get the parent of PORT if set\n\
319 lsp-get-tag PORT get the PORT's tag if set\n\
320 lsp-set-addresses PORT [ADDRESS]...\n\
321 set MAC or MAC+IP addresses for PORT.\n\
322 lsp-get-addresses PORT get a list of MAC addresses on PORT\n\
323 lsp-set-port-security PORT [ADDRS]...\n\
324 set port security addresses for PORT.\n\
325 lsp-get-port-security PORT get PORT's port security addresses\n\
326 lsp-get-up PORT get state of PORT ('up' or 'down')\n\
327 lsp-set-enabled PORT STATE\n\
328 set administrative state PORT\n\
329 ('enabled' or 'disabled')\n\
330 lsp-get-enabled PORT get administrative state PORT\n\
331 ('enabled' or 'disabled')\n\
332 lsp-set-type PORT TYPE set the type for PORT\n\
333 lsp-get-type PORT get the type for PORT\n\
334 lsp-set-options PORT KEY=VALUE [KEY=VALUE]...\n\
335 set options related to the type of PORT\n\
336 lsp-get-options PORT get the type specific options for PORT\n\
338 Logical router commands:\n\
339 lr-add [ROUTER] create a logical router named ROUTER\n\
340 lr-del ROUTER delete ROUTER and all its ports\n\
341 lr-list print the names of all logical routers\n\
343 Logical router port commands:\n\
344 lrp-add ROUTER PORT MAC NETWORK... [peer=PEER]\n\
345 add logical port PORT on ROUTER\n\
346 lrp-del PORT delete PORT from its attached router\n\
347 lrp-list ROUTER print the names of all ports on ROUTER\n\
348 lrp-set-enabled PORT STATE\n\
349 set administrative state PORT\n\
350 ('enabled' or 'disabled')\n\
351 lrp-get-enabled PORT get administrative state PORT\n\
352 ('enabled' or 'disabled')\n\
355 lr-route-add ROUTER PREFIX NEXTHOP [PORT]\n\
356 add a route to ROUTER\n\
357 lr-route-del ROUTER [PREFIX]\n\
358 remove routes from ROUTER\n\
359 lr-route-list ROUTER print routes for ROUTER\n\
364 --db=DATABASE connect to DATABASE\n\
366 -t, --timeout=SECS wait at most SECS seconds\n\
367 --dry-run do not commit changes to database\n\
368 --oneline print exactly one line of output per command\n",
369 program_name, program_name, ctl_get_db_cmd_usage(), nbctl_default_db());
372 --no-syslog equivalent to --verbose=nbctl:syslog:warn\n");
375 -h, --help display this help message\n\
376 -V, --version display version information\n");
381 /* Find a logical router given its id. */
382 static const struct nbrec_logical_router *
383 lr_by_name_or_uuid(struct ctl_context *ctx, const char *id,
386 const struct nbrec_logical_router *lr = NULL;
387 bool is_uuid = false;
390 if (uuid_from_string(&lr_uuid, id)) {
392 lr = nbrec_logical_router_get_for_uuid(ctx->idl, &lr_uuid);
396 const struct nbrec_logical_router *iter;
398 NBREC_LOGICAL_ROUTER_FOR_EACH(iter, ctx->idl) {
399 if (strcmp(iter->name, id)) {
403 ctl_fatal("Multiple logical routers named '%s'. "
410 if (!lr && must_exist) {
411 ctl_fatal("%s: router %s not found", id, is_uuid ? "UUID" : "name");
417 static const struct nbrec_logical_switch *
418 ls_by_name_or_uuid(struct ctl_context *ctx, const char *id, bool must_exist)
420 const struct nbrec_logical_switch *ls = NULL;
423 bool is_uuid = uuid_from_string(&ls_uuid, id);
425 ls = nbrec_logical_switch_get_for_uuid(ctx->idl, &ls_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 (!ls && must_exist) {
444 ctl_fatal("%s: switch %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_ls(const struct nbrec_logical_switch *ls, struct ds *s)
472 ds_put_format(s, " switch "UUID_FMT" (%s)\n",
473 UUID_ARGS(&ls->header_.uuid), ls->name);
475 for (size_t i = 0; i < ls->n_ports; i++) {
476 const struct nbrec_logical_switch_port *lsp = ls->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 *ls;
502 if (ctx->argc == 2) {
503 ls = ls_by_name_or_uuid(ctx, ctx->argv[1], false);
505 print_ls(ls, &ctx->output);
508 NBREC_LOGICAL_SWITCH_FOR_EACH(ls, ctx->idl) {
509 print_ls(ls, &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_ls_add(struct ctl_context *ctx)
529 const char *ls_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 *ls;
540 NBREC_LOGICAL_SWITCH_FOR_EACH (ls, ctx->idl) {
541 if (!strcmp(ls->name, ls_name)) {
545 ctl_fatal("%s: a switch 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 *ls;
557 ls = nbrec_logical_switch_insert(ctx->txn);
559 nbrec_logical_switch_set_name(ls, ls_name);
564 nbctl_ls_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 *ls;
570 ls = ls_by_name_or_uuid(ctx, id, must_exist);
575 nbrec_logical_switch_delete(ls);
579 nbctl_ls_list(struct ctl_context *ctx)
581 const struct nbrec_logical_switch *ls;
582 struct smap lswitches;
584 smap_init(&lswitches);
585 NBREC_LOGICAL_SWITCH_FOR_EACH(ls, ctx->idl) {
586 smap_add_format(&lswitches, ls->name, UUID_FMT " (%s)",
587 UUID_ARGS(&ls->header_.uuid), ls->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 logical switch that contains 'lsp'. */
626 static const struct nbrec_logical_switch *
627 lsp_to_ls(const struct ovsdb_idl *idl,
628 const struct nbrec_logical_switch_port *lsp)
630 const struct nbrec_logical_switch *ls;
631 NBREC_LOGICAL_SWITCH_FOR_EACH (ls, idl) {
632 for (size_t i = 0; i < ls->n_ports; i++) {
633 if (ls->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 ls_get_name(const struct nbrec_logical_switch *ls,
646 char uuid_s[UUID_LEN + 1], size_t uuid_s_size)
651 snprintf(uuid_s, uuid_s_size, UUID_FMT, UUID_ARGS(&ls->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 *ls;
661 ls = ls_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_ls(ctx->idl, lsp);
691 char uuid_s[UUID_LEN + 1];
692 ctl_fatal("%s: port already exists but in switch %s", lsp_name,
693 ls_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(ls);
732 struct nbrec_logical_switch_port **new_ports = xmalloc(sizeof *new_ports *
734 memcpy(new_ports, ls->ports, sizeof *new_ports * ls->n_ports);
735 new_ports[ls->n_ports] = CONST_CAST(struct nbrec_logical_switch_port *,
737 nbrec_logical_switch_set_ports(ls, new_ports, ls->n_ports + 1);
741 /* Removes logical switch port 'ls->ports[idx]'. */
743 remove_lsp(const struct nbrec_logical_switch *ls, size_t idx)
745 const struct nbrec_logical_switch_port *lsp = ls->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(ls->ports, sizeof *new_ports * ls->n_ports);
752 new_ports[idx] = new_ports[ls->n_ports - 1];
753 nbrec_logical_switch_verify_ports(ls);
754 nbrec_logical_switch_set_ports(ls, new_ports, ls->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 *ls;
777 NBREC_LOGICAL_SWITCH_FOR_EACH (ls, ctx->idl) {
778 for (size_t i = 0; i < ls->n_ports; i++) {
779 if (ls->ports[i] == lsp) {
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 *ls;
799 ls = ls_by_name_or_uuid(ctx, id, true);
802 for (i = 0; i < ls->n_ports; i++) {
803 const struct nbrec_logical_switch_port *lsp = ls->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 *ls;
1063 const struct nbrec_acl **acls;
1066 ls = ls_by_name_or_uuid(ctx, ctx->argv[1], true);
1068 acls = xmalloc(sizeof *acls * ls->n_acls);
1069 for (i = 0; i < ls->n_acls; i++) {
1070 acls[i] = ls->acls[i];
1073 qsort(acls, ls->n_acls, sizeof *acls, acl_cmp);
1075 for (i = 0; i < ls->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 *ls;
1114 const char *action = ctx->argv[5];
1116 ls = ls_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(ls);
1141 struct nbrec_acl **new_acls = xmalloc(sizeof *new_acls * (ls->n_acls + 1));
1142 memcpy(new_acls, ls->acls, sizeof *new_acls * ls->n_acls);
1143 new_acls[ls->n_acls] = acl;
1144 nbrec_logical_switch_set_acls(ls, new_acls, ls->n_acls + 1);
1149 nbctl_acl_del(struct ctl_context *ctx)
1151 const struct nbrec_logical_switch *ls;
1152 ls = ls_by_name_or_uuid(ctx, ctx->argv[1], true);
1154 if (ctx->argc != 2 && ctx->argc != 3 && ctx->argc != 5) {
1155 ctl_fatal("cannot specify priority without match");
1158 if (ctx->argc == 2) {
1159 /* If direction, priority, and match are not specified, delete
1161 nbrec_logical_switch_verify_acls(ls);
1162 nbrec_logical_switch_set_acls(ls, NULL, 0);
1166 const char *direction = parse_direction(ctx->argv[2]);
1168 /* If priority and match are not specified, delete all ACLs with the
1169 * specified direction. */
1170 if (ctx->argc == 3) {
1171 struct nbrec_acl **new_acls = xmalloc(sizeof *new_acls * ls->n_acls);
1174 for (size_t i = 0; i < ls->n_acls; i++) {
1175 if (strcmp(direction, ls->acls[i]->direction)) {
1176 new_acls[n_acls++] = ls->acls[i];
1180 nbrec_logical_switch_verify_acls(ls);
1181 nbrec_logical_switch_set_acls(ls, new_acls, n_acls);
1186 int64_t priority = parse_priority(ctx->argv[3]);
1188 /* Remove the matching rule. */
1189 for (size_t i = 0; i < ls->n_acls; i++) {
1190 struct nbrec_acl *acl = ls->acls[i];
1192 if (priority == acl->priority && !strcmp(ctx->argv[4], acl->match) &&
1193 !strcmp(direction, acl->direction)) {
1194 struct nbrec_acl **new_acls
1195 = xmemdup(ls->acls, sizeof *new_acls * ls->n_acls);
1196 new_acls[i] = ls->acls[ls->n_acls - 1];
1197 nbrec_logical_switch_verify_acls(ls);
1198 nbrec_logical_switch_set_acls(ls, new_acls,
1207 nbctl_lr_add(struct ctl_context *ctx)
1209 const char *lr_name = ctx->argc == 2 ? ctx->argv[1] : NULL;
1211 bool may_exist = shash_find(&ctx->options, "--may-exist") != NULL;
1212 bool add_duplicate = shash_find(&ctx->options, "--add-duplicate") != NULL;
1213 if (may_exist && add_duplicate) {
1214 ctl_fatal("--may-exist and --add-duplicate may not be used together");
1218 if (!add_duplicate) {
1219 const struct nbrec_logical_router *lr;
1220 NBREC_LOGICAL_ROUTER_FOR_EACH (lr, ctx->idl) {
1221 if (!strcmp(lr->name, lr_name)) {
1225 ctl_fatal("%s: a router with this name already exists",
1230 } else if (may_exist) {
1231 ctl_fatal("--may-exist requires specifying a name");
1232 } else if (add_duplicate) {
1233 ctl_fatal("--add-duplicate requires specifying a name");
1236 struct nbrec_logical_router *lr;
1237 lr = nbrec_logical_router_insert(ctx->txn);
1239 nbrec_logical_router_set_name(lr, lr_name);
1244 nbctl_lr_del(struct ctl_context *ctx)
1246 bool must_exist = !shash_find(&ctx->options, "--if-exists");
1247 const char *id = ctx->argv[1];
1248 const struct nbrec_logical_router *lr;
1250 lr = lr_by_name_or_uuid(ctx, id, must_exist);
1255 nbrec_logical_router_delete(lr);
1259 nbctl_lr_list(struct ctl_context *ctx)
1261 const struct nbrec_logical_router *lr;
1265 NBREC_LOGICAL_ROUTER_FOR_EACH(lr, ctx->idl) {
1266 smap_add_format(&lrs, lr->name, UUID_FMT " (%s)",
1267 UUID_ARGS(&lr->header_.uuid), lr->name);
1269 const struct smap_node **nodes = smap_sort(&lrs);
1270 for (size_t i = 0; i < smap_count(&lrs); i++) {
1271 const struct smap_node *node = nodes[i];
1272 ds_put_format(&ctx->output, "%s\n", node->value);
1278 /* The caller must free the returned string. */
1280 normalize_ipv4_prefix(ovs_be32 ipv4, unsigned int plen)
1282 ovs_be32 network = ipv4 & be32_prefix_mask(plen);
1284 return xasprintf(IP_FMT, IP_ARGS(network));
1286 return xasprintf(IP_FMT"/%d", IP_ARGS(network), plen);
1290 /* The caller must free the returned string. */
1292 normalize_ipv6_prefix(struct in6_addr ipv6, unsigned int plen)
1294 char network_s[INET6_ADDRSTRLEN];
1296 struct in6_addr mask = ipv6_create_mask(plen);
1297 struct in6_addr network = ipv6_addr_bitand(&ipv6, &mask);
1299 inet_ntop(AF_INET6, &network, network_s, INET6_ADDRSTRLEN);
1301 return xasprintf("%s", network_s);
1303 return xasprintf("%s/%d", network_s, plen);
1307 /* The caller must free the returned string. */
1309 normalize_prefix_str(const char *orig_prefix)
1315 error = ip_parse_cidr(orig_prefix, &ipv4, &plen);
1317 return normalize_ipv4_prefix(ipv4, plen);
1319 struct in6_addr ipv6;
1322 error = ipv6_parse_cidr(orig_prefix, &ipv6, &plen);
1327 return normalize_ipv6_prefix(ipv6, plen);
1332 nbctl_lr_route_add(struct ctl_context *ctx)
1334 const struct nbrec_logical_router *lr;
1335 lr = lr_by_name_or_uuid(ctx, ctx->argv[1], true);
1336 char *prefix, *next_hop;
1338 prefix = normalize_prefix_str(ctx->argv[2]);
1340 ctl_fatal("bad prefix argument: %s", ctx->argv[2]);
1343 next_hop = normalize_prefix_str(ctx->argv[3]);
1345 ctl_fatal("bad next hop argument: %s", ctx->argv[3]);
1348 if (strchr(prefix, '.')) {
1350 if (!ip_parse(ctx->argv[3], &hop_ipv4)) {
1351 ctl_fatal("bad IPv4 nexthop argument: %s", ctx->argv[3]);
1354 struct in6_addr hop_ipv6;
1355 if (!ipv6_parse(ctx->argv[3], &hop_ipv6)) {
1356 ctl_fatal("bad IPv6 nexthop argument: %s", ctx->argv[3]);
1360 bool may_exist = shash_find(&ctx->options, "--may-exist") != NULL;
1361 for (int i = 0; i < lr->n_static_routes; i++) {
1362 const struct nbrec_logical_router_static_route *route
1363 = lr->static_routes[i];
1366 rt_prefix = normalize_prefix_str(lr->static_routes[i]->ip_prefix);
1368 /* Ignore existing prefix we couldn't parse. */
1372 if (strcmp(rt_prefix, prefix)) {
1378 ctl_fatal("duplicate prefix: %s", prefix);
1381 /* Update the next hop for an existing route. */
1382 nbrec_logical_router_verify_static_routes(lr);
1383 nbrec_logical_router_static_route_verify_ip_prefix(route);
1384 nbrec_logical_router_static_route_verify_nexthop(route);
1385 nbrec_logical_router_static_route_set_ip_prefix(route, prefix);
1386 nbrec_logical_router_static_route_set_nexthop(route, next_hop);
1387 if (ctx->argc == 5) {
1388 nbrec_logical_router_static_route_set_output_port(route,
1397 struct nbrec_logical_router_static_route *route;
1398 route = nbrec_logical_router_static_route_insert(ctx->txn);
1399 nbrec_logical_router_static_route_set_ip_prefix(route, prefix);
1400 nbrec_logical_router_static_route_set_nexthop(route, next_hop);
1401 if (ctx->argc == 5) {
1402 nbrec_logical_router_static_route_set_output_port(route, ctx->argv[4]);
1405 nbrec_logical_router_verify_static_routes(lr);
1406 struct nbrec_logical_router_static_route **new_routes
1407 = xmalloc(sizeof *new_routes * (lr->n_static_routes + 1));
1408 memcpy(new_routes, lr->static_routes,
1409 sizeof *new_routes * lr->n_static_routes);
1410 new_routes[lr->n_static_routes] = route;
1411 nbrec_logical_router_set_static_routes(lr, new_routes,
1412 lr->n_static_routes + 1);
1419 nbctl_lr_route_del(struct ctl_context *ctx)
1421 const struct nbrec_logical_router *lr;
1422 lr = lr_by_name_or_uuid(ctx, ctx->argv[1], true);
1424 if (ctx->argc == 2) {
1425 /* If a prefix is not specified, delete all routes. */
1426 nbrec_logical_router_set_static_routes(lr, NULL, 0);
1430 char *prefix = normalize_prefix_str(ctx->argv[2]);
1432 ctl_fatal("bad prefix argument: %s", ctx->argv[2]);
1435 for (int i = 0; i < lr->n_static_routes; i++) {
1436 char *rt_prefix = normalize_prefix_str(lr->static_routes[i]->ip_prefix);
1438 /* Ignore existing prefix we couldn't parse. */
1442 if (!strcmp(prefix, rt_prefix)) {
1443 struct nbrec_logical_router_static_route **new_routes
1444 = xmemdup(lr->static_routes,
1445 sizeof *new_routes * lr->n_static_routes);
1447 new_routes[i] = lr->static_routes[lr->n_static_routes - 1];
1448 nbrec_logical_router_verify_static_routes(lr);
1449 nbrec_logical_router_set_static_routes(lr, new_routes,
1450 lr->n_static_routes - 1);
1459 if (!shash_find(&ctx->options, "--if-exists")) {
1460 ctl_fatal("no matching prefix: %s", prefix);
1465 static const struct nbrec_logical_router_port *
1466 lrp_by_name_or_uuid(struct ctl_context *ctx, const char *id, bool must_exist)
1468 const struct nbrec_logical_router_port *lrp = NULL;
1470 struct uuid lrp_uuid;
1471 bool is_uuid = uuid_from_string(&lrp_uuid, id);
1473 lrp = nbrec_logical_router_port_get_for_uuid(ctx->idl, &lrp_uuid);
1477 NBREC_LOGICAL_ROUTER_PORT_FOR_EACH(lrp, ctx->idl) {
1478 if (!strcmp(lrp->name, id)) {
1484 if (!lrp && must_exist) {
1485 ctl_fatal("%s: port %s not found", id, is_uuid ? "UUID" : "name");
1491 /* Returns the logical router that contains 'lrp'. */
1492 static const struct nbrec_logical_router *
1493 lrp_to_lr(const struct ovsdb_idl *idl,
1494 const struct nbrec_logical_router_port *lrp)
1496 const struct nbrec_logical_router *lr;
1497 NBREC_LOGICAL_ROUTER_FOR_EACH (lr, idl) {
1498 for (size_t i = 0; i < lr->n_ports; i++) {
1499 if (lr->ports[i] == lrp) {
1505 /* Can't happen because of the database schema */
1506 ctl_fatal("port %s is not part of any logical router",
1511 lr_get_name(const struct nbrec_logical_router *lr, char uuid_s[UUID_LEN + 1],
1517 snprintf(uuid_s, uuid_s_size, UUID_FMT, UUID_ARGS(&lr->header_.uuid));
1522 nbctl_lrp_add(struct ctl_context *ctx)
1524 bool may_exist = shash_find(&ctx->options, "--may-exist") != NULL;
1526 const struct nbrec_logical_router *lr;
1527 lr = lr_by_name_or_uuid(ctx, ctx->argv[1], true);
1529 const char *lrp_name = ctx->argv[2];
1530 const char *mac = ctx->argv[3];
1531 const char **networks = (const char **) &ctx->argv[4];
1533 int n_networks = ctx->argc - 4;
1534 for (int i = 4; i < ctx->argc; i++) {
1535 if (strchr(ctx->argv[i], '=')) {
1542 ctl_fatal("%s: router port requires specifying a network", lrp_name);
1545 char **settings = (char **) &ctx->argv[n_networks + 4];
1546 int n_settings = ctx->argc - 4 - n_networks;
1548 const struct nbrec_logical_router_port *lrp;
1549 lrp = lrp_by_name_or_uuid(ctx, lrp_name, false);
1552 ctl_fatal("%s: a port with this name already exists",
1556 const struct nbrec_logical_router *bound_lr;
1557 bound_lr = lrp_to_lr(ctx->idl, lrp);
1558 if (bound_lr != lr) {
1559 char uuid_s[UUID_LEN + 1];
1560 ctl_fatal("%s: port already exists but in router %s", lrp_name,
1561 lr_get_name(bound_lr, uuid_s, sizeof uuid_s));
1564 if (strcmp(mac, lrp->mac)) {
1565 ctl_fatal("%s: port already exists with mac %s", lrp_name,
1569 struct sset new_networks = SSET_INITIALIZER(&new_networks);
1570 for (int i = 0; i < n_networks; i++) {
1571 sset_add(&new_networks, networks[i]);
1574 struct sset orig_networks = SSET_INITIALIZER(&orig_networks);
1575 sset_add_array(&orig_networks, lrp->networks, lrp->n_networks);
1577 if (!sset_equals(&orig_networks, &new_networks)) {
1578 ctl_fatal("%s: port already exists with different network",
1582 sset_destroy(&orig_networks);
1583 sset_destroy(&new_networks);
1585 /* Special-case sanity-check of peer ports. */
1586 const char *peer = NULL;
1587 for (int i = 0; i < n_settings; i++) {
1588 if (!strncmp(settings[i], "peer=", 5)) {
1589 peer = settings[i] + 5;
1594 if ((!peer != !lrp->peer) ||
1595 (lrp->peer && strcmp(peer, lrp->peer))) {
1596 ctl_fatal("%s: port already exists with mismatching peer",
1604 if (!ovs_scan(mac, ETH_ADDR_SCAN_FMT, ETH_ADDR_SCAN_ARGS(ea))) {
1605 ctl_fatal("%s: invalid mac address %s", lrp_name, mac);
1608 for (int i = 0; i < n_networks; i++) {
1611 char *error = ip_parse_cidr(networks[i], &ipv4, &plen);
1614 struct in6_addr ipv6;
1615 error = ipv6_parse_cidr(networks[i], &ipv6, &plen);
1618 ctl_fatal("%s: invalid network address: %s", lrp_name,
1624 /* Create the logical port. */
1625 lrp = nbrec_logical_router_port_insert(ctx->txn);
1626 nbrec_logical_router_port_set_name(lrp, lrp_name);
1627 nbrec_logical_router_port_set_mac(lrp, mac);
1628 nbrec_logical_router_port_set_networks(lrp, networks, n_networks);
1630 for (int i = 0; i < n_settings; i++) {
1631 ctl_set_column("Logical_Router_Port", &lrp->header_, settings[i],
1635 /* Insert the logical port into the logical router. */
1636 nbrec_logical_router_verify_ports(lr);
1637 struct nbrec_logical_router_port **new_ports = xmalloc(sizeof *new_ports *
1639 memcpy(new_ports, lr->ports, sizeof *new_ports * lr->n_ports);
1640 new_ports[lr->n_ports] = CONST_CAST(struct nbrec_logical_router_port *,
1642 nbrec_logical_router_set_ports(lr, new_ports, lr->n_ports + 1);
1646 /* Removes logical router port 'lr->ports[idx]'. */
1648 remove_lrp(const struct nbrec_logical_router *lr, size_t idx)
1650 const struct nbrec_logical_router_port *lrp = lr->ports[idx];
1652 /* First remove 'lrp' from the array of ports. This is what will
1653 * actually cause the logical port to be deleted when the transaction is
1654 * sent to the database server (due to garbage collection). */
1655 struct nbrec_logical_router_port **new_ports
1656 = xmemdup(lr->ports, sizeof *new_ports * lr->n_ports);
1657 new_ports[idx] = new_ports[lr->n_ports - 1];
1658 nbrec_logical_router_verify_ports(lr);
1659 nbrec_logical_router_set_ports(lr, new_ports, lr->n_ports - 1);
1662 /* Delete 'lrp' from the IDL. This won't have a real effect on
1663 * the database server (the IDL will suppress it in fact) but it
1664 * means that it won't show up when we iterate with
1665 * NBREC_LOGICAL_ROUTER_PORT_FOR_EACH later. */
1666 nbrec_logical_router_port_delete(lrp);
1670 nbctl_lrp_del(struct ctl_context *ctx)
1672 bool must_exist = !shash_find(&ctx->options, "--if-exists");
1673 const struct nbrec_logical_router_port *lrp;
1675 lrp = lrp_by_name_or_uuid(ctx, ctx->argv[1], must_exist);
1680 /* Find the router that contains 'lrp', then delete it. */
1681 const struct nbrec_logical_router *lr;
1682 NBREC_LOGICAL_ROUTER_FOR_EACH (lr, ctx->idl) {
1683 for (size_t i = 0; i < lr->n_ports; i++) {
1684 if (lr->ports[i] == lrp) {
1691 /* Can't happen because of the database schema. */
1692 ctl_fatal("logical port %s is not part of any logical router",
1696 /* Print a list of logical router ports. */
1698 nbctl_lrp_list(struct ctl_context *ctx)
1700 const char *id = ctx->argv[1];
1701 const struct nbrec_logical_router *lr;
1705 lr = lr_by_name_or_uuid(ctx, id, true);
1708 for (i = 0; i < lr->n_ports; i++) {
1709 const struct nbrec_logical_router_port *lrp = lr->ports[i];
1710 smap_add_format(&lrps, lrp->name, UUID_FMT " (%s)",
1711 UUID_ARGS(&lrp->header_.uuid), lrp->name);
1713 const struct smap_node **nodes = smap_sort(&lrps);
1714 for (i = 0; i < smap_count(&lrps); i++) {
1715 const struct smap_node *node = nodes[i];
1716 ds_put_format(&ctx->output, "%s\n", node->value);
1718 smap_destroy(&lrps);
1722 /* Set the logical router port admin-enabled state. */
1724 nbctl_lrp_set_enabled(struct ctl_context *ctx)
1726 const char *id = ctx->argv[1];
1727 const char *state = ctx->argv[2];
1728 const struct nbrec_logical_router_port *lrp;
1730 lrp = lrp_by_name_or_uuid(ctx, id, true);
1735 bool enabled = parse_enabled(state);
1736 nbrec_logical_router_port_set_enabled(lrp, &enabled, 1);
1739 /* Print admin-enabled state for logical router port. */
1741 nbctl_lrp_get_enabled(struct ctl_context *ctx)
1743 const char *id = ctx->argv[1];
1744 const struct nbrec_logical_router_port *lrp;
1746 lrp = lrp_by_name_or_uuid(ctx, id, true);
1751 ds_put_format(&ctx->output, "%s\n",
1753 *lrp->enabled ? "enabled" : "disabled");
1759 const struct nbrec_logical_router_static_route *route;
1763 ipv4_route_cmp(const void *route1_, const void *route2_)
1765 const struct ipv4_route *route1p = route1_;
1766 const struct ipv4_route *route2p = route2_;
1768 if (route1p->plen != route2p->plen) {
1769 return route1p->plen > route2p->plen ? -1 : 1;
1770 } else if (route1p->addr != route2p->addr) {
1771 return ntohl(route1p->addr) < ntohl(route2p->addr) ? -1 : 1;
1779 struct in6_addr addr;
1780 const struct nbrec_logical_router_static_route *route;
1784 ipv6_route_cmp(const void *route1_, const void *route2_)
1786 const struct ipv6_route *route1p = route1_;
1787 const struct ipv6_route *route2p = route2_;
1789 if (route1p->plen != route2p->plen) {
1790 return route1p->plen > route2p->plen ? -1 : 1;
1792 return memcmp(&route1p->addr, &route2p->addr, sizeof(route1p->addr));
1796 print_route(const struct nbrec_logical_router_static_route *route, struct ds *s)
1799 char *prefix = normalize_prefix_str(route->ip_prefix);
1800 char *next_hop = normalize_prefix_str(route->nexthop);
1801 ds_put_format(s, "%25s %25s", prefix, next_hop);
1805 if (route->output_port) {
1806 ds_put_format(s, " %s", route->output_port);
1808 ds_put_char(s, '\n');
1812 nbctl_lr_route_list(struct ctl_context *ctx)
1814 const struct nbrec_logical_router *lr;
1815 struct ipv4_route *ipv4_routes;
1816 struct ipv6_route *ipv6_routes;
1817 size_t n_ipv4_routes = 0;
1818 size_t n_ipv6_routes = 0;
1820 lr = lr_by_name_or_uuid(ctx, ctx->argv[1], true);
1822 ipv4_routes = xmalloc(sizeof *ipv4_routes * lr->n_static_routes);
1823 ipv6_routes = xmalloc(sizeof *ipv6_routes * lr->n_static_routes);
1825 for (int i = 0; i < lr->n_static_routes; i++) {
1826 const struct nbrec_logical_router_static_route *route
1827 = lr->static_routes[i];
1832 error = ip_parse_cidr(route->ip_prefix, &ipv4, &plen);
1834 ipv4_routes[n_ipv4_routes].plen = plen;
1835 ipv4_routes[n_ipv4_routes].addr = ipv4;
1836 ipv4_routes[n_ipv4_routes].route = route;
1841 struct in6_addr ipv6;
1842 error = ipv6_parse_cidr(route->ip_prefix, &ipv6, &plen);
1844 ipv6_routes[n_ipv6_routes].plen = plen;
1845 ipv6_routes[n_ipv6_routes].addr = ipv6;
1846 ipv6_routes[n_ipv6_routes].route = route;
1849 /* Invalid prefix. */
1850 VLOG_WARN("router "UUID_FMT" (%s) has invalid prefix: %s",
1851 UUID_ARGS(&lr->header_.uuid), lr->name,
1859 qsort(ipv4_routes, n_ipv4_routes, sizeof *ipv4_routes, ipv4_route_cmp);
1860 qsort(ipv6_routes, n_ipv6_routes, sizeof *ipv6_routes, ipv6_route_cmp);
1862 if (n_ipv4_routes) {
1863 ds_put_cstr(&ctx->output, "IPv4 Routes\n");
1865 for (int i = 0; i < n_ipv4_routes; i++) {
1866 print_route(ipv4_routes[i].route, &ctx->output);
1869 if (n_ipv6_routes) {
1870 ds_put_format(&ctx->output, "%sIPv6 Routes\n",
1871 n_ipv4_routes ? "\n" : "");
1873 for (int i = 0; i < n_ipv6_routes; i++) {
1874 print_route(ipv6_routes[i].route, &ctx->output);
1881 static const struct ctl_table_class tables[] = {
1882 {&nbrec_table_logical_switch,
1883 {{&nbrec_table_logical_switch, &nbrec_logical_switch_col_name, NULL},
1884 {NULL, NULL, NULL}}},
1886 {&nbrec_table_logical_switch_port,
1887 {{&nbrec_table_logical_switch_port, &nbrec_logical_switch_port_col_name,
1889 {NULL, NULL, NULL}}},
1892 {{NULL, NULL, NULL},
1893 {NULL, NULL, NULL}}},
1895 {&nbrec_table_load_balancer,
1896 {{NULL, NULL, NULL},
1897 {NULL, NULL, NULL}}},
1899 {&nbrec_table_logical_router,
1900 {{&nbrec_table_logical_router, &nbrec_logical_router_col_name, NULL},
1901 {NULL, NULL, NULL}}},
1903 {&nbrec_table_logical_router_port,
1904 {{&nbrec_table_logical_router_port, &nbrec_logical_router_port_col_name,
1906 {NULL, NULL, NULL}}},
1908 {&nbrec_table_logical_router_static_route,
1909 {{&nbrec_table_logical_router_static_route, NULL,
1911 {NULL, NULL, NULL}}},
1914 {{&nbrec_table_nat, NULL,
1916 {NULL, NULL, NULL}}},
1918 {&nbrec_table_address_set,
1919 {{&nbrec_table_address_set, &nbrec_address_set_col_name, NULL},
1920 {NULL, NULL, NULL}}},
1922 {NULL, {{NULL, NULL, NULL}, {NULL, NULL, NULL}}}
1926 run_prerequisites(struct ctl_command *commands, size_t n_commands,
1927 struct ovsdb_idl *idl)
1929 struct ctl_command *c;
1931 for (c = commands; c < &commands[n_commands]; c++) {
1932 if (c->syntax->prerequisites) {
1933 struct ctl_context ctx;
1935 ds_init(&c->output);
1938 ctl_context_init(&ctx, c, idl, NULL, NULL, NULL);
1939 (c->syntax->prerequisites)(&ctx);
1940 ctl_context_done(&ctx, c);
1942 ovs_assert(!c->output.string);
1943 ovs_assert(!c->table);
1949 do_nbctl(const char *args, struct ctl_command *commands, size_t n_commands,
1950 struct ovsdb_idl *idl)
1952 struct ovsdb_idl_txn *txn;
1953 enum ovsdb_idl_txn_status status;
1954 struct ovsdb_symbol_table *symtab;
1955 struct ctl_context ctx;
1956 struct ctl_command *c;
1957 struct shash_node *node;
1960 txn = the_idl_txn = ovsdb_idl_txn_create(idl);
1962 ovsdb_idl_txn_set_dry_run(txn);
1965 ovsdb_idl_txn_add_comment(txn, "ovs-nbctl: %s", args);
1967 symtab = ovsdb_symbol_table_create();
1968 for (c = commands; c < &commands[n_commands]; c++) {
1969 ds_init(&c->output);
1972 ctl_context_init(&ctx, NULL, idl, txn, symtab, NULL);
1973 for (c = commands; c < &commands[n_commands]; c++) {
1974 ctl_context_init_command(&ctx, c);
1975 if (c->syntax->run) {
1976 (c->syntax->run)(&ctx);
1978 ctl_context_done_command(&ctx, c);
1980 if (ctx.try_again) {
1981 ctl_context_done(&ctx, NULL);
1985 ctl_context_done(&ctx, NULL);
1987 SHASH_FOR_EACH (node, &symtab->sh) {
1988 struct ovsdb_symbol *symbol = node->data;
1989 if (!symbol->created) {
1990 ctl_fatal("row id \"%s\" is referenced but never created (e.g. "
1991 "with \"-- --id=%s create ...\")",
1992 node->name, node->name);
1994 if (!symbol->strong_ref) {
1995 if (!symbol->weak_ref) {
1996 VLOG_WARN("row id \"%s\" was created but no reference to it "
1997 "was inserted, so it will not actually appear in "
1998 "the database", node->name);
2000 VLOG_WARN("row id \"%s\" was created but only a weak "
2001 "reference to it was inserted, so it will not "
2002 "actually appear in the database", node->name);
2007 status = ovsdb_idl_txn_commit_block(txn);
2008 if (status == TXN_UNCHANGED || status == TXN_SUCCESS) {
2009 for (c = commands; c < &commands[n_commands]; c++) {
2010 if (c->syntax->postprocess) {
2011 ctl_context_init(&ctx, c, idl, txn, symtab, NULL);
2012 (c->syntax->postprocess)(&ctx);
2013 ctl_context_done(&ctx, c);
2017 error = xstrdup(ovsdb_idl_txn_get_error(txn));
2020 case TXN_UNCOMMITTED:
2021 case TXN_INCOMPLETE:
2025 /* Should not happen--we never call ovsdb_idl_txn_abort(). */
2026 ctl_fatal("transaction aborted");
2036 ctl_fatal("transaction error: %s", error);
2038 case TXN_NOT_LOCKED:
2039 /* Should not happen--we never call ovsdb_idl_set_lock(). */
2040 ctl_fatal("database not locked");
2047 ovsdb_symbol_table_destroy(symtab);
2049 for (c = commands; c < &commands[n_commands]; c++) {
2050 struct ds *ds = &c->output;
2053 table_print(c->table, &table_style);
2054 } else if (oneline) {
2058 for (j = 0; j < ds->length; j++) {
2059 int ch = ds->string[j];
2062 fputs("\\n", stdout);
2066 fputs("\\\\", stdout);
2075 fputs(ds_cstr(ds), stdout);
2077 ds_destroy(&c->output);
2078 table_destroy(c->table);
2081 shash_destroy_free_data(&c->options);
2084 ovsdb_idl_txn_destroy(txn);
2085 ovsdb_idl_destroy(idl);
2090 /* Our transaction needs to be rerun, or a prerequisite was not met. Free
2091 * resources and return so that the caller can try again. */
2093 ovsdb_idl_txn_abort(txn);
2094 ovsdb_idl_txn_destroy(txn);
2097 ovsdb_symbol_table_destroy(symtab);
2098 for (c = commands; c < &commands[n_commands]; c++) {
2099 ds_destroy(&c->output);
2100 table_destroy(c->table);
2107 /* Frees the current transaction and the underlying IDL and then calls
2110 * Freeing the transaction and the IDL is not strictly necessary, but it makes
2111 * for a clean memory leak report from valgrind in the normal case. That makes
2112 * it easier to notice real memory leaks. */
2114 nbctl_exit(int status)
2117 ovsdb_idl_txn_abort(the_idl_txn);
2118 ovsdb_idl_txn_destroy(the_idl_txn);
2120 ovsdb_idl_destroy(the_idl);
2124 static const struct ctl_command_syntax nbctl_commands[] = {
2125 { "show", 0, 1, "[SWITCH]", NULL, nbctl_show, NULL, "", RO },
2127 /* logical switch commands. */
2128 { "ls-add", 0, 1, "[SWITCH]", NULL, nbctl_ls_add, NULL,
2129 "--may-exist,--add-duplicate", RW },
2130 { "ls-del", 1, 1, "SWITCH", NULL, nbctl_ls_del, NULL, "--if-exists", RW },
2131 { "ls-list", 0, 0, "", NULL, nbctl_ls_list, NULL, "", RO },
2134 { "acl-add", 5, 5, "SWITCH DIRECTION PRIORITY MATCH ACTION", NULL,
2135 nbctl_acl_add, NULL, "--log", RW },
2136 { "acl-del", 1, 4, "SWITCH [DIRECTION [PRIORITY MATCH]]", NULL,
2137 nbctl_acl_del, NULL, "", RW },
2138 { "acl-list", 1, 1, "SWITCH", NULL, nbctl_acl_list, NULL, "", RO },
2140 /* logical switch port commands. */
2141 { "lsp-add", 2, 4, "SWITCH PORT [PARENT] [TAG]", NULL, nbctl_lsp_add,
2142 NULL, "--may-exist", RW },
2143 { "lsp-del", 1, 1, "PORT", NULL, nbctl_lsp_del, NULL, "--if-exists", RW },
2144 { "lsp-list", 1, 1, "SWITCH", NULL, nbctl_lsp_list, NULL, "", RO },
2145 { "lsp-get-parent", 1, 1, "PORT", NULL, nbctl_lsp_get_parent, NULL,
2147 { "lsp-get-tag", 1, 1, "PORT", NULL, nbctl_lsp_get_tag, NULL, "", RO },
2148 { "lsp-set-addresses", 1, INT_MAX, "PORT [ADDRESS]...", NULL,
2149 nbctl_lsp_set_addresses, NULL, "", RW },
2150 { "lsp-get-addresses", 1, 1, "PORT", NULL, nbctl_lsp_get_addresses, NULL,
2152 { "lsp-set-port-security", 0, INT_MAX, "PORT [ADDRS]...", NULL,
2153 nbctl_lsp_set_port_security, NULL, "", RW },
2154 { "lsp-get-port-security", 1, 1, "PORT", NULL,
2155 nbctl_lsp_get_port_security, NULL, "", RO },
2156 { "lsp-get-up", 1, 1, "PORT", NULL, nbctl_lsp_get_up, NULL, "", RO },
2157 { "lsp-set-enabled", 2, 2, "PORT STATE", NULL, nbctl_lsp_set_enabled,
2159 { "lsp-get-enabled", 1, 1, "PORT", NULL, nbctl_lsp_get_enabled, NULL,
2161 { "lsp-set-type", 2, 2, "PORT TYPE", NULL, nbctl_lsp_set_type, NULL,
2163 { "lsp-get-type", 1, 1, "PORT", NULL, nbctl_lsp_get_type, NULL, "", RO },
2164 { "lsp-set-options", 1, INT_MAX, "PORT KEY=VALUE [KEY=VALUE]...", NULL,
2165 nbctl_lsp_set_options, NULL, "", RW },
2166 { "lsp-get-options", 1, 1, "PORT", NULL, nbctl_lsp_get_options, NULL,
2169 /* logical router commands. */
2170 { "lr-add", 0, 1, "[ROUTER]", NULL, nbctl_lr_add, NULL,
2171 "--may-exist,--add-duplicate", RW },
2172 { "lr-del", 1, 1, "ROUTER", NULL, nbctl_lr_del, NULL, "--if-exists", RW },
2173 { "lr-list", 0, 0, "", NULL, nbctl_lr_list, NULL, "", RO },
2175 /* logical router port commands. */
2176 { "lrp-add", 4, INT_MAX,
2177 "ROUTER PORT MAC NETWORK... [COLUMN[:KEY]=VALUE]...",
2178 NULL, nbctl_lrp_add, NULL, "--may-exist", RW },
2179 { "lrp-del", 1, 1, "PORT", NULL, nbctl_lrp_del, NULL, "--if-exists", RW },
2180 { "lrp-list", 1, 1, "ROUTER", NULL, nbctl_lrp_list, NULL, "", RO },
2181 { "lrp-set-enabled", 2, 2, "PORT STATE", NULL, nbctl_lrp_set_enabled,
2183 { "lrp-get-enabled", 1, 1, "PORT", NULL, nbctl_lrp_get_enabled,
2186 /* logical router route commands. */
2187 { "lr-route-add", 3, 4, "ROUTER PREFIX NEXTHOP [PORT]", NULL,
2188 nbctl_lr_route_add, NULL, "--may-exist", RW },
2189 { "lr-route-del", 1, 2, "ROUTER [PREFIX]", NULL, nbctl_lr_route_del,
2190 NULL, "--if-exists", RW },
2191 { "lr-route-list", 1, 1, "ROUTER", NULL, nbctl_lr_route_list, NULL,
2194 {NULL, 0, 0, NULL, NULL, NULL, NULL, "", RO},
2197 /* Registers nbctl and common db commands. */
2199 nbctl_cmd_init(void)
2201 ctl_init(tables, NULL, nbctl_exit);
2202 ctl_register_commands(nbctl_commands);