ovsdb: Allow comparison on optional scalar types
authorTerry Wilson <twilson@redhat.com>
Tue, 19 Aug 2014 23:28:55 +0000 (17:28 -0600)
committerBen Pfaff <blp@nicira.com>
Wed, 20 Aug 2014 17:25:35 +0000 (10:25 -0700)
This allows things like initiating a wait request on an interface
ofport being set.

When the optional field is empty and operation is != or excludes
then the result is true; otherwise it is false. If the field is
set then the field is compared normally for its type.

Signed-off-by: Terry Wilson <twilson@redhat.com>
[blp@nicira.com updated ovsdb-server(1) and NEWS.]
Signed-off-by: Ben Pfaff <blp@nicira.com>
AUTHORS
NEWS
lib/ovsdb-types.h
ovsdb/condition.c
ovsdb/ovsdb-server.1.in
tests/ovsdb-condition.at

diff --git a/AUTHORS b/AUTHORS
index 2a63450..cfbb03d 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -126,6 +126,7 @@ Simon Horman            horms@verge.net.au
 Stephane A. Sezer       sas@cd80.net
 SUGYO Kazushi           sugyo.org@gmail.com
 Tadaaki Nagao           nagao@stratosphere.co.jp
+Terry Wilson            twilson@redhat.com
 Tetsuo NAKAGAWA         nakagawa@mxc.nes.nec.co.jp
 Thomas Goirand          zigo@debian.org
 Thomas Graf             tgraf@noironetworks.com
diff --git a/NEWS b/NEWS
index 1ea7bda..fb39811 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -17,6 +17,8 @@ Post-v2.3.0
      * OpenFlow 1.5 (draft) Copy-Field action is now supported.
      * OpenFlow 1.3+ table features requests are now supported (read-only).
      * Nicira extension "move" actions may now be included in action sets.
+   - ovsdb-server: New OVSDB protocol extension allows inequality tests on
+     "optional scalar" columns.  See ovsdb-server(1) for details.
 
 
 v2.3.0 - 14 Aug 2014
index efd83a7..5b6b0f0 100644 (file)
@@ -152,6 +152,8 @@ bool ovsdb_type_is_valid(const struct ovsdb_type *);
 
 static inline bool ovsdb_type_is_scalar(const struct ovsdb_type *);
 static inline bool ovsdb_type_is_optional(const struct ovsdb_type *);
+static inline bool ovsdb_type_is_optional_scalar(
+    const struct ovsdb_type *);
 static inline bool ovsdb_type_is_composite(const struct ovsdb_type *);
 static inline bool ovsdb_type_is_set(const struct ovsdb_type *);
 static inline bool ovsdb_type_is_map(const struct ovsdb_type *);
@@ -202,6 +204,13 @@ static inline bool ovsdb_type_is_optional(const struct ovsdb_type *type)
     return type->n_min == 0;
 }
 
