Page MenuHomeFreeBSD

D54654.id.diff
No OneTemporary

D54654.id.diff

diff --git a/lib/libbhyve/Makefile b/lib/libbhyve/Makefile
--- a/lib/libbhyve/Makefile
+++ b/lib/libbhyve/Makefile
@@ -3,6 +3,7 @@
PACKAGE=lib${LIB}
LIB= bhyve
SRCS= config.c \
+ net_backends.c \
pci.c
INCS= bhyve/config.h \
bhyve/net_backends.h \
diff --git a/lib/libbhyve/net_backends.c b/lib/libbhyve/net_backends.c
new file mode 100644
--- /dev/null
+++ b/lib/libbhyve/net_backends.c
@@ -0,0 +1,307 @@
+/*
+ *
+ * Copyright (c) 2019 Vincenzo Maffione <vmaffione@FreeBSD.org>
+ * Copyright (c) 2023 Mark Johnston <markj@FreeBSD.org>
+ * Copyright (c) 2025 Bojan Novković <bnovkov@FreeBSD.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <sys/nv.h>
+#include <sys/nv_namespace.h>
+#include <sys/socket.h>
+
+#include <net/if.h>
+#include <net/netmap.h>
+#include <net/netmap_virt.h>
+#define NETMAP_WITH_LIBS
+#include <net/netmap_user.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <netgraph.h>
+#include <stdbool.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "bhyve/config.h"
+#include "bhyve/net_backends.h"
+#include "bhyve/pci.h"
+#include "internal.h"
+
+struct netbe_info {
+ const char *prefix;
+ int (*init_fds)(nvlist_t *);
+ bool (*validate_hotplug_request)(nvlist_t *);
+};
+
+static int
+slirp_init_fds(nvlist_t *nvl)
+{
+ int error;
+ int sockpair_fds[2];
+
+ error = socketpair(PF_LOCAL, SOCK_SEQPACKET | SOCK_NONBLOCK, 0,
+ sockpair_fds);
+ if (error != 0) {
+ nvlist_add_stringf(nvl, "error", "Unable to create pipe: %s",
+ strerror(errno));
+ return (error);
+ }
+
+ nvlist_move_descriptor_array(nvl, "sockpair", sockpair_fds,
+ sizeof(sockpair_fds));
+
+ return (0);
+}
+
+static bool
+slirp_validate_hotplug_request(nvlist_t *nvl)
+{
+ if (!nvlist_exists_descriptor_array(nvl, "sockpair")) {
+ nvlist_add_string(nvl, "error",
+ "missing socket descriptor pair");
+ return (false);
+ }
+ if (!nvlist_exists_descriptor_array(nvl, "pipe")) {
+ nvlist_add_string(nvl, "error", "missing pipe descriptor pair");
+ return (false);
+ }
+
+ return (true);
+}
+
+static int
+tap_init_fds(nvlist_t *nvl)
+{
+ int fd;
+ char tbuf[80];
+ const char *devname;
+
+ if (!nvlist_exists_string(nvl, "backend")) {
+ nvlist_add_string(nvl, "error", "missing backend parameter");
+ return (-1);
+ }
+
+ devname = nvlist_get_string(nvl, "backend");
+ strcpy(tbuf, "/dev/");
+ strlcat(tbuf, devname, sizeof(tbuf));
+ fd = open(tbuf, O_RDWR);
+ if (fd == -1) {
+ nvlist_add_stringf(nvl, "error",
+ "open of tap device %s failed: %s", tbuf, strerror(errno));
+ return (-1);
+ }
+ nvlist_move_descriptor(nvl, "devfd", fd);
+
+ return (0);
+}
+
+static bool
+tap_validate_hotplug_request(nvlist_t *nvl)
+{
+ if (!nvlist_exists_descriptor(nvl, "devfd")) {
+ nvlist_add_string(nvl, "error",
+ "missing tap device file descriptor");
+ return (false);
+ }
+ return (true);
+}
+
+static int
+ng_init_fds(nvlist_t *nvl)
+{
+ int csp, dsp;
+ const char *nodename;
+
+ if (!nvlist_exists_string(nvl, "socket")) {
+ nvlist_add_string(nvl, "error", "missing socket path");
+ return (-1);
+ }
+ nodename = nvlist_get_string(nvl, "socket");
+ if (NgMkSockNode(nodename, &csp, &dsp) < 0) {
+ nvlist_add_stringf(nvl, "error", "can't get Netgraph sockets");
+ return (-1);
+ }
+
+ nvlist_move_descriptor(nvl, "csp", csp);
+ nvlist_move_descriptor(nvl, "dsp", dsp);
+
+ return (0);
+}
+
+static bool
+ng_validate_hotplug_request(nvlist_t *nvl)
+{
+ if (!nvlist_exists_descriptor(nvl, "csp")) {
+ nvlist_add_string(nvl, "error",
+ "missing control socket descriptor");
+ return (false);
+ }
+ if (!nvlist_exists_descriptor(nvl, "dsp")) {
+ nvlist_add_string(nvl, "error",
+ "missing data socket descriptor");
+ return (false);
+ }
+
+ return (true);
+}
+
+static int
+netmap_init_fds(nvlist_t *nvl)
+{
+ struct nm_desc *nmd;
+ const char *devname;
+
+ if (!nvlist_exists_string(nvl, "backend")) {
+ nvlist_add_string(nvl, "error", "missing backend parameter");
+ return (-1);
+ }
+ devname = nvlist_get_string(nvl, "backend");
+ nmd = nm_open(devname, NULL, NETMAP_NO_TX_POLL, NULL);
+ if (nmd == NULL) {
+ nvlist_add_stringf(nvl, "error",
+ "Unable to nm_open(): interface '%s', errno (%s)", devname,
+ strerror(errno));
+ return (-1);
+ }
+ nvlist_move_binary(nvl, "nm_desc", nmd, sizeof(*nmd));
+
+ return (0);
+}
+
+static bool
+netmap_validate_hotplug_request(nvlist_t *nvl)
+{
+ size_t size;
+ struct nm_desc *nmd;
+
+ if (!nvlist_exists_binary(nvl, "nm_desc")) {
+ nvlist_add_string(nvl, "error",
+ "missing netmap descriptor structure");
+ return (false);
+ }
+
+ (void)nvlist_get_binary(nvl, "nm_desc", &size);
+ if (size != sizeof(*nmd)) {
+ nvlist_add_string(nvl, "error",
+ "mismatched netmap descriptor structure size");
+ return (false);
+ }
+
+ return (true);
+}
+
+static struct netbe_info netbe_tap = {
+ .prefix = "tap",
+ .init_fds = tap_init_fds,
+ .validate_hotplug_request = tap_validate_hotplug_request
+};
+
+static struct netbe_info netbe_ngd = {
+ .prefix = "ngd",
+ .init_fds = tap_init_fds,
+ .validate_hotplug_request = tap_validate_hotplug_request
+};
+
+static struct netbe_info netbe_netmap = {
+ .prefix = "netmap",
+ .init_fds = netmap_init_fds,
+ .validate_hotplug_request = netmap_validate_hotplug_request
+};
+
+static struct netbe_info netbe_netgraph = {
+ .prefix = "netgraph",
+ .init_fds = ng_init_fds,
+ .validate_hotplug_request = ng_validate_hotplug_request
+};
+
+static struct netbe_info netbe_slirp = {
+ .prefix = "slirp",
+ .init_fds = slirp_init_fds,
+ .validate_hotplug_request = slirp_validate_hotplug_request
+};
+
+SET_DECLARE(net_backends_info, struct netbe_info);
+DATA_SET(net_backends_info, netbe_netgraph);
+DATA_SET(net_backends_info, netbe_slirp);
+DATA_SET(net_backends_info, netbe_netmap);
+DATA_SET(net_backends_info, netbe_tap);
+DATA_SET(net_backends_info, netbe_ngd);
+
+static struct netbe_info *
+find_netbe_info(const char *backend)
+{
+ struct netbe_info **nbe;
+
+ SET_FOREACH(nbe, net_backends_info) {
+ if (strncmp(backend, (*nbe)->prefix,
+ strlen((*nbe)->prefix)) == 0) {
+ return (*nbe);
+ }
+ }
+ return (NULL);
+}
+
+int
+netbe_init_fds(nvlist_t *nvl)
+{
+ const char *backend;
+ struct netbe_info *nbi;
+
+ if (!nvlist_exists_string(nvl, "backend")) {
+ nvlist_add_string(nvl, "error", "missing backend argument");
+ return (-1);
+ }
+ backend = nvlist_get_string(nvl, "backend");
+ nbi = find_netbe_info(backend);
+ if (nbi == NULL) {
+ nvlist_add_stringf(nvl, "error", "unknown backend '%s'",
+ backend);
+ return (-1);
+ }
+
+ if (nbi->init_fds == NULL)
+ return (0);
+
+ return (nbi->init_fds(nvl));
+}
+
+int
+netbe_legacy_config(nvlist_t *nvl, const char *opts)
+{
+ char *backend, *cp;
+
+ if (opts == NULL)
+ return (0);
+
+ cp = strchr(opts, ',');
+ if (cp == NULL) {
+ set_config_value_node(nvl, "backend", opts);
+ return (0);
+ }
+ backend = strndup(opts, cp - opts);
+ set_config_value_node(nvl, "backend", backend);
+ free(backend);
+ return (pci_parse_legacy_config(nvl, cp + 1));
+}
+
+bool
+netbe_validate_hotplug_request(nvlist_t *nvl)
+{
+ const char *backend;
+ struct netbe_info *nbi;
+
+ if (!nvlist_exists_string(nvl, "backend")) {
+ nvlist_add_string(nvl, "error", "missing backend argument");
+ return (-1);
+ }
+ backend = nvlist_get_string(nvl, "backend");
+ nbi = find_netbe_info(backend);
+
+ if (nbi == NULL || nbi->validate_hotplug_request == NULL)
+ return (0);
+
+ return (nbi->validate_hotplug_request(nvl));
+}
diff --git a/usr.sbin/bhyve/net_backend_netgraph.c b/usr.sbin/bhyve/net_backend_netgraph.c
--- a/usr.sbin/bhyve/net_backend_netgraph.c
+++ b/usr.sbin/bhyve/net_backend_netgraph.c
@@ -53,7 +53,7 @@
{
struct tap_priv *p = NET_BE_PRIV(be);
struct ngm_connect ngc;
- const char *value, *nodename;
+ const char *value;
int sbsz;
int ctrl_sock;
int flags;
@@ -74,7 +74,7 @@
value = get_config_value_node(nvl, "path");
if (value == NULL) {
- EPRINTLN("path must be provided");
+ nvlist_add_string(nvl, "error", "path must be provided");
return (-1);
}
strncpy(ngc.path, value, NG_PATHSIZ - 1);
@@ -86,22 +86,18 @@
value = get_config_value_node(nvl, "peerhook");
if (value == NULL) {
- EPRINTLN("peer hook must be provided");
+ nvlist_add_string(nvl, "error", "peer hook must be provided");
return (-1);
}
strncpy(ngc.peerhook, value, NG_HOOKSIZ - 1);
- nodename = get_config_value_node(nvl, "socket");
- if (NgMkSockNode(nodename,
- &ctrl_sock, &be->fd) < 0) {
- EPRINTLN("can't get Netgraph sockets");
- return (-1);
- }
+ ctrl_sock = nvlist_take_descriptor(nvl, "csp");
+ be->fd = nvlist_take_descriptor(nvl, "dsp");
if (NgSendMsg(ctrl_sock, ".",
NGM_GENERIC_COOKIE,
NGM_CONNECT, &ngc, sizeof(ngc)) < 0) {
- EPRINTLN("can't connect to node");
+ nvlist_add_string(nvl, "error", "can't connect to node");
close(ctrl_sock);
goto error;
}
@@ -111,12 +107,12 @@
flags = fcntl(be->fd, F_GETFL);
if (flags < 0) {
- EPRINTLN("can't get socket flags");
+ nvlist_add_string(nvl, "error", "can't get socket flags");
goto error;
}
if (fcntl(be->fd, F_SETFL, flags | O_NONBLOCK) < 0) {
- EPRINTLN("can't set O_NONBLOCK flag");
+ nvlist_add_string(nvl, "error", "can't set O_NONBLOCK flag");
goto error;
}
@@ -128,7 +124,8 @@
msbsz = sizeof(maxsbsz);
if (sysctlbyname("kern.ipc.maxsockbuf", &maxsbsz, &msbsz,
NULL, 0) < 0) {
- EPRINTLN("can't get 'kern.ipc.maxsockbuf' value");
+ nvlist_add_string(nvl, "error",
+ "can't get 'kern.ipc.maxsockbuf' value");
goto error;
}
@@ -142,13 +139,13 @@
if (setsockopt(be->fd, SOL_SOCKET, SO_SNDBUF, &sbsz,
sizeof(sbsz)) < 0) {
- EPRINTLN("can't set TX buffer size");
+ nvlist_add_string(nvl, "error", "can't set TX buffer size");
goto error;
}
if (setsockopt(be->fd, SOL_SOCKET, SO_RCVBUF, &sbsz,
sizeof(sbsz)) < 0) {
- EPRINTLN("can't set RX buffer size");
+ nvlist_add_string(nvl, "error", "can't set RX buffer size");
goto error;
}
@@ -163,7 +160,7 @@
p->mevp = mevent_add_disabled(be->fd, EVF_READ, cb, param);
if (p->mevp == NULL) {
- EPRINTLN("Could not register event");
+ nvlist_add_string(nvl, "error", "Could not register event");
goto error;
}
diff --git a/usr.sbin/bhyve/net_backend_netmap.c b/usr.sbin/bhyve/net_backend_netmap.c
--- a/usr.sbin/bhyve/net_backend_netmap.c
+++ b/usr.sbin/bhyve/net_backend_netmap.c
@@ -123,21 +123,15 @@
}
static int
-netmap_init(struct net_backend *be, const char *devname,
- nvlist_t *nvl __unused, net_be_rxeof_t cb, void *param)
+netmap_init(struct net_backend *be, const char *devname, nvlist_t *nvl,
+ net_be_rxeof_t cb, void *param)
{
struct netmap_priv *priv = NET_BE_PRIV(be);
+ size_t size;
strlcpy(priv->ifname, devname, sizeof(priv->ifname));
priv->ifname[sizeof(priv->ifname) - 1] = '\0';
-
- priv->nmd = nm_open(priv->ifname, NULL, NETMAP_NO_TX_POLL, NULL);
- if (priv->nmd == NULL) {
- EPRINTLN("Unable to nm_open(): interface '%s', errno (%s)",
- devname, strerror(errno));
- return (-1);
- }
-
+ priv->nmd = nvlist_take_binary(nvl, "nm_desc", &size);
priv->memid = priv->nmd->req.nr_arg2;
priv->tx = NETMAP_TXRING(priv->nmd->nifp, 0);
priv->rx = NETMAP_RXRING(priv->nmd->nifp, 0);
@@ -147,7 +141,7 @@
priv->mevp = mevent_add_disabled(be->fd, EVF_READ, cb, param);
if (priv->mevp == NULL) {
- EPRINTLN("Could not register event");
+ nvlist_add_string(nvl, "error", "Could not register event");
return (-1);
}
diff --git a/usr.sbin/bhyve/net_backend_slirp.c b/usr.sbin/bhyve/net_backend_slirp.c
--- a/usr.sbin/bhyve/net_backend_slirp.c
+++ b/usr.sbin/bhyve/net_backend_slirp.c
@@ -88,12 +88,14 @@
pid_t child;
const char **argv;
char sockname[32];
- int error, s[2];
+ int error, *s;
+ size_t mtu, nitems;
const char *mtu_value;
- size_t mtu;
- if (socketpair(PF_LOCAL, SOCK_SEQPACKET | SOCK_NONBLOCK, 0, s) != 0) {
- EPRINTLN("socketpair");
+ s = nvlist_take_descriptor_array(nvl, "sockpair", &nitems);
+ if (nitems != 2) {
+ nvlist_add_string(nvl, "error",
+ "mismatched number of socket descriptors");
return (-1);
}
@@ -102,11 +104,13 @@
* one end is inherited by the child.
*/
if (posix_spawn_file_actions_init(&fa) != 0) {
- EPRINTLN("posix_spawn_file_actions_init");
+ nvlist_add_string(nvl, "error",
+ "posix_spawn_file_actions_init");
goto err;
}
if (posix_spawn_file_actions_addclose(&fa, s[0]) != 0) {
- EPRINTLN("posix_spawn_file_actions_addclose");
+ nvlist_add_string(nvl, "error",
+ "posix_spawn_file_actions_addclose");
posix_spawn_file_actions_destroy(&fa);
goto err;
}
@@ -119,22 +123,23 @@
&fa, NULL, __DECONST(char **, argv), environ);
posix_spawn_file_actions_destroy(&fa);
if (error != 0) {
- EPRINTLN("posix_spawn(bhyve-slirp-helper): %s",
+ nvlist_add_stringf(nvl, "error", "posix_spawn(bhyve-slirp-helper): %s",
strerror(error));
goto err;
}
config = nvlist_clone(nvl);
if (config == NULL) {
- EPRINTLN("nvlist_clone");
+ nvlist_add_string(nvl, "error",
+ "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;
+ nvlist_add_string(nvl, "error", "Could not parse MTU");
+ goto err;
}
} else {
mtu = DEFAULT_MTU;
@@ -144,7 +149,7 @@
priv->mtu = mtu;
priv->buf = malloc(mtu);
if (priv->buf == NULL) {
- EPRINTLN("Could not allocate buffer");
+ nvlist_add_string(nvl, "error", "Could not allocate MTU buffer");
goto err;
}
@@ -152,14 +157,15 @@
error = nvlist_send(s[0], config);
nvlist_destroy(config);
if (error != 0) {
- EPRINTLN("nvlist_send");
+ nvlist_add_string(nvl, "error",
+ "nvlist_send");
goto err;
}
be->fd = s[0];
priv->mevp = mevent_add_disabled(be->fd, EVF_READ, cb, param);
if (priv->mevp == NULL) {
- EPRINTLN("Could not register event");
+ nvlist_add_string(nvl, "error", "Could not register event");
goto err;
}
diff --git a/usr.sbin/bhyve/net_backends.c b/usr.sbin/bhyve/net_backends.c
--- a/usr.sbin/bhyve/net_backends.c
+++ b/usr.sbin/bhyve/net_backends.c
@@ -85,11 +85,10 @@
}
static int
-tap_init(struct net_backend *be, const char *devname,
- nvlist_t *nvl __unused, net_be_rxeof_t cb, void *param)
+tap_init(struct net_backend *be, const char *devname __unused, nvlist_t *nvl,
+ net_be_rxeof_t cb, void *param)
{
struct tap_priv *priv = NET_BE_PRIV(be);
- char tbuf[80];
int opt = 1, up = IFF_UP;
#ifndef WITHOUT_CAPSICUM
@@ -97,31 +96,25 @@
#endif
if (cb == NULL) {
- EPRINTLN("TAP backend requires non-NULL callback");
+ nvlist_add_string(nvl, "error",
+ "TAP backend requires non-NULL callback");
return (-1);
}
- strcpy(tbuf, "/dev/");
- strlcat(tbuf, devname, sizeof(tbuf));
-
- be->fd = open(tbuf, O_RDWR);
- if (be->fd == -1) {
- EPRINTLN("open of tap device %s failed", tbuf);
- goto error;
- }
+ be->fd = nvlist_take_descriptor(nvl, "devfd");
/*
* Set non-blocking and register for read
* notifications with the event loop
*/
if (ioctl(be->fd, FIONBIO, &opt) < 0) {
- EPRINTLN("tap device O_NONBLOCK failed");
+ nvlist_add_string(nvl, "error", "tap device O_NONBLOCK failed");
goto error;
}
if (strncmp("ngd", be->prefix, 3) &&
ioctl(be->fd, VMIO_SIOCSIFFLAGS, up)) {
- EPRINTLN("tap device link up failed");
+ nvlist_add_string(nvl, "error", "tap device link up failed");
goto error;
}
@@ -136,7 +129,7 @@
priv->mevp = mevent_add_disabled(be->fd, EVF_READ, cb, param);
if (priv->mevp == NULL) {
- EPRINTLN("Could not register event");
+ nvlist_add_string(nvl, "error", "Could not register event");
goto error;
}
@@ -293,25 +286,6 @@
DATA_SET(net_backend_set, vmnet_backend);
DATA_SET(net_backend_set, ngd_backend);
-int
-netbe_legacy_config(nvlist_t *nvl, const char *opts)
-{
- char *backend, *cp;
-
- if (opts == NULL)
- return (0);
-
- cp = strchr(opts, ',');
- if (cp == NULL) {
- set_config_value_node(nvl, "backend", opts);
- return (0);
- }
- backend = strndup(opts, cp - opts);
- set_config_value_node(nvl, "backend", backend);
- free(backend);
- return (pci_parse_legacy_config(nvl, cp + 1));
-}
-
/*
* Initialize a backend and attach to the frontend.
* This is called during frontend initialization.
@@ -335,6 +309,7 @@
value = get_config_value_node(nvl, "backend");
if (value == NULL) {
+ nvlist_add_string(nvl, "error", "missing backend argument");
return (-1);
}
devname = strdup(value);
@@ -367,6 +342,7 @@
*ret = NULL;
if (tbe == NULL) {
+ nvlist_add_stringf(nvl, "error", "unknown backend '%s'", type);
free(devname);
return (EINVAL);
}

File Metadata

Mime Type
text/plain
Expires
Fri, Jan 23, 5:52 PM (7 h, 40 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
27888261
Default Alt Text
D54654.id.diff (16 KB)

Event Timeline