2 * Licensed under the Apache License, Version 2.0 (the "License");
3 * you may not use this file except in compliance with the License.
4 * You may obtain a copy of the License at:
6 * http://www.apache.org/licenses/LICENSE-2.0
8 * Unless required by applicable law or agreed to in writing, software
9 * distributed under the License is distributed on an "AS IS" BASIS,
10 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 * See the License for the specific language governing permissions and
12 * limitations under the License.
22 #include "command-line.h"
23 #include "db-ctl-base.h"
25 #include "fatal-signal.h"
27 #include "ovn/lib/ovn-nb-idl.h"
29 #include "poll-loop.h"
33 #include "stream-ssl.h"
38 #include "openvswitch/vlog.h"
40 VLOG_DEFINE_THIS_MODULE(nbctl);
42 /* --db: The database server to contact. */
43 static const char *db;
45 /* --oneline: Write each command's output as a single line? */
48 /* --dry-run: Do not commit any changes. */
51 /* --timeout: Time to wait for a connection to 'db'. */
54 /* Format for table output. */
55 static struct table_style table_style = TABLE_STYLE_DEFAULT;
57 /* The IDL we're using and the current transaction, if any.
58 * This is for use by nbctl_exit() only, to allow it to clean up.
59 * Other code should use its context arguments. */
60 static struct ovsdb_idl *the_idl;
61 static struct ovsdb_idl_txn *the_idl_txn;
62 OVS_NO_RETURN static void nbctl_exit(int status);
64 static void nbctl_cmd_init(void);
65 OVS_NO_RETURN static void usage(void);
66 static void parse_options(int argc, char *argv[], struct shash *local_options);
67 static const char *nbctl_default_db(void);
68 static void run_prerequisites(struct ctl_command[], size_t n_commands,
70 static bool do_nbctl(const char *args, struct ctl_command *, size_t n,
74 main(int argc, char *argv[])
76 struct ovsdb_idl *idl;
77 struct ctl_command *commands;
78 struct shash local_options;
83 set_program_name(argv[0]);
84 fatal_ignore_sigpipe();
85 vlog_set_levels(NULL, VLF_CONSOLE, VLL_WARN);
86 vlog_set_levels_from_string_assert("reconnect:warn");
91 /* Log our arguments. This is often valuable for debugging systems. */
92 args = process_escape_args(argv);
93 VLOG(ctl_might_write_to_db(argv) ? VLL_INFO : VLL_DBG,
94 "Called as %s", args);
96 /* Parse command line. */
97 shash_init(&local_options);
98 parse_options(argc, argv, &local_options);
99 commands = ctl_parse_commands(argc - optind, argv + optind, &local_options,
106 /* Initialize IDL. */
107 idl = the_idl = ovsdb_idl_create(db, &nbrec_idl_class, true, false);
108 run_prerequisites(commands, n_commands, idl);
110 /* Execute the commands.
112 * 'seqno' is the database sequence number for which we last tried to
113 * execute our transaction. There's no point in trying to commit more than
114 * once for any given sequence number, because if the transaction fails
115 * it's because the database changed and we need to obtain an up-to-date
116 * view of the database before we try the transaction again. */
117 seqno = ovsdb_idl_get_seqno(idl);
120 if (!ovsdb_idl_is_alive(idl)) {
121 int retval = ovsdb_idl_get_last_error(idl);
122 ctl_fatal("%s: database connection failed (%s)",
123 db, ovs_retval_to_string(retval));
126 if (seqno != ovsdb_idl_get_seqno(idl)) {
127 seqno = ovsdb_idl_get_seqno(idl);
128 if (do_nbctl(args, commands, n_commands, idl)) {
134 if (seqno == ovsdb_idl_get_seqno(idl)) {
142 nbctl_default_db(void)
146 def = getenv("OVN_NB_DB");
148 def = xasprintf("unix:%s/ovnnb_db.sock", ovs_rundir());
155 parse_options(int argc, char *argv[], struct shash *local_options)
158 OPT_DB = UCHAR_MAX + 1,
168 static const struct option global_long_options[] = {
169 {"db", required_argument, NULL, OPT_DB},
170 {"no-syslog", no_argument, NULL, OPT_NO_SYSLOG},
171 {"dry-run", no_argument, NULL, OPT_DRY_RUN},
172 {"oneline", no_argument, NULL, OPT_ONELINE},
173 {"timeout", required_argument, NULL, 't'},
174 {"help", no_argument, NULL, 'h'},
175 {"commands", no_argument, NULL, OPT_COMMANDS},
176 {"options", no_argument, NULL, OPT_OPTIONS},
177 {"version", no_argument, NULL, 'V'},
179 STREAM_SSL_LONG_OPTIONS,
183 const int n_global_long_options = ARRAY_SIZE(global_long_options) - 1;
184 char *tmp, *short_options;
186 struct option *options;
187 size_t allocated_options;
191 tmp = ovs_cmdl_long_options_to_short_options(global_long_options);
192 short_options = xasprintf("+%s", tmp);
195 /* We want to parse both global and command-specific options here, but
196 * getopt_long() isn't too convenient for the job. We copy our global
197 * options into a dynamic array, then append all of the command-specific
199 options = xmemdup(global_long_options, sizeof global_long_options);
200 allocated_options = ARRAY_SIZE(global_long_options);
201 n_options = n_global_long_options;
202 ctl_add_cmd_options(&options, &n_options, &allocated_options, OPT_LOCAL);
203 table_style.format = TF_LIST;
209 c = getopt_long(argc, argv, short_options, options, &idx);
224 vlog_set_levels(&this_module, VLF_SYSLOG, VLL_WARN);
232 if (shash_find(local_options, options[idx].name)) {
233 ctl_fatal("'%s' option specified multiple times",
236 shash_add_nocopy(local_options,
237 xasprintf("--%s", options[idx].name),
238 optarg ? xstrdup(optarg) : NULL);
246 ctl_print_commands();
249 ctl_print_options(global_long_options);
252 ovs_print_version(0, 0);
253 printf("DB Schema %s\n", nbrec_get_db_version());
257 timeout = strtoul(optarg, NULL, 10);
259 ctl_fatal("value %s on -t or --timeout is invalid", optarg);
264 TABLE_OPTION_HANDLERS(&table_style)
265 STREAM_SSL_OPTION_HANDLERS
277 db = nbctl_default_db();
280 for (i = n_global_long_options; options[i].name; i++) {
281 free(CONST_CAST(char *, options[i].name));
290 %s: OVN northbound DB management utility\n\
291 usage: %s [OPTIONS] COMMAND [ARG...]\n\
294 show print overview of database contents\n\
295 show SWITCH print overview of database contents for SWITCH\n\
296 show ROUTER print overview of database contents for ROUTER\n\
298 Logical switch commands:\n\
299 ls-add [SWITCH] create a logical switch named SWITCH\n\
300 ls-del SWITCH delete SWITCH and all its ports\n\
301 ls-list print the names of all logical switches\n\
304 acl-add SWITCH DIRECTION PRIORITY MATCH ACTION [log]\n\
305 add an ACL to SWITCH\n\
306 acl-del SWITCH [DIRECTION [PRIORITY MATCH]]\n\
307 remove ACLs from SWITCH\n\
308 acl-list SWITCH print ACLs for SWITCH\n\
310 Logical switch port commands:\n\
311 lsp-add SWITCH PORT add logical port PORT on SWITCH\n\
312 lsp-add SWITCH PORT PARENT TAG\n\
313 add logical port PORT on SWITCH with PARENT\n\
315 lsp-del PORT delete PORT from its attached switch\n\
316 lsp-list SWITCH print the names of all logical ports on SWITCH\n\
317 lsp-get-parent PORT get the parent of PORT if set\n\
318 lsp-get-tag PORT get the PORT's tag if set\n\
319 lsp-set-addresses PORT [ADDRESS]...\n\
320 set MAC or MAC+IP addresses for PORT.\n\
321 lsp-get-addresses PORT get a list of MAC addresses on PORT\n\
322 lsp-set-port-security PORT [ADDRS]...\n\
323 set port security addresses for PORT.\n\
324 lsp-get-port-security PORT get PORT's port security addresses\n\
325 lsp-get-up PORT get state of PORT ('up' or 'down')\n\
326 lsp-set-enabled PORT STATE\n\
327 set administrative state PORT\n\
328 ('enabled' or 'disabled')\n\
329 lsp-get-enabled PORT get administrative state PORT\n\
330 ('enabled' or 'disabled')\n\
331 lsp-set-type PORT TYPE set the type for PORT\n\
332 lsp-get-type PORT get the type for PORT\n\
333 lsp-set-options PORT KEY=VALUE [KEY=VALUE]...\n\
334 set options related to the type of PORT\n\
335 lsp-get-options PORT get the type specific options for PORT\n\
337 Logical router commands:\n\
338 lr-add [ROUTER] create a logical router named ROUTER\n\
339 lr-del ROUTER delete ROUTER and all its ports\n\
340 lr-list print the names of all logical routers\n\
342 Logical router port commands:\n\
343 lrp-add ROUTER PORT MAC NETWORK [PEER]\n\
344 add logical port PORT on ROUTER\n\
345 lrp-del PORT delete PORT from its attached router\n\
346 lrp-list ROUTER print the names of all ports on ROUTER\n\
347 lrp-set-enabled PORT STATE\n\
348 set administrative state PORT\n\
349 ('enabled' or 'disabled')\n\
350 lrp-get-enabled PORT get administrative state PORT\n\
351 ('enabled' or 'disabled')\n\
354 lr-route-add ROUTER PREFIX NEXTHOP [PORT]\n\
355 add a route to ROUTER\n\
356 lr-route-del ROUTER [PREFIX]\n\
357 remove routes from ROUTER\n\
358 lr-route-list ROUTER print routes for ROUTER\n\
363 --db=DATABASE connect to DATABASE\n\
365 -t, --timeout=SECS wait at most SECS seconds\n\
366 --dry-run do not commit changes to database\n\
367 --oneline print exactly one line of output per command\n",
368 program_name, program_name, ctl_get_db_cmd_usage(), nbctl_default_db());
371 --no-syslog equivalent to --verbose=nbctl:syslog:warn\n");
374 -h, --help display this help message\n\
375 -V, --version display version information\n");
380 /* Find a logical router given its id. */
381 static const struct nbrec_logical_router *
382 lr_by_name_or_uuid(struct ctl_context *ctx, const char *id,
385 const struct nbrec_logical_router *lr = NULL;
386 bool is_uuid = false;
389 if (uuid_from_string(&lr_uuid, id)) {
391 lr = nbrec_logical_router_get_for_uuid(ctx->idl, &lr_uuid);
395 const struct nbrec_logical_router *iter;
397 NBREC_LOGICAL_ROUTER_FOR_EACH(iter, ctx->idl) {
398 if (strcmp(iter->name, id)) {
402 ctl_fatal("Multiple logical routers named '%s'. "
409 if (!lr && must_exist) {
410 ctl_fatal("%s: router %s not found", id, is_uuid ? "UUID" : "name");
416 static const struct nbrec_logical_switch *
417 ls_by_name_or_uuid(struct ctl_context *ctx, const char *id, bool must_exist)
419 const struct nbrec_logical_switch *ls = NULL;
422 bool is_uuid = uuid_from_string(&ls_uuid, id);
424 ls = nbrec_logical_switch_get_for_uuid(ctx->idl, &ls_uuid);
428 const struct nbrec_logical_switch *iter;
430 NBREC_LOGICAL_SWITCH_FOR_EACH(iter, ctx->idl) {
431 if (strcmp(iter->name, id)) {
435 ctl_fatal("Multiple logical switches named '%s'. "
442 if (!ls && must_exist) {
443 ctl_fatal("%s: switch %s not found", id, is_uuid ? "UUID" : "name");
449 /* Given pointer to logical router, this routine prints the router
452 print_lr(const struct nbrec_logical_router *lr, struct ds *s)
454 ds_put_format(s, " router "UUID_FMT" (%s)\n",
455 UUID_ARGS(&lr->header_.uuid), lr->name);
457 for (size_t i = 0; i < lr->n_ports; i++) {
458 const struct nbrec_logical_router_port *lrp = lr->ports[i];
459 ds_put_format(s, " port %s\n", lrp->name);
461 ds_put_cstr(s, " mac: ");
462 ds_put_format(s, "\"%s\"", lrp->mac);
464 ds_put_format(s, "\n");
469 print_ls(const struct nbrec_logical_switch *ls, struct ds *s)
471 ds_put_format(s, " switch "UUID_FMT" (%s)\n",
472 UUID_ARGS(&ls->header_.uuid), ls->name);
474 for (size_t i = 0; i < ls->n_ports; i++) {
475 const struct nbrec_logical_switch_port *lsp = ls->ports[i];
477 ds_put_format(s, " port %s\n", lsp->name);
478 if (lsp->parent_name) {
479 ds_put_format(s, " parent: %s\n", lsp->parent_name);
482 ds_put_format(s, " tag: %"PRIu64"\n", lsp->tag[0]);
484 if (lsp->n_addresses) {
485 ds_put_cstr(s, " addresses: [");
486 for (size_t j = 0; j < lsp->n_addresses; j++) {
487 ds_put_format(s, "%s\"%s\"",
491 ds_put_cstr(s, "]\n");
497 nbctl_show(struct ctl_context *ctx)
499 const struct nbrec_logical_switch *ls;
501 if (ctx->argc == 2) {
502 ls = ls_by_name_or_uuid(ctx, ctx->argv[1], false);
504 print_ls(ls, &ctx->output);
507 NBREC_LOGICAL_SWITCH_FOR_EACH(ls, ctx->idl) {
508 print_ls(ls, &ctx->output);
511 const struct nbrec_logical_router *lr;
513 if (ctx->argc == 2) {
514 lr = lr_by_name_or_uuid(ctx, ctx->argv[1], false);
516 print_lr(lr, &ctx->output);
519 NBREC_LOGICAL_ROUTER_FOR_EACH(lr, ctx->idl) {
520 print_lr(lr, &ctx->output);
526 nbctl_ls_add(struct ctl_context *ctx)
528 const char *ls_name = ctx->argc == 2 ? ctx->argv[1] : NULL;
530 bool may_exist = shash_find(&ctx->options, "--may-exist") != NULL;
531 bool add_duplicate = shash_find(&ctx->options, "--add-duplicate") != NULL;
532 if (may_exist && add_duplicate) {
533 ctl_fatal("--may-exist and --add-duplicate may not be used together");
537 if (!add_duplicate) {
538 const struct nbrec_logical_switch *ls;
539 NBREC_LOGICAL_SWITCH_FOR_EACH (ls, ctx->idl) {
540 if (!strcmp(ls->name, ls_name)) {
544 ctl_fatal("%s: a switch with this name already exists",
549 } else if (may_exist) {
550 ctl_fatal("--may-exist requires specifying a name");
551 } else if (add_duplicate) {
552 ctl_fatal("--add-duplicate requires specifying a name");
555 struct nbrec_logical_switch *ls;
556 ls = nbrec_logical_switch_insert(ctx->txn);
558 nbrec_logical_switch_set_name(ls, ls_name);
563 nbctl_ls_del(struct ctl_context *ctx)
565 bool must_exist = !shash_find(&ctx->options, "--if-exists");
566 const char *id = ctx->argv[1];
567 const struct nbrec_logical_switch *ls;
569 ls = ls_by_name_or_uuid(ctx, id, must_exist);
574 nbrec_logical_switch_delete(ls);
578 nbctl_ls_list(struct ctl_context *ctx)
580 const struct nbrec_logical_switch *ls;
581 struct smap lswitches;
583 smap_init(&lswitches);
584 NBREC_LOGICAL_SWITCH_FOR_EACH(ls, ctx->idl) {
585 smap_add_format(&lswitches, ls->name, UUID_FMT " (%s)",
586 UUID_ARGS(&ls->header_.uuid), ls->name);
588 const struct smap_node **nodes = smap_sort(&lswitches);
589 for (size_t i = 0; i < smap_count(&lswitches); i++) {
590 const struct smap_node *node = nodes[i];
591 ds_put_format(&ctx->output, "%s\n", node->value);
593 smap_destroy(&lswitches);
597 static const struct nbrec_logical_switch_port *
598 lsp_by_name_or_uuid(struct ctl_context *ctx, const char *id,
601 const struct nbrec_logical_switch_port *lsp = NULL;
603 struct uuid lsp_uuid;
604 bool is_uuid = uuid_from_string(&lsp_uuid, id);
606 lsp = nbrec_logical_switch_port_get_for_uuid(ctx->idl, &lsp_uuid);
610 NBREC_LOGICAL_SWITCH_PORT_FOR_EACH(lsp, ctx->idl) {
611 if (!strcmp(lsp->name, id)) {
617 if (!lsp && must_exist) {
618 ctl_fatal("%s: port %s not found", id, is_uuid ? "UUID" : "name");
624 /* Returns the logical switch that contains 'lsp'. */
625 static const struct nbrec_logical_switch *
626 lsp_to_ls(const struct ovsdb_idl *idl,
627 const struct nbrec_logical_switch_port *lsp)
629 const struct nbrec_logical_switch *ls;
630 NBREC_LOGICAL_SWITCH_FOR_EACH (ls, idl) {
631 for (size_t i = 0; i < ls->n_ports; i++) {
632 if (ls->ports[i] == lsp) {
638 /* Can't happen because of the database schema */
639 ctl_fatal("logical port %s is not part of any logical switch",
644 ls_get_name(const struct nbrec_logical_switch *ls,
645 char uuid_s[UUID_LEN + 1], size_t uuid_s_size)
650 snprintf(uuid_s, uuid_s_size, UUID_FMT, UUID_ARGS(&ls->header_.uuid));
655 nbctl_lsp_add(struct ctl_context *ctx)
657 bool may_exist = shash_find(&ctx->options, "--may-exist") != NULL;
659 const struct nbrec_logical_switch *ls;
660 ls = ls_by_name_or_uuid(ctx, ctx->argv[1], true);
662 const char *parent_name;
664 if (ctx->argc == 3) {
667 } else if (ctx->argc == 5) {
669 parent_name = ctx->argv[3];
670 if (!ovs_scan(ctx->argv[4], "%"SCNd64, &tag)
671 || tag < 0 || tag > 4095) {
672 ctl_fatal("%s: invalid tag", ctx->argv[4]);
675 ctl_fatal("lsp-add with parent must also specify a tag");
678 const char *lsp_name = ctx->argv[2];
679 const struct nbrec_logical_switch_port *lsp;
680 lsp = lsp_by_name_or_uuid(ctx, lsp_name, false);
683 ctl_fatal("%s: a port with this name already exists",
687 const struct nbrec_logical_switch *lsw;
688 lsw = lsp_to_ls(ctx->idl, lsp);
690 char uuid_s[UUID_LEN + 1];
691 ctl_fatal("%s: port already exists but in switch %s", lsp_name,
692 ls_get_name(lsw, uuid_s, sizeof uuid_s));
696 if (!lsp->parent_name) {
697 ctl_fatal("%s: port already exists but has no parent",
699 } else if (strcmp(parent_name, lsp->parent_name)) {
700 ctl_fatal("%s: port already exists with different parent %s",
701 lsp_name, lsp->parent_name);
705 ctl_fatal("%s: port already exists but has no tag",
707 } else if (lsp->tag[0] != tag) {
708 ctl_fatal("%s: port already exists with different "
709 "tag %"PRId64, lsp_name, lsp->tag[0]);
712 if (lsp->parent_name) {
713 ctl_fatal("%s: port already exists but has parent %s",
714 lsp_name, lsp->parent_name);
721 /* Create the logical port. */
722 lsp = nbrec_logical_switch_port_insert(ctx->txn);
723 nbrec_logical_switch_port_set_name(lsp, lsp_name);
725 nbrec_logical_switch_port_set_parent_name(lsp, parent_name);
726 nbrec_logical_switch_port_set_tag(lsp, &tag, 1);
729 /* Insert the logical port into the logical switch. */
730 nbrec_logical_switch_verify_ports(ls);
731 struct nbrec_logical_switch_port **new_ports = xmalloc(sizeof *new_ports *
733 memcpy(new_ports, ls->ports, sizeof *new_ports * ls->n_ports);
734 new_ports[ls->n_ports] = CONST_CAST(struct nbrec_logical_switch_port *,
736 nbrec_logical_switch_set_ports(ls, new_ports, ls->n_ports + 1);
740 /* Removes logical switch port 'ls->ports[idx]'. */
742 remove_lsp(const struct nbrec_logical_switch *ls, size_t idx)
744 const struct nbrec_logical_switch_port *lsp = ls->ports[idx];
746 /* First remove 'lsp' from the array of ports. This is what will
747 * actually cause the logical port to be deleted when the transaction is
748 * sent to the database server (due to garbage collection). */
749 struct nbrec_logical_switch_port **new_ports
750 = xmemdup(ls->ports, sizeof *new_ports * ls->n_ports);
751 new_ports[idx] = new_ports[ls->n_ports - 1];
752 nbrec_logical_switch_verify_ports(ls);
753 nbrec_logical_switch_set_ports(ls, new_ports, ls->n_ports - 1);
756 /* Delete 'lsp' from the IDL. This won't have a real effect on the
757 * database server (the IDL will suppress it in fact) but it means that it
758 * won't show up when we iterate with NBREC_LOGICAL_SWITCH_PORT_FOR_EACH
760 nbrec_logical_switch_port_delete(lsp);
764 nbctl_lsp_del(struct ctl_context *ctx)
766 bool must_exist = !shash_find(&ctx->options, "--if-exists");
767 const struct nbrec_logical_switch_port *lsp;
769 lsp = lsp_by_name_or_uuid(ctx, ctx->argv[1], must_exist);
774 /* Find the switch that contains 'lsp', then delete it. */
775 const struct nbrec_logical_switch *ls;
776 NBREC_LOGICAL_SWITCH_FOR_EACH (ls, ctx->idl) {
777 for (size_t i = 0; i < ls->n_ports; i++) {
778 if (ls->ports[i] == lsp) {
785 /* Can't happen because of the database schema. */
786 ctl_fatal("logical port %s is not part of any logical switch",
791 nbctl_lsp_list(struct ctl_context *ctx)
793 const char *id = ctx->argv[1];
794 const struct nbrec_logical_switch *ls;
798 ls = ls_by_name_or_uuid(ctx, id, true);
801 for (i = 0; i < ls->n_ports; i++) {
802 const struct nbrec_logical_switch_port *lsp = ls->ports[i];
803 smap_add_format(&lsps, lsp->name, UUID_FMT " (%s)",
804 UUID_ARGS(&lsp->header_.uuid), lsp->name);
806 const struct smap_node **nodes = smap_sort(&lsps);
807 for (i = 0; i < smap_count(&lsps); i++) {
808 const struct smap_node *node = nodes[i];
809 ds_put_format(&ctx->output, "%s\n", node->value);
816 nbctl_lsp_get_parent(struct ctl_context *ctx)
818 const struct nbrec_logical_switch_port *lsp;
820 lsp = lsp_by_name_or_uuid(ctx, ctx->argv[1], true);
821 if (lsp->parent_name) {
822 ds_put_format(&ctx->output, "%s\n", lsp->parent_name);
827 nbctl_lsp_get_tag(struct ctl_context *ctx)
829 const struct nbrec_logical_switch_port *lsp;
831 lsp = lsp_by_name_or_uuid(ctx, ctx->argv[1], true);
832 if (lsp->n_tag > 0) {
833 ds_put_format(&ctx->output, "%"PRId64"\n", lsp->tag[0]);
838 nbctl_lsp_set_addresses(struct ctl_context *ctx)
840 const char *id = ctx->argv[1];
841 const struct nbrec_logical_switch_port *lsp;
843 lsp = lsp_by_name_or_uuid(ctx, id, true);
846 for (i = 2; i < ctx->argc; i++) {
849 if (strcmp(ctx->argv[i], "unknown")
850 && !ovs_scan(ctx->argv[i], ETH_ADDR_SCAN_FMT,
851 ETH_ADDR_SCAN_ARGS(ea))) {
852 ctl_fatal("%s: Invalid address format. See ovn-nb(5). "
853 "Hint: An Ethernet address must be "
854 "listed before an IP address, together as a single "
855 "argument.", ctx->argv[i]);
859 nbrec_logical_switch_port_set_addresses(lsp,
860 (const char **) ctx->argv + 2, ctx->argc - 2);
864 nbctl_lsp_get_addresses(struct ctl_context *ctx)
866 const char *id = ctx->argv[1];
867 const struct nbrec_logical_switch_port *lsp;
868 struct svec addresses;
872 lsp = lsp_by_name_or_uuid(ctx, id, true);
874 svec_init(&addresses);
875 for (i = 0; i < lsp->n_addresses; i++) {
876 svec_add(&addresses, lsp->addresses[i]);
878 svec_sort(&addresses);
879 SVEC_FOR_EACH(i, mac, &addresses) {
880 ds_put_format(&ctx->output, "%s\n", mac);
882 svec_destroy(&addresses);
886 nbctl_lsp_set_port_security(struct ctl_context *ctx)
888 const char *id = ctx->argv[1];
889 const struct nbrec_logical_switch_port *lsp;
891 lsp = lsp_by_name_or_uuid(ctx, id, true);
892 nbrec_logical_switch_port_set_port_security(lsp,
893 (const char **) ctx->argv + 2, ctx->argc - 2);
897 nbctl_lsp_get_port_security(struct ctl_context *ctx)
899 const char *id = ctx->argv[1];
900 const struct nbrec_logical_switch_port *lsp;
905 lsp = lsp_by_name_or_uuid(ctx, id, true);
907 for (i = 0; i < lsp->n_port_security; i++) {
908 svec_add(&addrs, lsp->port_security[i]);
911 SVEC_FOR_EACH(i, addr, &addrs) {
912 ds_put_format(&ctx->output, "%s\n", addr);
914 svec_destroy(&addrs);
918 nbctl_lsp_get_up(struct ctl_context *ctx)
920 const char *id = ctx->argv[1];
921 const struct nbrec_logical_switch_port *lsp;
923 lsp = lsp_by_name_or_uuid(ctx, id, true);
924 ds_put_format(&ctx->output,
925 "%s\n", (lsp->up && *lsp->up) ? "up" : "down");
929 parse_enabled(const char *state)
931 if (!strcasecmp(state, "enabled")) {
933 } else if (!strcasecmp(state, "disabled")) {
936 ctl_fatal("%s: state must be \"enabled\" or \"disabled\"", state);
941 nbctl_lsp_set_enabled(struct ctl_context *ctx)
943 const char *id = ctx->argv[1];
944 const char *state = ctx->argv[2];
945 const struct nbrec_logical_switch_port *lsp;
947 lsp = lsp_by_name_or_uuid(ctx, id, true);
948 bool enabled = parse_enabled(state);
949 nbrec_logical_switch_port_set_enabled(lsp, &enabled, 1);
953 nbctl_lsp_get_enabled(struct ctl_context *ctx)
955 const char *id = ctx->argv[1];
956 const struct nbrec_logical_switch_port *lsp;
958 lsp = lsp_by_name_or_uuid(ctx, id, true);
959 ds_put_format(&ctx->output, "%s\n",
960 !lsp->enabled || *lsp->enabled ? "enabled" : "disabled");
964 nbctl_lsp_set_type(struct ctl_context *ctx)
966 const char *id = ctx->argv[1];
967 const char *type = ctx->argv[2];
968 const struct nbrec_logical_switch_port *lsp;
970 lsp = lsp_by_name_or_uuid(ctx, id, true);
971 nbrec_logical_switch_port_set_type(lsp, type);
975 nbctl_lsp_get_type(struct ctl_context *ctx)
977 const char *id = ctx->argv[1];
978 const struct nbrec_logical_switch_port *lsp;
980 lsp = lsp_by_name_or_uuid(ctx, id, true);
981 ds_put_format(&ctx->output, "%s\n", lsp->type);
985 nbctl_lsp_set_options(struct ctl_context *ctx)
987 const char *id = ctx->argv[1];
988 const struct nbrec_logical_switch_port *lsp;
990 struct smap options = SMAP_INITIALIZER(&options);
992 lsp = lsp_by_name_or_uuid(ctx, id, true);
993 for (i = 2; i < ctx->argc; i++) {
995 value = xstrdup(ctx->argv[i]);
996 key = strsep(&value, "=");
998 smap_add(&options, key, value);
1003 nbrec_logical_switch_port_set_options(lsp, &options);
1005 smap_destroy(&options);
1009 nbctl_lsp_get_options(struct ctl_context *ctx)
1011 const char *id = ctx->argv[1];
1012 const struct nbrec_logical_switch_port *lsp;
1013 struct smap_node *node;
1015 lsp = lsp_by_name_or_uuid(ctx, id, true);
1016 SMAP_FOR_EACH(node, &lsp->options) {
1017 ds_put_format(&ctx->output, "%s=%s\n", node->key, node->value);
1027 dir_encode(const char *dir)
1029 if (!strcmp(dir, "from-lport")) {
1030 return DIR_FROM_LPORT;
1031 } else if (!strcmp(dir, "to-lport")) {
1032 return DIR_TO_LPORT;
1039 acl_cmp(const void *acl1_, const void *acl2_)
1041 const struct nbrec_acl *const *acl1p = acl1_;
1042 const struct nbrec_acl *const *acl2p = acl2_;
1043 const struct nbrec_acl *acl1 = *acl1p;
1044 const struct nbrec_acl *acl2 = *acl2p;
1046 int dir1 = dir_encode(acl1->direction);
1047 int dir2 = dir_encode(acl2->direction);
1050 return dir1 < dir2 ? -1 : 1;
1051 } else if (acl1->priority != acl2->priority) {
1052 return acl1->priority > acl2->priority ? -1 : 1;
1054 return strcmp(acl1->match, acl2->match);
1059 nbctl_acl_list(struct ctl_context *ctx)
1061 const struct nbrec_logical_switch *ls;
1062 const struct nbrec_acl **acls;
1065 ls = ls_by_name_or_uuid(ctx, ctx->argv[1], true);
1067 acls = xmalloc(sizeof *acls * ls->n_acls);
1068 for (i = 0; i < ls->n_acls; i++) {
1069 acls[i] = ls->acls[i];
1072 qsort(acls, ls->n_acls, sizeof *acls, acl_cmp);
1074 for (i = 0; i < ls->n_acls; i++) {
1075 const struct nbrec_acl *acl = acls[i];
1076 ds_put_format(&ctx->output, "%10s %5"PRId64" (%s) %s%s\n",
1077 acl->direction, acl->priority,
1078 acl->match, acl->action, acl->log ? " log" : "");
1085 parse_direction(const char *arg)
1087 /* Validate direction. Only require the first letter. */
1088 if (arg[0] == 't') {
1090 } else if (arg[0] == 'f') {
1091 return "from-lport";
1093 ctl_fatal("%s: direction must be \"to-lport\" or \"from-lport\"", arg);
1098 parse_priority(const char *arg)
1100 /* Validate priority. */
1102 if (!ovs_scan(arg, "%"SCNd64, &priority)
1103 || priority < 0 || priority > 32767) {
1104 ctl_fatal("%s: priority must in range 0...32767", arg);
1110 nbctl_acl_add(struct ctl_context *ctx)
1112 const struct nbrec_logical_switch *ls;
1113 const char *action = ctx->argv[5];
1115 ls = ls_by_name_or_uuid(ctx, ctx->argv[1], true);
1117 const char *direction = parse_direction(ctx->argv[2]);
1118 int64_t priority = parse_priority(ctx->argv[3]);
1120 /* Validate action. */
1121 if (strcmp(action, "allow") && strcmp(action, "allow-related")
1122 && strcmp(action, "drop") && strcmp(action, "reject")) {
1123 ctl_fatal("%s: action must be one of \"allow\", \"allow-related\", "
1124 "\"drop\", and \"reject\"", action);
1128 /* Create the acl. */
1129 struct nbrec_acl *acl = nbrec_acl_insert(ctx->txn);
1130 nbrec_acl_set_priority(acl, priority);
1131 nbrec_acl_set_direction(acl, direction);
1132 nbrec_acl_set_match(acl, ctx->argv[4]);
1133 nbrec_acl_set_action(acl, action);
1134 if (shash_find(&ctx->options, "--log") != NULL) {
1135 nbrec_acl_set_log(acl, true);
1138 /* Insert the acl into the logical switch. */
1139 nbrec_logical_switch_verify_acls(ls);
1140 struct nbrec_acl **new_acls = xmalloc(sizeof *new_acls * (ls->n_acls + 1));
1141 memcpy(new_acls, ls->acls, sizeof *new_acls * ls->n_acls);
1142 new_acls[ls->n_acls] = acl;
1143 nbrec_logical_switch_set_acls(ls, new_acls, ls->n_acls + 1);
1148 nbctl_acl_del(struct ctl_context *ctx)
1150 const struct nbrec_logical_switch *ls;
1151 ls = ls_by_name_or_uuid(ctx, ctx->argv[1], true);
1153 if (ctx->argc != 2 && ctx->argc != 3 && ctx->argc != 5) {
1154 ctl_fatal("cannot specify priority without match");
1157 if (ctx->argc == 2) {
1158 /* If direction, priority, and match are not specified, delete
1160 nbrec_logical_switch_verify_acls(ls);
1161 nbrec_logical_switch_set_acls(ls, NULL, 0);
1165 const char *direction = parse_direction(ctx->argv[2]);
1167 /* If priority and match are not specified, delete all ACLs with the
1168 * specified direction. */
1169 if (ctx->argc == 3) {
1170 struct nbrec_acl **new_acls = xmalloc(sizeof *new_acls * ls->n_acls);
1173 for (size_t i = 0; i < ls->n_acls; i++) {
1174 if (strcmp(direction, ls->acls[i]->direction)) {
1175 new_acls[n_acls++] = ls->acls[i];
1179 nbrec_logical_switch_verify_acls(ls);
1180 nbrec_logical_switch_set_acls(ls, new_acls, n_acls);
1185 int64_t priority = parse_priority(ctx->argv[3]);
1187 /* Remove the matching rule. */
1188 for (size_t i = 0; i < ls->n_acls; i++) {
1189 struct nbrec_acl *acl = ls->acls[i];
1191 if (priority == acl->priority && !strcmp(ctx->argv[4], acl->match) &&
1192 !strcmp(direction, acl->direction)) {
1193 struct nbrec_acl **new_acls
1194 = xmemdup(ls->acls, sizeof *new_acls * ls->n_acls);
1195 new_acls[i] = ls->acls[ls->n_acls - 1];
1196 nbrec_logical_switch_verify_acls(ls);
1197 nbrec_logical_switch_set_acls(ls, new_acls,
1206 nbctl_lr_add(struct ctl_context *ctx)
1208 const char *lr_name = ctx->argc == 2 ? ctx->argv[1] : NULL;
1210 bool may_exist = shash_find(&ctx->options, "--may-exist") != NULL;
1211 bool add_duplicate = shash_find(&ctx->options, "--add-duplicate") != NULL;
1212 if (may_exist && add_duplicate) {
1213 ctl_fatal("--may-exist and --add-duplicate may not be used together");
1217 if (!add_duplicate) {
1218 const struct nbrec_logical_router *lr;
1219 NBREC_LOGICAL_ROUTER_FOR_EACH (lr, ctx->idl) {
1220 if (!strcmp(lr->name, lr_name)) {
1224 ctl_fatal("%s: a router with this name already exists",
1229 } else if (may_exist) {
1230 ctl_fatal("--may-exist requires specifying a name");
1231 } else if (add_duplicate) {
1232 ctl_fatal("--add-duplicate requires specifying a name");
1235 struct nbrec_logical_router *lr;
1236 lr = nbrec_logical_router_insert(ctx->txn);
1238 nbrec_logical_router_set_name(lr, lr_name);
1243 nbctl_lr_del(struct ctl_context *ctx)
1245 bool must_exist = !shash_find(&ctx->options, "--if-exists");
1246 const char *id = ctx->argv[1];
1247 const struct nbrec_logical_router *lr;
1249 lr = lr_by_name_or_uuid(ctx, id, must_exist);
1254 nbrec_logical_router_delete(lr);
1258 nbctl_lr_list(struct ctl_context *ctx)
1260 const struct nbrec_logical_router *lr;
1264 NBREC_LOGICAL_ROUTER_FOR_EACH(lr, ctx->idl) {
1265 smap_add_format(&lrs, lr->name, UUID_FMT " (%s)",
1266 UUID_ARGS(&lr->header_.uuid), lr->name);
1268 const struct smap_node **nodes = smap_sort(&lrs);
1269 for (size_t i = 0; i < smap_count(&lrs); i++) {
1270 const struct smap_node *node = nodes[i];
1271 ds_put_format(&ctx->output, "%s\n", node->value);
1277 /* The caller must free the returned string. */
1279 normalize_ipv4_prefix(ovs_be32 ipv4, unsigned int plen)
1281 ovs_be32 network = ipv4 & be32_prefix_mask(plen);
1283 return xasprintf(IP_FMT, IP_ARGS(network));
1285 return xasprintf(IP_FMT"/%d", IP_ARGS(network), plen);
1289 /* The caller must free the returned string. */
1291 normalize_ipv6_prefix(struct in6_addr ipv6, unsigned int plen)
1293 char network_s[INET6_ADDRSTRLEN];
1295 struct in6_addr mask = ipv6_create_mask(plen);
1296 struct in6_addr network = ipv6_addr_bitand(&ipv6, &mask);
1298 inet_ntop(AF_INET6, &network, network_s, INET6_ADDRSTRLEN);
1300 return xasprintf("%s", network_s);
1302 return xasprintf("%s/%d", network_s, plen);
1306 /* The caller must free the returned string. */
1308 normalize_prefix_str(const char *orig_prefix)
1314 error = ip_parse_cidr(orig_prefix, &ipv4, &plen);
1316 return normalize_ipv4_prefix(ipv4, plen);
1318 struct in6_addr ipv6;
1321 error = ipv6_parse_cidr(orig_prefix, &ipv6, &plen);
1326 return normalize_ipv6_prefix(ipv6, plen);
1331 nbctl_lr_route_add(struct ctl_context *ctx)
1333 const struct nbrec_logical_router *lr;
1334 lr = lr_by_name_or_uuid(ctx, ctx->argv[1], true);
1335 char *prefix, *next_hop;
1337 prefix = normalize_prefix_str(ctx->argv[2]);
1339 ctl_fatal("bad prefix argument: %s", ctx->argv[2]);
1342 next_hop = normalize_prefix_str(ctx->argv[3]);
1344 ctl_fatal("bad next hop argument: %s", ctx->argv[3]);
1347 if (strchr(prefix, '.')) {
1349 if (!ip_parse(ctx->argv[3], &hop_ipv4)) {
1350 ctl_fatal("bad IPv4 nexthop argument: %s", ctx->argv[3]);
1353 struct in6_addr hop_ipv6;
1354 if (!ipv6_parse(ctx->argv[3], &hop_ipv6)) {
1355 ctl_fatal("bad IPv6 nexthop argument: %s", ctx->argv[3]);
1359 bool may_exist = shash_find(&ctx->options, "--may-exist") != NULL;
1360 for (int i = 0; i < lr->n_static_routes; i++) {
1361 const struct nbrec_logical_router_static_route *route
1362 = lr->static_routes[i];
1365 rt_prefix = normalize_prefix_str(lr->static_routes[i]->ip_prefix);
1367 /* Ignore existing prefix we couldn't parse. */
1371 if (strcmp(rt_prefix, prefix)) {
1377 ctl_fatal("duplicate prefix: %s", prefix);
1380 /* Update the next hop for an existing route. */
1381 nbrec_logical_router_verify_static_routes(lr);
1382 nbrec_logical_router_static_route_verify_ip_prefix(route);
1383 nbrec_logical_router_static_route_verify_nexthop(route);
1384 nbrec_logical_router_static_route_set_ip_prefix(route, prefix);
1385 nbrec_logical_router_static_route_set_nexthop(route, next_hop);
1392 struct nbrec_logical_router_static_route *route;
1393 route = nbrec_logical_router_static_route_insert(ctx->txn);
1394 nbrec_logical_router_static_route_set_ip_prefix(route, prefix);
1395 nbrec_logical_router_static_route_set_nexthop(route, next_hop);
1396 if (ctx->argc == 5) {
1397 nbrec_logical_router_static_route_set_output_port(route, ctx->argv[4]);
1400 nbrec_logical_router_verify_static_routes(lr);
1401 struct nbrec_logical_router_static_route **new_routes
1402 = xmalloc(sizeof *new_routes * (lr->n_static_routes + 1));
1403 memcpy(new_routes, lr->static_routes,
1404 sizeof *new_routes * lr->n_static_routes);
1405 new_routes[lr->n_static_routes] = route;
1406 nbrec_logical_router_set_static_routes(lr, new_routes,
1407 lr->n_static_routes + 1);
1414 nbctl_lr_route_del(struct ctl_context *ctx)
1416 const struct nbrec_logical_router *lr;
1417 lr = lr_by_name_or_uuid(ctx, ctx->argv[1], true);
1419 if (ctx->argc == 2) {
1420 /* If a prefix is not specified, delete all routes. */
1421 nbrec_logical_router_set_static_routes(lr, NULL, 0);
1425 char *prefix = normalize_prefix_str(ctx->argv[2]);
1427 ctl_fatal("bad prefix argument: %s", ctx->argv[2]);
1430 for (int i = 0; i < lr->n_static_routes; i++) {
1431 char *rt_prefix = normalize_prefix_str(lr->static_routes[i]->ip_prefix);
1433 /* Ignore existing prefix we couldn't parse. */
1437 if (!strcmp(prefix, rt_prefix)) {
1438 struct nbrec_logical_router_static_route **new_routes
1439 = xmemdup(lr->static_routes,
1440 sizeof *new_routes * lr->n_static_routes);
1442 new_routes[i] = lr->static_routes[lr->n_static_routes - 1];
1443 nbrec_logical_router_verify_static_routes(lr);
1444 nbrec_logical_router_set_static_routes(lr, new_routes,
1445 lr->n_static_routes - 1);
1454 if (!shash_find(&ctx->options, "--if-exists")) {
1455 ctl_fatal("no matching prefix: %s", prefix);
1460 static const struct nbrec_logical_router_port *
1461 lrp_by_name_or_uuid(struct ctl_context *ctx, const char *id, bool must_exist)
1463 const struct nbrec_logical_router_port *lrp = NULL;
1465 struct uuid lrp_uuid;
1466 bool is_uuid = uuid_from_string(&lrp_uuid, id);
1468 lrp = nbrec_logical_router_port_get_for_uuid(ctx->idl, &lrp_uuid);
1472 NBREC_LOGICAL_ROUTER_PORT_FOR_EACH(lrp, ctx->idl) {
1473 if (!strcmp(lrp->name, id)) {
1479 if (!lrp && must_exist) {
1480 ctl_fatal("%s: port %s not found", id, is_uuid ? "UUID" : "name");
1486 /* Returns the logical router that contains 'lrp'. */
1487 static const struct nbrec_logical_router *
1488 lrp_to_lr(const struct ovsdb_idl *idl,
1489 const struct nbrec_logical_router_port *lrp)
1491 const struct nbrec_logical_router *lr;
1492 NBREC_LOGICAL_ROUTER_FOR_EACH (lr, idl) {
1493 for (size_t i = 0; i < lr->n_ports; i++) {
1494 if (lr->ports[i] == lrp) {
1500 /* Can't happen because of the database schema */
1501 ctl_fatal("port %s is not part of any logical router",
1506 lr_get_name(const struct nbrec_logical_router *lr, char uuid_s[UUID_LEN + 1],
1512 snprintf(uuid_s, uuid_s_size, UUID_FMT, UUID_ARGS(&lr->header_.uuid));
1517 nbctl_lrp_add(struct ctl_context *ctx)
1519 bool may_exist = shash_find(&ctx->options, "--may-exist") != NULL;
1521 const struct nbrec_logical_router *lr;
1522 lr = lr_by_name_or_uuid(ctx, ctx->argv[1], true);
1524 const char *lrp_name = ctx->argv[2];
1525 const char *mac = ctx->argv[3];
1526 const char *network = ctx->argv[4];
1527 const char *peer = (ctx->argc == 6) ? ctx->argv[5] : NULL;
1529 const struct nbrec_logical_router_port *lrp;
1530 lrp = lrp_by_name_or_uuid(ctx, lrp_name, false);
1533 ctl_fatal("%s: a port with this name already exists",
1537 const struct nbrec_logical_router *bound_lr;
1538 bound_lr = lrp_to_lr(ctx->idl, lrp);
1539 if (bound_lr != lr) {
1540 char uuid_s[UUID_LEN + 1];
1541 ctl_fatal("%s: port already exists but in router %s", lrp_name,
1542 lr_get_name(bound_lr, uuid_s, sizeof uuid_s));
1545 if (strcmp(mac, lrp->mac)) {
1546 ctl_fatal("%s: port already exists with mac %s", lrp_name,
1550 if (strcmp(network, lrp->network)) {
1551 ctl_fatal("%s: port already exists with network %s", lrp_name,
1555 if ((!peer != !lrp->peer) ||
1556 (lrp->peer && strcmp(peer, lrp->peer))) {
1557 ctl_fatal("%s: port already exists with mismatching peer",
1565 if (!ovs_scan(mac, ETH_ADDR_SCAN_FMT, ETH_ADDR_SCAN_ARGS(ea))) {
1566 ctl_fatal("%s: invalid mac address.", mac);
1571 char *error = ip_parse_cidr(network, &ipv4, &plen);
1574 struct in6_addr ipv6;
1575 error = ipv6_parse_cidr(network, &ipv6, &plen);
1578 ctl_fatal("%s: invalid network address.", network);
1582 /* Create the logical port. */
1583 lrp = nbrec_logical_router_port_insert(ctx->txn);
1584 nbrec_logical_router_port_set_name(lrp, lrp_name);
1585 nbrec_logical_router_port_set_mac(lrp, mac);
1586 nbrec_logical_router_port_set_network(lrp, network);
1588 nbrec_logical_router_port_set_peer(lrp, peer);
1591 /* Insert the logical port into the logical router. */
1592 nbrec_logical_router_verify_ports(lr);
1593 struct nbrec_logical_router_port **new_ports = xmalloc(sizeof *new_ports *
1595 memcpy(new_ports, lr->ports, sizeof *new_ports * lr->n_ports);
1596 new_ports[lr->n_ports] = CONST_CAST(struct nbrec_logical_router_port *,
1598 nbrec_logical_router_set_ports(lr, new_ports, lr->n_ports + 1);
1602 /* Removes logical router port 'lr->ports[idx]'. */
1604 remove_lrp(const struct nbrec_logical_router *lr, size_t idx)
1606 const struct nbrec_logical_router_port *lrp = lr->ports[idx];
1608 /* First remove 'lrp' from the array of ports. This is what will
1609 * actually cause the logical port to be deleted when the transaction is
1610 * sent to the database server (due to garbage collection). */
1611 struct nbrec_logical_router_port **new_ports
1612 = xmemdup(lr->ports, sizeof *new_ports * lr->n_ports);
1613 new_ports[idx] = new_ports[lr->n_ports - 1];
1614 nbrec_logical_router_verify_ports(lr);
1615 nbrec_logical_router_set_ports(lr, new_ports, lr->n_ports - 1);
1618 /* Delete 'lrp' from the IDL. This won't have a real effect on
1619 * the database server (the IDL will suppress it in fact) but it
1620 * means that it won't show up when we iterate with
1621 * NBREC_LOGICAL_ROUTER_PORT_FOR_EACH later. */
1622 nbrec_logical_router_port_delete(lrp);
1626 nbctl_lrp_del(struct ctl_context *ctx)
1628 bool must_exist = !shash_find(&ctx->options, "--if-exists");
1629 const struct nbrec_logical_router_port *lrp;
1631 lrp = lrp_by_name_or_uuid(ctx, ctx->argv[1], must_exist);
1636 /* Find the router that contains 'lrp', then delete it. */
1637 const struct nbrec_logical_router *lr;
1638 NBREC_LOGICAL_ROUTER_FOR_EACH (lr, ctx->idl) {
1639 for (size_t i = 0; i < lr->n_ports; i++) {
1640 if (lr->ports[i] == lrp) {
1647 /* Can't happen because of the database schema. */
1648 ctl_fatal("logical port %s is not part of any logical router",
1652 /* Print a list of logical router ports. */
1654 nbctl_lrp_list(struct ctl_context *ctx)
1656 const char *id = ctx->argv[1];
1657 const struct nbrec_logical_router *lr;
1661 lr = lr_by_name_or_uuid(ctx, id, true);
1664 for (i = 0; i < lr->n_ports; i++) {
1665 const struct nbrec_logical_router_port *lrp = lr->ports[i];
1666 smap_add_format(&lrps, lrp->name, UUID_FMT " (%s)",
1667 UUID_ARGS(&lrp->header_.uuid), lrp->name);
1669 const struct smap_node **nodes = smap_sort(&lrps);
1670 for (i = 0; i < smap_count(&lrps); i++) {
1671 const struct smap_node *node = nodes[i];
1672 ds_put_format(&ctx->output, "%s\n", node->value);
1674 smap_destroy(&lrps);
1678 /* Set the logical router port admin-enabled state. */
1680 nbctl_lrp_set_enabled(struct ctl_context *ctx)
1682 const char *id = ctx->argv[1];
1683 const char *state = ctx->argv[2];
1684 const struct nbrec_logical_router_port *lrp;
1686 lrp = lrp_by_name_or_uuid(ctx, id, true);
1691 bool enabled = parse_enabled(state);
1692 nbrec_logical_router_port_set_enabled(lrp, &enabled, 1);
1695 /* Print admin-enabled state for logical router port. */
1697 nbctl_lrp_get_enabled(struct ctl_context *ctx)
1699 const char *id = ctx->argv[1];
1700 const struct nbrec_logical_router_port *lrp;
1702 lrp = lrp_by_name_or_uuid(ctx, id, true);
1707 ds_put_format(&ctx->output, "%s\n",
1709 *lrp->enabled ? "enabled" : "disabled");
1715 const struct nbrec_logical_router_static_route *route;
1719 ipv4_route_cmp(const void *route1_, const void *route2_)
1721 const struct ipv4_route *route1p = route1_;
1722 const struct ipv4_route *route2p = route2_;
1724 if (route1p->plen != route2p->plen) {
1725 return route1p->plen > route2p->plen ? -1 : 1;
1726 } else if (route1p->addr != route2p->addr) {
1727 return ntohl(route1p->addr) < ntohl(route2p->addr) ? -1 : 1;
1735 struct in6_addr addr;
1736 const struct nbrec_logical_router_static_route *route;
1740 ipv6_route_cmp(const void *route1_, const void *route2_)
1742 const struct ipv6_route *route1p = route1_;
1743 const struct ipv6_route *route2p = route2_;
1745 if (route1p->plen != route2p->plen) {
1746 return route1p->plen > route2p->plen ? -1 : 1;
1748 return memcmp(&route1p->addr, &route2p->addr, sizeof(route1p->addr));
1752 print_route(const struct nbrec_logical_router_static_route *route, struct ds *s)
1755 char *prefix = normalize_prefix_str(route->ip_prefix);
1756 char *next_hop = normalize_prefix_str(route->nexthop);
1757 ds_put_format(s, "%25s %25s", prefix, next_hop);
1761 if (route->output_port) {
1762 ds_put_format(s, " %s", route->output_port);
1764 ds_put_char(s, '\n');
1768 nbctl_lr_route_list(struct ctl_context *ctx)
1770 const struct nbrec_logical_router *lr;
1771 struct ipv4_route *ipv4_routes;
1772 struct ipv6_route *ipv6_routes;
1773 size_t n_ipv4_routes = 0;
1774 size_t n_ipv6_routes = 0;
1776 lr = lr_by_name_or_uuid(ctx, ctx->argv[1], true);
1778 ipv4_routes = xmalloc(sizeof *ipv4_routes * lr->n_static_routes);
1779 ipv6_routes = xmalloc(sizeof *ipv6_routes * lr->n_static_routes);
1781 for (int i = 0; i < lr->n_static_routes; i++) {
1782 const struct nbrec_logical_router_static_route *route
1783 = lr->static_routes[i];
1788 error = ip_parse_cidr(route->ip_prefix, &ipv4, &plen);
1790 ipv4_routes[n_ipv4_routes].plen = plen;
1791 ipv4_routes[n_ipv4_routes].addr = ipv4;
1792 ipv4_routes[n_ipv4_routes].route = route;
1797 struct in6_addr ipv6;
1798 if (!ipv6_parse_cidr(route->ip_prefix, &ipv6, &plen)) {
1799 ipv6_routes[n_ipv6_routes].plen = plen;
1800 ipv6_routes[n_ipv6_routes].addr = ipv6;
1801 ipv6_routes[n_ipv6_routes].route = route;
1804 /* Invalid prefix. */
1805 VLOG_WARN("router "UUID_FMT" (%s) has invalid prefix: %s",
1806 UUID_ARGS(&lr->header_.uuid), lr->name,
1814 qsort(ipv4_routes, n_ipv4_routes, sizeof *ipv4_routes, ipv4_route_cmp);
1815 qsort(ipv6_routes, n_ipv6_routes, sizeof *ipv6_routes, ipv6_route_cmp);
1817 if (n_ipv4_routes) {
1818 ds_put_cstr(&ctx->output, "IPv4 Routes\n");
1820 for (int i = 0; i < n_ipv4_routes; i++) {
1821 print_route(ipv4_routes[i].route, &ctx->output);
1824 if (n_ipv6_routes) {
1825 ds_put_format(&ctx->output, "%sIPv6 Routes\n",
1826 n_ipv4_routes ? "\n" : "");
1828 for (int i = 0; i < n_ipv6_routes; i++) {
1829 print_route(ipv6_routes[i].route, &ctx->output);
1836 static const struct ctl_table_class tables[] = {
1837 {&nbrec_table_logical_switch,
1838 {{&nbrec_table_logical_switch, &nbrec_logical_switch_col_name, NULL},
1839 {NULL, NULL, NULL}}},
1841 {&nbrec_table_logical_switch_port,
1842 {{&nbrec_table_logical_switch_port, &nbrec_logical_switch_port_col_name,
1844 {NULL, NULL, NULL}}},
1847 {{NULL, NULL, NULL},
1848 {NULL, NULL, NULL}}},
1850 {&nbrec_table_logical_router,
1851 {{&nbrec_table_logical_router, &nbrec_logical_router_col_name, NULL},
1852 {NULL, NULL, NULL}}},
1854 {&nbrec_table_logical_router_port,
1855 {{&nbrec_table_logical_router_port, &nbrec_logical_router_port_col_name,
1857 {NULL, NULL, NULL}}},
1859 {&nbrec_table_logical_router_static_route,
1860 {{&nbrec_table_logical_router_static_route, NULL,
1862 {NULL, NULL, NULL}}},
1865 {{&nbrec_table_nat, NULL,
1867 {NULL, NULL, NULL}}},
1869 {NULL, {{NULL, NULL, NULL}, {NULL, NULL, NULL}}}
1873 run_prerequisites(struct ctl_command *commands, size_t n_commands,
1874 struct ovsdb_idl *idl)
1876 struct ctl_command *c;
1878 for (c = commands; c < &commands[n_commands]; c++) {
1879 if (c->syntax->prerequisites) {
1880 struct ctl_context ctx;
1882 ds_init(&c->output);
1885 ctl_context_init(&ctx, c, idl, NULL, NULL, NULL);
1886 (c->syntax->prerequisites)(&ctx);
1887 ctl_context_done(&ctx, c);
1889 ovs_assert(!c->output.string);
1890 ovs_assert(!c->table);
1896 do_nbctl(const char *args, struct ctl_command *commands, size_t n_commands,
1897 struct ovsdb_idl *idl)
1899 struct ovsdb_idl_txn *txn;
1900 enum ovsdb_idl_txn_status status;
1901 struct ovsdb_symbol_table *symtab;
1902 struct ctl_context ctx;
1903 struct ctl_command *c;
1904 struct shash_node *node;
1907 txn = the_idl_txn = ovsdb_idl_txn_create(idl);
1909 ovsdb_idl_txn_set_dry_run(txn);
1912 ovsdb_idl_txn_add_comment(txn, "ovs-nbctl: %s", args);
1914 symtab = ovsdb_symbol_table_create();
1915 for (c = commands; c < &commands[n_commands]; c++) {
1916 ds_init(&c->output);
1919 ctl_context_init(&ctx, NULL, idl, txn, symtab, NULL);
1920 for (c = commands; c < &commands[n_commands]; c++) {
1921 ctl_context_init_command(&ctx, c);
1922 if (c->syntax->run) {
1923 (c->syntax->run)(&ctx);
1925 ctl_context_done_command(&ctx, c);
1927 if (ctx.try_again) {
1928 ctl_context_done(&ctx, NULL);
1932 ctl_context_done(&ctx, NULL);
1934 SHASH_FOR_EACH (node, &symtab->sh) {
1935 struct ovsdb_symbol *symbol = node->data;
1936 if (!symbol->created) {
1937 ctl_fatal("row id \"%s\" is referenced but never created (e.g. "
1938 "with \"-- --id=%s create ...\")",
1939 node->name, node->name);
1941 if (!symbol->strong_ref) {
1942 if (!symbol->weak_ref) {
1943 VLOG_WARN("row id \"%s\" was created but no reference to it "
1944 "was inserted, so it will not actually appear in "
1945 "the database", node->name);
1947 VLOG_WARN("row id \"%s\" was created but only a weak "
1948 "reference to it was inserted, so it will not "
1949 "actually appear in the database", node->name);
1954 status = ovsdb_idl_txn_commit_block(txn);
1955 if (status == TXN_UNCHANGED || status == TXN_SUCCESS) {
1956 for (c = commands; c < &commands[n_commands]; c++) {
1957 if (c->syntax->postprocess) {
1958 ctl_context_init(&ctx, c, idl, txn, symtab, NULL);
1959 (c->syntax->postprocess)(&ctx);
1960 ctl_context_done(&ctx, c);
1964 error = xstrdup(ovsdb_idl_txn_get_error(txn));
1967 case TXN_UNCOMMITTED:
1968 case TXN_INCOMPLETE:
1972 /* Should not happen--we never call ovsdb_idl_txn_abort(). */
1973 ctl_fatal("transaction aborted");
1983 ctl_fatal("transaction error: %s", error);
1985 case TXN_NOT_LOCKED:
1986 /* Should not happen--we never call ovsdb_idl_set_lock(). */
1987 ctl_fatal("database not locked");
1994 ovsdb_symbol_table_destroy(symtab);
1996 for (c = commands; c < &commands[n_commands]; c++) {
1997 struct ds *ds = &c->output;
2000 table_print(c->table, &table_style);
2001 } else if (oneline) {
2005 for (j = 0; j < ds->length; j++) {
2006 int ch = ds->string[j];
2009 fputs("\\n", stdout);
2013 fputs("\\\\", stdout);
2022 fputs(ds_cstr(ds), stdout);
2024 ds_destroy(&c->output);
2025 table_destroy(c->table);
2028 shash_destroy_free_data(&c->options);
2031 ovsdb_idl_txn_destroy(txn);
2032 ovsdb_idl_destroy(idl);
2037 /* Our transaction needs to be rerun, or a prerequisite was not met. Free
2038 * resources and return so that the caller can try again. */
2040 ovsdb_idl_txn_abort(txn);
2041 ovsdb_idl_txn_destroy(txn);
2044 ovsdb_symbol_table_destroy(symtab);
2045 for (c = commands; c < &commands[n_commands]; c++) {
2046 ds_destroy(&c->output);
2047 table_destroy(c->table);
2054 /* Frees the current transaction and the underlying IDL and then calls
2057 * Freeing the transaction and the IDL is not strictly necessary, but it makes
2058 * for a clean memory leak report from valgrind in the normal case. That makes
2059 * it easier to notice real memory leaks. */
2061 nbctl_exit(int status)
2064 ovsdb_idl_txn_abort(the_idl_txn);
2065 ovsdb_idl_txn_destroy(the_idl_txn);
2067 ovsdb_idl_destroy(the_idl);
2071 static const struct ctl_command_syntax nbctl_commands[] = {
2072 { "show", 0, 1, "[SWITCH]", NULL, nbctl_show, NULL, "", RO },
2074 /* logical switch commands. */
2075 { "ls-add", 0, 1, "[SWITCH]", NULL, nbctl_ls_add, NULL,
2076 "--may-exist,--add-duplicate", RW },
2077 { "ls-del", 1, 1, "SWITCH", NULL, nbctl_ls_del, NULL, "--if-exists", RW },
2078 { "ls-list", 0, 0, "", NULL, nbctl_ls_list, NULL, "", RO },
2081 { "acl-add", 5, 5, "SWITCH DIRECTION PRIORITY MATCH ACTION", NULL,
2082 nbctl_acl_add, NULL, "--log", RW },
2083 { "acl-del", 1, 4, "SWITCH [DIRECTION [PRIORITY MATCH]]", NULL,
2084 nbctl_acl_del, NULL, "", RW },
2085 { "acl-list", 1, 1, "SWITCH", NULL, nbctl_acl_list, NULL, "", RO },
2087 /* logical switch port commands. */
2088 { "lsp-add", 2, 4, "SWITCH PORT [PARENT] [TAG]", NULL, nbctl_lsp_add,
2089 NULL, "--may-exist", RW },
2090 { "lsp-del", 1, 1, "PORT", NULL, nbctl_lsp_del, NULL, "--if-exists", RW },
2091 { "lsp-list", 1, 1, "SWITCH", NULL, nbctl_lsp_list, NULL, "", RO },
2092 { "lsp-get-parent", 1, 1, "PORT", NULL, nbctl_lsp_get_parent, NULL,
2094 { "lsp-get-tag", 1, 1, "PORT", NULL, nbctl_lsp_get_tag, NULL, "", RO },
2095 { "lsp-set-addresses", 1, INT_MAX, "PORT [ADDRESS]...", NULL,
2096 nbctl_lsp_set_addresses, NULL, "", RW },
2097 { "lsp-get-addresses", 1, 1, "PORT", NULL, nbctl_lsp_get_addresses, NULL,
2099 { "lsp-set-port-security", 0, INT_MAX, "PORT [ADDRS]...", NULL,
2100 nbctl_lsp_set_port_security, NULL, "", RW },
2101 { "lsp-get-port-security", 1, 1, "PORT", NULL,
2102 nbctl_lsp_get_port_security, NULL, "", RO },
2103 { "lsp-get-up", 1, 1, "PORT", NULL, nbctl_lsp_get_up, NULL, "", RO },
2104 { "lsp-set-enabled", 2, 2, "PORT STATE", NULL, nbctl_lsp_set_enabled,
2106 { "lsp-get-enabled", 1, 1, "PORT", NULL, nbctl_lsp_get_enabled, NULL,
2108 { "lsp-set-type", 2, 2, "PORT TYPE", NULL, nbctl_lsp_set_type, NULL,
2110 { "lsp-get-type", 1, 1, "PORT", NULL, nbctl_lsp_get_type, NULL, "", RO },
2111 { "lsp-set-options", 1, INT_MAX, "PORT KEY=VALUE [KEY=VALUE]...", NULL,
2112 nbctl_lsp_set_options, NULL, "", RW },
2113 { "lsp-get-options", 1, 1, "PORT", NULL, nbctl_lsp_get_options, NULL,
2116 /* logical router commands. */
2117 { "lr-add", 0, 1, "[ROUTER]", NULL, nbctl_lr_add, NULL,
2118 "--may-exist,--add-duplicate", RW },
2119 { "lr-del", 1, 1, "ROUTER", NULL, nbctl_lr_del, NULL, "--if-exists", RW },
2120 { "lr-list", 0, 0, "", NULL, nbctl_lr_list, NULL, "", RO },
2122 /* logical router port commands. */
2123 { "lrp-add", 4, 5, "ROUTER PORT MAC NETWORK [PEER]", NULL, nbctl_lrp_add,
2124 NULL, "--may-exist", RW },
2125 { "lrp-del", 1, 1, "LPORT", NULL, nbctl_lrp_del, NULL, "--if-exists", RW },
2126 { "lrp-list", 1, 1, "ROUTER", NULL, nbctl_lrp_list, NULL, "", RO },
2127 { "lrp-set-enabled", 2, 2, "PORT STATE", NULL, nbctl_lrp_set_enabled,
2129 { "lrp-get-enabled", 1, 1, "PORT", NULL, nbctl_lrp_get_enabled,
2132 /* logical router route commands. */
2133 { "lr-route-add", 3, 4, "ROUTER PREFIX NEXTHOP [PORT]", NULL,
2134 nbctl_lr_route_add, NULL, "--may-exist", RW },
2135 { "lr-route-del", 1, 2, "ROUTER [PREFIX]", NULL, nbctl_lr_route_del,
2136 NULL, "--if-exists", RW },
2137 { "lr-route-list", 1, 1, "ROUTER", NULL, nbctl_lr_route_list, NULL,
2140 {NULL, 0, 0, NULL, NULL, NULL, NULL, "", RO},
2143 /* Registers nbctl and common db commands. */
2145 nbctl_cmd_init(void)
2147 ctl_init(tables, NULL, nbctl_exit);
2148 ctl_register_commands(nbctl_commands);