Merge "[qca-nss-drv] Set not leak to remove meminfo allocation memleak list"
diff --git a/Makefile b/Makefile
index c4b4843..4ac93da 100644
--- a/Makefile
+++ b/Makefile
@@ -165,7 +165,10 @@
 			nss_crypto_cmn.o \
 			nss_crypto_cmn_log.o \
 			nss_ipsec_cmn_log.o \
-			nss_ipsec_cmn.o
+			nss_ipsec_cmn.o \
+			nss_qvpn.o \
+			nss_qvpn_stats.o \
+			nss_qvpn_log.o
 ccflags-y += -I$(obj)/nss_hal/ipq60xx -DNSS_HAL_IPQ60XX_SUPPORT -DNSS_MULTI_H2N_DATA_RING_SUPPORT
 endif
 
diff --git a/exports/nss_dynamic_interface.h b/exports/nss_dynamic_interface.h
index 54cf56c..05104ac 100644
--- a/exports/nss_dynamic_interface.h
+++ b/exports/nss_dynamic_interface.h
@@ -81,9 +81,9 @@
 	NSS_DYNAMIC_INTERFACE_TYPE_PPTP_OUTER,
 	NSS_DYNAMIC_INTERFACE_TYPE_PPTP_HOST_INNER,
 	NSS_DYNAMIC_INTERFACE_TYPE_IPSEC_CMN_INNER,
-	NSS_DYNAMIC_INTERFACE_TYPE_IPSEC_CMN_INNER_BOUNCE,
+	NSS_DYNAMIC_INTERFACE_TYPE_IPSEC_CMN_MDATA_INNER,
 	NSS_DYNAMIC_INTERFACE_TYPE_IPSEC_CMN_OUTER,
-	NSS_DYNAMIC_INTERFACE_TYPE_IPSEC_CMN_OUTER_BOUNCE,
+	NSS_DYNAMIC_INTERFACE_TYPE_IPSEC_CMN_MDATA_OUTER,
 	NSS_DYNAMIC_INTERFACE_TYPE_IPSEC_CMN_REDIRECT,
 	NSS_DYNAMIC_INTERFACE_TYPE_PVXLAN_HOST_INNER,
 	NSS_DYNAMIC_INTERFACE_TYPE_PVXLAN_OUTER,
diff --git a/exports/nss_ipsec_cmn.h b/exports/nss_ipsec_cmn.h
index 524d757..13ccd37 100644
--- a/exports/nss_ipsec_cmn.h
+++ b/exports/nss_ipsec_cmn.h
@@ -50,6 +50,10 @@
 
 #define NSS_IPSEC_CMN_FEATURE_INLINE_ACCEL 0x1		/**< Interface enabled for inline exception. */
 
+#define NSS_IPSEC_CMN_MDATA_VERSION 0x01		/**< Metadata version. */
+#define NSS_IPSEC_CMN_MDATA_MAGIC 0x8893		/**< Metadata magic. */
+#define NSS_IPSEC_CMN_MDATA_ORIGIN_HOST 0x01		/**< Metadata originates at the host. */
+#define NSS_IPSEC_CMN_MDATA_ALIGN_SZ sizeof(uint32_t)	/**< Metadata alignment size. */
 /**
  * nss_ipsec_cmn_msg_type
  *	IPsec message types.
@@ -95,9 +99,9 @@
 enum nss_ipsec_cmn_ctx_type {
 	NSS_IPSEC_CMN_CTX_TYPE_NONE = 0,	/**< Invalid direction. */
 	NSS_IPSEC_CMN_CTX_TYPE_INNER,		/**< Encapsulation. */
-	NSS_IPSEC_CMN_CTX_TYPE_INNER_BOUNCE,	/**< Inner bounce */
+	NSS_IPSEC_CMN_CTX_TYPE_MDATA_INNER,	/**< Metadata for encapsulation. */
 	NSS_IPSEC_CMN_CTX_TYPE_OUTER,		/**< Decapsulation. */
-	NSS_IPSEC_CMN_CTX_TYPE_OUTER_BOUNCE,	/**< Outer bounce. */
+	NSS_IPSEC_CMN_CTX_TYPE_MDATA_OUTER,	/**< Metadata for decapsulation. */
 	NSS_IPSEC_CMN_CTX_TYPE_REDIR,		/**< Redirect. */
 	NSS_IPSEC_CMN_CTX_TYPE_MAX
 };
@@ -282,6 +286,49 @@
 };
 
 /**
+ * nss_ipsec_cmn_mdata_cmn
+ *	IPsec common metadata information.
+ */
+struct nss_ipsec_cmn_mdata_cmn {
+	uint8_t version;		/**< Metadata version. */
+	uint8_t origin;			/**< Metadata origin (host or NSS). */
+	uint16_t len;			/**< Metadata length including extra bytes. */
+	uint8_t res[2];			/**< Reserved for future. */
+	uint16_t magic;			/**< Metadata magic. */
+};
+
+/**
+ * nss_ipsec_cmn_mdata_encap
+ *	IPsec encapsulation metadata information.
+ */
+struct nss_ipsec_cmn_mdata_encap {
+	struct nss_ipsec_cmn_sa_tuple sa;	/**< SA tuple. */
+	uint32_t seq_num;			/**< Sequence number for encapsulation (zero disables it). */
+	uint32_t flags;				/**< Encapsulation metadata flags. */
+};
+
+/**
+ * nss_ipsec_cmn_mdata_decap
+ *	IPsec decapsulation metadata information.
+ */
+struct nss_ipsec_cmn_mdata_decap {
+	struct nss_ipsec_cmn_sa_tuple sa;	/**< SA tuple. */
+};
+
+/**
+ * nss_ipsec_cmn_mdata
+ *	IPsec metadata for host originated packets.
+ */
+struct nss_ipsec_cmn_mdata {
+	struct nss_ipsec_cmn_mdata_cmn cm;		/**< Common metadata. */
+
+	union {
+		struct nss_ipsec_cmn_mdata_encap encap;	/**< Encapsulation metadata. */
+		struct nss_ipsec_cmn_mdata_decap decap;	/**< Decapsulation metadata. */
+	} data;						/**< Metadata payload. */
+};
+
+/**
  * nss_ipsec_cmn_msg
  *	Message structure for NSS IPsec messages.
  */
@@ -302,6 +349,29 @@
 };
 
 /**
+ * nss_ipsec_cmn_mdata_init
+ *	Initialize the metadata common fields.
+ *
+ * @datatypes
+ * nss_ipsec_cmn_mdata
+ *
+ * @param[in] mdata Metadata pointer.
+ * @param[in] len   Metadata length including extra bytes.
+ *
+ * @return
+ * Pointer to metadata payload.
+ */
+static inline void *nss_ipsec_cmn_mdata_init(struct nss_ipsec_cmn_mdata *mdata, uint16_t len)
+{
+	mdata->cm.len = len;
+	mdata->cm.magic = NSS_IPSEC_CMN_MDATA_MAGIC;
+	mdata->cm.version = NSS_IPSEC_CMN_MDATA_VERSION;
+	mdata->cm.origin = NSS_IPSEC_CMN_MDATA_ORIGIN_HOST;
+
+	return &mdata->data;
+}
+
+/**
  * Callback function for receiving message notifications.
  *
  * @datatypes
diff --git a/exports/nss_l2tpv2.h b/exports/nss_l2tpv2.h
index 6e45b80..a231f33 100644
--- a/exports/nss_l2tpv2.h
+++ b/exports/nss_l2tpv2.h
@@ -1,6 +1,6 @@
 /*
  **************************************************************************
- * Copyright (c) 2015, 2017-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015, 2017-2019, 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.
@@ -40,6 +40,7 @@
 	NSS_L2TPV2_MSG_SESSION_CREATE,
 	NSS_L2TPV2_MSG_SESSION_DESTROY,
 	NSS_L2TPV2_MSG_SYNC_STATS,
+	NSS_L2TPV2_MSG_BIND_IPSEC_IF,
 	NSS_L2TPV2_MSG_MAX
 };
 
@@ -76,6 +77,18 @@
 };
 
 /**
+ * nss_l2tpv2_bind_ipsec_if_msg
+ *	Message for binding IPsec interface with L2TP.
+ *
+ * Message for configuring the L2TP session with an
+ * IPsec inner interface number. This is used when
+ * L2TP tunnel is enabled with IPsec.
+ */
+struct nss_l2tpv2_bind_ipsec_if_msg {
+	uint32_t ipsec_ifnum;	/**< Inner IPSec interface number. */
+};
+
+/**
  * nss_l2tpv2_sync_session_stats_msg
  *	Message information for L2TPV2 synchronization statistics.
  */
@@ -100,6 +113,8 @@
 				/**< Buffer allocation failure during encapsulation. */
 		uint32_t decap_pbuf_alloc_fail;
 				/**< Buffer allocation failure during decapsulation. */
+		uint32_t decap_l2tpoipsec_src_error;
+				/**< Packets dropped due to wrong source for L2TPoIPsec flow. */
 	} debug_stats;	/**< Debug statistics object for l2tp v2. */
 };
 
@@ -120,6 +135,8 @@
 				/**< Session delete message. */
 		struct nss_l2tpv2_sync_session_stats_msg stats;
 				/**< Session statistics. */
+		struct nss_l2tpv2_bind_ipsec_if_msg bind_ipsec_if_msg;
+				/**< Bind IPsec interface message. */
 	} msg;			/**< Message payload. */
 };
 
diff --git a/exports/nss_pppoe.h b/exports/nss_pppoe.h
index 07f05bb..1df5828 100644
--- a/exports/nss_pppoe.h
+++ b/exports/nss_pppoe.h
@@ -45,14 +45,28 @@
 };
 
 /**
- * nss_pppoe_exception_events
- *	Exception events from the PPPoE handler.
+ * nss_pppoe_session_exception_events
+ *	Session exception events from the PPPoE handler.
  */
