All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/1] rps: Inspect PPTP encapsulated by GRE to get flow hash
@ 2016-07-28  7:14 fgao
  2016-08-02  1:36 ` Philp Prindeville
  2016-08-02 20:35 ` Tom Herbert
  0 siblings, 2 replies; 18+ messages in thread
From: fgao @ 2016-07-28  7:14 UTC (permalink / raw)
  To: davem, philipp, stephen, pshelar, tom, aduyck, netdev
  Cc: gfree.wind, Gao Feng

From: Gao Feng <fgao@ikuai8.com>

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 <fgao@ikuai8.com>
---
 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: Initial patch 

 include/uapi/linux/if_tunnel.h |   5 +-
 net/core/flow_dissector.c      | 146 ++++++++++++++++++++++++++---------------
 2 files changed, 97 insertions(+), 54 deletions(-)

diff --git a/include/uapi/linux/if_tunnel.h b/include/uapi/linux/if_tunnel.h
index 1046f55..dda4e4b 100644
--- a/include/uapi/linux/if_tunnel.h
+++ b/include/uapi/linux/if_tunnel.h
@@ -24,9 +24,12 @@
 #define GRE_SEQ		__cpu_to_be16(0x1000)
 #define GRE_STRICT	__cpu_to_be16(0x0800)
 #define GRE_REC		__cpu_to_be16(0x0700)
-#define GRE_FLAGS	__cpu_to_be16(0x00F8)
+#define GRE_ACK		__cpu_to_be16(0x0080)
+#define GRE_FLAGS	__cpu_to_be16(0x0078)
 #define GRE_VERSION	__cpu_to_be16(0x0007)
 
+#define GRE_PROTO_PPP	__cpu_to_be16(0x880b)
+
 struct ip_tunnel_parm {
 	char			name[IFNAMSIZ];
 	int			link;
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
index 61ad43f..33e957b 100644
--- a/net/core/flow_dissector.c
+++ b/net/core/flow_dissector.c
@@ -346,63 +346,103 @@ ip_proto_again:
 		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;
-
-			keyid = __skb_header_pointer(skb, nhoff, sizeof(_keyid),
-						     data, hlen, &_keyid);
 
-			if (!keyid)
-				goto out_bad;
+		/* Only look inside GRE without routing */
+		if (!(hdr->flags & GRE_ROUTING)) {
+			proto = hdr->proto;
+
+			if (hdr->flags & GRE_VERSION) {
+				/* It should be the PPTP in GRE */
+				u8 _ppp_hdr[PPP_HDRLEN];
+				u8 *ppp_hdr;
+				int offset = 0;
+
+				/* Check the flags according to RFC 2637*/
+				if (!(proto == GRE_PROTO_PPP && (hdr->flags & GRE_KEY) &&
+				      !(hdr->flags & (GRE_CSUM | GRE_STRICT | GRE_REC | GRE_FLAGS)))) {
+					break;
+				}
+
+				/* Skip GRE header */
+				offset += 4;
+				/* Skip payload length and call id */
+				offset += 4;
+
+				if (hdr->flags & GRE_SEQ)
+					offset += 4;
+
+				if (hdr->flags & GRE_ACK)
+					offset += 4;
+
+				ppp_hdr = skb_header_pointer(skb, nhoff + offset, sizeof(_ppp_hdr), _ppp_hdr);
+				if (!ppp_hdr)
+					goto out_bad;
+				proto = PPP_PROTOCOL(ppp_hdr);
+				if (proto == PPP_IP) {
+					nhoff += (PPP_HDRLEN + offset);
+					proto = htons(ETH_P_IP);
+					key_control->flags |= FLOW_DIS_ENCAPSULATION;
+					goto again;
+				} else if (proto == PPP_IPV6) {
+					nhoff += (PPP_HDRLEN + offset);
+					proto = htons(ETH_P_IPV6);
+					key_control->flags |= FLOW_DIS_ENCAPSULATION;
+					goto again;
+				}
+			} else {
+				/* Original GRE */
+				nhoff += 4;
+				if (hdr->flags & GRE_CSUM)
+					nhoff += 4;
+				if (hdr->flags & GRE_KEY) {
+					const __be32 *keyid;
+					__be32 _keyid;
+
+					keyid = __skb_header_pointer(skb, nhoff, sizeof(_keyid),
+								     data, hlen, &_keyid);
+
+					if (!keyid)
+						goto out_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;
+					}
+					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;
+				}
+
+				key_control->flags |= FLOW_DIS_ENCAPSULATION;
+				if (flags & FLOW_DISSECTOR_F_STOP_AT_ENCAP)
+					goto out_good;
 
-			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;
+				goto again;
 			}
-			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;
 		}
