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 (port && !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 (iface && !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 bool must_exist = !shash_find(&ctx->options, "--if-exists");
694 struct vsctl_bridge *bridge;
695 struct vsctl_info info;
697 get_info(ctx->ovs, &info);
698 bridge = find_bridge(&info, ctx->argv[1], must_exist);
700 struct shash_node *node;
702 SHASH_FOR_EACH (node, &info.ports) {
703 struct vsctl_port *port = node->data;
704 if (port->bridge == bridge
705 || !strcmp(port->port_cfg->name, bridge->name)) {
706 del_port(&info, port);
709 if (bridge->br_cfg) {
710 ovsrec_bridge_delete(bridge->br_cfg);
711 ovs_delete_bridge(ctx->ovs, bridge->br_cfg);
718 output_sorted(struct svec *svec, struct ds *output)
724 SVEC_FOR_EACH (i, name, svec) {
725 ds_put_format(output, "%s\n", name);
730 cmd_list_br(struct vsctl_context *ctx)
732 struct shash_node *node;
733 struct vsctl_info info;
736 get_info(ctx->ovs, &info);
739 SHASH_FOR_EACH (node, &info.bridges) {
740 struct vsctl_bridge *br = node->data;
741 svec_add(&bridges, br->name);
743 output_sorted(&bridges, &ctx->output);
744 svec_destroy(&bridges);
750 cmd_br_exists(struct vsctl_context *ctx)
752 struct vsctl_info info;
754 get_info(ctx->ovs, &info);
755 if (!find_bridge(&info, ctx->argv[1], false)) {
761 /* Returns true if 'b_prefix' (of length 'b_prefix_len') concatenated with 'b'
762 * equals 'a', false otherwise. */
764 key_matches(const char *a,
765 const char *b_prefix, size_t b_prefix_len, const char *b)
767 return !strncmp(a, b_prefix, b_prefix_len) && !strcmp(a + b_prefix_len, b);
771 set_external_id(char **old_keys, char **old_values, size_t old_n,
772 char *key, char *value,
773 char ***new_keysp, char ***new_valuesp, size_t *new_np)
780 new_keys = xmalloc(sizeof *new_keys * (old_n + 1));
781 new_values = xmalloc(sizeof *new_values * (old_n + 1));
783 for (i = 0; i < old_n; i++) {
784 if (strcmp(key, old_keys[i])) {
785 new_keys[new_n] = old_keys[i];
786 new_values[new_n] = old_values[i];
791 new_keys[new_n] = key;
792 new_values[new_n] = value;
795 *new_keysp = new_keys;
796 *new_valuesp = new_values;
801 cmd_br_set_external_id(struct vsctl_context *ctx)
803 struct vsctl_info info;
804 struct vsctl_bridge *bridge;
805 char **keys, **values;
808 get_info(ctx->ovs, &info);
809 bridge = find_bridge(&info, ctx->argv[1], true);
810 if (bridge->br_cfg) {
811 set_external_id(bridge->br_cfg->key_external_ids,
812 bridge->br_cfg->value_external_ids,
813 bridge->br_cfg->n_external_ids,
814 ctx->argv[2], ctx->argc >= 4 ? ctx->argv[3] : NULL,
816 ovsrec_bridge_set_external_ids(bridge->br_cfg, keys, values, n);
818 char *key = xasprintf("fake-bridge-%s", ctx->argv[2]);
819 struct vsctl_port *port = shash_find_data(&info.ports, ctx->argv[1]);
820 set_external_id(port->port_cfg->key_external_ids,
821 port->port_cfg->value_external_ids,
822 port->port_cfg->n_external_ids,
823 key, ctx->argc >= 4 ? ctx->argv[3] : NULL,
825 ovsrec_port_set_external_ids(port->port_cfg, keys, values, n);
835 get_external_id(char **keys, char **values, size_t n,
836 const char *prefix, const char *key,
839 size_t prefix_len = strlen(prefix);
844 for (i = 0; i < n; i++) {
845 if (!key && !strncmp(keys[i], prefix, prefix_len)) {
846 svec_add_nocopy(&svec, xasprintf("%s=%s",
847 keys[i] + prefix_len, values[i]));
848 } else if (key_matches(keys[i], prefix, prefix_len, key)) {
849 svec_add(&svec, values[i]);
853 output_sorted(&svec, output);
858 cmd_br_get_external_id(struct vsctl_context *ctx)
860 struct vsctl_info info;
861 struct vsctl_bridge *bridge;
863 get_info(ctx->ovs, &info);
864 bridge = find_bridge(&info, ctx->argv[1], true);
865 if (bridge->br_cfg) {
866 get_external_id(bridge->br_cfg->key_external_ids,
867 bridge->br_cfg->value_external_ids,
868 bridge->br_cfg->n_external_ids,
869 "", ctx->argc >= 3 ? ctx->argv[2] : NULL,
872 struct vsctl_port *port = shash_find_data(&info.ports, ctx->argv[1]);
873 get_external_id(port->port_cfg->key_external_ids,
874 port->port_cfg->value_external_ids,
875 port->port_cfg->n_external_ids,
876 "fake-bridge-", ctx->argc >= 3 ? ctx->argv[2] : NULL, &ctx->output);
883 cmd_list_ports(struct vsctl_context *ctx)
885 struct vsctl_bridge *br;
886 struct shash_node *node;
887 struct vsctl_info info;
890 get_info(ctx->ovs, &info);
891 br = find_bridge(&info, ctx->argv[1], true);
894 SHASH_FOR_EACH (node, &info.ports) {
895 struct vsctl_port *port = node->data;
897 if (strcmp(port->port_cfg->name, br->name) && br == port->bridge) {
898 svec_add(&ports, port->port_cfg->name);
901 output_sorted(&ports, &ctx->output);
902 svec_destroy(&ports);
908 add_port(const struct ovsrec_open_vswitch *ovs,
909 const char *br_name, const char *port_name,
910 char *iface_names[], int n_ifaces)
912 struct vsctl_info info;
913 struct vsctl_bridge *bridge;
914 struct ovsrec_interface **ifaces;
915 struct ovsrec_port *port;
918 get_info(ovs, &info);
919 check_conflicts(&info, port_name,
920 xasprintf("cannot create a port named %s", port_name));
921 /* XXX need to check for conflicts on interfaces too */
922 bridge = find_bridge(&info, br_name, true);
924 ifaces = xmalloc(n_ifaces * sizeof *ifaces);
925 for (i = 0; i < n_ifaces; i++) {
926 ifaces[i] = ovsrec_interface_insert(txn_from_openvswitch(ovs));
927 ovsrec_interface_set_name(ifaces[i], iface_names[i]);
930 port = ovsrec_port_insert(txn_from_openvswitch(ovs));
931 ovsrec_port_set_name(port, port_name);
932 ovsrec_port_set_interfaces(port, ifaces, n_ifaces);
936 int64_t tag = bridge->vlan;
937 ovsrec_port_set_tag(port, &tag, 1);
940 bridge_insert_port((bridge->parent ? bridge->parent->br_cfg
941 : bridge->br_cfg), port);
947 cmd_add_port(struct vsctl_context *ctx)
949 add_port(ctx->ovs, ctx->argv[1], ctx->argv[2], &ctx->argv[2], 1);
953 cmd_add_bond(struct vsctl_context *ctx)
955 add_port(ctx->ovs, ctx->argv[1], ctx->argv[2], &ctx->argv[3], ctx->argc - 3);
959 cmd_del_port(struct vsctl_context *ctx)
961 bool must_exist = !shash_find(&ctx->options, "--if-exists");
962 struct vsctl_info info;
964 get_info(ctx->ovs, &info);
965 if (ctx->argc == 2) {
966 struct vsctl_port *port = find_port(&info, ctx->argv[1], must_exist);
968 del_port(&info, port);
970 } else if (ctx->argc == 3) {
971 struct vsctl_bridge *bridge = find_bridge(&info, ctx->argv[1], true);
972 struct vsctl_port *port = find_port(&info, ctx->argv[2], must_exist);
975 if (port->bridge == bridge) {
976 del_port(&info, port);
977 } else if (port->bridge->parent == bridge) {
978 ovs_fatal(0, "bridge %s does not have a port %s (although its "
979 "parent bridge %s does)",
980 ctx->argv[1], ctx->argv[2], bridge->parent->name);
982 ovs_fatal(0, "bridge %s does not have a port %s",
983 ctx->argv[1], ctx->argv[2]);
991 cmd_port_to_br(struct vsctl_context *ctx)
993 struct vsctl_port *port;
994 struct vsctl_info info;
996 get_info(ctx->ovs, &info);
997 port = find_port(&info, ctx->argv[1], true);
998 ds_put_format(&ctx->output, "%s\n", port->bridge->name);
1003 cmd_port_set_external_id(struct vsctl_context *ctx)
1005 struct vsctl_info info;
1006 struct vsctl_port *port;
1007 char **keys, **values;
1010 get_info(ctx->ovs, &info);
1011 port = find_port(&info, ctx->argv[1], true);
1012 set_external_id(port->port_cfg->key_external_ids,
1013 port->port_cfg->value_external_ids,
1014 port->port_cfg->n_external_ids,
1015 ctx->argv[2], ctx->argc >= 4 ? ctx->argv[3] : NULL,
1016 &keys, &values, &n);
1017 ovsrec_port_set_external_ids(port->port_cfg, keys, values, n);
1025 cmd_port_get_external_id(struct vsctl_context *ctx)
1027 struct vsctl_info info;
1028 struct vsctl_port *port;
1030 get_info(ctx->ovs, &info);
1031 port = find_port(&info, ctx->argv[1], true);
1032 get_external_id(port->port_cfg->key_external_ids,
1033 port->port_cfg->value_external_ids,
1034 port->port_cfg->n_external_ids,
1035 "", ctx->argc >= 3 ? ctx->argv[2] : NULL, &ctx->output);
1040 cmd_br_to_vlan(struct vsctl_context *ctx)
1042 struct vsctl_bridge *bridge;
1043 struct vsctl_info info;
1045 get_info(ctx->ovs, &info);
1046 bridge = find_bridge(&info, ctx->argv[1], true);
1047 ds_put_format(&ctx->output, "%d\n", bridge->vlan);
1052 cmd_br_to_parent(struct vsctl_context *ctx)
1054 struct vsctl_bridge *bridge;
1055 struct vsctl_info info;
1057 get_info(ctx->ovs, &info);
1058 bridge = find_bridge(&info, ctx->argv[1], true);
1059 if (bridge->parent) {
1060 bridge = bridge->parent;
1062 ds_put_format(&ctx->output, "%s\n", bridge->name);
1067 cmd_list_ifaces(struct vsctl_context *ctx)
1069 struct vsctl_bridge *br;
1070 struct shash_node *node;
1071 struct vsctl_info info;
1074 get_info(ctx->ovs, &info);
1075 br = find_bridge(&info, ctx->argv[1], true);
1078 SHASH_FOR_EACH (node, &info.ifaces) {
1079 struct vsctl_iface *iface = node->data;
1081 if (strcmp(iface->iface_cfg->name, br->name)
1082 && br == iface->port->bridge) {
1083 svec_add(&ifaces, iface->iface_cfg->name);
1086 output_sorted(&ifaces, &ctx->output);
1087 svec_destroy(&ifaces);
1093 cmd_iface_to_br(struct vsctl_context *ctx)
1095 struct vsctl_iface *iface;
1096 struct vsctl_info info;
1098 get_info(ctx->ovs, &info);
1099 iface = find_iface(&info, ctx->argv[1], true);
1100 ds_put_format(&ctx->output, "%s\n", iface->port->bridge->name);
1105 cmd_iface_set_external_id(struct vsctl_context *ctx)
1107 struct vsctl_info info;
1108 struct vsctl_iface *iface;
1109 char **keys, **values;
1112 get_info(ctx->ovs, &info);
1113 iface = find_iface(&info, ctx->argv[1], true);
1114 set_external_id(iface->iface_cfg->key_external_ids,
1115 iface->iface_cfg->value_external_ids,
1116 iface->iface_cfg->n_external_ids,
1117 ctx->argv[2], ctx->argc >= 4 ? ctx->argv[3] : NULL,
1118 &keys, &values, &n);
1119 ovsrec_interface_set_external_ids(iface->iface_cfg, keys, values, n);
1127 cmd_iface_get_external_id(struct vsctl_context *ctx)
1129 struct vsctl_info info;
1130 struct vsctl_iface *iface;
1132 get_info(ctx->ovs, &info);
1133 iface = find_iface(&info, ctx->argv[1], true);
1134 get_external_id(iface->iface_cfg->key_external_ids,
1135 iface->iface_cfg->value_external_ids,
1136 iface->iface_cfg->n_external_ids,
1137 "", ctx->argc >= 3 ? ctx->argv[2] : NULL, &ctx->output);
1141 typedef void vsctl_handler_func(struct vsctl_context *);
1143 struct vsctl_command {
1147 vsctl_handler_func *handler;
1148 const char *options;
1151 static void run_vsctl_command(int argc, char *argv[],
1152 const struct ovsrec_open_vswitch *ovs,
1156 do_vsctl(int argc, char *argv[], struct ovsdb_idl *idl)
1158 struct ovsdb_idl_txn *txn;
1159 const struct ovsrec_open_vswitch *ovs;
1160 enum ovsdb_idl_txn_status status;
1165 ovs = ovsrec_open_vswitch_first(idl);
1167 /* XXX it would be more user-friendly to create a record ourselves
1168 * (while verifying that the table is empty before doing so). */
1169 ovs_fatal(0, "%s: database does not contain any Open vSwitch "
1170 "configuration", db);
1173 txn = ovsdb_idl_txn_create(idl);
1174 output = xmalloc(argc * sizeof *output);
1176 for (start = i = 0; i <= argc; i++) {
1177 if (i == argc || !strcmp(argv[i], "--")) {
1179 ds_init(&output[n_output]);
1180 run_vsctl_command(i - start, &argv[start], ovs,
1181 &output[n_output++]);
1187 while ((status = ovsdb_idl_txn_commit(txn)) == TXN_INCOMPLETE) {
1189 ovsdb_idl_wait(idl);
1190 ovsdb_idl_txn_wait(txn);
1193 ovsdb_idl_txn_destroy(txn);
1196 case TXN_INCOMPLETE:
1200 /* Should not happen--we never call ovsdb_idl_txn_abort(). */
1201 ovs_fatal(0, "transaction aborted");
1207 for (i = 0; i < n_output; i++) {
1208 ds_destroy(&output[i]);
1213 ovs_fatal(0, "transaction error");
1219 for (i = 0; i < n_output; i++) {
1220 struct ds *ds = &output[i];
1225 for (j = 0; j < ds->length; j++) {
1226 int c = ds->string[j];
1229 fputs("\\n", stdout);
1233 fputs("\\\\", stdout);
1242 fputs(ds_cstr(ds), stdout);
1248 static vsctl_handler_func *
1249 get_vsctl_handler(int argc, char *argv[], struct vsctl_context *ctx)
1251 static const struct vsctl_command all_commands[] = {
1252 /* Bridge commands. */
1253 {"add-br", 1, 3, cmd_add_br, ""},
1254 {"del-br", 1, 1, cmd_del_br, "--if-exists"},
1255 {"list-br", 0, 0, cmd_list_br, ""},
1256 {"br-exists", 1, 1, cmd_br_exists, ""},
1257 {"br-to-vlan", 1, 1, cmd_br_to_vlan, ""},
1258 {"br-to-parent", 1, 1, cmd_br_to_parent, ""},
1259 {"br-set-external-id", 2, 3, cmd_br_set_external_id, ""},
1260 {"br-get-external-id", 1, 2, cmd_br_get_external_id, ""},
1262 /* Port commands. */
1263 {"list-ports", 1, 1, cmd_list_ports, ""},
1264 {"add-port", 2, 2, cmd_add_port, ""},
1265 {"add-bond", 4, INT_MAX, cmd_add_bond, ""},
1266 {"del-port", 1, 2, cmd_del_port, "--if-exists"},
1267 {"port-to-br", 1, 1, cmd_port_to_br, ""},
1268 {"port-set-external-id", 2, 3, cmd_port_set_external_id, ""},
1269 {"port-get-external-id", 1, 2, cmd_port_get_external_id, ""},
1271 /* Interface commands. */
1272 {"list-ifaces", 1, 1, cmd_list_ifaces, ""},
1273 {"iface-to-br", 1, 1, cmd_iface_to_br, ""},
1274 {"iface-set-external-id", 2, 3, cmd_iface_set_external_id, ""},
1275 {"iface-get-external-id", 1, 2, cmd_iface_get_external_id, ""},
1278 const struct vsctl_command *p;
1281 shash_init(&ctx->options);
1282 for (i = 0; i < argc; i++) {
1283 if (argv[i][0] != '-') {
1286 if (!shash_add_once(&ctx->options, argv[i], NULL)) {
1287 ovs_fatal(0, "'%s' option specified multiple times", argv[i]);
1291 ovs_fatal(0, "missing command name");
1294 for (p = all_commands; p < &all_commands[ARRAY_SIZE(all_commands)]; p++) {
1295 if (!strcmp(p->name, argv[i])) {
1296 struct shash_node *node;
1299 SHASH_FOR_EACH (node, &ctx->options) {
1300 const char *s = strstr(p->options, node->name);
1301 int end = s ? s[strlen(node->name)] : EOF;
1302 if (end != ',' && end != ' ' && end != '\0') {
1303 ovs_fatal(0, "'%s' command has no '%s' option",
1304 argv[i], node->name);
1308 n_arg = argc - i - 1;
1309 if (n_arg < p->min_args) {
1310 ovs_fatal(0, "'%s' command requires at least %d arguments",
1311 p->name, p->min_args);
1312 } else if (n_arg > p->max_args) {
1313 ovs_fatal(0, "'%s' command takes at most %d arguments",
1314 p->name, p->max_args);
1316 ctx->argc = n_arg + 1;
1317 ctx->argv = &argv[i];
1323 ovs_fatal(0, "unknown command '%s'; use --help for help", argv[0]);
1327 check_vsctl_command(int argc, char *argv[])
1329 struct vsctl_context ctx;
1331 get_vsctl_handler(argc, argv, &ctx);
1332 shash_destroy(&ctx.options);
1336 run_vsctl_command(int argc, char *argv[],
1337 const struct ovsrec_open_vswitch *ovs, struct ds *output)
1339 vsctl_handler_func *function;
1340 struct vsctl_context ctx;
1342 function = get_vsctl_handler(argc, argv, &ctx);
1344 ds_init(&ctx.output);
1346 *output = ctx.output;
1347 shash_destroy(&ctx.options);