diff options
author | Mohsin Kazmi <sykazmi@cisco.com> | 2021-04-28 18:55:45 +0200 |
---|---|---|
committer | Beno�t Ganne <bganne@cisco.com> | 2021-05-04 16:48:11 +0000 |
commit | 6799f9b45379a8188bf418c61fe0e0aed5c14f01 (patch) | |
tree | 4126cb0f07f9f3ca0fa9592bc640b63b91e5b24b /src/vnet/devices/virtio/node.c | |
parent | db023809043f1dc64ed8c30dd5a575763df6045b (diff) |
virtio: fix the interrupt
Type: fix
virtio/tap interfaces set the empty buffers in the input node
for receiving data. Backend uses those buffers, fills them with
data and notifies the virtio/tap driver. But virtio/tap driver
gets into stall state if interface is created and configured
through exec script on VPP startup.conf and put the interface in
interrupt mode while VPP is only configured with main thread.
This patch fixes the problem by prefilling buffers during the
interface creation.
Change-Id: Ibc4d0e70e127ccc4b7cf8b2b18406ae4b02c73b4
Signed-off-by: Mohsin Kazmi <sykazmi@cisco.com>
Diffstat (limited to 'src/vnet/devices/virtio/node.c')
-rw-r--r-- | src/vnet/devices/virtio/node.c | 164 |
1 files changed, 2 insertions, 162 deletions
diff --git a/src/vnet/devices/virtio/node.c b/src/vnet/devices/virtio/node.c index df8c0fa9a64..f91dc877fb4 100644 --- a/src/vnet/devices/virtio/node.c +++ b/src/vnet/devices/virtio/node.c @@ -33,21 +33,10 @@ #include <vnet/ip/ip6_packet.h> #include <vnet/udp/udp_packet.h> #include <vnet/devices/virtio/virtio.h> - -#define foreach_virtio_input_error \ - _(BUFFER_ALLOC, "buffer alloc error") \ - _(UNKNOWN, "unknown") - -typedef enum -{ -#define _(f,s) VIRTIO_INPUT_ERROR_##f, - foreach_virtio_input_error -#undef _ - VIRTIO_INPUT_N_ERROR, -} virtio_input_error_t; +#include <vnet/devices/virtio/virtio_inline.h> static char *virtio_input_error_strings[] = { -#define _(n,s) s, +#define _(n, s) s, foreach_virtio_input_error #undef _ }; @@ -80,155 +69,6 @@ format_virtio_input_trace (u8 * s, va_list * args) } static_always_inline void -virtio_refill_vring_split (vlib_main_t * vm, virtio_if_t * vif, - virtio_if_type_t type, virtio_vring_t * vring, - const int hdr_sz, u32 node_index) -{ - u16 used, next, avail, n_slots, n_refill; - u16 sz = vring->size; - u16 mask = sz - 1; - -more: - used = vring->desc_in_use; - - if (sz - used < sz / 8) - return; - - /* deliver free buffers in chunks of 64 */ - n_refill = clib_min (sz - used, 64); - - next = vring->desc_next; - avail = vring->avail->idx; - n_slots = - vlib_buffer_alloc_to_ring_from_pool (vm, vring->buffers, next, - vring->size, n_refill, - vring->buffer_pool_index); - - if (PREDICT_FALSE (n_slots != n_refill)) - { - vlib_error_count (vm, node_index, - VIRTIO_INPUT_ERROR_BUFFER_ALLOC, n_refill - n_slots); - if (n_slots == 0) - return; - } - - while (n_slots) - { - vring_desc_t *d = &vring->desc[next];; - vlib_buffer_t *b = vlib_get_buffer (vm, vring->buffers[next]); - /* - * current_data may not be initialized with 0 and may contain - * previous offset. Here we want to make sure, it should be 0 - * initialized. - */ - b->current_data = -hdr_sz; - clib_memset (vlib_buffer_get_current (b), 0, hdr_sz); - d->addr = - ((type == VIRTIO_IF_TYPE_PCI) ? vlib_buffer_get_current_pa (vm, - b) : - pointer_to_uword (vlib_buffer_get_current (b))); - d->len = vlib_buffer_get_default_data_size (vm) + hdr_sz; - d->flags = VRING_DESC_F_WRITE; - vring->avail->ring[avail & mask] = next; - avail++; - next = (next + 1) & mask; - n_slots--; - used++; - } - clib_atomic_store_seq_cst (&vring->avail->idx, avail); - vring->desc_next = next; - vring->desc_in_use = used; - if ((clib_atomic_load_seq_cst (&vring->used->flags) & - VRING_USED_F_NO_NOTIFY) == 0) - { - virtio_kick (vm, vring, vif); - } - goto more; -} - -static_always_inline void -virtio_refill_vring_packed (vlib_main_t * vm, virtio_if_t * vif, - virtio_if_type_t type, virtio_vring_t * vring, - const int hdr_sz, u32 node_index) -{ - u16 used, next, n_slots, n_refill, flags = 0, first_desc_flags; - u16 sz = vring->size; - -more: - used = vring->desc_in_use; - - if (sz == used) - return; - - /* deliver free buffers in chunks of 64 */ - n_refill = clib_min (sz - used, 64); - - next = vring->desc_next; - first_desc_flags = vring->packed_desc[next].flags; - n_slots = - vlib_buffer_alloc_to_ring_from_pool (vm, vring->buffers, next, - sz, n_refill, - vring->buffer_pool_index); - - if (PREDICT_FALSE (n_slots != n_refill)) - { - vlib_error_count (vm, node_index, - VIRTIO_INPUT_ERROR_BUFFER_ALLOC, n_refill - n_slots); - if (n_slots == 0) - return; - } - - while (n_slots) - { - vring_packed_desc_t *d = &vring->packed_desc[next]; - vlib_buffer_t *b = vlib_get_buffer (vm, vring->buffers[next]); - /* - * current_data may not be initialized with 0 and may contain - * previous offset. Here we want to make sure, it should be 0 - * initialized. - */ - b->current_data = -hdr_sz; - clib_memset (vlib_buffer_get_current (b), 0, hdr_sz); - d->addr = - ((type == VIRTIO_IF_TYPE_PCI) ? vlib_buffer_get_current_pa (vm, - b) : - pointer_to_uword (vlib_buffer_get_current (b))); - d->len = vlib_buffer_get_default_data_size (vm) + hdr_sz; - - if (vring->avail_wrap_counter) - flags = (VRING_DESC_F_AVAIL | VRING_DESC_F_WRITE); - else - flags = (VRING_DESC_F_USED | VRING_DESC_F_WRITE); - - d->id = next; - if (vring->desc_next == next) - first_desc_flags = flags; - else - d->flags = flags; - - next++; - if (next >= sz) - { - next = 0; - vring->avail_wrap_counter ^= 1; - } - n_slots--; - used++; - } - CLIB_MEMORY_STORE_BARRIER (); - vring->packed_desc[vring->desc_next].flags = first_desc_flags; - vring->desc_next = next; - vring->desc_in_use = used; - CLIB_MEMORY_BARRIER (); - if (vring->device_event->flags != VRING_EVENT_F_DISABLE) - { - virtio_kick (vm, vring, vif); - } - - goto more; -} - -static_always_inline void virtio_needs_csum (vlib_buffer_t * b0, virtio_net_hdr_v1_t * hdr, u8 * l4_proto, u8 * l4_hdr_sz, virtio_if_type_t type) { |