[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH v4 4/4] libxl: call hotplug scripts from libxl for vif



As the previous change already introduces most of needed machinery to
call hotplug scripts from libxl, this only adds the necessary bits to
call this scripts for vif interfaces also.

libxl_device_nic_add has been changed to make use of the new event
functionality, and the necessary vif hotplug code has been added. No
changes where needed in the teardown part, since it uses exactly the
same code introduced for vbd.

Network devices are added after the domain model has launched, since
we need the tap inteface to be present when the hotplug script
is executed.

PV nic devices are set to LIBXL_NIC_TYPE_VIF, since the default value
is LIBXL_NIC_TYPE_IOEMU regardless of the guest type.

Changes since v3:

 * Entangle network device addition with the new AO domain creation,
   assute that network interfaces are always added after device model
   creation. Make sure the same happens for stubdomain network
   interfaces.

 * Make use of the new functions LOG, LOGE, GCNEW_ARRAY...

 * Remove disable_xl_vif_scripts, since now it's a global option that
   affects both vifs and disks hotplug scripts.

 * Added proper handling of IOEMU type of nics, we need to
   execute two different hotplug scripts. Now both scripts are
   chained, and one is executed after the other has finished (we call
   the next script from the callback of the previous one). Previously
   we used to launch both scripts simultaneously.

Changes since v2:

 * Added fancy functions to fetch tap and vif names, now the prefix of
   the tap device has been saved in a constant, called
   TAP_DEVICE_PREFIX.

 * Wait for timeout before nuking frontend xenstore entries.

 * Changed disable_vif_scripts to disable_xl_vif_scripts, it's easier
   to understand.

 * Default nic type set by libxl__device_nic_setdefault is VIF now
   (was IOEMU).

 * Save nic type and udev script exection inside
   /libxl/devices/<domid>/nic/<devid>/ instead of saving it in the
   backend path.

Changes since v1:

 * Propagated changes from previous patch (disable_udev and
   libxl_device_nic_add switch).

 * Modified udev rules to add the new env variable.

 * Added support for named interfaces.

Cc: Ian Jackson <ian.jackson@xxxxxxxxxxxxx>
Signed-off-by: Roger Pau Monne <roger.pau@xxxxxxxxxx>
---
 tools/hotplug/Linux/xen-backend.rules |    6 +-
 tools/libxl/libxl.c                   |  122 ++++---------------------------
 tools/libxl/libxl.h                   |    3 +-
 tools/libxl/libxl_create.c            |   78 ++++++++++++++++++--
 tools/libxl/libxl_device.c            |  122 +++++++++++++++++++++++++++++++
 tools/libxl/libxl_dm.c                |   64 +++++++++++++++-
 tools/libxl/libxl_internal.h          |    9 ++
 tools/libxl/libxl_linux.c             |  130 ++++++++++++++++++++++++++++++++-
 tools/libxl/xl_cmdimpl.c              |    2 +-
 9 files changed, 412 insertions(+), 124 deletions(-)

diff --git a/tools/hotplug/Linux/xen-backend.rules 
b/tools/hotplug/Linux/xen-backend.rules
index d55ff11..c591a3f 100644
--- a/tools/hotplug/Linux/xen-backend.rules
+++ b/tools/hotplug/Linux/xen-backend.rules
@@ -2,8 +2,8 @@ SUBSYSTEM=="xen-backend", KERNEL=="tap*", ENV{UDEV_CALL}="1", 
RUN+="/etc/xen/scr
 SUBSYSTEM=="xen-backend", KERNEL=="vbd*", ENV{UDEV_CALL}="1", 
RUN+="/etc/xen/scripts/block $env{ACTION}"
 SUBSYSTEM=="xen-backend", KERNEL=="vtpm*", RUN+="/etc/xen/scripts/vtpm 
$env{ACTION}"
 SUBSYSTEM=="xen-backend", KERNEL=="vif2-*", RUN+="/etc/xen/scripts/vif2 
