[libvirt] [PATCH 00/14] nwfilter: refactor the driver to make it independent of virt drivers

Today the nwfilter driver is entangled with the virt drivers in both directions. At various times when rebuilding filters nwfilter will call out to the virt driver to iterate over running guest's NICs. This has caused very complicated lock ordering rules to be required. If we are to split the virt drivers out into separate daemons we need to get rid of this coupling since we don't want the separate daemons calling each other, as that risks deadlock if all of the RPC workers are busy. The obvious way to solve this is to have the nwfilter driver remember all the filters it has active, avoiding the need to iterate over running guests. NB, these patches are all ready for review, but the last patch really should not be merged at this time. I need to do more work to be able to serialize the filter state to disk, so the nwfilter driver can keep track of it across daemon restarts. All except the last patch should be ok to merge though. Daniel P. Berrangé (14): nwfilter: remove pointless virNWFilterHashTable struct nwfilter: remove methods that are trivial wrappers for virHash APIs nwfilter: remove virNWFilterHashTable typedefs entirely nwfilter: make virNWFilterIPAddrLearnReq type private nwfilter: remove obsolete code related to firewalld nwfilter: fix leaking of filter parameters upon error nwfilter: introduce virNWFilterBinding to decouple from virDomainNet nwfilter: pass vm name in when instantiating filters nwfilter: convert the gentech driver code to use virNWFilterBinding nwfilter: convert IP address learning code to virNWFilterBinding nwfilter: convert DHCP address snooping code to virNWFilterBinding nwfilter: report an error if nic needs filtering by no driver is present nwfilter: keep track of active filter bindings nwfilter: remove virt driver callback layer for rebuilding filters src/conf/domain_conf.c | 8 +- src/conf/domain_conf.h | 2 +- src/conf/domain_nwfilter.c | 14 +- src/conf/domain_nwfilter.h | 6 +- src/conf/nwfilter_conf.c | 224 ++++++++--------- src/conf/nwfilter_conf.h | 67 ++--- src/conf/nwfilter_ipaddrmap.c | 15 +- src/conf/nwfilter_params.c | 127 +++------- src/conf/nwfilter_params.h | 33 +-- src/conf/virnwfilterobj.c | 4 +- src/conf/virnwfilterobj.h | 4 +- src/libvirt_private.syms | 8 +- src/lxc/lxc_driver.c | 28 --- src/lxc/lxc_process.c | 2 +- src/nwfilter/nwfilter_dhcpsnoop.c | 153 +++++------- src/nwfilter/nwfilter_dhcpsnoop.h | 7 +- src/nwfilter/nwfilter_driver.c | 97 +++++--- src/nwfilter/nwfilter_driver.h | 2 - src/nwfilter/nwfilter_gentech_driver.c | 432 ++++++++++++++++++--------------- src/nwfilter/nwfilter_gentech_driver.h | 28 +-- src/nwfilter/nwfilter_learnipaddr.c | 113 ++++----- src/nwfilter/nwfilter_learnipaddr.h | 25 +- src/nwfilter/nwfilter_tech_driver.h | 2 +- src/qemu/qemu_driver.c | 25 -- src/qemu/qemu_hotplug.c | 6 +- src/qemu/qemu_interface.c | 4 +- src/qemu/qemu_process.c | 2 +- src/uml/uml_conf.c | 2 +- src/uml/uml_driver.c | 29 --- tests/nwfilterxml2firewalltest.c | 36 +-- 30 files changed, 642 insertions(+), 863 deletions(-) -- 2.14.3

