@@ -170,14 +170,14 @@ static void nf_flow_tuple_encap(struct nf_flowtable_ctx *ctx,
int i = 0;
if (skb_vlan_tag_present(skb)) {
- tuple->encap[i].id = skb_vlan_tag_get(skb);
+ tuple->encap[i].id = skb_vlan_tag_get_id(skb);
tuple->encap[i].proto = skb->vlan_proto;
i++;
}
switch (skb->protocol) {
case htons(ETH_P_8021Q):
veth = (struct vlan_ethhdr *)skb_mac_header(skb);
- tuple->encap[i].id = ntohs(veth->h_vlan_TCI);
+ tuple->encap[i].id = ntohs(veth->h_vlan_TCI) & VLAN_VID_MASK;
tuple->encap[i].proto = skb->protocol;
offset += VLAN_HLEN;
break;
nf_flow_tuple_encap() stores the skb vlan tag in the encap tuple id using skb_vlan_tag_get(), which returns the unmasked TCI including the 3 PCP priority bits. The flowtable entry, however, is programmed by nf_dev_path_info() with vlan_dev_vlan_id(), a plain 12-bit VID. When a NIC delivers RX vlan offload skbs with a non-zero priority (an RTL9617C EPON ONU was observed handing over vid 818 skbs with tci 0x6332, PCP 3), the runtime lookup key never matches the programmed entry, so every packet misses the flow table and software flow offload is silently defeated. Mask both parse sites to the 12-bit VID so the lookup key matches for any priority. The in-header variant has the same problem for frames received with PCP != 0 on a non-offload path. The egress side is unaffected: nf_flow_encap_push() restores tags from the programmed tuple id, which never carried priority bits. Measured on an RTL9617C ONU (PPPoE over VLAN 818 WAN, NATed 6-flow download over a 1G EPON line), before -> after: download throughput 377 Mbps -> 936 Mbps CPU0 %soft at that rate 91.5% -> 70.9% Fixes: 4cd91f7c290f ("netfilter: flowtable: add vlan support") Cc: netfilter-devel@vger.kernel.org Signed-off-by: Shuangfeng He <huangya90@gmail.com> --- net/netfilter/nf_flow_table_ip.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)