$env{ACTION}"
-SUBSYSTEM=="xen-backend", KERNEL=="vif-*", ACTION=="online", 
RUN+="/etc/xen/scripts/vif-setup online type_if=vif"
-SUBSYSTEM=="xen-backend", KERNEL=="vif-*", ACTION=="offline", 
RUN+="/etc/xen/scripts/vif-setup offline type_if=vif"
+SUBSYSTEM=="xen-backend", KERNEL=="vif-*", ENV{UDEV_CALL}="1", 
ACTION=="online", RUN+="/etc/xen/scripts/vif-setup online type_if=vif"
+SUBSYSTEM=="xen-backend", KERNEL=="vif-*", ENV{UDEV_CALL}="1", 
ACTION=="offline", RUN+="/etc/xen/scripts/vif-setup offline type_if=vif"
 SUBSYSTEM=="xen-backend", KERNEL=="vscsi*", RUN+="/etc/xen/scripts/vscsi 
$env{ACTION}"
 SUBSYSTEM=="xen-backend", ACTION=="remove", ENV{UDEV_CALL}="1", 
RUN+="/etc/xen/scripts/xen-hotplug-cleanup"
 KERNEL=="evtchn", NAME="xen/%k"
@@ -13,4 +13,4 @@ KERNEL=="blktap-control", NAME="xen/blktap-2/control", 
MODE="0600"
 KERNEL=="gntdev", NAME="xen/%k", MODE="0600"
 KERNEL=="pci_iomul", NAME="xen/%k", MODE="0600"
 KERNEL=="tapdev[a-z]*", NAME="xen/blktap-2/tapdev%m", MODE="0600"
-SUBSYSTEM=="net", KERNEL=="vif*-emu", ACTION=="add", 
RUN+="/etc/xen/scripts/vif-setup $env{ACTION} type_if=tap"
+SUBSYSTEM=="net", KERNEL=="vif*-emu", ACTION=="add", ENV{UDEV_CALL}="1", 
RUN+="/etc/xen/scripts/vif-setup $env{ACTION} type_if=tap"
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index b438fbf..5a681b1 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -1634,123 +1634,29 @@ int libxl__device_nic_setdefault(libxl__gc *gc, 
libxl_device_nic *nic)
                                   libxl__xen_script_dir_path()) < 0 )
         return ERROR_FAIL;
     if (!nic->nictype)
-        nic->nictype = LIBXL_NIC_TYPE_IOEMU;
+        nic->nictype = LIBXL_NIC_TYPE_VIF;
     return 0;
 }
 
