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"
26 #include "openvswitch/json.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\"\n", lrp->mac);
465 if (lrp->n_networks) {
466 ds_put_cstr(s, " networks: [");
467 for (size_t j = 0; j < lrp->n_networks; j++) {
468 ds_put_format(s, "%s\"%s\"",
472 ds_put_cstr(s, "]\n");
478 print_ls(const struct nbrec_logical_switch *ls, struct ds *s)
480 ds_put_format(s, " switch "UUID_FMT" (%s)\n",
481 UUID_ARGS(&ls->header_.uuid), ls->name);
483 for (size_t i = 0; i < ls->n_ports; i++) {
484 const struct nbrec_logical_switch_port *lsp = ls->ports[i];
486 ds_put_format(s, " port %s\n", lsp->name);
487 if (lsp->parent_name) {
488 ds_put_format(s, " parent: %s\n", lsp->parent_name);
491 ds_put_format(s, " tag: %"PRIu64"\n", lsp->tag[0]);
493 if (lsp->n_addresses) {
494 ds_put_cstr(s, " addresses: [");
495 for (size_t j = 0; j < lsp->n_addresses; j++) {
496 ds_put_format(s, "%s\"%s\"",
500 ds_put_cstr(s, "]\n");
506 nbctl_show(struct ctl_context *ctx)
508 const struct nbrec_logical_switch *ls;
510 if (ctx->argc == 2) {
511 ls = ls_by_name_or_uuid(ctx, ctx->argv[1], false);
513 print_ls(ls, &ctx->output);
516 NBREC_LOGICAL_SWITCH_FOR_EACH(ls, ctx->idl) {
517 print_ls(ls, &ctx->output);
520 const struct nbrec_logical_router *lr;
522 if (ctx->argc == 2) {
523 lr = lr_by_name_or_uuid(ctx, ctx->argv[1], false);
525 print_lr(lr, &ctx->output);
528 NBREC_LOGICAL_ROUTER_FOR_EACH(lr, ctx->idl) {
529 print_lr(lr, &ctx->output);
535 nbctl_ls_add(struct ctl_context *ctx)
537 const char *ls_name = ctx->argc == 2 ? ctx->argv[1] : NULL;
539 bool may_exist = shash_find(&ctx->options, "--may-exist") != NULL;
540 bool add_duplicate = shash_find(&ctx->options, "--add-duplicate") != NULL;
541 if (may_exist && add_duplicate) {
542 ctl_fatal("--may-exist and --add-duplicate may not be used together");
546 if (!add_duplicate) {
547 const struct nbrec_logical_switch *ls;
548 NBREC_LOGICAL_SWITCH_FOR_EACH (ls, ctx->idl) {
549 if (!strcmp(ls->name, ls_name)) {
553 ctl_fatal("%s: a switch with this name already exists",
558 } else if (may_exist) {
559 ctl_fatal("--may-exist requires specifying a name");
560 } else if (add_duplicate) {
561 ctl_fatal("--add-duplicate requires specifying a name");
564 struct nbrec_logical_switch *ls;
565 ls = nbrec_logical_switch_insert(ctx->txn);
567 nbrec_logical_switch_set_name(ls, ls_name);
572 nbctl_ls_del(struct ctl_context *ctx)
574 bool must_exist = !shash_find(&ctx->options, "--if-exists");
575 const char *id = ctx->argv[1];
576 const struct nbrec_logical_switch *ls;
578 ls = ls_by_name_or_uuid(ctx, id, must_exist);
583 nbrec_logical_switch_delete(ls);
587 nbctl_ls_list(struct ctl_context *ctx)
589 const struct nbrec_logical_switch *ls;
590 struct smap lswitches;
592 smap_init(&lswitches);
593 NBREC_LOGICAL_SWITCH_FOR_EACH(ls, ctx->idl) {
594 smap_add_format(&lswitches, ls->name, UUID_FMT " (%s)",
595 UUID_ARGS(&ls->header_.uuid), ls->name);
597 const struct smap_node **nodes = smap_sort(&lswitches);
598 for (size_t i = 0; i < smap_count(&lswitches); i++) {
599 const struct smap_node *node = nodes[i];
600 ds_put_format(&ctx->output, "%s\n", node->value);
602 smap_destroy(&lswitches);
606 static const struct nbrec_logical_switch_port *
607 lsp_by_name_or_uuid(struct ctl_context *ctx, const char *id,
610 const struct nbrec_logical_switch_port *lsp = NULL;
612 struct uuid lsp_uuid;
613 bool is_uuid = uuid_from_string(&lsp_uuid, id);
615 lsp = nbrec_logical_switch_port_get_for_uuid(ctx->idl, &lsp_uuid);
619 NBREC_LOGICAL_SWITCH_PORT_FOR_EACH(lsp, ctx->idl) {
620 if (!strcmp(lsp->name, id)) {
626 if (!lsp && must_exist) {
627 ctl_fatal("%s: port %s not found", id, is_uuid ? "UUID" : "name");
633 /* Returns the logical switch that contains 'lsp'. */
634 static const struct nbrec_logical_switch *
635 lsp_to_ls(const struct ovsdb_idl *idl,
636 const struct nbrec_logical_switch_port *lsp)
638 const struct nbrec_logical_switch *ls;
639 NBREC_LOGICAL_SWITCH_FOR_EACH (ls, idl) {
640 for (size_t i = 0; i < ls->n_ports; i++) {
641 if (ls->ports[i] == lsp) {
647 /* Can't happen because of the database schema */
648 ctl_fatal("logical port %s is not part of any logical switch",
653 ls_get_name(const struct nbrec_logical_switch *ls,
654 char uuid_s[UUID_LEN + 1], size_t uuid_s_size)
659 snprintf(uuid_s, uuid_s_size, UUID_FMT, UUID_ARGS(&ls->header_.uuid));
664 nbctl_lsp_add(struct ctl_context *ctx)
666 bool may_exist = shash_find(&ctx->options, "--may-exist") != NULL;
668 const struct nbrec_logical_switch *ls;
669 ls = ls_by_name_or_uuid(ctx, ctx->argv[1], true);
671 const char *parent_name;
673 if (ctx->argc == 3) {
676 } else if (ctx->argc == 5) {
678 parent_name = ctx->argv[3];
679 if (!ovs_scan(ctx->argv[4], "%"SCNd64, &tag)
680 || tag < 0 || tag > 4095) {
681 ctl_fatal("%s: invalid tag", ctx->argv[4]);
684 ctl_fatal("lsp-add with parent must also specify a tag");
687 const char *lsp_name = ctx->argv[2];
688 const struct nbrec_logical_switch_port *lsp;
689 lsp = lsp_by_name_or_uuid(ctx, lsp_name, false);
692 ctl_fatal("%s: a port with this name already exists",
696 const struct nbrec_logical_switch *lsw;
697 lsw = lsp_to_ls(ctx->idl, lsp);
699 char uuid_s[UUID_LEN + 1];
700 ctl_fatal("%s: port already exists but in switch %s", lsp_name,
701 ls_get_name(lsw, uuid_s, sizeof uuid_s));
705 if (!lsp->parent_name) {
706 ctl_fatal("%s: port already exists but has no parent",
708 } else if (strcmp(parent_name, lsp->parent_name)) {
709 ctl_fatal("%s: port already exists with different parent %s",
710 lsp_name, lsp->parent_name);
714 ctl_fatal("%s: port already exists but has no tag",
716 } else if (lsp->tag[0] != tag) {
717 ctl_fatal("%s: port already exists with different "
718 "tag %"PRId64, lsp_name, lsp->tag[0]);
721 if (lsp->parent_name) {
722 ctl_fatal("%s: port already exists but has parent %s",
723 lsp_name, lsp->parent_name);
730 /* Create the logical port. */
731 lsp = nbrec_logical_switch_port_insert(ctx->txn);
732 nbrec_logical_switch_port_set_name(lsp, lsp_name);
734 nbrec_logical_switch_port_set_parent_name(lsp, parent_name);
735 nbrec_logical_switch_port_set_tag(lsp, &tag, 1);
738 /* Insert the logical port into the logical switch. */
739 nbrec_logical_switch_verify_ports(ls);
740 struct nbrec_logical_switch_port **new_ports = xmalloc(sizeof *new_ports *
742 memcpy(new_ports, ls->ports, sizeof *new_ports * ls->n_ports);
743 new_ports[ls->n_ports] = CONST_CAST(struct nbrec_logical_switch_port *,
745 nbrec_logical_switch_set_ports(ls, new_ports, ls->n_ports + 1);
749 /* Removes logical switch port 'ls->ports[idx]'. */
751 remove_lsp(const struct nbrec_logical_switch *ls, size_t idx)
753 const struct nbrec_logical_switch_port *lsp = ls->ports[idx];
755 /* First remove 'lsp' from the array of ports. This is what will
756 * actually cause the logical port to be deleted when the transaction is
757 * sent to the database server (due to garbage collection). */
758 struct nbrec_logical_switch_port **new_ports
759 = xmemdup(ls->ports, sizeof *new_ports * ls->n_ports);
760 new_ports[idx] = new_ports[ls->n_ports - 1];
761 nbrec_logical_switch_verify_ports(ls);
762 nbrec_logical_switch_set_ports(ls, new_ports, ls->n_ports - 1);
765 /* Delete 'lsp' from the IDL. This won't have a real effect on the
766 * database server (the IDL will suppress it in fact) but it means that it
767 * won't show up when we iterate with NBREC_LOGICAL_SWITCH_PORT_FOR_EACH
769 nbrec_logical_switch_port_delete(lsp);
773 nbctl_lsp_del(struct ctl_context *ctx)
775 bool must_exist = !shash_find(&ctx->options, "--if-exists");
776 const struct nbrec_logical_switch_port *lsp;
778 lsp = lsp_by_name_or_uuid(ctx, ctx->argv[1], must_exist);
783 /* Find the switch that contains 'lsp', then delete it. */
784 const struct nbrec_logical_switch *ls;
785 NBREC_LOGICAL_SWITCH_FOR_EACH (ls, ctx->idl) {
786 for (size_t i = 0; i < ls->n_ports; i++) {
787 if (ls->ports[i] == lsp) {
794 /* Can't happen because of the database schema. */
795 ctl_fatal("logical port %s is not part of any logical switch",
800 nbctl_lsp_list(struct ctl_context *ctx)
802 const char *id = ctx->argv[1];
803 const struct nbrec_logical_switch *ls;
807 ls = ls_by_name_or_uuid(ctx, id, true);
810 for (i = 0; i < ls->n_ports; i++) {
811 const struct nbrec_logical_switch_port *lsp = ls->ports[i];
812 smap_add_format(&lsps, lsp->name, UUID_FMT " (%s)",
813 UUID_ARGS(&lsp->header_.uuid), lsp->name);
815 const struct smap_node **nodes = smap_sort(&lsps);
816 for (i = 0; i < smap_count(&lsps); i++) {
817 const struct smap_node *node = nodes[i];
818 ds_put_format(&ctx->output, "%s\n", node->value);
825 nbctl_lsp_get_parent(struct ctl_context *ctx)
827 const struct nbrec_logical_switch_port *lsp;
829 lsp = lsp_by_name_or_uuid(ctx, ctx->argv[1], true);
830 if (lsp->parent_name) {
831 ds_put_format(&ctx->output, "%s\n", lsp->parent_name);
836 nbctl_lsp_get_tag(struct ctl_context *ctx)
838 const struct nbrec_logical_switch_port *lsp;
840 lsp = lsp_by_name_or_uuid(ctx, ctx->argv[1], true);
841 if (lsp->n_tag > 0) {
842 ds_put_format(&ctx->output, "%"PRId64"\n", lsp->tag[0]);
847 nbctl_lsp_set_addresses(struct ctl_context *ctx)
849 const char *id = ctx->argv[1];
850 const struct nbrec_logical_switch_port *lsp;
852 lsp = lsp_by_name_or_uuid(ctx, id, true);
855 for (i = 2; i < ctx->argc; i++) {
858 if (strcmp(ctx->argv[i], "unknown")
859 && !ovs_scan(ctx->argv[i], ETH_ADDR_SCAN_FMT,
860 ETH_ADDR_SCAN_ARGS(ea))) {
861 ctl_fatal("%s: Invalid address format. See ovn-nb(5). "
862 "Hint: An Ethernet address must be "
863 "listed before an IP address, together as a single "
864 "argument.", ctx->argv[i]);
868 nbrec_logical_switch_port_set_addresses(lsp,
869 (const char **) ctx->argv + 2, ctx->argc - 2);
873 nbctl_lsp_get_addresses(struct ctl_context *ctx)
875 const char *id = ctx->argv[1];
876 const struct nbrec_logical_switch_port *lsp;
877 struct svec addresses;
881 lsp = lsp_by_name_or_uuid(ctx, id, true);
883 svec_init(&addresses);
884 for (i = 0; i < lsp->n_addresses; i++) {
885 svec_add(&addresses, lsp->addresses[i]);
887 svec_sort(&addresses);
888 SVEC_FOR_EACH(i, mac, &addresses) {
889 ds_put_format(&ctx->output, "%s\n", mac);
891 svec_destroy(&addresses);
895 nbctl_lsp_set_port_security(struct ctl_context *ctx)
897 const char *id = ctx->argv[1];
898 const struct nbrec_logical_switch_port *lsp;
900 lsp = lsp_by_name_or_uuid(ctx, id, true);
901 nbrec_logical_switch_port_set_port_security(lsp,
902 (const char **) ctx->argv + 2, ctx->argc - 2);
906 nbctl_lsp_get_port_security(struct ctl_context *ctx)
908 const char *id = ctx->argv[1];
909 const struct nbrec_logical_switch_port *lsp;
914 lsp = lsp_by_name_or_uuid(ctx, id, true);
916 for (i = 0; i < lsp->n_port_security; i++) {
917 svec_add(&addrs, lsp->port_security[i]);
920 SVEC_FOR_EACH(i, addr, &addrs) {
921 ds_put_format(&ctx->output, "%s\n", addr);
923 svec_destroy(&addrs);
927 nbctl_lsp_get_up(struct ctl_context *ctx)
929 const char *id = ctx->argv[1];
930 const struct nbrec_logical_switch_port *lsp;
932 lsp = lsp_by_name_or_uuid(ctx, id, true);
933 ds_put_format(&ctx->output,
934 "%s\n", (lsp->up && *lsp->up) ? "up" : "down");
938 parse_enabled(const char *state)
940 if (!strcasecmp(state, "enabled")) {
942 } else if (!strcasecmp(state, "disabled")) {
945 ctl_fatal("%s: state must be \"enabled\" or \"disabled\"", state);
950 nbctl_lsp_set_enabled(struct ctl_context *ctx)
952 const char *id = ctx->argv[1];
953 const char *state = ctx->argv[2];
954 const struct nbrec_logical_switch_port *lsp;
956 lsp = lsp_by_name_or_uuid(ctx, id, true);
957 bool enabled = parse_enabled(state);
958 nbrec_logical_switch_port_set_enabled(lsp, &enabled, 1);
962 nbctl_lsp_get_enabled(struct ctl_context *ctx)
964 const char *id = ctx->argv[1];
965 const struct nbrec_logical_switch_port *lsp;
967 lsp = lsp_by_name_or_uuid(ctx, id, true);
968 ds_put_format(&ctx->output, "%s\n",
969 !lsp->enabled || *lsp->enabled ? "enabled" : "disabled");
973 nbctl_lsp_set_type(struct ctl_context *ctx)
975 const char *id = ctx->argv[1];
976 const char *type = ctx->argv[2];
977 const struct nbrec_logical_switch_port *lsp;
979 lsp = lsp_by_name_or_uuid(ctx, id, true);
980 nbrec_logical_switch_port_set_type(lsp, type);
984 nbctl_lsp_get_type(struct ctl_context *ctx)
986 const char *id = ctx->argv[1];
987 const struct nbrec_logical_switch_port *lsp;
989 lsp = lsp_by_name_or_uuid(ctx, id, true);
990 ds_put_format(&ctx->output, "%s\n", lsp->type);
994 nbctl_lsp_set_options(struct ctl_context *ctx)
996 const char *id = ctx->argv[1];
997 const struct nbrec_logical_switch_port *lsp;
999 struct smap options = SMAP_INITIALIZER(&options);
1001 lsp = lsp_by_name_or_uuid(ctx, id, true);
1002 for (i = 2; i < ctx->argc; i++) {
1004 value = xstrdup(ctx->argv[i]);
1005 key = strsep(&value, "=");
1007 smap_add(&options, key, value);
1012 nbrec_logical_switch_port_set_options(lsp, &options);
1014 smap_destroy(&options);
1018 nbctl_lsp_get_options(struct ctl_context *ctx)
1020 const char *id = ctx->argv[1];
1021 const struct nbrec_logical_switch_port *lsp;
1022 struct smap_node *node;
1024 lsp = lsp_by_name_or_uuid(ctx, id, true);
1025 SMAP_FOR_EACH(node, &lsp->options) {
1026 ds_put_format(&ctx->output, "%s=%s\n", node->key, node->value);
1036 dir_encode(const char *dir)
1038 if (!strcmp(dir, "from-lport")) {
1039 return DIR_FROM_LPORT;
1040 } else if (!strcmp(dir, "to-lport")) {
1041 return DIR_TO_LPORT;
1048 acl_cmp(const void *acl1_, const void *acl2_)
1050 const struct nbrec_acl *const *acl1p = acl1_;
1051 const struct nbrec_acl *const *acl2p = acl2_;
1052 const struct nbrec_acl *acl1 = *acl1p;
1053 const struct nbrec_acl *acl2 = *acl2p;
1055 int dir1 = dir_encode(acl1->direction);
1056 int dir2 = dir_encode(acl2->direction);
1059 return dir1 < dir2 ? -1 : 1;
1060 } else if (acl1->priority != acl2->priority) {
1061 return acl1->priority > acl2->priority ? -1 : 1;
1063 return strcmp(acl1->match, acl2->match);
1068 nbctl_acl_list(struct ctl_context *ctx)
1070 const struct nbrec_logical_switch *ls;
1071 const struct nbrec_acl **acls;
1074 ls = ls_by_name_or_uuid(ctx, ctx->argv[1], true);
1076 acls = xmalloc(sizeof *acls * ls->n_acls);
1077 for (i = 0; i < ls->n_acls; i++) {
1078 acls[i] = ls->acls[i];
1081 qsort(acls, ls->n_acls, sizeof *acls, acl_cmp);
1083 for (i = 0; i < ls->n_acls; i++) {
1084 const struct nbrec_acl *acl = acls[i];
1085 ds_put_format(&ctx->output, "%10s %5"PRId64" (%s) %s%s\n",
1086 acl->direction, acl->priority,
1087 acl->match, acl->action, acl->log ? " log" : "");
1094 parse_direction(const char *arg)
1096 /* Validate direction. Only require the first letter. */
1097 if (arg[0] == 't') {
1099 } else if (arg[0] == 'f') {
1100 return "from-lport";
1102 ctl_fatal("%s: direction must be \"to-lport\" or \"from-lport\"", arg);
1107 parse_priority(const char *arg)
1109 /* Validate priority. */
1111 if (!ovs_scan(arg, "%"SCNd64, &priority)
1112 || priority < 0 || priority > 32767) {
1113 ctl_fatal("%s: priority must in range 0...32767", arg);
1119 nbctl_acl_add(struct ctl_context *ctx)
1121 const struct nbrec_logical_switch *ls;
1122 const char *action = ctx->argv[5];
1124 ls = ls_by_name_or_uuid(ctx, ctx->argv[1], true);
1126 const char *direction = parse_direction(ctx->argv[2]);
1127 int64_t priority = parse_priority(ctx->argv[3]);
1129 /* Validate action. */
1130 if (strcmp(action, "allow") && strcmp(action, "allow-related")
1131 && strcmp(action, "drop") && strcmp(action, "reject")) {
1132 ctl_fatal("%s: action must be one of \"allow\", \"allow-related\", "
1133 "\"drop\", and \"reject\"", action);
1137 /* Create the acl. */
1138 struct nbrec_acl *acl = nbrec_acl_insert(ctx->txn);
1139 nbrec_acl_set_priority(acl, priority);
1140 nbrec_acl_set_direction(acl, direction);
1141 nbrec_acl_set_match(acl, ctx->argv[4]);
1142 nbrec_acl_set_action(acl, action);
1143 if (shash_find(&ctx->options, "--log") != NULL) {
1144 nbrec_acl_set_log(acl, true);
1147 /* Insert the acl into the logical switch. */
1148 nbrec_logical_switch_verify_acls(ls);
1149 struct nbrec_acl **new_acls = xmalloc(sizeof *new_acls * (ls->n_acls + 1));
1150 memcpy(new_acls, ls->acls, sizeof *new_acls * ls->n_acls);
1151 new_acls[ls->n_acls] = acl;
1152 nbrec_logical_switch_set_acls(ls, new_acls, ls->n_acls + 1);
1157 nbctl_acl_del(struct ctl_context *ctx)
1159 const struct nbrec_logical_switch *ls;
1160 ls = ls_by_name_or_uuid(ctx, ctx->argv[1], true);
1162 if (ctx->argc != 2 && ctx->argc != 3 && ctx->argc != 5) {
1163 ctl_fatal("cannot specify priority without match");
1166 if (ctx->argc == 2) {
1167 /* If direction, priority, and match are not specified, delete
1169 nbrec_logical_switch_verify_acls(ls);
1170 nbrec_logical_switch_set_acls(ls, NULL, 0);
1174 const char *direction = parse_direction(ctx->argv[2]);
1176 /* If priority and match are not specified, delete all ACLs with the
1177 * specified direction. */
1178 if (ctx->argc == 3) {
1179 struct nbrec_acl **new_acls = xmalloc(sizeof *new_acls * ls->n_acls);
1182 for (size_t i = 0; i < ls->n_acls; i++) {
1183 if (strcmp(direction, ls->acls[i]->direction)) {
1184 new_acls[n_acls++] = ls->acls[i];
1188 nbrec_logical_switch_verify_acls(ls);
1189 nbrec_logical_switch_set_acls(ls, new_acls, n_acls);
1194 int64_t priority = parse_priority(ctx->argv[3]);
1196 /* Remove the matching rule. */
1197 for (size_t i = 0; i < ls->n_acls; i++) {
1198 struct nbrec_acl *acl = ls->acls[i];
1200 if (priority == acl->priority && !strcmp(ctx->argv[4], acl->match) &&
1201 !strcmp(direction, acl->direction)) {
1202 struct nbrec_acl **new_acls
1203 = xmemdup(ls->acls, sizeof *new_acls * ls->n_acls);
1204 new_acls[i] = ls->acls[ls->n_acls - 1];
1205 nbrec_logical_switch_verify_acls(ls);
1206 nbrec_logical_switch_set_acls(ls, new_acls,
1215 nbctl_lr_add(struct ctl_context *ctx)
1217 const char *lr_name = ctx->argc == 2 ? ctx->argv[1] : NULL;
1219 bool may_exist = shash_find(&ctx->options, "--may-exist") != NULL;
1220 bool add_duplicate = shash_find(&ctx->options, "--add-duplicate") != NULL;
1221 if (may_exist && add_duplicate) {
1222 ctl_fatal("--may-exist and --add-duplicate may not be used together");
1226 if (!add_duplicate) {
1227 const struct nbrec_logical_router *lr;
1228 NBREC_LOGICAL_ROUTER_FOR_EACH (lr, ctx->idl) {
1229 if (!strcmp(lr->name, lr_name)) {
1233 ctl_fatal("%s: a router with this name already exists",
1238 } else if (may_exist) {
1239 ctl_fatal("--may-exist requires specifying a name");
1240 } else if (add_duplicate) {
1241 ctl_fatal("--add-duplicate requires specifying a name");
1244 struct nbrec_logical_router *lr;
1245 lr = nbrec_logical_router_insert(ctx->txn);
1247 nbrec_logical_router_set_name(lr, lr_name);
1252 nbctl_lr_del(struct ctl_context *ctx)
1254 bool must_exist = !shash_find(&ctx->options, "--if-exists");
1255 const char *id = ctx->argv[1];
1256 const struct nbrec_logical_router *lr;
1258 lr = lr_by_name_or_uuid(ctx, id, must_exist);
1263 nbrec_logical_router_delete(lr);
1267 nbctl_lr_list(struct ctl_context *ctx)
1269 const struct nbrec_logical_router *lr;
1273 NBREC_LOGICAL_ROUTER_FOR_EACH(lr, ctx->idl) {
1274 smap_add_format(&lrs, lr->name, UUID_FMT " (%s)",
1275 UUID_ARGS(&lr->header_.uuid), lr->name);
1277 const struct smap_node **nodes = smap_sort(&lrs);
1278 for (size_t i = 0; i < smap_count(&lrs); i++) {
1279 const struct smap_node *node = nodes[i];
1280 ds_put_format(&ctx->output, "%s\n", node->value);
1286 /* The caller must free the returned string. */
1288 normalize_ipv4_prefix(ovs_be32 ipv4, unsigned int plen)
1290 ovs_be32 network = ipv4 & be32_prefix_mask(plen);
1292 return xasprintf(IP_FMT, IP_ARGS(network));
1294 return xasprintf(IP_FMT"/%d", IP_ARGS(network), plen);
1298 /* The caller must free the returned string. */
1300 normalize_ipv6_prefix(struct in6_addr ipv6, unsigned int plen)
1302 char network_s[INET6_ADDRSTRLEN];
1304 struct in6_addr mask = ipv6_create_mask(plen);
1305 struct in6_addr network = ipv6_addr_bitand(&ipv6, &mask);
1307 inet_ntop(AF_INET6, &network, network_s, INET6_ADDRSTRLEN);
1309 return xasprintf("%s", network_s);
1311 return xasprintf("%s/%d", network_s, plen);
1315 /* The caller must free the returned string. */
1317 normalize_prefix_str(const char *orig_prefix)
1323 error = ip_parse_cidr(orig_prefix, &ipv4, &plen);
1325 return normalize_ipv4_prefix(ipv4, plen);
1327 struct in6_addr ipv6;
1330 error = ipv6_parse_cidr(orig_prefix, &ipv6, &plen);
1335 return normalize_ipv6_prefix(ipv6, plen);
1340 nbctl_lr_route_add(struct ctl_context *ctx)
1342 const struct nbrec_logical_router *lr;
1343 lr = lr_by_name_or_uuid(ctx, ctx->argv[1], true);
1344 char *prefix, *next_hop;
1346 prefix = normalize_prefix_str(ctx->argv[2]);
1348 ctl_fatal("bad prefix argument: %s", ctx->argv[2]);
1351 next_hop = normalize_prefix_str(ctx->argv[3]);
1353 ctl_fatal("bad next hop argument: %s", ctx->argv[3]);
1356 if (strchr(prefix, '.')) {
1358 if (!ip_parse(ctx->argv[3], &hop_ipv4)) {
1359 ctl_fatal("bad IPv4 nexthop argument: %s", ctx->argv[3]);
1362 struct in6_addr hop_ipv6;
1363 if (!ipv6_parse(ctx->argv[3], &hop_ipv6)) {
1364 ctl_fatal("bad IPv6 nexthop argument: %s", ctx->argv[3]);
1368 bool may_exist = shash_find(&ctx->options, "--may-exist") != NULL;
1369 for (int i = 0; i < lr->n_static_routes; i++) {
1370 const struct nbrec_logical_router_static_route *route
1371 = lr->static_routes[i];
1374 rt_prefix = normalize_prefix_str(lr->static_routes[i]->ip_prefix);
1376 /* Ignore existing prefix we couldn't parse. */
1380 if (strcmp(rt_prefix, prefix)) {
1386 ctl_fatal("duplicate prefix: %s", prefix);
1389 /* Update the next hop for an existing route. */
1390 nbrec_logical_router_verify_static_routes(lr);
1391 nbrec_logical_router_static_route_verify_ip_prefix(route);
1392 nbrec_logical_router_static_route_verify_nexthop(route);
1393 nbrec_logical_router_static_route_set_ip_prefix(route, prefix);
1394 nbrec_logical_router_static_route_set_nexthop(route, next_hop);
1395 if (ctx->argc == 5) {
1396 nbrec_logical_router_static_route_set_output_port(route,
1405 struct nbrec_logical_router_static_route *route;
1406 route = nbrec_logical_router_static_route_insert(ctx->txn);
1407 nbrec_logical_router_static_route_set_ip_prefix(route, prefix);
1408 nbrec_logical_router_static_route_set_nexthop(route, next_hop);
1409 if (ctx->argc == 5) {
1410 nbrec_logical_router_static_route_set_output_port(route, ctx->argv[4]);
1413 nbrec_logical_router_verify_static_routes(lr);
1414 struct nbrec_logical_router_static_route **new_routes
1415 = xmalloc(sizeof *new_routes * (lr->n_static_routes + 1));
1416 memcpy(new_routes, lr->static_routes,
1417 sizeof *new_routes * lr->n_static_routes);
1418 new_routes[lr->n_static_routes] = route;
1419 nbrec_logical_router_set_static_routes(lr, new_routes,
1420 lr->n_static_routes + 1);
1427 nbctl_lr_route_del(struct ctl_context *ctx)
1429 const struct nbrec_logical_router *lr;
1430 lr = lr_by_name_or_uuid(ctx, ctx->argv[1], true);
1432 if (ctx->argc == 2) {
1433 /* If a prefix is not specified, delete all routes. */
1434 nbrec_logical_router_set_static_routes(lr, NULL, 0);
1438 char *prefix = normalize_prefix_str(ctx->argv[2]);
1440 ctl_fatal("bad prefix argument: %s", ctx->argv[2]);
1443 for (int i = 0; i < lr->n_static_routes; i++) {
1444 char *rt_prefix = normalize_prefix_str(lr->static_routes[i]->ip_prefix);
1446 /* Ignore existing prefix we couldn't parse. */
1450 if (!strcmp(prefix, rt_prefix)) {
1451 struct nbrec_logical_router_static_route **new_routes
1452 = xmemdup(lr->static_routes,
1453 sizeof *new_routes * lr->n_static_routes);
1455 new_routes[i] = lr->static_routes[lr->n_static_routes - 1];
1456 nbrec_logical_router_verify_static_routes(lr);
1457 nbrec_logical_router_set_static_routes(lr, new_routes,
1458 lr->n_static_routes - 1);
1467 if (!shash_find(&ctx->options, "--if-exists")) {
1468 ctl_fatal("no matching prefix: %s", prefix);
1473 static const struct nbrec_logical_router_port *
1474 lrp_by_name_or_uuid(struct ctl_context *ctx, const char *id, bool must_exist)
1476 const struct nbrec_logical_router_port *lrp = NULL;
1478 struct uuid lrp_uuid;
1479 bool is_uuid = uuid_from_string(&lrp_uuid, id);
1481 lrp = nbrec_logical_router_port_get_for_uuid(ctx->idl, &lrp_uuid);
1485 NBREC_LOGICAL_ROUTER_PORT_FOR_EACH(lrp, ctx->idl) {
1486 if (!strcmp(lrp->name, id)) {
1492 if (!lrp && must_exist) {
1493 ctl_fatal("%s: port %s not found", id, is_uuid ? "UUID" : "name");
1499 /* Returns the logical router that contains 'lrp'. */
1500 static const struct nbrec_logical_router *
1501 lrp_to_lr(const struct ovsdb_idl *idl,
1502 const struct nbrec_logical_router_port *lrp)
1504 const struct nbrec_logical_router *lr;
1505 NBREC_LOGICAL_ROUTER_FOR_EACH (lr, idl) {
1506 for (size_t i = 0; i < lr->n_ports; i++) {
1507 if (lr->ports[i] == lrp) {
1513 /* Can't happen because of the database schema */
1514 ctl_fatal("port %s is not part of any logical router",
1519 lr_get_name(const struct nbrec_logical_router *lr, char uuid_s[UUID_LEN + 1],
1525 snprintf(uuid_s, uuid_s_size, UUID_FMT, UUID_ARGS(&lr->header_.uuid));
1530 nbctl_lrp_add(struct ctl_context *ctx)
1532 bool may_exist = shash_find(&ctx->options, "--may-exist") != NULL;
1534 const struct nbrec_logical_router *lr;
1535 lr = lr_by_name_or_uuid(ctx, ctx->argv[1], true);
1537 const char *lrp_name = ctx->argv[2];
1538 const char *mac = ctx->argv[3];
1539 const char **networks = (const char **) &ctx->argv[4];
1541 int n_networks = ctx->argc - 4;
1542 for (int i = 4; i < ctx->argc; i++) {
1543 if (strchr(ctx->argv[i], '=')) {
1550 ctl_fatal("%s: router port requires specifying a network", lrp_name);
1553 char **settings = (char **) &ctx->argv[n_networks + 4];
1554 int n_settings = ctx->argc - 4 - n_networks;
1556 const struct nbrec_logical_router_port *lrp;
1557 lrp = lrp_by_name_or_uuid(ctx, lrp_name, false);
1560 ctl_fatal("%s: a port with this name already exists",
1564 const struct nbrec_logical_router *bound_lr;
1565 bound_lr = lrp_to_lr(ctx->idl, lrp);
1566 if (bound_lr != lr) {
1567 char uuid_s[UUID_LEN + 1];
1568 ctl_fatal("%s: port already exists but in router %s", lrp_name,
1569 lr_get_name(bound_lr, uuid_s, sizeof uuid_s));
1572 if (strcmp(mac, lrp->mac)) {
1573 ctl_fatal("%s: port already exists with mac %s", lrp_name,
1577 struct sset new_networks = SSET_INITIALIZER(&new_networks);
1578 for (int i = 0; i < n_networks; i++) {
1579 sset_add(&new_networks, networks[i]);
1582 struct sset orig_networks = SSET_INITIALIZER(&orig_networks);
1583 sset_add_array(&orig_networks, lrp->networks, lrp->n_networks);
1585 if (!sset_equals(&orig_networks, &new_networks)) {
1586 ctl_fatal("%s: port already exists with different network",
1590 sset_destroy(&orig_networks);
1591 sset_destroy(&new_networks);
1593 /* Special-case sanity-check of peer ports. */
1594 const char *peer = NULL;
1595 for (int i = 0; i < n_settings; i++) {
1596 if (!strncmp(settings[i], "peer=", 5)) {
1597 peer = settings[i] + 5;
1602 if ((!peer != !lrp->peer) ||
1603 (lrp->peer && strcmp(peer, lrp->peer))) {
1604 ctl_fatal("%s: port already exists with mismatching peer",
1612 if (!ovs_scan(mac, ETH_ADDR_SCAN_FMT, ETH_ADDR_SCAN_ARGS(ea))) {
1613 ctl_fatal("%s: invalid mac address %s", lrp_name, mac);
1616 for (int i = 0; i < n_networks; i++) {
1619 char *error = ip_parse_cidr(networks[i], &ipv4, &plen);
1622 struct in6_addr ipv6;
1623 error = ipv6_parse_cidr(networks[i], &ipv6, &plen);
1626 ctl_fatal("%s: invalid network address: %s", lrp_name,
1632 /* Create the logical port. */
1633 lrp = nbrec_logical_router_port_insert(ctx->txn);
1634 nbrec_logical_router_port_set_name(lrp, lrp_name);
1635 nbrec_logical_router_port_set_mac(lrp, mac);
1636 nbrec_logical_router_port_set_networks(lrp, networks, n_networks);
1638 for (int i = 0; i < n_settings; i++) {
1639 ctl_set_column("Logical_Router_Port", &lrp->header_, settings[i],
1643 /* Insert the logical port into the logical router. */
1644 nbrec_logical_router_verify_ports(lr);
1645 struct nbrec_logical_router_port **new_ports = xmalloc(sizeof *new_ports *
1647 memcpy(new_ports, lr->ports, sizeof *new_ports * lr->n_ports);
1648 new_ports[lr->n_ports] = CONST_CAST(struct nbrec_logical_router_port *,
1650 nbrec_logical_router_set_ports(lr, new_ports, lr->n_ports + 1);
1654 /* Removes logical router port 'lr->ports[idx]'. */
1656 remove_lrp(const struct nbrec_logical_router *lr, size_t idx)
1658 const struct nbrec_logical_router_port *lrp = lr->ports[idx];
1660 /* First remove 'lrp' from the array of ports. This is what will
1661 * actually cause the logical port to be deleted when the transaction is
1662 * sent to the database server (due to garbage collection). */
1663 struct nbrec_logical_router_port **new_ports
1664 = xmemdup(lr->ports, sizeof *new_ports * lr->n_ports);
1665 new_ports[idx] = new_ports[lr->n_ports - 1];
1666 nbrec_logical_router_verify_ports(lr);
1667 nbrec_logical_router_set_ports(lr, new_ports, lr->n_ports - 1);
1670 /* Delete 'lrp' from the IDL. This won't have a real effect on
1671 * the database server (the IDL will suppress it in fact) but it
1672 * means that it won't show up when we iterate with
1673 * NBREC_LOGICAL_ROUTER_PORT_FOR_EACH later. */
1674 nbrec_logical_router_port_delete(lrp);
1678 nbctl_lrp_del(struct ctl_context *ctx)
1680 bool must_exist = !shash_find(&ctx->options, "--if-exists");
1681 const struct nbrec_logical_router_port *lrp;
1683 lrp = lrp_by_name_or_uuid(ctx, ctx->argv[1], must_exist);
1688 /* Find the router that contains 'lrp', then delete it. */
1689 const struct nbrec_logical_router *lr;
1690 NBREC_LOGICAL_ROUTER_FOR_EACH (lr, ctx->idl) {
1691 for (size_t i = 0; i < lr->n_ports; i++) {
1692 if (lr->ports[i] == lrp) {
1699 /* Can't happen because of the database schema. */
1700 ctl_fatal("logical port %s is not part of any logical router",
1704 /* Print a list of logical router ports. */
1706 nbctl_lrp_list(struct ctl_context *ctx)
1708 const char *id = ctx->argv[1];
1709 const struct nbrec_logical_router *lr;
1713 lr = lr_by_name_or_uuid(ctx, id, true);
1716 for (i = 0; i < lr->n_ports; i++) {
1717 const struct nbrec_logical_router_port *lrp = lr->ports[i];
1718 smap_add_format(&lrps, lrp->name, UUID_FMT " (%s)",
1719 UUID_ARGS(&lrp->header_.uuid), lrp->name);
1721 const struct smap_node **nodes = smap_sort(&lrps);
1722 for (i = 0; i < smap_count(&lrps); i++) {
1723 const struct smap_node *node = nodes[i];
1724 ds_put_format(&ctx->output, "%s\n", node->value);
1726 smap_destroy(&lrps);
1730 /* Set the logical router port admin-enabled state. */
1732 nbctl_lrp_set_enabled(struct ctl_context *ctx)
1734 const char *id = ctx->argv[1];
1735 const char *state = ctx->argv[2];
1736 const struct nbrec_logical_router_port *lrp;
1738 lrp = lrp_by_name_or_uuid(ctx, id, true);
1743 bool enabled = parse_enabled(state);
1744 nbrec_logical_router_port_set_enabled(lrp, &enabled, 1);
1747 /* Print admin-enabled state for logical router port. */
1749 nbctl_lrp_get_enabled(struct ctl_context *ctx)
1751 const char *id = ctx->argv[1];
1752 const struct nbrec_logical_router_port *lrp;
1754 lrp = lrp_by_name_or_uuid(ctx, id, true);
1759 ds_put_format(&ctx->output, "%s\n",
1761 *lrp->enabled ? "enabled" : "disabled");
1767 const struct nbrec_logical_router_static_route *route;
1771 ipv4_route_cmp(const void *route1_, const void *route2_)
1773 const struct ipv4_route *route1p = route1_;
1774 const struct ipv4_route *route2p = route2_;
1776 if (route1p->plen != route2p->plen) {
1777 return route1p->plen > route2p->plen ? -1 : 1;
1778 } else if (route1p->addr != route2p->addr) {
1779 return ntohl(route1p->addr) < ntohl(route2p->addr) ? -1 : 1;
1787 struct in6_addr addr;
1788 const struct nbrec_logical_router_static_route *route;
1792 ipv6_route_cmp(const void *route1_, const void *route2_)
1794 const struct ipv6_route *route1p = route1_;
1795 const struct ipv6_route *route2p = route2_;
1797 if (route1p->plen != route2p->plen) {
1798 return route1p->plen > route2p->plen ? -1 : 1;
1800 return memcmp(&route1p->addr, &route2p->addr, sizeof(route1p->addr));
1804 print_route(const struct nbrec_logical_router_static_route *route, struct ds *s)
1807 char *prefix = normalize_prefix_str(route->ip_prefix);
1808 char *next_hop = normalize_prefix_str(route->nexthop);
1809 ds_put_format(s, "%25s %25s", prefix, next_hop);
1813 if (route->output_port) {
1814 ds_put_format(s, " %s", route->output_port);
1816 ds_put_char(s, '\n');
1820 nbctl_lr_route_list(struct ctl_context *ctx)
1822 const struct nbrec_logical_router *lr;
1823 struct ipv4_route *ipv4_routes;
1824 struct ipv6_route *ipv6_routes;
1825 size_t n_ipv4_routes = 0;
1826 size_t n_ipv6_routes = 0;
1828 lr = lr_by_name_or_uuid(ctx, ctx->argv[1], true);
1830 ipv4_routes = xmalloc(sizeof *ipv4_routes * lr->n_static_routes);
1831 ipv6_routes = xmalloc(sizeof *ipv6_routes * lr->n_static_routes);
1833 for (int i = 0; i < lr->n_static_routes; i++) {
1834 const struct nbrec_logical_router_static_route *route
1835 = lr->static_routes[i];
1840 error = ip_parse_cidr(route->ip_prefix, &ipv4, &plen);
1842 ipv4_routes[n_ipv4_routes].plen = plen;
1843 ipv4_routes[n_ipv4_routes].addr = ipv4;
1844 ipv4_routes[n_ipv4_routes].route = route;
1849 struct in6_addr ipv6;
1850 error = ipv6_parse_cidr(route->ip_prefix, &ipv6, &plen);
1852 ipv6_routes[n_ipv6_routes].plen = plen;
1853 ipv6_routes[n_ipv6_routes].addr = ipv6;
1854 ipv6_routes[n_ipv6_routes].route = route;
1857 /* Invalid prefix. */
1858 VLOG_WARN("router "UUID_FMT" (%s) has invalid prefix: %s",
1859 UUID_ARGS(&lr->header_.uuid), lr->name,
1867 qsort(ipv4_routes, n_ipv4_routes, sizeof *ipv4_routes, ipv4_route_cmp);
1868 qsort(ipv6_routes, n_ipv6_routes, sizeof *ipv6_routes, ipv6_route_cmp);
1870 if (n_ipv4_routes) {
1871 ds_put_cstr(&ctx->output, "IPv4 Routes\n");
1873 for (int i = 0; i < n_ipv4_routes; i++) {
1874 print_route(ipv4_routes[i].route, &ctx->output);
1877 if (n_ipv6_routes) {
1878 ds_put_format(&ctx->output, "%sIPv6 Routes\n",
1879 n_ipv4_routes ? "\n" : "");
1881 for (int i = 0; i < n_ipv6_routes; i++) {
1882 print_route(ipv6_routes[i].route, &ctx->output);
1889 static const struct ctl_table_class tables[] = {
1890 {&nbrec_table_logical_switch,
1891 {{&nbrec_table_logical_switch, &nbrec_logical_switch_col_name, NULL},
1892 {NULL, NULL, NULL}}},
1894 {&nbrec_table_logical_switch_port,
1895 {{&nbrec_table_logical_switch_port, &nbrec_logical_switch_port_col_name,
1897 {NULL, NULL, NULL}}},
1900 {{NULL, NULL, NULL},
1901 {NULL, NULL, NULL}}},
1903 {&nbrec_table_load_balancer,
1904 {{NULL, NULL, NULL},
1905 {NULL, NULL, NULL}}},
1907 {&nbrec_table_logical_router,
1908 {{&nbrec_table_logical_router, &nbrec_logical_router_col_name, NULL},
1909 {NULL, NULL, NULL}}},
1911 {&nbrec_table_logical_router_port,
1912 {{&nbrec_table_logical_router_port, &nbrec_logical_router_port_col_name,
1914 {NULL, NULL, NULL}}},
1916 {&nbrec_table_logical_router_static_route,
1917 {{&nbrec_table_logical_router_static_route, NULL,
1919 {NULL, NULL, NULL}}},
1922 {{&nbrec_table_nat, NULL,
1924 {NULL, NULL, NULL}}},
1926 {&nbrec_table_address_set,
1927 {{&nbrec_table_address_set, &nbrec_address_set_col_name, NULL},
1928 {NULL, NULL, NULL}}},
1930 {NULL, {{NULL, NULL, NULL}, {NULL, NULL, NULL}}}
1934 run_prerequisites(struct ctl_command *commands, size_t n_commands,
1935 struct ovsdb_idl *idl)
1937 struct ctl_command *c;
1939 for (c = commands; c < &commands[n_commands]; c++) {
1940 if (c->syntax->prerequisites) {
1941 struct ctl_context ctx;
1943 ds_init(&c->output);
1946 ctl_context_init(&ctx, c, idl, NULL, NULL, NULL);
1947 (c->syntax->prerequisites)(&ctx);
1948 ctl_context_done(&ctx, c);
1950 ovs_assert(!c->output.string);
1951 ovs_assert(!c->table);
1957 do_nbctl(const char *args, struct ctl_command *commands, size_t n_commands,
1958 struct ovsdb_idl *idl)
1960 struct ovsdb_idl_txn *txn;
1961 enum ovsdb_idl_txn_status status;
1962 struct ovsdb_symbol_table *symtab;
1963 struct ctl_context ctx;
1964 struct ctl_command *c;
1965 struct shash_node *node;
1968 txn = the_idl_txn = ovsdb_idl_txn_create(idl);
1970 ovsdb_idl_txn_set_dry_run(txn);
1973 ovsdb_idl_txn_add_comment(txn, "ovs-nbctl: %s", args);
1975 symtab = ovsdb_symbol_table_create();
1976 for (c = commands; c < &commands[n_commands]; c++) {
1977 ds_init(&c->output);
1980 ctl_context_init(&ctx, NULL, idl, txn, symtab, NULL);
1981 for (c = commands; c < &commands[n_commands]; c++) {
1982 ctl_context_init_command(&ctx, c);
1983 if (c->syntax->run) {
1984 (c->syntax->run)(&ctx);
1986 ctl_context_done_command(&ctx, c);
1988 if (ctx.try_again) {
1989 ctl_context_done(&ctx, NULL);
1993 ctl_context_done(&ctx, NULL);
1995 SHASH_FOR_EACH (node, &symtab->sh) {
1996 struct ovsdb_symbol *symbol = node->data;
1997 if (!symbol->created) {
1998 ctl_fatal("row id \"%s\" is referenced but never created (e.g. "
1999 "with \"-- --id=%s create ...\")",
2000 node->name, node->name);
2002 if (!symbol->strong_ref) {
2003 if (!symbol->weak_ref) {
2004 VLOG_WARN("row id \"%s\" was created but no reference to it "
2005 "was inserted, so it will not actually appear in "
2006 "the database", node->name);
2008 VLOG_WARN("row id \"%s\" was created but only a weak "
2009 "reference to it was inserted, so it will not "
2010 "actually appear in the database", node->name);
2015 status = ovsdb_idl_txn_commit_block(txn);
2016 if (status == TXN_UNCHANGED || status == TXN_SUCCESS) {
2017 for (c = commands; c < &commands[n_commands]; c++) {
2018 if (c->syntax->postprocess) {
2019 ctl_context_init(&ctx, c, idl, txn, symtab, NULL);
2020 (c->syntax->postprocess)(&ctx);
2021 ctl_context_done(&ctx, c);
2025 error = xstrdup(ovsdb_idl_txn_get_error(txn));
2028 case TXN_UNCOMMITTED:
2029 case TXN_INCOMPLETE:
2033 /* Should not happen--we never call ovsdb_idl_txn_abort(). */
2034 ctl_fatal("transaction aborted");
2044 ctl_fatal("transaction error: %s", error);
2046 case TXN_NOT_LOCKED:
2047 /* Should not happen--we never call ovsdb_idl_set_lock(). */
2048 ctl_fatal("database not locked");
2055 ovsdb_symbol_table_destroy(symtab);
2057 for (c = commands; c < &commands[n_commands]; c++) {
2058 struct ds *ds = &c->output;
2061 table_print(c->table, &table_style);
2062 } else if (oneline) {
2066 for (j = 0; j < ds->length; j++) {
2067 int ch = ds->string[j];
2070 fputs("\\n", stdout);
2074 fputs("\\\\", stdout);
2083 fputs(ds_cstr(ds), stdout);
2085 ds_destroy(&c->output);
2086 table_destroy(c->table);
2089 shash_destroy_free_data(&c->options);
2092 ovsdb_idl_txn_destroy(txn);
2093 ovsdb_idl_destroy(idl);
2098 /* Our transaction needs to be rerun, or a prerequisite was not met. Free
2099 * resources and return so that the caller can try again. */
2101 ovsdb_idl_txn_abort(txn);
2102 ovsdb_idl_txn_destroy(txn);
2105 ovsdb_symbol_table_destroy(symtab);
2106 for (c = commands; c < &commands[n_commands]; c++) {
2107 ds_destroy(&c->output);
2108 table_destroy(c->table);
2115 /* Frees the current transaction and the underlying IDL and then calls
2118 * Freeing the transaction and the IDL is not strictly necessary, but it makes
2119 * for a clean memory leak report from valgrind in the normal case. That makes
2120 * it easier to notice real memory leaks. */
2122 nbctl_exit(int status)
2125 ovsdb_idl_txn_abort(the_idl_txn);
2126 ovsdb_idl_txn_destroy(the_idl_txn);
2128 ovsdb_idl_destroy(the_idl);
2132 static const struct ctl_command_syntax nbctl_commands[] = {
2133 { "show", 0, 1, "[SWITCH]", NULL, nbctl_show, NULL, "", RO },
2135 /* logical switch commands. */
2136 { "ls-add", 0, 1, "[SWITCH]", NULL, nbctl_ls_add, NULL,
2137 "--may-exist,--add-duplicate", RW },
2138 { "ls-del", 1, 1, "SWITCH", NULL, nbctl_ls_del, NULL, "--if-exists", RW },
2139 { "ls-list", 0, 0, "", NULL, nbctl_ls_list, NULL, "", RO },
2142 { "acl-add", 5, 5, "SWITCH DIRECTION PRIORITY MATCH ACTION", NULL,
2143 nbctl_acl_add, NULL, "--log", RW },
2144 { "acl-del", 1, 4, "SWITCH [DIRECTION [PRIORITY MATCH]]", NULL,
2145 nbctl_acl_del, NULL, "", RW },
2146 { "acl-list", 1, 1, "SWITCH", NULL, nbctl_acl_list, NULL, "", RO },
2148 /* logical switch port commands. */
2149 { "lsp-add", 2, 4, "SWITCH PORT [PARENT] [TAG]", NULL, nbctl_lsp_add,
2150 NULL, "--may-exist", RW },
2151 { "lsp-del", 1, 1, "PORT", NULL, nbctl_lsp_del, NULL, "--if-exists", RW },
2152 { "lsp-list", 1, 1, "SWITCH", NULL, nbctl_lsp_list, NULL, "", RO },
2153 { "lsp-get-parent", 1, 1, "PORT", NULL, nbctl_lsp_get_parent, NULL,
2155 { "lsp-get-tag", 1, 1, "PORT", NULL, nbctl_lsp_get_tag, NULL, "", RO },
2156 { "lsp-set-addresses", 1, INT_MAX, "PORT [ADDRESS]...", NULL,
2157 nbctl_lsp_set_addresses, NULL, "", RW },
2158 { "lsp-get-addresses", 1, 1, "PORT", NULL, nbctl_lsp_get_addresses, NULL,
2160 { "lsp-set-port-security", 0, INT_MAX, "PORT [ADDRS]...", NULL,
2161 nbctl_lsp_set_port_security, NULL, "", RW },
2162 { "lsp-get-port-security", 1, 1, "PORT", NULL,
2163 nbctl_lsp_get_port_security, NULL, "", RO },
2164 { "lsp-get-up", 1, 1, "PORT", NULL, nbctl_lsp_get_up, NULL, "", RO },
2165 { "lsp-set-enabled", 2, 2, "PORT STATE", NULL, nbctl_lsp_set_enabled,
2167 { "lsp-get-enabled", 1, 1, "PORT", NULL, nbctl_lsp_get_enabled, NULL,
2169 { "lsp-set-type", 2, 2, "PORT TYPE", NULL, nbctl_lsp_set_type, NULL,
2171 { "lsp-get-type", 1, 1, "PORT", NULL, nbctl_lsp_get_type, NULL, "", RO },
2172 { "lsp-set-options", 1, INT_MAX, "PORT KEY=VALUE [KEY=VALUE]...", NULL,
2173 nbctl_lsp_set_options, NULL, "", RW },
2174 { "lsp-get-options", 1, 1, "PORT", NULL, nbctl_lsp_get_options, NULL,
2177 /* logical router commands. */
2178 { "lr-add", 0, 1, "[ROUTER]", NULL, nbctl_lr_add, NULL,
2179 "--may-exist,--add-duplicate", RW },
2180 { "lr-del", 1, 1, "ROUTER", NULL, nbctl_lr_del, NULL, "--if-exists", RW },
2181 { "lr-list", 0, 0, "", NULL, nbctl_lr_list, NULL, "", RO },
2183 /* logical router port commands. */
2184 { "lrp-add", 4, INT_MAX,
2185 "ROUTER PORT MAC NETWORK... [COLUMN[:KEY]=VALUE]...",
2186 NULL, nbctl_lrp_add, NULL, "--may-exist", RW },
2187 { "lrp-del", 1, 1, "PORT", NULL, nbctl_lrp_del, NULL, "--if-exists", RW },
2188 { "lrp-list", 1, 1, "ROUTER", NULL, nbctl_lrp_list, NULL, "", RO },
2189 { "lrp-set-enabled", 2, 2, "PORT STATE", NULL, nbctl_lrp_set_enabled,
2191 { "lrp-get-enabled", 1, 1, "PORT", NULL, nbctl_lrp_get_enabled,
2194 /* logical router route commands. */
2195 { "lr-route-add", 3, 4, "ROUTER PREFIX NEXTHOP [PORT]", NULL,
2196 nbctl_lr_route_add, NULL, "--may-exist", RW },
2197 { "lr-route-del", 1, 2, "ROUTER [PREFIX]", NULL, nbctl_lr_route_del,
2198 NULL, "--if-exists", RW },
2199 { "lr-route-list", 1, 1, "ROUTER", NULL, nbctl_lr_route_list, NULL,
2202 {NULL, 0, 0, NULL, NULL, NULL, NULL, "", RO},
2205 /* Registers nbctl and common db commands. */
2207 nbctl_cmd_init(void)
2209 ctl_init(tables, NULL, nbctl_exit);
2210 ctl_register_commands(nbctl_commands);