Applications request specific monitor conditions via the
ovsdb_cs_set_condition() API.  This returns the condition sequence
number at which the client can assume that the server acknowledged
and applied the new monitor condition.

A corner case is when the client's first request is to set the condition
to a value that's equivalent to the default one ("<true>").  In such
cases, because it's requested explicitly by the client, we now
explicitly send the monitor_cond_change request to the server.  This
avoids cases in which the expected condition sequence number and the
acked condition sequence number get out of sync.

Reported-by: Numan Siddique <[email protected]>
Signed-off-by: Dumitru Ceara <[email protected]>
---
 lib/ovsdb-cs.c      |  1 +
 tests/ovsdb-idl.at  | 27 +++++++++++++++++++++++++++
 tests/test-ovsdb.c  | 28 ++++++++++++++++++++++++----
 tests/test-ovsdb.py | 20 +++++++++++++++++---
 4 files changed, 69 insertions(+), 7 deletions(-)

diff --git a/lib/ovsdb-cs.c b/lib/ovsdb-cs.c
index a6fbd290c87d..16c8f6a2cf55 100644
--- a/lib/ovsdb-cs.c
+++ b/lib/ovsdb-cs.c
@@ -894,6 +894,7 @@ ovsdb_cs_db_get_table(struct ovsdb_cs_db *db, const char 
*table)
     t->name = xstrdup(table);
     t->new_cond = json_array_create_1(json_boolean_create(true));
     hmap_insert(&db->tables, &t->hmap_node, hash);
+    db->cond_changed = true;
     return t;
 }
 
diff --git a/tests/ovsdb-idl.at b/tests/ovsdb-idl.at
index c2970984bae3..57ed0ac9d12c 100644
--- a/tests/ovsdb-idl.at
+++ b/tests/ovsdb-idl.at
@@ -599,6 +599,33 @@ OVSDB_CHECK_IDL([simple idl, conditional, true condition],
 004: done
 ]])
 
