/*
- * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2015 Nicira, Inc.
+ * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include "command-line.h"
#include "compiler.h"
-#include "dynamic-string.h"
+#include "dirs.h"
#include "fatal-signal.h"
#include "hash.h"
-#include "json.h"
+#include "openvswitch/dynamic-string.h"
+#include "openvswitch/json.h"
+#include "openvswitch/ofp-parse.h"
+#include "openvswitch/poll-loop.h"
+#include "openvswitch/vconn.h"
+#include "openvswitch/vlog.h"
#include "ovsdb-data.h"
#include "ovsdb-idl.h"
-#include "poll-loop.h"
#include "process.h"
+#include "simap.h"
#include "stream.h"
#include "stream-ssl.h"
#include "smap.h"
#include "table.h"
#include "timeval.h"
#include "util.h"
-#include "openvswitch/vconn.h"
-#include "openvswitch/vlog.h"
VLOG_DEFINE_THIS_MODULE(vsctl);
static bool wait_for_reload = true;
/* --timeout: Time to wait for a connection to 'db'. */
-static int timeout;
+static unsigned int timeout;
/* --retry: If true, ovs-vsctl will retry connecting to the database forever.
* If false and --db says to use an active connection method (e.g. "unix:",
* wait. */
static bool retry;
+/* --leader-only, --no-leader-only: Only accept the leader in a cluster.
+ *
+ * In a real Open vSwitch environment, it doesn't make much sense to cluster
+ * the Open vSwitch database. This option exists to enable using ovs-vsctl to
+ * test OVSDB's clustering feature. */
+static int leader_only = true;
+
+/* --shuffle-remotes, --no-shuffle-remotes: Shuffle the order of remotes that
+ * are specified in the connetion method string.
+ *
+ * In a real Open vSwitch environment, it doesn't make much sense to cluster
+ * the Open vSwitch database. This option exists to enable using ovs-vsctl to
+ * test OVSDB's clustering feature. */
+static int shuffle_remotes = true;
+
/* Format for table output. */
static struct table_style table_style = TABLE_STYLE_DEFAULT;
static void vsctl_cmd_init(void);
+
+/* The IDL we're using and the current transaction, if any.
+ * This is for use by vsctl_exit() only, to allow it to clean up.
+ * Other code should use its context arguments. */
+static struct ovsdb_idl *the_idl;
+static struct ovsdb_idl_txn *the_idl_txn;
+OVS_NO_RETURN static void vsctl_exit(int status);
+
OVS_NO_RETURN static void usage(void);
static void parse_options(int argc, char *argv[], struct shash *local_options);
static void run_prerequisites(struct ctl_command[], size_t n_commands,
struct ovsdb_idl *);
-static void do_vsctl(const char *args, struct ctl_command *, size_t n,
+static bool do_vsctl(const char *args, struct ctl_command *, size_t n,
struct ovsdb_idl *);
/* post_db_reload_check frame work is to allow ovs-vsctl to do additional
* either store a positive values on successful implementing the new
* interface, or -1 on failure.
*
- * Unless -no-wait command line option is specified,
+ * Unless --no-wait command line option is specified,
* post_db_reload_do_checks() is called right after any configuration
* changes is picked up (i.e. reload) by ovs-vswitchd. Any error detected
* post OVSDB reload is reported as ovs-vsctl errors. OVS-vswitchd logs
int
main(int argc, char *argv[])
{
- extern struct vlog_module VLM_reconnect;
struct ovsdb_idl *idl;
struct ctl_command *commands;
struct shash local_options;
unsigned int seqno;
size_t n_commands;
- char *args;
set_program_name(argv[0]);
fatal_ignore_sigpipe();
vlog_set_levels(NULL, VLF_CONSOLE, VLL_WARN);
- vlog_set_levels(&VLM_reconnect, VLF_ANY_DESTINATION, VLL_WARN);
- ovsrec_init();
+ vlog_set_levels_from_string_assert("reconnect:warn");
vsctl_cmd_init();
- /* Log our arguments. This is often valuable for debugging systems. */
- args = process_escape_args(argv);
- VLOG(ctl_might_write_to_db(argv) ? VLL_INFO : VLL_DBG, "Called as %s", args);
-
/* Parse command line. */
+ char *args = process_escape_args(argv);
shash_init(&local_options);
parse_options(argc, argv, &local_options);
- commands = ctl_parse_commands(argc - optind, argv + optind, &local_options,
- &n_commands);
-
- if (timeout) {
- time_alarm(timeout);
+ char *error = ctl_parse_commands(argc - optind, argv + optind,
+ &local_options, &commands, &n_commands);
+ if (error) {
+ ctl_fatal("%s", error);
}
+ VLOG(ctl_might_write_to_db(commands, n_commands) ? VLL_INFO : VLL_DBG,
+ "Called as %s", args);
+
+ ctl_timeout_setup(timeout);
/* Initialize IDL. */
- idl = the_idl = ovsdb_idl_create(db, &ovsrec_idl_class, false, retry);
+ idl = the_idl = ovsdb_idl_create_unconnected(&ovsrec_idl_class, false);
+ ovsdb_idl_set_shuffle_remotes(idl, shuffle_remotes);
+ ovsdb_idl_set_remote(idl, db, retry);
+ ovsdb_idl_set_leader_only(idl, leader_only);
run_prerequisites(commands, n_commands, idl);
/* Execute the commands.
if (seqno != ovsdb_idl_get_seqno(idl)) {
seqno = ovsdb_idl_get_seqno(idl);
- do_vsctl(args, commands, n_commands, idl);
+ if (do_vsctl(args, commands, n_commands, idl)) {
+ free(args);
+ exit(EXIT_SUCCESS);
+ }
}
if (seqno == ovsdb_idl_get_seqno(idl)) {
OPT_NO_SYSLOG,
OPT_NO_WAIT,
OPT_DRY_RUN,
+ OPT_BOOTSTRAP_CA_CERT,
OPT_PEER_CA_CERT,
OPT_LOCAL,
OPT_RETRY,
OPT_COMMANDS,
OPT_OPTIONS,
VLOG_OPTION_ENUMS,
- TABLE_OPTION_ENUMS
+ TABLE_OPTION_ENUMS,
+ SSL_OPTION_ENUMS,
};
static const struct option global_long_options[] = {
{"db", required_argument, NULL, OPT_DB},
{"help", no_argument, NULL, 'h'},
{"commands", no_argument, NULL, OPT_COMMANDS},
{"options", no_argument, NULL, OPT_OPTIONS},
+ {"leader-only", no_argument, &leader_only, true},
+ {"no-leader-only", no_argument, &leader_only, false},
+ {"shuffle-remotes", no_argument, &shuffle_remotes, true},
+ {"no-shuffle-remotes", no_argument, &shuffle_remotes, false},
{"version", no_argument, NULL, 'V'},
VLOG_LONG_OPTIONS,
TABLE_LONG_OPTIONS,
STREAM_SSL_LONG_OPTIONS,
+ {"bootstrap-ca-cert", required_argument, NULL, OPT_BOOTSTRAP_CA_CERT},
{"peer-ca-cert", required_argument, NULL, OPT_PEER_CA_CERT},
{NULL, 0, NULL, 0},
};
allocated_options = ARRAY_SIZE(global_long_options);
n_options = n_global_long_options;
ctl_add_cmd_options(&options, &n_options, &allocated_options, OPT_LOCAL);
- table_style.format = TF_LIST;
for (;;) {
int idx;
break;
case OPT_NO_SYSLOG:
- vlog_set_levels(&VLM_vsctl, VLF_SYSLOG, VLL_WARN);
+ vlog_set_levels(&this_module, VLF_SYSLOG, VLL_WARN);
break;
case OPT_NO_WAIT:
}
shash_add_nocopy(local_options,
xasprintf("--%s", options[idx].name),
- optarg ? xstrdup(optarg) : NULL);
+ nullable_xstrdup(optarg));
break;
case 'h':
case OPT_COMMANDS:
ctl_print_commands();
+ /* fall through */
case OPT_OPTIONS:
ctl_print_options(global_long_options);
+ /* fall through */
case 'V':
ovs_print_version(0, 0);
exit(EXIT_SUCCESS);
case 't':
- timeout = strtoul(optarg, NULL, 10);
- if (timeout < 0) {
- ctl_fatal("value %s on -t or --timeout is invalid",
- optarg);
+ if (!str_to_uint(optarg, 10, &timeout) || !timeout) {
+ ctl_fatal("value %s on -t or --timeout is invalid", optarg);
}
break;
stream_ssl_set_peer_ca_cert_file(optarg);
break;
+ case OPT_BOOTSTRAP_CA_CERT:
+ stream_ssl_set_ca_cert_file(optarg, true);
+ break;
+
case '?':
exit(EXIT_FAILURE);
+ case 0:
+ break;
+
default:
abort();
}
Controller commands:\n\
get-controller BRIDGE print the controllers for BRIDGE\n\
del-controller BRIDGE delete the controllers for BRIDGE\n\
+ [--inactivity-probe=MSECS]\n\
set-controller BRIDGE TARGET... set the controllers for BRIDGE\n\
get-fail-mode BRIDGE print the fail-mode for BRIDGE\n\
del-fail-mode BRIDGE delete the fail-mode for BRIDGE\n\
Manager commands:\n\
get-manager print the managers\n\
del-manager delete the managers\n\
+ [--inactivity-probe=MSECS]\n\
set-manager TARGET... set the list of managers to TARGET...\n\
\n\
SSL commands:\n\
emer-reset reset switch to known good state\n\
\n\
%s\
+%s\
\n\
Options:\n\
--db=DATABASE connect to DATABASE\n\
-t, --timeout=SECS wait at most SECS seconds for ovs-vswitchd\n\
--dry-run do not commit changes to database\n\
--oneline print exactly one line of output per command\n",
- program_name, program_name, ctl_get_db_cmd_usage(), ctl_default_db());
+ program_name, program_name, ctl_get_db_cmd_usage(),
+ ctl_list_db_tables_usage(), ctl_default_db());
+ table_usage();
vlog_usage();
printf("\
--no-syslog equivalent to --verbose=vsctl:syslog:warn\n");
- stream_usage("database", true, true, false);
+ stream_usage("database", true, true, true);
printf("\n\
Other options:\n\
-h, --help display this help message\n\
struct vsctl_port *port;
};
-/* Casts 'base' into 'strcut vsctl_context'. */
+/* Casts 'base' into 'struct vsctl_context'. */
static struct vsctl_context *
vsctl_context_cast(struct ctl_context *base)
{
struct vsctl_bridge *br = xmalloc(sizeof *br);
br->br_cfg = br_cfg;
br->name = xstrdup(name);
- list_init(&br->ports);
+ ovs_list_init(&br->ports);
br->parent = parent;
br->vlan = vlan;
hmap_init(&br->children);
static void
del_cached_bridge(struct vsctl_context *vsctl_ctx, struct vsctl_bridge *br)
{
- ovs_assert(list_is_empty(&br->ports));
+ ovs_assert(ovs_list_is_empty(&br->ports));
ovs_assert(hmap_is_empty(&br->children));
if (br->parent) {
hmap_remove(&br->parent->children, &br->children_node);
}
port = xmalloc(sizeof *port);
- list_push_back(&parent->ports, &port->ports_node);
- list_init(&port->ifaces);
+ ovs_list_push_back(&parent->ports, &port->ports_node);
+ ovs_list_init(&port->ifaces);
port->port_cfg = port_cfg;
port->bridge = parent;
shash_add(&vsctl_ctx->ports, port_cfg->name, port);
static void
del_cached_port(struct vsctl_context *vsctl_ctx, struct vsctl_port *port)
{
- ovs_assert(list_is_empty(&port->ifaces));
- list_remove(&port->ports_node);
+ ovs_assert(ovs_list_is_empty(&port->ifaces));
+ ovs_list_remove(&port->ports_node);
shash_find_and_delete(&vsctl_ctx->ports, port->port_cfg->name);
ovsrec_port_delete(port->port_cfg);
free(port);
struct vsctl_iface *iface;
iface = xmalloc(sizeof *iface);
- list_push_back(&parent->ifaces, &iface->ifaces_node);
+ ovs_list_push_back(&parent->ifaces, &iface->ifaces_node);
iface->iface_cfg = iface_cfg;
iface->port = parent;
shash_add(&vsctl_ctx->ifaces, iface_cfg->name, iface);
static void
del_cached_iface(struct vsctl_context *vsctl_ctx, struct vsctl_iface *iface)
{
- list_remove(&iface->ifaces_node);
+ ovs_list_remove(&iface->ifaces_node);
shash_find_and_delete(&vsctl_ctx->ifaces, iface->iface_cfg->name);
ovsrec_interface_delete(iface->iface_cfg);
free(iface);
ovsdb_idl_add_column(ctx->idl, &ovsrec_interface_col_name);
ovsdb_idl_add_column(ctx->idl, &ovsrec_interface_col_ofport);
+ ovsdb_idl_add_column(ctx->idl, &ovsrec_interface_col_error);
}
static void
continue;
}
br = add_bridge_to_cache(vsctl_ctx, br_cfg, br_cfg->name, NULL, 0);
- if (!br) {
- continue;
- }
for (j = 0; j < br_cfg->n_ports; j++) {
struct ovsrec_port *port_cfg = br_cfg->ports[j];
{
}
-struct cmd_show_table {
- const struct ovsdb_idl_table_class *table;
- const struct ovsdb_idl_column *name_column;
- const struct ovsdb_idl_column *columns[3];
- bool recurse;
-};
-
static struct cmd_show_table cmd_show_tables[] = {
{&ovsrec_table_open_vswitch,
NULL,
{&ovsrec_open_vswitch_col_manager_options,
&ovsrec_open_vswitch_col_bridges,
&ovsrec_open_vswitch_col_ovs_version},
- false},
+ {NULL, NULL, NULL}
+ },
{&ovsrec_table_bridge,
&ovsrec_bridge_col_name,
{&ovsrec_bridge_col_controller,
&ovsrec_bridge_col_fail_mode,
+ &ovsrec_bridge_col_datapath_type,
&ovsrec_bridge_col_ports},
- false},
+ {NULL, NULL, NULL}
+ },
{&ovsrec_table_port,
&ovsrec_port_col_name,
{&ovsrec_port_col_tag,
&ovsrec_port_col_trunks,
&ovsrec_port_col_interfaces},
- false},
+ {NULL, NULL, NULL}
+ },
{&ovsrec_table_interface,
&ovsrec_interface_col_name,
{&ovsrec_interface_col_type,
&ovsrec_interface_col_options,
- &ovsrec_interface_col_error},
- false},
+ &ovsrec_interface_col_error,
+ &ovsrec_interface_col_bfd_status},
+ {NULL, NULL, NULL}
+ },
{&ovsrec_table_controller,
&ovsrec_controller_col_target,
{&ovsrec_controller_col_is_connected,
NULL,
NULL},
- false},
+ {NULL, NULL, NULL}
+ },
{&ovsrec_table_manager,
&ovsrec_manager_col_target,
{&ovsrec_manager_col_is_connected,
NULL,
NULL},
- false},
-};
-
-static void
-pre_cmd_show(struct ctl_context *ctx)
-{
- struct cmd_show_table *show;
-
- for (show = cmd_show_tables;
- show < &cmd_show_tables[ARRAY_SIZE(cmd_show_tables)];
- show++) {
- size_t i;
-
- ovsdb_idl_add_table(ctx->idl, show->table);
- if (show->name_column) {
- ovsdb_idl_add_column(ctx->idl, show->name_column);
- }
- for (i = 0; i < ARRAY_SIZE(show->columns); i++) {
- const struct ovsdb_idl_column *column = show->columns[i];
- if (column) {
- ovsdb_idl_add_column(ctx->idl, column);
- }
- }
- }
-}
-
-static struct cmd_show_table *
-cmd_show_find_table_by_row(const struct ovsdb_idl_row *row)
-{
- struct cmd_show_table *show;
-
- for (show = cmd_show_tables;
- show < &cmd_show_tables[ARRAY_SIZE(cmd_show_tables)];
- show++) {
- if (show->table == row->table->class) {
- return show;
- }
- }
- return NULL;
-}
-
-static struct cmd_show_table *
-cmd_show_find_table_by_name(const char *name)
-{
- struct cmd_show_table *show;
-
- for (show = cmd_show_tables;
- show < &cmd_show_tables[ARRAY_SIZE(cmd_show_tables)];
- show++) {
- if (!strcmp(show->table->name, name)) {
- return show;
- }
- }
- return NULL;
-}
-
-static void
-cmd_show_row(struct ctl_context *ctx, const struct ovsdb_idl_row *row,
- int level)
-{
- struct cmd_show_table *show = cmd_show_find_table_by_row(row);
- size_t i;
-
- ds_put_char_multiple(&ctx->output, ' ', level * 4);
- if (show && show->name_column) {
- const struct ovsdb_datum *datum;
-
- ds_put_format(&ctx->output, "%s ", show->table->name);
- datum = ovsdb_idl_read(row, show->name_column);
- ovsdb_datum_to_string(datum, &show->name_column->type, &ctx->output);
- } else {
- ds_put_format(&ctx->output, UUID_FMT, UUID_ARGS(&row->uuid));
- }
- ds_put_char(&ctx->output, '\n');
-
- if (!show || show->recurse) {
- return;
- }
-
- show->recurse = true;
- for (i = 0; i < ARRAY_SIZE(show->columns); i++) {
- const struct ovsdb_idl_column *column = show->columns[i];
- const struct ovsdb_datum *datum;
-
- if (!column) {
- break;
- }
-
- datum = ovsdb_idl_read(row, column);
- if (column->type.key.type == OVSDB_TYPE_UUID &&
- column->type.key.u.uuid.refTableName) {
- struct cmd_show_table *ref_show;
- size_t j;
-
- ref_show = cmd_show_find_table_by_name(
- column->type.key.u.uuid.refTableName);
- if (ref_show) {
- for (j = 0; j < datum->n; j++) {
- const struct ovsdb_idl_row *ref_row;
-
- ref_row = ovsdb_idl_get_row_for_uuid(ctx->idl,
- ref_show->table,
- &datum->keys[j].uuid);
- if (ref_row) {
- cmd_show_row(ctx, ref_row, level + 1);
- }
- }
- continue;
- }
- }
-
- if (!ovsdb_datum_is_default(datum, &column->type)) {
- ds_put_char_multiple(&ctx->output, ' ', (level + 1) * 4);
- ds_put_format(&ctx->output, "%s: ", column->name);
- ovsdb_datum_to_string(datum, &column->type, &ctx->output);
- ds_put_char(&ctx->output, '\n');
- }
- }
- show->recurse = false;
-}
+ {NULL, NULL, NULL}
+ },
-static void
-cmd_show(struct ctl_context *ctx)
-{
- const struct ovsdb_idl_row *row;
-
- for (row = ovsdb_idl_first_row(ctx->idl, cmd_show_tables[0].table);
- row; row = ovsdb_idl_next_row(row)) {
- cmd_show_row(ctx, row, 0);
- }
-}
+ {NULL, NULL, {NULL, NULL, NULL}, {NULL, NULL, NULL}}
+};
static void
pre_cmd_emer_reset(struct ctl_context *ctx)
/* We only want to save the "hwaddr" key from other_config. */
hwaddr = smap_get(&br->other_config, "hwaddr");
if (hwaddr) {
- struct smap smap = SMAP_INITIALIZER(&smap);
- smap_add(&smap, "hwaddr", hwaddr);
+ const struct smap smap = SMAP_CONST1(&smap, "hwaddr", hwaddr);
ovsrec_bridge_set_other_config(br, &smap);
- smap_destroy(&smap);
} else {
ovsrec_bridge_set_other_config(br, NULL);
}
vsctl_context_invalidate_cache(ctx);
}
+static struct ovsrec_datapath *
+find_datapath(struct vsctl_context *vsctl_ctx, const char *dp_name)
+{
+ const struct ovsrec_open_vswitch *ovs = vsctl_ctx->ovs;
+
+ for (int i = 0; i < ovs->n_datapaths; i++) {
+ if (!strcmp(ovs->key_datapaths[i], dp_name)) {
+ return ovs->value_datapaths[i];
+ }
+ }
+ return NULL;
+}
+
+static struct ovsrec_ct_zone *
+find_ct_zone(struct ovsrec_datapath *dp, const int64_t zone_id)
+{
+ for (int i = 0; i < dp->n_ct_zones; i++) {
+ if (dp->key_ct_zones[i] == zone_id) {
+ return dp->value_ct_zones[i];
+ }
+ }
+ return NULL;
+}
+
+static struct ovsrec_ct_timeout_policy *
+create_timeout_policy(struct ctl_context *ctx, char **tps, int n_tps)
+{
+ const struct ovsrec_ct_timeout_policy_table *tp_table;
+ const struct ovsrec_ct_timeout_policy *row;
+ struct ovsrec_ct_timeout_policy *tp = NULL;
+ struct simap new_tp = SIMAP_INITIALIZER(&new_tp);
+
+ char **policies = xzalloc(sizeof *policies * n_tps);
+ const char **key_timeouts = xmalloc(sizeof *key_timeouts * n_tps);
+ int64_t *value_timeouts = xmalloc(sizeof *value_timeouts * n_tps);
+
+ /* Parse timeout arguments. */
+ for (int i = 0; i < n_tps; i++) {
+ policies[i] = xstrdup(tps[i]);
+
+ char *key, *value;
+ char *policy = policies[i];
+ if (!ofputil_parse_key_value(&policy, &key, &value)) {
+ goto done;
+ }
+ key_timeouts[i] = key;
+ value_timeouts[i] = atoi(value);
+ simap_put(&new_tp, key, (unsigned int)value_timeouts[i]);
+ }
+
+done:
+ tp_table = ovsrec_ct_timeout_policy_table_get(ctx->idl);
+ OVSREC_CT_TIMEOUT_POLICY_TABLE_FOR_EACH (row, tp_table) {
+ struct simap s = SIMAP_INITIALIZER(&s);
+
+ /* Convert to simap. */
+ for (int i = 0; i < row->n_timeouts; i++) {
+ simap_put(&s, row->key_timeouts[i], row->value_timeouts[i]);
+ }
+
+ if (simap_equal(&s, &new_tp)) {
+ tp = CONST_CAST(struct ovsrec_ct_timeout_policy *, row);
+ simap_destroy(&s);
+ break;
+ }
+ simap_destroy(&s);
+ }
+
+ if (!tp) {
+ tp = ovsrec_ct_timeout_policy_insert(ctx->txn);
+ ovsrec_ct_timeout_policy_set_timeouts(tp, key_timeouts,
+ (const int64_t *)value_timeouts,
+ n_tps);
+ }
+
+ for (int i = 0; i < n_tps; i++) {
+ free(policies[i]);
+ }
+ free(policies);
+ simap_destroy(&new_tp);
+ free(key_timeouts);
+ free(value_timeouts);
+ return tp;
+}
+
+static void
+cmd_add_zone_tp(struct ctl_context *ctx)
+{
+ struct vsctl_context *vsctl_ctx = vsctl_context_cast(ctx);
+ struct ovsrec_ct_timeout_policy *tp;
+ int64_t zone_id;
+
+ const char *dp_name = ctx->argv[1];
+ ovs_scan(ctx->argv[2], "zone=%"SCNi64, &zone_id);
+ bool may_exist = shash_find(&ctx->options, "--may-exist") != NULL;
+
+ struct ovsrec_datapath *dp = find_datapath(vsctl_ctx, dp_name);
+ if (!dp) {
+ ctl_fatal("datapath %s does not exist", dp_name);
+ }
+
+ int n_tps = ctx->argc - 3;
+ struct ovsrec_ct_zone *zone = find_ct_zone(dp, zone_id);
+
+ if (n_tps <= 0) {
+ ctl_fatal("No timeout policy");
+ }
+
+ if (zone && !may_exist) {
+ ctl_fatal("zone id %"PRIu64" already exists", zone_id);
+ }
+
+ tp = create_timeout_policy(ctx, &ctx->argv[3], n_tps);
+ if (zone) {
+ ovsrec_ct_zone_set_timeout_policy(zone, tp);
+ } else {
+ zone = ovsrec_ct_zone_insert(ctx->txn);
+ ovsrec_ct_zone_set_timeout_policy(zone, tp);
+ ovsrec_datapath_update_ct_zones_setkey(dp, zone_id, zone);
+ }
+}
+
+static void
+cmd_del_zone_tp(struct ctl_context *ctx)
+{
+ struct vsctl_context *vsctl_ctx = vsctl_context_cast(ctx);
+ int64_t zone_id;
+
+ bool must_exist = !shash_find(&ctx->options, "--if-exists");
+ const char *dp_name = ctx->argv[1];
+ ovs_scan(ctx->argv[2], "zone=%"SCNi64, &zone_id);
+
+ struct ovsrec_datapath *dp = find_datapath(vsctl_ctx, dp_name);
+ if (!dp) {
+ ctl_fatal("datapath %s does not exist", dp_name);
+ }
+
+ struct ovsrec_ct_zone *zone = find_ct_zone(dp, zone_id);
+ if (must_exist && !zone) {
+ ctl_fatal("zone id %"PRIu64" does not exist", zone_id);
+ }
+
+ if (zone) {
+ ovsrec_datapath_update_ct_zones_delkey(dp, zone_id);
+ }
+}
+
+static void
+cmd_list_zone_tp(struct ctl_context *ctx)
+{
+ struct vsctl_context *vsctl_ctx = vsctl_context_cast(ctx);
+
+ struct ovsrec_datapath *dp = find_datapath(vsctl_ctx, ctx->argv[1]);
+ if (!dp) {
+ ctl_fatal("datapath: %s record not found", ctx->argv[1]);
+ }
+
+ for (int i = 0; i < dp->n_ct_zones; i++) {
+ struct ovsrec_ct_zone *zone = dp->value_ct_zones[i];
+ ds_put_format(&ctx->output, "Zone:%"PRIu64", Timeout Policies: ",
+ dp->key_ct_zones[i]);
+
+ struct ovsrec_ct_timeout_policy *tp = zone->timeout_policy;
+
+ if (tp) {
+ for (int j = 0; j < tp->n_timeouts; j++) {
+ ds_put_format(&ctx->output, "%s=%"PRIu64" ",
+ tp->key_timeouts[j], tp->value_timeouts[j]);
+ }
+ } else {
+ ds_put_cstr(&ctx->output, "system default");
+ }
+ ds_chomp(&ctx->output, ' ');
+ ds_put_char(&ctx->output, '\n');
+ }
+}
+
+static void
+pre_get_zone(struct ctl_context *ctx)
+{
+ ovsdb_idl_add_column(ctx->idl, &ovsrec_open_vswitch_col_datapaths);
+ ovsdb_idl_add_column(ctx->idl, &ovsrec_datapath_col_ct_zones);
+ ovsdb_idl_add_column(ctx->idl, &ovsrec_ct_zone_col_timeout_policy);
+ ovsdb_idl_add_column(ctx->idl, &ovsrec_ct_timeout_policy_col_timeouts);
+}
+
+static void
+pre_get_dp_cap(struct ctl_context *ctx)
+{
+ ovsdb_idl_add_column(ctx->idl, &ovsrec_open_vswitch_col_datapaths);
+ ovsdb_idl_add_column(ctx->idl, &ovsrec_datapath_col_capabilities);
+}
+
+static void
+cmd_list_dp_cap(struct ctl_context *ctx)
+{
+ struct vsctl_context *vsctl_ctx = vsctl_context_cast(ctx);
+ struct smap_node *node;
+
+ struct ovsrec_datapath *dp = find_datapath(vsctl_ctx, ctx->argv[1]);
+ if (!dp) {
+ ctl_fatal("datapath \"%s\" record not found", ctx->argv[1]);
+ }
+
+ SMAP_FOR_EACH (node, &dp->capabilities) {
+ ds_put_format(&ctx->output, "%s=%s ",node->key, node->value);
+ }
+ ds_chomp(&ctx->output, ' ');
+ ds_put_char(&ctx->output, '\n');
+}
+
static void
cmd_add_br(struct ctl_context *ctx)
{
int vlan;
br_name = ctx->argv[1];
+ if (!br_name[0]) {
+ ctl_fatal("bridge name must not be empty string");
+ }
if (ctx->argc == 2) {
parent_name = NULL;
vlan = 0;
vsctl_context_populate_cache(ctx);
if (!find_bridge(vsctl_ctx, ctx->argv[1], false)) {
- ctl_exit(2);
+ vsctl_exit(2);
}
}
char *settings[], int n_settings)
{
struct vsctl_context *vsctl_ctx = vsctl_context_cast(ctx);
- struct vsctl_port *vsctl_port;
struct vsctl_bridge *bridge;
struct ovsrec_interface **ifaces;
struct ovsrec_port *port;
size_t i;
+ if (!port_name[0]) {
+ ctl_fatal("port name must not be empty string");
+ }
+ for (i = 0; i < n_ifaces; i++) {
+ if (!iface_names[i][0]) {
+ ctl_fatal("interface name must not be empty string");
+ }
+ }
+
vsctl_context_populate_cache(ctx);
if (may_exist) {
struct vsctl_port *vsctl_port;
}
for (i = 0; i < n_settings; i++) {
- set_column(get_table("Port"), &port->header_, settings[i],
- ctx->symtab);
+ char *error = ctl_set_column("Port", &port->header_, settings[i],
+ ctx->symtab);
+ if (error) {
+ ctl_fatal("%s", error);
+ }
}
bridge_insert_port((bridge->parent ? bridge->parent->br_cfg
: bridge->br_cfg), port);
- vsctl_port = add_port_to_cache(vsctl_ctx, bridge, port);
+ struct vsctl_port *vsctl_port = add_port_to_cache(vsctl_ctx, bridge, port);
for (i = 0; i < n_ifaces; i++) {
add_iface_to_cache(vsctl_ctx, vsctl_port, ifaces[i]);
}
&ctx->argv[n_ifaces + 3], ctx->argc - 3 - n_ifaces);
}
+static void
+cmd_add_bond_iface(struct ctl_context *ctx)
+{
+ vsctl_context_populate_cache(ctx);
+
+ struct vsctl_context *vsctl_ctx = vsctl_context_cast(ctx);
+ bool may_exist = shash_find(&ctx->options, "--may-exist") != NULL;
+ struct vsctl_port *port = find_port(vsctl_ctx, ctx->argv[1], true);
+
+ const char *iface_name = ctx->argv[2];
+ if (may_exist) {
+ struct vsctl_iface *iface = find_iface(vsctl_ctx, iface_name, false);
+ if (iface) {
+ if (iface->port == port) {
+ return;
+ }
+ char *command = vsctl_context_to_string(ctx);
+ ctl_fatal("\"%s\" but %s is actually attached to port %s",
+ command, iface_name, iface->port->port_cfg->name);
+ }
+ }
+ check_conflicts(vsctl_ctx, iface_name,
+ xasprintf("cannot create an interface named %s",
+ iface_name));
+
+ struct ovsrec_interface *iface = ovsrec_interface_insert(ctx->txn);
+ ovsrec_interface_set_name(iface, iface_name);
+ ovsrec_port_update_interfaces_addvalue(port->port_cfg, iface);
+ post_db_reload_expect_iface(iface);
+ add_iface_to_cache(vsctl_ctx, port, iface);
+}
+
+static void
+cmd_del_bond_iface(struct ctl_context *ctx)
+{
+ vsctl_context_populate_cache(ctx);
+
+ struct vsctl_context *vsctl_ctx = vsctl_context_cast(ctx);
+ const char *iface_name = ctx->argv[ctx->argc - 1];
+ bool must_exist = !shash_find(&ctx->options, "--if-exists");
+ struct vsctl_iface *iface = find_iface(vsctl_ctx, iface_name, must_exist);
+ if (!iface) {
+ ovs_assert(!must_exist);
+ return;
+ }
+
+ const char *port_name = ctx->argc > 2 ? ctx->argv[1] : NULL;
+ if (port_name) {
+ struct vsctl_port *port = find_port(vsctl_ctx, port_name, true);
+ if (iface->port != port) {
+ ctl_fatal("port %s does not have an interface %s",
+ port_name, iface_name);
+ }
+ }
+
+ if (ovs_list_is_short(&iface->port->ifaces)) {
+ ctl_fatal("cannot delete last interface from port %s",
+ iface->port->port_cfg->name);
+ }
+
+ ovsrec_port_update_interfaces_delvalue(iface->port->port_cfg,
+ iface->iface_cfg);
+ del_cached_iface(vsctl_ctx, iface);
+}
+
static void
cmd_del_port(struct ctl_context *ctx)
{
if (port->bridge != bridge) {
if (port->bridge->parent == bridge) {
ctl_fatal("bridge %s does not have a port %s (although "
- "its parent bridge %s does)",
+ "its child bridge %s does)",
ctx->argv[1], ctx->argv[2],
- bridge->parent->name);
+ port->bridge->name);
} else {
ctl_fatal("bridge %s does not have a port %s",
ctx->argv[1], ctx->argv[2]);
pre_get_info(ctx);
ovsdb_idl_add_column(ctx->idl, &ovsrec_controller_col_target);
+ ovsdb_idl_add_column(ctx->idl, &ovsrec_controller_col_inactivity_probe);
}
static void
}
static struct ovsrec_controller **
-insert_controllers(struct ovsdb_idl_txn *txn, char *targets[], size_t n)
+insert_controllers(struct ctl_context *ctx, char *targets[], size_t n)
{
struct ovsrec_controller **controllers;
size_t i;
+ const char *inactivity_probe = shash_find_data(&ctx->options,
+ "--inactivity-probe");
controllers = xmalloc(n * sizeof *controllers);
for (i = 0; i < n; i++) {
if (vconn_verify_name(targets[i]) && pvconn_verify_name(targets[i])) {
VLOG_WARN("target type \"%s\" is possibly erroneous", targets[i]);
}
- controllers[i] = ovsrec_controller_insert(txn);
+ controllers[i] = ovsrec_controller_insert(ctx->txn);
ovsrec_controller_set_target(controllers[i], targets[i]);
+ if (inactivity_probe) {
+ int64_t msecs = atoll(inactivity_probe);
+ ovsrec_controller_set_inactivity_probe(controllers[i], &msecs, 1);
+ }
}
return controllers;
delete_controllers(br->controller, br->n_controller);
n = ctx->argc - 2;
- controllers = insert_controllers(ctx->txn, &ctx->argv[2], n);
+ controllers = insert_controllers(ctx, &ctx->argv[2], n);
ovsrec_bridge_set_controller(br, controllers, n);
free(controllers);
}
{
ovsdb_idl_add_column(ctx->idl, &ovsrec_open_vswitch_col_manager_options);
ovsdb_idl_add_column(ctx->idl, &ovsrec_manager_col_target);
+ ovsdb_idl_add_column(ctx->idl, &ovsrec_manager_col_inactivity_probe);
}
static void
}
static void
-insert_managers(struct vsctl_context *vsctl_ctx, char *targets[], size_t n)
+insert_managers(struct vsctl_context *vsctl_ctx, char *targets[], size_t n,
+ struct shash *options)
{
struct ovsrec_manager **managers;
size_t i;
+ const char *inactivity_probe = shash_find_data(options,
+ "--inactivity-probe");
/* Insert each manager in a new row in Manager table. */
managers = xmalloc(n * sizeof *managers);
}
managers[i] = ovsrec_manager_insert(vsctl_ctx->base.txn);
ovsrec_manager_set_target(managers[i], targets[i]);
+ if (inactivity_probe) {
+ int64_t msecs = atoll(inactivity_probe);
+ ovsrec_manager_set_inactivity_probe(managers[i], &msecs, 1);
+ }
}
/* Store uuids of new Manager rows in 'manager_options' column. */
verify_managers(vsctl_ctx->ovs);
delete_managers(vsctl_ctx->ovs);
- insert_managers(vsctl_ctx, &ctx->argv[1], n);
+ insert_managers(vsctl_ctx, &ctx->argv[1], n, &ctx->options);
}
static void
br = br->parent;
}
- if (br && br->br_cfg) {
+ if (br->br_cfg) {
if (!br->br_cfg->auto_attach) {
struct ovsrec_autoattach *aa = ovsrec_autoattach_insert(ctx->txn);
ovsrec_bridge_set_auto_attach(br->br_cfg, aa);
br = br->parent;
}
- if (br && br->br_cfg && br->br_cfg->auto_attach &&
+ if (br->br_cfg && br->br_cfg->auto_attach &&
br->br_cfg->auto_attach->key_mappings &&
br->br_cfg->auto_attach->value_mappings) {
size_t i;
verify_auto_attach(br->br_cfg);
- if (br && br->br_cfg && br->br_cfg->auto_attach &&
+ if (br->br_cfg && br->br_cfg->auto_attach &&
br->br_cfg->auto_attach->key_mappings &&
br->br_cfg->auto_attach->value_mappings) {
size_t i;
}
\f
-const struct ctl_table_class tables[] = {
- {&ovsrec_table_bridge,
- {{&ovsrec_table_bridge, &ovsrec_bridge_col_name, NULL},
- {&ovsrec_table_flow_sample_collector_set, NULL,
- &ovsrec_flow_sample_collector_set_col_bridge}}},
+static const struct ctl_table_class tables[OVSREC_N_TABLES] = {
+ [OVSREC_TABLE_BRIDGE].row_ids[0] = {&ovsrec_bridge_col_name, NULL, NULL},
- {&ovsrec_table_controller,
- {{&ovsrec_table_bridge,
- &ovsrec_bridge_col_name,
- &ovsrec_bridge_col_controller}}},
+ [OVSREC_TABLE_CONTROLLER].row_ids[0]
+ = {&ovsrec_bridge_col_name, NULL, &ovsrec_bridge_col_controller},
- {&ovsrec_table_interface,
- {{&ovsrec_table_interface, &ovsrec_interface_col_name, NULL},
- {NULL, NULL, NULL}}},
+ [OVSREC_TABLE_INTERFACE].row_ids[0]
+ = {&ovsrec_interface_col_name, NULL, NULL},
- {&ovsrec_table_mirror,
- {{&ovsrec_table_mirror, &ovsrec_mirror_col_name, NULL},
- {NULL, NULL, NULL}}},
+ [OVSREC_TABLE_MIRROR].row_ids[0] = {&ovsrec_mirror_col_name, NULL, NULL},
- {&ovsrec_table_manager,
- {{&ovsrec_table_manager, &ovsrec_manager_col_target, NULL},
- {NULL, NULL, NULL}}},
+ [OVSREC_TABLE_MANAGER].row_ids[0]
+ = {&ovsrec_manager_col_target, NULL, NULL},
- {&ovsrec_table_netflow,
- {{&ovsrec_table_bridge,
- &ovsrec_bridge_col_name,
- &ovsrec_bridge_col_netflow},
- {NULL, NULL, NULL}}},
+ [OVSREC_TABLE_NETFLOW].row_ids[0]
+ = {&ovsrec_bridge_col_name, NULL, &ovsrec_bridge_col_netflow},
- {&ovsrec_table_open_vswitch,
- {{&ovsrec_table_open_vswitch, NULL, NULL},
- {NULL, NULL, NULL}}},
+ [OVSREC_TABLE_PORT].row_ids[0] = {&ovsrec_port_col_name, NULL, NULL},
- {&ovsrec_table_port,
- {{&ovsrec_table_port, &ovsrec_port_col_name, NULL},
- {NULL, NULL, NULL}}},
-
- {&ovsrec_table_qos,
- {{&ovsrec_table_port, &ovsrec_port_col_name, &ovsrec_port_col_qos},
- {NULL, NULL, NULL}}},
-
- {&ovsrec_table_queue,
- {{NULL, NULL, NULL},
- {NULL, NULL, NULL}}},
-
- {&ovsrec_table_ssl,
- {{&ovsrec_table_open_vswitch, NULL, &ovsrec_open_vswitch_col_ssl}}},
-
- {&ovsrec_table_sflow,
- {{&ovsrec_table_bridge,
- &ovsrec_bridge_col_name,
- &ovsrec_bridge_col_sflow},
- {NULL, NULL, NULL}}},
-
- {&ovsrec_table_flow_table,
- {{&ovsrec_table_flow_table, &ovsrec_flow_table_col_name, NULL},
- {NULL, NULL, NULL}}},
-
- {&ovsrec_table_ipfix,
- {{&ovsrec_table_bridge,
- &ovsrec_bridge_col_name,
- &ovsrec_bridge_col_ipfix},
- {&ovsrec_table_flow_sample_collector_set, NULL,
- &ovsrec_flow_sample_collector_set_col_ipfix}}},
-
- {&ovsrec_table_autoattach,
- {{&ovsrec_table_bridge,
- &ovsrec_bridge_col_name,
- &ovsrec_bridge_col_auto_attach},
- {NULL, NULL, NULL}}},
-
- {&ovsrec_table_flow_sample_collector_set,
- {{NULL, NULL, NULL},
- {NULL, NULL, NULL}}},
-
- {NULL, {{NULL, NULL, NULL}, {NULL, NULL, NULL}}}
+ [OVSREC_TABLE_QOS].row_ids[0]
+ = {&ovsrec_port_col_name, NULL, &ovsrec_port_col_qos},
+
+ [OVSREC_TABLE_SFLOW].row_ids[0]
+ = {&ovsrec_bridge_col_name, NULL, &ovsrec_bridge_col_sflow},
+
+ [OVSREC_TABLE_FLOW_TABLE].row_ids[0]
+ = {&ovsrec_flow_table_col_name, NULL, NULL},
+
+ [OVSREC_TABLE_IPFIX].row_ids[0]
+ = {&ovsrec_bridge_col_name, NULL, &ovsrec_bridge_col_ipfix},
+
+ [OVSREC_TABLE_AUTOATTACH].row_ids[0]
+ = {&ovsrec_bridge_col_name, NULL, &ovsrec_bridge_col_auto_attach},
+
+ [OVSREC_TABLE_FLOW_SAMPLE_COLLECTOR_SET].row_ids[0]
+ = {&ovsrec_flow_sample_collector_set_col_id, NULL, NULL},
};
static void
static void
post_db_reload_do_checks(const struct vsctl_context *vsctl_ctx)
{
- struct ds dead_ifaces = DS_EMPTY_INITIALIZER;
+ bool print_error = false;
size_t i;
for (i = 0; i < n_neoteric_ifaces; i++) {
iface = ovsrec_interface_get_for_uuid(vsctl_ctx->base.idl, uuid);
if (iface && (!iface->ofport || *iface->ofport == -1)) {
- ds_put_format(&dead_ifaces, "'%s', ", iface->name);
+ if (iface->error && *iface->error) {
+ ovs_error(0, "Error detected while setting up '%s': %s. "
+ "See ovs-vswitchd log for details.",
+ iface->name, iface->error);
+ } else {
+ ovs_error(0, "Error detected while setting up '%s'. "
+ "See ovs-vswitchd log for details.",
+ iface->name);
+ }
+ print_error = true;
}
}
}
- if (dead_ifaces.length) {
- dead_ifaces.length -= 2; /* Strip off trailing comma and space. */
- ovs_error(0, "Error detected while setting up %s. See ovs-vswitchd "
- "log for details.", ds_cstr(&dead_ifaces));
+ if (print_error) {
+ ovs_error(0, "The default log directory is \"%s\".", ovs_logdir());
}
-
- ds_destroy(&dead_ifaces);
}
\f
vsctl_context_init(&vsctl_ctx, c, idl, NULL, NULL, NULL);
(c->syntax->prerequisites)(&vsctl_ctx.base);
+ if (vsctl_ctx.base.error) {
+ ctl_fatal("%s", vsctl_ctx.base.error);
+ }
vsctl_context_done(&vsctl_ctx, c);
ovs_assert(!c->output.string);
}
}
-static void
+static char *
+vsctl_parent_process_info(void)
+{
+#ifdef __linux__
+ pid_t parent_pid;
+ struct ds s;
+
+ parent_pid = getppid();
+ ds_init(&s);
+
+ /* Retrive the command line of the parent process, except the init
+ * process since /proc/0 does not exist. */
+ if (parent_pid) {
+ char *procfile;
+ FILE *f;
+
+ procfile = xasprintf("/proc/%d/cmdline", parent_pid);
+
+ f = fopen(procfile, "r");
+ free(procfile);
+ if (f) {
+ ds_get_line(&s, f);
+ fclose(f);
+ }
+ } else {
+ ds_put_cstr(&s, "init");
+ }
+
+ ds_put_format(&s, " (pid %d)", parent_pid);
+ return ds_steal_cstr(&s);
+#else
+ return NULL;
+#endif
+}
+
+static bool
do_vsctl(const char *args, struct ctl_command *commands, size_t n_commands,
struct ovsdb_idl *idl)
{
struct ctl_command *c;
struct shash_node *node;
int64_t next_cfg = 0;
- char *error = NULL;
+ char *ppid_info = NULL;
txn = the_idl_txn = ovsdb_idl_txn_create(idl);
if (dry_run) {
ovsdb_idl_txn_set_dry_run(txn);
}
- ovsdb_idl_txn_add_comment(txn, "ovs-vsctl: %s", args);
+ ppid_info = vsctl_parent_process_info();
+ if (ppid_info) {
+ ovsdb_idl_txn_add_comment(txn, "ovs-vsctl (invoked by %s): %s",
+ ppid_info, args);
+ free(ppid_info);
+ } else {
+ ovsdb_idl_txn_add_comment(txn, "ovs-vsctl: %s", args);
+ }
ovs = ovsrec_open_vswitch_first(idl);
if (!ovs) {
if (wait_for_reload) {
ovsdb_idl_txn_increment(txn, &ovs->header_,
- &ovsrec_open_vswitch_col_next_cfg);
+ &ovsrec_open_vswitch_col_next_cfg, false);
}
post_db_reload_check_init();
if (c->syntax->run) {
(c->syntax->run)(&vsctl_ctx.base);
}
+ if (vsctl_ctx.base.error) {
+ ctl_fatal("%s", vsctl_ctx.base.error);
+ }
vsctl_context_done_command(&vsctl_ctx, c);
if (vsctl_ctx.base.try_again) {
if (c->syntax->postprocess) {
vsctl_context_init(&vsctl_ctx, c, idl, txn, ovs, symtab);
(c->syntax->postprocess)(&vsctl_ctx.base);
+ if (vsctl_ctx.base.error) {
+ ctl_fatal("%s", vsctl_ctx.base.error);
+ }
vsctl_context_done(&vsctl_ctx, c);
}
}
}
- error = xstrdup(ovsdb_idl_txn_get_error(txn));
switch (status) {
case TXN_UNCOMMITTED:
goto try_again;
case TXN_ERROR:
- ctl_fatal("transaction error: %s", error);
+ ctl_fatal("transaction error: %s", ovsdb_idl_txn_get_error(txn));
case TXN_NOT_LOCKED:
/* Should not happen--we never call ovsdb_idl_set_lock(). */
default:
OVS_NOT_REACHED();
}
- free(error);
ovsdb_symbol_table_destroy(symtab);
ovsdb_idl_txn_destroy(txn);
ovsdb_idl_destroy(idl);
- exit(EXIT_SUCCESS);
+ return true;
try_again:
/* Our transaction needs to be rerun, or a prerequisite was not met. Free
* resources and return so that the caller can try again. */
- if (txn) {
- ovsdb_idl_txn_abort(txn);
- ovsdb_idl_txn_destroy(txn);
- the_idl_txn = NULL;
- }
+ ovsdb_idl_txn_abort(txn);
+ ovsdb_idl_txn_destroy(txn);
+ the_idl_txn = NULL;
+
ovsdb_symbol_table_destroy(symtab);
for (c = commands; c < &commands[n_commands]; c++) {
ds_destroy(&c->output);
table_destroy(c->table);
free(c->table);
}
- free(error);
+ return false;
+}
+
+/* Frees the current transaction and the underlying IDL and then calls
+ * exit(status).
+ *
+ * Freeing the transaction and the IDL is not strictly necessary, but it makes
+ * for a clean memory leak report from valgrind in the normal case. That makes
+ * it easier to notice real memory leaks. */
+static void
+vsctl_exit(int status)
+{
+ if (the_idl_txn) {
+ ovsdb_idl_txn_abort(the_idl_txn);
+ ovsdb_idl_txn_destroy(the_idl_txn);
+ }
+ ovsdb_idl_destroy(the_idl);
+ exit(status);
}
/*
static const struct ctl_command_syntax vsctl_commands[] = {
/* Open vSwitch commands. */
{"init", 0, 0, "", NULL, cmd_init, NULL, "", RW},
- {"show", 0, 0, "", pre_cmd_show, cmd_show, NULL, "", RO},
/* Bridge commands. */
{"add-br", 1, 3, "NEW-BRIDGE [PARENT] [NEW-VLAN]", pre_get_info,
RO},
{"add-port", 2, INT_MAX, "BRIDGE NEW-PORT [COLUMN[:KEY]=VALUE]...",
pre_get_info, cmd_add_port, NULL, "--may-exist", RW},
- {"add-bond", 4, INT_MAX,
- "BRIDGE NEW-BOND-PORT SYSIFACE... [COLUMN[:KEY]=VALUE]...", pre_get_info,
- cmd_add_bond, NULL, "--may-exist,--fake-iface", RW},
{"del-port", 1, 2, "[BRIDGE] PORT|IFACE", pre_get_info, cmd_del_port, NULL,
"--if-exists,--with-iface", RW},
{"port-to-br", 1, 1, "PORT", pre_get_info, cmd_port_to_br, NULL, "", RO},
+ /* Bond commands. */
+ {"add-bond", 4, INT_MAX,
+ "BRIDGE BOND IFACE... [COLUMN[:KEY]=VALUE]...", pre_get_info,
+ cmd_add_bond, NULL, "--may-exist,--fake-iface", RW},
+ {"add-bond-iface", 2, 2, "BOND IFACE", pre_get_info, cmd_add_bond_iface,
+ NULL, "--may-exist", RW},
+ {"del-bond-iface", 1, 2, "[BOND] IFACE", pre_get_info, cmd_del_bond_iface,
+ NULL, "--if-exists", RW},
+
/* Interface commands. */
{"list-ifaces", 1, 1, "BRIDGE", pre_get_info, cmd_list_ifaces, NULL, "",
RO},
{"del-controller", 1, 1, "BRIDGE", pre_controller, cmd_del_controller,
NULL, "", RW},
{"set-controller", 1, INT_MAX, "BRIDGE TARGET...", pre_controller,
- cmd_set_controller, NULL, "", RW},
+ cmd_set_controller, NULL, "--inactivity-probe=", RW},
{"get-fail-mode", 1, 1, "BRIDGE", pre_get_info, cmd_get_fail_mode, NULL,
"", RO},
{"del-fail-mode", 1, 1, "BRIDGE", pre_get_info, cmd_del_fail_mode, NULL,
{"get-manager", 0, 0, "", pre_manager, cmd_get_manager, NULL, "", RO},
{"del-manager", 0, 0, "", pre_manager, cmd_del_manager, NULL, "", RW},
{"set-manager", 1, INT_MAX, "TARGET...", pre_manager, cmd_set_manager,
- NULL, "", RW},
+ NULL, "--inactivity-probe=", RW},
/* SSL commands. */
{"get-ssl", 0, 0, "", pre_cmd_get_ssl, cmd_get_ssl, NULL, "", RO},
/* Switch commands. */
{"emer-reset", 0, 0, "", pre_cmd_emer_reset, cmd_emer_reset, NULL, "", RW},
+ /* Zone and CT Timeout Policy commands. */
+ {"add-zone-tp", 3, INT_MAX, "", pre_get_zone, cmd_add_zone_tp, NULL,
+ "--may-exist", RW},
+ {"del-zone-tp", 2, 2, "", pre_get_zone, cmd_del_zone_tp, NULL,
+ "--if-exists", RW},
+ {"list-zone-tp", 1, 1, "", pre_get_zone, cmd_list_zone_tp, NULL, "", RO},
+
+ /* Datapath capabilities. */
+ {"list-dp-cap", 1, 1, "", pre_get_dp_cap, cmd_list_dp_cap, NULL, "", RO},
+
{NULL, 0, 0, NULL, NULL, NULL, NULL, NULL, RO},
};
static void
vsctl_cmd_init(void)
{
- ctl_init();
+ ctl_init(&ovsrec_idl_class, ovsrec_table_classes, tables, cmd_show_tables,
+ vsctl_exit);
ctl_register_commands(vsctl_commands);
}