tap: fix the buffering index for gro
[vpp.git] / src / vnet / devices / virtio / device.c
index 6b57dd6..5796b1d 100644 (file)
@@ -947,13 +947,11 @@ virtio_interface_tx_gso_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
   if (packed)
     return virtio_interface_tx_packed_gso_inline (vm, node, vif, type, vring,
                                                  buffers, n_left,
-                                                 1 /* do_gso */ ,
-                                                 1 /* checksum offload */ );
+                                                 do_gso, csum_offload);
   else
     return virtio_interface_tx_split_gso_inline (vm, node, vif, type, vring,
                                                 buffers, n_left,
-                                                1 /* do_gso */ ,
-                                                1 /* checksum offload */ );
+                                                do_gso, csum_offload);
 }
 
 static_always_inline u16
@@ -995,16 +993,20 @@ VNET_DEVICE_CLASS_TX_FN (virtio_device_class) (vlib_main_t * vm,
   u32 *buffers = vlib_frame_vector_args (frame);
   u32 to[GRO_TO_VECTOR_SIZE (n_left)];
   int packed = vif->is_packed;
+  u16 n_vectors = frame->n_vectors;
 
   clib_spinlock_lock_if_init (&vring->lockp);
 
-  if ((vring->used->flags & VRING_USED_F_NO_NOTIFY) == 0 &&
-      (vring->last_kick_avail_idx != vring->avail->idx))
+  if (packed && (vring->device_event->flags != VRING_EVENT_F_DISABLE))
+    virtio_kick (vm, vring, vif);
+  else if ((vring->used->flags & VRING_USED_F_NO_NOTIFY) == 0 &&
+          (vring->last_kick_avail_idx != vring->avail->idx))
     virtio_kick (vm, vring, vif);
 
   if (vif->packet_coalesce)
     {
-      n_left = vnet_gro_inline (vm, vring->flow_table, buffers, n_left, to);
+      n_vectors = n_left =
+       vnet_gro_inline (vm, vring->flow_table, buffers, n_left, to);
       buffers = to;
     }
 
@@ -1017,17 +1019,17 @@ retry:
   if (vif->type == VIRTIO_IF_TYPE_TAP)
     n_left = virtio_interface_tx_inline (vm, node, vif, vring,
                                         VIRTIO_IF_TYPE_TAP,
-                                        &buffers[frame->n_vectors - n_left],
+                                        &buffers[n_vectors - n_left],
                                         n_left, packed);
   else if (vif->type == VIRTIO_IF_TYPE_PCI)
     n_left = virtio_interface_tx_inline (vm, node, vif, vring,
                                         VIRTIO_IF_TYPE_PCI,
-                                        &buffers[frame->n_vectors - n_left],
+                                        &buffers[n_vectors - n_left],
                                         n_left, packed);
   else if (vif->type == VIRTIO_IF_TYPE_TUN)
     n_left = virtio_interface_tx_inline (vm, node, vif, vring,
                                         VIRTIO_IF_TYPE_TUN,
-                                        &buffers[frame->n_vectors - n_left],
+                                        &buffers[n_vectors - n_left],
                                         n_left, packed);
   else
     ASSERT (0);
@@ -1039,14 +1041,14 @@ retry:
     {
       u16 n_buffered = virtio_vring_buffering_store_packets (vring->buffering,
                                                             &buffers
-                                                            [frame->n_vectors
+                                                            [n_vectors
                                                              - n_left],
                                                             n_left);
       n_left -= n_buffered;
     }
   if (n_left)
     virtio_interface_drop_inline (vm, node->node_index,
-                                 &buffers[frame->n_vectors - n_left], n_left,
+                                 &buffers[n_vectors - n_left], n_left,
                                  VIRTIO_TX_ERROR_NO_FREE_SLOTS);
 
   clib_spinlock_unlock_if_init (&vring->lockp);
@@ -1080,6 +1082,24 @@ virtio_clear_hw_interface_counters (u32 instance)
   /* Nothing for now */
 }
 
+static_always_inline void
+virtio_set_rx_interrupt (virtio_if_t * vif, virtio_vring_t * vring)
+{
+  if (vif->is_packed)
+    vring->driver_event->flags &= ~VRING_EVENT_F_DISABLE;
+  else
+    vring->avail->flags &= ~VRING_AVAIL_F_NO_INTERRUPT;
+}
+
+static_always_inline void
+virtio_set_rx_polling (virtio_if_t * vif, virtio_vring_t * vring)
+{
+  if (vif->is_packed)
+    vring->driver_event->flags |= VRING_EVENT_F_DISABLE;
+  else
+    vring->avail->flags |= VRING_AVAIL_F_NO_INTERRUPT;
+}
+
 static clib_error_t *
 virtio_interface_rx_mode_change (vnet_main_t * vnm, u32 hw_if_index, u32 qid,
                                 vnet_hw_if_rx_mode mode)
@@ -1092,7 +1112,7 @@ virtio_interface_rx_mode_change (vnet_main_t * vnm, u32 hw_if_index, u32 qid,
 
   if (vif->type == VIRTIO_IF_TYPE_PCI && !(vif->support_int_mode))
     {
-      rx_vring->avail->flags |= VRING_AVAIL_F_NO_INTERRUPT;
+      virtio_set_rx_polling (vif, rx_vring);
       return clib_error_return (0, "interrupt mode is not supported");
     }
 
@@ -1107,7 +1127,7 @@ virtio_interface_rx_mode_change (vnet_main_t * vnm, u32 hw_if_index, u32 qid,
                                       virtio_send_interrupt_node.index,
                                       VIRTIO_EVENT_STOP_TIMER, 0);
        }
-      rx_vring->avail->flags |= VRING_AVAIL_F_NO_INTERRUPT;
+      virtio_set_rx_polling (vif, rx_vring);
     }
   else
     {
@@ -1119,7 +1139,7 @@ virtio_interface_rx_mode_change (vnet_main_t * vnm, u32 hw_if_index, u32 qid,
                                       virtio_send_interrupt_node.index,
                                       VIRTIO_EVENT_START_TIMER, 0);
        }
-      rx_vring->avail->flags &= ~VRING_AVAIL_F_NO_INTERRUPT;
+      virtio_set_rx_interrupt (vif, rx_vring);
     }
 
   rx_vring->mode = mode;