Update the netdev_class so that struct ofpbuf * is passed to rx_recv()
to provide both the data and size of the data to read a packet into.

On success, update struct ofpbuf size inside netdev_class rx_recv
implementation and return 0. This moves logic from the caller.
On error a negative error code is returned, this behaviour is unchanged
by this patch.

This patch should not have any behavioural changes.

This patch is in preparation for the netdev-linux variant of rx_recv()
making use of headroom in the struct ofpbuf * parameter to push a VLAN tag
obtained from auxdata.

Signed-off-by: Simon Horman <ho...@verge.net.au>

---
v3
* On success, update struct ofpbuf size inside netdev_class rx_recv
  implementation and return 0. This moves logic from the caller.
* Document that it is recommended that the struct ofpbuf should provide
  extra tailroom for a VLAN header. This will be used by a subsequent patch.
* Update BSD code

v2
* First post
---
 lib/netdev-bsd.c      | 24 ++++++++++++++----------
 lib/netdev-dummy.c    |  9 +++++----
 lib/netdev-linux.c    | 16 ++++++++++------
 lib/netdev-provider.h | 18 ++++++++++++------
 lib/netdev.c          |  4 +---
 5 files changed, 42 insertions(+), 29 deletions(-)

diff --git a/lib/netdev-bsd.c b/lib/netdev-bsd.c
index 442c384..37b2a02 100644
--- a/lib/netdev-bsd.c
+++ b/lib/netdev-bsd.c
@@ -568,20 +568,21 @@ proc_pkt(u_char *args_, const struct pcap_pkthdr *hdr, 
const u_char *packet)
  * from rx->pcap.
  */
 static int
