Merge "[qca-nss-drv] Updated documentation in exports/nss_if.h"
diff --git a/Makefile b/Makefile
index 460ca76..22ef50a 100644
--- a/Makefile
+++ b/Makefile
@@ -13,11 +13,11 @@
 			nss_cmn.o \
 			nss_core.o \
 			nss_coredump.o \
-			nss_crypto.o \
 			nss_dtls.o \
 			nss_dynamic_interface.o \
 			nss_edma.o \
 			nss_eth_rx.o \
+			nss_gre.o \
 			nss_gre_redir.o \
 			nss_gre_tunnel.o \
 			nss_if.o \
@@ -67,13 +67,15 @@
 
 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_hal/ipq806x/nss_hal_pvt.o \
+		    nss_crypto.o
 ccflags-y += -I$(obj)/nss_hal/ipq806x -DNSS_HAL_IPQ806X_SUPPORT
 endif
 
 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_hal/ipq807x/nss_hal_pvt.o \
+		    nss_crypto_cmn.o
 ccflags-y += -I$(obj)/nss_hal/ipq807x -DNSS_HAL_IPQ807x_SUPPORT
 endif
 
@@ -90,9 +92,11 @@
 ccflags-y += -I$(obj)
 endif
 
-# Only the 3.14 Kernel implements fabric scaling framework and map-t
+# Fabric scaling is supported in 3.14 and 4.4 only
 ifneq ($(findstring 3.14, $(KERNELVERSION)),)
 NSS_CCFLAGS += -DNSS_FABRIC_SCALING_SUPPORT=1
+else if ($(findstring 4.4, $(KERNELVERSION)),)
+NSS_CCFLAGS += -DNSS_FABRIC_SCALING_SUPPORT=1
 else
 NSS_CCFLAGS += -DNSS_FABRIC_SCALING_SUPPORT=0
 endif
@@ -110,4 +114,3 @@
 export NSS_CCFLAGS
 
 obj ?= .
-
diff --git a/exports/nss_api_if.h b/exports/nss_api_if.h
index 3bf70a4..d7eaf57 100644
--- a/exports/nss_api_if.h
+++ b/exports/nss_api_if.h
@@ -43,8 +43,10 @@
 #include "nss_virt_if.h"
 #include "nss_pppoe.h"
 #include "nss_crypto.h"
+#include "nss_crypto_cmn.h"
 #include "nss_profiler.h"
 #include "nss_dynamic_interface.h"
+#include "nss_gre.h"
 #include "nss_gre_redir.h"
 #include "nss_gre_tunnel.h"
 #include "nss_sjack.h"
@@ -79,7 +81,7 @@
 #define NSS_MAX_PHYSICAL_INTERFACES 8	/**< Maximum number of physical interfaces. */
 #define NSS_MAX_VIRTUAL_INTERFACES 16	/**< Maximum number of virtual interfaces. */
 #define NSS_MAX_TUNNEL_INTERFACES 4	/**< Maximum number of tunnel interfaces. */
-#define NSS_MAX_SPECIAL_INTERFACES 46	/**< Maximum number of special interfaces. */
+#define NSS_MAX_SPECIAL_INTERFACES 47	/**< Maximum number of special interfaces. */
 #define NSS_MAX_WIFI_RADIO_INTERFACES 3	/**< Maximum number of radio interfaces. */
 
 /*
@@ -128,11 +130,11 @@
 #define NSS_PROFILER_INTERFACE (NSS_SPECIAL_IF_START + 8)
 		/**< Special interface number for profile. */
 #define NSS_CRYPTO_INTERFACE (NSS_SPECIAL_IF_START + 9)
-		/**< Special interface number for crypto. */
+		/**< Special interface number for crypto CE5. */
 #define NSS_DTLS_INTERFACE (NSS_SPECIAL_IF_START + 10)
 		/**< Special interface number for DTLS. */
-#define NSS_RESERVED_INTERFACE2 (NSS_SPECIAL_IF_START + 11)
-		/**< Reserved interface 2. */
+#define NSS_CRYPTO_EIP197_INTERFACE (NSS_SPECIAL_IF_START + 11)
+		/**< Special interface number for crypto EIP197. */
 #define NSS_C2C_TX_INTERFACE (NSS_SPECIAL_IF_START + 12)
 		/**< Virtual interface number for IPSec tunnel. */
 #define NSS_IPSEC_RULE_INTERFACE (NSS_SPECIAL_IF_START + 18)
@@ -191,6 +193,8 @@
 		/**< Special interface number for NSS Wi-Fi VAPs base interfacse. */
 #define NSS_VLAN_INTERFACE (NSS_SPECIAL_IF_START + 45)
 		/**< Special interface number for VLAN. */
+#define NSS_GRE_INTERFACE (NSS_SPECIAL_IF_START + 46)
+		/**< Special GRE interface. */
 
 /**
  * Converts the format of an IPv6 address from Linux to NSS. @hideinitializer
@@ -230,7 +234,6 @@
 #define MAX_VLAN_DEPTH 2
 		/**< Number of ingress or egress VLANS supported in a connection entry. */
 
-
 /**
  * nss_pm_client
  *	Power management (PM) clients.
diff --git a/exports/nss_crypto_cmn.h b/exports/nss_crypto_cmn.h
new file mode 100644
index 0000000..1149a93
--- /dev/null
+++ b/exports/nss_crypto_cmn.h
@@ -0,0 +1,407 @@
+/*
+ **************************************************************************
+ * 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_crypto_cmn.h
+ *	NSS Crypto common interface definitions.
+ */
+#ifndef __NSS_CRYPTO_CMN_H
+#define __NSS_CRYPTO_CMN_H
+
+/**
+ * @addtogroup nss_crypto_cmn_subsystem
+ * @{
+ */
+
+/*
+ * nss_crypto_cmn_ctx message related array sizes
+ */
+#define NSS_CRYPTO_CMN_CTX_SPARE 4 /**< words */
+#define NSS_CRYPTO_CMN_VER_WORDS 4 /**< words */
+
+/**
+ * nss_crypto_cmn_algo
+ *	List of crypto algorithms supported
+ */
+enum nss_crypto_cmn_algo {
+	NSS_CRYPTO_CMN_ALGO_NULL,			/**< NULL tranform */
+	NSS_CRYPTO_CMN_ALGO_3DES_CBC,			/**< Async block cipher */
+	NSS_CRYPTO_CMN_ALGO_AES128_CBC,			/**< Async block cipher */
+	NSS_CRYPTO_CMN_ALGO_AES192_CBC,			/**< Async block cipher */
+	NSS_CRYPTO_CMN_ALGO_AES256_CBC,			/**< Async block cipher */
+	NSS_CRYPTO_CMN_ALGO_MD5_HMAC,			/**< Async digest */
+	NSS_CRYPTO_CMN_ALGO_SHA1_HMAC,			/**< Async digest */
+	NSS_CRYPTO_CMN_ALGO_SHA256_HMAC,		/**< Async digest */
+	NSS_CRYPTO_CMN_ALGO_AES128_GMAC,		/**< Async digest */
+	NSS_CRYPTO_CMN_ALGO_AES192_GMAC,		/**< Async digest */
+	NSS_CRYPTO_CMN_ALGO_AES256_GMAC,		/**< Async digest */
+	NSS_CRYPTO_CMN_ALGO_AES128_GCM_GMAC,		/**< AEAD transform */
+	NSS_CRYPTO_CMN_ALGO_AES128_CBC_MD5_HMAC,	/**< AEAD transform */
+	NSS_CRYPTO_CMN_ALGO_AES128_CBC_SHA1_HMAC,	/**< AEAD transform */
+	NSS_CRYPTO_CMN_ALGO_AES128_CBC_SHA256_HMAC,	/**< AEAD transform */
+	NSS_CRYPTO_CMN_ALGO_AES192_GCM_GMAC,		/**< AEAD transform */
+	NSS_CRYPTO_CMN_ALGO_AES192_CBC_MD5_HMAC,	/**< AEAD transform */
+	NSS_CRYPTO_CMN_ALGO_AES192_CBC_SHA1_HMAC,	/**< AEAD transform */
+	NSS_CRYPTO_CMN_ALGO_AES192_CBC_SHA256_HMAC,	/**< AEAD transform */
+	NSS_CRYPTO_CMN_ALGO_AES256_GCM_GMAC,		/**< AEAD transform */
+	NSS_CRYPTO_CMN_ALGO_AES256_CBC_MD5_HMAC,	/**< AEAD transform */
+	NSS_CRYPTO_CMN_ALGO_AES256_CBC_SHA1_HMAC,	/**< AEAD transform */
+	NSS_CRYPTO_CMN_ALGO_AES256_CBC_SHA256_HMAC,	/**< AEAD transform */
+	NSS_CRYPTO_CMN_ALGO_AES128_CTR_MD5_HMAC,	/**< AEAD transform */
+	NSS_CRYPTO_CMN_ALGO_AES128_CTR_SHA1_HMAC,	/**< AEAD transform */
+	NSS_CRYPTO_CMN_ALGO_AES128_CTR_SHA256_HMAC,	/**< AEAD transform */
+	NSS_CRYPTO_CMN_ALGO_AES192_CTR_MD5_HMAC,	/**< AEAD transform */
+	NSS_CRYPTO_CMN_ALGO_AES192_CTR_SHA1_HMAC,	/**< AEAD transform */
+	NSS_CRYPTO_CMN_ALGO_AES192_CTR_SHA256_HMAC,	/**< AEAD transform */
+	NSS_CRYPTO_CMN_ALGO_AES256_CTR_MD5_HMAC,	/**< AEAD transform */
+	NSS_CRYPTO_CMN_ALGO_AES256_CTR_SHA1_HMAC,	/**< AEAD transform */
+	NSS_CRYPTO_CMN_ALGO_AES256_CTR_SHA256_HMAC,	/**< AEAD transform */
+	NSS_CRYPTO_CMN_ALGO_3DES_CBC_MD5_HMAC,		/**< AEAD transform */
+	NSS_CRYPTO_CMN_ALGO_3DES_CBC_SHA1_HMAC,		/**< AEAD transform */
+	NSS_CRYPTO_CMN_ALGO_3DES_CBC_SHA256_HMAC,	/**< AEAD transform */
+	NSS_CRYPTO_CMN_ALGO_MAX
+};
+
+/**
+ * nss_crypto_cmn_msg_type
+ *	Message types supported.
+ */
+enum nss_crypto_cmn_msg_type {
+	NSS_CRYPTO_CMN_MSG_TYPE_NONE = 0,		/**< Invalid message */
+	NSS_CRYPTO_CMN_MSG_TYPE_SETUP_NODE,		/**< Initialize Node */
+	NSS_CRYPTO_CMN_MSG_TYPE_SETUP_ENG,		/**< Initialize Engine */
+	NSS_CRYPTO_CMN_MSG_TYPE_SETUP_DMA,		/**< Initialize DMA pair */
+	NSS_CRYPTO_CMN_MSG_TYPE_SETUP_CTX,		/**< Update context info */
+	NSS_CRYPTO_CMN_MSG_TYPE_CLEAR_CTX,		/**< Clear context info */
+	NSS_CRYPTO_CMN_MSG_TYPE_VERIFY_CTX,		/**< Verify if context is active */
+	NSS_CRYPTO_CMN_MSG_TYPE_SYNC_NODE_STATS,	/**< Sync node stats */
+	NSS_CRYPTO_CMN_MSG_TYPE_SYNC_ENG_STATS,		/**< Sync engine stats */
+	NSS_CRYPTO_CMN_MSG_TYPE_SYNC_CTX_STATS,		/**< Sync context stats */
+	NSS_CRYPTO_CMN_MSG_TYPE_MAX
+};
+
+/**
+ * nss_crypto_cmn_msg_error
+ *	Message error types supported.
+ */
+enum nss_crypto_cmn_msg_error {
+	NSS_CRYPTO_CMN_MSG_ERROR_NONE = 0,
+	NSS_CRYPTO_CMN_MSG_ERROR_HDR_VERSION_NOSUPP,	/**< Common header version not supported */
+	NSS_CRYPTO_CMN_MSG_ERROR_NODE_CTX_RANGE,	/**< Context index out-of-range for node */
+	NSS_CRYPTO_CMN_MSG_ERROR_DMA_MASK,		/**< DMA mask is out-of-range */
+	NSS_CRYPTO_CMN_MSG_ERROR_DMA_POW2,		/**< DMA count is not a power-of-two */
+	NSS_CRYPTO_CMN_MSG_ERROR_DMA_MAX_TOKEN,		/**< DMA count exceeds token count */
+	NSS_CRYPTO_CMN_MSG_ERROR_DMA_TOKEN_ALLOC,	/**< Failed to allocate token */
+	NSS_CRYPTO_CMN_MSG_ERROR_CTX_RANGE,		/**< Context index out-of-range */
+	NSS_CRYPTO_CMN_MSG_ERROR_CTX_INUSE,		/**< Context has references */
+	NSS_CRYPTO_CMN_MSG_ERROR_CTX_WORDS,		/**< Context size is bad */
+	NSS_CRYPTO_CMN_MSG_ERROR_CTX_ALGO,		/**< Context algorithm is bad */
+	NSS_CRYPTO_CMN_MSG_ERROR_CTX_ALLOC,		/**< Context alloc failed */
+	NSS_CRYPTO_CMN_MSG_ERROR_CTX_NOUSE,		/**< Context has no references */
+	NSS_CRYPTO_CMN_MSG_ERROR_CTX_FLAGS,		/**< Invalid context flags */
+	NSS_CRYPTO_CMN_MSG_ERROR_MAX
+};
+
+/**
+ * nss_crypto_cmn_ctx_flags
+ *	Context message specific flags.
+ */
+enum nss_crypto_cmn_ctx_flags {
+	NSS_CRYPTO_CMN_CTX_FLAGS_NONE = 0,		/**< Invalid flags. */
+	NSS_CRYPTO_CMN_CTX_FLAGS_SEC_OFFSET = 0x01,	/**< Secure offset is valid. */
+	NSS_CRYPTO_CMN_CTX_FLAGS_SPARE0 = 0x02,		/**< Spare word-0 valid. */
+	NSS_CRYPTO_CMN_CTX_FLAGS_SPARE1 = 0x04,		/**< Spare word-1 valid. */
+	NSS_CRYPTO_CMN_CTX_FLAGS_SPARE2 = 0x08,		/**< Spare word-2 valid. */
+	NSS_CRYPTO_CMN_CTX_FLAGS_SPARE3 = 0x10,		/**< Spare word-3 valid. */
+	NSS_CRYPTO_CMN_CTX_FLAGS_MAX
+};
+
+/**
+ * nss_crypto_cmn_node
+ *	Node message for setting up the crypto node
+ *
+ * Note: Upon boot this is the first message sent by Host to NSS crypto
+ *	- It notifies the maximum number of Crypto Context.
+ *	- It notifies the maximum number of DMA rings.
+ *	- It returns the maximum size of crypto context record.
+ */
+struct nss_crypto_cmn_node {
+	uint32_t max_dma_rings;		/**< Maximum DMA rings supported */
+	uint32_t max_ctx;		/**< Maximum contexts */
+	uint32_t max_ctx_size;		/**< Maximum context size */
+};
+
+/**
+ * nss_crypto_cmn_engine
+ *	Engine message for setting up the instance of crypto engine
+ *
+ * Note: This is sent after 'node' message for each engine to
+ *	- Get valid DMA pairs supported by firmware
+ *	- Get maximum request/token count available in firmware
+ */
+struct nss_crypto_cmn_engine {
+	uint32_t fw_ver[NSS_CRYPTO_CMN_VER_WORDS];	/**< FW version */
+	uint32_t dma_mask;				/**< Max DMA rings */
+	uint32_t req_count;				/**< Token count */
+};
+
+/**
+ * nss_crypto_cmn_dma
+ *	DMA message for setting up each DMA pair per engine
+ */
+struct nss_crypto_cmn_dma {
+	struct {
+		uint32_t ring_addr;	/**< Ring physical address */
+		uint32_t write_reg;	/**< Write register address */
+		uint32_t read_reg;	/**< Read register address */
+	} in, out;
+
+	uint16_t count;			/**< No. of descriptors */
+	uint16_t pair_id;		/**< DMA pair-id */
+};
+
+/**
+ * nss_crypto_cmn_ctx
+ *	Context message for setting up a crypto context in firmware
+ */
+struct nss_crypto_cmn_ctx {
+	uint32_t words;					/**< Number of valid context words */
+	uint32_t addr;					/**< Address to config */
+	uint32_t spare[NSS_CRYPTO_CMN_CTX_SPARE];	/**< Context spare words */
+
+	uint16_t index;					/**< Crypto index */
+	uint16_t sec_offset;				/**< Secure offset for copying keys */
+
+	enum nss_crypto_cmn_algo algo;			/**< Crypto algorithm */
+	enum nss_crypto_cmn_ctx_flags flags;		/**< Context specific flags */
+};
+
+/**
+ * nss_crypto_cmn_stats
+ *	statistics message applicable for Node/Engine/Context
+ */
+struct nss_crypto_cmn_stats {
+	struct nss_cmn_node_stats nstats;	/**< Common node stats */
+	uint32_t fail_version;			/**< Version mismatch failures */
+	uint32_t fail_ctx;			/**< Context related failures */
+	uint32_t fail_dma;			/**< DMA descriptor full */
+};
+
+/**
+ * nss_crypto_cmn_msg
+ *	Crypto common configuration message.
+ */
+struct nss_crypto_cmn_msg {
+	struct nss_cmn_msg cm;				/**< Common header */
+	uint32_t seq_num;				/**< Seq no. for messages */
+	uint32_t uid;					/**< Unique ID to identify Engine/Context */
+
+	union {
+		struct nss_crypto_cmn_node node;	/**< Node message */
+		struct nss_crypto_cmn_engine eng;	/**< Engine message */
+		struct nss_crypto_cmn_dma dma;		/**< DMA message */
+		struct nss_crypto_cmn_ctx ctx;		/**< Context message */
+		struct nss_crypto_cmn_stats stats;	/**< Stats message */
+	} msg;
+};
+
+#ifdef __KERNEL__  /* only kernel will use */
+
+/**
+ * Callback function for receiving crypto transformation upon completion
+ *
+ * @datatype
+ * net_device \n
+ * sk_buff \n
+ * napi_struct
+ *
+ * @param[in] netdev  networking device registered for callback
+ * @param[in] skb     packet buffer
+ * @param[in] napi    NAPI pointer for Linux NAPI handling
+ *
+ * @return
+ * None.
+ */
+typedef void (*nss_crypto_cmn_buf_callback_t)(struct net_device *netdev, struct sk_buff *skb,
+						struct napi_struct *napi);
+
+/**
+ * Callback function for receiving crypto_cmn messages
+ *
+ * @datatype
+ * nss_crypto_cmn_msg
+ *
+ * @param[in] app_data  Context of the callback user
+ * @param[in] msg       Crypto common message
+ *
+ * @return
+ * None.
+ */
+typedef void (*nss_crypto_cmn_msg_callback_t)(void *app_data, struct nss_crypto_cmn_msg *msg);
+
+/**
+ * nss_crypto_cmn_tx_buf
+ *	Send crypto payload to firmware for transformation
+ *
+ * @datatype
+ * nss_ctx_instance \n
+ * sk_buff
+ *
+ * @param[in] nss_ctx  NSS context per NSS core
+ * @param[in] if_num   Crypto interface to send the buffer
+ * @param[in] skb      Crypto payload
+ *
+ * @return
+ * Status of the TX operation.
+ */
+extern nss_tx_status_t nss_crypto_cmn_tx_buf(struct nss_ctx_instance *nss_ctx, uint32_t if_num, struct sk_buff *skb);
+
+/**
+ * nss_crypto_cmn_tx_msg
+ *	Send crypto message to firmware for configuration
+ *
+ * @datatype
+ * nss_ctx_instance \n
+ * nss_crypto_cmn_msg
+ *
+ * @param[in] nss_ctx]  NSS context per NSS core
+ * @param[in] msg       Control message
+ *
+ * @return
+ * Status of the TX operation.
+ */
+extern nss_tx_status_t nss_crypto_cmn_tx_msg(struct nss_ctx_instance *nss_ctx, struct nss_crypto_cmn_msg *msg);
+
+/**
+ * nss_crypto_cmn_tx_msg
+ *	Send crypto message to firmware for configuration synchronously
+ *
+ * @datatype
+ * nss_ctx_instance \n
+ * nss_crypto_cmn_msg
+ *
+ * @param[in]     nss_ctx  NSS context per NSS core
+ * @param[in,out] msg      Crypto message, response data is copied
+ *
+ * @return
+ * Status of the TX operation.
+ *
+ * @note
+ * Response data for the  message is copied into the 'msg'.
+ * The caller should read the content of the 'msg' to find out errors.
+ * The caller needs to invoke this from a non-atomic context.
+ */
+extern nss_tx_status_t nss_crypto_cmn_tx_msg_sync(struct nss_ctx_instance *nss_ctx, struct nss_crypto_cmn_msg *msg);
+
+/**
+ * nss_crypto_cmn_notify_register
+ *	register a event callback handler with NSS driver
+ *
+ * @datatype
+ * nss_crypto_cmn_msg_callback_t
+ *
+ * @param[in] cb            event callback function
+ * @param[in] app_data[IN]  context of the callback user
+ *
+ * @return
+ * Pointer to the NSS core context.
+ */
+extern struct nss_ctx_instance *nss_crypto_cmn_notify_register(nss_crypto_cmn_msg_callback_t cb, void *app_data);
+
+/**
+ * nss_crypto_cmn_notify_unregister
+ *	unregister the event callback handler with NSS driver
+ *
+ * @datatype
+ * nss_ctx_instance
+ *
+ * @param[in] nss_ctx  NSS context per NSS core
+ *
+ * @return
+ * None.
+ */
+extern void nss_crypto_cmn_notify_unregister(struct nss_ctx_instance *ctx);
+
+/**
+ * nss_crypto_cmn_data_register
+ *	crypto data register
+ *
+ * @datatype
+ * nss_crypto_cmn_buf_callback_t \n
+ * net_device
+ *
+ * @param[in] if_num    interface number
+ * @param[in] cb        callback function
+ * @param[in] netdev    net device
+ * @param[in] features  features supported
+ *
+ * @return
+ * Pointer to the NSS core context.
+ */
+extern struct nss_ctx_instance *nss_crypto_cmn_data_register(uint32_t if_num,
+						nss_crypto_cmn_buf_callback_t cb,
+						struct net_device *netdev,
+						uint32_t features);
+
+/**
+ * nss_crypto_cmn_data_unregister
+ *	crypto data unregister
+ *
+ * @param[in] ctx     NSS context per NSS core
+ * @param[in] if_num  interface number
+ *
+ * @return
+ * None.
+ */
+extern void nss_crypto_cmn_data_unregister(struct nss_ctx_instance *ctx, uint32_t if_num);
+
+/**
+ * nss_crypto_cmn_get_context
+ *	get the per NSS core context enabled for crypto
+ *
+ * @return
+ * Pointer to the NSS core context.
+ */
+extern struct nss_ctx_instance *nss_crypto_cmn_get_context(void);
+
+/**
+ * nss_crypto_cmn_msg_init
+ *	crypto common message init
+ *
+ * @datatype
+ * nss_crypto_cmn_msg \n
+ * nss_crypto_cmn_msg_callback_t
+ *
+ * @param[in] ncm       crypto cmn message
+ * @param[in] if_num    interface number
+ * @param[in] type      type
+ * @param[in] len       common message length
+ * @param[in] cb        callback function
+ * @param[in] app_data  appllication data
+ *
+ * @return
+ * None.
+ */
+extern void nss_crypto_cmn_msg_init(struct nss_crypto_cmn_msg *ncm, uint16_t if_num,
+				uint32_t type, uint32_t len, nss_crypto_cmn_msg_callback_t cb,
+				void *app_data);
+
+#endif /*__KERNEL__ */
+
+/**
+ * @}
+ */
+#endif
diff --git a/exports/nss_dynamic_interface.h b/exports/nss_dynamic_interface.h
index 26061f4..d07a5e5 100644
--- a/exports/nss_dynamic_interface.h
+++ b/exports/nss_dynamic_interface.h
@@ -52,6 +52,7 @@
 	NSS_DYNAMIC_INTERFACE_TYPE_GRE_TUNNEL,
 	NSS_DYNAMIC_INTERFACE_TYPE_BRIDGE,
 	NSS_DYNAMIC_INTERFACE_TYPE_VLAN,
