On Wed, Jan 15, 2014 at 05:17:02PM +0900, Simon Horman wrote:
> If VLAN acceleration is used when the kernel receives a packet
> then the outer-most VLAN tag will not be present in the packet
> when it is received by netdev-linux. Rather, it will be present
> in auxdata.
> 
> This patch uses recvmsg() instead of recv() to read auxdata for
> each packet and if the vlan_tid is set then it is added to the packet.
> 
> Adding the vlan_tid makes use of headroom available
> in the buffer parameter of rx_recv.
> 
> Co-authored-by: Ben Pfaff <b...@nicira.com>
> Signed-off-by: Simon Horman <ho...@verge.net.au>

I noticed one minor bug (ETH_ADDR_LEN should be ETH_HEADER_LEN) and a
number of opportunities for minor improvements.  I'm folding in the
following, and then I'll apply it to master.

Thank you!

diff --git a/lib/netdev-linux.c b/lib/netdev-linux.c
index 4bd4bfc..9c1a36d 100644
--- a/lib/netdev-linux.c
+++ b/lib/netdev-linux.c
@@ -809,9 +809,7 @@ netdev_linux_rx_construct(struct netdev_rx *rx_)
         }
 
         val = 1;
-        error = setsockopt(rx->fd, SOL_PACKET, PACKET_AUXDATA,
-                           &val, sizeof val);
-        if (error) {
+        if (setsockopt(rx->fd, SOL_PACKET, PACKET_AUXDATA, &val, sizeof val)) {
             error = errno;
             VLOG_ERR("%s: failed to mark socket for auxdata (%s)",
                      netdev_get_name(netdev_), ovs_strerror(error));
@@ -946,9 +944,9 @@ netdev_linux_rx_recv_sock(int fd, struct ofpbuf *buffer)
             continue;
         }
 
-        aux = (struct tpacket_auxdata *)(void *)CMSG_DATA(cmsg);
+        aux = ALIGNED_CAST(struct tpacket_auxdata *, CMSG_DATA(cmsg));
         if (auxdata_has_vlan_tci(aux)) {
-            if (retval < ETH_ADDR_LEN) {
+            if (retval < ETH_HEADER_LEN) {
                 return EINVAL;
             }
 
@@ -990,11 +988,9 @@ netdev_linux_rx_recv(struct netdev_rx *rx_, struct ofpbuf 
*buffer)
     retval = (rx->is_tap
               ? netdev_linux_rx_recv_tap(rx->fd, buffer)
               : netdev_linux_rx_recv_sock(rx->fd, buffer));
-    if (retval) {
-        if (retval != EAGAIN && retval != EMSGSIZE) {
-            VLOG_WARN_RL(&rl, "error receiving Ethernet packet on %s: %s",
-                         ovs_strerror(errno), netdev_rx_get_name(rx_));
-        }
+    if (retval && retval != EAGAIN && retval != EMSGSIZE) {
+        VLOG_WARN_RL(&rl, "error receiving Ethernet packet on %s: %s",
+                     ovs_strerror(errno), netdev_rx_get_name(rx_));
     }
 
     return retval;
diff --git a/lib/netdev.c b/lib/netdev.c
index 66b411a..8e62421 100644
--- a/lib/netdev.c
+++ b/lib/netdev.c
@@ -500,6 +500,13 @@ netdev_parse_name(const char *netdev_name_, char **name, 
char **type)
     }
 }
 
+/* Attempts to open a netdev_rx handle for obtaining packets received on
+ * 'netdev'.  On success, returns 0 and stores a nonnull 'netdev_rx *' into
+ * '*rxp'.  On failure, returns a positive errno value and stores NULL into
+ * '*rxp'.
+ *
+ * Some kinds of network devices might not support receiving packets.  This
+ * function returns EOPNOTSUPP in that case.*/
 int
 netdev_rx_open(struct netdev *netdev, struct netdev_rx **rxp)
     OVS_EXCLUDED(netdev_mutex)
@@ -531,6 +538,7 @@ netdev_rx_open(struct netdev *netdev, struct netdev_rx 
**rxp)
     return error;
 }
 
+/* Closes 'rx'. */
 void
 netdev_rx_close(struct netdev_rx *rx)
     OVS_EXCLUDED(netdev_mutex)
@@ -543,6 +551,29 @@ netdev_rx_close(struct netdev_rx *rx)
     }
 }
 
+/* Attempts to receive a packet from 'rx' into the tailroom of 'buffer', which
+ * must initially be empty.  If successful, returns 0 and increments
+ * 'buffer->size' by the number of bytes in the received packet, otherwise a
+ * positive errno value.
+ *
+ * Returns EAGAIN immediately if no packet is ready to be received.
+ *
+ * Returns EMSGSIZE, and discards the packet, if the received packet is longer
+ * than 'ofpbuf_tailroom(buffer)'.
+ *
+ * Implementations may make use of VLAN_HEADER_LEN bytes of tailroom to
+ * add a VLAN header which is obtained out-of-band to the packet. If
+ * this occurs then VLAN_HEADER_LEN bytes of tailroom will no longer be
+ * available for the packet, otherwise it may be used for the packet
+ * itself.
+ *
+ * It is advised that the tailroom of 'buffer' should be
+ * VLAN_HEADER_LEN bytes longer than the MTU to allow space for an
+ * out-of-band VLAN header to be added to the packet.  At the very least,
+ * 'buffer' must have at least ETH_TOTAL_MIN bytes of tailroom.
+ *
+ * This function may be set to null if it would always return EOPNOTSUPP
+ * anyhow. */
 int
 netdev_rx_recv(struct netdev_rx *rx, struct ofpbuf *buffer)
 {
@@ -563,12 +594,15 @@ netdev_rx_recv(struct netdev_rx *rx, struct ofpbuf 
*buffer)
     }
 }
 
+/* Arranges for poll_block() to wake up when a packet is ready to be received
+ * on 'rx'. */
 void
 netdev_rx_wait(struct netdev_rx *rx)
 {
     rx->netdev->netdev_class->rx_wait(rx);
 }
 
+/* Discards any packets ready to be received on 'rx'. */
 int
 netdev_rx_drain(struct netdev_rx *rx)
 {
_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to