diff mbox

[ovs-dev,2/3] ovsdb-idl: Properly handle conditional monitor update error

Message ID 1482227237-61638-2-git-send-email-azhou@ovn.org
State Changes Requested
Headers show

Commit Message

Andy Zhou Dec. 20, 2016, 9:47 a.m. UTC
From: andy zhou <azhou@ovn.org>

When generating conditional monitoring update request, current code
failed to update idl's 'request-id'.  This bug causes the reply
message of the update request, regardless an ACK or a NACK, be
logged as an unexpected message at the debug level and ignored by
the core idl logic.

In addition, the idl should not generate another conditional
monitoring update request when there is an outstanding request.
So that the requests and their reply are properly serialized.

When the conditional monitoring is nacked by the server, drop idl
into a client visible error state.

Signed-off-by: Andy Zhou <azhou@ovn.org>
---
 lib/ovsdb-idl.c | 32 ++++++++++++++++++++++++--------
 1 file changed, 24 insertions(+), 8 deletions(-)

Comments

Ben Pfaff Dec. 22, 2016, 5:21 p.m. UTC | #1
On Tue, Dec 20, 2016 at 01:47:16AM -0800, Andy Zhou wrote:
> From: andy zhou <azhou@ovn.org>
> 
> When generating conditional monitoring update request, current code
> failed to update idl's 'request-id'.  This bug causes the reply
> message of the update request, regardless an ACK or a NACK, be
> logged as an unexpected message at the debug level and ignored by
> the core idl logic.
> 
> In addition, the idl should not generate another conditional
> monitoring update request when there is an outstanding request.
> So that the requests and their reply are properly serialized.
> 
> When the conditional monitoring is nacked by the server, drop idl
> into a client visible error state.
> 
> Signed-off-by: Andy Zhou <azhou@ovn.org>

When the condition is changed when an update request is already in
flight, and the update request completes, will the code properly send
a new condition change at that point?
Andy Zhou Dec. 22, 2016, 8:12 p.m. UTC | #2
On Thu, Dec 22, 2016 at 9:21 AM, Ben Pfaff <blp@ovn.org> wrote:

> On Tue, Dec 20, 2016 at 01:47:16AM -0800, Andy Zhou wrote:
> > From: andy zhou <azhou@ovn.org>
> >
> > When generating conditional monitoring update request, current code
> > failed to update idl's 'request-id'.  This bug causes the reply
> > message of the update request, regardless an ACK or a NACK, be
> > logged as an unexpected message at the debug level and ignored by
> > the core idl logic.
> >
> > In addition, the idl should not generate another conditional
> > monitoring update request when there is an outstanding request.
> > So that the requests and their reply are properly serialized.
> >
> > When the conditional monitoring is nacked by the server, drop idl
> > into a client visible error state.
> >
> > Signed-off-by: Andy Zhou <azhou@ovn.org>
>
> When the condition is changed when an update request is already in
> flight, and the update request completes, will the code properly send
> a new condition change at that point?
>

When an ack is received, the request_id will be freed and set to NULL, thus
unblocking ovsdb_idl_send_cond_changge() to send out the next condition
change.

Am I still missing something?
Andy Zhou Jan. 6, 2017, 10:40 p.m. UTC | #3
On Wed, Jan 4, 2017 at 3:55 PM, Ben Pfaff <blp@ovn.org> wrote:

> On Thu, Dec 22, 2016 at 12:12:05PM -0800, Andy Zhou wrote:
> > On Thu, Dec 22, 2016 at 9:21 AM, Ben Pfaff <blp@ovn.org> wrote:
> >
> > > On Tue, Dec 20, 2016 at 01:47:16AM -0800, Andy Zhou wrote:
> > > > From: andy zhou <azhou@ovn.org>
> > > >
> > > > When generating conditional monitoring update request, current code
> > > > failed to update idl's 'request-id'.  This bug causes the reply
> > > > message of the update request, regardless an ACK or a NACK, be
> > > > logged as an unexpected message at the debug level and ignored by
> > > > the core idl logic.
> > > >
> > > > In addition, the idl should not generate another conditional
> > > > monitoring update request when there is an outstanding request.
> > > > So that the requests and their reply are properly serialized.
> > > >
> > > > When the conditional monitoring is nacked by the server, drop idl
> > > > into a client visible error state.
> > > >
> > > > Signed-off-by: Andy Zhou <azhou@ovn.org>
> > >
> > > When the condition is changed when an update request is already in
> > > flight, and the update request completes, will the code properly send
> > > a new condition change at that point?
> > >
> >
> > When an ack is received, the request_id will be freed and set to NULL,
> thus
> > unblocking ovsdb_idl_send_cond_changge() to send out the next condition
> > change.
> >
> > Am I still missing something?
>
> I asked the question because I hadn't looked, and it seemed like an easy
> mistake to make.  I agree that it seems OK.  However, I think that the
> loop in ovsdb_idl_run() can reset request_id without calling
> ovsdb_idl_send_cond_change() afterward.  That'll happen on the next trip
> through the main loop but at least in theory that could happen much
> later, so perhaps we should call it right away, e.g.:
>
> diff --git a/lib/ovsdb-idl.c b/lib/ovsdb-idl.c
> index 341951d..82c8584 100644
> --- a/lib/ovsdb-idl.c
> +++ b/lib/ovsdb-idl.c
> @@ -458,6 +458,7 @@ ovsdb_idl_run(struct ovsdb_idl *idl)
>
>              case IDL_S_MONITORING_COND:
>                  /* Conditional monitor clauses were updated. */
> +                ovsdb_idl_send_cond_change(idl);
>                  break;
>
>              case IDL_S_MONITORING:
>
> Probably the VLOG calls should be rate-limited.
>

