[qca-nss-ecm] Handle DSCP based action type.

If the DSCP to priority/action mapping table has a
not accel type for a particular dscp value, do not
process these packets, so that they are not offloaded
in NSS firmware.

Change-Id: Ie9f5d694cceec9d516d21e412885ae7c59d3c084
Signed-off-by: Murat Sezgin <msezgin@codeaurora.org>
diff --git a/ecm_tracker.c b/ecm_tracker.c
index 3770ceb..999c76d 100644
--- a/ecm_tracker.c
+++ b/ecm_tracker.c
@@ -481,6 +481,12 @@
 		ip_hdr->fragmented = (ntohs(v4_hdr->frag_off) & 0x3fff)? true : false;
 
 		/*
+		 * DSCP value is the 6 most significant bits of tos field, so left shifting
+		 * the tos value by 2 gives the DSCP value.
+		 */
+		ip_hdr->dscp = v4_hdr->tos >> 2;
+
+		/*
 		 * DS field
 		 */
 		ip_hdr->ds = ipv4_get_dsfield(v4_hdr);
@@ -551,6 +557,26 @@
 	}
 
 	/*
+	 * In IPv6 header, the version-class-flow_label is organized as:
+	 * version: u8:4
+	 * priority: u8:4
+	 * flow_lbl[3]
+	 *
+	 * Version(31-28), CLASS(27-20), FLOW(19-0)
+	 *
+	 * The dscp value is the most 6 significant bit of traffic-class field. Its 4-bits
+	 * belong to the priority field of the IPv6 header, the other 2-bits belong to the
+	 * flow_lbl[0]. So, to calculate the dscp value, we need to right shift the priority by 2 and OR
+	 * it with flow_lbl[0]'s most 2 significant bits.
+	 *
+	 * ECM_TRACKER_IPV6_FLOW_LBL_PRIORITY_MASK 0xC0
+	 * ECM_TRACKER_IPV6_FLOW_LBL_PRIORITY_SHIFT 6
+	 * ECM_TRACKER_IPV6_PRIORITY_SHIFT 2
+	 */
+	ip_hdr->dscp = (v6_hdr->priority << ECM_TRACKER_IPV6_PRIORITY_SHIFT) |
+			((v6_hdr->flow_lbl[0] & ECM_TRACKER_IPV6_FLOW_LBL_PRIORITY_MASK) >> ECM_TRACKER_IPV6_FLOW_LBL_PRIORITY_SHIFT);
+
+	/*
 	 * DS field
 	 */
 	ip_hdr->ds = ipv6_get_dsfield(v6_hdr);
diff --git a/ecm_tracker.h b/ecm_tracker.h
index 49cec58..9293d6e 100644
--- a/ecm_tracker.h
+++ b/ecm_tracker.h
@@ -24,6 +24,13 @@
 #define ECM_TRACKER_CONNECTION_TRACKING_LIMIT_DEFAULT (1024 * 1024)
 #define ECM_TRACKER_CONNECTION_TRACKING_LIMIT_MAX ECM_TRACKER_GLOBAL_DATA_LIMIT_DEFAULT
 
+/*
+ * Definitions for IPv6 version-class-flow_label field.
+ */
+#define ECM_TRACKER_IPV6_FLOW_LBL_PRIORITY_MASK 0xC0
+#define ECM_TRACKER_IPV6_FLOW_LBL_PRIORITY_SHIFT 6
+#define ECM_TRACKER_IPV6_PRIORITY_SHIFT 2
+
 enum ecm_tracker_sender_types {
 	ECM_TRACKER_SENDER_TYPE_SRC = 0,		/* Sender of tracked data is the source of the connection (who established the connection) */
 	ECM_TRACKER_SENDER_TYPE_DEST = 1,	/* Sender of tracked data is the destination of the connection (to whom connection was established) */
@@ -142,6 +149,7 @@
 	ip_addr_t dest_addr;		/* ECM ip address equivalent */
 	int protocol;			/* The upper layer transport protocol */
 	bool fragmented;		/* True when fragmented */
+	uint8_t dscp;			/* DSCP field from the packet */
 	uint8_t ds;			/* DS field from packet */
 	uint8_t ttl;			/* v4 TTL or v6 hop limit */
 	uint32_t ip_header_length;	/* Length of the IP header plus any variable sized intrinsically attached options */
diff --git a/frontends/nss/ecm_nss_ipv4.c b/frontends/nss/ecm_nss_ipv4.c
index 7e2cc99..a82cc02 100644
--- a/frontends/nss/ecm_nss_ipv4.c
+++ b/frontends/nss/ecm_nss_ipv4.c
@@ -910,6 +910,19 @@
 		return NF_ACCEPT;
 	}
 
+	/*
+	 * If the DSCP value of the packet maps to the NOT accel action type,
+	 * do not accelerate the packet and let it go through the
+	 * slow path.
+	 */
+	if (ip_hdr.protocol == IPPROTO_UDP) {
+		uint8_t action = nss_dscp2pri_get_action(ip_hdr.dscp);
+		if (action == NSS_DSCP2PRI_ACTION_NOT_ACCEL) {
+			DEBUG_TRACE("dscp: %d maps to action not accel type, skip acceleration\n", ip_hdr.dscp);
+			return NF_ACCEPT;
+		}
+	}
+
 	if (ip_hdr.fragmented) {
 		DEBUG_TRACE("skb %p is fragmented\n", skb);
 		return NF_ACCEPT;
diff --git a/frontends/nss/ecm_nss_ipv6.c b/frontends/nss/ecm_nss_ipv6.c
index 5fb76bd..f43ee59 100644
--- a/frontends/nss/ecm_nss_ipv6.c
+++ b/frontends/nss/ecm_nss_ipv6.c
@@ -833,6 +833,19 @@
 		return NF_ACCEPT;
 	}
 
+	/*
+	 * If the DSCP value of the packet maps to the NOT accel action type,
+	 * do not accelerate the packet and let it go through the
+	 * slow path.
+	 */
+	if (ip_hdr.protocol == IPPROTO_UDP) {
+		uint8_t action = nss_dscp2pri_get_action(ip_hdr.dscp);
+		if (action == NSS_DSCP2PRI_ACTION_NOT_ACCEL) {
+			DEBUG_TRACE("dscp: %d maps to action not accel type, skip acceleration\n", ip_hdr.dscp);
+			return NF_ACCEPT;
+		}
+	}
+
 	if (ip_hdr.fragmented) {
 		DEBUG_TRACE("skb %p is fragmented\n", skb);
 		return NF_ACCEPT;