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 " br-set-external-id BRIDGE KEY VALUE"
203 " set KEY on BRIDGE to VALUE\n"
204 " br-set-external-id BRIDGE KEY"
205 " unset KEY on BRIDGE\n"
206 " br-get-external-id BRIDGE KEY"
207 " print value of KEY on BRIDGE\n"
208 " br-get-external-id BRIDGE"
209 " list key-value pairs on BRIDGE\n"
211 printf("\nPort commands:\n"
212 " list-ports BRIDGE "
213 "print the names of all the ports on BRIDGE\n"
214 " add-port BRIDGE PORT "
215 "add network device PORT to BRIDGE\n"
216 " add-bond BRIDGE PORT IFACE... "
217 "add new bonded port PORT in BRIDGE from IFACES\n"
218 " del-port [BRIDGE] PORT "
219 "delete PORT (which may be bonded) from BRIDGE\n"
221 "print name of bridge that contains PORT\n"
222 " port-set-external-id PORT KEY VALUE"
223 " set KEY on PORT to VALUE\n"
224 " port-set-external-id PORT KEY"
225 " unset KEY on PORT\n"
226 " port-get-external-id PORT KEY"
227 " print value of KEY on PORT\n"
228 " port-get-external-id PORT"
229 " list key-value pairs on PORT\n"
230 "A bond is considered to be a single port.\n"
232 printf("\nInterface commands (a bond consists of multiple interfaces):\n"
233 " list-ifaces BRIDGE "
234 "print the names of all the interfaces on BRIDGE\n"
235 " iface-to-br IFACE "
236 "print name of bridge that contains IFACE\n"
237 " iface-set-external-id IFACE KEY VALUE"
238 " set KEY on IFACE to VALUE\n"
239 " iface-set-external-id IFACE KEY"
240 " unset KEY on IFACE\n"
241 " iface-get-external-id IFACE KEY"
242 " print value of KEY on IFACE\n"
243 " iface-get-external-id IFACE"
244 " list key-value pairs on IFACE\n"
246 printf("\nOptions:\n"
248 "connect to DATABASE\n"
252 "print exactly one line of output per command\n",
255 printf("\nOther options:\n"
257 "display this help message\n"
259 "display version information\n");
268 def = xasprintf("unix:%s/ovsdb-server", ovs_rundir);
273 struct vsctl_bridge {
274 struct ovsrec_bridge *br_cfg;
276 struct vsctl_bridge *parent;
281 struct ovsrec_port *port_cfg;
282 struct vsctl_bridge *bridge;
286 struct ovsrec_interface *iface_cfg;
287 struct vsctl_port *port;
291 struct shash bridges;
296 static struct ovsdb_idl_txn *
297 txn_from_openvswitch(const struct ovsrec_open_vswitch *ovs)
299 return ovsdb_idl_txn_get(&ovs->header_);
302 static struct vsctl_bridge *
303 add_bridge(struct vsctl_info *b,
304 struct ovsrec_bridge *br_cfg, const char *name,
305 struct vsctl_bridge *parent, int vlan)
307 struct vsctl_bridge *br = xmalloc(sizeof *br);
309 br->name = xstrdup(name);
312 shash_add(&b->bridges, br->name, br);
317 port_is_fake_bridge(const struct ovsrec_port *port_cfg)
319 return (port_cfg->fake_bridge
321 && *port_cfg->tag >= 1 && *port_cfg->tag <= 4095);
324 static struct vsctl_bridge *
325 find_vlan_bridge(struct vsctl_info *info,
326 struct vsctl_bridge *parent, int vlan)
328 struct shash_node *node;
330 SHASH_FOR_EACH (node, &info->bridges) {
331 struct vsctl_bridge *br = node->data;
332 if (br->parent == parent && br->vlan == vlan) {
341 free_info(struct vsctl_info *info)
343 struct shash_node *node;
345 SHASH_FOR_EACH (node, &info->bridges) {
346 struct vsctl_bridge *bridge = node->data;
350 shash_destroy(&info->bridges);
352 SHASH_FOR_EACH (node, &info->ports) {
353 struct vsctl_port *port = node->data;
356 shash_destroy(&info->ports);
358 SHASH_FOR_EACH (node, &info->ifaces) {
359 struct vsctl_iface *iface = node->data;
362 shash_destroy(&info->ifaces);
366 get_info(const struct ovsrec_open_vswitch *ovs, struct vsctl_info *info)
368 struct shash bridges, ports;
371 shash_init(&info->bridges);
372 shash_init(&info->ports);
373 shash_init(&info->ifaces);
375 shash_init(&bridges);
377 for (i = 0; i < ovs->n_bridges; i++) {
378 struct ovsrec_bridge *br_cfg = ovs->bridges[i];
379 struct vsctl_bridge *br;
382 if (!shash_add_once(&bridges, br_cfg->name, NULL)) {
383 VLOG_WARN("%s: database contains duplicate bridge name",
387 br = add_bridge(info, br_cfg, br_cfg->name, NULL, 0);
392 for (j = 0; j < br_cfg->n_ports; j++) {
393 struct ovsrec_port *port_cfg = br_cfg->ports[j];
395 if (!shash_add_once(&ports, port_cfg->name, NULL)) {
396 VLOG_WARN("%s: database contains duplicate port name",
401 if (port_is_fake_bridge(port_cfg)
402 && shash_add_once(&bridges, port_cfg->name, NULL)) {
403 add_bridge(info, NULL, port_cfg->name, br, *port_cfg->tag);
407 shash_destroy(&bridges);
408 shash_destroy(&ports);
410 shash_init(&bridges);
412 for (i = 0; i < ovs->n_bridges; i++) {
413 struct ovsrec_bridge *br_cfg = ovs->bridges[i];
414 struct vsctl_bridge *br;
417 if (!shash_add_once(&bridges, br_cfg->name, NULL)) {
420 br = shash_find_data(&info->bridges, br_cfg->name);
421 for (j = 0; j < br_cfg->n_ports; j++) {
422 struct ovsrec_port *port_cfg = br_cfg->ports[j];
423 struct vsctl_port *port;
426 if (!shash_add_once(&ports, port_cfg->name, NULL)) {
430 if (port_is_fake_bridge(port_cfg)
431 && !shash_add_once(&bridges, port_cfg->name, NULL)) {
435 port = xmalloc(sizeof *port);
436 port->port_cfg = port_cfg;
438 && *port_cfg->tag >= 1 && *port_cfg->tag <= 4095) {
439 port->bridge = find_vlan_bridge(info, br, *port_cfg->tag);
446 shash_add(&info->ports, port_cfg->name, port);
448 for (k = 0; k < port_cfg->n_interfaces; k++) {
449 struct ovsrec_interface *iface_cfg = port_cfg->interfaces[k];
450 struct vsctl_iface *iface;
452 if (shash_find(&info->ifaces, iface_cfg->name)) {
453 VLOG_WARN("%s: database contains duplicate interface name",
458 iface = xmalloc(sizeof *iface);
459 iface->iface_cfg = iface_cfg;
461 shash_add(&info->ifaces, iface_cfg->name, iface);
465 shash_destroy(&bridges);
466 shash_destroy(&ports);
470 check_conflicts(struct vsctl_info *info, const char *name,
473 struct vsctl_iface *iface;
474 struct vsctl_port *port;
476 if (shash_find(&info->bridges, name)) {
477 ovs_fatal(0, "%s because a bridge named %s already exists", msg, name);
480 port = shash_find_data(&info->ports, name);
482 ovs_fatal(0, "%s because a port named %s already exists on bridge %s",
483 msg, name, port->bridge->name);
486 iface = shash_find_data(&info->ifaces, name);
488 ovs_fatal(0, "%s because an interface named %s already exists "
489 "on bridge %s", msg, name, iface->port->bridge->name);
495 static struct vsctl_bridge *
496 find_bridge(struct vsctl_info *info, const char *name)
498 struct vsctl_bridge *br = shash_find_data(&info->bridges, name);
500 ovs_fatal(0, "no bridge named %s", name);
505 static struct vsctl_port *
506 find_port(struct vsctl_info *info, const char *name)
508 struct vsctl_port *port = shash_find_data(&info->ports, name);
509 if (!port || !strcmp(name, port->bridge->name)) {
510 ovs_fatal(0, "no port named %s", name);
515 static struct vsctl_iface *
516 find_iface(struct vsctl_info *info, const char *name)
518 struct vsctl_iface *iface = shash_find_data(&info->ifaces, name);
519 if (!iface || !strcmp(name, iface->port->bridge->name)) {
520 ovs_fatal(0, "no interface named %s", name);
526 bridge_insert_port(struct ovsrec_bridge *br, struct ovsrec_port *port)
528 struct ovsrec_port **ports;
531 ports = xmalloc(sizeof *br->ports * (br->n_ports + 1));
532 for (i = 0; i < br->n_ports; i++) {
533 ports[i] = br->ports[i];
535 ports[br->n_ports] = port;
536 ovsrec_bridge_set_ports(br, ports, br->n_ports + 1);
541 bridge_delete_port(struct ovsrec_bridge *br, struct ovsrec_port *port)
543 struct ovsrec_port **ports;
546 ports = xmalloc(sizeof *br->ports * br->n_ports);
547 for (i = n = 0; i < br->n_ports; i++) {
548 if (br->ports[i] != port) {
549 ports[n++] = br->ports[i];
552 ovsrec_bridge_set_ports(br, ports, n);
557 ovs_insert_bridge(const struct ovsrec_open_vswitch *ovs,
558 struct ovsrec_bridge *bridge)
560 struct ovsrec_bridge **bridges;
563 bridges = xmalloc(sizeof *ovs->bridges * (ovs->n_bridges + 1));
564 for (i = 0; i < ovs->n_bridges; i++) {
565 bridges[i] = ovs->bridges[i];
567 bridges[ovs->n_bridges] = bridge;
568 ovsrec_open_vswitch_set_bridges(ovs, bridges, ovs->n_bridges + 1);
573 ovs_delete_bridge(const struct ovsrec_open_vswitch *ovs,
574 struct ovsrec_bridge *bridge)
576 struct ovsrec_bridge **bridges;
579 bridges = xmalloc(sizeof *ovs->bridges * ovs->n_bridges);
580 for (i = n = 0; i < ovs->n_bridges; i++) {
581 if (ovs->bridges[i] != bridge) {
582 bridges[n++] = ovs->bridges[i];
585 ovsrec_open_vswitch_set_bridges(ovs, bridges, n);
590 cmd_add_br(int argc, char *argv[], const struct ovsrec_open_vswitch *ovs,
591 struct ds *output UNUSED)
593 const char *br_name = argv[1];
594 struct vsctl_info info;
596 get_info(ovs, &info);
597 check_conflicts(&info, br_name,
598 xasprintf("cannot create a bridge named %s", br_name));
601 struct ovsrec_bridge *br;
602 struct ovsrec_port *port;
603 struct ovsrec_interface *iface;
605 iface = ovsrec_interface_insert(txn_from_openvswitch(ovs));
606 ovsrec_interface_set_name(iface, br_name);
608 port = ovsrec_port_insert(txn_from_openvswitch(ovs));
609 ovsrec_port_set_name(port, br_name);
610 ovsrec_port_set_interfaces(port, &iface, 1);
612 br = ovsrec_bridge_insert(txn_from_openvswitch(ovs));
613 ovsrec_bridge_set_name(br, br_name);
614 ovsrec_bridge_set_ports(br, &port, 1);
616 ovs_insert_bridge(ovs, br);
617 } else if (argc == 3) {
618 ovs_fatal(0, "'%s' comamnd takes exactly 1 or 3 arguments", argv[0]);
619 } else if (argc == 4) {
620 const char *parent_name = argv[2];
621 int vlan = atoi(argv[3]);
622 struct ovsrec_bridge *br;
623 struct vsctl_bridge *parent;
624 struct ovsrec_port *port;
625 struct ovsrec_interface *iface;
628 if (vlan < 1 || vlan > 4095) {
629 ovs_fatal(0, "%s: vlan must be between 1 and 4095", argv[0]);
632 parent = shash_find_data(&info.bridges, parent_name);
633 if (parent && parent->vlan) {
634 ovs_fatal(0, "cannot create brdige with fake bridge as parent");
637 ovs_fatal(0, "parent bridge %s does not exist", parent_name);
641 iface = ovsrec_interface_insert(txn_from_openvswitch(ovs));
642 ovsrec_interface_set_name(iface, br_name);
643 ovsrec_interface_set_type(iface, "internal");
645 port = ovsrec_port_insert(txn_from_openvswitch(ovs));
646 ovsrec_port_set_name(port, br_name);
647 ovsrec_port_set_interfaces(port, &iface, 1);
648 ovsrec_port_set_fake_bridge(port, true);
649 ovsrec_port_set_tag(port, &tag, 1);
651 bridge_insert_port(br, port);
660 del_port(struct vsctl_info *info, struct vsctl_port *port)
662 struct shash_node *node;
664 SHASH_FOR_EACH (node, &info->ifaces) {
665 struct vsctl_iface *iface = node->data;
666 if (iface->port == port) {
667 ovsrec_interface_delete(iface->iface_cfg);
670 ovsrec_port_delete(port->port_cfg);
672 bridge_delete_port((port->bridge->parent
673 ? port->bridge->parent->br_cfg
674 : port->bridge->br_cfg), port->port_cfg);
678 cmd_del_br(int argc UNUSED, char *argv[],
679 const struct ovsrec_open_vswitch *ovs, struct ds *output UNUSED)
681 struct shash_node *node;
682 struct vsctl_info info;
683 struct vsctl_bridge *bridge;
685 get_info(ovs, &info);
686 bridge = find_bridge(&info, argv[1]);
687 SHASH_FOR_EACH (node, &info.ports) {
688 struct vsctl_port *port = node->data;
689 if (port->bridge == bridge
690 || !strcmp(port->port_cfg->name, bridge->name)) {
691 del_port(&info, port);
694 if (bridge->br_cfg) {
695 ovsrec_bridge_delete(bridge->br_cfg);
696 ovs_delete_bridge(ovs, bridge->br_cfg);
702 output_sorted(struct svec *svec, struct ds *output)
708 SVEC_FOR_EACH (i, name, svec) {
709 ds_put_format(output, "%s\n", name);
714 cmd_list_br(int argc UNUSED, char *argv[] UNUSED,
715 const struct ovsrec_open_vswitch *ovs, struct ds *output)
717 struct shash_node *node;
718 struct vsctl_info info;
721 get_info(ovs, &info);
724 SHASH_FOR_EACH (node, &info.bridges) {
725 struct vsctl_bridge *br = node->data;
726 svec_add(&bridges, br->name);
728 output_sorted(&bridges, output);
729 svec_destroy(&bridges);
735 cmd_br_exists(int argc UNUSED, char *argv[],
736 const struct ovsrec_open_vswitch *ovs, struct ds *output UNUSED)
738 struct vsctl_info info;
740 get_info(ovs, &info);
741 if (!shash_find_data(&info.bridges, argv[1])) {
747 /* Returns true if 'b_prefix' (of length 'b_prefix_len') concatenated with 'b'
748 * equals 'a', false otherwise. */
750 key_matches(const char *a,
751 const char *b_prefix, size_t b_prefix_len, const char *b)
753 return !strncmp(a, b_prefix, b_prefix_len) && !strcmp(a + b_prefix_len, b);
757 set_external_id(char **old_keys, char **old_values, size_t old_n,
758 char *key, char *value,
759 char ***new_keysp, char ***new_valuesp, size_t *new_np)
766 new_keys = xmalloc(sizeof *new_keys * (old_n + 1));
767 new_values = xmalloc(sizeof *new_values * (old_n + 1));
769 for (i = 0; i < old_n; i++) {
770 if (strcmp(key, old_keys[i])) {
771 new_keys[new_n] = old_keys[i];
772 new_values[new_n] = old_values[i];
777 new_keys[new_n] = key;
778 new_values[new_n] = value;
781 *new_keysp = new_keys;
782 *new_valuesp = new_values;
787 cmd_br_set_external_id(int argc, char *argv[],
788 const struct ovsrec_open_vswitch *ovs,
789 struct ds *output UNUSED)
791 struct vsctl_info info;
792 struct vsctl_bridge *bridge;
793 char **keys, **values;
796 get_info(ovs, &info);
797 bridge = find_bridge(&info, argv[1]);
798 if (bridge->br_cfg) {
799 set_external_id(bridge->br_cfg->key_external_ids,
800 bridge->br_cfg->value_external_ids,
801 bridge->br_cfg->n_external_ids,
802 argv[2], argc >= 4 ? argv[3] : NULL,
804 ovsrec_bridge_set_external_ids(bridge->br_cfg, keys, values, n);
806 char *key = xasprintf("fake-bridge-%s", argv[2]);
807 struct vsctl_port *port = shash_find_data(&info.ports, argv[1]);
808 set_external_id(port->port_cfg->key_external_ids,
809 port->port_cfg->value_external_ids,
810 port->port_cfg->n_external_ids,
811 key, argc >= 4 ? argv[3] : NULL,
813 ovsrec_port_set_external_ids(port->port_cfg, keys, values, n);
823 get_external_id(char **keys, char **values, size_t n,
824 const char *prefix, const char *key,
827 size_t prefix_len = strlen(prefix);
832 for (i = 0; i < n; i++) {
833 if (!key && !strncmp(keys[i], prefix, prefix_len)) {
834 svec_add_nocopy(&svec, xasprintf("%s=%s",
835 keys[i] + prefix_len, values[i]));
836 } else if (key_matches(keys[i], prefix, prefix_len, key)) {
837 svec_add(&svec, values[i]);
841 output_sorted(&svec, output);
846 cmd_br_get_external_id(int argc, char *argv[],
847 const struct ovsrec_open_vswitch *ovs,
850 struct vsctl_info info;
851 struct vsctl_bridge *bridge;
853 get_info(ovs, &info);
854 bridge = find_bridge(&info, argv[1]);
855 if (bridge->br_cfg) {
856 get_external_id(bridge->br_cfg->key_external_ids,
857 bridge->br_cfg->value_external_ids,
858 bridge->br_cfg->n_external_ids,
859 "", argc >= 3 ? argv[2] : NULL, output);
861 struct vsctl_port *port = shash_find_data(&info.ports, argv[1]);
862 get_external_id(port->port_cfg->key_external_ids,
863 port->port_cfg->value_external_ids,
864 port->port_cfg->n_external_ids,
865 "fake-bridge-", argc >= 3 ? argv[2] : NULL, output);
872 cmd_list_ports(int argc UNUSED, char *argv[],
873 const struct ovsrec_open_vswitch *ovs, struct ds *output)
875 struct vsctl_bridge *br;
876 struct shash_node *node;
877 struct vsctl_info info;
880 get_info(ovs, &info);
881 br = find_bridge(&info, argv[1]);
884 SHASH_FOR_EACH (node, &info.ports) {
885 struct vsctl_port *port = node->data;
887 if (strcmp(port->port_cfg->name, br->name) && br == port->bridge) {
888 svec_add(&ports, port->port_cfg->name);
891 output_sorted(&ports, output);
892 svec_destroy(&ports);
898 add_port(const struct ovsrec_open_vswitch *ovs,
899 const char *br_name, const char *port_name,
900 char *iface_names[], int n_ifaces)
902 struct vsctl_info info;
903 struct vsctl_bridge *bridge;
904 struct ovsrec_interface **ifaces;
905 struct ovsrec_port *port;
908 get_info(ovs, &info);
909 check_conflicts(&info, port_name,
910 xasprintf("cannot create a port named %s", port_name));
911 /* XXX need to check for conflicts on interfaces too */
912 bridge = find_bridge(&info, br_name);
914 ifaces = xmalloc(n_ifaces * sizeof *ifaces);
915 for (i = 0; i < n_ifaces; i++) {
916 ifaces[i] = ovsrec_interface_insert(txn_from_openvswitch(ovs));
917 ovsrec_interface_set_name(ifaces[i], iface_names[i]);
920 port = ovsrec_port_insert(txn_from_openvswitch(ovs));
921 ovsrec_port_set_name(port, port_name);
922 ovsrec_port_set_interfaces(port, ifaces, n_ifaces);
926 int64_t tag = bridge->vlan;
927 ovsrec_port_set_tag(port, &tag, 1);
930 bridge_insert_port((bridge->parent ? bridge->parent->br_cfg
931 : bridge->br_cfg), port);
937 cmd_add_port(int argc UNUSED, char *argv[],
938 const struct ovsrec_open_vswitch *ovs, struct ds *output UNUSED)
940 add_port(ovs, argv[1], argv[2], &argv[2], 1);
944 cmd_add_bond(int argc, char *argv[],
945 const struct ovsrec_open_vswitch *ovs, struct ds *output UNUSED)
947 add_port(ovs, argv[1], argv[2], &argv[3], argc - 3);
951 cmd_del_port(int argc, char *argv[],
952 const struct ovsrec_open_vswitch *ovs, struct ds *output UNUSED)
954 struct vsctl_info info;
956 get_info(ovs, &info);
958 struct vsctl_port *port = find_port(&info, argv[1]);
959 del_port(&info, port);
960 } else if (argc == 3) {
961 struct vsctl_bridge *bridge = find_bridge(&info, argv[1]);
962 struct vsctl_port *port = find_port(&info, argv[2]);
964 if (port->bridge == bridge) {
965 del_port(&info, port);
966 } else if (port->bridge->parent == bridge) {
967 ovs_fatal(0, "bridge %s does not have a port %s (although its "
968 "parent bridge %s does)",
969 argv[1], argv[2], bridge->parent->name);
971 ovs_fatal(0, "bridge %s does not have a port %s",
979 cmd_port_to_br(int argc UNUSED, char *argv[],
980 const struct ovsrec_open_vswitch *ovs, struct ds *output)
982 struct vsctl_port *port;
983 struct vsctl_info info;
985 get_info(ovs, &info);
986 port = find_port(&info, argv[1]);
987 ds_put_format(output, "%s\n", port->bridge->name);
992 cmd_port_set_external_id(int argc, char *argv[],
993 const struct ovsrec_open_vswitch *ovs,
994 struct ds *output UNUSED)
996 struct vsctl_info info;
997 struct vsctl_port *port;
998 char **keys, **values;
1001 get_info(ovs, &info);
1002 port = find_port(&info, argv[1]);
1003 set_external_id(port->port_cfg->key_external_ids,
1004 port->port_cfg->value_external_ids,
1005 port->port_cfg->n_external_ids,
1006 argv[2], argc >= 4 ? argv[3] : NULL,
1007 &keys, &values, &n);
1008 ovsrec_port_set_external_ids(port->port_cfg, keys, values, n);
1016 cmd_port_get_external_id(int argc, char *argv[],
1017 const struct ovsrec_open_vswitch *ovs,
1020 struct vsctl_info info;
1021 struct vsctl_port *port;
1023 get_info(ovs, &info);
1024 port = find_port(&info, argv[1]);
1025 get_external_id(port->port_cfg->key_external_ids,
1026 port->port_cfg->value_external_ids,
1027 port->port_cfg->n_external_ids,
1028 "", argc >= 3 ? argv[2] : NULL, output);
1033 cmd_br_to_vlan(int argc UNUSED, char *argv[],
1034 const struct ovsrec_open_vswitch *ovs, struct ds *output)
1036 struct vsctl_bridge *bridge;
1037 struct vsctl_info info;
1039 get_info(ovs, &info);
1040 bridge = find_bridge(&info, argv[1]);
1041 ds_put_format(output, "%d\n", bridge->vlan);
1046 cmd_br_to_parent(int argc UNUSED, char *argv[],
1047 const struct ovsrec_open_vswitch *ovs, struct ds *output)
1049 struct vsctl_bridge *bridge;
1050 struct vsctl_info info;
1052 get_info(ovs, &info);
1053 bridge = find_bridge(&info, argv[1]);
1054 if (bridge->parent) {
1055 bridge = bridge->parent;
1057 ds_put_format(output, "%s\n", bridge->name);
1062 cmd_list_ifaces(int argc UNUSED, char *argv[],
1063 const struct ovsrec_open_vswitch *ovs, struct ds *output)
1065 struct vsctl_bridge *br;
1066 struct shash_node *node;
1067 struct vsctl_info info;
1070 get_info(ovs, &info);
1071 br = find_bridge(&info, argv[1]);
1074 SHASH_FOR_EACH (node, &info.ifaces) {
1075 struct vsctl_iface *iface = node->data;
1077 if (strcmp(iface->iface_cfg->name, br->name)
1078 && br == iface->port->bridge) {
1079 svec_add(&ifaces, iface->iface_cfg->name);
1082 output_sorted(&ifaces, output);
1083 svec_destroy(&ifaces);
1089 cmd_iface_to_br(int argc UNUSED, char *argv[],
1090 const struct ovsrec_open_vswitch *ovs, struct ds *output)
1092 struct vsctl_iface *iface;
1093 struct vsctl_info info;
1095 get_info(ovs, &info);
1096 iface = find_iface(&info, argv[1]);
1097 ds_put_format(output, "%s\n", iface->port->bridge->name);
1102 cmd_iface_set_external_id(int argc, char *argv[],
1103 const struct ovsrec_open_vswitch *ovs,
1104 struct ds *output UNUSED)
1106 struct vsctl_info info;
1107 struct vsctl_iface *iface;
1108 char **keys, **values;
1111 get_info(ovs, &info);
1112 iface = find_iface(&info, argv[1]);
1113 set_external_id(iface->iface_cfg->key_external_ids,
1114 iface->iface_cfg->value_external_ids,
1115 iface->iface_cfg->n_external_ids,
1116 argv[2], argc >= 4 ? argv[3] : NULL,
1117 &keys, &values, &n);
1118 ovsrec_interface_set_external_ids(iface->iface_cfg, keys, values, n);
1126 cmd_iface_get_external_id(int argc, char *argv[],
1127 const struct ovsrec_open_vswitch *ovs,
1130 struct vsctl_info info;
1131 struct vsctl_iface *iface;
1133 get_info(ovs, &info);
1134 iface = find_iface(&info, argv[1]);
1135 get_external_id(iface->iface_cfg->key_external_ids,
1136 iface->iface_cfg->value_external_ids,
1137 iface->iface_cfg->n_external_ids,
1138 "", argc >= 3 ? argv[2] : NULL, output);
1142 typedef void vsctl_handler_func(int argc, char *argv[],
1143 const struct ovsrec_open_vswitch *,
1146 struct vsctl_command {
1150 vsctl_handler_func *handler;
1153 static void run_vsctl_command(int argc, char *argv[],
1154 const struct ovsrec_open_vswitch *ovs,
1158 do_vsctl(int argc, char *argv[], struct ovsdb_idl *idl)
1160 struct ovsdb_idl_txn *txn;
1161 const struct ovsrec_open_vswitch *ovs;
1162 enum ovsdb_idl_txn_status status;
1167 ovs = ovsrec_open_vswitch_first(idl);
1169 /* XXX it would be more user-friendly to create a record ourselves
1170 * (while verifying that the table is empty before doing so). */
1171 ovs_fatal(0, "%s: database does not contain any Open vSwitch "
1172 "configuration", db);
1175 txn = ovsdb_idl_txn_create(idl);
1176 output = xmalloc(argc * sizeof *output);
1178 for (start = i = 0; i <= argc; i++) {
1179 if (i == argc || !strcmp(argv[i], "--")) {
1181 ds_init(&output[n_output]);
1182 run_vsctl_command(i - start, &argv[start], ovs,
1183 &output[n_output++]);
1189 while ((status = ovsdb_idl_txn_commit(txn)) == TXN_INCOMPLETE) {
1191 ovsdb_idl_wait(idl);
1192 ovsdb_idl_txn_wait(txn);
1195 ovsdb_idl_txn_destroy(txn);
1198 case TXN_INCOMPLETE:
1202 /* Should not happen--we never call ovsdb_idl_txn_abort(). */
1203 ovs_fatal(0, "transaction aborted");
1209 for (i = 0; i < n_output; i++) {
1210 ds_destroy(&output[i]);
1215 ovs_fatal(0, "transaction error");
1221 for (i = 0; i < n_output; i++) {
1222 struct ds *ds = &output[i];
1227 for (j = 0; j < ds->length; j++) {
1228 int c = ds->string[j];
1231 fputs("\\n", stdout);
1235 fputs("\\\\", stdout);
1244 fputs(ds_cstr(ds), stdout);
1250 static vsctl_handler_func *
1251 get_vsctl_handler(int argc, char *argv[])
1253 static const struct vsctl_command all_commands[] = {
1254 /* Bridge commands. */
1255 {"add-br", 1, 3, cmd_add_br},
1256 {"del-br", 1, 1, cmd_del_br},
1257 {"list-br", 0, 0, cmd_list_br},
1258 {"br-exists", 1, 1, cmd_br_exists},
1259 {"br-to-vlan", 1, 1, cmd_br_to_vlan},
1260 {"br-to-parent", 1, 1, cmd_br_to_parent},
1261 {"br-set-external-id", 2, 3, cmd_br_set_external_id},
1262 {"br-get-external-id", 1, 2, cmd_br_get_external_id},
1264 /* Port commands. */
1265 {"list-ports", 1, 1, cmd_list_ports},
1266 {"add-port", 2, 2, cmd_add_port},
1267 {"add-bond", 4, INT_MAX, cmd_add_bond},
1268 {"del-port", 1, 2, cmd_del_port},
1269 {"port-to-br", 1, 1, cmd_port_to_br},
1270 {"port-set-external-id", 2, 3, cmd_port_set_external_id},
1271 {"port-get-external-id", 1, 2, cmd_port_get_external_id},
1273 /* Interface commands. */
1274 {"list-ifaces", 1, 1, cmd_list_ifaces},
1275 {"iface-to-br", 1, 1, cmd_iface_to_br},
1276 {"iface-set-external-id", 2, 3, cmd_iface_set_external_id},
1277 {"iface-get-external-id", 1, 2, cmd_iface_get_external_id},
1280 const struct vsctl_command *p;
1283 for (p = all_commands; p < &all_commands[ARRAY_SIZE(all_commands)]; p++) {
1284 if (!strcmp(p->name, argv[0])) {
1285 int n_arg = argc - 1;
1286 if (n_arg < p->min_args) {
1287 ovs_fatal(0, "'%s' command requires at least %d arguments",
1288 p->name, p->min_args);
1289 } else if (n_arg > p->max_args) {
1290 ovs_fatal(0, "'%s' command takes at most %d arguments",
1291 p->name, p->max_args);
1298 ovs_fatal(0, "unknown command '%s'; use --help for help", argv[0]);
1302 check_vsctl_command(int argc, char *argv[])
1304 get_vsctl_handler(argc, argv);
1308 run_vsctl_command(int argc, char *argv[],
1309 const struct ovsrec_open_vswitch *ovs, struct ds *output)
1311 get_vsctl_handler(argc, argv)(argc, argv, ovs, output);