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 /* --dry-run: Do not commit any changes. */
51 /* --timeout: Time to wait for a connection to 'db'. */
52 static int timeout = 5;
54 static void vsctl_fatal(const char *, ...) PRINTF_FORMAT(1, 2) NO_RETURN;
55 static char *default_db(void);
56 static void usage(void) NO_RETURN;
57 static void parse_options(int argc, char *argv[]);
59 static void check_vsctl_command(int argc, char *argv[]);
60 static void do_vsctl(int argc, char *argv[], struct ovsdb_idl *idl);
63 main(int argc, char *argv[])
65 struct ovsdb_idl *idl;
68 int start, n_commands;
72 set_program_name(argv[0]);
73 signal(SIGPIPE, SIG_IGN);
76 vlog_set_levels(VLM_ANY_MODULE, VLF_CONSOLE, VLL_WARN);
77 vlog_set_levels(VLM_reconnect, VLF_ANY_FACILITY, VLL_WARN);
78 parse_options(argc, argv);
84 /* Log our arguments. This is often valuable for debugging systems. */
86 for (i = 1; i < argc; i++) {
87 ds_put_format(&args, " %s", argv[i]);
89 VLOG_INFO("Called as%s", ds_cstr(&args));
92 /* Do basic command syntax checking. */
94 for (start = i = optind; i <= argc; i++) {
95 if (i == argc || !strcmp(argv[i], "--")) {
97 check_vsctl_command(i - start, &argv[start]);
104 vsctl_fatal("missing command name (use --help for help)");
107 /* Now execute the commands. */
108 idl = ovsdb_idl_create(db, &ovsrec_idl_class);
109 seqno = ovsdb_idl_get_seqno(idl);
112 unsigned int new_seqno;
115 new_seqno = ovsdb_idl_get_seqno(idl);
116 if (new_seqno != seqno) {
118 vsctl_fatal("too many database inconsistency failures");
120 do_vsctl(argc - optind, argv + optind, idl);
130 vsctl_fatal(const char *format, ...)
135 va_start(args, format);
136 message = xvasprintf(format, args);
139 vlog_set_levels(VLM_vsctl, VLF_CONSOLE, VLL_EMER);
140 VLOG_ERR("%s", message);
141 ovs_fatal(0, "%s", message);
145 parse_options(int argc, char *argv[])
148 OPT_DB = UCHAR_MAX + 1,
154 static struct option long_options[] = {
155 {"db", required_argument, 0, OPT_DB},
156 {"no-syslog", no_argument, 0, OPT_NO_SYSLOG},
157 {"no-wait", no_argument, 0, OPT_NO_WAIT},
158 {"dry-run", no_argument, 0, OPT_DRY_RUN},
159 {"oneline", no_argument, 0, OPT_ONELINE},
160 {"timeout", required_argument, 0, 't'},
161 {"verbose", optional_argument, 0, 'v'},
162 {"help", no_argument, 0, 'h'},
163 {"version", no_argument, 0, 'V'},
169 unsigned long int timeout;
172 c = getopt_long(argc, argv, "+v::hVt:", long_options, NULL);
187 vlog_set_levels(VLM_vsctl, VLF_SYSLOG, VLL_WARN);
191 /* XXX not yet implemented */
202 OVS_PRINT_VERSION(0, 0);
206 timeout = strtoul(optarg, NULL, 10);
208 ovs_fatal(0, "value %s on -t or --timeout is invalid",
214 vlog_set_verbosity(optarg);
233 printf("%s: ovs-vswitchd management utility\n"
234 "usage: %s [OPTIONS] COMMAND [ARG...]\n",
235 program_name, program_name);
236 printf("\nBridge commands:\n"
238 "create a new bridge named BRIDGE\n"
239 " add-br BRIDGE PARENT VLAN "
240 "create new fake bridge BRIDGE in PARENT on VLAN\n"
242 "delete BRIDGE and all of its ports\n"
244 "print the names of all the bridges\n"
246 "test whether BRIDGE exists\n"
247 " br-to-vlan BRIDGE "
248 "print the VLAN which BRIDGE is on\n"
249 " br-to-parent BRIDGE "
250 "print the parent of BRIDGE\n"
251 " br-set-external-id BRIDGE KEY VALUE"
252 " set KEY on BRIDGE to VALUE\n"
253 " br-set-external-id BRIDGE KEY"
254 " unset KEY on BRIDGE\n"
255 " br-get-external-id BRIDGE KEY"
256 " print value of KEY on BRIDGE\n"
257 " br-get-external-id BRIDGE"
258 " list key-value pairs on BRIDGE\n"
260 printf("\nPort commands:\n"
261 " list-ports BRIDGE "
262 "print the names of all the ports on BRIDGE\n"
263 " add-port BRIDGE PORT "
264 "add network device PORT to BRIDGE\n"
265 " add-bond BRIDGE PORT IFACE... "
266 "add new bonded port PORT in BRIDGE from IFACES\n"
267 " del-port [BRIDGE] PORT "
268 "delete PORT (which may be bonded) from BRIDGE\n"
270 "print name of bridge that contains PORT\n"
271 " port-set-external-id PORT KEY VALUE"
272 " set KEY on PORT to VALUE\n"
273 " port-set-external-id PORT KEY"
274 " unset KEY on PORT\n"
275 " port-get-external-id PORT KEY"
276 " print value of KEY on PORT\n"
277 " port-get-external-id PORT"
278 " list key-value pairs on PORT\n"
279 "A bond is considered to be a single port.\n"
281 printf("\nInterface commands (a bond consists of multiple interfaces):\n"
282 " list-ifaces BRIDGE "
283 "print the names of all the interfaces on BRIDGE\n"
284 " iface-to-br IFACE "
285 "print name of bridge that contains IFACE\n"
286 " iface-set-external-id IFACE KEY VALUE"
287 " set KEY on IFACE to VALUE\n"
288 " iface-set-external-id IFACE KEY"
289 " unset KEY on IFACE\n"
290 " iface-get-external-id IFACE KEY"
291 " print value of KEY on IFACE\n"
292 " iface-get-external-id IFACE"
293 " list key-value pairs on IFACE\n"
295 printf("\nOptions:\n"
297 "connect to DATABASE\n"
301 "print exactly one line of output per command\n",
304 printf("\nOther options:\n"
306 "display this help message\n"
308 "display version information\n");
317 def = xasprintf("unix:%s/ovsdb-server", ovs_rundir);
322 struct vsctl_context {
325 const struct ovsrec_open_vswitch *ovs;
327 struct shash options;
330 struct vsctl_bridge {
331 struct ovsrec_bridge *br_cfg;
333 struct vsctl_bridge *parent;
338 struct ovsrec_port *port_cfg;
339 struct vsctl_bridge *bridge;
343 struct ovsrec_interface *iface_cfg;
344 struct vsctl_port *port;
348 struct shash bridges;
353 static struct ovsdb_idl_txn *
354 txn_from_openvswitch(const struct ovsrec_open_vswitch *ovs)
356 return ovsdb_idl_txn_get(&ovs->header_);
359 static struct vsctl_bridge *
360 add_bridge(struct vsctl_info *b,
361 struct ovsrec_bridge *br_cfg, const char *name,
362 struct vsctl_bridge *parent, int vlan)
364 struct vsctl_bridge *br = xmalloc(sizeof *br);
366 br->name = xstrdup(name);
369 shash_add(&b->bridges, br->name, br);
374 port_is_fake_bridge(const struct ovsrec_port *port_cfg)
376 return (port_cfg->fake_bridge
378 && *port_cfg->tag >= 1 && *port_cfg->tag <= 4095);
381 static struct vsctl_bridge *
382 find_vlan_bridge(struct vsctl_info *info,
383 struct vsctl_bridge *parent, int vlan)
385 struct shash_node *node;
387 SHASH_FOR_EACH (node, &info->bridges) {
388 struct vsctl_bridge *br = node->data;
389 if (br->parent == parent && br->vlan == vlan) {
398 free_info(struct vsctl_info *info)
400 struct shash_node *node;
402 SHASH_FOR_EACH (node, &info->bridges) {
403 struct vsctl_bridge *bridge = node->data;
407 shash_destroy(&info->bridges);
409 SHASH_FOR_EACH (node, &info->ports) {
410 struct vsctl_port *port = node->data;
413 shash_destroy(&info->ports);
415 SHASH_FOR_EACH (node, &info->ifaces) {
416 struct vsctl_iface *iface = node->data;
419 shash_destroy(&info->ifaces);
423 get_info(const struct ovsrec_open_vswitch *ovs, struct vsctl_info *info)
425 struct shash bridges, ports;
428 shash_init(&info->bridges);
429 shash_init(&info->ports);
430 shash_init(&info->ifaces);
432 shash_init(&bridges);
434 for (i = 0; i < ovs->n_bridges; i++) {
435 struct ovsrec_bridge *br_cfg = ovs->bridges[i];
436 struct vsctl_bridge *br;
439 if (!shash_add_once(&bridges, br_cfg->name, NULL)) {
440 VLOG_WARN("%s: database contains duplicate bridge name",
444 br = add_bridge(info, br_cfg, br_cfg->name, NULL, 0);
449 for (j = 0; j < br_cfg->n_ports; j++) {
450 struct ovsrec_port *port_cfg = br_cfg->ports[j];
452 if (!shash_add_once(&ports, port_cfg->name, NULL)) {
453 VLOG_WARN("%s: database contains duplicate port name",
458 if (port_is_fake_bridge(port_cfg)
459 && shash_add_once(&bridges, port_cfg->name, NULL)) {
460 add_bridge(info, NULL, port_cfg->name, br, *port_cfg->tag);
464 shash_destroy(&bridges);
465 shash_destroy(&ports);
467 shash_init(&bridges);
469 for (i = 0; i < ovs->n_bridges; i++) {
470 struct ovsrec_bridge *br_cfg = ovs->bridges[i];
471 struct vsctl_bridge *br;
474 if (!shash_add_once(&bridges, br_cfg->name, NULL)) {
477 br = shash_find_data(&info->bridges, br_cfg->name);
478 for (j = 0; j < br_cfg->n_ports; j++) {
479 struct ovsrec_port *port_cfg = br_cfg->ports[j];
480 struct vsctl_port *port;
483 if (!shash_add_once(&ports, port_cfg->name, NULL)) {
487 if (port_is_fake_bridge(port_cfg)
488 && !shash_add_once(&bridges, port_cfg->name, NULL)) {
492 port = xmalloc(sizeof *port);
493 port->port_cfg = port_cfg;
495 && *port_cfg->tag >= 1 && *port_cfg->tag <= 4095) {
496 port->bridge = find_vlan_bridge(info, br, *port_cfg->tag);
503 shash_add(&info->ports, port_cfg->name, port);
505 for (k = 0; k < port_cfg->n_interfaces; k++) {
506 struct ovsrec_interface *iface_cfg = port_cfg->interfaces[k];
507 struct vsctl_iface *iface;
509 if (shash_find(&info->ifaces, iface_cfg->name)) {
510 VLOG_WARN("%s: database contains duplicate interface name",
515 iface = xmalloc(sizeof *iface);
516 iface->iface_cfg = iface_cfg;
518 shash_add(&info->ifaces, iface_cfg->name, iface);
522 shash_destroy(&bridges);
523 shash_destroy(&ports);
527 check_conflicts(struct vsctl_info *info, const char *name,
530 struct vsctl_iface *iface;
531 struct vsctl_port *port;
533 if (shash_find(&info->bridges, name)) {
534 vsctl_fatal("%s because a bridge named %s already exists",
538 port = shash_find_data(&info->ports, name);
540 vsctl_fatal("%s because a port named %s already exists on "
541 "bridge %s", msg, name, port->bridge->name);
544 iface = shash_find_data(&info->ifaces, name);
546 vsctl_fatal("%s because an interface named %s already exists "
547 "on bridge %s", msg, name, iface->port->bridge->name);
553 static struct vsctl_bridge *
554 find_bridge(struct vsctl_info *info, const char *name, bool must_exist)
556 struct vsctl_bridge *br = shash_find_data(&info->bridges, name);
557 if (must_exist && !br) {
558 vsctl_fatal("no bridge named %s", name);
563 static struct vsctl_port *
564 find_port(struct vsctl_info *info, const char *name, bool must_exist)
566 struct vsctl_port *port = shash_find_data(&info->ports, name);
567 if (port && !strcmp(name, port->bridge->name)) {
570 if (must_exist && !port) {
571 vsctl_fatal("no port named %s", name);
576 static struct vsctl_iface *
577 find_iface(struct vsctl_info *info, const char *name, bool must_exist)
579 struct vsctl_iface *iface = shash_find_data(&info->ifaces, name);
580 if (iface && !strcmp(name, iface->port->bridge->name)) {
583 if (must_exist && !iface) {
584 vsctl_fatal("no interface named %s", name);
590 bridge_insert_port(struct ovsrec_bridge *br, struct ovsrec_port *port)
592 struct ovsrec_port **ports;
595 ports = xmalloc(sizeof *br->ports * (br->n_ports + 1));
596 for (i = 0; i < br->n_ports; i++) {
597 ports[i] = br->ports[i];
599 ports[br->n_ports] = port;
600 ovsrec_bridge_set_ports(br, ports, br->n_ports + 1);
605 bridge_delete_port(struct ovsrec_bridge *br, struct ovsrec_port *port)
607 struct ovsrec_port **ports;
610 ports = xmalloc(sizeof *br->ports * br->n_ports);
611 for (i = n = 0; i < br->n_ports; i++) {
612 if (br->ports[i] != port) {
613 ports[n++] = br->ports[i];
616 ovsrec_bridge_set_ports(br, ports, n);
621 ovs_insert_bridge(const struct ovsrec_open_vswitch *ovs,
622 struct ovsrec_bridge *bridge)
624 struct ovsrec_bridge **bridges;
627 bridges = xmalloc(sizeof *ovs->bridges * (ovs->n_bridges + 1));
628 for (i = 0; i < ovs->n_bridges; i++) {
629 bridges[i] = ovs->bridges[i];
631 bridges[ovs->n_bridges] = bridge;
632 ovsrec_open_vswitch_set_bridges(ovs, bridges, ovs->n_bridges + 1);
637 ovs_delete_bridge(const struct ovsrec_open_vswitch *ovs,
638 struct ovsrec_bridge *bridge)
640 struct ovsrec_bridge **bridges;
643 bridges = xmalloc(sizeof *ovs->bridges * ovs->n_bridges);
644 for (i = n = 0; i < ovs->n_bridges; i++) {
645 if (ovs->bridges[i] != bridge) {
646 bridges[n++] = ovs->bridges[i];
649 ovsrec_open_vswitch_set_bridges(ovs, bridges, n);
654 cmd_init(struct vsctl_context *ctx UNUSED)
659 cmd_add_br(struct vsctl_context *ctx)
661 const char *br_name = ctx->argv[1];
662 struct vsctl_info info;
664 get_info(ctx->ovs, &info);
665 check_conflicts(&info, br_name,
666 xasprintf("cannot create a bridge named %s", br_name));
668 if (ctx->argc == 2) {
669 struct ovsrec_bridge *br;
670 struct ovsrec_port *port;
671 struct ovsrec_interface *iface;
673 iface = ovsrec_interface_insert(txn_from_openvswitch(ctx->ovs));
674 ovsrec_interface_set_name(iface, br_name);
676 port = ovsrec_port_insert(txn_from_openvswitch(ctx->ovs));
677 ovsrec_port_set_name(port, br_name);
678 ovsrec_port_set_interfaces(port, &iface, 1);
680 br = ovsrec_bridge_insert(txn_from_openvswitch(ctx->ovs));
681 ovsrec_bridge_set_name(br, br_name);
682 ovsrec_bridge_set_ports(br, &port, 1);
684 ovs_insert_bridge(ctx->ovs, br);
685 } else if (ctx->argc == 3) {
686 vsctl_fatal("'%s' command takes exactly 1 or 3 arguments",
688 } else if (ctx->argc == 4) {
689 const char *parent_name = ctx->argv[2];
690 int vlan = atoi(ctx->argv[3]);
691 struct ovsrec_bridge *br;
692 struct vsctl_bridge *parent;
693 struct ovsrec_port *port;
694 struct ovsrec_interface *iface;
697 if (vlan < 1 || vlan > 4095) {
698 vsctl_fatal("%s: vlan must be between 1 and 4095", ctx->argv[0]);
701 parent = find_bridge(&info, parent_name, false);
702 if (parent && parent->vlan) {
703 vsctl_fatal("cannot create brdige with fake bridge as parent");
706 vsctl_fatal("parent bridge %s does not exist", parent_name);
710 iface = ovsrec_interface_insert(txn_from_openvswitch(ctx->ovs));
711 ovsrec_interface_set_name(iface, br_name);
712 ovsrec_interface_set_type(iface, "internal");
714 port = ovsrec_port_insert(txn_from_openvswitch(ctx->ovs));
715 ovsrec_port_set_name(port, br_name);
716 ovsrec_port_set_interfaces(port, &iface, 1);
717 ovsrec_port_set_fake_bridge(port, true);
718 ovsrec_port_set_tag(port, &tag, 1);
720 bridge_insert_port(br, port);
729 del_port(struct vsctl_info *info, struct vsctl_port *port)
731 struct shash_node *node;
733 SHASH_FOR_EACH (node, &info->ifaces) {
734 struct vsctl_iface *iface = node->data;
735 if (iface->port == port) {
736 ovsrec_interface_delete(iface->iface_cfg);
739 ovsrec_port_delete(port->port_cfg);
741 bridge_delete_port((port->bridge->parent
742 ? port->bridge->parent->br_cfg
743 : port->bridge->br_cfg), port->port_cfg);
747 cmd_del_br(struct vsctl_context *ctx)
749 bool must_exist = !shash_find(&ctx->options, "--if-exists");
750 struct vsctl_bridge *bridge;
751 struct vsctl_info info;
753 get_info(ctx->ovs, &info);
754 bridge = find_bridge(&info, ctx->argv[1], must_exist);
756 struct shash_node *node;
758 SHASH_FOR_EACH (node, &info.ports) {
759 struct vsctl_port *port = node->data;
760 if (port->bridge == bridge
761 || !strcmp(port->port_cfg->name, bridge->name)) {
762 del_port(&info, port);
765 if (bridge->br_cfg) {
766 ovsrec_bridge_delete(bridge->br_cfg);
767 ovs_delete_bridge(ctx->ovs, bridge->br_cfg);
774 output_sorted(struct svec *svec, struct ds *output)
780 SVEC_FOR_EACH (i, name, svec) {
781 ds_put_format(output, "%s\n", name);
786 cmd_list_br(struct vsctl_context *ctx)
788 struct shash_node *node;
789 struct vsctl_info info;
792 get_info(ctx->ovs, &info);
795 SHASH_FOR_EACH (node, &info.bridges) {
796 struct vsctl_bridge *br = node->data;
797 svec_add(&bridges, br->name);
799 output_sorted(&bridges, &ctx->output);
800 svec_destroy(&bridges);
806 cmd_br_exists(struct vsctl_context *ctx)
808 struct vsctl_info info;
810 get_info(ctx->ovs, &info);
811 if (!find_bridge(&info, ctx->argv[1], false)) {
817 /* Returns true if 'b_prefix' (of length 'b_prefix_len') concatenated with 'b'
818 * equals 'a', false otherwise. */
820 key_matches(const char *a,
821 const char *b_prefix, size_t b_prefix_len, const char *b)
823 return !strncmp(a, b_prefix, b_prefix_len) && !strcmp(a + b_prefix_len, b);
827 set_external_id(char **old_keys, char **old_values, size_t old_n,
828 char *key, char *value,
829 char ***new_keysp, char ***new_valuesp, size_t *new_np)
836 new_keys = xmalloc(sizeof *new_keys * (old_n + 1));
837 new_values = xmalloc(sizeof *new_values * (old_n + 1));
839 for (i = 0; i < old_n; i++) {
840 if (strcmp(key, old_keys[i])) {
841 new_keys[new_n] = old_keys[i];
842 new_values[new_n] = old_values[i];
847 new_keys[new_n] = key;
848 new_values[new_n] = value;
851 *new_keysp = new_keys;
852 *new_valuesp = new_values;
857 cmd_br_set_external_id(struct vsctl_context *ctx)
859 struct vsctl_info info;
860 struct vsctl_bridge *bridge;
861 char **keys, **values;
864 get_info(ctx->ovs, &info);
865 bridge = find_bridge(&info, ctx->argv[1], true);
866 if (bridge->br_cfg) {
867 set_external_id(bridge->br_cfg->key_external_ids,
868 bridge->br_cfg->value_external_ids,
869 bridge->br_cfg->n_external_ids,
870 ctx->argv[2], ctx->argc >= 4 ? ctx->argv[3] : NULL,
872 ovsrec_bridge_set_external_ids(bridge->br_cfg, keys, values, n);
874 char *key = xasprintf("fake-bridge-%s", ctx->argv[2]);
875 struct vsctl_port *port = shash_find_data(&info.ports, ctx->argv[1]);
876 set_external_id(port->port_cfg->key_external_ids,
877 port->port_cfg->value_external_ids,
878 port->port_cfg->n_external_ids,
879 key, ctx->argc >= 4 ? ctx->argv[3] : NULL,
881 ovsrec_port_set_external_ids(port->port_cfg, keys, values, n);
891 get_external_id(char **keys, char **values, size_t n,
892 const char *prefix, const char *key,
895 size_t prefix_len = strlen(prefix);
900 for (i = 0; i < n; i++) {
901 if (!key && !strncmp(keys[i], prefix, prefix_len)) {
902 svec_add_nocopy(&svec, xasprintf("%s=%s",
903 keys[i] + prefix_len, values[i]));
904 } else if (key_matches(keys[i], prefix, prefix_len, key)) {
905 svec_add(&svec, values[i]);
909 output_sorted(&svec, output);
914 cmd_br_get_external_id(struct vsctl_context *ctx)
916 struct vsctl_info info;
917 struct vsctl_bridge *bridge;
919 get_info(ctx->ovs, &info);
920 bridge = find_bridge(&info, ctx->argv[1], true);
921 if (bridge->br_cfg) {
922 get_external_id(bridge->br_cfg->key_external_ids,
923 bridge->br_cfg->value_external_ids,
924 bridge->br_cfg->n_external_ids,
925 "", ctx->argc >= 3 ? ctx->argv[2] : NULL,
928 struct vsctl_port *port = shash_find_data(&info.ports, ctx->argv[1]);
929 get_external_id(port->port_cfg->key_external_ids,
930 port->port_cfg->value_external_ids,
931 port->port_cfg->n_external_ids,
932 "fake-bridge-", ctx->argc >= 3 ? ctx->argv[2] : NULL, &ctx->output);
939 cmd_list_ports(struct vsctl_context *ctx)
941 struct vsctl_bridge *br;
942 struct shash_node *node;
943 struct vsctl_info info;
946 get_info(ctx->ovs, &info);
947 br = find_bridge(&info, ctx->argv[1], true);
950 SHASH_FOR_EACH (node, &info.ports) {
951 struct vsctl_port *port = node->data;
953 if (strcmp(port->port_cfg->name, br->name) && br == port->bridge) {
954 svec_add(&ports, port->port_cfg->name);
957 output_sorted(&ports, &ctx->output);
958 svec_destroy(&ports);
964 add_port(const struct ovsrec_open_vswitch *ovs,
965 const char *br_name, const char *port_name,
966 char *iface_names[], int n_ifaces)
968 struct vsctl_info info;
969 struct vsctl_bridge *bridge;
970 struct ovsrec_interface **ifaces;
971 struct ovsrec_port *port;
974 get_info(ovs, &info);
975 check_conflicts(&info, port_name,
976 xasprintf("cannot create a port named %s", port_name));
977 /* XXX need to check for conflicts on interfaces too */
978 bridge = find_bridge(&info, br_name, true);
980 ifaces = xmalloc(n_ifaces * sizeof *ifaces);
981 for (i = 0; i < n_ifaces; i++) {
982 ifaces[i] = ovsrec_interface_insert(txn_from_openvswitch(ovs));
983 ovsrec_interface_set_name(ifaces[i], iface_names[i]);
986 port = ovsrec_port_insert(txn_from_openvswitch(ovs));
987 ovsrec_port_set_name(port, port_name);
988 ovsrec_port_set_interfaces(port, ifaces, n_ifaces);
992 int64_t tag = bridge->vlan;
993 ovsrec_port_set_tag(port, &tag, 1);
996 bridge_insert_port((bridge->parent ? bridge->parent->br_cfg
997 : bridge->br_cfg), port);
1003 cmd_add_port(struct vsctl_context *ctx)
1005 add_port(ctx->ovs, ctx->argv[1], ctx->argv[2], &ctx->argv[2], 1);
1009 cmd_add_bond(struct vsctl_context *ctx)
1011 add_port(ctx->ovs, ctx->argv[1], ctx->argv[2], &ctx->argv[3], ctx->argc - 3);
1015 cmd_del_port(struct vsctl_context *ctx)
1017 bool must_exist = !shash_find(&ctx->options, "--if-exists");
1018 struct vsctl_info info;
1020 get_info(ctx->ovs, &info);
1021 if (ctx->argc == 2) {
1022 struct vsctl_port *port = find_port(&info, ctx->argv[1], must_exist);
1024 del_port(&info, port);
1026 } else if (ctx->argc == 3) {
1027 struct vsctl_bridge *bridge = find_bridge(&info, ctx->argv[1], true);
1028 struct vsctl_port *port = find_port(&info, ctx->argv[2], must_exist);
1031 if (port->bridge == bridge) {
1032 del_port(&info, port);
1033 } else if (port->bridge->parent == bridge) {
1034 vsctl_fatal("bridge %s does not have a port %s (although its "
1035 "parent bridge %s does)",
1036 ctx->argv[1], ctx->argv[2], bridge->parent->name);
1038 vsctl_fatal("bridge %s does not have a port %s",
1039 ctx->argv[1], ctx->argv[2]);
1047 cmd_port_to_br(struct vsctl_context *ctx)
1049 struct vsctl_port *port;
1050 struct vsctl_info info;
1052 get_info(ctx->ovs, &info);
1053 port = find_port(&info, ctx->argv[1], true);
1054 ds_put_format(&ctx->output, "%s\n", port->bridge->name);
1059 cmd_port_set_external_id(struct vsctl_context *ctx)
1061 struct vsctl_info info;
1062 struct vsctl_port *port;
1063 char **keys, **values;
1066 get_info(ctx->ovs, &info);
1067 port = find_port(&info, ctx->argv[1], true);
1068 set_external_id(port->port_cfg->key_external_ids,
1069 port->port_cfg->value_external_ids,
1070 port->port_cfg->n_external_ids,
1071 ctx->argv[2], ctx->argc >= 4 ? ctx->argv[3] : NULL,
1072 &keys, &values, &n);
1073 ovsrec_port_set_external_ids(port->port_cfg, keys, values, n);
1081 cmd_port_get_external_id(struct vsctl_context *ctx)
1083 struct vsctl_info info;
1084 struct vsctl_port *port;
1086 get_info(ctx->ovs, &info);
1087 port = find_port(&info, ctx->argv[1], true);
1088 get_external_id(port->port_cfg->key_external_ids,
1089 port->port_cfg->value_external_ids,
1090 port->port_cfg->n_external_ids,
1091 "", ctx->argc >= 3 ? ctx->argv[2] : NULL, &ctx->output);
1096 cmd_br_to_vlan(struct vsctl_context *ctx)
1098 struct vsctl_bridge *bridge;
1099 struct vsctl_info info;
1101 get_info(ctx->ovs, &info);
1102 bridge = find_bridge(&info, ctx->argv[1], true);
1103 ds_put_format(&ctx->output, "%d\n", bridge->vlan);
1108 cmd_br_to_parent(struct vsctl_context *ctx)
1110 struct vsctl_bridge *bridge;
1111 struct vsctl_info info;
1113 get_info(ctx->ovs, &info);
1114 bridge = find_bridge(&info, ctx->argv[1], true);
1115 if (bridge->parent) {
1116 bridge = bridge->parent;
1118 ds_put_format(&ctx->output, "%s\n", bridge->name);
1123 cmd_list_ifaces(struct vsctl_context *ctx)
1125 struct vsctl_bridge *br;
1126 struct shash_node *node;
1127 struct vsctl_info info;
1130 get_info(ctx->ovs, &info);
1131 br = find_bridge(&info, ctx->argv[1], true);
1134 SHASH_FOR_EACH (node, &info.ifaces) {
1135 struct vsctl_iface *iface = node->data;
1137 if (strcmp(iface->iface_cfg->name, br->name)
1138 && br == iface->port->bridge) {
1139 svec_add(&ifaces, iface->iface_cfg->name);
1142 output_sorted(&ifaces, &ctx->output);
1143 svec_destroy(&ifaces);
1149 cmd_iface_to_br(struct vsctl_context *ctx)
1151 struct vsctl_iface *iface;
1152 struct vsctl_info info;
1154 get_info(ctx->ovs, &info);
1155 iface = find_iface(&info, ctx->argv[1], true);
1156 ds_put_format(&ctx->output, "%s\n", iface->port->bridge->name);
1161 cmd_iface_set_external_id(struct vsctl_context *ctx)
1163 struct vsctl_info info;
1164 struct vsctl_iface *iface;
1165 char **keys, **values;
1168 get_info(ctx->ovs, &info);
1169 iface = find_iface(&info, ctx->argv[1], true);
1170 set_external_id(iface->iface_cfg->key_external_ids,
1171 iface->iface_cfg->value_external_ids,
1172 iface->iface_cfg->n_external_ids,
1173 ctx->argv[2], ctx->argc >= 4 ? ctx->argv[3] : NULL,
1174 &keys, &values, &n);
1175 ovsrec_interface_set_external_ids(iface->iface_cfg, keys, values, n);
1183 cmd_iface_get_external_id(struct vsctl_context *ctx)
1185 struct vsctl_info info;
1186 struct vsctl_iface *iface;
1188 get_info(ctx->ovs, &info);
1189 iface = find_iface(&info, ctx->argv[1], true);
1190 get_external_id(iface->iface_cfg->key_external_ids,
1191 iface->iface_cfg->value_external_ids,
1192 iface->iface_cfg->n_external_ids,
1193 "", ctx->argc >= 3 ? ctx->argv[2] : NULL, &ctx->output);
1197 typedef void vsctl_handler_func(struct vsctl_context *);
1199 struct vsctl_command {
1203 vsctl_handler_func *handler;
1204 const char *options;
1207 static void run_vsctl_command(int argc, char *argv[],
1208 const struct ovsrec_open_vswitch *ovs,
1212 do_vsctl(int argc, char *argv[], struct ovsdb_idl *idl)
1214 struct ovsdb_idl_txn *txn;
1215 const struct ovsrec_open_vswitch *ovs;
1216 enum ovsdb_idl_txn_status status;
1221 txn = ovsdb_idl_txn_create(idl);
1223 ovsdb_idl_txn_set_dry_run(txn);
1226 ovs = ovsrec_open_vswitch_first(idl);
1228 /* XXX add verification that table is empty */
1229 ovs = ovsrec_open_vswitch_insert(txn);
1232 output = xmalloc(argc * sizeof *output);
1234 for (start = i = 0; i <= argc; i++) {
1235 if (i == argc || !strcmp(argv[i], "--")) {
1237 ds_init(&output[n_output]);
1238 run_vsctl_command(i - start, &argv[start], ovs,
1239 &output[n_output++]);
1245 while ((status = ovsdb_idl_txn_commit(txn)) == TXN_INCOMPLETE) {
1247 ovsdb_idl_wait(idl);
1248 ovsdb_idl_txn_wait(txn);
1251 ovsdb_idl_txn_destroy(txn);
1254 case TXN_INCOMPLETE:
1258 /* Should not happen--we never call ovsdb_idl_txn_abort(). */
1259 vsctl_fatal("transaction aborted");
1265 for (i = 0; i < n_output; i++) {
1266 ds_destroy(&output[i]);
1271 vsctl_fatal("transaction error");
1277 for (i = 0; i < n_output; i++) {
1278 struct ds *ds = &output[i];
1283 for (j = 0; j < ds->length; j++) {
1284 int c = ds->string[j];
1287 fputs("\\n", stdout);
1291 fputs("\\\\", stdout);
1300 fputs(ds_cstr(ds), stdout);
1306 static vsctl_handler_func *
1307 get_vsctl_handler(int argc, char *argv[], struct vsctl_context *ctx)
1309 static const struct vsctl_command all_commands[] = {
1310 /* Open vSwitch commands. */
1311 {"init", 0, 0, cmd_init, ""},
1313 /* Bridge commands. */
1314 {"add-br", 1, 3, cmd_add_br, ""},
1315 {"del-br", 1, 1, cmd_del_br, "--if-exists"},
1316 {"list-br", 0, 0, cmd_list_br, ""},
1317 {"br-exists", 1, 1, cmd_br_exists, ""},
1318 {"br-to-vlan", 1, 1, cmd_br_to_vlan, ""},
1319 {"br-to-parent", 1, 1, cmd_br_to_parent, ""},
1320 {"br-set-external-id", 2, 3, cmd_br_set_external_id, ""},
1321 {"br-get-external-id", 1, 2, cmd_br_get_external_id, ""},
1323 /* Port commands. */
1324 {"list-ports", 1, 1, cmd_list_ports, ""},
1325 {"add-port", 2, 2, cmd_add_port, ""},
1326 {"add-bond", 4, INT_MAX, cmd_add_bond, ""},
1327 {"del-port", 1, 2, cmd_del_port, "--if-exists"},
1328 {"port-to-br", 1, 1, cmd_port_to_br, ""},
1329 {"port-set-external-id", 2, 3, cmd_port_set_external_id, ""},
1330 {"port-get-external-id", 1, 2, cmd_port_get_external_id, ""},
1332 /* Interface commands. */
1333 {"list-ifaces", 1, 1, cmd_list_ifaces, ""},
1334 {"iface-to-br", 1, 1, cmd_iface_to_br, ""},
1335 {"iface-set-external-id", 2, 3, cmd_iface_set_external_id, ""},
1336 {"iface-get-external-id", 1, 2, cmd_iface_get_external_id, ""},
1339 const struct vsctl_command *p;
1342 shash_init(&ctx->options);
1343 for (i = 0; i < argc; i++) {
1344 if (argv[i][0] != '-') {
1347 if (!shash_add_once(&ctx->options, argv[i], NULL)) {
1348 vsctl_fatal("'%s' option specified multiple times", argv[i]);
1352 vsctl_fatal("missing command name");
1355 for (p = all_commands; p < &all_commands[ARRAY_SIZE(all_commands)]; p++) {
1356 if (!strcmp(p->name, argv[i])) {
1357 struct shash_node *node;
1360 SHASH_FOR_EACH (node, &ctx->options) {
1361 const char *s = strstr(p->options, node->name);
1362 int end = s ? s[strlen(node->name)] : EOF;
1363 if (end != ',' && end != ' ' && end != '\0') {
1364 vsctl_fatal("'%s' command has no '%s' option",
1365 argv[i], node->name);
1369 n_arg = argc - i - 1;
1370 if (n_arg < p->min_args) {
1371 vsctl_fatal("'%s' command requires at least %d arguments",
1372 p->name, p->min_args);
1373 } else if (n_arg > p->max_args) {
1374 vsctl_fatal("'%s' command takes at most %d arguments",
1375 p->name, p->max_args);
1377 ctx->argc = n_arg + 1;
1378 ctx->argv = &argv[i];
1384 vsctl_fatal("unknown command '%s'; use --help for help", argv[i]);
1388 check_vsctl_command(int argc, char *argv[])
1390 struct vsctl_context ctx;
1392 get_vsctl_handler(argc, argv, &ctx);
1393 shash_destroy(&ctx.options);
1397 run_vsctl_command(int argc, char *argv[],
1398 const struct ovsrec_open_vswitch *ovs, struct ds *output)
1400 vsctl_handler_func *function;
1401 struct vsctl_context ctx;
1403 function = get_vsctl_handler(argc, argv, &ctx);
1405 ds_init(&ctx.output);
1407 *output = ctx.output;
1408 shash_destroy(&ctx.options);