Changeset View
Changeset View
Standalone View
Standalone View
usr.sbin/bhyve/net_backend_slirp.c
| Show First 20 Lines • Show All 41 Lines • ▼ Show 20 Lines | |||||
| * | * | ||||
| * Packets to be transmitted to the guest (i.e., inserted into the frontend's | * Packets to be transmitted to the guest (i.e., inserted into the frontend's | ||||
| * receive buffers) are buffered in a per-interface socket pair and read by the | * receive buffers) are buffered in a per-interface socket pair and read by the | ||||
| * mevent loop. Sockets instantiated by libslirp are monitored by a thread | * mevent loop. Sockets instantiated by libslirp are monitored by a thread | ||||
| * which uses poll() and slirp_pollfds_poll() to drive libslirp events; this | * which uses poll() and slirp_pollfds_poll() to drive libslirp events; this | ||||
| * thread also handles timeout events from the libslirp context. | * thread also handles timeout events from the libslirp context. | ||||
| */ | */ | ||||
| #include <sys/procdesc.h> | |||||
| #include <sys/socket.h> | #include <sys/socket.h> | ||||
| #include <sys/wait.h> | #include <sys/wait.h> | ||||
| #include <assert.h> | #include <assert.h> | ||||
| #include <bhyve/config.h> | #include <bhyve/config.h> | ||||
| #include <errno.h> | #include <errno.h> | ||||
| #include <signal.h> | #include <signal.h> | ||||
| #include <spawn.h> | #include <spawn.h> | ||||
| Show All 21 Lines | |||||
| extern char **environ; | extern char **environ; | ||||
| static int | static int | ||||
| slirp_init(struct net_backend *be, const char *devname __unused, | slirp_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 slirp_priv *priv = NET_BE_PRIV(be); | struct slirp_priv *priv = NET_BE_PRIV(be); | ||||
| nvlist_t *config; | nvlist_t *config; | ||||
| posix_spawn_file_actions_t fa; | |||||
| pid_t child; | pid_t child; | ||||
| const char **argv; | int error, *s; | ||||
| char sockname[32]; | size_t mtu, nitems; | ||||
| int error, s[2]; | |||||
| const char *mtu_value; | const char *mtu_value; | ||||
| size_t mtu; | int helper_pd; | ||||
| if (socketpair(PF_LOCAL, SOCK_SEQPACKET | SOCK_NONBLOCK, 0, s) != 0) { | s = nvlist_take_descriptor_array(nvl, "sockpair", &nitems); | ||||
| EPRINTLN("socketpair"); | if (nitems != 2) { | ||||
| nvlist_add_string(nvl, "error", | |||||
| "mismatched number of socket descriptors"); | |||||
| return (-1); | return (-1); | ||||
| } | } | ||||
| /* | |||||
| * The child will exit once its connection goes away, so make sure only | |||||
| * one end is inherited by the child. | |||||
| */ | |||||
| if (posix_spawn_file_actions_init(&fa) != 0) { | |||||
| EPRINTLN("posix_spawn_file_actions_init"); | |||||
| goto err; | |||||
| } | |||||
| if (posix_spawn_file_actions_addclose(&fa, s[0]) != 0) { | |||||
| EPRINTLN("posix_spawn_file_actions_addclose"); | |||||
| posix_spawn_file_actions_destroy(&fa); | |||||
| goto err; | |||||
| } | |||||
| (void)snprintf(sockname, sizeof(sockname), "%d", s[1]); | |||||
| argv = (const char *[]){ | |||||
| "/usr/libexec/bhyve-slirp-helper", "-S", sockname, NULL | |||||
| }; | |||||
| error = posix_spawn(&child, "/usr/libexec/bhyve-slirp-helper", | |||||
| &fa, NULL, __DECONST(char **, argv), environ); | |||||
| posix_spawn_file_actions_destroy(&fa); | |||||
| if (error != 0) { | |||||
| EPRINTLN("posix_spawn(bhyve-slirp-helper): %s", | |||||
| strerror(error)); | |||||
| goto err; | |||||
| } | |||||
| config = nvlist_clone(nvl); | config = nvlist_clone(nvl); | ||||
| if (config == NULL) { | if (config == NULL) { | ||||
| EPRINTLN("nvlist_clone"); | nvlist_add_string(nvl, "error", | ||||
| "nvlist_clone"); | |||||
| goto err; | goto err; | ||||
| } | } | ||||
| mtu_value = get_config_value_node(config, "mtu"); | mtu_value = get_config_value_node(config, "mtu"); | ||||
| if (mtu_value != NULL) { | if (mtu_value != NULL) { | ||||
| if (net_parsemtu(mtu_value, &mtu)) { | if (net_parsemtu(mtu_value, &mtu)) { | ||||
| EPRINTLN("Could not parse MTU"); | nvlist_add_string(nvl, "error", "Could not parse MTU"); | ||||
| goto err; | goto err; | ||||
| } | } | ||||
| } else { | } else { | ||||
| mtu = DEFAULT_MTU; | mtu = DEFAULT_MTU; | ||||
| } | } | ||||
| nvlist_add_number(config, "mtui", mtu); | nvlist_add_number(config, "mtui", mtu); | ||||
| priv->mtu = mtu; | priv->mtu = mtu; | ||||
| priv->buf = malloc(mtu); | priv->buf = malloc(mtu); | ||||
| if (priv->buf == NULL) { | if (priv->buf == NULL) { | ||||
| EPRINTLN("Could not allocate buffer"); | nvlist_add_string(nvl, "error", "Could not allocate MTU buffer"); | ||||
| goto err; | goto err; | ||||
| } | } | ||||
| nvlist_add_string(config, "vmname", get_config_value("name")); | nvlist_add_string(config, "vmname", get_config_value("name")); | ||||
| error = nvlist_send(s[0], config); | error = nvlist_send(s[0], config); | ||||
| nvlist_destroy(config); | nvlist_destroy(config); | ||||
| if (error != 0) { | if (error != 0) { | ||||
| EPRINTLN("nvlist_send"); | nvlist_add_string(nvl, "error", | ||||
| "nvlist_send"); | |||||
| goto err; | goto err; | ||||
| } | } | ||||
| be->fd = s[0]; | be->fd = s[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 err; | |||||
| } | |||||
| helper_pd = nvlist_take_descriptor(nvl, "helper_pd"); | |||||
| if (pdgetpid(helper_pd, &child) != 0) { | |||||
| nvlist_add_string(nvl, "error", | |||||
| "pdgetpid failed"); | |||||
| goto err; | goto err; | ||||
| } | } | ||||
| priv->helper = child; | priv->helper = child; | ||||
| priv->s = s[0]; | priv->s = s[0]; | ||||
| (void)close(s[1]); | (void)close(s[1]); | ||||
| return (0); | return (0); | ||||
| ▲ Show 20 Lines • Show All 123 Lines • Show Last 20 Lines | |||||