-enum nss_pppoe_exception_events {
-	NSS_PPPOE_EXCEPTION_EVENT_WRONG_VERSION_OR_TYPE,
-	NSS_PPPOE_EXCEPTION_EVENT_WRONG_CODE,
-	NSS_PPPOE_EXCEPTION_EVENT_UNSUPPORTED_PPP_PROTOCOL,
-	NSS_PPPOE_EXCEPTION_EVENT_MAX
+enum nss_pppoe_session_exception_events {
+	NSS_PPPOE_SESSION_EXCEPTION_EVENT_WRONG_VERSION_OR_TYPE,
+	NSS_PPPOE_SESSION_EXCEPTION_EVENT_WRONG_CODE,
+	NSS_PPPOE_SESSION_EXCEPTION_EVENT_UNSUPPORTED_PPP_PROTOCOL,
+	NSS_PPPOE_SESSION_EXCEPTION_EVENT_MAX
+};
+
+/**
+ * pppoe_base_exception_events
+ * 	Base node exception events from the PPPoE handler.
+ */
+enum nss_pppoe_base_exception_events {
+	NSS_PPPOE_BASE_EXCEPTION_EVENT_SHORT_PPPOE_HDR_LENGTH,
+	NSS_PPPOE_BASE_EXCEPTION_EVENT_SHORT_PACKET_LENGTH,
+	NSS_PPPOE_BASE_EXCEPTION_EVENT_WRONG_VERSION_OR_TYPE,
+	NSS_PPPOE_BASE_EXCEPTION_EVENT_WRONG_CODE,
+	NSS_PPPOE_BASE_EXCEPTION_EVENT_UNSUPPORTED_PPP_PROTOCOL,
+	NSS_PPPOE_BASE_EXCEPTION_EVENT_DISABLED_BRIDGE_PACKET,
+	NSS_PPPOE_BASE_EXCEPTION_EVENT_MAX
 };
 
 /**
@@ -67,13 +81,32 @@
 };
 
 /**
+ * nss_pppoe_base_stats
+ * 	PPPoE base node synchronization statistics.
+ */
+struct nss_pppoe_base_stats {
+	struct nss_cmn_node_stats node;	/**< Common node statistics. */
+	uint32_t exception[NSS_PPPOE_BASE_EXCEPTION_EVENT_MAX];
+						/**< PPPoE base node exception events. */
+};
+
+/**
+ * nss_pppoe_session_stats
+ * 	PPPoE synchronization statistics per session.
+ */
+struct nss_pppoe_session_stats {
+	struct nss_cmn_node_stats node;	/**< Common node statistics. */
+	uint32_t exception[NSS_PPPOE_SESSION_EXCEPTION_EVENT_MAX];
+						/**< PPPoE session exception events. */
+};
+
+/**
  * nss_pppoe_sync_stats_msg
- *	PPPoE node synchronization statistics.
+ *	PPPoE synchronization statistics.
  */
 struct nss_pppoe_sync_stats_msg {
-	struct nss_cmn_node_stats stats;	/**< Common node statistics. */
-	uint32_t exception_events[NSS_PPPOE_EXCEPTION_EVENT_MAX];
-			/**< PPPoE exception events. */
+	struct nss_pppoe_session_stats session_stats;	/**< Session statistics. */
+	struct nss_pppoe_base_stats base_stats;		/**< Base node statistics. */
 };
 
 /**
diff --git a/nss_c2c_rx.c b/nss_c2c_rx.c
index 732a288..e67512e 100644
--- a/nss_c2c_rx.c
+++ b/nss_c2c_rx.c
@@ -1,6 +1,6 @@
 /*
  **************************************************************************
- * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018-2019, 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.
@@ -99,6 +99,9 @@
 void nss_c2c_rx_register_handler(struct nss_ctx_instance *nss_ctx)
 {
 	nss_core_register_handler(nss_ctx, NSS_C2C_RX_INTERFACE, nss_c2c_rx_interface_handler, NULL);
-	nss_c2c_rx_stats_dentry_create();
+
+	if (nss_ctx->id == NSS_CORE_0) {
+		nss_c2c_rx_stats_dentry_create();
+	}
 }
 EXPORT_SYMBOL(nss_c2c_rx_register_handler);
diff --git a/nss_c2c_tx.c b/nss_c2c_tx.c
index 683c13b..64e6d08 100644
--- a/nss_c2c_tx.c
+++ b/nss_c2c_tx.c
@@ -1,6 +1,6 @@
 /*
  **************************************************************************
- * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018-2019, 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.
@@ -134,7 +134,10 @@
 {
 	nss_info("%p: nss_c2c_tx_register_handler", nss_ctx);
 	nss_core_register_handler(nss_ctx, NSS_C2C_TX_INTERFACE, nss_c2c_tx_msg_handler, NULL);
-	nss_c2c_tx_stats_dentry_create();
+
+	if (nss_ctx->id == NSS_CORE_0) {
+		nss_c2c_tx_stats_dentry_create();
+	}
 }
 EXPORT_SYMBOL(nss_c2c_tx_register_handler);
 
diff --git a/nss_core.c b/nss_core.c
index 595d8ef..c2021e9 100644
--- a/nss_core.c
+++ b/nss_core.c
@@ -633,7 +633,7 @@
 
 	uint16_t queue_offset = 0;
 
-	NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_top->stats_drv[NSS_STATS_DRV_RX_VIRTUAL]);
+	NSS_PKT_STATS_INC(&nss_top->stats_drv[NSS_STATS_DRV_RX_VIRTUAL]);
 
 	/*
 	 * Checksum is already done by NSS for packets forwarded to virtual interfaces
@@ -725,7 +725,7 @@
 	nss_phys_if_rx_callback_t cb;
 	uint16_t queue_offset = qid - NSS_IF_N2H_DATA_QUEUE_0;
 
-	NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_top->stats_drv[NSS_STATS_DRV_RX_PACKET]);
+	NSS_PKT_STATS_INC(&nss_top->stats_drv[NSS_STATS_DRV_RX_PACKET]);
 
 	/*
 	 * Check if NSS was able to obtain checksum
@@ -808,7 +808,7 @@
 	struct net_device *ndev = NULL;
 	nss_phys_if_rx_ext_data_callback_t ext_cb;
 
-	NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_top->stats_drv[NSS_STATS_DRV_RX_PACKET]);
+	NSS_PKT_STATS_INC(&nss_top->stats_drv[NSS_STATS_DRV_RX_PACKET]);
 
 	/*
 	 * Check if NSS was able to obtain checksum
@@ -847,7 +847,7 @@
 	struct nss_shaper_bounce_registrant *reg = NULL;
 	int32_t status;
 
-	NSS_PKT_STATS_DECREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_NSS_SKB_COUNT]);
+	NSS_PKT_STATS_DEC(&nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_NSS_SKB_COUNT]);
 
 	if (interface_num >= NSS_MAX_NET_INTERFACES) {
 		nss_warning("%p: Invalid interface_num: %d", nss_ctx, interface_num);
@@ -879,6 +879,10 @@
 		break;
 
 	case N2H_BUFFER_SHAPER_BOUNCED_INTERFACE:
+		reg = &nss_ctx->nss_top->bounce_interface_registrants[interface_num];
+		nss_core_handle_bounced_pkt(nss_ctx, reg, nbuf);
+		break;
+
 	case N2H_BUFFER_SHAPER_BOUNCED_BRIDGE:
 		reg = &nss_ctx->nss_top->bounce_bridge_registrants[interface_num];
 		nss_core_handle_bounced_pkt(nss_ctx, reg, nbuf);
@@ -889,13 +893,13 @@
 		break;
 
 	case N2H_BUFFER_STATUS:
-		NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_RX_STATUS]);
+		NSS_PKT_STATS_INC(&nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_RX_STATUS]);
 		nss_core_handle_nss_status_pkt(nss_ctx, nbuf);
 		dev_kfree_skb_any(nbuf);
 		break;
 
 	case N2H_BUFFER_CRYPTO_RESP:
-		NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_RX_CRYPTO_RESP]);
+		NSS_PKT_STATS_INC(&nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_RX_CRYPTO_RESP]);
 		nss_core_handle_crypto_pkt(nss_ctx, interface_num, nbuf, napi);
 		break;
 
@@ -908,7 +912,7 @@
 		 * They are again marked with H2N_BUFFER_RATE_TEST buffer type so NSS can process
 		 * and count the test packets properly.
 		 */
-		NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_RX_STATUS]);
+		NSS_PKT_STATS_INC(&nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_RX_STATUS]);
 		status = nss_core_send_buffer(nss_ctx, 0, nbuf, NSS_IF_H2N_DATA_QUEUE, H2N_BUFFER_RATE_TEST, 0);
 		if (unlikely(status != NSS_CORE_STATUS_SUCCESS)) {
 			dev_kfree_skb_any(nbuf);
@@ -974,7 +978,7 @@
 	/*
 	 * Track Number of Fragments processed. First && Last is not true fragment
 	 */
-	NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_FRAG_SEG_PROCESSED]);
+	NSS_PKT_STATS_INC(&nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_FRAG_SEG_PROCESSED]);
 
 	/*
 	 * NSS sent us an SG chain.
@@ -1010,7 +1014,7 @@
 		return false;
 	}
 
-	NSS_PKT_STATS_DECREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_NSS_SKB_COUNT]);
+	NSS_PKT_STATS_DEC(&nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_NSS_SKB_COUNT]);
 
 	/*
 	 * We've received a middle or a last segment.
@@ -1106,14 +1110,14 @@
 		 * NSS should playaround with data area and should not
 		 * touch HEADROOM area
 		 */
-		NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_RX_SIMPLE]);
+		NSS_PKT_STATS_INC(&nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_RX_SIMPLE]);
 		return true;
 	}
 
 	/*
 	 * Track number of skb chain processed. First && Last is not true segment.
 	 */
-	NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_CHAIN_SEG_PROCESSED]);
+	NSS_PKT_STATS_INC(&nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_CHAIN_SEG_PROCESSED]);
 
 	/*
 	 * NSS sent us an SG chain.
@@ -1127,7 +1131,7 @@
 		 */
 		if (unlikely(head)) {
 			nss_warning("%p: received the second head before a last", head);
-			NSS_PKT_STATS_DECREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_NSS_SKB_COUNT]);
+			NSS_PKT_STATS_DEC(&nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_NSS_SKB_COUNT]);
 			dev_kfree_skb_any(head);
 		}
 
@@ -1139,7 +1143,7 @@
 			 * We don't support chain in a chain.
 			 */
 			nss_warning("%p: skb already has a fraglist", nbuf);
-			NSS_PKT_STATS_DECREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_NSS_SKB_COUNT]);
+			NSS_PKT_STATS_DEC(&nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_NSS_SKB_COUNT]);
 			dev_kfree_skb_any(nbuf);
 			return false;
 		}
@@ -1157,7 +1161,7 @@
 		return false;
 	}
 
-	NSS_PKT_STATS_DECREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_NSS_SKB_COUNT]);
+	NSS_PKT_STATS_DEC(&nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_NSS_SKB_COUNT]);
 
 	/*
 	 * We've received a middle segment.
@@ -1211,7 +1215,7 @@
 	*nbuf_ptr = head;
 	*head_ptr = NULL;
 	*tail_ptr = NULL;
-	NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_RX_SKB_FRAGLIST]);
+	NSS_PKT_STATS_INC(&nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_RX_SKB_FRAGLIST]);
 	return true;
 }
 
@@ -1261,15 +1265,15 @@
 			 * Invalid opaque pointer
 			 */
 			nss_dump_desc(nss_ctx, desc);
-			NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_RX_BAD_DESCRIPTOR]);
+			NSS_PKT_STATS_INC(&nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_RX_BAD_DESCRIPTOR]);
 			goto next;
 		}
 
 		dma_unmap_single(nss_ctx->dev, (desc->buffer + desc->payload_offs), desc->payload_len, DMA_TO_DEVICE);
 		dev_kfree_skb_any(nbuf);
 
-		NSS_PKT_STATS_DECREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_NSS_SKB_COUNT]);
-		NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_RX_EMPTY]);
+		NSS_PKT_STATS_DEC(&nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_NSS_SKB_COUNT]);
+		NSS_PKT_STATS_INC(&nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_RX_EMPTY]);
 
 next:
 		hlos_index = (hlos_index + 1) & (mask);
@@ -1397,7 +1401,7 @@
 			 * Invalid opaque pointer
 			 */
 			nss_dump_desc(nss_ctx, desc);
-			NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_RX_BAD_DESCRIPTOR]);
+			NSS_PKT_STATS_INC(&nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_RX_BAD_DESCRIPTOR]);
 			goto next;
 		}
 
@@ -1431,7 +1435,7 @@
 				nss_warning("%p: we should not have an incomplete paged skb while"
 								" constructing a linear skb %p", nbuf, n2h_desc_ring->head);
 
-				NSS_PKT_STATS_DECREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_NSS_SKB_COUNT]);
+				NSS_PKT_STATS_DEC(&nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_NSS_SKB_COUNT]);
 				dev_kfree_skb_any(n2h_desc_ring->head);
 				n2h_desc_ring->head = NULL;
 			}
@@ -1439,7 +1443,7 @@
 			if (!nss_core_handle_nr_frag_skb(nss_ctx, &nbuf, &n2h_desc_ring->jumbo_start, desc, buffer_type)) {
 				goto next;
 			}
-			NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_RX_NR_FRAGS]);
+			NSS_PKT_STATS_INC(&nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_RX_NR_FRAGS]);
 			goto consume;
 		}
 
@@ -1451,7 +1455,7 @@
 			nss_warning("%p: we should not have an incomplete linear skb while"
 							" constructing a paged skb %p", nbuf, n2h_desc_ring->jumbo_start);
 
