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_context {
276 const struct ovsrec_open_vswitch *ovs;
278 struct shash options;
281 struct vsctl_bridge {
282 struct ovsrec_bridge *br_cfg;
284 struct vsctl_bridge *parent;
289 struct ovsrec_port *port_cfg;
290 struct vsctl_bridge *bridge;
294 struct ovsrec_interface *iface_cfg;
295 struct vsctl_port *port;
299 struct shash bridges;
304 static struct ovsdb_idl_txn *
305 txn_from_openvswitch(const struct ovsrec_open_vswitch *ovs)
307 return ovsdb_idl_txn_get(&ovs->header_);
310 static struct vsctl_bridge *
311 add_bridge(struct vsctl_info *b,
312 struct ovsrec_bridge *br_cfg, const char *name,
313 struct vsctl_bridge *parent, int vlan)
315 struct vsctl_bridge *br = xmalloc(sizeof *br);
317 br->name = xstrdup(name);
320 shash_add(&b->bridges, br->name, br);
325 port_is_fake_bridge(const struct ovsrec_port *port_cfg)
327 return (port_cfg->fake_bridge
329 && *port_cfg->tag >= 1 && *port_cfg->tag <= 4095);
332 static struct vsctl_bridge *
333 find_vlan_bridge(struct vsctl_info *info,
334 struct vsctl_bridge *parent, int vlan)
336 struct shash_node *node;
338 SHASH_FOR_EACH (node, &info->bridges) {
339 struct vsctl_bridge *br = node->data;
340 if (br->parent == parent && br->vlan == vlan) {
349 free_info(struct vsctl_info *info)
351 struct shash_node *node;
353 SHASH_FOR_EACH (node, &info->bridges) {
354 struct vsctl_bridge *bridge = node->data;
358 shash_destroy(&info->bridges);
360 SHASH_FOR_EACH (node, &info->ports) {
361 struct vsctl_port *port = node->data;
364 shash_destroy(&info->ports);
366 SHASH_FOR_EACH (node, &info->ifaces) {
367 struct vsctl_iface *iface = node->data;
370 shash_destroy(&info->ifaces);
374 get_info(const struct ovsrec_open_vswitch *ovs, struct vsctl_info *info)
376 struct shash bridges, ports;
379 shash_init(&info->bridges);
380 shash_init(&info->ports);
381 shash_init(&info->ifaces);
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)) {
391 VLOG_WARN("%s: database contains duplicate bridge name",
395 br = add_bridge(info, br_cfg, br_cfg->name, NULL, 0);
400 for (j = 0; j < br_cfg->n_ports; j++) {
401 struct ovsrec_port *port_cfg = br_cfg->ports[j];
403 if (!shash_add_once(&ports, port_cfg->name, NULL)) {
404 VLOG_WARN("%s: database contains duplicate port name",
409 if (port_is_fake_bridge(port_cfg)
410 && shash_add_once(&bridges, port_cfg->name, NULL)) {
411 add_bridge(info, NULL, port_cfg->name, br, *port_cfg->tag);
415 shash_destroy(&bridges);
416 shash_destroy(&ports);
418 shash_init(&bridges);
420 for (i = 0; i < ovs->n_bridges; i++) {
421 struct ovsrec_bridge *br_cfg = ovs->bridges[i];
422 struct vsctl_bridge *br;
425 if (!shash_add_once(&bridges, br_cfg->name, NULL)) {
428 br = shash_find_data(&info->bridges, br_cfg->name);
429 for (j = 0; j < br_cfg->n_ports; j++) {
430 struct ovsrec_port *port_cfg = br_cfg->ports[j];
431 struct vsctl_port *port;
434 if (!shash_add_once(&ports, port_cfg->name, NULL)) {
438 if (port_is_fake_bridge(port_cfg)
439 && !shash_add_once(&bridges, port_cfg->name, NULL)) {
443 port = xmalloc(sizeof *port);
444 port->port_cfg = port_cfg;
446 && *port_cfg->tag >= 1 && *port_cfg->tag <= 4095) {
447 port->bridge = find_vlan_bridge(info, br, *port_cfg->tag);
454 shash_add(&info->ports, port_cfg->name, port);
456 for (k = 0; k < port_cfg->n_interfaces; k++) {
457 struct ovsrec_interface *iface_cfg = port_cfg->interfaces[k];
458 struct vsctl_iface *iface;
460 if (shash_find(&info->ifaces, iface_cfg->name)) {
461 VLOG_WARN("%s: database contains duplicate interface name",
466 iface = xmalloc(sizeof *iface);
467 iface->iface_cfg = iface_cfg;
469 shash_add(&info->ifaces, iface_cfg->name, iface);
473 shash_destroy(&bridges);
474 shash_destroy(&ports);
478 check_conflicts(struct vsctl_info *info, const char *name,
481 struct vsctl_iface *iface;
482 struct vsctl_port *port;
484 if (shash_find(&info->bridges, name)) {
485 ovs_fatal(0, "%s because a bridge named %s already exists", msg, name);
488 port = shash_find_data(&info->ports, name);
490 ovs_fatal(0, "%s because a port named %s already exists on bridge %s",
491 msg, name, port->bridge->name);
494 iface = shash_find_data(&info->ifaces, name);
496 ovs_fatal(0, "%s because an interface named %s already exists "
497 "on bridge %s", msg, name, iface->port->bridge->name);
503 static struct vsctl_bridge *
504 find_bridge(struct vsctl_info *info, const char *name)
506 struct vsctl_bridge *br = shash_find_data(&info->bridges, name);
508 ovs_fatal(0, "no bridge named %s", name);
513 static struct vsctl_port *
514 find_port(struct vsctl_info *info, const char *name)
516 struct vsctl_port *port = shash_find_data(&info->ports, name);
517 if (!port || !strcmp(name, port->bridge->name)) {
518 ovs_fatal(0, "no port named %s", name);
523 static struct vsctl_iface *
524 find_iface(struct vsctl_info *info, const char *name)
526 struct vsctl_iface *iface = shash_find_data(&info->ifaces, name);
527 if (!iface || !strcmp(name, iface->port->bridge->name)) {
528 ovs_fatal(0, "no interface named %s", name);
534 bridge_insert_port(struct ovsrec_bridge *br, struct ovsrec_port *port)
536 struct ovsrec_port **ports;
539 ports = xmalloc(sizeof *br->ports * (br->n_ports + 1));
540 for (i = 0; i < br->n_ports; i++) {
541 ports[i] = br->ports[i];
543 ports[br->n_ports] = port;
544 ovsrec_bridge_set_ports(br, ports, br->n_ports + 1);
549 bridge_delete_port(struct ovsrec_bridge *br, struct ovsrec_port *port)
551 struct ovsrec_port **ports;
554 ports = xmalloc(sizeof *br->ports * br->n_ports);
555 for (i = n = 0; i < br->n_ports; i++) {
556 if (br->ports[i] != port) {
557 ports[n++] = br->ports[i];
560 ovsrec_bridge_set_ports(br, ports, n);
565 ovs_insert_bridge(const struct ovsrec_open_vswitch *ovs,
566 struct ovsrec_bridge *bridge)
568 struct ovsrec_bridge **bridges;
571 bridges = xmalloc(sizeof *ovs->bridges * (ovs->n_bridges + 1));
572 for (i = 0; i < ovs->n_bridges; i++) {
573 bridges[i] = ovs->bridges[i];
575 bridges[ovs->n_bridges] = bridge;
576 ovsrec_open_vswitch_set_bridges(ovs, bridges, ovs->n_bridges + 1);
581 ovs_delete_bridge(const struct ovsrec_open_vswitch *ovs,
582 struct ovsrec_bridge *bridge)
584 struct ovsrec_bridge **bridges;
587 bridges = xmalloc(sizeof *ovs->bridges * ovs->n_bridges);
588 for (i = n = 0; i < ovs->n_bridges; i++) {
589 if (ovs->bridges[i] != bridge) {
590 bridges[n++] = ovs->bridges[i];
593 ovsrec_open_vswitch_set_bridges(ovs, bridges, n);
598 cmd_add_br(struct vsctl_context *ctx)
600 const char *br_name = ctx->argv[1];
601 struct vsctl_info info;
603 get_info(ctx->ovs, &info);
604 check_conflicts(&info, br_name,
605 xasprintf("cannot create a bridge named %s", br_name));
607 if (ctx->argc == 2) {
608 struct ovsrec_bridge *br;
609 struct ovsrec_port *port;
610 struct ovsrec_interface *iface;
612 iface = ovsrec_interface_insert(txn_from_openvswitch(ctx->ovs));
613 ovsrec_interface_set_name(iface, br_name);
615 port = ovsrec_port_insert(txn_from_openvswitch(ctx->ovs));
616 ovsrec_port_set_name(port, br_name);
617 ovsrec_port_set_interfaces(port, &iface, 1);
619 br = ovsrec_bridge_insert(txn_from_openvswitch(ctx->ovs));
620 ovsrec_bridge_set_name(br, br_name);
621 ovsrec_bridge_set_ports(br, &port, 1);
623 ovs_insert_bridge(ctx->ovs, br);
624 } else if (ctx->argc == 3) {
625 ovs_fatal(0, "'%s' comamnd takes exactly 1 or 3 arguments", ctx->argv[0]);
626 } else if (ctx->argc == 4) {
627 const char *parent_name = ctx->argv[2];
628 int vlan = atoi(ctx->argv[3]);
629 struct ovsrec_bridge *br;
630 struct vsctl_bridge *parent;
631 struct ovsrec_port *port;
632 struct ovsrec_interface *iface;
635 if (vlan < 1 || vlan > 4095) {
636 ovs_fatal(0, "%s: vlan must be between 1 and 4095", ctx->argv[0]);
639 parent = shash_find_data(&info.bridges, parent_name);
640 if (parent && parent->vlan) {
641 ovs_fatal(0, "cannot create brdige with fake bridge as parent");
644 ovs_fatal(0, "parent bridge %s does not exist", parent_name);
648 iface = ovsrec_interface_insert(txn_from_openvswitch(ctx->ovs));
649 ovsrec_interface_set_name(iface, br_name);
650 ovsrec_interface_set_type(iface, "internal");
652 port = ovsrec_port_insert(txn_from_openvswitch(ctx->ovs));
653 ovsrec_port_set_name(port, br_name);
654 ovsrec_port_set_interfaces(port, &iface, 1);
655 ovsrec_port_set_fake_bridge(port, true);
656 ovsrec_port_set_tag(port, &tag, 1);
658 bridge_insert_port(br, port);
667 del_port(struct vsctl_info *info, struct vsctl_port *port)
669 struct shash_node *node;
671 SHASH_FOR_EACH (node, &info->ifaces) {
672 struct vsctl_iface *iface = node->data;
673 if (iface->port == port) {
674 ovsrec_interface_delete(iface->iface_cfg);
677 ovsrec_port_delete(port->port_cfg);
679 bridge_delete_port((port->bridge->parent
680 ? port->bridge->parent->br_cfg
681 : port->bridge->br_cfg), port->port_cfg);
685 cmd_del_br(struct vsctl_context *ctx)
687 struct shash_node *node;
688 struct vsctl_info info;
689 struct vsctl_bridge *bridge;
691 get_info(ctx->ovs, &info);
692 bridge = find_bridge(&info, ctx->argv[1]);
693 SHASH_FOR_EACH (node, &info.ports) {
694 struct vsctl_port *port = node->data;
695 if (port->bridge == bridge
696 || !strcmp(port->port_cfg->name, bridge->name)) {
697 del_port(&info, port);
700 if (bridge->br_cfg) {
701 ovsrec_bridge_delete(bridge->br_cfg);
702 ovs_delete_bridge(ctx->ovs, bridge->br_cfg);
708 output_sorted(struct svec *svec, struct ds *output)
714 SVEC_FOR_EACH (i, name, svec) {
715 ds_put_format(output, "%s\n", name);
720 cmd_list_br(struct vsctl_context *ctx)
722 struct shash_node *node;
723 struct vsctl_info info;
726 get_info(ctx->ovs, &info);
729 SHASH_FOR_EACH (node, &info.bridges) {
730 struct vsctl_bridge *br = node->data;
731 svec_add(&bridges, br->name);
733 output_sorted(&bridges, &ctx->output);
734 svec_destroy(&bridges);
740 cmd_br_exists(struct vsctl_context *ctx)
742 struct vsctl_info info;
744 get_info(ctx->ovs, &info);
745 if (!shash_find_data(&info.bridges, ctx->argv[1])) {
751 /* Returns true if 'b_prefix' (of length 'b_prefix_len') concatenated with 'b'
752 * equals 'a', false otherwise. */
754 key_matches(const char *a,
755 const char *b_prefix, size_t b_prefix_len, const char *b)
757 return !strncmp(a, b_prefix, b_prefix_len) && !strcmp(a + b_prefix_len, b);
761 set_external_id(char **old_keys, char **old_values, size_t old_n,
762 char *key, char *value,
763 char ***new_keysp, char ***new_valuesp, size_t *new_np)
770 new_keys = xmalloc(sizeof *new_keys * (old_n + 1));
771 new_values = xmalloc(sizeof *new_values * (old_n + 1));
773 for (i = 0; i < old_n; i++) {
774 if (strcmp(key, old_keys[i])) {
775 new_keys[new_n] = old_keys[i];
776 new_values[new_n] = old_values[i];
781 new_keys[new_n] = key;
782 new_values[new_n] = value;
785 *new_keysp = new_keys;
786 *new_valuesp = new_values;
791 cmd_br_set_external_id(struct vsctl_context *ctx)
793 struct vsctl_info info;
794 struct vsctl_bridge *bridge;
795 char **keys, **values;
798 get_info(ctx->ovs, &info);
799 bridge = find_bridge(&info, ctx->argv[1]);
800 if (bridge->br_cfg) {
801 set_external_id(bridge->br_cfg->key_external_ids,
802 bridge->br_cfg->value_external_ids,
803 bridge->br_cfg->n_external_ids,
804 ctx->argv[2], ctx->argc >= 4 ? ctx->argv[3] : NULL,
806 ovsrec_bridge_set_external_ids(bridge->br_cfg, keys, values, n);
808 char *key = xasprintf("fake-bridge-%s", ctx->argv[2]);
809 struct vsctl_port *port = shash_find_data(&info.ports, ctx->argv[1]);
810 set_external_id(port->port_cfg->key_external_ids,
811 port->port_cfg->value_external_ids,
812 port->port_cfg->n_external_ids,
813 key, ctx->argc >= 4 ? ctx->argv[3] : NULL,
815 ovsrec_port_set_external_ids(port->port_cfg, keys, values, n);
825 get_external_id(char **keys, char **values, size_t n,
826 const char *prefix, const char *key,
829 size_t prefix_len = strlen(prefix);
834 for (i = 0; i < n; i++) {
835 if (!key && !strncmp(keys[i], prefix, prefix_len)) {
836 svec_add_nocopy(&svec, xasprintf("%s=%s",
837 keys[i] + prefix_len, values[i]));
838 } else if (key_matches(keys[i], prefix, prefix_len, key)) {
839 svec_add(&svec, values[i]);
843 output_sorted(&svec, output);
848 cmd_br_get_external_id(struct vsctl_context *ctx)
850 struct vsctl_info info;
851 struct vsctl_bridge *bridge;
853 get_info(ctx->ovs, &info);
854 bridge = find_bridge(&info, ctx->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 "", ctx->argc >= 3 ? ctx->argv[2] : NULL,
862 struct vsctl_port *port = shash_find_data(&info.ports, ctx->argv[1]);
863 get_external_id(port->port_cfg->key_external_ids,
864 port->port_cfg->value_external_ids,
865 port->port_cfg->n_external_ids,
866 "fake-bridge-", ctx->argc >= 3 ? ctx->argv[2] : NULL, &ctx->output);
873 cmd_list_ports(struct vsctl_context *ctx)
875 struct vsctl_bridge *br;
876 struct shash_node *node;
877 struct vsctl_info info;
880 get_info(ctx->ovs, &info);
881 br = find_bridge(&info, ctx->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, &ctx->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(struct vsctl_context *ctx)
939 add_port(ctx->ovs, ctx->argv[1], ctx->argv[2], &ctx->argv[2], 1);
943 cmd_add_bond(struct vsctl_context *ctx)
945 add_port(ctx->ovs, ctx->argv[1], ctx->argv[2], &ctx->argv[3], ctx->argc - 3);
949 cmd_del_port(struct vsctl_context *ctx)
951 struct vsctl_info info;
953 get_info(ctx->ovs, &info);
954 if (ctx->argc == 2) {
955 struct vsctl_port *port = find_port(&info, ctx->argv[1]);
956 del_port(&info, port);
957 } else if (ctx->argc == 3) {
958 struct vsctl_bridge *bridge = find_bridge(&info, ctx->argv[1]);
959 struct vsctl_port *port = find_port(&info, ctx->argv[2]);
961 if (port->bridge == bridge) {
962 del_port(&info, port);
963 } else if (port->bridge->parent == bridge) {
964 ovs_fatal(0, "bridge %s does not have a port %s (although its "
965 "parent bridge %s does)",
966 ctx->argv[1], ctx->argv[2], bridge->parent->name);
968 ovs_fatal(0, "bridge %s does not have a port %s",
969 ctx->argv[1], ctx->argv[2]);
976 cmd_port_to_br(struct vsctl_context *ctx)
978 struct vsctl_port *port;
979 struct vsctl_info info;
981 get_info(ctx->ovs, &info);
982 port = find_port(&info, ctx->argv[1]);
983 ds_put_format(&ctx->output, "%s\n", port->bridge->name);
988 cmd_port_set_external_id(struct vsctl_context *ctx)
990 struct vsctl_info info;
991 struct vsctl_port *port;
992 char **keys, **values;
995 get_info(ctx->ovs, &info);
996 port = find_port(&info, ctx->argv[1]);
997 set_external_id(port->port_cfg->key_external_ids,
998 port->port_cfg->value_external_ids,
999 port->port_cfg->n_external_ids,
1000 ctx->argv[2], ctx->argc >= 4 ? ctx->argv[3] : NULL,
1001 &keys, &values, &n);
1002 ovsrec_port_set_external_ids(port->port_cfg, keys, values, n);
1010 cmd_port_get_external_id(struct vsctl_context *ctx)
1012 struct vsctl_info info;
1013 struct vsctl_port *port;
1015 get_info(ctx->ovs, &info);
1016 port = find_port(&info, ctx->argv[1]);
1017 get_external_id(port->port_cfg->key_external_ids,
1018 port->port_cfg->value_external_ids,
1019 port->port_cfg->n_external_ids,
1020 "", ctx->argc >= 3 ? ctx->argv[2] : NULL, &ctx->output);
1025 cmd_br_to_vlan(struct vsctl_context *ctx)
1027 struct vsctl_bridge *bridge;
1028 struct vsctl_info info;
1030 get_info(ctx->ovs, &info);
1031 bridge = find_bridge(&info, ctx->argv[1]);
1032 ds_put_format(&ctx->output, "%d\n", bridge->vlan);
1037 cmd_br_to_parent(struct vsctl_context *ctx)
1039 struct vsctl_bridge *bridge;
1040 struct vsctl_info info;
1042 get_info(ctx->ovs, &info);
1043 bridge = find_bridge(&info, ctx->argv[1]);
1044 if (bridge->parent) {
1045 bridge = bridge->parent;
1047 ds_put_format(&ctx->output, "%s\n", bridge->name);
1052 cmd_list_ifaces(struct vsctl_context *ctx)
1054 struct vsctl_bridge *br;
1055 struct shash_node *node;
1056 struct vsctl_info info;
1059 get_info(ctx->ovs, &info);
1060 br = find_bridge(&info, ctx->argv[1]);
1063 SHASH_FOR_EACH (node, &info.ifaces) {
1064 struct vsctl_iface *iface = node->data;
1066 if (strcmp(iface->iface_cfg->name, br->name)
1067 && br == iface->port->bridge) {
1068 svec_add(&ifaces, iface->iface_cfg->name);
1071 output_sorted(&ifaces, &ctx->output);
1072 svec_destroy(&ifaces);
1078 cmd_iface_to_br(struct vsctl_context *ctx)
1080 struct vsctl_iface *iface;
1081 struct vsctl_info info;
1083 get_info(ctx->ovs, &info);
1084 iface = find_iface(&info, ctx->argv[1]);
1085 ds_put_format(&ctx->output, "%s\n", iface->port->bridge->name);
1090 cmd_iface_set_external_id(struct vsctl_context *ctx)
1092 struct vsctl_info info;
1093 struct vsctl_iface *iface;
1094 char **keys, **values;
1097 get_info(ctx->ovs, &info);
1098 iface = find_iface(&info, ctx->argv[1]);
1099 set_external_id(iface->iface_cfg->key_external_ids,
1100 iface->iface_cfg->value_external_ids,
1101 iface->iface_cfg->n_external_ids,
1102 ctx->argv[2], ctx->argc >= 4 ? ctx->argv[3] : NULL,
1103 &keys, &values, &n);
1104 ovsrec_interface_set_external_ids(iface->iface_cfg, keys, values, n);
1112 cmd_iface_get_external_id(struct vsctl_context *ctx)
1114 struct vsctl_info info;
1115 struct vsctl_iface *iface;
1117 get_info(ctx->ovs, &info);
1118 iface = find_iface(&info, ctx->argv[1]);
1119 get_external_id(iface->iface_cfg->key_external_ids,
1120 iface->iface_cfg->value_external_ids,
1121 iface->iface_cfg->n_external_ids,
1122 "", ctx->argc >= 3 ? ctx->argv[2] : NULL, &ctx->output);
1126 typedef void vsctl_handler_func(struct vsctl_context *);
1128 struct vsctl_command {
1132 vsctl_handler_func *handler;
1133 const char *options;
1136 static void run_vsctl_command(int argc, char *argv[],
1137 const struct ovsrec_open_vswitch *ovs,
1141 do_vsctl(int argc, char *argv[], struct ovsdb_idl *idl)
1143 struct ovsdb_idl_txn *txn;
1144 const struct ovsrec_open_vswitch *ovs;
1145 enum ovsdb_idl_txn_status status;
1150 ovs = ovsrec_open_vswitch_first(idl);
1152 /* XXX it would be more user-friendly to create a record ourselves
1153 * (while verifying that the table is empty before doing so). */
1154 ovs_fatal(0, "%s: database does not contain any Open vSwitch "
1155 "configuration", db);
1158 txn = ovsdb_idl_txn_create(idl);
1159 output = xmalloc(argc * sizeof *output);
1161 for (start = i = 0; i <= argc; i++) {
1162 if (i == argc || !strcmp(argv[i], "--")) {
1164 ds_init(&output[n_output]);
1165 run_vsctl_command(i - start, &argv[start], ovs,
1166 &output[n_output++]);
1172 while ((status = ovsdb_idl_txn_commit(txn)) == TXN_INCOMPLETE) {
1174 ovsdb_idl_wait(idl);
1175 ovsdb_idl_txn_wait(txn);
1178 ovsdb_idl_txn_destroy(txn);
1181 case TXN_INCOMPLETE:
1185 /* Should not happen--we never call ovsdb_idl_txn_abort(). */
1186 ovs_fatal(0, "transaction aborted");
1192 for (i = 0; i < n_output; i++) {
1193 ds_destroy(&output[i]);
1198 ovs_fatal(0, "transaction error");
1204 for (i = 0; i < n_output; i++) {
1205 struct ds *ds = &output[i];
1210 for (j = 0; j < ds->length; j++) {
1211 int c = ds->string[j];
1214 fputs("\\n", stdout);
1218 fputs("\\\\", stdout);
1227 fputs(ds_cstr(ds), stdout);
1233 static vsctl_handler_func *
1234 get_vsctl_handler(int argc, char *argv[], struct vsctl_context *ctx)
1236 static const struct vsctl_command all_commands[] = {
1237 /* Bridge commands. */
1238 {"add-br", 1, 3, cmd_add_br, ""},
1239 {"del-br", 1, 1, cmd_del_br, ""},
1240 {"list-br", 0, 0, cmd_list_br, ""},
1241 {"br-exists", 1, 1, cmd_br_exists, ""},
1242 {"br-to-vlan", 1, 1, cmd_br_to_vlan, ""},
1243 {"br-to-parent", 1, 1, cmd_br_to_parent, ""},
1244 {"br-set-external-id", 2, 3, cmd_br_set_external_id, ""},
1245 {"br-get-external-id", 1, 2, cmd_br_get_external_id, ""},
1247 /* Port commands. */
1248 {"list-ports", 1, 1, cmd_list_ports, ""},
1249 {"add-port", 2, 2, cmd_add_port, ""},
1250 {"add-bond", 4, INT_MAX, cmd_add_bond, ""},
1251 {"del-port", 1, 2, cmd_del_port, ""},
1252 {"port-to-br", 1, 1, cmd_port_to_br, ""},
1253 {"port-set-external-id", 2, 3, cmd_port_set_external_id, ""},
1254 {"port-get-external-id", 1, 2, cmd_port_get_external_id, ""},
1256 /* Interface commands. */
1257 {"list-ifaces", 1, 1, cmd_list_ifaces, ""},
1258 {"iface-to-br", 1, 1, cmd_iface_to_br, ""},
1259 {"iface-set-external-id", 2, 3, cmd_iface_set_external_id, ""},
1260 {"iface-get-external-id", 1, 2, cmd_iface_get_external_id, ""},
1263 const struct vsctl_command *p;
1266 shash_init(&ctx->options);
1267 for (i = 0; i < argc; i++) {
1268 if (argv[i][0] != '-') {
1271 if (!shash_add_once(&ctx->options, argv[i], NULL)) {
1272 ovs_fatal(0, "'%s' option specified multiple times", argv[i]);
1276 ovs_fatal(0, "missing command name");
1279 for (p = all_commands; p < &all_commands[ARRAY_SIZE(all_commands)]; p++) {
1280 if (!strcmp(p->name, argv[i])) {
1281 struct shash_node *node;
1284 SHASH_FOR_EACH (node, &ctx->options) {
1285 const char *s = strstr(p->options, node->name);
1286 int end = s ? s[strlen(node->name)] : EOF;
1287 if (end != ',' && end != ' ' && end != '\0') {
1288 ovs_fatal(0, "'%s' command has no '%s' option",
1289 argv[i], node->name);
1293 n_arg = argc - i - 1;
1294 if (n_arg < p->min_args) {
1295 ovs_fatal(0, "'%s' command requires at least %d arguments",
1296 p->name, p->min_args);
1297 } else if (n_arg > p->max_args) {
1298 ovs_fatal(0, "'%s' command takes at most %d arguments",
1299 p->name, p->max_args);
1301 ctx->argc = n_arg + 1;
1302 ctx->argv = &argv[i];
1308 ovs_fatal(0, "unknown command '%s'; use --help for help", argv[0]);
1312 check_vsctl_command(int argc, char *argv[])
1314 struct vsctl_context ctx;
1316 get_vsctl_handler(argc, argv, &ctx);
1317 shash_destroy(&ctx.options);
1321 run_vsctl_command(int argc, char *argv[],
1322 const struct ovsrec_open_vswitch *ovs, struct ds *output)
1324 vsctl_handler_func *function;
1325 struct vsctl_context ctx;
1327 function = get_vsctl_handler(argc, argv, &ctx);
1329 ds_init(&ctx.output);
1331 *output = ctx.output;
1332 shash_destroy(&ctx.options);