net: pass net_device_path_ctx to dev_fill_forward_path()

Refactor dev_fill_forward_path() to take a struct net_device_path_ctx
pointer instead of a (dev, daddr) pair, so the caller can build and
populate the context up front and keep it after the forward path walk.

This allows additional fields (e.g. vlan and ether_type) to be carried
in the context and shared with ndo_fill_forward_path implementations,
instead of being reconstructed on the stack inside the core helper.

Update the mtk_ppe_offload, airoha_ppe and nf_flow_table_path callers to
allocate and fill the context before invoking dev_fill_forward_path().
The network topology resolution behaviour is unchanged.

This is a preliminary patch to enable HW flowtable offload for IPv4
over IPv6 tunnels.

Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi@oss.qualcomm.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
Lorenzo Bianconi 2026-08-06 23:09:03 +02:00 committed by Pablo Neira Ayuso
parent 5546b082fa
commit 95133a4168
5 changed files with 26 additions and 15 deletions

View File

@ -283,14 +283,19 @@ static int airoha_ppe_get_wdma_info(struct net_device *dev, const u8 *addr,
struct airoha_wdma_info *info)
{
struct net_device_path_stack stack;
struct net_device_path_ctx ctx = {
.dev = dev,
};
struct net_device_path *path;
int err;
if (!dev)
return -ENODEV;
ether_addr_copy(ctx.daddr, addr);
rcu_read_lock();
err = dev_fill_forward_path(dev, addr, &stack);
err = dev_fill_forward_path(&ctx, &stack);
rcu_read_unlock();
if (err)
return err;

View File

@ -92,6 +92,9 @@ static int
mtk_flow_get_wdma_info(struct net_device *dev, const u8 *addr, struct mtk_wdma_info *info)
{
struct net_device_path_stack stack;
struct net_device_path_ctx ctx = {
.dev = dev,
};
struct net_device_path *path;
int err;
@ -101,8 +104,10 @@ mtk_flow_get_wdma_info(struct net_device *dev, const u8 *addr, struct mtk_wdma_i
if (!IS_ENABLED(CONFIG_NET_MEDIATEK_SOC_WED))
return -1;
ether_addr_copy(ctx.daddr, addr);
rcu_read_lock();
err = dev_fill_forward_path(dev, addr, &stack);
err = dev_fill_forward_path(&ctx, &stack);
rcu_read_unlock();
if (err)
return err;

View File

@ -3428,7 +3428,7 @@ void dev_remove_offload(struct packet_offload *po);
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,
int dev_fill_forward_path(struct net_device_path_ctx *ctx,
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);

View File

@ -769,35 +769,31 @@ void dev_fill_forward_path_release(struct net_device_path_stack *stack)
}
EXPORT_SYMBOL_GPL(dev_fill_forward_path_release);
int dev_fill_forward_path(const struct net_device *dev, const u8 *daddr,
int dev_fill_forward_path(struct net_device_path_ctx *ctx,
struct net_device_path_stack *stack)
{
const struct net_device *last_dev;
struct net_device_path_ctx ctx = {
.dev = dev,
};
struct net_device_path *path;
int ret = 0;
memcpy(ctx.daddr, daddr, sizeof(ctx.daddr));
stack->num_paths = 0;
while (ctx.dev && ctx.dev->netdev_ops->ndo_fill_forward_path) {
last_dev = ctx.dev;
while (ctx->dev && ctx->dev->netdev_ops->ndo_fill_forward_path) {
last_dev = ctx->dev;
path = dev_fwd_path(stack);
if (!path)
goto err_out;
memset(path, 0, sizeof(struct net_device_path));
ret = ctx.dev->netdev_ops->ndo_fill_forward_path(&ctx, path);
ret = ctx->dev->netdev_ops->ndo_fill_forward_path(ctx, path);
if (ret < 0)
goto err_out;
stack->num_paths++;
if (WARN_ON_ONCE(last_dev == ctx.dev))
if (WARN_ON_ONCE(last_dev == ctx->dev))
goto err_out;
}
if (!ctx.dev)
if (!ctx->dev)
return ret;
path = dev_fwd_path(stack);
@ -805,7 +801,7 @@ int dev_fill_forward_path(const struct net_device *dev, const u8 *daddr,
goto err_out;
path->type = DEV_PATH_ETHERNET;
path->dev = ctx.dev;
path->dev = ctx->dev;
stack->num_paths++;
return 0;

View File

@ -49,6 +49,9 @@ static int nft_dev_fill_forward_path(const struct dst_entry *dst_cache,
{
const void *daddr = &ct->tuplehash[!dir].tuple.src.u3;
struct net_device *dev = dst_cache->dev;
struct net_device_path_ctx ctx = {
.dev = dev,
};
struct neighbour *n;
u8 nud_state;
@ -71,7 +74,9 @@ static int nft_dev_fill_forward_path(const struct dst_entry *dst_cache,
return -1;
out:
return dev_fill_forward_path(dev, ha, stack);
ether_addr_copy(ctx.daddr, ha);
return dev_fill_forward_path(&ctx, stack);
}
struct nft_forward_info {