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 static void vsctl_fatal(const char *, ...) PRINTF_FORMAT(1, 2) NO_RETURN;
52 static char *default_db(void);
53 static void usage(void) NO_RETURN;
54 static void parse_options(int argc, char *argv[]);
56 static void check_vsctl_command(int argc, char *argv[]);
57 static void do_vsctl(int argc, char *argv[], struct ovsdb_idl *idl);
60 main(int argc, char *argv[])
62 struct ovsdb_idl *idl;
65 int start, n_commands;
69 set_program_name(argv[0]);
70 signal(SIGPIPE, SIG_IGN);
73 vlog_set_levels(VLM_ANY_MODULE, VLF_CONSOLE, VLL_WARN);
74 vlog_set_levels(VLM_reconnect, VLF_ANY_FACILITY, VLL_WARN);
75 parse_options(argc, argv);
77 /* Log our arguments. This is often valuable for debugging systems. */
79 for (i = 1; i < argc; i++) {
80 ds_put_format(&args, " %s", argv[i]);
82 VLOG_INFO("Called as%s", ds_cstr(&args));
85 /* Do basic command syntax checking. */
87 for (start = i = optind; i <= argc; i++) {
88 if (i == argc || !strcmp(argv[i], "--")) {
90 check_vsctl_command(i - start, &argv[start]);
97 vsctl_fatal("missing command name (use --help for help)");
100 /* Now execute the commands. */
101 idl = ovsdb_idl_create(db, &ovsrec_idl_class);
102 seqno = ovsdb_idl_get_seqno(idl);
105 unsigned int new_seqno;
108 new_seqno = ovsdb_idl_get_seqno(idl);
109 if (new_seqno != seqno) {
111 vsctl_fatal("too many database inconsistency failures");
113 do_vsctl(argc - optind, argv + optind, idl);
123 vsctl_fatal(const char *format, ...)
128 va_start(args, format);
129 message = xvasprintf(format, args);
132 vlog_set_levels(VLM_vsctl, VLF_CONSOLE, VLL_EMER);
133 VLOG_ERR("%s", message);
134 ovs_fatal(0, "%s", message);
138 parse_options(int argc, char *argv[])
141 OPT_DB = UCHAR_MAX + 1,
147 static struct option long_options[] = {
148 {"db", required_argument, 0, OPT_DB},
149 {"no-syslog", no_argument, 0, OPT_NO_SYSLOG},
150 {"no-wait", no_argument, 0, OPT_NO_WAIT},
151 {"dry-run", no_argument, 0, OPT_DRY_RUN},
152 {"oneline", no_argument, 0, OPT_ONELINE},
153 {"timeout", required_argument, 0, 't'},
154 {"verbose", optional_argument, 0, 'v'},
155 {"help", no_argument, 0, 'h'},
156 {"version", no_argument, 0, 'V'},
162 unsigned long int timeout;
165 c = getopt_long(argc, argv, "+v::hVt:", long_options, NULL);
180 vlog_set_levels(VLM_vsctl, VLF_SYSLOG, VLL_WARN);
184 /* XXX not yet implemented */
195 OVS_PRINT_VERSION(0, 0);
199 timeout = strtoul(optarg, NULL, 10);
201 ovs_fatal(0, "value %s on -t or --timeout is not at least 1",
209 vlog_set_verbosity(optarg);
228 printf("%s: ovs-vswitchd management utility\n"
229 "usage: %s [OPTIONS] COMMAND [ARG...]\n",
230 program_name, program_name);
231 printf("\nBridge commands:\n"
233 "create a new bridge named BRIDGE\n"
234 " add-br BRIDGE PARENT VLAN "
235 "create new fake bridge BRIDGE in PARENT on VLAN\n"
237 "delete BRIDGE and all of its ports\n"
239 "print the names of all the bridges\n"
241 "test whether BRIDGE exists\n"
242 " br-to-vlan BRIDGE "
243 "print the VLAN which BRIDGE is on\n"
244 " br-to-parent BRIDGE "
245 "print the parent of BRIDGE\n"
246 " br-set-external-id BRIDGE KEY VALUE"
247 " set KEY on BRIDGE to VALUE\n"
248 " br-set-external-id BRIDGE KEY"
249 " unset KEY on BRIDGE\n"
250 " br-get-external-id BRIDGE KEY"
251 " print value of KEY on BRIDGE\n"
252 " br-get-external-id BRIDGE"
253 " list key-value pairs on BRIDGE\n"
255 printf("\nPort commands:\n"
256 " list-ports BRIDGE "
257 "print the names of all the ports on BRIDGE\n"
258 " add-port BRIDGE PORT "
259 "add network device PORT to BRIDGE\n"
260 " add-bond BRIDGE PORT IFACE... "
261 "add new bonded port PORT in BRIDGE from IFACES\n"
262 " del-port [BRIDGE] PORT "
263 "delete PORT (which may be bonded) from BRIDGE\n"
265 "print name of bridge that contains PORT\n"
266 " port-set-external-id PORT KEY VALUE"
267 " set KEY on PORT to VALUE\n"
268 " port-set-external-id PORT KEY"
269 " unset KEY on PORT\n"
270 " port-get-external-id PORT KEY"
271 " print value of KEY on PORT\n"
272 " port-get-external-id PORT"
273 " list key-value pairs on PORT\n"
274 "A bond is considered to be a single port.\n"
276 printf("\nInterface commands (a bond consists of multiple interfaces):\n"
277 " list-ifaces BRIDGE "
278 "print the names of all the interfaces on BRIDGE\n"
279 " iface-to-br IFACE "
280 "print name of bridge that contains IFACE\n"
281 " iface-set-external-id IFACE KEY VALUE"
282 " set KEY on IFACE to VALUE\n"
283 " iface-set-external-id IFACE KEY"
284 " unset KEY on IFACE\n"
285 " iface-get-external-id IFACE KEY"
286 " print value of KEY on IFACE\n"
287 " iface-get-external-id IFACE"
288 " list key-value pairs on IFACE\n"
290 printf("\nOptions:\n"
292 "connect to DATABASE\n"
296 "print exactly one line of output per command\n",
299 printf("\nOther options:\n"
301 "display this help message\n"
303 "display version information\n");
312 def = xasprintf("unix:%s/ovsdb-server", ovs_rundir);
317 struct vsctl_context {
320 const struct ovsrec_open_vswitch *ovs;
322 struct shash options;
325 struct vsctl_bridge {
326 struct ovsrec_bridge *br_cfg;
328 struct vsctl_bridge *parent;
333 struct ovsrec_port *port_cfg;
334 struct vsctl_bridge *bridge;
338 struct ovsrec_interface *iface_cfg;
339 struct vsctl_port *port;
343 struct shash bridges;
348 static struct ovsdb_idl_txn *
349 txn_from_openvswitch(const struct ovsrec_open_vswitch *ovs)
351 return ovsdb_idl_txn_get(&ovs->header_);
354 static struct vsctl_bridge *
355 add_bridge(struct vsctl_info *b,
356 struct ovsrec_bridge *br_cfg, const char *name,
357 struct vsctl_bridge *parent, int vlan)
359 struct vsctl_bridge *br = xmalloc(sizeof *br);
361 br->name = xstrdup(name);
364 shash_add(&b->bridges, br->name, br);
369 port_is_fake_bridge(const struct ovsrec_port *port_cfg)
371 return (port_cfg->fake_bridge
373 && *port_cfg->tag >= 1 && *port_cfg->tag <= 4095);
376 static struct vsctl_bridge *
377 find_vlan_bridge(struct vsctl_info *info,
378 struct vsctl_bridge *parent, int vlan)
380 struct shash_node *node;
382 SHASH_FOR_EACH (node, &info->bridges) {
383 struct vsctl_bridge *br = node->data;
384 if (br->parent == parent && br->vlan == vlan) {
393 free_info(struct vsctl_info *info)
395 struct shash_node *node;
397 SHASH_FOR_EACH (node, &info->bridges) {
398 struct vsctl_bridge *bridge = node->data;
402 shash_destroy(&info->bridges);
404 SHASH_FOR_EACH (node, &info->ports) {
405 struct vsctl_port *port = node->data;
408 shash_destroy(&info->ports);
410 SHASH_FOR_EACH (node, &info->ifaces) {
411 struct vsctl_iface *iface = node->data;
414 shash_destroy(&info->ifaces);
418 get_info(const struct ovsrec_open_vswitch *ovs, struct vsctl_info *info)
420 struct shash bridges, ports;
423 shash_init(&info->bridges);
424 shash_init(&info->ports);
425 shash_init(&info->ifaces);
427 shash_init(&bridges);
429 for (i = 0; i < ovs->n_bridges; i++) {
430 struct ovsrec_bridge *br_cfg = ovs->bridges[i];
431 struct vsctl_bridge *br;
434 if (!shash_add_once(&bridges, br_cfg->name, NULL)) {
435 VLOG_WARN("%s: database contains duplicate bridge name",
439 br = add_bridge(info, br_cfg, br_cfg->name, NULL, 0);
444 for (j = 0; j < br_cfg->n_ports; j++) {
445 struct ovsrec_port *port_cfg = br_cfg->ports[j];
447 if (!shash_add_once(&ports, port_cfg->name, NULL)) {
448 VLOG_WARN("%s: database contains duplicate port name",
453 if (port_is_fake_bridge(port_cfg)
454 && shash_add_once(&bridges, port_cfg->name, NULL)) {
455 add_bridge(info, NULL, port_cfg->name, br, *port_cfg->tag);
459 shash_destroy(&bridges);
460 shash_destroy(&ports);
462 shash_init(&bridges);
464 for (i = 0; i < ovs->n_bridges; i++) {
465 struct ovsrec_bridge *br_cfg = ovs->bridges[i];
466 struct vsctl_bridge *br;
469 if (!shash_add_once(&bridges, br_cfg->name, NULL)) {
472 br = shash_find_data(&info->bridges, br_cfg->name);
473 for (j = 0; j < br_cfg->n_ports; j++) {
474 struct ovsrec_port *port_cfg = br_cfg->ports[j];
475 struct vsctl_port *port;
478 if (!shash_add_once(&ports, port_cfg->name, NULL)) {
482 if (port_is_fake_bridge(port_cfg)
483 && !shash_add_once(&bridges, port_cfg->name, NULL)) {
487 port = xmalloc(sizeof *port);
488 port->port_cfg = port_cfg;
490 && *port_cfg->tag >= 1 && *port_cfg->tag <= 4095) {
491 port->bridge = find_vlan_bridge(info, br, *port_cfg->tag);
498 shash_add(&info->ports, port_cfg->name, port);
500 for (k = 0; k < port_cfg->n_interfaces; k++) {
501 struct ovsrec_interface *iface_cfg = port_cfg->interfaces[k];
502 struct vsctl_iface *iface;
504 if (shash_find(&info->ifaces, iface_cfg->name)) {
505 VLOG_WARN("%s: database contains duplicate interface name",
510 iface = xmalloc(sizeof *iface);
511 iface->iface_cfg = iface_cfg;
513 shash_add(&info->ifaces, iface_cfg->name, iface);
517 shash_destroy(&bridges);
518 shash_destroy(&ports);
522 check_conflicts(struct vsctl_info *info, const char *name,
525 struct vsctl_iface *iface;
526 struct vsctl_port *port;
528 if (shash_find(&info->bridges, name)) {
529 vsctl_fatal("%s because a bridge named %s already exists",
533 port = shash_find_data(&info->ports, name);
535 vsctl_fatal("%s because a port named %s already exists on "
536 "bridge %s", msg, name, port->bridge->name);
539 iface = shash_find_data(&info->ifaces, name);
541 vsctl_fatal("%s because an interface named %s already exists "
542 "on bridge %s", msg, name, iface->port->bridge->name);
548 static struct vsctl_bridge *
549 find_bridge(struct vsctl_info *info, const char *name, bool must_exist)
551 struct vsctl_bridge *br = shash_find_data(&info->bridges, name);
552 if (must_exist && !br) {
553 vsctl_fatal("no bridge named %s", name);
558 static struct vsctl_port *
559 find_port(struct vsctl_info *info, const char *name, bool must_exist)
561 struct vsctl_port *port = shash_find_data(&info->ports, name);
562 if (port && !strcmp(name, port->bridge->name)) {
565 if (must_exist && !port) {
566 vsctl_fatal("no port named %s", name);
571 static struct vsctl_iface *
572 find_iface(struct vsctl_info *info, const char *name, bool must_exist)
574 struct vsctl_iface *iface = shash_find_data(&info->ifaces, name);
575 if (iface && !strcmp(name, iface->port->bridge->name)) {
578 if (must_exist && !iface) {
579 vsctl_fatal("no interface named %s", name);
585 bridge_insert_port(struct ovsrec_bridge *br, struct ovsrec_port *port)
587 struct ovsrec_port **ports;
590 ports = xmalloc(sizeof *br->ports * (br->n_ports + 1));
591 for (i = 0; i < br->n_ports; i++) {
592 ports[i] = br->ports[i];
594 ports[br->n_ports] = port;
595 ovsrec_bridge_set_ports(br, ports, br->n_ports + 1);
600 bridge_delete_port(struct ovsrec_bridge *br, struct ovsrec_port *port)
602 struct ovsrec_port **ports;
605 ports = xmalloc(sizeof *br->ports * br->n_ports);
606 for (i = n = 0; i < br->n_ports; i++) {
607 if (br->ports[i] != port) {
608 ports[n++] = br->ports[i];
611 ovsrec_bridge_set_ports(br, ports, n);
616 ovs_insert_bridge(const struct ovsrec_open_vswitch *ovs,
617 struct ovsrec_bridge *bridge)
619 struct ovsrec_bridge **bridges;
622 bridges = xmalloc(sizeof *ovs->bridges * (ovs->n_bridges + 1));
623 for (i = 0; i < ovs->n_bridges; i++) {
624 bridges[i] = ovs->bridges[i];
626 bridges[ovs->n_bridges] = bridge;
627 ovsrec_open_vswitch_set_bridges(ovs, bridges, ovs->n_bridges + 1);
632 ovs_delete_bridge(const struct ovsrec_open_vswitch *ovs,
633 struct ovsrec_bridge *bridge)
635 struct ovsrec_bridge **bridges;
638 bridges = xmalloc(sizeof *ovs->bridges * ovs->n_bridges);
639 for (i = n = 0; i < ovs->n_bridges; i++) {
640 if (ovs->bridges[i] != bridge) {
641 bridges[n++] = ovs->bridges[i];
644 ovsrec_open_vswitch_set_bridges(ovs, bridges, n);
649 cmd_init(struct vsctl_context *ctx UNUSED)
654 cmd_add_br(struct vsctl_context *ctx)
656 const char *br_name = ctx->argv[1];
657 struct vsctl_info info;
659 get_info(ctx->ovs, &info);
660 check_conflicts(&info, br_name,
661 xasprintf("cannot create a bridge named %s", br_name));
663 if (ctx->argc == 2) {
664 struct ovsrec_bridge *br;
665 struct ovsrec_port *port;
666 struct ovsrec_interface *iface;
668 iface = ovsrec_interface_insert(txn_from_openvswitch(ctx->ovs));
669 ovsrec_interface_set_name(iface, br_name);
671 port = ovsrec_port_insert(txn_from_openvswitch(ctx->ovs));
672 ovsrec_port_set_name(port, br_name);
673 ovsrec_port_set_interfaces(port, &iface, 1);
675 br = ovsrec_bridge_insert(txn_from_openvswitch(ctx->ovs));
676 ovsrec_bridge_set_name(br, br_name);
677 ovsrec_bridge_set_ports(br, &port, 1);
679 ovs_insert_bridge(ctx->ovs, br);
680 } else if (ctx->argc == 3) {
681 vsctl_fatal("'%s' command takes exactly 1 or 3 arguments",
683 } else if (ctx->argc == 4) {
684 const char *parent_name = ctx->argv[2];
685 int vlan = atoi(ctx->argv[3]);
686 struct ovsrec_bridge *br;
687 struct vsctl_bridge *parent;
688 struct ovsrec_port *port;
689 struct ovsrec_interface *iface;
692 if (vlan < 1 || vlan > 4095) {
693 vsctl_fatal("%s: vlan must be between 1 and 4095", ctx->argv[0]);
696 parent = find_bridge(&info, parent_name, false);
697 if (parent && parent->vlan) {
698 vsctl_fatal("cannot create brdige with fake bridge as parent");
701 vsctl_fatal("parent bridge %s does not exist", parent_name);
705 iface = ovsrec_interface_insert(txn_from_openvswitch(ctx->ovs));
706 ovsrec_interface_set_name(iface, br_name);
707 ovsrec_interface_set_type(iface, "internal");
709 port = ovsrec_port_insert(txn_from_openvswitch(ctx->ovs));
710 ovsrec_port_set_name(port, br_name);
711 ovsrec_port_set_interfaces(port, &iface, 1);
712 ovsrec_port_set_fake_bridge(port, true);
713 ovsrec_port_set_tag(port, &tag, 1);
715 bridge_insert_port(br, port);
724 del_port(struct vsctl_info *info, struct vsctl_port *port)
726 struct shash_node *node;
728 SHASH_FOR_EACH (node, &info->ifaces) {
729 struct vsctl_iface *iface = node->data;
730 if (iface->port == port) {
731 ovsrec_interface_delete(iface->iface_cfg);
734 ovsrec_port_delete(port->port_cfg);
736 bridge_delete_port((port->bridge->parent
737 ? port->bridge->parent->br_cfg
738 : port->bridge->br_cfg), port->port_cfg);
742 cmd_del_br(struct vsctl_context *ctx)
744 bool must_exist = !shash_find(&ctx->options, "--if-exists");
745 struct vsctl_bridge *bridge;
746 struct vsctl_info info;
748 get_info(ctx->ovs, &info);
749 bridge = find_bridge(&info, ctx->argv[1], must_exist);
751 struct shash_node *node;
753 SHASH_FOR_EACH (node, &info.ports) {
754 struct vsctl_port *port = node->data;
755 if (port->bridge == bridge
756 || !strcmp(port->port_cfg->name, bridge->name)) {
757 del_port(&info, port);
760 if (bridge->br_cfg) {
761 ovsrec_bridge_delete(bridge->br_cfg);
762 ovs_delete_bridge(ctx->ovs, bridge->br_cfg);
769 output_sorted(struct svec *svec, struct ds *output)
775 SVEC_FOR_EACH (i, name, svec) {
776 ds_put_format(output, "%s\n", name);
781 cmd_list_br(struct vsctl_context *ctx)
783 struct shash_node *node;
784 struct vsctl_info info;
787 get_info(ctx->ovs, &info);
790 SHASH_FOR_EACH (node, &info.bridges) {
791 struct vsctl_bridge *br = node->data;
792 svec_add(&bridges, br->name);
794 output_sorted(&bridges, &ctx->output);
795 svec_destroy(&bridges);
801 cmd_br_exists(struct vsctl_context *ctx)
803 struct vsctl_info info;
805 get_info(ctx->ovs, &info);
806 if (!find_bridge(&info, ctx->argv[1], false)) {
812 /* Returns true if 'b_prefix' (of length 'b_prefix_len') concatenated with 'b'
813 * equals 'a', false otherwise. */
815 key_matches(const char *a,
816 const char *b_prefix, size_t b_prefix_len, const char *b)
818 return !strncmp(a, b_prefix, b_prefix_len) && !strcmp(a + b_prefix_len, b);
822 set_external_id(char **old_keys, char **old_values, size_t old_n,
823 char *key, char *value,
824 char ***new_keysp, char ***new_valuesp, size_t *new_np)
831 new_keys = xmalloc(sizeof *new_keys * (old_n + 1));
832 new_values = xmalloc(sizeof *new_values * (old_n + 1));
834 for (i = 0; i < old_n; i++) {
835 if (strcmp(key, old_keys[i])) {
836 new_keys[new_n] = old_keys[i];
837 new_values[new_n] = old_values[i];
842 new_keys[new_n] = key;
843 new_values[new_n] = value;
846 *new_keysp = new_keys;
847 *new_valuesp = new_values;
852 cmd_br_set_external_id(struct vsctl_context *ctx)
854 struct vsctl_info info;
855 struct vsctl_bridge *bridge;
856 char **keys, **values;
859 get_info(ctx->ovs, &info);
860 bridge = find_bridge(&info, ctx->argv[1], true);
861 if (bridge->br_cfg) {
862 set_external_id(bridge->br_cfg->key_external_ids,
863 bridge->br_cfg->value_external_ids,
864 bridge->br_cfg->n_external_ids,
865 ctx->argv[2], ctx->argc >= 4 ? ctx->argv[3] : NULL,
867 ovsrec_bridge_set_external_ids(bridge->br_cfg, keys, values, n);
869 char *key = xasprintf("fake-bridge-%s", ctx->argv[2]);
870 struct vsctl_port *port = shash_find_data(&info.ports, ctx->argv[1]);
871 set_external_id(port->port_cfg->key_external_ids,
872 port->port_cfg->value_external_ids,
873 port->port_cfg->n_external_ids,
874 key, ctx->argc >= 4 ? ctx->argv[3] : NULL,
876 ovsrec_port_set_external_ids(port->port_cfg, keys, values, n);
886 get_external_id(char **keys, char **values, size_t n,
887 const char *prefix, const char *key,
890 size_t prefix_len = strlen(prefix);
895 for (i = 0; i < n; i++) {
896 if (!key && !strncmp(keys[i], prefix, prefix_len)) {
897 svec_add_nocopy(&svec, xasprintf("%s=%s",
898 keys[i] + prefix_len, values[i]));
899 } else if (key_matches(keys[i], prefix, prefix_len, key)) {
900 svec_add(&svec, values[i]);
904 output_sorted(&svec, output);
909 cmd_br_get_external_id(struct vsctl_context *ctx)
911 struct vsctl_info info;
912 struct vsctl_bridge *bridge;
914 get_info(ctx->ovs, &info);
915 bridge = find_bridge(&info, ctx->argv[1], true);
916 if (bridge->br_cfg) {
917 get_external_id(bridge->br_cfg->key_external_ids,
918 bridge->br_cfg->value_external_ids,
919 bridge->br_cfg->n_external_ids,
920 "", ctx->argc >= 3 ? ctx->argv[2] : NULL,
923 struct vsctl_port *port = shash_find_data(&info.ports, ctx->argv[1]);
924 get_external_id(port->port_cfg->key_external_ids,
925 port->port_cfg->value_external_ids,
926 port->port_cfg->n_external_ids,
927 "fake-bridge-", ctx->argc >= 3 ? ctx->argv[2] : NULL, &ctx->output);
934 cmd_list_ports(struct vsctl_context *ctx)
936 struct vsctl_bridge *br;
937 struct shash_node *node;
938 struct vsctl_info info;
941 get_info(ctx->ovs, &info);
942 br = find_bridge(&info, ctx->argv[1], true);
945 SHASH_FOR_EACH (node, &info.ports) {
946 struct vsctl_port *port = node->data;
948 if (strcmp(port->port_cfg->name, br->name) && br == port->bridge) {
949 svec_add(&ports, port->port_cfg->name);
952 output_sorted(&ports, &ctx->output);
953 svec_destroy(&ports);
959 add_port(const struct ovsrec_open_vswitch *ovs,
960 const char *br_name, const char *port_name,
961 char *iface_names[], int n_ifaces)
963 struct vsctl_info info;
964 struct vsctl_bridge *bridge;
965 struct ovsrec_interface **ifaces;
966 struct ovsrec_port *port;
969 get_info(ovs, &info);
970 check_conflicts(&info, port_name,
971 xasprintf("cannot create a port named %s", port_name));
972 /* XXX need to check for conflicts on interfaces too */
973 bridge = find_bridge(&info, br_name, true);
975 ifaces = xmalloc(n_ifaces * sizeof *ifaces);
976 for (i = 0; i < n_ifaces; i++) {
977 ifaces[i] = ovsrec_interface_insert(txn_from_openvswitch(ovs));
978 ovsrec_interface_set_name(ifaces[i], iface_names[i]);
981 port = ovsrec_port_insert(txn_from_openvswitch(ovs));
982 ovsrec_port_set_name(port, port_name);
983 ovsrec_port_set_interfaces(port, ifaces, n_ifaces);
987 int64_t tag = bridge->vlan;
988 ovsrec_port_set_tag(port, &tag, 1);
991 bridge_insert_port((bridge->parent ? bridge->parent->br_cfg
992 : bridge->br_cfg), port);
998 cmd_add_port(struct vsctl_context *ctx)
1000 add_port(ctx->ovs, ctx->argv[1], ctx->argv[2], &ctx->argv[2], 1);
1004 cmd_add_bond(struct vsctl_context *ctx)
1006 add_port(ctx->ovs, ctx->argv[1], ctx->argv[2], &ctx->argv[3], ctx->argc - 3);
1010 cmd_del_port(struct vsctl_context *ctx)
1012 bool must_exist = !shash_find(&ctx->options, "--if-exists");
1013 struct vsctl_info info;
1015 get_info(ctx->ovs, &info);
1016 if (ctx->argc == 2) {
1017 struct vsctl_port *port = find_port(&info, ctx->argv[1], must_exist);
1019 del_port(&info, port);
1021 } else if (ctx->argc == 3) {
1022 struct vsctl_bridge *bridge = find_bridge(&info, ctx->argv[1], true);
1023 struct vsctl_port *port = find_port(&info, ctx->argv[2], must_exist);
1026 if (port->bridge == bridge) {
1027 del_port(&info, port);
1028 } else if (port->bridge->parent == bridge) {
1029 vsctl_fatal("bridge %s does not have a port %s (although its "
1030 "parent bridge %s does)",
1031 ctx->argv[1], ctx->argv[2], bridge->parent->name);
1033 vsctl_fatal("bridge %s does not have a port %s",
1034 ctx->argv[1], ctx->argv[2]);
1042 cmd_port_to_br(struct vsctl_context *ctx)
1044 struct vsctl_port *port;
1045 struct vsctl_info info;
1047 get_info(ctx->ovs, &info);
1048 port = find_port(&info, ctx->argv[1], true);
1049 ds_put_format(&ctx->output, "%s\n", port->bridge->name);
1054 cmd_port_set_external_id(struct vsctl_context *ctx)
1056 struct vsctl_info info;
1057 struct vsctl_port *port;
1058 char **keys, **values;
1061 get_info(ctx->ovs, &info);
1062 port = find_port(&info, ctx->argv[1], true);
1063 set_external_id(port->port_cfg->key_external_ids,
1064 port->port_cfg->value_external_ids,
1065 port->port_cfg->n_external_ids,
1066 ctx->argv[2], ctx->argc >= 4 ? ctx->argv[3] : NULL,
1067 &keys, &values, &n);
1068 ovsrec_port_set_external_ids(port->port_cfg, keys, values, n);
1076 cmd_port_get_external_id(struct vsctl_context *ctx)
1078 struct vsctl_info info;
1079 struct vsctl_port *port;
1081 get_info(ctx->ovs, &info);
1082 port = find_port(&info, ctx->argv[1], true);
1083 get_external_id(port->port_cfg->key_external_ids,
1084 port->port_cfg->value_external_ids,
1085 port->port_cfg->n_external_ids,
1086 "", ctx->argc >= 3 ? ctx->argv[2] : NULL, &ctx->output);
1091 cmd_br_to_vlan(struct vsctl_context *ctx)
1093 struct vsctl_bridge *bridge;
1094 struct vsctl_info info;
1096 get_info(ctx->ovs, &info);
1097 bridge = find_bridge(&info, ctx->argv[1], true);
1098 ds_put_format(&ctx->output, "%d\n", bridge->vlan);
1103 cmd_br_to_parent(struct vsctl_context *ctx)
1105 struct vsctl_bridge *bridge;
1106 struct vsctl_info info;
1108 get_info(ctx->ovs, &info);
1109 bridge = find_bridge(&info, ctx->argv[1], true);
1110 if (bridge->parent) {
1111 bridge = bridge->parent;
1113 ds_put_format(&ctx->output, "%s\n", bridge->name);
1118 cmd_list_ifaces(struct vsctl_context *ctx)
1120 struct vsctl_bridge *br;
1121 struct shash_node *node;
1122 struct vsctl_info info;
1125 get_info(ctx->ovs, &info);
1126 br = find_bridge(&info, ctx->argv[1], true);
1129 SHASH_FOR_EACH (node, &info.ifaces) {
1130 struct vsctl_iface *iface = node->data;
1132 if (strcmp(iface->iface_cfg->name, br->name)
1133 && br == iface->port->bridge) {
1134 svec_add(&ifaces, iface->iface_cfg->name);
1137 output_sorted(&ifaces, &ctx->output);
1138 svec_destroy(&ifaces);
1144 cmd_iface_to_br(struct vsctl_context *ctx)
1146 struct vsctl_iface *iface;
1147 struct vsctl_info info;
1149 get_info(ctx->ovs, &info);
1150 iface = find_iface(&info, ctx->argv[1], true);
1151 ds_put_format(&ctx->output, "%s\n", iface->port->bridge->name);
1156 cmd_iface_set_external_id(struct vsctl_context *ctx)
1158 struct vsctl_info info;
1159 struct vsctl_iface *iface;
1160 char **keys, **values;
1163 get_info(ctx->ovs, &info);
1164 iface = find_iface(&info, ctx->argv[1], true);
1165 set_external_id(iface->iface_cfg->key_external_ids,
1166 iface->iface_cfg->value_external_ids,
1167 iface->iface_cfg->n_external_ids,
1168 ctx->argv[2], ctx->argc >= 4 ? ctx->argv[3] : NULL,
1169 &keys, &values, &n);
1170 ovsrec_interface_set_external_ids(iface->iface_cfg, keys, values, n);
1178 cmd_iface_get_external_id(struct vsctl_context *ctx)
1180 struct vsctl_info info;
1181 struct vsctl_iface *iface;
1183 get_info(ctx->ovs, &info);
1184 iface = find_iface(&info, ctx->argv[1], true);
1185 get_external_id(iface->iface_cfg->key_external_ids,
1186 iface->iface_cfg->value_external_ids,
1187 iface->iface_cfg->n_external_ids,
1188 "", ctx->argc >= 3 ? ctx->argv[2] : NULL, &ctx->output);
1192 typedef void vsctl_handler_func(struct vsctl_context *);
1194 struct vsctl_command {
1198 vsctl_handler_func *handler;
1199 const char *options;
1202 static void run_vsctl_command(int argc, char *argv[],
1203 const struct ovsrec_open_vswitch *ovs,
1207 do_vsctl(int argc, char *argv[], struct ovsdb_idl *idl)
1209 struct ovsdb_idl_txn *txn;
1210 const struct ovsrec_open_vswitch *ovs;
1211 enum ovsdb_idl_txn_status status;
1216 txn = ovsdb_idl_txn_create(idl);
1218 ovsdb_idl_txn_set_dry_run(txn);
1221 ovs = ovsrec_open_vswitch_first(idl);
1223 /* XXX add verification that table is empty */
1224 ovs = ovsrec_open_vswitch_insert(txn);
1227 output = xmalloc(argc * sizeof *output);
1229 for (start = i = 0; i <= argc; i++) {
1230 if (i == argc || !strcmp(argv[i], "--")) {
1232 ds_init(&output[n_output]);
1233 run_vsctl_command(i - start, &argv[start], ovs,
1234 &output[n_output++]);
1240 while ((status = ovsdb_idl_txn_commit(txn)) == TXN_INCOMPLETE) {
1242 ovsdb_idl_wait(idl);
1243 ovsdb_idl_txn_wait(txn);
1246 ovsdb_idl_txn_destroy(txn);
1249 case TXN_INCOMPLETE:
1253 /* Should not happen--we never call ovsdb_idl_txn_abort(). */
1254 vsctl_fatal("transaction aborted");
1260 for (i = 0; i < n_output; i++) {
1261 ds_destroy(&output[i]);
1266 vsctl_fatal("transaction error");
1272 for (i = 0; i < n_output; i++) {
1273 struct ds *ds = &output[i];
1278 for (j = 0; j < ds->length; j++) {
1279 int c = ds->string[j];
1282 fputs("\\n", stdout);
1286 fputs("\\\\", stdout);
1295 fputs(ds_cstr(ds), stdout);
1301 static vsctl_handler_func *
1302 get_vsctl_handler(int argc, char *argv[], struct vsctl_context *ctx)
1304 static const struct vsctl_command all_commands[] = {
1305 /* Open vSwitch commands. */
1306 {"init", 0, 0, cmd_init, ""},
1308 /* Bridge commands. */
1309 {"add-br", 1, 3, cmd_add_br, ""},
1310 {"del-br", 1, 1, cmd_del_br, "--if-exists"},
1311 {"list-br", 0, 0, cmd_list_br, ""},
1312 {"br-exists", 1, 1, cmd_br_exists, ""},
1313 {"br-to-vlan", 1, 1, cmd_br_to_vlan, ""},
1314 {"br-to-parent", 1, 1, cmd_br_to_parent, ""},
1315 {"br-set-external-id", 2, 3, cmd_br_set_external_id, ""},
1316 {"br-get-external-id", 1, 2, cmd_br_get_external_id, ""},
1318 /* Port commands. */
1319 {"list-ports", 1, 1, cmd_list_ports, ""},
1320 {"add-port", 2, 2, cmd_add_port, ""},
1321 {"add-bond", 4, INT_MAX, cmd_add_bond, ""},
1322 {"del-port", 1, 2, cmd_del_port, "--if-exists"},
1323 {"port-to-br", 1, 1, cmd_port_to_br, ""},
1324 {"port-set-external-id", 2, 3, cmd_port_set_external_id, ""},
1325 {"port-get-external-id", 1, 2, cmd_port_get_external_id, ""},
1327 /* Interface commands. */
1328 {"list-ifaces", 1, 1, cmd_list_ifaces, ""},
1329 {"iface-to-br", 1, 1, cmd_iface_to_br, ""},
1330 {"iface-set-external-id", 2, 3, cmd_iface_set_external_id, ""},
1331 {"iface-get-external-id", 1, 2, cmd_iface_get_external_id, ""},
1334 const struct vsctl_command *p;
1337 shash_init(&ctx->options);
1338 for (i = 0; i < argc; i++) {
1339 if (argv[i][0] != '-') {
1342 if (!shash_add_once(&ctx->options, argv[i], NULL)) {
1343 vsctl_fatal("'%s' option specified multiple times", argv[i]);
1347 vsctl_fatal("missing command name");
1350 for (p = all_commands; p < &all_commands[ARRAY_SIZE(all_commands)]; p++) {
1351 if (!strcmp(p->name, argv[i])) {
1352 struct shash_node *node;
1355 SHASH_FOR_EACH (node, &ctx->options) {
1356 const char *s = strstr(p->options, node->name);
1357 int end = s ? s[strlen(node->name)] : EOF;
1358 if (end != ',' && end != ' ' && end != '\0') {
1359 vsctl_fatal("'%s' command has no '%s' option",
1360 argv[i], node->name);
1364 n_arg = argc - i - 1;
1365 if (n_arg < p->min_args) {
1366 vsctl_fatal("'%s' command requires at least %d arguments",
1367 p->name, p->min_args);
1368 } else if (n_arg > p->max_args) {
1369 vsctl_fatal("'%s' command takes at most %d arguments",
1370 p->name, p->max_args);
1372 ctx->argc = n_arg + 1;
1373 ctx->argv = &argv[i];
1379 vsctl_fatal("unknown command '%s'; use --help for help", argv[i]);
1383 check_vsctl_command(int argc, char *argv[])
1385 struct vsctl_context ctx;
1387 get_vsctl_handler(argc, argv, &ctx);
1388 shash_destroy(&ctx.options);
1392 run_vsctl_command(int argc, char *argv[],
1393 const struct ovsrec_open_vswitch *ovs, struct ds *output)
1395 vsctl_handler_func *function;
1396 struct vsctl_context ctx;
1398 function = get_vsctl_handler(argc, argv, &ctx);
1400 ds_init(&ctx.output);
1402 *output = ctx.output;
1403 shash_destroy(&ctx.options);