-			NSS_PKT_STATS_DECREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_NSS_SKB_COUNT]);
+			NSS_PKT_STATS_DEC(&nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_NSS_SKB_COUNT]);
 			dev_kfree_skb_any(n2h_desc_ring->jumbo_start);
 			n2h_desc_ring->jumbo_start = NULL;
 		}
@@ -1577,7 +1581,7 @@
 			/*
 			 * ERR:
 			 */
-			NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_top->stats_drv[alloc_fail_count]);
+			NSS_PKT_STATS_INC(&nss_top->stats_drv[alloc_fail_count]);
 			nss_warning("%p: Could not obtain empty paged buffer", nss_ctx);
 			break;
 		}
@@ -1588,7 +1592,7 @@
 			 * ERR:
 			 */
 			dev_kfree_skb_any(nbuf);
-			NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_top->stats_drv[alloc_fail_count]);
+			NSS_PKT_STATS_INC(&nss_top->stats_drv[alloc_fail_count]);
 			nss_warning("%p: Could not obtain empty page", nss_ctx);
 			break;
 		}
@@ -1619,7 +1623,7 @@
 		 * We are holding this skb in NSS FW, let kmemleak know about it
 		 */
 		kmemleak_not_leak(nbuf);
-		NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_NSS_SKB_COUNT]);
+		NSS_PKT_STATS_INC(&nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_NSS_SKB_COUNT]);
 		desc->opaque = (nss_ptr_t)nbuf;
 		desc->buffer = buffer;
 		desc->buffer_type = buffer_type;
@@ -1644,7 +1648,7 @@
 	NSS_CORE_DMA_CACHE_MAINT(&if_map->h2n_hlos_index[buffer_queue], sizeof(uint32_t), DMA_TO_DEVICE);
 	NSS_CORE_DSB();
 
-	NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_top->stats_drv[stats_index]);
+	NSS_PKT_STATS_INC(&nss_top->stats_drv[stats_index]);
 }
 
 /*
@@ -1669,7 +1673,7 @@
 			/*
 			 * ERR:
 			 */
-			NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_top->stats_drv[NSS_STATS_DRV_NBUF_ALLOC_FAILS]);
+			NSS_PKT_STATS_INC(&nss_top->stats_drv[NSS_STATS_DRV_NBUF_ALLOC_FAILS]);
 			nss_warning("%p: Could not obtain empty jumbo mru buffer", nss_ctx);
 			break;
 		}
@@ -1693,7 +1697,7 @@
 		 * We are holding this skb in NSS FW, let kmemleak know about it
 		 */
 		kmemleak_not_leak(nbuf);
-		NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_NSS_SKB_COUNT]);
+		NSS_PKT_STATS_INC(&nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_NSS_SKB_COUNT]);
 		desc->opaque = (nss_ptr_t)nbuf;
 		desc->buffer = buffer;
 		desc->buffer_type = H2N_BUFFER_EMPTY;
@@ -1718,7 +1722,7 @@
 	NSS_CORE_DMA_CACHE_MAINT(&if_map->h2n_hlos_index[NSS_IF_H2N_EMPTY_BUFFER_QUEUE], sizeof(uint32_t), DMA_TO_DEVICE);
 	NSS_CORE_DSB();
 
-	NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_top->stats_drv[NSS_STATS_DRV_TX_EMPTY]);
+	NSS_PKT_STATS_INC(&nss_top->stats_drv[NSS_STATS_DRV_TX_EMPTY]);
 }
 
 /*
@@ -1745,7 +1749,7 @@
 			/*
 			 * ERR:
 			 */
-			NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_top->stats_drv[NSS_STATS_DRV_NBUF_ALLOC_FAILS]);
+			NSS_PKT_STATS_INC(&nss_top->stats_drv[NSS_STATS_DRV_NBUF_ALLOC_FAILS]);
 			nss_warning("%p: Could not obtain empty buffer", nss_ctx);
 			break;
 		}
@@ -1768,7 +1772,7 @@
 		 * We are holding this skb in NSS FW, let kmemleak know about it
 		 */
 		kmemleak_not_leak(nbuf);
-		NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_NSS_SKB_COUNT]);
+		NSS_PKT_STATS_INC(&nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_NSS_SKB_COUNT]);
 
 		desc->opaque = (nss_ptr_t)nbuf;
 		desc->buffer = buffer;
@@ -1807,7 +1811,7 @@
 	NSS_CORE_DMA_CACHE_MAINT(&if_map->h2n_hlos_index[NSS_IF_H2N_EMPTY_BUFFER_QUEUE], sizeof(uint32_t), DMA_TO_DEVICE);
 	NSS_CORE_DSB();
 
-	NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_top->stats_drv[NSS_STATS_DRV_TX_EMPTY]);
+	NSS_PKT_STATS_INC(&nss_top->stats_drv[NSS_STATS_DRV_TX_EMPTY]);
 }
 
 /*
@@ -2429,6 +2433,7 @@
 	bit_flags = flags | H2N_BIT_FLAG_FIRST_SEGMENT | H2N_BIT_FLAG_LAST_SEGMENT;
 	if (likely(nbuf->ip_summed == CHECKSUM_PARTIAL)) {
 		bit_flags |= H2N_BIT_FLAG_GEN_IP_TRANSPORT_CHECKSUM;
+		bit_flags |= H2N_BIT_FLAG_GEN_IPV4_IP_CHECKSUM;
 	} else if (nbuf->ip_summed == CHECKSUM_UNNECESSARY) {
 		bit_flags |= H2N_BIT_FLAG_GEN_IP_TRANSPORT_CHECKSUM_NONE;
 	}
@@ -2469,7 +2474,7 @@
 	 */
 	nss_skb_reuse(nbuf);
 
-	NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_TX_BUFFER_REUSE]);
+	NSS_PKT_STATS_INC(&nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_TX_BUFFER_REUSE]);
 	return 1;
 
 no_reuse:
@@ -2487,7 +2492,7 @@
 
 	NSS_CORE_DMA_CACHE_MAINT((void *)desc, sizeof(*desc), DMA_TO_DEVICE);
 
-	NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_TX_SIMPLE]);
+	NSS_PKT_STATS_INC(&nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_TX_SIMPLE]);
 	return 1;
 }
 
@@ -2523,6 +2528,7 @@
 	bit_flags = (flags | H2N_BIT_FLAG_DISCARD);
 	if (likely(nbuf->ip_summed == CHECKSUM_PARTIAL)) {
 		bit_flags |= H2N_BIT_FLAG_GEN_IP_TRANSPORT_CHECKSUM;
+		bit_flags |= H2N_BIT_FLAG_GEN_IPV4_IP_CHECKSUM;
 	}
 
 	mask = desc_if->size - 1;
@@ -2577,7 +2583,7 @@
 
 	NSS_CORE_DMA_CACHE_MAINT((void *)desc, sizeof(*desc), DMA_TO_DEVICE);
 
-	NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_TX_NR_FRAGS]);
+	NSS_PKT_STATS_INC(&nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_TX_NR_FRAGS]);
 	return i+1;
 }
 
@@ -2612,6 +2618,7 @@
 	bit_flags = flags;
 	if (likely(nbuf->ip_summed == CHECKSUM_PARTIAL)) {
 		bit_flags |= H2N_BIT_FLAG_GEN_IP_TRANSPORT_CHECKSUM;
+		bit_flags |= H2N_BIT_FLAG_GEN_IPV4_IP_CHECKSUM;
 	}
 
 	mask = desc_if->size - 1;
@@ -2678,7 +2685,7 @@
 	desc->bit_flags |= H2N_BIT_FLAG_LAST_SEGMENT;
 	NSS_CORE_DMA_CACHE_MAINT((void *)desc, sizeof(*desc), DMA_TO_DEVICE);
 
-	NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_TX_FRAGLIST]);
+	NSS_PKT_STATS_INC(&nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_TX_FRAGLIST]);
 	return i+1;
 }
 
@@ -2758,9 +2765,9 @@
 
 #if (NSS_PKT_STATS_ENABLED == 1)
 		if (nss_ctx->id == NSS_CORE_0) {
-			NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_TX_QUEUE_FULL_0]);
+			NSS_PKT_STATS_INC(&nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_TX_QUEUE_FULL_0]);
 		} else if (nss_ctx->id == NSS_CORE_1) {
-			NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_TX_QUEUE_FULL_1]);
+			NSS_PKT_STATS_INC(&nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_TX_QUEUE_FULL_1]);
 		} else {
 			nss_warning("%p: Invalid nss core: %d\n", nss_ctx, nss_ctx->id);
 		}
@@ -2856,7 +2863,7 @@
 	}
 #endif
 
-	NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_NSS_SKB_COUNT]);
+	NSS_PKT_STATS_INC(&nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_NSS_SKB_COUNT]);
 
 	spin_unlock_bh(&h2n_desc_ring->lock);
 	return NSS_CORE_STATUS_SUCCESS;
@@ -2892,7 +2899,7 @@
 
 	nbuf = dev_alloc_skb(buf_size);
 	if (unlikely(!nbuf)) {
-		NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_NBUF_ALLOC_FAILS]);
+		NSS_PKT_STATS_INC(&nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_NBUF_ALLOC_FAILS]);
 		nss_warning("%p: interface: %d type: %d msg dropped as command allocation failed", nss_ctx, ncm->interface, ncm->type);
 		return NSS_TX_FAILURE;
 	}
@@ -2902,13 +2909,13 @@
 	status = nss_core_send_buffer(nss_ctx, 0, nbuf, NSS_IF_H2N_CMD_QUEUE, H2N_BUFFER_CTRL, 0);
 	if (status != NSS_CORE_STATUS_SUCCESS) {
 		dev_kfree_skb_any(nbuf);
-		NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_TX_CMD_QUEUE_FULL]);
+		NSS_PKT_STATS_INC(&nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_TX_CMD_QUEUE_FULL]);
 		nss_warning("%p: interface: %d type: %d unable to enqueue message status %d\n", nss_ctx, ncm->interface, ncm->type, status);
 		return status;
 	}
 
 	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_INC(&nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_TX_CMD_REQ]);
 	return status;
 }
 
@@ -2945,8 +2952,8 @@
 	/*
 	 * Count per queue and aggregate packet count
 	 */
-	NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_TX_PACKET_QUEUE_0 + queue_id]);
+	NSS_PKT_STATS_INC(&nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_TX_PACKET_QUEUE_0 + queue_id]);
 #endif
-	NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_TX_PACKET]);
+	NSS_PKT_STATS_INC(&nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_TX_PACKET]);
 	return status;
 }
diff --git a/nss_core.h b/nss_core.h
index 9b3ed6c..c791c45 100644
--- a/nss_core.h
+++ b/nss_core.h
@@ -94,13 +94,17 @@
 #endif
 
 #if (NSS_PKT_STATS_ENABLED == 1)
-#define NSS_PKT_STATS_INCREMENT(nss_ctx, x) nss_pkt_stats_increment((nss_ctx), (x))
-#define NSS_PKT_STATS_DECREMENT(nss_ctx, x) nss_pkt_stats_decrement((nss_ctx), (x))
+#define NSS_PKT_STATS_INC(x) nss_pkt_stats_inc((x))
+#define NSS_PKT_STATS_DEC(x) nss_pkt_stats_dec((x))
+#define NSS_PKT_STATS_ADD(x, i) nss_pkt_stats_add((x), (i))
+#define NSS_PKT_STATS_SUB(x, i) nss_pkt_stats_sub((x), (i))
 #define NSS_PKT_STATS_READ(x) nss_pkt_stats_read(x)
 #else