+	NSS_DYNAMIC_INTERFACE_TYPE_GRE,
 	NSS_DYNAMIC_INTERFACE_TYPE_MAX
 };
 
diff --git a/exports/nss_edma.h b/exports/nss_edma.h
index b719ac2..4b2a185 100644
--- a/exports/nss_edma.h
+++ b/exports/nss_edma.h
@@ -100,7 +100,7 @@
 
 /**
  * nss_edma_port_stats
- *	EDMA port statistics.
+ *	Statistics for each EDMA port.
  */
 struct nss_edma_port_stats {
 	struct nss_cmn_node_stats node_stats;	/**< Common node statistics. */
@@ -111,7 +111,7 @@
 
 /**
  * nss_edma_port_stats_sync
- *	Synchronized EDMA port statistics.
+ *	Statistics for a group of EDMA ports.
  */
 struct nss_edma_port_stats_sync {
 	uint16_t start_port;		/**< Starting index of the subset. */
@@ -122,7 +122,7 @@
 
 /**
  * nss_edma_ring_stats_sync
- *	Synchronized EDMA ring statistics.
+ *	EDMA ring statistics.
  */
 struct nss_edma_ring_stats_sync {
 	struct nss_edma_tx_ring_stats tx_ring[NSS_EDMA_NUM_TX_RING_MAX];
@@ -148,13 +148,13 @@
 	 */
 	union {
 		struct nss_edma_port_stats_sync port_stats;
-				/**< Synchronized port statistics. ??is this comment correct? */
+				/**< EDMA port statistics message payload. */
 		struct nss_edma_ring_stats_sync ring_stats;
-				/**< Synchronized ring statistics. ??is this comment correct? */
-	} msg;			/**< Message payload. ??is this comment correct? I assumed it's the message payload because the first field is the message header */
+				/**< EDMA ring statistics message payload. */
+	} msg;			/**< EDMA message payload. */
 };
 
-#ifdef __KERNEL__ /* only kernel will use. ??do you want the following in the PDF?*/
+#ifdef __KERNEL__
 
 /**
  * Callback function for receiving EDMA messages.
diff --git a/exports/nss_gre.h b/exports/nss_gre.h
new file mode 100644
index 0000000..a6fec7c
--- /dev/null
+++ b/exports/nss_gre.h
@@ -0,0 +1,377 @@
+/*
+ **************************************************************************
+ * 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_gre.h
+ *	NSS GRE interface definitions.
+ */
+#ifndef _NSS_GRE_H_
+#define _NSS_GRE_H_
+
+/**
+ * @addtogroup nss_gre_subsystem
+ * @{
+ */
+
+/**
+ * Maximum number of session debug statistics
+ */
+#define NSS_GRE_MAX_DEBUG_SESSION_STATS 16
+
+/**
+ * GRE flags
+ */
+#define NSS_GRE_CONFIG_IKEY_VALID	0x00000001	/**< Incoming key of GRE header. */
+#define NSS_GRE_CONFIG_OKEY_VALID	0x00000002	/**< Key for outgoing GRE header. */
+#define NSS_GRE_CONFIG_ISEQ_VALID	0x00000004	/**< Enable sequence checking for incoming GRE traffic. */
+#define NSS_GRE_CONFIG_OSEQ_VALID	0x00000008	/**< Add sequence number for out going GRE packets. */
+#define NSS_GRE_CONFIG_ICSUM_VALID	0x00000010	/**< Validate incoming GRE header Checksum. */
+#define NSS_GRE_CONFIG_OCSUM_VALID	0x00000020	/**< Add CS header to GRE header*/
+#define NSS_GRE_CONFIG_TOS_INHERIT	0x00000040	/**< Inherit inner IP TOS to tunnel header, if not set configure provided TOS. */
+#define NSS_GRE_CONFIG_TTL_INHERIT	0x00000080	/**< Inherit inner IP TTL to tunnel header, if not set configure provided TTL. */
+#define NSS_GRE_CONFIG_SET_DF		0x00000100	/**< Enable DF bit on tunnel IP header. */
+#define NSS_GRE_CONFIG_SET_MAC		0x00000200	/**< Add MAC header to GRE+IP tunnel header. */
+#define NSS_GRE_CONFIG_SET_PADDING	0x00000400	/**< Add PADDING to align tunnel IP/GRE header. */
+#define NSS_GRE_CONFIG_NEXT_NODE_AVAILABLE  0x00000800	/**< Use provided next_node instead of existing next node. */
+
+/**
+ * nss_gre_msg_types
+ *	Message types for GRE requests and responses.
+ */
+enum nss_gre_msg_types {
+	NSS_GRE_MSG_CONFIGURE = NSS_IF_MAX_MSG_TYPES + 1,
+	NSS_GRE_MSG_DECONFIGURE,
+	NSS_GRE_MSG_SESSION_STATS,
+	NSS_GRE_MSG_BASE_STATS,
+	NSS_GRE_MSG_MAX
+};
+
+/**
+ * GRE Mode Types
+ */
+enum nss_gre_mode {
+	NSS_GRE_MODE_TUN,	/**< GRE Tunnel interface. */
+	NSS_GRE_MODE_TAP,	/**< GRE Tap interface. */
+	NSS_GRE_MODE_MAX	/**< Maxmum GRE mode. */
+};
+
+/**
+ * GRE IP Types
+ */
+enum nss_gre_ip_types {
+	NSS_GRE_IP_IPV4,	/**<  Outer Tunnel is IPV4. */
+	NSS_GRE_IP_IPV6,	/**<  Outer Tunnel is IPV6. */
+	NSS_GRE_IP_MAX,		/**<  Maximum IP Types. */
+};
+
+/**
+ * GRE Base debug statistics
+ */
+enum nss_gre_base_debug_types {
+	GRE_BASE_RX_PACKETS,			/**< Rx packet count. */
+	GRE_BASE_RX_DROPPED,			/**< Number of packet dropped at Rx. */
+	GRE_BASE_EXP_ETH_HDR_MISSING,		/**< Ethernet header missing. */
+	GRE_BASE_EXP_ETH_TYPE_NON_IP,		/**< Packet is not IPV4 or IPV6. */
+	GRE_BASE_EXP_IP_UNKNOWN_PROTOCOL,	/**< Packet protocol is unknown. */
+	GRE_BASE_EXP_IP_HEADER_INCOMPLETE,	/**< Bad IP header. */
+	GRE_BASE_EXP_IP_BAD_TOTAL_LENGTH,	/**< IP total lenghth is invalid. */
+	GRE_BASE_EXP_IP_BAD_CHECKSUM,		/**< IP checksum is bad. */
+	GRE_BASE_EXP_IP_DATAGRAM_INCOMPLETE,	/**< Bad packet. */
+	GRE_BASE_EXP_IP_FRAGMENT,		/**< IP packet is a fragment. */
+	GRE_BASE_EXP_IP_OPTIONS_INCOMPLETE,	/**< IP option is invalid. */
+	GRE_BASE_EXP_IP_WITH_OPTIONS,		/**< IP packet with options. */
+	GRE_BASE_EXP_IPV6_UNKNOWN_PROTOCOL,	/**< Protocol is unknown. */
+	GRE_BASE_EXP_IPV6_HEADER_INCOMPLETE,	/**< Incomplete ipv6 header. */
+	GRE_BASE_EXP_GRE_UNKNOWN_SESSION,	/**< Unknown GRE session. */
+	GRE_BASE_EXP_GRE_NODE_INACTIVE,		/**< GRE node is inactive. */
+	GRE_BASE_DEBUG_MAX,			/**< GRE base debug max. */
+};
+
+/*
+ * GRE session Packet drop and exception events.
+ */
+enum gre_session_debug_types {
+	GRE_SESSION_PBUF_ALLOC_FAIL,		/**< Pbuf allocation failure. */
+	GRE_SESSION_DECAP_FORWARD_ENQUEUE_FAIL,	/**< Rx forward enqueue failure. */
+	GRE_SESSION_ENCAP_FORWARD_ENQUEUE_FAIL,	/**< Tx forward enqueue failure. */
+	GRE_SESSION_DECAP_TX_FORWARDED,		/**< Number of packets forwarded after decap. */
+	GRE_SESSION_ENCAP_RX_RECEIVED,		/**< Number of packets received for encap. */
+	GRE_SESSION_ENCAP_RX_DROPPED,		/**< Packets dropped while enqueuing for encap. */
+	GRE_SESSION_ENCAP_RX_LINEAR_FAIL,	/**< Packets dropped during encap linearization. */
+	GRE_SESSION_EXP_RX_KEY_ERROR,		/**< Rx KEY error. */
+	GRE_SESSION_EXP_RX_SEQ_ERROR,		/**< Rx Sequence number error. */
+	GRE_SESSION_EXP_RX_CS_ERROR,		/**< Rx checksum error */
+	GRE_SESSION_EXP_RX_FLAG_MISMATCH,	/**< Rx flag mismatch. */
+	GRE_SESSION_EXP_RX_MALFORMED,		/**< Rx packet is malformed. */
+	GRE_SESSION_EXP_RX_INVALID_PROTOCOL,	/**< Rx packet protocol is invalid. */
+	GRE_SESSION_EXP_RX_NO_HEADROOM,		/**< Packet does not have enough headroom. */
+	GRE_SESSION_DEBUG_MAX,			/**< Session debug max. */
+};
+
+/**
+ * GRE create message structure.
+ */
+struct nss_gre_config_msg {
+	uint32_t src_ip[4];			/**< Source IPv4 or IPv6 Adddress. */
+	uint32_t dest_ip[4];			/**< Destination IPv4 or IPv6 Adddress. */
+	uint32_t flags;				/**< GRE Flags. */
+	uint32_t ikey;				/**< GRE rx KEY.*/
+	uint32_t okey;				/**< GRE tx KEY. */
+	uint32_t mode;				/**< GRE TUN or TAP. */
+	uint32_t ip_type;			/**< IPv4 or IPv6 type. */
+	uint32_t next_node_if_num;		/**< To whom to forward packets. */
+	uint16_t src_mac[3];			/**< Source MAC address. */
+	uint16_t dest_mac[3];			/**< Destination MAC address. */
+	uint8_t ttl;				/**< TTL or HOPLIMIT. */
+	uint8_t tos;				/**< Type of service. */
+	uint16_t reserved;			/**< Padding Reservation. */
+};
+
+/**
+ * GRE link up message structure
+ */
+struct nss_gre_linkup_msg {
+	int if_number;			/**< Interface number. */
+};
+
+/**
+ * GRE link down message structure
+ */
+struct nss_gre_linkdown_msg {
+	int if_number;			/**< Interface number. */
+};
+
+/**
+ * GRE deconfig message structure
+ */
+struct nss_gre_deconfig_msg {
+	int if_number;			/**< Interface number */
+};
+
+/**
+ * GRE session statistics message
+ */
+struct nss_gre_session_stats_msg {
+	struct nss_cmn_node_stats node_stats;	/**< Common node statistics. */
+	uint32_t stats[GRE_SESSION_DEBUG_MAX];	/**< Session debug statistics. */
+};
+
+/**
+ * GRE base statistics message
+ */
+struct nss_gre_base_stats_msg {
+	uint32_t stats[GRE_BASE_DEBUG_MAX];	/**< Base debug statistics. */
+};
+
+/**
+ * nss_gre_msg
+ *	Message structure to send/receive GRE messages
+ */
+struct nss_gre_msg {
+	struct nss_cmn_msg cm;					/**< Common message header */
+
+	/**
+	 * Payload of a GRE message.
+	 */
+	union {
+		struct nss_gre_config_msg cmsg;			/**< GRE session config message. */
+		struct nss_gre_deconfig_msg dmsg;		/**< GRE session deconfig message. */
+		struct nss_gre_linkup_msg linkup;		/**< GRE link up message. */
+		struct nss_gre_linkdown_msg linkdown;		/**< GRE link down message. */
+		struct nss_gre_session_stats_msg sstats;	/**< GRE session statistics message. */
+		struct nss_gre_base_stats_msg bstats;		/**< Base statistics message. */
+	} msg;							/**< Message payload. */
+};
+
+/**
+ * Callback function to receive GRE messages
+ *
+ * @datatypes
+ * nss_gre_msg
+ *
+ * @param[in] app_data  Pointer to the application context of the message.
+ * @param[in] msg       Pointer to the message data.
+ */
+typedef void (*nss_gre_msg_callback_t)(void *app_data, struct nss_gre_msg *msg);
+
+/**
+ * nss_gre_tx_msg
+ *	Sends GRE messages to the NSS.
+ *
+ * @datatypes
+ * nss_ctx_instance \n
+ * nss_gre_msg
+ *
+ * @param[in]     nss_ctx  Pointer to the NSS context.
+ * @param[in]     msg      Pointer to the message data.
+ *
+ * @return
+ * Status of the Tx operation.
+ */
+extern nss_tx_status_t nss_gre_tx_msg(struct nss_ctx_instance *nss_ctx, struct nss_gre_msg *msg);
+
+/**
+ * nss_gre_tx_msg_sync
+ *	Sends GRE messages to the NSS synchronously.
+ *
+ * @datatypes
+ * nss_ctx_instance \n
+ * nss_gre_msg
+ *
+ * @param[in]     nss_ctx  Pointer to the NSS context.
+ * @param[in]     msg      Pointer to the message data.
+ *
+ * @return
+ * Status of the Tx operation.
+ */
+extern nss_tx_status_t nss_gre_tx_msg_sync(struct nss_ctx_instance *nss_ctx, struct nss_gre_msg *msg);
+
+/**
+ * nss_gre_tx_buf
+ *	Sends packet to the NSS
+ *
+ * @datatypes
+ * nss_ctx_instance \n
+ * sk_buff
+ *
+ * @param[in]     nss_ctx  Pointer to the NSS context.
+ * @param[in]     if_num   Nss interface number.
+ * @param[in]     skb	   Pointer to sk_buff.
+ *
+ * @return Tx status
+ */
+extern nss_tx_status_t nss_gre_tx_buf(struct nss_ctx_instance *nss_ctx, uint32_t if_num, struct sk_buff *skb);
+
+/**
+ * nss_gre_get_context.
+ *	Gets the GRE context used in nss_gre_tx.
+ *
+ * @return
+ * Pointer to the NSS core context.
+ */
+extern struct nss_ctx_instance *nss_gre_get_context(void);
+
+/**
+ * Callback function for receiving GRE 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_gre_data_callback_t)(struct net_device *netdev, struct sk_buff *skb, struct napi_struct *napi);
+
+/**
+ * nss_gre_base_debug_stats_get
+ *	Gets NSS GRE base debug statistics.
+ *
+ * @param[in] stats_mem	Pointer to memory to which stats should be copied.
+ * @param[in] size 	Stats memory size.
+ * @param[out] stats_mem  Pointer to the memory address, which must be large
+ *                         enough to hold all the statistics.
+ *
+ * @return
+ * None.
+ */
+extern void nss_gre_base_debug_stats_get(void *stats_mem, int size);
+
+/**
+ * nss_gre_session_debug_stats_get
+ *	Gets NSS GRE session debug statistics.
+ *
+ * @param[in] stats_mem	  Pointer to memory to which stats should be copied.
+ * @param[in] size 	  Stats memory size.
+ * @param[out] stats_mem  Pointer to the memory address, which must be large
+ *                         enough to hold all the statistics.
+ *
+ * @return
+ * None.
+ */
+extern void nss_gre_session_debug_stats_get(void *stats_mem, int size);
+
+/**
+ * nss_gre_register_if
+ *	Registers the GRE interface with the NSS for sending and
+ *	receiving messages.
+ *
+ * @datatypes
+ * nss_gre_data_callback_t \n
+ * nss_gre_msg_callback_t \n
+ * net_device
+ *
+ * @param[in] if_num			NSS interface number.
+ * @param[in] nss_gre_data_callback     Callback for the data.
+ * @param[in] msg_callback		Callback for the message.
+ * @param[in] netdev			Pointer to the associated network device.
+ * @param[in] features			Socket buffer types supported by this interface.
+ *
+ * @return
+ * Pointer to the NSS core context.
+ */
+extern struct nss_ctx_instance *nss_gre_register_if(uint32_t if_num, nss_gre_data_callback_t gre_callback,
+					nss_gre_msg_callback_t msg_callback, struct net_device *netdev, uint32_t features);
+
+/**
+ * nss_gre_unregister_if
+ *	Deregisters the GRE interface from the NSS.
+ *
+ * @param[in] if_num  NSS interface number.
+. *
+ * @return
+ * None.
+ *
+ * @dependencies
+ * The tunnel interface must have been previously registered.
+ */
+extern void nss_gre_unregister_if(uint32_t if_num);
+
+/**
+ * nss_gre_msg_init
+ *	Initializes a GRE message.
+ *
+ * @datatypes
+ * nss_gre_msg
+ *
+ * @param[in,out] ncm       Pointer to the message.
+ * @param[in]     if_num    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 of the message.
+ *
+ * @return
+ * None.
+ */
+extern void nss_gre_msg_init(struct nss_gre_msg *ncm, uint16_t if_num, uint32_t type,  uint32_t len, void *cb, void *app_data);
+
+/**
+ * nss_gre_register_handler
+ *	Registers the GRE interface with the NSS debug statistics handler.
+ *
+ * @return
+ * None.
+ */
+extern void nss_gre_register_handler(void);
+
+/**
+ * @}
+ */
+
+#endif /* _NSS_GRE_H_ */
diff --git a/exports/nss_ipsec.h b/exports/nss_ipsec.h
index 381e227..69bbc30 100644
--- a/exports/nss_ipsec.h
+++ b/exports/nss_ipsec.h
@@ -88,6 +88,7 @@
 	NSS_IPSEC_ERROR_TYPE_MAX_SA = 5,
 	NSS_IPSEC_ERROR_TYPE_MAX_FLOW = 6,
 	NSS_IPSEC_ERROR_TYPE_INVALID_CINDEX = 7,
+	NSS_IPSEC_ERROR_TYPE_INVALID_IPVER = 8,
 	NSS_IPSEC_ERROR_TYPE_MAX
 };
 
