shortcut-fe: fix ipsec forwarding issue

SKBs to IPSEC can't be accelerated because they need further
encapsultion in XFRM stack before leaving a network interface.
But on the other direction, SKBs from IPSEC can be forwarded to
an interface directly. In this fix, we accelerate one direction
of XFRM tunnel flows.

Change-Id: I51a7561a7fb12843f8f4bd9455c43ad7c095081c
Signed-off-by: Zhi Chen <zhichen@codeaurora.org>
diff --git a/shortcut-fe/sfe_cm.c b/shortcut-fe/sfe_cm.c
index d463c16..cee000e 100644
--- a/shortcut-fe/sfe_cm.c
+++ b/shortcut-fe/sfe_cm.c
@@ -252,6 +252,16 @@
 		return NF_ACCEPT;
 	}
 
+#ifdef CONFIG_XFRM
+	/*
+	 * Packet to xfrm for encapsulation, we can't process it
+	 */
+	if (unlikely(skb_dst(skb)->xfrm)) {
+		DEBUG_TRACE("packet to xfrm, ignoring\n");
+		return NF_ACCEPT;
+	}
+#endif
+
 	/*
 	 * Don't process packets that are not being forwarded.
 	 */
@@ -392,6 +402,28 @@
 		return NF_ACCEPT;
 	}
 
+#ifdef CONFIG_XFRM
+	sic.original_accel = 1;
+	sic.reply_accel = 1;
+
+	/*
+	 * For packets de-capsulated from xfrm, we still can accelerate it
+	 * on the direction we just received the packet.
+	 */
+	if (unlikely(skb->sp)) {
+		if (sic.protocol == IPPROTO_TCP &&
+			!(sic.flags & SFE_CREATE_FLAG_NO_SEQ_CHECK)) {
+			return NF_ACCEPT;
+		}
+
+		if (CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL) {
+			sic.reply_accel = 0;
+		} else {
+			sic.original_accel = 0;
+		}
+	}
+#endif
+
 	/*
 	 * Get the net device and MAC addresses that correspond to the various source and
 	 * destination host addresses.
diff --git a/shortcut-fe/sfe_cm.h b/shortcut-fe/sfe_cm.h
index 594cdd9..a437788 100644
--- a/shortcut-fe/sfe_cm.h
+++ b/shortcut-fe/sfe_cm.h
@@ -57,6 +57,10 @@
 	uint32_t dest_td_end;
 	uint32_t dest_td_max_end;
 	uint32_t mark;
+#ifdef CONFIG_XFRM
+	uint32_t original_accel;
+	uint32_t reply_accel;
+#endif
 };
 
 /*
diff --git a/shortcut-fe/sfe_ipv4.c b/shortcut-fe/sfe_ipv4.c
index 4b8a5da..055242f 100644
--- a/shortcut-fe/sfe_ipv4.c
+++ b/shortcut-fe/sfe_ipv4.c
@@ -195,6 +195,9 @@
 #ifdef CONFIG_NF_FLOW_COOKIE
 	uint32_t flow_cookie;		/* used flow cookie, for debug */
 #endif
+#ifdef CONFIG_XFRM
+	uint32_t flow_accel;             /* The flow accelerated or not */
+#endif
 
 	/*
 	 * Connection state that we track once we match.
@@ -1281,6 +1284,18 @@
 		return 0;
 	}
 
+#ifdef CONFIG_XFRM
+	/*
+	 * We can't accelerate the flow on this direction, just let it go
+	 * through the slow path.
+	 */
+	if (unlikely(!cm->flow_accel)) {
+		si->packets_not_forwarded++;
+		spin_unlock(&si->lock);
+		return 0;
+	}
+#endif
+
 	/*
 	 * Does our TTL allow forwarding?
 	 */
@@ -1638,6 +1653,17 @@
 		return 0;
 	}
 
+#ifdef CONFIG_XFRM
+	/*
+	 * We can't accelerate the flow on this direction, just let it go
+	 * through the slow path.
+	 */
+	if (unlikely(!cm->flow_accel)) {
+		si->packets_not_forwarded++;
+		spin_unlock(&si->lock);
+		return 0;
+	}
+#endif
 	/*
 	 * Does our TTL allow forwarding?
 	 */
@@ -2500,6 +2526,9 @@
 #ifdef CONFIG_NF_FLOW_COOKIE
 	original_cm->flow_cookie = 0;
 #endif
+#ifdef CONFIG_XFRM
+	original_cm->flow_accel = sic->original_accel;
+#endif
 	original_cm->active_next = NULL;
 	original_cm->active_prev = NULL;
 	original_cm->active = false;
@@ -2548,6 +2577,9 @@
 #ifdef CONFIG_NF_FLOW_COOKIE
 	reply_cm->flow_cookie = 0;
 #endif
+#ifdef CONFIG_XFRM
+	reply_cm->flow_accel = sic->reply_accel;
+#endif
 	reply_cm->active_next = NULL;
 	reply_cm->active_prev = NULL;
 	reply_cm->active = false;
diff --git a/shortcut-fe/sfe_ipv6.c b/shortcut-fe/sfe_ipv6.c
index 3f5d6c0..b2958c6 100644
--- a/shortcut-fe/sfe_ipv6.c
+++ b/shortcut-fe/sfe_ipv6.c
@@ -225,6 +225,9 @@
 #ifdef CONFIG_NF_FLOW_COOKIE
 	uint32_t flow_cookie;		/* used flow cookie, for debug */
 #endif
+#ifdef CONFIG_XFRM
+	uint32_t flow_accel;            /* The flow accelerated or not */
+#endif
 
 	/*
 	 * Connection state that we track once we match.
@@ -1346,6 +1349,18 @@
 		return 0;
 	}
 
+#ifdef CONFIG_XFRM
+	/*
+	 * We can't accelerate the flow on this direction, just let it go
+	 * through the slow path.
+	 */
+	if (unlikely(!cm->flow_accel)) {
+		si->packets_not_forwarded++;
+		spin_unlock(&si->lock);
+		return 0;
+	}
+#endif
+
 	/*
 	 * Does our hop_limit allow forwarding?
 	 */
@@ -1682,6 +1697,18 @@
 		return 0;
 	}
 
+#ifdef CONFIG_XFRM
+	/*
+	 * We can't accelerate the flow on this direction, just let it go
+	 * through the slow path.
+	 */
+	if (unlikely(!cm->flow_accel)) {
+		si->packets_not_forwarded++;
+		spin_unlock(&si->lock);
+		return 0;
+	}
+#endif
+
 	/*
 	 * Does our hop_limit allow forwarding?
 	 */
@@ -2519,6 +2546,9 @@
 #ifdef CONFIG_NF_FLOW_COOKIE
 	original_cm->flow_cookie = 0;
 #endif
+#ifdef CONFIG_XFRM
+	original_cm->flow_accel = sic->original_accel;
+#endif
 	original_cm->active_next = NULL;
 	original_cm->active_prev = NULL;
 	original_cm->active = false;
@@ -2567,6 +2597,9 @@
 #ifdef CONFIG_NF_FLOW_COOKIE
 	reply_cm->flow_cookie = 0;
 #endif
+#ifdef CONFIG_XFRM
+	reply_cm->flow_accel = sic->reply_accel;
+#endif
 	reply_cm->active_next = NULL;
 	reply_cm->active_prev = NULL;
 	reply_cm->active = false;