[libvirt] [PATCH v3] qemu, util: on restart of libvirt restart vepa callbacks

D. Herrendoerfer d.herrendoerfer at herrendoerfer.name
Tue Mar 27 12:38:33 UTC 2012


From: "D. Herrendoerfer" <d.herrendoerfer at herrendoerfer.name>

When libvirtd is restarted, also restart the netlink event
message callbacks for existing VEPA connections and send
a message to lldpad for these existing links, so it learns
the new libvirtd pid.
This patch includes the nits sent by Laine Stump, and it tests out ok.

Signed-off-by: D. Herrendoerfer <d.herrendoerfer at herrendoerfer.name>
---
 src/qemu/qemu_driver.c      |   31 ++++++++++
 src/util/virnetdevmacvlan.c |  129 +++++++++++++++++++++++++++++++++---------
 src/util/virnetdevmacvlan.h |    9 +++
 src/util/virnetlink.c       |    6 ++-
 4 files changed, 146 insertions(+), 29 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 538a419..8e6663c 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -412,6 +412,35 @@ cleanup:
     virDomainObjUnlock(vm);
 }
 
+
+static void qemuDomainNetsRestart(void *payload,
+                                const void *name ATTRIBUTE_UNUSED,
+                                void *data ATTRIBUTE_UNUSED)
+{
+   int i;
+   virDomainObjPtr vm = (virDomainObjPtr)payload;
+   virDomainDefPtr def = vm->def;
+
+   virDomainObjLock(vm);
+
+   for (i = 0; i < def->nnets; i++) {
+       virDomainNetDefPtr net = def->nets[i];
+       if (virDomainNetGetActualType(net) == VIR_DOMAIN_NET_TYPE_DIRECT &&
+           virDomainNetGetActualDirectMode(net) == VIR_NETDEV_MACVLAN_MODE_VEPA) {
+           VIR_DEBUG("VEPA mode device %s active in domain %s. Reassociating.",
+                     net->ifname, def->name);
+           ignore_value(virNetDevMacVLanRestartWithVPortProfile(net->ifname,
+                                                                net->mac,
+                                                                virDomainNetGetActualDirectDev(net),
+                                                                def->uuid,
+                                                                virDomainNetGetActualVirtPortProfile(net),
+                                                                VIR_NETDEV_VPORT_PROFILE_OP_CREATE));
+       }
+   }
+
+   virDomainObjUnlock(vm);
+}
+
 /**
  * qemudStartup:
  *
@@ -668,6 +697,8 @@ qemudStartup(int privileged) {
                                 NULL, NULL) < 0)
         goto error;
 
+    virHashForEach(qemu_driver->domains.objs, qemuDomainNetsRestart, NULL);
+
     conn = virConnectOpen(qemu_driver->privileged ?
                           "qemu:///system" :
                           "qemu:///session");
diff --git a/src/util/virnetdevmacvlan.c b/src/util/virnetdevmacvlan.c
index 647679f..90888b0 100644
--- a/src/util/virnetdevmacvlan.c
+++ b/src/util/virnetdevmacvlan.c
@@ -769,6 +769,50 @@ virNetDevMacVLanVPortProfileDestroyCallback(int watch ATTRIBUTE_UNUSED,
     virNetlinkCallbackDataFree((virNetlinkCallbackDataPtr)opaque);
 }
 
+static int
+virNetDevMacVLanVPortProfileRegisterCallback(const char *ifname,
+                                             const unsigned char *macaddress,
+                                             const char *linkdev,
+                                             const unsigned char *vmuuid,
+                                             virNetDevVPortProfilePtr virtPortProfile,
+                                             enum virNetDevVPortProfileOp vmOp)
+{
+    virNetlinkCallbackDataPtr calld = NULL;
+
+    if (virtPortProfile && virNetlinkEventServiceIsRunning()) {
+        if (VIR_ALLOC(calld) < 0)
+            goto memory_error;
+        if ((calld->cr_ifname = strdup(ifname)) == NULL)
+            goto memory_error;
+        if (VIR_ALLOC(calld->virtPortProfile) < 0)
+            goto memory_error;
+        memcpy(calld->virtPortProfile, virtPortProfile, sizeof(*virtPortProfile));
+        if (VIR_ALLOC_N(calld->macaddress, VIR_MAC_BUFLEN) < 0)
+            goto memory_error;
+        memcpy(calld->macaddress, macaddress, VIR_MAC_BUFLEN);
+        if ((calld->linkdev = strdup(linkdev)) == NULL)
+            goto  memory_error;
+        if (VIR_ALLOC_N(calld->vmuuid, VIR_UUID_BUFLEN) < 0)
+            goto memory_error;
+        memcpy(calld->vmuuid, vmuuid, VIR_UUID_BUFLEN);
+
+        calld->vmOp = vmOp;
+
+        if (virNetlinkEventAddClient(virNetDevMacVLanVPortProfileCallback,
+                                     virNetDevMacVLanVPortProfileDestroyCallback,
+                                     calld, macaddress) < 0)
+            goto error;
+    }
+
+    return 0;
+
+memory_error:
+    virReportOOMError();
+error:
+    virNetlinkCallbackDataFree(calld);
+    return -1;
+}
+
 
 /**
  * virNetDevMacVLanCreateWithVPortProfile:
@@ -810,7 +854,6 @@ int virNetDevMacVLanCreateWithVPortProfile(const char *tgifname,
     int retries, do_retry = 0;
     uint32_t macvtapMode;
     const char *cr_ifname;
-    virNetlinkCallbackDataPtr calld = NULL;
     int ret;
     int vf = -1;
 
@@ -917,36 +960,12 @@ create_name:
         goto disassociate_exit;
     }
 
-    if (virtPortProfile && virNetlinkEventServiceIsRunning()) {
-        if (VIR_ALLOC(calld) < 0)
-            goto memory_error;
-        if ((calld->cr_ifname = strdup(cr_ifname)) == NULL)
-            goto memory_error;
-        if (VIR_ALLOC(calld->virtPortProfile) < 0)
-            goto memory_error;
-        memcpy(calld->virtPortProfile, virtPortProfile, sizeof(*virtPortProfile));
-        if (VIR_ALLOC_N(calld->macaddress, VIR_MAC_BUFLEN) < 0)
-            goto memory_error;
-        memcpy(calld->macaddress, macaddress, VIR_MAC_BUFLEN);
-        if ((calld->linkdev = strdup(linkdev)) == NULL)
-            goto  memory_error;
-        if (VIR_ALLOC_N(calld->vmuuid, VIR_UUID_BUFLEN) < 0)
-            goto memory_error;
-        memcpy(calld->vmuuid, vmuuid, VIR_UUID_BUFLEN);
-
-        calld->vmOp = vmOp;
-
-        virNetlinkEventAddClient(virNetDevMacVLanVPortProfileCallback,
-                                 virNetDevMacVLanVPortProfileDestroyCallback,
-                                 calld, macaddress);
-    }
+    if (virNetDevMacVLanVPortProfileRegisterCallback(cr_ifname, macaddress,
+                                         linkdev, vmuuid, virtPortProfile, vmOp) < 0 )
+        goto disassociate_exit;
 
     return rc;
 
- memory_error:
-    virReportOOMError();
-    virNetlinkCallbackDataFree(calld);
-
 disassociate_exit:
     ignore_value(virNetDevVPortProfileDisassociate(cr_ifname,
                                                    virtPortProfile,
@@ -1003,6 +1022,48 @@ int virNetDevMacVLanDeleteWithVPortProfile(const char *ifname,
     return ret;
 }
 
+/**
+ * virNetDevMacVLanRestartWithVPortProfile:
+ * Register a port profile callback handler for a VM that
+ * is already running
+ * .
+ * @cr_ifname: Interface name that the macvtap has.
+ * @macaddress: The MAC address for the macvtap device
+ * @linkdev: The interface name of the NIC to connect to the external bridge
+ * @vmuuid: The UUID of the VM the macvtap belongs to
+ * @virtPortProfile: pointer to object holding the virtual port profile data
+ * @vmOp: Operation to use during setup of the association
+ *
+ * Returns 0; returns -1 on error.
+ */
+int virNetDevMacVLanRestartWithVPortProfile(const char *cr_ifname,
+                                           const unsigned char *macaddress,
+                                           const char *linkdev,
+                                           const unsigned char *vmuuid,
+                                           virNetDevVPortProfilePtr virtPortProfile,
+                                           enum virNetDevVPortProfileOp vmOp)
+{
+    int rc = 0;
+
+    rc = virNetDevMacVLanVPortProfileRegisterCallback(cr_ifname, macaddress,
+                                                      linkdev, vmuuid,
+                                                      virtPortProfile, vmOp);
+    if (rc < 0)
+        goto error;
+
+    ignore_value(virNetDevVPortProfileAssociate(cr_ifname,
+                                                virtPortProfile,
+                                                macaddress,
+                                                linkdev,
+                                                -1,
+                                                vmuuid,
+                                                vmOp, true));
+
+error:
+    return rc;
+
+}
+
 #else /* ! WITH_MACVTAP */
 int virNetDevMacVLanCreate(const char *ifname ATTRIBUTE_UNUSED,
                            const char *type ATTRIBUTE_UNUSED,
@@ -1052,4 +1113,16 @@ int virNetDevMacVLanDeleteWithVPortProfile(const char *ifname ATTRIBUTE_UNUSED,
                          _("Cannot create macvlan devices on this platform"));
     return -1;
 }
