net: ip6_tunnel: use tunnel parameters for fill_forward_path route lookup

Reuse the flowi6 template t->fl.u.ip6 built by ip6_tnl_link_config() in
ip6_tnl_fill_forward_path(), aligning the fast-path route lookup with
the slow path in ipxip6_tnl_xmit(). This automatically inherits the
correct conditional FLOWLABEL masking based on the
IP6_TNL_F_USE_ORIG_FLOWLABEL flag.

Return -EOPNOTSUPP when IP6_TNL_F_USE_ORIG_TCLASS,
IP6_TNL_F_USE_ORIG_FLOWLABEL or IP6_TNL_F_USE_ORIG_FWMARK is set,
or for collect_md tunnels, since fill_forward_path has no access to
the original skb and cannot recover the per-packet traffic class,
flowlabel, mark or tunnel destination needed for the route lookup.

Reviewed-by: David Ahern <dsahern@kernel.org>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Link: https://patch.msgid.link/20260724-ip6ip6-route-lookup-fill_forward_path-v3-1-7b7991538614@kernel.org
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
Lorenzo Bianconi
2026-07-24 09:25:00 +02:00
committed by Paolo Abeni
parent af2e7bf983
commit b515dc5479

View File

@@ -1845,24 +1845,30 @@ static int ip6_tnl_fill_forward_path(struct net_device_path_ctx *ctx,
struct net_device_path *path)
{
struct ip6_tnl *t = netdev_priv(ctx->dev);
struct flowi6 fl6 = {
.daddr = t->parms.raddr,
};
struct dst_entry *dst;
struct flowi6 fl6;
int err;
if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT)) {
/* encaplimit option is currently not supported is
* sw-acceleration path.
*/
if (t->parms.flags & (IP6_TNL_F_USE_ORIG_TCLASS |
IP6_TNL_F_USE_ORIG_FLOWLABEL |
IP6_TNL_F_USE_ORIG_FWMARK))
return -EOPNOTSUPP;
}
if (t->parms.collect_md)
return -EOPNOTSUPP;
if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT))
return -EOPNOTSUPP;
memcpy(&fl6, &t->fl.u.ip6, sizeof(fl6));
fl6.flowi6_mark = t->parms.fwmark;
fl6.flowi6_proto = 0;
dst = ip6_route_output(dev_net(ctx->dev), NULL, &fl6);
if (!dst->error) {
path->type = DEV_PATH_TUN;
path->tun.src_v6 = t->parms.laddr;
path->tun.dst_v6 = t->parms.raddr;
path->tun.src_v6 = fl6.saddr;
path->tun.dst_v6 = fl6.daddr;
path->tun.l3_proto = IPPROTO_IPV6;
path->dev = ctx->dev;
ctx->dev = dst->dev;