[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v3 2/3] libxl: add support for channels
A 'channel' is a low-bandwidth private communication channel that resembles a physical serial port. This patch adds a list of channels to the IDL for the domain config. Each channel has a 'kind' which describes what should happen to the data. Currently defined kinds are: * PTY: the I/O surfaces as a pty in the backend domain * SOCKET: a listening Unix domain socket accepts a connection in the backend domain and proxies Channels are implemented using PV consoles backed by qemu (not xenconsoled). Channels may be listed but don't currently support hotplug/unplug. Signed-off-by: David Scott <dave.scott@xxxxxxxxxx> --- tools/libxl/libxl.c | 235 ++++++++++++++++++++++++++++++++-- tools/libxl/libxl.h | 17 +++ tools/libxl/libxl_create.c | 38 ++++-- tools/libxl/libxl_dm.c | 43 ++++++- tools/libxl/libxl_internal.h | 10 +- tools/libxl/libxl_types.idl | 37 ++++++ tools/libxl/libxl_types_internal.idl | 4 + 7 files changed, 359 insertions(+), 25 deletions(-) diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c index 900b8d4..8a069cd 100644 --- a/tools/libxl/libxl.c +++ b/tools/libxl/libxl.c @@ -3185,11 +3185,11 @@ const char *libxl__device_nic_devname(libxl__gc *gc, /******************************************************************************/ int libxl__device_console_add(libxl__gc *gc, uint32_t domid, libxl__device_console *console, - libxl__domain_build_state *state) + libxl__domain_build_state *state, + libxl__device *device) { flexarray_t *front, *ro_front; flexarray_t *back; - libxl__device device; int rc; if (console->devid && state) { @@ -3201,12 +3201,12 @@ int libxl__device_console_add(libxl__gc *gc, uint32_t domid, ro_front = flexarray_make(gc, 16, 1); back = flexarray_make(gc, 16, 1); - device.backend_devid = console->devid; - device.backend_domid = console->backend_domid; - device.backend_kind = LIBXL__DEVICE_KIND_CONSOLE; - device.devid = console->devid; - device.domid = domid; - device.kind = LIBXL__DEVICE_KIND_CONSOLE; + device->backend_devid = console->devid; + device->backend_domid = console->backend_domid; + device->backend_kind = LIBXL__DEVICE_KIND_CONSOLE; + device->devid = console->devid; + device->domid = domid; + device->kind = LIBXL__DEVICE_KIND_CONSOLE; flexarray_append(back, "frontend-id"); flexarray_append(back, libxl__sprintf(gc, "%d", domid)); @@ -3219,6 +3219,19 @@ int libxl__device_console_add(libxl__gc *gc, uint32_t domid, flexarray_append(back, "protocol"); flexarray_append(back, LIBXL_XENCONSOLE_PROTOCOL); + if (console->name) { + flexarray_append(ro_front, "name"); + flexarray_append(ro_front, console->name); + } + if (console->kind) { + flexarray_append(back, "kind"); + flexarray_append(back, console->kind); + } + if (console->path) { + flexarray_append(back, "path"); + flexarray_append(back, console->path); + } + flexarray_append(front, "backend-id"); flexarray_append(front, libxl__sprintf(gc, "%d", console->backend_domid)); @@ -3245,8 +3258,7 @@ int libxl__device_console_add(libxl__gc *gc, uint32_t domid, flexarray_append(front, "protocol"); flexarray_append(front, LIBXL_XENCONSOLE_PROTOCOL); } - - libxl__device_generic_add(gc, XBT_NULL, &device, + libxl__device_generic_add(gc, XBT_NULL, device, libxl__xs_kvs_of_flexarray(gc, back, back->count), libxl__xs_kvs_of_flexarray(gc, front, front->count), libxl__xs_kvs_of_flexarray(gc, ro_front, ro_front->count)); @@ -3257,6 +3269,209 @@ out: /******************************************************************************/ +int libxl__init_console_from_channel(libxl__gc *gc, + libxl__device_console *console, + int dev_num, + libxl_device_channel *channel) +{ + int rc; + libxl__device_console_init(console); + console->devid = dev_num; + console->consback = LIBXL__CONSOLE_BACKEND_IOEMU; + if (!channel->name){ + LIBXL__LOG(CTX, LIBXL__LOG_ERROR, + "channel %d has no name", channel->devid); + return ERROR_INVAL; + } + console->name = libxl__strdup(NOGC, channel->name); + + if (channel->backend_domname) { + rc = libxl_domain_qualifier_to_domid(CTX, channel->backend_domname, + &channel->backend_domid); + if (rc < 0) return rc; + } + + console->backend_domid = channel->backend_domid; + + switch (channel->kind) { + case LIBXL_CHANNEL_KIND_UNKNOWN: + LIBXL__LOG(CTX, LIBXL__LOG_ERROR, + "channel %d has no kind", channel->devid); + return ERROR_INVAL; + case LIBXL_CHANNEL_KIND_PTY: + console->kind = libxl__strdup(NOGC, "pty"); + console->output = libxl__sprintf(NOGC, "pty"); + break; + case LIBXL_CHANNEL_KIND_SOCKET: + console->kind = libxl__strdup(NOGC, "socket"); + if (!channel->u.socket.path) { + LIBXL__LOG(CTX, LIBXL__LOG_ERROR, + "channel %d has no path", channel->devid); + return ERROR_INVAL; + } + console->path = libxl__strdup(NOGC, channel->u.socket.path); + console->output = libxl__sprintf(NOGC, "chardev:libxl-channel%d", + channel->devid); + break; + default: + /* We've forgotten to add the clause */ + LOG(ERROR, "%s: unknown channel kind %d", __func__, channel->kind); + return ERROR_INVAL; + } + + return 0; +} + +static int libxl__device_channel_from_xs_be(libxl__gc *gc, + const char *be_path, + libxl_device_channel *channel) +{ + const char *tmp; + int rc; + + libxl_device_channel_init(channel); + + /* READ_BACKEND is from libxl__device_nic_from_xs_be above */ + channel->name = READ_BACKEND(NOGC, "name"); + tmp = READ_BACKEND(gc, "kind"); + if (!strcmp(tmp, "pty")) { + channel->kind = LIBXL_CHANNEL_KIND_PTY; + } else if (!strcmp(tmp, "socket")) { + channel->kind = LIBXL_CHANNEL_KIND_SOCKET; + channel->u.socket.path = READ_BACKEND(NOGC, "path"); + } else { + rc = ERROR_INVAL; + goto out; + } + + rc = 0; + out: + return rc; +} + +static int libxl__append_channel_list_of_type(libxl__gc *gc, + uint32_t domid, + const char *type, + libxl_device_channel **channels, + int *nchannels) +{ + char *fe_path = NULL, *be_path = NULL; + char **dir = NULL; + unsigned int n = 0, devid = 0; + libxl_device_channel *next = NULL; + int rc = 0, i; + + fe_path = GCSPRINTF("%s/device/%s", + libxl__xs_get_dompath(gc, domid), type); + dir = libxl__xs_directory(gc, XBT_NULL, fe_path, &n); + if (!dir || !n) + goto out; + + for (i = 0; i < n; i++) { + const char *p, *name; + libxl_device_channel *tmp; + p = libxl__sprintf(gc, "%s/%s", fe_path, dir[i]); + name = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/name", p)); + /* 'channels' are consoles with names, so ignore all consoles + without names */ + if (!name) continue; + be_path = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/backend", p)); + tmp = realloc(*channels, + sizeof(libxl_device_channel) * (*nchannels + devid + 1)); + if (!tmp) { + rc = ERROR_NOMEM; + goto out; + } + *channels = tmp; + next = *channels + *nchannels + devid; + rc = libxl__device_channel_from_xs_be(gc, be_path, next); + if (rc) goto out; + next->devid = devid; + devid++; + } + *nchannels += devid; + return 0; + + out: + return rc; +} + +libxl_device_channel *libxl_device_channel_list(libxl_ctx *ctx, + uint32_t domid, + int *num) +{ + GC_INIT(ctx); + libxl_device_channel *channels = NULL; + int rc; + + *num = 0; + + rc = libxl__append_channel_list_of_type(gc, domid, "console", &channels, num); + if (rc) goto out_err; + + GC_FREE; + return channels; + +out_err: + LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "Unable to list channels"); + while (*num) { + (*num)--; + libxl_device_channel_dispose(&channels[*num]); + } + free(channels); + return NULL; +} + +int libxl_device_channel_getinfo(libxl_ctx *ctx, uint32_t domid, + libxl_device_channel *channel, + libxl_channelinfo *channelinfo) +{ + GC_INIT(ctx); + char *dompath, *fe_path; + char *val; + + dompath = libxl__xs_get_dompath(gc, domid); + channelinfo->devid = channel->devid; + + fe_path = libxl__sprintf(gc, "%s/device/console/%d", dompath, + channelinfo->devid + 1); + channelinfo->backend = xs_read(ctx->xsh, XBT_NULL, + libxl__sprintf(gc, "%s/backend", + fe_path), NULL); + if (!channelinfo->backend) { + GC_FREE; + return ERROR_FAIL; + } + val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/backend-id", fe_path)); + channelinfo->backend_id = val ? strtoul(val, NULL, 10) : -1; + val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/state", fe_path)); + channelinfo->state = val ? strtoul(val, NULL, 10) : -1; + channelinfo->frontend = xs_read(ctx->xsh, XBT_NULL, + GCSPRINTF("%s/frontend", + channelinfo->backend), NULL); + val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/frontend-id", + channelinfo->backend)); + channelinfo->frontend_id = val ? strtoul(val, NULL, 10) : -1; + val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/ring-ref", fe_path)); + channelinfo->rref = val ? strtoul(val, NULL, 10) : -1; + val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/port", fe_path)); + channelinfo->evtch = val ? strtoul(val, NULL, 10) : -1; + + channelinfo->kind = channel->kind; + switch (channel->kind) { + case LIBXL_CHANNEL_KIND_PTY: + val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/tty", fe_path)); + channelinfo->u.pty.path = strdup(val); + break; + default: + break; + } + GC_FREE; + return 0; +} + +/******************************************************************************/ + int libxl__device_vkb_setdefault(libxl__gc *gc, libxl_device_vkb *vkb) { int rc; diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h index 80947c3..8d54456 100644 --- a/tools/libxl/libxl.h +++ b/tools/libxl/libxl.h @@ -482,6 +482,15 @@ */ #define LIBXL_HAVE_DEVICE_PCI_SEIZE 1 +/* + * LIBXL_HAVE_DEVICE_CHANNEL + * + * If this is defined, then the libxl_device_channel struct exists + * and channels can be attached to a domain both at build-time and at + * run-time by hotplug. + */ +#define LIBXL_HAVE_DEVICE_CHANNEL 1 + /* Functions annotated with LIBXL_EXTERNAL_CALLERS_ONLY may not be * called from within libxl itself. Callers outside libxl, who * do not #include libxl_internal.h, are fine. */ @@ -956,6 +965,14 @@ libxl_device_nic *libxl_device_nic_list(libxl_ctx *ctx, uint32_t domid, int *num int libxl_device_nic_getinfo(libxl_ctx *ctx, uint32_t domid, libxl_device_nic *nic, libxl_nicinfo *nicinfo); +/* Virtual Channels */ +libxl_device_channel *libxl_device_channel_list(libxl_ctx *ctx, + uint32_t domid, + int *num); +int libxl_device_channel_getinfo(libxl_ctx *ctx, uint32_t domid, + libxl_device_channel *channel, + libxl_channelinfo *channelinfo); + /* Virtual TPMs */ int libxl_device_vtpm_add(libxl_ctx *ctx, uint32_t domid, libxl_device_vtpm *vtpm, const libxl_asyncop_how *ao_how) diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c index d015cf4..ec5a4d6 100644 --- a/tools/libxl/libxl_create.c +++ b/tools/libxl/libxl_create.c @@ -355,14 +355,16 @@ int libxl__domain_build_info_setdefault(libxl__gc *gc, return 0; } -static int init_console_info(libxl__device_console *console, int dev_num) +static int init_console_info(libxl__gc *gc, + libxl__device_console *console, + int dev_num) { - memset(console, 0x00, sizeof(libxl__device_console)); + libxl__device_console_init(console); console->devid = dev_num; console->consback = LIBXL__CONSOLE_BACKEND_XENCONSOLED; - console->output = strdup("pty"); - if (!console->output) - return ERROR_NOMEM; + console->output = libxl__strdup(NOGC, "pty"); + /* console->{name,kind,path} are NULL on normal consoles. + Only 'channels' when mapped to consoles have a string name. */ return 0; } @@ -1110,17 +1112,31 @@ static void domcreate_launch_dm(libxl__egc *egc, libxl__multidev *multidev, } } + /* For both HVM and PV the 0th console is a regular console. We + map channels to IOEMU consoles starting at 1 */ + for (i = 0; i < d_config->num_channels; i++) { + libxl__device_console console; + libxl__device device; + ret = libxl__init_console_from_channel(gc, &console, i + 1, + &d_config->channels[i]); + if ( ret ) + goto error_out; + libxl__device_console_add(gc, domid, &console, NULL, &device); + libxl__device_console_dispose(&console); + } + switch (d_config->c_info.type) { case LIBXL_DOMAIN_TYPE_HVM: { libxl__device_console console; + libxl__device device; libxl_device_vkb vkb; - ret = init_console_info(&console, 0); + ret = init_console_info(gc, &console, 0); if ( ret ) goto error_out; console.backend_domid = state->console_domid; - libxl__device_console_add(gc, domid, &console, state); + libxl__device_console_add(gc, domid, &console, state, &device); libxl__device_console_dispose(&console); libxl_device_vkb_init(&vkb); @@ -1138,22 +1154,24 @@ static void domcreate_launch_dm(libxl__egc *egc, libxl__multidev *multidev, { int need_qemu = 0; libxl__device_console console; + libxl__device device; for (i = 0; i < d_config->num_vfbs; i++) { libxl__device_vfb_add(gc, domid, &d_config->vfbs[i]); libxl__device_vkb_add(gc, domid, &d_config->vkbs[i]); } - ret = init_console_info(&console, 0); + ret = init_console_info(gc, &console, 0); if ( ret ) goto error_out; need_qemu = libxl__need_xenpv_qemu(gc, 1, &console, d_config->num_vfbs, d_config->vfbs, - d_config->num_disks, &d_config->disks[0]); + d_config->num_disks, &d_config->disks[0], + d_config->num_channels, &d_config->channels[0]); console.backend_domid = state->console_domid; - libxl__device_console_add(gc, domid, &console, state); + libxl__device_console_add(gc, domid, &console, state, &device); libxl__device_console_dispose(&console); if (need_qemu) { diff --git a/tools/libxl/libxl_dm.c b/tools/libxl/libxl_dm.c index 51ab2bf..4338b08 100644 --- a/tools/libxl/libxl_dm.c +++ b/tools/libxl/libxl_dm.c @@ -394,8 +394,9 @@ static char ** libxl__build_device_model_args_new(libxl__gc *gc, const libxl_sdl_info *sdl = dm_sdl(guest_config); const char *keymap = dm_keymap(guest_config); flexarray_t *dm_args; - int i; + int i, kind, devid; uint64_t ram_size; + const char *path, *chardev; dm_args = flexarray_make(gc, 16, 1); @@ -412,6 +413,27 @@ static char ** libxl__build_device_model_args_new(libxl__gc *gc, flexarray_append(dm_args, "-mon"); flexarray_append(dm_args, "chardev=libxl-cmd,mode=control"); + for (i = 0; i < guest_config->num_channels; i++) { + kind = guest_config->channels[i].kind; + devid = guest_config->channels[i].devid; + switch (kind) { + case LIBXL_CHANNEL_KIND_PTY: + chardev = GCSPRINTF("pty,id=libxl-channel%d", devid); + break; + case LIBXL_CHANNEL_KIND_SOCKET: + path = guest_config->channels[i].u.socket.path; + chardev = GCSPRINTF("socket,id=libxl-channel%d,path=%s," + "server,nowait", devid, path); + break; + default: + /* We've forgotten to add the clause */ + LOG(ERROR, "%s: unknown channel kind %d", __func__, kind); + return NULL; + } + flexarray_append(dm_args, "-chardev"); + flexarray_append(dm_args, (void*)chardev); + } + /* * Remove default devices created by qemu. Qemu will create only devices * defined by xen, since the devices not defined by xen are not usable. @@ -1067,6 +1089,7 @@ static void spawn_stub_launch_dm(libxl__egc *egc, } for (i = 0; i < num_console; i++) { + libxl__device device; console[i].devid = i; console[i].consback = LIBXL__CONSOLE_BACKEND_IOEMU; /* STUBDOM_CONSOLE_LOGGING (console 0) is for minios logging @@ -1097,7 +1120,8 @@ static void spawn_stub_launch_dm(libxl__egc *egc, break; } ret = libxl__device_console_add(gc, dm_domid, &console[i], - i == STUBDOM_CONSOLE_LOGGING ? stubdom_state : NULL); + i == STUBDOM_CONSOLE_LOGGING ? stubdom_state : NULL, + &device); if (ret) goto out; } @@ -1517,7 +1541,8 @@ int libxl__destroy_device_model(libxl__gc *gc, uint32_t domid) int libxl__need_xenpv_qemu(libxl__gc *gc, int nr_consoles, libxl__device_console *consoles, int nr_vfbs, libxl_device_vfb *vfbs, - int nr_disks, libxl_device_disk *disks) + int nr_disks, libxl_device_disk *disks, + int nr_channels, libxl_device_channel *channels) { int i, ret = 0; uint32_t domid; @@ -1557,6 +1582,18 @@ int libxl__need_xenpv_qemu(libxl__gc *gc, } } + if (nr_channels > 0) { + ret = libxl__get_domid(gc, &domid); + if (ret) goto out; + for (i = 0; i < nr_channels; i++) { + if (channels[i].kind == LIBXL_CHANNEL_KIND_SOCKET && + channels[i].backend_domid == domid) { + ret = 1; + goto out; + } + } + } + out: return ret; } diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h index 082749e..8053663 100644 --- a/tools/libxl/libxl_internal.h +++ b/tools/libxl/libxl_internal.h @@ -1018,7 +1018,8 @@ _hidden int libxl__device_disk_dev_number(const char *virtpath, _hidden int libxl__device_console_add(libxl__gc *gc, uint32_t domid, libxl__device_console *console, - libxl__domain_build_state *state); + libxl__domain_build_state *state, + libxl__device *device); _hidden int libxl__device_generic_add(libxl__gc *gc, xs_transaction_t t, libxl__device *device, char **bents, char **fents, char **ro_fents); @@ -1031,6 +1032,10 @@ _hidden int libxl__wait_for_backend(libxl__gc *gc, const char *be_path, const char *state); _hidden int libxl__nic_type(libxl__gc *gc, libxl__device *dev, libxl_nic_type *nictype); +_hidden int libxl__init_console_from_channel(libxl__gc *gc, + libxl__device_console *console, + int dev_num, + libxl_device_channel *channel); /* * For each aggregate type which can be used as an input we provide: @@ -1450,7 +1455,8 @@ _hidden const char *libxl__domain_device_model(libxl__gc *gc, _hidden int libxl__need_xenpv_qemu(libxl__gc *gc, int nr_consoles, libxl__device_console *consoles, int nr_vfbs, libxl_device_vfb *vfbs, - int nr_disks, libxl_device_disk *disks); + int nr_disks, libxl_device_disk *disks, + int nr_channels, libxl_device_channel *channels); /* * This function will cause the whole libxl process to hang diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl index 52f1aa9..025bffd 100644 --- a/tools/libxl/libxl_types.idl +++ b/tools/libxl/libxl_types.idl @@ -51,6 +51,14 @@ libxl_domain_type = Enumeration("domain_type", [ (2, "PV"), ], init_val = -1) +libxl_channel_kind = Enumeration("channel_kind", [ + (0, "UNKNOWN"), + # Connect to a pty in the backend domain: + (1, "PTY"), + # Listen on a Unix domain socket in the backend domain: + (2, "SOCKET"), + ]) + libxl_device_model_version = Enumeration("device_model_version", [ (0, "UNKNOWN"), (1, "QEMU_XEN_TRADITIONAL"), # Historical qemu-xen device model (qemu-dm) @@ -245,6 +253,22 @@ libxl_cpupoolinfo = Struct("cpupoolinfo", [ ("cpumap", libxl_bitmap) ], dir=DIR_OUT) +libxl_channelinfo = Struct("channelinfo", [ + ("backend", string), + ("backend_id", uint32), + ("frontend", string), + ("frontend_id", uint32), + ("devid", libxl_devid), + ("state", integer), + ("evtch", integer), + ("rref", integer), + ("u", KeyedUnion(None, libxl_channel_kind, "kind", + [("unknown", None), + ("pty", Struct(None, [("path", string),])), + ("socket", None), + ])), + ], dir=DIR_OUT) + libxl_vminfo = Struct("vminfo", [ ("uuid", libxl_uuid), ("domid", libxl_domid), @@ -457,6 +481,18 @@ libxl_device_vtpm = Struct("device_vtpm", [ ("uuid", libxl_uuid), ]) +libxl_device_channel = Struct("device_channel", [ + ("backend_domid", libxl_domid), + ("backend_domname", string), + ("devid", libxl_devid), + ("name", string), + ("u", KeyedUnion(None, libxl_channel_kind, "kind", + [("unknown", None), + ("pty", None), + ("socket", Struct(None, [("path", string)])), + ])), +]) + libxl_domain_config = Struct("domain_config", [ ("c_info", libxl_domain_create_info), ("b_info", libxl_domain_build_info), @@ -467,6 +503,7 @@ libxl_domain_config = Struct("domain_config", [ ("vfbs", Array(libxl_device_vfb, "num_vfbs")), ("vkbs", Array(libxl_device_vkb, "num_vkbs")), ("vtpms", Array(libxl_device_vtpm, "num_vtpms")), + ("channels", Array(libxl_device_channel, "num_channels")), ("on_poweroff", libxl_action_on_shutdown), ("on_reboot", libxl_action_on_shutdown), diff --git a/tools/libxl/libxl_types_internal.idl b/tools/libxl/libxl_types_internal.idl index cb9444f..7d1e22c 100644 --- a/tools/libxl/libxl_types_internal.idl +++ b/tools/libxl/libxl_types_internal.idl @@ -32,6 +32,10 @@ libxl__device_console = Struct("device_console", [ ("devid", integer), ("consback", libxl__console_backend), ("output", string), + # These are specific to the 'channels', built on top of consoles: + ("name", string), + ("kind", string), + ("path", string), ]) libxl__device_action = Enumeration("device_action", [ -- 1.7.10.4 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |