summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukasz Rzasik <lukasz.rzasik@gmail.com>2016-12-29 15:55:46 -0700
committerBen Pfaff <blp@ovn.org>2017-01-05 08:48:10 -0800
commit1ab39058cc1fbe9b2ce48e784284fd0383d537c5 (patch)
tree9ce73e573c744e65074f920111c8f27d01f312fa
parent84d0ca5d00fe01b29163236d48fa0f9105687149 (diff)
downloadopenvswitch-1ab39058cc1fbe9b2ce48e784284fd0383d537c5.tar.gz
ovsdb-data: Add support for integer ranges in database commands
Adding / removing a range of integers to a column accepting a set of integers requires enumarating all of the integers. This patch simplifies it by introducing 'range' concept to the database commands. Two integers separated by a hyphen represent an inclusive range. The patch adds positive and negative tests for the new syntax. The patch was tested by 'make check'. Covarage was tested by 'make check-lcov'. Signed-off-by: Lukasz Rzasik <lukasz.rzasik@gmail.com> Suggested-by: <my_ovs_discuss@yahoo.com> Suggested-by: Ben Pfaff <blp@ovn.org> Signed-off-by: Ben Pfaff <blp@ovn.org>
-rw-r--r--AUTHORS.rst1
-rw-r--r--NEWS3
-rw-r--r--lib/db-ctl-base.c10
-rw-r--r--lib/db-ctl-base.man6
-rw-r--r--lib/ovsdb-data.c198
-rw-r--r--lib/ovsdb-data.h12
-rw-r--r--lib/util.c32
-rw-r--r--lib/util.h2
-rw-r--r--tests/ovs-vsctl.at2
-rw-r--r--tests/ovsdb-data.at69
-rw-r--r--tests/test-ovsdb.c16
11 files changed, 284 insertions, 67 deletions
diff --git a/AUTHORS.rst b/AUTHORS.rst
index 1efb33218..b7f5943e5 100644
--- a/AUTHORS.rst
+++ b/AUTHORS.rst
@@ -190,6 +190,7 @@ Luca Giraudo lgiraudo@nicira.com
Lucian Petrut lpetrut@cloudbasesolutions.com
Luigi Rizzo rizzo@iet.unipi.it
Luis E. P. l31g@hotmail.com
+Lukasz Rzasik lukasz.rzasik@gmail.com
Madhu Challa challa@noironetworks.com
Mario Cabrera mario.cabrera@hpe.com
Mark D. Gray mark.d.gray@intel.com
diff --git a/NEWS b/NEWS
index beee6cc9e..1b0aa5dd0 100644
--- a/NEWS
+++ b/NEWS
@@ -59,6 +59,9 @@ Post-v2.6.0
* Ports now have a "protected" flag. Protected ports can not forward
frames to other protected ports. Unprotected ports can receive and
forward frames to protected and other unprotected ports.
+ - ovs-vsctl, ovn-nbctl, ovn-sbctl, vtep-ctl:
+ * Database commands now accept integer ranges, e.g. "set port
+ eth0 trunks=1-10" to enable trunking VLANs 1 to 10.
v2.6.0 - 27 Sep 2016
---------------------
diff --git a/lib/db-ctl-base.c b/lib/db-ctl-base.c
index 02eb328e2..e32e94541 100644
--- a/lib/db-ctl-base.c
+++ b/lib/db-ctl-base.c
@@ -677,7 +677,7 @@ is_condition_satisfied(const struct ctl_table_class *table,
column->name);
}
- die_if_error(ovsdb_atom_from_string(&want_key, &column->type.key,
+ die_if_error(ovsdb_atom_from_string(&want_key, NULL, &column->type.key,
key_string, symtab));
type.key = type.value;
@@ -823,7 +823,7 @@ cmd_get(struct ctl_context *ctx)
column->name);
}
- die_if_error(ovsdb_atom_from_string(&key,
+ die_if_error(ovsdb_atom_from_string(&key, NULL,
&column->type.key,
key_string, ctx->symtab));
@@ -1118,13 +1118,13 @@ set_column(const struct ctl_table_class *table,
column->name);
}
- die_if_error(ovsdb_atom_from_string(&key, &column->type.key,
+ die_if_error(ovsdb_atom_from_string(&key, NULL, &column->type.key,
key_string, symtab));
- die_if_error(ovsdb_atom_from_string(&value, &column->type.value,
+ die_if_error(ovsdb_atom_from_string(&value, NULL, &column->type.value,
value_string, symtab));
ovsdb_datum_init_empty(&datum);
- ovsdb_datum_add_unsafe(&datum, &key, &value, &column->type);
+ ovsdb_datum_add_unsafe(&datum, &key, &value, &column->type, NULL);
ovsdb_atom_destroy(&key, column->type.key.type);
ovsdb_atom_destroy(&value, column->type.value.type);
diff --git a/lib/db-ctl-base.man b/lib/db-ctl-base.man
index 7b30501c5..88529b5fe 100644
--- a/lib/db-ctl-base.man
+++ b/lib/db-ctl-base.man
@@ -29,7 +29,11 @@ single comma. When multiple values are present, duplicates are not
allowed, and order is not important. Conversely, some database
columns can have an empty set of values, represented as \fB[]\fR, and
square brackets may optionally enclose other non-empty sets or single
-values as well.
+values as well. For a column accepting a set of integers, database commands
+accept a range. A range is represented by two integers separated by
+\fB-\fR. A range is inclusive. A range has a maximum size of 4096
+elements. If more elements are needed, they can be specified in seperate
+ranges.
.PP
A few database columns are ``maps'' of key-value pairs, where the key
and the value are each some fixed database type. These are specified
diff --git a/lib/ovsdb-data.c b/lib/ovsdb-data.c
index 0dda73a7e..840e18fa1 100644
--- a/lib/ovsdb-data.c
+++ b/lib/ovsdb-data.c
@@ -305,6 +305,25 @@ ovsdb_symbol_referenced(struct ovsdb_symbol *symbol,
}
}
+static union ovsdb_atom *
+alloc_default_atoms(enum ovsdb_atomic_type type, size_t n)
+{
+ if (type != OVSDB_TYPE_VOID && n) {
+ union ovsdb_atom *atoms;
+ unsigned int i;
+
+ atoms = xmalloc(n * sizeof *atoms);
+ for (i = 0; i < n; i++) {
+ ovsdb_atom_init_default(&atoms[i], type);
+ }
+ return atoms;
+ } else {
+ /* Avoid wasting memory in the n == 0 case, because xmalloc(0) is
+ * treated as xmalloc(1). */
+ return NULL;
+ }
+}
+
static struct ovsdb_error * OVS_WARN_UNUSED_RESULT
ovsdb_atom_parse_uuid(struct uuid *uuid, const struct json *json,
struct ovsdb_symbol_table *symtab,
@@ -468,6 +487,7 @@ ovsdb_atom_to_json(const union ovsdb_atom *atom, enum ovsdb_atomic_type type)
static char *
ovsdb_atom_from_string__(union ovsdb_atom *atom,
+ union ovsdb_atom **range_end_atom,
const struct ovsdb_base_type *base, const char *s,
struct ovsdb_symbol_table *symtab)
{
@@ -478,9 +498,20 @@ ovsdb_atom_from_string__(union ovsdb_atom *atom,
OVS_NOT_REACHED();
case OVSDB_TYPE_INTEGER: {
- long long int integer;
- if (!str_to_llong(s, 10, &integer)) {
- return xasprintf("\"%s\" is not a valid integer", s);
+ long long int integer, end;
+ if (range_end_atom
+ && str_to_llong_range(s, 10, &integer, &end)) {
+ if (end < integer) {
+ return xasprintf("\"%s\" is not a valid range. "
+ "Range end cannot be before start.", s);
+ }
+ *range_end_atom = alloc_default_atoms(type, 1);
+ if (!(*range_end_atom)) {
+ return xasprintf("\"%s\" is not a valid range", s);
+ }
+ (*range_end_atom)->integer = end;
+ } else if (!str_to_llong(s, 10, &integer)) {
+ return xasprintf("\"%s\" is not a valid integer or range", s);
}
atom->integer = integer;
}
@@ -549,10 +580,13 @@ ovsdb_atom_from_string__(union ovsdb_atom *atom,
return NULL;
}
-/* Initializes 'atom' to a value of type 'base' parsed from 's', which takes
- * one of the following forms:
+/* Initializes 'atom' and optionally 'range_end_atom' to a value of type 'base'
+ * parsed from 's', which takes one of the following forms:
*
- * - OVSDB_TYPE_INTEGER: A decimal integer optionally preceded by a sign.
+ * - OVSDB_TYPE_INTEGER: A decimal integer optionally preceded by a sign
+ * or two decimal integers optionally preceded by a sign and separated
+ * by a hyphen, representing inclusive range of integers
+ * ['atom', 'range_end_atom'].
*
* - OVSDB_TYPE_REAL: A floating-point number in the format accepted by
* strtod().
@@ -574,23 +608,62 @@ ovsdb_atom_from_string__(union ovsdb_atom *atom,
* Returns a null pointer if successful, otherwise an error message describing
* the problem. On failure, the contents of 'atom' are indeterminate. The
* caller is responsible for freeing the atom or the error.
+ *
+ * Does not attempt to parse range if 'range_end_atom' is a null pointer.
+ * Dynamically allocates ovdsb_atom and stores its address in '*range_end_atom'
+ * if successfully parses range. Caller is responsible for deallocating
+ * the memory by calling 'ovsdb_atom_destroy' and then 'free' on the address.
+ * Does not allocate memory and sets '*range_end_atom' to a null pointer
+ * if does not parse a range or fails for any reason.
*/
char *
ovsdb_atom_from_string(union ovsdb_atom *atom,
+ union ovsdb_atom **range_end_atom,
const struct ovsdb_base_type *base, const char *s,
struct ovsdb_symbol_table *symtab)
{
struct ovsdb_error *error;
char *msg;
- msg = ovsdb_atom_from_string__(atom, base, s, symtab);
+ if (range_end_atom) {
+ *range_end_atom = NULL;
+ }
+
+ msg = ovsdb_atom_from_string__(atom, range_end_atom, base, s, symtab);
if (msg) {
return msg;
}
error = ovsdb_atom_check_constraints(atom, base);
+
+ if (!error && range_end_atom && *range_end_atom) {
+ /* Check range constraints */
+ int64_t start = atom->integer;
+ int64_t end = (*range_end_atom)->integer;
+ if (base->enum_) {
+ for (int64_t i = start + 1; i <= end; i++) {
+ union ovsdb_atom ai = { .integer = i };
+ error = ovsdb_atom_check_constraints(&ai, base);
+ if (error) {
+ break;
+ }
+ }
+ } else {
+ error = ovsdb_atom_check_constraints(*range_end_atom, base);
+ }
+
+ if (!error) {
+ error = ovsdb_atom_range_check_size(start, end);
+ }
+ }
+
if (error) {
ovsdb_atom_destroy(atom, base->type);
+ if (range_end_atom && *range_end_atom) {
+ ovsdb_atom_destroy(*range_end_atom, base->type);
+ free(*range_end_atom);
+ *range_end_atom = NULL;
+ }
msg = ovsdb_error_to_string(error);
ovsdb_error_destroy(error);
}
@@ -811,25 +884,6 @@ ovsdb_atom_check_constraints(const union ovsdb_atom *atom,
}
}
-static union ovsdb_atom *
-alloc_default_atoms(enum ovsdb_atomic_type type, size_t n)
-{
- if (type != OVSDB_TYPE_VOID && n) {
- union ovsdb_atom *atoms;
- unsigned int i;
-
- atoms = xmalloc(n * sizeof *atoms);
- for (i = 0; i < n; i++) {
- ovsdb_atom_init_default(&atoms[i], type);
- }
- return atoms;
- } else {
- /* Avoid wasting memory in the n == 0 case, because xmalloc(0) is
- * treated as xmalloc(1). */
- return NULL;
- }
-}
-
/* Initializes 'datum' as an empty datum. (An empty datum can be treated as
* any type.) */
void
@@ -1336,13 +1390,15 @@ skip_spaces(const char *p)
static char *
parse_atom_token(const char **s, const struct ovsdb_base_type *base,
- union ovsdb_atom *atom, struct ovsdb_symbol_table *symtab)
+ union ovsdb_atom *atom, union ovsdb_atom **range_end_atom,
+ struct ovsdb_symbol_table *symtab)
{
char *token, *error;
error = ovsdb_token_parse(s, &token);
if (!error) {
- error = ovsdb_atom_from_string(atom, base, token, symtab);
+ error = ovsdb_atom_from_string(atom, range_end_atom,
+ base, token, symtab);
free(token);
}
return error;
@@ -1351,37 +1407,50 @@ parse_atom_token(const char **s, const struct ovsdb_base_type *base,
static char *
parse_key_value(const char **s, const struct ovsdb_type *type,
union ovsdb_atom *key, union ovsdb_atom *value,
- struct ovsdb_symbol_table *symtab)
+ struct ovsdb_symbol_table *symtab,
+ union ovsdb_atom **range_end_key)
{
const char *start = *s;
char *error;
- error = parse_atom_token(s, &type->key, key, symtab);
+ error = parse_atom_token(s, &type->key, key, range_end_key, symtab);
+
if (!error && type->value.type != OVSDB_TYPE_VOID) {
*s = skip_spaces(*s);
if (**s == '=') {
(*s)++;
*s = skip_spaces(*s);
- error = parse_atom_token(s, &type->value, value, symtab);
+ error = parse_atom_token(s, &type->value, value, NULL, symtab);
} else {
error = xasprintf("%s: syntax error at \"%c\" expecting \"=\"",
start, **s);
}
if (error) {
ovsdb_atom_destroy(key, type->key.type);
+ if (range_end_key && *range_end_key) {
+ ovsdb_atom_destroy(*range_end_key, type->key.type);
+ free(*range_end_key);
+ *range_end_key = NULL;
+ }
}
}
return error;
}
static void
-free_key_value(const struct ovsdb_type *type,
- union ovsdb_atom *key, union ovsdb_atom *value)
+free_key_value_range(const struct ovsdb_type *type,
+ union ovsdb_atom *key, union ovsdb_atom *value,
+ union ovsdb_atom **range_end_atom)
{
ovsdb_atom_destroy(key, type->key.type);
if (type->value.type != OVSDB_TYPE_VOID) {
ovsdb_atom_destroy(value, type->value.type);
}
+ if (range_end_atom && *range_end_atom) {
+ ovsdb_atom_destroy(*range_end_atom, type->key.type);
+ free(*range_end_atom);
+ *range_end_atom = NULL;
+ }
}
/* Initializes 'datum' as a datum of the given 'type', parsing its contents
@@ -1423,6 +1492,7 @@ ovsdb_datum_from_string(struct ovsdb_datum *datum,
while (*p && *p != end_delim) {
union ovsdb_atom key, value;
+ union ovsdb_atom *range_end_key = NULL;
if (ovsdb_token_is_delim(*p)) {
char *type_str = ovsdb_type_to_english(type);
@@ -1433,12 +1503,13 @@ ovsdb_datum_from_string(struct ovsdb_datum *datum,
}
/* Add to datum. */
- error = parse_key_value(&p, type, &key, &value, symtab);
+ error = parse_key_value(&p, type, &key, &value,
+ symtab, &range_end_key);
if (error) {
goto error;
}
- ovsdb_datum_add_unsafe(datum, &key, &value, type);
- free_key_value(type, &key, &value);
+ ovsdb_datum_add_unsafe(datum, &key, &value, type, range_end_key);
+ free_key_value_range(type, &key, &value, &range_end_key);
/* Skip optional white space and comma. */
p = skip_spaces(p);
@@ -1760,11 +1831,16 @@ ovsdb_datum_remove_unsafe(struct ovsdb_datum *datum, size_t idx,
}
/* Adds the element with the given 'key' and 'value' to 'datum', which must
- * have the specified 'type'.
+ * have the specified 'type'. Optionally if 'range_end_atom' is not
+ * a null pointer, adds a set of integers to 'datum' from inclusive
+ * range ['key', 'range_end_atom'].
*
* This function always allocates memory, so it is not an efficient way to add
* a number of elements to a datum.
*
+ * When adding a range of integers, this function allocates the memory once
+ * for the whole range.
+ *
* This function does not maintain ovsdb_datum invariants. Use
* ovsdb_datum_sort() to check and restore these invariants. (But a datum with
* 0 or 1 elements cannot violate the invariants anyhow.) */
@@ -1772,15 +1848,24 @@ void
ovsdb_datum_add_unsafe(struct ovsdb_datum *datum,
const union ovsdb_atom *key,
const union ovsdb_atom *value,
- const struct ovsdb_type *type)
+ const struct ovsdb_type *type,
+ const union ovsdb_atom *range_end_atom)
{
- size_t idx = datum->n++;
+ size_t idx = datum->n;
+ datum->n += range_end_atom ?
+ (range_end_atom->integer - key->integer + 1) : 1;
datum->keys = xrealloc(datum->keys, datum->n * sizeof *datum->keys);
- ovsdb_atom_clone(&datum->keys[idx], key, type->key.type);
- if (type->value.type != OVSDB_TYPE_VOID) {
- datum->values = xrealloc(datum->values,
- datum->n * sizeof *datum->values);
- ovsdb_atom_clone(&datum->values[idx], value, type->value.type);
+ if (range_end_atom && key->integer <= range_end_atom->integer) {
+ for (int64_t i = key->integer; i <= range_end_atom->integer; i++) {
+ datum->keys[idx++].integer = i;
+ }
+ } else {
+ ovsdb_atom_clone(&datum->keys[idx], key, type->key.type);
+ if (type->value.type != OVSDB_TYPE_VOID) {
+ datum->values = xrealloc(datum->values,
+ datum->n * sizeof *datum->values);
+ ovsdb_atom_clone(&datum->values[idx], value, type->value.type);
+ }
}
}
@@ -1937,29 +2022,31 @@ ovsdb_datum_diff(struct ovsdb_datum *diff,
type->key.type);
if (c < 0) {
ovsdb_datum_add_unsafe(diff, &old->keys[oi], &old->values[oi],
- type);
+ type, NULL);
oi++;
} else if (c > 0) {
ovsdb_datum_add_unsafe(diff, &new->keys[ni], &new->values[ni],
- type);
+ type, NULL);
ni++;
} else {
if (type->value.type != OVSDB_TYPE_VOID &&
ovsdb_atom_compare_3way(&old->values[oi], &new->values[ni],
type->value.type)) {
ovsdb_datum_add_unsafe(diff, &new->keys[ni], &new->values[ni],
- type);
+ type, NULL);
}
oi++; ni++;
}
}
for (; oi < old->n; oi++) {
- ovsdb_datum_add_unsafe(diff, &old->keys[oi], &old->values[oi], type);
+ ovsdb_datum_add_unsafe(diff, &old->keys[oi], &old->values[oi],
+ type, NULL);
}
for (; ni < new->n; ni++) {
- ovsdb_datum_add_unsafe(diff, &new->keys[ni], &new->values[ni], type);
+ ovsdb_datum_add_unsafe(diff, &new->keys[ni], &new->values[ni],
+ type, NULL);
}
}
@@ -2051,3 +2138,16 @@ ovsdb_token_is_delim(unsigned char c)
{
return strchr(":=, []{}!<>", c) != NULL;
}
+
+struct ovsdb_error *
+ovsdb_atom_range_check_size(int64_t range_start, int64_t range_end)
+{
+ if ((uint64_t) range_end - (uint64_t) range_start
+ >= MAX_OVSDB_ATOM_RANGE_SIZE) {
+ return ovsdb_error("constraint violation",
+ "Range \"%"PRId64"-%"PRId64"\" is too big. "
+ "Maximum allowed size is %d.",
+ range_start, range_end, MAX_OVSDB_ATOM_RANGE_SIZE);
+ }
+ return NULL;
+}
diff --git a/lib/ovsdb-data.h b/lib/ovsdb-data.h
index 9fce380cf..1bf90d59c 100644
--- a/lib/ovsdb-data.h
+++ b/lib/ovsdb-data.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009, 2010, 2011, 2012, 2015, 2016 Nicira, Inc.
+/* Copyright (c) 2009, 2010, 2011, 2012, 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.
@@ -21,6 +21,8 @@
#include "ovsdb-types.h"
#include "openvswitch/shash.h"
+#define MAX_OVSDB_ATOM_RANGE_SIZE 4096
+
struct ds;
struct ovsdb_symbol_table;
struct smap;
@@ -89,7 +91,7 @@ struct ovsdb_error *ovsdb_atom_from_json(union ovsdb_atom *,
struct json *ovsdb_atom_to_json(const union ovsdb_atom *,
enum ovsdb_atomic_type);
-char *ovsdb_atom_from_string(union ovsdb_atom *,
+char *ovsdb_atom_from_string(union ovsdb_atom *, union ovsdb_atom **,
const struct ovsdb_base_type *, const char *,
struct ovsdb_symbol_table *)
OVS_WARN_UNUSED_RESULT;
@@ -235,7 +237,8 @@ void ovsdb_datum_remove_unsafe(struct ovsdb_datum *, size_t idx,
void ovsdb_datum_add_unsafe(struct ovsdb_datum *,
const union ovsdb_atom *key,
const union ovsdb_atom *value,
- const struct ovsdb_type *);
+ const struct ovsdb_type *,
+ const union ovsdb_atom *range_end_atom);
/* Type checking. */
static inline bool
@@ -276,4 +279,7 @@ struct ovsdb_symbol *ovsdb_symbol_table_insert(struct ovsdb_symbol_table *,
char *ovsdb_token_parse(const char **, char **outp) OVS_WARN_UNUSED_RESULT;
bool ovsdb_token_is_delim(unsigned char);
+struct ovsdb_error *ovsdb_atom_range_check_size(int64_t range_start,
+ int64_t range_end);
+
#endif /* ovsdb-data.h */
diff --git a/lib/util.c b/lib/util.c
index 4208aa81d..1c06ce0d4 100644
--- a/lib/util.c
+++ b/lib/util.c
@@ -640,11 +640,22 @@ str_to_long(const char *s, int base, long *li)
bool
str_to_llong(const char *s, int base, long long *x)
{
- int save_errno = errno;
char *tail;
+ bool ok = str_to_llong_with_tail(s, &tail, base, x);
+ if (*tail != '\0') {
+ *x = 0;
+ return false;
+ }
+ return ok;
+}
+
+bool
+str_to_llong_with_tail(const char *s, char **tail, int base, long long *x)
+{
+ int save_errno = errno;
errno = 0;
- *x = strtoll(s, &tail, base);
- if (errno == EINVAL || errno == ERANGE || tail == s || *tail != '\0') {
+ *x = strtoll(s, tail, base);
+ if (errno == EINVAL || errno == ERANGE || *tail == s) {
errno = save_errno;
*x = 0;
return false;
@@ -668,6 +679,21 @@ str_to_uint(const char *s, int base, unsigned int *u)
}
}
+bool
+str_to_llong_range(const char *s, int base, long long *begin,
+ long long *end)
+{
+ char *tail;
+ if (str_to_llong_with_tail(s, &tail, base, begin)
+ && *tail == '-'
+ && str_to_llong(tail + 1, base, end)) {
+ return true;
+ }
+ *begin = 0;
+ *end = 0;
+ return false;
+}
+
/* Converts floating-point string 's' into a double. If successful, stores
* the double in '*d' and returns true; on failure, stores 0 in '*d' and
* returns false.
diff --git a/lib/util.h b/lib/util.h
index 5ad25cbb1..aa38122ee 100644
--- a/lib/util.h
+++ b/lib/util.h
@@ -153,7 +153,9 @@ void ovs_hex_dump(FILE *, const void *, size_t, uintptr_t offset, bool ascii);
bool str_to_int(const char *, int base, int *);
bool str_to_long(const char *, int base, long *);
bool str_to_llong(const char *, int base, long long *);
+bool str_to_llong_with_tail(const char *, char **, int base, long long *);
bool str_to_uint(const char *, int base, unsigned int *);
+bool str_to_llong_range(const char *, int base, long long *, long long *);
bool ovs_scan(const char *s, const char *format, ...) OVS_SCANF_FORMAT(2, 3);
bool ovs_scan_len(const char *s, int *n, const char *format, ...);
diff --git a/tests/ovs-vsctl.at b/tests/ovs-vsctl.at
index 87ee96715..94b431f92 100644
--- a/tests/ovs-vsctl.at
+++ b/tests/ovs-vsctl.at
@@ -860,7 +860,7 @@ AT_CHECK([RUN_OVS_VSCTL([remove bridge br0 name br1])],
[1], [], [ovs-vsctl: cannot modify read-only column name in table Bridge
], [OVS_VSCTL_CLEANUP])
AT_CHECK([RUN_OVS_VSCTL([remove bridge br1 flood-vlans true])],
- [1], [], [ovs-vsctl: "true" is not a valid integer
+ [1], [], [ovs-vsctl: "true" is not a valid integer or range
], [OVS_VSCTL_CLEANUP])
AT_CHECK([RUN_OVS_VSCTL([clear bridge br1 name])],
[1], [], [ovs-vsctl: cannot modify read-only column name in table Bridge
diff --git a/tests/ovsdb-data.at b/tests/ovsdb-data.at
index a8c092f39..8c40bcfbf 100644
--- a/tests/ovsdb-data.at
+++ b/tests/ovsdb-data.at
@@ -92,12 +92,26 @@ OVSDB_CHECK_POSITIVE([integer atom from string],
'-1' \
'+1000' \
'9223372036854775807' \
- '-9223372036854775808' ]],
+ '-9223372036854775808' \
+ '0-1000' \
+ '-1000-+1000' \
+ '-1000--10' \
+ '+10-+1000' \
+ '1-4096' \
+ '-4096--1' \
+ '-2000-2095']],
[0
-1
1000
9223372036854775807
--9223372036854775808])
+-9223372036854775808
+0-1000
+-1000-1000
+-1000--10
+10-1000
+1-4096
+-4096--1
+-2000-2095])
OVSDB_CHECK_POSITIVE_CPY([real atom from JSON],
[[parse-atoms '["real"]' \
@@ -258,6 +272,30 @@ OVSDB_CHECK_NEGATIVE([real not acceptable integer string atom],
[[parse-atom-strings '["integer"]' '0.5' ]],
["0.5" is not a valid integer])
+OVSDB_CHECK_NEGATIVE([inverted range is not acceptable integer string atom positive and negative],
+ [[parse-atom-strings -- '["integer"]' '10--10' ]],
+ ["10--10" is not a valid range. Range end cannot be before start.])
+
+OVSDB_CHECK_NEGATIVE([inverted range is not acceptable integer string atom negative],
+ [[parse-atom-strings -- '["integer"]' '-10--100' ]],
+ ["-10--100" is not a valid range. Range end cannot be before start.])
+
+OVSDB_CHECK_NEGATIVE([inverted range is not acceptable integer string atom positive],
+ [[parse-atom-strings -- '["integer"]' '100-10' ]],
+ ["100-10" is not a valid range. Range end cannot be before start.])
+
+OVSDB_CHECK_NEGATIVE([too big range is not acceptable integer string atom positive and negative],
+ [[parse-atom-strings -- '["integer"]' '-2000-2096' ]],
+ [Range "-2000-2096" is too big.])
+
+OVSDB_CHECK_NEGATIVE([too big range is not acceptable integer string atom negative],
+ [[parse-atom-strings -- '["integer"]' '-4097--1' ]],
+ [Range "-4097--1" is too big.])
+
+OVSDB_CHECK_NEGATIVE([too big range is not acceptable integer string atom positive],
+ [[parse-atom-strings -- '["integer"]' '1-4097' ]],
+ [Range "1-4097" is too big.])
+
OVSDB_CHECK_POSITIVE_CPY([string "true" not acceptable boolean JSON atom],
[[parse-atoms '["boolean"]' '["true"]' ]],
[syntax ""true"": syntax error: expected boolean])
@@ -323,6 +361,27 @@ constraint violation: 9 is not one of the allowed values ([1, 6, 8, 10])
10
constraint violation: 11 is not one of the allowed values ([1, 6, 8, 10])]])
+OVSDB_CHECK_POSITIVE([integer atom enum from string],
+ [[parse-atom-strings '[{"type": "integer", "enum": ["set", [1, 6, 8, 10, 20, 21, 22, 23, 24, 25]]}]' \
+ '1' \
+ '6' \
+ '8' \
+ '10' \
+ '20-25']],
+ [[1
+6
+8
+10
+20-25]])
+
+OVSDB_CHECK_NEGATIVE([integer not in enum set from string],
+ [[parse-atom-strings '[{"type": "integer", "enum": ["set", [1, 6, 8, 10]]}]' '0' ]],
+ [[constraint violation: 0 is not one of the allowed values ([1, 6, 8, 10])]])
+
+OVSDB_CHECK_NEGATIVE([integer range not in enum set from string],
+ [[parse-atom-strings '[{"type": "integer", "enum": ["set", [1, 6, 8, 10]]}]' '8-10' ]],
+ [[constraint violation: 9 is not one of the allowed values ([1, 6, 8, 10])]])
+
OVSDB_CHECK_POSITIVE_CPY([real atom enum],
[[parse-atoms '[{"type": "real", "enum": ["set", [-1.5, 1.5]]}]' \
'[-2]' \
@@ -590,12 +649,16 @@ OVSDB_CHECK_POSITIVE([string set of 0 or more integers],
'0, 1, 2' \
'[0, 1,2, 3, 4, 5]' \
'0, 1,2, 3,4, 5, 6, 7, 8' \
- '[0, 1, 2, 3, 4,5, 6,7, 8, 9, 10]']],
+ '[0, 1, 2, 3, 4,5, 6,7, 8, 9, 10]' \
+ '0-8' \
+ '[0-10']]],
[[[0]
[0, 1]
[0, 1, 2]
[0, 1, 2, 3, 4, 5]
[0, 1, 2, 3, 4, 5, 6, 7, 8]
+[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
+[0, 1, 2, 3, 4, 5, 6, 7, 8]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]]])
OVSDB_CHECK_POSITIVE_CPY([JSON set of 1 to 3 uuids],
diff --git a/tests/test-ovsdb.c b/tests/test-ovsdb.c
index 968c1de22..e297f9f9d 100644
--- a/tests/test-ovsdb.c
+++ b/tests/test-ovsdb.c
@@ -554,17 +554,29 @@ do_parse_atom_strings(struct ovs_cmdl_context *ctx)
json_destroy(json);
for (i = 2; i < ctx->argc; i++) {
- union ovsdb_atom atom;
+ union ovsdb_atom atom, *range_end_atom = NULL;
struct ds out;
- die_if_error(ovsdb_atom_from_string(&atom, &base, ctx->argv[i], NULL));
+ die_if_error(ovsdb_atom_from_string(&atom, &range_end_atom, &base,
+ ctx->argv[i], NULL));
ds_init(&out);
ovsdb_atom_to_string(&atom, base.type, &out);
+ if (range_end_atom) {
+ struct ds range_end_ds;
+ ds_init(&range_end_ds);
+ ovsdb_atom_to_string(range_end_atom, base.type, &range_end_ds);
+ ds_put_char(&out, '-');
+ ds_put_cstr(&out, ds_cstr(&range_end_ds));;
+ ds_destroy(&range_end_ds);
+ }
puts(ds_cstr(&out));
ds_destroy(&out);
ovsdb_atom_destroy(&atom, base.type);
+ if (range_end_atom) {
+ ovsdb_atom_destroy(range_end_atom, base.type);
+ }
}
ovsdb_base_type_destroy(&base);
}