2 * Copyright (c) 2009, 2010 Nicira Networks.
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:
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
31 #include "command-line.h"
34 #include "dynamic-string.h"
36 #include "ovsdb-data.h"
37 #include "ovsdb-idl.h"
38 #include "poll-loop.h"
40 #include "vswitchd/vswitch-idl.h"
45 #define THIS_MODULE VLM_vsctl
47 /* --db: The database server to contact. */
48 static const char *db;
50 /* --oneline: Write each command's output as a single line? */
53 /* --dry-run: Do not commit any changes. */
56 /* --no-wait: Wait for ovs-vswitchd to reload its configuration? */
57 static bool wait_for_reload = true;
59 /* --timeout: Time to wait for a connection to 'db'. */
60 static int timeout = 5;
62 static void vsctl_fatal(const char *, ...) PRINTF_FORMAT(1, 2) NO_RETURN;
63 static char *default_db(void);
64 static void usage(void) NO_RETURN;
65 static void parse_options(int argc, char *argv[]);
67 static void check_vsctl_command(int argc, char *argv[]);
68 static void do_vsctl(int argc, char *argv[], struct ovsdb_idl *idl);
71 main(int argc, char *argv[])
73 struct ovsdb_idl *idl;
76 int start, n_commands;
80 set_program_name(argv[0]);
81 signal(SIGPIPE, SIG_IGN);
84 vlog_set_levels(VLM_ANY_MODULE, VLF_CONSOLE, VLL_WARN);
85 vlog_set_levels(VLM_reconnect, VLF_ANY_FACILITY, VLL_WARN);
86 parse_options(argc, argv);
92 /* Log our arguments. This is often valuable for debugging systems. */
94 for (i = 1; i < argc; i++) {
95 ds_put_format(&args, " %s", argv[i]);
97 VLOG_INFO("Called as%s", ds_cstr(&args));
100 /* Do basic command syntax checking. */
102 for (start = i = optind; i <= argc; i++) {
103 if (i == argc || !strcmp(argv[i], "--")) {
105 check_vsctl_command(i - start, &argv[start]);
112 vsctl_fatal("missing command name (use --help for help)");
115 /* Now execute the commands. */
116 idl = ovsdb_idl_create(db, &ovsrec_idl_class);
117 seqno = ovsdb_idl_get_seqno(idl);
120 unsigned int new_seqno;
123 new_seqno = ovsdb_idl_get_seqno(idl);
124 if (new_seqno != seqno) {
126 vsctl_fatal("too many database inconsistency failures");
128 do_vsctl(argc - optind, argv + optind, idl);
138 vsctl_fatal(const char *format, ...)
143 va_start(args, format);
144 message = xvasprintf(format, args);
147 vlog_set_levels(VLM_vsctl, VLF_CONSOLE, VLL_EMER);
148 VLOG_ERR("%s", message);
149 ovs_fatal(0, "%s", message);
153 parse_options(int argc, char *argv[])
156 OPT_DB = UCHAR_MAX + 1,
163 static struct option long_options[] = {
164 {"db", required_argument, 0, OPT_DB},
165 {"no-syslog", no_argument, 0, OPT_NO_SYSLOG},
166 {"no-wait", no_argument, 0, OPT_NO_WAIT},
167 {"dry-run", no_argument, 0, OPT_DRY_RUN},
168 {"oneline", no_argument, 0, OPT_ONELINE},
169 {"timeout", required_argument, 0, 't'},
170 {"help", no_argument, 0, 'h'},
171 {"version", no_argument, 0, 'V'},
180 c = getopt_long(argc, argv, "+v::hVt:", long_options, NULL);
195 vlog_set_levels(VLM_vsctl, VLF_SYSLOG, VLL_WARN);
199 wait_for_reload = false;
210 OVS_PRINT_VERSION(0, 0);
214 timeout = strtoul(optarg, NULL, 10);
216 ovs_fatal(0, "value %s on -t or --timeout is invalid",
239 printf("%s: ovs-vswitchd management utility\n"
240 "usage: %s [OPTIONS] COMMAND [ARG...]\n",
241 program_name, program_name);
242 printf("\nBridge commands:\n"
244 "create a new bridge named BRIDGE\n"
245 " add-br BRIDGE PARENT VLAN "
246 "create new fake bridge BRIDGE in PARENT on VLAN\n"
248 "delete BRIDGE and all of its ports\n"
250 "print the names of all the bridges\n"
252 "test whether BRIDGE exists\n"
253 " br-to-vlan BRIDGE "
254 "print the VLAN which BRIDGE is on\n"
255 " br-to-parent BRIDGE "
256 "print the parent of BRIDGE\n"
257 " br-set-external-id BRIDGE KEY VALUE"
258 " set KEY on BRIDGE to VALUE\n"
259 " br-set-external-id BRIDGE KEY"
260 " unset KEY on BRIDGE\n"
261 " br-get-external-id BRIDGE KEY"
262 " print value of KEY on BRIDGE\n"
263 " br-get-external-id BRIDGE"
264 " list key-value pairs on BRIDGE\n"
266 printf("\nPort commands:\n"
267 " list-ports BRIDGE "
268 "print the names of all the ports on BRIDGE\n"
269 " add-port BRIDGE PORT "
270 "add network device PORT to BRIDGE\n"
271 " add-bond BRIDGE PORT IFACE... "
272 "add new bonded port PORT in BRIDGE from IFACES\n"
273 " del-port [BRIDGE] PORT "
274 "delete PORT (which may be bonded) from BRIDGE\n"
276 "print name of bridge that contains PORT\n"
277 " port-set-external-id PORT KEY VALUE"
278 " set KEY on PORT to VALUE\n"
279 " port-set-external-id PORT KEY"
280 " unset KEY on PORT\n"
281 " port-get-external-id PORT KEY"
282 " print value of KEY on PORT\n"
283 " port-get-external-id PORT"
284 " list key-value pairs on PORT\n"
285 "A bond is considered to be a single port.\n"
287 printf("\nInterface commands (a bond consists of multiple interfaces):\n"
288 " list-ifaces BRIDGE "
289 "print the names of all the interfaces on BRIDGE\n"
290 " iface-to-br IFACE "
291 "print name of bridge that contains IFACE\n"
292 " iface-set-external-id IFACE KEY VALUE"
293 " set KEY on IFACE to VALUE\n"
294 " iface-set-external-id IFACE KEY"
295 " unset KEY on IFACE\n"
296 " iface-get-external-id IFACE KEY"
297 " print value of KEY on IFACE\n"
298 " iface-get-external-id IFACE"
299 " list key-value pairs on IFACE\n"
301 printf("\nController commands:\n"
302 " get-controller [BRIDGE] "
303 "print the controller for BRIDGE\n"
304 " del-controller [BRIDGE] "
305 "delete the controller for BRIDGE\n"
306 " set-controller [BRIDGE] TARGET "
307 "set the controller for BRIDGE to TARGET\n"
308 " get-fail-mode [BRIDGE] "
309 "print the fail-mode for BRIDGE\n"
310 " del-fail-mode [BRIDGE] "
311 "delete the fail-mode for BRIDGE\n"
312 " set-fail-mode [BRIDGE] MODE "
313 "set the fail-mode for BRIDGE to MODE\n"
315 printf("\nSSL commands:\n"
317 "print the SSL configuration\n"
319 "delete the SSL configuration\n"
320 " set-ssl PRIV-KEY CERT CA-CERT "
321 "set the SSL configuration\n"
323 printf("\nOptions:\n"
325 "connect to DATABASE\n"
329 "print exactly one line of output per command\n",
332 printf("\nOther options:\n"
334 "display this help message\n"
336 "display version information\n");
345 def = xasprintf("unix:%s/ovsdb-server", ovs_rundir);
350 struct vsctl_context {
353 struct ovsdb_idl *idl;
354 const struct ovsrec_open_vswitch *ovs;
356 struct shash options;
359 struct vsctl_bridge {
360 struct ovsrec_bridge *br_cfg;
362 struct ovsrec_controller *ctrl;
363 struct vsctl_bridge *parent;
368 struct ovsrec_port *port_cfg;
369 struct vsctl_bridge *bridge;
373 struct ovsrec_interface *iface_cfg;
374 struct vsctl_port *port;
378 struct shash bridges;
381 struct ovsrec_controller *ctrl;
384 static struct ovsdb_idl_txn *
385 txn_from_openvswitch(const struct ovsrec_open_vswitch *ovs)
387 return ovsdb_idl_txn_get(&ovs->header_);
390 static struct vsctl_bridge *
391 add_bridge(struct vsctl_info *b,
392 struct ovsrec_bridge *br_cfg, const char *name,
393 struct vsctl_bridge *parent, int vlan)
395 struct vsctl_bridge *br = xmalloc(sizeof *br);
397 br->name = xstrdup(name);
400 br->ctrl = parent ? parent->br_cfg->controller : br_cfg->controller;
401 shash_add(&b->bridges, br->name, br);
406 port_is_fake_bridge(const struct ovsrec_port *port_cfg)
408 return (port_cfg->fake_bridge
410 && *port_cfg->tag >= 1 && *port_cfg->tag <= 4095);
413 static struct vsctl_bridge *
414 find_vlan_bridge(struct vsctl_info *info,
415 struct vsctl_bridge *parent, int vlan)
417 struct shash_node *node;
419 SHASH_FOR_EACH (node, &info->bridges) {
420 struct vsctl_bridge *br = node->data;
421 if (br->parent == parent && br->vlan == vlan) {
430 free_info(struct vsctl_info *info)
432 struct shash_node *node;
434 SHASH_FOR_EACH (node, &info->bridges) {
435 struct vsctl_bridge *bridge = node->data;
439 shash_destroy(&info->bridges);
441 SHASH_FOR_EACH (node, &info->ports) {
442 struct vsctl_port *port = node->data;
445 shash_destroy(&info->ports);
447 SHASH_FOR_EACH (node, &info->ifaces) {
448 struct vsctl_iface *iface = node->data;
451 shash_destroy(&info->ifaces);
455 get_info(const struct ovsrec_open_vswitch *ovs, struct vsctl_info *info)
457 struct shash bridges, ports;
460 shash_init(&info->bridges);
461 shash_init(&info->ports);
462 shash_init(&info->ifaces);
464 info->ctrl = ovs->controller;
466 shash_init(&bridges);
468 for (i = 0; i < ovs->n_bridges; i++) {
469 struct ovsrec_bridge *br_cfg = ovs->bridges[i];
470 struct vsctl_bridge *br;
473 if (!shash_add_once(&bridges, br_cfg->name, NULL)) {
474 VLOG_WARN("%s: database contains duplicate bridge name",
478 br = add_bridge(info, br_cfg, br_cfg->name, NULL, 0);
483 for (j = 0; j < br_cfg->n_ports; j++) {
484 struct ovsrec_port *port_cfg = br_cfg->ports[j];
486 if (!shash_add_once(&ports, port_cfg->name, NULL)) {
487 VLOG_WARN("%s: database contains duplicate port name",
492 if (port_is_fake_bridge(port_cfg)
493 && shash_add_once(&bridges, port_cfg->name, NULL)) {
494 add_bridge(info, NULL, port_cfg->name, br, *port_cfg->tag);
498 shash_destroy(&bridges);
499 shash_destroy(&ports);
501 shash_init(&bridges);
503 for (i = 0; i < ovs->n_bridges; i++) {
504 struct ovsrec_bridge *br_cfg = ovs->bridges[i];
505 struct vsctl_bridge *br;
508 if (!shash_add_once(&bridges, br_cfg->name, NULL)) {
511 br = shash_find_data(&info->bridges, br_cfg->name);
512 for (j = 0; j < br_cfg->n_ports; j++) {
513 struct ovsrec_port *port_cfg = br_cfg->ports[j];
514 struct vsctl_port *port;
517 if (!shash_add_once(&ports, port_cfg->name, NULL)) {
521 if (port_is_fake_bridge(port_cfg)
522 && !shash_add_once(&bridges, port_cfg->name, NULL)) {
526 port = xmalloc(sizeof *port);
527 port->port_cfg = port_cfg;
529 && *port_cfg->tag >= 1 && *port_cfg->tag <= 4095) {
530 port->bridge = find_vlan_bridge(info, br, *port_cfg->tag);
537 shash_add(&info->ports, port_cfg->name, port);
539 for (k = 0; k < port_cfg->n_interfaces; k++) {
540 struct ovsrec_interface *iface_cfg = port_cfg->interfaces[k];
541 struct vsctl_iface *iface;
543 if (shash_find(&info->ifaces, iface_cfg->name)) {
544 VLOG_WARN("%s: database contains duplicate interface name",
549 iface = xmalloc(sizeof *iface);
550 iface->iface_cfg = iface_cfg;
552 shash_add(&info->ifaces, iface_cfg->name, iface);
556 shash_destroy(&bridges);
557 shash_destroy(&ports);
561 check_conflicts(struct vsctl_info *info, const char *name,
564 struct vsctl_iface *iface;
565 struct vsctl_port *port;
567 if (shash_find(&info->bridges, name)) {
568 vsctl_fatal("%s because a bridge named %s already exists",
572 port = shash_find_data(&info->ports, name);
574 vsctl_fatal("%s because a port named %s already exists on "
575 "bridge %s", msg, name, port->bridge->name);
578 iface = shash_find_data(&info->ifaces, name);
580 vsctl_fatal("%s because an interface named %s already exists "
581 "on bridge %s", msg, name, iface->port->bridge->name);
587 static struct vsctl_bridge *
588 find_bridge(struct vsctl_info *info, const char *name, bool must_exist)
590 struct vsctl_bridge *br = shash_find_data(&info->bridges, name);
591 if (must_exist && !br) {
592 vsctl_fatal("no bridge named %s", name);
597 static struct vsctl_bridge *
598 find_real_bridge(struct vsctl_info *info, const char *name, bool must_exist)
600 struct vsctl_bridge *br = find_bridge(info, name, must_exist);
601 if (br && br->parent) {
602 vsctl_fatal("%s is a fake bridge", name);
607 static struct vsctl_port *
608 find_port(struct vsctl_info *info, const char *name, bool must_exist)
610 struct vsctl_port *port = shash_find_data(&info->ports, name);
611 if (port && !strcmp(name, port->bridge->name)) {
614 if (must_exist && !port) {
615 vsctl_fatal("no port named %s", name);
620 static struct vsctl_iface *
621 find_iface(struct vsctl_info *info, const char *name, bool must_exist)
623 struct vsctl_iface *iface = shash_find_data(&info->ifaces, name);
624 if (iface && !strcmp(name, iface->port->bridge->name)) {
627 if (must_exist && !iface) {
628 vsctl_fatal("no interface named %s", name);
634 bridge_insert_port(struct ovsrec_bridge *br, struct ovsrec_port *port)
636 struct ovsrec_port **ports;
639 ports = xmalloc(sizeof *br->ports * (br->n_ports + 1));
640 for (i = 0; i < br->n_ports; i++) {
641 ports[i] = br->ports[i];
643 ports[br->n_ports] = port;
644 ovsrec_bridge_set_ports(br, ports, br->n_ports + 1);
649 bridge_delete_port(struct ovsrec_bridge *br, struct ovsrec_port *port)
651 struct ovsrec_port **ports;
654 ports = xmalloc(sizeof *br->ports * br->n_ports);
655 for (i = n = 0; i < br->n_ports; i++) {
656 if (br->ports[i] != port) {
657 ports[n++] = br->ports[i];
660 ovsrec_bridge_set_ports(br, ports, n);
665 ovs_insert_bridge(const struct ovsrec_open_vswitch *ovs,
666 struct ovsrec_bridge *bridge)
668 struct ovsrec_bridge **bridges;
671 bridges = xmalloc(sizeof *ovs->bridges * (ovs->n_bridges + 1));
672 for (i = 0; i < ovs->n_bridges; i++) {
673 bridges[i] = ovs->bridges[i];
675 bridges[ovs->n_bridges] = bridge;
676 ovsrec_open_vswitch_set_bridges(ovs, bridges, ovs->n_bridges + 1);
681 ovs_delete_bridge(const struct ovsrec_open_vswitch *ovs,
682 struct ovsrec_bridge *bridge)
684 struct ovsrec_bridge **bridges;
687 bridges = xmalloc(sizeof *ovs->bridges * ovs->n_bridges);
688 for (i = n = 0; i < ovs->n_bridges; i++) {
689 if (ovs->bridges[i] != bridge) {
690 bridges[n++] = ovs->bridges[i];
693 ovsrec_open_vswitch_set_bridges(ovs, bridges, n);
698 cmd_init(struct vsctl_context *ctx UNUSED)
703 cmd_add_br(struct vsctl_context *ctx)
705 const char *br_name = ctx->argv[1];
706 struct vsctl_info info;
708 get_info(ctx->ovs, &info);
709 check_conflicts(&info, br_name,
710 xasprintf("cannot create a bridge named %s", br_name));
712 if (ctx->argc == 2) {
713 struct ovsrec_bridge *br;
714 struct ovsrec_port *port;
715 struct ovsrec_interface *iface;
717 iface = ovsrec_interface_insert(txn_from_openvswitch(ctx->ovs));
718 ovsrec_interface_set_name(iface, br_name);
720 port = ovsrec_port_insert(txn_from_openvswitch(ctx->ovs));
721 ovsrec_port_set_name(port, br_name);
722 ovsrec_port_set_interfaces(port, &iface, 1);
724 br = ovsrec_bridge_insert(txn_from_openvswitch(ctx->ovs));
725 ovsrec_bridge_set_name(br, br_name);
726 ovsrec_bridge_set_ports(br, &port, 1);
728 ovs_insert_bridge(ctx->ovs, br);
729 } else if (ctx->argc == 3) {
730 vsctl_fatal("'%s' command takes exactly 1 or 3 arguments",
732 } else if (ctx->argc == 4) {
733 const char *parent_name = ctx->argv[2];
734 int vlan = atoi(ctx->argv[3]);
735 struct ovsrec_bridge *br;
736 struct vsctl_bridge *parent;
737 struct ovsrec_port *port;
738 struct ovsrec_interface *iface;
741 if (vlan < 1 || vlan > 4095) {
742 vsctl_fatal("%s: vlan must be between 1 and 4095", ctx->argv[0]);
745 parent = find_bridge(&info, parent_name, false);
746 if (parent && parent->vlan) {
747 vsctl_fatal("cannot create bridge with fake bridge as parent");
750 vsctl_fatal("parent bridge %s does not exist", parent_name);
754 iface = ovsrec_interface_insert(txn_from_openvswitch(ctx->ovs));
755 ovsrec_interface_set_name(iface, br_name);
756 ovsrec_interface_set_type(iface, "internal");
758 port = ovsrec_port_insert(txn_from_openvswitch(ctx->ovs));
759 ovsrec_port_set_name(port, br_name);
760 ovsrec_port_set_interfaces(port, &iface, 1);
761 ovsrec_port_set_fake_bridge(port, true);
762 ovsrec_port_set_tag(port, &tag, 1);
764 bridge_insert_port(br, port);
773 del_port(struct vsctl_info *info, struct vsctl_port *port)
775 struct shash_node *node;
777 SHASH_FOR_EACH (node, &info->ifaces) {
778 struct vsctl_iface *iface = node->data;
779 if (iface->port == port) {
780 ovsrec_interface_delete(iface->iface_cfg);
783 ovsrec_port_delete(port->port_cfg);
785 bridge_delete_port((port->bridge->parent
786 ? port->bridge->parent->br_cfg
787 : port->bridge->br_cfg), port->port_cfg);
791 cmd_del_br(struct vsctl_context *ctx)
793 bool must_exist = !shash_find(&ctx->options, "--if-exists");
794 struct vsctl_bridge *bridge;
795 struct vsctl_info info;
797 get_info(ctx->ovs, &info);
798 bridge = find_bridge(&info, ctx->argv[1], must_exist);
800 struct shash_node *node;
802 SHASH_FOR_EACH (node, &info.ports) {
803 struct vsctl_port *port = node->data;
804 if (port->bridge == bridge
805 || !strcmp(port->port_cfg->name, bridge->name)) {
806 del_port(&info, port);
809 if (bridge->br_cfg) {
810 ovsrec_bridge_delete(bridge->br_cfg);
811 ovs_delete_bridge(ctx->ovs, bridge->br_cfg);
818 output_sorted(struct svec *svec, struct ds *output)
824 SVEC_FOR_EACH (i, name, svec) {
825 ds_put_format(output, "%s\n", name);
830 cmd_list_br(struct vsctl_context *ctx)
832 struct shash_node *node;
833 struct vsctl_info info;
836 get_info(ctx->ovs, &info);
839 SHASH_FOR_EACH (node, &info.bridges) {
840 struct vsctl_bridge *br = node->data;
841 svec_add(&bridges, br->name);
843 output_sorted(&bridges, &ctx->output);
844 svec_destroy(&bridges);
850 cmd_br_exists(struct vsctl_context *ctx)
852 struct vsctl_info info;
854 get_info(ctx->ovs, &info);
855 if (!find_bridge(&info, ctx->argv[1], false)) {
861 /* Returns true if 'b_prefix' (of length 'b_prefix_len') concatenated with 'b'
862 * equals 'a', false otherwise. */
864 key_matches(const char *a,
865 const char *b_prefix, size_t b_prefix_len, const char *b)
867 return !strncmp(a, b_prefix, b_prefix_len) && !strcmp(a + b_prefix_len, b);
871 set_external_id(char **old_keys, char **old_values, size_t old_n,
872 char *key, char *value,
873 char ***new_keysp, char ***new_valuesp, size_t *new_np)
880 new_keys = xmalloc(sizeof *new_keys * (old_n + 1));
881 new_values = xmalloc(sizeof *new_values * (old_n + 1));
883 for (i = 0; i < old_n; i++) {
884 if (strcmp(key, old_keys[i])) {
885 new_keys[new_n] = old_keys[i];
886 new_values[new_n] = old_values[i];
891 new_keys[new_n] = key;
892 new_values[new_n] = value;
895 *new_keysp = new_keys;
896 *new_valuesp = new_values;
901 cmd_br_set_external_id(struct vsctl_context *ctx)
903 struct vsctl_info info;
904 struct vsctl_bridge *bridge;
905 char **keys, **values;
908 get_info(ctx->ovs, &info);
909 bridge = find_bridge(&info, ctx->argv[1], true);
910 if (bridge->br_cfg) {
911 set_external_id(bridge->br_cfg->key_external_ids,
912 bridge->br_cfg->value_external_ids,
913 bridge->br_cfg->n_external_ids,
914 ctx->argv[2], ctx->argc >= 4 ? ctx->argv[3] : NULL,
916 ovsrec_bridge_set_external_ids(bridge->br_cfg, keys, values, n);
918 char *key = xasprintf("fake-bridge-%s", ctx->argv[2]);
919 struct vsctl_port *port = shash_find_data(&info.ports, ctx->argv[1]);
920 set_external_id(port->port_cfg->key_external_ids,
921 port->port_cfg->value_external_ids,
922 port->port_cfg->n_external_ids,
923 key, ctx->argc >= 4 ? ctx->argv[3] : NULL,
925 ovsrec_port_set_external_ids(port->port_cfg, keys, values, n);
935 get_external_id(char **keys, char **values, size_t n,
936 const char *prefix, const char *key,
939 size_t prefix_len = strlen(prefix);
944 for (i = 0; i < n; i++) {
945 if (!key && !strncmp(keys[i], prefix, prefix_len)) {
946 svec_add_nocopy(&svec, xasprintf("%s=%s",
947 keys[i] + prefix_len, values[i]));
948 } else if (key_matches(keys[i], prefix, prefix_len, key)) {
949 svec_add(&svec, values[i]);
953 output_sorted(&svec, output);
958 cmd_br_get_external_id(struct vsctl_context *ctx)
960 struct vsctl_info info;
961 struct vsctl_bridge *bridge;
963 get_info(ctx->ovs, &info);
964 bridge = find_bridge(&info, ctx->argv[1], true);
965 if (bridge->br_cfg) {
966 get_external_id(bridge->br_cfg->key_external_ids,
967 bridge->br_cfg->value_external_ids,
968 bridge->br_cfg->n_external_ids,
969 "", ctx->argc >= 3 ? ctx->argv[2] : NULL,
972 struct vsctl_port *port = shash_find_data(&info.ports, ctx->argv[1]);
973 get_external_id(port->port_cfg->key_external_ids,
974 port->port_cfg->value_external_ids,
975 port->port_cfg->n_external_ids,
976 "fake-bridge-", ctx->argc >= 3 ? ctx->argv[2] : NULL, &ctx->output);
983 cmd_list_ports(struct vsctl_context *ctx)
985 struct vsctl_bridge *br;
986 struct shash_node *node;
987 struct vsctl_info info;
990 get_info(ctx->ovs, &info);
991 br = find_bridge(&info, ctx->argv[1], true);
994 SHASH_FOR_EACH (node, &info.ports) {
995 struct vsctl_port *port = node->data;
997 if (strcmp(port->port_cfg->name, br->name) && br == port->bridge) {
998 svec_add(&ports, port->port_cfg->name);
1001 output_sorted(&ports, &ctx->output);
1002 svec_destroy(&ports);
1008 add_port(const struct ovsrec_open_vswitch *ovs,
1009 const char *br_name, const char *port_name, bool fake_iface,
1010 char *iface_names[], int n_ifaces)
1012 struct vsctl_info info;
1013 struct vsctl_bridge *bridge;
1014 struct ovsrec_interface **ifaces;
1015 struct ovsrec_port *port;
1018 get_info(ovs, &info);
1019 check_conflicts(&info, port_name,
1020 xasprintf("cannot create a port named %s", port_name));
1021 /* XXX need to check for conflicts on interfaces too */
1022 bridge = find_bridge(&info, br_name, true);
1024 ifaces = xmalloc(n_ifaces * sizeof *ifaces);
1025 for (i = 0; i < n_ifaces; i++) {
1026 ifaces[i] = ovsrec_interface_insert(txn_from_openvswitch(ovs));
1027 ovsrec_interface_set_name(ifaces[i], iface_names[i]);
1030 port = ovsrec_port_insert(txn_from_openvswitch(ovs));
1031 ovsrec_port_set_name(port, port_name);
1032 ovsrec_port_set_interfaces(port, ifaces, n_ifaces);
1033 ovsrec_port_set_bond_fake_iface(port, fake_iface);
1037 int64_t tag = bridge->vlan;
1038 ovsrec_port_set_tag(port, &tag, 1);
1041 bridge_insert_port((bridge->parent ? bridge->parent->br_cfg
1042 : bridge->br_cfg), port);
1048 cmd_add_port(struct vsctl_context *ctx)
1050 add_port(ctx->ovs, ctx->argv[1], ctx->argv[2], false, &ctx->argv[2], 1);
1054 cmd_add_bond(struct vsctl_context *ctx)
1056 bool fake_iface = shash_find(&ctx->options, "--fake-iface");
1058 add_port(ctx->ovs, ctx->argv[1], ctx->argv[2], fake_iface,
1059 &ctx->argv[3], ctx->argc - 3);
1063 cmd_del_port(struct vsctl_context *ctx)
1065 bool must_exist = !shash_find(&ctx->options, "--if-exists");
1066 struct vsctl_info info;
1068 get_info(ctx->ovs, &info);
1069 if (ctx->argc == 2) {
1070 struct vsctl_port *port = find_port(&info, ctx->argv[1], must_exist);
1072 del_port(&info, port);
1074 } else if (ctx->argc == 3) {
1075 struct vsctl_bridge *bridge = find_bridge(&info, ctx->argv[1], true);
1076 struct vsctl_port *port = find_port(&info, ctx->argv[2], must_exist);
1079 if (port->bridge == bridge) {
1080 del_port(&info, port);
1081 } else if (port->bridge->parent == bridge) {
1082 vsctl_fatal("bridge %s does not have a port %s (although its "
1083 "parent bridge %s does)",
1084 ctx->argv[1], ctx->argv[2], bridge->parent->name);
1086 vsctl_fatal("bridge %s does not have a port %s",
1087 ctx->argv[1], ctx->argv[2]);
1095 cmd_port_to_br(struct vsctl_context *ctx)
1097 struct vsctl_port *port;
1098 struct vsctl_info info;
1100 get_info(ctx->ovs, &info);
1101 port = find_port(&info, ctx->argv[1], true);
1102 ds_put_format(&ctx->output, "%s\n", port->bridge->name);
1107 cmd_port_set_external_id(struct vsctl_context *ctx)
1109 struct vsctl_info info;
1110 struct vsctl_port *port;
1111 char **keys, **values;
1114 get_info(ctx->ovs, &info);
1115 port = find_port(&info, ctx->argv[1], true);
1116 set_external_id(port->port_cfg->key_external_ids,
1117 port->port_cfg->value_external_ids,
1118 port->port_cfg->n_external_ids,
1119 ctx->argv[2], ctx->argc >= 4 ? ctx->argv[3] : NULL,
1120 &keys, &values, &n);
1121 ovsrec_port_set_external_ids(port->port_cfg, keys, values, n);
1129 cmd_port_get_external_id(struct vsctl_context *ctx)
1131 struct vsctl_info info;
1132 struct vsctl_port *port;
1134 get_info(ctx->ovs, &info);
1135 port = find_port(&info, ctx->argv[1], true);
1136 get_external_id(port->port_cfg->key_external_ids,
1137 port->port_cfg->value_external_ids,
1138 port->port_cfg->n_external_ids,
1139 "", ctx->argc >= 3 ? ctx->argv[2] : NULL, &ctx->output);
1144 cmd_br_to_vlan(struct vsctl_context *ctx)
1146 struct vsctl_bridge *bridge;
1147 struct vsctl_info info;
1149 get_info(ctx->ovs, &info);
1150 bridge = find_bridge(&info, ctx->argv[1], true);
1151 ds_put_format(&ctx->output, "%d\n", bridge->vlan);
1156 cmd_br_to_parent(struct vsctl_context *ctx)
1158 struct vsctl_bridge *bridge;
1159 struct vsctl_info info;
1161 get_info(ctx->ovs, &info);
1162 bridge = find_bridge(&info, ctx->argv[1], true);
1163 if (bridge->parent) {
1164 bridge = bridge->parent;
1166 ds_put_format(&ctx->output, "%s\n", bridge->name);
1171 cmd_list_ifaces(struct vsctl_context *ctx)
1173 struct vsctl_bridge *br;
1174 struct shash_node *node;
1175 struct vsctl_info info;
1178 get_info(ctx->ovs, &info);
1179 br = find_bridge(&info, ctx->argv[1], true);
1182 SHASH_FOR_EACH (node, &info.ifaces) {
1183 struct vsctl_iface *iface = node->data;
1185 if (strcmp(iface->iface_cfg->name, br->name)
1186 && br == iface->port->bridge) {
1187 svec_add(&ifaces, iface->iface_cfg->name);
1190 output_sorted(&ifaces, &ctx->output);
1191 svec_destroy(&ifaces);
1197 cmd_iface_to_br(struct vsctl_context *ctx)
1199 struct vsctl_iface *iface;
1200 struct vsctl_info info;
1202 get_info(ctx->ovs, &info);
1203 iface = find_iface(&info, ctx->argv[1], true);
1204 ds_put_format(&ctx->output, "%s\n", iface->port->bridge->name);
1209 cmd_iface_set_external_id(struct vsctl_context *ctx)
1211 struct vsctl_info info;
1212 struct vsctl_iface *iface;
1213 char **keys, **values;
1216 get_info(ctx->ovs, &info);
1217 iface = find_iface(&info, ctx->argv[1], true);
1218 set_external_id(iface->iface_cfg->key_external_ids,
1219 iface->iface_cfg->value_external_ids,
1220 iface->iface_cfg->n_external_ids,
1221 ctx->argv[2], ctx->argc >= 4 ? ctx->argv[3] : NULL,
1222 &keys, &values, &n);
1223 ovsrec_interface_set_external_ids(iface->iface_cfg, keys, values, n);
1231 cmd_iface_get_external_id(struct vsctl_context *ctx)
1233 struct vsctl_info info;
1234 struct vsctl_iface *iface;
1236 get_info(ctx->ovs, &info);
1237 iface = find_iface(&info, ctx->argv[1], true);
1238 get_external_id(iface->iface_cfg->key_external_ids,
1239 iface->iface_cfg->value_external_ids,
1240 iface->iface_cfg->n_external_ids,
1241 "", ctx->argc >= 3 ? ctx->argv[2] : NULL, &ctx->output);
1246 cmd_get_controller(struct vsctl_context *ctx)
1248 struct vsctl_info info;
1250 get_info(ctx->ovs, &info);
1252 if (ctx->argc == 1) {
1253 /* Return the controller from the "Open_vSwitch" table */
1255 ds_put_format(&ctx->output, "%s\n", info.ctrl->target);
1258 /* Return the controller for a particular bridge. */
1259 struct vsctl_bridge *br = find_bridge(&info, ctx->argv[1], true);
1261 /* If no controller is explicitly defined for the requested
1262 * bridge, fallback to the "Open_vSwitch" table's controller. */
1264 ds_put_format(&ctx->output, "%s\n", br->ctrl->target);
1265 } else if (info.ctrl) {
1266 ds_put_format(&ctx->output, "%s\n", info.ctrl->target);
1274 cmd_del_controller(struct vsctl_context *ctx)
1276 struct vsctl_info info;
1278 get_info(ctx->ovs, &info);
1280 if (ctx->argc == 1) {
1282 ovsrec_controller_delete(info.ctrl);
1283 ovsrec_open_vswitch_set_controller(ctx->ovs, NULL);
1286 struct vsctl_bridge *br = find_real_bridge(&info, ctx->argv[1], true);
1289 ovsrec_controller_delete(br->ctrl);
1290 ovsrec_bridge_set_controller(br->br_cfg, NULL);
1298 cmd_set_controller(struct vsctl_context *ctx)
1300 struct vsctl_info info;
1301 struct ovsrec_controller *ctrl;
1303 get_info(ctx->ovs, &info);
1305 if (ctx->argc == 2) {
1306 /* Set the controller in the "Open_vSwitch" table. */
1308 ovsrec_controller_delete(info.ctrl);
1310 ctrl = ovsrec_controller_insert(txn_from_openvswitch(ctx->ovs));
1311 ovsrec_controller_set_target(ctrl, ctx->argv[1]);
1312 ovsrec_open_vswitch_set_controller(ctx->ovs, ctrl);
1314 /* Set the controller for a particular bridge. */
1315 struct vsctl_bridge *br = find_real_bridge(&info, ctx->argv[1], true);
1318 ovsrec_controller_delete(br->ctrl);
1320 ctrl = ovsrec_controller_insert(txn_from_openvswitch(ctx->ovs));
1321 ovsrec_controller_set_target(ctrl, ctx->argv[2]);
1322 ovsrec_bridge_set_controller(br->br_cfg, ctrl);
1329 cmd_get_fail_mode(struct vsctl_context *ctx)
1331 struct vsctl_info info;
1332 const char *fail_mode = NULL;
1334 get_info(ctx->ovs, &info);
1336 if (ctx->argc == 1) {
1337 /* Return the fail-mode from the "Open_vSwitch" table */
1338 if (info.ctrl && info.ctrl->fail_mode) {
1339 fail_mode = info.ctrl->fail_mode;
1342 /* Return the fail-mode for a particular bridge. */
1343 struct vsctl_bridge *br = find_bridge(&info, ctx->argv[1], true);
1345 /* If no controller or fail-mode is explicitly defined for the
1346 * requested bridge, fallback to the "Open_vSwitch" table's
1348 if (br->ctrl && br->ctrl->fail_mode) {
1349 fail_mode = br->ctrl->fail_mode;
1350 } else if (info.ctrl && info.ctrl->fail_mode) {
1351 fail_mode = info.ctrl->fail_mode;
1355 if (fail_mode && strlen(fail_mode)) {
1356 ds_put_format(&ctx->output, "%s\n", fail_mode);
1363 cmd_del_fail_mode(struct vsctl_context *ctx)
1365 struct vsctl_info info;
1367 get_info(ctx->ovs, &info);
1369 if (ctx->argc == 1) {
1370 if (info.ctrl && info.ctrl->fail_mode) {
1371 ovsrec_controller_set_fail_mode(info.ctrl, NULL);
1374 struct vsctl_bridge *br = find_real_bridge(&info, ctx->argv[1], true);
1376 if (br->ctrl && br->ctrl->fail_mode) {
1377 ovsrec_controller_set_fail_mode(br->ctrl, NULL);
1385 cmd_set_fail_mode(struct vsctl_context *ctx)
1387 struct vsctl_info info;
1388 const char *fail_mode;
1390 get_info(ctx->ovs, &info);
1392 fail_mode = (ctx->argc == 2) ? ctx->argv[1] : ctx->argv[2];
1394 if (strcmp(fail_mode, "standalone") && strcmp(fail_mode, "secure")) {
1395 vsctl_fatal("fail-mode must be \"standalone\" or \"secure\"");
1398 if (ctx->argc == 2) {
1399 /* Set the fail-mode in the "Open_vSwitch" table. */
1401 vsctl_fatal("no controller declared");
1403 ovsrec_controller_set_fail_mode(info.ctrl, fail_mode);
1405 struct vsctl_bridge *br = find_real_bridge(&info, ctx->argv[1], true);
1408 vsctl_fatal("no controller declared for %s", br->name);
1410 ovsrec_controller_set_fail_mode(br->ctrl, fail_mode);
1417 cmd_get_ssl(struct vsctl_context *ctx)
1419 struct ovsrec_ssl *ssl = ctx->ovs->ssl;
1422 ds_put_format(&ctx->output, "Private key: %s\n", ssl->private_key);
1423 ds_put_format(&ctx->output, "Certificate: %s\n", ssl->certificate);
1424 ds_put_format(&ctx->output, "CA Certificate: %s\n", ssl->ca_cert);
1425 ds_put_format(&ctx->output, "Bootstrap: %s\n",
1426 ssl->bootstrap_ca_cert ? "true" : "false");
1431 cmd_del_ssl(struct vsctl_context *ctx)
1433 struct ovsrec_ssl *ssl = ctx->ovs->ssl;
1436 ovsrec_ssl_delete(ssl);
1437 ovsrec_open_vswitch_set_ssl(ctx->ovs, NULL);
1442 cmd_set_ssl(struct vsctl_context *ctx)
1444 bool bootstrap = shash_find(&ctx->options, "--bootstrap");
1445 struct ovsrec_ssl *ssl = ctx->ovs->ssl;
1448 ovsrec_ssl_delete(ssl);
1450 ssl = ovsrec_ssl_insert(txn_from_openvswitch(ctx->ovs));
1452 ovsrec_ssl_set_private_key(ssl, ctx->argv[1]);
1453 ovsrec_ssl_set_certificate(ssl, ctx->argv[2]);
1454 ovsrec_ssl_set_ca_cert(ssl, ctx->argv[3]);
1456 ovsrec_ssl_set_bootstrap_ca_cert(ssl, bootstrap);
1458 ovsrec_open_vswitch_set_ssl(ctx->ovs, ssl);
1461 /* Parameter commands. */
1463 /* POSIX extended regular expression for an 8-bit unsigned decimal integer. */
1464 #define OCTET_RE "([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])"
1466 /* POSIX extended regular expression for an IP address. */
1467 #define IP_RE "("OCTET_RE"\\."OCTET_RE"\\."OCTET_RE"\\."OCTET_RE")"
1469 /* POSIX extended regular expression for a netmask. */
1470 #define NETMASK_RE \
1471 "255.255.255."NETMASK_END_RE"|" \
1472 "255.255."NETMASK_END_RE".0|" \
1473 "255."NETMASK_END_RE".0.0|" \
1474 NETMASK_END_RE".0.0.0"
1475 #define NETMASK_END_RE "(255|254|252|248|240|224|192|128|0)"
1477 /* POSIX extended regular expression for an Ethernet address. */
1478 #define XX_RE "[0-9a-fA-F][0-9a-fA-F]"
1479 #define MAC_RE XX_RE":"XX_RE":"XX_RE":"XX_RE":"XX_RE":"XX_RE
1481 /* POSIX extended regular expression for a TCP or UDP port number. */
1485 "[1-9][0-9][0-9]|" \
1486 "[1-9][0-9][0-9][0-9]|" \
1487 "[1-5][0-9][0-9][0-9][0-9]|" \
1488 "6[1-4][0-9][0-9][0-9]|" \
1489 "65[1-4][0-9][0-9]|" \
1494 VSCF_READONLY = 1 << 0,
1495 VSCF_HIDDEN = 1 << 1
1498 struct vsctl_column {
1499 struct ovsdb_idl_column *idl;
1501 const char *constraint;
1504 static const struct vsctl_column bridge_columns[] = {
1505 {&ovsrec_bridge_col_datapath_id, VSCF_READONLY, NULL},
1506 {&ovsrec_bridge_col_name, VSCF_READONLY, NULL},
1507 {&ovsrec_bridge_col_mirrors, VSCF_READONLY, NULL},
1508 {&ovsrec_bridge_col_other_config, 0, NULL},
1509 {&ovsrec_bridge_col_flood_vlans, 0, "[1,4095]"},
1510 {&ovsrec_bridge_col_controller, VSCF_READONLY, NULL},
1511 {&ovsrec_bridge_col_netflow, VSCF_READONLY, NULL},
1512 {&ovsrec_bridge_col_external_ids, 0, NULL},
1513 {&ovsrec_bridge_col_ports, VSCF_READONLY, NULL},
1517 static const struct vsctl_column controller_columns[] = {
1518 {&ovsrec_controller_col_connection_mode, 0, "in-band|out-of-band"},
1519 {&ovsrec_controller_col_controller_burst_limit, 0, "[25,]"},
1520 {&ovsrec_controller_col_controller_rate_limit, 0, "[100,]"},
1521 {&ovsrec_controller_col_discover_accept_regex, 0, NULL},
1522 {&ovsrec_controller_col_discover_update_resolv_conf, 0, NULL},
1523 {&ovsrec_controller_col_fail_mode, 0, "standalone|secure"},
1524 {&ovsrec_controller_col_inactivity_probe, 0, "[5000,]"},
1525 {&ovsrec_controller_col_local_gateway, 0, IP_RE},
1526 {&ovsrec_controller_col_local_ip, 0, IP_RE},
1527 {&ovsrec_controller_col_local_netmask, 0, NETMASK_RE},
1528 {&ovsrec_controller_col_max_backoff, 0, "[1000,]"},
1529 {&ovsrec_controller_col_target, 0, NULL},
1533 static const struct vsctl_column interface_columns[] = {
1534 {&ovsrec_interface_col_external_ids, 0, NULL},
1535 {&ovsrec_interface_col_ingress_policing_burst, 0, "[10,]"},
1536 {&ovsrec_interface_col_ingress_policing_rate, 0, "[100,]"},
1537 {&ovsrec_interface_col_mac, 0, MAC_RE},
1538 {&ovsrec_interface_col_name, VSCF_READONLY, NULL},
1539 {&ovsrec_interface_col_ofport, VSCF_READONLY, NULL},
1540 {&ovsrec_interface_col_options, 0, NULL},
1541 {&ovsrec_interface_col_type, VSCF_READONLY, NULL},
1545 static const struct vsctl_column mirror_columns[] = {
1546 {&ovsrec_mirror_col_name, VSCF_READONLY, NULL},
1547 {&ovsrec_mirror_col_output_port, 0, "Port"},
1548 {&ovsrec_mirror_col_output_vlan, 0, "[1,4095]"},
1549 {&ovsrec_mirror_col_select_dst_port, 0, "Port"},
1550 {&ovsrec_mirror_col_select_src_port, 0, "Port"},
1551 {&ovsrec_mirror_col_select_vlan, 0, "[1,4095]"},
1555 static const struct vsctl_column netflow_columns[] = {
1556 {&ovsrec_netflow_col_active_timeout, 0, "[-1,]"},
1557 {&ovsrec_netflow_col_add_id_to_interface, 0, NULL},
1558 {&ovsrec_netflow_col_targets, 0, IP_RE":"PORT_RE},
1559 {&ovsrec_netflow_col_engine_type, 0, "[0,255]"},
1560 {&ovsrec_netflow_col_engine_id, 0, "[0,255]"},
1564 static const struct vsctl_column open_vswitch_columns[] = {
1565 {&ovsrec_open_vswitch_col_bridges, VSCF_READONLY, NULL},
1566 {&ovsrec_open_vswitch_col_controller, VSCF_READONLY, NULL},
1567 {&ovsrec_open_vswitch_col_cur_cfg, VSCF_HIDDEN, NULL},
1568 {&ovsrec_open_vswitch_col_management_id, 0, "[0-9a-fA-F]{12}"},
1569 {&ovsrec_open_vswitch_col_managers, 0, "p?(ssl|tcp|unix):.*"},
1570 {&ovsrec_open_vswitch_col_next_cfg, VSCF_HIDDEN, NULL},
1571 {&ovsrec_open_vswitch_col_ssl, VSCF_READONLY, NULL},
1575 static const struct vsctl_column port_columns[] = {
1576 {&ovsrec_port_col_bond_updelay, 0, "[0,]"},
1577 {&ovsrec_port_col_bond_downdelay, 0, "[0,]"},
1578 {&ovsrec_port_col_bond_fake_iface, VSCF_READONLY, NULL},
1579 {&ovsrec_port_col_external_ids, 0, NULL},
1580 {&ovsrec_port_col_fake_bridge, VSCF_READONLY, NULL},
1581 {&ovsrec_port_col_interfaces, VSCF_READONLY, NULL},
1582 {&ovsrec_port_col_mac, 0, MAC_RE},
1583 {&ovsrec_port_col_name, VSCF_READONLY, NULL},
1584 {&ovsrec_port_col_other_config, 0, NULL},
1585 {&ovsrec_port_col_tag, 0, "[0,4095]"},
1586 {&ovsrec_port_col_trunks, 0, "[0,4095]"},
1590 static const struct vsctl_column ssl_columns[] = {
1591 {&ovsrec_ssl_col_bootstrap_ca_cert, 0, NULL},
1592 {&ovsrec_ssl_col_ca_cert, 0, NULL},
1593 {&ovsrec_ssl_col_certificate, 0, NULL},
1594 {&ovsrec_ssl_col_private_key, 0, NULL},
1598 struct vsctl_row_id {
1599 const struct ovsdb_idl_table_class *table;
1600 const struct ovsdb_idl_column *name_column;
1601 const struct ovsdb_idl_column *uuid_column;
1604 struct vsctl_table_class {
1605 struct ovsdb_idl_table_class *class;
1606 const struct vsctl_column *columns;
1607 struct vsctl_row_id row_ids[2];
1610 static const struct vsctl_table_class tables[] = {
1611 {&ovsrec_table_bridge, bridge_columns,
1612 {{&ovsrec_table_bridge, &ovsrec_bridge_col_name, NULL},
1613 {NULL, NULL, NULL}}},
1615 {&ovsrec_table_controller, controller_columns,
1616 {{&ovsrec_table_bridge,
1617 &ovsrec_bridge_col_name,
1618 &ovsrec_bridge_col_controller},
1619 {&ovsrec_table_open_vswitch,
1621 &ovsrec_open_vswitch_col_controller}}},
1623 {&ovsrec_table_interface, interface_columns,
1624 {{&ovsrec_table_interface, &ovsrec_interface_col_name, NULL},
1625 {NULL, NULL, NULL}}},
1627 {&ovsrec_table_mirror, mirror_columns,
1628 {{&ovsrec_table_mirror, &ovsrec_mirror_col_name, NULL},
1629 {NULL, NULL, NULL}}},
1631 {&ovsrec_table_netflow, netflow_columns,
1632 {{&ovsrec_table_bridge,
1633 &ovsrec_bridge_col_name,
1634 &ovsrec_bridge_col_netflow},
1635 {NULL, NULL, NULL}}},
1637 {&ovsrec_table_open_vswitch, open_vswitch_columns,
1638 {{&ovsrec_table_open_vswitch, NULL, NULL},
1639 {NULL, NULL, NULL}}},
1641 {&ovsrec_table_port, port_columns,
1642 {{&ovsrec_table_port, &ovsrec_port_col_name, NULL},
1643 {NULL, NULL, NULL}}},
1645 {&ovsrec_table_ssl, ssl_columns,
1646 {{&ovsrec_table_open_vswitch, NULL, &ovsrec_open_vswitch_col_ssl}}},
1648 {NULL, NULL, {{NULL, NULL, NULL}, {NULL, NULL, NULL}}}
1652 die_if_error(char *error)
1655 ovs_fatal(0, "%s", error);
1660 to_lower_and_underscores(unsigned c)
1662 return c == '-' ? '_' : tolower(c);
1666 score_partial_match(const char *name, const char *s)
1670 if (!strcmp(name, s)) {
1673 for (score = 0; ; score++, name++, s++) {
1674 if (to_lower_and_underscores(*name) != to_lower_and_underscores(*s)) {
1676 } else if (*name == '\0') {
1677 return UINT_MAX - 1;
1680 return *s == '\0' ? score : 0;
1683 static const struct vsctl_table_class *
1684 get_table(const char *table_name)
1686 const struct vsctl_table_class *table;
1687 const struct vsctl_table_class *best_match = NULL;
1688 unsigned int best_score = 0;
1690 for (table = tables; table->class; table++) {
1691 unsigned int score = score_partial_match(table->class->name,
1693 if (score > best_score) {
1696 } else if (score == best_score) {
1702 } else if (best_score) {
1703 ovs_fatal(0, "multiple table names match \"%s\"", table_name);
1705 ovs_fatal(0, "unknown table \"%s\"", table_name);
1709 static const struct ovsdb_idl_row *
1710 get_row_by_id(struct vsctl_context *ctx, const struct vsctl_table_class *table,
1711 const struct vsctl_row_id *id, const char *record_id)
1713 const struct ovsdb_idl_row *referrer, *final;
1719 if (!id->name_column) {
1720 if (strcmp(record_id, ".")) {
1723 referrer = ovsdb_idl_first_row(ctx->idl, id->table);
1724 if (!referrer || ovsdb_idl_next_row(referrer)) {
1728 const struct ovsdb_idl_row *row;
1729 unsigned int best_score = 0;
1731 /* It might make sense to relax this assertion. */
1732 assert(id->name_column->type.key_type == OVSDB_TYPE_STRING);
1735 for (row = ovsdb_idl_first_row(ctx->idl, id->table);
1736 row != NULL && best_score != UINT_MAX;
1737 row = ovsdb_idl_next_row(row))
1739 struct ovsdb_datum name;
1741 ovsdb_idl_txn_read(row, id->name_column, &name);
1743 unsigned int score = score_partial_match(name.keys[0].string,
1745 if (score > best_score) {
1748 } else if (score == best_score) {
1752 ovsdb_datum_destroy(&name, &id->name_column->type);
1760 if (id->uuid_column) {
1761 struct ovsdb_datum uuid;
1763 assert(id->uuid_column->type.key_type == OVSDB_TYPE_UUID);
1764 assert(id->uuid_column->type.value_type == OVSDB_TYPE_VOID);
1766 ovsdb_idl_txn_read(referrer, id->uuid_column, &uuid);
1768 final = ovsdb_idl_get_row_for_uuid(ctx->idl, table->class,
1769 &uuid.keys[0].uuid);
1771 ovsdb_datum_destroy(&uuid, &id->uuid_column->type);
1779 static const struct ovsdb_idl_row *
1780 get_row(struct vsctl_context *ctx,
1781 const struct vsctl_table_class *table, const char *record_id)
1783 const struct ovsdb_idl_row *row;
1786 if (uuid_from_string(&uuid, record_id)) {
1787 row = ovsdb_idl_get_row_for_uuid(ctx->idl, table->class, &uuid);
1791 for (i = 0; i < ARRAY_SIZE(table->row_ids); i++) {
1792 row = get_row_by_id(ctx, table, &table->row_ids[i], record_id);
1801 static const struct ovsdb_idl_row *
1802 must_get_row(struct vsctl_context *ctx,
1803 const struct vsctl_table_class *table, const char *record_id)
1805 const struct ovsdb_idl_row *row = get_row(ctx, table, record_id);
1807 ovs_fatal(0, "no row \"%s\" in table %s",
1808 record_id, table->class->name);
1814 get_column(const struct vsctl_table_class *table, const char *column_name,
1815 const struct vsctl_column **columnp)
1817 const struct vsctl_column *column;
1818 const struct vsctl_column *best_match = NULL;
1819 unsigned int best_score = 0;
1821 for (column = table->columns; column->idl; column++) {
1822 if (!(column->flags & VSCF_HIDDEN)) {
1823 unsigned int score = score_partial_match(column->idl->name,
1825 if (score > best_score) {
1826 best_match = column;
1828 } else if (score == best_score) {
1834 *columnp = best_match;
1837 } else if (best_score) {
1838 return xasprintf("%s contains more than one column whose name "
1839 "matches \"%s\"", table->class->name, column_name);
1841 return xasprintf("%s does not contain a column whose name matches "
1842 "\"%s\"", table->class->name, column_name);
1846 static char * WARN_UNUSED_RESULT
1847 parse_column_key_value(const char *arg, const struct vsctl_table_class *table,
1848 const struct vsctl_column **columnp,
1849 char **keyp, char **valuep)
1851 const char *p = arg;
1854 assert(columnp || keyp);
1862 /* Parse column name. */
1866 error = ovsdb_token_parse(&p, &column_name);
1870 if (column_name[0] == '\0') {
1872 error = xasprintf("%s: missing column name", arg);
1875 error = get_column(table, column_name, columnp);
1882 /* Parse key string. */
1883 if (*p == ':' || !columnp) {
1887 error = xasprintf("%s: key not accepted here", arg);
1890 error = ovsdb_token_parse(&p, keyp);
1898 /* Parse value string. */
1901 error = xasprintf("%s: value not accepted here", arg);
1904 *valuep = xstrdup(p + 1);
1910 error = xasprintf("%s: trailing garbage in argument at offset %td",
1933 cmd_get(struct vsctl_context *ctx)
1935 const char *table_name = ctx->argv[1];
1936 const char *record_id = ctx->argv[2];
1937 const struct vsctl_table_class *table;
1938 const struct ovsdb_idl_row *row;
1939 struct ds *out = &ctx->output;
1942 table = get_table(table_name);
1943 row = must_get_row(ctx, table, record_id);
1944 for (i = 3; i < ctx->argc; i++) {
1945 const struct vsctl_column *column;
1946 struct ovsdb_datum datum;
1949 die_if_error(parse_column_key_value(ctx->argv[i], table,
1950 &column, &key_string, NULL));
1952 ovsdb_idl_txn_read(row, column->idl, &datum);
1954 union ovsdb_atom key;
1957 if (column->idl->type.value_type == OVSDB_TYPE_VOID) {
1958 ovs_fatal(0, "cannot specify key to get for non-map column %s",
1962 die_if_error(ovsdb_atom_from_string(&key,
1963 column->idl->type.key_type,
1966 idx = ovsdb_datum_find_key(&datum, &key,
1967 column->idl->type.key_type);
1968 if (idx == UINT_MAX) {
1969 ovs_fatal(0, "no key %s in %s record \"%s\" column %s",
1970 key_string, table_name, record_id,
1974 ovsdb_atom_to_string(&datum.values[idx],
1975 column->idl->type.value_type, out);
1977 ovsdb_atom_destroy(&key, column->idl->type.key_type);
1979 ovsdb_datum_to_string(&datum, &column->idl->type, out);
1981 ds_put_char(out, '\n');
1982 ovsdb_datum_destroy(&datum, &column->idl->type);
1989 list_record(const struct vsctl_table_class *table,
1990 const struct ovsdb_idl_row *row, struct ds *out)
1992 const struct vsctl_column *column;
1994 ds_put_format(out, "%-20s (RO): "UUID_FMT"\n", "_uuid",
1995 UUID_ARGS(&row->uuid));
1996 for (column = table->columns; column->idl; column++) {
1997 struct ovsdb_datum datum;
1999 if (column->flags & VSCF_HIDDEN) {
2003 ovsdb_idl_txn_read(row, column->idl, &datum);
2005 ds_put_format(out, "%-20s (%s): ", column->idl->name,
2006 column->flags & VSCF_READONLY ? "RO" : "RW");
2007 ovsdb_datum_to_string(&datum, &column->idl->type, out);
2008 ds_put_char(out, '\n');
2010 ovsdb_datum_destroy(&datum, &column->idl->type);
2015 cmd_list(struct vsctl_context *ctx)
2017 const char *table_name = ctx->argv[1];
2018 const struct vsctl_table_class *table;
2019 struct ds *out = &ctx->output;
2022 table = get_table(table_name);
2023 if (ctx->argc > 2) {
2024 for (i = 2; i < ctx->argc; i++) {
2026 ds_put_char(out, '\n');
2028 list_record(table, must_get_row(ctx, table, ctx->argv[i]), out);
2031 const struct ovsdb_idl_row *row;
2034 for (row = ovsdb_idl_first_row(ctx->idl, table->class), first = true;
2036 row = ovsdb_idl_next_row(row), first = false) {
2038 ds_put_char(out, '\n');
2040 list_record(table, row, out);
2046 check_string_constraint(const struct ovsdb_datum *datum,
2047 const char *constraint)
2054 regex = xasprintf("^%s$", constraint);
2055 retval = regcomp(&re, regex, REG_NOSUB | REG_EXTENDED);
2057 size_t length = regerror(retval, &re, NULL, 0);
2058 char *buffer = xmalloc(length);
2059 regerror(retval, &re, buffer, length);
2060 ovs_fatal(0, "internal error compiling regular expression %s: %s",
2064 for (i = 0; i < datum->n; i++) {
2065 const char *key = datum->keys[i].string;
2066 if (regexec(&re, key, 0, NULL, 0)) {
2067 ovs_fatal(0, "%s is not valid (it does not match %s)", key, regex);
2075 check_integer_constraint(const struct ovsdb_datum *datum,
2076 const char *constraint)
2082 sscanf(constraint, "[%"SCNd64",%"SCNd64"]%n", &min, &max, &n);
2084 sscanf(constraint, "[%"SCNd64",]%n", &min, &n);
2086 sscanf(constraint, "[,%"SCNd64"]%n", &max, &n);
2088 VLOG_DBG("internal error: bad integer contraint \"%s\"",
2099 for (i = 0; i < datum->n; i++) {
2100 int64_t value = datum->keys[i].integer;
2101 if (value < min || value > max) {
2102 if (max == INT64_MAX) {
2103 ovs_fatal(0, "%"PRId64" is less than the minimum "
2104 "allowed value %"PRId64, value, min);
2105 } else if (min == INT64_MIN) {
2106 ovs_fatal(0, "%"PRId64" is greater than the maximum "
2107 "allowed value %"PRId64, value, max);
2109 ovs_fatal(0, "%"PRId64" is outside the valid range %"PRId64" "
2110 "to %"PRId64" (inclusive)", value, min, max);
2117 check_constraint(const struct ovsdb_datum *datum,
2118 const struct ovsdb_type *type, const char *constraint)
2120 if (constraint && datum->n) {
2121 if (type->key_type == OVSDB_TYPE_STRING) {
2122 check_string_constraint(datum, constraint);
2123 } else if (type->key_type == OVSDB_TYPE_INTEGER) {
2124 check_integer_constraint(datum, constraint);
2130 set_column(const struct vsctl_table_class *table,
2131 const struct ovsdb_idl_row *row,
2132 const char *arg, bool force)
2134 const struct vsctl_column *column;
2135 char *key_string, *value_string;
2138 error = parse_column_key_value(arg, table, &column, &key_string,
2140 die_if_error(error);
2141 if (column->flags & VSCF_READONLY && !force) {
2142 ovs_fatal(0, "%s: cannot modify read-only column %s in table %s",
2143 arg, column->idl->name, table->class->name);
2145 if (!value_string) {
2146 ovs_fatal(0, "%s: missing value", arg);
2150 union ovsdb_atom key, value;
2151 struct ovsdb_datum old, new;
2153 if (column->idl->type.value_type == OVSDB_TYPE_VOID) {
2154 ovs_fatal(0, "cannot specify key to set for non-map column %s",
2158 die_if_error(ovsdb_atom_from_string(&key,
2159 column->idl->type.key_type,
2161 die_if_error(ovsdb_atom_from_string(&value,
2162 column->idl->type.value_type,
2165 ovsdb_datum_init_empty(&new);
2166 ovsdb_datum_add_unsafe(&new, &key, &value, &column->idl->type);
2168 ovsdb_idl_txn_read(row, column->idl, &old);
2169 ovsdb_datum_union(&old, &new, &column->idl->type, true);
2170 ovsdb_idl_txn_write(row, column->idl, &old);
2172 ovsdb_datum_destroy(&new, &column->idl->type);
2174 struct ovsdb_datum datum;
2176 die_if_error(ovsdb_datum_from_string(&datum, &column->idl->type,
2179 check_constraint(&datum, &column->idl->type,
2180 column->constraint);
2182 ovsdb_idl_txn_write(row, column->idl, &datum);
2189 cmd_set(struct vsctl_context *ctx)
2191 bool force = shash_find(&ctx->options, "--force");
2192 const char *table_name = ctx->argv[1];
2193 const char *record_id = ctx->argv[2];
2194 const struct vsctl_table_class *table;
2195 const struct ovsdb_idl_row *row;
2198 table = get_table(table_name);
2199 row = must_get_row(ctx, table, record_id);
2200 for (i = 3; i < ctx->argc; i++) {
2201 set_column(table, row, ctx->argv[i], force);
2206 cmd_add(struct vsctl_context *ctx)
2208 bool force = shash_find(&ctx->options, "--force");
2209 const char *table_name = ctx->argv[1];
2210 const char *record_id = ctx->argv[2];
2211 const char *column_name = ctx->argv[3];
2212 const struct vsctl_table_class *table;
2213 const struct vsctl_column *column;
2214 const struct ovsdb_idl_row *row;
2215 const struct ovsdb_type *type;
2216 struct ovsdb_datum old;
2219 table = get_table(table_name);
2220 row = must_get_row(ctx, table, record_id);
2221 die_if_error(get_column(table, column_name, &column));
2222 type = &column->idl->type;
2223 ovsdb_idl_txn_read(row, column->idl, &old);
2224 for (i = 4; i < ctx->argc; i++) {
2225 struct ovsdb_type add_type;
2226 struct ovsdb_datum add;
2228 if (column->flags & VSCF_READONLY && !force) {
2229 ovs_fatal(0, "%s: cannot modify read-only column %s in table %s",
2230 ctx->argv[i], column->idl->name, table_name);
2235 add_type.n_max = UINT_MAX;
2236 die_if_error(ovsdb_datum_from_string(&add, &add_type, ctx->argv[i]));
2237 ovsdb_datum_union(&old, &add, type, false);
2238 ovsdb_datum_destroy(&add, type);
2240 if (old.n > type->n_max) {
2241 ovs_fatal(0, "\"add\" operation would put %u %s in column %s of "
2242 "table %s but at most %u are allowed",
2244 type->value_type == OVSDB_TYPE_VOID ? "values" : "pairs",
2245 column->idl->name, table_name, type->n_max);
2247 ovsdb_idl_txn_write(row, column->idl, &old);
2251 cmd_remove(struct vsctl_context *ctx)
2253 bool force = shash_find(&ctx->options, "--force");
2254 const char *table_name = ctx->argv[1];
2255 const char *record_id = ctx->argv[2];
2256 const char *column_name = ctx->argv[3];
2257 const struct vsctl_table_class *table;
2258 const struct vsctl_column *column;
2259 const struct ovsdb_idl_row *row;
2260 const struct ovsdb_type *type;
2261 struct ovsdb_datum old;
2264 table = get_table(table_name);
2265 row = must_get_row(ctx, table, record_id);
2266 die_if_error(get_column(table, column_name, &column));
2267 type = &column->idl->type;
2268 ovsdb_idl_txn_read(row, column->idl, &old);
2269 for (i = 4; i < ctx->argc; i++) {
2270 struct ovsdb_type rm_type;
2271 struct ovsdb_datum rm;
2274 if (column->flags & VSCF_READONLY && !force) {
2275 ovs_fatal(0, "%s: cannot modify read-only column %s in table %s",
2276 ctx->argv[i], column->idl->name, table_name);
2281 rm_type.n_max = UINT_MAX;
2282 error = ovsdb_datum_from_string(&rm, &rm_type, ctx->argv[i]);
2283 if (error && ovsdb_type_is_map(&rm_type)) {
2285 rm_type.value_type = OVSDB_TYPE_VOID;
2286 die_if_error(ovsdb_datum_from_string(&rm, &rm_type, ctx->argv[i]));
2288 ovsdb_datum_subtract(&old, type, &rm, &rm_type);
2289 ovsdb_datum_destroy(&rm, &rm_type);
2291 if (old.n < type->n_min) {
2292 ovs_fatal(0, "\"remove\" operation would put %u %s in column %s of "
2293 "table %s but at least %u are required",
2295 type->value_type == OVSDB_TYPE_VOID ? "values" : "pairs",
2296 column->idl->name, table_name, type->n_min);
2298 ovsdb_idl_txn_write(row, column->idl, &old);
2302 cmd_clear(struct vsctl_context *ctx)
2304 bool force = shash_find(&ctx->options, "--force");
2305 const char *table_name = ctx->argv[1];
2306 const char *record_id = ctx->argv[2];
2307 const struct vsctl_table_class *table;
2308 const struct ovsdb_idl_row *row;
2311 table = get_table(table_name);
2312 row = must_get_row(ctx, table, record_id);
2313 for (i = 3; i < ctx->argc; i++) {
2314 const struct vsctl_column *column;
2315 const struct ovsdb_type *type;
2316 struct ovsdb_datum datum;
2318 die_if_error(get_column(table, ctx->argv[i], &column));
2320 type = &column->idl->type;
2321 if (column->flags & VSCF_READONLY && !force) {
2322 ovs_fatal(0, "%s: cannot modify read-only column %s in table %s",
2323 ctx->argv[i], column->idl->name, table_name);
2324 } else if (type->n_min > 0) {
2325 ovs_fatal(0, "\"clear\" operation cannot be applied to column %s "
2326 "of table %s, which is not allowed to be empty",
2327 column->idl->name, table_name);
2330 ovsdb_datum_init_empty(&datum);
2331 ovsdb_idl_txn_write(row, column->idl, &datum);
2336 cmd_create(struct vsctl_context *ctx)
2338 bool force = shash_find(&ctx->options, "--force");
2339 const char *table_name = ctx->argv[1];
2340 const struct vsctl_table_class *table;
2341 const struct ovsdb_idl_row *row;
2345 ovs_fatal(0, "\"create\" requires --force");
2348 table = get_table(table_name);
2349 row = ovsdb_idl_txn_insert(txn_from_openvswitch(ctx->ovs), table->class);
2350 for (i = 2; i < ctx->argc; i++) {
2351 set_column(table, row, ctx->argv[i], force);
2356 cmd_destroy(struct vsctl_context *ctx)
2358 bool force = shash_find(&ctx->options, "--force");
2359 bool must_exist = !shash_find(&ctx->options, "--if-exists");
2360 const char *table_name = ctx->argv[1];
2361 const struct vsctl_table_class *table;
2365 ovs_fatal(0, "\"destroy\" requires --force");
2368 table = get_table(table_name);
2369 for (i = 1; i < ctx->argc; i++) {
2370 const struct ovsdb_idl_row *row;
2372 row = (must_exist ? must_get_row : get_row)(ctx, table, ctx->argv[i]);
2374 ovsdb_idl_txn_delete(row);
2379 typedef void vsctl_handler_func(struct vsctl_context *);
2381 struct vsctl_command {
2385 vsctl_handler_func *handler;
2386 const char *options;
2389 static void run_vsctl_command(int argc, char *argv[],
2390 const struct ovsrec_open_vswitch *,
2391 struct ovsdb_idl *, struct ds *output);
2393 static struct json *
2394 where_uuid_equals(const struct uuid *uuid)
2397 json_array_create_1(
2398 json_array_create_3(
2399 json_string_create("_uuid"),
2400 json_string_create("=="),
2401 json_array_create_2(
2402 json_string_create("uuid"),
2403 json_string_create_nocopy(
2404 xasprintf(UUID_FMT, UUID_ARGS(uuid))))));
2408 do_vsctl(int argc, char *argv[], struct ovsdb_idl *idl)
2410 struct ovsdb_idl_txn *txn;
2411 const struct ovsrec_open_vswitch *ovs;
2412 enum ovsdb_idl_txn_status status;
2413 struct ds comment, *output;
2414 int64_t next_cfg = 0;
2418 txn = ovsdb_idl_txn_create(idl);
2420 ovsdb_idl_txn_set_dry_run(txn);
2424 ds_put_cstr(&comment, "ovs-vsctl:");
2425 for (i = 0; i < argc; i++) {
2426 ds_put_format(&comment, " %s", argv[i]);
2428 ovsdb_idl_txn_add_comment(txn, ds_cstr(&comment));
2429 ds_destroy(&comment);
2431 ovs = ovsrec_open_vswitch_first(idl);
2433 /* XXX add verification that table is empty */
2434 ovs = ovsrec_open_vswitch_insert(txn);
2437 if (wait_for_reload) {
2438 struct json *where = where_uuid_equals(&ovs->header_.uuid);
2439 ovsdb_idl_txn_increment(txn, "Open_vSwitch", "next_cfg", where);
2440 json_destroy(where);
2443 output = xmalloc(argc * sizeof *output);
2445 for (start = i = 0; i <= argc; i++) {
2446 if (i == argc || !strcmp(argv[i], "--")) {
2448 ds_init(&output[n_output]);
2449 run_vsctl_command(i - start, &argv[start], ovs, idl,
2450 &output[n_output++]);
2456 while ((status = ovsdb_idl_txn_commit(txn)) == TXN_INCOMPLETE) {
2458 ovsdb_idl_wait(idl);
2459 ovsdb_idl_txn_wait(txn);
2462 if (wait_for_reload && status == TXN_SUCCESS) {
2463 next_cfg = ovsdb_idl_txn_get_increment_new_value(txn);
2465 ovsdb_idl_txn_destroy(txn);
2468 case TXN_INCOMPLETE:
2472 /* Should not happen--we never call ovsdb_idl_txn_abort(). */
2473 vsctl_fatal("transaction aborted");
2480 for (i = 0; i < n_output; i++) {
2481 ds_destroy(&output[i]);
2486 vsctl_fatal("transaction error");
2492 for (i = 0; i < n_output; i++) {
2493 struct ds *ds = &output[i];
2498 for (j = 0; j < ds->length; j++) {
2499 int c = ds->string[j];
2502 fputs("\\n", stdout);
2506 fputs("\\\\", stdout);
2515 fputs(ds_cstr(ds), stdout);
2519 if (wait_for_reload && status != TXN_UNCHANGED) {
2521 const struct ovsrec_open_vswitch *ovs;
2524 OVSREC_OPEN_VSWITCH_FOR_EACH (ovs, idl) {
2525 if (ovs->cur_cfg >= next_cfg) {
2529 ovsdb_idl_wait(idl);
2538 static vsctl_handler_func *
2539 get_vsctl_handler(int argc, char *argv[], struct vsctl_context *ctx)
2541 static const struct vsctl_command all_commands[] = {
2542 /* Open vSwitch commands. */
2543 {"init", 0, 0, cmd_init, ""},
2545 /* Bridge commands. */
2546 {"add-br", 1, 3, cmd_add_br, ""},
2547 {"del-br", 1, 1, cmd_del_br, "--if-exists"},
2548 {"list-br", 0, 0, cmd_list_br, ""},
2549 {"br-exists", 1, 1, cmd_br_exists, ""},
2550 {"br-to-vlan", 1, 1, cmd_br_to_vlan, ""},
2551 {"br-to-parent", 1, 1, cmd_br_to_parent, ""},
2552 {"br-set-external-id", 2, 3, cmd_br_set_external_id, ""},
2553 {"br-get-external-id", 1, 2, cmd_br_get_external_id, ""},
2555 /* Port commands. */
2556 {"list-ports", 1, 1, cmd_list_ports, ""},
2557 {"add-port", 2, 2, cmd_add_port, ""},
2558 {"add-bond", 4, INT_MAX, cmd_add_bond, "--fake-iface"},
2559 {"del-port", 1, 2, cmd_del_port, "--if-exists"},
2560 {"port-to-br", 1, 1, cmd_port_to_br, ""},
2561 {"port-set-external-id", 2, 3, cmd_port_set_external_id, ""},
2562 {"port-get-external-id", 1, 2, cmd_port_get_external_id, ""},
2564 /* Interface commands. */
2565 {"list-ifaces", 1, 1, cmd_list_ifaces, ""},
2566 {"iface-to-br", 1, 1, cmd_iface_to_br, ""},
2567 {"iface-set-external-id", 2, 3, cmd_iface_set_external_id, ""},
2568 {"iface-get-external-id", 1, 2, cmd_iface_get_external_id, ""},
2570 /* Controller commands. */
2571 {"get-controller", 0, 1, cmd_get_controller, ""},
2572 {"del-controller", 0, 1, cmd_del_controller, ""},
2573 {"set-controller", 1, 2, cmd_set_controller, ""},
2574 {"get-fail-mode", 0, 1, cmd_get_fail_mode, ""},
2575 {"del-fail-mode", 0, 1, cmd_del_fail_mode, ""},
2576 {"set-fail-mode", 1, 2, cmd_set_fail_mode, ""},
2579 {"get-ssl", 0, 0, cmd_get_ssl, ""},
2580 {"del-ssl", 0, 0, cmd_del_ssl, ""},
2581 {"set-ssl", 3, 3, cmd_set_ssl, "--bootstrap"},
2583 /* Parameter commands. */
2584 {"get", 3, INT_MAX, cmd_get, ""},
2585 {"list", 1, INT_MAX, cmd_list, ""},
2586 {"set", 3, INT_MAX, cmd_set, "--force"},
2587 {"add", 4, INT_MAX, cmd_add, "--force"},
2588 {"remove", 4, INT_MAX, cmd_remove, "--force"},
2589 {"clear", 3, INT_MAX, cmd_clear, "--force"},
2590 {"create", 2, INT_MAX, cmd_create, "--force"},
2591 {"destroy", 1, INT_MAX, cmd_destroy, "--force,--if-exists"},
2594 const struct vsctl_command *p;
2597 shash_init(&ctx->options);
2598 for (i = 0; i < argc; i++) {
2599 if (argv[i][0] != '-') {
2602 if (!shash_add_once(&ctx->options, argv[i], NULL)) {
2603 vsctl_fatal("'%s' option specified multiple times", argv[i]);
2607 vsctl_fatal("missing command name");
2610 for (p = all_commands; p < &all_commands[ARRAY_SIZE(all_commands)]; p++) {
2611 if (!strcmp(p->name, argv[i])) {
2612 struct shash_node *node;
2615 SHASH_FOR_EACH (node, &ctx->options) {
2616 const char *s = strstr(p->options, node->name);
2617 int end = s ? s[strlen(node->name)] : EOF;
2618 if (end != ',' && end != ' ' && end != '\0') {
2619 vsctl_fatal("'%s' command has no '%s' option",
2620 argv[i], node->name);
2624 n_arg = argc - i - 1;
2625 if (n_arg < p->min_args) {
2626 vsctl_fatal("'%s' command requires at least %d arguments",
2627 p->name, p->min_args);
2628 } else if (n_arg > p->max_args) {
2629 vsctl_fatal("'%s' command takes at most %d arguments",
2630 p->name, p->max_args);
2632 ctx->argc = n_arg + 1;
2633 ctx->argv = &argv[i];
2639 vsctl_fatal("unknown command '%s'; use --help for help", argv[i]);
2643 check_vsctl_command(int argc, char *argv[])
2645 struct vsctl_context ctx;
2647 get_vsctl_handler(argc, argv, &ctx);
2648 shash_destroy(&ctx.options);
2652 run_vsctl_command(int argc, char *argv[],
2653 const struct ovsrec_open_vswitch *ovs,
2654 struct ovsdb_idl *idl, struct ds *output)
2656 vsctl_handler_func *function;
2657 struct vsctl_context ctx;
2659 function = get_vsctl_handler(argc, argv, &ctx);
2662 ds_init(&ctx.output);
2664 *output = ctx.output;
2665 shash_destroy(&ctx.options);