diff --git a/exports/nss_ipv4.h b/exports/nss_ipv4.h
index 41e1c66..d135bbd 100644
--- a/exports/nss_ipv4.h
+++ b/exports/nss_ipv4.h
@@ -30,11 +30,13 @@
 /**
  * nss_ipv4_message_types
  *	IPv4 bridge and routing rule message types.
+ *
+ * NSS_IPV4_RX_DEPRECATED0 is a deprecated type. It is kept for backward compatibility.
  */
 enum nss_ipv4_message_types {
 	NSS_IPV4_TX_CREATE_RULE_MSG,
 	NSS_IPV4_TX_DESTROY_RULE_MSG,
-	NSS_IPV4_RX_DEPRECATED0,		/**< Deprecated: NSS_IPV4_RX_ESTABLISH_RULE_MSG. ??what does this mean - customer is to use this msg? Can't find it in the headers */
+	NSS_IPV4_RX_DEPRECATED0,
 	NSS_IPV4_RX_CONN_STATS_SYNC_MSG,
 	NSS_IPV4_RX_NODE_STATS_SYNC_MSG,
 	NSS_IPV4_TX_CONN_CFG_RULE_MSG,
@@ -45,7 +47,7 @@
 };
 
 /*
- * NA IPv4 rule creation & rule update flags.
+ * NSS IPv4 rule creation & rule update flags.
  */
 #define NSS_IPV4_RULE_CREATE_FLAG_NO_SEQ_CHECK 0x01
 		/**< Do not perform TCP sequence number checks. */
@@ -103,19 +105,21 @@
 		/**< Ingress PPPoE fields are valid. */
 
 /*
- * Multicast connection per-interface rule flags (to be used with rule_flags field of nss_ipv4_mc_if_rule structure)
+ * Per-interface rule flags for a multicast connection (to be used with the rule_flags
+ * field of nss_ipv4_mc_if_rule structure).
  */
 #define NSS_IPV4_MC_RULE_CREATE_IF_FLAG_BRIDGE_FLOW 0x01
-		/**< Bridge flow. ??need more info */
+		/**< Multicast connection rule is created for a bridge flow. */
 #define NSS_IPV4_MC_RULE_CREATE_IF_FLAG_ROUTED_FLOW 0x02
-		/**< Routed flow. ??need more info */
+		/**< Multicast connection rule is created for a routed flow. */
 #define NSS_IPV4_MC_RULE_CREATE_IF_FLAG_JOIN 0x04
 		/**< Interface has joined the flow. */
 #define NSS_IPV4_MC_RULE_CREATE_IF_FLAG_LEAVE 0x08
 		/**< Interface has left the flow. */
 
 /*
- * Multicast connection per-interface valid flags (to be used with valid_flags field of nss_ipv4_mc_if_rule structure)
+ * Per-interface valid flags for a multicast connection (to be used with the valid_flags
+ * field of nss_ipv4_mc_if_rule structure).
  */
 #define NSS_IPV4_MC_RULE_CREATE_IF_FLAG_VLAN_VALID 0x01
 		/**< VLAN fields are valid. */
@@ -199,14 +203,22 @@
 
 /**
  * nss_ipv4_nexthop
- *	Information for next hop interface numbers. ??new
+ *	Information for next hop interface numbers.
  *
  * A next hop is the next interface that will receive the packet (as opposed to
- * the final interface that the packet will go out on ??out on what?).
+ * the final interface when the packet leaves the device.
  */
 struct nss_ipv4_nexthop {
-	int32_t flow_nexthop;		/**< Flow next hop interface number. ??doesn't make sense */
-	int32_t return_nexthop;		/**< Return next hop interface number. ??does this mean the next number is being returned? */
+	/**
+	 * Next hop interface number of the flow direction (from which the connection
+	 * originated).
+	 */
+	int32_t flow_nexthop;
+	/**
+	 * Next hop interface number of the return direction (to which the connection
+	 * is destined).
+	 */
+	int32_t return_nexthop;
 };
 
 /**
@@ -319,7 +331,7 @@
 	/*
 	 * Response
 	 */
-	uint32_t reserved;		/**< Alignment padding. ??is this comment correct? */
+	uint32_t reserved;	/**< Reserved field for a response message. */
 };
 
 /**
@@ -339,7 +351,7 @@
 	uint32_t if_num;		/**< Interface number. */
 	uint32_t if_mtu;		/**< Interface MTU. */
 	uint16_t if_mac[3];		/**< Interface MAC address. */
-	uint8_t reserved[2];		/**< Reserved for ?? bytes. */
+	uint8_t reserved[2];		/**< Reserved 2 bytes for alignment. */
 };
 
 /**
@@ -361,7 +373,7 @@
 	uint16_t dest_mac[3];			/**< Destination multicast MAC address. */
 	uint16_t if_count;			/**< Number of destination interfaces. */
 	uint8_t egress_dscp;			/**< Egress DSCP value for the flow. */
-	uint8_t reserved[3];			/**< Reserved for ?? bytes. */
+	uint8_t reserved[3];			/**< Reserved 3 bytes for alignment. */
 
 	struct nss_ipv4_mc_if_rule if_rule[NSS_MC_IF_MAX];
 						/**< Per-interface information. */
@@ -377,8 +389,8 @@
 
 /**
  * nss_ipv4_rule_conn_cfg_msg
-  *	IPv4 rule for connection configuration sub-messages.
-*/
+ *	IPv4 rule for connection configuration sub-messages.
+ */
 struct nss_ipv4_rule_conn_cfg_msg {
 	uint32_t num_conn;		/**< Number of supported IPv4 connections. */
 };
@@ -400,10 +412,10 @@
 
 /**
  * nss_ipv4_conn_sync
- *	IPv4 synchronized connections. ??is this comment correct?
+ *	IPv4 connection synchronization message.
  */
 struct nss_ipv4_conn_sync {
-	uint32_t reserved;		/**< Alignment padding. ??is this comment correct?  */
+	uint32_t reserved;		/**< Reserved field for backward compatibility. */
 	uint8_t protocol;		/**< Protocol number. */
 	uint32_t flow_ip;		/**< Flow IP address. */
 	uint32_t flow_ip_xlate;		/**< Translated flow IP address. */
@@ -474,7 +486,7 @@
 
 /**
  * nss_ipv4_conn_sync_many_msg
- *	Message information for synchronized IPv4 connection statistics for many messages. ??is this comment correct?
+ *	Information for a multiple IPv4 connection statistics synchronization message.
  */
 struct nss_ipv4_conn_sync_many_msg {
 	/*
@@ -662,13 +674,17 @@
 		struct nss_ipv4_mc_rule_create_msg mc_rule_create;
 				/**< Create a multicast rule. */
 		struct nss_ipv4_conn_sync_many_msg conn_stats_many;
-				/**< Synchronize connection statistics. */
+				/**< Synchronize multiple connection statistics. */
 		struct nss_ipv4_accel_mode_cfg_msg accel_mode_cfg;
-				/**< Acceleration ??accelerated? mode. */
-	} msg;			/**< Message payload. ??is this comment correct? I assumed it's the message payload because the first field is the message header */
+				/**< Acceleration mode. */
+	} msg;			/**< Message payload. */
 };
 
-extern int nss_ipv6_conn_cfg;	/**< ??description here. */
+/**
+ * Configured IPv6 connection number to use for calculating the total number of
+ * connections.
+ */
+extern int nss_ipv6_conn_cfg;
 
 #ifdef __KERNEL__ /* only kernel will use. */
 
@@ -701,8 +717,8 @@
  * nss_ctx_instance \n
  * nss_ipv4_msg
  *
- * @param[in,out] nss_ctx  Pointer to the NSS context.
- * @param[in]     msg      Pointer to the message data.
+ * @param[in] nss_ctx  Pointer to the NSS context.
+ * @param[in] msg      Pointer to the message data.
  *
  * @return
  * Status of the Tx operation.
@@ -717,9 +733,9 @@
  * nss_ctx_instance \n
  * nss_ipv4_msg
  *
- * @param[in,out] nss_ctx  Pointer to the NSS context.
- * @param[in]     msg      Pointer to the message data.
- * @param[in]     size     Actual size of this message.
+ * @param[in] nss_ctx  Pointer to the NSS context.
+ * @param[in] msg      Pointer to the message data.
+ * @param[in] size     Actual size of this message.
  *
  * @return
  * Status of the Tx operation.
@@ -728,7 +744,8 @@
 
 /**
  * nss_ipv4_notify_register
- *	Registers a notifier callback with the NSS for ??sending and receiving? IPv4 messages.
+ *	Registers a notifier callback to forward the IPv4 messages received from the NSS
+ *	firmware to the registered subsystem.
  *
  * @datatypes
  * nss_ipv4_msg_callback_t
@@ -782,7 +799,7 @@
 
 /**
  * nss_ipv4_get_mgr
- *	Gets the NSS context that is managing IPv4 ??IPv4 what?.
+ *	Gets the NSS context that is managing IPv4 processes.
  *
  * @return
  * Pointer to the NSS core context.
@@ -800,7 +817,7 @@
 
 /**
  * nss_ipv4_register_sysctl
- *	Registers the IPv4 system control ??.
+ *	Registers the IPv4 system control table.
  *
  * @return
  * None.
@@ -809,13 +826,13 @@
 
 /**
  * nss_ipv4_unregister_sysctl
- *	Deregisters the IPv4 system control ??.
+ *	Deregisters the IPv4 system control table.
  *
  * @return
  * None.
  *
  * @dependencies
- * The ?? must have been previously registered.
+ * The system control table must have been previously registered.
  */
 extern void nss_ipv4_unregister_sysctl(void);
 
@@ -857,7 +874,7 @@
 
 /**
  * nss_ipv4_log_tx_msg
- *	Sends an IPV4 logger message. ??correct?
+ *	Logs an IPv4 message that is sent to the NSS firmware.
  *
  * @datatypes
  * nss_ipv4_msg
@@ -871,7 +888,7 @@
 
 /**
  * nss_ipv4_log_rx_msg
- *	Receives an IPV4 logger message. ??correct?
+ *	Logs an IPv4 message that is received from the NSS firmware.
  *
  * @datatypes
  * nss_ipv4_msg
diff --git a/exports/nss_ipv6.h b/exports/nss_ipv6.h
index e373594..49aaf4f 100644
--- a/exports/nss_ipv6.h
+++ b/exports/nss_ipv6.h
@@ -30,11 +30,13 @@
 /**
  * nss_ipv6_message_types
  *	IPv6 bridge and routing rule message types.
+ *
+ * NSS_IPV6_RX_DEPRECATED0 is a deprecated type. It is kept for backward compatibility.
  */
 enum nss_ipv6_message_types {
 	NSS_IPV6_TX_CREATE_RULE_MSG,
 	NSS_IPV6_TX_DESTROY_RULE_MSG,
-	NSS_IPV6_RX_DEPRECATED0,		/**< Deprecated: NSS_IPV6_RX_ESTABLISH_RULE_MSG. ??what does this mean - customer is to use this msg? Or can we delete this comment?*/
+	NSS_IPV6_RX_DEPRECATED0,
 	NSS_IPV6_RX_CONN_STATS_SYNC_MSG,
 	NSS_IPV6_RX_NODE_STATS_SYNC_MSG,
 	NSS_IPV6_TX_CONN_CFG_RULE_MSG,
@@ -101,8 +103,8 @@
 		/**< Ingress PPPoE fields are valid. */
 
 /*
- * Multicast connection per-interface rule flags (to be used with rule_flags field of
- * nss_ipv4_mc_if_rule structure)
+ * Per-interface rule flags for a multicast connection (to be used with the rule_flags
+ * field of nss_ipv6_mc_if_rule structure).
  */
 #define NSS_IPV6_MC_RULE_CREATE_IF_FLAG_BRIDGE_FLOW 0x01
 		/**< Bridge flow. */
@@ -114,8 +116,8 @@
 		/**< Interface has left the flow. */
 
 /*
- * Multicast connection per-interface valid flags (to be used with valid_flags field of
- * nss_ipv6_mc_if_rule structure)
+ * Per-interface valid flags for a multicast connection (to be used with the valid_flags
+ * field of nss_ipv6_mc_if_rule structure).
  */
 #define NSS_IPV6_MC_RULE_CREATE_IF_FLAG_VLAN_VALID 0x01
 		/**< VLAN fields are valid. */
@@ -250,14 +252,22 @@
 
 /**
  * nss_ipv6_nexthop
- *	Information for next hop interface numbers.??new
+ *	Information for the next hop interface numbers.
  *
  * A next hop is the next interface that will receive the packet as opposed to
- * the final interface that the packet will go out on ??on what?).
+ * the final interface when the packet leaves the device.
  */
 struct nss_ipv6_nexthop {
-	int32_t flow_nexthop;		/**< Flow next hop interface number. ??doesn't make sense */
-	int32_t return_nexthop;		/**< Return next hop interface number. ??does this mean the next number is being returned? */
+	/**
+	 * Next hop interface number of the flow direction (from which the connection
+	 * originated).
+	 */
+	int32_t flow_nexthop;
+	/**
+	 * Next hop interface number of the return direction (to which the connection
+	 * is destined).
+	 */
+	int32_t return_nexthop;
 };
 
 /**
@@ -282,7 +292,7 @@
 	uint8_t return_window_scale;
 			/**< Window scaling factor for the return direction. */
 	uint16_t reserved;
-			/**< Alignment padding. ??is this comment correct?  */
+			/**< Alignment padding. */
 };
 
 /**
@@ -384,7 +394,7 @@
 	/*
 	 * Response
 	 */
-	uint32_t reserved;	/**< Reserved for what??. */
+	uint32_t reserved;	/**< Reserved field for a response message. */
 };
 
 /**
@@ -407,12 +417,12 @@
 	uint32_t if_num;		/**< Interface number. */
 	uint32_t if_mtu;		/**< MTU of the interface. */
 	uint16_t if_mac[3];		/**< Interface MAC address. */
-	uint8_t reserved[2];		/**< Reserved for ?? bytes. */
+	uint8_t reserved[2];		/**< Reserved 2 bytes for alignment. */
 };
 
 /**
  * nss_ipv6_mc_rule_create_msg
- *	IPv4 multicast rule for creating sub-messages.
+ *	IPv6 multicast rule for creating sub-messages.
  */
 struct nss_ipv6_mc_rule_create_msg {
 	struct nss_ipv6_5tuple tuple;	/**< Holds values of the 5 tuple. */
@@ -429,7 +439,7 @@
 	uint16_t dest_mac[3];		/**< Destination multicast MAC address. */
 	uint16_t if_count;		/**< Number of destination interfaces. */
 	uint8_t egress_dscp;		/**< Egress DSCP value for the flow. */
-	uint8_t reserved[3];		/**< Reserved for ?? bytes. */
+	uint8_t reserved[3];		/**< Reserved 3 bytes for alignment. */
 
 	struct nss_ipv6_mc_if_rule if_rule[NSS_MC_IF_MAX];
 			/**< Per-interface information. */
@@ -470,10 +480,10 @@
 
 /**
  * nss_ipv6_conn_sync
- *	IPv6 rule synchronized connections. ??is this comment correct>
+ *	IPv6 connection synchronization message.
  */
 struct nss_ipv6_conn_sync {
-	uint32_t reserved;		/**< Alignment padding. ??is this comment correct?  */
+	uint32_t reserved;		/**< Reserved field for backward compatibility. */
 	uint8_t protocol;		/**< Protocol number. */
 	uint32_t flow_ip[4];		/**< Flow IP address. */
 	uint32_t flow_ident;		/**< Flow identifier (e.g., port). */
@@ -530,7 +540,7 @@
 
 /**
  * nss_ipv6_conn_sync_many_msg
- *	Message information for synchronized IPv6 statistics for many messages. ??is this comment correct
+ *	Information for a multiple IPv6 connection statistics synchronization message.
  */
 struct nss_ipv6_conn_sync_many_msg {
 	/* Request. */
@@ -629,13 +639,17 @@
 		struct nss_ipv6_mc_rule_create_msg mc_rule_create;
 				/**< Create a multicast rule. */
 		struct nss_ipv6_conn_sync_many_msg conn_stats_many;
-				/**< Synchronize many statistics ??synchronize many times?. */
+				/**< Synchronize multiple connection statistics. */
 		struct nss_ipv6_accel_mode_cfg_msg accel_mode_cfg;
 				/**< Configure acceleration mode. */
-	} msg;			/**< Message payload. ??is this comment correct? I assumed it's the message payload because the first field is the message header */
+	} msg;			/**< Message payload. */
 };
 
-extern int nss_ipv4_conn_cfg; /**< ??description here */
+/**
+ * Configured IPv4 connection number to use for calculating the total number of
+ * connections.
+ */
+extern int nss_ipv4_conn_cfg;
 
 #ifdef __KERNEL__
 
@@ -668,8 +682,8 @@
  * nss_ctx_instance \n
  * nss_ipv6_msg
  *
- * @param[in,out] nss_ctx  Pointer to the NSS context.
- * @param[in]     msg      Pointer to the message data.
+ * @param[in] nss_ctx  Pointer to the NSS context.
+ * @param[in] msg      Pointer to the message data.
  *
  * @return
  * Status of the Tx operation.
@@ -684,9 +698,9 @@
  * nss_ctx_instance \n
  * nss_ipv6_msg
  *
