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 /* --dry-run: Do not commit any changes. */
51 static void vsctl_fatal(const char *, ...) PRINTF_FORMAT(1, 2) NO_RETURN;
52 static char *default_db(void);
53 static void usage(void) NO_RETURN;
54 static void parse_options(int argc, char *argv[]);
56 static void check_vsctl_command(int argc, char *argv[]);
57 static void do_vsctl(int argc, char *argv[], struct ovsdb_idl *idl);
60 main(int argc, char *argv[])
62 struct ovsdb_idl *idl;
65 int start, n_commands;
69 set_program_name(argv[0]);
70 signal(SIGPIPE, SIG_IGN);
73 vlog_set_levels(VLM_ANY_MODULE, VLF_CONSOLE, VLL_WARN);
74 vlog_set_levels(VLM_reconnect, VLF_ANY_FACILITY, VLL_WARN);
75 parse_options(argc, argv);
77 /* Log our arguments. This is often valuable for debugging systems. */
79 for (i = 1; i < argc; i++) {
80 ds_put_format(&args, " %s", argv[i]);
82 VLOG_INFO("Called as%s", ds_cstr(&args));
85 /* Do basic command syntax checking. */
87 for (start = i = optind; i <= argc; i++) {
88 if (i == argc || !strcmp(argv[i], "--")) {
90 check_vsctl_command(i - start, &argv[start]);
97 vsctl_fatal("missing command name (use --help for help)");
100 /* Now execute the commands. */
101 idl = ovsdb_idl_create(db, &ovsrec_idl_class);
102 seqno = ovsdb_idl_get_seqno(idl);
105 unsigned int new_seqno;
108 new_seqno = ovsdb_idl_get_seqno(idl);
109 if (new_seqno != seqno) {
111 vsctl_fatal("too many database inconsistency failures");
113 do_vsctl(argc - optind, argv + optind, idl);
123 vsctl_fatal(const char *format, ...)
128 va_start(args, format);
129 message = xvasprintf(format, args);
132 vlog_set_levels(VLM_vsctl, VLF_CONSOLE, VLL_EMER);
133 VLOG_ERR("%s", message);
134 ovs_fatal(0, "%s", message);
138 parse_options(int argc, char *argv[])
141 OPT_DB = UCHAR_MAX + 1,
147 static struct option long_options[] = {
148 {"db", required_argument, 0, OPT_DB},
149 {"no-syslog", no_argument, 0, OPT_NO_SYSLOG},
150 {"no-wait", no_argument, 0, OPT_NO_WAIT},
151 {"dry-run", no_argument, 0, OPT_DRY_RUN},
152 {"oneline", no_argument, 0, OPT_ONELINE},
153 {"verbose", optional_argument, 0, 'v'},
154 {"help", no_argument, 0, 'h'},
155 {"version", no_argument, 0, 'V'},
162 c = getopt_long(argc, argv, "+v::hV", long_options, NULL);
177 vlog_set_levels(VLM_vsctl, VLF_SYSLOG, VLL_WARN);
181 /* XXX not yet implemented */
192 OVS_PRINT_VERSION(0, 0);
196 vlog_set_verbosity(optarg);
215 printf("%s: ovs-vswitchd management utility\n"
216 "usage: %s [OPTIONS] COMMAND [ARG...]\n",
217 program_name, program_name);
218 printf("\nBridge commands:\n"
220 "create a new bridge named BRIDGE\n"
221 " add-br BRIDGE PARENT VLAN "
222 "create new fake bridge BRIDGE in PARENT on VLAN\n"
224 "delete BRIDGE and all of its ports\n"
226 "print the names of all the bridges\n"
228 "test whether BRIDGE exists\n"
229 " br-to-vlan BRIDGE "
230 "print the VLAN which BRIDGE is on\n"
231 " br-to-parent BRIDGE "
232 "print the parent of BRIDGE\n"
233 " br-set-external-id BRIDGE KEY VALUE"
234 " set KEY on BRIDGE to VALUE\n"
235 " br-set-external-id BRIDGE KEY"
236 " unset KEY on BRIDGE\n"
237 " br-get-external-id BRIDGE KEY"
238 " print value of KEY on BRIDGE\n"
239 " br-get-external-id BRIDGE"
240 " list key-value pairs on BRIDGE\n"
242 printf("\nPort commands:\n"
243 " list-ports BRIDGE "
244 "print the names of all the ports on BRIDGE\n"
245 " add-port BRIDGE PORT "
246 "add network device PORT to BRIDGE\n"
247 " add-bond BRIDGE PORT IFACE... "
248 "add new bonded port PORT in BRIDGE from IFACES\n"
249 " del-port [BRIDGE] PORT "
250 "delete PORT (which may be bonded) from BRIDGE\n"
252 "print name of bridge that contains PORT\n"
253 " port-set-external-id PORT KEY VALUE"
254 " set KEY on PORT to VALUE\n"
255 " port-set-external-id PORT KEY"
256 " unset KEY on PORT\n"
257 " port-get-external-id PORT KEY"
258 " print value of KEY on PORT\n"
259 " port-get-external-id PORT"
260 " list key-value pairs on PORT\n"
261 "A bond is considered to be a single port.\n"
263 printf("\nInterface commands (a bond consists of multiple interfaces):\n"
264 " list-ifaces BRIDGE "
265 "print the names of all the interfaces on BRIDGE\n"
266 " iface-to-br IFACE "
267 "print name of bridge that contains IFACE\n"
268 " iface-set-external-id IFACE KEY VALUE"
269 " set KEY on IFACE to VALUE\n"
270 " iface-set-external-id IFACE KEY"
271 " unset KEY on IFACE\n"
272 " iface-get-external-id IFACE KEY"
273 " print value of KEY on IFACE\n"
274 " iface-get-external-id IFACE"
275 " list key-value pairs on IFACE\n"
277 printf("\nOptions:\n"
279 "connect to DATABASE\n"
283 "print exactly one line of output per command\n",
286 printf("\nOther options:\n"
288 "display this help message\n"
290 "display version information\n");
299 def = xasprintf("unix:%s/ovsdb-server", ovs_rundir);
304 struct vsctl_context {
307 const struct ovsrec_open_vswitch *ovs;
309 struct shash options;
312 struct vsctl_bridge {
313 struct ovsrec_bridge *br_cfg;
315 struct vsctl_bridge *parent;
320 struct ovsrec_port *port_cfg;
321 struct vsctl_bridge *bridge;
325 struct ovsrec_interface *iface_cfg;
326 struct vsctl_port *port;
330 struct shash bridges;
335 static struct ovsdb_idl_txn *
336 txn_from_openvswitch(const struct ovsrec_open_vswitch *ovs)
338 return ovsdb_idl_txn_get(&ovs->header_);
341 static struct vsctl_bridge *
342 add_bridge(struct vsctl_info *b,
343 struct ovsrec_bridge *br_cfg, const char *name,
344 struct vsctl_bridge *parent, int vlan)
346 struct vsctl_bridge *br = xmalloc(sizeof *br);
348 br->name = xstrdup(name);
351 shash_add(&b->bridges, br->name, br);
356 port_is_fake_bridge(const struct ovsrec_port *port_cfg)
358 return (port_cfg->fake_bridge
360 && *port_cfg->tag >= 1 && *port_cfg->tag <= 4095);
363 static struct vsctl_bridge *
364 find_vlan_bridge(struct vsctl_info *info,
365 struct vsctl_bridge *parent, int vlan)
367 struct shash_node *node;
369 SHASH_FOR_EACH (node, &info->bridges) {
370 struct vsctl_bridge *br = node->data;
371 if (br->parent == parent && br->vlan == vlan) {
380 free_info(struct vsctl_info *info)
382 struct shash_node *node;
384 SHASH_FOR_EACH (node, &info->bridges) {
385 struct vsctl_bridge *bridge = node->data;
389 shash_destroy(&info->bridges);
391 SHASH_FOR_EACH (node, &info->ports) {
392 struct vsctl_port *port = node->data;
395 shash_destroy(&info->ports);
397 SHASH_FOR_EACH (node, &info->ifaces) {
398 struct vsctl_iface *iface = node->data;
401 shash_destroy(&info->ifaces);
405 get_info(const struct ovsrec_open_vswitch *ovs, struct vsctl_info *info)
407 struct shash bridges, ports;
410 shash_init(&info->bridges);
411 shash_init(&info->ports);
412 shash_init(&info->ifaces);
414 shash_init(&bridges);
416 for (i = 0; i < ovs->n_bridges; i++) {
417 struct ovsrec_bridge *br_cfg = ovs->bridges[i];
418 struct vsctl_bridge *br;
421 if (!shash_add_once(&bridges, br_cfg->name, NULL)) {
422 VLOG_WARN("%s: database contains duplicate bridge name",
426 br = add_bridge(info, br_cfg, br_cfg->name, NULL, 0);
431 for (j = 0; j < br_cfg->n_ports; j++) {
432 struct ovsrec_port *port_cfg = br_cfg->ports[j];
434 if (!shash_add_once(&ports, port_cfg->name, NULL)) {
435 VLOG_WARN("%s: database contains duplicate port name",
440 if (port_is_fake_bridge(port_cfg)
441 && shash_add_once(&bridges, port_cfg->name, NULL)) {
442 add_bridge(info, NULL, port_cfg->name, br, *port_cfg->tag);
446 shash_destroy(&bridges);
447 shash_destroy(&ports);
449 shash_init(&bridges);
451 for (i = 0; i < ovs->n_bridges; i++) {
452 struct ovsrec_bridge *br_cfg = ovs->bridges[i];
453 struct vsctl_bridge *br;
456 if (!shash_add_once(&bridges, br_cfg->name, NULL)) {
459 br = shash_find_data(&info->bridges, br_cfg->name);
460 for (j = 0; j < br_cfg->n_ports; j++) {
461 struct ovsrec_port *port_cfg = br_cfg->ports[j];
462 struct vsctl_port *port;
465 if (!shash_add_once(&ports, port_cfg->name, NULL)) {
469 if (port_is_fake_bridge(port_cfg)
470 && !shash_add_once(&bridges, port_cfg->name, NULL)) {
474 port = xmalloc(sizeof *port);
475 port->port_cfg = port_cfg;
477 && *port_cfg->tag >= 1 && *port_cfg->tag <= 4095) {
478 port->bridge = find_vlan_bridge(info, br, *port_cfg->tag);
485 shash_add(&info->ports, port_cfg->name, port);
487 for (k = 0; k < port_cfg->n_interfaces; k++) {
488 struct ovsrec_interface *iface_cfg = port_cfg->interfaces[k];
489 struct vsctl_iface *iface;
491 if (shash_find(&info->ifaces, iface_cfg->name)) {
492 VLOG_WARN("%s: database contains duplicate interface name",
497 iface = xmalloc(sizeof *iface);
498 iface->iface_cfg = iface_cfg;
500 shash_add(&info->ifaces, iface_cfg->name, iface);
504 shash_destroy(&bridges);
505 shash_destroy(&ports);
509 check_conflicts(struct vsctl_info *info, const char *name,
512 struct vsctl_iface *iface;
513 struct vsctl_port *port;
515 if (shash_find(&info->bridges, name)) {
516 vsctl_fatal("%s because a bridge named %s already exists",
520 port = shash_find_data(&info->ports, name);
522 vsctl_fatal("%s because a port named %s already exists on "
523 "bridge %s", msg, name, port->bridge->name);
526 iface = shash_find_data(&info->ifaces, name);
528 vsctl_fatal("%s because an interface named %s already exists "
529 "on bridge %s", msg, name, iface->port->bridge->name);
535 static struct vsctl_bridge *
536 find_bridge(struct vsctl_info *info, const char *name, bool must_exist)
538 struct vsctl_bridge *br = shash_find_data(&info->bridges, name);
539 if (must_exist && !br) {
540 vsctl_fatal("no bridge named %s", name);
545 static struct vsctl_port *
546 find_port(struct vsctl_info *info, const char *name, bool must_exist)
548 struct vsctl_port *port = shash_find_data(&info->ports, name);
549 if (port && !strcmp(name, port->bridge->name)) {
552 if (must_exist && !port) {
553 vsctl_fatal("no port named %s", name);
558 static struct vsctl_iface *
559 find_iface(struct vsctl_info *info, const char *name, bool must_exist)
561 struct vsctl_iface *iface = shash_find_data(&info->ifaces, name);
562 if (iface && !strcmp(name, iface->port->bridge->name)) {
565 if (must_exist && !iface) {
566 vsctl_fatal("no interface named %s", name);
572 bridge_insert_port(struct ovsrec_bridge *br, struct ovsrec_port *port)
574 struct ovsrec_port **ports;
577 ports = xmalloc(sizeof *br->ports * (br->n_ports + 1));
578 for (i = 0; i < br->n_ports; i++) {
579 ports[i] = br->ports[i];
581 ports[br->n_ports] = port;
582 ovsrec_bridge_set_ports(br, ports, br->n_ports + 1);
587 bridge_delete_port(struct ovsrec_bridge *br, struct ovsrec_port *port)
589 struct ovsrec_port **ports;
592 ports = xmalloc(sizeof *br->ports * br->n_ports);
593 for (i = n = 0; i < br->n_ports; i++) {
594 if (br->ports[i] != port) {
595 ports[n++] = br->ports[i];
598 ovsrec_bridge_set_ports(br, ports, n);
603 ovs_insert_bridge(const struct ovsrec_open_vswitch *ovs,
604 struct ovsrec_bridge *bridge)
606 struct ovsrec_bridge **bridges;
609 bridges = xmalloc(sizeof *ovs->bridges * (ovs->n_bridges + 1));
610 for (i = 0; i < ovs->n_bridges; i++) {
611 bridges[i] = ovs->bridges[i];
613 bridges[ovs->n_bridges] = bridge;
614 ovsrec_open_vswitch_set_bridges(ovs, bridges, ovs->n_bridges + 1);
619 ovs_delete_bridge(const struct ovsrec_open_vswitch *ovs,
620 struct ovsrec_bridge *bridge)
622 struct ovsrec_bridge **bridges;
625 bridges = xmalloc(sizeof *ovs->bridges * ovs->n_bridges);
626 for (i = n = 0; i < ovs->n_bridges; i++) {
627 if (ovs->bridges[i] != bridge) {
628 bridges[n++] = ovs->bridges[i];
631 ovsrec_open_vswitch_set_bridges(ovs, bridges, n);
636 cmd_init(struct vsctl_context *ctx UNUSED)
641 cmd_add_br(struct vsctl_context *ctx)
643 const char *br_name = ctx->argv[1];
644 struct vsctl_info info;
646 get_info(ctx->ovs, &info);
647 check_conflicts(&info, br_name,
648 xasprintf("cannot create a bridge named %s", br_name));
650 if (ctx->argc == 2) {
651 struct ovsrec_bridge *br;
652 struct ovsrec_port *port;
653 struct ovsrec_interface *iface;
655 iface = ovsrec_interface_insert(txn_from_openvswitch(ctx->ovs));
656 ovsrec_interface_set_name(iface, br_name);
658 port = ovsrec_port_insert(txn_from_openvswitch(ctx->ovs));
659 ovsrec_port_set_name(port, br_name);
660 ovsrec_port_set_interfaces(port, &iface, 1);
662 br = ovsrec_bridge_insert(txn_from_openvswitch(ctx->ovs));
663 ovsrec_bridge_set_name(br, br_name);
664 ovsrec_bridge_set_ports(br, &port, 1);
666 ovs_insert_bridge(ctx->ovs, br);
667 } else if (ctx->argc == 3) {
668 vsctl_fatal("'%s' command takes exactly 1 or 3 arguments",
670 } else if (ctx->argc == 4) {
671 const char *parent_name = ctx->argv[2];
672 int vlan = atoi(ctx->argv[3]);
673 struct ovsrec_bridge *br;
674 struct vsctl_bridge *parent;
675 struct ovsrec_port *port;
676 struct ovsrec_interface *iface;
679 if (vlan < 1 || vlan > 4095) {
680 vsctl_fatal("%s: vlan must be between 1 and 4095", ctx->argv[0]);
683 parent = find_bridge(&info, parent_name, false);
684 if (parent && parent->vlan) {
685 vsctl_fatal("cannot create brdige with fake bridge as parent");
688 vsctl_fatal("parent bridge %s does not exist", parent_name);
692 iface = ovsrec_interface_insert(txn_from_openvswitch(ctx->ovs));
693 ovsrec_interface_set_name(iface, br_name);
694 ovsrec_interface_set_type(iface, "internal");
696 port = ovsrec_port_insert(txn_from_openvswitch(ctx->ovs));
697 ovsrec_port_set_name(port, br_name);
698 ovsrec_port_set_interfaces(port, &iface, 1);
699 ovsrec_port_set_fake_bridge(port, true);
700 ovsrec_port_set_tag(port, &tag, 1);
702 bridge_insert_port(br, port);
711 del_port(struct vsctl_info *info, struct vsctl_port *port)
713 struct shash_node *node;
715 SHASH_FOR_EACH (node, &info->ifaces) {
716 struct vsctl_iface *iface = node->data;
717 if (iface->port == port) {
718 ovsrec_interface_delete(iface->iface_cfg);
721 ovsrec_port_delete(port->port_cfg);
723 bridge_delete_port((port->bridge->parent
724 ? port->bridge->parent->br_cfg
725 : port->bridge->br_cfg), port->port_cfg);
729 cmd_del_br(struct vsctl_context *ctx)
731 bool must_exist = !shash_find(&ctx->options, "--if-exists");
732 struct vsctl_bridge *bridge;
733 struct vsctl_info info;
735 get_info(ctx->ovs, &info);
736 bridge = find_bridge(&info, ctx->argv[1], must_exist);
738 struct shash_node *node;
740 SHASH_FOR_EACH (node, &info.ports) {
741 struct vsctl_port *port = node->data;
742 if (port->bridge == bridge
743 || !strcmp(port->port_cfg->name, bridge->name)) {
744 del_port(&info, port);
747 if (bridge->br_cfg) {
748 ovsrec_bridge_delete(bridge->br_cfg);
749 ovs_delete_bridge(ctx->ovs, bridge->br_cfg);
756 output_sorted(struct svec *svec, struct ds *output)
762 SVEC_FOR_EACH (i, name, svec) {
763 ds_put_format(output, "%s\n", name);
768 cmd_list_br(struct vsctl_context *ctx)
770 struct shash_node *node;
771 struct vsctl_info info;
774 get_info(ctx->ovs, &info);
777 SHASH_FOR_EACH (node, &info.bridges) {
778 struct vsctl_bridge *br = node->data;
779 svec_add(&bridges, br->name);
781 output_sorted(&bridges, &ctx->output);
782 svec_destroy(&bridges);
788 cmd_br_exists(struct vsctl_context *ctx)
790 struct vsctl_info info;
792 get_info(ctx->ovs, &info);
793 if (!find_bridge(&info, ctx->argv[1], false)) {
799 /* Returns true if 'b_prefix' (of length 'b_prefix_len') concatenated with 'b'
800 * equals 'a', false otherwise. */
802 key_matches(const char *a,
803 const char *b_prefix, size_t b_prefix_len, const char *b)
805 return !strncmp(a, b_prefix, b_prefix_len) && !strcmp(a + b_prefix_len, b);
809 set_external_id(char **old_keys, char **old_values, size_t old_n,
810 char *key, char *value,
811 char ***new_keysp, char ***new_valuesp, size_t *new_np)
818 new_keys = xmalloc(sizeof *new_keys * (old_n + 1));
819 new_values = xmalloc(sizeof *new_values * (old_n + 1));
821 for (i = 0; i < old_n; i++) {
822 if (strcmp(key, old_keys[i])) {
823 new_keys[new_n] = old_keys[i];
824 new_values[new_n] = old_values[i];
829 new_keys[new_n] = key;
830 new_values[new_n] = value;
833 *new_keysp = new_keys;
834 *new_valuesp = new_values;
839 cmd_br_set_external_id(struct vsctl_context *ctx)
841 struct vsctl_info info;
842 struct vsctl_bridge *bridge;
843 char **keys, **values;
846 get_info(ctx->ovs, &info);
847 bridge = find_bridge(&info, ctx->argv[1], true);
848 if (bridge->br_cfg) {
849 set_external_id(bridge->br_cfg->key_external_ids,
850 bridge->br_cfg->value_external_ids,
851 bridge->br_cfg->n_external_ids,
852 ctx->argv[2], ctx->argc >= 4 ? ctx->argv[3] : NULL,
854 ovsrec_bridge_set_external_ids(bridge->br_cfg, keys, values, n);
856 char *key = xasprintf("fake-bridge-%s", ctx->argv[2]);
857 struct vsctl_port *port = shash_find_data(&info.ports, ctx->argv[1]);
858 set_external_id(port->port_cfg->key_external_ids,
859 port->port_cfg->value_external_ids,
860 port->port_cfg->n_external_ids,
861 key, ctx->argc >= 4 ? ctx->argv[3] : NULL,
863 ovsrec_port_set_external_ids(port->port_cfg, keys, values, n);
873 get_external_id(char **keys, char **values, size_t n,
874 const char *prefix, const char *key,
877 size_t prefix_len = strlen(prefix);
882 for (i = 0; i < n; i++) {
883 if (!key && !strncmp(keys[i], prefix, prefix_len)) {
884 svec_add_nocopy(&svec, xasprintf("%s=%s",
885 keys[i] + prefix_len, values[i]));
886 } else if (key_matches(keys[i], prefix, prefix_len, key)) {
887 svec_add(&svec, values[i]);
891 output_sorted(&svec, output);
896 cmd_br_get_external_id(struct vsctl_context *ctx)
898 struct vsctl_info info;
899 struct vsctl_bridge *bridge;
901 get_info(ctx->ovs, &info);
902 bridge = find_bridge(&info, ctx->argv[1], true);
903 if (bridge->br_cfg) {
904 get_external_id(bridge->br_cfg->key_external_ids,
905 bridge->br_cfg->value_external_ids,
906 bridge->br_cfg->n_external_ids,
907 "", ctx->argc >= 3 ? ctx->argv[2] : NULL,
910 struct vsctl_port *port = shash_find_data(&info.ports, ctx->argv[1]);
911 get_external_id(port->port_cfg->key_external_ids,
912 port->port_cfg->value_external_ids,
913 port->port_cfg->n_external_ids,
914 "fake-bridge-", ctx->argc >= 3 ? ctx->argv[2] : NULL, &ctx->output);
921 cmd_list_ports(struct vsctl_context *ctx)
923 struct vsctl_bridge *br;
924 struct shash_node *node;
925 struct vsctl_info info;
928 get_info(ctx->ovs, &info);
929 br = find_bridge(&info, ctx->argv[1], true);
932 SHASH_FOR_EACH (node, &info.ports) {
933 struct vsctl_port *port = node->data;
935 if (strcmp(port->port_cfg->name, br->name) && br == port->bridge) {
936 svec_add(&ports, port->port_cfg->name);
939 output_sorted(&ports, &ctx->output);
940 svec_destroy(&ports);
946 add_port(const struct ovsrec_open_vswitch *ovs,
947 const char *br_name, const char *port_name,
948 char *iface_names[], int n_ifaces)
950 struct vsctl_info info;
951 struct vsctl_bridge *bridge;
952 struct ovsrec_interface **ifaces;
953 struct ovsrec_port *port;
956 get_info(ovs, &info);
957 check_conflicts(&info, port_name,
958 xasprintf("cannot create a port named %s", port_name));
959 /* XXX need to check for conflicts on interfaces too */
960 bridge = find_bridge(&info, br_name, true);
962 ifaces = xmalloc(n_ifaces * sizeof *ifaces);
963 for (i = 0; i < n_ifaces; i++) {
964 ifaces[i] = ovsrec_interface_insert(txn_from_openvswitch(ovs));
965 ovsrec_interface_set_name(ifaces[i], iface_names[i]);
968 port = ovsrec_port_insert(txn_from_openvswitch(ovs));
969 ovsrec_port_set_name(port, port_name);
970 ovsrec_port_set_interfaces(port, ifaces, n_ifaces);
974 int64_t tag = bridge->vlan;
975 ovsrec_port_set_tag(port, &tag, 1);
978 bridge_insert_port((bridge->parent ? bridge->parent->br_cfg
979 : bridge->br_cfg), port);
985 cmd_add_port(struct vsctl_context *ctx)
987 add_port(ctx->ovs, ctx->argv[1], ctx->argv[2], &ctx->argv[2], 1);
991 cmd_add_bond(struct vsctl_context *ctx)
993 add_port(ctx->ovs, ctx->argv[1], ctx->argv[2], &ctx->argv[3], ctx->argc - 3);
997 cmd_del_port(struct vsctl_context *ctx)
999 bool must_exist = !shash_find(&ctx->options, "--if-exists");
1000 struct vsctl_info info;
1002 get_info(ctx->ovs, &info);
1003 if (ctx->argc == 2) {
1004 struct vsctl_port *port = find_port(&info, ctx->argv[1], must_exist);
1006 del_port(&info, port);
1008 } else if (ctx->argc == 3) {
1009 struct vsctl_bridge *bridge = find_bridge(&info, ctx->argv[1], true);
1010 struct vsctl_port *port = find_port(&info, ctx->argv[2], must_exist);
1013 if (port->bridge == bridge) {
1014 del_port(&info, port);
1015 } else if (port->bridge->parent == bridge) {
1016 vsctl_fatal("bridge %s does not have a port %s (although its "
1017 "parent bridge %s does)",
1018 ctx->argv[1], ctx->argv[2], bridge->parent->name);
1020 vsctl_fatal("bridge %s does not have a port %s",
1021 ctx->argv[1], ctx->argv[2]);
1029 cmd_port_to_br(struct vsctl_context *ctx)
1031 struct vsctl_port *port;
1032 struct vsctl_info info;
1034 get_info(ctx->ovs, &info);
1035 port = find_port(&info, ctx->argv[1], true);
1036 ds_put_format(&ctx->output, "%s\n", port->bridge->name);
1041 cmd_port_set_external_id(struct vsctl_context *ctx)
1043 struct vsctl_info info;
1044 struct vsctl_port *port;
1045 char **keys, **values;
1048 get_info(ctx->ovs, &info);
1049 port = find_port(&info, ctx->argv[1], true);
1050 set_external_id(port->port_cfg->key_external_ids,
1051 port->port_cfg->value_external_ids,
1052 port->port_cfg->n_external_ids,
1053 ctx->argv[2], ctx->argc >= 4 ? ctx->argv[3] : NULL,
1054 &keys, &values, &n);
1055 ovsrec_port_set_external_ids(port->port_cfg, keys, values, n);
1063 cmd_port_get_external_id(struct vsctl_context *ctx)
1065 struct vsctl_info info;
1066 struct vsctl_port *port;
1068 get_info(ctx->ovs, &info);
1069 port = find_port(&info, ctx->argv[1], true);
1070 get_external_id(port->port_cfg->key_external_ids,
1071 port->port_cfg->value_external_ids,
1072 port->port_cfg->n_external_ids,
1073 "", ctx->argc >= 3 ? ctx->argv[2] : NULL, &ctx->output);
1078 cmd_br_to_vlan(struct vsctl_context *ctx)
1080 struct vsctl_bridge *bridge;
1081 struct vsctl_info info;
1083 get_info(ctx->ovs, &info);
1084 bridge = find_bridge(&info, ctx->argv[1], true);
1085 ds_put_format(&ctx->output, "%d\n", bridge->vlan);
1090 cmd_br_to_parent(struct vsctl_context *ctx)
1092 struct vsctl_bridge *bridge;
1093 struct vsctl_info info;
1095 get_info(ctx->ovs, &info);
1096 bridge = find_bridge(&info, ctx->argv[1], true);
1097 if (bridge->parent) {
1098 bridge = bridge->parent;
1100 ds_put_format(&ctx->output, "%s\n", bridge->name);
1105 cmd_list_ifaces(struct vsctl_context *ctx)
1107 struct vsctl_bridge *br;
1108 struct shash_node *node;
1109 struct vsctl_info info;
1112 get_info(ctx->ovs, &info);
1113 br = find_bridge(&info, ctx->argv[1], true);
1116 SHASH_FOR_EACH (node, &info.ifaces) {
1117 struct vsctl_iface *iface = node->data;
1119 if (strcmp(iface->iface_cfg->name, br->name)
1120 && br == iface->port->bridge) {
1121 svec_add(&ifaces, iface->iface_cfg->name);
1124 output_sorted(&ifaces, &ctx->output);
1125 svec_destroy(&ifaces);
1131 cmd_iface_to_br(struct vsctl_context *ctx)
1133 struct vsctl_iface *iface;
1134 struct vsctl_info info;
1136 get_info(ctx->ovs, &info);
1137 iface = find_iface(&info, ctx->argv[1], true);
1138 ds_put_format(&ctx->output, "%s\n", iface->port->bridge->name);
1143 cmd_iface_set_external_id(struct vsctl_context *ctx)
1145 struct vsctl_info info;
1146 struct vsctl_iface *iface;
1147 char **keys, **values;
1150 get_info(ctx->ovs, &info);
1151 iface = find_iface(&info, ctx->argv[1], true);
1152 set_external_id(iface->iface_cfg->key_external_ids,
1153 iface->iface_cfg->value_external_ids,
1154 iface->iface_cfg->n_external_ids,
1155 ctx->argv[2], ctx->argc >= 4 ? ctx->argv[3] : NULL,
1156 &keys, &values, &n);
1157 ovsrec_interface_set_external_ids(iface->iface_cfg, keys, values, n);
1165 cmd_iface_get_external_id(struct vsctl_context *ctx)
1167 struct vsctl_info info;
1168 struct vsctl_iface *iface;
1170 get_info(ctx->ovs, &info);
1171 iface = find_iface(&info, ctx->argv[1], true);
1172 get_external_id(iface->iface_cfg->key_external_ids,
1173 iface->iface_cfg->value_external_ids,
1174 iface->iface_cfg->n_external_ids,
1175 "", ctx->argc >= 3 ? ctx->argv[2] : NULL, &ctx->output);
1179 typedef void vsctl_handler_func(struct vsctl_context *);
1181 struct vsctl_command {
1185 vsctl_handler_func *handler;
1186 const char *options;
1189 static void run_vsctl_command(int argc, char *argv[],
1190 const struct ovsrec_open_vswitch *ovs,
1194 do_vsctl(int argc, char *argv[], struct ovsdb_idl *idl)
1196 struct ovsdb_idl_txn *txn;
1197 const struct ovsrec_open_vswitch *ovs;
1198 enum ovsdb_idl_txn_status status;
1203 txn = ovsdb_idl_txn_create(idl);
1205 ovsdb_idl_txn_set_dry_run(txn);
1208 ovs = ovsrec_open_vswitch_first(idl);
1210 /* XXX add verification that table is empty */
1211 ovs = ovsrec_open_vswitch_insert(txn);
1214 output = xmalloc(argc * sizeof *output);
1216 for (start = i = 0; i <= argc; i++) {
1217 if (i == argc || !strcmp(argv[i], "--")) {
1219 ds_init(&output[n_output]);
1220 run_vsctl_command(i - start, &argv[start], ovs,
1221 &output[n_output++]);
1227 while ((status = ovsdb_idl_txn_commit(txn)) == TXN_INCOMPLETE) {
1229 ovsdb_idl_wait(idl);
1230 ovsdb_idl_txn_wait(txn);
1233 ovsdb_idl_txn_destroy(txn);
1236 case TXN_INCOMPLETE:
1240 /* Should not happen--we never call ovsdb_idl_txn_abort(). */
1241 vsctl_fatal("transaction aborted");
1247 for (i = 0; i < n_output; i++) {
1248 ds_destroy(&output[i]);
1253 vsctl_fatal("transaction error");
1259 for (i = 0; i < n_output; i++) {
1260 struct ds *ds = &output[i];
1265 for (j = 0; j < ds->length; j++) {
1266 int c = ds->string[j];
1269 fputs("\\n", stdout);
1273 fputs("\\\\", stdout);
1282 fputs(ds_cstr(ds), stdout);
1288 static vsctl_handler_func *
1289 get_vsctl_handler(int argc, char *argv[], struct vsctl_context *ctx)
1291 static const struct vsctl_command all_commands[] = {
1292 /* Open vSwitch commands. */
1293 {"init", 0, 0, cmd_init, ""},
1295 /* Bridge commands. */
1296 {"add-br", 1, 3, cmd_add_br, ""},
1297 {"del-br", 1, 1, cmd_del_br, "--if-exists"},
1298 {"list-br", 0, 0, cmd_list_br, ""},
1299 {"br-exists", 1, 1, cmd_br_exists, ""},
1300 {"br-to-vlan", 1, 1, cmd_br_to_vlan, ""},
1301 {"br-to-parent", 1, 1, cmd_br_to_parent, ""},
1302 {"br-set-external-id", 2, 3, cmd_br_set_external_id, ""},
1303 {"br-get-external-id", 1, 2, cmd_br_get_external_id, ""},
1305 /* Port commands. */
1306 {"list-ports", 1, 1, cmd_list_ports, ""},
1307 {"add-port", 2, 2, cmd_add_port, ""},
1308 {"add-bond", 4, INT_MAX, cmd_add_bond, ""},
1309 {"del-port", 1, 2, cmd_del_port, "--if-exists"},
1310 {"port-to-br", 1, 1, cmd_port_to_br, ""},
1311 {"port-set-external-id", 2, 3, cmd_port_set_external_id, ""},
1312 {"port-get-external-id", 1, 2, cmd_port_get_external_id, ""},
1314 /* Interface commands. */
1315 {"list-ifaces", 1, 1, cmd_list_ifaces, ""},
1316 {"iface-to-br", 1, 1, cmd_iface_to_br, ""},
1317 {"iface-set-external-id", 2, 3, cmd_iface_set_external_id, ""},
1318 {"iface-get-external-id", 1, 2, cmd_iface_get_external_id, ""},
1321 const struct vsctl_command *p;
1324 shash_init(&ctx->options);
1325 for (i = 0; i < argc; i++) {
1326 if (argv[i][0] != '-') {
1329 if (!shash_add_once(&ctx->options, argv[i], NULL)) {
1330 vsctl_fatal("'%s' option specified multiple times", argv[i]);
1334 vsctl_fatal("missing command name");
1337 for (p = all_commands; p < &all_commands[ARRAY_SIZE(all_commands)]; p++) {
1338 if (!strcmp(p->name, argv[i])) {
1339 struct shash_node *node;
1342 SHASH_FOR_EACH (node, &ctx->options) {
1343 const char *s = strstr(p->options, node->name);
1344 int end = s ? s[strlen(node->name)] : EOF;
1345 if (end != ',' && end != ' ' && end != '\0') {
1346 vsctl_fatal("'%s' command has no '%s' option",
1347 argv[i], node->name);
1351 n_arg = argc - i - 1;
1352 if (n_arg < p->min_args) {
1353 vsctl_fatal("'%s' command requires at least %d arguments",
1354 p->name, p->min_args);
1355 } else if (n_arg > p->max_args) {
1356 vsctl_fatal("'%s' command takes at most %d arguments",
1357 p->name, p->max_args);
1359 ctx->argc = n_arg + 1;
1360 ctx->argv = &argv[i];
1366 vsctl_fatal("unknown command '%s'; use --help for help", argv[i]);
1370 check_vsctl_command(int argc, char *argv[])
1372 struct vsctl_context ctx;
1374 get_vsctl_handler(argc, argv, &ctx);
1375 shash_destroy(&ctx.options);
1379 run_vsctl_command(int argc, char *argv[],
1380 const struct ovsrec_open_vswitch *ovs, struct ds *output)
1382 vsctl_handler_func *function;
1383 struct vsctl_context ctx;
1385 function = get_vsctl_handler(argc, argv, &ctx);
1387 ds_init(&ctx.output);
1389 *output = ctx.output;
1390 shash_destroy(&ctx.options);