[PATCH nf-next v2] netfilter: nft_flow_offload: do not offload multicast
flat view
WARM2d
From: Koral Ilgun <hidden>
Date: 2026-10-29 22:01:52
Also in:
lkml, netfilter-devel
Subsystem:
netfilter, networking [general], the rest · Maintainers:
Pablo Neira Ayuso, Florian Westphal, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds
From: Koral Ilgun <redacted> A flow holds one output per direction, which it resolves when it is added. The outputs of a multicast route change when listeners join or leave. So a multicast flow in the flowtable continues to send to the output that it resolved, also after the last listener left, and the counters of the multicast routing stop. A ruleset can keep multicast out with a match before the flow offload statement. Without one, IPv4 multicast stays out of the flowtable only because the reverse route lookup in nft_flow_route() refuses a multicast source address. The IPv6 route lookup has no such check, so IPv6 multicast that ip6mr forwards goes into the flowtable. Skip a multicast destination for both families in the flow offload expression itself, so that the result no longer depends on the ruleset or on the route lookup. Signed-off-by: Koral Ilgun <redacted> --- v2: - Target nf-next, and drop the Fixes tag (Pablo). - Use the shorter form that Fernando suggested; the result is the same. - Say in the commit message that a ruleset can keep multicast out. v1: https://lore.kernel.org/all/20261028205938.662312-1-koralilgun@gmail.com/ (local) Tested with v1, which skips the same packets: on an arm64 router with Linux 6.18.54, with an inet flowtable that offloads forwarded flows, and IPv4 and IPv6 multicast routed from the WAN to one VLAN. Without this change, the IPv6 flow went into the flowtable after its first packets: the ip6mr vif counters showed 25 of 1,500 packets, and the receiver still got all 400 packets after its leave. With it, the vif counters showed 1,500 of 1,500, the flow stayed out of the flowtable, and the stream stopped about 2.5 s after the leave. Unicast IPv4 and IPv6 flows still went into the flowtable. net/netfilter/nft_flow_offload.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/net/netfilter/nft_flow_offload.c b/net/netfilter/nft_flow_offload.c
index d3c5651dd699..530e20c7fd45 100644
--- a/net/netfilter/nft_flow_offload.c
+++ b/net/netfilter/nft_flow_offload.c@@ -10,6 +10,7 @@ #include <linux/netfilter/nf_conntrack_common.h> #include <linux/netfilter/nf_tables.h> #include <net/ip.h> +#include <net/ipv6.h> #include <net/flow.h> #include <net/netfilter/nf_tables.h> #include <net/netfilter/nf_tables_core.h>
@@ -33,6 +34,10 @@ static bool nft_flow_offload_skip(struct sk_buff *skb, int family) if (unlikely(opt->optlen)) return true; + + return ipv4_is_multicast(ip_hdr(skb)->daddr); + } else if (family == NFPROTO_IPV6) { + return ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr); } return false;
base-commit: 734bef548a96e8774d6eef5dfa2026c6edc4e80b -- 2.43.0