diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index d503debcc0..7ff846f6f6 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -415,6 +415,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: * @@ -665,6 +694,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 d467990cfe..37891b48f8 100644 --- a/src/util/virnetdevmacvlan.c +++ b/src/util/virnetdevmacvlan.c @@ -754,6 +754,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: @@ -795,7 +839,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; @@ -902,36 +945,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, @@ -988,6 +1007,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, @@ -1037,4 +1098,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 130ecea6f0..14640cf82a 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 f099974dae..7017275b4b 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; } }