8ac1cd054eb95522bd910b829736bb9476f92d56
[cascardo/ovs.git] / ovn / utilities / ovn-nbctl.c
1 /*
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:
5  *
6  *     http://www.apache.org/licenses/LICENSE-2.0
7  *
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.
13  */
14
15 #include <config.h>
16
17 #include <getopt.h>
18 #include <inttypes.h>
19 #include <stdlib.h>
20 #include <stdio.h>
21
22 #include "command-line.h"
23 #include "db-ctl-base.h"
24 #include "dirs.h"
25 #include "fatal-signal.h"
26 #include "json.h"
27 #include "ovn/lib/ovn-nb-idl.h"
28 #include "packets.h"
29 #include "poll-loop.h"
30 #include "process.h"
31 #include "smap.h"
32 #include "stream.h"
33 #include "stream-ssl.h"
34 #include "svec.h"
35 #include "table.h"
36 #include "timeval.h"
37 #include "util.h"
38 #include "openvswitch/vlog.h"
39
40 VLOG_DEFINE_THIS_MODULE(nbctl);
41
42 /* --db: The database server to contact. */
43 static const char *db;
44
45 /* --oneline: Write each command's output as a single line? */
46 static bool oneline;
47
48 /* --dry-run: Do not commit any changes. */
49 static bool dry_run;
50
51 /* --timeout: Time to wait for a connection to 'db'. */
52 static int timeout;
53
54 /* Format for table output. */
55 static struct table_style table_style = TABLE_STYLE_DEFAULT;
56
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);
63
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,
69                               struct ovsdb_idl *);
70 static void do_nbctl(const char *args, struct ctl_command *, size_t n,
71                      struct ovsdb_idl *);
72
73 int
74 main(int argc, char *argv[])
75 {
76     extern struct vlog_module VLM_reconnect;
77     struct ovsdb_idl *idl;
78     struct ctl_command *commands;
79     struct shash local_options;
80     unsigned int seqno;
81     size_t n_commands;
82     char *args;
83
84     set_program_name(argv[0]);
85     fatal_ignore_sigpipe();
86     vlog_set_levels(NULL, VLF_CONSOLE, VLL_WARN);
87     vlog_set_levels(&VLM_reconnect, VLF_ANY_DESTINATION, VLL_WARN);
88     nbrec_init();
89
90     nbctl_cmd_init();
91
92     /* Log our arguments.  This is often valuable for debugging systems. */
93     args = process_escape_args(argv);
94     VLOG(ctl_might_write_to_db(argv) ? VLL_INFO : VLL_DBG,
95          "Called as %s", args);
96
97     /* Parse command line. */
98     shash_init(&local_options);
99     parse_options(argc, argv, &local_options);
100     commands = ctl_parse_commands(argc - optind, argv + optind, &local_options,
101                                   &n_commands);
102
103     if (timeout) {
104         time_alarm(timeout);
105     }
106
107     /* Initialize IDL. */
108     idl = the_idl = ovsdb_idl_create(db, &nbrec_idl_class, true, false);
109     run_prerequisites(commands, n_commands, idl);
110
111     /* Execute the commands.
112      *
113      * 'seqno' is the database sequence number for which we last tried to
114      * execute our transaction.  There's no point in trying to commit more than
115      * once for any given sequence number, because if the transaction fails
116      * it's because the database changed and we need to obtain an up-to-date
117      * view of the database before we try the transaction again. */
118     seqno = ovsdb_idl_get_seqno(idl);
119     for (;;) {
120         ovsdb_idl_run(idl);
121         if (!ovsdb_idl_is_alive(idl)) {
122             int retval = ovsdb_idl_get_last_error(idl);
123             ctl_fatal("%s: database connection failed (%s)",
124                         db, ovs_retval_to_string(retval));
125         }
126
127         if (seqno != ovsdb_idl_get_seqno(idl)) {
128             seqno = ovsdb_idl_get_seqno(idl);
129             do_nbctl(args, commands, n_commands, idl);
130         }
131
132         if (seqno == ovsdb_idl_get_seqno(idl)) {
133             ovsdb_idl_wait(idl);
134             poll_block();
135         }
136     }
137 }
138
139 static const char *
140 nbctl_default_db(void)
141 {
142     static char *def;
143     if (!def) {
144         def = getenv("OVN_NB_DB");
145         if (!def) {
146             def = ctl_default_db();
147         }
148     }
149     return def;
150 }
151
152 static void
153 parse_options(int argc, char *argv[], struct shash *local_options)
154 {
155     enum {
156         OPT_DB = UCHAR_MAX + 1,
157         OPT_NO_SYSLOG,
158         OPT_DRY_RUN,
159         OPT_ONELINE,
160         OPT_LOCAL,
161         OPT_COMMANDS,
162         OPT_OPTIONS,
163         VLOG_OPTION_ENUMS,
164         TABLE_OPTION_ENUMS
165     };
166     static const struct option global_long_options[] = {
167         {"db", required_argument, NULL, OPT_DB},
168         {"no-syslog", no_argument, NULL, OPT_NO_SYSLOG},
169         {"dry-run", no_argument, NULL, OPT_DRY_RUN},
170         {"oneline", no_argument, NULL, OPT_ONELINE},
171         {"timeout", required_argument, NULL, 't'},
172         {"help", no_argument, NULL, 'h'},
173         {"commands", no_argument, NULL, OPT_COMMANDS},
174         {"options", no_argument, NULL, OPT_OPTIONS},
175         {"version", no_argument, NULL, 'V'},
176         VLOG_LONG_OPTIONS,
177         STREAM_SSL_LONG_OPTIONS,
178         TABLE_LONG_OPTIONS,
179         {NULL, 0, NULL, 0},
180     };
181     const int n_global_long_options = ARRAY_SIZE(global_long_options) - 1;
182     char *tmp, *short_options;
183
184     struct option *options;
185     size_t allocated_options;
186     size_t n_options;
187     size_t i;
188
189     tmp = ovs_cmdl_long_options_to_short_options(global_long_options);
190     short_options = xasprintf("+%s", tmp);
191     free(tmp);
192
193     /* We want to parse both global and command-specific options here, but
194      * getopt_long() isn't too convenient for the job.  We copy our global
195      * options into a dynamic array, then append all of the command-specific
196      * options. */
197     options = xmemdup(global_long_options, sizeof global_long_options);
198     allocated_options = ARRAY_SIZE(global_long_options);
199     n_options = n_global_long_options;
200     ctl_add_cmd_options(&options, &n_options, &allocated_options, OPT_LOCAL);
201     table_style.format = TF_LIST;
202
203     for (;;) {
204         int idx;
205         int c;
206
207         c = getopt_long(argc, argv, short_options, options, &idx);
208         if (c == -1) {
209             break;
210         }
211
212         switch (c) {
213         case OPT_DB:
214             db = optarg;
215             break;
216
217         case OPT_ONELINE:
218             oneline = true;
219             break;
220
221         case OPT_NO_SYSLOG:
222             vlog_set_levels(&VLM_nbctl, VLF_SYSLOG, VLL_WARN);
223             break;
224
225         case OPT_DRY_RUN:
226             dry_run = true;
227             break;
228
229         case OPT_LOCAL:
230             if (shash_find(local_options, options[idx].name)) {
231                 ctl_fatal("'%s' option specified multiple times",
232                             options[idx].name);
233             }
234             shash_add_nocopy(local_options,
235                              xasprintf("--%s", options[idx].name),
236                              optarg ? xstrdup(optarg) : NULL);
237             break;
238
239         case 'h':
240             usage();
241             exit(EXIT_SUCCESS);
242
243         case OPT_COMMANDS:
244             ctl_print_commands();
245
246         case OPT_OPTIONS:
247             ctl_print_options(global_long_options);
248
249         case 'V':
250             ovs_print_version(0, 0);
251             printf("DB Schema %s\n", nbrec_get_db_version());
252             exit(EXIT_SUCCESS);
253
254         case 't':
255             timeout = strtoul(optarg, NULL, 10);
256             if (timeout < 0) {
257                 ctl_fatal("value %s on -t or --timeout is invalid", optarg);
258             }
259             break;
260
261         VLOG_OPTION_HANDLERS
262         TABLE_OPTION_HANDLERS(&table_style)
263         STREAM_SSL_OPTION_HANDLERS
264
265         case '?':
266             exit(EXIT_FAILURE);
267
268         default:
269             abort();
270         }
271     }
272     free(short_options);
273
274     if (!db) {
275         db = nbctl_default_db();
276     }
277
278     for (i = n_global_long_options; options[i].name; i++) {
279         free(CONST_CAST(char *, options[i].name));
280     }
281     free(options);
282 }
283
284 static void
285 usage(void)
286 {
287     printf("\
288 %s: OVN northbound DB management utility\n\
289 usage: %s [OPTIONS] COMMAND [ARG...]\n\
290 \n\
291 General commands:\n\
292   show                      print overview of database contents\n\
293   show LSWITCH              print overview of database contents for LSWITCH\n\
294 \n\
295 Logical switch commands:\n\
296   lswitch-add [LSWITCH]     create a logical switch named LSWITCH\n\
297   lswitch-del LSWITCH       delete LSWITCH and all its ports\n\
298   lswitch-list              print the names of all logical switches\n\
299 \n\
300 ACL commands:\n\
301   acl-add LSWITCH DIRECTION PRIORITY MATCH ACTION [log]\n\
302                             add an ACL to LSWITCH\n\
303   acl-del LSWITCH [DIRECTION [PRIORITY MATCH]]\n\
304                             remove ACLs from LSWITCH\n\
305   acl-list LSWITCH          print ACLs for LSWITCH\n\
306 \n\
307 Logical port commands:\n\
308   lport-add LSWITCH LPORT   add logical port LPORT on LSWITCH\n\
309   lport-add LSWITCH LPORT PARENT TAG\n\
310                             add logical port LPORT on LSWITCH with PARENT\n\
311                             on TAG\n\
312   lport-del LPORT           delete LPORT from its attached switch\n\
313   lport-list LSWITCH        print the names of all logical ports on LSWITCH\n\
314   lport-get-parent LPORT    get the parent of LPORT if set\n\
315   lport-get-tag LPORT       get the LPORT's tag if set\n\
316   lport-set-addresses LPORT [ADDRESS]...\n\
317                             set MAC or MAC+IP addresses for LPORT.\n\
318   lport-get-addresses LPORT      get a list of MAC addresses on LPORT\n\
319   lport-set-port-security LPORT [ADDRS]...\n\
320                             set port security addresses for LPORT.\n\
321   lport-get-port-security LPORT    get LPORT's port security addresses\n\
322   lport-get-up LPORT        get state of LPORT ('up' or 'down')\n\
323   lport-set-enabled LPORT STATE\n\
324                             set administrative state LPORT\n\
325                             ('enabled' or 'disabled')\n\
326   lport-get-enabled LPORT   get administrative state LPORT\n\
327                             ('enabled' or 'disabled')\n\
328   lport-set-type LPORT TYPE Set the type for LPORT\n\
329   lport-get-type LPORT      Get the type for LPORT\n\
330   lport-set-options LPORT KEY=VALUE [KEY=VALUE]...\n\
331                             Set options related to the type of LPORT\n\
332   lport-get-options LPORT   Get the type specific options for LPORT\n\
333 \n\
334 %s\
335 \n\
336 Options:\n\
337   --db=DATABASE               connect to DATABASE\n\
338                               (default: %s)\n\
339   -t, --timeout=SECS          wait at most SECS seconds\n\
340   --dry-run                   do not commit changes to database\n\
341   --oneline                   print exactly one line of output per command\n",
342            program_name, program_name, ctl_get_db_cmd_usage(), nbctl_default_db());
343     vlog_usage();
344     printf("\
345   --no-syslog             equivalent to --verbose=nbctl:syslog:warn\n");
346     printf("\n\
347 Other options:\n\
348   -h, --help                  display this help message\n\
349   -V, --version               display version information\n");
350     exit(EXIT_SUCCESS);
351 }
352 \f
353 static const struct nbrec_logical_switch *
354 lswitch_by_name_or_uuid(struct ctl_context *ctx, const char *id)
355 {
356     const struct nbrec_logical_switch *lswitch = NULL;
357     bool is_uuid = false;
358     bool duplicate = false;
359     struct uuid lswitch_uuid;
360
361     if (uuid_from_string(&lswitch_uuid, id)) {
362         is_uuid = true;
363         lswitch = nbrec_logical_switch_get_for_uuid(ctx->idl,
364                                                     &lswitch_uuid);
365     }
366
367     if (!lswitch) {
368         const struct nbrec_logical_switch *iter;
369
370         NBREC_LOGICAL_SWITCH_FOR_EACH(iter, ctx->idl) {
371             if (strcmp(iter->name, id)) {
372                 continue;
373             }
374             if (lswitch) {
375                 VLOG_WARN("There is more than one logical switch named '%s'. "
376                         "Use a UUID.", id);
377                 lswitch = NULL;
378                 duplicate = true;
379                 break;
380             }
381             lswitch = iter;
382         }
383     }
384
385     if (!lswitch && !duplicate) {
386         VLOG_WARN("lswitch not found for %s: '%s'",
387                 is_uuid ? "UUID" : "name", id);
388     }
389
390     return lswitch;
391 }
392
393 static void
394 print_lswitch(const struct nbrec_logical_switch *lswitch, struct ds *s)
395 {
396     ds_put_format(s, "    lswitch "UUID_FMT" (%s)\n",
397                   UUID_ARGS(&lswitch->header_.uuid), lswitch->name);
398
399     for (size_t i = 0; i < lswitch->n_ports; i++) {
400         const struct nbrec_logical_port *lport = lswitch->ports[i];
401
402         ds_put_format(s, "        lport %s\n", lport->name);
403         if (lport->parent_name) {
404             ds_put_format(s, "            parent: %s\n", lport->parent_name);
405         }
406         if (lport->n_tag) {
407             ds_put_format(s, "            tag: %"PRIu64"\n", lport->tag[0]);
408         }
409         if (lport->n_addresses) {
410             ds_put_cstr(s, "            addresses:");
411             for (size_t j = 0; j < lport->n_addresses; j++) {
412                 ds_put_format(s, " %s", lport->addresses[j]);
413             }
414             ds_put_char(s, '\n');
415         }
416     }
417 }
418
419 static void
420 nbctl_show(struct ctl_context *ctx)
421 {
422     const struct nbrec_logical_switch *lswitch;
423
424     if (ctx->argc == 2) {
425         lswitch = lswitch_by_name_or_uuid(ctx, ctx->argv[1]);
426         if (lswitch) {
427             print_lswitch(lswitch, &ctx->output);
428         }
429     } else {
430         NBREC_LOGICAL_SWITCH_FOR_EACH(lswitch, ctx->idl) {
431             print_lswitch(lswitch, &ctx->output);
432         }
433     }
434 }
435
436 static void
437 nbctl_lswitch_add(struct ctl_context *ctx)
438 {
439     struct nbrec_logical_switch *lswitch;
440
441     lswitch = nbrec_logical_switch_insert(ctx->txn);
442     if (ctx->argc == 2) {
443         nbrec_logical_switch_set_name(lswitch, ctx->argv[1]);
444     }
445 }
446
447 static void
448 nbctl_lswitch_del(struct ctl_context *ctx)
449 {
450     const char *id = ctx->argv[1];
451     const struct nbrec_logical_switch *lswitch;
452
453     lswitch = lswitch_by_name_or_uuid(ctx, id);
454     if (!lswitch) {
455         return;
456     }
457
458     nbrec_logical_switch_delete(lswitch);
459 }
460
461 static void
462 nbctl_lswitch_list(struct ctl_context *ctx)
463 {
464     const struct nbrec_logical_switch *lswitch;
465     struct smap lswitches;
466
467     smap_init(&lswitches);
468     NBREC_LOGICAL_SWITCH_FOR_EACH(lswitch, ctx->idl) {
469         smap_add_format(&lswitches, lswitch->name, UUID_FMT " (%s)",
470                         UUID_ARGS(&lswitch->header_.uuid), lswitch->name);
471     }
472     const struct smap_node **nodes = smap_sort(&lswitches);
473     for (size_t i = 0; i < smap_count(&lswitches); i++) {
474         const struct smap_node *node = nodes[i];
475         ds_put_format(&ctx->output, "%s\n", node->value);
476     }
477     smap_destroy(&lswitches);
478     free(nodes);
479 }
480 \f
481 static const struct nbrec_logical_port *
482 lport_by_name_or_uuid(struct ctl_context *ctx, const char *id)
483 {
484     const struct nbrec_logical_port *lport = NULL;
485     bool is_uuid = false;
486     struct uuid lport_uuid;
487
488     if (uuid_from_string(&lport_uuid, id)) {
489         is_uuid = true;
490         lport = nbrec_logical_port_get_for_uuid(ctx->idl, &lport_uuid);
491     }
492
493     if (!lport) {
494         NBREC_LOGICAL_PORT_FOR_EACH(lport, ctx->idl) {
495             if (!strcmp(lport->name, id)) {
496                 break;
497             }
498         }
499     }
500
501     if (!lport) {
502         VLOG_WARN("lport not found for %s: '%s'",
503                 is_uuid ? "UUID" : "name", id);
504     }
505
506     return lport;
507 }
508
509 static void
510 nbctl_lport_add(struct ctl_context *ctx)
511 {
512     struct nbrec_logical_port *lport;
513     const struct nbrec_logical_switch *lswitch;
514     int64_t tag;
515
516     lswitch = lswitch_by_name_or_uuid(ctx, ctx->argv[1]);
517     if (!lswitch) {
518         return;
519     }
520
521     if (ctx->argc != 3 && ctx->argc != 5) {
522         /* If a parent_name is specified, a tag must be specified as well. */
523         VLOG_WARN("Invalid arguments to lport-add.");
524         return;
525     }
526
527     if (ctx->argc == 5) {
528         /* Validate tag. */
529         if (!ovs_scan(ctx->argv[4], "%"SCNd64, &tag) || tag < 0 || tag > 4095) {
530             VLOG_WARN("Invalid tag '%s'", ctx->argv[4]);
531             return;
532         }
533     }
534
535     /* Create the logical port. */
536     lport = nbrec_logical_port_insert(ctx->txn);
537     nbrec_logical_port_set_name(lport, ctx->argv[2]);
538     if (ctx->argc == 5) {
539         nbrec_logical_port_set_parent_name(lport, ctx->argv[3]);
540         nbrec_logical_port_set_tag(lport, &tag, 1);
541     }
542
543     /* Insert the logical port into the logical switch. */
544     nbrec_logical_switch_verify_ports(lswitch);
545     struct nbrec_logical_port **new_ports = xmalloc(sizeof *new_ports *
546                                                     (lswitch->n_ports + 1));
547     memcpy(new_ports, lswitch->ports, sizeof *new_ports * lswitch->n_ports);
548     new_ports[lswitch->n_ports] = lport;
549     nbrec_logical_switch_set_ports(lswitch, new_ports, lswitch->n_ports + 1);
550     free(new_ports);
551 }
552
553 /* Removes lport 'lswitch->ports[idx]'. */
554 static void
555 remove_lport(const struct nbrec_logical_switch *lswitch, size_t idx)
556 {
557     const struct nbrec_logical_port *lport = lswitch->ports[idx];
558
559     /* First remove 'lport' from the array of ports.  This is what will
560      * actually cause the logical port to be deleted when the transaction is
561      * sent to the database server (due to garbage collection). */
562     struct nbrec_logical_port **new_ports
563         = xmemdup(lswitch->ports, sizeof *new_ports * lswitch->n_ports);
564     new_ports[idx] = new_ports[lswitch->n_ports - 1];
565     nbrec_logical_switch_verify_ports(lswitch);
566     nbrec_logical_switch_set_ports(lswitch, new_ports, lswitch->n_ports - 1);
567     free(new_ports);
568
569     /* Delete 'lport' from the IDL.  This won't have a real effect on the
570      * database server (the IDL will suppress it in fact) but it means that it
571      * won't show up when we iterate with NBREC_LOGICAL_PORT_FOR_EACH later. */
572     nbrec_logical_port_delete(lport);
573 }
574
575 static void
576 nbctl_lport_del(struct ctl_context *ctx)
577 {
578     const struct nbrec_logical_port *lport;
579
580     lport = lport_by_name_or_uuid(ctx, ctx->argv[1]);
581     if (!lport) {
582         return;
583     }
584
585     /* Find the switch that contains 'lport', then delete it. */
586     const struct nbrec_logical_switch *lswitch;
587     NBREC_LOGICAL_SWITCH_FOR_EACH (lswitch, ctx->idl) {
588         for (size_t i = 0; i < lswitch->n_ports; i++) {
589             if (lswitch->ports[i] == lport) {
590                 remove_lport(lswitch, i);
591                 return;
592             }
593         }
594     }
595
596     VLOG_WARN("logical port %s is not part of any logical switch",
597               ctx->argv[1]);
598 }
599
600 static void
601 nbctl_lport_list(struct ctl_context *ctx)
602 {
603     const char *id = ctx->argv[1];
604     const struct nbrec_logical_switch *lswitch;
605     struct smap lports;
606     size_t i;
607
608     lswitch = lswitch_by_name_or_uuid(ctx, id);
609     if (!lswitch) {
610         return;
611     }
612
613     smap_init(&lports);
614     for (i = 0; i < lswitch->n_ports; i++) {
615         const struct nbrec_logical_port *lport = lswitch->ports[i];
616         smap_add_format(&lports, lport->name, UUID_FMT " (%s)",
617                         UUID_ARGS(&lport->header_.uuid), lport->name);
618     }
619     const struct smap_node **nodes = smap_sort(&lports);
620     for (i = 0; i < smap_count(&lports); i++) {
621         const struct smap_node *node = nodes[i];
622         ds_put_format(&ctx->output, "%s\n", node->value);
623     }
624     smap_destroy(&lports);
625     free(nodes);
626 }
627
628 static void
629 nbctl_lport_get_parent(struct ctl_context *ctx)
630 {
631     const struct nbrec_logical_port *lport;
632
633     lport = lport_by_name_or_uuid(ctx, ctx->argv[1]);
634     if (!lport) {
635         return;
636     }
637
638     if (lport->parent_name) {
639         ds_put_format(&ctx->output, "%s\n", lport->parent_name);
640     }
641 }
642
643 static void
644 nbctl_lport_get_tag(struct ctl_context *ctx)
645 {
646     const struct nbrec_logical_port *lport;
647
648     lport = lport_by_name_or_uuid(ctx, ctx->argv[1]);
649     if (!lport) {
650         return;
651     }
652
653     if (lport->n_tag > 0) {
654         ds_put_format(&ctx->output, "%"PRId64"\n", lport->tag[0]);
655     }
656 }
657
658 static void
659 nbctl_lport_set_addresses(struct ctl_context *ctx)
660 {
661     const char *id = ctx->argv[1];
662     const struct nbrec_logical_port *lport;
663
664     lport = lport_by_name_or_uuid(ctx, id);
665     if (!lport) {
666         return;
667     }
668
669     int i;
670     for (i = 2; i < ctx->argc; i++) {
671         struct eth_addr ea;
672
673         if (strcmp(ctx->argv[i], "unknown")
674             && !ovs_scan(ctx->argv[i], ETH_ADDR_SCAN_FMT,
675                          ETH_ADDR_SCAN_ARGS(ea))) {
676             VLOG_ERR("Invalid address format (%s). See ovn-nb(5). "
677                      "Hint: An Ethernet address must be "
678                      "listed before an IP address, together as a single "
679                      "argument.", ctx->argv[i]);
680             return;
681         }
682     }
683
684     nbrec_logical_port_set_addresses(lport,
685             (const char **) ctx->argv + 2, ctx->argc - 2);
686 }
687
688 static void
689 nbctl_lport_get_addresses(struct ctl_context *ctx)
690 {
691     const char *id = ctx->argv[1];
692     const struct nbrec_logical_port *lport;
693     struct svec addresses;
694     const char *mac;
695     size_t i;
696
697     lport = lport_by_name_or_uuid(ctx, id);
698     if (!lport) {
699         return;
700     }
701
702     svec_init(&addresses);
703     for (i = 0; i < lport->n_addresses; i++) {
704         svec_add(&addresses, lport->addresses[i]);
705     }
706     svec_sort(&addresses);
707     SVEC_FOR_EACH(i, mac, &addresses) {
708         ds_put_format(&ctx->output, "%s\n", mac);
709     }
710     svec_destroy(&addresses);
711 }
712
713 static void
714 nbctl_lport_set_port_security(struct ctl_context *ctx)
715 {
716     const char *id = ctx->argv[1];
717     const struct nbrec_logical_port *lport;
718
719     lport = lport_by_name_or_uuid(ctx, id);
720     if (!lport) {
721         return;
722     }
723
724     nbrec_logical_port_set_port_security(lport,
725             (const char **) ctx->argv + 2, ctx->argc - 2);
726 }
727
728 static void
729 nbctl_lport_get_port_security(struct ctl_context *ctx)
730 {
731     const char *id = ctx->argv[1];
732     const struct nbrec_logical_port *lport;
733     struct svec addrs;
734     const char *addr;
735     size_t i;
736
737     lport = lport_by_name_or_uuid(ctx, id);
738     if (!lport) {
739         return;
740     }
741
742     svec_init(&addrs);
743     for (i = 0; i < lport->n_port_security; i++) {
744         svec_add(&addrs, lport->port_security[i]);
745     }
746     svec_sort(&addrs);
747     SVEC_FOR_EACH(i, addr, &addrs) {
748         ds_put_format(&ctx->output, "%s\n", addr);
749     }
750     svec_destroy(&addrs);
751 }
752
753 static void
754 nbctl_lport_get_up(struct ctl_context *ctx)
755 {
756     const char *id = ctx->argv[1];
757     const struct nbrec_logical_port *lport;
758
759     lport = lport_by_name_or_uuid(ctx, id);
760     if (!lport) {
761         return;
762     }
763
764     ds_put_format(&ctx->output,
765                   "%s\n", (lport->up && *lport->up) ? "up" : "down");
766 }
767
768 static void
769 nbctl_lport_set_enabled(struct ctl_context *ctx)
770 {
771     const char *id = ctx->argv[1];
772     const char *state = ctx->argv[2];
773     const struct nbrec_logical_port *lport;
774
775     lport = lport_by_name_or_uuid(ctx, id);
776     if (!lport) {
777         return;
778     }
779
780     if (!strcasecmp(state, "enabled")) {
781         bool enabled = true;
782         nbrec_logical_port_set_enabled(lport, &enabled, 1);
783     } else if (!strcasecmp(state, "disabled")) {
784         bool enabled = false;
785         nbrec_logical_port_set_enabled(lport, &enabled, 1);
786     } else {
787         VLOG_ERR("Invalid state '%s' provided to lport-set-enabled", state);
788     }
789 }
790
791 static void
792 nbctl_lport_get_enabled(struct ctl_context *ctx)
793 {
794     const char *id = ctx->argv[1];
795     const struct nbrec_logical_port *lport;
796
797     lport = lport_by_name_or_uuid(ctx, id);
798     if (!lport) {
799         return;
800     }
801
802     ds_put_format(&ctx->output, "%s\n",
803                   !lport->enabled || *lport->enabled ? "enabled" : "disabled");
804 }
805
806 static void
807 nbctl_lport_set_type(struct ctl_context *ctx)
808 {
809     const char *id = ctx->argv[1];
810     const char *type = ctx->argv[2];
811     const struct nbrec_logical_port *lport;
812
813     lport = lport_by_name_or_uuid(ctx, id);
814     if (!lport) {
815         return;
816     }
817
818     nbrec_logical_port_set_type(lport, type);
819 }
820
821 static void
822 nbctl_lport_get_type(struct ctl_context *ctx)
823 {
824     const char *id = ctx->argv[1];
825     const struct nbrec_logical_port *lport;
826
827     lport = lport_by_name_or_uuid(ctx, id);
828     if (!lport) {
829         return;
830     }
831
832     ds_put_format(&ctx->output, "%s\n", lport->type);
833 }
834
835 static void
836 nbctl_lport_set_options(struct ctl_context *ctx)
837 {
838     const char *id = ctx->argv[1];
839     const struct nbrec_logical_port *lport;
840     size_t i;
841     struct smap options = SMAP_INITIALIZER(&options);
842
843     lport = lport_by_name_or_uuid(ctx, id);
844     if (!lport) {
845         return;
846     }
847
848     for (i = 2; i < ctx->argc; i++) {
849         char *key, *value;
850         value = xstrdup(ctx->argv[i]);
851         key = strsep(&value, "=");
852         if (value) {
853             smap_add(&options, key, value);
854         }
855         free(key);
856     }
857
858     nbrec_logical_port_set_options(lport, &options);
859
860     smap_destroy(&options);
861 }
862
863 static void
864 nbctl_lport_get_options(struct ctl_context *ctx)
865 {
866     const char *id = ctx->argv[1];
867     const struct nbrec_logical_port *lport;
868     struct smap_node *node;
869
870     lport = lport_by_name_or_uuid(ctx, id);
871     if (!lport) {
872         return;
873     }
874
875     SMAP_FOR_EACH(node, &lport->options) {
876         ds_put_format(&ctx->output, "%s=%s\n", node->key, node->value);
877     }
878 }
879
880 enum {
881     DIR_FROM_LPORT,
882     DIR_TO_LPORT
883 };
884
885 static int
886 dir_encode(const char *dir)
887 {
888     if (!strcmp(dir, "from-lport")) {
889         return DIR_FROM_LPORT;
890     } else if (!strcmp(dir, "to-lport")) {
891         return DIR_TO_LPORT;
892     }
893
894     OVS_NOT_REACHED();
895 }
896
897 static int
898 acl_cmp(const void *acl1_, const void *acl2_)
899 {
900     const struct nbrec_acl *const *acl1p = acl1_;
901     const struct nbrec_acl *const *acl2p = acl2_;
902     const struct nbrec_acl *acl1 = *acl1p;
903     const struct nbrec_acl *acl2 = *acl2p;
904
905     int dir1 = dir_encode(acl1->direction);
906     int dir2 = dir_encode(acl2->direction);
907
908     if (dir1 != dir2) {
909         return dir1 < dir2 ? -1 : 1;
910     } else if (acl1->priority != acl2->priority) {
911         return acl1->priority > acl2->priority ? -1 : 1;
912     } else {
913         return strcmp(acl1->match, acl2->match);
914     }
915 }
916
917 static void
918 nbctl_acl_list(struct ctl_context *ctx)
919 {
920     const struct nbrec_logical_switch *lswitch;
921     const struct nbrec_acl **acls;
922     size_t i;
923
924     lswitch = lswitch_by_name_or_uuid(ctx, ctx->argv[1]);
925     if (!lswitch) {
926         return;
927     }
928
929     acls = xmalloc(sizeof *acls * lswitch->n_acls);
930     for (i = 0; i < lswitch->n_acls; i++) {
931         acls[i] = lswitch->acls[i];
932     }
933
934     qsort(acls, lswitch->n_acls, sizeof *acls, acl_cmp);
935
936     for (i = 0; i < lswitch->n_acls; i++) {
937         const struct nbrec_acl *acl = acls[i];
938         printf("%10s %5"PRId64" (%s) %s%s\n", acl->direction, acl->priority,
939                 acl->match, acl->action, acl->log ? " log" : "");
940     }
941
942     free(acls);
943 }
944
945 static void
946 nbctl_acl_add(struct ctl_context *ctx)
947 {
948     const struct nbrec_logical_switch *lswitch;
949     const char *action = ctx->argv[5];
950     const char *direction;
951     int64_t priority;
952
953     lswitch = lswitch_by_name_or_uuid(ctx, ctx->argv[1]);
954     if (!lswitch) {
955         return;
956     }
957
958     /* Validate direction.  Only require the first letter. */
959     if (ctx->argv[2][0] == 't') {
960         direction = "to-lport";
961     } else if (ctx->argv[2][0] == 'f') {
962         direction = "from-lport";
963     } else {
964         VLOG_WARN("Invalid direction '%s'", ctx->argv[2]);
965         return;
966     }
967
968     /* Validate priority. */
969     if (!ovs_scan(ctx->argv[3], "%"SCNd64, &priority) || priority < 0
970         || priority > 32767) {
971         VLOG_WARN("Invalid priority '%s'", ctx->argv[3]);
972         return;
973     }
974
975     /* Validate action. */
976     if (strcmp(action, "allow") && strcmp(action, "allow-related")
977         && strcmp(action, "drop") && strcmp(action, "reject")) {
978         VLOG_WARN("Invalid action '%s'", action);
979         return;
980     }
981
982     /* Create the acl. */
983     struct nbrec_acl *acl = nbrec_acl_insert(ctx->txn);
984     nbrec_acl_set_priority(acl, priority);
985     nbrec_acl_set_direction(acl, direction);
986     nbrec_acl_set_match(acl, ctx->argv[4]);
987     nbrec_acl_set_action(acl, action);
988     if (shash_find(&ctx->options, "--log") != NULL) {
989         nbrec_acl_set_log(acl, true);
990     }
991
992     /* Insert the acl into the logical switch. */
993     nbrec_logical_switch_verify_acls(lswitch);
994     struct nbrec_acl **new_acls = xmalloc(sizeof *new_acls *
995                                           (lswitch->n_acls + 1));
996     memcpy(new_acls, lswitch->acls, sizeof *new_acls * lswitch->n_acls);
997     new_acls[lswitch->n_acls] = acl;
998     nbrec_logical_switch_set_acls(lswitch, new_acls, lswitch->n_acls + 1);
999     free(new_acls);
1000 }
1001
1002 static void
1003 nbctl_acl_del(struct ctl_context *ctx)
1004 {
1005     const struct nbrec_logical_switch *lswitch;
1006     const char *direction;
1007     int64_t priority = 0;
1008
1009     lswitch = lswitch_by_name_or_uuid(ctx, ctx->argv[1]);
1010     if (!lswitch) {
1011         return;
1012     }
1013
1014     if (ctx->argc != 2 && ctx->argc != 3 && ctx->argc != 5) {
1015         VLOG_WARN("Invalid number of arguments");
1016         return;
1017     }
1018
1019     if (ctx->argc == 2) {
1020         /* If direction, priority, and match are not specified, delete
1021          * all ACLs. */
1022         nbrec_logical_switch_verify_acls(lswitch);
1023         nbrec_logical_switch_set_acls(lswitch, NULL, 0);
1024         return;
1025     }
1026
1027     /* Validate direction.  Only require first letter. */
1028     if (ctx->argv[2][0] == 't') {
1029         direction = "to-lport";
1030     } else if (ctx->argv[2][0] == 'f') {
1031         direction = "from-lport";
1032     } else {
1033         VLOG_WARN("Invalid direction '%s'", ctx->argv[2]);
1034         return;
1035     }
1036
1037     /* If priority and match are not specified, delete all ACLs with the
1038      * specified direction. */
1039     if (ctx->argc == 3) {
1040         struct nbrec_acl **new_acls
1041             = xmalloc(sizeof *new_acls * lswitch->n_acls);
1042
1043         int n_acls = 0;
1044         for (size_t i = 0; i < lswitch->n_acls; i++) {
1045             if (strcmp(direction, lswitch->acls[i]->direction)) {
1046                 new_acls[n_acls++] = lswitch->acls[i];
1047             }
1048         }
1049
1050         nbrec_logical_switch_verify_acls(lswitch);
1051         nbrec_logical_switch_set_acls(lswitch, new_acls, n_acls);
1052         free(new_acls);
1053         return;
1054     }
1055
1056     /* Validate priority. */
1057     if (!ovs_scan(ctx->argv[3], "%"SCNd64, &priority) || priority < 0
1058         || priority > 32767) {
1059         VLOG_WARN("Invalid priority '%s'", ctx->argv[3]);
1060         return;
1061     }
1062
1063     /* Remove the matching rule. */
1064     for (size_t i = 0; i < lswitch->n_acls; i++) {
1065         struct nbrec_acl *acl = lswitch->acls[i];
1066
1067         if (priority == acl->priority && !strcmp(ctx->argv[4], acl->match) &&
1068              !strcmp(direction, acl->direction)) {
1069             struct nbrec_acl **new_acls
1070                 = xmemdup(lswitch->acls, sizeof *new_acls * lswitch->n_acls);
1071             new_acls[i] = lswitch->acls[lswitch->n_acls - 1];
1072             nbrec_logical_switch_verify_acls(lswitch);
1073             nbrec_logical_switch_set_acls(lswitch, new_acls,
1074                                           lswitch->n_acls - 1);
1075             free(new_acls);
1076             return;
1077         }
1078     }
1079 }
1080 \f
1081 static const struct ctl_table_class tables[] = {
1082     {&nbrec_table_logical_switch,
1083      {{&nbrec_table_logical_switch, &nbrec_logical_switch_col_name, NULL},
1084       {NULL, NULL, NULL}}},
1085
1086     {&nbrec_table_logical_port,
1087      {{&nbrec_table_logical_port, &nbrec_logical_port_col_name, NULL},
1088       {NULL, NULL, NULL}}},
1089
1090     {&nbrec_table_acl,
1091      {{NULL, NULL, NULL},
1092       {NULL, NULL, NULL}}},
1093
1094     {&nbrec_table_logical_router,
1095      {{&nbrec_table_logical_router, &nbrec_logical_router_col_name, NULL},
1096       {NULL, NULL, NULL}}},
1097
1098     {&nbrec_table_logical_router_port,
1099      {{&nbrec_table_logical_router_port, &nbrec_logical_router_port_col_name,
1100        NULL},
1101       {NULL, NULL, NULL}}},
1102
1103     {NULL, {{NULL, NULL, NULL}, {NULL, NULL, NULL}}}
1104 };
1105 \f
1106 static void
1107 run_prerequisites(struct ctl_command *commands, size_t n_commands,
1108                   struct ovsdb_idl *idl)
1109 {
1110     struct ctl_command *c;
1111
1112     for (c = commands; c < &commands[n_commands]; c++) {
1113         if (c->syntax->prerequisites) {
1114             struct ctl_context ctx;
1115
1116             ds_init(&c->output);
1117             c->table = NULL;
1118
1119             ctl_context_init(&ctx, c, idl, NULL, NULL, NULL);
1120             (c->syntax->prerequisites)(&ctx);
1121             ctl_context_done(&ctx, c);
1122
1123             ovs_assert(!c->output.string);
1124             ovs_assert(!c->table);
1125         }
1126     }
1127 }
1128
1129 static void
1130 do_nbctl(const char *args, struct ctl_command *commands, size_t n_commands,
1131          struct ovsdb_idl *idl)
1132 {
1133     struct ovsdb_idl_txn *txn;
1134     enum ovsdb_idl_txn_status status;
1135     struct ovsdb_symbol_table *symtab;
1136     struct ctl_context ctx;
1137     struct ctl_command *c;
1138     struct shash_node *node;
1139     char *error = NULL;
1140
1141     txn = the_idl_txn = ovsdb_idl_txn_create(idl);
1142     if (dry_run) {
1143         ovsdb_idl_txn_set_dry_run(txn);
1144     }
1145
1146     ovsdb_idl_txn_add_comment(txn, "ovs-nbctl: %s", args);
1147
1148     symtab = ovsdb_symbol_table_create();
1149     for (c = commands; c < &commands[n_commands]; c++) {
1150         ds_init(&c->output);
1151         c->table = NULL;
1152     }
1153     ctl_context_init(&ctx, NULL, idl, txn, symtab, NULL);
1154     for (c = commands; c < &commands[n_commands]; c++) {
1155         ctl_context_init_command(&ctx, c);
1156         if (c->syntax->run) {
1157             (c->syntax->run)(&ctx);
1158         }
1159         ctl_context_done_command(&ctx, c);
1160
1161         if (ctx.try_again) {
1162             ctl_context_done(&ctx, NULL);
1163             goto try_again;
1164         }
1165     }
1166     ctl_context_done(&ctx, NULL);
1167
1168     SHASH_FOR_EACH (node, &symtab->sh) {
1169         struct ovsdb_symbol *symbol = node->data;
1170         if (!symbol->created) {
1171             ctl_fatal("row id \"%s\" is referenced but never created (e.g. "
1172                       "with \"-- --id=%s create ...\")",
1173                       node->name, node->name);
1174         }
1175         if (!symbol->strong_ref) {
1176             if (!symbol->weak_ref) {
1177                 VLOG_WARN("row id \"%s\" was created but no reference to it "
1178                           "was inserted, so it will not actually appear in "
1179                           "the database", node->name);
1180             } else {
1181                 VLOG_WARN("row id \"%s\" was created but only a weak "
1182                           "reference to it was inserted, so it will not "
1183                           "actually appear in the database", node->name);
1184             }
1185         }
1186     }
1187
1188     status = ovsdb_idl_txn_commit_block(txn);
1189     if (status == TXN_UNCHANGED || status == TXN_SUCCESS) {
1190         for (c = commands; c < &commands[n_commands]; c++) {
1191             if (c->syntax->postprocess) {
1192                 ctl_context_init(&ctx, c, idl, txn, symtab, NULL);
1193                 (c->syntax->postprocess)(&ctx);
1194                 ctl_context_done(&ctx, c);
1195             }
1196         }
1197     }
1198     error = xstrdup(ovsdb_idl_txn_get_error(txn));
1199
1200     switch (status) {
1201     case TXN_UNCOMMITTED:
1202     case TXN_INCOMPLETE:
1203         OVS_NOT_REACHED();
1204
1205     case TXN_ABORTED:
1206         /* Should not happen--we never call ovsdb_idl_txn_abort(). */
1207         ctl_fatal("transaction aborted");
1208
1209     case TXN_UNCHANGED:
1210     case TXN_SUCCESS:
1211         break;
1212
1213     case TXN_TRY_AGAIN:
1214         goto try_again;
1215
1216     case TXN_ERROR:
1217         ctl_fatal("transaction error: %s", error);
1218
1219     case TXN_NOT_LOCKED:
1220         /* Should not happen--we never call ovsdb_idl_set_lock(). */
1221         ctl_fatal("database not locked");
1222
1223     default:
1224         OVS_NOT_REACHED();
1225     }
1226     free(error);
1227
1228     ovsdb_symbol_table_destroy(symtab);
1229
1230     for (c = commands; c < &commands[n_commands]; c++) {
1231         struct ds *ds = &c->output;
1232
1233         if (c->table) {
1234             table_print(c->table, &table_style);
1235         } else if (oneline) {
1236             size_t j;
1237
1238             ds_chomp(ds, '\n');
1239             for (j = 0; j < ds->length; j++) {
1240                 int ch = ds->string[j];
1241                 switch (ch) {
1242                 case '\n':
1243                     fputs("\\n", stdout);
1244                     break;
1245
1246                 case '\\':
1247                     fputs("\\\\", stdout);
1248                     break;
1249
1250                 default:
1251                     putchar(ch);
1252                 }
1253             }
1254             putchar('\n');
1255         } else {
1256             fputs(ds_cstr(ds), stdout);
1257         }
1258         ds_destroy(&c->output);
1259         table_destroy(c->table);
1260         free(c->table);
1261
1262         shash_destroy_free_data(&c->options);
1263     }
1264     free(commands);
1265     ovsdb_idl_txn_destroy(txn);
1266     ovsdb_idl_destroy(idl);
1267
1268     exit(EXIT_SUCCESS);
1269
1270 try_again:
1271     /* Our transaction needs to be rerun, or a prerequisite was not met.  Free
1272      * resources and return so that the caller can try again. */
1273     if (txn) {
1274         ovsdb_idl_txn_abort(txn);
1275         ovsdb_idl_txn_destroy(txn);
1276         the_idl_txn = NULL;
1277     }
1278     ovsdb_symbol_table_destroy(symtab);
1279     for (c = commands; c < &commands[n_commands]; c++) {
1280         ds_destroy(&c->output);
1281         table_destroy(c->table);
1282         free(c->table);
1283     }
1284     free(error);
1285 }
1286
1287 /* Frees the current transaction and the underlying IDL and then calls
1288  * exit(status).
1289  *
1290  * Freeing the transaction and the IDL is not strictly necessary, but it makes
1291  * for a clean memory leak report from valgrind in the normal case.  That makes
1292  * it easier to notice real memory leaks. */
1293 static void
1294 nbctl_exit(int status)
1295 {
1296     if (the_idl_txn) {
1297         ovsdb_idl_txn_abort(the_idl_txn);
1298         ovsdb_idl_txn_destroy(the_idl_txn);
1299     }
1300     ovsdb_idl_destroy(the_idl);
1301     exit(status);
1302 }
1303
1304 static const struct ctl_command_syntax nbctl_commands[] = {
1305     { "show", 0, 1, "[LSWITCH]", NULL, nbctl_show, NULL, "", RO },
1306
1307     /* lswitch commands. */
1308     { "lswitch-add", 0, 1, "[LSWITCH]", NULL, nbctl_lswitch_add,
1309       NULL, "", RW },
1310     { "lswitch-del", 1, 1, "LSWITCH", NULL, nbctl_lswitch_del,
1311       NULL, "", RW },
1312     { "lswitch-list", 0, 0, "", NULL, nbctl_lswitch_list, NULL, "", RO },
1313
1314     /* acl commands. */
1315     { "acl-add", 5, 5, "LSWITCH DIRECTION PRIORITY MATCH ACTION", NULL,
1316       nbctl_acl_add, NULL, "--log", RW },
1317     { "acl-del", 1, 4, "LSWITCH [DIRECTION [PRIORITY MATCH]]", NULL,
1318       nbctl_acl_del, NULL, "", RW },
1319     { "acl-list", 1, 1, "LSWITCH", NULL, nbctl_acl_list, NULL, "", RO },
1320
1321     /* lport commands. */
1322     { "lport-add", 2, 4, "LSWITCH LPORT [PARENT] [TAG]", NULL, nbctl_lport_add,
1323       NULL, "", RW },
1324     { "lport-del", 1, 1, "LPORT", NULL, nbctl_lport_del, NULL, "", RO },
1325     { "lport-list", 1, 1, "LSWITCH", NULL, nbctl_lport_list, NULL, "", RO },
1326     { "lport-get-parent", 1, 1, "LPORT", NULL, nbctl_lport_get_parent, NULL,
1327       "", RO },
1328     { "lport-get-tag", 1, 1, "LPORT", NULL, nbctl_lport_get_tag, NULL, "",
1329       RO },
1330     { "lport-set-addresses", 1, INT_MAX, "LPORT [ADDRESS]...", NULL,
1331       nbctl_lport_set_addresses, NULL, "", RW },
1332     { "lport-get-addresses", 1, 1, "LPORT", NULL,
1333       nbctl_lport_get_addresses, NULL,
1334       "", RO },
1335     { "lport-set-port-security", 0, INT_MAX, "LPORT [ADDRS]...", NULL,
1336       nbctl_lport_set_port_security, NULL, "", RW },
1337     { "lport-get-port-security", 1, 1, "LPORT", NULL,
1338       nbctl_lport_get_port_security, NULL, "", RO },
1339     { "lport-get-up", 1, 1, "LPORT", NULL, nbctl_lport_get_up, NULL, "", RO },
1340     { "lport-set-enabled", 2, 2, "LPORT STATE", NULL, nbctl_lport_set_enabled,
1341       NULL, "", RW },
1342     { "lport-get-enabled", 1, 1, "LPORT", NULL, nbctl_lport_get_enabled, NULL,
1343       "", RO },
1344     { "lport-set-type", 2, 2, "LPORT TYPE", NULL, nbctl_lport_set_type, NULL,
1345       "", RW },
1346     { "lport-get-type", 1, 1, "LPORT", NULL, nbctl_lport_get_type, NULL, "",
1347       RO },
1348     { "lport-set-options", 1, INT_MAX, "LPORT KEY=VALUE [KEY=VALUE]...", NULL,
1349       nbctl_lport_set_options, NULL, "", RW },
1350     { "lport-get-options", 1, 1, "LPORT", NULL, nbctl_lport_get_options, NULL,
1351       "", RO },
1352
1353     {NULL, 0, 0, NULL, NULL, NULL, NULL, "", RO},
1354 };
1355
1356 /* Registers nbctl and common db commands. */
1357 static void
1358 nbctl_cmd_init(void)
1359 {
1360     ctl_init(tables, NULL, nbctl_exit);
1361     ctl_register_commands(nbctl_commands);
1362 }