-#define NSS_PKT_STATS_INCREMENT(nss_ctx, x)
-#define NSS_PKT_STATS_DECREMENT(nss_ctx, x)
-#define NSS_PKT_STATS_READ(x) (0)
+#define NSS_PKT_STATS_INC(x)
+#define NSS_PKT_STATS_DEC(x)
+#define NSS_PKT_STATS_ADD(x, i)
+#define NSS_PKT_STATS_SUB(x, i)
+#define NSS_PKT_STATS_READ(x)
 #endif
 
 /*
@@ -705,22 +709,38 @@
 
 #if (NSS_PKT_STATS_ENABLED == 1)
 /*
- * nss_pkt_stats_increment()
+ * nss_pkt_stats_inc()
  */
-static inline void nss_pkt_stats_increment(struct nss_ctx_instance *nss_ctx, atomic64_t *stat)
+static inline void nss_pkt_stats_inc(atomic64_t *stat)
 {
 	atomic64_inc(stat);
 }
 
 /*
- * nss_pkt_stats_increment()
+ * nss_pkt_stats_dec()
  */
-static inline void nss_pkt_stats_decrement(struct nss_ctx_instance *nss_ctx, atomic64_t *stat)
+static inline void nss_pkt_stats_dec(atomic64_t *stat)
 {
 	atomic64_dec(stat);
 }
 
 /*
+ * nss_pkt_stats_add()
+ */
+static inline void nss_pkt_stats_add(atomic64_t *stat, uint32_t pkt)
+{
+	atomic64_add(pkt, stat);
+}
+
+/*
+ * nss_pkt_stats_sub()
+ */
+static inline void nss_pkt_stats_sub(atomic64_t *stat, uint32_t pkt)
+{
+	atomic64_sub(pkt, stat);
+}
+
+/*
  * nss_pkt_stats_read()
  */
 static inline uint64_t nss_pkt_stats_read(atomic64_t *stat)
diff --git a/nss_crypto.c b/nss_crypto.c
index 7c9fa92..18ae4f3 100644
--- a/nss_crypto.c
+++ b/nss_crypto.c
@@ -1,6 +1,6 @@
 /*
  **************************************************************************
- * Copyright (c) 2013,2015-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013,2015-2019, 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.
@@ -31,7 +31,7 @@
 
 /*
  * nss_crypto_set_msg_callback()
- * 	this sets the message callback handler and its associated context
+ *	this sets the message callback handler and its associated context
  */
 static inline void nss_crypto_set_msg_callback(struct nss_ctx_instance *nss_ctx, nss_crypto_msg_callback_t cb, void *crypto_ctx)
 {
@@ -43,7 +43,7 @@
 
 /*
  * nss_crypto_get_msg_callback()
- * 	this gets the message callback handler and its associated context
+ *	this gets the message callback handler and its associated context
  */
 static inline nss_crypto_msg_callback_t nss_crypto_get_msg_callback(struct nss_ctx_instance *nss_ctx, void **crypto_ctx)
 {
@@ -55,7 +55,7 @@
 
 /*
  * nss_crypto_msg_handler()
- * 	this handles all the IPsec events and responses
+ *	this handles all the IPsec events and responses
  */
 static void nss_crypto_msg_handler(struct nss_ctx_instance *nss_ctx, struct nss_cmn_msg *ncm, void *app_data __attribute((unused)))
 {
@@ -179,7 +179,7 @@
 	 */
 	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]);
+	NSS_PKT_STATS_INC(&nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_TX_CRYPTO_REQ]);
 
 	return NSS_TX_SUCCESS;
 }
