/*
- * Copyright (c) 2009, 2010, 2011 Nicira Networks.
+ * Copyright (c) 2009, 2010, 2011, 2012 Nicira Networks.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include "stream-ssl.h"
#include "sset.h"
#include "svec.h"
-#include "vswitchd/vswitch-idl.h"
+#include "vswitch-idl.h"
#include "table.h"
#include "timeval.h"
#include "util.h"
+#include "vconn.h"
#include "vlog.h"
VLOG_DEFINE_THIS_MODULE(vsctl);
static const struct vsctl_command_syntax *find_command(const char *name);
static void run_prerequisites(struct vsctl_command[], size_t n_commands,
struct ovsdb_idl *);
-static void do_vsctl(const char *args,
- struct vsctl_command *, size_t n_commands,
- struct ovsdb_idl *);
+static enum ovsdb_idl_txn_status do_vsctl(const char *args,
+ struct vsctl_command *, size_t n,
+ struct ovsdb_idl *);
static const struct vsctl_table_class *get_table(const char *table_name);
static void set_column(const struct vsctl_table_class *,
main(int argc, char *argv[])
{
extern struct vlog_module VLM_reconnect;
+ enum ovsdb_idl_txn_status status;
struct ovsdb_idl *idl;
struct vsctl_command *commands;
size_t n_commands;
run_prerequisites(commands, n_commands, idl);
/* Now execute the commands. */
+ status = TXN_AGAIN_WAIT;
for (;;) {
- if (ovsdb_idl_run(idl)) {
- do_vsctl(args, commands, n_commands, idl);
+ if (ovsdb_idl_run(idl) || status == TXN_AGAIN_NOW) {
+ status = do_vsctl(args, commands, n_commands, idl);
}
- ovsdb_idl_wait(idl);
- poll_block();
+ if (status != TXN_AGAIN_NOW) {
+ ovsdb_idl_wait(idl);
+ poll_block();
+ }
}
}
usage();
case 'V':
- OVS_PRINT_VERSION(0, 0);
+ ovs_print_version(0, 0);
exit(EXIT_SUCCESS);
case 't':
message = xvasprintf(format, args);
va_end(args);
- vlog_set_levels(&VLM_vsctl, VLF_CONSOLE, VLL_EMER);
+ vlog_set_levels(&VLM_vsctl, VLF_CONSOLE, VLL_OFF);
VLOG_ERR("%s", message);
ovs_error(0, "%s", message);
vsctl_exit(EXIT_FAILURE);
add-br BRIDGE PARENT VLAN create new fake BRIDGE in PARENT on VLAN\n\
del-br BRIDGE delete BRIDGE and all of its ports\n\
list-br print the names of all the bridges\n\
- br-exists BRIDGE test whether BRIDGE exists\n\
+ br-exists BRIDGE exit 2 if BRIDGE does not exist\n\
br-to-vlan BRIDGE print the VLAN which BRIDGE is on\n\
br-to-parent BRIDGE print the parent of BRIDGE\n\
br-set-external-id BRIDGE KEY VALUE set KEY on BRIDGE to VALUE\n\
iface-to-br IFACE print name of bridge that contains IFACE\n\
\n\
Controller commands:\n\
- get-controller BRIDGE print the controller for BRIDGE\n\
- del-controller BRIDGE delete the controller for BRIDGE\n\
- set-controller BRIDGE TARGET set the controller for BRIDGE to TARGET\n\
+ get-controller BRIDGE print the controllers for BRIDGE\n\
+ del-controller BRIDGE delete the controllers for BRIDGE\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\
set-fail-mode BRIDGE MODE set the fail-mode for BRIDGE to MODE\n\
\n\
Manager commands:\n\
- get-manager print all manager(s)\n\
- del-manager delete all manager(s)\n\
- set-manager TARGET... set the list of manager(s) to TARGET(s)\n\
+ get-manager print the managers\n\
+ del-manager delete the managers\n\
+ set-manager TARGET... set the list of managers to TARGET...\n\
\n\
SSL commands:\n\
get-ssl print the SSL configuration\n\
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);
ovsrec_controller_set_target(controllers[i], targets[i]);
}
/* Insert each manager in a new row in Manager table. */
managers = xmalloc(n * sizeof *managers);
for (i = 0; i < n; i++) {
+ if (stream_verify_name(targets[i]) && pstream_verify_name(targets[i])) {
+ VLOG_WARN("target type \"%s\" is possibly erroneous", targets[i]);
+ }
managers[i] = ovsrec_manager_insert(ctx->txn);
ovsrec_manager_set_target(managers[i], targets[i]);
}
&ovsrec_bridge_col_sflow},
{NULL, NULL, NULL}}},
+ {&ovsrec_table_flow_table,
+ {{&ovsrec_table_flow_table, &ovsrec_flow_table_col_name, NULL},
+ {NULL, NULL, NULL}}},
+
{NULL, {{NULL, NULL, NULL}, {NULL, NULL, NULL}}}
};
* - If 'valuep' is nonnull, an operator followed by a value string. The
* allowed operators are the 'n_allowed' string in 'allowed_operators',
* or just "=" if 'n_allowed' is 0. If 'operatorp' is nonnull, then the
- * operator is stored into '*operatorp' (one of the pointers from
- * 'allowed_operators' is stored; nothing is malloc()'d). The value is
- * stored as a malloc()'d string into '*valuep', or NULL if no value is
- * present in 'arg'.
+ * index of the operator within 'allowed_operators' is stored into
+ * '*operatorp'. The value is stored as a malloc()'d string into
+ * '*valuep', or NULL if no value is present in 'arg'.
*
* On success, returns NULL. On failure, returned a malloc()'d string error
* message and stores NULL into all of the nonnull output arguments. */
parse_column_key_value(const char *arg,
const struct vsctl_table_class *table,
const struct ovsdb_idl_column **columnp, char **keyp,
- const char **operatorp,
+ int *operatorp,
const char **allowed_operators, size_t n_allowed,
char **valuep)
{
/* Parse value string. */
if (valuep) {
- const char *best;
size_t best_len;
size_t i;
+ int best;
if (!allowed_operators) {
static const char *equals = "=";
n_allowed = 1;
}
- best = NULL;
+ best = -1;
best_len = 0;
for (i = 0; i < n_allowed; i++) {
const char *op = allowed_operators[i];
if (op_len > best_len && !strncmp(op, p, op_len) && p[op_len]) {
best_len = op_len;
- best = op;
+ best = i;
}
}
- if (!best) {
+ if (best < 0) {
error = missing_operator_error(arg, allowed_operators, n_allowed);
goto error;
}
free(*valuep);
*valuep = NULL;
if (operatorp) {
- *operatorp = NULL;
+ *operatorp = -1;
}
}
return error;
}
}
+#define RELOPS \
+ RELOP(RELOP_EQ, "=") \
+ RELOP(RELOP_NE, "!=") \
+ RELOP(RELOP_LT, "<") \
+ RELOP(RELOP_GT, ">") \
+ RELOP(RELOP_LE, "<=") \
+ RELOP(RELOP_GE, ">=") \
+ RELOP(RELOP_SET_EQ, "{=}") \
+ RELOP(RELOP_SET_NE, "{!=}") \
+ RELOP(RELOP_SET_LT, "{<}") \
+ RELOP(RELOP_SET_GT, "{>}") \
+ RELOP(RELOP_SET_LE, "{<=}") \
+ RELOP(RELOP_SET_GE, "{>=}")
+
+enum relop {
+#define RELOP(ENUM, STRING) ENUM,
+ RELOPS
+#undef RELOP
+};
+
+static bool
+is_set_operator(enum relop op)
+{
+ return (op == RELOP_SET_EQ || op == RELOP_SET_NE ||
+ op == RELOP_SET_LT || op == RELOP_SET_GT ||
+ op == RELOP_SET_LE || op == RELOP_SET_GE);
+}
+
+static bool
+evaluate_relop(const struct ovsdb_datum *a, const struct ovsdb_datum *b,
+ const struct ovsdb_type *type, enum relop op)
+{
+ switch (op) {
+ case RELOP_EQ:
+ case RELOP_SET_EQ:
+ return ovsdb_datum_compare_3way(a, b, type) == 0;
+ case RELOP_NE:
+ case RELOP_SET_NE:
+ return ovsdb_datum_compare_3way(a, b, type) != 0;
+ case RELOP_LT:
+ return ovsdb_datum_compare_3way(a, b, type) < 0;
+ case RELOP_GT:
+ return ovsdb_datum_compare_3way(a, b, type) > 0;
+ case RELOP_LE:
+ return ovsdb_datum_compare_3way(a, b, type) <= 0;
+ case RELOP_GE:
+ return ovsdb_datum_compare_3way(a, b, type) >= 0;
+
+ case RELOP_SET_LT:
+ return b->n > a->n && ovsdb_datum_includes_all(a, b, type);
+ case RELOP_SET_GT:
+ return a->n > b->n && ovsdb_datum_includes_all(b, a, type);
+ case RELOP_SET_LE:
+ return ovsdb_datum_includes_all(a, b, type);
+ case RELOP_SET_GE:
+ return ovsdb_datum_includes_all(b, a, type);
+
+ default:
+ NOT_REACHED();
+ }
+}
+
static bool
is_condition_satisfied(const struct vsctl_table_class *table,
const struct ovsdb_idl_row *row, const char *arg,
struct ovsdb_symbol_table *symtab)
{
static const char *operators[] = {
- "=", "!=", "<", ">", "<=", ">="
+#define RELOP(ENUM, STRING) STRING,
+ RELOPS
+#undef RELOP
};
const struct ovsdb_idl_column *column;
const struct ovsdb_datum *have_datum;
char *key_string, *value_string;
- const char *operator;
- unsigned int idx;
+ struct ovsdb_type type;
+ int operator;
+ bool retval;
char *error;
- int cmp = 0;
error = parse_column_key_value(arg, table, &column, &key_string,
&operator, operators, ARRAY_SIZE(operators),
vsctl_fatal("%s: missing value", arg);
}
+ type = column->type;
+ type.n_max = UINT_MAX;
+
have_datum = ovsdb_idl_read(row, column);
if (key_string) {
- union ovsdb_atom want_key, want_value;
+ union ovsdb_atom want_key;
+ struct ovsdb_datum b;
+ unsigned int idx;
if (column->type.value.type == OVSDB_TYPE_VOID) {
vsctl_fatal("cannot specify key to check for non-map column %s",
die_if_error(ovsdb_atom_from_string(&want_key, &column->type.key,
key_string, symtab));
- die_if_error(ovsdb_atom_from_string(&want_value, &column->type.value,
- value_string, symtab));
+
+ type.key = type.value;
+ type.value.type = OVSDB_TYPE_VOID;
+ die_if_error(ovsdb_datum_from_string(&b, &type, value_string, symtab));
idx = ovsdb_datum_find_key(have_datum,
&want_key, column->type.key.type);
- if (idx != UINT_MAX) {
- cmp = ovsdb_atom_compare_3way(&have_datum->values[idx],
- &want_value,
- column->type.value.type);
+ if (idx == UINT_MAX && !is_set_operator(operator)) {
+ retval = false;
+ } else {
+ struct ovsdb_datum a;
+
+ if (idx != UINT_MAX) {
+ a.n = 1;
+ a.keys = &have_datum->values[idx];
+ a.values = NULL;
+ } else {
+ a.n = 0;
+ a.keys = NULL;
+ a.values = NULL;
+ }
+
+ retval = evaluate_relop(&a, &b, &type, operator);
}
ovsdb_atom_destroy(&want_key, column->type.key.type);
- ovsdb_atom_destroy(&want_value, column->type.value.type);
} else {
struct ovsdb_datum want_datum;
die_if_error(ovsdb_datum_from_string(&want_datum, &column->type,
value_string, symtab));
- idx = 0;
- cmp = ovsdb_datum_compare_3way(have_datum, &want_datum,
- &column->type);
+ retval = evaluate_relop(have_datum, &want_datum, &type, operator);
ovsdb_datum_destroy(&want_datum, &column->type);
}
free(key_string);
free(value_string);
- return (idx == UINT_MAX ? false
- : !strcmp(operator, "=") ? cmp == 0
- : !strcmp(operator, "!=") ? cmp != 0
- : !strcmp(operator, "<") ? cmp < 0
- : !strcmp(operator, ">") ? cmp > 0
- : !strcmp(operator, "<=") ? cmp <= 0
- : !strcmp(operator, ">=") ? cmp >= 0
- : (abort(), 0));
+ return retval;
}
static void
}
}
-static void
+static enum ovsdb_idl_txn_status
do_vsctl(const char *args, struct vsctl_command *commands, size_t n_commands,
struct ovsdb_idl *idl)
{
vsctl_context_done(&ctx, c);
if (ctx.try_again) {
+ status = TXN_AGAIN_WAIT;
goto try_again;
}
}
case TXN_SUCCESS:
break;
- case TXN_TRY_AGAIN:
+ case TXN_AGAIN_WAIT:
+ case TXN_AGAIN_NOW:
goto try_again;
case TXN_ERROR:
free(c->table);
}
free(error);
+
+ return status;
}
static const struct vsctl_command_syntax all_commands[] = {