- * @param[in,out] nss_ctx  Pointer to the NSS context.
- * @param[in]     msg      Pointer to the message data.
- * @param[in]     size     Actual size of this message.
+ * @param[in] nss_ctx  Pointer to the NSS context.
+ * @param[in] msg      Pointer to the message data.
+ * @param[in] size     Actual size of this message.
  *
  * @return
  * Status of the Tx operation.
@@ -695,7 +709,8 @@
 
 /**
  * nss_ipv6_notify_register
- *	Registers a notifier callback with the NSS for ??sending and receiving? IPv6 messages.
+ *	Registers a notifier callback to forward the IPv6 messages received from the NSS
+ *	firmware to the registered subsystem.
  *
  * @datatypes
  * nss_ipv6_msg_callback_t
@@ -749,7 +764,7 @@
 
 /**
  * nss_ipv6_get_mgr
- *	Gets the NSS context that is managing the IPv6 instance.
+ *	Gets the NSS context that is managing the IPv6 processes.
  *
  * @return
  * Pointer to the NSS core context.
@@ -767,7 +782,7 @@
 
 /**
  * nss_ipv6_register_sysctl
- *	Registers the IPv6 system control.
+ *	Registers the IPv6 system control table.
  *
  * @return
  * None.
@@ -776,13 +791,13 @@
 
 /**
  * nss_ipv6_unregister_sysctl
- *	Deregisters the IPv6 system control.
+ *	Deregisters the IPv6 system control table.
  *
  * @return
  * None.
  *
  * @dependencies
- * The ?? must have been previously registered.
+ * The system control table must have been previously registered.
  */
 extern void nss_ipv6_unregister_sysctl(void);
 
@@ -824,7 +839,7 @@
 
 /**
  * nss_ipv6_log_tx_msg
- *	Sends an IPV6 logger message.
+ *	Logs an IPv6 message that is sent to the NSS firmware.
  *
  * @datatypes
  * nss_ipv6_msg
@@ -838,7 +853,7 @@
 
 /**
  * nss_ipv6_log_rx_msg
- *	Receives an IPV6 logger message.
+ *	Logs an IPv6 message that is received from the NSS firmware.
  *
  * @datatypes
  * nss_ipv6_msg
diff --git a/exports/nss_oam.h b/exports/nss_oam.h
index 3c9fabf..292d8be 100644
--- a/exports/nss_oam.h
+++ b/exports/nss_oam.h
@@ -17,11 +17,6 @@
 /*
  * @file nss_oam.h
  *	NSS OAM - Operations, Administration and Maintenance Service
- *
- * @brief This adapter module is responsible for sending and
- * receiving to and from NSS FW.
- *
- * This file contains NSS to HLOS interface and msg definitions.
  */
 
 #ifndef __NSS_OAM_H
@@ -62,18 +57,12 @@
  *	OAM firmware version.
  */
 struct nss_oam_fw_ver {
-	uint8_t string[NSS_OAM_FW_VERSION_LEN];	/**< Null-terminated string. ??is this enough info for customers?*/
+	uint8_t string[NSS_OAM_FW_VERSION_LEN];	/**< OAM firmware version. */
 };
 
 /**
  * nss_oam_msg
  *	Data for sending and receiving OAM messages.
- *
- * This common structure is shared between the netlink and driver for
- * commands and messages sent between the NSS and HLOS.
- * Commands are sent by the HLOS to the NSS (set and get requests). Messages are
- * sent by the NSS to the HLOS (response to a get or set command, or a
- * notification). ??should this paragraph be in all the headers for a common payload struct?
  */
 struct nss_oam_msg {
 	struct nss_cmn_msg cm;	/**< Common message header. */
@@ -84,7 +73,7 @@
 	union {
 		struct nss_oam_fw_ver fw_ver;
 				/**< Firmware version. */
-	} msg;			/**< Message payload. ??is this comment correct? I assumed it's the message payload because the first field is the message header */
+	} msg;			/**< Message payload. */
 };
 
 /**
@@ -106,8 +95,8 @@
  * nss_ctx_instance \n
  * nss_oam_msg
  *
- * @param[in,out] nss_ctx  Pointer to the NSS context.
- * @param[in]     msg      Pointer to the message data.
+ * @param[in] nss_ctx  Pointer to the NSS context.
+ * @param[in] msg      Pointer to the message data.
  *
  * @return
  * Status of the Tx operation
@@ -142,7 +131,7 @@
  * nss_register_oam_if
  *	Registers the OAM interface handler with the NSS.
  *
- * @param[in] if_number  ID of the OAM interface. ??is this comment correct?
+ * @param[in] if_number  Interface number of the OAM interface.
  *
  * @return
  * Boolean status of handler registration
diff --git a/exports/nss_pppoe.h b/exports/nss_pppoe.h
index ab716ca..d57cb85 100644
--- a/exports/nss_pppoe.h
+++ b/exports/nss_pppoe.h
@@ -30,12 +30,13 @@
 /**
  * nss_pppoe_metadata_types
  *	Message types for PPPoE requests and responses.
+ *
+ * NSS_PPPOE_RX_DEPRECATED0 and NSS_PPPOE_RX_DEPRECATED1 are deprecated types.
+ * They are kept for backward compatibility.
  */
 enum nss_pppoe_metadata_types {
 	NSS_PPPOE_RX_DEPRECATED0,
-		/**< Deprecated: NSS_PPPOE_TX_CONN_RULE_DESTROY. ??what does this comment mean, to use this command instead? Or can we delete this comment?*/
 	NSS_PPPOE_RX_DEPRECATED1,
-		/**< Deprecated: NSS_PPPOE_TX_CONN_RULE_SUCCESS. ??what does this comment mean, to use this command instead? Or can we delete this comment?*/
 	NSS_PPPOE_RX_CONN_STATS_SYNC,
 	NSS_PPPOE_RX_NODE_STATS_SYNC,
 	NSS_PPPOE_RX_SESSION_RESET,
@@ -57,20 +58,18 @@
 
 /**
  * nss_pppoe_node_stats_sync_msg
- *	PPPoE node statistics.
- 
- ??note for the rest of this file - comments must be meaningful, not just repeating the code name.
+ *	PPPoE node synchronization statistics.
  */
 struct nss_pppoe_node_stats_sync_msg {
 	struct nss_cmn_node_stats node_stats;	/**< Common node statistics. */
 	uint32_t pppoe_session_create_requests;
-			/**< PPPoE session create requests.??need more info */
+			/**< Number of PPPoE session create requests. */
 	uint32_t pppoe_session_create_failures;
-			/**< PPPoE session create failures. ??need more info */
+			/**< Number of PPPoE session create failures. */
 	uint32_t pppoe_session_destroy_requests;
-			/**< PPPoE session destroy requests.??need more info */
+			/**< Number of PPPoE session destroy requests. */
 	uint32_t pppoe_session_destroy_misses;
-			/**< PPPoE session destroy misses.??need more info */
+			/**< Number of PPPoE session destroy misses. */
 };
 
 /**
@@ -78,8 +77,8 @@
  *	Reset message information for a PPPoE session.
  */
 struct nss_pppoe_session_reset_msg {
-	uint32_t interface;		/**< ??NSS or PPPoE? interface number?. */
-	uint32_t session_index;		/**< Index of the PPPoE session??. */
+	uint32_t interface;	/**< NSS interface number. */
+	uint32_t session_index;	/**< Index of the session in the NSS PPPoE session array. */
 };
 
 /**
@@ -116,19 +115,19 @@
 				/**< Synchronized statistics for a node. */
 		struct nss_pppoe_session_reset_msg pppoe_session_reset;
 				/**< Reset a session. */
-	} msg;			/**< Message payload. ??is this comment correct? I assumed it's the message payload because the first field is the message header */
+	} msg;			/**< Message payload. */
 };
 
 /**
  * nss_pppoe_tx
- *	Sends a PPPoE message. ??to what?
+ *	Sends a PPPoE message to the NSS firmware.
  *
  * @datatypes
  * nss_ctx_instance \n
  * nss_pppoe_msg
  *
- * @param[in,out] nss_ctx  Pointer to the NSS context.
- * @param[in]     msg      Pointer to the message data.
+ * @param[in] nss_ctx  Pointer to the NSS context.
+ * @param[in] msg      Pointer to the message data.
  *
  * @return
  * Status of the Tx operation.
diff --git a/exports/nss_profiler.h b/exports/nss_profiler.h
index c33878c..8e83586 100644
--- a/exports/nss_profiler.h
+++ b/exports/nss_profiler.h
@@ -1,6 +1,6 @@
 /*
  **************************************************************************
- * Copyright (c) 2014, 2015, 2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2015, 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.
@@ -51,8 +51,8 @@
  *
  * Do not alter this enumeration. However, adding more types is allowed.
  */
-enum nss_profiler_message_types {/* ??shouldn't the following code be SAMPLING and not SIMPLING?*/
-	NSS_PROFILER_CHANGE_SIMPLING_RATE_MSG,	/**< Host-to-NSS: ask to do a rate change. */
+enum nss_profiler_message_types {
+	NSS_PROFILER_CHANGE_SAMPLING_RATE_MSG,	/**< Host-to-NSS: ask to do a rate change. */
 	NSS_PROFILER_START_MSG,			/**< Host-to-NSS: start the NSS Profiler. */
 	NSS_PROFILER_STOP_MSG,			/**< Host-to-NSS: stop the NSS Profiler. */
 	NSS_PROFILER_FLOWCTRL_MSG,		/**< Host-to-NSS: do flow control on sampling. */
@@ -90,15 +90,15 @@
 	uint32_t hd_magic;		/**< Common overlay in all headers. */
 	uint32_t num_counters;
 			/**< Number of registered performance (application) counters. */
-	uint32_t ocm_size;		/**< Size of the ??ocm?. */
-	uint32_t sram_start;		/**< ??Description here. */
+	uint32_t ocm_size;		/**< Size of the on-chip-memory. */
+	uint32_t sram_start;		/**< DDR starting address. */
 	uint32_t rate;			/**< Sampling rate. */
 	uint32_t cpu_id;		/**< ID of the chip register. */
 	uint32_t cpu_freq;		/**< Chip clock frequency. */
 	uint32_t ddr_freq;		/**< DDR memory speed. */
 
 	struct nss_profile_counter counters[PROFILE_MAX_APP_COUNTERS];
-			/**< Number of profile counters ??. */
+			/**< Application profiling counters. */
 };
 
 /**
@@ -129,30 +129,29 @@
 	/**
 	 * Payload of a Profiler message.
 	 */
-	union {
+	union npm_body {
 		struct nss_profiler_cmd_param pcmdp;	/**< Command parameters. */
 		struct nss_profiler_debug_msg pdm;	/**< Debug packet. */
 		struct nss_profiler_data_msg msg;	/**< Sampling data. */
-	} payload;	/**< Message payload. The data length is in cm ??centimeters?. ??is this comment correct? I assumed it's the message payload because the first field is the message header. And do we need the info about data length? none of the other payloads (in other headers) have it. */
+	} payload;	/**< Message payload. The data length is set in common message header. */
 };
 
 /**
  * Callback function for receiving Profiler messages.
  *
- * ??the following statement doesn't look like it belongs in this typedef; there is no ncm param. Please verify.
- Memory pointed by buf (ncm) is owned by caller (i.e. NSS driver)
+ * @note: Memory (buffer) pointed by npm is owned by caller, that is, NSS driver.
  *
  * @datatypes
  * nss_profiler_msg
  *
- * @param[in] ctx  Pointer to the context of the Profiler.
+ * @param[in] ctx  Pointer to the context of the NSS process (core).
  * @param[in] npm  Pointer to the NSS Profiler message.
  */
 typedef void (*nss_profiler_callback_t)(void *ctx, struct nss_profiler_msg *npm);
 
 /**
  * nss_profiler_notify_register
- *	Registers the Profiler interface ??with the NSS? for sending and receiving messages.
+ *	Registers the Profiler interface with the NSS driver for sending and receiving messages.
  *
  * This function must be called once for each core.
  *
@@ -162,7 +161,7 @@
  *
  * @param[in] profiler_callback  Callback for the data.
  * @param[in] core_id            NSS core ID.
- * @param[in] ctx                Pointer to the context of the Profiler. The context is
+ * @param[in] ctx                Pointer to the context of the NSS core. The context is
                                  provided to caller in the registered callback function.
  *
  * @return
@@ -175,7 +174,7 @@
 
 /**
  * nss_profiler_notify_unregister
- *	Deregisters the Profiler interface ??from the NSS?.
+ *	Deregisters the Profiler interface from the NSS driver.
  *
  * @datatypes
  * nss_core_id_t
@@ -192,13 +191,13 @@
 
 /**
  * nss_profiler_if_tx_buf
- *	Sends a Profiler command to the NSS.
+ *	Sends a Profiler command to the NSS firmware.
  *
- * @param[in,out] nss_ctx   Pointer to the NSS context.
- * @param[in]     buf       Buffer to send to NSS
- * @param[in]     len       Length of the buffer.
- * @param[in]     cb        Pointer to the message callback.
- * @param[in]     app_data  Pointer to the application context of the message.
+ * @param[in] nss_ctx   Pointer to the NSS context.
+ * @param[in] buf       Buffer to send to NSS firmware.
+ * @param[in] len       Length of the buffer.
+ * @param[in] cb        Pointer to the message callback.
+ * @param[in] app_data  Pointer to the application context of the message.
  *
  * @return
  * Status of the Tx operation.
@@ -211,29 +210,16 @@
 		void *buf, uint32_t len, void *cb, void *app_data);
 
 /**
- * profile_handle_constant_info
- *	Handles NSS changed control information change ??this comment needs clarification - does the NSS change the info?
- *
- * @datatypes
- * nss_profiler_msg
- *
- * @param[in] arg  Pointer to the application data.
- * @param[in] npm  Pointer to the NSS Profiler message.
- *
- * @return
- * None.
- */
-extern void profile_handle_constant_info(void *arg, struct nss_profiler_msg *npm);
-
-/**
  * profile_register_performance_counter
- *	Registers a Linux counter ??with the NSS? for any variables.
+ *	Registers a Linux counter with the profiler for any variables.
  *
- * @param[in] counter  Pointer to the variable address.
- * @param[in] name     Pointer to the variable name (meaningful for read, and 23 bytes or less). ??not sure how to edit this - is the name 23 bytes/less? what does "meaningful for read" mean?
+ * @param[in] counter	Pointer to the variable address.
+ * @param[in] name	Pointer to the variable name: if name is longer than
+			23 characters, then only the first 23 bytes are used.
  *
  * @return
- * None.
+ * 0	if counter array is full -- too many registered counters.
+ * 1	on success
  */
 extern int profile_register_performance_counter(volatile unsigned int *counter, char *name);
 
@@ -255,8 +241,9 @@
  * @return
  * None.
  */
