From: Ryan Chen 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 . Signed-off-by: Ryan Chen Signed-off-by: Daniel Pawlik --- 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 #include #include +#include #include #include @@ -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