diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/vnet/devices/virtio/device.c | 75 | ||||
-rw-r--r-- | src/vnet/devices/virtio/pci.c | 11 |
2 files changed, 79 insertions, 7 deletions
diff --git a/src/vnet/devices/virtio/device.c b/src/vnet/devices/virtio/device.c index 9d04474ada0..367372fa29a 100644 --- a/src/vnet/devices/virtio/device.c +++ b/src/vnet/devices/virtio/device.c @@ -126,6 +126,14 @@ virtio_free_used_device_desc (vlib_main_t * vm, virtio_vring_t * vring, n_left--; last++; n_buffers++; + struct vring_desc *d = &vring->desc[e->id]; + u16 next; + while (d->flags & VRING_DESC_F_NEXT) + { + n_buffers++; + next = d->next; + d = &vring->desc[next]; + } if (n_left == 0) break; e = &vring->used->ring[last & mask]; @@ -238,8 +246,9 @@ set_gso_offsets (vlib_buffer_t * b, struct virtio_net_hdr_v1 *hdr) static_always_inline u16 add_buffer_to_slot (vlib_main_t * vm, virtio_if_t * vif, - virtio_vring_t * vring, u32 bi, u16 avail, u16 next, - u16 mask, int do_gso, int csum_offload, uword node_index) + virtio_vring_t * vring, u32 bi, u16 free_desc_count, + u16 avail, u16 next, u16 mask, int do_gso, + int csum_offload, uword node_index) { u16 n_added = 0; int hdr_sz = vif->virtio_net_hdr_sz; @@ -283,7 +292,7 @@ add_buffer_to_slot (vlib_main_t * vm, virtio_if_t * vif, d->len = b->current_length + hdr_sz; d->flags = 0; } - else + else if (vif->features & VIRTIO_FEATURE (VIRTIO_RING_F_INDIRECT_DESC)) { /* * We are using single vlib_buffer_t for indirect descriptor(s) @@ -367,6 +376,55 @@ add_buffer_to_slot (vlib_main_t * vm, virtio_if_t * vif, d->len = count * sizeof (struct vring_desc); d->flags = VRING_DESC_F_INDIRECT; } + else if (vif->type == VIRTIO_IF_TYPE_PCI) + { + u16 count = next; + vlib_buffer_t *b_temp = b; + u16 n_buffers_in_chain = 1; + + /* + * Check the length of the chain for the required number of + * descriptors. Return from here, retry to get more descriptors, + * if chain length is greater than available descriptors. + */ + while (b_temp->flags & VLIB_BUFFER_NEXT_PRESENT) + { + n_buffers_in_chain++; + b_temp = vlib_get_buffer (vm, b_temp->next_buffer); + } + + if (n_buffers_in_chain > free_desc_count) + return n_buffers_in_chain; + + d->addr = vlib_buffer_get_current_pa (vm, b) - hdr_sz; + d->len = b->current_length + hdr_sz; + + while (b->flags & VLIB_BUFFER_NEXT_PRESENT) + { + d->flags = VRING_DESC_F_NEXT; + vring->buffers[count] = bi; + b->flags &= + ~(VLIB_BUFFER_NEXT_PRESENT | VLIB_BUFFER_TOTAL_LENGTH_VALID); + bi = b->next_buffer; + b->next_buffer = 0; + n_added++; + count = (count + 1) & mask; + d->next = count; + d = &vring->desc[count]; + b = vlib_get_buffer (vm, bi); + d->addr = vlib_buffer_get_current_pa (vm, b); + d->len = b->current_length; + } + d->flags = 0; + vring->buffers[count] = bi; + vring->avail->ring[avail & mask] = next; + n_added++; + return n_added; + } + else + { + ASSERT (0); + } vring->buffers[next] = bi; vring->avail->ring[avail & mask] = next; n_added++; @@ -457,8 +515,9 @@ retry: { u16 n_added = 0; n_added = - add_buffer_to_slot (vm, vif, vring, buffers[0], avail, next, mask, - do_gso, csum_offload, node->node_index); + add_buffer_to_slot (vm, vif, vring, buffers[0], free_desc_count, + avail, next, mask, do_gso, csum_offload, + node->node_index); if (PREDICT_FALSE (n_added == 0)) { @@ -466,13 +525,15 @@ retry: n_left--; continue; } + else if (PREDICT_FALSE (n_added > free_desc_count)) + break; - avail += n_added; + avail++; next = (next + n_added) & mask; used += n_added; buffers++; n_left--; - free_desc_count--; + free_desc_count -= n_added; } if (n_left != frame->n_vectors) diff --git a/src/vnet/devices/virtio/pci.c b/src/vnet/devices/virtio/pci.c index 5482822b54d..c7398c95fe8 100644 --- a/src/vnet/devices/virtio/pci.c +++ b/src/vnet/devices/virtio/pci.c @@ -1052,6 +1052,17 @@ virtio_pci_device_init (vlib_main_t * vm, virtio_if_t * vif, * read device features and negotiate (user) requested features */ virtio_pci_read_device_feature (vm, vif); + if ((vif->remote_features & VIRTIO_FEATURE (VIRTIO_RING_F_INDIRECT_DESC)) == + 0) + { + virtio_log_warning (vif, "error encountered: vhost-net backend doesn't " + "support VIRTIO_RING_F_INDIRECT_DESC features"); + } + if ((vif->remote_features & VIRTIO_FEATURE (VIRTIO_NET_F_MRG_RXBUF)) == 0) + { + virtio_log_warning (vif, "error encountered: vhost-net backend doesn't " + "support VIRTIO_NET_F_MRG_RXBUF features"); + } virtio_negotiate_features (vm, vif, args->features); /* |