-extern void nss_profiler_msg_init(struct nss_profiler_msg *npm, uint16_t if_num, uint32_t type, uint32_t len,
-					nss_profiler_callback_t cb, void *app_data);
+extern void nss_profiler_msg_init(struct nss_profiler_msg *npm, uint16_t if_num,
+				uint32_t type, uint32_t len,
+				nss_profiler_callback_t cb, void *app_data);
 
 /**
  * @}
diff --git a/exports/nss_shaper.h b/exports/nss_shaper.h
index 9f5edbe..51996cd 100644
--- a/exports/nss_shaper.h
+++ b/exports/nss_shaper.h
@@ -177,7 +177,7 @@
 
 /**
  * nss_shaper_config_alloc_shaper_node
- *	Used when allocating a shaper node in the NSS interface.
+ *	Message information for allocating a shaper node for a NSS interface.
  */
 struct nss_shaper_config_alloc_shaper_node {
 	nss_shaper_node_type_t node_type;	/**< Type of shaper node. */
@@ -186,7 +186,7 @@
 
 /**
  * nss_shaper_config_free_shaper_node
- *	Used when freeing a shaper node from the NSS interface.
+ *	Message information for freeing a shaper node from a NSS interface.
  */
 struct nss_shaper_config_free_shaper_node {
 	uint32_t qos_tag;	/**< QoS tag of the node. */
@@ -194,7 +194,7 @@
 
 /**
  * nss_shaper_config_set_root_node
- *	Used when setting a shaper node as the root shaper node.
+ *	Message information for setting a shaper node as the root.
  */
 struct nss_shaper_config_set_root_node {
 	uint32_t qos_tag;	/**< QoS tag of the node. */
@@ -202,7 +202,7 @@
 
 /**
  * nss_shaper_config_set_default_node
- *	Used when setting a shaper node as the default node for a queue.
+ *	Message information for setting a shaper node as the default node for enqueueing.
  */
 struct nss_shaper_config_set_default_node {
 	uint32_t qos_tag;	/**< QoS tag of the node. */
@@ -210,43 +210,43 @@
 
 /**
  * nss_shaper_config_set_hybrid_mode
- *	Used when setting a shaper to operate in Hybrid mode.
+ *	Message information for setting a shaper to operate in hybrid mode.
  */
 struct nss_shaper_config_set_hybrid_mode {
-	uint32_t offset;	/**< Offset for packets to be queued in the hardware. ??is this comment correct?*/
+	uint32_t offset;	/**< Queue offset for packets sent to the hardware. */
 };
 
 /**
  * nss_shaper_config_prio_attach
- *	Used when setting the priority of a child shaper node. ??is this comment correct?
+ *	Message information for attaching a shaper node to a PRIO shaper node.
  */
 struct nss_shaper_config_prio_attach {
 	uint32_t child_qos_tag;	/**< QoS tag of the child shaper node. */
-	uint32_t priority;	/**< Priority of the child. */
+	uint32_t priority;	/**< Priority of the child shaper node. */
 };
 
 /**
  * nss_shaper_config_prio_detach
- *	Used when detaching a specified priority from a child shaper node. ??is this comment correct?
+ *	Message information for detaching a shaper node from a PRIO shaper node.
  */
 struct nss_shaper_config_prio_detach {
-	uint32_t priority;	/**< Priority of the child. */
+	uint32_t priority;	/**< Priority of the child shaper node. */
 };
 
 /**
  * nss_shaper_config_codel_alg_param
- *	CoDel algorithm configuration parameters.
+ *	Message information for configuring a CoDel algorithm.
  */
 struct nss_shaper_config_codel_alg_param {
 	uint16_t interval;	/**< Buffer time to smooth a state transition. */
 	uint16_t target;	/**< Acceptable delay associated with a queue. */
 	uint16_t mtu;		/**< MTU for the associated interface. */
-	uint16_t reserved;	/**< Alignment padding. ??is this comment correct?  */
+	uint16_t reserved;	/**< Alignment padding. */
 };
 
 /**
  * nss_shaper_config_codel_param
- *	Parameters used when configuring a CoDel shaper node.
+ *	Message information for configuring a CoDel shaper node.
  */
 struct nss_shaper_config_codel_param {
 	int32_t qlen_max;
@@ -257,25 +257,25 @@
 
 /**
  * nss_shaper_config_rate_param
- *	Parameters related to the rate limiter algorithm.
+ *	Message information for configuring the rate limiter algorithm.
  */
 struct nss_shaper_config_rate_param {
 	uint32_t rate;
 			/**< Allowed traffic rate measured in bytes per second. */
 	uint32_t burst;
-			/**< Maximum bytes that can be sent before the next token update. */
+			/**< Maximum bytes that can be sent in a burst. */
 	uint32_t max_size;
 			/**< Maximum size of the supported packets (in bytes). */
 
 	/**
-	 * Specifies whether the limiter will stop limiting the sending rate.
+	 * Specifies whether the rate limiter will be bypassed (short circuited).
 	 */
 	bool short_circuit;
 };
 
 /**
  * nss_shaper_configure_tbl_attach
- *	Used when attaching a shaper node to a configuration table. ??is this comment correct?
+ *	Message information for attaching a shaper node to a TBL shaper node.
  */
 struct nss_shaper_config_tbl_attach {
 	uint32_t child_qos_tag;	/**< QoS tag of the child shaper node. */
@@ -283,18 +283,18 @@
 
 /**
  * nss_shaper_configure_tbl_param
- *	Parameter configuration table. ??is this comment correct?
+ *	Message information for detaching a shaper node from a TBL shaper node.
  */
 struct nss_shaper_config_tbl_param {
 	struct nss_shaper_config_rate_param lap_cir;
-		/**< Configuration of the LAP committed information rate. ??what is LAP?*/
+		/**< Configuration parameters for the committed information rate. */
 	struct nss_shaper_config_rate_param lap_pir;
-		/**< Configuration of the LAP ??what is pir? p__ information rate. */
+		/**< Configuration parameters for the peak information rate. */
 };
 
 /**
  * nss_shaper_config_bf_attach
- *	Used when attaching a shaper node to a BF shaper node. ??what is BF?
+ *	Message information for attaching a shaper node to a BF shaper node.
  */
 struct nss_shaper_config_bf_attach {
 	uint32_t child_qos_tag;	/**< QoS tag of the child shaper node. */
@@ -302,7 +302,7 @@
 
 /**
  * nss_shaper_config_bf_detach
- *	Used when detaching a child shaper node from a bf shaper node.
+ *	Message information for detaching a shaper node from a BF shaper node.
  */
 struct nss_shaper_config_bf_detach {
 	uint32_t child_qos_tag;	/**< QoS tag of the child shaper node. */
@@ -310,7 +310,7 @@
 
 /**
  * nss_shaper_config_bf_group_attach
- *	Used when attaching a shaper node to a bf group shaper.
+ *	Message information for attaching a shaper node to a BF group shaper node.
  */
 struct nss_shaper_config_bf_group_attach {
 	uint32_t child_qos_tag;	/**< QoS tag of the child shaper node. */
@@ -318,7 +318,7 @@
 
 /**
  * nss_shaper_config_bf_group_param
- *	Configuration parameters for a BF group shaper node. ??is this comment correct?
+ *	Configuration parameters for a BF group shaper node.
  */
 struct nss_shaper_config_bf_group_param {
 	uint32_t quantum;
@@ -342,7 +342,7 @@
 
 /**
  * nss_shaper_config_fifo_param
- *	FIFO configuration parameters.
+ *	Message information for configuring a FIFO shaper node.
  */
 struct nss_shaper_config_fifo_param {
 	uint32_t limit;		/**< Queue limit in packets. */
@@ -364,7 +364,7 @@
 
 /**
  * nss_shaper_red_alg_param
- *	RED algorithm parameters. ??what is RED?
+ *	Message information for configuring the RED algorithm.
  */
 struct nss_shaper_red_alg_param {
 	uint32_t min;			/**< Minimum size of the queue. */
@@ -375,30 +375,32 @@
 	 */
 	uint32_t probability;
 
+	/**
+	 * Exponential weight factor to calculate the average queue size.
+	 */
 	uint32_t exp_weight_factor;
-			/**< Exp??exponential? weight factor to calculate the average queue size. */
 };
 
 /**
  * nss_shaper_config_wred_param
- *	WRED configuration parameters. ??what is WRED?
+ *	Message information for configuring the WRED algorithm.
  */
 struct nss_shaper_config_wred_param {
-	uint32_t limit;			/**< Queue limit. ??need more info */
+	uint32_t limit;			/**< Queue limit in bytes. */
 	nss_shaper_config_wred_weight_mode_t weight_mode;
-					/**< Weight mode. ??need more info */
-	uint32_t traffic_classes;	/**< How many traffic classes: DPs. ??needs clarification */
-	uint32_t def_traffic_class;	/**< Default traffic if no match: def_DP. ??needs clarification */
-	uint32_t traffic_id;		/**< Traffic ID to configure: DP. ??needs clarification */
-	uint32_t weight_mode_value;	/**< Weight mode value. ??need more info */
+					/**< WRED weight mode. */
+	uint32_t traffic_classes;	/**< Number of traffic classes (drop probability). */
+	uint32_t def_traffic_class;	/**< Default traffic class used when there is no match. */
+	uint32_t traffic_id;		/**< Traffic class to configure. */
+	uint32_t weight_mode_value;	/**< Value to match the selected header field against. */
 	struct nss_shaper_red_alg_param rap;
-					/**< RED algorithm parameter. ??need more info */
+					/**< Configuration parameters for the RED algorithm. */
 	uint8_t ecn;			/**< Mark an ECN bit or drop packet. */
 };
 
 /**
  * nss_shaper_config_wrr_attach
- *	Used when attaching a shaper node to a Weighted Round Robin (WRR) shaper node.
+ *	Message information for attaching a shaper node to a WRR shaper node.
  */
 struct nss_shaper_config_wrr_attach {
 	uint32_t child_qos_tag;	/**< QoS tag of the child shaper node. */
@@ -406,7 +408,7 @@
 
 /**
  * nss_shaper_config_wrr_detach
- *	Used when detaching a child node from a WRR shaper node.
+ *	Message information for detaching a child node from a WRR shaper node.
  */
 struct nss_shaper_config_wrr_detach {
 	uint32_t child_qos_tag;	/**< QoS tag of the child shaper node. */
@@ -414,7 +416,7 @@
 
 /**
  * nss_shaper_config_wrr_group_attach
- *	Used when attaching a shaper node to a WRR group shaper.
+ *	Message information for attaching a shaper node to a WRR group.
  */
 struct nss_shaper_config_wrr_group_attach {
 	uint32_t child_qos_tag;	/**< QoS tag of the child shaper node. */
@@ -432,7 +434,7 @@
 
 /**
  * nss_shaper_config_wrr_param
- *	Used when configuring a WRR shaper to operate in a specified mode.
+ *	Message information for configuring the operation mode of a WRR shaper node.
  */
 struct nss_shaper_config_wrr_param {
 	uint32_t operation_mode;	/**< Mode in which to operate. */
@@ -440,7 +442,7 @@
 
 /**
  * nss_shaper_config_wrr_group_param
- *	Used when configuring a WRR group shaper node with a specified quantum value.
+ *	Message information for configuring a quantum value of a WRR group shaper node.
  */
 struct nss_shaper_config_wrr_group_param {
 	uint32_t quantum;	/**< Smallest increment value for the DRRs. */
@@ -448,8 +450,7 @@
 
 /**
  * nss_shaper_config_htb_attach
- *	Used when attaching a shaper node to a hierarchical token bucket (HTB) shaper
- *	node.
+ *	Message information for attaching a shaper node to an HTB shaper node.
  */
 struct nss_shaper_config_htb_attach {
 	uint32_t child_qos_tag;	/**< QoS tag of the child shaper node. */
@@ -457,7 +458,7 @@
 
 /**
  * nss_shaper_config_htb_group_attach
- *	Used when attaching a shaper node to an HTB group shaper.
+ *	Message information for attaching a shaper node to an HTB group.
  */
 struct nss_shaper_config_htb_group_attach {
 	uint32_t child_qos_tag;	/**< QoS tag of the child shaper node. */
@@ -465,7 +466,7 @@
 
 /**
  * nss_shaper_config_htb_group_detach
- *	Used when detaching a shaper node to an HTB group shaper.
+ *	Message information for detaching a shaper node from an HTB group.
  */
 struct nss_shaper_config_htb_group_detach {
 	uint32_t child_qos_tag;	/**< QoS tag of the child shaper node. */
@@ -473,21 +474,21 @@
 
 /**
  * nss_shaper_config_htb_group_param
- *	Configuration parameters for an HTB group shaper node.
+ *	Message information for configuring an HTB group shaper node.
  */
 struct nss_shaper_config_htb_group_param {
 	uint32_t quantum;	/**< Smallest increment value for the DRRs. */
 	uint32_t priority;	/**< Value of the priority for this group. */
 	uint32_t overhead;	/**< Overhead in bytes to be added per packet. */
 	struct nss_shaper_config_rate_param rate_police;
-		/**< Configuration parameters for the police rate. */
+		/**< Configuration parameters for the policing rate. */
 	struct nss_shaper_config_rate_param rate_ceil;
-		/**< Configuration parameters for the ceiling rate. ??does ceil mean ceiling?*/
+		/**< Configuration parameters for the ceiling rate. */
 };
 
 /**
  * nss_shaper_config_ppe_sn_attach
- *	Used when attaching a shaper node to a PPE ??what is PPE?.
+ *	Message information for attaching a shaper node to a PPE shaper node.
  */
 struct nss_shaper_config_ppe_sn_attach {
 	uint32_t child_qos_tag;	/**< QoS tag of the child shaper node. */
@@ -495,7 +496,7 @@
 
 /**
  * nss_shaper_config_ppe_sn_detach
- *	Used when detaching a child shaper node from a PPE.
+ *	Message information for detaching a shaper node from a PPE shaper node.
  */
 struct nss_shaper_config_ppe_sn_detach {
 	uint32_t child_qos_tag;	/**< QoS tag of the child shaper node. */
@@ -523,15 +524,15 @@
 
 /**
  * nss_shaper_config_ppe_sn_param
- *	Configuration parameters for a PPE SN group shaper node. ??is this comment correct? what is SN?
+ *	Message information for configuring a PPE shaper node.
  */
 struct nss_shaper_config_ppe_sn_param {
 	enum nss_shaper_config_ppe_sn_type type;
-					/**< Type of PPE shaper node. */
-	uint16_t base;			/**< Resource ID of the base hardware. */
-	uint16_t offset;		/**< Offset from the base resource ID. */
-	uint8_t port;			/**< PPE port on which this group is configured. ??does "this" refer to the group, if the description on line 526 is correct?? */
-	uint8_t reserved[3];		/**< Reserved ??for ?-byte alignment padding?. */
+				/**< Type of PPE shaper node. */
+	uint16_t base;		/**< Resource ID of the base hardware. */
+	uint16_t offset;	/**< Offset from the base resource ID. */
+	uint8_t port;		/**< PPE port on which this shaper node is configured. */
+	uint8_t reserved[3];	/**< Reserved for padding. */
 };
 
 /*
@@ -542,60 +543,60 @@
 	uint32_t qos_tag;	/**< ID of the shaper node to be configured. */
 
 	/**
-	 * Configuration messages for all types of shaper nodes. ??I added comments below; are they correct?
+	 * Configuration messages for all types of shaper nodes.
 	 */
 	union {
 		struct nss_shaper_config_prio_attach prio_attach;
-			/**< Priority setting for attaching a shaper node. */
+			/**< Attach a shaper node to a PRIO shaper node. */
 		struct nss_shaper_config_prio_detach prio_detach;
-			/**< Priority setting for detaching a shaper node. */
+			/**< Detach a shaper node from a PRIO shaper node. */
 
 		struct nss_shaper_config_codel_param codel_param;
 			/**< Configure a CoDel shaper node. */
 
 		struct nss_shaper_config_tbl_attach tbl_attach;
-			/**< Attach a shaper node to a configuration table. */
+			/**< Attach a shaper node to a TBL shaper node. */
 		struct nss_shaper_config_tbl_param tbl_param;
-			/**< Parameter configuration table. */
+			/**< Configuration parameters for a TBL shaper node. */
 
 		struct nss_shaper_config_bf_attach bf_attach;
 			/**< Attach a shaper node to a BF shaper node. */
 		struct nss_shaper_config_bf_detach bf_detach;
-			/**< Detach a child shaper node from a BF shaper nod. */
+			/**< Detach a child shaper node from BF shaper node. */
 		struct nss_shaper_config_bf_group_attach bf_group_attach;
-			/**< Attach a shaper node to a BF group shaper. */
+			/**< Attach a shaper node to a BF group shaper node. */
 		struct nss_shaper_config_bf_group_param bf_group_param;
 			/**< Configure parameters for a BF group shaper node. */
 
 		struct nss_shaper_config_fifo_param fifo_param;
-			/**< IFO configuration parameters. */
+			/**< Configure a FIFO shaper node. */
 
 		struct nss_shaper_config_wrr_attach wrr_attach;
 			/**< Attach a shaper node to a WRR shaper node. */
 		struct nss_shaper_config_wrr_detach wrr_detach;
-			/**< Attach a shaper node from a WRR shaper node. */
+			/**< Detach a shaper node from a WRR shaper node. */
 		struct nss_shaper_config_wrr_param wrr_param;
-			/**< WRR configure parameters . */
+			/**< Configuration parameters for a WRR shaper node . */
 		struct nss_shaper_config_wrr_group_attach wrr_group_attach;
-			/**< Attach a shaper node to a WRR group shaper. */
+			/**< Attach a shaper node to a WRR group shaper node. */
 		struct nss_shaper_config_wrr_group_param wrr_group_param;
 			/**< Configure a WRR group shaper node with a quantum value. */
 		struct nss_shaper_config_htb_attach htb_attach;
 			/**< Attach a shaper node to an HTB shaper node. */
 		struct nss_shaper_config_htb_group_attach htb_group_attach;
-			/**< Attach a shaper node to an HTB group shaper. */
+			/**< Attach a shaper node to an HTB group shaper node. */
 		struct nss_shaper_config_htb_group_detach htb_group_detach;
-			/**< Detach a shaper node to an HTB group shaper. */
+			/**< Detach a shaper node from an HTB group shaper node. */
 		struct nss_shaper_config_htb_group_param htb_group_param;
 			/**< Configuration parameters for an HTB group shaper node. */
 		struct nss_shaper_config_wred_param wred_param;
-			/**< WRED configuration parameters. */
+			/**< Configuration parameters for a WRED shaper node. */
 		struct nss_shaper_config_ppe_sn_attach ppe_sn_attach;
-			/**< Attach a shaper node to a PPE SN. */
+			/**< Attach a shaper node to a PPE shaper node. */
 		struct nss_shaper_config_ppe_sn_detach ppe_sn_detach;
-			/**< Detach a shaper node from a PPE SN. */
+			/**< Detach a shaper node from a PPE shaper node. */
 		struct nss_shaper_config_ppe_sn_param ppe_sn_param;
-			/**< PPE SN shaper node configuration parametere. */
+			/**< Configuration parameters for a PPE shaper node. */
 	} snc;	/**< Types of shaper node configuration messages. */
 };
 
@@ -762,7 +763,7 @@
  * @param[in] app_data  Pointer to the application context of the message.
                         This context is passed to the callback together with the
                         sk_buff to provide context to the registrant (state).
- * @param[in] owner     Pass THIS_MODULE for this parameter - your module is held until you unregister
+ * @param[in] owner     Pointer to the kernel module. The module is held until it deregisters.
  *
  * @return
  * Pointer to the NSS core context.
@@ -798,7 +799,7 @@
  * @param[in] app_data  Pointer to the application context of the message.
                         This context is passed to the callback together with the
                         sk_buff to provide context to the registrant (state).
- * @param[in] owner     Pointer to the owner ??what owner?. ??original description was - "Pass THIS_MODULE for this parameter - your module is held until you unregister". This doesn't say what the owner param is.
+ * @param[in] owner     Pointer to the kernel module.
  *
  * @return
  * Pointer to the NSS core context.
@@ -826,7 +827,7 @@
  * @datatypes
  * sk_buff
  *
- * @param[in,out] ctx     Pointer to the NSS context provided during registration.
+ * @param[in]     ctx     Pointer to the NSS context provided during registration.
  * @param[in]     if_num  NSS interface number.
  * @param[in]     skb     Pointer to the data socket buffer.
  *
@@ -842,7 +843,7 @@
  * @datatypes
  * sk_buff
  *
- * @param[in,out] ctx     Pointer to the NSS context provided during registration.
+ * @param[in]     ctx     Pointer to the NSS context provided during registration.
  * @param[in]     if_num  NSS interface number.
  * @param[in]     skb     Pointer to the data socket buffer.
  *
@@ -858,7 +859,7 @@
  * @datatypes
  * nss_shaper_configure
  *
- * @param[in,out] ctx     Pointer to the NSS context.
+ * @param[in]     ctx     Pointer to the NSS context.
  * @param[in]     config  Pointer to the configuration message.
  *
  * @return
diff --git a/exports/nss_wifi.h b/exports/nss_wifi.h
index c020951..d44f4ef 100644
--- a/exports/nss_wifi.h
+++ b/exports/nss_wifi.h
@@ -88,6 +88,8 @@
 	NSS_WIFI_ALWAYS_PRIMARY_SET_MSG,
 	NSS_WIFI_FLUSH_HTT_CMD_MSG,
 	NSS_WIFI_CMD_MSG,
+	NSS_WIFI_ENABLE_OL_STATSV2_MSG,
+	NSS_WIFI_OL_PEER_TIME_MSG,
 	NSS_WIFI_MAX_MSG
 };
 
@@ -132,6 +134,7 @@
 	NSS_WIFI_RX_EXT_INV_PEER_TYPE,
 	NSS_WIFI_RX_EXT_PKTLOG_TYPE,
 	NSS_WIFI_RX_EXT_CBF_REMOTE,
+	NSS_WIFI_RX_STATS_V2_EXCEPTION,
 	NSS_WIFI_RX_EXT_MAX_TYPE,
 };
 
@@ -362,6 +365,40 @@
 };
 
 /**
+ * peer tx time stamp stats per tid
+ */
+struct nss_wifi_peer_txtime_stats {
+	uint32_t sum_tx;	/**< sum of sojourn for each packet */
+	uint32_t sum_msdus;	/**< num of msdus per peer per tid */
+};
+
+/**
+ * peer id and timestamp stats per tid
+ */
+struct nss_wifi_peer_tstamp_stats {
+	uint32_t peer_id;			/**< tid value */
+	struct nss_wifi_peer_txtime_stats sum[NSS_WIFI_TX_NUM_TOS_TIDS];
+							/**< timestamps */
+	uint32_t avg[NSS_WIFI_TX_NUM_TOS_TIDS];	/**< exponential weighted avg */
+};
+
+/**
+ * nss wifi tx timestamp msg for npeers
+ */
+struct nss_wifi_ol_peer_time_msg {
+	uint32_t npeers;			/**< number of peers */
+	struct nss_wifi_peer_tstamp_stats tstats[1];
+						/**< one instance of struct */
+};
+
+/**
+ * wifi enable/disable send packet to host
+ */
+struct nss_wifi_enable_ol_statsv2 {
+	uint32_t enable_ol_statsv2;	/**< flag to send packet to host */
+};
+
+/**
  * nss_wifi_dbdc_process_enable_msg
  *	Wi-Fi DBDC repeater process configuration. ??what is DBDC?
  */
@@ -710,6 +747,21 @@
 };
 
 /**
+ * nss_wifi_append_metaheader
+ *
+ * 	Append metaheader after pbuf->data for stats_v2.
+ */
+struct nss_wifi_append_statsv2_metahdr {
+	uint32_t rxstatsmagic;	/**< Magic to be verified on host */
+	uint32_t seq_number;	/**< sequence number of packets sent from nss */
+	uint16_t peer_id;	/**< peer_id of peer */
+	uint16_t num_msdus;	/**< msdus in ppdu */
+	uint16_t num_retries;	/**< retries in ppdu */
+	uint16_t num_mpdus;	/**< mpdus in ppdu */
+	uint32_t num_bytes;	/**< bytes in ppdu */
+};
+
+/**
  * nss_wifi_peer_stats_msg
  *	Wi-Fi peer statistics.
  */
@@ -842,10 +894,23 @@
 				/**< Always set the Wi-Fi primary radio. */
 		struct nss_wifi_cmd_msg wcmdm;
 				/**< Pdev command information. */
+		struct nss_wifi_enable_ol_statsv2 wesh_msg;
+				/**< Enable version 2 tx/rx stats. */
+		struct nss_wifi_ol_peer_time_msg wopt_msg;
+				/**< Send per peer/tid timestamp stats to host. */
 	} msg;			/**< Message payload. ??is this comment correct? I assumed it's the message payload because the first field is the message header */
 };
 
 /**
+ * nss_wifi_get_context
+ *	Gets the wifi context used in nss_gre_tx.
+ *
+ * @return
+ * Pointer to the NSS core context.
+ */
+extern struct nss_ctx_instance *nss_wifi_get_context(void);
+
+/**
  * nss_wifi_tx_msg
  *	Sends a Wi-Fi message to ??the NSS?.
  *
diff --git a/exports/nss_wifi_vdev.h b/exports/nss_wifi_vdev.h
index 4067247..32965d3 100644
--- a/exports/nss_wifi_vdev.h
+++ b/exports/nss_wifi_vdev.h
@@ -65,6 +65,7 @@
 	NSS_WIFI_VDEV_UPDATECHDR_MSG,
 	NSS_WIFI_VDEV_ME_SYNC_MSG,
 	NSS_WIFI_VDEV_STATS_MSG,
+	NSS_WIFI_VDEV_SET_NEXT_HOP,
 	NSS_WIFI_VDEV_MAX_MSG
 };
 
@@ -103,6 +104,7 @@
 	NSS_WIFI_VDEV_RADIO_NOT_PRESENT,
 	NSS_WIFI_VDEV_CHDRUPD_FAIL,
 	NSS_WIFI_VDEV_ME_DENY_GRP_MAX_RCHD,
+	NSS_WIFI_VDEV_EINV_NEXT_HOP,
 	NSS_WIFI_VDEV_EINV_MAX_CFG
 };
 
@@ -190,6 +192,13 @@
 };
 
 /**
+ * Set wifi vdev set next hop
+ */
+struct nss_wifi_vdev_set_next_hop_msg {
+	uint32_t ifnumber;	/**< next hop interface number */
+};
+
+/**
  * nss_wifi_vdev_cmd_msg
  *	Virtual device commands.
  */
@@ -687,6 +696,8 @@
 				/**< Synchronization message for a multicast enhancement host group. ??is this comment correct? */
 		struct nss_wifi_vdev_stats_sync_msg vdev_stats;
 				/**< Synchronization message for virtual device statistics. ??is this comment correct? */
+		struct nss_wifi_vdev_set_next_hop_msg next_hop;
+				/**< Next hop message for virtual device. */
 	} msg;		/**< Message payload. ??is this comment correct? I assumed it's the message payload because the first field is the message header */
 };
 
@@ -844,6 +855,22 @@
 nss_tx_status_t nss_wifi_vdev_tx_msg_ext(struct nss_ctx_instance *nss_ctx, struct sk_buff *os_buf);
 
 /**
+ * nss_wifi_vdev_set_next_hop
+ *	Sendnext hop message to WIFI vdev.
+ *
+ * @datatypes
+ * nss_ctx_instance
+ *
+ * @param[in] nss_ctx  Pointer to the NSS core context.
+ * @param[in]     if_num   Nss interface number.
+ * @param[in]	  next_hop Next hop interface number.
+ *
+ * @return
+ * Status of the Tx operation.
+ */
+nss_tx_status_t nss_wifi_vdev_set_next_hop(struct nss_ctx_instance *nss_ctx, int if_num, int next_hop);
+
+/**
  * @}
  */
 
diff --git a/nss_core.h b/nss_core.h
index 485782f..2d5e52b 100644
--- a/nss_core.h
+++ b/nss_core.h
@@ -680,6 +680,67 @@
 };
 
 /*
+ * GRE base debug statistics types
+ */
+enum nss_stats_gre_base_debug_types {
+	NSS_STATS_GRE_BASE_RX_PACKETS,			/**< Rx packet count. */
+	NSS_STATS_GRE_BASE_RX_DROPPED,			/**< Rx dropped count. */
+	NSS_STATS_GRE_BASE_EXP_ETH_HDR_MISSING,		/**< Ethernet header missing. */
+	NSS_STATS_GRE_BASE_EXP_ETH_TYPE_NON_IP,		/**< Not IPV4 or IPV6 packet. */
+	NSS_STATS_GRE_BASE_EXP_IP_UNKNOWN_PROTOCOL,	/**< Unknown protocol. */
+	NSS_STATS_GRE_BASE_EXP_IP_HEADER_INCOMPLETE,	/**< Bad IP header. */
+	NSS_STATS_GRE_BASE_EXP_IP_BAD_TOTAL_LENGTH,	/**< Invalid IP packet length. */
+	NSS_STATS_GRE_BASE_EXP_IP_BAD_CHECKSUM,		/**< Bad packet checksum. */
+	NSS_STATS_GRE_BASE_EXP_IP_DATAGRAM_INCOMPLETE,	/**< Bad packet. */
+	NSS_STATS_GRE_BASE_EXP_IP_FRAGMENT,		/**< IP fragment. */
+	NSS_STATS_GRE_BASE_EXP_IP_OPTIONS_INCOMPLETE,	/**< Invalid IP options. */
+	NSS_STATS_GRE_BASE_EXP_IP_WITH_OPTIONS,		/**< IP packet with options. */
+	NSS_STATS_GRE_BASE_EXP_IPV6_UNKNOWN_PROTOCOL,	/**< Unknown protocol. */
+	NSS_STATS_GRE_BASE_EXP_IPV6_HEADER_INCOMPLETE,	/**< Incomplete IPV6 header. */
+	NSS_STATS_GRE_BASE_EXP_GRE_UNKNOWN_SESSION,	/**< Unknown GRE session. */
+	NSS_STATS_GRE_BASE_EXP_GRE_NODE_INACTIVE,	/**< GRE node inactive. */
+	NSS_STATS_GRE_BASE_DEBUG_MAX,			/**< GRE base error max. */
+};
+
+/*
+ *  GRE base debug statistics
+ */
+struct nss_stats_gre_base_debug {
+	uint64_t stats[NSS_STATS_GRE_BASE_DEBUG_MAX];	/**< GRE debug statistics. */
+};
+
+/*
+ * GRE session debug statistics types
+ */
+enum nss_stats_gre_session_debug_types {
+	NSS_STATS_GRE_SESSION_PBUF_ALLOC_FAIL,			/**< Pbuf alloc failure. */
+	NSS_STATS_GRE_SESSION_DECAP_FORWARD_ENQUEUE_FAIL,	/**< Rx forward enqueue failure. */
+	NSS_STATS_GRE_SESSION_ENCAP_FORWARD_ENQUEUE_FAIL,	/**< Tx forward enqueue failure. */
+	NSS_STATS_GRE_SESSION_DECAP_TX_FORWARDED,		/**< Packets forwarded after decap. */
+	NSS_STATS_GRE_SESSION_ENCAP_RX_RECEIVED,		/**< Packets received for encap. */
+	NSS_STATS_GRE_SESSION_ENCAP_RX_DROPPED,			/**< Packets dropped while enqueue for encap. */
+	NSS_STATS_GRE_SESSION_ENCAP_RX_LINEAR_FAIL,		/**< Packets dropped during encap linearization. */
+	NSS_STATS_GRE_SESSION_EXP_RX_KEY_ERROR,			/**< Rx KEY error. */
+	NSS_STATS_GRE_SESSION_EXP_RX_SEQ_ERROR,			/**< Rx sequence number error. */
+	NSS_STATS_GRE_SESSION_EXP_RX_CS_ERROR,			/**< Rx checksum error. */
+	NSS_STATS_GRE_SESSION_EXP_RX_FLAG_MISMATCH,		/**< Rx flag mismatch. */
+	NSS_STATS_GRE_SESSION_EXP_RX_MALFORMED,			/**< Rx malformed packet. */
+	NSS_STATS_GRE_SESSION_EXP_RX_INVALID_PROTOCOL,		/**< Rx invalid protocol. */
+	NSS_STATS_GRE_SESSION_EXP_RX_NO_HEADROOM,		/**< Rx no headroom. */
+	NSS_STATS_GRE_SESSION_DEBUG_MAX,			/**< Session debug max. */
+};
+
+/*
+ *  GRE session debug statistics
+ */
+struct nss_stats_gre_session_debug {
+	uint64_t stats[NSS_STATS_GRE_SESSION_DEBUG_MAX];	/**< Session debug statistics. */
+	int32_t if_index;					/**< Netdevice's ifindex. */
+	uint32_t if_num;					/**< NSS interface number. */
+	bool valid;						/**< Is node valid ? */
+};
+
+/*
  * MAP-T debug error types
  */
 enum nss_stats_map_t_instance {
@@ -953,6 +1014,7 @@
 	struct dentry *pptp_dentry;		/* PPTP  stats dentry */
 	struct dentry *l2tpv2_dentry;		/* L2TPV2  stats dentry */
 	struct dentry *dtls_dentry;		/* DTLS stats dentry */
+	struct dentry *gre_dentry;		/* GRE stats dentry */
 	struct dentry *gre_tunnel_dentry;	/* GRE Tunnel stats dentry */
 	struct dentry *map_t_dentry;		/* MAP-T stats dentry */
 	struct dentry *gmac_dentry;		/* GMAC ethnode stats dentry */
@@ -995,6 +1057,7 @@
 	uint8_t pptp_handler_id;
 	uint8_t l2tpv2_handler_id;
 	uint8_t dtls_handler_id;
+	uint8_t gre_handler_id;
 	uint8_t map_t_handler_id;
 	uint8_t tunipip6_handler_id;
 	uint8_t frequency_handler_id;
@@ -1025,6 +1088,7 @@
 	nss_ipsec_msg_callback_t ipsec_decap_callback;
 					/* IPsec event callback function */
 	nss_crypto_msg_callback_t crypto_msg_callback;
+	nss_crypto_cmn_msg_callback_t crypto_cmn_msg_callback;
 	nss_crypto_buf_callback_t crypto_buf_callback;
 	nss_crypto_pm_event_callback_t crypto_pm_callback;
 					/* crypto interface callback functions */
@@ -1042,6 +1106,8 @@
 
 	nss_map_t_msg_callback_t map_t_msg_callback;
 					/* map-t interface event callback function */
+	nss_gre_msg_callback_t gre_msg_callback;
+					/* gre interface event callback function */
 	nss_tunipip6_msg_callback_t tunipip6_msg_callback;
 					/* ipip6 tunnel interface event callback function */
 	nss_pptp_msg_callback_t pptp_msg_callback;
@@ -1276,6 +1342,8 @@
 				/* Does this core handle l2tpv2 Tunnel ? */
 	enum nss_feature_enabled map_t_enabled;
 				/* Does this core handle map-t */
+	enum nss_feature_enabled gre_enabled;
+				/* Does this core handle GRE */
 	enum nss_feature_enabled oam_enabled;
 				/* Does this core handle oam? */
 	enum nss_feature_enabled ppe_enabled;
@@ -1360,7 +1428,7 @@
  * APIs provided by nss_tx_rx.c
  */
 extern void nss_rx_handle_status_pkt(struct nss_ctx_instance *nss_ctx, struct sk_buff *nbuf);
-extern void nss_crypto_buf_handler(struct nss_ctx_instance *nss_ctx, void *buf, uint32_t paddr, uint16_t len);
+
 /*
  * APIs provided by nss_stats.c
  */
diff --git a/nss_crypto_cmn.c b/nss_crypto_cmn.c
new file mode 100644
index 0000000..b62b3cc
--- /dev/null
+++ b/nss_crypto_cmn.c
@@ -0,0 +1,400 @@
+/*
+ **************************************************************************
+ * Copyright (c) 2013,2015-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.
+ **************************************************************************
+ */
+
+/*
+ * nss_crypto_cmn.c
+ *	NSS Crypto common API implementation
+ */
+
+#include "nss_tx_rx_common.h"
+#include "nss_crypto_cmn.h"
+
+/*
+ * Amount time the synchronous message should wait for response from
+ * NSS before the timeout happens. After the timeout the message
+ * response even if it arrives has to be discarded. Typically, the
+ * time needs to be selected based on the worst case time in case of
+ * peak throughput between host & NSS.
+ */
+#define NSS_CRYPTO_CMN_TX_TIMEO_TICKS msecs_to_jiffies(3000) /* milliseconds */
+
+/*
+ * Private data structure to hold state for
+ * the crypto specific NSS interaction
+ */
+struct nss_crypto_cmn_pvt {
+	struct semaphore sem;		/* used for synchronizing 'tx_msg_sync' */
+	struct completion complete;	/* completion callback */
+	atomic_t seq_no;		/* used for tracking tx_msg_sync requests */
+};
+
+/*
+ * This is a single instance applicable for all crypto synchronous
+ * messaging interaction with NSS.
+ */
+static struct nss_crypto_cmn_pvt g_nss_crypto_cmn;
+
+/*
+ * nss_crypto_cmn_msg_handler()
+ *	this handles all the IPsec events and responses
+ */
+static void nss_crypto_cmn_msg_handler(struct nss_ctx_instance *nss_ctx, struct nss_cmn_msg *ncm,
+					void *app_data __attribute((unused)))
+{
+	struct nss_crypto_cmn_msg *nim = (struct nss_crypto_cmn_msg *)ncm;
+	nss_crypto_cmn_msg_callback_t cb = NULL;
+
+	/*
+	 * Sanity check the message type
+	 */
+	if (ncm->type > NSS_CRYPTO_CMN_MSG_TYPE_MAX) {
+		nss_warning("%p: rx message type out of range: %d", nss_ctx, ncm->type);
+		return;
+	}
+
+	/*
+	 * Check if the message structure length matches that of Host side. In case
+	 * of failure this indicates ether the structure is different or this is not
+	 * the intended interface.
+	 */
+	if (nss_cmn_get_msg_len(ncm) != sizeof(*nim)) {
+		nss_warning("%p: rx message length is invalid: %d", nss_ctx, nss_cmn_get_msg_len(ncm));
+		return;
+	}
+
+	if (ncm->response == NSS_CMN_RESPONSE_LAST) {
+		nss_warning("%p: rx message response for if %d, type %d, is invalid: %d", nss_ctx,
+				ncm->interface, ncm->type, ncm->response);
+		return;
+	}
+
+	if (ncm->response == NSS_CMM_RESPONSE_NOTIFY) {
+		ncm->cb = (nss_ptr_t)nss_ctx->nss_top->crypto_cmn_msg_callback;
+		ncm->app_data = (nss_ptr_t)nss_ctx->nss_top->crypto_ctx;
+	}
+
+	nss_core_log_msg_failures(nss_ctx, ncm);
+
+	/*
+	 * Load, Test & call
+	 */
+	cb = (nss_crypto_cmn_msg_callback_t)ncm->cb;
+	if (unlikely(!cb)) {
+		nss_warning("%p: rx handler has been unregistered for i/f: %d", nss_ctx, ncm->interface);
+		return;
+	}
+
+	cb((void *)ncm->app_data, nim);
+}
+
+/*
+ * nss_crypto_cmn_tx_msg
+ *	Send crypto config to NSS.
+ */
+nss_tx_status_t nss_crypto_cmn_tx_msg(struct nss_ctx_instance *nss_ctx, struct nss_crypto_cmn_msg *msg)
+{
+	struct nss_top_instance *nss_top = &nss_top_main;
+	struct nss_cmn_msg *ncm = &msg->cm;
+	uint16_t msg_len = nss_cmn_get_msg_len(ncm);
+
+	struct sk_buff *nbuf;
+	int32_t status;
+
+	nss_info("%p: tx message %d for if %d", nss_ctx, ncm->type, ncm->interface);
+
+	NSS_VERIFY_CTX_MAGIC(nss_ctx);
+	if (unlikely(nss_ctx->state != NSS_CORE_STATE_INITIALIZED)) {
+		nss_warning("%p: message dropped, core not ready", nss_ctx);
+		return NSS_TX_FAILURE_NOT_READY;
+	}
+
+	BUILD_BUG_ON(NSS_NBUF_PAYLOAD_SIZE < sizeof(*msg));
+
+	if (ncm->type > NSS_CRYPTO_CMN_MSG_TYPE_MAX) {
+		nss_warning("%p: message type out of range: %d", nss_ctx, ncm->type);
+		return NSS_TX_FAILURE;
+	}
+
+	/*
+	 * Check if the message structure length matches the structure length. Otherwise
+	 * the sender accidentally programmed a incorrect length into the message.
+	 */
+	if (msg_len != sizeof(*msg)) {
+		nss_warning("%p: message request len bad: %d", nss_ctx, msg_len);
+		return NSS_TX_FAILURE_BAD_PARAM;
+	}
+
+	nbuf = dev_alloc_skb(NSS_NBUF_PAYLOAD_SIZE);
+	if (unlikely(!nbuf)) {
+		NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_top->stats_drv[NSS_STATS_DRV_NBUF_ALLOC_FAILS]);
+		nss_warning("%p: tx config dropped as command allocation failed", nss_ctx);
+		return NSS_TX_FAILURE;
+	}
+
+	nss_trace("%p: msg params version:%d, interface:%d, type:%d, cb:%p, app_data:%p, len:%d",
+			nss_ctx, ncm->version, ncm->interface, ncm->type,
+			(void *)ncm->cb, (void *)ncm->app_data, ncm->len);
+
+	memcpy(skb_put(nbuf, msg_len), msg, msg_len);
+
+	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: 	/* queue full condition */
+		dev_kfree_skb_any(nbuf);
+		nss_warning("%p: H2N queue full for tx_msg", nss_ctx);
+		return NSS_TX_FAILURE_QUEUE;
+
+	default:				/* all other tx failures */
+		dev_kfree_skb_any(nbuf);
+		nss_warning("%p: general failure for tx_msg", nss_ctx);
+		return NSS_TX_FAILURE;
+	}
+
+	nss_hal_send_interrupt(nss_ctx, NSS_H2N_INTR_DATA_COMMAND_QUEUE);
+	return NSS_TX_SUCCESS;
+}
+EXPORT_SYMBOL(nss_crypto_cmn_tx_msg);
+
+/*
+ * nss_crypto_cmn_tx_msg_cb()
+ *	Callback to handle the synchronous completion of messages.
+ */
+static void nss_crypto_cmn_tx_msg_cb(void *app_data, struct nss_crypto_cmn_msg *nim)
+{
+	struct nss_crypto_cmn_pvt *pvt = &g_nss_crypto_cmn;
+	struct nss_crypto_cmn_msg *resp = (struct nss_crypto_cmn_msg *)nim->cm.app_data;
+
+	/*
+	 * Only update the message structure if the sequence no. matches
+	 * Otherwise, a timeout might have happened in between and we
+	 * are probably receiving the completion for an older message
+	 */
+	if (atomic_read(&pvt->seq_no) == nim->seq_num) {
+		memcpy(resp, nim, sizeof(struct nss_crypto_cmn_msg));
+		complete(&pvt->complete);
+	}
+}
+
+/*
+ * nss_crypto_cmn_tx_msg_sync()
+ *	Transmit a crypto message to NSS firmware synchronously.
+ */
+nss_tx_status_t nss_crypto_cmn_tx_msg_sync(struct nss_ctx_instance *nss_ctx, struct nss_crypto_cmn_msg *msg)
+{
+	struct nss_crypto_cmn_pvt *pvt = &g_nss_crypto_cmn;
+	nss_tx_status_t status;
+	int ret = 0;
+
+	down(&pvt->sem);
+	atomic_inc(&pvt->seq_no);
+
+	/*
+	 * this is a synchronous message; overload the callback
+	 * and app_data
+	 */
+	msg->cm.cb = (nss_ptr_t)nss_crypto_cmn_tx_msg_cb;
+	msg->cm.app_data = (nss_ptr_t)msg;
+	msg->seq_num = atomic_read(&pvt->seq_no);
+
+	status = nss_crypto_cmn_tx_msg(nss_ctx, msg);
+	if (status != NSS_TX_SUCCESS) {
+		nss_warning("%p: tx_msg failed", nss_ctx);
+		up(&pvt->sem);
+		return status;
+	}
+
+	/*
+	 * Note: This cannot be called in atomic context
+	 */
+	ret = wait_for_completion_timeout(&pvt->complete, NSS_CRYPTO_CMN_TX_TIMEO_TICKS);
+	if (!ret) {
+		atomic_inc(&pvt->seq_no);
+		nss_warning("%p: tx_msg_sync timed out", nss_ctx);
+		up(&pvt->sem);
+		return NSS_TX_FAILURE;
+	}
+
+	/*
+	 * This ensures that the even if the response arrives on a different
+	 * CPU core the data copied by the response callback will be visible
+	 * to the caller which is sleeping for it on a different core. For
+	 * further details read Linux/Documentation/memory-barrier.txt
+	 */
+	smp_rmb();
+	up(&pvt->sem);
+
+	return NSS_TX_SUCCESS;
+}
+EXPORT_SYMBOL(nss_crypto_cmn_tx_msg_sync);
+
+/*
+ * nss_crypto_cmn_tx_buf()
+ *	NSS crypto TX data API. Sends a crypto buffer to NSS.
+ */
+nss_tx_status_t nss_crypto_cmn_tx_buf(struct nss_ctx_instance *nss_ctx, uint32_t if_num,
+					struct sk_buff *skb)
+{
+	int32_t status;
+
+	NSS_VERIFY_CTX_MAGIC(nss_ctx);
+	if (unlikely(nss_ctx->state != NSS_CORE_STATE_INITIALIZED)) {
+		nss_warning("%p: tx_data packet dropped as core not ready", nss_ctx);
+		return NSS_TX_FAILURE_NOT_READY;
+	}
+
+	status = nss_core_send_buffer(nss_ctx, if_num, skb, NSS_IF_DATA_QUEUE_0, H2N_BUFFER_PACKET, 0);
+	switch (status) {
+	case NSS_CORE_STATUS_SUCCESS:
+		break;
+
+	case NSS_CORE_STATUS_FAILURE_QUEUE: /* queue full condition */
+		nss_warning("%p: H2N queue full for tx_buf", nss_ctx);
+		return NSS_TX_FAILURE_QUEUE;
+
+	default:
+		nss_warning("%p: general failure for tx_buf", nss_ctx);
+		return NSS_TX_FAILURE;
+	}
+
+	/*
+	 * Kick the NSS awake so it can process our new entry.
+	 */
+	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_CRYPTO_REQ]);
+
+	return NSS_TX_SUCCESS;
+}
+EXPORT_SYMBOL(nss_crypto_cmn_tx_buf);
+
+/*
+ * nss_crypto_cmn_notify_register()
+ *	register message notifier for crypto interface
+ */
+struct nss_ctx_instance *nss_crypto_cmn_notify_register(nss_crypto_cmn_msg_callback_t cb, void *app_data)
+{
+	struct nss_top_instance *nss_top = &nss_top_main;
+	struct nss_ctx_instance *nss_ctx = &nss_top->nss[nss_top->crypto_handler_id];
+
+	nss_top->crypto_ctx = app_data;
+	nss_top->crypto_cmn_msg_callback = cb;
+
+	return nss_ctx;
+}
+EXPORT_SYMBOL(nss_crypto_cmn_notify_register);
+
+/*
+ * nss_crypto_cmn_notify_unregister()
+ *	De-register the message notifier for crypto interface
+ */
+void nss_crypto_cmn_notify_unregister(struct nss_ctx_instance *nss_ctx)
+{
+	struct nss_top_instance *nss_top = &nss_top_main;
+
+	nss_top->crypto_ctx = NULL;
+	nss_top->crypto_cmn_msg_callback = NULL;
+}
+EXPORT_SYMBOL(nss_crypto_cmn_notify_unregister);
+
+/*
+ * nss_crypto_cmn_data_register()
+ *	Register the data callback routine
+ */
+struct nss_ctx_instance *nss_crypto_cmn_data_register(uint32_t if_num, nss_crypto_cmn_buf_callback_t cb,
+		struct net_device *netdev, uint32_t features)
+{
+	struct nss_ctx_instance *nss_ctx;
+
+	if (if_num < NSS_SPECIAL_IF_START) {
+		nss_warning("%p: interface number is not special interface %d", nss_ctx, if_num);
+		return NULL;
+	}
+
+	nss_ctx = &nss_top_main.nss[nss_top_main.crypto_handler_id];
+
+	/*
+	 * avoid multiple registration for same interface number
+	 */
+	if (nss_ctx->subsys_dp_register[if_num].cb)
+		return nss_ctx;
+
+	/*
+	 * Note: no locking is required for updating this as
+	 * the registration is only a module load time operation.
+	 */
+	nss_ctx->subsys_dp_register[if_num].cb = cb;
+	nss_ctx->subsys_dp_register[if_num].app_data = NULL;
+	nss_ctx->subsys_dp_register[if_num].ndev = netdev;
+	nss_ctx->subsys_dp_register[if_num].features = features;
+
+	return nss_ctx;
+}
+EXPORT_SYMBOL(nss_crypto_cmn_data_register);
+
+/*
+ * nss_crypto_cmn_data_unregister()
+ *	De-register the data callback routine
+ */
+void nss_crypto_cmn_data_unregister(struct nss_ctx_instance *nss_ctx, uint32_t if_num)
+{
+	if (if_num < NSS_SPECIAL_IF_START) {
+		nss_warning("%p: interface number is not special interface %d", nss_ctx, if_num);
+		return;
+	}
+
+	/*
+	 * Note: no locking is required for updating this as
+	 * the registration is only a module load time operation.
+	 */
+	nss_ctx->subsys_dp_register[if_num].cb = NULL;
+	nss_ctx->subsys_dp_register[if_num].app_data = NULL;
+	nss_ctx->subsys_dp_register[if_num].ndev = NULL;
+	nss_ctx->subsys_dp_register[if_num].features = 0;
+}
+EXPORT_SYMBOL(nss_crypto_cmn_data_unregister);
+
+/*
+ * nss_crypto_cmn_get_context()
+ *	get NSS context instance for crypto handle
+ */
+struct nss_ctx_instance *nss_crypto_cmn_get_context(void)
+{
+	return (struct nss_ctx_instance *)&nss_top_main.nss[nss_top_main.crypto_handler_id];
+}
+EXPORT_SYMBOL(nss_crypto_cmn_get_context);
+
+/*
+ * nss_crypto_cmn_register_handler()
+ */
+void nss_crypto_cmn_register_handler(void)
+{
+	sema_init(&g_nss_crypto_cmn.sem, 1);
+	init_completion(&g_nss_crypto_cmn.complete);
+	nss_core_register_handler(NSS_CRYPTO_EIP197_INTERFACE, nss_crypto_cmn_msg_handler, NULL);
+}
+
+/*
+ * nss_crypto_cmn_msg_init()
+ *	Initialize crypto message
+ */
+void nss_crypto_cmn_msg_init(struct nss_crypto_cmn_msg *ncm, uint16_t if_num, uint32_t type,
+			uint32_t len, nss_crypto_cmn_msg_callback_t cb, void *app_data)
+{
+	nss_cmn_msg_init(&ncm->cm, if_num, type, len, (void *)cb, app_data);
+}
+EXPORT_SYMBOL(nss_crypto_cmn_msg_init);
diff --git a/nss_gre.c b/nss_gre.c
new file mode 100644
index 0000000..a86bbd1
--- /dev/null
+++ b/nss_gre.c
@@ -0,0 +1,456 @@
+/*
+ **************************************************************************
+ * 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_GRE_TX_TIMEOUT 3000 /* 3 Seconds */
+
+/*
+ * Private data structure
+ */
+static struct {
+	struct semaphore sem;
+	struct completion complete;
+	int response;
+	void *cb;
+	void *app_data;
+} nss_gre_pvt;
+
+/*
+ * Data structures to store GRE nss debug stats
+ */
+static DEFINE_SPINLOCK(nss_gre_stats_lock);
+static struct nss_stats_gre_session_debug session_debug_stats[NSS_GRE_MAX_DEBUG_SESSION_STATS];
+static struct nss_stats_gre_base_debug base_debug_stats;
+
+/*
+ * nss_gre_session_debug_stats_sync()
+ *	debug statistics sync for GRE session.
+ */
+static void nss_gre_session_debug_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_gre_session_stats_msg *sstats, uint16_t if_num)
+{
+	int i, j;
+	spin_lock_bh(&nss_gre_stats_lock);
+	for (i = 0; i < NSS_GRE_MAX_DEBUG_SESSION_STATS; i++) {
+		if (session_debug_stats[i].if_num == if_num) {
+			for (j = 0; j < NSS_STATS_GRE_SESSION_DEBUG_MAX; j++) {
+				session_debug_stats[i].stats[j] += sstats->stats[j];
+			}
+			break;
+		}
+	}
+	spin_unlock_bh(&nss_gre_stats_lock);
+}
+
+/*
+ * nss_gre_session_debug_stats_get()
+ *	Get GRE session debug statistics.
+ */
+void nss_gre_session_debug_stats_get(void *stats_mem, int size)
+{
+	struct nss_stats_gre_session_debug *stats = (struct nss_stats_gre_session_debug *)stats_mem;
+	int i;
+
+	if (!stats || (size < (sizeof(struct nss_stats_gre_session_debug) * NSS_STATS_GRE_SESSION_DEBUG_MAX)))  {
+		nss_warning("No memory to copy gre stats");
+		return;
+	}
+
+	spin_lock_bh(&nss_gre_stats_lock);
+	for (i = 0; i < NSS_GRE_MAX_DEBUG_SESSION_STATS; i++) {
+		if (session_debug_stats[i].valid) {
+			memcpy(stats, &session_debug_stats[i], sizeof(struct nss_stats_gre_session_debug));
+			stats++;
+		}
+	}
+	spin_unlock_bh(&nss_gre_stats_lock);
+}
+
+/*
+ * nss_gre_base_debug_stats_sync()
+ *	Debug statistics sync for GRE base node.
+ */
+void nss_gre_base_debug_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_gre_base_stats_msg *bstats)
+{
+	int i;
+	spin_lock_bh(&nss_gre_stats_lock);
+	for (i = 0; i < NSS_STATS_GRE_BASE_DEBUG_MAX; i++) {
+		base_debug_stats.stats[i] += bstats->stats[i];
+	}
+	spin_unlock_bh(&nss_gre_stats_lock);
+}
+
+/*
+ * nss_gre_base_debug_stats_get()
+ *	Get GRE debug base statistics.
+ */
+void nss_gre_base_debug_stats_get(void *stats_mem, int size)
+{
+	struct nss_stats_gre_base_debug *stats = (struct nss_stats_gre_base_debug *)stats_mem;
+
+	if (!stats) {
+		nss_warning("No memory to copy GRE base stats\n");
+		return;
+	}
+
+	if (size < sizeof(struct nss_stats_gre_base_debug)) {
+		nss_warning("Not enough memory to copy GRE base stats\n");
+		return;
+	}
+
+	spin_lock_bh(&nss_gre_stats_lock);
+	memcpy(stats, &base_debug_stats, sizeof(struct nss_stats_gre_base_debug));
+	spin_unlock_bh(&nss_gre_stats_lock);
+}
+
+/*
+ * nss_gre_msg_handler()
+ *	Handle NSS -> HLOS messages for GRE
+ */
+static void nss_gre_msg_handler(struct nss_ctx_instance *nss_ctx, struct nss_cmn_msg *ncm, __attribute__((unused))void *app_data)
+{
+	struct nss_gre_msg *ntm = (struct nss_gre_msg *)ncm;
+	void *ctx;
+
+	nss_gre_msg_callback_t cb;
+
+	NSS_VERIFY_CTX_MAGIC(nss_ctx);
+	BUG_ON(!(nss_is_dynamic_interface(ncm->interface) || ncm->interface == NSS_GRE_INTERFACE));
+
+	/*
+	 * Is this a valid request/response packet?
+	 */
+	if (ncm->type >= NSS_GRE_MSG_MAX) {
+		nss_warning("%p: received invalid message %d for GRE STD interface", nss_ctx, ncm->type);
+		return;
+	}
+
+	if (nss_cmn_get_msg_len(ncm) > sizeof(struct nss_gre_msg)) {
+		nss_warning("%p: tx request for another interface: %d", nss_ctx, ncm->interface);
+		return;
+	}
+
+	switch (ntm->cm.type) {
+	case NSS_GRE_MSG_SESSION_STATS:
+		/*
+		 * debug stats embedded in stats msg
+		 */
+		nss_gre_session_debug_stats_sync(nss_ctx, &ntm->msg.sstats, ncm->interface);
+		break;
+
+	case NSS_GRE_MSG_BASE_STATS:
+		nss_gre_base_debug_stats_sync(nss_ctx, &ntm->msg.bstats);
+		break;
+
+	default:
+		break;
+
+	}
+
+	/*
+	 * Update the callback and app_data for NOTIFY messages, gre sends all notify messages
+	 * to the same callback/app_data.
+	 */
+	if (ncm->response == NSS_CMM_RESPONSE_NOTIFY) {
+		ncm->cb = (nss_ptr_t)nss_ctx->nss_top->gre_msg_callback;
+		ncm->app_data = (nss_ptr_t)nss_ctx->subsys_dp_register[ncm->interface].app_data;
+	}
+
+	/*
+	 * Log failures
+	 */
+	nss_core_log_msg_failures(nss_ctx, ncm);
+
+	/*
+	 * callback
+	 */
+	cb = (nss_gre_msg_callback_t)ncm->cb;
+	ctx = (void *)ncm->app_data;
+
+	/*
+	 * call gre-std callback
+	 */
+	if (!cb) {
+		nss_warning("%p: No callback for gre-std interface %d",
+			    nss_ctx, ncm->interface);
+		return;
+	}
+
+	cb(ctx, ntm);
+}
+
+/*
+ * nss_gre_callback()
+ *	Callback to handle the completion of HLOS-->NSS messages.
+ */
+static void nss_gre_callback(void *app_data, struct nss_gre_msg *nim)
+{
+	nss_gre_msg_callback_t callback = (nss_gre_msg_callback_t)nss_gre_pvt.cb;
+	void *data = nss_gre_pvt.app_data;
+
+	nss_gre_pvt.cb = NULL;
+	nss_gre_pvt.app_data = NULL;
+
+	if (nim->cm.response != NSS_CMN_RESPONSE_ACK) {
+		nss_warning("gre Error response %d\n", nim->cm.response);
+		nss_gre_pvt.response = NSS_TX_FAILURE;
+	} else {
+		nss_gre_pvt.response = NSS_TX_SUCCESS;
+	}
+
+	if (callback) {
+		callback(data, nim);
+	}
+
+	complete(&nss_gre_pvt.complete);
+}
+
+/*
+ * nss_gre_tx_msg()
+ *	Transmit a GRE message to NSS firmware
+ */
+nss_tx_status_t nss_gre_tx_msg(struct nss_ctx_instance *nss_ctx, struct nss_gre_msg *msg)
+{
+	struct nss_gre_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: gre msg dropped as core not ready", nss_ctx);
+		return NSS_TX_FAILURE_NOT_READY;
+	}
+
+	/*
+	 * Sanity check the message
+	 */
+	if (!nss_is_dynamic_interface(ncm->interface)) {
+		nss_warning("%p: tx request for non dynamic interface: %d", nss_ctx, ncm->interface);
+		return NSS_TX_FAILURE;
+	}
+
+	if (ncm->type > NSS_GRE_MSG_MAX) {
+		nss_warning("%p: message type out of range: %d", nss_ctx, ncm->type);
+		return NSS_TX_FAILURE;
+	}
+
+	if (nss_cmn_get_msg_len(ncm) > sizeof(struct nss_gre_msg)) {
+		nss_warning("%p: message length is invalid: %d", nss_ctx, nss_cmn_get_msg_len(ncm));
+		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: msg dropped as command allocation failed", nss_ctx);
+		return NSS_TX_FAILURE;
+	}
+
+	/*
+	 * Copy the message to our skb
+	 */
+	nm = (struct nss_gre_msg *)skb_put(nbuf, sizeof(struct nss_gre_msg));
+	memcpy(nm, msg, sizeof(struct nss_gre_msg));
+
+	status = nss_core_send_buffer(nss_ctx, 0, nbuf, NSS_IF_CMD_QUEUE, H2N_BUFFER_CTRL, 0);
+	if (status != NSS_CORE_STATUS_SUCCESS) {
+		dev_kfree_skb_any(nbuf);
+		nss_warning("%p: Unable to enqueue 'gre message'\n", nss_ctx);
+		if (status == NSS_CORE_STATUS_FAILURE_QUEUE) {
+			return NSS_TX_FAILURE_QUEUE;
+		}
+		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_CMD_REQ]);
+	return NSS_TX_SUCCESS;
+}
+EXPORT_SYMBOL(nss_gre_tx_msg);
+
+/*
+ * nss_gre_tx_msg_sync()
+ *	Transmit a GRE message to NSS firmware synchronously.
+ */
+nss_tx_status_t nss_gre_tx_msg_sync(struct nss_ctx_instance *nss_ctx, struct nss_gre_msg *msg)
+{
+	nss_tx_status_t status;
+	int ret = 0;
+
+	down(&nss_gre_pvt.sem);
+	nss_gre_pvt.cb = (void *)msg->cm.cb;
+	nss_gre_pvt.app_data = (void *)msg->cm.app_data;
+
+	msg->cm.cb = (nss_ptr_t)nss_gre_callback;
+	msg->cm.app_data = (nss_ptr_t)NULL;
+
+	status = nss_gre_tx_msg(nss_ctx, msg);
+	if (status != NSS_TX_SUCCESS) {
+		nss_warning("%p: gre_tx_msg failed\n", nss_ctx);
+		up(&nss_gre_pvt.sem);
+		return status;
+	}
+	ret = wait_for_completion_timeout(&nss_gre_pvt.complete, msecs_to_jiffies(NSS_GRE_TX_TIMEOUT));
+
+	if (!ret) {
+		nss_warning("%p: GRE STD tx sync failed due to timeout\n", nss_ctx);
+		nss_gre_pvt.response = NSS_TX_FAILURE;
+	}
+
+	status = nss_gre_pvt.response;
+	up(&nss_gre_pvt.sem);
+	return status;
+}
+EXPORT_SYMBOL(nss_gre_tx_msg_sync);
+
+/*
+ * nss_gre_tx_buf()
+ *	Send packet to GRE interface owned by NSS
+ */
+nss_tx_status_t nss_gre_tx_buf(struct nss_ctx_instance *nss_ctx, uint32_t if_num, struct sk_buff *skb)
+{
+	int32_t status;
+
+	NSS_VERIFY_CTX_MAGIC(nss_ctx);
+	if (unlikely(nss_ctx->state != NSS_CORE_STATE_INITIALIZED)) {
+		nss_warning("%p: GRE std packet dropped as core not ready", nss_ctx);
+		return NSS_TX_FAILURE_NOT_READY;
+	}
+
+	status = nss_core_send_buffer(nss_ctx, if_num, skb, NSS_IF_DATA_QUEUE_0, H2N_BUFFER_PACKET, H2N_BIT_FLAG_VIRTUAL_BUFFER);
+	if (unlikely(status != NSS_CORE_STATUS_SUCCESS)) {
+		nss_warning("%p: Unable to enqueue GRE std packet\n", nss_ctx);
+		return NSS_TX_FAILURE_QUEUE;
+	}
+
+	/*
+	 * Kick the NSS awake so it can process our new entry.
+	 */
+	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_gre_tx_buf);
+
+/*
+ ***********************************
+ * Register/Unregister/Miscellaneous APIs
+ ***********************************
+ */
+
+/*
+ * nss_gre_register_if()
+ *	Register data and message handlers for GRE.
+ */
+struct nss_ctx_instance *nss_gre_register_if(uint32_t if_num, nss_gre_data_callback_t gre_callback,
+			nss_gre_msg_callback_t event_callback, struct net_device *netdev, uint32_t features)
+{
+	struct nss_ctx_instance *nss_ctx = (struct nss_ctx_instance *)&nss_top_main.nss[nss_top_main.gre_handler_id];
+	int i = 0;
+
+	nss_assert(nss_ctx);
+	nss_assert(nss_is_dynamic_interface(if_num));
+
+	nss_ctx->subsys_dp_register[if_num].ndev = netdev;
+	nss_ctx->subsys_dp_register[if_num].cb = gre_callback;
+	nss_ctx->subsys_dp_register[if_num].app_data = netdev;
+	nss_ctx->subsys_dp_register[if_num].features = features;
+
+	nss_top_main.gre_msg_callback = event_callback;
+
+	nss_core_register_handler(if_num, nss_gre_msg_handler, NULL);
+
+	spin_lock_bh(&nss_gre_stats_lock);
+	for (i = 0; i < NSS_GRE_MAX_DEBUG_SESSION_STATS; i++) {
+		if (!session_debug_stats[i].valid) {
+			session_debug_stats[i].valid = true;
+			session_debug_stats[i].if_num = if_num;
+			session_debug_stats[i].if_index = netdev->ifindex;
+			break;
+		}
+	}
+	spin_unlock_bh(&nss_gre_stats_lock);
+
+	return nss_ctx;
+}
+EXPORT_SYMBOL(nss_gre_register_if);
+
+/*
+ * nss_gre_unregister_if()
+ *	Unregister data and message handler.
+ */
+void nss_gre_unregister_if(uint32_t if_num)
+{
+	struct nss_ctx_instance *nss_ctx = (struct nss_ctx_instance *)&nss_top_main.nss[nss_top_main.gre_handler_id];
+	int i;
+
+	nss_assert(nss_ctx);
+	nss_assert(nss_is_dynamic_interface(if_num));
+
+	nss_ctx->subsys_dp_register[if_num].ndev = NULL;
+	nss_ctx->subsys_dp_register[if_num].cb = NULL;
+	nss_ctx->subsys_dp_register[if_num].app_data = NULL;
+	nss_ctx->subsys_dp_register[if_num].features = 0;
+
+	nss_top_main.gre_msg_callback = NULL;
+
+	nss_core_unregister_handler(if_num);
+
+	spin_lock_bh(&nss_gre_stats_lock);
+	for (i = 0; i < NSS_GRE_MAX_DEBUG_SESSION_STATS; i++) {
+		if (session_debug_stats[i].if_num == if_num) {
+			memset(&session_debug_stats[i], 0, sizeof(struct nss_stats_gre_session_debug));
+			break;
+		}
+	}
+	spin_unlock_bh(&nss_gre_stats_lock);
+}
+EXPORT_SYMBOL(nss_gre_unregister_if);
+
+/*
+ * nss_get_gre_context()
+ */
+struct nss_ctx_instance *nss_gre_get_context()
+{
+	return (struct nss_ctx_instance *)&nss_top_main.nss[nss_top_main.gre_handler_id];
+}
+EXPORT_SYMBOL(nss_gre_get_context);
+
+/*
+ * nss_gre_msg_init()
+ *	Initialize nss_gre msg.
+ */
+void nss_gre_msg_init(struct nss_gre_msg *ncm, uint16_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_gre_msg_init);
+
+/*
+ * nss_gre_register_handler()
+ *	debugfs stats msg handler received on static gre interface
+ */
+void nss_gre_register_handler(void)
+{
+	nss_info("nss_gre_register_handler");
+	sema_init(&nss_gre_pvt.sem, 1);
+	init_completion(&nss_gre_pvt.complete);
+	nss_core_register_handler(NSS_GRE_INTERFACE, nss_gre_msg_handler, NULL);
+}
diff --git a/nss_hal/fsm9010/nss_hal_pvt.c b/nss_hal/fsm9010/nss_hal_pvt.c
index 62b65ee..591e50d 100644
--- a/nss_hal/fsm9010/nss_hal_pvt.c
+++ b/nss_hal/fsm9010/nss_hal_pvt.c
@@ -95,7 +95,7 @@
 	}
 
 	if (of_property_read_u32(np, "qcom,id", &npd->id)
-	    || of_property_read_u32(np, "qcom,num_queue", &npd->num_queue)) {
+	    || of_property_read_u32(np, "qcom,num-queue", &npd->num_queue)) {
 		pr_err("%s: error reading critical device node properties\n", np->name);
 		goto out;
 	}
diff --git a/nss_hal/nss_hal.c b/nss_hal/nss_hal.c
index 7970602..f3046f3 100644
--- a/nss_hal/nss_hal.c
+++ b/nss_hal/nss_hal.c
@@ -110,6 +110,7 @@
 	npd->ipv6_reasm_enabled = of_property_read_bool(np, "qcom,ipv6-reasm-enabled");
 	npd->l2tpv2_enabled = of_property_read_bool(np, "qcom,l2tpv2-enabled");
 	npd->map_t_enabled = of_property_read_bool(np, "qcom,map-t-enabled");
+	npd->gre_enabled = of_property_read_bool(np, "qcom,gre-enabled");
 	npd->oam_enabled = of_property_read_bool(np, "qcom,oam-enabled");
 	npd->ppe_enabled = of_property_read_bool(np, "qcom,ppe-enabled");
 	npd->pppoe_enabled = of_property_read_bool(np, "qcom,pppoe-enabled");
@@ -386,10 +387,18 @@
 		nss_ipv6_reasm_register_handler();
 	}
 
+	/*
+	 * TODO: when Crypto is moved to Core-1 it needs to
+	 * flush based on nss_top->crypto_enabled
+	 */
 	if (npd->crypto_enabled == NSS_FEATURE_ENABLED) {
-		nss_top->crypto_enabled = 1;
 		nss_top->crypto_handler_id = nss_dev->id;
+#if defined(NSS_HAL_IPQ807x_SUPPORT)
+		nss_crypto_cmn_register_handler();
+#else
+		nss_top->crypto_enabled = 1;
 		nss_crypto_register_handler();
+#endif
 	}
 
 	if (npd->ipsec_enabled == NSS_FEATURE_ENABLED) {
@@ -431,6 +440,11 @@
 		nss_map_t_register_handler();
 	}
 
+	if (npd->gre_enabled == NSS_FEATURE_ENABLED) {
+		nss_top->gre_handler_id = nss_dev->id;
+		nss_gre_register_handler();
+	}
+
 	if (npd->tunipip6_enabled == NSS_FEATURE_ENABLED) {
 		nss_top->tunipip6_handler_id = nss_dev->id;
 		nss_tunipip6_register_handler();
@@ -626,4 +640,3 @@
 	nss_info("%p: All resources freed for nss core%d", nss_ctx, nss_dev->id);
 	return 0;
 }
-
diff --git a/nss_shaper.c b/nss_shaper.c
index 5eb35b4..70a71eb 100644
--- a/nss_shaper.c
+++ b/nss_shaper.c
@@ -1,6 +1,6 @@
 /*
  **************************************************************************
- * Copyright (c) 2014, 2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014, 2016-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.
@@ -290,13 +290,13 @@
 	}
 	spin_unlock_bh(&nss_top->lock);
 
-	status = nss_core_send_buffer(nss_ctx, if_num, skb, 0, H2N_BUFFER_SHAPER_BOUNCE_INTERFACE, 0);
+	status = nss_core_send_buffer(nss_ctx, if_num, skb, NSS_IF_DATA_QUEUE_0, H2N_BUFFER_SHAPER_BOUNCE_INTERFACE, 0);
 	if (status != NSS_CORE_STATUS_SUCCESS) {
 		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_CMD_REQ]);
+	NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_TX_PACKET]);
 	return NSS_TX_SUCCESS;
 }
 
@@ -334,14 +334,14 @@
 	spin_unlock_bh(&nss_top->lock);
 
 	nss_info("%s: Bridge bounce skb: %p, if_num: %u, ctx: %p", __func__, skb, if_num, nss_ctx);
-	status = nss_core_send_buffer(nss_ctx, if_num, skb, NSS_IF_CMD_QUEUE, H2N_BUFFER_SHAPER_BOUNCE_BRIDGE, 0);
+	status = nss_core_send_buffer(nss_ctx, if_num, skb, NSS_IF_DATA_QUEUE_0, H2N_BUFFER_SHAPER_BOUNCE_BRIDGE, 0);
 	if (status != NSS_CORE_STATUS_SUCCESS) {
 		nss_info("%s: Bridge bounce core send rejected", __func__);
 		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_CMD_REQ]);
+	NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_TX_PACKET]);
 	return NSS_TX_SUCCESS;
 }
 
diff --git a/nss_stats.c b/nss_stats.c
index b7f10d7..6fd1d8f 100644
--- a/nss_stats.c
+++ b/nss_stats.c
@@ -625,6 +625,50 @@
 	"MAP_T_V6_TO_V4_RULE_ERR_REMOTE_IPV4"
 };
 
+ /*
+ * nss_stats_str_gre_base_stats
+ *	GRE debug statistics strings for base types
+ */
+static int8_t *nss_stats_str_gre_base_debug_stats[NSS_STATS_GRE_BASE_DEBUG_MAX] = {
+	"GRE_BASE_RX_PACKETS",
+	"GRE_BASE_RX_DROPPED",
+	"GRE_BASE_EXP_ETH_HDR_MISSING",
+	"GRE_BASE_EXP_ETH_TYPE_NON_IP",
+	"GRE_BASE_EXP_IP_UNKNOWN_PROTOCOL",
+	"GRE_BASE_EXP_IP_HEADER_INCOMPLETE",
+	"GRE_BASE_EXP_IP_BAD_TOTAL_LENGTH",
+	"GRE_BASE_EXP_IP_BAD_CHECKSUM",
+	"GRE_BASE_EXP_IP_DATAGRAM_INCOMPLETE",
+	"GRE_BASE_EXP_IP_FRAGMENT",
+	"GRE_BASE_EXP_IP_OPTIONS_INCOMPLETE",
+	"GRE_BASE_EXP_IP_WITH_OPTIONS",
+	"GRE_BASE_EXP_IPV6_UNKNOWN_PROTOCOL",
+	"GRE_BASE_EXP_IPV6_HEADER_INCOMPLETE",
+	"GRE_BASE_EXP_GRE_UNKNOWN_SESSION",
+	"GRE_BASE_EXP_GRE_NODE_INACTIVE",
+};
+
+/*
+ * nss_stats_str_gre_session_stats
+ *	GRE debug statistics strings for sessions
+ */
+static int8_t *nss_stats_str_gre_session_debug_stats[NSS_STATS_GRE_SESSION_DEBUG_MAX] = {
+	"GRE_SESSION_PBUF_ALLOC_FAIL",
+	"GRE_SESSION_DECAP_FORWARD_ENQUEUE_FAIL",
+	"GRE_SESSION_ENCAP_FORWARD_ENQUEUE_FAIL",
+	"GRE_SESSION_DECAP_TX_FORWARDED",
+	"GRE_SESSION_ENCAP_RX_RECEIVED",
+	"GRE_SESSION_ENCAP_RX_DROPPED",
+	"GRE_SESSION_ENCAP_RX_LINEAR_FAIL",
+	"GRE_SESSION_EXP_RX_KEY_ERROR",
+	"GRE_SESSION_EXP_RX_SEQ_ERROR",
+	"GRE_SESSION_EXP_RX_CS_ERROR",
+	"GRE_SESSION_EXP_RX_FLAG_MISMATCH",
+	"GRE_SESSION_EXP_RX_MALFORMED",
+	"GRE_SESSION_EXP_RX_INVALID_PROTOCOL",
+	"GRE_SESSION_EXP_RX_NO_HEADROOM",
+};
+
 /*
  * nss_stats_str_ppe_conn
  *	PPE statistics strings for nss flow stats
@@ -2231,6 +2275,99 @@
 	return bytes_read;
 }
 
+ /*
+ * nss_stats_gre_read()
+ *	Read GRE statistics
+ */
+static ssize_t nss_stats_gre_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
+{
+	uint32_t max_output_lines = 2 /* header & footer for base debug stats */
+		+ 2 /* header & footer for session debug stats */
+		+ NSS_STATS_GRE_BASE_DEBUG_MAX  /* Base debug */
+		+ NSS_GRE_MAX_DEBUG_SESSION_STATS * (NSS_STATS_GRE_SESSION_DEBUG_MAX + 2) /*session stats */
+		+ 2;
+	size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
+	size_t size_wr = 0;
+	ssize_t bytes_read = 0;
+	struct net_device *dev;
+	struct nss_stats_gre_session_debug *sstats;
+	struct nss_stats_gre_base_debug *bstats;
+	int id, i;
+
+	char *lbuf = kzalloc(size_al, GFP_KERNEL);
+	if (unlikely(!lbuf)) {
+		nss_warning("Could not allocate memory for local statistics buffer");
+		return 0;
+	}
+
+	bstats = kzalloc(sizeof(struct nss_stats_gre_base_debug), GFP_KERNEL);
+	if (unlikely(!bstats)) {
+		nss_warning("Could not allocate memory for base debug statistics buffer");
+		kfree(lbuf);
+		return 0;
+	}
+
+	sstats = kzalloc(sizeof(struct nss_stats_gre_session_debug) * NSS_GRE_MAX_DEBUG_SESSION_STATS, GFP_KERNEL);
+	if (unlikely(!sstats)) {
+		nss_warning("Could not allocate memory for base debug statistics buffer");
+		kfree(lbuf);
+		kfree(bstats);
+		return 0;
+	}
+
+	/*
+	 * Get all base stats
+	 */
+	nss_gre_base_debug_stats_get((void *)bstats, sizeof(struct nss_stats_gre_base_debug));
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\ngre Base stats start:\n\n");
+	for (i = 0; i < NSS_STATS_GRE_BASE_DEBUG_MAX; i++) {
+		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
+				     "\t%s = %llu\n", nss_stats_str_gre_base_debug_stats[i],
+				     bstats->stats[i]);
+	}
+
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\ngre Base stats End\n\n");
+
+	/*
+	 * Get all session stats
+	 */
+	nss_gre_session_debug_stats_get(sstats, sizeof(struct nss_stats_gre_session_debug) * NSS_GRE_MAX_DEBUG_SESSION_STATS);
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\ngre Session stats start:\n\n");
+
+	for (id = 0; id < NSS_GRE_MAX_DEBUG_SESSION_STATS; id++) {
+
+		if (!((sstats + id)->valid)) {
+			continue;
+		}
+
+		dev = dev_get_by_index(&init_net, (sstats + id)->if_index);
+		if (likely(dev)) {
+
+			size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "%d. nss interface id=%d, netdevice=%s\n", id,
+					     (sstats + id)->if_num, dev->name);
+			dev_put(dev);
+		} else {
+			size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "%d. nss interface id=%d\n", id,
+					     (sstats + id)->if_num);
+		}
+
+		for (i = 0; i < NSS_STATS_GRE_SESSION_DEBUG_MAX; i++) {
+			size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
+					     "\t%s = %llu\n", nss_stats_str_gre_session_debug_stats[i],
+					     (sstats + id)->stats[i]);
+		}
+		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\n");
+	}
+
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\ngre Session stats end\n");
+	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, size_wr);
+
+	kfree(sstats);
+	kfree(bstats);
+	kfree(lbuf);
+	return bytes_read;
+}
+
 /*
  * nss_stats_ppe_conn_read()
  *	Read ppe connection stats
@@ -2248,7 +2385,6 @@
 				+ 2;
 	size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
 
-
 	lbuf = kzalloc(size_al, GFP_KERNEL);
 	if (unlikely(lbuf == NULL)) {
 		nss_warning("Could not allocate memory for local statistics buffer");
@@ -3317,6 +3453,11 @@
 NSS_STATS_DECLARE_FILE_OPERATIONS(map_t)
 
 /*
+ * gre_stats_ops
+ */
+NSS_STATS_DECLARE_FILE_OPERATIONS(gre)
+
+/*
  * ppe_stats_ops
  */
 NSS_STATS_DECLARE_FILE_OPERATIONS(ppe_conn)
