Merge "[qca-nss-drv] Create new DTLS framework"
diff --git a/Makefile b/Makefile
index 0f6f7a7..dc69777 100644
--- a/Makefile
+++ b/Makefile
@@ -14,8 +14,6 @@
 			nss_cmn.o \
 			nss_core.o \
 			nss_coredump.o \
-			nss_dtls.o \
-			nss_dtls_stats.o \
 			nss_dynamic_interface.o \
 			nss_edma.o \
 			nss_edma_stats.o \
@@ -97,6 +95,8 @@
 ifeq ($(SoC),$(filter $(SoC),ipq806x ipq40xx))
 qca-nss-drv-objs += nss_data_plane/nss_data_plane_gmac.o \
 		    nss_hal/ipq806x/nss_hal_pvt.o \
+		    nss_dtls.o \
+		    nss_dtls_stats.o \
 		    nss_crypto.o
 ccflags-y += -I$(obj)/nss_hal/ipq806x -DNSS_HAL_IPQ806X_SUPPORT
 endif
@@ -104,6 +104,7 @@
 ifeq ($(SoC),$(filter $(SoC),ipq807x ipq807x_64))
 qca-nss-drv-objs += nss_data_plane/nss_data_plane_edma.o \
 		    nss_hal/ipq807x/nss_hal_pvt.o \
+		    nss_dtls_cmn.o \
 		    nss_crypto_cmn.o
 ccflags-y += -I$(obj)/nss_hal/ipq807x -DNSS_HAL_IPQ807x_SUPPORT
 endif
diff --git a/exports/nss_api_if.h b/exports/nss_api_if.h
index 74ec181..606f1dc 100644
--- a/exports/nss_api_if.h
+++ b/exports/nss_api_if.h
@@ -59,6 +59,7 @@
 #include "nss_portid.h"
 #include "nss_oam.h"
 #include "nss_dtls.h"
+#include "nss_dtls_cmn.h"
 #include "nss_edma.h"
 #include "nss_bridge.h"
 #include "nss_ppe.h"
