On Mon, Feb 16, 2026 at 11:42:37AM +0100, Dion Bosschieter wrote:
> Resolves issue: https://gitlab.com/libvirt/libvirt/-/issues/603
> Benchmarks showed that the amount of iifname jumps for each
> interface is the cause for this.
> Switched the nftables driver towards a vmap (verdict map) so we
> can have 1 rule that jumps to the correct root input/output chain
> per interface. Which improves throughput as when the number of
> interface check and jump rules increases the throughput decreases.
> The issue describes the interface matching works using the interface
> name and the majority of the effort is the strncpy, this commit also
> switches nftables to an interface_index compare instead.
> However, just using the interface_index is not enough, the amount of
> oif and iif jump rules causes quite a performance issue,
> the vmap instead solves this.
>
> Split rules into separate tables: "libvirt_nwfilter_ethernet" and
> "libvirt_nwfilter_inet" to preserve existing ebip firewall behavior.
>
> Reworked chain logic for clarity with root -input/-output chains per
> interface. input in the VM interface is filtered in the -input
> chain(s), output out of the VM inteface is filtered in the -output
> chain(s).
>
> Stuck with two tables for compatibility reasons with ebiptables.
> Unifying into a single table would break users’ firewall definitions, which
> depend on being able to accept traffic at the Ethernet layer
> (currently defined via ebtables) and apply additional filtering
> via IP rules (currently defined via ip(6)tables).
> The nwfilter_nftables_driver splits the ethernet and
> non ethernet (inet) rules in seperate tables, for above mentioned
> compatibility reasons.
> “libvirt_nwfilter_ethernet” and “libvirt_nwfilter_inet”.
>
> Rewrote chain logic, so it is easier to understand,
> input in the VM interface is filtered in the -input
> chain(s), output out of the VM inteface is filtered in the -output
> chain(s). _ethernet and _inet table follow the same style and
> hook in the same way.
>
> Simplified conntrack handling: rules with accept+conntrack are
> duplicated to the opposite chain for symmetric behavior, to support
> the existing ebiptables logic.
>
> Firewall updates continue to use tmp names for atomic replacement.
>
> Unsupported nwfilter features (for now):
> - STP filtering
> - Gratuitous ARP filtering
> - IPSets (potential future support via nft sets)
>
> Signed-off-by: Dion Bosschieter <[email protected]>
> ---
> po/POTFILES | 1 +
> src/nwfilter/meson.build | 1 +
> src/nwfilter/nwfilter_nftables_driver.c | 2667 +++++++++++++++++++++++
> src/nwfilter/nwfilter_nftables_driver.h | 28 +
> 4 files changed, 2697 insertions(+)
> create mode 100644 src/nwfilter/nwfilter_nftables_driver.c
> create mode 100644 src/nwfilter/nwfilter_nftables_driver.h
>
> + /* process rule comment */
> + virFirewallCmdAddArg(fw, fwrule, "comment");
> +
> + /* ethernet rules don't have the allHdrFilter */
> + if (HAS_ENTRY_ITEM(&rule->p.allHdrFilter.ipHdr.dataComment) &&
> + !virNWFilterRuleIsProtocolEthernet(rule)) {
> + nftablesAddCmdUserComment(fw, fwrule, rule);
> + } else {
> + virFirewallCmdAddArgFormat(fw, fwrule, "\"priority=%d\"",
> rule->priority);
> + }
I'm wondering why we need to include "priority=NNN" in a comment against
every rule ?
Is that left-over debugging from an earlier version of the patches?
IIUC, we're correctly using the priority numbers to sort the rules in
your impl here.
With regards,
Daniel
--
|: https://berrange.com ~~ https://hachyderm.io/@berrange :|
|: https://libvirt.org ~~ https://entangle-photo.org :|
|: https://pixelfed.art/berrange ~~ https://fstop138.berrange.com :|