From: Gao Feng <redacted>
The PPTP is encapsulated by GRE header with that GRE_VERSION bits
must contain one. But current GRE RPS needs the GRE_VERSION must be
zero. So RPS does not work for PPTP traffic.
In my test environment, there are four MIPS cores, and all traffic
are passed through by PPTP. As a result, only one core is 100% busy
while other three cores are very idle. After this patch, the usage
of four cores are balanced well.
Signed-off-by: Gao Feng <redacted>
---
v3: 1) Move struct pptp_gre_header defination into new file pptp.h
2) Use sizeof GRE and PPTP type instead of literal value;
3) Remove strict flag check for PPTP to robust;
4) Consolidate the codes again;
v2: Update according to Tom and Philp's advice.
1) Consolidate the codes with GRE version 0 path;
2) Use PPP_PROTOCOL to get ppp protol;
3) Set the FLOW_DIS_ENCAPSULATION flag;
v1: Intial patch
drivers/net/ppp/pptp.c | 36 +----------
include/net/pptp.h | 40 ++++++++++++
include/uapi/linux/if_tunnel.h | 7 +-
net/core/flow_dissector.c | 141 +++++++++++++++++++++++++----------------
4 files changed, 134 insertions(+), 90 deletions(-)
create mode 100644 include/net/pptp.h
@@ -338,71 +340,102 @@ mpls:ip_proto_again:switch(ip_proto){caseIPPROTO_GRE:{-structgre_hdr{-__be16flags;-__be16proto;-}*hdr,_hdr;+structgre_base_hdr*hdr,_hdr;hdr=__skb_header_pointer(skb,nhoff,sizeof(_hdr),data,hlen,&_hdr);if(!hdr)gotoout_bad;-/*-*OnlylookinsideGREifversionzeroandno-*routing-*/-if(hdr->flags&(GRE_VERSION|GRE_ROUTING))-break;-proto=hdr->proto;-nhoff+=4;-if(hdr->flags&GRE_CSUM)-nhoff+=4;-if(hdr->flags&GRE_KEY){-const__be32*keyid;-__be32_keyid;+/* Only look inside GRE without routing */+if(!(hdr->flags&GRE_ROUTING)){+intoffset=0;-keyid=__skb_header_pointer(skb,nhoff,sizeof(_keyid),-data,hlen,&_keyid);+proto=hdr->protocol;-if(!keyid)-gotoout_bad;+if(hdr->flags&GRE_VERSION){+/* Maybe PPTP in GRE */+if(!(proto==GRE_PROTO_PPP&&(hdr->flags&GRE_KEY)&&+(hdr->flags&GRE_VERSION)==GRE_VERSION_1))+break;+}-if(dissector_uses_key(flow_dissector,-FLOW_DISSECTOR_KEY_GRE_KEYID)){-key_keyid=skb_flow_dissector_target(flow_dissector,-FLOW_DISSECTOR_KEY_GRE_KEYID,-target_container);-key_keyid->keyid=*keyid;+offset+=sizeof(structgre_base_hdr);++if(hdr->flags&GRE_CSUM)+offset+=sizeof(__be32);++if(hdr->flags&GRE_KEY){+const__be32*keyid;+__be32_keyid;++keyid=__skb_header_pointer(skb,nhoff+offset,sizeof(_keyid),+data,hlen,&_keyid);++if(!keyid)+gotoout_bad;++if(dissector_uses_key(flow_dissector,+FLOW_DISSECTOR_KEY_GRE_KEYID)){+key_keyid=skb_flow_dissector_target(flow_dissector,+FLOW_DISSECTOR_KEY_GRE_KEYID,+target_container);+key_keyid->keyid=*keyid;+}+offset+=sizeof(_keyid);}-nhoff+=4;-}-if(hdr->flags&GRE_SEQ)-nhoff+=4;-if(proto==htons(ETH_P_TEB)){-conststructethhdr*eth;-structethhdr_eth;--eth=__skb_header_pointer(skb,nhoff,-sizeof(_eth),-data,hlen,&_eth);-if(!eth)-gotoout_bad;-proto=eth->h_proto;-nhoff+=sizeof(*eth);--/* Cap headers that we access via pointers at the-*endoftheEthernetheaderasourmaximumalignment-*atthatpointisonly2bytes.-*/-if(NET_IP_ALIGN)-hlen=nhoff;-}-key_control->flags|=FLOW_DIS_ENCAPSULATION;-if(flags&FLOW_DISSECTOR_F_STOP_AT_ENCAP)-gotoout_good;+if(hdr->flags&GRE_SEQ)+offset+=sizeof(((structpptp_gre_header*)0)->seq);++if(hdr->flags&GRE_ACK)+offset+=sizeof(((structpptp_gre_header*)0)->ack);++if(proto==GRE_PROTO_PPP){+u8_ppp_hdr[PPP_HDRLEN];+u8*ppp_hdr;++ppp_hdr=skb_header_pointer(skb,nhoff+offset,+sizeof(_ppp_hdr),_ppp_hdr);+if(!ppp_hdr)+gotoout_bad;++proto=PPP_PROTOCOL(ppp_hdr);+if(proto==PPP_IP)+proto=htons(ETH_P_IP);+elseif(proto==PPP_IPV6)+proto=htons(ETH_P_IPV6);+else+break;++offset+=PPP_HDRLEN;+}elseif(proto==htons(ETH_P_TEB)){+conststructethhdr*eth;+structethhdr_eth;++eth=__skb_header_pointer(skb,nhoff+offset,+sizeof(_eth),+data,hlen,&_eth);+if(!eth)+gotoout_bad;+proto=eth->h_proto;+offset+=sizeof(*eth);++/* Cap headers that we access via pointers at the+*endoftheEthernetheaderasourmaximumalignment+*atthatpointisonly2bytes.+*/+if(NET_IP_ALIGN)+hlen=(nhoff+offset);+}-gotoagain;+nhoff+=offset;+key_control->flags|=FLOW_DIS_ENCAPSULATION;+if(flags&FLOW_DISSECTOR_F_STOP_AT_ENCAP)+gotoout_good;++gotoagain;+}+break;}caseNEXTHDR_HOP:caseNEXTHDR_ROUTING:
From: Tom Herbert <hidden> Date: 2016-08-03 16:15:45
On Wed, Aug 3, 2016 at 7:52 AM, [off-list ref] wrote:
quoted hunk
From: Gao Feng <redacted>
The PPTP is encapsulated by GRE header with that GRE_VERSION bits
must contain one. But current GRE RPS needs the GRE_VERSION must be
zero. So RPS does not work for PPTP traffic.
In my test environment, there are four MIPS cores, and all traffic
are passed through by PPTP. As a result, only one core is 100% busy
while other three cores are very idle. After this patch, the usage
of four cores are balanced well.
Signed-off-by: Gao Feng <redacted>
---
v3: 1) Move struct pptp_gre_header defination into new file pptp.h
2) Use sizeof GRE and PPTP type instead of literal value;
3) Remove strict flag check for PPTP to robust;
4) Consolidate the codes again;
v2: Update according to Tom and Philp's advice.
1) Consolidate the codes with GRE version 0 path;
2) Use PPP_PROTOCOL to get ppp protol;
3) Set the FLOW_DIS_ENCAPSULATION flag;
v1: Intial patch
drivers/net/ppp/pptp.c | 36 +----------
include/net/pptp.h | 40 ++++++++++++
include/uapi/linux/if_tunnel.h | 7 +-
net/core/flow_dissector.c | 141 +++++++++++++++++++++++++----------------
4 files changed, 134 insertions(+), 90 deletions(-)
create mode 100644 include/net/pptp.h
@@ -338,71 +340,102 @@ mpls:ip_proto_again:switch(ip_proto){caseIPPROTO_GRE:{-structgre_hdr{-__be16flags;-__be16proto;-}*hdr,_hdr;+structgre_base_hdr*hdr,_hdr;hdr=__skb_header_pointer(skb,nhoff,sizeof(_hdr),data,hlen,&_hdr);if(!hdr)gotoout_bad;-/*-*OnlylookinsideGREifversionzeroandno-*routing-*/-if(hdr->flags&(GRE_VERSION|GRE_ROUTING))-break;-proto=hdr->proto;-nhoff+=4;-if(hdr->flags&GRE_CSUM)-nhoff+=4;-if(hdr->flags&GRE_KEY){-const__be32*keyid;-__be32_keyid;+/* Only look inside GRE without routing */+if(!(hdr->flags&GRE_ROUTING)){+intoffset=0;-keyid=__skb_header_pointer(skb,nhoff,sizeof(_keyid),-data,hlen,&_keyid);+proto=hdr->protocol;-if(!keyid)-gotoout_bad;+if(hdr->flags&GRE_VERSION){+/* Maybe PPTP in GRE */+if(!(proto==GRE_PROTO_PPP&&(hdr->flags&GRE_KEY)&&+(hdr->flags&GRE_VERSION)==GRE_VERSION_1))+break;+}-if(dissector_uses_key(flow_dissector,-FLOW_DISSECTOR_KEY_GRE_KEYID)){-key_keyid=skb_flow_dissector_target(flow_dissector,-FLOW_DISSECTOR_KEY_GRE_KEYID,-target_container);-key_keyid->keyid=*keyid;+offset+=sizeof(structgre_base_hdr);++if(hdr->flags&GRE_CSUM)+offset+=sizeof(__be32);++if(hdr->flags&GRE_KEY){+const__be32*keyid;+__be32_keyid;++keyid=__skb_header_pointer(skb,nhoff+offset,sizeof(_keyid),+data,hlen,&_keyid);++if(!keyid)+gotoout_bad;++if(dissector_uses_key(flow_dissector,+FLOW_DISSECTOR_KEY_GRE_KEYID)){+key_keyid=skb_flow_dissector_target(flow_dissector,+FLOW_DISSECTOR_KEY_GRE_KEYID,+target_container);+key_keyid->keyid=*keyid;+}+offset+=sizeof(_keyid);}-nhoff+=4;-}-if(hdr->flags&GRE_SEQ)-nhoff+=4;-if(proto==htons(ETH_P_TEB)){-conststructethhdr*eth;-structethhdr_eth;--eth=__skb_header_pointer(skb,nhoff,-sizeof(_eth),-data,hlen,&_eth);-if(!eth)-gotoout_bad;-proto=eth->h_proto;-nhoff+=sizeof(*eth);--/* Cap headers that we access via pointers at the-*endoftheEthernetheaderasourmaximumalignment-*atthatpointisonly2bytes.-*/-if(NET_IP_ALIGN)-hlen=nhoff;-}-key_control->flags|=FLOW_DIS_ENCAPSULATION;-if(flags&FLOW_DISSECTOR_F_STOP_AT_ENCAP)-gotoout_good;+if(hdr->flags&GRE_SEQ)+offset+=sizeof(((structpptp_gre_header*)0)->seq);++if(hdr->flags&GRE_ACK)+offset+=sizeof(((structpptp_gre_header*)0)->ack);++if(proto==GRE_PROTO_PPP){+u8_ppp_hdr[PPP_HDRLEN];+u8*ppp_hdr;++ppp_hdr=skb_header_pointer(skb,nhoff+offset,+sizeof(_ppp_hdr),_ppp_hdr);+if(!ppp_hdr)+gotoout_bad;++proto=PPP_PROTOCOL(ppp_hdr);+if(proto==PPP_IP)+proto=htons(ETH_P_IP);+elseif(proto==PPP_IPV6)+proto=htons(ETH_P_IPV6);+else+break;++offset+=PPP_HDRLEN;+}elseif(proto==htons(ETH_P_TEB)){+conststructethhdr*eth;+structethhdr_eth;++eth=__skb_header_pointer(skb,nhoff+offset,+sizeof(_eth),+data,hlen,&_eth);+if(!eth)+gotoout_bad;+proto=eth->h_proto;+offset+=sizeof(*eth);++/* Cap headers that we access via pointers at the+*endoftheEthernetheaderasourmaximumalignment+*atthatpointisonly2bytes.+*/+if(NET_IP_ALIGN)+hlen=(nhoff+offset);+}-gotoagain;+nhoff+=offset;+key_control->flags|=FLOW_DIS_ENCAPSULATION;+if(flags&FLOW_DISSECTOR_F_STOP_AT_ENCAP)+gotoout_good;++gotoagain;+}+break;}caseNEXTHDR_HOP:caseNEXTHDR_ROUTING:--
1.9.1
HI Feng,
Please be careful about order of processing GRE options, keyid must be
handled first. GRE_ACK looks like the only new field that needs to be
considered for v1. Also, the keyid in v1 is split into two 16 bit
fields; the first is payload length which is not usable for entropy,
but the second (Call ID) does look useful for that. I would suggest
the IPPROTO_GRE could look something like:
data, hlen, &_hdr);
if (!hdr)
goto out_bad;
+
+ /* Only look inside GRE for versions 0 and 1 */
+ gre_ver = hdr->flags & GRE_VERSION;
+ if (gre_ver > 1)
+ break;
/*
- * Only look inside GRE if version zero and no
- * routing
+ * Only look inside GRE if no routing
*/
- if (hdr->flags & (GRE_VERSION | GRE_ROUTING))
+ if (hdr->flags & GRE_ROUTING)
break;
proto = hdr->proto;
@@ -372,30 +377,62 @@ ip_proto_again: key_keyid =
skb_flow_dissector_target(flow_dissector,
FLOW_DISSECTOR_KEY_GRE_KEYID,
target_container);
- key_keyid->keyid = *keyid;
+ if (gre_ver == 0)
+ key_keyid->keyid = *keyid;
+ else
+ key_keyid->keyid = *keyid &
htonl(0xffff);
}
nhoff += 4;
}
if (hdr->flags & GRE_SEQ)
nhoff += 4;
- if (proto == htons(ETH_P_TEB)) {
- const struct ethhdr *eth;
- struct ethhdr _eth;
-
- eth = __skb_header_pointer(skb, nhoff,
- sizeof(_eth),
- data, hlen, &_eth);
- if (!eth)
- goto out_bad;
- proto = eth->h_proto;
- nhoff += sizeof(*eth);
-
- /* Cap headers that we access via pointers at the
- * end of the Ethernet header as our maximum alignment
- * at that point is only 2 bytes.
- */
- if (NET_IP_ALIGN)
- hlen = nhoff;
+ if (gre_ver == 0) {
+ if (proto == htons(ETH_P_TEB)) {
+ const struct ethhdr *eth;
+ struct ethhdr _eth;
+
+ eth = __skb_header_pointer(skb, nhoff,
+ sizeof(_eth),
+ data, hlen, &_eth);
+ if (!eth)
+ goto out_bad;
+ proto = eth->h_proto;
+ nhoff += sizeof(*eth);
+
+ /* Cap headers that we access via
pointers at the
+ * end of the Ethernet header as our
maximum alignment
+ * at that point is only 2 bytes.
+ */
+ if (NET_IP_ALIGN)
+ hlen = nhoff;
+ }
+ } else { /* Version 1 */
+ if (hdr->flags & GRE_ACK)
+ offset += 4;
+
+ if (proto == GRE_PROTO_PPP) {
+ u8 _ppp_hdr[PPP_HDRLEN];
+ u8 *ppp_hdr;
+
+ ppp_hdr = skb_header_pointer(skb,
nhoff + offset,
+ sizeof(_ppp_hdr), _ppp_hdr);
+ if (!ppp_hdr)
+ goto out_bad;
+
+ switch (PPP_PROTOCOL(ppp_hdr));
+ case PPP_IP:
+ proto = htons(ETH_P_IP);
+ break;
+ case PPP_IPV6:
+ proto = htons(ETH_P_IPV6);
+ break;
+ default:
+ /* Could probably catch some
more like MPLS */
+ break;
+ }
+
+ offset += PPP_HDRLEN;
+ }
}
key_control->flags |= FLOW_DIS_ENCAPSULATION;
From: Philip Prindeville <hidden> Date: 2016-08-03 20:46:37
Inline…
quoted hunk
On Aug 3, 2016, at 8:52 AM, fgao@48lvckh6395k16k5.yundunddos.com wrote:
From: Gao Feng <redacted>
The PPTP is encapsulated by GRE header with that GRE_VERSION bits
must contain one. But current GRE RPS needs the GRE_VERSION must be
zero. So RPS does not work for PPTP traffic.
In my test environment, there are four MIPS cores, and all traffic
are passed through by PPTP. As a result, only one core is 100% busy
while other three cores are very idle. After this patch, the usage
of four cores are balanced well.
Signed-off-by: Gao Feng <redacted>
---
v3: 1) Move struct pptp_gre_header defination into new file pptp.h
2) Use sizeof GRE and PPTP type instead of literal value;
3) Remove strict flag check for PPTP to robust;
4) Consolidate the codes again;
v2: Update according to Tom and Philp's advice.
1) Consolidate the codes with GRE version 0 path;
2) Use PPP_PROTOCOL to get ppp protol;
3) Set the FLOW_DIS_ENCAPSULATION flag;
v1: Intial patch
drivers/net/ppp/pptp.c | 36 +----------
include/net/pptp.h | 40 ++++++++++++
include/uapi/linux/if_tunnel.h | 7 +-
net/core/flow_dissector.c | 141 +++++++++++++++++++++++++----------------
4 files changed, 134 insertions(+), 90 deletions(-)
create mode 100644 include/net/pptp.h
ip_proto_again:
switch (ip_proto) {
case IPPROTO_GRE: {
- struct gre_hdr {
- __be16 flags;
- __be16 proto;
- } *hdr, _hdr;
+ struct gre_base_hdr *hdr, _hdr;
hdr = __skb_header_pointer(skb, nhoff, sizeof(_hdr), data, hlen, &_hdr);
if (!hdr)
goto out_bad;
- /*
- * Only look inside GRE if version zero and no
- * routing
- */
- if (hdr->flags & (GRE_VERSION | GRE_ROUTING))
- break;
- proto = hdr->proto;
- nhoff += 4;
- if (hdr->flags & GRE_CSUM)
- nhoff += 4;
- if (hdr->flags & GRE_KEY) {
- const __be32 *keyid;
- __be32 _keyid;
+ /* Only look inside GRE without routing */
+ if (!(hdr->flags & GRE_ROUTING)) {
+ int offset = 0;
- keyid = __skb_header_pointer(skb, nhoff, sizeof(_keyid),
- data, hlen, &_keyid);
+ proto = hdr->protocol;
- if (!keyid)
- goto out_bad;
+ if (hdr->flags & GRE_VERSION) {
+ /* Maybe PPTP in GRE */
+ if (!(proto == GRE_PROTO_PPP && (hdr->flags & GRE_KEY) &&
+ (hdr->flags & GRE_VERSION) == GRE_VERSION_1))
+ break;
+ }
- if (dissector_uses_key(flow_dissector,
- FLOW_DISSECTOR_KEY_GRE_KEYID)) {
- key_keyid = skb_flow_dissector_target(flow_dissector,
- FLOW_DISSECTOR_KEY_GRE_KEYID,
- target_container);
- key_keyid->keyid = *keyid;
+ offset += sizeof(struct gre_base_hdr);
+
+ if (hdr->flags & GRE_CSUM)
+ offset += sizeof(__be32);
This doesn’t tell me as much as taking the sizeof() of the particular field (by name) in the packet that you’re skipping. Best way to do this is naming the field in the structure…
Hi Tom,
inline comments
On Thu, Aug 4, 2016 at 12:15 AM, Tom Herbert [off-list ref] wrote:
On Wed, Aug 3, 2016 at 7:52 AM, [off-list ref] wrote:
quoted
From: Gao Feng <redacted>
The PPTP is encapsulated by GRE header with that GRE_VERSION bits
must contain one. But current GRE RPS needs the GRE_VERSION must be
zero. So RPS does not work for PPTP traffic.
In my test environment, there are four MIPS cores, and all traffic
are passed through by PPTP. As a result, only one core is 100% busy
while other three cores are very idle. After this patch, the usage
of four cores are balanced well.
Signed-off-by: Gao Feng <redacted>
---
v3: 1) Move struct pptp_gre_header defination into new file pptp.h
2) Use sizeof GRE and PPTP type instead of literal value;
3) Remove strict flag check for PPTP to robust;
4) Consolidate the codes again;
v2: Update according to Tom and Philp's advice.
1) Consolidate the codes with GRE version 0 path;
2) Use PPP_PROTOCOL to get ppp protol;
3) Set the FLOW_DIS_ENCAPSULATION flag;
v1: Intial patch
drivers/net/ppp/pptp.c | 36 +----------
include/net/pptp.h | 40 ++++++++++++
include/uapi/linux/if_tunnel.h | 7 +-
net/core/flow_dissector.c | 141 +++++++++++++++++++++++++----------------
4 files changed, 134 insertions(+), 90 deletions(-)
create mode 100644 include/net/pptp.h
@@ -338,71 +340,102 @@ mpls:ip_proto_again:switch(ip_proto){caseIPPROTO_GRE:{-structgre_hdr{-__be16flags;-__be16proto;-}*hdr,_hdr;+structgre_base_hdr*hdr,_hdr;hdr=__skb_header_pointer(skb,nhoff,sizeof(_hdr),data,hlen,&_hdr);if(!hdr)gotoout_bad;-/*-*OnlylookinsideGREifversionzeroandno-*routing-*/-if(hdr->flags&(GRE_VERSION|GRE_ROUTING))-break;-proto=hdr->proto;-nhoff+=4;-if(hdr->flags&GRE_CSUM)-nhoff+=4;-if(hdr->flags&GRE_KEY){-const__be32*keyid;-__be32_keyid;+/* Only look inside GRE without routing */+if(!(hdr->flags&GRE_ROUTING)){+intoffset=0;-keyid=__skb_header_pointer(skb,nhoff,sizeof(_keyid),-data,hlen,&_keyid);+proto=hdr->protocol;-if(!keyid)-gotoout_bad;+if(hdr->flags&GRE_VERSION){+/* Maybe PPTP in GRE */+if(!(proto==GRE_PROTO_PPP&&(hdr->flags&GRE_KEY)&&+(hdr->flags&GRE_VERSION)==GRE_VERSION_1))+break;+}-if(dissector_uses_key(flow_dissector,-FLOW_DISSECTOR_KEY_GRE_KEYID)){-key_keyid=skb_flow_dissector_target(flow_dissector,-FLOW_DISSECTOR_KEY_GRE_KEYID,-target_container);-key_keyid->keyid=*keyid;+offset+=sizeof(structgre_base_hdr);++if(hdr->flags&GRE_CSUM)+offset+=sizeof(__be32);++if(hdr->flags&GRE_KEY){+const__be32*keyid;+__be32_keyid;++keyid=__skb_header_pointer(skb,nhoff+offset,sizeof(_keyid),+data,hlen,&_keyid);++if(!keyid)+gotoout_bad;++if(dissector_uses_key(flow_dissector,+FLOW_DISSECTOR_KEY_GRE_KEYID)){+key_keyid=skb_flow_dissector_target(flow_dissector,+FLOW_DISSECTOR_KEY_GRE_KEYID,+target_container);+key_keyid->keyid=*keyid;+}+offset+=sizeof(_keyid);}-nhoff+=4;-}-if(hdr->flags&GRE_SEQ)-nhoff+=4;-if(proto==htons(ETH_P_TEB)){-conststructethhdr*eth;-structethhdr_eth;--eth=__skb_header_pointer(skb,nhoff,-sizeof(_eth),-data,hlen,&_eth);-if(!eth)-gotoout_bad;-proto=eth->h_proto;-nhoff+=sizeof(*eth);--/* Cap headers that we access via pointers at the-*endoftheEthernetheaderasourmaximumalignment-*atthatpointisonly2bytes.-*/-if(NET_IP_ALIGN)-hlen=nhoff;-}-key_control->flags|=FLOW_DIS_ENCAPSULATION;-if(flags&FLOW_DISSECTOR_F_STOP_AT_ENCAP)-gotoout_good;+if(hdr->flags&GRE_SEQ)+offset+=sizeof(((structpptp_gre_header*)0)->seq);++if(hdr->flags&GRE_ACK)+offset+=sizeof(((structpptp_gre_header*)0)->ack);++if(proto==GRE_PROTO_PPP){+u8_ppp_hdr[PPP_HDRLEN];+u8*ppp_hdr;++ppp_hdr=skb_header_pointer(skb,nhoff+offset,+sizeof(_ppp_hdr),_ppp_hdr);+if(!ppp_hdr)+gotoout_bad;++proto=PPP_PROTOCOL(ppp_hdr);+if(proto==PPP_IP)+proto=htons(ETH_P_IP);+elseif(proto==PPP_IPV6)+proto=htons(ETH_P_IPV6);+else+break;++offset+=PPP_HDRLEN;+}elseif(proto==htons(ETH_P_TEB)){+conststructethhdr*eth;+structethhdr_eth;++eth=__skb_header_pointer(skb,nhoff+offset,+sizeof(_eth),+data,hlen,&_eth);+if(!eth)+gotoout_bad;+proto=eth->h_proto;+offset+=sizeof(*eth);++/* Cap headers that we access via pointers at the+*endoftheEthernetheaderasourmaximumalignment+*atthatpointisonly2bytes.+*/+if(NET_IP_ALIGN)+hlen=(nhoff+offset);+}-gotoagain;+nhoff+=offset;+key_control->flags|=FLOW_DIS_ENCAPSULATION;+if(flags&FLOW_DISSECTOR_F_STOP_AT_ENCAP)+gotoout_good;++gotoagain;+}+break;}caseNEXTHDR_HOP:caseNEXTHDR_ROUTING:--
1.9.1
HI Feng,
Please be careful about order of processing GRE options, keyid must be
handled first.
Thanks your reminder. But I think the keyid should be processed
secondly and I did it in v4 patch.
Because the keyid option is processed secondly in original codes.
GRE_ACK looks like the only new field that needs to be
considered for v1. Also, the keyid in v1 is split into two 16 bit
fields; the first is payload length which is not usable for entropy,
but the second (Call ID) does look useful for that. I would suggest
the IPPROTO_GRE could look something like:
data, hlen, &_hdr);
if (!hdr)
goto out_bad;
+
+ /* Only look inside GRE for versions 0 and 1 */
+ gre_ver = hdr->flags & GRE_VERSION;
+ if (gre_ver > 1)
+ break;
/*
- * Only look inside GRE if version zero and no
- * routing
+ * Only look inside GRE if no routing
*/
- if (hdr->flags & (GRE_VERSION | GRE_ROUTING))
+ if (hdr->flags & GRE_ROUTING)
break;
proto = hdr->proto;
@@ -372,30 +377,62 @@ ip_proto_again: key_keyid =
skb_flow_dissector_target(flow_dissector,
FLOW_DISSECTOR_KEY_GRE_KEYID,
target_container);
- key_keyid->keyid = *keyid;
+ if (gre_ver == 0)
+ key_keyid->keyid = *keyid;
+ else
+ key_keyid->keyid = *keyid &
htonl(0xffff);
}
nhoff += 4;
}
if (hdr->flags & GRE_SEQ)
nhoff += 4;
- if (proto == htons(ETH_P_TEB)) {
- const struct ethhdr *eth;
- struct ethhdr _eth;
-
- eth = __skb_header_pointer(skb, nhoff,
- sizeof(_eth),
- data, hlen, &_eth);
- if (!eth)
- goto out_bad;
- proto = eth->h_proto;
- nhoff += sizeof(*eth);
-
- /* Cap headers that we access via pointers at the
- * end of the Ethernet header as our maximum alignment
- * at that point is only 2 bytes.
- */
- if (NET_IP_ALIGN)
- hlen = nhoff;
+ if (gre_ver == 0) {
+ if (proto == htons(ETH_P_TEB)) {
+ const struct ethhdr *eth;
+ struct ethhdr _eth;
+
+ eth = __skb_header_pointer(skb, nhoff,
+ sizeof(_eth),
+ data, hlen, &_eth);
+ if (!eth)
+ goto out_bad;
+ proto = eth->h_proto;
+ nhoff += sizeof(*eth);
+
+ /* Cap headers that we access via
pointers at the
+ * end of the Ethernet header as our
maximum alignment
+ * at that point is only 2 bytes.
+ */
+ if (NET_IP_ALIGN)
+ hlen = nhoff;
+ }
+ } else { /* Version 1 */
+ if (hdr->flags & GRE_ACK)
+ offset += 4;
+
+ if (proto == GRE_PROTO_PPP) {
+ u8 _ppp_hdr[PPP_HDRLEN];
+ u8 *ppp_hdr;
+
+ ppp_hdr = skb_header_pointer(skb,
nhoff + offset,
+ sizeof(_ppp_hdr), _ppp_hdr);
+ if (!ppp_hdr)
+ goto out_bad;
+
+ switch (PPP_PROTOCOL(ppp_hdr));
+ case PPP_IP:
+ proto = htons(ETH_P_IP);
+ break;
+ case PPP_IPV6:
+ proto = htons(ETH_P_IPV6);
+ break;
+ default:
+ /* Could probably catch some
more like MPLS */
+ break;
+ }
+
+ offset += PPP_HDRLEN;
+ }
}
key_control->flags |= FLOW_DIS_ENCAPSULATION;
inline comment.
There are two comments that I am not clear.
Best Regards
Feng
On Thu, Aug 4, 2016 at 4:43 AM, Philip Prindeville
[off-list ref] wrote:
Inline…
quoted
On Aug 3, 2016, at 8:52 AM, fgao@48lvckh6395k16k5.yundunddos.com wrote:
From: Gao Feng <redacted>
The PPTP is encapsulated by GRE header with that GRE_VERSION bits
must contain one. But current GRE RPS needs the GRE_VERSION must be
zero. So RPS does not work for PPTP traffic.
In my test environment, there are four MIPS cores, and all traffic
are passed through by PPTP. As a result, only one core is 100% busy
while other three cores are very idle. After this patch, the usage
of four cores are balanced well.
Signed-off-by: Gao Feng <redacted>
---
v3: 1) Move struct pptp_gre_header defination into new file pptp.h
2) Use sizeof GRE and PPTP type instead of literal value;
3) Remove strict flag check for PPTP to robust;
4) Consolidate the codes again;
v2: Update according to Tom and Philp's advice.
1) Consolidate the codes with GRE version 0 path;
2) Use PPP_PROTOCOL to get ppp protol;
3) Set the FLOW_DIS_ENCAPSULATION flag;
v1: Intial patch
drivers/net/ppp/pptp.c | 36 +----------
include/net/pptp.h | 40 ++++++++++++
include/uapi/linux/if_tunnel.h | 7 +-
net/core/flow_dissector.c | 141 +++++++++++++++++++++++++----------------
4 files changed, 134 insertions(+), 90 deletions(-)
create mode 100644 include/net/pptp.h
ip_proto_again:
switch (ip_proto) {
case IPPROTO_GRE: {
- struct gre_hdr {
- __be16 flags;
- __be16 proto;
- } *hdr, _hdr;
+ struct gre_base_hdr *hdr, _hdr;
hdr = __skb_header_pointer(skb, nhoff, sizeof(_hdr), data, hlen, &_hdr);
if (!hdr)
goto out_bad;
- /*
- * Only look inside GRE if version zero and no
- * routing
- */
- if (hdr->flags & (GRE_VERSION | GRE_ROUTING))
- break;
- proto = hdr->proto;
- nhoff += 4;
- if (hdr->flags & GRE_CSUM)
- nhoff += 4;
- if (hdr->flags & GRE_KEY) {
- const __be32 *keyid;
- __be32 _keyid;
+ /* Only look inside GRE without routing */
+ if (!(hdr->flags & GRE_ROUTING)) {
+ int offset = 0;
- keyid = __skb_header_pointer(skb, nhoff, sizeof(_keyid),
- data, hlen, &_keyid);
+ proto = hdr->protocol;
- if (!keyid)
- goto out_bad;
+ if (hdr->flags & GRE_VERSION) {
+ /* Maybe PPTP in GRE */
+ if (!(proto == GRE_PROTO_PPP && (hdr->flags & GRE_KEY) &&
+ (hdr->flags & GRE_VERSION) == GRE_VERSION_1))
+ break;
+ }
- if (dissector_uses_key(flow_dissector,
- FLOW_DISSECTOR_KEY_GRE_KEYID)) {
- key_keyid = skb_flow_dissector_target(flow_dissector,
- FLOW_DISSECTOR_KEY_GRE_KEYID,
- target_container);
- key_keyid->keyid = *keyid;
+ offset += sizeof(struct gre_base_hdr);
+
+ if (hdr->flags & GRE_CSUM)
+ offset += sizeof(__be32);
This doesn’t tell me as much as taking the sizeof() of the particular field (by name) in the packet that you’re skipping. Best way to do this is naming the field in the structure…
inline comment.
There are two comments that I am not clear.
Best Regards
Feng
On Thu, Aug 4, 2016 at 4:43 AM, Philip Prindeville
[off-list ref] wrote:
quoted
Inline…
quoted
On Aug 3, 2016, at 8:52 AM, fgao@48lvckh6395k16k5.yundunddos.com wrote:
From: Gao Feng <redacted>
The PPTP is encapsulated by GRE header with that GRE_VERSION bits
must contain one. But current GRE RPS needs the GRE_VERSION must be
zero. So RPS does not work for PPTP traffic.
In my test environment, there are four MIPS cores, and all traffic
are passed through by PPTP. As a result, only one core is 100% busy
while other three cores are very idle. After this patch, the usage
of four cores are balanced well.
Signed-off-by: Gao Feng <redacted>
---
v3: 1) Move struct pptp_gre_header defination into new file pptp.h
2) Use sizeof GRE and PPTP type instead of literal value;
3) Remove strict flag check for PPTP to robust;
4) Consolidate the codes again;
v2: Update according to Tom and Philp's advice.
1) Consolidate the codes with GRE version 0 path;
2) Use PPP_PROTOCOL to get ppp protol;
3) Set the FLOW_DIS_ENCAPSULATION flag;
v1: Intial patch
drivers/net/ppp/pptp.c | 36 +----------
include/net/pptp.h | 40 ++++++++++++
include/uapi/linux/if_tunnel.h | 7 +-
net/core/flow_dissector.c | 141 +++++++++++++++++++++++++----------------
4 files changed, 134 insertions(+), 90 deletions(-)
create mode 100644 include/net/pptp.h
What about a definition of a V0 (RFC-1701) packet? We’re handling both, so it makes sense to define both.
I don't get you. The struct "gre_base_hdr" is defined in gre.h. Do you
mean define them in same file ?
Sorry, I phrased that poorly. Yes, they're both defined (in different
headers)... but when you're parsing the v0 header you're not referencing
the gre_base_hdr members to calculate your offsets.
-Philip
ip_proto_again:
switch (ip_proto) {
case IPPROTO_GRE: {
- struct gre_hdr {
- __be16 flags;
- __be16 proto;
- } *hdr, _hdr;
+ struct gre_base_hdr *hdr, _hdr;
hdr = __skb_header_pointer(skb, nhoff, sizeof(_hdr), data, hlen, &_hdr);
if (!hdr)
goto out_bad;
- /*
- * Only look inside GRE if version zero and no
- * routing
- */
- if (hdr->flags & (GRE_VERSION | GRE_ROUTING))
- break;
- proto = hdr->proto;
- nhoff += 4;
- if (hdr->flags & GRE_CSUM)
- nhoff += 4;
- if (hdr->flags & GRE_KEY) {
- const __be32 *keyid;
- __be32 _keyid;
+ /* Only look inside GRE without routing */
+ if (!(hdr->flags & GRE_ROUTING)) {
+ int offset = 0;
- keyid = __skb_header_pointer(skb, nhoff, sizeof(_keyid),
- data, hlen, &_keyid);
+ proto = hdr->protocol;
- if (!keyid)
- goto out_bad;
+ if (hdr->flags & GRE_VERSION) {
+ /* Maybe PPTP in GRE */
+ if (!(proto == GRE_PROTO_PPP && (hdr->flags & GRE_KEY) &&
+ (hdr->flags & GRE_VERSION) == GRE_VERSION_1))
+ break;
+ }
- if (dissector_uses_key(flow_dissector,
- FLOW_DISSECTOR_KEY_GRE_KEYID)) {
- key_keyid = skb_flow_dissector_target(flow_dissector,
- FLOW_DISSECTOR_KEY_GRE_KEYID,
- target_container);
- key_keyid->keyid = *keyid;
+ offset += sizeof(struct gre_base_hdr);
+
+ if (hdr->flags & GRE_CSUM)
+ offset += sizeof(__be32);
This doesn’t tell me as much as taking the sizeof() of the particular field (by name) in the packet that you’re skipping. Best way to do this is naming the field in the structure…
Hi Tom & Philp,
The v4 patch is sent already.
Could you help review again please?
Tom,
I follow your modification.
Philp,
I define one new struct gre_full_hdr which contains the completed gre
header, for example, csum, key, and so on.
And these members are not defined in gre_base_hdr.
It is only used to offset the sizeof type.
BTW, I find the struct and macro about pptp and gre are redundant.
I want to refactor them in other patches.
On Thu, Aug 4, 2016 at 8:33 AM, Philp Prindeville
[off-list ref] wrote:
Inline
On 08/03/2016 05:58 PM, Feng Gao wrote:
quoted
inline comment.
There are two comments that I am not clear.
Best Regards
Feng
On Thu, Aug 4, 2016 at 4:43 AM, Philip Prindeville
[off-list ref] wrote:
quoted
Inline…
quoted
On Aug 3, 2016, at 8:52 AM, fgao@48lvckh6395k16k5.yundunddos.com wrote:
From: Gao Feng <redacted>
The PPTP is encapsulated by GRE header with that GRE_VERSION bits
must contain one. But current GRE RPS needs the GRE_VERSION must be
zero. So RPS does not work for PPTP traffic.
In my test environment, there are four MIPS cores, and all traffic
are passed through by PPTP. As a result, only one core is 100% busy
while other three cores are very idle. After this patch, the usage
of four cores are balanced well.
Signed-off-by: Gao Feng <redacted>
---
v3: 1) Move struct pptp_gre_header defination into new file pptp.h
2) Use sizeof GRE and PPTP type instead of literal value;
3) Remove strict flag check for PPTP to robust;
4) Consolidate the codes again;
v2: Update according to Tom and Philp's advice.
1) Consolidate the codes with GRE version 0 path;
2) Use PPP_PROTOCOL to get ppp protol;
3) Set the FLOW_DIS_ENCAPSULATION flag;
v1: Intial patch
drivers/net/ppp/pptp.c | 36 +----------
include/net/pptp.h | 40 ++++++++++++
include/uapi/linux/if_tunnel.h | 7 +-
net/core/flow_dissector.c | 141
+++++++++++++++++++++++++----------------
4 files changed, 134 insertions(+), 90 deletions(-)
create mode 100644 include/net/pptp.h
What about a definition of a V0 (RFC-1701) packet? We’re handling both,
so it makes sense to define both.
I don't get you. The struct "gre_base_hdr" is defined in gre.h. Do you
mean define them in same file ?
Sorry, I phrased that poorly. Yes, they're both defined (in different
headers)... but when you're parsing the v0 header you're not referencing the
gre_base_hdr members to calculate your offsets.
-Philip
quoted
quoted
quoted
+
+
+#endif
diff --git a/include/uapi/linux/if_tunnel.h
b/include/uapi/linux/if_tunnel.h
index 1046f55..7d889db 100644
ip_proto_again:
switch (ip_proto) {
case IPPROTO_GRE: {
- struct gre_hdr {
- __be16 flags;
- __be16 proto;
- } *hdr, _hdr;
+ struct gre_base_hdr *hdr, _hdr;
hdr = __skb_header_pointer(skb, nhoff, sizeof(_hdr),
data, hlen, &_hdr);
if (!hdr)
goto out_bad;
- /*
- * Only look inside GRE if version zero and no
- * routing
- */
- if (hdr->flags & (GRE_VERSION | GRE_ROUTING))
- break;
- proto = hdr->proto;
- nhoff += 4;
- if (hdr->flags & GRE_CSUM)
- nhoff += 4;
- if (hdr->flags & GRE_KEY) {
- const __be32 *keyid;
- __be32 _keyid;
+ /* Only look inside GRE without routing */
+ if (!(hdr->flags & GRE_ROUTING)) {
+ int offset = 0;
- keyid = __skb_header_pointer(skb, nhoff,
sizeof(_keyid),
- data, hlen, &_keyid);
+ proto = hdr->protocol;
- if (!keyid)
- goto out_bad;
+ if (hdr->flags & GRE_VERSION) {
+ /* Maybe PPTP in GRE */
+ if (!(proto == GRE_PROTO_PPP &&
(hdr->flags & GRE_KEY) &&
+ (hdr->flags & GRE_VERSION) ==
GRE_VERSION_1))
+ break;
+ }
- if (dissector_uses_key(flow_dissector,
-
FLOW_DISSECTOR_KEY_GRE_KEYID)) {
- key_keyid =
skb_flow_dissector_target(flow_dissector,
-
FLOW_DISSECTOR_KEY_GRE_KEYID,
-
target_container);
- key_keyid->keyid = *keyid;
+ offset += sizeof(struct gre_base_hdr);
+
+ if (hdr->flags & GRE_CSUM)
+ offset += sizeof(__be32);
This doesn’t tell me as much as taking the sizeof() of the particular
field (by name) in the packet that you’re skipping. Best way to do this is
naming the field in the structure…
Hi Tom & Philp,
The v4 patch is sent already.
Could you help review again please?
Tom,
I follow your modification.
Philp,
I define one new struct gre_full_hdr which contains the completed gre
header, for example, csum, key, and so on.
And these members are not defined in gre_base_hdr.
It is only used to offset the sizeof type.
BTW, I find the struct and macro about pptp and gre are redundant.
I want to refactor them in other patches.
On Thu, Aug 4, 2016 at 8:33 AM, Philp Prindeville
[off-list ref] wrote:
quoted
Inline
On 08/03/2016 05:58 PM, Feng Gao wrote:
quoted
inline comment.
There are two comments that I am not clear.
Best Regards
Feng
On Thu, Aug 4, 2016 at 4:43 AM, Philip Prindeville
[off-list ref] wrote:
quoted
Inline…
quoted
On Aug 3, 2016, at 8:52 AM, fgao@48lvckh6395k16k5.yundunddos.com wrote:
From: Gao Feng <redacted>
The PPTP is encapsulated by GRE header with that GRE_VERSION bits
must contain one. But current GRE RPS needs the GRE_VERSION must be
zero. So RPS does not work for PPTP traffic.
In my test environment, there are four MIPS cores, and all traffic
are passed through by PPTP. As a result, only one core is 100% busy
while other three cores are very idle. After this patch, the usage
of four cores are balanced well.
Signed-off-by: Gao Feng <redacted>
---
v3: 1) Move struct pptp_gre_header defination into new file pptp.h
2) Use sizeof GRE and PPTP type instead of literal value;
3) Remove strict flag check for PPTP to robust;
4) Consolidate the codes again;
v2: Update according to Tom and Philp's advice.
1) Consolidate the codes with GRE version 0 path;
2) Use PPP_PROTOCOL to get ppp protol;
3) Set the FLOW_DIS_ENCAPSULATION flag;
v1: Intial patch
drivers/net/ppp/pptp.c | 36 +----------
include/net/pptp.h | 40 ++++++++++++
include/uapi/linux/if_tunnel.h | 7 +-
net/core/flow_dissector.c | 141
+++++++++++++++++++++++++----------------
4 files changed, 134 insertions(+), 90 deletions(-)
create mode 100644 include/net/pptp.h
What about a definition of a V0 (RFC-1701) packet? We’re handling both,
so it makes sense to define both.
I don't get you. The struct "gre_base_hdr" is defined in gre.h. Do you
mean define them in same file ?
Sorry, I phrased that poorly. Yes, they're both defined (in different
headers)... but when you're parsing the v0 header you're not referencing the
gre_base_hdr members to calculate your offsets.
-Philip
quoted
quoted
quoted
+
+
+#endif
diff --git a/include/uapi/linux/if_tunnel.h
b/include/uapi/linux/if_tunnel.h
index 1046f55..7d889db 100644
ip_proto_again:
switch (ip_proto) {
case IPPROTO_GRE: {
- struct gre_hdr {
- __be16 flags;
- __be16 proto;
- } *hdr, _hdr;
+ struct gre_base_hdr *hdr, _hdr;
hdr = __skb_header_pointer(skb, nhoff, sizeof(_hdr),
data, hlen, &_hdr);
if (!hdr)
goto out_bad;
- /*
- * Only look inside GRE if version zero and no
- * routing
- */
- if (hdr->flags & (GRE_VERSION | GRE_ROUTING))
- break;
- proto = hdr->proto;
- nhoff += 4;
- if (hdr->flags & GRE_CSUM)
- nhoff += 4;
- if (hdr->flags & GRE_KEY) {
- const __be32 *keyid;
- __be32 _keyid;
+ /* Only look inside GRE without routing */
+ if (!(hdr->flags & GRE_ROUTING)) {
+ int offset = 0;
- keyid = __skb_header_pointer(skb, nhoff,
sizeof(_keyid),
- data, hlen, &_keyid);
+ proto = hdr->protocol;
- if (!keyid)
- goto out_bad;
+ if (hdr->flags & GRE_VERSION) {
+ /* Maybe PPTP in GRE */
+ if (!(proto == GRE_PROTO_PPP &&
(hdr->flags & GRE_KEY) &&
+ (hdr->flags & GRE_VERSION) ==
GRE_VERSION_1))
+ break;
+ }
- if (dissector_uses_key(flow_dissector,
-
FLOW_DISSECTOR_KEY_GRE_KEYID)) {
- key_keyid =
skb_flow_dissector_target(flow_dissector,
-
FLOW_DISSECTOR_KEY_GRE_KEYID,
-
target_container);
- key_keyid->keyid = *keyid;
+ offset += sizeof(struct gre_base_hdr);
+
+ if (hdr->flags & GRE_CSUM)
+ offset += sizeof(__be32);
This doesn’t tell me as much as taking the sizeof() of the particular
field (by name) in the packet that you’re skipping. Best way to do this is
naming the field in the structure…