[ovs-dev] [PATCH 1/2] vconn-stream: Refactor vconn_stream_recv() for readability.

Ben Pfaff blp at nicira.com
Mon May 10 22:05:20 UTC 2010


On Fri, May 07, 2010 at 06:09:25PM -0700, Jesse Gross wrote:
> On Wed, May 5, 2010 at 10:31 AM, Ben Pfaff <blp at nicira.com> wrote:
> 
> > Backward "goto" statement are rarely a good idea, so this rewrites that
> > code to be a little more readable.
> >
> 
> This looks correct but to be honest I actually find the old version more
> readable.  When I first looked at this, I thought that the loop could
> potentially execute many times.  It also seems to make more sense that the
> success exit condition should be grouped with the packet length
> determination in the second pass, since that is the only time that it can be
> hit.

You're right.  The new version is at least as confusing.

Here's another try.  Do you like it better?  I think that I do.

(The patch was not easily readable as a unified diff (diff -u), so I
reformatted it as a context diff (diff -c), which is easier to read in
this case.)

--8<--------------------------cut here-------------------------->8--

>From 9366a2bacc59f58d78a424e4e7503490a54c0546 Mon Sep 17 00:00:00 2001
From: Ben Pfaff <blp at nicira.com>
Date: Mon, 10 May 2010 15:01:25 -0700
Subject: [PATCH] vconn-stream: Refactor vconn_stream_recv() for readability.

Backward "goto" statement are rarely a good idea, so this rewrites that
code for readability.
---
 lib/vconn-stream.c |   86 +++++++++++++++++++++++++++-------------------------
 1 files changed, 45 insertions(+), 41 deletions(-)

diff --git a/lib/vconn-stream.c b/lib/vconn-stream.c
index 034d1d5..0a721d9 100644
*** a/lib/vconn-stream.c
--- b/lib/vconn-stream.c
***************
*** 116,178 ****
  }
  
  static int
! vconn_stream_recv(struct vconn *vconn, struct ofpbuf **bufferp)
  {
!     struct vconn_stream *s = vconn_stream_cast(vconn);
!     struct ofpbuf *rx;
!     size_t want_bytes;
!     ssize_t retval;
  
!     if (s->rxbuf == NULL) {
!         s->rxbuf = ofpbuf_new(1564);
!     }
!     rx = s->rxbuf;
! 
! again:
!     if (sizeof(struct ofp_header) > rx->size) {
!         want_bytes = sizeof(struct ofp_header) - rx->size;
!     } else {
!         struct ofp_header *oh = rx->data;
!         size_t length = ntohs(oh->length);
!         if (length < sizeof(struct ofp_header)) {
!             VLOG_ERR_RL(&rl, "received too-short ofp_header (%zu bytes)",
!                         length);
!             return EPROTO;
!         }
!         want_bytes = length - rx->size;
!         if (!want_bytes) {
!             *bufferp = rx;
!             s->rxbuf = NULL;
!             return 0;
!         }
!     }
      ofpbuf_prealloc_tailroom(rx, want_bytes);
- 
      retval = stream_recv(s->stream, ofpbuf_tail(rx), want_bytes);
      if (retval > 0) {
          rx->size += retval;
!         if (retval == want_bytes) {
!             if (rx->size > sizeof(struct ofp_header)) {
!                 *bufferp = rx;
!                 s->rxbuf = NULL;
!                 return 0;
!             } else {
!                 goto again;
!             }
!         }
!         return EAGAIN;
      } else if (retval == 0) {
          if (rx->size) {
              VLOG_ERR_RL(&rl, "connection dropped mid-packet");
              return EPROTO;
-         } else {
-             return EOF;
          }
      } else {
          return -retval;
      }
  }
  
  static void
  vconn_stream_clear_txbuf(struct vconn_stream *s)
  {
- - 
--- 116,182 ----
  }
  
  static int
! vconn_stream_recv__(struct vconn_stream *s, int rx_len)
  {
!     struct ofpbuf *rx = s->rxbuf;
!     int want_bytes, retval;
  
!     want_bytes = rx_len - rx->size;
      ofpbuf_prealloc_tailroom(rx, want_bytes);
      retval = stream_recv(s->stream, ofpbuf_tail(rx), want_bytes);
      if (retval > 0) {
          rx->size += retval;
!         return retval == want_bytes ? 0 : EAGAIN;
      } else if (retval == 0) {
          if (rx->size) {
              VLOG_ERR_RL(&rl, "connection dropped mid-packet");
              return EPROTO;
          }
+         return EOF;
      } else {
          return -retval;
      }
  }
  
+ static int
+ vconn_stream_recv(struct vconn *vconn, struct ofpbuf **bufferp)
+ {
+     struct vconn_stream *s = vconn_stream_cast(vconn);
+     const struct ofp_header *oh;
+     int rx_len;
+ 
+     /* Allocate new receive buffer if we don't have one. */
+     if (s->rxbuf == NULL) {
+         s->rxbuf = ofpbuf_new(1564);
+     }
+ 
+     /* Read ofp_header. */
+     if (s->rxbuf->size < sizeof(struct ofp_header)) {
+         int retval = vconn_stream_recv__(s, sizeof(struct ofp_header));
+         if (retval) {
+             return retval;
+         }
+     }
+ 
+     /* Read payload. */
+     oh = s->rxbuf->data;
+     rx_len = ntohs(oh->length);
+     if (rx_len < sizeof(struct ofp_header)) {
+         VLOG_ERR_RL(&rl, "received too-short ofp_header (%zu bytes)",
+                     rx_len);
+         return EPROTO;
+     } else if (s->rxbuf->size < rx_len) {
+         int retval = vconn_stream_recv__(s, rx_len);
+         if (retval) {
+             return retval;
+         }
+     }
+ 
+     *bufferp = s->rxbuf;
+     s->rxbuf = NULL;
+     return 0;
+ }
+ 
  static void
  vconn_stream_clear_txbuf(struct vconn_stream *s)
  {
1.6.6.1





More information about the dev mailing list