When using QEMU with the KVM accelerator, MMIO writes to the queue
doorbell register are likely to hit an ioeventfd region. KVM will
signal readiness on the ioeventfd file descriptor (which will
eventually wake up the QEMU userspace process to handle the MMIO
write) and then immediately resume execution of the iPXE guest.
This can result in high latencies in processing submitted descriptors.
With the small transmit queue fill level used by iPXE, this can easily
overrun the transmit queue and result in large numbers of dropped
transmissions.
Increase the transmit queue fill level to utilise the whole queue if
needed, and use the transmission deferral mechanism to avoid dropping
packets when high latencies occur during operation.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
static int virtio_net_transmit ( struct net_device *netdev,
struct io_buffer *iobuf ) {
struct virtio_net *vnet = netdev->priv;
- struct virtio_device *virtio = &vnet->virtio;
struct virtio_net_queue *queue = &vnet->tx;
- /* Check for an available transmit descriptor */
+ /* Defer packet if there are no available transmit descriptors */
if ( ( queue->queue.prod - queue->queue.cons ) >= queue->fill ) {
- DBGC ( vnet, "VNET %s out of transmit descriptors\n",
- virtio->name );
- return -ENOBUFS;
+ netdev_tx_defer ( netdev, iobuf );
+ return 0;
}
/* Submit I/O buffer */
#define VIRTIO_NET_TX_COUNT 128
/** Transmit queue maximum fill level */
-#define VIRTIO_NET_TX_MAX 32
+#define VIRTIO_NET_TX_MAX 128
/** Number of descriptors per packet */
#define VIRTIO_NET_DESCS 2