-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;
-}
-
-int libxl_device_nic_add(libxl_ctx *ctx, uint32_t domid, libxl_device_nic *nic)
+int libxl_device_nic_add(libxl_ctx *ctx, uint32_t domid, libxl_device_nic *nic,
+                         const libxl_asyncop_how *ao_how)
 {
-    GC_INIT(ctx);
-    flexarray_t *front;
-    flexarray_t *back;
-    libxl__device device;
-    char *dompath, **l;
-    unsigned int nb, rc;
-
-    rc = libxl__device_nic_setdefault(gc, nic);
-    if (rc) goto out;
+    AO_CREATE(ctx, domid, ao_how);
+    libxl__ao_device *device;
+    int rc;
 
-    front = flexarray_make(16, 1);
-    if (!front) {
-        rc = ERROR_NOMEM;
+    GCNEW(device);
+    libxl__init_ao_device(device, ao, NULL);
+    device->callback = libxl__device_cb;
+    rc = libxl__device_nic_add(egc, domid, nic, device);
+    if (rc) {
+        LOGE(ERROR, "unable to add nic %s", nic->ifname);
         goto out;
     }
-    back = flexarray_make(16, 1);
-    if (!back) {
-        rc = ERROR_NOMEM;
-        goto out_free;
-    }
-
-    if (nic->devid == -1) {
-        if (!(dompath = libxl__xs_get_dompath(gc, domid))) {
-            rc = ERROR_FAIL;
-            goto out_free;
-        }
-        if (!(l = libxl__xs_directory(gc, XBT_NULL,
-                                     libxl__sprintf(gc, "%s/device/vif", 
dompath), &nb))) {
-            nic->devid = 0;
-        } else {
-            nic->devid = strtoul(l[nb - 1], NULL, 10) + 1;
-        }
-    }
-
-    rc = libxl__device_from_nic(gc, domid, nic, &device);
-    if ( rc != 0 ) goto out_free;
-
-    flexarray_append(back, "frontend-id");
-    flexarray_append(back, libxl__sprintf(gc, "%d", domid));
-    flexarray_append(back, "online");
-    flexarray_append(back, "1");
-    flexarray_append(back, "state");
-    flexarray_append(back, libxl__sprintf(gc, "%d", 1));
-    if (nic->script) {
-        flexarray_append(back, "script");
-        flexarray_append(back, nic->script[0]=='/' ? nic->script
-                         : libxl__sprintf(gc, "%s/%s",
-                                          libxl__xen_script_dir_path(),
-                                          nic->script));
-    }
-
-    if (nic->ifname) {
-        flexarray_append(back, "vifname");
-        flexarray_append(back, nic->ifname);
-    }
-
-    flexarray_append(back, "mac");
-    flexarray_append(back,libxl__sprintf(gc,
-                                    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->rate_interval_usecs > 0) {
-        flexarray_append(back, "rate");
-        flexarray_append(back, libxl__sprintf(gc, "%"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, libxl__sprintf(gc, "%d", nic->devid));
-
-    flexarray_append(front, "backend-id");
-    flexarray_append(front, libxl__sprintf(gc, "%d", nic->backend_domid));
-    flexarray_append(front, "state");
-    flexarray_append(front, libxl__sprintf(gc, "%d", 1));
-    flexarray_append(front, "handle");
-    flexarray_append(front, libxl__sprintf(gc, "%d", nic->devid));
-    flexarray_append(front, "mac");
-    flexarray_append(front, libxl__sprintf(gc,
-                                    LIBXL_MAC_FMT, LIBXL_MAC_BYTES(nic->mac)));
-    libxl__device_generic_add(gc, &device,
-                             libxl__xs_kvs_of_flexarray(gc, back, back->count),
-                             libxl__xs_kvs_of_flexarray(gc, front, 
front->count));
-
-    /* FIXME: wait for plug */
-    rc = 0;
-out_free:
-    flexarray_free(back);
-    flexarray_free(front);
 out:
-    GC_FREE;
-    return rc;
+    if (rc) return AO_ABORT(rc);
+    return AO_INPROGRESS;
 }
 
 int libxl_device_nic_remove(libxl_ctx *ctx, uint32_t domid,
diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h
index 0ab1531..6689baf 100644
--- a/tools/libxl/libxl.h
+++ b/tools/libxl/libxl.h
@@ -688,7 +688,8 @@ char * libxl_device_disk_local_attach(libxl_ctx *ctx, 
libxl_device_disk *disk);
 int libxl_device_disk_local_detach(libxl_ctx *ctx, libxl_device_disk *disk);
 
 /* Network Interfaces */
-int libxl_device_nic_add(libxl_ctx *ctx, uint32_t domid, libxl_device_nic 
*nic);
+int libxl_device_nic_add(libxl_ctx *ctx, uint32_t domid, libxl_device_nic *nic,
+                         const libxl_asyncop_how *ao_how);
 int libxl_device_nic_remove(libxl_ctx *ctx, uint32_t domid,
                             libxl_device_nic *nic,
                             const libxl_asyncop_how *ao_how);
diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c
index db58fd0..69f4e4d 100644
--- a/tools/libxl/libxl_create.c
+++ b/tools/libxl/libxl_create.c
@@ -605,6 +605,11 @@ static void domcreate_disk_connected(libxl__egc *egc,
 static void domcreate_console_available(libxl__egc *egc,
                                         libxl__domain_create_state *dcs);
 
+static void domcreate_nics_connected(libxl__egc *egc, libxl__ao_device *aorm);
+
+static void domcreate_attach_pci(libxl__egc *egc,
+                                 libxl__domain_create_state *dcs);
+
 /* Our own function to clean up and call the user's callback.
  * The final call in the sequence if domain creation is successful. */
 static void domcreate_complete(libxl__egc *egc,
@@ -747,13 +752,11 @@ static void domcreate_bootloader_done(libxl__egc *egc,
         }
     }
     for (i = 0; i < d_config->num_vifs; i++) {
-        ret = libxl_device_nic_add(ctx, domid, &d_config->vifs[i]);
-        if (ret) {
-            LIBXL__LOG(ctx, LIBXL__LOG_ERROR,
-                       "cannot add nic %d to domain: %d", i, ret);
-            ret = ERROR_FAIL;
-            goto error_out;
-        }
+        /* We have to init the nic here, because we still haven't
+         * called libxl_device_nic_add at this point, but qemu needs
+         * the nic information to be complete.
+         */
+        libxl__device_nic_setdefault(gc, &d_config->vifs[i]);
     }
     return;
 
@@ -885,6 +888,67 @@ static void domcreate_devmodel_started(libxl__egc *egc,
         }
     }
 
+    /* Plug nic interfaces */
+    if (!ret && d_config->num_vifs > 0) {
+        /* Attach nics */
+        GCNEW_ARRAY(dcs->devices, d_config->num_vifs);
+        dcs->num_devices = d_config->num_vifs;
+        for (i = 0; i < d_config->num_vifs; i++) {
+            libxl__init_ao_device(&dcs->devices[i], ao, &dcs->devices);
+            dcs->devices[i].callback = domcreate_nics_connected;
+            ret = libxl__device_nic_add(egc, domid, &d_config->vifs[i],
+                                        &dcs->devices[i]);
+            if (ret) {
+                LOGE(ERROR, "cannot add nic %d to domain: %d", i, domid);
+                ret = ERROR_FAIL;
+                goto error_out;
+            }
+        }
+        return;
+    }
+
+    domcreate_attach_pci(egc, dcs);
+    return;
+
+error_out:
+    assert(ret);
+    domcreate_complete(egc, dcs, ret);
+}
+
+static void domcreate_nics_connected(libxl__egc *egc, libxl__ao_device *aorm)
+{
+    STATE_AO_GC(aorm->ao);
+    libxl__domain_create_state *dcs = CONTAINER_OF(aorm->base, *dcs, devices);
+    int last, ret = 0;
+
+    ret = libxl__ao_device_check_last(gc, aorm, dcs->devices,
+                                      dcs->num_devices, &last);
+
+    if (!last) return;
+    if (last && ret) {
+        LOGE(ERROR, "error connecting nics devices");
+        goto error_out;
+    }
+
+    domcreate_attach_pci(egc, dcs);
+    return;
+
+error_out:
+    assert(ret);
+    domcreate_complete(egc, dcs, ret);
+}
+
+static void domcreate_attach_pci(libxl__egc *egc,
+                                 libxl__domain_create_state *dcs)
+{
+    STATE_AO_GC(dcs->ao);
+    int i, ret = 0;
+    libxl_ctx *ctx = CTX;
+    int domid = dcs->guest_domid;
+
+    /* convenience aliases */
+    libxl_domain_config *const d_config = dcs->guest_config;
+
     for (i = 0; i < d_config->num_pcidevs; i++)
         libxl__device_pci_add(gc, domid, &d_config->pcidevs[i], 1);
 
diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c
index 275ab43..6b431a2 100644
--- a/tools/libxl/libxl_device.c
+++ b/tools/libxl/libxl_device.c
@@ -191,6 +191,20 @@ int libxl__device_from_disk(libxl__gc *gc, uint32_t domid,
     return 0;
 }
 
+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;
+}
+
 int libxl__device_disk_add(libxl__egc *egc, uint32_t domid,
                            libxl_device_disk *disk,
                            libxl__ao_device *aorm)
@@ -324,6 +338,114 @@ out:
     return rc;
 }
 
+int libxl__device_nic_add(libxl__egc *egc, uint32_t domid,
+                          libxl_device_nic *nic, libxl__ao_device *aorm)
+{
+    STATE_AO_GC(aorm->ao);
+    flexarray_t *front;
+    flexarray_t *back;
+    libxl__device *device;
+    char *dompath, **l;
+    unsigned int nb, rc;
+
+    rc = libxl__device_nic_setdefault(gc, nic);
+    if (rc) goto out;
+
+    front = flexarray_make(16, 1);
+    if (!front) {
+        rc = ERROR_NOMEM;
+        goto out;
+    }
+    back = flexarray_make(18, 1);
+    if (!back) {
+        rc = ERROR_NOMEM;
+        goto out_free;
+    }
+
+    if (nic->devid == -1) {
+        if (!(dompath = libxl__xs_get_dompath(gc, domid))) {
+            rc = ERROR_FAIL;
+            goto out_free;
+        }
+        if (!(l = libxl__xs_directory(gc, XBT_NULL, GCSPRINTF("%s/device/vif",
+                                                            dompath), &nb))) {
+            nic->devid = 0;
+        } else {
+            nic->devid = strtoul(l[nb - 1], NULL, 10) + 1;
+        }
+    }
+
+    GCNEW(device);
+    rc = libxl__device_from_nic(gc, domid, nic, device);
+    if (rc != 0) goto out_free;
+
+    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", 1));
+    if (nic->script) {
+        flexarray_append(back, "script");
+        flexarray_append(back, nic->script[0] == '/' ?
+                               nic->script :
+                               GCSPRINTF("%s/%s", libxl__xen_script_dir_path(),
+                         nic->script));
+    }
+
+    if (nic->ifname) {
+        flexarray_append(back, "vifname");
+        flexarray_append(back, nic->ifname);
+    }
+
+    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->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, GCSPRINTF("%s",
+                                     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", 1));
+    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)));
+    libxl__device_generic_add(gc, device,
+                        libxl__xs_kvs_of_flexarray(gc, back, back->count),
+                        libxl__xs_kvs_of_flexarray(gc, front, front->count));
+
+    aorm->dev = device;
+    aorm->action = DEVICE_CONNECT;
+    libxl__initiate_device_add(egc, aorm);
+
+    rc = 0;
+out_free:
+    flexarray_free(back);
+    flexarray_free(front);
+out:
+    return rc;
+}
+
+
 typedef struct {
     libxl__gc *gc;
     libxl_device_disk *disk;
diff --git a/tools/libxl/libxl_dm.c b/tools/libxl/libxl_dm.c
index b2622ee..ff5f8ad 100644
--- a/tools/libxl/libxl_dm.c
+++ b/tools/libxl/libxl_dm.c
@@ -666,6 +666,12 @@ static void spawn_stubdom_pvqemu_cb(libxl__egc *egc,
                                 libxl__dm_spawn_state *stubdom_dmss,
                                 int rc);
 
+static void stubdom_nics_connected(libxl__egc *egc, libxl__ao_device *aorm);
+
+static void stubdom_pvqemu_cb(libxl__egc *egc,
+                              libxl__dm_spawn_state *stubdom_dmss,
+                              int rc);
+
 void libxl__spawn_stub_dm(libxl__egc *egc, libxl__stub_dm_spawn_state *sdss)
 {
     STATE_AO_GC(sdss->dm.spawn.ao);
@@ -838,9 +844,11 @@ static void spawn_stub_disk_connected(libxl__egc *egc, 
libxl__ao_device *aorm)
     }
 
     for (i = 0; i < dm_config->num_vifs; i++) {
-        ret = libxl_device_nic_add(ctx, dm_domid, &dm_config->vifs[i]);
-        if (ret)
-            goto out;
+        /* We have to init the nic here, because we still haven't
+         * called libxl_device_nic_add at this point, but qemu needs
+         * the nic information to be complete.
+         */
+        libxl__device_nic_setdefault(gc, &dm_config->vifs[i]);
     }
     ret = libxl_device_vfb_add(ctx, dm_domid, &dm_config->vfbs[0]);
     if (ret)
@@ -915,9 +923,59 @@ static void spawn_stubdom_pvqemu_cb(libxl__egc *egc,
         CONTAINER_OF(stubdom_dmss, *sdss, pvqemu);
     STATE_AO_GC(sdss->dm.spawn.ao);
     uint32_t dm_domid = sdss->pvqemu.guest_domid;
+    libxl_domain_config *d_config = stubdom_dmss->guest_config;
+    int ret2, i;
 
     if (rc) goto out;
 
+    if (!rc && d_config->num_vifs > 0) {
+        GCNEW_ARRAY(stubdom_dmss->devices, d_config->num_vifs);
+        stubdom_dmss->num_devices = d_config->num_vifs;
+        for (i = 0; i < d_config->num_vifs; i++) {
+            libxl__init_ao_device(&stubdom_dmss->devices[i], ao,
+                                  &stubdom_dmss->devices);
+            stubdom_dmss->devices[i].callback = stubdom_nics_connected;
+            ret2 = libxl__device_nic_add(egc, dm_domid, &d_config->vifs[i],
+                                        &stubdom_dmss->devices[i]);
+            if (ret2) {
+                LOGE(ERROR, "cannot add nic %d to domain: %d", i, dm_domid);
+                rc = ERROR_FAIL;
+                goto out;
+            }
+        }
+        return;
+    }
+
+out:
+    stubdom_pvqemu_cb(egc, stubdom_dmss, rc);
+}
+
+static void stubdom_nics_connected(libxl__egc *egc, libxl__ao_device *aorm)
+{
+    STATE_AO_GC(aorm->ao);
+    libxl__dm_spawn_state *dmss = CONTAINER_OF(aorm->base, *dmss, devices);
+    int last, ret = 0;
+
+    ret = libxl__ao_device_check_last(gc, aorm, dmss->devices,
+                                      dmss->num_devices, &last);
+
+    if (!last) return;
+    if (last && ret)
+        LOGE(ERROR, "error connecting nics devices");
+
+    stubdom_pvqemu_cb(egc, dmss, ret);
+    return;
+}
+
+static void stubdom_pvqemu_cb(libxl__egc *egc,
+                              libxl__dm_spawn_state *stubdom_dmss,
+                              int rc)
+{
+    libxl__stub_dm_spawn_state *sdss =
+        CONTAINER_OF(stubdom_dmss, *sdss, pvqemu);
+    STATE_AO_GC(sdss->dm.spawn.ao);
+    uint32_t dm_domid = sdss->pvqemu.guest_domid;
+
     rc = libxl_domain_unpause(CTX, dm_domid);
     if (rc) goto out;
 
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index faeb965..91eba63 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -782,6 +782,9 @@ _hidden int libxl__domain_pvcontrol_write(libxl__gc *gc, 
xs_transaction_t t,
 _hidden char *libxl__device_disk_string_of_backend(libxl_disk_backend backend);
 _hidden char *libxl__device_disk_string_of_format(libxl_disk_format format);
 _hidden int libxl__device_disk_set_backend(libxl__gc*, libxl_device_disk*);
+_hidden int libxl__device_from_nic(libxl__gc *gc, uint32_t domid,
+                                   libxl_device_nic *nic,
+                                   libxl__device *device);
 _hidden int libxl__device_from_disk(libxl__gc *gc, uint32_t domid,
                                     libxl_device_disk *disk,
                                     libxl__device *device);
@@ -965,6 +968,7 @@ struct libxl__ao_device {
     libxl__device_callback *callback;
     /* private for implementation */
     int rc;
+    int vif_executed;
     libxl__ev_time ev;
     libxl__ev_child child;
     libxl__ev_devstate ds;
@@ -974,6 +978,9 @@ struct libxl__ao_device {
 _hidden int libxl__device_disk_add(libxl__egc *egc, uint32_t domid,
                                    libxl_device_disk *disk,
                                    libxl__ao_device *aorm);
+_hidden int libxl__device_nic_add(libxl__egc *egc, uint32_t domid,
+                                  libxl_device_nic *nic,
+                                  libxl__ao_device *aorm);
 
 /*
  *----- spawn -----
@@ -1147,6 +1154,8 @@ struct libxl__dm_spawn_state {
     libxl_domain_config *guest_config;
     libxl__domain_build_state *build_state; /* relates to guest_domid */
     libxl__dm_spawn_cb *callback;
+    libxl__ao_device *devices;
+    int num_devices;
 };
 
 _hidden void libxl__spawn_local_dm(libxl__egc *egc, libxl__dm_spawn_state*);
diff --git a/tools/libxl/libxl_linux.c b/tools/libxl/libxl_linux.c
index 315ce15..6e752bd 100644
--- a/tools/libxl/libxl_linux.c
+++ b/tools/libxl/libxl_linux.c
@@ -28,6 +28,26 @@ int libxl__try_phy_backend(mode_t st_mode)
 
 /* Hotplug scripts helpers */
 
+static libxl_nic_type get_nic_type(libxl__gc *gc, libxl__device *dev)
+{
+    char *snictype, *be_path;
+    libxl_nic_type nictype;
+
+    be_path = libxl__device_backend_path(gc, dev);
+    snictype = libxl__xs_read(gc, XBT_NULL,
+                              GCSPRINTF("%s/%s", be_path, "type"));
+    if (!snictype) {
+        LOGE(ERROR, "unable to read nictype from %s", be_path);
+        return -1;
+    }
+    if (libxl_nic_type_from_string(snictype, &nictype) < 0) {
+        LOGE(ERROR, "unable to parse nictype from %s", be_path);
+        return -1;
+    }
+
+    return nictype;
+}
+
 static void cleanup(libxl__gc *gc, libxl__ao_device *aorm)
 {
     if (!aorm) return;
@@ -47,7 +67,18 @@ static void callback(libxl__egc *egc, libxl__ev_child *child,
                                                     : LIBXL__LOG_WARNING,
                                       aorm->what, pid, status);
         aorm->rc = ERROR_FAIL;
+        goto out;
+    }
+
+    if (aorm->dev->backend_kind == LIBXL__DEVICE_KIND_VIF &&
+        get_nic_type(gc, aorm->dev) == LIBXL_NIC_TYPE_IOEMU &&
+        !aorm->vif_executed) {
+        aorm->vif_executed = 1;
+        libxl__device_hotplug(egc, aorm);
+        return;
     }
+
+out:
     aorm->callback(egc, aorm);
 }
 
@@ -66,7 +97,7 @@ static char **get_hotplug_env(libxl__gc *gc, libxl__device 
*dev)
         return NULL;
     }
 
-    GCNEW_ARRAY(env, 9);
+    GCNEW_ARRAY(env, 13);
     env[nr++] = "script";
     env[nr++] = script;
     env[nr++] = "XENBUS_TYPE";
@@ -75,6 +106,24 @@ static char **get_hotplug_env(libxl__gc *gc, libxl__device 
*dev)
     env[nr++] = GCSPRINTF("backend/%s/%u/%d", type, dev->domid, dev->devid);
     env[nr++] = "XENBUS_BASE_PATH";
     env[nr++] = "backend";
+    if (dev->backend_kind == LIBXL__DEVICE_KIND_VIF) {
+        switch (get_nic_type(gc, dev)) {
+        case LIBXL_NIC_TYPE_IOEMU:
+            env[nr++] = "INTERFACE";
+            env[nr++] = libxl__strdup(gc, libxl__device_nic_devname(gc,
+                                                      dev->domid, dev->devid,
+                                                      LIBXL_NIC_TYPE_IOEMU));
+        case LIBXL_NIC_TYPE_VIF:
+            env[nr++] = "vif";
+            env[nr++] = libxl__strdup(gc, libxl__device_nic_devname(gc,
+                                                      dev->domid, dev->devid,
+                                                      LIBXL_NIC_TYPE_VIF));
+            break;
+        default:
+            return NULL;
+        }
+    }
+
     env[nr++] = NULL;
 
     return env;
@@ -119,6 +168,81 @@ out_free:
     return rc;
 }
 
+static int libxl__hotplug_nic(libxl__gc *gc, libxl__ao_device *aorm)
+{
+    char *be_path = libxl__device_backend_path(gc, aorm->dev);
+    char *what, *script;
+    char **args, **env;
+    int nr = 0, rc = 0;
+    libxl_nic_type nictype;
+
+    script = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/%s", be_path,
+                                                             "script"));
+    if (!script) {
+        LOGE(ERROR, "unable to read script from %s", be_path);
+        return -1;
+    }
+
+    nictype = get_nic_type(gc, aorm->dev);
+    if (nictype < 0) {
+        LOGE(ERROR, "error when fetching nic type");
+        return -1;
+    }
+
+    env = get_hotplug_env(gc, aorm->dev);
+    if (!env)
+        return -1;
+
+    GCNEW_ARRAY(args, 4);
+
+    switch (nictype) {
+    case LIBXL_NIC_TYPE_IOEMU:
+        if (!aorm->vif_executed) goto execute_vif;
+        args[nr++] = script;
+        args[nr++] = aorm->action == DEVICE_CONNECT ? "add" : "remove";
+        args[nr++] = libxl__strdup(gc, "type_if=tap");
+        args[nr++] = NULL;
+        what = GCSPRINTF("%s %s", args[0], aorm->action == DEVICE_CONNECT ?
+                                           "connect" : "disconnect");
+        LOG(DEBUG, "Calling hotplug script: %s %s %s",
+                   args[0], args[1], args[2]);
+        rc = libxl__hotplug_launch(gc, aorm, args[0], args, env, callback);
+        if (rc) {
+            LOGE(ERROR, "unable execute hotplug scripts for vif device 
%"PRIu32,
+                        aorm->dev->devid);
+            goto out;
+        }
+        break;
+    case LIBXL_NIC_TYPE_VIF:
+execute_vif:
+        args[nr++] = script;
+        args[nr++] = aorm->action == DEVICE_CONNECT ? "online" : "offline";
+        args[nr++] = libxl__strdup(gc, "type_if=vif");
+        args[nr++] = NULL;
+        what = GCSPRINTF("%s %s", args[0], aorm->action == DEVICE_CONNECT ?
+                                           "connect" : "disconnect");
+        LOG(DEBUG, "Calling hotplug script: %s %s %s",
+                   args[0], args[1], args[2]);
+        rc = libxl__hotplug_launch(gc, aorm, args[0], args, env, callback);
+        if (rc) {
+            LOGE(ERROR, "unable execute hotplug scripts for vif device 
%"PRIu32,
+                        aorm->dev->devid);
+            goto out;
+        }
+        break;
+    default:
+        /* Unknown network type */
+        LOG(DEBUG, "unknown network card type with id %"PRIu32,
+                   aorm->dev->devid);
+        return 0;
+    }
+
+    rc = 0;
+
+out:
+    return rc;
+}
+
 void libxl__device_hotplug(libxl__egc *egc, libxl__ao_device *aorm)
 {
     STATE_AO_GC(aorm->ao);
@@ -132,6 +256,10 @@ void libxl__device_hotplug(libxl__egc *egc, 
libxl__ao_device *aorm)
         aorm->rc = libxl__hotplug_disk(gc, aorm);
         if (aorm->rc) goto error;
         break;
+    case LIBXL__DEVICE_KIND_VIF:
+        aorm->rc = libxl__hotplug_nic(gc, aorm);
+        if (aorm->rc) goto error;
+        break;
     default:
         /* If no need to execute any hotplug scripts,
          * call the callback manually
diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c
index 3f1bbf6..162bb82 100644
--- a/tools/libxl/xl_cmdimpl.c
+++ b/tools/libxl/xl_cmdimpl.c
@@ -4967,7 +4967,7 @@ int main_networkattach(int argc, char **argv)
         return 0;
     }
 
-    if (libxl_device_nic_add(ctx, domid, &nic)) {
+    if (libxl_device_nic_add(ctx, domid, &nic, 0)) {
         fprintf(stderr, "libxl_device_nic_add failed.\n");
         return 1;
     }
-- 
1.7.7.5 (Apple Git-26)


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

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