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