[qca-nss-sfe] Add src iface check with no flush flag

This is required to re-inject the packets to the stack,
if L2 acceleration is not enabled for the flows. By doing
this check, first pass of the flow with the L2 interface will be
skipped and the flow will come to SFE with the L3 interface in the
second pass.

Change-Id: I83585c3cf937451545e7854f51a0389c2ca557c5
Signed-off-by: Murat Sezgin <quic_msezgin@quicinc.com>
diff --git a/exports/sfe_api.h b/exports/sfe_api.h
index 9477550..e224652 100644
--- a/exports/sfe_api.h
+++ b/exports/sfe_api.h
@@ -68,9 +68,15 @@
 #define SFE_RULE_CREATE_FLAG_L2_ENCAP     (1<<7)		/**< Consists of an encapsulating protocol that carries an IPv4 payload within it. */
 #define SFE_RULE_CREATE_FLAG_USE_FLOW_BOTTOM_INTERFACE (1<<8)	/**< Use flow interface number instead of top interface. */
 #define SFE_RULE_CREATE_FLAG_USE_RETURN_BOTTOM_INTERFACE (1<<9) /**< Use return interface number instead of top interface. */
-#define SFE_RULE_CREATE_FLAG_SRC_INTERFACE_CHECK  (1<<10)  	/**< Check source interface. */
-#define SFE_RULE_CREATE_FLAG_FLOW_TRANSMIT_FAST (1<<11) 	/**< Original flow can be transmitted fast. */
-#define SFE_RULE_CREATE_FLAG_RETURN_TRANSMIT_FAST (1<<12) 	/**< Return flow can be transmitted fast. */
+#define SFE_RULE_CREATE_FLAG_FLOW_SRC_INTERFACE_CHECK  (1<<10)  /**< Check source interface on the flow direction. */
+#define SFE_RULE_CREATE_FLAG_RETURN_SRC_INTERFACE_CHECK  (1<<11)
+								/**< Check source interface on the return direction. */
+#define SFE_RULE_CREATE_FLAG_FLOW_TRANSMIT_FAST (1<<12) 	/**< Original flow can be transmitted fast. */
+#define SFE_RULE_CREATE_FLAG_RETURN_TRANSMIT_FAST (1<<13) 	/**< Return flow can be transmitted fast. */
+#define SFE_RULE_CREATE_FLAG_FLOW_SRC_INTERFACE_CHECK_NO_FLUSH  (1<<14)
+								/**< Check source interface on the flow direction but do not flush the connection. */
+#define SFE_RULE_CREATE_FLAG_RETURN_SRC_INTERFACE_CHECK_NO_FLUSH  (1<<15)
+								/**< Check source interface on the return direction but do not flush the connection. */
 
 /*
  * Rule creation validity flags.
diff --git a/sfe_ipv4.c b/sfe_ipv4.c
index 0e12441..637ad9a 100644
--- a/sfe_ipv4.c
+++ b/sfe_ipv4.c
@@ -1390,10 +1390,14 @@
 		}
 	}
 
-	if (msg->rule_flags & SFE_RULE_CREATE_FLAG_SRC_INTERFACE_CHECK) {
+	if (msg->rule_flags & SFE_RULE_CREATE_FLAG_FLOW_SRC_INTERFACE_CHECK) {
 		original_cm->flags |= SFE_IPV4_CONNECTION_MATCH_FLAG_SRC_INTERFACE_CHECK;
 	}
 
+	if (msg->rule_flags & SFE_RULE_CREATE_FLAG_FLOW_SRC_INTERFACE_CHECK_NO_FLUSH) {
+		original_cm->flags |= SFE_IPV4_CONNECTION_MATCH_FLAG_SRC_INTERFACE_CHECK_NO_FLUSH;
+	}
+
 	/*
 	 * Adding PPPoE parameters to original and reply entries based on the direction where
 	 * PPPoE header is valid in ECM rule.
@@ -1428,10 +1432,14 @@
 		ether_addr_copy(reply_cm->pppoe_remote_mac, msg->pppoe_rule.return_pppoe_remote_mac);
 	}
 
-	if (msg->rule_flags & SFE_RULE_CREATE_FLAG_SRC_INTERFACE_CHECK) {
+	if (msg->rule_flags & SFE_RULE_CREATE_FLAG_RETURN_SRC_INTERFACE_CHECK) {
 		reply_cm->flags |= SFE_IPV4_CONNECTION_MATCH_FLAG_SRC_INTERFACE_CHECK;
 	}
 
+	if (msg->rule_flags & SFE_RULE_CREATE_FLAG_RETURN_SRC_INTERFACE_CHECK_NO_FLUSH) {
+		reply_cm->flags |= SFE_IPV4_CONNECTION_MATCH_FLAG_SRC_INTERFACE_CHECK_NO_FLUSH;
+	}
+
 	/*
 	 * For the non-arp interface, we don't write L2 HDR.
 	 */
