Changeset View
Changeset View
Standalone View
Standalone View
usr.sbin/bhyve/net_backends.c
| Show First 20 Lines • Show All 79 Lines • ▼ Show 20 Lines | tap_cleanup(struct net_backend *be) | ||||
| } | } | ||||
| if (be->fd != -1) { | if (be->fd != -1) { | ||||
| close(be->fd); | close(be->fd); | ||||
| be->fd = -1; | be->fd = -1; | ||||
| } | } | ||||
| } | } | ||||
| static int | static int | ||||
| tap_init(struct net_backend *be, const char *devname, | tap_init(struct net_backend *be, const char *devname __unused, nvlist_t *nvl, | ||||
| nvlist_t *nvl __unused, net_be_rxeof_t cb, void *param) | net_be_rxeof_t cb, void *param) | ||||
| { | { | ||||
| struct tap_priv *priv = NET_BE_PRIV(be); | struct tap_priv *priv = NET_BE_PRIV(be); | ||||
| char tbuf[80]; | |||||
| int opt = 1, up = IFF_UP; | int opt = 1, up = IFF_UP; | ||||
| #ifndef WITHOUT_CAPSICUM | #ifndef WITHOUT_CAPSICUM | ||||
| cap_rights_t rights; | cap_rights_t rights; | ||||
| #endif | #endif | ||||
| if (cb == NULL) { | if (cb == NULL) { | ||||
| EPRINTLN("TAP backend requires non-NULL callback"); | nvlist_add_string(nvl, "error", | ||||
| "TAP backend requires non-NULL callback"); | |||||
| return (-1); | return (-1); | ||||
| } | } | ||||
| strcpy(tbuf, "/dev/"); | be->fd = nvlist_take_descriptor(nvl, "devfd"); | ||||
| 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; | |||||
| } | |||||
| /* | /* | ||||
| * Set non-blocking and register for read | * Set non-blocking and register for read | ||||
| * notifications with the event loop | * notifications with the event loop | ||||
| */ | */ | ||||
| if (ioctl(be->fd, FIONBIO, &opt) < 0) { | 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; | goto error; | ||||
| } | } | ||||
| if (strncmp("ngd", be->prefix, 3) && | if (strncmp("ngd", be->prefix, 3) && | ||||
| ioctl(be->fd, VMIO_SIOCSIFFLAGS, up)) { | ioctl(be->fd, VMIO_SIOCSIFFLAGS, up)) { | ||||
| EPRINTLN("tap device link up failed"); | nvlist_add_string(nvl, "error", "tap device link up failed"); | ||||
| 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(priv->bbuf, 0, sizeof(priv->bbuf)); | memset(priv->bbuf, 0, sizeof(priv->bbuf)); | ||||
| priv->bbuflen = 0; | priv->bbuflen = 0; | ||||
| priv->mevp = mevent_add_disabled(be->fd, EVF_READ, cb, param); | priv->mevp = mevent_add_disabled(be->fd, EVF_READ, cb, param); | ||||
| if (priv->mevp == NULL) { | if (priv->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 20 Lines • Show All 140 Lines • ▼ Show 20 Lines | static struct net_backend ngd_backend = { | ||||
| .get_cap = tap_get_cap, | .get_cap = tap_get_cap, | ||||
| .set_cap = tap_set_cap, | .set_cap = tap_set_cap, | ||||
| }; | }; | ||||
| DATA_SET(net_backend_set, tap_backend); | DATA_SET(net_backend_set, tap_backend); | ||||
| DATA_SET(net_backend_set, vmnet_backend); | DATA_SET(net_backend_set, vmnet_backend); | ||||
| DATA_SET(net_backend_set, ngd_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. | * Initialize a backend and attach to the frontend. | ||||
| * This is called during frontend initialization. | * This is called during frontend initialization. | ||||
| * @ret is a pointer to the backend to be initialized | * @ret is a pointer to the backend to be initialized | ||||
| * @devname is the backend-name as supplied on the command line, | * @devname is the backend-name as supplied on the command line, | ||||
| * e.g. -s 2:0,frontend-name,backend-name[,other-args] | * e.g. -s 2:0,frontend-name,backend-name[,other-args] | ||||
| * @cb is the receive callback supplied by the frontend, | * @cb is the receive callback supplied by the frontend, | ||||
| * and it is invoked in the event loop when a receive | * and it is invoked in the event loop when a receive | ||||
| * event is generated in the hypervisor, | * event is generated in the hypervisor, | ||||
| * @param is a pointer to the frontend, and normally used as | * @param is a pointer to the frontend, and normally used as | ||||
| * the argument for the callback. | * the argument for the callback. | ||||
| */ | */ | ||||
| int | int | ||||
| netbe_init(struct net_backend **ret, nvlist_t *nvl, net_be_rxeof_t cb, | netbe_init(struct net_backend **ret, nvlist_t *nvl, net_be_rxeof_t cb, | ||||
| void *param) | void *param) | ||||
| { | { | ||||
| struct net_backend **pbe, *nbe, *tbe = NULL; | struct net_backend **pbe, *nbe, *tbe = NULL; | ||||
| const char *value, *type; | const char *value, *type; | ||||
| char *devname; | char *devname; | ||||
| int err; | int err; | ||||
| value = get_config_value_node(nvl, "backend"); | value = get_config_value_node(nvl, "backend"); | ||||
| if (value == NULL) { | if (value == NULL) { | ||||
| nvlist_add_string(nvl, "error", "missing backend argument"); | |||||
| return (-1); | return (-1); | ||||
| } | } | ||||
| devname = strdup(value); | devname = strdup(value); | ||||
| /* | /* | ||||
| * Use the type given by configuration if exists; otherwise | * Use the type given by configuration if exists; otherwise | ||||
| * use the prefix of the backend as the type. | * use the prefix of the backend as the type. | ||||
| */ | */ | ||||
| Show All 16 Lines | if (strncmp(type, (*pbe)->prefix, | ||||
| assert(tbe->get_cap != NULL); | assert(tbe->get_cap != NULL); | ||||
| assert(tbe->set_cap != NULL); | assert(tbe->set_cap != NULL); | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| *ret = NULL; | *ret = NULL; | ||||
| if (tbe == NULL) { | if (tbe == NULL) { | ||||
| nvlist_add_stringf(nvl, "error", "unknown backend '%s'", type); | |||||
| free(devname); | free(devname); | ||||
| return (EINVAL); | return (EINVAL); | ||||
| } | } | ||||
| nbe = calloc(1, NET_BE_SIZE(tbe)); | nbe = calloc(1, NET_BE_SIZE(tbe)); | ||||
| *nbe = *tbe; /* copy the template */ | *nbe = *tbe; /* copy the template */ | ||||
| nbe->fd = -1; | nbe->fd = -1; | ||||
| nbe->sc = param; | nbe->sc = param; | ||||
| ▲ Show 20 Lines • Show All 125 Lines • Show Last 20 Lines | |||||