[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

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.