+ vec_reset_length (ptd->copy_ops);
+ vec_reset_length (ptd->buffers);
+
+ CLIB_MEMORY_STORE_BARRIER ();
+ if (type == MEMIF_RING_S2M)
+ ring->head = slot;
+ else
+ ring->tail = slot;
+
+ if (n_left && n_retries--)
+ goto retry;
+
+ clib_spinlock_unlock_if_init (&mif->lockp);
+
+ if (n_left)
+ {
+ vlib_error_count (vm, node->node_index, MEMIF_TX_ERROR_NO_FREE_SLOTS,
+ n_left);
+ }
+
+ if ((ring->flags & MEMIF_RING_FLAG_MASK_INT) == 0 && mq->int_fd > -1)
+ {
+ u64 b = 1;
+ CLIB_UNUSED (int r) = write (mq->int_fd, &b, sizeof (b));
+ mq->int_count++;
+ }
+
+ vlib_buffer_free (vm, vlib_frame_args (frame), frame->n_vectors);
+
+ return frame->n_vectors;
+}
+
+static_always_inline uword
+memif_interface_tx_zc_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
+ vlib_frame_t * frame, memif_if_t * mif,
+ memif_queue_t * mq,
+ memif_per_thread_data_t * ptd)
+{
+ memif_ring_t *ring = mq->ring;
+ u32 *buffers = vlib_frame_args (frame);
+ u32 n_left = frame->n_vectors;
+ u16 slot, free_slots, n_free;
+ u16 ring_size = 1 << mq->log2_ring_size;
+ u16 mask = ring_size - 1;
+ int n_retries = 5;
+ vlib_buffer_t *b0;
+
+retry:
+ n_free = ring->tail - mq->last_tail;
+ if (n_free >= 16)
+ {
+ vlib_buffer_free_from_ring_no_next (vm, mq->buffers,
+ mq->last_tail & mask,
+ ring_size, n_free);
+ mq->last_tail += n_free;
+ }
+
+ slot = ring->head;
+ free_slots = ring_size - ring->head + mq->last_tail;
+