commit b0d24540237404e3c840600e54109be4e5789f0a
Author: Chunyan Liu <cyliu@suse.com>
Date:   Tue Jul 15 13:03:15 2014 +0800

    libxl: support hotplug of <interface>
    
    Add code to support attach/detaching a network device.
    
    Signed-off-by: Chunyan Liu <cyliu@suse.com>

Index: libvirt-1.2.5/src/libxl/libxl_domain.c
===================================================================
--- libvirt-1.2.5.orig/src/libxl/libxl_domain.c
+++ libvirt-1.2.5/src/libxl/libxl_domain.c
@@ -482,8 +482,16 @@ libxlDomainDeviceDefPostParse(virDomainD
         STRNEQ(def->os.type, "hvm"))
         dev->data.chr->targetType = VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_XEN;
 
-    if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV) {
-        virDomainHostdevDefPtr hostdev = dev->data.hostdev;
+    if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV ||
+        (dev->type == VIR_DOMAIN_DEVICE_NET &&
+         dev->data.net->type == VIR_DOMAIN_NET_TYPE_HOSTDEV)) {
+
+        virDomainHostdevDefPtr hostdev;
+
+        if (dev->type == VIR_DOMAIN_DEVICE_NET)
+            hostdev = &(dev->data.net)->data.hostdev.def;
+        else
+            hostdev = dev->data.hostdev;
 
         if (hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
             hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI &&
Index: libvirt-1.2.5/src/libxl/libxl_driver.c
===================================================================
--- libvirt-1.2.5.orig/src/libxl/libxl_driver.c
+++ libvirt-1.2.5/src/libxl/libxl_driver.c
@@ -55,6 +55,7 @@
 #include "viraccessapicheck.h"
 #include "viratomic.h"
 #include "virhostdev.h"
+#include "network/bridge_driver.h"
 
 #define VIR_FROM_THIS VIR_FROM_LIBXL
 
@@ -2679,10 +2680,8 @@ static int
 libxlDomainAttachHostDevice(libxlDriverPrivatePtr driver,
                             libxlDomainObjPrivatePtr priv,
                             virDomainObjPtr vm,
-                            virDomainDeviceDefPtr dev)
+                            virDomainHostdevDefPtr hostdev)
 {
-    virDomainHostdevDefPtr hostdev = dev->data.hostdev;
-
     if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) {
         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                        _("hostdev mode '%s' not supported"),
@@ -2761,6 +2760,60 @@ libxlDomainDetachDeviceDiskLive(libxlDom
 }
 
 static int
+libxlDomainAttachNetDevice(libxlDriverPrivatePtr driver,
+                           libxlDomainObjPrivatePtr priv,
+                           virDomainObjPtr vm,
+                           virDomainNetDefPtr net)
+{
+    int actualType;
+    libxl_device_nic nic;
+    int ret = -1;
+
+    /* preallocate new slot for device */
+    if (VIR_REALLOC_N(vm->def->nets, vm->def->nnets + 1) < 0)
+        return -1;
+
+    /* If appropriate, grab a physical device from the configured
+     * network's pool of devices, or resolve bridge device name
+     * to the one defined in the network definition.
+     */
+    if (networkAllocateActualDevice(vm->def, net) < 0)
+        return -1;
+
+    actualType = virDomainNetGetActualType(net);
+
+    if (actualType == VIR_DOMAIN_NET_TYPE_HOSTDEV) {
+        /* This is really a "smart hostdev", so it should be attached
+         * as a hostdev (the hostdev code will reach over into the
+         * netdev-specific code as appropriate), then also added to
+         * the nets list (see out:) if successful.
+         */
+        ret = libxlDomainAttachHostDevice(driver, priv, vm,
+                                          virDomainNetGetActualHostdev(net));
+        goto out;
+    }
+
+    libxl_device_nic_init(&nic);
+    if (libxlMakeNic(vm->def, net, &nic) < 0)
+        goto cleanup;
+
+    if (libxl_device_nic_add(priv->ctx, vm->def->id, &nic, 0)) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("libxenlight failed to attach network device"));
+        goto cleanup;
+    }
+
+    ret = 0;
+
+ cleanup:
+    libxl_device_nic_dispose(&nic);
+ out:
+    if (!ret)
+        vm->def->nets[vm->def->nnets++] = net;
+    return ret;
+}
+
+static int
 libxlDomainAttachDeviceLive(libxlDriverPrivatePtr driver,
                             libxlDomainObjPrivatePtr priv,
                             virDomainObjPtr vm,
@@ -2775,8 +2828,16 @@ libxlDomainAttachDeviceLive(libxlDriverP
                 dev->data.disk = NULL;
             break;
 
+        case VIR_DOMAIN_DEVICE_NET:
+            ret = libxlDomainAttachNetDevice(driver, priv, vm,
+                                             dev->data.net);
+            if (!ret)
+                dev->data.net = NULL;
+            break;
+
         case VIR_DOMAIN_DEVICE_HOSTDEV:
-            ret = libxlDomainAttachHostDevice(driver, priv, vm, dev);
+            ret = libxlDomainAttachHostDevice(driver, priv, vm,
+                                              dev->data.hostdev);
             if (!ret)
                 dev->data.hostdev = NULL;
             break;
@@ -2795,6 +2856,7 @@ static int
 libxlDomainAttachDeviceConfig(virDomainDefPtr vmdef, virDomainDeviceDefPtr dev)
 {
     virDomainDiskDefPtr disk;
+    virDomainNetDefPtr net;
     virDomainHostdevDefPtr hostdev;
     virDomainHostdevDefPtr found;
 
@@ -2811,6 +2873,14 @@ libxlDomainAttachDeviceConfig(virDomainD
             /* vmdef has the pointer. Generic codes for vmdef will do all jobs */
             dev->data.disk = NULL;
             break;
+
+        case VIR_DOMAIN_DEVICE_NET:
+            net = dev->data.net;
+            if (virDomainNetInsert(vmdef, net))
+                return -1;
+            dev->data.net = NULL;
+            break;
+
         case VIR_DOMAIN_DEVICE_HOSTDEV:
             hostdev = dev->data.hostdev;
 
@@ -2933,9 +3003,8 @@ static int
 libxlDomainDetachHostDevice(libxlDriverPrivatePtr driver,
                             libxlDomainObjPrivatePtr priv,
                             virDomainObjPtr vm,
-                            virDomainDeviceDefPtr dev)
+                            virDomainHostdevDefPtr hostdev)
 {
-    virDomainHostdevDefPtr hostdev = dev->data.hostdev;
     virDomainHostdevSubsysPtr subsys = &hostdev->source.subsys;
 
     if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) {
@@ -2959,6 +3028,53 @@ libxlDomainDetachHostDevice(libxlDriverP
 }
 
 static int
+libxlDomainDetachNetDevice(libxlDriverPrivatePtr driver,
+                           libxlDomainObjPrivatePtr priv,
+                           virDomainObjPtr vm,
+                           virDomainNetDefPtr net)
+{
+    int detachidx;
+    virDomainNetDefPtr detach = NULL;
+    libxl_device_nic nic;
+    char mac[VIR_MAC_STRING_BUFLEN];
+    int ret = -1;
+
+    if ((detachidx = virDomainNetFindIdx(vm->def, net)) < 0)
+        return -1;
+
+    detach = vm->def->nets[detachidx];
+
+    if (virDomainNetGetActualType(detach) == VIR_DOMAIN_NET_TYPE_HOSTDEV) {
+        /* This is really a "smart hostdev", so it should be attached as a
+         * hostdev, then also removed from nets list (see out:) if successful.
+         */
+        ret = libxlDomainDetachHostDevice(driver, priv, vm,
+                                          virDomainNetGetActualHostdev(detach));
+        goto out;
+    }
+
+    libxl_device_nic_init(&nic);
+    if (libxl_mac_to_device_nic(priv->ctx, vm->def->id,
+                                virMacAddrFormat(&detach->mac, mac), &nic))
+        goto cleanup;
+
+    if (libxl_device_nic_remove(priv->ctx, vm->def->id, &nic, 0)) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("libxenlight failed to detach network device"));
+        goto cleanup;
+    }
+
+    ret = 0;
+
+ cleanup:
+    libxl_device_nic_dispose(&nic);
+ out:
+    if (!ret)
+        virDomainNetRemove(vm->def, detachidx);
+    return ret;
+}
+
+static int
 libxlDomainDetachDeviceLive(libxlDriverPrivatePtr driver,
                             libxlDomainObjPrivatePtr priv,
                             virDomainObjPtr vm,
@@ -2971,8 +3087,14 @@ libxlDomainDetachDeviceLive(libxlDriverP
             ret = libxlDomainDetachDeviceDiskLive(priv, vm, dev);
             break;
 
+        case VIR_DOMAIN_DEVICE_NET:
+            ret = libxlDomainDetachNetDevice(driver, priv, vm,
+                                             dev->data.net);
+            break;
+
         case VIR_DOMAIN_DEVICE_HOSTDEV:
-            ret = libxlDomainDetachHostDevice(driver, priv, vm, dev);
+            ret = libxlDomainDetachHostDevice(driver, priv, vm,
+                                              dev->data.hostdev);
             break;
 
         default:
@@ -2991,6 +3113,7 @@ libxlDomainDetachDeviceConfig(virDomainD
 {
     virDomainDiskDefPtr disk, detach;
     virDomainHostdevDefPtr hostdev, det_hostdev;
+    virDomainNetDefPtr net;
     int idx;
 
     switch (dev->type) {
@@ -3004,6 +3127,15 @@ libxlDomainDetachDeviceConfig(virDomainD
             virDomainDiskDefFree(detach);
             break;
 
+        case VIR_DOMAIN_DEVICE_NET:
+            net = dev->data.net;
+            if ((idx = virDomainNetFindIdx(vmdef, net)) < 0)
+                return -1;
+
+            /* this is guaranteed to succeed */
+            virDomainNetDefFree(virDomainNetRemove(vmdef, idx));
+            break;
+
         case VIR_DOMAIN_DEVICE_HOSTDEV: {
             hostdev = dev->data.hostdev;
             if ((idx = virDomainHostdevFind(vmdef, hostdev, &det_hostdev)) < 0) {
