X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Fdevices%2Fvirtio%2Fdevice.c;h=e560c29e5e75603cf116e347cf461eb3e14f5a75;hb=55203e745f5e3f1f6c4dbe99d6eab8dee4d13ea6;hp=609ffb47de84f13047823a96b5e7df52f2fcf164;hpb=6a7cff7ec234af8529ff72a530076e191cc8d759;p=vpp.git diff --git a/src/vnet/devices/virtio/device.c b/src/vnet/devices/virtio/device.c index 609ffb47de8..e560c29e5e7 100644 --- a/src/vnet/devices/virtio/device.c +++ b/src/vnet/devices/virtio/device.c @@ -46,6 +46,7 @@ static char *virtio_tx_func_error_strings[] = { #undef _ }; +#ifndef CLIB_MARCH_VARIANT u8 * format_virtio_device_name (u8 * s, va_list * args) { @@ -64,6 +65,7 @@ format_virtio_device_name (u8 * s, va_list * args) return s; } +#endif /* CLIB_MARCH_VARIANT */ static u8 * format_virtio_device (u8 * s, va_list * args) @@ -88,8 +90,8 @@ format_virtio_tx_trace (u8 * s, va_list * args) return s; } -inline void -virtio_free_used_desc (vlib_main_t * vm, virtio_vring_t * vring) +static_always_inline void +virtio_free_used_device_desc (vlib_main_t * vm, virtio_vring_t * vring) { u16 used = vring->desc_in_use; u16 sz = vring->size; @@ -103,12 +105,31 @@ virtio_free_used_desc (vlib_main_t * vm, virtio_vring_t * vring) while (n_left) { struct vring_used_elem *e = &vring->used->ring[last & mask]; - u16 slot = e->id; + u16 slot, n_buffers; + slot = n_buffers = e->id; - vlib_buffer_free (vm, &vring->buffers[slot], 1); - used--; - last++; - n_left--; + while (e->id == n_buffers) + { + n_left--; + last++; + n_buffers++; + if (n_left == 0) + break; + e = &vring->used->ring[last & mask]; + } + vlib_buffer_free_from_ring (vm, vring->buffers, slot, + sz, (n_buffers - slot)); + used -= (n_buffers - slot); + + if (n_left > 0) + { + slot = e->id; + + vlib_buffer_free (vm, &vring->buffers[slot], 1); + used--; + last++; + n_left--; + } } vring->desc_in_use = used; vring->last_used_idx = last; @@ -166,9 +187,15 @@ add_buffer_to_slot (vlib_main_t * vm, virtio_if_t * vif, * It can easily support 65535 bytes of Jumbo frames with * each data buffer size of 512 bytes minimum. */ - vlib_buffer_t *indirect_desc = - vlib_get_buffer (vm, vring->indirect_buffers[next]); + u32 indirect_buffer = 0; + if (PREDICT_FALSE (vlib_buffer_alloc (vm, &indirect_buffer, 1) == 0)) + return n_added; + + vlib_buffer_t *indirect_desc = vlib_get_buffer (vm, indirect_buffer); indirect_desc->current_data = 0; + indirect_desc->flags |= VLIB_BUFFER_NEXT_PRESENT; + indirect_desc->next_buffer = bi; + bi = indirect_buffer; struct vring_desc *id = (struct vring_desc *) vlib_buffer_get_current (indirect_desc); @@ -241,22 +268,23 @@ virtio_interface_tx_inline (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame, virtio_if_t * vif, int do_gso) { - u8 qid = 0; u16 n_left = frame->n_vectors; - virtio_vring_t *vring = vec_elt_at_index (vif->vrings, (qid << 1) + 1); + virtio_vring_t *vring; + u16 qid = vm->thread_index % vif->num_txqs; + vring = vec_elt_at_index (vif->txq_vrings, qid); u16 used, next, avail; u16 sz = vring->size; u16 mask = sz - 1; u32 *buffers = vlib_frame_vector_args (frame); - clib_spinlock_lock_if_init (&vif->lockp); + clib_spinlock_lock_if_init (&vring->lockp); if ((vring->used->flags & VIRTIO_RING_FLAG_MASK_INT) == 0 && (vring->last_kick_avail_idx != vring->avail->idx)) virtio_kick (vm, vring, vif); /* free consumed buffers */ - virtio_free_used_desc (vm, vring); + virtio_free_used_device_desc (vm, vring); used = vring->desc_in_use; next = vring->desc_next; @@ -294,20 +322,20 @@ virtio_interface_tx_inline (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_buffer_free (vm, buffers, n_left); } - clib_spinlock_unlock_if_init (&vif->lockp); + clib_spinlock_unlock_if_init (&vring->lockp); return frame->n_vectors - n_left; } -static uword -virtio_interface_tx (vlib_main_t * vm, - vlib_node_runtime_t * node, vlib_frame_t * frame) +VNET_DEVICE_CLASS_TX_FN (virtio_device_class) (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * frame) { virtio_main_t *nm = &virtio_main; vnet_interface_output_runtime_t *rund = (void *) node->runtime_data; virtio_if_t *vif = pool_elt_at_index (nm->interfaces, rund->dev_instance); - vnet_main_t *vnm = vnet_get_main (); + if (vnm->interface_main.gso_interface_count > 0) return virtio_interface_tx_inline (vm, node, frame, vif, 1 /* do_gso */ ); else @@ -348,7 +376,7 @@ virtio_interface_rx_mode_change (vnet_main_t * vnm, u32 hw_if_index, u32 qid, virtio_main_t *mm = &virtio_main; vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, hw_if_index); virtio_if_t *vif = pool_elt_at_index (mm->interfaces, hw->dev_instance); - virtio_vring_t *vring = vec_elt_at_index (vif->vrings, qid); + virtio_vring_t *vring = vec_elt_at_index (vif->rxq_vrings, qid); if (vif->type == VIRTIO_IF_TYPE_PCI && !(vif->support_int_mode)) { @@ -391,7 +419,6 @@ virtio_subif_add_del_function (vnet_main_t * vnm, /* *INDENT-OFF* */ VNET_DEVICE_CLASS (virtio_device_class) = { .name = "virtio", - .tx_function = virtio_interface_tx, .format_device_name = format_virtio_device_name, .format_device = format_virtio_device, .format_tx_trace = format_virtio_tx_trace, @@ -403,9 +430,6 @@ VNET_DEVICE_CLASS (virtio_device_class) = { .subif_add_del_function = virtio_subif_add_del_function, .rx_mode_change_function = virtio_interface_rx_mode_change, }; - -VLIB_DEVICE_TX_FUNCTION_MULTIARCH(virtio_device_class, - virtio_interface_tx) /* *INDENT-ON* */ /*