V1:
https://listman.redhat.com/archives/libvir-list/2023-May/239720.html
Finally, a V2! :-/
This patch series enables libvirt to use nftables rules rather than
iptables *when setting up virtual networks* (it does *not* add
nftables support to the nwfilter driver).
This is accomplished by
1) moving all virtual network iptables-related code from both
util/viriptables.c and network/bridge_driver_linux.c into
util/network_iptables.c, leaving only 3 iptables-related functions
that are called from the bridge driver:
networkAddFirewallRules()
networkRemoveFirewallRules()
networkSetupPrivateChains()
2) creating a network/network_nftables.c that implements nftables
equivalents for 2 of those 3 functions
(networkRemoveFirewallRules() isn't needed for nftables because
other patches in this series update virFirewall to automatically
create the list of commands needed to remove all the rules added by
a particular virFirewall).
There's a bunch of other cleanup and reorganization going on that's
described in the individual patches.
Changes from V1:
* The biggest change is that in V1 I had made a virNetFilter API that
was at the same level as all the low level functions in
viriptable.c. But in the end I realized that, while this would
guarantee that the rules added by the nftables backend were as close
as possible to those created by the iptables backend, it also meant
that any modifications to improve the nftables rules would anyway
necessitate splitting off at a higher level (the 3 functions listed
above), while at the same time rendering the virNetfilter API
unnecessary. So instead I consolidated everything at/below the level
of the 3 above functions into a single file, with a very simple
interface, then duplicated that file and modified the duplicate to
produce nftables rules instead of iptables. The result is that I've
copied slightly more code, but any changes to nftables rules won't
have any effect on the iptables backend.
* util/viriptables.c was moved to network/network_iptables.c since it
is a specific enough API that it was only ever used by the network
driver.
* There is no more circular dependency between virfirewall,
virnetfilter, & virXXtables as pointed out by danpb in his review of
V1. virFirewall does still have the functionality of automatically
generating the necessary commands to remove a firewall (which was
the reason for the circle), but it is self-contained in a couple of
functions in virfirewall.c rather than calling out to virnetfilter.c
(which, btw, doesn't even exist in V2).
* Based on the exchange in the responses to V1, I went ahead and made
nftables the default backend when available (V1 left iptables as the
default). The only behavioral difference between iptables and
nftables is the lack of checksum fixup of bad DHCP packets which is
only an issue for very old guest OSes, and is easy to workaround
(see patches 24 & 26 for details)
The firewall unit tests have been parameterized so that all the tests
are run for both backends. This of course does nothing for all the
tests in libvirt-tck (and any other tests that validate via checking
the output of e.g. "iptables -S"). That is going to take some work,
somewhere, by somebody :-)
One thing I'm undecided about is the firewall object stored in the
networkobj (patches 19 & 20) - the way the code is currently written,
the xml element is called <firewall>, and it contains the virFirewall
object that will remove the network's firewall. I have pondered the
idea of saving the entire original virFirewall object (which includes
all the commands that were used to *create* the firewall, as well as
all the commands needed to remove it), since this might be useful in
debugging. It is quite a lot of data though, and not easily readable
by a human (there is a separate element for each option of each
commandline), so I haven't decided if it's worthwhile. (Alternately,
if I leave it as is, maybe I should change the element name to
<fwRemoval>? Does anyone have an opinion?)
Laine Stump (27):
util/network: move viriptables.[ch] from util to network directory
network: move all functions manipulating iptables rules into
network_iptables.c
network: make all iptables functions used only in network_iptables.c
static
util: #define the names used for private packet filter chains
util: change name of virFirewallRule to virFirewallCmd
util: rename virNetFilterAction to iptablesAction, and add
VIR_ENUM_DECL/IMPL
util: check for 0 args when applying iptables rule
util: add -w/--concurrent when applying a FirewallCmd rather than when
building it
util: determine ignoreErrors value when creating virFirewallCmd, not
when applying
util/network: new virFirewallBackend enum
network: add (empty) network.conf file to distribution files
network: support setting firewallBackend from network.conf
network: framework to call backend-specific function to init private
filter chains
util: new functions to support adding individual firewall rollback
commands
util: implement rollback rule autocreation for iptables commands
network: turn on auto-rollback for the rules added for virtual
networks
util: new function virFirewallNewFromRollback()
util: new functions virFirewallParseXML() and virFirewallFormat()
conf: add a virFirewall object to virNetworkObj
network: use previously saved list of firewall removal commands
network: save network status when firewall rules are reloaded
meson: stop looking for iptables/ip6tables/ebtables at build time
rpm: drop BuildRequires for iptables and ebtables
network: add an nftables backend for network driver's firewall
construction
tests: test cases for nftables backend
network: prefer the nftables backend over iptables
RFC: spec: change iptables/ebtables from Requires to Recommends, add
nftables
libvirt.spec.in | 12 +-
meson.build | 3 -
po/POTFILES | 3 +-
src/conf/virnetworkobj.c | 40 +
src/conf/virnetworkobj.h | 11 +
src/libvirt_private.syms | 57 +-
src/network/bridge_driver.c | 35 +-
src/network/bridge_driver_conf.c | 45 +
src/network/bridge_driver_conf.h | 3 +
src/network/bridge_driver_linux.c | 639 +------
src/network/bridge_driver_nop.c | 6 +-
src/network/bridge_driver_platform.h | 6 +-
src/network/libvirtd_network.aug | 39 +
src/network/meson.build | 13 +
src/network/network.conf | 27 +
src/network/network_iptables.c | 1677 +++++++++++++++++
src/network/network_iptables.h | 30 +
src/network/network_nftables.c | 940 +++++++++
src/network/network_nftables.h | 28 +
src/network/test_libvirtd_network.aug.in | 5 +
src/nwfilter/nwfilter_ebiptables_driver.c | 1004 +++++-----
src/util/meson.build | 1 -
src/util/virebtables.c | 36 +-
src/util/virfirewall.c | 801 ++++++--
src/util/virfirewall.h | 86 +-
src/util/viriptables.c | 1072 -----------
src/util/viriptables.h | 155 --
.../{base.args => base.iptables} | 0
tests/networkxml2firewalldata/base.nftables | 256 +++
...-linux.args => nat-default-linux.iptables} | 0
.../nat-default-linux.nftables | 248 +++
...pv6-linux.args => nat-ipv6-linux.iptables} | 0
.../nat-ipv6-linux.nftables | 384 ++++
...rgs => nat-ipv6-masquerade-linux.iptables} | 0
.../nat-ipv6-masquerade-linux.nftables | 456 +++++
...linux.args => nat-many-ips-linux.iptables} | 0
.../nat-many-ips-linux.nftables | 472 +++++
...-linux.args => nat-no-dhcp-linux.iptables} | 0
.../nat-no-dhcp-linux.nftables | 384 ++++
...ftp-linux.args => nat-tftp-linux.iptables} | 0
.../nat-tftp-linux.nftables | 274 +++
...inux.args => route-default-linux.iptables} | 0
.../route-default-linux.nftables | 162 ++
tests/networkxml2firewalltest.c | 56 +-
tests/virfirewalltest.c | 424 ++---
45 files changed, 7138 insertions(+), 2752 deletions(-)
create mode 100644 src/network/libvirtd_network.aug
create mode 100644 src/network/network.conf
create mode 100644 src/network/network_iptables.c
create mode 100644 src/network/network_iptables.h
create mode 100644 src/network/network_nftables.c
create mode 100644 src/network/network_nftables.h
create mode 100644 src/network/test_libvirtd_network.aug.in
delete mode 100644 src/util/viriptables.c
delete mode 100644 src/util/viriptables.h
rename tests/networkxml2firewalldata/{base.args => base.iptables} (100%)
create mode 100644 tests/networkxml2firewalldata/base.nftables
rename tests/networkxml2firewalldata/{nat-default-linux.args =>
nat-default-linux.iptables} (100%)
create mode 100644 tests/networkxml2firewalldata/nat-default-linux.nftables
rename tests/networkxml2firewalldata/{nat-ipv6-linux.args => nat-ipv6-linux.iptables}
(100%)
create mode 100644 tests/networkxml2firewalldata/nat-ipv6-linux.nftables
rename tests/networkxml2firewalldata/{nat-ipv6-masquerade-linux.args =>
nat-ipv6-masquerade-linux.iptables} (100%)
create mode 100644 tests/networkxml2firewalldata/nat-ipv6-masquerade-linux.nftables
rename tests/networkxml2firewalldata/{nat-many-ips-linux.args =>
nat-many-ips-linux.iptables} (100%)
create mode 100644 tests/networkxml2firewalldata/nat-many-ips-linux.nftables
rename tests/networkxml2firewalldata/{nat-no-dhcp-linux.args =>
nat-no-dhcp-linux.iptables} (100%)
create mode 100644 tests/networkxml2firewalldata/nat-no-dhcp-linux.nftables
rename tests/networkxml2firewalldata/{nat-tftp-linux.args => nat-tftp-linux.iptables}
(100%)
create mode 100644 tests/networkxml2firewalldata/nat-tftp-linux.nftables
rename tests/networkxml2firewalldata/{route-default-linux.args =>
route-default-linux.iptables} (100%)
create mode 100644 tests/networkxml2firewalldata/route-default-linux.nftables
--
2.44.0