The virNWFilterHashTable struct only contains a single virHashTable member since commit 293d4fe2f11db98c91175525056c8883725d4b22 Author: Daniel P. Berrange <berrange@redhat.com> Date: Mon Mar 24 16:35:23 2014 +0000 Remove pointless storage of var names in virNWFilterHashTable Thus, this struct wrapper adds no real value over just using the virHashTable directly, but brings the complexity of needing to derefence the hashtable to call virHash* APIs, and adds extra memory allocation step. To minimize code churn this just turns virNWFilterHashTable into a typedef aliases virHashTable. Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/conf/nwfilter_ipaddrmap.c | 6 ++--- src/conf/nwfilter_params.c | 49 +++++++++++----------------------- src/conf/nwfilter_params.h | 8 ++---- src/nwfilter/nwfilter_dhcpsnoop.c | 4 +-- src/nwfilter/nwfilter_gentech_driver.c | 14 +++++----- tests/nwfilterxml2firewalltest.c | 2 +- 6 files changed, 31 insertions(+), 52 deletions(-) diff --git a/src/conf/nwfilter_ipaddrmap.c b/src/conf/nwfilter_ipaddrmap.c index 54e6d0f0f4..680667bac9 100644 --- a/src/conf/nwfilter_ipaddrmap.c +++ b/src/conf/nwfilter_ipaddrmap.c @@ -61,7 +61,7 @@ virNWFilterIPAddrMapAddIPAddr(const char *ifname, char *addr) virMutexLock(&ipAddressMapLock); - val = virHashLookup(ipAddressMap->hashTable, ifname); + val = virHashLookup(ipAddressMap, ifname); if (!val) { val = virNWFilterVarValueCreateSimple(addrCopy); if (!val) @@ -109,7 +109,7 @@ virNWFilterIPAddrMapDelIPAddr(const char *ifname, const char *ipaddr) virMutexLock(&ipAddressMapLock); if (ipaddr != NULL) { - val = virHashLookup(ipAddressMap->hashTable, ifname); + val = virHashLookup(ipAddressMap, ifname); if (val) { if (virNWFilterVarValueGetCardinality(val) == 1 && STREQ(ipaddr, @@ -144,7 +144,7 @@ virNWFilterIPAddrMapGetIPAddr(const char *ifname) virMutexLock(&ipAddressMapLock); - res = virHashLookup(ipAddressMap->hashTable, ifname); + res = virHashLookup(ipAddressMap, ifname); virMutexUnlock(&ipAddressMapLock); diff --git a/src/conf/nwfilter_params.c b/src/conf/nwfilter_params.c index 3a01049182..e833c8cb5d 100644 --- a/src/conf/nwfilter_params.c +++ b/src/conf/nwfilter_params.c @@ -355,7 +355,7 @@ virNWFilterVarCombIterAddVariable(virNWFilterVarCombIterEntryPtr cie, unsigned int maxValue = 0, minValue = 0; const char *varName = virNWFilterVarAccessGetVarName(varAccess); - varValue = virHashLookup(hash->hashTable, varName); + varValue = virHashLookup(hash, varName); if (varValue == NULL) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not find value for variable '%s'"), @@ -421,7 +421,7 @@ virNWFilterVarCombIterEntryAreUniqueEntries(virNWFilterVarCombIterEntryPtr cie, virNWFilterVarValuePtr varValue, tmp; const char *value; - varValue = virHashLookup(hash->hashTable, cie->varNames[0]); + varValue = virHashLookup(hash, cie->varNames[0]); if (!varValue) { /* caller's error */ VIR_ERROR(_("hash lookup resulted in NULL pointer")); @@ -439,7 +439,7 @@ virNWFilterVarCombIterEntryAreUniqueEntries(virNWFilterVarCombIterEntryPtr cie, if (STREQ(value, virNWFilterVarValueGetNthValue(varValue, i))) { bool isSame = true; for (j = 1; j < cie->nVarNames; j++) { - tmp = virHashLookup(hash->hashTable, cie->varNames[j]); + tmp = virHashLookup(hash, cie->varNames[j]); if (!tmp) { /* should never occur to step on a NULL here */ return true; @@ -604,7 +604,7 @@ virNWFilterVarCombIterGetVarValue(virNWFilterVarCombIterPtr ci, return NULL; } - value = virHashLookup(ci->hashTable->hashTable, varName); + value = virHashLookup(ci->hashTable, varName); if (!value) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not find value for variable '%s'"), @@ -648,11 +648,11 @@ virNWFilterHashTablePut(virNWFilterHashTablePtr table, const char *name, virNWFilterVarValuePtr val) { - if (!virHashLookup(table->hashTable, name)) { - if (virHashAddEntry(table->hashTable, name, val) < 0) + if (!virHashLookup(table, name)) { + if (virHashAddEntry(table, name, val) < 0) return -1; } else { - if (virHashUpdateEntry(table->hashTable, name, val) < 0) + if (virHashUpdateEntry(table, name, val) < 0) return -1; } return 0; @@ -671,27 +671,14 @@ virNWFilterHashTablePut(virNWFilterHashTablePtr table, void virNWFilterHashTableFree(virNWFilterHashTablePtr table) { - if (!table) - return; - virHashFree(table->hashTable); - - VIR_FREE(table); + virHashFree(table); } virNWFilterHashTablePtr virNWFilterHashTableCreate(int n) { - virNWFilterHashTablePtr ret; - - if (VIR_ALLOC(ret) < 0) - return NULL; - ret->hashTable = virHashCreate(n, hashDataFree); - if (!ret->hashTable) { - VIR_FREE(ret); - return NULL; - } - return ret; + return virHashCreate(n, hashDataFree); } @@ -699,7 +686,7 @@ void * virNWFilterHashTableRemoveEntry(virNWFilterHashTablePtr ht, const char *entry) { - return virHashSteal(ht->hashTable, entry); + return virHashSteal(ht, entry); } @@ -745,7 +732,7 @@ virNWFilterHashTablePutAll(virNWFilterHashTablePtr src, .errOccurred = 0, }; - virHashForEach(src->hashTable, addToTable, &atts); + virHashForEach(src, addToTable, &atts); if (atts.errOccurred) goto err_exit; @@ -770,11 +757,7 @@ bool virNWFilterHashTableEqual(virNWFilterHashTablePtr a, virNWFilterHashTablePtr b) { - if (!(a || b)) - return true; - if (!(a && b)) - return false; - return virHashEqual(a->hashTable, b->hashTable, virNWFilterVarValueCompare); + return virHashEqual(a, b, virNWFilterVarValueCompare); } static bool @@ -819,7 +802,7 @@ virNWFilterParseParamAttributes(xmlNodePtr cur) goto skip_entry; if (!isValidVarValue(val)) goto skip_entry; - value = virHashLookup(table->hashTable, nam); + value = virHashLookup(table, nam); if (value) { /* add value to existing value -> list */ if (virNWFilterVarValueAddValue(value, val) < 0) { @@ -871,7 +854,7 @@ virNWFilterFormatParamAttributes(virBufferPtr buf, size_t i, j; int card, numKeys; - numKeys = virHashSize(table->hashTable); + numKeys = virHashSize(table); if (numKeys < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", @@ -879,7 +862,7 @@ virNWFilterFormatParamAttributes(virBufferPtr buf, return -1; } - items = virHashGetItems(table->hashTable, + items = virHashGetItems(table, virNWFilterFormatParameterNameSorter); if (!items) return -1; @@ -1103,7 +1086,7 @@ virNWFilterVarAccessIsAvailable(const virNWFilterVarAccess *varAccess, unsigned int idx; virNWFilterVarValuePtr varValue; - varValue = virHashLookup(hash->hashTable, varName); + varValue = virHashLookup(hash, varName); if (!varValue) return false; diff --git a/src/conf/nwfilter_params.h b/src/conf/nwfilter_params.h index abd5b85fec..b3ed3e6418 100644 --- a/src/conf/nwfilter_params.h +++ b/src/conf/nwfilter_params.h @@ -63,12 +63,8 @@ int virNWFilterVarValueAddValue(virNWFilterVarValuePtr val, char *value); int virNWFilterVarValueAddValueCopy(virNWFilterVarValuePtr val, const char *value); int virNWFilterVarValueDelValue(virNWFilterVarValuePtr val, const char *value); -typedef struct _virNWFilterHashTable virNWFilterHashTable; -typedef virNWFilterHashTable *virNWFilterHashTablePtr; -struct _virNWFilterHashTable { - virHashTablePtr hashTable; -}; - +typedef virHashTable virNWFilterHashTable; +typedef virHashTable *virNWFilterHashTablePtr; virNWFilterHashTablePtr virNWFilterParseParamAttributes(xmlNodePtr cur); int virNWFilterFormatParamAttributes(virBufferPtr buf, diff --git a/src/nwfilter/nwfilter_dhcpsnoop.c b/src/nwfilter/nwfilter_dhcpsnoop.c index 6069e70460..d1e3f836a1 100644 --- a/src/nwfilter/nwfilter_dhcpsnoop.c +++ b/src/nwfilter/nwfilter_dhcpsnoop.c @@ -883,7 +883,7 @@ virNWFilterSnoopReqLeaseDel(virNWFilterSnoopReqPtr req, req->vars); } else { virNWFilterVarValuePtr dhcpsrvrs = - virHashLookup(req->vars->hashTable, NWFILTER_VARNAME_DHCPSERVER); + virHashLookup(req->vars, NWFILTER_VARNAME_DHCPSERVER); if (req->techdriver && req->techdriver->applyDHCPOnlyRules(req->ifname, &req->macaddr, @@ -1648,7 +1648,7 @@ virNWFilterDHCPSnoopReq(virNWFilterTechDriverPtr techdriver, goto exit_snoopreqput; } - dhcpsrvrs = virHashLookup(filterparams->hashTable, + dhcpsrvrs = virHashLookup(filterparams, NWFILTER_VARNAME_DHCPSERVER); if (techdriver->applyDHCPOnlyRules(req->ifname, &req->macaddr, diff --git a/src/nwfilter/nwfilter_gentech_driver.c b/src/nwfilter/nwfilter_gentech_driver.c index 5ef26b6afb..4706f1f1da 100644 --- a/src/nwfilter/nwfilter_gentech_driver.c +++ b/src/nwfilter/nwfilter_gentech_driver.c @@ -153,7 +153,7 @@ virNWFilterVarHashmapAddStdValues(virNWFilterHashTablePtr table, if (!val) return -1; - if (virHashAddEntry(table->hashTable, + if (virHashAddEntry(table, NWFILTER_STD_VAR_MAC, val) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, @@ -167,7 +167,7 @@ virNWFilterVarHashmapAddStdValues(virNWFilterHashTablePtr table, if (!val) return -1; - if (virHashAddEntry(table->hashTable, + if (virHashAddEntry(table, NWFILTER_STD_VAR_IP, val) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, @@ -633,7 +633,7 @@ virNWFilterDoInstantiate(const unsigned char *vmuuid, if (rc < 0) goto err_exit; - lv = virHashLookup(vars->hashTable, NWFILTER_VARNAME_CTRL_IP_LEARNING); + lv = virHashLookup(vars, NWFILTER_VARNAME_CTRL_IP_LEARNING); if (lv) learning = virNWFilterVarValueGetNthValue(lv, 0); else @@ -642,8 +642,8 @@ virNWFilterDoInstantiate(const unsigned char *vmuuid, if (learning == NULL) learning = NWFILTER_DFLT_LEARN; - if (virHashSize(missing_vars->hashTable) == 1) { - if (virHashLookup(missing_vars->hashTable, + if (virHashSize(missing_vars) == 1) { + if (virHashLookup(missing_vars, NWFILTER_STD_VAR_IP) != NULL) { if (STRCASEEQ(learning, "none")) { /* no learning */ reportIP = true; @@ -677,7 +677,7 @@ virNWFilterDoInstantiate(const unsigned char *vmuuid, } else { goto err_unresolvable_vars; } - } else if (virHashSize(missing_vars->hashTable) > 1) { + } else if (virHashSize(missing_vars) > 1) { goto err_unresolvable_vars; } else if (!forceWithPendingReq && virNWFilterLookupLearnReq(ifindex) != NULL) { @@ -729,7 +729,7 @@ virNWFilterDoInstantiate(const unsigned char *vmuuid, err_unresolvable_vars: - buf = virNWFilterPrintVars(missing_vars->hashTable, ", ", false, reportIP); + buf = virNWFilterPrintVars(missing_vars, ", ", false, reportIP); if (buf) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Cannot instantiate filter due to unresolvable " diff --git a/tests/nwfilterxml2firewalltest.c b/tests/nwfilterxml2firewalltest.c index b5eec538c4..bf1400d2d0 100644 --- a/tests/nwfilterxml2firewalltest.c +++ b/tests/nwfilterxml2firewalltest.c @@ -333,7 +333,7 @@ static int testSetOneParameter(virNWFilterHashTablePtr vars, int ret = -1; virNWFilterVarValuePtr val; - if ((val = virHashLookup(vars->hashTable, name)) == NULL) { + if ((val = virHashLookup(vars, name)) == NULL) { val = virNWFilterVarValueCreateSimpleCopyValue(value); if (!val) goto cleanup; -- 2.14.3

On Fri, Apr 27, 2018 at 16:25:00 +0100, Daniel P. Berrangé wrote:
The virNWFilterHashTable struct only contains a single virHashTable member since
commit 293d4fe2f11db98c91175525056c8883725d4b22 Author: Daniel P. Berrange <berrange@redhat.com> Date: Mon Mar 24 16:35:23 2014 +0000
Remove pointless storage of var names in virNWFilterHashTable
Thus, this struct wrapper adds no real value over just using the virHashTable directly, but brings the complexity of needing to derefence the hashtable to call virHash* APIs, and adds extra memory allocation step.
To minimize code churn this just turns virNWFilterHashTable into a typedef aliases virHashTable.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/conf/nwfilter_ipaddrmap.c | 6 ++--- src/conf/nwfilter_params.c | 49 +++++++++++----------------------- src/conf/nwfilter_params.h | 8 ++---- src/nwfilter/nwfilter_dhcpsnoop.c | 4 +-- src/nwfilter/nwfilter_gentech_driver.c | 14 +++++----- tests/nwfilterxml2firewalltest.c | 2 +- 6 files changed, 31 insertions(+), 52 deletions(-)
Reviewed-by: Jiri Denemark <jdenemar@redhat.com>

This removes the virNWFilterHashTableFree, virNWFilterHashTablePut and virNWFilterHashTableRemove methods, in favour of just calling the virHash APIs directly. The virNWFilterHashTablePut method was unreasonably complex because the virHashUpdateEntry already knows how to create the entry if it does not currently exist. Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/conf/domain_conf.c | 6 ++-- src/conf/nwfilter_conf.c | 2 +- src/conf/nwfilter_ipaddrmap.c | 7 ++-- src/conf/nwfilter_params.c | 62 ++-------------------------------- src/conf/nwfilter_params.h | 6 ---- src/libvirt_private.syms | 3 -- src/nwfilter/nwfilter_dhcpsnoop.c | 4 +-- src/nwfilter/nwfilter_gentech_driver.c | 18 +++++----- src/nwfilter/nwfilter_learnipaddr.c | 4 +-- tests/nwfilterxml2firewalltest.c | 10 +++--- 10 files changed, 28 insertions(+), 94 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index b0257068da..627058a144 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -2093,7 +2093,7 @@ virDomainNetDefClear(virDomainNetDefPtr def) virDomainDeviceInfoClear(&def->info); VIR_FREE(def->filter); - virNWFilterHashTableFree(def->filterparams); + virHashFree(def->filterparams); def->filterparams = NULL; virNetDevBandwidthFree(def->bandwidth); @@ -11046,7 +11046,7 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt, goto error; } filter = virXMLPropString(cur, "filter"); - virNWFilterHashTableFree(filterparams); + virHashFree(filterparams); filterparams = virNWFilterParseParamAttributes(cur); } else if ((flags & VIR_DOMAIN_DEF_PARSE_STATUS) && virXMLNodeNameEqual(cur, "state")) { @@ -11679,7 +11679,7 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt, VIR_FREE(vhost_path); VIR_FREE(localaddr); VIR_FREE(localport); - virNWFilterHashTableFree(filterparams); + virHashFree(filterparams); return def; diff --git a/src/conf/nwfilter_conf.c b/src/conf/nwfilter_conf.c index fd42d58c2c..5d04f2a93c 100644 --- a/src/conf/nwfilter_conf.c +++ b/src/conf/nwfilter_conf.c @@ -312,7 +312,7 @@ virNWFilterIncludeDefFree(virNWFilterIncludeDefPtr inc) { if (!inc) return; - virNWFilterHashTableFree(inc->params); + virHashFree(inc->params); VIR_FREE(inc->filterref); VIR_FREE(inc); } diff --git a/src/conf/nwfilter_ipaddrmap.c b/src/conf/nwfilter_ipaddrmap.c index 680667bac9..a921d7cfd6 100644 --- a/src/conf/nwfilter_ipaddrmap.c +++ b/src/conf/nwfilter_ipaddrmap.c @@ -67,7 +67,7 @@ virNWFilterIPAddrMapAddIPAddr(const char *ifname, char *addr) if (!val) goto cleanup; addrCopy = NULL; - ret = virNWFilterHashTablePut(ipAddressMap, ifname, val); + ret = virHashUpdateEntry(ipAddressMap, ifname, val); if (ret < 0) virNWFilterVarValueFree(val); goto cleanup; @@ -121,8 +121,7 @@ virNWFilterIPAddrMapDelIPAddr(const char *ifname, const char *ipaddr) } else { remove_entry: /* remove whole entry */ - val = virNWFilterHashTableRemoveEntry(ipAddressMap, ifname); - virNWFilterVarValueFree(val); + virHashRemoveEntry(ipAddressMap, ifname); ret = 0; } @@ -164,6 +163,6 @@ virNWFilterIPAddrMapInit(void) void virNWFilterIPAddrMapShutdown(void) { - virNWFilterHashTableFree(ipAddressMap); + virHashFree(ipAddressMap); ipAddressMap = NULL; } diff --git a/src/conf/nwfilter_params.c b/src/conf/nwfilter_params.c index e833c8cb5d..ee9c063941 100644 --- a/src/conf/nwfilter_params.c +++ b/src/conf/nwfilter_params.c @@ -631,65 +631,12 @@ hashDataFree(void *payload, const void *name ATTRIBUTE_UNUSED) } -/** - * virNWFilterHashTablePut: - * @table: Pointer to a virNWFilterHashTable - * @name: name of the key to enter - * @val: The value associated with the key - * @freeName: Whether the name must be freed on table destruction - * - * Returns 0 on success, -1 on failure. - * - * Put an entry into the hashmap replacing and freeing an existing entry - * if one existed. - */ -int -virNWFilterHashTablePut(virNWFilterHashTablePtr table, - const char *name, - virNWFilterVarValuePtr val) -{ - if (!virHashLookup(table, name)) { - if (virHashAddEntry(table, name, val) < 0) - return -1; - } else { - if (virHashUpdateEntry(table, name, val) < 0) - return -1; - } - return 0; -} - - -/** - * virNWFilterHashTableFree: - * @table: Pointer to virNWFilterHashTable - * - * Free a hashtable de-allocating memory for all its entries. - * - * All hash tables within the NWFilter driver must use this - * function to deallocate and free their content. - */ -void -virNWFilterHashTableFree(virNWFilterHashTablePtr table) -{ - virHashFree(table); -} - - virNWFilterHashTablePtr virNWFilterHashTableCreate(int n) { return virHashCreate(n, hashDataFree); } - -void * -virNWFilterHashTableRemoveEntry(virNWFilterHashTablePtr ht, - const char *entry) -{ - return virHashSteal(ht, entry); -} - - struct addToTableStruct { virNWFilterHashTablePtr target; int errOccurred; @@ -711,10 +658,7 @@ addToTable(void *payload, const void *name, void *data) return 0; } - if (virNWFilterHashTablePut(atts->target, (const char *)name, val) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Could not put variable '%s' into hashmap"), - (const char *)name); + if (virHashUpdateEntry(atts->target, (const char *)name, val) < 0) { atts->errOccurred = 1; virNWFilterVarValueFree(val); } @@ -814,7 +758,7 @@ virNWFilterParseParamAttributes(xmlNodePtr cur) value = virNWFilterParseVarValue(val); if (!value) goto skip_entry; - if (virNWFilterHashTablePut(table, nam, value) < 0) + if (virHashUpdateEntry(table, nam, value) < 0) goto err_exit; } value = NULL; @@ -833,7 +777,7 @@ virNWFilterParseParamAttributes(xmlNodePtr cur) VIR_FREE(nam); VIR_FREE(val); virNWFilterVarValueFree(value); - virNWFilterHashTableFree(table); + virHashFree(table); return NULL; } diff --git a/src/conf/nwfilter_params.h b/src/conf/nwfilter_params.h index b3ed3e6418..b24f023633 100644 --- a/src/conf/nwfilter_params.h +++ b/src/conf/nwfilter_params.h @@ -72,12 +72,6 @@ int virNWFilterFormatParamAttributes(virBufferPtr buf, const char *filterref); virNWFilterHashTablePtr virNWFilterHashTableCreate(int n); -void virNWFilterHashTableFree(virNWFilterHashTablePtr table); -int virNWFilterHashTablePut(virNWFilterHashTablePtr table, - const char *name, - virNWFilterVarValuePtr val); -void *virNWFilterHashTableRemoveEntry(virNWFilterHashTablePtr table, - const char *name); int virNWFilterHashTablePutAll(virNWFilterHashTablePtr src, virNWFilterHashTablePtr dest); bool virNWFilterHashTableEqual(virNWFilterHashTablePtr a, diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index d2728749fb..bf17d17777 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -820,10 +820,7 @@ virNWFilterIPAddrMapShutdown; # conf/nwfilter_params.h virNWFilterHashTableCreate; virNWFilterHashTableEqual; -virNWFilterHashTableFree; -virNWFilterHashTablePut; virNWFilterHashTablePutAll; -virNWFilterHashTableRemoveEntry; virNWFilterVarAccessGetVarName; virNWFilterVarAccessIsAvailable; virNWFilterVarAccessPrint; diff --git a/src/nwfilter/nwfilter_dhcpsnoop.c b/src/nwfilter/nwfilter_dhcpsnoop.c index d1e3f836a1..d23cad3b75 100644 --- a/src/nwfilter/nwfilter_dhcpsnoop.c +++ b/src/nwfilter/nwfilter_dhcpsnoop.c @@ -636,7 +636,7 @@ virNWFilterSnoopReqFree(virNWFilterSnoopReqPtr req) VIR_FREE(req->ifname); VIR_FREE(req->linkdev); VIR_FREE(req->filtername); - virNWFilterHashTableFree(req->vars); + virHashFree(req->vars); virMutexDestroy(&req->lock); virCondDestroy(&req->threadStatusCond); @@ -1617,7 +1617,7 @@ virNWFilterDHCPSnoopReq(virNWFilterTechDriverPtr techdriver, } /* a recycled req may still have filtername and vars */ VIR_FREE(req->filtername); - virNWFilterHashTableFree(req->vars); + virHashFree(req->vars); } else { req = virNWFilterSnoopReqNew(ifkey); if (!req) diff --git a/src/nwfilter/nwfilter_gentech_driver.c b/src/nwfilter/nwfilter_gentech_driver.c index 4706f1f1da..130a366d67 100644 --- a/src/nwfilter/nwfilter_gentech_driver.c +++ b/src/nwfilter/nwfilter_gentech_driver.c @@ -123,7 +123,7 @@ virNWFilterRuleInstFree(virNWFilterRuleInstPtr inst) if (!inst) return; - virNWFilterHashTableFree(inst->vars); + virHashFree(inst->vars); VIR_FREE(inst); } @@ -200,7 +200,7 @@ virNWFilterCreateVarHashmap(char *macaddr, return NULL; if (virNWFilterVarHashmapAddStdValues(table, macaddr, ipaddr) < 0) { - virNWFilterHashTableFree(table); + virHashFree(table); return NULL; } return table; @@ -295,7 +295,7 @@ virNWFilterCreateVarsFrom(virNWFilterHashTablePtr vars1, return res; err_exit: - virNWFilterHashTableFree(res); + virHashFree(res); return NULL; } @@ -424,7 +424,7 @@ virNWFilterIncludeDefToRuleInst(virNWFilterDriverStatePtr driver, cleanup: if (ret < 0) virNWFilterInstReset(inst); - virNWFilterHashTableFree(tmpvars); + virHashFree(tmpvars); if (obj) virNWFilterObjUnlock(obj); return ret; @@ -524,7 +524,7 @@ virNWFilterDetermineMissingVarsRec(virNWFilterDefPtr filter, } varAccess = virBufferContentAndReset(&buf); - rc = virNWFilterHashTablePut(missing_vars, varAccess, val); + rc = virHashUpdateEntry(missing_vars, varAccess, val); VIR_FREE(varAccess); if (rc < 0) { virNWFilterVarValueFree(val); @@ -562,7 +562,7 @@ virNWFilterDetermineMissingVarsRec(virNWFilterDefPtr filter, useNewFilter, driver); - virNWFilterHashTableFree(tmpvars); + virHashFree(tmpvars); virNWFilterObjUnlock(obj); if (rc < 0) @@ -723,7 +723,7 @@ virNWFilterDoInstantiate(const unsigned char *vmuuid, err_exit: virNWFilterInstReset(&inst); - virNWFilterHashTableFree(missing_vars); + virHashFree(missing_vars); return rc; @@ -832,10 +832,10 @@ virNWFilterInstantiateFilterUpdate(virNWFilterDriverStatePtr driver, teardownOld, macaddr, driver, forceWithPendingReq); - virNWFilterHashTableFree(vars); + virHashFree(vars); err_exit_vars1: - virNWFilterHashTableFree(vars1); + virHashFree(vars1); err_exit: virNWFilterObjUnlock(obj); diff --git a/src/nwfilter/nwfilter_learnipaddr.c b/src/nwfilter/nwfilter_learnipaddr.c index 9ca0639576..f5b94cf27d 100644 --- a/src/nwfilter/nwfilter_learnipaddr.c +++ b/src/nwfilter/nwfilter_learnipaddr.c @@ -216,7 +216,7 @@ virNWFilterIPAddrLearnReqFree(virNWFilterIPAddrLearnReqPtr req) return; VIR_FREE(req->filtername); - virNWFilterHashTableFree(req->filterparams); + virHashFree(req->filterparams); VIR_FREE(req); } @@ -765,7 +765,7 @@ virNWFilterLearnIPAddress(virNWFilterTechDriverPtr techdriver, err_dereg_req: virNWFilterDeregisterLearnReq(ifindex); err_free_ht: - virNWFilterHashTableFree(ht); + virHashFree(ht); err_free_req: virNWFilterIPAddrLearnReqFree(req); err_no_req: diff --git a/tests/nwfilterxml2firewalltest.c b/tests/nwfilterxml2firewalltest.c index bf1400d2d0..a51ad9412a 100644 --- a/tests/nwfilterxml2firewalltest.c +++ b/tests/nwfilterxml2firewalltest.c @@ -164,7 +164,7 @@ virNWFilterCreateVarsFrom(virNWFilterHashTablePtr vars1, return res; err_exit: - virNWFilterHashTableFree(res); + virHashFree(res); return NULL; } @@ -175,7 +175,7 @@ virNWFilterRuleInstFree(virNWFilterRuleInstPtr inst) if (!inst) return; - virNWFilterHashTableFree(inst->vars); + virHashFree(inst->vars); VIR_FREE(inst); } @@ -263,7 +263,7 @@ virNWFilterIncludeDefToRuleInst(virNWFilterIncludeDefPtr inc, cleanup: if (ret < 0) virNWFilterInstReset(inst); - virNWFilterHashTableFree(tmpvars); + virHashFree(tmpvars); VIR_FREE(xml); return ret; } @@ -337,7 +337,7 @@ static int testSetOneParameter(virNWFilterHashTablePtr vars, val = virNWFilterVarValueCreateSimpleCopyValue(value); if (!val) goto cleanup; - if (virNWFilterHashTablePut(vars, name, val) < 0) { + if (virHashUpdateEntry(vars, name, val) < 0) { virNWFilterVarValueFree(val); goto cleanup; } @@ -414,7 +414,7 @@ static int testCompareXMLToArgvFiles(const char *xml, virBufferFreeAndReset(&buf); VIR_FREE(actualargv); virNWFilterInstReset(&inst); - virNWFilterHashTableFree(vars); + virHashFree(vars); return ret; } -- 2.14.3

On Fri, Apr 27, 2018 at 16:25:01 +0100, Daniel P. Berrangé wrote:
This removes the virNWFilterHashTableFree, virNWFilterHashTablePut and virNWFilterHashTableRemove methods, in favour of just calling the virHash APIs directly.
The virNWFilterHashTablePut method was unreasonably complex because the virHashUpdateEntry already knows how to create the entry if it does not currently exist.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/conf/domain_conf.c | 6 ++-- src/conf/nwfilter_conf.c | 2 +- src/conf/nwfilter_ipaddrmap.c | 7 ++-- src/conf/nwfilter_params.c | 62 ++-------------------------------- src/conf/nwfilter_params.h | 6 ---- src/libvirt_private.syms | 3 -- src/nwfilter/nwfilter_dhcpsnoop.c | 4 +-- src/nwfilter/nwfilter_gentech_driver.c | 18 +++++----- src/nwfilter/nwfilter_learnipaddr.c | 4 +-- tests/nwfilterxml2firewalltest.c | 10 +++--- 10 files changed, 28 insertions(+), 94 deletions(-)
Reviewed-by: Jiri Denemark <jdenemar@redhat.com>

All the code now just uses the virHashTablePtr type directly. Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/conf/domain_conf.c | 2 +- src/conf/domain_conf.h | 2 +- src/conf/nwfilter_conf.h | 2 +- src/conf/nwfilter_ipaddrmap.c | 2 +- src/conf/nwfilter_params.c | 26 ++++++++++----------- src/conf/nwfilter_params.h | 23 ++++++++----------- src/nwfilter/nwfilter_dhcpsnoop.c | 6 ++--- src/nwfilter/nwfilter_dhcpsnoop.h | 2 +- src/nwfilter/nwfilter_gentech_driver.c | 42 +++++++++++++++++----------------- src/nwfilter/nwfilter_gentech_driver.h | 4 ++-- src/nwfilter/nwfilter_learnipaddr.c | 6 ++--- src/nwfilter/nwfilter_learnipaddr.h | 4 ++-- src/nwfilter/nwfilter_tech_driver.h | 2 +- tests/nwfilterxml2firewalltest.c | 24 +++++++++---------- 14 files changed, 72 insertions(+), 75 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 627058a144..bdda11c599 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -10868,7 +10868,7 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt, char *vhostuser_type = NULL; char *trustGuestRxFilters = NULL; char *vhost_path = NULL; - virNWFilterHashTablePtr filterparams = NULL; + virHashTablePtr filterparams = NULL; virDomainActualNetDefPtr actual = NULL; xmlNodePtr oldnode = ctxt->node; virDomainChrSourceReconnectDef reconnect = {0}; diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 3c7eccb8ca..b954f4d462 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1057,7 +1057,7 @@ struct _virDomainNetDef { virNetDevIPInfo guestIP; virDomainDeviceInfo info; char *filter; - virNWFilterHashTablePtr filterparams; + virHashTablePtr filterparams; virNetDevBandwidthPtr bandwidth; virNetDevVlan vlan; int trustGuestRxFilters; /* enum virTristateBool */ diff --git a/src/conf/nwfilter_conf.h b/src/conf/nwfilter_conf.h index f960bf3d56..a31db6d3ff 100644 --- a/src/conf/nwfilter_conf.h +++ b/src/conf/nwfilter_conf.h @@ -501,7 +501,7 @@ typedef struct _virNWFilterIncludeDef virNWFilterIncludeDef; typedef virNWFilterIncludeDef *virNWFilterIncludeDefPtr; struct _virNWFilterIncludeDef { char *filterref; - virNWFilterHashTablePtr params; + virHashTablePtr params; }; diff --git a/src/conf/nwfilter_ipaddrmap.c b/src/conf/nwfilter_ipaddrmap.c index a921d7cfd6..14a62c1a74 100644 --- a/src/conf/nwfilter_ipaddrmap.c +++ b/src/conf/nwfilter_ipaddrmap.c @@ -36,7 +36,7 @@ #define VIR_FROM_THIS VIR_FROM_NWFILTER static virMutex ipAddressMapLock = VIR_MUTEX_INITIALIZER; -static virNWFilterHashTablePtr ipAddressMap; +static virHashTablePtr ipAddressMap; /* Add an IP address to the list of IP addresses an interface is diff --git a/src/conf/nwfilter_params.c b/src/conf/nwfilter_params.c index ee9c063941..ffffc6bae8 100644 --- a/src/conf/nwfilter_params.c +++ b/src/conf/nwfilter_params.c @@ -348,7 +348,7 @@ virNWFilterVarCombIterEntryInit(virNWFilterVarCombIterEntryPtr cie, static int virNWFilterVarCombIterAddVariable(virNWFilterVarCombIterEntryPtr cie, - virNWFilterHashTablePtr hash, + virHashTablePtr hash, const virNWFilterVarAccess *varAccess) { virNWFilterVarValuePtr varValue; @@ -415,7 +415,7 @@ virNWFilterVarCombIterAddVariable(virNWFilterVarCombIterEntryPtr cie, */ static bool virNWFilterVarCombIterEntryAreUniqueEntries(virNWFilterVarCombIterEntryPtr cie, - virNWFilterHashTablePtr hash) + virHashTablePtr hash) { size_t i, j; virNWFilterVarValuePtr varValue, tmp; @@ -473,7 +473,7 @@ virNWFilterVarCombIterEntryAreUniqueEntries(virNWFilterVarCombIterEntryPtr cie, * be created. */ virNWFilterVarCombIterPtr -virNWFilterVarCombIterCreate(virNWFilterHashTablePtr hash, +virNWFilterVarCombIterCreate(virHashTablePtr hash, virNWFilterVarAccessPtr *varAccess, size_t nVarAccess) { @@ -631,14 +631,14 @@ hashDataFree(void *payload, const void *name ATTRIBUTE_UNUSED) } -virNWFilterHashTablePtr +virHashTablePtr virNWFilterHashTableCreate(int n) { return virHashCreate(n, hashDataFree); } struct addToTableStruct { - virNWFilterHashTablePtr target; + virHashTablePtr target; int errOccurred; }; @@ -668,8 +668,8 @@ addToTable(void *payload, const void *name, void *data) int -virNWFilterHashTablePutAll(virNWFilterHashTablePtr src, - virNWFilterHashTablePtr dest) +virNWFilterHashTablePutAll(virHashTablePtr src, + virHashTablePtr dest) { struct addToTableStruct atts = { .target = dest, @@ -698,8 +698,8 @@ virNWFilterVarValueCompare(const void *a, const void *b) } bool -virNWFilterHashTableEqual(virNWFilterHashTablePtr a, - virNWFilterHashTablePtr b) +virNWFilterHashTableEqual(virHashTablePtr a, + virHashTablePtr b) { return virHashEqual(a, b, virNWFilterVarValueCompare); } @@ -723,13 +723,13 @@ virNWFilterParseVarValue(const char *val) return virNWFilterVarValueCreateSimpleCopyValue(val); } -virNWFilterHashTablePtr +virHashTablePtr virNWFilterParseParamAttributes(xmlNodePtr cur) { char *nam, *val; virNWFilterVarValuePtr value; - virNWFilterHashTablePtr table = virNWFilterHashTableCreate(0); + virHashTablePtr table = virNWFilterHashTableCreate(0); if (!table) return NULL; @@ -791,7 +791,7 @@ virNWFilterFormatParameterNameSorter(const virHashKeyValuePair *a, int virNWFilterFormatParamAttributes(virBufferPtr buf, - virNWFilterHashTablePtr table, + virHashTablePtr table, const char *filterref) { virHashKeyValuePairPtr items; @@ -1023,7 +1023,7 @@ virNWFilterVarAccessGetIntIterId(const virNWFilterVarAccess *vap) bool virNWFilterVarAccessIsAvailable(const virNWFilterVarAccess *varAccess, - const virNWFilterHashTable *hash) + const virHashTable *hash) { const char *varName = virNWFilterVarAccessGetVarName(varAccess); const char *res; diff --git a/src/conf/nwfilter_params.h b/src/conf/nwfilter_params.h index b24f023633..9bdf65c033 100644 --- a/src/conf/nwfilter_params.h +++ b/src/conf/nwfilter_params.h @@ -63,19 +63,16 @@ int virNWFilterVarValueAddValue(virNWFilterVarValuePtr val, char *value); int virNWFilterVarValueAddValueCopy(virNWFilterVarValuePtr val, const char *value); int virNWFilterVarValueDelValue(virNWFilterVarValuePtr val, const char *value); -typedef virHashTable virNWFilterHashTable; -typedef virHashTable *virNWFilterHashTablePtr; - -virNWFilterHashTablePtr virNWFilterParseParamAttributes(xmlNodePtr cur); +virHashTablePtr virNWFilterParseParamAttributes(xmlNodePtr cur); int virNWFilterFormatParamAttributes(virBufferPtr buf, - virNWFilterHashTablePtr table, + virHashTablePtr table, const char *filterref); -virNWFilterHashTablePtr virNWFilterHashTableCreate(int n); -int virNWFilterHashTablePutAll(virNWFilterHashTablePtr src, - virNWFilterHashTablePtr dest); -bool virNWFilterHashTableEqual(virNWFilterHashTablePtr a, - virNWFilterHashTablePtr b); +virHashTablePtr virNWFilterHashTableCreate(int n); +int virNWFilterHashTablePutAll(virHashTablePtr src, + virHashTablePtr dest); +bool virNWFilterHashTableEqual(virHashTablePtr a, + virHashTablePtr b); # define VALID_VARNAME \ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_" @@ -123,7 +120,7 @@ virNWFilterVarAccessType virNWFilterVarAccessGetType( unsigned int virNWFilterVarAccessGetIterId(const virNWFilterVarAccess *vap); unsigned int virNWFilterVarAccessGetIndex(const virNWFilterVarAccess *vap); bool virNWFilterVarAccessIsAvailable(const virNWFilterVarAccess *vap, - const virNWFilterHashTable *hash); + const virHashTable *hash); typedef struct _virNWFilterVarCombIterEntry virNWFilterVarCombIterEntry; typedef virNWFilterVarCombIterEntry *virNWFilterVarCombIterEntryPtr; @@ -139,12 +136,12 @@ struct _virNWFilterVarCombIterEntry { typedef struct _virNWFilterVarCombIter virNWFilterVarCombIter; typedef virNWFilterVarCombIter *virNWFilterVarCombIterPtr; struct _virNWFilterVarCombIter { - virNWFilterHashTablePtr hashTable; + virHashTablePtr hashTable; size_t nIter; virNWFilterVarCombIterEntry iter[0]; }; virNWFilterVarCombIterPtr virNWFilterVarCombIterCreate( - virNWFilterHashTablePtr hash, + virHashTablePtr hash, virNWFilterVarAccessPtr *vars, size_t nVars); diff --git a/src/nwfilter/nwfilter_dhcpsnoop.c b/src/nwfilter/nwfilter_dhcpsnoop.c index d23cad3b75..aec68ab847 100644 --- a/src/nwfilter/nwfilter_dhcpsnoop.c +++ b/src/nwfilter/nwfilter_dhcpsnoop.c @@ -141,7 +141,7 @@ struct _virNWFilterSnoopReq { char ifkey[VIR_IFKEY_LEN]; virMacAddr macaddr; char *filtername; - virNWFilterHashTablePtr vars; + virHashTablePtr vars; virNWFilterDriverStatePtr driver; /* start and end of lease list, ordered by lease time */ virNWFilterSnoopIPLeasePtr start; @@ -1595,7 +1595,7 @@ virNWFilterDHCPSnoopReq(virNWFilterTechDriverPtr techdriver, const unsigned char *vmuuid, const virMacAddr *macaddr, const char *filtername, - virNWFilterHashTablePtr filterparams, + virHashTablePtr filterparams, virNWFilterDriverStatePtr driver) { virNWFilterSnoopReqPtr req; @@ -2239,7 +2239,7 @@ virNWFilterDHCPSnoopReq(virNWFilterTechDriverPtr techdriver ATTRIBUTE_UNUSED, const unsigned char *vmuuid ATTRIBUTE_UNUSED, const virMacAddr *macaddr ATTRIBUTE_UNUSED, const char *filtername ATTRIBUTE_UNUSED, - virNWFilterHashTablePtr filterparams ATTRIBUTE_UNUSED, + virHashTablePtr filterparams ATTRIBUTE_UNUSED, virNWFilterDriverStatePtr driver ATTRIBUTE_UNUSED) { virReportError(VIR_ERR_INTERNAL_ERROR, diff --git a/src/nwfilter/nwfilter_dhcpsnoop.h b/src/nwfilter/nwfilter_dhcpsnoop.h index 3ef96fa4e1..a5925de40a 100644 --- a/src/nwfilter/nwfilter_dhcpsnoop.h +++ b/src/nwfilter/nwfilter_dhcpsnoop.h @@ -35,7 +35,7 @@ int virNWFilterDHCPSnoopReq(virNWFilterTechDriverPtr techdriver, const unsigned char *vmuuid, const virMacAddr *macaddr, const char *filtername, - virNWFilterHashTablePtr filterparams, + virHashTablePtr filterparams, virNWFilterDriverStatePtr driver); void virNWFilterDHCPSnoopEnd(const char *ifname); #endif /* __NWFILTER_DHCPSNOOP_H */ diff --git a/src/nwfilter/nwfilter_gentech_driver.c b/src/nwfilter/nwfilter_gentech_driver.c index 130a366d67..0735426734 100644 --- a/src/nwfilter/nwfilter_gentech_driver.c +++ b/src/nwfilter/nwfilter_gentech_driver.c @@ -142,7 +142,7 @@ virNWFilterRuleInstFree(virNWFilterRuleInstPtr inst) * Adds a couple of standard keys (MAC, IP) to the hash table. */ static int -virNWFilterVarHashmapAddStdValues(virNWFilterHashTablePtr table, +virNWFilterVarHashmapAddStdValues(virHashTablePtr table, char *macaddr, const virNWFilterVarValue *ipaddr) { @@ -191,11 +191,11 @@ virNWFilterVarHashmapAddStdValues(virNWFilterHashTablePtr table, * * Returns pointer to hashmap, NULL if an error occurred. */ -virNWFilterHashTablePtr +virHashTablePtr virNWFilterCreateVarHashmap(char *macaddr, const virNWFilterVarValue *ipaddr) { - virNWFilterHashTablePtr table = virNWFilterHashTableCreate(0); + virHashTablePtr table = virNWFilterHashTableCreate(0); if (!table) return NULL; @@ -208,7 +208,7 @@ virNWFilterCreateVarHashmap(char *macaddr, /** - * Convert a virNWFilterHashTable into a string of comma-separated + * Convert a virHashTable into a string of comma-separated * variable names. */ struct printString @@ -278,11 +278,11 @@ virNWFilterPrintVars(virHashTablePtr vars, * Creates a new hash table with contents of var1 and var2 added where * contents of var2 will overwrite those of var1. */ -static virNWFilterHashTablePtr -virNWFilterCreateVarsFrom(virNWFilterHashTablePtr vars1, - virNWFilterHashTablePtr vars2) +static virHashTablePtr +virNWFilterCreateVarsFrom(virHashTablePtr vars1, + virHashTablePtr vars2) { - virNWFilterHashTablePtr res = virNWFilterHashTableCreate(0); + virHashTablePtr res = virNWFilterHashTableCreate(0); if (!res) return NULL; @@ -330,7 +330,7 @@ virNWFilterInstReset(virNWFilterInstPtr inst) static int virNWFilterDefToInst(virNWFilterDriverStatePtr driver, virNWFilterDefPtr def, - virNWFilterHashTablePtr vars, + virHashTablePtr vars, enum instCase useNewFilter, bool *foundNewFilter, virNWFilterInstPtr inst); @@ -338,7 +338,7 @@ virNWFilterDefToInst(virNWFilterDriverStatePtr driver, static int virNWFilterRuleDefToRuleInst(virNWFilterDefPtr def, virNWFilterRuleDefPtr rule, - virNWFilterHashTablePtr vars, + virHashTablePtr vars, virNWFilterInstPtr inst) { virNWFilterRuleInstPtr ruleinst; @@ -371,13 +371,13 @@ virNWFilterRuleDefToRuleInst(virNWFilterDefPtr def, static int virNWFilterIncludeDefToRuleInst(virNWFilterDriverStatePtr driver, virNWFilterIncludeDefPtr inc, - virNWFilterHashTablePtr vars, + virHashTablePtr vars, enum instCase useNewFilter, bool *foundNewFilter, virNWFilterInstPtr inst) { virNWFilterObjPtr obj; - virNWFilterHashTablePtr tmpvars = NULL; + virHashTablePtr tmpvars = NULL; virNWFilterDefPtr childdef; virNWFilterDefPtr newChilddef; int ret = -1; @@ -452,7 +452,7 @@ virNWFilterIncludeDefToRuleInst(virNWFilterDriverStatePtr driver, static int virNWFilterDefToInst(virNWFilterDriverStatePtr driver, virNWFilterDefPtr def, - virNWFilterHashTablePtr vars, + virHashTablePtr vars, enum instCase useNewFilter, bool *foundNewFilter, virNWFilterInstPtr inst) @@ -487,8 +487,8 @@ virNWFilterDefToInst(virNWFilterDriverStatePtr driver, static int virNWFilterDetermineMissingVarsRec(virNWFilterDefPtr filter, - virNWFilterHashTablePtr vars, - virNWFilterHashTablePtr missing_vars, + virHashTablePtr vars, + virHashTablePtr missing_vars, int useNewFilter, virNWFilterDriverStatePtr driver) { @@ -498,7 +498,7 @@ virNWFilterDetermineMissingVarsRec(virNWFilterDefPtr filter, virNWFilterDefPtr next_filter; virNWFilterDefPtr newNext_filter; virNWFilterVarValuePtr val; - virNWFilterHashTablePtr tmpvars; + virHashTablePtr tmpvars; for (i = 0; i < filter->nentries; i++) { virNWFilterRuleDefPtr rule = filter->filterEntries[i]->rule; @@ -600,7 +600,7 @@ virNWFilterDoInstantiate(const unsigned char *vmuuid, const char *ifname, int ifindex, const char *linkdev, - virNWFilterHashTablePtr vars, + virHashTablePtr vars, enum instCase useNewFilter, bool *foundNewFilter, bool teardownOld, @@ -616,7 +616,7 @@ virNWFilterDoInstantiate(const unsigned char *vmuuid, const char *learning; bool reportIP = false; - virNWFilterHashTablePtr missing_vars = virNWFilterHashTableCreate(0); + virHashTablePtr missing_vars = virNWFilterHashTableCreate(0); memset(&inst, 0, sizeof(inst)); @@ -754,7 +754,7 @@ virNWFilterInstantiateFilterUpdate(virNWFilterDriverStatePtr driver, const char *linkdev, const virMacAddr *macaddr, const char *filtername, - virNWFilterHashTablePtr filterparams, + virHashTablePtr filterparams, enum instCase useNewFilter, bool forceWithPendingReq, bool *foundNewFilter) @@ -763,7 +763,7 @@ virNWFilterInstantiateFilterUpdate(virNWFilterDriverStatePtr driver, const char *drvname = EBIPTABLES_DRIVER_ID; virNWFilterTechDriverPtr techdriver; virNWFilterObjPtr obj; - virNWFilterHashTablePtr vars, vars1; + virHashTablePtr vars, vars1; virNWFilterDefPtr filter; virNWFilterDefPtr newFilter; char vmmacaddr[VIR_MAC_STRING_BUFLEN] = {0}; @@ -896,7 +896,7 @@ virNWFilterInstantiateFilterLate(virNWFilterDriverStatePtr driver, const char *linkdev, const virMacAddr *macaddr, const char *filtername, - virNWFilterHashTablePtr filterparams) + virHashTablePtr filterparams) { int rc; bool foundNewFilter = false; diff --git a/src/nwfilter/nwfilter_gentech_driver.h b/src/nwfilter/nwfilter_gentech_driver.h index 71924879a2..67092157b8 100644 --- a/src/nwfilter/nwfilter_gentech_driver.h +++ b/src/nwfilter/nwfilter_gentech_driver.h @@ -53,11 +53,11 @@ int virNWFilterInstantiateFilterLate(virNWFilterDriverStatePtr driver, const char *linkdev, const virMacAddr *macaddr, const char *filtername, - virNWFilterHashTablePtr filterparams); + virHashTablePtr filterparams); int virNWFilterTeardownFilter(const virDomainNetDef *net); -virNWFilterHashTablePtr virNWFilterCreateVarHashmap(char *macaddr, +virHashTablePtr virNWFilterCreateVarHashmap(char *macaddr, const virNWFilterVarValue *value); int virNWFilterDomainFWUpdateCB(virDomainObjPtr vm, diff --git a/src/nwfilter/nwfilter_learnipaddr.c b/src/nwfilter/nwfilter_learnipaddr.c index f5b94cf27d..2401857ddb 100644 --- a/src/nwfilter/nwfilter_learnipaddr.c +++ b/src/nwfilter/nwfilter_learnipaddr.c @@ -692,14 +692,14 @@ virNWFilterLearnIPAddress(virNWFilterTechDriverPtr techdriver, const char *linkdev, const virMacAddr *macaddr, const char *filtername, - virNWFilterHashTablePtr filterparams, + virHashTablePtr filterparams, virNWFilterDriverStatePtr driver, enum howDetect howDetect) { int rc; virThread thread; virNWFilterIPAddrLearnReqPtr req = NULL; - virNWFilterHashTablePtr ht = NULL; + virHashTablePtr ht = NULL; if (howDetect == 0) return -1; @@ -781,7 +781,7 @@ virNWFilterLearnIPAddress(virNWFilterTechDriverPtr techdriver ATTRIBUTE_UNUSED, const char *linkdev ATTRIBUTE_UNUSED, const virMacAddr *macaddr ATTRIBUTE_UNUSED, const char *filtername ATTRIBUTE_UNUSED, - virNWFilterHashTablePtr filterparams ATTRIBUTE_UNUSED, + virHashTablePtr filterparams ATTRIBUTE_UNUSED, virNWFilterDriverStatePtr driver ATTRIBUTE_UNUSED, enum howDetect howDetect ATTRIBUTE_UNUSED) { diff --git a/src/nwfilter/nwfilter_learnipaddr.h b/src/nwfilter/nwfilter_learnipaddr.h index b93ed38cff..dc4c0d110f 100644 --- a/src/nwfilter/nwfilter_learnipaddr.h +++ b/src/nwfilter/nwfilter_learnipaddr.h @@ -44,7 +44,7 @@ struct _virNWFilterIPAddrLearnReq { char linkdev[IF_NAMESIZE]; virMacAddr macaddr; char *filtername; - virNWFilterHashTablePtr filterparams; + virHashTablePtr filterparams; virNWFilterDriverStatePtr driver; enum howDetect howDetect; @@ -58,7 +58,7 @@ int virNWFilterLearnIPAddress(virNWFilterTechDriverPtr techdriver, const char *linkdev, const virMacAddr *macaddr, const char *filtername, - virNWFilterHashTablePtr filterparams, + virHashTablePtr filterparams, virNWFilterDriverStatePtr driver, enum howDetect howDetect); diff --git a/src/nwfilter/nwfilter_tech_driver.h b/src/nwfilter/nwfilter_tech_driver.h index bc30496644..d2ac0077db 100644 --- a/src/nwfilter/nwfilter_tech_driver.h +++ b/src/nwfilter/nwfilter_tech_driver.h @@ -39,7 +39,7 @@ struct _virNWFilterRuleInst { virNWFilterChainPriority chainPriority; virNWFilterRuleDefPtr def; virNWFilterRulePriority priority; - virNWFilterHashTablePtr vars; + virHashTablePtr vars; }; diff --git a/tests/nwfilterxml2firewalltest.c b/tests/nwfilterxml2firewalltest.c index a51ad9412a..043b7d170e 100644 --- a/tests/nwfilterxml2firewalltest.c +++ b/tests/nwfilterxml2firewalltest.c @@ -147,11 +147,11 @@ static const char *commonRules[] = { }; -static virNWFilterHashTablePtr -virNWFilterCreateVarsFrom(virNWFilterHashTablePtr vars1, - virNWFilterHashTablePtr vars2) +static virHashTablePtr +virNWFilterCreateVarsFrom(virHashTablePtr vars1, + virHashTablePtr vars2) { - virNWFilterHashTablePtr res = virNWFilterHashTableCreate(0); + virHashTablePtr res = virNWFilterHashTableCreate(0); if (!res) return NULL; @@ -199,13 +199,13 @@ virNWFilterInstReset(virNWFilterInstPtr inst) static int virNWFilterDefToInst(const char *xml, - virNWFilterHashTablePtr vars, + virHashTablePtr vars, virNWFilterInstPtr inst); static int virNWFilterRuleDefToRuleInst(virNWFilterDefPtr def, virNWFilterRuleDefPtr rule, - virNWFilterHashTablePtr vars, + virHashTablePtr vars, virNWFilterInstPtr inst) { virNWFilterRuleInstPtr ruleinst; @@ -238,10 +238,10 @@ virNWFilterRuleDefToRuleInst(virNWFilterDefPtr def, static int virNWFilterIncludeDefToRuleInst(virNWFilterIncludeDefPtr inc, - virNWFilterHashTablePtr vars, + virHashTablePtr vars, virNWFilterInstPtr inst) { - virNWFilterHashTablePtr tmpvars = NULL; + virHashTablePtr tmpvars = NULL; int ret = -1; char *xml; @@ -270,7 +270,7 @@ virNWFilterIncludeDefToRuleInst(virNWFilterIncludeDefPtr inc, static int virNWFilterDefToInst(const char *xml, - virNWFilterHashTablePtr vars, + virHashTablePtr vars, virNWFilterInstPtr inst) { size_t i; @@ -326,7 +326,7 @@ static void testRemoveCommonRules(char *rules) } -static int testSetOneParameter(virNWFilterHashTablePtr vars, +static int testSetOneParameter(virHashTablePtr vars, const char *name, const char *value) { @@ -350,7 +350,7 @@ static int testSetOneParameter(virNWFilterHashTablePtr vars, return ret; } -static int testSetDefaultParameters(virNWFilterHashTablePtr vars) +static int testSetDefaultParameters(virHashTablePtr vars) { if (testSetOneParameter(vars, "IPSETNAME", "tck_test") < 0 || testSetOneParameter(vars, "A", "1.1.1.1") || @@ -374,7 +374,7 @@ static int testCompareXMLToArgvFiles(const char *xml, { char *actualargv = NULL; virBuffer buf = VIR_BUFFER_INITIALIZER; - virNWFilterHashTablePtr vars = virNWFilterHashTableCreate(0); + virHashTablePtr vars = virNWFilterHashTableCreate(0); virNWFilterInst inst; int ret = -1; -- 2.14.3

On Fri, Apr 27, 2018 at 16:25:02 +0100, Daniel P. Berrangé wrote:
All the code now just uses the virHashTablePtr type directly.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/conf/domain_conf.c | 2 +- src/conf/domain_conf.h | 2 +- src/conf/nwfilter_conf.h | 2 +- src/conf/nwfilter_ipaddrmap.c | 2 +- src/conf/nwfilter_params.c | 26 ++++++++++----------- src/conf/nwfilter_params.h | 23 ++++++++----------- src/nwfilter/nwfilter_dhcpsnoop.c | 6 ++--- src/nwfilter/nwfilter_dhcpsnoop.h | 2 +- src/nwfilter/nwfilter_gentech_driver.c | 42 +++++++++++++++++----------------- src/nwfilter/nwfilter_gentech_driver.h | 4 ++-- src/nwfilter/nwfilter_learnipaddr.c | 6 ++--- src/nwfilter/nwfilter_learnipaddr.h | 4 ++-- src/nwfilter/nwfilter_tech_driver.h | 2 +- tests/nwfilterxml2firewalltest.c | 24 +++++++++---------- 14 files changed, 72 insertions(+), 75 deletions(-) ... diff --git a/src/nwfilter/nwfilter_dhcpsnoop.c b/src/nwfilter/nwfilter_dhcpsnoop.c index d23cad3b75..aec68ab847 100644 --- a/src/nwfilter/nwfilter_dhcpsnoop.c +++ b/src/nwfilter/nwfilter_dhcpsnoop.c @@ -141,7 +141,7 @@ struct _virNWFilterSnoopReq { char ifkey[VIR_IFKEY_LEN]; virMacAddr macaddr; char *filtername; - virNWFilterHashTablePtr vars; + virHashTablePtr vars;
One space between virHashTablePtr and vars would be enough. Or fix the alignment if you want to keep it consistently aligned.
virNWFilterDriverStatePtr driver; /* start and end of lease list, ordered by lease time */ virNWFilterSnoopIPLeasePtr start;
...
diff --git a/src/nwfilter/nwfilter_gentech_driver.h b/src/nwfilter/nwfilter_gentech_driver.h index 71924879a2..67092157b8 100644 --- a/src/nwfilter/nwfilter_gentech_driver.h +++ b/src/nwfilter/nwfilter_gentech_driver.h @@ -53,11 +53,11 @@ int virNWFilterInstantiateFilterLate(virNWFilterDriverStatePtr driver, const char *linkdev, const virMacAddr *macaddr, const char *filtername, - virNWFilterHashTablePtr filterparams); + virHashTablePtr filterparams);
int virNWFilterTeardownFilter(const virDomainNetDef *net);
-virNWFilterHashTablePtr virNWFilterCreateVarHashmap(char *macaddr, +virHashTablePtr virNWFilterCreateVarHashmap(char *macaddr, const virNWFilterVarValue *value);
The indentation could be updated here as well.
int virNWFilterDomainFWUpdateCB(virDomainObjPtr vm,
... Reviewed-by: Jiri Denemark <jdenemar@redhat.com>

The virNWFilterIPAddrLearnReq type should only be used by the IP address learning code, so can live in the implementation file instead of header file. Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/nwfilter/nwfilter_gentech_driver.c | 8 ++++---- src/nwfilter/nwfilter_learnipaddr.c | 23 ++++++++++++++++++++--- src/nwfilter/nwfilter_learnipaddr.h | 19 +------------------ 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/src/nwfilter/nwfilter_gentech_driver.c b/src/nwfilter/nwfilter_gentech_driver.c index 0735426734..91794dd3ad 100644 --- a/src/nwfilter/nwfilter_gentech_driver.c +++ b/src/nwfilter/nwfilter_gentech_driver.c @@ -655,7 +655,7 @@ virNWFilterDoInstantiate(const unsigned char *vmuuid, filter->name, vars, driver); goto err_exit; } else if (STRCASEEQ(learning, "any")) { - if (virNWFilterLookupLearnReq(ifindex) == NULL) { + if (!virNWFilterHasLearnReq(ifindex)) { rc = virNWFilterLearnIPAddress(techdriver, ifname, ifindex, @@ -680,7 +680,7 @@ virNWFilterDoInstantiate(const unsigned char *vmuuid, } else if (virHashSize(missing_vars) > 1) { goto err_unresolvable_vars; } else if (!forceWithPendingReq && - virNWFilterLookupLearnReq(ifindex) != NULL) { + virNWFilterHasLearnReq(ifindex)) { goto err_exit; } @@ -976,7 +976,7 @@ virNWFilterRollbackUpdateFilter(const virDomainNetDef *net) /* don't tear anything while the address is being learned */ if (virNetDevGetIndex(net->ifname, &ifindex) < 0) virResetLastError(); - else if (virNWFilterLookupLearnReq(ifindex) != NULL) + else if (virNWFilterHasLearnReq(ifindex)) return 0; return techdriver->tearNewRules(net->ifname); @@ -1002,7 +1002,7 @@ virNWFilterTearOldFilter(virDomainNetDefPtr net) /* don't tear anything while the address is being learned */ if (virNetDevGetIndex(net->ifname, &ifindex) < 0) virResetLastError(); - else if (virNWFilterLookupLearnReq(ifindex) != NULL) + else if (virNWFilterHasLearnReq(ifindex)) return 0; return techdriver->tearOldRules(net->ifname); diff --git a/src/nwfilter/nwfilter_learnipaddr.c b/src/nwfilter/nwfilter_learnipaddr.c index 2401857ddb..cc3bfd971c 100644 --- a/src/nwfilter/nwfilter_learnipaddr.c +++ b/src/nwfilter/nwfilter_learnipaddr.c @@ -133,6 +133,23 @@ struct _virNWFilterIfaceLock { int refctr; }; +typedef struct _virNWFilterIPAddrLearnReq virNWFilterIPAddrLearnReq; +typedef virNWFilterIPAddrLearnReq *virNWFilterIPAddrLearnReqPtr; +struct _virNWFilterIPAddrLearnReq { + virNWFilterTechDriverPtr techdriver; + char ifname[IF_NAMESIZE]; + int ifindex; + char linkdev[IF_NAMESIZE]; + virMacAddr macaddr; + char *filtername; + virHashTablePtr filterparams; + virNWFilterDriverStatePtr driver; + enum howDetect howDetect; + + int status; + volatile bool terminate; +}; + static bool threadsTerminate; @@ -279,8 +296,8 @@ virNWFilterTerminateLearnReq(const char *ifname) } -virNWFilterIPAddrLearnReqPtr -virNWFilterLookupLearnReq(int ifindex) +bool +virNWFilterHasLearnReq(int ifindex) { void *res; IFINDEX2STR(ifindex_str, ifindex); @@ -291,7 +308,7 @@ virNWFilterLookupLearnReq(int ifindex) virMutexUnlock(&pendingLearnReqLock); - return res; + return res != NULL; } diff --git a/src/nwfilter/nwfilter_learnipaddr.h b/src/nwfilter/nwfilter_learnipaddr.h index dc4c0d110f..06fea5bff8 100644 --- a/src/nwfilter/nwfilter_learnipaddr.h +++ b/src/nwfilter/nwfilter_learnipaddr.h @@ -35,23 +35,6 @@ enum howDetect { DETECT_STATIC = 2, }; -typedef struct _virNWFilterIPAddrLearnReq virNWFilterIPAddrLearnReq; -typedef virNWFilterIPAddrLearnReq *virNWFilterIPAddrLearnReqPtr; -struct _virNWFilterIPAddrLearnReq { - virNWFilterTechDriverPtr techdriver; - char ifname[IF_NAMESIZE]; - int ifindex; - char linkdev[IF_NAMESIZE]; - virMacAddr macaddr; - char *filtername; - virHashTablePtr filterparams; - virNWFilterDriverStatePtr driver; - enum howDetect howDetect; - - int status; - volatile bool terminate; -}; - int virNWFilterLearnIPAddress(virNWFilterTechDriverPtr techdriver, const char *ifname, int ifindex, @@ -62,7 +45,7 @@ int virNWFilterLearnIPAddress(virNWFilterTechDriverPtr techdriver, virNWFilterDriverStatePtr driver, enum howDetect howDetect); -virNWFilterIPAddrLearnReqPtr virNWFilterLookupLearnReq(int ifindex); +bool virNWFilterHasLearnReq(int ifindex); int virNWFilterTerminateLearnReq(const char *ifname); int virNWFilterLockIface(const char *ifname) ATTRIBUTE_RETURN_CHECK; -- 2.14.3

On Fri, Apr 27, 2018 at 16:25:03 +0100, Daniel P. Berrangé wrote:
The virNWFilterIPAddrLearnReq type should only be used by the IP address learning code, so can live in the implementation file instead of header file.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/nwfilter/nwfilter_gentech_driver.c | 8 ++++---- src/nwfilter/nwfilter_learnipaddr.c | 23 ++++++++++++++++++++--- src/nwfilter/nwfilter_learnipaddr.h | 19 +------------------ 3 files changed, 25 insertions(+), 25 deletions(-)
Reviewed-by: Jiri Denemark <jdenemar@redhat.com>

On Fri, Apr 27, 2018 at 04:25:03PM +0100, Daniel P. Berrangé wrote:
The virNWFilterIPAddrLearnReq type should only be used by the IP address learning code, so can live in the implementation file instead of header file.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> ---
Could have split the patch in 2, one that moves the type and the other refactoring the getter. Erik

On Mon, Apr 30, 2018 at 03:30:35PM +0200, Erik Skultety wrote:
On Fri, Apr 27, 2018 at 04:25:03PM +0100, Daniel P. Berrangé wrote:
The virNWFilterIPAddrLearnReq type should only be used by the IP address learning code, so can live in the implementation file instead of header file.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> ---
Could have split the patch in 2, one that moves the type and the other refactoring the getter.
Ok, will split this before pushing with Jiri's ACK. Regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|

There is a bunch of left over code in the nwfilter driver related to monitoring firewalld over dbus, that is no longer used since the conversion to use virFirewall APIs. Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/conf/virnwfilterobj.h | 1 - src/nwfilter/nwfilter_driver.c | 18 ------------------ src/nwfilter/nwfilter_driver.h | 2 -- 3 files changed, 21 deletions(-) diff --git a/src/conf/virnwfilterobj.h b/src/conf/virnwfilterobj.h index 8e79518ed3..433b0402d0 100644 --- a/src/conf/virnwfilterobj.h +++ b/src/conf/virnwfilterobj.h @@ -38,7 +38,6 @@ struct _virNWFilterDriverState { virNWFilterObjListPtr nwfilters; char *configDir; - bool watchingFirewallD; }; virNWFilterDefPtr diff --git a/src/nwfilter/nwfilter_driver.c b/src/nwfilter/nwfilter_driver.c index 542de03596..fef3aa272b 100644 --- a/src/nwfilter/nwfilter_driver.c +++ b/src/nwfilter/nwfilter_driver.c @@ -186,8 +186,6 @@ nwfilterStateInitialize(bool privileged, if (virMutexInit(&driver->lock) < 0) goto err_free_driverstate; - /* remember that we are going to use firewalld */ - driver->watchingFirewallD = (sysbus != NULL); driver->privileged = privileged; if (!(driver->nwfilters = virNWFilterObjListNew())) goto error; @@ -311,22 +309,6 @@ nwfilterStateReload(void) } -/** - * virNWFilterIsWatchingFirewallD: - * - * Checks if the nwfilter has the DBus watches for FirewallD installed. - * - * Returns true if it is watching firewalld, false otherwise - */ -bool -virNWFilterDriverIsWatchingFirewallD(void) -{ - if (!driver) - return false; - - return driver->watchingFirewallD; -} - /** * nwfilterStateCleanup: * diff --git a/src/nwfilter/nwfilter_driver.h b/src/nwfilter/nwfilter_driver.h index 06d7572d21..ad56e7bb2f 100644 --- a/src/nwfilter/nwfilter_driver.h +++ b/src/nwfilter/nwfilter_driver.h @@ -33,6 +33,4 @@ int nwfilterRegister(void); -bool virNWFilterDriverIsWatchingFirewallD(void); - #endif /* __VIR_NWFILTER_DRIVER_H__ */ -- 2.14.3

On Fri, Apr 27, 2018 at 16:25:04 +0100, Daniel P. Berrangé wrote:
There is a bunch of left over code in the nwfilter driver related to monitoring firewalld over dbus, that is no longer used since the conversion to use virFirewall APIs.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/conf/virnwfilterobj.h | 1 - src/nwfilter/nwfilter_driver.c | 18 ------------------ src/nwfilter/nwfilter_driver.h | 2 -- 3 files changed, 21 deletions(-)
Reviewed-by: Jiri Denemark <jdenemar@redhat.com>

The filter parameters were not correctly free'd when an error hits while adding to the hash table. Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/nwfilter/nwfilter_gentech_driver.c | 22 ++++++---------------- src/nwfilter/nwfilter_gentech_driver.h | 2 +- 2 files changed, 7 insertions(+), 17 deletions(-) diff --git a/src/nwfilter/nwfilter_gentech_driver.c b/src/nwfilter/nwfilter_gentech_driver.c index 91794dd3ad..af4411d4db 100644 --- a/src/nwfilter/nwfilter_gentech_driver.c +++ b/src/nwfilter/nwfilter_gentech_driver.c @@ -143,19 +143,20 @@ virNWFilterRuleInstFree(virNWFilterRuleInstPtr inst) */ static int virNWFilterVarHashmapAddStdValues(virHashTablePtr table, - char *macaddr, + const char *macaddr, const virNWFilterVarValue *ipaddr) { virNWFilterVarValue *val; if (macaddr) { - val = virNWFilterVarValueCreateSimple(macaddr); + val = virNWFilterVarValueCreateSimpleCopyValue(macaddr); if (!val) return -1; if (virHashAddEntry(table, NWFILTER_STD_VAR_MAC, val) < 0) { + virNWFilterVarValueFree(val); virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not add variable 'MAC' to hashmap")); return -1; @@ -170,6 +171,7 @@ virNWFilterVarHashmapAddStdValues(virHashTablePtr table, if (virHashAddEntry(table, NWFILTER_STD_VAR_IP, val) < 0) { + virNWFilterVarValueFree(val); virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not add variable 'IP' to hashmap")); return -1; @@ -192,7 +194,7 @@ virNWFilterVarHashmapAddStdValues(virHashTablePtr table, * Returns pointer to hashmap, NULL if an error occurred. */ virHashTablePtr -virNWFilterCreateVarHashmap(char *macaddr, +virNWFilterCreateVarHashmap(const char *macaddr, const virNWFilterVarValue *ipaddr) { virHashTablePtr table = virNWFilterHashTableCreate(0); @@ -767,9 +769,7 @@ virNWFilterInstantiateFilterUpdate(virNWFilterDriverStatePtr driver, virNWFilterDefPtr filter; virNWFilterDefPtr newFilter; char vmmacaddr[VIR_MAC_STRING_BUFLEN] = {0}; - char *str_macaddr = NULL; virNWFilterVarValuePtr ipaddr; - char *str_ipaddr = NULL; techdriver = virNWFilterTechDriverForName(drvname); @@ -788,22 +788,15 @@ virNWFilterInstantiateFilterUpdate(virNWFilterDriverStatePtr driver, return -1; virMacAddrFormat(macaddr, vmmacaddr); - if (VIR_STRDUP(str_macaddr, vmmacaddr) < 0) { - rc = -1; - goto err_exit; - } ipaddr = virNWFilterIPAddrMapGetIPAddr(ifname); - vars1 = virNWFilterCreateVarHashmap(str_macaddr, ipaddr); + vars1 = virNWFilterCreateVarHashmap(vmmacaddr, ipaddr); if (!vars1) { rc = -1; goto err_exit; } - str_macaddr = NULL; - str_ipaddr = NULL; - vars = virNWFilterCreateVarsFrom(vars1, filterparams); if (!vars) { @@ -840,9 +833,6 @@ virNWFilterInstantiateFilterUpdate(virNWFilterDriverStatePtr driver, err_exit: virNWFilterObjUnlock(obj); - VIR_FREE(str_ipaddr); - VIR_FREE(str_macaddr); - return rc; } diff --git a/src/nwfilter/nwfilter_gentech_driver.h b/src/nwfilter/nwfilter_gentech_driver.h index 67092157b8..86cc677e79 100644 --- a/src/nwfilter/nwfilter_gentech_driver.h +++ b/src/nwfilter/nwfilter_gentech_driver.h @@ -57,7 +57,7 @@ int virNWFilterInstantiateFilterLate(virNWFilterDriverStatePtr driver, int virNWFilterTeardownFilter(const virDomainNetDef *net); -virHashTablePtr virNWFilterCreateVarHashmap(char *macaddr, +virHashTablePtr virNWFilterCreateVarHashmap(const char *macaddr, const virNWFilterVarValue *value); int virNWFilterDomainFWUpdateCB(virDomainObjPtr vm, -- 2.14.3

On Fri, Apr 27, 2018 at 16:25:05 +0100, Daniel P. Berrangé wrote:
The filter parameters were not correctly free'd when an error hits while adding to the hash table.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/nwfilter/nwfilter_gentech_driver.c | 22 ++++++---------------- src/nwfilter/nwfilter_gentech_driver.h | 2 +- 2 files changed, 7 insertions(+), 17 deletions(-) ... diff --git a/src/nwfilter/nwfilter_gentech_driver.h b/src/nwfilter/nwfilter_gentech_driver.h index 67092157b8..86cc677e79 100644 --- a/src/nwfilter/nwfilter_gentech_driver.h +++ b/src/nwfilter/nwfilter_gentech_driver.h @@ -57,7 +57,7 @@ int virNWFilterInstantiateFilterLate(virNWFilterDriverStatePtr driver,
int virNWFilterTeardownFilter(const virDomainNetDef *net);
-virHashTablePtr virNWFilterCreateVarHashmap(char *macaddr, +virHashTablePtr virNWFilterCreateVarHashmap(const char *macaddr, const virNWFilterVarValue *value);
The alignment needs some adjustment. However, the function has no users outside nwfilter_gentech_driver.c so a separate patch could make it static. Reviewed-by: Jiri Denemark <jdenemar@redhat.com>

The virDomainNet struct contains everything related to configuring a guest network device. Out of all of this info, only 5 fields are relevant to configuring network filters. It will be more convenient for future changes to the nwfilter driver if the relevant fields are kept in a dedicated struct. Thus the virNWFilterBinding struct is created to track this information. Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/conf/nwfilter_conf.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++- src/conf/nwfilter_conf.h | 18 +++++++++++++++- src/libvirt_private.syms | 2 ++ 3 files changed, 71 insertions(+), 2 deletions(-) diff --git a/src/conf/nwfilter_conf.c b/src/conf/nwfilter_conf.c index 5d04f2a93c..3d2ae9d0f3 100644 --- a/src/conf/nwfilter_conf.c +++ b/src/conf/nwfilter_conf.c @@ -2,7 +2,7 @@ * nwfilter_conf.c: network filter XML processing * (derived from storage_conf.c) * - * Copyright (C) 2006-2014 Red Hat, Inc. + * Copyright (C) 2006-2018 Red Hat, Inc. * Copyright (C) 2006-2008 Daniel P. Berrange * * Copyright (C) 2010-2011 IBM Corporation @@ -3265,3 +3265,54 @@ virNWFilterRuleIsProtocolEthernet(virNWFilterRuleDefPtr rule) return true; return false; } + +void virNWFilterBindingFree(virNWFilterBindingPtr binding) +{ + if (!binding) + return; + + VIR_FREE(binding->ownername); + VIR_FREE(binding->portdevname); + VIR_FREE(binding->linkdevname); + VIR_FREE(binding->filter); + virHashFree(binding->filterparams); + + VIR_FREE(binding); +} + +virNWFilterBindingPtr virNWFilterBindingCopy(virNWFilterBindingPtr src) +{ + virNWFilterBindingPtr ret; + + if (VIR_ALLOC(ret) < 0) + return NULL; + + if (VIR_STRDUP(ret->ownername, src->ownername) < 0) + goto error; + + memcpy(ret->owneruuid, src->owneruuid, sizeof(ret->owneruuid)); + + if (VIR_STRDUP(ret->portdevname, src->portdevname) < 0) + goto error; + + if (src->linkdevname && + VIR_STRDUP(ret->linkdevname, src->linkdevname) < 0) + goto error; + + ret->mac = src->mac; + + if (VIR_STRDUP(ret->filter, src->filter) < 0) + goto error; + + if (!(ret->filterparams = virNWFilterHashTableCreate(0))) + goto error; + + if (virNWFilterHashTablePutAll(src->filterparams, ret->filterparams) < 0) + goto error; + + return ret; + + error: + virNWFilterBindingFree(ret); + return NULL; +} diff --git a/src/conf/nwfilter_conf.h b/src/conf/nwfilter_conf.h index a31db6d3ff..8c5421ee62 100644 --- a/src/conf/nwfilter_conf.h +++ b/src/conf/nwfilter_conf.h @@ -2,7 +2,7 @@ * nwfilter_conf.h: network filter XML processing * (derived from storage_conf.h) * - * Copyright (C) 2006-2010, 2012-2014 Red Hat, Inc. + * Copyright (C) 2006-2010, 2012-2018 Red Hat, Inc. * Copyright (C) 2006-2008 Daniel P. Berrange * * Copyright (C) 2010 IBM Corporation @@ -545,6 +545,19 @@ struct _virNWFilterDef { virNWFilterEntryPtr *filterEntries; }; +typedef struct virNWFilterBinding virNWFilterBinding; +typedef virNWFilterBinding *virNWFilterBindingPtr; + +struct virNWFilterBinding { + char *ownername; + unsigned char owneruuid[VIR_UUID_BUFLEN]; + char *portdevname; + char *linkdevname; + virMacAddr mac; + char *filter; + virHashTablePtr filterparams; +}; + typedef enum { STEP_APPLY_NEW, @@ -650,6 +663,9 @@ virNWFilterRuleIsProtocolIPv6(virNWFilterRuleDefPtr rule); bool virNWFilterRuleIsProtocolEthernet(virNWFilterRuleDefPtr rule); +void virNWFilterBindingFree(virNWFilterBindingPtr binding); +virNWFilterBindingPtr virNWFilterBindingCopy(virNWFilterBindingPtr src); + VIR_ENUM_DECL(virNWFilterRuleAction); VIR_ENUM_DECL(virNWFilterRuleDirection); VIR_ENUM_DECL(virNWFilterRuleProtocol); diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index bf17d17777..9fc0aa470d 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -780,6 +780,8 @@ virDomainNumatuneSpecifiedMaxNode; # conf/nwfilter_conf.h +virNWFilterBindingCopy; +virNWFilterBindingFree; virNWFilterCallbackDriversLock; virNWFilterCallbackDriversUnlock; virNWFilterChainSuffixTypeToString; -- 2.14.3

On Fri, Apr 27, 2018 at 16:25:06 +0100, Daniel P. Berrangé wrote:
The virDomainNet struct contains everything related to configuring a guest network device. Out of all of this info, only 5 fields are relevant to configuring network filters. It will be more convenient for future changes to the nwfilter driver if the relevant fields are kept in a dedicated struct. Thus the virNWFilterBinding struct is created to track this information.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/conf/nwfilter_conf.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++- src/conf/nwfilter_conf.h | 18 +++++++++++++++- src/libvirt_private.syms | 2 ++ 3 files changed, 71 insertions(+), 2 deletions(-)
diff --git a/src/conf/nwfilter_conf.c b/src/conf/nwfilter_conf.c index 5d04f2a93c..3d2ae9d0f3 100644 --- a/src/conf/nwfilter_conf.c +++ b/src/conf/nwfilter_conf.c @@ -2,7 +2,7 @@ * nwfilter_conf.c: network filter XML processing * (derived from storage_conf.c) * - * Copyright (C) 2006-2014 Red Hat, Inc. + * Copyright (C) 2006-2018 Red Hat, Inc. * Copyright (C) 2006-2008 Daniel P. Berrange * * Copyright (C) 2010-2011 IBM Corporation @@ -3265,3 +3265,54 @@ virNWFilterRuleIsProtocolEthernet(virNWFilterRuleDefPtr rule) return true; return false; } +
Two empty lines between functions, please.
+void virNWFilterBindingFree(virNWFilterBindingPtr binding)
The type should be on a separate line.
+{ + if (!binding) + return; + + VIR_FREE(binding->ownername); + VIR_FREE(binding->portdevname); + VIR_FREE(binding->linkdevname); + VIR_FREE(binding->filter); + virHashFree(binding->filterparams); + + VIR_FREE(binding); +} +
Two empty lines between functions, please.
+virNWFilterBindingPtr virNWFilterBindingCopy(virNWFilterBindingPtr src)
The type should be on a separate line.
+{ + virNWFilterBindingPtr ret; + + if (VIR_ALLOC(ret) < 0) + return NULL; + + if (VIR_STRDUP(ret->ownername, src->ownername) < 0) + goto error; + + memcpy(ret->owneruuid, src->owneruuid, sizeof(ret->owneruuid)); + + if (VIR_STRDUP(ret->portdevname, src->portdevname) < 0) + goto error; + + if (src->linkdevname && + VIR_STRDUP(ret->linkdevname, src->linkdevname) < 0)
VIR_STRDUP can be safely used on NULL source, you don't need to guard it with the extra check.
+ goto error; + + ret->mac = src->mac; + + if (VIR_STRDUP(ret->filter, src->filter) < 0) + goto error; + + if (!(ret->filterparams = virNWFilterHashTableCreate(0))) + goto error; + + if (virNWFilterHashTablePutAll(src->filterparams, ret->filterparams) < 0) + goto error; + + return ret; + + error: + virNWFilterBindingFree(ret); + return NULL; +} diff --git a/src/conf/nwfilter_conf.h b/src/conf/nwfilter_conf.h index a31db6d3ff..8c5421ee62 100644 --- a/src/conf/nwfilter_conf.h +++ b/src/conf/nwfilter_conf.h @@ -2,7 +2,7 @@ * nwfilter_conf.h: network filter XML processing * (derived from storage_conf.h) * - * Copyright (C) 2006-2010, 2012-2014 Red Hat, Inc. + * Copyright (C) 2006-2010, 2012-2018 Red Hat, Inc. * Copyright (C) 2006-2008 Daniel P. Berrange * * Copyright (C) 2010 IBM Corporation @@ -545,6 +545,19 @@ struct _virNWFilterDef { virNWFilterEntryPtr *filterEntries; };
+typedef struct virNWFilterBinding virNWFilterBinding; +typedef virNWFilterBinding *virNWFilterBindingPtr; + +struct virNWFilterBinding { + char *ownername; + unsigned char owneruuid[VIR_UUID_BUFLEN]; + char *portdevname; + char *linkdevname; + virMacAddr mac; + char *filter; + virHashTablePtr filterparams; +}; +
typedef enum { STEP_APPLY_NEW, @@ -650,6 +663,9 @@ virNWFilterRuleIsProtocolIPv6(virNWFilterRuleDefPtr rule); bool virNWFilterRuleIsProtocolEthernet(virNWFilterRuleDefPtr rule);
+void virNWFilterBindingFree(virNWFilterBindingPtr binding); +virNWFilterBindingPtr virNWFilterBindingCopy(virNWFilterBindingPtr src);
The types should be on separate lines for consistency with the rest of this header file.
+ VIR_ENUM_DECL(virNWFilterRuleAction); VIR_ENUM_DECL(virNWFilterRuleDirection); VIR_ENUM_DECL(virNWFilterRuleProtocol); diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index bf17d17777..9fc0aa470d 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -780,6 +780,8 @@ virDomainNumatuneSpecifiedMaxNode;
# conf/nwfilter_conf.h +virNWFilterBindingCopy; +virNWFilterBindingFree; virNWFilterCallbackDriversLock; virNWFilterCallbackDriversUnlock; virNWFilterChainSuffixTypeToString;
See my replies to the following patches for possible modifications... Reviewed-by: Jiri Denemark <jdenemar@redhat.com>

The vm name is not needed for any functional requirement, but it will be useful when debugging problems to identify which VM is associated with a filter, since UUID is not human friendly. Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/conf/domain_nwfilter.c | 5 +++-- src/conf/domain_nwfilter.h | 6 ++++-- src/lxc/lxc_process.c | 2 +- src/nwfilter/nwfilter_driver.c | 3 ++- src/qemu/qemu_hotplug.c | 6 ++++-- src/qemu/qemu_interface.c | 4 ++-- src/qemu/qemu_process.c | 2 +- src/uml/uml_conf.c | 2 +- 8 files changed, 18 insertions(+), 12 deletions(-) diff --git a/src/conf/domain_nwfilter.c b/src/conf/domain_nwfilter.c index 176e7e6734..e360aceeba 100644 --- a/src/conf/domain_nwfilter.c +++ b/src/conf/domain_nwfilter.c @@ -38,11 +38,12 @@ virDomainConfNWFilterRegister(virDomainConfNWFilterDriverPtr driver) } int -virDomainConfNWFilterInstantiate(const unsigned char *vmuuid, +virDomainConfNWFilterInstantiate(const char *vmname, + const unsigned char *vmuuid, virDomainNetDefPtr net) { if (nwfilterDriver != NULL) - return nwfilterDriver->instantiateFilter(vmuuid, net); + return nwfilterDriver->instantiateFilter(vmname, vmuuid, net); /* driver module not available -- don't indicate failure */ return 0; } diff --git a/src/conf/domain_nwfilter.h b/src/conf/domain_nwfilter.h index af047c745a..857cac6c2a 100644 --- a/src/conf/domain_nwfilter.h +++ b/src/conf/domain_nwfilter.h @@ -23,7 +23,8 @@ #ifndef DOMAIN_NWFILTER_H # define DOMAIN_NWFILTER_H -typedef int (*virDomainConfInstantiateNWFilter)(const unsigned char *vmuuid, +typedef int (*virDomainConfInstantiateNWFilter)(const char *vmname, + const unsigned char *vmuuid, virDomainNetDefPtr net); typedef void (*virDomainConfTeardownNWFilter)(virDomainNetDefPtr net); @@ -35,7 +36,8 @@ typedef virDomainConfNWFilterDriver *virDomainConfNWFilterDriverPtr; void virDomainConfNWFilterRegister(virDomainConfNWFilterDriverPtr driver); -int virDomainConfNWFilterInstantiate(const unsigned char *vmuuid, +int virDomainConfNWFilterInstantiate(const char *vmname, + const unsigned char *vmuuid, virDomainNetDefPtr net); void virDomainConfNWFilterTeardown(virDomainNetDefPtr net); void virDomainConfVMNWFilterTeardown(virDomainObjPtr vm); diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c index e911d88b56..3610523c06 100644 --- a/src/lxc/lxc_process.c +++ b/src/lxc/lxc_process.c @@ -304,7 +304,7 @@ virLXCProcessSetupInterfaceTap(virDomainDefPtr vm, } if (net->filter && - virDomainConfNWFilterInstantiate(vm->uuid, net) < 0) + virDomainConfNWFilterInstantiate(vm->name, vm->uuid, net) < 0) goto cleanup; ret = containerVeth; diff --git a/src/nwfilter/nwfilter_driver.c b/src/nwfilter/nwfilter_driver.c index fef3aa272b..d17a8ec00b 100644 --- a/src/nwfilter/nwfilter_driver.c +++ b/src/nwfilter/nwfilter_driver.c @@ -642,7 +642,8 @@ nwfilterGetXMLDesc(virNWFilterPtr nwfilter, static int -nwfilterInstantiateFilter(const unsigned char *vmuuid, +nwfilterInstantiateFilter(const char *vmname ATTRIBUTE_UNUSED, + const unsigned char *vmuuid, virDomainNetDefPtr net) { return virNWFilterInstantiateFilter(driver, vmuuid, net); diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index df9e8aa716..3bb0c72257 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -3016,7 +3016,8 @@ qemuDomainChangeNetFilter(virDomainObjPtr vm, virDomainConfNWFilterTeardown(olddev); if (newdev->filter && - virDomainConfNWFilterInstantiate(vm->def->uuid, newdev) < 0) { + virDomainConfNWFilterInstantiate(vm->def->name, + vm->def->uuid, newdev) < 0) { virErrorPtr errobj; virReportError(VIR_ERR_OPERATION_FAILED, @@ -3024,7 +3025,8 @@ qemuDomainChangeNetFilter(virDomainObjPtr vm, "- attempting to restore old rules"), olddev->ifname); virErrorPreserveLast(&errobj); - ignore_value(virDomainConfNWFilterInstantiate(vm->def->uuid, olddev)); + ignore_value(virDomainConfNWFilterInstantiate(vm->def->name, + vm->def->uuid, olddev)); virErrorRestore(&errobj); return -1; } diff --git a/src/qemu/qemu_interface.c b/src/qemu/qemu_interface.c index ffa4b875c0..5d54a85c53 100644 --- a/src/qemu/qemu_interface.c +++ b/src/qemu/qemu_interface.c @@ -467,7 +467,7 @@ qemuInterfaceEthernetConnect(virDomainDefPtr def, goto cleanup; if (net->filter && - virDomainConfNWFilterInstantiate(def->uuid, net) < 0) { + virDomainConfNWFilterInstantiate(def->name, def->uuid, net) < 0) { goto cleanup; } @@ -586,7 +586,7 @@ qemuInterfaceBridgeConnect(virDomainDefPtr def, goto cleanup; if (net->filter && - virDomainConfNWFilterInstantiate(def->uuid, net) < 0) { + virDomainConfNWFilterInstantiate(def->name, def->uuid, net) < 0) { goto cleanup; } diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 6a5262ae46..9233d26948 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -2952,7 +2952,7 @@ qemuProcessFiltersInstantiate(virDomainDefPtr def) for (i = 0; i < def->nnets; i++) { virDomainNetDefPtr net = def->nets[i]; if ((net->filter) && (net->ifname)) { - if (virDomainConfNWFilterInstantiate(def->uuid, net) < 0) + if (virDomainConfNWFilterInstantiate(def->name, def->uuid, net) < 0) return 1; } } diff --git a/src/uml/uml_conf.c b/src/uml/uml_conf.c index 49589b33c9..9c548f0e80 100644 --- a/src/uml/uml_conf.c +++ b/src/uml/uml_conf.c @@ -137,7 +137,7 @@ umlConnectTapDevice(virDomainDefPtr vm, } if (net->filter) { - if (virDomainConfNWFilterInstantiate(vm->uuid, net) < 0) { + if (virDomainConfNWFilterInstantiate(vm->name, vm->uuid, net) < 0) { if (template_ifname) VIR_FREE(net->ifname); goto error; -- 2.14.3

On Fri, Apr 27, 2018 at 16:25:07 +0100, Daniel P. Berrangé wrote:
The vm name is not needed for any functional requirement, but it will be useful when debugging problems to identify which VM is associated with a filter, since UUID is not human friendly.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/conf/domain_nwfilter.c | 5 +++-- src/conf/domain_nwfilter.h | 6 ++++-- src/lxc/lxc_process.c | 2 +- src/nwfilter/nwfilter_driver.c | 3 ++- src/qemu/qemu_hotplug.c | 6 ++++-- src/qemu/qemu_interface.c | 4 ++-- src/qemu/qemu_process.c | 2 +- src/uml/uml_conf.c | 2 +- 8 files changed, 18 insertions(+), 12 deletions(-)
Reviewed-by: Jiri Denemark <jdenemar@redhat.com>

On Mon, Apr 30, 2018 at 04:09:40PM +0200, Jiri Denemark wrote:
On Fri, Apr 27, 2018 at 16:25:07 +0100, Daniel P. Berrangé wrote:
The vm name is not needed for any functional requirement, but it will be useful when debugging problems to identify which VM is associated with a filter, since UUID is not human friendly.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/conf/domain_nwfilter.c | 5 +++-- src/conf/domain_nwfilter.h | 6 ++++-- src/lxc/lxc_process.c | 2 +- src/nwfilter/nwfilter_driver.c | 3 ++- src/qemu/qemu_hotplug.c | 6 ++++-- src/qemu/qemu_interface.c | 4 ++-- src/qemu/qemu_process.c | 2 +- src/uml/uml_conf.c | 2 +- 8 files changed, 18 insertions(+), 12 deletions(-)
Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
FYI, I have pushed upto & including this patch. Regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|

Use the virNWFilterBinding struct in the gentech driver code directly. Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/nwfilter/nwfilter_dhcpsnoop.c | 35 +++--- src/nwfilter/nwfilter_driver.c | 21 +++- src/nwfilter/nwfilter_gentech_driver.c | 211 +++++++++++++++++---------------- src/nwfilter/nwfilter_gentech_driver.h | 22 ++-- src/nwfilter/nwfilter_learnipaddr.c | 16 +-- 5 files changed, 168 insertions(+), 137 deletions(-) diff --git a/src/nwfilter/nwfilter_dhcpsnoop.c b/src/nwfilter/nwfilter_dhcpsnoop.c index aec68ab847..dc4e3cb834 100644 --- a/src/nwfilter/nwfilter_dhcpsnoop.c +++ b/src/nwfilter/nwfilter_dhcpsnoop.c @@ -486,15 +486,18 @@ virNWFilterSnoopIPLeaseInstallRule(virNWFilterSnoopIPLeasePtr ipl, /* instantiate the filters */ - if (req->ifname) + if (req->ifname) { + virNWFilterBinding binding = { + .portdevname = req->ifname, + .linkdevname = req->linkdev, + .mac = req->macaddr, + .filter = req->filtername, + .filterparams = req->vars, + }; rc = virNWFilterInstantiateFilterLate(req->driver, - NULL, - req->ifname, - req->ifindex, - req->linkdev, - &req->macaddr, - req->filtername, - req->vars); + &binding, + req->ifindex); + } exit_snooprequnlock: virNWFilterSnoopReqUnlock(req); @@ -873,14 +876,16 @@ virNWFilterSnoopReqLeaseDel(virNWFilterSnoopReqPtr req, goto skip_instantiate; if (ipAddrLeft) { + virNWFilterBinding binding = { + .portdevname = req->ifname, + .linkdevname = req->linkdev, + .mac = req->macaddr, + .filter = req->filtername, + .filterparams = req->vars, + }; ret = virNWFilterInstantiateFilterLate(req->driver, - NULL, - req->ifname, - req->ifindex, - req->linkdev, - &req->macaddr, - req->filtername, - req->vars); + &binding, + req->ifindex); } else { virNWFilterVarValuePtr dhcpsrvrs = virHashLookup(req->vars, NWFILTER_VARNAME_DHCPSERVER); diff --git a/src/nwfilter/nwfilter_driver.c b/src/nwfilter/nwfilter_driver.c index d17a8ec00b..a375e9bda8 100644 --- a/src/nwfilter/nwfilter_driver.c +++ b/src/nwfilter/nwfilter_driver.c @@ -642,19 +642,34 @@ nwfilterGetXMLDesc(virNWFilterPtr nwfilter, static int -nwfilterInstantiateFilter(const char *vmname ATTRIBUTE_UNUSED, +nwfilterInstantiateFilter(const char *vmname, const unsigned char *vmuuid, virDomainNetDefPtr net) { - return virNWFilterInstantiateFilter(driver, vmuuid, net); + virNWFilterBindingPtr binding; + int ret; + + if (!(binding = virNWFilterBindingForNet(vmname, vmuuid, net))) + return -1; + ret = virNWFilterInstantiateFilter(driver, binding); + virNWFilterBindingFree(binding); + return ret; } static void nwfilterTeardownFilter(virDomainNetDefPtr net) { + virNWFilterBinding binding = { + .portdevname = net->ifname, + .linkdevname = (net->type == VIR_DOMAIN_NET_TYPE_DIRECT ? + net->data.direct.linkdev : NULL), + .mac = net->mac, + .filter = net->filter, + .filterparams = net->filterparams, + }; if ((net->ifname) && (net->filter)) - virNWFilterTeardownFilter(net); + virNWFilterTeardownFilter(&binding); } diff --git a/src/nwfilter/nwfilter_gentech_driver.c b/src/nwfilter/nwfilter_gentech_driver.c index af4411d4db..c755350586 100644 --- a/src/nwfilter/nwfilter_gentech_driver.c +++ b/src/nwfilter/nwfilter_gentech_driver.c @@ -577,12 +577,9 @@ virNWFilterDetermineMissingVarsRec(virNWFilterDefPtr filter, /** * virNWFilterDoInstantiate: - * @vmuuid: The UUID of the VM * @techdriver: The driver to use for instantiation + * @binding: description of port to bind the filter to * @filter: The filter to instantiate - * @ifname: The name of the interface to apply the rules to - * @vars: A map holding variable names and values used for instantiating - * the filter and its subfilters. * @forceWithPendingReq: Ignore the check whether a pending learn request * is active; 'true' only when the rules are applied late * @@ -596,17 +593,13 @@ virNWFilterDetermineMissingVarsRec(virNWFilterDefPtr filter, * Call this function while holding the NWFilter filter update lock */ static int -virNWFilterDoInstantiate(const unsigned char *vmuuid, - virNWFilterTechDriverPtr techdriver, +virNWFilterDoInstantiate(virNWFilterTechDriverPtr techdriver, + virNWFilterBindingPtr binding, virNWFilterDefPtr filter, - const char *ifname, int ifindex, - const char *linkdev, - virHashTablePtr vars, enum instCase useNewFilter, bool *foundNewFilter, bool teardownOld, - const virMacAddr *macaddr, virNWFilterDriverStatePtr driver, bool forceWithPendingReq) { @@ -628,14 +621,14 @@ virNWFilterDoInstantiate(const unsigned char *vmuuid, } rc = virNWFilterDetermineMissingVarsRec(filter, - vars, + binding->filterparams, missing_vars, useNewFilter, driver); if (rc < 0) goto err_exit; - lv = virHashLookup(vars, NWFILTER_VARNAME_CTRL_IP_LEARNING); + lv = virHashLookup(binding->filterparams, NWFILTER_VARNAME_CTRL_IP_LEARNING); if (lv) learning = virNWFilterVarValueGetNthValue(lv, 0); else @@ -652,19 +645,20 @@ virNWFilterDoInstantiate(const unsigned char *vmuuid, goto err_unresolvable_vars; } if (STRCASEEQ(learning, "dhcp")) { - rc = virNWFilterDHCPSnoopReq(techdriver, ifname, linkdev, - vmuuid, macaddr, - filter->name, vars, driver); + rc = virNWFilterDHCPSnoopReq(techdriver, binding->portdevname, + binding->linkdevname, + binding->owneruuid, &binding->mac, + filter->name, binding->filterparams, driver); goto err_exit; } else if (STRCASEEQ(learning, "any")) { if (!virNWFilterHasLearnReq(ifindex)) { rc = virNWFilterLearnIPAddress(techdriver, - ifname, + binding->portdevname, ifindex, - linkdev, - macaddr, + binding->linkdevname, + &binding->mac, filter->name, - vars, driver, + binding->filterparams, driver, DETECT_DHCP|DETECT_STATIC); } goto err_exit; @@ -688,7 +682,7 @@ virNWFilterDoInstantiate(const unsigned char *vmuuid, rc = virNWFilterDefToInst(driver, filter, - vars, + binding->filterparams, useNewFilter, foundNewFilter, &inst); @@ -705,22 +699,22 @@ virNWFilterDoInstantiate(const unsigned char *vmuuid, } if (instantiate) { - if (virNWFilterLockIface(ifname) < 0) + if (virNWFilterLockIface(binding->portdevname) < 0) goto err_exit; - rc = techdriver->applyNewRules(ifname, inst.rules, inst.nrules); + rc = techdriver->applyNewRules(binding->portdevname, inst.rules, inst.nrules); if (teardownOld && rc == 0) - techdriver->tearOldRules(ifname); + techdriver->tearOldRules(binding->portdevname); - if (rc == 0 && (virNetDevValidateConfig(ifname, NULL, ifindex) <= 0)) { + if (rc == 0 && (virNetDevValidateConfig(binding->portdevname, NULL, ifindex) <= 0)) { virResetLastError(); /* interface changed/disppeared */ - techdriver->allTeardown(ifname); + techdriver->allTeardown(binding->portdevname); rc = -1; } - virNWFilterUnlockIface(ifname); + virNWFilterUnlockIface(binding->portdevname); } err_exit: @@ -749,14 +743,9 @@ virNWFilterDoInstantiate(const unsigned char *vmuuid, */ static int virNWFilterInstantiateFilterUpdate(virNWFilterDriverStatePtr driver, - const unsigned char *vmuuid, bool teardownOld, - const char *ifname, + virNWFilterBindingPtr binding, int ifindex, - const char *linkdev, - const virMacAddr *macaddr, - const char *filtername, - virHashTablePtr filterparams, enum instCase useNewFilter, bool forceWithPendingReq, bool *foundNewFilter) @@ -765,7 +754,6 @@ virNWFilterInstantiateFilterUpdate(virNWFilterDriverStatePtr driver, const char *drvname = EBIPTABLES_DRIVER_ID; virNWFilterTechDriverPtr techdriver; virNWFilterObjPtr obj; - virHashTablePtr vars, vars1; virNWFilterDefPtr filter; virNWFilterDefPtr newFilter; char vmmacaddr[VIR_MAC_STRING_BUFLEN] = {0}; @@ -781,29 +769,22 @@ virNWFilterInstantiateFilterUpdate(virNWFilterDriverStatePtr driver, return -1; } - VIR_DEBUG("filter name: %s", filtername); + VIR_DEBUG("filter name: %s", binding->filter); if (!(obj = virNWFilterObjListFindInstantiateFilter(driver->nwfilters, - filtername))) + binding->filter))) return -1; - virMacAddrFormat(macaddr, vmmacaddr); + virMacAddrFormat(&binding->mac, vmmacaddr); - ipaddr = virNWFilterIPAddrMapGetIPAddr(ifname); + ipaddr = virNWFilterIPAddrMapGetIPAddr(binding->portdevname); - vars1 = virNWFilterCreateVarHashmap(vmmacaddr, ipaddr); - if (!vars1) { + if (virNWFilterVarHashmapAddStdValues(binding->filterparams, + vmmacaddr, ipaddr) < 0) { rc = -1; goto err_exit; } - vars = virNWFilterCreateVarsFrom(vars1, - filterparams); - if (!vars) { - rc = -1; - goto err_exit_vars1; - } - filter = virNWFilterObjGetDef(obj); switch (useNewFilter) { @@ -819,17 +800,11 @@ virNWFilterInstantiateFilterUpdate(virNWFilterDriverStatePtr driver, break; } - rc = virNWFilterDoInstantiate(vmuuid, techdriver, filter, - ifname, ifindex, linkdev, - vars, useNewFilter, foundNewFilter, - teardownOld, macaddr, driver, + rc = virNWFilterDoInstantiate(techdriver, binding, filter, + ifindex, useNewFilter, foundNewFilter, + teardownOld, driver, forceWithPendingReq); - virHashFree(vars); - - err_exit_vars1: - virHashFree(vars1); - err_exit: virNWFilterObjUnlock(obj); @@ -839,15 +814,11 @@ virNWFilterInstantiateFilterUpdate(virNWFilterDriverStatePtr driver, static int virNWFilterInstantiateFilterInternal(virNWFilterDriverStatePtr driver, - const unsigned char *vmuuid, - const virDomainNetDef *net, + virNWFilterBindingPtr binding, bool teardownOld, enum instCase useNewFilter, bool *foundNewFilter) { - const char *linkdev = (net->type == VIR_DOMAIN_NET_TYPE_DIRECT) - ? net->data.direct.linkdev - : NULL; int ifindex; int rc; @@ -856,8 +827,8 @@ virNWFilterInstantiateFilterInternal(virNWFilterDriverStatePtr driver, /* after grabbing the filter update lock check for the interface; if it's not there anymore its filters will be or are being removed (while holding the lock) and we don't want to build new ones */ - if (virNetDevExists(net->ifname) != 1 || - virNetDevGetIndex(net->ifname, &ifindex) < 0) { + if (virNetDevExists(binding->portdevname) != 1 || + virNetDevGetIndex(binding->portdevname, &ifindex) < 0) { /* interfaces / VMs can disappear during filter instantiation; don't mark it as an error */ virResetLastError(); @@ -865,10 +836,10 @@ virNWFilterInstantiateFilterInternal(virNWFilterDriverStatePtr driver, goto cleanup; } - rc = virNWFilterInstantiateFilterUpdate(driver, vmuuid, teardownOld, - net->ifname, ifindex, linkdev, - &net->mac, net->filter, - net->filterparams, useNewFilter, + rc = virNWFilterInstantiateFilterUpdate(driver, teardownOld, + binding, + ifindex, + useNewFilter, false, foundNewFilter); cleanup: @@ -880,13 +851,8 @@ virNWFilterInstantiateFilterInternal(virNWFilterDriverStatePtr driver, int virNWFilterInstantiateFilterLate(virNWFilterDriverStatePtr driver, - const unsigned char *vmuuid, - const char *ifname, - int ifindex, - const char *linkdev, - const virMacAddr *macaddr, - const char *filtername, - virHashTablePtr filterparams) + virNWFilterBindingPtr binding, + int ifindex) { int rc; bool foundNewFilter = false; @@ -894,18 +860,17 @@ virNWFilterInstantiateFilterLate(virNWFilterDriverStatePtr driver, virNWFilterReadLockFilterUpdates(); virMutexLock(&updateMutex); - rc = virNWFilterInstantiateFilterUpdate(driver, vmuuid, true, - ifname, ifindex, linkdev, - macaddr, filtername, filterparams, + rc = virNWFilterInstantiateFilterUpdate(driver, true, + binding, ifindex, INSTANTIATE_ALWAYS, true, &foundNewFilter); if (rc < 0) { /* something went wrong... 'DOWN' the interface */ - if ((virNetDevValidateConfig(ifname, NULL, ifindex) <= 0) || - (virNetDevSetOnline(ifname, false) < 0)) { + if ((virNetDevValidateConfig(binding->portdevname, NULL, ifindex) <= 0) || + (virNetDevSetOnline(binding->portdevname, false) < 0)) { virResetLastError(); /* assuming interface disappeared... */ - _virNWFilterTeardownFilter(ifname); + _virNWFilterTeardownFilter(binding->portdevname); } } @@ -918,12 +883,11 @@ virNWFilterInstantiateFilterLate(virNWFilterDriverStatePtr driver, int virNWFilterInstantiateFilter(virNWFilterDriverStatePtr driver, - const unsigned char *vmuuid, - const virDomainNetDef *net) + virNWFilterBindingPtr binding) { bool foundNewFilter = false; - return virNWFilterInstantiateFilterInternal(driver, vmuuid, net, + return virNWFilterInstantiateFilterInternal(driver, binding, 1, INSTANTIATE_ALWAYS, &foundNewFilter); @@ -932,13 +896,12 @@ virNWFilterInstantiateFilter(virNWFilterDriverStatePtr driver, int virNWFilterUpdateInstantiateFilter(virNWFilterDriverStatePtr driver, - const unsigned char *vmuuid, - const virDomainNetDef *net, + virNWFilterBindingPtr binding, bool *skipIface) { bool foundNewFilter = false; - int rc = virNWFilterInstantiateFilterInternal(driver, vmuuid, net, + int rc = virNWFilterInstantiateFilterInternal(driver, binding, 0, INSTANTIATE_FOLLOW_NEWFILTER, &foundNewFilter); @@ -948,7 +911,7 @@ virNWFilterUpdateInstantiateFilter(virNWFilterDriverStatePtr driver, } static int -virNWFilterRollbackUpdateFilter(const virDomainNetDef *net) +virNWFilterRollbackUpdateFilter(virNWFilterBindingPtr binding) { const char *drvname = EBIPTABLES_DRIVER_ID; int ifindex; @@ -964,17 +927,17 @@ virNWFilterRollbackUpdateFilter(const virDomainNetDef *net) } /* don't tear anything while the address is being learned */ - if (virNetDevGetIndex(net->ifname, &ifindex) < 0) + if (virNetDevGetIndex(binding->portdevname, &ifindex) < 0) virResetLastError(); else if (virNWFilterHasLearnReq(ifindex)) return 0; - return techdriver->tearNewRules(net->ifname); + return techdriver->tearNewRules(binding->portdevname); } static int -virNWFilterTearOldFilter(virDomainNetDefPtr net) +virNWFilterTearOldFilter(virNWFilterBindingPtr binding) { const char *drvname = EBIPTABLES_DRIVER_ID; int ifindex; @@ -990,12 +953,12 @@ virNWFilterTearOldFilter(virDomainNetDefPtr net) } /* don't tear anything while the address is being learned */ - if (virNetDevGetIndex(net->ifname, &ifindex) < 0) + if (virNetDevGetIndex(binding->portdevname, &ifindex) < 0) virResetLastError(); else if (virNWFilterHasLearnReq(ifindex)) return 0; - return techdriver->tearOldRules(net->ifname); + return techdriver->tearOldRules(binding->portdevname); } @@ -1032,11 +995,11 @@ _virNWFilterTeardownFilter(const char *ifname) int -virNWFilterTeardownFilter(const virDomainNetDef *net) +virNWFilterTeardownFilter(virNWFilterBindingPtr binding) { int ret; virMutexLock(&updateMutex); - ret = _virNWFilterTeardownFilter(net->ifname); + ret = _virNWFilterTeardownFilter(binding->portdevname); virMutexUnlock(&updateMutex); return ret; } @@ -1057,12 +1020,21 @@ virNWFilterDomainFWUpdateCB(virDomainObjPtr obj, if (virDomainObjIsActive(obj)) { for (i = 0; i < vm->nnets; i++) { virDomainNetDefPtr net = vm->nets[i]; + virNWFilterBinding binding = { + .ownername = vm->name, + .portdevname = net->ifname, + .linkdevname = (net->type == VIR_DOMAIN_NET_TYPE_DIRECT ? + net->data.direct.linkdev : NULL), + .mac = net->mac, + .filter = net->filter, + .filterparams = net->filterparams, + }; + memcpy(binding.owneruuid, vm->uuid, sizeof(binding.owneruuid)); if ((net->filter) && (net->ifname)) { switch (cb->step) { case STEP_APPLY_NEW: ret = virNWFilterUpdateInstantiateFilter(cb->opaque, - vm->uuid, - net, + &binding, &skipIface); if (ret == 0 && skipIface) { /* filter tree unchanged -- no update needed */ @@ -1074,18 +1046,17 @@ virNWFilterDomainFWUpdateCB(virDomainObjPtr obj, case STEP_TEAR_NEW: if (!virHashLookup(cb->skipInterfaces, net->ifname)) - ret = virNWFilterRollbackUpdateFilter(net); + ret = virNWFilterRollbackUpdateFilter(&binding); break; case STEP_TEAR_OLD: if (!virHashLookup(cb->skipInterfaces, net->ifname)) - ret = virNWFilterTearOldFilter(net); + ret = virNWFilterTearOldFilter(&binding); break; case STEP_APPLY_CURRENT: ret = virNWFilterInstantiateFilter(cb->opaque, - vm->uuid, - net); + &binding); if (ret) virReportError(VIR_ERR_INTERNAL_ERROR, _("Failure while applying current filter on " @@ -1101,3 +1072,45 @@ virNWFilterDomainFWUpdateCB(virDomainObjPtr obj, virObjectUnlock(obj); return ret; } + + +virNWFilterBindingPtr virNWFilterBindingForNet(const char *vmname, + const unsigned char *vmuuid, + virDomainNetDefPtr net) +{ + virNWFilterBindingPtr ret; + + if (VIR_ALLOC(ret) < 0) + return NULL; + + if (VIR_STRDUP(ret->ownername, vmname) < 0) + goto error; + + memcpy(ret->owneruuid, vmuuid, sizeof(ret->owneruuid)); + + if (VIR_STRDUP(ret->portdevname, net->ifname) < 0) + goto error; + + if (net->type == VIR_DOMAIN_NET_TYPE_DIRECT && + net->data.direct.linkdev && + VIR_STRDUP(ret->linkdevname, net->data.direct.linkdev) < 0) + goto error; + + ret->mac = net->mac; + + if (VIR_STRDUP(ret->filter, net->filter) < 0) + goto error; + + if (!(ret->filterparams = virNWFilterHashTableCreate(0))) + goto error; + + if (net->filterparams && + virNWFilterHashTablePutAll(net->filterparams, ret->filterparams) < 0) + goto error; + + return ret; + + error: + virNWFilterBindingFree(ret); + return NULL; +} diff --git a/src/nwfilter/nwfilter_gentech_driver.h b/src/nwfilter/nwfilter_gentech_driver.h index 86cc677e79..0d846dc92f 100644 --- a/src/nwfilter/nwfilter_gentech_driver.h +++ b/src/nwfilter/nwfilter_gentech_driver.h @@ -37,25 +37,17 @@ enum instCase { INSTANTIATE_FOLLOW_NEWFILTER, }; - int virNWFilterInstantiateFilter(virNWFilterDriverStatePtr driver, - const unsigned char *vmuuid, - const virDomainNetDef *net); + virNWFilterBindingPtr binding); int virNWFilterUpdateInstantiateFilter(virNWFilterDriverStatePtr driver, - const unsigned char *vmuuid, - const virDomainNetDef *net, + virNWFilterBindingPtr binding, bool *skipIface); int virNWFilterInstantiateFilterLate(virNWFilterDriverStatePtr driver, - const unsigned char *vmuuid, - const char *ifname, - int ifindex, - const char *linkdev, - const virMacAddr *macaddr, - const char *filtername, - virHashTablePtr filterparams); + virNWFilterBindingPtr binding, + int ifindex); -int virNWFilterTeardownFilter(const virDomainNetDef *net); +int virNWFilterTeardownFilter(virNWFilterBindingPtr binding); virHashTablePtr virNWFilterCreateVarHashmap(const char *macaddr, const virNWFilterVarValue *value); @@ -63,4 +55,8 @@ virHashTablePtr virNWFilterCreateVarHashmap(const char *macaddr, int virNWFilterDomainFWUpdateCB(virDomainObjPtr vm, void *data); +virNWFilterBindingPtr virNWFilterBindingForNet(const char *vmname, + const unsigned char *vmuuid, + virDomainNetDefPtr net); + #endif diff --git a/src/nwfilter/nwfilter_learnipaddr.c b/src/nwfilter/nwfilter_learnipaddr.c index cc3bfd971c..4b13370661 100644 --- a/src/nwfilter/nwfilter_learnipaddr.c +++ b/src/nwfilter/nwfilter_learnipaddr.c @@ -643,19 +643,21 @@ learnIPAddressThread(void *arg) virNWFilterUnlockIface(req->ifname); if ((inetaddr = virSocketAddrFormat(&sa)) != NULL) { + virNWFilterBinding binding = { + .portdevname = req->ifname, + .linkdevname = req->linkdev, + .mac = req->macaddr, + .filter = req->filtername, + .filterparams = req->filterparams, + }; if (virNWFilterIPAddrMapAddIPAddr(req->ifname, inetaddr) < 0) { VIR_ERROR(_("Failed to add IP address %s to IP address " "cache for interface %s"), inetaddr, req->ifname); } ret = virNWFilterInstantiateFilterLate(req->driver, - NULL, - req->ifname, - req->ifindex, - req->linkdev, - &req->macaddr, - req->filtername, - req->filterparams); + &binding, + req->ifindex); VIR_DEBUG("Result from applying firewall rules on " "%s with IP addr %s : %d", req->ifname, inetaddr, ret); VIR_FREE(inetaddr); -- 2.14.3

On Fri, Apr 27, 2018 at 16:25:08 +0100, Daniel P. Berrangé wrote:
Use the virNWFilterBinding struct in the gentech driver code directly.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/nwfilter/nwfilter_dhcpsnoop.c | 35 +++--- src/nwfilter/nwfilter_driver.c | 21 +++- src/nwfilter/nwfilter_gentech_driver.c | 211 +++++++++++++++++---------------- src/nwfilter/nwfilter_gentech_driver.h | 22 ++-- src/nwfilter/nwfilter_learnipaddr.c | 16 +-- 5 files changed, 168 insertions(+), 137 deletions(-)
diff --git a/src/nwfilter/nwfilter_dhcpsnoop.c b/src/nwfilter/nwfilter_dhcpsnoop.c index aec68ab847..dc4e3cb834 100644 --- a/src/nwfilter/nwfilter_dhcpsnoop.c +++ b/src/nwfilter/nwfilter_dhcpsnoop.c @@ -486,15 +486,18 @@ virNWFilterSnoopIPLeaseInstallRule(virNWFilterSnoopIPLeasePtr ipl,
/* instantiate the filters */
- if (req->ifname) + if (req->ifname) { + virNWFilterBinding binding = { + .portdevname = req->ifname, + .linkdevname = req->linkdev, + .mac = req->macaddr, + .filter = req->filtername, + .filterparams = req->vars, + }; rc = virNWFilterInstantiateFilterLate(req->driver, - NULL, - req->ifname, - req->ifindex, - req->linkdev, - &req->macaddr, - req->filtername, - req->vars); + &binding, + req->ifindex); + }
exit_snooprequnlock: virNWFilterSnoopReqUnlock(req); @@ -873,14 +876,16 @@ virNWFilterSnoopReqLeaseDel(virNWFilterSnoopReqPtr req, goto skip_instantiate;
if (ipAddrLeft) { + virNWFilterBinding binding = { + .portdevname = req->ifname, + .linkdevname = req->linkdev, + .mac = req->macaddr, + .filter = req->filtername, + .filterparams = req->vars, + }; ret = virNWFilterInstantiateFilterLate(req->driver, - NULL, - req->ifname, - req->ifindex, - req->linkdev, - &req->macaddr, - req->filtername, - req->vars); + &binding, + req->ifindex); } else { virNWFilterVarValuePtr dhcpsrvrs = virHashLookup(req->vars, NWFILTER_VARNAME_DHCPSERVER); diff --git a/src/nwfilter/nwfilter_driver.c b/src/nwfilter/nwfilter_driver.c index d17a8ec00b..a375e9bda8 100644 --- a/src/nwfilter/nwfilter_driver.c +++ b/src/nwfilter/nwfilter_driver.c @@ -642,19 +642,34 @@ nwfilterGetXMLDesc(virNWFilterPtr nwfilter,
static int -nwfilterInstantiateFilter(const char *vmname ATTRIBUTE_UNUSED, +nwfilterInstantiateFilter(const char *vmname, const unsigned char *vmuuid, virDomainNetDefPtr net) { - return virNWFilterInstantiateFilter(driver, vmuuid, net); + virNWFilterBindingPtr binding; + int ret; + + if (!(binding = virNWFilterBindingForNet(vmname, vmuuid, net))) + return -1; + ret = virNWFilterInstantiateFilter(driver, binding); + virNWFilterBindingFree(binding); + return ret; }
static void nwfilterTeardownFilter(virDomainNetDefPtr net) { + virNWFilterBinding binding = { + .portdevname = net->ifname, + .linkdevname = (net->type == VIR_DOMAIN_NET_TYPE_DIRECT ? + net->data.direct.linkdev : NULL), + .mac = net->mac, + .filter = net->filter, + .filterparams = net->filterparams, + };
I think using virNWFilterBindingForNet or its variant which doesn't copy the arguments would be a bit better than open coding it here. But for consistency and safety reasons I'd prefer if we used virNWFilterBindingForNet everywhere without introducing a non-copying version.
if ((net->ifname) && (net->filter)) - virNWFilterTeardownFilter(net); + virNWFilterTeardownFilter(&binding); }
diff --git a/src/nwfilter/nwfilter_gentech_driver.c b/src/nwfilter/nwfilter_gentech_driver.c index af4411d4db..c755350586 100644 --- a/src/nwfilter/nwfilter_gentech_driver.c +++ b/src/nwfilter/nwfilter_gentech_driver.c @@ -577,12 +577,9 @@ virNWFilterDetermineMissingVarsRec(virNWFilterDefPtr filter,
/** * virNWFilterDoInstantiate: - * @vmuuid: The UUID of the VM * @techdriver: The driver to use for instantiation + * @binding: description of port to bind the filter to * @filter: The filter to instantiate - * @ifname: The name of the interface to apply the rules to - * @vars: A map holding variable names and values used for instantiating - * the filter and its subfilters. * @forceWithPendingReq: Ignore the check whether a pending learn request * is active; 'true' only when the rules are applied late * @@ -596,17 +593,13 @@ virNWFilterDetermineMissingVarsRec(virNWFilterDefPtr filter, * Call this function while holding the NWFilter filter update lock */ static int -virNWFilterDoInstantiate(const unsigned char *vmuuid, - virNWFilterTechDriverPtr techdriver, +virNWFilterDoInstantiate(virNWFilterTechDriverPtr techdriver, + virNWFilterBindingPtr binding, virNWFilterDefPtr filter, - const char *ifname, int ifindex, - const char *linkdev, - virHashTablePtr vars, enum instCase useNewFilter, bool *foundNewFilter, bool teardownOld, - const virMacAddr *macaddr, virNWFilterDriverStatePtr driver, bool forceWithPendingReq) { @@ -628,14 +621,14 @@ virNWFilterDoInstantiate(const unsigned char *vmuuid, }
rc = virNWFilterDetermineMissingVarsRec(filter, - vars, + binding->filterparams, missing_vars, useNewFilter, driver); if (rc < 0) goto err_exit;
- lv = virHashLookup(vars, NWFILTER_VARNAME_CTRL_IP_LEARNING); + lv = virHashLookup(binding->filterparams, NWFILTER_VARNAME_CTRL_IP_LEARNING); if (lv) learning = virNWFilterVarValueGetNthValue(lv, 0); else @@ -652,19 +645,20 @@ virNWFilterDoInstantiate(const unsigned char *vmuuid, goto err_unresolvable_vars; } if (STRCASEEQ(learning, "dhcp")) { - rc = virNWFilterDHCPSnoopReq(techdriver, ifname, linkdev, - vmuuid, macaddr, - filter->name, vars, driver); + rc = virNWFilterDHCPSnoopReq(techdriver, binding->portdevname, + binding->linkdevname, + binding->owneruuid, &binding->mac, + filter->name, binding->filterparams, driver); goto err_exit; } else if (STRCASEEQ(learning, "any")) { if (!virNWFilterHasLearnReq(ifindex)) { rc = virNWFilterLearnIPAddress(techdriver, - ifname, + binding->portdevname, ifindex, - linkdev, - macaddr, + binding->linkdevname, + &binding->mac, filter->name, - vars, driver, + binding->filterparams, driver, DETECT_DHCP|DETECT_STATIC); } goto err_exit; @@ -688,7 +682,7 @@ virNWFilterDoInstantiate(const unsigned char *vmuuid,
rc = virNWFilterDefToInst(driver, filter, - vars, + binding->filterparams, useNewFilter, foundNewFilter, &inst);
@@ -705,22 +699,22 @@ virNWFilterDoInstantiate(const unsigned char *vmuuid, }
if (instantiate) { - if (virNWFilterLockIface(ifname) < 0) + if (virNWFilterLockIface(binding->portdevname) < 0) goto err_exit;
- rc = techdriver->applyNewRules(ifname, inst.rules, inst.nrules); + rc = techdriver->applyNewRules(binding->portdevname, inst.rules, inst.nrules);
if (teardownOld && rc == 0) - techdriver->tearOldRules(ifname); + techdriver->tearOldRules(binding->portdevname);
- if (rc == 0 && (virNetDevValidateConfig(ifname, NULL, ifindex) <= 0)) { + if (rc == 0 && (virNetDevValidateConfig(binding->portdevname, NULL, ifindex) <= 0)) { virResetLastError(); /* interface changed/disppeared */ - techdriver->allTeardown(ifname); + techdriver->allTeardown(binding->portdevname); rc = -1; }
- virNWFilterUnlockIface(ifname); + virNWFilterUnlockIface(binding->portdevname); }
err_exit: @@ -749,14 +743,9 @@ virNWFilterDoInstantiate(const unsigned char *vmuuid, */ static int virNWFilterInstantiateFilterUpdate(virNWFilterDriverStatePtr driver, - const unsigned char *vmuuid, bool teardownOld, - const char *ifname, + virNWFilterBindingPtr binding, int ifindex, - const char *linkdev, - const virMacAddr *macaddr, - const char *filtername, - virHashTablePtr filterparams, enum instCase useNewFilter, bool forceWithPendingReq, bool *foundNewFilter) @@ -765,7 +754,6 @@ virNWFilterInstantiateFilterUpdate(virNWFilterDriverStatePtr driver, const char *drvname = EBIPTABLES_DRIVER_ID; virNWFilterTechDriverPtr techdriver; virNWFilterObjPtr obj; - virHashTablePtr vars, vars1; virNWFilterDefPtr filter; virNWFilterDefPtr newFilter; char vmmacaddr[VIR_MAC_STRING_BUFLEN] = {0}; @@ -781,29 +769,22 @@ virNWFilterInstantiateFilterUpdate(virNWFilterDriverStatePtr driver, return -1; }
- VIR_DEBUG("filter name: %s", filtername); + VIR_DEBUG("filter name: %s", binding->filter);
if (!(obj = virNWFilterObjListFindInstantiateFilter(driver->nwfilters, - filtername))) + binding->filter))) return -1;
- virMacAddrFormat(macaddr, vmmacaddr); + virMacAddrFormat(&binding->mac, vmmacaddr);
- ipaddr = virNWFilterIPAddrMapGetIPAddr(ifname); + ipaddr = virNWFilterIPAddrMapGetIPAddr(binding->portdevname);
The following change should be in a separate patch with an explanation why it is safe. Originally, we made a copy of filterparams and added NWFILTER_STD_VAR_MAC and NWFILTER_STD_VAR_IP into the copy. But now this code just operates directly on filterparams possibly modifying net-filterparams. This doesn't look like something we should do IMHO.
- vars1 = virNWFilterCreateVarHashmap(vmmacaddr, ipaddr); - if (!vars1) { + if (virNWFilterVarHashmapAddStdValues(binding->filterparams, + vmmacaddr, ipaddr) < 0) { rc = -1; goto err_exit; }
- vars = virNWFilterCreateVarsFrom(vars1, - filterparams); - if (!vars) { - rc = -1; - goto err_exit_vars1; - } - filter = virNWFilterObjGetDef(obj);
switch (useNewFilter) { @@ -819,17 +800,11 @@ virNWFilterInstantiateFilterUpdate(virNWFilterDriverStatePtr driver, break; }
- rc = virNWFilterDoInstantiate(vmuuid, techdriver, filter, - ifname, ifindex, linkdev, - vars, useNewFilter, foundNewFilter, - teardownOld, macaddr, driver, + rc = virNWFilterDoInstantiate(techdriver, binding, filter, + ifindex, useNewFilter, foundNewFilter, + teardownOld, driver, forceWithPendingReq);
- virHashFree(vars); - - err_exit_vars1: - virHashFree(vars1); - err_exit: virNWFilterObjUnlock(obj);
@@ -839,15 +814,11 @@ virNWFilterInstantiateFilterUpdate(virNWFilterDriverStatePtr driver,
static int virNWFilterInstantiateFilterInternal(virNWFilterDriverStatePtr driver, - const unsigned char *vmuuid, - const virDomainNetDef *net, + virNWFilterBindingPtr binding, bool teardownOld, enum instCase useNewFilter, bool *foundNewFilter) { - const char *linkdev = (net->type == VIR_DOMAIN_NET_TYPE_DIRECT) - ? net->data.direct.linkdev - : NULL; int ifindex; int rc;
@@ -856,8 +827,8 @@ virNWFilterInstantiateFilterInternal(virNWFilterDriverStatePtr driver, /* after grabbing the filter update lock check for the interface; if it's not there anymore its filters will be or are being removed (while holding the lock) and we don't want to build new ones */ - if (virNetDevExists(net->ifname) != 1 || - virNetDevGetIndex(net->ifname, &ifindex) < 0) { + if (virNetDevExists(binding->portdevname) != 1 || + virNetDevGetIndex(binding->portdevname, &ifindex) < 0) { /* interfaces / VMs can disappear during filter instantiation; don't mark it as an error */ virResetLastError(); @@ -865,10 +836,10 @@ virNWFilterInstantiateFilterInternal(virNWFilterDriverStatePtr driver, goto cleanup; }
- rc = virNWFilterInstantiateFilterUpdate(driver, vmuuid, teardownOld, - net->ifname, ifindex, linkdev, - &net->mac, net->filter, - net->filterparams, useNewFilter, + rc = virNWFilterInstantiateFilterUpdate(driver, teardownOld, + binding, + ifindex, + useNewFilter, false, foundNewFilter);
cleanup: @@ -880,13 +851,8 @@ virNWFilterInstantiateFilterInternal(virNWFilterDriverStatePtr driver,
int virNWFilterInstantiateFilterLate(virNWFilterDriverStatePtr driver, - const unsigned char *vmuuid, - const char *ifname, - int ifindex, - const char *linkdev, - const virMacAddr *macaddr, - const char *filtername, - virHashTablePtr filterparams) + virNWFilterBindingPtr binding, + int ifindex) { int rc; bool foundNewFilter = false; @@ -894,18 +860,17 @@ virNWFilterInstantiateFilterLate(virNWFilterDriverStatePtr driver, virNWFilterReadLockFilterUpdates(); virMutexLock(&updateMutex);
- rc = virNWFilterInstantiateFilterUpdate(driver, vmuuid, true, - ifname, ifindex, linkdev, - macaddr, filtername, filterparams, + rc = virNWFilterInstantiateFilterUpdate(driver, true, + binding, ifindex, INSTANTIATE_ALWAYS, true, &foundNewFilter); if (rc < 0) { /* something went wrong... 'DOWN' the interface */ - if ((virNetDevValidateConfig(ifname, NULL, ifindex) <= 0) || - (virNetDevSetOnline(ifname, false) < 0)) { + if ((virNetDevValidateConfig(binding->portdevname, NULL, ifindex) <= 0) || + (virNetDevSetOnline(binding->portdevname, false) < 0)) { virResetLastError(); /* assuming interface disappeared... */ - _virNWFilterTeardownFilter(ifname); + _virNWFilterTeardownFilter(binding->portdevname); } }
@@ -918,12 +883,11 @@ virNWFilterInstantiateFilterLate(virNWFilterDriverStatePtr driver,
int virNWFilterInstantiateFilter(virNWFilterDriverStatePtr driver, - const unsigned char *vmuuid, - const virDomainNetDef *net) + virNWFilterBindingPtr binding) { bool foundNewFilter = false;
- return virNWFilterInstantiateFilterInternal(driver, vmuuid, net, + return virNWFilterInstantiateFilterInternal(driver, binding, 1, INSTANTIATE_ALWAYS, &foundNewFilter); @@ -932,13 +896,12 @@ virNWFilterInstantiateFilter(virNWFilterDriverStatePtr driver,
int virNWFilterUpdateInstantiateFilter(virNWFilterDriverStatePtr driver, - const unsigned char *vmuuid, - const virDomainNetDef *net, + virNWFilterBindingPtr binding, bool *skipIface) { bool foundNewFilter = false;
- int rc = virNWFilterInstantiateFilterInternal(driver, vmuuid, net, + int rc = virNWFilterInstantiateFilterInternal(driver, binding, 0, INSTANTIATE_FOLLOW_NEWFILTER, &foundNewFilter); @@ -948,7 +911,7 @@ virNWFilterUpdateInstantiateFilter(virNWFilterDriverStatePtr driver, }
static int -virNWFilterRollbackUpdateFilter(const virDomainNetDef *net) +virNWFilterRollbackUpdateFilter(virNWFilterBindingPtr binding) { const char *drvname = EBIPTABLES_DRIVER_ID; int ifindex; @@ -964,17 +927,17 @@ virNWFilterRollbackUpdateFilter(const virDomainNetDef *net) }
/* don't tear anything while the address is being learned */ - if (virNetDevGetIndex(net->ifname, &ifindex) < 0) + if (virNetDevGetIndex(binding->portdevname, &ifindex) < 0) virResetLastError(); else if (virNWFilterHasLearnReq(ifindex)) return 0;
- return techdriver->tearNewRules(net->ifname); + return techdriver->tearNewRules(binding->portdevname); }
static int -virNWFilterTearOldFilter(virDomainNetDefPtr net) +virNWFilterTearOldFilter(virNWFilterBindingPtr binding) { const char *drvname = EBIPTABLES_DRIVER_ID; int ifindex; @@ -990,12 +953,12 @@ virNWFilterTearOldFilter(virDomainNetDefPtr net) }
/* don't tear anything while the address is being learned */ - if (virNetDevGetIndex(net->ifname, &ifindex) < 0) + if (virNetDevGetIndex(binding->portdevname, &ifindex) < 0) virResetLastError(); else if (virNWFilterHasLearnReq(ifindex)) return 0;
- return techdriver->tearOldRules(net->ifname); + return techdriver->tearOldRules(binding->portdevname); }
@@ -1032,11 +995,11 @@ _virNWFilterTeardownFilter(const char *ifname)
int -virNWFilterTeardownFilter(const virDomainNetDef *net) +virNWFilterTeardownFilter(virNWFilterBindingPtr binding) { int ret; virMutexLock(&updateMutex); - ret = _virNWFilterTeardownFilter(net->ifname); + ret = _virNWFilterTeardownFilter(binding->portdevname); virMutexUnlock(&updateMutex); return ret; } @@ -1057,12 +1020,21 @@ virNWFilterDomainFWUpdateCB(virDomainObjPtr obj, if (virDomainObjIsActive(obj)) { for (i = 0; i < vm->nnets; i++) { virDomainNetDefPtr net = vm->nets[i]; + virNWFilterBinding binding = { + .ownername = vm->name, + .portdevname = net->ifname, + .linkdevname = (net->type == VIR_DOMAIN_NET_TYPE_DIRECT ? + net->data.direct.linkdev : NULL), + .mac = net->mac, + .filter = net->filter, + .filterparams = net->filterparams, + }; + memcpy(binding.owneruuid, vm->uuid, sizeof(binding.owneruuid));
I'd prefer virNWFilterBindingForNet here too.
if ((net->filter) && (net->ifname)) { switch (cb->step) { case STEP_APPLY_NEW: ret = virNWFilterUpdateInstantiateFilter(cb->opaque, - vm->uuid, - net, + &binding, &skipIface); if (ret == 0 && skipIface) { /* filter tree unchanged -- no update needed */ @@ -1074,18 +1046,17 @@ virNWFilterDomainFWUpdateCB(virDomainObjPtr obj,
case STEP_TEAR_NEW: if (!virHashLookup(cb->skipInterfaces, net->ifname)) - ret = virNWFilterRollbackUpdateFilter(net); + ret = virNWFilterRollbackUpdateFilter(&binding); break;
case STEP_TEAR_OLD: if (!virHashLookup(cb->skipInterfaces, net->ifname)) - ret = virNWFilterTearOldFilter(net); + ret = virNWFilterTearOldFilter(&binding); break;
case STEP_APPLY_CURRENT: ret = virNWFilterInstantiateFilter(cb->opaque, - vm->uuid, - net); + &binding); if (ret) virReportError(VIR_ERR_INTERNAL_ERROR, _("Failure while applying current filter on " @@ -1101,3 +1072,45 @@ virNWFilterDomainFWUpdateCB(virDomainObjPtr obj, virObjectUnlock(obj); return ret; } + + +virNWFilterBindingPtr virNWFilterBindingForNet(const char *vmname,
The type should be on a separate line.
+ const unsigned char *vmuuid, + virDomainNetDefPtr net)
This function would better fit in nwfilter_conf.c next to virNWFilterBindingCopy and it could even be added in the same patch. Or is there a good reason for having this function in nwfilter_gentech_driver.c?
+{ + virNWFilterBindingPtr ret; + + if (VIR_ALLOC(ret) < 0) + return NULL; + + if (VIR_STRDUP(ret->ownername, vmname) < 0) + goto error; + + memcpy(ret->owneruuid, vmuuid, sizeof(ret->owneruuid)); + + if (VIR_STRDUP(ret->portdevname, net->ifname) < 0) + goto error; + + if (net->type == VIR_DOMAIN_NET_TYPE_DIRECT && + net->data.direct.linkdev &&
VIR_STRDUP accepts NULL source.
+ VIR_STRDUP(ret->linkdevname, net->data.direct.linkdev) < 0) + goto error; + + ret->mac = net->mac; + + if (VIR_STRDUP(ret->filter, net->filter) < 0) + goto error; + + if (!(ret->filterparams = virNWFilterHashTableCreate(0))) + goto error; + + if (net->filterparams && + virNWFilterHashTablePutAll(net->filterparams, ret->filterparams) < 0) + goto error; + + return ret; + + error: + virNWFilterBindingFree(ret); + return NULL; +} diff --git a/src/nwfilter/nwfilter_gentech_driver.h b/src/nwfilter/nwfilter_gentech_driver.h index 86cc677e79..0d846dc92f 100644 --- a/src/nwfilter/nwfilter_gentech_driver.h +++ b/src/nwfilter/nwfilter_gentech_driver.h @@ -37,25 +37,17 @@ enum instCase { INSTANTIATE_FOLLOW_NEWFILTER, };
-
Unrelated.
int virNWFilterInstantiateFilter(virNWFilterDriverStatePtr driver, - const unsigned char *vmuuid, - const virDomainNetDef *net); + virNWFilterBindingPtr binding); int virNWFilterUpdateInstantiateFilter(virNWFilterDriverStatePtr driver, - const unsigned char *vmuuid, - const virDomainNetDef *net, + virNWFilterBindingPtr binding, bool *skipIface);
int virNWFilterInstantiateFilterLate(virNWFilterDriverStatePtr driver, - const unsigned char *vmuuid, - const char *ifname, - int ifindex, - const char *linkdev, - const virMacAddr *macaddr, - const char *filtername, - virHashTablePtr filterparams); + virNWFilterBindingPtr binding, + int ifindex);
-int virNWFilterTeardownFilter(const virDomainNetDef *net); +int virNWFilterTeardownFilter(virNWFilterBindingPtr binding);
virHashTablePtr virNWFilterCreateVarHashmap(const char *macaddr, const virNWFilterVarValue *value); @@ -63,4 +55,8 @@ virHashTablePtr virNWFilterCreateVarHashmap(const char *macaddr, int virNWFilterDomainFWUpdateCB(virDomainObjPtr vm, void *data);
+virNWFilterBindingPtr virNWFilterBindingForNet(const char *vmname, + const unsigned char *vmuuid, + virDomainNetDefPtr net); + #endif diff --git a/src/nwfilter/nwfilter_learnipaddr.c b/src/nwfilter/nwfilter_learnipaddr.c index cc3bfd971c..4b13370661 100644 --- a/src/nwfilter/nwfilter_learnipaddr.c +++ b/src/nwfilter/nwfilter_learnipaddr.c @@ -643,19 +643,21 @@ learnIPAddressThread(void *arg) virNWFilterUnlockIface(req->ifname);
if ((inetaddr = virSocketAddrFormat(&sa)) != NULL) { + virNWFilterBinding binding = { + .portdevname = req->ifname, + .linkdevname = req->linkdev, + .mac = req->macaddr, + .filter = req->filtername, + .filterparams = req->filterparams, + }; if (virNWFilterIPAddrMapAddIPAddr(req->ifname, inetaddr) < 0) { VIR_ERROR(_("Failed to add IP address %s to IP address " "cache for interface %s"), inetaddr, req->ifname); }
ret = virNWFilterInstantiateFilterLate(req->driver, - NULL, - req->ifname, - req->ifindex, - req->linkdev, - &req->macaddr, - req->filtername, - req->filterparams); + &binding, + req->ifindex); VIR_DEBUG("Result from applying firewall rules on " "%s with IP addr %s : %d", req->ifname, inetaddr, ret); VIR_FREE(inetaddr);
Jirka

On Mon, Apr 30, 2018 at 05:05:40PM +0200, Jiri Denemark wrote:
On Fri, Apr 27, 2018 at 16:25:08 +0100, Daniel P. Berrangé wrote:
Use the virNWFilterBinding struct in the gentech driver code directly.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/nwfilter/nwfilter_dhcpsnoop.c | 35 +++--- src/nwfilter/nwfilter_driver.c | 21 +++- src/nwfilter/nwfilter_gentech_driver.c | 211 +++++++++++++++++---------------- src/nwfilter/nwfilter_gentech_driver.h | 22 ++-- src/nwfilter/nwfilter_learnipaddr.c | 16 +-- 5 files changed, 168 insertions(+), 137 deletions(-)
diff --git a/src/nwfilter/nwfilter_driver.c b/src/nwfilter/nwfilter_driver.c index d17a8ec00b..a375e9bda8 100644 --- a/src/nwfilter/nwfilter_driver.c +++ b/src/nwfilter/nwfilter_driver.c
static void nwfilterTeardownFilter(virDomainNetDefPtr net) { + virNWFilterBinding binding = { + .portdevname = net->ifname, + .linkdevname = (net->type == VIR_DOMAIN_NET_TYPE_DIRECT ? + net->data.direct.linkdev : NULL), + .mac = net->mac, + .filter = net->filter, + .filterparams = net->filterparams, + };
I think using virNWFilterBindingForNet or its variant which doesn't copy the arguments would be a bit better than open coding it here. But for consistency and safety reasons I'd prefer if we used virNWFilterBindingForNet everywhere without introducing a non-copying version.
Your point is right, but it isn't worth doing as this is just temporary code that's deleted again in patch 13 :-)
diff --git a/src/nwfilter/nwfilter_gentech_driver.c b/src/nwfilter/nwfilter_gentech_driver.c index af4411d4db..c755350586 100644 --- a/src/nwfilter/nwfilter_gentech_driver.c +++ b/src/nwfilter/nwfilter_gentech_driver.c
static int virNWFilterInstantiateFilterUpdate(virNWFilterDriverStatePtr driver, - const unsigned char *vmuuid, bool teardownOld, - const char *ifname, + virNWFilterBindingPtr binding, int ifindex, - const char *linkdev, - const virMacAddr *macaddr, - const char *filtername, - virHashTablePtr filterparams, enum instCase useNewFilter, bool forceWithPendingReq, bool *foundNewFilter) @@ -765,7 +754,6 @@ virNWFilterInstantiateFilterUpdate(virNWFilterDriverStatePtr driver, const char *drvname = EBIPTABLES_DRIVER_ID; virNWFilterTechDriverPtr techdriver; virNWFilterObjPtr obj; - virHashTablePtr vars, vars1; virNWFilterDefPtr filter; virNWFilterDefPtr newFilter; char vmmacaddr[VIR_MAC_STRING_BUFLEN] = {0}; @@ -781,29 +769,22 @@ virNWFilterInstantiateFilterUpdate(virNWFilterDriverStatePtr driver, return -1; }
- VIR_DEBUG("filter name: %s", filtername); + VIR_DEBUG("filter name: %s", binding->filter);
if (!(obj = virNWFilterObjListFindInstantiateFilter(driver->nwfilters, - filtername))) + binding->filter))) return -1;
- virMacAddrFormat(macaddr, vmmacaddr); + virMacAddrFormat(&binding->mac, vmmacaddr);
- ipaddr = virNWFilterIPAddrMapGetIPAddr(ifname); + ipaddr = virNWFilterIPAddrMapGetIPAddr(binding->portdevname);
The following change should be in a separate patch with an explanation why it is safe. Originally, we made a copy of filterparams and added NWFILTER_STD_VAR_MAC and NWFILTER_STD_VAR_IP into the copy. But now this code just operates directly on filterparams possibly modifying net-filterparams. This doesn't look like something we should do IMHO.
We still make a copy of filterparams higher up in the call stack. virNWFilterBindingForNet() deep-copies what is in the virDomainNetPtr object - I discovered the need for this the hard way when I saw the domain XML gaining these two parameters :-)
@@ -1057,12 +1020,21 @@ virNWFilterDomainFWUpdateCB(virDomainObjPtr obj, if (virDomainObjIsActive(obj)) { for (i = 0; i < vm->nnets; i++) { virDomainNetDefPtr net = vm->nets[i]; + virNWFilterBinding binding = { + .ownername = vm->name, + .portdevname = net->ifname, + .linkdevname = (net->type == VIR_DOMAIN_NET_TYPE_DIRECT ? + net->data.direct.linkdev : NULL), + .mac = net->mac, + .filter = net->filter, + .filterparams = net->filterparams, + }; + memcpy(binding.owneruuid, vm->uuid, sizeof(binding.owneruuid));
I'd prefer virNWFilterBindingForNet here too.
This code gets removed in the last patch in this series too.
@@ -1101,3 +1072,45 @@ virNWFilterDomainFWUpdateCB(virDomainObjPtr obj, virObjectUnlock(obj); return ret; } + + +virNWFilterBindingPtr virNWFilterBindingForNet(const char *vmname,
The type should be on a separate line.
+ const unsigned char *vmuuid, + virDomainNetDefPtr net)
This function would better fit in nwfilter_conf.c next to virNWFilterBindingCopy and it could even be added in the same patch. Or is there a good reason for having this function in nwfilter_gentech_driver.c?
I'm undecided on this point. Ultimately I'll probably want to push the virDomainNetDefPtr -> virNWFilterBindingPtr conversion into the virt drivers, so they can parse an XML doc of the virNWFilterBindingPtr into the nwfilter daemon. So it'll almost certainly end up outside the nwfilter codebase, but not 100% decided where yet.
+{ + virNWFilterBindingPtr ret; + + if (VIR_ALLOC(ret) < 0) + return NULL; + + if (VIR_STRDUP(ret->ownername, vmname) < 0) + goto error; + + memcpy(ret->owneruuid, vmuuid, sizeof(ret->owneruuid)); + + if (VIR_STRDUP(ret->portdevname, net->ifname) < 0) + goto error; + + if (net->type == VIR_DOMAIN_NET_TYPE_DIRECT && + net->data.direct.linkdev &&
VIR_STRDUP accepts NULL source.
+ VIR_STRDUP(ret->linkdevname, net->data.direct.linkdev) < 0) + goto error; + + ret->mac = net->mac; + + if (VIR_STRDUP(ret->filter, net->filter) < 0) + goto error; + + if (!(ret->filterparams = virNWFilterHashTableCreate(0))) + goto error; + + if (net->filterparams && + virNWFilterHashTablePutAll(net->filterparams, ret->filterparams) < 0) + goto error; + + return ret; + + error: + virNWFilterBindingFree(ret); + return NULL; +}
Regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|

On Thu, May 03, 2018 at 02:57:04PM +0100, Daniel P. Berrangé wrote:
On Mon, Apr 30, 2018 at 05:05:40PM +0200, Jiri Denemark wrote:
On Fri, Apr 27, 2018 at 16:25:08 +0100, Daniel P. Berrangé wrote:
Use the virNWFilterBinding struct in the gentech driver code directly.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/nwfilter/nwfilter_dhcpsnoop.c | 35 +++--- src/nwfilter/nwfilter_driver.c | 21 +++- src/nwfilter/nwfilter_gentech_driver.c | 211 +++++++++++++++++---------------- src/nwfilter/nwfilter_gentech_driver.h | 22 ++-- src/nwfilter/nwfilter_learnipaddr.c | 16 +-- 5 files changed, 168 insertions(+), 137 deletions(-)
diff --git a/src/nwfilter/nwfilter_driver.c b/src/nwfilter/nwfilter_driver.c index d17a8ec00b..a375e9bda8 100644 --- a/src/nwfilter/nwfilter_driver.c +++ b/src/nwfilter/nwfilter_driver.c
static void nwfilterTeardownFilter(virDomainNetDefPtr net) { + virNWFilterBinding binding = { + .portdevname = net->ifname, + .linkdevname = (net->type == VIR_DOMAIN_NET_TYPE_DIRECT ? + net->data.direct.linkdev : NULL), + .mac = net->mac, + .filter = net->filter, + .filterparams = net->filterparams, + };
I think using virNWFilterBindingForNet or its variant which doesn't copy the arguments would be a bit better than open coding it here. But for consistency and safety reasons I'd prefer if we used virNWFilterBindingForNet everywhere without introducing a non-copying version.
Your point is right, but it isn't worth doing as this is just temporary code that's deleted again in patch 13 :-)
diff --git a/src/nwfilter/nwfilter_gentech_driver.c b/src/nwfilter/nwfilter_gentech_driver.c index af4411d4db..c755350586 100644 --- a/src/nwfilter/nwfilter_gentech_driver.c +++ b/src/nwfilter/nwfilter_gentech_driver.c
static int virNWFilterInstantiateFilterUpdate(virNWFilterDriverStatePtr driver, - const unsigned char *vmuuid, bool teardownOld, - const char *ifname, + virNWFilterBindingPtr binding, int ifindex, - const char *linkdev, - const virMacAddr *macaddr, - const char *filtername, - virHashTablePtr filterparams, enum instCase useNewFilter, bool forceWithPendingReq, bool *foundNewFilter) @@ -765,7 +754,6 @@ virNWFilterInstantiateFilterUpdate(virNWFilterDriverStatePtr driver, const char *drvname = EBIPTABLES_DRIVER_ID; virNWFilterTechDriverPtr techdriver; virNWFilterObjPtr obj; - virHashTablePtr vars, vars1; virNWFilterDefPtr filter; virNWFilterDefPtr newFilter; char vmmacaddr[VIR_MAC_STRING_BUFLEN] = {0}; @@ -781,29 +769,22 @@ virNWFilterInstantiateFilterUpdate(virNWFilterDriverStatePtr driver, return -1; }
- VIR_DEBUG("filter name: %s", filtername); + VIR_DEBUG("filter name: %s", binding->filter);
if (!(obj = virNWFilterObjListFindInstantiateFilter(driver->nwfilters, - filtername))) + binding->filter))) return -1;
- virMacAddrFormat(macaddr, vmmacaddr); + virMacAddrFormat(&binding->mac, vmmacaddr);
- ipaddr = virNWFilterIPAddrMapGetIPAddr(ifname); + ipaddr = virNWFilterIPAddrMapGetIPAddr(binding->portdevname);
The following change should be in a separate patch with an explanation why it is safe. Originally, we made a copy of filterparams and added NWFILTER_STD_VAR_MAC and NWFILTER_STD_VAR_IP into the copy. But now this code just operates directly on filterparams possibly modifying net-filterparams. This doesn't look like something we should do IMHO.
We still make a copy of filterparams higher up in the call stack. virNWFilterBindingForNet() deep-copies what is in the virDomainNetPtr object - I discovered the need for this the hard way when I saw the domain XML gaining these two parameters :-)
@@ -1057,12 +1020,21 @@ virNWFilterDomainFWUpdateCB(virDomainObjPtr obj, if (virDomainObjIsActive(obj)) { for (i = 0; i < vm->nnets; i++) { virDomainNetDefPtr net = vm->nets[i]; + virNWFilterBinding binding = { + .ownername = vm->name, + .portdevname = net->ifname, + .linkdevname = (net->type == VIR_DOMAIN_NET_TYPE_DIRECT ? + net->data.direct.linkdev : NULL), + .mac = net->mac, + .filter = net->filter, + .filterparams = net->filterparams, + }; + memcpy(binding.owneruuid, vm->uuid, sizeof(binding.owneruuid));
I'd prefer virNWFilterBindingForNet here too.
This code gets removed in the last patch in this series too.
Actually in this case, it is critical to use virNWFilterBindingForNet to avoid net->filterparams getting splattered during rebuild. So I must make this change now to preserve git bisectability. Regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|

Use the virNWFilterBinding struct i nthe IP address learning code directly. Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/nwfilter/nwfilter_gentech_driver.c | 7 +-- src/nwfilter/nwfilter_learnipaddr.c | 98 ++++++++++------------------------ src/nwfilter/nwfilter_learnipaddr.h | 6 +-- 3 files changed, 30 insertions(+), 81 deletions(-) diff --git a/src/nwfilter/nwfilter_gentech_driver.c b/src/nwfilter/nwfilter_gentech_driver.c index c755350586..514315f781 100644 --- a/src/nwfilter/nwfilter_gentech_driver.c +++ b/src/nwfilter/nwfilter_gentech_driver.c @@ -653,12 +653,9 @@ virNWFilterDoInstantiate(virNWFilterTechDriverPtr techdriver, } else if (STRCASEEQ(learning, "any")) { if (!virNWFilterHasLearnReq(ifindex)) { rc = virNWFilterLearnIPAddress(techdriver, - binding->portdevname, + binding, ifindex, - binding->linkdevname, - &binding->mac, - filter->name, - binding->filterparams, driver, + driver, DETECT_DHCP|DETECT_STATIC); } goto err_exit; diff --git a/src/nwfilter/nwfilter_learnipaddr.c b/src/nwfilter/nwfilter_learnipaddr.c index 4b13370661..0e76921648 100644 --- a/src/nwfilter/nwfilter_learnipaddr.c +++ b/src/nwfilter/nwfilter_learnipaddr.c @@ -137,12 +137,8 @@ typedef struct _virNWFilterIPAddrLearnReq virNWFilterIPAddrLearnReq; typedef virNWFilterIPAddrLearnReq *virNWFilterIPAddrLearnReqPtr; struct _virNWFilterIPAddrLearnReq { virNWFilterTechDriverPtr techdriver; - char ifname[IF_NAMESIZE]; int ifindex; - char linkdev[IF_NAMESIZE]; - virMacAddr macaddr; - char *filtername; - virHashTablePtr filterparams; + virNWFilterBindingPtr binding; virNWFilterDriverStatePtr driver; enum howDetect howDetect; @@ -232,8 +228,7 @@ virNWFilterIPAddrLearnReqFree(virNWFilterIPAddrLearnReqPtr req) if (!req) return; - VIR_FREE(req->filtername); - virHashFree(req->filterparams); + virNWFilterBindingFree(req->binding); VIR_FREE(req); } @@ -404,8 +399,9 @@ learnIPAddressThread(void *arg) virNWFilterIPAddrLearnReqPtr req = arg; uint32_t vmaddr = 0, bcastaddr = 0; unsigned int ethHdrSize; - char *listen_if = (strlen(req->linkdev) != 0) ? req->linkdev - : req->ifname; + char *listen_if = (req->binding->linkdevname ? + req->binding->linkdevname : + req->binding->portdevname); int dhcp_opts_len; char macaddr[VIR_MAC_STRING_BUFLEN]; virBuffer buf = VIR_BUFFER_INITIALIZER; @@ -415,13 +411,13 @@ learnIPAddressThread(void *arg) enum howDetect howDetected = 0; virNWFilterTechDriverPtr techdriver = req->techdriver; - if (virNWFilterLockIface(req->ifname) < 0) + if (virNWFilterLockIface(req->binding->portdevname) < 0) goto err_no_lock; req->status = 0; /* anything change to the VM's interface -- check at least once */ - if (virNetDevValidateConfig(req->ifname, NULL, req->ifindex) <= 0) { + if (virNetDevValidateConfig(req->binding->portdevname, NULL, req->ifindex) <= 0) { virResetLastError(); req->status = ENODEV; goto done; @@ -435,12 +431,12 @@ learnIPAddressThread(void *arg) goto done; } - virMacAddrFormat(&req->macaddr, macaddr); + virMacAddrFormat(&req->binding->mac, macaddr); switch (req->howDetect) { case DETECT_DHCP: - if (techdriver->applyDHCPOnlyRules(req->ifname, - &req->macaddr, + if (techdriver->applyDHCPOnlyRules(req->binding->portdevname, + &req->binding->mac, NULL, false) < 0) { req->status = EINVAL; goto done; @@ -448,8 +444,8 @@ learnIPAddressThread(void *arg) virBufferAddLit(&buf, "src port 67 and dst port 68"); break; case DETECT_STATIC: - if (techdriver->applyBasicRules(req->ifname, - &req->macaddr) < 0) { + if (techdriver->applyBasicRules(req->binding->portdevname, + &req->binding->mac) < 0) { req->status = EINVAL; goto done; } @@ -495,7 +491,7 @@ learnIPAddressThread(void *arg) } /* check whether VM's dev is still there */ - if (virNetDevValidateConfig(req->ifname, NULL, req->ifindex) <= 0) { + if (virNetDevValidateConfig(req->binding->portdevname, NULL, req->ifindex) <= 0) { virResetLastError(); req->status = ENODEV; showError = false; @@ -527,7 +523,7 @@ learnIPAddressThread(void *arg) continue; } - if (virMacAddrCmpRaw(&req->macaddr, ether_hdr->ether_shost) == 0) { + if (virMacAddrCmpRaw(&req->binding->mac, ether_hdr->ether_shost) == 0) { /* packets from the VM */ if (etherType == ETHERTYPE_IP && @@ -566,7 +562,7 @@ learnIPAddressThread(void *arg) break; } } - } else if (virMacAddrCmpRaw(&req->macaddr, + } else if (virMacAddrCmpRaw(&req->binding->mac, ether_hdr->ether_dhost) == 0 || /* allow Broadcast replies from DHCP server */ virMacAddrIsBroadcastRaw(ether_hdr->ether_dhost)) { @@ -596,7 +592,7 @@ learnIPAddressThread(void *arg) ((char *)udphdr + sizeof(udphdr)); if (dhcp->op == 2 /* BOOTREPLY */ && virMacAddrCmpRaw( - &req->macaddr, + &req->binding->mac, &dhcp->chaddr[0]) == 0) { dhcp_opts_len = header.len - (ethHdrSize + iphdr->ihl * 4 + @@ -640,26 +636,19 @@ learnIPAddressThread(void *arg) * Also it is safe to unlock interface here because we stopped * capturing and applied necessary rules on the interface, while * instantiating a new filter doesn't require a locked interface.*/ - virNWFilterUnlockIface(req->ifname); + virNWFilterUnlockIface(req->binding->portdevname); if ((inetaddr = virSocketAddrFormat(&sa)) != NULL) { - virNWFilterBinding binding = { - .portdevname = req->ifname, - .linkdevname = req->linkdev, - .mac = req->macaddr, - .filter = req->filtername, - .filterparams = req->filterparams, - }; - if (virNWFilterIPAddrMapAddIPAddr(req->ifname, inetaddr) < 0) { + if (virNWFilterIPAddrMapAddIPAddr(req->binding->portdevname, inetaddr) < 0) { VIR_ERROR(_("Failed to add IP address %s to IP address " - "cache for interface %s"), inetaddr, req->ifname); + "cache for interface %s"), inetaddr, req->binding->portdevname); } ret = virNWFilterInstantiateFilterLate(req->driver, - &binding, + req->binding, req->ifindex); VIR_DEBUG("Result from applying firewall rules on " - "%s with IP addr %s : %d", req->ifname, inetaddr, ret); + "%s with IP addr %s : %d", req->binding->portdevname, inetaddr, ret); VIR_FREE(inetaddr); } } else { @@ -667,13 +656,13 @@ learnIPAddressThread(void *arg) virReportSystemError(req->status, _("encountered an error on interface %s " "index %d"), - req->ifname, req->ifindex); + req->binding->portdevname, req->ifindex); - techdriver->applyDropAllRules(req->ifname); - virNWFilterUnlockIface(req->ifname); + techdriver->applyDropAllRules(req->binding->portdevname); + virNWFilterUnlockIface(req->binding->portdevname); } - VIR_DEBUG("pcap thread terminating for interface %s", req->ifname); + VIR_DEBUG("pcap thread terminating for interface %s", req->binding->portdevname); err_no_lock: @@ -706,19 +695,14 @@ learnIPAddressThread(void *arg) */ int virNWFilterLearnIPAddress(virNWFilterTechDriverPtr techdriver, - const char *ifname, + virNWFilterBindingPtr binding, int ifindex, - const char *linkdev, - const virMacAddr *macaddr, - const char *filtername, - virHashTablePtr filterparams, virNWFilterDriverStatePtr driver, enum howDetect howDetect) { int rc; virThread thread; virNWFilterIPAddrLearnReqPtr req = NULL; - virHashTablePtr ht = NULL; if (howDetect == 0) return -1; @@ -734,37 +718,11 @@ virNWFilterLearnIPAddress(virNWFilterTechDriverPtr techdriver, if (VIR_ALLOC(req) < 0) goto err_no_req; - ht = virNWFilterHashTableCreate(0); - if (ht == NULL) + if (!(req->binding = virNWFilterBindingCopy(binding))) goto err_free_req; - if (virNWFilterHashTablePutAll(filterparams, ht) < 0) - goto err_free_ht; - - if (VIR_STRDUP(req->filtername, filtername) < 0) - goto err_free_ht; - - if (virStrcpyStatic(req->ifname, ifname) == NULL) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Destination buffer for ifname ('%s') " - "not large enough"), ifname); - goto err_free_ht; - } - - if (linkdev) { - if (virStrcpyStatic(req->linkdev, linkdev) == NULL) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Destination buffer for linkdev ('%s') " - "not large enough"), linkdev); - goto err_free_ht; - } - } - req->ifindex = ifindex; - virMacAddrSet(&req->macaddr, macaddr); req->driver = driver; - req->filterparams = ht; - ht = NULL; req->howDetect = howDetect; req->techdriver = techdriver; @@ -783,8 +741,6 @@ virNWFilterLearnIPAddress(virNWFilterTechDriverPtr techdriver, err_dereg_req: virNWFilterDeregisterLearnReq(ifindex); - err_free_ht: - virHashFree(ht); err_free_req: virNWFilterIPAddrLearnReqFree(req); err_no_req: diff --git a/src/nwfilter/nwfilter_learnipaddr.h b/src/nwfilter/nwfilter_learnipaddr.h index 06fea5bff8..2646019ade 100644 --- a/src/nwfilter/nwfilter_learnipaddr.h +++ b/src/nwfilter/nwfilter_learnipaddr.h @@ -36,12 +36,8 @@ enum howDetect { }; int virNWFilterLearnIPAddress(virNWFilterTechDriverPtr techdriver, - const char *ifname, + virNWFilterBindingPtr binding, int ifindex, - const char *linkdev, - const virMacAddr *macaddr, - const char *filtername, - virHashTablePtr filterparams, virNWFilterDriverStatePtr driver, enum howDetect howDetect); -- 2.14.3

Use the virNWFilterBinding struct in the DHCP address snooping code directly. Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/nwfilter/nwfilter_dhcpsnoop.c | 150 +++++++++++++-------------------- src/nwfilter/nwfilter_dhcpsnoop.h | 7 +- src/nwfilter/nwfilter_gentech_driver.c | 7 +- 3 files changed, 61 insertions(+), 103 deletions(-) diff --git a/src/nwfilter/nwfilter_dhcpsnoop.c b/src/nwfilter/nwfilter_dhcpsnoop.c index dc4e3cb834..e67cea40ab 100644 --- a/src/nwfilter/nwfilter_dhcpsnoop.c +++ b/src/nwfilter/nwfilter_dhcpsnoop.c @@ -135,13 +135,9 @@ struct _virNWFilterSnoopReq { int refctr; virNWFilterTechDriverPtr techdriver; - char *ifname; + virNWFilterBindingPtr binding; int ifindex; - char *linkdev; char ifkey[VIR_IFKEY_LEN]; - virMacAddr macaddr; - char *filtername; - virHashTablePtr vars; virNWFilterDriverStatePtr driver; /* start and end of lease list, ordered by lease time */ virNWFilterSnoopIPLeasePtr start; @@ -473,10 +469,10 @@ virNWFilterSnoopIPLeaseInstallRule(virNWFilterSnoopIPLeasePtr ipl, req = ipl->snoopReq; - /* protect req->ifname */ + /* protect req->binding->portdevname */ virNWFilterSnoopReqLock(req); - if (virNWFilterIPAddrMapAddIPAddr(req->ifname, ipaddr) < 0) + if (virNWFilterIPAddrMapAddIPAddr(req->binding->portdevname, ipaddr) < 0) goto exit_snooprequnlock; if (!instantiate) { @@ -486,16 +482,9 @@ virNWFilterSnoopIPLeaseInstallRule(virNWFilterSnoopIPLeasePtr ipl, /* instantiate the filters */ - if (req->ifname) { - virNWFilterBinding binding = { - .portdevname = req->ifname, - .linkdevname = req->linkdev, - .mac = req->macaddr, - .filter = req->filtername, - .filterparams = req->vars, - }; + if (req->binding->portdevname) { rc = virNWFilterInstantiateFilterLate(req->driver, - &binding, + req->binding, req->ifindex); } @@ -636,10 +625,7 @@ virNWFilterSnoopReqFree(virNWFilterSnoopReqPtr req) virNWFilterSnoopReqLeaseDel(req, &ipl->ipAddress, false, false); /* free all req data */ - VIR_FREE(req->ifname); - VIR_FREE(req->linkdev); - VIR_FREE(req->filtername); - virHashFree(req->vars); + virNWFilterBindingFree(req->binding); virMutexDestroy(&req->lock); virCondDestroy(&req->threadStatusCond); @@ -870,28 +856,23 @@ virNWFilterSnoopReqLeaseDel(virNWFilterSnoopReqPtr req, if (update_leasefile) virNWFilterSnoopLeaseFileSave(ipl); - ipAddrLeft = virNWFilterIPAddrMapDelIPAddr(req->ifname, ipstr); + ipAddrLeft = virNWFilterIPAddrMapDelIPAddr(req->binding->portdevname, ipstr); if (!req->threadkey || !instantiate) goto skip_instantiate; if (ipAddrLeft) { - virNWFilterBinding binding = { - .portdevname = req->ifname, - .linkdevname = req->linkdev, - .mac = req->macaddr, - .filter = req->filtername, - .filterparams = req->vars, - }; ret = virNWFilterInstantiateFilterLate(req->driver, - &binding, + req->binding, req->ifindex); } else { virNWFilterVarValuePtr dhcpsrvrs = - virHashLookup(req->vars, NWFILTER_VARNAME_DHCPSERVER); + virHashLookup(req->binding->filterparams, + NWFILTER_VARNAME_DHCPSERVER); if (req->techdriver && - req->techdriver->applyDHCPOnlyRules(req->ifname, &req->macaddr, + req->techdriver->applyDHCPOnlyRules(req->binding->portdevname, + &req->binding->mac, dhcpsrvrs, false) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("virNWFilterSnoopListDel failed")); @@ -1021,7 +1002,7 @@ virNWFilterSnoopDHCPDecode(virNWFilterSnoopReqPtr req, * inside the DHCP response */ if (!fromVM) { - if (virMacAddrCmpRaw(&req->macaddr, + if (virMacAddrCmpRaw(&req->binding->mac, (unsigned char *)&pd->d_chaddr) != 0) return -2; } @@ -1178,7 +1159,7 @@ static void virNWFilterDHCPDecodeWorker(void *jobdata, void *opaque) virReportError(VIR_ERR_INTERNAL_ERROR, _("Instantiation of rules failed on " - "interface '%s'"), req->ifname); + "interface '%s'"), req->binding->portdevname); } virAtomicIntDecAndTest(job->qCtr); VIR_FREE(job); @@ -1387,13 +1368,14 @@ virNWFilterDHCPSnoopThread(void *req0) /* whoever started us increased the reference counter for the req for us */ - /* protect req->ifname & req->threadkey */ + /* protect req->binding->portdevname & req->threadkey */ virNWFilterSnoopReqLock(req); - if (req->ifname && req->threadkey) { + if (req->binding->portdevname && req->threadkey) { for (i = 0; i < ARRAY_CARDINALITY(pcapConf); i++) { pcapConf[i].handle = - virNWFilterSnoopDHCPOpen(req->ifname, &req->macaddr, + virNWFilterSnoopDHCPOpen(req->binding->portdevname, + &req->binding->mac, pcapConf[i].filter, pcapConf[i].dir); if (!pcapConf[i].handle) { @@ -1402,7 +1384,7 @@ virNWFilterDHCPSnoopThread(void *req0) } fds[i].fd = pcap_fileno(pcapConf[i].handle); } - tmp = virNetDevGetIndex(req->ifname, &ifindex); + tmp = virNetDevGetIndex(req->binding->portdevname, &ifindex); ignore_value(VIR_STRDUP(threadkey, req->threadkey)); worker = virThreadPoolNew(1, 1, 0, virNWFilterDHCPDecodeWorker, @@ -1467,11 +1449,11 @@ virNWFilterDHCPSnoopThread(void *req0) /* error reading from socket */ tmp = -1; - /* protect req->ifname */ + /* protect req->binding->portdevname */ virNWFilterSnoopReqLock(req); - if (req->ifname) - tmp = virNetDevValidateConfig(req->ifname, NULL, ifindex); + if (req->binding->portdevname) + tmp = virNetDevValidateConfig(req->binding->portdevname, NULL, ifindex); virNWFilterSnoopReqUnlock(req); @@ -1484,16 +1466,17 @@ virNWFilterDHCPSnoopThread(void *req0) pcap_close(pcapConf[i].handle); pcapConf[i].handle = NULL; - /* protect req->ifname */ + /* protect req->binding->portdevname */ virNWFilterSnoopReqLock(req); virReportError(VIR_ERR_INTERNAL_ERROR, _("interface '%s' failing; " "reopening"), - req->ifname); - if (req->ifname) + req->binding->portdevname); + if (req->binding->portdevname) pcapConf[i].handle = - virNWFilterSnoopDHCPOpen(req->ifname, &req->macaddr, + virNWFilterSnoopDHCPOpen(req->binding->portdevname, + &req->binding->mac, pcapConf[i].filter, pcapConf[i].dir); @@ -1519,7 +1502,7 @@ virNWFilterDHCPSnoopThread(void *req0) last_displayed_queue = time(0); VIR_WARN("Worker thread for interface '%s' has a " "job queue that is too long", - req->ifname); + req->binding->portdevname); } continue; } @@ -1532,7 +1515,7 @@ virNWFilterDHCPSnoopThread(void *req0) if (time(0) - last_displayed > 10) { last_displayed = time(0); VIR_WARN("Too many DHCP packets on interface '%s'", - req->ifname); + req->binding->portdevname); } continue; } @@ -1543,7 +1526,7 @@ virNWFilterDHCPSnoopThread(void *req0) &pcapConf[i].qCtr) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Job submission failed on " - "interface '%s'"), req->ifname); + "interface '%s'"), req->binding->portdevname); error = true; break; } @@ -1554,15 +1537,15 @@ virNWFilterDHCPSnoopThread(void *req0) /* protect IfNameToKey */ virNWFilterSnoopLock(); - /* protect req->ifname & req->threadkey */ + /* protect req->binding->portdevname & req->threadkey */ virNWFilterSnoopReqLock(req); virNWFilterSnoopCancel(&req->threadkey); ignore_value(virHashRemoveEntry(virNWFilterSnoopState.ifnameToKey, - req->ifname)); + req->binding->portdevname)); - VIR_FREE(req->ifname); + VIR_FREE(req->binding->portdevname); virNWFilterSnoopReqUnlock(req); virNWFilterSnoopUnlock(); @@ -1595,12 +1578,7 @@ virNWFilterSnoopIFKeyFMT(char *ifkey, const unsigned char *vmuuid, int virNWFilterDHCPSnoopReq(virNWFilterTechDriverPtr techdriver, - const char *ifname, - const char *linkdev, - const unsigned char *vmuuid, - const virMacAddr *macaddr, - const char *filtername, - virHashTablePtr filterparams, + virNWFilterBindingPtr binding, virNWFilterDriverStatePtr driver) { virNWFilterSnoopReqPtr req; @@ -1611,7 +1589,7 @@ virNWFilterDHCPSnoopReq(virNWFilterTechDriverPtr techdriver, virNWFilterVarValuePtr dhcpsrvrs; bool threadPuts = false; - virNWFilterSnoopIFKeyFMT(ifkey, vmuuid, macaddr); + virNWFilterSnoopIFKeyFMT(ifkey, binding->owneruuid, &binding->mac); req = virNWFilterSnoopReqGetByIFKey(ifkey); isnewreq = (req == NULL); @@ -1620,9 +1598,8 @@ virNWFilterDHCPSnoopReq(virNWFilterTechDriverPtr techdriver, virNWFilterSnoopReqPut(req); return 0; } - /* a recycled req may still have filtername and vars */ - VIR_FREE(req->filtername); - virHashFree(req->vars); + virNWFilterBindingFree(req->binding); + req->binding = NULL; } else { req = virNWFilterSnoopReqNew(ifkey); if (!req) @@ -1631,17 +1608,9 @@ virNWFilterDHCPSnoopReq(virNWFilterTechDriverPtr techdriver, req->driver = driver; req->techdriver = techdriver; - tmp = virNetDevGetIndex(ifname, &req->ifindex); - virMacAddrSet(&req->macaddr, macaddr); - req->vars = virNWFilterHashTableCreate(0); - req->linkdev = NULL; - - if (VIR_STRDUP(req->ifname, ifname) < 0 || - VIR_STRDUP(req->filtername, filtername) < 0 || - VIR_STRDUP(req->linkdev, linkdev) < 0) + if ((tmp = virNetDevGetIndex(binding->portdevname, &req->ifindex)) < 0) goto exit_snoopreqput; - - if (!req->vars || tmp < 0) + if (!(req->binding = virNWFilterBindingCopy(binding))) goto exit_snoopreqput; /* check that all tools are available for applying the filters (late) */ @@ -1653,10 +1622,11 @@ virNWFilterDHCPSnoopReq(virNWFilterTechDriverPtr techdriver, goto exit_snoopreqput; } - dhcpsrvrs = virHashLookup(filterparams, + dhcpsrvrs = virHashLookup(binding->filterparams, NWFILTER_VARNAME_DHCPSERVER); - if (techdriver->applyDHCPOnlyRules(req->ifname, &req->macaddr, + if (techdriver->applyDHCPOnlyRules(req->binding->portdevname, + &req->binding->mac, dhcpsrvrs, false) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("applyDHCPOnlyRules " @@ -1664,20 +1634,14 @@ virNWFilterDHCPSnoopReq(virNWFilterTechDriverPtr techdriver, goto exit_snoopreqput; } - if (virNWFilterHashTablePutAll(filterparams, req->vars) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("virNWFilterDHCPSnoopReq: can't copy variables" - " on if %s"), ifkey); - goto exit_snoopreqput; - } - virNWFilterSnoopLock(); - if (virHashAddEntry(virNWFilterSnoopState.ifnameToKey, ifname, + if (virHashAddEntry(virNWFilterSnoopState.ifnameToKey, + req->binding->portdevname, req->ifkey) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("virNWFilterDHCPSnoopReq ifname map failed" - " on interface \"%s\" key \"%s\""), ifname, + " on interface \"%s\" key \"%s\""), binding->portdevname, ifkey); goto exit_snoopunlock; } @@ -1686,7 +1650,7 @@ virNWFilterDHCPSnoopReq(virNWFilterTechDriverPtr techdriver, virHashAddEntry(virNWFilterSnoopState.snoopReqs, ifkey, req) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("virNWFilterDHCPSnoopReq req add failed on" - " interface \"%s\" ifkey \"%s\""), ifname, + " interface \"%s\" ifkey \"%s\""), binding->portdevname, ifkey); goto exit_rem_ifnametokey; } @@ -1698,7 +1662,7 @@ virNWFilterDHCPSnoopReq(virNWFilterTechDriverPtr techdriver, req) != 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("virNWFilterDHCPSnoopReq virThreadCreate " - "failed on interface '%s'"), ifname); + "failed on interface '%s'"), binding->portdevname); goto exit_snoopreq_unlock; } @@ -1710,14 +1674,14 @@ virNWFilterDHCPSnoopReq(virNWFilterTechDriverPtr techdriver, if (!req->threadkey) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Activation of snoop request failed on " - "interface '%s'"), req->ifname); + "interface '%s'"), req->binding->portdevname); goto exit_snoopreq_unlock; } if (virNWFilterSnoopReqRestore(req) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Restoring of leases failed on " - "interface '%s'"), req->ifname); + "interface '%s'"), req->binding->portdevname); goto exit_snoop_cancel; } @@ -1746,7 +1710,7 @@ virNWFilterDHCPSnoopReq(virNWFilterTechDriverPtr techdriver, exit_snoopreq_unlock: virNWFilterSnoopReqUnlock(req); exit_rem_ifnametokey: - virHashRemoveEntry(virNWFilterSnoopState.ifnameToKey, ifname); + virHashRemoveEntry(virNWFilterSnoopState.ifnameToKey, binding->portdevname); exit_snoopunlock: virNWFilterSnoopUnlock(); exit_snoopreqput: @@ -2054,21 +2018,21 @@ virNWFilterSnoopRemAllReqIter(const void *payload, { virNWFilterSnoopReqPtr req = (virNWFilterSnoopReqPtr)payload; - /* protect req->ifname */ + /* protect req->binding->portdevname */ virNWFilterSnoopReqLock(req); - if (req->ifname) { + if (req->binding->portdevname) { ignore_value(virHashRemoveEntry(virNWFilterSnoopState.ifnameToKey, - req->ifname)); + req->binding->portdevname)); /* * Remove all IP addresses known to be associated with this * interface so that a new thread will be started on this * interface */ - virNWFilterIPAddrMapDelIPAddr(req->ifname, NULL); + virNWFilterIPAddrMapDelIPAddr(req->binding->portdevname, NULL); - VIR_FREE(req->ifname); + VIR_FREE(req->binding->portdevname); } virNWFilterSnoopReqUnlock(req); @@ -2171,13 +2135,13 @@ virNWFilterDHCPSnoopEnd(const char *ifname) goto cleanup; } - /* protect req->ifname & req->threadkey */ + /* protect req->binding->portdevname & req->threadkey */ virNWFilterSnoopReqLock(req); /* keep valid lease req; drop interface association */ virNWFilterSnoopCancel(&req->threadkey); - VIR_FREE(req->ifname); + VIR_FREE(req->binding->portdevname); virNWFilterSnoopReqUnlock(req); diff --git a/src/nwfilter/nwfilter_dhcpsnoop.h b/src/nwfilter/nwfilter_dhcpsnoop.h index a5925de40a..0c047fd5a1 100644 --- a/src/nwfilter/nwfilter_dhcpsnoop.h +++ b/src/nwfilter/nwfilter_dhcpsnoop.h @@ -30,12 +30,7 @@ int virNWFilterDHCPSnoopInit(void); void virNWFilterDHCPSnoopShutdown(void); int virNWFilterDHCPSnoopReq(virNWFilterTechDriverPtr techdriver, - const char *ifname, - const char *linkdev, - const unsigned char *vmuuid, - const virMacAddr *macaddr, - const char *filtername, - virHashTablePtr filterparams, + virNWFilterBindingPtr binding, virNWFilterDriverStatePtr driver); void virNWFilterDHCPSnoopEnd(const char *ifname); #endif /* __NWFILTER_DHCPSNOOP_H */ diff --git a/src/nwfilter/nwfilter_gentech_driver.c b/src/nwfilter/nwfilter_gentech_driver.c index 514315f781..0dc51d16c5 100644 --- a/src/nwfilter/nwfilter_gentech_driver.c +++ b/src/nwfilter/nwfilter_gentech_driver.c @@ -645,10 +645,9 @@ virNWFilterDoInstantiate(virNWFilterTechDriverPtr techdriver, goto err_unresolvable_vars; } if (STRCASEEQ(learning, "dhcp")) { - rc = virNWFilterDHCPSnoopReq(techdriver, binding->portdevname, - binding->linkdevname, - binding->owneruuid, &binding->mac, - filter->name, binding->filterparams, driver); + rc = virNWFilterDHCPSnoopReq(techdriver, + binding, + driver); goto err_exit; } else if (STRCASEEQ(learning, "any")) { if (!virNWFilterHasLearnReq(ifindex)) { -- 2.14.3

If a <interface> includes a filter name but the nwfilter driver is not present we silently do nothing. This is very bad, because an application that thinks it is protected by malicious guest traffic will in fact be vulnerable. Reporting an error gives the administrator the ability to know there is a problem and fix it. Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/conf/domain_nwfilter.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/conf/domain_nwfilter.c b/src/conf/domain_nwfilter.c index e360aceeba..7570e0ae83 100644 --- a/src/conf/domain_nwfilter.c +++ b/src/conf/domain_nwfilter.c @@ -28,6 +28,9 @@ #include "datatypes.h" #include "domain_conf.h" #include "domain_nwfilter.h" +#include "virerror.h" + +#define VIR_FROM_THIS VIR_FROM_NWFILTER static virDomainConfNWFilterDriverPtr nwfilterDriver; @@ -44,8 +47,10 @@ virDomainConfNWFilterInstantiate(const char *vmname, { if (nwfilterDriver != NULL) return nwfilterDriver->instantiateFilter(vmname, vmuuid, net); - /* driver module not available -- don't indicate failure */ - return 0; + + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("No network filter driver available")); + return -1; } void -- 2.14.3

Currently the nwfilter driver does not keep any record of what filter bindings it has active. This means that when it needs to recreate filters, it has to rely on triggering callbacks provided by the virt drivers. This introduces a hash table recording the virNWFilterBinding objects so the driver has a record of all active filters. Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/conf/virnwfilterobj.h | 3 +++ src/nwfilter/nwfilter_driver.c | 57 +++++++++++++++++++++++++++++++++--------- 2 files changed, 48 insertions(+), 12 deletions(-) diff --git a/src/conf/virnwfilterobj.h b/src/conf/virnwfilterobj.h index 433b0402d0..5e69313476 100644 --- a/src/conf/virnwfilterobj.h +++ b/src/conf/virnwfilterobj.h @@ -37,6 +37,9 @@ struct _virNWFilterDriverState { virNWFilterObjListPtr nwfilters; + /* ifname -> virNWFilterBindingPtr */ + virHashTablePtr bindings; + char *configDir; }; diff --git a/src/nwfilter/nwfilter_driver.c b/src/nwfilter/nwfilter_driver.c index a375e9bda8..ccbcfbbf67 100644 --- a/src/nwfilter/nwfilter_driver.c +++ b/src/nwfilter/nwfilter_driver.c @@ -163,6 +163,13 @@ nwfilterDriverInstallDBusMatches(DBusConnection *sysbus ATTRIBUTE_UNUSED) #endif /* HAVE_FIREWALLD */ +static void virNWFilterBindingDataFree(void *payload, const void *name ATTRIBUTE_UNUSED) +{ + virNWFilterBindingPtr binding = payload; + + virNWFilterBindingFree(binding); +} + /** * nwfilterStateInitialize: * @@ -190,6 +197,10 @@ nwfilterStateInitialize(bool privileged, if (!(driver->nwfilters = virNWFilterObjListNew())) goto error; + if (!(driver->bindings = virHashCreate(0, + virNWFilterBindingDataFree))) + goto error; + if (!privileged) return 0; @@ -335,6 +346,8 @@ nwfilterStateCleanup(void) nwfilterDriverUnlock(); } + virHashFree(driver->bindings); + /* free inactive nwfilters */ virNWFilterObjListFree(driver->nwfilters); @@ -649,10 +662,28 @@ nwfilterInstantiateFilter(const char *vmname, virNWFilterBindingPtr binding; int ret; - if (!(binding = virNWFilterBindingForNet(vmname, vmuuid, net))) + nwfilterDriverLock(); + binding = virHashLookup(driver->bindings, net->ifname); + if (binding) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Filter already present for NIC %s"), net->ifname); + nwfilterDriverUnlock(); + return -1; + } + if (!(binding = virNWFilterBindingForNet(vmname, vmuuid, net))) { + nwfilterDriverUnlock(); return -1; + } + virHashAddEntry(driver->bindings, net->ifname, binding); + nwfilterDriverUnlock(); + ret = virNWFilterInstantiateFilter(driver, binding); - virNWFilterBindingFree(binding); + + if (ret < 0) { + nwfilterDriverLock(); + virHashRemoveEntry(driver->bindings, net->ifname); + nwfilterDriverUnlock(); + } return ret; } @@ -660,16 +691,18 @@ nwfilterInstantiateFilter(const char *vmname, static void nwfilterTeardownFilter(virDomainNetDefPtr net) { - virNWFilterBinding binding = { - .portdevname = net->ifname, - .linkdevname = (net->type == VIR_DOMAIN_NET_TYPE_DIRECT ? - net->data.direct.linkdev : NULL), - .mac = net->mac, - .filter = net->filter, - .filterparams = net->filterparams, - }; - if ((net->ifname) && (net->filter)) - virNWFilterTeardownFilter(&binding); + virNWFilterBindingPtr binding; + if (!net->ifname) + return; + + nwfilterDriverLock(); + binding = virHashSteal(driver->bindings, net->ifname); + nwfilterDriverUnlock(); + if (!binding) + return; + + virNWFilterTeardownFilter(binding); + virNWFilterBindingFree(binding); } -- 2.14.3

Now that the nwfilter driver keeps a list of bindings that it has created, there is no need for the complex virt driver callbacks. It is possible to simply iterate of the list of recorded filter bindings. This means that rebuilding filters no longer has to acquire any locks on the virDomainObj objects, as they're never touched. Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> --- src/conf/nwfilter_conf.c | 169 ++++++++++----------------------- src/conf/nwfilter_conf.h | 51 +--------- src/conf/virnwfilterobj.c | 4 +- src/libvirt_private.syms | 3 +- src/lxc/lxc_driver.c | 28 ------ src/nwfilter/nwfilter_driver.c | 22 +++-- src/nwfilter/nwfilter_gentech_driver.c | 169 ++++++++++++++++++++------------- src/nwfilter/nwfilter_gentech_driver.h | 4 +- src/qemu/qemu_driver.c | 25 ----- src/uml/uml_driver.c | 29 ------ 10 files changed, 175 insertions(+), 329 deletions(-) diff --git a/src/conf/nwfilter_conf.c b/src/conf/nwfilter_conf.c index 3d2ae9d0f3..83c9ff920f 100644 --- a/src/conf/nwfilter_conf.c +++ b/src/conf/nwfilter_conf.c @@ -2819,121 +2819,6 @@ virNWFilterSaveConfig(const char *configDir, } -int nCallbackDriver; -#define MAX_CALLBACK_DRIVER 10 -static virNWFilterCallbackDriverPtr callbackDrvArray[MAX_CALLBACK_DRIVER]; - -void -virNWFilterRegisterCallbackDriver(virNWFilterCallbackDriverPtr cbd) -{ - if (nCallbackDriver < MAX_CALLBACK_DRIVER) - callbackDrvArray[nCallbackDriver++] = cbd; -} - - -void -virNWFilterUnRegisterCallbackDriver(virNWFilterCallbackDriverPtr cbd) -{ - size_t i = 0; - - while (i < nCallbackDriver && callbackDrvArray[i] != cbd) - i++; - - if (i < nCallbackDriver) { - memmove(&callbackDrvArray[i], &callbackDrvArray[i+1], - (nCallbackDriver - i - 1) * sizeof(callbackDrvArray[i])); - callbackDrvArray[i] = 0; - nCallbackDriver--; - } -} - - -void -virNWFilterCallbackDriversLock(void) -{ - size_t i; - - for (i = 0; i < nCallbackDriver; i++) - callbackDrvArray[i]->vmDriverLock(); -} - - -void -virNWFilterCallbackDriversUnlock(void) -{ - size_t i; - - for (i = 0; i < nCallbackDriver; i++) - callbackDrvArray[i]->vmDriverUnlock(); -} - - -static virDomainObjListIterator virNWFilterDomainFWUpdateCB; -static void *virNWFilterDomainFWUpdateOpaque; - -/** - * virNWFilterInstFiltersOnAllVMs: - * Apply all filters on all running VMs. Don't terminate in case of an - * error. This should be called upon reloading of the driver. - */ -int -virNWFilterInstFiltersOnAllVMs(void) -{ - size_t i; - struct domUpdateCBStruct cb = { - .opaque = virNWFilterDomainFWUpdateOpaque, - .step = STEP_APPLY_CURRENT, - .skipInterfaces = NULL, /* not needed */ - }; - - for (i = 0; i < nCallbackDriver; i++) - callbackDrvArray[i]->vmFilterRebuild(virNWFilterDomainFWUpdateCB, - &cb); - - return 0; -} - - -int -virNWFilterTriggerVMFilterRebuild(void) -{ - size_t i; - int ret = 0; - struct domUpdateCBStruct cb = { - .opaque = virNWFilterDomainFWUpdateOpaque, - .step = STEP_APPLY_NEW, - .skipInterfaces = virHashCreate(0, NULL), - }; - - if (!cb.skipInterfaces) - return -1; - - for (i = 0; i < nCallbackDriver; i++) { - if (callbackDrvArray[i]->vmFilterRebuild(virNWFilterDomainFWUpdateCB, - &cb) < 0) - ret = -1; - } - - if (ret < 0) { - cb.step = STEP_TEAR_NEW; /* rollback */ - - for (i = 0; i < nCallbackDriver; i++) - callbackDrvArray[i]->vmFilterRebuild(virNWFilterDomainFWUpdateCB, - &cb); - } else { - cb.step = STEP_TEAR_OLD; /* switch over */ - - for (i = 0; i < nCallbackDriver; i++) - callbackDrvArray[i]->vmFilterRebuild(virNWFilterDomainFWUpdateCB, - &cb); - } - - virHashFree(cb.skipInterfaces); - - return ret; -} - - int virNWFilterDeleteDef(const char *configDir, virNWFilterDefPtr def) @@ -3204,16 +3089,18 @@ virNWFilterDefFormat(const virNWFilterDef *def) return NULL; } +static virNWFilterTriggerRebuildCallback rebuildCallback; +static void *rebuildOpaque; int -virNWFilterConfLayerInit(virDomainObjListIterator domUpdateCB, +virNWFilterConfLayerInit(virNWFilterTriggerRebuildCallback cb, void *opaque) { if (initialized) return -1; - virNWFilterDomainFWUpdateCB = domUpdateCB; - virNWFilterDomainFWUpdateOpaque = opaque; + rebuildCallback = cb; + rebuildOpaque = opaque; initialized = true; @@ -3233,8 +3120,50 @@ virNWFilterConfLayerShutdown(void) virRWLockDestroy(&updateLock); initialized = false; - virNWFilterDomainFWUpdateOpaque = NULL; - virNWFilterDomainFWUpdateCB = NULL; + rebuildCallback = NULL; + rebuildOpaque = NULL; +} + +int +virNWFilterTriggerRebuild(void) +{ +#if 0 + size_t i; + int ret = 0; + struct domUpdateCBStruct cb = { + .opaque = virNWFilterDomainFWUpdateOpaque, + .step = STEP_APPLY_NEW, + .skipInterfaces = virHashCreate(0, NULL), + }; + + if (!cb.skipInterfaces) + return -1; + + for (i = 0; i < nCallbackDriver; i++) { + if (callbackDrvArray[i]->vmFilterRebuild(virNWFilterDomainFWUpdateCB, + &cb) < 0) + ret = -1; + } + + if (ret < 0) { + cb.step = STEP_TEAR_NEW; /* rollback */ + + for (i = 0; i < nCallbackDriver; i++) + callbackDrvArray[i]->vmFilterRebuild(virNWFilterDomainFWUpdateCB, + &cb); + } else { + cb.step = STEP_TEAR_OLD; /* switch over */ + + for (i = 0; i < nCallbackDriver; i++) + callbackDrvArray[i]->vmFilterRebuild(virNWFilterDomainFWUpdateCB, + &cb); + } + + virHashFree(cb.skipInterfaces); + + return ret; +#endif + return rebuildCallback(rebuildOpaque); } diff --git a/src/conf/nwfilter_conf.h b/src/conf/nwfilter_conf.h index 8c5421ee62..3b36a02a78 100644 --- a/src/conf/nwfilter_conf.h +++ b/src/conf/nwfilter_conf.h @@ -559,20 +559,6 @@ struct virNWFilterBinding { }; -typedef enum { - STEP_APPLY_NEW, - STEP_TEAR_NEW, - STEP_TEAR_OLD, - STEP_APPLY_CURRENT, -} UpdateStep; - -struct domUpdateCBStruct { - void *opaque; - UpdateStep step; - virHashTablePtr skipInterfaces; -}; - - void virNWFilterRuleDefFree(virNWFilterRuleDefPtr def); @@ -580,7 +566,7 @@ void virNWFilterDefFree(virNWFilterDefPtr def); int -virNWFilterTriggerVMFilterRebuild(void); +virNWFilterTriggerRebuild(void); int virNWFilterDeleteDef(const char *configDir, @@ -612,44 +598,15 @@ virNWFilterReadLockFilterUpdates(void); void virNWFilterUnlockFilterUpdates(void); +typedef int (*virNWFilterTriggerRebuildCallback)(void *opaque); + int -virNWFilterConfLayerInit(virDomainObjListIterator domUpdateCB, +virNWFilterConfLayerInit(virNWFilterTriggerRebuildCallback cb, void *opaque); void virNWFilterConfLayerShutdown(void); -int -virNWFilterInstFiltersOnAllVMs(void); - -typedef int -(*virNWFilterRebuild)(virDomainObjListIterator domUpdateCB, - void *data); - -typedef void -(*virNWFilterVoidCall)(void); - -typedef struct _virNWFilterCallbackDriver virNWFilterCallbackDriver; -typedef virNWFilterCallbackDriver *virNWFilterCallbackDriverPtr; -struct _virNWFilterCallbackDriver { - const char *name; - - virNWFilterRebuild vmFilterRebuild; - virNWFilterVoidCall vmDriverLock; - virNWFilterVoidCall vmDriverUnlock; -}; - -void -virNWFilterRegisterCallbackDriver(virNWFilterCallbackDriverPtr); - -void -virNWFilterUnRegisterCallbackDriver(virNWFilterCallbackDriverPtr); - -void -virNWFilterCallbackDriversLock(void); - -void -virNWFilterCallbackDriversUnlock(void); char * virNWFilterPrintTCPFlags(uint8_t flags); diff --git a/src/conf/virnwfilterobj.c b/src/conf/virnwfilterobj.c index 87d7e72703..0136a0d56c 100644 --- a/src/conf/virnwfilterobj.c +++ b/src/conf/virnwfilterobj.c @@ -276,7 +276,7 @@ virNWFilterObjTestUnassignDef(virNWFilterObjPtr obj) obj->wantRemoved = true; /* trigger the update on VMs referencing the filter */ - if (virNWFilterTriggerVMFilterRebuild() < 0) + if (virNWFilterTriggerRebuild() < 0) rc = -1; obj->wantRemoved = false; @@ -358,7 +358,7 @@ virNWFilterObjListAssignDef(virNWFilterObjListPtr nwfilters, obj->newDef = def; /* trigger the update on VMs referencing the filter */ - if (virNWFilterTriggerVMFilterRebuild() < 0) { + if (virNWFilterTriggerRebuild() < 0) { obj->newDef = NULL; virNWFilterObjUnlock(obj); return NULL; diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 9fc0aa470d..fd5edc86ad 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -792,7 +792,6 @@ virNWFilterDefFree; virNWFilterDefParseFile; virNWFilterDefParseString; virNWFilterDeleteDef; -virNWFilterInstFiltersOnAllVMs; virNWFilterJumpTargetTypeToString; virNWFilterPrintStateMatchFlags; virNWFilterPrintTCPFlags; @@ -805,7 +804,7 @@ virNWFilterRuleIsProtocolIPv4; virNWFilterRuleIsProtocolIPv6; virNWFilterRuleProtocolTypeToString; virNWFilterSaveConfig; -virNWFilterTriggerVMFilterRebuild; +virNWFilterTriggerRebuild; virNWFilterUnlockFilterUpdates; virNWFilterUnRegisterCallbackDriver; virNWFilterWriteLockFilterUpdates; diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index ca01d369d5..a6b689aef0 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -66,7 +66,6 @@ #include "virfdstream.h" #include "domain_audit.h" #include "domain_nwfilter.h" -#include "nwfilter_conf.h" #include "virinitctl.h" #include "virnetdev.h" #include "virnetdevtap.h" @@ -95,31 +94,6 @@ static int lxcStateInitialize(bool privileged, static int lxcStateCleanup(void); virLXCDriverPtr lxc_driver = NULL; -/* callbacks for nwfilter */ -static int -lxcVMFilterRebuild(virDomainObjListIterator iter, void *data) -{ - return virDomainObjListForEach(lxc_driver->domains, iter, data); -} - -static void -lxcVMDriverLock(void) -{ - lxcDriverLock(lxc_driver); -} - -static void -lxcVMDriverUnlock(void) -{ - lxcDriverUnlock(lxc_driver); -} - -static virNWFilterCallbackDriver lxcCallbackDriver = { - .name = "LXC", - .vmFilterRebuild = lxcVMFilterRebuild, - .vmDriverLock = lxcVMDriverLock, - .vmDriverUnlock = lxcVMDriverUnlock, -}; /** * lxcDomObjFromDomain: @@ -1691,7 +1665,6 @@ static int lxcStateInitialize(bool privileged, NULL, NULL) < 0) goto cleanup; - virNWFilterRegisterCallbackDriver(&lxcCallbackDriver); virObjectUnref(caps); return 0; @@ -1764,7 +1737,6 @@ static int lxcStateCleanup(void) if (lxc_driver == NULL) return -1; - virNWFilterUnRegisterCallbackDriver(&lxcCallbackDriver); virObjectUnref(lxc_driver->domains); virObjectUnref(lxc_driver->domainEventState); diff --git a/src/nwfilter/nwfilter_driver.c b/src/nwfilter/nwfilter_driver.c index ccbcfbbf67..92389840fd 100644 --- a/src/nwfilter/nwfilter_driver.c +++ b/src/nwfilter/nwfilter_driver.c @@ -170,6 +170,15 @@ static void virNWFilterBindingDataFree(void *payload, const void *name ATTRIBUTE virNWFilterBindingFree(binding); } + +static int virNWFilterTriggerRebuildImpl(void *opaque) +{ + virNWFilterDriverStatePtr nwdriver = opaque; + + return virNWFilterBuildAll(nwdriver, true); +} + + /** * nwfilterStateInitialize: * @@ -216,7 +225,7 @@ nwfilterStateInitialize(bool privileged, if (virNWFilterTechDriversInit(privileged) < 0) goto err_dhcpsnoop_shutdown; - if (virNWFilterConfLayerInit(virNWFilterDomainFWUpdateCB, + if (virNWFilterConfLayerInit(virNWFilterTriggerRebuildImpl, driver) < 0) goto err_techdrivers_shutdown; @@ -306,15 +315,14 @@ nwfilterStateReload(void) nwfilterDriverLock(); virNWFilterWriteLockFilterUpdates(); - virNWFilterCallbackDriversLock(); virNWFilterObjListLoadAllConfigs(driver->nwfilters, driver->configDir); - virNWFilterCallbackDriversUnlock(); virNWFilterUnlockFilterUpdates(); - nwfilterDriverUnlock(); - virNWFilterInstFiltersOnAllVMs(); + virNWFilterBuildAll(driver, false); + + nwfilterDriverUnlock(); return 0; } @@ -550,7 +558,6 @@ nwfilterDefineXML(virConnectPtr conn, nwfilterDriverLock(); virNWFilterWriteLockFilterUpdates(); - virNWFilterCallbackDriversLock(); if (!(def = virNWFilterDefParseString(xml))) goto cleanup; @@ -575,7 +582,6 @@ nwfilterDefineXML(virConnectPtr conn, if (obj) virNWFilterObjUnlock(obj); - virNWFilterCallbackDriversUnlock(); virNWFilterUnlockFilterUpdates(); nwfilterDriverUnlock(); return nwfilter; @@ -591,7 +597,6 @@ nwfilterUndefine(virNWFilterPtr nwfilter) nwfilterDriverLock(); virNWFilterWriteLockFilterUpdates(); - virNWFilterCallbackDriversLock(); if (!(obj = nwfilterObjFromNWFilter(nwfilter->uuid))) goto cleanup; @@ -618,7 +623,6 @@ nwfilterUndefine(virNWFilterPtr nwfilter) if (obj) virNWFilterObjUnlock(obj); - virNWFilterCallbackDriversUnlock(); virNWFilterUnlockFilterUpdates(); nwfilterDriverUnlock(); return ret; diff --git a/src/nwfilter/nwfilter_gentech_driver.c b/src/nwfilter/nwfilter_gentech_driver.c index 0dc51d16c5..5c83b06504 100644 --- a/src/nwfilter/nwfilter_gentech_driver.c +++ b/src/nwfilter/nwfilter_gentech_driver.c @@ -153,9 +153,9 @@ virNWFilterVarHashmapAddStdValues(virHashTablePtr table, if (!val) return -1; - if (virHashAddEntry(table, - NWFILTER_STD_VAR_MAC, - val) < 0) { + if (virHashUpdateEntry(table, + NWFILTER_STD_VAR_MAC, + val) < 0) { virNWFilterVarValueFree(val); virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not add variable 'MAC' to hashmap")); @@ -168,9 +168,9 @@ virNWFilterVarHashmapAddStdValues(virHashTablePtr table, if (!val) return -1; - if (virHashAddEntry(table, - NWFILTER_STD_VAR_IP, - val) < 0) { + if (virHashUpdateEntry(table, + NWFILTER_STD_VAR_IP, + val) < 0) { virNWFilterVarValueFree(val); virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not add variable 'IP' to hashmap")); @@ -1000,72 +1000,111 @@ virNWFilterTeardownFilter(virNWFilterBindingPtr binding) return ret; } +enum { + STEP_APPLY_NEW, + STEP_TEAR_NEW, + STEP_TEAR_OLD, + STEP_APPLY_CURRENT, +}; -int -virNWFilterDomainFWUpdateCB(virDomainObjPtr obj, - void *data) +static int +virNWFilterBuildOne(virNWFilterDriverStatePtr driver, + virNWFilterBindingPtr binding, + virHashTablePtr skipInterfaces, + int step) { - virDomainDefPtr vm = obj->def; - struct domUpdateCBStruct *cb = data; - size_t i; bool skipIface; int ret = 0; - - virObjectLock(obj); - - if (virDomainObjIsActive(obj)) { - for (i = 0; i < vm->nnets; i++) { - virDomainNetDefPtr net = vm->nets[i]; - virNWFilterBinding binding = { - .ownername = vm->name, - .portdevname = net->ifname, - .linkdevname = (net->type == VIR_DOMAIN_NET_TYPE_DIRECT ? - net->data.direct.linkdev : NULL), - .mac = net->mac, - .filter = net->filter, - .filterparams = net->filterparams, - }; - memcpy(binding.owneruuid, vm->uuid, sizeof(binding.owneruuid)); - if ((net->filter) && (net->ifname)) { - switch (cb->step) { - case STEP_APPLY_NEW: - ret = virNWFilterUpdateInstantiateFilter(cb->opaque, - &binding, - &skipIface); - if (ret == 0 && skipIface) { - /* filter tree unchanged -- no update needed */ - ret = virHashAddEntry(cb->skipInterfaces, - net->ifname, - (void *)~0); - } - break; - - case STEP_TEAR_NEW: - if (!virHashLookup(cb->skipInterfaces, net->ifname)) - ret = virNWFilterRollbackUpdateFilter(&binding); - break; - - case STEP_TEAR_OLD: - if (!virHashLookup(cb->skipInterfaces, net->ifname)) - ret = virNWFilterTearOldFilter(&binding); - break; - - case STEP_APPLY_CURRENT: - ret = virNWFilterInstantiateFilter(cb->opaque, - &binding); - if (ret) - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Failure while applying current filter on " - "VM %s"), vm->name); - break; - } - if (ret) - break; - } + VIR_DEBUG("Building filter for portdev=%s step=%d", binding->portdevname, step); + + switch (step) { + case STEP_APPLY_NEW: + ret = virNWFilterUpdateInstantiateFilter(driver, + binding, + &skipIface); + if (ret == 0 && skipIface) { + /* filter tree unchanged -- no update needed */ + ret = virHashAddEntry(skipInterfaces, + binding->portdevname, + (void *)~0); } + break; + + case STEP_TEAR_NEW: + if (!virHashLookup(skipInterfaces, binding->portdevname)) + ret = virNWFilterRollbackUpdateFilter(binding); + break; + + case STEP_TEAR_OLD: + if (!virHashLookup(skipInterfaces, binding->portdevname)) + ret = virNWFilterTearOldFilter(binding); + break; + + case STEP_APPLY_CURRENT: + ret = virNWFilterInstantiateFilter(driver, + binding); + break; } - virObjectUnlock(obj); + return ret; +} + + +struct virNWFilterBuildData { + virNWFilterDriverStatePtr driver; + virHashTablePtr skipInterfaces; + int step; +}; + +static int +virNWFilterBuildIter(void *payload, const void *name ATTRIBUTE_UNUSED, void *opaque) +{ + virNWFilterBindingPtr binding = payload; + struct virNWFilterBuildData *data = opaque; + + return virNWFilterBuildOne(data->driver, binding, + data->skipInterfaces, data->step); +} + +int +virNWFilterBuildAll(virNWFilterDriverStatePtr driver, + bool newFilters) +{ + struct virNWFilterBuildData data = { + .driver = driver, + }; + int ret = 0; + + VIR_DEBUG("Build all filters newFilters=%d", newFilters); + + if (newFilters) { + if (!(data.skipInterfaces = virHashCreate(0, NULL))) + return -1; + + data.step = STEP_APPLY_NEW; + if (virHashForEach(driver->bindings, + virNWFilterBuildIter, + &data) < 0) + ret = -1; + + if (ret == -1) { + data.step = STEP_TEAR_NEW; + virHashForEach(driver->bindings, + virNWFilterBuildIter, + &data); + } else { + data.step = STEP_TEAR_OLD; + virHashForEach(driver->bindings, + virNWFilterBuildIter, + &data); + } + } else { + data.step = STEP_APPLY_CURRENT; + if (virHashForEach(driver->bindings, + virNWFilterBuildIter, + &data) < 0) + ret = -1; + } return ret; } diff --git a/src/nwfilter/nwfilter_gentech_driver.h b/src/nwfilter/nwfilter_gentech_driver.h index 0d846dc92f..8bfc323808 100644 --- a/src/nwfilter/nwfilter_gentech_driver.h +++ b/src/nwfilter/nwfilter_gentech_driver.h @@ -52,8 +52,8 @@ int virNWFilterTeardownFilter(virNWFilterBindingPtr binding); virHashTablePtr virNWFilterCreateVarHashmap(const char *macaddr, const virNWFilterVarValue *value); -int virNWFilterDomainFWUpdateCB(virDomainObjPtr vm, - void *data); +int virNWFilterBuildAll(virNWFilterDriverStatePtr driver, + bool newFilters); virNWFilterBindingPtr virNWFilterBindingForNet(const char *vmname, const unsigned char *vmuuid, diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 7484b00e23..668891a119 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -84,7 +84,6 @@ #include "cpu/cpu.h" #include "virsysinfo.h" #include "domain_nwfilter.h" -#include "nwfilter_conf.h" #include "virhook.h" #include "virstoragefile.h" #include "virfile.h" @@ -164,28 +163,6 @@ static int qemuARPGetInterfaces(virDomainObjPtr vm, static virQEMUDriverPtr qemu_driver; - -static void -qemuVMDriverLock(void) -{} -static void -qemuVMDriverUnlock(void) -{} - -static int -qemuVMFilterRebuild(virDomainObjListIterator iter, void *data) -{ - return virDomainObjListForEach(qemu_driver->domains, iter, data); -} - -static virNWFilterCallbackDriver qemuCallbackDriver = { - .name = QEMU_DRIVER_NAME, - .vmFilterRebuild = qemuVMFilterRebuild, - .vmDriverLock = qemuVMDriverLock, - .vmDriverUnlock = qemuVMDriverUnlock, -}; - - /** * qemuDomObjFromDomain: * @domain: Domain pointer that has to be looked up @@ -938,7 +915,6 @@ qemuStateInitialize(bool privileged, if (!qemu_driver->workerPool) goto error; - virNWFilterRegisterCallbackDriver(&qemuCallbackDriver); return 0; error: @@ -1078,7 +1054,6 @@ qemuStateCleanup(void) if (!qemu_driver) return -1; - virNWFilterUnRegisterCallbackDriver(&qemuCallbackDriver); virThreadPoolFree(qemu_driver->workerPool); virObjectUnref(qemu_driver->config); virObjectUnref(qemu_driver->hostdevMgr); diff --git a/src/uml/uml_driver.c b/src/uml/uml_driver.c index b50ba1ba64..4da8fdf473 100644 --- a/src/uml/uml_driver.c +++ b/src/uml/uml_driver.c @@ -55,7 +55,6 @@ #include "datatypes.h" #include "virlog.h" #include "domain_nwfilter.h" -#include "nwfilter_conf.h" #include "virfile.h" #include "virfdstream.h" #include "configmake.h" @@ -145,25 +144,6 @@ static int umlMonitorCommand(const struct uml_driver *driver, static struct uml_driver *uml_driver; -static int -umlVMFilterRebuild(virDomainObjListIterator iter, void *data) -{ - return virDomainObjListForEach(uml_driver->domains, iter, data); -} - -static void -umlVMDriverLock(void) -{ - umlDriverLock(uml_driver); -} - -static void -umlVMDriverUnlock(void) -{ - umlDriverUnlock(uml_driver); -} - - static virDomainObjPtr umlDomObjFromDomainLocked(struct uml_driver *driver, const unsigned char *uuid) @@ -196,13 +176,6 @@ umlDomObjFromDomain(struct uml_driver *driver, } -static virNWFilterCallbackDriver umlCallbackDriver = { - .name = "UML", - .vmFilterRebuild = umlVMFilterRebuild, - .vmDriverLock = umlVMDriverLock, - .vmDriverUnlock = umlVMDriverUnlock, -}; - struct umlAutostartData { struct uml_driver *driver; virConnectPtr conn; @@ -615,7 +588,6 @@ umlStateInitialize(bool privileged, VIR_FREE(userdir); - virNWFilterRegisterCallbackDriver(¨CallbackDriver); return 0; out_of_memory: @@ -709,7 +681,6 @@ umlStateCleanup(void) return -1; umlDriverLock(uml_driver); - virNWFilterRegisterCallbackDriver(¨CallbackDriver); if (uml_driver->inotifyWatch != -1) virEventRemoveHandle(uml_driver->inotifyWatch); VIR_FORCE_CLOSE(uml_driver->inotifyFD); -- 2.14.3

On 04/27/2018 11:24 AM, Daniel P. Berrangé wrote:
Today the nwfilter driver is entangled with the virt drivers in both directions. At various times when rebuilding filters nwfilter will call out to the virt driver to iterate over running guest's NICs. This has caused very complicated lock ordering rules to be required. If we are to split the virt drivers out into separate daemons we need to get rid of this coupling since we don't want the separate daemons calling each other, as that risks deadlock if all of the RPC workers are busy.
The obvious way to solve this is to have the nwfilter driver remember all the filters it has active, avoiding the need to iterate over running guests.
NB, these patches are all ready for review, but the last patch really should not be merged at this time. I need to do more work to be able to serialize the filter state to disk, so the nwfilter driver can keep track of it across daemon restarts. All except the last patch should be ok to merge though.
As usual, thinking about the dusty corners of this... First - this is a *great* idea, and we should do something similar to the network driver (keep track of all the connections to each network so they can be re-connected when a network is stopped/started). Second - we need to think about the situation where the nwfilter process is stopped during a time when the hypervisor driver shuts down a guest. If nwfilter keeps track of the current set of active filters, serializes them to disk, and then rereads/reloads that list of filters when it's restarted, then this sequence is possible: 1) nwfilter daemon is stopped 2) qemu destroys a guest 3) nwfilter daemon is restarted Since we wouldn't want qemu to just hang forever during guest shutdown if one of the subordinate drivers was unavailable, we could end up with the filter rules for the defunct guest (which were saved off to disk by nwfilter) being reloaded in step 3, and there would be no way to clear them out short of rebooting the host. I can think of two ways to solve this: 1) qemu (or whichever hypervisor) keeps a queue of pending requests to nwfilter, and re-sends them when the nwfilter daemon once again becomes available and is reconnected. (But then what happens if qemu is restarted while there are pending requests to nwfilter? We would need to keep all the pending requests serialized on disk too? :-/) 2) each time qemu reconnects to the nwfilter driver, it issues a "reset" command, which through some form of magic hand waving both reloads the rules for all guests that are still active, and deletes the rules for those that aren't. (2) seems like it might be simpler and more robust - perhaps all that would be needed would be for nwfilter to keep the name/uuid of each guest that has active rules (which you're already doing in this series, although we also need something to identify the hypervisor driver that requested the rules (if all connections are local, then just a driver name and pid would probably be sufficient), and have a virNWFilterReset() (or some other better name) API that accepts a list of active uuids. each time qemu connects to nwfilter, it could send this list, and nwfilter would delete all rules associated with that hypervisor and a name/uuid not in the list; as a bonus it could also reload the rules for guests that *are* still active) (similar to the way the network driver reloads the iptables rules for all the networks when it is restarted).

On Mon, Apr 30, 2018 at 12:12:24PM -0400, Laine Stump wrote:
First - this is a *great* idea, and we should do something similar to the network driver (keep track of all the connections to each network so they can be re-connected when a network is stopped/started).
Yes, this nwfilter tracking is a pre-requisite for similar work that we need todo in network driver. eg, when an unprivileged libvirtd asks privileged network driver for a TAP device, the network driver will also need to talk to the nwfilter driver to setup filtering. We'll need something similar in the node dev driver too, before we can do the network driver, because of the horrible <interface type=hostdev> stuff we need to support.
Second - we need to think about the situation where the nwfilter process is stopped during a time when the hypervisor driver shuts down a guest. If nwfilter keeps track of the current set of active filters, serializes them to disk, and then rereads/reloads that list of filters when it's restarted, then this sequence is possible:
1) nwfilter daemon is stopped 2) qemu destroys a guest 3) nwfilter daemon is restarted
Since we wouldn't want qemu to just hang forever during guest shutdown if one of the subordinate drivers was unavailable, we could end up with the filter rules for the defunct guest (which were saved off to disk by nwfilter) being reloaded in step 3, and there would be no way to clear them out short of rebooting the host.
I can think of two ways to solve this:
1) qemu (or whichever hypervisor) keeps a queue of pending requests to nwfilter, and re-sends them when the nwfilter daemon once again becomes available and is reconnected. (But then what happens if qemu is restarted while there are pending requests to nwfilter? We would need to keep all the pending requests serialized on disk too? :-/)
2) each time qemu reconnects to the nwfilter driver, it issues a "reset" command, which through some form of magic hand waving both reloads the rules for all guests that are still active, and deletes the rules for those that aren't.
(2) seems like it might be simpler and more robust - perhaps all that would be needed would be for nwfilter to keep the name/uuid of each guest that has active rules (which you're already doing in this series, although we also need something to identify the hypervisor driver that requested the rules (if all connections are local, then just a driver name and pid would probably be sufficient), and have a virNWFilterReset() (or some other better name) API that accepts a list of active uuids. each time qemu connects to nwfilter, it could send this list, and nwfilter would delete all rules associated with that hypervisor and a name/uuid not in the list; as a bonus it could also reload the rules for guests that *are* still active) (similar to the way the network driver reloads the iptables rules for all the networks when it is restarted).
Key thing to bear in mind here is that whatever solution is taken actually needs to be applicable to network devices, and host devices too. So I think want to avoid overloading semantics that are specific to the task of firewalling. IOW, I would not want to rebuild all filters just because the hypervisor driver restarted. IMHO is the nwfilter drivers job to expose a mechanism - create filter binding, list filter bindings, and delete filter bindings. It is then upto the caller to decide when these should be called, and ensure that they are always called eventually, even if a service is temporarily offline. This all says option (1) to me, even if it is requiring more explicit state tracking in the virt drivers, compared to our ability to be lazy right now. Regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|
participants (4)
-
Daniel P. Berrangé
-
Erik Skultety
-
Jiri Denemark
-
Laine Stump