net: pass dst via net_device_path in dev_fill_forward_path()

Add dst_entry to tunnel device path, this will allow us to remove
a duplicated route lookup.

This is a preparation patch to retrieve the tunnel route directly
from the .fill_forward_path. This new dst_entry in the tunnel will be
used by a follow up patch.

Since dst_release() works fine on NULL interface, this is still
noop until the flowtable starts using this.

Add a new dev_fill_forward_path_release() function to drop the refcount
on the tunnel device route and use it in case of error out. Export it so
to drop the refcount on the tunnel route at a later stage.

Adjust existing drivers that recycle dev_fill_forward_path() to call
dev_fill_forward_path_release() for safety reasons.

Acked-by: Lorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
Pablo Neira Ayuso
2026-07-28 18:30:48 +02:00
parent 5deda60c56
commit 0ad8404e77
4 changed files with 47 additions and 11 deletions

View File

@@ -296,14 +296,18 @@ static int airoha_ppe_get_wdma_info(struct net_device *dev, const u8 *addr,
return err;
path = &stack.path[stack.num_paths - 1];
if (path->type != DEV_PATH_MTK_WDMA)
return -EINVAL;
if (path->type != DEV_PATH_MTK_WDMA) {
err = -EINVAL;
goto err_out;
}
info->idx = path->mtk_wdma.wdma_idx;
info->bss = path->mtk_wdma.bss;
info->wcid = path->mtk_wdma.wcid;
err_out:
dev_fill_forward_path_release(&stack);
return 0;
return err;
}
static int airoha_get_dsa_port(struct net_device **dev)

View File

@@ -108,16 +108,20 @@ mtk_flow_get_wdma_info(struct net_device *dev, const u8 *addr, struct mtk_wdma_i
return err;
path = &stack.path[stack.num_paths - 1];
if (path->type != DEV_PATH_MTK_WDMA)
return -1;
if (path->type != DEV_PATH_MTK_WDMA) {
err = -EINVAL;
goto err_out;
}
info->wdma_idx = path->mtk_wdma.wdma_idx;
info->queue = path->mtk_wdma.queue;
info->bss = path->mtk_wdma.bss;
info->wcid = path->mtk_wdma.wcid;
info->amsdu = path->mtk_wdma.amsdu;
err_out:
dev_fill_forward_path_release(&stack);
return 0;
return err;
}

View File

@@ -892,6 +892,7 @@ struct net_device_path {
u8 h_dest[ETH_ALEN];
} encap;
struct {
struct dst_entry *dst;
union {
struct in_addr src_v4;
struct in6_addr src_v6;
@@ -3427,6 +3428,7 @@ int dev_get_iflink(const struct net_device *dev);
int dev_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb);
int dev_fill_forward_path(const struct net_device *dev, const u8 *daddr,
struct net_device_path_stack *stack);
void dev_fill_forward_path_release(struct net_device_path_stack *stack);
struct net_device *dev_get_by_name(struct net *net, const char *name);
struct net_device *dev_get_by_name_rcu(struct net *net, const char *name);
struct net_device *__dev_get_by_name(struct net *net, const char *name);

View File

@@ -748,6 +748,27 @@ static struct net_device_path *dev_fwd_path(struct net_device_path_stack *stack)
return &stack->path[stack->num_paths];
}
void dev_fill_forward_path_release(struct net_device_path_stack *stack)
{
struct net_device_path *path;
int k;
if (stack->num_paths == 0)
return;
for (k = stack->num_paths - 1; k >= 0; k--) {
path = &stack->path[k];
switch (path->type) {
case DEV_PATH_TUN:
dst_release(path->tun.dst);
break;
default:
break;
}
}
}
EXPORT_SYMBOL_GPL(dev_fill_forward_path_release);
int dev_fill_forward_path(const struct net_device *dev, const u8 *daddr,
struct net_device_path_stack *stack)
{
@@ -764,16 +785,16 @@ int dev_fill_forward_path(const struct net_device *dev, const u8 *daddr,
last_dev = ctx.dev;
path = dev_fwd_path(stack);
if (!path)
return -1;
goto err_out;
memset(path, 0, sizeof(struct net_device_path));
ret = ctx.dev->netdev_ops->ndo_fill_forward_path(&ctx, path);
if (ret < 0)
return -1;
goto err_out;
stack->num_paths++;
if (WARN_ON_ONCE(last_dev == ctx.dev))
return -1;
goto err_out;
}
if (!ctx.dev)
@@ -781,12 +802,17 @@ int dev_fill_forward_path(const struct net_device *dev, const u8 *daddr,
path = dev_fwd_path(stack);
if (!path)
return -1;
goto err_out;
path->type = DEV_PATH_ETHERNET;
path->dev = ctx.dev;
stack->num_paths++;
return ret;
return 0;
err_out:
dev_fill_forward_path_release(stack);
return -1;
}
EXPORT_SYMBOL_GPL(dev_fill_forward_path);