diff options
author | Steven <sluong@cisco.com> | 2018-01-09 11:13:29 -0800 |
---|---|---|
committer | steven luong <sluong@cisco.com> | 2018-01-16 16:59:18 +0000 |
commit | a624dbe7711a5852110a2cc28da1f72f5817708b (patch) | |
tree | 04f727fa8ed3955d0b306b6136671c81efff5c26 /src/vnet/devices/virtio/virtio.c | |
parent | 887ffb65fd9ce99db9a2ae0a3a1fa5456ba9b67c (diff) |
tapv2: deleting tap interface may leak buffers (VPP-1124)
Buffers may be allocated for indirect descriptors by tx thread and
they are freed when tx thread is invoked in the next invocation.
This is to allow the recipient (kernel) to have a chance to process
them. But if the tap interface is deleted, the tx thread may not yet
be called to clean up the indirect descriptors' buffers. In that case,
we need to remove them without waiting for the tx thread to be called.
Failure to do so may cause buffers leak when the tap interface is deleted.
For the RX ring, leakage also exists for vring->buffers when the interface
is removed.
Change-Id: I3df313a0e60334776b19daf51a9f5bf20dfdc489
Signed-off-by: Steven <sluong@cisco.com>
(cherry picked from commit d8a998e74b815dd3725dfcd80080e4e540940236)
Diffstat (limited to 'src/vnet/devices/virtio/virtio.c')
-rw-r--r-- | src/vnet/devices/virtio/virtio.c | 35 |
1 files changed, 28 insertions, 7 deletions
diff --git a/src/vnet/devices/virtio/virtio.c b/src/vnet/devices/virtio/virtio.c index 7829da6b1a1..3867cf03a46 100644 --- a/src/vnet/devices/virtio/virtio.c +++ b/src/vnet/devices/virtio/virtio.c @@ -134,20 +134,41 @@ error: return err; } +static_always_inline void +virtio_free_rx_buffers (vlib_main_t * vm, virtio_vring_t * vring) +{ + u16 used = vring->desc_in_use; + u16 next = vring->desc_next; + u16 mask = vring->size - 1; + + while (used) + { + vlib_buffer_free (vm, &vring->buffers[next], 1); + next = (next + 1) & mask; + used--; + } +} + clib_error_t * -virtio_vring_free (virtio_if_t * vif, u32 idx) +virtio_vring_free (vlib_main_t * vm, virtio_if_t * vif, u32 idx) { - //TODO free buffers and indirect descriptor allocs virtio_vring_t *vring = vec_elt_at_index (vif->vrings, idx); + + clib_file_del_by_index (&file_main, vring->call_file_index); + close (vring->kick_fd); + close (vring->call_fd); + if (vring->used) + { + if ((idx & 1) == 1) + virtio_free_used_desc (vm, vring); + else + virtio_free_rx_buffers (vm, vring); + clib_mem_free (vring->used); + } if (vring->desc) clib_mem_free (vring->desc); if (vring->avail) clib_mem_free (vring->avail); - if (vring->used) - clib_mem_free (vring->used); - clib_file_del_by_index (&file_main, vring->call_file_index); - close (vring->kick_fd); - close (vring->call_fd); vec_free (vring->buffers); return 0; } |