Thanks for the suggestion. I folded this change into v2.
diff mbox

Patch

diff --git a/lib/ovsdb-idl.c b/lib/ovsdb-idl.c
index 218b6b3..341951d 100644
--- a/lib/ovsdb-idl.c
+++ b/lib/ovsdb-idl.c
@@ -456,8 +456,11 @@  ovsdb_idl_run(struct ovsdb_idl *idl)
                 idl->schema = NULL;
                 break;
 
-            case IDL_S_MONITORING:
             case IDL_S_MONITORING_COND:
+                /* Conditional monitor clauses were updated. */
+                break;
+
+            case IDL_S_MONITORING:
             case IDL_S_NO_SCHEMA:
             default:
                 OVS_NOT_REACHED();
@@ -496,14 +499,23 @@  ovsdb_idl_run(struct ovsdb_idl *idl)
                 idl->state = IDL_S_MONITOR_REQUESTED;
             }
         } else if (msg->type == JSONRPC_ERROR
+                   && idl->state == IDL_S_MONITORING_COND
+                   && idl->request_id
+                   && json_equal(idl->request_id, msg->id)) {
+            json_destroy(idl->request_id);
+            idl->request_id = NULL;
+            VLOG_ERR("%s: conditional monitor update failed",
+                     jsonrpc_session_get_name(idl->session));
+            idl->state = IDL_S_NO_SCHEMA;
+        } else if (msg->type == JSONRPC_ERROR
                    && idl->state == IDL_S_SCHEMA_REQUESTED
                    && idl->request_id
                    && json_equal(idl->request_id, msg->id)) {
-                json_destroy(idl->request_id);
-                idl->request_id = NULL;
-                VLOG_ERR("%s: requested schema not found",
-                         jsonrpc_session_get_name(idl->session));
-                idl->state = IDL_S_NO_SCHEMA;
+            json_destroy(idl->request_id);
+            idl->request_id = NULL;
+            VLOG_ERR("%s: requested schema not found",
+                     jsonrpc_session_get_name(idl->session));
+            idl->state = IDL_S_NO_SCHEMA;
         } else if ((msg->type == JSONRPC_ERROR
                     || msg->type == JSONRPC_REPLY)
                    && ovsdb_idl_txn_process_reply(idl, msg)) {
@@ -1091,8 +1103,11 @@  ovsdb_idl_send_cond_change(struct ovsdb_idl *idl)
     struct json *params, *json_uuid;
     struct jsonrpc_msg *request;
 
+    /* When 'idl-request_id' is not NULL, there is an outstanding
+     * conditional monitoring update request that we have not heard
+     * from the server yet. Don't generate another request in this case.  */
     if (!idl->cond_changed || !jsonrpc_session_is_connected(idl->session) ||
-        idl->state != IDL_S_MONITORING_COND) {
+        idl->state != IDL_S_MONITORING_COND || idl->request_id) {
         return;
     }
 
@@ -1128,7 +1143,8 @@  ovsdb_idl_send_cond_change(struct ovsdb_idl *idl)
         params = json_array_create_3(json_uuid, json_string_create(uuid),
                                      monitor_cond_change_requests);
 
-        request = jsonrpc_create_request("monitor_cond_change", params, NULL);
+        request = jsonrpc_create_request("monitor_cond_change", params,
+                                         &idl->request_id);
         jsonrpc_session_send(idl->session, request);
     }
     idl->cond_changed = false;