+dnl This test ensures that the first explicitly set monitor condition
+dnl is sent to the server.
+OVSDB_CHECK_IDL([simple idl, conditional, wait for condition],
+  [],
+  [['["idltest",
+       {"op": "insert",
+       "table": "simple",
+       "row": {"i": 1,
+               "r": 2.0,
+               "b": true}}]' \
+     'condition simple [true]' \
+     '^["idltest",
+       {"op": "insert",
+       "table": "simple",
+       "row": {"i": 2,
+               "r": 4.0,
+               "b": true}}]']],
+  [[000: empty
+001: {"error":null,"result":[{"uuid":["uuid","<0>"]}]}
+002: table simple: i=1 r=2 b=true s= u=<1> ia=[] ra=[] ba=[] sa=[] ua=[] 
uuid=<0>
+003: change conditions
+004: {"error":null,"result":[{"uuid":["uuid","<2>"]}]}
+005: table simple: i=1 r=2 b=true s= u=<1> ia=[] ra=[] ba=[] sa=[] ua=[] 
uuid=<0>
+005: table simple: i=2 r=4 b=true s= u=<1> ia=[] ra=[] ba=[] sa=[] ua=[] 
uuid=<2>
+006: done
+]])
+
 OVSDB_CHECK_IDL([simple idl, conditional, multiple clauses in condition],
   [['["idltest",
        {"op": "insert",
diff --git a/tests/test-ovsdb.c b/tests/test-ovsdb.c
index 84fe232765aa..23cfd79a433e 100644
--- a/tests/test-ovsdb.c
+++ b/tests/test-ovsdb.c
@@ -2627,11 +2627,12 @@ parse_link2_json_clause(struct ovsdb_idl_condition 
*cond,
     }
 }
 
-static void
+static unsigned int
 update_conditions(struct ovsdb_idl *idl, char *commands)
 {
-    char *cmd, *save_ptr1 = NULL;
     const struct ovsdb_idl_table_class *tc;
+    unsigned int next_cond_seqno = 0;
+    char *cmd, *save_ptr1 = NULL;
 
     for (cmd = strtok_r(commands, ";", &save_ptr1); cmd;
          cmd = strtok_r(NULL, ";", &save_ptr1)) {
@@ -2688,9 +2689,11 @@ update_conditions(struct ovsdb_idl *idl, char *commands)
         if (next_seqno != new_next_seqno) {
             ovs_fatal(0, "condition expected seqno changed");
         }
+        next_cond_seqno = MAX(next_cond_seqno, next_seqno);
         ovsdb_idl_condition_destroy(&cond);
         json_destroy(json);
     }
+    return next_cond_seqno;
 }
 
 static void
@@ -2699,6 +2702,7 @@ do_idl(struct ovs_cmdl_context *ctx)
     struct test_ovsdb_pvt_context *pvt = ctx->pvt;
     struct jsonrpc *rpc;
     struct ovsdb_idl *idl;
+    unsigned int next_cond_seqno = 0;
     unsigned int seqno = 0;
     struct ovsdb_symbol_table *symtab;
     size_t n_uuids = 0;
@@ -2735,7 +2739,8 @@ do_idl(struct ovs_cmdl_context *ctx)
     const char remote_s[] = "set-remote ";
     const char cond_s[] = "condition ";
     if (ctx->argc > 2 && strstr(ctx->argv[2], cond_s)) {
-        update_conditions(idl, ctx->argv[2] + strlen(cond_s));
+        next_cond_seqno =
+            update_conditions(idl, ctx->argv[2] + strlen(cond_s));
         print_and_log("%03d: change conditions", step++);
         i = 3;
     } else {
@@ -2755,6 +2760,21 @@ do_idl(struct ovs_cmdl_context *ctx)
         if (*arg == '+') {
             /* The previous transaction didn't change anything. */
             arg++;
+        } else if (*arg == '^') {
+            /* Wait for condition change to be acked by the server. */
+            arg++;
+            for (;;) {
+                ovsdb_idl_run(idl);
+                ovsdb_idl_check_consistency(idl);
+                if (ovsdb_idl_get_condition_seqno(idl) == next_cond_seqno) {
+                    break;
+                }
+                jsonrpc_run(rpc);
+
+                ovsdb_idl_wait(idl);
+                jsonrpc_wait(rpc);
+                poll_block();
+            }
         } else {
             /* Wait for update. */
             for (;;) {
@@ -2789,7 +2809,7 @@ do_idl(struct ovs_cmdl_context *ctx)
                           arg + strlen(remote_s),
                           ovsdb_idl_is_connected(idl) ? "true" : "false");
         }  else if (!strncmp(arg, cond_s, strlen(cond_s))) {
-            update_conditions(idl, arg + strlen(cond_s));
+            next_cond_seqno = update_conditions(idl, arg + strlen(cond_s));
             print_and_log("%03d: change conditions", step++);
         } else if (arg[0] != '[') {
             if (!idl_set(idl, arg, step++)) {
diff --git a/tests/test-ovsdb.py b/tests/test-ovsdb.py
index cca1818ea3aa..86184e6d4e4d 100644
--- a/tests/test-ovsdb.py
+++ b/tests/test-ovsdb.py
@@ -627,6 +627,7 @@ def idl_set(idl, commands, step):
 
 
 def update_condition(idl, commands):
+    expected_seqno = 0
     commands = commands[len("condition "):].split(";")
     for command in commands:
         command = command.split(" ")
@@ -637,7 +638,8 @@ def update_condition(idl, commands):
         table = command[0]
         cond = ovs.json.from_string(command[1])
 
-        idl.cond_change(table, cond)
+        expected_seqno = max(expected_seqno, idl.cond_change(table, cond))
+    return expected_seqno
 
 
 def do_idl(schema_file, remote, *commands):
@@ -694,6 +696,7 @@ def do_idl(schema_file, remote, *commands):
     else:
         rpc = None
 
+    next_cond_seqno = 0
     symtab = {}
     seqno = 0
     step = 0
@@ -717,7 +720,7 @@ def do_idl(schema_file, remote, *commands):
 
     commands = list(commands)
     if len(commands) >= 1 and "condition" in commands[0]:
-        update_condition(idl, commands.pop(0))
+        next_cond_seqno = update_condition(idl, commands.pop(0))
         sys.stdout.write("%03d: change conditions\n" % step)
         sys.stdout.flush()
         step += 1
@@ -732,6 +735,17 @@ def do_idl(schema_file, remote, *commands):
         if command.startswith("+"):
             # The previous transaction didn't change anything.
             command = command[1:]
+        elif command.startswith("^"):
+            # Wait for condition change to be acked by the server.
+            command = command[1:]
+            while idl.cond_seqno != next_cond_seqno and \
+                    not idl.run():
+                rpc.run()
+
+                poller = ovs.poller.Poller()
+                idl.wait(poller)
+                rpc.wait(poller)
+                poller.block()
         else:
             # Wait for update.
             while idl.change_seqno == seqno and not idl.run():
@@ -753,7 +767,7 @@ def do_idl(schema_file, remote, *commands):
             step += 1
             idl.force_reconnect()
         elif "condition" in command:
-            update_condition(idl, command)
+            next_cond_seqno = update_condition(idl, command)
             sys.stdout.write("%03d: change conditions\n" % step)
             sys.stdout.flush()
             step += 1
-- 
2.31.1

_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to