[libvirt] [PATCH v3 20/20] nwfilter: convert virt drivers to use public API for nwfilter bindings
John Ferlan
jferlan at redhat.com
Mon Jun 18 21:02:05 UTC 2018
On 06/14/2018 08:33 AM, Daniel P. Berrangé wrote:
> Remove the callbacks that the nwfilter driver registers with the domain
> object config layer. Instead make the current helper methods call into
> the public API for creating/deleting nwfilter bindings.
>
> Signed-off-by: Daniel P. Berrangé <berrange at redhat.com>
> ---
> src/conf/domain_nwfilter.c | 124 +++++++++++++++++++++----
> src/conf/domain_nwfilter.h | 13 ---
> src/libvirt_private.syms | 1 -
> src/nwfilter/nwfilter_driver.c | 84 +++--------------
> src/nwfilter/nwfilter_gentech_driver.c | 42 ---------
> src/nwfilter/nwfilter_gentech_driver.h | 4 -
> 6 files changed, 120 insertions(+), 148 deletions(-)
>
I ran the more "aggressive" Avocado tests based on an old bz
(https://bugzilla.redhat.com/show_bug.cgi?id=1034807) and got the
following in my debug libvirtd output:
2018-06-15 15:46:18.683+0000: 18817: error :
virNWFilterBindingLookupByPortDev:589 : portdev in
virNWFilterBindingLookupByPortDev must not be NULL
2018-06-15 15:46:18.684+0000: 18817: error :
virNWFilterBindingLookupByPortDev:589 : portdev in
virNWFilterBindingLookupByPortDev must not be NULL
The first thing the test does is remove the defined interface:
<interface type='bridge'>
<mac address='52:54:00:9a:9b:9c'/>
<source bridge='virbr0'/>
<model type='virtio'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x03'
function='0x0'/>
</interface>
and then replaces/adds with a new interface:
<interface type="bridge">
<mac address="52:54:00:9a:9b:9c" />
<source bridge="virbr0" />
<model type="virtio" />
<address bus="0x00" domain="0x0000" function="0x0" slot="0x03"
type="pci" />
<filterref filter="allow-arp" />
</interface>
for the test domain via device attach.
Then 2 threads are started - 1 that continually starts/destroys the
domain and 1 that continually removes/adds allow-arp. The actual logic
in the test is busted because starting up a domain without a defined
filter will fail and the thread doing the start/stop has no retry
(try/except) logic. When I added the try/except logic and toned down the
retry logic a bit I could get the test to pass with a few adjustments to
the libvirt code here. Ironically, when the test goes too fast it
caused my CPU's to get hot and generate a false positive failure because
there were dmesg events related to core temperature above threshold.
Anyway, I've noted a couple of places I think adjustments could/should
be made - hopefully they make sense as I started looking "backwards" to
see where things go introduced.
> diff --git a/src/conf/domain_nwfilter.c b/src/conf/domain_nwfilter.c
> index 7570e0ae83..ed45394918 100644
> --- a/src/conf/domain_nwfilter.c
> +++ b/src/conf/domain_nwfilter.c
[...]
>
> +
> int
> virDomainConfNWFilterInstantiate(const char *vmname,
> const unsigned char *vmuuid,
> virDomainNetDefPtr net)
Revisiting my comment from patch 13 - it is possible to enter here with
net->filter being NULL. Is it worth returning 0 in that case under the
assumption that there is no filter so that the callers then don't have
to make that check? If portdev/ifname is NULL, not much is going to be
found as well.
> {
> - if (nwfilterDriver != NULL)
> - return nwfilterDriver->instantiateFilter(vmname, vmuuid, net);
> + virConnectPtr conn = virGetConnectNWFilter();
> + virNWFilterBindingDefPtr def = NULL;
> + virNWFilterBindingPtr binding = NULL;
> + char *xml;
> + int ret = -1;
> +
> + VIR_DEBUG("vmname=%s portdev=%s filter=%s",
> + vmname, NULLSTR(net->ifname), NULLSTR(net->filter));
Both being NULL probably is not a good thing - what filter for what portdev?
> +
> + if (!conn)
> + goto cleanup;
> +
Based on patch 16/19 comments and the thought above:
if (!net->ifname ||
(binding = virNWFilterBindingLookupByPortDev(conn, net->ifname))) {
ret = 0;
goto cleanup;
}
where the !net->ifname may avoids the patch 13 comment issue and the ret
= 0 when finding the binding handles the filter already loaded issue.
The filter would be loaded for a running guest (after at least the
second libvirtd restart) by virNWFilterBindingObjListLoadAllConfigs.
> + if (!(def = virNWFilterBindingDefForNet(vmname, vmuuid, net)))
> + goto cleanup;
> +
> + if (!(xml = virNWFilterBindingDefFormat(def)))
> + goto cleanup;
> +
> + if (!(binding = virNWFilterBindingCreateXML(conn, xml, 0)))
> + goto cleanup;
> +
> + ret = 0;
> +
> + cleanup:
> + VIR_FREE(xml);
> + virNWFilterBindingDefFree(def);
> + virObjectUnref(binding);
> + virObjectUnref(conn);
> + return ret;
> +}
> +
> +
> +static void
> +virDomainConfNWFilterTeardownImpl(virConnectPtr conn,
> + virDomainNetDefPtr net)
> +{
> + virNWFilterBindingPtr binding;
>
> - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> - _("No network filter driver available"));
> - return -1;
> + binding = virNWFilterBindingLookupByPortDev(conn, net->ifname);
> + if (!binding)
virNWFilterBindingLookupByPortDev will generate an error when there's no
filter defined for @net (if you're running libvirtd in a debugger you
see it).
Shouldn't the call be guarded by a "if (!net->filter)"?
if (!net->filter ||
!binding = vir...())
return;
if not, then we probably should reset the last error since we're just
returning (error as in [1]).
> + return;
> +
> + virNWFilterBindingDelete(binding);
> +
> + virObjectUnref(binding);
> }
>
> +
> void
> virDomainConfNWFilterTeardown(virDomainNetDefPtr net)
> {
> - if (nwfilterDriver != NULL)
> - nwfilterDriver->teardownFilter(net);
> + virConnectPtr conn = virGetConnectNWFilter();
> +
> + if (!conn)
> + return;
> +
> + virDomainConfNWFilterTeardownImpl(conn, net);
> +
> + virObjectUnref(conn);
> }
>
may as well add the blank line here from ...
> void
> virDomainConfVMNWFilterTeardown(virDomainObjPtr vm)
> {
> size_t i;
> + virConnectPtr conn = virGetConnectNWFilter();
> +
> + if (!conn)
> + return;
> +
... here... or at least remove this extra blank line.
> +
> + for (i = 0; i < vm->def->nnets; i++)
> + virDomainConfNWFilterTeardownImpl(conn, vm->def->nets[i]);
>
> - if (nwfilterDriver != NULL) {
> - for (i = 0; i < vm->def->nnets; i++)
> - virDomainConfNWFilterTeardown(vm->def->nets[i]);
> - }
> + virObjectUnref(conn);
> }
[...]
>
> diff --git a/src/nwfilter/nwfilter_driver.c b/src/nwfilter/nwfilter_driver.c
> index 2b6856a36c..26e6e76b3b 100644
> --- a/src/nwfilter/nwfilter_driver.c
> +++ b/src/nwfilter/nwfilter_driver.c
> @@ -654,67 +654,6 @@ nwfilterGetXMLDesc(virNWFilterPtr nwfilter,
> }
>
>
[...]
> static virNWFilterBindingPtr
> nwfilterBindingLookupByPortDev(virConnectPtr conn,
> const char *portdev)
> @@ -725,8 +664,11 @@ nwfilterBindingLookupByPortDev(virConnectPtr conn,
>
> obj = virNWFilterBindingObjListFindByPortDev(driver->bindings,
> portdev);
> - if (!obj)
> + if (!obj) {
> + virReportError(VIR_ERR_NO_NWFILTER_BINDING,
> + _("no nwfilter binding for port dev '%s'"), portdev);454
[1]
Adding this error here for someone running debug will cause those
virDomainConfNWFilterTeardownImpl consumers w/o a filter to display this
message. Of course removing it means the callers all have to add some
sort of message.
John
> goto cleanup;
> + }
>
> def = virNWFilterBindingObjGetDef(obj);
> if (virNWFilterBindingLookupByPortDevEnsureACL(conn, def) < 0)
[...]
More information about the libvir-list
mailing list