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 /* --wait=TYPE: Wait for configuration change to take effect? */
53 enum nbctl_wait_type
{
54 NBCTL_WAIT_NONE
, /* Do not wait. */
55 NBCTL_WAIT_SB
, /* Wait for southbound database updates. */
56 NBCTL_WAIT_HV
/* Wait for hypervisors to catch up. */
58 static enum nbctl_wait_type wait_type
= NBCTL_WAIT_NONE
;
60 /* Should we wait (if specified by 'wait_type') even if the commands don't
61 * change the database at all? */
62 static bool force_wait
= false;
64 /* --timeout: Time to wait for a connection to 'db'. */
67 /* Format for table output. */
68 static struct table_style table_style
= TABLE_STYLE_DEFAULT
;
70 /* The IDL we're using and the current transaction, if any.
71 * This is for use by nbctl_exit() only, to allow it to clean up.
72 * Other code should use its context arguments. */
73 static struct ovsdb_idl
*the_idl
;
74 static struct ovsdb_idl_txn
*the_idl_txn
;
75 OVS_NO_RETURN
static void nbctl_exit(int status
);
77 static void nbctl_cmd_init(void);
78 OVS_NO_RETURN
static void usage(void);
79 static void parse_options(int argc
, char *argv
[], struct shash
*local_options
);
80 static const char *nbctl_default_db(void);
81 static void run_prerequisites(struct ctl_command
[], size_t n_commands
,
83 static bool do_nbctl(const char *args
, struct ctl_command
*, size_t n
,
85 static const struct nbrec_dhcp_options
*dhcp_options_get(
86 struct ctl_context
*ctx
, const char *id
, bool must_exist
);
89 main(int argc
, char *argv
[])
91 struct ovsdb_idl
*idl
;
92 struct ctl_command
*commands
;
93 struct shash local_options
;
98 set_program_name(argv
[0]);
99 fatal_ignore_sigpipe();
100 vlog_set_levels(NULL
, VLF_CONSOLE
, VLL_WARN
);
101 vlog_set_levels_from_string_assert("reconnect:warn");
106 /* Log our arguments. This is often valuable for debugging systems. */
107 args
= process_escape_args(argv
);
108 VLOG(ctl_might_write_to_db(argv
) ? VLL_INFO
: VLL_DBG
,
109 "Called as %s", args
);
111 /* Parse command line. */
112 shash_init(&local_options
);
113 parse_options(argc
, argv
, &local_options
);
114 commands
= ctl_parse_commands(argc
- optind
, argv
+ optind
, &local_options
,
121 /* Initialize IDL. */
122 idl
= the_idl
= ovsdb_idl_create(db
, &nbrec_idl_class
, true, false);
123 run_prerequisites(commands
, n_commands
, idl
);
125 /* Execute the commands.
127 * 'seqno' is the database sequence number for which we last tried to
128 * execute our transaction. There's no point in trying to commit more than
129 * once for any given sequence number, because if the transaction fails
130 * it's because the database changed and we need to obtain an up-to-date
131 * view of the database before we try the transaction again. */
132 seqno
= ovsdb_idl_get_seqno(idl
);
135 if (!ovsdb_idl_is_alive(idl
)) {
136 int retval
= ovsdb_idl_get_last_error(idl
);
137 ctl_fatal("%s: database connection failed (%s)",
138 db
, ovs_retval_to_string(retval
));
141 if (seqno
!= ovsdb_idl_get_seqno(idl
)) {
142 seqno
= ovsdb_idl_get_seqno(idl
);
143 if (do_nbctl(args
, commands
, n_commands
, idl
)) {
149 if (seqno
== ovsdb_idl_get_seqno(idl
)) {
157 nbctl_default_db(void)
161 def
= getenv("OVN_NB_DB");
163 def
= xasprintf("unix:%s/ovnnb_db.sock", ovs_rundir());
170 parse_options(int argc
, char *argv
[], struct shash
*local_options
)
173 OPT_DB
= UCHAR_MAX
+ 1,
185 static const struct option global_long_options
[] = {
186 {"db", required_argument
, NULL
, OPT_DB
},
187 {"no-syslog", no_argument
, NULL
, OPT_NO_SYSLOG
},
188 {"no-wait", no_argument
, NULL
, OPT_NO_WAIT
},
189 {"wait", required_argument
, NULL
, OPT_WAIT
},
190 {"dry-run", no_argument
, NULL
, OPT_DRY_RUN
},
191 {"oneline", no_argument
, NULL
, OPT_ONELINE
},
192 {"timeout", required_argument
, NULL
, 't'},
193 {"help", no_argument
, NULL
, 'h'},
194 {"commands", no_argument
, NULL
, OPT_COMMANDS
},
195 {"options", no_argument
, NULL
, OPT_OPTIONS
},
196 {"version", no_argument
, NULL
, 'V'},
198 STREAM_SSL_LONG_OPTIONS
,
202 const int n_global_long_options
= ARRAY_SIZE(global_long_options
) - 1;
203 char *tmp
, *short_options
;
205 struct option
*options
;
206 size_t allocated_options
;
210 tmp
= ovs_cmdl_long_options_to_short_options(global_long_options
);
211 short_options
= xasprintf("+%s", tmp
);
214 /* We want to parse both global and command-specific options here, but
215 * getopt_long() isn't too convenient for the job. We copy our global
216 * options into a dynamic array, then append all of the command-specific
218 options
= xmemdup(global_long_options
, sizeof global_long_options
);
219 allocated_options
= ARRAY_SIZE(global_long_options
);
220 n_options
= n_global_long_options
;
221 ctl_add_cmd_options(&options
, &n_options
, &allocated_options
, OPT_LOCAL
);
222 table_style
.format
= TF_LIST
;
228 c
= getopt_long(argc
, argv
, short_options
, options
, &idx
);
243 vlog_set_levels(&this_module
, VLF_SYSLOG
, VLL_WARN
);
247 wait_type
= NBCTL_WAIT_NONE
;
251 if (!strcmp(optarg
, "none")) {
252 wait_type
= NBCTL_WAIT_NONE
;
253 } else if (!strcmp(optarg
, "sb")) {
254 wait_type
= NBCTL_WAIT_SB
;
255 } else if (!strcmp(optarg
, "hv")) {
256 wait_type
= NBCTL_WAIT_HV
;
258 ctl_fatal("argument to --wait must be "
259 "\"none\", \"sb\", or \"hv\"");
268 if (shash_find(local_options
, options
[idx
].name
)) {
269 ctl_fatal("'%s' option specified multiple times",
272 shash_add_nocopy(local_options
,
273 xasprintf("--%s", options
[idx
].name
),
274 nullable_xstrdup(optarg
));
282 ctl_print_commands();
285 ctl_print_options(global_long_options
);
288 ovs_print_version(0, 0);
289 printf("DB Schema %s\n", nbrec_get_db_version());
293 timeout
= strtoul(optarg
, NULL
, 10);
295 ctl_fatal("value %s on -t or --timeout is invalid", optarg
);
300 TABLE_OPTION_HANDLERS(&table_style
)
301 STREAM_SSL_OPTION_HANDLERS
313 db
= nbctl_default_db();
316 for (i
= n_global_long_options
; options
[i
].name
; i
++) {
317 free(CONST_CAST(char *, options
[i
].name
));
326 %s: OVN northbound DB management utility\n\
327 usage: %s [OPTIONS] COMMAND [ARG...]\n\
330 init initialize the database\n\
331 show print overview of database contents\n\
332 show SWITCH print overview of database contents for SWITCH\n\
333 show ROUTER print overview of database contents for ROUTER\n\
335 Logical switch commands:\n\
336 ls-add [SWITCH] create a logical switch named SWITCH\n\
337 ls-del SWITCH delete SWITCH and all its ports\n\
338 ls-list print the names of all logical switches\n\
341 acl-add SWITCH DIRECTION PRIORITY MATCH ACTION [log]\n\
342 add an ACL to SWITCH\n\
343 acl-del SWITCH [DIRECTION [PRIORITY MATCH]]\n\
344 remove ACLs from SWITCH\n\
345 acl-list SWITCH print ACLs for SWITCH\n\
347 Logical switch port commands:\n\
348 lsp-add SWITCH PORT add logical port PORT on SWITCH\n\
349 lsp-add SWITCH PORT PARENT TAG\n\
350 add logical port PORT on SWITCH with PARENT\n\
352 lsp-del PORT delete PORT from its attached switch\n\
353 lsp-list SWITCH print the names of all logical ports on SWITCH\n\
354 lsp-get-parent PORT get the parent of PORT if set\n\
355 lsp-get-tag PORT get the PORT's tag if set\n\
356 lsp-set-addresses PORT [ADDRESS]...\n\
357 set MAC or MAC+IP addresses for PORT.\n\
358 lsp-get-addresses PORT get a list of MAC or MAC+IP addresses on PORT\n\
359 lsp-set-port-security PORT [ADDRS]...\n\
360 set port security addresses for PORT.\n\
361 lsp-get-port-security PORT get PORT's port security addresses\n\
362 lsp-get-up PORT get state of PORT ('up' or 'down')\n\
363 lsp-set-enabled PORT STATE\n\
364 set administrative state PORT\n\
365 ('enabled' or 'disabled')\n\
366 lsp-get-enabled PORT get administrative state PORT\n\
367 ('enabled' or 'disabled')\n\
368 lsp-set-type PORT TYPE set the type for PORT\n\
369 lsp-get-type PORT get the type for PORT\n\
370 lsp-set-options PORT KEY=VALUE [KEY=VALUE]...\n\
371 set options related to the type of PORT\n\
372 lsp-get-options PORT get the type specific options for PORT\n\
373 lsp-set-dhcpv4-options PORT [DHCP_OPTIONS_UUID]\n\
374 set dhcpv4 options for PORT\n\
375 lsp-get-dhcpv4-options PORT get the dhcpv4 options for PORT\n\
377 Logical router commands:\n\
378 lr-add [ROUTER] create a logical router named ROUTER\n\
379 lr-del ROUTER delete ROUTER and all its ports\n\
380 lr-list print the names of all logical routers\n\
382 Logical router port commands:\n\
383 lrp-add ROUTER PORT MAC NETWORK... [peer=PEER]\n\
384 add logical port PORT on ROUTER\n\
385 lrp-del PORT delete PORT from its attached router\n\
386 lrp-list ROUTER print the names of all ports on ROUTER\n\
387 lrp-set-enabled PORT STATE\n\
388 set administrative state PORT\n\
389 ('enabled' or 'disabled')\n\
390 lrp-get-enabled PORT get administrative state PORT\n\
391 ('enabled' or 'disabled')\n\
394 lr-route-add ROUTER PREFIX NEXTHOP [PORT]\n\
395 add a route to ROUTER\n\
396 lr-route-del ROUTER [PREFIX]\n\
397 remove routes from ROUTER\n\
398 lr-route-list ROUTER print routes for ROUTER\n\
401 DHCP Options commands:\n\
402 dhcp-options-create CIDR [EXTERNAL_IDS]\n\
403 create a DHCP options row with CIDR\n\
404 dhcp-options-del DHCP_OPTIONS_UUID\n\
405 delete DHCP_OPTIONS_UUID\n\
406 dhcp-options-list \n\
407 lists the DHCP_Options rows\n\
408 dhcp-options-set-options DHCP_OPTIONS_UUID KEY=VALUE [KEY=VALUE]...\n\
409 set DHCP options for DHCP_OPTIONS_UUID\n\
410 dhcp-options-get-options DHCO_OPTIONS_UUID \n\
411 displays the DHCP options for DHCP_OPTIONS_UUID\n\
415 Synchronization command (use with --wait=sb|hv):\n\
416 sync wait even for earlier changes to take effect\n\
419 --db=DATABASE connect to DATABASE\n\
421 --no-wait, --wait=none do not wait for OVN reconfiguration (default)\n\
422 --wait=sb wait for southbound database update\n\
423 --wait=hv wait for all chassis to catch up\n\
424 -t, --timeout=SECS wait at most SECS seconds\n\
425 --dry-run do not commit changes to database\n\
426 --oneline print exactly one line of output per command\n",
427 program_name
, program_name
, ctl_get_db_cmd_usage(), nbctl_default_db());
430 --no-syslog equivalent to --verbose=nbctl:syslog:warn\n");
433 -h, --help display this help message\n\
434 -V, --version display version information\n");
439 /* Find a logical router given its id. */
440 static const struct nbrec_logical_router
*
441 lr_by_name_or_uuid(struct ctl_context
*ctx
, const char *id
,
444 const struct nbrec_logical_router
*lr
= NULL
;
445 bool is_uuid
= false;
448 if (uuid_from_string(&lr_uuid
, id
)) {
450 lr
= nbrec_logical_router_get_for_uuid(ctx
->idl
, &lr_uuid
);
454 const struct nbrec_logical_router
*iter
;
456 NBREC_LOGICAL_ROUTER_FOR_EACH(iter
, ctx
->idl
) {
457 if (strcmp(iter
->name
, id
)) {
461 ctl_fatal("Multiple logical routers named '%s'. "
468 if (!lr
&& must_exist
) {
469 ctl_fatal("%s: router %s not found", id
, is_uuid
? "UUID" : "name");
475 static const struct nbrec_logical_switch
*
476 ls_by_name_or_uuid(struct ctl_context
*ctx
, const char *id
, bool must_exist
)
478 const struct nbrec_logical_switch
*ls
= NULL
;
481 bool is_uuid
= uuid_from_string(&ls_uuid
, id
);
483 ls
= nbrec_logical_switch_get_for_uuid(ctx
->idl
, &ls_uuid
);
487 const struct nbrec_logical_switch
*iter
;
489 NBREC_LOGICAL_SWITCH_FOR_EACH(iter
, ctx
->idl
) {
490 if (strcmp(iter
->name
, id
)) {
494 ctl_fatal("Multiple logical switches named '%s'. "
501 if (!ls
&& must_exist
) {
502 ctl_fatal("%s: switch %s not found", id
, is_uuid
? "UUID" : "name");
508 /* Given pointer to logical router, this routine prints the router
511 print_lr(const struct nbrec_logical_router
*lr
, struct ds
*s
)
513 ds_put_format(s
, " router "UUID_FMT
" (%s)\n",
514 UUID_ARGS(&lr
->header_
.uuid
), lr
->name
);
516 for (size_t i
= 0; i
< lr
->n_ports
; i
++) {
517 const struct nbrec_logical_router_port
*lrp
= lr
->ports
[i
];
518 ds_put_format(s
, " port %s\n", lrp
->name
);
520 ds_put_cstr(s
, " mac: ");
521 ds_put_format(s
, "\"%s\"\n", lrp
->mac
);
523 if (lrp
->n_networks
) {
524 ds_put_cstr(s
, " networks: [");
525 for (size_t j
= 0; j
< lrp
->n_networks
; j
++) {
526 ds_put_format(s
, "%s\"%s\"",
530 ds_put_cstr(s
, "]\n");
536 print_ls(const struct nbrec_logical_switch
*ls
, struct ds
*s
)
538 ds_put_format(s
, " switch "UUID_FMT
" (%s)\n",
539 UUID_ARGS(&ls
->header_
.uuid
), ls
->name
);
541 for (size_t i
= 0; i
< ls
->n_ports
; i
++) {
542 const struct nbrec_logical_switch_port
*lsp
= ls
->ports
[i
];
544 ds_put_format(s
, " port %s\n", lsp
->name
);
545 if (lsp
->parent_name
) {
546 ds_put_format(s
, " parent: %s\n", lsp
->parent_name
);
549 ds_put_format(s
, " tag: %"PRIu64
"\n", lsp
->tag
[0]);
551 if (lsp
->n_addresses
) {
552 ds_put_cstr(s
, " addresses: [");
553 for (size_t j
= 0; j
< lsp
->n_addresses
; j
++) {
554 ds_put_format(s
, "%s\"%s\"",
558 ds_put_cstr(s
, "]\n");
564 nbctl_init(struct ctl_context
*ctx OVS_UNUSED
)
569 nbctl_pre_sync(struct ctl_context
*ctx OVS_UNUSED
)
571 if (wait_type
!= NBCTL_WAIT_NONE
) {
574 VLOG_INFO("\"sync\" command has no effect without --wait");
579 nbctl_sync(struct ctl_context
*ctx OVS_UNUSED
)
584 nbctl_show(struct ctl_context
*ctx
)
586 const struct nbrec_logical_switch
*ls
;
588 if (ctx
->argc
== 2) {
589 ls
= ls_by_name_or_uuid(ctx
, ctx
->argv
[1], false);
591 print_ls(ls
, &ctx
->output
);
594 NBREC_LOGICAL_SWITCH_FOR_EACH(ls
, ctx
->idl
) {
595 print_ls(ls
, &ctx
->output
);
598 const struct nbrec_logical_router
*lr
;
600 if (ctx
->argc
== 2) {
601 lr
= lr_by_name_or_uuid(ctx
, ctx
->argv
[1], false);
603 print_lr(lr
, &ctx
->output
);
606 NBREC_LOGICAL_ROUTER_FOR_EACH(lr
, ctx
->idl
) {
607 print_lr(lr
, &ctx
->output
);
613 nbctl_ls_add(struct ctl_context
*ctx
)
615 const char *ls_name
= ctx
->argc
== 2 ? ctx
->argv
[1] : NULL
;
617 bool may_exist
= shash_find(&ctx
->options
, "--may-exist") != NULL
;
618 bool add_duplicate
= shash_find(&ctx
->options
, "--add-duplicate") != NULL
;
619 if (may_exist
&& add_duplicate
) {
620 ctl_fatal("--may-exist and --add-duplicate may not be used together");
624 if (!add_duplicate
) {
625 const struct nbrec_logical_switch
*ls
;
626 NBREC_LOGICAL_SWITCH_FOR_EACH (ls
, ctx
->idl
) {
627 if (!strcmp(ls
->name
, ls_name
)) {
631 ctl_fatal("%s: a switch with this name already exists",
636 } else if (may_exist
) {
637 ctl_fatal("--may-exist requires specifying a name");
638 } else if (add_duplicate
) {
639 ctl_fatal("--add-duplicate requires specifying a name");
642 struct nbrec_logical_switch
*ls
;
643 ls
= nbrec_logical_switch_insert(ctx
->txn
);
645 nbrec_logical_switch_set_name(ls
, ls_name
);
650 nbctl_ls_del(struct ctl_context
*ctx
)
652 bool must_exist
= !shash_find(&ctx
->options
, "--if-exists");
653 const char *id
= ctx
->argv
[1];
654 const struct nbrec_logical_switch
*ls
;
656 ls
= ls_by_name_or_uuid(ctx
, id
, must_exist
);
661 nbrec_logical_switch_delete(ls
);
665 nbctl_ls_list(struct ctl_context
*ctx
)
667 const struct nbrec_logical_switch
*ls
;
668 struct smap lswitches
;
670 smap_init(&lswitches
);
671 NBREC_LOGICAL_SWITCH_FOR_EACH(ls
, ctx
->idl
) {
672 smap_add_format(&lswitches
, ls
->name
, UUID_FMT
" (%s)",
673 UUID_ARGS(&ls
->header_
.uuid
), ls
->name
);
675 const struct smap_node
**nodes
= smap_sort(&lswitches
);
676 for (size_t i
= 0; i
< smap_count(&lswitches
); i
++) {
677 const struct smap_node
*node
= nodes
[i
];
678 ds_put_format(&ctx
->output
, "%s\n", node
->value
);
680 smap_destroy(&lswitches
);
684 static const struct nbrec_logical_switch_port
*
685 lsp_by_name_or_uuid(struct ctl_context
*ctx
, const char *id
,
688 const struct nbrec_logical_switch_port
*lsp
= NULL
;
690 struct uuid lsp_uuid
;
691 bool is_uuid
= uuid_from_string(&lsp_uuid
, id
);
693 lsp
= nbrec_logical_switch_port_get_for_uuid(ctx
->idl
, &lsp_uuid
);
697 NBREC_LOGICAL_SWITCH_PORT_FOR_EACH(lsp
, ctx
->idl
) {
698 if (!strcmp(lsp
->name
, id
)) {
704 if (!lsp
&& must_exist
) {
705 ctl_fatal("%s: port %s not found", id
, is_uuid
? "UUID" : "name");
711 /* Returns the logical switch that contains 'lsp'. */
712 static const struct nbrec_logical_switch
*
713 lsp_to_ls(const struct ovsdb_idl
*idl
,
714 const struct nbrec_logical_switch_port
*lsp
)
716 const struct nbrec_logical_switch
*ls
;
717 NBREC_LOGICAL_SWITCH_FOR_EACH (ls
, idl
) {
718 for (size_t i
= 0; i
< ls
->n_ports
; i
++) {
719 if (ls
->ports
[i
] == lsp
) {
725 /* Can't happen because of the database schema */
726 ctl_fatal("logical port %s is not part of any logical switch",
731 ls_get_name(const struct nbrec_logical_switch
*ls
,
732 char uuid_s
[UUID_LEN
+ 1], size_t uuid_s_size
)
737 snprintf(uuid_s
, uuid_s_size
, UUID_FMT
, UUID_ARGS(&ls
->header_
.uuid
));
742 nbctl_lsp_add(struct ctl_context
*ctx
)
744 bool may_exist
= shash_find(&ctx
->options
, "--may-exist") != NULL
;
746 const struct nbrec_logical_switch
*ls
;
747 ls
= ls_by_name_or_uuid(ctx
, ctx
->argv
[1], true);
749 const char *parent_name
;
751 if (ctx
->argc
== 3) {
754 } else if (ctx
->argc
== 5) {
756 parent_name
= ctx
->argv
[3];
757 if (!ovs_scan(ctx
->argv
[4], "%"SCNd64
, &tag
)
758 || tag
< 0 || tag
> 4095) {
759 ctl_fatal("%s: invalid tag", ctx
->argv
[4]);
762 ctl_fatal("lsp-add with parent must also specify a tag");
765 const char *lsp_name
= ctx
->argv
[2];
766 const struct nbrec_logical_switch_port
*lsp
;
767 lsp
= lsp_by_name_or_uuid(ctx
, lsp_name
, false);
770 ctl_fatal("%s: a port with this name already exists",
774 const struct nbrec_logical_switch
*lsw
;
775 lsw
= lsp_to_ls(ctx
->idl
, lsp
);
777 char uuid_s
[UUID_LEN
+ 1];
778 ctl_fatal("%s: port already exists but in switch %s", lsp_name
,
779 ls_get_name(lsw
, uuid_s
, sizeof uuid_s
));
783 if (!lsp
->parent_name
) {
784 ctl_fatal("%s: port already exists but has no parent",
786 } else if (strcmp(parent_name
, lsp
->parent_name
)) {
787 ctl_fatal("%s: port already exists with different parent %s",
788 lsp_name
, lsp
->parent_name
);
792 ctl_fatal("%s: port already exists but has no tag",
794 } else if (lsp
->tag
[0] != tag
) {
795 ctl_fatal("%s: port already exists with different "
796 "tag %"PRId64
, lsp_name
, lsp
->tag
[0]);
799 if (lsp
->parent_name
) {
800 ctl_fatal("%s: port already exists but has parent %s",
801 lsp_name
, lsp
->parent_name
);
808 /* Create the logical port. */
809 lsp
= nbrec_logical_switch_port_insert(ctx
->txn
);
810 nbrec_logical_switch_port_set_name(lsp
, lsp_name
);
812 nbrec_logical_switch_port_set_parent_name(lsp
, parent_name
);
813 nbrec_logical_switch_port_set_tag(lsp
, &tag
, 1);
816 /* Insert the logical port into the logical switch. */
817 nbrec_logical_switch_verify_ports(ls
);
818 struct nbrec_logical_switch_port
**new_ports
= xmalloc(sizeof *new_ports
*
820 memcpy(new_ports
, ls
->ports
, sizeof *new_ports
* ls
->n_ports
);
821 new_ports
[ls
->n_ports
] = CONST_CAST(struct nbrec_logical_switch_port
*,
823 nbrec_logical_switch_set_ports(ls
, new_ports
, ls
->n_ports
+ 1);
827 /* Removes logical switch port 'ls->ports[idx]'. */
829 remove_lsp(const struct nbrec_logical_switch
*ls
, size_t idx
)
831 const struct nbrec_logical_switch_port
*lsp
= ls
->ports
[idx
];
833 /* First remove 'lsp' from the array of ports. This is what will
834 * actually cause the logical port to be deleted when the transaction is
835 * sent to the database server (due to garbage collection). */
836 struct nbrec_logical_switch_port
**new_ports
837 = xmemdup(ls
->ports
, sizeof *new_ports
* ls
->n_ports
);
838 new_ports
[idx
] = new_ports
[ls
->n_ports
- 1];
839 nbrec_logical_switch_verify_ports(ls
);
840 nbrec_logical_switch_set_ports(ls
, new_ports
, ls
->n_ports
- 1);
843 /* Delete 'lsp' from the IDL. This won't have a real effect on the
844 * database server (the IDL will suppress it in fact) but it means that it
845 * won't show up when we iterate with NBREC_LOGICAL_SWITCH_PORT_FOR_EACH
847 nbrec_logical_switch_port_delete(lsp
);
851 nbctl_lsp_del(struct ctl_context
*ctx
)
853 bool must_exist
= !shash_find(&ctx
->options
, "--if-exists");
854 const struct nbrec_logical_switch_port
*lsp
;
856 lsp
= lsp_by_name_or_uuid(ctx
, ctx
->argv
[1], must_exist
);
861 /* Find the switch that contains 'lsp', then delete it. */
862 const struct nbrec_logical_switch
*ls
;
863 NBREC_LOGICAL_SWITCH_FOR_EACH (ls
, ctx
->idl
) {
864 for (size_t i
= 0; i
< ls
->n_ports
; i
++) {
865 if (ls
->ports
[i
] == lsp
) {
872 /* Can't happen because of the database schema. */
873 ctl_fatal("logical port %s is not part of any logical switch",
878 nbctl_lsp_list(struct ctl_context
*ctx
)
880 const char *id
= ctx
->argv
[1];
881 const struct nbrec_logical_switch
*ls
;
885 ls
= ls_by_name_or_uuid(ctx
, id
, true);
888 for (i
= 0; i
< ls
->n_ports
; i
++) {
889 const struct nbrec_logical_switch_port
*lsp
= ls
->ports
[i
];
890 smap_add_format(&lsps
, lsp
->name
, UUID_FMT
" (%s)",
891 UUID_ARGS(&lsp
->header_
.uuid
), lsp
->name
);
893 const struct smap_node
**nodes
= smap_sort(&lsps
);
894 for (i
= 0; i
< smap_count(&lsps
); i
++) {
895 const struct smap_node
*node
= nodes
[i
];
896 ds_put_format(&ctx
->output
, "%s\n", node
->value
);
903 nbctl_lsp_get_parent(struct ctl_context
*ctx
)
905 const struct nbrec_logical_switch_port
*lsp
;
907 lsp
= lsp_by_name_or_uuid(ctx
, ctx
->argv
[1], true);
908 if (lsp
->parent_name
) {
909 ds_put_format(&ctx
->output
, "%s\n", lsp
->parent_name
);
914 nbctl_lsp_get_tag(struct ctl_context
*ctx
)
916 const struct nbrec_logical_switch_port
*lsp
;
918 lsp
= lsp_by_name_or_uuid(ctx
, ctx
->argv
[1], true);
919 if (lsp
->n_tag
> 0) {
920 ds_put_format(&ctx
->output
, "%"PRId64
"\n", lsp
->tag
[0]);
925 nbctl_lsp_set_addresses(struct ctl_context
*ctx
)
927 const char *id
= ctx
->argv
[1];
928 const struct nbrec_logical_switch_port
*lsp
;
930 lsp
= lsp_by_name_or_uuid(ctx
, id
, true);
933 for (i
= 2; i
< ctx
->argc
; i
++) {
936 if (strcmp(ctx
->argv
[i
], "unknown") && strcmp(ctx
->argv
[i
], "dynamic")
937 && !ovs_scan(ctx
->argv
[i
], ETH_ADDR_SCAN_FMT
,
938 ETH_ADDR_SCAN_ARGS(ea
))) {
939 ctl_fatal("%s: Invalid address format. See ovn-nb(5). "
940 "Hint: An Ethernet address must be "
941 "listed before an IP address, together as a single "
942 "argument.", ctx
->argv
[i
]);
946 nbrec_logical_switch_port_set_addresses(lsp
,
947 (const char **) ctx
->argv
+ 2, ctx
->argc
- 2);
951 nbctl_lsp_get_addresses(struct ctl_context
*ctx
)
953 const char *id
= ctx
->argv
[1];
954 const struct nbrec_logical_switch_port
*lsp
;
955 struct svec addresses
;
959 lsp
= lsp_by_name_or_uuid(ctx
, id
, true);
961 svec_init(&addresses
);
962 for (i
= 0; i
< lsp
->n_addresses
; i
++) {
963 svec_add(&addresses
, lsp
->addresses
[i
]);
965 svec_sort(&addresses
);
966 SVEC_FOR_EACH(i
, mac
, &addresses
) {
967 ds_put_format(&ctx
->output
, "%s\n", mac
);
969 svec_destroy(&addresses
);
973 nbctl_lsp_set_port_security(struct ctl_context
*ctx
)
975 const char *id
= ctx
->argv
[1];
976 const struct nbrec_logical_switch_port
*lsp
;
978 lsp
= lsp_by_name_or_uuid(ctx
, id
, true);
979 nbrec_logical_switch_port_set_port_security(lsp
,
980 (const char **) ctx
->argv
+ 2, ctx
->argc
- 2);
984 nbctl_lsp_get_port_security(struct ctl_context
*ctx
)
986 const char *id
= ctx
->argv
[1];
987 const struct nbrec_logical_switch_port
*lsp
;
992 lsp
= lsp_by_name_or_uuid(ctx
, id
, true);
994 for (i
= 0; i
< lsp
->n_port_security
; i
++) {
995 svec_add(&addrs
, lsp
->port_security
[i
]);
998 SVEC_FOR_EACH(i
, addr
, &addrs
) {
999 ds_put_format(&ctx
->output
, "%s\n", addr
);
1001 svec_destroy(&addrs
);
1005 nbctl_lsp_get_up(struct ctl_context
*ctx
)
1007 const char *id
= ctx
->argv
[1];
1008 const struct nbrec_logical_switch_port
*lsp
;
1010 lsp
= lsp_by_name_or_uuid(ctx
, id
, true);
1011 ds_put_format(&ctx
->output
,
1012 "%s\n", (lsp
->up
&& *lsp
->up
) ? "up" : "down");
1016 parse_enabled(const char *state
)
1018 if (!strcasecmp(state
, "enabled")) {
1020 } else if (!strcasecmp(state
, "disabled")) {
1023 ctl_fatal("%s: state must be \"enabled\" or \"disabled\"", state
);
1028 nbctl_lsp_set_enabled(struct ctl_context
*ctx
)
1030 const char *id
= ctx
->argv
[1];
1031 const char *state
= ctx
->argv
[2];
1032 const struct nbrec_logical_switch_port
*lsp
;
1034 lsp
= lsp_by_name_or_uuid(ctx
, id
, true);
1035 bool enabled
= parse_enabled(state
);
1036 nbrec_logical_switch_port_set_enabled(lsp
, &enabled
, 1);
1040 nbctl_lsp_get_enabled(struct ctl_context
*ctx
)
1042 const char *id
= ctx
->argv
[1];
1043 const struct nbrec_logical_switch_port
*lsp
;
1045 lsp
= lsp_by_name_or_uuid(ctx
, id
, true);
1046 ds_put_format(&ctx
->output
, "%s\n",
1047 !lsp
->enabled
|| *lsp
->enabled
? "enabled" : "disabled");
1051 nbctl_lsp_set_type(struct ctl_context
*ctx
)
1053 const char *id
= ctx
->argv
[1];
1054 const char *type
= ctx
->argv
[2];
1055 const struct nbrec_logical_switch_port
*lsp
;
1057 lsp
= lsp_by_name_or_uuid(ctx
, id
, true);
1058 nbrec_logical_switch_port_set_type(lsp
, type
);
1062 nbctl_lsp_get_type(struct ctl_context
*ctx
)
1064 const char *id
= ctx
->argv
[1];
1065 const struct nbrec_logical_switch_port
*lsp
;
1067 lsp
= lsp_by_name_or_uuid(ctx
, id
, true);
1068 ds_put_format(&ctx
->output
, "%s\n", lsp
->type
);
1072 nbctl_lsp_set_options(struct ctl_context
*ctx
)
1074 const char *id
= ctx
->argv
[1];
1075 const struct nbrec_logical_switch_port
*lsp
;
1077 struct smap options
= SMAP_INITIALIZER(&options
);
1079 lsp
= lsp_by_name_or_uuid(ctx
, id
, true);
1080 for (i
= 2; i
< ctx
->argc
; i
++) {
1082 value
= xstrdup(ctx
->argv
[i
]);
1083 key
= strsep(&value
, "=");
1085 smap_add(&options
, key
, value
);
1090 nbrec_logical_switch_port_set_options(lsp
, &options
);
1092 smap_destroy(&options
);
1096 nbctl_lsp_get_options(struct ctl_context
*ctx
)
1098 const char *id
= ctx
->argv
[1];
1099 const struct nbrec_logical_switch_port
*lsp
;
1100 struct smap_node
*node
;
1102 lsp
= lsp_by_name_or_uuid(ctx
, id
, true);
1103 SMAP_FOR_EACH(node
, &lsp
->options
) {
1104 ds_put_format(&ctx
->output
, "%s=%s\n", node
->key
, node
->value
);
1109 nbctl_lsp_set_dhcpv4_options(struct ctl_context
*ctx
)
1111 const char *id
= ctx
->argv
[1];
1112 const struct nbrec_logical_switch_port
*lsp
;
1114 lsp
= lsp_by_name_or_uuid(ctx
, id
, true);
1115 const struct nbrec_dhcp_options
*dhcp_opt
= NULL
;
1116 if (ctx
->argc
== 3 ) {
1117 dhcp_opt
= dhcp_options_get(ctx
, ctx
->argv
[2], true);
1123 char *error
= ip_parse_cidr(dhcp_opt
->cidr
, &ip
, &plen
);
1126 ctl_fatal("DHCP options cidr '%s' is not IPv4", dhcp_opt
->cidr
);
1130 nbrec_logical_switch_port_set_dhcpv4_options(lsp
, dhcp_opt
);
1134 nbctl_lsp_get_dhcpv4_options(struct ctl_context
*ctx
)
1136 const char *id
= ctx
->argv
[1];
1137 const struct nbrec_logical_switch_port
*lsp
;
1139 lsp
= lsp_by_name_or_uuid(ctx
, id
, true);
1140 if (lsp
->dhcpv4_options
) {
1141 ds_put_format(&ctx
->output
, UUID_FMT
" (%s)\n",
1142 UUID_ARGS(&lsp
->dhcpv4_options
->header_
.uuid
),
1143 lsp
->dhcpv4_options
->cidr
);
1153 dir_encode(const char *dir
)
1155 if (!strcmp(dir
, "from-lport")) {
1156 return DIR_FROM_LPORT
;
1157 } else if (!strcmp(dir
, "to-lport")) {
1158 return DIR_TO_LPORT
;
1165 acl_cmp(const void *acl1_
, const void *acl2_
)
1167 const struct nbrec_acl
*const *acl1p
= acl1_
;
1168 const struct nbrec_acl
*const *acl2p
= acl2_
;
1169 const struct nbrec_acl
*acl1
= *acl1p
;
1170 const struct nbrec_acl
*acl2
= *acl2p
;
1172 int dir1
= dir_encode(acl1
->direction
);
1173 int dir2
= dir_encode(acl2
->direction
);
1176 return dir1
< dir2
? -1 : 1;
1177 } else if (acl1
->priority
!= acl2
->priority
) {
1178 return acl1
->priority
> acl2
->priority
? -1 : 1;
1180 return strcmp(acl1
->match
, acl2
->match
);
1185 nbctl_acl_list(struct ctl_context
*ctx
)
1187 const struct nbrec_logical_switch
*ls
;
1188 const struct nbrec_acl
**acls
;
1191 ls
= ls_by_name_or_uuid(ctx
, ctx
->argv
[1], true);
1193 acls
= xmalloc(sizeof *acls
* ls
->n_acls
);
1194 for (i
= 0; i
< ls
->n_acls
; i
++) {
1195 acls
[i
] = ls
->acls
[i
];
1198 qsort(acls
, ls
->n_acls
, sizeof *acls
, acl_cmp
);
1200 for (i
= 0; i
< ls
->n_acls
; i
++) {
1201 const struct nbrec_acl
*acl
= acls
[i
];
1202 ds_put_format(&ctx
->output
, "%10s %5"PRId64
" (%s) %s%s\n",
1203 acl
->direction
, acl
->priority
,
1204 acl
->match
, acl
->action
, acl
->log
? " log" : "");
1211 parse_direction(const char *arg
)
1213 /* Validate direction. Only require the first letter. */
1214 if (arg
[0] == 't') {
1216 } else if (arg
[0] == 'f') {
1217 return "from-lport";
1219 ctl_fatal("%s: direction must be \"to-lport\" or \"from-lport\"", arg
);
1224 parse_priority(const char *arg
)
1226 /* Validate priority. */
1228 if (!ovs_scan(arg
, "%"SCNd64
, &priority
)
1229 || priority
< 0 || priority
> 32767) {
1230 ctl_fatal("%s: priority must in range 0...32767", arg
);
1236 nbctl_acl_add(struct ctl_context
*ctx
)
1238 const struct nbrec_logical_switch
*ls
;
1239 const char *action
= ctx
->argv
[5];
1241 ls
= ls_by_name_or_uuid(ctx
, ctx
->argv
[1], true);
1243 const char *direction
= parse_direction(ctx
->argv
[2]);
1244 int64_t priority
= parse_priority(ctx
->argv
[3]);
1246 /* Validate action. */
1247 if (strcmp(action
, "allow") && strcmp(action
, "allow-related")
1248 && strcmp(action
, "drop") && strcmp(action
, "reject")) {
1249 ctl_fatal("%s: action must be one of \"allow\", \"allow-related\", "
1250 "\"drop\", and \"reject\"", action
);
1254 /* Create the acl. */
1255 struct nbrec_acl
*acl
= nbrec_acl_insert(ctx
->txn
);
1256 nbrec_acl_set_priority(acl
, priority
);
1257 nbrec_acl_set_direction(acl
, direction
);
1258 nbrec_acl_set_match(acl
, ctx
->argv
[4]);
1259 nbrec_acl_set_action(acl
, action
);
1260 if (shash_find(&ctx
->options
, "--log") != NULL
) {
1261 nbrec_acl_set_log(acl
, true);
1264 /* Insert the acl into the logical switch. */
1265 nbrec_logical_switch_verify_acls(ls
);
1266 struct nbrec_acl
**new_acls
= xmalloc(sizeof *new_acls
* (ls
->n_acls
+ 1));
1267 memcpy(new_acls
, ls
->acls
, sizeof *new_acls
* ls
->n_acls
);
1268 new_acls
[ls
->n_acls
] = acl
;
1269 nbrec_logical_switch_set_acls(ls
, new_acls
, ls
->n_acls
+ 1);
1274 nbctl_acl_del(struct ctl_context
*ctx
)
1276 const struct nbrec_logical_switch
*ls
;
1277 ls
= ls_by_name_or_uuid(ctx
, ctx
->argv
[1], true);
1279 if (ctx
->argc
!= 2 && ctx
->argc
!= 3 && ctx
->argc
!= 5) {
1280 ctl_fatal("cannot specify priority without match");
1283 if (ctx
->argc
== 2) {
1284 /* If direction, priority, and match are not specified, delete
1286 nbrec_logical_switch_verify_acls(ls
);
1287 nbrec_logical_switch_set_acls(ls
, NULL
, 0);
1291 const char *direction
= parse_direction(ctx
->argv
[2]);
1293 /* If priority and match are not specified, delete all ACLs with the
1294 * specified direction. */
1295 if (ctx
->argc
== 3) {
1296 struct nbrec_acl
**new_acls
= xmalloc(sizeof *new_acls
* ls
->n_acls
);
1299 for (size_t i
= 0; i
< ls
->n_acls
; i
++) {
1300 if (strcmp(direction
, ls
->acls
[i
]->direction
)) {
1301 new_acls
[n_acls
++] = ls
->acls
[i
];
1305 nbrec_logical_switch_verify_acls(ls
);
1306 nbrec_logical_switch_set_acls(ls
, new_acls
, n_acls
);
1311 int64_t priority
= parse_priority(ctx
->argv
[3]);
1313 /* Remove the matching rule. */
1314 for (size_t i
= 0; i
< ls
->n_acls
; i
++) {
1315 struct nbrec_acl
*acl
= ls
->acls
[i
];
1317 if (priority
== acl
->priority
&& !strcmp(ctx
->argv
[4], acl
->match
) &&
1318 !strcmp(direction
, acl
->direction
)) {
1319 struct nbrec_acl
**new_acls
1320 = xmemdup(ls
->acls
, sizeof *new_acls
* ls
->n_acls
);
1321 new_acls
[i
] = ls
->acls
[ls
->n_acls
- 1];
1322 nbrec_logical_switch_verify_acls(ls
);
1323 nbrec_logical_switch_set_acls(ls
, new_acls
,
1332 nbctl_lr_add(struct ctl_context
*ctx
)
1334 const char *lr_name
= ctx
->argc
== 2 ? ctx
->argv
[1] : NULL
;
1336 bool may_exist
= shash_find(&ctx
->options
, "--may-exist") != NULL
;
1337 bool add_duplicate
= shash_find(&ctx
->options
, "--add-duplicate") != NULL
;
1338 if (may_exist
&& add_duplicate
) {
1339 ctl_fatal("--may-exist and --add-duplicate may not be used together");
1343 if (!add_duplicate
) {
1344 const struct nbrec_logical_router
*lr
;
1345 NBREC_LOGICAL_ROUTER_FOR_EACH (lr
, ctx
->idl
) {
1346 if (!strcmp(lr
->name
, lr_name
)) {
1350 ctl_fatal("%s: a router with this name already exists",
1355 } else if (may_exist
) {
1356 ctl_fatal("--may-exist requires specifying a name");
1357 } else if (add_duplicate
) {
1358 ctl_fatal("--add-duplicate requires specifying a name");
1361 struct nbrec_logical_router
*lr
;
1362 lr
= nbrec_logical_router_insert(ctx
->txn
);
1364 nbrec_logical_router_set_name(lr
, lr_name
);
1369 nbctl_lr_del(struct ctl_context
*ctx
)
1371 bool must_exist
= !shash_find(&ctx
->options
, "--if-exists");
1372 const char *id
= ctx
->argv
[1];
1373 const struct nbrec_logical_router
*lr
;
1375 lr
= lr_by_name_or_uuid(ctx
, id
, must_exist
);
1380 nbrec_logical_router_delete(lr
);
1384 nbctl_lr_list(struct ctl_context
*ctx
)
1386 const struct nbrec_logical_router
*lr
;
1390 NBREC_LOGICAL_ROUTER_FOR_EACH(lr
, ctx
->idl
) {
1391 smap_add_format(&lrs
, lr
->name
, UUID_FMT
" (%s)",
1392 UUID_ARGS(&lr
->header_
.uuid
), lr
->name
);
1394 const struct smap_node
**nodes
= smap_sort(&lrs
);
1395 for (size_t i
= 0; i
< smap_count(&lrs
); i
++) {
1396 const struct smap_node
*node
= nodes
[i
];
1397 ds_put_format(&ctx
->output
, "%s\n", node
->value
);
1403 static const struct nbrec_dhcp_options
*
1404 dhcp_options_get(struct ctl_context
*ctx
, const char *id
, bool must_exist
)
1406 struct uuid dhcp_opts_uuid
;
1407 const struct nbrec_dhcp_options
*dhcp_opts
= NULL
;
1408 if (uuid_from_string(&dhcp_opts_uuid
, id
)) {
1409 dhcp_opts
= nbrec_dhcp_options_get_for_uuid(ctx
->idl
, &dhcp_opts_uuid
);
1412 if (!dhcp_opts
&& must_exist
) {
1413 ctl_fatal("%s: dhcp options UUID not found", id
);
1419 nbctl_dhcp_options_create(struct ctl_context
*ctx
)
1421 /* Validate the cidr */
1424 char *error
= ip_parse_cidr(ctx
->argv
[1], &ip
, &plen
);
1426 /* check if its IPv6 cidr */
1428 struct in6_addr ipv6
;
1429 error
= ipv6_parse_cidr(ctx
->argv
[1], &ipv6
, &plen
);
1432 ctl_fatal("Invalid cidr format '%s'", ctx
->argv
[1]);
1437 struct nbrec_dhcp_options
*dhcp_opts
= nbrec_dhcp_options_insert(ctx
->txn
);
1438 nbrec_dhcp_options_set_cidr(dhcp_opts
, ctx
->argv
[1]);
1440 struct smap ext_ids
= SMAP_INITIALIZER(&ext_ids
);
1441 for (size_t i
= 2; i
< ctx
->argc
; i
++) {
1443 value
= xstrdup(ctx
->argv
[i
]);
1444 key
= strsep(&value
, "=");
1446 smap_add(&ext_ids
, key
, value
);
1451 nbrec_dhcp_options_set_external_ids(dhcp_opts
, &ext_ids
);
1452 smap_destroy(&ext_ids
);
1456 nbctl_dhcp_options_set_options(struct ctl_context
*ctx
)
1458 const struct nbrec_dhcp_options
*dhcp_opts
= dhcp_options_get(
1459 ctx
, ctx
->argv
[1], true);
1461 struct smap dhcp_options
= SMAP_INITIALIZER(&dhcp_options
);
1462 for (size_t i
= 2; i
< ctx
->argc
; i
++) {
1464 value
= xstrdup(ctx
->argv
[i
]);
1465 key
= strsep(&value
, "=");
1467 smap_add(&dhcp_options
, key
, value
);
1472 nbrec_dhcp_options_set_options(dhcp_opts
, &dhcp_options
);
1473 smap_destroy(&dhcp_options
);
1477 nbctl_dhcp_options_get_options(struct ctl_context
*ctx
)
1479 const struct nbrec_dhcp_options
*dhcp_opts
= dhcp_options_get(
1480 ctx
, ctx
->argv
[1], true);
1482 struct smap_node
*node
;
1483 SMAP_FOR_EACH(node
, &dhcp_opts
->options
) {
1484 ds_put_format(&ctx
->output
, "%s=%s\n", node
->key
, node
->value
);
1489 nbctl_dhcp_options_del(struct ctl_context
*ctx
)
1491 bool must_exist
= !shash_find(&ctx
->options
, "--if-exists");
1492 const char *id
= ctx
->argv
[1];
1493 const struct nbrec_dhcp_options
*dhcp_opts
;
1495 dhcp_opts
= dhcp_options_get(ctx
, id
, must_exist
);
1500 nbrec_dhcp_options_delete(dhcp_opts
);
1504 nbctl_dhcp_options_list(struct ctl_context
*ctx
)
1506 const struct nbrec_dhcp_options
*dhcp_opts
;
1507 struct smap dhcp_options
;
1509 smap_init(&dhcp_options
);
1510 NBREC_DHCP_OPTIONS_FOR_EACH(dhcp_opts
, ctx
->idl
) {
1511 smap_add_format(&dhcp_options
, dhcp_opts
->cidr
, UUID_FMT
,
1512 UUID_ARGS(&dhcp_opts
->header_
.uuid
));
1514 const struct smap_node
**nodes
= smap_sort(&dhcp_options
);
1515 for (size_t i
= 0; i
< smap_count(&dhcp_options
); i
++) {
1516 const struct smap_node
*node
= nodes
[i
];
1517 ds_put_format(&ctx
->output
, "%s\n", node
->value
);
1519 smap_destroy(&dhcp_options
);
1523 /* The caller must free the returned string. */
1525 normalize_ipv4_prefix(ovs_be32 ipv4
, unsigned int plen
)
1527 ovs_be32 network
= ipv4
& be32_prefix_mask(plen
);
1529 return xasprintf(IP_FMT
, IP_ARGS(network
));
1531 return xasprintf(IP_FMT
"/%d", IP_ARGS(network
), plen
);
1535 /* The caller must free the returned string. */
1537 normalize_ipv6_prefix(struct in6_addr ipv6
, unsigned int plen
)
1539 char network_s
[INET6_ADDRSTRLEN
];
1541 struct in6_addr mask
= ipv6_create_mask(plen
);
1542 struct in6_addr network
= ipv6_addr_bitand(&ipv6
, &mask
);
1544 inet_ntop(AF_INET6
, &network
, network_s
, INET6_ADDRSTRLEN
);
1546 return xasprintf("%s", network_s
);
1548 return xasprintf("%s/%d", network_s
, plen
);
1552 /* The caller must free the returned string. */
1554 normalize_prefix_str(const char *orig_prefix
)
1560 error
= ip_parse_cidr(orig_prefix
, &ipv4
, &plen
);
1562 return normalize_ipv4_prefix(ipv4
, plen
);
1564 struct in6_addr ipv6
;
1567 error
= ipv6_parse_cidr(orig_prefix
, &ipv6
, &plen
);
1572 return normalize_ipv6_prefix(ipv6
, plen
);
1577 nbctl_lr_route_add(struct ctl_context
*ctx
)
1579 const struct nbrec_logical_router
*lr
;
1580 lr
= lr_by_name_or_uuid(ctx
, ctx
->argv
[1], true);
1581 char *prefix
, *next_hop
;
1583 prefix
= normalize_prefix_str(ctx
->argv
[2]);
1585 ctl_fatal("bad prefix argument: %s", ctx
->argv
[2]);
1588 next_hop
= normalize_prefix_str(ctx
->argv
[3]);
1590 ctl_fatal("bad next hop argument: %s", ctx
->argv
[3]);
1593 if (strchr(prefix
, '.')) {
1595 if (!ip_parse(ctx
->argv
[3], &hop_ipv4
)) {
1596 ctl_fatal("bad IPv4 nexthop argument: %s", ctx
->argv
[3]);
1599 struct in6_addr hop_ipv6
;
1600 if (!ipv6_parse(ctx
->argv
[3], &hop_ipv6
)) {
1601 ctl_fatal("bad IPv6 nexthop argument: %s", ctx
->argv
[3]);
1605 bool may_exist
= shash_find(&ctx
->options
, "--may-exist") != NULL
;
1606 for (int i
= 0; i
< lr
->n_static_routes
; i
++) {
1607 const struct nbrec_logical_router_static_route
*route
1608 = lr
->static_routes
[i
];
1611 rt_prefix
= normalize_prefix_str(lr
->static_routes
[i
]->ip_prefix
);
1613 /* Ignore existing prefix we couldn't parse. */
1617 if (strcmp(rt_prefix
, prefix
)) {
1623 ctl_fatal("duplicate prefix: %s", prefix
);
1626 /* Update the next hop for an existing route. */
1627 nbrec_logical_router_verify_static_routes(lr
);
1628 nbrec_logical_router_static_route_verify_ip_prefix(route
);
1629 nbrec_logical_router_static_route_verify_nexthop(route
);
1630 nbrec_logical_router_static_route_set_ip_prefix(route
, prefix
);
1631 nbrec_logical_router_static_route_set_nexthop(route
, next_hop
);
1632 if (ctx
->argc
== 5) {
1633 nbrec_logical_router_static_route_set_output_port(route
,
1642 struct nbrec_logical_router_static_route
*route
;
1643 route
= nbrec_logical_router_static_route_insert(ctx
->txn
);
1644 nbrec_logical_router_static_route_set_ip_prefix(route
, prefix
);
1645 nbrec_logical_router_static_route_set_nexthop(route
, next_hop
);
1646 if (ctx
->argc
== 5) {
1647 nbrec_logical_router_static_route_set_output_port(route
, ctx
->argv
[4]);
1650 nbrec_logical_router_verify_static_routes(lr
);
1651 struct nbrec_logical_router_static_route
**new_routes
1652 = xmalloc(sizeof *new_routes
* (lr
->n_static_routes
+ 1));
1653 memcpy(new_routes
, lr
->static_routes
,
1654 sizeof *new_routes
* lr
->n_static_routes
);
1655 new_routes
[lr
->n_static_routes
] = route
;
1656 nbrec_logical_router_set_static_routes(lr
, new_routes
,
1657 lr
->n_static_routes
+ 1);
1664 nbctl_lr_route_del(struct ctl_context
*ctx
)
1666 const struct nbrec_logical_router
*lr
;
1667 lr
= lr_by_name_or_uuid(ctx
, ctx
->argv
[1], true);
1669 if (ctx
->argc
== 2) {
1670 /* If a prefix is not specified, delete all routes. */
1671 nbrec_logical_router_set_static_routes(lr
, NULL
, 0);
1675 char *prefix
= normalize_prefix_str(ctx
->argv
[2]);
1677 ctl_fatal("bad prefix argument: %s", ctx
->argv
[2]);
1680 for (int i
= 0; i
< lr
->n_static_routes
; i
++) {
1681 char *rt_prefix
= normalize_prefix_str(lr
->static_routes
[i
]->ip_prefix
);
1683 /* Ignore existing prefix we couldn't parse. */
1687 if (!strcmp(prefix
, rt_prefix
)) {
1688 struct nbrec_logical_router_static_route
**new_routes
1689 = xmemdup(lr
->static_routes
,
1690 sizeof *new_routes
* lr
->n_static_routes
);
1692 new_routes
[i
] = lr
->static_routes
[lr
->n_static_routes
- 1];
1693 nbrec_logical_router_verify_static_routes(lr
);
1694 nbrec_logical_router_set_static_routes(lr
, new_routes
,
1695 lr
->n_static_routes
- 1);
1704 if (!shash_find(&ctx
->options
, "--if-exists")) {
1705 ctl_fatal("no matching prefix: %s", prefix
);
1710 static const struct nbrec_logical_router_port
*
1711 lrp_by_name_or_uuid(struct ctl_context
*ctx
, const char *id
, bool must_exist
)
1713 const struct nbrec_logical_router_port
*lrp
= NULL
;
1715 struct uuid lrp_uuid
;
1716 bool is_uuid
= uuid_from_string(&lrp_uuid
, id
);
1718 lrp
= nbrec_logical_router_port_get_for_uuid(ctx
->idl
, &lrp_uuid
);
1722 NBREC_LOGICAL_ROUTER_PORT_FOR_EACH(lrp
, ctx
->idl
) {
1723 if (!strcmp(lrp
->name
, id
)) {
1729 if (!lrp
&& must_exist
) {
1730 ctl_fatal("%s: port %s not found", id
, is_uuid
? "UUID" : "name");
1736 /* Returns the logical router that contains 'lrp'. */
1737 static const struct nbrec_logical_router
*
1738 lrp_to_lr(const struct ovsdb_idl
*idl
,
1739 const struct nbrec_logical_router_port
*lrp
)
1741 const struct nbrec_logical_router
*lr
;
1742 NBREC_LOGICAL_ROUTER_FOR_EACH (lr
, idl
) {
1743 for (size_t i
= 0; i
< lr
->n_ports
; i
++) {
1744 if (lr
->ports
[i
] == lrp
) {
1750 /* Can't happen because of the database schema */
1751 ctl_fatal("port %s is not part of any logical router",
1756 lr_get_name(const struct nbrec_logical_router
*lr
, char uuid_s
[UUID_LEN
+ 1],
1762 snprintf(uuid_s
, uuid_s_size
, UUID_FMT
, UUID_ARGS(&lr
->header_
.uuid
));
1767 nbctl_lrp_add(struct ctl_context
*ctx
)
1769 bool may_exist
= shash_find(&ctx
->options
, "--may-exist") != NULL
;
1771 const struct nbrec_logical_router
*lr
;
1772 lr
= lr_by_name_or_uuid(ctx
, ctx
->argv
[1], true);
1774 const char *lrp_name
= ctx
->argv
[2];
1775 const char *mac
= ctx
->argv
[3];
1776 const char **networks
= (const char **) &ctx
->argv
[4];
1778 int n_networks
= ctx
->argc
- 4;
1779 for (int i
= 4; i
< ctx
->argc
; i
++) {
1780 if (strchr(ctx
->argv
[i
], '=')) {
1787 ctl_fatal("%s: router port requires specifying a network", lrp_name
);
1790 char **settings
= (char **) &ctx
->argv
[n_networks
+ 4];
1791 int n_settings
= ctx
->argc
- 4 - n_networks
;
1793 const struct nbrec_logical_router_port
*lrp
;
1794 lrp
= lrp_by_name_or_uuid(ctx
, lrp_name
, false);
1797 ctl_fatal("%s: a port with this name already exists",
1801 const struct nbrec_logical_router
*bound_lr
;
1802 bound_lr
= lrp_to_lr(ctx
->idl
, lrp
);
1803 if (bound_lr
!= lr
) {
1804 char uuid_s
[UUID_LEN
+ 1];
1805 ctl_fatal("%s: port already exists but in router %s", lrp_name
,
1806 lr_get_name(bound_lr
, uuid_s
, sizeof uuid_s
));
1809 if (strcmp(mac
, lrp
->mac
)) {
1810 ctl_fatal("%s: port already exists with mac %s", lrp_name
,
1814 struct sset new_networks
= SSET_INITIALIZER(&new_networks
);
1815 for (int i
= 0; i
< n_networks
; i
++) {
1816 sset_add(&new_networks
, networks
[i
]);
1819 struct sset orig_networks
= SSET_INITIALIZER(&orig_networks
);
1820 sset_add_array(&orig_networks
, lrp
->networks
, lrp
->n_networks
);
1822 if (!sset_equals(&orig_networks
, &new_networks
)) {
1823 ctl_fatal("%s: port already exists with different network",
1827 sset_destroy(&orig_networks
);
1828 sset_destroy(&new_networks
);
1830 /* Special-case sanity-check of peer ports. */
1831 const char *peer
= NULL
;
1832 for (int i
= 0; i
< n_settings
; i
++) {
1833 if (!strncmp(settings
[i
], "peer=", 5)) {
1834 peer
= settings
[i
] + 5;
1839 if ((!peer
!= !lrp
->peer
) ||
1840 (lrp
->peer
&& strcmp(peer
, lrp
->peer
))) {
1841 ctl_fatal("%s: port already exists with mismatching peer",
1849 if (!ovs_scan(mac
, ETH_ADDR_SCAN_FMT
, ETH_ADDR_SCAN_ARGS(ea
))) {
1850 ctl_fatal("%s: invalid mac address %s", lrp_name
, mac
);
1853 for (int i
= 0; i
< n_networks
; i
++) {
1856 char *error
= ip_parse_cidr(networks
[i
], &ipv4
, &plen
);
1859 struct in6_addr ipv6
;
1860 error
= ipv6_parse_cidr(networks
[i
], &ipv6
, &plen
);
1863 ctl_fatal("%s: invalid network address: %s", lrp_name
,
1869 /* Create the logical port. */
1870 lrp
= nbrec_logical_router_port_insert(ctx
->txn
);
1871 nbrec_logical_router_port_set_name(lrp
, lrp_name
);
1872 nbrec_logical_router_port_set_mac(lrp
, mac
);
1873 nbrec_logical_router_port_set_networks(lrp
, networks
, n_networks
);
1875 for (int i
= 0; i
< n_settings
; i
++) {
1876 ctl_set_column("Logical_Router_Port", &lrp
->header_
, settings
[i
],
1880 /* Insert the logical port into the logical router. */
1881 nbrec_logical_router_verify_ports(lr
);
1882 struct nbrec_logical_router_port
**new_ports
= xmalloc(sizeof *new_ports
*
1884 memcpy(new_ports
, lr
->ports
, sizeof *new_ports
* lr
->n_ports
);
1885 new_ports
[lr
->n_ports
] = CONST_CAST(struct nbrec_logical_router_port
*,
1887 nbrec_logical_router_set_ports(lr
, new_ports
, lr
->n_ports
+ 1);
1891 /* Removes logical router port 'lr->ports[idx]'. */
1893 remove_lrp(const struct nbrec_logical_router
*lr
, size_t idx
)
1895 const struct nbrec_logical_router_port
*lrp
= lr
->ports
[idx
];
1897 /* First remove 'lrp' from the array of ports. This is what will
1898 * actually cause the logical port to be deleted when the transaction is
1899 * sent to the database server (due to garbage collection). */
1900 struct nbrec_logical_router_port
**new_ports
1901 = xmemdup(lr
->ports
, sizeof *new_ports
* lr
->n_ports
);
1902 new_ports
[idx
] = new_ports
[lr
->n_ports
- 1];
1903 nbrec_logical_router_verify_ports(lr
);
1904 nbrec_logical_router_set_ports(lr
, new_ports
, lr
->n_ports
- 1);
1907 /* Delete 'lrp' from the IDL. This won't have a real effect on
1908 * the database server (the IDL will suppress it in fact) but it
1909 * means that it won't show up when we iterate with
1910 * NBREC_LOGICAL_ROUTER_PORT_FOR_EACH later. */
1911 nbrec_logical_router_port_delete(lrp
);
1915 nbctl_lrp_del(struct ctl_context
*ctx
)
1917 bool must_exist
= !shash_find(&ctx
->options
, "--if-exists");
1918 const struct nbrec_logical_router_port
*lrp
;
1920 lrp
= lrp_by_name_or_uuid(ctx
, ctx
->argv
[1], must_exist
);
1925 /* Find the router that contains 'lrp', then delete it. */
1926 const struct nbrec_logical_router
*lr
;
1927 NBREC_LOGICAL_ROUTER_FOR_EACH (lr
, ctx
->idl
) {
1928 for (size_t i
= 0; i
< lr
->n_ports
; i
++) {
1929 if (lr
->ports
[i
] == lrp
) {
1936 /* Can't happen because of the database schema. */
1937 ctl_fatal("logical port %s is not part of any logical router",
1941 /* Print a list of logical router ports. */
1943 nbctl_lrp_list(struct ctl_context
*ctx
)
1945 const char *id
= ctx
->argv
[1];
1946 const struct nbrec_logical_router
*lr
;
1950 lr
= lr_by_name_or_uuid(ctx
, id
, true);
1953 for (i
= 0; i
< lr
->n_ports
; i
++) {
1954 const struct nbrec_logical_router_port
*lrp
= lr
->ports
[i
];
1955 smap_add_format(&lrps
, lrp
->name
, UUID_FMT
" (%s)",
1956 UUID_ARGS(&lrp
->header_
.uuid
), lrp
->name
);
1958 const struct smap_node
**nodes
= smap_sort(&lrps
);
1959 for (i
= 0; i
< smap_count(&lrps
); i
++) {
1960 const struct smap_node
*node
= nodes
[i
];
1961 ds_put_format(&ctx
->output
, "%s\n", node
->value
);
1963 smap_destroy(&lrps
);
1967 /* Set the logical router port admin-enabled state. */
1969 nbctl_lrp_set_enabled(struct ctl_context
*ctx
)
1971 const char *id
= ctx
->argv
[1];
1972 const char *state
= ctx
->argv
[2];
1973 const struct nbrec_logical_router_port
*lrp
;
1975 lrp
= lrp_by_name_or_uuid(ctx
, id
, true);
1980 bool enabled
= parse_enabled(state
);
1981 nbrec_logical_router_port_set_enabled(lrp
, &enabled
, 1);
1984 /* Print admin-enabled state for logical router port. */
1986 nbctl_lrp_get_enabled(struct ctl_context
*ctx
)
1988 const char *id
= ctx
->argv
[1];
1989 const struct nbrec_logical_router_port
*lrp
;
1991 lrp
= lrp_by_name_or_uuid(ctx
, id
, true);
1996 ds_put_format(&ctx
->output
, "%s\n",
1998 *lrp
->enabled
? "enabled" : "disabled");
2004 const struct nbrec_logical_router_static_route
*route
;
2008 ipv4_route_cmp(const void *route1_
, const void *route2_
)
2010 const struct ipv4_route
*route1p
= route1_
;
2011 const struct ipv4_route
*route2p
= route2_
;
2013 if (route1p
->plen
!= route2p
->plen
) {
2014 return route1p
->plen
> route2p
->plen
? -1 : 1;
2015 } else if (route1p
->addr
!= route2p
->addr
) {
2016 return ntohl(route1p
->addr
) < ntohl(route2p
->addr
) ? -1 : 1;
2024 struct in6_addr addr
;
2025 const struct nbrec_logical_router_static_route
*route
;
2029 ipv6_route_cmp(const void *route1_
, const void *route2_
)
2031 const struct ipv6_route
*route1p
= route1_
;
2032 const struct ipv6_route
*route2p
= route2_
;
2034 if (route1p
->plen
!= route2p
->plen
) {
2035 return route1p
->plen
> route2p
->plen
? -1 : 1;
2037 return memcmp(&route1p
->addr
, &route2p
->addr
, sizeof(route1p
->addr
));
2041 print_route(const struct nbrec_logical_router_static_route
*route
, struct ds
*s
)
2044 char *prefix
= normalize_prefix_str(route
->ip_prefix
);
2045 char *next_hop
= normalize_prefix_str(route
->nexthop
);
2046 ds_put_format(s
, "%25s %25s", prefix
, next_hop
);
2050 if (route
->output_port
) {
2051 ds_put_format(s
, " %s", route
->output_port
);
2053 ds_put_char(s
, '\n');
2057 nbctl_lr_route_list(struct ctl_context
*ctx
)
2059 const struct nbrec_logical_router
*lr
;
2060 struct ipv4_route
*ipv4_routes
;
2061 struct ipv6_route
*ipv6_routes
;
2062 size_t n_ipv4_routes
= 0;
2063 size_t n_ipv6_routes
= 0;
2065 lr
= lr_by_name_or_uuid(ctx
, ctx
->argv
[1], true);
2067 ipv4_routes
= xmalloc(sizeof *ipv4_routes
* lr
->n_static_routes
);
2068 ipv6_routes
= xmalloc(sizeof *ipv6_routes
* lr
->n_static_routes
);
2070 for (int i
= 0; i
< lr
->n_static_routes
; i
++) {
2071 const struct nbrec_logical_router_static_route
*route
2072 = lr
->static_routes
[i
];
2077 error
= ip_parse_cidr(route
->ip_prefix
, &ipv4
, &plen
);
2079 ipv4_routes
[n_ipv4_routes
].plen
= plen
;
2080 ipv4_routes
[n_ipv4_routes
].addr
= ipv4
;
2081 ipv4_routes
[n_ipv4_routes
].route
= route
;
2086 struct in6_addr ipv6
;
2087 error
= ipv6_parse_cidr(route
->ip_prefix
, &ipv6
, &plen
);
2089 ipv6_routes
[n_ipv6_routes
].plen
= plen
;
2090 ipv6_routes
[n_ipv6_routes
].addr
= ipv6
;
2091 ipv6_routes
[n_ipv6_routes
].route
= route
;
2094 /* Invalid prefix. */
2095 VLOG_WARN("router "UUID_FMT
" (%s) has invalid prefix: %s",
2096 UUID_ARGS(&lr
->header_
.uuid
), lr
->name
,
2104 qsort(ipv4_routes
, n_ipv4_routes
, sizeof *ipv4_routes
, ipv4_route_cmp
);
2105 qsort(ipv6_routes
, n_ipv6_routes
, sizeof *ipv6_routes
, ipv6_route_cmp
);
2107 if (n_ipv4_routes
) {
2108 ds_put_cstr(&ctx
->output
, "IPv4 Routes\n");
2110 for (int i
= 0; i
< n_ipv4_routes
; i
++) {
2111 print_route(ipv4_routes
[i
].route
, &ctx
->output
);
2114 if (n_ipv6_routes
) {
2115 ds_put_format(&ctx
->output
, "%sIPv6 Routes\n",
2116 n_ipv4_routes
? "\n" : "");
2118 for (int i
= 0; i
< n_ipv6_routes
; i
++) {
2119 print_route(ipv6_routes
[i
].route
, &ctx
->output
);
2126 static const struct ctl_table_class tables
[] = {
2127 {&nbrec_table_nb_global
,
2128 {{&nbrec_table_nb_global
, NULL
, NULL
},
2129 {NULL
, NULL
, NULL
}}},
2131 {&nbrec_table_logical_switch
,
2132 {{&nbrec_table_logical_switch
, &nbrec_logical_switch_col_name
, NULL
},
2133 {NULL
, NULL
, NULL
}}},
2135 {&nbrec_table_logical_switch_port
,
2136 {{&nbrec_table_logical_switch_port
, &nbrec_logical_switch_port_col_name
,
2138 {NULL
, NULL
, NULL
}}},
2141 {{NULL
, NULL
, NULL
},
2142 {NULL
, NULL
, NULL
}}},
2144 {&nbrec_table_load_balancer
,
2145 {{NULL
, NULL
, NULL
},
2146 {NULL
, NULL
, NULL
}}},
2148 {&nbrec_table_logical_router
,
2149 {{&nbrec_table_logical_router
, &nbrec_logical_router_col_name
, NULL
},
2150 {NULL
, NULL
, NULL
}}},
2152 {&nbrec_table_logical_router_port
,
2153 {{&nbrec_table_logical_router_port
, &nbrec_logical_router_port_col_name
,
2155 {NULL
, NULL
, NULL
}}},
2157 {&nbrec_table_logical_router_static_route
,
2158 {{&nbrec_table_logical_router_static_route
, NULL
,
2160 {NULL
, NULL
, NULL
}}},
2163 {{&nbrec_table_nat
, NULL
,
2165 {NULL
, NULL
, NULL
}}},
2167 {&nbrec_table_address_set
,
2168 {{&nbrec_table_address_set
, &nbrec_address_set_col_name
, NULL
},
2169 {NULL
, NULL
, NULL
}}},
2171 {&nbrec_table_dhcp_options
,
2172 {{&nbrec_table_dhcp_options
, NULL
,
2174 {NULL
, NULL
, NULL
}}},
2176 {NULL
, {{NULL
, NULL
, NULL
}, {NULL
, NULL
, NULL
}}}
2180 run_prerequisites(struct ctl_command
*commands
, size_t n_commands
,
2181 struct ovsdb_idl
*idl
)
2183 ovsdb_idl_add_table(idl
, &nbrec_table_nb_global
);
2184 if (wait_type
== NBCTL_WAIT_SB
) {
2185 ovsdb_idl_add_column(idl
, &nbrec_nb_global_col_sb_cfg
);
2186 } else if (wait_type
== NBCTL_WAIT_HV
) {
2187 ovsdb_idl_add_column(idl
, &nbrec_nb_global_col_hv_cfg
);
2190 for (struct ctl_command
*c
= commands
; c
< &commands
[n_commands
]; c
++) {
2191 if (c
->syntax
->prerequisites
) {
2192 struct ctl_context ctx
;
2194 ds_init(&c
->output
);
2197 ctl_context_init(&ctx
, c
, idl
, NULL
, NULL
, NULL
);
2198 (c
->syntax
->prerequisites
)(&ctx
);
2199 ctl_context_done(&ctx
, c
);
2201 ovs_assert(!c
->output
.string
);
2202 ovs_assert(!c
->table
);
2208 do_nbctl(const char *args
, struct ctl_command
*commands
, size_t n_commands
,
2209 struct ovsdb_idl
*idl
)
2211 struct ovsdb_idl_txn
*txn
;
2212 enum ovsdb_idl_txn_status status
;
2213 struct ovsdb_symbol_table
*symtab
;
2214 struct ctl_context ctx
;
2215 struct ctl_command
*c
;
2216 struct shash_node
*node
;
2217 int64_t next_cfg
= 0;
2220 txn
= the_idl_txn
= ovsdb_idl_txn_create(idl
);
2222 ovsdb_idl_txn_set_dry_run(txn
);
2225 ovsdb_idl_txn_add_comment(txn
, "ovs-nbctl: %s", args
);
2227 const struct nbrec_nb_global
*nb
= nbrec_nb_global_first(idl
);
2229 /* XXX add verification that table is empty */
2230 nb
= nbrec_nb_global_insert(txn
);
2233 if (wait_type
!= NBCTL_WAIT_NONE
) {
2234 ovsdb_idl_txn_increment(txn
, &nb
->header_
, &nbrec_nb_global_col_nb_cfg
,
2238 symtab
= ovsdb_symbol_table_create();
2239 for (c
= commands
; c
< &commands
[n_commands
]; c
++) {
2240 ds_init(&c
->output
);
2243 ctl_context_init(&ctx
, NULL
, idl
, txn
, symtab
, NULL
);
2244 for (c
= commands
; c
< &commands
[n_commands
]; c
++) {
2245 ctl_context_init_command(&ctx
, c
);
2246 if (c
->syntax
->run
) {
2247 (c
->syntax
->run
)(&ctx
);
2249 ctl_context_done_command(&ctx
, c
);
2251 if (ctx
.try_again
) {
2252 ctl_context_done(&ctx
, NULL
);
2256 ctl_context_done(&ctx
, NULL
);
2258 SHASH_FOR_EACH (node
, &symtab
->sh
) {
2259 struct ovsdb_symbol
*symbol
= node
->data
;
2260 if (!symbol
->created
) {
2261 ctl_fatal("row id \"%s\" is referenced but never created (e.g. "
2262 "with \"-- --id=%s create ...\")",
2263 node
->name
, node
->name
);
2265 if (!symbol
->strong_ref
) {
2266 if (!symbol
->weak_ref
) {
2267 VLOG_WARN("row id \"%s\" was created but no reference to it "
2268 "was inserted, so it will not actually appear in "
2269 "the database", node
->name
);
2271 VLOG_WARN("row id \"%s\" was created but only a weak "
2272 "reference to it was inserted, so it will not "
2273 "actually appear in the database", node
->name
);
2278 status
= ovsdb_idl_txn_commit_block(txn
);
2279 if (wait_type
!= NBCTL_WAIT_NONE
&& status
== TXN_SUCCESS
) {
2280 next_cfg
= ovsdb_idl_txn_get_increment_new_value(txn
);
2282 if (status
== TXN_UNCHANGED
|| status
== TXN_SUCCESS
) {
2283 for (c
= commands
; c
< &commands
[n_commands
]; c
++) {
2284 if (c
->syntax
->postprocess
) {
2285 ctl_context_init(&ctx
, c
, idl
, txn
, symtab
, NULL
);
2286 (c
->syntax
->postprocess
)(&ctx
);
2287 ctl_context_done(&ctx
, c
);
2291 error
= xstrdup(ovsdb_idl_txn_get_error(txn
));
2294 case TXN_UNCOMMITTED
:
2295 case TXN_INCOMPLETE
:
2299 /* Should not happen--we never call ovsdb_idl_txn_abort(). */
2300 ctl_fatal("transaction aborted");
2310 ctl_fatal("transaction error: %s", error
);
2312 case TXN_NOT_LOCKED
:
2313 /* Should not happen--we never call ovsdb_idl_set_lock(). */
2314 ctl_fatal("database not locked");
2321 ovsdb_symbol_table_destroy(symtab
);
2323 for (c
= commands
; c
< &commands
[n_commands
]; c
++) {
2324 struct ds
*ds
= &c
->output
;
2327 table_print(c
->table
, &table_style
);
2328 } else if (oneline
) {
2332 for (j
= 0; j
< ds
->length
; j
++) {
2333 int ch
= ds
->string
[j
];
2336 fputs("\\n", stdout
);
2340 fputs("\\\\", stdout
);
2349 fputs(ds_cstr(ds
), stdout
);
2351 ds_destroy(&c
->output
);
2352 table_destroy(c
->table
);
2355 shash_destroy_free_data(&c
->options
);
2359 if (wait_type
!= NBCTL_WAIT_NONE
&& status
!= TXN_UNCHANGED
) {
2360 ovsdb_idl_enable_reconnect(idl
);
2363 NBREC_NB_GLOBAL_FOR_EACH (nb
, idl
) {
2364 int64_t cur_cfg
= (wait_type
== NBCTL_WAIT_SB
2367 if (cur_cfg
>= next_cfg
) {
2371 ovsdb_idl_wait(idl
);
2377 ovsdb_idl_txn_destroy(txn
);
2378 ovsdb_idl_destroy(idl
);
2383 /* Our transaction needs to be rerun, or a prerequisite was not met. Free
2384 * resources and return so that the caller can try again. */
2386 ovsdb_idl_txn_abort(txn
);
2387 ovsdb_idl_txn_destroy(txn
);
2390 ovsdb_symbol_table_destroy(symtab
);
2391 for (c
= commands
; c
< &commands
[n_commands
]; c
++) {
2392 ds_destroy(&c
->output
);
2393 table_destroy(c
->table
);
2400 /* Frees the current transaction and the underlying IDL and then calls
2403 * Freeing the transaction and the IDL is not strictly necessary, but it makes
2404 * for a clean memory leak report from valgrind in the normal case. That makes
2405 * it easier to notice real memory leaks. */
2407 nbctl_exit(int status
)
2410 ovsdb_idl_txn_abort(the_idl_txn
);
2411 ovsdb_idl_txn_destroy(the_idl_txn
);
2413 ovsdb_idl_destroy(the_idl
);
2417 static const struct ctl_command_syntax nbctl_commands
[] = {
2418 { "init", 0, 0, "", NULL
, nbctl_init
, NULL
, "", RW
},
2419 { "sync", 0, 0, "", nbctl_pre_sync
, nbctl_sync
, NULL
, "", RO
},
2420 { "show", 0, 1, "[SWITCH]", NULL
, nbctl_show
, NULL
, "", RO
},
2422 /* logical switch commands. */
2423 { "ls-add", 0, 1, "[SWITCH]", NULL
, nbctl_ls_add
, NULL
,
2424 "--may-exist,--add-duplicate", RW
},
2425 { "ls-del", 1, 1, "SWITCH", NULL
, nbctl_ls_del
, NULL
, "--if-exists", RW
},
2426 { "ls-list", 0, 0, "", NULL
, nbctl_ls_list
, NULL
, "", RO
},
2429 { "acl-add", 5, 5, "SWITCH DIRECTION PRIORITY MATCH ACTION", NULL
,
2430 nbctl_acl_add
, NULL
, "--log", RW
},
2431 { "acl-del", 1, 4, "SWITCH [DIRECTION [PRIORITY MATCH]]", NULL
,
2432 nbctl_acl_del
, NULL
, "", RW
},
2433 { "acl-list", 1, 1, "SWITCH", NULL
, nbctl_acl_list
, NULL
, "", RO
},
2435 /* logical switch port commands. */
2436 { "lsp-add", 2, 4, "SWITCH PORT [PARENT] [TAG]", NULL
, nbctl_lsp_add
,
2437 NULL
, "--may-exist", RW
},
2438 { "lsp-del", 1, 1, "PORT", NULL
, nbctl_lsp_del
, NULL
, "--if-exists", RW
},
2439 { "lsp-list", 1, 1, "SWITCH", NULL
, nbctl_lsp_list
, NULL
, "", RO
},
2440 { "lsp-get-parent", 1, 1, "PORT", NULL
, nbctl_lsp_get_parent
, NULL
,
2442 { "lsp-get-tag", 1, 1, "PORT", NULL
, nbctl_lsp_get_tag
, NULL
, "", RO
},
2443 { "lsp-set-addresses", 1, INT_MAX
, "PORT [ADDRESS]...", NULL
,
2444 nbctl_lsp_set_addresses
, NULL
, "", RW
},
2445 { "lsp-get-addresses", 1, 1, "PORT", NULL
, nbctl_lsp_get_addresses
, NULL
,
2447 { "lsp-set-port-security", 0, INT_MAX
, "PORT [ADDRS]...", NULL
,
2448 nbctl_lsp_set_port_security
, NULL
, "", RW
},
2449 { "lsp-get-port-security", 1, 1, "PORT", NULL
,
2450 nbctl_lsp_get_port_security
, NULL
, "", RO
},
2451 { "lsp-get-up", 1, 1, "PORT", NULL
, nbctl_lsp_get_up
, NULL
, "", RO
},
2452 { "lsp-set-enabled", 2, 2, "PORT STATE", NULL
, nbctl_lsp_set_enabled
,
2454 { "lsp-get-enabled", 1, 1, "PORT", NULL
, nbctl_lsp_get_enabled
, NULL
,
2456 { "lsp-set-type", 2, 2, "PORT TYPE", NULL
, nbctl_lsp_set_type
, NULL
,
2458 { "lsp-get-type", 1, 1, "PORT", NULL
, nbctl_lsp_get_type
, NULL
, "", RO
},
2459 { "lsp-set-options", 1, INT_MAX
, "PORT KEY=VALUE [KEY=VALUE]...", NULL
,
2460 nbctl_lsp_set_options
, NULL
, "", RW
},
2461 { "lsp-get-options", 1, 1, "PORT", NULL
, nbctl_lsp_get_options
, NULL
,
2463 { "lsp-set-dhcpv4-options", 1, 2, "PORT [DHCP_OPT_UUID]", NULL
,
2464 nbctl_lsp_set_dhcpv4_options
, NULL
, "", RW
},
2465 { "lsp-get-dhcpv4-options", 1, 1, "PORT", NULL
,
2466 nbctl_lsp_get_dhcpv4_options
, NULL
, "", RO
},
2468 /* logical router commands. */
2469 { "lr-add", 0, 1, "[ROUTER]", NULL
, nbctl_lr_add
, NULL
,
2470 "--may-exist,--add-duplicate", RW
},
2471 { "lr-del", 1, 1, "ROUTER", NULL
, nbctl_lr_del
, NULL
, "--if-exists", RW
},
2472 { "lr-list", 0, 0, "", NULL
, nbctl_lr_list
, NULL
, "", RO
},
2474 /* logical router port commands. */
2475 { "lrp-add", 4, INT_MAX
,
2476 "ROUTER PORT MAC NETWORK... [COLUMN[:KEY]=VALUE]...",
2477 NULL
, nbctl_lrp_add
, NULL
, "--may-exist", RW
},
2478 { "lrp-del", 1, 1, "PORT", NULL
, nbctl_lrp_del
, NULL
, "--if-exists", RW
},
2479 { "lrp-list", 1, 1, "ROUTER", NULL
, nbctl_lrp_list
, NULL
, "", RO
},
2480 { "lrp-set-enabled", 2, 2, "PORT STATE", NULL
, nbctl_lrp_set_enabled
,
2482 { "lrp-get-enabled", 1, 1, "PORT", NULL
, nbctl_lrp_get_enabled
,
2485 /* logical router route commands. */
2486 { "lr-route-add", 3, 4, "ROUTER PREFIX NEXTHOP [PORT]", NULL
,
2487 nbctl_lr_route_add
, NULL
, "--may-exist", RW
},
2488 { "lr-route-del", 1, 2, "ROUTER [PREFIX]", NULL
, nbctl_lr_route_del
,
2489 NULL
, "--if-exists", RW
},
2490 { "lr-route-list", 1, 1, "ROUTER", NULL
, nbctl_lr_route_list
, NULL
,
2493 /* DHCP_Options commands */
2494 {"dhcp-options-create", 1, INT_MAX
, "CIDR [EXTERNAL:IDS]", NULL
,
2495 nbctl_dhcp_options_create
, NULL
, "", RW
},
2496 {"dhcp-options-del", 1, 1, "DHCP_OPT_UUID", NULL
,
2497 nbctl_dhcp_options_del
, NULL
, "", RW
},
2498 {"dhcp-options-list", 0, 0, "", NULL
, nbctl_dhcp_options_list
, NULL
, "", RO
},
2499 {"dhcp-options-set-options", 1, INT_MAX
, "DHCP_OPT_UUID KEY=VALUE [KEY=VALUE]...",
2500 NULL
, nbctl_dhcp_options_set_options
, NULL
, "", RW
},
2501 {"dhcp-options-get-options", 1, 1, "DHCP_OPT_UUID", NULL
,
2502 nbctl_dhcp_options_get_options
, NULL
, "", RO
},
2504 {NULL
, 0, 0, NULL
, NULL
, NULL
, NULL
, "", RO
},
2507 /* Registers nbctl and common db commands. */
2509 nbctl_cmd_init(void)
2511 ctl_init(tables
, NULL
, nbctl_exit
);
2512 ctl_register_commands(nbctl_commands
);