@@ -192,7 +192,7 @@
 
 /*
  * nss_crypto_notify_register()
- * 	register message notifier for crypto interface
+ *	register message notifier for crypto interface
  */
 struct nss_ctx_instance *nss_crypto_notify_register(nss_crypto_msg_callback_t cb, void *app_data)
 {
@@ -207,7 +207,7 @@
 
 /*
  * nss_crypto_notify_unregister()
- * 	unregister message notifier for crypto interface
+ *	unregister message notifier for crypto interface
  */
 void nss_crypto_notify_unregister(struct nss_ctx_instance *nss_ctx)
 {
@@ -216,7 +216,7 @@
 
 /*
  * nss_crypto_data_register()
- * 	register a data callback routine
+ *	register a data callback routine
  */
 struct nss_ctx_instance *nss_crypto_data_register(uint32_t if_num, nss_crypto_buf_callback_t cb,
 		struct net_device *netdev, uint32_t features)
@@ -240,7 +240,7 @@
 
 /*
  * nss_crypto_data_unregister()
- * 	unregister a data callback routine
+ *	unregister a data callback routine
  */
 void nss_crypto_data_unregister(struct nss_ctx_instance *nss_ctx, uint32_t if_num)
 {
@@ -254,7 +254,7 @@
 
 /*
  * nss_crypto_pm_notify_register()
- * 	register a PM notify callback routine
+ *	register a PM notify callback routine
  */
 void nss_crypto_pm_notify_register(nss_crypto_pm_event_callback_t cb, void *app_data)
 {
@@ -264,7 +264,7 @@
 
 /*
  * nss_crypto_pm_notify_unregister()
- * 	unregister a PM notify callback routine
+ *	unregister a PM notify callback routine
  */
 void nss_crypto_pm_notify_unregister(void)
 {
diff --git a/nss_crypto_cmn.c b/nss_crypto_cmn.c
index a53afe0..13133a8 100644
--- a/nss_crypto_cmn.c
+++ b/nss_crypto_cmn.c
@@ -1,6 +1,6 @@
 /*
  **************************************************************************
- * Copyright (c) 2013,2015-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013,2015-2019, 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.
@@ -251,7 +251,7 @@
 	 * 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]);
+	NSS_PKT_STATS_INC(&nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_TX_CRYPTO_REQ]);
 
 	return NSS_TX_SUCCESS;
 }
diff --git a/nss_crypto_cmn_log.c b/nss_crypto_cmn_log.c
index ed44f3c..b696cc0 100644
--- a/nss_crypto_cmn_log.c
+++ b/nss_crypto_cmn_log.c
@@ -1,6 +1,6 @@
 /*
  **************************************************************************
- * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018-2019, 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.
@@ -142,9 +142,17 @@
 		break;
 
 	case NSS_CRYPTO_CMN_MSG_TYPE_SETUP_CTX:
+	case NSS_CRYPTO_CMN_MSG_TYPE_CLEAR_CTX:
+	case NSS_CRYPTO_CMN_MSG_TYPE_VERIFY_CTX:
 		nss_crypto_cmn_ctx_msg(ncm);
 		break;
 
+	case NSS_CRYPTO_CMN_MSG_TYPE_SYNC_NODE_STATS:
+	case NSS_CRYPTO_CMN_MSG_TYPE_SYNC_ENG_STATS:
+	case NSS_CRYPTO_CMN_MSG_TYPE_SYNC_CTX_STATS:
+		/* Getting logged in stats */
+		break;
+
 	default:
 		nss_warning("%p: Invalid message type\n", ncm);
 		break;
diff --git a/nss_data_plane/nss_data_plane_edma.c b/nss_data_plane/nss_data_plane_edma.c
index 3a778b0..40bdeed 100644
--- a/nss_data_plane/nss_data_plane_edma.c
+++ b/nss_data_plane/nss_data_plane_edma.c
@@ -322,12 +322,6 @@
 	}
 
 	/*
-	 * Packets with the ptp service code should be delivered to PHY driver for timestamping
-	 */
-	nss_cmn_register_service_code(nss_ctx, nss_phy_tstamp_rx_buf,
-			NSS_PTP_EVENT_SERVICE_CODE, netdev);
-
-	/*
 	 * Now we are registered and our side is ready, if the data plane was opened, ask it to start again
 	 */
 	if (is_open) {
@@ -365,6 +359,13 @@
 			nss_info("%p: Register data plan to data plane %d success\n", nss_ctx, i);
 		}
 	}
+
+	/*
+	 * Packets with the ptp service code should be delivered to PHY driver for timestamping
+	 */
+	nss_cmn_register_service_code(nss_ctx, nss_phy_tstamp_rx_buf,
+			NSS_PTP_EVENT_SERVICE_CODE, nss_ctx);
+
 }
 
 /*
diff --git a/nss_data_plane/nss_data_plane_gmac.c b/nss_data_plane/nss_data_plane_gmac.c
index 1345cbb..64da8de 100644
--- a/nss_data_plane/nss_data_plane_gmac.c
+++ b/nss_data_plane/nss_data_plane_gmac.c
@@ -1,6 +1,6 @@
 /*
  **************************************************************************
- * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2019, 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.
@@ -287,10 +287,7 @@
 	gmac_stats->rx_packets += stats->if_stats.rx_packets;
 	gmac_stats->rx_errors += stats->estats.rx_errors;
 	gmac_stats->rx_receive_errors += stats->estats.rx_receive_errors;
-	gmac_stats->rx_overflow_errors += stats->estats.rx_overflow_errors;
 	gmac_stats->rx_descriptor_errors += stats->estats.rx_descriptor_errors;
-	gmac_stats->rx_watchdog_timeout_errors += stats->estats.rx_watchdog_timeout_errors;
-	gmac_stats->rx_crc_errors += stats->estats.rx_crc_errors;
 	gmac_stats->rx_late_collision_errors += stats->estats.rx_late_collision_errors;
 	gmac_stats->rx_dribble_bit_errors += stats->estats.rx_dribble_bit_errors;
 	gmac_stats->rx_length_errors += stats->estats.rx_length_errors;
@@ -334,24 +331,27 @@
 	gmac_stats->gmac_worst_case_ticks += stats->estats.gmac_worst_case_ticks;
 	gmac_stats->gmac_iterations += stats->estats.gmac_iterations;
 	gmac_stats->tx_pause_frames += stats->estats.tx_pause_frames;
-
-	gmac_stats->rx_octets_g += stats->estats.rx_octets_g;
-	gmac_stats->rx_ucast_frames += stats->estats.rx_ucast_frames;
-	gmac_stats->rx_bcast_frames += stats->estats.rx_bcast_frames;
-	gmac_stats->rx_mcast_frames += stats->estats.rx_mcast_frames;
-	gmac_stats->rx_undersize += stats->estats.rx_undersize;
-	gmac_stats->rx_oversize += stats->estats.rx_oversize;
-	gmac_stats->rx_jabber += stats->estats.rx_jabber;
-	gmac_stats->rx_octets_gb += stats->estats.rx_octets_gb;
-	gmac_stats->rx_frag_frames_g += stats->estats.rx_frag_frames_g;
-	gmac_stats->tx_octets_g += stats->estats.tx_octets_g;
-	gmac_stats->tx_ucast_frames += stats->estats.tx_ucast_frames;
-	gmac_stats->tx_bcast_frames += stats->estats.tx_bcast_frames;
-	gmac_stats->tx_mcast_frames += stats->estats.tx_mcast_frames;
-	gmac_stats->tx_deferred += stats->estats.tx_deferred;
-	gmac_stats->tx_single_col += stats->estats.tx_single_col;
-	gmac_stats->tx_multiple_col += stats->estats.tx_multiple_col;
-	gmac_stats->tx_octets_gb += stats->estats.tx_octets_gb;
+	gmac_stats->mmc_rx_overflow_errors += stats->estats.mmc_rx_overflow_errors;
+	gmac_stats->mmc_rx_watchdog_timeout_errors += stats->estats.mmc_rx_watchdog_timeout_errors;
+	gmac_stats->mmc_rx_crc_errors += stats->estats.mmc_rx_crc_errors;
+	gmac_stats->mmc_rx_ip_header_errors += stats->estats.mmc_rx_ip_header_errors;
+	gmac_stats->mmc_rx_octets_g += stats->estats.mmc_rx_octets_g;
+	gmac_stats->mmc_rx_ucast_frames += stats->estats.mmc_rx_ucast_frames;
+	gmac_stats->mmc_rx_bcast_frames += stats->estats.mmc_rx_bcast_frames;
+	gmac_stats->mmc_rx_mcast_frames += stats->estats.mmc_rx_mcast_frames;
+	gmac_stats->mmc_rx_undersize += stats->estats.mmc_rx_undersize;
+	gmac_stats->mmc_rx_oversize += stats->estats.mmc_rx_oversize;
+	gmac_stats->mmc_rx_jabber += stats->estats.mmc_rx_jabber;
+	gmac_stats->mmc_rx_octets_gb += stats->estats.mmc_rx_octets_gb;
+	gmac_stats->mmc_rx_frag_frames_g += stats->estats.mmc_rx_frag_frames_g;
+	gmac_stats->mmc_tx_octets_g += stats->estats.mmc_tx_octets_g;
+	gmac_stats->mmc_tx_ucast_frames += stats->estats.mmc_tx_ucast_frames;
+	gmac_stats->mmc_tx_bcast_frames += stats->estats.mmc_tx_bcast_frames;
+	gmac_stats->mmc_tx_mcast_frames += stats->estats.mmc_tx_mcast_frames;
+	gmac_stats->mmc_tx_deferred += stats->estats.mmc_tx_deferred;
+	gmac_stats->mmc_tx_single_col += stats->estats.mmc_tx_single_col;
+	gmac_stats->mmc_tx_multiple_col += stats->estats.mmc_tx_multiple_col;
+	gmac_stats->mmc_tx_octets_gb += stats->estats.mmc_tx_octets_gb;
 
 	spin_unlock_bh(&nss_data_plane_gmac_stats_lock);
 }
diff --git a/nss_hal/nss_hal.c b/nss_hal/nss_hal.c
index 2dbadd7..80b54f1 100644
--- a/nss_hal/nss_hal.c
+++ b/nss_hal/nss_hal.c
@@ -391,8 +391,8 @@
 #if defined(NSS_HAL_IPQ807x_SUPPORT) || defined(NSS_HAL_IPQ60XX_SUPPORT)
 		nss_top->dynamic_interface_table[NSS_DYNAMIC_INTERFACE_TYPE_IPSEC_CMN_INNER] = nss_dev->id;
 		nss_top->dynamic_interface_table[NSS_DYNAMIC_INTERFACE_TYPE_IPSEC_CMN_OUTER] = nss_dev->id;
-		nss_top->dynamic_interface_table[NSS_DYNAMIC_INTERFACE_TYPE_IPSEC_CMN_INNER_BOUNCE] = nss_dev->id;
-		nss_top->dynamic_interface_table[NSS_DYNAMIC_INTERFACE_TYPE_IPSEC_CMN_OUTER_BOUNCE] = nss_dev->id;
+		nss_top->dynamic_interface_table[NSS_DYNAMIC_INTERFACE_TYPE_IPSEC_CMN_MDATA_INNER] = nss_dev->id;
+		nss_top->dynamic_interface_table[NSS_DYNAMIC_INTERFACE_TYPE_IPSEC_CMN_MDATA_OUTER] = nss_dev->id;
 		nss_top->dynamic_interface_table[NSS_DYNAMIC_INTERFACE_TYPE_IPSEC_CMN_REDIRECT] = nss_dev->id;
 		nss_ipsec_cmn_register_handler();
 #else
@@ -514,7 +514,7 @@
 		nss_vlan_register_handler();
 	}
 
-#if defined(NSS_HAL_IPQ807x_SUPPORT)
+#if defined(NSS_HAL_IPQ807x_SUPPORT) || defined(NSS_HAL_IPQ60XX_SUPPORT)
 	if (npd->qvpn_enabled == NSS_FEATURE_ENABLED) {
 		nss_top->qvpn_handler_id = nss_dev->id;
 		nss_top->dynamic_interface_table[NSS_DYNAMIC_INTERFACE_TYPE_QVPN_OUTER] = nss_dev->id;
diff --git a/nss_ipsec_cmn.c b/nss_ipsec_cmn.c
index 0f07f81..a59fe54 100644
--- a/nss_ipsec_cmn.c
+++ b/nss_ipsec_cmn.c
@@ -99,10 +99,18 @@
 			len += scnprintf(buf + len, size - len, "\nInner if_num:%03u", if_num);
 			break;
 
+		case NSS_DYNAMIC_INTERFACE_TYPE_IPSEC_CMN_MDATA_INNER:
+			len += scnprintf(buf + len, size - len, "\nMetadata inner if_num:%03u", if_num);
+			break;
+
 		case NSS_DYNAMIC_INTERFACE_TYPE_IPSEC_CMN_OUTER:
 			len += scnprintf(buf + len, size - len, "\nOuter if_num:%03u", if_num);
 			break;
 
+		case NSS_DYNAMIC_INTERFACE_TYPE_IPSEC_CMN_MDATA_OUTER:
+			len += scnprintf(buf + len, size - len, "\nMetadata outer if_num:%03u", if_num);
+			break;
+
 		default:
 			len += scnprintf(buf + len, size - len, "\nUnknown(%d) if_num:%03u", type, if_num);
 			break;
@@ -137,8 +145,8 @@
 	switch (type) {
 	case NSS_DYNAMIC_INTERFACE_TYPE_IPSEC_CMN_INNER:
 	case NSS_DYNAMIC_INTERFACE_TYPE_IPSEC_CMN_OUTER:
-	case NSS_DYNAMIC_INTERFACE_TYPE_IPSEC_CMN_INNER_BOUNCE:
-	case NSS_DYNAMIC_INTERFACE_TYPE_IPSEC_CMN_OUTER_BOUNCE:
+	case NSS_DYNAMIC_INTERFACE_TYPE_IPSEC_CMN_MDATA_INNER:
+	case NSS_DYNAMIC_INTERFACE_TYPE_IPSEC_CMN_MDATA_OUTER:
 	case NSS_DYNAMIC_INTERFACE_TYPE_IPSEC_CMN_REDIRECT:
 		return true;
 
diff --git a/nss_ipv4.c b/nss_ipv4.c
index 2693957..2ad87fb 100644
--- a/nss_ipv4.c
+++ b/nss_ipv4.c
@@ -1,6 +1,6 @@
 /*
  **************************************************************************
- * Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2019, 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.
@@ -401,7 +401,7 @@
 	}
 
 	nss_ipv4_conn_cfg = ntohl(nirccm->num_conn);
-	nss_warning("%p: IPv4 connection configuration success: %d\n", nss_ctx, nim->cm.error);
+	nss_info("%p: IPv4 connection configuration success: %d\n", nss_ctx, nim->cm.error);
 }
 
 /*
@@ -536,7 +536,7 @@
 		(ipv4_num_conn < NSS_MIN_NUM_CONN)) {
 		nss_warning("%p: input supported connections (%d) does not adhere\
 				specifications\n1) not multiple of 1024,\n2) is less than \
-				min val: %d, OR\n 	IPv4/6 total exceeds %d\n",
+				min val: %d, OR\n	IPv4/6 total exceeds %d\n",
 				nss_ctx,
 				ipv4_num_conn,
 				NSS_MIN_NUM_CONN,
diff --git a/nss_ipv6.c b/nss_ipv6.c
index 850ba49..02a4b0b 100644
--- a/nss_ipv6.c
+++ b/nss_ipv6.c
@@ -1,6 +1,6 @@
 /*
  **************************************************************************
- * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2019, 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.
@@ -404,7 +404,7 @@
 
 	nss_ipv6_conn_cfg = ntohl(nirccm->num_conn);
 
-	nss_warning("%p: IPv6 connection configuration success: %d\n", nss_ctx, nim->cm.error);
+	nss_info("%p: IPv6 connection configuration success: %d\n", nss_ctx, nim->cm.error);
 }
 
 /*
@@ -433,7 +433,7 @@
 							conn);
 		goto fail;
 	}
-	nss_warning("%p: CE Memory allocated for IPv6 Connections: %d\n",
+	nss_info("%p: CE Memory allocated for IPv6 Connections: %d\n",
 							nss_ctx,
 							conn);
 
@@ -445,7 +445,7 @@
 							conn);
 		goto fail;
 	}
-	nss_warning("%p: CME Memory allocated for IPv6 Connections: %d\n",
+	nss_info("%p: CME Memory allocated for IPv6 Connections: %d\n",
 							nss_ctx,
 							conn);
 
@@ -546,7 +546,7 @@
 		(ipv6_num_conn < NSS_MIN_NUM_CONN)) {
 		nss_warning("%p: input supported connections (%d) does not adhere\
 				specifications\n1) not power of 2,\n2) is less than \
-				min val: %d, OR\n 	IPv4/6 total exceeds %d\n",
+				min val: %d, OR\n	IPv4/6 total exceeds %d\n",
 				nss_ctx,
 				ipv6_num_conn,
 				NSS_MIN_NUM_CONN,
diff --git a/nss_l2tpv2.c b/nss_l2tpv2.c
index f2c012b..223c4de 100644
--- a/nss_l2tpv2.c
+++ b/nss_l2tpv2.c
@@ -1,6 +1,6 @@
 /*
  **************************************************************************
- * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2019, 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.
@@ -40,6 +40,7 @@
 			nss_l2tpv2_session_debug_stats[i].stats[NSS_L2TPV2_STATS_SESSION_RX_EXP_DATA_PKTS] += stats_msg->debug_stats.rx_exception_data_pkts;
 			nss_l2tpv2_session_debug_stats[i].stats[NSS_L2TPV2_STATS_SESSION_ENCAP_PBUF_ALLOC_FAIL_PKTS] += stats_msg->debug_stats.encap_pbuf_alloc_fail;
 			nss_l2tpv2_session_debug_stats[i].stats[NSS_L2TPV2_STATS_SESSION_DECAP_PBUF_ALLOC_FAIL_PKTS] += stats_msg->debug_stats.decap_pbuf_alloc_fail;
+			nss_l2tpv2_session_debug_stats[i].stats[NSS_L2TPV2_STATS_SESSION_DECAP_L2TPOIPSEC_SRC_ERR] += stats_msg->debug_stats.decap_l2tpoipsec_src_error;
 			break;
 		}
 	}
diff --git a/nss_l2tpv2_stats.c b/nss_l2tpv2_stats.c
index 00e35da..24aecab 100644
--- a/nss_l2tpv2_stats.c
+++ b/nss_l2tpv2_stats.c
@@ -1,6 +1,6 @@
 /*
  **************************************************************************
- * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017, 2019, 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.
@@ -26,7 +26,8 @@
 	"RX_PPP_LCP_PKTS",
 	"RX_EXP_PKTS",
 	"ENCAP_PBUF_ALLOC_FAIL",
-	"DECAP_PBUF_ALLOC_FAIL"
+	"DECAP_PBUF_ALLOC_FAIL",
+	"DECAP_L2TPOIPSEC_SRC_ERR"
 };
 
 /*
diff --git a/nss_l2tpv2_stats.h b/nss_l2tpv2_stats.h
index c199afa..afa9caa 100644
--- a/nss_l2tpv2_stats.h
+++ b/nss_l2tpv2_stats.h
@@ -1,6 +1,6 @@
 /*
  ******************************************************************************
- * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017, 2019, 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.
@@ -25,6 +25,7 @@
 	NSS_L2TPV2_STATS_SESSION_RX_EXP_DATA_PKTS,	/* Number of RX exceptioned packets */
 	NSS_L2TPV2_STATS_SESSION_ENCAP_PBUF_ALLOC_FAIL_PKTS,	/* Number of times packet buffer allocation failed during encap */
 	NSS_L2TPV2_STATS_SESSION_DECAP_PBUF_ALLOC_FAIL_PKTS,	/* Number of times packet buffer allocation failed during decap */
+	NSS_L2TPV2_STATS_SESSION_DECAP_L2TPOIPSEC_SRC_ERR,	/* Number of packets dropped due to source error in l2tp over ipsec flow in decap */
 	NSS_L2TPV2_STATS_SESSION_MAX
 };
 
diff --git a/nss_n2h.c b/nss_n2h.c
index 552642a..e6c7697 100644
--- a/nss_n2h.c
+++ b/nss_n2h.c
@@ -2053,7 +2053,9 @@
 
 	nss_core_register_handler(nss_ctx, NSS_N2H_INTERFACE, nss_n2h_interface_handler, NULL);
 
-	nss_n2h_stats_dentry_create();
+	if (nss_ctx->id == NSS_CORE_0) {
+		nss_n2h_stats_dentry_create();
+	}
 }
 
 /*
diff --git a/nss_phys_if.h b/nss_phys_if.h
index e89aee9..164e95f 100644
--- a/nss_phys_if.h
+++ b/nss_phys_if.h
@@ -32,11 +32,7 @@
 struct nss_phys_if_estats {
 	uint32_t rx_errors;		/**< Number of RX errors */
 	uint32_t rx_receive_errors;	/**< Number of RX receive errors */
