Changeset View
Changeset View
Standalone View
Standalone View
usr.sbin/bhyve/net_backend_netgraph.c
| Show First 20 Lines • Show All 47 Lines • ▼ Show 20 Lines | |||||
| #define NG_SBUF_MAX_SIZE (4 * 1024 * 1024) | #define NG_SBUF_MAX_SIZE (4 * 1024 * 1024) | ||||
| static int | static int | ||||
| ng_init(struct net_backend *be, const char *devname __unused, | ng_init(struct net_backend *be, const char *devname __unused, | ||||
| nvlist_t *nvl, net_be_rxeof_t cb, void *param) | nvlist_t *nvl, net_be_rxeof_t cb, void *param) | ||||
| { | { | ||||
| struct tap_priv *p = NET_BE_PRIV(be); | struct tap_priv *p = NET_BE_PRIV(be); | ||||
| struct ngm_connect ngc; | struct ngm_connect ngc; | ||||
| const char *value, *nodename; | const char *value; | ||||
| int sbsz; | int sbsz; | ||||
| int ctrl_sock; | int ctrl_sock; | ||||
| int flags; | int flags; | ||||
| unsigned long maxsbsz; | unsigned long maxsbsz; | ||||
| size_t msbsz; | size_t msbsz; | ||||
| #ifndef WITHOUT_CAPSICUM | #ifndef WITHOUT_CAPSICUM | ||||
| cap_rights_t rights; | cap_rights_t rights; | ||||
| #endif | #endif | ||||
| if (cb == NULL) { | if (cb == NULL) { | ||||
| EPRINTLN("Netgraph backend requires non-NULL callback"); | EPRINTLN("Netgraph backend requires non-NULL callback"); | ||||
| return (-1); | return (-1); | ||||
| } | } | ||||
| be->fd = -1; | be->fd = -1; | ||||
| memset(&ngc, 0, sizeof(ngc)); | memset(&ngc, 0, sizeof(ngc)); | ||||
| value = get_config_value_node(nvl, "path"); | value = get_config_value_node(nvl, "path"); | ||||
| if (value == NULL) { | if (value == NULL) { | ||||
| EPRINTLN("path must be provided"); | nvlist_add_string(nvl, "error", "path must be provided"); | ||||
| return (-1); | return (-1); | ||||
| } | } | ||||
| strncpy(ngc.path, value, NG_PATHSIZ - 1); | strncpy(ngc.path, value, NG_PATHSIZ - 1); | ||||
| value = get_config_value_node(nvl, "hook"); | value = get_config_value_node(nvl, "hook"); | ||||
| if (value == NULL) | if (value == NULL) | ||||
| value = "vmlink"; | value = "vmlink"; | ||||
| strncpy(ngc.ourhook, value, NG_HOOKSIZ - 1); | strncpy(ngc.ourhook, value, NG_HOOKSIZ - 1); | ||||
| value = get_config_value_node(nvl, "peerhook"); | value = get_config_value_node(nvl, "peerhook"); | ||||
| if (value == NULL) { | if (value == NULL) { | ||||
| EPRINTLN("peer hook must be provided"); | nvlist_add_string(nvl, "error", "peer hook must be provided"); | ||||
| return (-1); | return (-1); | ||||
| } | } | ||||
| strncpy(ngc.peerhook, value, NG_HOOKSIZ - 1); | strncpy(ngc.peerhook, value, NG_HOOKSIZ - 1); | ||||
| nodename = get_config_value_node(nvl, "socket"); | ctrl_sock = nvlist_take_descriptor(nvl, "csp"); | ||||
| if (NgMkSockNode(nodename, | be->fd = nvlist_take_descriptor(nvl, "dsp"); | ||||
| &ctrl_sock, &be->fd) < 0) { | |||||
| EPRINTLN("can't get Netgraph sockets"); | |||||
| return (-1); | |||||
| } | |||||
| if (NgSendMsg(ctrl_sock, ".", | if (NgSendMsg(ctrl_sock, ".", | ||||
| NGM_GENERIC_COOKIE, | NGM_GENERIC_COOKIE, | ||||
| NGM_CONNECT, &ngc, sizeof(ngc)) < 0) { | 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); | close(ctrl_sock); | ||||
| goto error; | goto error; | ||||
| } | } | ||||
| close(ctrl_sock); | close(ctrl_sock); | ||||
| flags = fcntl(be->fd, F_GETFL); | flags = fcntl(be->fd, F_GETFL); | ||||
| if (flags < 0) { | if (flags < 0) { | ||||
| EPRINTLN("can't get socket flags"); | nvlist_add_string(nvl, "error", "can't get socket flags"); | ||||
| goto error; | goto error; | ||||
| } | } | ||||
| if (fcntl(be->fd, F_SETFL, flags | O_NONBLOCK) < 0) { | 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; | goto error; | ||||
| } | } | ||||
| /* | /* | ||||
| * The default ng_socket(4) buffer's size is too low. | * The default ng_socket(4) buffer's size is too low. | ||||
| * Calculate the minimum value between NG_SBUF_MAX_SIZE | * Calculate the minimum value between NG_SBUF_MAX_SIZE | ||||
| * and kern.ipc.maxsockbuf. | * and kern.ipc.maxsockbuf. | ||||
| */ | */ | ||||
| msbsz = sizeof(maxsbsz); | msbsz = sizeof(maxsbsz); | ||||
| if (sysctlbyname("kern.ipc.maxsockbuf", &maxsbsz, &msbsz, | if (sysctlbyname("kern.ipc.maxsockbuf", &maxsbsz, &msbsz, | ||||
| NULL, 0) < 0) { | 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; | goto error; | ||||
| } | } | ||||
| /* | /* | ||||
| * We can't set the socket buffer size to kern.ipc.maxsockbuf value, | * We can't set the socket buffer size to kern.ipc.maxsockbuf value, | ||||
| * as it takes into account the mbuf(9) overhead. | * as it takes into account the mbuf(9) overhead. | ||||
| */ | */ | ||||
| maxsbsz = maxsbsz * MCLBYTES / (MSIZE + MCLBYTES); | maxsbsz = maxsbsz * MCLBYTES / (MSIZE + MCLBYTES); | ||||
| sbsz = MIN(NG_SBUF_MAX_SIZE, maxsbsz); | sbsz = MIN(NG_SBUF_MAX_SIZE, maxsbsz); | ||||
| if (setsockopt(be->fd, SOL_SOCKET, SO_SNDBUF, &sbsz, | if (setsockopt(be->fd, SOL_SOCKET, SO_SNDBUF, &sbsz, | ||||
| sizeof(sbsz)) < 0) { | sizeof(sbsz)) < 0) { | ||||
| EPRINTLN("can't set TX buffer size"); | nvlist_add_string(nvl, "error", "can't set TX buffer size"); | ||||
| goto error; | goto error; | ||||
| } | } | ||||
| if (setsockopt(be->fd, SOL_SOCKET, SO_RCVBUF, &sbsz, | if (setsockopt(be->fd, SOL_SOCKET, SO_RCVBUF, &sbsz, | ||||
| sizeof(sbsz)) < 0) { | sizeof(sbsz)) < 0) { | ||||
| EPRINTLN("can't set RX buffer size"); | nvlist_add_string(nvl, "error", "can't set RX buffer size"); | ||||
| goto error; | goto error; | ||||
| } | } | ||||
| #ifndef WITHOUT_CAPSICUM | #ifndef WITHOUT_CAPSICUM | ||||
| cap_rights_init(&rights, CAP_EVENT, CAP_READ, CAP_WRITE); | cap_rights_init(&rights, CAP_EVENT, CAP_READ, CAP_WRITE); | ||||
| if (caph_rights_limit(be->fd, &rights) == -1) | if (caph_rights_limit(be->fd, &rights) == -1) | ||||
| errx(EX_OSERR, "Unable to apply rights for sandbox"); | errx(EX_OSERR, "Unable to apply rights for sandbox"); | ||||
| #endif | #endif | ||||
| memset(p->bbuf, 0, sizeof(p->bbuf)); | memset(p->bbuf, 0, sizeof(p->bbuf)); | ||||
| p->bbuflen = 0; | p->bbuflen = 0; | ||||
| p->mevp = mevent_add_disabled(be->fd, EVF_READ, cb, param); | p->mevp = mevent_add_disabled(be->fd, EVF_READ, cb, param); | ||||
| if (p->mevp == NULL) { | if (p->mevp == NULL) { | ||||
| EPRINTLN("Could not register event"); | nvlist_add_string(nvl, "error", "Could not register event"); | ||||
| goto error; | goto error; | ||||
| } | } | ||||
| return (0); | return (0); | ||||
| error: | error: | ||||
| tap_cleanup(be); | tap_cleanup(be); | ||||
| return (-1); | return (-1); | ||||
| Show All 17 Lines | |||||