+
+int virNetDevMacVLanRestartWithVPortProfile(const char *cr_ifname ATTRIBUTE_UNUSED,
+                                           const unsigned char *macaddress ATTRIBUTE_UNUSED,
+                                           const char *linkdev ATTRIBUTE_UNUSED,
+                                           const unsigned char *vmuuid ATTRIBUTE_UNUSED,
+                                           virNetDevVPortProfilePtr virtPortProfile ATTRIBUTE_UNUSED,
+                                           enum virNetDevVPortProfileOp vmOp ATTRIBUTE_UNUSED)
+{
+    virReportSystemError(ENOSYS, "%s",
+                         _("Cannot create macvlan devices on this platform"));
+    return -1;
+}
 #endif /* ! WITH_MACVTAP */
diff --git a/src/util/virnetdevmacvlan.h b/src/util/virnetdevmacvlan.h
index 130ecea..14640cf 100644
--- a/src/util/virnetdevmacvlan.h
+++ b/src/util/virnetdevmacvlan.h
@@ -75,4 +75,13 @@ int virNetDevMacVLanDeleteWithVPortProfile(const char *ifname,
     ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
     ATTRIBUTE_NONNULL(6) ATTRIBUTE_RETURN_CHECK;
 
+int virNetDevMacVLanRestartWithVPortProfile(const char *cr_ifname,
+                                           const unsigned char *macaddress,
+                                           const char *linkdev,
+                                           const unsigned char *vmuuid,
+                                           virNetDevVPortProfilePtr virtPortProfile,
+                                           enum virNetDevVPortProfileOp vmOp)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
+    ATTRIBUTE_NONNULL(4) ATTRIBUTE_NONNULL(5) ATTRIBUTE_RETURN_CHECK;
+
 #endif /* __UTIL_MACVTAP_H__ */
diff --git a/src/util/virnetlink.c b/src/util/virnetlink.c
index 59f3e39..2cb3656 100644
--- a/src/util/virnetlink.c
+++ b/src/util/virnetlink.c
@@ -428,8 +428,11 @@ virNetlinkEventAddClient(virNetlinkEventHandleCallback handleCB,
     int i, r, ret = -1;
     virNetlinkEventSrvPrivatePtr srv = server;
 
-    if (handleCB == NULL)
+    if (handleCB == NULL) {
+        netlinkError(VIR_ERR_INTERNAL_ERROR, "%s",
+                     _("Invalid NULL callback provided"));
         return -1;
+    }
 
     virNetlinkEventServerLock(srv);
 
@@ -449,6 +452,7 @@ virNetlinkEventAddClient(virNetlinkEventHandleCallback handleCB,
                   srv->handlesAlloc, NETLINK_EVENT_ALLOC_EXTENT);
         if (VIR_RESIZE_N(srv->handles, srv->handlesAlloc,
                         srv->handlesCount, NETLINK_EVENT_ALLOC_EXTENT) < 0) {
+            virReportOOMError();
             goto error;
         }
     }
-- 
1.7.7.6




More information about the libvir-list mailing list