-netdev_rx_bsd_recv_pcap(struct netdev_rx_bsd *rx, void *data, size_t size)
+netdev_rx_bsd_recv_pcap(struct netdev_rx_bsd *rx, struct ofpbuf *buffer)
 {
     struct pcap_arg arg;
     int ret;
 
     /* prepare the pcap argument to store the packet */
-    arg.size = size;
-    arg.data = data;
+    arg.size = ofpbuf_tailroom(buffer);
+    arg.data = buffer->data;
 
     for (;;) {
         ret = pcap_dispatch(rx->pcap_handle, 1, proc_pkt, (u_char *) &arg);
 
         if (ret > 0) {
-            return arg.retval; /* arg.retval < 0 is handled in the caller */
+            buffer->size += retval;
+            return 0;
         }
         if (ret == -1) {
             if (errno == EINTR) {
@@ -599,12 +600,15 @@ netdev_rx_bsd_recv_pcap(struct netdev_rx_bsd *rx, void 
*data, size_t size)
  * 'rx->fd' is initialized with the tap file descriptor.
  */
 static int
-netdev_rx_bsd_recv_tap(struct netdev_rx_bsd *rx, void *data, size_t size)
+netdev_rx_bsd_recv_tap(struct netdev_rx_bsd *rx, struct ofpbuf *buffer)
 {
+    size_t size = ofpbuf_tailroom(buffer);
+
     for (;;) {
-        ssize_t retval = read(rx->fd, data, size);
+        ssize_t retval = read(rx->fd, buffer->data, size);
         if (retval >= 0) {
-            return retval;
+            buffer->size += retval;
+            return 0;
         } else if (errno != EINTR) {
             if (errno != EAGAIN) {
                 VLOG_WARN_RL(&rl, "error receiving Ethernet packet on %s: %s",
@@ -616,13 +620,13 @@ netdev_rx_bsd_recv_tap(struct netdev_rx_bsd *rx, void 
*data, size_t size)
 }
 
 static int
-netdev_bsd_rx_recv(struct netdev_rx *rx_, void *data, size_t size)
+netdev_bsd_rx_recv(struct netdev_rx *rx_, struct ofpbuf *buffer)
 {
     struct netdev_rx_bsd *rx = netdev_rx_bsd_cast(rx_);
 
     return (rx->pcap_handle
-            ? netdev_rx_bsd_recv_pcap(rx, data, size)
-            : netdev_rx_bsd_recv_tap(rx, data, size));
+            ? netdev_rx_bsd_recv_pcap(rx, buffer)
+            : netdev_rx_bsd_recv_tap(rx, buffer));
 }
 
 /*
diff --git a/lib/netdev-dummy.c b/lib/netdev-dummy.c
index 9515021..51b77db 100644
--- a/lib/netdev-dummy.c
+++ b/lib/netdev-dummy.c
@@ -445,7 +445,7 @@ netdev_dummy_rx_dealloc(struct netdev_rx *rx_)
 }
 
 static int
-netdev_dummy_rx_recv(struct netdev_rx *rx_, void *buffer, size_t size)
+netdev_dummy_rx_recv(struct netdev_rx *rx_, struct ofpbuf *buffer)
 {
     struct netdev_rx_dummy *rx = netdev_rx_dummy_cast(rx_);
     struct netdev_dummy *netdev = netdev_dummy_cast(rx->up.netdev);
@@ -465,9 +465,10 @@ netdev_dummy_rx_recv(struct netdev_rx *rx_, void *buffer, 
size_t size)
         return -EAGAIN;
     }
 
-    if (packet->size <= size) {
-        memcpy(buffer, packet->data, packet->size);
-        retval = packet->size;
+    if (packet->size <= ofpbuf_tailroom(buffer)) {
+        memcpy(buffer->data, packet->data, packet->size);
+        buffer->size += packet->size;
+        retval = 0;
 
         ovs_mutex_lock(&netdev->mutex);
         netdev->stats.rx_packets++;
diff --git a/lib/netdev-linux.c b/lib/netdev-linux.c
index 9bdbbdf..ffaaa3b 100644
--- a/lib/netdev-linux.c
+++ b/lib/netdev-linux.c
@@ -849,25 +849,29 @@ netdev_linux_rx_dealloc(struct netdev_rx *rx_)
 }
 
 static int
-netdev_linux_rx_recv(struct netdev_rx *rx_, void *data, size_t size)
+netdev_linux_rx_recv(struct netdev_rx *rx_, struct ofpbuf *buffer)
 {
     struct netdev_rx_linux *rx = netdev_rx_linux_cast(rx_);
     ssize_t retval;
+    size_t size = ofpbuf_tailroom(buffer);
 
     do {
         retval = (rx->is_tap
-                  ? read(rx->fd, data, size)
-                  : recv(rx->fd, data, size, MSG_TRUNC));
+                  ? read(rx->fd, buffer->data, size)
+                  : recv(rx->fd, buffer->data, size, MSG_TRUNC));
     } while (retval < 0 && errno == EINTR);
 
-    if (retval >= 0) {
-        return retval > size ? -EMSGSIZE : retval;
-    } else {
+    if (retval < 0) {
         if (errno != EAGAIN) {
             VLOG_WARN_RL(&rl, "error receiving Ethernet packet on %s: %s",
                          ovs_strerror(errno), netdev_rx_get_name(rx_));
         }
         return -errno;
+    } else if (retval > size) {
+        return -EMSGSIZE;
+    } else {
+        buffer->size += retval;
+        return 0;
     }
 }
 
diff --git a/lib/netdev-provider.h b/lib/netdev-provider.h
index 40ba944..6eec315 100644
--- a/lib/netdev-provider.h
+++ b/lib/netdev-provider.h
@@ -634,16 +634,22 @@ struct netdev_class {
     void (*rx_destruct)(struct netdev_rx *);
     void (*rx_dealloc)(struct netdev_rx *);
 
-    /* Attempts to receive a packet from 'rx' into the 'size' bytes in
-     * 'buffer'.  If successful, returns the number of bytes in the received
-     * packet, otherwise a negative errno value.  Returns -EAGAIN immediately
-     * if no packet is ready to be received.
+    /* Attempts to receive a packet from 'rx' into 'buffer'.
+     * If successful, returns 0 and increments the 'size' field of 'buffer'
+     * by the number of bytes in the received packet, otherwise a negative
+     * errno value.  Returns -EAGAIN immediately if no packet is ready to
+     * be received.
      *
      * Must return -EMSGSIZE, and discard the packet, if the received packet
-     * is longer than 'size' bytes.
+     * is longer than the tailroom of 'buffer'.
+     *
+     * It is advised that the tailroom of 'buffer' should be
+     * VLAN_HEADER_LEN bytes longer than the expected maximum packet size
+     * to allow space for an out of band VLAN header to be added to the
+     * packet.
      *
      * Specify NULL if this */
-    int (*rx_recv)(struct netdev_rx *rx, void *buffer, size_t size);
+    int (*rx_recv)(struct netdev_rx *rx, struct ofpbuf *buffer);
 
     /* Registers with the poll loop to wake up from the next call to
      * poll_block() when a packet is ready to be received with netdev_rx_recv()
diff --git a/lib/netdev.c b/lib/netdev.c
index 1bcd80f..276bf84 100644
--- a/lib/netdev.c
+++ b/lib/netdev.c
@@ -550,11 +550,9 @@ netdev_rx_recv(struct netdev_rx *rx, struct ofpbuf *buffer)
     ovs_assert(buffer->size == 0);
     ovs_assert(ofpbuf_tailroom(buffer) >= ETH_TOTAL_MIN);
 
-    retval = rx->netdev->netdev_class->rx_recv(rx, buffer->data,
-                                               ofpbuf_tailroom(buffer));
+    retval = rx->netdev->netdev_class->rx_recv(rx, buffer);
     if (retval >= 0) {
         COVERAGE_INC(netdev_received);
-        buffer->size += retval;
         if (buffer->size < ETH_TOTAL_MIN) {
             ofpbuf_put_zeros(buffer, ETH_TOTAL_MIN - buffer->size);
         }
-- 
1.8.4

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to