]> git.proxmox.com Git - mirror_ovs.git/blame - utilities/ovs-vsctl.c
ovsdb-data: Short-circuit ovsdb_datum_includes_all() in trivial case.
[mirror_ovs.git] / utilities / ovs-vsctl.c
CommitLineData
c75d1511 1/*
f158c54a 2 * Copyright (c) 2009, 2010, 2011 Nicira Networks.
c75d1511
BP
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <config.h>
18
19#include <assert.h>
ad83bfa6 20#include <ctype.h>
c75d1511 21#include <errno.h>
ad83bfa6 22#include <float.h>
c75d1511
BP
23#include <getopt.h>
24#include <inttypes.h>
25#include <signal.h>
26#include <stdarg.h>
27#include <stdlib.h>
28#include <string.h>
6d5abe94 29#include <unistd.h>
c75d1511
BP
30
31#include "command-line.h"
32#include "compiler.h"
33#include "dirs.h"
34#include "dynamic-string.h"
b54e22e9 35#include "json.h"
ad83bfa6 36#include "ovsdb-data.h"
c75d1511
BP
37#include "ovsdb-idl.h"
38#include "poll-loop.h"
f8ff4bc4 39#include "process.h"
ae9a3235 40#include "stream.h"
218a6f59 41#include "stream-ssl.h"
b3c01ed3 42#include "sset.h"
dfbe07ba 43#include "svec.h"
c75d1511 44#include "vswitchd/vswitch-idl.h"
e051b42c 45#include "table.h"
c75d1511
BP
46#include "timeval.h"
47#include "util.h"
070723f9 48#include "vconn.h"
c75d1511 49#include "vlog.h"
5136ce49 50
d98e6007 51VLOG_DEFINE_THIS_MODULE(vsctl);
c75d1511 52
def90f62
BP
53/* vsctl_fatal() also logs the error, so it is preferred in this file. */
54#define ovs_fatal please_use_vsctl_fatal_instead_of_ovs_fatal
55
f8ff4bc4
BP
56struct vsctl_context;
57
e5e12280 58/* A command supported by ovs-vsctl. */
f8ff4bc4 59struct vsctl_command_syntax {
e5e12280
BP
60 const char *name; /* e.g. "add-br" */
61 int min_args; /* Min number of arguments following name. */
62 int max_args; /* Max number of arguments following name. */
63
64 /* If nonnull, calls ovsdb_idl_add_column() or ovsdb_idl_add_table() for
65 * each column or table in ctx->idl that it uses. */
66 void (*prerequisites)(struct vsctl_context *ctx);
67
68 /* Does the actual work of the command and puts the command's output, if
e051b42c 69 * any, in ctx->output or ctx->table.
e5e12280
BP
70 *
71 * Alternatively, if some prerequisite of the command is not met and the
72 * caller should wait for something to change and then retry, it may set
73 * ctx->try_again to true. (Only the "wait-until" command currently does
74 * this.) */
75 void (*run)(struct vsctl_context *ctx);
76
77 /* If nonnull, called after the transaction has been successfully
78 * committed. ctx->output is the output from the "run" function, which
79 * this function may modify and otherwise postprocess as needed. (Only the
80 * "create" command currently does any postprocessing.) */
81 void (*postprocess)(struct vsctl_context *ctx);
82
83 /* A comma-separated list of supported options, e.g. "--a,--b", or the
84 * empty string if the command does not support any options. */
f8ff4bc4 85 const char *options;
0c18b5a0 86 enum { RO, RW } mode; /* Does this command modify the database? */
f8ff4bc4
BP
87};
88
89struct vsctl_command {
90 /* Data that remains constant after initialization. */
91 const struct vsctl_command_syntax *syntax;
92 int argc;
93 char **argv;
94 struct shash options;
95
96 /* Data modified by commands. */
97 struct ds output;
e051b42c 98 struct table *table;
f8ff4bc4
BP
99};
100
c75d1511
BP
101/* --db: The database server to contact. */
102static const char *db;
103
104/* --oneline: Write each command's output as a single line? */
105static bool oneline;
106
577aebdf
BP
107/* --dry-run: Do not commit any changes. */
108static bool dry_run;
109
b54e22e9
BP
110/* --no-wait: Wait for ovs-vswitchd to reload its configuration? */
111static bool wait_for_reload = true;
112
a39a859a 113/* --timeout: Time to wait for a connection to 'db'. */
6b7b9d34 114static int timeout;
a39a859a 115
e051b42c
BP
116/* Format for table output. */
117static struct table_style table_style = TABLE_STYLE_DEFAULT;
118
f8ff4bc4
BP
119/* All supported commands. */
120static const struct vsctl_command_syntax all_commands[];
121
1d48b4be
BP
122/* The IDL we're using and the current transaction, if any.
123 * This is for use by vsctl_exit() only, to allow it to clean up.
124 * Other code should use its context arguments. */
125static struct ovsdb_idl *the_idl;
126static struct ovsdb_idl_txn *the_idl_txn;
127
128static void vsctl_exit(int status) NO_RETURN;
c88b6a27 129static void vsctl_fatal(const char *, ...) PRINTF_FORMAT(1, 2) NO_RETURN;
c75d1511
BP
130static char *default_db(void);
131static void usage(void) NO_RETURN;
132static void parse_options(int argc, char *argv[]);
0c18b5a0 133static bool might_write_to_db(char **argv);
c75d1511 134
f8ff4bc4
BP
135static struct vsctl_command *parse_commands(int argc, char *argv[],
136 size_t *n_commandsp);
137static void parse_command(int argc, char *argv[], struct vsctl_command *);
1998cd4d 138static const struct vsctl_command_syntax *find_command(const char *name);
e5e12280
BP
139static void run_prerequisites(struct vsctl_command[], size_t n_commands,
140 struct ovsdb_idl *);
4fdfe5cc
BP
141static enum ovsdb_idl_txn_status do_vsctl(const char *args,
142 struct vsctl_command *, size_t n,
143 struct ovsdb_idl *);
c75d1511 144
18b239f5
BP
145static const struct vsctl_table_class *get_table(const char *table_name);
146static void set_column(const struct vsctl_table_class *,
ce5a3e38
BP
147 const struct ovsdb_idl_row *, const char *arg,
148 struct ovsdb_symbol_table *);
18b239f5 149
0a140468
BP
150static bool is_condition_satisfied(const struct vsctl_table_class *,
151 const struct ovsdb_idl_row *,
152 const char *arg,
153 struct ovsdb_symbol_table *);
154
c75d1511
BP
155int
156main(int argc, char *argv[])
157{
480ce8ab 158 extern struct vlog_module VLM_reconnect;
4fdfe5cc 159 enum ovsdb_idl_txn_status status;
c75d1511 160 struct ovsdb_idl *idl;
f8ff4bc4
BP
161 struct vsctl_command *commands;
162 size_t n_commands;
163 char *args;
c75d1511
BP
164
165 set_program_name(argv[0]);
166 signal(SIGPIPE, SIG_IGN);
480ce8ab
BP
167 vlog_set_levels(NULL, VLF_CONSOLE, VLL_WARN);
168 vlog_set_levels(&VLM_reconnect, VLF_ANY_FACILITY, VLL_WARN);
bd76d25d 169 ovsrec_init();
f8ff4bc4
BP
170
171 /* Log our arguments. This is often valuable for debugging systems. */
172 args = process_escape_args(argv);
0c18b5a0 173 VLOG(might_write_to_db(argv) ? VLL_INFO : VLL_DBG, "Called as %s", args);
f8ff4bc4
BP
174
175 /* Parse command line. */
c75d1511 176 parse_options(argc, argv);
f8ff4bc4 177 commands = parse_commands(argc - optind, argv + optind, &n_commands);
c75d1511 178
a39a859a
JP
179 if (timeout) {
180 time_alarm(timeout);
181 }
182
e5e12280
BP
183 /* Initialize IDL. */
184 idl = the_idl = ovsdb_idl_create(db, &ovsrec_idl_class, false);
185 run_prerequisites(commands, n_commands, idl);
186
524555d1 187 /* Now execute the commands. */
4fdfe5cc 188 status = TXN_AGAIN_WAIT;
c75d1511 189 for (;;) {
4fdfe5cc
BP
190 if (ovsdb_idl_run(idl) || status == TXN_AGAIN_NOW) {
191 status = do_vsctl(args, commands, n_commands, idl);
c75d1511
BP
192 }
193
4fdfe5cc
BP
194 if (status != TXN_AGAIN_NOW) {
195 ovsdb_idl_wait(idl);
196 poll_block();
197 }
c75d1511
BP
198 }
199}
200
201static void
202parse_options(int argc, char *argv[])
203{
204 enum {
205 OPT_DB = UCHAR_MAX + 1,
206 OPT_ONELINE,
0c3dd1e1 207 OPT_NO_SYSLOG,
577aebdf 208 OPT_NO_WAIT,
e26b5a06 209 OPT_DRY_RUN,
218a6f59 210 OPT_PEER_CA_CERT,
e051b42c
BP
211 VLOG_OPTION_ENUMS,
212 TABLE_OPTION_ENUMS
c75d1511
BP
213 };
214 static struct option long_options[] = {
e3c17733
BP
215 {"db", required_argument, NULL, OPT_DB},
216 {"no-syslog", no_argument, NULL, OPT_NO_SYSLOG},
217 {"no-wait", no_argument, NULL, OPT_NO_WAIT},
218 {"dry-run", no_argument, NULL, OPT_DRY_RUN},
219 {"oneline", no_argument, NULL, OPT_ONELINE},
220 {"timeout", required_argument, NULL, 't'},
221 {"help", no_argument, NULL, 'h'},
222 {"version", no_argument, NULL, 'V'},
e26b5a06 223 VLOG_LONG_OPTIONS,
e051b42c 224 TABLE_LONG_OPTIONS,
bf8f2167 225 STREAM_SSL_LONG_OPTIONS,
e3c17733
BP
226 {"peer-ca-cert", required_argument, NULL, OPT_PEER_CA_CERT},
227 {NULL, 0, NULL, 0},
c75d1511 228 };
a2a9d2d9 229 char *tmp, *short_options;
c75d1511 230
a2a9d2d9
BP
231 tmp = long_options_to_short_options(long_options);
232 short_options = xasprintf("+%s", tmp);
233 free(tmp);
342045e1 234
e051b42c
BP
235 table_style.format = TF_LIST;
236
c75d1511
BP
237 for (;;) {
238 int c;
239
a2a9d2d9 240 c = getopt_long(argc, argv, short_options, long_options, NULL);
c75d1511
BP
241 if (c == -1) {
242 break;
243 }
244
245 switch (c) {
246 case OPT_DB:
247 db = optarg;
248 break;
249
250 case OPT_ONELINE:
251 oneline = true;
252 break;
253
dfbe07ba 254 case OPT_NO_SYSLOG:
480ce8ab 255 vlog_set_levels(&VLM_vsctl, VLF_SYSLOG, VLL_WARN);
dfbe07ba
BP
256 break;
257
0c3dd1e1 258 case OPT_NO_WAIT:
b54e22e9 259 wait_for_reload = false;
0c3dd1e1
BP
260 break;
261
577aebdf
BP
262 case OPT_DRY_RUN:
263 dry_run = true;
264 break;
265
c75d1511
BP
266 case 'h':
267 usage();
268
269 case 'V':
55d5bb44 270 ovs_print_version(0, 0);
c75d1511
BP
271 exit(EXIT_SUCCESS);
272
342045e1
BP
273 case 't':
274 timeout = strtoul(optarg, NULL, 10);
a39a859a 275 if (timeout < 0) {
def90f62
BP
276 vsctl_fatal("value %s on -t or --timeout is invalid",
277 optarg);
342045e1
BP
278 }
279 break;
280
e26b5a06 281 VLOG_OPTION_HANDLERS
e051b42c 282 TABLE_OPTION_HANDLERS(&table_style)
c75d1511 283
218a6f59
BP
284 STREAM_SSL_OPTION_HANDLERS
285
286 case OPT_PEER_CA_CERT:
287 stream_ssl_set_peer_ca_cert_file(optarg);
288 break;
218a6f59 289
c75d1511
BP
290 case '?':
291 exit(EXIT_FAILURE);
292
293 default:
294 abort();
295 }
296 }
a2a9d2d9 297 free(short_options);
c75d1511
BP
298
299 if (!db) {
300 db = default_db();
301 }
302}
303
f8ff4bc4
BP
304static struct vsctl_command *
305parse_commands(int argc, char *argv[], size_t *n_commandsp)
306{
307 struct vsctl_command *commands;
308 size_t n_commands, allocated_commands;
309 int i, start;
310
311 commands = NULL;
312 n_commands = allocated_commands = 0;
313
314 for (start = i = 0; i <= argc; i++) {
315 if (i == argc || !strcmp(argv[i], "--")) {
316 if (i > start) {
317 if (n_commands >= allocated_commands) {
318 struct vsctl_command *c;
319
320 commands = x2nrealloc(commands, &allocated_commands,
321 sizeof *commands);
322 for (c = commands; c < &commands[n_commands]; c++) {
323 shash_moved(&c->options);
324 }
325 }
326 parse_command(i - start, &argv[start],
327 &commands[n_commands++]);
328 }
329 start = i + 1;
330 }
331 }
332 if (!n_commands) {
333 vsctl_fatal("missing command name (use --help for help)");
334 }
335 *n_commandsp = n_commands;
336 return commands;
337}
338
339static void
340parse_command(int argc, char *argv[], struct vsctl_command *command)
341{
342 const struct vsctl_command_syntax *p;
1998cd4d
BP
343 struct shash_node *node;
344 int n_arg;
f8ff4bc4
BP
345 int i;
346
347 shash_init(&command->options);
348 for (i = 0; i < argc; i++) {
4a033593
BP
349 const char *option = argv[i];
350 const char *equals;
351 char *key, *value;
352
353 if (option[0] != '-') {
f8ff4bc4
BP
354 break;
355 }
4a033593
BP
356
357 equals = strchr(option, '=');
358 if (equals) {
359 key = xmemdup0(option, equals - option);
360 value = xstrdup(equals + 1);
361 } else {
362 key = xstrdup(option);
363 value = NULL;
364 }
365
366 if (shash_find(&command->options, key)) {
f8ff4bc4
BP
367 vsctl_fatal("'%s' option specified multiple times", argv[i]);
368 }
4a033593 369 shash_add_nocopy(&command->options, key, value);
f8ff4bc4
BP
370 }
371 if (i == argc) {
372 vsctl_fatal("missing command name");
373 }
374
1998cd4d
BP
375 p = find_command(argv[i]);
376 if (!p) {
377 vsctl_fatal("unknown command '%s'; use --help for help", argv[i]);
378 }
f8ff4bc4 379
1998cd4d
BP
380 SHASH_FOR_EACH (node, &command->options) {
381 const char *s = strstr(p->options, node->name);
382 int end = s ? s[strlen(node->name)] : EOF;
4a033593 383
1998cd4d
BP
384 if (end != '=' && end != ',' && end != ' ' && end != '\0') {
385 vsctl_fatal("'%s' command has no '%s' option",
386 argv[i], node->name);
387 }
388 if ((end == '=') != (node->data != NULL)) {
389 if (end == '=') {
390 vsctl_fatal("missing argument to '%s' option on '%s' "
391 "command", node->name, argv[i]);
392 } else {
393 vsctl_fatal("'%s' option on '%s' does not accept an "
394 "argument", node->name, argv[i]);
f8ff4bc4 395 }
1998cd4d
BP
396 }
397 }
f8ff4bc4 398
1998cd4d
BP
399 n_arg = argc - i - 1;
400 if (n_arg < p->min_args) {
401 vsctl_fatal("'%s' command requires at least %d arguments",
402 p->name, p->min_args);
403 } else if (n_arg > p->max_args) {
404 int j;
405
406 for (j = i + 1; j < argc; j++) {
407 if (argv[j][0] == '-') {
408 vsctl_fatal("'%s' command takes at most %d arguments "
409 "(note that options must precede command "
410 "names and follow a \"--\" argument)",
f8ff4bc4 411 p->name, p->max_args);
f8ff4bc4
BP
412 }
413 }
1998cd4d
BP
414
415 vsctl_fatal("'%s' command takes at most %d arguments",
416 p->name, p->max_args);
417 }
418
419 command->syntax = p;
420 command->argc = n_arg + 1;
421 command->argv = &argv[i];
422}
423
424/* Returns the "struct vsctl_command_syntax" for a given command 'name', or a
425 * null pointer if there is none. */
426static const struct vsctl_command_syntax *
427find_command(const char *name)
428{
429 static struct shash commands = SHASH_INITIALIZER(&commands);
430
431 if (shash_is_empty(&commands)) {
432 const struct vsctl_command_syntax *p;
433
434 for (p = all_commands; p->name; p++) {
435 shash_add_assert(&commands, p->name, p);
436 }
f8ff4bc4
BP
437 }
438
1998cd4d 439 return shash_find_data(&commands, name);
f8ff4bc4
BP
440}
441
442static void
443vsctl_fatal(const char *format, ...)
444{
445 char *message;
446 va_list args;
447
448 va_start(args, format);
449 message = xvasprintf(format, args);
450 va_end(args);
451
c1a543a8 452 vlog_set_levels(&VLM_vsctl, VLF_CONSOLE, VLL_OFF);
f8ff4bc4 453 VLOG_ERR("%s", message);
def90f62 454 ovs_error(0, "%s", message);
1d48b4be
BP
455 vsctl_exit(EXIT_FAILURE);
456}
457
458/* Frees the current transaction and the underlying IDL and then calls
459 * exit(status).
460 *
461 * Freeing the transaction and the IDL is not strictly necessary, but it makes
462 * for a clean memory leak report from valgrind in the normal case. That makes
463 * it easier to notice real memory leaks. */
464static void
465vsctl_exit(int status)
466{
467 if (the_idl_txn) {
468 ovsdb_idl_txn_abort(the_idl_txn);
469 ovsdb_idl_txn_destroy(the_idl_txn);
470 }
471 ovsdb_idl_destroy(the_idl);
472 exit(status);
f8ff4bc4
BP
473}
474
c75d1511
BP
475static void
476usage(void)
477{
8f7501e8
BP
478 printf("\
479%s: ovs-vswitchd management utility\n\
480usage: %s [OPTIONS] COMMAND [ARG...]\n\
481\n\
ae9a3235
BP
482Open vSwitch commands:\n\
483 init initialize database, if not yet initialized\n\
9b1735a7 484 show print overview of database contents\n\
ae9a3235
BP
485 emer-reset reset configuration to clean state\n\
486\n\
8f7501e8
BP
487Bridge commands:\n\
488 add-br BRIDGE create a new bridge named BRIDGE\n\
489 add-br BRIDGE PARENT VLAN create new fake BRIDGE in PARENT on VLAN\n\
490 del-br BRIDGE delete BRIDGE and all of its ports\n\
491 list-br print the names of all the bridges\n\
492 br-exists BRIDGE test whether BRIDGE exists\n\
493 br-to-vlan BRIDGE print the VLAN which BRIDGE is on\n\
494 br-to-parent BRIDGE print the parent of BRIDGE\n\
495 br-set-external-id BRIDGE KEY VALUE set KEY on BRIDGE to VALUE\n\
496 br-set-external-id BRIDGE KEY unset KEY on BRIDGE\n\
497 br-get-external-id BRIDGE KEY print value of KEY on BRIDGE\n\
498 br-get-external-id BRIDGE list key-value pairs on BRIDGE\n\
499\n\
ae9a3235 500Port commands (a bond is considered to be a single port):\n\
8f7501e8
BP
501 list-ports BRIDGE print the names of all the ports on BRIDGE\n\
502 add-port BRIDGE PORT add network device PORT to BRIDGE\n\
503 add-bond BRIDGE PORT IFACE... add bonded port PORT in BRIDGE from IFACES\n\
504 del-port [BRIDGE] PORT delete PORT (which may be bonded) from BRIDGE\n\
505 port-to-br PORT print name of bridge that contains PORT\n\
8f7501e8
BP
506\n\
507Interface commands (a bond consists of multiple interfaces):\n\
508 list-ifaces BRIDGE print the names of all interfaces on BRIDGE\n\
509 iface-to-br IFACE print name of bridge that contains IFACE\n\
8f7501e8
BP
510\n\
511Controller commands:\n\
a892775d
BP
512 get-controller BRIDGE print the controllers for BRIDGE\n\
513 del-controller BRIDGE delete the controllers for BRIDGE\n\
514 set-controller BRIDGE TARGET... set the controllers for BRIDGE\n\
1a048029
JP
515 get-fail-mode BRIDGE print the fail-mode for BRIDGE\n\
516 del-fail-mode BRIDGE delete the fail-mode for BRIDGE\n\
517 set-fail-mode BRIDGE MODE set the fail-mode for BRIDGE to MODE\n\
8f7501e8 518\n\
24b8b259 519Manager commands:\n\
a892775d
BP
520 get-manager print the managers\n\
521 del-manager delete the managers\n\
522 set-manager TARGET... set the list of managers to TARGET...\n\
24b8b259 523\n\
8f7501e8
BP
524SSL commands:\n\
525 get-ssl print the SSL configuration\n\
526 del-ssl delete the SSL configuration\n\
527 set-ssl PRIV-KEY CERT CA-CERT set the SSL configuration\n\
528\n\
18ee958b
JP
529Switch commands:\n\
530 emer-reset reset switch to known good state\n\
531\n\
8f7501e8
BP
532Database commands:\n\
533 list TBL [REC] list RECord (or all records) in TBL\n\
0a140468 534 find TBL CONDITION... list records satisfying CONDITION in TBL\n\
4f1361e8 535 get TBL REC COL[:KEY] print values of COLumns in RECord in TBL\n\
8f7501e8
BP
536 set TBL REC COL[:KEY]=VALUE set COLumn values in RECord in TBL\n\
537 add TBL REC COL [KEY=]VALUE add (KEY=)VALUE to COLumn in RECord in TBL\n\
538 remove TBL REC COL [KEY=]VALUE remove (KEY=)VALUE from COLumn\n\
539 clear TBL REC COL clear values from COLumn in RECord in TBL\n\
540 create TBL COL[:KEY]=VALUE create and initialize new record\n\
4f1361e8 541 destroy TBL REC delete RECord from TBL\n\
7db03f7c 542 wait-until TBL REC [COL[:KEY]=VALUE] wait until condition is true\n\
8f7501e8
BP
543Potentially unsafe database commands require --force option.\n\
544\n\
545Options:\n\
546 --db=DATABASE connect to DATABASE\n\
547 (default: %s)\n\
ae9a3235
BP
548 --no-wait do not wait for ovs-vswitchd to reconfigure\n\
549 -t, --timeout=SECS wait at most SECS seconds for ovs-vswitchd\n\
550 --dry-run do not commit changes to database\n\
8f7501e8
BP
551 --oneline print exactly one line of output per command\n",
552 program_name, program_name, default_db());
c75d1511 553 vlog_usage();
ae9a3235
BP
554 printf("\
555 --no-syslog equivalent to --verbose=vsctl:syslog:warn\n");
556 stream_usage("database", true, true, false);
8f7501e8
BP
557 printf("\n\
558Other options:\n\
559 -h, --help display this help message\n\
560 -V, --version display version information\n");
c75d1511
BP
561 exit(EXIT_SUCCESS);
562}
563
564static char *
565default_db(void)
566{
567 static char *def;
568 if (!def) {
b43c6fe2 569 def = xasprintf("unix:%s/db.sock", ovs_rundir());
c75d1511
BP
570 }
571 return def;
572}
0c18b5a0
BP
573
574/* Returns true if it looks like this set of arguments might modify the
575 * database, otherwise false. (Not very smart, so it's prone to false
576 * positives.) */
577static bool
578might_write_to_db(char **argv)
579{
580 for (; *argv; argv++) {
581 const struct vsctl_command_syntax *p = find_command(*argv);
582 if (p && p->mode == RW) {
583 return true;
584 }
585 }
586 return false;
587}
c75d1511 588\f
5d9cb63c 589struct vsctl_context {
f8ff4bc4 590 /* Read-only. */
5d9cb63c
BP
591 int argc;
592 char **argv;
f8ff4bc4
BP
593 struct shash options;
594
595 /* Modifiable state. */
596 struct ds output;
e051b42c 597 struct table *table;
ad83bfa6 598 struct ovsdb_idl *idl;
f8ff4bc4 599 struct ovsdb_idl_txn *txn;
ce5a3e38 600 struct ovsdb_symbol_table *symtab;
5d9cb63c 601 const struct ovsrec_open_vswitch *ovs;
f74055e7 602 bool verified_ports;
87b23a01
BP
603
604 /* A command may set this member to true if some prerequisite is not met
605 * and the caller should wait for something to change and then retry. */
606 bool try_again;
5d9cb63c
BP
607};
608
c75d1511
BP
609struct vsctl_bridge {
610 struct ovsrec_bridge *br_cfg;
611 char *name;
76ce9432 612 struct ovsrec_controller **ctrl;
31681a5d 613 char *fail_mode;
76ce9432 614 size_t n_ctrl;
c75d1511
BP
615 struct vsctl_bridge *parent;
616 int vlan;
617};
618
619struct vsctl_port {
620 struct ovsrec_port *port_cfg;
621 struct vsctl_bridge *bridge;
622};
623
624struct vsctl_iface {
625 struct ovsrec_interface *iface_cfg;
626 struct vsctl_port *port;
627};
628
629struct vsctl_info {
1588bb8d 630 struct vsctl_context *ctx;
e5e12280
BP
631 struct shash bridges; /* Maps from bridge name to struct vsctl_bridge. */
632 struct shash ports; /* Maps from port name to struct vsctl_port. */
633 struct shash ifaces; /* Maps from port name to struct vsctl_iface. */
c75d1511
BP
634};
635
bb1c67c8
BP
636static char *
637vsctl_context_to_string(const struct vsctl_context *ctx)
638{
639 const struct shash_node *node;
640 struct svec words;
641 char *s;
642 int i;
643
644 svec_init(&words);
645 SHASH_FOR_EACH (node, &ctx->options) {
646 svec_add(&words, node->name);
647 }
648 for (i = 0; i < ctx->argc; i++) {
649 svec_add(&words, ctx->argv[i]);
650 }
651 svec_terminate(&words);
652
653 s = process_escape_args(words.names);
654
655 svec_destroy(&words);
656
657 return s;
658}
659
f74055e7
BP
660static void
661verify_ports(struct vsctl_context *ctx)
662{
663 if (!ctx->verified_ports) {
664 const struct ovsrec_bridge *bridge;
665 const struct ovsrec_port *port;
666
667 ovsrec_open_vswitch_verify_bridges(ctx->ovs);
668 OVSREC_BRIDGE_FOR_EACH (bridge, ctx->idl) {
669 ovsrec_bridge_verify_ports(bridge);
670 }
671 OVSREC_PORT_FOR_EACH (port, ctx->idl) {
672 ovsrec_port_verify_interfaces(port);
673 }
674
675 ctx->verified_ports = true;
676 }
677}
678
c75d1511
BP
679static struct vsctl_bridge *
680add_bridge(struct vsctl_info *b,
681 struct ovsrec_bridge *br_cfg, const char *name,
682 struct vsctl_bridge *parent, int vlan)
683{
684 struct vsctl_bridge *br = xmalloc(sizeof *br);
685 br->br_cfg = br_cfg;
686 br->name = xstrdup(name);
687 br->parent = parent;
688 br->vlan = vlan;
76ce9432
BP
689 if (parent) {
690 br->ctrl = parent->br_cfg->controller;
691 br->n_ctrl = parent->br_cfg->n_controller;
31681a5d 692 br->fail_mode = parent->br_cfg->fail_mode;
76ce9432
BP
693 } else {
694 br->ctrl = br_cfg->controller;
695 br->n_ctrl = br_cfg->n_controller;
31681a5d 696 br->fail_mode = br_cfg->fail_mode;
76ce9432 697 }
c75d1511
BP
698 shash_add(&b->bridges, br->name, br);
699 return br;
700}
701
702static bool
703port_is_fake_bridge(const struct ovsrec_port *port_cfg)
704{
705 return (port_cfg->fake_bridge
706 && port_cfg->tag
707 && *port_cfg->tag >= 1 && *port_cfg->tag <= 4095);
708}
709
710static struct vsctl_bridge *
711find_vlan_bridge(struct vsctl_info *info,
712 struct vsctl_bridge *parent, int vlan)
713{
714 struct shash_node *node;
715
716 SHASH_FOR_EACH (node, &info->bridges) {
717 struct vsctl_bridge *br = node->data;
718 if (br->parent == parent && br->vlan == vlan) {
719 return br;
720 }
721 }
722
723 return NULL;
724}
725
726static void
727free_info(struct vsctl_info *info)
728{
729 struct shash_node *node;
730
731 SHASH_FOR_EACH (node, &info->bridges) {
732 struct vsctl_bridge *bridge = node->data;
733 free(bridge->name);
734 free(bridge);
735 }
736 shash_destroy(&info->bridges);
737
506051fc
BP
738 shash_destroy_free_data(&info->ports);
739 shash_destroy_free_data(&info->ifaces);
c75d1511
BP
740}
741
e5e12280
BP
742static void
743pre_get_info(struct vsctl_context *ctx)
744{
745 ovsdb_idl_add_column(ctx->idl, &ovsrec_open_vswitch_col_bridges);
746
747 ovsdb_idl_add_column(ctx->idl, &ovsrec_bridge_col_name);
748 ovsdb_idl_add_column(ctx->idl, &ovsrec_bridge_col_controller);
749 ovsdb_idl_add_column(ctx->idl, &ovsrec_bridge_col_fail_mode);
750 ovsdb_idl_add_column(ctx->idl, &ovsrec_bridge_col_ports);
751
752 ovsdb_idl_add_column(ctx->idl, &ovsrec_port_col_name);
753 ovsdb_idl_add_column(ctx->idl, &ovsrec_port_col_fake_bridge);
754 ovsdb_idl_add_column(ctx->idl, &ovsrec_port_col_tag);
755 ovsdb_idl_add_column(ctx->idl, &ovsrec_port_col_interfaces);
756
757 ovsdb_idl_add_column(ctx->idl, &ovsrec_interface_col_name);
758}
759
c75d1511 760static void
1588bb8d 761get_info(struct vsctl_context *ctx, struct vsctl_info *info)
c75d1511 762{
1588bb8d 763 const struct ovsrec_open_vswitch *ovs = ctx->ovs;
b3c01ed3 764 struct sset bridges, ports;
c75d1511
BP
765 size_t i;
766
1588bb8d 767 info->ctx = ctx;
c75d1511
BP
768 shash_init(&info->bridges);
769 shash_init(&info->ports);
770 shash_init(&info->ifaces);
771
b3c01ed3
BP
772 sset_init(&bridges);
773 sset_init(&ports);
c75d1511
BP
774 for (i = 0; i < ovs->n_bridges; i++) {
775 struct ovsrec_bridge *br_cfg = ovs->bridges[i];
776 struct vsctl_bridge *br;
777 size_t j;
778
b3c01ed3 779 if (!sset_add(&bridges, br_cfg->name)) {
c75d1511
BP
780 VLOG_WARN("%s: database contains duplicate bridge name",
781 br_cfg->name);
782 continue;
783 }
784 br = add_bridge(info, br_cfg, br_cfg->name, NULL, 0);
785 if (!br) {
786 continue;
787 }
788
789 for (j = 0; j < br_cfg->n_ports; j++) {
790 struct ovsrec_port *port_cfg = br_cfg->ports[j];
791
b3c01ed3 792 if (!sset_add(&ports, port_cfg->name)) {
48a69501 793 /* Duplicate port name. (We will warn about that later.) */
c75d1511
BP
794 continue;
795 }
796
797 if (port_is_fake_bridge(port_cfg)
b3c01ed3 798 && sset_add(&bridges, port_cfg->name)) {
c75d1511
BP
799 add_bridge(info, NULL, port_cfg->name, br, *port_cfg->tag);
800 }
801 }
802 }
b3c01ed3
BP
803 sset_destroy(&bridges);
804 sset_destroy(&ports);
c75d1511 805
b3c01ed3 806 sset_init(&bridges);
c75d1511
BP
807 for (i = 0; i < ovs->n_bridges; i++) {
808 struct ovsrec_bridge *br_cfg = ovs->bridges[i];
809 struct vsctl_bridge *br;
810 size_t j;
811
b3c01ed3 812 if (!sset_add(&bridges, br_cfg->name)) {
c75d1511
BP
813 continue;
814 }
815 br = shash_find_data(&info->bridges, br_cfg->name);
816 for (j = 0; j < br_cfg->n_ports; j++) {
817 struct ovsrec_port *port_cfg = br_cfg->ports[j];
818 struct vsctl_port *port;
819 size_t k;
820
48a69501
BP
821 port = shash_find_data(&info->ports, port_cfg->name);
822 if (port) {
823 if (port_cfg == port->port_cfg) {
824 VLOG_WARN("%s: port is in multiple bridges (%s and %s)",
825 port_cfg->name, br->name, port->bridge->name);
826 } else {
827 /* Log as an error because this violates the database's
828 * uniqueness constraints, so the database server shouldn't
829 * have allowed it. */
830 VLOG_ERR("%s: database contains duplicate port name",
831 port_cfg->name);
832 }
c75d1511
BP
833 continue;
834 }
835
836 if (port_is_fake_bridge(port_cfg)
b3c01ed3 837 && !sset_add(&bridges, port_cfg->name)) {
c75d1511
BP
838 continue;
839 }
840
841 port = xmalloc(sizeof *port);
842 port->port_cfg = port_cfg;
843 if (port_cfg->tag
844 && *port_cfg->tag >= 1 && *port_cfg->tag <= 4095) {
845 port->bridge = find_vlan_bridge(info, br, *port_cfg->tag);
846 if (!port->bridge) {
847 port->bridge = br;
848 }
849 } else {
850 port->bridge = br;
851 }
852 shash_add(&info->ports, port_cfg->name, port);
853
854 for (k = 0; k < port_cfg->n_interfaces; k++) {
855 struct ovsrec_interface *iface_cfg = port_cfg->interfaces[k];
856 struct vsctl_iface *iface;
857
48a69501
BP
858 iface = shash_find_data(&info->ifaces, iface_cfg->name);
859 if (iface) {
860 if (iface_cfg == iface->iface_cfg) {
861 VLOG_WARN("%s: interface is in multiple ports "
862 "(%s and %s)",
863 iface_cfg->name,
864 iface->port->port_cfg->name,
865 port->port_cfg->name);
866 } else {
867 /* Log as an error because this violates the database's
868 * uniqueness constraints, so the database server
869 * shouldn't have allowed it. */
870 VLOG_ERR("%s: database contains duplicate interface "
871 "name", iface_cfg->name);
872 }
c75d1511
BP
873 continue;
874 }
875
876 iface = xmalloc(sizeof *iface);
877 iface->iface_cfg = iface_cfg;
878 iface->port = port;
dfbe07ba 879 shash_add(&info->ifaces, iface_cfg->name, iface);
c75d1511
BP
880 }
881 }
882 }
b3c01ed3 883 sset_destroy(&bridges);
c75d1511
BP
884}
885
886static void
887check_conflicts(struct vsctl_info *info, const char *name,
888 char *msg)
889{
890 struct vsctl_iface *iface;
891 struct vsctl_port *port;
892
f74055e7
BP
893 verify_ports(info->ctx);
894
c75d1511 895 if (shash_find(&info->bridges, name)) {
c88b6a27
BP
896 vsctl_fatal("%s because a bridge named %s already exists",
897 msg, name);
c75d1511
BP
898 }
899
900 port = shash_find_data(&info->ports, name);
901 if (port) {
c88b6a27
BP
902 vsctl_fatal("%s because a port named %s already exists on "
903 "bridge %s", msg, name, port->bridge->name);
c75d1511
BP
904 }
905
906 iface = shash_find_data(&info->ifaces, name);
907 if (iface) {
c88b6a27
BP
908 vsctl_fatal("%s because an interface named %s already exists "
909 "on bridge %s", msg, name, iface->port->bridge->name);
c75d1511
BP
910 }
911
912 free(msg);
913}
914
915static struct vsctl_bridge *
01845ce8 916find_bridge(struct vsctl_info *info, const char *name, bool must_exist)
c75d1511
BP
917{
918 struct vsctl_bridge *br = shash_find_data(&info->bridges, name);
01845ce8 919 if (must_exist && !br) {
c88b6a27 920 vsctl_fatal("no bridge named %s", name);
c75d1511 921 }
f74055e7 922 ovsrec_open_vswitch_verify_bridges(info->ctx->ovs);
c75d1511
BP
923 return br;
924}
925
975ac531
JP
926static struct vsctl_bridge *
927find_real_bridge(struct vsctl_info *info, const char *name, bool must_exist)
928{
929 struct vsctl_bridge *br = find_bridge(info, name, must_exist);
930 if (br && br->parent) {
931 vsctl_fatal("%s is a fake bridge", name);
932 }
933 return br;
934}
935
c75d1511 936static struct vsctl_port *
01845ce8 937find_port(struct vsctl_info *info, const char *name, bool must_exist)
c75d1511
BP
938{
939 struct vsctl_port *port = shash_find_data(&info->ports, name);
460aad80 940 if (port && !strcmp(name, port->bridge->name)) {
01845ce8
BP
941 port = NULL;
942 }
943 if (must_exist && !port) {
c88b6a27 944 vsctl_fatal("no port named %s", name);
c75d1511 945 }
f74055e7 946 verify_ports(info->ctx);
c75d1511
BP
947 return port;
948}
949
950static struct vsctl_iface *
01845ce8 951find_iface(struct vsctl_info *info, const char *name, bool must_exist)
c75d1511
BP
952{
953 struct vsctl_iface *iface = shash_find_data(&info->ifaces, name);
460aad80 954 if (iface && !strcmp(name, iface->port->bridge->name)) {
01845ce8
BP
955 iface = NULL;
956 }
957 if (must_exist && !iface) {
c88b6a27 958 vsctl_fatal("no interface named %s", name);
c75d1511 959 }
f74055e7 960 verify_ports(info->ctx);
c75d1511
BP
961 return iface;
962}
963
964static void
965bridge_insert_port(struct ovsrec_bridge *br, struct ovsrec_port *port)
966{
967 struct ovsrec_port **ports;
968 size_t i;
969
970 ports = xmalloc(sizeof *br->ports * (br->n_ports + 1));
971 for (i = 0; i < br->n_ports; i++) {
972 ports[i] = br->ports[i];
973 }
c75d1511
BP
974 ports[br->n_ports] = port;
975 ovsrec_bridge_set_ports(br, ports, br->n_ports + 1);
976 free(ports);
977}
978
979static void
980bridge_delete_port(struct ovsrec_bridge *br, struct ovsrec_port *port)
981{
982 struct ovsrec_port **ports;
983 size_t i, n;
984
985 ports = xmalloc(sizeof *br->ports * br->n_ports);
986 for (i = n = 0; i < br->n_ports; i++) {
987 if (br->ports[i] != port) {
988 ports[n++] = br->ports[i];
989 }
990 }
991 ovsrec_bridge_set_ports(br, ports, n);
992 free(ports);
993}
994
995static void
996ovs_insert_bridge(const struct ovsrec_open_vswitch *ovs,
997 struct ovsrec_bridge *bridge)
998{
999 struct ovsrec_bridge **bridges;
1000 size_t i;
1001
1002 bridges = xmalloc(sizeof *ovs->bridges * (ovs->n_bridges + 1));
1003 for (i = 0; i < ovs->n_bridges; i++) {
1004 bridges[i] = ovs->bridges[i];
1005 }
1006 bridges[ovs->n_bridges] = bridge;
1007 ovsrec_open_vswitch_set_bridges(ovs, bridges, ovs->n_bridges + 1);
1008 free(bridges);
1009}
1010
1011static void
1012ovs_delete_bridge(const struct ovsrec_open_vswitch *ovs,
1013 struct ovsrec_bridge *bridge)
1014{
1015 struct ovsrec_bridge **bridges;
1016 size_t i, n;
1017
1018 bridges = xmalloc(sizeof *ovs->bridges * ovs->n_bridges);
1019 for (i = n = 0; i < ovs->n_bridges; i++) {
1020 if (ovs->bridges[i] != bridge) {
1021 bridges[n++] = ovs->bridges[i];
1022 }
1023 }
1024 ovsrec_open_vswitch_set_bridges(ovs, bridges, n);
1025 free(bridges);
1026}
1027
524555d1 1028static void
c69ee87c 1029cmd_init(struct vsctl_context *ctx OVS_UNUSED)
524555d1
BP
1030{
1031}
1032
9b1735a7
BP
1033struct cmd_show_table {
1034 const struct ovsdb_idl_table_class *table;
1035 const struct ovsdb_idl_column *name_column;
1036 const struct ovsdb_idl_column *columns[3];
1037 bool recurse;
1038};
1039
1040static struct cmd_show_table cmd_show_tables[] = {
1041 {&ovsrec_table_open_vswitch,
1042 NULL,
1043 {&ovsrec_open_vswitch_col_manager_options,
1044 &ovsrec_open_vswitch_col_bridges,
1045 &ovsrec_open_vswitch_col_ovs_version},
1046 false},
1047
1048 {&ovsrec_table_bridge,
1049 &ovsrec_bridge_col_name,
1050 {&ovsrec_bridge_col_controller,
1051 &ovsrec_bridge_col_fail_mode,
1052 &ovsrec_bridge_col_ports},
1053 false},
1054
1055 {&ovsrec_table_port,
1056 &ovsrec_port_col_name,
1057 {&ovsrec_port_col_tag,
1058 &ovsrec_port_col_trunks,
1059 &ovsrec_port_col_interfaces},
1060 false},
1061
1062 {&ovsrec_table_interface,
1063 &ovsrec_interface_col_name,
1064 {&ovsrec_interface_col_type,
1065 &ovsrec_interface_col_options,
1066 NULL},
1067 false},
1068
1069 {&ovsrec_table_controller,
1070 &ovsrec_controller_col_target,
1071 {&ovsrec_controller_col_is_connected,
1072 NULL,
1073 NULL},
1074 false},
1075
1076 {&ovsrec_table_manager,
1077 &ovsrec_manager_col_target,
1078 {&ovsrec_manager_col_is_connected,
1079 NULL,
1080 NULL},
1081 false},
1082};
1083
1084static void
1085pre_cmd_show(struct vsctl_context *ctx)
1086{
1087 struct cmd_show_table *show;
1088
1089 for (show = cmd_show_tables;
1090 show < &cmd_show_tables[ARRAY_SIZE(cmd_show_tables)];
1091 show++) {
1092 size_t i;
1093
1094 ovsdb_idl_add_table(ctx->idl, show->table);
1095 if (show->name_column) {
1096 ovsdb_idl_add_column(ctx->idl, show->name_column);
1097 }
1098 for (i = 0; i < ARRAY_SIZE(show->columns); i++) {
1099 const struct ovsdb_idl_column *column = show->columns[i];
1100 if (column) {
1101 ovsdb_idl_add_column(ctx->idl, column);
1102 }
1103 }
1104 }
1105}
1106
1107static struct cmd_show_table *
1108cmd_show_find_table_by_row(const struct ovsdb_idl_row *row)
1109{
1110 struct cmd_show_table *show;
1111
1112 for (show = cmd_show_tables;
1113 show < &cmd_show_tables[ARRAY_SIZE(cmd_show_tables)];
1114 show++) {
1115 if (show->table == row->table->class) {
1116 return show;
1117 }
1118 }
1119 return NULL;
1120}
1121
1122static struct cmd_show_table *
1123cmd_show_find_table_by_name(const char *name)
1124{
1125 struct cmd_show_table *show;
1126
1127 for (show = cmd_show_tables;
1128 show < &cmd_show_tables[ARRAY_SIZE(cmd_show_tables)];
1129 show++) {
1130 if (!strcmp(show->table->name, name)) {
1131 return show;
1132 }
1133 }
1134 return NULL;
1135}
1136
1137static void
1138cmd_show_row(struct vsctl_context *ctx, const struct ovsdb_idl_row *row,
1139 int level)
1140{
1141 struct cmd_show_table *show = cmd_show_find_table_by_row(row);
1142 size_t i;
1143
1144 ds_put_char_multiple(&ctx->output, ' ', level * 4);
1145 if (show && show->name_column) {
1146 const struct ovsdb_datum *datum;
1147
1148 ds_put_format(&ctx->output, "%s ", show->table->name);
1149 datum = ovsdb_idl_read(row, show->name_column);
1150 ovsdb_datum_to_string(datum, &show->name_column->type, &ctx->output);
1151 } else {
1152 ds_put_format(&ctx->output, UUID_FMT, UUID_ARGS(&row->uuid));
1153 }
1154 ds_put_char(&ctx->output, '\n');
1155
1156 if (!show || show->recurse) {
1157 return;
1158 }
1159
1160 show->recurse = true;
1161 for (i = 0; i < ARRAY_SIZE(show->columns); i++) {
1162 const struct ovsdb_idl_column *column = show->columns[i];
1163 const struct ovsdb_datum *datum;
1164
1165 if (!column) {
1166 break;
1167 }
1168
1169 datum = ovsdb_idl_read(row, column);
1170 if (column->type.key.type == OVSDB_TYPE_UUID &&
1171 column->type.key.u.uuid.refTableName) {
1172 struct cmd_show_table *ref_show;
1173 size_t j;
1174
1175 ref_show = cmd_show_find_table_by_name(
1176 column->type.key.u.uuid.refTableName);
1177 if (ref_show) {
1178 for (j = 0; j < datum->n; j++) {
1179 const struct ovsdb_idl_row *ref_row;
1180
1181 ref_row = ovsdb_idl_get_row_for_uuid(ctx->idl,
1182 ref_show->table,
1183 &datum->keys[j].uuid);
1184 if (ref_row) {
1185 cmd_show_row(ctx, ref_row, level + 1);
1186 }
1187 }
1188 continue;
1189 }
1190 }
1191
1192 if (!ovsdb_datum_is_default(datum, &column->type)) {
1193 ds_put_char_multiple(&ctx->output, ' ', (level + 1) * 4);
1194 ds_put_format(&ctx->output, "%s: ", column->name);
1195 ovsdb_datum_to_string(datum, &column->type, &ctx->output);
1196 ds_put_char(&ctx->output, '\n');
1197 }
1198 }
1199 show->recurse = false;
1200}
1201
1202static void
1203cmd_show(struct vsctl_context *ctx)
1204{
1205 const struct ovsdb_idl_row *row;
1206
1207 for (row = ovsdb_idl_first_row(ctx->idl, cmd_show_tables[0].table);
1208 row; row = ovsdb_idl_next_row(row)) {
1209 cmd_show_row(ctx, row, 0);
1210 }
1211}
1212
e5e12280
BP
1213static void
1214pre_cmd_emer_reset(struct vsctl_context *ctx)
1215{
87824b0b 1216 ovsdb_idl_add_column(ctx->idl, &ovsrec_open_vswitch_col_manager_options);
e5e12280
BP
1217 ovsdb_idl_add_column(ctx->idl, &ovsrec_open_vswitch_col_ssl);
1218
1219 ovsdb_idl_add_column(ctx->idl, &ovsrec_bridge_col_controller);
f67e3b66 1220 ovsdb_idl_add_column(ctx->idl, &ovsrec_bridge_col_fail_mode);
e5e12280
BP
1221 ovsdb_idl_add_column(ctx->idl, &ovsrec_bridge_col_mirrors);
1222 ovsdb_idl_add_column(ctx->idl, &ovsrec_bridge_col_netflow);
1223 ovsdb_idl_add_column(ctx->idl, &ovsrec_bridge_col_sflow);
1224 ovsdb_idl_add_column(ctx->idl, &ovsrec_bridge_col_flood_vlans);
1225 ovsdb_idl_add_column(ctx->idl, &ovsrec_bridge_col_other_config);
1226
1227 ovsdb_idl_add_column(ctx->idl, &ovsrec_port_col_other_config);
1228
1229 ovsdb_idl_add_column(ctx->idl,
1230 &ovsrec_interface_col_ingress_policing_rate);
1231 ovsdb_idl_add_column(ctx->idl,
1232 &ovsrec_interface_col_ingress_policing_burst);
1233}
1234
18ee958b
JP
1235static void
1236cmd_emer_reset(struct vsctl_context *ctx)
1237{
1238 const struct ovsdb_idl *idl = ctx->idl;
1239 const struct ovsrec_bridge *br;
1240 const struct ovsrec_port *port;
1241 const struct ovsrec_interface *iface;
28a14bf3
EJ
1242 const struct ovsrec_mirror *mirror, *next_mirror;
1243 const struct ovsrec_controller *ctrl, *next_ctrl;
1244 const struct ovsrec_manager *mgr, *next_mgr;
1245 const struct ovsrec_netflow *nf, *next_nf;
1246 const struct ovsrec_ssl *ssl, *next_ssl;
1247 const struct ovsrec_sflow *sflow, *next_sflow;
18ee958b 1248
18ee958b 1249 /* Reset the Open_vSwitch table. */
87824b0b 1250 ovsrec_open_vswitch_set_manager_options(ctx->ovs, NULL, 0);
18ee958b
JP
1251 ovsrec_open_vswitch_set_ssl(ctx->ovs, NULL);
1252
1253 OVSREC_BRIDGE_FOR_EACH (br, idl) {
1254 int i;
1255 char *hw_key = "hwaddr";
1256 char *hw_val = NULL;
1257
1258 ovsrec_bridge_set_controller(br, NULL, 0);
f67e3b66 1259 ovsrec_bridge_set_fail_mode(br, NULL);
18ee958b
JP
1260 ovsrec_bridge_set_mirrors(br, NULL, 0);
1261 ovsrec_bridge_set_netflow(br, NULL);
1262 ovsrec_bridge_set_sflow(br, NULL);
1263 ovsrec_bridge_set_flood_vlans(br, NULL, 0);
1264
1265 /* We only want to save the "hwaddr" key from other_config. */
1266 for (i=0; i < br->n_other_config; i++) {
1267 if (!strcmp(br->key_other_config[i], hw_key)) {
1268 hw_val = br->value_other_config[i];
1269 break;
1270 }
1271 }
1272 if (hw_val) {
1273 char *val = xstrdup(hw_val);
1274 ovsrec_bridge_set_other_config(br, &hw_key, &val, 1);
1275 free(val);
1276 } else {
1277 ovsrec_bridge_set_other_config(br, NULL, NULL, 0);
1278 }
1279 }
1280
1281 OVSREC_PORT_FOR_EACH (port, idl) {
1282 ovsrec_port_set_other_config(port, NULL, NULL, 0);
1283 }
1284
1285 OVSREC_INTERFACE_FOR_EACH (iface, idl) {
1286 /* xxx What do we do about gre/patch devices created by mgr? */
1287
1288 ovsrec_interface_set_ingress_policing_rate(iface, 0);
1289 ovsrec_interface_set_ingress_policing_burst(iface, 0);
1290 }
28a14bf3
EJ
1291
1292 OVSREC_MIRROR_FOR_EACH_SAFE (mirror, next_mirror, idl) {
1293 ovsrec_mirror_delete(mirror);
1294 }
1295
1296 OVSREC_CONTROLLER_FOR_EACH_SAFE (ctrl, next_ctrl, idl) {
1297 ovsrec_controller_delete(ctrl);
1298 }
1299
1300 OVSREC_MANAGER_FOR_EACH_SAFE (mgr, next_mgr, idl) {
1301 ovsrec_manager_delete(mgr);
1302 }
1303
1304 OVSREC_NETFLOW_FOR_EACH_SAFE (nf, next_nf, idl) {
1305 ovsrec_netflow_delete(nf);
1306 }
1307
1308 OVSREC_SSL_FOR_EACH_SAFE (ssl, next_ssl, idl) {
1309 ovsrec_ssl_delete(ssl);
1310 }
1311
1312 OVSREC_SFLOW_FOR_EACH_SAFE (sflow, next_sflow, idl) {
1313 ovsrec_sflow_delete(sflow);
1314 }
18ee958b
JP
1315}
1316
c75d1511 1317static void
5d9cb63c 1318cmd_add_br(struct vsctl_context *ctx)
c75d1511 1319{
e3c17733 1320 bool may_exist = shash_find(&ctx->options, "--may-exist") != NULL;
b89d8339 1321 const char *br_name, *parent_name;
c75d1511 1322 struct vsctl_info info;
b89d8339 1323 int vlan;
c75d1511 1324
aeee85aa
BP
1325 br_name = ctx->argv[1];
1326 if (ctx->argc == 2) {
1327 parent_name = NULL;
1328 vlan = 0;
1329 } else if (ctx->argc == 4) {
1330 parent_name = ctx->argv[2];
1331 vlan = atoi(ctx->argv[3]);
1332 if (vlan < 1 || vlan > 4095) {
1333 vsctl_fatal("%s: vlan must be between 1 and 4095", ctx->argv[0]);
1334 }
1335 } else {
1336 vsctl_fatal("'%s' command takes exactly 1 or 3 arguments",
1337 ctx->argv[0]);
1338 }
1339
1588bb8d 1340 get_info(ctx, &info);
aeee85aa
BP
1341 if (may_exist) {
1342 struct vsctl_bridge *br;
1343
1344 br = find_bridge(&info, br_name, false);
1345 if (br) {
1346 if (!parent_name) {
1347 if (br->parent) {
1348 vsctl_fatal("\"--may-exist add-br %s\" but %s is "
1349 "a VLAN bridge for VLAN %d",
1350 br_name, br_name, br->vlan);
1351 }
1352 } else {
1353 if (!br->parent) {
1354 vsctl_fatal("\"--may-exist add-br %s %s %d\" but %s "
1355 "is not a VLAN bridge",
1356 br_name, parent_name, vlan, br_name);
1357 } else if (strcmp(br->parent->name, parent_name)) {
1358 vsctl_fatal("\"--may-exist add-br %s %s %d\" but %s "
1359 "has the wrong parent %s",
1360 br_name, parent_name, vlan,
1361 br_name, br->parent->name);
1362 } else if (br->vlan != vlan) {
1363 vsctl_fatal("\"--may-exist add-br %s %s %d\" but %s "
1364 "is a VLAN bridge for the wrong VLAN %d",
1365 br_name, parent_name, vlan, br_name, br->vlan);
1366 }
1367 }
1368 return;
1369 }
1370 }
c75d1511
BP
1371 check_conflicts(&info, br_name,
1372 xasprintf("cannot create a bridge named %s", br_name));
1373
aeee85aa 1374 if (!parent_name) {
c75d1511
BP
1375 struct ovsrec_port *port;
1376 struct ovsrec_interface *iface;
aeee85aa 1377 struct ovsrec_bridge *br;
c75d1511 1378
f8ff4bc4 1379 iface = ovsrec_interface_insert(ctx->txn);
c75d1511 1380 ovsrec_interface_set_name(iface, br_name);
9106d88c 1381 ovsrec_interface_set_type(iface, "internal");
c75d1511 1382
f8ff4bc4 1383 port = ovsrec_port_insert(ctx->txn);
c75d1511
BP
1384 ovsrec_port_set_name(port, br_name);
1385 ovsrec_port_set_interfaces(port, &iface, 1);
1386
f8ff4bc4 1387 br = ovsrec_bridge_insert(ctx->txn);
c75d1511
BP
1388 ovsrec_bridge_set_name(br, br_name);
1389 ovsrec_bridge_set_ports(br, &port, 1);
1390
5d9cb63c 1391 ovs_insert_bridge(ctx->ovs, br);
aeee85aa 1392 } else {
c75d1511
BP
1393 struct vsctl_bridge *parent;
1394 struct ovsrec_port *port;
1395 struct ovsrec_interface *iface;
aeee85aa 1396 struct ovsrec_bridge *br;
c75d1511
BP
1397 int64_t tag = vlan;
1398
01845ce8 1399 parent = find_bridge(&info, parent_name, false);
c75d1511 1400 if (parent && parent->vlan) {
11aa5627 1401 vsctl_fatal("cannot create bridge with fake bridge as parent");
c75d1511
BP
1402 }
1403 if (!parent) {
c88b6a27 1404 vsctl_fatal("parent bridge %s does not exist", parent_name);
c75d1511
BP
1405 }
1406 br = parent->br_cfg;
1407
f8ff4bc4 1408 iface = ovsrec_interface_insert(ctx->txn);
c75d1511
BP
1409 ovsrec_interface_set_name(iface, br_name);
1410 ovsrec_interface_set_type(iface, "internal");
1411
f8ff4bc4 1412 port = ovsrec_port_insert(ctx->txn);
c75d1511
BP
1413 ovsrec_port_set_name(port, br_name);
1414 ovsrec_port_set_interfaces(port, &iface, 1);
1415 ovsrec_port_set_fake_bridge(port, true);
1416 ovsrec_port_set_tag(port, &tag, 1);
dfbe07ba
BP
1417
1418 bridge_insert_port(br, port);
c75d1511
BP
1419 }
1420
1421 free_info(&info);
1422}
1423
1424static void
28a14bf3 1425del_port(struct vsctl_info *info, struct vsctl_port *port)
c75d1511 1426{
28a14bf3
EJ
1427 struct shash_node *node;
1428
1429 SHASH_FOR_EACH (node, &info->ifaces) {
1430 struct vsctl_iface *iface = node->data;
1431 if (iface->port == port) {
1432 ovsrec_interface_delete(iface->iface_cfg);
1433 }
1434 }
1435 ovsrec_port_delete(port->port_cfg);
1436
c75d1511
BP
1437 bridge_delete_port((port->bridge->parent
1438 ? port->bridge->parent->br_cfg
1439 : port->bridge->br_cfg), port->port_cfg);
1440}
1441
1442static void
5d9cb63c 1443cmd_del_br(struct vsctl_context *ctx)
c75d1511 1444{
460aad80 1445 bool must_exist = !shash_find(&ctx->options, "--if-exists");
c75d1511 1446 struct vsctl_bridge *bridge;
460aad80 1447 struct vsctl_info info;
c75d1511 1448
1588bb8d 1449 get_info(ctx, &info);
460aad80
BP
1450 bridge = find_bridge(&info, ctx->argv[1], must_exist);
1451 if (bridge) {
28a14bf3 1452 struct shash_node *node;
c5f341ab 1453
28a14bf3
EJ
1454 SHASH_FOR_EACH (node, &info.ports) {
1455 struct vsctl_port *port = node->data;
1456 if (port->bridge == bridge || port->bridge->parent == bridge
1457 || !strcmp(port->port_cfg->name, bridge->name)) {
1458 del_port(&info, port);
c5f341ab 1459 }
c75d1511 1460 }
28a14bf3
EJ
1461 if (bridge->br_cfg) {
1462 ovsrec_bridge_delete(bridge->br_cfg);
1463 ovs_delete_bridge(ctx->ovs, bridge->br_cfg);
1464 }
c75d1511
BP
1465 }
1466 free_info(&info);
1467}
1468
dfbe07ba
BP
1469static void
1470output_sorted(struct svec *svec, struct ds *output)
1471{
1472 const char *name;
1473 size_t i;
1474
1475 svec_sort(svec);
1476 SVEC_FOR_EACH (i, name, svec) {
1477 ds_put_format(output, "%s\n", name);
1478 }
1479}
1480
c75d1511 1481static void
5d9cb63c 1482cmd_list_br(struct vsctl_context *ctx)
c75d1511
BP
1483{
1484 struct shash_node *node;
1485 struct vsctl_info info;
dfbe07ba 1486 struct svec bridges;
c75d1511 1487
1588bb8d 1488 get_info(ctx, &info);
dfbe07ba
BP
1489
1490 svec_init(&bridges);
c75d1511
BP
1491 SHASH_FOR_EACH (node, &info.bridges) {
1492 struct vsctl_bridge *br = node->data;
dfbe07ba 1493 svec_add(&bridges, br->name);
c75d1511 1494 }
5d9cb63c 1495 output_sorted(&bridges, &ctx->output);
dfbe07ba
BP
1496 svec_destroy(&bridges);
1497
c75d1511
BP
1498 free_info(&info);
1499}
1500
1501static void
5d9cb63c 1502cmd_br_exists(struct vsctl_context *ctx)
c75d1511
BP
1503{
1504 struct vsctl_info info;
1505
1588bb8d 1506 get_info(ctx, &info);
01845ce8 1507 if (!find_bridge(&info, ctx->argv[1], false)) {
1d48b4be 1508 vsctl_exit(2);
c75d1511
BP
1509 }
1510 free_info(&info);
1511}
1512
457e1eb0
BP
1513/* Returns true if 'b_prefix' (of length 'b_prefix_len') concatenated with 'b'
1514 * equals 'a', false otherwise. */
1515static bool
1516key_matches(const char *a,
1517 const char *b_prefix, size_t b_prefix_len, const char *b)
1518{
1519 return !strncmp(a, b_prefix, b_prefix_len) && !strcmp(a + b_prefix_len, b);
1520}
1521
1522static void
1523set_external_id(char **old_keys, char **old_values, size_t old_n,
1524 char *key, char *value,
1525 char ***new_keysp, char ***new_valuesp, size_t *new_np)
1526{
1527 char **new_keys;
1528 char **new_values;
1529 size_t new_n;
1530 size_t i;
1531
1532 new_keys = xmalloc(sizeof *new_keys * (old_n + 1));
1533 new_values = xmalloc(sizeof *new_values * (old_n + 1));
1534 new_n = 0;
1535 for (i = 0; i < old_n; i++) {
1536 if (strcmp(key, old_keys[i])) {
1537 new_keys[new_n] = old_keys[i];
1538 new_values[new_n] = old_values[i];
1539 new_n++;
1540 }
1541 }
1542 if (value) {
1543 new_keys[new_n] = key;
1544 new_values[new_n] = value;
1545 new_n++;
1546 }
1547 *new_keysp = new_keys;
1548 *new_valuesp = new_values;
1549 *new_np = new_n;
1550}
1551
e5e12280
BP
1552static void
1553pre_cmd_br_set_external_id(struct vsctl_context *ctx)
1554{
1555 pre_get_info(ctx);
1556 ovsdb_idl_add_column(ctx->idl, &ovsrec_bridge_col_external_ids);
1557 ovsdb_idl_add_column(ctx->idl, &ovsrec_port_col_external_ids);
1558}
1559
457e1eb0 1560static void
5d9cb63c 1561cmd_br_set_external_id(struct vsctl_context *ctx)
457e1eb0
BP
1562{
1563 struct vsctl_info info;
1564 struct vsctl_bridge *bridge;
1565 char **keys, **values;
1566 size_t n;
1567
1588bb8d 1568 get_info(ctx, &info);
01845ce8 1569 bridge = find_bridge(&info, ctx->argv[1], true);
457e1eb0
BP
1570 if (bridge->br_cfg) {
1571 set_external_id(bridge->br_cfg->key_external_ids,
1572 bridge->br_cfg->value_external_ids,
1573 bridge->br_cfg->n_external_ids,
5d9cb63c 1574 ctx->argv[2], ctx->argc >= 4 ? ctx->argv[3] : NULL,
457e1eb0 1575 &keys, &values, &n);
f74055e7 1576 ovsrec_bridge_verify_external_ids(bridge->br_cfg);
457e1eb0
BP
1577 ovsrec_bridge_set_external_ids(bridge->br_cfg, keys, values, n);
1578 } else {
5d9cb63c
BP
1579 char *key = xasprintf("fake-bridge-%s", ctx->argv[2]);
1580 struct vsctl_port *port = shash_find_data(&info.ports, ctx->argv[1]);
457e1eb0
BP
1581 set_external_id(port->port_cfg->key_external_ids,
1582 port->port_cfg->value_external_ids,
1583 port->port_cfg->n_external_ids,
5d9cb63c 1584 key, ctx->argc >= 4 ? ctx->argv[3] : NULL,
457e1eb0 1585 &keys, &values, &n);
f74055e7 1586 ovsrec_port_verify_external_ids(port->port_cfg);
457e1eb0
BP
1587 ovsrec_port_set_external_ids(port->port_cfg, keys, values, n);
1588 free(key);
1589 }
1590 free(keys);
1591 free(values);
1592
1593 free_info(&info);
1594}
1595
1596static void
1597get_external_id(char **keys, char **values, size_t n,
1598 const char *prefix, const char *key,
1599 struct ds *output)
1600{
1601 size_t prefix_len = strlen(prefix);
1602 struct svec svec;
1603 size_t i;
1604
1605 svec_init(&svec);
1606 for (i = 0; i < n; i++) {
1607 if (!key && !strncmp(keys[i], prefix, prefix_len)) {
1608 svec_add_nocopy(&svec, xasprintf("%s=%s",
1609 keys[i] + prefix_len, values[i]));
a6c8e0d9 1610 } else if (key && key_matches(keys[i], prefix, prefix_len, key)) {
457e1eb0
BP
1611 svec_add(&svec, values[i]);
1612 break;
1613 }
1614 }
1615 output_sorted(&svec, output);
1616 svec_destroy(&svec);
1617}
1618
e5e12280
BP
1619static void
1620pre_cmd_br_get_external_id(struct vsctl_context *ctx)
1621{
1622 pre_cmd_br_set_external_id(ctx);
1623}
1624
457e1eb0 1625static void
5d9cb63c 1626cmd_br_get_external_id(struct vsctl_context *ctx)
457e1eb0
BP
1627{
1628 struct vsctl_info info;
1629 struct vsctl_bridge *bridge;
1630
1588bb8d 1631 get_info(ctx, &info);
01845ce8 1632 bridge = find_bridge(&info, ctx->argv[1], true);
457e1eb0 1633 if (bridge->br_cfg) {
f74055e7 1634 ovsrec_bridge_verify_external_ids(bridge->br_cfg);
457e1eb0
BP
1635 get_external_id(bridge->br_cfg->key_external_ids,
1636 bridge->br_cfg->value_external_ids,
1637 bridge->br_cfg->n_external_ids,
5d9cb63c
BP
1638 "", ctx->argc >= 3 ? ctx->argv[2] : NULL,
1639 &ctx->output);
457e1eb0 1640 } else {
5d9cb63c 1641 struct vsctl_port *port = shash_find_data(&info.ports, ctx->argv[1]);
f74055e7 1642 ovsrec_port_verify_external_ids(port->port_cfg);
457e1eb0
BP
1643 get_external_id(port->port_cfg->key_external_ids,
1644 port->port_cfg->value_external_ids,
1645 port->port_cfg->n_external_ids,
5d9cb63c 1646 "fake-bridge-", ctx->argc >= 3 ? ctx->argv[2] : NULL, &ctx->output);
457e1eb0
BP
1647 }
1648 free_info(&info);
1649}
1650
1651
c75d1511 1652static void
5d9cb63c 1653cmd_list_ports(struct vsctl_context *ctx)
c75d1511
BP
1654{
1655 struct vsctl_bridge *br;
1656 struct shash_node *node;
1657 struct vsctl_info info;
dfbe07ba 1658 struct svec ports;
c75d1511 1659
1588bb8d 1660 get_info(ctx, &info);
01845ce8 1661 br = find_bridge(&info, ctx->argv[1], true);
f74055e7 1662 ovsrec_bridge_verify_ports(br->br_cfg ? br->br_cfg : br->parent->br_cfg);
dfbe07ba
BP
1663
1664 svec_init(&ports);
c75d1511
BP
1665 SHASH_FOR_EACH (node, &info.ports) {
1666 struct vsctl_port *port = node->data;
1667
1668 if (strcmp(port->port_cfg->name, br->name) && br == port->bridge) {
dfbe07ba 1669 svec_add(&ports, port->port_cfg->name);
c75d1511
BP
1670 }
1671 }
5d9cb63c 1672 output_sorted(&ports, &ctx->output);
dfbe07ba
BP
1673 svec_destroy(&ports);
1674
c75d1511
BP
1675 free_info(&info);
1676}
1677
1678static void
f8ff4bc4 1679add_port(struct vsctl_context *ctx,
bb1c67c8
BP
1680 const char *br_name, const char *port_name,
1681 bool may_exist, bool fake_iface,
18b239f5
BP
1682 char *iface_names[], int n_ifaces,
1683 char *settings[], int n_settings)
c75d1511
BP
1684{
1685 struct vsctl_info info;
1686 struct vsctl_bridge *bridge;
1687 struct ovsrec_interface **ifaces;
1688 struct ovsrec_port *port;
1689 size_t i;
1690
1588bb8d 1691 get_info(ctx, &info);
bb1c67c8 1692 if (may_exist) {
2a022368 1693 struct vsctl_port *vsctl_port;
bb1c67c8 1694
2a022368
BP
1695 vsctl_port = find_port(&info, port_name, false);
1696 if (vsctl_port) {
bb1c67c8 1697 struct svec want_names, have_names;
bb1c67c8
BP
1698
1699 svec_init(&want_names);
1700 for (i = 0; i < n_ifaces; i++) {
1701 svec_add(&want_names, iface_names[i]);
1702 }
1703 svec_sort(&want_names);
1704
1705 svec_init(&have_names);
2a022368
BP
1706 for (i = 0; i < vsctl_port->port_cfg->n_interfaces; i++) {
1707 svec_add(&have_names,
1708 vsctl_port->port_cfg->interfaces[i]->name);
bb1c67c8
BP
1709 }
1710 svec_sort(&have_names);
1711
2a022368 1712 if (strcmp(vsctl_port->bridge->name, br_name)) {
bb1c67c8
BP
1713 char *command = vsctl_context_to_string(ctx);
1714 vsctl_fatal("\"%s\" but %s is actually attached to bridge %s",
2a022368 1715 command, port_name, vsctl_port->bridge->name);
bb1c67c8
BP
1716 }
1717
1718 if (!svec_equal(&want_names, &have_names)) {
1719 char *have_names_string = svec_join(&have_names, ", ", "");
1720 char *command = vsctl_context_to_string(ctx);
1721
1722 vsctl_fatal("\"%s\" but %s actually has interface(s) %s",
1723 command, port_name, have_names_string);
1724 }
1725
1726 svec_destroy(&want_names);
1727 svec_destroy(&have_names);
1728
1729 return;
1730 }
1731 }
c75d1511
BP
1732 check_conflicts(&info, port_name,
1733 xasprintf("cannot create a port named %s", port_name));
bb1c67c8
BP
1734 for (i = 0; i < n_ifaces; i++) {
1735 check_conflicts(&info, iface_names[i],
1736 xasprintf("cannot create an interface named %s",
1737 iface_names[i]));
1738 }
01845ce8 1739 bridge = find_bridge(&info, br_name, true);
c75d1511
BP
1740
1741 ifaces = xmalloc(n_ifaces * sizeof *ifaces);
1742 for (i = 0; i < n_ifaces; i++) {
f8ff4bc4 1743 ifaces[i] = ovsrec_interface_insert(ctx->txn);
c75d1511
BP
1744 ovsrec_interface_set_name(ifaces[i], iface_names[i]);
1745 }
1746
f8ff4bc4 1747 port = ovsrec_port_insert(ctx->txn);
c75d1511
BP
1748 ovsrec_port_set_name(port, port_name);
1749 ovsrec_port_set_interfaces(port, ifaces, n_ifaces);
b4182c7f 1750 ovsrec_port_set_bond_fake_iface(port, fake_iface);
a0a9f31d
JP
1751 free(ifaces);
1752
c75d1511
BP
1753 if (bridge->vlan) {
1754 int64_t tag = bridge->vlan;
1755 ovsrec_port_set_tag(port, &tag, 1);
1756 }
1757
18b239f5 1758 for (i = 0; i < n_settings; i++) {
ce5a3e38
BP
1759 set_column(get_table("Port"), &port->header_, settings[i],
1760 ctx->symtab);
18b239f5
BP
1761 }
1762
c75d1511
BP
1763 bridge_insert_port((bridge->parent ? bridge->parent->br_cfg
1764 : bridge->br_cfg), port);
1765
1766 free_info(&info);
1767}
1768
1769static void
5d9cb63c 1770cmd_add_port(struct vsctl_context *ctx)
c75d1511 1771{
e3c17733 1772 bool may_exist = shash_find(&ctx->options, "--may-exist") != NULL;
bb1c67c8
BP
1773
1774 add_port(ctx, ctx->argv[1], ctx->argv[2], may_exist, false,
18b239f5 1775 &ctx->argv[2], 1, &ctx->argv[3], ctx->argc - 3);
c75d1511
BP
1776}
1777
1778static void
5d9cb63c 1779cmd_add_bond(struct vsctl_context *ctx)
c75d1511 1780{
e3c17733 1781 bool may_exist = shash_find(&ctx->options, "--may-exist") != NULL;
b4182c7f 1782 bool fake_iface = shash_find(&ctx->options, "--fake-iface");
18b239f5
BP
1783 int n_ifaces;
1784 int i;
1785
1786 n_ifaces = ctx->argc - 3;
1787 for (i = 3; i < ctx->argc; i++) {
1788 if (strchr(ctx->argv[i], '=')) {
1789 n_ifaces = i - 3;
1790 break;
1791 }
1792 }
1793 if (n_ifaces < 2) {
1794 vsctl_fatal("add-bond requires at least 2 interfaces, but only "
1795 "%d were specified", n_ifaces);
1796 }
b4182c7f 1797
bb1c67c8 1798 add_port(ctx, ctx->argv[1], ctx->argv[2], may_exist, fake_iface,
18b239f5
BP
1799 &ctx->argv[3], n_ifaces,
1800 &ctx->argv[n_ifaces + 3], ctx->argc - 3 - n_ifaces);
c75d1511
BP
1801}
1802
1803static void
5d9cb63c 1804cmd_del_port(struct vsctl_context *ctx)
c75d1511 1805{
460aad80 1806 bool must_exist = !shash_find(&ctx->options, "--if-exists");
7c79588e
BP
1807 bool with_iface = shash_find(&ctx->options, "--with-iface") != NULL;
1808 struct vsctl_port *port;
c75d1511
BP
1809 struct vsctl_info info;
1810
1588bb8d 1811 get_info(ctx, &info);
7c79588e
BP
1812 if (!with_iface) {
1813 port = find_port(&info, ctx->argv[ctx->argc - 1], must_exist);
1814 } else {
1815 const char *target = ctx->argv[ctx->argc - 1];
1816 struct vsctl_iface *iface;
1817
1818 port = find_port(&info, target, false);
1819 if (!port) {
1820 iface = find_iface(&info, target, false);
1821 if (iface) {
1822 port = iface->port;
1823 }
1824 }
1825 if (must_exist && !port) {
1826 vsctl_fatal("no port or interface named %s", target);
460aad80 1827 }
7c79588e 1828 }
460aad80 1829
7c79588e
BP
1830 if (port) {
1831 if (ctx->argc == 3) {
1832 struct vsctl_bridge *bridge;
1833
1834 bridge = find_bridge(&info, ctx->argv[1], true);
1835 if (port->bridge != bridge) {
1836 if (port->bridge->parent == bridge) {
1837 vsctl_fatal("bridge %s does not have a port %s (although "
1838 "its parent bridge %s does)",
1839 ctx->argv[1], ctx->argv[2],
1840 bridge->parent->name);
1841 } else {
1842 vsctl_fatal("bridge %s does not have a port %s",
1843 ctx->argv[1], ctx->argv[2]);
1844 }
460aad80 1845 }
c75d1511 1846 }
7c79588e 1847
28a14bf3 1848 del_port(&info, port);
c75d1511 1849 }
7c79588e 1850
c75d1511
BP
1851 free_info(&info);
1852}
1853
1854static void
5d9cb63c 1855cmd_port_to_br(struct vsctl_context *ctx)
c75d1511
BP
1856{
1857 struct vsctl_port *port;
1858 struct vsctl_info info;
1859
1588bb8d 1860 get_info(ctx, &info);
01845ce8 1861 port = find_port(&info, ctx->argv[1], true);
5d9cb63c 1862 ds_put_format(&ctx->output, "%s\n", port->bridge->name);
c75d1511
BP
1863 free_info(&info);
1864}
1865
1866static void
5d9cb63c 1867cmd_br_to_vlan(struct vsctl_context *ctx)
c75d1511
BP
1868{
1869 struct vsctl_bridge *bridge;
1870 struct vsctl_info info;
1871
1588bb8d 1872 get_info(ctx, &info);
01845ce8 1873 bridge = find_bridge(&info, ctx->argv[1], true);
5d9cb63c 1874 ds_put_format(&ctx->output, "%d\n", bridge->vlan);
c75d1511
BP
1875 free_info(&info);
1876}
1877
1878static void
5d9cb63c 1879cmd_br_to_parent(struct vsctl_context *ctx)
c75d1511
BP
1880{
1881 struct vsctl_bridge *bridge;
1882 struct vsctl_info info;
1883
1588bb8d 1884 get_info(ctx, &info);
01845ce8 1885 bridge = find_bridge(&info, ctx->argv[1], true);
c75d1511
BP
1886 if (bridge->parent) {
1887 bridge = bridge->parent;
1888 }
5d9cb63c 1889 ds_put_format(&ctx->output, "%s\n", bridge->name);
c75d1511
BP
1890 free_info(&info);
1891}
1892
1893static void
5d9cb63c 1894cmd_list_ifaces(struct vsctl_context *ctx)
c75d1511
BP
1895{
1896 struct vsctl_bridge *br;
1897 struct shash_node *node;
1898 struct vsctl_info info;
dfbe07ba 1899 struct svec ifaces;
c75d1511 1900
1588bb8d 1901 get_info(ctx, &info);
01845ce8 1902 br = find_bridge(&info, ctx->argv[1], true);
f74055e7 1903 verify_ports(ctx);
dfbe07ba
BP
1904
1905 svec_init(&ifaces);
c75d1511
BP
1906 SHASH_FOR_EACH (node, &info.ifaces) {
1907 struct vsctl_iface *iface = node->data;
1908
dfbe07ba
BP
1909 if (strcmp(iface->iface_cfg->name, br->name)
1910 && br == iface->port->bridge) {
1911 svec_add(&ifaces, iface->iface_cfg->name);
c75d1511
BP
1912 }
1913 }
5d9cb63c 1914 output_sorted(&ifaces, &ctx->output);
dfbe07ba
BP
1915 svec_destroy(&ifaces);
1916
c75d1511
BP
1917 free_info(&info);
1918}
1919
1920static void
5d9cb63c 1921cmd_iface_to_br(struct vsctl_context *ctx)
c75d1511
BP
1922{
1923 struct vsctl_iface *iface;
1924 struct vsctl_info info;
1925
1588bb8d 1926 get_info(ctx, &info);
01845ce8 1927 iface = find_iface(&info, ctx->argv[1], true);
5d9cb63c 1928 ds_put_format(&ctx->output, "%s\n", iface->port->bridge->name);
c75d1511
BP
1929 free_info(&info);
1930}
457e1eb0 1931
f74055e7
BP
1932static void
1933verify_controllers(struct ovsrec_bridge *bridge)
1934{
1935 if (bridge) {
1936 size_t i;
1937
1938 ovsrec_bridge_verify_controller(bridge);
1939 for (i = 0; i < bridge->n_controller; i++) {
1940 ovsrec_controller_verify_target(bridge->controller[i]);
1941 }
1942 }
1943}
1944
4e3e7ff9
BP
1945static void
1946pre_controller(struct vsctl_context *ctx)
1947{
1948 pre_get_info(ctx);
1949
1950 ovsdb_idl_add_column(ctx->idl, &ovsrec_controller_col_target);
1951}
1952
76ce9432 1953static void
1a048029 1954cmd_get_controller(struct vsctl_context *ctx)
76ce9432 1955{
1a048029
JP
1956 struct vsctl_info info;
1957 struct vsctl_bridge *br;
76ce9432
BP
1958 struct svec targets;
1959 size_t i;
1960
1588bb8d 1961 get_info(ctx, &info);
1a048029 1962 br = find_bridge(&info, ctx->argv[1], true);
f74055e7 1963 verify_controllers(br->br_cfg);
1a048029
JP
1964
1965 /* Print the targets in sorted order for reproducibility. */
76ce9432 1966 svec_init(&targets);
1a048029
JP
1967 for (i = 0; i < br->n_ctrl; i++) {
1968 svec_add(&targets, br->ctrl[i]->target);
76ce9432
BP
1969 }
1970
1971 svec_sort(&targets);
1972 for (i = 0; i < targets.n; i++) {
1973 ds_put_format(&ctx->output, "%s\n", targets.names[i]);
1974 }
1975 svec_destroy(&targets);
5aa00635
JP
1976
1977 free_info(&info);
1978}
1979
28a14bf3
EJ
1980static void
1981delete_controllers(struct ovsrec_controller **controllers,
1982 size_t n_controllers)
1983{
1984 size_t i;
1985
1986 for (i = 0; i < n_controllers; i++) {
1987 ovsrec_controller_delete(controllers[i]);
1988 }
1989}
1990
5aa00635
JP
1991static void
1992cmd_del_controller(struct vsctl_context *ctx)
1993{
1994 struct vsctl_info info;
1a048029 1995 struct vsctl_bridge *br;
5aa00635 1996
1588bb8d 1997 get_info(ctx, &info);
5aa00635 1998
c5f341ab 1999 br = find_real_bridge(&info, ctx->argv[1], true);
28a14bf3
EJ
2000 verify_controllers(br->br_cfg);
2001
2002 if (br->ctrl) {
2003 delete_controllers(br->ctrl, br->n_ctrl);
2004 ovsrec_bridge_set_controller(br->br_cfg, NULL, 0);
2005 }
5aa00635
JP
2006
2007 free_info(&info);
2008}
2009
76ce9432
BP
2010static struct ovsrec_controller **
2011insert_controllers(struct ovsdb_idl_txn *txn, char *targets[], size_t n)
2012{
2013 struct ovsrec_controller **controllers;
2014 size_t i;
2015
2016 controllers = xmalloc(n * sizeof *controllers);
2017 for (i = 0; i < n; i++) {
070723f9
JP
2018 if (vconn_verify_name(targets[i]) && pvconn_verify_name(targets[i])) {
2019 VLOG_WARN("target type \"%s\" is possibly erroneous", targets[i]);
2020 }
76ce9432
BP
2021 controllers[i] = ovsrec_controller_insert(txn);
2022 ovsrec_controller_set_target(controllers[i], targets[i]);
2023 }
2024
2025 return controllers;
2026}
2027
5aa00635
JP
2028static void
2029cmd_set_controller(struct vsctl_context *ctx)
2030{
2031 struct vsctl_info info;
1a048029
JP
2032 struct vsctl_bridge *br;
2033 struct ovsrec_controller **controllers;
2034 size_t n;
5aa00635 2035
1588bb8d 2036 get_info(ctx, &info);
1a048029 2037 br = find_real_bridge(&info, ctx->argv[1], true);
28a14bf3
EJ
2038 verify_controllers(br->br_cfg);
2039
2040 delete_controllers(br->ctrl, br->n_ctrl);
76ce9432 2041
1a048029
JP
2042 n = ctx->argc - 2;
2043 controllers = insert_controllers(ctx->txn, &ctx->argv[2], n);
2044 ovsrec_bridge_set_controller(br->br_cfg, controllers, n);
2045 free(controllers);
5aa00635
JP
2046
2047 free_info(&info);
2048}
2049
2050static void
2051cmd_get_fail_mode(struct vsctl_context *ctx)
2052{
2053 struct vsctl_info info;
1a048029 2054 struct vsctl_bridge *br;
5aa00635 2055
1588bb8d 2056 get_info(ctx, &info);
1a048029 2057 br = find_bridge(&info, ctx->argv[1], true);
5aa00635 2058
f74055e7
BP
2059 if (br->br_cfg) {
2060 ovsrec_bridge_verify_fail_mode(br->br_cfg);
2061 }
31681a5d
JP
2062 if (br->fail_mode && strlen(br->fail_mode)) {
2063 ds_put_format(&ctx->output, "%s\n", br->fail_mode);
5aa00635
JP
2064 }
2065
2066 free_info(&info);
2067}
2068
2069static void
2070cmd_del_fail_mode(struct vsctl_context *ctx)
2071{
2072 struct vsctl_info info;
1a048029 2073 struct vsctl_bridge *br;
5aa00635 2074
1588bb8d 2075 get_info(ctx, &info);
1a048029 2076 br = find_real_bridge(&info, ctx->argv[1], true);
5aa00635 2077
31681a5d 2078 ovsrec_bridge_set_fail_mode(br->br_cfg, NULL);
5aa00635
JP
2079
2080 free_info(&info);
2081}
2082
2083static void
2084cmd_set_fail_mode(struct vsctl_context *ctx)
2085{
2086 struct vsctl_info info;
1a048029
JP
2087 struct vsctl_bridge *br;
2088 const char *fail_mode = ctx->argv[2];
5aa00635 2089
1588bb8d 2090 get_info(ctx, &info);
1a048029 2091 br = find_real_bridge(&info, ctx->argv[1], true);
5aa00635
JP
2092
2093 if (strcmp(fail_mode, "standalone") && strcmp(fail_mode, "secure")) {
2094 vsctl_fatal("fail-mode must be \"standalone\" or \"secure\"");
2095 }
2096
31681a5d 2097 ovsrec_bridge_set_fail_mode(br->br_cfg, fail_mode);
5aa00635
JP
2098
2099 free_info(&info);
2100}
dd8ac6fe 2101
24b8b259
AE
2102static void
2103verify_managers(const struct ovsrec_open_vswitch *ovs)
2104{
2105 size_t i;
2106
24b8b259
AE
2107 ovsrec_open_vswitch_verify_manager_options(ovs);
2108
2109 for (i = 0; i < ovs->n_manager_options; ++i) {
2110 const struct ovsrec_manager *mgr = ovs->manager_options[i];
2111
2112 ovsrec_manager_verify_target(mgr);
2113 }
2114}
2115
2116static void
2117pre_manager(struct vsctl_context *ctx)
2118{
24b8b259
AE
2119 ovsdb_idl_add_column(ctx->idl, &ovsrec_open_vswitch_col_manager_options);
2120 ovsdb_idl_add_column(ctx->idl, &ovsrec_manager_col_target);
2121}
2122
2123static void
2124cmd_get_manager(struct vsctl_context *ctx)
2125{
2126 const struct ovsrec_open_vswitch *ovs = ctx->ovs;
2127 struct svec targets;
2128 size_t i;
2129
2130 verify_managers(ovs);
2131
2132 /* Print the targets in sorted order for reproducibility. */
2133 svec_init(&targets);
2134
24b8b259
AE
2135 for (i = 0; i < ovs->n_manager_options; i++) {
2136 svec_add(&targets, ovs->manager_options[i]->target);
2137 }
2138
2139 svec_sort_unique(&targets);
2140 for (i = 0; i < targets.n; i++) {
2141 ds_put_format(&ctx->output, "%s\n", targets.names[i]);
2142 }
2143 svec_destroy(&targets);
2144}
2145
24b8b259 2146static void
28a14bf3 2147delete_managers(const struct vsctl_context *ctx)
24b8b259
AE
2148{
2149 const struct ovsrec_open_vswitch *ovs = ctx->ovs;
28a14bf3
EJ
2150 size_t i;
2151
2152 /* Delete Manager rows pointed to by 'manager_options' column. */
2153 for (i = 0; i < ovs->n_manager_options; i++) {
2154 ovsrec_manager_delete(ovs->manager_options[i]);
2155 }
24b8b259 2156
28a14bf3 2157 /* Delete 'Manager' row refs in 'manager_options' column. */
c5f341ab 2158 ovsrec_open_vswitch_set_manager_options(ovs, NULL, 0);
24b8b259
AE
2159}
2160
28a14bf3
EJ
2161static void
2162cmd_del_manager(struct vsctl_context *ctx)
2163{
2164 const struct ovsrec_open_vswitch *ovs = ctx->ovs;
2165
2166 verify_managers(ovs);
2167 delete_managers(ctx);
2168}
2169
24b8b259
AE
2170static void
2171insert_managers(struct vsctl_context *ctx, char *targets[], size_t n)
2172{
2173 struct ovsrec_manager **managers;
2174 size_t i;
2175
24b8b259
AE
2176 /* Insert each manager in a new row in Manager table. */
2177 managers = xmalloc(n * sizeof *managers);
2178 for (i = 0; i < n; i++) {
070723f9
JP
2179 if (stream_verify_name(targets[i]) && pstream_verify_name(targets[i])) {
2180 VLOG_WARN("target type \"%s\" is possibly erroneous", targets[i]);
2181 }
24b8b259
AE
2182 managers[i] = ovsrec_manager_insert(ctx->txn);
2183 ovsrec_manager_set_target(managers[i], targets[i]);
2184 }
2185
2186 /* Store uuids of new Manager rows in 'manager_options' column. */
2187 ovsrec_open_vswitch_set_manager_options(ctx->ovs, managers, n);
2188 free(managers);
2189}
2190
2191static void
2192cmd_set_manager(struct vsctl_context *ctx)
2193{
2194 const size_t n = ctx->argc - 1;
2195
28a14bf3
EJ
2196 verify_managers(ctx->ovs);
2197 delete_managers(ctx);
24b8b259
AE
2198 insert_managers(ctx, &ctx->argv[1], n);
2199}
2200
e5e12280
BP
2201static void
2202pre_cmd_get_ssl(struct vsctl_context *ctx)
2203{
2204 ovsdb_idl_add_column(ctx->idl, &ovsrec_open_vswitch_col_ssl);
2205
2206 ovsdb_idl_add_column(ctx->idl, &ovsrec_ssl_col_private_key);
2207 ovsdb_idl_add_column(ctx->idl, &ovsrec_ssl_col_certificate);
2208 ovsdb_idl_add_column(ctx->idl, &ovsrec_ssl_col_ca_cert);
2209 ovsdb_idl_add_column(ctx->idl, &ovsrec_ssl_col_bootstrap_ca_cert);
2210}
2211
dd8ac6fe
JP
2212static void
2213cmd_get_ssl(struct vsctl_context *ctx)
2214{
2215 struct ovsrec_ssl *ssl = ctx->ovs->ssl;
2216
f74055e7 2217 ovsrec_open_vswitch_verify_ssl(ctx->ovs);
dd8ac6fe 2218 if (ssl) {
f74055e7
BP
2219 ovsrec_ssl_verify_private_key(ssl);
2220 ovsrec_ssl_verify_certificate(ssl);
2221 ovsrec_ssl_verify_ca_cert(ssl);
2222 ovsrec_ssl_verify_bootstrap_ca_cert(ssl);
2223
dd8ac6fe
JP
2224 ds_put_format(&ctx->output, "Private key: %s\n", ssl->private_key);
2225 ds_put_format(&ctx->output, "Certificate: %s\n", ssl->certificate);
2226 ds_put_format(&ctx->output, "CA Certificate: %s\n", ssl->ca_cert);
2227 ds_put_format(&ctx->output, "Bootstrap: %s\n",
2228 ssl->bootstrap_ca_cert ? "true" : "false");
2229 }
2230}
2231
e5e12280
BP
2232static void
2233pre_cmd_del_ssl(struct vsctl_context *ctx)
2234{
2235 ovsdb_idl_add_column(ctx->idl, &ovsrec_open_vswitch_col_ssl);
2236}
2237
dd8ac6fe
JP
2238static void
2239cmd_del_ssl(struct vsctl_context *ctx)
2240{
28a14bf3
EJ
2241 struct ovsrec_ssl *ssl = ctx->ovs->ssl;
2242
2243 if (ssl) {
2244 ovsrec_open_vswitch_verify_ssl(ctx->ovs);
2245 ovsrec_ssl_delete(ssl);
2246 ovsrec_open_vswitch_set_ssl(ctx->ovs, NULL);
2247 }
dd8ac6fe
JP
2248}
2249
e5e12280
BP
2250static void
2251pre_cmd_set_ssl(struct vsctl_context *ctx)
2252{
2253 ovsdb_idl_add_column(ctx->idl, &ovsrec_open_vswitch_col_ssl);
2254}
2255
dd8ac6fe
JP
2256static void
2257cmd_set_ssl(struct vsctl_context *ctx)
2258{
2259 bool bootstrap = shash_find(&ctx->options, "--bootstrap");
28a14bf3 2260 struct ovsrec_ssl *ssl = ctx->ovs->ssl;
dd8ac6fe 2261
28a14bf3
EJ
2262 ovsrec_open_vswitch_verify_ssl(ctx->ovs);
2263 if (ssl) {
2264 ovsrec_ssl_delete(ssl);
2265 }
f8ff4bc4 2266 ssl = ovsrec_ssl_insert(ctx->txn);
dd8ac6fe
JP
2267
2268 ovsrec_ssl_set_private_key(ssl, ctx->argv[1]);
2269 ovsrec_ssl_set_certificate(ssl, ctx->argv[2]);
2270 ovsrec_ssl_set_ca_cert(ssl, ctx->argv[3]);
2271
2272 ovsrec_ssl_set_bootstrap_ca_cert(ssl, bootstrap);
2273
2274 ovsrec_open_vswitch_set_ssl(ctx->ovs, ssl);
2275}
c75d1511 2276\f
ad83bfa6
BP
2277/* Parameter commands. */
2278
ad83bfa6
BP
2279struct vsctl_row_id {
2280 const struct ovsdb_idl_table_class *table;
2281 const struct ovsdb_idl_column *name_column;
2282 const struct ovsdb_idl_column *uuid_column;
2283};
2284
2285struct vsctl_table_class {
2286 struct ovsdb_idl_table_class *class;
ad83bfa6
BP
2287 struct vsctl_row_id row_ids[2];
2288};
2289
2290static const struct vsctl_table_class tables[] = {
bd76d25d 2291 {&ovsrec_table_bridge,
ad83bfa6
BP
2292 {{&ovsrec_table_bridge, &ovsrec_bridge_col_name, NULL},
2293 {NULL, NULL, NULL}}},
2294
bd76d25d 2295 {&ovsrec_table_controller,
ad83bfa6
BP
2296 {{&ovsrec_table_bridge,
2297 &ovsrec_bridge_col_name,
1a048029 2298 &ovsrec_bridge_col_controller}}},
ad83bfa6 2299
bd76d25d 2300 {&ovsrec_table_interface,
ad83bfa6
BP
2301 {{&ovsrec_table_interface, &ovsrec_interface_col_name, NULL},
2302 {NULL, NULL, NULL}}},
2303
bd76d25d 2304 {&ovsrec_table_mirror,
ad83bfa6
BP
2305 {{&ovsrec_table_mirror, &ovsrec_mirror_col_name, NULL},
2306 {NULL, NULL, NULL}}},
2307
94db5407
BP
2308 {&ovsrec_table_manager,
2309 {{&ovsrec_table_manager, &ovsrec_manager_col_target, NULL},
2310 {NULL, NULL, NULL}}},
2311
bd76d25d 2312 {&ovsrec_table_netflow,
ad83bfa6
BP
2313 {{&ovsrec_table_bridge,
2314 &ovsrec_bridge_col_name,
2315 &ovsrec_bridge_col_netflow},
2316 {NULL, NULL, NULL}}},
2317
bd76d25d 2318 {&ovsrec_table_open_vswitch,
ad83bfa6
BP
2319 {{&ovsrec_table_open_vswitch, NULL, NULL},
2320 {NULL, NULL, NULL}}},
2321
bd76d25d 2322 {&ovsrec_table_port,
ad83bfa6
BP
2323 {{&ovsrec_table_port, &ovsrec_port_col_name, NULL},
2324 {NULL, NULL, NULL}}},
2325
c1c9c9c4
BP
2326 {&ovsrec_table_qos,
2327 {{&ovsrec_table_port, &ovsrec_port_col_name, &ovsrec_port_col_qos},
2328 {NULL, NULL, NULL}}},
2329
2330 {&ovsrec_table_queue,
2331 {{NULL, NULL, NULL},
2332 {NULL, NULL, NULL}}},
2333
bd76d25d 2334 {&ovsrec_table_ssl,
ad83bfa6
BP
2335 {{&ovsrec_table_open_vswitch, NULL, &ovsrec_open_vswitch_col_ssl}}},
2336
d01600a2
BP
2337 {&ovsrec_table_sflow,
2338 {{&ovsrec_table_bridge,
2339 &ovsrec_bridge_col_name,
2340 &ovsrec_bridge_col_sflow},
2341 {NULL, NULL, NULL}}},
2342
bd76d25d 2343 {NULL, {{NULL, NULL, NULL}, {NULL, NULL, NULL}}}
ad83bfa6
BP
2344};
2345
1bc6ff29
BP
2346static void
2347die_if_error(char *error)
2348{
2349 if (error) {
def90f62 2350 vsctl_fatal("%s", error);
1bc6ff29
BP
2351 }
2352}
2353
ad83bfa6
BP
2354static int
2355to_lower_and_underscores(unsigned c)
2356{
2357 return c == '-' ? '_' : tolower(c);
2358}
2359
2360static unsigned int
2361score_partial_match(const char *name, const char *s)
2362{
2363 int score;
2364
5128bd9c
BP
2365 if (!strcmp(name, s)) {
2366 return UINT_MAX;
2367 }
ad83bfa6
BP
2368 for (score = 0; ; score++, name++, s++) {
2369 if (to_lower_and_underscores(*name) != to_lower_and_underscores(*s)) {
2370 break;
2371 } else if (*name == '\0') {
5128bd9c 2372 return UINT_MAX - 1;
ad83bfa6
BP
2373 }
2374 }
2375 return *s == '\0' ? score : 0;
2376}
2377
2378static const struct vsctl_table_class *
2379get_table(const char *table_name)
2380{
2381 const struct vsctl_table_class *table;
2382 const struct vsctl_table_class *best_match = NULL;
2383 unsigned int best_score = 0;
2384
2385 for (table = tables; table->class; table++) {
2386 unsigned int score = score_partial_match(table->class->name,
2387 table_name);
2388 if (score > best_score) {
2389 best_match = table;
2390 best_score = score;
2391 } else if (score == best_score) {
2392 best_match = NULL;
2393 }
2394 }
2395 if (best_match) {
2396 return best_match;
2397 } else if (best_score) {
def90f62 2398 vsctl_fatal("multiple table names match \"%s\"", table_name);
ad83bfa6 2399 } else {
def90f62 2400 vsctl_fatal("unknown table \"%s\"", table_name);
ad83bfa6
BP
2401 }
2402}
2403
e5e12280
BP
2404static const struct vsctl_table_class *
2405pre_get_table(struct vsctl_context *ctx, const char *table_name)
2406{
2407 const struct vsctl_table_class *table_class;
2408 int i;
2409
2410 table_class = get_table(table_name);
2411 ovsdb_idl_add_table(ctx->idl, table_class->class);
2412
2413 for (i = 0; i < ARRAY_SIZE(table_class->row_ids); i++) {
2414 const struct vsctl_row_id *id = &table_class->row_ids[i];
2415 if (id->table) {
2416 ovsdb_idl_add_table(ctx->idl, id->table);
2417 }
2418 if (id->name_column) {
2419 ovsdb_idl_add_column(ctx->idl, id->name_column);
2420 }
2421 if (id->uuid_column) {
2422 ovsdb_idl_add_column(ctx->idl, id->uuid_column);
2423 }
2424 }
2425
2426 return table_class;
2427}
2428
ad83bfa6
BP
2429static const struct ovsdb_idl_row *
2430get_row_by_id(struct vsctl_context *ctx, const struct vsctl_table_class *table,
e111e681 2431 const struct vsctl_row_id *id, const char *record_id)
ad83bfa6
BP
2432{
2433 const struct ovsdb_idl_row *referrer, *final;
2434
2435 if (!id->table) {
2436 return NULL;
2437 }
2438
2439 if (!id->name_column) {
2440 if (strcmp(record_id, ".")) {
2441 return NULL;
2442 }
2443 referrer = ovsdb_idl_first_row(ctx->idl, id->table);
2444 if (!referrer || ovsdb_idl_next_row(referrer)) {
2445 return NULL;
2446 }
2447 } else {
2448 const struct ovsdb_idl_row *row;
ad83bfa6 2449
ad83bfa6
BP
2450 referrer = NULL;
2451 for (row = ovsdb_idl_first_row(ctx->idl, id->table);
e111e681 2452 row != NULL;
ad83bfa6
BP
2453 row = ovsdb_idl_next_row(row))
2454 {
8c3c2f30 2455 const struct ovsdb_datum *name;
ad83bfa6 2456
8c3c2f30
BP
2457 name = ovsdb_idl_get(row, id->name_column,
2458 OVSDB_TYPE_STRING, OVSDB_TYPE_VOID);
e111e681
BP
2459 if (name->n == 1 && !strcmp(name->keys[0].string, record_id)) {
2460 if (referrer) {
2461 vsctl_fatal("multiple rows in %s match \"%s\"",
2462 table->class->name, record_id);
ad83bfa6 2463 }
e111e681 2464 referrer = row;
ad83bfa6 2465 }
ad83bfa6
BP
2466 }
2467 }
2468 if (!referrer) {
2469 return NULL;
2470 }
2471
93255bc5 2472 final = NULL;
ad83bfa6 2473 if (id->uuid_column) {
8c3c2f30 2474 const struct ovsdb_datum *uuid;
ad83bfa6 2475
f74055e7 2476 ovsdb_idl_txn_verify(referrer, id->uuid_column);
8c3c2f30
BP
2477 uuid = ovsdb_idl_get(referrer, id->uuid_column,
2478 OVSDB_TYPE_UUID, OVSDB_TYPE_VOID);
2479 if (uuid->n == 1) {
ad83bfa6 2480 final = ovsdb_idl_get_row_for_uuid(ctx->idl, table->class,
8c3c2f30 2481 &uuid->keys[0].uuid);
ad83bfa6 2482 }
ad83bfa6
BP
2483 } else {
2484 final = referrer;
2485 }
2486
2487 return final;
2488}
2489
2490static const struct ovsdb_idl_row *
e111e681
BP
2491get_row (struct vsctl_context *ctx,
2492 const struct vsctl_table_class *table, const char *record_id)
ad83bfa6
BP
2493{
2494 const struct ovsdb_idl_row *row;
2495 struct uuid uuid;
2496
2497 if (uuid_from_string(&uuid, record_id)) {
2498 row = ovsdb_idl_get_row_for_uuid(ctx->idl, table->class, &uuid);
2499 } else {
2500 int i;
2501
2502 for (i = 0; i < ARRAY_SIZE(table->row_ids); i++) {
e111e681 2503 row = get_row_by_id(ctx, table, &table->row_ids[i], record_id);
ad83bfa6
BP
2504 if (row) {
2505 break;
2506 }
2507 }
2508 }
b7f74b6f
BP
2509 return row;
2510}
2511
2512static const struct ovsdb_idl_row *
2513must_get_row(struct vsctl_context *ctx,
2514 const struct vsctl_table_class *table, const char *record_id)
2515{
2516 const struct ovsdb_idl_row *row = get_row(ctx, table, record_id);
ad83bfa6 2517 if (!row) {
def90f62
BP
2518 vsctl_fatal("no row \"%s\" in table %s",
2519 record_id, table->class->name);
ad83bfa6
BP
2520 }
2521 return row;
2522}
2523
1bc6ff29
BP
2524static char *
2525get_column(const struct vsctl_table_class *table, const char *column_name,
bd76d25d 2526 const struct ovsdb_idl_column **columnp)
ad83bfa6 2527{
bd76d25d 2528 const struct ovsdb_idl_column *best_match = NULL;
ad83bfa6 2529 unsigned int best_score = 0;
bd76d25d 2530 size_t i;
ad83bfa6 2531
bd76d25d
BP
2532 for (i = 0; i < table->class->n_columns; i++) {
2533 const struct ovsdb_idl_column *column = &table->class->columns[i];
2534 unsigned int score = score_partial_match(column->name, column_name);
2535 if (score > best_score) {
2536 best_match = column;
2537 best_score = score;
2538 } else if (score == best_score) {
2539 best_match = NULL;
ad83bfa6
BP
2540 }
2541 }
1bc6ff29
BP
2542
2543 *columnp = best_match;
ad83bfa6 2544 if (best_match) {
1bc6ff29 2545 return NULL;
ad83bfa6 2546 } else if (best_score) {
1bc6ff29
BP
2547 return xasprintf("%s contains more than one column whose name "
2548 "matches \"%s\"", table->class->name, column_name);
ad83bfa6 2549 } else {
1bc6ff29
BP
2550 return xasprintf("%s does not contain a column whose name matches "
2551 "\"%s\"", table->class->name, column_name);
ad83bfa6
BP
2552 }
2553}
2554
c5f341ab 2555static struct ovsdb_symbol *
aed133bf
BP
2556create_symbol(struct ovsdb_symbol_table *symtab, const char *id, bool *newp)
2557{
2558 struct ovsdb_symbol *symbol;
2559
2560 if (id[0] != '@') {
2561 vsctl_fatal("row id \"%s\" does not begin with \"@\"", id);
2562 }
2563
2564 if (newp) {
2565 *newp = ovsdb_symbol_table_get(symtab, id) == NULL;
2566 }
2567
2568 symbol = ovsdb_symbol_table_insert(symtab, id);
e9387de4 2569 if (symbol->created) {
aed133bf
BP
2570 vsctl_fatal("row id \"%s\" may only be specified on one --id option",
2571 id);
2572 }
e9387de4 2573 symbol->created = true;
c5f341ab 2574 return symbol;
aed133bf
BP
2575}
2576
e5e12280
BP
2577static void
2578pre_get_column(struct vsctl_context *ctx,
2579 const struct vsctl_table_class *table, const char *column_name,
2580 const struct ovsdb_idl_column **columnp)
2581{
2582 die_if_error(get_column(table, column_name, columnp));
2583 ovsdb_idl_add_column(ctx->idl, *columnp);
2584}
2585
e89e5374
BP
2586static char *
2587missing_operator_error(const char *arg, const char **allowed_operators,
2588 size_t n_allowed)
2589{
2590 struct ds s;
2591
2592 ds_init(&s);
2593 ds_put_format(&s, "%s: argument does not end in ", arg);
2594 ds_put_format(&s, "\"%s\"", allowed_operators[0]);
2595 if (n_allowed == 2) {
2596 ds_put_format(&s, " or \"%s\"", allowed_operators[1]);
2597 } else if (n_allowed > 2) {
2598 size_t i;
2599
2600 for (i = 1; i < n_allowed - 1; i++) {
2601 ds_put_format(&s, ", \"%s\"", allowed_operators[i]);
2602 }
2603 ds_put_format(&s, ", or \"%s\"", allowed_operators[i]);
2604 }
2605 ds_put_format(&s, " followed by a value.");
2606
2607 return ds_steal_cstr(&s);
2608}
2609
2610/* Breaks 'arg' apart into a number of fields in the following order:
2611 *
4a433a0f
BP
2612 * - The name of a column in 'table', stored into '*columnp'. The column
2613 * name may be abbreviated.
e89e5374 2614 *
4a433a0f
BP
2615 * - Optionally ':' followed by a key string. The key is stored as a
2616 * malloc()'d string into '*keyp', or NULL if no key is present in
2617 * 'arg'.
e89e5374
BP
2618 *
2619 * - If 'valuep' is nonnull, an operator followed by a value string. The
2620 * allowed operators are the 'n_allowed' string in 'allowed_operators',
2621 * or just "=" if 'n_allowed' is 0. If 'operatorp' is nonnull, then the
2622 * operator is stored into '*operatorp' (one of the pointers from
2623 * 'allowed_operators' is stored; nothing is malloc()'d). The value is
2624 * stored as a malloc()'d string into '*valuep', or NULL if no value is
2625 * present in 'arg'.
2626 *
e89e5374
BP
2627 * On success, returns NULL. On failure, returned a malloc()'d string error
2628 * message and stores NULL into all of the nonnull output arguments. */
1bc6ff29 2629static char * WARN_UNUSED_RESULT
e89e5374
BP
2630parse_column_key_value(const char *arg,
2631 const struct vsctl_table_class *table,
2632 const struct ovsdb_idl_column **columnp, char **keyp,
2633 const char **operatorp,
2634 const char **allowed_operators, size_t n_allowed,
2635 char **valuep)
ad83bfa6
BP
2636{
2637 const char *p = arg;
4a433a0f 2638 char *column_name;
1bc6ff29 2639 char *error;
ad83bfa6 2640
e89e5374 2641 assert(!(operatorp && !valuep));
4a433a0f 2642 *keyp = NULL;
1bc6ff29
BP
2643 if (valuep) {
2644 *valuep = NULL;
2645 }
ad83bfa6
BP
2646
2647 /* Parse column name. */
4a433a0f
BP
2648 error = ovsdb_token_parse(&p, &column_name);
2649 if (error) {
2650 goto error;
2651 }
2652 if (column_name[0] == '\0') {
a3326252 2653 free(column_name);
4a433a0f
BP
2654 error = xasprintf("%s: missing column name", arg);
2655 goto error;
2656 }
2657 error = get_column(table, column_name, columnp);
2658 free(column_name);
2659 if (error) {
2660 goto error;
ad83bfa6
BP
2661 }
2662
2663 /* Parse key string. */
4a433a0f
BP
2664 if (*p == ':') {
2665 p++;
1bc6ff29
BP
2666 error = ovsdb_token_parse(&p, keyp);
2667 if (error) {
2668 goto error;
ad83bfa6 2669 }
ad83bfa6
BP
2670 }
2671
2672 /* Parse value string. */
e89e5374
BP
2673 if (valuep) {
2674 const char *best;
2675 size_t best_len;
2676 size_t i;
2677
2678 if (!allowed_operators) {
2679 static const char *equals = "=";
2680 allowed_operators = &equals;
2681 n_allowed = 1;
2682 }
2683
2684 best = NULL;
2685 best_len = 0;
2686 for (i = 0; i < n_allowed; i++) {
2687 const char *op = allowed_operators[i];
2688 size_t op_len = strlen(op);
2689
7db03f7c 2690 if (op_len > best_len && !strncmp(op, p, op_len) && p[op_len]) {
e89e5374
BP
2691 best_len = op_len;
2692 best = op;
2693 }
2694 }
2695 if (!best) {
2696 error = missing_operator_error(arg, allowed_operators, n_allowed);
1bc6ff29 2697 goto error;
ad83bfa6 2698 }
e89e5374
BP
2699
2700 if (operatorp) {
2701 *operatorp = best;
2702 }
7db03f7c 2703 *valuep = xstrdup(p + best_len);
ad83bfa6 2704 } else {
1bc6ff29 2705 if (*p != '\0') {
c29a8ba8
BP
2706 error = xasprintf("%s: trailing garbage \"%s\" in argument",
2707 arg, p);
1bc6ff29
BP
2708 goto error;
2709 }
2710 }
2711 return NULL;
2712
2713error:
4a433a0f
BP
2714 *columnp = NULL;
2715 free(*keyp);
2716 *keyp = NULL;
1bc6ff29
BP
2717 if (valuep) {
2718 free(*valuep);
2719 *valuep = NULL;
e89e5374
BP
2720 if (operatorp) {
2721 *operatorp = NULL;
2722 }
ad83bfa6 2723 }
1bc6ff29 2724 return error;
ad83bfa6
BP
2725}
2726
e5e12280
BP
2727static void
2728pre_parse_column_key_value(struct vsctl_context *ctx,
2729 const char *arg,
2730 const struct vsctl_table_class *table)
2731{
2732 const struct ovsdb_idl_column *column;
2733 const char *p;
2734 char *column_name;
2735
2736 p = arg;
2737 die_if_error(ovsdb_token_parse(&p, &column_name));
2738 if (column_name[0] == '\0') {
2739 vsctl_fatal("%s: missing column name", arg);
2740 }
2741
2742 pre_get_column(ctx, table, column_name, &column);
2743 free(column_name);
2744}
2745
2746static void
2747pre_cmd_get(struct vsctl_context *ctx)
2748{
6d5abe94 2749 const char *id = shash_find_data(&ctx->options, "--id");
e5e12280
BP
2750 const char *table_name = ctx->argv[1];
2751 const struct vsctl_table_class *table;
2752 int i;
2753
6d5abe94
BP
2754 /* Using "get" without --id or a column name could possibly make sense.
2755 * Maybe, for example, a ovs-vsctl run wants to assert that a row exists.
2756 * But it is unlikely that an interactive user would want to do that, so
2757 * issue a warning if we're running on a terminal. */
2758 if (!id && ctx->argc <= 3 && isatty(STDOUT_FILENO)) {
2759 VLOG_WARN("\"get\" command without row arguments or \"--id\" is "
2760 "possibly erroneous");
2761 }
2762
e5e12280
BP
2763 table = pre_get_table(ctx, table_name);
2764 for (i = 3; i < ctx->argc; i++) {
2765 if (!strcasecmp(ctx->argv[i], "_uuid")
2766 || !strcasecmp(ctx->argv[i], "-uuid")) {
2767 continue;
2768 }
2769
2770 pre_parse_column_key_value(ctx, ctx->argv[i], table);
2771 }
2772}
2773
ad83bfa6
BP
2774static void
2775cmd_get(struct vsctl_context *ctx)
2776{
aed133bf 2777 const char *id = shash_find_data(&ctx->options, "--id");
870aeb4a 2778 bool if_exists = shash_find(&ctx->options, "--if-exists");
ad83bfa6
BP
2779 const char *table_name = ctx->argv[1];
2780 const char *record_id = ctx->argv[2];
2781 const struct vsctl_table_class *table;
2782 const struct ovsdb_idl_row *row;
2783 struct ds *out = &ctx->output;
2784 int i;
2785
2786 table = get_table(table_name);
b7f74b6f 2787 row = must_get_row(ctx, table, record_id);
aed133bf 2788 if (id) {
c5f341ab 2789 struct ovsdb_symbol *symbol;
aed133bf
BP
2790 bool new;
2791
c5f341ab 2792 symbol = create_symbol(ctx->symtab, id, &new);
aed133bf
BP
2793 if (!new) {
2794 vsctl_fatal("row id \"%s\" specified on \"get\" command was used "
2795 "before it was defined", id);
2796 }
c5f341ab
BP
2797 symbol->uuid = row->uuid;
2798
2799 /* This symbol refers to a row that already exists, so disable warnings
2800 * about it being unreferenced. */
2801 symbol->strong_ref = true;
aed133bf 2802 }
ad83bfa6 2803 for (i = 3; i < ctx->argc; i++) {
bd76d25d 2804 const struct ovsdb_idl_column *column;
8c3c2f30 2805 const struct ovsdb_datum *datum;
ad83bfa6
BP
2806 char *key_string;
2807
f40a9b61
BP
2808 /* Special case for obtaining the UUID of a row. We can't just do this
2809 * through parse_column_key_value() below since it returns a "struct
2810 * ovsdb_idl_column" and the UUID column doesn't have one. */
2811 if (!strcasecmp(ctx->argv[i], "_uuid")
2812 || !strcasecmp(ctx->argv[i], "-uuid")) {
2813 ds_put_format(out, UUID_FMT"\n", UUID_ARGS(&row->uuid));
2814 continue;
2815 }
2816
1bc6ff29 2817 die_if_error(parse_column_key_value(ctx->argv[i], table,
e89e5374
BP
2818 &column, &key_string,
2819 NULL, NULL, 0, NULL));
ad83bfa6 2820
f74055e7 2821 ovsdb_idl_txn_verify(row, column);
8c3c2f30 2822 datum = ovsdb_idl_read(row, column);
ad83bfa6
BP
2823 if (key_string) {
2824 union ovsdb_atom key;
2825 unsigned int idx;
2826
bd76d25d 2827 if (column->type.value.type == OVSDB_TYPE_VOID) {
def90f62 2828 vsctl_fatal("cannot specify key to get for non-map column %s",
bd76d25d 2829 column->name);
ad83bfa6
BP
2830 }
2831
1bc6ff29 2832 die_if_error(ovsdb_atom_from_string(&key,
bd76d25d 2833 &column->type.key,
ce5a3e38 2834 key_string, ctx->symtab));
ad83bfa6 2835
8c3c2f30 2836 idx = ovsdb_datum_find_key(datum, &key,
bd76d25d 2837 column->type.key.type);
ad83bfa6 2838 if (idx == UINT_MAX) {
870aeb4a 2839 if (!if_exists) {
def90f62
BP
2840 vsctl_fatal("no key \"%s\" in %s record \"%s\" column %s",
2841 key_string, table->class->name, record_id,
bd76d25d 2842 column->name);
870aeb4a
BP
2843 }
2844 } else {
8c3c2f30 2845 ovsdb_atom_to_string(&datum->values[idx],
bd76d25d 2846 column->type.value.type, out);
ad83bfa6 2847 }
bd76d25d 2848 ovsdb_atom_destroy(&key, column->type.key.type);
ad83bfa6 2849 } else {
8c3c2f30 2850 ovsdb_datum_to_string(datum, &column->type, out);
ad83bfa6
BP
2851 }
2852 ds_put_char(out, '\n');
ad83bfa6
BP
2853
2854 free(key_string);
2855 }
2856}
2857
9591fefe
BP
2858static void
2859parse_column_names(const char *column_names,
2860 const struct vsctl_table_class *table,
2861 const struct ovsdb_idl_column ***columnsp,
2862 size_t *n_columnsp)
2863{
2864 const struct ovsdb_idl_column **columns;
2865 size_t n_columns;
2866
2867 if (!column_names) {
2868 size_t i;
2869
2870 n_columns = table->class->n_columns + 1;
2871 columns = xmalloc(n_columns * sizeof *columns);
2872 columns[0] = NULL;
2873 for (i = 0; i < table->class->n_columns; i++) {
2874 columns[i + 1] = &table->class->columns[i];
2875 }
2876 } else {
2877 char *s = xstrdup(column_names);
2878 size_t allocated_columns;
2879 char *save_ptr = NULL;
2880 char *column_name;
2881
2882 columns = NULL;
2883 allocated_columns = n_columns = 0;
2884 for (column_name = strtok_r(s, ", ", &save_ptr); column_name;
2885 column_name = strtok_r(NULL, ", ", &save_ptr)) {
2886 const struct ovsdb_idl_column *column;
2887
2888 if (!strcasecmp(column_name, "_uuid")) {
2889 column = NULL;
2890 } else {
2891 die_if_error(get_column(table, column_name, &column));
2892 }
2893 if (n_columns >= allocated_columns) {
2894 columns = x2nrealloc(columns, &allocated_columns,
2895 sizeof *columns);
2896 }
2897 columns[n_columns++] = column;
2898 }
2899 free(s);
2900
2901 if (!n_columns) {
2902 vsctl_fatal("must specify at least one column name");
2903 }
2904 }
2905 *columnsp = columns;
2906 *n_columnsp = n_columns;
2907}
2908
2909
2910static void
2911pre_list_columns(struct vsctl_context *ctx,
2912 const struct vsctl_table_class *table,
2913 const char *column_names)
2914{
2915 const struct ovsdb_idl_column **columns;
2916 size_t n_columns;
2917 size_t i;
2918
2919 parse_column_names(column_names, table, &columns, &n_columns);
2920 for (i = 0; i < n_columns; i++) {
2921 if (columns[i]) {
2922 ovsdb_idl_add_column(ctx->idl, columns[i]);
2923 }
2924 }
2925 free(columns);
2926}
2927
e5e12280
BP
2928static void
2929pre_cmd_list(struct vsctl_context *ctx)
2930{
9591fefe 2931 const char *column_names = shash_find_data(&ctx->options, "--columns");
e5e12280
BP
2932 const char *table_name = ctx->argv[1];
2933 const struct vsctl_table_class *table;
e5e12280
BP
2934
2935 table = pre_get_table(ctx, table_name);
9591fefe 2936 pre_list_columns(ctx, table, column_names);
e5e12280
BP
2937}
2938
e051b42c
BP
2939static struct table *
2940list_make_table(const struct ovsdb_idl_column **columns, size_t n_columns)
2941{
2942 struct table *out;
2943 size_t i;
2944
2945 out = xmalloc(sizeof *out);
2946 table_init(out);
2947
2948 for (i = 0; i < n_columns; i++) {
2949 const struct ovsdb_idl_column *column = columns[i];
2950 const char *column_name = column ? column->name : "_uuid";
2951
2952 table_add_column(out, "%s", column_name);
2953 }
2954
2955 return out;
2956}
2957
ad83bfa6 2958static void
9591fefe
BP
2959list_record(const struct ovsdb_idl_row *row,
2960 const struct ovsdb_idl_column **columns, size_t n_columns,
e051b42c 2961 struct table *out)
ad83bfa6 2962{
bd76d25d 2963 size_t i;
ad83bfa6 2964
e051b42c 2965 table_add_row(out);
9591fefe
BP
2966 for (i = 0; i < n_columns; i++) {
2967 const struct ovsdb_idl_column *column = columns[i];
e051b42c 2968 struct cell *cell = table_add_cell(out);
ad83bfa6 2969
9591fefe 2970 if (!column) {
e051b42c
BP
2971 struct ovsdb_datum datum;
2972 union ovsdb_atom atom;
2973
2974 atom.uuid = row->uuid;
2975
2976 datum.keys = &atom;
2977 datum.values = NULL;
2978 datum.n = 1;
2979
2980 cell->json = ovsdb_datum_to_json(&datum, &ovsdb_type_uuid);
2981 cell->type = &ovsdb_type_uuid;
9591fefe
BP
2982 } else {
2983 const struct ovsdb_datum *datum = ovsdb_idl_read(row, column);
e051b42c
BP
2984
2985 cell->json = ovsdb_datum_to_json(datum, &column->type);
2986 cell->type = &column->type;
9591fefe 2987 }
ad83bfa6
BP
2988 }
2989}
2990
2991static void
2992cmd_list(struct vsctl_context *ctx)
2993{
9591fefe
BP
2994 const char *column_names = shash_find_data(&ctx->options, "--columns");
2995 const struct ovsdb_idl_column **columns;
ad83bfa6
BP
2996 const char *table_name = ctx->argv[1];
2997 const struct vsctl_table_class *table;
e051b42c 2998 struct table *out;
9591fefe 2999 size_t n_columns;
ad83bfa6
BP
3000 int i;
3001
3002 table = get_table(table_name);
9591fefe 3003 parse_column_names(column_names, table, &columns, &n_columns);
e051b42c 3004 out = ctx->table = list_make_table(columns, n_columns);
ad83bfa6
BP
3005 if (ctx->argc > 2) {
3006 for (i = 2; i < ctx->argc; i++) {
9591fefe
BP
3007 list_record(must_get_row(ctx, table, ctx->argv[i]),
3008 columns, n_columns, out);
ad83bfa6
BP
3009 }
3010 } else {
3011 const struct ovsdb_idl_row *row;
ad83bfa6 3012
16f4f61d
EJ
3013 for (row = ovsdb_idl_first_row(ctx->idl, table->class); row != NULL;
3014 row = ovsdb_idl_next_row(row)) {
9591fefe 3015 list_record(row, columns, n_columns, out);
ad83bfa6
BP
3016 }
3017 }
9591fefe 3018 free(columns);
ad83bfa6
BP
3019}
3020
0a140468
BP
3021static void
3022pre_cmd_find(struct vsctl_context *ctx)
3023{
3024 const char *column_names = shash_find_data(&ctx->options, "--columns");
3025 const char *table_name = ctx->argv[1];
3026 const struct vsctl_table_class *table;
3027 int i;
3028
3029 table = pre_get_table(ctx, table_name);
3030 pre_list_columns(ctx, table, column_names);
3031 for (i = 2; i < ctx->argc; i++) {
3032 pre_parse_column_key_value(ctx, ctx->argv[i], table);
3033 }
3034}
3035
3036static void
3037cmd_find(struct vsctl_context *ctx)
3038{
3039 const char *column_names = shash_find_data(&ctx->options, "--columns");
3040 const struct ovsdb_idl_column **columns;
3041 const char *table_name = ctx->argv[1];
3042 const struct vsctl_table_class *table;
3043 const struct ovsdb_idl_row *row;
e051b42c 3044 struct table *out;
0a140468
BP
3045 size_t n_columns;
3046
3047 table = get_table(table_name);
3048 parse_column_names(column_names, table, &columns, &n_columns);
e051b42c 3049 out = ctx->table = list_make_table(columns, n_columns);
0a140468
BP
3050 for (row = ovsdb_idl_first_row(ctx->idl, table->class); row;
3051 row = ovsdb_idl_next_row(row)) {
3052 int i;
3053
3054 for (i = 2; i < ctx->argc; i++) {
3055 if (!is_condition_satisfied(table, row, ctx->argv[i],
3056 ctx->symtab)) {
3057 goto next_row;
3058 }
3059 }
0a140468
BP
3060 list_record(row, columns, n_columns, out);
3061
3062 next_row: ;
3063 }
cea0c393 3064 free(columns);
0a140468
BP
3065}
3066
e5e12280
BP
3067static void
3068pre_cmd_set(struct vsctl_context *ctx)
3069{
3070 const char *table_name = ctx->argv[1];
3071 const struct vsctl_table_class *table;
3072 int i;
3073
3074 table = pre_get_table(ctx, table_name);
3075 for (i = 3; i < ctx->argc; i++) {
3076 pre_parse_column_key_value(ctx, ctx->argv[i], table);
3077 }
3078}
3079
ad83bfa6 3080static void
557e3718 3081set_column(const struct vsctl_table_class *table,
ce5a3e38
BP
3082 const struct ovsdb_idl_row *row, const char *arg,
3083 struct ovsdb_symbol_table *symtab)
ad83bfa6 3084{
bd76d25d 3085 const struct ovsdb_idl_column *column;
557e3718
BP
3086 char *key_string, *value_string;
3087 char *error;
ad83bfa6 3088
557e3718 3089 error = parse_column_key_value(arg, table, &column, &key_string,
e89e5374 3090 NULL, NULL, 0, &value_string);
557e3718 3091 die_if_error(error);
557e3718 3092 if (!value_string) {
def90f62 3093 vsctl_fatal("%s: missing value", arg);
557e3718 3094 }
ad83bfa6 3095
557e3718
BP
3096 if (key_string) {
3097 union ovsdb_atom key, value;
8c3c2f30 3098 struct ovsdb_datum datum;
557e3718 3099
bd76d25d 3100 if (column->type.value.type == OVSDB_TYPE_VOID) {
def90f62 3101 vsctl_fatal("cannot specify key to set for non-map column %s",
bd76d25d 3102 column->name);
ad83bfa6
BP
3103 }
3104
bd76d25d 3105 die_if_error(ovsdb_atom_from_string(&key, &column->type.key,
ce5a3e38 3106 key_string, symtab));
bd76d25d 3107 die_if_error(ovsdb_atom_from_string(&value, &column->type.value,
ce5a3e38 3108 value_string, symtab));
ad83bfa6 3109
8c3c2f30
BP
3110 ovsdb_datum_init_empty(&datum);
3111 ovsdb_datum_add_unsafe(&datum, &key, &value, &column->type);
ad83bfa6 3112
bd76d25d
BP
3113 ovsdb_atom_destroy(&key, column->type.key.type);
3114 ovsdb_atom_destroy(&value, column->type.value.type);
a3326252 3115
8c3c2f30
BP
3116 ovsdb_datum_union(&datum, ovsdb_idl_read(row, column),
3117 &column->type, false);
3118 ovsdb_idl_txn_write(row, column, &datum);
557e3718
BP
3119 } else {
3120 struct ovsdb_datum datum;
ad83bfa6 3121
bd76d25d 3122 die_if_error(ovsdb_datum_from_string(&datum, &column->type,
ce5a3e38 3123 value_string, symtab));
bd76d25d 3124 ovsdb_idl_txn_write(row, column, &datum);
557e3718 3125 }
ad83bfa6 3126
557e3718 3127 free(key_string);
a3326252 3128 free(value_string);
557e3718 3129}
ad83bfa6 3130
557e3718
BP
3131static void
3132cmd_set(struct vsctl_context *ctx)
3133{
557e3718
BP
3134 const char *table_name = ctx->argv[1];
3135 const char *record_id = ctx->argv[2];
3136 const struct vsctl_table_class *table;
3137 const struct ovsdb_idl_row *row;
3138 int i;
ad83bfa6 3139
557e3718 3140 table = get_table(table_name);
b7f74b6f 3141 row = must_get_row(ctx, table, record_id);
557e3718 3142 for (i = 3; i < ctx->argc; i++) {
ce5a3e38 3143 set_column(table, row, ctx->argv[i], ctx->symtab);
ad83bfa6
BP
3144 }
3145}
3146
e5e12280
BP
3147static void
3148pre_cmd_add(struct vsctl_context *ctx)
3149{
3150 const char *table_name = ctx->argv[1];
3151 const char *column_name = ctx->argv[3];
3152 const struct vsctl_table_class *table;
3153 const struct ovsdb_idl_column *column;
3154
3155 table = pre_get_table(ctx, table_name);
3156 pre_get_column(ctx, table, column_name, &column);
3157}
3158
ad83bfa6
BP
3159static void
3160cmd_add(struct vsctl_context *ctx)
3161{
3162 const char *table_name = ctx->argv[1];
3163 const char *record_id = ctx->argv[2];
3164 const char *column_name = ctx->argv[3];
3165 const struct vsctl_table_class *table;
bd76d25d 3166 const struct ovsdb_idl_column *column;
ad83bfa6
BP
3167 const struct ovsdb_idl_row *row;
3168 const struct ovsdb_type *type;
3169 struct ovsdb_datum old;
3170 int i;
3171
3172 table = get_table(table_name);
b7f74b6f 3173 row = must_get_row(ctx, table, record_id);
1bc6ff29 3174 die_if_error(get_column(table, column_name, &column));
c29a8ba8 3175
bd76d25d 3176 type = &column->type;
8c3c2f30 3177 ovsdb_datum_clone(&old, ovsdb_idl_read(row, column), &column->type);
ad83bfa6
BP
3178 for (i = 4; i < ctx->argc; i++) {
3179 struct ovsdb_type add_type;
3180 struct ovsdb_datum add;
3181
ad83bfa6
BP
3182 add_type = *type;
3183 add_type.n_min = 1;
3184 add_type.n_max = UINT_MAX;
ce5a3e38
BP
3185 die_if_error(ovsdb_datum_from_string(&add, &add_type, ctx->argv[i],
3186 ctx->symtab));
ad83bfa6
BP
3187 ovsdb_datum_union(&old, &add, type, false);
3188 ovsdb_datum_destroy(&add, type);
3189 }
3190 if (old.n > type->n_max) {
def90f62
BP
3191 vsctl_fatal("\"add\" operation would put %u %s in column %s of "
3192 "table %s but the maximum number is %u",
3193 old.n,
bd76d25d
BP
3194 type->value.type == OVSDB_TYPE_VOID ? "values" : "pairs",
3195 column->name, table->class->name, type->n_max);
ad83bfa6 3196 }
f74055e7 3197 ovsdb_idl_txn_verify(row, column);
bd76d25d 3198 ovsdb_idl_txn_write(row, column, &old);
ad83bfa6 3199}
90c4bd00 3200
e5e12280
BP
3201static void
3202pre_cmd_remove(struct vsctl_context *ctx)
3203{
3204 const char *table_name = ctx->argv[1];
3205 const char *column_name = ctx->argv[3];
3206 const struct vsctl_table_class *table;
3207 const struct ovsdb_idl_column *column;
3208
3209 table = pre_get_table(ctx, table_name);
3210 pre_get_column(ctx, table, column_name, &column);
3211}
3212
90c4bd00
BP
3213static void
3214cmd_remove(struct vsctl_context *ctx)
3215{
3216 const char *table_name = ctx->argv[1];
3217 const char *record_id = ctx->argv[2];
3218 const char *column_name = ctx->argv[3];
3219 const struct vsctl_table_class *table;
bd76d25d 3220 const struct ovsdb_idl_column *column;
90c4bd00
BP
3221 const struct ovsdb_idl_row *row;
3222 const struct ovsdb_type *type;
3223 struct ovsdb_datum old;
3224 int i;
3225
3226 table = get_table(table_name);
b7f74b6f 3227 row = must_get_row(ctx, table, record_id);
90c4bd00 3228 die_if_error(get_column(table, column_name, &column));
c29a8ba8 3229
bd76d25d 3230 type = &column->type;
8c3c2f30 3231 ovsdb_datum_clone(&old, ovsdb_idl_read(row, column), &column->type);
90c4bd00
BP
3232 for (i = 4; i < ctx->argc; i++) {
3233 struct ovsdb_type rm_type;
3234 struct ovsdb_datum rm;
3235 char *error;
3236
90c4bd00
BP
3237 rm_type = *type;
3238 rm_type.n_min = 1;
3239 rm_type.n_max = UINT_MAX;
ce5a3e38
BP
3240 error = ovsdb_datum_from_string(&rm, &rm_type,
3241 ctx->argv[i], ctx->symtab);
90c4bd00
BP
3242 if (error && ovsdb_type_is_map(&rm_type)) {
3243 free(error);
bd76d25d 3244 rm_type.value.type = OVSDB_TYPE_VOID;
ce5a3e38
BP
3245 die_if_error(ovsdb_datum_from_string(&rm, &rm_type,
3246 ctx->argv[i], ctx->symtab));
90c4bd00
BP
3247 }
3248 ovsdb_datum_subtract(&old, type, &rm, &rm_type);
3249 ovsdb_datum_destroy(&rm, &rm_type);
3250 }
3251 if (old.n < type->n_min) {
def90f62 3252 vsctl_fatal("\"remove\" operation would put %u %s in column %s of "
f19f25a4 3253 "table %s but the minimum number is %u",
def90f62 3254 old.n,
bd76d25d
BP
3255 type->value.type == OVSDB_TYPE_VOID ? "values" : "pairs",
3256 column->name, table->class->name, type->n_min);
90c4bd00 3257 }
f74055e7 3258 ovsdb_idl_txn_verify(row, column);
bd76d25d 3259 ovsdb_idl_txn_write(row, column, &old);
90c4bd00
BP
3260}
3261
e5e12280
BP
3262static void
3263pre_cmd_clear(struct vsctl_context *ctx)
3264{
3265 const char *table_name = ctx->argv[1];
3266 const struct vsctl_table_class *table;
3267 int i;
3268
3269 table = pre_get_table(ctx, table_name);
3270 for (i = 3; i < ctx->argc; i++) {
3271 const struct ovsdb_idl_column *column;
3272
3273 pre_get_column(ctx, table, ctx->argv[i], &column);
3274 }
3275}
3276
90c4bd00
BP
3277static void
3278cmd_clear(struct vsctl_context *ctx)
3279{
3280 const char *table_name = ctx->argv[1];
3281 const char *record_id = ctx->argv[2];
3282 const struct vsctl_table_class *table;
3283 const struct ovsdb_idl_row *row;
3284 int i;
3285
3286 table = get_table(table_name);
b7f74b6f 3287 row = must_get_row(ctx, table, record_id);
90c4bd00 3288 for (i = 3; i < ctx->argc; i++) {
bd76d25d 3289 const struct ovsdb_idl_column *column;
90c4bd00
BP
3290 const struct ovsdb_type *type;
3291 struct ovsdb_datum datum;
3292
3293 die_if_error(get_column(table, ctx->argv[i], &column));
3294
bd76d25d
BP
3295 type = &column->type;
3296 if (type->n_min > 0) {
def90f62
BP
3297 vsctl_fatal("\"clear\" operation cannot be applied to column %s "
3298 "of table %s, which is not allowed to be empty",
bd76d25d 3299 column->name, table->class->name);
90c4bd00
BP
3300 }
3301
3302 ovsdb_datum_init_empty(&datum);
bd76d25d 3303 ovsdb_idl_txn_write(row, column, &datum);
90c4bd00
BP
3304 }
3305}
557e3718
BP
3306
3307static void
c5f341ab 3308pre_create(struct vsctl_context *ctx)
557e3718 3309{
ce5a3e38 3310 const char *id = shash_find_data(&ctx->options, "--id");
557e3718
BP
3311 const char *table_name = ctx->argv[1];
3312 const struct vsctl_table_class *table;
c5f341ab
BP
3313
3314 table = get_table(table_name);
3315 if (!id && !table->class->is_root) {
3316 VLOG_WARN("applying \"create\" command to table %s without --id "
3317 "option will have no effect", table->class->name);
3318 }
3319}
3320
3321static void
3322cmd_create(struct vsctl_context *ctx)
3323{
3324 const char *id = shash_find_data(&ctx->options, "--id");
3325 const char *table_name = ctx->argv[1];
3326 const struct vsctl_table_class *table = get_table(table_name);
557e3718 3327 const struct ovsdb_idl_row *row;
ce5a3e38 3328 const struct uuid *uuid;
557e3718
BP
3329 int i;
3330
c5f341ab
BP
3331 if (id) {
3332 struct ovsdb_symbol *symbol = create_symbol(ctx->symtab, id, NULL);
3333 if (table->class->is_root) {
3334 /* This table is in the root set, meaning that rows created in it
3335 * won't disappear even if they are unreferenced, so disable
3336 * warnings about that by pretending that there is a reference. */
3337 symbol->strong_ref = true;
3338 }
3339 uuid = &symbol->uuid;
3340 } else {
3341 uuid = NULL;
3342 }
ce5a3e38 3343
ce5a3e38 3344 row = ovsdb_idl_txn_insert(ctx->txn, table->class, uuid);
557e3718 3345 for (i = 2; i < ctx->argc; i++) {
ce5a3e38 3346 set_column(table, row, ctx->argv[i], ctx->symtab);
557e3718 3347 }
f8ff4bc4 3348 ds_put_format(&ctx->output, UUID_FMT, UUID_ARGS(&row->uuid));
557e3718 3349}
b7f74b6f 3350
3ef917b5
BP
3351/* This function may be used as the 'postprocess' function for commands that
3352 * insert new rows into the database. It expects that the command's 'run'
3353 * function prints the UUID reported by ovsdb_idl_txn_insert() as the command's
3354 * sole output. It replaces that output by the row's permanent UUID assigned
3355 * by the database server and appends a new-line.
3356 *
3357 * Currently we use this only for "create", because the higher-level commands
3358 * are supposed to be independent of the actual structure of the vswitch
3359 * configuration. */
3360static void
3361post_create(struct vsctl_context *ctx)
3362{
3363 const struct uuid *real;
3364 struct uuid dummy;
3365
1611cf3f
BP
3366 if (!uuid_from_string(&dummy, ds_cstr(&ctx->output))) {
3367 NOT_REACHED();
3368 }
3ef917b5
BP
3369 real = ovsdb_idl_txn_get_insert_uuid(ctx->txn, &dummy);
3370 if (real) {
3371 ds_clear(&ctx->output);
3372 ds_put_format(&ctx->output, UUID_FMT, UUID_ARGS(real));
3373 }
3374 ds_put_char(&ctx->output, '\n');
3375}
3376
e5e12280
BP
3377static void
3378pre_cmd_destroy(struct vsctl_context *ctx)
3379{
3380 const char *table_name = ctx->argv[1];
3381
3382 pre_get_table(ctx, table_name);
3383}
3384
b7f74b6f
BP
3385static void
3386cmd_destroy(struct vsctl_context *ctx)
3387{
b7f74b6f
BP
3388 bool must_exist = !shash_find(&ctx->options, "--if-exists");
3389 const char *table_name = ctx->argv[1];
3390 const struct vsctl_table_class *table;
3391 int i;
3392
b7f74b6f 3393 table = get_table(table_name);
f8ff4bc4 3394 for (i = 2; i < ctx->argc; i++) {
b7f74b6f
BP
3395 const struct ovsdb_idl_row *row;
3396
3397 row = (must_exist ? must_get_row : get_row)(ctx, table, ctx->argv[i]);
3398 if (row) {
3399 ovsdb_idl_txn_delete(row);
3400 }
3401 }
3402}
7db03f7c
BP
3403
3404static bool
f158c54a
BP
3405is_condition_satisfied(const struct vsctl_table_class *table,
3406 const struct ovsdb_idl_row *row, const char *arg,
3407 struct ovsdb_symbol_table *symtab)
7db03f7c
BP
3408{
3409 static const char *operators[] = {
3410 "=", "!=", "<", ">", "<=", ">="
3411 };
3412
3413 const struct ovsdb_idl_column *column;
8c3c2f30 3414 const struct ovsdb_datum *have_datum;
7db03f7c 3415 char *key_string, *value_string;
7db03f7c
BP
3416 const char *operator;
3417 unsigned int idx;
3418 char *error;
af9af3e2 3419 int cmp = 0;
7db03f7c
BP
3420
3421 error = parse_column_key_value(arg, table, &column, &key_string,
3422 &operator, operators, ARRAY_SIZE(operators),
3423 &value_string);
3424 die_if_error(error);
3425 if (!value_string) {
3426 vsctl_fatal("%s: missing value", arg);
3427 }
3428
8c3c2f30 3429 have_datum = ovsdb_idl_read(row, column);
7db03f7c
BP
3430 if (key_string) {
3431 union ovsdb_atom want_key, want_value;
3432
3433 if (column->type.value.type == OVSDB_TYPE_VOID) {
3434 vsctl_fatal("cannot specify key to check for non-map column %s",
3435 column->name);
3436 }
3437
3438 die_if_error(ovsdb_atom_from_string(&want_key, &column->type.key,
3439 key_string, symtab));
3440 die_if_error(ovsdb_atom_from_string(&want_value, &column->type.value,
3441 value_string, symtab));
3442
8c3c2f30 3443 idx = ovsdb_datum_find_key(have_datum,
7db03f7c
BP
3444 &want_key, column->type.key.type);
3445 if (idx != UINT_MAX) {
8c3c2f30 3446 cmp = ovsdb_atom_compare_3way(&have_datum->values[idx],
7db03f7c
BP
3447 &want_value,
3448 column->type.value.type);
3449 }
3450
3451 ovsdb_atom_destroy(&want_key, column->type.key.type);
3452 ovsdb_atom_destroy(&want_value, column->type.value.type);
3453 } else {
3454 struct ovsdb_datum want_datum;
3455
3456 die_if_error(ovsdb_datum_from_string(&want_datum, &column->type,
3457 value_string, symtab));
3458 idx = 0;
8c3c2f30 3459 cmp = ovsdb_datum_compare_3way(have_datum, &want_datum,
7db03f7c
BP
3460 &column->type);
3461 ovsdb_datum_destroy(&want_datum, &column->type);
3462 }
7db03f7c
BP
3463
3464 free(key_string);
3465 free(value_string);
3466
3467 return (idx == UINT_MAX ? false
3468 : !strcmp(operator, "=") ? cmp == 0
3469 : !strcmp(operator, "!=") ? cmp != 0
3470 : !strcmp(operator, "<") ? cmp < 0
3471 : !strcmp(operator, ">") ? cmp > 0
3472 : !strcmp(operator, "<=") ? cmp <= 0
3473 : !strcmp(operator, ">=") ? cmp >= 0
3474 : (abort(), 0));
3475}
3476
e5e12280
BP
3477static void
3478pre_cmd_wait_until(struct vsctl_context *ctx)
3479{
3480 const char *table_name = ctx->argv[1];
3481 const struct vsctl_table_class *table;
3482 int i;
3483
3484 table = pre_get_table(ctx, table_name);
3485
3486 for (i = 3; i < ctx->argc; i++) {
3487 pre_parse_column_key_value(ctx, ctx->argv[i], table);
3488 }
3489}
3490
7db03f7c
BP
3491static void
3492cmd_wait_until(struct vsctl_context *ctx)
3493{
3494 const char *table_name = ctx->argv[1];
3495 const char *record_id = ctx->argv[2];
3496 const struct vsctl_table_class *table;
3497 const struct ovsdb_idl_row *row;
3498 int i;
3499
3500 table = get_table(table_name);
3501
e111e681 3502 row = get_row(ctx, table, record_id);
7db03f7c
BP
3503 if (!row) {
3504 ctx->try_again = true;
3505 return;
3506 }
3507
3508 for (i = 3; i < ctx->argc; i++) {
f158c54a 3509 if (!is_condition_satisfied(table, row, ctx->argv[i], ctx->symtab)) {
7db03f7c
BP
3510 ctx->try_again = true;
3511 return;
3512 }
3513 }
3514}
ad83bfa6 3515\f
b54e22e9
BP
3516static struct json *
3517where_uuid_equals(const struct uuid *uuid)
3518{
3519 return
3520 json_array_create_1(
3521 json_array_create_3(
3522 json_string_create("_uuid"),
3523 json_string_create("=="),
3524 json_array_create_2(
3525 json_string_create("uuid"),
3526 json_string_create_nocopy(
3527 xasprintf(UUID_FMT, UUID_ARGS(uuid))))));
3528}
3529
c75d1511 3530static void
f8ff4bc4
BP
3531vsctl_context_init(struct vsctl_context *ctx, struct vsctl_command *command,
3532 struct ovsdb_idl *idl, struct ovsdb_idl_txn *txn,
ce5a3e38 3533 const struct ovsrec_open_vswitch *ovs,
e5e12280 3534 struct ovsdb_symbol_table *symtab)
f8ff4bc4
BP
3535{
3536 ctx->argc = command->argc;
3537 ctx->argv = command->argv;
3538 ctx->options = command->options;
3539
3540 ds_swap(&ctx->output, &command->output);
e051b42c 3541 ctx->table = command->table;
f8ff4bc4
BP
3542 ctx->idl = idl;
3543 ctx->txn = txn;
3544 ctx->ovs = ovs;
ce5a3e38 3545 ctx->symtab = symtab;
f74055e7 3546 ctx->verified_ports = false;
87b23a01
BP
3547
3548 ctx->try_again = false;
f8ff4bc4
BP
3549}
3550
3551static void
3552vsctl_context_done(struct vsctl_context *ctx, struct vsctl_command *command)
3553{
3554 ds_swap(&ctx->output, &command->output);
e051b42c 3555 command->table = ctx->table;
f8ff4bc4
BP
3556}
3557
e5e12280
BP
3558static void
3559run_prerequisites(struct vsctl_command *commands, size_t n_commands,
3560 struct ovsdb_idl *idl)
3561{
3562 struct vsctl_command *c;
3563
3564 ovsdb_idl_add_table(idl, &ovsrec_table_open_vswitch);
b8fa7102
BP
3565 if (wait_for_reload) {
3566 ovsdb_idl_add_column(idl, &ovsrec_open_vswitch_col_cur_cfg);
3567 }
e5e12280
BP
3568 for (c = commands; c < &commands[n_commands]; c++) {
3569 if (c->syntax->prerequisites) {
3570 struct vsctl_context ctx;
3571
3572 ds_init(&c->output);
e051b42c 3573 c->table = NULL;
e5e12280
BP
3574
3575 vsctl_context_init(&ctx, c, idl, NULL, NULL, NULL);
3576 (c->syntax->prerequisites)(&ctx);
3577 vsctl_context_done(&ctx, c);
3578
3579 assert(!c->output.string);
e051b42c 3580 assert(!c->table);
e5e12280
BP
3581 }
3582 }
3583}
3584
4fdfe5cc 3585static enum ovsdb_idl_txn_status
f8ff4bc4
BP
3586do_vsctl(const char *args, struct vsctl_command *commands, size_t n_commands,
3587 struct ovsdb_idl *idl)
c75d1511
BP
3588{
3589 struct ovsdb_idl_txn *txn;
3590 const struct ovsrec_open_vswitch *ovs;
3591 enum ovsdb_idl_txn_status status;
ce5a3e38 3592 struct ovsdb_symbol_table *symtab;
f8ff4bc4 3593 struct vsctl_command *c;
0dc66db9 3594 struct shash_node *node;
84a0ee89 3595 int64_t next_cfg = 0;
af9af3e2 3596 char *error = NULL;
c75d1511 3597
1d48b4be 3598 txn = the_idl_txn = ovsdb_idl_txn_create(idl);
577aebdf
BP
3599 if (dry_run) {
3600 ovsdb_idl_txn_set_dry_run(txn);
3601 }
524555d1 3602
e1c0e2d1 3603 ovsdb_idl_txn_add_comment(txn, "ovs-vsctl: %s", args);
d171b584 3604
c75d1511
BP
3605 ovs = ovsrec_open_vswitch_first(idl);
3606 if (!ovs) {
524555d1
BP
3607 /* XXX add verification that table is empty */
3608 ovs = ovsrec_open_vswitch_insert(txn);
c75d1511
BP
3609 }
3610
b54e22e9
BP
3611 if (wait_for_reload) {
3612 struct json *where = where_uuid_equals(&ovs->header_.uuid);
ad83bfa6 3613 ovsdb_idl_txn_increment(txn, "Open_vSwitch", "next_cfg", where);
b54e22e9
BP
3614 json_destroy(where);
3615 }
3616
ce5a3e38 3617 symtab = ovsdb_symbol_table_create();
87b23a01
BP
3618 for (c = commands; c < &commands[n_commands]; c++) {
3619 ds_init(&c->output);
e051b42c 3620 c->table = NULL;
87b23a01 3621 }
f8ff4bc4
BP
3622 for (c = commands; c < &commands[n_commands]; c++) {
3623 struct vsctl_context ctx;
3624
ce5a3e38 3625 vsctl_context_init(&ctx, c, idl, txn, ovs, symtab);
ffd66ea9
BP
3626 if (c->syntax->run) {
3627 (c->syntax->run)(&ctx);
3628 }
f8ff4bc4 3629 vsctl_context_done(&ctx, c);
87b23a01
BP
3630
3631 if (ctx.try_again) {
4fdfe5cc 3632 status = TXN_AGAIN_WAIT;
87b23a01
BP
3633 goto try_again;
3634 }
c75d1511 3635 }
c75d1511 3636
0dc66db9
BP
3637 SHASH_FOR_EACH (node, &symtab->sh) {
3638 struct ovsdb_symbol *symbol = node->data;
3639 if (!symbol->created) {
3640 vsctl_fatal("row id \"%s\" is referenced but never created (e.g. "
3641 "with \"-- --id=%s create ...\")",
3642 node->name, node->name);
3643 }
c5f341ab
BP
3644 if (!symbol->strong_ref) {
3645 if (!symbol->weak_ref) {
3646 VLOG_WARN("row id \"%s\" was created but no reference to it "
3647 "was inserted, so it will not actually appear in "
3648 "the database", node->name);
3649 } else {
3650 VLOG_WARN("row id \"%s\" was created but only a weak "
3651 "reference to it was inserted, so it will not "
3652 "actually appear in the database", node->name);
3653 }
3654 }
28a3b753
BP
3655 }
3656
af96ccd2 3657 status = ovsdb_idl_txn_commit_block(txn);
b54e22e9
BP
3658 if (wait_for_reload && status == TXN_SUCCESS) {
3659 next_cfg = ovsdb_idl_txn_get_increment_new_value(txn);
3660 }
8d49c47a
BP
3661 if (status == TXN_UNCHANGED || status == TXN_SUCCESS) {
3662 for (c = commands; c < &commands[n_commands]; c++) {
3663 if (c->syntax->postprocess) {
3664 struct vsctl_context ctx;
3665
ce5a3e38 3666 vsctl_context_init(&ctx, c, idl, txn, ovs, symtab);
8d49c47a
BP
3667 (c->syntax->postprocess)(&ctx);
3668 vsctl_context_done(&ctx, c);
3669 }
3da1c516
BP
3670 }
3671 }
91e310a5 3672 error = xstrdup(ovsdb_idl_txn_get_error(txn));
c75d1511 3673 ovsdb_idl_txn_destroy(txn);
b7b6e2c4 3674 txn = the_idl_txn = NULL;
c75d1511
BP
3675
3676 switch (status) {
2096903b 3677 case TXN_UNCOMMITTED:
c75d1511
BP
3678 case TXN_INCOMPLETE:
3679 NOT_REACHED();
3680
3681 case TXN_ABORTED:
3682 /* Should not happen--we never call ovsdb_idl_txn_abort(). */
c88b6a27 3683 vsctl_fatal("transaction aborted");
c75d1511 3684
b54e22e9 3685 case TXN_UNCHANGED:
c75d1511
BP
3686 case TXN_SUCCESS:
3687 break;
3688
4fdfe5cc
BP
3689 case TXN_AGAIN_WAIT:
3690 case TXN_AGAIN_NOW:
87b23a01 3691 goto try_again;
c75d1511
BP
3692
3693 case TXN_ERROR:
91e310a5 3694 vsctl_fatal("transaction error: %s", error);
c75d1511 3695
06b6d651
BP
3696 case TXN_NOT_LOCKED:
3697 /* Should not happen--we never call ovsdb_idl_set_lock(). */
3698 vsctl_fatal("database not locked");
3699
c75d1511
BP
3700 default:
3701 NOT_REACHED();
3702 }
91e310a5 3703 free(error);
c75d1511 3704
87b23a01
BP
3705 ovsdb_symbol_table_destroy(symtab);
3706
f8ff4bc4
BP
3707 for (c = commands; c < &commands[n_commands]; c++) {
3708 struct ds *ds = &c->output;
ce5a3e38 3709
e051b42c
BP
3710 if (c->table) {
3711 table_print(c->table, &table_style);
3712 } else if (oneline) {
c75d1511
BP
3713 size_t j;
3714
3715 ds_chomp(ds, '\n');
3716 for (j = 0; j < ds->length; j++) {
2a022368
BP
3717 int ch = ds->string[j];
3718 switch (ch) {
c75d1511
BP
3719 case '\n':
3720 fputs("\\n", stdout);
3721 break;
3722
3723 case '\\':
3724 fputs("\\\\", stdout);
3725 break;
3726
3727 default:
2a022368 3728 putchar(ch);
c75d1511
BP
3729 }
3730 }
3731 putchar('\n');
3732 } else {
3733 fputs(ds_cstr(ds), stdout);
3734 }
b86b43aa 3735 ds_destroy(&c->output);
e051b42c
BP
3736 table_destroy(c->table);
3737 free(c->table);
ce5a3e38 3738
c56d226f 3739 smap_destroy(&c->options);
c75d1511 3740 }
b86b43aa 3741 free(commands);
b54e22e9
BP
3742
3743 if (wait_for_reload && status != TXN_UNCHANGED) {
3744 for (;;) {
b54e22e9
BP
3745 ovsdb_idl_run(idl);
3746 OVSREC_OPEN_VSWITCH_FOR_EACH (ovs, idl) {
3747 if (ovs->cur_cfg >= next_cfg) {
3748 goto done;
3749 }
3750 }
3751 ovsdb_idl_wait(idl);
3752 poll_block();
3753 }
3754 done: ;
3755 }
b86b43aa 3756 ovsdb_idl_destroy(idl);
b54e22e9 3757
c75d1511 3758 exit(EXIT_SUCCESS);
87b23a01
BP
3759
3760try_again:
3761 /* Our transaction needs to be rerun, or a prerequisite was not met. Free
3762 * resources and return so that the caller can try again. */
b7b6e2c4
JP
3763 if (txn) {
3764 ovsdb_idl_txn_abort(txn);
3765 ovsdb_idl_txn_destroy(txn);
3766 }
87b23a01
BP
3767 ovsdb_symbol_table_destroy(symtab);
3768 for (c = commands; c < &commands[n_commands]; c++) {
3769 ds_destroy(&c->output);
e051b42c
BP
3770 table_destroy(c->table);
3771 free(c->table);
87b23a01
BP
3772 }
3773 free(error);
4fdfe5cc
BP
3774
3775 return status;
c75d1511
BP
3776}
3777
f8ff4bc4
BP
3778static const struct vsctl_command_syntax all_commands[] = {
3779 /* Open vSwitch commands. */
e5e12280 3780 {"init", 0, 0, NULL, cmd_init, NULL, "", RW},
9b1735a7 3781 {"show", 0, 0, pre_cmd_show, cmd_show, NULL, "", RO},
f8ff4bc4
BP
3782
3783 /* Bridge commands. */
e5e12280
BP
3784 {"add-br", 1, 3, pre_get_info, cmd_add_br, NULL, "--may-exist", RW},
3785 {"del-br", 1, 1, pre_get_info, cmd_del_br, NULL, "--if-exists", RW},
3786 {"list-br", 0, 0, pre_get_info, cmd_list_br, NULL, "", RO},
3787 {"br-exists", 1, 1, pre_get_info, cmd_br_exists, NULL, "", RO},
3788 {"br-to-vlan", 1, 1, pre_get_info, cmd_br_to_vlan, NULL, "", RO},
3789 {"br-to-parent", 1, 1, pre_get_info, cmd_br_to_parent, NULL, "", RO},
fbd8715e
BP
3790 {"br-set-external-id", 2, 3, pre_cmd_br_set_external_id,
3791 cmd_br_set_external_id, NULL, "", RW},
e5e12280
BP
3792 {"br-get-external-id", 1, 2, pre_cmd_br_get_external_id,
3793 cmd_br_get_external_id, NULL, "", RO},
f8ff4bc4
BP
3794
3795 /* Port commands. */
e5e12280
BP
3796 {"list-ports", 1, 1, pre_get_info, cmd_list_ports, NULL, "", RO},
3797 {"add-port", 2, INT_MAX, pre_get_info, cmd_add_port, NULL, "--may-exist",
3798 RW},
3799 {"add-bond", 4, INT_MAX, pre_get_info, cmd_add_bond, NULL,
3800 "--may-exist,--fake-iface", RW},
3801 {"del-port", 1, 2, pre_get_info, cmd_del_port, NULL,
3802 "--if-exists,--with-iface", RW},
3803 {"port-to-br", 1, 1, pre_get_info, cmd_port_to_br, NULL, "", RO},
f8ff4bc4
BP
3804
3805 /* Interface commands. */
e5e12280
BP
3806 {"list-ifaces", 1, 1, pre_get_info, cmd_list_ifaces, NULL, "", RO},
3807 {"iface-to-br", 1, 1, pre_get_info, cmd_iface_to_br, NULL, "", RO},
f8ff4bc4
BP
3808
3809 /* Controller commands. */
4e3e7ff9
BP
3810 {"get-controller", 1, 1, pre_controller, cmd_get_controller, NULL, "", RO},
3811 {"del-controller", 1, 1, pre_controller, cmd_del_controller, NULL, "", RW},
3812 {"set-controller", 1, INT_MAX, pre_controller, cmd_set_controller, NULL,
3813 "", RW},
e5e12280
BP
3814 {"get-fail-mode", 1, 1, pre_get_info, cmd_get_fail_mode, NULL, "", RO},
3815 {"del-fail-mode", 1, 1, pre_get_info, cmd_del_fail_mode, NULL, "", RW},
3816 {"set-fail-mode", 2, 2, pre_get_info, cmd_set_fail_mode, NULL, "", RW},
f8ff4bc4 3817
24b8b259
AE
3818 /* Manager commands. */
3819 {"get-manager", 0, 0, pre_manager, cmd_get_manager, NULL, "", RO},
3820 {"del-manager", 0, INT_MAX, pre_manager, cmd_del_manager, NULL, "", RW},
3821 {"set-manager", 1, INT_MAX, pre_manager, cmd_set_manager, NULL, "", RW},
3822
f8ff4bc4 3823 /* SSL commands. */
e5e12280
BP
3824 {"get-ssl", 0, 0, pre_cmd_get_ssl, cmd_get_ssl, NULL, "", RO},
3825 {"del-ssl", 0, 0, pre_cmd_del_ssl, cmd_del_ssl, NULL, "", RW},
3826 {"set-ssl", 3, 3, pre_cmd_set_ssl, cmd_set_ssl, NULL, "--bootstrap", RW},
f8ff4bc4 3827
18ee958b 3828 /* Switch commands. */
e5e12280 3829 {"emer-reset", 0, 0, pre_cmd_emer_reset, cmd_emer_reset, NULL, "", RW},
18ee958b 3830
ffd66ea9
BP
3831 /* Database commands. */
3832 {"comment", 0, INT_MAX, NULL, NULL, NULL, "", RO},
e5e12280 3833 {"get", 2, INT_MAX, pre_cmd_get, cmd_get, NULL, "--if-exists,--id=", RO},
9591fefe 3834 {"list", 1, INT_MAX, pre_cmd_list, cmd_list, NULL, "--columns=", RO},
0a140468 3835 {"find", 1, INT_MAX, pre_cmd_find, cmd_find, NULL, "--columns=", RO},
e5e12280
BP
3836 {"set", 3, INT_MAX, pre_cmd_set, cmd_set, NULL, "", RW},
3837 {"add", 4, INT_MAX, pre_cmd_add, cmd_add, NULL, "", RW},
3838 {"remove", 4, INT_MAX, pre_cmd_remove, cmd_remove, NULL, "", RW},
3839 {"clear", 3, INT_MAX, pre_cmd_clear, cmd_clear, NULL, "", RW},
c5f341ab 3840 {"create", 2, INT_MAX, pre_create, cmd_create, post_create, "--id=", RW},
e5e12280
BP
3841 {"destroy", 1, INT_MAX, pre_cmd_destroy, cmd_destroy, NULL, "--if-exists",
3842 RW},
3843 {"wait-until", 2, INT_MAX, pre_cmd_wait_until, cmd_wait_until, NULL, "",
3844 RO},
3845
3846 {NULL, 0, 0, NULL, NULL, NULL, NULL, RO},
f8ff4bc4 3847};
5d9cb63c 3848