mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-10 23:07:44 +00:00
nwfilter: fix tear down order and consolidate functions
To avoid race-conditions, the tear down of a filter has to happen before the tap interface disappears and another tap interface with the same name can re-appear. This patch tries to fix this. In one place, where communication with the qemu monitor may fail, I am only tearing the filters down after knowing that the function did not fail. I am also moving the tear down functions into an include file for other drivers to reuse.
This commit is contained in:
parent
c41873f40e
commit
41b087198d
@ -65,4 +65,20 @@ void virNWFilterDomainFWUpdateCB(void *payload,
|
|||||||
const char *name ATTRIBUTE_UNUSED,
|
const char *name ATTRIBUTE_UNUSED,
|
||||||
void *data);
|
void *data);
|
||||||
|
|
||||||
|
|
||||||
|
/* tear down an interface's filter before tearing down the interface */
|
||||||
|
static inline void
|
||||||
|
virNWFilterTearNWFilter(virDomainNetDefPtr net) {
|
||||||
|
if ((net->filter) && (net->ifname))
|
||||||
|
virNWFilterTeardownFilter(net);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
virNWFilterTearVMNWFilters(virDomainObjPtr vm) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < vm->def->nnets; i++)
|
||||||
|
virNWFilterTearNWFilter(vm->def->nets[i]);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -4074,10 +4074,13 @@ int qemudBuildCommandLine(virConnectPtr conn,
|
|||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
if (VIR_REALLOC_N(*tapfds, (*ntapfds)+1) < 0) {
|
if (VIR_REALLOC_N(*tapfds, (*ntapfds)+1) < 0) {
|
||||||
|
virNWFilterTearNWFilter(net);
|
||||||
close(tapfd);
|
close(tapfd);
|
||||||
goto no_memory;
|
goto no_memory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
last_good_net = i;
|
||||||
|
|
||||||
(*tapfds)[(*ntapfds)++] = tapfd;
|
(*tapfds)[(*ntapfds)++] = tapfd;
|
||||||
|
|
||||||
if (snprintf(tapfd_name, sizeof(tapfd_name), "%d", tapfd) >= sizeof(tapfd_name))
|
if (snprintf(tapfd_name, sizeof(tapfd_name), "%d", tapfd) >= sizeof(tapfd_name))
|
||||||
@ -4091,10 +4094,13 @@ int qemudBuildCommandLine(virConnectPtr conn,
|
|||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
if (VIR_REALLOC_N(*tapfds, (*ntapfds)+1) < 0) {
|
if (VIR_REALLOC_N(*tapfds, (*ntapfds)+1) < 0) {
|
||||||
|
virNWFilterTearNWFilter(net);
|
||||||
close(tapfd);
|
close(tapfd);
|
||||||
goto no_memory;
|
goto no_memory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
last_good_net = i;
|
||||||
|
|
||||||
(*tapfds)[(*ntapfds)++] = tapfd;
|
(*tapfds)[(*ntapfds)++] = tapfd;
|
||||||
|
|
||||||
if (snprintf(tapfd_name, sizeof(tapfd_name), "%d", tapfd) >= sizeof(tapfd_name))
|
if (snprintf(tapfd_name, sizeof(tapfd_name), "%d", tapfd) >= sizeof(tapfd_name))
|
||||||
@ -4154,7 +4160,6 @@ int qemudBuildCommandLine(virConnectPtr conn,
|
|||||||
goto error;
|
goto error;
|
||||||
ADD_ARG(host);
|
ADD_ARG(host);
|
||||||
}
|
}
|
||||||
last_good_net = i;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4603,6 +4608,8 @@ int qemudBuildCommandLine(virConnectPtr conn,
|
|||||||
no_memory:
|
no_memory:
|
||||||
virReportOOMError();
|
virReportOOMError();
|
||||||
error:
|
error:
|
||||||
|
for (i = 0; i <= last_good_net; i++)
|
||||||
|
virNWFilterTearNWFilter(def->nets[i]);
|
||||||
if (tapfds &&
|
if (tapfds &&
|
||||||
*tapfds) {
|
*tapfds) {
|
||||||
for (i = 0; i < *ntapfds; i++)
|
for (i = 0; i < *ntapfds; i++)
|
||||||
@ -4620,11 +4627,6 @@ int qemudBuildCommandLine(virConnectPtr conn,
|
|||||||
VIR_FREE((qenv)[i]);
|
VIR_FREE((qenv)[i]);
|
||||||
VIR_FREE(qenv);
|
VIR_FREE(qenv);
|
||||||
}
|
}
|
||||||
for (i = 0; i <= last_good_net; i++) {
|
|
||||||
virDomainNetDefPtr net = def->nets[i];
|
|
||||||
if ((net->filter) && (net->ifname))
|
|
||||||
virNWFilterTeardownFilter(net);
|
|
||||||
}
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
#undef ADD_ARG
|
#undef ADD_ARG
|
||||||
|
@ -3070,21 +3070,6 @@ cleanup:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
qemuTearNWFilter(virDomainNetDefPtr net) {
|
|
||||||
if ((net->filter) && (net->ifname))
|
|
||||||
virNWFilterTeardownFilter(net);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
qemuTearVMNWFilters(virDomainObjPtr vm) {
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < vm->def->nnets; i++)
|
|
||||||
qemuTearNWFilter(vm->def->nets[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
struct qemudHookData {
|
struct qemudHookData {
|
||||||
virConnectPtr conn;
|
virConnectPtr conn;
|
||||||
virDomainObjPtr vm;
|
virDomainObjPtr vm;
|
||||||
@ -3397,6 +3382,9 @@ static int qemudStartVMDaemon(virConnectPtr conn,
|
|||||||
VIR_FREE(progenv[i]);
|
VIR_FREE(progenv[i]);
|
||||||
VIR_FREE(progenv);
|
VIR_FREE(progenv);
|
||||||
|
|
||||||
|
if (ret == -1) /* The VM failed to start; tear filters before taps */
|
||||||
|
virNWFilterTearVMNWFilters(vm);
|
||||||
|
|
||||||
if (tapfds) {
|
if (tapfds) {
|
||||||
for (i = 0 ; i < ntapfds ; i++) {
|
for (i = 0 ; i < ntapfds ; i++) {
|
||||||
close(tapfds[i]);
|
close(tapfds[i]);
|
||||||
@ -3461,8 +3449,6 @@ cleanup:
|
|||||||
/* We jump here if we failed to start the VM for any reason
|
/* We jump here if we failed to start the VM for any reason
|
||||||
* XXX investigate if we can kill this block and safely call
|
* XXX investigate if we can kill this block and safely call
|
||||||
* qemudShutdownVMDaemon even though no PID is running */
|
* qemudShutdownVMDaemon even though no PID is running */
|
||||||
qemuTearVMNWFilters(vm);
|
|
||||||
|
|
||||||
qemuDomainReAttachHostDevices(driver, vm->def);
|
qemuDomainReAttachHostDevices(driver, vm->def);
|
||||||
|
|
||||||
if (driver->securityDriver &&
|
if (driver->securityDriver &&
|
||||||
@ -3511,7 +3497,7 @@ static void qemudShutdownVMDaemon(struct qemud_driver *driver,
|
|||||||
* reporting so we don't squash a legit error. */
|
* reporting so we don't squash a legit error. */
|
||||||
orig_err = virSaveLastError();
|
orig_err = virSaveLastError();
|
||||||
|
|
||||||
qemuTearVMNWFilters(vm);
|
virNWFilterTearVMNWFilters(vm);
|
||||||
|
|
||||||
if (driver->macFilter) {
|
if (driver->macFilter) {
|
||||||
def = vm->def;
|
def = vm->def;
|
||||||
@ -7158,7 +7144,8 @@ cleanup:
|
|||||||
qemuDomainPCIAddressReleaseAddr(priv->pciaddrs, &net->info) < 0)
|
qemuDomainPCIAddressReleaseAddr(priv->pciaddrs, &net->info) < 0)
|
||||||
VIR_WARN0("Unable to release PCI address on NIC");
|
VIR_WARN0("Unable to release PCI address on NIC");
|
||||||
|
|
||||||
qemuTearNWFilter(net);
|
if (ret != 0)
|
||||||
|
virNWFilterTearNWFilter(net);
|
||||||
|
|
||||||
VIR_FREE(nicstr);
|
VIR_FREE(nicstr);
|
||||||
VIR_FREE(netstr);
|
VIR_FREE(netstr);
|
||||||
@ -7958,6 +7945,8 @@ qemudDomainDetachNetDevice(struct qemud_driver *driver,
|
|||||||
}
|
}
|
||||||
qemuDomainObjExitMonitorWithDriver(driver, vm);
|
qemuDomainObjExitMonitorWithDriver(driver, vm);
|
||||||
|
|
||||||
|
virNWFilterTearNWFilter(detach);
|
||||||
|
|
||||||
#if WITH_MACVTAP
|
#if WITH_MACVTAP
|
||||||
if (detach->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
|
if (detach->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
|
||||||
if (detach->ifname)
|
if (detach->ifname)
|
||||||
@ -7975,8 +7964,6 @@ qemudDomainDetachNetDevice(struct qemud_driver *driver,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
qemuTearNWFilter(detach);
|
|
||||||
|
|
||||||
if (vm->def->nnets > 1) {
|
if (vm->def->nnets > 1) {
|
||||||
memmove(vm->def->nets + i,
|
memmove(vm->def->nets + i,
|
||||||
vm->def->nets + i + 1,
|
vm->def->nets + i + 1,
|
||||||
|
Loading…
Reference in New Issue
Block a user