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, bool must_exist)
506 struct vsctl_bridge *br = shash_find_data(&info->bridges, name);
507 if (must_exist && !br) {
508 ovs_fatal(0, "no bridge named %s", name);
513 static struct vsctl_port *
514 find_port(struct vsctl_info *info, const char *name, bool must_exist)
516 struct vsctl_port *port = shash_find_data(&info->ports, name);
517 if (!strcmp(name, port->bridge->name)) {
520 if (must_exist && !port) {
521 ovs_fatal(0, "no port named %s", name);
526 static struct vsctl_iface *
527 find_iface(struct vsctl_info *info, const char *name, bool must_exist)
529 struct vsctl_iface *iface = shash_find_data(&info->ifaces, name);
530 if (!strcmp(name, iface->port->bridge->name)) {
533 if (must_exist && !iface) {
534 ovs_fatal(0, "no interface named %s", name);
540 bridge_insert_port(struct ovsrec_bridge *br, struct ovsrec_port *port)
542 struct ovsrec_port **ports;
545 ports = xmalloc(sizeof *br->ports * (br->n_ports + 1));
546 for (i = 0; i < br->n_ports; i++) {
547 ports[i] = br->ports[i];
549 ports[br->n_ports] = port;
550 ovsrec_bridge_set_ports(br, ports, br->n_ports + 1);
555 bridge_delete_port(struct ovsrec_bridge *br, struct ovsrec_port *port)
557 struct ovsrec_port **ports;
560 ports = xmalloc(sizeof *br->ports * br->n_ports);
561 for (i = n = 0; i < br->n_ports; i++) {
562 if (br->ports[i] != port) {
563 ports[n++] = br->ports[i];
566 ovsrec_bridge_set_ports(br, ports, n);
571 ovs_insert_bridge(const struct ovsrec_open_vswitch *ovs,
572 struct ovsrec_bridge *bridge)
574 struct ovsrec_bridge **bridges;
577 bridges = xmalloc(sizeof *ovs->bridges * (ovs->n_bridges + 1));
578 for (i = 0; i < ovs->n_bridges; i++) {
579 bridges[i] = ovs->bridges[i];
581 bridges[ovs->n_bridges] = bridge;
582 ovsrec_open_vswitch_set_bridges(ovs, bridges, ovs->n_bridges + 1);
587 ovs_delete_bridge(const struct ovsrec_open_vswitch *ovs,
588 struct ovsrec_bridge *bridge)
590 struct ovsrec_bridge **bridges;
593 bridges = xmalloc(sizeof *ovs->bridges * ovs->n_bridges);
594 for (i = n = 0; i < ovs->n_bridges; i++) {
595 if (ovs->bridges[i] != bridge) {
596 bridges[n++] = ovs->bridges[i];
599 ovsrec_open_vswitch_set_bridges(ovs, bridges, n);
604 cmd_add_br(struct vsctl_context *ctx)
606 const char *br_name = ctx->argv[1];
607 struct vsctl_info info;
609 get_info(ctx->ovs, &info);
610 check_conflicts(&info, br_name,
611 xasprintf("cannot create a bridge named %s", br_name));
613 if (ctx->argc == 2) {
614 struct ovsrec_bridge *br;
615 struct ovsrec_port *port;
616 struct ovsrec_interface *iface;
618 iface = ovsrec_interface_insert(txn_from_openvswitch(ctx->ovs));
619 ovsrec_interface_set_name(iface, br_name);
621 port = ovsrec_port_insert(txn_from_openvswitch(ctx->ovs));
622 ovsrec_port_set_name(port, br_name);
623 ovsrec_port_set_interfaces(port, &iface, 1);
625 br = ovsrec_bridge_insert(txn_from_openvswitch(ctx->ovs));
626 ovsrec_bridge_set_name(br, br_name);
627 ovsrec_bridge_set_ports(br, &port, 1);
629 ovs_insert_bridge(ctx->ovs, br);
630 } else if (ctx->argc == 3) {
631 ovs_fatal(0, "'%s' comamnd takes exactly 1 or 3 arguments", ctx->argv[0]);
632 } else if (ctx->argc == 4) {
633 const char *parent_name = ctx->argv[2];
634 int vlan = atoi(ctx->argv[3]);
635 struct ovsrec_bridge *br;
636 struct vsctl_bridge *parent;
637 struct ovsrec_port *port;
638 struct ovsrec_interface *iface;
641 if (vlan < 1 || vlan > 4095) {
642 ovs_fatal(0, "%s: vlan must be between 1 and 4095", ctx->argv[0]);
645 parent = find_bridge(&info, parent_name, false);
646 if (parent && parent->vlan) {
647 ovs_fatal(0, "cannot create brdige with fake bridge as parent");
650 ovs_fatal(0, "parent bridge %s does not exist", parent_name);
654 iface = ovsrec_interface_insert(txn_from_openvswitch(ctx->ovs));
655 ovsrec_interface_set_name(iface, br_name);
656 ovsrec_interface_set_type(iface, "internal");
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);
661 ovsrec_port_set_fake_bridge(port, true);
662 ovsrec_port_set_tag(port, &tag, 1);
664 bridge_insert_port(br, port);
673 del_port(struct vsctl_info *info, struct vsctl_port *port)
675 struct shash_node *node;
677 SHASH_FOR_EACH (node, &info->ifaces) {
678 struct vsctl_iface *iface = node->data;
679 if (iface->port == port) {
680 ovsrec_interface_delete(iface->iface_cfg);
683 ovsrec_port_delete(port->port_cfg);
685 bridge_delete_port((port->bridge->parent
686 ? port->bridge->parent->br_cfg
687 : port->bridge->br_cfg), port->port_cfg);
691 cmd_del_br(struct vsctl_context *ctx)
693 struct shash_node *node;
694 struct vsctl_info info;
695 struct vsctl_bridge *bridge;
697 get_info(ctx->ovs, &info);
698 bridge = find_bridge(&info, ctx->argv[1], true);
699 SHASH_FOR_EACH (node, &info.ports) {
700 struct vsctl_port *port = node->data;
701 if (port->bridge == bridge
702 || !strcmp(port->port_cfg->name, bridge->name)) {
703 del_port(&info, port);
706 if (bridge->br_cfg) {
707 ovsrec_bridge_delete(bridge->br_cfg);
708 ovs_delete_bridge(ctx->ovs, bridge->br_cfg);
714 output_sorted(struct svec *svec, struct ds *output)
720 SVEC_FOR_EACH (i, name, svec) {
721 ds_put_format(output, "%s\n", name);
726 cmd_list_br(struct vsctl_context *ctx)
728 struct shash_node *node;
729 struct vsctl_info info;
732 get_info(ctx->ovs, &info);
735 SHASH_FOR_EACH (node, &info.bridges) {
736 struct vsctl_bridge *br = node->data;
737 svec_add(&bridges, br->name);
739 output_sorted(&bridges, &ctx->output);
740 svec_destroy(&bridges);
746 cmd_br_exists(struct vsctl_context *ctx)
748 struct vsctl_info info;
750 get_info(ctx->ovs, &info);
751 if (!find_bridge(&info, ctx->argv[1], false)) {
757 /* Returns true if 'b_prefix' (of length 'b_prefix_len') concatenated with 'b'
758 * equals 'a', false otherwise. */
760 key_matches(const char *a,
761 const char *b_prefix, size_t b_prefix_len, const char *b)
763 return !strncmp(a, b_prefix, b_prefix_len) && !strcmp(a + b_prefix_len, b);
767 set_external_id(char **old_keys, char **old_values, size_t old_n,
768 char *key, char *value,
769 char ***new_keysp, char ***new_valuesp, size_t *new_np)
776 new_keys = xmalloc(sizeof *new_keys * (old_n + 1));
777 new_values = xmalloc(sizeof *new_values * (old_n + 1));
779 for (i = 0; i < old_n; i++) {
780 if (strcmp(key, old_keys[i])) {
781 new_keys[new_n] = old_keys[i];
782 new_values[new_n] = old_values[i];
787 new_keys[new_n] = key;
788 new_values[new_n] = value;
791 *new_keysp = new_keys;
792 *new_valuesp = new_values;
797 cmd_br_set_external_id(struct vsctl_context *ctx)
799 struct vsctl_info info;
800 struct vsctl_bridge *bridge;
801 char **keys, **values;
804 get_info(ctx->ovs, &info);
805 bridge = find_bridge(&info, ctx->argv[1], true);
806 if (bridge->br_cfg) {
807 set_external_id(bridge->br_cfg->key_external_ids,
808 bridge->br_cfg->value_external_ids,
809 bridge->br_cfg->n_external_ids,
810 ctx->argv[2], ctx->argc >= 4 ? ctx->argv[3] : NULL,
812 ovsrec_bridge_set_external_ids(bridge->br_cfg, keys, values, n);
814 char *key = xasprintf("fake-bridge-%s", ctx->argv[2]);
815 struct vsctl_port *port = shash_find_data(&info.ports, ctx->argv[1]);
816 set_external_id(port->port_cfg->key_external_ids,
817 port->port_cfg->value_external_ids,
818 port->port_cfg->n_external_ids,
819 key, ctx->argc >= 4 ? ctx->argv[3] : NULL,
821 ovsrec_port_set_external_ids(port->port_cfg, keys, values, n);
831 get_external_id(char **keys, char **values, size_t n,
832 const char *prefix, const char *key,
835 size_t prefix_len = strlen(prefix);
840 for (i = 0; i < n; i++) {
841 if (!key && !strncmp(keys[i], prefix, prefix_len)) {
842 svec_add_nocopy(&svec, xasprintf("%s=%s",
843 keys[i] + prefix_len, values[i]));
844 } else if (key_matches(keys[i], prefix, prefix_len, key)) {
845 svec_add(&svec, values[i]);
849 output_sorted(&svec, output);
854 cmd_br_get_external_id(struct vsctl_context *ctx)
856 struct vsctl_info info;
857 struct vsctl_bridge *bridge;
859 get_info(ctx->ovs, &info);
860 bridge = find_bridge(&info, ctx->argv[1], true);
861 if (bridge->br_cfg) {
862 get_external_id(bridge->br_cfg->key_external_ids,
863 bridge->br_cfg->value_external_ids,
864 bridge->br_cfg->n_external_ids,
865 "", ctx->argc >= 3 ? ctx->argv[2] : NULL,
868 struct vsctl_port *port = shash_find_data(&info.ports, ctx->argv[1]);
869 get_external_id(port->port_cfg->key_external_ids,
870 port->port_cfg->value_external_ids,
871 port->port_cfg->n_external_ids,
872 "fake-bridge-", ctx->argc >= 3 ? ctx->argv[2] : NULL, &ctx->output);
879 cmd_list_ports(struct vsctl_context *ctx)
881 struct vsctl_bridge *br;
882 struct shash_node *node;
883 struct vsctl_info info;
886 get_info(ctx->ovs, &info);
887 br = find_bridge(&info, ctx->argv[1], true);
890 SHASH_FOR_EACH (node, &info.ports) {
891 struct vsctl_port *port = node->data;
893 if (strcmp(port->port_cfg->name, br->name) && br == port->bridge) {
894 svec_add(&ports, port->port_cfg->name);
897 output_sorted(&ports, &ctx->output);
898 svec_destroy(&ports);
904 add_port(const struct ovsrec_open_vswitch *ovs,
905 const char *br_name, const char *port_name,
906 char *iface_names[], int n_ifaces)
908 struct vsctl_info info;
909 struct vsctl_bridge *bridge;
910 struct ovsrec_interface **ifaces;
911 struct ovsrec_port *port;
914 get_info(ovs, &info);
915 check_conflicts(&info, port_name,
916 xasprintf("cannot create a port named %s", port_name));
917 /* XXX need to check for conflicts on interfaces too */
918 bridge = find_bridge(&info, br_name, true);
920 ifaces = xmalloc(n_ifaces * sizeof *ifaces);
921 for (i = 0; i < n_ifaces; i++) {
922 ifaces[i] = ovsrec_interface_insert(txn_from_openvswitch(ovs));
923 ovsrec_interface_set_name(ifaces[i], iface_names[i]);
926 port = ovsrec_port_insert(txn_from_openvswitch(ovs));
927 ovsrec_port_set_name(port, port_name);
928 ovsrec_port_set_interfaces(port, ifaces, n_ifaces);
932 int64_t tag = bridge->vlan;
933 ovsrec_port_set_tag(port, &tag, 1);
936 bridge_insert_port((bridge->parent ? bridge->parent->br_cfg
937 : bridge->br_cfg), port);
943 cmd_add_port(struct vsctl_context *ctx)
945 add_port(ctx->ovs, ctx->argv[1], ctx->argv[2], &ctx->argv[2], 1);
949 cmd_add_bond(struct vsctl_context *ctx)
951 add_port(ctx->ovs, ctx->argv[1], ctx->argv[2], &ctx->argv[3], ctx->argc - 3);
955 cmd_del_port(struct vsctl_context *ctx)
957 struct vsctl_info info;
959 get_info(ctx->ovs, &info);
960 if (ctx->argc == 2) {
961 struct vsctl_port *port = find_port(&info, ctx->argv[1], true);
962 del_port(&info, port);
963 } else if (ctx->argc == 3) {
964 struct vsctl_bridge *bridge = find_bridge(&info, ctx->argv[1], true);
965 struct vsctl_port *port = find_port(&info, ctx->argv[2], true);
967 if (port->bridge == bridge) {
968 del_port(&info, port);
969 } else if (port->bridge->parent == bridge) {
970 ovs_fatal(0, "bridge %s does not have a port %s (although its "
971 "parent bridge %s does)",
972 ctx->argv[1], ctx->argv[2], bridge->parent->name);
974 ovs_fatal(0, "bridge %s does not have a port %s",
975 ctx->argv[1], ctx->argv[2]);
982 cmd_port_to_br(struct vsctl_context *ctx)
984 struct vsctl_port *port;
985 struct vsctl_info info;
987 get_info(ctx->ovs, &info);
988 port = find_port(&info, ctx->argv[1], true);
989 ds_put_format(&ctx->output, "%s\n", port->bridge->name);
994 cmd_port_set_external_id(struct vsctl_context *ctx)
996 struct vsctl_info info;
997 struct vsctl_port *port;
998 char **keys, **values;
1001 get_info(ctx->ovs, &info);
1002 port = find_port(&info, ctx->argv[1], true);
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 ctx->argv[2], ctx->argc >= 4 ? ctx->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(struct vsctl_context *ctx)
1018 struct vsctl_info info;
1019 struct vsctl_port *port;
1021 get_info(ctx->ovs, &info);
1022 port = find_port(&info, ctx->argv[1], true);
1023 get_external_id(port->port_cfg->key_external_ids,
1024 port->port_cfg->value_external_ids,
1025 port->port_cfg->n_external_ids,
1026 "", ctx->argc >= 3 ? ctx->argv[2] : NULL, &ctx->output);
1031 cmd_br_to_vlan(struct vsctl_context *ctx)
1033 struct vsctl_bridge *bridge;
1034 struct vsctl_info info;
1036 get_info(ctx->ovs, &info);
1037 bridge = find_bridge(&info, ctx->argv[1], true);
1038 ds_put_format(&ctx->output, "%d\n", bridge->vlan);
1043 cmd_br_to_parent(struct vsctl_context *ctx)
1045 struct vsctl_bridge *bridge;
1046 struct vsctl_info info;
1048 get_info(ctx->ovs, &info);
1049 bridge = find_bridge(&info, ctx->argv[1], true);
1050 if (bridge->parent) {
1051 bridge = bridge->parent;
1053 ds_put_format(&ctx->output, "%s\n", bridge->name);
1058 cmd_list_ifaces(struct vsctl_context *ctx)
1060 struct vsctl_bridge *br;
1061 struct shash_node *node;
1062 struct vsctl_info info;
1065 get_info(ctx->ovs, &info);
1066 br = find_bridge(&info, ctx->argv[1], true);
1069 SHASH_FOR_EACH (node, &info.ifaces) {
1070 struct vsctl_iface *iface = node->data;
1072 if (strcmp(iface->iface_cfg->name, br->name)
1073 && br == iface->port->bridge) {
1074 svec_add(&ifaces, iface->iface_cfg->name);
1077 output_sorted(&ifaces, &ctx->output);
1078 svec_destroy(&ifaces);
1084 cmd_iface_to_br(struct vsctl_context *ctx)
1086 struct vsctl_iface *iface;
1087 struct vsctl_info info;
1089 get_info(ctx->ovs, &info);
1090 iface = find_iface(&info, ctx->argv[1], true);
1091 ds_put_format(&ctx->output, "%s\n", iface->port->bridge->name);
1096 cmd_iface_set_external_id(struct vsctl_context *ctx)
1098 struct vsctl_info info;
1099 struct vsctl_iface *iface;
1100 char **keys, **values;
1103 get_info(ctx->ovs, &info);
1104 iface = find_iface(&info, ctx->argv[1], true);
1105 set_external_id(iface->iface_cfg->key_external_ids,
1106 iface->iface_cfg->value_external_ids,
1107 iface->iface_cfg->n_external_ids,
1108 ctx->argv[2], ctx->argc >= 4 ? ctx->argv[3] : NULL,
1109 &keys, &values, &n);
1110 ovsrec_interface_set_external_ids(iface->iface_cfg, keys, values, n);
1118 cmd_iface_get_external_id(struct vsctl_context *ctx)
1120 struct vsctl_info info;
1121 struct vsctl_iface *iface;
1123 get_info(ctx->ovs, &info);
1124 iface = find_iface(&info, ctx->argv[1], true);
1125 get_external_id(iface->iface_cfg->key_external_ids,
1126 iface->iface_cfg->value_external_ids,
1127 iface->iface_cfg->n_external_ids,
1128 "", ctx->argc >= 3 ? ctx->argv[2] : NULL, &ctx->output);
1132 typedef void vsctl_handler_func(struct vsctl_context *);
1134 struct vsctl_command {
1138 vsctl_handler_func *handler;
1139 const char *options;
1142 static void run_vsctl_command(int argc, char *argv[],
1143 const struct ovsrec_open_vswitch *ovs,
1147 do_vsctl(int argc, char *argv[], struct ovsdb_idl *idl)
1149 struct ovsdb_idl_txn *txn;
1150 const struct ovsrec_open_vswitch *ovs;
1151 enum ovsdb_idl_txn_status status;
1156 ovs = ovsrec_open_vswitch_first(idl);
1158 /* XXX it would be more user-friendly to create a record ourselves
1159 * (while verifying that the table is empty before doing so). */
1160 ovs_fatal(0, "%s: database does not contain any Open vSwitch "
1161 "configuration", db);
1164 txn = ovsdb_idl_txn_create(idl);
1165 output = xmalloc(argc * sizeof *output);
1167 for (start = i = 0; i <= argc; i++) {
1168 if (i == argc || !strcmp(argv[i], "--")) {
1170 ds_init(&output[n_output]);
1171 run_vsctl_command(i - start, &argv[start], ovs,
1172 &output[n_output++]);
1178 while ((status = ovsdb_idl_txn_commit(txn)) == TXN_INCOMPLETE) {
1180 ovsdb_idl_wait(idl);
1181 ovsdb_idl_txn_wait(txn);
1184 ovsdb_idl_txn_destroy(txn);
1187 case TXN_INCOMPLETE:
1191 /* Should not happen--we never call ovsdb_idl_txn_abort(). */
1192 ovs_fatal(0, "transaction aborted");
1198 for (i = 0; i < n_output; i++) {
1199 ds_destroy(&output[i]);
1204 ovs_fatal(0, "transaction error");
1210 for (i = 0; i < n_output; i++) {
1211 struct ds *ds = &output[i];
1216 for (j = 0; j < ds->length; j++) {
1217 int c = ds->string[j];
1220 fputs("\\n", stdout);
1224 fputs("\\\\", stdout);
1233 fputs(ds_cstr(ds), stdout);
1239 static vsctl_handler_func *
1240 get_vsctl_handler(int argc, char *argv[], struct vsctl_context *ctx)
1242 static const struct vsctl_command all_commands[] = {
1243 /* Bridge commands. */
1244 {"add-br", 1, 3, cmd_add_br, ""},
1245 {"del-br", 1, 1, cmd_del_br, ""},
1246 {"list-br", 0, 0, cmd_list_br, ""},
1247 {"br-exists", 1, 1, cmd_br_exists, ""},
1248 {"br-to-vlan", 1, 1, cmd_br_to_vlan, ""},
1249 {"br-to-parent", 1, 1, cmd_br_to_parent, ""},
1250 {"br-set-external-id", 2, 3, cmd_br_set_external_id, ""},
1251 {"br-get-external-id", 1, 2, cmd_br_get_external_id, ""},
1253 /* Port commands. */
1254 {"list-ports", 1, 1, cmd_list_ports, ""},
1255 {"add-port", 2, 2, cmd_add_port, ""},
1256 {"add-bond", 4, INT_MAX, cmd_add_bond, ""},
1257 {"del-port", 1, 2, cmd_del_port, ""},
1258 {"port-to-br", 1, 1, cmd_port_to_br, ""},
1259 {"port-set-external-id", 2, 3, cmd_port_set_external_id, ""},
1260 {"port-get-external-id", 1, 2, cmd_port_get_external_id, ""},
1262 /* Interface commands. */
1263 {"list-ifaces", 1, 1, cmd_list_ifaces, ""},
1264 {"iface-to-br", 1, 1, cmd_iface_to_br, ""},
1265 {"iface-set-external-id", 2, 3, cmd_iface_set_external_id, ""},
1266 {"iface-get-external-id", 1, 2, cmd_iface_get_external_id, ""},
1269 const struct vsctl_command *p;
1272 shash_init(&ctx->options);
1273 for (i = 0; i < argc; i++) {
1274 if (argv[i][0] != '-') {
1277 if (!shash_add_once(&ctx->options, argv[i], NULL)) {
1278 ovs_fatal(0, "'%s' option specified multiple times", argv[i]);
1282 ovs_fatal(0, "missing command name");
1285 for (p = all_commands; p < &all_commands[ARRAY_SIZE(all_commands)]; p++) {
1286 if (!strcmp(p->name, argv[i])) {
1287 struct shash_node *node;
1290 SHASH_FOR_EACH (node, &ctx->options) {
1291 const char *s = strstr(p->options, node->name);
1292 int end = s ? s[strlen(node->name)] : EOF;
1293 if (end != ',' && end != ' ' && end != '\0') {
1294 ovs_fatal(0, "'%s' command has no '%s' option",
1295 argv[i], node->name);
1299 n_arg = argc - i - 1;
1300 if (n_arg < p->min_args) {
1301 ovs_fatal(0, "'%s' command requires at least %d arguments",
1302 p->name, p->min_args);
1303 } else if (n_arg > p->max_args) {
1304 ovs_fatal(0, "'%s' command takes at most %d arguments",
1305 p->name, p->max_args);
1307 ctx->argc = n_arg + 1;
1308 ctx->argv = &argv[i];
1314 ovs_fatal(0, "unknown command '%s'; use --help for help", argv[0]);
1318 check_vsctl_command(int argc, char *argv[])
1320 struct vsctl_context ctx;
1322 get_vsctl_handler(argc, argv, &ctx);
1323 shash_destroy(&ctx.options);
1327 run_vsctl_command(int argc, char *argv[],
1328 const struct ovsrec_open_vswitch *ovs, struct ds *output)
1330 vsctl_handler_func *function;
1331 struct vsctl_context ctx;
1333 function = get_vsctl_handler(argc, argv, &ctx);
1335 ds_init(&ctx.output);
1337 *output = ctx.output;
1338 shash_destroy(&ctx.options);