aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDamjan Marion <damarion@cisco.com>2018-12-20 10:44:47 +0100
committersteven luong <sluong@cisco.com>2019-01-23 03:43:27 +0000
commit9858d374ad1f789c8c860e00e2b8d4d01fdc1e73 (patch)
tree0e92410c675ec7f71df2be9318c647366ddd52a8
parent69a9fc053d2d2bc11399e0c74d23983298da8187 (diff)
virtio: fix kick race issue [VPP-1489]
Change-Id: I25b2a28513821bc5eab9ac6890a3964d412b0399 Signed-off-by: Damjan Marion <damarion@cisco.com> (cherry picked from commit e40231b1ecf4b49faaa9ce7b615a7d867104825b)
-rw-r--r--src/vnet/devices/virtio/device.c10
-rw-r--r--src/vnet/devices/virtio/node.c18
-rw-r--r--src/vnet/devices/virtio/virtio.h11
3 files changed, 29 insertions, 10 deletions
diff --git a/src/vnet/devices/virtio/device.c b/src/vnet/devices/virtio/device.c
index c7efe6519cd..d50ef88d3fb 100644
--- a/src/vnet/devices/virtio/device.c
+++ b/src/vnet/devices/virtio/device.c
@@ -169,7 +169,6 @@ add_buffer_to_slot (vlib_main_t * vm, virtio_vring_t * vring, u32 bi,
return n_added;
}
-
static_always_inline uword
virtio_interface_tx_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
vlib_frame_t * frame, virtio_if_t * vif)
@@ -184,6 +183,10 @@ virtio_interface_tx_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
clib_spinlock_lock_if_init (&vif->lockp);
+ if ((vring->used->flags & VIRTIO_RING_FLAG_MASK_INT) == 0 &&
+ vring->last_kick_avail_idx != vring->avail->idx)
+ virtio_kick (vring);
+
/* free consumed buffers */
virtio_free_used_desc (vm, vring);
@@ -209,10 +212,7 @@ virtio_interface_tx_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
vring->desc_next = next;
vring->desc_in_use = used;
if ((vring->used->flags & VIRTIO_RING_FLAG_MASK_INT) == 0)
- {
- u64 x = 1;
- CLIB_UNUSED (int r) = write (vring->kick_fd, &x, sizeof (x));
- }
+ virtio_kick (vring);
}
diff --git a/src/vnet/devices/virtio/node.c b/src/vnet/devices/virtio/node.c
index 339c48c93f5..419b025b3ae 100644
--- a/src/vnet/devices/virtio/node.c
+++ b/src/vnet/devices/virtio/node.c
@@ -87,17 +87,23 @@ virtio_refill_vring (vlib_main_t * vm, virtio_vring_t * vring)
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];;
@@ -117,10 +123,8 @@ virtio_refill_vring (vlib_main_t * vm, virtio_vring_t * vring)
vring->desc_in_use = used;
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 (vring);
+ goto more;
}
static_always_inline uword
@@ -140,6 +144,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 (vring);
+
if (n_left == 0)
goto refill;
diff --git a/src/vnet/devices/virtio/virtio.h b/src/vnet/devices/virtio/virtio.h
index 5fc521672d9..8ac87c8ccfd 100644
--- a/src/vnet/devices/virtio/virtio.h
+++ b/src/vnet/devices/virtio/virtio.h
@@ -86,6 +86,7 @@ typedef struct
u32 call_file_index;
u32 *buffers;
u16 last_used_idx;
+ u16 last_kick_avail_idx;
} virtio_vring_t;
typedef struct
@@ -136,6 +137,16 @@ extern void virtio_free_used_desc (vlib_main_t * vm, virtio_vring_t * vring);
format_function_t format_virtio_device_name;
+static_always_inline void
+virtio_kick (virtio_vring_t * vring)
+{
+ u64 x = 1;
+ int __clib_unused r;
+
+ r = write (vring->kick_fd, &x, sizeof (x));
+ vring->last_kick_avail_idx = vring->avail->idx;
+}
+
#endif /* _VNET_DEVICES_VIRTIO_VIRTIO_H_ */
/*