From: "D. Herrendoerfer" <d.herrendoerfer@xxxxxxxxxxxxxxxxxx> 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 only includes qemu support as a base if this works out I'll add others. Signed-off-by: D. Herrendoerfer <d.herrendoerfer@xxxxxxxxxxxxxxxxxx> --- src/qemu/qemu_driver.c | 30 ++++++++++ src/util/virnetdevmacvlan.c | 128 +++++++++++++++++++++++++++++++++--------- src/util/virnetdevmacvlan.h | 9 +++ 3 files changed, 139 insertions(+), 28 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 538a419..c93ece3 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -412,6 +412,34 @@ cleanup: virDomainObjUnlock(vm); } + +static void qemuDomainNetsRestart(void *payload, + const void *name ATTRIBUTE_UNUSED, + void *data) +{ + 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 (net->type == VIR_DOMAIN_NET_TYPE_DIRECT && + net->data.direct.mode == VIR_NETDEV_MACVLAN_MODE_VEPA) { + VIR_DEBUG("Device active on %s in VEPA mode. Reassociating.",net->ifname); + ignore_value(virNetDevMacVLanRestartWithVPortProfile(net->ifname, + net->mac, + net->data.direct.linkdev, + def->uuid, + net->data.direct.virtPortProfile, + VIR_NETDEV_VPORT_PROFILE_OP_CREATE)); + } + } + + virDomainObjUnlock(vm); +} + /** * qemudStartup: * @@ -668,6 +696,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..eca4b6e 100644 --- a/src/util/virnetdevmacvlan.c +++ b/src/util/virnetdevmacvlan.c @@ -769,6 +769,49 @@ 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; + + virNetlinkEventAddClient(virNetDevMacVLanVPortProfileCallback, + virNetDevMacVLanVPortProfileDestroyCallback, + calld, macaddress); + } + + return 0; + + memory_error: + virReportOOMError(); + virNetlinkCallbackDataFree(calld); + + return -1; +} + /** * virNetDevMacVLanCreateWithVPortProfile: @@ -810,7 +853,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 +959,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 +1021,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 +1112,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__ */ -- 1.7.7.6 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list