* [PATCH nf-next 1/7] net: pass net_device_path_ctx to dev_fill_forward_path()
2026-08-06 22:35 [PATCH nf-next 0/7] flowtable preparation for IPv4 over IPv6 and SIT Pablo Neira Ayuso
@ 2026-08-06 22:35 ` Pablo Neira Ayuso
2026-08-06 22:35 ` [PATCH nf-next 2/7] net: netfilter: add ether_type to net_device_path_ctx and use it Pablo Neira Ayuso
` (5 subsequent siblings)
6 siblings, 0 replies; 14+ messages in thread
From: Pablo Neira Ayuso @ 2026-08-06 22:35 UTC (permalink / raw)
To: netfilter-devel; +Cc: lorenzo.bianconi, lorenzo
From: Lorenzo Bianconi <lorenzo.bianconi@oss.qualcomm.com>
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>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
v2: Just a rebase on top of current nf-next.git
drivers/net/ethernet/airoha/airoha_ppe.c | 7 ++++++-
.../net/ethernet/mediatek/mtk_ppe_offload.c | 7 ++++++-
include/linux/netdevice.h | 2 +-
net/core/dev.c | 18 +++++++-----------
net/netfilter/nf_flow_table_path.c | 7 ++++++-
5 files changed, 26 insertions(+), 15 deletions(-)
diff --git a/drivers/net/ethernet/airoha/airoha_ppe.c b/drivers/net/ethernet/airoha/airoha_ppe.c
index a03af9750573..92611802801e 100644
--- a/drivers/net/ethernet/airoha/airoha_ppe.c
+++ b/drivers/net/ethernet/airoha/airoha_ppe.c
@@ -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;
diff --git a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
index 771d9118f94a..99b28aaa7cc4 100644
--- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
+++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
@@ -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;
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 62cfad7e6b79..4319b949f405 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -3426,7 +3426,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);
diff --git a/net/core/dev.c b/net/core/dev.c
index e50ed677de72..13dfd2113a5a 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -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;
diff --git a/net/netfilter/nf_flow_table_path.c b/net/netfilter/nf_flow_table_path.c
index 56219b02e122..0cbde535b8ba 100644
--- a/net/netfilter/nf_flow_table_path.c
+++ b/net/netfilter/nf_flow_table_path.c
@@ -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 {
--
2.47.3
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH nf-next 2/7] net: netfilter: add ether_type to net_device_path_ctx and use it
2026-08-06 22:35 [PATCH nf-next 0/7] flowtable preparation for IPv4 over IPv6 and SIT Pablo Neira Ayuso
2026-08-06 22:35 ` [PATCH nf-next 1/7] net: pass net_device_path_ctx to dev_fill_forward_path() Pablo Neira Ayuso
@ 2026-08-06 22:35 ` Pablo Neira Ayuso
2026-08-07 9:00 ` Lorenzo Bianconi
2026-08-06 22:35 ` [PATCH nf-next 3/7] netfilter: flowtable: rename tun.l3_proto to tun.inner_proto Pablo Neira Ayuso
` (4 subsequent siblings)
6 siblings, 1 reply; 14+ messages in thread
From: Pablo Neira Ayuso @ 2026-08-06 22:35 UTC (permalink / raw)
To: netfilter-devel; +Cc: lorenzo.bianconi, lorenzo
Add an ether_type field to struct net_device_path_ctx to reject IPv4
over IPv6 and vice-versa, this is currently not support. Otherwise,
incorrect dst_entry family can be reached from datapath.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
include/linux/netdevice.h | 1 +
net/ipv4/ipip.c | 3 +++
net/ipv6/ip6_tunnel.c | 3 +++
net/netfilter/nf_flow_table_path.c | 6 ++++--
4 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 4319b949f405..d9962c50bd60 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -939,6 +939,7 @@ struct net_device_path_stack {
struct net_device_path_ctx {
const struct net_device *dev;
u8 daddr[ETH_ALEN];
+ __be16 ether_type;
int num_vlans;
struct {
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
index fb7d96f99b06..62a374079bfc 100644
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@ -360,6 +360,9 @@ static int ipip_fill_forward_path(struct net_device_path_ctx *ctx,
const struct iphdr *tiph = &tunnel->parms.iph;
struct rtable *rt;
+ if (ctx->ether_type != cpu_to_be16(ETH_P_IP))
+ return -EOPNOTSUPP;
+
if (tunnel->collect_md)
return -EOPNOTSUPP;
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index d80020bc2620..3bfaa98e7f33 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -1849,6 +1849,9 @@ static int ip6_tnl_fill_forward_path(struct net_device_path_ctx *ctx,
struct flowi6 fl6;
int err;
+ if (ctx->ether_type != cpu_to_be16(ETH_P_IPV6))
+ return -EOPNOTSUPP;
+
if (t->parms.flags & (IP6_TNL_F_USE_ORIG_TCLASS |
IP6_TNL_F_USE_ORIG_FLOWLABEL |
IP6_TNL_F_USE_ORIG_FWMARK))
diff --git a/net/netfilter/nf_flow_table_path.c b/net/netfilter/nf_flow_table_path.c
index 0cbde535b8ba..5f166da3b09b 100644
--- a/net/netfilter/nf_flow_table_path.c
+++ b/net/netfilter/nf_flow_table_path.c
@@ -44,13 +44,15 @@ static bool nft_is_valid_ether_device(const struct net_device *dev)
static int nft_dev_fill_forward_path(const struct dst_entry *dst_cache,
const struct nf_conn *ct,
- enum ip_conntrack_dir dir, u8 *ha,
+ enum ip_conntrack_dir dir,
+ u8 *ha, __be16 ether_type,
struct net_device_path_stack *stack)
{
const void *daddr = &ct->tuplehash[!dir].tuple.src.u3;
struct net_device *dev = dst_cache->dev;
struct net_device_path_ctx ctx = {
.dev = dev,
+ .ether_type = ether_type,
};
struct neighbour *n;
u8 nud_state;
@@ -228,7 +230,7 @@ static int nft_dev_forward_path(const struct nft_pktinfo *pkt,
unsigned char ha[ETH_ALEN];
int i;
- if (nft_dev_fill_forward_path(dst, ct, dir, ha, &stack) < 0 ||
+ if (nft_dev_fill_forward_path(dst, ct, dir, ha, pkt->ethertype, &stack) < 0 ||
nft_dev_path_info(&stack, &info, ha, ft) < 0)
return -ENOENT;
--
2.47.3
^ permalink raw reply related [flat|nested] 14+ messages in thread* Re: [PATCH nf-next 2/7] net: netfilter: add ether_type to net_device_path_ctx and use it
2026-08-06 22:35 ` [PATCH nf-next 2/7] net: netfilter: add ether_type to net_device_path_ctx and use it Pablo Neira Ayuso
@ 2026-08-07 9:00 ` Lorenzo Bianconi
0 siblings, 0 replies; 14+ messages in thread
From: Lorenzo Bianconi @ 2026-08-07 9:00 UTC (permalink / raw)
To: Pablo Neira Ayuso; +Cc: netfilter-devel, lorenzo.bianconi
[-- Attachment #1: Type: text/plain, Size: 3210 bytes --]
> Add an ether_type field to struct net_device_path_ctx to reject IPv4
> over IPv6 and vice-versa, this is currently not support. Otherwise,
> incorrect dst_entry family can be reached from datapath.
>
> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Acked-by: Lorenzo Bianconi <lorenzo@kernel.org>
> ---
> include/linux/netdevice.h | 1 +
> net/ipv4/ipip.c | 3 +++
> net/ipv6/ip6_tunnel.c | 3 +++
> net/netfilter/nf_flow_table_path.c | 6 ++++--
> 4 files changed, 11 insertions(+), 2 deletions(-)
>
> diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
> index 4319b949f405..d9962c50bd60 100644
> --- a/include/linux/netdevice.h
> +++ b/include/linux/netdevice.h
> @@ -939,6 +939,7 @@ struct net_device_path_stack {
> struct net_device_path_ctx {
> const struct net_device *dev;
> u8 daddr[ETH_ALEN];
> + __be16 ether_type;
>
> int num_vlans;
> struct {
> diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
> index fb7d96f99b06..62a374079bfc 100644
> --- a/net/ipv4/ipip.c
> +++ b/net/ipv4/ipip.c
> @@ -360,6 +360,9 @@ static int ipip_fill_forward_path(struct net_device_path_ctx *ctx,
> const struct iphdr *tiph = &tunnel->parms.iph;
> struct rtable *rt;
>
> + if (ctx->ether_type != cpu_to_be16(ETH_P_IP))
> + return -EOPNOTSUPP;
> +
> if (tunnel->collect_md)
> return -EOPNOTSUPP;
>
> diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
> index d80020bc2620..3bfaa98e7f33 100644
> --- a/net/ipv6/ip6_tunnel.c
> +++ b/net/ipv6/ip6_tunnel.c
> @@ -1849,6 +1849,9 @@ static int ip6_tnl_fill_forward_path(struct net_device_path_ctx *ctx,
> struct flowi6 fl6;
> int err;
>
> + if (ctx->ether_type != cpu_to_be16(ETH_P_IPV6))
> + return -EOPNOTSUPP;
> +
> if (t->parms.flags & (IP6_TNL_F_USE_ORIG_TCLASS |
> IP6_TNL_F_USE_ORIG_FLOWLABEL |
> IP6_TNL_F_USE_ORIG_FWMARK))
> diff --git a/net/netfilter/nf_flow_table_path.c b/net/netfilter/nf_flow_table_path.c
> index 0cbde535b8ba..5f166da3b09b 100644
> --- a/net/netfilter/nf_flow_table_path.c
> +++ b/net/netfilter/nf_flow_table_path.c
> @@ -44,13 +44,15 @@ static bool nft_is_valid_ether_device(const struct net_device *dev)
>
> static int nft_dev_fill_forward_path(const struct dst_entry *dst_cache,
> const struct nf_conn *ct,
> - enum ip_conntrack_dir dir, u8 *ha,
> + enum ip_conntrack_dir dir,
> + u8 *ha, __be16 ether_type,
> struct net_device_path_stack *stack)
> {
> const void *daddr = &ct->tuplehash[!dir].tuple.src.u3;
> struct net_device *dev = dst_cache->dev;
> struct net_device_path_ctx ctx = {
> .dev = dev,
> + .ether_type = ether_type,
> };
> struct neighbour *n;
> u8 nud_state;
> @@ -228,7 +230,7 @@ static int nft_dev_forward_path(const struct nft_pktinfo *pkt,
> unsigned char ha[ETH_ALEN];
> int i;
>
> - if (nft_dev_fill_forward_path(dst, ct, dir, ha, &stack) < 0 ||
> + if (nft_dev_fill_forward_path(dst, ct, dir, ha, pkt->ethertype, &stack) < 0 ||
> nft_dev_path_info(&stack, &info, ha, ft) < 0)
> return -ENOENT;
>
> --
> 2.47.3
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH nf-next 3/7] netfilter: flowtable: rename tun.l3_proto to tun.inner_proto
2026-08-06 22:35 [PATCH nf-next 0/7] flowtable preparation for IPv4 over IPv6 and SIT Pablo Neira Ayuso
2026-08-06 22:35 ` [PATCH nf-next 1/7] net: pass net_device_path_ctx to dev_fill_forward_path() Pablo Neira Ayuso
2026-08-06 22:35 ` [PATCH nf-next 2/7] net: netfilter: add ether_type to net_device_path_ctx and use it Pablo Neira Ayuso
@ 2026-08-06 22:35 ` Pablo Neira Ayuso
2026-08-07 9:01 ` Lorenzo Bianconi
2026-08-06 22:35 ` [PATCH nf-next 4/7] netfilter: flowtable: rename ctx.tun.proto to ctx.tun.inner_proto Pablo Neira Ayuso
` (3 subsequent siblings)
6 siblings, 1 reply; 14+ messages in thread
From: Pablo Neira Ayuso @ 2026-08-06 22:35 UTC (permalink / raw)
To: netfilter-devel; +Cc: lorenzo.bianconi, lorenzo
This field refers to the inner protocol that is encapsulated by the
tunnel header, just a comestic change. No functional changes are
expected.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
include/linux/netdevice.h | 2 +-
include/net/netfilter/nf_flow_table.h | 2 +-
net/ipv4/ipip.c | 2 +-
net/ipv6/ip6_tunnel.c | 2 +-
net/netfilter/nf_flow_table_ip.c | 6 +++---
net/netfilter/nf_flow_table_path.c | 4 ++--
6 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index d9962c50bd60..68ccb5868070 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -902,7 +902,7 @@ struct net_device_path {
struct in6_addr dst_v6;
};
- u8 l3_proto;
+ u8 inner_proto;
} tun;
struct {
enum {
diff --git a/include/net/netfilter/nf_flow_table.h b/include/net/netfilter/nf_flow_table.h
index a090ec3ffef2..f2e2771f188f 100644
--- a/include/net/netfilter/nf_flow_table.h
+++ b/include/net/netfilter/nf_flow_table.h
@@ -117,7 +117,7 @@ struct flow_offload_tunnel {
struct in6_addr dst_v6;
};
- u8 l3_proto;
+ u8 inner_proto;
};
struct flow_offload_tuple {
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
index 62a374079bfc..1630325c77d3 100644
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@ -378,7 +378,7 @@ static int ipip_fill_forward_path(struct net_device_path_ctx *ctx,
path->type = DEV_PATH_TUN;
path->tun.src_v4.s_addr = tiph->saddr;
path->tun.dst_v4.s_addr = tiph->daddr;
- path->tun.l3_proto = IPPROTO_IPIP;
+ path->tun.inner_proto = IPPROTO_IPIP;
path->tun.dst = &rt->dst;
path->dev = ctx->dev;
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index 3bfaa98e7f33..7b54919232ba 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -1872,7 +1872,7 @@ static int ip6_tnl_fill_forward_path(struct net_device_path_ctx *ctx,
path->type = DEV_PATH_TUN;
path->tun.src_v6 = fl6.saddr;
path->tun.dst_v6 = fl6.daddr;
- path->tun.l3_proto = IPPROTO_IPV6;
+ path->tun.inner_proto = IPPROTO_IPV6;
path->tun.dst = dst;
path->dev = ctx->dev;
ctx->dev = dst->dev;
diff --git a/net/netfilter/nf_flow_table_ip.c b/net/netfilter/nf_flow_table_ip.c
index 0b314b10e705..e1aa01763f33 100644
--- a/net/netfilter/nf_flow_table_ip.c
+++ b/net/netfilter/nf_flow_table_ip.c
@@ -197,7 +197,7 @@ static void nf_flow_tuple_encap(struct nf_flowtable_ctx *ctx,
if (ctx->tun.proto == IPPROTO_IPIP) {
tuple->tun.dst_v4.s_addr = iph->daddr;
tuple->tun.src_v4.s_addr = iph->saddr;
- tuple->tun.l3_proto = IPPROTO_IPIP;
+ tuple->tun.inner_proto = IPPROTO_IPIP;
}
break;
case htons(ETH_P_IPV6):
@@ -205,7 +205,7 @@ static void nf_flow_tuple_encap(struct nf_flowtable_ctx *ctx,
if (ctx->tun.proto == IPPROTO_IPV6) {
tuple->tun.dst_v6 = ip6h->daddr;
tuple->tun.src_v6 = ip6h->saddr;
- tuple->tun.l3_proto = IPPROTO_IPV6;
+ tuple->tun.inner_proto = IPPROTO_IPV6;
}
break;
default:
@@ -611,7 +611,7 @@ static int nf_flow_tunnel_ipip_push(struct net *net, struct sk_buff *skb,
iph->version = 4;
iph->ihl = sizeof(*iph) >> 2;
iph->frag_off = ip_mtu_locked(&rt->dst) ? 0 : frag_off;
- iph->protocol = tuple->tun.l3_proto;
+ iph->protocol = tuple->tun.inner_proto;
iph->tos = tos;
iph->daddr = tuple->tun.src_v4.s_addr;
iph->saddr = tuple->tun.dst_v4.s_addr;
diff --git a/net/netfilter/nf_flow_table_path.c b/net/netfilter/nf_flow_table_path.c
index 5f166da3b09b..1e55644f2edb 100644
--- a/net/netfilter/nf_flow_table_path.c
+++ b/net/netfilter/nf_flow_table_path.c
@@ -133,7 +133,7 @@ static int nft_dev_path_info(struct net_device_path_stack *stack,
info->tun.src_v6 = path->tun.src_v6;
info->tun.dst_v6 = path->tun.dst_v6;
- info->tun.l3_proto = path->tun.l3_proto;
+ info->tun.inner_proto = path->tun.inner_proto;
info->tun_dst = path->tun.dst;
info->num_tuns++;
} else {
@@ -245,7 +245,7 @@ static int nft_dev_forward_path(const struct nft_pktinfo *pkt,
if (info.num_tuns) {
route->tuple[!dir].in.tun.src_v6 = info.tun.dst_v6;
route->tuple[!dir].in.tun.dst_v6 = info.tun.src_v6;
- route->tuple[!dir].in.tun.l3_proto = info.tun.l3_proto;
+ route->tuple[!dir].in.tun.inner_proto = info.tun.inner_proto;
route->tuple[!dir].in.num_tuns = info.num_tuns;
dst_release(route->tuple[dir].dst);
route->tuple[dir].dst = info.tun_dst;
--
2.47.3
^ permalink raw reply related [flat|nested] 14+ messages in thread* Re: [PATCH nf-next 3/7] netfilter: flowtable: rename tun.l3_proto to tun.inner_proto
2026-08-06 22:35 ` [PATCH nf-next 3/7] netfilter: flowtable: rename tun.l3_proto to tun.inner_proto Pablo Neira Ayuso
@ 2026-08-07 9:01 ` Lorenzo Bianconi
0 siblings, 0 replies; 14+ messages in thread
From: Lorenzo Bianconi @ 2026-08-07 9:01 UTC (permalink / raw)
To: Pablo Neira Ayuso; +Cc: netfilter-devel, lorenzo.bianconi
[-- Attachment #1: Type: text/plain, Size: 4859 bytes --]
> This field refers to the inner protocol that is encapsulated by the
> tunnel header, just a comestic change. No functional changes are
> expected.
>
> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Acked-by: Lorenzo Bianconi <lorenzo@kernel.org>
> ---
> include/linux/netdevice.h | 2 +-
> include/net/netfilter/nf_flow_table.h | 2 +-
> net/ipv4/ipip.c | 2 +-
> net/ipv6/ip6_tunnel.c | 2 +-
> net/netfilter/nf_flow_table_ip.c | 6 +++---
> net/netfilter/nf_flow_table_path.c | 4 ++--
> 6 files changed, 9 insertions(+), 9 deletions(-)
>
> diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
> index d9962c50bd60..68ccb5868070 100644
> --- a/include/linux/netdevice.h
> +++ b/include/linux/netdevice.h
> @@ -902,7 +902,7 @@ struct net_device_path {
> struct in6_addr dst_v6;
> };
>
> - u8 l3_proto;
> + u8 inner_proto;
> } tun;
> struct {
> enum {
> diff --git a/include/net/netfilter/nf_flow_table.h b/include/net/netfilter/nf_flow_table.h
> index a090ec3ffef2..f2e2771f188f 100644
> --- a/include/net/netfilter/nf_flow_table.h
> +++ b/include/net/netfilter/nf_flow_table.h
> @@ -117,7 +117,7 @@ struct flow_offload_tunnel {
> struct in6_addr dst_v6;
> };
>
> - u8 l3_proto;
> + u8 inner_proto;
> };
>
> struct flow_offload_tuple {
> diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
> index 62a374079bfc..1630325c77d3 100644
> --- a/net/ipv4/ipip.c
> +++ b/net/ipv4/ipip.c
> @@ -378,7 +378,7 @@ static int ipip_fill_forward_path(struct net_device_path_ctx *ctx,
> path->type = DEV_PATH_TUN;
> path->tun.src_v4.s_addr = tiph->saddr;
> path->tun.dst_v4.s_addr = tiph->daddr;
> - path->tun.l3_proto = IPPROTO_IPIP;
> + path->tun.inner_proto = IPPROTO_IPIP;
> path->tun.dst = &rt->dst;
> path->dev = ctx->dev;
>
> diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
> index 3bfaa98e7f33..7b54919232ba 100644
> --- a/net/ipv6/ip6_tunnel.c
> +++ b/net/ipv6/ip6_tunnel.c
> @@ -1872,7 +1872,7 @@ static int ip6_tnl_fill_forward_path(struct net_device_path_ctx *ctx,
> path->type = DEV_PATH_TUN;
> path->tun.src_v6 = fl6.saddr;
> path->tun.dst_v6 = fl6.daddr;
> - path->tun.l3_proto = IPPROTO_IPV6;
> + path->tun.inner_proto = IPPROTO_IPV6;
> path->tun.dst = dst;
> path->dev = ctx->dev;
> ctx->dev = dst->dev;
> diff --git a/net/netfilter/nf_flow_table_ip.c b/net/netfilter/nf_flow_table_ip.c
> index 0b314b10e705..e1aa01763f33 100644
> --- a/net/netfilter/nf_flow_table_ip.c
> +++ b/net/netfilter/nf_flow_table_ip.c
> @@ -197,7 +197,7 @@ static void nf_flow_tuple_encap(struct nf_flowtable_ctx *ctx,
> if (ctx->tun.proto == IPPROTO_IPIP) {
> tuple->tun.dst_v4.s_addr = iph->daddr;
> tuple->tun.src_v4.s_addr = iph->saddr;
> - tuple->tun.l3_proto = IPPROTO_IPIP;
> + tuple->tun.inner_proto = IPPROTO_IPIP;
> }
> break;
> case htons(ETH_P_IPV6):
> @@ -205,7 +205,7 @@ static void nf_flow_tuple_encap(struct nf_flowtable_ctx *ctx,
> if (ctx->tun.proto == IPPROTO_IPV6) {
> tuple->tun.dst_v6 = ip6h->daddr;
> tuple->tun.src_v6 = ip6h->saddr;
> - tuple->tun.l3_proto = IPPROTO_IPV6;
> + tuple->tun.inner_proto = IPPROTO_IPV6;
> }
> break;
> default:
> @@ -611,7 +611,7 @@ static int nf_flow_tunnel_ipip_push(struct net *net, struct sk_buff *skb,
> iph->version = 4;
> iph->ihl = sizeof(*iph) >> 2;
> iph->frag_off = ip_mtu_locked(&rt->dst) ? 0 : frag_off;
> - iph->protocol = tuple->tun.l3_proto;
> + iph->protocol = tuple->tun.inner_proto;
> iph->tos = tos;
> iph->daddr = tuple->tun.src_v4.s_addr;
> iph->saddr = tuple->tun.dst_v4.s_addr;
> diff --git a/net/netfilter/nf_flow_table_path.c b/net/netfilter/nf_flow_table_path.c
> index 5f166da3b09b..1e55644f2edb 100644
> --- a/net/netfilter/nf_flow_table_path.c
> +++ b/net/netfilter/nf_flow_table_path.c
> @@ -133,7 +133,7 @@ static int nft_dev_path_info(struct net_device_path_stack *stack,
>
> info->tun.src_v6 = path->tun.src_v6;
> info->tun.dst_v6 = path->tun.dst_v6;
> - info->tun.l3_proto = path->tun.l3_proto;
> + info->tun.inner_proto = path->tun.inner_proto;
> info->tun_dst = path->tun.dst;
> info->num_tuns++;
> } else {
> @@ -245,7 +245,7 @@ static int nft_dev_forward_path(const struct nft_pktinfo *pkt,
> if (info.num_tuns) {
> route->tuple[!dir].in.tun.src_v6 = info.tun.dst_v6;
> route->tuple[!dir].in.tun.dst_v6 = info.tun.src_v6;
> - route->tuple[!dir].in.tun.l3_proto = info.tun.l3_proto;
> + route->tuple[!dir].in.tun.inner_proto = info.tun.inner_proto;
> route->tuple[!dir].in.num_tuns = info.num_tuns;
> dst_release(route->tuple[dir].dst);
> route->tuple[dir].dst = info.tun_dst;
> --
> 2.47.3
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH nf-next 4/7] netfilter: flowtable: rename ctx.tun.proto to ctx.tun.inner_proto
2026-08-06 22:35 [PATCH nf-next 0/7] flowtable preparation for IPv4 over IPv6 and SIT Pablo Neira Ayuso
` (2 preceding siblings ...)
2026-08-06 22:35 ` [PATCH nf-next 3/7] netfilter: flowtable: rename tun.l3_proto to tun.inner_proto Pablo Neira Ayuso
@ 2026-08-06 22:35 ` Pablo Neira Ayuso
2026-08-07 9:02 ` Lorenzo Bianconi
2026-08-06 22:35 ` [PATCH nf-next 5/7] netfilter: flowtable: store ethertype in flowtable context Pablo Neira Ayuso
` (2 subsequent siblings)
6 siblings, 1 reply; 14+ messages in thread
From: Pablo Neira Ayuso @ 2026-08-06 22:35 UTC (permalink / raw)
To: netfilter-devel; +Cc: lorenzo.bianconi, lorenzo
For consistency with the tun.l3proto rename, use same name field.
No functional changes are intended.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
net/netfilter/nf_flow_table_ip.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/net/netfilter/nf_flow_table_ip.c b/net/netfilter/nf_flow_table_ip.c
index e1aa01763f33..ed90809b206e 100644
--- a/net/netfilter/nf_flow_table_ip.c
+++ b/net/netfilter/nf_flow_table_ip.c
@@ -153,7 +153,7 @@ struct nf_flowtable_ctx {
/* Tunnel IP header size */
u32 hdr_size;
/* IP tunnel protocol */
- u8 proto;
+ u8 inner_proto;
} tun;
};
@@ -194,7 +194,7 @@ static void nf_flow_tuple_encap(struct nf_flowtable_ctx *ctx,
switch (inner_proto) {
case htons(ETH_P_IP):
iph = (struct iphdr *)(skb_network_header(skb) + offset);
- if (ctx->tun.proto == IPPROTO_IPIP) {
+ if (ctx->tun.inner_proto == IPPROTO_IPIP) {
tuple->tun.dst_v4.s_addr = iph->daddr;
tuple->tun.src_v4.s_addr = iph->saddr;
tuple->tun.inner_proto = IPPROTO_IPIP;
@@ -202,7 +202,7 @@ static void nf_flow_tuple_encap(struct nf_flowtable_ctx *ctx,
break;
case htons(ETH_P_IPV6):
ip6h = (struct ipv6hdr *)(skb_network_header(skb) + offset);
- if (ctx->tun.proto == IPPROTO_IPV6) {
+ if (ctx->tun.inner_proto == IPPROTO_IPV6) {
tuple->tun.dst_v6 = ip6h->daddr;
tuple->tun.src_v6 = ip6h->saddr;
tuple->tun.inner_proto = IPPROTO_IPV6;
@@ -328,7 +328,7 @@ static bool nf_flow_ip4_tunnel_proto(struct nf_flowtable_ctx *ctx,
return false;
if (iph->protocol == IPPROTO_IPIP) {
- ctx->tun.proto = iph->protocol;
+ ctx->tun.inner_proto = iph->protocol;
ctx->tun.hdr_size = size;
ctx->offset += ctx->tun.hdr_size;
}
@@ -353,7 +353,7 @@ static bool nf_flow_ip6_tunnel_proto(struct nf_flowtable_ctx *ctx,
return false;
if (ip6h->nexthdr == IPPROTO_IPV6) {
- ctx->tun.proto = ip6h->nexthdr;
+ ctx->tun.inner_proto = ip6h->nexthdr;
ctx->tun.hdr_size = sizeof(*ip6h);
ctx->offset += ctx->tun.hdr_size;
}
@@ -367,8 +367,8 @@ static bool nf_flow_ip6_tunnel_proto(struct nf_flowtable_ctx *ctx,
static void nf_flow_ip_tunnel_pop(struct nf_flowtable_ctx *ctx,
struct sk_buff *skb)
{
- if (ctx->tun.proto != IPPROTO_IPIP &&
- ctx->tun.proto != IPPROTO_IPV6)
+ if (ctx->tun.inner_proto != IPPROTO_IPIP &&
+ ctx->tun.inner_proto != IPPROTO_IPV6)
return;
skb_pull(skb, ctx->tun.hdr_size);
--
2.47.3
^ permalink raw reply related [flat|nested] 14+ messages in thread* Re: [PATCH nf-next 4/7] netfilter: flowtable: rename ctx.tun.proto to ctx.tun.inner_proto
2026-08-06 22:35 ` [PATCH nf-next 4/7] netfilter: flowtable: rename ctx.tun.proto to ctx.tun.inner_proto Pablo Neira Ayuso
@ 2026-08-07 9:02 ` Lorenzo Bianconi
0 siblings, 0 replies; 14+ messages in thread
From: Lorenzo Bianconi @ 2026-08-07 9:02 UTC (permalink / raw)
To: Pablo Neira Ayuso; +Cc: netfilter-devel, lorenzo.bianconi
[-- Attachment #1: Type: text/plain, Size: 2699 bytes --]
> For consistency with the tun.l3proto rename, use same name field.
> No functional changes are intended.
>
> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Acked-by: Lorenzo Bianconi <lorenzo@kernel.org>
> ---
> net/netfilter/nf_flow_table_ip.c | 14 +++++++-------
> 1 file changed, 7 insertions(+), 7 deletions(-)
>
> diff --git a/net/netfilter/nf_flow_table_ip.c b/net/netfilter/nf_flow_table_ip.c
> index e1aa01763f33..ed90809b206e 100644
> --- a/net/netfilter/nf_flow_table_ip.c
> +++ b/net/netfilter/nf_flow_table_ip.c
> @@ -153,7 +153,7 @@ struct nf_flowtable_ctx {
> /* Tunnel IP header size */
> u32 hdr_size;
> /* IP tunnel protocol */
> - u8 proto;
> + u8 inner_proto;
> } tun;
> };
>
> @@ -194,7 +194,7 @@ static void nf_flow_tuple_encap(struct nf_flowtable_ctx *ctx,
> switch (inner_proto) {
> case htons(ETH_P_IP):
> iph = (struct iphdr *)(skb_network_header(skb) + offset);
> - if (ctx->tun.proto == IPPROTO_IPIP) {
> + if (ctx->tun.inner_proto == IPPROTO_IPIP) {
> tuple->tun.dst_v4.s_addr = iph->daddr;
> tuple->tun.src_v4.s_addr = iph->saddr;
> tuple->tun.inner_proto = IPPROTO_IPIP;
> @@ -202,7 +202,7 @@ static void nf_flow_tuple_encap(struct nf_flowtable_ctx *ctx,
> break;
> case htons(ETH_P_IPV6):
> ip6h = (struct ipv6hdr *)(skb_network_header(skb) + offset);
> - if (ctx->tun.proto == IPPROTO_IPV6) {
> + if (ctx->tun.inner_proto == IPPROTO_IPV6) {
> tuple->tun.dst_v6 = ip6h->daddr;
> tuple->tun.src_v6 = ip6h->saddr;
> tuple->tun.inner_proto = IPPROTO_IPV6;
> @@ -328,7 +328,7 @@ static bool nf_flow_ip4_tunnel_proto(struct nf_flowtable_ctx *ctx,
> return false;
>
> if (iph->protocol == IPPROTO_IPIP) {
> - ctx->tun.proto = iph->protocol;
> + ctx->tun.inner_proto = iph->protocol;
> ctx->tun.hdr_size = size;
> ctx->offset += ctx->tun.hdr_size;
> }
> @@ -353,7 +353,7 @@ static bool nf_flow_ip6_tunnel_proto(struct nf_flowtable_ctx *ctx,
> return false;
>
> if (ip6h->nexthdr == IPPROTO_IPV6) {
> - ctx->tun.proto = ip6h->nexthdr;
> + ctx->tun.inner_proto = ip6h->nexthdr;
> ctx->tun.hdr_size = sizeof(*ip6h);
> ctx->offset += ctx->tun.hdr_size;
> }
> @@ -367,8 +367,8 @@ static bool nf_flow_ip6_tunnel_proto(struct nf_flowtable_ctx *ctx,
> static void nf_flow_ip_tunnel_pop(struct nf_flowtable_ctx *ctx,
> struct sk_buff *skb)
> {
> - if (ctx->tun.proto != IPPROTO_IPIP &&
> - ctx->tun.proto != IPPROTO_IPV6)
> + if (ctx->tun.inner_proto != IPPROTO_IPIP &&
> + ctx->tun.inner_proto != IPPROTO_IPV6)
> return;
>
> skb_pull(skb, ctx->tun.hdr_size);
> --
> 2.47.3
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH nf-next 5/7] netfilter: flowtable: store ethertype in flowtable context
2026-08-06 22:35 [PATCH nf-next 0/7] flowtable preparation for IPv4 over IPv6 and SIT Pablo Neira Ayuso
` (3 preceding siblings ...)
2026-08-06 22:35 ` [PATCH nf-next 4/7] netfilter: flowtable: rename ctx.tun.proto to ctx.tun.inner_proto Pablo Neira Ayuso
@ 2026-08-06 22:35 ` Pablo Neira Ayuso
2026-08-07 9:10 ` Lorenzo Bianconi
2026-08-06 22:35 ` [PATCH nf-next 6/7] netfilter: flowtable: move ipv4 and ipv6 xmit path to function Pablo Neira Ayuso
2026-08-06 22:35 ` [PATCH nf-next 7/7] netfilter: flowtable: detach layer 2 encapsulation parser from lookup Pablo Neira Ayuso
6 siblings, 1 reply; 14+ messages in thread
From: Pablo Neira Ayuso @ 2026-08-06 22:35 UTC (permalink / raw)
To: netfilter-devel; +Cc: lorenzo.bianconi, lorenzo
Add a new field to store the ethertype of the packet, skipping layer 2
encapsulation. Store the ether_type in the context after parsing the
layer 2 header for the first time and then use it later on.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
net/netfilter/nf_flow_table_ip.c | 47 +++++++++++++++++++-------------
1 file changed, 28 insertions(+), 19 deletions(-)
diff --git a/net/netfilter/nf_flow_table_ip.c b/net/netfilter/nf_flow_table_ip.c
index ed90809b206e..4437f3a13cb2 100644
--- a/net/netfilter/nf_flow_table_ip.c
+++ b/net/netfilter/nf_flow_table_ip.c
@@ -147,6 +147,7 @@ static bool ip_has_options(unsigned int thoff)
struct nf_flowtable_ctx {
const struct net_device *in;
+ __be16 ether_type;
u32 offset;
u32 hdrsize;
struct {
@@ -161,7 +162,6 @@ static void nf_flow_tuple_encap(struct nf_flowtable_ctx *ctx,
struct sk_buff *skb,
struct flow_offload_tuple *tuple)
{
- __be16 inner_proto = skb->protocol;
struct vlan_ethhdr *veth;
struct pppoe_hdr *phdr;
struct ipv6hdr *ip6h;
@@ -179,19 +179,17 @@ static void nf_flow_tuple_encap(struct nf_flowtable_ctx *ctx,
veth = (struct vlan_ethhdr *)skb_mac_header(skb);
tuple->encap[i].id = ntohs(veth->h_vlan_TCI);
tuple->encap[i].proto = skb->protocol;
- inner_proto = veth->h_vlan_encapsulated_proto;
offset += VLAN_HLEN;
break;
case htons(ETH_P_PPP_SES):
phdr = (struct pppoe_hdr *)skb_network_header(skb);
tuple->encap[i].id = ntohs(phdr->sid);
tuple->encap[i].proto = skb->protocol;
- inner_proto = *((__be16 *)(phdr + 1));
offset += PPPOE_SES_HLEN;
break;
}
- switch (inner_proto) {
+ switch (ctx->ether_type) {
case htons(ETH_P_IP):
iph = (struct iphdr *)(skb_network_header(skb) + offset);
if (ctx->tun.inner_proto == IPPROTO_IPIP) {
@@ -376,10 +374,10 @@ static void nf_flow_ip_tunnel_pop(struct nf_flowtable_ctx *ctx,
}
static bool nf_flow_skb_encap_protocol(struct nf_flowtable_ctx *ctx,
- struct sk_buff *skb, __be16 proto)
+ struct sk_buff *skb)
{
- __be16 inner_proto = skb->protocol;
struct vlan_ethhdr *veth;
+ __be16 ether_type;
bool ret = false;
switch (skb->protocol) {
@@ -388,22 +386,27 @@ static bool nf_flow_skb_encap_protocol(struct nf_flowtable_ctx *ctx,
return false;
veth = (struct vlan_ethhdr *)skb_mac_header(skb);
- if (veth->h_vlan_encapsulated_proto == proto) {
- ctx->offset += VLAN_HLEN;
- inner_proto = proto;
- ret = true;
- }
+ ctx->ether_type = veth->h_vlan_encapsulated_proto;
+ ctx->offset += VLAN_HLEN;
+ ret = true;
break;
case htons(ETH_P_PPP_SES):
- if (nf_flow_pppoe_proto(skb, &inner_proto) &&
- inner_proto == proto) {
- ctx->offset += PPPOE_SES_HLEN;
- ret = true;
- }
+ if (!nf_flow_pppoe_proto(skb, ðer_type))
+ return false;
+
+ ctx->ether_type = ether_type;
+ ctx->offset += PPPOE_SES_HLEN;
+ ret = true;
+ break;
+ case htons(ETH_P_IP):
+ case htons(ETH_P_IPV6):
+ ctx->ether_type = skb->protocol;
break;
+ default:
+ return false;
}
- switch (inner_proto) {
+ switch (ctx->ether_type) {
case htons(ETH_P_IP):
ret = nf_flow_ip4_tunnel_proto(ctx, skb);
break;
@@ -455,7 +458,10 @@ nf_flow_offload_lookup(struct nf_flowtable_ctx *ctx,
{
struct flow_offload_tuple tuple = {};
- if (!nf_flow_skb_encap_protocol(ctx, skb, htons(ETH_P_IP)))
+ if (!nf_flow_skb_encap_protocol(ctx, skb))
+ return NULL;
+
+ if (unlikely(ctx->ether_type != htons(ETH_P_IP)))
return NULL;
if (nf_flow_tuple_ip(ctx, skb, &tuple) < 0)
@@ -1101,7 +1107,10 @@ nf_flow_offload_ipv6_lookup(struct nf_flowtable_ctx *ctx,
{
struct flow_offload_tuple tuple = {};
- if (!nf_flow_skb_encap_protocol(ctx, skb, htons(ETH_P_IPV6)))
+ if (!nf_flow_skb_encap_protocol(ctx, skb))
+ return NULL;
+
+ if (unlikely(ctx->ether_type != htons(ETH_P_IPV6)))
return NULL;
if (nf_flow_tuple_ipv6(ctx, skb, &tuple) < 0)
--
2.47.3
^ permalink raw reply related [flat|nested] 14+ messages in thread* Re: [PATCH nf-next 5/7] netfilter: flowtable: store ethertype in flowtable context
2026-08-06 22:35 ` [PATCH nf-next 5/7] netfilter: flowtable: store ethertype in flowtable context Pablo Neira Ayuso
@ 2026-08-07 9:10 ` Lorenzo Bianconi
0 siblings, 0 replies; 14+ messages in thread
From: Lorenzo Bianconi @ 2026-08-07 9:10 UTC (permalink / raw)
To: Pablo Neira Ayuso; +Cc: netfilter-devel, lorenzo.bianconi
[-- Attachment #1: Type: text/plain, Size: 4347 bytes --]
> Add a new field to store the ethertype of the packet, skipping layer 2
> encapsulation. Store the ether_type in the context after parsing the
> layer 2 header for the first time and then use it later on.
>
> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Acked-by: Lorenzo Bianconi <lorenzo@kernel.org>
> ---
> net/netfilter/nf_flow_table_ip.c | 47 +++++++++++++++++++-------------
> 1 file changed, 28 insertions(+), 19 deletions(-)
>
> diff --git a/net/netfilter/nf_flow_table_ip.c b/net/netfilter/nf_flow_table_ip.c
> index ed90809b206e..4437f3a13cb2 100644
> --- a/net/netfilter/nf_flow_table_ip.c
> +++ b/net/netfilter/nf_flow_table_ip.c
> @@ -147,6 +147,7 @@ static bool ip_has_options(unsigned int thoff)
>
> struct nf_flowtable_ctx {
> const struct net_device *in;
> + __be16 ether_type;
> u32 offset;
> u32 hdrsize;
> struct {
> @@ -161,7 +162,6 @@ static void nf_flow_tuple_encap(struct nf_flowtable_ctx *ctx,
> struct sk_buff *skb,
> struct flow_offload_tuple *tuple)
> {
> - __be16 inner_proto = skb->protocol;
> struct vlan_ethhdr *veth;
> struct pppoe_hdr *phdr;
> struct ipv6hdr *ip6h;
> @@ -179,19 +179,17 @@ static void nf_flow_tuple_encap(struct nf_flowtable_ctx *ctx,
> veth = (struct vlan_ethhdr *)skb_mac_header(skb);
> tuple->encap[i].id = ntohs(veth->h_vlan_TCI);
> tuple->encap[i].proto = skb->protocol;
> - inner_proto = veth->h_vlan_encapsulated_proto;
> offset += VLAN_HLEN;
> break;
> case htons(ETH_P_PPP_SES):
> phdr = (struct pppoe_hdr *)skb_network_header(skb);
> tuple->encap[i].id = ntohs(phdr->sid);
> tuple->encap[i].proto = skb->protocol;
> - inner_proto = *((__be16 *)(phdr + 1));
> offset += PPPOE_SES_HLEN;
> break;
> }
>
> - switch (inner_proto) {
> + switch (ctx->ether_type) {
> case htons(ETH_P_IP):
> iph = (struct iphdr *)(skb_network_header(skb) + offset);
> if (ctx->tun.inner_proto == IPPROTO_IPIP) {
> @@ -376,10 +374,10 @@ static void nf_flow_ip_tunnel_pop(struct nf_flowtable_ctx *ctx,
> }
>
> static bool nf_flow_skb_encap_protocol(struct nf_flowtable_ctx *ctx,
> - struct sk_buff *skb, __be16 proto)
> + struct sk_buff *skb)
> {
> - __be16 inner_proto = skb->protocol;
> struct vlan_ethhdr *veth;
> + __be16 ether_type;
> bool ret = false;
>
> switch (skb->protocol) {
> @@ -388,22 +386,27 @@ static bool nf_flow_skb_encap_protocol(struct nf_flowtable_ctx *ctx,
> return false;
>
> veth = (struct vlan_ethhdr *)skb_mac_header(skb);
> - if (veth->h_vlan_encapsulated_proto == proto) {
> - ctx->offset += VLAN_HLEN;
> - inner_proto = proto;
> - ret = true;
> - }
> + ctx->ether_type = veth->h_vlan_encapsulated_proto;
> + ctx->offset += VLAN_HLEN;
> + ret = true;
> break;
> case htons(ETH_P_PPP_SES):
> - if (nf_flow_pppoe_proto(skb, &inner_proto) &&
> - inner_proto == proto) {
> - ctx->offset += PPPOE_SES_HLEN;
> - ret = true;
> - }
> + if (!nf_flow_pppoe_proto(skb, ðer_type))
> + return false;
> +
> + ctx->ether_type = ether_type;
> + ctx->offset += PPPOE_SES_HLEN;
> + ret = true;
> + break;
> + case htons(ETH_P_IP):
> + case htons(ETH_P_IPV6):
> + ctx->ether_type = skb->protocol;
> break;
> + default:
> + return false;
> }
>
> - switch (inner_proto) {
> + switch (ctx->ether_type) {
> case htons(ETH_P_IP):
> ret = nf_flow_ip4_tunnel_proto(ctx, skb);
> break;
> @@ -455,7 +458,10 @@ nf_flow_offload_lookup(struct nf_flowtable_ctx *ctx,
> {
> struct flow_offload_tuple tuple = {};
>
> - if (!nf_flow_skb_encap_protocol(ctx, skb, htons(ETH_P_IP)))
> + if (!nf_flow_skb_encap_protocol(ctx, skb))
> + return NULL;
> +
> + if (unlikely(ctx->ether_type != htons(ETH_P_IP)))
> return NULL;
>
> if (nf_flow_tuple_ip(ctx, skb, &tuple) < 0)
> @@ -1101,7 +1107,10 @@ nf_flow_offload_ipv6_lookup(struct nf_flowtable_ctx *ctx,
> {
> struct flow_offload_tuple tuple = {};
>
> - if (!nf_flow_skb_encap_protocol(ctx, skb, htons(ETH_P_IPV6)))
> + if (!nf_flow_skb_encap_protocol(ctx, skb))
> + return NULL;
> +
> + if (unlikely(ctx->ether_type != htons(ETH_P_IPV6)))
> return NULL;
>
> if (nf_flow_tuple_ipv6(ctx, skb, &tuple) < 0)
> --
> 2.47.3
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH nf-next 6/7] netfilter: flowtable: move ipv4 and ipv6 xmit path to function
2026-08-06 22:35 [PATCH nf-next 0/7] flowtable preparation for IPv4 over IPv6 and SIT Pablo Neira Ayuso
` (4 preceding siblings ...)
2026-08-06 22:35 ` [PATCH nf-next 5/7] netfilter: flowtable: store ethertype in flowtable context Pablo Neira Ayuso
@ 2026-08-06 22:35 ` Pablo Neira Ayuso
2026-08-07 9:13 ` Lorenzo Bianconi
2026-08-06 22:35 ` [PATCH nf-next 7/7] netfilter: flowtable: detach layer 2 encapsulation parser from lookup Pablo Neira Ayuso
6 siblings, 1 reply; 14+ messages in thread
From: Pablo Neira Ayuso @ 2026-08-06 22:35 UTC (permalink / raw)
To: netfilter-devel; +Cc: lorenzo.bianconi, lorenzo
Move the existing ipv4 and ipv6 transmit path to functions in
preparation of the IPv4 over IPv6 and SIT support.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
net/netfilter/nf_flow_table_ip.c | 92 +++++++++++++++++++-------------
1 file changed, 54 insertions(+), 38 deletions(-)
diff --git a/net/netfilter/nf_flow_table_ip.c b/net/netfilter/nf_flow_table_ip.c
index 4437f3a13cb2..18febca1dcef 100644
--- a/net/netfilter/nf_flow_table_ip.c
+++ b/net/netfilter/nf_flow_table_ip.c
@@ -800,33 +800,17 @@ static unsigned int nf_flow_queue_xmit(struct net *net, struct sk_buff *skb,
return NF_STOLEN;
}
-unsigned int
-nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb,
- const struct nf_hook_state *state)
+static int nf_flow_queue_xmit4(struct sk_buff *skb,
+ struct flow_offload_tuple_rhash *tuplehash,
+ const struct nf_hook_state *state)
{
- struct flow_offload_tuple_rhash *tuplehash;
- struct nf_flowtable *flow_table = priv;
struct flow_offload_tuple *other_tuple;
enum flow_offload_tuple_dir dir;
- struct nf_flowtable_ctx ctx = {
- .in = state->in,
- };
struct nf_flow_xmit xmit = {};
struct flow_offload *flow;
struct neighbour *neigh;
struct rtable *rt;
__be32 ip_daddr;
- int ret;
-
- tuplehash = nf_flow_offload_lookup(&ctx, flow_table, skb);
- if (!tuplehash)
- return NF_ACCEPT;
-
- ret = nf_flow_offload_forward(&ctx, flow_table, tuplehash, skb);
- if (ret < 0)
- return NF_DROP;
- else if (ret == 0)
- return NF_ACCEPT;
if (unlikely(tuplehash->tuple.xmit_type == FLOW_OFFLOAD_XMIT_XFRM)) {
rt = dst_rtable(tuplehash->tuple.dst_cache);
@@ -879,6 +863,30 @@ nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb,
return nf_flow_queue_xmit(state->net, skb, &xmit);
}
+
+unsigned int
+nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb,
+ const struct nf_hook_state *state)
+{
+ struct flow_offload_tuple_rhash *tuplehash;
+ struct nf_flowtable *flow_table = priv;
+ struct nf_flowtable_ctx ctx = {
+ .in = state->in,
+ };
+ int ret;
+
+ tuplehash = nf_flow_offload_lookup(&ctx, flow_table, skb);
+ if (!tuplehash)
+ return NF_ACCEPT;
+
+ ret = nf_flow_offload_forward(&ctx, flow_table, tuplehash, skb);
+ if (ret < 0)
+ return NF_DROP;
+ else if (ret == 0)
+ return NF_ACCEPT;
+
+ return nf_flow_queue_xmit4(skb, tuplehash, state);
+}
EXPORT_SYMBOL_GPL(nf_flow_offload_ip_hook);
static void nf_flow_nat_ipv6_tcp(struct sk_buff *skb, unsigned int thoff,
@@ -1119,33 +1127,17 @@ nf_flow_offload_ipv6_lookup(struct nf_flowtable_ctx *ctx,
return flow_offload_lookup(flow_table, &tuple);
}
-unsigned int
-nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb,
- const struct nf_hook_state *state)
+static int nf_flow_queue_xmit6(struct sk_buff *skb,
+ struct flow_offload_tuple_rhash *tuplehash,
+ const struct nf_hook_state *state)
{
- struct flow_offload_tuple_rhash *tuplehash;
- struct nf_flowtable *flow_table = priv;
struct flow_offload_tuple *other_tuple;
enum flow_offload_tuple_dir dir;
- struct nf_flowtable_ctx ctx = {
- .in = state->in,
- };
struct nf_flow_xmit xmit = {};
struct in6_addr *ip6_daddr;
struct flow_offload *flow;
struct neighbour *neigh;
struct rt6_info *rt;
- int ret;
-
- tuplehash = nf_flow_offload_ipv6_lookup(&ctx, flow_table, skb);
- if (tuplehash == NULL)
- return NF_ACCEPT;
-
- ret = nf_flow_offload_ipv6_forward(&ctx, flow_table, tuplehash, skb);
- if (ret < 0)
- return NF_DROP;
- else if (ret == 0)
- return NF_ACCEPT;
if (unlikely(tuplehash->tuple.xmit_type == FLOW_OFFLOAD_XMIT_XFRM)) {
rt = dst_rt6_info(tuplehash->tuple.dst_cache);
@@ -1199,4 +1191,28 @@ nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb,
return nf_flow_queue_xmit(state->net, skb, &xmit);
}
+
+unsigned int
+nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb,
+ const struct nf_hook_state *state)
+{
+ struct flow_offload_tuple_rhash *tuplehash;
+ struct nf_flowtable *flow_table = priv;
+ struct nf_flowtable_ctx ctx = {
+ .in = state->in,
+ };
+ int ret;
+
+ tuplehash = nf_flow_offload_ipv6_lookup(&ctx, flow_table, skb);
+ if (!tuplehash)
+ return NF_ACCEPT;
+
+ ret = nf_flow_offload_ipv6_forward(&ctx, flow_table, tuplehash, skb);
+ if (ret < 0)
+ return NF_DROP;
+ else if (ret == 0)
+ return NF_ACCEPT;
+
+ return nf_flow_queue_xmit6(skb, tuplehash, state);
+}
EXPORT_SYMBOL_GPL(nf_flow_offload_ipv6_hook);
--
2.47.3
^ permalink raw reply related [flat|nested] 14+ messages in thread* Re: [PATCH nf-next 6/7] netfilter: flowtable: move ipv4 and ipv6 xmit path to function
2026-08-06 22:35 ` [PATCH nf-next 6/7] netfilter: flowtable: move ipv4 and ipv6 xmit path to function Pablo Neira Ayuso
@ 2026-08-07 9:13 ` Lorenzo Bianconi
0 siblings, 0 replies; 14+ messages in thread
From: Lorenzo Bianconi @ 2026-08-07 9:13 UTC (permalink / raw)
To: Pablo Neira Ayuso; +Cc: netfilter-devel, lorenzo.bianconi
[-- Attachment #1: Type: text/plain, Size: 4935 bytes --]
> Move the existing ipv4 and ipv6 transmit path to functions in
> preparation of the IPv4 over IPv6 and SIT support.
>
> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Nice :)
Acked-by: Lorenzo Bianconi <lorenzo@kernel.org>
> ---
> net/netfilter/nf_flow_table_ip.c | 92 +++++++++++++++++++-------------
> 1 file changed, 54 insertions(+), 38 deletions(-)
>
> diff --git a/net/netfilter/nf_flow_table_ip.c b/net/netfilter/nf_flow_table_ip.c
> index 4437f3a13cb2..18febca1dcef 100644
> --- a/net/netfilter/nf_flow_table_ip.c
> +++ b/net/netfilter/nf_flow_table_ip.c
> @@ -800,33 +800,17 @@ static unsigned int nf_flow_queue_xmit(struct net *net, struct sk_buff *skb,
> return NF_STOLEN;
> }
>
> -unsigned int
> -nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb,
> - const struct nf_hook_state *state)
> +static int nf_flow_queue_xmit4(struct sk_buff *skb,
> + struct flow_offload_tuple_rhash *tuplehash,
> + const struct nf_hook_state *state)
> {
> - struct flow_offload_tuple_rhash *tuplehash;
> - struct nf_flowtable *flow_table = priv;
> struct flow_offload_tuple *other_tuple;
> enum flow_offload_tuple_dir dir;
> - struct nf_flowtable_ctx ctx = {
> - .in = state->in,
> - };
> struct nf_flow_xmit xmit = {};
> struct flow_offload *flow;
> struct neighbour *neigh;
> struct rtable *rt;
> __be32 ip_daddr;
> - int ret;
> -
> - tuplehash = nf_flow_offload_lookup(&ctx, flow_table, skb);
> - if (!tuplehash)
> - return NF_ACCEPT;
> -
> - ret = nf_flow_offload_forward(&ctx, flow_table, tuplehash, skb);
> - if (ret < 0)
> - return NF_DROP;
> - else if (ret == 0)
> - return NF_ACCEPT;
>
> if (unlikely(tuplehash->tuple.xmit_type == FLOW_OFFLOAD_XMIT_XFRM)) {
> rt = dst_rtable(tuplehash->tuple.dst_cache);
> @@ -879,6 +863,30 @@ nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb,
>
> return nf_flow_queue_xmit(state->net, skb, &xmit);
> }
> +
> +unsigned int
> +nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb,
> + const struct nf_hook_state *state)
> +{
> + struct flow_offload_tuple_rhash *tuplehash;
> + struct nf_flowtable *flow_table = priv;
> + struct nf_flowtable_ctx ctx = {
> + .in = state->in,
> + };
> + int ret;
> +
> + tuplehash = nf_flow_offload_lookup(&ctx, flow_table, skb);
> + if (!tuplehash)
> + return NF_ACCEPT;
> +
> + ret = nf_flow_offload_forward(&ctx, flow_table, tuplehash, skb);
> + if (ret < 0)
> + return NF_DROP;
> + else if (ret == 0)
> + return NF_ACCEPT;
> +
> + return nf_flow_queue_xmit4(skb, tuplehash, state);
> +}
> EXPORT_SYMBOL_GPL(nf_flow_offload_ip_hook);
>
> static void nf_flow_nat_ipv6_tcp(struct sk_buff *skb, unsigned int thoff,
> @@ -1119,33 +1127,17 @@ nf_flow_offload_ipv6_lookup(struct nf_flowtable_ctx *ctx,
> return flow_offload_lookup(flow_table, &tuple);
> }
>
> -unsigned int
> -nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb,
> - const struct nf_hook_state *state)
> +static int nf_flow_queue_xmit6(struct sk_buff *skb,
> + struct flow_offload_tuple_rhash *tuplehash,
> + const struct nf_hook_state *state)
> {
> - struct flow_offload_tuple_rhash *tuplehash;
> - struct nf_flowtable *flow_table = priv;
> struct flow_offload_tuple *other_tuple;
> enum flow_offload_tuple_dir dir;
> - struct nf_flowtable_ctx ctx = {
> - .in = state->in,
> - };
> struct nf_flow_xmit xmit = {};
> struct in6_addr *ip6_daddr;
> struct flow_offload *flow;
> struct neighbour *neigh;
> struct rt6_info *rt;
> - int ret;
> -
> - tuplehash = nf_flow_offload_ipv6_lookup(&ctx, flow_table, skb);
> - if (tuplehash == NULL)
> - return NF_ACCEPT;
> -
> - ret = nf_flow_offload_ipv6_forward(&ctx, flow_table, tuplehash, skb);
> - if (ret < 0)
> - return NF_DROP;
> - else if (ret == 0)
> - return NF_ACCEPT;
>
> if (unlikely(tuplehash->tuple.xmit_type == FLOW_OFFLOAD_XMIT_XFRM)) {
> rt = dst_rt6_info(tuplehash->tuple.dst_cache);
> @@ -1199,4 +1191,28 @@ nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb,
>
> return nf_flow_queue_xmit(state->net, skb, &xmit);
> }
> +
> +unsigned int
> +nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb,
> + const struct nf_hook_state *state)
> +{
> + struct flow_offload_tuple_rhash *tuplehash;
> + struct nf_flowtable *flow_table = priv;
> + struct nf_flowtable_ctx ctx = {
> + .in = state->in,
> + };
> + int ret;
> +
> + tuplehash = nf_flow_offload_ipv6_lookup(&ctx, flow_table, skb);
> + if (!tuplehash)
> + return NF_ACCEPT;
> +
> + ret = nf_flow_offload_ipv6_forward(&ctx, flow_table, tuplehash, skb);
> + if (ret < 0)
> + return NF_DROP;
> + else if (ret == 0)
> + return NF_ACCEPT;
> +
> + return nf_flow_queue_xmit6(skb, tuplehash, state);
> +}
> EXPORT_SYMBOL_GPL(nf_flow_offload_ipv6_hook);
> --
> 2.47.3
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH nf-next 7/7] netfilter: flowtable: detach layer 2 encapsulation parser from lookup
2026-08-06 22:35 [PATCH nf-next 0/7] flowtable preparation for IPv4 over IPv6 and SIT Pablo Neira Ayuso
` (5 preceding siblings ...)
2026-08-06 22:35 ` [PATCH nf-next 6/7] netfilter: flowtable: move ipv4 and ipv6 xmit path to function Pablo Neira Ayuso
@ 2026-08-06 22:35 ` Pablo Neira Ayuso
2026-08-07 9:15 ` Lorenzo Bianconi
6 siblings, 1 reply; 14+ messages in thread
From: Pablo Neira Ayuso @ 2026-08-06 22:35 UTC (permalink / raw)
To: netfilter-devel; +Cc: lorenzo.bianconi, lorenzo
Move the layer 2 encapsulation header parser out of the lookup function
to prepare for IPv4 over IPv6 and SIT.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
net/netfilter/nf_flow_table_ip.c | 24 ++++++++++++------------
1 file changed, 12 insertions(+), 12 deletions(-)
diff --git a/net/netfilter/nf_flow_table_ip.c b/net/netfilter/nf_flow_table_ip.c
index 18febca1dcef..af534000a287 100644
--- a/net/netfilter/nf_flow_table_ip.c
+++ b/net/netfilter/nf_flow_table_ip.c
@@ -458,12 +458,6 @@ nf_flow_offload_lookup(struct nf_flowtable_ctx *ctx,
{
struct flow_offload_tuple tuple = {};
- if (!nf_flow_skb_encap_protocol(ctx, skb))
- return NULL;
-
- if (unlikely(ctx->ether_type != htons(ETH_P_IP)))
- return NULL;
-
if (nf_flow_tuple_ip(ctx, skb, &tuple) < 0)
return NULL;
@@ -875,6 +869,12 @@ nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb,
};
int ret;
+ if (!nf_flow_skb_encap_protocol(&ctx, skb))
+ return NF_ACCEPT;
+
+ if (unlikely(ctx.ether_type != htons(ETH_P_IP)))
+ return NF_ACCEPT;
+
tuplehash = nf_flow_offload_lookup(&ctx, flow_table, skb);
if (!tuplehash)
return NF_ACCEPT;
@@ -1115,12 +1115,6 @@ nf_flow_offload_ipv6_lookup(struct nf_flowtable_ctx *ctx,
{
struct flow_offload_tuple tuple = {};
- if (!nf_flow_skb_encap_protocol(ctx, skb))
- return NULL;
-
- if (unlikely(ctx->ether_type != htons(ETH_P_IPV6)))
- return NULL;
-
if (nf_flow_tuple_ipv6(ctx, skb, &tuple) < 0)
return NULL;
@@ -1203,6 +1197,12 @@ nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb,
};
int ret;
+ if (!nf_flow_skb_encap_protocol(&ctx, skb))
+ return NF_ACCEPT;
+
+ if (unlikely(ctx.ether_type != htons(ETH_P_IPV6)))
+ return NF_ACCEPT;
+
tuplehash = nf_flow_offload_ipv6_lookup(&ctx, flow_table, skb);
if (!tuplehash)
return NF_ACCEPT;
--
2.47.3
^ permalink raw reply related [flat|nested] 14+ messages in thread* Re: [PATCH nf-next 7/7] netfilter: flowtable: detach layer 2 encapsulation parser from lookup
2026-08-06 22:35 ` [PATCH nf-next 7/7] netfilter: flowtable: detach layer 2 encapsulation parser from lookup Pablo Neira Ayuso
@ 2026-08-07 9:15 ` Lorenzo Bianconi
0 siblings, 0 replies; 14+ messages in thread
From: Lorenzo Bianconi @ 2026-08-07 9:15 UTC (permalink / raw)
To: Pablo Neira Ayuso; +Cc: netfilter-devel, lorenzo.bianconi
[-- Attachment #1: Type: text/plain, Size: 2084 bytes --]
> Move the layer 2 encapsulation header parser out of the lookup function
> to prepare for IPv4 over IPv6 and SIT.
>
> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Acked-by: Lorenzo Bianconi <lorenzo@kernel.org>
> ---
> net/netfilter/nf_flow_table_ip.c | 24 ++++++++++++------------
> 1 file changed, 12 insertions(+), 12 deletions(-)
>
> diff --git a/net/netfilter/nf_flow_table_ip.c b/net/netfilter/nf_flow_table_ip.c
> index 18febca1dcef..af534000a287 100644
> --- a/net/netfilter/nf_flow_table_ip.c
> +++ b/net/netfilter/nf_flow_table_ip.c
> @@ -458,12 +458,6 @@ nf_flow_offload_lookup(struct nf_flowtable_ctx *ctx,
> {
> struct flow_offload_tuple tuple = {};
>
> - if (!nf_flow_skb_encap_protocol(ctx, skb))
> - return NULL;
> -
> - if (unlikely(ctx->ether_type != htons(ETH_P_IP)))
> - return NULL;
> -
> if (nf_flow_tuple_ip(ctx, skb, &tuple) < 0)
> return NULL;
>
> @@ -875,6 +869,12 @@ nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb,
> };
> int ret;
>
> + if (!nf_flow_skb_encap_protocol(&ctx, skb))
> + return NF_ACCEPT;
> +
> + if (unlikely(ctx.ether_type != htons(ETH_P_IP)))
> + return NF_ACCEPT;
> +
> tuplehash = nf_flow_offload_lookup(&ctx, flow_table, skb);
> if (!tuplehash)
> return NF_ACCEPT;
> @@ -1115,12 +1115,6 @@ nf_flow_offload_ipv6_lookup(struct nf_flowtable_ctx *ctx,
> {
> struct flow_offload_tuple tuple = {};
>
> - if (!nf_flow_skb_encap_protocol(ctx, skb))
> - return NULL;
> -
> - if (unlikely(ctx->ether_type != htons(ETH_P_IPV6)))
> - return NULL;
> -
> if (nf_flow_tuple_ipv6(ctx, skb, &tuple) < 0)
> return NULL;
>
> @@ -1203,6 +1197,12 @@ nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb,
> };
> int ret;
>
> + if (!nf_flow_skb_encap_protocol(&ctx, skb))
> + return NF_ACCEPT;
> +
> + if (unlikely(ctx.ether_type != htons(ETH_P_IPV6)))
> + return NF_ACCEPT;
> +
> tuplehash = nf_flow_offload_ipv6_lookup(&ctx, flow_table, skb);
> if (!tuplehash)
> return NF_ACCEPT;
> --
> 2.47.3
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 14+ messages in thread