On Fri, Oct 31, 2025 at 01:05:44PM +0100, Dion Bosschieter wrote:
> Change the nwfilter driver loading mechanism to read from nwfilter.conf.
> By default, it will use the existing ebiptables driver, which can be
> replaced in the future to remove the {eb,ip}tables dependency.
>
> Added nftables to *filter_tech_drivers as an available driver option
> for users to choose from.
>
> Signed-off-by: Dion Bosschieter <[email protected]>
> ---
> src/nwfilter/nwfilter_driver.c | 49 +++++++++++++++++++--
> src/nwfilter/nwfilter_gentech_driver.c | 60 +++++++++++---------------
> src/nwfilter/nwfilter_gentech_driver.h | 4 +-
> 3 files changed, 73 insertions(+), 40 deletions(-)
Adding a config file makes sense, but we need todo a bit more.
The default file should be in git as src/nwfilter/nwfilter.conf.in
so we show (& thus document) the available config options, and
installed by meson.
Also there needs to be augeas files for parsing the config file.
For a trivial example, follow what's done for the virtual network
driver with src/network/libvirtd_network.aug and
src/network/test_libvirtd_network.aug.in. Also see the meson
file for how to invoke the test file as part of unit tests.
>
> diff --git a/src/nwfilter/nwfilter_driver.c b/src/nwfilter/nwfilter_driver.c
> index 522cfda022..18d322574d 100644
> --- a/src/nwfilter/nwfilter_driver.c
> +++ b/src/nwfilter/nwfilter_driver.c
> @@ -26,9 +26,7 @@
>
> #include "virgdbus.h"
> #include "virlog.h"
> -
> #include "internal.h"
> -
> #include "virerror.h"
> #include "datatypes.h"
> #include "nwfilter_driver.h"
> @@ -36,7 +34,6 @@
> #include "configmake.h"
> #include "virpidfile.h"
> #include "viraccessapicheck.h"
> -
> #include "nwfilter_ipaddrmap.h"
> #include "nwfilter_dhcpsnoop.h"
> #include "nwfilter_learnipaddr.h"
> @@ -203,6 +200,41 @@ nwfilterStateCleanup(void)
> }
>
>
> +/**
> + * virNWFilterLoadGentechDriverFromConfig:
> + *
> + * Loading driver name from nwfilter.conf config file
> + */
> +static char *
> +virNWFilterLoadGentechDriverFromConfig(const char *configfile)
> +{
> + g_autoptr(virConf) conf = NULL;
> + g_autofree char *drivername = NULL;
> +
> + if (access(configfile, R_OK) == 0) {
> +
> + conf = virConfReadFile(configfile, 0);
> + if (!conf)
> + return NULL;
> +
> + if (virConfGetValueString(conf, "driver", &drivername) < 0)
> + return NULL;
> +
> + if (drivername) {
> + VIR_DEBUG("nwfilter driver setting requested from config file
> %s: '%s'",
> + configfile, drivername);
> + }
> + }
> +
> + if (!drivername) {
> + drivername = g_strdup(NWFILTER_DEFAULT_DRIVER);
> + }
Rather than harcoding this, we should try to auto-detect the right
option, and we should honour the existing 'firewall_backend_priority'
meson option that is used for the network driver.
Take a look at src/network/bridge_driver_conf.c which can be used
as a template for the nwfilter driver - worth putting it into
separate nwfilter_driver_conf.{h,c} files to match the common
pattern we use in other drivers.
> +
> +
> + return g_steal_pointer(&drivername);
> +}
> +
> +
> /**
> * nwfilterStateInitialize:
> *
> @@ -217,6 +249,8 @@ nwfilterStateInitialize(bool privileged,
> {
> VIR_LOCK_GUARD lock = virLockGuardLock(&driverMutex);
> GDBusConnection *sysbus = NULL;
> + g_autofree char *configfile = NULL;
> + char *gentechdrivername = NULL;
>
> if (root != NULL) {
> virReportError(VIR_ERR_INVALID_ARG, "%s",
> @@ -266,7 +300,14 @@ nwfilterStateInitialize(bool privileged,
> if (virNWFilterDHCPSnoopInit() < 0)
> goto error;
>
> - if (virNWFilterTechDriversInit(privileged) < 0)
> + configfile = g_strdup(SYSCONFDIR "/libvirt/nwfilter.conf");
> +
> + /* get chosen driver from config file */
> + gentechdrivername = virNWFilterLoadGentechDriverFromConfig(configfile);
> + if (gentechdrivername == NULL)
> + goto error;
> +
> + if (virNWFilterTechDriversInit(privileged, gentechdrivername) < 0)
> goto error;
>
> if (virNWFilterConfLayerInit(virNWFilterTriggerRebuildImpl, driver) < 0)
> diff --git a/src/nwfilter/nwfilter_gentech_driver.c
> b/src/nwfilter/nwfilter_gentech_driver.c
> index 1465734a54..adb96acca6 100644
> --- a/src/nwfilter/nwfilter_gentech_driver.c
> +++ b/src/nwfilter/nwfilter_gentech_driver.c
> @@ -32,6 +32,7 @@
> #include "nwfilter_dhcpsnoop.h"
> #include "nwfilter_ipaddrmap.h"
> #include "nwfilter_learnipaddr.h"
> +#include "nwfilter_nftables_driver.h"
> #include "virnetdev.h"
>
> #define VIR_FROM_THIS VIR_FROM_NWFILTER
> @@ -48,18 +49,20 @@ static int _virNWFilterTeardownFilter(const char *ifname);
>
> static virNWFilterTechDriver *filter_tech_drivers[] = {
> &ebiptables_driver,
> - NULL
> + &nftables_driver,
> };
>
> -int virNWFilterTechDriversInit(bool privileged)
> +int virNWFilterTechDriversInit(bool privileged, const char *drivername)
> {
> size_t i = 0;
> - VIR_DEBUG("Initializing NWFilter technology drivers");
> - while (filter_tech_drivers[i]) {
> - if (!(filter_tech_drivers[i]->flags & TECHDRV_FLAG_INITIALIZED))
> + VIR_DEBUG("Initializing NWFilter technology drivers, chosen %s",
> drivername);
> +
> + for (i = 0; i < G_N_ELEMENTS(filter_tech_drivers); i++) {
> + if (!(filter_tech_drivers[i]->flags & TECHDRV_FLAG_INITIALIZED)
> + && STREQ(filter_tech_drivers[i]->name, drivername))
> filter_tech_drivers[i]->init(privileged);
> - i++;
> }
> +
> return 0;
> }
>
> @@ -67,25 +70,20 @@ int virNWFilterTechDriversInit(bool privileged)
> void virNWFilterTechDriversShutdown(void)
> {
> size_t i = 0;
> - while (filter_tech_drivers[i]) {
> + for (i = 0; i < G_N_ELEMENTS(filter_tech_drivers); i++) {
> if ((filter_tech_drivers[i]->flags & TECHDRV_FLAG_INITIALIZED))
> filter_tech_drivers[i]->shutdown();
> - i++;
> }
> }
>
>
> static virNWFilterTechDriver *
> -virNWFilterTechDriverForName(const char *name)
> +virNWFilterInitializedTechDriver(void)
> {
> size_t i = 0;
> - while (filter_tech_drivers[i]) {
> - if (STREQ(filter_tech_drivers[i]->name, name)) {
> - if ((filter_tech_drivers[i]->flags & TECHDRV_FLAG_INITIALIZED)
> == 0)
> - break;
> + for (i = 0; i < G_N_ELEMENTS(filter_tech_drivers); i++) {
> + if ((filter_tech_drivers[i]->flags & TECHDRV_FLAG_INITIALIZED))
> return filter_tech_drivers[i];
> - }
> - i++;
> }
> return NULL;
> }
> @@ -617,7 +615,6 @@ virNWFilterInstantiateFilterUpdate(virNWFilterDriverState
> *driver,
> bool *foundNewFilter)
> {
> int rc = -1;
> - const char *drvname = EBIPTABLES_DRIVER_ID;
> virNWFilterTechDriver *techdriver;
> virNWFilterObj *obj;
> virNWFilterDef *filter;
> @@ -625,12 +622,11 @@
> virNWFilterInstantiateFilterUpdate(virNWFilterDriverState *driver,
> char vmmacaddr[VIR_MAC_STRING_BUFLEN] = {0};
> virNWFilterVarValue *ipaddr;
>
> - techdriver = virNWFilterTechDriverForName(drvname);
> + techdriver = virNWFilterInitializedTechDriver();
>
> if (!techdriver) {
> - virReportError(VIR_ERR_INTERNAL_ERROR,
> - _("Could not get access to ACL tech driver '%1$s'"),
> - drvname);
> + virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> + _("Could not get access to ACL tech driver"));
> return -1;
> }
>
> @@ -768,15 +764,13 @@
> virNWFilterUpdateInstantiateFilter(virNWFilterDriverState *driver,
> static int
> virNWFilterRollbackUpdateFilter(virNWFilterBindingDef *binding)
> {
> - const char *drvname = EBIPTABLES_DRIVER_ID;
> int ifindex;
> virNWFilterTechDriver *techdriver;
>
> - techdriver = virNWFilterTechDriverForName(drvname);
> + techdriver = virNWFilterInitializedTechDriver();
> if (!techdriver) {
> - virReportError(VIR_ERR_INTERNAL_ERROR,
> - _("Could not get access to ACL tech driver '%1$s'"),
> - drvname);
> + virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> + _("Could not get access to ACL tech driver"));
> return -1;
> }
>
> @@ -793,15 +787,13 @@ virNWFilterRollbackUpdateFilter(virNWFilterBindingDef
> *binding)
> static int
> virNWFilterTearOldFilter(virNWFilterBindingDef *binding)
> {
> - const char *drvname = EBIPTABLES_DRIVER_ID;
> int ifindex;
> virNWFilterTechDriver *techdriver;
>
> - techdriver = virNWFilterTechDriverForName(drvname);
> + techdriver = virNWFilterInitializedTechDriver();
> if (!techdriver) {
> - virReportError(VIR_ERR_INTERNAL_ERROR,
> - _("Could not get access to ACL tech driver '%1$s'"),
> - drvname);
> + virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> + _("Could not get access to ACL tech driver"));
> return -1;
> }
>
> @@ -818,14 +810,12 @@ virNWFilterTearOldFilter(virNWFilterBindingDef *binding)
> static int
> _virNWFilterTeardownFilter(const char *ifname)
> {
> - const char *drvname = EBIPTABLES_DRIVER_ID;
> virNWFilterTechDriver *techdriver;
> - techdriver = virNWFilterTechDriverForName(drvname);
> + techdriver = virNWFilterInitializedTechDriver();
>
> if (!techdriver) {
> - virReportError(VIR_ERR_INTERNAL_ERROR,
> - _("Could not get access to ACL tech driver '%1$s'"),
> - drvname);
> + virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> + _("Could not get access to ACL tech driver"));
> return -1;
> }
>
> diff --git a/src/nwfilter/nwfilter_gentech_driver.h
> b/src/nwfilter/nwfilter_gentech_driver.h
> index 946d5d3d56..8f6f4d164a 100644
> --- a/src/nwfilter/nwfilter_gentech_driver.h
> +++ b/src/nwfilter/nwfilter_gentech_driver.h
> @@ -25,7 +25,9 @@
> #include "virnwfilterobj.h"
> #include "virnwfilterbindingdef.h"
>
> -int virNWFilterTechDriversInit(bool privileged);
> +#define NWFILTER_DEFAULT_DRIVER "ebiptables"
> +
> +int virNWFilterTechDriversInit(bool privileged, const char *drivername);
> void virNWFilterTechDriversShutdown(void);
>
> enum instCase {
> --
> 2.43.0
>
With 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 :|