Here's my understanding of Virtio:

The VM chooses what size of buffers to give us. The default behavior on Linux is unhelpfully pairs of 12-byte (for metadata) and 1514-byte (for payload) buffers, independent of the configure MTU of the device. However, if we advertise the "we can merge buffers" (i.e. iovec-style) feature then we will always be given 4KB buffers and we can create packets using N buffers and we can choose the size of each buffer (but not the starting address, that's fixed).

I suspect we could also have the VM give us ~64KB buffers by advertising different flag. This could lead to a simple design with one buffer per packet, but currently my feeling is that header-splitting is worth the trouble if it saves us a lot of packet copies (and even from loading payload into the CPU's cache at all if nobody ever looks at it).