On Wed, Aug 8, 2012 at 4:14 PM, Ben Pfaff <[email protected]> wrote:
> Until now, the jsonrpc code has only counted receiving a full JSON-RPC
> messages as activity.  This could theoretically time out, then, while a
> very long message is in transit or if a slow link is involved.  This commit
> changes this code to count receiving any part of a message as activity.
>
> This isn't a problem for OpenFlow connections because OpenFlow messages are
> at most 64 kB in size.
>
> This problem hasn't actually been observed in practice.
>
> Bug #12789.
> Signed-off-by: Ben Pfaff <[email protected]>
> ---
>  lib/jsonrpc.c         |   21 ++++++++++++++++++++-
>  lib/jsonrpc.h         |    1 +
>  python/ovs/jsonrpc.py |   14 ++++++++++++++
>  3 files changed, 35 insertions(+), 1 deletions(-)
>
> diff --git a/lib/jsonrpc.c b/lib/jsonrpc.c
> index 9c0aaa9..81a6e53 100644
> --- a/lib/jsonrpc.c
> +++ b/lib/jsonrpc.c
> @@ -178,6 +178,14 @@ jsonrpc_get_backlog(const struct jsonrpc *rpc)
>      return rpc->status ? 0 : rpc->backlog;
>  }
>
> +/* Returns the number of bytes that have been received on 'rpc''s underlying
> + * stream.  (The value wraps around if it exceeds UINT_MAX.) */
> +unsigned int
> +jsonrpc_get_received_bytes(const struct jsonrpc *rpc)
> +{
> +    return rpc->input.head;
> +}
> +
>  /* Returns 'rpc''s name, that is, the name returned by stream_get_name() for
>   * the stream underlying 'rpc' when 'rpc' was created. */
>  const char *
> @@ -987,10 +995,21 @@ struct jsonrpc_msg *
>  jsonrpc_session_recv(struct jsonrpc_session *s)
>  {
>      if (s->rpc) {
> +        unsigned int received_bytes;
>          struct jsonrpc_msg *msg;
> +
> +        received_bytes = jsonrpc_get_received_bytes(s->rpc);
>          jsonrpc_recv(s->rpc, &msg);
> -        if (msg) {
> +        if (received_bytes != jsonrpc_get_received_bytes(s->rpc)) {
> +            /* Data was successfully received.
> +             *
> +             * Previously we only counted receiving a full message as 
> activity,
> +             * but with large messages or a slow connection that policy could
> +             * time out the session mid-message. */
>              reconnect_activity(s->reconnect, time_msec());
> +        }
> +
> +        if (msg) {
>              if (msg->type == JSONRPC_REQUEST && !strcmp(msg->method, 
> "echo")) {
>                  /* Echo request.  Send reply. */
>                  struct jsonrpc_msg *reply;
> diff --git a/lib/jsonrpc.h b/lib/jsonrpc.h
> index cd78170..44ae06f 100644
> --- a/lib/jsonrpc.h
> +++ b/lib/jsonrpc.h
> @@ -50,6 +50,7 @@ void jsonrpc_wait(struct jsonrpc *);
>
>  int jsonrpc_get_status(const struct jsonrpc *);
>  size_t jsonrpc_get_backlog(const struct jsonrpc *);
> +unsigned int jsonrpc_get_received_bytes(const struct jsonrpc *);
>  const char *jsonrpc_get_name(const struct jsonrpc *);
>
>  int jsonrpc_send(struct jsonrpc *, struct jsonrpc_msg *);
> diff --git a/python/ovs/jsonrpc.py b/python/ovs/jsonrpc.py
> index 4496bba..67e798a 100644
> --- a/python/ovs/jsonrpc.py
> +++ b/python/ovs/jsonrpc.py
> @@ -186,6 +186,7 @@ class Connection(object):
>          self.input = ""
>          self.output = ""
>          self.parser = None
> +        self.received_bytes = 0
>
>      def close(self):
>          self.stream.close()
> @@ -221,6 +222,9 @@ class Connection(object):
>          else:
>              return len(self.output)
>
> +    def get_received_bytes(self):
> +        return self.received_bytes
> +
>      def __log_msg(self, title, msg):
>          vlog.dbg("%s: %s %s" % (self.name, title, msg))
>
> @@ -271,6 +275,7 @@ class Connection(object):
>                      return EOF, None
>                  else:
>                      self.input += data
> +                    self.received_bytes += len(data)
>              else:
>                  if self.parser is None:
>                      self.parser = ovs.json.Parser()
> @@ -444,7 +449,16 @@ class Session(object):
>                  self.pstream = None
>
>          if self.rpc:
> +            received_bytes = self.rpc.get_received_bytes()
>              self.rpc.run()
> +            if received_bytes != self.rpc.get_received_bytes():
> +                # Data was successfully received.
> +                #
> +                # Previously we only counted receiving a full message as
> +                # activity, but with large messages or a slow connection that
> +                # policy could time out the session mid-message.
> +                self.reconnect.activity(ovs.timeval.msec())
> +
>              error = self.rpc.get_status()
>              if error != 0:
>                  self.reconnect.disconnected(ovs.timeval.msec(), error)
Looks good!
> --
> 1.7.2.5
>
> _______________________________________________
> dev mailing list
> [email protected]
> http://openvswitch.org/mailman/listinfo/dev
_______________________________________________
dev mailing list
[email protected]
http://openvswitch.org/mailman/listinfo/dev

Reply via email to