NETMAP: Some fixes 51/951/6
authorMohsin Kazmi <sykazmi@cisco.com>
Mon, 2 May 2016 12:04:57 +0000 (14:04 +0200)
committerDamjan Marion <damarion@cisco.com>
Wed, 4 May 2016 17:18:11 +0000 (17:18 +0000)
1) Correct the NIOCRXSYNC macro on receive side from NIOCTXSYNC.
2) Flush the pending messages in the tx rings.

Change-Id: I581040d03b1633a3d6fb22fa1fb285bcb7975afb
Signed-off-by: Mohsin Kazmi <sykazmi@cisco.com>
vnet/vnet/devices/netmap/device.c
vnet/vnet/devices/netmap/netmap.h
vnet/vnet/devices/netmap/node.c

index 36e17da..dcd0473 100644 (file)
@@ -22,7 +22,8 @@
 #include <vnet/devices/netmap/netmap.h>
 
 #define foreach_netmap_tx_func_error          \
-_(NO_FREE_SLOTS, "no free tx slots")
+_(NO_FREE_SLOTS, "no free tx slots")           \
+_(PENDING_MSGS, "pending msgs in tx ring")
 
 typedef enum {
 #define _(f,s) NETMAP_TX_ERROR_##f,
@@ -92,6 +93,7 @@ netmap_interface_tx (vlib_main_t * vm,
   netmap_main_t * nm = &netmap_main;
   u32 * buffers = vlib_frame_args (frame);
   u32 n_left = frame->n_vectors;
+  f64 const time_constant = 1e3;
   vnet_interface_output_runtime_t * rd = (void *) node->runtime_data;
   netmap_if_t * nif = pool_elt_at_index (nm->interfaces, rd->dev_instance);
   int cur_ring;
@@ -104,21 +106,27 @@ netmap_interface_tx (vlib_main_t * vm,
       int n_free_slots = nm_ring_space(ring);
       uint cur = ring->cur;
 
-      if (!n_free_slots)
-       {
-         cur_ring++;
-         continue;
-       }
+      if (nm_tx_pending(ring))
+        {
+         ioctl(nif->fd, NIOCTXSYNC, NULL);
+         clib_cpu_time_wait(time_constant);
+
+         if (nm_tx_pending(ring) && !n_free_slots)
+           {
+             cur_ring++;
+             continue;
+           }
+        }
 
       while (n_left && n_free_slots)
        {
-         vlib_buffer_t * b0;
+         vlib_buffer_t * b0 = 0;
          u32 bi = buffers[0];
          u32 len;
          u32 offset = 0;
          buffers++;
 
-         struct netmap_slot * slot = &ring->slot[cur];
+          struct netmap_slot * slot = &ring->slot[cur];
 
          do
            {
@@ -144,8 +152,8 @@ netmap_interface_tx (vlib_main_t * vm,
       ioctl(nif->fd, NIOCTXSYNC, NULL);
 
   if (n_left)
-    vlib_error_count (vm, node->node_index, NETMAP_TX_ERROR_NO_FREE_SLOTS,
-                     n_left);
+    vlib_error_count (vm, node->node_index,
+    (n_left == frame->n_vectors ? NETMAP_TX_ERROR_PENDING_MSGS : NETMAP_TX_ERROR_NO_FREE_SLOTS), n_left);
 
   vlib_buffer_free (vm, vlib_frame_args (frame), frame->n_vectors);
   return frame->n_vectors;
index d9a476b..15b14db 100644 (file)
@@ -119,6 +119,23 @@ int netmap_delete_if(vlib_main_t * vm, u8 * host_if_name);
        ( ((char *)(buf) - ((char *)(ring) + (ring)->buf_ofs) ) / \
                (ring)->nr_buf_size )
 
+static inline uint32_t
+nm_ring_next(struct netmap_ring *ring, uint32_t i)
+{
+        return ( unlikely(i + 1 == ring->num_slots) ? 0 : i + 1);
+}
+
+
+/*
+ * Return 1 if we have pending transmissions in the tx ring.
+ * When everything is complete ring->head = ring->tail + 1 (modulo ring size)
+ */
+static inline int
+nm_tx_pending(struct netmap_ring *ring)
+{
+        return nm_ring_next(ring, ring->tail) != ring->head;
+}
+
 static inline uint32_t
 nm_ring_space(struct netmap_ring *ring)
 {
index f866a28..d4c0141 100644 (file)
@@ -235,7 +235,7 @@ netmap_device_input_fn  (vlib_main_t * vm, vlib_node_runtime_t * node,
     }
 
   if (n_rx_packets)
-    ioctl(nif->fd, NIOCTXSYNC, NULL);
+    ioctl(nif->fd, NIOCRXSYNC, NULL);
 
   vlib_increment_combined_counter
     (vnet_get_main()->interface_main.combined_sw_if_counters