]> git.proxmox.com Git - ovs.git/blob - vtep/vtep-ctl.c
db-ctl-base: make use of user supplied exit function
[ovs.git] / vtep / vtep-ctl.c
1 /*
2 * Copyright (c) 2009, 2010, 2011, 2012, 2014, 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 "hash.h"
37 #include "json.h"
38 #include "ovsdb-data.h"
39 #include "ovsdb-idl.h"
40 #include "poll-loop.h"
41 #include "process.h"
42 #include "stream.h"
43 #include "stream-ssl.h"
44 #include "smap.h"
45 #include "sset.h"
46 #include "svec.h"
47 #include "vtep/vtep-idl.h"
48 #include "table.h"
49 #include "timeval.h"
50 #include "util.h"
51 #include "openvswitch/vconn.h"
52 #include "openvswitch/vlog.h"
53
54 VLOG_DEFINE_THIS_MODULE(vtep_ctl);
55
56 struct vtep_ctl_context;
57
58 /* --db: The database server to contact. */
59 static const char *db;
60
61 /* --oneline: Write each command's output as a single line? */
62 static bool oneline;
63
64 /* --dry-run: Do not commit any changes. */
65 static bool dry_run;
66
67 /* --timeout: Time to wait for a connection to 'db'. */
68 static int timeout;
69
70 /* Format for table output. */
71 static struct table_style table_style = TABLE_STYLE_DEFAULT;
72
73 /* The IDL we're using and the current transaction, if any.
74 * This is for use by vtep_ctl_exit() only, to allow it to clean up.
75 * Other code should use its context arguments. */
76 static struct ovsdb_idl *the_idl;
77 static struct ovsdb_idl_txn *the_idl_txn;
78
79 OVS_NO_RETURN static void vtep_ctl_exit(int status);
80 static void vtep_ctl_cmd_init(void);
81 OVS_NO_RETURN static void usage(void);
82 static void parse_options(int argc, char *argv[], struct shash *local_options);
83 static void run_prerequisites(struct ctl_command[], size_t n_commands,
84 struct ovsdb_idl *);
85 static void do_vtep_ctl(const char *args, struct ctl_command *, size_t n,
86 struct ovsdb_idl *);
87 static struct vtep_ctl_lswitch *find_lswitch(struct vtep_ctl_context *,
88 const char *name,
89 bool must_exist);
90
91 int
92 main(int argc, char *argv[])
93 {
94 extern struct vlog_module VLM_reconnect;
95 struct ovsdb_idl *idl;
96 struct ctl_command *commands;
97 struct shash local_options;
98 unsigned int seqno;
99 size_t n_commands;
100 char *args;
101
102 set_program_name(argv[0]);
103 fatal_ignore_sigpipe();
104 vlog_set_levels(NULL, VLF_CONSOLE, VLL_WARN);
105 vlog_set_levels(&VLM_reconnect, VLF_ANY_DESTINATION, VLL_WARN);
106 vteprec_init();
107
108 vtep_ctl_cmd_init();
109
110 /* Log our arguments. This is often valuable for debugging systems. */
111 args = process_escape_args(argv);
112 VLOG(ctl_might_write_to_db(argv) ? VLL_INFO : VLL_DBG, "Called as %s", args);
113
114 /* Parse command line. */
115 shash_init(&local_options);
116 parse_options(argc, argv, &local_options);
117 commands = ctl_parse_commands(argc - optind, argv + optind, &local_options,
118 &n_commands);
119
120 if (timeout) {
121 time_alarm(timeout);
122 }
123
124 /* Initialize IDL. */
125 idl = the_idl = ovsdb_idl_create(db, &vteprec_idl_class, false, false);
126 run_prerequisites(commands, n_commands, idl);
127
128 /* Execute the commands.
129 *
130 * 'seqno' is the database sequence number for which we last tried to
131 * execute our transaction. There's no point in trying to commit more than
132 * once for any given sequence number, because if the transaction fails
133 * it's because the database changed and we need to obtain an up-to-date
134 * view of the database before we try the transaction again. */
135 seqno = ovsdb_idl_get_seqno(idl);
136 for (;;) {
137 ovsdb_idl_run(idl);
138
139 if (seqno != ovsdb_idl_get_seqno(idl)) {
140 seqno = ovsdb_idl_get_seqno(idl);
141 do_vtep_ctl(args, commands, n_commands, idl);
142 }
143
144 if (seqno == ovsdb_idl_get_seqno(idl)) {
145 ovsdb_idl_wait(idl);
146 poll_block();
147 }
148 }
149 }
150
151 static void
152 parse_options(int argc, char *argv[], struct shash *local_options)
153 {
154 enum {
155 OPT_DB = UCHAR_MAX + 1,
156 OPT_ONELINE,
157 OPT_NO_SYSLOG,
158 OPT_DRY_RUN,
159 OPT_PEER_CA_CERT,
160 OPT_LOCAL,
161 VLOG_OPTION_ENUMS,
162 TABLE_OPTION_ENUMS
163 };
164 static const struct option global_long_options[] = {
165 {"db", required_argument, NULL, OPT_DB},
166 {"no-syslog", no_argument, NULL, OPT_NO_SYSLOG},
167 {"dry-run", no_argument, NULL, OPT_DRY_RUN},
168 {"oneline", no_argument, NULL, OPT_ONELINE},
169 {"timeout", required_argument, NULL, 't'},
170 {"help", no_argument, NULL, 'h'},
171 {"version", no_argument, NULL, 'V'},
172 VLOG_LONG_OPTIONS,
173 TABLE_LONG_OPTIONS,
174 STREAM_SSL_LONG_OPTIONS,
175 {"peer-ca-cert", required_argument, NULL, OPT_PEER_CA_CERT},
176 {NULL, 0, NULL, 0},
177 };
178 const int n_global_long_options = ARRAY_SIZE(global_long_options) - 1;
179 char *tmp, *short_options;
180
181 struct option *options;
182 size_t allocated_options;
183 size_t n_options;
184 size_t i;
185
186 tmp = ovs_cmdl_long_options_to_short_options(global_long_options);
187 short_options = xasprintf("+%s", tmp);
188 free(tmp);
189
190 /* We want to parse both global and command-specific options here, but
191 * getopt_long() isn't too convenient for the job. We copy our global
192 * options into a dynamic array, then append all of the command-specific
193 * options. */
194 options = xmemdup(global_long_options, sizeof global_long_options);
195 allocated_options = ARRAY_SIZE(global_long_options);
196 n_options = n_global_long_options;
197 ctl_add_cmd_options(&options, &n_options, &allocated_options, OPT_LOCAL);
198 table_style.format = TF_LIST;
199
200 for (;;) {
201 int idx;
202 int c;
203
204 c = getopt_long(argc, argv, short_options, options, &idx);
205 if (c == -1) {
206 break;
207 }
208
209 switch (c) {
210 case OPT_DB:
211 db = optarg;
212 break;
213
214 case OPT_ONELINE:
215 oneline = true;
216 break;
217
218 case OPT_NO_SYSLOG:
219 vlog_set_levels(&VLM_vtep_ctl, VLF_SYSLOG, VLL_WARN);
220 break;
221
222 case OPT_DRY_RUN:
223 dry_run = true;
224 break;
225
226 case OPT_LOCAL:
227 if (shash_find(local_options, options[idx].name)) {
228 ctl_fatal("'%s' option specified multiple times",
229 options[idx].name);
230 }
231 shash_add_nocopy(local_options,
232 xasprintf("--%s", options[idx].name),
233 optarg ? xstrdup(optarg) : NULL);
234 break;
235
236 case 'h':
237 usage();
238
239 case 'V':
240 ovs_print_version(0, 0);
241 printf("DB Schema %s\n", vteprec_get_db_version());
242 exit(EXIT_SUCCESS);
243
244 case 't':
245 timeout = strtoul(optarg, NULL, 10);
246 if (timeout < 0) {
247 ctl_fatal("value %s on -t or --timeout is invalid",
248 optarg);
249 }
250 break;
251
252 VLOG_OPTION_HANDLERS
253 TABLE_OPTION_HANDLERS(&table_style)
254
255 STREAM_SSL_OPTION_HANDLERS
256
257 case OPT_PEER_CA_CERT:
258 stream_ssl_set_peer_ca_cert_file(optarg);
259 break;
260
261 case '?':
262 exit(EXIT_FAILURE);
263
264 default:
265 abort();
266 }
267 }
268 free(short_options);
269
270 if (!db) {
271 db = ctl_default_db();
272 }
273
274 for (i = n_global_long_options; options[i].name; i++) {
275 free(CONST_CAST(char *, options[i].name));
276 }
277 free(options);
278 }
279
280 /* Frees the current transaction and the underlying IDL and then calls
281 * exit(status).
282 *
283 * Freeing the transaction and the IDL is not strictly necessary, but it makes
284 * for a clean memory leak report from valgrind in the normal case. That makes
285 * it easier to notice real memory leaks. */
286 static void
287 vtep_ctl_exit(int status)
288 {
289 if (the_idl_txn) {
290 ovsdb_idl_txn_abort(the_idl_txn);
291 ovsdb_idl_txn_destroy(the_idl_txn);
292 }
293 ovsdb_idl_destroy(the_idl);
294 exit(status);
295 }
296
297 static void
298 usage(void)
299 {
300 printf("\
301 %s: VTEP configuration utility\n\
302 usage: %s [OPTIONS] COMMAND [ARG...]\n\
303 \n\
304 VTEP commands:\n\
305 show print overview of database contents\n\
306 \n\
307 Manager commands:\n\
308 get-manager print the managers\n\
309 del-manager delete the managers\n\
310 set-manager TARGET... set the list of managers to TARGET...\n\
311 \n\
312 Physical Switch commands:\n\
313 add-ps PS create a new physical switch named PS\n\
314 del-ps PS delete PS and all of its ports\n\
315 list-ps print the names of all the physical switches\n\
316 ps-exists PS exit 2 if PS does not exist\n\
317 \n\
318 Port commands:\n\
319 list-ports PS print the names of all the ports on PS\n\
320 add-port PS PORT add network device PORT to PS\n\
321 del-port PS PORT delete PORT from PS\n\
322 \n\
323 Logical Switch commands:\n\
324 add-ls LS create a new logical switch named LS\n\
325 del-ls LS delete LS and all of its ports\n\
326 list-ls print the names of all the logical switches\n\
327 ls-exists LS exit 2 if LS does not exist\n\
328 bind-ls PS PORT VLAN LS bind LS to VLAN on PORT\n\
329 unbind-ls PS PORT VLAN unbind logical switch on VLAN from PORT\n\
330 list-bindings PS PORT list bindings for PORT on PS\n\
331 \n\
332 MAC binding commands:\n\
333 add-ucast-local LS MAC [ENCAP] IP add ucast local entry in LS\n\
334 del-ucast-local LS MAC del ucast local entry from LS\n\
335 add-mcast-local LS MAC [ENCAP] IP add mcast local entry in LS\n\
336 del-mcast-local LS MAC [ENCAP] IP del mcast local entry from LS\n\
337 clear-local-macs LS clear local mac entries\n\
338 list-local-macs LS list local mac entries\n\
339 add-ucast-remote LS MAC [ENCAP] IP add ucast remote entry in LS\n\
340 del-ucast-remote LS MAC del ucast remote entry from LS\n\
341 add-mcast-remote LS MAC [ENCAP] IP add mcast remote entry in LS\n\
342 del-mcast-remote LS MAC [ENCAP] IP del mcast remote entry from LS\n\
343 clear-remote-macs LS clear remote mac entries\n\
344 list-remote-macs LS list remote mac entries\n\
345 \n\
346 %s\
347 \n\
348 Options:\n\
349 --db=DATABASE connect to DATABASE\n\
350 (default: %s)\n\
351 -t, --timeout=SECS wait at most SECS seconds\n\
352 --dry-run do not commit changes to database\n\
353 --oneline print exactly one line of output per command\n",
354 program_name, program_name, ctl_get_db_cmd_usage(), ctl_default_db());
355 vlog_usage();
356 printf("\
357 --no-syslog equivalent to --verbose=vtep_ctl:syslog:warn\n");
358 stream_usage("database", true, true, false);
359 printf("\n\
360 Other options:\n\
361 -h, --help display this help message\n\
362 -V, --version display version information\n");
363 exit(EXIT_SUCCESS);
364 }
365
366 \f
367 struct cmd_show_table cmd_show_tables[] = {
368 {&vteprec_table_global,
369 NULL,
370 {&vteprec_global_col_managers,
371 &vteprec_global_col_switches,
372 NULL},
373 false},
374
375 {&vteprec_table_manager,
376 &vteprec_manager_col_target,
377 {&vteprec_manager_col_is_connected,
378 NULL,
379 NULL},
380 false},
381
382 {&vteprec_table_physical_switch,
383 &vteprec_physical_switch_col_name,
384 {&vteprec_physical_switch_col_management_ips,
385 &vteprec_physical_switch_col_tunnel_ips,
386 &vteprec_physical_switch_col_ports},
387 false},
388
389 {&vteprec_table_physical_port,
390 &vteprec_physical_port_col_name,
391 {&vteprec_physical_port_col_vlan_bindings,
392 NULL,
393 NULL},
394 false},
395
396 {&vteprec_table_logical_switch,
397 &vteprec_logical_switch_col_name,
398 {NULL,
399 NULL,
400 NULL},
401 false},
402
403 {NULL, NULL, {NULL, NULL, NULL}, false}
404 };
405
406 /* vtep-ctl specific context. Inherits the 'struct ctl_context' as base. */
407 struct vtep_ctl_context {
408 struct ctl_context base;
409
410 /* Modifiable state. */
411 const struct vteprec_global *vtep_global;
412 bool verified_ports;
413
414 /* A cache of the contents of the database.
415 *
416 * A command that needs to use any of this information must first
417 * call vtep_ctl_context_populate_cache(). A command that changes
418 * anything that could invalidate the cache must either call
419 * vtep_ctl_context_invalidate_cache() or manually update the cache
420 * to maintain its correctness. */
421 bool cache_valid;
422 struct shash pswitches; /* Maps from physical switch name to
423 * struct vtep_ctl_pswitch. */
424 struct shash ports; /* Maps from port name to struct vtep_ctl_port. */
425
426 struct shash lswitches; /* Maps from logical switch name to
427 * struct vtep_ctl_lswitch. */
428 struct shash plocs; /* Maps from "<encap>+<dst_ip>" to
429 * struct vteprec_physical_locator. */
430 };
431
432 /* Casts 'base' into 'strcut vtep_ctl_context'. */
433 static struct vtep_ctl_context *
434 vtep_ctl_context_cast(struct ctl_context *base)
435 {
436 return CONTAINER_OF(base, struct vtep_ctl_context, base);
437 }
438
439 struct vtep_ctl_pswitch {
440 const struct vteprec_physical_switch *ps_cfg;
441 char *name;
442 struct ovs_list ports; /* Contains "struct vteprec_physical_port"s. */
443 };
444
445 struct vtep_ctl_port {
446 struct ovs_list ports_node; /* In struct vtep_ctl_pswitch's 'ports' list. */
447 const struct vteprec_physical_port *port_cfg;
448 struct vtep_ctl_pswitch *ps;
449 struct shash bindings; /* Maps from vlan to vtep_ctl_lswitch. */
450 };
451
452 struct vtep_ctl_lswitch {
453 const struct vteprec_logical_switch *ls_cfg;
454 char *name;
455 struct shash ucast_local; /* Maps from mac to vteprec_ucast_macs_local. */
456 struct shash ucast_remote; /* Maps from mac to vteprec_ucast_macs_remote.*/
457 struct shash mcast_local; /* Maps from mac to vtep_ctl_mcast_mac. */
458 struct shash mcast_remote; /* Maps from mac to vtep_ctl_mcast_mac. */
459 };
460
461 struct vtep_ctl_mcast_mac {
462 const struct vteprec_mcast_macs_local *local_cfg;
463 const struct vteprec_mcast_macs_remote *remote_cfg;
464
465 const struct vteprec_physical_locator_set *ploc_set_cfg;
466 struct ovs_list locators; /* Contains 'vtep_ctl_ploc's. */
467 };
468
469 struct vtep_ctl_ploc {
470 struct ovs_list locators_node; /* In struct vtep_ctl_ploc_set's 'locators'
471 list. */
472 const struct vteprec_physical_locator *ploc_cfg;
473 };
474
475 static void
476 verify_ports(struct vtep_ctl_context *vtepctl_ctx)
477 {
478 if (!vtepctl_ctx->verified_ports) {
479 const struct vteprec_physical_switch *ps;
480
481 vteprec_global_verify_switches(vtepctl_ctx->vtep_global);
482 VTEPREC_PHYSICAL_SWITCH_FOR_EACH (ps, vtepctl_ctx->base.idl) {
483 vteprec_physical_switch_verify_ports(ps);
484 }
485
486 vtepctl_ctx->verified_ports = true;
487 }
488 }
489
490 static struct vtep_ctl_port *
491 add_port_to_cache(struct vtep_ctl_context *vtepctl_ctx,
492 struct vtep_ctl_pswitch *ps,
493 struct vteprec_physical_port *port_cfg)
494 {
495 char *cache_name = xasprintf("%s+%s", ps->name, port_cfg->name);
496 struct vtep_ctl_port *port;
497
498 port = xmalloc(sizeof *port);
499 list_push_back(&ps->ports, &port->ports_node);
500 port->port_cfg = port_cfg;
501 port->ps = ps;
502 shash_add(&vtepctl_ctx->ports, cache_name, port);
503 free(cache_name);
504 shash_init(&port->bindings);
505
506 return port;
507 }
508
509 static void
510 del_cached_port(struct vtep_ctl_context *vtepctl_ctx,
511 struct vtep_ctl_port *port)
512 {
513 char *cache_name = xasprintf("%s+%s", port->ps->name, port->port_cfg->name);
514
515 list_remove(&port->ports_node);
516 shash_find_and_delete(&vtepctl_ctx->ports, cache_name);
517 vteprec_physical_port_delete(port->port_cfg);
518 free(cache_name);
519 free(port);
520 }
521
522 static void
523 add_pswitch_to_cache(struct vtep_ctl_context *vtepctl_ctx,
524 struct vteprec_physical_switch *ps_cfg)
525 {
526 struct vtep_ctl_pswitch *ps = xmalloc(sizeof *ps);
527 ps->ps_cfg = ps_cfg;
528 ps->name = xstrdup(ps_cfg->name);
529 list_init(&ps->ports);
530 shash_add(&vtepctl_ctx->pswitches, ps->name, ps);
531 }
532
533 static void
534 vtep_delete_pswitch(const struct vteprec_global *vtep_global,
535 const struct vteprec_physical_switch *ps)
536 {
537 struct vteprec_physical_switch **pswitches;
538 size_t i, n;
539
540 pswitches = xmalloc(sizeof *vtep_global->switches
541 * vtep_global->n_switches);
542 for (i = n = 0; i < vtep_global->n_switches; i++) {
543 if (vtep_global->switches[i] != ps) {
544 pswitches[n++] = vtep_global->switches[i];
545 }
546 }
547 vteprec_global_set_switches(vtep_global, pswitches, n);
548 free(pswitches);
549 }
550
551 static void
552 del_cached_pswitch(struct vtep_ctl_context *ctx, struct vtep_ctl_pswitch *ps)
553 {
554 ovs_assert(list_is_empty(&ps->ports));
555 if (ps->ps_cfg) {
556 vteprec_physical_switch_delete(ps->ps_cfg);
557 vtep_delete_pswitch(ctx->vtep_global, ps->ps_cfg);
558 }
559 shash_find_and_delete(&ctx->pswitches, ps->name);
560 free(ps->name);
561 free(ps);
562 }
563
564 static struct vtep_ctl_lswitch *
565 add_lswitch_to_cache(struct vtep_ctl_context *vtepctl_ctx,
566 const struct vteprec_logical_switch *ls_cfg)
567 {
568 struct vtep_ctl_lswitch *ls = xmalloc(sizeof *ls);
569 ls->ls_cfg = ls_cfg;
570 ls->name = xstrdup(ls_cfg->name);
571 shash_add(&vtepctl_ctx->lswitches, ls->name, ls);
572 shash_init(&ls->ucast_local);
573 shash_init(&ls->ucast_remote);
574 shash_init(&ls->mcast_local);
575 shash_init(&ls->mcast_remote);
576 return ls;
577 }
578
579 static void
580 del_cached_lswitch(struct vtep_ctl_context *ctx, struct vtep_ctl_lswitch *ls)
581 {
582 if (ls->ls_cfg) {
583 vteprec_logical_switch_delete(ls->ls_cfg);
584 }
585 shash_find_and_delete(&ctx->lswitches, ls->name);
586 free(ls->name);
587 free(ls);
588 }
589
590 static void
591 commit_ls_bindings(struct vtep_ctl_port *port)
592 {
593 struct vteprec_logical_switch **binding_values;
594 int64_t *binding_keys;
595 size_t n_bindings;
596 struct shash_node *node;
597 int i;
598
599 n_bindings = shash_count(&port->bindings);
600 binding_keys = xmalloc(n_bindings * sizeof *binding_keys);
601 binding_values = xmalloc(n_bindings * sizeof *binding_values);
602
603 i = 0;
604 SHASH_FOR_EACH(node, &port->bindings) {
605 struct vtep_ctl_lswitch *ls_entry = node->data;
606
607 binding_keys[i] = strtoll(node->name, NULL, 0);
608 binding_values[i] = (struct vteprec_logical_switch *)ls_entry->ls_cfg;
609 i++;
610 }
611
612 vteprec_physical_port_set_vlan_bindings(port->port_cfg,
613 binding_keys, binding_values,
614 n_bindings);
615 free(binding_values);
616 free(binding_keys);
617 }
618
619 static void
620 add_ls_binding_to_cache(struct vtep_ctl_port *port,
621 const char *vlan,
622 struct vtep_ctl_lswitch *ls)
623 {
624 if (shash_find(&port->bindings, vlan)) {
625 ctl_fatal("multiple bindings for vlan %s", vlan);
626 }
627
628 shash_add(&port->bindings, vlan, ls);
629 }
630
631 static void
632 del_cached_ls_binding(struct vtep_ctl_port *port, const char *vlan)
633 {
634 if (!shash_find(&port->bindings, vlan)) {
635 ctl_fatal("no binding for vlan %s", vlan);
636 }
637
638 shash_find_and_delete(&port->bindings, vlan);
639 }
640
641 static struct vteprec_physical_locator *
642 find_ploc(struct vtep_ctl_context *vtepctl_ctx, const char *encap,
643 const char *dst_ip)
644 {
645 struct vteprec_physical_locator *ploc;
646 char *name = xasprintf("%s+%s", encap, dst_ip);
647
648 ovs_assert(vtepctl_ctx->cache_valid);
649
650 ploc = shash_find_data(&vtepctl_ctx->plocs, name);
651 free(name);
652
653 return ploc;
654 }
655
656 static void
657 add_ploc_to_cache(struct vtep_ctl_context *vtepctl_ctx,
658 struct vteprec_physical_locator *ploc)
659 {
660 char *name = xasprintf("%s+%s", ploc->encapsulation_type, ploc->dst_ip);
661 struct vteprec_physical_locator *orig_ploc;
662
663 orig_ploc = find_ploc(vtepctl_ctx, ploc->encapsulation_type, ploc->dst_ip);
664 if (!orig_ploc) {
665 shash_add(&vtepctl_ctx->plocs, name, ploc);
666 }
667
668 free(name);
669 }
670
671 static void
672 add_ploc_to_mcast_mac(struct vtep_ctl_mcast_mac *mcast_mac,
673 struct vteprec_physical_locator *ploc_cfg)
674 {
675 struct vtep_ctl_ploc *ploc;
676
677 ploc = xmalloc(sizeof *ploc);
678 ploc->ploc_cfg = ploc_cfg;
679 list_push_back(&mcast_mac->locators, &ploc->locators_node);
680 }
681
682 static void
683 del_ploc_from_mcast_mac(struct vtep_ctl_mcast_mac *mcast_mac,
684 struct vteprec_physical_locator *ploc_cfg)
685 {
686 struct vtep_ctl_ploc *ploc;
687
688 LIST_FOR_EACH (ploc, locators_node, &mcast_mac->locators) {
689 if (ploc->ploc_cfg == ploc_cfg) {
690 list_remove(&ploc->locators_node);
691 free(ploc);
692 return;
693 }
694 }
695 }
696
697 static struct vtep_ctl_mcast_mac *
698 add_mcast_mac_to_cache(struct vtep_ctl_context *vtepctl_ctx,
699 struct vtep_ctl_lswitch *ls, const char *mac,
700 struct vteprec_physical_locator_set *ploc_set_cfg,
701 bool local)
702 {
703 struct vtep_ctl_mcast_mac *mcast_mac;
704 struct shash *mcast_shash;
705 size_t i;
706
707 mcast_mac = xmalloc(sizeof *mcast_mac);
708 mcast_shash = local ? &ls->mcast_local : &ls->mcast_remote;
709
710 mcast_mac->ploc_set_cfg = ploc_set_cfg;
711 list_init(&mcast_mac->locators);
712 shash_add(mcast_shash, mac, mcast_mac);
713
714 for (i = 0; i < ploc_set_cfg->n_locators; i++) {
715 struct vteprec_physical_locator *ploc_cfg;
716
717 ploc_cfg = ploc_set_cfg->locators[i];
718 add_ploc_to_mcast_mac(mcast_mac, ploc_cfg);
719 add_ploc_to_cache(vtepctl_ctx, ploc_cfg);
720 }
721
722 return mcast_mac;
723 }
724
725 static void
726 vtep_ctl_context_invalidate_cache(struct ctl_context *ctx)
727 {
728 struct vtep_ctl_context *vtepctl_ctx = vtep_ctl_context_cast(ctx);
729 struct shash_node *node;
730
731 if (!vtepctl_ctx->cache_valid) {
732 return;
733 }
734 vtepctl_ctx->cache_valid = false;
735
736 SHASH_FOR_EACH (node, &vtepctl_ctx->pswitches) {
737 struct vtep_ctl_pswitch *ps = node->data;
738 free(ps->name);
739 free(ps);
740 }
741 shash_destroy(&vtepctl_ctx->pswitches);
742
743 SHASH_FOR_EACH (node, &vtepctl_ctx->ports) {
744 struct vtep_ctl_port *port = node->data;
745 shash_destroy(&port->bindings);
746 }
747 shash_destroy_free_data(&vtepctl_ctx->ports);
748
749 SHASH_FOR_EACH (node, &vtepctl_ctx->lswitches) {
750 struct vtep_ctl_lswitch *ls = node->data;
751 struct shash_node *node2, *next_node2;
752
753 shash_destroy(&ls->ucast_local);
754 shash_destroy(&ls->ucast_remote);
755
756 SHASH_FOR_EACH_SAFE (node2, next_node2, &ls->mcast_local) {
757 struct vtep_ctl_mcast_mac *mcast_mac = node2->data;
758 struct vtep_ctl_ploc *ploc, *next_ploc;
759
760 LIST_FOR_EACH_SAFE (ploc, next_ploc, locators_node,
761 &mcast_mac->locators) {
762 free(ploc);
763 }
764 free(mcast_mac);
765 }
766 shash_destroy(&ls->mcast_local);
767
768 SHASH_FOR_EACH_SAFE (node2, next_node2, &ls->mcast_remote) {
769 struct vtep_ctl_mcast_mac *mcast_mac = node2->data;
770 struct vtep_ctl_ploc *ploc, *next_ploc;
771
772 LIST_FOR_EACH_SAFE (ploc, next_ploc, locators_node,
773 &mcast_mac->locators) {
774 free(ploc);
775 }
776 free(mcast_mac);
777 }
778 shash_destroy(&ls->mcast_remote);
779
780 free(ls->name);
781 free(ls);
782 }
783 shash_destroy(&vtepctl_ctx->lswitches);
784 shash_destroy(&vtepctl_ctx->plocs);
785 }
786
787 static void
788 pre_get_info(struct ctl_context *ctx)
789 {
790 ovsdb_idl_add_column(ctx->idl, &vteprec_global_col_switches);
791
792 ovsdb_idl_add_column(ctx->idl, &vteprec_physical_switch_col_name);
793 ovsdb_idl_add_column(ctx->idl, &vteprec_physical_switch_col_ports);
794 ovsdb_idl_add_column(ctx->idl, &vteprec_physical_switch_col_tunnels);
795
796 ovsdb_idl_add_column(ctx->idl, &vteprec_physical_port_col_name);
797 ovsdb_idl_add_column(ctx->idl, &vteprec_physical_port_col_vlan_bindings);
798
799 ovsdb_idl_add_column(ctx->idl, &vteprec_logical_switch_col_name);
800
801 ovsdb_idl_add_column(ctx->idl, &vteprec_ucast_macs_local_col_MAC);
802 ovsdb_idl_add_column(ctx->idl, &vteprec_ucast_macs_local_col_locator);
803 ovsdb_idl_add_column(ctx->idl,
804 &vteprec_ucast_macs_local_col_logical_switch);
805
806 ovsdb_idl_add_column(ctx->idl, &vteprec_ucast_macs_remote_col_MAC);
807 ovsdb_idl_add_column(ctx->idl, &vteprec_ucast_macs_remote_col_locator);
808 ovsdb_idl_add_column(ctx->idl,
809 &vteprec_ucast_macs_remote_col_logical_switch);
810
811 ovsdb_idl_add_column(ctx->idl, &vteprec_mcast_macs_local_col_MAC);
812 ovsdb_idl_add_column(ctx->idl,
813 &vteprec_mcast_macs_local_col_locator_set);
814 ovsdb_idl_add_column(ctx->idl,
815 &vteprec_mcast_macs_local_col_logical_switch);
816
817 ovsdb_idl_add_column(ctx->idl, &vteprec_mcast_macs_remote_col_MAC);
818 ovsdb_idl_add_column(ctx->idl,
819 &vteprec_mcast_macs_remote_col_locator_set);
820 ovsdb_idl_add_column(ctx->idl,
821 &vteprec_mcast_macs_remote_col_logical_switch);
822
823 ovsdb_idl_add_column(ctx->idl,
824 &vteprec_physical_locator_set_col_locators);
825
826 ovsdb_idl_add_column(ctx->idl,
827 &vteprec_physical_locator_col_dst_ip);
828 ovsdb_idl_add_column(ctx->idl,
829 &vteprec_physical_locator_col_encapsulation_type);
830
831 ovsdb_idl_add_column(ctx->idl, &vteprec_tunnel_col_local);
832 ovsdb_idl_add_column(ctx->idl, &vteprec_tunnel_col_remote);
833 }
834
835 static void
836 vtep_ctl_context_populate_cache(struct ctl_context *ctx)
837 {
838 struct vtep_ctl_context *vtepctl_ctx = vtep_ctl_context_cast(ctx);
839 const struct vteprec_global *vtep_global = vtepctl_ctx->vtep_global;
840 const struct vteprec_logical_switch *ls_cfg;
841 const struct vteprec_ucast_macs_local *ucast_local_cfg;
842 const struct vteprec_ucast_macs_remote *ucast_remote_cfg;
843 const struct vteprec_mcast_macs_local *mcast_local_cfg;
844 const struct vteprec_mcast_macs_remote *mcast_remote_cfg;
845 const struct vteprec_tunnel *tunnel_cfg;
846 struct sset pswitches, ports, lswitches;
847 size_t i;
848
849 if (vtepctl_ctx->cache_valid) {
850 /* Cache is already populated. */
851 return;
852 }
853 vtepctl_ctx->cache_valid = true;
854 shash_init(&vtepctl_ctx->pswitches);
855 shash_init(&vtepctl_ctx->ports);
856 shash_init(&vtepctl_ctx->lswitches);
857 shash_init(&vtepctl_ctx->plocs);
858
859 sset_init(&pswitches);
860 sset_init(&ports);
861 for (i = 0; i < vtep_global->n_switches; i++) {
862 struct vteprec_physical_switch *ps_cfg = vtep_global->switches[i];
863 size_t j;
864
865 if (!sset_add(&pswitches, ps_cfg->name)) {
866 VLOG_WARN("%s: database contains duplicate physical switch name",
867 ps_cfg->name);
868 continue;
869 }
870 add_pswitch_to_cache(vtepctl_ctx, ps_cfg);
871
872 for (j = 0; j < ps_cfg->n_ports; j++) {
873 struct vteprec_physical_port *port_cfg = ps_cfg->ports[j];
874
875 if (!sset_add(&ports, port_cfg->name)) {
876 /* Duplicate port name. (We will warn about that later.) */
877 continue;
878 }
879 }
880 }
881 sset_destroy(&pswitches);
882 sset_destroy(&ports);
883
884 sset_init(&lswitches);
885 VTEPREC_LOGICAL_SWITCH_FOR_EACH (ls_cfg, ctx->idl) {
886 if (!sset_add(&lswitches, ls_cfg->name)) {
887 VLOG_WARN("%s: database contains duplicate logical switch name",
888 ls_cfg->name);
889 continue;
890 }
891 add_lswitch_to_cache(vtepctl_ctx, ls_cfg);
892 }
893 sset_destroy(&lswitches);
894
895 VTEPREC_UCAST_MACS_LOCAL_FOR_EACH (ucast_local_cfg, ctx->idl) {
896 struct vtep_ctl_lswitch *ls;
897
898 if (!ucast_local_cfg->logical_switch) {
899 continue;
900 }
901 ls = find_lswitch(vtepctl_ctx, ucast_local_cfg->logical_switch->name,
902 false);
903 if (!ls) {
904 continue;
905 }
906
907 if (ucast_local_cfg->locator) {
908 add_ploc_to_cache(vtepctl_ctx, ucast_local_cfg->locator);
909 }
910
911 shash_add(&ls->ucast_local, ucast_local_cfg->MAC, ucast_local_cfg);
912 }
913
914 VTEPREC_UCAST_MACS_REMOTE_FOR_EACH (ucast_remote_cfg, ctx->idl) {
915 struct vtep_ctl_lswitch *ls;
916
917 if (!ucast_remote_cfg->logical_switch) {
918 continue;
919 }
920 ls = find_lswitch(vtepctl_ctx, ucast_remote_cfg->logical_switch->name,
921 false);
922 if (!ls) {
923 continue;
924 }
925
926 if (ucast_remote_cfg->locator) {
927 add_ploc_to_cache(vtepctl_ctx, ucast_remote_cfg->locator);
928 }
929
930 shash_add(&ls->ucast_remote, ucast_remote_cfg->MAC, ucast_remote_cfg);
931 }
932
933 VTEPREC_MCAST_MACS_LOCAL_FOR_EACH (mcast_local_cfg, ctx->idl) {
934 struct vtep_ctl_mcast_mac *mcast_mac;
935 struct vtep_ctl_lswitch *ls;
936
937 if (!mcast_local_cfg->logical_switch) {
938 continue;
939 }
940 ls = find_lswitch(vtepctl_ctx, mcast_local_cfg->logical_switch->name,
941 false);
942 if (!ls) {
943 continue;
944 }
945
946 mcast_mac = add_mcast_mac_to_cache(vtepctl_ctx, ls, mcast_local_cfg->MAC,
947 mcast_local_cfg->locator_set,
948 true);
949 mcast_mac->local_cfg = mcast_local_cfg;
950 }
951
952 VTEPREC_MCAST_MACS_REMOTE_FOR_EACH (mcast_remote_cfg, ctx->idl) {
953 struct vtep_ctl_mcast_mac *mcast_mac;
954 struct vtep_ctl_lswitch *ls;
955
956 if (!mcast_remote_cfg->logical_switch) {
957 continue;
958 }
959 ls = find_lswitch(vtepctl_ctx, mcast_remote_cfg->logical_switch->name,
960 false);
961 if (!ls) {
962 continue;
963 }
964
965 mcast_mac = add_mcast_mac_to_cache(vtepctl_ctx, ls, mcast_remote_cfg->MAC,
966 mcast_remote_cfg->locator_set,
967 false);
968 mcast_mac->remote_cfg = mcast_remote_cfg;
969 }
970
971 VTEPREC_TUNNEL_FOR_EACH (tunnel_cfg, ctx->idl) {
972 if (tunnel_cfg->local) {
973 add_ploc_to_cache(vtepctl_ctx, tunnel_cfg->local);
974 }
975 if (tunnel_cfg->remote) {
976 add_ploc_to_cache(vtepctl_ctx, tunnel_cfg->remote);
977 }
978 }
979
980 sset_init(&pswitches);
981 for (i = 0; i < vtep_global->n_switches; i++) {
982 struct vteprec_physical_switch *ps_cfg = vtep_global->switches[i];
983 struct vtep_ctl_pswitch *ps;
984 size_t j;
985
986 if (!sset_add(&pswitches, ps_cfg->name)) {
987 continue;
988 }
989 ps = shash_find_data(&vtepctl_ctx->pswitches, ps_cfg->name);
990 for (j = 0; j < ps_cfg->n_ports; j++) {
991 struct vteprec_physical_port *port_cfg = ps_cfg->ports[j];
992 struct vtep_ctl_port *port;
993 size_t k;
994
995 port = shash_find_data(&vtepctl_ctx->ports, port_cfg->name);
996 if (port) {
997 if (port_cfg == port->port_cfg) {
998 VLOG_WARN("%s: port is in multiple physical switches "
999 "(%s and %s)",
1000 port_cfg->name, ps->name, port->ps->name);
1001 } else {
1002 /* Log as an error because this violates the database's
1003 * uniqueness constraints, so the database server shouldn't
1004 * have allowed it. */
1005 VLOG_ERR("%s: database contains duplicate port name",
1006 port_cfg->name);
1007 }
1008 continue;
1009 }
1010
1011 port = add_port_to_cache(vtepctl_ctx, ps, port_cfg);
1012
1013 for (k = 0; k < port_cfg->n_vlan_bindings; k++) {
1014 struct vteprec_logical_switch *ls_cfg;
1015 struct vtep_ctl_lswitch *ls;
1016 char *vlan;
1017
1018 vlan = xasprintf("%"PRId64, port_cfg->key_vlan_bindings[k]);
1019 if (shash_find(&port->bindings, vlan)) {
1020 ctl_fatal("multiple bindings for vlan %s", vlan);
1021 }
1022
1023 ls_cfg = port_cfg->value_vlan_bindings[k];
1024 ls = find_lswitch(vtepctl_ctx, ls_cfg->name, true);
1025
1026 shash_add_nocopy(&port->bindings, vlan, ls);
1027 }
1028 }
1029 }
1030 sset_destroy(&pswitches);
1031 }
1032
1033 static struct vtep_ctl_pswitch *
1034 find_pswitch(struct vtep_ctl_context *vtepctl_ctx, const char *name, bool must_exist)
1035 {
1036 struct vtep_ctl_pswitch *ps;
1037
1038 ovs_assert(vtepctl_ctx->cache_valid);
1039
1040 ps = shash_find_data(&vtepctl_ctx->pswitches, name);
1041 if (must_exist && !ps) {
1042 ctl_fatal("no physical switch named %s", name);
1043 }
1044 vteprec_global_verify_switches(vtepctl_ctx->vtep_global);
1045 return ps;
1046 }
1047
1048 static struct vtep_ctl_port *
1049 find_port(struct vtep_ctl_context *vtepctl_ctx, const char *ps_name,
1050 const char *port_name, bool must_exist)
1051 {
1052 char *cache_name = xasprintf("%s+%s", ps_name, port_name);
1053 struct vtep_ctl_port *port;
1054
1055 ovs_assert(vtepctl_ctx->cache_valid);
1056
1057 port = shash_find_data(&vtepctl_ctx->ports, cache_name);
1058 if (port && !strcmp(port_name, port->ps->name)) {
1059 port = NULL;
1060 }
1061 free(cache_name);
1062 if (must_exist && !port) {
1063 ctl_fatal("no port named %s", port_name);
1064 }
1065 verify_ports(vtepctl_ctx);
1066 return port;
1067 }
1068
1069 static void
1070 pswitch_insert_port(const struct vteprec_physical_switch *ps,
1071 struct vteprec_physical_port *port)
1072 {
1073 struct vteprec_physical_port **ports;
1074 size_t i;
1075
1076 ports = xmalloc(sizeof *ps->ports * (ps->n_ports + 1));
1077 for (i = 0; i < ps->n_ports; i++) {
1078 ports[i] = ps->ports[i];
1079 }
1080 ports[ps->n_ports] = port;
1081 vteprec_physical_switch_set_ports(ps, ports, ps->n_ports + 1);
1082 free(ports);
1083 }
1084
1085 static void
1086 pswitch_delete_port(const struct vteprec_physical_switch *ps,
1087 const struct vteprec_physical_port *port)
1088 {
1089 struct vteprec_physical_port **ports;
1090 size_t i, n;
1091
1092 ports = xmalloc(sizeof *ps->ports * ps->n_ports);
1093 for (i = n = 0; i < ps->n_ports; i++) {
1094 if (ps->ports[i] != port) {
1095 ports[n++] = ps->ports[i];
1096 }
1097 }
1098 vteprec_physical_switch_set_ports(ps, ports, n);
1099 free(ports);
1100 }
1101
1102 static void
1103 vtep_insert_pswitch(const struct vteprec_global *vtep_global,
1104 struct vteprec_physical_switch *ps)
1105 {
1106 struct vteprec_physical_switch **pswitches;
1107 size_t i;
1108
1109 pswitches = xmalloc(sizeof *vtep_global->switches
1110 * (vtep_global->n_switches + 1));
1111 for (i = 0; i < vtep_global->n_switches; i++) {
1112 pswitches[i] = vtep_global->switches[i];
1113 }
1114 pswitches[vtep_global->n_switches] = ps;
1115 vteprec_global_set_switches(vtep_global, pswitches,
1116 vtep_global->n_switches + 1);
1117 free(pswitches);
1118 }
1119
1120 static void
1121 cmd_add_ps(struct ctl_context *ctx)
1122 {
1123 struct vtep_ctl_context *vtepctl_ctx = vtep_ctl_context_cast(ctx);
1124 const char *ps_name = ctx->argv[1];
1125 bool may_exist = shash_find(&ctx->options, "--may-exist") != NULL;
1126 struct vteprec_physical_switch *ps;
1127
1128 vtep_ctl_context_populate_cache(ctx);
1129 if (find_pswitch(vtepctl_ctx, ps_name, false)) {
1130 if (!may_exist) {
1131 ctl_fatal("cannot create physical switch %s because it "
1132 "already exists", ps_name);
1133 }
1134 return;
1135 }
1136
1137 ps = vteprec_physical_switch_insert(ctx->txn);
1138 vteprec_physical_switch_set_name(ps, ps_name);
1139
1140 vtep_insert_pswitch(vtepctl_ctx->vtep_global, ps);
1141
1142 vtep_ctl_context_invalidate_cache(ctx);
1143 }
1144
1145 static void
1146 del_port(struct vtep_ctl_context *vtepctl_ctx, struct vtep_ctl_port *port)
1147 {
1148 pswitch_delete_port(port->ps->ps_cfg, port->port_cfg);
1149 del_cached_port(vtepctl_ctx, port);
1150 }
1151
1152 static void
1153 del_pswitch(struct vtep_ctl_context *vtepctl_ctx, struct vtep_ctl_pswitch *ps)
1154 {
1155 struct vtep_ctl_port *port, *next_port;
1156
1157 LIST_FOR_EACH_SAFE (port, next_port, ports_node, &ps->ports) {
1158 del_port(vtepctl_ctx, port);
1159 }
1160
1161 del_cached_pswitch(vtepctl_ctx, ps);
1162 }
1163
1164 static void
1165 cmd_del_ps(struct ctl_context *ctx)
1166 {
1167 struct vtep_ctl_context *vtepctl_ctx = vtep_ctl_context_cast(ctx);
1168 bool must_exist = !shash_find(&ctx->options, "--if-exists");
1169 struct vtep_ctl_pswitch *ps;
1170
1171 vtep_ctl_context_populate_cache(ctx);
1172 ps = find_pswitch(vtepctl_ctx, ctx->argv[1], must_exist);
1173 if (ps) {
1174 del_pswitch(vtepctl_ctx, ps);
1175 }
1176 }
1177
1178 static void
1179 output_sorted(struct svec *svec, struct ds *output)
1180 {
1181 const char *name;
1182 size_t i;
1183
1184 svec_sort(svec);
1185 SVEC_FOR_EACH (i, name, svec) {
1186 ds_put_format(output, "%s\n", name);
1187 }
1188 }
1189
1190 static void
1191 cmd_list_ps(struct ctl_context *ctx)
1192 {
1193 struct vtep_ctl_context *vtepctl_ctx = vtep_ctl_context_cast(ctx);
1194 struct shash_node *node;
1195 struct svec pswitches;
1196
1197 vtep_ctl_context_populate_cache(ctx);
1198
1199 svec_init(&pswitches);
1200 SHASH_FOR_EACH (node, &vtepctl_ctx->pswitches) {
1201 struct vtep_ctl_pswitch *ps = node->data;
1202
1203 svec_add(&pswitches, ps->name);
1204 }
1205 output_sorted(&pswitches, &ctx->output);
1206 svec_destroy(&pswitches);
1207 }
1208
1209 static void
1210 cmd_ps_exists(struct ctl_context *ctx)
1211 {
1212 struct vtep_ctl_context *vtepctl_ctx = vtep_ctl_context_cast(ctx);
1213
1214 vtep_ctl_context_populate_cache(ctx);
1215 if (!find_pswitch(vtepctl_ctx, ctx->argv[1], false)) {
1216 vtep_ctl_exit(2);
1217 }
1218 }
1219
1220 static void
1221 cmd_list_ports(struct ctl_context *ctx)
1222 {
1223 struct vtep_ctl_context *vtepctl_ctx = vtep_ctl_context_cast(ctx);
1224 struct vtep_ctl_pswitch *ps;
1225 struct vtep_ctl_port *port;
1226 struct svec ports;
1227
1228 vtep_ctl_context_populate_cache(ctx);
1229 ps = find_pswitch(vtepctl_ctx, ctx->argv[1], true);
1230 vteprec_physical_switch_verify_ports(ps->ps_cfg);
1231
1232 svec_init(&ports);
1233 LIST_FOR_EACH (port, ports_node, &ps->ports) {
1234 if (strcmp(port->port_cfg->name, ps->name)) {
1235 svec_add(&ports, port->port_cfg->name);
1236 }
1237 }
1238 output_sorted(&ports, &ctx->output);
1239 svec_destroy(&ports);
1240 }
1241
1242 static void
1243 add_port(struct ctl_context *ctx, const char *ps_name,
1244 const char *port_name, bool may_exist)
1245 {
1246 struct vtep_ctl_context *vtepctl_ctx = vtep_ctl_context_cast(ctx);
1247 struct vtep_ctl_port *vtep_ctl_port;
1248 struct vtep_ctl_pswitch *ps;
1249 struct vteprec_physical_port *port;
1250
1251 vtep_ctl_context_populate_cache(ctx);
1252
1253 vtep_ctl_port = find_port(vtepctl_ctx, ps_name, port_name, false);
1254 if (vtep_ctl_port) {
1255 if (!may_exist) {
1256 ctl_fatal("cannot create a port named %s on %s because a "
1257 "port with that name already exists",
1258 port_name, ps_name);
1259 }
1260 return;
1261 }
1262
1263 ps = find_pswitch(vtepctl_ctx, ps_name, true);
1264
1265 port = vteprec_physical_port_insert(ctx->txn);
1266 vteprec_physical_port_set_name(port, port_name);
1267
1268 pswitch_insert_port(ps->ps_cfg, port);
1269
1270 add_port_to_cache(vtepctl_ctx, ps, port);
1271 }
1272
1273 static void
1274 cmd_add_port(struct ctl_context *ctx)
1275 {
1276 bool may_exist = shash_find(&ctx->options, "--may-exist") != NULL;
1277
1278 add_port(ctx, ctx->argv[1], ctx->argv[2], may_exist);
1279 }
1280
1281 static void
1282 cmd_del_port(struct ctl_context *ctx)
1283 {
1284 struct vtep_ctl_context *vtepctl_ctx = vtep_ctl_context_cast(ctx);
1285 bool must_exist = !shash_find(&ctx->options, "--if-exists");
1286 struct vtep_ctl_port *port;
1287
1288 vtep_ctl_context_populate_cache(ctx);
1289
1290 port = find_port(vtepctl_ctx, ctx->argv[1], ctx->argv[2], must_exist);
1291 if (port) {
1292 if (ctx->argc == 3) {
1293 struct vtep_ctl_pswitch *ps;
1294
1295 ps = find_pswitch(vtepctl_ctx, ctx->argv[1], true);
1296 if (port->ps != ps) {
1297 ctl_fatal("physical switch %s does not have a port %s",
1298 ctx->argv[1], ctx->argv[2]);
1299 }
1300 }
1301
1302 del_port(vtepctl_ctx, port);
1303 }
1304 }
1305
1306 static struct vtep_ctl_lswitch *
1307 find_lswitch(struct vtep_ctl_context *vtepctl_ctx,
1308 const char *name, bool must_exist)
1309 {
1310 struct vtep_ctl_lswitch *ls;
1311
1312 ovs_assert(vtepctl_ctx->cache_valid);
1313
1314 ls = shash_find_data(&vtepctl_ctx->lswitches, name);
1315 if (must_exist && !ls) {
1316 ctl_fatal("no logical switch named %s", name);
1317 }
1318 return ls;
1319 }
1320
1321 static void
1322 cmd_add_ls(struct ctl_context *ctx)
1323 {
1324 struct vtep_ctl_context *vtepctl_ctx = vtep_ctl_context_cast(ctx);
1325 const char *ls_name = ctx->argv[1];
1326 bool may_exist = shash_find(&ctx->options, "--may-exist") != NULL;
1327 struct vteprec_logical_switch *ls;
1328
1329 vtep_ctl_context_populate_cache(ctx);
1330 if (find_lswitch(vtepctl_ctx, ls_name, false)) {
1331 if (!may_exist) {
1332 ctl_fatal("cannot create logical switch %s because it "
1333 "already exists", ls_name);
1334 }
1335 return;
1336 }
1337
1338 ls = vteprec_logical_switch_insert(ctx->txn);
1339 vteprec_logical_switch_set_name(ls, ls_name);
1340
1341 vtep_ctl_context_invalidate_cache(ctx);
1342 }
1343
1344 static void
1345 del_lswitch(struct vtep_ctl_context *vtepctl_ctx, struct vtep_ctl_lswitch *ls)
1346 {
1347 del_cached_lswitch(vtepctl_ctx, ls);
1348 }
1349
1350 static void
1351 cmd_del_ls(struct ctl_context *ctx)
1352 {
1353 struct vtep_ctl_context *vtepctl_ctx = vtep_ctl_context_cast(ctx);
1354 bool must_exist = !shash_find(&ctx->options, "--if-exists");
1355 struct vtep_ctl_lswitch *ls;
1356
1357 vtep_ctl_context_populate_cache(ctx);
1358 ls = find_lswitch(vtepctl_ctx, ctx->argv[1], must_exist);
1359 if (ls) {
1360 del_lswitch(vtepctl_ctx, ls);
1361 }
1362 }
1363
1364 static void
1365 cmd_list_ls(struct ctl_context *ctx)
1366 {
1367 struct vtep_ctl_context *vtepctl_ctx = vtep_ctl_context_cast(ctx);
1368 struct shash_node *node;
1369 struct svec lswitches;
1370
1371 vtep_ctl_context_populate_cache(ctx);
1372
1373 svec_init(&lswitches);
1374 SHASH_FOR_EACH (node, &vtepctl_ctx->lswitches) {
1375 struct vtep_ctl_lswitch *ls = node->data;
1376
1377 svec_add(&lswitches, ls->name);
1378 }
1379 output_sorted(&lswitches, &ctx->output);
1380 svec_destroy(&lswitches);
1381 }
1382
1383 static void
1384 cmd_ls_exists(struct ctl_context *ctx)
1385 {
1386 struct vtep_ctl_context *vtepctl_ctx = vtep_ctl_context_cast(ctx);
1387
1388 vtep_ctl_context_populate_cache(ctx);
1389 if (!find_lswitch(vtepctl_ctx, ctx->argv[1], false)) {
1390 vtep_ctl_exit(2);
1391 }
1392 }
1393
1394 static void
1395 cmd_list_bindings(struct ctl_context *ctx)
1396 {
1397 struct vtep_ctl_context *vtepctl_ctx = vtep_ctl_context_cast(ctx);
1398 const struct shash_node *node;
1399 struct vtep_ctl_port *port;
1400 struct svec bindings;
1401
1402 vtep_ctl_context_populate_cache(ctx);
1403 port = find_port(vtepctl_ctx, ctx->argv[1], ctx->argv[2], true);
1404
1405 svec_init(&bindings);
1406 SHASH_FOR_EACH (node, &port->bindings) {
1407 struct vtep_ctl_lswitch *lswitch = node->data;
1408 char *binding;
1409
1410 binding = xasprintf("%04lld %s", strtoll(node->name, NULL, 0),
1411 lswitch->name);
1412 svec_add_nocopy(&bindings, binding);
1413 }
1414 output_sorted(&bindings, &ctx->output);
1415 svec_destroy(&bindings);
1416 }
1417
1418 static void
1419 cmd_bind_ls(struct ctl_context *ctx)
1420 {
1421 struct vtep_ctl_context *vtepctl_ctx = vtep_ctl_context_cast(ctx);
1422 struct vtep_ctl_lswitch *ls;
1423 struct vtep_ctl_port *port;
1424 const char *vlan;
1425
1426 vtep_ctl_context_populate_cache(ctx);
1427
1428 port = find_port(vtepctl_ctx, ctx->argv[1], ctx->argv[2], true);
1429 vlan = ctx->argv[3];
1430 ls = find_lswitch(vtepctl_ctx, ctx->argv[4], true);
1431
1432 add_ls_binding_to_cache(port, vlan, ls);
1433 commit_ls_bindings(port);
1434
1435 vtep_ctl_context_invalidate_cache(ctx);
1436 }
1437
1438 static void
1439 cmd_unbind_ls(struct ctl_context *ctx)
1440 {
1441 struct vtep_ctl_context *vtepctl_ctx = vtep_ctl_context_cast(ctx);
1442 struct vtep_ctl_port *port;
1443 const char *vlan;
1444
1445 vtep_ctl_context_populate_cache(ctx);
1446
1447 port = find_port(vtepctl_ctx, ctx->argv[1], ctx->argv[2], true);
1448 vlan = ctx->argv[3];
1449
1450 del_cached_ls_binding(port, vlan);
1451 commit_ls_bindings(port);
1452
1453 vtep_ctl_context_invalidate_cache(ctx);
1454 }
1455
1456 static void
1457 add_ucast_entry(struct ctl_context *ctx, bool local)
1458 {
1459 struct vtep_ctl_context *vtepctl_ctx = vtep_ctl_context_cast(ctx);
1460 struct vtep_ctl_lswitch *ls;
1461 const char *mac;
1462 const char *encap;
1463 const char *dst_ip;
1464 struct vteprec_physical_locator *ploc_cfg;
1465
1466 vtep_ctl_context_populate_cache(ctx);
1467
1468 ls = find_lswitch(vtepctl_ctx, ctx->argv[1], true);
1469 mac = ctx->argv[2];
1470
1471 if (ctx->argc == 4) {
1472 encap = "vxlan_over_ipv4";
1473 dst_ip = ctx->argv[3];
1474 } else {
1475 encap = ctx->argv[3];
1476 dst_ip = ctx->argv[4];
1477 }
1478
1479 ploc_cfg = find_ploc(vtepctl_ctx, encap, dst_ip);
1480 if (!ploc_cfg) {
1481 ploc_cfg = vteprec_physical_locator_insert(ctx->txn);
1482 vteprec_physical_locator_set_dst_ip(ploc_cfg, dst_ip);
1483 vteprec_physical_locator_set_encapsulation_type(ploc_cfg, encap);
1484
1485 add_ploc_to_cache(vtepctl_ctx, ploc_cfg);
1486 }
1487
1488 if (local) {
1489 struct vteprec_ucast_macs_local *ucast_cfg;
1490
1491 ucast_cfg = shash_find_data(&ls->ucast_local, mac);
1492 if (!ucast_cfg) {
1493 ucast_cfg = vteprec_ucast_macs_local_insert(ctx->txn);
1494 vteprec_ucast_macs_local_set_MAC(ucast_cfg, mac);
1495 vteprec_ucast_macs_local_set_logical_switch(ucast_cfg, ls->ls_cfg);
1496 shash_add(&ls->ucast_local, mac, ucast_cfg);
1497 }
1498 vteprec_ucast_macs_local_set_locator(ucast_cfg, ploc_cfg);
1499 } else {
1500 struct vteprec_ucast_macs_remote *ucast_cfg;
1501
1502 ucast_cfg = shash_find_data(&ls->ucast_remote, mac);
1503 if (!ucast_cfg) {
1504 ucast_cfg = vteprec_ucast_macs_remote_insert(ctx->txn);
1505 vteprec_ucast_macs_remote_set_MAC(ucast_cfg, mac);
1506 vteprec_ucast_macs_remote_set_logical_switch(ucast_cfg, ls->ls_cfg);
1507 shash_add(&ls->ucast_remote, mac, ucast_cfg);
1508 }
1509 vteprec_ucast_macs_remote_set_locator(ucast_cfg, ploc_cfg);
1510 }
1511
1512 vtep_ctl_context_invalidate_cache(ctx);
1513 }
1514
1515 static void
1516 cmd_add_ucast_local(struct ctl_context *ctx)
1517 {
1518 add_ucast_entry(ctx, true);
1519 }
1520
1521 static void
1522 cmd_add_ucast_remote(struct ctl_context *ctx)
1523 {
1524 add_ucast_entry(ctx, false);
1525 }
1526
1527 static void
1528 del_ucast_entry(struct ctl_context *ctx, bool local)
1529 {
1530 struct vtep_ctl_context *vtepctl_ctx = vtep_ctl_context_cast(ctx);
1531 struct vtep_ctl_lswitch *ls;
1532 struct shash *ucast_shash;
1533 struct shash_node *node;
1534
1535 vtep_ctl_context_populate_cache(ctx);
1536
1537 ls = find_lswitch(vtepctl_ctx, ctx->argv[1], true);
1538 ucast_shash = local ? &ls->ucast_local : &ls->ucast_remote;
1539
1540 node = shash_find(ucast_shash, ctx->argv[2]);
1541 if (!node) {
1542 return;
1543 }
1544
1545 if (local) {
1546 struct vteprec_ucast_macs_local *ucast_cfg = node->data;
1547 vteprec_ucast_macs_local_delete(ucast_cfg);
1548 } else {
1549 struct vteprec_ucast_macs_remote *ucast_cfg = node->data;
1550 vteprec_ucast_macs_remote_delete(ucast_cfg);
1551 }
1552 shash_delete(ucast_shash, node);
1553
1554 vtep_ctl_context_invalidate_cache(ctx);
1555 }
1556
1557 static void
1558 cmd_del_ucast_local(struct ctl_context *ctx)
1559 {
1560 del_ucast_entry(ctx, true);
1561 }
1562
1563 static void
1564 cmd_del_ucast_remote(struct ctl_context *ctx)
1565 {
1566 del_ucast_entry(ctx, false);
1567 }
1568
1569 static void
1570 commit_mcast_entries(struct vtep_ctl_mcast_mac *mcast_mac)
1571 {
1572 struct vtep_ctl_ploc *ploc;
1573 struct vteprec_physical_locator **locators = NULL;
1574 size_t n_locators;
1575 int i;
1576
1577 n_locators = list_size(&mcast_mac->locators);
1578 ovs_assert(n_locators);
1579
1580 locators = xmalloc(n_locators * sizeof *locators);
1581
1582 i = 0;
1583 LIST_FOR_EACH (ploc, locators_node, &mcast_mac->locators) {
1584 locators[i] = (struct vteprec_physical_locator *)ploc->ploc_cfg;
1585 i++;
1586 }
1587
1588 vteprec_physical_locator_set_set_locators(mcast_mac->ploc_set_cfg,
1589 locators,
1590 n_locators);
1591
1592 free(locators);
1593 }
1594
1595 static void
1596 add_mcast_entry(struct ctl_context *ctx,
1597 struct vtep_ctl_lswitch *ls, const char *mac,
1598 const char *encap, const char *dst_ip, bool local)
1599 {
1600 struct vtep_ctl_context *vtepctl_ctx = vtep_ctl_context_cast(ctx);
1601 struct shash *mcast_shash;
1602 struct vtep_ctl_mcast_mac *mcast_mac;
1603 struct vteprec_physical_locator *ploc_cfg;
1604 struct vteprec_physical_locator_set *ploc_set_cfg;
1605
1606 mcast_shash = local ? &ls->mcast_local : &ls->mcast_remote;
1607
1608 /* Physical locator sets are immutable, so allocate a new one. */
1609 ploc_set_cfg = vteprec_physical_locator_set_insert(ctx->txn);
1610
1611 mcast_mac = shash_find_data(mcast_shash, mac);
1612 if (!mcast_mac) {
1613 mcast_mac = add_mcast_mac_to_cache(vtepctl_ctx, ls, mac, ploc_set_cfg,
1614 local);
1615
1616 if (local) {
1617 mcast_mac->local_cfg = vteprec_mcast_macs_local_insert(ctx->txn);
1618 vteprec_mcast_macs_local_set_MAC(mcast_mac->local_cfg, mac);
1619 vteprec_mcast_macs_local_set_locator_set(mcast_mac->local_cfg,
1620 ploc_set_cfg);
1621 vteprec_mcast_macs_local_set_logical_switch(mcast_mac->local_cfg,
1622 ls->ls_cfg);
1623 mcast_mac->remote_cfg = NULL;
1624 } else {
1625 mcast_mac->remote_cfg = vteprec_mcast_macs_remote_insert(ctx->txn);
1626 vteprec_mcast_macs_remote_set_MAC(mcast_mac->remote_cfg, mac);
1627 vteprec_mcast_macs_remote_set_locator_set(mcast_mac->remote_cfg,
1628 ploc_set_cfg);
1629 vteprec_mcast_macs_remote_set_logical_switch(mcast_mac->remote_cfg,
1630 ls->ls_cfg);
1631 mcast_mac->local_cfg = NULL;
1632 }
1633 } else {
1634 mcast_mac->ploc_set_cfg = ploc_set_cfg;
1635 if (local) {
1636 vteprec_mcast_macs_local_set_locator_set(mcast_mac->local_cfg,
1637 ploc_set_cfg);
1638 } else {
1639 vteprec_mcast_macs_remote_set_locator_set(mcast_mac->remote_cfg,
1640 ploc_set_cfg);
1641 }
1642 }
1643
1644 ploc_cfg = find_ploc(vtepctl_ctx, encap, dst_ip);
1645 if (!ploc_cfg) {
1646 ploc_cfg = vteprec_physical_locator_insert(ctx->txn);
1647 vteprec_physical_locator_set_dst_ip(ploc_cfg, dst_ip);
1648 vteprec_physical_locator_set_encapsulation_type(ploc_cfg, encap);
1649
1650 add_ploc_to_cache(vtepctl_ctx, ploc_cfg);
1651 }
1652
1653 add_ploc_to_mcast_mac(mcast_mac, ploc_cfg);
1654 commit_mcast_entries(mcast_mac);
1655 }
1656
1657 static void
1658 del_mcast_entry(struct ctl_context *ctx,
1659 struct vtep_ctl_lswitch *ls, const char *mac,
1660 const char *encap, const char *dst_ip, bool local)
1661 {
1662 struct vtep_ctl_context *vtepctl_ctx = vtep_ctl_context_cast(ctx);
1663 struct vtep_ctl_mcast_mac *mcast_mac;
1664 struct shash *mcast_shash;
1665 struct vteprec_physical_locator *ploc_cfg;
1666 struct vteprec_physical_locator_set *ploc_set_cfg;
1667
1668 mcast_shash = local ? &ls->mcast_local : &ls->mcast_remote;
1669
1670 mcast_mac = shash_find_data(mcast_shash, mac);
1671 if (!mcast_mac) {
1672 return;
1673 }
1674
1675 ploc_cfg = find_ploc(vtepctl_ctx, encap, dst_ip);
1676 if (!ploc_cfg) {
1677 /* Couldn't find the physical locator, so just ignore. */
1678 return;
1679 }
1680
1681 /* Physical locator sets are immutable, so allocate a new one. */
1682 ploc_set_cfg = vteprec_physical_locator_set_insert(ctx->txn);
1683 mcast_mac->ploc_set_cfg = ploc_set_cfg;
1684
1685 del_ploc_from_mcast_mac(mcast_mac, ploc_cfg);
1686 if (list_is_empty(&mcast_mac->locators)) {
1687 struct shash_node *node = shash_find(mcast_shash, mac);
1688
1689 vteprec_physical_locator_set_delete(ploc_set_cfg);
1690
1691 if (local) {
1692 vteprec_mcast_macs_local_delete(mcast_mac->local_cfg);
1693 } else {
1694 vteprec_mcast_macs_remote_delete(mcast_mac->remote_cfg);
1695 }
1696
1697 free(node->data);
1698 shash_delete(mcast_shash, node);
1699 } else {
1700 if (local) {
1701 vteprec_mcast_macs_local_set_locator_set(mcast_mac->local_cfg,
1702 ploc_set_cfg);
1703 } else {
1704 vteprec_mcast_macs_remote_set_locator_set(mcast_mac->remote_cfg,
1705 ploc_set_cfg);
1706 }
1707 commit_mcast_entries(mcast_mac);
1708 }
1709 }
1710
1711 static void
1712 add_del_mcast_entry(struct ctl_context *ctx, bool add, bool local)
1713 {
1714 struct vtep_ctl_context *vtepctl_ctx = vtep_ctl_context_cast(ctx);
1715 struct vtep_ctl_lswitch *ls;
1716 const char *mac;
1717 const char *encap;
1718 const char *dst_ip;
1719
1720 vtep_ctl_context_populate_cache(ctx);
1721
1722 ls = find_lswitch(vtepctl_ctx, ctx->argv[1], true);
1723 mac = ctx->argv[2];
1724
1725 if (ctx->argc == 4) {
1726 encap = "vxlan_over_ipv4";
1727 dst_ip = ctx->argv[3];
1728 } else {
1729 encap = ctx->argv[3];
1730 dst_ip = ctx->argv[4];
1731 }
1732
1733 if (add) {
1734 add_mcast_entry(ctx, ls, mac, encap, dst_ip, local);
1735 } else {
1736 del_mcast_entry(ctx, ls, mac, encap, dst_ip, local);
1737 }
1738
1739 vtep_ctl_context_invalidate_cache(ctx);
1740 }
1741
1742 static void
1743 cmd_add_mcast_local(struct ctl_context *ctx)
1744 {
1745 add_del_mcast_entry(ctx, true, true);
1746 }
1747
1748 static void
1749 cmd_add_mcast_remote(struct ctl_context *ctx)
1750 {
1751 add_del_mcast_entry(ctx, true, false);
1752 }
1753
1754 static void
1755 cmd_del_mcast_local(struct ctl_context *ctx)
1756 {
1757 add_del_mcast_entry(ctx, false, true);
1758 }
1759
1760 static void
1761 cmd_del_mcast_remote(struct ctl_context *ctx)
1762 {
1763 add_del_mcast_entry(ctx, false, false);
1764 }
1765
1766 static void
1767 clear_macs(struct ctl_context *ctx, bool local)
1768 {
1769 struct vtep_ctl_context *vtepctl_ctx = vtep_ctl_context_cast(ctx);
1770 struct vtep_ctl_lswitch *ls;
1771 const struct shash_node *node;
1772 struct shash *ucast_shash;
1773 struct shash *mcast_shash;
1774
1775 vtep_ctl_context_populate_cache(ctx);
1776 ls = find_lswitch(vtepctl_ctx, ctx->argv[1], true);
1777
1778 ucast_shash = local ? &ls->ucast_local : &ls->ucast_remote;
1779 mcast_shash = local ? &ls->mcast_local : &ls->mcast_remote;
1780
1781 SHASH_FOR_EACH (node, ucast_shash) {
1782 if (local) {
1783 struct vteprec_ucast_macs_local *ucast_cfg = node->data;
1784 vteprec_ucast_macs_local_delete(ucast_cfg);
1785 } else {
1786 struct vteprec_ucast_macs_remote *ucast_cfg = node->data;
1787 vteprec_ucast_macs_remote_delete(ucast_cfg);
1788 }
1789 }
1790
1791 SHASH_FOR_EACH (node, mcast_shash) {
1792 struct vtep_ctl_mcast_mac *mcast_mac = node->data;
1793 if (local) {
1794 vteprec_mcast_macs_local_delete(mcast_mac->local_cfg);
1795 } else {
1796 vteprec_mcast_macs_remote_delete(mcast_mac->remote_cfg);
1797 }
1798 }
1799
1800 vtep_ctl_context_invalidate_cache(ctx);
1801 }
1802
1803 static void
1804 cmd_clear_local_macs(struct ctl_context *ctx)
1805 {
1806 clear_macs(ctx, true);
1807 }
1808
1809 static void
1810 cmd_clear_remote_macs(struct ctl_context *ctx)
1811 {
1812 clear_macs(ctx, false);
1813 }
1814
1815 static void
1816 list_macs(struct ctl_context *ctx, bool local)
1817 {
1818 struct vtep_ctl_context *vtepctl_ctx = vtep_ctl_context_cast(ctx);
1819 struct vtep_ctl_lswitch *ls;
1820 const struct shash_node *node;
1821 struct shash *ucast_shash;
1822 struct svec ucast_macs;
1823 struct shash *mcast_shash;
1824 struct svec mcast_macs;
1825
1826 vtep_ctl_context_populate_cache(ctx);
1827 ls = find_lswitch(vtepctl_ctx, ctx->argv[1], true);
1828
1829 ucast_shash = local ? &ls->ucast_local : &ls->ucast_remote;
1830 mcast_shash = local ? &ls->mcast_local : &ls->mcast_remote;
1831
1832 svec_init(&ucast_macs);
1833 SHASH_FOR_EACH (node, ucast_shash) {
1834 struct vteprec_ucast_macs_local *ucast_local = node->data;
1835 struct vteprec_ucast_macs_remote *ucast_remote = node->data;
1836 struct vteprec_physical_locator *ploc_cfg;
1837 char *entry;
1838
1839 ploc_cfg = local ? ucast_local->locator : ucast_remote->locator;
1840
1841 entry = xasprintf(" %s -> %s/%s", node->name,
1842 ploc_cfg->encapsulation_type, ploc_cfg->dst_ip);
1843 svec_add_nocopy(&ucast_macs, entry);
1844 }
1845 ds_put_format(&ctx->output, "ucast-mac-%s\n", local ? "local" : "remote");
1846 output_sorted(&ucast_macs, &ctx->output);
1847 ds_put_char(&ctx->output, '\n');
1848 svec_destroy(&ucast_macs);
1849
1850 svec_init(&mcast_macs);
1851 SHASH_FOR_EACH (node, mcast_shash) {
1852 struct vtep_ctl_mcast_mac *mcast_mac = node->data;
1853 struct vtep_ctl_ploc *ploc;
1854 char *entry;
1855
1856 LIST_FOR_EACH (ploc, locators_node, &mcast_mac->locators) {
1857 entry = xasprintf(" %s -> %s/%s", node->name,
1858 ploc->ploc_cfg->encapsulation_type,
1859 ploc->ploc_cfg->dst_ip);
1860 svec_add_nocopy(&mcast_macs, entry);
1861 }
1862 }
1863 ds_put_format(&ctx->output, "mcast-mac-%s\n", local ? "local" : "remote");
1864 output_sorted(&mcast_macs, &ctx->output);
1865 ds_put_char(&ctx->output, '\n');
1866 svec_destroy(&mcast_macs);
1867 }
1868
1869 static void
1870 cmd_list_local_macs(struct ctl_context *ctx)
1871 {
1872 list_macs(ctx, true);
1873 }
1874
1875 static void
1876 cmd_list_remote_macs(struct ctl_context *ctx)
1877 {
1878 list_macs(ctx, false);
1879 }
1880
1881 static void
1882 verify_managers(const struct vteprec_global *vtep_global)
1883 {
1884 size_t i;
1885
1886 vteprec_global_verify_managers(vtep_global);
1887
1888 for (i = 0; i < vtep_global->n_managers; ++i) {
1889 const struct vteprec_manager *mgr = vtep_global->managers[i];
1890
1891 vteprec_manager_verify_target(mgr);
1892 }
1893 }
1894
1895 static void
1896 pre_manager(struct ctl_context *ctx)
1897 {
1898 ovsdb_idl_add_column(ctx->idl, &vteprec_global_col_managers);
1899 ovsdb_idl_add_column(ctx->idl, &vteprec_manager_col_target);
1900 }
1901
1902 static void
1903 cmd_get_manager(struct ctl_context *ctx)
1904 {
1905 struct vtep_ctl_context *vtepctl_ctx = vtep_ctl_context_cast(ctx);
1906 const struct vteprec_global *vtep_global = vtepctl_ctx->vtep_global;
1907 struct svec targets;
1908 size_t i;
1909
1910 verify_managers(vtep_global);
1911
1912 /* Print the targets in sorted order for reproducibility. */
1913 svec_init(&targets);
1914
1915 for (i = 0; i < vtep_global->n_managers; i++) {
1916 svec_add(&targets, vtep_global->managers[i]->target);
1917 }
1918
1919 svec_sort_unique(&targets);
1920 for (i = 0; i < targets.n; i++) {
1921 ds_put_format(&ctx->output, "%s\n", targets.names[i]);
1922 }
1923 svec_destroy(&targets);
1924 }
1925
1926 static void
1927 delete_managers(const struct vtep_ctl_context *vtepctl_ctx)
1928 {
1929 const struct vteprec_global *vtep_global = vtepctl_ctx->vtep_global;
1930 size_t i;
1931
1932 /* Delete Manager rows pointed to by 'managers' column. */
1933 for (i = 0; i < vtep_global->n_managers; i++) {
1934 vteprec_manager_delete(vtep_global->managers[i]);
1935 }
1936
1937 /* Delete 'Manager' row refs in 'managers' column. */
1938 vteprec_global_set_managers(vtep_global, NULL, 0);
1939 }
1940
1941 static void
1942 cmd_del_manager(struct ctl_context *ctx)
1943 {
1944 struct vtep_ctl_context *vtepctl_ctx = vtep_ctl_context_cast(ctx);
1945 const struct vteprec_global *vtep_global = vtepctl_ctx->vtep_global;
1946
1947 verify_managers(vtep_global);
1948 delete_managers(vtepctl_ctx);
1949 }
1950
1951 static void
1952 insert_managers(struct vtep_ctl_context *vtepctl_ctx, char *targets[], size_t n)
1953 {
1954 struct vteprec_manager **managers;
1955 size_t i;
1956
1957 /* Insert each manager in a new row in Manager table. */
1958 managers = xmalloc(n * sizeof *managers);
1959 for (i = 0; i < n; i++) {
1960 if (stream_verify_name(targets[i]) && pstream_verify_name(targets[i])) {
1961 VLOG_WARN("target type \"%s\" is possibly erroneous", targets[i]);
1962 }
1963 managers[i] = vteprec_manager_insert(vtepctl_ctx->base.txn);
1964 vteprec_manager_set_target(managers[i], targets[i]);
1965 }
1966
1967 /* Store uuids of new Manager rows in 'managers' column. */
1968 vteprec_global_set_managers(vtepctl_ctx->vtep_global, managers, n);
1969 free(managers);
1970 }
1971
1972 static void
1973 cmd_set_manager(struct ctl_context *ctx)
1974 {
1975 struct vtep_ctl_context *vtepctl_ctx = vtep_ctl_context_cast(ctx);
1976 const size_t n = ctx->argc - 1;
1977
1978 verify_managers(vtepctl_ctx->vtep_global);
1979 delete_managers(vtepctl_ctx);
1980 insert_managers(vtepctl_ctx, &ctx->argv[1], n);
1981 }
1982
1983 /* Parameter commands. */
1984 static const struct ctl_table_class tables[] = {
1985 {&vteprec_table_global,
1986 {{&vteprec_table_global, NULL, NULL},
1987 {NULL, NULL, NULL}}},
1988
1989 {&vteprec_table_logical_binding_stats,
1990 {{NULL, NULL, NULL},
1991 {NULL, NULL, NULL}}},
1992
1993 {&vteprec_table_logical_switch,
1994 {{&vteprec_table_logical_switch, &vteprec_logical_switch_col_name, NULL},
1995 {NULL, NULL, NULL}}},
1996
1997 {&vteprec_table_ucast_macs_local,
1998 {{NULL, NULL, NULL},
1999 {NULL, NULL, NULL}}},
2000
2001 {&vteprec_table_ucast_macs_remote,
2002 {{NULL, NULL, NULL},
2003 {NULL, NULL, NULL}}},
2004
2005 {&vteprec_table_mcast_macs_local,
2006 {{NULL, NULL, NULL},
2007 {NULL, NULL, NULL}}},
2008
2009 {&vteprec_table_mcast_macs_remote,
2010 {{NULL, NULL, NULL},
2011 {NULL, NULL, NULL}}},
2012
2013 {&vteprec_table_manager,
2014 {{&vteprec_table_manager, &vteprec_manager_col_target, NULL},
2015 {NULL, NULL, NULL}}},
2016
2017 {&vteprec_table_physical_locator,
2018 {{NULL, NULL, NULL},
2019 {NULL, NULL, NULL}}},
2020
2021 {&vteprec_table_physical_locator_set,
2022 {{NULL, NULL, NULL},
2023 {NULL, NULL, NULL}}},
2024
2025 {&vteprec_table_physical_port,
2026 {{&vteprec_table_physical_port, &vteprec_physical_port_col_name, NULL},
2027 {NULL, NULL, NULL}}},
2028
2029 {&vteprec_table_physical_switch,
2030 {{&vteprec_table_physical_switch, &vteprec_physical_switch_col_name, NULL},
2031 {NULL, NULL, NULL}}},
2032
2033 {&vteprec_table_tunnel,
2034 {{NULL, NULL, NULL},
2035 {NULL, NULL, NULL}}},
2036
2037 {NULL, {{NULL, NULL, NULL}, {NULL, NULL, NULL}}}
2038 };
2039
2040 \f
2041 static void
2042 vtep_ctl_context_init_command(struct vtep_ctl_context *vtepctl_ctx,
2043 struct ctl_command *command)
2044 {
2045 ctl_context_init_command(&vtepctl_ctx->base, command);
2046 vtepctl_ctx->verified_ports = false;
2047
2048 }
2049
2050 static void
2051 vtep_ctl_context_init(struct vtep_ctl_context *vtepctl_ctx,
2052 struct ctl_command *command,
2053 struct ovsdb_idl *idl, struct ovsdb_idl_txn *txn,
2054 const struct vteprec_global *vtep_global,
2055 struct ovsdb_symbol_table *symtab)
2056 {
2057 ctl_context_init(&vtepctl_ctx->base, command, idl, txn, symtab,
2058 vtep_ctl_context_invalidate_cache);
2059 if (command) {
2060 vtepctl_ctx->verified_ports = false;
2061 }
2062 vtepctl_ctx->vtep_global = vtep_global;
2063 vtepctl_ctx->cache_valid = false;
2064 }
2065
2066 static void
2067 vtep_ctl_context_done_command(struct vtep_ctl_context *vtepctl_ctx,
2068 struct ctl_command *command)
2069 {
2070 ctl_context_done_command(&vtepctl_ctx->base, command);
2071 }
2072
2073 static void
2074 vtep_ctl_context_done(struct vtep_ctl_context *vtepctl_ctx,
2075 struct ctl_command *command)
2076 {
2077 ctl_context_done(&vtepctl_ctx->base, command);
2078 }
2079
2080 static void
2081 run_prerequisites(struct ctl_command *commands, size_t n_commands,
2082 struct ovsdb_idl *idl)
2083 {
2084 struct ctl_command *c;
2085
2086 ovsdb_idl_add_table(idl, &vteprec_table_global);
2087 for (c = commands; c < &commands[n_commands]; c++) {
2088 if (c->syntax->prerequisites) {
2089 struct vtep_ctl_context vtepctl_ctx;
2090
2091 ds_init(&c->output);
2092 c->table = NULL;
2093
2094 vtep_ctl_context_init(&vtepctl_ctx, c, idl, NULL, NULL, NULL);
2095 (c->syntax->prerequisites)(&vtepctl_ctx.base);
2096 vtep_ctl_context_done(&vtepctl_ctx, c);
2097
2098 ovs_assert(!c->output.string);
2099 ovs_assert(!c->table);
2100 }
2101 }
2102 }
2103
2104 static void
2105 do_vtep_ctl(const char *args, struct ctl_command *commands,
2106 size_t n_commands, struct ovsdb_idl *idl)
2107 {
2108 struct ovsdb_idl_txn *txn;
2109 const struct vteprec_global *vtep_global;
2110 enum ovsdb_idl_txn_status status;
2111 struct ovsdb_symbol_table *symtab;
2112 struct vtep_ctl_context vtepctl_ctx;
2113 struct ctl_command *c;
2114 struct shash_node *node;
2115 char *error = NULL;
2116
2117 txn = the_idl_txn = ovsdb_idl_txn_create(idl);
2118 if (dry_run) {
2119 ovsdb_idl_txn_set_dry_run(txn);
2120 }
2121
2122 ovsdb_idl_txn_add_comment(txn, "vtep-ctl: %s", args);
2123
2124 vtep_global = vteprec_global_first(idl);
2125 if (!vtep_global) {
2126 /* XXX add verification that table is empty */
2127 vtep_global = vteprec_global_insert(txn);
2128 }
2129
2130 symtab = ovsdb_symbol_table_create();
2131 for (c = commands; c < &commands[n_commands]; c++) {
2132 ds_init(&c->output);
2133 c->table = NULL;
2134 }
2135 vtep_ctl_context_init(&vtepctl_ctx, NULL, idl, txn, vtep_global, symtab);
2136 for (c = commands; c < &commands[n_commands]; c++) {
2137 vtep_ctl_context_init_command(&vtepctl_ctx, c);
2138 if (c->syntax->run) {
2139 (c->syntax->run)(&vtepctl_ctx.base);
2140 }
2141 vtep_ctl_context_done_command(&vtepctl_ctx, c);
2142
2143 if (vtepctl_ctx.base.try_again) {
2144 vtep_ctl_context_done(&vtepctl_ctx, NULL);
2145 goto try_again;
2146 }
2147 }
2148 vtep_ctl_context_done(&vtepctl_ctx, NULL);
2149
2150 SHASH_FOR_EACH (node, &symtab->sh) {
2151 struct ovsdb_symbol *symbol = node->data;
2152 if (!symbol->created) {
2153 ctl_fatal("row id \"%s\" is referenced but never created "
2154 "(e.g. with \"-- --id=%s create ...\")",
2155 node->name, node->name);
2156 }
2157 if (!symbol->strong_ref) {
2158 if (!symbol->weak_ref) {
2159 VLOG_WARN("row id \"%s\" was created but no reference to it "
2160 "was inserted, so it will not actually appear in "
2161 "the database", node->name);
2162 } else {
2163 VLOG_WARN("row id \"%s\" was created but only a weak "
2164 "reference to it was inserted, so it will not "
2165 "actually appear in the database", node->name);
2166 }
2167 }
2168 }
2169
2170 status = ovsdb_idl_txn_commit_block(txn);
2171 if (status == TXN_UNCHANGED || status == TXN_SUCCESS) {
2172 for (c = commands; c < &commands[n_commands]; c++) {
2173 if (c->syntax->postprocess) {
2174 vtep_ctl_context_init(&vtepctl_ctx, c, idl, txn, vtep_global, symtab);
2175 (c->syntax->postprocess)(&vtepctl_ctx.base);
2176 vtep_ctl_context_done(&vtepctl_ctx, c);
2177 }
2178 }
2179 }
2180 error = xstrdup(ovsdb_idl_txn_get_error(txn));
2181 ovsdb_idl_txn_destroy(txn);
2182 txn = the_idl_txn = NULL;
2183
2184 switch (status) {
2185 case TXN_UNCOMMITTED:
2186 case TXN_INCOMPLETE:
2187 OVS_NOT_REACHED();
2188
2189 case TXN_ABORTED:
2190 /* Should not happen--we never call ovsdb_idl_txn_abort(). */
2191 ctl_fatal("transaction aborted");
2192
2193 case TXN_UNCHANGED:
2194 case TXN_SUCCESS:
2195 break;
2196
2197 case TXN_TRY_AGAIN:
2198 goto try_again;
2199
2200 case TXN_ERROR:
2201 ctl_fatal("transaction error: %s", error);
2202
2203 case TXN_NOT_LOCKED:
2204 /* Should not happen--we never call ovsdb_idl_set_lock(). */
2205 ctl_fatal("database not locked");
2206
2207 default:
2208 OVS_NOT_REACHED();
2209 }
2210 free(error);
2211
2212 ovsdb_symbol_table_destroy(symtab);
2213
2214 for (c = commands; c < &commands[n_commands]; c++) {
2215 struct ds *ds = &c->output;
2216
2217 if (c->table) {
2218 table_print(c->table, &table_style);
2219 } else if (oneline) {
2220 size_t j;
2221
2222 ds_chomp(ds, '\n');
2223 for (j = 0; j < ds->length; j++) {
2224 int ch = ds->string[j];
2225 switch (ch) {
2226 case '\n':
2227 fputs("\\n", stdout);
2228 break;
2229
2230 case '\\':
2231 fputs("\\\\", stdout);
2232 break;
2233
2234 default:
2235 putchar(ch);
2236 }
2237 }
2238 putchar('\n');
2239 } else {
2240 fputs(ds_cstr(ds), stdout);
2241 }
2242 ds_destroy(&c->output);
2243 table_destroy(c->table);
2244 free(c->table);
2245
2246 shash_destroy_free_data(&c->options);
2247 }
2248 free(commands);
2249
2250 ovsdb_idl_destroy(idl);
2251
2252 exit(EXIT_SUCCESS);
2253
2254 try_again:
2255 /* Our transaction needs to be rerun, or a prerequisite was not met. Free
2256 * resources and return so that the caller can try again. */
2257 if (txn) {
2258 ovsdb_idl_txn_abort(txn);
2259 ovsdb_idl_txn_destroy(txn);
2260 }
2261 ovsdb_symbol_table_destroy(symtab);
2262 for (c = commands; c < &commands[n_commands]; c++) {
2263 ds_destroy(&c->output);
2264 table_destroy(c->table);
2265 free(c->table);
2266 }
2267 free(error);
2268 }
2269
2270 static const struct ctl_command_syntax vtep_commands[] = {
2271 /* Physical Switch commands. */
2272 {"add-ps", 1, 1, NULL, pre_get_info, cmd_add_ps, NULL, "--may-exist", RW},
2273 {"del-ps", 1, 1, NULL, pre_get_info, cmd_del_ps, NULL, "--if-exists", RW},
2274 {"list-ps", 0, 0, NULL, pre_get_info, cmd_list_ps, NULL, "", RO},
2275 {"ps-exists", 1, 1, NULL, pre_get_info, cmd_ps_exists, NULL, "", RO},
2276
2277 /* Port commands. */
2278 {"list-ports", 1, 1, NULL, pre_get_info, cmd_list_ports, NULL, "", RO},
2279 {"add-port", 2, 2, NULL, pre_get_info, cmd_add_port, NULL, "--may-exist",
2280 RW},
2281 {"del-port", 2, 2, NULL, pre_get_info, cmd_del_port, NULL, "--if-exists",
2282 RW},
2283
2284 /* Logical Switch commands. */
2285 {"add-ls", 1, 1, NULL, pre_get_info, cmd_add_ls, NULL, "--may-exist", RW},
2286 {"del-ls", 1, 1, NULL, pre_get_info, cmd_del_ls, NULL, "--if-exists", RW},
2287 {"list-ls", 0, 0, NULL, pre_get_info, cmd_list_ls, NULL, "", RO},
2288 {"ls-exists", 1, 1, NULL, pre_get_info, cmd_ls_exists, NULL, "", RO},
2289 {"list-bindings", 2, 2, NULL, pre_get_info, cmd_list_bindings, NULL, "", RO},
2290 {"bind-ls", 4, 4, NULL, pre_get_info, cmd_bind_ls, NULL, "", RO},
2291 {"unbind-ls", 3, 3, NULL, pre_get_info, cmd_unbind_ls, NULL, "", RO},
2292
2293 /* MAC binding commands. */
2294 {"add-ucast-local", 3, 4, NULL, pre_get_info, cmd_add_ucast_local, NULL,
2295 "", RW},
2296 {"del-ucast-local", 2, 2, NULL, pre_get_info, cmd_del_ucast_local, NULL,
2297 "", RW},
2298 {"add-mcast-local", 3, 4, NULL, pre_get_info, cmd_add_mcast_local, NULL,
2299 "", RW},
2300 {"del-mcast-local", 3, 4, NULL, pre_get_info, cmd_del_mcast_local, NULL,
2301 "", RW},
2302 {"clear-local-macs", 1, 1, NULL, pre_get_info, cmd_clear_local_macs, NULL,
2303 "", RO},
2304 {"list-local-macs", 1, 1, NULL, pre_get_info, cmd_list_local_macs, NULL,
2305 "", RO},
2306 {"add-ucast-remote", 3, 4, NULL, pre_get_info, cmd_add_ucast_remote, NULL,
2307 "", RW},
2308 {"del-ucast-remote", 2, 2, NULL, pre_get_info, cmd_del_ucast_remote, NULL,
2309 "", RW},
2310 {"add-mcast-remote", 3, 4, NULL, pre_get_info, cmd_add_mcast_remote, NULL,
2311 "", RW},
2312 {"del-mcast-remote", 3, 4, NULL, pre_get_info, cmd_del_mcast_remote, NULL,
2313 "", RW},
2314 {"clear-remote-macs", 1, 1, NULL, pre_get_info, cmd_clear_remote_macs, NULL,
2315 "", RO},
2316 {"list-remote-macs", 1, 1, NULL, pre_get_info, cmd_list_remote_macs, NULL,
2317 "", RO},
2318
2319 /* Manager commands. */
2320 {"get-manager", 0, 0, NULL, pre_manager, cmd_get_manager, NULL, "", RO},
2321 {"del-manager", 0, 0, NULL, pre_manager, cmd_del_manager, NULL, "", RW},
2322 {"set-manager", 1, INT_MAX, NULL, pre_manager, cmd_set_manager, NULL, "",
2323 RW},
2324
2325 {NULL, 0, 0, NULL, NULL, NULL, NULL, NULL, RO},
2326 };
2327
2328 /* Registers vsctl and common db commands. */
2329 static void
2330 vtep_ctl_cmd_init(void)
2331 {
2332 ctl_init(tables, vtep_ctl_exit);
2333 ctl_register_commands(vtep_commands);
2334 }