@@ -3817,6 +3958,16 @@
 	}
 
 	/*
+	 *  GRE statistics
+	 */
+	nss_top_main.gre_dentry = debugfs_create_file("gre", 0400,
+						nss_top_main.stats_dentry, &nss_top_main, &nss_stats_gre_ops);
+	if (unlikely(nss_top_main.gre_dentry == NULL)) {
+		nss_warning("Failed to create qca-nss-drv/stats/gre file in debugfs");
+		return;
+	}
+
+	/*
 	 *  PPE Stats
 	 */
 	nss_top_main.ppe_dentry = debugfs_create_dir("ppe", nss_top_main.stats_dentry);
diff --git a/nss_tx_rx_common.h b/nss_tx_rx_common.h
index ef7894a..5882507 100644
--- a/nss_tx_rx_common.h
+++ b/nss_tx_rx_common.h
@@ -178,6 +178,7 @@
  */
 void nss_phys_if_register_handler(uint32_t if_num);
 extern void nss_crypto_register_handler(void);
+extern void nss_crypto_cmn_register_handler(void);
 extern void nss_ipsec_register_handler(void);
 extern void nss_ipv4_register_handler(void);
 extern void nss_ipv4_reasm_register_handler(void);
diff --git a/nss_wifi.c b/nss_wifi.c
index da48f09..f0a3b17 100644
--- a/nss_wifi.c
+++ b/nss_wifi.c
@@ -71,6 +71,14 @@
 	spin_unlock_bh(&nss_top->stats_lock);
 }
 
