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