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,
127 static struct option long_options[] = {
128 {"db", required_argument, 0, OPT_DB},
129 {"no-syslog", no_argument, 0, OPT_NO_SYSLOG},
130 {"no-wait", no_argument, 0, OPT_NO_WAIT},
131 {"oneline", no_argument, 0, OPT_ONELINE},
132 {"verbose", optional_argument, 0, 'v'},
133 {"help", no_argument, 0, 'h'},
134 {"version", no_argument, 0, 'V'},
141 c = getopt_long(argc, argv, "+v::hV", long_options, NULL);
156 vlog_set_levels(VLM_vsctl, VLF_SYSLOG, VLL_WARN);
160 /* XXX not yet implemented */
167 OVS_PRINT_VERSION(0, 0);
171 vlog_set_verbosity(optarg);
190 printf("%s: ovs-vswitchd management utility\n"
191 "usage: %s [OPTIONS] COMMAND [ARG...]\n",
192 program_name, program_name);
193 printf("\nBridge commands:\n"
195 "create a new bridge named BRIDGE\n"
196 " add-br BRIDGE PARENT VLAN "
197 "create new fake bridge BRIDGE in PARENT on VLAN\n"
199 "delete BRIDGE and all of its ports\n"
201 "print the names of all the bridges\n"
203 "test whether BRIDGE exists\n"
204 " br-to-vlan BRIDGE "
205 "print the VLAN which BRIDGE is on\n"
206 " br-to-parent BRIDGE "
207 "print the parent of BRIDGE\n"
208 " br-set-external-id BRIDGE KEY VALUE"
209 " set KEY on BRIDGE to VALUE\n"
210 " br-set-external-id BRIDGE KEY"
211 " unset KEY on BRIDGE\n"
212 " br-get-external-id BRIDGE KEY"
213 " print value of KEY on BRIDGE\n"
214 " br-get-external-id BRIDGE"
215 " list key-value pairs on BRIDGE\n"
217 printf("\nPort commands:\n"
218 " list-ports BRIDGE "
219 "print the names of all the ports on BRIDGE\n"
220 " add-port BRIDGE PORT "
221 "add network device PORT to BRIDGE\n"
222 " add-bond BRIDGE PORT IFACE... "
223 "add new bonded port PORT in BRIDGE from IFACES\n"
224 " del-port [BRIDGE] PORT "
225 "delete PORT (which may be bonded) from BRIDGE\n"
227 "print name of bridge that contains PORT\n"
228 " port-set-external-id PORT KEY VALUE"
229 " set KEY on PORT to VALUE\n"
230 " port-set-external-id PORT KEY"
231 " unset KEY on PORT\n"
232 " port-get-external-id PORT KEY"
233 " print value of KEY on PORT\n"
234 " port-get-external-id PORT"
235 " list key-value pairs on PORT\n"
236 "A bond is considered to be a single port.\n"
238 printf("\nInterface commands (a bond consists of multiple interfaces):\n"
239 " list-ifaces BRIDGE "
240 "print the names of all the interfaces on BRIDGE\n"
241 " iface-to-br IFACE "
242 "print name of bridge that contains IFACE\n"
243 " iface-set-external-id IFACE KEY VALUE"
244 " set KEY on IFACE to VALUE\n"
245 " iface-set-external-id IFACE KEY"
246 " unset KEY on IFACE\n"
247 " iface-get-external-id IFACE KEY"
248 " print value of KEY on IFACE\n"
249 " iface-get-external-id IFACE"
250 " list key-value pairs on IFACE\n"
252 printf("\nOptions:\n"
254 "connect to DATABASE\n"
258 "print exactly one line of output per command\n",
261 printf("\nOther options:\n"
263 "display this help message\n"
265 "display version information\n");
274 def = xasprintf("unix:%s/ovsdb-server", ovs_rundir);
279 struct vsctl_context {
282 const struct ovsrec_open_vswitch *ovs;
284 struct shash options;
287 struct vsctl_bridge {
288 struct ovsrec_bridge *br_cfg;
290 struct vsctl_bridge *parent;
295 struct ovsrec_port *port_cfg;
296 struct vsctl_bridge *bridge;
300 struct ovsrec_interface *iface_cfg;
301 struct vsctl_port *port;
305 struct shash bridges;
310 static struct ovsdb_idl_txn *
311 txn_from_openvswitch(const struct ovsrec_open_vswitch *ovs)
313 return ovsdb_idl_txn_get(&ovs->header_);
316 static struct vsctl_bridge *
317 add_bridge(struct vsctl_info *b,
318 struct ovsrec_bridge *br_cfg, const char *name,
319 struct vsctl_bridge *parent, int vlan)
321 struct vsctl_bridge *br = xmalloc(sizeof *br);
323 br->name = xstrdup(name);
326 shash_add(&b->bridges, br->name, br);
331 port_is_fake_bridge(const struct ovsrec_port *port_cfg)
333 return (port_cfg->fake_bridge
335 && *port_cfg->tag >= 1 && *port_cfg->tag <= 4095);
338 static struct vsctl_bridge *
339 find_vlan_bridge(struct vsctl_info *info,
340 struct vsctl_bridge *parent, int vlan)
342 struct shash_node *node;
344 SHASH_FOR_EACH (node, &info->bridges) {
345 struct vsctl_bridge *br = node->data;
346 if (br->parent == parent && br->vlan == vlan) {
355 free_info(struct vsctl_info *info)
357 struct shash_node *node;
359 SHASH_FOR_EACH (node, &info->bridges) {
360 struct vsctl_bridge *bridge = node->data;
364 shash_destroy(&info->bridges);
366 SHASH_FOR_EACH (node, &info->ports) {
367 struct vsctl_port *port = node->data;
370 shash_destroy(&info->ports);
372 SHASH_FOR_EACH (node, &info->ifaces) {
373 struct vsctl_iface *iface = node->data;
376 shash_destroy(&info->ifaces);
380 get_info(const struct ovsrec_open_vswitch *ovs, struct vsctl_info *info)
382 struct shash bridges, ports;
385 shash_init(&info->bridges);
386 shash_init(&info->ports);
387 shash_init(&info->ifaces);
389 shash_init(&bridges);
391 for (i = 0; i < ovs->n_bridges; i++) {
392 struct ovsrec_bridge *br_cfg = ovs->bridges[i];
393 struct vsctl_bridge *br;
396 if (!shash_add_once(&bridges, br_cfg->name, NULL)) {
397 VLOG_WARN("%s: database contains duplicate bridge name",
401 br = add_bridge(info, br_cfg, br_cfg->name, NULL, 0);
406 for (j = 0; j < br_cfg->n_ports; j++) {
407 struct ovsrec_port *port_cfg = br_cfg->ports[j];
409 if (!shash_add_once(&ports, port_cfg->name, NULL)) {
410 VLOG_WARN("%s: database contains duplicate port name",
415 if (port_is_fake_bridge(port_cfg)
416 && shash_add_once(&bridges, port_cfg->name, NULL)) {
417 add_bridge(info, NULL, port_cfg->name, br, *port_cfg->tag);
421 shash_destroy(&bridges);
422 shash_destroy(&ports);
424 shash_init(&bridges);
426 for (i = 0; i < ovs->n_bridges; i++) {
427 struct ovsrec_bridge *br_cfg = ovs->bridges[i];
428 struct vsctl_bridge *br;
431 if (!shash_add_once(&bridges, br_cfg->name, NULL)) {
434 br = shash_find_data(&info->bridges, br_cfg->name);
435 for (j = 0; j < br_cfg->n_ports; j++) {
436 struct ovsrec_port *port_cfg = br_cfg->ports[j];
437 struct vsctl_port *port;
440 if (!shash_add_once(&ports, port_cfg->name, NULL)) {
444 if (port_is_fake_bridge(port_cfg)
445 && !shash_add_once(&bridges, port_cfg->name, NULL)) {
449 port = xmalloc(sizeof *port);
450 port->port_cfg = port_cfg;
452 && *port_cfg->tag >= 1 && *port_cfg->tag <= 4095) {
453 port->bridge = find_vlan_bridge(info, br, *port_cfg->tag);
460 shash_add(&info->ports, port_cfg->name, port);
462 for (k = 0; k < port_cfg->n_interfaces; k++) {
463 struct ovsrec_interface *iface_cfg = port_cfg->interfaces[k];
464 struct vsctl_iface *iface;
466 if (shash_find(&info->ifaces, iface_cfg->name)) {
467 VLOG_WARN("%s: database contains duplicate interface name",
472 iface = xmalloc(sizeof *iface);
473 iface->iface_cfg = iface_cfg;
475 shash_add(&info->ifaces, iface_cfg->name, iface);
479 shash_destroy(&bridges);
480 shash_destroy(&ports);
484 check_conflicts(struct vsctl_info *info, const char *name,
487 struct vsctl_iface *iface;
488 struct vsctl_port *port;
490 if (shash_find(&info->bridges, name)) {
491 ovs_fatal(0, "%s because a bridge named %s already exists", msg, name);
494 port = shash_find_data(&info->ports, name);
496 ovs_fatal(0, "%s because a port named %s already exists on bridge %s",
497 msg, name, port->bridge->name);
500 iface = shash_find_data(&info->ifaces, name);
502 ovs_fatal(0, "%s because an interface named %s already exists "
503 "on bridge %s", msg, name, iface->port->bridge->name);
509 static struct vsctl_bridge *
510 find_bridge(struct vsctl_info *info, const char *name, bool must_exist)
512 struct vsctl_bridge *br = shash_find_data(&info->bridges, name);
513 if (must_exist && !br) {
514 ovs_fatal(0, "no bridge named %s", name);
519 static struct vsctl_port *
520 find_port(struct vsctl_info *info, const char *name, bool must_exist)
522 struct vsctl_port *port = shash_find_data(&info->ports, name);
523 if (port && !strcmp(name, port->bridge->name)) {
526 if (must_exist && !port) {
527 ovs_fatal(0, "no port named %s", name);
532 static struct vsctl_iface *
533 find_iface(struct vsctl_info *info, const char *name, bool must_exist)
535 struct vsctl_iface *iface = shash_find_data(&info->ifaces, name);
536 if (iface && !strcmp(name, iface->port->bridge->name)) {
539 if (must_exist && !iface) {
540 ovs_fatal(0, "no interface named %s", name);
546 bridge_insert_port(struct ovsrec_bridge *br, struct ovsrec_port *port)
548 struct ovsrec_port **ports;
551 ports = xmalloc(sizeof *br->ports * (br->n_ports + 1));
552 for (i = 0; i < br->n_ports; i++) {
553 ports[i] = br->ports[i];
555 ports[br->n_ports] = port;
556 ovsrec_bridge_set_ports(br, ports, br->n_ports + 1);
561 bridge_delete_port(struct ovsrec_bridge *br, struct ovsrec_port *port)
563 struct ovsrec_port **ports;
566 ports = xmalloc(sizeof *br->ports * br->n_ports);
567 for (i = n = 0; i < br->n_ports; i++) {
568 if (br->ports[i] != port) {
569 ports[n++] = br->ports[i];
572 ovsrec_bridge_set_ports(br, ports, n);
577 ovs_insert_bridge(const struct ovsrec_open_vswitch *ovs,
578 struct ovsrec_bridge *bridge)
580 struct ovsrec_bridge **bridges;
583 bridges = xmalloc(sizeof *ovs->bridges * (ovs->n_bridges + 1));
584 for (i = 0; i < ovs->n_bridges; i++) {
585 bridges[i] = ovs->bridges[i];
587 bridges[ovs->n_bridges] = bridge;
588 ovsrec_open_vswitch_set_bridges(ovs, bridges, ovs->n_bridges + 1);
593 ovs_delete_bridge(const struct ovsrec_open_vswitch *ovs,
594 struct ovsrec_bridge *bridge)
596 struct ovsrec_bridge **bridges;
599 bridges = xmalloc(sizeof *ovs->bridges * ovs->n_bridges);
600 for (i = n = 0; i < ovs->n_bridges; i++) {
601 if (ovs->bridges[i] != bridge) {
602 bridges[n++] = ovs->bridges[i];
605 ovsrec_open_vswitch_set_bridges(ovs, bridges, n);
610 cmd_add_br(struct vsctl_context *ctx)
612 const char *br_name = ctx->argv[1];
613 struct vsctl_info info;
615 get_info(ctx->ovs, &info);
616 check_conflicts(&info, br_name,
617 xasprintf("cannot create a bridge named %s", br_name));
619 if (ctx->argc == 2) {
620 struct ovsrec_bridge *br;
621 struct ovsrec_port *port;
622 struct ovsrec_interface *iface;
624 iface = ovsrec_interface_insert(txn_from_openvswitch(ctx->ovs));
625 ovsrec_interface_set_name(iface, br_name);
627 port = ovsrec_port_insert(txn_from_openvswitch(ctx->ovs));
628 ovsrec_port_set_name(port, br_name);
629 ovsrec_port_set_interfaces(port, &iface, 1);
631 br = ovsrec_bridge_insert(txn_from_openvswitch(ctx->ovs));
632 ovsrec_bridge_set_name(br, br_name);
633 ovsrec_bridge_set_ports(br, &port, 1);
635 ovs_insert_bridge(ctx->ovs, br);
636 } else if (ctx->argc == 3) {
637 ovs_fatal(0, "'%s' comamnd takes exactly 1 or 3 arguments", ctx->argv[0]);
638 } else if (ctx->argc == 4) {
639 const char *parent_name = ctx->argv[2];
640 int vlan = atoi(ctx->argv[3]);
641 struct ovsrec_bridge *br;
642 struct vsctl_bridge *parent;
643 struct ovsrec_port *port;
644 struct ovsrec_interface *iface;
647 if (vlan < 1 || vlan > 4095) {
648 ovs_fatal(0, "%s: vlan must be between 1 and 4095", ctx->argv[0]);
651 parent = find_bridge(&info, parent_name, false);
652 if (parent && parent->vlan) {
653 ovs_fatal(0, "cannot create brdige with fake bridge as parent");
656 ovs_fatal(0, "parent bridge %s does not exist", parent_name);
660 iface = ovsrec_interface_insert(txn_from_openvswitch(ctx->ovs));
661 ovsrec_interface_set_name(iface, br_name);
662 ovsrec_interface_set_type(iface, "internal");
664 port = ovsrec_port_insert(txn_from_openvswitch(ctx->ovs));
665 ovsrec_port_set_name(port, br_name);
666 ovsrec_port_set_interfaces(port, &iface, 1);
667 ovsrec_port_set_fake_bridge(port, true);
668 ovsrec_port_set_tag(port, &tag, 1);
670 bridge_insert_port(br, port);
679 del_port(struct vsctl_info *info, struct vsctl_port *port)
681 struct shash_node *node;
683 SHASH_FOR_EACH (node, &info->ifaces) {
684 struct vsctl_iface *iface = node->data;
685 if (iface->port == port) {
686 ovsrec_interface_delete(iface->iface_cfg);
689 ovsrec_port_delete(port->port_cfg);
691 bridge_delete_port((port->bridge->parent
692 ? port->bridge->parent->br_cfg
693 : port->bridge->br_cfg), port->port_cfg);
697 cmd_del_br(struct vsctl_context *ctx)
699 bool must_exist = !shash_find(&ctx->options, "--if-exists");
700 struct vsctl_bridge *bridge;
701 struct vsctl_info info;
703 get_info(ctx->ovs, &info);
704 bridge = find_bridge(&info, ctx->argv[1], must_exist);
706 struct shash_node *node;
708 SHASH_FOR_EACH (node, &info.ports) {
709 struct vsctl_port *port = node->data;
710 if (port->bridge == bridge
711 || !strcmp(port->port_cfg->name, bridge->name)) {
712 del_port(&info, port);
715 if (bridge->br_cfg) {
716 ovsrec_bridge_delete(bridge->br_cfg);
717 ovs_delete_bridge(ctx->ovs, bridge->br_cfg);
724 output_sorted(struct svec *svec, struct ds *output)
730 SVEC_FOR_EACH (i, name, svec) {
731 ds_put_format(output, "%s\n", name);
736 cmd_list_br(struct vsctl_context *ctx)
738 struct shash_node *node;
739 struct vsctl_info info;
742 get_info(ctx->ovs, &info);
745 SHASH_FOR_EACH (node, &info.bridges) {
746 struct vsctl_bridge *br = node->data;
747 svec_add(&bridges, br->name);
749 output_sorted(&bridges, &ctx->output);
750 svec_destroy(&bridges);
756 cmd_br_exists(struct vsctl_context *ctx)
758 struct vsctl_info info;
760 get_info(ctx->ovs, &info);
761 if (!find_bridge(&info, ctx->argv[1], false)) {
767 /* Returns true if 'b_prefix' (of length 'b_prefix_len') concatenated with 'b'
768 * equals 'a', false otherwise. */
770 key_matches(const char *a,
771 const char *b_prefix, size_t b_prefix_len, const char *b)
773 return !strncmp(a, b_prefix, b_prefix_len) && !strcmp(a + b_prefix_len, b);
777 set_external_id(char **old_keys, char **old_values, size_t old_n,
778 char *key, char *value,
779 char ***new_keysp, char ***new_valuesp, size_t *new_np)
786 new_keys = xmalloc(sizeof *new_keys * (old_n + 1));
787 new_values = xmalloc(sizeof *new_values * (old_n + 1));
789 for (i = 0; i < old_n; i++) {
790 if (strcmp(key, old_keys[i])) {
791 new_keys[new_n] = old_keys[i];
792 new_values[new_n] = old_values[i];
797 new_keys[new_n] = key;
798 new_values[new_n] = value;
801 *new_keysp = new_keys;
802 *new_valuesp = new_values;
807 cmd_br_set_external_id(struct vsctl_context *ctx)
809 struct vsctl_info info;
810 struct vsctl_bridge *bridge;
811 char **keys, **values;
814 get_info(ctx->ovs, &info);
815 bridge = find_bridge(&info, ctx->argv[1], true);
816 if (bridge->br_cfg) {
817 set_external_id(bridge->br_cfg->key_external_ids,
818 bridge->br_cfg->value_external_ids,
819 bridge->br_cfg->n_external_ids,
820 ctx->argv[2], ctx->argc >= 4 ? ctx->argv[3] : NULL,
822 ovsrec_bridge_set_external_ids(bridge->br_cfg, keys, values, n);
824 char *key = xasprintf("fake-bridge-%s", ctx->argv[2]);
825 struct vsctl_port *port = shash_find_data(&info.ports, ctx->argv[1]);
826 set_external_id(port->port_cfg->key_external_ids,
827 port->port_cfg->value_external_ids,
828 port->port_cfg->n_external_ids,
829 key, ctx->argc >= 4 ? ctx->argv[3] : NULL,
831 ovsrec_port_set_external_ids(port->port_cfg, keys, values, n);
841 get_external_id(char **keys, char **values, size_t n,
842 const char *prefix, const char *key,
845 size_t prefix_len = strlen(prefix);
850 for (i = 0; i < n; i++) {
851 if (!key && !strncmp(keys[i], prefix, prefix_len)) {
852 svec_add_nocopy(&svec, xasprintf("%s=%s",
853 keys[i] + prefix_len, values[i]));
854 } else if (key_matches(keys[i], prefix, prefix_len, key)) {
855 svec_add(&svec, values[i]);
859 output_sorted(&svec, output);
864 cmd_br_get_external_id(struct vsctl_context *ctx)
866 struct vsctl_info info;
867 struct vsctl_bridge *bridge;
869 get_info(ctx->ovs, &info);
870 bridge = find_bridge(&info, ctx->argv[1], true);
871 if (bridge->br_cfg) {
872 get_external_id(bridge->br_cfg->key_external_ids,
873 bridge->br_cfg->value_external_ids,
874 bridge->br_cfg->n_external_ids,
875 "", ctx->argc >= 3 ? ctx->argv[2] : NULL,
878 struct vsctl_port *port = shash_find_data(&info.ports, ctx->argv[1]);
879 get_external_id(port->port_cfg->key_external_ids,
880 port->port_cfg->value_external_ids,
881 port->port_cfg->n_external_ids,
882 "fake-bridge-", ctx->argc >= 3 ? ctx->argv[2] : NULL, &ctx->output);
889 cmd_list_ports(struct vsctl_context *ctx)
891 struct vsctl_bridge *br;
892 struct shash_node *node;
893 struct vsctl_info info;
896 get_info(ctx->ovs, &info);
897 br = find_bridge(&info, ctx->argv[1], true);
900 SHASH_FOR_EACH (node, &info.ports) {
901 struct vsctl_port *port = node->data;
903 if (strcmp(port->port_cfg->name, br->name) && br == port->bridge) {
904 svec_add(&ports, port->port_cfg->name);
907 output_sorted(&ports, &ctx->output);
908 svec_destroy(&ports);
914 add_port(const struct ovsrec_open_vswitch *ovs,
915 const char *br_name, const char *port_name,
916 char *iface_names[], int n_ifaces)
918 struct vsctl_info info;
919 struct vsctl_bridge *bridge;
920 struct ovsrec_interface **ifaces;
921 struct ovsrec_port *port;
924 get_info(ovs, &info);
925 check_conflicts(&info, port_name,
926 xasprintf("cannot create a port named %s", port_name));
927 /* XXX need to check for conflicts on interfaces too */
928 bridge = find_bridge(&info, br_name, true);
930 ifaces = xmalloc(n_ifaces * sizeof *ifaces);
931 for (i = 0; i < n_ifaces; i++) {
932 ifaces[i] = ovsrec_interface_insert(txn_from_openvswitch(ovs));
933 ovsrec_interface_set_name(ifaces[i], iface_names[i]);
936 port = ovsrec_port_insert(txn_from_openvswitch(ovs));
937 ovsrec_port_set_name(port, port_name);
938 ovsrec_port_set_interfaces(port, ifaces, n_ifaces);
942 int64_t tag = bridge->vlan;
943 ovsrec_port_set_tag(port, &tag, 1);
946 bridge_insert_port((bridge->parent ? bridge->parent->br_cfg
947 : bridge->br_cfg), port);
953 cmd_add_port(struct vsctl_context *ctx)
955 add_port(ctx->ovs, ctx->argv[1], ctx->argv[2], &ctx->argv[2], 1);
959 cmd_add_bond(struct vsctl_context *ctx)
961 add_port(ctx->ovs, ctx->argv[1], ctx->argv[2], &ctx->argv[3], ctx->argc - 3);
965 cmd_del_port(struct vsctl_context *ctx)
967 bool must_exist = !shash_find(&ctx->options, "--if-exists");
968 struct vsctl_info info;
970 get_info(ctx->ovs, &info);
971 if (ctx->argc == 2) {
972 struct vsctl_port *port = find_port(&info, ctx->argv[1], must_exist);
974 del_port(&info, port);
976 } else if (ctx->argc == 3) {
977 struct vsctl_bridge *bridge = find_bridge(&info, ctx->argv[1], true);
978 struct vsctl_port *port = find_port(&info, ctx->argv[2], must_exist);
981 if (port->bridge == bridge) {
982 del_port(&info, port);
983 } else if (port->bridge->parent == bridge) {
984 ovs_fatal(0, "bridge %s does not have a port %s (although its "
985 "parent bridge %s does)",
986 ctx->argv[1], ctx->argv[2], bridge->parent->name);
988 ovs_fatal(0, "bridge %s does not have a port %s",
989 ctx->argv[1], ctx->argv[2]);
997 cmd_port_to_br(struct vsctl_context *ctx)
999 struct vsctl_port *port;
1000 struct vsctl_info info;
1002 get_info(ctx->ovs, &info);
1003 port = find_port(&info, ctx->argv[1], true);
1004 ds_put_format(&ctx->output, "%s\n", port->bridge->name);
1009 cmd_port_set_external_id(struct vsctl_context *ctx)
1011 struct vsctl_info info;
1012 struct vsctl_port *port;
1013 char **keys, **values;
1016 get_info(ctx->ovs, &info);
1017 port = find_port(&info, ctx->argv[1], true);
1018 set_external_id(port->port_cfg->key_external_ids,
1019 port->port_cfg->value_external_ids,
1020 port->port_cfg->n_external_ids,
1021 ctx->argv[2], ctx->argc >= 4 ? ctx->argv[3] : NULL,
1022 &keys, &values, &n);
1023 ovsrec_port_set_external_ids(port->port_cfg, keys, values, n);
1031 cmd_port_get_external_id(struct vsctl_context *ctx)
1033 struct vsctl_info info;
1034 struct vsctl_port *port;
1036 get_info(ctx->ovs, &info);
1037 port = find_port(&info, ctx->argv[1], true);
1038 get_external_id(port->port_cfg->key_external_ids,
1039 port->port_cfg->value_external_ids,
1040 port->port_cfg->n_external_ids,
1041 "", ctx->argc >= 3 ? ctx->argv[2] : NULL, &ctx->output);
1046 cmd_br_to_vlan(struct vsctl_context *ctx)
1048 struct vsctl_bridge *bridge;
1049 struct vsctl_info info;
1051 get_info(ctx->ovs, &info);
1052 bridge = find_bridge(&info, ctx->argv[1], true);
1053 ds_put_format(&ctx->output, "%d\n", bridge->vlan);
1058 cmd_br_to_parent(struct vsctl_context *ctx)
1060 struct vsctl_bridge *bridge;
1061 struct vsctl_info info;
1063 get_info(ctx->ovs, &info);
1064 bridge = find_bridge(&info, ctx->argv[1], true);
1065 if (bridge->parent) {
1066 bridge = bridge->parent;
1068 ds_put_format(&ctx->output, "%s\n", bridge->name);
1073 cmd_list_ifaces(struct vsctl_context *ctx)
1075 struct vsctl_bridge *br;
1076 struct shash_node *node;
1077 struct vsctl_info info;
1080 get_info(ctx->ovs, &info);
1081 br = find_bridge(&info, ctx->argv[1], true);
1084 SHASH_FOR_EACH (node, &info.ifaces) {
1085 struct vsctl_iface *iface = node->data;
1087 if (strcmp(iface->iface_cfg->name, br->name)
1088 && br == iface->port->bridge) {
1089 svec_add(&ifaces, iface->iface_cfg->name);
1092 output_sorted(&ifaces, &ctx->output);
1093 svec_destroy(&ifaces);
1099 cmd_iface_to_br(struct vsctl_context *ctx)
1101 struct vsctl_iface *iface;
1102 struct vsctl_info info;
1104 get_info(ctx->ovs, &info);
1105 iface = find_iface(&info, ctx->argv[1], true);
1106 ds_put_format(&ctx->output, "%s\n", iface->port->bridge->name);
1111 cmd_iface_set_external_id(struct vsctl_context *ctx)
1113 struct vsctl_info info;
1114 struct vsctl_iface *iface;
1115 char **keys, **values;
1118 get_info(ctx->ovs, &info);
1119 iface = find_iface(&info, ctx->argv[1], true);
1120 set_external_id(iface->iface_cfg->key_external_ids,
1121 iface->iface_cfg->value_external_ids,
1122 iface->iface_cfg->n_external_ids,
1123 ctx->argv[2], ctx->argc >= 4 ? ctx->argv[3] : NULL,
1124 &keys, &values, &n);
1125 ovsrec_interface_set_external_ids(iface->iface_cfg, keys, values, n);
1133 cmd_iface_get_external_id(struct vsctl_context *ctx)
1135 struct vsctl_info info;
1136 struct vsctl_iface *iface;
1138 get_info(ctx->ovs, &info);
1139 iface = find_iface(&info, ctx->argv[1], true);
1140 get_external_id(iface->iface_cfg->key_external_ids,
1141 iface->iface_cfg->value_external_ids,
1142 iface->iface_cfg->n_external_ids,
1143 "", ctx->argc >= 3 ? ctx->argv[2] : NULL, &ctx->output);
1147 typedef void vsctl_handler_func(struct vsctl_context *);
1149 struct vsctl_command {
1153 vsctl_handler_func *handler;
1154 const char *options;
1157 static void run_vsctl_command(int argc, char *argv[],
1158 const struct ovsrec_open_vswitch *ovs,
1162 do_vsctl(int argc, char *argv[], struct ovsdb_idl *idl)
1164 struct ovsdb_idl_txn *txn;
1165 const struct ovsrec_open_vswitch *ovs;
1166 enum ovsdb_idl_txn_status status;
1171 ovs = ovsrec_open_vswitch_first(idl);
1173 /* XXX it would be more user-friendly to create a record ourselves
1174 * (while verifying that the table is empty before doing so). */
1175 ovs_fatal(0, "%s: database does not contain any Open vSwitch "
1176 "configuration", db);
1179 txn = ovsdb_idl_txn_create(idl);
1180 output = xmalloc(argc * sizeof *output);
1182 for (start = i = 0; i <= argc; i++) {
1183 if (i == argc || !strcmp(argv[i], "--")) {
1185 ds_init(&output[n_output]);
1186 run_vsctl_command(i - start, &argv[start], ovs,
1187 &output[n_output++]);
1193 while ((status = ovsdb_idl_txn_commit(txn)) == TXN_INCOMPLETE) {
1195 ovsdb_idl_wait(idl);
1196 ovsdb_idl_txn_wait(txn);
1199 ovsdb_idl_txn_destroy(txn);
1202 case TXN_INCOMPLETE:
1206 /* Should not happen--we never call ovsdb_idl_txn_abort(). */
1207 ovs_fatal(0, "transaction aborted");
1213 for (i = 0; i < n_output; i++) {
1214 ds_destroy(&output[i]);
1219 ovs_fatal(0, "transaction error");
1225 for (i = 0; i < n_output; i++) {
1226 struct ds *ds = &output[i];
1231 for (j = 0; j < ds->length; j++) {
1232 int c = ds->string[j];
1235 fputs("\\n", stdout);
1239 fputs("\\\\", stdout);
1248 fputs(ds_cstr(ds), stdout);
1254 static vsctl_handler_func *
1255 get_vsctl_handler(int argc, char *argv[], struct vsctl_context *ctx)
1257 static const struct vsctl_command all_commands[] = {
1258 /* Bridge commands. */
1259 {"add-br", 1, 3, cmd_add_br, ""},
1260 {"del-br", 1, 1, cmd_del_br, "--if-exists"},
1261 {"list-br", 0, 0, cmd_list_br, ""},
1262 {"br-exists", 1, 1, cmd_br_exists, ""},
1263 {"br-to-vlan", 1, 1, cmd_br_to_vlan, ""},
1264 {"br-to-parent", 1, 1, cmd_br_to_parent, ""},
1265 {"br-set-external-id", 2, 3, cmd_br_set_external_id, ""},
1266 {"br-get-external-id", 1, 2, cmd_br_get_external_id, ""},
1268 /* Port commands. */
1269 {"list-ports", 1, 1, cmd_list_ports, ""},
1270 {"add-port", 2, 2, cmd_add_port, ""},
1271 {"add-bond", 4, INT_MAX, cmd_add_bond, ""},
1272 {"del-port", 1, 2, cmd_del_port, "--if-exists"},
1273 {"port-to-br", 1, 1, cmd_port_to_br, ""},
1274 {"port-set-external-id", 2, 3, cmd_port_set_external_id, ""},
1275 {"port-get-external-id", 1, 2, cmd_port_get_external_id, ""},
1277 /* Interface commands. */
1278 {"list-ifaces", 1, 1, cmd_list_ifaces, ""},
1279 {"iface-to-br", 1, 1, cmd_iface_to_br, ""},
1280 {"iface-set-external-id", 2, 3, cmd_iface_set_external_id, ""},
1281 {"iface-get-external-id", 1, 2, cmd_iface_get_external_id, ""},
1284 const struct vsctl_command *p;
1287 shash_init(&ctx->options);
1288 for (i = 0; i < argc; i++) {
1289 if (argv[i][0] != '-') {
1292 if (!shash_add_once(&ctx->options, argv[i], NULL)) {
1293 ovs_fatal(0, "'%s' option specified multiple times", argv[i]);
1297 ovs_fatal(0, "missing command name");
1300 for (p = all_commands; p < &all_commands[ARRAY_SIZE(all_commands)]; p++) {
1301 if (!strcmp(p->name, argv[i])) {
1302 struct shash_node *node;
1305 SHASH_FOR_EACH (node, &ctx->options) {
1306 const char *s = strstr(p->options, node->name);
1307 int end = s ? s[strlen(node->name)] : EOF;
1308 if (end != ',' && end != ' ' && end != '\0') {
1309 ovs_fatal(0, "'%s' command has no '%s' option",
1310 argv[i], node->name);
1314 n_arg = argc - i - 1;
1315 if (n_arg < p->min_args) {
1316 ovs_fatal(0, "'%s' command requires at least %d arguments",
1317 p->name, p->min_args);
1318 } else if (n_arg > p->max_args) {
1319 ovs_fatal(0, "'%s' command takes at most %d arguments",
1320 p->name, p->max_args);
1322 ctx->argc = n_arg + 1;
1323 ctx->argv = &argv[i];
1329 ovs_fatal(0, "unknown command '%s'; use --help for help", argv[0]);
1333 check_vsctl_command(int argc, char *argv[])
1335 struct vsctl_context ctx;
1337 get_vsctl_handler(argc, argv, &ctx);
1338 shash_destroy(&ctx.options);
1342 run_vsctl_command(int argc, char *argv[],
1343 const struct ovsrec_open_vswitch *ovs, struct ds *output)
1345 vsctl_handler_func *function;
1346 struct vsctl_context ctx;
1348 function = get_vsctl_handler(argc, argv, &ctx);
1350 ds_init(&ctx.output);
1352 *output = ctx.output;
1353 shash_destroy(&ctx.options);