-	uint32_t rx_overflow_errors;	/**< Number of RX overflow errors */
 	uint32_t rx_descriptor_errors;	/**< Number of RX descriptor errors */
-	uint32_t rx_watchdog_timeout_errors;
-					/**< Number of RX watchdog timeout errors */
-	uint32_t rx_crc_errors;		/**< Number of RX CRC errors */
 	uint32_t rx_late_collision_errors;
 					/**< Number of RX late collision errors */
 	uint32_t rx_dribble_bit_errors;	/**< Number of RX dribble bit errors */
@@ -74,23 +70,30 @@
 	uint32_t gmac_worst_case_ticks;	/**< Worst case iteration of the GMAC in ticks */
 	uint32_t gmac_iterations;	/**< Number of iterations around the GMAC */
 	uint32_t tx_pause_frames;	/**< Number of pause frames sent by the GMAC */
-	uint32_t rx_octets_g;		/* Number of good octets received */
-	uint32_t rx_ucast_frames;	/* Number of Unicast frames received */
-	uint32_t rx_bcast_frames;	/* Number of Bcast frames received */
-	uint32_t rx_mcast_frames;	/* Number of Mcast frames received */
-	uint32_t rx_undersize;		/* Number of RX undersize frames */
-	uint32_t rx_oversize;		/* Number of RX oversize frames */
-	uint32_t rx_jabber;		/* Number of jabber frames */
-	uint32_t rx_octets_gb;		/* Number of good/bad octets */
-	uint32_t rx_frag_frames_g;	/* Number of good ipv4 frag frames */
-	uint32_t tx_octets_g;		/* Number of good octets sent */
-	uint32_t tx_ucast_frames;	/* Number of Unicast frames sent*/
-	uint32_t tx_bcast_frames;	/* Number of Broadcast frames sent */
-	uint32_t tx_mcast_frames;	/* Number of Multicast frames sent */
-	uint32_t tx_deferred;		/* Number of Deferred frames sent */
-	uint32_t tx_single_col;		/* Number of single collisions */
-	uint32_t tx_multiple_col;	/* Number of multiple collisions */
-	uint32_t tx_octets_gb;		/* Number of good/bad octets sent*/
+	uint32_t mmc_rx_overflow_errors;
+					/**< Number of RX overflow errors */
+	uint32_t mmc_rx_watchdog_timeout_errors;
+					/**< Number of RX watchdog timeout errors */
+	uint32_t mmc_rx_crc_errors;	/**< Number of RX CRC errors */
+	uint32_t mmc_rx_ip_header_errors;
+					/**< Number of RX IP header errors */
+	uint32_t mmc_rx_octets_g;		/* Number of good octets received */
+	uint32_t mmc_rx_ucast_frames;	/* Number of Unicast frames received */
+	uint32_t mmc_rx_bcast_frames;	/* Number of Bcast frames received */
+	uint32_t mmc_rx_mcast_frames;	/* Number of Mcast frames received */
+	uint32_t mmc_rx_undersize;	/* Number of RX undersize frames */
+	uint32_t mmc_rx_oversize;	/* Number of RX oversize frames */
+	uint32_t mmc_rx_jabber;		/* Number of jabber frames */
+	uint32_t mmc_rx_octets_gb;	/* Number of good/bad octets */
+	uint32_t mmc_rx_frag_frames_g;	/* Number of good ipv4 frag frames */
+	uint32_t mmc_tx_octets_g;	/* Number of good octets sent */
+	uint32_t mmc_tx_ucast_frames;	/* Number of Unicast frames sent*/
+	uint32_t mmc_tx_bcast_frames;	/* Number of Broadcast frames sent */
+	uint32_t mmc_tx_mcast_frames;	/* Number of Multicast frames sent */
+	uint32_t mmc_tx_deferred;	/* Number of Deferred frames sent */
+	uint32_t mmc_tx_single_col;	/* Number of single collisions */
+	uint32_t mmc_tx_multiple_col;	/* Number of multiple collisions */
+	uint32_t mmc_tx_octets_gb;	/* Number of good/bad octets sent*/
 };
 
 /**
diff --git a/nss_pppoe.c b/nss_pppoe.c
index a85c7a2..bee4ca9 100644
--- a/nss_pppoe.c
+++ b/nss_pppoe.c
@@ -25,11 +25,6 @@
 
 #define NSS_PPPOE_TX_TIMEOUT 3000 /* 3 Seconds */
 
-/*
- * Data structures to store pppoe nss debug stats
- */
-static DEFINE_SPINLOCK(nss_pppoe_lock);
-static struct nss_pppoe_stats_session_debug nss_pppoe_debug_stats[NSS_MAX_PPPOE_DYNAMIC_INTERFACES];
 int nss_pppoe_br_accel_mode __read_mostly = NSS_PPPOE_BR_ACCEL_MODE_EN_5T;
 
 /*
@@ -57,28 +52,6 @@
 }
 
 /*
- * nss_pppoe_debug_stats_sync
- *	Per session debug stats for pppoe
- */
-static void nss_pppoe_debug_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_pppoe_sync_stats_msg *stats_msg, uint16_t if_num)
-{
-	int i;
-	spin_lock_bh(&nss_pppoe_lock);
-	for (i = 0; i < NSS_MAX_PPPOE_DYNAMIC_INTERFACES; i++) {
-		if (nss_pppoe_debug_stats[i].if_num == if_num) {
-			nss_pppoe_debug_stats[i].stats[NSS_PPPOE_STATS_RX_PACKETS] += stats_msg->stats.rx_packets;
-			nss_pppoe_debug_stats[i].stats[NSS_PPPOE_STATS_RX_BYTES] += stats_msg->stats.rx_bytes;
-			nss_pppoe_debug_stats[i].stats[NSS_PPPOE_STATS_TX_PACKETS] += stats_msg->stats.tx_packets;
-			nss_pppoe_debug_stats[i].stats[NSS_PPPOE_STATS_TX_BYTES] += stats_msg->stats.tx_bytes;
-			nss_pppoe_debug_stats[i].stats[NSS_PPPOE_STATS_SESSION_WRONG_VERSION_OR_TYPE] += stats_msg->exception_events[NSS_PPPOE_EXCEPTION_EVENT_WRONG_VERSION_OR_TYPE];
-			nss_pppoe_debug_stats[i].stats[NSS_PPPOE_STATS_SESSION_WRONG_CODE] += stats_msg->exception_events[NSS_PPPOE_EXCEPTION_EVENT_WRONG_CODE];
-			nss_pppoe_debug_stats[i].stats[NSS_PPPOE_STATS_SESSION_UNSUPPORTED_PPP_PROTOCOL] += stats_msg->exception_events[NSS_PPPOE_EXCEPTION_EVENT_UNSUPPORTED_PPP_PROTOCOL];
-			break;
-		}
-	}
-	spin_unlock_bh(&nss_pppoe_lock);
-}
-/*
  * nss_pppoe_get_context()
  */
 struct nss_ctx_instance *nss_pppoe_get_context(void)
