X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Fdevices%2Fvirtio%2Fnode.c;h=c02b607d5fe20b6fa012e9459f7fae804ecc9a22;hb=d6c15af33;hp=e019513932109a33331edf3ada41a635886dcc2e;hpb=178cf493d009995b28fdf220f04c98860ff79a9b;p=vpp.git diff --git a/src/vnet/devices/virtio/node.c b/src/vnet/devices/virtio/node.c index e0195139321..c02b607d5fe 100644 --- a/src/vnet/devices/virtio/node.c +++ b/src/vnet/devices/virtio/node.c @@ -80,29 +80,46 @@ format_virtio_input_trace (u8 * s, va_list * args) } static_always_inline void -virtio_refill_vring (vlib_main_t * vm, virtio_vring_t * vring) +virtio_refill_vring (vlib_main_t * vm, virtio_if_t * vif, + virtio_vring_t * vring, const int hdr_sz) { - const int hdr_sz = sizeof (struct virtio_net_hdr_v1); u16 used, next, avail, n_slots; u16 sz = vring->size; u16 mask = sz - 1; +more: used = vring->desc_in_use; if (sz - used < sz / 8) return; - n_slots = sz - used; + /* deliver free buffers in chunks of 64 */ + n_slots = clib_min (sz - used, 64); + next = vring->desc_next; avail = vring->avail->idx; n_slots = vlib_buffer_alloc_to_ring (vm, vring->buffers, next, vring->size, n_slots); + if (n_slots == 0) + return; + while (n_slots) { struct vring_desc *d = &vring->desc[next];; vlib_buffer_t *b = vlib_get_buffer (vm, vring->buffers[next]); - d->addr = pointer_to_uword (vlib_buffer_get_current (b)) - hdr_sz; + /* + * 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 = 0; + b->current_data -= hdr_sz; + memset (vlib_buffer_get_current (b), 0, hdr_sz); + d->addr = + ((vif->type == VIRTIO_IF_TYPE_PCI) ? vlib_buffer_get_current_pa (vm, + b) : + pointer_to_uword (vlib_buffer_get_current (b))); d->len = VLIB_BUFFER_DATA_SIZE + hdr_sz; d->flags = VRING_DESC_F_WRITE; vring->avail->ring[avail & mask] = next; @@ -118,9 +135,9 @@ virtio_refill_vring (vlib_main_t * vm, virtio_vring_t * vring) if ((vring->used->flags & VIRTIO_RING_FLAG_MASK_INT) == 0) { - u64 b = 1; - CLIB_UNUSED (int r) = write (vring->kick_fd, &b, sizeof (b)); + virtio_kick (vm, vring, vif); } + goto more; } static_always_inline uword @@ -132,7 +149,7 @@ virtio_device_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node, uword n_trace = vlib_get_trace_count (vm, node); virtio_vring_t *vring = vec_elt_at_index (vif->vrings, 0); u32 next_index = VNET_DEVICE_INPUT_NEXT_ETHERNET_INPUT; - const int hdr_sz = sizeof (struct virtio_net_hdr_v1); + const int hdr_sz = vif->virtio_net_hdr_sz; u32 *to_next = 0; u32 n_rx_packets = 0; u32 n_rx_bytes = 0; @@ -140,6 +157,10 @@ virtio_device_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node, u16 last = vring->last_used_idx; u16 n_left = vring->used->idx - last; + if ((vring->used->flags & VIRTIO_RING_FLAG_MASK_INT) == 0 && + vring->last_kick_avail_idx != vring->avail->idx) + virtio_kick (vm, vring, vif); + if (n_left == 0) goto refill; @@ -151,17 +172,18 @@ virtio_device_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node, while (n_left && n_left_to_next) { - u16 num_buffers; + u16 num_buffers = 1; struct vring_used_elem *e = &vring->used->ring[last & mask]; struct virtio_net_hdr_v1 *hdr; u16 slot = e->id; u16 len = e->len - hdr_sz; u32 bi0 = vring->buffers[slot]; vlib_buffer_t *b0 = vlib_get_buffer (vm, bi0); - hdr = vlib_buffer_get_current (b0) - hdr_sz; - num_buffers = hdr->num_buffers; + hdr = vlib_buffer_get_current (b0); + if (hdr_sz == sizeof (struct virtio_net_hdr_v1)) + num_buffers = hdr->num_buffers; - b0->current_data = 0; + b0->current_data += hdr_sz; b0->current_length = len; b0->total_length_not_including_first_buffer = 0; b0->flags = VLIB_BUFFER_TOTAL_LENGTH_VALID; @@ -181,7 +203,6 @@ virtio_device_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node, cb = vlib_get_buffer (vm, cbi); /* current buffer */ - cb->current_data = -hdr_sz; cb->current_length = e->len; /* previous buffer */ @@ -245,7 +266,7 @@ virtio_device_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node, n_rx_bytes); refill: - virtio_refill_vring (vm, vring); + virtio_refill_vring (vm, vif, vring, hdr_sz); return n_rx_packets; }