diff --git a/sfe_ipv4.h b/sfe_ipv4.h
index f19adb1..6c058e0 100644
--- a/sfe_ipv4.h
+++ b/sfe_ipv4.h
@@ -70,7 +70,7 @@
 #define SFE_IPV4_CONNECTION_MATCH_FLAG_INSERT_EGRESS_VLAN_TAG (1<<12)
 					/* Insert VLAN tag */
 #define SFE_IPV4_CONNECTION_MATCH_FLAG_SRC_INTERFACE_CHECK (1<<13)
-					/* Source interface check.*/
+					/* Source interface check */
 #define SFE_IPV4_CONNECTION_MATCH_FLAG_PASSTHROUGH (1<<14)
 					/* passthrough flow: encap/decap to be skipped for this flow */
 #define SFE_IPV4_CONNECTION_MATCH_FLAG_FAST_XMIT (1<<15)
@@ -79,6 +79,8 @@
 					/* Fast xmit flow checked or not */
 #define SFE_IPV4_CONNECTION_MATCH_FLAG_FAST_XMIT_DEV_ADMISSION (1<<17)
 					/* Fast xmit may be possible for this flow, if SFE check passes */
+#define SFE_IPV4_CONNECTION_MATCH_FLAG_SRC_INTERFACE_CHECK_NO_FLUSH (1<<18)
+					/* Source interface check but do not flush the connection */
 
 /*
  * IPv4 connection matching structure.
diff --git a/sfe_ipv4_gre.c b/sfe_ipv4_gre.c
index da05d69..ea9a000 100644
--- a/sfe_ipv4_gre.c
+++ b/sfe_ipv4_gre.c
@@ -101,19 +101,22 @@
 	 * Source interface validate.
 	 */
 	if (unlikely((cm->flags & SFE_IPV4_CONNECTION_MATCH_FLAG_SRC_INTERFACE_CHECK) && (cm->match_dev != dev))) {
-		struct sfe_ipv4_connection *c = cm->connection;
-		int ret;
+		if (!(cm->flags & SFE_IPV4_CONNECTION_MATCH_FLAG_SRC_INTERFACE_CHECK_NO_FLUSH)) {
+			struct sfe_ipv4_connection *c = cm->connection;
+			int ret;
 
-		spin_lock_bh(&si->lock);
-		ret = sfe_ipv4_remove_connection(si, c);
-		spin_unlock_bh(&si->lock);
+			DEBUG_TRACE("flush on source interface check failure\n");
+			spin_lock_bh(&si->lock);
+			ret = sfe_ipv4_remove_connection(si, c);
+			spin_unlock_bh(&si->lock);
 
-		if (ret) {
-			sfe_ipv4_flush_connection(si, c, SFE_SYNC_REASON_FLUSH);
+			if (ret) {
+				sfe_ipv4_flush_connection(si, c, SFE_SYNC_REASON_FLUSH);
+			}
 		}
 		rcu_read_unlock();
 		sfe_ipv4_exception_stats_inc(si, SFE_IPV4_EXCEPTION_EVENT_INVALID_SRC_IFACE);
-		DEBUG_TRACE("flush on wrong source interface check failure\n");
+		DEBUG_TRACE("exception the packet on source interface check failure\n");
 		return 0;
 	}
 
diff --git a/sfe_ipv4_tcp.c b/sfe_ipv4_tcp.c
index 22071ee..aea240e 100644
--- a/sfe_ipv4_tcp.c
+++ b/sfe_ipv4_tcp.c
@@ -195,17 +195,20 @@
 	 * Source interface validate.
 	 */
 	if (unlikely((cm->flags & SFE_IPV4_CONNECTION_MATCH_FLAG_SRC_INTERFACE_CHECK) && (cm->match_dev != dev))) {
-		struct sfe_ipv4_connection *c = cm->connection;
-		spin_lock_bh(&si->lock);
-		ret = sfe_ipv4_remove_connection(si, c);
-		spin_unlock_bh(&si->lock);
+		if (!(cm->flags & SFE_IPV4_CONNECTION_MATCH_FLAG_SRC_INTERFACE_CHECK_NO_FLUSH)) {
+			struct sfe_ipv4_connection *c = cm->connection;
+			DEBUG_TRACE("flush on source interface check failure\n");
+			spin_lock_bh(&si->lock);
+			ret = sfe_ipv4_remove_connection(si, c);
+			spin_unlock_bh(&si->lock);
 
-		if (ret) {
-			sfe_ipv4_flush_connection(si, c, SFE_SYNC_REASON_FLUSH);
+			if (ret) {
+				sfe_ipv4_flush_connection(si, c, SFE_SYNC_REASON_FLUSH);
+			}
 		}
 		rcu_read_unlock();
 		sfe_ipv4_exception_stats_inc(si, SFE_IPV4_EXCEPTION_EVENT_INVALID_SRC_IFACE);
-		DEBUG_TRACE("flush on wrong source interface check failure\n");
+		DEBUG_TRACE("exception the packet on source interface check failure\n");
 		return 0;
 	}
 
diff --git a/sfe_ipv4_udp.c b/sfe_ipv4_udp.c
index abaa873..922e54e 100644
--- a/sfe_ipv4_udp.c
+++ b/sfe_ipv4_udp.c
@@ -191,17 +191,20 @@
 	 * Source interface validate.
 	 */
 	if (unlikely((cm->flags & SFE_IPV4_CONNECTION_MATCH_FLAG_SRC_INTERFACE_CHECK) && (cm->match_dev != dev))) {
-		struct sfe_ipv4_connection *c = cm->connection;
-		spin_lock_bh(&si->lock);
-		ret = sfe_ipv4_remove_connection(si, c);
-		spin_unlock_bh(&si->lock);
+		if (!(cm->flags & SFE_IPV4_CONNECTION_MATCH_FLAG_SRC_INTERFACE_CHECK_NO_FLUSH)) {
+			struct sfe_ipv4_connection *c = cm->connection;
+			DEBUG_TRACE("flush on source interface check failure\n");
+			spin_lock_bh(&si->lock);
+			ret = sfe_ipv4_remove_connection(si, c);
+			spin_unlock_bh(&si->lock);
 
-		if (ret) {
-			sfe_ipv4_flush_connection(si, c, SFE_SYNC_REASON_FLUSH);
+			if (ret) {
+				sfe_ipv4_flush_connection(si, c, SFE_SYNC_REASON_FLUSH);
+			}
 		}
 		rcu_read_unlock();
 		sfe_ipv4_exception_stats_inc(si, SFE_IPV4_EXCEPTION_EVENT_INVALID_SRC_IFACE);
-		DEBUG_TRACE("flush on wrong source interface check failure\n");
+		DEBUG_TRACE("exception the packet on source interface check failure\n");
 		return 0;
 	}
 
diff --git a/sfe_ipv6.c b/sfe_ipv6.c
index 01183af..0accdc6 100644
--- a/sfe_ipv6.c
+++ b/sfe_ipv6.c
@@ -1405,10 +1405,14 @@
 		ether_addr_copy(reply_cm->pppoe_remote_mac, msg->pppoe_rule.return_pppoe_remote_mac);
 	}
 
-	if (msg->rule_flags & SFE_RULE_CREATE_FLAG_SRC_INTERFACE_CHECK) {
+	if (msg->rule_flags & SFE_RULE_CREATE_FLAG_FLOW_SRC_INTERFACE_CHECK) {
 		original_cm->flags |= SFE_IPV6_CONNECTION_MATCH_FLAG_SRC_INTERFACE_CHECK;
 	}
 
+	if (msg->rule_flags & SFE_RULE_CREATE_FLAG_FLOW_SRC_INTERFACE_CHECK_NO_FLUSH) {
+		original_cm->flags |= SFE_IPV6_CONNECTION_MATCH_FLAG_SRC_INTERFACE_CHECK_NO_FLUSH;
+	}
+
 	/*
 	 * For the non-arp interface, we don't write L2 HDR.
 	 * Excluding PPPoE from this, since we are now supporting PPPoE encap/decap.
@@ -1674,10 +1678,14 @@
 		}
 	}
 
-	if (msg->rule_flags & SFE_RULE_CREATE_FLAG_SRC_INTERFACE_CHECK) {
+	if (msg->rule_flags & SFE_RULE_CREATE_FLAG_RETURN_SRC_INTERFACE_CHECK) {
 		reply_cm->flags |= SFE_IPV6_CONNECTION_MATCH_FLAG_SRC_INTERFACE_CHECK;
 	}
 
+	if (msg->rule_flags & SFE_RULE_CREATE_FLAG_RETURN_SRC_INTERFACE_CHECK_NO_FLUSH) {
+		reply_cm->flags |= SFE_IPV6_CONNECTION_MATCH_FLAG_SRC_INTERFACE_CHECK_NO_FLUSH;
+	}
+
 	/*
 	 * For the non-arp interface, we don't write L2 HDR.
 	 * Excluding PPPoE from this, since we are now supporting PPPoE encap/decap.
diff --git a/sfe_ipv6.h b/sfe_ipv6.h
index b32de57..865a7e1 100644
--- a/sfe_ipv6.h
+++ b/sfe_ipv6.h
@@ -82,7 +82,7 @@
 #define SFE_IPV6_CONNECTION_MATCH_FLAG_INSERT_EGRESS_VLAN_TAG (1<<12)
 					/* Insert VLAN tag */
 #define SFE_IPV6_CONNECTION_MATCH_FLAG_SRC_INTERFACE_CHECK (1<<13)
-					/* Source interface check.*/
+					/* Source interface check */
 #define SFE_IPV6_CONNECTION_MATCH_FLAG_PASSTHROUGH (1<<14)
 					/* passthrough flow: encap/decap to be skipped for this flow */
 #define SFE_IPV6_CONNECTION_MATCH_FLAG_FAST_XMIT (1<<15)
@@ -91,6 +91,8 @@
 					/* fast xmit checked or not*/
 #define SFE_IPV6_CONNECTION_MATCH_FLAG_FAST_XMIT_DEV_ADMISSION (1<<17)
 					/* Fast xmit may be possible for this flow, if SFE check passes */
+#define SFE_IPV6_CONNECTION_MATCH_FLAG_SRC_INTERFACE_CHECK_NO_FLUSH (1<<18)
+					/* Source interface check but do not flush the connection */
 
 /*
  * IPv6 connection matching structure.
diff --git a/sfe_ipv6_gre.c b/sfe_ipv6_gre.c
index 1db0f6f..eae7d56 100644
--- a/sfe_ipv6_gre.c
+++ b/sfe_ipv6_gre.c
@@ -100,18 +100,21 @@
 	 * Source interface validate.
 	 */
 	if (unlikely((cm->flags & SFE_IPV6_CONNECTION_MATCH_FLAG_SRC_INTERFACE_CHECK) && (cm->match_dev != dev))) {
-		struct sfe_ipv6_connection *c = cm->connection;
-		int ret;
-		spin_lock_bh(&si->lock);
-		ret = sfe_ipv6_remove_connection(si, c);
-		spin_unlock_bh(&si->lock);
+		if (!(cm->flags & SFE_IPV6_CONNECTION_MATCH_FLAG_SRC_INTERFACE_CHECK_NO_FLUSH)) {
+			struct sfe_ipv6_connection *c = cm->connection;
+			int ret;
+			DEBUG_TRACE("flush on source interface check failure\n");
+			spin_lock_bh(&si->lock);
+			ret = sfe_ipv6_remove_connection(si, c);
+			spin_unlock_bh(&si->lock);
 
-		if (ret) {
-			sfe_ipv6_flush_connection(si, c, SFE_SYNC_REASON_FLUSH);
+			if (ret) {
+				sfe_ipv6_flush_connection(si, c, SFE_SYNC_REASON_FLUSH);
+			}
 		}
 		rcu_read_unlock();
 		sfe_ipv6_exception_stats_inc(si, SFE_IPV6_EXCEPTION_EVENT_INVALID_SRC_IFACE);
-		DEBUG_TRACE("flush on wrong source interface check failure\n");
+		DEBUG_TRACE("exception the packet on source interface check failure\n");
 		return 0;
 	}
 
diff --git a/sfe_ipv6_tcp.c b/sfe_ipv6_tcp.c
index 5ae829c..e2f2cd8 100644
--- a/sfe_ipv6_tcp.c
+++ b/sfe_ipv6_tcp.c
@@ -197,17 +197,20 @@
 	 * Source interface validate.
 	 */
 	if (unlikely((cm->flags & SFE_IPV6_CONNECTION_MATCH_FLAG_SRC_INTERFACE_CHECK) && (cm->match_dev != dev))) {
-		struct sfe_ipv6_connection *c = cm->connection;
-		spin_lock_bh(&si->lock);
-		ret = sfe_ipv6_remove_connection(si, c);
-		spin_unlock_bh(&si->lock);
+		if (!(cm->flags & SFE_IPV6_CONNECTION_MATCH_FLAG_SRC_INTERFACE_CHECK_NO_FLUSH)) {
+			struct sfe_ipv6_connection *c = cm->connection;
+			DEBUG_TRACE("flush on source interface check failure\n");
+			spin_lock_bh(&si->lock);
+			ret = sfe_ipv6_remove_connection(si, c);
+			spin_unlock_bh(&si->lock);
 
-		if (ret) {
-			sfe_ipv6_flush_connection(si, c, SFE_SYNC_REASON_FLUSH);
+			if (ret) {
+				sfe_ipv6_flush_connection(si, c, SFE_SYNC_REASON_FLUSH);
+			}
 		}
 		rcu_read_unlock();
 		sfe_ipv6_exception_stats_inc(si, SFE_IPV6_EXCEPTION_EVENT_INVALID_SRC_IFACE);
-		DEBUG_TRACE("flush on wrong source interface check failure\n");
+		DEBUG_TRACE("exception the packet on source interface check failure\n");
 		return 0;
 	}
 
diff --git a/sfe_ipv6_udp.c b/sfe_ipv6_udp.c
index 08263bd..0afa6f3 100644
--- a/sfe_ipv6_udp.c
+++ b/sfe_ipv6_udp.c
@@ -207,17 +207,20 @@
 	 * Source interface validate.
 	 */
 	if (unlikely((cm->flags & SFE_IPV6_CONNECTION_MATCH_FLAG_SRC_INTERFACE_CHECK) && (cm->match_dev != dev))) {
-		struct sfe_ipv6_connection *c = cm->connection;
-		spin_lock_bh(&si->lock);
-		ret = sfe_ipv6_remove_connection(si, c);
-		spin_unlock_bh(&si->lock);
+		if (!(cm->flags & SFE_IPV6_CONNECTION_MATCH_FLAG_SRC_INTERFACE_CHECK_NO_FLUSH)) {
+			struct sfe_ipv6_connection *c = cm->connection;
+			DEBUG_TRACE("flush on source interface check failure\n");
+			spin_lock_bh(&si->lock);
+			ret = sfe_ipv6_remove_connection(si, c);
+			spin_unlock_bh(&si->lock);
 
-		if (ret) {
-			sfe_ipv6_flush_connection(si, c, SFE_SYNC_REASON_FLUSH);
+			if (ret) {
+				sfe_ipv6_flush_connection(si, c, SFE_SYNC_REASON_FLUSH);
+			}
 		}
 		rcu_read_unlock();
 		sfe_ipv6_exception_stats_inc(si, SFE_IPV6_EXCEPTION_EVENT_INVALID_SRC_IFACE);
-		DEBUG_TRACE("flush on wrong source interface check failure\n");
+		DEBUG_TRACE("exception the packet on source interface check failure\n");
 		return 0;
 	}