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"
32 #include "ovsdb-idl.h"
33 #include "poll-loop.h"
35 #include "vswitchd/vswitch-idl.h"
40 #define THIS_MODULE VLM_vsctl
42 /* --db: The database server to contact. */
43 static const char *db;
45 /* --oneline: Write each command's output as a single line? */
48 static void vsctl_fatal(const char *, ...) PRINTF_FORMAT(1, 2) NO_RETURN;
49 static char *default_db(void);
50 static void usage(void) NO_RETURN;
51 static void parse_options(int argc, char *argv[]);
53 static void check_vsctl_command(int argc, char *argv[]);
54 static void do_vsctl(int argc, char *argv[], struct ovsdb_idl *idl);
57 main(int argc, char *argv[])
59 struct ovsdb_idl *idl;
62 int start, n_commands;
66 set_program_name(argv[0]);
67 signal(SIGPIPE, SIG_IGN);
70 vlog_set_levels(VLM_ANY_MODULE, VLF_CONSOLE, VLL_WARN);
71 vlog_set_levels(VLM_reconnect, VLF_ANY_FACILITY, VLL_WARN);
72 parse_options(argc, argv);
74 /* Log our arguments. This is often valuable for debugging systems. */
76 for (i = 1; i < argc; i++) {
77 ds_put_format(&args, " %s", argv[i]);
79 VLOG_INFO("Called as%s", ds_cstr(&args));
82 /* Do basic command syntax checking. */
84 for (start = i = optind; i <= argc; i++) {
85 if (i == argc || !strcmp(argv[i], "--")) {
87 check_vsctl_command(i - start, &argv[start]);
94 vsctl_fatal("missing command name (use --help for help)");
97 /* Now execut the commands. */
98 idl = ovsdb_idl_create(db, &ovsrec_idl_class);
99 seqno = ovsdb_idl_get_seqno(idl);
102 unsigned int new_seqno;
105 new_seqno = ovsdb_idl_get_seqno(idl);
106 if (new_seqno != seqno) {
108 vsctl_fatal("too many database inconsistency failures");
110 do_vsctl(argc - optind, argv + optind, idl);
120 vsctl_fatal(const char *format, ...)
125 va_start(args, format);
126 message = xvasprintf(format, args);
129 vlog_set_levels(VLM_vsctl, VLF_CONSOLE, VLL_EMER);
130 VLOG_ERR("%s", message);
131 ovs_fatal(0, "%s", message);
135 parse_options(int argc, char *argv[])
138 OPT_DB = UCHAR_MAX + 1,
143 static struct option long_options[] = {
144 {"db", required_argument, 0, OPT_DB},
145 {"no-syslog", no_argument, 0, OPT_NO_SYSLOG},
146 {"no-wait", no_argument, 0, OPT_NO_WAIT},
147 {"oneline", no_argument, 0, OPT_ONELINE},
148 {"verbose", optional_argument, 0, 'v'},
149 {"help", no_argument, 0, 'h'},
150 {"version", no_argument, 0, 'V'},
157 c = getopt_long(argc, argv, "+v::hV", long_options, NULL);
172 vlog_set_levels(VLM_vsctl, VLF_SYSLOG, VLL_WARN);
176 /* XXX not yet implemented */
183 OVS_PRINT_VERSION(0, 0);
187 vlog_set_verbosity(optarg);
206 printf("%s: ovs-vswitchd management utility\n"
207 "usage: %s [OPTIONS] COMMAND [ARG...]\n",
208 program_name, program_name);
209 printf("\nBridge commands:\n"
211 "create a new bridge named BRIDGE\n"
212 " add-br BRIDGE PARENT VLAN "
213 "create new fake bridge BRIDGE in PARENT on VLAN\n"
215 "delete BRIDGE and all of its ports\n"
217 "print the names of all the bridges\n"
219 "test whether BRIDGE exists\n"
220 " br-to-vlan BRIDGE "
221 "print the VLAN which BRIDGE is on\n"
222 " br-to-parent BRIDGE "
223 "print the parent of BRIDGE\n"
224 " br-set-external-id BRIDGE KEY VALUE"
225 " set KEY on BRIDGE to VALUE\n"
226 " br-set-external-id BRIDGE KEY"
227 " unset KEY on BRIDGE\n"
228 " br-get-external-id BRIDGE KEY"
229 " print value of KEY on BRIDGE\n"
230 " br-get-external-id BRIDGE"
231 " list key-value pairs on BRIDGE\n"
233 printf("\nPort commands:\n"
234 " list-ports BRIDGE "
235 "print the names of all the ports on BRIDGE\n"
236 " add-port BRIDGE PORT "
237 "add network device PORT to BRIDGE\n"
238 " add-bond BRIDGE PORT IFACE... "
239 "add new bonded port PORT in BRIDGE from IFACES\n"
240 " del-port [BRIDGE] PORT "
241 "delete PORT (which may be bonded) from BRIDGE\n"
243 "print name of bridge that contains PORT\n"
244 " port-set-external-id PORT KEY VALUE"
245 " set KEY on PORT to VALUE\n"
246 " port-set-external-id PORT KEY"
247 " unset KEY on PORT\n"
248 " port-get-external-id PORT KEY"
249 " print value of KEY on PORT\n"
250 " port-get-external-id PORT"
251 " list key-value pairs on PORT\n"
252 "A bond is considered to be a single port.\n"
254 printf("\nInterface commands (a bond consists of multiple interfaces):\n"
255 " list-ifaces BRIDGE "
256 "print the names of all the interfaces on BRIDGE\n"
257 " iface-to-br IFACE "
258 "print name of bridge that contains IFACE\n"
259 " iface-set-external-id IFACE KEY VALUE"
260 " set KEY on IFACE to VALUE\n"
261 " iface-set-external-id IFACE KEY"
262 " unset KEY on IFACE\n"
263 " iface-get-external-id IFACE KEY"
264 " print value of KEY on IFACE\n"
265 " iface-get-external-id IFACE"
266 " list key-value pairs on IFACE\n"
268 printf("\nOptions:\n"
270 "connect to DATABASE\n"
274 "print exactly one line of output per command\n",
277 printf("\nOther options:\n"
279 "display this help message\n"
281 "display version information\n");
290 def = xasprintf("unix:%s/ovsdb-server", ovs_rundir);
295 struct vsctl_context {
298 const struct ovsrec_open_vswitch *ovs;
300 struct shash options;
303 struct vsctl_bridge {
304 struct ovsrec_bridge *br_cfg;
306 struct vsctl_bridge *parent;
311 struct ovsrec_port *port_cfg;
312 struct vsctl_bridge *bridge;
316 struct ovsrec_interface *iface_cfg;
317 struct vsctl_port *port;
321 struct shash bridges;
326 static struct ovsdb_idl_txn *
327 txn_from_openvswitch(const struct ovsrec_open_vswitch *ovs)
329 return ovsdb_idl_txn_get(&ovs->header_);
332 static struct vsctl_bridge *
333 add_bridge(struct vsctl_info *b,
334 struct ovsrec_bridge *br_cfg, const char *name,
335 struct vsctl_bridge *parent, int vlan)
337 struct vsctl_bridge *br = xmalloc(sizeof *br);
339 br->name = xstrdup(name);
342 shash_add(&b->bridges, br->name, br);
347 port_is_fake_bridge(const struct ovsrec_port *port_cfg)
349 return (port_cfg->fake_bridge
351 && *port_cfg->tag >= 1 && *port_cfg->tag <= 4095);
354 static struct vsctl_bridge *
355 find_vlan_bridge(struct vsctl_info *info,
356 struct vsctl_bridge *parent, int vlan)
358 struct shash_node *node;
360 SHASH_FOR_EACH (node, &info->bridges) {
361 struct vsctl_bridge *br = node->data;
362 if (br->parent == parent && br->vlan == vlan) {
371 free_info(struct vsctl_info *info)
373 struct shash_node *node;
375 SHASH_FOR_EACH (node, &info->bridges) {
376 struct vsctl_bridge *bridge = node->data;
380 shash_destroy(&info->bridges);
382 SHASH_FOR_EACH (node, &info->ports) {
383 struct vsctl_port *port = node->data;
386 shash_destroy(&info->ports);
388 SHASH_FOR_EACH (node, &info->ifaces) {
389 struct vsctl_iface *iface = node->data;
392 shash_destroy(&info->ifaces);
396 get_info(const struct ovsrec_open_vswitch *ovs, struct vsctl_info *info)
398 struct shash bridges, ports;
401 shash_init(&info->bridges);
402 shash_init(&info->ports);
403 shash_init(&info->ifaces);
405 shash_init(&bridges);
407 for (i = 0; i < ovs->n_bridges; i++) {
408 struct ovsrec_bridge *br_cfg = ovs->bridges[i];
409 struct vsctl_bridge *br;
412 if (!shash_add_once(&bridges, br_cfg->name, NULL)) {
413 VLOG_WARN("%s: database contains duplicate bridge name",
417 br = add_bridge(info, br_cfg, br_cfg->name, NULL, 0);
422 for (j = 0; j < br_cfg->n_ports; j++) {
423 struct ovsrec_port *port_cfg = br_cfg->ports[j];
425 if (!shash_add_once(&ports, port_cfg->name, NULL)) {
426 VLOG_WARN("%s: database contains duplicate port name",
431 if (port_is_fake_bridge(port_cfg)
432 && shash_add_once(&bridges, port_cfg->name, NULL)) {
433 add_bridge(info, NULL, port_cfg->name, br, *port_cfg->tag);
437 shash_destroy(&bridges);
438 shash_destroy(&ports);
440 shash_init(&bridges);
442 for (i = 0; i < ovs->n_bridges; i++) {
443 struct ovsrec_bridge *br_cfg = ovs->bridges[i];
444 struct vsctl_bridge *br;
447 if (!shash_add_once(&bridges, br_cfg->name, NULL)) {
450 br = shash_find_data(&info->bridges, br_cfg->name);
451 for (j = 0; j < br_cfg->n_ports; j++) {
452 struct ovsrec_port *port_cfg = br_cfg->ports[j];
453 struct vsctl_port *port;
456 if (!shash_add_once(&ports, port_cfg->name, NULL)) {
460 if (port_is_fake_bridge(port_cfg)
461 && !shash_add_once(&bridges, port_cfg->name, NULL)) {
465 port = xmalloc(sizeof *port);
466 port->port_cfg = port_cfg;
468 && *port_cfg->tag >= 1 && *port_cfg->tag <= 4095) {
469 port->bridge = find_vlan_bridge(info, br, *port_cfg->tag);
476 shash_add(&info->ports, port_cfg->name, port);
478 for (k = 0; k < port_cfg->n_interfaces; k++) {
479 struct ovsrec_interface *iface_cfg = port_cfg->interfaces[k];
480 struct vsctl_iface *iface;
482 if (shash_find(&info->ifaces, iface_cfg->name)) {
483 VLOG_WARN("%s: database contains duplicate interface name",
488 iface = xmalloc(sizeof *iface);
489 iface->iface_cfg = iface_cfg;
491 shash_add(&info->ifaces, iface_cfg->name, iface);
495 shash_destroy(&bridges);
496 shash_destroy(&ports);
500 check_conflicts(struct vsctl_info *info, const char *name,
503 struct vsctl_iface *iface;
504 struct vsctl_port *port;
506 if (shash_find(&info->bridges, name)) {
507 vsctl_fatal("%s because a bridge named %s already exists",
511 port = shash_find_data(&info->ports, name);
513 vsctl_fatal("%s because a port named %s already exists on "
514 "bridge %s", msg, name, port->bridge->name);
517 iface = shash_find_data(&info->ifaces, name);
519 vsctl_fatal("%s because an interface named %s already exists "
520 "on bridge %s", msg, name, iface->port->bridge->name);
526 static struct vsctl_bridge *
527 find_bridge(struct vsctl_info *info, const char *name, bool must_exist)
529 struct vsctl_bridge *br = shash_find_data(&info->bridges, name);
530 if (must_exist && !br) {
531 vsctl_fatal("no bridge named %s", name);
536 static struct vsctl_port *
537 find_port(struct vsctl_info *info, const char *name, bool must_exist)
539 struct vsctl_port *port = shash_find_data(&info->ports, name);
540 if (port && !strcmp(name, port->bridge->name)) {
543 if (must_exist && !port) {
544 vsctl_fatal("no port named %s", name);
549 static struct vsctl_iface *
550 find_iface(struct vsctl_info *info, const char *name, bool must_exist)
552 struct vsctl_iface *iface = shash_find_data(&info->ifaces, name);
553 if (iface && !strcmp(name, iface->port->bridge->name)) {
556 if (must_exist && !iface) {
557 vsctl_fatal("no interface named %s", name);
563 bridge_insert_port(struct ovsrec_bridge *br, struct ovsrec_port *port)
565 struct ovsrec_port **ports;
568 ports = xmalloc(sizeof *br->ports * (br->n_ports + 1));
569 for (i = 0; i < br->n_ports; i++) {
570 ports[i] = br->ports[i];
572 ports[br->n_ports] = port;
573 ovsrec_bridge_set_ports(br, ports, br->n_ports + 1);
578 bridge_delete_port(struct ovsrec_bridge *br, struct ovsrec_port *port)
580 struct ovsrec_port **ports;
583 ports = xmalloc(sizeof *br->ports * br->n_ports);
584 for (i = n = 0; i < br->n_ports; i++) {
585 if (br->ports[i] != port) {
586 ports[n++] = br->ports[i];
589 ovsrec_bridge_set_ports(br, ports, n);
594 ovs_insert_bridge(const struct ovsrec_open_vswitch *ovs,
595 struct ovsrec_bridge *bridge)
597 struct ovsrec_bridge **bridges;
600 bridges = xmalloc(sizeof *ovs->bridges * (ovs->n_bridges + 1));
601 for (i = 0; i < ovs->n_bridges; i++) {
602 bridges[i] = ovs->bridges[i];
604 bridges[ovs->n_bridges] = bridge;
605 ovsrec_open_vswitch_set_bridges(ovs, bridges, ovs->n_bridges + 1);
610 ovs_delete_bridge(const struct ovsrec_open_vswitch *ovs,
611 struct ovsrec_bridge *bridge)
613 struct ovsrec_bridge **bridges;
616 bridges = xmalloc(sizeof *ovs->bridges * ovs->n_bridges);
617 for (i = n = 0; i < ovs->n_bridges; i++) {
618 if (ovs->bridges[i] != bridge) {
619 bridges[n++] = ovs->bridges[i];
622 ovsrec_open_vswitch_set_bridges(ovs, bridges, n);
627 cmd_add_br(struct vsctl_context *ctx)
629 const char *br_name = ctx->argv[1];
630 struct vsctl_info info;
632 get_info(ctx->ovs, &info);
633 check_conflicts(&info, br_name,
634 xasprintf("cannot create a bridge named %s", br_name));
636 if (ctx->argc == 2) {
637 struct ovsrec_bridge *br;
638 struct ovsrec_port *port;
639 struct ovsrec_interface *iface;
641 iface = ovsrec_interface_insert(txn_from_openvswitch(ctx->ovs));
642 ovsrec_interface_set_name(iface, br_name);
644 port = ovsrec_port_insert(txn_from_openvswitch(ctx->ovs));
645 ovsrec_port_set_name(port, br_name);
646 ovsrec_port_set_interfaces(port, &iface, 1);
648 br = ovsrec_bridge_insert(txn_from_openvswitch(ctx->ovs));
649 ovsrec_bridge_set_name(br, br_name);
650 ovsrec_bridge_set_ports(br, &port, 1);
652 ovs_insert_bridge(ctx->ovs, br);
653 } else if (ctx->argc == 3) {
654 vsctl_fatal("'%s' command takes exactly 1 or 3 arguments",
656 } else if (ctx->argc == 4) {
657 const char *parent_name = ctx->argv[2];
658 int vlan = atoi(ctx->argv[3]);
659 struct ovsrec_bridge *br;
660 struct vsctl_bridge *parent;
661 struct ovsrec_port *port;
662 struct ovsrec_interface *iface;
665 if (vlan < 1 || vlan > 4095) {
666 vsctl_fatal("%s: vlan must be between 1 and 4095", ctx->argv[0]);
669 parent = find_bridge(&info, parent_name, false);
670 if (parent && parent->vlan) {
671 vsctl_fatal("cannot create brdige with fake bridge as parent");
674 vsctl_fatal("parent bridge %s does not exist", parent_name);
678 iface = ovsrec_interface_insert(txn_from_openvswitch(ctx->ovs));
679 ovsrec_interface_set_name(iface, br_name);
680 ovsrec_interface_set_type(iface, "internal");
682 port = ovsrec_port_insert(txn_from_openvswitch(ctx->ovs));
683 ovsrec_port_set_name(port, br_name);
684 ovsrec_port_set_interfaces(port, &iface, 1);
685 ovsrec_port_set_fake_bridge(port, true);
686 ovsrec_port_set_tag(port, &tag, 1);
688 bridge_insert_port(br, port);
697 del_port(struct vsctl_info *info, struct vsctl_port *port)
699 struct shash_node *node;
701 SHASH_FOR_EACH (node, &info->ifaces) {
702 struct vsctl_iface *iface = node->data;
703 if (iface->port == port) {
704 ovsrec_interface_delete(iface->iface_cfg);
707 ovsrec_port_delete(port->port_cfg);
709 bridge_delete_port((port->bridge->parent
710 ? port->bridge->parent->br_cfg
711 : port->bridge->br_cfg), port->port_cfg);
715 cmd_del_br(struct vsctl_context *ctx)
717 bool must_exist = !shash_find(&ctx->options, "--if-exists");
718 struct vsctl_bridge *bridge;
719 struct vsctl_info info;
721 get_info(ctx->ovs, &info);
722 bridge = find_bridge(&info, ctx->argv[1], must_exist);
724 struct shash_node *node;
726 SHASH_FOR_EACH (node, &info.ports) {
727 struct vsctl_port *port = node->data;
728 if (port->bridge == bridge
729 || !strcmp(port->port_cfg->name, bridge->name)) {
730 del_port(&info, port);
733 if (bridge->br_cfg) {
734 ovsrec_bridge_delete(bridge->br_cfg);
735 ovs_delete_bridge(ctx->ovs, bridge->br_cfg);
742 output_sorted(struct svec *svec, struct ds *output)
748 SVEC_FOR_EACH (i, name, svec) {
749 ds_put_format(output, "%s\n", name);
754 cmd_list_br(struct vsctl_context *ctx)
756 struct shash_node *node;
757 struct vsctl_info info;
760 get_info(ctx->ovs, &info);
763 SHASH_FOR_EACH (node, &info.bridges) {
764 struct vsctl_bridge *br = node->data;
765 svec_add(&bridges, br->name);
767 output_sorted(&bridges, &ctx->output);
768 svec_destroy(&bridges);
774 cmd_br_exists(struct vsctl_context *ctx)
776 struct vsctl_info info;
778 get_info(ctx->ovs, &info);
779 if (!find_bridge(&info, ctx->argv[1], false)) {
785 /* Returns true if 'b_prefix' (of length 'b_prefix_len') concatenated with 'b'
786 * equals 'a', false otherwise. */
788 key_matches(const char *a,
789 const char *b_prefix, size_t b_prefix_len, const char *b)
791 return !strncmp(a, b_prefix, b_prefix_len) && !strcmp(a + b_prefix_len, b);
795 set_external_id(char **old_keys, char **old_values, size_t old_n,
796 char *key, char *value,
797 char ***new_keysp, char ***new_valuesp, size_t *new_np)
804 new_keys = xmalloc(sizeof *new_keys * (old_n + 1));
805 new_values = xmalloc(sizeof *new_values * (old_n + 1));
807 for (i = 0; i < old_n; i++) {
808 if (strcmp(key, old_keys[i])) {
809 new_keys[new_n] = old_keys[i];
810 new_values[new_n] = old_values[i];
815 new_keys[new_n] = key;
816 new_values[new_n] = value;
819 *new_keysp = new_keys;
820 *new_valuesp = new_values;
825 cmd_br_set_external_id(struct vsctl_context *ctx)
827 struct vsctl_info info;
828 struct vsctl_bridge *bridge;
829 char **keys, **values;
832 get_info(ctx->ovs, &info);
833 bridge = find_bridge(&info, ctx->argv[1], true);
834 if (bridge->br_cfg) {
835 set_external_id(bridge->br_cfg->key_external_ids,
836 bridge->br_cfg->value_external_ids,
837 bridge->br_cfg->n_external_ids,
838 ctx->argv[2], ctx->argc >= 4 ? ctx->argv[3] : NULL,
840 ovsrec_bridge_set_external_ids(bridge->br_cfg, keys, values, n);
842 char *key = xasprintf("fake-bridge-%s", ctx->argv[2]);
843 struct vsctl_port *port = shash_find_data(&info.ports, ctx->argv[1]);
844 set_external_id(port->port_cfg->key_external_ids,
845 port->port_cfg->value_external_ids,
846 port->port_cfg->n_external_ids,
847 key, ctx->argc >= 4 ? ctx->argv[3] : NULL,
849 ovsrec_port_set_external_ids(port->port_cfg, keys, values, n);
859 get_external_id(char **keys, char **values, size_t n,
860 const char *prefix, const char *key,
863 size_t prefix_len = strlen(prefix);
868 for (i = 0; i < n; i++) {
869 if (!key && !strncmp(keys[i], prefix, prefix_len)) {
870 svec_add_nocopy(&svec, xasprintf("%s=%s",
871 keys[i] + prefix_len, values[i]));
872 } else if (key_matches(keys[i], prefix, prefix_len, key)) {
873 svec_add(&svec, values[i]);
877 output_sorted(&svec, output);
882 cmd_br_get_external_id(struct vsctl_context *ctx)
884 struct vsctl_info info;
885 struct vsctl_bridge *bridge;
887 get_info(ctx->ovs, &info);
888 bridge = find_bridge(&info, ctx->argv[1], true);
889 if (bridge->br_cfg) {
890 get_external_id(bridge->br_cfg->key_external_ids,
891 bridge->br_cfg->value_external_ids,
892 bridge->br_cfg->n_external_ids,
893 "", ctx->argc >= 3 ? ctx->argv[2] : NULL,
896 struct vsctl_port *port = shash_find_data(&info.ports, ctx->argv[1]);
897 get_external_id(port->port_cfg->key_external_ids,
898 port->port_cfg->value_external_ids,
899 port->port_cfg->n_external_ids,
900 "fake-bridge-", ctx->argc >= 3 ? ctx->argv[2] : NULL, &ctx->output);
907 cmd_list_ports(struct vsctl_context *ctx)
909 struct vsctl_bridge *br;
910 struct shash_node *node;
911 struct vsctl_info info;
914 get_info(ctx->ovs, &info);
915 br = find_bridge(&info, ctx->argv[1], true);
918 SHASH_FOR_EACH (node, &info.ports) {
919 struct vsctl_port *port = node->data;
921 if (strcmp(port->port_cfg->name, br->name) && br == port->bridge) {
922 svec_add(&ports, port->port_cfg->name);
925 output_sorted(&ports, &ctx->output);
926 svec_destroy(&ports);
932 add_port(const struct ovsrec_open_vswitch *ovs,
933 const char *br_name, const char *port_name,
934 char *iface_names[], int n_ifaces)
936 struct vsctl_info info;
937 struct vsctl_bridge *bridge;
938 struct ovsrec_interface **ifaces;
939 struct ovsrec_port *port;
942 get_info(ovs, &info);
943 check_conflicts(&info, port_name,
944 xasprintf("cannot create a port named %s", port_name));
945 /* XXX need to check for conflicts on interfaces too */
946 bridge = find_bridge(&info, br_name, true);
948 ifaces = xmalloc(n_ifaces * sizeof *ifaces);
949 for (i = 0; i < n_ifaces; i++) {
950 ifaces[i] = ovsrec_interface_insert(txn_from_openvswitch(ovs));
951 ovsrec_interface_set_name(ifaces[i], iface_names[i]);
954 port = ovsrec_port_insert(txn_from_openvswitch(ovs));
955 ovsrec_port_set_name(port, port_name);
956 ovsrec_port_set_interfaces(port, ifaces, n_ifaces);
960 int64_t tag = bridge->vlan;
961 ovsrec_port_set_tag(port, &tag, 1);
964 bridge_insert_port((bridge->parent ? bridge->parent->br_cfg
965 : bridge->br_cfg), port);
971 cmd_add_port(struct vsctl_context *ctx)
973 add_port(ctx->ovs, ctx->argv[1], ctx->argv[2], &ctx->argv[2], 1);
977 cmd_add_bond(struct vsctl_context *ctx)
979 add_port(ctx->ovs, ctx->argv[1], ctx->argv[2], &ctx->argv[3], ctx->argc - 3);
983 cmd_del_port(struct vsctl_context *ctx)
985 bool must_exist = !shash_find(&ctx->options, "--if-exists");
986 struct vsctl_info info;
988 get_info(ctx->ovs, &info);
989 if (ctx->argc == 2) {
990 struct vsctl_port *port = find_port(&info, ctx->argv[1], must_exist);
992 del_port(&info, port);
994 } else if (ctx->argc == 3) {
995 struct vsctl_bridge *bridge = find_bridge(&info, ctx->argv[1], true);
996 struct vsctl_port *port = find_port(&info, ctx->argv[2], must_exist);
999 if (port->bridge == bridge) {
1000 del_port(&info, port);
1001 } else if (port->bridge->parent == bridge) {
1002 vsctl_fatal("bridge %s does not have a port %s (although its "
1003 "parent bridge %s does)",
1004 ctx->argv[1], ctx->argv[2], bridge->parent->name);
1006 vsctl_fatal("bridge %s does not have a port %s",
1007 ctx->argv[1], ctx->argv[2]);
1015 cmd_port_to_br(struct vsctl_context *ctx)
1017 struct vsctl_port *port;
1018 struct vsctl_info info;
1020 get_info(ctx->ovs, &info);
1021 port = find_port(&info, ctx->argv[1], true);
1022 ds_put_format(&ctx->output, "%s\n", port->bridge->name);
1027 cmd_port_set_external_id(struct vsctl_context *ctx)
1029 struct vsctl_info info;
1030 struct vsctl_port *port;
1031 char **keys, **values;
1034 get_info(ctx->ovs, &info);
1035 port = find_port(&info, ctx->argv[1], true);
1036 set_external_id(port->port_cfg->key_external_ids,
1037 port->port_cfg->value_external_ids,
1038 port->port_cfg->n_external_ids,
1039 ctx->argv[2], ctx->argc >= 4 ? ctx->argv[3] : NULL,
1040 &keys, &values, &n);
1041 ovsrec_port_set_external_ids(port->port_cfg, keys, values, n);
1049 cmd_port_get_external_id(struct vsctl_context *ctx)
1051 struct vsctl_info info;
1052 struct vsctl_port *port;
1054 get_info(ctx->ovs, &info);
1055 port = find_port(&info, ctx->argv[1], true);
1056 get_external_id(port->port_cfg->key_external_ids,
1057 port->port_cfg->value_external_ids,
1058 port->port_cfg->n_external_ids,
1059 "", ctx->argc >= 3 ? ctx->argv[2] : NULL, &ctx->output);
1064 cmd_br_to_vlan(struct vsctl_context *ctx)
1066 struct vsctl_bridge *bridge;
1067 struct vsctl_info info;
1069 get_info(ctx->ovs, &info);
1070 bridge = find_bridge(&info, ctx->argv[1], true);
1071 ds_put_format(&ctx->output, "%d\n", bridge->vlan);
1076 cmd_br_to_parent(struct vsctl_context *ctx)
1078 struct vsctl_bridge *bridge;
1079 struct vsctl_info info;
1081 get_info(ctx->ovs, &info);
1082 bridge = find_bridge(&info, ctx->argv[1], true);
1083 if (bridge->parent) {
1084 bridge = bridge->parent;
1086 ds_put_format(&ctx->output, "%s\n", bridge->name);
1091 cmd_list_ifaces(struct vsctl_context *ctx)
1093 struct vsctl_bridge *br;
1094 struct shash_node *node;
1095 struct vsctl_info info;
1098 get_info(ctx->ovs, &info);
1099 br = find_bridge(&info, ctx->argv[1], true);
1102 SHASH_FOR_EACH (node, &info.ifaces) {
1103 struct vsctl_iface *iface = node->data;
1105 if (strcmp(iface->iface_cfg->name, br->name)
1106 && br == iface->port->bridge) {
1107 svec_add(&ifaces, iface->iface_cfg->name);
1110 output_sorted(&ifaces, &ctx->output);
1111 svec_destroy(&ifaces);
1117 cmd_iface_to_br(struct vsctl_context *ctx)
1119 struct vsctl_iface *iface;
1120 struct vsctl_info info;
1122 get_info(ctx->ovs, &info);
1123 iface = find_iface(&info, ctx->argv[1], true);
1124 ds_put_format(&ctx->output, "%s\n", iface->port->bridge->name);
1129 cmd_iface_set_external_id(struct vsctl_context *ctx)
1131 struct vsctl_info info;
1132 struct vsctl_iface *iface;
1133 char **keys, **values;
1136 get_info(ctx->ovs, &info);
1137 iface = find_iface(&info, ctx->argv[1], true);
1138 set_external_id(iface->iface_cfg->key_external_ids,
1139 iface->iface_cfg->value_external_ids,
1140 iface->iface_cfg->n_external_ids,
1141 ctx->argv[2], ctx->argc >= 4 ? ctx->argv[3] : NULL,
1142 &keys, &values, &n);
1143 ovsrec_interface_set_external_ids(iface->iface_cfg, keys, values, n);
1151 cmd_iface_get_external_id(struct vsctl_context *ctx)
1153 struct vsctl_info info;
1154 struct vsctl_iface *iface;
1156 get_info(ctx->ovs, &info);
1157 iface = find_iface(&info, ctx->argv[1], true);
1158 get_external_id(iface->iface_cfg->key_external_ids,
1159 iface->iface_cfg->value_external_ids,
1160 iface->iface_cfg->n_external_ids,
1161 "", ctx->argc >= 3 ? ctx->argv[2] : NULL, &ctx->output);
1165 typedef void vsctl_handler_func(struct vsctl_context *);
1167 struct vsctl_command {
1171 vsctl_handler_func *handler;
1172 const char *options;
1175 static void run_vsctl_command(int argc, char *argv[],
1176 const struct ovsrec_open_vswitch *ovs,
1180 do_vsctl(int argc, char *argv[], struct ovsdb_idl *idl)
1182 struct ovsdb_idl_txn *txn;
1183 const struct ovsrec_open_vswitch *ovs;
1184 enum ovsdb_idl_txn_status status;
1189 ovs = ovsrec_open_vswitch_first(idl);
1191 /* XXX it would be more user-friendly to create a record ourselves
1192 * (while verifying that the table is empty before doing so). */
1193 vsctl_fatal("%s: database does not contain any Open vSwitch "
1194 "configuration", db);
1197 txn = ovsdb_idl_txn_create(idl);
1198 output = xmalloc(argc * sizeof *output);
1200 for (start = i = 0; i <= argc; i++) {
1201 if (i == argc || !strcmp(argv[i], "--")) {
1203 ds_init(&output[n_output]);
1204 run_vsctl_command(i - start, &argv[start], ovs,
1205 &output[n_output++]);
1211 while ((status = ovsdb_idl_txn_commit(txn)) == TXN_INCOMPLETE) {
1213 ovsdb_idl_wait(idl);
1214 ovsdb_idl_txn_wait(txn);
1217 ovsdb_idl_txn_destroy(txn);
1220 case TXN_INCOMPLETE:
1224 /* Should not happen--we never call ovsdb_idl_txn_abort(). */
1225 vsctl_fatal("transaction aborted");
1231 for (i = 0; i < n_output; i++) {
1232 ds_destroy(&output[i]);
1237 vsctl_fatal("transaction error");
1243 for (i = 0; i < n_output; i++) {
1244 struct ds *ds = &output[i];
1249 for (j = 0; j < ds->length; j++) {
1250 int c = ds->string[j];
1253 fputs("\\n", stdout);
1257 fputs("\\\\", stdout);
1266 fputs(ds_cstr(ds), stdout);
1272 static vsctl_handler_func *
1273 get_vsctl_handler(int argc, char *argv[], struct vsctl_context *ctx)
1275 static const struct vsctl_command all_commands[] = {
1276 /* Bridge commands. */
1277 {"add-br", 1, 3, cmd_add_br, ""},
1278 {"del-br", 1, 1, cmd_del_br, "--if-exists"},
1279 {"list-br", 0, 0, cmd_list_br, ""},
1280 {"br-exists", 1, 1, cmd_br_exists, ""},
1281 {"br-to-vlan", 1, 1, cmd_br_to_vlan, ""},
1282 {"br-to-parent", 1, 1, cmd_br_to_parent, ""},
1283 {"br-set-external-id", 2, 3, cmd_br_set_external_id, ""},
1284 {"br-get-external-id", 1, 2, cmd_br_get_external_id, ""},
1286 /* Port commands. */
1287 {"list-ports", 1, 1, cmd_list_ports, ""},
1288 {"add-port", 2, 2, cmd_add_port, ""},
1289 {"add-bond", 4, INT_MAX, cmd_add_bond, ""},
1290 {"del-port", 1, 2, cmd_del_port, "--if-exists"},
1291 {"port-to-br", 1, 1, cmd_port_to_br, ""},
1292 {"port-set-external-id", 2, 3, cmd_port_set_external_id, ""},
1293 {"port-get-external-id", 1, 2, cmd_port_get_external_id, ""},
1295 /* Interface commands. */
1296 {"list-ifaces", 1, 1, cmd_list_ifaces, ""},
1297 {"iface-to-br", 1, 1, cmd_iface_to_br, ""},
1298 {"iface-set-external-id", 2, 3, cmd_iface_set_external_id, ""},
1299 {"iface-get-external-id", 1, 2, cmd_iface_get_external_id, ""},
1302 const struct vsctl_command *p;
1305 shash_init(&ctx->options);
1306 for (i = 0; i < argc; i++) {
1307 if (argv[i][0] != '-') {
1310 if (!shash_add_once(&ctx->options, argv[i], NULL)) {
1311 vsctl_fatal("'%s' option specified multiple times", argv[i]);
1315 vsctl_fatal("missing command name");
1318 for (p = all_commands; p < &all_commands[ARRAY_SIZE(all_commands)]; p++) {
1319 if (!strcmp(p->name, argv[i])) {
1320 struct shash_node *node;
1323 SHASH_FOR_EACH (node, &ctx->options) {
1324 const char *s = strstr(p->options, node->name);
1325 int end = s ? s[strlen(node->name)] : EOF;
1326 if (end != ',' && end != ' ' && end != '\0') {
1327 vsctl_fatal("'%s' command has no '%s' option",
1328 argv[i], node->name);
1332 n_arg = argc - i - 1;
1333 if (n_arg < p->min_args) {
1334 vsctl_fatal("'%s' command requires at least %d arguments",
1335 p->name, p->min_args);
1336 } else if (n_arg > p->max_args) {
1337 vsctl_fatal("'%s' command takes at most %d arguments",
1338 p->name, p->max_args);
1340 ctx->argc = n_arg + 1;
1341 ctx->argv = &argv[i];
1347 vsctl_fatal("unknown command '%s'; use --help for help", argv[i]);
1351 check_vsctl_command(int argc, char *argv[])
1353 struct vsctl_context ctx;
1355 get_vsctl_handler(argc, argv, &ctx);
1356 shash_destroy(&ctx.options);
1360 run_vsctl_command(int argc, char *argv[],
1361 const struct ovsrec_open_vswitch *ovs, struct ds *output)
1363 vsctl_handler_func *function;
1364 struct vsctl_context ctx;
1366 function = get_vsctl_handler(argc, argv, &ctx);
1368 ds_init(&ctx.output);
1370 *output = ctx.output;
1371 shash_destroy(&ctx.options);