Skip to content

Commit

Permalink
bhyve: Use a non-blocking read in slirp_recv()
Browse files Browse the repository at this point in the history
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
  • Loading branch information
markjdb committed Jan 7, 2025
1 parent 596ee23 commit d3bdfa5
Showing 1 changed file with 13 additions and 2 deletions.
15 changes: 13 additions & 2 deletions usr.sbin/bhyve/net_backend_slirp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down

0 comments on commit d3bdfa5

Please sign in to comment.