Support (8021q + 8021q + pppoe) encap tuple. We need encap put to skb Before dev_hard_header().
Signed-off-by: LiXiong Liu <lx...@ikuai8.com> --- ...ilter-flowtable-support-nf_flow_encap_put.patch | 157 +++++++++++++++++++++ 1 file changed, 157 insertions(+) create mode 100644 target/linux/generic/pending-5.10/706-03-netfilter-flowtable-support-nf_flow_encap_put.patch diff --git a/target/linux/generic/pending-5.10/706-03-netfilter-flowtable-support-nf_flow_encap_put.patch b/target/linux/generic/pending-5.10/706-03-netfilter-flowtable-support-nf_flow_encap_put.patch new file mode 100644 index 0000000..545a956 --- /dev/null +++ b/target/linux/generic/pending-5.10/706-03-netfilter-flowtable-support-nf_flow_encap_put.patch @@ -0,0 +1,157 @@ +--- a/net/netfilter/nf_flow_table_ip.c ++++ b/net/netfilter/nf_flow_table_ip.c +@@ -145,6 +145,7 @@ static void nf_flow_tuple_encap(struct s + struct vlan_ethhdr *veth; + struct pppoe_hdr *phdr; + int i = 0; ++ __be16 *proto_ptr; + + if (skb_vlan_tag_present(skb)) { + tuple->encap[i].id = skb_vlan_tag_get(skb); +@@ -156,6 +157,17 @@ static void nf_flow_tuple_encap(struct s + veth = (struct vlan_ethhdr *)skb_mac_header(skb); + tuple->encap[i].id = ntohs(veth->h_vlan_TCI); + tuple->encap[i].proto = skb->protocol; ++ i++; ++ ++ proto_ptr = &veth->h_vlan_encapsulated_proto; ++ if (*proto_ptr == htons(ETH_P_8021Q)) { ++ tuple->encap[i].id = ntohs(*(proto_ptr + 1)); ++ tuple->encap[i].proto = htons(ETH_P_8021Q); ++ } else if (*proto_ptr == htons(ETH_P_PPP_SES)) { ++ phdr = (struct pppoe_hdr *)(skb_mac_header(skb) + ETH_HLEN + VLAN_HLEN); ++ tuple->encap[i].id = ntohs(phdr->sid); ++ tuple->encap[i].proto = htons(ETH_P_PPP_SES); ++ } + break; + case htons(ETH_P_PPP_SES): + phdr = (struct pppoe_hdr *)(skb_mac_header(skb) + ETH_HLEN); +@@ -248,11 +260,11 @@ static unsigned int nf_flow_xmit_xfrm(st + return NF_STOLEN; + } + +-static inline __be16 nf_flow_pppoe_proto(const struct sk_buff *skb) ++static inline __be16 nf_flow_pppoe_proto(const struct sk_buff *skb, u32 offset) + { + __be16 proto; + +- proto = *((__be16 *)(skb_mac_header(skb) + ETH_HLEN + ++ proto = *((__be16 *)(skb_mac_header(skb) + ETH_HLEN + offset + + sizeof(struct pppoe_hdr))); + switch (proto) { + case htons(PPP_IP): +@@ -268,17 +280,29 @@ static bool nf_flow_skb_encap_protocol(c + u32 *offset) + { + struct vlan_ethhdr *veth; ++ __be16 *proto_ptr; + + switch (skb->protocol) { + case htons(ETH_P_8021Q): + veth = (struct vlan_ethhdr *)skb_mac_header(skb); +- if (veth->h_vlan_encapsulated_proto == proto) { ++ proto_ptr = &veth->h_vlan_encapsulated_proto; ++ *offset += VLAN_HLEN; ++ ++ if (*proto_ptr == htons(ETH_P_PPP_SES)) ++ goto pppoe; ++ ++ if (*proto_ptr == htons(ETH_P_8021Q)) { + *offset += VLAN_HLEN; +- return true; ++ proto_ptr += 2; + } ++ ++ if (*proto_ptr == proto) ++ return true; ++ + break; + case htons(ETH_P_PPP_SES): +- if (nf_flow_pppoe_proto(skb) == proto) { ++pppoe: ++ if (nf_flow_pppoe_proto(skb, *offset) == proto) { + *offset += PPPOE_SES_HLEN; + return true; + } +@@ -307,7 +331,7 @@ static void nf_flow_encap_pop(struct sk_ + skb_reset_network_header(skb); + break; + case htons(ETH_P_PPP_SES): +- skb->protocol = nf_flow_pppoe_proto(skb); ++ skb->protocol = nf_flow_pppoe_proto(skb, 0); + skb_pull(skb, PPPOE_SES_HLEN); + skb_reset_network_header(skb); + break; +@@ -315,6 +339,62 @@ static void nf_flow_encap_pop(struct sk_ + } + } + ++static int nf_flow_encap_put(struct sk_buff *skb, unsigned short *type, ++ struct flow_offload_tuple_rhash *tuplehash) ++{ ++ struct vlan_hdr *vlan_hdr = NULL; ++ struct pppoe_hdr *ph; ++ struct pppoe_tag *pt; ++ u16 data_len = skb->len; ++ int i; ++ ++ if ((skb->data - PPPOE_SES_HLEN - VLAN_HLEN * 2) < skb->head) ++ if (skb_cow_head(skb, LL_RESERVED_SPACE(skb->dev) + ++ PPPOE_SES_HLEN + VLAN_HLEN * 2)) ++ return -1; ++ ++ /* Offset the pointer in the reverse direction */ ++ tuplehash = (tuplehash->tuple.dir) ? (tuplehash - 1) : (tuplehash + 1); ++ for (i = tuplehash->tuple.encap_num - 1; i >= 0; i--) { ++ switch (tuplehash->tuple.encap[i].proto) { ++ case htons(ETH_P_8021Q): ++ vlan_hdr = __skb_push(skb, VLAN_HLEN); ++ vlan_hdr->h_vlan_TCI = htons(tuplehash->tuple.encap[i].id); ++ vlan_hdr->h_vlan_encapsulated_proto = htons(*type); ++ ++ skb->protocol = htons(ETH_P_8021Q); ++ *type = ETH_P_8021Q; ++ break; ++ case htons(ETH_P_PPP_SES): ++ __skb_push(skb, PPPOE_SES_HLEN); ++ skb_reset_network_header(skb); ++ ++ ph = pppoe_hdr(skb); ++ pt = ph->tag; ++ ph->ver = 1; ++ ph->type = 1; ++ ph->code = 0; ++ ph->sid = htons(tuplehash->tuple.encap[i].id); ++ ph->length = htons(data_len+2); ++ ++ switch (*type) { ++ case ETH_P_IP: ++ pt->tag_type = htons(PPP_IP); ++ break; ++ case ETH_P_IPV6: ++ pt->tag_type = htons(PPP_IPV6); ++ break; ++ } ++ ++ skb->protocol = htons(ETH_P_PPP_SES); ++ *type = ETH_P_PPP_SES; ++ break; ++ } ++ } ++ ++ return 0; ++} ++ + static unsigned int nf_flow_queue_xmit(struct net *net, struct sk_buff *skb, + const struct flow_offload_tuple_rhash *tuplehash, + unsigned short type) +@@ -326,6 +406,9 @@ static unsigned int nf_flow_queue_xmit(s + return NF_DROP; + + skb->dev = outdev; ++ if (nf_flow_encap_put(skb, &type, (void *)tuplehash)) ++ return NF_DROP; ++ + dev_hard_header(skb, skb->dev, type, tuplehash->tuple.out.h_dest, + tuplehash->tuple.out.h_source, skb->len); + dev_queue_xmit(skb); -- 2.7.4 _______________________________________________ openwrt-devel mailing list openwrt-devel@lists.openwrt.org https://lists.openwrt.org/mailman/listinfo/openwrt-devel