Merge "[qca-nss-sfe] Accelerate DS-LITE traffic with encap_limit"
diff --git a/sfe_ipv6_tunipip6.c b/sfe_ipv6_tunipip6.c
index aaf2f89..8690f26 100644
--- a/sfe_ipv6_tunipip6.c
+++ b/sfe_ipv6_tunipip6.c
@@ -42,7 +42,10 @@
 	struct sfe_ipv6_addr *dest_ip;
 	__be16 src_port = 0;
 	__be16 dest_port = 0;
+	unsigned int ihl_tmp = sizeof(struct ipv6hdr);
 	struct sfe_ipv6_connection_match *cm;
+	bool non_dst = false;
+	u8 next_hdr;
 
 	DEBUG_TRACE("%px: sfe: sfe_ipv6_recv_tunipip6 called.\n", skb);
 
@@ -73,11 +76,36 @@
 		return 0;
 	}
 
+	next_hdr = iph->nexthdr;
+
+	/*
+	 * Try to find an extension header(if any) that is not NEXTHDR_DEST.
+	 */
+	while (unlikely(sfe_ipv6_is_ext_hdr(next_hdr))) {
+		struct sfe_ipv6_ext_hdr *ext_hdr;
+		unsigned int ext_hdr_len;
+
+		if(next_hdr != NEXTHDR_DEST) {
+			non_dst = true;
+			break;
+		}
+
+		ext_hdr = (struct sfe_ipv6_ext_hdr *)(skb->data + ihl_tmp);
+
+		ext_hdr_len = ext_hdr->hdr_len;
+		ext_hdr_len <<= 3;
+		ext_hdr_len += sizeof(struct sfe_ipv6_ext_hdr);
+		ihl_tmp += ext_hdr_len;
+
+		next_hdr = ext_hdr->next_hdr;
+	}
+
 	/*
 	 * If our packet has been marked as "sync on find" we will sync the status
-	 * and forward it to slowpath.
+	 * and forward it to slowpath, except that encap_limit is set for dslite tunnel
+	 * which is embedded in exthdr type NEXTHDR_DEST.
 	 */
-	if (unlikely(sync_on_find)) {
+	if (unlikely(sync_on_find && non_dst)) {
 		sfe_ipv6_sync_status(si, cm->connection, SFE_SYNC_REASON_STATS);
 		rcu_read_unlock();
 		sfe_ipv6_exception_stats_inc(si, SFE_IPV6_EXCEPTION_EVENT_TUNIPIP6_SYNC_ON_FIND);