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 char *default_db(void);
49 static void usage(void) NO_RETURN;
50 static void parse_options(int argc, char *argv[]);
52 static void check_vsctl_command(int argc, char *argv[]);
53 static void do_vsctl(int argc, char *argv[], struct ovsdb_idl *idl);
56 main(int argc, char *argv[])
58 struct ovsdb_idl *idl;
61 int start, n_commands;
65 set_program_name(argv[0]);
66 signal(SIGPIPE, SIG_IGN);
69 vlog_set_levels(VLM_ANY_MODULE, VLF_CONSOLE, VLL_WARN);
70 vlog_set_levels(VLM_reconnect, VLF_ANY_FACILITY, VLL_WARN);
71 parse_options(argc, argv);
73 /* Log our arguments. This is often valuable for debugging systems. */
75 for (i = 1; i < argc; i++) {
76 ds_put_format(&args, " %s", argv[i]);
78 VLOG_INFO("Called as%s", ds_cstr(&args));
81 /* Do basic command syntax checking. */
83 for (start = i = optind; i <= argc; i++) {
84 if (i == argc || !strcmp(argv[i], "--")) {
86 check_vsctl_command(i - start, &argv[start]);
93 ovs_fatal(0, "missing command name (use --help for help)");
96 /* Now execut the commands. */
97 idl = ovsdb_idl_create(db, &ovsrec_idl_class);
98 seqno = ovsdb_idl_get_seqno(idl);
101 unsigned int new_seqno;
104 new_seqno = ovsdb_idl_get_seqno(idl);
105 if (new_seqno != seqno) {
107 ovs_fatal(0, "too many database inconsistency failures");
109 do_vsctl(argc - optind, argv + optind, idl);
119 parse_options(int argc, char *argv[])
122 OPT_DB = UCHAR_MAX + 1,
126 static struct option long_options[] = {
127 {"db", required_argument, 0, OPT_DB},
128 {"no-syslog", no_argument, 0, OPT_NO_SYSLOG},
129 {"oneline", no_argument, 0, OPT_ONELINE},
130 {"verbose", optional_argument, 0, 'v'},
131 {"help", no_argument, 0, 'h'},
132 {"version", no_argument, 0, 'V'},
139 c = getopt_long(argc, argv, "+v::hV", long_options, NULL);
154 vlog_set_levels(VLM_vsctl, VLF_SYSLOG, VLL_WARN);
161 OVS_PRINT_VERSION(0, 0);
165 vlog_set_verbosity(optarg);
184 printf("%s: ovs-vswitchd management utility\n"
185 "usage: %s [OPTIONS] COMMAND [ARG...]\n",
186 program_name, program_name);
187 printf("\nBridge commands:\n"
189 "create a new bridge named BRIDGE\n"
190 " add-br BRIDGE PARENT VLAN "
191 "create new fake bridge BRIDGE in PARENT on VLAN\n"
193 "delete BRIDGE and all of its ports\n"
195 "print the names of all the bridges\n"
197 "test whether BRIDGE exists\n"
198 " br-to-vlan BRIDGE "
199 "print the VLAN which BRIDGE is on\n"
200 " br-to-parent BRIDGE "
201 "print the parent of BRIDGE\n");
202 printf("\nPort commands:\n"
203 " list-ports BRIDGE "
204 "print the names of all the ports on BRIDGE\n"
205 " add-port BRIDGE PORT "
206 "add network device PORT to BRIDGE\n"
207 " add-bond BRIDGE PORT IFACE... "
208 "add new bonded port PORT in BRIDGE from IFACES\n"
209 " del-port [BRIDGE] PORT "
210 "delete PORT (which may be bonded) from BRIDGE\n"
212 "print name of bridge that contains PORT\n"
213 "A bond is considered to be a single port.\n");
214 printf("\nInterface commands (a bond consists of multiple interfaces):\n"
215 " list-ifaces BRIDGE "
216 "print the names of all the interfaces on BRIDGE\n"
217 " iface-to-br IFACE "
218 "print name of bridge that contains IFACE\n");
219 printf("\nOptions:\n"
221 "connect to DATABASE\n"
225 "print exactly one line of output per command\n",
228 printf("\nOther options:\n"
230 "display this help message\n"
232 "display version information\n");
241 def = xasprintf("unix:%s/ovsdb-server", ovs_rundir);
246 struct vsctl_bridge {
247 struct ovsrec_bridge *br_cfg;
249 struct vsctl_bridge *parent;
254 struct ovsrec_port *port_cfg;
255 struct vsctl_bridge *bridge;
259 struct ovsrec_interface *iface_cfg;
260 struct vsctl_port *port;
264 struct shash bridges;
269 static struct ovsdb_idl_txn *
270 txn_from_openvswitch(const struct ovsrec_open_vswitch *ovs)
272 return ovsdb_idl_txn_get(&ovs->header_);
275 static struct vsctl_bridge *
276 add_bridge(struct vsctl_info *b,
277 struct ovsrec_bridge *br_cfg, const char *name,
278 struct vsctl_bridge *parent, int vlan)
280 struct vsctl_bridge *br = xmalloc(sizeof *br);
282 br->name = xstrdup(name);
285 shash_add(&b->bridges, br->name, br);
290 port_is_fake_bridge(const struct ovsrec_port *port_cfg)
292 return (port_cfg->fake_bridge
294 && *port_cfg->tag >= 1 && *port_cfg->tag <= 4095);
297 static struct vsctl_bridge *
298 find_vlan_bridge(struct vsctl_info *info,
299 struct vsctl_bridge *parent, int vlan)
301 struct shash_node *node;
303 SHASH_FOR_EACH (node, &info->bridges) {
304 struct vsctl_bridge *br = node->data;
305 if (br->parent == parent && br->vlan == vlan) {
314 free_info(struct vsctl_info *info)
316 struct shash_node *node;
318 SHASH_FOR_EACH (node, &info->bridges) {
319 struct vsctl_bridge *bridge = node->data;
323 shash_destroy(&info->bridges);
325 SHASH_FOR_EACH (node, &info->ports) {
326 struct vsctl_port *port = node->data;
329 shash_destroy(&info->ports);
331 SHASH_FOR_EACH (node, &info->ifaces) {
332 struct vsctl_iface *iface = node->data;
335 shash_destroy(&info->ifaces);
339 get_info(const struct ovsrec_open_vswitch *ovs, struct vsctl_info *info)
341 struct shash bridges, ports;
344 shash_init(&info->bridges);
345 shash_init(&info->ports);
346 shash_init(&info->ifaces);
348 shash_init(&bridges);
350 for (i = 0; i < ovs->n_bridges; i++) {
351 struct ovsrec_bridge *br_cfg = ovs->bridges[i];
352 struct vsctl_bridge *br;
355 if (!shash_add_once(&bridges, br_cfg->name, NULL)) {
356 VLOG_WARN("%s: database contains duplicate bridge name",
360 br = add_bridge(info, br_cfg, br_cfg->name, NULL, 0);
365 for (j = 0; j < br_cfg->n_ports; j++) {
366 struct ovsrec_port *port_cfg = br_cfg->ports[j];
368 if (!shash_add_once(&ports, port_cfg->name, NULL)) {
369 VLOG_WARN("%s: database contains duplicate port name",
374 if (port_is_fake_bridge(port_cfg)
375 && shash_add_once(&bridges, port_cfg->name, NULL)) {
376 add_bridge(info, NULL, port_cfg->name, br, *port_cfg->tag);
380 shash_destroy(&bridges);
381 shash_destroy(&ports);
383 shash_init(&bridges);
385 for (i = 0; i < ovs->n_bridges; i++) {
386 struct ovsrec_bridge *br_cfg = ovs->bridges[i];
387 struct vsctl_bridge *br;
390 if (!shash_add_once(&bridges, br_cfg->name, NULL)) {
393 br = shash_find_data(&info->bridges, br_cfg->name);
394 for (j = 0; j < br_cfg->n_ports; j++) {
395 struct ovsrec_port *port_cfg = br_cfg->ports[j];
396 struct vsctl_port *port;
399 if (!shash_add_once(&ports, port_cfg->name, NULL)) {
403 if (port_is_fake_bridge(port_cfg)
404 && !shash_add_once(&bridges, port_cfg->name, NULL)) {
408 port = xmalloc(sizeof *port);
409 port->port_cfg = port_cfg;
411 && *port_cfg->tag >= 1 && *port_cfg->tag <= 4095) {
412 port->bridge = find_vlan_bridge(info, br, *port_cfg->tag);
419 shash_add(&info->ports, port_cfg->name, port);
421 for (k = 0; k < port_cfg->n_interfaces; k++) {
422 struct ovsrec_interface *iface_cfg = port_cfg->interfaces[k];
423 struct vsctl_iface *iface;
425 if (shash_find(&info->ifaces, iface_cfg->name)) {
426 VLOG_WARN("%s: database contains duplicate interface name",
431 iface = xmalloc(sizeof *iface);
432 iface->iface_cfg = iface_cfg;
434 shash_add(&info->ifaces, iface_cfg->name, iface);
438 shash_destroy(&bridges);
439 shash_destroy(&ports);
443 check_conflicts(struct vsctl_info *info, const char *name,
446 struct vsctl_iface *iface;
447 struct vsctl_port *port;
449 if (shash_find(&info->bridges, name)) {
450 ovs_fatal(0, "%s because a bridge named %s already exists", msg, name);
453 port = shash_find_data(&info->ports, name);
455 ovs_fatal(0, "%s because a port named %s already exists on bridge %s",
456 msg, name, port->bridge->name);
459 iface = shash_find_data(&info->ifaces, name);
461 ovs_fatal(0, "%s because an interface named %s already exists "
462 "on bridge %s", msg, name, iface->port->bridge->name);
468 static struct vsctl_bridge *
469 find_bridge(struct vsctl_info *info, const char *name)
471 struct vsctl_bridge *br = shash_find_data(&info->bridges, name);
473 ovs_fatal(0, "no bridge named %s", name);
478 static struct vsctl_port *
479 find_port(struct vsctl_info *info, const char *name)
481 struct vsctl_port *port = shash_find_data(&info->ports, name);
482 if (!port || !strcmp(name, port->bridge->name)) {
483 ovs_fatal(0, "no port named %s", name);
488 static struct vsctl_iface *
489 find_iface(struct vsctl_info *info, const char *name)
491 struct vsctl_iface *iface = shash_find_data(&info->ifaces, name);
492 if (!iface || !strcmp(name, iface->port->bridge->name)) {
493 ovs_fatal(0, "no interface named %s", name);
499 bridge_insert_port(struct ovsrec_bridge *br, struct ovsrec_port *port)
501 struct ovsrec_port **ports;
504 ports = xmalloc(sizeof *br->ports * (br->n_ports + 1));
505 for (i = 0; i < br->n_ports; i++) {
506 ports[i] = br->ports[i];
508 ports[br->n_ports] = port;
509 ovsrec_bridge_set_ports(br, ports, br->n_ports + 1);
514 bridge_delete_port(struct ovsrec_bridge *br, struct ovsrec_port *port)
516 struct ovsrec_port **ports;
519 ports = xmalloc(sizeof *br->ports * br->n_ports);
520 for (i = n = 0; i < br->n_ports; i++) {
521 if (br->ports[i] != port) {
522 ports[n++] = br->ports[i];
525 ovsrec_bridge_set_ports(br, ports, n);
530 ovs_insert_bridge(const struct ovsrec_open_vswitch *ovs,
531 struct ovsrec_bridge *bridge)
533 struct ovsrec_bridge **bridges;
536 bridges = xmalloc(sizeof *ovs->bridges * (ovs->n_bridges + 1));
537 for (i = 0; i < ovs->n_bridges; i++) {
538 bridges[i] = ovs->bridges[i];
540 bridges[ovs->n_bridges] = bridge;
541 ovsrec_open_vswitch_set_bridges(ovs, bridges, ovs->n_bridges + 1);
546 ovs_delete_bridge(const struct ovsrec_open_vswitch *ovs,
547 struct ovsrec_bridge *bridge)
549 struct ovsrec_bridge **bridges;
552 bridges = xmalloc(sizeof *ovs->bridges * ovs->n_bridges);
553 for (i = n = 0; i < ovs->n_bridges; i++) {
554 if (ovs->bridges[i] != bridge) {
555 bridges[n++] = ovs->bridges[i];
558 ovsrec_open_vswitch_set_bridges(ovs, bridges, n);
563 cmd_add_br(int argc, char *argv[], const struct ovsrec_open_vswitch *ovs,
564 struct ds *output UNUSED)
566 const char *br_name = argv[1];
567 struct vsctl_info info;
569 get_info(ovs, &info);
570 check_conflicts(&info, br_name,
571 xasprintf("cannot create a bridge named %s", br_name));
574 struct ovsrec_bridge *br;
575 struct ovsrec_port *port;
576 struct ovsrec_interface *iface;
578 iface = ovsrec_interface_insert(txn_from_openvswitch(ovs));
579 ovsrec_interface_set_name(iface, br_name);
581 port = ovsrec_port_insert(txn_from_openvswitch(ovs));
582 ovsrec_port_set_name(port, br_name);
583 ovsrec_port_set_interfaces(port, &iface, 1);
585 br = ovsrec_bridge_insert(txn_from_openvswitch(ovs));
586 ovsrec_bridge_set_name(br, br_name);
587 ovsrec_bridge_set_ports(br, &port, 1);
589 ovs_insert_bridge(ovs, br);
590 } else if (argc == 3) {
591 ovs_fatal(0, "'%s' comamnd takes exactly 1 or 3 arguments", argv[0]);
592 } else if (argc == 4) {
593 const char *parent_name = argv[2];
594 int vlan = atoi(argv[3]);
595 struct ovsrec_bridge *br;
596 struct vsctl_bridge *parent;
597 struct ovsrec_port *port;
598 struct ovsrec_interface *iface;
601 if (vlan < 1 || vlan > 4095) {
602 ovs_fatal(0, "%s: vlan must be between 1 and 4095", argv[0]);
605 parent = shash_find_data(&info.bridges, parent_name);
606 if (parent && parent->vlan) {
607 ovs_fatal(0, "cannot create brdige with fake bridge as parent");
610 ovs_fatal(0, "parent bridge %s does not exist", parent_name);
614 iface = ovsrec_interface_insert(txn_from_openvswitch(ovs));
615 ovsrec_interface_set_name(iface, br_name);
616 ovsrec_interface_set_type(iface, "internal");
618 port = ovsrec_port_insert(txn_from_openvswitch(ovs));
619 ovsrec_port_set_name(port, br_name);
620 ovsrec_port_set_interfaces(port, &iface, 1);
621 ovsrec_port_set_fake_bridge(port, true);
622 ovsrec_port_set_tag(port, &tag, 1);
624 bridge_insert_port(br, port);
633 del_port(struct vsctl_info *info, struct vsctl_port *port)
635 struct shash_node *node;
637 SHASH_FOR_EACH (node, &info->ifaces) {
638 struct vsctl_iface *iface = node->data;
639 if (iface->port == port) {
640 ovsrec_interface_delete(iface->iface_cfg);
643 ovsrec_port_delete(port->port_cfg);
645 bridge_delete_port((port->bridge->parent
646 ? port->bridge->parent->br_cfg
647 : port->bridge->br_cfg), port->port_cfg);
651 cmd_del_br(int argc UNUSED, char *argv[],
652 const struct ovsrec_open_vswitch *ovs, struct ds *output UNUSED)
654 struct shash_node *node;
655 struct vsctl_info info;
656 struct vsctl_bridge *bridge;
658 get_info(ovs, &info);
659 bridge = find_bridge(&info, argv[1]);
660 SHASH_FOR_EACH (node, &info.ports) {
661 struct vsctl_port *port = node->data;
662 if (port->bridge == bridge
663 || !strcmp(port->port_cfg->name, bridge->name)) {
664 del_port(&info, port);
667 if (bridge->br_cfg) {
668 ovsrec_bridge_delete(bridge->br_cfg);
669 ovs_delete_bridge(ovs, bridge->br_cfg);
675 output_sorted(struct svec *svec, struct ds *output)
681 SVEC_FOR_EACH (i, name, svec) {
682 ds_put_format(output, "%s\n", name);
687 cmd_list_br(int argc UNUSED, char *argv[] UNUSED,
688 const struct ovsrec_open_vswitch *ovs, struct ds *output)
690 struct shash_node *node;
691 struct vsctl_info info;
694 get_info(ovs, &info);
697 SHASH_FOR_EACH (node, &info.bridges) {
698 struct vsctl_bridge *br = node->data;
699 svec_add(&bridges, br->name);
701 output_sorted(&bridges, output);
702 svec_destroy(&bridges);
708 cmd_br_exists(int argc UNUSED, char *argv[],
709 const struct ovsrec_open_vswitch *ovs, struct ds *output UNUSED)
711 struct vsctl_info info;
713 get_info(ovs, &info);
714 if (!shash_find_data(&info.bridges, argv[1])) {
720 /* Returns true if 'b_prefix' (of length 'b_prefix_len') concatenated with 'b'
721 * equals 'a', false otherwise. */
723 key_matches(const char *a,
724 const char *b_prefix, size_t b_prefix_len, const char *b)
726 return !strncmp(a, b_prefix, b_prefix_len) && !strcmp(a + b_prefix_len, b);
730 set_external_id(char **old_keys, char **old_values, size_t old_n,
731 char *key, char *value,
732 char ***new_keysp, char ***new_valuesp, size_t *new_np)
739 new_keys = xmalloc(sizeof *new_keys * (old_n + 1));
740 new_values = xmalloc(sizeof *new_values * (old_n + 1));
742 for (i = 0; i < old_n; i++) {
743 if (strcmp(key, old_keys[i])) {
744 new_keys[new_n] = old_keys[i];
745 new_values[new_n] = old_values[i];
750 new_keys[new_n] = key;
751 new_values[new_n] = value;
754 *new_keysp = new_keys;
755 *new_valuesp = new_values;
760 cmd_br_set_external_id(int argc, char *argv[],
761 const struct ovsrec_open_vswitch *ovs,
762 struct ds *output UNUSED)
764 struct vsctl_info info;
765 struct vsctl_bridge *bridge;
766 char **keys, **values;
769 get_info(ovs, &info);
770 bridge = find_bridge(&info, argv[1]);
771 if (bridge->br_cfg) {
772 set_external_id(bridge->br_cfg->key_external_ids,
773 bridge->br_cfg->value_external_ids,
774 bridge->br_cfg->n_external_ids,
775 argv[2], argc >= 4 ? argv[3] : NULL,
777 ovsrec_bridge_set_external_ids(bridge->br_cfg, keys, values, n);
779 char *key = xasprintf("fake-bridge-%s", argv[2]);
780 struct vsctl_port *port = shash_find_data(&info.ports, argv[1]);
781 set_external_id(port->port_cfg->key_external_ids,
782 port->port_cfg->value_external_ids,
783 port->port_cfg->n_external_ids,
784 key, argc >= 4 ? argv[3] : NULL,
786 ovsrec_port_set_external_ids(port->port_cfg, keys, values, n);
796 get_external_id(char **keys, char **values, size_t n,
797 const char *prefix, const char *key,
800 size_t prefix_len = strlen(prefix);
805 for (i = 0; i < n; i++) {
806 if (!key && !strncmp(keys[i], prefix, prefix_len)) {
807 svec_add_nocopy(&svec, xasprintf("%s=%s",
808 keys[i] + prefix_len, values[i]));
809 } else if (key_matches(keys[i], prefix, prefix_len, key)) {
810 svec_add(&svec, values[i]);
814 output_sorted(&svec, output);
819 cmd_br_get_external_id(int argc, char *argv[],
820 const struct ovsrec_open_vswitch *ovs,
823 struct vsctl_info info;
824 struct vsctl_bridge *bridge;
826 get_info(ovs, &info);
827 bridge = find_bridge(&info, argv[1]);
828 if (bridge->br_cfg) {
829 get_external_id(bridge->br_cfg->key_external_ids,
830 bridge->br_cfg->value_external_ids,
831 bridge->br_cfg->n_external_ids,
832 "", argc >= 3 ? argv[2] : NULL, output);
834 struct vsctl_port *port = shash_find_data(&info.ports, argv[1]);
835 get_external_id(port->port_cfg->key_external_ids,
836 port->port_cfg->value_external_ids,
837 port->port_cfg->n_external_ids,
838 "fake-bridge-", argc >= 3 ? argv[2] : NULL, output);
845 cmd_list_ports(int argc UNUSED, char *argv[],
846 const struct ovsrec_open_vswitch *ovs, struct ds *output)
848 struct vsctl_bridge *br;
849 struct shash_node *node;
850 struct vsctl_info info;
853 get_info(ovs, &info);
854 br = find_bridge(&info, argv[1]);
857 SHASH_FOR_EACH (node, &info.ports) {
858 struct vsctl_port *port = node->data;
860 if (strcmp(port->port_cfg->name, br->name) && br == port->bridge) {
861 svec_add(&ports, port->port_cfg->name);
864 output_sorted(&ports, output);
865 svec_destroy(&ports);
871 add_port(const struct ovsrec_open_vswitch *ovs,
872 const char *br_name, const char *port_name,
873 char *iface_names[], int n_ifaces)
875 struct vsctl_info info;
876 struct vsctl_bridge *bridge;
877 struct ovsrec_interface **ifaces;
878 struct ovsrec_port *port;
881 get_info(ovs, &info);
882 check_conflicts(&info, port_name,
883 xasprintf("cannot create a port named %s", port_name));
884 /* XXX need to check for conflicts on interfaces too */
885 bridge = find_bridge(&info, br_name);
887 ifaces = xmalloc(n_ifaces * sizeof *ifaces);
888 for (i = 0; i < n_ifaces; i++) {
889 ifaces[i] = ovsrec_interface_insert(txn_from_openvswitch(ovs));
890 ovsrec_interface_set_name(ifaces[i], iface_names[i]);
893 port = ovsrec_port_insert(txn_from_openvswitch(ovs));
894 ovsrec_port_set_name(port, port_name);
895 ovsrec_port_set_interfaces(port, ifaces, n_ifaces);
897 int64_t tag = bridge->vlan;
898 ovsrec_port_set_tag(port, &tag, 1);
901 bridge_insert_port((bridge->parent ? bridge->parent->br_cfg
902 : bridge->br_cfg), port);
908 cmd_add_port(int argc UNUSED, char *argv[],
909 const struct ovsrec_open_vswitch *ovs, struct ds *output UNUSED)
911 add_port(ovs, argv[1], argv[2], &argv[2], 1);
915 cmd_add_bond(int argc, char *argv[],
916 const struct ovsrec_open_vswitch *ovs, struct ds *output UNUSED)
918 add_port(ovs, argv[1], argv[2], &argv[3], argc - 3);
922 cmd_del_port(int argc, char *argv[],
923 const struct ovsrec_open_vswitch *ovs, struct ds *output UNUSED)
925 struct vsctl_info info;
927 get_info(ovs, &info);
929 struct vsctl_port *port = find_port(&info, argv[1]);
930 del_port(&info, port);
931 } else if (argc == 3) {
932 struct vsctl_bridge *bridge = find_bridge(&info, argv[1]);
933 struct vsctl_port *port = find_port(&info, argv[2]);
935 if (port->bridge == bridge) {
936 del_port(&info, port);
937 } else if (port->bridge->parent == bridge) {
938 ovs_fatal(0, "bridge %s does not have a port %s (although its "
939 "parent bridge %s does)",
940 argv[1], argv[2], bridge->parent->name);
942 ovs_fatal(0, "bridge %s does not have a port %s",
950 cmd_port_to_br(int argc UNUSED, char *argv[],
951 const struct ovsrec_open_vswitch *ovs, struct ds *output)
953 struct vsctl_port *port;
954 struct vsctl_info info;
956 get_info(ovs, &info);
957 port = find_port(&info, argv[1]);
958 ds_put_format(output, "%s\n", port->bridge->name);
963 cmd_port_set_external_id(int argc, char *argv[],
964 const struct ovsrec_open_vswitch *ovs,
965 struct ds *output UNUSED)
967 struct vsctl_info info;
968 struct vsctl_port *port;
969 char **keys, **values;
972 get_info(ovs, &info);
973 port = find_port(&info, argv[1]);
974 set_external_id(port->port_cfg->key_external_ids,
975 port->port_cfg->value_external_ids,
976 port->port_cfg->n_external_ids,
977 argv[2], argc >= 4 ? argv[3] : NULL,
979 ovsrec_port_set_external_ids(port->port_cfg, keys, values, n);
987 cmd_port_get_external_id(int argc, char *argv[],
988 const struct ovsrec_open_vswitch *ovs,
991 struct vsctl_info info;
992 struct vsctl_port *port;
994 get_info(ovs, &info);
995 port = find_port(&info, argv[1]);
996 get_external_id(port->port_cfg->key_external_ids,
997 port->port_cfg->value_external_ids,
998 port->port_cfg->n_external_ids,
999 "", argc >= 3 ? argv[2] : NULL, output);
1004 cmd_br_to_vlan(int argc UNUSED, char *argv[],
1005 const struct ovsrec_open_vswitch *ovs, struct ds *output)
1007 struct vsctl_bridge *bridge;
1008 struct vsctl_info info;
1010 get_info(ovs, &info);
1011 bridge = find_bridge(&info, argv[1]);
1012 ds_put_format(output, "%d\n", bridge->vlan);
1017 cmd_br_to_parent(int argc UNUSED, char *argv[],
1018 const struct ovsrec_open_vswitch *ovs, struct ds *output)
1020 struct vsctl_bridge *bridge;
1021 struct vsctl_info info;
1023 get_info(ovs, &info);
1024 bridge = find_bridge(&info, argv[1]);
1025 if (bridge->parent) {
1026 bridge = bridge->parent;
1028 ds_put_format(output, "%s\n", bridge->name);
1033 cmd_list_ifaces(int argc UNUSED, char *argv[],
1034 const struct ovsrec_open_vswitch *ovs, struct ds *output)
1036 struct vsctl_bridge *br;
1037 struct shash_node *node;
1038 struct vsctl_info info;
1041 get_info(ovs, &info);
1042 br = find_bridge(&info, argv[1]);
1045 SHASH_FOR_EACH (node, &info.ifaces) {
1046 struct vsctl_iface *iface = node->data;
1048 if (strcmp(iface->iface_cfg->name, br->name)
1049 && br == iface->port->bridge) {
1050 svec_add(&ifaces, iface->iface_cfg->name);
1053 output_sorted(&ifaces, output);
1054 svec_destroy(&ifaces);
1060 cmd_iface_to_br(int argc UNUSED, char *argv[],
1061 const struct ovsrec_open_vswitch *ovs, struct ds *output)
1063 struct vsctl_iface *iface;
1064 struct vsctl_info info;
1066 get_info(ovs, &info);
1067 iface = find_iface(&info, argv[1]);
1068 ds_put_format(output, "%s\n", iface->port->bridge->name);
1073 cmd_iface_set_external_id(int argc, char *argv[],
1074 const struct ovsrec_open_vswitch *ovs,
1075 struct ds *output UNUSED)
1077 struct vsctl_info info;
1078 struct vsctl_iface *iface;
1079 char **keys, **values;
1082 get_info(ovs, &info);
1083 iface = find_iface(&info, argv[1]);
1084 set_external_id(iface->iface_cfg->key_external_ids,
1085 iface->iface_cfg->value_external_ids,
1086 iface->iface_cfg->n_external_ids,
1087 argv[2], argc >= 4 ? argv[3] : NULL,
1088 &keys, &values, &n);
1089 ovsrec_interface_set_external_ids(iface->iface_cfg, keys, values, n);
1097 cmd_iface_get_external_id(int argc, char *argv[],
1098 const struct ovsrec_open_vswitch *ovs,
1101 struct vsctl_info info;
1102 struct vsctl_iface *iface;
1104 get_info(ovs, &info);
1105 iface = find_iface(&info, argv[1]);
1106 get_external_id(iface->iface_cfg->key_external_ids,
1107 iface->iface_cfg->value_external_ids,
1108 iface->iface_cfg->n_external_ids,
1109 "", argc >= 3 ? argv[2] : NULL, output);
1113 typedef void vsctl_handler_func(int argc, char *argv[],
1114 const struct ovsrec_open_vswitch *,
1117 struct vsctl_command {
1121 vsctl_handler_func *handler;
1124 static void run_vsctl_command(int argc, char *argv[],
1125 const struct ovsrec_open_vswitch *ovs,
1129 do_vsctl(int argc, char *argv[], struct ovsdb_idl *idl)
1131 struct ovsdb_idl_txn *txn;
1132 const struct ovsrec_open_vswitch *ovs;
1133 enum ovsdb_idl_txn_status status;
1138 ovs = ovsrec_open_vswitch_first(idl);
1140 /* XXX it would be more user-friendly to create a record ourselves
1141 * (while verifying that the table is empty before doing so). */
1142 ovs_fatal(0, "%s: database does not contain any Open vSwitch "
1143 "configuration", db);
1146 txn = ovsdb_idl_txn_create(idl);
1147 output = xmalloc(argc * sizeof *output);
1149 for (start = i = 0; i <= argc; i++) {
1150 if (i == argc || !strcmp(argv[i], "--")) {
1152 ds_init(&output[n_output]);
1153 run_vsctl_command(i - start, &argv[start], ovs,
1154 &output[n_output++]);
1160 while ((status = ovsdb_idl_txn_commit(txn)) == TXN_INCOMPLETE) {
1162 ovsdb_idl_wait(idl);
1163 ovsdb_idl_txn_wait(txn);
1166 ovsdb_idl_txn_destroy(txn);
1169 case TXN_INCOMPLETE:
1173 /* Should not happen--we never call ovsdb_idl_txn_abort(). */
1174 ovs_fatal(0, "transaction aborted");
1180 for (i = 0; i < n_output; i++) {
1181 ds_destroy(&output[i]);
1186 ovs_fatal(0, "transaction error");
1192 for (i = 0; i < n_output; i++) {
1193 struct ds *ds = &output[i];
1198 for (j = 0; j < ds->length; j++) {
1199 int c = ds->string[j];
1202 fputs("\\n", stdout);
1206 fputs("\\\\", stdout);
1215 fputs(ds_cstr(ds), stdout);
1221 static vsctl_handler_func *
1222 get_vsctl_handler(int argc, char *argv[])
1224 static const struct vsctl_command all_commands[] = {
1225 /* Bridge commands. */
1226 {"add-br", 1, 3, cmd_add_br},
1227 {"del-br", 1, 1, cmd_del_br},
1228 {"list-br", 0, 0, cmd_list_br},
1229 {"br-exists", 1, 1, cmd_br_exists},
1230 {"br-to-vlan", 1, 1, cmd_br_to_vlan},
1231 {"br-to-parent", 1, 1, cmd_br_to_parent},
1232 {"br-set-external-id", 2, 3, cmd_br_set_external_id},
1233 {"br-get-external-id", 1, 2, cmd_br_get_external_id},
1235 /* Port commands. */
1236 {"list-ports", 1, 1, cmd_list_ports},
1237 {"add-port", 2, 2, cmd_add_port},
1238 {"add-bond", 4, INT_MAX, cmd_add_bond},
1239 {"del-port", 1, 2, cmd_del_port},
1240 {"port-to-br", 1, 1, cmd_port_to_br},
1241 {"port-set-external-id", 2, 3, cmd_port_set_external_id},
1242 {"port-get-external-id", 1, 2, cmd_port_get_external_id},
1244 /* Interface commands. */
1245 {"list-ifaces", 1, 1, cmd_list_ifaces},
1246 {"iface-to-br", 1, 1, cmd_iface_to_br},
1247 {"iface-set-external-id", 2, 3, cmd_iface_set_external_id},
1248 {"iface-get-external-id", 1, 2, cmd_iface_get_external_id},
1251 const struct vsctl_command *p;
1254 for (p = all_commands; p < &all_commands[ARRAY_SIZE(all_commands)]; p++) {
1255 if (!strcmp(p->name, argv[0])) {
1256 int n_arg = argc - 1;
1257 if (n_arg < p->min_args) {
1258 ovs_fatal(0, "'%s' command requires at least %d arguments",
1259 p->name, p->min_args);
1260 } else if (n_arg > p->max_args) {
1261 ovs_fatal(0, "'%s' command takes at most %d arguments",
1262 p->name, p->max_args);
1269 ovs_fatal(0, "unknown command '%s'; use --help for help", argv[0]);
1273 check_vsctl_command(int argc, char *argv[])
1275 get_vsctl_handler(argc, argv);
1279 run_vsctl_command(int argc, char *argv[],
1280 const struct ovsrec_open_vswitch *ovs, struct ds *output)
1282 get_vsctl_handler(argc, argv)(argc, argv, ovs, output);