Page MenuHomeFreeBSD

D24620.diff
No OneTemporary

D24620.diff

Index: head/usr.sbin/bhyve/Makefile
===================================================================
--- head/usr.sbin/bhyve/Makefile
+++ head/usr.sbin/bhyve/Makefile
@@ -90,6 +90,10 @@
.if ${MK_INET6_SUPPORT} != "no"
CFLAGS+=-DINET6
.endif
+.if ${MK_NETGRAPH_SUPPORT} != "no"
+CFLAGS+=-DNETGRAPH
+LIBADD+= netgraph
+.endif
.if ${MK_OPENSSL} == "no"
CFLAGS+=-DNO_OPENSSL
.else
Index: head/usr.sbin/bhyve/net_backends.c
===================================================================
--- head/usr.sbin/bhyve/net_backends.c
+++ head/usr.sbin/bhyve/net_backends.c
@@ -69,6 +69,11 @@
#include <poll.h>
#include <assert.h>
+#ifdef NETGRAPH
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <netgraph.h>
+#endif
#include "debug.h"
#include "iov.h"
@@ -382,6 +387,194 @@
DATA_SET(net_backend_set, tap_backend);
DATA_SET(net_backend_set, vmnet_backend);
+
+#ifdef NETGRAPH
+
+/*
+ * Netgraph backend
+ */
+
+#define NG_SBUF_MAX_SIZE (4 * 1024 * 1024)
+
+static int
+ng_init(struct net_backend *be, const char *devname,
+ const char *opts, net_be_rxeof_t cb, void *param)
+{
+ struct tap_priv *p = (struct tap_priv *)be->opaque;
+ struct ngm_connect ngc;
+ char *ngopts, *tofree;
+ char nodename[NG_NODESIZ];
+ int sbsz;
+ int ctrl_sock;
+ int flags;
+ int path_provided;
+ int peerhook_provided;
+ int socket_provided;
+ unsigned long maxsbsz;
+ size_t msbsz;
+#ifndef WITHOUT_CAPSICUM
+ cap_rights_t rights;
+#endif
+
+ if (cb == NULL) {
+ WPRINTF(("Netgraph backend requires non-NULL callback"));
+ return (-1);
+ }
+
+ be->fd = -1;
+
+ memset(&ngc, 0, sizeof(ngc));
+
+ strncpy(ngc.ourhook, "vmlink", NG_HOOKSIZ - 1);
+
+ tofree = ngopts = strdup(opts);
+
+ if (ngopts == NULL) {
+ WPRINTF(("strdup error"));
+ return (-1);
+ }
+
+ socket_provided = 0;
+ path_provided = 0;
+ peerhook_provided = 0;
+
+ (void)strsep(&ngopts, ",");
+
+ while (ngopts != NULL) {
+ char *value = ngopts;
+ char *key;
+
+ key = strsep(&value, "=");
+ if (value == NULL)
+ break;
+ ngopts = value;
+ (void) strsep(&ngopts, ",");
+
+ if (strcmp(key, "socket") == 0) {
+ strncpy(nodename, value, NG_NODESIZ - 1);
+ socket_provided = 1;
+ } else if (strcmp(key, "path") == 0) {
+ strncpy(ngc.path, value, NG_PATHSIZ - 1);
+ path_provided = 1;
+ } else if (strcmp(key, "hook") == 0) {
+ strncpy(ngc.ourhook, value, NG_HOOKSIZ - 1);
+ } else if (strcmp(key, "peerhook") == 0) {
+ strncpy(ngc.peerhook, value, NG_HOOKSIZ - 1);
+ peerhook_provided = 1;
+ }
+ }
+
+ free(tofree);
+
+ if (!path_provided) {
+ WPRINTF(("path must be provided"));
+ return (-1);
+ }
+
+ if (!peerhook_provided) {
+ WPRINTF(("peer hook must be provided"));
+ return (-1);
+ }
+
+ if (NgMkSockNode(socket_provided ? nodename : NULL,
+ &ctrl_sock, &be->fd) < 0) {
+ WPRINTF(("can't get Netgraph sockets"));
+ return (-1);
+ }
+
+ if (NgSendMsg(ctrl_sock, ".",
+ NGM_GENERIC_COOKIE,
+ NGM_CONNECT, &ngc, sizeof(ngc)) < 0) {
+ WPRINTF(("can't connect to node"));
+ close(ctrl_sock);
+ goto error;
+ }
+
+ close(ctrl_sock);
+
+ flags = fcntl(be->fd, F_GETFL);
+
+ if (flags < 0) {
+ WPRINTF(("can't get socket flags"));
+ goto error;
+ }
+
+ if (fcntl(be->fd, F_SETFL, flags | O_NONBLOCK) < 0) {
+ WPRINTF(("can't set O_NONBLOCK flag"));
+ goto error;
+ }
+
+ /*
+ * The default ng_socket(4) buffer's size is too low.
+ * Calculate the minimum value between NG_SBUF_MAX_SIZE
+ * and kern.ipc.maxsockbuf.
+ */
+ msbsz = sizeof(maxsbsz);
+ if (sysctlbyname("kern.ipc.maxsockbuf", &maxsbsz, &msbsz,
+ NULL, 0) < 0) {
+ WPRINTF(("can't get 'kern.ipc.maxsockbuf' value"));
+ goto error;
+ }
+
+ /*
+ * We can't set the socket buffer size to kern.ipc.maxsockbuf value,
+ * as it takes into account the mbuf(9) overhead.
+ */
+ maxsbsz = maxsbsz * MCLBYTES / (MSIZE + MCLBYTES);
+
+ sbsz = MIN(NG_SBUF_MAX_SIZE, maxsbsz);
+
+ if (setsockopt(be->fd, SOL_SOCKET, SO_SNDBUF, &sbsz,
+ sizeof(sbsz)) < 0) {
+ WPRINTF(("can't set TX buffer size"));
+ goto error;
+ }
+
+ if (setsockopt(be->fd, SOL_SOCKET, SO_RCVBUF, &sbsz,
+ sizeof(sbsz)) < 0) {
+ WPRINTF(("can't set RX buffer size"));
+ goto error;
+ }
+
+#ifndef WITHOUT_CAPSICUM
+ cap_rights_init(&rights, CAP_EVENT, CAP_READ, CAP_WRITE);
+ if (caph_rights_limit(be->fd, &rights) == -1)
+ errx(EX_OSERR, "Unable to apply rights for sandbox");
+#endif
+
+ memset(p->bbuf, 0, sizeof(p->bbuf));
+ p->bbuflen = 0;
+
+ p->mevp = mevent_add_disabled(be->fd, EVF_READ, cb, param);
+ if (p->mevp == NULL) {
+ WPRINTF(("Could not register event"));
+ goto error;
+ }
+
+ return (0);
+
+error:
+ tap_cleanup(be);
+ return (-1);
+}
+
+static struct net_backend ng_backend = {
+ .prefix = "netgraph",
+ .priv_size = sizeof(struct tap_priv),
+ .init = ng_init,
+ .cleanup = tap_cleanup,
+ .send = tap_send,
+ .peek_recvlen = tap_peek_recvlen,
+ .recv = tap_recv,
+ .recv_enable = tap_recv_enable,
+ .recv_disable = tap_recv_disable,
+ .get_cap = tap_get_cap,
+ .set_cap = tap_set_cap,
+};
+
+DATA_SET(net_backend_set, ng_backend);
+
+#endif /* NETGRAPH */
/*
* The netmap backend

File Metadata

Mime Type
text/plain
Expires
Tue, Nov 26, 11:58 AM (4 h, 24 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
14861030
Default Alt Text
D24620.diff (4 KB)

Event Timeline