diff --git a/src/conf/nwfilter_conf.c b/src/conf/nwfilter_conf.c index a8a6a78ab6..ea73a33e0f 100644 --- a/src/conf/nwfilter_conf.c +++ b/src/conf/nwfilter_conf.c @@ -2088,8 +2088,14 @@ virNWFilterTriggerVMFilterRebuild(virConnectPtr conn) .conn = conn, .err = 0, .step = STEP_APPLY_NEW, + .skipInterfaces = virHashCreate(0), }; + if (!cb.skipInterfaces) { + virReportOOMError(); + return 1; + } + for (i = 0; i < nCallbackDriver; i++) { callbackDrvArray[i]->vmFilterRebuild(conn, virNWFilterDomainFWUpdateCB, @@ -2115,6 +2121,8 @@ virNWFilterTriggerVMFilterRebuild(virConnectPtr conn) &cb); } + virHashFree(cb.skipInterfaces, NULL); + return err; } diff --git a/src/conf/nwfilter_conf.h b/src/conf/nwfilter_conf.h index 3aef3fb110..b7b62adc33 100644 --- a/src/conf/nwfilter_conf.h +++ b/src/conf/nwfilter_conf.h @@ -471,6 +471,7 @@ struct domUpdateCBStruct { virConnectPtr conn; enum UpdateStep step; int err; + virHashTablePtr skipInterfaces; }; diff --git a/src/nwfilter/nwfilter_gentech_driver.c b/src/nwfilter/nwfilter_gentech_driver.c index 515d381a18..494637354e 100644 --- a/src/nwfilter/nwfilter_gentech_driver.c +++ b/src/nwfilter/nwfilter_gentech_driver.c @@ -316,7 +316,7 @@ _virNWFilterInstantiateRec(virConnectPtr conn, virNWFilterHashTablePtr vars, int *nEntries, virNWFilterRuleInstPtr **insts, - enum instCase useNewFilter, int *foundNewFilter, + enum instCase useNewFilter, bool *foundNewFilter, virNWFilterDriverStatePtr driver) { virNWFilterPoolObjPtr obj; @@ -381,7 +381,7 @@ _virNWFilterInstantiateRec(virConnectPtr conn, case INSTANTIATE_FOLLOW_NEWFILTER: if (obj->newDef) { next_filter = obj->newDef; - *foundNewFilter = 1; + *foundNewFilter = true; } break; case INSTANTIATE_ALWAYS: @@ -562,7 +562,7 @@ virNWFilterInstantiate(virConnectPtr conn, int ifindex, const char *linkdev, virNWFilterHashTablePtr vars, - enum instCase useNewFilter, int *foundNewFilter, + enum instCase useNewFilter, bool *foundNewFilter, bool teardownOld, const unsigned char *macaddr, virNWFilterDriverStatePtr driver, @@ -693,7 +693,8 @@ __virNWFilterInstantiateFilter(virConnectPtr conn, virNWFilterHashTablePtr filterparams, enum instCase useNewFilter, virNWFilterDriverStatePtr driver, - bool forceWithPendingReq) + bool forceWithPendingReq, + bool *foundNewFilter) { int rc; const char *drvname = EBIPTABLES_DRIVER_ID; @@ -702,7 +703,6 @@ __virNWFilterInstantiateFilter(virConnectPtr conn, virNWFilterHashTablePtr vars, vars1; virNWFilterDefPtr filter; char vmmacaddr[VIR_MAC_STRING_BUFLEN] = {0}; - int foundNewFilter = 0; char *str_macaddr = NULL; const char *ipaddr; char *str_ipaddr = NULL; @@ -775,7 +775,7 @@ __virNWFilterInstantiateFilter(virConnectPtr conn, case INSTANTIATE_FOLLOW_NEWFILTER: if (obj->newDef) { filter = obj->newDef; - foundNewFilter = 1; + *foundNewFilter = true; } break; @@ -791,7 +791,7 @@ __virNWFilterInstantiateFilter(virConnectPtr conn, ifindex, linkdev, vars, - useNewFilter, &foundNewFilter, + useNewFilter, foundNewFilter, teardownOld, macaddr, driver, @@ -816,7 +816,8 @@ static int _virNWFilterInstantiateFilter(virConnectPtr conn, const virDomainNetDefPtr net, bool teardownOld, - enum instCase useNewFilter) + enum instCase useNewFilter, + bool *foundNewFilter) { const char *linkdev = (net->type == VIR_DOMAIN_NET_TYPE_DIRECT) ? net->data.direct.linkdev @@ -837,7 +838,8 @@ _virNWFilterInstantiateFilter(virConnectPtr conn, net->filterparams, useNewFilter, conn->nwfilterPrivateData, - false); + false, + foundNewFilter); } @@ -853,6 +855,8 @@ virNWFilterInstantiateFilterLate(virConnectPtr conn, virNWFilterDriverStatePtr driver) { int rc; + bool foundNewFilter = false; + rc = __virNWFilterInstantiateFilter(conn, 1, ifname, @@ -864,7 +868,8 @@ virNWFilterInstantiateFilterLate(virConnectPtr conn, filterparams, INSTANTIATE_ALWAYS, driver, - true); + true, + &foundNewFilter); if (rc) { //something went wrong... 'DOWN' the interface if (ifaceCheck(false, ifname, NULL, ifindex) != 0 || @@ -881,19 +886,29 @@ int virNWFilterInstantiateFilter(virConnectPtr conn, const virDomainNetDefPtr net) { + bool foundNewFilter = false; + return _virNWFilterInstantiateFilter(conn, net, 1, - INSTANTIATE_ALWAYS); + INSTANTIATE_ALWAYS, + &foundNewFilter); } int virNWFilterUpdateInstantiateFilter(virConnectPtr conn, - const virDomainNetDefPtr net) + const virDomainNetDefPtr net, + bool *skipIface) { - return _virNWFilterInstantiateFilter(conn, net, - 0, - INSTANTIATE_FOLLOW_NEWFILTER); + bool foundNewFilter = false; + + int rc = _virNWFilterInstantiateFilter(conn, net, + 0, + INSTANTIATE_FOLLOW_NEWFILTER, + &foundNewFilter); + + *skipIface = !foundNewFilter; + return rc; } int virNWFilterRollbackUpdateFilter(virConnectPtr conn, @@ -993,6 +1008,7 @@ virNWFilterDomainFWUpdateCB(void *payload, virDomainDefPtr vm = obj->def; struct domUpdateCBStruct *cb = data; int i; + bool skipIface; virDomainObjLock(obj); @@ -1003,15 +1019,29 @@ virNWFilterDomainFWUpdateCB(void *payload, switch (cb->step) { case STEP_APPLY_NEW: cb->err = virNWFilterUpdateInstantiateFilter(cb->conn, - net); + net, + &skipIface); + if (cb->err == 0 && skipIface == true) { + // filter tree unchanged -- no update needed + cb->err = virHashAddEntry(cb->skipInterfaces, + net->ifname, + (void *)~0); + if (cb->err) + virReportOOMError(); + } break; case STEP_TEAR_NEW: - cb->err = virNWFilterRollbackUpdateFilter(cb->conn, net); + if ( !virHashLookup(cb->skipInterfaces, net->ifname)) { + cb->err = virNWFilterRollbackUpdateFilter(cb->conn, + net); + } break; case STEP_TEAR_OLD: - cb->err = virNWFilterTearOldFilter(cb->conn, net); + if ( !virHashLookup(cb->skipInterfaces, net->ifname)) { + cb->err = virNWFilterTearOldFilter(cb->conn, net); + } break; } if (cb->err) diff --git a/src/nwfilter/nwfilter_gentech_driver.h b/src/nwfilter/nwfilter_gentech_driver.h index 646a558d29..7328c516e3 100644 --- a/src/nwfilter/nwfilter_gentech_driver.h +++ b/src/nwfilter/nwfilter_gentech_driver.h @@ -40,7 +40,8 @@ enum instCase { int virNWFilterInstantiateFilter(virConnectPtr conn, const virDomainNetDefPtr net); int virNWFilterUpdateInstantiateFilter(virConnectPtr conn, - const virDomainNetDefPtr net); + const virDomainNetDefPtr net, + bool *skipIface); int virNWFilterRollbackUpdateFilter(virConnectPtr conn, const virDomainNetDefPtr net);