@@ -150,7 +123,7 @@
  */
 static void nss_pppoe_handler(struct nss_ctx_instance *nss_ctx, struct nss_cmn_msg *ncm, __attribute__((unused))void *app_data)
 {
-	struct nss_pppoe_msg *nim = (struct nss_pppoe_msg *)ncm;
+	struct nss_pppoe_msg *npm = (struct nss_pppoe_msg *)ncm;
 	void *ctx;
 	nss_pppoe_msg_callback_t cb;
 
@@ -159,7 +132,7 @@
 	/*
 	 * Trace Messages
 	 */
-	nss_pppoe_log_rx_msg(nim);
+	nss_pppoe_log_rx_msg(npm);
 
 	/*
 	 * Sanity check the message type
@@ -182,9 +155,9 @@
 	/*
 	 * Handling PPPoE messages coming from NSS fw.
 	 */
-	switch (nim->cm.type) {
+	switch (npm->cm.type) {
 	case NSS_PPPOE_MSG_SYNC_STATS:
-		nss_pppoe_debug_stats_sync(nss_ctx, &nim->msg.sync_stats, ncm->interface);
+		nss_pppoe_stats_sync(nss_ctx, &npm->msg.sync_stats, ncm->interface);
 		break;
 	default:
 		nss_warning("%p: Received response %d for type %d, interface %d\n",
@@ -218,31 +191,7 @@
 	cb = (nss_pppoe_msg_callback_t)ncm->cb;
 	ctx = (void *)ncm->app_data;
 
-	cb(ctx, nim);
-}
-
-/*
- * nss_pppoe_debug_stats_get()
- *	Get session pppoe statistics.
- */
-void nss_pppoe_debug_stats_get(void *stats_mem)
-{
-	struct nss_pppoe_stats_session_debug *stats = (struct nss_pppoe_stats_session_debug *)stats_mem;
-	int i;
-
-	if (!stats) {
-		nss_warning("No memory to copy pppoe session stats\n");
-		return;
-	}
-
-	spin_lock_bh(&nss_pppoe_lock);
-	for (i = 0; i < NSS_MAX_PPPOE_DYNAMIC_INTERFACES; i++) {
-		if (nss_pppoe_debug_stats[i].valid) {
-			memcpy(stats, &nss_pppoe_debug_stats[i], sizeof(struct nss_pppoe_stats_session_debug));
-			stats++;
-		}
-	}
-	spin_unlock_bh(&nss_pppoe_lock);
+	cb(ctx, npm);
 }
 
 /*
@@ -349,23 +298,11 @@
 						       struct net_device *netdev, uint32_t features, void *app_ctx)
 {
 	struct nss_ctx_instance *nss_ctx = nss_pppoe_get_context();
-	int i = 0;
 
 	nss_assert(nss_ctx);
 	nss_assert(nss_is_dynamic_interface(if_num));
 
-	spin_lock_bh(&nss_pppoe_lock);
-	for (i = 0; i < NSS_MAX_PPPOE_DYNAMIC_INTERFACES; i++) {
-		if (!nss_pppoe_debug_stats[i].valid) {
-			nss_pppoe_debug_stats[i].valid = true;
-			nss_pppoe_debug_stats[i].if_num = if_num;
-			nss_pppoe_debug_stats[i].if_index = netdev->ifindex;
-			break;
-		}
-	}
-	spin_unlock_bh(&nss_pppoe_lock);
-
-	if (i == NSS_MAX_PPPOE_DYNAMIC_INTERFACES) {
+	if (!nss_pppoe_stats_pppoe_session_init(if_num, netdev)) {
 		return NULL;
 	}
 
@@ -385,20 +322,11 @@
 void nss_unregister_pppoe_session_if(uint32_t if_num)
 {
 	struct nss_ctx_instance *nss_ctx = nss_pppoe_get_context();
-	int i;
 
 	nss_assert(nss_ctx);
 	nss_assert(nss_is_dynamic_interface(if_num));
 
-	spin_lock_bh(&nss_pppoe_lock);
-	for (i = 0; i < NSS_MAX_PPPOE_DYNAMIC_INTERFACES; i++) {
-		if (nss_pppoe_debug_stats[i].if_num == if_num) {
-			nss_pppoe_debug_stats[i].valid = false;
-			nss_pppoe_debug_stats[i].if_num = 0;
-			nss_pppoe_debug_stats[i].if_index = 0;
-		}
-	}
-	spin_unlock_bh(&nss_pppoe_lock);
+	nss_pppoe_stats_pppoe_session_deinit(if_num);
 
 	nss_core_unregister_subsys_dp(nss_ctx, if_num);
 
@@ -480,19 +408,9 @@
  */
 void nss_pppoe_register_handler(void)
 {
-	int i;
-
 	nss_info("nss_pppoe_register_handler\n");
 	nss_core_register_handler(nss_pppoe_get_context(), NSS_PPPOE_INTERFACE, nss_pppoe_handler, NULL);
 
-	spin_lock_bh(&nss_pppoe_lock);
-	for (i = 0; i < NSS_MAX_PPPOE_DYNAMIC_INTERFACES; i++) {
-		nss_pppoe_debug_stats[i].valid = false;
-		nss_pppoe_debug_stats[i].if_num = 0;
-		nss_pppoe_debug_stats[i].if_index = 0;
-	}
-	spin_unlock_bh(&nss_pppoe_lock);
-
 	sema_init(&pppoe_pvt.sem, 1);
 	init_completion(&pppoe_pvt.complete);
 
diff --git a/nss_pppoe_stats.c b/nss_pppoe_stats.c
index c5c95af..b7cc748 100644
--- a/nss_pppoe_stats.c
+++ b/nss_pppoe_stats.c
@@ -1,6 +1,6 @@
 /*
  **************************************************************************
- * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2019, 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.
@@ -16,13 +16,73 @@
 
 #include "nss_stats.h"
 #include "nss_core.h"
-#include "nss_pppoe_stats.h"
 
 /*
- * nss_pppoe_stats_str
- *	PPPoE stats strings
+ * Lock used for PPPoE statistics
  */
-static int8_t *nss_pppoe_stats_debug_str[NSS_PPPOE_STATS_SESSION_MAX] = {
+static DEFINE_SPINLOCK(nss_pppoe_stats_lock);
+
+/*
+ * PPPoE per session statistics
+ */
+enum nss_pppoe_stats_session {
+	NSS_PPPOE_STATS_SESSION_RX_PACKETS,
+	NSS_PPPOE_STATS_SESSION_RX_BYTES,
+	NSS_PPPOE_STATS_SESSION_TX_PACKETS,
+	NSS_PPPOE_STATS_SESSION_TX_BYTES,
+	NSS_PPPOE_STATS_SESSION_WRONG_VERSION_OR_TYPE,
+	NSS_PPPOE_STATS_SESSION_WRONG_CODE,
+	NSS_PPPOE_STATS_SESSION_UNSUPPORTED_PPP_PROTOCOL,
+	NSS_PPPOE_STATS_SESSION_MAX
+};
+
+/*
+ * PPPoE base node statistics
+ */
+enum nss_pppoe_stats_base {
+	NSS_PPPOE_STATS_BASE_RX_PACKETS,
+	NSS_PPPOE_STATS_BASE_RX_BYTES,
+	NSS_PPPOE_STATS_BASE_TX_PACKETS,
+	NSS_PPPOE_STATS_BASE_TX_BYTES,
+	NSS_PPPOE_STATS_BASE_RX_QUEUE_0_DROPPED,
+	NSS_PPPOE_STATS_BASE_RX_QUEUE_1_DROPPED,
+	NSS_PPPOE_STATS_BASE_RX_QUEUE_2_DROPPED,
+	NSS_PPPOE_STATS_BASE_RX_QUEUE_3_DROPPED,
+	NSS_PPPOE_STATS_BASE_SHORT_PPPOE_HDR_LENGTH,
+	NSS_PPPOE_STATS_BASE_SHORT_PACKET_LENGTH,
+	NSS_PPPOE_STATS_BASE_WRONG_VERSION_OR_TYPE,
+	NSS_PPPOE_STATS_BASE_WRONG_CODE,
+	NSS_PPPOE_STATS_BASE_UNSUPPORTED_PPP_PROTOCOL,
+	NSS_PPPOE_STATS_BASE_DISABLED_BRIDGE_PACKET,
+	NSS_PPPOE_STATS_BASE_MAX
+};
+
+/*
+ * PPPoE session stats structure for debug interface
+ */
+struct nss_pppoe_stats_session_stats {
+	uint64_t stats[NSS_PPPOE_STATS_SESSION_MAX];
+						/* stats for the session */
+	int32_t if_index;	/* net device index for the session */
+	uint32_t if_num;	/* nss interface number */
+	bool valid;			/* dynamic interface valid flag */
+};
+
+/*
+ * PPPoE interface stats structure for base node and sessions
+ */
+struct nss_pppoe_stats {
+	uint64_t base_stats[NSS_PPPOE_STATS_BASE_MAX];
+						/* Base node stats */
+	struct nss_pppoe_stats_session_stats session_stats[NSS_MAX_PPPOE_DYNAMIC_INTERFACES];
+					/* Per session stats */
+};
+
+/*
+ * nss_pppoe_stats_session_str
+ *	PPPoE session stats strings
+ */
+static int8_t *nss_pppoe_stats_session_str[NSS_PPPOE_STATS_SESSION_MAX] = {
 	"RX_PACKETS",
 	"RX_BYTES",
 	"TX_PACKETS",
@@ -33,6 +93,32 @@
 };
 
 /*
+ * nss_pppoe_stats_base_str
+ * 	PPPoE base node stats strings
+ */
+static int8_t *nss_pppoe_stats_base_str[NSS_PPPOE_STATS_BASE_MAX] = {
+	"RX_PACKETS",
+	"RX_BYTES",
+	"TX_PACKETS",
+	"TX_BYTES",
+	"RX_DROPPED[0]",
+	"RX_DROPPED[1]",
+	"RX_DROPPED[2]",
+	"RX_DROPPED[3]",
+	"SHORT_PPPOE_HDR_LENGTH",
+	"SHORT_PACKET_LENGTH",
+	"WRONG_VERSION_OR_TYPE",
+	"WRONG_CODE",
+	"UNSUPPORTED_PPP_PROTOCOL",
+	"DISABLED_BRIDGE_PACKET"
+};
+
+/*
+ * Global PPPoE stats decleration.
+ */
+static struct nss_pppoe_stats pppoe_stats;
+
+/*
  * nss_pppoe_stats_read()
  *	Read pppoe statistics
  */
@@ -41,12 +127,11 @@
 
 	uint32_t max_output_lines = 2 /* header & footer for session stats */
 					+ NSS_MAX_PPPOE_DYNAMIC_INTERFACES * (NSS_PPPOE_STATS_SESSION_MAX + 2) /*session stats */
-					+ 2;
+					+ 2 + NSS_PPPOE_STATS_BASE_MAX + 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_pppoe_stats_session_debug pppoe_session_stats[NSS_MAX_PPPOE_DYNAMIC_INTERFACES];
 	int id, i;
 
 	char *lbuf = kzalloc(size_al, GFP_KERNEL);
@@ -55,38 +140,40 @@
 		return 0;
 	}
 
-	memset(&pppoe_session_stats, 0, sizeof(struct nss_pppoe_stats_session_debug) * NSS_MAX_PPPOE_DYNAMIC_INTERFACES);
-
 	/*
-	 * Get all stats
+	 * Base node stats
 	 */
-	nss_pppoe_debug_stats_get((void *)&pppoe_session_stats);
+	size_wr = scnprintf(lbuf + size_wr, size_al - size_wr, "\npppoe base node stats start:\n\n");
+	for (i = 0; i < NSS_PPPOE_STATS_BASE_MAX; i++) {
+		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
+				     "\t%s = %llu\n", nss_pppoe_stats_base_str[i],
+				      pppoe_stats.base_stats[i]);
+	}
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\npppoe base node stats end:\n\n");
 
 	/*
 	 * Session stats
 	 */
 	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\npppoe session stats start:\n\n");
 	for (id = 0; id < NSS_MAX_PPPOE_DYNAMIC_INTERFACES; id++) {
-		if (!pppoe_session_stats[id].valid) {
-			break;
+		if (!pppoe_stats.session_stats[id].valid) {
+			continue;
 		}
 
-		dev = dev_get_by_index(&init_net, pppoe_session_stats[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,
-					pppoe_session_stats[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,
-					pppoe_session_stats[id].if_num);
+		dev = dev_get_by_index(&init_net, pppoe_stats.session_stats[id].if_index);
+		if (unlikely(!dev)) {
+			continue;
 		}
 
+		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "%d. nss interface id=%d, netdevice=%s\n", id,
+				pppoe_stats.session_stats[id].if_num, dev->name);
+		dev_put(dev);
+
 		for (i = 0; i < NSS_PPPOE_STATS_SESSION_MAX; i++) {
 			size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
-					     "\t%s = %llu\n", nss_pppoe_stats_debug_str[i],
-					      pppoe_session_stats[id].stats[i]);
+					     "\t%s = %llu\n", nss_pppoe_stats_session_str[i],
+					      pppoe_stats.session_stats[id].stats[i]);
 		}
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\n");
 	}
 
 	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\npppoe session stats end\n");
@@ -97,6 +184,96 @@
 }
 
 /*
+ * nss_pppoe_stats_pppoe_session_init()
+ *	Initialize the session statistics.
+ */
+bool nss_pppoe_stats_pppoe_session_init(uint32_t if_num, struct net_device *dev)
+{
+	int i;
+
+	spin_lock_bh(&nss_pppoe_stats_lock);
+	for (i = 0; i < NSS_MAX_PPPOE_DYNAMIC_INTERFACES; i++) {
+		if (!pppoe_stats.session_stats[i].valid) {
+			pppoe_stats.session_stats[i].valid = true;
+			pppoe_stats.session_stats[i].if_num = if_num;
+			pppoe_stats.session_stats[i].if_index = dev->ifindex;
+			spin_unlock_bh(&nss_pppoe_stats_lock);
+			return true;
+		}
+	}
+	spin_unlock_bh(&nss_pppoe_stats_lock);
+
+	return false;
+}
+
+/*
+ * nss_pppoe_stats_pppoe_session_deinit()
+ *	De-initialize the session's stats.
+ */
+void nss_pppoe_stats_pppoe_session_deinit(uint32_t if_num)
+{
+	int i;
+
+	spin_lock_bh(&nss_pppoe_stats_lock);
+	for (i = 0; i < NSS_MAX_PPPOE_DYNAMIC_INTERFACES; i++) {
+		if (pppoe_stats.session_stats[i].if_num == if_num) {
+			memset(&pppoe_stats.session_stats[i], 0, sizeof(pppoe_stats.session_stats[i]));
+		}
+	}
+	spin_unlock_bh(&nss_pppoe_stats_lock);
+}
+
+/*
+ * nss_pppoe_stats_sync
+ *	Per session debug stats for pppoe
+ */
+void nss_pppoe_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_pppoe_sync_stats_msg *stats_msg, uint16_t if_num)
+{
+	int i;
+	spin_lock_bh(&nss_pppoe_stats_lock);
+	for (i = 0; i < NSS_MAX_PPPOE_DYNAMIC_INTERFACES; i++) {
+		if (pppoe_stats.session_stats[i].if_num == if_num) {
+			int j;
+
+			/*
+			 * Sync PPPoE session stats.
+			 */
+			pppoe_stats.session_stats[i].stats[NSS_PPPOE_STATS_SESSION_RX_PACKETS] += stats_msg->session_stats.node.rx_packets;
+			pppoe_stats.session_stats[i].stats[NSS_PPPOE_STATS_SESSION_RX_BYTES] += stats_msg->session_stats.node.rx_bytes;
+			pppoe_stats.session_stats[i].stats[NSS_PPPOE_STATS_SESSION_TX_PACKETS] += stats_msg->session_stats.node.tx_packets;
+			pppoe_stats.session_stats[i].stats[NSS_PPPOE_STATS_SESSION_TX_BYTES] += stats_msg->session_stats.node.tx_bytes;
+			pppoe_stats.session_stats[i].stats[NSS_PPPOE_STATS_SESSION_WRONG_VERSION_OR_TYPE] += stats_msg->session_stats.exception[NSS_PPPOE_SESSION_EXCEPTION_EVENT_WRONG_VERSION_OR_TYPE];
+			pppoe_stats.session_stats[i].stats[NSS_PPPOE_STATS_SESSION_WRONG_CODE] += stats_msg->session_stats.exception[NSS_PPPOE_SESSION_EXCEPTION_EVENT_WRONG_CODE];
+			pppoe_stats.session_stats[i].stats[NSS_PPPOE_STATS_SESSION_UNSUPPORTED_PPP_PROTOCOL] += stats_msg->session_stats.exception[NSS_PPPOE_SESSION_EXCEPTION_EVENT_UNSUPPORTED_PPP_PROTOCOL];
+
+			/*
+			 * Sync PPPoE base node stats coming with this session's stats.
+			 */
+			pppoe_stats.base_stats[NSS_PPPOE_STATS_BASE_RX_PACKETS] += stats_msg->base_stats.node.rx_packets;
+			pppoe_stats.base_stats[NSS_PPPOE_STATS_BASE_RX_BYTES] += stats_msg->base_stats.node.rx_bytes;
+			pppoe_stats.base_stats[NSS_PPPOE_STATS_BASE_TX_PACKETS] += stats_msg->base_stats.node.tx_packets;
+			pppoe_stats.base_stats[NSS_PPPOE_STATS_BASE_TX_BYTES] += stats_msg->base_stats.node.tx_bytes;
+
+			for (j = 0; j < NSS_MAX_NUM_PRI; j++) {
+				pppoe_stats.base_stats[NSS_PPPOE_STATS_BASE_RX_QUEUE_0_DROPPED + j] += stats_msg->base_stats.node.rx_dropped[j];
+			}
+
+			/*
+			 * Sync PPPoE base exception stats coming with this session's stats.
+			 */
+			pppoe_stats.base_stats[NSS_PPPOE_STATS_BASE_SHORT_PPPOE_HDR_LENGTH] += stats_msg->base_stats.exception[NSS_PPPOE_BASE_EXCEPTION_EVENT_SHORT_PPPOE_HDR_LENGTH];
+			pppoe_stats.base_stats[NSS_PPPOE_STATS_BASE_SHORT_PACKET_LENGTH] += stats_msg->base_stats.exception[NSS_PPPOE_BASE_EXCEPTION_EVENT_SHORT_PACKET_LENGTH];
+			pppoe_stats.base_stats[NSS_PPPOE_STATS_BASE_WRONG_VERSION_OR_TYPE] += stats_msg->base_stats.exception[NSS_PPPOE_BASE_EXCEPTION_EVENT_WRONG_VERSION_OR_TYPE];
+			pppoe_stats.base_stats[NSS_PPPOE_STATS_BASE_WRONG_CODE] += stats_msg->base_stats.exception[NSS_PPPOE_BASE_EXCEPTION_EVENT_WRONG_CODE];
+			pppoe_stats.base_stats[NSS_PPPOE_STATS_BASE_UNSUPPORTED_PPP_PROTOCOL] += stats_msg->base_stats.exception[NSS_PPPOE_BASE_EXCEPTION_EVENT_UNSUPPORTED_PPP_PROTOCOL];
+			pppoe_stats.base_stats[NSS_PPPOE_STATS_BASE_DISABLED_BRIDGE_PACKET] += stats_msg->base_stats.exception[NSS_PPPOE_BASE_EXCEPTION_EVENT_DISABLED_BRIDGE_PACKET];
+			break;
+		}
+	}
+	spin_unlock_bh(&nss_pppoe_stats_lock);
+}
+
+/*
  * nss_pppoe_stats_ops
  */
 NSS_STATS_DECLARE_FILE_OPERATIONS(pppoe)
diff --git a/nss_pppoe_stats.h b/nss_pppoe_stats.h
index 358e7a2..70d65a3 100644
--- a/nss_pppoe_stats.h
+++ b/nss_pppoe_stats.h
@@ -1,6 +1,6 @@
 /*
  ******************************************************************************
- * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017, 2019 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.
@@ -18,33 +18,10 @@
 #define __NSS_PPPOE_STATS_H
 
 /*
- * PPPoE statistics
- */
-enum nss_pppoe_stats_session {
-	NSS_PPPOE_STATS_RX_PACKETS,
-	NSS_PPPOE_STATS_RX_BYTES,
-	NSS_PPPOE_STATS_TX_PACKETS,
-	NSS_PPPOE_STATS_TX_BYTES,
-	NSS_PPPOE_STATS_SESSION_WRONG_VERSION_OR_TYPE,
-	NSS_PPPOE_STATS_SESSION_WRONG_CODE,
-	NSS_PPPOE_STATS_SESSION_UNSUPPORTED_PPP_PROTOCOL,
-	NSS_PPPOE_STATS_SESSION_MAX
-};
-
-/*
- * PPPoE session stats structure for debug interface
- */
-struct nss_pppoe_stats_session_debug {
-	uint64_t stats[NSS_PPPOE_STATS_SESSION_MAX];
-				/* stats for the session */
-	int32_t if_index;	/* net device index for the session */
-	uint32_t if_num;	/* nss interface number */
-	bool valid;		/* dynamic interface valid flag */
-};
-
-/*
  * PPPoE statistics APIs
  */
 extern void nss_pppoe_stats_dentry_create(void);
-
+extern void nss_pppoe_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_pppoe_sync_stats_msg *stats_msg, uint16_t if_num);
+extern bool nss_pppoe_stats_pppoe_session_init(uint32_t if_num, struct net_device *dev);
+extern void nss_pppoe_stats_pppoe_session_deinit(uint32_t if_num);
 #endif /* __NSS_PPPOE_STATS_H */
