devices: restore regular af-packet tx path

This change restores the af_packet tx path prior
in use prior to Change
Idf0bdd88990254a614962c2f7bc3e0292ccfd61a but
fixes the stalling issue by ensuring that the next
tx frame pointer is only incremented when a new tx
frame is used. This change also enables the
af_packet PACKET_QDISC_BYPASS option, for better
performance.

Change-Id: I65dde648ed66d21654847a900ceda5a8980ae6ec
Type: improvement
Signed-off-by: Mohammed Hawari <mohammed@hawari.fr>
diff --git a/src/vnet/devices/af_packet/af_packet.c b/src/vnet/devices/af_packet/af_packet.c
index 76677a4..cace345 100644
--- a/src/vnet/devices/af_packet/af_packet.c
+++ b/src/vnet/devices/af_packet/af_packet.c
@@ -192,6 +192,15 @@
       goto error;
     }
 
+  if (setsockopt (*fd, SOL_PACKET, PACKET_QDISC_BYPASS, &opt, sizeof (opt)) <
+      0)
+    {
+      vlib_log_debug (apm->log_class,
+		      "Failed to set qdisc bypass error "
+		      "handling option: %s (errno %d)",
+		      strerror (errno), errno);
+    }
+
   if (setsockopt (*fd, SOL_PACKET, PACKET_RX_RING, rx_req, req_sz) < 0)
     {
       vlib_log_debug (apm->log_class,
diff --git a/src/vnet/devices/af_packet/device.c b/src/vnet/devices/af_packet/device.c
index b6b99a0..8a6ff1d 100644
--- a/src/vnet/devices/af_packet/device.c
+++ b/src/vnet/devices/af_packet/device.c
@@ -149,17 +149,12 @@
       u32 bi = buffers[0];
       buffers++;
 
-    nextframe:
       tph = (struct tpacket2_hdr *) (block_start + tx_frame * frame_size);
       if (PREDICT_FALSE (tph->tp_status &
 			 (TP_STATUS_SEND_REQUEST | TP_STATUS_SENDING)))
 	{
-	  tx_frame = (tx_frame + 1) % frame_num;
 	  frame_not_ready++;
-	  /* check if we've exhausted the ring */
-	  if (PREDICT_FALSE (frame_not_ready + n_sent == frame_num))
-	    break;
-	  goto nextframe;
+	  goto next;
 	}
 
       do
@@ -180,6 +175,7 @@
 
       tx_frame = (tx_frame + 1) % frame_num;
 
+    next:
       /* check if we've exhausted the ring */
       if (PREDICT_FALSE (frame_not_ready + n_sent == frame_num))
 	break;
@@ -187,22 +183,24 @@
 
   CLIB_MEMORY_BARRIER ();
 
-  apif->next_tx_frame = tx_frame;
-
   if (PREDICT_TRUE (n_sent))
-    if (PREDICT_FALSE (sendto (apif->fd, NULL, 0, MSG_DONTWAIT, NULL, 0) ==
-		       -1))
-      {
-	/* Uh-oh, drop & move on, but count whether it was fatal or not.
-	 * Note that we have no reliable way to properly determine the
-	 * disposition of the packets we just enqueued for delivery.
-	 */
-	vlib_error_count (vm, node->node_index,
-			  unix_error_is_fatal (errno) ?
-			    AF_PACKET_TX_ERROR_TXRING_FATAL :
-			    AF_PACKET_TX_ERROR_TXRING_EAGAIN,
-			  n_sent);
-      }
+    {
+      apif->next_tx_frame = tx_frame;
+
+      if (PREDICT_FALSE (sendto (apif->fd, NULL, 0, MSG_DONTWAIT, NULL, 0) ==
+			 -1))
+	{
+	  /* Uh-oh, drop & move on, but count whether it was fatal or not.
+	   * Note that we have no reliable way to properly determine the
+	   * disposition of the packets we just enqueued for delivery.
+	   */
+	  vlib_error_count (vm, node->node_index,
+			    unix_error_is_fatal (errno) ?
+			      AF_PACKET_TX_ERROR_TXRING_FATAL :
+			      AF_PACKET_TX_ERROR_TXRING_EAGAIN,
+			    n_sent);
+	}
+    }
 
   clib_spinlock_unlock_if_init (&apif->lockp);