]> git.proxmox.com Git - mirror_ovs.git/blob - ovn/utilities/ovn-sbctl.c
ovn: Add lflow-list to ovn-sbctl.
[mirror_ovs.git] / ovn / utilities / ovn-sbctl.c
1 /*
2 * Copyright (c) 2015 Nicira, Inc.
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 <ctype.h>
20 #include <errno.h>
21 #include <float.h>
22 #include <getopt.h>
23 #include <inttypes.h>
24 #include <signal.h>
25 #include <stdarg.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <unistd.h>
29
30 #include "db-ctl-base.h"
31
32 #include "command-line.h"
33 #include "compiler.h"
34 #include "dynamic-string.h"
35 #include "fatal-signal.h"
36 #include "json.h"
37 #include "ovsdb-data.h"
38 #include "ovsdb-idl.h"
39 #include "poll-loop.h"
40 #include "process.h"
41 #include "sset.h"
42 #include "shash.h"
43 #include "table.h"
44 #include "timeval.h"
45 #include "util.h"
46 #include "openvswitch/vlog.h"
47 #include "ovn/lib/ovn-sb-idl.h"
48
49 VLOG_DEFINE_THIS_MODULE(sbctl);
50
51 struct sbctl_context;
52
53 /* --db: The database server to contact. */
54 static const char *db;
55
56 /* --oneline: Write each command's output as a single line? */
57 static bool oneline;
58
59 /* --dry-run: Do not commit any changes. */
60 static bool dry_run;
61
62 /* --timeout: Time to wait for a connection to 'db'. */
63 static int timeout;
64
65 /* Format for table output. */
66 static struct table_style table_style = TABLE_STYLE_DEFAULT;
67
68 /* The IDL we're using and the current transaction, if any.
69 * This is for use by sbctl_exit() only, to allow it to clean up.
70 * Other code should use its context arguments. */
71 static struct ovsdb_idl *the_idl;
72 static struct ovsdb_idl_txn *the_idl_txn;
73 OVS_NO_RETURN static void sbctl_exit(int status);
74
75 static void sbctl_cmd_init(void);
76 OVS_NO_RETURN static void usage(void);
77 static void parse_options(int argc, char *argv[], struct shash *local_options);
78 static void run_prerequisites(struct ctl_command[], size_t n_commands,
79 struct ovsdb_idl *);
80 static void do_sbctl(const char *args, struct ctl_command *, size_t n,
81 struct ovsdb_idl *);
82
83 int
84 main(int argc, char *argv[])
85 {
86 extern struct vlog_module VLM_reconnect;
87 struct ovsdb_idl *idl;
88 struct ctl_command *commands;
89 struct shash local_options;
90 unsigned int seqno;
91 size_t n_commands;
92 char *args;
93
94 set_program_name(argv[0]);
95 fatal_ignore_sigpipe();
96 vlog_set_levels(NULL, VLF_CONSOLE, VLL_WARN);
97 vlog_set_levels(&VLM_reconnect, VLF_ANY_DESTINATION, VLL_WARN);
98 sbrec_init();
99
100 sbctl_cmd_init();
101
102 /* Log our arguments. This is often valuable for debugging systems. */
103 args = process_escape_args(argv);
104 VLOG(ctl_might_write_to_db(argv) ? VLL_INFO : VLL_DBG, "Called as %s", args);
105
106 /* Parse command line. */
107 shash_init(&local_options);
108 parse_options(argc, argv, &local_options);
109 commands = ctl_parse_commands(argc - optind, argv + optind, &local_options,
110 &n_commands);
111
112 if (timeout) {
113 time_alarm(timeout);
114 }
115
116 /* Initialize IDL. */
117 idl = the_idl = ovsdb_idl_create(db, &sbrec_idl_class, false, false);
118 run_prerequisites(commands, n_commands, idl);
119
120 /* Execute the commands.
121 *
122 * 'seqno' is the database sequence number for which we last tried to
123 * execute our transaction. There's no point in trying to commit more than
124 * once for any given sequence number, because if the transaction fails
125 * it's because the database changed and we need to obtain an up-to-date
126 * view of the database before we try the transaction again. */
127 seqno = ovsdb_idl_get_seqno(idl);
128 for (;;) {
129 ovsdb_idl_run(idl);
130 if (!ovsdb_idl_is_alive(idl)) {
131 int retval = ovsdb_idl_get_last_error(idl);
132 ctl_fatal("%s: database connection failed (%s)",
133 db, ovs_retval_to_string(retval));
134 }
135
136 if (seqno != ovsdb_idl_get_seqno(idl)) {
137 seqno = ovsdb_idl_get_seqno(idl);
138 do_sbctl(args, commands, n_commands, idl);
139 }
140
141 if (seqno == ovsdb_idl_get_seqno(idl)) {
142 ovsdb_idl_wait(idl);
143 poll_block();
144 }
145 }
146 }
147
148 static void
149 parse_options(int argc, char *argv[], struct shash *local_options)
150 {
151 enum {
152 OPT_DB = UCHAR_MAX + 1,
153 OPT_ONELINE,
154 OPT_NO_SYSLOG,
155 OPT_DRY_RUN,
156 OPT_PEER_CA_CERT,
157 OPT_LOCAL,
158 OPT_COMMANDS,
159 OPT_OPTIONS,
160 VLOG_OPTION_ENUMS,
161 TABLE_OPTION_ENUMS
162 };
163 static const struct option global_long_options[] = {
164 {"db", required_argument, NULL, OPT_DB},
165 {"no-syslog", no_argument, NULL, OPT_NO_SYSLOG},
166 {"dry-run", no_argument, NULL, OPT_DRY_RUN},
167 {"oneline", no_argument, NULL, OPT_ONELINE},
168 {"timeout", required_argument, NULL, 't'},
169 {"help", no_argument, NULL, 'h'},
170 {"commands", no_argument, NULL, OPT_COMMANDS},
171 {"options", no_argument, NULL, OPT_OPTIONS},
172 {"version", no_argument, NULL, 'V'},
173 VLOG_LONG_OPTIONS,
174 TABLE_LONG_OPTIONS,
175 {NULL, 0, NULL, 0},
176 };
177 const int n_global_long_options = ARRAY_SIZE(global_long_options) - 1;
178 char *tmp, *short_options;
179
180 struct option *options;
181 size_t allocated_options;
182 size_t n_options;
183 size_t i;
184
185 tmp = ovs_cmdl_long_options_to_short_options(global_long_options);
186 short_options = xasprintf("+%s", tmp);
187 free(tmp);
188
189 /* We want to parse both global and command-specific options here, but
190 * getopt_long() isn't too convenient for the job. We copy our global
191 * options into a dynamic array, then append all of the command-specific
192 * options. */
193 options = xmemdup(global_long_options, sizeof global_long_options);
194 allocated_options = ARRAY_SIZE(global_long_options);
195 n_options = n_global_long_options;
196 ctl_add_cmd_options(&options, &n_options, &allocated_options, OPT_LOCAL);
197 table_style.format = TF_LIST;
198
199 for (;;) {
200 int idx;
201 int c;
202
203 c = getopt_long(argc, argv, short_options, options, &idx);
204 if (c == -1) {
205 break;
206 }
207
208 switch (c) {
209 case OPT_DB:
210 db = optarg;
211 break;
212
213 case OPT_ONELINE:
214 oneline = true;
215 break;
216
217 case OPT_NO_SYSLOG:
218 vlog_set_levels(&VLM_sbctl, VLF_SYSLOG, VLL_WARN);
219 break;
220
221 case OPT_DRY_RUN:
222 dry_run = true;
223 break;
224
225 case OPT_LOCAL:
226 if (shash_find(local_options, options[idx].name)) {
227 ctl_fatal("'%s' option specified multiple times",
228 options[idx].name);
229 }
230 shash_add_nocopy(local_options,
231 xasprintf("--%s", options[idx].name),
232 optarg ? xstrdup(optarg) : NULL);
233 break;
234
235 case 'h':
236 usage();
237
238 case OPT_COMMANDS:
239 ctl_print_commands();
240
241 case OPT_OPTIONS:
242 ctl_print_options(global_long_options);
243
244 case 'V':
245 ovs_print_version(0, 0);
246 printf("DB Schema %s\n", sbrec_get_db_version());
247 exit(EXIT_SUCCESS);
248
249 case 't':
250 timeout = strtoul(optarg, NULL, 10);
251 if (timeout < 0) {
252 ctl_fatal("value %s on -t or --timeout is invalid",
253 optarg);
254 }
255 break;
256
257 VLOG_OPTION_HANDLERS
258 TABLE_OPTION_HANDLERS(&table_style)
259
260 case '?':
261 exit(EXIT_FAILURE);
262
263 default:
264 abort();
265 }
266 }
267 free(short_options);
268
269 if (!db) {
270 db = ctl_default_db();
271 }
272
273 for (i = n_global_long_options; options[i].name; i++) {
274 free(CONST_CAST(char *, options[i].name));
275 }
276 free(options);
277 }
278
279 static void
280 usage(void)
281 {
282 printf("\
283 %s: ovs-vswitchd management utility\n\
284 \n\
285 for debugging and testing only, never use it in production\n\
286 \n\
287 usage: %s [OPTIONS] COMMAND [ARG...]\n\
288 \n\
289 SouthBound DB commands:\n\
290 show print overview of database contents\n\
291 \n\
292 Chassis commands:\n\
293 chassis-add CHASSIS ENCAP-TYPE ENCAP-IP create a new chassis named\n\
294 CHASSIS with one encapsulation\n\
295 entry of ENCAP-TYPE and ENCAP-IP\n\
296 chassis-del CHASSIS delete CHASSIS and all of its encaps,\n\
297 and gateway_ports\n\
298 \n\
299 Port binding commands:\n\
300 lport-bind LPORT CHASSIS bind logical port LPORT to CHASSIS\n\
301 lport-unbind LPORT reset the port binding of logical port LPORT\n\
302 \n\
303 Logical flow commands:\n\
304 lflow-list [DATAPATH] List logical flows for all or a single datapath\n\
305 dump-flows [DATAPATH] Alias for lflow-list\n\
306 \n\
307 %s\
308 \n\
309 Options:\n\
310 --db=DATABASE connect to DATABASE\n\
311 (default: %s)\n\
312 -t, --timeout=SECS wait at most SECS seconds for ovs-vswitchd\n\
313 --dry-run do not commit changes to database\n\
314 --oneline print exactly one line of output per command\n",
315 program_name, program_name, ctl_get_db_cmd_usage(), ctl_default_db());
316 vlog_usage();
317 printf("\
318 --no-syslog equivalent to --verbose=sbctl:syslog:warn\n");
319 printf("\n\
320 Other options:\n\
321 -h, --help display this help message\n\
322 -V, --version display version information\n");
323 exit(EXIT_SUCCESS);
324 }
325
326 \f
327 /* ovs-sbctl specific context. Inherits the 'struct ctl_context' as base. */
328 struct sbctl_context {
329 struct ctl_context base;
330
331 /* A cache of the contents of the database.
332 *
333 * A command that needs to use any of this information must first call
334 * sbctl_context_populate_cache(). A command that changes anything that
335 * could invalidate the cache must either call
336 * sbctl_context_invalidate_cache() or manually update the cache to
337 * maintain its correctness. */
338 bool cache_valid;
339 /* Maps from chassis name to struct sbctl_chassis. */
340 struct shash chassis;
341 /* Maps from lport name to struct sbctl_port_binding. */
342 struct shash port_bindings;
343 };
344
345 /* Casts 'base' into 'strcut sbctl_context'. */
346 static struct sbctl_context *
347 sbctl_context_cast(struct ctl_context *base)
348 {
349 return CONTAINER_OF(base, struct sbctl_context, base);
350 }
351
352 struct sbctl_chassis {
353 const struct sbrec_chassis *ch_cfg;
354 };
355
356 struct sbctl_port_binding {
357 const struct sbrec_port_binding *bd_cfg;
358 };
359
360 static void
361 sbctl_context_invalidate_cache(struct ctl_context *ctx)
362 {
363 struct sbctl_context *sbctl_ctx = sbctl_context_cast(ctx);
364
365 if (!sbctl_ctx->cache_valid) {
366 return;
367 }
368 sbctl_ctx->cache_valid = false;
369 shash_destroy_free_data(&sbctl_ctx->chassis);
370 shash_destroy_free_data(&sbctl_ctx->port_bindings);
371 }
372
373 static void
374 sbctl_context_populate_cache(struct ctl_context *ctx)
375 {
376 struct sbctl_context *sbctl_ctx = sbctl_context_cast(ctx);
377 const struct sbrec_chassis *chassis_rec;
378 const struct sbrec_port_binding *port_binding_rec;
379 struct sset chassis, port_bindings;
380
381 if (sbctl_ctx->cache_valid) {
382 /* Cache is already populated. */
383 return;
384 }
385 sbctl_ctx->cache_valid = true;
386 shash_init(&sbctl_ctx->chassis);
387 shash_init(&sbctl_ctx->port_bindings);
388 sset_init(&chassis);
389 SBREC_CHASSIS_FOR_EACH(chassis_rec, ctx->idl) {
390 struct sbctl_chassis *ch;
391
392 if (!sset_add(&chassis, chassis_rec->name)) {
393 VLOG_WARN("database contains duplicate chassis name (%s)",
394 chassis_rec->name);
395 continue;
396 }
397
398 ch = xmalloc(sizeof *ch);
399 ch->ch_cfg = chassis_rec;
400 shash_add(&sbctl_ctx->chassis, chassis_rec->name, ch);
401 }
402 sset_destroy(&chassis);
403
404 sset_init(&port_bindings);
405 SBREC_PORT_BINDING_FOR_EACH(port_binding_rec, ctx->idl) {
406 struct sbctl_port_binding *bd;
407
408 if (!sset_add(&port_bindings, port_binding_rec->logical_port)) {
409 VLOG_WARN("database contains duplicate port binding for logical "
410 "port (%s)",
411 port_binding_rec->logical_port);
412 continue;
413 }
414
415 bd = xmalloc(sizeof *bd);
416 bd->bd_cfg = port_binding_rec;
417 shash_add(&sbctl_ctx->port_bindings, port_binding_rec->logical_port,
418 bd);
419 }
420 sset_destroy(&port_bindings);
421 }
422
423 static void
424 check_conflicts(struct sbctl_context *sbctl_ctx, const char *name,
425 char *msg)
426 {
427 if (shash_find(&sbctl_ctx->chassis, name)) {
428 ctl_fatal("%s because a chassis named %s already exists",
429 msg, name);
430 }
431 free(msg);
432 }
433
434 static struct sbctl_chassis *
435 find_chassis(struct sbctl_context *sbctl_ctx, const char *name,
436 bool must_exist)
437 {
438 struct sbctl_chassis *sbctl_ch;
439
440 ovs_assert(sbctl_ctx->cache_valid);
441
442 sbctl_ch = shash_find_data(&sbctl_ctx->chassis, name);
443 if (must_exist && !sbctl_ch) {
444 ctl_fatal("no chassis named %s", name);
445 }
446
447 return sbctl_ch;
448 }
449
450 static struct sbctl_port_binding *
451 find_port_binding(struct sbctl_context *sbctl_ctx, const char *name,
452 bool must_exist)
453 {
454 struct sbctl_port_binding *bd;
455
456 ovs_assert(sbctl_ctx->cache_valid);
457
458 bd = shash_find_data(&sbctl_ctx->port_bindings, name);
459 if (must_exist && !bd) {
460 ctl_fatal("no port named %s", name);
461 }
462
463 return bd;
464 }
465
466 static void
467 pre_get_info(struct ctl_context *ctx)
468 {
469 ovsdb_idl_add_column(ctx->idl, &sbrec_chassis_col_name);
470 ovsdb_idl_add_column(ctx->idl, &sbrec_chassis_col_encaps);
471
472 ovsdb_idl_add_column(ctx->idl, &sbrec_encap_col_type);
473 ovsdb_idl_add_column(ctx->idl, &sbrec_encap_col_ip);
474
475 ovsdb_idl_add_column(ctx->idl, &sbrec_port_binding_col_logical_port);
476 ovsdb_idl_add_column(ctx->idl, &sbrec_port_binding_col_chassis);
477
478 ovsdb_idl_add_column(ctx->idl, &sbrec_logical_flow_col_logical_datapath);
479 ovsdb_idl_add_column(ctx->idl, &sbrec_logical_flow_col_pipeline);
480 ovsdb_idl_add_column(ctx->idl, &sbrec_logical_flow_col_actions);
481 ovsdb_idl_add_column(ctx->idl, &sbrec_logical_flow_col_priority);
482 ovsdb_idl_add_column(ctx->idl, &sbrec_logical_flow_col_table_id);
483 ovsdb_idl_add_column(ctx->idl, &sbrec_logical_flow_col_match);
484 }
485
486 static struct cmd_show_table cmd_show_tables[] = {
487 {&sbrec_table_chassis,
488 &sbrec_chassis_col_name,
489 {&sbrec_chassis_col_encaps,
490 NULL,
491 NULL}},
492
493 {&sbrec_table_encap,
494 &sbrec_encap_col_type,
495 {&sbrec_encap_col_ip,
496 &sbrec_encap_col_options,
497 NULL}},
498
499 {NULL, NULL, {NULL, NULL, NULL}},
500 };
501
502 static void
503 cmd_chassis_add(struct ctl_context *ctx)
504 {
505 struct sbctl_context *sbctl_ctx = sbctl_context_cast(ctx);
506 struct sbrec_chassis *ch;
507 struct sbrec_encap *encap;
508 bool may_exist = shash_find(&ctx->options, "--may-exist") != NULL;
509 const char *ch_name, *encap_type, *encap_ip;
510
511 ch_name = ctx->argv[1];
512 encap_type = ctx->argv[2];
513 encap_ip = ctx->argv[3];
514
515 sbctl_context_populate_cache(ctx);
516 if (may_exist) {
517 struct sbctl_chassis *sbctl_ch;
518
519 sbctl_ch = find_chassis(sbctl_ctx, ch_name, false);
520 if (sbctl_ch) {
521 return;
522 }
523 }
524 check_conflicts(sbctl_ctx, ch_name,
525 xasprintf("cannot create a chassis named %s", ch_name));
526 ch = sbrec_chassis_insert(ctx->txn);
527 sbrec_chassis_set_name(ch, ch_name);
528 encap = sbrec_encap_insert(ctx->txn);
529 sbrec_encap_set_type(encap, encap_type);
530 sbrec_encap_set_ip(encap, encap_ip);
531 sbrec_chassis_set_encaps(ch, &encap, 1);
532 sbctl_context_invalidate_cache(ctx);
533 }
534
535 static void
536 cmd_chassis_del(struct ctl_context *ctx)
537 {
538 struct sbctl_context *sbctl_ctx = sbctl_context_cast(ctx);
539 bool must_exist = !shash_find(&ctx->options, "--if-exists");
540 struct sbctl_chassis *sbctl_ch;
541
542 sbctl_context_populate_cache(ctx);
543 sbctl_ch = find_chassis(sbctl_ctx, ctx->argv[1], must_exist);
544 if (sbctl_ch) {
545 if (sbctl_ch->ch_cfg) {
546 sbrec_chassis_delete(sbctl_ch->ch_cfg);
547 }
548 shash_find_and_delete(&sbctl_ctx->chassis, ctx->argv[1]);
549 free(sbctl_ch);
550 }
551 }
552
553 static void
554 cmd_lport_bind(struct ctl_context *ctx)
555 {
556 struct sbctl_context *sbctl_ctx = sbctl_context_cast(ctx);
557 bool may_exist = shash_find(&ctx->options, "--may-exist") != NULL;
558 struct sbctl_chassis *sbctl_ch;
559 struct sbctl_port_binding *sbctl_bd;
560 char *lport_name, *ch_name;
561
562 /* port_binding must exist, chassis must exist! */
563 lport_name = ctx->argv[1];
564 ch_name = ctx->argv[2];
565
566 sbctl_context_populate_cache(ctx);
567 sbctl_bd = find_port_binding(sbctl_ctx, lport_name, true);
568 sbctl_ch = find_chassis(sbctl_ctx, ch_name, true);
569
570 if (sbctl_bd->bd_cfg->chassis) {
571 if (may_exist && sbctl_bd->bd_cfg->chassis == sbctl_ch->ch_cfg) {
572 return;
573 } else {
574 ctl_fatal("lport (%s) has already been binded to chassis (%s)",
575 lport_name, sbctl_bd->bd_cfg->chassis->name);
576 }
577 }
578 sbrec_port_binding_set_chassis(sbctl_bd->bd_cfg, sbctl_ch->ch_cfg);
579 sbctl_context_invalidate_cache(ctx);
580 }
581
582 static void
583 cmd_lport_unbind(struct ctl_context *ctx)
584 {
585 struct sbctl_context *sbctl_ctx = sbctl_context_cast(ctx);
586 bool must_exist = !shash_find(&ctx->options, "--if-exists");
587 struct sbctl_port_binding *sbctl_bd;
588 char *lport_name;
589
590 lport_name = ctx->argv[1];
591 sbctl_context_populate_cache(ctx);
592 sbctl_bd = find_port_binding(sbctl_ctx, lport_name, must_exist);
593 if (sbctl_bd) {
594 sbrec_port_binding_set_chassis(sbctl_bd->bd_cfg, NULL);
595 }
596 }
597
598 enum {
599 PL_INGRESS,
600 PL_EGRESS,
601 };
602
603 /* Help ensure we catch any future pipeline values */
604 static int
605 pipeline_encode(const char *pl)
606 {
607 if (!strcmp(pl, "ingress")) {
608 return PL_INGRESS;
609 } else if (!strcmp(pl, "egress")) {
610 return PL_EGRESS;
611 }
612
613 OVS_NOT_REACHED();
614 }
615
616 static int
617 lflow_cmp(const void *lf1_, const void *lf2_)
618 {
619 const struct sbrec_logical_flow *lf1, *lf2;
620
621 lf1 = *((struct sbrec_logical_flow **) lf1_);
622 lf2 = *((struct sbrec_logical_flow **) lf2_);
623
624 int pl1 = pipeline_encode(lf1->pipeline);
625 int pl2 = pipeline_encode(lf2->pipeline);
626
627 #define CMP(expr) \
628 do { \
629 int res; \
630 res = (expr); \
631 if (res) { \
632 return res; \
633 } \
634 } while (0)
635
636 CMP(uuid_compare_3way(&lf1->logical_datapath->header_.uuid,
637 &lf2->logical_datapath->header_.uuid));
638 CMP(pl1 - pl2);
639 CMP(lf1->table_id > lf2->table_id ? 1 :
640 (lf1->table_id < lf2->table_id ? -1 : 0));
641 CMP(lf1->priority > lf2->priority ? -1 :
642 (lf1->priority < lf2->priority ? 1 : 0));
643 CMP(strcmp(lf1->match, lf2->match));
644
645 #undef CMP
646
647 return 0;
648 }
649
650 static void
651 cmd_lflow_list(struct ctl_context *ctx)
652 {
653 const char *datapath = ctx->argc == 2 ? ctx->argv[1] : NULL;
654 struct uuid datapath_uuid = { .parts = { 0, }};
655 const struct sbrec_logical_flow **lflows;
656 const struct sbrec_logical_flow *lflow;
657 size_t n_flows = 0, n_capacity = 64;
658
659 if (datapath && !uuid_from_string(&datapath_uuid, datapath)) {
660 VLOG_ERR("Invalid format of datapath UUID");
661 return;
662 }
663
664 lflows = xmalloc(sizeof *lflows * n_capacity);
665 SBREC_LOGICAL_FLOW_FOR_EACH (lflow, ctx->idl) {
666 if (n_flows == n_capacity) {
667 lflows = x2nrealloc(lflows, &n_capacity, sizeof *lflows);
668 }
669 lflows[n_flows] = lflow;
670 n_flows++;
671 }
672
673 qsort(lflows, n_flows, sizeof *lflows, lflow_cmp);
674
675 const char *cur_pipeline = "";
676 size_t i;
677 for (i = 0; i < n_flows; i++) {
678 lflow = lflows[i];
679 if (datapath && !uuid_equals(&datapath_uuid,
680 &lflow->logical_datapath->header_.uuid)) {
681 continue;
682 }
683 if (strcmp(cur_pipeline, lflow->pipeline)) {
684 printf("Datapath: " UUID_FMT " Pipeline: %s\n",
685 UUID_ARGS(&lflow->logical_datapath->header_.uuid),
686 lflow->pipeline);
687 cur_pipeline = lflow->pipeline;
688 }
689 printf(" table_id=%" PRId64 ", priority=%3" PRId64 ", "
690 "match=(%s), action=(%s)\n",
691 lflow->table_id, lflow->priority,
692 lflow->match, lflow->actions);
693 }
694
695 free(lflows);
696 }
697
698 \f
699 static const struct ctl_table_class tables[] = {
700 {&sbrec_table_chassis,
701 {{&sbrec_table_chassis, &sbrec_chassis_col_name, NULL},
702 {NULL, NULL, NULL}}},
703
704 {&sbrec_table_encap,
705 {{NULL, NULL, NULL},
706 {NULL, NULL, NULL}}},
707
708 {&sbrec_table_logical_flow,
709 {{&sbrec_table_logical_flow, NULL,
710 &sbrec_logical_flow_col_logical_datapath},
711 {NULL, NULL, NULL}}},
712
713 {&sbrec_table_multicast_group,
714 {{NULL, NULL, NULL},
715 {NULL, NULL, NULL}}},
716
717 {&sbrec_table_datapath_binding,
718 {{NULL, NULL, NULL},
719 {NULL, NULL, NULL}}},
720
721 {&sbrec_table_port_binding,
722 {{&sbrec_table_port_binding, &sbrec_port_binding_col_logical_port, NULL},
723 {NULL, NULL, NULL}}},
724
725 {NULL, {{NULL, NULL, NULL}, {NULL, NULL, NULL}}}
726 };
727
728 \f
729 static void
730 sbctl_context_init_command(struct sbctl_context *sbctl_ctx,
731 struct ctl_command *command)
732 {
733 ctl_context_init_command(&sbctl_ctx->base, command);
734 }
735
736 static void
737 sbctl_context_init(struct sbctl_context *sbctl_ctx,
738 struct ctl_command *command, struct ovsdb_idl *idl,
739 struct ovsdb_idl_txn *txn,
740 struct ovsdb_symbol_table *symtab)
741 {
742 ctl_context_init(&sbctl_ctx->base, command, idl, txn, symtab,
743 sbctl_context_invalidate_cache);
744 sbctl_ctx->cache_valid = false;
745 }
746
747 static void
748 sbctl_context_done_command(struct sbctl_context *sbctl_ctx,
749 struct ctl_command *command)
750 {
751 ctl_context_done_command(&sbctl_ctx->base, command);
752 }
753
754 static void
755 sbctl_context_done(struct sbctl_context *sbctl_ctx,
756 struct ctl_command *command)
757 {
758 ctl_context_done(&sbctl_ctx->base, command);
759 }
760
761 static void
762 run_prerequisites(struct ctl_command *commands, size_t n_commands,
763 struct ovsdb_idl *idl)
764 {
765 struct ctl_command *c;
766
767 for (c = commands; c < &commands[n_commands]; c++) {
768 if (c->syntax->prerequisites) {
769 struct sbctl_context sbctl_ctx;
770
771 ds_init(&c->output);
772 c->table = NULL;
773
774 sbctl_context_init(&sbctl_ctx, c, idl, NULL, NULL);
775 (c->syntax->prerequisites)(&sbctl_ctx.base);
776 sbctl_context_done(&sbctl_ctx, c);
777
778 ovs_assert(!c->output.string);
779 ovs_assert(!c->table);
780 }
781 }
782 }
783
784 static void
785 do_sbctl(const char *args, struct ctl_command *commands, size_t n_commands,
786 struct ovsdb_idl *idl)
787 {
788 struct ovsdb_idl_txn *txn;
789 enum ovsdb_idl_txn_status status;
790 struct ovsdb_symbol_table *symtab;
791 struct sbctl_context sbctl_ctx;
792 struct ctl_command *c;
793 struct shash_node *node;
794 char *error = NULL;
795
796 txn = the_idl_txn = ovsdb_idl_txn_create(idl);
797 if (dry_run) {
798 ovsdb_idl_txn_set_dry_run(txn);
799 }
800
801 ovsdb_idl_txn_add_comment(txn, "ovs-sbctl: %s", args);
802
803 symtab = ovsdb_symbol_table_create();
804 for (c = commands; c < &commands[n_commands]; c++) {
805 ds_init(&c->output);
806 c->table = NULL;
807 }
808 sbctl_context_init(&sbctl_ctx, NULL, idl, txn, symtab);
809 for (c = commands; c < &commands[n_commands]; c++) {
810 sbctl_context_init_command(&sbctl_ctx, c);
811 if (c->syntax->run) {
812 (c->syntax->run)(&sbctl_ctx.base);
813 }
814 sbctl_context_done_command(&sbctl_ctx, c);
815
816 if (sbctl_ctx.base.try_again) {
817 sbctl_context_done(&sbctl_ctx, NULL);
818 goto try_again;
819 }
820 }
821 sbctl_context_done(&sbctl_ctx, NULL);
822
823 SHASH_FOR_EACH (node, &symtab->sh) {
824 struct ovsdb_symbol *symbol = node->data;
825 if (!symbol->created) {
826 ctl_fatal("row id \"%s\" is referenced but never created (e.g. "
827 "with \"-- --id=%s create ...\")",
828 node->name, node->name);
829 }
830 if (!symbol->strong_ref) {
831 if (!symbol->weak_ref) {
832 VLOG_WARN("row id \"%s\" was created but no reference to it "
833 "was inserted, so it will not actually appear in "
834 "the database", node->name);
835 } else {
836 VLOG_WARN("row id \"%s\" was created but only a weak "
837 "reference to it was inserted, so it will not "
838 "actually appear in the database", node->name);
839 }
840 }
841 }
842
843 status = ovsdb_idl_txn_commit_block(txn);
844 if (status == TXN_UNCHANGED || status == TXN_SUCCESS) {
845 for (c = commands; c < &commands[n_commands]; c++) {
846 if (c->syntax->postprocess) {
847 sbctl_context_init(&sbctl_ctx, c, idl, txn, symtab);
848 (c->syntax->postprocess)(&sbctl_ctx.base);
849 sbctl_context_done(&sbctl_ctx, c);
850 }
851 }
852 }
853 error = xstrdup(ovsdb_idl_txn_get_error(txn));
854
855 switch (status) {
856 case TXN_UNCOMMITTED:
857 case TXN_INCOMPLETE:
858 OVS_NOT_REACHED();
859
860 case TXN_ABORTED:
861 /* Should not happen--we never call ovsdb_idl_txn_abort(). */
862 ctl_fatal("transaction aborted");
863
864 case TXN_UNCHANGED:
865 case TXN_SUCCESS:
866 break;
867
868 case TXN_TRY_AGAIN:
869 goto try_again;
870
871 case TXN_ERROR:
872 ctl_fatal("transaction error: %s", error);
873
874 case TXN_NOT_LOCKED:
875 /* Should not happen--we never call ovsdb_idl_set_lock(). */
876 ctl_fatal("database not locked");
877
878 default:
879 OVS_NOT_REACHED();
880 }
881 free(error);
882
883 ovsdb_symbol_table_destroy(symtab);
884
885 for (c = commands; c < &commands[n_commands]; c++) {
886 struct ds *ds = &c->output;
887
888 if (c->table) {
889 table_print(c->table, &table_style);
890 } else if (oneline) {
891 size_t j;
892
893 ds_chomp(ds, '\n');
894 for (j = 0; j < ds->length; j++) {
895 int ch = ds->string[j];
896 switch (ch) {
897 case '\n':
898 fputs("\\n", stdout);
899 break;
900
901 case '\\':
902 fputs("\\\\", stdout);
903 break;
904
905 default:
906 putchar(ch);
907 }
908 }
909 putchar('\n');
910 } else {
911 fputs(ds_cstr(ds), stdout);
912 }
913 ds_destroy(&c->output);
914 table_destroy(c->table);
915 free(c->table);
916
917 shash_destroy_free_data(&c->options);
918 }
919 free(commands);
920 ovsdb_idl_txn_destroy(txn);
921 ovsdb_idl_destroy(idl);
922
923 exit(EXIT_SUCCESS);
924
925 try_again:
926 /* Our transaction needs to be rerun, or a prerequisite was not met. Free
927 * resources and return so that the caller can try again. */
928 if (txn) {
929 ovsdb_idl_txn_abort(txn);
930 ovsdb_idl_txn_destroy(txn);
931 the_idl_txn = NULL;
932 }
933 ovsdb_symbol_table_destroy(symtab);
934 for (c = commands; c < &commands[n_commands]; c++) {
935 ds_destroy(&c->output);
936 table_destroy(c->table);
937 free(c->table);
938 }
939 free(error);
940 }
941
942 /* Frees the current transaction and the underlying IDL and then calls
943 * exit(status).
944 *
945 * Freeing the transaction and the IDL is not strictly necessary, but it makes
946 * for a clean memory leak report from valgrind in the normal case. That makes
947 * it easier to notice real memory leaks. */
948 static void
949 sbctl_exit(int status)
950 {
951 if (the_idl_txn) {
952 ovsdb_idl_txn_abort(the_idl_txn);
953 ovsdb_idl_txn_destroy(the_idl_txn);
954 }
955 ovsdb_idl_destroy(the_idl);
956 exit(status);
957 }
958
959 static const struct ctl_command_syntax sbctl_commands[] = {
960 /* Chassis commands. */
961 {"chassis-add", 3, 3, "CHASSIS ENCAP-TYPE ENCAP-IP", pre_get_info,
962 cmd_chassis_add, NULL, "--may-exist", RW},
963 {"chassis-del", 1, 1, "CHASSIS", pre_get_info, cmd_chassis_del, NULL,
964 "--if-exists", RW},
965
966 /* Port binding commands. */
967 {"lport-bind", 2, 2, "LPORT CHASSIS", pre_get_info, cmd_lport_bind, NULL,
968 "--may-exist", RW},
969 {"lport-unbind", 1, 1, "LPORT", pre_get_info, cmd_lport_unbind, NULL,
970 "--if-exists", RW},
971
972 /* Logical flow commands */
973 {"lflow-list", 0, 1, "[DATAPATH]", pre_get_info, cmd_lflow_list, NULL,
974 "", RO},
975 {"dump-flows", 0, 1, "[DATAPATH]", pre_get_info, cmd_lflow_list, NULL,
976 "", RO}, /* Friendly alias for lflow-list */
977
978 /* SSL commands (To Be Added). */
979
980 {NULL, 0, 0, NULL, NULL, NULL, NULL, NULL, RO},
981 };
982
983 /* Registers sbctl and common db commands. */
984 static void
985 sbctl_cmd_init(void)
986 {
987 ctl_init(tables, cmd_show_tables, sbctl_exit);
988 ctl_register_commands(sbctl_commands);
989 }