2 * Copyright (c) 2009 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.
28 #include "command-line.h"
31 #include "dynamic-string.h"
33 #include "ovsdb-idl.h"
34 #include "poll-loop.h"
36 #include "vswitchd/vswitch-idl.h"
41 #define THIS_MODULE VLM_vsctl
43 /* --db: The database server to contact. */
44 static const char *db;
46 /* --oneline: Write each command's output as a single line? */
49 /* --dry-run: Do not commit any changes. */
52 /* --no-wait: Wait for ovs-vswitchd to reload its configuration? */
53 static bool wait_for_reload = true;
55 /* --timeout: Time to wait for a connection to 'db'. */
56 static int timeout = 5;
58 static void vsctl_fatal(const char *, ...) PRINTF_FORMAT(1, 2) NO_RETURN;
59 static char *default_db(void);
60 static void usage(void) NO_RETURN;
61 static void parse_options(int argc, char *argv[]);
63 static void check_vsctl_command(int argc, char *argv[]);
64 static void do_vsctl(int argc, char *argv[], struct ovsdb_idl *idl);
67 main(int argc, char *argv[])
69 struct ovsdb_idl *idl;
72 int start, n_commands;
76 set_program_name(argv[0]);
77 signal(SIGPIPE, SIG_IGN);
80 vlog_set_levels(VLM_ANY_MODULE, VLF_CONSOLE, VLL_WARN);
81 vlog_set_levels(VLM_reconnect, VLF_ANY_FACILITY, VLL_WARN);
82 parse_options(argc, argv);
88 /* Log our arguments. This is often valuable for debugging systems. */
90 for (i = 1; i < argc; i++) {
91 ds_put_format(&args, " %s", argv[i]);
93 VLOG_INFO("Called as%s", ds_cstr(&args));
96 /* Do basic command syntax checking. */
98 for (start = i = optind; i <= argc; i++) {
99 if (i == argc || !strcmp(argv[i], "--")) {
101 check_vsctl_command(i - start, &argv[start]);
108 vsctl_fatal("missing command name (use --help for help)");
111 /* Now execute the commands. */
112 idl = ovsdb_idl_create(db, &ovsrec_idl_class);
113 seqno = ovsdb_idl_get_seqno(idl);
116 unsigned int new_seqno;
119 new_seqno = ovsdb_idl_get_seqno(idl);
120 if (new_seqno != seqno) {
122 vsctl_fatal("too many database inconsistency failures");
124 do_vsctl(argc - optind, argv + optind, idl);
134 vsctl_fatal(const char *format, ...)
139 va_start(args, format);
140 message = xvasprintf(format, args);
143 vlog_set_levels(VLM_vsctl, VLF_CONSOLE, VLL_EMER);
144 VLOG_ERR("%s", message);
145 ovs_fatal(0, "%s", message);
149 parse_options(int argc, char *argv[])
152 OPT_DB = UCHAR_MAX + 1,
158 static struct option long_options[] = {
159 {"db", required_argument, 0, OPT_DB},
160 {"no-syslog", no_argument, 0, OPT_NO_SYSLOG},
161 {"no-wait", no_argument, 0, OPT_NO_WAIT},
162 {"dry-run", no_argument, 0, OPT_DRY_RUN},
163 {"oneline", no_argument, 0, OPT_ONELINE},
164 {"timeout", required_argument, 0, 't'},
165 {"verbose", optional_argument, 0, 'v'},
166 {"help", no_argument, 0, 'h'},
167 {"version", no_argument, 0, 'V'},
173 unsigned long int timeout;
176 c = getopt_long(argc, argv, "+v::hVt:", long_options, NULL);
191 vlog_set_levels(VLM_vsctl, VLF_SYSLOG, VLL_WARN);
195 wait_for_reload = false;
206 OVS_PRINT_VERSION(0, 0);
210 timeout = strtoul(optarg, NULL, 10);
212 ovs_fatal(0, "value %s on -t or --timeout is invalid",
218 vlog_set_verbosity(optarg);
237 printf("%s: ovs-vswitchd management utility\n"
238 "usage: %s [OPTIONS] COMMAND [ARG...]\n",
239 program_name, program_name);
240 printf("\nBridge commands:\n"
242 "create a new bridge named BRIDGE\n"
243 " add-br BRIDGE PARENT VLAN "
244 "create new fake bridge BRIDGE in PARENT on VLAN\n"
246 "delete BRIDGE and all of its ports\n"
248 "print the names of all the bridges\n"
250 "test whether BRIDGE exists\n"
251 " br-to-vlan BRIDGE "
252 "print the VLAN which BRIDGE is on\n"
253 " br-to-parent BRIDGE "
254 "print the parent of BRIDGE\n"
255 " br-set-external-id BRIDGE KEY VALUE"
256 " set KEY on BRIDGE to VALUE\n"
257 " br-set-external-id BRIDGE KEY"
258 " unset KEY on BRIDGE\n"
259 " br-get-external-id BRIDGE KEY"
260 " print value of KEY on BRIDGE\n"
261 " br-get-external-id BRIDGE"
262 " list key-value pairs on BRIDGE\n"
264 printf("\nPort commands:\n"
265 " list-ports BRIDGE "
266 "print the names of all the ports on BRIDGE\n"
267 " add-port BRIDGE PORT "
268 "add network device PORT to BRIDGE\n"
269 " add-bond BRIDGE PORT IFACE... "
270 "add new bonded port PORT in BRIDGE from IFACES\n"
271 " del-port [BRIDGE] PORT "
272 "delete PORT (which may be bonded) from BRIDGE\n"
274 "print name of bridge that contains PORT\n"
275 " port-set-external-id PORT KEY VALUE"
276 " set KEY on PORT to VALUE\n"
277 " port-set-external-id PORT KEY"
278 " unset KEY on PORT\n"
279 " port-get-external-id PORT KEY"
280 " print value of KEY on PORT\n"
281 " port-get-external-id PORT"
282 " list key-value pairs on PORT\n"
283 "A bond is considered to be a single port.\n"
285 printf("\nInterface commands (a bond consists of multiple interfaces):\n"
286 " list-ifaces BRIDGE "
287 "print the names of all the interfaces on BRIDGE\n"
288 " iface-to-br IFACE "
289 "print name of bridge that contains IFACE\n"
290 " iface-set-external-id IFACE KEY VALUE"
291 " set KEY on IFACE to VALUE\n"
292 " iface-set-external-id IFACE KEY"
293 " unset KEY on IFACE\n"
294 " iface-get-external-id IFACE KEY"
295 " print value of KEY on IFACE\n"
296 " iface-get-external-id IFACE"
297 " list key-value pairs on IFACE\n"
299 printf("\nOptions:\n"
301 "connect to DATABASE\n"
305 "print exactly one line of output per command\n",
308 printf("\nOther options:\n"
310 "display this help message\n"
312 "display version information\n");
321 def = xasprintf("unix:%s/ovsdb-server", ovs_rundir);
326 struct vsctl_context {
329 const struct ovsrec_open_vswitch *ovs;
331 struct shash options;
334 struct vsctl_bridge {
335 struct ovsrec_bridge *br_cfg;
337 struct vsctl_bridge *parent;
342 struct ovsrec_port *port_cfg;
343 struct vsctl_bridge *bridge;
347 struct ovsrec_interface *iface_cfg;
348 struct vsctl_port *port;
352 struct shash bridges;
357 static struct ovsdb_idl_txn *
358 txn_from_openvswitch(const struct ovsrec_open_vswitch *ovs)
360 return ovsdb_idl_txn_get(&ovs->header_);
363 static struct vsctl_bridge *
364 add_bridge(struct vsctl_info *b,
365 struct ovsrec_bridge *br_cfg, const char *name,
366 struct vsctl_bridge *parent, int vlan)
368 struct vsctl_bridge *br = xmalloc(sizeof *br);
370 br->name = xstrdup(name);
373 shash_add(&b->bridges, br->name, br);
378 port_is_fake_bridge(const struct ovsrec_port *port_cfg)
380 return (port_cfg->fake_bridge
382 && *port_cfg->tag >= 1 && *port_cfg->tag <= 4095);
385 static struct vsctl_bridge *
386 find_vlan_bridge(struct vsctl_info *info,
387 struct vsctl_bridge *parent, int vlan)
389 struct shash_node *node;
391 SHASH_FOR_EACH (node, &info->bridges) {
392 struct vsctl_bridge *br = node->data;
393 if (br->parent == parent && br->vlan == vlan) {
402 free_info(struct vsctl_info *info)
404 struct shash_node *node;
406 SHASH_FOR_EACH (node, &info->bridges) {
407 struct vsctl_bridge *bridge = node->data;
411 shash_destroy(&info->bridges);
413 SHASH_FOR_EACH (node, &info->ports) {
414 struct vsctl_port *port = node->data;
417 shash_destroy(&info->ports);
419 SHASH_FOR_EACH (node, &info->ifaces) {
420 struct vsctl_iface *iface = node->data;
423 shash_destroy(&info->ifaces);
427 get_info(const struct ovsrec_open_vswitch *ovs, struct vsctl_info *info)
429 struct shash bridges, ports;
432 shash_init(&info->bridges);
433 shash_init(&info->ports);
434 shash_init(&info->ifaces);
436 shash_init(&bridges);
438 for (i = 0; i < ovs->n_bridges; i++) {
439 struct ovsrec_bridge *br_cfg = ovs->bridges[i];
440 struct vsctl_bridge *br;
443 if (!shash_add_once(&bridges, br_cfg->name, NULL)) {
444 VLOG_WARN("%s: database contains duplicate bridge name",
448 br = add_bridge(info, br_cfg, br_cfg->name, NULL, 0);
453 for (j = 0; j < br_cfg->n_ports; j++) {
454 struct ovsrec_port *port_cfg = br_cfg->ports[j];
456 if (!shash_add_once(&ports, port_cfg->name, NULL)) {
457 VLOG_WARN("%s: database contains duplicate port name",
462 if (port_is_fake_bridge(port_cfg)
463 && shash_add_once(&bridges, port_cfg->name, NULL)) {
464 add_bridge(info, NULL, port_cfg->name, br, *port_cfg->tag);
468 shash_destroy(&bridges);
469 shash_destroy(&ports);
471 shash_init(&bridges);
473 for (i = 0; i < ovs->n_bridges; i++) {
474 struct ovsrec_bridge *br_cfg = ovs->bridges[i];
475 struct vsctl_bridge *br;
478 if (!shash_add_once(&bridges, br_cfg->name, NULL)) {
481 br = shash_find_data(&info->bridges, br_cfg->name);
482 for (j = 0; j < br_cfg->n_ports; j++) {
483 struct ovsrec_port *port_cfg = br_cfg->ports[j];
484 struct vsctl_port *port;
487 if (!shash_add_once(&ports, port_cfg->name, NULL)) {
491 if (port_is_fake_bridge(port_cfg)
492 && !shash_add_once(&bridges, port_cfg->name, NULL)) {
496 port = xmalloc(sizeof *port);
497 port->port_cfg = port_cfg;
499 && *port_cfg->tag >= 1 && *port_cfg->tag <= 4095) {
500 port->bridge = find_vlan_bridge(info, br, *port_cfg->tag);
507 shash_add(&info->ports, port_cfg->name, port);
509 for (k = 0; k < port_cfg->n_interfaces; k++) {
510 struct ovsrec_interface *iface_cfg = port_cfg->interfaces[k];
511 struct vsctl_iface *iface;
513 if (shash_find(&info->ifaces, iface_cfg->name)) {
514 VLOG_WARN("%s: database contains duplicate interface name",
519 iface = xmalloc(sizeof *iface);
520 iface->iface_cfg = iface_cfg;
522 shash_add(&info->ifaces, iface_cfg->name, iface);
526 shash_destroy(&bridges);
527 shash_destroy(&ports);
531 check_conflicts(struct vsctl_info *info, const char *name,
534 struct vsctl_iface *iface;
535 struct vsctl_port *port;
537 if (shash_find(&info->bridges, name)) {
538 vsctl_fatal("%s because a bridge named %s already exists",
542 port = shash_find_data(&info->ports, name);
544 vsctl_fatal("%s because a port named %s already exists on "
545 "bridge %s", msg, name, port->bridge->name);
548 iface = shash_find_data(&info->ifaces, name);
550 vsctl_fatal("%s because an interface named %s already exists "
551 "on bridge %s", msg, name, iface->port->bridge->name);
557 static struct vsctl_bridge *
558 find_bridge(struct vsctl_info *info, const char *name, bool must_exist)
560 struct vsctl_bridge *br = shash_find_data(&info->bridges, name);
561 if (must_exist && !br) {
562 vsctl_fatal("no bridge named %s", name);
567 static struct vsctl_port *
568 find_port(struct vsctl_info *info, const char *name, bool must_exist)
570 struct vsctl_port *port = shash_find_data(&info->ports, name);
571 if (port && !strcmp(name, port->bridge->name)) {
574 if (must_exist && !port) {
575 vsctl_fatal("no port named %s", name);
580 static struct vsctl_iface *
581 find_iface(struct vsctl_info *info, const char *name, bool must_exist)
583 struct vsctl_iface *iface = shash_find_data(&info->ifaces, name);
584 if (iface && !strcmp(name, iface->port->bridge->name)) {
587 if (must_exist && !iface) {
588 vsctl_fatal("no interface named %s", name);
594 bridge_insert_port(struct ovsrec_bridge *br, struct ovsrec_port *port)
596 struct ovsrec_port **ports;
599 ports = xmalloc(sizeof *br->ports * (br->n_ports + 1));
600 for (i = 0; i < br->n_ports; i++) {
601 ports[i] = br->ports[i];
603 ports[br->n_ports] = port;
604 ovsrec_bridge_set_ports(br, ports, br->n_ports + 1);
609 bridge_delete_port(struct ovsrec_bridge *br, struct ovsrec_port *port)
611 struct ovsrec_port **ports;
614 ports = xmalloc(sizeof *br->ports * br->n_ports);
615 for (i = n = 0; i < br->n_ports; i++) {
616 if (br->ports[i] != port) {
617 ports[n++] = br->ports[i];
620 ovsrec_bridge_set_ports(br, ports, n);
625 ovs_insert_bridge(const struct ovsrec_open_vswitch *ovs,
626 struct ovsrec_bridge *bridge)
628 struct ovsrec_bridge **bridges;
631 bridges = xmalloc(sizeof *ovs->bridges * (ovs->n_bridges + 1));
632 for (i = 0; i < ovs->n_bridges; i++) {
633 bridges[i] = ovs->bridges[i];
635 bridges[ovs->n_bridges] = bridge;
636 ovsrec_open_vswitch_set_bridges(ovs, bridges, ovs->n_bridges + 1);
641 ovs_delete_bridge(const struct ovsrec_open_vswitch *ovs,
642 struct ovsrec_bridge *bridge)
644 struct ovsrec_bridge **bridges;
647 bridges = xmalloc(sizeof *ovs->bridges * ovs->n_bridges);
648 for (i = n = 0; i < ovs->n_bridges; i++) {
649 if (ovs->bridges[i] != bridge) {
650 bridges[n++] = ovs->bridges[i];
653 ovsrec_open_vswitch_set_bridges(ovs, bridges, n);
658 cmd_init(struct vsctl_context *ctx UNUSED)
663 cmd_add_br(struct vsctl_context *ctx)
665 const char *br_name = ctx->argv[1];
666 struct vsctl_info info;
668 get_info(ctx->ovs, &info);
669 check_conflicts(&info, br_name,
670 xasprintf("cannot create a bridge named %s", br_name));
672 if (ctx->argc == 2) {
673 struct ovsrec_bridge *br;
674 struct ovsrec_port *port;
675 struct ovsrec_interface *iface;
677 iface = ovsrec_interface_insert(txn_from_openvswitch(ctx->ovs));
678 ovsrec_interface_set_name(iface, br_name);
680 port = ovsrec_port_insert(txn_from_openvswitch(ctx->ovs));
681 ovsrec_port_set_name(port, br_name);
682 ovsrec_port_set_interfaces(port, &iface, 1);
684 br = ovsrec_bridge_insert(txn_from_openvswitch(ctx->ovs));
685 ovsrec_bridge_set_name(br, br_name);
686 ovsrec_bridge_set_ports(br, &port, 1);
688 ovs_insert_bridge(ctx->ovs, br);
689 } else if (ctx->argc == 3) {
690 vsctl_fatal("'%s' command takes exactly 1 or 3 arguments",
692 } else if (ctx->argc == 4) {
693 const char *parent_name = ctx->argv[2];
694 int vlan = atoi(ctx->argv[3]);
695 struct ovsrec_bridge *br;
696 struct vsctl_bridge *parent;
697 struct ovsrec_port *port;
698 struct ovsrec_interface *iface;
701 if (vlan < 1 || vlan > 4095) {
702 vsctl_fatal("%s: vlan must be between 1 and 4095", ctx->argv[0]);
705 parent = find_bridge(&info, parent_name, false);
706 if (parent && parent->vlan) {
707 vsctl_fatal("cannot create brdige with fake bridge as parent");
710 vsctl_fatal("parent bridge %s does not exist", parent_name);
714 iface = ovsrec_interface_insert(txn_from_openvswitch(ctx->ovs));
715 ovsrec_interface_set_name(iface, br_name);
716 ovsrec_interface_set_type(iface, "internal");
718 port = ovsrec_port_insert(txn_from_openvswitch(ctx->ovs));
719 ovsrec_port_set_name(port, br_name);
720 ovsrec_port_set_interfaces(port, &iface, 1);
721 ovsrec_port_set_fake_bridge(port, true);
722 ovsrec_port_set_tag(port, &tag, 1);
724 bridge_insert_port(br, port);
733 del_port(struct vsctl_info *info, struct vsctl_port *port)
735 struct shash_node *node;
737 SHASH_FOR_EACH (node, &info->ifaces) {
738 struct vsctl_iface *iface = node->data;
739 if (iface->port == port) {
740 ovsrec_interface_delete(iface->iface_cfg);
743 ovsrec_port_delete(port->port_cfg);
745 bridge_delete_port((port->bridge->parent
746 ? port->bridge->parent->br_cfg
747 : port->bridge->br_cfg), port->port_cfg);
751 cmd_del_br(struct vsctl_context *ctx)
753 bool must_exist = !shash_find(&ctx->options, "--if-exists");
754 struct vsctl_bridge *bridge;
755 struct vsctl_info info;
757 get_info(ctx->ovs, &info);
758 bridge = find_bridge(&info, ctx->argv[1], must_exist);
760 struct shash_node *node;
762 SHASH_FOR_EACH (node, &info.ports) {
763 struct vsctl_port *port = node->data;
764 if (port->bridge == bridge
765 || !strcmp(port->port_cfg->name, bridge->name)) {
766 del_port(&info, port);
769 if (bridge->br_cfg) {
770 ovsrec_bridge_delete(bridge->br_cfg);
771 ovs_delete_bridge(ctx->ovs, bridge->br_cfg);
778 output_sorted(struct svec *svec, struct ds *output)
784 SVEC_FOR_EACH (i, name, svec) {
785 ds_put_format(output, "%s\n", name);
790 cmd_list_br(struct vsctl_context *ctx)
792 struct shash_node *node;
793 struct vsctl_info info;
796 get_info(ctx->ovs, &info);
799 SHASH_FOR_EACH (node, &info.bridges) {
800 struct vsctl_bridge *br = node->data;
801 svec_add(&bridges, br->name);
803 output_sorted(&bridges, &ctx->output);
804 svec_destroy(&bridges);
810 cmd_br_exists(struct vsctl_context *ctx)
812 struct vsctl_info info;
814 get_info(ctx->ovs, &info);
815 if (!find_bridge(&info, ctx->argv[1], false)) {
821 /* Returns true if 'b_prefix' (of length 'b_prefix_len') concatenated with 'b'
822 * equals 'a', false otherwise. */
824 key_matches(const char *a,
825 const char *b_prefix, size_t b_prefix_len, const char *b)
827 return !strncmp(a, b_prefix, b_prefix_len) && !strcmp(a + b_prefix_len, b);
831 set_external_id(char **old_keys, char **old_values, size_t old_n,
832 char *key, char *value,
833 char ***new_keysp, char ***new_valuesp, size_t *new_np)
840 new_keys = xmalloc(sizeof *new_keys * (old_n + 1));
841 new_values = xmalloc(sizeof *new_values * (old_n + 1));
843 for (i = 0; i < old_n; i++) {
844 if (strcmp(key, old_keys[i])) {
845 new_keys[new_n] = old_keys[i];
846 new_values[new_n] = old_values[i];
851 new_keys[new_n] = key;
852 new_values[new_n] = value;
855 *new_keysp = new_keys;
856 *new_valuesp = new_values;
861 cmd_br_set_external_id(struct vsctl_context *ctx)
863 struct vsctl_info info;
864 struct vsctl_bridge *bridge;
865 char **keys, **values;
868 get_info(ctx->ovs, &info);
869 bridge = find_bridge(&info, ctx->argv[1], true);
870 if (bridge->br_cfg) {
871 set_external_id(bridge->br_cfg->key_external_ids,
872 bridge->br_cfg->value_external_ids,
873 bridge->br_cfg->n_external_ids,
874 ctx->argv[2], ctx->argc >= 4 ? ctx->argv[3] : NULL,
876 ovsrec_bridge_set_external_ids(bridge->br_cfg, keys, values, n);
878 char *key = xasprintf("fake-bridge-%s", ctx->argv[2]);
879 struct vsctl_port *port = shash_find_data(&info.ports, ctx->argv[1]);
880 set_external_id(port->port_cfg->key_external_ids,
881 port->port_cfg->value_external_ids,
882 port->port_cfg->n_external_ids,
883 key, ctx->argc >= 4 ? ctx->argv[3] : NULL,
885 ovsrec_port_set_external_ids(port->port_cfg, keys, values, n);
895 get_external_id(char **keys, char **values, size_t n,
896 const char *prefix, const char *key,
899 size_t prefix_len = strlen(prefix);
904 for (i = 0; i < n; i++) {
905 if (!key && !strncmp(keys[i], prefix, prefix_len)) {
906 svec_add_nocopy(&svec, xasprintf("%s=%s",
907 keys[i] + prefix_len, values[i]));
908 } else if (key_matches(keys[i], prefix, prefix_len, key)) {
909 svec_add(&svec, values[i]);
913 output_sorted(&svec, output);
918 cmd_br_get_external_id(struct vsctl_context *ctx)
920 struct vsctl_info info;
921 struct vsctl_bridge *bridge;
923 get_info(ctx->ovs, &info);
924 bridge = find_bridge(&info, ctx->argv[1], true);
925 if (bridge->br_cfg) {
926 get_external_id(bridge->br_cfg->key_external_ids,
927 bridge->br_cfg->value_external_ids,
928 bridge->br_cfg->n_external_ids,
929 "", ctx->argc >= 3 ? ctx->argv[2] : NULL,
932 struct vsctl_port *port = shash_find_data(&info.ports, ctx->argv[1]);
933 get_external_id(port->port_cfg->key_external_ids,
934 port->port_cfg->value_external_ids,
935 port->port_cfg->n_external_ids,
936 "fake-bridge-", ctx->argc >= 3 ? ctx->argv[2] : NULL, &ctx->output);
943 cmd_list_ports(struct vsctl_context *ctx)
945 struct vsctl_bridge *br;
946 struct shash_node *node;
947 struct vsctl_info info;
950 get_info(ctx->ovs, &info);
951 br = find_bridge(&info, ctx->argv[1], true);
954 SHASH_FOR_EACH (node, &info.ports) {
955 struct vsctl_port *port = node->data;
957 if (strcmp(port->port_cfg->name, br->name) && br == port->bridge) {
958 svec_add(&ports, port->port_cfg->name);
961 output_sorted(&ports, &ctx->output);
962 svec_destroy(&ports);
968 add_port(const struct ovsrec_open_vswitch *ovs,
969 const char *br_name, const char *port_name,
970 char *iface_names[], int n_ifaces)
972 struct vsctl_info info;
973 struct vsctl_bridge *bridge;
974 struct ovsrec_interface **ifaces;
975 struct ovsrec_port *port;
978 get_info(ovs, &info);
979 check_conflicts(&info, port_name,
980 xasprintf("cannot create a port named %s", port_name));
981 /* XXX need to check for conflicts on interfaces too */
982 bridge = find_bridge(&info, br_name, true);
984 ifaces = xmalloc(n_ifaces * sizeof *ifaces);
985 for (i = 0; i < n_ifaces; i++) {
986 ifaces[i] = ovsrec_interface_insert(txn_from_openvswitch(ovs));
987 ovsrec_interface_set_name(ifaces[i], iface_names[i]);
990 port = ovsrec_port_insert(txn_from_openvswitch(ovs));
991 ovsrec_port_set_name(port, port_name);
992 ovsrec_port_set_interfaces(port, ifaces, n_ifaces);
996 int64_t tag = bridge->vlan;
997 ovsrec_port_set_tag(port, &tag, 1);
1000 bridge_insert_port((bridge->parent ? bridge->parent->br_cfg
1001 : bridge->br_cfg), port);
1007 cmd_add_port(struct vsctl_context *ctx)
1009 add_port(ctx->ovs, ctx->argv[1], ctx->argv[2], &ctx->argv[2], 1);
1013 cmd_add_bond(struct vsctl_context *ctx)
1015 add_port(ctx->ovs, ctx->argv[1], ctx->argv[2], &ctx->argv[3], ctx->argc - 3);
1019 cmd_del_port(struct vsctl_context *ctx)
1021 bool must_exist = !shash_find(&ctx->options, "--if-exists");
1022 struct vsctl_info info;
1024 get_info(ctx->ovs, &info);
1025 if (ctx->argc == 2) {
1026 struct vsctl_port *port = find_port(&info, ctx->argv[1], must_exist);
1028 del_port(&info, port);
1030 } else if (ctx->argc == 3) {
1031 struct vsctl_bridge *bridge = find_bridge(&info, ctx->argv[1], true);
1032 struct vsctl_port *port = find_port(&info, ctx->argv[2], must_exist);
1035 if (port->bridge == bridge) {
1036 del_port(&info, port);
1037 } else if (port->bridge->parent == bridge) {
1038 vsctl_fatal("bridge %s does not have a port %s (although its "
1039 "parent bridge %s does)",
1040 ctx->argv[1], ctx->argv[2], bridge->parent->name);
1042 vsctl_fatal("bridge %s does not have a port %s",
1043 ctx->argv[1], ctx->argv[2]);
1051 cmd_port_to_br(struct vsctl_context *ctx)
1053 struct vsctl_port *port;
1054 struct vsctl_info info;
1056 get_info(ctx->ovs, &info);
1057 port = find_port(&info, ctx->argv[1], true);
1058 ds_put_format(&ctx->output, "%s\n", port->bridge->name);
1063 cmd_port_set_external_id(struct vsctl_context *ctx)
1065 struct vsctl_info info;
1066 struct vsctl_port *port;
1067 char **keys, **values;
1070 get_info(ctx->ovs, &info);
1071 port = find_port(&info, ctx->argv[1], true);
1072 set_external_id(port->port_cfg->key_external_ids,
1073 port->port_cfg->value_external_ids,
1074 port->port_cfg->n_external_ids,
1075 ctx->argv[2], ctx->argc >= 4 ? ctx->argv[3] : NULL,
1076 &keys, &values, &n);
1077 ovsrec_port_set_external_ids(port->port_cfg, keys, values, n);
1085 cmd_port_get_external_id(struct vsctl_context *ctx)
1087 struct vsctl_info info;
1088 struct vsctl_port *port;
1090 get_info(ctx->ovs, &info);
1091 port = find_port(&info, ctx->argv[1], true);
1092 get_external_id(port->port_cfg->key_external_ids,
1093 port->port_cfg->value_external_ids,
1094 port->port_cfg->n_external_ids,
1095 "", ctx->argc >= 3 ? ctx->argv[2] : NULL, &ctx->output);
1100 cmd_br_to_vlan(struct vsctl_context *ctx)
1102 struct vsctl_bridge *bridge;
1103 struct vsctl_info info;
1105 get_info(ctx->ovs, &info);
1106 bridge = find_bridge(&info, ctx->argv[1], true);
1107 ds_put_format(&ctx->output, "%d\n", bridge->vlan);
1112 cmd_br_to_parent(struct vsctl_context *ctx)
1114 struct vsctl_bridge *bridge;
1115 struct vsctl_info info;
1117 get_info(ctx->ovs, &info);
1118 bridge = find_bridge(&info, ctx->argv[1], true);
1119 if (bridge->parent) {
1120 bridge = bridge->parent;
1122 ds_put_format(&ctx->output, "%s\n", bridge->name);
1127 cmd_list_ifaces(struct vsctl_context *ctx)
1129 struct vsctl_bridge *br;
1130 struct shash_node *node;
1131 struct vsctl_info info;
1134 get_info(ctx->ovs, &info);
1135 br = find_bridge(&info, ctx->argv[1], true);
1138 SHASH_FOR_EACH (node, &info.ifaces) {
1139 struct vsctl_iface *iface = node->data;
1141 if (strcmp(iface->iface_cfg->name, br->name)
1142 && br == iface->port->bridge) {
1143 svec_add(&ifaces, iface->iface_cfg->name);
1146 output_sorted(&ifaces, &ctx->output);
1147 svec_destroy(&ifaces);
1153 cmd_iface_to_br(struct vsctl_context *ctx)
1155 struct vsctl_iface *iface;
1156 struct vsctl_info info;
1158 get_info(ctx->ovs, &info);
1159 iface = find_iface(&info, ctx->argv[1], true);
1160 ds_put_format(&ctx->output, "%s\n", iface->port->bridge->name);
1165 cmd_iface_set_external_id(struct vsctl_context *ctx)
1167 struct vsctl_info info;
1168 struct vsctl_iface *iface;
1169 char **keys, **values;
1172 get_info(ctx->ovs, &info);
1173 iface = find_iface(&info, ctx->argv[1], true);
1174 set_external_id(iface->iface_cfg->key_external_ids,
1175 iface->iface_cfg->value_external_ids,
1176 iface->iface_cfg->n_external_ids,
1177 ctx->argv[2], ctx->argc >= 4 ? ctx->argv[3] : NULL,
1178 &keys, &values, &n);
1179 ovsrec_interface_set_external_ids(iface->iface_cfg, keys, values, n);
1187 cmd_iface_get_external_id(struct vsctl_context *ctx)
1189 struct vsctl_info info;
1190 struct vsctl_iface *iface;
1192 get_info(ctx->ovs, &info);
1193 iface = find_iface(&info, ctx->argv[1], true);
1194 get_external_id(iface->iface_cfg->key_external_ids,
1195 iface->iface_cfg->value_external_ids,
1196 iface->iface_cfg->n_external_ids,
1197 "", ctx->argc >= 3 ? ctx->argv[2] : NULL, &ctx->output);
1201 typedef void vsctl_handler_func(struct vsctl_context *);
1203 struct vsctl_command {
1207 vsctl_handler_func *handler;
1208 const char *options;
1211 static void run_vsctl_command(int argc, char *argv[],
1212 const struct ovsrec_open_vswitch *ovs,
1215 static struct json *
1216 where_uuid_equals(const struct uuid *uuid)
1219 json_array_create_1(
1220 json_array_create_3(
1221 json_string_create("_uuid"),
1222 json_string_create("=="),
1223 json_array_create_2(
1224 json_string_create("uuid"),
1225 json_string_create_nocopy(
1226 xasprintf(UUID_FMT, UUID_ARGS(uuid))))));
1230 do_vsctl(int argc, char *argv[], struct ovsdb_idl *idl)
1232 struct ovsdb_idl_txn *txn;
1233 const struct ovsrec_open_vswitch *ovs;
1234 enum ovsdb_idl_txn_status status;
1235 struct ds comment, *output;
1240 txn = ovsdb_idl_txn_create(idl);
1242 ovsdb_idl_txn_set_dry_run(txn);
1246 ds_put_cstr(&comment, "ovs-vsctl:");
1247 for (i = 0; i < argc; i++) {
1248 ds_put_format(&comment, " %s", argv[i]);
1250 ovsdb_idl_txn_add_comment(txn, ds_cstr(&comment));
1251 ds_destroy(&comment);
1253 ovs = ovsrec_open_vswitch_first(idl);
1255 /* XXX add verification that table is empty */
1256 ovs = ovsrec_open_vswitch_insert(txn);
1259 if (wait_for_reload) {
1260 struct json *where = where_uuid_equals(&ovs->header_.uuid);
1261 ovsdb_idl_txn_increment(txn, "Open_vSwitch", "next_cfg",
1263 json_destroy(where);
1266 output = xmalloc(argc * sizeof *output);
1268 for (start = i = 0; i <= argc; i++) {
1269 if (i == argc || !strcmp(argv[i], "--")) {
1271 ds_init(&output[n_output]);
1272 run_vsctl_command(i - start, &argv[start], ovs,
1273 &output[n_output++]);
1279 while ((status = ovsdb_idl_txn_commit(txn)) == TXN_INCOMPLETE) {
1281 ovsdb_idl_wait(idl);
1282 ovsdb_idl_txn_wait(txn);
1285 if (wait_for_reload && status == TXN_SUCCESS) {
1286 next_cfg = ovsdb_idl_txn_get_increment_new_value(txn);
1288 ovsdb_idl_txn_destroy(txn);
1291 case TXN_INCOMPLETE:
1295 /* Should not happen--we never call ovsdb_idl_txn_abort(). */
1296 vsctl_fatal("transaction aborted");
1303 for (i = 0; i < n_output; i++) {
1304 ds_destroy(&output[i]);
1309 vsctl_fatal("transaction error");
1315 for (i = 0; i < n_output; i++) {
1316 struct ds *ds = &output[i];
1321 for (j = 0; j < ds->length; j++) {
1322 int c = ds->string[j];
1325 fputs("\\n", stdout);
1329 fputs("\\\\", stdout);
1338 fputs(ds_cstr(ds), stdout);
1342 if (wait_for_reload && status != TXN_UNCHANGED) {
1344 const struct ovsrec_open_vswitch *ovs;
1347 OVSREC_OPEN_VSWITCH_FOR_EACH (ovs, idl) {
1348 if (ovs->cur_cfg >= next_cfg) {
1352 ovsdb_idl_wait(idl);
1361 static vsctl_handler_func *
1362 get_vsctl_handler(int argc, char *argv[], struct vsctl_context *ctx)
1364 static const struct vsctl_command all_commands[] = {
1365 /* Open vSwitch commands. */
1366 {"init", 0, 0, cmd_init, ""},
1368 /* Bridge commands. */
1369 {"add-br", 1, 3, cmd_add_br, ""},
1370 {"del-br", 1, 1, cmd_del_br, "--if-exists"},
1371 {"list-br", 0, 0, cmd_list_br, ""},
1372 {"br-exists", 1, 1, cmd_br_exists, ""},
1373 {"br-to-vlan", 1, 1, cmd_br_to_vlan, ""},
1374 {"br-to-parent", 1, 1, cmd_br_to_parent, ""},
1375 {"br-set-external-id", 2, 3, cmd_br_set_external_id, ""},
1376 {"br-get-external-id", 1, 2, cmd_br_get_external_id, ""},
1378 /* Port commands. */
1379 {"list-ports", 1, 1, cmd_list_ports, ""},
1380 {"add-port", 2, 2, cmd_add_port, ""},
1381 {"add-bond", 4, INT_MAX, cmd_add_bond, ""},
1382 {"del-port", 1, 2, cmd_del_port, "--if-exists"},
1383 {"port-to-br", 1, 1, cmd_port_to_br, ""},
1384 {"port-set-external-id", 2, 3, cmd_port_set_external_id, ""},
1385 {"port-get-external-id", 1, 2, cmd_port_get_external_id, ""},
1387 /* Interface commands. */
1388 {"list-ifaces", 1, 1, cmd_list_ifaces, ""},
1389 {"iface-to-br", 1, 1, cmd_iface_to_br, ""},
1390 {"iface-set-external-id", 2, 3, cmd_iface_set_external_id, ""},
1391 {"iface-get-external-id", 1, 2, cmd_iface_get_external_id, ""},
1394 const struct vsctl_command *p;
1397 shash_init(&ctx->options);
1398 for (i = 0; i < argc; i++) {
1399 if (argv[i][0] != '-') {
1402 if (!shash_add_once(&ctx->options, argv[i], NULL)) {
1403 vsctl_fatal("'%s' option specified multiple times", argv[i]);
1407 vsctl_fatal("missing command name");
1410 for (p = all_commands; p < &all_commands[ARRAY_SIZE(all_commands)]; p++) {
1411 if (!strcmp(p->name, argv[i])) {
1412 struct shash_node *node;
1415 SHASH_FOR_EACH (node, &ctx->options) {
1416 const char *s = strstr(p->options, node->name);
1417 int end = s ? s[strlen(node->name)] : EOF;
1418 if (end != ',' && end != ' ' && end != '\0') {
1419 vsctl_fatal("'%s' command has no '%s' option",
1420 argv[i], node->name);
1424 n_arg = argc - i - 1;
1425 if (n_arg < p->min_args) {
1426 vsctl_fatal("'%s' command requires at least %d arguments",
1427 p->name, p->min_args);
1428 } else if (n_arg > p->max_args) {
1429 vsctl_fatal("'%s' command takes at most %d arguments",
1430 p->name, p->max_args);
1432 ctx->argc = n_arg + 1;
1433 ctx->argv = &argv[i];
1439 vsctl_fatal("unknown command '%s'; use --help for help", argv[i]);
1443 check_vsctl_command(int argc, char *argv[])
1445 struct vsctl_context ctx;
1447 get_vsctl_handler(argc, argv, &ctx);
1448 shash_destroy(&ctx.options);
1452 run_vsctl_command(int argc, char *argv[],
1453 const struct ovsrec_open_vswitch *ovs, struct ds *output)
1455 vsctl_handler_func *function;
1456 struct vsctl_context ctx;
1458 function = get_vsctl_handler(argc, argv, &ctx);
1460 ds_init(&ctx.output);
1462 *output = ctx.output;
1463 shash_destroy(&ctx.options);