On Thu, Nov 28, 2024 at 01:57:34PM +0100, Laurent Vivier wrote:On 26/11/2024 06:24, David Gibson wrote:Huh, right. I guess that means you can't quite put a maximum size IP frame on ethernet, because you'll run out of Ethernet MTU before you run out of IP MTU. I think we should work based on the IP limits, not the L2 limit: our operation means we're inherently connected to IP. *Currently* we always use Ethernet headers as well, but that could reasonably change ("tun" mode support, or other possible L2s). So, that would give us: IP_MAX_MTU + ETH_HLEN + sizeof(virtio_net_hdr_mrg_rxbuf) -- David Gibson (he or they) | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you, not the other way | around. http://www.ozlabs.org/~dgibsonI think it would be semantically more correct to use "ETH_MAX_MTU + sizeof(struct virtio_net_hdr_mrg_rxbuf)", but as ETH_MAX_MTU and IP_MAX_MTU are both defined to USHRT_MAX I'm not sure how to compute the segment size...static int udp_vu_sock_recv(const struct ctx *c, int s, uint32_t events, + bool v6, ssize_t *dlen) +{ + struct vu_dev *vdev = c->vdev; + struct vu_virtq *vq = &vdev->vq[VHOST_USER_RX_QUEUE]; + int iov_cnt, idx, iov_used; + struct msghdr msg = { 0 }; + size_t off, hdrlen; + + ASSERT(!c->no_udp); + + if (!(events & EPOLLIN)) + return 0; + + /* compute L2 header length */ + hdrlen = udp_vu_hdrlen(v6); + + vu_init_elem(elem, iov_vu, VIRTQUEUE_MAX_SIZE); + + iov_cnt = vu_collect(vdev, vq, elem, VIRTQUEUE_MAX_SIZE, + IP_MAX_MTU - sizeof(struct udphdr) + hdrlen,I don't think this calculation is quite right, though it's probably safe. At least for IPv4, IP_MAX_MTU includes the IP header itself, but then you count that again in hdrlen.