git: f34a651bc988 - stable/14 - bhyve: Use a non-blocking read in slirp_recv()
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 07 Feb 2025 14:47:00 UTC
The branch stable/14 has been updated by markj: URL: https://cgit.FreeBSD.org/src/commit/?id=f34a651bc98881ab352132496e82acb960c321a3 commit f34a651bc98881ab352132496e82acb960c321a3 Author: Mark Johnston <markj@FreeBSD.org> AuthorDate: 2025-01-07 14:33:06 +0000 Commit: Mark Johnston <markj@FreeBSD.org> CommitDate: 2025-02-07 14:46:53 +0000 bhyve: Use a non-blocking read in slirp_recv() When using the slirp backend with the e1000 frontend, I otherwise get hangs in readv(), caused by the e1000 emulation not checking whether bytes are available before trying to read them. In particular, that device model expects the recv callback to return 0 if no bytes are available, and with slirp it would end up blocking forever. The virtio device model uses the peek_recvlen to check first, so I didn't notice the problem when implementing the slirp backend. Make the slirp backend more flexible to accommodate e1000. MFC after: 1 month Differential Revision: https://reviews.freebsd.org/D48164 (cherry picked from commit d3bdfa583044dbfb76ef777939b86bb68baebee7) --- usr.sbin/bhyve/net_backend_slirp.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/usr.sbin/bhyve/net_backend_slirp.c b/usr.sbin/bhyve/net_backend_slirp.c index 1d6ed45b90f2..45139214afd6 100644 --- a/usr.sbin/bhyve/net_backend_slirp.c +++ b/usr.sbin/bhyve/net_backend_slirp.c @@ -609,11 +609,22 @@ static ssize_t slirp_recv(struct net_backend *be, const struct iovec *iov, int iovcnt) { struct slirp_priv *priv = NET_BE_PRIV(be); + struct msghdr hdr; ssize_t n; - n = readv(priv->pipe[0], iov, iovcnt); - if (n < 0) + hdr.msg_name = NULL; + hdr.msg_namelen = 0; + hdr.msg_iov = __DECONST(struct iovec *, iov); + hdr.msg_iovlen = iovcnt; + hdr.msg_control = NULL; + hdr.msg_controllen = 0; + hdr.msg_flags = 0; + n = recvmsg(priv->pipe[0], &hdr, MSG_DONTWAIT); + if (n < 0) { + if (errno == EWOULDBLOCK) + return (0); return (-1); + } assert(n <= SLIRP_MTU); return (n); }