+static inline bool ovsdb_type_is_optional_scalar(
+    const struct ovsdb_type *type)
+{
+    return (type->value.type == OVSDB_TYPE_VOID
+            && type->n_min == 0 && type->n_max == 1);
+}
+
 static inline bool ovsdb_type_is_composite(const struct ovsdb_type *type)
 {
     return type->n_max > 1;
index 8e67c88..570f14d 100644 (file)
@@ -93,10 +93,10 @@ ovsdb_clause_from_json(const struct ovsdb_table_schema *ts,
     case OVSDB_F_LE:
     case OVSDB_F_GT:
     case OVSDB_F_GE:
-        /* XXX should we also allow these operators for types with n_min == 0,
-         * n_max == 1?  (They would always be "false" if the value was
-         * missing.) */
-        if (!ovsdb_type_is_scalar(&type)
+        /* Allow these operators for types with n_min == 0, n_max == 1.
+         * (They will always be "false" if the value is missing.) */
+        if (!(ovsdb_type_is_scalar(&type)
+            || ovsdb_type_is_optional_scalar(&type))
             || (type.key.type != OVSDB_TYPE_INTEGER
                 && type.key.type != OVSDB_TYPE_REAL)) {
             char *s = ovsdb_type_to_english(&type);
@@ -225,7 +225,21 @@ ovsdb_clause_evaluate(const struct ovsdb_row *row,
     const struct ovsdb_datum *arg = &c->arg;
     const struct ovsdb_type *type = &c->column->type;
 
-    if (ovsdb_type_is_scalar(type)) {
+    if (ovsdb_type_is_optional_scalar(type) && field->n == 0) {
+        switch (c->function) {
+            case OVSDB_F_LT:
+            case OVSDB_F_LE:
+            case OVSDB_F_EQ:
+            case OVSDB_F_GE:
+            case OVSDB_F_GT:
+            case OVSDB_F_INCLUDES:
+                return false;
+            case OVSDB_F_NE:
+            case OVSDB_F_EXCLUDES:
+                return true;
+        }
+    } else if (ovsdb_type_is_scalar(type)
+               || ovsdb_type_is_optional_scalar(type)) {
         int cmp = ovsdb_atom_compare_3way(&field->keys[0], &arg->keys[0],
                                           type->key.type);
         switch (c->function) {
index ec408a6..c713937 100644 (file)
@@ -243,6 +243,15 @@ notifications (see below) to the request, it must be unique among all
 active monitors.  \fBovsdb\-server\fR rejects attempt to create two
 monitors with the same identifier.
 .
+.IP "5.1. Notation"
+For <condition>, RFC 7047 only allows the use of \fB!=\fR, \fB==\fR,
+\fBincludes\fR, and \fBexcludes\fR operators with set types.  Open
+vSwitch 2.4 and later extend <condition> to allow the use of \fB<\fR,
+\fB<=\fR, \fB>=\fR, and \fB>\fR operators with columns with type ``set
+of 0 or 1 integer'' and ``set of 0 or 1 real''.  These conditions
+evaluate to false when the column is empty, and otherwise as described
+in RFC 7047 for integer and real types.
+.
 .IP "6. IANA Considerations"
 \fBovsdb\-server\fR currently defaults to its historical port number
 6632.  Future versions will adopt IANA-assigned port 6640 as default.
index d3d7d83..ab54b1c 100644 (file)
@@ -576,3 +576,84 @@ condition 29: T-TTT ---T- -----
 condition 30: TTT-T -T-T- T----
 condition 31: T-T-T ---T- -----
 condition 32: ----- T---- ---T-], [condition])
+
+OVSDB_CHECK_POSITIVE([evaluating conditions on optional integers],
+  [[evaluate-conditions \
+    '{"columns": {"i": {"type": {"key": "integer", "min": 0, "max": 1}}}}' \
+    '[[["i", "<", 1]],
+      [["i", "<=", 1]],
+      [["i", "==", 1]],
+      [["i", "!=", 1]],
+      [["i", ">=", 1]],
+      [["i", ">", 1]],
+      [["i", "includes", 1]],
+      [["i", "excludes", 1]],
+      [["i", ">", 0], ["i", "<", 2]]]' \
+    '[{"i": ["set", []]},
+      {"i": ["set", [0]]},
+      {"i": ["set", [1]]},
+      {"i": ["set", [2]]}]']],
+  [dnl
+condition  0: -T--
+condition  1: -TT-
+condition  2: --T-
+condition  3: TT-T
+condition  4: --TT
+condition  5: ---T
+condition  6: --T-
+condition  7: TT-T
+condition  8: --T-], [condition])
+
+OVSDB_CHECK_POSITIVE([evaluating conditions on optional strings],
+  [[evaluate-conditions \
+    '{"columns": {"s": {"type": {"key": "string", "min": 0, "max": 1}}}}' \
+    '[[["s", "==", ""]],
+      [["s", "!=", ""]],
+      [["s", "includes", ""]],
+      [["s", "excludes", ""]],
+      [["s", "==", "foo"]],
+      [["s", "!=", "foo"]],
+      [["s", "includes", "foo"]],
+      [["s", "excludes", "foo"]],
+      [["s", "!=", "foo"], ["s", "!=", ""]]]' \
+    '[{"s": ["set", [""]]},
+      {"s": ["set", ["foo"]]},
+      {"s": ["set", ["xxx"]]},
+      {"s": ["set", []]}]']],
+  [dnl
+condition  0: T---
+condition  1: -TTT
+condition  2: T---
+condition  3: -TTT
+condition  4: -T--
+condition  5: T-TT
+condition  6: -T--
+condition  7: T-TT
+condition  8: --TT], [condition])
+
+OVSDB_CHECK_POSITIVE([evaluating conditions on optional reals],
+  [[evaluate-conditions \
+    '{"columns": {"r": {"type": {"key": "real", "min": 0, "max": 1}}}}' \
+    '[[["r", "<", 5.0]],
+      [["r", "<=", 5.0]],
+      [["r", "==", 5.0]],
+      [["r", "!=", 5.0]],
+      [["r", ">=", 5.0]],
+      [["r", ">", 5.0]],
+      [["r", "includes", 5.0]],
+      [["r", "excludes", 5.0]],
+      [["r", "!=", 0], ["r", "!=", 5.1]]]' \
+    '[{"r": ["set", [0]]},
+      {"r": ["set", [5.0]]},
+      {"r": ["set", [5.1]]},
+      {"r": ["set", []]}]']],
+  [dnl
+condition  0: T---
+condition  1: TT--
+condition  2: -T--
+condition  3: T-TT
+condition  4: -TT-
+condition  5: --T-
+condition  6: -T--
+condition  7: T-TT
+condition  8: -T-T], [condition])