[PATCH 5/5] netfilter: nf_flow_table_path: add VLAN passthrough support
Daniel Pawlik
pawlik.dan at gmail.com
Mon Jun 29 05:32:53 PDT 2026
From: Ryan Chen <rchen14b at gmail.com>
VLAN passthrough packets can be offloaded when bridge-nf-filter-vlan-tagged
is enabled. When a packet has a VLAN tag and the bridge does not have VLAN
filtering enabled (passthrough mode), record the VLAN encap info so the
hardware flow offload entry includes the correct VLAN tag.
Without this change, VLAN-tagged bridged traffic cannot be offloaded by PPE
because the VLAN encap information is missing from the flow entry.
Enable with: echo 1 > /proc/sys/net/bridge/bridge-nf-filter-vlan-tagged
Based on a MediaTek SDK patch by Chak-Kei Lam <chak-kei.lam at mediatek.com>.
Signed-off-by: Ryan Chen <rchen14b at gmail.com>
Signed-off-by: Daniel Pawlik <pawlik.dan at gmail.com>
---
net/netfilter/nf_flow_table_path.c | 32 ++++++++++++++++++++++++++++--
1 file changed, 30 insertions(+), 2 deletions(-)
diff --git a/net/netfilter/nf_flow_table_path.c b/net/netfilter/nf_flow_table_path.c
index 580aa1db3cb4..d15c425c88c4 100644
--- a/net/netfilter/nf_flow_table_path.c
+++ b/net/netfilter/nf_flow_table_path.c
@@ -17,6 +17,7 @@
#include <net/netfilter/nf_flow_table.h>
#include <linux/if_bridge.h>
#include <linux/if_ether.h>
+#include <linux/if_vlan.h>
#include <net/route.h>
#include <net/ip6_route.h>
@@ -136,6 +137,29 @@ struct nft_forward_info {
enum flow_offload_xmit_type xmit_type;
};
+static void nft_fill_vlan_passthrough_info(const struct nft_pktinfo *pkt,
+ struct nft_forward_info *info)
+{
+ if (!skb_vlan_tag_present(pkt->skb))
+ return;
+
+ rcu_read_lock();
+ /* when bridge VLAN filtering is enabled, the bridge handles the tag */
+ if (netif_is_bridge_port(pkt->skb->dev) &&
+ !br_vlan_is_enabled_rcu(pkt->skb->dev)) {
+ if (info->num_encaps >= NF_FLOW_TABLE_ENCAP_MAX) {
+ info->indev = NULL;
+ } else {
+ info->encap[info->num_encaps].id =
+ skb_vlan_tag_get_id(pkt->skb);
+ info->encap[info->num_encaps].proto =
+ pkt->skb->vlan_proto;
+ info->num_encaps++;
+ }
+ }
+ rcu_read_unlock();
+}
+
static int nft_dev_path_info(const struct net_device_path_stack *stack,
struct nft_forward_info *info,
unsigned char *ha, struct nf_flowtable *flowtable)
@@ -326,8 +350,12 @@ static int nft_dev_forward_path(const struct nft_pktinfo *pkt,
nft_br_vlan_dev_fill_forward_path(pkt, &ctx);
}
- if (nft_dev_fill_forward_path(&ctx, route, dst, ct, dir, ha, &stack) < 0 ||
- nft_dev_path_info(&stack, &info, ha, &ft->data) < 0)
+ if (nft_dev_fill_forward_path(&ctx, route, dst, ct, dir, ha, &stack) < 0)
+ return -ENOENT;
+
+ nft_fill_vlan_passthrough_info(pkt, &info);
+
+ if (nft_dev_path_info(&stack, &info, ha, &ft->data) < 0)
return -ENOENT;
if (!nft_flowtable_find_dev(info.indev, ft))
--
2.54.0
More information about the Linux-mediatek
mailing list