diff --git a/exports/nss_dtls_cmn.h b/exports/nss_dtls_cmn.h
new file mode 100644
index 0000000..2285974
--- /dev/null
+++ b/exports/nss_dtls_cmn.h
@@ -0,0 +1,387 @@
+/*
+ **************************************************************************
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all copies.
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ **************************************************************************
+ */
+
+/**
+ * @file nss_dtls_cmn.h
+ *	NSS DTLS common interface definitions, supports inner/outer interface split.
+ */
+
+#ifndef _NSS_DTLS_CMN_H_
+#define _NSS_DTLS_CMN_H_
+
+/**
+ * @addtogroup nss_dtls_cmn_subsystem
+ * @{
+ */
+
+#define NSS_DTLS_CMN_CTX_HDR_IPV6 0x0001		/**< DTLS with IPv6. */
+#define NSS_DTLS_CMN_CTX_HDR_UDPLITE 0x0002		/**< DTLS with UDPLite. */
+#define NSS_DTLS_CMN_CTX_HDR_CAPWAP 0x0004		/**< DTLS with CAPWAP. */
+#define NSS_DTLS_CMN_CTX_CIPHER_MODE_GCM 0x0008		/**< DTLS with GCM cipher mode. */
+#define NSS_DTLS_CMN_CTX_OUTER_UDPLITE_CSUM 0x10000	/**< Checksum only UDPLite header. */
+#define NSS_DTLS_CMN_CTX_INNER_ACCEPT_ALL 0x20000
+#define NSS_DTLS_CMN_CLE_MAX 32				/**< Max classification error. */
+
+/**
+ * nss_dtls_cmn_metadata_types
+ *	Message types for DTLS requests and responses.
+ */
+enum nss_dtls_cmn_msg_type {
+	NSS_DTLS_CMN_MSG_TYPE_CONFIGURE_NODE,	/**< Configure DTLS firmware node. */
+	NSS_DTLS_CMN_MSG_TYPE_CONFIGURE_HDR,	/**< Configure the base context parameter. */
+	NSS_DTLS_CMN_MSG_TYPE_CONFIGURE_DTLS,	/**< Configure DTLS parameters. */
+	NSS_DTLS_CMN_MSG_TYPE_SWITCH_DTLS,	/**< Switch to new DTLS transform. */
+	NSS_DTLS_CMN_MSG_TYPE_DECONFIGURE,	/**< Deconfigure context. */
+	NSS_DTLS_CMN_MSG_TYPE_SYNC_STATS,	/**< Synchronize statistics. */
+	NSS_DTLS_CMN_MSG_TYPE_NODE_STATS,	/**< Node statistics. */
+	NSS_DTLS_CMN_MSG_MAX
+};
+
+/**
+ * nss_dtls_cmn_error_response_types
+ *	Error types for DTLS responses.
+ */
+enum nss_dtls_cmn_error {
+	NSS_DTLS_CMN_ERROR_NONE = 0,
+	NSS_DTLS_CMN_ERROR_UNKNOWN_MSG,
+	NSS_DTLS_CMN_ERROR_INVALID_DESTIF,
+	NSS_DTLS_CMN_ERROR_INVALID_SRCIF,
+	NSS_DTLS_CMN_ERROR_INVALID_CRYPTO,
+	NSS_DTLS_CMN_ERROR_INVALID_VER,
+	NSS_DTLS_CMN_ERROR_INVALID_CTX_TYPE,
+	NSS_DTLS_CMN_ERROR_INVALID_CTX_WORDS,
+	NSS_DTLS_CMN_ERROR_FAIL_ALLOC_HWCTX,
+	NSS_DTLS_CMN_ERROR_FAIL_COPY_CTX,
+	NSS_DTLS_CMN_ERROR_FAIL_SWITCH_HWCTX,
+	NSS_DTLS_CMN_ERROR_ALREADY_CONFIGURED,
+	NSS_DTLS_CMN_ERROR_NOMEM,
+	NSS_DTLS_CMN_ERROR_MAX,
+};
+
+/**
+ * DTLS node statistics
+ */
+struct nss_dtls_cmn_node_stats {
+	uint32_t fail_ctx_alloc;	/**< Failure in allocating a context. */
+	uint32_t fail_ctx_free;		/**< Failure in freeing up the context. */
+	uint32_t fail_pbuf_stats;	/**< Failure in pbuf allocation for statistics. */
+};
+
+/**
+ * DTLS hardware statistics
+ */
+struct nss_dtls_cmn_hw_stats {
+	uint32_t len_error;             /**< Length error. */
+	uint32_t token_error;           /**< Token error, unknown token command/instruction. */
+	uint32_t bypass_error;          /**< Token contains too much bypass data. */
+	uint32_t config_error;          /**< Invalid command/algorithm/mode/combination. */
+	uint32_t algo_error;            /**< Unsupported algorithm. */
+	uint32_t hash_ovf_error;        /**< Hash input overflow. */
+	uint32_t ttl_error;             /**< TTL or HOP-Limit underflow. */
+	uint32_t csum_error;            /**< Checksum error. */
+	uint32_t timeout_error;         /**< Data timed-out. */
+};
+
+/**
+ * nss_dtls_cmn_ctx_stats
+ *	DTLS session statistics.
+ */
+struct nss_dtls_cmn_ctx_stats {
+	struct nss_cmn_node_stats pkt;		/**< Common node statistics. */
+	uint32_t rx_single_rec;			/**< Received single DTLS record datagrams. */
+	uint32_t rx_multi_rec;			/**< Received multiple DTLS record datagrams. */
+	uint32_t fail_crypto_resource;		/**< Failure in allocation of crypto resource. */
+	uint32_t fail_crypto_enqueue;		/**< Failure due to queue full in crypto or hardware. */
+	uint32_t fail_headroom;			/**< Failure in headroom check. */
+	uint32_t fail_tailroom;			/**< Failure in tailroom check. */
+	uint32_t fail_ver;			/**< Failure in DTLS version check. */
+	uint32_t fail_epoch;			/**< Failure in DTLS epoch check. */
+	uint32_t fail_dtls_record;		/**< Failure in reading DTLS record. */
+	uint32_t fail_capwap;			/**< Failure in CAPWAP classification. */
+	uint32_t fail_replay;			/**< Failure in anti-replay check. */
+	uint32_t fail_replay_dup;		/**< Failure in anti-replay; duplicate records. */
+	uint32_t fail_replay_win;		/**< Failure in anti-replay; packet outside the window. */
+	uint32_t fail_queue;			/**< Failure due to queue full in DTLS. */
+	uint32_t fail_queue_nexthop;		/**< Failure due to queue full in next_hop. */
+	uint32_t fail_pbuf_alloc;		/**< Failure in pbuf allocation. */
+	uint32_t fail_pbuf_linear;		/**< Failure in pbuf linearization. */
+	uint32_t fail_pbuf_stats;		/**< Failure in pbuf allocation for statistics. */
+	uint32_t fail_pbuf_align;		/**< Failure in pbuf alignment. */
+	uint32_t fail_ctx_active;		/**< Failure in enqueue due to inactive context. */
+	uint32_t fail_hwctx_active;		/**< Failure in enqueue due to inactive hardware context. */
+	uint32_t fail_cipher;			/**< Failure in decrypting the data. */
+	uint32_t fail_auth;			/**< Failure in authenticating the data. */
+	uint32_t fail_seq_ovf;			/**< Failure due to sequence number overflow. */
+	uint32_t fail_blk_len;			/**< Failure in decapsulation due to bad cipher block length. */
+	uint32_t fail_hash_len;			/**< Failure in decapsulation due to bad hash block length. */
+
+	struct nss_dtls_cmn_hw_stats fail_hw;	/**< Hardware failure statistics. */
+
+	uint32_t fail_cle[NSS_DTLS_CMN_CLE_MAX];/**< Classification errors. */
+
+	uint32_t seq_low;			/**< Lower 32 bits of current Tx sequence number. */
+	uint32_t seq_high;			/**< Upper 16 bits of current Tx sequence number. */
+
+	uint16_t epoch;				/**< Current epoch value. */
+	uint8_t res1[2];			/**< Reserved for future use. */
+
+	uint8_t res2[16];			/**< Reserved for future use. */
+};
+
+/**
+ * nss_dtls_cmn_ctx_config_hdr
+ *	Parameters for outer header transform.
+ */
+struct nss_dtls_cmn_ctx_config_hdr {
+	uint32_t flags;		/**< Context flags. */
+	uint32_t dest_ifnum;	/**< Destination interface for packets. */
+	uint32_t src_ifnum;	/**< Source interface of packets. */
+	uint32_t sip[4];	/**< Source IPv4/v6 address. */
+	uint32_t dip[4];	/**< Destination IPv4/v6 address. */
+
+	uint16_t sport;		/**< Source UDP/UDPLite port. */
+	uint16_t dport;		/**< Destination UDP/UDPLite port. */
+
+	uint8_t hop_limit_ttl;	/**< IP header TTL field. */
+	uint8_t dscp;		/**< DSCP value. */
+	uint8_t dscp_copy; 	/**< Copy DSCP value. */
+	uint8_t df;		/**< Do not fragment DTLS over IPv4. */
+};
+
+/**
+ * nss_dtls_cmn_ctx_config_dtls
+ *	Parameters for DTLS transform.
+ */
+struct nss_dtls_cmn_ctx_config_dtls {
+	uint32_t ver;		/**< Version (enum dtls_cmn_ver). */
+	uint32_t crypto_idx;	/**< Crypto index for cipher context. */
+
+	uint16_t window_size;	/**< Anti-replay window size. */
+	uint16_t epoch;		/**< Initial epoch value. */
+
+	uint8_t iv_len;		/**< Crypto IV length for encapsulation. */
+	uint8_t hash_len;	/**< Auth hash length for encapsulation. */
+	uint8_t blk_len;	/**< Cipher block length. */
+	uint8_t res1;		/**< Reserved for alignment. */
+};
+
+/**
+ * nss_dtls_cmn_msg
+ *	Data for sending and receiving DTLS messages.
+ */
+struct nss_dtls_cmn_msg {
+	struct nss_cmn_msg cm;		/**< Common message header. */
+
+	/**
+	 * Payload of a DTLS message.
+	 */
+	union {
+		struct nss_dtls_cmn_ctx_config_hdr hdr_cfg;	/**< Session configuration. */
+		struct nss_dtls_cmn_ctx_config_dtls dtls_cfg;	/**< Cipher update information. */
+		struct nss_dtls_cmn_ctx_stats stats;		/**< Session statistics. */
+		struct nss_dtls_cmn_node_stats node_stats;	/**< Node statistics. */
+	} msg;			/**< Message payload for DTLS session messages exchanged with NSS core. */
+};
+
+/**
+ * Callback function for receiving DTLS messages.
+ *
+ * @datatypes
+ * nss_dtls_cmn_msg
+ *
+ * @param[in] app_data  Pointer to the application context of the message.
+ * @param[in] msg       Pointer to the message data.
+ */
+typedef void (*nss_dtls_cmn_msg_callback_t)(void *app_data, struct nss_cmn_msg *msg);
+
+/**
+ * Callback function for receiving DTLS session data.
+ *
+ * @datatypes
+ * net_device \n
+ * sk_buff \n
+ * napi_struct
+ *
+ * @param[in] netdev  Pointer to the associated network device.
+ * @param[in] skb     Pointer to the data socket buffer.
+ * @param[in] napi    Pointer to the NAPI structure.
+ */
+typedef void (*nss_dtls_cmn_data_callback_t)(struct net_device *netdev, struct sk_buff *skb, struct napi_struct *napi);
+
+/**
+ * nss_dtls_cmn_tx_buf
+ *	Sends a DTLS data packet to the NSS.
+ *
+ * @datatypes
+ * sk_buff \n
+ * nss_ctx_instance
+ *
+ * @param[in]     os_buf   Pointer to the OS data buffer.
+ * @param[in]     if_num   NSS interface number.
+ * @param[in]     nss_ctx  Pointer to the NSS core context.
+ *
+ * @return
+ * Status of Tx buffer forwarded to NSS for DTLS operation.
+ */
+nss_tx_status_t nss_dtls_cmn_tx_buf(struct sk_buff *os_buf, uint32_t if_num, struct nss_ctx_instance *nss_ctx);
+
+/**
+ * nss_dtls_cmn_tx_msg
+ *	Sends DTLS messages.
+ *
+ * @param[in]     nss_ctx  Pointer to the NSS core context.
+ * @param[in,out] msg      Pointer to the message data.
+ *
+ * @return
+ * Status of the Tx operation.
+ */
+extern nss_tx_status_t nss_dtls_cmn_tx_msg(struct nss_ctx_instance *nss_ctx, struct nss_dtls_cmn_msg *msg);
+
+/**
+ * nss_dtls_cmn_tx_msg_sync
+ *	Sends DTLS messages synchronously.
+ *
+ * @datatypes
+ * nss_ctx_instance \n
+ * nss_dtls_cmn_msg_type \n
+ * nss_dtls_cmn_msg \n
+ * nss_dtls_cmn_error
+ *
+ * @param[in]     nss_ctx  Pointer to the NSS context.
+ * @param[in]     if_num   NSS interface number.
+ * @param[in]     type     Type of message.
+ * @param[in]     len      Size of the payload.
+ * @param[in]     ndcm     Pointer to the message data.
+ * @param[in,out] resp     Response for the configuration.
+ *
+ * @return
+ * Status of the Tx operation.
+ */
+extern nss_tx_status_t nss_dtls_cmn_tx_msg_sync(struct nss_ctx_instance *nss_ctx, uint32_t if_num,
+						enum nss_dtls_cmn_msg_type type, uint16_t len,
+						struct nss_dtls_cmn_msg *ndcm, enum nss_dtls_cmn_error *resp);
+
+/**
+ * nss_dtls_cmn_register_if
+ *	Registers a DTLS session interface with the NSS for sending and receiving
+ *	messages.
+ *
+ * @datatypes
+ * nss_dtls_cmn_data_callback_t \n
+ * nss_dtls_cmn_msg_callback_t
+ *
+ * @param[in] if_num        NSS interface number.
+ * @param[in] data_cb       Callback function for the message.
+ * @param[in] msg_cb        Callback for DTLS tunnel message.
+ * @param[in] netdev        Pointer to the associated network device.
+ * @param[in] features      Data socket buffer types supported by this interface.
+ * @param[in] app_ctx       Pointer to the application context.
+ *
+ * @return
+ * Pointer to the NSS core context.
+ */
+extern struct nss_ctx_instance *nss_dtls_cmn_register_if(uint32_t if_num,
+							 nss_dtls_cmn_data_callback_t data_cb,
+							 nss_dtls_cmn_msg_callback_t msg_cb,
+							 struct net_device *netdev,
+							 uint32_t features,
+							 uint32_t type,
+							 void *app_ctx);
+
+/**
+ * nss_dtls_cmn_unregister_if
+ *	Deregisters a DTLS session interface from the NSS.
+ *
+ * @param[in] if_num  NSS interface number.
+ *
+ * @return
+ * None.
+ *
+ * @dependencies
+ * The DTLS session interface must have been previously registered.
+ */
+extern void nss_dtls_cmn_unregister_if(uint32_t if_num);
+
+/**
+ * nss_dtls_cmn_notify_register
+ *	Register an event callback to handle notification from DTLS firmware package.
+ *
+ * @param[in] if_num     NSS interface number.
+ * @param[in] ev_cb      Callback for DTLS tunnel message.
+ * @param[in] app_data   Pointer to the application context.
+ *
+ * @return
+ * Pointer to NSS core context.
+ */
+extern struct nss_ctx_instance *nss_dtls_cmn_notify_register(uint32_t ifnum, nss_dtls_cmn_msg_callback_t ev_cb,
+							     void *app_data);
+
+/**
+ * nss_dtls_cmn_notify_unregister
+ *	Unregister an event callback.
+ *
+ * @param[in] if_num      NSS interface number.
+ *
+ * @return
+ * None.
+ */
+extern void nss_dtls_cmn_notify_unregister(uint32_t ifnum);
+
+/**
+ * nss_dtls_cmn_msg_init
+ *	Initializes a DTLS message.
+ *
+ * @datatypes
+ * nss_dtls_cmn_msg
+ *
+ * @param[in,out] ncm       Pointer to the message.
+ * @param[in]     if_num    NSS interface number.
+ * @param[in]     type      Type of message.
+ * @param[in]     len       Size of the payload.
+ * @param[in]     cb        Pointer to the message callback.
+ * @param[in]     app_data  Pointer to the application context.
+ *
+ * @return
+ * None.
+ */
+extern void nss_dtls_cmn_msg_init(struct nss_dtls_cmn_msg *ncm, uint32_t if_num, uint32_t type, uint32_t len, void *cb,
+				void *app_data);
+
+/**
+ * nss_dtls_cmn_get_context
+ *	Gets the NSS core context for the DTLS session.
+ *
+ * @return
+ * Pointer to the NSS core context.
+ */
+extern struct nss_ctx_instance *nss_dtls_cmn_get_context(void);
+
+/**
+ * nss_dtls_cmn_get_ifnum
+ *	Gets the DTLS interface number with a core ID.
+ *
+ * @param[in] if_num  NSS interface number.
+ *
+ * @return
+ * Interface number with the core ID.
+ */
+extern int32_t nss_dtls_cmn_get_ifnum(int32_t if_num);
+
+/**
+ * @}
+ */
+
+#endif /* _NSS_DTLS_CMN_H_. */
diff --git a/exports/nss_dynamic_interface.h b/exports/nss_dynamic_interface.h
index 5a0147f..9399ae5 100644
--- a/exports/nss_dynamic_interface.h
+++ b/exports/nss_dynamic_interface.h
@@ -58,6 +58,8 @@
 	NSS_DYNAMIC_INTERFACE_TYPE_GRE_REDIR_OUTER,
 	NSS_DYNAMIC_INTERFACE_TYPE_GRE_TUNNEL_INNER,
 	NSS_DYNAMIC_INTERFACE_TYPE_GRE_TUNNEL_OUTER,