diff --git a/nss_qrfs.c b/nss_qrfs.c
index baa23fe..5401efe 100644
--- a/nss_qrfs.c
+++ b/nss_qrfs.c
@@ -1,6 +1,6 @@
 /*
  **************************************************************************
- * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2019, 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.
@@ -420,7 +420,10 @@
 void nss_qrfs_register_handler(struct nss_ctx_instance *nss_ctx)
 {
 	nss_core_register_handler(nss_ctx, NSS_QRFS_INTERFACE, nss_qrfs_msg_handler, NULL);
-	nss_qrfs_stats_dentry_create();
+
+	if (nss_ctx->id == NSS_CORE_0) {
+		nss_qrfs_stats_dentry_create();
+	}
 }
 EXPORT_SYMBOL(nss_qrfs_register_handler);
 
diff --git a/nss_shaper.c b/nss_shaper.c
index 4633d35..325e9ac 100644
--- a/nss_shaper.c
+++ b/nss_shaper.c
@@ -1,6 +1,6 @@
 /*
  **************************************************************************
- * Copyright (c) 2014, 2016-2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014, 2016-2019 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.
@@ -296,7 +296,7 @@
 	}
 	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]);
+	NSS_PKT_STATS_INC(&nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_TX_PACKET]);
 	return NSS_TX_SUCCESS;
 }
 
@@ -341,7 +341,7 @@
 	}
 	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]);
+	NSS_PKT_STATS_INC(&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 c02f001..516c85d 100644
--- a/nss_stats.c
+++ b/nss_stats.c
@@ -1,6 +1,6 @@
 /*
  **************************************************************************
- * Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2019, 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.
@@ -100,7 +100,7 @@
 void nss_stats_create_dentry(char *name, const struct file_operations *ops)
 {
 	if (!debugfs_create_file(name, 0400, nss_top_main.stats_dentry, &nss_top_main, ops)) {
-		nss_warning("Faied to create debug entry for subsystem %s\n", name);
+		nss_warning("Failed to create debug entry for subsystem %s\n", name);
 	}
 }
 
@@ -367,7 +367,7 @@
 
 /*
  * nss_stats_clean()
- * 	Cleanup NSS statistics files
+ *	Cleanup NSS statistics files
  */
 void nss_stats_clean(void)
 {
@@ -382,7 +382,7 @@
 
 /*
  * nss_stats_init()
- * 	Enable NSS statistics
+ *	Enable NSS statistics
  */
 void nss_stats_init(void)
 {
diff --git a/nss_unaligned.c b/nss_unaligned.c
index 840f40d..f84ed8f 100644
--- a/nss_unaligned.c
+++ b/nss_unaligned.c
@@ -84,5 +84,8 @@
 void nss_unaligned_register_handler(struct nss_ctx_instance *nss_ctx)
 {
 	nss_core_register_handler(nss_ctx, NSS_UNALIGNED_INTERFACE, nss_unaligned_msg_handler, NULL);
-	nss_unaligned_stats_dentry_create();
+
+	if (nss_ctx->id == NSS_CORE_0) {
+		nss_unaligned_stats_dentry_create();
+	}
 }
diff --git a/nss_wifi_vdev.c b/nss_wifi_vdev.c
index 783e030..b398b21 100644
--- a/nss_wifi_vdev.c
+++ b/nss_wifi_vdev.c
@@ -1,6 +1,6 @@
 /*
  **************************************************************************
- * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2019, 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.
@@ -18,7 +18,7 @@
 
 /*
  * nss_wifi_vdev_handler()
- * 	Handle NSS -> HLOS messages for wifi_vdev
+ *	Handle NSS -> HLOS messages for wifi_vdev
  */
 static void nss_wifi_vdev_handler(struct nss_ctx_instance *nss_ctx, struct nss_cmn_msg *ncm, __attribute__((unused))void *app_data)
 {
@@ -84,7 +84,7 @@
 
 /*
  * nss_wifi_vdev_base_tx_msg()
- * 	Transmit a wifi vdev base message to NSSFW
+ *	Transmit a wifi vdev base message to NSSFW
  */
 nss_tx_status_t nss_wifi_vdev_base_tx_msg(struct nss_ctx_instance *nss_ctx, struct nss_wifi_vdev_msg *msg)
 {
@@ -115,7 +115,7 @@
 
 /*
  * nss_wifi_vdev_tx_msg()
- * 	Transmit a wifi vdev message to NSSFW
+ *	Transmit a wifi vdev message to NSSFW
  */
 nss_tx_status_t nss_wifi_vdev_tx_msg(struct nss_ctx_instance *nss_ctx, struct nss_wifi_vdev_msg *msg)
 {
@@ -146,7 +146,7 @@
 
 /*
  * nss_wifi_vdev_tx_msg_ext()
- * 	Send special data packet with metadata for vap processing
+ *	Send special data packet with metadata for vap processing
  */
 nss_tx_status_t nss_wifi_vdev_tx_msg_ext(struct nss_ctx_instance *nss_ctx, struct sk_buff *os_buf)
 {
@@ -187,7 +187,7 @@
 
 	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_INC(&nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_TX_CMD_REQ]);
 
 return status;
 }
@@ -195,7 +195,7 @@
 
 /*
  * nss_wifi_vdev_tx_buf
- * 	Send data packet for vap processing
+ *	Send data packet for vap processing
  */
 nss_tx_status_t nss_wifi_vdev_tx_buf(struct nss_ctx_instance *nss_ctx, struct sk_buff *os_buf, uint32_t if_num)
 {