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

Reply via email to