[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH 6/6] libxl: move common nic stuff into one source
Put all nic related stuff of libxl form common files into a dedicated source file. Signed-off-by: Juergen Gross <jgross@xxxxxxxx> --- tools/libxl/Makefile | 2 +- tools/libxl/libxl.c | 474 +----------------------------------- tools/libxl/libxl_create.c | 23 +- tools/libxl/libxl_internal.h | 5 +- tools/libxl/libxl_nic.c | 554 +++++++++++++++++++++++++++++++++++++++++++ tools/libxl/libxl_utils.c | 35 --- 6 files changed, 573 insertions(+), 520 deletions(-) create mode 100644 tools/libxl/libxl_nic.c diff --git a/tools/libxl/Makefile b/tools/libxl/Makefile index 86c11bf..14a1a8e 100644 --- a/tools/libxl/Makefile +++ b/tools/libxl/Makefile @@ -115,7 +115,7 @@ LIBXL_OBJS = flexarray.o libxl.o libxl_create.o libxl_dm.o libxl_pci.o \ libxl_save_callout.o _libxl_save_msgs_callout.o \ libxl_qmp.o libxl_event.o libxl_fork.o \ libxl_dom_suspend.o libxl_dom_save.o libxl_pvusb.o \ - libxl_vtpm.o \ + libxl_vtpm.o libxl_nic.o \ $(LIBXL_OBJS-y) LIBXL_OBJS += libxl_genid.o LIBXL_OBJS += _libxl_types.o libxl_flask.o _libxl_types_internal.o diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c index 03e5a58..58d80b7 100644 --- a/tools/libxl/libxl.c +++ b/tools/libxl/libxl.c @@ -21,15 +21,6 @@ #define PAGE_TO_MEMKB(pages) ((pages) * 4) #define BACKEND_STRING_SIZE 5 -/* Utility to read /libxl xenstore keys, from libxl_path */ -#define READ_LIBXLDEV(tgc, subpath) ({ \ - rc = libxl__xs_read_checked(tgc, XBT_NULL, \ - GCSPRINTF("%s/" subpath, libxl_path), \ - &tmp); \ - if (rc) goto out; \ - (char*)tmp; \ - }); - int libxl_ctx_alloc(libxl_ctx **pctx, int version, unsigned flags, xentoollog_logger * lg) { @@ -3069,433 +3060,6 @@ out: } /******************************************************************************/ - -int libxl__device_nic_setdefault(libxl__gc *gc, libxl_device_nic *nic, - uint32_t domid, bool hotplug) -{ - int rc; - - if (!nic->mtu) - nic->mtu = 1492; - if (!nic->model) { - nic->model = strdup("rtl8139"); - if (!nic->model) return ERROR_NOMEM; - } - if (libxl__mac_is_default(&nic->mac)) { - const uint8_t *r; - libxl_uuid uuid; - - libxl_uuid_generate(&uuid); - r = libxl_uuid_bytearray(&uuid); - - nic->mac[0] = 0x00; - nic->mac[1] = 0x16; - nic->mac[2] = 0x3e; - nic->mac[3] = r[0] & 0x7f; - nic->mac[4] = r[1]; - nic->mac[5] = r[2]; - } - if (!nic->bridge) { - nic->bridge = strdup("xenbr0"); - if (!nic->bridge) return ERROR_NOMEM; - } - if ( !nic->script && asprintf(&nic->script, "%s/vif-bridge", - libxl__xen_script_dir_path()) < 0 ) - return ERROR_FAIL; - - rc = libxl__resolve_domid(gc, nic->backend_domname, &nic->backend_domid); - if (rc < 0) return rc; - - switch (libxl__domain_type(gc, domid)) { - case LIBXL_DOMAIN_TYPE_HVM: - if (!nic->nictype) { - if (hotplug || - (libxl__device_model_version_running(gc, domid) == - LIBXL_DEVICE_MODEL_VERSION_NONE)) - nic->nictype = LIBXL_NIC_TYPE_VIF; - else - nic->nictype = LIBXL_NIC_TYPE_VIF_IOEMU; - } - break; - case LIBXL_DOMAIN_TYPE_PV: - if (nic->nictype == LIBXL_NIC_TYPE_VIF_IOEMU) { - LOG(ERROR, "trying to create PV guest with an emulated interface"); - return ERROR_INVAL; - } - nic->nictype = LIBXL_NIC_TYPE_VIF; - break; - case LIBXL_DOMAIN_TYPE_INVALID: - return ERROR_FAIL; - default: - abort(); - } - - return rc; -} - -static int libxl__device_from_nic(libxl__gc *gc, uint32_t domid, - libxl_device_nic *nic, - libxl__device *device) -{ - device->backend_devid = nic->devid; - device->backend_domid = nic->backend_domid; - device->backend_kind = LIBXL__DEVICE_KIND_VIF; - device->devid = nic->devid; - device->domid = domid; - device->kind = LIBXL__DEVICE_KIND_VIF; - - return 0; -} - -static void libxl__update_config_nic(libxl__gc *gc, libxl_device_nic *dst, - const libxl_device_nic *src) -{ - dst->devid = src->devid; - dst->nictype = src->nictype; - libxl_mac_copy(CTX, &dst->mac, &src->mac); -} - -static void libxl__device_nic_add(libxl__egc *egc, uint32_t domid, - libxl_device_nic *nic, - libxl__ao_device *aodev) -{ - STATE_AO_GC(aodev->ao); - flexarray_t *front; - flexarray_t *back; - libxl__device *device; - int rc; - xs_transaction_t t = XBT_NULL; - libxl_domain_config d_config; - libxl_device_nic nic_saved; - libxl__domain_userdata_lock *lock = NULL; - - libxl_domain_config_init(&d_config); - libxl_device_nic_init(&nic_saved); - libxl_device_nic_copy(CTX, &nic_saved, nic); - - rc = libxl__device_nic_setdefault(gc, nic, domid, aodev->update_json); - if (rc) goto out; - - front = flexarray_make(gc, 16, 1); - back = flexarray_make(gc, 18, 1); - - if (nic->devid == -1) { - if ((nic->devid = libxl__device_nextid(gc, domid, "vif")) < 0) { - rc = ERROR_FAIL; - goto out; - } - } - - libxl__update_config_nic(gc, &nic_saved, nic); - - GCNEW(device); - rc = libxl__device_from_nic(gc, domid, nic, device); - if ( rc != 0 ) goto out; - - flexarray_append(back, "frontend-id"); - flexarray_append(back, GCSPRINTF("%d", domid)); - flexarray_append(back, "online"); - flexarray_append(back, "1"); - flexarray_append(back, "state"); - flexarray_append(back, GCSPRINTF("%d", XenbusStateInitialising)); - if (nic->script) - flexarray_append_pair(back, "script", - libxl__abs_path(gc, nic->script, - libxl__xen_script_dir_path())); - - if (nic->ifname) { - flexarray_append(back, "vifname"); - flexarray_append(back, nic->ifname); - } - - if (nic->coloft_forwarddev) { - flexarray_append(back, "forwarddev"); - flexarray_append(back, nic->coloft_forwarddev); - } - - flexarray_append(back, "mac"); - flexarray_append(back,GCSPRINTF(LIBXL_MAC_FMT, LIBXL_MAC_BYTES(nic->mac))); - if (nic->ip) { - flexarray_append(back, "ip"); - flexarray_append(back, libxl__strdup(gc, nic->ip)); - } - if (nic->gatewaydev) { - flexarray_append(back, "gatewaydev"); - flexarray_append(back, libxl__strdup(gc, nic->gatewaydev)); - } - - if (nic->rate_interval_usecs > 0) { - flexarray_append(back, "rate"); - flexarray_append(back, GCSPRINTF("%"PRIu64",%"PRIu32"", - nic->rate_bytes_per_interval, - nic->rate_interval_usecs)); - } - - flexarray_append(back, "bridge"); - flexarray_append(back, libxl__strdup(gc, nic->bridge)); - flexarray_append(back, "handle"); - flexarray_append(back, GCSPRINTF("%d", nic->devid)); - flexarray_append(back, "type"); - flexarray_append(back, libxl__strdup(gc, - libxl_nic_type_to_string(nic->nictype))); - - flexarray_append(front, "backend-id"); - flexarray_append(front, GCSPRINTF("%d", nic->backend_domid)); - flexarray_append(front, "state"); - flexarray_append(front, GCSPRINTF("%d", XenbusStateInitialising)); - flexarray_append(front, "handle"); - flexarray_append(front, GCSPRINTF("%d", nic->devid)); - flexarray_append(front, "mac"); - flexarray_append(front, GCSPRINTF( - LIBXL_MAC_FMT, LIBXL_MAC_BYTES(nic->mac))); - - if (aodev->update_json) { - lock = libxl__lock_domain_userdata(gc, domid); - if (!lock) { - rc = ERROR_LOCK_FAIL; - goto out; - } - - rc = libxl__get_domain_configuration(gc, domid, &d_config); - if (rc) goto out; - - DEVICE_ADD(nic, nics, domid, &nic_saved, COMPARE_DEVID, &d_config); - - rc = libxl__dm_check_start(gc, &d_config, domid); - if (rc) goto out; - } - - for (;;) { - rc = libxl__xs_transaction_start(gc, &t); - if (rc) goto out; - - rc = libxl__device_exists(gc, t, device); - if (rc < 0) goto out; - if (rc == 1) { /* already exists in xenstore */ - LOG(ERROR, "device already exists in xenstore"); - aodev->action = LIBXL__DEVICE_ACTION_ADD; /* for error message */ - rc = ERROR_DEVICE_EXISTS; - goto out; - } - - if (aodev->update_json) { - rc = libxl__set_domain_configuration(gc, domid, &d_config); - if (rc) goto out; - } - - libxl__device_generic_add(gc, t, device, - libxl__xs_kvs_of_flexarray(gc, back, - back->count), - libxl__xs_kvs_of_flexarray(gc, front, - front->count), - NULL); - - rc = libxl__xs_transaction_commit(gc, &t); - if (!rc) break; - if (rc < 0) goto out; - } - - aodev->dev = device; - aodev->action = LIBXL__DEVICE_ACTION_ADD; - libxl__wait_device_connection(egc, aodev); - - rc = 0; -out: - libxl__xs_transaction_abort(gc, &t); - if (lock) libxl__unlock_domain_userdata(lock); - libxl_device_nic_dispose(&nic_saved); - libxl_domain_config_dispose(&d_config); - aodev->rc = rc; - if (rc) aodev->callback(egc, aodev); - return; -} - -static int libxl__device_nic_from_xenstore(libxl__gc *gc, - const char *libxl_path, - libxl_device_nic *nic) -{ - const char *tmp; - int rc; - - libxl_device_nic_init(nic); - - tmp = READ_LIBXLDEV(gc, "handle"); - if (tmp) - nic->devid = atoi(tmp); - else - nic->devid = 0; - - /* nic->mtu = */ - - tmp = READ_LIBXLDEV(gc, "mac"); - if (tmp) { - rc = libxl__parse_mac(tmp, nic->mac); - if (rc) goto out; - } else { - memset(nic->mac, 0, sizeof(nic->mac)); - } - - nic->ip = READ_LIBXLDEV(NOGC, "ip"); - nic->bridge = READ_LIBXLDEV(NOGC, "bridge"); - nic->script = READ_LIBXLDEV(NOGC, "script"); - nic->coloft_forwarddev = READ_LIBXLDEV(NOGC, "forwarddev"); - - /* vif_ioemu nics use the same xenstore entries as vif interfaces */ - tmp = READ_LIBXLDEV(gc, "type"); - if (tmp) { - rc = libxl_nic_type_from_string(tmp, &nic->nictype); - if (rc) goto out; - } else { - nic->nictype = LIBXL_NIC_TYPE_VIF; - } - nic->model = NULL; /* XXX Only for TYPE_IOEMU */ - nic->ifname = NULL; /* XXX Only for TYPE_IOEMU */ - - rc = 0; - out: - return rc; -} - -int libxl_devid_to_device_nic(libxl_ctx *ctx, uint32_t domid, - int devid, libxl_device_nic *nic) -{ - GC_INIT(ctx); - char *libxl_dom_path, *libxl_path; - int rc = ERROR_FAIL; - - libxl_device_nic_init(nic); - libxl_dom_path = libxl__xs_libxl_path(gc, domid); - if (!libxl_dom_path) - goto out; - - libxl_path = GCSPRINTF("%s/device/vif/%d", libxl_dom_path, devid); - - rc = libxl__device_nic_from_xenstore(gc, libxl_path, nic); - if (rc) goto out; - - rc = 0; -out: - GC_FREE; - return rc; -} - -static int libxl__append_nic_list(libxl__gc *gc, - uint32_t domid, - libxl_device_nic **nics, - int *nnics) -{ - char *libxl_dir_path = NULL; - char **dir = NULL; - unsigned int n = 0; - libxl_device_nic *pnic = NULL, *pnic_end = NULL; - int rc; - - libxl_dir_path = GCSPRINTF("%s/device/vif", - libxl__xs_libxl_path(gc, domid)); - dir = libxl__xs_directory(gc, XBT_NULL, libxl_dir_path, &n); - if (dir && n) { - libxl_device_nic *tmp; - tmp = realloc(*nics, sizeof (libxl_device_nic) * (*nnics + n)); - if (tmp == NULL) - return ERROR_NOMEM; - *nics = tmp; - pnic = *nics + *nnics; - pnic_end = *nics + *nnics + n; - for (; pnic < pnic_end; pnic++, dir++) { - const char *p; - p = GCSPRINTF("%s/%s", libxl_dir_path, *dir); - rc = libxl__device_nic_from_xenstore(gc, p, pnic); - if (rc) goto out; - } - *nnics += n; - } - return 0; - - out: - return rc; -} - -libxl_device_nic *libxl_device_nic_list(libxl_ctx *ctx, uint32_t domid, int *num) -{ - GC_INIT(ctx); - libxl_device_nic *nics = NULL; - int rc; - - *num = 0; - - rc = libxl__append_nic_list(gc, domid, &nics, num); - if (rc) goto out_err; - - GC_FREE; - return nics; - -out_err: - LOG(ERROR, "Unable to list nics"); - while (*num) { - (*num)--; - libxl_device_nic_dispose(&nics[*num]); - } - free(nics); - return NULL; -} - -int libxl_device_nic_getinfo(libxl_ctx *ctx, uint32_t domid, - libxl_device_nic *nic, libxl_nicinfo *nicinfo) -{ - GC_INIT(ctx); - char *dompath, *nicpath, *libxl_path; - char *val; - int rc; - - dompath = libxl__xs_get_dompath(gc, domid); - nicinfo->devid = nic->devid; - - nicpath = GCSPRINTF("%s/device/vif/%d", dompath, nicinfo->devid); - libxl_path = GCSPRINTF("%s/device/vif/%d", - libxl__xs_libxl_path(gc, domid), nicinfo->devid); - nicinfo->backend = xs_read(ctx->xsh, XBT_NULL, - GCSPRINTF("%s/backend", libxl_path), NULL); - if (!nicinfo->backend) { - GC_FREE; - return ERROR_FAIL; - } - rc = libxl__backendpath_parse_domid(gc, nicinfo->backend, - &nicinfo->backend_id); - if (rc) goto out; - - val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/state", nicpath)); - nicinfo->state = val ? strtoul(val, NULL, 10) : -1; - val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/event-channel", nicpath)); - nicinfo->evtch = val ? strtoul(val, NULL, 10) : -1; - val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/tx-ring-ref", nicpath)); - nicinfo->rref_tx = val ? strtoul(val, NULL, 10) : -1; - val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/rx-ring-ref", nicpath)); - nicinfo->rref_rx = val ? strtoul(val, NULL, 10) : -1; - nicinfo->frontend = libxl__strdup(NOGC, nicpath); - nicinfo->frontend_id = domid; - - rc = 0; - out: - GC_FREE; - return rc; -} - -const char *libxl__device_nic_devname(libxl__gc *gc, - uint32_t domid, - uint32_t devid, - libxl_nic_type type) -{ - switch (type) { - case LIBXL_NIC_TYPE_VIF: - return GCSPRINTF(NETBACK_NIC_NAME, domid, devid); - case LIBXL_NIC_TYPE_VIF_IOEMU: - return GCSPRINTF(NETBACK_NIC_NAME TAP_DEVICE_SUFFIX, domid, devid); - default: - abort(); - } -} - -/******************************************************************************/ int libxl__device_console_add(libxl__gc *gc, uint32_t domid, libxl__device_console *console, libxl__domain_build_state *state, @@ -3660,14 +3224,21 @@ static int libxl__device_channel_from_xenstore(libxl__gc *gc, libxl_device_channel_init(channel); - /* READ_BACKEND is from libxl__device_nic_from_xenstore above */ - channel->name = READ_LIBXLDEV(NOGC, "name"); - tmp = READ_LIBXLDEV(gc, "connection"); + rc = libxl__xs_read_checked(NOGC, XBT_NULL, + GCSPRINTF("%s/name", libxl_path), + (const char **)(&channel->name)); + if (rc) goto out; + rc = libxl__xs_read_checked(NOGC, XBT_NULL, + GCSPRINTF("%s/connection", libxl_path), &tmp); + if (rc) goto out; if (!strcmp(tmp, "pty")) { channel->connection = LIBXL_CHANNEL_CONNECTION_PTY; } else if (!strcmp(tmp, "socket")) { channel->connection = LIBXL_CHANNEL_CONNECTION_SOCKET; - channel->u.socket.path = READ_LIBXLDEV(NOGC, "path"); + rc = libxl__xs_read_checked(NOGC, XBT_NULL, + GCSPRINTF("%s/path", libxl_path), + (const char **)(&channel->u.socket.path)); + if (rc) goto out; } else { rc = ERROR_INVAL; goto out; @@ -4027,10 +3598,6 @@ out: * libxl__add_disks * libxl_device_disk_remove * libxl_device_disk_destroy - * libxl_device_nic_add - * libxl__add_nics - * libxl_device_nic_remove - * libxl_device_nic_destroy * libxl_device_vkb_remove * libxl_device_vkb_destroy * libxl_device_vfb_remove @@ -4046,11 +3613,6 @@ LIBXL_DEFINE_DEVICE_ADD(disk) LIBXL_DEFINE_DEVICES_ADD(disk) LIBXL_DEFINE_DEVICE_REMOVE(disk) -/* nic */ -LIBXL_DEFINE_DEVICE_ADD(nic) -LIBXL_DEFINE_DEVICES_ADD(nic) -LIBXL_DEFINE_DEVICE_REMOVE(nic) - /* vkb */ LIBXL_DEFINE_DEVICE_REMOVE(vkb) @@ -7199,25 +6761,11 @@ static int libxl_device_disk_dm_needed(void *e, unsigned domid) elem->backend_domid == domid; } -static int libxl_device_nic_compare(libxl_device_nic *d1, - libxl_device_nic *d2) -{ - return COMPARE_DEVID(d1, d2); -} - -static void libxl_device_nic_update_config(libxl__gc *gc, void *d, void *s) -{ - libxl__update_config_nic(gc, d, s); -} - DEFINE_DEVICE_TYPE_STRUCT(disk, .merge = libxl_device_disk_merge, .dm_needed = libxl_device_disk_dm_needed, .skip_attach = 1 ); -DEFINE_DEVICE_TYPE_STRUCT(nic, - .update_config = libxl_device_nic_update_config -); /* * Local variables: diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c index 23b82e9..d7db9e9 100644 --- a/tools/libxl/libxl_create.c +++ b/tools/libxl/libxl_create.c @@ -772,7 +772,6 @@ static void initiate_domain_create(libxl__egc *egc, libxl_ctx *ctx = libxl__gc_owner(gc); uint32_t domid; int i, ret; - size_t last_devid = -1; bool pod_enabled = false; /* convenience aliases */ @@ -932,25 +931,9 @@ static void initiate_domain_create(libxl__egc *egc, * Make two runs over configured NICs in order to avoid duplicate IDs * in case the caller partially assigned IDs. */ - for (i = 0; i < d_config->num_nics; i++) { - /* We have to init the nic here, because we still haven't - * called libxl_device_nic_add when domcreate_launch_dm gets called, - * but qemu needs the nic information to be complete. - */ - ret = libxl__device_nic_setdefault(gc, &d_config->nics[i], domid, - false); - if (ret) { - LOG(ERROR, "Unable to set nic defaults for nic %d", i); - goto error_out; - } - - if (d_config->nics[i].devid > last_devid) - last_devid = d_config->nics[i].devid; - } - for (i = 0; i < d_config->num_nics; i++) { - if (d_config->nics[i].devid < 0) - d_config->nics[i].devid = ++last_devid; - } + ret = libxl__device_nic_set_devids(gc, d_config, domid); + if (ret) + goto error_out; if (restore_fd >= 0 || dcs->domid_soft_reset != INVALID_DOMID) { LOG(DEBUG, "restoring, not running bootloader"); diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h index cdc23e2..0e78c12 100644 --- a/tools/libxl/libxl_internal.h +++ b/tools/libxl/libxl_internal.h @@ -1288,7 +1288,6 @@ bool libxl__xswait_inuse(const libxl__xswait_state *ss); int libxl__xswait_start(libxl__gc*, libxl__xswait_state*); - /* * libxl__ev_devstate - waits a given time for a device to * reach a given state. Follows the libxl_ev_* conventions. @@ -3679,6 +3678,10 @@ struct libxl__domain_create_state { libxl__multidev multidev; }; +_hidden int libxl__device_nic_set_devids(libxl__gc *gc, + libxl_domain_config *d_config, + uint32_t domid); + /*----- Domain suspend (save) functions -----*/ /* calls dss->callback when done */ diff --git a/tools/libxl/libxl_nic.c b/tools/libxl/libxl_nic.c new file mode 100644 index 0000000..ff1834f --- /dev/null +++ b/tools/libxl/libxl_nic.c @@ -0,0 +1,554 @@ +/* + * Copyright (C) 2016 SUSE Linux GmbH + * Author Juergen Gross <jgross@xxxxxxxx> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; version 2.1 only. with the special + * exception on linking described in file LICENSE. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + */ + +#include "libxl_osdeps.h" + +#include "libxl_internal.h" + +int libxl_mac_to_device_nic(libxl_ctx *ctx, uint32_t domid, + const char *mac, libxl_device_nic *nic) +{ + libxl_device_nic *nics; + int nb, rc, i; + libxl_mac mac_n; + + rc = libxl__parse_mac(mac, mac_n); + if (rc) + return rc; + + nics = libxl_device_nic_list(ctx, domid, &nb); + if (!nics) + return ERROR_FAIL; + + memset(nic, 0, sizeof (libxl_device_nic)); + + rc = ERROR_INVAL; + for (i = 0; i < nb; ++i) { + if (!libxl__compare_macs(&mac_n, &nics[i].mac)) { + *nic = nics[i]; + rc = 0; + i++; /* Do not dispose this NIC on exit path */ + break; + } + libxl_device_nic_dispose(&nics[i]); + } + + for (; i<nb; i++) + libxl_device_nic_dispose(&nics[i]); + + free(nics); + return rc; +} + +int libxl__device_nic_setdefault(libxl__gc *gc, libxl_device_nic *nic, + uint32_t domid, bool hotplug) +{ + int rc; + + if (!nic->mtu) + nic->mtu = 1492; + if (!nic->model) { + nic->model = strdup("rtl8139"); + if (!nic->model) return ERROR_NOMEM; + } + if (libxl__mac_is_default(&nic->mac)) { + const uint8_t *r; + libxl_uuid uuid; + + libxl_uuid_generate(&uuid); + r = libxl_uuid_bytearray(&uuid); + + nic->mac[0] = 0x00; + nic->mac[1] = 0x16; + nic->mac[2] = 0x3e; + nic->mac[3] = r[0] & 0x7f; + nic->mac[4] = r[1]; + nic->mac[5] = r[2]; + } + if (!nic->bridge) { + nic->bridge = strdup("xenbr0"); + if (!nic->bridge) return ERROR_NOMEM; + } + if ( !nic->script && asprintf(&nic->script, "%s/vif-bridge", + libxl__xen_script_dir_path()) < 0 ) + return ERROR_FAIL; + + rc = libxl__resolve_domid(gc, nic->backend_domname, &nic->backend_domid); + if (rc < 0) return rc; + + switch (libxl__domain_type(gc, domid)) { + case LIBXL_DOMAIN_TYPE_HVM: + if (!nic->nictype) { + if (hotplug || + (libxl__device_model_version_running(gc, domid) == + LIBXL_DEVICE_MODEL_VERSION_NONE)) + nic->nictype = LIBXL_NIC_TYPE_VIF; + else + nic->nictype = LIBXL_NIC_TYPE_VIF_IOEMU; + } + break; + case LIBXL_DOMAIN_TYPE_PV: + if (nic->nictype == LIBXL_NIC_TYPE_VIF_IOEMU) { + LOG(ERROR, "trying to create PV guest with an emulated interface"); + return ERROR_INVAL; + } + nic->nictype = LIBXL_NIC_TYPE_VIF; + break; + case LIBXL_DOMAIN_TYPE_INVALID: + return ERROR_FAIL; + default: + abort(); + } + + return rc; +} + +static int libxl__device_from_nic(libxl__gc *gc, uint32_t domid, + libxl_device_nic *nic, + libxl__device *device) +{ + device->backend_devid = nic->devid; + device->backend_domid = nic->backend_domid; + device->backend_kind = LIBXL__DEVICE_KIND_VIF; + device->devid = nic->devid; + device->domid = domid; + device->kind = LIBXL__DEVICE_KIND_VIF; + + return 0; +} + +static void libxl__update_config_nic(libxl__gc *gc, libxl_device_nic *dst, + const libxl_device_nic *src) +{ + dst->devid = src->devid; + dst->nictype = src->nictype; + libxl_mac_copy(CTX, &dst->mac, &src->mac); +} + +static void libxl__device_nic_add(libxl__egc *egc, uint32_t domid, + libxl_device_nic *nic, + libxl__ao_device *aodev) +{ + STATE_AO_GC(aodev->ao); + flexarray_t *front; + flexarray_t *back; + libxl__device *device; + int rc; + xs_transaction_t t = XBT_NULL; + libxl_domain_config d_config; + libxl_device_nic nic_saved; + libxl__domain_userdata_lock *lock = NULL; + + libxl_domain_config_init(&d_config); + libxl_device_nic_init(&nic_saved); + libxl_device_nic_copy(CTX, &nic_saved, nic); + + rc = libxl__device_nic_setdefault(gc, nic, domid, aodev->update_json); + if (rc) goto out; + + front = flexarray_make(gc, 16, 1); + back = flexarray_make(gc, 18, 1); + + if (nic->devid == -1) { + if ((nic->devid = libxl__device_nextid(gc, domid, "vif")) < 0) { + rc = ERROR_FAIL; + goto out; + } + } + + libxl__update_config_nic(gc, &nic_saved, nic); + + GCNEW(device); + rc = libxl__device_from_nic(gc, domid, nic, device); + if ( rc != 0 ) goto out; + + flexarray_append(back, "frontend-id"); + flexarray_append(back, GCSPRINTF("%d", domid)); + flexarray_append(back, "online"); + flexarray_append(back, "1"); + flexarray_append(back, "state"); + flexarray_append(back, GCSPRINTF("%d", XenbusStateInitialising)); + if (nic->script) + flexarray_append_pair(back, "script", + libxl__abs_path(gc, nic->script, + libxl__xen_script_dir_path())); + + if (nic->ifname) { + flexarray_append(back, "vifname"); + flexarray_append(back, nic->ifname); + } + + if (nic->coloft_forwarddev) { + flexarray_append(back, "forwarddev"); + flexarray_append(back, nic->coloft_forwarddev); + } + + flexarray_append(back, "mac"); + flexarray_append(back,GCSPRINTF(LIBXL_MAC_FMT, LIBXL_MAC_BYTES(nic->mac))); + if (nic->ip) { + flexarray_append(back, "ip"); + flexarray_append(back, libxl__strdup(gc, nic->ip)); + } + if (nic->gatewaydev) { + flexarray_append(back, "gatewaydev"); + flexarray_append(back, libxl__strdup(gc, nic->gatewaydev)); + } + + if (nic->rate_interval_usecs > 0) { + flexarray_append(back, "rate"); + flexarray_append(back, GCSPRINTF("%"PRIu64",%"PRIu32"", + nic->rate_bytes_per_interval, + nic->rate_interval_usecs)); + } + + flexarray_append(back, "bridge"); + flexarray_append(back, libxl__strdup(gc, nic->bridge)); + flexarray_append(back, "handle"); + flexarray_append(back, GCSPRINTF("%d", nic->devid)); + flexarray_append(back, "type"); + flexarray_append(back, libxl__strdup(gc, + libxl_nic_type_to_string(nic->nictype))); + + flexarray_append(front, "backend-id"); + flexarray_append(front, GCSPRINTF("%d", nic->backend_domid)); + flexarray_append(front, "state"); + flexarray_append(front, GCSPRINTF("%d", XenbusStateInitialising)); + flexarray_append(front, "handle"); + flexarray_append(front, GCSPRINTF("%d", nic->devid)); + flexarray_append(front, "mac"); + flexarray_append(front, GCSPRINTF( + LIBXL_MAC_FMT, LIBXL_MAC_BYTES(nic->mac))); + + if (aodev->update_json) { + lock = libxl__lock_domain_userdata(gc, domid); + if (!lock) { + rc = ERROR_LOCK_FAIL; + goto out; + } + + rc = libxl__get_domain_configuration(gc, domid, &d_config); + if (rc) goto out; + + DEVICE_ADD(nic, nics, domid, &nic_saved, COMPARE_DEVID, &d_config); + + rc = libxl__dm_check_start(gc, &d_config, domid); + if (rc) goto out; + } + + for (;;) { + rc = libxl__xs_transaction_start(gc, &t); + if (rc) goto out; + + rc = libxl__device_exists(gc, t, device); + if (rc < 0) goto out; + if (rc == 1) { /* already exists in xenstore */ + LOG(ERROR, "device already exists in xenstore"); + aodev->action = LIBXL__DEVICE_ACTION_ADD; /* for error message */ + rc = ERROR_DEVICE_EXISTS; + goto out; + } + + if (aodev->update_json) { + rc = libxl__set_domain_configuration(gc, domid, &d_config); + if (rc) goto out; + } + + libxl__device_generic_add(gc, t, device, + libxl__xs_kvs_of_flexarray(gc, back, + back->count), + libxl__xs_kvs_of_flexarray(gc, front, + front->count), + NULL); + + rc = libxl__xs_transaction_commit(gc, &t); + if (!rc) break; + if (rc < 0) goto out; + } + + aodev->dev = device; + aodev->action = LIBXL__DEVICE_ACTION_ADD; + libxl__wait_device_connection(egc, aodev); + + rc = 0; +out: + libxl__xs_transaction_abort(gc, &t); + if (lock) libxl__unlock_domain_userdata(lock); + libxl_device_nic_dispose(&nic_saved); + libxl_domain_config_dispose(&d_config); + aodev->rc = rc; + if (rc) aodev->callback(egc, aodev); + return; +} + +static int libxl__device_nic_from_xenstore(libxl__gc *gc, + const char *libxl_path, + libxl_device_nic *nic) +{ + const char *tmp; + int rc; + + libxl_device_nic_init(nic); + + rc = libxl__xs_read_checked(gc, XBT_NULL, + GCSPRINTF("%s/handle", libxl_path), &tmp); + if (rc) goto out; + if (tmp) + nic->devid = atoi(tmp); + else + nic->devid = 0; + + /* nic->mtu = */ + + rc = libxl__xs_read_checked(gc, XBT_NULL, + GCSPRINTF("%s/mac", libxl_path), &tmp); + if (rc) goto out; + if (tmp) { + rc = libxl__parse_mac(tmp, nic->mac); + if (rc) goto out; + } else { + memset(nic->mac, 0, sizeof(nic->mac)); + } + + rc = libxl__xs_read_checked(gc, XBT_NULL, + GCSPRINTF("%s/ip", libxl_path), + (const char **)(&nic->ip)); + if (rc) goto out; + rc = libxl__xs_read_checked(gc, XBT_NULL, + GCSPRINTF("%s/bridge", libxl_path), + (const char **)(&nic->bridge)); + if (rc) goto out; + rc = libxl__xs_read_checked(gc, XBT_NULL, + GCSPRINTF("%s/script", libxl_path), + (const char **)(&nic->script)); + if (rc) goto out; + rc = libxl__xs_read_checked(gc, XBT_NULL, + GCSPRINTF("%s/forwarddev", libxl_path), + (const char **)(&nic->coloft_forwarddev)); + if (rc) goto out; + + /* vif_ioemu nics use the same xenstore entries as vif interfaces */ + rc = libxl__xs_read_checked(gc, XBT_NULL, + GCSPRINTF("%s/type", libxl_path), &tmp); + if (rc) goto out; + if (tmp) { + rc = libxl_nic_type_from_string(tmp, &nic->nictype); + if (rc) goto out; + } else { + nic->nictype = LIBXL_NIC_TYPE_VIF; + } + nic->model = NULL; /* XXX Only for TYPE_IOEMU */ + nic->ifname = NULL; /* XXX Only for TYPE_IOEMU */ + + rc = 0; + out: + return rc; +} + +int libxl_devid_to_device_nic(libxl_ctx *ctx, uint32_t domid, + int devid, libxl_device_nic *nic) +{ + GC_INIT(ctx); + char *libxl_dom_path, *libxl_path; + int rc = ERROR_FAIL; + + libxl_device_nic_init(nic); + libxl_dom_path = libxl__xs_libxl_path(gc, domid); + if (!libxl_dom_path) + goto out; + + libxl_path = GCSPRINTF("%s/device/vif/%d", libxl_dom_path, devid); + + rc = libxl__device_nic_from_xenstore(gc, libxl_path, nic); + if (rc) goto out; + + rc = 0; +out: + GC_FREE; + return rc; +} + +static int libxl__append_nic_list(libxl__gc *gc, + uint32_t domid, + libxl_device_nic **nics, + int *nnics) +{ + char *libxl_dir_path = NULL; + char **dir = NULL; + unsigned int n = 0; + libxl_device_nic *pnic = NULL, *pnic_end = NULL; + int rc; + + libxl_dir_path = GCSPRINTF("%s/device/vif", + libxl__xs_libxl_path(gc, domid)); + dir = libxl__xs_directory(gc, XBT_NULL, libxl_dir_path, &n); + if (dir && n) { + libxl_device_nic *tmp; + tmp = realloc(*nics, sizeof (libxl_device_nic) * (*nnics + n)); + if (tmp == NULL) + return ERROR_NOMEM; + *nics = tmp; + pnic = *nics + *nnics; + pnic_end = *nics + *nnics + n; + for (; pnic < pnic_end; pnic++, dir++) { + const char *p; + p = GCSPRINTF("%s/%s", libxl_dir_path, *dir); + rc = libxl__device_nic_from_xenstore(gc, p, pnic); + if (rc) goto out; + } + *nnics += n; + } + return 0; + + out: + return rc; +} + +libxl_device_nic *libxl_device_nic_list(libxl_ctx *ctx, uint32_t domid, int *num) +{ + GC_INIT(ctx); + libxl_device_nic *nics = NULL; + int rc; + + *num = 0; + + rc = libxl__append_nic_list(gc, domid, &nics, num); + if (rc) goto out_err; + + GC_FREE; + return nics; + +out_err: + LOG(ERROR, "Unable to list nics"); + while (*num) { + (*num)--; + libxl_device_nic_dispose(&nics[*num]); + } + free(nics); + return NULL; +} + +int libxl_device_nic_getinfo(libxl_ctx *ctx, uint32_t domid, + libxl_device_nic *nic, libxl_nicinfo *nicinfo) +{ + GC_INIT(ctx); + char *dompath, *nicpath, *libxl_path; + char *val; + int rc; + + dompath = libxl__xs_get_dompath(gc, domid); + nicinfo->devid = nic->devid; + + nicpath = GCSPRINTF("%s/device/vif/%d", dompath, nicinfo->devid); + libxl_path = GCSPRINTF("%s/device/vif/%d", + libxl__xs_libxl_path(gc, domid), nicinfo->devid); + nicinfo->backend = xs_read(ctx->xsh, XBT_NULL, + GCSPRINTF("%s/backend", libxl_path), NULL); + if (!nicinfo->backend) { + GC_FREE; + return ERROR_FAIL; + } + rc = libxl__backendpath_parse_domid(gc, nicinfo->backend, + &nicinfo->backend_id); + if (rc) goto out; + + val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/state", nicpath)); + nicinfo->state = val ? strtoul(val, NULL, 10) : -1; + val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/event-channel", nicpath)); + nicinfo->evtch = val ? strtoul(val, NULL, 10) : -1; + val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/tx-ring-ref", nicpath)); + nicinfo->rref_tx = val ? strtoul(val, NULL, 10) : -1; + val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/rx-ring-ref", nicpath)); + nicinfo->rref_rx = val ? strtoul(val, NULL, 10) : -1; + nicinfo->frontend = libxl__strdup(NOGC, nicpath); + nicinfo->frontend_id = domid; + + rc = 0; + out: + GC_FREE; + return rc; +} + +const char *libxl__device_nic_devname(libxl__gc *gc, + uint32_t domid, + uint32_t devid, + libxl_nic_type type) +{ + switch (type) { + case LIBXL_NIC_TYPE_VIF: + return GCSPRINTF(NETBACK_NIC_NAME, domid, devid); + case LIBXL_NIC_TYPE_VIF_IOEMU: + return GCSPRINTF(NETBACK_NIC_NAME TAP_DEVICE_SUFFIX, domid, devid); + default: + abort(); + } +} + +static int libxl_device_nic_compare(libxl_device_nic *d1, + libxl_device_nic *d2) +{ + return COMPARE_DEVID(d1, d2); +} + +static void libxl_device_nic_update_config(libxl__gc *gc, void *d, void *s) +{ + libxl__update_config_nic(gc, d, s); +} + +int libxl__device_nic_set_devids(libxl__gc *gc, libxl_domain_config *d_config, + uint32_t domid) +{ + int ret = 0; + int i; + size_t last_devid = -1; + + for (i = 0; i < d_config->num_nics; i++) { + /* We have to init the nic here, because we still haven't + * called libxl_device_nic_add when domcreate_launch_dm gets called, + * but qemu needs the nic information to be complete. + */ + ret = libxl__device_nic_setdefault(gc, &d_config->nics[i], domid, + false); + if (ret) { + LOG(ERROR, "Unable to set nic defaults for nic %d", i); + goto out; + } + + if (d_config->nics[i].devid > last_devid) + last_devid = d_config->nics[i].devid; + } + for (i = 0; i < d_config->num_nics; i++) { + if (d_config->nics[i].devid < 0) + d_config->nics[i].devid = ++last_devid; + } + +out: + return ret; +} + +LIBXL_DEFINE_DEVICE_ADD(nic) +LIBXL_DEFINE_DEVICES_ADD(nic) +LIBXL_DEFINE_DEVICE_REMOVE(nic) + +DEFINE_DEVICE_TYPE_STRUCT(nic, + .update_config = libxl_device_nic_update_config +); + +/* + * Local variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/tools/libxl/libxl_utils.c b/tools/libxl/libxl_utils.c index b748555..49cbaa5 100644 --- a/tools/libxl/libxl_utils.c +++ b/tools/libxl/libxl_utils.c @@ -598,41 +598,6 @@ int libxl_pipe(libxl_ctx *ctx, int pipes[2]) return ret; } -int libxl_mac_to_device_nic(libxl_ctx *ctx, uint32_t domid, - const char *mac, libxl_device_nic *nic) -{ - libxl_device_nic *nics; - int nb, rc, i; - libxl_mac mac_n; - - rc = libxl__parse_mac(mac, mac_n); - if (rc) - return rc; - - nics = libxl_device_nic_list(ctx, domid, &nb); - if (!nics) - return ERROR_FAIL; - - memset(nic, 0, sizeof (libxl_device_nic)); - - rc = ERROR_INVAL; - for (i = 0; i < nb; ++i) { - if (!libxl__compare_macs(&mac_n, &nics[i].mac)) { - *nic = nics[i]; - rc = 0; - i++; /* Do not dispose this NIC on exit path */ - break; - } - libxl_device_nic_dispose(&nics[i]); - } - - for (; i<nb; i++) - libxl_device_nic_dispose(&nics[i]); - - free(nics); - return rc; -} - int libxl_bitmap_alloc(libxl_ctx *ctx, libxl_bitmap *bitmap, int n_bits) { GC_INIT(ctx); -- 2.6.6 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx https://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |