On 3/27/26 13:06, Daniel P. Berrangé wrote:
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 ?

We don't need to, I found it easier to read the nftables rules when comparing them to the nwfilter source.

I'll remove them in a v6.


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

With regards,

Dion

Reply via email to