+/*
+ * nss_wifi_get_context()
+ *	Get NSS context of Wifi.
+ */
+struct nss_ctx_instance *nss_wifi_get_context()
+{
+	return (struct nss_ctx_instance *)&nss_top_main.nss[nss_top_main.wifi_handler_id];
+}
 
 /*
  * nss_wifi_handler()
@@ -269,6 +277,7 @@
 	nss_core_register_handler(NSS_WIFI_INTERFACE2, nss_wifi_handler, NULL);
 }
 
+EXPORT_SYMBOL(nss_wifi_get_context);
 EXPORT_SYMBOL(nss_wifi_tx_msg);
 EXPORT_SYMBOL(nss_register_wifi_if);
 EXPORT_SYMBOL(nss_unregister_wifi_if);
diff --git a/nss_wifi_vdev.c b/nss_wifi_vdev.c
index 452c54e..76ab99c 100644
--- a/nss_wifi_vdev.c
+++ b/nss_wifi_vdev.c
@@ -238,6 +238,32 @@
 }
 
 /*
+ * nss_wifi_vdev_set_next_hop()
+ */
+nss_tx_status_t nss_wifi_vdev_set_next_hop(struct nss_ctx_instance *ctx, int if_num, int next_hop)
+{
+	nss_tx_status_t status;
+	struct nss_wifi_vdev_msg *wifivdevmsg = kzalloc(sizeof(struct nss_wifi_vdev_msg), GFP_KERNEL);
+	struct nss_wifi_vdev_set_next_hop_msg *next_hop_msg = &wifivdevmsg->msg.next_hop;
+
+	if (!wifivdevmsg) {
+		nss_warning("%p: Unable to allocate next hop message", ctx);
+		return NSS_TX_FAILURE;
+	}
+
+	next_hop_msg->ifnumber = next_hop;
+	nss_wifi_vdev_msg_init(wifivdevmsg, if_num, NSS_WIFI_VDEV_SET_NEXT_HOP, 0, NULL, NULL);
+
+	status = nss_wifi_vdev_tx_msg(ctx, wifivdevmsg);
+	if (status != NSS_TX_SUCCESS) {
+		nss_warning("%p: Unable to send next hop message", ctx);
+	}
+
+	kfree(wifivdevmsg);
+	return status;
+}
+
+/*
  ***********************************
  * Register/Unregister/Miscellaneous APIs
  ***********************************
@@ -294,5 +320,6 @@
 EXPORT_SYMBOL(nss_wifi_vdev_msg_init);
 EXPORT_SYMBOL(nss_wifi_vdev_tx_msg);
 EXPORT_SYMBOL(nss_wifi_vdev_tx_buf);
+EXPORT_SYMBOL(nss_wifi_vdev_set_next_hop);
 EXPORT_SYMBOL(nss_register_wifi_vdev_if);
 EXPORT_SYMBOL(nss_unregister_wifi_vdev_if);