-
-		key_control->flags |= FLOW_DIS_ENCAPSULATION;
-		if (flags & FLOW_DISSECTOR_F_STOP_AT_ENCAP)
-			goto out_good;
-
-		goto again;
+		break;
 	}
 	case NEXTHDR_HOP:
 	case NEXTHDR_ROUTING:
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 18+ messages in thread
* [PATCH 1/1] rps: Inspect PPTP encapsulated by GRE to get flow hash
@ 2016-07-27 23:42 fgao
  2016-07-28  0:04 ` Tom Herbert
  0 siblings, 1 reply; 18+ messages in thread
From: fgao @ 2016-07-27 23:42 UTC (permalink / raw)
  To: davem, philipp, stephen, pshelar, tom, aduyck, netdev
  Cc: gfree.wind, Gao Feng

From: Gao Feng <fgao@ikuai8.com>

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 <fgao@ikuai8.com>
---
 v1: Initial patch

 include/uapi/linux/if_tunnel.h |   5 +-
 net/core/flow_dissector.c      | 138 ++++++++++++++++++++++++++---------------
 2 files changed, 92 insertions(+), 51 deletions(-)

diff --git a/include/uapi/linux/if_tunnel.h b/include/uapi/linux/if_tunnel.h
index 1046f55..dda4e4b 100644
--- a/include/uapi/linux/if_tunnel.h
+++ b/include/uapi/linux/if_tunnel.h
@@ -24,9 +24,12 @@
 #define GRE_SEQ		__cpu_to_be16(0x1000)
 #define GRE_STRICT	__cpu_to_be16(0x0800)
 #define GRE_REC		__cpu_to_be16(0x0700)
-#define GRE_FLAGS	__cpu_to_be16(0x00F8)
+#define GRE_ACK		__cpu_to_be16(0x0080)
+#define GRE_FLAGS	__cpu_to_be16(0x0078)
 #define GRE_VERSION	__cpu_to_be16(0x0007)
 
+#define GRE_PROTO_PPP	__cpu_to_be16(0x880b)
+
 struct ip_tunnel_parm {
 	char			name[IFNAMSIZ];
 	int			link;
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
index 61ad43f..d95e060 100644
--- a/net/core/flow_dissector.c
+++ b/net/core/flow_dissector.c
@@ -346,63 +346,101 @@ ip_proto_again:
 		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)
+		/*
+		* Only look inside GRE if version zero and no
+		* routing
+		*/
+		if (!(hdr->flags & (GRE_VERSION | GRE_ROUTING))) {
+			proto = hdr->proto;
 			nhoff += 4;
-		if (hdr->flags & GRE_KEY) {
-			const __be32 *keyid;
-			__be32 _keyid;
+			if (hdr->flags & GRE_CSUM)
+				nhoff += 4;
+			if (hdr->flags & GRE_KEY) {
+				const __be32 *keyid;
+				__be32 _keyid;
+
+				keyid = __skb_header_pointer(skb, nhoff, sizeof(_keyid),
+							     data, hlen, &_keyid);
+
+				if (!keyid)
+					goto out_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;
+				}
+				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;
+			}
 
-			keyid = __skb_header_pointer(skb, nhoff, sizeof(_keyid),
-						     data, hlen, &_keyid);
+			key_control->flags |= FLOW_DIS_ENCAPSULATION;
+			if (flags & FLOW_DISSECTOR_F_STOP_AT_ENCAP)
+				goto out_good;
 
-			if (!keyid)
+			goto again;
+		} else if (hdr->proto == GRE_PROTO_PPP && (hdr->flags & GRE_VERSION) &&
+			(hdr->flags & GRE_KEY) &&
+			!(hdr->flags & (GRE_CSUM | GRE_ROUTING | GRE_STRICT | GRE_REC | GRE_FLAGS))) {
+			/* It should be the PPTP in GRE
+			 * We have checked the flags according to the
+			 * RFC 2637
+			 */
+			struct ppp_frame {
+				/* address & control, just ignore it */
+				__be16 ignore;
+				__be16 proto;
+			} *frame, _frame;
+			int offset = 0;
+
+			/* Skip GRE header */
+			offset += 4;
+			/* Skip payload length and call id */
+			offset += 4;
+
+			if (hdr->flags & GRE_SEQ)
+				offset += 4;
+
+			if (hdr->flags & GRE_ACK)
+				offset += 4;
+
+			frame = skb_header_pointer(skb, nhoff + offset, sizeof(_frame), &_frame);
+			if (!frame)
 				goto out_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;
+			if (frame->proto == __constant_htons(PPP_IP)) {
+				nhoff += (sizeof(*frame) + offset);
+				proto = __constant_htons(ETH_P_IP);
+				goto again;
+			} else if (frame->proto == __constant_htons(PPP_IPV6)) {
+				nhoff += (sizeof(*frame) + offset);
+				proto = __constant_htons(ETH_P_IPV6);
+				goto again;
 			}
-			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;
-		}
-
-		key_control->flags |= FLOW_DIS_ENCAPSULATION;
-		if (flags & FLOW_DISSECTOR_F_STOP_AT_ENCAP)
-			goto out_good;
-
-		goto again;
+		break;
 	}
 	case NEXTHDR_HOP:
 	case NEXTHDR_ROUTING:
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2016-08-03 15:03 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-07-28  7:14 [PATCH 1/1] rps: Inspect PPTP encapsulated by GRE to get flow hash fgao
2016-08-02  1:36 ` Philp Prindeville
2016-08-02  6:10   ` Feng Gao
2016-08-02 17:33     ` Philp Prindeville
2016-08-03  0:22       ` Feng Gao
2016-08-02 20:35 ` Tom Herbert
2016-08-03  0:28   ` Feng Gao
2016-08-03  1:11     ` Philip Prindeville
2016-08-03  1:59     ` Tom Herbert
2016-08-03  2:17       ` Feng Gao
2016-08-03  4:01         ` Tom Herbert
2016-08-03 15:02           ` Feng Gao
  -- strict thread matches above, loose matches on Subject: below --
2016-07-27 23:42 fgao
2016-07-28  0:04 ` Tom Herbert
2016-07-28  0:24   ` Feng Gao
2016-07-28  0:35     ` Feng Gao
2016-07-28  0:46   ` Philp Prindeville
2016-08-01  7:36     ` Feng Gao

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.