+	NSS_DYNAMIC_INTERFACE_TYPE_DTLS_CMN_INNER,
+	NSS_DYNAMIC_INTERFACE_TYPE_DTLS_CMN_OUTER,
 	NSS_DYNAMIC_INTERFACE_TYPE_MAX
 };
 
diff --git a/nss_dtls_cmn.c b/nss_dtls_cmn.c
new file mode 100644
index 0000000..1ac43fb
--- /dev/null
+++ b/nss_dtls_cmn.c
@@ -0,0 +1,567 @@
+/*
+ **************************************************************************
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all copies.
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ **************************************************************************
+ */
+
+#include "nss_tx_rx_common.h"
+
+#define NSS_DTLS_CMN_TX_TIMEOUT 3000 /* 3 Seconds */
+#define NSS_DTLS_CMN_INTERFACE_MAX_LONG BITS_TO_LONGS(NSS_MAX_NET_INTERFACES)
+#define NSS_DTLS_CMN_STATS_MAX_LINES (NSS_STATS_NODE_MAX + 32)
+#define NSS_DTLS_CMN_STATS_SIZE_PER_IF (NSS_STATS_MAX_STR_LENGTH * NSS_DTLS_CMN_STATS_MAX_LINES)
+/*
+ * Private data structure
+ */
+static struct nss_dtls_cmn_cmn_pvt {
+	struct semaphore sem;
+	struct completion complete;
+	enum nss_dtls_cmn_error resp;
+	unsigned long if_map[NSS_DTLS_CMN_INTERFACE_MAX_LONG];
+} dtls_cmn_pvt;
+
+/*
+ * nss_dtls_cmn_stats_sync()
+ *	Update dtls_cmn node statistics.
+ */
+static void nss_dtls_cmn_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_cmn_msg *ncm)
+{
+	struct nss_dtls_cmn_msg *ndcm = (struct nss_dtls_cmn_msg *)ncm;
+	struct nss_top_instance *nss_top = nss_ctx->nss_top;
+	struct nss_dtls_cmn_ctx_stats *msg_stats = &ndcm->msg.stats;
+	uint64_t *if_stats;
+
+	spin_lock_bh(&nss_top->stats_lock);
+
+	/*
+	 * Update common node stats,
+	 * Note: DTLS only supports a single queue for RX
+	 */
+	if_stats = nss_top->stats_node[ncm->interface];
+	if_stats[NSS_STATS_NODE_RX_PKTS] += msg_stats->pkt.rx_packets;
+	if_stats[NSS_STATS_NODE_RX_BYTES] += msg_stats->pkt.rx_bytes;
+	if_stats[NSS_STATS_NODE_RX_QUEUE_0_DROPPED] += msg_stats->pkt.rx_dropped[0];
+
+	if_stats[NSS_STATS_NODE_TX_PKTS] += msg_stats->pkt.tx_packets;
+	if_stats[NSS_STATS_NODE_TX_BYTES] += msg_stats->pkt.tx_bytes;
+
+	spin_unlock_bh(&nss_top->stats_lock);
+}
+
+/*
+ * nss_dtls_cmn_stats_read()
+ *	Read dtls_cmn node statiistics.
+ */
+static ssize_t nss_dtls_cmn_stats_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
+{
+	struct nss_ctx_instance *nss_ctx = nss_dtls_cmn_get_context();
+	enum nss_dynamic_interface_type type;
+	ssize_t bytes_read = 0;
+	size_t len = 0, size;
+	uint32_t if_num;
+	char *buf;
+
+	size = NSS_DTLS_CMN_STATS_SIZE_PER_IF * bitmap_weight(dtls_cmn_pvt.if_map, NSS_MAX_NET_INTERFACES);
+
+	buf = kzalloc(size, GFP_KERNEL);
+	if (!buf) {
+		nss_warning("Could not allocate memory for local statistics buffer");
+		return 0;
+	}
+
+	/*
+	 * Common node stats for each DTLS dynamic interface.
+	 */
+	for_each_set_bit(if_num, dtls_cmn_pvt.if_map, NSS_MAX_NET_INTERFACES) {
+
+		type = nss_dynamic_interface_get_type(nss_ctx, if_num);
+
+		switch (type) {
+		case NSS_DYNAMIC_INTERFACE_TYPE_DTLS_CMN_INNER:
+			len += scnprintf(buf + len, size - len, "\nInner if_num:%03u", if_num);
+			break;
+
+		case NSS_DYNAMIC_INTERFACE_TYPE_DTLS_CMN_OUTER:
+			len += scnprintf(buf + len, size - len, "\nOuter if_num:%03u", if_num);
+			break;
+
+		default:
+			len += scnprintf(buf + len, size - len, "\nUnknown(%d) if_num:%03u", type, if_num);
+			break;
+		}
+
+		len += scnprintf(buf + len, size - len, "\n-------------------\n");
+		len += nss_stats_fill_common_stats(if_num, buf, len, size - len);
+	}
+
+	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, buf, len);
+	kfree(buf);
+
+	return bytes_read;
+}
+
+/*
+ * nss_dtls_cmn_stats_ops
+ */
+NSS_STATS_DECLARE_FILE_OPERATIONS(dtls_cmn)
+
+/*
+ * nss_dtls_cmn_verify_ifnum()
+ *	Verify if the interface number is a DTLS interface.
+ */
+static bool nss_dtls_cmn_verify_ifnum(struct nss_ctx_instance *nss_ctx, uint32_t if_num)
+{
+	enum nss_dynamic_interface_type type = nss_dynamic_interface_get_type(nss_ctx, if_num);
+
+	if (type == NSS_DYNAMIC_INTERFACE_TYPE_DTLS_CMN_INNER)
+		return true;
+
+	if (type == NSS_DYNAMIC_INTERFACE_TYPE_DTLS_CMN_OUTER)
+		return true;
+
+	if (if_num == NSS_DTLS_INTERFACE)
+		return true;
+
+	return false;
+}
+
+/*
+ * nss_dtls_cmn_handler()
+ *	Handle NSS -> HLOS messages for dtls tunnel
+ */
+static void nss_dtls_cmn_handler(struct nss_ctx_instance *nss_ctx, struct nss_cmn_msg *ncm, void *data)
+{
+	nss_dtls_cmn_msg_callback_t cb;
+	void *app_data;
+
+	NSS_VERIFY_CTX_MAGIC(nss_ctx);
+
+	nss_trace("%p: handle event for interface num :%u", nss_ctx, ncm->interface);
+
+	/*
+	 * Is this a valid request/response packet?
+	 */
+	if (ncm->type >= NSS_DTLS_CMN_MSG_MAX) {
+		nss_warning("%p:Bad message type(%d) for DTLS interface %d", nss_ctx, ncm->type, ncm->interface);
+		return;
+	}
+
+	if (nss_cmn_get_msg_len(ncm) > sizeof(struct nss_dtls_cmn_msg)) {
+		nss_warning("%p:Bad message length(%d)", nss_ctx, ncm->len);
+		return;
+	}
+
+	if (ncm->type == NSS_DTLS_CMN_MSG_TYPE_SYNC_STATS)
+		nss_dtls_cmn_stats_sync(nss_ctx, ncm);
+
+	/*
+	 * Update the callback and app_data for NOTIFY messages
+	 */
+	if (ncm->response == NSS_CMM_RESPONSE_NOTIFY) {
+		ncm->cb = (nss_ptr_t)nss_top_main.if_rx_msg_callback[ncm->interface];
+		ncm->app_data = (nss_ptr_t)nss_ctx->nss_rx_interface_handlers[nss_ctx->id][ncm->interface].app_data;
+	}
+
+	/*
+	 * Log failures
+	 */
+	nss_core_log_msg_failures(nss_ctx, ncm);
+
+	/*
+	 * Callback
+	 */
+	cb = (nss_dtls_cmn_msg_callback_t)ncm->cb;
+	app_data = (void *)ncm->app_data;
+
+	/*
+	 * Call DTLS session callback
+	 */
+	if (!cb) {
+		nss_warning("%p: No callback for dtls session interface %d", nss_ctx, ncm->interface);
+		return;
+	}
+
+	nss_trace("%p: calling dtlsmgr event handler(%u)", nss_ctx, ncm->interface);
+	cb(app_data, ncm);
+}
+
+/*
+ * nss_dtls_cmn_callback()
+ *	Callback to handle the completion of NSS->HLOS messages.
+ */
+static void nss_dtls_cmn_callback(void *app_data, struct nss_cmn_msg *ncm)
+{
+	/*
+	 * This callback is for synchronous operation. The caller sends its
+	 * response pointer which needs to be loaded with the response
+	 * data arriving from the NSS
+	 */
+	enum nss_dtls_cmn_error *resp = (enum nss_dtls_cmn_error *)app_data;
+
+	*resp = (ncm->response == NSS_CMN_RESPONSE_ACK) ?  NSS_DTLS_CMN_ERROR_NONE : ncm->error;
+	complete(&dtls_cmn_pvt.complete);
+
+	return;
+}
+
+/*
+ * nss_dtls_cmn_tx_buf()
+ *	Transmit buffer over DTLS interface
+ */
+nss_tx_status_t nss_dtls_cmn_tx_buf(struct sk_buff *skb, uint32_t if_num, struct nss_ctx_instance *nss_ctx)
+{
+	int32_t status;
+
+	NSS_VERIFY_CTX_MAGIC(nss_ctx);
+
+	if (unlikely(nss_ctx->state != NSS_CORE_STATE_INITIALIZED)) {
+		nss_warning("%p: 'DTLS If Tx' core not ready", nss_ctx);
+		return NSS_TX_FAILURE_NOT_READY;
+	}
+
+	if (!nss_dtls_cmn_verify_ifnum(nss_ctx, if_num))
+		return NSS_TX_FAILURE;
+
+	status = nss_core_send_buffer(nss_ctx, if_num, skb, NSS_IF_DATA_QUEUE_0,
+					H2N_BUFFER_PACKET, H2N_BIT_FLAG_VIRTUAL_BUFFER);
+	switch (status) {
+	case NSS_CORE_STATUS_SUCCESS:
+		break;
+
+	case NSS_CORE_STATUS_FAILURE_QUEUE:
+		nss_warning("%p: Unable to enqueue DTLS packet(%u); queue full", nss_ctx, if_num);
+		return NSS_TX_FAILURE_QUEUE;
+
+	default:
+		nss_warning("%p: Unable to enqueue DTLS packet(%u)", nss_ctx, if_num);
+		return NSS_TX_FAILURE;
+	}
+
+	nss_hal_send_interrupt(nss_ctx, NSS_H2N_INTR_DATA_COMMAND_QUEUE);
+	NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_TX_PACKET]);
+
+	return NSS_TX_SUCCESS;
+}
+EXPORT_SYMBOL(nss_dtls_cmn_tx_buf);
+
+/*
+ * nss_dtls_cmn_tx_msg()
+ *	Transmit a DTLS message to NSS firmware
+ */
+nss_tx_status_t nss_dtls_cmn_tx_msg(struct nss_ctx_instance *nss_ctx, struct nss_dtls_cmn_msg *msg)
+{
+	struct nss_dtls_cmn_msg *nm;
+	struct nss_cmn_msg *ncm = &msg->cm;
+	struct sk_buff *nbuf;
+	int32_t status;
+
+	NSS_VERIFY_CTX_MAGIC(nss_ctx);
+	if (unlikely(nss_ctx->state != NSS_CORE_STATE_INITIALIZED)) {
+		nss_warning("%p: dtls msg dropped as core not ready", nss_ctx);
+		return NSS_TX_FAILURE_NOT_READY;
+	}
+
+	if (ncm->type >= NSS_DTLS_CMN_MSG_MAX) {
+		nss_warning("%p: dtls message type out of range: %d", nss_ctx, ncm->type);
+		return NSS_TX_FAILURE;
+	}
+
+	if (!nss_dtls_cmn_verify_ifnum(nss_ctx, ncm->interface)) {
+		nss_warning("%p: dtls message interface is bad: %u", nss_ctx, ncm->interface);
+		return NSS_TX_FAILURE;
+	}
+
+	if (nss_cmn_get_msg_len(ncm) > sizeof(struct nss_dtls_cmn_msg)) {
+		nss_warning("%p: dtls message length is invalid: %d", nss_ctx, ncm->len);
+		return NSS_TX_FAILURE;
+	}
+
+	nbuf = dev_alloc_skb(NSS_NBUF_PAYLOAD_SIZE);
+	if (unlikely(!nbuf)) {
+		NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_NBUF_ALLOC_FAILS]);
+		nss_warning("%p: dtls msg dropped as command allocation failed", nss_ctx);
+		return NSS_TX_FAILURE;
+	}
+
+	/*
+	 * Copy the message to our skb
+	 */
+	nm = (struct nss_dtls_cmn_msg *)skb_put(nbuf, sizeof(struct nss_dtls_cmn_msg));
+	memcpy(nm, msg, sizeof(struct nss_dtls_cmn_msg));
+
+	status = nss_core_send_buffer(nss_ctx, 0, nbuf, NSS_IF_CMD_QUEUE, H2N_BUFFER_CTRL, 0);
+	switch (status) {
+	case NSS_CORE_STATUS_SUCCESS:
+		break;
+
+	case NSS_CORE_STATUS_FAILURE_QUEUE:
+		dev_kfree_skb_any(nbuf);
+		nss_warning("%p: Unable to enqueue DTLS packet(%u); queue full", nss_ctx, ncm->interface);
+		return NSS_TX_FAILURE_QUEUE;
+
+	default:
+		dev_kfree_skb_any(nbuf);
+		nss_warning("%p: Unable to enqueue DTLS packet(%u)", nss_ctx, ncm->interface);
+		return NSS_TX_FAILURE;
+	}
+
+	nss_trace("%p: sending message for interface (%u), type(%d)", nss_ctx, ncm->interface, ncm->type);
+
+	nss_hal_send_interrupt(nss_ctx, NSS_H2N_INTR_DATA_COMMAND_QUEUE);
+
+	NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_TX_CMD_REQ]);
+	return NSS_TX_SUCCESS;
+}
+EXPORT_SYMBOL(nss_dtls_cmn_tx_msg);
+
+/*
+ * nss_dtls_cmn_tx_msg_sync()
+ *	Transmit a DTLS message to NSS firmware synchronously.
+ */
+nss_tx_status_t nss_dtls_cmn_tx_msg_sync(struct nss_ctx_instance *nss_ctx, uint32_t if_num,
+					enum nss_dtls_cmn_msg_type type, uint16_t len,
+					struct nss_dtls_cmn_msg *ndcm, enum nss_dtls_cmn_error *resp)
+{
+	struct nss_dtls_cmn_msg ndcm_local;
+	nss_tx_status_t status;
+	int ret;
+
+	/*
+	 * Length of the message should be the based on type
+	 */
+	if (len > sizeof(ndcm_local.msg)) {
+		nss_warning("%p: (%u)Bad message length(%u) for type (%d)", nss_ctx, if_num, len, type);
+		return NSS_TX_FAILURE_TOO_LARGE;
+	}
+
+	/*
+	 * Response buffer is a required for copying the response for message
+	 */
+	if (!resp) {
+		nss_warning("%p: (%u)Response buffer is empty, type(%d)", nss_ctx, if_num, type);
+		return NSS_TX_FAILURE_BAD_PARAM;
+	}
+
+	/*
+	 * TODO: this can be removed in future as we need to ensure that the response
+	 * memory is only updated when the current outstanding request is waiting.
+	 * This can be solved by introducing sequence no. in messages and only completing
+	 * the message if the sequence no. matches. For now this is solved by passing
+	 * a known memory dtls_cmn_pvt.resp
+	 */
+	down(&dtls_cmn_pvt.sem);
+
+	/*
+	 * We need to copy the message content into the actual message
+	 * to be sent to NSS
+	 */
+	nss_dtls_cmn_msg_init(&ndcm_local, if_num, type, len, nss_dtls_cmn_callback, &dtls_cmn_pvt.resp);
+	memcpy(&ndcm_local.msg, &ndcm->msg, len);
+
+	status = nss_dtls_cmn_tx_msg(nss_ctx, &ndcm_local);
+	if (status != NSS_TX_SUCCESS) {
+		nss_warning("%p: dtls_tx_msg failed", nss_ctx);
+		goto done;
+	}
+
+	ret = wait_for_completion_timeout(&dtls_cmn_pvt.complete, msecs_to_jiffies(NSS_DTLS_CMN_TX_TIMEOUT));
+	if (!ret) {
+		nss_warning("%p: DTLS msg tx failed due to timeout", nss_ctx);
+		status = NSS_TX_FAILURE_NOT_READY;
+		goto done;
+	}
+
+	/*
+	 * Read memory barrier
+	 */
+	smp_rmb();
+
+	/*
+	 * Copy the response received
+	 */
+	*resp = dtls_cmn_pvt.resp;
+
+	/*
+	 * Only in case of non-error response we will
+	 * indicate success
+	 */
+	if (dtls_cmn_pvt.resp != NSS_DTLS_CMN_ERROR_NONE)
+		status = NSS_TX_FAILURE;
+
+done:
+	up(&dtls_cmn_pvt.sem);
+	return status;
+}
+EXPORT_SYMBOL(nss_dtls_cmn_tx_msg_sync);
+
+/*
+ * nss_dtls_cmn_notify_register()
+ *	Register a handler for notification from NSS firmware.
+ */
+struct nss_ctx_instance *nss_dtls_cmn_notify_register(uint32_t if_num, nss_dtls_cmn_msg_callback_t ev_cb,
+							void *app_data)
+{
+	struct nss_ctx_instance *nss_ctx = nss_dtls_cmn_get_context();
+	uint32_t ret;
+
+	BUG_ON(!nss_ctx);
+
+	ret = nss_core_register_handler(nss_ctx, if_num, nss_dtls_cmn_handler, app_data);
+	if (ret != NSS_CORE_STATUS_SUCCESS) {
+		nss_warning("%p: unable to register event handler for interface(%u)", nss_ctx, if_num);
+		return NULL;
+	}
+
+	nss_top_main.if_rx_msg_callback[if_num] = ev_cb;
+
+	return nss_ctx;
+}
+EXPORT_SYMBOL(nss_dtls_cmn_notify_register);
+
+/*
+ * nss_dtls_cmn_notify_unregister()
+ *	Unregister notification callback handler.
+ */
+void nss_dtls_cmn_notify_unregister(uint32_t if_num)
+{
+	struct nss_ctx_instance *nss_ctx = nss_dtls_cmn_get_context();
+	uint32_t ret;
+
+	BUG_ON(!nss_ctx);
+
+	ret = nss_core_unregister_handler(nss_ctx, if_num);
+	if (ret != NSS_CORE_STATUS_SUCCESS) {
+		nss_warning("%p: unable to un register event handler for interface(%u)", nss_ctx, if_num);
+		return;
+	}
+
+	nss_top_main.if_rx_msg_callback[if_num] = NULL;
+
+	return;
+}
+EXPORT_SYMBOL(nss_dtls_cmn_notify_unregister);
+
+/*
+ * nss_dtls_cmn_register_if()
+ *	Register data and event callback handlers for dynamic interface.
+ */
+struct nss_ctx_instance *nss_dtls_cmn_register_if(uint32_t if_num,
+						  nss_dtls_cmn_data_callback_t data_cb,
+						  nss_dtls_cmn_msg_callback_t ev_cb,
+						  struct net_device *netdev,
+						  uint32_t features,
+						  uint32_t type,
+						  void *app_data)
+{
+	struct nss_ctx_instance *nss_ctx = nss_dtls_cmn_get_context();
+	uint32_t ret;
+
+	if (!nss_dtls_cmn_verify_ifnum(nss_ctx, if_num)) {
+		nss_warning("%p: DTLS Interface is not dynamic:%u", nss_ctx, if_num);
+		return NULL;
+	}
+
+	if (nss_ctx->subsys_dp_register[if_num].ndev) {
+		nss_warning("%p: Cannot find free slot for DTLS NSS I/F:%u", nss_ctx, if_num);
+		return NULL;
+	}
+
+	nss_core_register_subsys_dp(nss_ctx, if_num, data_cb, NULL, app_data, netdev, features);
+	nss_ctx->subsys_dp_register[if_num].type = type;
+
+	ret = nss_core_register_handler(nss_ctx, if_num, nss_dtls_cmn_handler, app_data);
+	if (ret != NSS_CORE_STATUS_SUCCESS) {
+		nss_warning("%p: unable to register event handler for interface(%u)", nss_ctx, if_num);
+		return NULL;
+	}
+
+	nss_top_main.if_rx_msg_callback[if_num] = ev_cb;
+
+	/*
+	 * Atomically set the bitmap for the interface number
+	 */
+	set_bit(if_num, dtls_cmn_pvt.if_map);
+	return nss_ctx;
+}
+EXPORT_SYMBOL(nss_dtls_cmn_register_if);
+
+/*
+ * nss_dtls_cmn_unregister_if()
+ *	Unregister data and event callback handlers for the interface.
+ */
+void nss_dtls_cmn_unregister_if(uint32_t if_num)
+{
+	struct nss_ctx_instance *nss_ctx = nss_dtls_cmn_get_context();
+
+	if (!nss_ctx->subsys_dp_register[if_num].ndev) {
+		nss_warning("%p: Cannot find registered netdev for DTLS NSS I/F:%u", nss_ctx, if_num);
+		return;
+	}
+
+	nss_core_unregister_subsys_dp(nss_ctx, if_num);
+	nss_ctx->subsys_dp_register[if_num].type = 0;
+
+	nss_core_unregister_handler(nss_ctx, if_num);
+	nss_top_main.if_rx_msg_callback[if_num] = NULL;
+
+	/*
+	 * Atomically clear the bitmap for the interface number
+	 */
+	clear_bit(if_num, dtls_cmn_pvt.if_map);
+}
+EXPORT_SYMBOL(nss_dtls_cmn_unregister_if);
+
+/*
+ * nss_dtls_get_context()
+ *	Return DTLS NSS context.
+ */
+struct nss_ctx_instance *nss_dtls_cmn_get_context(void)
+{
+	return (struct nss_ctx_instance *)&nss_top_main.nss[nss_top_main.dtls_handler_id];
+}
+EXPORT_SYMBOL(nss_dtls_cmn_get_context);
+
+/*
+ * nss_dtls_cmn_msg_init()
+ *	Initialize nss_dtls_cmn msg.
+ */
+void nss_dtls_cmn_msg_init(struct nss_dtls_cmn_msg *ncm, uint32_t if_num,
+		       uint32_t type, uint32_t len, void *cb, void *app_data)
+{
+	nss_cmn_msg_init(&ncm->cm, if_num, type, len, cb, app_data);
+}
+EXPORT_SYMBOL(nss_dtls_cmn_msg_init);
+
+/*
+ * nss_dtls_cmn_get_ifnum()
+ *	Return DTLS interface number with coreid.
+ */
+int32_t nss_dtls_cmn_get_ifnum(int32_t if_num)
+{
+	struct nss_ctx_instance *nss_ctx = nss_dtls_cmn_get_context();
+
+	NSS_VERIFY_CTX_MAGIC(nss_ctx);
+	return NSS_INTERFACE_NUM_APPEND_COREID(nss_ctx, if_num);
+}
+EXPORT_SYMBOL(nss_dtls_cmn_get_ifnum);
+
+/*
+ * nss_dtls_cmn_register_handler()
+ *	DTLS initialization.
+ */
+void nss_dtls_cmn_register_handler(void)
+{
+	sema_init(&dtls_cmn_pvt.sem, 1);
+	init_completion(&dtls_cmn_pvt.complete);
+	nss_stats_create_dentry("dtls_cmn", &nss_dtls_cmn_stats_ops);
+}
diff --git a/nss_hal/nss_hal.c b/nss_hal/nss_hal.c
index dacab2b..cd3592a 100644
--- a/nss_hal/nss_hal.c
+++ b/nss_hal/nss_hal.c
@@ -426,8 +426,14 @@
 
 	if (npd->dtls_enabled == NSS_FEATURE_ENABLED) {
 		nss_top->dtls_handler_id = nss_dev->id;
+#if defined(NSS_HAL_IPQ807x_SUPPORT)
+		nss_top->dynamic_interface_table[NSS_DYNAMIC_INTERFACE_TYPE_DTLS_CMN_INNER] = nss_dev->id;
+		nss_top->dynamic_interface_table[NSS_DYNAMIC_INTERFACE_TYPE_DTLS_CMN_OUTER] = nss_dev->id;
+		nss_dtls_cmn_register_handler();
+#else
 		nss_top->dynamic_interface_table[NSS_DYNAMIC_INTERFACE_TYPE_DTLS] = nss_dev->id;
 		nss_dtls_register_handler();
+#endif
 	}
 
 	if (npd->map_t_enabled == NSS_FEATURE_ENABLED) {
diff --git a/nss_tx_rx_common.h b/nss_tx_rx_common.h
index 6e80af4..e27077e 100644
--- a/nss_tx_rx_common.h
+++ b/nss_tx_rx_common.h
@@ -198,6 +198,7 @@
 extern void nss_portid_register_handler(void);
 extern void nss_oam_register_handler(void);
 extern void nss_dtls_register_handler(void);
+extern void nss_dtls_cmn_register_handler(void);
 extern void nss_gre_tunnel_register_handler(void);
 extern void nss_trustsec_tx_register_handler(void);
 extern void nss_wifili_register_handler(void);