summaryrefslogtreecommitdiff
path: root/net/core
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2026-07-28 18:30:48 +0200
committerPablo Neira Ayuso <pablo@netfilter.org>2026-07-31 14:47:03 +0200
commit0ad8404e776698de4dac5cc0df3be68d344e741c (patch)
tree71f6b42bf1633e76efc10c976e156fb2b596cb6f /net/core
parent5deda60c56eeeab25beb10cf4d48e07587076b11 (diff)
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>
Diffstat (limited to 'net/core')
-rw-r--r--net/core/dev.c36
1 files changed, 31 insertions, 5 deletions
diff --git a/net/core/dev.c b/net/core/dev.c
index 429a55fff667..e50ed677de72 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -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);