diff options
Diffstat (limited to 'src/vnet/devices/virtio/node.c')
-rw-r--r-- | src/vnet/devices/virtio/node.c | 37 |
1 files changed, 25 insertions, 12 deletions
diff --git a/src/vnet/devices/virtio/node.c b/src/vnet/devices/virtio/node.c index d7a0b3964b4..c02b607d5fe 100644 --- a/src/vnet/devices/virtio/node.c +++ b/src/vnet/devices/virtio/node.c @@ -80,9 +80,9 @@ 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; @@ -108,7 +108,18 @@ more: { 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; @@ -123,7 +134,9 @@ more: vring->desc_in_use = used; if ((vring->used->flags & VIRTIO_RING_FLAG_MASK_INT) == 0) - virtio_kick (vring); + { + virtio_kick (vm, vring, vif); + } goto more; } @@ -136,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; @@ -146,7 +159,7 @@ virtio_device_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node, if ((vring->used->flags & VIRTIO_RING_FLAG_MASK_INT) == 0 && vring->last_kick_avail_idx != vring->avail->idx) - virtio_kick (vring); + virtio_kick (vm, vring, vif); if (n_left == 0) goto refill; @@ -159,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; @@ -189,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 */ @@ -253,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; } |