bhyve: support MTU configuration for SLIRP net backend

Support configuring MTU for the SLIRP net backend, for example:

  -s 1:0,virtio-net,slirp,mtu=2048,open

Update the manual page accordingly.  While here, also document
MAC address configuration.

Reviewed by:	markj
Approved by:	markj
Sponsored by:	The FreeBSD Foundation
MFC after:	1 month
Differential Revision:	https://reviews.freebsd.org/D54133
This commit is contained in:
Roman Bogorodskiy
2025-12-08 18:37:09 +01:00
parent bf98d6775d
commit 90b9a77ebe
3 changed files with 47 additions and 14 deletions
+3 -1
View File
@@ -25,7 +25,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.Dd December 26, 2025
.Dd January 5, 2026
.Dt BHYVE 8
.Os
.Sh NAME
@@ -542,6 +542,8 @@ considered unconnected.
.Cm slirp
.Op Cm \&,open
.Op Cm \&,hostfwd= Ar proto : Ar hostaddr : Ar hostport - Ar guestaddr : Ar guestport
.Op Cm \&,mac= Ar xx:xx:xx:xx:xx:xx
.Op Cm \&,mtu= Ar N
.Xc
.El
.Sm on
+30 -5
View File
@@ -62,15 +62,18 @@
#include "config.h"
#include "debug.h"
#include "mevent.h"
#include "net_utils.h"
#include "net_backends.h"
#include "net_backends_priv.h"
#define SLIRP_MTU 2048
#define DEFAULT_MTU 2048
struct slirp_priv {
int s;
pid_t helper;
struct mevent *mevp;
size_t mtu;
uint8_t *buf;
};
extern char **environ;
@@ -86,6 +89,8 @@ slirp_init(struct net_backend *be, const char *devname __unused,
const char **argv;
char sockname[32];
int error, s[2];
const char *mtu_value;
size_t mtu;
if (socketpair(PF_LOCAL, SOCK_SEQPACKET | SOCK_NONBLOCK, 0, s) != 0) {
EPRINTLN("socketpair");
@@ -124,6 +129,25 @@ slirp_init(struct net_backend *be, const char *devname __unused,
EPRINTLN("nvlist_clone");
goto err;
}
mtu_value = get_config_value_node(config, "mtu");
if (mtu_value != NULL) {
if (net_parsemtu(mtu_value, &mtu)) {
EPRINTLN("Could not parse MTU");
goto err;
}
} else {
mtu = DEFAULT_MTU;
}
nvlist_add_number(config, "mtui", mtu);
priv->mtu = mtu;
priv->buf = malloc(mtu);
if (priv->buf == NULL) {
EPRINTLN("Could not allocate buffer");
goto err;
}
nvlist_add_string(config, "vmname", get_config_value("name"));
error = nvlist_send(s[0], config);
nvlist_destroy(config);
@@ -146,6 +170,7 @@ slirp_init(struct net_backend *be, const char *devname __unused,
return (0);
err:
free(priv->buf);
(void)close(s[0]);
(void)close(s[1]);
return (-1);
@@ -168,6 +193,8 @@ slirp_cleanup(struct net_backend *be)
{
struct slirp_priv *priv = NET_BE_PRIV(be);
free(priv->buf);
if (priv->helper > 0) {
int status;
@@ -184,17 +211,15 @@ static ssize_t
slirp_peek_recvlen(struct net_backend *be)
{
struct slirp_priv *priv = NET_BE_PRIV(be);
uint8_t buf[SLIRP_MTU];
ssize_t n;
/*
* Copying into the buffer is totally unnecessary, but we don't
* implement MSG_TRUNC for SEQPACKET sockets.
*/
n = recv(priv->s, buf, sizeof(buf), MSG_PEEK | MSG_DONTWAIT);
n = recv(priv->s, priv->buf, priv->mtu, MSG_PEEK | MSG_DONTWAIT);
if (n < 0)
return (errno == EWOULDBLOCK ? 0 : -1);
assert((size_t)n <= SLIRP_MTU);
return (n);
}
@@ -218,7 +243,7 @@ slirp_recv(struct net_backend *be, const struct iovec *iov, int iovcnt)
return (0);
return (-1);
}
assert(n <= SLIRP_MTU);
assert((size_t)n <= priv->mtu);
return (n);
}
+14 -8
View File
@@ -38,8 +38,6 @@
#include "config.h"
#include "libslirp.h"
#define SLIRP_MTU 2048
struct slirp_priv {
Slirp *slirp; /* libslirp handle */
int sock; /* data and control socket */
@@ -47,6 +45,8 @@ struct slirp_priv {
struct pollfd *pollfds;
size_t npollfds;
size_t lastpollfd;
size_t mtu;
uint8_t *buf;
};
typedef int (*slirp_add_hostxfwd_p_t)(Slirp *,
@@ -104,7 +104,7 @@ slirp_cb_send_packet(const void *buf, size_t len, void *param)
priv = param;
assert(len <= SLIRP_MTU);
assert(len <= priv->mtu);
n = send(priv->sock, buf, len, MSG_EOR);
if (n < 0) {
warn("slirp_cb_send_packet: send");
@@ -289,16 +289,14 @@ slirp_pollfd_loop(struct slirp_priv *priv)
ssize_t n;
do {
uint8_t buf[SLIRP_MTU];
n = recv(priv->sock, buf, sizeof(buf),
n = recv(priv->sock, priv->buf, priv->mtu,
MSG_DONTWAIT);
if (n < 0) {
if (errno == EWOULDBLOCK)
break;
err(1, "recv");
}
slirp_input_p(priv->slirp, buf, (int)n);
slirp_input_p(priv->slirp, priv->buf, (int)n);
} while (n >= 0);
}
}
@@ -464,6 +462,7 @@ main(int argc, char **argv)
const char *hostfwd, *vmname;
int ch, fd, sd;
bool restricted;
size_t mtu;
sd = -1;
while ((ch = getopt(argc, argv, "S:")) != -1) {
@@ -514,6 +513,13 @@ main(int argc, char **argv)
config = nvlist_recv(sd, 0);
if (config == NULL)
err(1, "nvlist_recv");
mtu = nvlist_get_number(config, "mtui");
priv.mtu = mtu;
priv.buf = malloc(mtu);
if (priv.buf == NULL)
err(1, "malloc");
vmname = get_config_value_node(config, "vmname");
if (vmname != NULL)
setproctitle("%s", vmname);
@@ -521,7 +527,7 @@ main(int argc, char **argv)
slirpconfig = (SlirpConfig){
.version = 4,
.if_mtu = SLIRP_MTU,
.if_mtu = mtu,
.restricted = restricted,
.in_enabled = true,
.vnetwork.s_addr = htonl(0x0a000200), /* 10.0.2.0/24 */