Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F142725545
D54654.id.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
16 KB
Referenced Files
None
Subscribers
None
D54654.id.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D54654: bhyve/net_backends: Source file descriptors from nvlists
Attached
Detach File
Event Timeline
Log In to Comment