From: Pablo Neira Ayuso <pablo@netfilter.org>
To: netfilter-devel@vger.kernel.org
Cc: davem@davemloft.net, netdev@vger.kernel.org, kuba@kernel.org,
pabeni@redhat.com, edumazet@google.com, fw@strlen.de,
horms@kernel.org
Subject: [PATCH net-next 02/16] netfilter: flowtable: consolidate xmit path
Date: Tue, 25 Nov 2025 22:32:58 +0000 [thread overview]
Message-ID: <20251125223312.1246891-3-pablo@netfilter.org> (raw)
In-Reply-To: <20251125223312.1246891-1-pablo@netfilter.org>
Use dev_queue_xmit() for the XMIT_NEIGH case. Store the interface index
of the real device behind the vlan/pppoe device, this introduces an
extra lookup for the real device in the xmit path because rt->dst.dev
provides the vlan/pppoe device.
XMIT_NEIGH now looks more similar to XMIT_DIRECT but the check for stale
dst and the neighbour lookup still remain in place which is convenient
to deal with network topology changes.
Note that nft_flow_route() needs to relax the check for _XMIT_NEIGH so
the existing basic xfrm offload (which only works in one direction) does
not break.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
include/net/netfilter/nf_flow_table.h | 1 +
net/netfilter/nf_flow_table_core.c | 1 +
net/netfilter/nf_flow_table_ip.c | 87 ++++++++++++++++-----------
net/netfilter/nf_flow_table_path.c | 7 +--
4 files changed, 57 insertions(+), 39 deletions(-)
diff --git a/include/net/netfilter/nf_flow_table.h b/include/net/netfilter/nf_flow_table.h
index e9f72d2558e9..efede742106c 100644
--- a/include/net/netfilter/nf_flow_table.h
+++ b/include/net/netfilter/nf_flow_table.h
@@ -140,6 +140,7 @@ struct flow_offload_tuple {
u16 mtu;
union {
struct {
+ u32 ifidx;
struct dst_entry *dst_cache;
u32 dst_cookie;
};
diff --git a/net/netfilter/nf_flow_table_core.c b/net/netfilter/nf_flow_table_core.c
index 9441ac3d8c1a..98d7b3708602 100644
--- a/net/netfilter/nf_flow_table_core.c
+++ b/net/netfilter/nf_flow_table_core.c
@@ -132,6 +132,7 @@ static int flow_offload_fill_route(struct flow_offload *flow,
break;
case FLOW_OFFLOAD_XMIT_XFRM:
case FLOW_OFFLOAD_XMIT_NEIGH:
+ flow_tuple->ifidx = route->tuple[dir].out.ifindex;
flow_tuple->dst_cache = dst;
flow_tuple->dst_cookie = flow_offload_dst_cookie(flow_tuple);
break;
diff --git a/net/netfilter/nf_flow_table_ip.c b/net/netfilter/nf_flow_table_ip.c
index 8cd4cf7ae211..8b74fb34998e 100644
--- a/net/netfilter/nf_flow_table_ip.c
+++ b/net/netfilter/nf_flow_table_ip.c
@@ -333,19 +333,18 @@ static void nf_flow_encap_pop(struct sk_buff *skb,
}
}
+struct nf_flow_xmit {
+ const void *dest;
+ const void *source;
+ struct net_device *outdev;
+};
+
static unsigned int nf_flow_queue_xmit(struct net *net, struct sk_buff *skb,
- const struct flow_offload_tuple_rhash *tuplehash,
- unsigned short type)
+ struct nf_flow_xmit *xmit)
{
- struct net_device *outdev;
-
- outdev = dev_get_by_index_rcu(net, tuplehash->tuple.out.ifidx);
- if (!outdev)
- return NF_DROP;
-
- skb->dev = outdev;
- dev_hard_header(skb, skb->dev, type, tuplehash->tuple.out.h_dest,
- tuplehash->tuple.out.h_source, skb->len);
+ skb->dev = xmit->outdev;
+ dev_hard_header(skb, skb->dev, ntohs(skb->protocol),
+ xmit->dest, xmit->source, skb->len);
dev_queue_xmit(skb);
return NF_STOLEN;
@@ -424,10 +423,10 @@ nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb,
struct nf_flowtable_ctx ctx = {
.in = state->in,
};
+ struct nf_flow_xmit xmit = {};
struct flow_offload *flow;
- struct net_device *outdev;
+ struct neighbour *neigh;
struct rtable *rt;
- __be32 nexthop;
int ret;
tuplehash = nf_flow_offload_lookup(&ctx, flow_table, skb);
@@ -454,25 +453,34 @@ nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb,
switch (tuplehash->tuple.xmit_type) {
case FLOW_OFFLOAD_XMIT_NEIGH:
rt = dst_rtable(tuplehash->tuple.dst_cache);
- outdev = rt->dst.dev;
- skb->dev = outdev;
- nexthop = rt_nexthop(rt, flow->tuplehash[!dir].tuple.src_v4.s_addr);
+ xmit.outdev = dev_get_by_index_rcu(state->net, tuplehash->tuple.ifidx);
+ if (!xmit.outdev) {
+ flow_offload_teardown(flow);
+ return NF_DROP;
+ }
+ neigh = ip_neigh_gw4(rt->dst.dev, rt_nexthop(rt, flow->tuplehash[!dir].tuple.src_v4.s_addr));
+ if (IS_ERR(neigh)) {
+ flow_offload_teardown(flow);
+ return NF_DROP;
+ }
+ xmit.dest = neigh->ha;
skb_dst_set_noref(skb, &rt->dst);
- neigh_xmit(NEIGH_ARP_TABLE, outdev, &nexthop, skb);
- ret = NF_STOLEN;
break;
case FLOW_OFFLOAD_XMIT_DIRECT:
- ret = nf_flow_queue_xmit(state->net, skb, tuplehash, ETH_P_IP);
- if (ret == NF_DROP)
+ xmit.outdev = dev_get_by_index_rcu(state->net, tuplehash->tuple.out.ifidx);
+ if (!xmit.outdev) {
flow_offload_teardown(flow);
+ return NF_DROP;
+ }
+ xmit.dest = tuplehash->tuple.out.h_dest;
+ xmit.source = tuplehash->tuple.out.h_source;
break;
default:
WARN_ON_ONCE(1);
- ret = NF_DROP;
- break;
+ return NF_DROP;
}
- return ret;
+ return nf_flow_queue_xmit(state->net, skb, &xmit);
}
EXPORT_SYMBOL_GPL(nf_flow_offload_ip_hook);
@@ -719,9 +727,9 @@ nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb,
struct nf_flowtable_ctx ctx = {
.in = state->in,
};
- const struct in6_addr *nexthop;
+ struct nf_flow_xmit xmit = {};
struct flow_offload *flow;
- struct net_device *outdev;
+ struct neighbour *neigh;
struct rt6_info *rt;
int ret;
@@ -749,24 +757,33 @@ nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb,
switch (tuplehash->tuple.xmit_type) {
case FLOW_OFFLOAD_XMIT_NEIGH:
rt = dst_rt6_info(tuplehash->tuple.dst_cache);
- outdev = rt->dst.dev;
- skb->dev = outdev;
- nexthop = rt6_nexthop(rt, &flow->tuplehash[!dir].tuple.src_v6);
+ xmit.outdev = dev_get_by_index_rcu(state->net, tuplehash->tuple.out.ifidx);
+ if (!xmit.outdev) {
+ flow_offload_teardown(flow);
+ return NF_DROP;
+ }
+ neigh = ip_neigh_gw6(rt->dst.dev, rt6_nexthop(rt, &flow->tuplehash[!dir].tuple.src_v6));
+ if (IS_ERR(neigh)) {
+ flow_offload_teardown(flow);
+ return NF_DROP;
+ }
+ xmit.dest = neigh->ha;
skb_dst_set_noref(skb, &rt->dst);
- neigh_xmit(NEIGH_ND_TABLE, outdev, nexthop, skb);
- ret = NF_STOLEN;
break;
case FLOW_OFFLOAD_XMIT_DIRECT:
- ret = nf_flow_queue_xmit(state->net, skb, tuplehash, ETH_P_IPV6);
- if (ret == NF_DROP)
+ xmit.outdev = dev_get_by_index_rcu(state->net, tuplehash->tuple.out.ifidx);
+ if (!xmit.outdev) {
flow_offload_teardown(flow);
+ return NF_DROP;
+ }
+ xmit.dest = tuplehash->tuple.out.h_dest;
+ xmit.source = tuplehash->tuple.out.h_source;
break;
default:
WARN_ON_ONCE(1);
- ret = NF_DROP;
- break;
+ return NF_DROP;
}
- return ret;
+ return nf_flow_queue_xmit(state->net, skb, &xmit);
}
EXPORT_SYMBOL_GPL(nf_flow_offload_ipv6_hook);
diff --git a/net/netfilter/nf_flow_table_path.c b/net/netfilter/nf_flow_table_path.c
index 159aa5c8da60..15c042cab9fb 100644
--- a/net/netfilter/nf_flow_table_path.c
+++ b/net/netfilter/nf_flow_table_path.c
@@ -204,11 +204,11 @@ static void nft_dev_forward_path(struct nf_flow_route *route,
}
route->tuple[!dir].in.num_encaps = info.num_encaps;
route->tuple[!dir].in.ingress_vlans = info.ingress_vlans;
+ route->tuple[dir].out.ifindex = info.outdev->ifindex;
if (info.xmit_type == FLOW_OFFLOAD_XMIT_DIRECT) {
memcpy(route->tuple[dir].out.h_source, info.h_source, ETH_ALEN);
memcpy(route->tuple[dir].out.h_dest, info.h_dest, ETH_ALEN);
- route->tuple[dir].out.ifindex = info.outdev->ifindex;
route->tuple[dir].out.hw_ifindex = info.hw_outdev->ifindex;
route->tuple[dir].xmit_type = info.xmit_type;
}
@@ -256,11 +256,10 @@ int nft_flow_route(const struct nft_pktinfo *pkt, const struct nf_conn *ct,
nft_default_forward_path(route, this_dst, dir);
nft_default_forward_path(route, other_dst, !dir);
- if (route->tuple[dir].xmit_type == FLOW_OFFLOAD_XMIT_NEIGH &&
- route->tuple[!dir].xmit_type == FLOW_OFFLOAD_XMIT_NEIGH) {
+ if (route->tuple[dir].xmit_type == FLOW_OFFLOAD_XMIT_NEIGH)
nft_dev_forward_path(route, ct, dir, ft);
+ if (route->tuple[!dir].xmit_type == FLOW_OFFLOAD_XMIT_NEIGH)
nft_dev_forward_path(route, ct, !dir, ft);
- }
return 0;
}
--
2.47.3
next prev parent reply other threads:[~2025-11-25 22:33 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-11-25 22:32 [PATCH net-next 00/16] Netfilter updates for net-next Pablo Neira Ayuso
2025-11-25 22:32 ` [PATCH net-next 01/16] netfilter: flowtable: move path discovery infrastructure to its own file Pablo Neira Ayuso
2025-11-25 22:32 ` Pablo Neira Ayuso [this message]
2025-11-26 4:20 ` [PATCH net-next 02/16] netfilter: flowtable: consolidate xmit path Eric Dumazet
2025-11-25 22:32 ` [PATCH net-next 03/16] netfilter: flowtable: inline vlan encapsulation in " Pablo Neira Ayuso
2025-11-25 22:33 ` [PATCH net-next 04/16] netfilter: flowtable: inline pppoe " Pablo Neira Ayuso
2025-11-26 3:33 ` Qingfang Deng
2025-11-25 22:33 ` [PATCH net-next 05/16] netfilter: flowtable: remove hw_ifidx Pablo Neira Ayuso
2025-11-25 22:33 ` [PATCH net-next 06/16] netfilter: flowtable: use tuple address to calculate next hop Pablo Neira Ayuso
2025-11-25 22:33 ` [PATCH net-next 07/16] netfilter: flowtable: Add IPIP rx sw acceleration Pablo Neira Ayuso
2025-11-25 22:33 ` [PATCH net-next 08/16] netfilter: flowtable: Add IPIP tx " Pablo Neira Ayuso
2025-11-25 22:33 ` [PATCH net-next 09/16] selftests: netfilter: nft_flowtable.sh: Add IPIP flowtable selftest Pablo Neira Ayuso
2025-11-25 22:33 ` [PATCH net-next 10/16] netfilter: nf_conncount: rework API to use sk_buff directly Pablo Neira Ayuso
2025-11-25 22:33 ` [PATCH net-next 11/16] netfilter: nf_conncount: make nf_conncount_gc_list() to disable BH Pablo Neira Ayuso
2025-11-25 22:33 ` [PATCH net-next 12/16] netfilter: nft_connlimit: update the count if add was skipped Pablo Neira Ayuso
2025-11-25 22:33 ` [PATCH net-next 13/16] netfilter: nft_connlimit: add support to object update operation Pablo Neira Ayuso
2025-11-25 22:33 ` [PATCH net-next 14/16] selftests: netfilter: nft_flowtable.sh: Add the capability to send IPv6 TCP traffic Pablo Neira Ayuso
2025-11-25 22:33 ` [PATCH net-next 15/16] netfilter: ip6t_srh: fix UAPI kernel-doc comments format Pablo Neira Ayuso
2025-11-25 22:33 ` [PATCH net-next 16/16] netfilter: nf_tables: improve UAPI kernel-doc comments Pablo Neira Ayuso
-- strict thread matches above, loose matches on Subject: below --
2025-11-26 20:55 [PATCH net-next,v2 00/16] Netfilter updates for net-next Pablo Neira Ayuso
2025-11-26 20:55 ` [PATCH net-next 02/16] netfilter: flowtable: consolidate xmit path Pablo Neira Ayuso
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20251125223312.1246891-3-pablo@netfilter.org \
--to=pablo@netfilter.org \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=fw@strlen.de \
--cc=horms@kernel.org \
--cc=kuba@kernel.org \
--cc=netdev@vger.kernel.org \
--cc=netfilter-devel@vger.kernel.org \
--cc=pabeni@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.