[qca-nss-drv] Break up statistics implementation

Break up the centralized statistics implementation to be subsystem based
statistics implementation.

Change-Id: Ibc14d88f391e816d3d6284a57ea6676f2842ac70
Signed-off-by: Yu Huang <yuhuang@codeaurora.org>
diff --git a/Makefile b/Makefile
index 33b5dbd..5d7afdf 100644
--- a/Makefile
+++ b/Makefile
@@ -10,59 +10,85 @@
 qca-nss-drv-objs := \
 			nss_bridge.o \
 			nss_capwap.o \
+			nss_capwap_stats.o \
 			nss_cmn.o \
 			nss_core.o \
 			nss_coredump.o \
 			nss_dtls.o \
+			nss_dtls_stats.o \
 			nss_dynamic_interface.o \
 			nss_edma.o \
+			nss_edma_stats.o \
 			nss_eth_rx.o \
+			nss_eth_rx_stats.o \
 			nss_gre.o \
+			nss_gre_stats.o \
 			nss_gre_redir.o \
+			nss_gre_redir_stats.o \
 			nss_gre_tunnel.o \
+			nss_gre_tunnel_stats.o \
 			nss_if.o \
 			nss_init.o \
 			nss_ipsec.o \
 			nss_ipv4.o \
+			nss_ipv4_stats.o \
 			nss_ipv4_log.o \
 			nss_ipv4_reasm.o \
+			nss_ipv4_reasm_stats.o \
 			nss_ipv6.o \
+			nss_ipv6_stats.o \
 			nss_ipv6_log.o \
 			nss_ipv6_reasm.o \
+			nss_ipv6_reasm_stats.o \
 			nss_l2tpv2.o \
+			nss_l2tpv2_stats.o \
 			nss_lag.o \
 			nss_log.o \
 			nss_lso_rx.o \
+			nss_lso_rx_stats.o \
 			nss_map_t.o \
+			nss_map_t_stats.o \
 			nss_n2h.o \
+			nss_n2h_stats.o \
 			nss_oam.o \
 			nss_phys_if.o \
 			nss_pm.o \
 			nss_profiler.o \
 			nss_project.o \
 			nss_portid.o \
+			nss_portid_stats.o \
 			nss_ppe.o \
+			nss_ppe_stats.o \
 			nss_pppoe.o \
+			nss_pppoe_stats.o \
 			nss_pptp.o \
+			nss_pptp_stats.o \
 			nss_shaper.o \
 			nss_sjack.o \
+			nss_sjack_stats.o \
 			nss_stats.o \
 			nss_tstamp.o \
 			nss_tun6rd.o \
 			nss_trustsec_tx.o \
+			nss_trustsec_tx_stats.o \
 			nss_tunipip6.o \
 			nss_virt_if.o \
+			nss_virt_if_stats.o \
 			nss_vlan.o \
 			nss_tstamp.o \
 			nss_wifi.o \
+			nss_wifi_stats.o \
 			nss_wifi_vdev.o \
 			nss_wifi_if.o \
-			nss_wifili.o
+			nss_wifi_if_stats.o \
+			nss_wifili.o \
+			nss_wifili_stats.o
 
 #
 # TODO: Deprecated files should be removed before merge
 #
-qca-nss-drv-objs += nss_tx_rx_virt_if.o
+qca-nss-drv-objs += nss_tx_rx_virt_if.o \
+			nss_tx_rx_virt_if_stats.o
 
 # Base NSS data plane/HAL support
 qca-nss-drv-objs += nss_data_plane/nss_data_plane.o
diff --git a/Makefile.fsm b/Makefile.fsm
index 241fa7d..61f4f1e 100644
--- a/Makefile.fsm
+++ b/Makefile.fsm
@@ -9,57 +9,82 @@
 qca-nss-drv-objs := \
 			nss_bridge.o \
 			nss_capwap.o \
+			nss_capwap_stats.o \
 			nss_cmn.o \
 			nss_core.o \
 			nss_coredump.o \
 			nss_crypto.o \
 			nss_dtls.o \
+			nss_dtls_stats.o \
 			nss_dynamic_interface.o \
 			nss_edma.o \
+			nss_edma_stats.o \
 			nss_eth_rx.o \
+			nss_eth_rx_stats.o \
 			nss_gre.o \
+			nss_gre_stats.o \
 			nss_gre_redir.o \
+			nss_gre_redir_stats.o \
 			nss_gre_tunnel.o \
+			nss_gre_tunnel_stats.o \
 			nss_if.o \
 			nss_init.o \
 			nss_ipsec.o \
 			nss_ipv4.o \
+			nss_ipv4_stats.o \
 			nss_ipv4_log.o \
 			nss_ipv4_reasm.o \
+			nss_ipv4_reasm_stats.o \
 			nss_ipv6.o \
+			nss_ipv6_stats.o \
 			nss_ipv6_log.o \
 			nss_ipv6_reasm.o \
+			nss_ipv6_reasm_stats.o \
 			nss_l2tpv2.o \
+			nss_l2tpv2_stats.o \
 			nss_lag.o \
 			nss_log.o \
 			nss_lso_rx.o \
+			nss_lso_rx_stats.o \
 			nss_map_t.o \
+			nss_map_t_stats.o \
 			nss_n2h.o \
+			nss_n2h_stats.o \
 			nss_oam.o \
 			nss_phys_if.o \
 			nss_pm.o \
 			nss_profiler.o \
 			nss_portid.o \
+			nss_portid_stats.o \
 			nss_ppe.o \
+			nss_ppe_stats.o \
 			nss_pppoe.o \
+			nss_pppoe_stats.o \
 			nss_pptp.o \
+			nss_pptp_stats.o \
 			nss_shaper.o \
 			nss_sjack.o \
+			nss_sjack_stats.o \
 			nss_stats.o \
 			nss_tstamp.o \
 			nss_tun6rd.o \
 			nss_trustsec_tx.o \
+			nss_trustsec_tx_stats.o \
 			nss_tunipip6.o \
 			nss_virt_if.o \
+			nss_virt_if_stats.o \
 			nss_vlan.o \
 			nss_wifi.o \
+			nss_wifi_stats.o \
 			nss_wifi_if.o \
+			nss_wifi_if_stats.o \
 			nss_wifi_vdev.o
 
 #
 # TODO: Deprecated files should be removed before merge
 #
-qca-nss-drv-objs += nss_tx_rx_virt_if.o
+qca-nss-drv-objs += nss_tx_rx_virt_if.o \
+			nss_tx_rx_virt_if_stats.o
 
 qca-nss-drv-objs += nss_hal/nss_hal.o
 qca-nss-drv-objs += nss_hal/fsm9010/nss_hal_pvt.o
diff --git a/exports/nss_gre.h b/exports/nss_gre.h
index d2a2d19..93fbf81 100644
--- a/exports/nss_gre.h
+++ b/exports/nss_gre.h
@@ -297,32 +297,6 @@
 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.
diff --git a/exports/nss_ipv4.h b/exports/nss_ipv4.h
index 10880fa..d79e3de 100644
--- a/exports/nss_ipv4.h
+++ b/exports/nss_ipv4.h
@@ -560,89 +560,89 @@
 };
 
 /**
- * exception_events_ipv4
+ * nss_ipv4_exception_events
  *	Exception events from the bridge or route handler.
  */
-enum exception_events_ipv4 {
-	NSS_EXCEPTION_EVENT_IPV4_ICMP_HEADER_INCOMPLETE,
-	NSS_EXCEPTION_EVENT_IPV4_ICMP_UNHANDLED_TYPE,
-	NSS_EXCEPTION_EVENT_IPV4_ICMP_IPV4_HEADER_INCOMPLETE,
-	NSS_EXCEPTION_EVENT_IPV4_ICMP_IPV4_UDP_HEADER_INCOMPLETE,
-	NSS_EXCEPTION_EVENT_IPV4_ICMP_IPV4_TCP_HEADER_INCOMPLETE,
-	NSS_EXCEPTION_EVENT_IPV4_ICMP_IPV4_UNKNOWN_PROTOCOL,
-	NSS_EXCEPTION_EVENT_IPV4_ICMP_NO_ICME,
-	NSS_EXCEPTION_EVENT_IPV4_ICMP_FLUSH_TO_HOST,
-	NSS_EXCEPTION_EVENT_IPV4_TCP_HEADER_INCOMPLETE,
-	NSS_EXCEPTION_EVENT_IPV4_TCP_NO_ICME,
-	NSS_EXCEPTION_EVENT_IPV4_TCP_IP_OPTION,
-	NSS_EXCEPTION_EVENT_IPV4_TCP_IP_FRAGMENT,
-	NSS_EXCEPTION_EVENT_IPV4_TCP_SMALL_TTL,
-	NSS_EXCEPTION_EVENT_IPV4_TCP_NEEDS_FRAGMENTATION,
-	NSS_EXCEPTION_EVENT_IPV4_TCP_FLAGS,
-	NSS_EXCEPTION_EVENT_IPV4_TCP_SEQ_EXCEEDS_RIGHT_EDGE,
-	NSS_EXCEPTION_EVENT_IPV4_TCP_SMALL_DATA_OFFS,
-	NSS_EXCEPTION_EVENT_IPV4_TCP_BAD_SACK,
-	NSS_EXCEPTION_EVENT_IPV4_TCP_BIG_DATA_OFFS,
-	NSS_EXCEPTION_EVENT_IPV4_TCP_SEQ_BEFORE_LEFT_EDGE,
-	NSS_EXCEPTION_EVENT_IPV4_TCP_ACK_EXCEEDS_RIGHT_EDGE,
-	NSS_EXCEPTION_EVENT_IPV4_TCP_ACK_BEFORE_LEFT_EDGE,
-	NSS_EXCEPTION_EVENT_IPV4_UDP_HEADER_INCOMPLETE,
-	NSS_EXCEPTION_EVENT_IPV4_UDP_NO_ICME,
-	NSS_EXCEPTION_EVENT_IPV4_UDP_IP_OPTION,
-	NSS_EXCEPTION_EVENT_IPV4_UDP_IP_FRAGMENT,
-	NSS_EXCEPTION_EVENT_IPV4_UDP_SMALL_TTL,
-	NSS_EXCEPTION_EVENT_IPV4_UDP_NEEDS_FRAGMENTATION,
-	NSS_EXCEPTION_EVENT_IPV4_WRONG_TARGET_MAC,
-	NSS_EXCEPTION_EVENT_IPV4_HEADER_INCOMPLETE,
-	NSS_EXCEPTION_EVENT_IPV4_BAD_TOTAL_LENGTH,
-	NSS_EXCEPTION_EVENT_IPV4_BAD_CHECKSUM,
-	NSS_EXCEPTION_EVENT_IPV4_NON_INITIAL_FRAGMENT,
-	NSS_EXCEPTION_EVENT_IPV4_DATAGRAM_INCOMPLETE,
-	NSS_EXCEPTION_EVENT_IPV4_OPTIONS_INCOMPLETE,
-	NSS_EXCEPTION_EVENT_IPV4_UNKNOWN_PROTOCOL,
-	NSS_EXCEPTION_EVENT_IPV4_ESP_HEADER_INCOMPLETE,
-	NSS_EXCEPTION_EVENT_IPV4_ESP_NO_ICME,
-	NSS_EXCEPTION_EVENT_IPV4_ESP_IP_OPTION,
-	NSS_EXCEPTION_EVENT_IPV4_ESP_IP_FRAGMENT,
-	NSS_EXCEPTION_EVENT_IPV4_ESP_SMALL_TTL,
-	NSS_EXCEPTION_EVENT_IPV4_ESP_NEEDS_FRAGMENTATION,
-	NSS_EXCEPTION_EVENT_IPV4_IVID_MISMATCH,
-	NSS_EXCEPTION_EVENT_IPV4_IVID_MISSING,
-	NSS_EXCEPTION_EVENT_IPV4_6RD_NO_ICME,
-	NSS_EXCEPTION_EVENT_IPV4_6RD_IP_OPTION,
-	NSS_EXCEPTION_EVENT_IPV4_6RD_IP_FRAGMENT,
-	NSS_EXCEPTION_EVENT_IPV4_6RD_NEEDS_FRAGMENTATION,
-	NSS_EXCEPTION_EVENT_IPV4_DSCP_MARKING_MISMATCH,
-	NSS_EXCEPTION_EVENT_IPV4_VLAN_MARKING_MISMATCH,
-	NSS_EXCEPTION_EVENT_IPV4_DEPRECATED,
-	NSS_EXCEPTION_EVENT_GRE_HEADER_INCOMPLETE,
-	NSS_EXCEPTION_EVENT_GRE_NO_ICME,
-	NSS_EXCEPTION_EVENT_GRE_IP_OPTION,
-	NSS_EXCEPTION_EVENT_GRE_IP_FRAGMENT,
-	NSS_EXCEPTION_EVENT_GRE_SMALL_TTL,
-	NSS_EXCEPTION_EVENT_GRE_NEEDS_FRAGMENTATION,
-	NSS_EXCEPTION_EVENT_IPV4_PPTP_GRE_SESSION_MATCH_FAIL,
-	NSS_EXCEPTION_EVENT_IPV4_PPTP_GRE_INVALID_PROTO,
-	NSS_EXCEPTION_EVENT_IPV4_PPTP_GRE_NO_CME,
-	NSS_EXCEPTION_EVENT_IPV4_PPTP_GRE_IP_OPTION,
-	NSS_EXCEPTION_EVENT_IPV4_PPTP_GRE_IP_FRAGMENT,
-	NSS_EXCEPTION_EVENT_IPV4_PPTP_GRE_SMALL_TTL,
-	NSS_EXCEPTION_EVENT_IPV4_PPTP_GRE_NEEDS_FRAGMENTATION,
-	NSS_EXCEPTION_EVENT_IPV4_DESTROY,
-	NSS_EXCEPTION_EVENT_IPV4_FRAG_DF_SET,
-	NSS_EXCEPTION_EVENT_IPV4_FRAG_FAIL,
-	NSS_EXCEPTION_EVENT_IPV4_ICMP_IPV4_UDPLITE_HEADER_INCOMPLETE,
-	NSS_EXCEPTION_EVENT_IPV4_UDPLITE_HEADER_INCOMPLETE,
-	NSS_EXCEPTION_EVENT_IPV4_UDPLITE_NO_ICME,
-	NSS_EXCEPTION_EVENT_IPV4_UDPLITE_IP_OPTION,
-	NSS_EXCEPTION_EVENT_IPV4_UDPLITE_IP_FRAGMENT,
-	NSS_EXCEPTION_EVENT_IPV4_UDPLITE_SMALL_TTL,
-	NSS_EXCEPTION_EVENT_IPV4_UDPLITE_NEEDS_FRAGMENTATION,
-	NSS_EXCEPTION_EVENT_IPV4_MC_UDP_NO_ICME,
-	NSS_EXCEPTION_EVENT_IPV4_MC_MEM_ALLOC_FAILURE,
-	NSS_EXCEPTION_EVENT_IPV4_MC_UPDATE_FAILURE,
-	NSS_EXCEPTION_EVENT_IPV4_MC_PBUF_ALLOC_FAILURE,
-	NSS_EXCEPTION_EVENT_IPV4_MAX
+enum nss_ipv4_exception_events {
+	NSS_IPV4_EXCEPTION_EVENT_ICMP_HEADER_INCOMPLETE,
+	NSS_IPV4_EXCEPTION_EVENT_ICMP_UNHANDLED_TYPE,
+	NSS_IPV4_EXCEPTION_EVENT_ICMP_IPV4_HEADER_INCOMPLETE,
+	NSS_IPV4_EXCEPTION_EVENT_ICMP_IPV4_UDP_HEADER_INCOMPLETE,
+	NSS_IPV4_EXCEPTION_EVENT_ICMP_IPV4_TCP_HEADER_INCOMPLETE,
+	NSS_IPV4_EXCEPTION_EVENT_ICMP_IPV4_UNKNOWN_PROTOCOL,
+	NSS_IPV4_EXCEPTION_EVENT_ICMP_NO_ICME,
+	NSS_IPV4_EXCEPTION_EVENT_ICMP_FLUSH_TO_HOST,
+	NSS_IPV4_EXCEPTION_EVENT_TCP_HEADER_INCOMPLETE,
+	NSS_IPV4_EXCEPTION_EVENT_TCP_NO_ICME,
+	NSS_IPV4_EXCEPTION_EVENT_TCP_IP_OPTION,
+	NSS_IPV4_EXCEPTION_EVENT_TCP_IP_FRAGMENT,
+	NSS_IPV4_EXCEPTION_EVENT_TCP_SMALL_TTL,
+	NSS_IPV4_EXCEPTION_EVENT_TCP_NEEDS_FRAGMENTATION,
+	NSS_IPV4_EXCEPTION_EVENT_TCP_FLAGS,
+	NSS_IPV4_EXCEPTION_EVENT_TCP_SEQ_EXCEEDS_RIGHT_EDGE,
+	NSS_IPV4_EXCEPTION_EVENT_TCP_SMALL_DATA_OFFS,
+	NSS_IPV4_EXCEPTION_EVENT_TCP_BAD_SACK,
+	NSS_IPV4_EXCEPTION_EVENT_TCP_BIG_DATA_OFFS,
+	NSS_IPV4_EXCEPTION_EVENT_TCP_SEQ_BEFORE_LEFT_EDGE,
+	NSS_IPV4_EXCEPTION_EVENT_TCP_ACK_EXCEEDS_RIGHT_EDGE,
+	NSS_IPV4_EXCEPTION_EVENT_TCP_ACK_BEFORE_LEFT_EDGE,
+	NSS_IPV4_EXCEPTION_EVENT_UDP_HEADER_INCOMPLETE,
+	NSS_IPV4_EXCEPTION_EVENT_UDP_NO_ICME,
+	NSS_IPV4_EXCEPTION_EVENT_UDP_IP_OPTION,
+	NSS_IPV4_EXCEPTION_EVENT_UDP_IP_FRAGMENT,
+	NSS_IPV4_EXCEPTION_EVENT_UDP_SMALL_TTL,
+	NSS_IPV4_EXCEPTION_EVENT_UDP_NEEDS_FRAGMENTATION,
+	NSS_IPV4_EXCEPTION_EVENT_WRONG_TARGET_MAC,
+	NSS_IPV4_EXCEPTION_EVENT_HEADER_INCOMPLETE,
+	NSS_IPV4_EXCEPTION_EVENT_BAD_TOTAL_LENGTH,
+	NSS_IPV4_EXCEPTION_EVENT_BAD_CHECKSUM,
+	NSS_IPV4_EXCEPTION_EVENT_NON_INITIAL_FRAGMENT,
+	NSS_IPV4_EXCEPTION_EVENT_DATAGRAM_INCOMPLETE,
+	NSS_IPV4_EXCEPTION_EVENT_OPTIONS_INCOMPLETE,
+	NSS_IPV4_EXCEPTION_EVENT_UNKNOWN_PROTOCOL,
+	NSS_IPV4_EXCEPTION_EVENT_ESP_HEADER_INCOMPLETE,
+	NSS_IPV4_EXCEPTION_EVENT_ESP_NO_ICME,
+	NSS_IPV4_EXCEPTION_EVENT_ESP_IP_OPTION,
+	NSS_IPV4_EXCEPTION_EVENT_ESP_IP_FRAGMENT,
+	NSS_IPV4_EXCEPTION_EVENT_ESP_SMALL_TTL,
+	NSS_IPV4_EXCEPTION_EVENT_ESP_NEEDS_FRAGMENTATION,
+	NSS_IPV4_EXCEPTION_EVENT_IVID_MISMATCH,
+	NSS_IPV4_EXCEPTION_EVENT_IVID_MISSING,
+	NSS_IPV4_EXCEPTION_EVENT_6RD_NO_ICME,
+	NSS_IPV4_EXCEPTION_EVENT_6RD_IP_OPTION,
+	NSS_IPV4_EXCEPTION_EVENT_6RD_IP_FRAGMENT,
+	NSS_IPV4_EXCEPTION_EVENT_6RD_NEEDS_FRAGMENTATION,
+	NSS_IPV4_EXCEPTION_EVENT_DSCP_MARKING_MISMATCH,
+	NSS_IPV4_EXCEPTION_EVENT_VLAN_MARKING_MISMATCH,
+	NSS_IPV4_EXCEPTION_EVENT_DEPRECATED,
+	NSS_IPV4_EXCEPTION_EVENT_GRE_HEADER_INCOMPLETE,
+	NSS_IPV4_EXCEPTION_EVENT_GRE_NO_ICME,
+	NSS_IPV4_EXCEPTION_EVENT_GRE_IP_OPTION,
+	NSS_IPV4_EXCEPTION_EVENT_GRE_IP_FRAGMENT,
+	NSS_IPV4_EXCEPTION_EVENT_GRE_SMALL_TTL,
+	NSS_IPV4_EXCEPTION_EVENT_GRE_NEEDS_FRAGMENTATION,
+	NSS_IPV4_EXCEPTION_EVENT_PPTP_GRE_SESSION_MATCH_FAIL,
+	NSS_IPV4_EXCEPTION_EVENT_PPTP_GRE_INVALID_PROTO,
+	NSS_IPV4_EXCEPTION_EVENT_PPTP_GRE_NO_CME,
+	NSS_IPV4_EXCEPTION_EVENT_PPTP_GRE_IP_OPTION,
+	NSS_IPV4_EXCEPTION_EVENT_PPTP_GRE_IP_FRAGMENT,
+	NSS_IPV4_EXCEPTION_EVENT_PPTP_GRE_SMALL_TTL,
+	NSS_IPV4_EXCEPTION_EVENT_PPTP_GRE_NEEDS_FRAGMENTATION,
+	NSS_IPV4_EXCEPTION_EVENT_DESTROY,
+	NSS_IPV4_EXCEPTION_EVENT_FRAG_DF_SET,
+	NSS_IPV4_EXCEPTION_EVENT_FRAG_FAIL,
+	NSS_IPV4_EXCEPTION_EVENT_ICMP_IPV4_UDPLITE_HEADER_INCOMPLETE,
+	NSS_IPV4_EXCEPTION_EVENT_UDPLITE_HEADER_INCOMPLETE,
+	NSS_IPV4_EXCEPTION_EVENT_UDPLITE_NO_ICME,
+	NSS_IPV4_EXCEPTION_EVENT_UDPLITE_IP_OPTION,
+	NSS_IPV4_EXCEPTION_EVENT_UDPLITE_IP_FRAGMENT,
+	NSS_IPV4_EXCEPTION_EVENT_UDPLITE_SMALL_TTL,
+	NSS_IPV4_EXCEPTION_EVENT_UDPLITE_NEEDS_FRAGMENTATION,
+	NSS_IPV4_EXCEPTION_EVENT_MC_UDP_NO_ICME,
+	NSS_IPV4_EXCEPTION_EVENT_MC_MEM_ALLOC_FAILURE,
+	NSS_IPV4_EXCEPTION_EVENT_MC_UPDATE_FAILURE,
+	NSS_IPV4_EXCEPTION_EVENT_MC_PBUF_ALLOC_FAILURE,
+	NSS_IPV4_EXCEPTION_EVENT_MAX
 };
 
 /**
@@ -696,7 +696,7 @@
 
 	uint32_t ipv4_mc_connection_flushes;
 			/**< Number of multicast connection flushes. */
-	uint32_t exception_events[NSS_EXCEPTION_EVENT_IPV4_MAX];
+	uint32_t exception_events[NSS_IPV4_EXCEPTION_EVENT_MAX];
 			/**< Number of exception events. */
 };
 
diff --git a/exports/nss_ipv6.h b/exports/nss_ipv6.h
index 70ae39a..dd35df1 100644
--- a/exports/nss_ipv6.h
+++ b/exports/nss_ipv6.h
@@ -149,61 +149,61 @@
 		/**< MAC address for the return interface is valid. */
 
 /**
- * exception_events_ipv6
+ * nss_ipv6_exception_events
  *	Exception events from an IPv6 bridge or route handler.
  */
-enum exception_events_ipv6 {
-	NSS_EXCEPTION_EVENT_IPV6_ICMP_HEADER_INCOMPLETE,
-	NSS_EXCEPTION_EVENT_IPV6_ICMP_UNHANDLED_TYPE,
-	NSS_EXCEPTION_EVENT_IPV6_ICMP_IPV6_HEADER_INCOMPLETE,
-	NSS_EXCEPTION_EVENT_IPV6_ICMP_IPV6_UDP_HEADER_INCOMPLETE,
-	NSS_EXCEPTION_EVENT_IPV6_ICMP_IPV6_TCP_HEADER_INCOMPLETE,
-	NSS_EXCEPTION_EVENT_IPV6_ICMP_IPV6_UNKNOWN_PROTOCOL,
-	NSS_EXCEPTION_EVENT_IPV6_ICMP_NO_ICME,
-	NSS_EXCEPTION_EVENT_IPV6_ICMP_FLUSH_TO_HOST,
-	NSS_EXCEPTION_EVENT_IPV6_TCP_HEADER_INCOMPLETE,
-	NSS_EXCEPTION_EVENT_IPV6_TCP_NO_ICME,
-	NSS_EXCEPTION_EVENT_IPV6_TCP_SMALL_HOP_LIMIT,
-	NSS_EXCEPTION_EVENT_IPV6_TCP_NEEDS_FRAGMENTATION,
-	NSS_EXCEPTION_EVENT_IPV6_TCP_FLAGS,
-	NSS_EXCEPTION_EVENT_IPV6_TCP_SEQ_EXCEEDS_RIGHT_EDGE,
-	NSS_EXCEPTION_EVENT_IPV6_TCP_SMALL_DATA_OFFS,
-	NSS_EXCEPTION_EVENT_IPV6_TCP_BAD_SACK,
-	NSS_EXCEPTION_EVENT_IPV6_TCP_BIG_DATA_OFFS,
-	NSS_EXCEPTION_EVENT_IPV6_TCP_SEQ_BEFORE_LEFT_EDGE,
-	NSS_EXCEPTION_EVENT_IPV6_TCP_ACK_EXCEEDS_RIGHT_EDGE,
-	NSS_EXCEPTION_EVENT_IPV6_TCP_ACK_BEFORE_LEFT_EDGE,
-	NSS_EXCEPTION_EVENT_IPV6_UDP_HEADER_INCOMPLETE,
-	NSS_EXCEPTION_EVENT_IPV6_UDP_NO_ICME,
-	NSS_EXCEPTION_EVENT_IPV6_UDP_SMALL_HOP_LIMIT,
-	NSS_EXCEPTION_EVENT_IPV6_UDP_NEEDS_FRAGMENTATION,
-	NSS_EXCEPTION_EVENT_IPV6_WRONG_TARGET_MAC,
-	NSS_EXCEPTION_EVENT_IPV6_HEADER_INCOMPLETE,
-	NSS_EXCEPTION_EVENT_IPV6_UNKNOWN_PROTOCOL,
-	NSS_EXCEPTION_EVENT_IPV6_IVID_MISMATCH,
-	NSS_EXCEPTION_EVENT_IPV6_IVID_MISSING,
-	NSS_EXCEPTION_EVENT_IPV6_DSCP_MARKING_MISMATCH,
-	NSS_EXCEPTION_EVENT_IPV6_VLAN_MARKING_MISMATCH,
-	NSS_EXCEPTION_EVENT_IPV6_DEPRECATED,
-	NSS_EXCEPTION_EVENT_IPV6_GRE_NO_ICME,
-	NSS_EXCEPTION_EVENT_IPV6_GRE_NEEDS_FRAGMENTATION,
-	NSS_EXCEPTION_EVENT_IPV6_GRE_SMALL_HOP_LIMIT,
-	NSS_EXCEPTION_EVENT_IPV6_DESTROY,
-	NSS_EXCEPTION_EVENT_IPV6_ICMP_IPV6_UDPLITE_HEADER_INCOMPLETE,
-	NSS_EXCEPTION_EVENT_IPV6_UDPLITE_HEADER_INCOMPLETE,
-	NSS_EXCEPTION_EVENT_IPV6_UDPLITE_NO_ICME,
-	NSS_EXCEPTION_EVENT_IPV6_UDPLITE_SMALL_HOP_LIMIT,
-	NSS_EXCEPTION_EVENT_IPV6_UDPLITE_NEEDS_FRAGMENTATION,
-	NSS_EXCEPTION_EVENT_IPV6_MC_UDP_NO_ICME,
-	NSS_EXCEPTION_EVENT_IPV6_MC_MEM_ALLOC_FAILURE,
-	NSS_EXCEPTION_EVENT_IPV6_MC_UPDATE_FAILURE,
-	NSS_EXCEPTION_EVENT_IPV6_MC_PBUF_ALLOC_FAILURE,
-	NSS_EXCEPTION_EVENT_IPV6_ESP_HEADER_INCOMPLETE,
-	NSS_EXCEPTION_EVENT_IPV6_ESP_NO_ICME,
-	NSS_EXCEPTION_EVENT_IPV6_ESP_IP_FRAGMENT,
-	NSS_EXCEPTION_EVENT_IPV6_ESP_SMALL_HOP_LIMIT,
-	NSS_EXCEPTION_EVENT_IPV6_ESP_NEEDS_FRAGMENTATION,
-	NSS_EXCEPTION_EVENT_IPV6_MAX
+enum nss_ipv6_exception_events {
+	NSS_IPV6_EXCEPTION_EVENT_ICMP_HEADER_INCOMPLETE,
+	NSS_IPV6_EXCEPTION_EVENT_ICMP_UNHANDLED_TYPE,
+	NSS_IPV6_EXCEPTION_EVENT_ICMP_IPV6_HEADER_INCOMPLETE,
+	NSS_IPV6_EXCEPTION_EVENT_ICMP_IPV6_UDP_HEADER_INCOMPLETE,
+	NSS_IPV6_EXCEPTION_EVENT_ICMP_IPV6_TCP_HEADER_INCOMPLETE,
+	NSS_IPV6_EXCEPTION_EVENT_ICMP_IPV6_UNKNOWN_PROTOCOL,
+	NSS_IPV6_EXCEPTION_EVENT_ICMP_NO_ICME,
+	NSS_IPV6_EXCEPTION_EVENT_ICMP_FLUSH_TO_HOST,
+	NSS_IPV6_EXCEPTION_EVENT_TCP_HEADER_INCOMPLETE,
+	NSS_IPV6_EXCEPTION_EVENT_TCP_NO_ICME,
+	NSS_IPV6_EXCEPTION_EVENT_TCP_SMALL_HOP_LIMIT,
+	NSS_IPV6_EXCEPTION_EVENT_TCP_NEEDS_FRAGMENTATION,
+	NSS_IPV6_EXCEPTION_EVENT_TCP_FLAGS,
+	NSS_IPV6_EXCEPTION_EVENT_TCP_SEQ_EXCEEDS_RIGHT_EDGE,
+	NSS_IPV6_EXCEPTION_EVENT_TCP_SMALL_DATA_OFFS,
+	NSS_IPV6_EXCEPTION_EVENT_TCP_BAD_SACK,
+	NSS_IPV6_EXCEPTION_EVENT_TCP_BIG_DATA_OFFS,
+	NSS_IPV6_EXCEPTION_EVENT_TCP_SEQ_BEFORE_LEFT_EDGE,
+	NSS_IPV6_EXCEPTION_EVENT_TCP_ACK_EXCEEDS_RIGHT_EDGE,
+	NSS_IPV6_EXCEPTION_EVENT_TCP_ACK_BEFORE_LEFT_EDGE,
+	NSS_IPV6_EXCEPTION_EVENT_UDP_HEADER_INCOMPLETE,
+	NSS_IPV6_EXCEPTION_EVENT_UDP_NO_ICME,
+	NSS_IPV6_EXCEPTION_EVENT_UDP_SMALL_HOP_LIMIT,
+	NSS_IPV6_EXCEPTION_EVENT_UDP_NEEDS_FRAGMENTATION,
+	NSS_IPV6_EXCEPTION_EVENT_WRONG_TARGET_MAC,
+	NSS_IPV6_EXCEPTION_EVENT_HEADER_INCOMPLETE,
+	NSS_IPV6_EXCEPTION_EVENT_UNKNOWN_PROTOCOL,
+	NSS_IPV6_EXCEPTION_EVENT_IVID_MISMATCH,
+	NSS_IPV6_EXCEPTION_EVENT_IVID_MISSING,
+	NSS_IPV6_EXCEPTION_EVENT_DSCP_MARKING_MISMATCH,
+	NSS_IPV6_EXCEPTION_EVENT_VLAN_MARKING_MISMATCH,
+	NSS_IPV6_EXCEPTION_EVENT_DEPRECATED,
+	NSS_IPV6_EXCEPTION_EVENT_GRE_NO_ICME,
+	NSS_IPV6_EXCEPTION_EVENT_GRE_NEEDS_FRAGMENTATION,
+	NSS_IPV6_EXCEPTION_EVENT_GRE_SMALL_HOP_LIMIT,
+	NSS_IPV6_EXCEPTION_EVENT_DESTROY,
+	NSS_IPV6_EXCEPTION_EVENT_ICMP_IPV6_UDPLITE_HEADER_INCOMPLETE,
+	NSS_IPV6_EXCEPTION_EVENT_UDPLITE_HEADER_INCOMPLETE,
+	NSS_IPV6_EXCEPTION_EVENT_UDPLITE_NO_ICME,
+	NSS_IPV6_EXCEPTION_EVENT_UDPLITE_SMALL_HOP_LIMIT,
+	NSS_IPV6_EXCEPTION_EVENT_UDPLITE_NEEDS_FRAGMENTATION,
+	NSS_IPV6_EXCEPTION_EVENT_MC_UDP_NO_ICME,
+	NSS_IPV6_EXCEPTION_EVENT_MC_MEM_ALLOC_FAILURE,
+	NSS_IPV6_EXCEPTION_EVENT_MC_UPDATE_FAILURE,
+	NSS_IPV6_EXCEPTION_EVENT_MC_PBUF_ALLOC_FAILURE,
+	NSS_IPV6_EXCEPTION_EVENT_ESP_HEADER_INCOMPLETE,
+	NSS_IPV6_EXCEPTION_EVENT_ESP_NO_ICME,
+	NSS_IPV6_EXCEPTION_EVENT_ESP_IP_FRAGMENT,
+	NSS_IPV6_EXCEPTION_EVENT_ESP_SMALL_HOP_LIMIT,
+	NSS_IPV6_EXCEPTION_EVENT_ESP_NEEDS_FRAGMENTATION,
+	NSS_IPV6_EXCEPTION_EVENT_MAX
 };
 
 /**
@@ -660,7 +660,7 @@
 
 	uint32_t ipv6_mc_connection_flushes;
 			/**< Number of multicast connection flushes. */
-	uint32_t exception_events[NSS_EXCEPTION_EVENT_IPV6_MAX];
+	uint32_t exception_events[NSS_IPV6_EXCEPTION_EVENT_MAX];
 			/**< Number of exception events. */
 };
 
diff --git a/exports/nss_virt_if.h b/exports/nss_virt_if.h
index a4b8bd7..c7eeb53 100644
--- a/exports/nss_virt_if.h
+++ b/exports/nss_virt_if.h
@@ -312,19 +312,6 @@
 extern void nss_virt_if_unregister(struct nss_virt_if_handle *handle);
 
 /**
- * nss_virt_if_copy_stats
- *	Gets statistics for the virtual interface from the NSS driver.
- *
- * @param[in]  if_num  NSS interface number (provided during dynamic interface allocation).
- * @param[in]  i       Index of statistics.
- * @param[out] line    Buffer into which the statistics are copied.
- *
- * @return
- * Returns 0 if if_num is not in range, or the number of bytes copied.
- */
-extern int32_t nss_virt_if_copy_stats(int32_t if_num, int i, char *line);
-
-/**
  * nss_virt_if_get_interface_num
  *	Returns the virtual interface number associated with the handle.
  *
diff --git a/exports/nss_wifili_if.h b/exports/nss_wifili_if.h
index 4bbd7d0..8591855 100644
--- a/exports/nss_wifili_if.h
+++ b/exports/nss_wifili_if.h
@@ -911,4 +911,5 @@
  * void
  */
 void nss_unregister_wifili_radio_if(uint32_t if_num);
+
 #endif /* __NSS_WIFILI_H */
diff --git a/nss_capwap.c b/nss_capwap.c
index 0366da9..f14bfaf 100644
--- a/nss_capwap.c
+++ b/nss_capwap.c
@@ -15,13 +15,14 @@
  */
 
  /*
-  * nss_capwap.h
+  * nss_capwap.c
   *	NSS CAPWAP driver interface APIs
   */
 #include "nss_core.h"
 #include "nss_capwap.h"
 #include "nss_cmn.h"
 #include "nss_tx_rx_common.h"
+#include "nss_capwap_stats.h"
 
 /*
  * Spinlock for protecting tunnel operations colliding with a tunnel destroy
@@ -596,6 +597,7 @@
 void nss_capwap_init()
 {
 	memset(&nss_capwap_hdl, 0, sizeof(nss_capwap_hdl));
+	nss_capwap_stats_dentry_create();
 }
 
 /*
diff --git a/nss_capwap_stats.c b/nss_capwap_stats.c
new file mode 100644
index 0000000..4b00536
--- /dev/null
+++ b/nss_capwap_stats.c
@@ -0,0 +1,290 @@
+/*
+ **************************************************************************
+ * 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_stats.h"
+#include "nss_core.h"
+#include "nss_capwap.h"
+#include "nss_capwap_stats.h"
+
+/*
+ * nss_capwap_stats_encap_str
+ *	CAPWAP encap statistics string
+ */
+static int8_t *nss_capwap_stats_encap_str[NSS_CAPWAP_STATS_ENCAP_MAX] = {
+	"packets",
+	"bytes",
+	"fragments",
+	"drop_ref",
+	"drop_ver",
+	"drop_unalign",
+	"drop_hroom",
+	"drop_dtls",
+	"drop_nwireless"
+	"drop_qfull",
+	"drop_memfail"
+};
+
+/*
+ * nss_capwap_stats_decap_str
+ *	CAPWAP decap statistics string
+ */
+static int8_t *nss_capwap_stats_decap_str[NSS_CAPWAP_STATS_DECAP_MAX] = {
+	"packets",
+	"bytes",
+	"DTLS_pkts",
+	"fragments",
+	"rx_dropped",
+	"drop_oversize",
+	"drop_frag_timeout",
+	"drop_frag_dup",
+	"drop_frag_gap",
+	"drop_qfull",
+	"drop_memfail",
+	"drop_csum",
+	"drop_malformed"
+};
+
+/*
+ * nss_capwap_stats_encap()
+ *	Make a row for CAPWAP encap stats.
+ */
+static ssize_t nss_capwap_stats_encap(char *line, int len, int i, struct nss_capwap_tunnel_stats *s)
+{
+	uint64_t tcnt = 0;
+
+	switch (i) {
+	case 0:
+		tcnt = s->pnode_stats.tx_packets;
+		break;
+	case 1:
+		tcnt = s->pnode_stats.tx_bytes;
+		break;
+	case 2:
+		tcnt = s->tx_segments;
+		break;
+	case 3:
+		tcnt = s->tx_dropped_sg_ref;
+		break;
+	case 4:
+		tcnt = s->tx_dropped_ver_mis;
+		break;
+	case 5:
+		tcnt = s->tx_dropped_unalign;
+		break;
+	case 6:
+		tcnt = s->tx_dropped_hroom;
+		break;
+	case 7:
+		tcnt = s->tx_dropped_dtls;
+		break;
+	case 8:
+		tcnt = s->tx_dropped_nwireless;
+		break;
+	case 9:
+		tcnt = s->tx_queue_full_drops;
+		break;
+	case 10:
+		tcnt = s->tx_mem_failure_drops;
+		break;
+	default:
+		return 0;
+	}
+
+	return snprintf(line, len, "%s = %llu\n", nss_capwap_stats_encap_str[i], tcnt);
+}
+
+/*
+ * nss_capwap_stats_decap()
+ *	Make a row for CAPWAP decap stats.
+ */
+static ssize_t nss_capwap_stats_decap(char *line, int len, int i, struct nss_capwap_tunnel_stats *s)
+{
+	uint64_t tcnt = 0;
+
+	switch (i) {
+	case 0:
+		tcnt = s->pnode_stats.rx_packets;
+		break;
+	case 1:
+		tcnt = s->pnode_stats.rx_bytes;
+		break;
+	case 2:
+		tcnt = s->dtls_pkts;
+		break;
+	case 3:
+		tcnt = s->rx_segments;
+		break;
+	case 4:
+		tcnt = s->pnode_stats.rx_dropped;
+		break;
+	case 5:
+		tcnt = s->rx_oversize_drops;
+		break;
+	case 6:
+		tcnt = s->rx_frag_timeout_drops;
+		break;
+	case 7:
+		tcnt = s->rx_dup_frag;
+		break;
+	case 8:
+		tcnt = s->rx_frag_gap_drops;
+		break;
+	case 9:
+		tcnt = s->rx_queue_full_drops;
+		return snprintf(line, len, "%s = %llu (n2h = %llu)\n", nss_capwap_stats_decap_str[i], tcnt, s->rx_n2h_queue_full_drops);
+	case 10:
+		tcnt = s->rx_mem_failure_drops;
+		break;
+	case 11:
+		tcnt = s->rx_csum_drops;
+		break;
+	case 12:
+		tcnt = s->rx_malformed;
+		break;
+	default:
+		return 0;
+	}
+
+	return snprintf(line, len, "%s = %llu\n", nss_capwap_stats_decap_str[i], tcnt);
+}
+
+/*
+ * nss_capwap_stats_read()
+ *	Read CAPWAP stats
+ */
+static ssize_t nss_capwap_stats_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos, uint16_t type)
+{
+	struct nss_stats_data *data = fp->private_data;
+	ssize_t bytes_read = 0;
+	struct nss_capwap_tunnel_stats stats;
+	size_t bytes;
+	char line[80];
+	int start;
+	uint32_t if_num = NSS_DYNAMIC_IF_START;
+	uint32_t max_if_num = NSS_DYNAMIC_IF_START + NSS_MAX_DYNAMIC_INTERFACES;
+
+	if (data) {
+		if_num = data->if_num;
+	}
+
+	/*
+	 * If we are done accomodating all the CAPWAP tunnels.
+	 */
+	if (if_num > max_if_num) {
+		return 0;
+	}
+
+	for (; if_num <= max_if_num; if_num++) {
+		bool isthere;
+
+		if (nss_is_dynamic_interface(if_num) == false) {
+			continue;
+		}
+
+		if (nss_dynamic_interface_get_type(nss_capwap_get_ctx(), if_num) != NSS_DYNAMIC_INTERFACE_TYPE_CAPWAP) {
+			continue;
+		}
+
+		/*
+		 * If CAPWAP tunnel does not exists, then isthere will be false.
+		 */
+		isthere = nss_capwap_get_stats(if_num, &stats);
+		if (!isthere) {
+			continue;
+		}
+
+		bytes = snprintf(line, sizeof(line), "----if_num : %2d----\n", if_num);
+		if ((bytes_read + bytes) > sz) {
+			break;
+		}
+
+		if (copy_to_user(ubuf + bytes_read, line, bytes) != 0) {
+			bytes_read = -EFAULT;
+			goto fail;
+		}
+		bytes_read += bytes;
+		start = 0;
+		while (bytes_read < sz) {
+			if (type == 1) {
+				bytes = nss_capwap_stats_encap(line, sizeof(line), start, &stats);
+			} else {
+				bytes = nss_capwap_stats_decap(line, sizeof(line), start, &stats);
+			}
+
+			/*
+			 * If we don't have any more lines in decap/encap.
+			 */
+			if (bytes == 0) {
+				break;
+			}
+
+			if ((bytes_read + bytes) > sz)
+				break;
+
+			if (copy_to_user(ubuf + bytes_read, line, bytes) != 0) {
+				bytes_read = -EFAULT;
+				goto fail;
+			}
+
+			bytes_read += bytes;
+			start++;
+		}
+	}
+
+	if (bytes_read > 0) {
+		*ppos = bytes_read;
+	}
+
+	if (data) {
+		data->if_num = if_num;
+	}
+fail:
+	return bytes_read;
+}
+
+/*
+ * nss_capwap_decap_stats_read()
+ *	Read CAPWAP decap stats
+ */
+static ssize_t nss_capwap_decap_stats_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
+{
+	return nss_capwap_stats_read(fp, ubuf, sz, ppos, 0);
+}
+
+/*
+ * nss_capwap_encap_stats_read()
+ *	Read CAPWAP encap stats
+ */
+static ssize_t nss_capwap_encap_stats_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
+{
+	return nss_capwap_stats_read(fp, ubuf, sz, ppos, 1);
+}
+
+/*
+ * nss_capwap_stats_ops
+ */
+NSS_STATS_DECLARE_FILE_OPERATIONS(capwap_encap)
+NSS_STATS_DECLARE_FILE_OPERATIONS(capwap_decap)
+
+/*
+ * nss_capwap_stats_dentry_create()
+ *	Create CAPWAP statistics debug entry
+ */
+void nss_capwap_stats_dentry_create(void)
+{
+	nss_stats_create_dentry("capwap_encap", &nss_capwap_encap_stats_ops);
+	nss_stats_create_dentry("capwap_decap", &nss_capwap_decap_stats_ops);
+}
diff --git a/nss_capwap_stats.h b/nss_capwap_stats.h
new file mode 100644
index 0000000..0a64189
--- /dev/null
+++ b/nss_capwap_stats.h
@@ -0,0 +1,63 @@
+/*
+ ******************************************************************************
+ * 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.
+ * ****************************************************************************
+ */
+
+#ifndef __NSS_CAPWAP_STATS_H__
+#define __NSS_CAPWAP_STATS_H__
+
+/*
+ * CAPWAP encap statistics
+ */
+enum nss_capwap_stats_encap_types {
+	NSS_CAPWAP_STATS_ENCAP_TX_PKTS,
+	NSS_CAPWAP_STATS_ENCAP_TX_BYTES,
+	NSS_CAPWAP_STATS_ENCAP_TX_SEGMENTS,
+	NSS_CAPWAP_STATS_ENCAP_TX_DROP_SG_REF,
+	NSS_CAPWAP_STATS_ENCAP_TX_DROP_VER_MISMATCH,
+	NSS_CAPWAP_STATS_ENCAP_TX_DROP_UNALIGN,
+	NSS_CAPWAP_STATS_ENCAP_TX_DROP_HEADER_ROOM,
+	NSS_CAPWAP_STATS_ENCAP_TX_DROP_DTLS,
+	NSS_CAPWAP_STATS_ENCAP_TX_DROP_NWIRELESS,
+	NSS_CAPWAP_STATS_ENCAP_TX_DROP_QUEUE_FULL,
+	NSS_CAPWAP_STATS_ENCAP_TX_DROP_MEM_FAIL,
+	NSS_CAPWAP_STATS_ENCAP_MAX
+};
+
+/*
+ * CAPWAP decap statistics
+ */
+enum nss_capwap_stats_decap_types {
+	NSS_CAPWAP_STATS_DECAP_RX_PKTS,
+	NSS_CAPWAP_STATS_DECAP_RX_BYTES,
+	NSS_CAPWAP_STATS_DECAP_RX_DTLS_PKTS,
+	NSS_CAPWAP_STATS_DECAP_RX_SEGMENTS,
+	NSS_CAPWAP_STATS_DECAP_RX_DROP,
+	NSS_CAPWAP_STATS_DECAP_RX_DROP_OVERSIZE,
+	NSS_CAPWAP_STATS_DECAP_RX_DROP_FRAG_TIMEOUT,
+	NSS_CAPWAP_STATS_DECAP_RX_DROP_DUP_FRAG,
+	NSS_CAPWAP_STATS_DECAP_RX_DROP_FRAG_GAP,
+	NSS_CAPWAP_STATS_DECAP_RX_DROP_QUEUE_FULL,
+	NSS_CAPWAP_STATS_DECAP_RX_DROP_MEM_FAIL,
+	NSS_CAPWAP_STATS_DECAP_RX_DROP_CHECKSUM,
+	NSS_CAPWAP_STATS_DECAP_RX_MALFORMED,
+	NSS_CAPWAP_STATS_DECAP_MAX
+};
+
+/*
+ * CAPWAP statistics APIs
+ */
+extern void nss_capwap_stats_dentry_create(void);
+
+#endif /* __NSS_CAPWAP_STATS_H__ */
diff --git a/nss_core.h b/nss_core.h
index 4f2aa1d..dd98d27 100644
--- a/nss_core.h
+++ b/nss_core.h
@@ -38,6 +38,7 @@
 #include "nss_hlos_if.h"
 #include "nss_oam.h"
 #include "nss_data_plane.h"
+#include "nss_stats.h"
 
 /*
  * XXX:can't add this to api_if.h till the deprecated
@@ -263,144 +264,6 @@
 extern struct nss_top_instance nss_top_main;
 
 /*
- * IPV4 node statistics
- *
- * WARNING: There is a 1:1 mapping between values below and corresponding
- *	stats string array in nss_stats.c
- */
-enum nss_stats_ipv4 {
-	NSS_STATS_IPV4_ACCELERATED_RX_PKTS = 0,
-					/* Accelerated IPv4 RX packets */
-	NSS_STATS_IPV4_ACCELERATED_RX_BYTES,
-					/* Accelerated IPv4 RX bytes */
-	NSS_STATS_IPV4_ACCELERATED_TX_PKTS,
-					/* Accelerated IPv4 TX packets */
-	NSS_STATS_IPV4_ACCELERATED_TX_BYTES,
-					/* Accelerated IPv4 TX bytes */
-	NSS_STATS_IPV4_CONNECTION_CREATE_REQUESTS,
-					/* Number of IPv4 connection create requests */
-	NSS_STATS_IPV4_CONNECTION_CREATE_COLLISIONS,
-					/* Number of IPv4 connection create requests that collided with existing entries */
-	NSS_STATS_IPV4_CONNECTION_CREATE_INVALID_INTERFACE,
-					/* Number of IPv4 connection create requests that had invalid interface */
-	NSS_STATS_IPV4_CONNECTION_DESTROY_REQUESTS,
-					/* Number of IPv4 connection destroy requests */
-	NSS_STATS_IPV4_CONNECTION_DESTROY_MISSES,
-					/* Number of IPv4 connection destroy requests that missed the cache */
-	NSS_STATS_IPV4_CONNECTION_HASH_HITS,
-					/* Number of IPv4 connection hash hits */
-	NSS_STATS_IPV4_CONNECTION_HASH_REORDERS,
-					/* Number of IPv4 connection hash reorders */
-	NSS_STATS_IPV4_CONNECTION_FLUSHES,
-					/* Number of IPv4 connection flushes */
-	NSS_STATS_IPV4_CONNECTION_EVICTIONS,
-					/* Number of IPv4 connection evictions */
-	NSS_STATS_IPV4_FRAGMENTATIONS,
-					/* Number of successful IPv4 fragmentations performed */
-	NSS_STATS_IPV4_DROPPED_BY_RULE,
-					/* Number of IPv4 packets dropped because of a drop rule. */
-	NSS_STATS_IPV4_MC_CONNECTION_CREATE_REQUESTS,
-					/* Number of successful IPv4 Multicast create requests */
-	NSS_STATS_IPV4_MC_CONNECTION_UPDATE_REQUESTS,
-					/* Number of successful IPv4 Multicast update requests */
-	NSS_STATS_IPV4_MC_CONNECTION_CREATE_INVALID_INTERFACE,
-					/* Number of IPv4 Multicast connection create requests that had invalid interface */
-	NSS_STATS_IPV4_MC_CONNECTION_DESTROY_REQUESTS,
-					/* Number of IPv4 Multicast connection destroy requests */
-	NSS_STATS_IPV4_MC_CONNECTION_DESTROY_MISSES,
-					/* Number of IPv4 Multicast connection destroy requests that missed the cache */
-	NSS_STATS_IPV4_MC_CONNECTION_FLUSHES,
-					/* Number of IPv4 Multicast connection flushes */
-	NSS_STATS_IPV4_MAX,
-};
-
-/*
- * IPV4 reasm node statistics
- *
- * WARNING: There is a 1:1 mapping between values below and corresponding
- *	stats string array in nss_stats.c
- */
-enum nss_stats_ipv4_reasm {
-	NSS_STATS_IPV4_REASM_EVICTIONS = 0,
-					/* Number of evicted fragment queues due to set memory threshold */
-	NSS_STATS_IPV4_REASM_ALLOC_FAILS,
-					/* Number of fragment queue allocation failures */
-	NSS_STATS_IPV4_REASM_TIMEOUTS,
-					/* Number of expired fragment queues */
-	NSS_STATS_IPV4_REASM_MAX,
-};
-
-/*
- * IPV6 node statistics
- *
- * WARNING: There is a 1:1 mapping between values below and corresponding
- *	stats string array in nss_stats.c
- */
-enum nss_stats_ipv6 {
-	NSS_STATS_IPV6_ACCELERATED_RX_PKTS = 0,
-					/* Accelerated IPv6 RX packets */
-	NSS_STATS_IPV6_ACCELERATED_RX_BYTES,
-					/* Accelerated IPv6 RX bytes */
-	NSS_STATS_IPV6_ACCELERATED_TX_PKTS,
-					/* Accelerated IPv6 TX packets */
-	NSS_STATS_IPV6_ACCELERATED_TX_BYTES,
-					/* Accelerated IPv6 TX bytes */
-	NSS_STATS_IPV6_CONNECTION_CREATE_REQUESTS,
-					/* Number of IPv6 connection create requests */
-	NSS_STATS_IPV6_CONNECTION_CREATE_COLLISIONS,
-					/* Number of IPv6 connection create requests that collided with existing entries */
-	NSS_STATS_IPV6_CONNECTION_CREATE_INVALID_INTERFACE,
-					/* Number of IPv6 connection create requests that had invalid interface */
-	NSS_STATS_IPV6_CONNECTION_DESTROY_REQUESTS,
-					/* Number of IPv6 connection destroy requests */
-	NSS_STATS_IPV6_CONNECTION_DESTROY_MISSES,
-					/* Number of IPv6 connection destroy requests that missed the cache */
-	NSS_STATS_IPV6_CONNECTION_HASH_HITS,
-					/* Number of IPv6 connection hash hits */
-	NSS_STATS_IPV6_CONNECTION_HASH_REORDERS,
-					/* Number of IPv6 connection hash reorders */
-	NSS_STATS_IPV6_CONNECTION_FLUSHES,
-					/* Number of IPv6 connection flushes */
-	NSS_STATS_IPV6_CONNECTION_EVICTIONS,
-					/* Number of IPv6 connection evictions */
-	NSS_STATS_IPV6_FRAGMENTATIONS,
-					/* Number of successful IPv6 fragmentations performed */
-	NSS_STATS_IPV6_FRAG_FAILS,
-					/* Number of IPv6 fragmentation fails */
-	NSS_STATS_IPV6_DROPPED_BY_RULE,
-					/* Number of IPv6 packets dropped by a drop rule. */
-	NSS_STATS_IPV6_MC_CONNECTION_CREATE_REQUESTS,
-					/* Number of successful IPv6 Multicast create requests */
-	NSS_STATS_IPV6_MC_CONNECTION_UPDATE_REQUESTS,
-					/* Number of successful IPv6 Multicast update requests */
-	NSS_STATS_IPV6_MC_CONNECTION_CREATE_INVALID_INTERFACE,
-					/* Number of IPv6 Multicast connection create requests that had invalid interface */
-	NSS_STATS_IPV6_MC_CONNECTION_DESTROY_REQUESTS,
-					/* Number of IPv6 Multicast connection destroy requests */
-	NSS_STATS_IPV6_MC_CONNECTION_DESTROY_MISSES,
-					/* Number of IPv6 Multicast connection destroy requests that missed the cache */
-	NSS_STATS_IPV6_MC_CONNECTION_FLUSHES,
-					/* Number of IPv6 Multicast connection flushes */
-	NSS_STATS_IPV6_MAX,
-};
-
-/*
- * IPv6 reasm node statistics
- *
- * WARNING: There is a 1:1 mapping between values below and corresponding
- *	stats string array in nss_stats.c
- */
-enum nss_stats_ipv6_reasm {
-	NSS_STATS_IPV6_REASM_ALLOC_FAILS = 0,
-					/* Number of fragment queue allocation failures */
-	NSS_STATS_IPV6_REASM_TIMEOUTS,
-					/* Number of expired fragment queues */
-	NSS_STATS_IPV6_REASM_DISCARDS,
-					/* Number of fragment queues discarded due to malformed fragments*/
-	NSS_STATS_IPV6_REASM_MAX,
-};
-
-/*
  * HLOS driver statistics
  *
  * WARNING: There is a 1:1 mapping between values below and corresponding
@@ -437,24 +300,6 @@
 };
 
 /*
- * PPPoE statistics
- *
- * WARNING: There is a 1:1 mapping between values below and corresponding
- *	stats string array in nss_stats.c
- */
-enum nss_stats_pppoe {
-	NSS_STATS_PPPOE_SESSION_CREATE_REQUESTS = 0,
-					/* Number of PPPoE session create requests */
-	NSS_STATS_PPPOE_SESSION_CREATE_FAILURES,
-					/* Number of PPPoE session create failures */
-	NSS_STATS_PPPOE_SESSION_DESTROY_REQUESTS,
-					/* Number of PPPoE session destroy requests */
-	NSS_STATS_PPPOE_SESSION_DESTROY_MISSES,
-					/* Number of PPPoE session destroy requests that missed the cache */
-	NSS_STATS_PPPOE_MAX,
-};
-
-/*
  * GMAC node statistics
  *
  * WARNING: There is a 1:1 mapping between values below and corresponding
@@ -470,896 +315,6 @@
 };
 
 /*
- * ETH_RX node statistics
- *
- * WARNING: There is a 1:1 mapping between values below and corresponding
- *	stats string array in nss_stats.c
- */
-enum nss_stats_eth_rx {
-	NSS_STATS_ETH_RX_TOTAL_TICKS = 0,
-					/* Total clock ticks spend inside the eth_rx package */
-	NSS_STATS_ETH_RX_WORST_CASE_TICKS,
-					/* Worst case iteration of the eth_rx in ticks */
-	NSS_STATS_ETH_RX_ITERATIONS,	/* Number of iterations around the eth_rx */
-	NSS_STATS_ETH_RX_MAX,
-};
-
-/*
- * Node statistics
- *
- * WARNING: There is a 1:1 mapping between values below and corresponding
- *	stats string array in nss_stats.c
- */
-enum nss_stats_node {
-	NSS_STATS_NODE_RX_PKTS,
-					/* Accelerated node RX packets */
-	NSS_STATS_NODE_RX_BYTES,
-					/* Accelerated node RX bytes */
-	NSS_STATS_NODE_TX_PKTS,
-					/* Accelerated node TX packets */
-	NSS_STATS_NODE_TX_BYTES,
-					/* Accelerated node TX bytes */
-	NSS_STATS_NODE_RX_QUEUE_0_DROPPED,
-					/* Accelerated node RX Queue 0 dropped */
-	NSS_STATS_NODE_RX_QUEUE_1_DROPPED,
-					/* Accelerated node RX Queue 1 dropped */
-	NSS_STATS_NODE_RX_QUEUE_2_DROPPED,
-					/* Accelerated node RX Queue 2 dropped */
-	NSS_STATS_NODE_RX_QUEUE_3_DROPPED,
-					/* Accelerated node RX Queue 3 dropped */
-	NSS_STATS_NODE_MAX,
-};
-
-/*
- * N2H node statistics
- *
- * WARNING: There is a 1:1 mapping between values below and corresponding
- *	stats string array in nss_stats.c
- */
-enum nss_stats_n2h {
-	NSS_STATS_N2H_QUEUE_DROPPED = NSS_STATS_NODE_MAX,
-					/* Number of packets dropped because the exception queue is too full */
-	NSS_STATS_N2H_TOTAL_TICKS,	/* Total clock ticks spend inside the N2H */
-	NSS_STATS_N2H_WORST_CASE_TICKS,	/* Worst case iteration of the exception path in ticks */
-	NSS_STATS_N2H_ITERATIONS,	/* Number of iterations around the N2H */
-
-	NSS_STATS_N2H_PBUF_OCM_ALLOC_FAILS,	/* Number of pbuf ocm allocations that have failed */
-	NSS_STATS_N2H_PBUF_OCM_FREE_COUNT,	/* Number of pbuf ocm free count */
-	NSS_STATS_N2H_PBUF_OCM_TOTAL_COUNT,	/* Number of pbuf ocm total count */
-
-	NSS_STATS_N2H_PBUF_DEFAULT_ALLOC_FAILS,	/* Number of pbuf default allocations that have failed */
-	NSS_STATS_N2H_PBUF_DEFAULT_FREE_COUNT,	/* Number of pbuf default free count */
-	NSS_STATS_N2H_PBUF_DEFAULT_TOTAL_COUNT,	/* Number of pbuf default total count */
-
-	NSS_STATS_N2H_PAYLOAD_ALLOC_FAILS,	/* Number of pbuf allocations that have failed because there were no free payloads */
-	NSS_STATS_N2H_PAYLOAD_FREE_COUNT,	/* Number of free payloads that exist */
-
-	NSS_STATS_N2H_H2N_CONTROL_PACKETS,	/* Control packets received from HLOS */
-	NSS_STATS_N2H_H2N_CONTROL_BYTES,	/* Control bytes received from HLOS */
-	NSS_STATS_N2H_N2H_CONTROL_PACKETS,	/* Control packets sent to HLOS */
-	NSS_STATS_N2H_N2H_CONTROL_BYTES,	/* Control bytes sent to HLOS */
-
-	NSS_STATS_N2H_H2N_DATA_PACKETS,		/* Data packets received from HLOS */
-	NSS_STATS_N2H_H2N_DATA_BYTES,		/* Data bytes received from HLOS */
-	NSS_STATS_N2H_N2H_DATA_PACKETS,		/* Data packets sent to HLOS */
-	NSS_STATS_N2H_N2H_DATA_BYTES,		/* Data bytes sent to HLOS */
-	NSS_STATS_N2H_N2H_TOT_PAYLOADS,		/* No. of payloads in NSS */
-	NSS_STATS_N2H_N2H_INTERFACE_INVALID,	/* No. of bad interface access */
-
-	NSS_STATS_N2H_MAX,
-};
-
-/*
- * LSO_RX driver statistics
- *
- * WARNING: There is a 1:1 mapping between values below and corresponding
- *	stats string array in nss_stats.c
- */
-enum nss_stats_lso_rx {
-	NSS_STATS_LSO_RX_TX_DROPPED,		/* Number of packets dropped cause transmit queue is full */
-	NSS_STATS_LSO_RX_DROPPED,		/* Number of packets dropped because of node internal errors */
-	NSS_STATS_LSO_RX_PBUF_ALLOC_FAIL,	/* Number of pbuf alloc failures */
-	NSS_STATS_LSO_RX_PBUF_REFERENCE_FAIL,	/* Number of pbuf reference failures */
-	NSS_STATS_LSO_RX_MAX,
-};
-
-/*
- * wifi statistics
- */
-enum nss_stats_wifi {
-	NSS_STATS_WIFI_RX_PKTS,				/* Number of packets enqueud to wifi */
-	NSS_STATS_WIFI_RX_QUEUE_0_DROPPED,		/* Number of packet dropped during enqueue to wifi queue 0 */
-	NSS_STATS_WIFI_RX_QUEUE_1_DROPPED,		/* Number of packet dropped during enqueue to wifi queue 1 */
-	NSS_STATS_WIFI_RX_QUEUE_2_DROPPED,		/* Number of packet dropped during enqueue to wifi queue 2 */
-	NSS_STATS_WIFI_RX_QUEUE_3_DROPPED,		/* Number of packet dropped during enqueue to wifi queue 3 */
-	NSS_STATS_WIFI_TX_PKTS,				/* Number of packets transmited out to wifi */
-	NSS_STATS_WIFI_TX_DROPPED,			/* Number of packets dropped during transmission */
-	NSS_STATS_WIFI_TX_COMPLETED,			/* Number of packets for which transmission completion received */
-	NSS_STATS_WIFI_MGMT_RCV_CNT,			/* Number of management packets received from host for transmission */
-	NSS_STATS_WIFI_MGMT_TX_PKTS,			/* Number of management packets transmitted over wifi */
-	NSS_STATS_WIFI_MGMT_TX_DROPPED,			/* Number of management packets dropped because of transmission failure */
-	NSS_STATS_WIFI_MGMT_TX_COMPLETIONS,		/* Number of management packets for which tx completions are received */
-	NSS_STATS_WIFI_TX_INV_PEER_ENQUEUE_CNT,		/* Number of packets for which tx enqueue failed because of invalid peer */
-	NSS_STATS_WIFI_RX_INV_PEER_RCV_CNT,		/* Number of packets received from wifi with invalid peer id */
-	NSS_STATS_WIFI_RX_PN_CHECK_FAILED,		/* Number of rx packets which failed packet number check */
-	NSS_STATS_WIFI_RX_DELIVERED,			/* Number of rx packets that NSS wifi offload path could successfully process */
-	NSS_STATS_WIFI_RX_BYTES_DELIVERED,		/* Number of rx bytes that NSS wifi offload path could successfully process */
-	NSS_STATS_WIFI_TX_BYTES_COMPLETED,		/* Number of bytes for which transmission completion received */
-	NSS_STATS_WIFI_RX_DELIVER_UNALIGNED_DROP_CNT,	/* Number of rx packets that dropped beacause of alignment mismatch*/
-	NSS_STATS_WIFI_TIDQ_ENQUEUE_CNT,		/* Number of packets enqueued to  TIDQ */
-	NSS_STATS_WIFI_TIDQ_DEQUEUE_CNT = NSS_STATS_WIFI_TIDQ_ENQUEUE_CNT + 8,		/* Number of packets dequeued from  TIDQ */
-	NSS_STATS_WIFI_TIDQ_ENQUEUE_FAIL_CNT = NSS_STATS_WIFI_TIDQ_DEQUEUE_CNT + 8,	/* Enqueue fail count */
-	NSS_STATS_WIFI_TIDQ_TTL_EXPIRE_CNT = NSS_STATS_WIFI_TIDQ_ENQUEUE_FAIL_CNT + 8,	/* Number of packets expired from  TIDQ */
-	NSS_STATS_WIFI_TIDQ_DEQUEUE_REQ_CNT = NSS_STATS_WIFI_TIDQ_TTL_EXPIRE_CNT + 8,	/* Dequeue reuest count from wifi fw */
-	NSS_STATS_WIFI_TOTAL_TIDQ_DEPTH = NSS_STATS_WIFI_TIDQ_DEQUEUE_REQ_CNT + 8,	/* Tidq depth */
-	NSS_STATS_WIFI_RX_HTT_FETCH_CNT,	/* Total number of HTT Fetch Messages received from wifi fw */
-	NSS_STATS_WIFI_TOTAL_TIDQ_BYPASS_CNT,	/* Total number of packets which have bypassed tidq and sent to wifi fw */
-	NSS_STATS_WIFI_GLOBAL_Q_FULL_CNT,	/* Total number of packets dropped due to global queue full condition */
-	NSS_STATS_WIFI_TIDQ_FULL_CNT,		/* Total number of packets dropped due to TID queue full condition */
-	NSS_STATS_WIFI_MAX,
-};
-
-/*
- * wifili txrx statistics
- *
- * WARNING: There is a 1:1 mapping between values below and corresponding
- *	stats string array in nss_stats.c
- */
-enum nss_stats_wifili_txrx {
-	NSS_STATS_WIFILI_RX_MSDU_ERROR,			/* Number of rx packets received from ring with msdu error */
-	NSS_STATS_WIFILI_RX_INV_PEER_RCV,		/* Number of rx packets with invalid peer id */
-	NSS_STATS_WIFILI_RX_WDS_SRCPORT_EXCEPTION,	/* Number of rx packets exceptioned to host because of src port learn fail */
-	NSS_STATS_WIFILI_RX_WDS_SRCPORT_EXCEPTION_FAIL,	/* Number of rx src port learn fail packets failed to get enqueued to host */
-	NSS_STATS_WIFILI_RX_DELIVERD,			/* Number of packets wifili has given to next node */
-	NSS_STATS_WIFILI_RX_DELIVER_DROPPED,		/* Number of packets which wifili failed to enqueue to next node */
-	NSS_STATS_WIFILI_RX_INTRA_BSS_UCAST,		/* Number of packets which wifili send for intra bss ucast packet */
-	NSS_STATS_WIFILI_RX_INTRA_BSS_UCAST_FAIL,	/* Number of packets which wifili send for intra bss ucast packet failed */
-	NSS_STATS_WIFILI_RX_INTRA_BSS_MCAST,		/* Number of packets which wifili send for intra bss mcast packet */
-	NSS_STATS_WIFILI_RX_INTRA_BSS_MCAST_FAIL,	/* Number of packets which wifili send for intra bss mcast packet failed */
-	NSS_STATS_WIFILI_RX_SG_RCV_SEND,		/* Number of packets sg send */
-	NSS_STATS_WIFILI_RX_SG_RCV_FAIL,		/* Number of packets sg received failure */
-	NSS_STATS_WIFILI_RX_MCAST_ECHO,			/* Number of multicast echo packets received */
-	NSS_STATS_WIFILI_TX_ENQUEUE,			/* Number of packets that got enqueued to wifili */
-	NSS_STATS_WIFILI_TX_ENQUEUE_DROP,		/* Number of packets that dropped during enqueue to wifili */
-	NSS_STATS_WIFILI_TX_DEQUEUE,			/* Number of packets that are dequeued by wifili */
-	NSS_STATS_WIFILI_TX_HW_ENQUEUE_FAIL,		/* Number of rx packets that NSS wifi offload path could successfully process */
-	NSS_STATS_WIFILI_TX_SENT_COUNT,			/* Number of Tx packets sent to hw */
-	NSS_STATS_WIFILI_TXRX_MAX,			/* Number of max txrx stats*/
-};
-
-/*
- * wifili tcl stats
- *
- * WARNING: There is a 1:1 mapping between values below and corresponding
- *	stats string array in nss_stats.c
- */
-enum nss_stats_wifili_tcl {
-	NSS_STATS_WIFILI_TCL_NO_HW_DESC,		/* Number of tcl hw desc*/
-	NSS_STATS_WIFILI_TCL_RING_FULL,			/* Number of times tcl ring full*/
-	NSS_STATS_WIFILI_TCL_RING_SENT,			/* Number of times tcl desc sent*/
-	NSS_STATS_WIFILI_TCL_MAX,			/* Number of max tcl stats*/
-};
-
-/*
- * wifili tx comp stats
- *
- * WARNING: There is a 1:1 mapping between values below and corresponding
- *  	stats string array in nss_stats.c
- */
-enum nss_stats_wifili_tx_comp {
-	NSS_STATS_WIFILI_TX_DESC_FREE_INV_BUFSRC,	/* Number of invalid bufsrc packets */
-	NSS_STATS_WIFILI_TX_DESC_FREE_INV_COOKIE,	/* Number of invalid cookie packets */
-	NSS_STATS_WIFILI_TX_DESC_FREE_HW_RING_EMPTY,	/* Number of time times hw ring empty found*/
-	NSS_STATS_WIFILI_TX_DESC_FREE_REAPED,		/* Number of tx packets that are reaped out of tx completion ring */
-	NSS_STATS_WIFILI_TX_DESC_FREE_MAX,		/* Number of tx comp stats */
-};
-
-/*
- * wifili tx reo stats
- *
- * WARNING: There is a 1:1 mapping between values below and corresponding
- *  	stats string array in nss_stats.c
- */
-enum nss_stats_wifili_reo {
-	NSS_STATS_WIFILI_REO_ERROR,			/* Number of reo error*/
-	NSS_STATS_WIFILI_REO_REAPED,			/* Number of reo reaped*/
-	NSS_STATS_WIFILI_REO_INV_COOKIE,		/* Number of invalid cookie*/
-	NSS_STATS_WIFILI_REO_MAX,			/* Number of reo stats*/
-};
-
-/*
- * wifili tx desc stats
- *
- * WARNING: There is a 1:1 mapping between values below and corresponding
- *	stats string array in nss_stats.c
- */
-enum nss_stats_wifili_txsw_pool {
-	NSS_STATS_WIFILI_TX_DESC_IN_USE,		/* Number of tx packets that are currently in flight */
-	NSS_STATS_WIFILI_TX_DESC_ALLOC_FAIL,		/* Number of tx sw desc alloc failures */
-	NSS_STATS_WIFILI_TX_DESC_ALREADY_ALLOCATED,	/* Number of tx sw desc already allocated*/
-	NSS_STATS_WIFILI_TX_DESC_INVALID_FREE,		/* Number of tx sw desc invalid free*/
-	NSS_STATS_WIFILI_TX_DESC_FREE_SRC_FW,		/* Number of tx desc for which release src is fw */
-	NSS_STATS_WIFILI_TX_DESC_FREE_COMPLETION,	/* Number of tx desc completion*/
-	NSS_STATS_WIFILI_TX_DESC_NO_PB,			/* Number of tx desc pb is null*/
-	NSS_STATS_WIFILI_TX_DESC_MAX,			/* Number of tx desc stats*/
-};
-
-/*
- * wifili tx ext desc stats
- *
- * WARNING: There is a 1:1 mapping between values below and corresponding
- *	stats string array in nss_stats.c
- */
-enum nss_stats_wifili_ext_txsw_pool {
-	NSS_STATS_WIFILI_EXT_TX_DESC_IN_USE,		/* Number of ext tx packets that are currently in flight */
-	NSS_STATS_WIFILI_EXT_TX_DESC_ALLOC_FAIL,	/* Number of ext tx sw desc alloc failures */
-	NSS_STATS_WIFILI_EXT_TX_DESC_ALREADY_ALLOCATED,	/* Number of ext tx sw desc already allocated*/
-	NSS_STATS_WIFILI_EXT_TX_DESC_INVALID_FREE,	/* Number of ext tx sw desc invalid free*/
-	NSS_STATS_WIFILI_EXT_TX_DESC_MAX,		/* Number of ext tx desc stats*/
-};
-
-/*
- * wifili rx desc stats
- *
- * WARNING: There is a 1:1 mapping between values below and corresponding
- *	stats string array in nss_stats.c
- */
-enum nss_stats_wifili_rxdma_pool {
-	NSS_STATS_WIFILI_RX_DESC_NO_PB,			/* Number of rx desc no pb*/
-	NSS_STATS_WIFILI_RX_DESC_ALLOC_FAIL,		/* Number of rx desc alloc failures */
-	NSS_STATS_WIFILI_RX_DESC_IN_USE,		/* Number of rx desc alloc in use*/
-	NSS_STATS_WIFILI_RX_DESC_MAX,			/* Number of rx desc stats*/
-};
-
-/*
- * wifili rx dma ring stats
- *
- * WARNING: There is a 1:1 mapping between values below and corresponding
- *	stats string array in nss_stats.c
- */
-enum nss_stats_wifili_rxdma_ring {
-	NSS_STATS_WIFILI_RXDMA_DESC_UNAVAILABLE, 	/* Number of rx dma desc unavailable */
-	NSS_STATS_WIFILI_RXDMA_BUF_REPLENISHED, 	/* Number of rx dma buf replished */
-	NSS_STATS_WIFILI_RXDMA_DESC_MAX,	 	/* Number of rx dma desc stast */
-};
-
-/*
- * wifili wbm ring stats
- *
- * WARNING: There is a 1:1 mapping between values below and corresponding
- *	stats string array in nss_stats.c
- */
-enum nss_stats_wifili_wbm {
-	NSS_STATS_WIFILI_WBM_SRC_DMA,			/* Number of rx invalid src dma */
-	NSS_STATS_WIFILI_WBM_SRC_DMA_CODE_INV,		/* Number of rx invalid src dma */
-	NSS_STATS_WIFILI_WBM_SRC_REO,			/* Number of rx invalid src reo */
-	NSS_STATS_WIFILI_WBM_SRC_REO_CODE_NULLQ,	/* Number of rx invalid reo error with null q */
-	NSS_STATS_WIFILI_WBM_SRC_REO_CODE_INV,		/* Number of rx invalid reo error with null q */
-	NSS_STATS_WIFILI_WBM_SRC_INV,			/* Number of rx invalid reo code invalid */
-	NSS_STATS_WIFILI_WBM_MAX,			/* Number of rx wbm stats */
-};
-
-/*
- * NSS core state -- for H2N/N2H
- * l2tpv2 debug stats
- */
-enum nss_stats_l2tpv2_session {
-	NSS_STATS_L2TPV2_SESSION_RX_PPP_LCP_PKTS,	/* Number of ppp lcp packets received */
-	NSS_STATS_L2TPV2_SESSION_RX_EXP_DATA_PKTS,	/* Number of RX exceptioned packets */
-	NSS_STATS_L2TPV2_SESSION_ENCAP_PBUF_ALLOC_FAIL_PKTS,	/* Number of times packet buffer allocation failed during encap */
-	NSS_STATS_L2TPV2_SESSION_DECAP_PBUF_ALLOC_FAIL_PKTS,	/* Number of times packet buffer allocation failed during decap */
-	NSS_STATS_L2TPV2_SESSION_MAX
-};
-
-/*
- * PortID statistics
- */
-enum nss_stats_portid {
-	NSS_STATS_PORTID_RX_INVALID_HEADER,
-	NSS_STATS_PORTID_MAX,
-};
-
-struct nss_stats_l2tpv2_session_debug {
-	uint64_t stats[NSS_STATS_L2TPV2_SESSION_MAX];
-	int32_t if_index;
-	uint32_t if_num; /* nss interface number */
-	bool valid;
-};
-
-/*
- * PPTP debug stats
- */
-enum nss_stats_pptp_session {
-	NSS_STATS_PPTP_ENCAP_RX_PACKETS,
-	NSS_STATS_PPTP_ENCAP_RX_BYTES,
-	NSS_STATS_PPTP_ENCAP_TX_PACKETS,
-	NSS_STATS_PPTP_ENCAP_TX_BYTES,
-	NSS_STATS_PPTP_ENCAP_RX_QUEUE_0_DROP,
-	NSS_STATS_PPTP_ENCAP_RX_QUEUE_1_DROP,
-	NSS_STATS_PPTP_ENCAP_RX_QUEUE_2_DROP,
-	NSS_STATS_PPTP_ENCAP_RX_QUEUE_3_DROP,
-	NSS_STATS_PPTP_DECAP_RX_PACKETS,
-	NSS_STATS_PPTP_DECAP_RX_BYTES,
-	NSS_STATS_PPTP_DECAP_TX_PACKETS,
-	NSS_STATS_PPTP_DECAP_TX_BYTES,
-	NSS_STATS_PPTP_DECAP_RX_QUEUE_0_DROP,
-	NSS_STATS_PPTP_DECAP_RX_QUEUE_1_DROP,
-	NSS_STATS_PPTP_DECAP_RX_QUEUE_2_DROP,
-	NSS_STATS_PPTP_DECAP_RX_QUEUE_3_DROP,
-	NSS_STATS_PPTP_SESSION_ENCAP_HEADROOM_ERR,
-	NSS_STATS_PPTP_SESSION_ENCAP_SMALL_SIZE,
-	NSS_STATS_PPTP_SESSION_ENCAP_PNODE_ENQUEUE_FAIL,
-	NSS_STATS_PPTP_SESSION_DECAP_NO_SEQ_NOR_ACK,
-	NSS_STATS_PPTP_SESSION_DECAP_INVAL_GRE_FLAGS,
-	NSS_STATS_PPTP_SESSION_DECAP_INVAL_GRE_PROTO,
-	NSS_STATS_PPTP_SESSION_DECAP_WRONG_SEQ,
-	NSS_STATS_PPTP_SESSION_DECAP_INVAL_PPP_HDR,
-	NSS_STATS_PPTP_SESSION_DECAP_PPP_LCP,
-	NSS_STATS_PPTP_SESSION_DECAP_UNSUPPORTED_PPP_PROTO,
-	NSS_STATS_PPTP_SESSION_DECAP_PNODE_ENQUEUE_FAIL,
-	NSS_STATS_PPTP_SESSION_MAX
-};
-
-struct nss_stats_pptp_session_debug {
-	uint64_t stats[NSS_STATS_PPTP_SESSION_MAX];
-	int32_t if_index;
-	uint32_t if_num; /* nss interface number */
-	bool valid;
-};
-
-/*
- * PPE stats
- */
-enum nss_stats_ppe_conn {
-	NSS_STATS_PPE_V4_L3_FLOWS,		/* No of v4 routed flows */
-	NSS_STATS_PPE_V4_L2_FLOWS,		/* No of v4 bridge flows */
-	NSS_STATS_PPE_V4_CREATE_REQ,		/* No of v4 create requests */
-	NSS_STATS_PPE_V4_CREATE_FAIL,		/* No of v4 create failure */
-	NSS_STATS_PPE_V4_DESTROY_REQ,		/* No of v4 delete requests */
-	NSS_STATS_PPE_V4_DESTROY_FAIL,		/* No of v4 delete failure */
-	NSS_STATS_PPE_V4_MC_CREATE_REQ,		/* No of v4 MC create requests */
-	NSS_STATS_PPE_V4_MC_CREATE_FAIL,	/* No of v4 MC create failure */
-	NSS_STATS_PPE_V4_MC_UPDATE_REQ,		/* No of v4 MC update requests */
-	NSS_STATS_PPE_V4_MC_UPDATE_FAIL,	/* No of v4 MC update failure */
-	NSS_STATS_PPE_V4_MC_DESTROY_REQ,	/* No of v4 MC delete requests */
-	NSS_STATS_PPE_V4_MC_DESTROY_FAIL,	/* No of v4 MC delete failure */
-
-	NSS_STATS_PPE_V6_L3_FLOWS,		/* No of v6 routed flows */
-	NSS_STATS_PPE_V6_L2_FLOWS,		/* No of v6 bridge flows */
-	NSS_STATS_PPE_V6_CREATE_REQ,		/* No of v6 create requests */
-	NSS_STATS_PPE_V6_CREATE_FAIL,		/* No of v6 create failure */
-	NSS_STATS_PPE_V6_DESTROY_REQ,		/* No of v6 delete requests */
-	NSS_STATS_PPE_V6_DESTROY_FAIL,		/* No of v6 delete failure */
-	NSS_STATS_PPE_V6_MC_CREATE_REQ,		/* No of v6 MC create requests */
-	NSS_STATS_PPE_V6_MC_CREATE_FAIL,	/* No of v6 MC create failure */
-	NSS_STATS_PPE_V6_MC_UPDATE_REQ,		/* No of v6 MC update requests */
-	NSS_STATS_PPE_V6_MC_UPDATE_FAIL,	/* No of v6 MC update failure */
-	NSS_STATS_PPE_V6_MC_DESTROY_REQ,	/* No of v6 MC delete requests */
-	NSS_STATS_PPE_V6_MC_DESTROY_FAIL,	/* No of v6 MC delete failure */
-
-	NSS_STATS_PPE_FAIL_VP_FULL,		/* Create req fail due to VP table full */
-	NSS_STATS_PPE_FAIL_NH_FULL,		/* Create req fail due to nexthop table full */
-	NSS_STATS_PPE_FAIL_FLOW_FULL,		/* Create req fail due to flow table full */
-	NSS_STATS_PPE_FAIL_HOST_FULL,		/* Create req fail due to host table full */
-	NSS_STATS_PPE_FAIL_PUBIP_FULL,		/* Create req fail due to pub-ip table full */
-	NSS_STATS_PPE_FAIL_PORT_SETUP,		/* Create req fail due to PPE port not setup */
-	NSS_STATS_PPE_FAIL_RW_FIFO_FULL,	/* Create req fail due to rw fifo full */
-	NSS_STATS_PPE_FAIL_FLOW_COMMAND,	/* Create req fail due to PPE flow command failure */
-	NSS_STATS_PPE_FAIL_UNKNOWN_PROTO,	/* Create req fail due to unknown protocol */
-	NSS_STATS_PPE_FAIL_PPE_UNRESPONSIVE,	/* Create req fail due to PPE not responding */
-	NSS_STATS_PPE_CE_OPAQUE_INVALID,	/* Create req fail due to invalid opaque in CE */
-	NSS_STATS_PPE_FAIL_FQG_FULL,		/* Create req fail due to flow qos group full */
-	NSS_STATS_PPE_CONN_MAX
-};
-
-enum nss_stats_ppe_l3 {
-	NSS_STATS_PPE_L3_DBG_0,		/* PPE L3 debug register 0 */
-	NSS_STATS_PPE_L3_DBG_1,		/* PPE L3 debug register 1 */
-	NSS_STATS_PPE_L3_DBG_2,		/* PPE L3 debug register 2 */
-	NSS_STATS_PPE_L3_DBG_3,		/* PPE L3 debug register 3 */
-	NSS_STATS_PPE_L3_DBG_4,		/* PPE L3 debug register 4 */
-	NSS_STATS_PPE_L3_DBG_PORT,	/* PPE L3 debug register Port */
-	NSS_STATS_PPE_L3_MAX
-};
-
-enum nss_stats_ppe_code {
-	NSS_STATS_PPE_CODE_CPU,		/* PPE CPU code for last packet processed */
-	NSS_STATS_PPE_CODE_DROP,	/* PPE DROP code for last packet processed */
-	NSS_STATS_PPE_CODE_MAX
-};
-
-/*
- * PPE drop codes
- */
-enum nss_stats_ppe_dc {
-	NSS_STATS_PPE_DROP_CODE_UNKNOWN,				/* PPE drop code unknown */
-	NSS_STATS_PPE_DROP_CODE_EXP_UNKNOWN_L2_PROT,			/* PPE drop code exp unknown l2 prot */
-	NSS_STATS_PPE_DROP_CODE_EXP_PPPOE_WRONG_VER_TYPE,		/* PPE drop code exp pppoe wrong ver type */
-	NSS_STATS_PPE_DROP_CODE_EXP_PPPOE_WRONG_CODE,			/* PPE drop code exp pppoe wrong code */
-	NSS_STATS_PPE_DROP_CODE_EXP_PPPOE_UNSUPPORTED_PPP_PROT,		/* PPE drop code exp pppoe unsupported ppp prot */
-	NSS_STATS_PPE_DROP_CODE_EXP_IPV4_WRONG_VER,			/* PPE drop code exp ipv4 wrong ver */
-	NSS_STATS_PPE_DROP_CODE_EXP_IPV4_SMALL_IHL,			/* PPE drop code exp ipv4 small ihl */
-	NSS_STATS_PPE_DROP_CODE_EXP_IPV4_WITH_OPTION,			/* PPE drop code exp ipv4 with option */
-	NSS_STATS_PPE_DROP_CODE_EXP_IPV4_HDR_INCOMPLETE,		/* PPE drop code exp ipv4 hdr incomplete */
-	NSS_STATS_PPE_DROP_CODE_EXP_IPV4_BAD_TOTAL_LEN,			/* PPE drop code exp ipv4 bad total len */
-	NSS_STATS_PPE_DROP_CODE_EXP_IPV4_DATA_INCOMPLETE,		/* PPE drop code exp ipv4 data incomplete */
-	NSS_STATS_PPE_DROP_CODE_EXP_IPV4_FRAG,				/* PPE drop code exp ipv4 frag */
-	NSS_STATS_PPE_DROP_CODE_EXP_IPV4_PING_OF_DEATH,			/* PPE drop code exp ipv4 ping of death */
-	NSS_STATS_PPE_DROP_CODE_EXP_IPV4_SNALL_TTL,			/* PPE drop code exp ipv4 snall ttl */
-	NSS_STATS_PPE_DROP_CODE_EXP_IPV4_UNK_IP_PROT,			/* PPE drop code exp ipv4 unk ip prot */
-	NSS_STATS_PPE_DROP_CODE_EXP_IPV4_CHECKSUM_ERR,			/* PPE drop code exp ipv4 checksum err */
-	NSS_STATS_PPE_DROP_CODE_EXP_IPV4_INV_SIP,			/* PPE drop code exp ipv4 inv sip */
-	NSS_STATS_PPE_DROP_CODE_EXP_IPV4_INV_DIP,			/* PPE drop code exp ipv4 inv dip */
-	NSS_STATS_PPE_DROP_CODE_EXP_IPV4_LAND_ATTACK,			/* PPE drop code exp ipv4 land attack */
-	NSS_STATS_PPE_DROP_CODE_EXP_IPV4_AH_HDR_INCOMPLETE,		/* PPE drop code exp ipv4 ah hdr incomplete */
-	NSS_STATS_PPE_DROP_CODE_EXP_IPV4_AH_HDR_CROSS_BORDER,		/* PPE drop code exp ipv4 ah hdr cross border */
-	NSS_STATS_PPE_DROP_CODE_EXP_IPV4_ESP_HDR_INCOMPLETE,		/* PPE drop code exp ipv4 esp hdr incomplete */
-	NSS_STATS_PPE_DROP_CODE_EXP_IPV6_WRONG_VER,			/* PPE drop code exp ipv6 wrong ver */
-	NSS_STATS_PPE_DROP_CODE_EXP_IPV6_HDR_INCOMPLETE,		/* PPE drop code exp ipv6 hdr incomplete */
-	NSS_STATS_PPE_DROP_CODE_EXP_IPV6_BAD_PAYLOAD_LEN,		/* PPE drop code exp ipv6 bad payload len */
-	NSS_STATS_PPE_DROP_CODE_EXP_IPV6_DATA_INCOMPLETE,	 	/* PPE drop code exp ipv6 data incomplete */
-	NSS_STATS_PPE_DROP_CODE_EXP_IPV6_WITH_EXT_HDR,			/* PPE drop code exp ipv6 with ext hdr */
-	NSS_STATS_PPE_DROP_CODE_EXP_IPV6_SMALL_HOP_LIMIT,		/* PPE drop code exp ipv6 small hop limit */
-	NSS_STATS_PPE_DROP_CODE_EXP_IPV6_INV_SIP,			/* PPE drop code exp ipv6 inv sip */
-	NSS_STATS_PPE_DROP_CODE_EXP_IPV6_INV_DIP,			/* PPE drop code exp ipv6 inv dip */
-	NSS_STATS_PPE_DROP_CODE_EXP_IPV6_LAND_ATTACK,			/* PPE drop code exp ipv6 land attack */
-	NSS_STATS_PPE_DROP_CODE_EXP_IPV6_FRAG,				/* PPE drop code exp ipv6 frag */
-	NSS_STATS_PPE_DROP_CODE_EXP_IPV6_PING_OF_DEATH,			/* PPE drop code exp ipv6 ping of death */
-	NSS_STATS_PPE_DROP_CODE_EXP_IPV6_WITH_MORE_EXT_HDR,		/* PPE drop code exp ipv6 with more ext hdr */
-	NSS_STATS_PPE_DROP_CODE_EXP_IPV6_UNK_LAST_NEXT_HDR,		/* PPE drop code exp ipv6 unk last next hdr */
-	NSS_STATS_PPE_DROP_CODE_EXP_IPV6_MOBILITY_HDR_INCOMPLETE,	/* PPE drop code exp ipv6 mobility hdr incomplete */
-	NSS_STATS_PPE_DROP_CODE_EXP_IPV6_MOBILITY_HDR_CROSS_BORDER,	/* PPE drop code exp ipv6 mobility hdr cross border */
-	NSS_STATS_PPE_DROP_CODE_EXP_IPV6_AH_HDR_INCOMPLETE,		/* PPE drop code exp ipv6 ah hdr incomplete */
-	NSS_STATS_PPE_DROP_CODE_EXP_IPV6_AH_HDR_CROSS_BORDER,		/* PPE drop code exp ipv6 ah hdr cross border */
-	NSS_STATS_PPE_DROP_CODE_EXP_IPV6_ESP_HDR_INCOMPLETE,		/* PPE drop code exp ipv6 esp hdr incomplete */
-	NSS_STATS_PPE_DROP_CODE_EXP_IPV6_ESP_HDR_CROSS_BORDER,		/* PPE drop code exp ipv6 esp hdr cross border */
-	NSS_STATS_PPE_DROP_CODE_EXP_IPV6_OTHER_EXT_HDR_INCOMPLETE,	/* PPE drop code exp ipv6 other ext hdr incomplete */
-	NSS_STATS_PPE_DROP_CODE_EXP_IPV6_OTHER_EXT_HDR_CROSS_BORDER,	/* PPE drop code exp ipv6 other ext hdr cross border */
-	NSS_STATS_PPE_DROP_CODE_EXP_TCP_HDR_INCOMPLETE,			/* PPE drop code exp tcp hdr incomplete */
-	NSS_STATS_PPE_DROP_CODE_EXP_TCP_HDR_CROSS_BORDER,		/* PPE drop code exp tcp hdr cross border */
-	NSS_STATS_PPE_DROP_CODE_EXP_TCP_SMAE_SP_DP,			/* PPE drop code exp tcp smae sp dp */
-	NSS_STATS_PPE_DROP_CODE_EXP_TCP_SMALL_DATA_OFFSET,		/* PPE drop code exp tcp small data offset */
-	NSS_STATS_PPE_DROP_CODE_EXP_TCP_FLAGS_0,			/* PPE drop code exp tcp flags 0 */
-	NSS_STATS_PPE_DROP_CODE_EXP_TCP_FLAGS_1,			/* PPE drop code exp tcp flags 1 */
-	NSS_STATS_PPE_DROP_CODE_EXP_TCP_FLAGS_2,			/* PPE drop code exp tcp flags 2 */
-	NSS_STATS_PPE_DROP_CODE_EXP_TCP_FLAGS_3,			/* PPE drop code exp tcp flags 3 */
-	NSS_STATS_PPE_DROP_CODE_EXP_TCP_FLAGS_4,			/* PPE drop code exp tcp flags 4 */
-	NSS_STATS_PPE_DROP_CODE_EXP_TCP_FLAGS_5,			/* PPE drop code exp tcp flags 5 */
-	NSS_STATS_PPE_DROP_CODE_EXP_TCP_FLAGS_6,			/* PPE drop code exp tcp flags 6 */
-	NSS_STATS_PPE_DROP_CODE_EXP_TCP_FLAGS_7,			/* PPE drop code exp tcp flags 7 */
-	NSS_STATS_PPE_DROP_CODE_EXP_TCP_CHECKSUM_ERR,			/* PPE drop code exp tcp checksum err */
-	NSS_STATS_PPE_DROP_CODE_EXP_UDP_HDR_INCOMPLETE,			/* PPE drop code exp udp hdr incomplete */
-	NSS_STATS_PPE_DROP_CODE_EXP_UDP_HDR_CROSS_BORDER,		/* PPE drop code exp udp hdr cross border */
-	NSS_STATS_PPE_DROP_CODE_EXP_UDP_SMAE_SP_DP,			/* PPE drop code exp udp smae sp dp */
-	NSS_STATS_PPE_DROP_CODE_EXP_UDP_BAD_LEN,			/* PPE drop code exp udp bad len */
-	NSS_STATS_PPE_DROP_CODE_EXP_UDP_DATA_INCOMPLETE,		/* PPE drop code exp udp data incomplete */
-	NSS_STATS_PPE_DROP_CODE_EXP_UDP_CHECKSUM_ERR,			/* PPE drop code exp udp checksum err */
-	NSS_STATS_PPE_DROP_CODE_EXP_UDP_LITE_HDR_INCOMPLETE,		/* PPE drop code exp udp lite hdr incomplete */
-	NSS_STATS_PPE_DROP_CODE_EXP_UDP_LITE_HDR_CROSS_BORDER,		/* PPE drop code exp udp lite hdr cross border */
-	NSS_STATS_PPE_DROP_CODE_EXP_UDP_LITE_SMAE_SP_DP,		/* PPE drop code exp udp lite smae sp dp */
-	NSS_STATS_PPE_DROP_CODE_EXP_UDP_LITE_CSM_COV_1_TO_7,		/* PPE drop code exp udp lite csm cov 1 to 7 */
-	NSS_STATS_PPE_DROP_CODE_EXP_UDP_LITE_CSM_COV_TOO_LONG,		/* PPE drop code exp udp lite csm cov too long */
-	NSS_STATS_PPE_DROP_CODE_EXP_UDP_LITE_CSM_COV_CROSS_BORDER,	/* PPE drop code exp udp lite csm cov cross border */
-	NSS_STATS_PPE_DROP_CODE_EXP_UDP_LITE_CHECKSUM_ERR,		/* PPE drop code exp udp lite checksum err */
-	NSS_STATS_PPE_DROP_CODE_L3_MC_BRIDGE_ACTION,			/* PPE drop code l3 mc bridge action */
-	NSS_STATS_PPE_DROP_CODE_L3_NO_ROUTE_PREHEAD_NAT_ACTION,		/* PPE drop code l3 no route prehead nat action */
-	NSS_STATS_PPE_DROP_CODE_L3_NO_ROUTE_PREHEAD_NAT_ERROR,		/* PPE drop code l3 no route prehead nat error */
-	NSS_STATS_PPE_DROP_CODE_L3_ROUTE_ACTION,			/* PPE drop code l3 route action */
-	NSS_STATS_PPE_DROP_CODE_L3_NO_ROUTE_ACTION,			/* PPE drop code l3 no route action */
-	NSS_STATS_PPE_DROP_CODE_L3_NO_ROUTE_NH_INVALID_ACTION,		/* PPE drop code l3 no route nh invalid action */
-	NSS_STATS_PPE_DROP_CODE_L3_NO_ROUTE_PREHEAD_ACTION,		/* PPE drop code l3 no route prehead action */
-	NSS_STATS_PPE_DROP_CODE_L3_BRIDGE_ACTION,			/* PPE drop code l3 bridge action */
-	NSS_STATS_PPE_DROP_CODE_L3_FLOW_ACTION,				/* PPE drop code l3 flow action */
-	NSS_STATS_PPE_DROP_CODE_L3_FLOW_MISS_ACTION,			/* PPE drop code l3 flow miss action */
-	NSS_STATS_PPE_DROP_CODE_L2_EXP_MRU_FAIL,			/* PPE drop code l2 exp mru fail */
-	NSS_STATS_PPE_DROP_CODE_L2_EXP_MTU_FAIL,			/* PPE drop code l2 exp mtu fail */
-	NSS_STATS_PPE_DROP_CODE_L3_EXP_IP_PREFIX_BC,			/* PPE drop code l3 exp ip prefix bc */
-	NSS_STATS_PPE_DROP_CODE_L3_EXP_MTU_FAIL,			/* PPE drop code l3 exp mtu fail */
-	NSS_STATS_PPE_DROP_CODE_L3_EXP_MRU_FAIL,			/* PPE drop code l3 exp mru fail */
-	NSS_STATS_PPE_DROP_CODE_L3_EXP_ICMP_RDT,			/* PPE drop code l3 exp icmp rdt */
-	NSS_STATS_PPE_DROP_CODE_FAKE_MAC_HEADER_ERR,			/* PPE drop code fake mac header err */
-	NSS_STATS_PPE_DROP_CODE_L3_EXP_IP_RT_TTL_ZERO,			/* PPE drop code l3 exp ip rt ttl zero */
-	NSS_STATS_PPE_DROP_CODE_L3_FLOW_SERVICE_CODE_LOOP,		/* PPE drop code l3 flow service code loop */
-	NSS_STATS_PPE_DROP_CODE_L3_FLOW_DE_ACCELEARTE,			/* PPE drop code l3 flow de accelearte */
-	NSS_STATS_PPE_DROP_CODE_L3_EXP_FLOW_SRC_IF_CHK_FAIL,		/* PPE drop code l3 exp flow src if chk fail */
-	NSS_STATS_PPE_DROP_CODE_L3_FLOW_SYNC_TOGGLE_MISMATCH,		/* PPE drop code l3 flow sync toggle mismatch */
-	NSS_STATS_PPE_DROP_CODE_L3_EXP_MTU_DF_FAIL,			/* PPE drop code l3 exp mtu df fail */
-	NSS_STATS_PPE_DROP_CODE_L3_EXP_PPPOE_MULTICAST,			/* PPE drop code l3 exp pppoe multicast */
-	NSS_STATS_PPE_DROP_CODE_IPV4_SG_UNKNOWN,			/* PPE drop code ipv4 sg unknown */
-	NSS_STATS_PPE_DROP_CODE_IPV6_SG_UNKNOWN,			/* PPE drop code ipv6 sg unknown */
-	NSS_STATS_PPE_DROP_CODE_ARP_SG_UNKNOWN,				/* PPE drop code arp sg unknown */
-	NSS_STATS_PPE_DROP_CODE_ND_SG_UNKNOWN,				/* PPE drop code nd sg unknown */
-	NSS_STATS_PPE_DROP_CODE_IPV4_SG_VIO,				/* PPE drop code ipv4 sg vio */
-	NSS_STATS_PPE_DROP_CODE_IPV6_SG_VIO,				/* PPE drop code ipv6 sg vio */
-	NSS_STATS_PPE_DROP_CODE_ARP_SG_VIO,				/* PPE drop code arp sg vio */
-	NSS_STATS_PPE_DROP_CODE_ND_SG_VIO,				/* PPE drop code nd sg vio */
-	NSS_STATS_PPE_DROP_CODE_L2_NEW_MAC_ADDRESS,			/* PPE drop code l2 new mac address */
-	NSS_STATS_PPE_DROP_CODE_L2_HASH_COLLISION,			/* PPE drop code l2 hash collision */
-	NSS_STATS_PPE_DROP_CODE_L2_STATION_MOVE,			/* PPE drop code l2 station move */
-	NSS_STATS_PPE_DROP_CODE_L2_LEARN_LIMIT,				/* PPE drop code l2 learn limit */
-	NSS_STATS_PPE_DROP_CODE_L2_SA_LOOKUP_ACTION,			/* PPE drop code l2 sa lookup action */
-	NSS_STATS_PPE_DROP_CODE_L2_DA_LOOKUP_ACTION,			/* PPE drop code l2 da lookup action */
-	NSS_STATS_PPE_DROP_CODE_APP_CTRL_ACTION,			/* PPE drop code app ctrl action */
-	NSS_STATS_PPE_DROP_CODE_IN_VLAN_FILTER_ACTION,			/* PPE drop code in vlan filter action */
-	NSS_STATS_PPE_DROP_CODE_IN_VLAN_XLT_MISS,			/* PPE drop code in vlan xlt miss */
-	NSS_STATS_PPE_DROP_CODE_EG_VLAN_FILTER_DROP,			/* PPE drop code eg vlan filter drop */
-	NSS_STATS_PPE_DROP_CODE_ACL_PRE_ACTION,				/* PPE drop code acl pre action */
-	NSS_STATS_PPE_DROP_CODE_ACL_POST_ACTION,			/* PPE drop code acl post action */
-	NSS_STATS_PPE_DROP_CODE_MC_BC_SA,				/* PPE drop code mc bc sa */
-	NSS_STATS_PPE_DROP_CODE_NO_DESTINATION,				/* PPE drop code no destination */
-	NSS_STATS_PPE_DROP_CODE_STG_IN_FILTER,				/* PPE drop code stg in filter */
-	NSS_STATS_PPE_DROP_CODE_STG_EG_FILTER,				/* PPE drop code stg eg filter */
-	NSS_STATS_PPE_DROP_CODE_SOURCE_FILTER_FAIL,			/* PPE drop code source filter fail */
-	NSS_STATS_PPE_DROP_CODE_TRUNK_SEL_FAIL,				/* PPE drop code trunk sel fail */
-	NSS_STATS_PPE_DROP_CODE_TX_EN_FAIL,				/* PPE drop code tx en fail */
-	NSS_STATS_PPE_DROP_CODE_VLAN_TAG_FMT,				/* PPE drop code vlan tag fmt */
-	NSS_STATS_PPE_DROP_CODE_CRC_ERR,				/* PPE drop code crc err */
-	NSS_STATS_PPE_DROP_CODE_PAUSE_FRAME,				/* PPE drop code pause frame */
-	NSS_STATS_PPE_DROP_CODE_PROMISC,				/* PPE drop code promisc */
-	NSS_STATS_PPE_DROP_CODE_ISOLATION,				/* PPE drop code isolation */
-	NSS_STATS_PPE_DROP_CODE_MGMT_APP,				/* PPE drop code mgmt app */
-	NSS_STATS_PPE_DROP_CODE_FAKE_L2_PROT_ERR,			/* PPE drop code fake l2 prot err */
-	NSS_STATS_PPE_DROP_CODE_POLICER,				/* PPE drop code policer */
-	NSS_STATS_PPE_DROP_CODE_MAX					/* PPE drop code max */
-};
-
-/*
- * PPE CPU codes
- */
-#define NSS_STATS_PPE_CPU_CODE_MAX 150
-#define NSS_STATS_PPE_CPU_CODE_EXCEPTION_MAX 69
-#define NSS_STATS_PPE_CPU_CODE_NONEXCEPTION_START 69
-#define NSS_STATS_PPE_CPU_CODE_NONEXCEPTION_MAX (NSS_STATS_PPE_CPU_CODE_MAX - NSS_STATS_PPE_CPU_CODE_NONEXCEPTION_START)
-enum nss_stats_ppe_cc {
-	NSS_STATS_PPE_CPU_CODE_FORWARDING                         = 0, /* PPE cpu code forwarding */
-	NSS_STATS_PPE_CPU_CODE_EXP_UNKNOWN_L2_PROT                = 1, /* PPE cpu code exp unknown l2 prot */
-	NSS_STATS_PPE_CPU_CODE_EXP_PPPOE_WRONG_VER_TYPE           = 2, /* PPE cpu code exp pppoe wrong ver type */
-	NSS_STATS_PPE_CPU_CODE_EXP_PPPOE_WRONG_CODE               = 3, /* PPE cpu code exp pppoe wrong code */
-	NSS_STATS_PPE_CPU_CODE_EXP_PPPOE_UNSUPPORTED_PPP_PROT     = 4, /* PPE cpu code exp pppoe unsupported ppp prot */
-	NSS_STATS_PPE_CPU_CODE_EXP_IPV4_WRONG_VER                 = 5, /* PPE cpu code exp ipv4 wrong ver */
-	NSS_STATS_PPE_CPU_CODE_EXP_IPV4_SMALL_IHL                 = 6, /* PPE cpu code exp ipv4 small ihl */
-	NSS_STATS_PPE_CPU_CODE_EXP_IPV4_WITH_OPTION               = 7, /* PPE cpu code exp ipv4 with option */
-	NSS_STATS_PPE_CPU_CODE_EXP_IPV4_HDR_INCOMPLETE            = 8, /* PPE cpu code exp ipv4 hdr incomplete */
-	NSS_STATS_PPE_CPU_CODE_EXP_IPV4_BAD_TOTAL_LEN             = 9, /* PPE cpu code exp ipv4 bad total len */
-	NSS_STATS_PPE_CPU_CODE_EXP_IPV4_DATA_INCOMPLETE           = 10, /* PPE cpu code exp ipv4 data incomplete */
-	NSS_STATS_PPE_CPU_CODE_EXP_IPV4_FRAG                      = 11, /* PPE cpu code exp ipv4 frag */
-	NSS_STATS_PPE_CPU_CODE_EXP_IPV4_PING_OF_DEATH             = 12, /* PPE cpu code exp ipv4 ping of death */
-	NSS_STATS_PPE_CPU_CODE_EXP_IPV4_SNALL_TTL                 = 13, /* PPE cpu code exp ipv4 snall ttl */
-	NSS_STATS_PPE_CPU_CODE_EXP_IPV4_UNK_IP_PROT               = 14, /* PPE cpu code exp ipv4 unk ip prot */
-	NSS_STATS_PPE_CPU_CODE_EXP_IPV4_CHECKSUM_ERR              = 15, /* PPE cpu code exp ipv4 checksum err */
-	NSS_STATS_PPE_CPU_CODE_EXP_IPV4_INV_SIP                   = 16, /* PPE cpu code exp ipv4 inv sip */
-	NSS_STATS_PPE_CPU_CODE_EXP_IPV4_INV_DIP                   = 17, /* PPE cpu code exp ipv4 inv dip */
-	NSS_STATS_PPE_CPU_CODE_EXP_IPV4_LAND_ATTACK               = 18, /* PPE cpu code exp ipv4 land attack */
-	NSS_STATS_PPE_CPU_CODE_EXP_IPV4_AH_HDR_INCOMPLETE         = 19, /* PPE cpu code exp ipv4 ah hdr incomplete */
-	NSS_STATS_PPE_CPU_CODE_EXP_IPV4_AH_HDR_CROSS_BORDER       = 20, /* PPE cpu code exp ipv4 ah hdr cross border */
-	NSS_STATS_PPE_CPU_CODE_EXP_IPV4_ESP_HDR_INCOMPLETE        = 21, /* PPE cpu code exp ipv4 esp hdr incomplete */
-	NSS_STATS_PPE_CPU_CODE_EXP_IPV6_WRONG_VER                 = 22, /* PPE cpu code exp ipv6 wrong ver */
-	NSS_STATS_PPE_CPU_CODE_EXP_IPV6_HDR_INCOMPLETE            = 23, /* PPE cpu code exp ipv6 hdr incomplete */
-	NSS_STATS_PPE_CPU_CODE_EXP_IPV6_BAD_PAYLOAD_LEN           = 24, /* PPE cpu code exp ipv6 bad payload len */
-	NSS_STATS_PPE_CPU_CODE_EXP_IPV6_DATA_INCOMPLETE           = 25, /* PPE cpu code exp ipv6 data incomplete */
-	NSS_STATS_PPE_CPU_CODE_EXP_IPV6_WITH_EXT_HDR              = 26, /* PPE cpu code exp ipv6 with ext hdr */
-	NSS_STATS_PPE_CPU_CODE_EXP_IPV6_SMALL_HOP_LIMIT           = 27, /* PPE cpu code exp ipv6 small hop limit */
-	NSS_STATS_PPE_CPU_CODE_EXP_IPV6_INV_SIP                   = 28, /* PPE cpu code exp ipv6 inv sip */
-	NSS_STATS_PPE_CPU_CODE_EXP_IPV6_INV_DIP                   = 29, /* PPE cpu code exp ipv6 inv dip */
-	NSS_STATS_PPE_CPU_CODE_EXP_IPV6_LAND_ATTACK               = 30, /* PPE cpu code exp ipv6 land attack */
-	NSS_STATS_PPE_CPU_CODE_EXP_IPV6_FRAG                      = 31, /* PPE cpu code exp ipv6 frag */
-	NSS_STATS_PPE_CPU_CODE_EXP_IPV6_PING_OF_DEATH             = 32, /* PPE cpu code exp ipv6 ping of death */
-	NSS_STATS_PPE_CPU_CODE_EXP_IPV6_WITH_MORE_EXT_HDR         = 33, /* PPE cpu code exp ipv6 with more ext hdr */
-	NSS_STATS_PPE_CPU_CODE_EXP_IPV6_UNK_LAST_NEXT_HDR         = 34, /* PPE cpu code exp ipv6 unk last next hdr */
-	NSS_STATS_PPE_CPU_CODE_EXP_IPV6_MOBILITY_HDR_INCOMPLETE   = 35, /* PPE cpu code exp ipv6 mobility hdr incomplete */
-	NSS_STATS_PPE_CPU_CODE_EXP_IPV6_MOBILITY_HDR_CROSS_BORDER = 36, /* PPE cpu code exp ipv6 mobility hdr cross border */
-	NSS_STATS_PPE_CPU_CODE_EXP_IPV6_AH_HDR_INCOMPLETE         = 37, /* PPE cpu code exp ipv6 ah hdr incomplete */
-	NSS_STATS_PPE_CPU_CODE_EXP_IPV6_AH_HDR_CROSS_BORDER       = 38, /* PPE cpu code exp ipv6 ah hdr cross border */
-	NSS_STATS_PPE_CPU_CODE_EXP_IPV6_ESP_HDR_INCOMPLETE        = 39, /* PPE cpu code exp ipv6 esp hdr incomplete */
-	NSS_STATS_PPE_CPU_CODE_EXP_IPV6_ESP_HDR_CROSS_BORDER      = 40, /* PPE cpu code exp ipv6 esp hdr cross border */
-	NSS_STATS_PPE_CPU_CODE_EXP_IPV6_OTHER_EXT_HDR_INCOMPLETE  = 41, /* PPE cpu code exp ipv6 other ext hdr incomplete */
-	NSS_STATS_PPE_CPU_CODE_EXP_IPV6_OTHER_EXT_HDR_CROSS_BORDER = 42, /* PPE cpu code exp ipv6 other ext hdr cross border */
-	NSS_STATS_PPE_CPU_CODE_EXP_TCP_HDR_INCOMPLETE             = 43, /* PPE cpu code exp tcp hdr incomplete */
-	NSS_STATS_PPE_CPU_CODE_EXP_TCP_HDR_CROSS_BORDER           = 44, /* PPE cpu code exp tcp hdr cross border */
-	NSS_STATS_PPE_CPU_CODE_EXP_TCP_SMAE_SP_DP                 = 45, /* PPE cpu code exp tcp smae sp dp */
-	NSS_STATS_PPE_CPU_CODE_EXP_TCP_SMALL_DATA_OFFSET          = 46, /* PPE cpu code exp tcp small data offset */
-	NSS_STATS_PPE_CPU_CODE_EXP_TCP_FLAGS_0                    = 47, /* PPE cpu code exp tcp flags 0 */
-	NSS_STATS_PPE_CPU_CODE_EXP_TCP_FLAGS_1                    = 48, /* PPE cpu code exp tcp flags 1 */
-	NSS_STATS_PPE_CPU_CODE_EXP_TCP_FLAGS_2                    = 49, /* PPE cpu code exp tcp flags 2 */
-	NSS_STATS_PPE_CPU_CODE_EXP_TCP_FLAGS_3                    = 50, /* PPE cpu code exp tcp flags 3 */
-	NSS_STATS_PPE_CPU_CODE_EXP_TCP_FLAGS_4                    = 51, /* PPE cpu code exp tcp flags 4 */
-	NSS_STATS_PPE_CPU_CODE_EXP_TCP_FLAGS_5                    = 52, /* PPE cpu code exp tcp flags 5 */
-	NSS_STATS_PPE_CPU_CODE_EXP_TCP_FLAGS_6                    = 53, /* PPE cpu code exp tcp flags 6 */
-	NSS_STATS_PPE_CPU_CODE_EXP_TCP_FLAGS_7                    = 54, /* PPE cpu code exp tcp flags 7 */
-	NSS_STATS_PPE_CPU_CODE_EXP_TCP_CHECKSUM_ERR               = 55, /* PPE cpu code exp tcp checksum err */
-	NSS_STATS_PPE_CPU_CODE_EXP_UDP_HDR_INCOMPLETE             = 56, /* PPE cpu code exp udp hdr incomplete */
-	NSS_STATS_PPE_CPU_CODE_EXP_UDP_HDR_CROSS_BORDER           = 57, /* PPE cpu code exp udp hdr cross border */
-	NSS_STATS_PPE_CPU_CODE_EXP_UDP_SMAE_SP_DP                 = 58, /* PPE cpu code exp udp smae sp dp */
-	NSS_STATS_PPE_CPU_CODE_EXP_UDP_BAD_LEN                    = 59, /* PPE cpu code exp udp bad len */
-	NSS_STATS_PPE_CPU_CODE_EXP_UDP_DATA_INCOMPLETE            = 60, /* PPE cpu code exp udp data incomplete */
-	NSS_STATS_PPE_CPU_CODE_EXP_UDP_CHECKSUM_ERR               = 61, /* PPE cpu code exp udp checksum err */
-	NSS_STATS_PPE_CPU_CODE_EXP_UDP_LITE_HDR_INCOMPLETE        = 62, /* PPE cpu code exp udp lite hdr incomplete */
-	NSS_STATS_PPE_CPU_CODE_EXP_UDP_LITE_HDR_CROSS_BORDER      = 63, /* PPE cpu code exp udp lite hdr cross border */
-	NSS_STATS_PPE_CPU_CODE_EXP_UDP_LITE_SMAE_SP_DP            = 64, /* PPE cpu code exp udp lite smae sp dp */
-	NSS_STATS_PPE_CPU_CODE_EXP_UDP_LITE_CSM_COV_1_TO_7        = 65, /* PPE cpu code exp udp lite csm cov 1 to 7 */
-	NSS_STATS_PPE_CPU_CODE_EXP_UDP_LITE_CSM_COV_TOO_LONG      = 66, /* PPE cpu code exp udp lite csm cov too long */
-	NSS_STATS_PPE_CPU_CODE_EXP_UDP_LITE_CSM_COV_CROSS_BORDER  = 67, /* PPE cpu code exp udp lite csm cov cross border */
-	NSS_STATS_PPE_CPU_CODE_EXP_UDP_LITE_CHECKSUM_ERR          = 68, /* PPE cpu code exp udp lite checksum err */
-	NSS_STATS_PPE_CPU_CODE_EXP_FAKE_L2_PROT_ERR               = 69, /* PPE cpu code exp fake l2 prot err */
-	NSS_STATS_PPE_CPU_CODE_EXP_FAKE_MAC_HEADER_ERR            = 70, /* PPE cpu code exp fake mac header err */
-	NSS_STATS_PPE_CPU_CODE_EXP_BITMAP_MAX                     = 78, /* PPE cpu code exp bitmap max */
-	NSS_STATS_PPE_CPU_CODE_L2_EXP_MRU_FAIL                    = 79, /* PPE cpu code l2 exp mru fail */
-	NSS_STATS_PPE_CPU_CODE_L2_EXP_MTU_FAIL                    = 80, /* PPE cpu code l2 exp mtu fail */
-	NSS_STATS_PPE_CPU_CODE_L3_EXP_IP_PREFIX_BC                = 81, /* PPE cpu code l3 exp ip prefix bc */
-	NSS_STATS_PPE_CPU_CODE_L3_EXP_MTU_FAIL                    = 82, /* PPE cpu code l3 exp mtu fail */
-	NSS_STATS_PPE_CPU_CODE_L3_EXP_MRU_FAIL                    = 83, /* PPE cpu code l3 exp mru fail */
-	NSS_STATS_PPE_CPU_CODE_L3_EXP_ICMP_RDT                    = 84, /* PPE cpu code l3 exp icmp rdt */
-	NSS_STATS_PPE_CPU_CODE_L3_EXP_IP_RT_TTL1_TO_ME            = 85, /* PPE cpu code l3 exp ip rt ttl1 to me */
-	NSS_STATS_PPE_CPU_CODE_L3_EXP_IP_RT_TTL_ZERO              = 86, /* PPE cpu code l3 exp ip rt ttl zero */
-	NSS_STATS_PPE_CPU_CODE_L3_FLOW_SERVICE_CODE_LOOP          = 87, /* PPE cpu code l3 flow service code loop */
-	NSS_STATS_PPE_CPU_CODE_L3_FLOW_DE_ACCELERATE              = 88, /* PPE cpu code l3 flow de accelerate */
-	NSS_STATS_PPE_CPU_CODE_L3_EXP_FLOW_SRC_IF_CHK_FAIL        = 89, /* PPE cpu code l3 exp flow src if chk fail */
-	NSS_STATS_PPE_CPU_CODE_L3_FLOW_SYNC_TOGGLE_MISMATCH       = 90, /* PPE cpu code l3 flow sync toggle mismatch */
-	NSS_STATS_PPE_CPU_CODE_L3_EXP_MTU_DF_FAIL                 = 91, /* PPE cpu code l3 exp mtu df fail */
-	NSS_STATS_PPE_CPU_CODE_L3_EXP_PPPOE_MULTICAST             = 92, /* PPE cpu code l3 exp pppoe multicast */
-	NSS_STATS_PPE_CPU_CODE_MGMT_OFFSET                        = 96, /* PPE cpu code mgmt offset */
-	NSS_STATS_PPE_CPU_CODE_MGMT_EAPOL                         = 97, /* PPE cpu code mgmt eapol */
-	NSS_STATS_PPE_CPU_CODE_MGMT_PPPOE_DIS                     = 98, /* PPE cpu code mgmt pppoe dis */
-	NSS_STATS_PPE_CPU_CODE_MGMT_IGMP                          = 99, /* PPE cpu code mgmt igmp */
-	NSS_STATS_PPE_CPU_CODE_MGMT_ARP_REQ                       = 100, /* PPE cpu code mgmt arp req */
-	NSS_STATS_PPE_CPU_CODE_MGMT_ARP_REP                       = 101, /* PPE cpu code mgmt arp rep */
-	NSS_STATS_PPE_CPU_CODE_MGMT_DHCPv4                        = 102, /* PPE cpu code mgmt dhcpv4 */
-	NSS_STATS_PPE_CPU_CODE_MGMT_MLD                           = 107, /* PPE cpu code mgmt mld */
-	NSS_STATS_PPE_CPU_CODE_MGMT_NS                            = 108, /* PPE cpu code mgmt ns */
-	NSS_STATS_PPE_CPU_CODE_MGMT_NA                            = 109, /* PPE cpu code mgmt na */
-	NSS_STATS_PPE_CPU_CODE_MGMT_DHCPv6                        = 110, /* PPE cpu code mgmt dhcpv6 */
-	NSS_STATS_PPE_CPU_CODE_PTP_OFFSET                         = 112, /* PPE cpu code ptp offset */
-	NSS_STATS_PPE_CPU_CODE_PTP_SYNC                           = 113, /* PPE cpu code ptp sync */
-	NSS_STATS_PPE_CPU_CODE_PTP_FOLLOW_UP                      = 114, /* PPE cpu code ptp follow up */
-	NSS_STATS_PPE_CPU_CODE_PTP_DELAY_REQ                      = 115, /* PPE cpu code ptp delay req */
-	NSS_STATS_PPE_CPU_CODE_PTP_DELAY_RESP                     = 116, /* PPE cpu code ptp delay resp */
-	NSS_STATS_PPE_CPU_CODE_PTP_PDELAY_REQ                     = 117, /* PPE cpu code ptp pdelay req */
-	NSS_STATS_PPE_CPU_CODE_PTP_PDELAY_RESP                    = 118, /* PPE cpu code ptp pdelay resp */
-	NSS_STATS_PPE_CPU_CODE_PTP_PDELAY_RESP_FOLLOW_UP          = 119, /* PPE cpu code ptp pdelay resp follow up */
-	NSS_STATS_PPE_CPU_CODE_PTP_ANNOUNCE                       = 120, /* PPE cpu code ptp announce */
-	NSS_STATS_PPE_CPU_CODE_PTP_MANAGEMENT                     = 121, /* PPE cpu code ptp management */
-	NSS_STATS_PPE_CPU_CODE_PTP_SIGNALING                      = 122, /* PPE cpu code ptp signaling */
-	NSS_STATS_PPE_CPU_CODE_PTP_PKT_RSV_MSG                    = 127, /* PPE cpu code ptp pkt rsv msg */
-	NSS_STATS_PPE_CPU_CODE_IPV4_SG_UNKNOWN                    = 136, /* PPE cpu code ipv4 sg unknown */
-	NSS_STATS_PPE_CPU_CODE_IPV6_SG_UNKNOWN                    = 137, /* PPE cpu code ipv6 sg unknown */
-	NSS_STATS_PPE_CPU_CODE_ARP_SG_UNKNOWN                     = 138, /* PPE cpu code arp sg unknown */
-	NSS_STATS_PPE_CPU_CODE_ND_SG_UNKNOWN                      = 139, /* PPE cpu code nd sg unknown */
-	NSS_STATS_PPE_CPU_CODE_IPV4_SG_VIO                        = 140, /* PPE cpu code ipv4 sg vio */
-	NSS_STATS_PPE_CPU_CODE_IPV6_SG_VIO                        = 141, /* PPE cpu code ipv6 sg vio */
-	NSS_STATS_PPE_CPU_CODE_ARP_SG_VIO                         = 142, /* PPE cpu code arp sg vio */
-	NSS_STATS_PPE_CPU_CODE_ND_SG_VIO                          = 143, /* PPE cpu code nd sg vio */
-	NSS_STATS_PPE_CPU_CODE_L3_ROUTING_IP_TO_ME                = 148, /* PPE cpu code l3 routing ip to me */
-	NSS_STATS_PPE_CPU_CODE_L3_FLOW_SNAT_ACTION                = 149, /* PPE cpu code l3 flow snat action */
-	NSS_STATS_PPE_CPU_CODE_L3_FLOW_DNAT_ACTION                = 150, /* PPE cpu code l3 flow dnat action */
-	NSS_STATS_PPE_CPU_CODE_L3_FLOW_RT_ACTION                  = 151, /* PPE cpu code l3 flow rt action */
-	NSS_STATS_PPE_CPU_CODE_L3_FLOW_BR_ACTION                  = 152, /* PPE cpu code l3 flow br action */
-	NSS_STATS_PPE_CPU_CODE_L3_MC_BRIDGE_ACTION                = 153, /* PPE cpu code l3 mc bridge action */
-	NSS_STATS_PPE_CPU_CODE_L3_ROUTE_PREHEAD_RT_ACTION         = 154, /* PPE cpu code l3 route prehead rt action */
-	NSS_STATS_PPE_CPU_CODE_L3_ROUTE_PREHEAD_SNAPT_ACTION      = 155, /* PPE cpu code l3 route prehead snapt action */
-	NSS_STATS_PPE_CPU_CODE_L3_ROUTE_PREHEAD_DNAPT_ACTION      = 156, /* PPE cpu code l3 route prehead dnapt action */
-	NSS_STATS_PPE_CPU_CODE_L3_ROUTE_PREHEAD_SNAT_ACTION       = 157, /* PPE cpu code l3 route prehead snat action */
-	NSS_STATS_PPE_CPU_CODE_L3_ROUTE_PREHEAD_DNAT_ACTION       = 158, /* PPE cpu code l3 route prehead dnat action */
-	NSS_STATS_PPE_CPU_CODE_L3_NO_ROUTE_PREHEAD_NAT_ACTION     = 159, /* PPE cpu code l3 no route prehead nat action */
-	NSS_STATS_PPE_CPU_CODE_L3_NO_ROUTE_PREHEAD_NAT_ERROR      = 160, /* PPE cpu code l3 no route prehead nat error */
-	NSS_STATS_PPE_CPU_CODE_L3_ROUTE_ACTION                    = 161, /* PPE cpu code l3 route action */
-	NSS_STATS_PPE_CPU_CODE_L3_NO_ROUTE_ACTION                 = 162, /* PPE cpu code l3 no route action */
-	NSS_STATS_PPE_CPU_CODE_L3_NO_ROUTE_NH_INVALID_ACTION      = 163, /* PPE cpu code l3 no route nh invalid action */
-	NSS_STATS_PPE_CPU_CODE_L3_NO_ROUTE_PREHEAD_ACTION         = 164, /* PPE cpu code l3 no route prehead action */
-	NSS_STATS_PPE_CPU_CODE_L3_BRIDGE_ACTION                   = 165, /* PPE cpu code l3 bridge action */
-	NSS_STATS_PPE_CPU_CODE_L3_FLOW_ACTION                     = 166, /* PPE cpu code l3 flow action */
-	NSS_STATS_PPE_CPU_CODE_L3_FLOW_MISS_ACTION                = 167, /* PPE cpu code l3 flow miss action */
-	NSS_STATS_PPE_CPU_CODE_L2_NEW_MAC_ADDRESS                 = 168, /* PPE cpu code l2 new mac address */
-	NSS_STATS_PPE_CPU_CODE_L2_HASH_COLLISION                  = 169, /* PPE cpu code l2 hash collision */
-	NSS_STATS_PPE_CPU_CODE_L2_STATION_MOVE                    = 170, /* PPE cpu code l2 station move */
-	NSS_STATS_PPE_CPU_CODE_L2_LEARN_LIMIT                     = 171, /* PPE cpu code l2 learn limit */
-	NSS_STATS_PPE_CPU_CODE_L2_SA_LOOKUP_ACTION                = 172, /* PPE cpu code l2 sa lookup action */
-	NSS_STATS_PPE_CPU_CODE_L2_DA_LOOKUP_ACTION                = 173, /* PPE cpu code l2 da lookup action */
-	NSS_STATS_PPE_CPU_CODE_APP_CTRL_ACTION                    = 174, /* PPE cpu code app ctrl action */
-	NSS_STATS_PPE_CPU_CODE_IN_VLAN_FILTER_ACTION              = 175, /* PPE cpu code in vlan filter action */
-	NSS_STATS_PPE_CPU_CODE_IN_VLAN_XLT_MISS                   = 176, /* PPE cpu code in vlan xlt miss */
-	NSS_STATS_PPE_CPU_CODE_EG_VLAN_FILTER_DROP                = 177, /* PPE cpu code eg vlan filter drop */
-	NSS_STATS_PPE_CPU_CODE_ACL_PRE_ACTION                     = 178, /* PPE cpu code acl pre action */
-	NSS_STATS_PPE_CPU_CODE_ACL_POST_ACTION                    = 179, /* PPE cpu code acl post action */
-	NSS_STATS_PPE_CPU_CODE_SERVICE_CODE_ACTION                = 180, /* PPE cpu code service code action */
-};
-
-struct nss_stats_ppe_debug {
-	uint32_t conn_stats[NSS_STATS_PPE_CONN_MAX];
-	uint32_t l3_stats[NSS_STATS_PPE_L3_MAX];
-	uint32_t code_stats[NSS_STATS_PPE_CODE_MAX];
-	int32_t if_index;
-	uint32_t if_num; /* nss interface number */
-	bool valid;
-};
-
-/*
- * 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 {
-	NSS_STATS_MAP_T_V4_TO_V6_PBUF_EXCEPTION,
-	NSS_STATS_MAP_T_V4_TO_V6_PBUF_NO_MATCHING_RULE,
-	NSS_STATS_MAP_T_V4_TO_V6_PBUF_NOT_TCP_OR_UDP,
-	NSS_STATS_MAP_T_V4_TO_V6_RULE_ERR_LOCAL_PSID,
-	NSS_STATS_MAP_T_V4_TO_V6_RULE_ERR_LOCAL_IPV6,
-	NSS_STATS_MAP_T_V4_TO_V6_RULE_ERR_REMOTE_PSID,
-	NSS_STATS_MAP_T_V4_TO_V6_RULE_ERR_REMOTE_EA_BITS,
-	NSS_STATS_MAP_T_V4_TO_V6_RULE_ERR_REMOTE_IPV6,
-	NSS_STATS_MAP_T_V6_TO_V4_PBUF_EXCEPTION,
-	NSS_STATS_MAP_T_V6_TO_V4_PBUF_NO_MATCHING_RULE,
-	NSS_STATS_MAP_T_V6_TO_V4_PBUF_NOT_TCP_OR_UDP,
-	NSS_STATS_MAP_T_V6_TO_V4_RULE_ERR_LOCAL_IPV4,
-	NSS_STATS_MAP_T_V6_TO_V4_RULE_ERR_REMOTE_IPV4,
-	NSS_STATS_MAP_T_MAX
-};
-
-/*
- * Trustsec TX statistics
- */
-enum nss_stats_trustsec_tx {
-	NSS_STATS_TRUSTSEC_TX_INVALID_SRC,
-					/* Number of packets with invalid src if */
-	NSS_STATS_TRUSTSEC_TX_UNCONFIGURED_SRC,
-					/* Number of packets with unconfigured src if */
-	NSS_STATS_IRUSTSEC_TX_HEADROOM_NOT_ENOUGH,
-					/* Number of packets with not enough headroom */
-	NSS_STATS_TRUSTSEC_TX_MAX
-};
-
-/*
- * NSS core stats -- for H2N/N2H map_t debug stats
- */
-struct nss_stats_map_t_instance_debug {
-	uint64_t stats[NSS_STATS_MAP_T_MAX];
-	int32_t if_index;
-	uint32_t if_num; /* nss interface number */
-	bool valid;
-};
-
-/*
- * Types of EDMA Tx ring stats
- */
-enum nss_stats_edma_tx_t {
-	NSS_STATS_EDMA_TX_ERR,
-	NSS_STATS_EDMA_TX_DROPPED,
-	NSS_STATS_EDMA_TX_DESC,
-	NSS_STATS_EDMA_TX_MAX
-};
-
-/*
- * Types of EDMA Rx ring stats
- */
-enum nss_stats_edma_rx_t {
-	NSS_STATS_EDMA_RX_CSUM_ERR,
-	NSS_STATS_EDMA_RX_DESC,
-	NSS_STATS_EDMA_RX_QOS_ERR,
-	NSS_STATS_EDMA_RX_MAX
-};
-
-/*
- * Types of EDMA Tx complete stats
- */
-enum nss_stats_edma_txcmpl_t {
-	NSS_STATS_EDMA_TXCMPL_DESC,
-	NSS_STATS_EDMA_TXCMPL_MAX
-};
-
-/*
- * Types of EDMA Rx fill stats
- */
-enum nss_stats_edma_rxfill_t {
-	NSS_STATS_EDMA_RXFILL_DESC,
-	NSS_STATS_EDMA_RXFILL_MAX
-};
-
-/*
- * Port to EDMA ring map
- */
-enum nss_edma_port_ring_map_t {
-	NSS_EDMA_PORT_RX_RING,
-	NSS_EDMA_PORT_TX_RING,
-	NSS_EDMA_PORT_RING_MAP_MAX
-};
-
-/*
- * Types of EDMA ERROR STATS
- */
-enum nss_edma_err_t {
-	NSS_EDMA_AXI_RD_ERR,
-	NSS_EDMA_AXI_WR_ERR,
-	NSS_EDMA_RX_DESC_FIFO_FULL_ERR,
-	NSS_EDMA_RX_BUF_SIZE_ERR,
-	NSS_EDMA_TX_SRAM_FULL_ERR,
-	NSS_EDMA_TX_CMPL_BUF_FULL_ERR,
-	NSS_EDMA_PKT_LEN_LA64K_ERR,
-	NSS_EDMA_PKT_LEN_LE33_ERR,
-	NSS_EDMA_DATA_LEN_ERR,
-	NSS_EDMA_ALLOC_FAIL_CNT,
-	NSS_EDMA_ERR_STATS_MAX
-};
-
-/*
- * NSS EDMA port stats
- */
-struct nss_edma_port_info {
-	uint64_t port_stats[NSS_STATS_NODE_MAX];
-	uint64_t port_type;
-	uint64_t port_ring_map[NSS_EDMA_PORT_RING_MAP_MAX];
-};
-
-/*
- * NSS EDMA node statistics
- */
-struct nss_edma_stats {
-	struct nss_edma_port_info port[NSS_EDMA_NUM_PORTS_MAX];
-	uint64_t tx_stats[NSS_EDMA_NUM_TX_RING_MAX][NSS_STATS_EDMA_TX_MAX];
-	uint64_t rx_stats[NSS_EDMA_NUM_RX_RING_MAX][NSS_STATS_EDMA_RX_MAX];
-	uint64_t txcmpl_stats[NSS_EDMA_NUM_TXCMPL_RING_MAX][NSS_STATS_EDMA_TXCMPL_MAX];
-	uint64_t rxfill_stats[NSS_EDMA_NUM_RXFILL_RING_MAX][NSS_STATS_EDMA_RXFILL_MAX];
-	uint64_t misc_err[NSS_EDMA_ERR_STATS_MAX];
-};
-
-/*
  * NSS core state
  */
 enum nss_core_state {
@@ -1509,8 +464,6 @@
 	spinlock_t decongest_cb_lock;	/* Lock to protect queue decongestion cb table */
 	uint16_t phys_if_mtu[NSS_MAX_PHYSICAL_INTERFACES];
 					/* Current MTU value of physical interface */
-	uint64_t stats_n2h[NSS_STATS_N2H_MAX];
-					/* N2H node stats: includes node, n2h, pbuf in this order */
 	uint32_t worker_thread_count;	/* Number of NSS core worker threads for statistics */
 	uint32_t irq_count;		/* Number of NSS core IRQs for statistics */
 	struct nss_worker_thread_stats *wt_stats;
@@ -1524,30 +477,6 @@
 };
 
 /*
- * NSS wifili stats
- */
-struct nss_wifili_stats {
-	uint64_t stats_txrx[NSS_WIFILI_MAX_PDEV_NUM_MSG][NSS_STATS_WIFILI_TXRX_MAX];
-							/* Number of txrx stats*/
-	uint64_t stats_tcl_ring[NSS_WIFILI_MAX_TCL_DATA_RINGS_MSG][NSS_STATS_WIFILI_TCL_MAX];
-							/* Tcl stats for each ring*/
-	uint64_t stats_tx_comp[NSS_WIFILI_MAX_TCL_DATA_RINGS_MSG][NSS_STATS_WIFILI_TX_DESC_FREE_MAX];
-							/* Tx comp ring stats*/
-	uint64_t stats_tx_desc[NSS_WIFILI_MAX_TXDESC_POOLS_MSG][NSS_STATS_WIFILI_TX_DESC_MAX];
-							/* Tx desc pool stats*/
-	uint64_t stats_ext_tx_desc[NSS_WIFILI_MAX_TX_EXT_DESC_POOLS_MSG][NSS_STATS_WIFILI_EXT_TX_DESC_MAX];
-							/* Tx ext desc pool stats*/
-	uint64_t stats_reo[NSS_WIFILI_MAX_REO_DATA_RINGS_MSG][NSS_STATS_WIFILI_REO_MAX];
-							/* Rx  reo ring stats*/
-	uint64_t stats_rx_desc[NSS_WIFILI_MAX_PDEV_NUM_MSG][NSS_STATS_WIFILI_RX_DESC_MAX];
-							/* Rx  rx sw pool stats*/
-	uint64_t stats_rxdma[NSS_WIFILI_MAX_PDEV_NUM_MSG][NSS_STATS_WIFILI_RXDMA_DESC_MAX];
-							/* Rx  dma ring stats*/
-	uint64_t stats_wbm[NSS_STATS_WIFILI_WBM_MAX];
-							/* Wbm  error ring stats*/
-};
-
-/*
  * Main NSS context structure (singleton)
  */
 struct nss_top_instance {
@@ -1559,43 +488,7 @@
 	struct mutex wq_lock;			/* Mutex for NSS Work queue function */
 	struct dentry *top_dentry;		/* Top dentry for nss */
 	struct dentry *stats_dentry;		/* Top dentry for nss stats */
-	struct dentry *ipv4_dentry;		/* IPv4 stats dentry */
-	struct dentry *ipv4_reasm_dentry;
-						/* IPv4 reassembly stats dentry */
-	struct dentry *ipv6_dentry;		/* IPv6 stats dentry */
-	struct dentry *ipv6_reasm_dentry;
-						/* IPv6 reassembly stats dentry */
-	struct dentry *eth_rx_dentry;		/* ETH_RX stats dentry */
-	struct dentry *n2h_dentry;		/* N2H stats dentry */
-	struct dentry *lso_rx_dentry;		/* LSO_RX stats dentry */
-	struct dentry *drv_dentry;		/* HLOS driver stats dentry */
-	struct dentry *pppoe_dentry;		/* PPPOE stats dentry */
-	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 */
-	struct dentry *capwap_decap_dentry;	/* CAPWAP decap ethnode stats dentry */
-	struct dentry *capwap_encap_dentry;	/* CAPWAP encap ethnode stats dentry */
-	struct dentry *ppe_dentry;	/* PPE root dentry */
-	struct dentry *ppe_conn_dentry;	/* PPE connection stats dentry */
-	struct dentry *ppe_l3_dentry;	/* PPE L3 debug stats dentry */
-	struct dentry *ppe_code_dentry;	/* PPE code stats dentry */
-	struct dentry *gre_redir_dentry;	/* gre_redir ethnode stats dentry */
-	struct dentry *sjack_dentry;		/* sjack stats dentry */
-	struct dentry *trustsec_tx_dentry;	/* trustsec tx stats dentry */
-	struct dentry *portid_dentry;		/* portid stats dentry */
-	struct dentry *wifi_dentry;		/* wifi stats dentry */
-	struct dentry *logs_dentry;		/* NSS FW logs directory */
-	struct dentry *core_log_dentry;		/* NSS Core's FW log file */
-	struct dentry *wifi_if_dentry;		/* wifi_if stats dentry */
-	struct dentry *virt_if_dentry;		/* virt_if stats dentry */
-	struct dentry *tx_rx_virt_if_dentry;	/* tx_rx_virt_if stats dentry. Will be deprecated soon */
-	struct dentry *wifili_dentry;		/* wifili stats dentry */
 	struct dentry *project_dentry;		/* per-project stats dentry */
-
 	struct nss_ctx_instance nss[NSS_MAX_CORES];
 						/* NSS contexts */
 	/*
@@ -1714,44 +607,12 @@
 	/*
 	 * Statistics for various interfaces
 	 */
-	uint64_t stats_ipv4[NSS_STATS_IPV4_MAX];
-					/* IPv4 statistics */
-	uint64_t stats_ipv4_reasm[NSS_STATS_IPV4_REASM_MAX];
-					/* IPv4 reasm statistics */
-	uint64_t stats_ipv6[NSS_STATS_IPV6_MAX];
-					/* IPv6 statistics */
-	uint64_t stats_ipv6_reasm[NSS_STATS_IPV6_REASM_MAX];
-					/* IPv6 reasm statistics */
-	uint64_t stats_lso_rx[NSS_STATS_LSO_RX_MAX];
-					/* LSO_RX statistics */
 	atomic64_t stats_drv[NSS_STATS_DRV_MAX];
 					/* Hlos driver statistics */
-	uint64_t stats_pppoe[NSS_STATS_PPPOE_MAX];
-					/* PPPoE statistics */
 	uint64_t stats_gmac[NSS_MAX_PHYSICAL_INTERFACES][NSS_STATS_GMAC_MAX];
 					/* GMAC statistics */
-	uint64_t stats_wifi[NSS_MAX_WIFI_RADIO_INTERFACES][NSS_STATS_WIFI_MAX];
-					/* WIFI statistics */
-	uint64_t stats_eth_rx[NSS_STATS_ETH_RX_MAX];
-					/* ETH_RX statistics */
 	uint64_t stats_node[NSS_MAX_NET_INTERFACES][NSS_STATS_NODE_MAX];
 					/* IPv4 statistics per interface */
-	uint64_t stats_if_exception_eth_rx[NSS_EXCEPTION_EVENT_ETH_RX_MAX];
-					/* Unknown protocol exception events per interface */
-	uint64_t stats_if_exception_ipv4[NSS_EXCEPTION_EVENT_IPV4_MAX];
-					/* IPv4 protocol exception events per interface */
-	uint64_t stats_if_exception_ipv6[NSS_EXCEPTION_EVENT_IPV6_MAX];
-					/* IPv6 protocol exception events per interface */
-	uint64_t stats_if_exception_pppoe[NSS_MAX_PHYSICAL_INTERFACES + 1][NSS_PPPOE_NUM_SESSION_PER_INTERFACE + 1][NSS_PPPOE_EXCEPTION_EVENT_MAX];
-					/* PPPoE exception events for per session on per interface. Interface and session indexes start with 1. */
-	uint64_t stats_portid[NSS_STATS_PORTID_MAX];
-					/* PortID statistics */
-	struct nss_edma_stats stats_edma;
-					/* EDMA node stats */
-	uint64_t stats_trustsec_tx[NSS_STATS_TRUSTSEC_TX_MAX];
-					/* Trustsec TX stats */
-
-	struct nss_wifili_stats stats_wifili; /* Wifili stats*/
 	bool nss_hal_common_init_done;
 
 	uint16_t prev_mtu_sz;		/* mtu sz needed as of now */
diff --git a/nss_dtls.c b/nss_dtls.c
index 6fcd88b..f6ec614 100644
--- a/nss_dtls.c
+++ b/nss_dtls.c
@@ -22,8 +22,8 @@
 /*
  * Data structures to store DTLS nss debug stats
  */
-static DEFINE_SPINLOCK(nss_dtls_session_debug_stats_lock);
-static struct nss_stats_dtls_session_debug nss_dtls_session_debug_stats[NSS_MAX_DTLS_SESSIONS];
+static DEFINE_SPINLOCK(nss_dtls_session_stats_lock);
+static struct nss_dtls_stats_session session_stats[NSS_MAX_DTLS_SESSIONS];
 
 /*
  * Private data structure
@@ -61,68 +61,68 @@
 					uint16_t if_num)
 {
 	int i;
-	struct nss_stats_dtls_session_debug *s = NULL;
+	struct nss_dtls_stats_session *s = NULL;
 
 	NSS_VERIFY_CTX_MAGIC(nss_ctx);
 
-	spin_lock_bh(&nss_dtls_session_debug_stats_lock);
+	spin_lock_bh(&nss_dtls_session_stats_lock);
 	for (i = 0; i < NSS_MAX_DTLS_SESSIONS; i++) {
-		if (nss_dtls_session_debug_stats[i].if_num != if_num) {
+		if (session_stats[i].if_num != if_num) {
 			continue;
 		}
 
-		s = &nss_dtls_session_debug_stats[i];
+		s = &session_stats[i];
 		break;
 	}
 
 	if (!s) {
-		spin_unlock_bh(&nss_dtls_session_debug_stats_lock);
+		spin_unlock_bh(&nss_dtls_session_stats_lock);
 		return;
 	}
 
-	s->stats[NSS_STATS_DTLS_SESSION_RX_PKTS] += stats_msg->node_stats.rx_packets;
-	s->stats[NSS_STATS_DTLS_SESSION_TX_PKTS] += stats_msg->node_stats.tx_packets;
+	s->stats[NSS_DTLS_STATS_SESSION_RX_PKTS] += stats_msg->node_stats.rx_packets;
+	s->stats[NSS_DTLS_STATS_SESSION_TX_PKTS] += stats_msg->node_stats.tx_packets;
 	for (i = 0; i < NSS_MAX_NUM_PRI; i++) {
-		s->stats[NSS_STATS_DTLS_SESSION_RX_QUEUE_0_DROPPED + i] += stats_msg->node_stats.rx_dropped[i];
+		s->stats[NSS_DTLS_STATS_SESSION_RX_QUEUE_0_DROPPED + i] += stats_msg->node_stats.rx_dropped[i];
 	}
-	s->stats[NSS_STATS_DTLS_SESSION_RX_AUTH_DONE] += stats_msg->rx_auth_done;
-	s->stats[NSS_STATS_DTLS_SESSION_TX_AUTH_DONE] += stats_msg->tx_auth_done;
-	s->stats[NSS_STATS_DTLS_SESSION_RX_CIPHER_DONE] += stats_msg->rx_cipher_done;
-	s->stats[NSS_STATS_DTLS_SESSION_TX_CIPHER_DONE] += stats_msg->tx_cipher_done;
-	s->stats[NSS_STATS_DTLS_SESSION_RX_CBUF_ALLOC_FAIL] += stats_msg->rx_cbuf_alloc_fail;
-	s->stats[NSS_STATS_DTLS_SESSION_TX_CBUF_ALLOC_FAIL] += stats_msg->tx_cbuf_alloc_fail;
-	s->stats[NSS_STATS_DTLS_SESSION_TX_CENQUEUE_FAIL] += stats_msg->tx_cenqueue_fail;
-	s->stats[NSS_STATS_DTLS_SESSION_RX_CENQUEUE_FAIL] += stats_msg->rx_cenqueue_fail;
-	s->stats[NSS_STATS_DTLS_SESSION_TX_DROPPED_HROOM] += stats_msg->tx_dropped_hroom;
-	s->stats[NSS_STATS_DTLS_SESSION_TX_DROPPED_TROOM] += stats_msg->tx_dropped_troom;
-	s->stats[NSS_STATS_DTLS_SESSION_TX_FORWARD_ENQUEUE_FAIL] += stats_msg->tx_forward_enqueue_fail;
-	s->stats[NSS_STATS_DTLS_SESSION_RX_FORWARD_ENQUEUE_FAIL] += stats_msg->rx_forward_enqueue_fail;
-	s->stats[NSS_STATS_DTLS_SESSION_RX_INVALID_VERSION] += stats_msg->rx_invalid_version;
-	s->stats[NSS_STATS_DTLS_SESSION_RX_INVALID_EPOCH] += stats_msg->rx_invalid_epoch;
-	s->stats[NSS_STATS_DTLS_SESSION_RX_MALFORMED] += stats_msg->rx_malformed;
-	s->stats[NSS_STATS_DTLS_SESSION_RX_CIPHER_FAIL] += stats_msg->rx_cipher_fail;
-	s->stats[NSS_STATS_DTLS_SESSION_RX_AUTH_FAIL] += stats_msg->rx_auth_fail;
-	s->stats[NSS_STATS_DTLS_SESSION_RX_CAPWAP_CLASSIFY_FAIL] += stats_msg->rx_capwap_classify_fail;
-	s->stats[NSS_STATS_DTLS_SESSION_RX_SINGLE_REC_DGRAM] += stats_msg->rx_single_rec_dgram;
-	s->stats[NSS_STATS_DTLS_SESSION_RX_MULTI_REC_DGRAM] += stats_msg->rx_multi_rec_dgram;
-	s->stats[NSS_STATS_DTLS_SESSION_RX_REPLAY_FAIL] += stats_msg->rx_replay_fail;
-	s->stats[NSS_STATS_DTLS_SESSION_RX_REPLAY_DUPLICATE] += stats_msg->rx_replay_duplicate;
-	s->stats[NSS_STATS_DTLS_SESSION_RX_REPLAY_OUT_OF_WINDOW] += stats_msg->rx_replay_out_of_window;
-	s->stats[NSS_STATS_DTLS_SESSION_OUTFLOW_QUEUE_FULL] += stats_msg->outflow_queue_full;
-	s->stats[NSS_STATS_DTLS_SESSION_DECAP_QUEUE_FULL] += stats_msg->decap_queue_full;
-	s->stats[NSS_STATS_DTLS_SESSION_PBUF_ALLOC_FAIL] += stats_msg->pbuf_alloc_fail;
-	s->stats[NSS_STATS_DTLS_SESSION_PBUF_COPY_FAIL] += stats_msg->pbuf_copy_fail;
-	s->stats[NSS_STATS_DTLS_SESSION_EPOCH] = stats_msg->epoch;
-	s->stats[NSS_STATS_DTLS_SESSION_TX_SEQ_HIGH] = stats_msg->tx_seq_high;
-	s->stats[NSS_STATS_DTLS_SESSION_TX_SEQ_LOW] = stats_msg->tx_seq_low;
-	spin_unlock_bh(&nss_dtls_session_debug_stats_lock);
+	s->stats[NSS_DTLS_STATS_SESSION_RX_AUTH_DONE] += stats_msg->rx_auth_done;
+	s->stats[NSS_DTLS_STATS_SESSION_TX_AUTH_DONE] += stats_msg->tx_auth_done;
+	s->stats[NSS_DTLS_STATS_SESSION_RX_CIPHER_DONE] += stats_msg->rx_cipher_done;
+	s->stats[NSS_DTLS_STATS_SESSION_TX_CIPHER_DONE] += stats_msg->tx_cipher_done;
+	s->stats[NSS_DTLS_STATS_SESSION_RX_CBUF_ALLOC_FAIL] += stats_msg->rx_cbuf_alloc_fail;
+	s->stats[NSS_DTLS_STATS_SESSION_TX_CBUF_ALLOC_FAIL] += stats_msg->tx_cbuf_alloc_fail;
+	s->stats[NSS_DTLS_STATS_SESSION_TX_CENQUEUE_FAIL] += stats_msg->tx_cenqueue_fail;
+	s->stats[NSS_DTLS_STATS_SESSION_RX_CENQUEUE_FAIL] += stats_msg->rx_cenqueue_fail;
+	s->stats[NSS_DTLS_STATS_SESSION_TX_DROPPED_HROOM] += stats_msg->tx_dropped_hroom;
+	s->stats[NSS_DTLS_STATS_SESSION_TX_DROPPED_TROOM] += stats_msg->tx_dropped_troom;
+	s->stats[NSS_DTLS_STATS_SESSION_TX_FORWARD_ENQUEUE_FAIL] += stats_msg->tx_forward_enqueue_fail;
+	s->stats[NSS_DTLS_STATS_SESSION_RX_FORWARD_ENQUEUE_FAIL] += stats_msg->rx_forward_enqueue_fail;
+	s->stats[NSS_DTLS_STATS_SESSION_RX_INVALID_VERSION] += stats_msg->rx_invalid_version;
+	s->stats[NSS_DTLS_STATS_SESSION_RX_INVALID_EPOCH] += stats_msg->rx_invalid_epoch;
+	s->stats[NSS_DTLS_STATS_SESSION_RX_MALFORMED] += stats_msg->rx_malformed;
+	s->stats[NSS_DTLS_STATS_SESSION_RX_CIPHER_FAIL] += stats_msg->rx_cipher_fail;
+	s->stats[NSS_DTLS_STATS_SESSION_RX_AUTH_FAIL] += stats_msg->rx_auth_fail;
+	s->stats[NSS_DTLS_STATS_SESSION_RX_CAPWAP_CLASSIFY_FAIL] += stats_msg->rx_capwap_classify_fail;
+	s->stats[NSS_DTLS_STATS_SESSION_RX_SINGLE_REC_DGRAM] += stats_msg->rx_single_rec_dgram;
+	s->stats[NSS_DTLS_STATS_SESSION_RX_MULTI_REC_DGRAM] += stats_msg->rx_multi_rec_dgram;
+	s->stats[NSS_DTLS_STATS_SESSION_RX_REPLAY_FAIL] += stats_msg->rx_replay_fail;
+	s->stats[NSS_DTLS_STATS_SESSION_RX_REPLAY_DUPLICATE] += stats_msg->rx_replay_duplicate;
+	s->stats[NSS_DTLS_STATS_SESSION_RX_REPLAY_OUT_OF_WINDOW] += stats_msg->rx_replay_out_of_window;
+	s->stats[NSS_DTLS_STATS_SESSION_OUTFLOW_QUEUE_FULL] += stats_msg->outflow_queue_full;
+	s->stats[NSS_DTLS_STATS_SESSION_DECAP_QUEUE_FULL] += stats_msg->decap_queue_full;
+	s->stats[NSS_DTLS_STATS_SESSION_PBUF_ALLOC_FAIL] += stats_msg->pbuf_alloc_fail;
+	s->stats[NSS_DTLS_STATS_SESSION_PBUF_COPY_FAIL] += stats_msg->pbuf_copy_fail;
+	s->stats[NSS_DTLS_STATS_SESSION_EPOCH] = stats_msg->epoch;
+	s->stats[NSS_DTLS_STATS_SESSION_TX_SEQ_HIGH] = stats_msg->tx_seq_high;
+	s->stats[NSS_DTLS_STATS_SESSION_TX_SEQ_LOW] = stats_msg->tx_seq_low;
+	spin_unlock_bh(&nss_dtls_session_stats_lock);
 }
 
 /*
- * nss_dtls_session_debug_stats_get()
+ * nss_dtls_session_stats_get()
  *	Get session DTLS statitics.
  */
-void nss_dtls_session_debug_stats_get(struct nss_stats_dtls_session_debug *stats)
+void nss_dtls_session_stats_get(struct nss_dtls_stats_session *stats)
 {
 	int i;
 
@@ -131,15 +131,15 @@
 		return;
 	}
 
-	spin_lock_bh(&nss_dtls_session_debug_stats_lock);
+	spin_lock_bh(&nss_dtls_session_stats_lock);
 	for (i = 0; i < NSS_MAX_DTLS_SESSIONS; i++) {
-		if (nss_dtls_session_debug_stats[i].valid) {
-			memcpy(stats, &nss_dtls_session_debug_stats[i],
-			       sizeof(struct nss_stats_dtls_session_debug));
+		if (session_stats[i].valid) {
+			memcpy(stats, &session_stats[i],
+			       sizeof(struct nss_dtls_stats_session));
 			stats++;
 		}
 	}
-	spin_unlock_bh(&nss_dtls_session_debug_stats_lock);
+	spin_unlock_bh(&nss_dtls_session_stats_lock);
 }
 
 /*
@@ -410,16 +410,16 @@
 
 	BUG_ON(!nss_dtls_verify_if_num(if_num));
 
-	spin_lock_bh(&nss_dtls_session_debug_stats_lock);
+	spin_lock_bh(&nss_dtls_session_stats_lock);
 	for (i = 0; i < NSS_MAX_DTLS_SESSIONS; i++) {
-		if (!nss_dtls_session_debug_stats[i].valid) {
-			nss_dtls_session_debug_stats[i].valid = true;
-			nss_dtls_session_debug_stats[i].if_num = if_num;
-			nss_dtls_session_debug_stats[i].if_index = netdev->ifindex;
+		if (!session_stats[i].valid) {
+			session_stats[i].valid = true;
+			session_stats[i].if_num = if_num;
+			session_stats[i].if_index = netdev->ifindex;
 			break;
 		}
 	}
-	spin_unlock_bh(&nss_dtls_session_debug_stats_lock);
+	spin_unlock_bh(&nss_dtls_session_stats_lock);
 
 	if (i == NSS_MAX_DTLS_SESSIONS) {
 		nss_warning("%p: Cannot find free slot for "
@@ -453,15 +453,15 @@
 
 	BUG_ON(!nss_dtls_verify_if_num(if_num));
 
-	spin_lock_bh(&nss_dtls_session_debug_stats_lock);
+	spin_lock_bh(&nss_dtls_session_stats_lock);
 	for (i = 0; i < NSS_MAX_DTLS_SESSIONS; i++) {
-		if (nss_dtls_session_debug_stats[i].if_num == if_num) {
-			memset(&nss_dtls_session_debug_stats[i], 0,
-			       sizeof(struct nss_stats_dtls_session_debug));
+		if (session_stats[i].if_num == if_num) {
+			memset(&session_stats[i], 0,
+			       sizeof(struct nss_dtls_stats_session));
 			break;
 		}
 	}
-	spin_unlock_bh(&nss_dtls_session_debug_stats_lock);
+	spin_unlock_bh(&nss_dtls_session_stats_lock);
 
 	if (i == NSS_MAX_DTLS_SESSIONS) {
 		nss_warning("%p: Cannot find debug stats for DTLS session %d\n", nss_ctx, if_num);
@@ -520,4 +520,6 @@
 {
 	sema_init(&dtls_pvt.sem, 1);
 	init_completion(&dtls_pvt.complete);
+
+	nss_dtls_stats_dentry_create();
 }
diff --git a/nss_dtls_stats.c b/nss_dtls_stats.c
new file mode 100644
index 0000000..a15e716
--- /dev/null
+++ b/nss_dtls_stats.c
@@ -0,0 +1,150 @@
+/*
+ **************************************************************************
+ * 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_stats.h"
+#include "nss_core.h"
+#include "nss_dtls_stats.h"
+
+/*
+ * nss_dtls_stats_session_str
+ *	DTLS statistics strings for nss session stats
+ */
+static int8_t *nss_dtls_stats_session_str[NSS_DTLS_STATS_SESSION_MAX] = {
+	"RX_PKTS",
+	"TX_PKTS",
+	"RX_DROPPED",
+	"RX_AUTH_DONE",
+	"TX_AUTH_DONE",
+	"RX_CIPHER_DONE",
+	"TX_CIPHER_DONE",
+	"RX_CBUF_ALLOC_FAIL",
+	"TX_CBUF_ALLOC_FAIL",
+	"TX_CENQUEUE_FAIL",
+	"RX_CENQUEUE_FAIL",
+	"TX_DROPPED_HROOM",
+	"TX_DROPPED_TROOM",
+	"TX_FORWARD_ENQUEUE_FAIL",
+	"RX_FORWARD_ENQUEUE_FAIL",
+	"RX_INVALID_VERSION",
+	"RX_INVALID_EPOCH",
+	"RX_MALFORMED",
+	"RX_CIPHER_FAIL",
+	"RX_AUTH_FAIL",
+	"RX_CAPWAP_CLASSIFY_FAIL",
+	"RX_SINGLE_REC_DGRAM",
+	"RX_MULTI_REC_DGRAM",
+	"RX_REPLAY_FAIL",
+	"RX_REPLAY_DUPLICATE",
+	"RX_REPLAY_OUT_OF_WINDOW",
+	"OUTFLOW_QUEUE_FULL",
+	"DECAP_QUEUE_FULL",
+	"PBUF_ALLOC_FAIL",
+	"PBUF_COPY_FAIL",
+	"EPOCH",
+	"TX_SEQ_HIGH",
+	"TX_SEQ_LOW",
+};
+
+/*
+ * nss_dtls_stats_read()
+ * 	Read DTLS session statistics
+ */
+static ssize_t nss_dtls_stats_read(struct file *fp, char __user *ubuf,
+				   size_t sz, loff_t *ppos)
+{
+	uint32_t max_output_lines = 2 + (NSS_MAX_DTLS_SESSIONS
+					* (NSS_DTLS_STATS_SESSION_MAX + 2)) + 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;
+	int id, i;
+	struct nss_dtls_stats_session *dtls_session_stats = NULL;
+
+	char *lbuf = kzalloc(size_al, GFP_KERNEL);
+	if (unlikely(lbuf == NULL)) {
+		nss_warning("Could not allocate memory for local statistics buffer");
+		return 0;
+	}
+
+	dtls_session_stats = kzalloc((sizeof(struct nss_dtls_stats_session)
+				     * NSS_MAX_DTLS_SESSIONS), GFP_KERNEL);
+	if (unlikely(dtls_session_stats == NULL)) {
+		nss_warning("Could not allocate memory for populating DTLS stats");
+		kfree(lbuf);
+		return 0;
+	}
+
+	/*
+	 * Get all stats
+	 */
+	nss_dtls_session_stats_get(dtls_session_stats);
+
+	/*
+	 * Session stats
+	 */
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
+			     "\nDTLS session stats start:\n\n");
+
+	for (id = 0; id < NSS_MAX_DTLS_SESSIONS; id++) {
+		if (!dtls_session_stats[id].valid)
+			break;
+
+		dev = dev_get_by_index(&init_net, dtls_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, dtls_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,
+					     dtls_session_stats[id].if_num);
+		}
+
+		for (i = 0; i < NSS_DTLS_STATS_SESSION_MAX; i++) {
+			size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
+					     "\t%s = %llu\n",
+					     nss_dtls_stats_session_str[i],
+					     dtls_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,
+			     "\nDTLS session stats end\n");
+	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, size_wr);
+
+	kfree(dtls_session_stats);
+	kfree(lbuf);
+	return bytes_read;
+}
+
+/*
+ * nss_dtls_stats_ops
+ */
+NSS_STATS_DECLARE_FILE_OPERATIONS(dtls)
+
+/*
+ * nss_dtls_stats_dentry_create()
+ *	Create DTLS statistics debug entry.
+ */
+void nss_dtls_stats_dentry_create(void)
+{
+	nss_stats_create_dentry("dtls", &nss_dtls_stats_ops);
+}
diff --git a/nss_dtls_stats.h b/nss_dtls_stats.h
index e8da83a..bf6a148 100644
--- a/nss_dtls_stats.h
+++ b/nss_dtls_stats.h
@@ -1,6 +1,6 @@
 /*
  ******************************************************************************
- * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 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.
@@ -14,87 +14,89 @@
  * ****************************************************************************
  */
 
+#ifndef __NSS_DTLS_STATS_H
+#define __NSS_DTLS_STATS_H
+
 /*
  * DTLS session debug statistic counters
  */
-enum nss_stats_dtls_session {
-	NSS_STATS_DTLS_SESSION_RX_PKTS,
+enum nss_dtls_stats_session_types {
+	NSS_DTLS_STATS_SESSION_RX_PKTS,
 			/* Rx packets */
-	NSS_STATS_DTLS_SESSION_TX_PKTS,
+	NSS_DTLS_STATS_SESSION_TX_PKTS,
 			/* Tx packets */
-	NSS_STATS_DTLS_SESSION_RX_QUEUE_0_DROPPED,
-	NSS_STATS_DTLS_SESSION_RX_QUEUE_1_DROPPED,
-	NSS_STATS_DTLS_SESSION_RX_QUEUE_2_DROPPED,
-	NSS_STATS_DTLS_SESSION_RX_QUEUE_3_DROPPED,
-			/* Rx dropped */
-	NSS_STATS_DTLS_SESSION_RX_AUTH_DONE,
+	NSS_DTLS_STATS_SESSION_RX_QUEUE_0_DROPPED,
+	NSS_DTLS_STATS_SESSION_RX_QUEUE_1_DROPPED,
+	NSS_DTLS_STATS_SESSION_RX_QUEUE_2_DROPPED,
+	NSS_DTLS_STATS_SESSION_RX_QUEUE_3_DROPPED,
+	NSS_DTLS_STATS_SESSION_RX_AUTH_DONE,
 			/* Rx successful authentication */
-	NSS_STATS_DTLS_SESSION_TX_AUTH_DONE,
+	NSS_DTLS_STATS_SESSION_TX_AUTH_DONE,
 			/* Tx authentication done */
-	NSS_STATS_DTLS_SESSION_RX_CIPHER_DONE,
+	NSS_DTLS_STATS_SESSION_RX_CIPHER_DONE,
 			/* Rx cipher done */
-	NSS_STATS_DTLS_SESSION_TX_CIPHER_DONE,
+	NSS_DTLS_STATS_SESSION_TX_CIPHER_DONE,
 			/* Tx cipher done */
-	NSS_STATS_DTLS_SESSION_RX_CBUF_ALLOC_FAIL,
+	NSS_DTLS_STATS_SESSION_RX_CBUF_ALLOC_FAIL,
 			/* Rx crypto buffer alloc fail */
-	NSS_STATS_DTLS_SESSION_TX_CBUF_ALLOC_FAIL,
+	NSS_DTLS_STATS_SESSION_TX_CBUF_ALLOC_FAIL,
 			/* Tx crypto buffer alloc fail */
-	NSS_STATS_DTLS_SESSION_TX_CENQUEUE_FAIL,
+	NSS_DTLS_STATS_SESSION_TX_CENQUEUE_FAIL,
 			/* Tx enqueue to crypto fail */
-	NSS_STATS_DTLS_SESSION_RX_CENQUEUE_FAIL,
+	NSS_DTLS_STATS_SESSION_RX_CENQUEUE_FAIL,
 			/* Rx enqueue to crypto fail */
-	NSS_STATS_DTLS_SESSION_TX_DROPPED_HROOM,
+	NSS_DTLS_STATS_SESSION_TX_DROPPED_HROOM,
 			/* Tx drop due to insufficient headroom */
-	NSS_STATS_DTLS_SESSION_TX_DROPPED_TROOM,
+	NSS_DTLS_STATS_SESSION_TX_DROPPED_TROOM,
 			/* Tx drop due to insufficient tailroom */
-	NSS_STATS_DTLS_SESSION_TX_FORWARD_ENQUEUE_FAIL,
+	NSS_DTLS_STATS_SESSION_TX_FORWARD_ENQUEUE_FAIL,
 			/* Enqueue failed to Tx node after encap */
-	NSS_STATS_DTLS_SESSION_RX_FORWARD_ENQUEUE_FAIL,
+	NSS_DTLS_STATS_SESSION_RX_FORWARD_ENQUEUE_FAIL,
 			/* Enqueue failed to Rx node after decap */
-	NSS_STATS_DTLS_SESSION_RX_INVALID_VERSION,
+	NSS_DTLS_STATS_SESSION_RX_INVALID_VERSION,
 			/* Rx invalid DTLS version */
-	NSS_STATS_DTLS_SESSION_RX_INVALID_EPOCH,
+	NSS_DTLS_STATS_SESSION_RX_INVALID_EPOCH,
 			/* Rx invalid DTLS epoch */
-	NSS_STATS_DTLS_SESSION_RX_MALFORMED,
+	NSS_DTLS_STATS_SESSION_RX_MALFORMED,
 			/* Rx malformed DTLS record */
-	NSS_STATS_DTLS_SESSION_RX_CIPHER_FAIL,
+	NSS_DTLS_STATS_SESSION_RX_CIPHER_FAIL,
 			/* Rx cipher fail */
-	NSS_STATS_DTLS_SESSION_RX_AUTH_FAIL,
+	NSS_DTLS_STATS_SESSION_RX_AUTH_FAIL,
 			/* Rx authentication fail */
-	NSS_STATS_DTLS_SESSION_RX_CAPWAP_CLASSIFY_FAIL,
+	NSS_DTLS_STATS_SESSION_RX_CAPWAP_CLASSIFY_FAIL,
 			/* Rx CAPWAP classification fail */
-	NSS_STATS_DTLS_SESSION_RX_SINGLE_REC_DGRAM,
+	NSS_DTLS_STATS_SESSION_RX_SINGLE_REC_DGRAM,
 			/* Rx single record datagrams processed */
-	NSS_STATS_DTLS_SESSION_RX_MULTI_REC_DGRAM,
+	NSS_DTLS_STATS_SESSION_RX_MULTI_REC_DGRAM,
 			/* Rx multi record datagrams processed */
-	NSS_STATS_DTLS_SESSION_RX_REPLAY_FAIL,
+	NSS_DTLS_STATS_SESSION_RX_REPLAY_FAIL,
 			/* Rx anti-replay failures */
-	NSS_STATS_DTLS_SESSION_RX_REPLAY_DUPLICATE,
+	NSS_DTLS_STATS_SESSION_RX_REPLAY_DUPLICATE,
 			/* Rx anti-replay fail due to duplicate record */
-	NSS_STATS_DTLS_SESSION_RX_REPLAY_OUT_OF_WINDOW,
+	NSS_DTLS_STATS_SESSION_RX_REPLAY_OUT_OF_WINDOW,
 			/* Rx anti-replay fail due to out of window record */
-	NSS_STATS_DTLS_SESSION_OUTFLOW_QUEUE_FULL,
+	NSS_DTLS_STATS_SESSION_OUTFLOW_QUEUE_FULL,
 			/* Tx drop due to encap queue full */
-	NSS_STATS_DTLS_SESSION_DECAP_QUEUE_FULL,
+	NSS_DTLS_STATS_SESSION_DECAP_QUEUE_FULL,
 			/* Rx drop due to decap queue full */
-	NSS_STATS_DTLS_SESSION_PBUF_ALLOC_FAIL,
+	NSS_DTLS_STATS_SESSION_PBUF_ALLOC_FAIL,
 			/* Drops due to buffer allocation failure */
-	NSS_STATS_DTLS_SESSION_PBUF_COPY_FAIL,
+	NSS_DTLS_STATS_SESSION_PBUF_COPY_FAIL,
 			/* Drops due to buffer copy failure */
-	NSS_STATS_DTLS_SESSION_EPOCH,
+	NSS_DTLS_STATS_SESSION_EPOCH,
 			/* Current Epoch */
-	NSS_STATS_DTLS_SESSION_TX_SEQ_HIGH,
+	NSS_DTLS_STATS_SESSION_TX_SEQ_HIGH,
 			/* Upper 16-bits of current sequence number */
-	NSS_STATS_DTLS_SESSION_TX_SEQ_LOW,
+	NSS_DTLS_STATS_SESSION_TX_SEQ_LOW,
 			/* Lower 32-bits of current sequence number */
-	NSS_STATS_DTLS_SESSION_MAX,
+	NSS_DTLS_STATS_SESSION_MAX,
 };
 
 /*
- * DTLS session debug statistics
+ * DTLS session statistics
  */
-struct nss_stats_dtls_session_debug {
-	uint64_t stats[NSS_STATS_DTLS_SESSION_MAX];
+struct nss_dtls_stats_session {
+	uint64_t stats[NSS_DTLS_STATS_SESSION_MAX];
 	int32_t if_index;
 	uint32_t if_num; /* nss interface number */
 	bool valid;
@@ -103,4 +105,11 @@
 /*
  * Stats APIs provided by nss_dtls.c
  */
-extern void nss_dtls_session_debug_stats_get(struct nss_stats_dtls_session_debug *s);
+extern void nss_dtls_session_stats_get(struct nss_dtls_stats_session *s);
+
+/*
+ * DTLS statistics APIs
+ */
+extern void nss_dtls_stats_dentry_create(void);
+
+#endif /* __NSS_DTLS_STATS_H */
diff --git a/nss_edma.c b/nss_edma.c
index bfcca62..0abb48e 100644
--- a/nss_edma.c
+++ b/nss_edma.c
@@ -20,6 +20,7 @@
  */
 
 #include "nss_tx_rx_common.h"
+#include "nss_edma_stats.h"
 
 /*
  **********************************
@@ -28,110 +29,6 @@
  */
 
 /*
- * nss_edma_metadata_port_stats_sync()
- *	Handle the syncing of EDMA port statistics.
- */
-static void nss_edma_metadata_port_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_edma_port_stats_sync *nepss)
-{
-	int i;
-	struct nss_top_instance *nss_top = nss_ctx->nss_top;
-
-	spin_lock_bh(&nss_top->stats_lock);
-
-	/*
-	 * edma port stats
-	 * We process a subset of port stats since msg payload is not enough to hold all ports at once.
-	 */
-	for (i = nepss->start_port; i < nepss->end_port; i++) {
-		int k;
-
-		nss_top->stats_edma.port[i].port_stats[NSS_STATS_NODE_RX_PKTS] += nepss->port_stats[i].node_stats.rx_packets;
-		nss_top->stats_edma.port[i].port_stats[NSS_STATS_NODE_RX_BYTES] += nepss->port_stats[i].node_stats.rx_bytes;
-		nss_top->stats_edma.port[i].port_stats[NSS_STATS_NODE_TX_PKTS] += nepss->port_stats[i].node_stats.tx_packets;
-		nss_top->stats_edma.port[i].port_stats[NSS_STATS_NODE_TX_BYTES] += nepss->port_stats[i].node_stats.tx_bytes;
-
-		for (k = 0; k < NSS_MAX_NUM_PRI; k++) {
-			nss_top->stats_edma.port[i].port_stats[NSS_STATS_NODE_RX_QUEUE_0_DROPPED + k] += nepss->port_stats[i].node_stats.rx_dropped[k];
-		}
-
-		nss_top->stats_edma.port[i].port_type = nepss->port_stats[i].port_type;
-		nss_top->stats_edma.port[i].port_ring_map[NSS_EDMA_PORT_RX_RING] = nepss->port_stats[i].edma_rx_ring;
-		nss_top->stats_edma.port[i].port_ring_map[NSS_EDMA_PORT_TX_RING] = nepss->port_stats[i].edma_tx_ring;
-	}
-
-	spin_unlock_bh(&nss_top->stats_lock);
-}
-
-/*
- * nss_edma_metadata_ring_stats_sync()
- *	Handle the syncing of EDMA ring statistics.
- */
-static void nss_edma_metadata_ring_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_edma_ring_stats_sync *nerss)
-{
-	int i;
-	struct nss_top_instance *nss_top = nss_ctx->nss_top;
-
-	spin_lock_bh(&nss_top->stats_lock);
-
-	/*
-	 * edma tx ring stats
-	 */
-	for (i = 0; i < NSS_EDMA_NUM_TX_RING_MAX; i++) {
-		nss_top->stats_edma.tx_stats[i][NSS_STATS_EDMA_TX_ERR] += nerss->tx_ring[i].tx_err;
-		nss_top->stats_edma.tx_stats[i][NSS_STATS_EDMA_TX_DROPPED] += nerss->tx_ring[i].tx_dropped;
-		nss_top->stats_edma.tx_stats[i][NSS_STATS_EDMA_TX_DESC] += nerss->tx_ring[i].desc_cnt;
-	}
-
-	/*
-	 * edma rx ring stats
-	 */
-	for (i = 0; i < NSS_EDMA_NUM_RX_RING_MAX; i++) {
-		nss_top->stats_edma.rx_stats[i][NSS_STATS_EDMA_RX_CSUM_ERR] += nerss->rx_ring[i].rx_csum_err;
-		nss_top->stats_edma.rx_stats[i][NSS_STATS_EDMA_RX_DESC] += nerss->rx_ring[i].desc_cnt;
-		nss_top->stats_edma.rx_stats[i][NSS_STATS_EDMA_RX_QOS_ERR] += nerss->rx_ring[i].qos_err;
-	}
-
-	/*
-	 * edma tx cmpl ring stats
-	 */
-	for (i = 0; i < NSS_EDMA_NUM_TXCMPL_RING_MAX; i++) {
-		nss_top->stats_edma.txcmpl_stats[i][NSS_STATS_EDMA_TXCMPL_DESC] += nerss->txcmpl_ring[i].desc_cnt;
-	}
-
-	/*
-	 * edma rx fill ring stats
-	 */
-	for (i = 0; i < NSS_EDMA_NUM_RXFILL_RING_MAX; i++) {
-		nss_top->stats_edma.rxfill_stats[i][NSS_STATS_EDMA_RXFILL_DESC] += nerss->rxfill_ring[i].desc_cnt;
-	}
-
-	spin_unlock_bh(&nss_top->stats_lock);
-}
-
-/*
- * nss_edma_metadata_err_stats_sync()
- *	Handle the syncing of EDMA error statistics.
- */
-static void nss_edma_metadata_err_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_edma_err_stats_sync *nerss)
-{
-
-	struct nss_top_instance *nss_top = nss_ctx->nss_top;
-
-	spin_lock_bh(&nss_top->stats_lock);
-	nss_top->stats_edma.misc_err[NSS_EDMA_AXI_RD_ERR] += nerss->msg_err_stats.axi_rd_err;
-	nss_top->stats_edma.misc_err[NSS_EDMA_AXI_WR_ERR] += nerss->msg_err_stats.axi_wr_err;
-	nss_top->stats_edma.misc_err[NSS_EDMA_RX_DESC_FIFO_FULL_ERR] += nerss->msg_err_stats.rx_desc_fifo_full_err;
-	nss_top->stats_edma.misc_err[NSS_EDMA_RX_BUF_SIZE_ERR] += nerss->msg_err_stats.rx_buf_size_err;
-	nss_top->stats_edma.misc_err[NSS_EDMA_TX_SRAM_FULL_ERR] += nerss->msg_err_stats.tx_sram_full_err;
-	nss_top->stats_edma.misc_err[NSS_EDMA_TX_CMPL_BUF_FULL_ERR] += nerss->msg_err_stats.tx_cmpl_buf_full_err;
-	nss_top->stats_edma.misc_err[NSS_EDMA_PKT_LEN_LA64K_ERR] += nerss->msg_err_stats.pkt_len_la64k_err;
-	nss_top->stats_edma.misc_err[NSS_EDMA_PKT_LEN_LE33_ERR] += nerss->msg_err_stats.pkt_len_le33_err;
-	nss_top->stats_edma.misc_err[NSS_EDMA_DATA_LEN_ERR] += nerss->msg_err_stats.data_len_err;
-	nss_top->stats_edma.misc_err[NSS_EDMA_ALLOC_FAIL_CNT] += nerss->msg_err_stats.alloc_fail_cnt;
-	spin_unlock_bh(&nss_top->stats_lock);
-}
-
-/*
  * nss_edma_interface_handler()
  *	Handle NSS -> HLOS messages for EDMA node
  */
@@ -233,4 +130,6 @@
 	struct nss_ctx_instance *nss_ctx = nss_edma_get_context();
 
 	nss_core_register_handler(nss_ctx, NSS_EDMA_INTERFACE, nss_edma_interface_handler, NULL);
+
+	nss_edma_stats_dentry_create();
 }
diff --git a/nss_edma_stats.c b/nss_edma_stats.c
new file mode 100644
index 0000000..23cca5b
--- /dev/null
+++ b/nss_edma_stats.c
@@ -0,0 +1,882 @@
+/*
+ **************************************************************************
+ * 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.
+ **************************************************************************
+ */
+
+/*
+ * nss_edma_stats.c
+ *	NSS EDMA statistics APIs
+ */
+
+#include "nss_stats.h"
+#include "nss_tx_rx_common.h"
+#include "nss_edma_stats.h"
+
+struct nss_edma_stats edma_stats;
+
+/*
+ * nss_edma_stats_str_node
+ */
+static int8_t *nss_edma_stats_str_node[NSS_STATS_NODE_MAX] = {
+	"rx_packets",
+	"rx_bytes",
+	"tx_packets",
+	"tx_bytes",
+	"rx_queue_0_dropped",
+	"rx_queue_1_dropped",
+	"rx_queue_2_dropped",
+	"rx_queue_3_dropped",
+};
+
+/*
+ * nss_edma_stats_str_tx
+ */
+static int8_t *nss_edma_stats_str_tx[NSS_EDMA_STATS_TX_MAX] = {
+	"tx_err",
+	"tx_dropped",
+	"desc_cnt"
+};
+
+/*
+ * nss_edma_stats_str_rx
+ */
+static int8_t *nss_edma_stats_str_rx[NSS_EDMA_STATS_RX_MAX] = {
+	"rx_csum_err",
+	"desc_cnt",
+	"qos_err"
+};
+
+/*
+ * nss_edma_stats_str_txcmpl
+ */
+static int8_t *nss_edma_stats_str_txcmpl[NSS_EDMA_STATS_TXCMPL_MAX] = {
+	"desc_cnt"
+};
+
+/*
+ * nss_edma_stats_str_rxfill
+ */
+static int8_t *nss_edma_stats_str_rxfill[NSS_EDMA_STATS_RXFILL_MAX] = {
+	"desc_cnt"
+};
+
+/*
+ * nss_edma_stats_str_port_type
+ */
+static int8_t *nss_edma_stats_str_port_type[NSS_EDMA_PORT_TYPE_MAX] = {
+	"physical_port",
+	"virtual_port"
+};
+
+/*
+ * nss_edma_stats_str_port_ring_map
+ */
+static int8_t *nss_edma_stats_str_port_ring_map[NSS_EDMA_PORT_RING_MAP_MAX] = {
+	"rx_ring",
+	"tx_ring"
+};
+
+/*
+ * nss_edma_stats_str_err_map
+ */
+static int8_t *nss_edma_stats_str_err_map[NSS_EDMA_ERR_STATS_MAX] = {
+	"axi_rd_err",
+	"axi_wr_err",
+	"rx_desc_fifo_full_err",
+	"rx_buf_size_err",
+	"tx_sram_full_err",
+	"tx_cmpl_buf_full_err",
+	"pkt_len_la64k_err",
+	"pkt_len_le33_err",
+	"data_len_err",
+	"alloc_fail_cnt"
+};
+
+/*
+ **********************************
+ EDMA statistics APIs
+ **********************************
+ */
+
+/*
+ * nss_edma_port_stats_read()
+ *	Read EDMA port statistics
+ */
+static ssize_t nss_edma_port_stats_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
+{
+	int32_t i;
+
+	/*
+	 * max output lines = #stats + start tag line + end tag line + three blank lines
+	 */
+	uint32_t max_output_lines = (NSS_STATS_NODE_MAX + 2) + 3;
+	size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
+	size_t size_wr = 0;
+	ssize_t bytes_read = 0;
+	uint64_t *stats_shadow;
+	struct nss_stats_data *data = fp->private_data;
+
+	char *lbuf = kzalloc(size_al, GFP_KERNEL);
+	if (unlikely(lbuf == NULL)) {
+		nss_warning("Could not allocate memory for local statistics buffer");
+		return 0;
+	}
+
+	/*
+	 * Note: The assumption here is that we do not have more than 64 stats
+	 */
+	stats_shadow = kzalloc(64 * 8, GFP_KERNEL);
+	if (unlikely(stats_shadow == NULL)) {
+		nss_warning("Could not allocate memory for local shadow buffer");
+		kfree(lbuf);
+		return 0;
+	}
+
+	size_wr = scnprintf(lbuf, size_al, "edma stats start:\n\n");
+
+	/*
+	 * Common node stats
+	 */
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "edma port %d stats:\n\n", data->edma_id);
+
+	spin_lock_bh(&nss_top_main.stats_lock);
+	for (i = 0; (i < NSS_STATS_NODE_MAX); i++) {
+		stats_shadow[i] = edma_stats.port[data->edma_id].port_stats[i];
+	}
+
+	spin_unlock_bh(&nss_top_main.stats_lock);
+
+	for (i = 0; (i < NSS_STATS_NODE_MAX); i++) {
+		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
+					"%s = %llu\n", nss_edma_stats_str_node[i], stats_shadow[i]);
+	}
+
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nedma stats end\n\n");
+	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
+	kfree(lbuf);
+	kfree(stats_shadow);
+
+	return bytes_read;
+}
+
+/*
+ * nss_edma_port_type_stats_read()
+ *	Read EDMA port type
+ */
+static ssize_t nss_edma_port_type_stats_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
+{
+	/*
+	 * max output lines = #stats + start tag line + end tag line + three blank lines
+	 */
+	uint32_t max_output_lines = (1 + 2) + 3;
+	size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
+	size_t size_wr = 0;
+	ssize_t bytes_read = 0;
+	uint64_t port_type;
+	struct nss_stats_data *data = fp->private_data;
+
+	char *lbuf = kzalloc(size_al, GFP_KERNEL);
+	if (unlikely(lbuf == NULL)) {
+		nss_warning("Could not allocate memory for local statistics buffer");
+		return 0;
+	}
+
+	size_wr = scnprintf(lbuf, size_al, "edma port type start:\n\n");
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "edma port %d type:\n\n", data->edma_id);
+
+	/*
+	 * Port type
+	 */
+	spin_lock_bh(&nss_top_main.stats_lock);
+	port_type = edma_stats.port[data->edma_id].port_type;
+	spin_unlock_bh(&nss_top_main.stats_lock);
+
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
+					"port_type = %s\n", nss_edma_stats_str_port_type[port_type]);
+
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nedma stats end\n");
+	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
+	kfree(lbuf);
+
+	return bytes_read;
+}
+
+/*
+ * nss_edma_port_ring_map_stats_read()
+ *	Read EDMA port ring map
+ */
+static ssize_t nss_edma_port_ring_map_stats_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
+{
+	int32_t i;
+
+	/*
+	 * max output lines = #stats + start tag line + end tag line + three blank lines
+	 */
+	uint32_t max_output_lines = (4 + 2) + 3;
+	size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
+	size_t size_wr = 0;
+	ssize_t bytes_read = 0;
+	uint64_t *stats_shadow;
+	struct nss_stats_data *data = fp->private_data;
+
+	char *lbuf = kzalloc(size_al, GFP_KERNEL);
+	if (unlikely(lbuf == NULL)) {
+		nss_warning("Could not allocate memory for local statistics buffer");
+		return 0;
+	}
+
+	/*
+	 * Note: The assumption here is that we do not have more than 64 stats
+	 */
+	stats_shadow = kzalloc(64 * 8, GFP_KERNEL);
+	if (unlikely(stats_shadow == NULL)) {
+		nss_warning("Could not allocate memory for local shadow buffer");
+		kfree(lbuf);
+		return 0;
+	}
+
+	size_wr = scnprintf(lbuf, size_al, "edma port ring map start:\n\n");
+
+	/*
+	 * Port ring map
+	 */
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "edma port %d ring map:\n\n", data->edma_id);
+	spin_lock_bh(&nss_top_main.stats_lock);
+	for (i = 0; i < NSS_EDMA_PORT_RING_MAP_MAX; i++) {
+		stats_shadow[i] = edma_stats.port[data->edma_id].port_ring_map[i];
+	}
+
+	spin_unlock_bh(&nss_top_main.stats_lock);
+
+	for (i = 0; i < NSS_EDMA_PORT_RING_MAP_MAX; i++) {
+		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
+					"%s = %llu\n", nss_edma_stats_str_port_ring_map[i], stats_shadow[i]);
+	}
+
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nedma stats end\n\n");
+	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
+	kfree(lbuf);
+	kfree(stats_shadow);
+
+	return bytes_read;
+}
+
+/*
+ * nss_edma_txring_stats_read()
+ *	Read EDMA Tx ring stats
+ */
+static ssize_t nss_edma_txring_stats_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
+{
+	int32_t i;
+
+	/*
+	 * max output lines = #stats + start tag line + end tag line + three blank lines
+	 */
+	uint32_t max_output_lines = (NSS_EDMA_STATS_TX_MAX + 2) + 3;
+	size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
+	size_t size_wr = 0;
+	ssize_t bytes_read = 0;
+	uint64_t *stats_shadow;
+	struct nss_stats_data *data = fp->private_data;
+
+	char *lbuf = kzalloc(size_al, GFP_KERNEL);
+	if (unlikely(lbuf == NULL)) {
+		nss_warning("Could not allocate memory for local statistics buffer");
+		return 0;
+	}
+
+	/*
+	 * Note: The assumption here is that we do not have more than 64 stats
+	 */
+	stats_shadow = kzalloc(64 * 8, GFP_KERNEL);
+	if (unlikely(stats_shadow == NULL)) {
+		nss_warning("Could not allocate memory for local shadow buffer");
+		kfree(lbuf);
+		return 0;
+	}
+
+	size_wr = scnprintf(lbuf, size_al, "edma Tx ring stats start:\n\n");
+
+	/*
+	 * Tx ring stats
+	 */
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "Tx ring %d stats:\n\n", data->edma_id);
+	spin_lock_bh(&nss_top_main.stats_lock);
+	for (i = 0; i < NSS_EDMA_STATS_TX_MAX; i++) {
+		stats_shadow[i] = edma_stats.tx_stats[data->edma_id][i];
+	}
+
+	spin_unlock_bh(&nss_top_main.stats_lock);
+
+	for (i = 0; i < NSS_EDMA_STATS_TX_MAX; i++) {
+		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
+					"%s = %llu\n", nss_edma_stats_str_tx[i], stats_shadow[i]);
+	}
+
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nedma Tx ring stats end\n\n");
+	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
+	kfree(lbuf);
+	kfree(stats_shadow);
+
+	return bytes_read;
+}
+
+/*
+ * nss_edma_rxring_stats_read()
+ *	Read EDMA rxring stats
+ */
+static ssize_t nss_edma_rxring_stats_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
+{
+	int32_t i;
+
+	/*
+	 * max output lines = #stats + start tag line + end tag line + three blank lines
+	 */
+	uint32_t max_output_lines = (NSS_EDMA_STATS_RX_MAX + 2) + 3;
+	size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
+	size_t size_wr = 0;
+	ssize_t bytes_read = 0;
+	uint64_t *stats_shadow;
+	struct nss_stats_data *data = fp->private_data;
+
+	char *lbuf = kzalloc(size_al, GFP_KERNEL);
+	if (unlikely(lbuf == NULL)) {
+		nss_warning("Could not allocate memory for local statistics buffer");
+		return 0;
+	}
+
+	/*
+	 * Note: The assumption here is that we do not have more than 64 stats
+	 */
+	stats_shadow = kzalloc(64 * 8, GFP_KERNEL);
+	if (unlikely(stats_shadow == NULL)) {
+		nss_warning("Could not allocate memory for local shadow buffer");
+		kfree(lbuf);
+		return 0;
+	}
+
+	size_wr = scnprintf(lbuf, size_al, "edma Rx ring stats start:\n\n");
+
+	/*
+	 * RX ring stats
+	 */
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "Rx ring %d stats:\n\n", data->edma_id);
+	spin_lock_bh(&nss_top_main.stats_lock);
+	for (i = 0; i < NSS_EDMA_STATS_RX_MAX; i++) {
+		stats_shadow[i] = edma_stats.rx_stats[data->edma_id][i];
+	}
+
+	spin_unlock_bh(&nss_top_main.stats_lock);
+
+	for (i = 0; i < NSS_EDMA_STATS_RX_MAX; i++) {
+		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
+					"%s = %llu\n", nss_edma_stats_str_rx[i], stats_shadow[i]);
+	}
+
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nedma Rx ring stats end\n\n");
+	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
+	kfree(lbuf);
+	kfree(stats_shadow);
+
+	return bytes_read;
+}
+
+/*
+ * nss_edma_txcmplring_stats_read()
+ *	Read EDMA txcmplring stats
+ */
+static ssize_t nss_edma_txcmplring_stats_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
+{
+	int32_t i;
+
+	/*
+	 * max output lines = #stats + start tag line + end tag line + three blank lines
+	 */
+	uint32_t max_output_lines = (NSS_EDMA_STATS_TXCMPL_MAX + 2) + 3;
+	size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
+	size_t size_wr = 0;
+	ssize_t bytes_read = 0;
+	uint64_t *stats_shadow;
+	struct nss_stats_data *data = fp->private_data;
+
+	char *lbuf = kzalloc(size_al, GFP_KERNEL);
+	if (unlikely(lbuf == NULL)) {
+		nss_warning("Could not allocate memory for local statistics buffer");
+		return 0;
+	}
+
+	/*
+	 * Note: The assumption here is that we do not have more than 64 stats
+	 */
+	stats_shadow = kzalloc(64 * 8, GFP_KERNEL);
+	if (unlikely(stats_shadow == NULL)) {
+		nss_warning("Could not allocate memory for local shadow buffer");
+		kfree(lbuf);
+		return 0;
+	}
+
+	size_wr = scnprintf(lbuf, size_al, "edma Tx cmpl ring stats start:\n\n");
+
+	/*
+	 * Tx cmpl ring stats
+	 */
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "Tx cmpl ring %d stats:\n\n", data->edma_id);
+	spin_lock_bh(&nss_top_main.stats_lock);
+	for (i = 0; i < NSS_EDMA_STATS_TXCMPL_MAX; i++) {
+		stats_shadow[i] = edma_stats.txcmpl_stats[data->edma_id][i];
+	}
+
+	spin_unlock_bh(&nss_top_main.stats_lock);
+
+	for (i = 0; i < NSS_EDMA_STATS_TXCMPL_MAX; i++) {
+		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
+					"%s = %llu\n", nss_edma_stats_str_txcmpl[i], stats_shadow[i]);
+	}
+
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nedma Tx cmpl ring stats end\n\n");
+	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
+	kfree(lbuf);
+	kfree(stats_shadow);
+
+	return bytes_read;
+}
+
+/*
+ * nss_edma_rxfillring_stats_read()
+ *	Read EDMA rxfillring stats
+ */
+static ssize_t nss_edma_rxfillring_stats_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
+{
+	int32_t i;
+
+	/*
+	 * max output lines = #stats + start tag line + end tag line + three blank lines
+	 */
+	uint32_t max_output_lines = (NSS_EDMA_STATS_RXFILL_MAX + 2) + 3;
+	size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
+	size_t size_wr = 0;
+	ssize_t bytes_read = 0;
+	uint64_t *stats_shadow;
+	struct nss_stats_data *data = fp->private_data;
+
+	char *lbuf = kzalloc(size_al, GFP_KERNEL);
+	if (unlikely(lbuf == NULL)) {
+		nss_warning("Could not allocate memory for local statistics buffer");
+		return 0;
+	}
+
+	/*
+	 * Note: The assumption here is that we do not have more than 64 stats
+	 */
+	stats_shadow = kzalloc(64 * 8, GFP_KERNEL);
+	if (unlikely(stats_shadow == NULL)) {
+		nss_warning("Could not allocate memory for local shadow buffer");
+		kfree(lbuf);
+		return 0;
+	}
+
+	size_wr = scnprintf(lbuf, size_al, "edma Rx fill ring stats start:\n\n");
+
+	/*
+	 * Rx fill ring stats
+	 */
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "Rx fill ring %d stats:\n\n", data->edma_id);
+	spin_lock_bh(&nss_top_main.stats_lock);
+	for (i = 0; i < NSS_EDMA_STATS_RXFILL_MAX; i++) {
+		stats_shadow[i] = edma_stats.rxfill_stats[data->edma_id][i];
+	}
+
+	spin_unlock_bh(&nss_top_main.stats_lock);
+
+	for (i = 0; i < NSS_EDMA_STATS_RXFILL_MAX; i++) {
+		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
+					"%s = %llu\n", nss_edma_stats_str_rxfill[i], stats_shadow[i]);
+	}
+
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nedma Rx fill ring stats end\n\n");
+	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
+	kfree(lbuf);
+	kfree(stats_shadow);
+
+	return bytes_read;
+}
+
+/*
+ * nss_edma_err_stats_read()
+ *      Read EDMA err stats
+ */
+static ssize_t nss_edma_err_stats_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
+{
+	int32_t i;
+
+	/*
+	 * max output lines = #stats + start tag line + end tag line + three blank lines
+	 */
+	uint32_t max_output_lines = (NSS_EDMA_ERR_STATS_MAX + 2) + 3;
+	size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
+	size_t size_wr = 0;
+	ssize_t bytes_read = 0;
+	uint64_t *stats_shadow;
+
+	char *lbuf = kzalloc(size_al, GFP_KERNEL);
+	if (unlikely(lbuf == NULL)) {
+		nss_warning("Could not allocate memory for local statistics buffer");
+		return 0;
+	}
+
+	/*
+	 * Note: The assumption here is that we do not have more than 64 stats
+	 */
+	stats_shadow = kzalloc(64 * 8, GFP_KERNEL);
+	if (unlikely(stats_shadow == NULL)) {
+		nss_warning("Could not allocate memory for local shadow buffer");
+		kfree(lbuf);
+		return 0;
+	}
+
+	size_wr = scnprintf(lbuf, size_al, "edma error stats start:\n\n");
+
+	/*
+	 * Common node stats
+	 */
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "edma error stats:\n\n");
+	spin_lock_bh(&nss_top_main.stats_lock);
+
+	for (i = 0; (i < NSS_EDMA_ERR_STATS_MAX); i++)
+		stats_shadow[i] = edma_stats.misc_err[i];
+
+	spin_unlock_bh(&nss_top_main.stats_lock);
+
+	for (i = 0; (i < NSS_EDMA_ERR_STATS_MAX); i++) {
+		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
+					"%s = %llu\n", nss_edma_stats_str_err_map[i], stats_shadow[i]);
+	}
+
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nedma error stats end\n\n");
+	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
+	kfree(lbuf);
+	kfree(stats_shadow);
+
+	return bytes_read;
+}
+
+/*
+ * edma_port_stats_ops
+ */
+NSS_STATS_DECLARE_FILE_OPERATIONS(edma_port)
+
+/*
+ * edma_port_type_stats_ops
+ */
+NSS_STATS_DECLARE_FILE_OPERATIONS(edma_port_type)
+
+/*
+ * edma_port_ring_map_stats_ops
+ */
+NSS_STATS_DECLARE_FILE_OPERATIONS(edma_port_ring_map)
+
+/*
+ * edma_txring_stats_ops
+ */
+NSS_STATS_DECLARE_FILE_OPERATIONS(edma_txring)
+
+/*
+ * edma_rxring_stats_ops
+ */
+NSS_STATS_DECLARE_FILE_OPERATIONS(edma_rxring)
+
+/*
+ * edma_txcmplring_stats_ops
+ */
+NSS_STATS_DECLARE_FILE_OPERATIONS(edma_txcmplring)
+
+/*
+ * edma_rxfillring_stats_ops
+ */
+NSS_STATS_DECLARE_FILE_OPERATIONS(edma_rxfillring)
+
+/*
+ * edma_err_stats_ops
+ */
+NSS_STATS_DECLARE_FILE_OPERATIONS(edma_err)
+
+/*
+ * nss_edma_stats_dentry_create()
+ *	Create edma statistics debug entry.
+ */
+void nss_edma_stats_dentry_create(void)
+{
+	int i;
+	struct dentry *edma_d = NULL;
+	struct dentry *edma_port_dir_d = NULL;
+	struct dentry *edma_port_d = NULL;
+	struct dentry *edma_port_type_d = NULL;
+	struct dentry *edma_port_stats_d = NULL;
+	struct dentry *edma_port_ring_map_d = NULL;
+	struct dentry *edma_rings_dir_d = NULL;
+	struct dentry *edma_tx_dir_d = NULL;
+	struct dentry *edma_tx_d = NULL;
+	struct dentry *edma_rx_dir_d = NULL;
+	struct dentry *edma_rx_d = NULL;
+	struct dentry *edma_txcmpl_dir_d = NULL;
+	struct dentry *edma_txcmpl_d = NULL;
+	struct dentry *edma_rxfill_dir_d = NULL;
+	struct dentry *edma_rxfill_d = NULL;
+	struct dentry *edma_err_stats_d = NULL;
+	char file_name[10];
+
+	edma_d = debugfs_create_dir("edma", nss_top_main.stats_dentry);
+	if (unlikely(edma_d == NULL)) {
+		nss_warning("Failed to create qca-nss-drv/stats/edma directory");
+		return;
+	}
+
+	/*
+	 * edma port stats
+	 */
+	edma_port_dir_d = debugfs_create_dir("ports", edma_d);
+	if (unlikely(edma_port_dir_d == NULL)) {
+		nss_warning("Failed to create qca-nss-drv/stats/edma/ports directory");
+		return;
+	}
+
+	for (i = 0; i < NSS_EDMA_NUM_PORTS_MAX; i++) {
+		memset(file_name, 0, sizeof(file_name));
+		snprintf(file_name, sizeof(file_name), "%d", i);
+
+		edma_port_d = debugfs_create_dir(file_name, edma_port_dir_d);
+		if (unlikely(edma_port_d == NULL)) {
+			nss_warning("Failed to create qca-nss-drv/stats/edma/ports/%d directory", i);
+			return;
+		}
+
+		edma_port_stats_d = debugfs_create_file("stats", 0400, edma_port_d, (void *)(nss_ptr_t)i, &nss_edma_port_stats_ops);
+		if (unlikely(edma_port_stats_d == NULL)) {
+			nss_warning("Failed to create qca-nss-drv/stats/edma/ports/%d/stats file", i);
+			return;
+		}
+
+		edma_port_type_d = debugfs_create_file("type", 0400, edma_port_d, (void *)(nss_ptr_t)i, &nss_edma_port_type_stats_ops);
+		if (unlikely(edma_port_type_d == NULL)) {
+			nss_warning("Failed to create qca-nss-drv/stats/edma/ports/%d/type file", i);
+			return;
+		}
+
+		edma_port_ring_map_d = debugfs_create_file("ring_map", 0400, edma_port_d, (void *)(nss_ptr_t)i, &nss_edma_port_ring_map_stats_ops);
+		if (unlikely(edma_port_ring_map_d == NULL)) {
+			nss_warning("Failed to create qca-nss-drv/stats/edma/ports/%d/ring_map file", i);
+			return;
+		}
+	}
+
+	/*
+	 *  edma error stats
+	 */
+	edma_err_stats_d = NULL;
+	edma_err_stats_d = debugfs_create_file("err_stats", 0400, edma_d, &nss_top_main, &nss_edma_err_stats_ops);
+	if (unlikely(edma_port_stats_d == NULL)) {
+		nss_warning("Failed to create qca-nss-drv/stats/edma/%d/err_stats file", 0);
+		return;
+	}
+
+	/*
+	 * edma ring stats
+	 */
+	edma_rings_dir_d = debugfs_create_dir("rings", edma_d);
+	if (unlikely(edma_rings_dir_d == NULL)) {
+		nss_warning("Failed to create qca-nss-drv/stats/edma/rings directory");
+		return;
+	}
+
+	/*
+	 * edma tx ring stats
+	 */
+	edma_tx_dir_d = debugfs_create_dir("tx", edma_rings_dir_d);
+	if (unlikely(edma_tx_dir_d == NULL)) {
+		nss_warning("Failed to create qca-nss-drv/stats/edma/rings/tx directory");
+		return;
+	}
+
+	for (i = 0; i < NSS_EDMA_NUM_TX_RING_MAX; i++) {
+		memset(file_name, 0, sizeof(file_name));
+		scnprintf(file_name, sizeof(file_name), "%d", i);
+		edma_tx_d = debugfs_create_file(file_name, 0400, edma_tx_dir_d, (void *)(nss_ptr_t)i, &nss_edma_txring_stats_ops);
+		if (unlikely(edma_tx_d == NULL)) {
+			nss_warning("Failed to create qca-nss-drv/stats/edma/rings/tx/%d file", i);
+			return;
+		}
+	}
+
+	/*
+	 * edma rx ring stats
+	 */
+	edma_rx_dir_d = debugfs_create_dir("rx", edma_rings_dir_d);
+	if (unlikely(edma_rx_dir_d == NULL)) {
+		nss_warning("Failed to create qca-nss-drv/stats/edma/rings/rx directory");
+		return;
+	}
+
+	for (i = 0; i < NSS_EDMA_NUM_RX_RING_MAX; i++) {
+		memset(file_name, 0, sizeof(file_name));
+		scnprintf(file_name, sizeof(file_name), "%d", i);
+		edma_rx_d = debugfs_create_file(file_name, 0400, edma_rx_dir_d, (void *)(nss_ptr_t)i, &nss_edma_rxring_stats_ops);
+		if (unlikely(edma_rx_d == NULL)) {
+			nss_warning("Failed to create qca-nss-drv/stats/edma/rings/rx/%d file", i);
+			return;
+		}
+	}
+
+	/*
+	 * edma tx cmpl ring stats
+	 */
+	edma_txcmpl_dir_d = debugfs_create_dir("txcmpl", edma_rings_dir_d);
+	if (unlikely(edma_txcmpl_dir_d == NULL)) {
+		nss_warning("Failed to create qca-nss-drv/stats/edma/rings/txcmpl directory");
+		return;
+	}
+
+	for (i = 0; i < NSS_EDMA_NUM_TXCMPL_RING_MAX; i++) {
+		memset(file_name, 0, sizeof(file_name));
+		scnprintf(file_name, sizeof(file_name), "%d", i);
+		edma_txcmpl_d = debugfs_create_file(file_name, 0400, edma_txcmpl_dir_d, (void *)(nss_ptr_t)i, &nss_edma_txcmplring_stats_ops);
+		if (unlikely(edma_txcmpl_d == NULL)) {
+			nss_warning("Failed to create qca-nss-drv/stats/edma/rings/txcmpl/%d file", i);
+			return;
+		}
+	}
+
+	/*
+	 * edma rx fill ring stats
+	 */
+	edma_rxfill_dir_d = debugfs_create_dir("rxfill", edma_rings_dir_d);
+	if (unlikely(edma_rxfill_dir_d == NULL)) {
+		nss_warning("Failed to create qca-nss-drv/stats/edma/rings/rxfill directory");
+		return;
+	}
+
+	for (i = 0; i < NSS_EDMA_NUM_RXFILL_RING_MAX; i++) {
+		memset(file_name, 0, sizeof(file_name));
+		scnprintf(file_name, sizeof(file_name), "%d", i);
+		edma_rxfill_d = debugfs_create_file(file_name, 0400, edma_rxfill_dir_d, (void *)(nss_ptr_t)i, &nss_edma_rxfillring_stats_ops);
+		if (unlikely(edma_rxfill_d == NULL)) {
+			nss_warning("Failed to create qca-nss-drv/stats/edma/rings/rxfill/%d file", i);
+			return;
+		}
+	}
+}
+
+/*
+ * nss_edma_metadata_port_stats_sync()
+ *	Handle the syncing of EDMA port statistics.
+ */
+void nss_edma_metadata_port_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_edma_port_stats_sync *nepss)
+{
+	uint16_t i, j = 0;
+	struct nss_top_instance *nss_top = nss_ctx->nss_top;
+
+	spin_lock_bh(&nss_top->stats_lock);
+
+	/*
+	 * edma port stats
+	 * We process a subset of port stats since msg payload is not enough to hold all ports at once.
+	 */
+	for (i = nepss->start_port; i < nepss->end_port; i++) {
+		int k;
+
+		edma_stats.port[i].port_stats[NSS_STATS_NODE_RX_PKTS] += nepss->port_stats[j].node_stats.rx_packets;
+		edma_stats.port[i].port_stats[NSS_STATS_NODE_RX_BYTES] += nepss->port_stats[j].node_stats.rx_bytes;
+		edma_stats.port[i].port_stats[NSS_STATS_NODE_TX_PKTS] += nepss->port_stats[j].node_stats.tx_packets;
+		edma_stats.port[i].port_stats[NSS_STATS_NODE_TX_BYTES] += nepss->port_stats[j].node_stats.tx_bytes;
+
+		for (k = 0; k < NSS_MAX_NUM_PRI; k++) {
+			edma_stats.port[i].port_stats[NSS_STATS_NODE_RX_QUEUE_0_DROPPED + k] += nepss->port_stats[i].node_stats.rx_dropped[k];
+		}
+
+		edma_stats.port[i].port_type = nepss->port_stats[j].port_type;
+		edma_stats.port[i].port_ring_map[NSS_EDMA_PORT_RX_RING] = nepss->port_stats[j].edma_rx_ring;
+		edma_stats.port[i].port_ring_map[NSS_EDMA_PORT_TX_RING] = nepss->port_stats[j].edma_tx_ring;
+		j++;
+	}
+
+	spin_unlock_bh(&nss_top->stats_lock);
+}
+
+/*
+ * nss_edma_metadata_ring_stats_sync()
+ *	Handle the syncing of EDMA ring statistics.
+ */
+void nss_edma_metadata_ring_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_edma_ring_stats_sync *nerss)
+{
+	int32_t i;
+	struct nss_top_instance *nss_top = nss_ctx->nss_top;
+
+	spin_lock_bh(&nss_top->stats_lock);
+
+	/*
+	 * edma tx ring stats
+	 */
+	for (i = 0; i < NSS_EDMA_NUM_TX_RING_MAX; i++) {
+		edma_stats.tx_stats[i][NSS_EDMA_STATS_TX_ERR] += nerss->tx_ring[i].tx_err;
+		edma_stats.tx_stats[i][NSS_EDMA_STATS_TX_DROPPED] += nerss->tx_ring[i].tx_dropped;
+		edma_stats.tx_stats[i][NSS_EDMA_STATS_TX_DESC] += nerss->tx_ring[i].desc_cnt;
+	}
+
+	/*
+	 * edma rx ring stats
+	 */
+	for (i = 0; i < NSS_EDMA_NUM_RX_RING_MAX; i++) {
+		edma_stats.rx_stats[i][NSS_EDMA_STATS_RX_CSUM_ERR] += nerss->rx_ring[i].rx_csum_err;
+		edma_stats.rx_stats[i][NSS_EDMA_STATS_RX_DESC] += nerss->rx_ring[i].desc_cnt;
+	}
+
+	/*
+	 * edma tx cmpl ring stats
+	 */
+	for (i = 0; i < NSS_EDMA_NUM_TXCMPL_RING_MAX; i++) {
+		edma_stats.txcmpl_stats[i][NSS_EDMA_STATS_TXCMPL_DESC] += nerss->txcmpl_ring[i].desc_cnt;
+	}
+
+	/*
+	 * edma rx fill ring stats
+	 */
+	for (i = 0; i < NSS_EDMA_NUM_RXFILL_RING_MAX; i++) {
+		edma_stats.rxfill_stats[i][NSS_EDMA_STATS_RXFILL_DESC] += nerss->rxfill_ring[i].desc_cnt;
+	}
+
+	spin_unlock_bh(&nss_top->stats_lock);
+}
+
+/*
+ * nss_edma_metadata_err_stats_sync()
+ *	Handle the syncing of EDMA error statistics.
+ */
+void nss_edma_metadata_err_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_edma_err_stats_sync *nerss)
+{
+
+	struct nss_top_instance *nss_top = nss_ctx->nss_top;
+
+	spin_lock_bh(&nss_top->stats_lock);
+
+	edma_stats.misc_err[NSS_EDMA_AXI_RD_ERR] += nerss->msg_err_stats.axi_rd_err;
+	edma_stats.misc_err[NSS_EDMA_AXI_WR_ERR] += nerss->msg_err_stats.axi_wr_err;
+	edma_stats.misc_err[NSS_EDMA_RX_DESC_FIFO_FULL_ERR] += nerss->msg_err_stats.rx_desc_fifo_full_err;
+	edma_stats.misc_err[NSS_EDMA_RX_BUF_SIZE_ERR] += nerss->msg_err_stats.rx_buf_size_err;
+	edma_stats.misc_err[NSS_EDMA_TX_SRAM_FULL_ERR] += nerss->msg_err_stats.tx_sram_full_err;
+	edma_stats.misc_err[NSS_EDMA_TX_CMPL_BUF_FULL_ERR] += nerss->msg_err_stats.tx_cmpl_buf_full_err;
+	edma_stats.misc_err[NSS_EDMA_PKT_LEN_LA64K_ERR] += nerss->msg_err_stats.pkt_len_la64k_err;
+	edma_stats.misc_err[NSS_EDMA_PKT_LEN_LE33_ERR] += nerss->msg_err_stats.pkt_len_le33_err;
+	edma_stats.misc_err[NSS_EDMA_DATA_LEN_ERR] += nerss->msg_err_stats.data_len_err;
+
+	spin_unlock_bh(&nss_top->stats_lock);
+}
diff --git a/nss_edma_stats.h b/nss_edma_stats.h
new file mode 100644
index 0000000..1c61075
--- /dev/null
+++ b/nss_edma_stats.h
@@ -0,0 +1,118 @@
+/*
+ ******************************************************************************
+ * 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.
+ * ****************************************************************************
+ */
+
+/*
+ * nss_edma_stats.h
+ *	NSS EDMA statistics header file.
+ */
+
+#ifndef __NSS_EDMA_STATS_H
+#define __NSS_EDMA_STATS_H
+
+#include "nss_core.h"
+
+/*
+ * Types of EDMA Tx ring stats
+ */
+enum nss_edma_stats_tx_t {
+	NSS_EDMA_STATS_TX_ERR,
+	NSS_EDMA_STATS_TX_DROPPED,
+	NSS_EDMA_STATS_TX_DESC,
+	NSS_EDMA_STATS_TX_MAX
+};
+
+/*
+ * Types of EDMA Rx ring stats
+ */
+enum nss_edma_stats_rx_t {
+	NSS_EDMA_STATS_RX_CSUM_ERR,
+	NSS_EDMA_STATS_RX_DESC,
+	NSS_EDMA_STATS_RX_QOS_ERR,
+	NSS_EDMA_STATS_RX_MAX
+};
+
+/*
+ * Types of EDMA Tx complete stats
+ */
+enum nss_edma_stats_txcmpl_t {
+	NSS_EDMA_STATS_TXCMPL_DESC,
+	NSS_EDMA_STATS_TXCMPL_MAX
+};
+
+/*
+ * Types of EDMA Rx fill stats
+ */
+enum nss_edma_stats_rxfill_t {
+	NSS_EDMA_STATS_RXFILL_DESC,
+	NSS_EDMA_STATS_RXFILL_MAX
+};
+
+/*
+ * Port to EDMA ring map
+ */
+enum nss_edma_port_ring_map_t {
+	NSS_EDMA_PORT_RX_RING,
+	NSS_EDMA_PORT_TX_RING,
+	NSS_EDMA_PORT_RING_MAP_MAX
+};
+
+/*
+ * Types of EDMA ERROR STATS
+ */
+enum nss_edma_err_t {
+	NSS_EDMA_AXI_RD_ERR,
+	NSS_EDMA_AXI_WR_ERR,
+	NSS_EDMA_RX_DESC_FIFO_FULL_ERR,
+	NSS_EDMA_RX_BUF_SIZE_ERR,
+	NSS_EDMA_TX_SRAM_FULL_ERR,
+	NSS_EDMA_TX_CMPL_BUF_FULL_ERR,
+	NSS_EDMA_PKT_LEN_LA64K_ERR,
+	NSS_EDMA_PKT_LEN_LE33_ERR,
+	NSS_EDMA_DATA_LEN_ERR,
+	NSS_EDMA_ALLOC_FAIL_CNT,
+	NSS_EDMA_ERR_STATS_MAX
+};
+
+/*
+ * NSS EDMA port stats
+ */
+struct nss_edma_port_info {
+	uint64_t port_stats[NSS_STATS_NODE_MAX];
+	uint64_t port_type;
+	uint64_t port_ring_map[NSS_EDMA_PORT_RING_MAP_MAX];
+};
+
+/*
+ * NSS EDMA node statistics
+ */
+struct nss_edma_stats {
+	struct nss_edma_port_info port[NSS_EDMA_NUM_PORTS_MAX];
+	uint64_t tx_stats[NSS_EDMA_NUM_TX_RING_MAX][NSS_EDMA_STATS_TX_MAX];
+	uint64_t rx_stats[NSS_EDMA_NUM_RX_RING_MAX][NSS_EDMA_STATS_RX_MAX];
+	uint64_t txcmpl_stats[NSS_EDMA_NUM_TXCMPL_RING_MAX][NSS_EDMA_STATS_TXCMPL_MAX];
+	uint64_t rxfill_stats[NSS_EDMA_NUM_RXFILL_RING_MAX][NSS_EDMA_STATS_RXFILL_MAX];
+	uint64_t misc_err[NSS_EDMA_ERR_STATS_MAX];
+};
+
+/*
+ * NSS EDMA statistics APIs
+ */
+extern void nss_edma_metadata_port_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_edma_port_stats_sync *nepss);
+extern void nss_edma_metadata_ring_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_edma_ring_stats_sync *nerss);
+extern void nss_edma_metadata_err_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_edma_err_stats_sync *nerss);
+extern void nss_edma_stats_dentry_create(void);
+
+#endif /* __NSS_EDMA_STATS_H */
diff --git a/nss_eth_rx.c b/nss_eth_rx.c
index 2ac5687..6d1fb4a 100644
--- a/nss_eth_rx.c
+++ b/nss_eth_rx.c
@@ -1,6 +1,6 @@
 /*
  **************************************************************************
- * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-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.
@@ -20,6 +20,7 @@
  */
 
 #include "nss_tx_rx_common.h"
+#include "nss_eth_rx_stats.h"
 
 /*
  **********************************
@@ -28,37 +29,6 @@
  */
 
 /*
- * nss_eth_rx_metadata_stats_sync()
- *	Handle the syncing of PPPoE node statistics.
- */
-static void nss_eth_rx_metadata_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_eth_rx_node_sync *nens)
-{
-	int i;
-	struct nss_top_instance *nss_top = nss_ctx->nss_top;
-
-	spin_lock_bh(&nss_top->stats_lock);
-
-	nss_top->stats_node[NSS_ETH_RX_INTERFACE][NSS_STATS_NODE_RX_PKTS] += nens->node_stats.rx_packets;
-	nss_top->stats_node[NSS_ETH_RX_INTERFACE][NSS_STATS_NODE_RX_BYTES] += nens->node_stats.rx_bytes;
-	nss_top->stats_node[NSS_ETH_RX_INTERFACE][NSS_STATS_NODE_TX_PKTS] += nens->node_stats.tx_packets;
-	nss_top->stats_node[NSS_ETH_RX_INTERFACE][NSS_STATS_NODE_TX_BYTES] += nens->node_stats.tx_bytes;
-
-	for (i = 0; i < NSS_MAX_NUM_PRI; i++) {
-		nss_top->stats_node[NSS_ETH_RX_INTERFACE][NSS_STATS_NODE_RX_QUEUE_0_DROPPED + i] += nens->node_stats.rx_dropped[i];
-	}
-
-	nss_top->stats_eth_rx[NSS_STATS_ETH_RX_TOTAL_TICKS] += nens->total_ticks;
-	nss_top->stats_eth_rx[NSS_STATS_ETH_RX_WORST_CASE_TICKS] += nens->worst_case_ticks;
-	nss_top->stats_eth_rx[NSS_STATS_ETH_RX_ITERATIONS] += nens->iterations;
-
-	for (i = 0; i < NSS_EXCEPTION_EVENT_ETH_RX_MAX; i++) {
-		nss_top->stats_if_exception_eth_rx[i] += nens->exception_events[i];
-	}
-
-	spin_unlock_bh(&nss_top->stats_lock);
-}
-
-/*
  * nss_eth_rx_interface_handler()
  *	Handle NSS -> HLOS messages for ETH_RX node
  */
@@ -96,4 +66,6 @@
 void nss_eth_rx_register_handler(struct nss_ctx_instance *nss_ctx)
 {
 	nss_core_register_handler(nss_ctx, NSS_ETH_RX_INTERFACE, nss_eth_rx_interface_handler, NULL);
+
+	nss_eth_rx_stats_dentry_create();
 }
diff --git a/nss_eth_rx_stats.c b/nss_eth_rx_stats.c
new file mode 100644
index 0000000..617e846
--- /dev/null
+++ b/nss_eth_rx_stats.c
@@ -0,0 +1,166 @@
+/*
+ **************************************************************************
+ * 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_stats.h"
+#include "nss_core.h"
+#include "nss_eth_rx_stats.h"
+
+/*
+ * nss_eth_rx_stats_str
+ *	eth_rx stats strings
+ */
+static int8_t *nss_eth_rx_stats_str[NSS_ETH_RX_STATS_MAX] = {
+	"ticks",
+	"worst_ticks",
+	"iterations"
+};
+
+/*
+ * nss_eth_rx_exception_stats_str
+ *	Interface stats strings for unknown exceptions
+ */
+static int8_t *nss_eth_rx_exception_stats_str[NSS_ETH_RX_EXCEPTION_EVENT_MAX] = {
+	"UNKNOWN_L3_PROTOCOL",
+	"ETH_HDR_MISSING",
+	"VLAN_MISSING",
+	"TRUSTSEC_HDR_MISSING"
+};
+
+uint64_t nss_eth_rx_stats[NSS_ETH_RX_STATS_MAX];			/* ETH_RX statistics */
+uint64_t nss_eth_rx_exception_stats[NSS_ETH_RX_EXCEPTION_EVENT_MAX];	/* Unknown protocol exception events per interface */
+
+/*
+ * nss_eth_rx_stats_read()
+ *	Read ETH_RX stats
+ */
+static ssize_t nss_eth_rx_stats_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
+{
+	int32_t i;
+
+	/*
+	 * max output lines = #stats + start tag line + end tag line + three blank lines
+	 */
+	uint32_t max_output_lines = (NSS_STATS_NODE_MAX + 2) + (NSS_ETH_RX_STATS_MAX + 3) + (NSS_ETH_RX_EXCEPTION_EVENT_MAX + 3) + 5;
+	size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
+	size_t size_wr = 0;
+	ssize_t bytes_read = 0;
+	uint64_t *stats_shadow;
+
+	char *lbuf = kzalloc(size_al, GFP_KERNEL);
+	if (unlikely(lbuf == NULL)) {
+		nss_warning("Could not allocate memory for local statistics buffer");
+		return 0;
+	}
+
+	/*
+	 * Note: The assumption here is that we do not have more than 64 stats
+	 */
+	stats_shadow = kzalloc(64 * 8, GFP_KERNEL);
+	if (unlikely(stats_shadow == NULL)) {
+		nss_warning("Could not allocate memory for local shadow buffer");
+		kfree(lbuf);
+		return 0;
+	}
+
+	size_wr = scnprintf(lbuf, size_al, "eth_rx stats start:\n\n");
+
+	size_wr = nss_stats_fill_common_stats(NSS_ETH_RX_INTERFACE, lbuf, size_wr, size_al);
+
+	/*
+	 * eth_rx node stats
+	 */
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\neth_rx node stats:\n\n");
+	spin_lock_bh(&nss_top_main.stats_lock);
+	for (i = 0; (i < NSS_ETH_RX_STATS_MAX); i++) {
+		stats_shadow[i] = nss_eth_rx_stats[i];
+	}
+
+	spin_unlock_bh(&nss_top_main.stats_lock);
+
+	for (i = 0; (i < NSS_ETH_RX_STATS_MAX); i++) {
+		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
+					"%s = %llu\n", nss_eth_rx_stats_str[i], stats_shadow[i]);
+	}
+
+	/*
+	 * Exception stats
+	 */
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\neth_rx exception stats:\n\n");
+
+	spin_lock_bh(&nss_top_main.stats_lock);
+	for (i = 0; (i < NSS_ETH_RX_EXCEPTION_EVENT_MAX); i++) {
+		stats_shadow[i] = nss_eth_rx_exception_stats[i];
+	}
+
+	spin_unlock_bh(&nss_top_main.stats_lock);
+
+	for (i = 0; (i < NSS_ETH_RX_EXCEPTION_EVENT_MAX); i++) {
+		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
+					"%s = %llu\n", nss_eth_rx_exception_stats_str[i], stats_shadow[i]);
+	}
+
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\neth_rx stats end\n\n");
+	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
+	kfree(lbuf);
+	kfree(stats_shadow);
+
+	return bytes_read;
+}
+
+/*
+ * nss_eth_rx_stats_ops
+ */
+NSS_STATS_DECLARE_FILE_OPERATIONS(eth_rx)
+
+/*
+ * nss_eth_rx_stats_dentry_create()
+ *	Create eth_rx statistics debug entry.
+ */
+void nss_eth_rx_stats_dentry_create(void)
+{
+	nss_stats_create_dentry("eth_rx", &nss_eth_rx_stats_ops);
+}
+
+/*
+ * nss_eth_rx_metadata_stats_sync()
+ *	Handle the syncing of ETH_RX node statistics.
+ */
+void nss_eth_rx_metadata_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_eth_rx_node_sync *nens)
+{
+	int32_t i;
+	struct nss_top_instance *nss_top = nss_ctx->nss_top;
+
+	spin_lock_bh(&nss_top->stats_lock);
+
+	nss_top->stats_node[NSS_ETH_RX_INTERFACE][NSS_STATS_NODE_RX_PKTS] += nens->node_stats.rx_packets;
+	nss_top->stats_node[NSS_ETH_RX_INTERFACE][NSS_STATS_NODE_RX_BYTES] += nens->node_stats.rx_bytes;
+	nss_top->stats_node[NSS_ETH_RX_INTERFACE][NSS_STATS_NODE_TX_PKTS] += nens->node_stats.tx_packets;
+	nss_top->stats_node[NSS_ETH_RX_INTERFACE][NSS_STATS_NODE_TX_BYTES] += nens->node_stats.tx_bytes;
+
+	for (i = 0; i < NSS_MAX_NUM_PRI; i++) {
+		nss_top->stats_node[NSS_ETH_RX_INTERFACE][NSS_STATS_NODE_RX_QUEUE_0_DROPPED + i] += nens->node_stats.rx_dropped[i];
+	}
+
+	nss_eth_rx_stats[NSS_ETH_RX_STATS_TOTAL_TICKS] += nens->total_ticks;
+	nss_eth_rx_stats[NSS_ETH_RX_STATS_WORST_CASE_TICKS] += nens->worst_case_ticks;
+	nss_eth_rx_stats[NSS_ETH_RX_STATS_ITERATIONS] += nens->iterations;
+
+	for (i = 0; i < NSS_ETH_RX_EXCEPTION_EVENT_MAX; i++) {
+		nss_eth_rx_exception_stats[i] += nens->exception_events[i];
+	}
+
+	spin_unlock_bh(&nss_top->stats_lock);
+}
diff --git a/nss_eth_rx_stats.h b/nss_eth_rx_stats.h
new file mode 100644
index 0000000..bc60da2
--- /dev/null
+++ b/nss_eth_rx_stats.h
@@ -0,0 +1,82 @@
+/*
+ **************************************************************************
+ * 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.
+ **************************************************************************
+ */
+
+#ifndef __NSS_ETH_RX_STATS_H
+#define __NSS_ETH_RX_STATS_H
+
+#include <nss_cmn.h>
+
+/*
+ * nss_eth_rx_stats.h
+ *	NSS driver ETH_RX statistics header file.
+ */
+
+/*
+ * ETH_RX node statistics
+ */
+enum nss_eth_rx_stats {
+	NSS_ETH_RX_STATS_TOTAL_TICKS = 0,	/* Total clock ticks spend inside the eth_rx package */
+	NSS_ETH_RX_STATS_WORST_CASE_TICKS,	/* Worst case iteration of the eth_rx in ticks */
+	NSS_ETH_RX_STATS_ITERATIONS,		/* Number of iterations around the eth_rx */
+	NSS_ETH_RX_STATS_MAX,
+};
+
+/*
+ * Exception events from bridge/route handler
+ */
+enum nss_eth_rx_exception_events {
+	NSS_ETH_RX_EXCEPTION_EVENT_UNKNOWN_L3_PROTOCOL,
+	NSS_ETH_RX_EXCEPTION_EVENT_ETH_HDR_MISSING,
+	NSS_ETH_RX_EXCEPTION_EVENT_VLAN_MISSING,
+	NSS_ETH_RX_EXCEPTION_EVENT_TRUSTSEC_HDR_MISSING,
+	NSS_ETH_RX_EXCEPTION_EVENT_MAX,
+};
+
+/*
+ * Request/Response types
+ */
+enum nss_eth_rx_metadata_types {
+	NSS_RX_METADATA_TYPE_ETH_RX_STATS_SYNC,
+	NSS_METADATA_TYPE_ETH_RX_MAX,
+};
+
+/*
+ * The NSS eth_rx node stats structure.
+ */
+struct nss_eth_rx_node_sync {
+	struct nss_cmn_node_stats node_stats;
+				/* Common node stats for ETH_RX */
+	uint32_t total_ticks;		/* Total clock ticks spend inside the eth_rx */
+	uint32_t worst_case_ticks;	/* Worst case iteration of the eth_rx in ticks */
+	uint32_t iterations;		/* Number of iterations around the eth_rx */
+	uint32_t exception_events[NSS_ETH_RX_EXCEPTION_EVENT_MAX];
+				/* Number of ETH_RX exception events */
+};
+
+/*
+ * Message structure to send/receive eth_rx commands
+ */
+struct nss_eth_rx_msg {
+	struct nss_cmn_msg cm;		/* Message Header */
+	union {
+		struct nss_eth_rx_node_sync node_sync;	/* Message: node statistics sync */
+	} msg;
+};
+
+extern void nss_eth_rx_metadata_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_eth_rx_node_sync *nens);
+extern void nss_eth_rx_stats_dentry_create(void);
+
+#endif /* __NSS_ETH_RX_STATS_H */
diff --git a/nss_gre.c b/nss_gre.c
index 902e9d4..4c426e8 100644
--- a/nss_gre.c
+++ b/nss_gre.c
@@ -15,6 +15,7 @@
  */
 
 #include "nss_tx_rx_common.h"
+#include "nss_gre_stats.h"
 
 #define NSS_GRE_TX_TIMEOUT 3000 /* 3 Seconds */
 
@@ -29,13 +30,6 @@
 	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;
-
 static atomic64_t pkt_cb_addr = ATOMIC64_INIT(0);
 
 /*
@@ -60,39 +54,6 @@
 }
 
 /*
- * 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_base_debug_stats_sync()
- *	Debug statistics sync for GRE base node.
- */
-static 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_msg_handler()
  *	Handle NSS -> HLOS messages for GRE
  */
@@ -124,11 +85,11 @@
 		/*
 		 * debug stats embedded in stats msg
 		 */
-		nss_gre_session_debug_stats_sync(nss_ctx, &ntm->msg.sstats, ncm->interface);
+		nss_gre_stats_session_debug_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);
+		nss_gre_stats_base_debug_sync(nss_ctx, &ntm->msg.bstats);
 		break;
 
 	default:
@@ -195,53 +156,6 @@
 }
 
 /*
- * 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_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_register_pkt_callback()
  *	Register for data callback.
  */
@@ -406,7 +320,6 @@
 			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));
@@ -418,16 +331,7 @@
 
 	nss_core_register_handler(nss_ctx, 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);
+	nss_gre_stats_session_register(if_num, netdev);
 
 	return nss_ctx;
 }
@@ -440,7 +344,6 @@
 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));
@@ -451,14 +354,7 @@
 
 	nss_core_unregister_handler(nss_ctx, 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);
+	nss_gre_stats_session_unregister(if_num);
 }
 EXPORT_SYMBOL(nss_gre_unregister_if);
 
@@ -493,4 +389,5 @@
 	sema_init(&nss_gre_pvt.sem, 1);
 	init_completion(&nss_gre_pvt.complete);
 	nss_core_register_handler(nss_ctx, NSS_GRE_INTERFACE, nss_gre_msg_handler, NULL);
+	nss_gre_stats_dentry_create();
 }
diff --git a/nss_gre_redir.c b/nss_gre_redir.c
index 1ff3106..55ce3b7 100644
--- a/nss_gre_redir.c
+++ b/nss_gre_redir.c
@@ -15,6 +15,7 @@
  */
 
 #include "nss_tx_rx_common.h"
+#include "nss_gre_redir_stats.h"
 
 /*
  * Spinlock to update tunnel stats
@@ -354,6 +355,8 @@
 		nss_warning("Not able to register handler for gre_redir base interface with NSS core\n");
 		return;
 	}
+
+	nss_gre_redir_stats_dentry_create();
 }
 
 EXPORT_SYMBOL(nss_gre_redir_tx_msg);
diff --git a/nss_gre_redir_stats.c b/nss_gre_redir_stats.c
new file mode 100644
index 0000000..e350f5e
--- /dev/null
+++ b/nss_gre_redir_stats.c
@@ -0,0 +1,159 @@
+/*
+ **************************************************************************
+ * 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_core.h"
+#include "nss_stats.h"
+#include "nss_gre_redir.h"
+#include "nss_gre_redir_stats.h"
+
+/*
+ * nss_gre_redir_stats_str
+ *	GRE REDIR statistics string
+ */
+static int8_t *nss_gre_redir_stats_str[NSS_GRE_REDIR_STATS_MAX] = {
+	"TX Packets",
+	"TX Bytes",
+	"TX Drops",
+	"RX Packets",
+	"RX Bytes",
+	"Rx Drops"
+};
+
+/*
+ * nss_gre_redir_stats()
+ *	Make a row for GRE_REDIR stats.
+ */
+static ssize_t nss_gre_redir_stats(char *line, int len, int i, struct nss_gre_redir_tunnel_stats *s)
+{
+	char name[20];
+	uint64_t tcnt = 0;
+	int j = 0;
+
+	switch (i) {
+	case 0:
+		tcnt = s->node_stats.tx_packets;
+		return snprintf(line, len, "%s = %llu\n", nss_gre_redir_stats_str[i], tcnt);
+	case 1:
+		tcnt = s->node_stats.tx_bytes;
+		return snprintf(line, len, "%s = %llu\n", nss_gre_redir_stats_str[i], tcnt);
+	case 2:
+		tcnt = s->tx_dropped;
+		return snprintf(line, len, "%s = %llu\n", nss_gre_redir_stats_str[i], tcnt);
+	case 3:
+		tcnt = s->node_stats.rx_packets;
+		return snprintf(line, len, "%s = %llu\n", nss_gre_redir_stats_str[i], tcnt);
+	case 4:
+		tcnt = s->node_stats.rx_bytes;
+		return snprintf(line, len, "%s = %llu\n", nss_gre_redir_stats_str[i], tcnt);
+	case 5:
+		for (j = 0; j < NSS_MAX_NUM_PRI; j++) {
+			scnprintf(name, 20, "Rx Queue %d Drops", j);
+			tcnt += snprintf(line, len, "%s = %u\n", name, s->node_stats.rx_dropped[j]);
+		}
+		return tcnt;
+
+	default:
+		return 0;
+	}
+
+	return snprintf(line, len, "%s = %llu\n", nss_gre_redir_stats_str[i], tcnt);
+}
+
+/*
+ * nss_gre_redir_stats_read()
+ *	READ gre_redir tunnel stats.
+ */
+static ssize_t nss_gre_redir_stats_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
+{
+	struct nss_stats_data *data = fp->private_data;
+	ssize_t bytes_read = 0;
+	struct nss_gre_redir_tunnel_stats stats;
+	size_t bytes;
+	char line[80];
+	int start, end;
+	int index = 0;
+
+	if (data) {
+		index = data->index;
+	}
+
+	/*
+	 * If we are done accomodating all the GRE_REDIR tunnels.
+	 */
+	if (index >= NSS_GRE_REDIR_MAX_INTERFACES) {
+		return 0;
+	}
+
+	for (; index < NSS_GRE_REDIR_MAX_INTERFACES; index++) {
+		bool isthere;
+
+		/*
+		 * If gre_redir tunnel does not exists, then isthere will be false.
+		 */
+		isthere = nss_gre_redir_get_stats(index, &stats);
+		if (!isthere) {
+			continue;
+		}
+
+		bytes = snprintf(line, sizeof(line), "\nTunnel if_num: %2d\n", stats.if_num);
+		if ((bytes_read + bytes) > sz) {
+			break;
+		}
+
+		if (copy_to_user(ubuf + bytes_read, line, bytes) != 0) {
+			bytes_read = -EFAULT;
+			goto fail;
+		}
+		bytes_read += bytes;
+		start = 0;
+		end = 6;
+		while (bytes_read < sz && start < end) {
+			bytes = nss_gre_redir_stats(line, sizeof(line), start, &stats);
+
+			if ((bytes_read + bytes) > sz)
+				break;
+
+			if (copy_to_user(ubuf + bytes_read, line, bytes) != 0) {
+				bytes_read = -EFAULT;
+				goto fail;
+			}
+
+			bytes_read += bytes;
+			start++;
+		}
+	}
+
+	if (bytes_read > 0) {
+		*ppos = bytes_read;
+	}
+
+	if (data) {
+		data->index = index;
+	}
+
+fail:
+	return bytes_read;
+}
+
+/*
+ * nss_gre_redir_stats_ops
+ */
+NSS_STATS_DECLARE_FILE_OPERATIONS(gre_redir)
+
+void nss_gre_redir_stats_dentry_create(void)
+{
+	nss_stats_create_dentry("gre_redir", &nss_gre_redir_stats_ops);
+}
diff --git a/nss_gre_redir_stats.h b/nss_gre_redir_stats.h
new file mode 100644
index 0000000..a551931
--- /dev/null
+++ b/nss_gre_redir_stats.h
@@ -0,0 +1,38 @@
+/*
+ ******************************************************************************
+ * 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.
+ * ****************************************************************************
+ */
+
+#ifndef __NSS_GRE_REDIR_STATS_H__
+#define __NSS_GRE_REDIR_STATS_H__
+
+/*
+ * GRE REDIR statistics
+ */
+enum nss_gre_redir_stats_types {
+	NSS_GRE_REDIR_STATS_TX_PKTS,
+	NSS_GRE_REDIR_STATS_TX_BYTES,
+	NSS_GRE_REDIR_STATS_TX_DROPS,
+	NSS_GRE_REDIR_STATS_RX_PKTS,
+	NSS_GRE_REDIR_STATS_RX_BYTES,
+	NSS_GRE_REDIR_STATS_RX_DROPS,
+	NSS_GRE_REDIR_STATS_MAX
+};
+
+/*
+ * NSS GRE REDIR statistics APIs
+ */
+extern void nss_gre_redir_stats_dentry_create(void);
+
+#endif /* __NSS_GRE_REDIR_STATS_H__ */
diff --git a/nss_gre_stats.c b/nss_gre_stats.c
new file mode 100644
index 0000000..7bead7b
--- /dev/null
+++ b/nss_gre_stats.c
@@ -0,0 +1,308 @@
+/*
+ **************************************************************************
+ * 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.
+ **************************************************************************
+ */
+
+/*
+ * nss_gre_stats.c
+ *	NSS GRE statistics APIs
+ *
+ */
+
+#include "nss_tx_rx_common.h"
+#include "nss_stats.h"
+#include "nss_gre_stats.h"
+
+/*
+ * Data structures to store GRE nss debug stats
+ */
+static DEFINE_SPINLOCK(nss_gre_stats_lock);
+static struct nss_gre_stats_session_debug session_debug_stats[NSS_GRE_MAX_DEBUG_SESSION_STATS];
+static struct nss_gre_stats_base_debug base_debug_stats;
+
+/*
+ * nss_gre_stats_base_debug_str
+ *	GRE debug statistics strings for base types
+ */
+static int8_t *nss_gre_stats_base_debug_str[NSS_GRE_STATS_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_gre_stats_session_debug_str
+ *	GRE debug statistics strings for sessions
+ */
+static int8_t *nss_gre_stats_session_debug_str[NSS_GRE_STATS_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",
+};
+
+/*
+ * GRE statistics APIs
+ */
+
+/*
+ * nss_gre_stats_session_register()
+ *	Register debug statistic for GRE session.
+ */
+void nss_gre_stats_session_register(uint32_t if_num, struct net_device *netdev)
+{
+	int i;
+
+	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);
+}
+
+/*
+ * nss_gre_stats_session_unregister()
+ *	Unregister debug statistic for GRE session.
+ */
+void nss_gre_stats_session_unregister(uint32_t if_num)
+{
+	int i;
+
+	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_gre_stats_session_debug));
+			break;
+		}
+	}
+	spin_unlock_bh(&nss_gre_stats_lock);
+}
+
+/*
+ * nss_gre_stats_session_debug_sync()
+ *	debug statistics sync for GRE session.
+ */
+void nss_gre_stats_session_debug_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_GRE_STATS_SESSION_DEBUG_MAX; j++) {
+				session_debug_stats[i].stats[j] += sstats->stats[j];
+			}
+			break;
+		}
+	}
+	spin_unlock_bh(&nss_gre_stats_lock);
+}
+
+/*
+ * nss_gre_stats_base_debug_sync()
+ *	Debug statistics sync for GRE base node.
+ */
+void nss_gre_stats_base_debug_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_GRE_STATS_BASE_DEBUG_MAX; i++) {
+		base_debug_stats.stats[i] += bstats->stats[i];
+	}
+	spin_unlock_bh(&nss_gre_stats_lock);
+}
+
+/*
+ * nss_gre_stats_session_debug_get()
+ *	Get GRE session debug statistics.
+ */
+static void nss_gre_stats_session_debug_get(void *stats_mem, int size)
+{
+	struct nss_gre_stats_session_debug *stats = (struct nss_gre_stats_session_debug *)stats_mem;
+	int i;
+
+	if (!stats || (size < (sizeof(struct nss_gre_stats_session_debug) * NSS_GRE_MAX_DEBUG_SESSION_STATS)))  {
+		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_gre_stats_session_debug));
+			stats++;
+		}
+	}
+	spin_unlock_bh(&nss_gre_stats_lock);
+}
+
+/*
+ * nss_gre_stats_base_debug_get()
+ *	Get GRE debug base statistics.
+ */
+static void nss_gre_stats_base_debug_get(void *stats_mem, int size)
+{
+	struct nss_gre_stats_base_debug *stats = (struct nss_gre_stats_base_debug *)stats_mem;
+
+	if (!stats) {
+		nss_warning("No memory to copy GRE base stats\n");
+		return;
+	}
+
+	if (size < sizeof(struct nss_gre_stats_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_gre_stats_base_debug));
+	spin_unlock_bh(&nss_gre_stats_lock);
+}
+
+/*
+ * nss_gre_stats_read()
+ *	Read GRE statistics
+ */
+static ssize_t nss_gre_stats_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_GRE_STATS_BASE_DEBUG_MAX  /* Base debug */
+		+ NSS_GRE_MAX_DEBUG_SESSION_STATS * (NSS_GRE_STATS_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_gre_stats_session_debug *sstats;
+	struct nss_gre_stats_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_gre_stats_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_gre_stats_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_stats_base_debug_get((void *)bstats, sizeof(struct nss_gre_stats_base_debug));
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\ngre Base stats start:\n\n");
+	for (i = 0; i < NSS_GRE_STATS_BASE_DEBUG_MAX; i++) {
+		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
+				     "\t%s = %llu\n", nss_gre_stats_base_debug_str[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_stats_session_debug_get(sstats, sizeof(struct nss_gre_stats_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_GRE_STATS_SESSION_DEBUG_MAX; i++) {
+			size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
+					     "\t%s = %llu\n", nss_gre_stats_session_debug_str[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_gre_stats_ops
+ */
+NSS_STATS_DECLARE_FILE_OPERATIONS(gre)
+
+/*
+ * nss_gre_stats_dentry_create()
+ *	Create gre statistics debug entry.
+ */
+void nss_gre_stats_dentry_create(void)
+{
+	nss_stats_create_dentry("gre", &nss_gre_stats_ops);
+}
+
diff --git a/nss_gre_stats.h b/nss_gre_stats.h
new file mode 100644
index 0000000..a16bd34
--- /dev/null
+++ b/nss_gre_stats.h
@@ -0,0 +1,95 @@
+/*
+ **************************************************************************
+ * 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.
+ **************************************************************************
+ */
+
+/*
+ * nss_gre_stats.h
+ *	NSS GRE statistics header file.
+ */
+
+#ifndef __NSS_GRE_STATS_H
+#define __NSS_GRE_STATS_H
+
+/*
+ * GRE base debug statistics types
+ */
+enum nss_gre_stats_base_debug_types {
+	NSS_GRE_STATS_BASE_RX_PACKETS,			/**< Rx packet count. */
+	NSS_GRE_STATS_BASE_RX_DROPPED,			/**< Rx dropped count. */
+	NSS_GRE_STATS_BASE_EXP_ETH_HDR_MISSING,		/**< Ethernet header missing. */
+	NSS_GRE_STATS_BASE_EXP_ETH_TYPE_NON_IP,		/**< Not IPV4 or IPV6 packet. */
+	NSS_GRE_STATS_BASE_EXP_IP_UNKNOWN_PROTOCOL,	/**< Unknown protocol. */
+	NSS_GRE_STATS_BASE_EXP_IP_HEADER_INCOMPLETE,	/**< Bad IP header. */
+	NSS_GRE_STATS_BASE_EXP_IP_BAD_TOTAL_LENGTH,	/**< Invalid IP packet length. */
+	NSS_GRE_STATS_BASE_EXP_IP_BAD_CHECKSUM,		/**< Bad packet checksum. */
+	NSS_GRE_STATS_BASE_EXP_IP_DATAGRAM_INCOMPLETE,	/**< Bad packet. */
+	NSS_GRE_STATS_BASE_EXP_IP_FRAGMENT,		/**< IP fragment. */
+	NSS_GRE_STATS_BASE_EXP_IP_OPTIONS_INCOMPLETE,	/**< Invalid IP options. */
+	NSS_GRE_STATS_BASE_EXP_IP_WITH_OPTIONS,		/**< IP packet with options. */
+	NSS_GRE_STATS_BASE_EXP_IPV6_UNKNOWN_PROTOCOL,	/**< Unknown protocol. */
+	NSS_GRE_STATS_BASE_EXP_IPV6_HEADER_INCOMPLETE,	/**< Incomplete IPV6 header. */
+	NSS_GRE_STATS_BASE_EXP_GRE_UNKNOWN_SESSION,	/**< Unknown GRE session. */
+	NSS_GRE_STATS_BASE_EXP_GRE_NODE_INACTIVE,	/**< GRE node inactive. */
+	NSS_GRE_STATS_BASE_DEBUG_MAX,			/**< GRE base error max. */
+};
+
+/*
+ *  GRE base debug statistics
+ */
+struct nss_gre_stats_base_debug	{
+	uint64_t stats[NSS_GRE_STATS_BASE_DEBUG_MAX];	/**< GRE debug statistics. */
+};
+
+/*
+ * GRE session debug statistics types
+ */
+enum nss_gre_stats_session_debug_types {
+	NSS_GRE_STATS_SESSION_PBUF_ALLOC_FAIL,			/**< Pbuf alloc failure. */
+	NSS_GRE_STATS_SESSION_DECAP_FORWARD_ENQUEUE_FAIL,	/**< Rx forward enqueue failure. */
+	NSS_GRE_STATS_SESSION_ENCAP_FORWARD_ENQUEUE_FAIL,	/**< Tx forward enqueue failure. */
+	NSS_GRE_STATS_SESSION_DECAP_TX_FORWARDED,		/**< Packets forwarded after decap. */
+	NSS_GRE_STATS_SESSION_ENCAP_RX_RECEIVED,		/**< Packets received for encap. */
+	NSS_GRE_STATS_SESSION_ENCAP_RX_DROPPED,			/**< Packets dropped while enqueue for encap. */
+	NSS_GRE_STATS_SESSION_ENCAP_RX_LINEAR_FAIL,		/**< Packets dropped during encap linearization. */
+	NSS_GRE_STATS_SESSION_EXP_RX_KEY_ERROR,			/**< Rx KEY error. */
+	NSS_GRE_STATS_SESSION_EXP_RX_SEQ_ERROR,			/**< Rx sequence number error. */
+	NSS_GRE_STATS_SESSION_EXP_RX_CS_ERROR,			/**< Rx checksum error. */
+	NSS_GRE_STATS_SESSION_EXP_RX_FLAG_MISMATCH,		/**< Rx flag mismatch. */
+	NSS_GRE_STATS_SESSION_EXP_RX_MALFORMED,			/**< Rx malformed packet. */
+	NSS_GRE_STATS_SESSION_EXP_RX_INVALID_PROTOCOL,		/**< Rx invalid protocol. */
+	NSS_GRE_STATS_SESSION_EXP_RX_NO_HEADROOM,		/**< Rx no headroom. */
+	NSS_GRE_STATS_SESSION_DEBUG_MAX,			/**< Session debug max. */
+};
+
+/*
+ *  GRE session debug statistics
+ */
+struct nss_gre_stats_session_debug {
+	uint64_t stats[NSS_GRE_STATS_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 ? */
+};
+
+/*
+ * GRE statistics APIs
+ */
+extern void nss_gre_stats_session_debug_sync(struct nss_ctx_instance *nss_ctx, struct nss_gre_session_stats_msg *sstats, uint16_t if_num);
+extern void nss_gre_stats_base_debug_sync(struct nss_ctx_instance *nss_ctx, struct nss_gre_base_stats_msg *bstats);
+extern void nss_gre_stats_session_register(uint32_t if_num, struct net_device *netdev);
+extern void nss_gre_stats_session_unregister(uint32_t if_num);
+extern void nss_gre_stats_dentry_create(void);
+
+#endif /* __NSS_GRE_STATS_H */
diff --git a/nss_gre_tunnel.c b/nss_gre_tunnel.c
index e515fcc..05605f3 100644
--- a/nss_gre_tunnel.c
+++ b/nss_gre_tunnel.c
@@ -20,12 +20,6 @@
 #define NSS_GRE_TUNNEL_TX_TIMEOUT 3000 /* 3 Seconds */
 
 /*
- * Data structures to store GRE Tunnel nss debug stats
- */
-static DEFINE_SPINLOCK(nss_gre_tunnel_session_debug_stats_lock);
-static struct nss_stats_gre_tunnel_session_debug nss_gre_tunnel_session_debug_stats[NSS_MAX_GRE_TUNNEL_SESSIONS];
-
-/*
  * Private data structure
  */
 static struct nss_gre_tunnel_pvt {
@@ -52,84 +46,6 @@
 }
 
 /*
- * nss_gre_tunnel_session_stats_sync()
- *	Sync function for statistics
- */
-static void nss_gre_tunnel_session_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_gre_tunnel_stats *stats_msg,
-					uint16_t if_num)
-{
-	int i;
-	struct nss_stats_gre_tunnel_session_debug *s = NULL;
-
-	NSS_VERIFY_CTX_MAGIC(nss_ctx);
-
-	spin_lock_bh(&nss_gre_tunnel_session_debug_stats_lock);
-	for (i = 0; i < NSS_MAX_GRE_TUNNEL_SESSIONS; i++) {
-		if (nss_gre_tunnel_session_debug_stats[i].if_num == if_num) {
-			s = &nss_gre_tunnel_session_debug_stats[i];
-			break;
-		}
-	}
-
-	if (!s) {
-		spin_unlock_bh(&nss_gre_tunnel_session_debug_stats_lock);
-		nss_warning("%p: Session not found: %u", nss_ctx, if_num);
-		return;
-	}
-
-	s->stats[NSS_STATS_GRE_TUNNEL_SESSION_RX_PKTS] += stats_msg->node_stats.rx_packets;
-	s->stats[NSS_STATS_GRE_TUNNEL_SESSION_TX_PKTS] += stats_msg->node_stats.tx_packets;
-	for (i = 0; i < NSS_MAX_NUM_PRI; i++) {
-		s->stats[NSS_STATS_GRE_TUNNEL_SESSION_RX_QUEUE_0_DROPPED + i] += stats_msg->node_stats.rx_dropped[i];
-	}
-	s->stats[NSS_STATS_GRE_TUNNEL_SESSION_RX_MALFORMED] += stats_msg->rx_malformed;
-	s->stats[NSS_STATS_GRE_TUNNEL_SESSION_RX_INVALID_PROT] += stats_msg->rx_invalid_prot;
-	s->stats[NSS_STATS_GRE_TUNNEL_SESSION_DECAP_QUEUE_FULL] += stats_msg->decap_queue_full;
-	s->stats[NSS_STATS_GRE_TUNNEL_SESSION_RX_SINGLE_REC_DGRAM] += stats_msg->rx_single_rec_dgram;
-	s->stats[NSS_STATS_GRE_TUNNEL_SESSION_RX_INVALID_REC_DGRAM] += stats_msg->rx_invalid_rec_dgram;
-	s->stats[NSS_STATS_GRE_TUNNEL_SESSION_BUFFER_ALLOC_FAIL] += stats_msg->buffer_alloc_fail;
-	s->stats[NSS_STATS_GRE_TUNNEL_SESSION_BUFFER_COPY_FAIL] += stats_msg->buffer_copy_fail;
-	s->stats[NSS_STATS_GRE_TUNNEL_SESSION_OUTFLOW_QUEUE_FULL] += stats_msg->outflow_queue_full;
-	s->stats[NSS_STATS_GRE_TUNNEL_SESSION_RX_DROPPED_HROOM] += stats_msg->rx_dropped_hroom;
-	s->stats[NSS_STATS_GRE_TUNNEL_SESSION_RX_CBUFFER_ALLOC_FAIL] += stats_msg->rx_cbuf_alloc_fail;
-	s->stats[NSS_STATS_GRE_TUNNEL_SESSION_RX_CENQUEUE_FAIL] += stats_msg->rx_cenqueue_fail;
-	s->stats[NSS_STATS_GRE_TUNNEL_SESSION_RX_DECRYPT_DONE] += stats_msg->rx_decrypt_done;
-	s->stats[NSS_STATS_GRE_TUNNEL_SESSION_RX_FORWARD_ENQUEUE_FAIL] += stats_msg->rx_forward_enqueue_fail;
-	s->stats[NSS_STATS_GRE_TUNNEL_SESSION_TX_CBUFFER_ALLOC_FAIL] += stats_msg->tx_cbuf_alloc_fail;
-	s->stats[NSS_STATS_GRE_TUNNEL_SESSION_TX_CENQUEUE_FAIL] += stats_msg->tx_cenqueue_fail;
-	s->stats[NSS_STATS_GRE_TUNNEL_SESSION_RX_DROPPED_TROOM] += stats_msg->rx_dropped_troom;
-	s->stats[NSS_STATS_GRE_TUNNEL_SESSION_TX_FORWARD_ENQUEUE_FAIL] += stats_msg->tx_forward_enqueue_fail;
-	s->stats[NSS_STATS_GRE_TUNNEL_SESSION_TX_CIPHER_DONE] += stats_msg->tx_cipher_done;
-	s->stats[NSS_STATS_GRE_TUNNEL_SESSION_CRYPTO_NOSUPP] += stats_msg->crypto_nosupp;
-	s->stats[NSS_STATS_GRE_TUNNEL_SESSION_RX_DROPPED_MH_VERSION] += stats_msg->rx_dropped_mh_ver;
-	spin_unlock_bh(&nss_gre_tunnel_session_debug_stats_lock);
-}
-
-/*
- * nss_gre_tunnel_session_debug_stats_get()
- *	Get session GRE Tunnel statitics.
- */
-void nss_gre_tunnel_session_debug_stats_get(struct nss_stats_gre_tunnel_session_debug *stats)
-{
-	int i;
-
-	if (!stats) {
-		nss_warning("No memory to copy gre_tunnel session stats");
-		return;
-	}
-
-	spin_lock_bh(&nss_gre_tunnel_session_debug_stats_lock);
-	for (i = 0; i < NSS_MAX_GRE_TUNNEL_SESSIONS; i++) {
-		if (nss_gre_tunnel_session_debug_stats[i].valid) {
-			memcpy(stats, &nss_gre_tunnel_session_debug_stats[i],
-			       sizeof(struct nss_stats_gre_tunnel_session_debug));
-			stats++;
-		}
-	}
-	spin_unlock_bh(&nss_gre_tunnel_session_debug_stats_lock);
-}
-
-/*
  * nss_gre_tunnel_handler()
  *	Handle NSS to HLOS messages for gre_tunnel
  */
@@ -161,7 +77,7 @@
 	 */
 	switch (ngtm->cm.type) {
 	case NSS_GRE_TUNNEL_MSG_STATS:
-		nss_gre_tunnel_session_stats_sync(nss_ctx, &ngtm->msg.stats, ncm->interface);
+		nss_gre_tunnel_stats_session_sync(nss_ctx, &ngtm->msg.stats, ncm->interface);
 		break;
 	}
 
@@ -405,7 +321,7 @@
 
 	BUG_ON(!nss_gre_tunnel_verify_if_num(if_num));
 
-	spin_lock_bh(&nss_gre_tunnel_session_debug_stats_lock);
+	spin_lock_bh(&nss_gre_tunnel_stats_session_debug_lock);
 	for (i = 0; i < NSS_MAX_GRE_TUNNEL_SESSIONS; i++) {
 		if (!nss_gre_tunnel_session_debug_stats[i].valid) {
 			nss_gre_tunnel_session_debug_stats[i].valid = true;
@@ -414,7 +330,7 @@
 			break;
 		}
 	}
-	spin_unlock_bh(&nss_gre_tunnel_session_debug_stats_lock);
+	spin_unlock_bh(&nss_gre_tunnel_stats_session_debug_lock);
 
 	if (i == NSS_MAX_GRE_TUNNEL_SESSIONS) {
 		nss_warning("%p: Cannot find free slot for GRE Tunnel session stats, I/F:%u\n", nss_ctx, if_num);
@@ -433,6 +349,7 @@
 
 	nss_top_main.gre_tunnel_msg_callback = ev_cb;
 	nss_core_register_handler(nss_ctx, if_num, nss_gre_tunnel_handler, app_ctx);
+	nss_gre_tunnel_stats_dentry_create();
 
 	return nss_ctx;
 }
@@ -449,15 +366,15 @@
 
 	BUG_ON(!nss_gre_tunnel_verify_if_num(if_num));
 
-	spin_lock_bh(&nss_gre_tunnel_session_debug_stats_lock);
+	spin_lock_bh(&nss_gre_tunnel_stats_session_debug_lock);
 	for (i = 0; i < NSS_MAX_GRE_TUNNEL_SESSIONS; i++) {
 		if (nss_gre_tunnel_session_debug_stats[i].if_num == if_num) {
 			memset(&nss_gre_tunnel_session_debug_stats[i], 0,
-			       sizeof(struct nss_stats_gre_tunnel_session_debug));
+			       sizeof(struct nss_gre_tunnel_stats_session_debug));
 			break;
 		}
 	}
-	spin_unlock_bh(&nss_gre_tunnel_session_debug_stats_lock);
+	spin_unlock_bh(&nss_gre_tunnel_stats_session_debug_lock);
 
 	if (i == NSS_MAX_GRE_TUNNEL_SESSIONS) {
 		nss_warning("%p: Cannot find debug stats for GRE Tunnel session: %d\n", nss_ctx, if_num);
diff --git a/nss_gre_tunnel_stats.c b/nss_gre_tunnel_stats.c
new file mode 100644
index 0000000..a4fd60e
--- /dev/null
+++ b/nss_gre_tunnel_stats.c
@@ -0,0 +1,220 @@
+/*
+ **************************************************************************
+ * 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"
+#include "nss_gre_tunnel_stats.h"
+
+/*
+ * nss_gre_tunnel_stats_session_debug_str
+ *	GRE Tunnel statistics strings for nss session stats
+ */
+static int8_t *nss_gre_tunnel_stats_session_debug_str[NSS_GRE_TUNNEL_STATS_SESSION_MAX] = {
+	"RX_PKTS",
+	"TX_PKTS",
+	"RX_QUEUE_0_DROPPED",
+	"RX_QUEUE_1_DROPPED",
+	"RX_QUEUE_2_DROPPED",
+	"RX_QUEUE_3_DROPPED",
+	"RX_MALFORMED",
+	"RX_INVALID_PROT",
+	"DECAP_QUEUE_FULL",
+	"RX_SINGLE_REC_DGRAM",
+	"RX_INVALID_REC_DGRAM",
+	"BUFFER_ALLOC_FAIL",
+	"BUFFER_COPY_FAIL",
+	"OUTFLOW_QUEUE_FULL",
+	"TX_DROPPED_HROOM",
+	"RX_CBUFFER_ALLOC_FAIL",
+	"RX_CENQUEUE_FAIL",
+	"RX_DECRYPT_DONE",
+	"RX_FORWARD_ENQUEUE_FAIL",
+	"TX_CBUFFER_ALLOC_FAIL",
+	"TX_CENQUEUE_FAIL",
+	"TX_DROPPED_TROOM",
+	"TX_FORWARD_ENQUEUE_FAIL",
+	"TX_CIPHER_DONE",
+	"CRYPTO_NOSUPP",
+	"RX_DROPPED_MH_VERSION",
+};
+
+/*
+ * nss_gre_tunnel_stats_session_sync()
+ *	Sync function for GRE Tunnel statistics
+ */
+void nss_gre_tunnel_stats_session_sync(struct nss_ctx_instance *nss_ctx, struct nss_gre_tunnel_stats *stats_msg,
+					uint16_t if_num)
+{
+	int i;
+	struct nss_gre_tunnel_stats_session_debug *s = NULL;
+
+	NSS_VERIFY_CTX_MAGIC(nss_ctx);
+
+	spin_lock_bh(&nss_gre_tunnel_stats_session_debug_lock);
+	for (i = 0; i < NSS_MAX_GRE_TUNNEL_SESSIONS; i++) {
+		if (nss_gre_tunnel_session_debug_stats[i].if_num == if_num) {
+			s = &nss_gre_tunnel_session_debug_stats[i];
+			break;
+		}
+	}
+
+	if (!s) {
+		spin_unlock_bh(&nss_gre_tunnel_stats_session_debug_lock);
+		nss_warning("%p: Session not found: %u", nss_ctx, if_num);
+		return;
+	}
+
+	s->stats[NSS_GRE_TUNNEL_STATS_SESSION_RX_PKTS] += stats_msg->node_stats.rx_packets;
+	s->stats[NSS_GRE_TUNNEL_STATS_SESSION_TX_PKTS] += stats_msg->node_stats.tx_packets;
+	for (i = 0; i < NSS_MAX_NUM_PRI; i++) {
+		s->stats[NSS_GRE_TUNNEL_STATS_SESSION_RX_QUEUE_0_DROPPED + i] += stats_msg->node_stats.rx_dropped[i];
+	}
+	s->stats[NSS_GRE_TUNNEL_STATS_SESSION_RX_MALFORMED] += stats_msg->rx_malformed;
+	s->stats[NSS_GRE_TUNNEL_STATS_SESSION_RX_INVALID_PROT] += stats_msg->rx_invalid_prot;
+	s->stats[NSS_GRE_TUNNEL_STATS_SESSION_DECAP_QUEUE_FULL] += stats_msg->decap_queue_full;
+	s->stats[NSS_GRE_TUNNEL_STATS_SESSION_RX_SINGLE_REC_DGRAM] += stats_msg->rx_single_rec_dgram;
+	s->stats[NSS_GRE_TUNNEL_STATS_SESSION_RX_INVALID_REC_DGRAM] += stats_msg->rx_invalid_rec_dgram;
+	s->stats[NSS_GRE_TUNNEL_STATS_SESSION_BUFFER_ALLOC_FAIL] += stats_msg->buffer_alloc_fail;
+	s->stats[NSS_GRE_TUNNEL_STATS_SESSION_BUFFER_COPY_FAIL] += stats_msg->buffer_copy_fail;
+	s->stats[NSS_GRE_TUNNEL_STATS_SESSION_OUTFLOW_QUEUE_FULL] += stats_msg->outflow_queue_full;
+	s->stats[NSS_GRE_TUNNEL_STATS_SESSION_RX_DROPPED_HROOM] += stats_msg->rx_dropped_hroom;
+	s->stats[NSS_GRE_TUNNEL_STATS_SESSION_RX_CBUFFER_ALLOC_FAIL] += stats_msg->rx_cbuf_alloc_fail;
+	s->stats[NSS_GRE_TUNNEL_STATS_SESSION_RX_CENQUEUE_FAIL] += stats_msg->rx_cenqueue_fail;
+	s->stats[NSS_GRE_TUNNEL_STATS_SESSION_RX_DECRYPT_DONE] += stats_msg->rx_decrypt_done;
+	s->stats[NSS_GRE_TUNNEL_STATS_SESSION_RX_FORWARD_ENQUEUE_FAIL] += stats_msg->rx_forward_enqueue_fail;
+	s->stats[NSS_GRE_TUNNEL_STATS_SESSION_TX_CBUFFER_ALLOC_FAIL] += stats_msg->tx_cbuf_alloc_fail;
+	s->stats[NSS_GRE_TUNNEL_STATS_SESSION_TX_CENQUEUE_FAIL] += stats_msg->tx_cenqueue_fail;
+	s->stats[NSS_GRE_TUNNEL_STATS_SESSION_RX_DROPPED_TROOM] += stats_msg->rx_dropped_troom;
+	s->stats[NSS_GRE_TUNNEL_STATS_SESSION_TX_FORWARD_ENQUEUE_FAIL] += stats_msg->tx_forward_enqueue_fail;
+	s->stats[NSS_GRE_TUNNEL_STATS_SESSION_TX_CIPHER_DONE] += stats_msg->tx_cipher_done;
+	s->stats[NSS_GRE_TUNNEL_STATS_SESSION_CRYPTO_NOSUPP] += stats_msg->crypto_nosupp;
+	spin_unlock_bh(&nss_gre_tunnel_stats_session_debug_lock);
+}
+
+/*
+ * nss_gre_tunnel_stats_session_debug_get()
+ *	Get session GRE Tunnel statitics.
+ */
+static void nss_gre_tunnel_stats_session_debug_get(struct nss_gre_tunnel_stats_session_debug *stats)
+{
+	int i;
+
+	if (!stats) {
+		nss_warning("No memory to copy gre_tunnel session stats");
+		return;
+	}
+
+	spin_lock_bh(&nss_gre_tunnel_stats_session_debug_lock);
+	for (i = 0; i < NSS_MAX_GRE_TUNNEL_SESSIONS; i++) {
+		if (nss_gre_tunnel_session_debug_stats[i].valid) {
+			memcpy(stats, &nss_gre_tunnel_session_debug_stats[i],
+				sizeof(struct nss_gre_tunnel_stats_session_debug));
+			stats++;
+		}
+	}
+	spin_unlock_bh(&nss_gre_tunnel_stats_session_debug_lock);
+}
+
+/*
+ * nss_gre_tunnel_stats_read()
+ *	Read GRE Tunnel session statistics
+ */
+static ssize_t nss_gre_tunnel_stats_read(struct file *fp, char __user *ubuf,
+					size_t sz, loff_t *ppos)
+{
+	uint32_t max_output_lines = 2 + (NSS_MAX_GRE_TUNNEL_SESSIONS
+					* (NSS_GRE_TUNNEL_STATS_SESSION_MAX + 2)) + 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;
+	int id, i;
+	struct nss_gre_tunnel_stats_session_debug *gre_tunnel_session_stats = NULL;
+
+	char *lbuf = kzalloc(size_al, GFP_KERNEL);
+	if (unlikely(lbuf == NULL)) {
+		nss_warning("Could not allocate memory for local statistics buffer");
+		return 0;
+	}
+
+	gre_tunnel_session_stats = kzalloc((sizeof(struct nss_gre_tunnel_stats_session_debug)
+						* NSS_MAX_GRE_TUNNEL_SESSIONS), GFP_KERNEL);
+	if (unlikely(gre_tunnel_session_stats == NULL)) {
+		nss_warning("Could not allocate memory for populating GRE Tunnel stats");
+		kfree(lbuf);
+		return 0;
+	}
+
+	/*
+	 * Get all stats
+	 */
+	nss_gre_tunnel_stats_session_debug_get(gre_tunnel_session_stats);
+
+	/*
+	 * Session stats
+	 */
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
+				"\nGRE Tunnel session stats start:\n\n");
+
+	for (id = 0; id < NSS_MAX_GRE_TUNNEL_SESSIONS; id++) {
+		if (!gre_tunnel_session_stats[id].valid)
+			break;
+
+		dev = dev_get_by_index(&init_net, gre_tunnel_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, gre_tunnel_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,
+						gre_tunnel_session_stats[id].if_num);
+		}
+
+		for (i = 0; i < NSS_GRE_TUNNEL_STATS_SESSION_MAX; i++) {
+			size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
+						"\t%s = %llu\n",
+						nss_gre_tunnel_stats_session_debug_str[i],
+						gre_tunnel_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,
+				"\nGRE Tunnel session stats end\n");
+	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, size_wr);
+
+	kfree(gre_tunnel_session_stats);
+	kfree(lbuf);
+	return bytes_read;
+}
+
+/*
+ * nss_gre_tunnel_stats_ops
+ */
+NSS_STATS_DECLARE_FILE_OPERATIONS(gre_tunnel)
+
+/*
+ * nss_gre_tunnel_stats_dentry_create()
+ *	Create gre tunnel statistics debug entry.
+ */
+void nss_gre_tunnel_stats_dentry_create(void)
+{
+	nss_stats_create_dentry("gre_tunnel", &nss_gre_tunnel_stats_ops);
+}
+
diff --git a/nss_gre_tunnel_stats.h b/nss_gre_tunnel_stats.h
index 623f11d..f53eb38 100644
--- a/nss_gre_tunnel_stats.h
+++ b/nss_gre_tunnel_stats.h
@@ -1,6 +1,6 @@
 /*
  ******************************************************************************
- * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 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.
@@ -14,50 +14,62 @@
  * ****************************************************************************
  */
 
+#ifndef __NSS_GRE_TUNNEL_STATS_H
+#define __NSS_GRE_TUNNEL_STATS_H
+
 /*
  * GRE Tunnel session debug statistic counters
  */
-enum nss_stats_gre_tunnel_session {
-	NSS_STATS_GRE_TUNNEL_SESSION_RX_PKTS,
-	NSS_STATS_GRE_TUNNEL_SESSION_TX_PKTS,
-	NSS_STATS_GRE_TUNNEL_SESSION_RX_QUEUE_0_DROPPED,
-	NSS_STATS_GRE_TUNNEL_SESSION_RX_QUEUE_1_DROPPED,
-	NSS_STATS_GRE_TUNNEL_SESSION_RX_QUEUE_2_DROPPED,
-	NSS_STATS_GRE_TUNNEL_SESSION_RX_QUEUE_3_DROPPED,
-	NSS_STATS_GRE_TUNNEL_SESSION_RX_MALFORMED,
-	NSS_STATS_GRE_TUNNEL_SESSION_RX_INVALID_PROT,
-	NSS_STATS_GRE_TUNNEL_SESSION_DECAP_QUEUE_FULL,
-	NSS_STATS_GRE_TUNNEL_SESSION_RX_SINGLE_REC_DGRAM,
-	NSS_STATS_GRE_TUNNEL_SESSION_RX_INVALID_REC_DGRAM,
-	NSS_STATS_GRE_TUNNEL_SESSION_BUFFER_ALLOC_FAIL,
-	NSS_STATS_GRE_TUNNEL_SESSION_BUFFER_COPY_FAIL,
-	NSS_STATS_GRE_TUNNEL_SESSION_OUTFLOW_QUEUE_FULL,
-	NSS_STATS_GRE_TUNNEL_SESSION_RX_DROPPED_HROOM,
-	NSS_STATS_GRE_TUNNEL_SESSION_RX_CBUFFER_ALLOC_FAIL,
-	NSS_STATS_GRE_TUNNEL_SESSION_RX_CENQUEUE_FAIL,
-	NSS_STATS_GRE_TUNNEL_SESSION_RX_DECRYPT_DONE,
-	NSS_STATS_GRE_TUNNEL_SESSION_RX_FORWARD_ENQUEUE_FAIL,
-	NSS_STATS_GRE_TUNNEL_SESSION_TX_CBUFFER_ALLOC_FAIL,
-	NSS_STATS_GRE_TUNNEL_SESSION_TX_CENQUEUE_FAIL,
-	NSS_STATS_GRE_TUNNEL_SESSION_RX_DROPPED_TROOM,
-	NSS_STATS_GRE_TUNNEL_SESSION_TX_FORWARD_ENQUEUE_FAIL,
-	NSS_STATS_GRE_TUNNEL_SESSION_TX_CIPHER_DONE,
-	NSS_STATS_GRE_TUNNEL_SESSION_CRYPTO_NOSUPP,
-	NSS_STATS_GRE_TUNNEL_SESSION_RX_DROPPED_MH_VERSION,
-	NSS_STATS_GRE_TUNNEL_SESSION_MAX,
+enum nss_gre_tunnel_stats_session {
+	NSS_GRE_TUNNEL_STATS_SESSION_RX_PKTS,
+	NSS_GRE_TUNNEL_STATS_SESSION_TX_PKTS,
+	NSS_GRE_TUNNEL_STATS_SESSION_RX_QUEUE_0_DROPPED,
+	NSS_GRE_TUNNEL_STATS_SESSION_RX_QUEUE_1_DROPPED,
+	NSS_GRE_TUNNEL_STATS_SESSION_RX_QUEUE_2_DROPPED,
+	NSS_GRE_TUNNEL_STATS_SESSION_RX_QUEUE_3_DROPPED,
+	NSS_GRE_TUNNEL_STATS_SESSION_RX_MALFORMED,
+	NSS_GRE_TUNNEL_STATS_SESSION_RX_INVALID_PROT,
+	NSS_GRE_TUNNEL_STATS_SESSION_DECAP_QUEUE_FULL,
+	NSS_GRE_TUNNEL_STATS_SESSION_RX_SINGLE_REC_DGRAM,
+	NSS_GRE_TUNNEL_STATS_SESSION_RX_INVALID_REC_DGRAM,
+	NSS_GRE_TUNNEL_STATS_SESSION_BUFFER_ALLOC_FAIL,
+	NSS_GRE_TUNNEL_STATS_SESSION_BUFFER_COPY_FAIL,
+	NSS_GRE_TUNNEL_STATS_SESSION_OUTFLOW_QUEUE_FULL,
+	NSS_GRE_TUNNEL_STATS_SESSION_RX_DROPPED_HROOM,
+	NSS_GRE_TUNNEL_STATS_SESSION_RX_CBUFFER_ALLOC_FAIL,
+	NSS_GRE_TUNNEL_STATS_SESSION_RX_CENQUEUE_FAIL,
+	NSS_GRE_TUNNEL_STATS_SESSION_RX_DECRYPT_DONE,
+	NSS_GRE_TUNNEL_STATS_SESSION_RX_FORWARD_ENQUEUE_FAIL,
+	NSS_GRE_TUNNEL_STATS_SESSION_TX_CBUFFER_ALLOC_FAIL,
+	NSS_GRE_TUNNEL_STATS_SESSION_TX_CENQUEUE_FAIL,
+	NSS_GRE_TUNNEL_STATS_SESSION_RX_DROPPED_TROOM,
+	NSS_GRE_TUNNEL_STATS_SESSION_TX_FORWARD_ENQUEUE_FAIL,
+	NSS_GRE_TUNNEL_STATS_SESSION_TX_CIPHER_DONE,
+	NSS_GRE_TUNNEL_STATS_SESSION_CRYPTO_NOSUPP,
+	NSS_GRE_TUNNEL_STATS_SESSION_RX_DROPPED_MH_VERSION,
+	NSS_GRE_TUNNEL_STATS_SESSION_MAX,
 };
 
 /*
  * GRE Tunnel session debug statistics
  */
-struct nss_stats_gre_tunnel_session_debug {
-	uint64_t stats[NSS_STATS_GRE_TUNNEL_SESSION_MAX];
+struct nss_gre_tunnel_stats_session_debug {
+	uint64_t stats[NSS_GRE_TUNNEL_STATS_SESSION_MAX];
 	int32_t if_index;
 	uint32_t if_num; /* nss interface number */
 	bool valid;
 };
 
 /*
- * Stats APIs provided by nss_gre_tunnel.c
+ * Data structures to store GRE Tunnel nss debug stats
  */
-extern void nss_gre_tunnel_session_debug_stats_get(struct nss_stats_gre_tunnel_session_debug *s);
+static DEFINE_SPINLOCK(nss_gre_tunnel_stats_session_debug_lock);
+static struct nss_gre_tunnel_stats_session_debug nss_gre_tunnel_session_debug_stats[NSS_MAX_GRE_TUNNEL_SESSIONS];
+
+/*
+ * GRE Tunnel statistics APIs
+ */
+extern void nss_gre_tunnel_stats_session_sync(struct nss_ctx_instance *nss_ctx, struct nss_gre_tunnel_stats *stats_msg, uint16_t if_num);
+extern void nss_gre_tunnel_stats_dentry_create(void);
+
+#endif /* __NSS_GRE_TUNNEL_STATS_H */
diff --git a/nss_hlos_if.h b/nss_hlos_if.h
index 401f12e..72a9896 100644
--- a/nss_hlos_if.h
+++ b/nss_hlos_if.h
@@ -48,52 +48,6 @@
 };
 
 /*
- * ETH_RX
-*/
-
-/*
- * Request/Response types
- */
-enum nss_eth_rx_metadata_types {
-	NSS_RX_METADATA_TYPE_ETH_RX_STATS_SYNC,
-	NSS_METADATA_TYPE_ETH_RX_MAX,
-};
-
-/*
- * Exception events from bridge/route handler
- */
-enum exception_events_eth_rx {
-	NSS_EXCEPTION_EVENT_ETH_RX_UNKNOWN_L3_PROTOCOL,
-	NSS_EXCEPTION_EVENT_ETH_RX_ETH_HDR_MISSING,
-	NSS_EXCEPTION_EVENT_ETH_RX_VLAN_MISSING,
-	NSS_EXCEPTION_EVENT_ETH_RX_TRUSTSEC_HDR_MISSING,
-	NSS_EXCEPTION_EVENT_ETH_RX_MAX,
-};
-
-/*
- * The NSS eth_rx node stats structure.
- */
-struct nss_eth_rx_node_sync {
-	struct nss_cmn_node_stats node_stats;
-				/* Common node stats for ETH_RX */
-	uint32_t total_ticks;		/* Total clock ticks spend inside the eth_rx */
-	uint32_t worst_case_ticks;	/* Worst case iteration of the eth_rx in ticks */
-	uint32_t iterations;		/* Number of iterations around the eth_rx */
-	uint32_t exception_events[NSS_EXCEPTION_EVENT_ETH_RX_MAX];
-				/* Number of ETH_RX exception events */
-};
-
-/*
- * Message structure to send/receive eth_rx commands
- */
-struct nss_eth_rx_msg {
-	struct nss_cmn_msg cm;		/* Message Header */
-	union {
-		struct nss_eth_rx_node_sync node_sync;	/* Message: node statistics sync */
-	} msg;
-};
-
-/*
  * C2C message structures
  */
 
@@ -261,44 +215,6 @@
 };
 
 /*
- * lso_rx_node statistics.
- */
-struct nss_lso_rx_stats_sync {
-	struct nss_cmn_node_stats node_stats;
-
-	uint32_t tx_dropped;				/* Number of packets dropped because lso_rx transmit queue is full */
-	uint32_t dropped;				/* Total of packets dropped by the node internally */
-	uint32_t pbuf_alloc_fail;			/* Count number of pbuf alloc fails */
-	uint32_t pbuf_reference_fail;			/* Count number of pbuf ref fails */
-
-	/*
-	 * If we're generating per-packet statistics then we count total lso_rx processing ticks
-	 * worst-case ticks and the number of iterations around the lso_rx handler that we take.
-	 */
-	uint32_t total_ticks;			/* Total clock ticks spend inside the lso_rx handler */
-	uint32_t worst_case_ticks;
-						/* Worst case iteration of the lso_rx handler in ticks */
-	uint32_t iterations;			/* Number of iterations around the lso_rx handler */
-};
-
-/*
- * Message types for lso_rx
- */
-enum nss_lso_rx_metadata_types {
-	NSS_LSO_RX_STATS_SYNC_MSG,			/* Message type - stats sync message */
-};
-
-/*
- * Message structure to send receive LSO_RX commands
- */
-struct nss_lso_rx_msg {
-	struct nss_cmn_msg cm;					/* Message header */
-	union {
-		struct nss_lso_rx_stats_sync stats_sync;	/* Stats sub-message */
-	} msg;
-};
-
-/*
  * H2N Buffer Types
  */
 #define H2N_BUFFER_EMPTY			0
diff --git a/nss_ipv4.c b/nss_ipv4.c
index e6dfe1a..6126dcb 100644
--- a/nss_ipv4.c
+++ b/nss_ipv4.c
@@ -21,6 +21,7 @@
 #include <linux/sysctl.h>
 #include "nss_tx_rx_common.h"
 #include "nss_dscp_map.h"
+#include "nss_ipv4_stats.h"
 
 #define NSS_IPV4_TX_MSG_TIMEOUT 1000	/* 1 sec timeout for IPv4 messages */
 
@@ -69,92 +70,6 @@
 }
 
 /*
- * nss_ipv4_driver_conn_sync_update()
- *	Update driver specific information from the messsage.
- */
-static void nss_ipv4_driver_conn_sync_update(struct nss_ctx_instance *nss_ctx, struct nss_ipv4_conn_sync *nirs)
-{
-	struct nss_top_instance *nss_top = nss_ctx->nss_top;
-
-	/*
-	 * Update statistics maintained by NSS driver
-	 */
-	spin_lock_bh(&nss_top->stats_lock);
-	nss_top->stats_ipv4[NSS_STATS_IPV4_ACCELERATED_RX_PKTS] += nirs->flow_rx_packet_count + nirs->return_rx_packet_count;
-	nss_top->stats_ipv4[NSS_STATS_IPV4_ACCELERATED_RX_BYTES] += nirs->flow_rx_byte_count + nirs->return_rx_byte_count;
-	nss_top->stats_ipv4[NSS_STATS_IPV4_ACCELERATED_TX_PKTS] += nirs->flow_tx_packet_count + nirs->return_tx_packet_count;
-	nss_top->stats_ipv4[NSS_STATS_IPV4_ACCELERATED_TX_BYTES] += nirs->flow_tx_byte_count + nirs->return_tx_byte_count;
-	spin_unlock_bh(&nss_top->stats_lock);
-}
-
-/*
- * nss_ipv4_driver_conn_sync_many_update()
- *	Update driver specific information from the conn_sync_many messsage.
- */
-static void nss_ipv4_driver_conn_sync_many_update(struct nss_ctx_instance *nss_ctx, struct nss_ipv4_conn_sync_many_msg *nicsm)
-{
-	int i;
-
-	/*
-	 * Sanity check for the stats count
-	 */
-	if (nicsm->count * sizeof(struct nss_ipv4_conn_sync) >= nicsm->size) {
-		nss_warning("%p: stats sync count %u exceeds the size of this msg %u", nss_ctx, nicsm->count, nicsm->size);
-		return;
-	}
-
-	for (i = 0; i < nicsm->count; i++) {
-		nss_ipv4_driver_conn_sync_update(nss_ctx, &nicsm->conn_sync[i]);
-	}
-}
-
-/*
- * nss_ipv4_driver_node_sync_update)
- *	Update driver specific information from the messsage.
- */
-static void nss_ipv4_driver_node_sync_update(struct nss_ctx_instance *nss_ctx, struct nss_ipv4_node_sync *nins)
-{
-	struct nss_top_instance *nss_top = nss_ctx->nss_top;
-	int i;
-
-	/*
-	 * Update statistics maintained by NSS driver
-	 */
-	spin_lock_bh(&nss_top->stats_lock);
-	nss_top->stats_node[NSS_IPV4_RX_INTERFACE][NSS_STATS_NODE_RX_PKTS] += nins->node_stats.rx_packets;
-	nss_top->stats_node[NSS_IPV4_RX_INTERFACE][NSS_STATS_NODE_RX_BYTES] += nins->node_stats.rx_bytes;
-	nss_top->stats_node[NSS_IPV4_RX_INTERFACE][NSS_STATS_NODE_TX_PKTS] += nins->node_stats.tx_packets;
-	nss_top->stats_node[NSS_IPV4_RX_INTERFACE][NSS_STATS_NODE_TX_BYTES] += nins->node_stats.tx_bytes;
-
-	for (i = 0; i < NSS_MAX_NUM_PRI; i++) {
-		nss_top->stats_node[NSS_IPV4_RX_INTERFACE][NSS_STATS_NODE_RX_QUEUE_0_DROPPED + i] += nins->node_stats.rx_dropped[i];
-	}
-
-	nss_top->stats_ipv4[NSS_STATS_IPV4_CONNECTION_CREATE_REQUESTS] += nins->ipv4_connection_create_requests;
-	nss_top->stats_ipv4[NSS_STATS_IPV4_CONNECTION_CREATE_COLLISIONS] += nins->ipv4_connection_create_collisions;
-	nss_top->stats_ipv4[NSS_STATS_IPV4_CONNECTION_CREATE_INVALID_INTERFACE] += nins->ipv4_connection_create_invalid_interface;
-	nss_top->stats_ipv4[NSS_STATS_IPV4_CONNECTION_DESTROY_REQUESTS] += nins->ipv4_connection_destroy_requests;
-	nss_top->stats_ipv4[NSS_STATS_IPV4_CONNECTION_DESTROY_MISSES] += nins->ipv4_connection_destroy_misses;
-	nss_top->stats_ipv4[NSS_STATS_IPV4_CONNECTION_HASH_HITS] += nins->ipv4_connection_hash_hits;
-	nss_top->stats_ipv4[NSS_STATS_IPV4_CONNECTION_HASH_REORDERS] += nins->ipv4_connection_hash_reorders;
-	nss_top->stats_ipv4[NSS_STATS_IPV4_CONNECTION_FLUSHES] += nins->ipv4_connection_flushes;
-	nss_top->stats_ipv4[NSS_STATS_IPV4_CONNECTION_EVICTIONS] += nins->ipv4_connection_evictions;
-	nss_top->stats_ipv4[NSS_STATS_IPV4_FRAGMENTATIONS] += nins->ipv4_fragmentations;
-	nss_top->stats_ipv4[NSS_STATS_IPV4_MC_CONNECTION_CREATE_REQUESTS] += nins->ipv4_mc_connection_create_requests;
-	nss_top->stats_ipv4[NSS_STATS_IPV4_MC_CONNECTION_UPDATE_REQUESTS] += nins->ipv4_mc_connection_update_requests;
-	nss_top->stats_ipv4[NSS_STATS_IPV4_MC_CONNECTION_CREATE_INVALID_INTERFACE] += nins->ipv4_mc_connection_create_invalid_interface;
-	nss_top->stats_ipv4[NSS_STATS_IPV4_MC_CONNECTION_DESTROY_REQUESTS] += nins->ipv4_mc_connection_destroy_requests;
-	nss_top->stats_ipv4[NSS_STATS_IPV4_MC_CONNECTION_DESTROY_MISSES] += nins->ipv4_mc_connection_destroy_misses;
-	nss_top->stats_ipv4[NSS_STATS_IPV4_MC_CONNECTION_FLUSHES] += nins->ipv4_mc_connection_flushes;
-	nss_top->stats_ipv4[NSS_STATS_IPV4_DROPPED_BY_RULE] += nins->ipv4_dropped_by_rule;
-
-	for (i = 0; i < NSS_EXCEPTION_EVENT_IPV4_MAX; i++) {
-		 nss_top->stats_if_exception_ipv4[i] += nins->exception_events[i];
-	}
-	spin_unlock_bh(&nss_top->stats_lock);
-}
-
-/*
  * nss_ipv4_rx_msg_handler()
  *	Handle NSS -> HLOS messages for IPv4 bridge/route
  */
@@ -188,21 +103,21 @@
 		/*
 		* Update driver statistics on node sync.
 		*/
-		nss_ipv4_driver_node_sync_update(nss_ctx, &nim->msg.node_stats);
+		nss_ipv4_stats_node_sync(nss_ctx, &nim->msg.node_stats);
 		break;
 
 	case NSS_IPV4_RX_CONN_STATS_SYNC_MSG:
 		/*
 		 * Update driver statistics on connection sync.
 		 */
-		nss_ipv4_driver_conn_sync_update(nss_ctx, &nim->msg.conn_stats);
+		nss_ipv4_stats_conn_sync(nss_ctx, &nim->msg.conn_stats);
 		break;
 
 	case NSS_IPV4_TX_CONN_STATS_SYNC_MANY_MSG:
 		/*
 		 * Update driver statistics on connection sync many.
 		 */
-		nss_ipv4_driver_conn_sync_many_update(nss_ctx, &nim->msg.conn_stats_many);
+		nss_ipv4_stats_conn_sync_many(nss_ctx, &nim->msg.conn_stats_many);
 		ncm->cb = (nss_ptr_t)nss_ipv4_conn_sync_many_msg_cb;
 		break;
 	}
@@ -507,6 +422,8 @@
 	if (nss_core_register_handler(nss_ctx, NSS_IPV4_RX_INTERFACE, nss_ipv4_rx_msg_handler, NULL) != NSS_CORE_STATUS_SUCCESS) {
 		nss_warning("IPv4 handler failed to register");
 	}
+
+	nss_ipv4_stats_dentry_create();
 }
 
 /*
diff --git a/nss_ipv4_reasm.c b/nss_ipv4_reasm.c
index 80a230f..6837544 100644
--- a/nss_ipv4_reasm.c
+++ b/nss_ipv4_reasm.c
@@ -1,6 +1,6 @@
 /*
  **************************************************************************
- * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014, 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.
@@ -19,39 +19,8 @@
  *	NSS IPv4 Reassembly APIs
  */
 #include "nss_tx_rx_common.h"
-
-/*
- * nss_ipv4_reasm_stats_sync()
- *	Update driver specific information from the messsage.
- */
-static void nss_ipv4_reasm_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_ipv4_reasm_stats_sync *nirs)
-{
-	int i;
-	struct nss_top_instance *nss_top = nss_ctx->nss_top;
-
-	spin_lock_bh(&nss_top->stats_lock);
-
-	/*
-	 * Common node stats
-	 */
-	nss_top->stats_node[NSS_IPV4_REASM_INTERFACE][NSS_STATS_NODE_RX_PKTS] += nirs->node_stats.rx_packets;
-	nss_top->stats_node[NSS_IPV4_REASM_INTERFACE][NSS_STATS_NODE_RX_BYTES] += nirs->node_stats.rx_bytes;
-	nss_top->stats_node[NSS_IPV4_REASM_INTERFACE][NSS_STATS_NODE_TX_PKTS] += nirs->node_stats.tx_packets;
-	nss_top->stats_node[NSS_IPV4_REASM_INTERFACE][NSS_STATS_NODE_TX_BYTES] += nirs->node_stats.tx_bytes;
-
-	for (i = 0; i < NSS_MAX_NUM_PRI; i++) {
-		nss_top->stats_node[NSS_IPV4_REASM_INTERFACE][NSS_STATS_NODE_RX_QUEUE_0_DROPPED + i] += nirs->node_stats.rx_dropped[0];
-	}
-
-	/*
-	 * IPv4 reasm node stats
-	 */
-	nss_top->stats_ipv4_reasm[NSS_STATS_IPV4_REASM_EVICTIONS] += nirs->ipv4_reasm_evictions;
-	nss_top->stats_ipv4_reasm[NSS_STATS_IPV4_REASM_ALLOC_FAILS] += nirs->ipv4_reasm_alloc_fails;
-	nss_top->stats_ipv4_reasm[NSS_STATS_IPV4_REASM_TIMEOUTS] += nirs->ipv4_reasm_timeouts;
-
-	spin_unlock_bh(&nss_top->stats_lock);
-}
+#include "nss_stats.h"
+#include "nss_ipv4_reasm_stats.h"
 
 /*
  * nss_ipv4_reasm_msg_handler()
@@ -99,4 +68,6 @@
 	if (nss_core_register_handler(nss_ctx, NSS_IPV4_REASM_INTERFACE, nss_ipv4_reasm_msg_handler, NULL) != NSS_CORE_STATUS_SUCCESS) {
 		nss_warning("IPv4 reasm handler failed to register");
 	}
+
+	nss_ipv4_reasm_stats_dentry_create();
 }
diff --git a/nss_ipv4_reasm_stats.c b/nss_ipv4_reasm_stats.c
new file mode 100644
index 0000000..7d2791f
--- /dev/null
+++ b/nss_ipv4_reasm_stats.c
@@ -0,0 +1,135 @@
+/*
+ **************************************************************************
+ * 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_stats.h"
+#include "nss_core.h"
+#include "nss_ipv4_reasm_stats.h"
+
+/*
+ * IPv4 reassembly stats strings
+ */
+static int8_t *nss_ipv4_reasm_stats_str[NSS_IPV4_REASM_STATS_MAX] = {
+	"evictions",
+	"alloc_fails",
+	"timeouts",
+};
+
+uint64_t nss_ipv4_reasm_stats[NSS_IPV4_REASM_STATS_MAX]; /* IPv4 reasm statistics */
+
+/*
+ * nss_ipv4_reasm_stats_read()
+ *	Read IPV4 reassembly stats
+ */
+static ssize_t nss_ipv4_reasm_stats_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
+{
+	int32_t i;
+	/*
+	 * max output lines = #stats + start tag line + end tag line + three blank lines
+	 */
+	uint32_t max_output_lines = (NSS_STATS_NODE_MAX + 2) + (NSS_IPV4_REASM_STATS_MAX + 3) + 5;
+	size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
+	size_t size_wr = 0;
+	ssize_t bytes_read = 0;
+	uint64_t *stats_shadow;
+
+	char *lbuf = kzalloc(size_al, GFP_KERNEL);
+	if (unlikely(lbuf == NULL)) {
+		nss_warning("Could not allocate memory for local statistics buffer");
+		return 0;
+	}
+
+	stats_shadow = kzalloc(NSS_IPV4_REASM_STATS_MAX * 8, GFP_KERNEL);
+	if (unlikely(stats_shadow == NULL)) {
+		nss_warning("Could not allocate memory for local shadow buffer");
+		kfree(lbuf);
+		return 0;
+	}
+
+	size_wr = scnprintf(lbuf, size_al, "ipv4 reasm stats start:\n\n");
+
+	size_wr = nss_stats_fill_common_stats(NSS_IPV4_REASM_INTERFACE, lbuf, size_wr, size_al);
+
+	/*
+	 * IPv4 reasm node stats
+	 */
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nipv4 reasm node stats:\n\n");
+
+	spin_lock_bh(&nss_top_main.stats_lock);
+	for (i = 0; (i < NSS_IPV4_REASM_STATS_MAX); i++) {
+		stats_shadow[i] = nss_ipv4_reasm_stats[i];
+	}
+
+	spin_unlock_bh(&nss_top_main.stats_lock);
+
+	for (i = 0; (i < NSS_IPV4_REASM_STATS_MAX); i++) {
+		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
+					"%s = %llu\n", nss_ipv4_reasm_stats_str[i], stats_shadow[i]);
+	}
+
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nipv4 reasm stats end\n\n");
+	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
+	kfree(lbuf);
+	kfree(stats_shadow);
+
+	return bytes_read;
+}
+
+/*
+ * nss_ipv4_reasm_stats_ops
+ */
+NSS_STATS_DECLARE_FILE_OPERATIONS(ipv4_reasm)
+
+/*
+ * nss_ipv4_reasm_stats_dentry_create()
+ *	Create the IPv4 reasm statistics debug entry
+ */
+void nss_ipv4_reasm_stats_dentry_create(void)
+{
+	nss_stats_create_dentry("ipv4_reasm", &nss_ipv4_reasm_stats_ops);
+}
+
+/*
+ * nss_ipv4_reasm_stats_sync()
+ *	Update driver specific information from the messsage.
+ */
+void nss_ipv4_reasm_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_ipv4_reasm_stats_sync *nirs)
+{
+	int i;
+	struct nss_top_instance *nss_top = nss_ctx->nss_top;
+
+	spin_lock_bh(&nss_top->stats_lock);
+
+	/*
+	 * Common node stats
+	 */
+	nss_top->stats_node[NSS_IPV4_REASM_INTERFACE][NSS_STATS_NODE_RX_PKTS] += nirs->node_stats.rx_packets;
+	nss_top->stats_node[NSS_IPV4_REASM_INTERFACE][NSS_STATS_NODE_RX_BYTES] += nirs->node_stats.rx_bytes;
+	nss_top->stats_node[NSS_IPV4_REASM_INTERFACE][NSS_STATS_NODE_TX_PKTS] += nirs->node_stats.tx_packets;
+	nss_top->stats_node[NSS_IPV4_REASM_INTERFACE][NSS_STATS_NODE_TX_BYTES] += nirs->node_stats.tx_bytes;
+
+	for (i = 0; i < NSS_MAX_NUM_PRI; i++) {
+		nss_top->stats_node[NSS_IPV4_REASM_INTERFACE][NSS_STATS_NODE_RX_QUEUE_0_DROPPED + i] += nirs->node_stats.rx_dropped[i];
+	}
+
+	/*
+	 * IPv4 reasm node stats
+	 */
+	nss_ipv4_reasm_stats[NSS_IPV4_REASM_STATS_EVICTIONS] += nirs->ipv4_reasm_evictions;
+	nss_ipv4_reasm_stats[NSS_IPV4_REASM_STATS_ALLOC_FAILS] += nirs->ipv4_reasm_alloc_fails;
+	nss_ipv4_reasm_stats[NSS_IPV4_REASM_STATS_TIMEOUTS] += nirs->ipv4_reasm_timeouts;
+
+	spin_unlock_bh(&nss_top->stats_lock);
+}
diff --git a/nss_ipv4_reasm_stats.h b/nss_ipv4_reasm_stats.h
new file mode 100644
index 0000000..73bb031
--- /dev/null
+++ b/nss_ipv4_reasm_stats.h
@@ -0,0 +1,39 @@
+/*
+ **************************************************************************
+ * 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.
+ **************************************************************************
+ */
+
+#ifndef __NSS_IPV4_REASM_STATS_H
+#define __NSS_IPV4_REASM_STATS_H
+
+/*
+ * IPV4 reasm node statistics
+ */
+enum nss_ipv4_reasm_stats_types {
+	NSS_IPV4_REASM_STATS_EVICTIONS = 0,
+					/* Number of evicted fragment queues due to set memory threshold */
+	NSS_IPV4_REASM_STATS_ALLOC_FAILS,
+					/* Number of fragment queue allocation failures */
+	NSS_IPV4_REASM_STATS_TIMEOUTS,
+					/* Number of expired fragment queues */
+	NSS_IPV4_REASM_STATS_MAX,
+};
+
+/*
+ * IPV4 reasm statistics APIs
+ */
+extern void nss_ipv4_reasm_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_ipv4_reasm_stats_sync *nirs);
+extern void nss_ipv4_reasm_stats_dentry_create(void);
+
+#endif /* __NSS_IPV4_REASM_STATS_H */
diff --git a/nss_ipv4_stats.c b/nss_ipv4_stats.c
new file mode 100644
index 0000000..7317f6a
--- /dev/null
+++ b/nss_ipv4_stats.c
@@ -0,0 +1,313 @@
+/*
+ **************************************************************************
+ * Copyright (c) 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.
+ * 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_stats.h"
+#include "nss_core.h"
+#include <nss_ipv4.h>
+#include "nss_ipv4_stats.h"
+
+/*
+ * nss_ipv4_exception_stats_str
+ *	Interface stats strings for ipv4 exceptions
+ */
+static int8_t *nss_ipv4_exception_stats_str[NSS_IPV4_EXCEPTION_EVENT_MAX] = {
+	"IPV4_ICMP_HEADER_INCOMPLETE",
+	"IPV4_ICMP_UNHANDLED_TYPE",
+	"IPV4_ICMP_IPV4_HEADER_INCOMPLETE",
+	"IPV4_ICMP_IPV4_UDP_HEADER_INCOMPLETE",
+	"IPV4_ICMP_IPV4_TCP_HEADER_INCOMPLETE",
+	"IPV4_ICMP_SIPV4_UNKNOWN_PROTOCOL",
+	"IPV4_ICMP_NO_ICME",
+	"IPV4_ICMP_FLUSH_TO_HOST",
+	"IPV4_TCP_HEADER_INCOMPLETE",
+	"IPV4_TCP_NO_ICME",
+	"IPV4_TCP_IP_OPTION",
+	"IPV4_TCP_IP_FRAGMENT",
+	"IPV4_TCP_SMALL_TTL",
+	"IPV4_TCP_NEEDS_FRAGMENTATION",
+	"IPV4_TCP_FLAGS",
+	"IPV4_TCP_SEQ_EXCEEDS_RIGHT_EDGE",
+	"IPV4_TCP_SMALL_DATA_OFFS",
+	"IPV4_TCP_BAD_SACK",
+	"IPV4_TCP_BIG_DATA_OFFS",
+	"IPV4_TCP_SEQ_BEFORE_LEFT_EDGE",
+	"IPV4_TCP_ACK_EXCEEDS_RIGHT_EDGE",
+	"IPV4_TCP_ACK_BEFORE_LEFT_EDGE",
+	"IPV4_UDP_HEADER_INCOMPLETE",
+	"IPV4_UDP_NO_ICME",
+	"IPV4_UDP_IP_OPTION",
+	"IPV4_UDP_IP_FRAGMENT",
+	"IPV4_UDP_SMALL_TTL",
+	"IPV4_UDP_NEEDS_FRAGMENTATION",
+	"IPV4_WRONG_TARGET_MAC",
+	"IPV4_HEADER_INCOMPLETE",
+	"IPV4_BAD_TOTAL_LENGTH",
+	"IPV4_BAD_CHECKSUM",
+	"IPV4_NON_INITIAL_FRAGMENT",
+	"IPV4_DATAGRAM_INCOMPLETE",
+	"IPV4_OPTIONS_INCOMPLETE",
+	"IPV4_UNKNOWN_PROTOCOL",
+	"IPV4_ESP_HEADER_INCOMPLETE",
+	"IPV4_ESP_NO_ICME",
+	"IPV4_ESP_IP_OPTION",
+	"IPV4_ESP_IP_FRAGMENT",
+	"IPV4_ESP_SMALL_TTL",
+	"IPV4_ESP_NEEDS_FRAGMENTATION",
+	"IPV4_INGRESS_VID_MISMATCH",
+	"IPV4_INGRESS_VID_MISSING",
+	"IPV4_6RD_NO_ICME",
+	"IPV4_6RD_IP_OPTION",
+	"IPV4_6RD_IP_FRAGMENT",
+	"IPV4_6RD_NEEDS_FRAGMENTATION",
+	"IPV4_DSCP_MARKING_MISMATCH",
+	"IPV4_VLAN_MARKING_MISMATCH",
+	"IPV4_DEPRECATED",
+	"IPV4_GRE_HEADER_INCOMPLETE",
+	"IPV4_GRE_NO_ICME",
+	"IPV4_GRE_IP_OPTION",
+	"IPV4_GRE_IP_FRAGMENT",
+	"IPV4_GRE_SMALL_TTL",
+	"IPV4_GRE_NEEDS_FRAGMENTATION",
+	"IPV4_PPTP_GRE_SESSION_MATCH_FAIL",
+	"IPV4_PPTP_GRE_INVALID_PROTO",
+	"IPV4_PPTP_GRE_NO_CME",
+	"IPV4_PPTP_GRE_IP_OPTION",
+	"IPV4_PPTP_GRE_IP_FRAGMENT",
+	"IPV4_PPTP_GRE_SMALL_TTL",
+	"IPV4_PPTP_GRE_NEEDS_FRAGMENTATION",
+	"IPV4_DESTROY",
+	"IPV4_FRAG_DF_SET",
+	"IPV4_FRAG_FAIL",
+	"IPV4_ICMP_IPV4_UDPLITE_HEADER_INCOMPLETE",
+	"IPV4_UDPLITE_HEADER_INCOMPLETE",
+	"IPV4_UDPLITE_NO_ICME",
+	"IPV4_UDPLITE_IP_OPTION",
+	"IPV4_UDPLITE_IP_FRAGMENT",
+	"IPV4_UDPLITE_SMALL_TTL",
+	"IPV4_UDPLITE_NEEDS_FRAGMENTATION",
+	"IPV4_MC_UDP_NO_ICME",
+	"IPV4_MC_MEM_ALLOC_FAILURE",
+	"IPV4_MC_UPDATE_FAILURE",
+	"IPV4_MC_PBUF_ALLOC_FAILURE"
+};
+
+uint64_t nss_ipv4_stats[NSS_IPV4_STATS_MAX];
+uint64_t nss_ipv4_exception_stats[NSS_IPV4_EXCEPTION_EVENT_MAX];
+
+/*
+ * nss_ipv4_stats_str
+ *	IPv4 stats strings
+ */
+static int8_t *nss_ipv4_stats_str[NSS_IPV4_STATS_MAX] = {
+	"rx_pkts",
+	"rx_bytes",
+	"tx_pkts",
+	"tx_bytes",
+	"create_requests",
+	"create_collisions",
+	"create_invalid_interface",
+	"destroy_requests",
+	"destroy_misses",
+	"hash_hits",
+	"hash_reorders",
+	"flushes",
+	"evictions",
+	"fragmentations",
+	"by_rule_drops",
+	"mc_create_requests",
+	"mc_update_requests",
+	"mc_create_invalid_interface",
+	"mc_destroy_requests",
+	"mc_destroy_misses",
+	"mc_flushes",
+};
+
+/*
+ * nss_ipv4_stats_read()
+ *	Read IPV4 stats
+ */
+static ssize_t nss_ipv4_stats_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
+{
+	int32_t i;
+	/*
+	 * max output lines = #stats + start tag line + end tag line + three blank lines
+	 */
+	uint32_t max_output_lines = (NSS_STATS_NODE_MAX + 2) + (NSS_IPV4_STATS_MAX + 3) + (NSS_IPV4_EXCEPTION_EVENT_MAX + 3) + 5;
+	size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
+	size_t size_wr = 0;
+	ssize_t bytes_read = 0;
+	uint64_t *stats_shadow;
+
+	char *lbuf = kzalloc(size_al, GFP_KERNEL);
+	if (unlikely(lbuf == NULL)) {
+		nss_warning("Could not allocate memory for local statistics buffer");
+		return 0;
+	}
+
+	/*
+	 * Note: The assumption here is that exception event count is larger than other statistics count for IPv4
+	 */
+	stats_shadow = kzalloc(NSS_IPV4_EXCEPTION_EVENT_MAX * 8, GFP_KERNEL);
+	if (unlikely(stats_shadow == NULL)) {
+		nss_warning("Could not allocate memory for local shadow buffer");
+		kfree(lbuf);
+		return 0;
+	}
+
+	size_wr = scnprintf(lbuf, size_al, "ipv4 stats start:\n\n");
+
+	size_wr = nss_stats_fill_common_stats(NSS_IPV4_RX_INTERFACE, lbuf, size_wr, size_al);
+
+	/*
+	 * IPv4 node stats
+	 */
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nipv4 node stats:\n\n");
+
+	spin_lock_bh(&nss_top_main.stats_lock);
+	for (i = 0; (i < NSS_IPV4_STATS_MAX); i++) {
+		stats_shadow[i] = nss_ipv4_stats[i];
+	}
+
+	spin_unlock_bh(&nss_top_main.stats_lock);
+
+	for (i = 0; (i < NSS_IPV4_STATS_MAX); i++) {
+		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
+					"%s = %llu\n", nss_ipv4_stats_str[i], stats_shadow[i]);
+	}
+
+	/*
+	 * Exception stats
+	 */
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nipv4 exception stats:\n\n");
+
+	spin_lock_bh(&nss_top_main.stats_lock);
+	for (i = 0; (i < NSS_IPV4_EXCEPTION_EVENT_MAX); i++) {
+		stats_shadow[i] = nss_ipv4_exception_stats[i];
+	}
+
+	spin_unlock_bh(&nss_top_main.stats_lock);
+
+	for (i = 0; (i < NSS_IPV4_EXCEPTION_EVENT_MAX); i++) {
+		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
+					"%s = %llu\n", nss_ipv4_exception_stats_str[i], stats_shadow[i]);
+	}
+
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nipv4 stats end\n\n");
+	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
+	kfree(lbuf);
+	kfree(stats_shadow);
+
+	return bytes_read;
+}
+
+/*
+ * nss_ipv4_stats_conn_sync()
+ *	Update driver specific information from the messsage.
+ */
+void nss_ipv4_stats_conn_sync(struct nss_ctx_instance *nss_ctx, struct nss_ipv4_conn_sync *nirs)
+{
+	struct nss_top_instance *nss_top = nss_ctx->nss_top;
+
+	/*
+	 * Update statistics maintained by NSS driver
+	 */
+	spin_lock_bh(&nss_top->stats_lock);
+	nss_ipv4_stats[NSS_IPV4_STATS_ACCELERATED_RX_PKTS] += nirs->flow_rx_packet_count + nirs->return_rx_packet_count;
+	nss_ipv4_stats[NSS_IPV4_STATS_ACCELERATED_RX_BYTES] += nirs->flow_rx_byte_count + nirs->return_rx_byte_count;
+	nss_ipv4_stats[NSS_IPV4_STATS_ACCELERATED_TX_PKTS] += nirs->flow_tx_packet_count + nirs->return_tx_packet_count;
+	nss_ipv4_stats[NSS_IPV4_STATS_ACCELERATED_TX_BYTES] += nirs->flow_tx_byte_count + nirs->return_tx_byte_count;
+	spin_unlock_bh(&nss_top->stats_lock);
+}
+
+/*
+ * nss_ipv4_stats_conn_sync_many()
+ *	Update driver specific information from the conn_sync_many messsage.
+ */
+void nss_ipv4_stats_conn_sync_many(struct nss_ctx_instance *nss_ctx, struct nss_ipv4_conn_sync_many_msg *nicsm)
+{
+	int i;
+
+	/*
+	 * Sanity check for the stats count
+	 */
+	if (nicsm->count * sizeof(struct nss_ipv4_conn_sync) >= nicsm->size) {
+		nss_warning("%p: stats sync count %u exceeds the size of this msg %u", nss_ctx, nicsm->count, nicsm->size);
+		return;
+	}
+
+	for (i = 0; i < nicsm->count; i++) {
+		nss_ipv4_stats_conn_sync(nss_ctx, &nicsm->conn_sync[i]);
+	}
+}
+
+/*
+ * nss_ipv4_stats_node_sync()
+ *	Update driver specific information from the messsage.
+ */
+void nss_ipv4_stats_node_sync(struct nss_ctx_instance *nss_ctx, struct nss_ipv4_node_sync *nins)
+{
+	struct nss_top_instance *nss_top = nss_ctx->nss_top;
+	uint32_t i;
+
+	/*
+	 * Update statistics maintained by NSS driver
+	 */
+	spin_lock_bh(&nss_top->stats_lock);
+	nss_top->stats_node[NSS_IPV4_RX_INTERFACE][NSS_STATS_NODE_RX_PKTS] += nins->node_stats.rx_packets;
+	nss_top->stats_node[NSS_IPV4_RX_INTERFACE][NSS_STATS_NODE_RX_BYTES] += nins->node_stats.rx_bytes;
+	nss_top->stats_node[NSS_IPV4_RX_INTERFACE][NSS_STATS_NODE_TX_PKTS] += nins->node_stats.tx_packets;
+	nss_top->stats_node[NSS_IPV4_RX_INTERFACE][NSS_STATS_NODE_TX_BYTES] += nins->node_stats.tx_bytes;
+
+	for (i = 0; i < NSS_MAX_NUM_PRI; i++) {
+		nss_top->stats_node[NSS_IPV4_RX_INTERFACE][NSS_STATS_NODE_RX_QUEUE_0_DROPPED + i] += nins->node_stats.rx_dropped[i];
+	}
+
+	nss_ipv4_stats[NSS_IPV4_STATS_CONNECTION_CREATE_REQUESTS] += nins->ipv4_connection_create_requests;
+	nss_ipv4_stats[NSS_IPV4_STATS_CONNECTION_CREATE_COLLISIONS] += nins->ipv4_connection_create_collisions;
+	nss_ipv4_stats[NSS_IPV4_STATS_CONNECTION_CREATE_INVALID_INTERFACE] += nins->ipv4_connection_create_invalid_interface;
+	nss_ipv4_stats[NSS_IPV4_STATS_CONNECTION_DESTROY_REQUESTS] += nins->ipv4_connection_destroy_requests;
+	nss_ipv4_stats[NSS_IPV4_STATS_CONNECTION_DESTROY_MISSES] += nins->ipv4_connection_destroy_misses;
+	nss_ipv4_stats[NSS_IPV4_STATS_CONNECTION_HASH_HITS] += nins->ipv4_connection_hash_hits;
+	nss_ipv4_stats[NSS_IPV4_STATS_CONNECTION_HASH_REORDERS] += nins->ipv4_connection_hash_reorders;
+	nss_ipv4_stats[NSS_IPV4_STATS_CONNECTION_FLUSHES] += nins->ipv4_connection_flushes;
+	nss_ipv4_stats[NSS_IPV4_STATS_CONNECTION_EVICTIONS] += nins->ipv4_connection_evictions;
+	nss_ipv4_stats[NSS_IPV4_STATS_FRAGMENTATIONS] += nins->ipv4_fragmentations;
+	nss_ipv4_stats[NSS_IPV4_STATS_MC_CONNECTION_CREATE_REQUESTS] += nins->ipv4_mc_connection_create_requests;
+	nss_ipv4_stats[NSS_IPV4_STATS_MC_CONNECTION_UPDATE_REQUESTS] += nins->ipv4_mc_connection_update_requests;
+	nss_ipv4_stats[NSS_IPV4_STATS_MC_CONNECTION_CREATE_INVALID_INTERFACE] += nins->ipv4_mc_connection_create_invalid_interface;
+	nss_ipv4_stats[NSS_IPV4_STATS_MC_CONNECTION_DESTROY_REQUESTS] += nins->ipv4_mc_connection_destroy_requests;
+	nss_ipv4_stats[NSS_IPV4_STATS_MC_CONNECTION_DESTROY_MISSES] += nins->ipv4_mc_connection_destroy_misses;
+	nss_ipv4_stats[NSS_IPV4_STATS_MC_CONNECTION_FLUSHES] += nins->ipv4_mc_connection_flushes;
+
+	for (i = 0; i < NSS_IPV4_EXCEPTION_EVENT_MAX; i++) {
+		nss_ipv4_exception_stats[i] += nins->exception_events[i];
+	}
+	spin_unlock_bh(&nss_top->stats_lock);
+}
+
+/*
+ * nss_ipv4_stats_ops
+ */
+NSS_STATS_DECLARE_FILE_OPERATIONS(ipv4)
+
+/*
+ * nss_ipv4_stats_dentry_create()
+ *	Create IPv4 statistics debug entry.
+ */
+void nss_ipv4_stats_dentry_create(void)
+{
+	nss_stats_create_dentry("ipv4", &nss_ipv4_stats_ops);
+}
diff --git a/nss_ipv4_stats.h b/nss_ipv4_stats.h
new file mode 100644
index 0000000..d28cdc0
--- /dev/null
+++ b/nss_ipv4_stats.h
@@ -0,0 +1,77 @@
+/*
+ **************************************************************************
+ * 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.
+ **************************************************************************
+ */
+
+#ifndef __NSS_IPV4_STATS_H
+#define __NSS_IPV4_STATS_H
+
+/*
+ * IPV4 node statistics
+ */
+enum nss_ipv4_stats_types {
+	NSS_IPV4_STATS_ACCELERATED_RX_PKTS = 0,
+					/* Accelerated IPv4 RX packets */
+	NSS_IPV4_STATS_ACCELERATED_RX_BYTES,
+					/* Accelerated IPv4 RX bytes */
+	NSS_IPV4_STATS_ACCELERATED_TX_PKTS,
+					/* Accelerated IPv4 TX packets */
+	NSS_IPV4_STATS_ACCELERATED_TX_BYTES,
+					/* Accelerated IPv4 TX bytes */
+	NSS_IPV4_STATS_CONNECTION_CREATE_REQUESTS,
+					/* Number of IPv4 connection create requests */
+	NSS_IPV4_STATS_CONNECTION_CREATE_COLLISIONS,
+					/* Number of IPv4 connection create requests that collided with existing entries */
+	NSS_IPV4_STATS_CONNECTION_CREATE_INVALID_INTERFACE,
+					/* Number of IPv4 connection create requests that had invalid interface */
+	NSS_IPV4_STATS_CONNECTION_DESTROY_REQUESTS,
+					/* Number of IPv4 connection destroy requests */
+	NSS_IPV4_STATS_CONNECTION_DESTROY_MISSES,
+					/* Number of IPv4 connection destroy requests that missed the cache */
+	NSS_IPV4_STATS_CONNECTION_HASH_HITS,
+					/* Number of IPv4 connection hash hits */
+	NSS_IPV4_STATS_CONNECTION_HASH_REORDERS,
+					/* Number of IPv4 connection hash reorders */
+	NSS_IPV4_STATS_CONNECTION_FLUSHES,
+					/* Number of IPv4 connection flushes */
+	NSS_IPV4_STATS_CONNECTION_EVICTIONS,
+					/* Number of IPv4 connection evictions */
+	NSS_IPV4_STATS_FRAGMENTATIONS,
+					/* Number of successful IPv4 fragmentations performed */
+	NSS_IPV4_STATS_DROPPED_BY_RULE,
+					/* Number of IPv4 packets dropped because of a drop rule.*/
+	NSS_IPV4_STATS_MC_CONNECTION_CREATE_REQUESTS,
+					/* Number of successful IPv4 Multicast create requests */
+	NSS_IPV4_STATS_MC_CONNECTION_UPDATE_REQUESTS,
+					/* Number of successful IPv4 Multicast update requests */
+	NSS_IPV4_STATS_MC_CONNECTION_CREATE_INVALID_INTERFACE,
+					/* Number of IPv4 Multicast connection create requests that had invalid interface */
+	NSS_IPV4_STATS_MC_CONNECTION_DESTROY_REQUESTS,
+					/* Number of IPv4 Multicast connection destroy requests */
+	NSS_IPV4_STATS_MC_CONNECTION_DESTROY_MISSES,
+					/* Number of IPv4 Multicast connection destroy requests that missed the cache */
+	NSS_IPV4_STATS_MC_CONNECTION_FLUSHES,
+					/* Number of IPv4 Multicast connection flushes */
+	NSS_IPV4_STATS_MAX,
+};
+
+/*
+ * NSS IPV4 statistics APIs
+ */
+extern void nss_ipv4_stats_node_sync(struct nss_ctx_instance *nss_ctx, struct nss_ipv4_node_sync *nins);
+extern void nss_ipv4_stats_conn_sync(struct nss_ctx_instance *nss_ctx, struct nss_ipv4_conn_sync *nirs);
+extern void nss_ipv4_stats_conn_sync_many(struct nss_ctx_instance *nss_ctx, struct nss_ipv4_conn_sync_many_msg *nicsm);
+extern void nss_ipv4_stats_dentry_create(void);
+
+#endif /* __NSS_IPV4_STATS_H */
diff --git a/nss_ipv6.c b/nss_ipv6.c
index ae83ea2..b840504 100644
--- a/nss_ipv6.c
+++ b/nss_ipv6.c
@@ -20,6 +20,7 @@
  */
 #include "nss_tx_rx_common.h"
 #include "nss_dscp_map.h"
+#include "nss_ipv6_stats.h"
 
 #define NSS_IPV6_TX_MSG_TIMEOUT 1000	/* 1 sec timeout for IPv6 messages */
 
@@ -68,93 +69,6 @@
 }
 
 /*
- * nss_ipv6_driver_conn_sync_update()
- *	Update driver specific information from the messsage.
- */
-static void nss_ipv6_driver_conn_sync_update(struct nss_ctx_instance *nss_ctx, struct nss_ipv6_conn_sync *nics)
-{
-	struct nss_top_instance *nss_top = nss_ctx->nss_top;
-
-	/*
-	 * Update statistics maintained by NSS driver
-	 */
-	spin_lock_bh(&nss_top->stats_lock);
-	nss_top->stats_ipv6[NSS_STATS_IPV6_ACCELERATED_RX_PKTS] += nics->flow_rx_packet_count + nics->return_rx_packet_count;
-	nss_top->stats_ipv6[NSS_STATS_IPV6_ACCELERATED_RX_BYTES] += nics->flow_rx_byte_count + nics->return_rx_byte_count;
-	nss_top->stats_ipv6[NSS_STATS_IPV6_ACCELERATED_TX_PKTS] += nics->flow_tx_packet_count + nics->return_tx_packet_count;
-	nss_top->stats_ipv6[NSS_STATS_IPV6_ACCELERATED_TX_BYTES] += nics->flow_tx_byte_count + nics->return_tx_byte_count;
-	spin_unlock_bh(&nss_top->stats_lock);
-}
-
-/*
- * nss_ipv6_driver_conn_sync_many_update()
- *	Update driver specific information from the conn_sync_many messsage.
- */
-static void nss_ipv6_driver_conn_sync_many_update(struct nss_ctx_instance *nss_ctx, struct nss_ipv6_conn_sync_many_msg *nicsm)
-{
-	uint32_t i;
-
-	/*
-	 * Sanity check for the stats count
-	 */
-	if (nicsm->count * sizeof(struct nss_ipv6_conn_sync) >= nicsm->size) {
-		nss_warning("%p: stats sync count %u exceeds the size of this msg %u", nss_ctx, nicsm->count, nicsm->size);
-		return;
-	}
-
-	for (i = 0; i < nicsm->count; i++) {
-		nss_ipv6_driver_conn_sync_update(nss_ctx, &nicsm->conn_sync[i]);
-	}
-}
-
-/*
- * nss_ipv6_driver_node_sync_update)
- *	Update driver specific information from the messsage.
- */
-static void nss_ipv6_driver_node_sync_update(struct nss_ctx_instance *nss_ctx, struct nss_ipv6_node_sync *nins)
-{
-	struct nss_top_instance *nss_top = nss_ctx->nss_top;
-	int i;
-
-	/*
-	 * Update statistics maintained by NSS driver
-	 */
-	spin_lock_bh(&nss_top->stats_lock);
-	nss_top->stats_node[NSS_IPV6_RX_INTERFACE][NSS_STATS_NODE_RX_PKTS] += nins->node_stats.rx_packets;
-	nss_top->stats_node[NSS_IPV6_RX_INTERFACE][NSS_STATS_NODE_RX_BYTES] += nins->node_stats.rx_bytes;
-	nss_top->stats_node[NSS_IPV6_RX_INTERFACE][NSS_STATS_NODE_TX_PKTS] += nins->node_stats.tx_packets;
-	nss_top->stats_node[NSS_IPV6_RX_INTERFACE][NSS_STATS_NODE_TX_BYTES] += nins->node_stats.tx_bytes;
-
-	for (i = 0; i < NSS_MAX_NUM_PRI; i++) {
-		nss_top->stats_node[NSS_IPV6_RX_INTERFACE][NSS_STATS_NODE_RX_QUEUE_0_DROPPED + i] += nins->node_stats.rx_dropped[i];
-	}
-
-	nss_top->stats_ipv6[NSS_STATS_IPV6_CONNECTION_CREATE_REQUESTS] += nins->ipv6_connection_create_requests;
-	nss_top->stats_ipv6[NSS_STATS_IPV6_CONNECTION_CREATE_COLLISIONS] += nins->ipv6_connection_create_collisions;
-	nss_top->stats_ipv6[NSS_STATS_IPV6_CONNECTION_CREATE_INVALID_INTERFACE] += nins->ipv6_connection_create_invalid_interface;
-	nss_top->stats_ipv6[NSS_STATS_IPV6_CONNECTION_DESTROY_REQUESTS] += nins->ipv6_connection_destroy_requests;
-	nss_top->stats_ipv6[NSS_STATS_IPV6_CONNECTION_DESTROY_MISSES] += nins->ipv6_connection_destroy_misses;
-	nss_top->stats_ipv6[NSS_STATS_IPV6_CONNECTION_HASH_HITS] += nins->ipv6_connection_hash_hits;
-	nss_top->stats_ipv6[NSS_STATS_IPV6_CONNECTION_HASH_REORDERS] += nins->ipv6_connection_hash_reorders;
-	nss_top->stats_ipv6[NSS_STATS_IPV6_CONNECTION_FLUSHES] += nins->ipv6_connection_flushes;
-	nss_top->stats_ipv6[NSS_STATS_IPV6_CONNECTION_EVICTIONS] += nins->ipv6_connection_evictions;
-	nss_top->stats_ipv6[NSS_STATS_IPV6_FRAGMENTATIONS] += nins->ipv6_fragmentations;
-	nss_top->stats_ipv6[NSS_STATS_IPV6_FRAG_FAILS] += nins->ipv6_frag_fails;
-	nss_top->stats_ipv6[NSS_STATS_IPV6_DROPPED_BY_RULE] += nins->ipv6_dropped_by_rule;
-	nss_top->stats_ipv6[NSS_STATS_IPV6_MC_CONNECTION_CREATE_REQUESTS] += nins->ipv6_mc_connection_create_requests;
-	nss_top->stats_ipv6[NSS_STATS_IPV6_MC_CONNECTION_UPDATE_REQUESTS] += nins->ipv6_mc_connection_update_requests;
-	nss_top->stats_ipv6[NSS_STATS_IPV6_MC_CONNECTION_CREATE_INVALID_INTERFACE] += nins->ipv6_mc_connection_create_invalid_interface;
-	nss_top->stats_ipv6[NSS_STATS_IPV6_MC_CONNECTION_DESTROY_REQUESTS] += nins->ipv6_mc_connection_destroy_requests;
-	nss_top->stats_ipv6[NSS_STATS_IPV6_MC_CONNECTION_DESTROY_MISSES] += nins->ipv6_mc_connection_destroy_misses;
-	nss_top->stats_ipv6[NSS_STATS_IPV6_MC_CONNECTION_FLUSHES] += nins->ipv6_mc_connection_flushes;
-
-	for (i = 0; i < NSS_EXCEPTION_EVENT_IPV6_MAX; i++) {
-		 nss_top->stats_if_exception_ipv6[i] += nins->exception_events[i];
-	}
-	spin_unlock_bh(&nss_top->stats_lock);
-}
-
-/*
  * nss_ipv6_rx_msg_handler()
  *	Handle NSS -> HLOS messages for IPv6 bridge/route
  */
@@ -191,21 +105,21 @@
 		/*
 		* Update driver statistics on node sync.
 		*/
-		nss_ipv6_driver_node_sync_update(nss_ctx, &nim->msg.node_stats);
+		nss_ipv6_stats_node_sync(nss_ctx, &nim->msg.node_stats);
 		break;
 
 	case NSS_IPV6_RX_CONN_STATS_SYNC_MSG:
 		/*
 		 * Update driver statistics on connection sync.
 		 */
-		nss_ipv6_driver_conn_sync_update(nss_ctx, &nim->msg.conn_stats);
+		nss_ipv6_stats_conn_sync(nss_ctx, &nim->msg.conn_stats);
 		break;
 
 	case NSS_IPV6_TX_CONN_STATS_SYNC_MANY_MSG:
 		/*
 		 * Update driver statistics on connection sync many.
 		 */
-		nss_ipv6_driver_conn_sync_many_update(nss_ctx, &nim->msg.conn_stats_many);
+		nss_ipv6_stats_conn_sync_many(nss_ctx, &nim->msg.conn_stats_many);
 		ncm->cb = (nss_ptr_t)nss_ipv6_conn_sync_many_msg_cb;
 		break;
 	}
@@ -510,6 +424,8 @@
 	if (nss_core_register_handler(nss_ctx, NSS_IPV6_RX_INTERFACE, nss_ipv6_rx_msg_handler, NULL) != NSS_CORE_STATUS_SUCCESS) {
 		nss_warning("IPv6 handler failed to register");
 	}
+
+	nss_ipv6_stats_dentry_create();
 }
 
 /*
diff --git a/nss_ipv6_reasm.c b/nss_ipv6_reasm.c
index b818be3..4870a95 100644
--- a/nss_ipv6_reasm.c
+++ b/nss_ipv6_reasm.c
@@ -19,39 +19,7 @@
  *	NSS IPv6 Reassembly APIs
  */
 #include "nss_tx_rx_common.h"
-
-/*
- * nss_ipv6_reasm_stats_sync()
- *	Update driver specific information from the messsage.
- */
-static void nss_ipv6_reasm_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_ipv6_reasm_stats_sync *nirs)
-{
-	struct nss_top_instance *nss_top = nss_ctx->nss_top;
-	int j;
-
-	spin_lock_bh(&nss_top->stats_lock);
-
-	/*
-	 * Common node stats
-	 */
-	nss_top->stats_node[NSS_IPV6_REASM_INTERFACE][NSS_STATS_NODE_RX_PKTS] += nirs->node_stats.rx_packets;
-	nss_top->stats_node[NSS_IPV6_REASM_INTERFACE][NSS_STATS_NODE_RX_BYTES] += nirs->node_stats.rx_bytes;
-	nss_top->stats_node[NSS_IPV6_REASM_INTERFACE][NSS_STATS_NODE_TX_PKTS] += nirs->node_stats.tx_packets;
-	nss_top->stats_node[NSS_IPV6_REASM_INTERFACE][NSS_STATS_NODE_TX_BYTES] += nirs->node_stats.tx_bytes;
-
-	for (j = 0; j < NSS_MAX_NUM_PRI; j++) {
-		nss_top->stats_node[NSS_IPV6_REASM_INTERFACE][NSS_STATS_NODE_RX_QUEUE_0_DROPPED + j] += nirs->node_stats.rx_dropped[j];
-	}
-
-	/*
-	 * IPv6 reasm node stats
-	 */
-	nss_top->stats_ipv6_reasm[NSS_STATS_IPV6_REASM_ALLOC_FAILS] += nirs->ipv6_reasm_alloc_fails;
-	nss_top->stats_ipv6_reasm[NSS_STATS_IPV6_REASM_TIMEOUTS] += nirs->ipv6_reasm_timeouts;
-	nss_top->stats_ipv6_reasm[NSS_STATS_IPV6_REASM_DISCARDS] += nirs->ipv6_reasm_discards;
-
-	spin_unlock_bh(&nss_top->stats_lock);
-}
+#include "nss_ipv6_reasm_stats.h"
 
 /*
  * nss_ipv6_reasm_msg_handler()
@@ -96,4 +64,6 @@
 	if (nss_core_register_handler(nss_ctx, NSS_IPV6_REASM_INTERFACE, nss_ipv6_reasm_msg_handler, NULL) != NSS_CORE_STATUS_SUCCESS) {
 		nss_warning("IPv6 reasm handler failed to register");
 	}
+
+	nss_ipv6_reasm_stats_dentry_create();
 }
diff --git a/nss_ipv6_reasm_stats.c b/nss_ipv6_reasm_stats.c
new file mode 100644
index 0000000..f896406
--- /dev/null
+++ b/nss_ipv6_reasm_stats.c
@@ -0,0 +1,136 @@
+/*
+ **************************************************************************
+ * 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_stats.h"
+#include "nss_core.h"
+#include "nss_ipv6_reasm_stats.h"
+
+/*
+ * nss_ipv6_reasm_stats_str
+ *	IPv6 reassembly stats strings
+ */
+static int8_t *nss_ipv6_reasm_stats_str[NSS_IPV6_REASM_STATS_MAX] = {
+	"alloc_fails",
+	"timeouts",
+	"discards",
+};
+
+uint64_t nss_ipv6_reasm_stats[NSS_IPV6_REASM_STATS_MAX]; /* IPv6 reasm statistics */
+
+/*
+ * nss_ipv6_stats_reasm_read()
+ *	Read IPV6 reassembly stats
+ */
+static ssize_t nss_ipv6_reasm_stats_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
+{
+	int32_t i;
+	/*
+	 * max output lines = #stats + start tag line + end tag line + three blank lines
+	 */
+	uint32_t max_output_lines = (NSS_STATS_NODE_MAX + 2) + (NSS_IPV6_REASM_STATS_MAX + 3) + 5;
+	size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
+	size_t size_wr = 0;
+	ssize_t bytes_read = 0;
+	uint64_t *stats_shadow;
+
+	char *lbuf = kzalloc(size_al, GFP_KERNEL);
+	if (unlikely(lbuf == NULL)) {
+		nss_warning("Could not allocate memory for local statistics buffer");
+		return 0;
+	}
+
+	stats_shadow = kzalloc(NSS_IPV6_REASM_STATS_MAX * 8, GFP_KERNEL);
+	if (unlikely(stats_shadow == NULL)) {
+		nss_warning("Could not allocate memory for local shadow buffer");
+		kfree(lbuf);
+		return 0;
+	}
+
+	size_wr = scnprintf(lbuf, size_al, "ipv6 reasm stats start:\n\n");
+
+	size_wr = nss_stats_fill_common_stats(NSS_IPV6_REASM_INTERFACE, lbuf, size_wr, size_al);
+
+	/*
+	 * Ipv6 reasm node stats
+	 */
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nipv6 reasm node stats:\n\n");
+
+	spin_lock_bh(&nss_top_main.stats_lock);
+	for (i = 0; (i < NSS_IPV6_REASM_STATS_MAX); i++) {
+		stats_shadow[i] = nss_ipv6_reasm_stats[i];
+	}
+
+	spin_unlock_bh(&nss_top_main.stats_lock);
+
+	for (i = 0; (i < NSS_IPV6_REASM_STATS_MAX); i++) {
+		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
+					"%s = %llu\n", nss_ipv6_reasm_stats_str[i], stats_shadow[i]);
+	}
+
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nipv6 reasm stats end\n\n");
+	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
+	kfree(lbuf);
+	kfree(stats_shadow);
+
+	return bytes_read;
+}
+
+/*
+ * nss_ipv6_reasm_stats_ops
+ */
+NSS_STATS_DECLARE_FILE_OPERATIONS(ipv6_reasm)
+
+/*
+ * nss_ipv6_reasm_stats_dentry_create()
+ *	Create IPv6 reasm statistics debug entry.
+ */
+void nss_ipv6_reasm_stats_dentry_create(void)
+{
+	nss_stats_create_dentry("ipv6_reasm", &nss_ipv6_reasm_stats_ops);
+}
+
+/*
+ * nss_ipv6_reasm_stats_sync()
+ *	Update driver specific information from the messsage.
+ */
+void nss_ipv6_reasm_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_ipv6_reasm_stats_sync *nirs)
+{
+	struct nss_top_instance *nss_top = nss_ctx->nss_top;
+	int j;
+
+	spin_lock_bh(&nss_top->stats_lock);
+
+	/*
+	 * Common node stats
+	 */
+	nss_top->stats_node[NSS_IPV6_REASM_INTERFACE][NSS_STATS_NODE_RX_PKTS] += nirs->node_stats.rx_packets;
+	nss_top->stats_node[NSS_IPV6_REASM_INTERFACE][NSS_STATS_NODE_RX_BYTES] += nirs->node_stats.rx_bytes;
+	nss_top->stats_node[NSS_IPV6_REASM_INTERFACE][NSS_STATS_NODE_TX_PKTS] += nirs->node_stats.tx_packets;
+	nss_top->stats_node[NSS_IPV6_REASM_INTERFACE][NSS_STATS_NODE_TX_BYTES] += nirs->node_stats.tx_bytes;
+
+	for (j = 0; j < NSS_MAX_NUM_PRI; j++) {
+		nss_top->stats_node[NSS_IPV6_REASM_INTERFACE][NSS_STATS_NODE_RX_QUEUE_0_DROPPED + j] += nirs->node_stats.rx_dropped[j];
+	}
+
+	/*
+	 * IPv6 reasm node stats
+	 */
+	nss_ipv6_reasm_stats[NSS_IPV6_REASM_STATS_ALLOC_FAILS] += nirs->ipv6_reasm_alloc_fails;
+	nss_ipv6_reasm_stats[NSS_IPV6_REASM_STATS_TIMEOUTS] += nirs->ipv6_reasm_timeouts;
+	nss_ipv6_reasm_stats[NSS_IPV6_REASM_STATS_DISCARDS] += nirs->ipv6_reasm_discards;
+
+	spin_unlock_bh(&nss_top->stats_lock);
+}
diff --git a/nss_ipv6_reasm_stats.h b/nss_ipv6_reasm_stats.h
new file mode 100644
index 0000000..45eff95
--- /dev/null
+++ b/nss_ipv6_reasm_stats.h
@@ -0,0 +1,39 @@
+/*
+ **************************************************************************
+ * 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.
+ **************************************************************************
+ */
+
+#ifndef __NSS_IPV6_REASM_STATS_H
+#define __NSS_IPV6_REASM_STATS_H
+
+/*
+ * IPv6 reasm node statistics
+ */
+enum nss_ipv6_reasm_stats {
+	NSS_IPV6_REASM_STATS_ALLOC_FAILS = 0,
+					/* Number of fragment queue allocation failures */
+	NSS_IPV6_REASM_STATS_TIMEOUTS,
+					/* Number of expired fragment queues */
+	NSS_IPV6_REASM_STATS_DISCARDS,
+					/* Number of fragment queues discarded due to malformed fragments*/
+	NSS_IPV6_REASM_STATS_MAX,
+};
+
+/*
+ * NSS IPv6 reasm statistics APIs
+ */
+extern void nss_ipv6_reasm_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_ipv6_reasm_stats_sync *nirs);
+extern void nss_ipv6_reasm_stats_dentry_create(void);
+
+#endif /* __NSS_IPV6_REASM_STATS_H */
diff --git a/nss_ipv6_stats.c b/nss_ipv6_stats.c
new file mode 100644
index 0000000..24b1e77
--- /dev/null
+++ b/nss_ipv6_stats.c
@@ -0,0 +1,287 @@
+/*
+ **************************************************************************
+ * Copyright (c) 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.
+ * 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_stats.h"
+#include "nss_core.h"
+#include <nss_ipv6.h>
+#include "nss_ipv6_stats.h"
+
+/*
+ * nss_ipv6_exception_stats_str
+ *	Interface stats strings for ipv6 exceptions
+ */
+static int8_t *nss_ipv6_exception_stats_str[NSS_IPV6_EXCEPTION_EVENT_MAX] = {
+	"IPV6_ICMP_HEADER_INCOMPLETE",
+	"IPV6_ICMP_UNHANDLED_TYPE",
+	"IPV6_ICMP_IPV6_HEADER_INCOMPLETE",
+	"IPV6_ICMP_IPV6_UDP_HEADER_INCOMPLETE",
+	"IPV6_ICMP_IPV6_TCP_HEADER_INCOMPLETE",
+	"IPV6_ICMP_IPV6_UNKNOWN_PROTOCOL",
+	"IPV6_ICMP_NO_ICME",
+	"IPV6_ICMP_FLUSH_TO_HOST",
+	"IPV6_TCP_HEADER_INCOMPLETE",
+	"IPV6_TCP_NO_ICME",
+	"IPV6_TCP_SMALL_HOP_LIMIT",
+	"IPV6_TCP_NEEDS_FRAGMENTATION",
+	"IPV6_TCP_FLAGS",
+	"IPV6_TCP_SEQ_EXCEEDS_RIGHT_EDGE",
+	"IPV6_TCP_SMALL_DATA_OFFS",
+	"IPV6_TCP_BAD_SACK",
+	"IPV6_TCP_BIG_DATA_OFFS",
+	"IPV6_TCP_SEQ_BEFORE_LEFT_EDGE",
+	"IPV6_TCP_ACK_EXCEEDS_RIGHT_EDGE",
+	"IPV6_TCP_ACK_BEFORE_LEFT_EDGE",
+	"IPV6_UDP_HEADER_INCOMPLETE",
+	"IPV6_UDP_NO_ICME",
+	"IPV6_UDP_SMALL_HOP_LIMIT",
+	"IPV6_UDP_NEEDS_FRAGMENTATION",
+	"IPV6_WRONG_TARGET_MAC",
+	"IPV6_HEADER_INCOMPLETE",
+	"IPV6_UNKNOWN_PROTOCOL",
+	"IPV6_INGRESS_VID_MISMATCH",
+	"IPV6_INGRESS_VID_MISSING",
+	"IPV6_DSCP_MARKING_MISMATCH",
+	"IPV6_VLAN_MARKING_MISMATCH",
+	"IPV6_DEPRECATED",
+	"IPV6_GRE_NO_ICME",
+	"IPV6_GRE_NEEDS_FRAGMENTATION",
+	"IPV6_GRE_SMALL_HOP_LIMIT",
+	"IPV6_DESTROY",
+	"IPV6_ICMP_IPV6_UDPLITE_HEADER_INCOMPLETE",
+	"IPV6_UDPLITE_HEADER_INCOMPLETE",
+	"IPV6_UDPLITE_NO_ICME",
+	"IPV6_UDPLITE_SMALL_HOP_LIMIT",
+	"IPV6_UDPLITE_NEEDS_FRAGMENTATION",
+	"IPV6_MC_UDP_NO_ICME",
+	"IPV6_MC_MEM_ALLOC_FAILURE",
+	"IPV6_MC_UPDATE_FAILURE",
+	"IPV6_MC_PBUF_ALLOC_FAILURE",
+	"IPV6_ESP_HEADER_INCOMPLETE",
+	"IPV6_ESP_NO_ICME",
+	"IPV6_ESP_IP_FRAGMENT",
+	"IPV6_ESP_SMALL_HOP_LIMIT",
+	"IPV6_ESP_NEEDS_FRAGMENTATION"
+};
+
+uint64_t nss_ipv6_stats[NSS_IPV6_STATS_MAX];
+uint64_t nss_ipv6_exception_stats[NSS_IPV6_EXCEPTION_EVENT_MAX];
+
+/*
+ * nss_ipv6_stats_str
+ *	IPv6 stats strings
+ */
+static int8_t *nss_ipv6_stats_str[NSS_IPV6_STATS_MAX] = {
+	"rx_pkts",
+	"rx_bytes",
+	"tx_pkts",
+	"tx_bytes",
+	"create_requests",
+	"create_collisions",
+	"create_invalid_interface",
+	"destroy_requests",
+	"destroy_misses",
+	"hash_hits",
+	"hash_reorders",
+	"flushes",
+	"evictions",
+	"fragmentations",
+	"frag_fails",
+	"by_rule_drops",
+	"mc_create_requests",
+	"mc_update_requests",
+	"mc_create_invalid_interface",
+	"mc_destroy_requests",
+	"mc_destroy_misses",
+	"mc_flushes",
+};
+
+/*
+ * nss_ipv6_stats_read()
+ *	Read IPV6 stats
+ */
+static ssize_t nss_ipv6_stats_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
+{
+	int32_t i;
+
+	/*
+	 * max output lines = #stats + start tag line + end tag line + three blank lines
+	 */
+	uint32_t max_output_lines = (NSS_STATS_NODE_MAX + 2) + (NSS_IPV6_STATS_MAX + 3) + (NSS_IPV6_EXCEPTION_EVENT_MAX + 3) + 5;
+	size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
+	size_t size_wr = 0;
+	ssize_t bytes_read = 0;
+	uint64_t *stats_shadow;
+
+	char *lbuf = kzalloc(size_al, GFP_KERNEL);
+	if (unlikely(lbuf == NULL)) {
+		nss_warning("Could not allocate memory for local statistics buffer");
+		return 0;
+	}
+
+	/*
+	 * Note: The assumption here is that exception event count is larger than other statistics count for IPv6
+	 */
+	stats_shadow = kzalloc(NSS_IPV6_EXCEPTION_EVENT_MAX * 8, GFP_KERNEL);
+	if (unlikely(stats_shadow == NULL)) {
+		nss_warning("Could not allocate memory for local shadow buffer");
+		kfree(lbuf);
+		return 0;
+	}
+
+	size_wr = scnprintf(lbuf, size_al, "ipv6 stats start:\n\n");
+
+	size_wr = nss_stats_fill_common_stats(NSS_IPV6_RX_INTERFACE, lbuf, size_wr, size_al);
+
+	/*
+	 * IPv6 node stats
+	 */
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nipv6 node stats:\n\n");
+
+	spin_lock_bh(&nss_top_main.stats_lock);
+	for (i = 0; (i < NSS_IPV6_STATS_MAX); i++) {
+		stats_shadow[i] = nss_ipv6_stats[i];
+	}
+
+	spin_unlock_bh(&nss_top_main.stats_lock);
+
+	for (i = 0; (i < NSS_IPV6_STATS_MAX); i++) {
+		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
+					"%s = %llu\n", nss_ipv6_stats_str[i], stats_shadow[i]);
+	}
+
+	/*
+	 * Exception stats
+	 */
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nipv6 exception stats:\n\n");
+
+	spin_lock_bh(&nss_top_main.stats_lock);
+	for (i = 0; (i < NSS_IPV6_EXCEPTION_EVENT_MAX); i++) {
+		stats_shadow[i] = nss_ipv6_exception_stats[i];
+	}
+	spin_unlock_bh(&nss_top_main.stats_lock);
+
+	for (i = 0; (i < NSS_IPV6_EXCEPTION_EVENT_MAX); i++) {
+		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
+					"%s = %llu\n", nss_ipv6_exception_stats_str[i], stats_shadow[i]);
+	}
+
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nipv6 stats end\n\n");
+	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
+	kfree(lbuf);
+	kfree(stats_shadow);
+
+	return bytes_read;
+}
+
+/*
+ * nss_ipv6_stats_conn_sync()
+ *	Update driver specific information from the messsage.
+ */
+void nss_ipv6_stats_conn_sync(struct nss_ctx_instance *nss_ctx, struct nss_ipv6_conn_sync *nics)
+{
+	struct nss_top_instance *nss_top = nss_ctx->nss_top;
+
+	/*
+	 * Update statistics maintained by NSS driver
+	 */
+	spin_lock_bh(&nss_top->stats_lock);
+	nss_ipv6_stats[NSS_IPV6_STATS_ACCELERATED_RX_PKTS] += nics->flow_rx_packet_count + nics->return_rx_packet_count;
+	nss_ipv6_stats[NSS_IPV6_STATS_ACCELERATED_RX_BYTES] += nics->flow_rx_byte_count + nics->return_rx_byte_count;
+	nss_ipv6_stats[NSS_IPV6_STATS_ACCELERATED_TX_PKTS] += nics->flow_tx_packet_count + nics->return_tx_packet_count;
+	nss_ipv6_stats[NSS_IPV6_STATS_ACCELERATED_TX_BYTES] += nics->flow_tx_byte_count + nics->return_tx_byte_count;
+	spin_unlock_bh(&nss_top->stats_lock);
+}
+
+/*
+ * nss_ipv6_stats_conn_sync_many()
+ *	Update driver specific information from the conn_sync_many messsage.
+ */
+void nss_ipv6_stats_conn_sync_many(struct nss_ctx_instance *nss_ctx, struct nss_ipv6_conn_sync_many_msg *nicsm)
+{
+	uint32_t i;
+
+	/*
+	 * Sanity check for the stats count
+	 */
+	if (nicsm->count * sizeof(struct nss_ipv6_conn_sync) >= nicsm->size) {
+		nss_warning("%p: stats sync count %u exceeds the size of this msg %u", nss_ctx, nicsm->count, nicsm->size);
+		return;
+	}
+
+	for (i = 0; i < nicsm->count; i++) {
+		nss_ipv6_stats_conn_sync(nss_ctx, &nicsm->conn_sync[i]);
+	}
+}
+
+/*
+ * nss_ipv6_stats_node_sync()
+ *	Update driver specific information from the messsage.
+ */
+void nss_ipv6_stats_node_sync(struct nss_ctx_instance *nss_ctx, struct nss_ipv6_node_sync *nins)
+{
+	struct nss_top_instance *nss_top = nss_ctx->nss_top;
+	uint32_t i;
+
+	/*
+	 * Update statistics maintained by NSS driver
+	 */
+	spin_lock_bh(&nss_top->stats_lock);
+	nss_top->stats_node[NSS_IPV6_RX_INTERFACE][NSS_STATS_NODE_RX_PKTS] += nins->node_stats.rx_packets;
+	nss_top->stats_node[NSS_IPV6_RX_INTERFACE][NSS_STATS_NODE_RX_BYTES] += nins->node_stats.rx_bytes;
+	nss_top->stats_node[NSS_IPV6_RX_INTERFACE][NSS_STATS_NODE_TX_PKTS] += nins->node_stats.tx_packets;
+	nss_top->stats_node[NSS_IPV6_RX_INTERFACE][NSS_STATS_NODE_TX_BYTES] += nins->node_stats.tx_bytes;
+
+	for (i = 0; i < NSS_MAX_NUM_PRI; i++) {
+		nss_top->stats_node[NSS_IPV6_RX_INTERFACE][NSS_STATS_NODE_RX_QUEUE_0_DROPPED + i] += nins->node_stats.rx_dropped[i];
+	}
+
+	nss_ipv6_stats[NSS_IPV6_STATS_CONNECTION_CREATE_REQUESTS] += nins->ipv6_connection_create_requests;
+	nss_ipv6_stats[NSS_IPV6_STATS_CONNECTION_CREATE_COLLISIONS] += nins->ipv6_connection_create_collisions;
+	nss_ipv6_stats[NSS_IPV6_STATS_CONNECTION_CREATE_INVALID_INTERFACE] += nins->ipv6_connection_create_invalid_interface;
+	nss_ipv6_stats[NSS_IPV6_STATS_CONNECTION_DESTROY_REQUESTS] += nins->ipv6_connection_destroy_requests;
+	nss_ipv6_stats[NSS_IPV6_STATS_CONNECTION_DESTROY_MISSES] += nins->ipv6_connection_destroy_misses;
+	nss_ipv6_stats[NSS_IPV6_STATS_CONNECTION_HASH_HITS] += nins->ipv6_connection_hash_hits;
+	nss_ipv6_stats[NSS_IPV6_STATS_CONNECTION_HASH_REORDERS] += nins->ipv6_connection_hash_reorders;
+	nss_ipv6_stats[NSS_IPV6_STATS_CONNECTION_FLUSHES] += nins->ipv6_connection_flushes;
+	nss_ipv6_stats[NSS_IPV6_STATS_CONNECTION_EVICTIONS] += nins->ipv6_connection_evictions;
+	nss_ipv6_stats[NSS_IPV6_STATS_FRAGMENTATIONS] += nins->ipv6_fragmentations;
+	nss_ipv6_stats[NSS_IPV6_STATS_FRAG_FAILS] += nins->ipv6_frag_fails;
+	nss_ipv6_stats[NSS_IPV6_STATS_MC_CONNECTION_CREATE_REQUESTS] += nins->ipv6_mc_connection_create_requests;
+	nss_ipv6_stats[NSS_IPV6_STATS_MC_CONNECTION_UPDATE_REQUESTS] += nins->ipv6_mc_connection_update_requests;
+	nss_ipv6_stats[NSS_IPV6_STATS_MC_CONNECTION_CREATE_INVALID_INTERFACE] += nins->ipv6_mc_connection_create_invalid_interface;
+	nss_ipv6_stats[NSS_IPV6_STATS_MC_CONNECTION_DESTROY_REQUESTS] += nins->ipv6_mc_connection_destroy_requests;
+	nss_ipv6_stats[NSS_IPV6_STATS_MC_CONNECTION_DESTROY_MISSES] += nins->ipv6_mc_connection_destroy_misses;
+	nss_ipv6_stats[NSS_IPV6_STATS_MC_CONNECTION_FLUSHES] += nins->ipv6_mc_connection_flushes;
+
+	for (i = 0; i < NSS_IPV6_EXCEPTION_EVENT_MAX; i++) {
+		nss_ipv6_exception_stats[i] += nins->exception_events[i];
+	}
+	spin_unlock_bh(&nss_top->stats_lock);
+}
+
+/*
+ * nss_ipv6_stats_ops
+ */
+NSS_STATS_DECLARE_FILE_OPERATIONS(ipv6)
+
+/*
+ * nss_ipv6_stats_dentry_create()
+ *	Create IPv6 statistics debug entry.
+ */
+void nss_ipv6_stats_dentry_create(void)
+{
+	nss_stats_create_dentry("ipv6", &nss_ipv6_stats_ops);
+}
diff --git a/nss_ipv6_stats.h b/nss_ipv6_stats.h
new file mode 100644
index 0000000..536e49f
--- /dev/null
+++ b/nss_ipv6_stats.h
@@ -0,0 +1,79 @@
+/*
+ **************************************************************************
+ * 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.
+ **************************************************************************
+ */
+
+#ifndef __NSS_IPV6_STATS_H
+#define __NSS_IPV6_STATS_H
+
+/*
+ * IPV6 node statistics
+ */
+enum nss_ipv6_stats_types {
+	NSS_IPV6_STATS_ACCELERATED_RX_PKTS = 0,
+					/* Accelerated IPv6 RX packets */
+	NSS_IPV6_STATS_ACCELERATED_RX_BYTES,
+					/* Accelerated IPv6 RX bytes */
+	NSS_IPV6_STATS_ACCELERATED_TX_PKTS,
+					/* Accelerated IPv6 TX packets */
+	NSS_IPV6_STATS_ACCELERATED_TX_BYTES,
+					/* Accelerated IPv6 TX bytes */
+	NSS_IPV6_STATS_CONNECTION_CREATE_REQUESTS,
+					/* Number of IPv6 connection create requests */
+	NSS_IPV6_STATS_CONNECTION_CREATE_COLLISIONS,
+					/* Number of IPv6 connection create requests that collided with existing entries */
+	NSS_IPV6_STATS_CONNECTION_CREATE_INVALID_INTERFACE,
+					/* Number of IPv6 connection create requests that had invalid interface */
+	NSS_IPV6_STATS_CONNECTION_DESTROY_REQUESTS,
+					/* Number of IPv6 connection destroy requests */
+	NSS_IPV6_STATS_CONNECTION_DESTROY_MISSES,
+					/* Number of IPv6 connection destroy requests that missed the cache */
+	NSS_IPV6_STATS_CONNECTION_HASH_HITS,
+					/* Number of IPv6 connection hash hits */
+	NSS_IPV6_STATS_CONNECTION_HASH_REORDERS,
+					/* Number of IPv6 connection hash reorders */
+	NSS_IPV6_STATS_CONNECTION_FLUSHES,
+					/* Number of IPv6 connection flushes */
+	NSS_IPV6_STATS_CONNECTION_EVICTIONS,
+					/* Number of IPv6 connection evictions */
+	NSS_IPV6_STATS_FRAGMENTATIONS,
+					/* Number of successful IPv6 fragmentations performed */
+	NSS_IPV6_STATS_FRAG_FAILS,
+					/* Number of IPv6 fragmentation fails */
+	NSS_IPV6_STATS_DROPPED_BY_RULE,
+					/* Number of IPv6 packets dropped by a drop rule. */
+	NSS_IPV6_STATS_MC_CONNECTION_CREATE_REQUESTS,
+					/* Number of successful IPv6 Multicast create requests */
+	NSS_IPV6_STATS_MC_CONNECTION_UPDATE_REQUESTS,
+					/* Number of successful IPv6 Multicast update requests */
+	NSS_IPV6_STATS_MC_CONNECTION_CREATE_INVALID_INTERFACE,
+					/* Number of IPv6 Multicast connection create requests that had invalid interface */
+	NSS_IPV6_STATS_MC_CONNECTION_DESTROY_REQUESTS,
+					/* Number of IPv6 Multicast connection destroy requests */
+	NSS_IPV6_STATS_MC_CONNECTION_DESTROY_MISSES,
+					/* Number of IPv6 Multicast connection destroy requests that missed the cache */
+	NSS_IPV6_STATS_MC_CONNECTION_FLUSHES,
+					/* Number of IPv6 Multicast connection flushes */
+	NSS_IPV6_STATS_MAX,
+};
+
+/*
+ * IPV6 statistics APIs
+ */
+extern void nss_ipv6_stats_node_sync(struct nss_ctx_instance *nss_ctx, struct nss_ipv6_node_sync *nins);
+extern void nss_ipv6_stats_conn_sync(struct nss_ctx_instance *nss_ctx, struct nss_ipv6_conn_sync *nics);
+extern void nss_ipv6_stats_conn_sync_many(struct nss_ctx_instance *nss_ctx, struct nss_ipv6_conn_sync_many_msg *nicsm);
+extern void nss_ipv6_stats_dentry_create(void);
+
+#endif /* __NSS_IPV6_STATS_H */
diff --git a/nss_l2tpv2.c b/nss_l2tpv2.c
index ef05e20..af39b9d 100644
--- a/nss_l2tpv2.c
+++ b/nss_l2tpv2.c
@@ -17,12 +17,13 @@
 #include <linux/l2tp.h>
 #include <net/sock.h>
 #include "nss_tx_rx_common.h"
+#include "nss_l2tpv2_stats.h"
 
 /*
  * Data structures to store l2tpv2 nss debug stats
  */
 static DEFINE_SPINLOCK(nss_l2tpv2_session_debug_stats_lock);
-static struct nss_stats_l2tpv2_session_debug  nss_l2tpv2_session_debug_stats[NSS_MAX_L2TPV2_DYNAMIC_INTERFACES];
+static struct nss_l2tpv2_stats_session_debug  nss_l2tpv2_session_debug_stats[NSS_MAX_L2TPV2_DYNAMIC_INTERFACES];
 
 /*
  * nss_l2tpv2_session_debug_stats_sync
@@ -34,10 +35,10 @@
 	spin_lock_bh(&nss_l2tpv2_session_debug_stats_lock);
 	for (i = 0; i < NSS_MAX_L2TPV2_DYNAMIC_INTERFACES; i++) {
 		if (nss_l2tpv2_session_debug_stats[i].if_num == if_num) {
-			nss_l2tpv2_session_debug_stats[i].stats[NSS_STATS_L2TPV2_SESSION_RX_PPP_LCP_PKTS] += stats_msg->debug_stats.rx_ppp_lcp_pkts;
-			nss_l2tpv2_session_debug_stats[i].stats[NSS_STATS_L2TPV2_SESSION_RX_EXP_DATA_PKTS] += stats_msg->debug_stats.rx_exception_data_pkts;
-			nss_l2tpv2_session_debug_stats[i].stats[NSS_STATS_L2TPV2_SESSION_ENCAP_PBUF_ALLOC_FAIL_PKTS] += stats_msg->debug_stats.encap_pbuf_alloc_fail;
-			nss_l2tpv2_session_debug_stats[i].stats[NSS_STATS_L2TPV2_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_RX_PPP_LCP_PKTS] += stats_msg->debug_stats.rx_ppp_lcp_pkts;
+			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;
 			break;
 		}
 	}
@@ -50,7 +51,7 @@
  */
 void nss_l2tpv2_session_debug_stats_get(void *stats_mem)
 {
-	struct nss_stats_l2tpv2_session_debug *stats = (struct nss_stats_l2tpv2_session_debug *)stats_mem;
+	struct nss_l2tpv2_stats_session_debug *stats = (struct nss_l2tpv2_stats_session_debug *)stats_mem;
 	int i;
 
 	if (!stats) {
@@ -61,7 +62,7 @@
 	spin_lock_bh(&nss_l2tpv2_session_debug_stats_lock);
 	for (i = 0; i < NSS_MAX_L2TPV2_DYNAMIC_INTERFACES; i++) {
 		if (nss_l2tpv2_session_debug_stats[i].valid) {
-			memcpy(stats, &nss_l2tpv2_session_debug_stats[i], sizeof(struct nss_stats_l2tpv2_session_debug));
+			memcpy(stats, &nss_l2tpv2_session_debug_stats[i], sizeof(struct nss_l2tpv2_stats_session_debug));
 			stats++;
 		}
 	}
@@ -264,7 +265,7 @@
 	spin_lock_bh(&nss_l2tpv2_session_debug_stats_lock);
 	for (i = 0; i < NSS_MAX_L2TPV2_DYNAMIC_INTERFACES; i++) {
 		if (nss_l2tpv2_session_debug_stats[i].if_num == if_num) {
-			memset(&nss_l2tpv2_session_debug_stats[i], 0, sizeof(struct nss_stats_l2tpv2_session_debug));
+			memset(&nss_l2tpv2_session_debug_stats[i], 0, sizeof(struct nss_l2tpv2_stats_session_debug));
 			break;
 		}
 	}
@@ -281,7 +282,7 @@
 
 /*
  * nss_l2tpv2_msg_init()
- *      Initialize nss_l2tpv2 msg.
+ *	Initialize nss_l2tpv2 msg.
  */
 void nss_l2tpv2_msg_init(struct nss_l2tpv2_msg *ncm, uint16_t if_num, uint32_t type,  uint32_t len, void *cb, void *app_data)
 {
@@ -297,6 +298,8 @@
 
 	nss_info("nss_l2tpv2_register_handler");
 	nss_core_register_handler(nss_ctx, NSS_L2TPV2_INTERFACE, nss_l2tpv2_handler, NULL);
+
+	nss_l2tpv2_stats_dentry_create();
 }
 
 EXPORT_SYMBOL(nss_l2tpv2_get_context);
diff --git a/nss_l2tpv2_stats.c b/nss_l2tpv2_stats.c
new file mode 100644
index 0000000..00e35da
--- /dev/null
+++ b/nss_l2tpv2_stats.c
@@ -0,0 +1,110 @@
+/*
+ **************************************************************************
+ * 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_stats.h"
+#include "nss_core.h"
+#include "nss_l2tpv2_stats.h"
+
+/*
+ * nss_l2tpv2_stats_session_str
+ *	l2tpv2 statistics strings for nss session stats
+ */
+static int8_t *nss_l2tpv2_stats_session_str[NSS_L2TPV2_STATS_SESSION_MAX] = {
+	"RX_PPP_LCP_PKTS",
+	"RX_EXP_PKTS",
+	"ENCAP_PBUF_ALLOC_FAIL",
+	"DECAP_PBUF_ALLOC_FAIL"
+};
+
+/*
+ * nss_l2tpv2_stats_read()
+ *	Read l2tpv2 statistics
+ */
+static ssize_t nss_l2tpv2_stats_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
+{
+
+	uint32_t max_output_lines = 2 /* header & footer for session stats */
+					+ NSS_MAX_L2TPV2_DYNAMIC_INTERFACES * (NSS_L2TPV2_STATS_SESSION_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_l2tpv2_stats_session_debug l2tpv2_session_stats[NSS_MAX_L2TPV2_DYNAMIC_INTERFACES];
+	int id, i;
+
+	char *lbuf = kzalloc(size_al, GFP_KERNEL);
+	if (unlikely(lbuf == NULL)) {
+		nss_warning("Could not allocate memory for local statistics buffer");
+		return 0;
+	}
+
+	memset(&l2tpv2_session_stats, 0, sizeof(struct nss_l2tpv2_stats_session_debug) * NSS_MAX_L2TPV2_DYNAMIC_INTERFACES);
+
+	/*
+	 * Get all stats
+	 */
+	nss_l2tpv2_session_debug_stats_get((void *)&l2tpv2_session_stats);
+
+	/*
+	 * Session stats
+	 */
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nl2tp v2 session stats start:\n\n");
+	for (id = 0; id < NSS_MAX_L2TPV2_DYNAMIC_INTERFACES; id++) {
+
+			if (!l2tpv2_session_stats[id].valid) {
+				break;
+			}
+
+			dev = dev_get_by_index(&init_net, l2tpv2_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,
+						l2tpv2_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,
+						l2tpv2_session_stats[id].if_num);
+			}
+
+			for (i = 0; i < NSS_L2TPV2_STATS_SESSION_MAX; i++) {
+				size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
+						     "\t%s = %llu\n", nss_l2tpv2_stats_session_str[i],
+						      l2tpv2_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, "\nl2tp v2 session stats end\n");
+	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, size_wr);
+
+	kfree(lbuf);
+	return bytes_read;
+}
+
+/*
+ * nss_l2tpv2_stats_ops
+ */
+NSS_STATS_DECLARE_FILE_OPERATIONS(l2tpv2)
+
+/*
+ * nss_l2tpv2_stats_dentry_create()
+ *	Create l2tpv2 statistics debug entry.
+ */
+void nss_l2tpv2_stats_dentry_create(void)
+{
+	nss_stats_create_dentry("l2tpv2", &nss_l2tpv2_stats_ops);
+}
diff --git a/nss_l2tpv2_stats.h b/nss_l2tpv2_stats.h
new file mode 100644
index 0000000..c199afa
--- /dev/null
+++ b/nss_l2tpv2_stats.h
@@ -0,0 +1,43 @@
+/*
+ ******************************************************************************
+ * 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.
+ * ****************************************************************************
+ */
+
+#ifndef __NSS_L2TPV2_STATS_H
+#define __NSS_L2TPV2_STATS_H
+
+/*
+ * l2tpv2 debug stats
+ */
+enum nss_l2tpv2_stats_session {
+	NSS_L2TPV2_STATS_SESSION_RX_PPP_LCP_PKTS,	/* Number of ppp lcp packets received */
+	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_MAX
+};
+
+struct nss_l2tpv2_stats_session_debug {
+	uint64_t stats[NSS_L2TPV2_STATS_SESSION_MAX];
+	int32_t if_index;
+	uint32_t if_num; /* nss interface number */
+	bool valid;
+};
+
+/*
+ * l2tpv2 statistics APIs
+ */
+extern void nss_l2tpv2_stats_dentry_create(void);
+
+#endif /* __NSS_L2TPV2_STATS_H */
diff --git a/nss_log.c b/nss_log.c
index 0480ad0..a538264 100644
--- a/nss_log.c
+++ b/nss_log.c
@@ -655,6 +655,8 @@
 void nss_log_init(void)
 {
 	int i;
+	struct dentry *logs_dentry;
+	struct dentry *core_log_dentry;
 
 	memset(nss_rbe, 0, sizeof(nss_rbe));
 	init_waitqueue_head(&nss_log_wq);
@@ -663,8 +665,8 @@
 	/*
 	 * Create directory for obtaining NSS FW logs from each core
 	 */
-	nss_top_main.logs_dentry = debugfs_create_dir("logs", nss_top_main.top_dentry);
-	if (unlikely(!nss_top_main.logs_dentry)) {
+	logs_dentry = debugfs_create_dir("logs", nss_top_main.top_dentry);
+	if (unlikely(!logs_dentry)) {
 		nss_warning("Failed to create qca-nss-drv/logs directory in debugfs");
 		return;
 	}
@@ -674,9 +676,9 @@
 		extern struct file_operations nss_logs_core_ops;
 
 		snprintf(file, sizeof(file), "core%d", i);
-		nss_top_main.core_log_dentry = debugfs_create_file(file, 0400,
-						nss_top_main.logs_dentry, (void *)(nss_ptr_t)i, &nss_logs_core_ops);
-		if (unlikely(!nss_top_main.core_log_dentry)) {
+		core_log_dentry = debugfs_create_file(file, 0400,
+						logs_dentry, (void *)(nss_ptr_t)i, &nss_logs_core_ops);
+		if (unlikely(!core_log_dentry)) {
 			nss_warning("Failed to create qca-nss-drv/logs/%s file in debugfs", file);
 			return;
 		}
diff --git a/nss_lso_rx.c b/nss_lso_rx.c
index fb961ae..378818d 100644
--- a/nss_lso_rx.c
+++ b/nss_lso_rx.c
@@ -1,6 +1,6 @@
 /*
  **************************************************************************
- * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014, 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.
@@ -20,44 +20,7 @@
  */
 
 #include "nss_tx_rx_common.h"
-
-/*
- * nss_rx_lso_rx_stats_sync()
- *	Handle the syncing of lso_rx node statistics.
- */
-static void nss_rx_lso_rx_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_lso_rx_stats_sync *nlrss)
-{
-	struct nss_top_instance *nss_top = nss_ctx->nss_top;
-	int j;
-
-	spin_lock_bh(&nss_top->stats_lock);
-
-	/*
-	 * common node stats
-	 */
-	nss_top->stats_node[NSS_LSO_RX_INTERFACE][NSS_STATS_NODE_RX_PKTS] += nlrss->node_stats.rx_packets;
-	nss_top->stats_node[NSS_LSO_RX_INTERFACE][NSS_STATS_NODE_RX_BYTES] += nlrss->node_stats.rx_bytes;
-	nss_top->stats_node[NSS_LSO_RX_INTERFACE][NSS_STATS_NODE_TX_PKTS] += nlrss->node_stats.tx_packets;
-	nss_top->stats_node[NSS_LSO_RX_INTERFACE][NSS_STATS_NODE_TX_BYTES] += nlrss->node_stats.tx_bytes;
-
-	for (j = 0; j < NSS_MAX_NUM_PRI; j++) {
-		nss_top->stats_node[NSS_LSO_RX_INTERFACE][NSS_STATS_NODE_RX_QUEUE_0_DROPPED + j] += nlrss->node_stats.rx_dropped[j];
-	}
-
-	/*
-	 * General LSO_RX stats
-	 */
-	nss_top->stats_lso_rx[NSS_STATS_LSO_RX_TX_DROPPED] += nlrss->tx_dropped;
-	nss_top->stats_lso_rx[NSS_STATS_LSO_RX_DROPPED] += nlrss->dropped;
-
-	/*
-	 * pbuf
-	 */
-	nss_top->stats_lso_rx[NSS_STATS_LSO_RX_PBUF_ALLOC_FAIL] += nlrss->pbuf_alloc_fail;
-	nss_top->stats_lso_rx[NSS_STATS_LSO_RX_PBUF_REFERENCE_FAIL] += nlrss->pbuf_reference_fail;
-
-	spin_unlock_bh(&nss_top->stats_lock);
-}
+#include "nss_lso_rx.h"
 
 /*
  * nss_rx_lso_rx_interface_handler()
@@ -69,7 +32,7 @@
 
 	switch (nlrm->cm.type) {
 	case NSS_LSO_RX_STATS_SYNC_MSG:
-		nss_rx_lso_rx_stats_sync(nss_ctx, &nlrm->msg.stats_sync);
+		nss_lso_rx_stats_sync(nss_ctx, &nlrm->msg.stats_sync);
 		break;
 
 	default:
@@ -89,4 +52,5 @@
 void nss_lso_rx_register_handler(struct nss_ctx_instance *nss_ctx)
 {
 	nss_core_register_handler(nss_ctx, NSS_LSO_RX_INTERFACE, nss_rx_lso_rx_interface_handler, NULL);
+	nss_lso_rx_stats_dentry_create();
 }
diff --git a/nss_lso_rx.h b/nss_lso_rx.h
new file mode 100644
index 0000000..62aa9dd
--- /dev/null
+++ b/nss_lso_rx.h
@@ -0,0 +1,82 @@
+/*
+ **************************************************************************
+ * 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.
+ **************************************************************************
+ */
+
+#ifndef __NSS_LSO_RX_H
+#define __NSS_LSO_RX_H
+
+#include <nss_cmn.h>
+
+/*
+ * nss_lso_rx.h
+ *	NSS driver lso_RX header file.
+ */
+
+/*
+ * LSO_RX driver statistics
+ */
+enum nss_lso_rx_stats_types {
+	NSS_LSO_RX_STATS_TX_DROPPED,		/* Number of packets dropped cause transmit queue is full */
+	NSS_LSO_RX_STATS_DROPPED,		/* Number of packets dropped because of node internal errors */
+	NSS_LSO_RX_STATS_PBUF_ALLOC_FAIL,	/* Number of pbuf alloc failures */
+	NSS_LSO_RX_STATS_PBUF_REFERENCE_FAIL,	/* Number of pbuf reference failures */
+	NSS_LSO_RX_STATS_MAX,
+};
+
+/*
+ * lso_rx_node statistics.
+ */
+struct nss_lso_rx_stats_sync {
+	struct nss_cmn_node_stats node_stats;
+
+	uint32_t tx_dropped;				/* Number of packets dropped because lso_rx transmit queue is full */
+	uint32_t dropped;				/* Total of packets dropped by the node internally */
+	uint32_t pbuf_alloc_fail;			/* Count number of pbuf alloc fails */
+	uint32_t pbuf_reference_fail;			/* Count number of pbuf ref fails */
+
+	/*
+	 * If we're generating per-packet statistics then we count total lso_rx processing ticks
+	 * worst-case ticks and the number of iterations around the lso_rx handler that we take.
+	 */
+	uint32_t total_ticks;			/* Total clock ticks spend inside the lso_rx handler */
+	uint32_t worst_case_ticks;
+						/* Worst case iteration of the lso_rx handler in ticks */
+	uint32_t iterations;			/* Number of iterations around the lso_rx handler */
+};
+
+/*
+ * Message types for lso_rx
+ */
+enum nss_lso_rx_metadata_types {
+	NSS_LSO_RX_STATS_SYNC_MSG,			/* Message type - stats sync message */
+};
+
+/*
+ * Message structure to send receive LSO_RX commands
+ */
+struct nss_lso_rx_msg {
+	struct nss_cmn_msg cm;					/* Message header */
+	union {
+		struct nss_lso_rx_stats_sync stats_sync;	/* Stats sub-message */
+	} msg;
+};
+
+/*
+ * lso_rx statistics APIs
+ */
+extern void nss_lso_rx_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_lso_rx_stats_sync *nlrss);
+extern void nss_lso_rx_stats_dentry_create(void);
+
+#endif /* __NSS_LSO_RX_H */
diff --git a/nss_lso_rx_stats.c b/nss_lso_rx_stats.c
new file mode 100644
index 0000000..92aa6ea
--- /dev/null
+++ b/nss_lso_rx_stats.c
@@ -0,0 +1,142 @@
+/*
+ **************************************************************************
+ * 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_stats.h"
+#include "nss_core.h"
+#include "nss_lso_rx.h"
+
+/*
+ * nss_lso_rx_stats_str
+ *	LSO_RX stats strings
+ */
+static int8_t *nss_lso_rx_stats_str[NSS_LSO_RX_STATS_MAX] = {
+	"tx_dropped",
+	"dropped",
+	"pbuf_alloc_fail",
+	"pbuf_reference_fail"
+};
+
+uint64_t nss_lso_rx_stats[NSS_LSO_RX_STATS_MAX];	/* LSO_RX statistics */
+
+/*
+ * nss_lso_rx_stats_read()
+ *	Read LSO_RX stats
+ */
+static ssize_t nss_lso_rx_stats_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
+{
+	int32_t i;
+
+	/*
+	 * max output lines = #stats + start tag line + end tag line + three blank lines
+	 */
+	uint32_t max_output_lines = (NSS_STATS_NODE_MAX + 2) + (NSS_LSO_RX_STATS_MAX + 3) + 5;
+	size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
+	size_t size_wr = 0;
+	ssize_t bytes_read = 0;
+	uint64_t *stats_shadow;
+
+	char *lbuf = kzalloc(size_al, GFP_KERNEL);
+	if (unlikely(lbuf == NULL)) {
+		nss_warning("Could not allocate memory for local statistics buffer");
+		return 0;
+	}
+
+	stats_shadow = kzalloc(NSS_LSO_RX_STATS_MAX * 8, GFP_KERNEL);
+	if (unlikely(stats_shadow == NULL)) {
+		nss_warning("Could not allocate memory for local shadow buffer");
+		kfree(lbuf);
+		return 0;
+	}
+
+	size_wr = scnprintf(lbuf, size_al, "lso_rx stats start:\n\n");
+
+	size_wr = nss_stats_fill_common_stats(NSS_LSO_RX_INTERFACE, lbuf, size_wr, size_al);
+
+	/*
+	 * lso_rx node stats
+	 */
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nlso_rx node stats:\n\n");
+	spin_lock_bh(&nss_top_main.stats_lock);
+	for (i = 0; (i < NSS_LSO_RX_STATS_MAX); i++) {
+		stats_shadow[i] = nss_lso_rx_stats[i];
+	}
+
+	spin_unlock_bh(&nss_top_main.stats_lock);
+
+	for (i = 0; i < NSS_LSO_RX_STATS_MAX; i++) {
+		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
+					"%s = %llu\n", nss_lso_rx_stats_str[i], stats_shadow[i]);
+	}
+
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nlso_rx stats end\n\n");
+	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
+	kfree(lbuf);
+	kfree(stats_shadow);
+
+	return bytes_read;
+}
+
+/*
+ * nss_lso_rx_stats_ops
+ */
+NSS_STATS_DECLARE_FILE_OPERATIONS(lso_rx)
+
+/*
+ * nss_lso_rx_stats_dentry_create()
+ *	Create lso_rx statistics debug entry.
+ */
+void nss_lso_rx_stats_dentry_create(void)
+{
+	nss_stats_create_dentry("lso_rx", &nss_lso_rx_stats_ops);
+}
+
+/*
+ * nss_lso_rx_stats_sync()
+ *	Handle the syncing of lso_rx node statistics.
+ */
+void nss_lso_rx_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_lso_rx_stats_sync *nlrss)
+{
+	struct nss_top_instance *nss_top = nss_ctx->nss_top;
+	int j;
+
+	spin_lock_bh(&nss_top->stats_lock);
+
+	/*
+	 * common node stats
+	 */
+	nss_top->stats_node[NSS_LSO_RX_INTERFACE][NSS_STATS_NODE_RX_PKTS] += nlrss->node_stats.rx_packets;
+	nss_top->stats_node[NSS_LSO_RX_INTERFACE][NSS_STATS_NODE_RX_BYTES] += nlrss->node_stats.rx_bytes;
+	nss_top->stats_node[NSS_LSO_RX_INTERFACE][NSS_STATS_NODE_TX_PKTS] += nlrss->node_stats.tx_packets;
+	nss_top->stats_node[NSS_LSO_RX_INTERFACE][NSS_STATS_NODE_TX_BYTES] += nlrss->node_stats.tx_bytes;
+
+	for (j = 0; j < NSS_MAX_NUM_PRI; j++) {
+		nss_top->stats_node[NSS_LSO_RX_INTERFACE][NSS_STATS_NODE_RX_QUEUE_0_DROPPED + j] += nlrss->node_stats.rx_dropped[j];
+	}
+
+	/*
+	 * General LSO_RX stats
+	 */
+	nss_lso_rx_stats[NSS_LSO_RX_STATS_TX_DROPPED] += nlrss->tx_dropped;
+	nss_lso_rx_stats[NSS_LSO_RX_STATS_DROPPED] += nlrss->dropped;
+
+	/*
+	 * pbuf
+	 */
+	nss_lso_rx_stats[NSS_LSO_RX_STATS_PBUF_ALLOC_FAIL] += nlrss->pbuf_alloc_fail;
+	nss_lso_rx_stats[NSS_LSO_RX_STATS_PBUF_REFERENCE_FAIL] += nlrss->pbuf_reference_fail;
+
+	spin_unlock_bh(&nss_top->stats_lock);
+}
diff --git a/nss_map_t.c b/nss_map_t.c
index 0369fd9..f23dcec 100644
--- a/nss_map_t.c
+++ b/nss_map_t.c
@@ -15,6 +15,7 @@
  */
 
 #include "nss_tx_rx_common.h"
+#include "nss_map_t_stats.h"
 
 #define NSS_MAP_T_TX_TIMEOUT 3000 /* 3 Seconds */
 
@@ -33,7 +34,7 @@
  * Data structures to store map_t nss debug stats
  */
 static DEFINE_SPINLOCK(nss_map_t_debug_stats_lock);
-static struct nss_stats_map_t_instance_debug nss_map_t_debug_stats[NSS_MAX_MAP_T_DYNAMIC_INTERFACES];
+static struct nss_map_t_stats_instance_debug nss_map_t_debug_stats[NSS_MAX_MAP_T_DYNAMIC_INTERFACES];
 
 /*
  * nss_map_t_verify_if_num()
@@ -63,20 +64,20 @@
 	spin_lock_bh(&nss_map_t_debug_stats_lock);
 	for (i = 0; i < NSS_MAX_MAP_T_DYNAMIC_INTERFACES; i++) {
 		if (nss_map_t_debug_stats[i].if_num == if_num) {
-			nss_map_t_debug_stats[i].stats[NSS_STATS_MAP_T_V4_TO_V6_PBUF_EXCEPTION] += stats_msg->debug_stats.v4_to_v6.exception_pkts;
-			nss_map_t_debug_stats[i].stats[NSS_STATS_MAP_T_V4_TO_V6_PBUF_NO_MATCHING_RULE] += stats_msg->debug_stats.v4_to_v6.no_matching_rule;
-			nss_map_t_debug_stats[i].stats[NSS_STATS_MAP_T_V4_TO_V6_PBUF_NOT_TCP_OR_UDP] += stats_msg->debug_stats.v4_to_v6.not_tcp_or_udp;
-			nss_map_t_debug_stats[i].stats[NSS_STATS_MAP_T_V4_TO_V6_RULE_ERR_LOCAL_PSID] += stats_msg->debug_stats.v4_to_v6.rule_err_local_psid;
-			nss_map_t_debug_stats[i].stats[NSS_STATS_MAP_T_V4_TO_V6_RULE_ERR_LOCAL_IPV6] += stats_msg->debug_stats.v4_to_v6.rule_err_local_ipv6;
-			nss_map_t_debug_stats[i].stats[NSS_STATS_MAP_T_V4_TO_V6_RULE_ERR_REMOTE_PSID] += stats_msg->debug_stats.v4_to_v6.rule_err_remote_psid;
-			nss_map_t_debug_stats[i].stats[NSS_STATS_MAP_T_V4_TO_V6_RULE_ERR_REMOTE_EA_BITS] += stats_msg->debug_stats.v4_to_v6.rule_err_remote_ea_bits;
-			nss_map_t_debug_stats[i].stats[NSS_STATS_MAP_T_V4_TO_V6_RULE_ERR_REMOTE_IPV6] += stats_msg->debug_stats.v4_to_v6.rule_err_remote_ipv6;
+			nss_map_t_debug_stats[i].stats[NSS_MAP_T_STATS_V4_TO_V6_PBUF_EXCEPTION] += stats_msg->debug_stats.v4_to_v6.exception_pkts;
+			nss_map_t_debug_stats[i].stats[NSS_MAP_T_STATS_V4_TO_V6_PBUF_NO_MATCHING_RULE] += stats_msg->debug_stats.v4_to_v6.no_matching_rule;
+			nss_map_t_debug_stats[i].stats[NSS_MAP_T_STATS_V4_TO_V6_PBUF_NOT_TCP_OR_UDP] += stats_msg->debug_stats.v4_to_v6.not_tcp_or_udp;
+			nss_map_t_debug_stats[i].stats[NSS_MAP_T_STATS_V4_TO_V6_RULE_ERR_LOCAL_PSID] += stats_msg->debug_stats.v4_to_v6.rule_err_local_psid;
+			nss_map_t_debug_stats[i].stats[NSS_MAP_T_STATS_V4_TO_V6_RULE_ERR_LOCAL_IPV6] += stats_msg->debug_stats.v4_to_v6.rule_err_local_ipv6;
+			nss_map_t_debug_stats[i].stats[NSS_MAP_T_STATS_V4_TO_V6_RULE_ERR_REMOTE_PSID] += stats_msg->debug_stats.v4_to_v6.rule_err_remote_psid;
+			nss_map_t_debug_stats[i].stats[NSS_MAP_T_STATS_V4_TO_V6_RULE_ERR_REMOTE_EA_BITS] += stats_msg->debug_stats.v4_to_v6.rule_err_remote_ea_bits;
+			nss_map_t_debug_stats[i].stats[NSS_MAP_T_STATS_V4_TO_V6_RULE_ERR_REMOTE_IPV6] += stats_msg->debug_stats.v4_to_v6.rule_err_remote_ipv6;
 
-			nss_map_t_debug_stats[i].stats[NSS_STATS_MAP_T_V6_TO_V4_PBUF_EXCEPTION] += stats_msg->debug_stats.v6_to_v4.exception_pkts;
-			nss_map_t_debug_stats[i].stats[NSS_STATS_MAP_T_V6_TO_V4_PBUF_NO_MATCHING_RULE] += stats_msg->debug_stats.v6_to_v4.no_matching_rule;
-			nss_map_t_debug_stats[i].stats[NSS_STATS_MAP_T_V6_TO_V4_PBUF_NOT_TCP_OR_UDP] += stats_msg->debug_stats.v6_to_v4.not_tcp_or_udp;
-			nss_map_t_debug_stats[i].stats[NSS_STATS_MAP_T_V6_TO_V4_RULE_ERR_LOCAL_IPV4] += stats_msg->debug_stats.v6_to_v4.rule_err_local_ipv4;
-			nss_map_t_debug_stats[i].stats[NSS_STATS_MAP_T_V6_TO_V4_RULE_ERR_REMOTE_IPV4] += stats_msg->debug_stats.v6_to_v4.rule_err_remote_ipv4;
+			nss_map_t_debug_stats[i].stats[NSS_MAP_T_STATS_V6_TO_V4_PBUF_EXCEPTION] += stats_msg->debug_stats.v6_to_v4.exception_pkts;
+			nss_map_t_debug_stats[i].stats[NSS_MAP_T_STATS_V6_TO_V4_PBUF_NO_MATCHING_RULE] += stats_msg->debug_stats.v6_to_v4.no_matching_rule;
+			nss_map_t_debug_stats[i].stats[NSS_MAP_T_STATS_V6_TO_V4_PBUF_NOT_TCP_OR_UDP] += stats_msg->debug_stats.v6_to_v4.not_tcp_or_udp;
+			nss_map_t_debug_stats[i].stats[NSS_MAP_T_STATS_V6_TO_V4_RULE_ERR_LOCAL_IPV4] += stats_msg->debug_stats.v6_to_v4.rule_err_local_ipv4;
+			nss_map_t_debug_stats[i].stats[NSS_MAP_T_STATS_V6_TO_V4_RULE_ERR_REMOTE_IPV4] += stats_msg->debug_stats.v6_to_v4.rule_err_remote_ipv4;
 			break;
 		}
 	}
@@ -84,12 +85,12 @@
 }
 
 /*
- * nss_map_t_instance_stats_get()
+ * nss_map_t_instance_debug_stats_get()
  *	Get map_t statitics.
  */
 void nss_map_t_instance_debug_stats_get(void *stats_mem)
 {
-	struct nss_stats_map_t_instance_debug *stats = (struct nss_stats_map_t_instance_debug *)stats_mem;
+	struct nss_map_t_stats_instance_debug *stats = (struct nss_map_t_stats_instance_debug *)stats_mem;
 	int i;
 
 	if (!stats) {
@@ -100,7 +101,7 @@
 	spin_lock_bh(&nss_map_t_debug_stats_lock);
 	for (i = 0; i < NSS_MAX_MAP_T_DYNAMIC_INTERFACES; i++) {
 		if (nss_map_t_debug_stats[i].valid) {
-			memcpy(stats, &nss_map_t_debug_stats[i], sizeof(struct nss_stats_map_t_instance_debug));
+			memcpy(stats, &nss_map_t_debug_stats[i], sizeof(struct nss_map_t_stats_instance_debug));
 			stats++;
 		}
 	}
@@ -360,7 +361,7 @@
 	spin_lock_bh(&nss_map_t_debug_stats_lock);
 	for (i = 0; i < NSS_MAX_MAP_T_DYNAMIC_INTERFACES; i++) {
 		if (nss_map_t_debug_stats[i].if_num == if_num) {
-			memset(&nss_map_t_debug_stats[i], 0, sizeof(struct nss_stats_map_t_instance_debug));
+			memset(&nss_map_t_debug_stats[i], 0, sizeof(struct nss_map_t_stats_instance_debug));
 			break;
 		}
 	}
@@ -399,4 +400,6 @@
 	sema_init(&nss_map_t_pvt.sem, 1);
 	init_completion(&nss_map_t_pvt.complete);
 	nss_core_register_handler(nss_ctx, NSS_MAP_T_INTERFACE, nss_map_t_handler, NULL);
+
+	nss_map_t_stats_dentry_create();
 }
diff --git a/nss_map_t_stats.c b/nss_map_t_stats.c
new file mode 100644
index 0000000..8406d2e
--- /dev/null
+++ b/nss_map_t_stats.c
@@ -0,0 +1,119 @@
+/*
+ **************************************************************************
+ * 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_stats.h"
+#include "nss_core.h"
+#include "nss_map_t_stats.h"
+
+/*
+ * nss_map_t_stats_instance_str
+ *	map_t statistics strings for nss session stats
+ */
+static int8_t *nss_map_t_stats_instance_str[NSS_MAP_T_STATS_MAX] = {
+	"MAP_T_V4_TO_V6_PBUF_EXCEPTION_PKTS",
+	"MAP_T_V4_TO_V6_PBUF_NO_MATCHING_RULE",
+	"MAP_T_V4_TO_V6_PBUF_NOT_TCP_OR_UDP",
+	"MAP_T_V4_TO_V6_RULE_ERR_LOCAL_PSID",
+	"MAP_T_V4_TO_V6_RULE_ERR_LOCAL_IPV6",
+	"MAP_T_V4_TO_V6_RULE_ERR_REMOTE_PSID",
+	"MAP_T_V4_TO_V6_RULE_ERR_REMOTE_EA_BITS",
+	"MAP_T_V4_TO_V6_RULE_ERR_REMOTE_IPV6",
+	"MAP_T_V6_TO_V4_PBUF_EXCEPTION_PKTS",
+	"MAP_T_V6_TO_V4_PBUF_NO_MATCHING_RULE",
+	"MAP_T_V6_TO_V4_PBUF_NOT_TCP_OR_UDP",
+	"MAP_T_V6_TO_V4_RULE_ERR_LOCAL_IPV4",
+	"MAP_T_V6_TO_V4_RULE_ERR_REMOTE_IPV4"
+};
+
+/*
+ * nss_map_t_stats_read()
+ *	Read map_t statistics
+ */
+static ssize_t nss_map_t_stats_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
+{
+
+	uint32_t max_output_lines = 2 /* header & footer for instance stats */
+					+ NSS_MAX_MAP_T_DYNAMIC_INTERFACES * (NSS_MAP_T_STATS_MAX + 2) /*instance 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_map_t_stats_instance_debug map_t_instance_stats[NSS_MAX_MAP_T_DYNAMIC_INTERFACES];
+	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;
+	}
+
+	memset(&map_t_instance_stats, 0, sizeof(struct nss_map_t_stats_instance_debug) * NSS_MAX_MAP_T_DYNAMIC_INTERFACES);
+
+	/*
+	 * Get all stats
+	 */
+	nss_map_t_instance_debug_stats_get((void *)&map_t_instance_stats);
+
+	/*
+	 * Session stats
+	 */
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nmap_t instance stats start:\n\n");
+	for (id = 0; id < NSS_MAX_MAP_T_DYNAMIC_INTERFACES; id++) {
+
+			if (!map_t_instance_stats[id].valid) {
+				break;
+			}
+
+			dev = dev_get_by_index(&init_net, map_t_instance_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,
+						map_t_instance_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,
+						map_t_instance_stats[id].if_num);
+			}
+
+			for (i = 0; i < NSS_MAP_T_STATS_MAX; i++) {
+				size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
+						     "\t%s = %llu\n", nss_map_t_stats_instance_str[i],
+						      map_t_instance_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, "\nmap_t instance stats end\n");
+	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, size_wr);
+
+	kfree(lbuf);
+	return bytes_read;
+}
+
+/*
+ * nss_map_t_stats_ops
+ */
+NSS_STATS_DECLARE_FILE_OPERATIONS(map_t)
+
+/*
+ * nss_map_t_stats_dentry_create()
+ *	Create map_t statistics debug entry.
+ */
+void nss_map_t_stats_dentry_create(void)
+{
+	nss_stats_create_dentry("map_t", &nss_map_t_stats_ops);
+}
diff --git a/nss_map_t_stats.h b/nss_map_t_stats.h
new file mode 100644
index 0000000..c0704df
--- /dev/null
+++ b/nss_map_t_stats.h
@@ -0,0 +1,55 @@
+/*
+ ******************************************************************************
+ * 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.
+ * ****************************************************************************
+ */
+
+#ifndef __NSS_MAP_T_STATS_H
+#define __NSS_MAP_T_STATS_H
+
+/*
+ * MAP-T debug error types
+ */
+enum nss_map_t_stats_instance {
+	NSS_MAP_T_STATS_V4_TO_V6_PBUF_EXCEPTION,
+	NSS_MAP_T_STATS_V4_TO_V6_PBUF_NO_MATCHING_RULE,
+	NSS_MAP_T_STATS_V4_TO_V6_PBUF_NOT_TCP_OR_UDP,
+	NSS_MAP_T_STATS_V4_TO_V6_RULE_ERR_LOCAL_PSID,
+	NSS_MAP_T_STATS_V4_TO_V6_RULE_ERR_LOCAL_IPV6,
+	NSS_MAP_T_STATS_V4_TO_V6_RULE_ERR_REMOTE_PSID,
+	NSS_MAP_T_STATS_V4_TO_V6_RULE_ERR_REMOTE_EA_BITS,
+	NSS_MAP_T_STATS_V4_TO_V6_RULE_ERR_REMOTE_IPV6,
+	NSS_MAP_T_STATS_V6_TO_V4_PBUF_EXCEPTION,
+	NSS_MAP_T_STATS_V6_TO_V4_PBUF_NO_MATCHING_RULE,
+	NSS_MAP_T_STATS_V6_TO_V4_PBUF_NOT_TCP_OR_UDP,
+	NSS_MAP_T_STATS_V6_TO_V4_RULE_ERR_LOCAL_IPV4,
+	NSS_MAP_T_STATS_V6_TO_V4_RULE_ERR_REMOTE_IPV4,
+	NSS_MAP_T_STATS_MAX
+};
+
+/*
+ * NSS core stats -- for H2N/N2H map_t debug stats
+ */
+struct nss_map_t_stats_instance_debug {
+	uint64_t stats[NSS_MAP_T_STATS_MAX];
+	int32_t if_index;
+	uint32_t if_num; /* nss interface number */
+	bool valid;
+};
+
+/*
+ * MAP-T statistics APIs
+ */
+extern void nss_map_t_stats_dentry_create(void);
+
+#endif /* __NSS_MAP_T_STATS_H */
diff --git a/nss_n2h.c b/nss_n2h.c
index 3d6d303..e09834a 100644
--- a/nss_n2h.c
+++ b/nss_n2h.c
@@ -20,6 +20,7 @@
  */
 
 #include "nss_tx_rx_common.h"
+#include "nss_n2h_stats.h"
 
 #define NSS_N2H_MAX_BUF_POOL_SIZE (1024 * 1024 * 8) /* 8MB */
 #define NSS_N2H_MIN_EMPTY_POOL_BUF_SZ		32
@@ -52,80 +53,6 @@
 static struct nss_n2h_cfg_pvt nss_n2h_q_cfg_pvt;
 
 /*
- * nss_n2h_stats_sync()
- *	Handle the syncing of NSS statistics.
- */
-static void nss_n2h_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_n2h_stats_sync *nnss)
-{
-	struct nss_top_instance *nss_top = nss_ctx->nss_top;
-	int j;
-
-	spin_lock_bh(&nss_top->stats_lock);
-
-	/*
-	 * common node stats
-	 */
-	nss_ctx->stats_n2h[NSS_STATS_NODE_RX_PKTS] += nnss->node_stats.rx_packets;
-	nss_ctx->stats_n2h[NSS_STATS_NODE_RX_BYTES] += nnss->node_stats.rx_bytes;
-	nss_ctx->stats_n2h[NSS_STATS_NODE_TX_PKTS] += nnss->node_stats.tx_packets;
-	nss_ctx->stats_n2h[NSS_STATS_NODE_TX_BYTES] += nnss->node_stats.tx_bytes;
-
-	for (j = 0; j < NSS_MAX_NUM_PRI; j++) {
-		nss_ctx->stats_n2h[NSS_STATS_NODE_RX_QUEUE_0_DROPPED + j] += nnss->node_stats.rx_dropped[j];
-	}
-
-	/*
-	 * General N2H stats
-	 */
-	nss_ctx->stats_n2h[NSS_STATS_N2H_QUEUE_DROPPED] += nnss->queue_dropped;
-	nss_ctx->stats_n2h[NSS_STATS_N2H_TOTAL_TICKS] += nnss->total_ticks;
-	nss_ctx->stats_n2h[NSS_STATS_N2H_WORST_CASE_TICKS] += nnss->worst_case_ticks;
-	nss_ctx->stats_n2h[NSS_STATS_N2H_ITERATIONS] += nnss->iterations;
-
-	/*
-	 * pbuf manager ocm and default pool stats
-	 */
-	nss_ctx->stats_n2h[NSS_STATS_N2H_PBUF_OCM_ALLOC_FAILS] += nnss->pbuf_ocm_stats.pbuf_alloc_fails;
-	nss_ctx->stats_n2h[NSS_STATS_N2H_PBUF_OCM_FREE_COUNT] = nnss->pbuf_ocm_stats.pbuf_free_count;
-	nss_ctx->stats_n2h[NSS_STATS_N2H_PBUF_OCM_TOTAL_COUNT] = nnss->pbuf_ocm_stats.pbuf_total_count;
-
-	nss_ctx->stats_n2h[NSS_STATS_N2H_PBUF_DEFAULT_ALLOC_FAILS] += nnss->pbuf_default_stats.pbuf_alloc_fails;
-	nss_ctx->stats_n2h[NSS_STATS_N2H_PBUF_DEFAULT_FREE_COUNT] = nnss->pbuf_default_stats.pbuf_free_count;
-	nss_ctx->stats_n2h[NSS_STATS_N2H_PBUF_DEFAULT_TOTAL_COUNT] = nnss->pbuf_default_stats.pbuf_total_count;
-
-	/*
-	 * payload mgr stats
-	 */
-	nss_ctx->stats_n2h[NSS_STATS_N2H_PAYLOAD_ALLOC_FAILS] += nnss->payload_alloc_fails;
-	nss_ctx->stats_n2h[NSS_STATS_N2H_PAYLOAD_FREE_COUNT] = nnss->payload_free_count;
-
-	/*
-	 * Host <=> NSS control traffic stats
-	 */
-	nss_ctx->stats_n2h[NSS_STATS_N2H_H2N_CONTROL_PACKETS] += nnss->h2n_ctrl_pkts;
-	nss_ctx->stats_n2h[NSS_STATS_N2H_H2N_CONTROL_BYTES] += nnss->h2n_ctrl_bytes;
-	nss_ctx->stats_n2h[NSS_STATS_N2H_N2H_CONTROL_PACKETS] += nnss->n2h_ctrl_pkts;
-	nss_ctx->stats_n2h[NSS_STATS_N2H_N2H_CONTROL_BYTES] += nnss->n2h_ctrl_bytes;
-
-	/*
-	 * Host <=> NSS control data traffic stats
-	 */
-	nss_ctx->stats_n2h[NSS_STATS_N2H_H2N_DATA_PACKETS] += nnss->h2n_data_pkts;
-	nss_ctx->stats_n2h[NSS_STATS_N2H_H2N_DATA_BYTES] += nnss->h2n_data_bytes;
-	nss_ctx->stats_n2h[NSS_STATS_N2H_N2H_DATA_PACKETS] += nnss->n2h_data_pkts;
-	nss_ctx->stats_n2h[NSS_STATS_N2H_N2H_DATA_BYTES] += nnss->n2h_data_bytes;
-
-	/*
-	 * Payloads related stats
-	 */
-	nss_ctx->stats_n2h[NSS_STATS_N2H_N2H_TOT_PAYLOADS] = nnss->tot_payloads;
-
-	nss_ctx->stats_n2h[NSS_STATS_N2H_N2H_INTERFACE_INVALID] += nnss->data_interface_invalid;
-
-	spin_unlock_bh(&nss_top->stats_lock);
-}
-
-/*
  * nss_n2h_interface_handler()
  *	Handle NSS -> HLOS messages for N2H node
  */
@@ -1853,6 +1780,8 @@
 	init_completion(&nss_n2h_q_cfg_pvt.complete);
 
 	nss_core_register_handler(nss_ctx, NSS_N2H_INTERFACE, nss_n2h_interface_handler, NULL);
+
+	nss_n2h_stats_dentry_create();
 }
 
 /*
diff --git a/nss_n2h_stats.c b/nss_n2h_stats.c
new file mode 100644
index 0000000..b188c14
--- /dev/null
+++ b/nss_n2h_stats.c
@@ -0,0 +1,205 @@
+/*
+ **************************************************************************
+ * 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_stats.h"
+#include "nss_core.h"
+#include "nss_n2h_stats.h"
+
+/*
+ * nss_n2h_stats_str
+ *	N2H stats strings
+ */
+static int8_t *nss_n2h_stats_str[NSS_N2H_STATS_MAX] = {
+	"rx_packets",
+	"rx_bytes",
+	"tx_packets",
+	"tx_bytes",
+	"rx_queue_0_dropped",
+	"rx_queue_1_dropped",
+	"rx_queue_2_dropped",
+	"rx_queue_3_dropped",
+	"queue_dropped",
+	"ticks",
+	"worst_ticks",
+	"iterations",
+	"pbuf_ocm_alloc_fails",
+	"pbuf_ocm_free_count",
+	"pbuf_ocm_total_count",
+	"pbuf_default_alloc_fails",
+	"pbuf_default_free_count",
+	"pbuf_default_total_count",
+	"payload_fails",
+	"payload_free_count",
+	"h2n_control_packets",
+	"h2n_control_bytes",
+	"n2h_control_packets",
+	"n2h_control_bytes",
+	"h2n_data_packets",
+	"h2n_data_bytes",
+	"n2h_data_packets",
+	"n2h_data_bytes",
+	"n2h_tot_payloads",
+	"n2h_data_interface_invalid",
+};
+
+uint64_t nss_n2h_stats[NSS_MAX_CORES][NSS_N2H_STATS_MAX];
+
+/*
+ * nss_n2h_stats_read()
+ *	Read N2H stats
+ */
+static ssize_t nss_n2h_stats_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
+{
+	int32_t i, core;
+
+	/*
+	 * max output lines = #stats + start tag line + end tag line + three blank lines
+	 */
+	uint32_t max_output_lines = (NSS_N2H_STATS_MAX + 3) * 2 + 5;
+	size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
+	size_t size_wr = 0;
+	ssize_t bytes_read = 0;
+	uint64_t *stats_shadow;
+
+	char *lbuf = kzalloc(size_al, GFP_KERNEL);
+	if (unlikely(lbuf == NULL)) {
+		nss_warning("Could not allocate memory for local statistics buffer");
+		return 0;
+	}
+
+	stats_shadow = kzalloc(NSS_N2H_STATS_MAX * 8, GFP_KERNEL);
+	if (unlikely(stats_shadow == NULL)) {
+		nss_warning("Could not allocate memory for local shadow buffer");
+		kfree(lbuf);
+		return 0;
+	}
+
+	size_wr = scnprintf(lbuf, size_al, "n2h stats start:\n\n");
+
+	/*
+	 * N2H node stats
+	 */
+	for (core = 0; core < NSS_MAX_CORES; core++) {
+		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nn2h core %d stats:\n\n", core);
+		spin_lock_bh(&nss_top_main.stats_lock);
+		for (i = 0; i < NSS_N2H_STATS_MAX; i++) {
+			stats_shadow[i] = nss_n2h_stats[core][i];
+		}
+		spin_unlock_bh(&nss_top_main.stats_lock);
+
+		for (i = 0; i < NSS_N2H_STATS_MAX; i++) {
+			size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
+					"%s = %llu\n", nss_n2h_stats_str[i], stats_shadow[i]);
+		}
+	}
+
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nn2h stats end\n\n");
+	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
+	kfree(lbuf);
+	kfree(stats_shadow);
+
+	return bytes_read;
+}
+
+/*
+ * nss_n2h_stats_ops
+ */
+NSS_STATS_DECLARE_FILE_OPERATIONS(n2h)
+
+/*
+ * nss_n2h_stats_dentry_create()
+ *	Create N2H statistics debug entry.
+ */
+void nss_n2h_stats_dentry_create(void)
+{
+	nss_stats_create_dentry("n2h", &nss_n2h_stats_ops);
+}
+
+/*
+ * nss_n2h_stats_sync()
+ *	Handle the syncing of NSS statistics.
+ */
+void nss_n2h_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_n2h_stats_sync *nnss)
+{
+	struct nss_top_instance *nss_top = nss_ctx->nss_top;
+	int id = nss_ctx->id;
+	int j;
+
+	spin_lock_bh(&nss_top->stats_lock);
+
+	/*
+	 * common node stats
+	 */
+	nss_n2h_stats[id][NSS_STATS_NODE_RX_PKTS] += nnss->node_stats.rx_packets;
+	nss_n2h_stats[id][NSS_STATS_NODE_RX_BYTES] += nnss->node_stats.rx_bytes;
+	nss_n2h_stats[id][NSS_STATS_NODE_TX_PKTS] += nnss->node_stats.tx_packets;
+	nss_n2h_stats[id][NSS_STATS_NODE_TX_BYTES] += nnss->node_stats.tx_bytes;
+
+	for (j = 0; j < NSS_MAX_NUM_PRI; j++) {
+		nss_n2h_stats[id][NSS_STATS_NODE_RX_QUEUE_0_DROPPED + j] += nnss->node_stats.rx_dropped[j];
+	}
+
+	/*
+	 * General N2H stats
+	 */
+	nss_n2h_stats[id][NSS_N2H_STATS_QUEUE_DROPPED] += nnss->queue_dropped;
+	nss_n2h_stats[id][NSS_N2H_STATS_TOTAL_TICKS] += nnss->total_ticks;
+	nss_n2h_stats[id][NSS_N2H_STATS_WORST_CASE_TICKS] += nnss->worst_case_ticks;
+	nss_n2h_stats[id][NSS_N2H_STATS_ITERATIONS] += nnss->iterations;
+
+	/*
+	 * pbuf manager ocm and default pool stats
+	 */
+	nss_n2h_stats[id][NSS_N2H_STATS_PBUF_OCM_ALLOC_FAILS] += nnss->pbuf_ocm_stats.pbuf_alloc_fails;
+	nss_n2h_stats[id][NSS_N2H_STATS_PBUF_OCM_FREE_COUNT] = nnss->pbuf_ocm_stats.pbuf_free_count;
+	nss_n2h_stats[id][NSS_N2H_STATS_PBUF_OCM_TOTAL_COUNT] = nnss->pbuf_ocm_stats.pbuf_total_count;
+
+	nss_n2h_stats[id][NSS_N2H_STATS_PBUF_DEFAULT_ALLOC_FAILS] += nnss->pbuf_default_stats.pbuf_alloc_fails;
+	nss_n2h_stats[id][NSS_N2H_STATS_PBUF_DEFAULT_FREE_COUNT] = nnss->pbuf_default_stats.pbuf_free_count;
+	nss_n2h_stats[id][NSS_N2H_STATS_PBUF_DEFAULT_TOTAL_COUNT] = nnss->pbuf_default_stats.pbuf_total_count;
+
+	/*
+	 * payload mgr stats
+	 */
+	nss_n2h_stats[id][NSS_N2H_STATS_PAYLOAD_ALLOC_FAILS] += nnss->payload_alloc_fails;
+	nss_n2h_stats[id][NSS_N2H_STATS_PAYLOAD_FREE_COUNT] = nnss->payload_free_count;
+
+	/*
+	 * Host <=> NSS control traffic stats
+	 */
+	nss_n2h_stats[id][NSS_N2H_STATS_H2N_CONTROL_PACKETS] += nnss->h2n_ctrl_pkts;
+	nss_n2h_stats[id][NSS_N2H_STATS_H2N_CONTROL_BYTES] += nnss->h2n_ctrl_bytes;
+	nss_n2h_stats[id][NSS_N2H_STATS_N2H_CONTROL_PACKETS] += nnss->n2h_ctrl_pkts;
+	nss_n2h_stats[id][NSS_N2H_STATS_N2H_CONTROL_BYTES] += nnss->n2h_ctrl_bytes;
+
+	/*
+	 * Host <=> NSS control data traffic stats
+	 */
+	nss_n2h_stats[id][NSS_N2H_STATS_H2N_DATA_PACKETS] += nnss->h2n_data_pkts;
+	nss_n2h_stats[id][NSS_N2H_STATS_H2N_DATA_BYTES] += nnss->h2n_data_bytes;
+	nss_n2h_stats[id][NSS_N2H_STATS_N2H_DATA_PACKETS] += nnss->n2h_data_pkts;
+	nss_n2h_stats[id][NSS_N2H_STATS_N2H_DATA_BYTES] += nnss->n2h_data_bytes;
+
+	/*
+	 * Payloads related stats
+	 */
+	nss_n2h_stats[id][NSS_N2H_STATS_N2H_TOT_PAYLOADS] = nnss->tot_payloads;
+
+	nss_n2h_stats[id][NSS_N2H_STATS_N2H_INTERFACE_INVALID] += nnss->data_interface_invalid;
+
+	spin_unlock_bh(&nss_top->stats_lock);
+}
+
diff --git a/nss_n2h_stats.h b/nss_n2h_stats.h
new file mode 100644
index 0000000..58d76d2
--- /dev/null
+++ b/nss_n2h_stats.h
@@ -0,0 +1,62 @@
+/*
+ ******************************************************************************
+ * 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.
+ * ****************************************************************************
+ */
+
+#ifndef __NSS_N2H_STATS_H
+#define __NSS_N2H_STATS_H
+
+/*
+ * N2H node statistics
+ */
+enum nss_n2h_stats_types {
+	NSS_N2H_STATS_QUEUE_DROPPED = NSS_STATS_NODE_MAX,
+					/* Number of packets dropped because the exception queue is too full */
+	NSS_N2H_STATS_TOTAL_TICKS,	/* Total clock ticks spend inside the N2H */
+	NSS_N2H_STATS_WORST_CASE_TICKS,	/* Worst case iteration of the exception path in ticks */
+	NSS_N2H_STATS_ITERATIONS,	/* Number of iterations around the N2H */
+
+	NSS_N2H_STATS_PBUF_OCM_ALLOC_FAILS,	/* Number of pbuf ocm allocations that have failed */
+	NSS_N2H_STATS_PBUF_OCM_FREE_COUNT,	/* Number of pbuf ocm free count */
+	NSS_N2H_STATS_PBUF_OCM_TOTAL_COUNT,	/* Number of pbuf ocm total count */
+
+	NSS_N2H_STATS_PBUF_DEFAULT_ALLOC_FAILS,	/* Number of pbuf default allocations that have failed */
+	NSS_N2H_STATS_PBUF_DEFAULT_FREE_COUNT,	/* Number of pbuf default free count */
+	NSS_N2H_STATS_PBUF_DEFAULT_TOTAL_COUNT,	/* Number of pbuf default total count */
+
+	NSS_N2H_STATS_PAYLOAD_ALLOC_FAILS,	/* Number of pbuf allocations that have failed because there were no free payloads */
+	NSS_N2H_STATS_PAYLOAD_FREE_COUNT,	/* Number of free payloads that exist */
+
+	NSS_N2H_STATS_H2N_CONTROL_PACKETS,	/* Control packets received from HLOS */
+	NSS_N2H_STATS_H2N_CONTROL_BYTES,	/* Control bytes received from HLOS */
+	NSS_N2H_STATS_N2H_CONTROL_PACKETS,	/* Control packets sent to HLOS */
+	NSS_N2H_STATS_N2H_CONTROL_BYTES,	/* Control bytes sent to HLOS */
+
+	NSS_N2H_STATS_H2N_DATA_PACKETS,		/* Data packets received from HLOS */
+	NSS_N2H_STATS_H2N_DATA_BYTES,		/* Data bytes received from HLOS */
+	NSS_N2H_STATS_N2H_DATA_PACKETS,		/* Data packets sent to HLOS */
+	NSS_N2H_STATS_N2H_DATA_BYTES,		/* Data bytes sent to HLOS */
+	NSS_N2H_STATS_N2H_TOT_PAYLOADS,		/* No. of payloads in NSS */
+	NSS_N2H_STATS_N2H_INTERFACE_INVALID,	/* No. of bad interface access */
+
+	NSS_N2H_STATS_MAX,
+};
+
+/*
+ * N2H statistics APIs
+ */
+extern void nss_n2h_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_n2h_stats_sync *nnss);
+extern void nss_n2h_stats_dentry_create(void);
+
+#endif /* __NSS_N2H_STATS_H */
diff --git a/nss_portid.c b/nss_portid.c
index 3476a44..66e1e47 100644
--- a/nss_portid.c
+++ b/nss_portid.c
@@ -15,6 +15,7 @@
  */
 
 #include "nss_tx_rx_common.h"
+#include "nss_portid_stats.h"
 
 /*
  * Spinlock to protect portid interface create/destroy/update
@@ -35,63 +36,7 @@
 /*
  * Array of portid interface handles. Indexing based on the physical port_id
  */
-struct nss_portid_handle {
-	uint32_t if_num;			/**< Interface number */
-	struct rtnl_link_stats64 stats;		/**< statistics counters */
-};
-static struct nss_portid_handle nss_portid_hdl[NSS_PORTID_MAX_SWITCH_PORT];
-
-/*
- * nss_portid_node_sync_update()
- *	Update portid node stats.
- */
-static void nss_portid_sync_update(struct nss_ctx_instance *nss_ctx, struct nss_portid_stats_sync_msg *npsm)
-{
-	struct nss_top_instance *nss_top = nss_ctx->nss_top;
-	struct nss_portid_handle *hdl;
-	int j;
-
-	if (npsm->port_id == NSS_PORTID_MAX_SWITCH_PORT) {
-		/*
-		 * Update PORTID base node stats.
-		 */
-		spin_lock_bh(&nss_top->stats_lock);
-		nss_top->stats_node[NSS_PORTID_INTERFACE][NSS_STATS_NODE_RX_PKTS] += npsm->node_stats.rx_packets;
-		nss_top->stats_node[NSS_PORTID_INTERFACE][NSS_STATS_NODE_RX_BYTES] += npsm->node_stats.rx_bytes;
-		nss_top->stats_node[NSS_PORTID_INTERFACE][NSS_STATS_NODE_TX_PKTS] += npsm->node_stats.tx_packets;
-		nss_top->stats_node[NSS_PORTID_INTERFACE][NSS_STATS_NODE_TX_BYTES] += npsm->node_stats.tx_bytes;
-
-		for (j = 0; j < NSS_MAX_NUM_PRI; j++) {
-			nss_top->stats_node[NSS_PORTID_INTERFACE][NSS_STATS_NODE_RX_QUEUE_0_DROPPED + j] += npsm->node_stats.rx_dropped[j];
-		}
-
-		nss_top->stats_portid[NSS_STATS_PORTID_RX_INVALID_HEADER] += npsm->rx_invalid_header;
-		spin_unlock_bh(&nss_top->stats_lock);
-		return;
-	}
-
-	if (npsm->port_id >= NSS_PORTID_MAX_SWITCH_PORT) {
-		nss_warning("port_id %d exceeds NSS_PORTID_MAX_SWITCH_PORT\n", npsm->port_id);
-		return;
-	}
-
-	/*
-	 * Update PORTID interface stats.
-	 */
-	spin_lock_bh(&nss_portid_spinlock);
-	hdl = &nss_portid_hdl[npsm->port_id];
-	if (hdl->if_num == 0) {
-		nss_warning("%p: nss_portid recv'd stats with unconfigured port %d", nss_ctx, npsm->port_id);
-		spin_unlock_bh(&nss_portid_spinlock);
-		return;
-	}
-	hdl->stats.rx_packets += npsm->node_stats.rx_packets;
-	hdl->stats.rx_bytes += npsm->node_stats.rx_bytes;
-	hdl->stats.rx_dropped += nss_cmn_rx_dropped_sum(&npsm->node_stats);
-	hdl->stats.tx_packets += npsm->node_stats.tx_packets;
-	hdl->stats.tx_bytes += npsm->node_stats.tx_bytes;
-	spin_unlock_bh(&nss_portid_spinlock);
-}
+struct nss_portid_handle nss_portid_hdl[NSS_PORTID_MAX_SWITCH_PORT];
 
 /*
  * nss_portid_handler()
@@ -128,7 +73,7 @@
 		/*
 		 * Update portid statistics.
 		 */
-		nss_portid_sync_update(nss_ctx, &npm->msg.stats_sync);
+		nss_portid_stats_sync(nss_ctx, &npm->msg.stats_sync);
 		break;
 	}
 
@@ -497,6 +442,8 @@
 
 	nss_core_register_handler(nss_ctx, NSS_PORTID_INTERFACE, nss_portid_handler, NULL);
 
+	nss_portid_stats_dentry_create();
+
 	sema_init(&pid.sem, 1);
 	init_completion(&pid.complete);
 }
diff --git a/nss_portid_stats.c b/nss_portid_stats.c
new file mode 100644
index 0000000..4400bfd
--- /dev/null
+++ b/nss_portid_stats.c
@@ -0,0 +1,157 @@
+/*
+ **************************************************************************
+ * Copyright (c) 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.
+ * 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_stats.h"
+#include "nss_core.h"
+#include "nss_portid_stats.h"
+
+extern spinlock_t nss_portid_spinlock;
+extern struct nss_portid_handle nss_portid_hdl[];
+
+/*
+ * nss_portid_stats_str
+ *	PortID statistics strings
+ */
+static int8_t *nss_portid_stats_str[NSS_PORTID_STATS_MAX] = {
+	"RX_INVALID_HEADER",
+};
+
+uint64_t nss_portid_stats[NSS_PORTID_STATS_MAX];
+
+/*
+ * nss_portid_stats_read()
+ *	Read PortID stats
+ */
+static ssize_t nss_portid_stats_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
+{
+	int32_t i;
+	/*
+	 * max output lines = #stats + start tag line + end tag line + three blank lines
+	 */
+	uint32_t max_output_lines = NSS_STATS_NODE_MAX + NSS_PORTID_STATS_MAX + 5;
+	size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
+	size_t size_wr = 0;
+	ssize_t bytes_read = 0;
+	uint64_t *stats_shadow;
+
+	char *lbuf = kzalloc(size_al, GFP_KERNEL);
+	if (unlikely(lbuf == NULL)) {
+		nss_warning("Could not allocate memory for local statistics buffer");
+		return 0;
+	}
+
+	stats_shadow = kzalloc(NSS_STATS_NODE_MAX * 8, GFP_KERNEL);
+	if (unlikely(stats_shadow == NULL)) {
+		nss_warning("Could not allocate memory for local shadow buffer");
+		kfree(lbuf);
+		return 0;
+	}
+
+	size_wr = scnprintf(lbuf, size_al, "portid stats start:\n\n");
+
+	size_wr = nss_stats_fill_common_stats(NSS_PORTID_INTERFACE, lbuf, size_wr, size_al);
+
+	/*
+	 * PortID node stats
+	 */
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nportid node stats:\n\n");
+
+	spin_lock_bh(&nss_top_main.stats_lock);
+	for (i = 0; (i < NSS_PORTID_STATS_MAX); i++) {
+		stats_shadow[i] = nss_portid_stats[i];
+	}
+
+	spin_unlock_bh(&nss_top_main.stats_lock);
+
+	for (i = 0; (i < NSS_PORTID_STATS_MAX); i++) {
+		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
+					"%s = %llu\n", nss_portid_stats_str[i], stats_shadow[i]);
+	}
+
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nportid stats end\n\n");
+
+	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
+	kfree(lbuf);
+	kfree(stats_shadow);
+
+	return bytes_read;
+}
+
+/*
+ * nss_portid_stats_ops
+ */
+NSS_STATS_DECLARE_FILE_OPERATIONS(portid)
+
+/*
+ * nss_portid_stats_dentry_create()
+ *	Create portid node statistics debug entry.
+ */
+void nss_portid_stats_dentry_create(void)
+{
+	nss_stats_create_dentry("portid", &nss_portid_stats_ops);
+}
+
+/*
+ * nss_portid_stats_sync()
+ *	Update portid node stats.
+ */
+void nss_portid_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_portid_stats_sync_msg *npsm)
+{
+	struct nss_top_instance *nss_top = nss_ctx->nss_top;
+	struct nss_portid_handle *hdl;
+	int j;
+
+	if (npsm->port_id == NSS_PORTID_MAX_SWITCH_PORT) {
+		/*
+		 * Update PORTID base node stats.
+		 */
+		spin_lock_bh(&nss_top->stats_lock);
+		nss_top->stats_node[NSS_PORTID_INTERFACE][NSS_STATS_NODE_RX_PKTS] += npsm->node_stats.rx_packets;
+		nss_top->stats_node[NSS_PORTID_INTERFACE][NSS_STATS_NODE_RX_BYTES] += npsm->node_stats.rx_bytes;
+		nss_top->stats_node[NSS_PORTID_INTERFACE][NSS_STATS_NODE_TX_PKTS] += npsm->node_stats.tx_packets;
+		nss_top->stats_node[NSS_PORTID_INTERFACE][NSS_STATS_NODE_TX_BYTES] += npsm->node_stats.tx_bytes;
+
+		for (j = 0; j < NSS_MAX_NUM_PRI; j++) {
+			nss_top->stats_node[NSS_PORTID_INTERFACE][NSS_STATS_NODE_RX_QUEUE_0_DROPPED + j] += npsm->node_stats.rx_dropped[j];
+		}
+
+		nss_portid_stats[NSS_PORTID_STATS_RX_INVALID_HEADER] += npsm->rx_invalid_header;
+		spin_unlock_bh(&nss_top->stats_lock);
+		return;
+	}
+
+	if (npsm->port_id >= NSS_PORTID_MAX_SWITCH_PORT) {
+		nss_warning("port_id %d exceeds NSS_PORTID_MAX_SWITCH_PORT\n", npsm->port_id);
+		return;
+	}
+
+	/*
+	 * Update PORTID interface stats.
+	 */
+	spin_lock_bh(&nss_portid_spinlock);
+	hdl = &nss_portid_hdl[npsm->port_id];
+	if (hdl->if_num == 0) {
+		nss_warning("%p: nss_portid recv'd stats with unconfigured port %d", nss_ctx, npsm->port_id);
+		spin_unlock_bh(&nss_portid_spinlock);
+		return;
+	}
+	hdl->stats.rx_packets += npsm->node_stats.rx_packets;
+	hdl->stats.rx_bytes += npsm->node_stats.rx_bytes;
+	hdl->stats.rx_dropped += nss_cmn_rx_dropped_sum(&npsm->node_stats);
+	hdl->stats.tx_packets += npsm->node_stats.tx_packets;
+	hdl->stats.tx_bytes += npsm->node_stats.tx_bytes;
+	spin_unlock_bh(&nss_portid_spinlock);
+}
diff --git a/nss_portid_stats.h b/nss_portid_stats.h
new file mode 100644
index 0000000..b1a1ee5
--- /dev/null
+++ b/nss_portid_stats.h
@@ -0,0 +1,39 @@
+/*
+ ******************************************************************************
+ * 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.
+ * ****************************************************************************
+ */
+
+#ifndef __NSS_PORTID_STATS_H
+#define __NSS_PORTID_STATS_H
+
+/*
+ * PortID statistics
+ */
+enum nss_portid_stats_types {
+	NSS_PORTID_STATS_RX_INVALID_HEADER,
+	NSS_PORTID_STATS_MAX,
+};
+
+struct nss_portid_handle {
+	uint32_t if_num;			/**< Interface number */
+	struct rtnl_link_stats64 stats;		/**< statistics counters */
+};
+
+/*
+ * PortID statistics APIs
+ */
+extern void nss_portid_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_portid_stats_sync_msg *npsm);
+extern void nss_portid_stats_dentry_create(void);
+
+#endif /* __NSS_PORTID_STATS_H */
diff --git a/nss_ppe.c b/nss_ppe.c
index c66327e..1a07cdb 100644
--- a/nss_ppe.c
+++ b/nss_ppe.c
@@ -15,90 +15,7 @@
  */
 
 #include "nss_ppe.h"
-
-static uint8_t ppe_cc_nonexception[NSS_STATS_PPE_CPU_CODE_NONEXCEPTION_MAX] = {
-	NSS_STATS_PPE_CPU_CODE_EXP_FAKE_L2_PROT_ERR,
-	NSS_STATS_PPE_CPU_CODE_EXP_FAKE_MAC_HEADER_ERR,
-	NSS_STATS_PPE_CPU_CODE_EXP_BITMAP_MAX,
-	NSS_STATS_PPE_CPU_CODE_L2_EXP_MRU_FAIL,
-	NSS_STATS_PPE_CPU_CODE_L2_EXP_MTU_FAIL,
-	NSS_STATS_PPE_CPU_CODE_L3_EXP_IP_PREFIX_BC,
-	NSS_STATS_PPE_CPU_CODE_L3_EXP_MTU_FAIL,
-	NSS_STATS_PPE_CPU_CODE_L3_EXP_MRU_FAIL,
-	NSS_STATS_PPE_CPU_CODE_L3_EXP_ICMP_RDT,
-	NSS_STATS_PPE_CPU_CODE_L3_EXP_IP_RT_TTL1_TO_ME,
-	NSS_STATS_PPE_CPU_CODE_L3_EXP_IP_RT_TTL_ZERO,
-	NSS_STATS_PPE_CPU_CODE_L3_FLOW_SERVICE_CODE_LOOP,
-	NSS_STATS_PPE_CPU_CODE_L3_FLOW_DE_ACCELERATE,
-	NSS_STATS_PPE_CPU_CODE_L3_EXP_FLOW_SRC_IF_CHK_FAIL,
-	NSS_STATS_PPE_CPU_CODE_L3_FLOW_SYNC_TOGGLE_MISMATCH,
-	NSS_STATS_PPE_CPU_CODE_L3_EXP_MTU_DF_FAIL,
-	NSS_STATS_PPE_CPU_CODE_L3_EXP_PPPOE_MULTICAST,
-	NSS_STATS_PPE_CPU_CODE_MGMT_OFFSET,
-	NSS_STATS_PPE_CPU_CODE_MGMT_EAPOL,
-	NSS_STATS_PPE_CPU_CODE_MGMT_PPPOE_DIS,
-	NSS_STATS_PPE_CPU_CODE_MGMT_IGMP,
-	NSS_STATS_PPE_CPU_CODE_MGMT_ARP_REQ,
-	NSS_STATS_PPE_CPU_CODE_MGMT_ARP_REP,
-	NSS_STATS_PPE_CPU_CODE_MGMT_DHCPv4,
-	NSS_STATS_PPE_CPU_CODE_MGMT_MLD,
-	NSS_STATS_PPE_CPU_CODE_MGMT_NS,
-	NSS_STATS_PPE_CPU_CODE_MGMT_NA,
-	NSS_STATS_PPE_CPU_CODE_MGMT_DHCPv6,
-	NSS_STATS_PPE_CPU_CODE_PTP_OFFSET,
-	NSS_STATS_PPE_CPU_CODE_PTP_SYNC,
-	NSS_STATS_PPE_CPU_CODE_PTP_FOLLOW_UP,
-	NSS_STATS_PPE_CPU_CODE_PTP_DELAY_REQ,
-	NSS_STATS_PPE_CPU_CODE_PTP_DELAY_RESP,
-	NSS_STATS_PPE_CPU_CODE_PTP_PDELAY_REQ,
-	NSS_STATS_PPE_CPU_CODE_PTP_PDELAY_RESP,
-	NSS_STATS_PPE_CPU_CODE_PTP_PDELAY_RESP_FOLLOW_UP,
-	NSS_STATS_PPE_CPU_CODE_PTP_ANNOUNCE,
-	NSS_STATS_PPE_CPU_CODE_PTP_MANAGEMENT,
-	NSS_STATS_PPE_CPU_CODE_PTP_SIGNALING,
-	NSS_STATS_PPE_CPU_CODE_PTP_PKT_RSV_MSG,
-	NSS_STATS_PPE_CPU_CODE_IPV4_SG_UNKNOWN,
-	NSS_STATS_PPE_CPU_CODE_IPV6_SG_UNKNOWN,
-	NSS_STATS_PPE_CPU_CODE_ARP_SG_UNKNOWN,
-	NSS_STATS_PPE_CPU_CODE_ND_SG_UNKNOWN,
-	NSS_STATS_PPE_CPU_CODE_IPV4_SG_VIO,
-	NSS_STATS_PPE_CPU_CODE_IPV6_SG_VIO,
-	NSS_STATS_PPE_CPU_CODE_ARP_SG_VIO,
-	NSS_STATS_PPE_CPU_CODE_ND_SG_VIO,
-	NSS_STATS_PPE_CPU_CODE_L3_ROUTING_IP_TO_ME,
-	NSS_STATS_PPE_CPU_CODE_L3_FLOW_SNAT_ACTION,
-	NSS_STATS_PPE_CPU_CODE_L3_FLOW_DNAT_ACTION,
-	NSS_STATS_PPE_CPU_CODE_L3_FLOW_RT_ACTION,
-	NSS_STATS_PPE_CPU_CODE_L3_FLOW_BR_ACTION,
-	NSS_STATS_PPE_CPU_CODE_L3_MC_BRIDGE_ACTION,
-	NSS_STATS_PPE_CPU_CODE_L3_ROUTE_PREHEAD_RT_ACTION,
-	NSS_STATS_PPE_CPU_CODE_L3_ROUTE_PREHEAD_SNAPT_ACTION,
-	NSS_STATS_PPE_CPU_CODE_L3_ROUTE_PREHEAD_DNAPT_ACTION,
-	NSS_STATS_PPE_CPU_CODE_L3_ROUTE_PREHEAD_SNAT_ACTION,
-	NSS_STATS_PPE_CPU_CODE_L3_ROUTE_PREHEAD_DNAT_ACTION,
-	NSS_STATS_PPE_CPU_CODE_L3_NO_ROUTE_PREHEAD_NAT_ACTION,
-	NSS_STATS_PPE_CPU_CODE_L3_NO_ROUTE_PREHEAD_NAT_ERROR,
-	NSS_STATS_PPE_CPU_CODE_L3_ROUTE_ACTION,
-	NSS_STATS_PPE_CPU_CODE_L3_NO_ROUTE_ACTION,
-	NSS_STATS_PPE_CPU_CODE_L3_NO_ROUTE_NH_INVALID_ACTION,
-	NSS_STATS_PPE_CPU_CODE_L3_NO_ROUTE_PREHEAD_ACTION,
-	NSS_STATS_PPE_CPU_CODE_L3_BRIDGE_ACTION,
-	NSS_STATS_PPE_CPU_CODE_L3_FLOW_ACTION,
-	NSS_STATS_PPE_CPU_CODE_L3_FLOW_MISS_ACTION,
-	NSS_STATS_PPE_CPU_CODE_L2_NEW_MAC_ADDRESS,
-	NSS_STATS_PPE_CPU_CODE_L2_HASH_COLLISION,
-	NSS_STATS_PPE_CPU_CODE_L2_STATION_MOVE,
-	NSS_STATS_PPE_CPU_CODE_L2_LEARN_LIMIT,
-	NSS_STATS_PPE_CPU_CODE_L2_SA_LOOKUP_ACTION,
-	NSS_STATS_PPE_CPU_CODE_L2_DA_LOOKUP_ACTION,
-	NSS_STATS_PPE_CPU_CODE_APP_CTRL_ACTION,
-	NSS_STATS_PPE_CPU_CODE_IN_VLAN_FILTER_ACTION,
-	NSS_STATS_PPE_CPU_CODE_IN_VLAN_XLT_MISS,
-	NSS_STATS_PPE_CPU_CODE_EG_VLAN_FILTER_DROP,
-	NSS_STATS_PPE_CPU_CODE_ACL_PRE_ACTION,
-	NSS_STATS_PPE_CPU_CODE_ACL_POST_ACTION,
-	NSS_STATS_PPE_CPU_CODE_SERVICE_CODE_ACTION,
-};
+#include "nss_ppe_stats.h"
 
 /*
  * nss_ppe_verify_ifnum()
@@ -110,54 +27,6 @@
 }
 
 /*
- * nss_ppe_stats_sync
- *	PPE connection sync stats from NSS
- */
-static void nss_ppe_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_ppe_sync_stats_msg *stats_msg, uint16_t if_num)
-{
-	spin_lock_bh(&nss_ppe_stats_lock);
-	nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_V4_L3_FLOWS] += stats_msg->nss_ppe_v4_l3_flows;
-	nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_V4_L2_FLOWS] += stats_msg->nss_ppe_v4_l2_flows;
-	nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_V4_CREATE_REQ] += stats_msg->nss_ppe_v4_create_req;
-	nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_V4_CREATE_FAIL] += stats_msg->nss_ppe_v4_create_fail;
-	nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_V4_DESTROY_REQ] += stats_msg->nss_ppe_v4_destroy_req;
-	nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_V4_DESTROY_FAIL] += stats_msg->nss_ppe_v4_destroy_fail;
-	nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_V4_MC_CREATE_REQ] += stats_msg->nss_ppe_v4_mc_create_req;
-	nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_V4_MC_CREATE_FAIL] += stats_msg->nss_ppe_v4_mc_create_fail;
-	nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_V4_MC_UPDATE_REQ] += stats_msg->nss_ppe_v4_mc_update_req;
-	nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_V4_MC_UPDATE_FAIL] += stats_msg->nss_ppe_v4_mc_update_fail;
-	nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_V4_MC_DESTROY_REQ] += stats_msg->nss_ppe_v4_mc_destroy_req;
-	nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_V4_MC_DESTROY_FAIL] += stats_msg->nss_ppe_v4_mc_destroy_fail;
-
-	nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_V6_L3_FLOWS] += stats_msg->nss_ppe_v6_l3_flows;
-	nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_V6_L2_FLOWS] += stats_msg->nss_ppe_v6_l2_flows;
-	nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_V6_CREATE_REQ] += stats_msg->nss_ppe_v6_create_req;
-	nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_V6_CREATE_FAIL] += stats_msg->nss_ppe_v6_create_fail;
-	nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_V6_DESTROY_REQ] += stats_msg->nss_ppe_v6_destroy_req;
-	nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_V6_DESTROY_FAIL] += stats_msg->nss_ppe_v6_destroy_fail;
-	nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_V6_MC_CREATE_REQ] += stats_msg->nss_ppe_v6_mc_create_req;
-	nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_V6_MC_CREATE_FAIL] += stats_msg->nss_ppe_v6_mc_create_fail;
-	nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_V6_MC_UPDATE_REQ] += stats_msg->nss_ppe_v6_mc_update_req;
-	nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_V6_MC_UPDATE_FAIL] += stats_msg->nss_ppe_v6_mc_update_fail;
-	nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_V6_MC_DESTROY_REQ] += stats_msg->nss_ppe_v6_mc_destroy_req;
-	nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_V6_MC_DESTROY_FAIL] += stats_msg->nss_ppe_v6_mc_destroy_fail;
-
-	nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_FAIL_VP_FULL] += stats_msg->nss_ppe_fail_vp_full;
-	nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_FAIL_NH_FULL] += stats_msg->nss_ppe_fail_nh_full;
-	nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_FAIL_FLOW_FULL] += stats_msg->nss_ppe_fail_flow_full;
-	nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_FAIL_HOST_FULL] += stats_msg->nss_ppe_fail_host_full;
-	nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_FAIL_PUBIP_FULL] += stats_msg->nss_ppe_fail_pubip_full;
-	nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_FAIL_PORT_SETUP] += stats_msg->nss_ppe_fail_port_setup;
-	nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_FAIL_RW_FIFO_FULL] += stats_msg->nss_ppe_fail_rw_fifo_full;
-	nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_FAIL_FLOW_COMMAND] += stats_msg->nss_ppe_fail_flow_command;
-	nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_FAIL_UNKNOWN_PROTO] += stats_msg->nss_ppe_fail_unknown_proto;
-	nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_FAIL_PPE_UNRESPONSIVE] += stats_msg->nss_ppe_fail_ppe_unresponsive;
-	nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_CE_OPAQUE_INVALID] += stats_msg->nss_ppe_ce_opaque_invalid;
-	nss_ppe_debug_stats.conn_stats[NSS_STATS_PPE_FAIL_FQG_FULL] += stats_msg->nss_ppe_fail_fqg_full;
-	spin_unlock_bh(&nss_ppe_stats_lock);
-}
-
-/*
  * nss_ppe_callback()
  *	Callback to handle the completion of NSS->HLOS messages.
  */
@@ -322,195 +191,6 @@
 EXPORT_SYMBOL(nss_ppe_tx_l2_exception_msg);
 
 /*
- * nss_ppe_stats_conn_get()
- *	Get ppe connection stats.
- */
-void nss_ppe_stats_conn_get(uint32_t *stats)
-{
-	if (!stats) {
-		nss_warning("No memory to copy ppe connection stats\n");
-		return;
-	}
-
-	spin_lock_bh(&nss_ppe_stats_lock);
-
-	if (!nss_ppe_debug_stats.valid) {
-		spin_unlock_bh(&nss_ppe_stats_lock);
-		nss_warning("PPE base address not initialized!\n");
-		return;
-	}
-
-	/*
-	 * Get flow stats
-	 */
-	memcpy(stats, nss_ppe_debug_stats.conn_stats, (sizeof(uint32_t) * NSS_STATS_PPE_CONN_MAX));
-
-	spin_unlock_bh(&nss_ppe_stats_lock);
-}
-
-/*
- * nss_ppe_stats_l3_get()
- *	Get ppe L3 debug stats.
- */
-void nss_ppe_stats_l3_get(uint32_t *stats)
-{
-	if (!stats) {
-		nss_warning("No memory to copy ppe l3 dbg stats\n");
-		return;
-	}
-
-	spin_lock_bh(&nss_ppe_stats_lock);
-
-	if (!nss_ppe_debug_stats.valid) {
-		spin_unlock_bh(&nss_ppe_stats_lock);
-		nss_warning("PPE base address not initialized!\n");
-		return;
-	}
-
-	nss_ppe_reg_write(PPE_L3_DBG_WR_OFFSET, PPE_L3_DBG0_OFFSET);
-	nss_ppe_reg_read(PPE_L3_DBG_RD_OFFSET, &stats[NSS_STATS_PPE_L3_DBG_0]);
-
-	nss_ppe_reg_write(PPE_L3_DBG_WR_OFFSET, PPE_L3_DBG1_OFFSET);
-	nss_ppe_reg_read(PPE_L3_DBG_RD_OFFSET, &stats[NSS_STATS_PPE_L3_DBG_1]);
-
-	nss_ppe_reg_write(PPE_L3_DBG_WR_OFFSET, PPE_L3_DBG2_OFFSET);
-	nss_ppe_reg_read(PPE_L3_DBG_RD_OFFSET, &stats[NSS_STATS_PPE_L3_DBG_2]);
-
-	nss_ppe_reg_write(PPE_L3_DBG_WR_OFFSET, PPE_L3_DBG3_OFFSET);
-	nss_ppe_reg_read(PPE_L3_DBG_RD_OFFSET, &stats[NSS_STATS_PPE_L3_DBG_3]);
-
-	nss_ppe_reg_write(PPE_L3_DBG_WR_OFFSET, PPE_L3_DBG4_OFFSET);
-	nss_ppe_reg_read(PPE_L3_DBG_RD_OFFSET, &stats[NSS_STATS_PPE_L3_DBG_4]);
-
-	nss_ppe_reg_write(PPE_L3_DBG_WR_OFFSET, PPE_L3_DBG_PORT_OFFSET);
-	nss_ppe_reg_read(PPE_L3_DBG_RD_OFFSET, &stats[NSS_STATS_PPE_L3_DBG_PORT]);
-
-	spin_unlock_bh(&nss_ppe_stats_lock);
-}
-
-/*
- * nss_ppe_stats_code_get()
- *	Get ppe CPU and DROP code for last packet processed.
- */
-void nss_ppe_stats_code_get(uint32_t *stats)
-{
-	uint32_t drop_0, drop_1, cpu_code;
-
-	nss_trace("%s(%d) Start\n", __func__, __LINE__);
-	if (!stats) {
-		nss_warning("No memory to copy ppe code\n");
-		return;
-	}
-
-	if (!nss_ppe_debug_stats.valid) {
-		nss_warning("PPE base address not initialized!\n");
-		return;
-	}
-
-	spin_lock_bh(&nss_ppe_stats_lock);
-	nss_ppe_reg_write(PPE_PKT_CODE_WR_OFFSET, PPE_PKT_CODE_DROP0_OFFSET);
-	nss_ppe_reg_read(PPE_PKT_CODE_RD_OFFSET, &drop_0);
-
-	nss_ppe_reg_write(PPE_PKT_CODE_WR_OFFSET, PPE_PKT_CODE_DROP1_OFFSET);
-	nss_ppe_reg_read(PPE_PKT_CODE_RD_OFFSET, &drop_1);
-
-	stats[NSS_STATS_PPE_CODE_DROP] = PPE_PKT_CODE_DROP_GET(drop_0, drop_1);
-
-	nss_ppe_reg_write(PPE_PKT_CODE_WR_OFFSET, PPE_PKT_CODE_CPU_OFFSET);
-	nss_ppe_reg_read(PPE_PKT_CODE_RD_OFFSET, &cpu_code);
-
-	stats[NSS_STATS_PPE_CODE_CPU] = PPE_PKT_CODE_CPU_GET(cpu_code);
-
-	spin_unlock_bh(&nss_ppe_stats_lock);
-}
-
-/*
- * nss_ppe_port_drop_code_get()
- *	Get ppe per port drop code.
- */
-void nss_ppe_port_drop_code_get(uint32_t *stats, uint8_t port_id)
-{
-	uint8_t i;
-	nss_trace("%s(%d) Start\n", __func__, __LINE__);
-	if (!stats) {
-		nss_warning("No memory to copy ppe code\n");
-		return;
-	}
-
-	if (port_id > NSS_PPE_NUM_PHY_PORTS_MAX) {
-		nss_warning("Port id is out of range\n");
-		return;
-	}
-
-	if (!nss_ppe_debug_stats.valid) {
-		nss_warning("PPE base address not initialized!\n");
-		return;
-	}
-
-	spin_lock_bh(&nss_ppe_stats_lock);
-
-	for (i = 0; i < NSS_STATS_PPE_DROP_CODE_MAX; i++) {
-		nss_ppe_reg_read(PPE_DROP_CODE_OFFSET(i, port_id), &stats[i]);
-	}
-
-	spin_unlock_bh(&nss_ppe_stats_lock);
-}
-
-/*
- * nss_ppe_cpu_code_exception_get()
- *	Get ppe cpu code specific for flow exceptions.
- */
-void nss_ppe_cpu_code_exception_get(uint32_t *stats)
-{
-	uint8_t i;
-	nss_trace("%s(%d) Start\n", __func__, __LINE__);
-	if (!stats) {
-		nss_warning("No memory to copy ppe code\n");
-		return;
-	}
-
-	if (!nss_ppe_debug_stats.valid) {
-		nss_warning("PPE base address not initialized!\n");
-		return;
-	}
-
-	spin_lock_bh(&nss_ppe_stats_lock);
-
-	for (i = 0; i < NSS_STATS_PPE_CPU_CODE_EXCEPTION_MAX ; i++) {
-		nss_ppe_reg_read(PPE_CPU_CODE_OFFSET(i), &stats[i]);
-	}
-
-	spin_unlock_bh(&nss_ppe_stats_lock);
-}
-
-/*
- * nss_ppe_cpu_code_nonexception_get()
- *	Get ppe cpu code specific for flow exceptions.
- */
-void nss_ppe_cpu_code_nonexception_get(uint32_t *stats)
-{
-	uint8_t i;
-	nss_trace("%s(%d) Start\n", __func__, __LINE__);
-	if (!stats) {
-		nss_warning("No memory to copy ppe code\n");
-		return;
-	}
-
-	if (!nss_ppe_debug_stats.valid) {
-		nss_warning("PPE base address not initialized!\n");
-		return;
-	}
-
-	spin_lock_bh(&nss_ppe_stats_lock);
-
-	for (i = 0; i < NSS_STATS_PPE_CPU_CODE_NONEXCEPTION_MAX; i++) {
-		nss_ppe_reg_read(PPE_CPU_CODE_OFFSET(ppe_cc_nonexception[i]), &stats[i]);
-	}
-
-	spin_unlock_bh(&nss_ppe_stats_lock);
-}
-
-/*
  * nss_ppe_handler()
  *	Handle NSS -> HLOS messages for ppe
  */
@@ -578,6 +258,8 @@
 	struct nss_ctx_instance *nss_ctx = nss_ppe_get_context();
 
 	nss_core_register_handler(nss_ctx, NSS_PPE_INTERFACE, nss_ppe_handler, NULL);
+
+	nss_ppe_stats_dentry_create();
 }
 
 /*
diff --git a/nss_ppe.h b/nss_ppe.h
index 7139819..5f4e90e 100644
--- a/nss_ppe.h
+++ b/nss_ppe.h
@@ -74,7 +74,6 @@
  * Data structures to store ppe nss debug stats
  */
 static DEFINE_SPINLOCK(nss_ppe_stats_lock);
-static struct nss_stats_ppe_debug nss_ppe_debug_stats;
 
 /*
  * Private data structure
diff --git a/nss_ppe_stats.c b/nss_ppe_stats.c
new file mode 100644
index 0000000..df4a9d2
--- /dev/null
+++ b/nss_ppe_stats.c
@@ -0,0 +1,1144 @@
+/*
+ **************************************************************************
+ * 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_core.h"
+#include "nss_ppe.h"
+#include "nss_ppe_stats.h"
+
+static uint8_t ppe_cc_nonexception[NSS_PPE_STATS_CPU_CODE_NONEXCEPTION_MAX] = {
+	NSS_PPE_STATS_CPU_CODE_EXP_FAKE_L2_PROT_ERR,
+	NSS_PPE_STATS_CPU_CODE_EXP_FAKE_MAC_HEADER_ERR,
+	NSS_PPE_STATS_CPU_CODE_EXP_BITMAP_MAX,
+	NSS_PPE_STATS_CPU_CODE_L2_EXP_MRU_FAIL,
+	NSS_PPE_STATS_CPU_CODE_L2_EXP_MTU_FAIL,
+	NSS_PPE_STATS_CPU_CODE_L3_EXP_IP_PREFIX_BC,
+	NSS_PPE_STATS_CPU_CODE_L3_EXP_MTU_FAIL,
+	NSS_PPE_STATS_CPU_CODE_L3_EXP_MRU_FAIL,
+	NSS_PPE_STATS_CPU_CODE_L3_EXP_ICMP_RDT,
+	NSS_PPE_STATS_CPU_CODE_L3_EXP_IP_RT_TTL1_TO_ME,
+	NSS_PPE_STATS_CPU_CODE_L3_EXP_IP_RT_TTL_ZERO,
+	NSS_PPE_STATS_CPU_CODE_L3_FLOW_SERVICE_CODE_LOOP,
+	NSS_PPE_STATS_CPU_CODE_L3_FLOW_DE_ACCELERATE,
+	NSS_PPE_STATS_CPU_CODE_L3_EXP_FLOW_SRC_IF_CHK_FAIL,
+	NSS_PPE_STATS_CPU_CODE_L3_FLOW_SYNC_TOGGLE_MISMATCH,
+	NSS_PPE_STATS_CPU_CODE_L3_EXP_MTU_DF_FAIL,
+	NSS_PPE_STATS_CPU_CODE_L3_EXP_PPPOE_MULTICAST,
+	NSS_PPE_STATS_CPU_CODE_MGMT_OFFSET,
+	NSS_PPE_STATS_CPU_CODE_MGMT_EAPOL,
+	NSS_PPE_STATS_CPU_CODE_MGMT_PPPOE_DIS,
+	NSS_PPE_STATS_CPU_CODE_MGMT_IGMP,
+	NSS_PPE_STATS_CPU_CODE_MGMT_ARP_REQ,
+	NSS_PPE_STATS_CPU_CODE_MGMT_ARP_REP,
+	NSS_PPE_STATS_CPU_CODE_MGMT_DHCPv4,
+	NSS_PPE_STATS_CPU_CODE_MGMT_MLD,
+	NSS_PPE_STATS_CPU_CODE_MGMT_NS,
+	NSS_PPE_STATS_CPU_CODE_MGMT_NA,
+	NSS_PPE_STATS_CPU_CODE_MGMT_DHCPv6,
+	NSS_PPE_STATS_CPU_CODE_PTP_OFFSET,
+	NSS_PPE_STATS_CPU_CODE_PTP_SYNC,
+	NSS_PPE_STATS_CPU_CODE_PTP_FOLLOW_UP,
+	NSS_PPE_STATS_CPU_CODE_PTP_DELAY_REQ,
+	NSS_PPE_STATS_CPU_CODE_PTP_DELAY_RESP,
+	NSS_PPE_STATS_CPU_CODE_PTP_PDELAY_REQ,
+	NSS_PPE_STATS_CPU_CODE_PTP_PDELAY_RESP,
+	NSS_PPE_STATS_CPU_CODE_PTP_PDELAY_RESP_FOLLOW_UP,
+	NSS_PPE_STATS_CPU_CODE_PTP_ANNOUNCE,
+	NSS_PPE_STATS_CPU_CODE_PTP_MANAGEMENT,
+	NSS_PPE_STATS_CPU_CODE_PTP_SIGNALING,
+	NSS_PPE_STATS_CPU_CODE_PTP_PKT_RSV_MSG,
+	NSS_PPE_STATS_CPU_CODE_IPV4_SG_UNKNOWN,
+	NSS_PPE_STATS_CPU_CODE_IPV6_SG_UNKNOWN,
+	NSS_PPE_STATS_CPU_CODE_ARP_SG_UNKNOWN,
+	NSS_PPE_STATS_CPU_CODE_ND_SG_UNKNOWN,
+	NSS_PPE_STATS_CPU_CODE_IPV4_SG_VIO,
+	NSS_PPE_STATS_CPU_CODE_IPV6_SG_VIO,
+	NSS_PPE_STATS_CPU_CODE_ARP_SG_VIO,
+	NSS_PPE_STATS_CPU_CODE_ND_SG_VIO,
+	NSS_PPE_STATS_CPU_CODE_L3_ROUTING_IP_TO_ME,
+	NSS_PPE_STATS_CPU_CODE_L3_FLOW_SNAT_ACTION,
+	NSS_PPE_STATS_CPU_CODE_L3_FLOW_DNAT_ACTION,
+	NSS_PPE_STATS_CPU_CODE_L3_FLOW_RT_ACTION,
+	NSS_PPE_STATS_CPU_CODE_L3_FLOW_BR_ACTION,
+	NSS_PPE_STATS_CPU_CODE_L3_MC_BRIDGE_ACTION,
+	NSS_PPE_STATS_CPU_CODE_L3_ROUTE_PREHEAD_RT_ACTION,
+	NSS_PPE_STATS_CPU_CODE_L3_ROUTE_PREHEAD_SNAPT_ACTION,
+	NSS_PPE_STATS_CPU_CODE_L3_ROUTE_PREHEAD_DNAPT_ACTION,
+	NSS_PPE_STATS_CPU_CODE_L3_ROUTE_PREHEAD_SNAT_ACTION,
+	NSS_PPE_STATS_CPU_CODE_L3_ROUTE_PREHEAD_DNAT_ACTION,
+	NSS_PPE_STATS_CPU_CODE_L3_NO_ROUTE_PREHEAD_NAT_ACTION,
+	NSS_PPE_STATS_CPU_CODE_L3_NO_ROUTE_PREHEAD_NAT_ERROR,
+	NSS_PPE_STATS_CPU_CODE_L3_ROUTE_ACTION,
+	NSS_PPE_STATS_CPU_CODE_L3_NO_ROUTE_ACTION,
+	NSS_PPE_STATS_CPU_CODE_L3_NO_ROUTE_NH_INVALID_ACTION,
+	NSS_PPE_STATS_CPU_CODE_L3_NO_ROUTE_PREHEAD_ACTION,
+	NSS_PPE_STATS_CPU_CODE_L3_BRIDGE_ACTION,
+	NSS_PPE_STATS_CPU_CODE_L3_FLOW_ACTION,
+	NSS_PPE_STATS_CPU_CODE_L3_FLOW_MISS_ACTION,
+	NSS_PPE_STATS_CPU_CODE_L2_NEW_MAC_ADDRESS,
+	NSS_PPE_STATS_CPU_CODE_L2_HASH_COLLISION,
+	NSS_PPE_STATS_CPU_CODE_L2_STATION_MOVE,
+	NSS_PPE_STATS_CPU_CODE_L2_LEARN_LIMIT,
+	NSS_PPE_STATS_CPU_CODE_L2_SA_LOOKUP_ACTION,
+	NSS_PPE_STATS_CPU_CODE_L2_DA_LOOKUP_ACTION,
+	NSS_PPE_STATS_CPU_CODE_APP_CTRL_ACTION,
+	NSS_PPE_STATS_CPU_CODE_IN_VLAN_FILTER_ACTION,
+	NSS_PPE_STATS_CPU_CODE_IN_VLAN_XLT_MISS,
+	NSS_PPE_STATS_CPU_CODE_EG_VLAN_FILTER_DROP,
+	NSS_PPE_STATS_CPU_CODE_ACL_PRE_ACTION,
+	NSS_PPE_STATS_CPU_CODE_ACL_POST_ACTION,
+	NSS_PPE_STATS_CPU_CODE_SERVICE_CODE_ACTION,
+};
+
+/*
+ * nss_ppe_stats_str_conn
+ *	PPE statistics strings for nss flow stats
+ */
+static int8_t *nss_ppe_stats_str_conn[NSS_PPE_STATS_CONN_MAX] = {
+	"v4 routed flows",
+	"v4 bridge flows",
+	"v4 conn create req",
+	"v4 conn create fail",
+	"v4 conn destroy req",
+	"v4 conn destroy fail",
+	"v4 conn MC create req",
+	"v4 conn MC create fail",
+	"v4 conn MC update req",
+	"v4 conn MC update fail",
+	"v4 conn MC delete req",
+	"v4 conn MC delete fail",
+
+	"v6 routed flows",
+	"v6 bridge flows",
+	"v6 conn create req",
+	"v6 conn create fail",
+	"v6 conn destroy req",
+	"v6 conn destroy fail",
+	"v6 conn MC create req",
+	"v6 conn MC create fail",
+	"v6 conn MC update req",
+	"v6 conn MC update fail",
+	"v6 conn MC delete req",
+	"v6 conn MC delete fail",
+
+	"conn fail - vp full",
+	"conn fail - nexthop full",
+	"conn fail - flow full",
+	"conn fail - host full",
+	"conn fail - pub-ip full",
+	"conn fail - port not setup",
+	"conn fail - rw fifo full",
+	"conn fail - flow cmd failure",
+	"conn fail - unknown proto",
+	"conn fail - ppe not responding",
+	"conn fail - CE opaque invalid",
+	"conn fail - fqg full"
+};
+
+/*
+ * nss_ppe_stats_str_l3
+ *	PPE statistics strings for nss debug stats
+ */
+static int8_t *nss_ppe_stats_str_l3[NSS_PPE_STATS_L3_MAX] = {
+	"PPE L3 dbg reg 0",
+	"PPE L3 dbg reg 1",
+	"PPE L3 dbg reg 2",
+	"PPE L3 dbg reg 3",
+	"PPE L3 dbg reg 4",
+	"PPE L3 dbg reg port",
+};
+
+/*
+ * nss_ppe_stats_str_code
+ *	PPE statistics strings for nss debug stats
+ */
+static int8_t *nss_ppe_stats_str_code[NSS_PPE_STATS_CODE_MAX] = {
+	"PPE CPU_CODE",
+	"PPE DROP_CODE",
+};
+
+/*
+ * nss_ppe_stats_str_dc
+ *	PPE statistics strings for drop code
+ */
+static int8_t *nss_ppe_stats_str_dc[NSS_PPE_STATS_DROP_CODE_MAX] = {
+	"PPE_DROP_CODE_NONE",
+	"PPE_DROP_CODE_EXP_UNKNOWN_L2_PORT",
+	"PPE_DROP_CODE_EXP_PPPOE_WRONG_VER_TYPE",
+	"PPE_DROP_CODE_EXP_PPPOE_WRONG_CODE",
+	"PPE_DROP_CODE_EXP_PPPOE_UNSUPPORTED_PPP_PROT",
+	"PPE_DROP_CODE_EXP_IPV4_WRONG_VER",
+	"PPE_DROP_CODE_EXP_IPV4_SMALL_IHL",
+	"PPE_DROP_CODE_EXP_IPV4_WITH_OPTION",
+	"PPE_DROP_CODE_EXP_IPV4_HDR_INCOMPLETE",
+	"PPE_DROP_CODE_EXP_IPV4_BAD_TOTAL_LEN",
+	"PPE_DROP_CODE_EXP_IPV4_DATA_INCOMPLETE",
+	"PPE_DROP_CODE_EXP_IPV4_FRAG",
+	"PPE_DROP_CODE_EXP_IPV4_PING_OF_DEATH",
+	"PPE_DROP_CODE_EXP_IPV4_SNALL_TTL",
+	"PPE_DROP_CODE_EXP_IPV4_UNK_IP_PROT",
+	"PPE_DROP_CODE_EXP_IPV4_CHECKSUM_ERR",
+	"PPE_DROP_CODE_EXP_IPV4_INV_SIP",
+	"PPE_DROP_CODE_EXP_IPV4_INV_DIP",
+	"PPE_DROP_CODE_EXP_IPV4_LAND_ATTACK",
+	"PPE_DROP_CODE_EXP_IPV4_AH_HDR_INCOMPLETE",
+	"PPE_DROP_CODE_EXP_IPV4_AH_HDR_CROSS_BORDER",
+	"PPE_DROP_CODE_EXP_IPV4_ESP_HDR_INCOMPLETE",
+	"PPE_DROP_CODE_EXP_IPV6_WRONG_VER",
+	"PPE_DROP_CODE_EXP_IPV6_HDR_INCOMPLETE",
+	"PPE_DROP_CODE_EXP_IPV6_BAD_PAYLOAD_LEN",
+	"PPE_DROP_CODE_EXP_IPV6_DATA_INCOMPLETE",
+	"PPE_DROP_CODE_EXP_IPV6_WITH_EXT_HDR",
+	"PPE_DROP_CODE_EXP_IPV6_SMALL_HOP_LIMIT",
+	"PPE_DROP_CODE_EXP_IPV6_INV_SIP",
+	"PPE_DROP_CODE_EXP_IPV6_INV_DIP",
+	"PPE_DROP_CODE_EXP_IPV6_LAND_ATTACK",
+	"PPE_DROP_CODE_EXP_IPV6_FRAG",
+	"PPE_DROP_CODE_EXP_IPV6_PING_OF_DEATH",
+	"PPE_DROP_CODE_EXP_IPV6_WITH_MORE_EXT_HDR",
+	"PPE_DROP_CODE_EXP_IPV6_UNK_LAST_NEXT_HDR",
+	"PPE_DROP_CODE_EXP_IPV6_MOBILITY_HDR_INCOMPLETE",
+	"PPE_DROP_CODE_EXP_IPV6_MOBILITY_HDR_CROSS_BORDER",
+	"PPE_DROP_CODE_EXP_IPV6_AH_HDR_INCOMPLETE",
+	"PPE_DROP_CODE_EXP_IPV6_AH_HDR_CROSS_BORDER",
+	"PPE_DROP_CODE_EXP_IPV6_ESP_HDR_INCOMPLETE",
+	"PPE_DROP_CODE_EXP_IPV6_ESP_HDR_CROSS_BORDER",
+	"PPE_DROP_CODE_EXP_IPV6_OTHER_EXT_HDR_INCOMPLETE",
+	"PPE_DROP_CODE_EXP_IPV6_OTHER_EXT_HDR_CROSS_BORDER",
+	"PPE_DROP_CODE_EXP_TCP_HDR_INCOMPLETE",
+	"PPE_DROP_CODE_EXP_TCP_HDR_CROSS_BORDER",
+	"PPE_DROP_CODE_EXP_TCP_SMAE_SP_DP",
+	"PPE_DROP_CODE_EXP_TCP_SMALL_DATA_OFFSET",
+	"PPE_DROP_CODE_EXP_TCP_FLAGS_0",
+	"PPE_DROP_CODE_EXP_TCP_FLAGS_1",
+	"PPE_DROP_CODE_EXP_TCP_FLAGS_2",
+	"PPE_DROP_CODE_EXP_TCP_FLAGS_3",
+	"PPE_DROP_CODE_EXP_TCP_FLAGS_4",
+	"PPE_DROP_CODE_EXP_TCP_FLAGS_5",
+	"PPE_DROP_CODE_EXP_TCP_FLAGS_6",
+	"PPE_DROP_CODE_EXP_TCP_FLAGS_7",
+	"PPE_DROP_CODE_EXP_TCP_CHECKSUM_ERR",
+	"PPE_DROP_CODE_EXP_UDP_HDR_INCOMPLETE",
+	"PPE_DROP_CODE_EXP_UDP_HDR_CROSS_BORDER",
+	"PPE_DROP_CODE_EXP_UDP_SMAE_SP_DP",
+	"PPE_DROP_CODE_EXP_UDP_BAD_LEN",
+	"PPE_DROP_CODE_EXP_UDP_DATA_INCOMPLETE",
+	"PPE_DROP_CODE_EXP_UDP_CHECKSUM_ERR",
+	"PPE_DROP_CODE_EXP_UDP_LITE_HDR_INCOMPLETE",
+	"PPE_DROP_CODE_EXP_UDP_LITE_HDR_CROSS_BORDER",
+	"PPE_DROP_CODE_EXP_UDP_LITE_SMAE_SP_DP",
+	"PPE_DROP_CODE_EXP_UDP_LITE_CSM_COV_1_TO_7",
+	"PPE_DROP_CODE_EXP_UDP_LITE_CSM_COV_TOO_LONG",
+	"PPE_DROP_CODE_EXP_UDP_LITE_CSM_COV_CROSS_BORDER",
+	"PPE_DROP_CODE_EXP_UDP_LITE_CHECKSUM_ERR",
+	"PPE_DROP_CODE_L3_MC_BRIDGE_ACTION",
+	"PPE_DROP_CODE_L3_NO_ROUTE_PREHEAD_NAT_ACTION",
+	"PPE_DROP_CODE_L3_NO_ROUTE_PREHEAD_NAT_ERROR",
+	"PPE_DROP_CODE_L3_ROUTE_ACTION",
+	"PPE_DROP_CODE_L3_NO_ROUTE_ACTION",
+	"PPE_DROP_CODE_L3_NO_ROUTE_NH_INVALID_ACTION",
+	"PPE_DROP_CODE_L3_NO_ROUTE_PREHEAD_ACTION",
+	"PPE_DROP_CODE_L3_BRIDGE_ACTION",
+	"PPE_DROP_CODE_L3_FLOW_ACTION",
+	"PPE_DROP_CODE_L3_FLOW_MISS_ACTION",
+	"PPE_DROP_CODE_L2_EXP_MRU_FAIL",
+	"PPE_DROP_CODE_L2_EXP_MTU_FAIL",
+	"PPE_DROP_CODE_L3_EXP_IP_PREFIX_BC",
+	"PPE_DROP_CODE_L3_EXP_MTU_FAIL",
+	"PPE_DROP_CODE_L3_EXP_MRU_FAIL",
+	"PPE_DROP_CODE_L3_EXP_ICMP_RDT",
+	"PPE_DROP_CODE_FAKE_MAC_HEADER_ERR",
+	"PPE_DROP_CODE_L3_EXP_IP_RT_TTL_ZERO",
+	"PPE_DROP_CODE_L3_FLOW_SERVICE_CODE_LOOP",
+	"PPE_DROP_CODE_L3_FLOW_DE_ACCELEARTE",
+	"PPE_DROP_CODE_L3_EXP_FLOW_SRC_IF_CHK_FAIL",
+	"PPE_DROP_CODE_L3_FLOW_SYNC_TOGGLE_MISMATCH",
+	"PPE_DROP_CODE_L3_EXP_MTU_DF_FAIL",
+	"PPE_DROP_CODE_L3_EXP_PPPOE_MULTICAST",
+	"PPE_DROP_CODE_IPV4_SG_UNKNOWN",
+	"PPE_DROP_CODE_IPV6_SG_UNKNOWN",
+	"PPE_DROP_CODE_ARP_SG_UNKNOWN",
+	"PPE_DROP_CODE_ND_SG_UNKNOWN",
+	"PPE_DROP_CODE_IPV4_SG_VIO",
+	"PPE_DROP_CODE_IPV6_SG_VIO",
+	"PPE_DROP_CODE_ARP_SG_VIO",
+	"PPE_DROP_CODE_ND_SG_VIO",
+	"PPE_DROP_CODE_L2_NEW_MAC_ADDRESS",
+	"PPE_DROP_CODE_L2_HASH_COLLISION",
+	"PPE_DROP_CODE_L2_STATION_MOVE",
+	"PPE_DROP_CODE_L2_LEARN_LIMIT",
+	"PPE_DROP_CODE_L2_SA_LOOKUP_ACTION",
+	"PPE_DROP_CODE_L2_DA_LOOKUP_ACTION",
+	"PPE_DROP_CODE_APP_CTRL_ACTION",
+	"PPE_DROP_CODE_IN_VLAN_FILTER_ACTION",
+	"PPE_DROP_CODE_IN_VLAN_XLT_MISS",
+	"PPE_DROP_CODE_EG_VLAN_FILTER_DROP",
+	"PPE_DROP_CODE_ACL_PRE_ACTION",
+	"PPE_DROP_CODE_ACL_POST_ACTION",
+	"PPE_DROP_CODE_MC_BC_SA",
+	"PPE_DROP_CODE_NO_DESTINATION",
+	"PPE_DROP_CODE_STG_IN_FILTER",
+	"PPE_DROP_CODE_STG_EG_FILTER",
+	"PPE_DROP_CODE_SOURCE_FILTER_FAIL",
+	"PPE_DROP_CODE_TRUNK_SEL_FAIL",
+	"PPE_DROP_CODE_TX_EN_FAIL",
+	"PPE_DROP_CODE_VLAN_TAG_FMT",
+	"PPE_DROP_CODE_CRC_ERR",
+	"PPE_DROP_CODE_PAUSE_FRAME",
+	"PPE_DROP_CODE_PROMISC",
+	"PPE_DROP_CODE_ISOLATION",
+	"PPE_DROP_CODE_MGMT_APP",
+	"PPE_DROP_CODE_FAKE_L2_PROT_ERR",
+	"PPE_DROP_CODE_POLICER",
+};
+
+/*
+ * nss_ppe_stats_str_cc
+ *      PPE statistics strings for cpu code
+ */
+static int8_t *nss_ppe_stats_str_cc[NSS_PPE_STATS_CPU_CODE_MAX] = {
+	"PPE_CPU_CODE_FORWARDING",
+	"PPE_CPU_CODE_EXP_UNKNOWN_L2_PROT",
+	"PPE_CPU_CODE_EXP_PPPOE_WRONG_VER_TYPE",
+	"PPE_CPU_CODE_EXP_WRONG_CODE",
+	"PPE_CPU_CODE_EXP_PPPOE_UNSUPPORTED_PPP_PROT",
+	"PPE_CPU_CODE_EXP_WRONG_VER",
+	"PPE_CPU_CODE_EXP_SMALL_IHL",
+	"PPE_CPU_CODE_EXP_WITH_OPTION",
+	"PPE_CPU_CODE_EXP_HDR_INCOMPLETE",
+	"PPE_CPU_CODE_EXP_IPV4_BAD_TOTAL_LEN",
+	"PPE_CPU_CODE_EXP_DATA_INCOMPLETE",
+	"PPE_CPU_CODE_IPV4_FRAG",
+	"PPE_CPU_CODE_EXP_IPV4_PING_OF_DEATH",
+	"PPE_CPU_CODE_EXP_SNALL_TTL",
+	"PPE_CPU_CODE_EXP_IPV4_UNK_IP_PROT",
+	"PPE_CPU_CODE_EXP_CHECKSUM_ERR",
+	"PPE_CPU_CODE_EXP_INV_SIP",
+	"PPE_CPU_CODE_EXP_INV_DIP",
+	"PPE_CPU_CODE_EXP_LAND_ATTACK",
+	"PPE_CPU_CODE_EXP_IPV4_AH_HDR_INCOMPLETE",
+	"PPE_CPU_CODE_EXP_IPV4_AH_CROSS_BORDER",
+	"PPE_CPU_CODE_EXP_IPV4_ESP_HDR_INCOMPLETE",
+	"PPE_CPU_CODE_EXP_WRONG_VER",
+	"PPE_CPU_CODE_EXP_HDR_INCOMPLETE",
+	"PPE_CPU_CODE_EXP_IPV6_BAD_PAYLOAD_LEN",
+	"PPE_CPU_CODE_EXP_DATA_INCOMPLETE",
+	"PPE_CPU_CODE_EXP_IPV6_WITH_EXT_HDR",
+	"PPE_CPU_CODE_EXP_IPV6_SMALL_HOP_LIMIT",
+	"PPE_CPU_CODE_EXP_INV_SIP",
+	"PPE_CPU_CODE_EXP_INV_DIP",
+	"PPE_CPU_CODE_EXP_LAND_ATTACK",
+	"PPE_CPU_CODE_IPV6_FRAG",
+	"PPE_CPU_CODE_EXP_IPV6_PING_OF_DEATH",
+	"PPE_CPU_CODE_EXP_IPV6_WITH_EXT_HDR",
+	"PPE_CPU_CODE_EXP_IPV6_UNK_NEXT_HDR",
+	"PPE_CPU_CODE_EXP_IPV6_MOBILITY_HDR_INCOMPLETE",
+	"PPE_CPU_CODE_EXP_IPV6_MOBILITY_CROSS_BORDER",
+	"PPE_CPU_CODE_EXP_IPV6_AH_HDR_INCOMPLETE",
+	"PPE_CPU_CODE_EXP_IPV6_AH_CROSS_BORDER",
+	"PPE_CPU_CODE_EXP_IPV6_ESP_HDR_INCOMPLETE",
+	"PPE_CPU_CODE_EXP_IPV6_ESP_CROSS_BORDER",
+	"PPE_CPU_CODE_EXP_IPV6_OTHER_HDR_INCOMPLETE",
+	"PPE_CPU_CODE_EXP_IPV6_OTHER_EXT_CROSS_BORDER",
+	"PPE_CPU_CODE_EXP_HDR_INCOMPLETE",
+	"PPE_CPU_CODE_EXP_TCP_HDR_CROSS_BORDER",
+	"PPE_CPU_CODE_EXP_TCP_SMAE_SP_DP",
+	"PPE_CPU_CODE_EXP_TCP_SMALL_DATA_OFFSET",
+	"PPE_CPU_CODE_EXP_FLAGS_0",
+	"PPE_CPU_CODE_EXP_FLAGS_1",
+	"PPE_CPU_CODE_EXP_FLAGS_2",
+	"PPE_CPU_CODE_EXP_FLAGS_3",
+	"PPE_CPU_CODE_EXP_FLAGS_4",
+	"PPE_CPU_CODE_EXP_FLAGS_5",
+	"PPE_CPU_CODE_EXP_FLAGS_6",
+	"PPE_CPU_CODE_EXP_FLAGS_7",
+	"PPE_CPU_CODE_EXP_CHECKSUM_ERR",
+	"PPE_CPU_CODE_EXP_HDR_INCOMPLETE",
+	"PPE_CPU_CODE_EXP_UDP_HDR_CROSS_BORDER",
+	"PPE_CPU_CODE_EXP_UDP_SMAE_SP_DP",
+	"PPE_CPU_CODE_EXP_BAD_LEN",
+	"PPE_CPU_CODE_EXP_DATA_INCOMPLETE",
+	"PPE_CPU_CODE_EXP_CHECKSUM_ERR",
+	"PPE_CPU_CODE_EXP_UDP_LITE_HDR_INCOMPLETE",
+	"PPE_CPU_CODE_EXP_UDP_LITE_CROSS_BORDER",
+	"PPE_CPU_CODE_EXP_UDP_LITE_SP_DP",
+	"PPE_CPU_CODE_EXP_UDP_LITE_CSM_COV_TO_7",
+	"PPE_CPU_CODE_EXP_UDP_LITE_CSM_TOO_LONG",
+	"PPE_CPU_CODE_EXP_UDP_LITE_CSM_CROSS_BORDER",
+	"PPE_CPU_CODE_EXP_UDP_LITE_CHECKSUM_ERR",
+	"PPE_CPU_CODE_EXP_FAKE_L2_PROT_ERR",
+	"PPE_CPU_CODE_EXP_FAKE_MAC_HEADER_ERR",
+	"PPE_CPU_CODE_BITMAP_MAX",
+	"PPE_CPU_CODE_L2_MRU_FAIL",
+	"PPE_CPU_CODE_L2_MTU_FAIL",
+	"PPE_CPU_CODE_L3_EXP_IP_PREFIX_BC",
+	"PPE_CPU_CODE_L3_MTU_FAIL",
+	"PPE_CPU_CODE_L3_MRU_FAIL",
+	"PPE_CPU_CODE_L3_ICMP_RDT",
+	"PPE_CPU_CODE_L3_EXP_IP_RT_TO_ME",
+	"PPE_CPU_CODE_L3_EXP_IP_TTL_ZERO",
+	"PPE_CPU_CODE_L3_FLOW_SERVICE_CODE_LOOP",
+	"PPE_CPU_CODE_L3_DE_ACCELERATE",
+	"PPE_CPU_CODE_L3_EXP_FLOW_SRC_CHK_FAIL",
+	"PPE_CPU_CODE_L3_FLOW_SYNC_TOGGLE_MISMATCH",
+	"PPE_CPU_CODE_L3_EXP_MTU_DF_FAIL",
+	"PPE_CPU_CODE_L3_PPPOE_MULTICAST",
+	"PPE_CPU_CODE_MGMT_OFFSET",
+	"PPE_CPU_CODE_MGMT_EAPOL",
+	"PPE_CPU_CODE_PPPOE_DIS",
+	"PPE_CPU_CODE_MGMT_IGMP",
+	"PPE_CPU_CODE_ARP_REQ",
+	"PPE_CPU_CODE_ARP_REP",
+	"PPE_CPU_CODE_MGMT_DHCPv4",
+	"PPE_CPU_CODE_MGMT_MLD",
+	"PPE_CPU_CODE_MGMT_NS",
+	"PPE_CPU_CODE_MGMT_NA",
+	"PPE_CPU_CODE_MGMT_DHCPv6",
+	"PPE_CPU_CODE_PTP_OFFSET",
+	"PPE_CPU_CODE_PTP_SYNC",
+	"PPE_CPU_CODE_FOLLOW_UP",
+	"PPE_CPU_CODE_DELAY_REQ",
+	"PPE_CPU_CODE_DELAY_RESP",
+	"PPE_CPU_CODE_PDELAY_REQ",
+	"PPE_CPU_CODE_PDELAY_RESP",
+	"PPE_CPU_CODE_PTP_PDELAY_RESP_FOLLOW_UP",
+	"PPE_CPU_CODE_PTP_ANNOUNCE",
+	"PPE_CPU_CODE_PTP_MANAGEMENT",
+	"PPE_CPU_CODE_PTP_SIGNALING",
+	"PPE_CPU_CODE_PTP_RSV_MSG",
+	"PPE_CPU_CODE_SG_UNKNOWN",
+	"PPE_CPU_CODE_SG_UNKNOWN",
+	"PPE_CPU_CODE_SG_UNKNOWN",
+	"PPE_CPU_CODE_SG_UNKNOWN",
+	"PPE_CPU_CODE_SG_VIO",
+	"PPE_CPU_CODE_SG_VIO",
+	"PPE_CPU_CODE_SG_VIO",
+	"PPE_CPU_CODE_SG_VIO",
+	"PPE_CPU_CODE_L3_ROUTING_IP_TO_ME",
+	"PPE_CPU_CODE_L3_SNAT_ACTION",
+	"PPE_CPU_CODE_L3_DNAT_ACTION",
+	"PPE_CPU_CODE_L3_RT_ACTION",
+	"PPE_CPU_CODE_L3_BR_ACTION",
+	"PPE_CPU_CODE_L3_BRIDGE_ACTION",
+	"PPE_CPU_CODE_L3_ROUTE_PREHEAD_RT_ACTION",
+	"PPE_CPU_CODE_L3_ROUTE_PREHEAD_SNAPT_ACTION",
+	"PPE_CPU_CODE_L3_ROUTE_PREHEAD_DNAPT_ACTION",
+	"PPE_CPU_CODE_L3_ROUTE_PREHEAD_SNAT_ACTION",
+	"PPE_CPU_CODE_L3_ROUTE_PREHEAD_DNAT_ACTION",
+	"PPE_CPU_CODE_L3_NO_ROUTE_NAT_ACTION",
+	"PPE_CPU_CODE_L3_NO_ROUTE_NAT_ERROR",
+	"PPE_CPU_CODE_ROUTE_ACTION",
+	"PPE_CPU_CODE_L3_ROUTE_ACTION",
+	"PPE_CPU_CODE_L3_NO_ROUTE_INVALID_ACTION",
+	"PPE_CPU_CODE_L3_NO_ROUTE_PREHEAD_ACTION",
+	"PPE_CPU_CODE_BRIDGE_ACTION",
+	"PPE_CPU_CODE_FLOW_ACTION",
+	"PPE_CPU_CODE_L3_MISS_ACTION",
+	"PPE_CPU_CODE_L2_MAC_ADDRESS",
+	"PPE_CPU_CODE_HASH_COLLISION",
+	"PPE_CPU_CODE_STATION_MOVE",
+	"PPE_CPU_CODE_LEARN_LIMIT",
+	"PPE_CPU_CODE_L2_LOOKUP_ACTION",
+	"PPE_CPU_CODE_L2_LOOKUP_ACTION",
+	"PPE_CPU_CODE_CTRL_ACTION",
+	"PPE_CPU_CODE_IN_FILTER_ACTION",
+	"PPE_CPU_CODE_IN_XLT_MISS",
+	"PPE_CPU_CODE_EG_FILTER_DROP",
+	"PPE_CPU_CODE_PRE_ACTION",
+	"PPE_CPU_CODE_POST_ACTION",
+	"PPE_CPU_CODE_CODE_ACTION",
+};
+
+/*
+ * nss_ppe_stats_sync
+ *	PPE connection sync statistics from NSS
+ */
+void nss_ppe_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_ppe_sync_stats_msg *stats_msg, uint16_t if_num)
+{
+	spin_lock_bh(&nss_ppe_stats_lock);
+	nss_ppe_debug_stats.conn_stats[NSS_PPE_STATS_V4_L3_FLOWS] += stats_msg->nss_ppe_v4_l3_flows;
+	nss_ppe_debug_stats.conn_stats[NSS_PPE_STATS_V4_L2_FLOWS] += stats_msg->nss_ppe_v4_l2_flows;
+	nss_ppe_debug_stats.conn_stats[NSS_PPE_STATS_V4_CREATE_REQ] += stats_msg->nss_ppe_v4_create_req;
+	nss_ppe_debug_stats.conn_stats[NSS_PPE_STATS_V4_CREATE_FAIL] += stats_msg->nss_ppe_v4_create_fail;
+	nss_ppe_debug_stats.conn_stats[NSS_PPE_STATS_V4_DESTROY_REQ] += stats_msg->nss_ppe_v4_destroy_req;
+	nss_ppe_debug_stats.conn_stats[NSS_PPE_STATS_V4_DESTROY_FAIL] += stats_msg->nss_ppe_v4_destroy_fail;
+
+	nss_ppe_debug_stats.conn_stats[NSS_PPE_STATS_V6_L3_FLOWS] += stats_msg->nss_ppe_v6_l3_flows;
+	nss_ppe_debug_stats.conn_stats[NSS_PPE_STATS_V6_L2_FLOWS] += stats_msg->nss_ppe_v6_l2_flows;
+	nss_ppe_debug_stats.conn_stats[NSS_PPE_STATS_V6_CREATE_REQ] += stats_msg->nss_ppe_v6_create_req;
+	nss_ppe_debug_stats.conn_stats[NSS_PPE_STATS_V6_CREATE_FAIL] += stats_msg->nss_ppe_v6_create_fail;
+	nss_ppe_debug_stats.conn_stats[NSS_PPE_STATS_V6_DESTROY_REQ] += stats_msg->nss_ppe_v6_destroy_req;
+	nss_ppe_debug_stats.conn_stats[NSS_PPE_STATS_V6_DESTROY_FAIL] += stats_msg->nss_ppe_v6_destroy_fail;
+
+	nss_ppe_debug_stats.conn_stats[NSS_PPE_STATS_FAIL_NH_FULL] += stats_msg->nss_ppe_fail_nh_full;
+	nss_ppe_debug_stats.conn_stats[NSS_PPE_STATS_FAIL_FLOW_FULL] += stats_msg->nss_ppe_fail_flow_full;
+	nss_ppe_debug_stats.conn_stats[NSS_PPE_STATS_FAIL_HOST_FULL] += stats_msg->nss_ppe_fail_host_full;
+	nss_ppe_debug_stats.conn_stats[NSS_PPE_STATS_FAIL_PUBIP_FULL] += stats_msg->nss_ppe_fail_pubip_full;
+	nss_ppe_debug_stats.conn_stats[NSS_PPE_STATS_FAIL_PORT_SETUP] += stats_msg->nss_ppe_fail_port_setup;
+	nss_ppe_debug_stats.conn_stats[NSS_PPE_STATS_FAIL_RW_FIFO_FULL] += stats_msg->nss_ppe_fail_rw_fifo_full;
+	nss_ppe_debug_stats.conn_stats[NSS_PPE_STATS_FAIL_FLOW_COMMAND] += stats_msg->nss_ppe_fail_flow_command;
+	nss_ppe_debug_stats.conn_stats[NSS_PPE_STATS_FAIL_UNKNOWN_PROTO] += stats_msg->nss_ppe_fail_unknown_proto;
+	nss_ppe_debug_stats.conn_stats[NSS_PPE_STATS_FAIL_PPE_UNRESPONSIVE] += stats_msg->nss_ppe_fail_ppe_unresponsive;
+	nss_ppe_debug_stats.conn_stats[NSS_PPE_STATS_FAIL_FQG_FULL] += stats_msg->nss_ppe_fail_fqg_full;
+	spin_unlock_bh(&nss_ppe_stats_lock);
+}
+
+/*
+ * nss_ppe_stats_conn_get()
+ *	Get PPE connection statistics.
+ */
+void nss_ppe_stats_conn_get(uint32_t *stats)
+{
+	if (!stats) {
+		nss_warning("No memory to copy ppe connection stats");
+		return;
+	}
+
+	spin_lock_bh(&nss_ppe_stats_lock);
+
+	if (!nss_ppe_debug_stats.valid) {
+		spin_unlock_bh(&nss_ppe_stats_lock);
+		nss_warning("PPE base address not initialized!\n");
+		return;
+	}
+
+	/*
+	 * Get flow stats
+	 */
+	memcpy(stats, nss_ppe_debug_stats.conn_stats, (sizeof(uint32_t) * NSS_PPE_STATS_CONN_MAX));
+
+	spin_unlock_bh(&nss_ppe_stats_lock);
+}
+
+/*
+ * nss_ppe_stats_l3_get()
+ *	Get PPE L3 debug statistics.
+ */
+void nss_ppe_stats_l3_get(uint32_t *stats)
+{
+	if (!stats) {
+		nss_warning("No memory to copy ppe l3 dbg stats\n");
+		return;
+	}
+
+	spin_lock_bh(&nss_ppe_stats_lock);
+
+	if (!nss_ppe_debug_stats.valid) {
+		spin_unlock_bh(&nss_ppe_stats_lock);
+		nss_warning("PPE base address not initialized!\n");
+		return;
+	}
+
+	nss_ppe_reg_write(PPE_L3_DBG_WR_OFFSET, PPE_L3_DBG0_OFFSET);
+	nss_ppe_reg_read(PPE_L3_DBG_RD_OFFSET, &stats[NSS_PPE_STATS_L3_DBG_0]);
+
+	nss_ppe_reg_write(PPE_L3_DBG_WR_OFFSET, PPE_L3_DBG1_OFFSET);
+	nss_ppe_reg_read(PPE_L3_DBG_RD_OFFSET, &stats[NSS_PPE_STATS_L3_DBG_1]);
+
+	nss_ppe_reg_write(PPE_L3_DBG_WR_OFFSET, PPE_L3_DBG2_OFFSET);
+	nss_ppe_reg_read(PPE_L3_DBG_RD_OFFSET, &stats[NSS_PPE_STATS_L3_DBG_2]);
+
+	nss_ppe_reg_write(PPE_L3_DBG_WR_OFFSET, PPE_L3_DBG3_OFFSET);
+	nss_ppe_reg_read(PPE_L3_DBG_RD_OFFSET, &stats[NSS_PPE_STATS_L3_DBG_3]);
+
+	nss_ppe_reg_write(PPE_L3_DBG_WR_OFFSET, PPE_L3_DBG4_OFFSET);
+	nss_ppe_reg_read(PPE_L3_DBG_RD_OFFSET, &stats[NSS_PPE_STATS_L3_DBG_4]);
+
+	nss_ppe_reg_write(PPE_L3_DBG_WR_OFFSET, PPE_L3_DBG_PORT_OFFSET);
+	nss_ppe_reg_read(PPE_L3_DBG_RD_OFFSET, &stats[NSS_PPE_STATS_L3_DBG_PORT]);
+
+	spin_unlock_bh(&nss_ppe_stats_lock);
+}
+
+/*
+ * nss_ppe_stats_code_get()
+ *	Get PPE CPU and DROP code for last packet processed.
+ */
+void nss_ppe_stats_code_get(uint32_t *stats)
+{
+	uint32_t drop_0, drop_1, cpu_code;
+
+	nss_trace("%s(%d) Start\n", __func__, __LINE__);
+	if (!stats) {
+		nss_warning("No memory to copy ppe code\n");
+		return;
+	}
+
+	if (!nss_ppe_debug_stats.valid) {
+		nss_warning("PPE base address not initialized!\n");
+		return;
+	}
+
+	spin_lock_bh(&nss_ppe_stats_lock);
+	nss_ppe_reg_write(PPE_PKT_CODE_WR_OFFSET, PPE_PKT_CODE_DROP0_OFFSET);
+	nss_ppe_reg_read(PPE_PKT_CODE_RD_OFFSET, &drop_0);
+
+	nss_ppe_reg_write(PPE_PKT_CODE_WR_OFFSET, PPE_PKT_CODE_DROP1_OFFSET);
+	nss_ppe_reg_read(PPE_PKT_CODE_RD_OFFSET, &drop_1);
+
+	stats[NSS_PPE_STATS_CODE_DROP] = PPE_PKT_CODE_DROP_GET(drop_0, drop_1);
+
+	nss_ppe_reg_write(PPE_PKT_CODE_WR_OFFSET, PPE_PKT_CODE_CPU_OFFSET);
+	nss_ppe_reg_read(PPE_PKT_CODE_RD_OFFSET, &cpu_code);
+
+	stats[NSS_PPE_STATS_CODE_CPU] = PPE_PKT_CODE_CPU_GET(cpu_code);
+
+	spin_unlock_bh(&nss_ppe_stats_lock);
+}
+
+/*
+ * nss_ppe_port_drop_code_get()
+ *	Get ppe per port drop code.
+ */
+void nss_ppe_port_drop_code_get(uint32_t *stats, uint8_t port_id)
+{
+	uint8_t i;
+	nss_trace("%s(%d) Start\n", __func__, __LINE__);
+	if (!stats) {
+		nss_warning("No memory to copy ppe code\n");
+		return;
+	}
+
+	if (port_id > NSS_PPE_NUM_PHY_PORTS_MAX) {
+		nss_warning("Port id is out of range\n");
+		return;
+	}
+
+	if (!nss_ppe_debug_stats.valid) {
+		nss_warning("PPE base address not initialized!\n");
+		return;
+	}
+
+	spin_lock_bh(&nss_ppe_stats_lock);
+
+	for (i = 0; i < NSS_PPE_STATS_DROP_CODE_MAX; i++) {
+		nss_ppe_reg_read(PPE_DROP_CODE_OFFSET(i, port_id), &stats[i]);
+	}
+
+	spin_unlock_bh(&nss_ppe_stats_lock);
+}
+
+/*
+ * nss_ppe_cpu_code_exception_get()
+ *	Get ppe cpu code specific for flow exceptions.
+ */
+void nss_ppe_cpu_code_exception_get(uint32_t *stats)
+{
+	uint8_t i;
+	nss_trace("%s(%d) Start\n", __func__, __LINE__);
+	if (!stats) {
+		nss_warning("No memory to copy ppe code\n");
+		return;
+	}
+
+	if (!nss_ppe_debug_stats.valid) {
+		nss_warning("PPE base address not initialized!\n");
+		return;
+	}
+
+	spin_lock_bh(&nss_ppe_stats_lock);
+
+	for (i = 0; i < NSS_PPE_STATS_CPU_CODE_EXCEPTION_MAX ; i++) {
+		nss_ppe_reg_read(PPE_CPU_CODE_OFFSET(i), &stats[i]);
+	}
+
+	spin_unlock_bh(&nss_ppe_stats_lock);
+}
+
+/*
+ * nss_ppe_cpu_code_nonexception_get()
+ *	Get ppe cpu code specific for flow exceptions.
+ */
+void nss_ppe_cpu_code_nonexception_get(uint32_t *stats)
+{
+	uint8_t i;
+	nss_trace("%s(%d) Start\n", __func__, __LINE__);
+	if (!stats) {
+		nss_warning("No memory to copy ppe code\n");
+		return;
+	}
+
+	if (!nss_ppe_debug_stats.valid) {
+		nss_warning("PPE base address not initialized!\n");
+		return;
+	}
+
+	spin_lock_bh(&nss_ppe_stats_lock);
+
+	for (i = 0; i < NSS_PPE_STATS_CPU_CODE_NONEXCEPTION_MAX; i++) {
+		nss_ppe_reg_read(PPE_CPU_CODE_OFFSET(ppe_cc_nonexception[i]), &stats[i]);
+	}
+
+	spin_unlock_bh(&nss_ppe_stats_lock);
+}
+
+/*
+ * nss_ppe_conn_stats_read()
+ *	Read ppe connection statistics
+ */
+static ssize_t nss_ppe_conn_stats_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
+{
+	int i;
+	char *lbuf = NULL;
+	size_t size_wr = 0;
+	ssize_t bytes_read = 0;
+	uint32_t ppe_stats[NSS_PPE_STATS_CONN_MAX];
+	uint32_t max_output_lines = 2 /* header & footer for session stats */
+				+ NSS_PPE_STATS_CONN_MAX /* PPE flow counters */
+				+ 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");
+		return 0;
+	}
+
+	memset(ppe_stats, 0, sizeof(uint32_t) * NSS_PPE_STATS_CONN_MAX);
+
+	/*
+	 * Get all stats
+	 */
+	nss_ppe_stats_conn_get(ppe_stats);
+
+	/*
+	 * flow stats
+	 */
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nppe flow counters start:\n\n");
+
+	for (i = 0; i < NSS_PPE_STATS_CONN_MAX; i++) {
+		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
+				"\t%s = %u\n", nss_ppe_stats_str_conn[i],
+				ppe_stats[i]);
+	}
+
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\n");
+
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nppe flow counters end\n");
+	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, size_wr);
+
+	kfree(lbuf);
+	return bytes_read;
+}
+
+/*
+ * nss_ppe_l3_stats_read()
+ *	Read PPE L3 debug statistics
+ */
+static ssize_t nss_ppe_l3_stats_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
+{
+	int i;
+	char *lbuf = NULL;
+	size_t size_wr = 0;
+	ssize_t bytes_read = 0;
+	uint32_t ppe_stats[NSS_PPE_STATS_L3_MAX];
+	uint32_t max_output_lines = 2 /* header & footer for session stats */
+				+ NSS_PPE_STATS_L3_MAX /* PPE flow counters */
+				+ 2;
+	size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
+
+	lbuf = kzalloc(size_al, GFP_KERNEL);
+	if (unlikely(!lbuf)) {
+		nss_warning("Could not allocate memory for local statistics buffer");
+		return 0;
+	}
+
+	memset(ppe_stats, 0, sizeof(uint32_t) * NSS_PPE_STATS_L3_MAX);
+
+	/*
+	 * Get all stats
+	 */
+	nss_ppe_stats_l3_get(ppe_stats);
+
+	/*
+	 * flow stats
+	 */
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nppe l3 debug stats start:\n\n");
+
+	for (i = 0; i < NSS_PPE_STATS_L3_MAX; i++) {
+		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
+				"\t%s = 0x%x\n", nss_ppe_stats_str_l3[i],
+				ppe_stats[i]);
+	}
+
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\n");
+
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nppe l3 debug stats end\n");
+	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, size_wr);
+
+	kfree(lbuf);
+	return bytes_read;
+}
+
+/*
+ * nss_ppe_code_stats_read()
+ *	Read ppe CPU & DROP code
+ */
+static ssize_t nss_ppe_code_stats_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
+{
+	int i;
+	char *lbuf = NULL;
+	size_t size_wr = 0;
+	ssize_t bytes_read = 0;
+	uint32_t ppe_stats[NSS_PPE_STATS_CODE_MAX];
+	uint32_t max_output_lines = 2 /* header & footer for session stats */
+				+ NSS_PPE_STATS_CODE_MAX /* PPE flow counters */
+				+ 2;
+	size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
+
+	lbuf = kzalloc(size_al, GFP_KERNEL);
+	if (unlikely(!lbuf)) {
+		nss_warning("Could not allocate memory for local statistics buffer");
+		return 0;
+	}
+
+	memset(ppe_stats, 0, sizeof(uint32_t) * NSS_PPE_STATS_CODE_MAX);
+
+	/*
+	 * Get all stats
+	 */
+	nss_ppe_stats_code_get(ppe_stats);
+
+	/*
+	 * flow stats
+	 */
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nppe session stats start:\n\n");
+
+	for (i = 0; i < NSS_PPE_STATS_CODE_MAX; i++) {
+		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
+				"\t%s = %u\n", nss_ppe_stats_str_code[i],
+				ppe_stats[i]);
+	}
+
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\n");
+
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nppe session stats end\n");
+	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, size_wr);
+
+	kfree(lbuf);
+	return bytes_read;
+}
+
+/*
+ * nss_ppe_port_dc_stats_read()
+ *      Read PPE per port drop code stats
+ */
+static ssize_t nss_ppe_port_dc_stats_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
+{
+	int32_t i;
+
+	/*
+	 * max output lines = #stats + 2 start tag line + 2 end tag line + five blank lines
+	 */
+	uint32_t max_output_lines = (NSS_PPE_STATS_DROP_CODE_MAX + 4) + 5;
+	size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
+	size_t size_wr = 0;
+	ssize_t bytes_read = 0;
+	struct nss_stats_data *data = fp->private_data;
+	uint32_t *ppe_stats;
+
+	char *lbuf = kzalloc(size_al, GFP_KERNEL);
+	if (unlikely(lbuf == NULL)) {
+		nss_warning("Could not allocate memory for local statistics buffer");
+		return 0;
+	}
+
+	ppe_stats = kzalloc(sizeof(uint32_t) * NSS_PPE_STATS_DROP_CODE_MAX, GFP_KERNEL);
+	if (unlikely(ppe_stats == NULL)) {
+		kfree(lbuf);
+		nss_warning("Could not allocate memory for ppe stats buffer");
+		return 0;
+	}
+
+	/*
+	 * Get drop code counters for specific port
+	 */
+	nss_ppe_port_drop_code_get(ppe_stats, data->edma_id);
+	size_wr = scnprintf(lbuf, size_al, "ppe no drop code stats start:\n\n");
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
+				"\t%s = %u\n", nss_ppe_stats_str_dc[0],
+				ppe_stats[0]);
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nppe no drop code stats end\n\n");
+
+	/*
+	 * Drop code stats
+	 */
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "ppe non-zero drop code stats start:\n\n");
+	for (i = 1; i < NSS_PPE_STATS_DROP_CODE_MAX; i++) {
+		/*
+		 * Print only non-zero stats.
+		 */
+		if (!ppe_stats[i]) {
+			continue;
+		}
+
+		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
+				"\t%s = %u\n", nss_ppe_stats_str_dc[i],
+				ppe_stats[i]);
+	}
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nppe non-zero drop code stats end\n\n");
+
+	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
+	kfree(ppe_stats);
+	kfree(lbuf);
+
+	return bytes_read;
+}
+
+/*
+ * nss_ppe_exception_cc_stats_read()
+ *	Read PPE CPU code stats specific to flow exceptions
+ */
+static ssize_t nss_ppe_exception_cc_stats_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
+{
+	int32_t i;
+
+	/*
+	 * max output lines = #stats + start tag line + end tag line + three blank lines
+	 */
+	uint32_t max_output_lines = (NSS_PPE_STATS_CPU_CODE_EXCEPTION_MAX + 2) + 3;
+	size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
+	size_t size_wr = 0;
+	ssize_t bytes_read = 0;
+	uint32_t *ppe_stats;
+
+	char *lbuf = kzalloc(size_al, GFP_KERNEL);
+	if (unlikely(lbuf == NULL)) {
+		nss_warning("Could not allocate memory for local statistics buffer");
+		return 0;
+	}
+
+	ppe_stats = kzalloc(sizeof(uint32_t) * NSS_PPE_STATS_CPU_CODE_EXCEPTION_MAX, GFP_KERNEL);
+	if (unlikely(ppe_stats == NULL)) {
+		kfree(lbuf);
+		nss_warning("Could not allocate memory for ppe stats buffer");
+		return 0;
+	}
+
+	/*
+	 * Get CPU code counters for flow specific exceptions
+	 */
+	nss_ppe_cpu_code_exception_get(ppe_stats);
+
+	size_wr = scnprintf(lbuf, size_al, "ppe non-zero cpu code flow-exception stats start:\n\n");
+
+	/*
+	 * CPU code stats
+	 */
+	for (i = 0; i < NSS_PPE_STATS_CPU_CODE_EXCEPTION_MAX; i++) {
+		/*
+		 * Print only non-zero stats.
+		 */
+		if (!ppe_stats[i]) {
+			continue;
+		}
+
+		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
+				"\t%s = %u\n", nss_ppe_stats_str_cc[i],
+				ppe_stats[i]);
+	}
+
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nppe non-zero cpu code flow-exception stats end\n\n");
+	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
+	kfree(ppe_stats);
+	kfree(lbuf);
+
+	return bytes_read;
+}
+
+/*
+ * nss_ppe_nonexception_cc_stats_read()
+ *      Read PPE CPU code stats for other than flow exceptions
+ */
+static ssize_t nss_ppe_nonexception_cc_stats_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
+{
+	int32_t i;
+
+	/*
+	 * max output lines = #stats + start tag line + end tag line + three blank lines
+	 */
+	uint32_t max_output_lines = (NSS_PPE_STATS_CPU_CODE_NONEXCEPTION_MAX + 2) + 3;
+	size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
+	size_t size_wr = 0;
+	ssize_t bytes_read = 0;
+	uint32_t *ppe_stats;
+
+	char *lbuf = kzalloc(size_al, GFP_KERNEL);
+	if (unlikely(lbuf == NULL)) {
+		nss_warning("Could not allocate memory for local statistics buffer");
+		return 0;
+	}
+
+	ppe_stats = kzalloc(sizeof(uint32_t) * NSS_PPE_STATS_CPU_CODE_NONEXCEPTION_MAX, GFP_KERNEL);
+	if (unlikely(ppe_stats == NULL)) {
+		kfree(lbuf);
+		nss_warning("Could not allocate memory for ppe stats buffer");
+		return 0;
+	}
+
+	/*
+	 * Get CPU code counters for non flow exceptions
+	 */
+	nss_ppe_cpu_code_nonexception_get(ppe_stats);
+
+	/*
+	 * CPU code stats
+	 */
+	size_wr = scnprintf(lbuf, size_al, "ppe non-zero cpu code non-flow exception stats start:\n\n");
+	for (i = 0; i < NSS_PPE_STATS_CPU_CODE_NONEXCEPTION_MAX; i++) {
+		/*
+		 * Print only non-zero stats.
+		 */
+		if (!ppe_stats[i]) {
+			continue;
+		}
+
+		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
+				"\t%s = %u\n", nss_ppe_stats_str_cc[i + NSS_PPE_STATS_CPU_CODE_NONEXCEPTION_START],
+				ppe_stats[i]);
+	}
+
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nppe non-zero cpu code non-flow exception stats end\n\n");
+	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
+	kfree(ppe_stats);
+	kfree(lbuf);
+
+	return bytes_read;
+}
+
+/*
+ * nss_ppe_conn_stats_ops
+ */
+NSS_STATS_DECLARE_FILE_OPERATIONS(ppe_conn)
+
+/*
+ * nss_ppe_l3_stats_ops
+ */
+NSS_STATS_DECLARE_FILE_OPERATIONS(ppe_l3)
+
+/*
+ * nss_ppe_code_stats_ops
+ */
+NSS_STATS_DECLARE_FILE_OPERATIONS(ppe_code)
+
+/*
+ * nss_ppe_port_dc_stats_ops
+ */
+NSS_STATS_DECLARE_FILE_OPERATIONS(ppe_port_dc)
+/*
+ *  nss_ppe_exception_cc_stats_ops
+ */
+NSS_STATS_DECLARE_FILE_OPERATIONS(ppe_exception_cc)
+
+/*
+ *  nss_ppe_nonexception_cc_stats_ops
+ */
+NSS_STATS_DECLARE_FILE_OPERATIONS(ppe_nonexception_cc)
+
+/*
+ * nss_ppe_stats_dentry_create()
+ *	Create PPE statistics debug entry.
+ */
+void nss_ppe_stats_dentry_create(void)
+{
+	int i;
+	struct dentry *ppe_dentry = NULL;
+	struct dentry *ppe_conn_d = NULL;
+	struct dentry *ppe_l3_d = NULL;
+	struct dentry *ppe_ppe_code_d = NULL;
+	struct dentry *ppe_code_d = NULL;
+	struct dentry *ppe_drop_d = NULL;
+	struct dentry *ppe_port_dc_d = NULL;
+	struct dentry *ppe_cpu_d = NULL;
+	struct dentry *ppe_exception_d = NULL;
+	struct dentry *ppe_nonexception_d = NULL;
+	char file_name[10];
+
+	ppe_dentry = debugfs_create_dir("ppe", nss_top_main.stats_dentry);
+	if (unlikely(ppe_dentry == NULL)) {
+		nss_warning("Failed to create qca-nss-drv/stats/ppe directory");
+		return;
+	}
+
+	ppe_conn_d = debugfs_create_file("connection", 0400, ppe_dentry,
+					&nss_top_main, &nss_ppe_conn_stats_ops);
+	if (unlikely(ppe_conn_d == NULL)) {
+		nss_warning("Failed to create qca-nss-drv/stats/ppe/connection file");
+		return;
+	}
+
+	ppe_l3_d = debugfs_create_file("l3", 0400, ppe_dentry,
+					&nss_top_main, &nss_ppe_l3_stats_ops);
+	if (unlikely(ppe_l3_d == NULL)) {
+		nss_warning("Failed to create qca-nss-drv/stats/ppe/l3 filed");
+		return;
+	}
+
+	ppe_ppe_code_d = debugfs_create_file("ppe_code", 0400, ppe_dentry,
+						&nss_top_main, &nss_ppe_code_stats_ops);
+	if (unlikely(ppe_ppe_code_d == NULL)) {
+		nss_warning("Failed to create qca-nss-drv/stats/ppe/ppe_code file");
+		return;
+	}
+
+	/*
+	 * ppe exception and drop code stats
+	 */
+	ppe_code_d = debugfs_create_dir("code", ppe_dentry);
+	if (unlikely(ppe_code_d == NULL)) {
+		nss_warning("Failed to create qca-nss-drv/stats/ppe/code directory");
+		return;
+	}
+
+	ppe_cpu_d = debugfs_create_dir("cpu", ppe_code_d);
+	if (unlikely(ppe_cpu_d == NULL)) {
+		nss_warning("Failed to create qca-nss-drv/stats/ppe/code/cpu directory");
+		return;
+	}
+
+	ppe_exception_d = debugfs_create_file("exception", 0400, ppe_cpu_d,
+					&nss_top_main, &nss_ppe_exception_cc_stats_ops);
+	if (unlikely(ppe_exception_d == NULL)) {
+		nss_warning("Failed to create qca-nss-drv/stats/ppe/code/exception file");
+		return;
+	}
+
+	ppe_nonexception_d = debugfs_create_file("non-exception", 0400, ppe_cpu_d,
+					&nss_top_main, &nss_ppe_nonexception_cc_stats_ops);
+	if (unlikely(ppe_nonexception_d == NULL)) {
+		nss_warning("Failed to create qca-nss-drv/stats/ppe/code/non-exception file");
+		return;
+	}
+
+	ppe_drop_d = debugfs_create_dir("drop", ppe_code_d);
+	if (unlikely(ppe_drop_d == NULL)) {
+		nss_warning("Failed to create qca-nss-drv/stats/ppe/code/drop directory");
+		return;
+	}
+
+	for (i = 0; i < NSS_PPE_NUM_PHY_PORTS_MAX; i++) {
+		if (i > 0) {
+			memset(file_name, 0, sizeof(file_name));
+			snprintf(file_name, sizeof(file_name), "%d", i);
+		}
+
+		ppe_port_dc_d = debugfs_create_file((i == 0) ? "cpu" : file_name, 0400, ppe_drop_d,
+					(void *)(nss_ptr_t)i, &nss_ppe_port_dc_stats_ops);
+		if (unlikely(ppe_port_dc_d == NULL)) {
+			nss_warning("Failed to create qca-nss-drv/stats/ppe/code/drop/%d file", i);
+			return;
+		}
+	}
+}
diff --git a/nss_ppe_stats.h b/nss_ppe_stats.h
new file mode 100644
index 0000000..9fb2c26
--- /dev/null
+++ b/nss_ppe_stats.h
@@ -0,0 +1,411 @@
+/*
+ **************************************************************************
+ * 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.
+ **************************************************************************
+ */
+
+/*
+ * nss_ppe_stats.h
+ *	NSS PPE statistics header file.
+ */
+
+#ifndef __NSS_PPE_STATS_H
+#define __NSS_PPE_STATS_H
+
+/*
+ * NSS PPE connection statistics
+ */
+enum nss_ppe_stats_conn {
+	NSS_PPE_STATS_V4_L3_FLOWS,		/* No of v4 routed flows */
+	NSS_PPE_STATS_V4_L2_FLOWS,		/* No of v4 bridge flows */
+	NSS_PPE_STATS_V4_CREATE_REQ,		/* No of v4 create requests */
+	NSS_PPE_STATS_V4_CREATE_FAIL,		/* No of v4 create failure */
+	NSS_PPE_STATS_V4_DESTROY_REQ,		/* No of v4 delete requests */
+	NSS_PPE_STATS_V4_DESTROY_FAIL,		/* No of v4 delete failure */
+	NSS_PPE_STATS_V4_MC_CREATE_REQ,		/* No of v4 MC create requests */
+	NSS_PPE_STATS_V4_MC_CREATE_FAIL,	/* No of v4 MC create failure */
+	NSS_PPE_STATS_V4_MC_UPDATE_REQ,		/* No of v4 MC update requests */
+	NSS_PPE_STATS_V4_MC_UPDATE_FAIL,	/* No of v4 MC update failure */
+	NSS_PPE_STATS_V4_MC_DESTROY_REQ,	/* No of v4 MC delete requests */
+	NSS_PPE_STATS_V4_MC_DESTROY_FAIL,	/* No of v4 MC delete failure */
+
+	NSS_PPE_STATS_V6_L3_FLOWS,		/* No of v6 routed flows */
+	NSS_PPE_STATS_V6_L2_FLOWS,		/* No of v6 bridge flows */
+	NSS_PPE_STATS_V6_CREATE_REQ,		/* No of v6 create requests */
+	NSS_PPE_STATS_V6_CREATE_FAIL,		/* No of v6 create failure */
+	NSS_PPE_STATS_V6_DESTROY_REQ,		/* No of v6 delete requests */
+	NSS_PPE_STATS_V6_DESTROY_FAIL,		/* No of v6 delete failure */
+	NSS_PPE_STATS_V6_MC_CREATE_REQ,		/* No of v6 MC create requests */
+	NSS_PPE_STATS_V6_MC_CREATE_FAIL,	/* No of v6 MC create failure */
+	NSS_PPE_STATS_V6_MC_UPDATE_REQ,		/* No of v6 MC update requests */
+	NSS_PPE_STATS_V6_MC_UPDATE_FAIL,	/* No of v6 MC update failure */
+	NSS_PPE_STATS_V6_MC_DESTROY_REQ,	/* No of v6 MC delete requests */
+	NSS_PPE_STATS_V6_MC_DESTROY_FAIL,	/* No of v6 MC delete failure */
+
+	NSS_PPE_STATS_FAIL_VP_FULL,		/* Create req fail due to VP table full */
+	NSS_PPE_STATS_FAIL_NH_FULL,		/* Create req fail due to nexthop table full */
+	NSS_PPE_STATS_FAIL_FLOW_FULL,		/* Create req fail due to flow table full */
+	NSS_PPE_STATS_FAIL_HOST_FULL,		/* Create req fail due to host table full */
+	NSS_PPE_STATS_FAIL_PUBIP_FULL,		/* Create req fail due to pub-ip table full */
+	NSS_PPE_STATS_FAIL_PORT_SETUP,		/* Create req fail due to PPE port not setup */
+	NSS_PPE_STATS_FAIL_RW_FIFO_FULL,	/* Create req fail due to rw fifo full */
+	NSS_PPE_STATS_FAIL_FLOW_COMMAND,	/* Create req fail due to PPE flow command failure */
+	NSS_PPE_STATS_FAIL_UNKNOWN_PROTO,	/* Create req fail due to unknown protocol */
+	NSS_PPE_STATS_FAIL_PPE_UNRESPONSIVE,	/* Create req fail due to PPE not responding */
+	NSS_PPE_STATS_CE_OPAQUE_INVALID,	/* Create req fail due to invalid opaque in CE */
+	NSS_PPE_STATS_FAIL_FQG_FULL,		/* Create req fail due to flow qos group full */
+	NSS_PPE_STATS_CONN_MAX
+};
+
+/*
+ * NSS PPE L3 statistics
+ */
+enum nss_ppe_stats_l3 {
+	NSS_PPE_STATS_L3_DBG_0,		/* PPE L3 debug register 0 */
+	NSS_PPE_STATS_L3_DBG_1,		/* PPE L3 debug register 1 */
+	NSS_PPE_STATS_L3_DBG_2,		/* PPE L3 debug register 2 */
+	NSS_PPE_STATS_L3_DBG_3,		/* PPE L3 debug register 3 */
+	NSS_PPE_STATS_L3_DBG_4,		/* PPE L3 debug register 4 */
+	NSS_PPE_STATS_L3_DBG_PORT,	/* PPE L3 debug register Port */
+	NSS_PPE_STATS_L3_MAX
+};
+
+/*
+ * NSS PPE_code statistics
+ */
+enum nss_ppe_stats_code {
+	NSS_PPE_STATS_CODE_CPU,		/* PPE CPU code for last packet processed */
+	NSS_PPE_STATS_CODE_DROP,	/* PPE DROP code for last packet processed */
+	NSS_PPE_STATS_CODE_MAX
+};
+
+/*
+ * PPE drop codes
+ */
+enum nss_ppe_stats_dc {
+	NSS_PPE_STATS_DROP_CODE_UNKNOWN,                                /* PPE drop code unknown */
+	NSS_PPE_STATS_DROP_CODE_EXP_UNKNOWN_L2_PROT,                    /* PPE drop code exp unknown l2 prot */
+	NSS_PPE_STATS_DROP_CODE_EXP_PPPOE_WRONG_VER_TYPE,               /* PPE drop code exp pppoe wrong ver type */
+	NSS_PPE_STATS_DROP_CODE_EXP_PPPOE_WRONG_CODE,                   /* PPE drop code exp pppoe wrong code */
+	NSS_PPE_STATS_DROP_CODE_EXP_PPPOE_UNSUPPORTED_PPP_PROT,         /* PPE drop code exp pppoe unsupported ppp prot */
+	NSS_PPE_STATS_DROP_CODE_EXP_IPV4_WRONG_VER,                     /* PPE drop code exp ipv4 wrong ver */
+	NSS_PPE_STATS_DROP_CODE_EXP_IPV4_SMALL_IHL,                     /* PPE drop code exp ipv4 small ihl */
+	NSS_PPE_STATS_DROP_CODE_EXP_IPV4_WITH_OPTION,                   /* PPE drop code exp ipv4 with option */
+	NSS_PPE_STATS_DROP_CODE_EXP_IPV4_HDR_INCOMPLETE,                /* PPE drop code exp ipv4 hdr incomplete */
+	NSS_PPE_STATS_DROP_CODE_EXP_IPV4_BAD_TOTAL_LEN,                 /* PPE drop code exp ipv4 bad total len */
+	NSS_PPE_STATS_DROP_CODE_EXP_IPV4_DATA_INCOMPLETE,               /* PPE drop code exp ipv4 data incomplete */
+	NSS_PPE_STATS_DROP_CODE_EXP_IPV4_FRAG,                          /* PPE drop code exp ipv4 frag */
+	NSS_PPE_STATS_DROP_CODE_EXP_IPV4_PING_OF_DEATH,                 /* PPE drop code exp ipv4 ping of death */
+	NSS_PPE_STATS_DROP_CODE_EXP_IPV4_SNALL_TTL,                     /* PPE drop code exp ipv4 snall ttl */
+	NSS_PPE_STATS_DROP_CODE_EXP_IPV4_UNK_IP_PROT,                   /* PPE drop code exp ipv4 unk ip prot */
+	NSS_PPE_STATS_DROP_CODE_EXP_IPV4_CHECKSUM_ERR,                  /* PPE drop code exp ipv4 checksum err */
+	NSS_PPE_STATS_DROP_CODE_EXP_IPV4_INV_SIP,                       /* PPE drop code exp ipv4 inv sip */
+	NSS_PPE_STATS_DROP_CODE_EXP_IPV4_INV_DIP,                       /* PPE drop code exp ipv4 inv dip */
+	NSS_PPE_STATS_DROP_CODE_EXP_IPV4_LAND_ATTACK,                   /* PPE drop code exp ipv4 land attack */
+	NSS_PPE_STATS_DROP_CODE_EXP_IPV4_AH_HDR_INCOMPLETE,             /* PPE drop code exp ipv4 ah hdr incomplete */
+	NSS_PPE_STATS_DROP_CODE_EXP_IPV4_AH_HDR_CROSS_BORDER,           /* PPE drop code exp ipv4 ah hdr cross border */
+	NSS_PPE_STATS_DROP_CODE_EXP_IPV4_ESP_HDR_INCOMPLETE,            /* PPE drop code exp ipv4 esp hdr incomplete */
+	NSS_PPE_STATS_DROP_CODE_EXP_IPV6_WRONG_VER,                     /* PPE drop code exp ipv6 wrong ver */
+	NSS_PPE_STATS_DROP_CODE_EXP_IPV6_HDR_INCOMPLETE,                /* PPE drop code exp ipv6 hdr incomplete */
+	NSS_PPE_STATS_DROP_CODE_EXP_IPV6_BAD_PAYLOAD_LEN,               /* PPE drop code exp ipv6 bad payload len */
+	NSS_PPE_STATS_DROP_CODE_EXP_IPV6_DATA_INCOMPLETE,               /* PPE drop code exp ipv6 data incomplete */
+	NSS_PPE_STATS_DROP_CODE_EXP_IPV6_WITH_EXT_HDR,                  /* PPE drop code exp ipv6 with ext hdr */
+	NSS_PPE_STATS_DROP_CODE_EXP_IPV6_SMALL_HOP_LIMIT,               /* PPE drop code exp ipv6 small hop limit */
+	NSS_PPE_STATS_DROP_CODE_EXP_IPV6_INV_SIP,                       /* PPE drop code exp ipv6 inv sip */
+	NSS_PPE_STATS_DROP_CODE_EXP_IPV6_INV_DIP,                       /* PPE drop code exp ipv6 inv dip */
+	NSS_PPE_STATS_DROP_CODE_EXP_IPV6_LAND_ATTACK,                   /* PPE drop code exp ipv6 land attack */
+	NSS_PPE_STATS_DROP_CODE_EXP_IPV6_FRAG,                          /* PPE drop code exp ipv6 frag */
+	NSS_PPE_STATS_DROP_CODE_EXP_IPV6_PING_OF_DEATH,                 /* PPE drop code exp ipv6 ping of death */
+	NSS_PPE_STATS_DROP_CODE_EXP_IPV6_WITH_MORE_EXT_HDR,             /* PPE drop code exp ipv6 with more ext hdr */
+	NSS_PPE_STATS_DROP_CODE_EXP_IPV6_UNK_LAST_NEXT_HDR,             /* PPE drop code exp ipv6 unk last next hdr */
+	NSS_PPE_STATS_DROP_CODE_EXP_IPV6_MOBILITY_HDR_INCOMPLETE,       /* PPE drop code exp ipv6 mobility hdr incomplete */
+	NSS_PPE_STATS_DROP_CODE_EXP_IPV6_MOBILITY_HDR_CROSS_BORDER,     /* PPE drop code exp ipv6 mobility hdr cross border */
+	NSS_PPE_STATS_DROP_CODE_EXP_IPV6_AH_HDR_INCOMPLETE,             /* PPE drop code exp ipv6 ah hdr incomplete */
+	NSS_PPE_STATS_DROP_CODE_EXP_IPV6_AH_HDR_CROSS_BORDER,           /* PPE drop code exp ipv6 ah hdr cross border */
+	NSS_PPE_STATS_DROP_CODE_EXP_IPV6_ESP_HDR_INCOMPLETE,            /* PPE drop code exp ipv6 esp hdr incomplete */
+	NSS_PPE_STATS_DROP_CODE_EXP_IPV6_ESP_HDR_CROSS_BORDER,          /* PPE drop code exp ipv6 esp hdr cross border */
+	NSS_PPE_STATS_DROP_CODE_EXP_IPV6_OTHER_EXT_HDR_INCOMPLETE,      /* PPE drop code exp ipv6 other ext hdr incomplete */
+	NSS_PPE_STATS_DROP_CODE_EXP_IPV6_OTHER_EXT_HDR_CROSS_BORDER,    /* PPE drop code exp ipv6 other ext hdr cross border */
+	NSS_PPE_STATS_DROP_CODE_EXP_TCP_HDR_INCOMPLETE,                 /* PPE drop code exp tcp hdr incomplete */
+	NSS_PPE_STATS_DROP_CODE_EXP_TCP_HDR_CROSS_BORDER,               /* PPE drop code exp tcp hdr cross border */
+	NSS_PPE_STATS_DROP_CODE_EXP_TCP_SMAE_SP_DP,                     /* PPE drop code exp tcp smae sp dp */
+	NSS_PPE_STATS_DROP_CODE_EXP_TCP_SMALL_DATA_OFFSET,              /* PPE drop code exp tcp small data offset */
+	NSS_PPE_STATS_DROP_CODE_EXP_TCP_FLAGS_0,                        /* PPE drop code exp tcp flags 0 */
+	NSS_PPE_STATS_DROP_CODE_EXP_TCP_FLAGS_1,                        /* PPE drop code exp tcp flags 1 */
+	NSS_PPE_STATS_DROP_CODE_EXP_TCP_FLAGS_2,                        /* PPE drop code exp tcp flags 2 */
+	NSS_PPE_STATS_DROP_CODE_EXP_TCP_FLAGS_3,                        /* PPE drop code exp tcp flags 3 */
+	NSS_PPE_STATS_DROP_CODE_EXP_TCP_FLAGS_4,                        /* PPE drop code exp tcp flags 4 */
+	NSS_PPE_STATS_DROP_CODE_EXP_TCP_FLAGS_5,                        /* PPE drop code exp tcp flags 5 */
+	NSS_PPE_STATS_DROP_CODE_EXP_TCP_FLAGS_6,                        /* PPE drop code exp tcp flags 6 */
+	NSS_PPE_STATS_DROP_CODE_EXP_TCP_FLAGS_7,                        /* PPE drop code exp tcp flags 7 */
+	NSS_PPE_STATS_DROP_CODE_EXP_TCP_CHECKSUM_ERR,                   /* PPE drop code exp tcp checksum err */
+	NSS_PPE_STATS_DROP_CODE_EXP_UDP_HDR_INCOMPLETE,                 /* PPE drop code exp udp hdr incomplete */
+	NSS_PPE_STATS_DROP_CODE_EXP_UDP_HDR_CROSS_BORDER,               /* PPE drop code exp udp hdr cross border */
+	NSS_PPE_STATS_DROP_CODE_EXP_UDP_SMAE_SP_DP,                     /* PPE drop code exp udp smae sp dp */
+	NSS_PPE_STATS_DROP_CODE_EXP_UDP_BAD_LEN,                        /* PPE drop code exp udp bad len */
+	NSS_PPE_STATS_DROP_CODE_EXP_UDP_DATA_INCOMPLETE,                /* PPE drop code exp udp data incomplete */
+	NSS_PPE_STATS_DROP_CODE_EXP_UDP_CHECKSUM_ERR,                   /* PPE drop code exp udp checksum err */
+	NSS_PPE_STATS_DROP_CODE_EXP_UDP_LITE_HDR_INCOMPLETE,            /* PPE drop code exp udp lite hdr incomplete */
+	NSS_PPE_STATS_DROP_CODE_EXP_UDP_LITE_HDR_CROSS_BORDER,          /* PPE drop code exp udp lite hdr cross border */
+	NSS_PPE_STATS_DROP_CODE_EXP_UDP_LITE_SMAE_SP_DP,                /* PPE drop code exp udp lite smae sp dp */
+	NSS_PPE_STATS_DROP_CODE_EXP_UDP_LITE_CSM_COV_1_TO_7,            /* PPE drop code exp udp lite csm cov 1 to 7 */
+	NSS_PPE_STATS_DROP_CODE_EXP_UDP_LITE_CSM_COV_TOO_LONG,          /* PPE drop code exp udp lite csm cov too long */
+	NSS_PPE_STATS_DROP_CODE_EXP_UDP_LITE_CSM_COV_CROSS_BORDER,      /* PPE drop code exp udp lite csm cov cross border */
+	NSS_PPE_STATS_DROP_CODE_EXP_UDP_LITE_CHECKSUM_ERR,              /* PPE drop code exp udp lite checksum err */
+	NSS_PPE_STATS_DROP_CODE_L3_MC_BRIDGE_ACTION,                    /* PPE drop code l3 mc bridge action */
+	NSS_PPE_STATS_DROP_CODE_L3_NO_ROUTE_PREHEAD_NAT_ACTION,         /* PPE drop code l3 no route prehead nat action */
+	NSS_PPE_STATS_DROP_CODE_L3_NO_ROUTE_PREHEAD_NAT_ERROR,          /* PPE drop code l3 no route prehead nat error */
+	NSS_PPE_STATS_DROP_CODE_L3_ROUTE_ACTION,                        /* PPE drop code l3 route action */
+	NSS_PPE_STATS_DROP_CODE_L3_NO_ROUTE_ACTION,                     /* PPE drop code l3 no route action */
+	NSS_PPE_STATS_DROP_CODE_L3_NO_ROUTE_NH_INVALID_ACTION,          /* PPE drop code l3 no route nh invalid action */
+	NSS_PPE_STATS_DROP_CODE_L3_NO_ROUTE_PREHEAD_ACTION,             /* PPE drop code l3 no route prehead action */
+	NSS_PPE_STATS_DROP_CODE_L3_BRIDGE_ACTION,                       /* PPE drop code l3 bridge action */
+	NSS_PPE_STATS_DROP_CODE_L3_FLOW_ACTION,                         /* PPE drop code l3 flow action */
+	NSS_PPE_STATS_DROP_CODE_L3_FLOW_MISS_ACTION,                    /* PPE drop code l3 flow miss action */
+	NSS_PPE_STATS_DROP_CODE_L2_EXP_MRU_FAIL,                        /* PPE drop code l2 exp mru fail */
+	NSS_PPE_STATS_DROP_CODE_L2_EXP_MTU_FAIL,                        /* PPE drop code l2 exp mtu fail */
+	NSS_PPE_STATS_DROP_CODE_L3_EXP_IP_PREFIX_BC,                    /* PPE drop code l3 exp ip prefix bc */
+	NSS_PPE_STATS_DROP_CODE_L3_EXP_MTU_FAIL,                        /* PPE drop code l3 exp mtu fail */
+	NSS_PPE_STATS_DROP_CODE_L3_EXP_MRU_FAIL,                        /* PPE drop code l3 exp mru fail */
+	NSS_PPE_STATS_DROP_CODE_L3_EXP_ICMP_RDT,                        /* PPE drop code l3 exp icmp rdt */
+	NSS_PPE_STATS_DROP_CODE_FAKE_MAC_HEADER_ERR,                    /* PPE drop code fake mac header err */
+	NSS_PPE_STATS_DROP_CODE_L3_EXP_IP_RT_TTL_ZERO,                  /* PPE drop code l3 exp ip rt ttl zero */
+	NSS_PPE_STATS_DROP_CODE_L3_FLOW_SERVICE_CODE_LOOP,              /* PPE drop code l3 flow service code loop */
+	NSS_PPE_STATS_DROP_CODE_L3_FLOW_DE_ACCELEARTE,                  /* PPE drop code l3 flow de accelearte */
+	NSS_PPE_STATS_DROP_CODE_L3_EXP_FLOW_SRC_IF_CHK_FAIL,            /* PPE drop code l3 exp flow src if chk fail */
+	NSS_PPE_STATS_DROP_CODE_L3_FLOW_SYNC_TOGGLE_MISMATCH,           /* PPE drop code l3 flow sync toggle mismatch */
+	NSS_PPE_STATS_DROP_CODE_L3_EXP_MTU_DF_FAIL,                     /* PPE drop code l3 exp mtu df fail */
+	NSS_PPE_STATS_DROP_CODE_L3_EXP_PPPOE_MULTICAST,                 /* PPE drop code l3 exp pppoe multicast */
+	NSS_PPE_STATS_DROP_CODE_IPV4_SG_UNKNOWN,                        /* PPE drop code ipv4 sg unknown */
+	NSS_PPE_STATS_DROP_CODE_IPV6_SG_UNKNOWN,                        /* PPE drop code ipv6 sg unknown */
+	NSS_PPE_STATS_DROP_CODE_ARP_SG_UNKNOWN,                         /* PPE drop code arp sg unknown */
+	NSS_PPE_STATS_DROP_CODE_ND_SG_UNKNOWN,                          /* PPE drop code nd sg unknown */
+	NSS_PPE_STATS_DROP_CODE_IPV4_SG_VIO,                            /* PPE drop code ipv4 sg vio */
+	NSS_PPE_STATS_DROP_CODE_IPV6_SG_VIO,                            /* PPE drop code ipv6 sg vio */
+	NSS_PPE_STATS_DROP_CODE_ARP_SG_VIO,                             /* PPE drop code arp sg vio */
+	NSS_PPE_STATS_DROP_CODE_ND_SG_VIO,                              /* PPE drop code nd sg vio */
+	NSS_PPE_STATS_DROP_CODE_L2_NEW_MAC_ADDRESS,                     /* PPE drop code l2 new mac address */
+	NSS_PPE_STATS_DROP_CODE_L2_HASH_COLLISION,                      /* PPE drop code l2 hash collision */
+	NSS_PPE_STATS_DROP_CODE_L2_STATION_MOVE,                        /* PPE drop code l2 station move */
+	NSS_PPE_STATS_DROP_CODE_L2_LEARN_LIMIT,                         /* PPE drop code l2 learn limit */
+	NSS_PPE_STATS_DROP_CODE_L2_SA_LOOKUP_ACTION,                    /* PPE drop code l2 sa lookup action */
+	NSS_PPE_STATS_DROP_CODE_L2_DA_LOOKUP_ACTION,                    /* PPE drop code l2 da lookup action */
+	NSS_PPE_STATS_DROP_CODE_APP_CTRL_ACTION,                        /* PPE drop code app ctrl action */
+	NSS_PPE_STATS_DROP_CODE_IN_VLAN_FILTER_ACTION,                  /* PPE drop code in vlan filter action */
+	NSS_PPE_STATS_DROP_CODE_IN_VLAN_XLT_MISS,                       /* PPE drop code in vlan xlt miss */
+	NSS_PPE_STATS_DROP_CODE_EG_VLAN_FILTER_DROP,                    /* PPE drop code eg vlan filter drop */
+	NSS_PPE_STATS_DROP_CODE_ACL_PRE_ACTION,                         /* PPE drop code acl pre action */
+	NSS_PPE_STATS_DROP_CODE_ACL_POST_ACTION,                        /* PPE drop code acl post action */
+	NSS_PPE_STATS_DROP_CODE_MC_BC_SA,                               /* PPE drop code mc bc sa */
+	NSS_PPE_STATS_DROP_CODE_NO_DESTINATION,                         /* PPE drop code no destination */
+	NSS_PPE_STATS_DROP_CODE_STG_IN_FILTER,                          /* PPE drop code stg in filter */
+	NSS_PPE_STATS_DROP_CODE_STG_EG_FILTER,                          /* PPE drop code stg eg filter */
+	NSS_PPE_STATS_DROP_CODE_SOURCE_FILTER_FAIL,                     /* PPE drop code source filter fail */
+	NSS_PPE_STATS_DROP_CODE_TRUNK_SEL_FAIL,                         /* PPE drop code trunk sel fail */
+	NSS_PPE_STATS_DROP_CODE_TX_EN_FAIL,                             /* PPE drop code tx en fail */
+	NSS_PPE_STATS_DROP_CODE_VLAN_TAG_FMT,                           /* PPE drop code vlan tag fmt */
+	NSS_PPE_STATS_DROP_CODE_CRC_ERR,                                /* PPE drop code crc err */
+	NSS_PPE_STATS_DROP_CODE_PAUSE_FRAME,                            /* PPE drop code pause frame */
+	NSS_PPE_STATS_DROP_CODE_PROMISC,                                /* PPE drop code promisc */
+	NSS_PPE_STATS_DROP_CODE_ISOLATION,                              /* PPE drop code isolation */
+	NSS_PPE_STATS_DROP_CODE_MGMT_APP,                               /* PPE drop code mgmt app */
+	NSS_PPE_STATS_DROP_CODE_FAKE_L2_PROT_ERR,                       /* PPE drop code fake l2 prot err */
+	NSS_PPE_STATS_DROP_CODE_POLICER,                                /* PPE drop code policer */
+	NSS_PPE_STATS_DROP_CODE_MAX                                     /* PPE drop code max */
+};
+
+/*
+ * PPE CPU codes
+ */
+#define NSS_PPE_STATS_CPU_CODE_MAX 150
+#define NSS_PPE_STATS_CPU_CODE_EXCEPTION_MAX 69
+#define NSS_PPE_STATS_CPU_CODE_NONEXCEPTION_START 69
+#define NSS_PPE_STATS_CPU_CODE_NONEXCEPTION_MAX (NSS_PPE_STATS_CPU_CODE_MAX - NSS_PPE_STATS_CPU_CODE_NONEXCEPTION_START)
+
+enum nss_ppe_stats_cc {
+	NSS_PPE_STATS_CPU_CODE_FORWARDING                         = 0, /* PPE cpu code forwarding */
+	NSS_PPE_STATS_CPU_CODE_EXP_UNKNOWN_L2_PROT                = 1, /* PPE cpu code exp unknown l2 prot */
+	NSS_PPE_STATS_CPU_CODE_EXP_PPPOE_WRONG_VER_TYPE           = 2, /* PPE cpu code exp pppoe wrong ver type */
+	NSS_PPE_STATS_CPU_CODE_EXP_PPPOE_WRONG_CODE               = 3, /* PPE cpu code exp pppoe wrong code */
+	NSS_PPE_STATS_CPU_CODE_EXP_PPPOE_UNSUPPORTED_PPP_PROT     = 4, /* PPE cpu code exp pppoe unsupported ppp prot */
+	NSS_PPE_STATS_CPU_CODE_EXP_IPV4_WRONG_VER                 = 5, /* PPE cpu code exp ipv4 wrong ver */
+	NSS_PPE_STATS_CPU_CODE_EXP_IPV4_SMALL_IHL                 = 6, /* PPE cpu code exp ipv4 small ihl */
+	NSS_PPE_STATS_CPU_CODE_EXP_IPV4_WITH_OPTION               = 7, /* PPE cpu code exp ipv4 with option */
+	NSS_PPE_STATS_CPU_CODE_EXP_IPV4_HDR_INCOMPLETE            = 8, /* PPE cpu code exp ipv4 hdr incomplete */
+	NSS_PPE_STATS_CPU_CODE_EXP_IPV4_BAD_TOTAL_LEN             = 9, /* PPE cpu code exp ipv4 bad total len */
+	NSS_PPE_STATS_CPU_CODE_EXP_IPV4_DATA_INCOMPLETE           = 10, /* PPE cpu code exp ipv4 data incomplete */
+	NSS_PPE_STATS_CPU_CODE_EXP_IPV4_FRAG                      = 11, /* PPE cpu code exp ipv4 frag */
+	NSS_PPE_STATS_CPU_CODE_EXP_IPV4_PING_OF_DEATH             = 12, /* PPE cpu code exp ipv4 ping of death */
+	NSS_PPE_STATS_CPU_CODE_EXP_IPV4_SNALL_TTL                 = 13, /* PPE cpu code exp ipv4 snall ttl */
+	NSS_PPE_STATS_CPU_CODE_EXP_IPV4_UNK_IP_PROT               = 14, /* PPE cpu code exp ipv4 unk ip prot */
+	NSS_PPE_STATS_CPU_CODE_EXP_IPV4_CHECKSUM_ERR              = 15, /* PPE cpu code exp ipv4 checksum err */
+	NSS_PPE_STATS_CPU_CODE_EXP_IPV4_INV_SIP                   = 16, /* PPE cpu code exp ipv4 inv sip */
+	NSS_PPE_STATS_CPU_CODE_EXP_IPV4_INV_DIP                   = 17, /* PPE cpu code exp ipv4 inv dip */
+	NSS_PPE_STATS_CPU_CODE_EXP_IPV4_LAND_ATTACK               = 18, /* PPE cpu code exp ipv4 land attack */
+	NSS_PPE_STATS_CPU_CODE_EXP_IPV4_AH_HDR_INCOMPLETE         = 19, /* PPE cpu code exp ipv4 ah hdr incomplete */
+	NSS_PPE_STATS_CPU_CODE_EXP_IPV4_AH_HDR_CROSS_BORDER       = 20, /* PPE cpu code exp ipv4 ah hdr cross border */
+	NSS_PPE_STATS_CPU_CODE_EXP_IPV4_ESP_HDR_INCOMPLETE        = 21, /* PPE cpu code exp ipv4 esp hdr incomplete */
+	NSS_PPE_STATS_CPU_CODE_EXP_IPV6_WRONG_VER                 = 22, /* PPE cpu code exp ipv6 wrong ver */
+	NSS_PPE_STATS_CPU_CODE_EXP_IPV6_HDR_INCOMPLETE            = 23, /* PPE cpu code exp ipv6 hdr incomplete */
+	NSS_PPE_STATS_CPU_CODE_EXP_IPV6_BAD_PAYLOAD_LEN           = 24, /* PPE cpu code exp ipv6 bad payload len */
+	NSS_PPE_STATS_CPU_CODE_EXP_IPV6_DATA_INCOMPLETE           = 25, /* PPE cpu code exp ipv6 data incomplete */
+	NSS_PPE_STATS_CPU_CODE_EXP_IPV6_WITH_EXT_HDR              = 26, /* PPE cpu code exp ipv6 with ext hdr */
+	NSS_PPE_STATS_CPU_CODE_EXP_IPV6_SMALL_HOP_LIMIT           = 27, /* PPE cpu code exp ipv6 small hop limit */
+	NSS_PPE_STATS_CPU_CODE_EXP_IPV6_INV_SIP                   = 28, /* PPE cpu code exp ipv6 inv sip */
+	NSS_PPE_STATS_CPU_CODE_EXP_IPV6_INV_DIP                   = 29, /* PPE cpu code exp ipv6 inv dip */
+	NSS_PPE_STATS_CPU_CODE_EXP_IPV6_LAND_ATTACK               = 30, /* PPE cpu code exp ipv6 land attack */
+	NSS_PPE_STATS_CPU_CODE_EXP_IPV6_FRAG                      = 31, /* PPE cpu code exp ipv6 frag */
+	NSS_PPE_STATS_CPU_CODE_EXP_IPV6_PING_OF_DEATH             = 32, /* PPE cpu code exp ipv6 ping of death */
+	NSS_PPE_STATS_CPU_CODE_EXP_IPV6_WITH_MORE_EXT_HDR         = 33, /* PPE cpu code exp ipv6 with more ext hdr */
+	NSS_PPE_STATS_CPU_CODE_EXP_IPV6_UNK_LAST_NEXT_HDR         = 34, /* PPE cpu code exp ipv6 unk last next hdr */
+	NSS_PPE_STATS_CPU_CODE_EXP_IPV6_MOBILITY_HDR_INCOMPLETE   = 35, /* PPE cpu code exp ipv6 mobility hdr incomplete */
+	NSS_PPE_STATS_CPU_CODE_EXP_IPV6_MOBILITY_HDR_CROSS_BORDER = 36, /* PPE cpu code exp ipv6 mobility hdr cross border */
+	NSS_PPE_STATS_CPU_CODE_EXP_IPV6_AH_HDR_INCOMPLETE         = 37, /* PPE cpu code exp ipv6 ah hdr incomplete */
+	NSS_PPE_STATS_CPU_CODE_EXP_IPV6_AH_HDR_CROSS_BORDER       = 38, /* PPE cpu code exp ipv6 ah hdr cross border */
+	NSS_PPE_STATS_CPU_CODE_EXP_IPV6_ESP_HDR_INCOMPLETE        = 39, /* PPE cpu code exp ipv6 esp hdr incomplete */
+	NSS_PPE_STATS_CPU_CODE_EXP_IPV6_ESP_HDR_CROSS_BORDER      = 40, /* PPE cpu code exp ipv6 esp hdr cross border */
+	NSS_PPE_STATS_CPU_CODE_EXP_IPV6_OTHER_EXT_HDR_INCOMPLETE  = 41, /* PPE cpu code exp ipv6 other ext hdr incomplete */
+	NSS_PPE_STATS_CPU_CODE_EXP_IPV6_OTHER_EXT_HDR_CROSS_BORDER = 42, /* PPE cpu code exp ipv6 other ext hdr cross border */
+	NSS_PPE_STATS_CPU_CODE_EXP_TCP_HDR_INCOMPLETE             = 43, /* PPE cpu code exp tcp hdr incomplete */
+	NSS_PPE_STATS_CPU_CODE_EXP_TCP_HDR_CROSS_BORDER           = 44, /* PPE cpu code exp tcp hdr cross border */
+	NSS_PPE_STATS_CPU_CODE_EXP_TCP_SMAE_SP_DP                 = 45, /* PPE cpu code exp tcp smae sp dp */
+	NSS_PPE_STATS_CPU_CODE_EXP_TCP_SMALL_DATA_OFFSET          = 46, /* PPE cpu code exp tcp small data offset */
+	NSS_PPE_STATS_CPU_CODE_EXP_TCP_FLAGS_0                    = 47, /* PPE cpu code exp tcp flags 0 */
+	NSS_PPE_STATS_CPU_CODE_EXP_TCP_FLAGS_1                    = 48, /* PPE cpu code exp tcp flags 1 */
+	NSS_PPE_STATS_CPU_CODE_EXP_TCP_FLAGS_2                    = 49, /* PPE cpu code exp tcp flags 2 */
+	NSS_PPE_STATS_CPU_CODE_EXP_TCP_FLAGS_3                    = 50, /* PPE cpu code exp tcp flags 3 */
+	NSS_PPE_STATS_CPU_CODE_EXP_TCP_FLAGS_4                    = 51, /* PPE cpu code exp tcp flags 4 */
+	NSS_PPE_STATS_CPU_CODE_EXP_TCP_FLAGS_5                    = 52, /* PPE cpu code exp tcp flags 5 */
+	NSS_PPE_STATS_CPU_CODE_EXP_TCP_FLAGS_6                    = 53, /* PPE cpu code exp tcp flags 6 */
+	NSS_PPE_STATS_CPU_CODE_EXP_TCP_FLAGS_7                    = 54, /* PPE cpu code exp tcp flags 7 */
+	NSS_PPE_STATS_CPU_CODE_EXP_TCP_CHECKSUM_ERR               = 55, /* PPE cpu code exp tcp checksum err */
+	NSS_PPE_STATS_CPU_CODE_EXP_UDP_HDR_INCOMPLETE             = 56, /* PPE cpu code exp udp hdr incomplete */
+	NSS_PPE_STATS_CPU_CODE_EXP_UDP_HDR_CROSS_BORDER           = 57, /* PPE cpu code exp udp hdr cross border */
+	NSS_PPE_STATS_CPU_CODE_EXP_UDP_SMAE_SP_DP                 = 58, /* PPE cpu code exp udp smae sp dp */
+	NSS_PPE_STATS_CPU_CODE_EXP_UDP_BAD_LEN                    = 59, /* PPE cpu code exp udp bad len */
+	NSS_PPE_STATS_CPU_CODE_EXP_UDP_DATA_INCOMPLETE            = 60, /* PPE cpu code exp udp data incomplete */
+	NSS_PPE_STATS_CPU_CODE_EXP_UDP_CHECKSUM_ERR               = 61, /* PPE cpu code exp udp checksum err */
+	NSS_PPE_STATS_CPU_CODE_EXP_UDP_LITE_HDR_INCOMPLETE        = 62, /* PPE cpu code exp udp lite hdr incomplete */
+	NSS_PPE_STATS_CPU_CODE_EXP_UDP_LITE_HDR_CROSS_BORDER      = 63, /* PPE cpu code exp udp lite hdr cross border */
+	NSS_PPE_STATS_CPU_CODE_EXP_UDP_LITE_SMAE_SP_DP            = 64, /* PPE cpu code exp udp lite smae sp dp */
+	NSS_PPE_STATS_CPU_CODE_EXP_UDP_LITE_CSM_COV_1_TO_7        = 65, /* PPE cpu code exp udp lite csm cov 1 to 7 */
+	NSS_PPE_STATS_CPU_CODE_EXP_UDP_LITE_CSM_COV_TOO_LONG      = 66, /* PPE cpu code exp udp lite csm cov too long */
+	NSS_PPE_STATS_CPU_CODE_EXP_UDP_LITE_CSM_COV_CROSS_BORDER  = 67, /* PPE cpu code exp udp lite csm cov cross border */
+	NSS_PPE_STATS_CPU_CODE_EXP_UDP_LITE_CHECKSUM_ERR          = 68, /* PPE cpu code exp udp lite checksum err */
+	NSS_PPE_STATS_CPU_CODE_EXP_FAKE_L2_PROT_ERR               = 69, /* PPE cpu code exp fake l2 prot err */
+	NSS_PPE_STATS_CPU_CODE_EXP_FAKE_MAC_HEADER_ERR            = 70, /* PPE cpu code exp fake mac header err */
+	NSS_PPE_STATS_CPU_CODE_EXP_BITMAP_MAX                     = 78, /* PPE cpu code exp bitmap max */
+	NSS_PPE_STATS_CPU_CODE_L2_EXP_MRU_FAIL                    = 79, /* PPE cpu code l2 exp mru fail */
+	NSS_PPE_STATS_CPU_CODE_L2_EXP_MTU_FAIL                    = 80, /* PPE cpu code l2 exp mtu fail */
+	NSS_PPE_STATS_CPU_CODE_L3_EXP_IP_PREFIX_BC                = 81, /* PPE cpu code l3 exp ip prefix bc */
+	NSS_PPE_STATS_CPU_CODE_L3_EXP_MTU_FAIL                    = 82, /* PPE cpu code l3 exp mtu fail */
+	NSS_PPE_STATS_CPU_CODE_L3_EXP_MRU_FAIL                    = 83, /* PPE cpu code l3 exp mru fail */
+	NSS_PPE_STATS_CPU_CODE_L3_EXP_ICMP_RDT                    = 84, /* PPE cpu code l3 exp icmp rdt */
+	NSS_PPE_STATS_CPU_CODE_L3_EXP_IP_RT_TTL1_TO_ME            = 85, /* PPE cpu code l3 exp ip rt ttl1 to me */
+	NSS_PPE_STATS_CPU_CODE_L3_EXP_IP_RT_TTL_ZERO              = 86, /* PPE cpu code l3 exp ip rt ttl zero */
+	NSS_PPE_STATS_CPU_CODE_L3_FLOW_SERVICE_CODE_LOOP          = 87, /* PPE cpu code l3 flow service code loop */
+	NSS_PPE_STATS_CPU_CODE_L3_FLOW_DE_ACCELERATE              = 88, /* PPE cpu code l3 flow de accelerate */
+	NSS_PPE_STATS_CPU_CODE_L3_EXP_FLOW_SRC_IF_CHK_FAIL        = 89, /* PPE cpu code l3 exp flow src if chk fail */
+	NSS_PPE_STATS_CPU_CODE_L3_FLOW_SYNC_TOGGLE_MISMATCH       = 90, /* PPE cpu code l3 flow sync toggle mismatch */
+	NSS_PPE_STATS_CPU_CODE_L3_EXP_MTU_DF_FAIL                 = 91, /* PPE cpu code l3 exp mtu df fail */
+	NSS_PPE_STATS_CPU_CODE_L3_EXP_PPPOE_MULTICAST             = 92, /* PPE cpu code l3 exp pppoe multicast */
+	NSS_PPE_STATS_CPU_CODE_MGMT_OFFSET                        = 96, /* PPE cpu code mgmt offset */
+	NSS_PPE_STATS_CPU_CODE_MGMT_EAPOL                         = 97, /* PPE cpu code mgmt eapol */
+	NSS_PPE_STATS_CPU_CODE_MGMT_PPPOE_DIS                     = 98, /* PPE cpu code mgmt pppoe dis */
+	NSS_PPE_STATS_CPU_CODE_MGMT_IGMP                          = 99, /* PPE cpu code mgmt igmp */
+	NSS_PPE_STATS_CPU_CODE_MGMT_ARP_REQ                       = 100, /* PPE cpu code mgmt arp req */
+	NSS_PPE_STATS_CPU_CODE_MGMT_ARP_REP                       = 101, /* PPE cpu code mgmt arp rep */
+	NSS_PPE_STATS_CPU_CODE_MGMT_DHCPv4                        = 102, /* PPE cpu code mgmt dhcpv4 */
+	NSS_PPE_STATS_CPU_CODE_MGMT_MLD                           = 107, /* PPE cpu code mgmt mld */
+	NSS_PPE_STATS_CPU_CODE_MGMT_NS                            = 108, /* PPE cpu code mgmt ns */
+	NSS_PPE_STATS_CPU_CODE_MGMT_NA                            = 109, /* PPE cpu code mgmt na */
+	NSS_PPE_STATS_CPU_CODE_MGMT_DHCPv6                        = 110, /* PPE cpu code mgmt dhcpv6 */
+	NSS_PPE_STATS_CPU_CODE_PTP_OFFSET                         = 112, /* PPE cpu code ptp offset */
+	NSS_PPE_STATS_CPU_CODE_PTP_SYNC                           = 113, /* PPE cpu code ptp sync */
+	NSS_PPE_STATS_CPU_CODE_PTP_FOLLOW_UP                      = 114, /* PPE cpu code ptp follow up */
+	NSS_PPE_STATS_CPU_CODE_PTP_DELAY_REQ                      = 115, /* PPE cpu code ptp delay req */
+	NSS_PPE_STATS_CPU_CODE_PTP_DELAY_RESP                     = 116, /* PPE cpu code ptp delay resp */
+	NSS_PPE_STATS_CPU_CODE_PTP_PDELAY_REQ                     = 117, /* PPE cpu code ptp pdelay req */
+	NSS_PPE_STATS_CPU_CODE_PTP_PDELAY_RESP                    = 118, /* PPE cpu code ptp pdelay resp */
+	NSS_PPE_STATS_CPU_CODE_PTP_PDELAY_RESP_FOLLOW_UP          = 119, /* PPE cpu code ptp pdelay resp follow up */
+	NSS_PPE_STATS_CPU_CODE_PTP_ANNOUNCE                       = 120, /* PPE cpu code ptp announce */
+	NSS_PPE_STATS_CPU_CODE_PTP_MANAGEMENT                     = 121, /* PPE cpu code ptp management */
+	NSS_PPE_STATS_CPU_CODE_PTP_SIGNALING                      = 122, /* PPE cpu code ptp signaling */
+	NSS_PPE_STATS_CPU_CODE_PTP_PKT_RSV_MSG                    = 127, /* PPE cpu code ptp pkt rsv msg */
+	NSS_PPE_STATS_CPU_CODE_IPV4_SG_UNKNOWN                    = 136, /* PPE cpu code ipv4 sg unknown */
+	NSS_PPE_STATS_CPU_CODE_IPV6_SG_UNKNOWN                    = 137, /* PPE cpu code ipv6 sg unknown */
+	NSS_PPE_STATS_CPU_CODE_ARP_SG_UNKNOWN                     = 138, /* PPE cpu code arp sg unknown */
+	NSS_PPE_STATS_CPU_CODE_ND_SG_UNKNOWN                      = 139, /* PPE cpu code nd sg unknown */
+	NSS_PPE_STATS_CPU_CODE_IPV4_SG_VIO                        = 140, /* PPE cpu code ipv4 sg vio */
+	NSS_PPE_STATS_CPU_CODE_IPV6_SG_VIO                        = 141, /* PPE cpu code ipv6 sg vio */
+	NSS_PPE_STATS_CPU_CODE_ARP_SG_VIO                         = 142, /* PPE cpu code arp sg vio */
+	NSS_PPE_STATS_CPU_CODE_ND_SG_VIO                          = 143, /* PPE cpu code nd sg vio */
+	NSS_PPE_STATS_CPU_CODE_L3_ROUTING_IP_TO_ME                = 148, /* PPE cpu code l3 routing ip to me */
+	NSS_PPE_STATS_CPU_CODE_L3_FLOW_SNAT_ACTION                = 149, /* PPE cpu code l3 flow snat action */
+	NSS_PPE_STATS_CPU_CODE_L3_FLOW_DNAT_ACTION                = 150, /* PPE cpu code l3 flow dnat action */
+	NSS_PPE_STATS_CPU_CODE_L3_FLOW_RT_ACTION                  = 151, /* PPE cpu code l3 flow rt action */
+	NSS_PPE_STATS_CPU_CODE_L3_FLOW_BR_ACTION                  = 152, /* PPE cpu code l3 flow br action */
+	NSS_PPE_STATS_CPU_CODE_L3_MC_BRIDGE_ACTION                = 153, /* PPE cpu code l3 mc bridge action */
+	NSS_PPE_STATS_CPU_CODE_L3_ROUTE_PREHEAD_RT_ACTION         = 154, /* PPE cpu code l3 route prehead rt action */
+	NSS_PPE_STATS_CPU_CODE_L3_ROUTE_PREHEAD_SNAPT_ACTION      = 155, /* PPE cpu code l3 route prehead snapt action */
+	NSS_PPE_STATS_CPU_CODE_L3_ROUTE_PREHEAD_DNAPT_ACTION      = 156, /* PPE cpu code l3 route prehead dnapt action */
+	NSS_PPE_STATS_CPU_CODE_L3_ROUTE_PREHEAD_SNAT_ACTION       = 157, /* PPE cpu code l3 route prehead snat action */
+	NSS_PPE_STATS_CPU_CODE_L3_ROUTE_PREHEAD_DNAT_ACTION       = 158, /* PPE cpu code l3 route prehead dnat action */
+	NSS_PPE_STATS_CPU_CODE_L3_NO_ROUTE_PREHEAD_NAT_ACTION     = 159, /* PPE cpu code l3 no route prehead nat action */
+	NSS_PPE_STATS_CPU_CODE_L3_NO_ROUTE_PREHEAD_NAT_ERROR      = 160, /* PPE cpu code l3 no route prehead nat error */
+	NSS_PPE_STATS_CPU_CODE_L3_ROUTE_ACTION                    = 161, /* PPE cpu code l3 route action */
+	NSS_PPE_STATS_CPU_CODE_L3_NO_ROUTE_ACTION                 = 162, /* PPE cpu code l3 no route action */
+	NSS_PPE_STATS_CPU_CODE_L3_NO_ROUTE_NH_INVALID_ACTION      = 163, /* PPE cpu code l3 no route nh invalid action */
+	NSS_PPE_STATS_CPU_CODE_L3_NO_ROUTE_PREHEAD_ACTION         = 164, /* PPE cpu code l3 no route prehead action */
+	NSS_PPE_STATS_CPU_CODE_L3_BRIDGE_ACTION                   = 165, /* PPE cpu code l3 bridge action */
+	NSS_PPE_STATS_CPU_CODE_L3_FLOW_ACTION                     = 166, /* PPE cpu code l3 flow action */
+	NSS_PPE_STATS_CPU_CODE_L3_FLOW_MISS_ACTION                = 167, /* PPE cpu code l3 flow miss action */
+	NSS_PPE_STATS_CPU_CODE_L2_NEW_MAC_ADDRESS                 = 168, /* PPE cpu code l2 new mac address */
+	NSS_PPE_STATS_CPU_CODE_L2_HASH_COLLISION                  = 169, /* PPE cpu code l2 hash collision */
+	NSS_PPE_STATS_CPU_CODE_L2_STATION_MOVE                    = 170, /* PPE cpu code l2 station move */
+	NSS_PPE_STATS_CPU_CODE_L2_LEARN_LIMIT                     = 171, /* PPE cpu code l2 learn limit */
+	NSS_PPE_STATS_CPU_CODE_L2_SA_LOOKUP_ACTION                = 172, /* PPE cpu code l2 sa lookup action */
+	NSS_PPE_STATS_CPU_CODE_L2_DA_LOOKUP_ACTION                = 173, /* PPE cpu code l2 da lookup action */
+	NSS_PPE_STATS_CPU_CODE_APP_CTRL_ACTION                    = 174, /* PPE cpu code app ctrl action */
+	NSS_PPE_STATS_CPU_CODE_IN_VLAN_FILTER_ACTION              = 175, /* PPE cpu code in vlan filter action */
+	NSS_PPE_STATS_CPU_CODE_IN_VLAN_XLT_MISS                   = 176, /* PPE cpu code in vlan xlt miss */
+	NSS_PPE_STATS_CPU_CODE_EG_VLAN_FILTER_DROP                = 177, /* PPE cpu code eg vlan filter drop */
+	NSS_PPE_STATS_CPU_CODE_ACL_PRE_ACTION                     = 178, /* PPE cpu code acl pre action */
+	NSS_PPE_STATS_CPU_CODE_ACL_POST_ACTION                    = 179, /* PPE cpu code acl post action */
+	NSS_PPE_STATS_CPU_CODE_SERVICE_CODE_ACTION                = 180, /* PPE cpu code service code action */
+};
+
+/*
+ * NSS PPE statistics
+ */
+struct nss_ppe_stats_debug {
+	uint32_t conn_stats[NSS_PPE_STATS_CONN_MAX];
+	uint32_t l3_stats[NSS_PPE_STATS_L3_MAX];
+	uint32_t code_stats[NSS_PPE_STATS_CODE_MAX];
+	int32_t if_index;
+	uint32_t if_num;	/* nss interface number */
+	bool valid;
+};
+
+/*
+ * Data structures to store NSS PPE debug statistics
+ */
+static struct nss_ppe_stats_debug nss_ppe_debug_stats;
+
+/*
+ * NSS PPE statistics APIs
+ */
+extern void nss_ppe_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_ppe_sync_stats_msg *stats_msg, uint16_t if_num);
+extern void nss_ppe_stats_dentry_create(void);
+
+#endif /* __NSS_PPE_STATS_H */
diff --git a/nss_pppoe.c b/nss_pppoe.c
index 43a1946..18faea2 100644
--- a/nss_pppoe.c
+++ b/nss_pppoe.c
@@ -1,6 +1,6 @@
 /*
  **************************************************************************
- * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-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.
@@ -21,6 +21,7 @@
 
 #include "nss_tx_rx_common.h"
 #include <linux/if_pppox.h>
+#include "nss_pppoe_stats.h"
 
 /*
  * nss_pppoe_tx()
@@ -92,83 +93,6 @@
  */
 
 /*
- * nss_pppoe_session_reset()
- * 	Reset PPPoE session when session is destroyed.
- */
-static void nss_pppoe_session_reset(struct nss_ctx_instance *nss_ctx, struct nss_pppoe_session_reset_msg *npsr)
-{
-	uint32_t i;
-	uint32_t interface = npsr->interface;
-	uint32_t session_index = npsr->session_index;
-
-	/*
-	 * Reset the PPPoE statistics for this specific session.
-	 */
-	spin_lock_bh(&nss_ctx->nss_top->stats_lock);
-	for (i = 0; i < NSS_PPPOE_EXCEPTION_EVENT_MAX; i++) {
-		nss_ctx->nss_top->stats_if_exception_pppoe[interface][session_index][i] = 0;
-	}
-	spin_unlock_bh(&nss_ctx->nss_top->stats_lock);
-}
-
-/*
- * nss_pppoe_exception_stats_sync()
- *	Handle the syncing of PPPoE exception statistics.
- */
-static void nss_pppoe_exception_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_pppoe_conn_stats_sync_msg *npess)
-{
-	struct nss_top_instance *nss_top = nss_ctx->nss_top;
-	uint32_t index = npess->index;
-	uint32_t interface_num = npess->interface_num;
-	uint32_t i;
-
-	spin_lock_bh(&nss_top->stats_lock);
-
-	if (interface_num >= NSS_MAX_PHYSICAL_INTERFACES) {
-		spin_unlock_bh(&nss_top->stats_lock);
-		nss_warning("%p: Incorrect interface number %d for PPPoE exception stats", nss_ctx, interface_num);
-		return;
-	}
-
-	/*
-	 * pppoe exception stats
-	 */
-	for (i = 0; i < NSS_PPPOE_EXCEPTION_EVENT_MAX; i++) {
-		nss_top->stats_if_exception_pppoe[interface_num][index][i] += npess->exception_events_pppoe[i];
-	}
-
-	spin_unlock_bh(&nss_top->stats_lock);
-}
-
-/*
- * nss_pppoe_node_stats_sync()
- *	Handle the syncing of PPPoE node statistics.
- */
-static void nss_pppoe_node_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_pppoe_node_stats_sync_msg *npess)
-{
-	struct nss_top_instance *nss_top = nss_ctx->nss_top;
-	int j;
-
-	spin_lock_bh(&nss_top->stats_lock);
-
-	nss_top->stats_node[NSS_PPPOE_RX_INTERFACE][NSS_STATS_NODE_RX_PKTS] += npess->node_stats.rx_packets;
-	nss_top->stats_node[NSS_PPPOE_RX_INTERFACE][NSS_STATS_NODE_RX_BYTES] += npess->node_stats.rx_bytes;
-	nss_top->stats_node[NSS_PPPOE_RX_INTERFACE][NSS_STATS_NODE_TX_PKTS] += npess->node_stats.tx_packets;
-	nss_top->stats_node[NSS_PPPOE_RX_INTERFACE][NSS_STATS_NODE_TX_BYTES] += npess->node_stats.tx_bytes;
-
-	for (j = 0; j < NSS_MAX_NUM_PRI; j++) {
-		nss_top->stats_node[NSS_PPPOE_RX_INTERFACE][NSS_STATS_NODE_RX_QUEUE_0_DROPPED + j] += npess->node_stats.rx_dropped[j];
-	}
-
-	nss_top->stats_pppoe[NSS_STATS_PPPOE_SESSION_CREATE_REQUESTS] += npess->pppoe_session_create_requests;
-	nss_top->stats_pppoe[NSS_STATS_PPPOE_SESSION_CREATE_FAILURES] += npess->pppoe_session_create_failures;
-	nss_top->stats_pppoe[NSS_STATS_PPPOE_SESSION_DESTROY_REQUESTS] += npess->pppoe_session_destroy_requests;
-	nss_top->stats_pppoe[NSS_STATS_PPPOE_SESSION_DESTROY_REQUESTS] += npess->pppoe_session_destroy_requests;
-
-	spin_unlock_bh(&nss_top->stats_lock);
-}
-
-/*
  * nss_pppoe_rx_msg_handler()
  *	Handle NSS -> HLOS messages for PPPoE
  */
@@ -201,13 +125,13 @@
 	 */
 	switch (nim->cm.type) {
 	case NSS_PPPOE_RX_NODE_STATS_SYNC:
-		nss_pppoe_node_stats_sync(nss_ctx, &nim->msg.pppoe_node_stats_sync);
+		nss_pppoe_stats_node_sync(nss_ctx, &nim->msg.pppoe_node_stats_sync);
 		break;
 	case NSS_PPPOE_RX_CONN_STATS_SYNC:
-		nss_pppoe_exception_stats_sync(nss_ctx, &nim->msg.pppoe_conn_stats_sync);
+		nss_pppoe_stats_exception_sync(nss_ctx, &nim->msg.pppoe_conn_stats_sync);
 		break;
 	case NSS_PPPOE_RX_SESSION_RESET:
-		nss_pppoe_session_reset(nss_ctx, &nim->msg.pppoe_session_reset);
+		nss_pppoe_stats_session_reset(nss_ctx, &nim->msg.pppoe_session_reset);
 		break;
 	default:
 		nss_warning("%p: Received response %d for type %d, interface %d",
@@ -221,6 +145,8 @@
 void nss_pppoe_register_handler(struct nss_ctx_instance *nss_ctx)
 {
 	nss_core_register_handler(nss_ctx, NSS_PPPOE_RX_INTERFACE, nss_pppoe_rx_msg_handler, NULL);
+
+	nss_pppoe_stats_dentry_create();
 }
 
 /*
diff --git a/nss_pppoe_stats.c b/nss_pppoe_stats.c
new file mode 100644
index 0000000..e95582e
--- /dev/null
+++ b/nss_pppoe_stats.c
@@ -0,0 +1,222 @@
+/*
+ **************************************************************************
+ * Copyright (c) 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.
+ * 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_stats.h"
+#include "nss_core.h"
+#include "nss_pppoe_stats.h"
+
+uint64_t nss_pppoe_stats[NSS_PPPOE_STATS_MAX];
+uint64_t nss_pppoe_stats_exception[NSS_MAX_PHYSICAL_INTERFACES + 1][NSS_PPPOE_NUM_SESSION_PER_INTERFACE + 1][NSS_PPPOE_EXCEPTION_EVENT_MAX];
+
+/*
+ * nss_pppoe_stats_str
+ *	PPPoE stats strings
+ */
+static int8_t *nss_pppoe_stats_str[NSS_PPPOE_STATS_MAX] = {
+	"create_requests",
+	"create_failures",
+	"destroy_requests",
+	"destroy_misses"
+};
+
+/*
+ * nss_pppoe_stats_exception_str
+ *	Interface stats strings for PPPoE exceptions
+ */
+static int8_t *nss_pppoe_stats_exception_str[NSS_PPPOE_EXCEPTION_EVENT_MAX] = {
+	"PPPOE_WRONG_VERSION_OR_TYPE",
+	"PPPOE_WRONG_CODE",
+	"PPPOE_HEADER_INCOMPLETE",
+	"PPPOE_UNSUPPORTED_PPP_PROTOCOL",
+	"PPPOE_DEPRECATED"
+};
+
+/*
+ * nss_pppoe_stats_read()
+ *	Read PPPoE stats
+ */
+static ssize_t nss_pppoe_stats_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
+{
+	uint64_t stats_shadow_pppoe_except[NSS_PPPOE_NUM_SESSION_PER_INTERFACE][NSS_PPPOE_EXCEPTION_EVENT_MAX];
+	int32_t i, j, k;
+
+	/*
+	 * max output lines = #stats + start tag line + end tag line + three blank lines
+	 */
+	uint32_t max_output_lines = (NSS_STATS_NODE_MAX + 2) + (NSS_PPPOE_STATS_MAX + 3) +
+					((NSS_MAX_PHYSICAL_INTERFACES * NSS_PPPOE_NUM_SESSION_PER_INTERFACE * (NSS_PPPOE_EXCEPTION_EVENT_MAX + 5)) + 3) + 5;
+	size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
+	size_t size_wr = 0;
+	ssize_t bytes_read = 0;
+	uint64_t *stats_shadow;
+
+	char *lbuf = kzalloc(size_al, GFP_KERNEL);
+	if (unlikely(lbuf == NULL)) {
+		nss_warning("Could not allocate memory for local statistics buffer");
+		return 0;
+	}
+
+	stats_shadow = kzalloc(64 * 8, GFP_KERNEL);
+	if (unlikely(stats_shadow == NULL)) {
+		nss_warning("Could not allocate memory for local shadow buffer");
+		kfree(lbuf);
+		return 0;
+	}
+
+	size_wr = scnprintf(lbuf, size_al, "pppoe stats start:\n\n");
+
+	size_wr = nss_stats_fill_common_stats(NSS_PPPOE_RX_INTERFACE, lbuf, size_wr, size_al);
+
+	/*
+	 * PPPoE node stats
+	 */
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\npppoe node stats:\n\n");
+	spin_lock_bh(&nss_top_main.stats_lock);
+	for (i = 0; (i < NSS_PPPOE_STATS_MAX); i++) {
+		stats_shadow[i] = nss_pppoe_stats[i];
+	}
+	spin_unlock_bh(&nss_top_main.stats_lock);
+
+	for (i = 0; (i < NSS_PPPOE_STATS_MAX); i++) {
+		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
+					"%s = %llu\n", nss_pppoe_stats_str[i], stats_shadow[i]);
+	}
+
+	/*
+	 * Exception stats
+	 */
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nException PPPoE:\n\n");
+
+	for (j = 1; j <= NSS_MAX_PHYSICAL_INTERFACES; j++) {
+		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nInterface %d:\n\n", j);
+
+		spin_lock_bh(&nss_top_main.stats_lock);
+		for (k = 1; k <= NSS_PPPOE_NUM_SESSION_PER_INTERFACE; k++) {
+			for (i = 0; (i < NSS_PPPOE_EXCEPTION_EVENT_MAX); i++) {
+				stats_shadow_pppoe_except[k - 1][i] = nss_pppoe_stats_exception[j][k][i];
+			}
+		}
+		spin_unlock_bh(&nss_top_main.stats_lock);
+
+		for (k = 1; k <= NSS_PPPOE_NUM_SESSION_PER_INTERFACE; k++) {
+			size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "%d. Session\n", k);
+			for (i = 0; (i < NSS_PPPOE_EXCEPTION_EVENT_MAX); i++) {
+				size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
+						"%s = %llu\n",
+						nss_pppoe_stats_exception_str[i],
+						stats_shadow_pppoe_except[k - 1][i]);
+			}
+		}
+
+	}
+
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\npppoe stats end\n\n");
+	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
+	kfree(lbuf);
+	kfree(stats_shadow);
+
+	return bytes_read;
+}
+
+/*
+ * nss_pppoe_stats_ops
+ */
+NSS_STATS_DECLARE_FILE_OPERATIONS(pppoe)
+
+/*
+ * nss_pppoe_stats_dentry_create()
+ *	Create PPPoE node statistics debug entry.
+ */
+void nss_pppoe_stats_dentry_create(void)
+{
+	nss_stats_create_dentry("pppoe", &nss_pppoe_stats_ops);
+}
+
+/*
+ * nss_pppoe_stats_node_sync()
+ *	Handle the syncing of PPPoE node statistics.
+ */
+void nss_pppoe_stats_node_sync(struct nss_ctx_instance *nss_ctx, struct nss_pppoe_node_stats_sync_msg *npess)
+{
+	struct nss_top_instance *nss_top = nss_ctx->nss_top;
+	int j;
+
+	spin_lock_bh(&nss_top->stats_lock);
+
+	nss_top->stats_node[NSS_PPPOE_RX_INTERFACE][NSS_STATS_NODE_RX_PKTS] += npess->node_stats.rx_packets;
+	nss_top->stats_node[NSS_PPPOE_RX_INTERFACE][NSS_STATS_NODE_RX_BYTES] += npess->node_stats.rx_bytes;
+	nss_top->stats_node[NSS_PPPOE_RX_INTERFACE][NSS_STATS_NODE_TX_PKTS] += npess->node_stats.tx_packets;
+	nss_top->stats_node[NSS_PPPOE_RX_INTERFACE][NSS_STATS_NODE_TX_BYTES] += npess->node_stats.tx_bytes;
+
+	for (j = 0; j < NSS_MAX_NUM_PRI; j++) {
+		nss_top->stats_node[NSS_PPPOE_RX_INTERFACE][NSS_STATS_NODE_RX_QUEUE_0_DROPPED + j] += npess->node_stats.rx_dropped[j];
+	}
+
+	nss_pppoe_stats[NSS_PPPOE_STATS_SESSION_CREATE_REQUESTS] += npess->pppoe_session_create_requests;
+	nss_pppoe_stats[NSS_PPPOE_STATS_SESSION_CREATE_FAILURES] += npess->pppoe_session_create_failures;
+	nss_pppoe_stats[NSS_PPPOE_STATS_SESSION_DESTROY_REQUESTS] += npess->pppoe_session_destroy_requests;
+	nss_pppoe_stats[NSS_PPPOE_STATS_SESSION_DESTROY_REQUESTS] += npess->pppoe_session_destroy_requests;
+
+	spin_unlock_bh(&nss_top->stats_lock);
+}
+
+/*
+ * nss_pppoe_stats_session_reset()
+ * 	Reset PPPoE session when session is destroyed.
+ */
+void nss_pppoe_stats_session_reset(struct nss_ctx_instance *nss_ctx, struct nss_pppoe_session_reset_msg *npsr)
+{
+	uint32_t i;
+	uint32_t interface = npsr->interface;
+	uint32_t session_index = npsr->session_index;
+
+	/*
+	 * Reset the PPPoE statistics for this specific session.
+	 */
+	spin_lock_bh(&nss_ctx->nss_top->stats_lock);
+	for (i = 0; i < NSS_PPPOE_EXCEPTION_EVENT_MAX; i++) {
+		nss_pppoe_stats_exception[interface][session_index][i] = 0;
+	}
+	spin_unlock_bh(&nss_ctx->nss_top->stats_lock);
+}
+
+/*
+ * nss_pppoe_stats_exception_sync()
+ *	Handle the syncing of PPPoE exception statistics.
+ */
+void nss_pppoe_stats_exception_sync(struct nss_ctx_instance *nss_ctx, struct nss_pppoe_conn_stats_sync_msg *npess)
+{
+	struct nss_top_instance *nss_top = nss_ctx->nss_top;
+	uint32_t index = npess->index;
+	uint32_t interface_num = npess->interface_num;
+	uint32_t i;
+
+	spin_lock_bh(&nss_top->stats_lock);
+
+	if (interface_num >= NSS_MAX_PHYSICAL_INTERFACES) {
+		spin_unlock_bh(&nss_top->stats_lock);
+		nss_warning("%p: Incorrect interface number %d for PPPoE exception stats", nss_ctx, interface_num);
+		return;
+	}
+
+	/*
+	 * pppoe exception stats
+	 */
+	for (i = 0; i < NSS_PPPOE_EXCEPTION_EVENT_MAX; i++) {
+		nss_pppoe_stats_exception[interface_num][index][i] += npess->exception_events_pppoe[i];
+	}
+	spin_unlock_bh(&nss_top->stats_lock);
+}
diff --git a/nss_pppoe_stats.h b/nss_pppoe_stats.h
new file mode 100644
index 0000000..dc33f7b
--- /dev/null
+++ b/nss_pppoe_stats.h
@@ -0,0 +1,43 @@
+/*
+ ******************************************************************************
+ * 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.
+ * ****************************************************************************
+ */
+
+#ifndef __NSS_PPPOE_STATS_H
+#define __NSS_PPPOE_STATS_H
+
+/*
+ * PPPoE statistics
+ */
+enum nss_pppoe_stats_types {
+	NSS_PPPOE_STATS_SESSION_CREATE_REQUESTS = 0,
+					/* Number of PPPoE session create requests */
+	NSS_PPPOE_STATS_SESSION_CREATE_FAILURES,
+					/* Number of PPPoE session create failures */
+	NSS_PPPOE_STATS_SESSION_DESTROY_REQUESTS,
+					/* Number of PPPoE session destroy requests */
+	NSS_PPPOE_STATS_SESSION_DESTROY_MISSES,
+					/* Number of PPPoE session destroy requests that missed the cache */
+	NSS_PPPOE_STATS_MAX,
+};
+
+/*
+ * PPPoE statistics APIs
+ */
+extern void nss_pppoe_stats_node_sync(struct nss_ctx_instance *nss_ctx, struct nss_pppoe_node_stats_sync_msg *npess);
+extern void nss_pppoe_stats_session_reset(struct nss_ctx_instance *nss_ctx, struct nss_pppoe_session_reset_msg *npsr);
+extern void nss_pppoe_stats_exception_sync(struct nss_ctx_instance *nss_ctx, struct nss_pppoe_conn_stats_sync_msg *npess);
+extern void nss_pppoe_stats_dentry_create(void);
+
+#endif /* __NSS_PPPOE_STATS_H */
diff --git a/nss_pptp.c b/nss_pptp.c
index dc66b14..8af8ef2 100644
--- a/nss_pptp.c
+++ b/nss_pptp.c
@@ -16,6 +16,7 @@
 
 #include <net/sock.h>
 #include "nss_tx_rx_common.h"
+#include "nss_pptp_stats.h"
 
 #define NSS_PPTP_TX_TIMEOUT 3000 /* 3 Seconds */
 
@@ -23,7 +24,7 @@
  * Data structures to store pptp nss debug stats
  */
 static DEFINE_SPINLOCK(nss_pptp_session_debug_stats_lock);
-static struct nss_stats_pptp_session_debug nss_pptp_session_debug_stats[NSS_MAX_PPTP_DYNAMIC_INTERFACES];
+static struct nss_pptp_stats_session_debug nss_pptp_session_debug_stats[NSS_MAX_PPTP_DYNAMIC_INTERFACES];
 
 /*
  * Private data structure
@@ -46,31 +47,31 @@
 	spin_lock_bh(&nss_pptp_session_debug_stats_lock);
 	for (i = 0; i < NSS_MAX_PPTP_DYNAMIC_INTERFACES; i++) {
 		if (nss_pptp_session_debug_stats[i].if_num == if_num) {
-			nss_pptp_session_debug_stats[i].stats[NSS_STATS_PPTP_ENCAP_RX_PACKETS] += stats_msg->encap_stats.rx_packets;
-			nss_pptp_session_debug_stats[i].stats[NSS_STATS_PPTP_ENCAP_RX_BYTES] += stats_msg->encap_stats.rx_bytes;
-			nss_pptp_session_debug_stats[i].stats[NSS_STATS_PPTP_ENCAP_TX_PACKETS] += stats_msg->encap_stats.tx_packets;
-			nss_pptp_session_debug_stats[i].stats[NSS_STATS_PPTP_ENCAP_TX_BYTES] += stats_msg->encap_stats.tx_bytes;
+			nss_pptp_session_debug_stats[i].stats[NSS_PPTP_STATS_ENCAP_RX_PACKETS] += stats_msg->encap_stats.rx_packets;
+			nss_pptp_session_debug_stats[i].stats[NSS_PPTP_STATS_ENCAP_RX_BYTES] += stats_msg->encap_stats.rx_bytes;
+			nss_pptp_session_debug_stats[i].stats[NSS_PPTP_STATS_ENCAP_TX_PACKETS] += stats_msg->encap_stats.tx_packets;
+			nss_pptp_session_debug_stats[i].stats[NSS_PPTP_STATS_ENCAP_TX_BYTES] += stats_msg->encap_stats.tx_bytes;
 			for (j = 0; j < NSS_MAX_NUM_PRI; j++) {
-				nss_pptp_session_debug_stats[i].stats[NSS_STATS_PPTP_ENCAP_RX_QUEUE_0_DROP + j] += stats_msg->encap_stats.rx_dropped[j];
+				nss_pptp_session_debug_stats[i].stats[NSS_PPTP_STATS_ENCAP_RX_QUEUE_0_DROP + j] += stats_msg->encap_stats.rx_dropped[j];
 			}
-			nss_pptp_session_debug_stats[i].stats[NSS_STATS_PPTP_DECAP_RX_PACKETS] += stats_msg->decap_stats.rx_packets;
-			nss_pptp_session_debug_stats[i].stats[NSS_STATS_PPTP_DECAP_RX_BYTES] += stats_msg->decap_stats.rx_bytes;
-			nss_pptp_session_debug_stats[i].stats[NSS_STATS_PPTP_DECAP_TX_PACKETS] += stats_msg->decap_stats.tx_packets;
-			nss_pptp_session_debug_stats[i].stats[NSS_STATS_PPTP_DECAP_TX_BYTES] += stats_msg->decap_stats.tx_bytes;
+			nss_pptp_session_debug_stats[i].stats[NSS_PPTP_STATS_DECAP_RX_PACKETS] += stats_msg->decap_stats.rx_packets;
+			nss_pptp_session_debug_stats[i].stats[NSS_PPTP_STATS_DECAP_RX_BYTES] += stats_msg->decap_stats.rx_bytes;
+			nss_pptp_session_debug_stats[i].stats[NSS_PPTP_STATS_DECAP_TX_PACKETS] += stats_msg->decap_stats.tx_packets;
+			nss_pptp_session_debug_stats[i].stats[NSS_PPTP_STATS_DECAP_TX_BYTES] += stats_msg->decap_stats.tx_bytes;
 			for (j = 0; j < NSS_MAX_NUM_PRI; j++) {
-				nss_pptp_session_debug_stats[i].stats[NSS_STATS_PPTP_DECAP_RX_QUEUE_0_DROP + j] += stats_msg->decap_stats.rx_dropped[j];
+				nss_pptp_session_debug_stats[i].stats[NSS_PPTP_STATS_DECAP_RX_QUEUE_0_DROP + j] += stats_msg->decap_stats.rx_dropped[j];
 			}
-			nss_pptp_session_debug_stats[i].stats[NSS_STATS_PPTP_SESSION_ENCAP_HEADROOM_ERR] += stats_msg->exception_events[PPTP_EXCEPTION_EVENT_ENCAP_HEADROOM_ERR];
-			nss_pptp_session_debug_stats[i].stats[NSS_STATS_PPTP_SESSION_ENCAP_SMALL_SIZE] += stats_msg->exception_events[PPTP_EXCEPTION_EVENT_ENCAP_SMALL_SIZE];
-			nss_pptp_session_debug_stats[i].stats[NSS_STATS_PPTP_SESSION_ENCAP_PNODE_ENQUEUE_FAIL] += stats_msg->exception_events[PPTP_EXCEPTION_EVENT_ENCAP_PNODE_ENQUEUE_FAIL];
-			nss_pptp_session_debug_stats[i].stats[NSS_STATS_PPTP_SESSION_DECAP_NO_SEQ_NOR_ACK] += stats_msg->exception_events[PPTP_EXCEPTION_EVENT_DECAP_NO_SEQ_NOR_ACK];
-			nss_pptp_session_debug_stats[i].stats[NSS_STATS_PPTP_SESSION_DECAP_INVAL_GRE_FLAGS] += stats_msg->exception_events[PPTP_EXCEPTION_EVENT_DECAP_INVAL_GRE_FLAGS];
-			nss_pptp_session_debug_stats[i].stats[NSS_STATS_PPTP_SESSION_DECAP_INVAL_GRE_PROTO] += stats_msg->exception_events[PPTP_EXCEPTION_EVENT_DECAP_INVAL_GRE_PROTO];
-			nss_pptp_session_debug_stats[i].stats[NSS_STATS_PPTP_SESSION_DECAP_WRONG_SEQ] += stats_msg->exception_events[PPTP_EXCEPTION_EVENT_DECAP_WRONG_SEQ];
-			nss_pptp_session_debug_stats[i].stats[NSS_STATS_PPTP_SESSION_DECAP_INVAL_PPP_HDR] += stats_msg->exception_events[PPTP_EXCEPTION_EVENT_DECAP_INVAL_PPP_HDR];
-			nss_pptp_session_debug_stats[i].stats[NSS_STATS_PPTP_SESSION_DECAP_PPP_LCP] += stats_msg->exception_events[PPTP_EXCEPTION_EVENT_DECAP_PPP_LCP];
-			nss_pptp_session_debug_stats[i].stats[NSS_STATS_PPTP_SESSION_DECAP_UNSUPPORTED_PPP_PROTO] += stats_msg->exception_events[PPTP_EXCEPTION_EVENT_DECAP_UNSUPPORTED_PPP_PROTO];
-			nss_pptp_session_debug_stats[i].stats[NSS_STATS_PPTP_SESSION_DECAP_PNODE_ENQUEUE_FAIL] += stats_msg->exception_events[PPTP_EXCEPTION_EVENT_DECAP_PNODE_ENQUEUE_FAIL];
+			nss_pptp_session_debug_stats[i].stats[NSS_PPTP_STATS_SESSION_ENCAP_HEADROOM_ERR] += stats_msg->exception_events[PPTP_EXCEPTION_EVENT_ENCAP_HEADROOM_ERR];
+			nss_pptp_session_debug_stats[i].stats[NSS_PPTP_STATS_SESSION_ENCAP_SMALL_SIZE] += stats_msg->exception_events[PPTP_EXCEPTION_EVENT_ENCAP_SMALL_SIZE];
+			nss_pptp_session_debug_stats[i].stats[NSS_PPTP_STATS_SESSION_ENCAP_PNODE_ENQUEUE_FAIL] += stats_msg->exception_events[PPTP_EXCEPTION_EVENT_ENCAP_PNODE_ENQUEUE_FAIL];
+			nss_pptp_session_debug_stats[i].stats[NSS_PPTP_STATS_SESSION_DECAP_NO_SEQ_NOR_ACK] += stats_msg->exception_events[PPTP_EXCEPTION_EVENT_DECAP_NO_SEQ_NOR_ACK];
+			nss_pptp_session_debug_stats[i].stats[NSS_PPTP_STATS_SESSION_DECAP_INVAL_GRE_FLAGS] += stats_msg->exception_events[PPTP_EXCEPTION_EVENT_DECAP_INVAL_GRE_FLAGS];
+			nss_pptp_session_debug_stats[i].stats[NSS_PPTP_STATS_SESSION_DECAP_INVAL_GRE_PROTO] += stats_msg->exception_events[PPTP_EXCEPTION_EVENT_DECAP_INVAL_GRE_PROTO];
+			nss_pptp_session_debug_stats[i].stats[NSS_PPTP_STATS_SESSION_DECAP_WRONG_SEQ] += stats_msg->exception_events[PPTP_EXCEPTION_EVENT_DECAP_WRONG_SEQ];
+			nss_pptp_session_debug_stats[i].stats[NSS_PPTP_STATS_SESSION_DECAP_INVAL_PPP_HDR] += stats_msg->exception_events[PPTP_EXCEPTION_EVENT_DECAP_INVAL_PPP_HDR];
+			nss_pptp_session_debug_stats[i].stats[NSS_PPTP_STATS_SESSION_DECAP_PPP_LCP] += stats_msg->exception_events[PPTP_EXCEPTION_EVENT_DECAP_PPP_LCP];
+			nss_pptp_session_debug_stats[i].stats[NSS_PPTP_STATS_SESSION_DECAP_UNSUPPORTED_PPP_PROTO] += stats_msg->exception_events[PPTP_EXCEPTION_EVENT_DECAP_UNSUPPORTED_PPP_PROTO];
+			nss_pptp_session_debug_stats[i].stats[NSS_PPTP_STATS_SESSION_DECAP_PNODE_ENQUEUE_FAIL] += stats_msg->exception_events[PPTP_EXCEPTION_EVENT_DECAP_PNODE_ENQUEUE_FAIL];
 			break;
 		}
 	}
@@ -83,7 +84,7 @@
  */
 void nss_pptp_session_debug_stats_get(void *stats_mem)
 {
-	struct nss_stats_pptp_session_debug *stats = (struct nss_stats_pptp_session_debug *)stats_mem;
+	struct nss_pptp_stats_session_debug *stats = (struct nss_pptp_stats_session_debug *)stats_mem;
 	int i;
 
 	if (!stats) {
@@ -94,7 +95,7 @@
 	spin_lock_bh(&nss_pptp_session_debug_stats_lock);
 	for (i = 0; i < NSS_MAX_PPTP_DYNAMIC_INTERFACES; i++) {
 		if (nss_pptp_session_debug_stats[i].valid) {
-			memcpy(stats, &nss_pptp_session_debug_stats[i], sizeof(struct nss_stats_pptp_session_debug));
+			memcpy(stats, &nss_pptp_session_debug_stats[i], sizeof(struct nss_pptp_stats_session_debug));
 			stats++;
 		}
 	}
@@ -437,6 +438,8 @@
 
 	sema_init(&pptp_pvt.sem, 1);
 	init_completion(&pptp_pvt.complete);
+
+	nss_pptp_stats_dentry_create();
 }
 
 EXPORT_SYMBOL(nss_pptp_get_context);
diff --git a/nss_pptp_stats.c b/nss_pptp_stats.c
new file mode 100644
index 0000000..1e578cd
--- /dev/null
+++ b/nss_pptp_stats.c
@@ -0,0 +1,133 @@
+/*
+ **************************************************************************
+ * Copyright (c) 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.
+ * 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_stats.h"
+#include "nss_core.h"
+#include "nss_pptp_stats.h"
+
+/*
+ * nss_pptp_stats_session_debug_str
+ *	PPTP statistics strings for nss session stats
+ */
+static int8_t *nss_pptp_stats_session_debug_str[NSS_PPTP_STATS_SESSION_MAX] = {
+	"ENCAP_RX_PACKETS",
+	"ENCAP_RX_BYTES",
+	"ENCAP_TX_PACKETS",
+	"ENCAP_TX_BYTES",
+	"ENCAP_RX_QUEUE_0_DROP",
+	"ENCAP_RX_QUEUE_1_DROP",
+	"ENCAP_RX_QUEUE_2_DROP",
+	"ENCAP_RX_QUEUE_3_DROP",
+	"DECAP_RX_PACKETS",
+	"DECAP_RX_BYTES",
+	"DECAP_TX_PACKETS",
+	"DECAP_TX_BYTES",
+	"DECAP_RX_QUEUE_0_DROP",
+	"DECAP_RX_QUEUE_1_DROP",
+	"DECAP_RX_QUEUE_2_DROP",
+	"DECAP_RX_QUEUE_3_DROP",
+	"ENCAP_HEADROOM_ERR",
+	"ENCAP_SMALL_SIZE",
+	"ENCAP_PNODE_ENQUEUE_FAIL",
+	"DECAP_NO_SEQ_NOR_ACK",
+	"DECAP_INVAL_GRE_FLAGS",
+	"DECAP_INVAL_GRE_PROTO",
+	"DECAP_WRONG_SEQ",
+	"DECAP_INVAL_PPP_HDR",
+	"DECAP_PPP_LCP",
+	"DECAP_UNSUPPORTED_PPP_PROTO",
+	"DECAP_PNODE_ENQUEUE_FAIL",
+};
+
+/*
+ * nss_pptp_stats_read()
+ *	Read pptp statistics
+ */
+static ssize_t nss_pptp_stats_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
+{
+
+	uint32_t max_output_lines = 2 /* header & footer for session stats */
+					+ NSS_MAX_PPTP_DYNAMIC_INTERFACES * (NSS_PPTP_STATS_SESSION_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_pptp_stats_session_debug pptp_session_stats[NSS_MAX_PPTP_DYNAMIC_INTERFACES];
+	int id, i;
+
+	char *lbuf = kzalloc(size_al, GFP_KERNEL);
+	if (unlikely(lbuf == NULL)) {
+		nss_warning("Could not allocate memory for local statistics buffer");
+		return 0;
+	}
+
+	memset(&pptp_session_stats, 0, sizeof(struct nss_pptp_stats_session_debug) * NSS_MAX_PPTP_DYNAMIC_INTERFACES);
+
+	/*
+	 * Get all stats
+	 */
+	nss_pptp_session_debug_stats_get((void *)&pptp_session_stats);
+
+	/*
+	 * Session stats
+	 */
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\npptp session stats start:\n\n");
+	for (id = 0; id < NSS_MAX_PPTP_DYNAMIC_INTERFACES; id++) {
+
+			if (!pptp_session_stats[id].valid) {
+				break;
+			}
+
+			dev = dev_get_by_index(&init_net, pptp_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,
+						pptp_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,
+						pptp_session_stats[id].if_num);
+			}
+
+			for (i = 0; i < NSS_PPTP_STATS_SESSION_MAX; i++) {
+				size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
+						     "\t%s = %llu\n", nss_pptp_stats_session_debug_str[i],
+						      pptp_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, "\npptp session stats end\n");
+	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, size_wr);
+
+	kfree(lbuf);
+	return bytes_read;
+}
+
+/*
+ * nss_pptp_stats_ops
+ */
+NSS_STATS_DECLARE_FILE_OPERATIONS(pptp)
+
+/*
+ * nss_pptp_stats_dentry_create()
+ *	Create PPTP node statistics debug entry.
+ */
+void nss_pptp_stats_dentry_create(void)
+{
+	nss_stats_create_dentry("pptp", &nss_pptp_stats_ops);
+}
diff --git a/nss_pptp_stats.h b/nss_pptp_stats.h
new file mode 100644
index 0000000..5860ae0
--- /dev/null
+++ b/nss_pptp_stats.h
@@ -0,0 +1,69 @@
+/*
+ ******************************************************************************
+ * Copyright (c) 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.
+ * 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.
+ * ****************************************************************************
+ */
+
+#ifndef __NSS_PPTP_STATS_H
+#define __NSS_PPTP_STATS_H
+
+/*
+ * PPTP debug stats
+ */
+enum nss_pptp_stats_session {
+	NSS_PPTP_STATS_ENCAP_RX_PACKETS,
+	NSS_PPTP_STATS_ENCAP_RX_BYTES,
+	NSS_PPTP_STATS_ENCAP_TX_PACKETS,
+	NSS_PPTP_STATS_ENCAP_TX_BYTES,
+	NSS_PPTP_STATS_ENCAP_RX_QUEUE_0_DROP,
+	NSS_PPTP_STATS_ENCAP_RX_QUEUE_1_DROP,
+	NSS_PPTP_STATS_ENCAP_RX_QUEUE_2_DROP,
+	NSS_PPTP_STATS_ENCAP_RX_QUEUE_3_DROP,
+	NSS_PPTP_STATS_DECAP_RX_PACKETS,
+	NSS_PPTP_STATS_DECAP_RX_BYTES,
+	NSS_PPTP_STATS_DECAP_TX_PACKETS,
+	NSS_PPTP_STATS_DECAP_TX_BYTES,
+	NSS_PPTP_STATS_DECAP_RX_QUEUE_0_DROP,
+	NSS_PPTP_STATS_DECAP_RX_QUEUE_1_DROP,
+	NSS_PPTP_STATS_DECAP_RX_QUEUE_2_DROP,
+	NSS_PPTP_STATS_DECAP_RX_QUEUE_3_DROP,
+	NSS_PPTP_STATS_SESSION_ENCAP_HEADROOM_ERR,
+	NSS_PPTP_STATS_SESSION_ENCAP_SMALL_SIZE,
+	NSS_PPTP_STATS_SESSION_ENCAP_PNODE_ENQUEUE_FAIL,
+	NSS_PPTP_STATS_SESSION_DECAP_NO_SEQ_NOR_ACK,
+	NSS_PPTP_STATS_SESSION_DECAP_INVAL_GRE_FLAGS,
+	NSS_PPTP_STATS_SESSION_DECAP_INVAL_GRE_PROTO,
+	NSS_PPTP_STATS_SESSION_DECAP_WRONG_SEQ,
+	NSS_PPTP_STATS_SESSION_DECAP_INVAL_PPP_HDR,
+	NSS_PPTP_STATS_SESSION_DECAP_PPP_LCP,
+	NSS_PPTP_STATS_SESSION_DECAP_UNSUPPORTED_PPP_PROTO,
+	NSS_PPTP_STATS_SESSION_DECAP_PNODE_ENQUEUE_FAIL,
+	NSS_PPTP_STATS_SESSION_MAX
+};
+
+/*
+ * NSS PPTP node statistics session
+ */
+struct nss_pptp_stats_session_debug {
+	uint64_t stats[NSS_PPTP_STATS_SESSION_MAX];
+	int32_t if_index;
+	uint32_t if_num; /* nss interface number */
+	bool valid;
+};
+
+/*
+ * NSS PPTP statistics APIs
+ */
+extern void nss_pptp_stats_dentry_create(void);
+
+#endif /* __NSS_PPTP_STATS_H */
diff --git a/nss_sjack.c b/nss_sjack.c
index 84b5f92..ab79f9b 100644
--- a/nss_sjack.c
+++ b/nss_sjack.c
@@ -15,31 +15,7 @@
  */
 
 #include "nss_tx_rx_common.h"
-
-/*
- * nss_sjack_node_sync_update()
- *	Update sjack node stats.
- */
-static void nss_sjack_node_sync_update(struct nss_ctx_instance *nss_ctx, struct nss_sjack_stats_sync_msg *nins)
-{
-	struct nss_top_instance *nss_top = nss_ctx->nss_top;
-	int j;
-
-	/*
-	 * Update SJACK node stats.
-	 */
-	spin_lock_bh(&nss_top->stats_lock);
-	nss_top->stats_node[NSS_SJACK_INTERFACE][NSS_STATS_NODE_RX_PKTS] += nins->node_stats.rx_packets;
-	nss_top->stats_node[NSS_SJACK_INTERFACE][NSS_STATS_NODE_RX_BYTES] += nins->node_stats.rx_bytes;
-	nss_top->stats_node[NSS_SJACK_INTERFACE][NSS_STATS_NODE_TX_PKTS] += nins->node_stats.tx_packets;
-	nss_top->stats_node[NSS_SJACK_INTERFACE][NSS_STATS_NODE_TX_BYTES] += nins->node_stats.tx_bytes;
-
-	for (j = 0; j < NSS_MAX_NUM_PRI; j++) {
-		nss_top->stats_node[NSS_SJACK_INTERFACE][NSS_STATS_NODE_RX_QUEUE_0_DROPPED + j] += nins->node_stats.rx_dropped[j];
-	}
-
-	spin_unlock_bh(&nss_top->stats_lock);
-}
+#include "nss_sjack_stats.h"
 
 /*
  * nss_sjack_handler()
@@ -85,7 +61,7 @@
 		/*
 		 * Update sjack statistics on node sync.
 		 */
-		nss_sjack_node_sync_update(nss_ctx, &nsm->msg.stats_sync);
+		nss_sjack_stats_node_sync(nss_ctx, &nsm->msg.stats_sync);
 		break;
 	}
 
@@ -219,6 +195,8 @@
 	struct nss_ctx_instance *nss_ctx = nss_sjack_get_context();
 
 	nss_core_register_handler(nss_ctx, NSS_SJACK_INTERFACE, nss_sjack_handler, NULL);
+
+	nss_sjack_stats_dentry_create();
 }
 
 EXPORT_SYMBOL(nss_sjack_register_if);
diff --git a/nss_sjack_stats.c b/nss_sjack_stats.c
new file mode 100644
index 0000000..ce3458e
--- /dev/null
+++ b/nss_sjack_stats.c
@@ -0,0 +1,99 @@
+/*
+ **************************************************************************
+ * Copyright (c) 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.
+ * 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_stats.h"
+#include "nss_core.h"
+#include "nss_sjack_stats.h"
+
+/*
+ * nss_sjack_stats_read()
+ *	Read SJACK stats
+ */
+static ssize_t nss_sjack_stats_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
+{
+	/*
+	 * max output lines = #stats + start tag line + end tag line + three blank lines
+	 */
+	uint32_t max_output_lines = NSS_STATS_NODE_MAX + 5;
+	size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
+	size_t size_wr = 0;
+	ssize_t bytes_read = 0;
+	uint64_t *stats_shadow;
+
+	char *lbuf = kzalloc(size_al, GFP_KERNEL);
+	if (unlikely(lbuf == NULL)) {
+		nss_warning("Could not allocate memory for local statistics buffer");
+		return 0;
+	}
+
+	stats_shadow = kzalloc(NSS_STATS_NODE_MAX * 8, GFP_KERNEL);
+	if (unlikely(stats_shadow == NULL)) {
+		nss_warning("Could not allocate memory for local shadow buffer");
+		kfree(lbuf);
+		return 0;
+	}
+
+	size_wr = scnprintf(lbuf, size_al, "sjack stats start:\n\n");
+
+	size_wr = nss_stats_fill_common_stats(NSS_SJACK_INTERFACE, lbuf, size_wr, size_al);
+
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nsjack stats end\n\n");
+
+	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
+	kfree(lbuf);
+	kfree(stats_shadow);
+
+	return bytes_read;
+}
+
+/*
+ * nss_sjack_stats_ops
+ */
+NSS_STATS_DECLARE_FILE_OPERATIONS(sjack)
+
+/*
+ * nss_sjack_stats_dentry_create()
+ *	Create SJACK node statistics debug entry.
+ */
+void nss_sjack_stats_dentry_create(void)
+{
+	nss_stats_create_dentry("sjack", &nss_sjack_stats_ops);
+}
+
+/*
+ * nss_sjack_stats_node_sync()
+ *	Update sjack node stats.
+ */
+void nss_sjack_stats_node_sync(struct nss_ctx_instance *nss_ctx, struct nss_sjack_stats_sync_msg *nins)
+{
+	struct nss_top_instance *nss_top = nss_ctx->nss_top;
+	int j;
+
+	/*
+	 * Update SJACK node stats.
+	 */
+	spin_lock_bh(&nss_top->stats_lock);
+	nss_top->stats_node[NSS_SJACK_INTERFACE][NSS_SJACK_STATS_RX_PKTS] += nins->node_stats.rx_packets;
+	nss_top->stats_node[NSS_SJACK_INTERFACE][NSS_SJACK_STATS_RX_BYTES] += nins->node_stats.rx_bytes;
+	nss_top->stats_node[NSS_SJACK_INTERFACE][NSS_SJACK_STATS_TX_PKTS] += nins->node_stats.tx_packets;
+	nss_top->stats_node[NSS_SJACK_INTERFACE][NSS_SJACK_STATS_TX_BYTES] += nins->node_stats.tx_bytes;
+
+	for (j = 0; j < NSS_MAX_NUM_PRI; j++) {
+		nss_top->stats_node[NSS_SJACK_INTERFACE][NSS_SJACK_STATS_RX_QUEUE_0_DROPPED + j] += nins->node_stats.rx_dropped[j];
+	}
+
+	spin_unlock_bh(&nss_top->stats_lock);
+}
diff --git a/nss_sjack_stats.h b/nss_sjack_stats.h
new file mode 100644
index 0000000..cbcd604
--- /dev/null
+++ b/nss_sjack_stats.h
@@ -0,0 +1,45 @@
+/*
+ ******************************************************************************
+ * 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.
+ * ****************************************************************************
+ */
+
+#ifndef __NSS_SJACK_STATS_H
+#define __NSS_SJACK_STATS_H
+
+/*
+ * SJACK statistics
+ */
+enum nss_sjack_stats_types {
+	NSS_SJACK_STATS_RX_PKTS,	/* sjack node RX packets */
+	NSS_SJACK_STATS_RX_BYTES,	/* sjack node RX bytes */
+	NSS_SJACK_STATS_TX_PKTS,	/* sjack node TX packets */
+	NSS_SJACK_STATS_TX_BYTES,	/* sjack node TX bytes */
+	NSS_SJACK_STATS_RX_QUEUE_0_DROPPED,
+					/* sjack node RX Queue 0 dropped */
+	NSS_SJACK_STATS_RX_QUEUE_1_DROPPED,
+					/* sjack node RX Queue 1 dropped */
+	NSS_SJACK_STATS_RX_QUEUE_2_DROPPED,
+					/* sjack node RX Queue 2 dropped */
+	NSS_SJACK_STATS_RX_QUEUE_3_DROPPED,
+					/* sjack node RX Queue 3 dropped */
+	NSS_SJACK_STATS_MAX,
+};
+
+/*
+ * SJACK statistics APIs
+ */
+extern void nss_sjack_stats_node_sync(struct nss_ctx_instance *nss_ctx, struct nss_sjack_stats_sync_msg *nins);
+extern void nss_sjack_stats_dentry_create(void);
+
+#endif /* __NSS_SJACK_STATS_H */
diff --git a/nss_stats.c b/nss_stats.c
index 6d4ea03..5996b54 100644
--- a/nss_stats.c
+++ b/nss_stats.c
@@ -20,157 +20,9 @@
  *
  */
 
-#include "nss_core.h"
-#include "nss_dtls_stats.h"
-#include "nss_gre_tunnel_stats.h"
 #include "nss_tx_rx_common.h"
-
-/*
- * Maximum string length:
- * This should be equal to maximum string size of any stats
- * inclusive of stats value
- */
-#define NSS_STATS_MAX_STR_LENGTH 96
-#define NSS_STATS_WIFILI_MAX	(NSS_STATS_WIFILI_TXRX_MAX + NSS_STATS_WIFILI_TCL_MAX + \
-				NSS_STATS_WIFILI_TX_DESC_FREE_MAX + NSS_STATS_WIFILI_REO_MAX + \
-				NSS_STATS_WIFILI_TX_DESC_MAX + NSS_STATS_WIFILI_EXT_TX_DESC_MAX + \
-				NSS_STATS_WIFILI_RX_DESC_MAX + NSS_STATS_WIFILI_RXDMA_DESC_MAX)
-
-extern int32_t nss_tx_rx_virt_if_copy_stats(int32_t if_num, int i, char *line);
-
-uint64_t stats_shadow_pppoe_except[NSS_PPPOE_NUM_SESSION_PER_INTERFACE][NSS_PPPOE_EXCEPTION_EVENT_MAX];
-
-/*
- * Private data for every file descriptor
- */
-struct nss_stats_data {
-	uint32_t if_num;	/* Interface number for stats */
-	uint32_t index;		/* Index for GRE_REDIR stats */
-	uint32_t edma_id;	/* EDMA port ID or ring ID */
-	struct nss_ctx_instance *nss_ctx;
-				/* The core for project stats */
-};
-
-/*
- * Statistics structures
- */
-
-/*
- * nss_stats_str_ipv4
- *	IPv4 stats strings
- */
-static int8_t *nss_stats_str_ipv4[NSS_STATS_IPV4_MAX] = {
-	"rx_pkts",
-	"rx_bytes",
-	"tx_pkts",
-	"tx_bytes",
-	"create_requests",
-	"create_collisions",
-	"create_invalid_interface",
-	"destroy_requests",
-	"destroy_misses",
-	"hash_hits",
-	"hash_reorders",
-	"flushes",
-	"evictions",
-	"fragmentations",
-	"dropped_by_rule",
-	"mc_create_requests",
-	"mc_update_requests",
-	"mc_create_invalid_interface",
-	"mc_destroy_requests",
-	"mc_destroy_misses",
-	"mc_flushes",
-};
-
-/*
- * nss_stats_str_ipv4_reasm
- *	IPv4 reassembly stats strings
- */
-static int8_t *nss_stats_str_ipv4_reasm[NSS_STATS_IPV4_REASM_MAX] = {
-	"evictions",
-	"alloc_fails",
-	"timeouts",
-};
-
-/*
- * nss_stats_str_ipv6
- *	IPv6 stats strings
- */
-static int8_t *nss_stats_str_ipv6[NSS_STATS_IPV6_MAX] = {
-	"rx_pkts",
-	"rx_bytes",
-	"tx_pkts",
-	"tx_bytes",
-	"create_requests",
-	"create_collisions",
-	"create_invalid_interface",
-	"destroy_requests",
-	"destroy_misses",
-	"hash_hits",
-	"hash_reorders",
-	"flushes",
-	"evictions",
-	"fragmentations",
-	"frag_fails",
-	"dropped_by_rule",
-	"mc_create_requests",
-	"mc_update_requests",
-	"mc_create_invalid_interface",
-	"mc_destroy_requests",
-	"mc_destroy_misses",
-	"mc_flushes",
-};
-
-/*
- * nss_stats_str_ipv6_reasm
- *	IPv6 reassembly stats strings
- */
-static int8_t *nss_stats_str_ipv6_reasm[NSS_STATS_IPV6_REASM_MAX] = {
-	"alloc_fails",
-	"timeouts",
-	"discards",
-};
-
-/*
- * nss_stats_str_n2h
- *	N2H stats strings
- */
-static int8_t *nss_stats_str_n2h[NSS_STATS_N2H_MAX] = {
-	"queue_dropped",
-	"ticks",
-	"worst_ticks",
-	"iterations",
-	"pbuf_ocm_alloc_fails",
-	"pbuf_ocm_free_count",
-	"pbuf_ocm_total_count",
-	"pbuf_default_alloc_fails",
-	"pbuf_default_free_count",
-	"pbuf_default_total_count",
-	"payload_fails",
-	"payload_free_count",
-	"h2n_control_packets",
-	"h2n_control_bytes",
-	"n2h_control_packets",
-	"n2h_control_bytes",
-	"h2n_data_packets",
-	"h2n_data_bytes",
-	"n2h_data_packets",
-	"n2h_data_bytes",
-	"n2h_tot_payloads",
-	"n2h_data_interface_invalid",
-};
-
-/*
- * nss_stats_str_lso_rx
- *	LSO_RX stats strings
- */
-static int8_t *nss_stats_str_lso_rx[NSS_STATS_LSO_RX_MAX] = {
-	"tx_dropped",
-	"dropped",
-	"pbuf_alloc_fail",
-	"pbuf_reference_fail"
-};
+#include "nss_core.h"
+#include "nss_stats.h"
 
 /*
  * nss_stats_str_drv
@@ -206,17 +58,6 @@
 };
 
 /*
- * nss_stats_str_pppoe
- *	PPPoE stats strings
- */
-static int8_t *nss_stats_str_pppoe[NSS_STATS_PPPOE_MAX] = {
-	"create_requests",
-	"create_failures",
-	"destroy_requests",
-	"destroy_misses"
-};
-
-/*
  * nss_stats_str_gmac
  *	GMAC stats strings
  */
@@ -227,70 +68,6 @@
 };
 
 /*
- * nss_stats_str_edma_tx
- */
-static int8_t *nss_stats_str_edma_tx[NSS_STATS_EDMA_TX_MAX] = {
-	"tx_err",
-	"tx_dropped",
-	"desc_cnt"
-};
-
-/*
- * nss_stats_str_edma_rx
- */
-static int8_t *nss_stats_str_edma_rx[NSS_STATS_EDMA_RX_MAX] = {
-	"rx_csum_err",
-	"desc_cnt",
-	"qos_err"
-};
-
-/*
- * nss_stats_str_edma_txcmpl
- */
-static int8_t *nss_stats_str_edma_txcmpl[NSS_STATS_EDMA_TXCMPL_MAX] = {
-	"desc_cnt"
-};
-
-/*
- * nss_stats_str_edma_rxfill
- */
-static int8_t *nss_stats_str_edma_rxfill[NSS_STATS_EDMA_RXFILL_MAX] = {
-	"desc_cnt"
-};
-
-/*
- * nss_stats_str_edma_port_type
- */
-static int8_t *nss_stats_str_edma_port_type[NSS_EDMA_PORT_TYPE_MAX] = {
-	"physical_port",
-	"virtual_port"
-};
-
-/*
- * nss_stats_str_edma_port_ring_map
- */
-static int8_t *nss_stats_str_edma_port_ring_map[NSS_EDMA_PORT_RING_MAP_MAX] = {
-	"rx_ring",
-	"tx_ring"
-};
-
-/*
- * nss_stats_str_edma_err_map
- */
-static int8_t *nss_stats_str_edma_err_map[NSS_EDMA_ERR_STATS_MAX] = {
-	"axi_rd_err",
-	"axi_wr_err",
-	"rx_desc_fifo_full_err",
-	"rx_buf_size_err",
-	"tx_sram_full_err",
-	"tx_cmpl_buf_full_err",
-	"pkt_len_la64k_err",
-	"pkt_len_le33_err",
-	"data_len_err",
-	"alloc_fail_cnt"
-};
-
-/*
  * nss_stats_str_node
  *	Interface stats strings per node
  */
@@ -306,969 +83,30 @@
 };
 
 /*
- * nss_stats_str_eth_rx
- *	eth_rx stats strings
+ * nss_stats_create_dentry()
+ *	Create statistics debug entry for subsystem.
  */
-static int8_t *nss_stats_str_eth_rx[NSS_STATS_ETH_RX_MAX] = {
-	"ticks",
-	"worst_ticks",
-	"iterations"
-};
-
-/*
- * nss_stats_str_if_exception_unknown
- *	Interface stats strings for unknown exceptions
- */
-static int8_t *nss_stats_str_if_exception_eth_rx[NSS_EXCEPTION_EVENT_ETH_RX_MAX] = {
-	"UNKNOWN_L3_PROTOCOL",
-	"ETH_HDR_MISSING",
-	"VLAN_MISSING",
-	"TRUSTSEC_HDR_MISSING"
-};
-
-/*
- * nss_stats_str_if_exception_ipv4
- *	Interface stats strings for ipv4 exceptions
- */
-static int8_t *nss_stats_str_if_exception_ipv4[NSS_EXCEPTION_EVENT_IPV4_MAX] = {
-	"IPV4_ICMP_HEADER_INCOMPLETE",
-	"IPV4_ICMP_UNHANDLED_TYPE",
-	"IPV4_ICMP_IPV4_HEADER_INCOMPLETE",
-	"IPV4_ICMP_IPV4_UDP_HEADER_INCOMPLETE",
-	"IPV4_ICMP_IPV4_TCP_HEADER_INCOMPLETE",
-	"IPV4_ICMP_IPV4_UNKNOWN_PROTOCOL",
-	"IPV4_ICMP_NO_ICME",
-	"IPV4_ICMP_FLUSH_TO_HOST",
-	"IPV4_TCP_HEADER_INCOMPLETE",
-	"IPV4_TCP_NO_ICME",
-	"IPV4_TCP_IP_OPTION",
-	"IPV4_TCP_IP_FRAGMENT",
-	"IPV4_TCP_SMALL_TTL",
-	"IPV4_TCP_NEEDS_FRAGMENTATION",
-	"IPV4_TCP_FLAGS",
-	"IPV4_TCP_SEQ_EXCEEDS_RIGHT_EDGE",
-	"IPV4_TCP_SMALL_DATA_OFFS",
-	"IPV4_TCP_BAD_SACK",
-	"IPV4_TCP_BIG_DATA_OFFS",
-	"IPV4_TCP_SEQ_BEFORE_LEFT_EDGE",
-	"IPV4_TCP_ACK_EXCEEDS_RIGHT_EDGE",
-	"IPV4_TCP_ACK_BEFORE_LEFT_EDGE",
-	"IPV4_UDP_HEADER_INCOMPLETE",
-	"IPV4_UDP_NO_ICME",
-	"IPV4_UDP_IP_OPTION",
-	"IPV4_UDP_IP_FRAGMENT",
-	"IPV4_UDP_SMALL_TTL",
-	"IPV4_UDP_NEEDS_FRAGMENTATION",
-	"IPV4_WRONG_TARGET_MAC",
-	"IPV4_HEADER_INCOMPLETE",
-	"IPV4_BAD_TOTAL_LENGTH",
-	"IPV4_BAD_CHECKSUM",
-	"IPV4_NON_INITIAL_FRAGMENT",
-	"IPV4_DATAGRAM_INCOMPLETE",
-	"IPV4_OPTIONS_INCOMPLETE",
-	"IPV4_UNKNOWN_PROTOCOL",
-	"IPV4_ESP_HEADER_INCOMPLETE",
-	"IPV4_ESP_NO_ICME",
-	"IPV4_ESP_IP_OPTION",
-	"IPV4_ESP_IP_FRAGMENT",
-	"IPV4_ESP_SMALL_TTL",
-	"IPV4_ESP_NEEDS_FRAGMENTATION",
-	"IPV4_INGRESS_VID_MISMATCH",
-	"IPV4_INGRESS_VID_MISSING",
-	"IPV4_6RD_NO_ICME",
-	"IPV4_6RD_IP_OPTION",
-	"IPV4_6RD_IP_FRAGMENT",
-	"IPV4_6RD_NEEDS_FRAGMENTATION",
-	"IPV4_DSCP_MARKING_MISMATCH",
-	"IPV4_VLAN_MARKING_MISMATCH",
-	"IPV4_DEPRECATED",
-	"IPV4_GRE_HEADER_INCOMPLETE",
-	"IPV4_GRE_NO_ICME",
-	"IPV4_GRE_IP_OPTION",
-	"IPV4_GRE_IP_FRAGMENT",
-	"IPV4_GRE_SMALL_TTL",
-	"IPV4_GRE_NEEDS_FRAGMENTATION",
-	"IPV4_PPTP_GRE_SESSION_MATCH_FAIL",
-	"IPV4_PPTP_GRE_INVALID_PROTO",
-	"IPV4_PPTP_GRE_NO_CME",
-	"IPV4_PPTP_GRE_IP_OPTION",
-	"IPV4_PPTP_GRE_IP_FRAGMENT",
-	"IPV4_PPTP_GRE_SMALL_TTL",
-	"IPV4_PPTP_GRE_NEEDS_FRAGMENTATION",
-	"IPV4_DESTROY",
-	"IPV4_FRAG_DF_SET",
-	"IPV4_FRAG_FAIL",
-	"IPV4_ICMP_IPV4_UDPLITE_HEADER_INCOMPLETE",
-	"IPV4_UDPLITE_HEADER_INCOMPLETE",
-	"IPV4_UDPLITE_NO_ICME",
-	"IPV4_UDPLITE_IP_OPTION",
-	"IPV4_UDPLITE_IP_FRAGMENT",
-	"IPV4_UDPLITE_SMALL_TTL",
-	"IPV4_UDPLITE_NEEDS_FRAGMENTATION",
-	"IPV4_MC_UDP_NO_ICME",
-	"IPV4_MC_MEM_ALLOC_FAILURE",
-	"IPV4_MC_UPDATE_FAILURE",
-	"IPV4_MC_PBUF_ALLOC_FAILURE"
-};
-
-/*
- * nss_stats_str_if_exception_ipv6
- *	Interface stats strings for ipv6 exceptions
- */
-static int8_t *nss_stats_str_if_exception_ipv6[NSS_EXCEPTION_EVENT_IPV6_MAX] = {
-	"IPV6_ICMP_HEADER_INCOMPLETE",
-	"IPV6_ICMP_UNHANDLED_TYPE",
-	"IPV6_ICMP_IPV6_HEADER_INCOMPLETE",
-	"IPV6_ICMP_IPV6_UDP_HEADER_INCOMPLETE",
-	"IPV6_ICMP_IPV6_TCP_HEADER_INCOMPLETE",
-	"IPV6_ICMP_IPV6_UNKNOWN_PROTOCOL",
-	"IPV6_ICMP_NO_ICME",
-	"IPV6_ICMP_FLUSH_TO_HOST",
-	"IPV6_TCP_HEADER_INCOMPLETE",
-	"IPV6_TCP_NO_ICME",
-	"IPV6_TCP_SMALL_HOP_LIMIT",
-	"IPV6_TCP_NEEDS_FRAGMENTATION",
-	"IPV6_TCP_FLAGS",
-	"IPV6_TCP_SEQ_EXCEEDS_RIGHT_EDGE",
-	"IPV6_TCP_SMALL_DATA_OFFS",
-	"IPV6_TCP_BAD_SACK",
-	"IPV6_TCP_BIG_DATA_OFFS",
-	"IPV6_TCP_SEQ_BEFORE_LEFT_EDGE",
-	"IPV6_TCP_ACK_EXCEEDS_RIGHT_EDGE",
-	"IPV6_TCP_ACK_BEFORE_LEFT_EDGE",
-	"IPV6_UDP_HEADER_INCOMPLETE",
-	"IPV6_UDP_NO_ICME",
-	"IPV6_UDP_SMALL_HOP_LIMIT",
-	"IPV6_UDP_NEEDS_FRAGMENTATION",
-	"IPV6_WRONG_TARGET_MAC",
-	"IPV6_HEADER_INCOMPLETE",
-	"IPV6_UNKNOWN_PROTOCOL",
-	"IPV6_INGRESS_VID_MISMATCH",
-	"IPV6_INGRESS_VID_MISSING",
-	"IPV6_DSCP_MARKING_MISMATCH",
-	"IPV6_VLAN_MARKING_MISMATCH",
-	"IPV6_DEPRECATED",
-	"IPV6_GRE_NO_ICME",
-	"IPV6_GRE_NEEDS_FRAGMENTATION",
-	"IPV6_GRE_SMALL_HOP_LIMIT",
-	"IPV6_DESTROY",
-	"IPV6_ICMP_IPV6_UDPLITE_HEADER_INCOMPLETE",
-	"IPV6_UDPLITE_HEADER_INCOMPLETE",
-	"IPV6_UDPLITE_NO_ICME",
-	"IPV6_UDPLITE_SMALL_HOP_LIMIT",
-	"IPV6_UDPLITE_NEEDS_FRAGMENTATION",
-	"IPV6_MC_UDP_NO_ICME",
-	"IPV6_MC_MEM_ALLOC_FAILURE",
-	"IPV6_MC_UPDATE_FAILURE",
-	"IPV6_MC_PBUF_ALLOC_FAILURE",
-	"IPV6_ESP_HEADER_INCOMPLETE",
-	"IPV6_ESP_NO_ICME",
-	"IPV6_ESP_IP_FRAGMENT",
-	"IPV6_ESP_SMALL_HOP_LIMIT",
-	"IPV6_ESP_NEEDS_FRAGMENTATION"
-};
-
-/*
- * nss_stats_str_if_exception_pppoe
- *	Interface stats strings for PPPoE exceptions
- */
-static int8_t *nss_stats_str_if_exception_pppoe[NSS_PPPOE_EXCEPTION_EVENT_MAX] = {
-	"PPPOE_WRONG_VERSION_OR_TYPE",
-	"PPPOE_WRONG_CODE",
-	"PPPOE_HEADER_INCOMPLETE",
-	"PPPOE_UNSUPPORTED_PPP_PROTOCOL",
-	"PPPOE_DEPRECATED"
-};
-
-/*
- * nss_stats_str_wifi
- *	Wifi statistics strings
- */
-static int8_t *nss_stats_str_wifi[NSS_STATS_WIFI_MAX] = {
-	"RX_PACKETS",
-	"RX_QUEUE_0_DROPPED",
-	"RX_QUEUE_1_DROPPED",
-	"RX_QUEUE_2_DROPPED",
-	"RX_QUEUE_3_DROPPED",
-	"TX_PACKETS",
-	"TX_DROPPED",
-	"TX_TRANSMIT_COMPLETED",
-	"TX_MGMT_RECEIVED",
-	"TX_MGMT_TRANSMITTED",
-	"TX_MGMT_DROPPED",
-	"TX_MGMT_COMPLETED",
-	"TX_INV_PEER_ENQ_CNT",
-	"RX_INV_PEER_RCV_CNT",
-	"RX_PN_CHECK_FAILED",
-	"RX_PKTS_DELIVERD",
-	"RX_BYTES_DELIVERED",
-	"TX_BYTES_COMPLETED",
-	"RX_DELIVER_UNALIGNED_DROP_CNT",
-	"TIDQ_ENQUEUE_CNT_0",
-	"TIDQ_ENQUEUE_CNT_1",
-	"TIDQ_ENQUEUE_CNT_2",
-	"TIDQ_ENQUEUE_CNT_3",
-	"TIDQ_ENQUEUE_CNT_4",
-	"TIDQ_ENQUEUE_CNT_5",
-	"TIDQ_ENQUEUE_CNT_6",
-	"TIDQ_ENQUEUE_CNT_7",
-	"TIDQ_DEQUEUE_CNT_0",
-	"TIDQ_DEQUEUE_CNT_1",
-	"TIDQ_DEQUEUE_CNT_2",
-	"TIDQ_DEQUEUE_CNT_3",
-	"TIDQ_DEQUEUE_CNT_4",
-	"TIDQ_DEQUEUE_CNT_5",
-	"TIDQ_DEQUEUE_CNT_6",
-	"TIDQ_DEQUEUE_CNT_7",
-	"TIDQ_ENQUEUE_FAIL_CNT_0",
-	"TIDQ_ENQUEUE_FAIL_CNT_1",
-	"TIDQ_ENQUEUE_FAIL_CNT_2",
-	"TIDQ_ENQUEUE_FAIL_CNT_3",
-	"TIDQ_ENQUEUE_FAIL_CNT_4",
-	"TIDQ_ENQUEUE_FAIL_CNT_5",
-	"TIDQ_ENQUEUE_FAIL_CNT_6",
-	"TIDQ_ENQUEUE_FAIL_CNT_7",
-	"TIDQ_TTL_EXPIRE_CNT_0",
-	"TIDQ_TTL_EXPIRE_CNT_1",
-	"TIDQ_TTL_EXPIRE_CNT_2",
-	"TIDQ_TTL_EXPIRE_CNT_3",
-	"TIDQ_TTL_EXPIRE_CNT_4",
-	"TIDQ_TTL_EXPIRE_CNT_5",
-	"TIDQ_TTL_EXPIRE_CNT_6",
-	"TIDQ_TTL_EXPIRE_CNT_7",
-	"TIDQ_DEQUEUE_REQ_CNT_0",
-	"TIDQ_DEQUEUE_REQ_CNT_1",
-	"TIDQ_DEQUEUE_REQ_CNT_2",
-	"TIDQ_DEQUEUE_REQ_CNT_3",
-	"TIDQ_DEQUEUE_REQ_CNT_4",
-	"TIDQ_DEQUEUE_REQ_CNT_5",
-	"TIDQ_DEQUEUE_REQ_CNT_6",
-	"TIDQ_DEQUEUE_REQ_CNT_7",
-	"TOTAL_TIDQ_DEPTH",
-	"RX_HTT_FETCH_CNT",
-	"TOTAL_TIDQ_BYPASS_CNT",
-	"GLOBAL_Q_FULL_CNT",
-	"TIDQ_FULL_CNT",
-};
-
-/*
- * nss_stats_str_wifili
- *	wifili txrx statistics
- */
-static int8_t *nss_stats_str_wifili_txrx[NSS_STATS_WIFILI_TXRX_MAX] = {
-	"WIFILI_RX_MSDU_ERROR",
-	"WIFILI_RX_INV_PEER_RCV",
-	"WIFILI_RX_WDS_SRCPORT_EXCEPTION",
-	"WIFILI_RX_WDS_SRCPORT_EXCEPTION_FAIL",
-	"WIFILI_RX_DELIVERD",
-	"WIFILI_RX_DELIVER_DROPPED",
-	"WIFILI_RX_INTRA_BSS_UCAST",
-	"WIFILI_RX_INTRA_BSS_UCAST_FAIL",
-	"WIFILI_RX_INTRA_BSS_MCAST",
-	"WIFILI_RX_INTRA_BSS_MCAST_FAIL",
-	"WIFILI_RX_SG_RCV_SEND",
-	"WIFILI_RX_SG_RCV_FAIL",
-	"WIFILI_RX_MCAST_ECHO",
-	"WIFILI_TX_ENQUEUE",
-	"WIFILI_TX_ENQUEUE_DROP",
-	"WIFILI_TX_DEQUEUE",
-	"WIFILI_TX_HW_ENQUEUE_FAIL",
-	"WIFILI_TX_SENT_COUNT",
-};
-
-/*
- * nss_stats_str_wifili_tcl
- *	wifili tcl stats
- */
-static int8_t *nss_stats_str_wifili_tcl[NSS_STATS_WIFILI_TCL_MAX] = {
-	"WIFILI_TCL_NO_HW_DESC",
-	"WIFILI_TCL_RING_FULL",
-	"WIFILI_TCL_RING_SENT",
-};
-
-/*
- * nss_stats_str_wifili_tx_comp
- *	wifili tx comp stats
- */
-static int8_t *nss_stats_str_wifili_tx_comp[NSS_STATS_WIFILI_TX_DESC_FREE_MAX] = {
-	"WIFILI_TX_DESC_FREE_INV_BUFSRC",
-	"WIFILI_TX_DESC_FREE_INV_COOKIE",
-	"WIFILI_TX_DESC_FREE_HW_RING_EMPTY",
-	"WIFILI_TX_DESC_FREE_REAPED",
-};
-
-/*
- * nss_stats_str_wifili_reo
- *	wifili tx reo stats
- */
-static int8_t *nss_stats_str_wifili_reo[NSS_STATS_WIFILI_REO_MAX] = {
-	"WIFILI_REO_ERROR",
-	"WIFILI_REO_REAPED",
-	"WIFILI_REO_INV_COOKIE",
-};
-
-/*
- * nss_stats_str_wifili_txsw_pool
- *	wifili tx desc stats
- */
-static int8_t *nss_stats_str_wifili_txsw_pool[NSS_STATS_WIFILI_TX_DESC_MAX] = {
-	"WIFILI_TX_DESC_IN_USE",
-	"WIFILI_TX_DESC_ALLOC_FAIL",
-	"WIFILI_TX_DESC_ALREADY_ALLOCATED",
-	"WIFILI_TX_DESC_INVALID_FREE",
-	"WIFILI_TX_DESC_FREE_SRC_FW",
-	"WIFILI_TX_DESC_FREE_COMPLETION",
-	"WIFILI_TX_DESC_NO_PB",
-};
-
-/*
- * nss_stats_str_wifili_ext_txsw_pool
- *	wifili tx ext desc stats
- */
-static uint8_t *nss_stats_str_wifili_ext_txsw_pool[NSS_STATS_WIFILI_EXT_TX_DESC_MAX] = {
-	"WIFILI_EXT_TX_DESC_IN_USE",
-	"WIFILI_EXT_TX_DESC_ALLOC_FAIL",
-	"WIFILI_EXT_TX_DESC_ALREADY_ALLOCATED",
-	"WIFILI_EXT_TX_DESC_INVALID_FREE",
-};
-
-/*
- * nss_stats_str_wifili_rxdma_pool
- *	wifili rx desc stats
- */
-static int8_t *nss_stats_str_wifili_rxdma_pool[NSS_STATS_WIFILI_RX_DESC_MAX] = {
-	"WIFILI_RX_DESC_NO_PB",
-	"WIFILI_RX_DESC_ALLOC_FAIL",
-	"WIFILI_RX_DESC_IN_USE",
-};
-
-/*
- * nss_stats_str_wifili_rxdma_ring
- *	wifili rx dma ring stats
- */
-static int8_t *nss_stats_str_wifili_rxdma_ring[NSS_STATS_WIFILI_RXDMA_DESC_MAX] = {
-	"WIFILI_RXDMA_HW_DESC_UNAVAILABLE",
-	"WIFILI_RXDMA_BUF_REPLENISHED",
-};
-
-/*
- * nss_stats_str_wifili_wbm
- *	wifili wbm ring stats
- */
-static int8_t *nss_stats_str_wifili_wbm[NSS_STATS_WIFILI_WBM_MAX] = {
-	"WIFILI_WBM_SRC_DMA",
-	"WIFILI_WBM_SRC_DMA_CODE_INV",
-	"WIFILI_WBM_SRC_REO",
-	"WIFILI_WBM_SRC_REO_CODE_NULLQ",
-	"WIFILI_WBM_SRC_REO_CODE_INV",
-	"WIFILI_WBM_SRC_INV",
-};
-
-/*
- * nss_stats_str_portid
- *	PortID statistics strings
- */
-static int8_t *nss_stats_str_portid[NSS_STATS_PORTID_MAX] = {
-	"RX_INVALID_HEADER",
-};
-
-/*
- * nss_stats_str_dtls_session_stats
- *	DTLS statistics strings for nss session stats
- */
-static int8_t *nss_stats_str_dtls_session_debug_stats[NSS_STATS_DTLS_SESSION_MAX] = {
-	"RX_PKTS",
-	"TX_PKTS",
-	"RX_QUEUE_0_DROPPED",
-	"RX_QUEUE_1_DROPPED",
-	"RX_QUEUE_2_DROPPED",
-	"RX_QUEUE_3_DROPPED",
-	"RX_AUTH_DONE",
-	"TX_AUTH_DONE",
-	"RX_CIPHER_DONE",
-	"TX_CIPHER_DONE",
-	"RX_CBUF_ALLOC_FAIL",
-	"TX_CBUF_ALLOC_FAIL",
-	"TX_CENQUEUE_FAIL",
-	"RX_CENQUEUE_FAIL",
-	"TX_DROPPED_HROOM",
-	"TX_DROPPED_TROOM",
-	"TX_FORWARD_ENQUEUE_FAIL",
-	"RX_FORWARD_ENQUEUE_FAIL",
-	"RX_INVALID_VERSION",
-	"RX_INVALID_EPOCH",
-	"RX_MALFORMED",
-	"RX_CIPHER_FAIL",
-	"RX_AUTH_FAIL",
-	"RX_CAPWAP_CLASSIFY_FAIL",
-	"RX_SINGLE_REC_DGRAM",
-	"RX_MULTI_REC_DGRAM",
-	"RX_REPLAY_FAIL",
-	"RX_REPLAY_DUPLICATE",
-	"RX_REPLAY_OUT_OF_WINDOW",
-	"OUTFLOW_QUEUE_FULL",
-	"DECAP_QUEUE_FULL",
-	"PBUF_ALLOC_FAIL",
-	"PBUF_COPY_FAIL",
-	"EPOCH",
-	"TX_SEQ_HIGH",
-	"TX_SEQ_LOW",
-};
-
-/*
- * nss_stats_str_gre_tunnel_session_stats
- *	GRE Tunnel statistics strings for nss session stats
- */
-static int8_t *nss_stats_str_gre_tunnel_session_debug_stats[NSS_STATS_GRE_TUNNEL_SESSION_MAX] = {
-	"RX_PKTS",
-	"TX_PKTS",
-	"RX_QUEUE_0_DROPPED",
-	"RX_QUEUE_1_DROPPED",
-	"RX_QUEUE_2_DROPPED",
-	"RX_QUEUE_3_DROPPED",
-	"RX_MALFORMED",
-	"RX_INVALID_PROT",
-	"DECAP_QUEUE_FULL",
-	"RX_SINGLE_REC_DGRAM",
-	"RX_INVALID_REC_DGRAM",
-	"BUFFER_ALLOC_FAIL",
-	"BUFFER_COPY_FAIL",
-	"OUTFLOW_QUEUE_FULL",
-	"TX_DROPPED_HROOM",
-	"RX_CBUFFER_ALLOC_FAIL",
-	"RX_CENQUEUE_FAIL",
-	"RX_DECRYPT_DONE",
-	"RX_FORWARD_ENQUEUE_FAIL",
-	"TX_CBUFFER_ALLOC_FAIL",
-	"TX_CENQUEUE_FAIL",
-	"TX_DROPPED_TROOM",
-	"TX_FORWARD_ENQUEUE_FAIL",
-	"TX_CIPHER_DONE",
-	"CRYPTO_NOSUPP",
-	"RX_DROPPED_MH_VERSION",
-};
-
-/*
- * nss_stats_str_l2tpv2_session_stats
- *	l2tpv2 statistics strings for nss session stats
- */
-static int8_t *nss_stats_str_l2tpv2_session_debug_stats[NSS_STATS_L2TPV2_SESSION_MAX] = {
-	"RX_PPP_LCP_PKTS",
-	"RX_EXP_PKTS",
-	"ENCAP_PBUF_ALLOC_FAIL",
-	"DECAP_PBUF_ALLOC_FAIL"
-};
-
-/*
- * nss_stats_str_map_t_instance_stats
- *	map_t statistics strings for nss session stats
- */
-static int8_t *nss_stats_str_map_t_instance_debug_stats[NSS_STATS_MAP_T_MAX] = {
-	"MAP_T_V4_TO_V6_PBUF_EXCEPTION_PKTS",
-	"MAP_T_V4_TO_V6_PBUF_NO_MATCHING_RULE",
-	"MAP_T_V4_TO_V6_PBUF_NOT_TCP_OR_UDP",
-	"MAP_T_V4_TO_V6_RULE_ERR_LOCAL_PSID",
-	"MAP_T_V4_TO_V6_RULE_ERR_LOCAL_IPV6",
-	"MAP_T_V4_TO_V6_RULE_ERR_REMOTE_PSID",
-	"MAP_T_V4_TO_V6_RULE_ERR_REMOTE_EA_BITS",
-	"MAP_T_V4_TO_V6_RULE_ERR_REMOTE_IPV6",
-	"MAP_T_V6_TO_V4_PBUF_EXCEPTION_PKTS",
-	"MAP_T_V6_TO_V4_PBUF_NO_MATCHING_RULE",
-	"MAP_T_V6_TO_V4_PBUF_NOT_TCP_OR_UDP",
-	"MAP_T_V6_TO_V4_RULE_ERR_LOCAL_IPV4",
-	"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
- */
-static int8_t *nss_stats_str_ppe_conn[NSS_STATS_PPE_CONN_MAX] = {
-	"v4 routed flows",
-	"v4 bridge flows",
-	"v4 conn create req",
-	"v4 conn create fail",
-	"v4 conn destroy req",
-	"v4 conn destroy fail",
-	"v4 conn MC create req",
-	"v4 conn MC create fail",
-	"v4 conn MC update req",
-	"v4 conn MC update fail",
-	"v4 conn MC delete req",
-	"v4 conn MC delete fail",
-
-	"v6 routed flows",
-	"v6 bridge flows",
-	"v6 conn create req",
-	"v6 conn create fail",
-	"v6 conn destroy req",
-	"v6 conn destroy fail",
-	"v6 conn MC create req",
-	"v6 conn MC create fail",
-	"v6 conn MC update req",
-	"v6 conn MC update fail",
-	"v6 conn MC delete req",
-	"v6 conn MC delete fail",
-
-	"conn fail - vp full",
-	"conn fail - nexthop full",
-	"conn fail - flow full",
-	"conn fail - host full",
-	"conn fail - pub-ip full",
-	"conn fail - port not setup",
-	"conn fail - rw fifo full",
-	"conn fail - flow cmd failure",
-	"conn fail - unknown proto",
-	"conn fail - ppe not responding",
-	"conn fail - CE opaque invalid",
-	"conn fail - fqg full"
-};
-
-/*
- * nss_stats_str_ppe_l3
- *	PPE statistics strings for nss debug stats
- */
-static int8_t *nss_stats_str_ppe_l3[NSS_STATS_PPE_L3_MAX] = {
-	"PPE L3 dbg reg 0",
-	"PPE L3 dbg reg 1",
-	"PPE L3 dbg reg 2",
-	"PPE L3 dbg reg 3",
-	"PPE L3 dbg reg 4",
-	"PPE L3 dbg reg port",
-};
-
-/*
- * nss_stats_str_ppe_code
- *	PPE statistics strings for nss debug stats
- */
-static int8_t *nss_stats_str_ppe_code[NSS_STATS_PPE_CODE_MAX] = {
-	"PPE CPU_CODE",
-	"PPE DROP_CODE",
-};
-
-/*
- * nss_stats_str_ppe_dc
- *	PPE statistics strings for drop code
- */
-static int8_t *nss_stats_str_ppe_dc[NSS_STATS_PPE_DROP_CODE_MAX] = {
-	"PPE_DROP_CODE_NONE",
-	"PPE_DROP_CODE_EXP_UNKNOWN_L2_PORT",
-	"PPE_DROP_CODE_EXP_PPPOE_WRONG_VER_TYPE",
-	"PPE_DROP_CODE_EXP_PPPOE_WRONG_CODE",
-	"PPE_DROP_CODE_EXP_PPPOE_UNSUPPORTED_PPP_PROT",
-	"PPE_DROP_CODE_EXP_IPV4_WRONG_VER",
-	"PPE_DROP_CODE_EXP_IPV4_SMALL_IHL",
-	"PPE_DROP_CODE_EXP_IPV4_WITH_OPTION",
-	"PPE_DROP_CODE_EXP_IPV4_HDR_INCOMPLETE",
-	"PPE_DROP_CODE_EXP_IPV4_BAD_TOTAL_LEN",
-	"PPE_DROP_CODE_EXP_IPV4_DATA_INCOMPLETE",
-	"PPE_DROP_CODE_EXP_IPV4_FRAG",
-	"PPE_DROP_CODE_EXP_IPV4_PING_OF_DEATH",
-	"PPE_DROP_CODE_EXP_IPV4_SNALL_TTL",
-	"PPE_DROP_CODE_EXP_IPV4_UNK_IP_PROT",
-	"PPE_DROP_CODE_EXP_IPV4_CHECKSUM_ERR",
-	"PPE_DROP_CODE_EXP_IPV4_INV_SIP",
-	"PPE_DROP_CODE_EXP_IPV4_INV_DIP",
-	"PPE_DROP_CODE_EXP_IPV4_LAND_ATTACK",
-	"PPE_DROP_CODE_EXP_IPV4_AH_HDR_INCOMPLETE",
-	"PPE_DROP_CODE_EXP_IPV4_AH_HDR_CROSS_BORDER",
-	"PPE_DROP_CODE_EXP_IPV4_ESP_HDR_INCOMPLETE",
-	"PPE_DROP_CODE_EXP_IPV6_WRONG_VER",
-	"PPE_DROP_CODE_EXP_IPV6_HDR_INCOMPLETE",
-	"PPE_DROP_CODE_EXP_IPV6_BAD_PAYLOAD_LEN",
-	"PPE_DROP_CODE_EXP_IPV6_DATA_INCOMPLETE",
-	"PPE_DROP_CODE_EXP_IPV6_WITH_EXT_HDR",
-	"PPE_DROP_CODE_EXP_IPV6_SMALL_HOP_LIMIT",
-	"PPE_DROP_CODE_EXP_IPV6_INV_SIP",
-	"PPE_DROP_CODE_EXP_IPV6_INV_DIP",
-	"PPE_DROP_CODE_EXP_IPV6_LAND_ATTACK",
-	"PPE_DROP_CODE_EXP_IPV6_FRAG",
-	"PPE_DROP_CODE_EXP_IPV6_PING_OF_DEATH",
-	"PPE_DROP_CODE_EXP_IPV6_WITH_MORE_EXT_HDR",
-	"PPE_DROP_CODE_EXP_IPV6_UNK_LAST_NEXT_HDR",
-	"PPE_DROP_CODE_EXP_IPV6_MOBILITY_HDR_INCOMPLETE",
-	"PPE_DROP_CODE_EXP_IPV6_MOBILITY_HDR_CROSS_BORDER",
-	"PPE_DROP_CODE_EXP_IPV6_AH_HDR_INCOMPLETE",
-	"PPE_DROP_CODE_EXP_IPV6_AH_HDR_CROSS_BORDER",
-	"PPE_DROP_CODE_EXP_IPV6_ESP_HDR_INCOMPLETE",
-	"PPE_DROP_CODE_EXP_IPV6_ESP_HDR_CROSS_BORDER",
-	"PPE_DROP_CODE_EXP_IPV6_OTHER_EXT_HDR_INCOMPLETE",
-	"PPE_DROP_CODE_EXP_IPV6_OTHER_EXT_HDR_CROSS_BORDER",
-	"PPE_DROP_CODE_EXP_TCP_HDR_INCOMPLETE",
-	"PPE_DROP_CODE_EXP_TCP_HDR_CROSS_BORDER",
-	"PPE_DROP_CODE_EXP_TCP_SMAE_SP_DP",
-	"PPE_DROP_CODE_EXP_TCP_SMALL_DATA_OFFSET",
-	"PPE_DROP_CODE_EXP_TCP_FLAGS_0",
-	"PPE_DROP_CODE_EXP_TCP_FLAGS_1",
-	"PPE_DROP_CODE_EXP_TCP_FLAGS_2",
-	"PPE_DROP_CODE_EXP_TCP_FLAGS_3",
-	"PPE_DROP_CODE_EXP_TCP_FLAGS_4",
-	"PPE_DROP_CODE_EXP_TCP_FLAGS_5",
-	"PPE_DROP_CODE_EXP_TCP_FLAGS_6",
-	"PPE_DROP_CODE_EXP_TCP_FLAGS_7",
-	"PPE_DROP_CODE_EXP_TCP_CHECKSUM_ERR",
-	"PPE_DROP_CODE_EXP_UDP_HDR_INCOMPLETE",
-	"PPE_DROP_CODE_EXP_UDP_HDR_CROSS_BORDER",
-	"PPE_DROP_CODE_EXP_UDP_SMAE_SP_DP",
-	"PPE_DROP_CODE_EXP_UDP_BAD_LEN",
-	"PPE_DROP_CODE_EXP_UDP_DATA_INCOMPLETE",
-	"PPE_DROP_CODE_EXP_UDP_CHECKSUM_ERR",
-	"PPE_DROP_CODE_EXP_UDP_LITE_HDR_INCOMPLETE",
-	"PPE_DROP_CODE_EXP_UDP_LITE_HDR_CROSS_BORDER",
-	"PPE_DROP_CODE_EXP_UDP_LITE_SMAE_SP_DP",
-	"PPE_DROP_CODE_EXP_UDP_LITE_CSM_COV_1_TO_7",
-	"PPE_DROP_CODE_EXP_UDP_LITE_CSM_COV_TOO_LONG",
-	"PPE_DROP_CODE_EXP_UDP_LITE_CSM_COV_CROSS_BORDER",
-	"PPE_DROP_CODE_EXP_UDP_LITE_CHECKSUM_ERR",
-	"PPE_DROP_CODE_L3_MC_BRIDGE_ACTION",
-	"PPE_DROP_CODE_L3_NO_ROUTE_PREHEAD_NAT_ACTION",
-	"PPE_DROP_CODE_L3_NO_ROUTE_PREHEAD_NAT_ERROR",
-	"PPE_DROP_CODE_L3_ROUTE_ACTION",
-	"PPE_DROP_CODE_L3_NO_ROUTE_ACTION",
-	"PPE_DROP_CODE_L3_NO_ROUTE_NH_INVALID_ACTION",
-	"PPE_DROP_CODE_L3_NO_ROUTE_PREHEAD_ACTION",
-	"PPE_DROP_CODE_L3_BRIDGE_ACTION",
-	"PPE_DROP_CODE_L3_FLOW_ACTION",
-	"PPE_DROP_CODE_L3_FLOW_MISS_ACTION",
-	"PPE_DROP_CODE_L2_EXP_MRU_FAIL",
-	"PPE_DROP_CODE_L2_EXP_MTU_FAIL",
-	"PPE_DROP_CODE_L3_EXP_IP_PREFIX_BC",
-	"PPE_DROP_CODE_L3_EXP_MTU_FAIL",
-	"PPE_DROP_CODE_L3_EXP_MRU_FAIL",
-	"PPE_DROP_CODE_L3_EXP_ICMP_RDT",
-	"PPE_DROP_CODE_FAKE_MAC_HEADER_ERR",
-	"PPE_DROP_CODE_L3_EXP_IP_RT_TTL_ZERO",
-	"PPE_DROP_CODE_L3_FLOW_SERVICE_CODE_LOOP",
-	"PPE_DROP_CODE_L3_FLOW_DE_ACCELEARTE",
-	"PPE_DROP_CODE_L3_EXP_FLOW_SRC_IF_CHK_FAIL",
-	"PPE_DROP_CODE_L3_FLOW_SYNC_TOGGLE_MISMATCH",
-	"PPE_DROP_CODE_L3_EXP_MTU_DF_FAIL",
-	"PPE_DROP_CODE_L3_EXP_PPPOE_MULTICAST",
-	"PPE_DROP_CODE_IPV4_SG_UNKNOWN",
-	"PPE_DROP_CODE_IPV6_SG_UNKNOWN",
-	"PPE_DROP_CODE_ARP_SG_UNKNOWN",
-	"PPE_DROP_CODE_ND_SG_UNKNOWN",
-	"PPE_DROP_CODE_IPV4_SG_VIO",
-	"PPE_DROP_CODE_IPV6_SG_VIO",
-	"PPE_DROP_CODE_ARP_SG_VIO",
-	"PPE_DROP_CODE_ND_SG_VIO",
-	"PPE_DROP_CODE_L2_NEW_MAC_ADDRESS",
-	"PPE_DROP_CODE_L2_HASH_COLLISION",
-	"PPE_DROP_CODE_L2_STATION_MOVE",
-	"PPE_DROP_CODE_L2_LEARN_LIMIT",
-	"PPE_DROP_CODE_L2_SA_LOOKUP_ACTION",
-	"PPE_DROP_CODE_L2_DA_LOOKUP_ACTION",
-	"PPE_DROP_CODE_APP_CTRL_ACTION",
-	"PPE_DROP_CODE_IN_VLAN_FILTER_ACTION",
-	"PPE_DROP_CODE_IN_VLAN_XLT_MISS",
-	"PPE_DROP_CODE_EG_VLAN_FILTER_DROP",
-	"PPE_DROP_CODE_ACL_PRE_ACTION",
-	"PPE_DROP_CODE_ACL_POST_ACTION",
-	"PPE_DROP_CODE_MC_BC_SA",
-	"PPE_DROP_CODE_NO_DESTINATION",
-	"PPE_DROP_CODE_STG_IN_FILTER",
-	"PPE_DROP_CODE_STG_EG_FILTER",
-	"PPE_DROP_CODE_SOURCE_FILTER_FAIL",
-	"PPE_DROP_CODE_TRUNK_SEL_FAIL",
-	"PPE_DROP_CODE_TX_EN_FAIL",
-	"PPE_DROP_CODE_VLAN_TAG_FMT",
-	"PPE_DROP_CODE_CRC_ERR",
-	"PPE_DROP_CODE_PAUSE_FRAME",
-	"PPE_DROP_CODE_PROMISC",
-	"PPE_DROP_CODE_ISOLATION",
-	"PPE_DROP_CODE_MGMT_APP",
-	"PPE_DROP_CODE_FAKE_L2_PROT_ERR",
-	"PPE_DROP_CODE_POLICER",
-};
-
-/*
- * nss_stats_str_ppe_cc
- *	PPE statistics strings for cpu code
- */
-static int8_t *nss_stats_str_ppe_cc[NSS_STATS_PPE_CPU_CODE_MAX] = {
-	"PPE_CPU_CODE_FORWARDING",
-	"PPE_CPU_CODE_EXP_UNKNOWN_L2_PROT",
-	"PPE_CPU_CODE_EXP_PPPOE_WRONG_VER_TYPE",
-	"PPE_CPU_CODE_EXP_WRONG_CODE",
-	"PPE_CPU_CODE_EXP_PPPOE_UNSUPPORTED_PPP_PROT",
-	"PPE_CPU_CODE_EXP_WRONG_VER",
-	"PPE_CPU_CODE_EXP_SMALL_IHL",
-	"PPE_CPU_CODE_EXP_WITH_OPTION",
-	"PPE_CPU_CODE_EXP_HDR_INCOMPLETE",
-	"PPE_CPU_CODE_EXP_IPV4_BAD_TOTAL_LEN",
-	"PPE_CPU_CODE_EXP_DATA_INCOMPLETE",
-	"PPE_CPU_CODE_IPV4_FRAG",
-	"PPE_CPU_CODE_EXP_IPV4_PING_OF_DEATH",
-	"PPE_CPU_CODE_EXP_SNALL_TTL",
-	"PPE_CPU_CODE_EXP_IPV4_UNK_IP_PROT",
-	"PPE_CPU_CODE_EXP_CHECKSUM_ERR",
-	"PPE_CPU_CODE_EXP_INV_SIP",
-	"PPE_CPU_CODE_EXP_INV_DIP",
-	"PPE_CPU_CODE_EXP_LAND_ATTACK",
-	"PPE_CPU_CODE_EXP_IPV4_AH_HDR_INCOMPLETE",
-	"PPE_CPU_CODE_EXP_IPV4_AH_CROSS_BORDER",
-	"PPE_CPU_CODE_EXP_IPV4_ESP_HDR_INCOMPLETE",
-	"PPE_CPU_CODE_EXP_WRONG_VER",
-	"PPE_CPU_CODE_EXP_HDR_INCOMPLETE",
-	"PPE_CPU_CODE_EXP_IPV6_BAD_PAYLOAD_LEN",
-	"PPE_CPU_CODE_EXP_DATA_INCOMPLETE",
-	"PPE_CPU_CODE_EXP_IPV6_WITH_EXT_HDR",
-	"PPE_CPU_CODE_EXP_IPV6_SMALL_HOP_LIMIT",
-	"PPE_CPU_CODE_EXP_INV_SIP",
-	"PPE_CPU_CODE_EXP_INV_DIP",
-	"PPE_CPU_CODE_EXP_LAND_ATTACK",
-	"PPE_CPU_CODE_IPV6_FRAG",
-	"PPE_CPU_CODE_EXP_IPV6_PING_OF_DEATH",
-	"PPE_CPU_CODE_EXP_IPV6_WITH_EXT_HDR",
-	"PPE_CPU_CODE_EXP_IPV6_UNK_NEXT_HDR",
-	"PPE_CPU_CODE_EXP_IPV6_MOBILITY_HDR_INCOMPLETE",
-	"PPE_CPU_CODE_EXP_IPV6_MOBILITY_CROSS_BORDER",
-	"PPE_CPU_CODE_EXP_IPV6_AH_HDR_INCOMPLETE",
-	"PPE_CPU_CODE_EXP_IPV6_AH_CROSS_BORDER",
-	"PPE_CPU_CODE_EXP_IPV6_ESP_HDR_INCOMPLETE",
-	"PPE_CPU_CODE_EXP_IPV6_ESP_CROSS_BORDER",
-	"PPE_CPU_CODE_EXP_IPV6_OTHER_HDR_INCOMPLETE",
-	"PPE_CPU_CODE_EXP_IPV6_OTHER_EXT_CROSS_BORDER",
-	"PPE_CPU_CODE_EXP_HDR_INCOMPLETE",
-	"PPE_CPU_CODE_EXP_TCP_HDR_CROSS_BORDER",
-	"PPE_CPU_CODE_EXP_TCP_SMAE_SP_DP",
-	"PPE_CPU_CODE_EXP_TCP_SMALL_DATA_OFFSET",
-	"PPE_CPU_CODE_EXP_FLAGS_0",
-	"PPE_CPU_CODE_EXP_FLAGS_1",
-	"PPE_CPU_CODE_EXP_FLAGS_2",
-	"PPE_CPU_CODE_EXP_FLAGS_3",
-	"PPE_CPU_CODE_EXP_FLAGS_4",
-	"PPE_CPU_CODE_EXP_FLAGS_5",
-	"PPE_CPU_CODE_EXP_FLAGS_6",
-	"PPE_CPU_CODE_EXP_FLAGS_7",
-	"PPE_CPU_CODE_EXP_CHECKSUM_ERR",
-	"PPE_CPU_CODE_EXP_HDR_INCOMPLETE",
-	"PPE_CPU_CODE_EXP_UDP_HDR_CROSS_BORDER",
-	"PPE_CPU_CODE_EXP_UDP_SMAE_SP_DP",
-	"PPE_CPU_CODE_EXP_BAD_LEN",
-	"PPE_CPU_CODE_EXP_DATA_INCOMPLETE",
-	"PPE_CPU_CODE_EXP_CHECKSUM_ERR",
-	"PPE_CPU_CODE_EXP_UDP_LITE_HDR_INCOMPLETE",
-	"PPE_CPU_CODE_EXP_UDP_LITE_CROSS_BORDER",
-	"PPE_CPU_CODE_EXP_UDP_LITE_SP_DP",
-	"PPE_CPU_CODE_EXP_UDP_LITE_CSM_COV_TO_7",
-	"PPE_CPU_CODE_EXP_UDP_LITE_CSM_TOO_LONG",
-	"PPE_CPU_CODE_EXP_UDP_LITE_CSM_CROSS_BORDER",
-	"PPE_CPU_CODE_EXP_UDP_LITE_CHECKSUM_ERR",
-	"PPE_CPU_CODE_EXP_FAKE_L2_PROT_ERR",
-	"PPE_CPU_CODE_EXP_FAKE_MAC_HEADER_ERR",
-	"PPE_CPU_CODE_BITMAP_MAX",
-	"PPE_CPU_CODE_L2_MRU_FAIL",
-	"PPE_CPU_CODE_L2_MTU_FAIL",
-	"PPE_CPU_CODE_L3_EXP_IP_PREFIX_BC",
-	"PPE_CPU_CODE_L3_MTU_FAIL",
-	"PPE_CPU_CODE_L3_MRU_FAIL",
-	"PPE_CPU_CODE_L3_ICMP_RDT",
-	"PPE_CPU_CODE_L3_EXP_IP_RT_TO_ME",
-	"PPE_CPU_CODE_L3_EXP_IP_TTL_ZERO",
-	"PPE_CPU_CODE_L3_FLOW_SERVICE_CODE_LOOP",
-	"PPE_CPU_CODE_L3_DE_ACCELERATE",
-	"PPE_CPU_CODE_L3_EXP_FLOW_SRC_CHK_FAIL",
-	"PPE_CPU_CODE_L3_FLOW_SYNC_TOGGLE_MISMATCH",
-	"PPE_CPU_CODE_L3_EXP_MTU_DF_FAIL",
-	"PPE_CPU_CODE_L3_PPPOE_MULTICAST",
-	"PPE_CPU_CODE_MGMT_OFFSET",
-	"PPE_CPU_CODE_MGMT_EAPOL",
-	"PPE_CPU_CODE_PPPOE_DIS",
-	"PPE_CPU_CODE_MGMT_IGMP",
-	"PPE_CPU_CODE_ARP_REQ",
-	"PPE_CPU_CODE_ARP_REP",
-	"PPE_CPU_CODE_MGMT_DHCPv4",
-	"PPE_CPU_CODE_MGMT_MLD",
-	"PPE_CPU_CODE_MGMT_NS",
-	"PPE_CPU_CODE_MGMT_NA",
-	"PPE_CPU_CODE_MGMT_DHCPv6",
-	"PPE_CPU_CODE_PTP_OFFSET",
-	"PPE_CPU_CODE_PTP_SYNC",
-	"PPE_CPU_CODE_FOLLOW_UP",
-	"PPE_CPU_CODE_DELAY_REQ",
-	"PPE_CPU_CODE_DELAY_RESP",
-	"PPE_CPU_CODE_PDELAY_REQ",
-	"PPE_CPU_CODE_PDELAY_RESP",
-	"PPE_CPU_CODE_PTP_PDELAY_RESP_FOLLOW_UP",
-	"PPE_CPU_CODE_PTP_ANNOUNCE",
-	"PPE_CPU_CODE_PTP_MANAGEMENT",
-	"PPE_CPU_CODE_PTP_SIGNALING",
-	"PPE_CPU_CODE_PTP_RSV_MSG",
-	"PPE_CPU_CODE_SG_UNKNOWN",
-	"PPE_CPU_CODE_SG_UNKNOWN",
-	"PPE_CPU_CODE_SG_UNKNOWN",
-	"PPE_CPU_CODE_SG_UNKNOWN",
-	"PPE_CPU_CODE_SG_VIO",
-	"PPE_CPU_CODE_SG_VIO",
-	"PPE_CPU_CODE_SG_VIO",
-	"PPE_CPU_CODE_SG_VIO",
-	"PPE_CPU_CODE_L3_ROUTING_IP_TO_ME",
-	"PPE_CPU_CODE_L3_SNAT_ACTION",
-	"PPE_CPU_CODE_L3_DNAT_ACTION",
-	"PPE_CPU_CODE_L3_RT_ACTION",
-	"PPE_CPU_CODE_L3_BR_ACTION",
-	"PPE_CPU_CODE_L3_BRIDGE_ACTION",
-	"PPE_CPU_CODE_L3_ROUTE_PREHEAD_RT_ACTION",
-	"PPE_CPU_CODE_L3_ROUTE_PREHEAD_SNAPT_ACTION",
-	"PPE_CPU_CODE_L3_ROUTE_PREHEAD_DNAPT_ACTION",
-	"PPE_CPU_CODE_L3_ROUTE_PREHEAD_SNAT_ACTION",
-	"PPE_CPU_CODE_L3_ROUTE_PREHEAD_DNAT_ACTION",
-	"PPE_CPU_CODE_L3_NO_ROUTE_NAT_ACTION",
-	"PPE_CPU_CODE_L3_NO_ROUTE_NAT_ERROR",
-	"PPE_CPU_CODE_ROUTE_ACTION",
-	"PPE_CPU_CODE_L3_ROUTE_ACTION",
-	"PPE_CPU_CODE_L3_NO_ROUTE_INVALID_ACTION",
-	"PPE_CPU_CODE_L3_NO_ROUTE_PREHEAD_ACTION",
-	"PPE_CPU_CODE_BRIDGE_ACTION",
-	"PPE_CPU_CODE_FLOW_ACTION",
-	"PPE_CPU_CODE_L3_MISS_ACTION",
-	"PPE_CPU_CODE_L2_MAC_ADDRESS",
-	"PPE_CPU_CODE_HASH_COLLISION",
-	"PPE_CPU_CODE_STATION_MOVE",
-	"PPE_CPU_CODE_LEARN_LIMIT",
-	"PPE_CPU_CODE_L2_LOOKUP_ACTION",
-	"PPE_CPU_CODE_L2_LOOKUP_ACTION",
-	"PPE_CPU_CODE_CTRL_ACTION",
-	"PPE_CPU_CODE_IN_FILTER_ACTION",
-	"PPE_CPU_CODE_IN_XLT_MISS",
-	"PPE_CPU_CODE_EG_FILTER_DROP",
-	"PPE_CPU_CODE_PRE_ACTION",
-	"PPE_CPU_CODE_POST_ACTION",
-	"PPE_CPU_CODE_CODE_ACTION",
-};
-
-/*
- * nss_stats_str_ppt_session_stats
- *	PPTP statistics strings for nss session stats
- */
-static int8_t *nss_stats_str_pptp_session_debug_stats[NSS_STATS_PPTP_SESSION_MAX] = {
-	"ENCAP_RX_PACKETS",
-	"ENCAP_RX_BYTES",
-	"ENCAP_TX_PACKETS",
-	"ENCAP_TX_BYTES",
-	"ENCAP_RX_QUEUE_0_DROP",
-	"ENCAP_RX_QUEUE_1_DROP",
-	"ENCAP_RX_QUEUE_2_DROP",
-	"ENCAP_RX_QUEUE_3_DROP",
-	"DECAP_RX_PACKETS",
-	"DECAP_RX_BYTES",
-	"DECAP_TX_PACKETS",
-	"DECAP_TX_BYTES",
-	"DECAP_RX_QUEUE_0_DROP",
-	"DECAP_RX_QUEUE_1_DROP",
-	"DECAP_RX_QUEUE_2_DROP",
-	"DECAP_RX_QUEUE_3_DROP",
-	"ENCAP_HEADROOM_ERR",
-	"ENCAP_SMALL_SIZE",
-	"ENCAP_PNODE_ENQUEUE_FAIL",
-	"DECAP_NO_SEQ_NOR_ACK",
-	"DECAP_INVAL_GRE_FLAGS",
-	"DECAP_INVAL_GRE_PROTO",
-	"DECAP_WRONG_SEQ",
-	"DECAP_INVAL_PPP_HDR",
-	"DECAP_PPP_LCP",
-	"DECAP_UNSUPPORTED_PPP_PROTO",
-	"DECAP_PNODE_ENQUEUE_FAIL",
-};
-
-/*
- * nss_stats_str_trustsec_tx
- *	Trustsec TX stats strings
- */
-static int8_t *nss_stats_str_trustsec_tx[NSS_STATS_TRUSTSEC_TX_MAX] = {
-	"INVALID_SRC",
-	"UNCONFIGURED_SRC",
-	"HEADROOM_NOT_ENOUGH",
-};
-
-/*
- * nss_stats_ipv4_read()
- *	Read IPV4 stats
- */
-static ssize_t nss_stats_ipv4_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
+void nss_stats_create_dentry(char *name, const struct file_operations *ops)
 {
-	int32_t i;
-	/*
-	 * max output lines = #stats + start tag line + end tag line + three blank lines
-	 */
-	uint32_t max_output_lines = (NSS_STATS_NODE_MAX + 2) + (NSS_STATS_IPV4_MAX + 3) + (NSS_EXCEPTION_EVENT_IPV4_MAX + 3) + 5;
-	size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
-	size_t size_wr = 0;
-	ssize_t bytes_read = 0;
-	uint64_t *stats_shadow;
-
-	char *lbuf = kzalloc(size_al, GFP_KERNEL);
-	if (unlikely(lbuf == NULL)) {
-		nss_warning("Could not allocate memory for local statistics buffer");
-		return 0;
+	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);
 	}
+}
 
-	/*
-	 * Note: The assumption here is that exception event count is larger than other statistics count for IPv4
-	 */
-	stats_shadow = kzalloc(NSS_EXCEPTION_EVENT_IPV4_MAX * 8, GFP_KERNEL);
-	if (unlikely(stats_shadow == NULL)) {
-		nss_warning("Could not allocate memory for local shadow buffer");
-		kfree(lbuf);
-		return 0;
-	}
+/*
+ * nss_stats_fill_common_stats()
+ *	Fill common node statistics.
+ */
+size_t nss_stats_fill_common_stats(uint32_t if_num, char *lbuf, size_t size_wr, size_t size_al)
+{
+	uint64_t stats_shadow[NSS_STATS_NODE_MAX];
+	int i;
 
-	size_wr = scnprintf(lbuf, size_al, "ipv4 stats start:\n\n");
-
-	/*
-	 * Common node stats
-	 */
 	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "common node stats:\n\n");
 	spin_lock_bh(&nss_top_main.stats_lock);
 	for (i = 0; (i < NSS_STATS_NODE_MAX); i++) {
-		stats_shadow[i] = nss_top_main.stats_node[NSS_IPV4_RX_INTERFACE][i];
+		stats_shadow[i] = nss_top_main.stats_node[if_num][i];
 	}
-
 	spin_unlock_bh(&nss_top_main.stats_lock);
 
 	for (i = 0; (i < NSS_STATS_NODE_MAX); i++) {
@@ -1276,988 +114,14 @@
 					"%s = %llu\n", nss_stats_str_node[i], stats_shadow[i]);
 	}
 
-	/*
-	 * IPv4 node stats
-	 */
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nipv4 node stats:\n\n");
-
-	spin_lock_bh(&nss_top_main.stats_lock);
-	for (i = 0; (i < NSS_STATS_IPV4_MAX); i++) {
-		stats_shadow[i] = nss_top_main.stats_ipv4[i];
-	}
-
-	spin_unlock_bh(&nss_top_main.stats_lock);
-
-	for (i = 0; (i < NSS_STATS_IPV4_MAX); i++) {
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
-					"%s = %llu\n", nss_stats_str_ipv4[i], stats_shadow[i]);
-	}
-
-	/*
-	 * Exception stats
-	 */
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nipv4 exception stats:\n\n");
-
-	spin_lock_bh(&nss_top_main.stats_lock);
-	for (i = 0; (i < NSS_EXCEPTION_EVENT_IPV4_MAX); i++) {
-		stats_shadow[i] = nss_top_main.stats_if_exception_ipv4[i];
-	}
-
-	spin_unlock_bh(&nss_top_main.stats_lock);
-
-	for (i = 0; (i < NSS_EXCEPTION_EVENT_IPV4_MAX); i++) {
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
-					"%s = %llu\n", nss_stats_str_if_exception_ipv4[i], stats_shadow[i]);
-	}
-
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nipv4 stats end\n\n");
-	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
-	kfree(lbuf);
-	kfree(stats_shadow);
-
-	return bytes_read;
+	return size_wr;
 }
 
 /*
- * nss_stats_ipv4_reasm_read()
- *	Read IPV4 reassembly stats
- */
-static ssize_t nss_stats_ipv4_reasm_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
-{
-	int32_t i;
-	/*
-	 * max output lines = #stats + start tag line + end tag line + three blank lines
-	 */
-	uint32_t max_output_lines = (NSS_STATS_NODE_MAX + 2) + (NSS_STATS_IPV4_REASM_MAX + 3) + 5;
-	size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
-	size_t size_wr = 0;
-	ssize_t bytes_read = 0;
-	uint64_t *stats_shadow;
-
-	char *lbuf = kzalloc(size_al, GFP_KERNEL);
-	if (unlikely(lbuf == NULL)) {
-		nss_warning("Could not allocate memory for local statistics buffer");
-		return 0;
-	}
-
-	stats_shadow = kzalloc(NSS_STATS_IPV4_REASM_MAX * 8, GFP_KERNEL);
-	if (unlikely(stats_shadow == NULL)) {
-		nss_warning("Could not allocate memory for local shadow buffer");
-		kfree(lbuf);
-		return 0;
-	}
-
-	size_wr = scnprintf(lbuf, size_al, "ipv4 reasm stats start:\n\n");
-
-	/*
-	 * Common node stats
-	 */
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "common node stats:\n\n");
-	spin_lock_bh(&nss_top_main.stats_lock);
-	for (i = 0; (i < NSS_STATS_NODE_MAX); i++) {
-		stats_shadow[i] = nss_top_main.stats_node[NSS_IPV4_REASM_INTERFACE][i];
-	}
-
-	spin_unlock_bh(&nss_top_main.stats_lock);
-
-	for (i = 0; (i < NSS_STATS_NODE_MAX); i++) {
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
-					"%s = %llu\n", nss_stats_str_node[i], stats_shadow[i]);
-	}
-
-	/*
-	 * IPv4 reasm node stats
-	 */
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nipv4 reasm node stats:\n\n");
-
-	spin_lock_bh(&nss_top_main.stats_lock);
-	for (i = 0; (i < NSS_STATS_IPV4_REASM_MAX); i++) {
-		stats_shadow[i] = nss_top_main.stats_ipv4_reasm[i];
-	}
-
-	spin_unlock_bh(&nss_top_main.stats_lock);
-
-	for (i = 0; (i < NSS_STATS_IPV4_REASM_MAX); i++) {
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
-					"%s = %llu\n", nss_stats_str_ipv4_reasm[i], stats_shadow[i]);
-	}
-
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nipv4 reasm stats end\n\n");
-	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
-	kfree(lbuf);
-	kfree(stats_shadow);
-
-	return bytes_read;
-}
-
-/*
- * nss_stats_ipv6_read()
- *	Read IPV6 stats
- */
-static ssize_t nss_stats_ipv6_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
-{
-	int32_t i;
-
-	/*
-	 * max output lines = #stats + start tag line + end tag line + three blank lines
-	 */
-	uint32_t max_output_lines = (NSS_STATS_NODE_MAX + 2) + (NSS_STATS_IPV6_MAX + 3) + (NSS_EXCEPTION_EVENT_IPV6_MAX + 3) + 5;
-	size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
-	size_t size_wr = 0;
-	ssize_t bytes_read = 0;
-	uint64_t *stats_shadow;
-
-	char *lbuf = kzalloc(size_al, GFP_KERNEL);
-	if (unlikely(lbuf == NULL)) {
-		nss_warning("Could not allocate memory for local statistics buffer");
-		return 0;
-	}
-
-	/*
-	 * Note: The assumption here is that exception event count is larger than other statistics count for IPv4
-	 */
-	stats_shadow = kzalloc(NSS_EXCEPTION_EVENT_IPV6_MAX * 8, GFP_KERNEL);
-	if (unlikely(stats_shadow == NULL)) {
-		nss_warning("Could not allocate memory for local shadow buffer");
-		kfree(lbuf);
-		return 0;
-	}
-
-	size_wr = scnprintf(lbuf, size_al, "ipv6 stats start:\n\n");
-
-	/*
-	 * Common node stats
-	 */
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "common node stats:\n\n");
-	spin_lock_bh(&nss_top_main.stats_lock);
-	for (i = 0; (i < NSS_STATS_NODE_MAX); i++) {
-		stats_shadow[i] = nss_top_main.stats_node[NSS_IPV6_RX_INTERFACE][i];
-	}
-
-	spin_unlock_bh(&nss_top_main.stats_lock);
-
-	for (i = 0; (i < NSS_STATS_NODE_MAX); i++) {
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
-					"%s = %llu\n", nss_stats_str_node[i], stats_shadow[i]);
-	}
-
-	/*
-	 * IPv6 node stats
-	 */
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nipv6 node stats:\n\n");
-
-	spin_lock_bh(&nss_top_main.stats_lock);
-	for (i = 0; (i < NSS_STATS_IPV6_MAX); i++) {
-		stats_shadow[i] = nss_top_main.stats_ipv6[i];
-	}
-
-	spin_unlock_bh(&nss_top_main.stats_lock);
-
-	for (i = 0; (i < NSS_STATS_IPV6_MAX); i++) {
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
-					"%s = %llu\n", nss_stats_str_ipv6[i], stats_shadow[i]);
-	}
-
-	/*
-	 * Exception stats
-	 */
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nipv6 exception stats:\n\n");
-
-	spin_lock_bh(&nss_top_main.stats_lock);
-	for (i = 0; (i < NSS_EXCEPTION_EVENT_IPV6_MAX); i++) {
-		stats_shadow[i] = nss_top_main.stats_if_exception_ipv6[i];
-	}
-
-	spin_unlock_bh(&nss_top_main.stats_lock);
-
-	for (i = 0; (i < NSS_EXCEPTION_EVENT_IPV6_MAX); i++) {
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
-					"%s = %llu\n", nss_stats_str_if_exception_ipv6[i], stats_shadow[i]);
-	}
-
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nipv6 stats end\n\n");
-	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
-	kfree(lbuf);
-	kfree(stats_shadow);
-
-	return bytes_read;
-}
-
-/*
- * nss_stats_ipv6_reasm_read()
- *	Read IPV6 reassembly stats
- */
-static ssize_t nss_stats_ipv6_reasm_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
-{
-	int32_t i;
-	/*
-	 * max output lines = #stats + start tag line + end tag line + three blank lines
-	 */
-	uint32_t max_output_lines = (NSS_STATS_NODE_MAX + 2) + (NSS_STATS_IPV6_REASM_MAX + 3) + 5;
-	size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
-	size_t size_wr = 0;
-	ssize_t bytes_read = 0;
-	uint64_t *stats_shadow;
-
-	char *lbuf = kzalloc(size_al, GFP_KERNEL);
-	if (unlikely(lbuf == NULL)) {
-		nss_warning("Could not allocate memory for local statistics buffer");
-		return 0;
-	}
-
-	stats_shadow = kzalloc(NSS_STATS_IPV6_REASM_MAX * 8, GFP_KERNEL);
-	if (unlikely(stats_shadow == NULL)) {
-		nss_warning("Could not allocate memory for local shadow buffer");
-		kfree(lbuf);
-		return 0;
-	}
-
-	size_wr = scnprintf(lbuf, size_al, "ipv6 reasm stats start:\n\n");
-
-	/*
-	 * Common node stats
-	 */
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "common node stats:\n\n");
-	spin_lock_bh(&nss_top_main.stats_lock);
-	for (i = 0; (i < NSS_STATS_NODE_MAX); i++) {
-		stats_shadow[i] = nss_top_main.stats_node[NSS_IPV6_REASM_INTERFACE][i];
-	}
-
-	spin_unlock_bh(&nss_top_main.stats_lock);
-
-	for (i = 0; (i < NSS_STATS_NODE_MAX); i++) {
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
-					"%s = %llu\n", nss_stats_str_node[i], stats_shadow[i]);
-	}
-
-	/*
-	 * Ipv6 reasm node stats
-	 */
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nipv6 reasm node stats:\n\n");
-
-	spin_lock_bh(&nss_top_main.stats_lock);
-	for (i = 0; (i < NSS_STATS_IPV6_REASM_MAX); i++) {
-		stats_shadow[i] = nss_top_main.stats_ipv6_reasm[i];
-	}
-
-	spin_unlock_bh(&nss_top_main.stats_lock);
-
-	for (i = 0; (i < NSS_STATS_IPV6_REASM_MAX); i++) {
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
-					"%s = %llu\n", nss_stats_str_ipv6_reasm[i], stats_shadow[i]);
-	}
-
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nipv6 reasm stats end\n\n");
-	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
-	kfree(lbuf);
-	kfree(stats_shadow);
-
-	return bytes_read;
-}
-
-/*
- * nss_stats_edma_port_stats_read()
- *	Read EDMA port stats
- */
-static ssize_t nss_stats_edma_port_stats_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
-{
-	int32_t i;
-
-	/*
-	 * max output lines = #stats + start tag line + end tag line + three blank lines
-	 */
-	uint32_t max_output_lines = (NSS_STATS_NODE_MAX + 2) + 3;
-	size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
-	size_t size_wr = 0;
-	ssize_t bytes_read = 0;
-	uint64_t *stats_shadow;
-	struct nss_stats_data *data = fp->private_data;
-
-	char *lbuf = kzalloc(size_al, GFP_KERNEL);
-	if (unlikely(lbuf == NULL)) {
-		nss_warning("Could not allocate memory for local statistics buffer");
-		return 0;
-	}
-
-	/*
-	 * Note: The assumption here is that we do not have more than 64 stats
-	 */
-	stats_shadow = kzalloc(64 * 8, GFP_KERNEL);
-	if (unlikely(stats_shadow == NULL)) {
-		nss_warning("Could not allocate memory for local shadow buffer");
-		kfree(lbuf);
-		return 0;
-	}
-
-	size_wr = scnprintf(lbuf, size_al, "edma stats start:\n\n");
-
-	/*
-	 * Common node stats
-	 */
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "edma port %d stats:\n\n", data->edma_id);
-	spin_lock_bh(&nss_top_main.stats_lock);
-	for (i = 0; (i < NSS_STATS_NODE_MAX); i++) {
-		stats_shadow[i] = nss_top_main.stats_edma.port[data->edma_id].port_stats[i];
-	}
-
-	spin_unlock_bh(&nss_top_main.stats_lock);
-
-	for (i = 0; (i < NSS_STATS_NODE_MAX); i++) {
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
-					"%s = %llu\n", nss_stats_str_node[i], stats_shadow[i]);
-	}
-
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nedma stats end\n\n");
-	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
-	kfree(lbuf);
-	kfree(stats_shadow);
-
-	return bytes_read;
-}
-
-/*
- * nss_stats_edma_err_stats_read()
- *	Read EDMA err stats
- */
-static ssize_t nss_stats_edma_err_stats_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
-{
-	int32_t i;
-
-	/*
-	 * max output lines = #stats + start tag line + end tag line + three blank lines
-	 */
-	uint32_t max_output_lines = (NSS_EDMA_ERR_STATS_MAX + 2) + 3;
-	size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
-	size_t size_wr = 0;
-	ssize_t bytes_read = 0;
-	uint64_t *stats_shadow;
-
-	char *lbuf = kzalloc(size_al, GFP_KERNEL);
-	if (unlikely(lbuf == NULL)) {
-		nss_warning("Could not allocate memory for local statistics buffer");
-		return 0;
-	}
-
-	/*
-	 * Note: The assumption here is that we do not have more than 64 stats
-	 */
-	stats_shadow = kzalloc(64 * 8, GFP_KERNEL);
-	if (unlikely(stats_shadow == NULL)) {
-		nss_warning("Could not allocate memory for local shadow buffer");
-		kfree(lbuf);
-		return 0;
-	}
-
-	size_wr = scnprintf(lbuf, size_al, "edma error stats start:\n\n");
-
-	/*
-	 * Common node stats
-	 */
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "edma error stats:\n\n");
-	spin_lock_bh(&nss_top_main.stats_lock);
-
-	for (i = 0; (i < NSS_EDMA_ERR_STATS_MAX); i++)
-		stats_shadow[i] = nss_top_main.stats_edma.misc_err[i];
-
-	spin_unlock_bh(&nss_top_main.stats_lock);
-
-	for (i = 0; (i < NSS_EDMA_ERR_STATS_MAX); i++) {
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
-					"%s = %llu\n", nss_stats_str_edma_err_map[i], stats_shadow[i]);
-	}
-
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nedma error stats end\n\n");
-	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
-	kfree(lbuf);
-	kfree(stats_shadow);
-
-	return bytes_read;
-}
-
-/*
- * nss_stats_edma_port_type_read()
- *	Read EDMA port type
- */
-static ssize_t nss_stats_edma_port_type_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
-{
-	/*
-	 * max output lines = #stats + start tag line + end tag line + three blank lines
-	 */
-	uint32_t max_output_lines = (1 + 2) + 3;
-	size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
-	size_t size_wr = 0;
-	ssize_t bytes_read = 0;
-	uint64_t port_type;
-	struct nss_stats_data *data = fp->private_data;
-
-	char *lbuf = kzalloc(size_al, GFP_KERNEL);
-	if (unlikely(lbuf == NULL)) {
-		nss_warning("Could not allocate memory for local statistics buffer");
-		return 0;
-	}
-
-	size_wr = scnprintf(lbuf, size_al, "edma port type start:\n\n");
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "edma port %d type:\n\n", data->edma_id);
-
-	/*
-	 * Port type
-	 */
-	spin_lock_bh(&nss_top_main.stats_lock);
-	port_type = nss_top_main.stats_edma.port[data->edma_id].port_type;
-	spin_unlock_bh(&nss_top_main.stats_lock);
-
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
-					"port_type = %s\n", nss_stats_str_edma_port_type[port_type]);
-
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nedma stats end\n");
-	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
-	kfree(lbuf);
-
-	return bytes_read;
-}
-
-/*
- * nss_stats_edma_port_ring_map_read()
- *	Read EDMA port ring map
- */
-static ssize_t nss_stats_edma_port_ring_map_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
-{
-	int32_t i;
-
-	/*
-	 * max output lines = #stats + start tag line + end tag line + three blank lines
-	 */
-	uint32_t max_output_lines = (4 + 2) + 3;
-	size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
-	size_t size_wr = 0;
-	ssize_t bytes_read = 0;
-	uint64_t *stats_shadow;
-	struct nss_stats_data *data = fp->private_data;
-
-	char *lbuf = kzalloc(size_al, GFP_KERNEL);
-	if (unlikely(lbuf == NULL)) {
-		nss_warning("Could not allocate memory for local statistics buffer");
-		return 0;
-	}
-
-	/*
-	 * Note: The assumption here is that we do not have more than 64 stats
-	 */
-	stats_shadow = kzalloc(64 * 8, GFP_KERNEL);
-	if (unlikely(stats_shadow == NULL)) {
-		nss_warning("Could not allocate memory for local shadow buffer");
-		kfree(lbuf);
-		return 0;
-	}
-
-	size_wr = scnprintf(lbuf, size_al, "edma port ring map start:\n\n");
-
-	/*
-	 * Port ring map
-	 */
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "edma port %d ring map:\n\n", data->edma_id);
-	spin_lock_bh(&nss_top_main.stats_lock);
-	for (i = 0; i < NSS_EDMA_PORT_RING_MAP_MAX; i++) {
-		stats_shadow[i] = nss_top_main.stats_edma.port[data->edma_id].port_ring_map[i];
-	}
-
-	spin_unlock_bh(&nss_top_main.stats_lock);
-
-	for (i = 0; i < NSS_EDMA_PORT_RING_MAP_MAX; i++) {
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
-					"%s = %llu\n", nss_stats_str_edma_port_ring_map[i], stats_shadow[i]);
-	}
-
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nedma stats end\n\n");
-	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
-	kfree(lbuf);
-	kfree(stats_shadow);
-
-	return bytes_read;
-}
-
-/*
- * nss_stats_edma_txring_read()
- *	Read EDMA Tx ring stats
- */
-static ssize_t nss_stats_edma_txring_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
-{
-	int32_t i;
-
-	/*
-	 * max output lines = #stats + start tag line + end tag line + three blank lines
-	 */
-	uint32_t max_output_lines = (NSS_STATS_EDMA_TX_MAX + 2) + 3;
-	size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
-	size_t size_wr = 0;
-	ssize_t bytes_read = 0;
-	uint64_t *stats_shadow;
-	struct nss_stats_data *data = fp->private_data;
-
-	char *lbuf = kzalloc(size_al, GFP_KERNEL);
-	if (unlikely(lbuf == NULL)) {
-		nss_warning("Could not allocate memory for local statistics buffer");
-		return 0;
-	}
-
-	/*
-	 * Note: The assumption here is that we do not have more than 64 stats
-	 */
-	stats_shadow = kzalloc(64 * 8, GFP_KERNEL);
-	if (unlikely(stats_shadow == NULL)) {
-		nss_warning("Could not allocate memory for local shadow buffer");
-		kfree(lbuf);
-		return 0;
-	}
-
-	size_wr = scnprintf(lbuf, size_al, "edma Tx ring stats start:\n\n");
-
-	/*
-	 * Tx ring stats
-	 */
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "Tx ring %d stats:\n\n", data->edma_id);
-	spin_lock_bh(&nss_top_main.stats_lock);
-	for (i = 0; i < NSS_STATS_EDMA_TX_MAX; i++) {
-		stats_shadow[i] = nss_top_main.stats_edma.tx_stats[data->edma_id][i];
-	}
-
-	spin_unlock_bh(&nss_top_main.stats_lock);
-
-	for (i = 0; i < NSS_STATS_EDMA_TX_MAX; i++) {
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
-					"%s = %llu\n", nss_stats_str_edma_tx[i], stats_shadow[i]);
-	}
-
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nedma Tx ring stats end\n\n");
-	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
-	kfree(lbuf);
-	kfree(stats_shadow);
-
-	return bytes_read;
-}
-
-/*
- * nss_stats_edma_rxring_read()
- *	Read EDMA rxring stats
- */
-static ssize_t nss_stats_edma_rxring_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
-{
-	int32_t i;
-
-	/*
-	 * max output lines = #stats + start tag line + end tag line + three blank lines
-	 */
-	uint32_t max_output_lines = (NSS_STATS_EDMA_RX_MAX + 2) + 3;
-	size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
-	size_t size_wr = 0;
-	ssize_t bytes_read = 0;
-	uint64_t *stats_shadow;
-	struct nss_stats_data *data = fp->private_data;
-
-	char *lbuf = kzalloc(size_al, GFP_KERNEL);
-	if (unlikely(lbuf == NULL)) {
-		nss_warning("Could not allocate memory for local statistics buffer");
-		return 0;
-	}
-
-	/*
-	 * Note: The assumption here is that we do not have more than 64 stats
-	 */
-	stats_shadow = kzalloc(64 * 8, GFP_KERNEL);
-	if (unlikely(stats_shadow == NULL)) {
-		nss_warning("Could not allocate memory for local shadow buffer");
-		kfree(lbuf);
-		return 0;
-	}
-
-	size_wr = scnprintf(lbuf, size_al, "edma Rx ring stats start:\n\n");
-
-	/*
-	 * RX ring stats
-	 */
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "Rx ring %d stats:\n\n", data->edma_id);
-	spin_lock_bh(&nss_top_main.stats_lock);
-	for (i = 0; i < NSS_STATS_EDMA_RX_MAX; i++) {
-		stats_shadow[i] = nss_top_main.stats_edma.rx_stats[data->edma_id][i];
-	}
-
-	spin_unlock_bh(&nss_top_main.stats_lock);
-
-	for (i = 0; i < NSS_STATS_EDMA_RX_MAX; i++) {
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
-					"%s = %llu\n", nss_stats_str_edma_rx[i], stats_shadow[i]);
-	}
-
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nedma Rx ring stats end\n\n");
-	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
-	kfree(lbuf);
-	kfree(stats_shadow);
-
-	return bytes_read;
-}
-
-/*
- * nss_stats_edma_txcmplring_read()
- *	Read EDMA txcmplring stats
- */
-static ssize_t nss_stats_edma_txcmplring_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
-{
-	int32_t i;
-
-	/*
-	 * max output lines = #stats + start tag line + end tag line + three blank lines
-	 */
-	uint32_t max_output_lines = (NSS_STATS_EDMA_TXCMPL_MAX + 2) + 3;
-	size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
-	size_t size_wr = 0;
-	ssize_t bytes_read = 0;
-	uint64_t *stats_shadow;
-	struct nss_stats_data *data = fp->private_data;
-
-	char *lbuf = kzalloc(size_al, GFP_KERNEL);
-	if (unlikely(lbuf == NULL)) {
-		nss_warning("Could not allocate memory for local statistics buffer");
-		return 0;
-	}
-
-	/*
-	 * Note: The assumption here is that we do not have more than 64 stats
-	 */
-	stats_shadow = kzalloc(64 * 8, GFP_KERNEL);
-	if (unlikely(stats_shadow == NULL)) {
-		nss_warning("Could not allocate memory for local shadow buffer");
-		kfree(lbuf);
-		return 0;
-	}
-
-	size_wr = scnprintf(lbuf, size_al, "edma Tx cmpl ring stats start:\n\n");
-
-	/*
-	 * Tx cmpl ring stats
-	 */
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "Tx cmpl ring %d stats:\n\n", data->edma_id);
-	spin_lock_bh(&nss_top_main.stats_lock);
-	for (i = 0; i < NSS_STATS_EDMA_TXCMPL_MAX; i++) {
-		stats_shadow[i] = nss_top_main.stats_edma.txcmpl_stats[data->edma_id][i];
-	}
-
-	spin_unlock_bh(&nss_top_main.stats_lock);
-
-	for (i = 0; i < NSS_STATS_EDMA_TXCMPL_MAX; i++) {
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
-					"%s = %llu\n", nss_stats_str_edma_txcmpl[i], stats_shadow[i]);
-	}
-
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nedma Tx cmpl ring stats end\n\n");
-	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
-	kfree(lbuf);
-	kfree(stats_shadow);
-
-	return bytes_read;
-}
-
-/*
- * nss_stats_edma_rxfillring_read()
- *	Read EDMA rxfillring stats
- */
-static ssize_t nss_stats_edma_rxfillring_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
-{
-	int32_t i;
-
-	/*
-	 * max output lines = #stats + start tag line + end tag line + three blank lines
-	 */
-	uint32_t max_output_lines = (NSS_STATS_EDMA_RXFILL_MAX + 2) + 3;
-	size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
-	size_t size_wr = 0;
-	ssize_t bytes_read = 0;
-	uint64_t *stats_shadow;
-	struct nss_stats_data *data = fp->private_data;
-
-	char *lbuf = kzalloc(size_al, GFP_KERNEL);
-	if (unlikely(lbuf == NULL)) {
-		nss_warning("Could not allocate memory for local statistics buffer");
-		return 0;
-	}
-
-	/*
-	 * Note: The assumption here is that we do not have more than 64 stats
-	 */
-	stats_shadow = kzalloc(64 * 8, GFP_KERNEL);
-	if (unlikely(stats_shadow == NULL)) {
-		nss_warning("Could not allocate memory for local shadow buffer");
-		kfree(lbuf);
-		return 0;
-	}
-
-	size_wr = scnprintf(lbuf, size_al, "edma Rx fill ring stats start:\n\n");
-
-	/*
-	 * Rx fill ring stats
-	 */
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "Rx fill ring %d stats:\n\n", data->edma_id);
-	spin_lock_bh(&nss_top_main.stats_lock);
-	for (i = 0; i < NSS_STATS_EDMA_RXFILL_MAX; i++) {
-		stats_shadow[i] = nss_top_main.stats_edma.rxfill_stats[data->edma_id][i];
-	}
-
-	spin_unlock_bh(&nss_top_main.stats_lock);
-
-	for (i = 0; i < NSS_STATS_EDMA_RXFILL_MAX; i++) {
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
-					"%s = %llu\n", nss_stats_str_edma_rxfill[i], stats_shadow[i]);
-	}
-
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nedma Rx fill ring stats end\n\n");
-	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
-	kfree(lbuf);
-	kfree(stats_shadow);
-
-	return bytes_read;
-}
-
-/*
- * nss_stats_eth_rx_read()
- *	Read ETH_RX stats
- */
-static ssize_t nss_stats_eth_rx_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
-{
-	int32_t i;
-
-	/*
-	 * max output lines = #stats + start tag line + end tag line + three blank lines
-	 */
-	uint32_t max_output_lines = (NSS_STATS_NODE_MAX + 2) + (NSS_STATS_ETH_RX_MAX + 3) + (NSS_EXCEPTION_EVENT_ETH_RX_MAX + 3) + 5;
-	size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
-	size_t size_wr = 0;
-	ssize_t bytes_read = 0;
-	uint64_t *stats_shadow;
-
-	char *lbuf = kzalloc(size_al, GFP_KERNEL);
-	if (unlikely(lbuf == NULL)) {
-		nss_warning("Could not allocate memory for local statistics buffer");
-		return 0;
-	}
-
-	/*
-	 * Note: The assumption here is that we do not have more than 64 stats
-	 */
-	stats_shadow = kzalloc(64 * 8, GFP_KERNEL);
-	if (unlikely(stats_shadow == NULL)) {
-		nss_warning("Could not allocate memory for local shadow buffer");
-		kfree(lbuf);
-		return 0;
-	}
-
-	size_wr = scnprintf(lbuf, size_al, "eth_rx stats start:\n\n");
-
-	/*
-	 * Common node stats
-	 */
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "common node stats:\n\n");
-	spin_lock_bh(&nss_top_main.stats_lock);
-	for (i = 0; (i < NSS_STATS_NODE_MAX); i++) {
-		stats_shadow[i] = nss_top_main.stats_node[NSS_ETH_RX_INTERFACE][i];
-	}
-
-	spin_unlock_bh(&nss_top_main.stats_lock);
-
-	for (i = 0; (i < NSS_STATS_NODE_MAX); i++) {
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
-					"%s = %llu\n", nss_stats_str_node[i], stats_shadow[i]);
-	}
-
-	/*
-	 * eth_rx node stats
-	 */
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\neth_rx node stats:\n\n");
-	spin_lock_bh(&nss_top_main.stats_lock);
-	for (i = 0; (i < NSS_STATS_ETH_RX_MAX); i++) {
-		stats_shadow[i] = nss_top_main.stats_eth_rx[i];
-	}
-
-	spin_unlock_bh(&nss_top_main.stats_lock);
-
-	for (i = 0; (i < NSS_STATS_ETH_RX_MAX); i++) {
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
-					"%s = %llu\n", nss_stats_str_eth_rx[i], stats_shadow[i]);
-	}
-
-	/*
-	 * Exception stats
-	 */
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\neth_rx exception stats:\n\n");
-
-	spin_lock_bh(&nss_top_main.stats_lock);
-	for (i = 0; (i < NSS_EXCEPTION_EVENT_ETH_RX_MAX); i++) {
-		stats_shadow[i] = nss_top_main.stats_if_exception_eth_rx[i];
-	}
-
-	spin_unlock_bh(&nss_top_main.stats_lock);
-
-	for (i = 0; (i < NSS_EXCEPTION_EVENT_ETH_RX_MAX); i++) {
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
-					"%s = %llu\n", nss_stats_str_if_exception_eth_rx[i], stats_shadow[i]);
-	}
-
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\neth_rx stats end\n\n");
-	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
-	kfree(lbuf);
-	kfree(stats_shadow);
-
-	return bytes_read;
-}
-
-/*
- * nss_stats_n2h_read()
- *	Read N2H stats
- */
-static ssize_t nss_stats_n2h_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
-{
-	int32_t i;
-
-	/*
-	 * max output lines = #stats + start tag line + end tag line + three blank lines
-	 */
-	uint32_t max_output_lines = (NSS_STATS_NODE_MAX + 2) + (NSS_STATS_N2H_MAX + 3) + 5;
-	size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
-	size_t size_wr = 0;
-	ssize_t bytes_read = 0;
-	uint64_t *stats_shadow;
-	int max = NSS_STATS_N2H_MAX - NSS_STATS_NODE_MAX;
-
-	char *lbuf = kzalloc(size_al, GFP_KERNEL);
-	if (unlikely(lbuf == NULL)) {
-		nss_warning("Could not allocate memory for local statistics buffer");
-		return 0;
-	}
-
-	stats_shadow = kzalloc(NSS_STATS_N2H_MAX * 8, GFP_KERNEL);
-	if (unlikely(stats_shadow == NULL)) {
-		nss_warning("Could not allocate memory for local shadow buffer");
-		kfree(lbuf);
-		return 0;
-	}
-
-	size_wr = scnprintf(lbuf, size_al, "n2h stats start:\n\n");
-
-	/*
-	 * Common node stats
-	 */
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "common node stats:\n\n");
-	spin_lock_bh(&nss_top_main.stats_lock);
-	for (i = 0; (i < NSS_STATS_NODE_MAX); i++) {
-		stats_shadow[i] = nss_top_main.nss[0].stats_n2h[i];
-	}
-
-	spin_unlock_bh(&nss_top_main.stats_lock);
-
-	for (i = 0; (i < NSS_STATS_NODE_MAX); i++) {
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
-					"%s = %llu\n", nss_stats_str_node[i], stats_shadow[i]);
-	}
-
-	/*
-	 * N2H node stats
-	 */
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nn2h node stats:\n\n");
-	spin_lock_bh(&nss_top_main.stats_lock);
-	for (i = NSS_STATS_NODE_MAX; (i < NSS_STATS_N2H_MAX); i++) {
-		stats_shadow[i] = nss_top_main.nss[0].stats_n2h[i];
-	}
-
-	spin_unlock_bh(&nss_top_main.stats_lock);
-
-	for (i = 0; i < max; i++) {
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
-					"%s = %llu\n", nss_stats_str_n2h[i], stats_shadow[i + NSS_STATS_NODE_MAX]);
-	}
-
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nn2h stats end\n\n");
-	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
-	kfree(lbuf);
-	kfree(stats_shadow);
-
-	return bytes_read;
-}
-
-/*
- * nss_stats_lso_rx_read()
- *	Read LSO_RX stats
- */
-static ssize_t nss_stats_lso_rx_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
-{
-	int32_t i;
-
-	/*
-	 * max output lines = #stats + start tag line + end tag line + three blank lines
-	 */
-	uint32_t max_output_lines = (NSS_STATS_NODE_MAX + 2) + (NSS_STATS_LSO_RX_MAX + 3) + 5;
-	size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
-	size_t size_wr = 0;
-	ssize_t bytes_read = 0;
-	uint64_t *stats_shadow;
-
-	char *lbuf = kzalloc(size_al, GFP_KERNEL);
-	if (unlikely(lbuf == NULL)) {
-		nss_warning("Could not allocate memory for local statistics buffer");
-		return 0;
-	}
-
-	stats_shadow = kzalloc(NSS_STATS_LSO_RX_MAX * 8, GFP_KERNEL);
-	if (unlikely(stats_shadow == NULL)) {
-		nss_warning("Could not allocate memory for local shadow buffer");
-		kfree(lbuf);
-		return 0;
-	}
-
-	size_wr = scnprintf(lbuf, size_al, "lso_rx stats start:\n\n");
-
-	/*
-	 * Common node stats
-	 */
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "common node stats:\n\n");
-	spin_lock_bh(&nss_top_main.stats_lock);
-	for (i = 0; (i < NSS_STATS_NODE_MAX); i++) {
-		stats_shadow[i] = nss_top_main.stats_node[NSS_LSO_RX_INTERFACE][i];
-	}
-
-	spin_unlock_bh(&nss_top_main.stats_lock);
-
-	for (i = 0; (i < NSS_STATS_NODE_MAX); i++) {
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
-					"%s = %llu\n", nss_stats_str_node[i], stats_shadow[i]);
-	}
-
-	/*
-	 * lso_rx node stats
-	 */
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nlso_rx node stats:\n\n");
-	spin_lock_bh(&nss_top_main.stats_lock);
-	for (i = 0; (i < NSS_STATS_LSO_RX_MAX); i++) {
-		stats_shadow[i] = nss_top_main.stats_lso_rx[i];
-	}
-
-	spin_unlock_bh(&nss_top_main.stats_lock);
-
-	for (i = 0; i < NSS_STATS_LSO_RX_MAX; i++) {
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
-					"%s = %llu\n", nss_stats_str_lso_rx[i], stats_shadow[i]);
-	}
-
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nlso_rx stats end\n\n");
-	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
-	kfree(lbuf);
-	kfree(stats_shadow);
-
-	return bytes_read;
-}
-
-/*
- * nss_stats_drv_read()
+ * nss_drv_stats_read()
  *	Read HLOS driver stats
  */
-static ssize_t nss_stats_drv_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
+static ssize_t nss_drv_stats_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
 {
 	int32_t i;
 
@@ -2302,112 +166,10 @@
 }
 
 /*
- * nss_stats_pppoe_read()
- *	Read PPPoE stats
- */
-static ssize_t nss_stats_pppoe_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
-{
-	int32_t i, j, k;
-
-	/*
-	 * max output lines = #stats + start tag line + end tag line + three blank lines
-	 */
-	uint32_t max_output_lines = (NSS_STATS_NODE_MAX + 2) + (NSS_STATS_PPPOE_MAX + 3) +
-					((NSS_MAX_PHYSICAL_INTERFACES * NSS_PPPOE_NUM_SESSION_PER_INTERFACE * (NSS_PPPOE_EXCEPTION_EVENT_MAX + 5)) + 3) + 5;
-	size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
-	size_t size_wr = 0;
-	ssize_t bytes_read = 0;
-	uint64_t *stats_shadow;
-
-	char *lbuf = kzalloc(size_al, GFP_KERNEL);
-	if (unlikely(lbuf == NULL)) {
-		nss_warning("Could not allocate memory for local statistics buffer");
-		return 0;
-	}
-
-	stats_shadow = kzalloc(64 * 8, GFP_KERNEL);
-	if (unlikely(stats_shadow == NULL)) {
-		nss_warning("Could not allocate memory for local shadow buffer");
-		kfree(lbuf);
-		return 0;
-	}
-
-	size_wr = scnprintf(lbuf, size_al, "pppoe stats start:\n\n");
-
-	/*
-	 * Common node stats
-	 */
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "common node stats:\n\n");
-	spin_lock_bh(&nss_top_main.stats_lock);
-	for (i = 0; (i < NSS_STATS_NODE_MAX); i++) {
-		stats_shadow[i] = nss_top_main.stats_node[NSS_PPPOE_RX_INTERFACE][i];
-	}
-
-	spin_unlock_bh(&nss_top_main.stats_lock);
-
-	for (i = 0; (i < NSS_STATS_NODE_MAX); i++) {
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
-				 "%s = %llu\n", nss_stats_str_node[i], stats_shadow[i]);
-	}
-
-	/*
-	 * PPPoE node stats
-	 */
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\npppoe node stats:\n\n");
-	spin_lock_bh(&nss_top_main.stats_lock);
-	for (i = 0; (i < NSS_STATS_PPPOE_MAX); i++) {
-		stats_shadow[i] = nss_top_main.stats_pppoe[i];
-	}
-
-	spin_unlock_bh(&nss_top_main.stats_lock);
-
-	for (i = 0; (i < NSS_STATS_PPPOE_MAX); i++) {
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
-					"%s = %llu\n", nss_stats_str_pppoe[i], stats_shadow[i]);
-	}
-
-	/*
-	 * Exception stats
-	 */
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nException PPPoE:\n\n");
-
-	for (j = 1; j <= NSS_MAX_PHYSICAL_INTERFACES; j++) {
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nInterface %d:\n\n", j);
-
-		spin_lock_bh(&nss_top_main.stats_lock);
-		for (k = 1; k <= NSS_PPPOE_NUM_SESSION_PER_INTERFACE; k++) {
-			for (i = 0; (i < NSS_PPPOE_EXCEPTION_EVENT_MAX); i++) {
-				stats_shadow_pppoe_except[k - 1][i] = nss_top_main.stats_if_exception_pppoe[j][k][i];
-			}
-		}
-
-		spin_unlock_bh(&nss_top_main.stats_lock);
-
-		for (k = 1; k <= NSS_PPPOE_NUM_SESSION_PER_INTERFACE; k++) {
-			size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "%d. Session\n", k);
-			for (i = 0; (i < NSS_PPPOE_EXCEPTION_EVENT_MAX); i++) {
-				size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
-						"%s = %llu\n",
-						nss_stats_str_if_exception_pppoe[i],
-						stats_shadow_pppoe_except[k - 1][i]);
-			}
-		}
-
-	}
-
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\npppoe stats end\n\n");
-	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
-	kfree(lbuf);
-	kfree(stats_shadow);
-
-	return bytes_read;
-}
-
-/*
- * nss_stats_gmac_read()
+ * nss_gmac_stats_read()
  *	Read GMAC stats
  */
-static ssize_t nss_stats_gmac_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
+static ssize_t nss_gmac_stats_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
 {
 	uint32_t i, id;
 
@@ -2460,1792 +222,10 @@
 }
 
 /*
- * nss_stats_wifi_read()
- * 	Read wifi statistics
- */
-static ssize_t nss_stats_wifi_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
-{
-	uint32_t i, id;
-
-	/*
-	 * max output lines = ((#stats + start tag + one blank) * #WIFI RADIOs) + start/end tag + 3 blank
-	 */
-	uint32_t max_output_lines = ((NSS_STATS_WIFI_MAX + 2) * NSS_MAX_WIFI_RADIO_INTERFACES) + 5;
-	size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
-	size_t size_wr = 0;
-	ssize_t bytes_read = 0;
-	uint64_t *stats_shadow;
-
-	char *lbuf = kzalloc(size_al, GFP_KERNEL);
-	if (unlikely(lbuf == NULL)) {
-		nss_warning("Could not allocate memory for local statistics buffer");
-		return 0;
-	}
-
-	stats_shadow = kzalloc(NSS_STATS_WIFI_MAX * 8, GFP_KERNEL);
-	if (unlikely(stats_shadow == NULL)) {
-		nss_warning("Could not allocate memory for local shadow buffer");
-		kfree(lbuf);
-		return 0;
-	}
-
-	size_wr = scnprintf(lbuf, size_al, "wifi stats start:\n\n");
-
-	for (id = 0; id < NSS_MAX_WIFI_RADIO_INTERFACES; id++) {
-		spin_lock_bh(&nss_top_main.stats_lock);
-		for (i = 0; (i < NSS_STATS_WIFI_MAX); i++) {
-			stats_shadow[i] = nss_top_main.stats_wifi[id][i];
-		}
-
-		spin_unlock_bh(&nss_top_main.stats_lock);
-
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "WIFI ID: %d\n", id);
-		for (i = 0; (i < NSS_STATS_WIFI_MAX); i++) {
-			size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
-					"%s = %llu\n", nss_stats_str_wifi[i], stats_shadow[i]);
-		}
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,"\n");
-	}
-
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nwifi stats end\n\n");
-	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
-	kfree(lbuf);
-	kfree(stats_shadow);
-
-	return bytes_read;
-}
-
-/*
- * nss_stats_wifili_read()
- * 	Read wifili statistics
- */
-static ssize_t nss_stats_wifili_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
-{
-	uint32_t i, j;
-
-	/*
-	 * max output lines = ((#stats + eight blank lines) * #WIFILI #STATS) + start/end tag + 3 blank
-	 */
-	uint32_t max_output_lines = (((NSS_STATS_WIFILI_MAX + 9) * NSS_WIFILI_MAX_PDEV_NUM_MSG)+
-									NSS_STATS_WIFILI_WBM_MAX + 5);
-	size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
-	size_t size_wr = 0;
-	ssize_t bytes_read = 0;
-	uint64_t *stats_shadow;
-
-	char *lbuf = kzalloc(size_al, GFP_KERNEL);
-	if (unlikely(lbuf == NULL)) {
-		nss_warning("Could not allocate memory for local statistics buffer");
-		return 0;
-	}
-
-	/*
-	 * Take max of all wifili stats
-	 *
-	 * NOTE: txrx stats is bigger of all stats
-	 */
-	stats_shadow = kzalloc(NSS_STATS_WIFILI_TXRX_MAX * 8, GFP_KERNEL);
-	if (unlikely(stats_shadow == NULL)) {
-		nss_warning("Could not allocate memory for local shadow buffer");
-		kfree(lbuf);
-		return 0;
-	}
-
-	size_wr = scnprintf(lbuf, size_al, "wifili stats start:\n\n");
-
-	for (i = 0; i < NSS_WIFILI_MAX_PDEV_NUM_MSG; i++) {
-
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "WIFILI ID: %d\n", i);
-
-		spin_lock_bh(&nss_top_main.stats_lock);
-		for (j = 0; (j < NSS_STATS_WIFILI_TXRX_MAX); j++) {
-			stats_shadow[j] = nss_top_main.stats_wifili.stats_txrx[i][j];
-			size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
-					"%s = %llu\n", nss_stats_str_wifili_txrx[j], stats_shadow[j]);
-		}
-
-		spin_unlock_bh(&nss_top_main.stats_lock);
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\n");
-
-		/*
-		 * Fillinng TCL ring stats
-		 */
-		spin_lock_bh(&nss_top_main.stats_lock);
-		for (j = 0; (j < NSS_STATS_WIFILI_TCL_MAX); j++) {
-			stats_shadow[j] = nss_top_main.stats_wifili.stats_tcl_ring[i][j];
-			size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
-					"%s = %llu\n", nss_stats_str_wifili_tcl[j], stats_shadow[j]);
-		}
-
-		spin_unlock_bh(&nss_top_main.stats_lock);
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\n");
-
-		/*
-		 * Fillinng TCL comp stats
-		 */
-		spin_lock_bh(&nss_top_main.stats_lock);
-		for (j = 0; (j < NSS_STATS_WIFILI_TX_DESC_FREE_MAX); j++) {
-			stats_shadow[j] = nss_top_main.stats_wifili.stats_tx_comp[i][j];
-			size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
-					"%s = %llu\n", nss_stats_str_wifili_tx_comp[j], stats_shadow[j]);
-		}
-
-		spin_unlock_bh(&nss_top_main.stats_lock);
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\n");
-
-		/*
-		 * Fillinng reo ring stats
-		 */
-		spin_lock_bh(&nss_top_main.stats_lock);
-		for (j = 0; (j < NSS_STATS_WIFILI_REO_MAX); j++) {
-			stats_shadow[j] = nss_top_main.stats_wifili.stats_reo[i][j];
-			size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
-					"%s = %llu\n", nss_stats_str_wifili_reo[j], stats_shadow[j]);
-		}
-
-		spin_unlock_bh(&nss_top_main.stats_lock);
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\n");
-
-		/*
-		 * Fillinng TX SW Pool
-		 */
-		spin_lock_bh(&nss_top_main.stats_lock);
-		for (j = 0; (j < NSS_STATS_WIFILI_TX_DESC_MAX); j++) {
-			stats_shadow[j] = nss_top_main.stats_wifili.stats_tx_desc[i][j];
-			size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
-					"%s = %llu\n", nss_stats_str_wifili_txsw_pool[j], stats_shadow[j]);
-		}
-
-		spin_unlock_bh(&nss_top_main.stats_lock);
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\n");
-
-		/*
-		 * Fillinng TX  EXt SW Pool
-		 */
-		spin_lock_bh(&nss_top_main.stats_lock);
-		for (j = 0; (j < NSS_STATS_WIFILI_EXT_TX_DESC_MAX); j++) {
-			stats_shadow[j] = nss_top_main.stats_wifili.stats_ext_tx_desc[i][j];
-			size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
-					"%s = %llu\n", nss_stats_str_wifili_ext_txsw_pool[j], stats_shadow[j]);
-		}
-
-		spin_unlock_bh(&nss_top_main.stats_lock);
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\n");
-
-		/*
-		 * Fillinng rxdma pool stats
-		 */
-		spin_lock_bh(&nss_top_main.stats_lock);
-		for (j = 0; (j < NSS_STATS_WIFILI_RX_DESC_MAX); j++) {
-			stats_shadow[j] = nss_top_main.stats_wifili.stats_rx_desc[i][j];
-			size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
-					"%s = %llu\n", nss_stats_str_wifili_rxdma_pool[j], stats_shadow[j]);
-		}
-
-		spin_unlock_bh(&nss_top_main.stats_lock);
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\n");
-
-		/*
-		 * Fillinng rxdma ring stats
-		 */
-		spin_lock_bh(&nss_top_main.stats_lock);
-		for (j = 0; (j < NSS_STATS_WIFILI_RXDMA_DESC_MAX); j++) {
-			stats_shadow[j] = nss_top_main.stats_wifili.stats_rxdma[i][j];
-			size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
-					"%s = %llu\n", nss_stats_str_wifili_rxdma_ring[j], stats_shadow[j]);
-		}
-
-		spin_unlock_bh(&nss_top_main.stats_lock);
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\n");
-
-	}
-
-	/*
-	 * Fillinng wbm ring stats
-	 */
-	spin_lock_bh(&nss_top_main.stats_lock);
-	for (j = 0; (j < NSS_STATS_WIFILI_WBM_MAX); j++) {
-		stats_shadow[j] = nss_top_main.stats_wifili.stats_wbm[j];
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
-				"%s = %llu\n", nss_stats_str_wifili_wbm[j], stats_shadow[j]);
-	}
-
-	spin_unlock_bh(&nss_top_main.stats_lock);
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nwifili stats end\n\n");
-
-	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
-	kfree(lbuf);
-	kfree(stats_shadow);
-
-	return bytes_read;
-}
-
-/*
- * nss_stats_dtls_read()
- *	Read DTLS session statistics
- */
-static ssize_t nss_stats_dtls_read(struct file *fp, char __user *ubuf,
-				   size_t sz, loff_t *ppos)
-{
-	uint32_t max_output_lines = 2 + (NSS_MAX_DTLS_SESSIONS
-					* (NSS_STATS_DTLS_SESSION_MAX + 2)) + 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;
-	int id, i;
-	struct nss_stats_dtls_session_debug *dtls_session_stats = NULL;
-
-	char *lbuf = kzalloc(size_al, GFP_KERNEL);
-	if (unlikely(lbuf == NULL)) {
-		nss_warning("Could not allocate memory for local statistics buffer");
-		return 0;
-	}
-
-	dtls_session_stats = kzalloc((sizeof(struct nss_stats_dtls_session_debug)
-				     * NSS_MAX_DTLS_SESSIONS), GFP_KERNEL);
-	if (unlikely(dtls_session_stats == NULL)) {
-		nss_warning("Could not allocate memory for populating DTLS stats");
-		kfree(lbuf);
-		return 0;
-	}
-
-	/*
-	 * Get all stats
-	 */
-	nss_dtls_session_debug_stats_get(dtls_session_stats);
-
-	/*
-	 * Session stats
-	 */
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
-			     "\nDTLS session stats start:\n\n");
-
-	for (id = 0; id < NSS_MAX_DTLS_SESSIONS; id++) {
-		if (!dtls_session_stats[id].valid)
-			break;
-
-		dev = dev_get_by_index(&init_net, dtls_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, dtls_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,
-					     dtls_session_stats[id].if_num);
-		}
-
-		for (i = 0; i < NSS_STATS_DTLS_SESSION_MAX; i++) {
-			size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
-					     "\t%s = %llu\n",
-					     nss_stats_str_dtls_session_debug_stats[i],
-					     dtls_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,
-			     "\nDTLS session stats end\n");
-	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, size_wr);
-
-	kfree(dtls_session_stats);
-	kfree(lbuf);
-	return bytes_read;
-}
-
-/*
- * nss_stats_gre_tunnel_read()
- *	Read GRE Tunnel session statistics
- */
-static ssize_t nss_stats_gre_tunnel_read(struct file *fp, char __user *ubuf,
-				   size_t sz, loff_t *ppos)
-{
-	uint32_t max_output_lines = 2 + (NSS_MAX_GRE_TUNNEL_SESSIONS
-					* (NSS_STATS_GRE_TUNNEL_SESSION_MAX + 2)) + 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;
-	int id, i;
-	struct nss_stats_gre_tunnel_session_debug *gre_tunnel_session_stats = NULL;
-
-	char *lbuf = kzalloc(size_al, GFP_KERNEL);
-	if (unlikely(lbuf == NULL)) {
-		nss_warning("Could not allocate memory for local statistics buffer");
-		return 0;
-	}
-
-	gre_tunnel_session_stats = kzalloc((sizeof(struct nss_stats_gre_tunnel_session_debug)
-				     * NSS_MAX_GRE_TUNNEL_SESSIONS), GFP_KERNEL);
-	if (unlikely(gre_tunnel_session_stats == NULL)) {
-		nss_warning("Could not allocate memory for populating GRE Tunnel stats");
-		kfree(lbuf);
-		return 0;
-	}
-
-	/*
-	 * Get all stats
-	 */
-	nss_gre_tunnel_session_debug_stats_get(gre_tunnel_session_stats);
-
-	/*
-	 * Session stats
-	 */
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
-			     "\nGRE Tunnel session stats start:\n\n");
-
-	for (id = 0; id < NSS_MAX_GRE_TUNNEL_SESSIONS; id++) {
-		if (!gre_tunnel_session_stats[id].valid)
-			break;
-
-		dev = dev_get_by_index(&init_net, gre_tunnel_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, gre_tunnel_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,
-					     gre_tunnel_session_stats[id].if_num);
-		}
-
-		for (i = 0; i < NSS_STATS_GRE_TUNNEL_SESSION_MAX; i++) {
-			size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
-					     "\t%s = %llu\n",
-					     nss_stats_str_gre_tunnel_session_debug_stats[i],
-					     gre_tunnel_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,
-			     "\nGRE Tunnel session stats end\n");
-	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, size_wr);
-
-	kfree(gre_tunnel_session_stats);
-	kfree(lbuf);
-	return bytes_read;
-}
-
-/*
- * nss_stats_l2tpv2_read()
- *	Read l2tpv2 statistics
- */
-static ssize_t nss_stats_l2tpv2_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
-{
-
-	uint32_t max_output_lines = 2 /* header & footer for session stats */
-					+ NSS_MAX_L2TPV2_DYNAMIC_INTERFACES * (NSS_STATS_L2TPV2_SESSION_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_l2tpv2_session_debug l2tpv2_session_stats[NSS_MAX_L2TPV2_DYNAMIC_INTERFACES];
-	int id, i;
-
-	char *lbuf = kzalloc(size_al, GFP_KERNEL);
-	if (unlikely(lbuf == NULL)) {
-		nss_warning("Could not allocate memory for local statistics buffer");
-		return 0;
-	}
-
-	memset(&l2tpv2_session_stats, 0, sizeof(struct nss_stats_l2tpv2_session_debug) * NSS_MAX_L2TPV2_DYNAMIC_INTERFACES);
-
-	/*
-	 * Get all stats
-	 */
-	nss_l2tpv2_session_debug_stats_get((void *)&l2tpv2_session_stats);
-
-	/*
-	 * Session stats
-	 */
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nl2tp v2 session stats start:\n\n");
-	for (id = 0; id < NSS_MAX_L2TPV2_DYNAMIC_INTERFACES; id++) {
-
-			if (!l2tpv2_session_stats[id].valid) {
-				break;
-			}
-
-			dev = dev_get_by_index(&init_net, l2tpv2_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,
-						l2tpv2_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,
-						l2tpv2_session_stats[id].if_num);
-			}
-
-			for (i = 0; i < NSS_STATS_L2TPV2_SESSION_MAX; i++) {
-				size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
-						     "\t%s = %llu\n", nss_stats_str_l2tpv2_session_debug_stats[i],
-						      l2tpv2_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, "\nl2tp v2 session stats end\n");
-	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, size_wr);
-
-	kfree(lbuf);
-	return bytes_read;
-}
-
-/*
- * nss_stats_map_t_read()
- *	Read map_t statistics
- */
-static ssize_t nss_stats_map_t_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
-{
-
-	uint32_t max_output_lines = 2 /* header & footer for instance stats */
-					+ NSS_MAX_MAP_T_DYNAMIC_INTERFACES * (NSS_STATS_MAP_T_MAX + 2) /*instance 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_map_t_instance_debug map_t_instance_stats[NSS_MAX_MAP_T_DYNAMIC_INTERFACES];
-	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;
-	}
-
-	memset(&map_t_instance_stats, 0, sizeof(struct nss_stats_map_t_instance_debug) * NSS_MAX_MAP_T_DYNAMIC_INTERFACES);
-
-	/*
-	 * Get all stats
-	 */
-	nss_map_t_instance_debug_stats_get((void *)&map_t_instance_stats);
-
-	/*
-	 * Session stats
-	 */
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nmap_t instance stats start:\n\n");
-	for (id = 0; id < NSS_MAX_MAP_T_DYNAMIC_INTERFACES; id++) {
-
-			if (!map_t_instance_stats[id].valid) {
-				break;
-			}
-
-			dev = dev_get_by_index(&init_net, map_t_instance_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,
-						map_t_instance_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,
-						map_t_instance_stats[id].if_num);
-			}
-
-			for (i = 0; i < NSS_STATS_MAP_T_MAX; i++) {
-				size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
-						     "\t%s = %llu\n", nss_stats_str_map_t_instance_debug_stats[i],
-						      map_t_instance_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, "\nmap_t instance stats end\n");
-	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, size_wr);
-
-	kfree(lbuf);
-	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
- */
-static ssize_t nss_stats_ppe_conn_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
-{
-
-	int i;
-	char *lbuf = NULL;
-	size_t size_wr = 0;
-	ssize_t bytes_read = 0;
-	uint32_t ppe_stats[NSS_STATS_PPE_CONN_MAX];
-	uint32_t max_output_lines = 2 /* header & footer for session stats */
-				+ NSS_STATS_PPE_CONN_MAX /* PPE flow counters */
-				+ 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");
-		return 0;
-	}
-
-	memset(&ppe_stats, 0, sizeof(uint32_t) * NSS_STATS_PPE_CONN_MAX);
-
-	/*
-	 * Get all stats
-	 */
-	nss_ppe_stats_conn_get(ppe_stats);
-
-	/*
-	 * flow stats
-	 */
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nppe flow counters start:\n\n");
-
-	for (i = 0; i < NSS_STATS_PPE_CONN_MAX; i++) {
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
-				"\t%s = %u\n", nss_stats_str_ppe_conn[i],
-				ppe_stats[i]);
-	}
-
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\n");
-
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nppe flow counters end\n");
-	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, size_wr);
-
-	kfree(lbuf);
-	return bytes_read;
-}
-
-/*
- * nss_stats_ppe_l3_read()
- *	Read ppe L3 debug stats
- */
-static ssize_t nss_stats_ppe_l3_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
-{
-
-	int i;
-	char *lbuf = NULL;
-	size_t size_wr = 0;
-	ssize_t bytes_read = 0;
-	uint32_t ppe_stats[NSS_STATS_PPE_L3_MAX];
-	uint32_t max_output_lines = 2 /* header & footer for session stats */
-				+ NSS_STATS_PPE_L3_MAX /* PPE flow counters */
-				+ 2;
-	size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
-
-	lbuf = kzalloc(size_al, GFP_KERNEL);
-	if (unlikely(!lbuf)) {
-		nss_warning("Could not allocate memory for local statistics buffer");
-		return 0;
-	}
-
-	memset(ppe_stats, 0, sizeof(uint32_t) * NSS_STATS_PPE_L3_MAX);
-
-	/*
-	 * Get all stats
-	 */
-	nss_ppe_stats_l3_get(ppe_stats);
-
-	/*
-	 * flow stats
-	 */
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nppe l3 debug stats start:\n\n");
-
-	for (i = 0; i < NSS_STATS_PPE_L3_MAX; i++) {
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
-				"\t%s = 0x%x\n", nss_stats_str_ppe_l3[i],
-				ppe_stats[i]);
-	}
-
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\n");
-
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nppe l3 debug stats end\n");
-	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, size_wr);
-
-	kfree(lbuf);
-	return bytes_read;
-}
-
-/*
- * nss_stats_ppe_code_read()
- *	Read ppe CPU & DROP code
- */
-static ssize_t nss_stats_ppe_code_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
-{
-
-	int i;
-	char *lbuf = NULL;
-	size_t size_wr = 0;
-	ssize_t bytes_read = 0;
-	uint32_t ppe_stats[NSS_STATS_PPE_CODE_MAX];
-	uint32_t max_output_lines = 2 /* header & footer for session stats */
-				+ NSS_STATS_PPE_CODE_MAX /* PPE flow counters */
-				+ 2;
-	size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
-
-	lbuf = kzalloc(size_al, GFP_KERNEL);
-	if (unlikely(!lbuf)) {
-		nss_warning("Could not allocate memory for local statistics buffer");
-		return 0;
-	}
-
-	memset(ppe_stats, 0, sizeof(uint32_t) * NSS_STATS_PPE_CODE_MAX);
-
-	/*
-	 * Get all stats
-	 */
-	nss_ppe_stats_code_get(ppe_stats);
-
-	/*
-	 * flow stats
-	 */
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nppe session stats start:\n\n");
-
-	for (i = 0; i < NSS_STATS_PPE_CODE_MAX; i++) {
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
-				"\t%s = %u\n", nss_stats_str_ppe_code[i],
-				ppe_stats[i]);
-	}
-
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\n");
-
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nppe session stats end\n");
-	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, size_wr);
-
-	kfree(lbuf);
-	return bytes_read;
-}
-
-/*
- * nss_stats_ppe_port_dc_read()
- *	Read PPE per port drop code stats
- */
-static ssize_t nss_stats_ppe_port_dc_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
-{
-	int32_t i;
-
-	/*
-	 * max output lines = #stats + 2 start tag line + 2 end tag line + five blank lines
-	 */
-	uint32_t max_output_lines = (NSS_STATS_PPE_DROP_CODE_MAX + 4) + 5;
-	size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
-	size_t size_wr = 0;
-	ssize_t bytes_read = 0;
-	struct nss_stats_data *data = fp->private_data;
-	uint32_t *ppe_stats;
-
-	char *lbuf = kzalloc(size_al, GFP_KERNEL);
-	if (unlikely(lbuf == NULL)) {
-		nss_warning("Could not allocate memory for local statistics buffer");
-		return 0;
-	}
-
-	ppe_stats = kzalloc(sizeof(uint32_t) * NSS_STATS_PPE_DROP_CODE_MAX, GFP_KERNEL);
-	if (unlikely(ppe_stats == NULL)) {
-		kfree(lbuf);
-		nss_warning("Could not allocate memory for ppe stats buffer");
-		return 0;
-	}
-
-	/*
-	 * Get drop code counters for specific port
-	 */
-	nss_ppe_port_drop_code_get(ppe_stats, data->edma_id);
-	size_wr = scnprintf(lbuf, size_al, "ppe no drop code stats start:\n\n");
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
-				"\t%s = %u\n", nss_stats_str_ppe_dc[0],
-				ppe_stats[0]);
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nppe no drop code stats end\n\n");
-
-	/*
-	 * Drop code stats
-	 */
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "ppe non-zero drop code stats start:\n\n");
-	for (i = 1; i < NSS_STATS_PPE_DROP_CODE_MAX; i++) {
-		/*
-		 * Print only non-zero stats.
-		 */
-		if (!ppe_stats[i]) {
-			continue;
-		}
-
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
-				"\t%s = %u\n", nss_stats_str_ppe_dc[i],
-				ppe_stats[i]);
-	}
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nppe non-zero drop code stats end\n\n");
-
-	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
-	kfree(ppe_stats);
-	kfree(lbuf);
-
-	return bytes_read;
-}
-
-/*
- * nss_stats_ppe_exception_cc_read()
- *	Read PPE CPU code stats specific to flow exceptions
- */
-static ssize_t nss_stats_ppe_exception_cc_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
-{
-	int32_t i;
-
-	/*
-	 * max output lines = #stats + start tag line + end tag line + three blank lines
-	 */
-	uint32_t max_output_lines = (NSS_STATS_PPE_CPU_CODE_EXCEPTION_MAX + 2) + 3;
-	size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
-	size_t size_wr = 0;
-	ssize_t bytes_read = 0;
-	uint32_t *ppe_stats;
-
-	char *lbuf = kzalloc(size_al, GFP_KERNEL);
-	if (unlikely(lbuf == NULL)) {
-		nss_warning("Could not allocate memory for local statistics buffer");
-		return 0;
-	}
-
-	ppe_stats = kzalloc(sizeof(uint32_t) * NSS_STATS_PPE_CPU_CODE_EXCEPTION_MAX, GFP_KERNEL);
-	if (unlikely(ppe_stats == NULL)) {
-		kfree(lbuf);
-		nss_warning("Could not allocate memory for ppe stats buffer");
-		return 0;
-	}
-
-	/*
-	 * Get CPU code counters for flow specific exceptions
-	 */
-	nss_ppe_cpu_code_exception_get(ppe_stats);
-
-	size_wr = scnprintf(lbuf, size_al, "ppe non-zero cpu code flow-exception stats start:\n\n");
-
-	/*
-	 * CPU code stats
-	 */
-	for (i = 0; i < NSS_STATS_PPE_CPU_CODE_EXCEPTION_MAX; i++) {
-		/*
-		 * Print only non-zero stats.
-		 */
-		if (!ppe_stats[i]) {
-			continue;
-		}
-
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
-				"\t%s = %u\n", nss_stats_str_ppe_cc[i],
-				ppe_stats[i]);
-	}
-
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nppe non-zero cpu code flow-exception stats end\n\n");
-	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
-	kfree(ppe_stats);
-	kfree(lbuf);
-
-	return bytes_read;
-}
-
-/*
- * nss_stats_ppe_nonexception_cc_read()
- *	Read PPE CPU code stats for other than flow exceptions
- */
-static ssize_t nss_stats_ppe_nonexception_cc_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
-{
-	int32_t i;
-
-	/*
-	 * max output lines = #stats + start tag line + end tag line + three blank lines
-	 */
-	uint32_t max_output_lines = (NSS_STATS_PPE_CPU_CODE_NONEXCEPTION_MAX + 2) + 3;
-	size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
-	size_t size_wr = 0;
-	ssize_t bytes_read = 0;
-	uint32_t *ppe_stats;
-
-	char *lbuf = kzalloc(size_al, GFP_KERNEL);
-	if (unlikely(lbuf == NULL)) {
-		nss_warning("Could not allocate memory for local statistics buffer");
-		return 0;
-	}
-
-	ppe_stats = kzalloc(sizeof(uint32_t) * NSS_STATS_PPE_CPU_CODE_NONEXCEPTION_MAX, GFP_KERNEL);
-	if (unlikely(ppe_stats == NULL)) {
-		kfree(lbuf);
-		nss_warning("Could not allocate memory for ppe stats buffer");
-		return 0;
-	}
-
-	/*
-	 * Get CPU code counters for non flow exceptions
-	 */
-	nss_ppe_cpu_code_nonexception_get(ppe_stats);
-
-	/*
-	 * CPU code stats
-	 */
-	size_wr = scnprintf(lbuf, size_al, "ppe non-zero cpu code non-flow exception stats start:\n\n");
-	for (i = 0; i < NSS_STATS_PPE_CPU_CODE_NONEXCEPTION_MAX; i++) {
-		/*
-		 * Print only non-zero stats.
-		 */
-		if (!ppe_stats[i]) {
-			continue;
-		}
-
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
-				"\t%s = %u\n", nss_stats_str_ppe_cc[i + NSS_STATS_PPE_CPU_CODE_NONEXCEPTION_START],
-				ppe_stats[i]);
-	}
-
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nppe non-zero cpu code non-flow exception stats end\n\n");
-	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
-	kfree(ppe_stats);
-	kfree(lbuf);
-
-	return bytes_read;
-}
-
-/*
- * nss_stats_pptp_read()
- *	Read pptp statistics
- */
-static ssize_t nss_stats_pptp_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
-{
-
-	uint32_t max_output_lines = 2 /* header & footer for session stats */
-					+ NSS_MAX_PPTP_DYNAMIC_INTERFACES * (NSS_STATS_PPTP_SESSION_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_pptp_session_debug pptp_session_stats[NSS_MAX_PPTP_DYNAMIC_INTERFACES];
-	int id, i;
-
-	char *lbuf = kzalloc(size_al, GFP_KERNEL);
-	if (unlikely(lbuf == NULL)) {
-		nss_warning("Could not allocate memory for local statistics buffer");
-		return 0;
-	}
-
-	memset(&pptp_session_stats, 0, sizeof(struct nss_stats_pptp_session_debug) * NSS_MAX_PPTP_DYNAMIC_INTERFACES);
-
-	/*
-	 * Get all stats
-	 */
-	nss_pptp_session_debug_stats_get((void *)&pptp_session_stats);
-
-	/*
-	 * Session stats
-	 */
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\npptp session stats start:\n\n");
-	for (id = 0; id < NSS_MAX_PPTP_DYNAMIC_INTERFACES; id++) {
-
-			if (!pptp_session_stats[id].valid) {
-				break;
-			}
-
-			dev = dev_get_by_index(&init_net, pptp_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,
-						pptp_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,
-						pptp_session_stats[id].if_num);
-			}
-
-			for (i = 0; i < NSS_STATS_PPTP_SESSION_MAX; i++) {
-				size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
-						     "\t%s = %llu\n", nss_stats_str_pptp_session_debug_stats[i],
-						      pptp_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, "\npptp session stats end\n");
-	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, size_wr);
-
-	kfree(lbuf);
-	return bytes_read;
-}
-
-/*
- * nss_stats_sjack_read()
- *	Read SJACK stats
- */
-static ssize_t nss_stats_sjack_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
-{
-	int32_t i;
-	/*
-	 * max output lines = #stats + start tag line + end tag line + three blank lines
-	 */
-	uint32_t max_output_lines = NSS_STATS_NODE_MAX + 5;
-	size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
-	size_t size_wr = 0;
-	ssize_t bytes_read = 0;
-	uint64_t *stats_shadow;
-
-	char *lbuf = kzalloc(size_al, GFP_KERNEL);
-	if (unlikely(lbuf == NULL)) {
-		nss_warning("Could not allocate memory for local statistics buffer");
-		return 0;
-	}
-
-	stats_shadow = kzalloc(NSS_STATS_NODE_MAX * 8, GFP_KERNEL);
-	if (unlikely(stats_shadow == NULL)) {
-		nss_warning("Could not allocate memory for local shadow buffer");
-		kfree(lbuf);
-		return 0;
-	}
-
-	size_wr = scnprintf(lbuf, size_al, "sjack stats start:\n\n");
-
-	/*
-	 * Common node stats
-	 */
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "common node stats:\n\n");
-	spin_lock_bh(&nss_top_main.stats_lock);
-	for (i = 0; (i < NSS_STATS_NODE_MAX); i++) {
-		stats_shadow[i] = nss_top_main.stats_node[NSS_SJACK_INTERFACE][i];
-	}
-
-	spin_unlock_bh(&nss_top_main.stats_lock);
-
-	for (i = 0; (i < NSS_STATS_NODE_MAX); i++) {
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
-					"%s = %llu\n", nss_stats_str_node[i], stats_shadow[i]);
-	}
-
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nsjack stats end\n\n");
-
-	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
-	kfree(lbuf);
-	kfree(stats_shadow);
-
-	return bytes_read;
-}
-
-/*
- * nss_stats_portid_read()
- *	Read PortID stats
- */
-static ssize_t nss_stats_portid_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
-{
-	int32_t i;
-	/*
-	 * max output lines = #stats + start tag line + end tag line + three blank lines
-	 */
-	uint32_t max_output_lines = NSS_STATS_NODE_MAX + NSS_STATS_PORTID_MAX + 5;
-	size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
-	size_t size_wr = 0;
-	ssize_t bytes_read = 0;
-	uint64_t *stats_shadow;
-
-	char *lbuf = kzalloc(size_al, GFP_KERNEL);
-	if (unlikely(lbuf == NULL)) {
-		nss_warning("Could not allocate memory for local statistics buffer");
-		return 0;
-	}
-
-	stats_shadow = kzalloc(NSS_STATS_NODE_MAX * 8, GFP_KERNEL);
-	if (unlikely(stats_shadow == NULL)) {
-		nss_warning("Could not allocate memory for local shadow buffer");
-		kfree(lbuf);
-		return 0;
-	}
-
-	size_wr = scnprintf(lbuf, size_al, "portid stats start:\n\n");
-
-	/*
-	 * Common node stats
-	 */
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "common node stats:\n\n");
-	spin_lock_bh(&nss_top_main.stats_lock);
-	for (i = 0; (i < NSS_STATS_NODE_MAX); i++) {
-		stats_shadow[i] = nss_top_main.stats_node[NSS_PORTID_INTERFACE][i];
-	}
-
-	spin_unlock_bh(&nss_top_main.stats_lock);
-
-	for (i = 0; (i < NSS_STATS_NODE_MAX); i++) {
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
-					"%s = %llu\n", nss_stats_str_node[i], stats_shadow[i]);
-	}
-
-	/*
-	 * PortID node stats
-	 */
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nportid node stats:\n\n");
-
-	spin_lock_bh(&nss_top_main.stats_lock);
-	for (i = 0; (i < NSS_STATS_PORTID_MAX); i++) {
-		stats_shadow[i] = nss_top_main.stats_portid[i];
-	}
-
-	spin_unlock_bh(&nss_top_main.stats_lock);
-
-	for (i = 0; (i < NSS_STATS_PORTID_MAX); i++) {
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
-					"%s = %llu\n", nss_stats_str_portid[i], stats_shadow[i]);
-	}
-
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nportid stats end\n\n");
-
-	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
-	kfree(lbuf);
-	kfree(stats_shadow);
-
-	return bytes_read;
-}
-
-/*
- * nss_stats_capwap_encap()
- *	Make a row for CAPWAP encap stats.
- */
-static ssize_t nss_stats_capwap_encap(char *line, int len, int i, struct nss_capwap_tunnel_stats *s)
-{
-	char *header[] = { "packets", "bytes", "fragments", "drop_ref", "drop_ver", "drop_unalign",
-			"drop_hroom", "drop_dtls", "drop_nwireless", "drop_qfull", "drop_memfail", "unknown" };
-	uint64_t tcnt = 0;
-
-	switch (i) {
-	case 0:
-		tcnt = s->pnode_stats.tx_packets;
-		break;
-	case 1:
-		tcnt = s->pnode_stats.tx_bytes;
-		break;
-	case 2:
-		tcnt = s->tx_segments;
-		break;
-	case 3:
-		tcnt = s->tx_dropped_sg_ref;
-		break;
-	case 4:
-		tcnt = s->tx_dropped_ver_mis;
-		break;
-	case 5:
-		tcnt = s->tx_dropped_unalign;
-		break;
-	case 6:
-		tcnt = s->tx_dropped_hroom;
-		break;
-	case 7:
-		tcnt = s->tx_dropped_dtls;
-		break;
-	case 8:
-		tcnt = s->tx_dropped_nwireless;
-		break;
-	case 9:
-		tcnt = s->tx_queue_full_drops;
-		break;
-	case 10:
-		tcnt = s->tx_mem_failure_drops;
-		break;
-	default:
-		return 0;
-	}
-
-	return (snprintf(line, len, "%s = %llu\n", header[i], tcnt));
-}
-
-/*
- * nss_stats_capwap_decap()
- *	Make a row for CAPWAP decap stats.
- */
-static ssize_t nss_stats_capwap_decap(char *line, int len, int i, struct nss_capwap_tunnel_stats *s)
-{
-	char *header[] = { "packets", "bytes", "DTLS_pkts", "fragments", "rx_dropped", "drop_oversize",
-		"drop_frag_timeout", "drop_frag_dup", "drop_frag_gap", "drop_qfull", "drop_memfail",
-		"drop_csum", "drop_malformed", "unknown" };
-	uint64_t tcnt = 0;
-
-	switch (i) {
-	case 0:
-		tcnt = s->pnode_stats.rx_packets;
-		break;
-	case 1:
-		tcnt = s->pnode_stats.rx_bytes;
-		break;
-	case 2:
-		tcnt = s->dtls_pkts;
-		break;
-	case 3:
-		tcnt = s->rx_segments;
-		break;
-	case 4:
-		tcnt = s->pnode_stats.rx_dropped;
-		break;
-	case 5:
-		tcnt = s->rx_oversize_drops;
-		break;
-	case 6:
-		tcnt = s->rx_frag_timeout_drops;
-		break;
-	case 7:
-		tcnt = s->rx_dup_frag;
-		break;
-	case 8:
-		tcnt = s->rx_frag_gap_drops;
-		break;
-	case 9:
-		tcnt = s->rx_queue_full_drops;
-		return (snprintf(line, len, "%s = %llu (n2h = %llu)\n", header[i], tcnt, s->rx_n2h_queue_full_drops));
-	case 10:
-		tcnt = s->rx_mem_failure_drops;
-		break;
-	case 11:
-		tcnt = s->rx_csum_drops;
-		break;
-	case 12:
-		tcnt = s->rx_malformed;
-		break;
-	default:
-		return 0;
-	}
-
-	return (snprintf(line, len, "%s = %llu\n", header[i], tcnt));
-}
-
-/*
- * nss_stats_capwap_read()
- *	Read CAPWAP stats
- */
-static ssize_t nss_stats_capwap_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos, uint16_t type)
-{
-	struct nss_stats_data *data = fp->private_data;
-	ssize_t bytes_read = 0;
-	struct nss_capwap_tunnel_stats stats;
-	size_t bytes;
-	char line[80];
-	int start;
-	uint32_t if_num = NSS_DYNAMIC_IF_START;
-	uint32_t max_if_num = NSS_DYNAMIC_IF_START + NSS_MAX_DYNAMIC_INTERFACES;
-
-	if (data) {
-		if_num = data->if_num;
-	}
-
-	/*
-	 * If we are done accomodating all the CAPWAP tunnels.
-	 */
-	if (if_num > max_if_num) {
-		return 0;
-	}
-
-	for (; if_num <= max_if_num; if_num++) {
-		bool isthere;
-
-		if (nss_is_dynamic_interface(if_num) == false) {
-			continue;
-		}
-
-		if (nss_dynamic_interface_get_type(nss_capwap_get_ctx(), if_num) != NSS_DYNAMIC_INTERFACE_TYPE_CAPWAP) {
-			continue;
-		}
-
-		/*
-		 * If CAPWAP tunnel does not exists, then isthere will be false.
-		 */
-		isthere = nss_capwap_get_stats(if_num, &stats);
-		if (!isthere) {
-			continue;
-		}
-
-		bytes = snprintf(line, sizeof(line), "----if_num : %2d----\n", if_num);
-		if ((bytes_read + bytes) > sz) {
-			break;
-		}
-
-		if (copy_to_user(ubuf + bytes_read, line, bytes) != 0) {
-			bytes_read = -EFAULT;
-			goto fail;
-		}
-		bytes_read += bytes;
-		start = 0;
-		while (bytes_read < sz) {
-			if (type == 1) {
-				bytes = nss_stats_capwap_encap(line, sizeof(line), start, &stats);
-			} else {
-				bytes = nss_stats_capwap_decap(line, sizeof(line), start, &stats);
-			}
-
-			/*
-			 * If we don't have any more lines in decap/encap.
-			 */
-			if (bytes == 0) {
-				break;
-			}
-
-			if ((bytes_read + bytes) > sz)
-				break;
-
-			if (copy_to_user(ubuf + bytes_read, line, bytes) != 0) {
-				bytes_read = -EFAULT;
-				goto fail;
-			}
-
-			bytes_read += bytes;
-			start++;
-		}
-	}
-
-	if (bytes_read > 0) {
-		*ppos = bytes_read;
-	}
-
-	if (data) {
-		data->if_num = if_num;
-	}
-fail:
-	return bytes_read;
-}
-
-/*
- * nss_stats_capwap_decap_read()
- *	Read CAPWAP decap stats
- */
-static ssize_t nss_stats_capwap_decap_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
-{
-	return (nss_stats_capwap_read(fp, ubuf, sz, ppos, 0));
-}
-
-/*
- * nss_stats_capwap_encap_read()
- *	Read CAPWAP encap stats
- */
-static ssize_t nss_stats_capwap_encap_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
-{
-	return (nss_stats_capwap_read(fp, ubuf, sz, ppos, 1));
-}
-
-/*
- * nss_stats_gre_redir()
- *	Make a row for GRE_REDIR stats.
- */
-static ssize_t nss_stats_gre_redir(char *line, int len, int i, struct nss_gre_redir_tunnel_stats *s)
-{
-	char *header[] = { "TX Packets", "TX Bytes", "TX Drops", "RX Packets", "RX Bytes" };
-	char name[20];
-	uint64_t tcnt = 0;
-	int j = 0;
-
-	switch (i) {
-	case 0:
-		return snprintf(line, len, "%s = %u\n", header[i], s->node_stats.tx_packets);
-	case 1:
-		return snprintf(line, len, "%s = %u\n", header[i], s->node_stats.tx_bytes);
-	case 2:
-		return snprintf(line, len, "%s = %u\n", header[i], s->tx_dropped);
-	case 3:
-		return snprintf(line, len, "%s = %u\n", header[i], s->node_stats.rx_packets);
-	case 4:
-		return snprintf(line, len, "%s = %u\n", header[i], s->node_stats.rx_bytes);
-	case 5:
-		for (j = 0; j < NSS_MAX_NUM_PRI; j++) {
-			scnprintf(name, 20, "Rx Queue %d Drops", j);
-			tcnt += snprintf(line, len, "%s = %u\n", name, s->node_stats.rx_dropped[j]);
-		}
-		return tcnt;
-
-	default:
-		return 0;
-	}
-
-}
-
-/*
- * nss_stats_gre_redir_read()
- *	READ gre_redir tunnel stats.
- */
-static ssize_t nss_stats_gre_redir_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
-{
-	struct nss_stats_data *data = fp->private_data;
-	ssize_t bytes_read = 0;
-	struct nss_gre_redir_tunnel_stats stats;
-	size_t bytes;
-	char line[80 * NSS_MAX_NUM_PRI];
-	int start, end;
-	int index = 0;
-
-	if (data) {
-		index = data->index;
-	}
-
-	/*
-	 * If we are done accomodating all the GRE_REDIR tunnels.
-	 */
-	if (index >= NSS_GRE_REDIR_MAX_INTERFACES) {
-		return 0;
-	}
-
-	for (; index < NSS_GRE_REDIR_MAX_INTERFACES; index++) {
-		bool isthere;
-
-		/*
-		 * If gre_redir tunnel does not exists, then isthere will be false.
-		 */
-		isthere = nss_gre_redir_get_stats(index, &stats);
-		if (!isthere) {
-			continue;
-		}
-
-		bytes = snprintf(line, sizeof(line), "\nTunnel if_num: %2d\n", stats.if_num);
-		if ((bytes_read + bytes) > sz) {
-			break;
-		}
-
-		if (copy_to_user(ubuf + bytes_read, line, bytes) != 0) {
-			bytes_read = -EFAULT;
-			goto fail;
-		}
-		bytes_read += bytes;
-		start = 0;
-		end = 6;
-		while (bytes_read < sz && start < end) {
-			bytes = nss_stats_gre_redir(line, sizeof(line), start, &stats);
-
-			if ((bytes_read + bytes) > sz)
-				break;
-
-			if (copy_to_user(ubuf + bytes_read, line, bytes) != 0) {
-				bytes_read = -EFAULT;
-				goto fail;
-			}
-
-			bytes_read += bytes;
-			start++;
-		}
-	}
-
-	if (bytes_read > 0) {
-		*ppos = bytes_read;
-	}
-
-	if (data) {
-		data->index = index;
-	}
-
-fail:
-	return bytes_read;
-}
-
-/*
- * nss_stats_wifi_if_read()
- *	Read wifi_if statistics
- */
-static ssize_t nss_stats_wifi_if_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
-{
-	struct nss_stats_data *data = fp->private_data;
-	struct nss_ctx_instance *nss_ctx = (struct nss_ctx_instance *)&nss_top_main.nss[nss_top_main.wifi_handler_id];
-	int32_t if_num = NSS_DYNAMIC_IF_START;
-	int32_t max_if_num = if_num + NSS_MAX_DYNAMIC_INTERFACES;
-	size_t bytes = 0;
-	ssize_t bytes_read = 0;
-	char line[80];
-	int start, end;
-
-	if (data) {
-		if_num = data->if_num;
-	}
-
-	if (if_num > max_if_num) {
-		return 0;
-	}
-
-	for (; if_num < max_if_num; if_num++) {
-		if (nss_dynamic_interface_get_type(nss_ctx, if_num) != NSS_DYNAMIC_INTERFACE_TYPE_WIFI)
-			continue;
-
-		bytes = scnprintf(line, sizeof(line), "if_num %d stats start:\n\n", if_num);
-		if ((bytes_read + bytes) > sz)
-			break;
-
-		if (copy_to_user(ubuf + bytes_read, line, bytes) != 0) {
-			bytes_read = -EFAULT;
-			goto end;
-		}
-
-		bytes_read += bytes;
-
-		start = 0;
-		end = 7;
-		while (bytes_read < sz && start < end) {
-			bytes = nss_wifi_if_copy_stats(if_num, start, line);
-			if (!bytes)
-				break;
-
-			if ((bytes_read + bytes) > sz)
-				break;
-
-			if (copy_to_user(ubuf + bytes_read, line, bytes) != 0) {
-				bytes_read = -EFAULT;
-				goto end;
-			}
-
-			bytes_read += bytes;
-			start++;
-		}
-
-		bytes = scnprintf(line, sizeof(line), "if_num %d stats end:\n\n", if_num);
-		if (bytes_read > (sz - bytes))
-			break;
-
-		if (copy_to_user(ubuf + bytes_read, line, bytes) != 0) {
-			bytes_read = -EFAULT;
-			goto end;
-		}
-
-		bytes_read += bytes;
-	}
-
-	if (bytes_read > 0) {
-		*ppos = bytes_read;
-	}
-
-	if (data) {
-		data->if_num = if_num;
-	}
-
-end:
-	return bytes_read;
-}
-
-/*
- * nss_stats_virt_if_read()
- *	Read virt_if statistics
- */
-static ssize_t nss_stats_virt_if_read(struct file *fp, char __user *ubuf,
-						size_t sz, loff_t *ppos)
-{
-	struct nss_stats_data *data = fp->private_data;
-	struct nss_ctx_instance *nss_ctx = (struct nss_ctx_instance *)&nss_top_main.nss[nss_top_main.wifi_handler_id];
-	int32_t if_num = NSS_DYNAMIC_IF_START;
-	int32_t max_if_num = if_num + NSS_MAX_DYNAMIC_INTERFACES;
-	size_t bytes = 0;
-	ssize_t bytes_read = 0;
-	char line[80];
-	int start, end;
-
-	if (data) {
-		if_num = data->if_num;
-	}
-
-	if (if_num > max_if_num) {
-		return 0;
-	}
-
-	for (; if_num < max_if_num; if_num++) {
-		if (nss_dynamic_interface_get_type(nss_ctx, if_num) != NSS_DYNAMIC_INTERFACE_TYPE_802_3_REDIR)
-			continue;
-
-		bytes = scnprintf(line, sizeof(line), "if_num %d stats start:\n\n", if_num);
-		if ((bytes_read + bytes) > sz)
-			break;
-
-		if (copy_to_user(ubuf + bytes_read, line, bytes) != 0) {
-			bytes_read = -EFAULT;
-			goto end;
-		}
-
-		bytes_read += bytes;
-
-		start = 0;
-		end = 7;
-		while (bytes_read < sz && start < end) {
-			bytes = nss_virt_if_copy_stats(if_num, start, line);
-			if (!bytes)
-				break;
-
-			if ((bytes_read + bytes) > sz)
-				break;
-
-			if (copy_to_user(ubuf + bytes_read, line, bytes) != 0) {
-				bytes_read = -EFAULT;
-				goto end;
-			}
-
-			bytes_read += bytes;
-			start++;
-		}
-
-		bytes = scnprintf(line, sizeof(line), "if_num %d stats end:\n\n", if_num);
-		if (bytes_read > (sz - bytes))
-			break;
-
-		if (copy_to_user(ubuf + bytes_read, line, bytes) != 0) {
-			bytes_read = -EFAULT;
-			goto end;
-		}
-
-		bytes_read += bytes;
-	}
-
-	if (bytes_read > 0) {
-		*ppos = bytes_read;
-	}
-
-	if (data) {
-		data->if_num = if_num;
-	}
-
-end:
-	return bytes_read;
-}
-
-/*
- * nss_stats_tx_rx_virt_if_read()
- *	Read tx_rx_virt_if statistics
- */
-static ssize_t nss_stats_tx_rx_virt_if_read(struct file *fp, char __user *ubuf,
-						size_t sz, loff_t *ppos)
-{
-	struct nss_stats_data *data = fp->private_data;
-	struct nss_ctx_instance *nss_ctx = (struct nss_ctx_instance *)&nss_top_main.nss[nss_top_main.wifi_handler_id];
-	int32_t if_num = NSS_DYNAMIC_IF_START;
-	int32_t max_if_num = if_num + NSS_MAX_DYNAMIC_INTERFACES;
-	size_t bytes = 0;
-	ssize_t bytes_read = 0;
-	char line[80];
-	int start, end;
-
-	if (data) {
-		if_num = data->if_num;
-	}
-
-	if (if_num > max_if_num) {
-		return 0;
-	}
-
-	for (; if_num < max_if_num; if_num++) {
-		if (nss_dynamic_interface_get_type(nss_ctx, if_num) != NSS_DYNAMIC_INTERFACE_TYPE_VIRTIF_DEPRECATED)
-			continue;
-
-		bytes = scnprintf(line, sizeof(line), "if_num %d stats start:\n\n", if_num);
-		if ((bytes_read + bytes) > sz)
-			break;
-
-		if (copy_to_user(ubuf + bytes_read, line, bytes) != 0) {
-			bytes_read = -EFAULT;
-			goto end;
-		}
-
-		bytes_read += bytes;
-
-		start = 0;
-		end = 7;
-		while (bytes_read < sz && start < end) {
-			bytes = nss_tx_rx_virt_if_copy_stats(if_num, start, line);
-			if (!bytes)
-				break;
-
-			if ((bytes_read + bytes) > sz)
-				break;
-
-			if (copy_to_user(ubuf + bytes_read, line, bytes) != 0) {
-				bytes_read = -EFAULT;
-				goto end;
-			}
-
-			bytes_read += bytes;
-			start++;
-		}
-
-		bytes = scnprintf(line, sizeof(line), "if_num %d stats end:\n\n", if_num);
-		if (bytes_read > (sz - bytes))
-			break;
-
-		if (copy_to_user(ubuf + bytes_read, line, bytes) != 0) {
-			bytes_read = -EFAULT;
-			goto end;
-		}
-
-		bytes_read += bytes;
-	}
-
-	if (bytes_read > 0) {
-		*ppos = bytes_read;
-	}
-
-	if (data) {
-		data->if_num = if_num;
-	}
-
-end:
-	return bytes_read;
-}
-
-/*
- * nss_stats_trustsec_tx_read()
- *	Read trustsec_tx stats
- */
-static ssize_t nss_stats_trustsec_tx_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
-{
-	int32_t i;
-
-	/*
-	 * max output lines = #stats + start tag line + end tag line + three blank lines
-	 */
-	uint32_t max_output_lines = (NSS_STATS_NODE_MAX + 2) + (NSS_STATS_TRUSTSEC_TX_MAX + 3) + 5;
-	size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
-	size_t size_wr = 0;
-	ssize_t bytes_read = 0;
-	uint64_t *stats_shadow;
-
-	char *lbuf = kzalloc(size_al, GFP_KERNEL);
-	if (unlikely(lbuf == NULL)) {
-		nss_warning("Could not allocate memory for local statistics buffer");
-		return 0;
-	}
-
-	stats_shadow = kzalloc(NSS_STATS_NODE_MAX * 8, GFP_KERNEL);
-	if (unlikely(stats_shadow == NULL)) {
-		nss_warning("Could not allocate memory for local shadow buffer");
-		kfree(lbuf);
-		return 0;
-	}
-
-	size_wr = scnprintf(lbuf, size_al, "trustsec_tx stats start:\n\n");
-
-	/*
-	 * Common node stats
-	 */
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "common node stats:\n\n");
-	spin_lock_bh(&nss_top_main.stats_lock);
-	for (i = 0; (i < NSS_STATS_NODE_MAX); i++) {
-		stats_shadow[i] = nss_top_main.stats_node[NSS_TRUSTSEC_TX_INTERFACE][i];
-	}
-
-	spin_unlock_bh(&nss_top_main.stats_lock);
-
-	for (i = 0; (i < NSS_STATS_NODE_MAX); i++) {
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
-					"%s = %llu\n", nss_stats_str_node[i], stats_shadow[i]);
-	}
-
-	/*
-	 * TrustSec TX node stats
-	 */
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\ntrustsec tx node stats:\n\n");
-
-	spin_lock_bh(&nss_top_main.stats_lock);
-	for (i = 0; (i < NSS_STATS_TRUSTSEC_TX_MAX); i++) {
-		stats_shadow[i] = nss_top_main.stats_trustsec_tx[i];
-	}
-
-	spin_unlock_bh(&nss_top_main.stats_lock);
-
-	for (i = 0; (i < NSS_STATS_TRUSTSEC_TX_MAX); i++) {
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
-					"%s = %llu\n", nss_stats_str_trustsec_tx[i], stats_shadow[i]);
-	}
-
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\ntrustsec tx stats end\n\n");
-	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
-	kfree(lbuf);
-	kfree(stats_shadow);
-
-	return bytes_read;
-}
-
-/*
- * nss_stats_wt_read()
+ * nss_wt_stats_read()
  *	Reads and formats worker thread statistics and outputs them to ubuf
  */
-static ssize_t nss_stats_wt_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
+static ssize_t nss_wt_stats_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
 {
 	struct nss_stats_data *data = fp->private_data;
 	struct nss_ctx_instance *nss_ctx = data->nss_ctx;
@@ -4290,7 +270,7 @@
 		/*
 		 * The statistics shadow is an array with thread_count * irq_count
 		 * items in it. Each item is located at the index:
-		 *	(thread number) * (irq_count) + (irq number)
+		 *      (thread number) * (irq_count) + (irq number)
 		 * thus simulating a two-dimensional array.
 		 */
 		for (j = 0; j < irq_count; ++j) {
@@ -4327,7 +307,7 @@
 /*
  * nss_stats_open()
  */
-static int nss_stats_open(struct inode *inode, struct file *filp)
+int nss_stats_open(struct inode *inode, struct file *filp)
 {
 	struct nss_stats_data *data = NULL;
 
@@ -4348,7 +328,7 @@
 /*
  * nss_stats_release()
  */
-static int nss_stats_release(struct inode *inode, struct file *filp)
+int nss_stats_release(struct inode *inode, struct file *filp)
 {
 	struct nss_stats_data *data = filp->private_data;
 
@@ -4359,224 +339,46 @@
 	return 0;
 }
 
-#define NSS_STATS_DECLARE_FILE_OPERATIONS(name) \
-static const struct file_operations nss_stats_##name##_ops = { \
-	.open = nss_stats_open, \
-	.read = nss_stats_##name##_read, \
-	.llseek = generic_file_llseek, \
-	.release = nss_stats_release, \
-};
-
-/*
- * nss_ipv4_stats_ops
- */
-NSS_STATS_DECLARE_FILE_OPERATIONS(ipv4)
-
-/*
- * ipv4_reasm_stats_ops
- */
-NSS_STATS_DECLARE_FILE_OPERATIONS(ipv4_reasm)
-
-/*
- * ipv6_stats_ops
- */
-NSS_STATS_DECLARE_FILE_OPERATIONS(ipv6)
-
-/*
- * ipv6_reasm_stats_ops
- */
-NSS_STATS_DECLARE_FILE_OPERATIONS(ipv6_reasm)
-
-/*
- * n2h_stats_ops
- */
-NSS_STATS_DECLARE_FILE_OPERATIONS(n2h)
-
-/*
- * lso_rx_stats_ops
- */
-NSS_STATS_DECLARE_FILE_OPERATIONS(lso_rx)
-
 /*
  * drv_stats_ops
  */
 NSS_STATS_DECLARE_FILE_OPERATIONS(drv)
 
 /*
- * pppoe_stats_ops
- */
-NSS_STATS_DECLARE_FILE_OPERATIONS(pppoe)
-
-/*
- * l2tpv2_stats_ops
- */
-NSS_STATS_DECLARE_FILE_OPERATIONS(l2tpv2)
-
-/*
- * map_t_stats_ops
- */
-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)
-NSS_STATS_DECLARE_FILE_OPERATIONS(ppe_l3)
-NSS_STATS_DECLARE_FILE_OPERATIONS(ppe_code)
-NSS_STATS_DECLARE_FILE_OPERATIONS(ppe_port_dc)
-NSS_STATS_DECLARE_FILE_OPERATIONS(ppe_exception_cc)
-NSS_STATS_DECLARE_FILE_OPERATIONS(ppe_nonexception_cc)
-
-/*
- * pptp_stats_ops
- */
-NSS_STATS_DECLARE_FILE_OPERATIONS(pptp)
-
-/*
  * gmac_stats_ops
  */
 NSS_STATS_DECLARE_FILE_OPERATIONS(gmac)
 
 /*
- * capwap_stats_ops
- */
-NSS_STATS_DECLARE_FILE_OPERATIONS(capwap_encap)
-NSS_STATS_DECLARE_FILE_OPERATIONS(capwap_decap)
-
-/*
- * eth_rx_stats_ops
- */
-NSS_STATS_DECLARE_FILE_OPERATIONS(eth_rx)
-
-/*
- * edma_port_stats_ops
- */
-NSS_STATS_DECLARE_FILE_OPERATIONS(edma_port_stats)
-
-/*
- * edma_port_type_ops
- */
-NSS_STATS_DECLARE_FILE_OPERATIONS(edma_port_type)
-
-/*
- * edma_port_ring_map_ops
- */
-NSS_STATS_DECLARE_FILE_OPERATIONS(edma_port_ring_map)
-
-/*
- * edma_txring_stats_ops
- */
-NSS_STATS_DECLARE_FILE_OPERATIONS(edma_txring)
-
-/*
- * edma_rxring_stats_ops
- */
-NSS_STATS_DECLARE_FILE_OPERATIONS(edma_rxring)
-
-/*
- * edma_txcmplring_stats_ops
- */
-NSS_STATS_DECLARE_FILE_OPERATIONS(edma_txcmplring)
-
-/*
- * edma_rxfillring_stats_ops
- */
-NSS_STATS_DECLARE_FILE_OPERATIONS(edma_rxfillring)
-
-/*
- * edma_err_stats_ops
- */
-NSS_STATS_DECLARE_FILE_OPERATIONS(edma_err_stats)
-
-/*
- * gre_redir_ops
- */
-NSS_STATS_DECLARE_FILE_OPERATIONS(gre_redir)
-
-/*
- * sjack_stats_ops
- */
-NSS_STATS_DECLARE_FILE_OPERATIONS(sjack)
-
-/*
- * portid_ops
- */
-NSS_STATS_DECLARE_FILE_OPERATIONS(portid)
-
-NSS_STATS_DECLARE_FILE_OPERATIONS(wifi_if)
-
-NSS_STATS_DECLARE_FILE_OPERATIONS(virt_if)
-
-NSS_STATS_DECLARE_FILE_OPERATIONS(tx_rx_virt_if)
-
-/*
- * wifi_stats_ops
- */
-NSS_STATS_DECLARE_FILE_OPERATIONS(wifi)
-
-/*
- * dtls_stats_ops
- */
-NSS_STATS_DECLARE_FILE_OPERATIONS(dtls)
-
-/*
- * gre_tunnel_stats_ops
- */
-NSS_STATS_DECLARE_FILE_OPERATIONS(gre_tunnel)
-
-/*
- * trustsec_tx_stats_ops
- */
-NSS_STATS_DECLARE_FILE_OPERATIONS(trustsec_tx)
-
-/*
- * wifili_stats_ops
- */
-NSS_STATS_DECLARE_FILE_OPERATIONS(wifili)
-
-/*
  * wt_stats_ops
  */
 NSS_STATS_DECLARE_FILE_OPERATIONS(wt)
+
+/*
+ * nss_stats_clean()
+ * 	Cleanup NSS statistics files
+ */
+void nss_stats_clean(void)
+{
+	/*
+	 * Remove debugfs tree
+	 */
+	if (likely(nss_top_main.top_dentry != NULL)) {
+		debugfs_remove_recursive(nss_top_main.top_dentry);
+		nss_top_main.top_dentry = NULL;
+	}
+}
+
 /*
  * nss_stats_init()
  * 	Enable NSS statistics
  */
 void nss_stats_init(void)
 {
-	int i = 0;
-	struct dentry *edma_d = NULL;
-	struct dentry *edma_port_dir_d = NULL;
-	struct dentry *edma_port_d = NULL;
-	struct dentry *edma_port_type_d = NULL;
-	struct dentry *edma_port_stats_d = NULL;
-	struct dentry *edma_port_ring_map_d = NULL;
-	struct dentry *edma_rings_dir_d = NULL;
-	struct dentry *edma_tx_dir_d = NULL;
-	struct dentry *edma_tx_d = NULL;
-	struct dentry *edma_rx_dir_d = NULL;
-	struct dentry *edma_rx_d = NULL;
-	struct dentry *edma_txcmpl_dir_d = NULL;
-	struct dentry *edma_txcmpl_d = NULL;
-	struct dentry *edma_rxfill_dir_d = NULL;
-	struct dentry *edma_rxfill_d = NULL;
-	struct dentry *edma_err_stats_d = NULL;
-
-	struct dentry *ppe_code_d = NULL;
-	struct dentry *ppe_drop_d = NULL;
-	struct dentry *ppe_port_dc_d = NULL;
-	struct dentry *ppe_cpu_d = NULL;
-	struct dentry *ppe_exception_d = NULL;
-	struct dentry *ppe_nonexception_d = NULL;
 	struct dentry *core_dentry = NULL;
 	struct dentry *wt_dentry = NULL;
-
 	char file_name[10];
+	int i;
 
 	/*
 	 * NSS driver entry
@@ -4608,498 +410,14 @@
 	 */
 
 	/*
-	 * ipv4_stats
-	 */
-	nss_top_main.ipv4_dentry = debugfs_create_file("ipv4", 0400,
-						nss_top_main.stats_dentry, &nss_top_main, &nss_stats_ipv4_ops);
-	if (unlikely(nss_top_main.ipv4_dentry == NULL)) {
-		nss_warning("Failed to create qca-nss-drv/stats/ipv4 file in debugfs");
-		return;
-	}
-
-	/*
-	 * ipv4_reasm_stats
-	 */
-	nss_top_main.ipv4_reasm_dentry = debugfs_create_file("ipv4_reasm", 0400,
-						nss_top_main.stats_dentry, &nss_top_main, &nss_stats_ipv4_reasm_ops);
-	if (unlikely(nss_top_main.ipv4_reasm_dentry == NULL)) {
-		nss_warning("Failed to create qca-nss-drv/stats/ipv4_reasm file in debugfs");
-		return;
-	}
-
-	/*
-	 * ipv6_stats
-	 */
-	nss_top_main.ipv6_dentry = debugfs_create_file("ipv6", 0400,
-						nss_top_main.stats_dentry, &nss_top_main, &nss_stats_ipv6_ops);
-	if (unlikely(nss_top_main.ipv6_dentry == NULL)) {
-		nss_warning("Failed to create qca-nss-drv/stats/ipv6 file in debugfs");
-		return;
-	}
-
-	/*
-	 * ipv6_reasm_stats
-	 */
-	nss_top_main.ipv6_reasm_dentry = debugfs_create_file("ipv6_reasm", 0400,
-						nss_top_main.stats_dentry, &nss_top_main, &nss_stats_ipv6_reasm_ops);
-	if (unlikely(nss_top_main.ipv6_reasm_dentry == NULL)) {
-		nss_warning("Failed to create qca-nss-drv/stats/ipv6_reasm file in debugfs");
-		return;
-	}
-
-	/*
-	 * eth_rx__stats
-	 */
-	nss_top_main.eth_rx_dentry = debugfs_create_file("eth_rx", 0400,
-						nss_top_main.stats_dentry, &nss_top_main, &nss_stats_eth_rx_ops);
-	if (unlikely(nss_top_main.eth_rx_dentry == NULL)) {
-		nss_warning("Failed to create qca-nss-drv/stats/eth_rx file in debugfs");
-		return;
-	}
-
-	/*
-	 * edma stats
-	 */
-	edma_d = debugfs_create_dir("edma", nss_top_main.stats_dentry);
-	if (unlikely(edma_d == NULL)) {
-		nss_warning("Failed to create qca-nss-drv/stats/edma directory in debugfs");
-		return;
-	}
-
-	/*
-	 * edma port stats
-	 */
-	edma_port_dir_d = debugfs_create_dir("ports", edma_d);
-	if (unlikely(edma_port_dir_d == NULL)) {
-		nss_warning("Failed to create qca-nss-drv/stats/edma/ports directory in debugfs");
-		return;
-	}
-
-	for (i = 0; i < NSS_EDMA_NUM_PORTS_MAX; i++) {
-		memset(file_name, 0, sizeof(file_name));
-		snprintf(file_name, sizeof(file_name), "%d", i);
-		edma_port_d  = NULL;
-		edma_port_stats_d = NULL;
-		edma_port_type_d = NULL;
-		edma_port_ring_map_d = NULL;
-
-		edma_port_d = debugfs_create_dir(file_name, edma_port_dir_d);
-		if (unlikely(edma_port_d == NULL)) {
-			nss_warning("Failed to create qca-nss-drv/stats/edma/ports/%d dir in debugfs", i);
-			return;
-		}
-
-		edma_port_stats_d = debugfs_create_file("stats", 0400, edma_port_d, (void *)(nss_ptr_t)i, &nss_stats_edma_port_stats_ops);
-		if (unlikely(edma_port_stats_d == NULL)) {
-			nss_warning("Failed to create qca-nss-drv/stats/edma/ports/%d/stats file in debugfs", i);
-			return;
-		}
-
-		edma_port_type_d = debugfs_create_file("type", 0400, edma_port_d, (void *)(nss_ptr_t)i, &nss_stats_edma_port_type_ops);
-		if (unlikely(edma_port_type_d == NULL)) {
-			nss_warning("Failed to create qca-nss-drv/stats/edma/ports/%d/type file in debugfs", i);
-			return;
-		}
-
-		edma_port_ring_map_d = debugfs_create_file("ring_map", 0400, edma_port_d, (void *)(nss_ptr_t)i, &nss_stats_edma_port_ring_map_ops);
-		if (unlikely(edma_port_ring_map_d == NULL)) {
-			nss_warning("Failed to create qca-nss-drv/stats/edma/ports/%d/ring_map file in debugfs", i);
-			return;
-		}
-	}
-
-	/*
-	 *  edma error stats
-	 */
-	edma_err_stats_d = NULL;
-	edma_err_stats_d = debugfs_create_file("err_stats", 0400, edma_d, &nss_top_main, &nss_stats_edma_err_stats_ops);
-	if (unlikely(edma_port_stats_d == NULL)) {
-		nss_warning("Failed to create qca-nss-drv/stats/edma/%d/err_stats file in debugfs", 0);
-		return;
-	}
-
-	/*
-	 * edma ring stats
-	 */
-	edma_rings_dir_d = debugfs_create_dir("rings", edma_d);
-	if (unlikely(edma_rings_dir_d == NULL)) {
-		nss_warning("Failed to create qca-nss-drv/stats/edma/rings directory in debugfs");
-		return;
-	}
-
-	/*
-	 * edma tx ring stats
-	 */
-	edma_tx_dir_d = debugfs_create_dir("tx", edma_rings_dir_d);
-	if (unlikely(edma_tx_dir_d == NULL)) {
-		nss_warning("Failed to create qca-nss-drv/stats/edma/rings/tx directory in debugfs");
-		return;
-	}
-
-	for (i = 0; i < NSS_EDMA_NUM_TX_RING_MAX; i++) {
-		memset(file_name, 0, sizeof(file_name));
-		scnprintf(file_name, sizeof(file_name), "%d", i);
-		edma_tx_d = NULL;
-		edma_tx_d = debugfs_create_file(file_name, 0400, edma_tx_dir_d, (void *)(nss_ptr_t)i, &nss_stats_edma_txring_ops);
-		if (unlikely(edma_tx_d == NULL)) {
-			nss_warning("Failed to create qca-nss-drv/stats/edma/rings/tx/%d file in debugfs", i);
-			return;
-		}
-	}
-
-	/*
-	 * edma rx ring stats
-	 */
-	edma_rx_dir_d = debugfs_create_dir("rx", edma_rings_dir_d);
-	if (unlikely(edma_rx_dir_d == NULL)) {
-		nss_warning("Failed to create qca-nss-drv/stats/edma/rings/rx directory in debugfs");
-		return;
-	}
-
-	for (i = 0; i < NSS_EDMA_NUM_RX_RING_MAX; i++) {
-		memset(file_name, 0, sizeof(file_name));
-		scnprintf(file_name, sizeof(file_name), "%d", i);
-		edma_rx_d = NULL;
-		edma_rx_d = debugfs_create_file(file_name, 0400, edma_rx_dir_d, (void *)(nss_ptr_t)i, &nss_stats_edma_rxring_ops);
-		if (unlikely(edma_rx_d == NULL)) {
-			nss_warning("Failed to create qca-nss-drv/stats/edma/rings/rx/%d file in debugfs", i);
-			return;
-		}
-	}
-
-	/*
-	 * edma tx cmpl ring stats
-	 */
-	edma_txcmpl_dir_d = debugfs_create_dir("txcmpl", edma_rings_dir_d);
-	if (unlikely(edma_txcmpl_dir_d == NULL)) {
-		nss_warning("Failed to create qca-nss-drv/stats/edma/rings/txcmpl directory in debugfs");
-		return;
-	}
-
-	for (i = 0; i < NSS_EDMA_NUM_TXCMPL_RING_MAX; i++) {
-		memset(file_name, 0, sizeof(file_name));
-		scnprintf(file_name, sizeof(file_name), "%d", i);
-		edma_txcmpl_d = NULL;
-		edma_txcmpl_d = debugfs_create_file(file_name, 0400, edma_txcmpl_dir_d, (void *)(nss_ptr_t)i, &nss_stats_edma_txcmplring_ops);
-		if (unlikely(edma_txcmpl_d == NULL)) {
-			nss_warning("Failed to create qca-nss-drv/stats/edma/rings/txcmpl/%d file in debugfs", i);
-			return;
-		}
-	}
-
-	/*
-	 * edma rx fill ring stats
-	 */
-	edma_rxfill_dir_d = debugfs_create_dir("rxfill", edma_rings_dir_d);
-	if (unlikely(edma_rxfill_dir_d == NULL)) {
-		nss_warning("Failed to create qca-nss-drv/stats/edma/rings/rxfill directory in debugfs");
-		return;
-	}
-
-	for (i = 0; i < NSS_EDMA_NUM_RXFILL_RING_MAX; i++) {
-		memset(file_name, 0, sizeof(file_name));
-		scnprintf(file_name, sizeof(file_name), "%d", i);
-		edma_rxfill_d = NULL;
-		edma_rxfill_d = debugfs_create_file(file_name, 0400, edma_rxfill_dir_d, (void *)(nss_ptr_t)i, &nss_stats_edma_rxfillring_ops);
-		if (unlikely(edma_rxfill_d == NULL)) {
-			nss_warning("Failed to create qca-nss-drv/stats/edma/rings/rxfill/%d file in debugfs", i);
-			return;
-		}
-	}
-
-	/*
-	 * n2h_stats
-	 */
-	nss_top_main.n2h_dentry = debugfs_create_file("n2h", 0400,
-						nss_top_main.stats_dentry, &nss_top_main, &nss_stats_n2h_ops);
-	if (unlikely(nss_top_main.n2h_dentry == NULL)) {
-		nss_warning("Failed to create qca-nss-drv/stats/n2h directory in debugfs");
-		return;
-	}
-
-	/*
-	 * lso_rx_stats
-	 */
-	nss_top_main.lso_rx_dentry = debugfs_create_file("lso_rx", 0400,
-						nss_top_main.stats_dentry, &nss_top_main, &nss_stats_lso_rx_ops);
-	if (unlikely(nss_top_main.lso_rx_dentry == NULL)) {
-		nss_warning("Failed to create qca-nss-drv/stats/lso_rx file in debugfs");
-		return;
-	}
-
-	/*
 	 * drv_stats
 	 */
-	nss_top_main.drv_dentry = debugfs_create_file("drv", 0400,
-						nss_top_main.stats_dentry, &nss_top_main, &nss_stats_drv_ops);
-	if (unlikely(nss_top_main.drv_dentry == NULL)) {
-		nss_warning("Failed to create qca-nss-drv/stats/drv directory in debugfs");
-		return;
-	}
-
-	/*
-	 * pppoe_stats
-	 */
-	nss_top_main.pppoe_dentry = debugfs_create_file("pppoe", 0400,
-						nss_top_main.stats_dentry, &nss_top_main, &nss_stats_pppoe_ops);
-	if (unlikely(nss_top_main.pppoe_dentry == NULL)) {
-		nss_warning("Failed to create qca-nss-drv/stats/pppoe file in debugfs");
-		return;
-	}
+	nss_stats_create_dentry("drv", &nss_drv_stats_ops);
 
 	/*
 	 * gmac_stats
 	 */
-	nss_top_main.gmac_dentry = debugfs_create_file("gmac", 0400,
-						nss_top_main.stats_dentry, &nss_top_main, &nss_stats_gmac_ops);
-	if (unlikely(nss_top_main.gmac_dentry == NULL)) {
-		nss_warning("Failed to create qca-nss-drv/stats/gmac file in debugfs");
-		return;
-	}
-
-	/*
-	 * CAPWAP stats.
-	 */
-	nss_top_main.capwap_encap_dentry = debugfs_create_file("capwap_encap", 0400,
-	nss_top_main.stats_dentry, &nss_top_main, &nss_stats_capwap_encap_ops);
-	if (unlikely(nss_top_main.capwap_encap_dentry == NULL)) {
-		nss_warning("Failed to create qca-nss-drv/stats/capwap_encap file in debugfs");
-		return;
-	}
-
-	nss_top_main.capwap_decap_dentry = debugfs_create_file("capwap_decap", 0400,
-	nss_top_main.stats_dentry, &nss_top_main, &nss_stats_capwap_decap_ops);
-	if (unlikely(nss_top_main.capwap_decap_dentry == NULL)) {
-		nss_warning("Failed to create qca-nss-drv/stats/capwap_decap file in debugfs");
-		return;
-	}
-
-	/*
-	 * GRE_REDIR stats
-	 */
-	nss_top_main.gre_redir_dentry = debugfs_create_file("gre_redir", 0400,
-						nss_top_main.stats_dentry, &nss_top_main, &nss_stats_gre_redir_ops);
-	if (unlikely(nss_top_main.gre_redir_dentry == NULL)) {
-		nss_warning("Failed to create qca-nss-drv/stats/gre_redir file in debugfs");
-		return;
-	}
-
-	/*
-	 * SJACK stats
-	 */
-	nss_top_main.sjack_dentry = debugfs_create_file("sjack", 0400,
-						nss_top_main.stats_dentry, &nss_top_main, &nss_stats_sjack_ops);
-	if (unlikely(nss_top_main.sjack_dentry == NULL)) {
-		nss_warning("Failed to create qca-nss-drv/stats/sjack file in debugfs");
-		return;
-	}
-
-	/*
-	 * PORTID stats
-	 */
-	nss_top_main.portid_dentry = debugfs_create_file("portid", 0400,
-						nss_top_main.stats_dentry, &nss_top_main, &nss_stats_portid_ops);
-	if (unlikely(nss_top_main.portid_dentry == NULL)) {
-		nss_warning("Failed to create qca-nss-drv/stats/portid file in debugfs");
-		return;
-	}
-
-	/*
-	 * WIFI stats
-	 */
-	nss_top_main.wifi_dentry = debugfs_create_file("wifi", 0400,
-						nss_top_main.stats_dentry, &nss_top_main, &nss_stats_wifi_ops);
-	if (unlikely(nss_top_main.wifi_dentry == NULL)) {
-		nss_warning("Failed to create qca-nss-drv/stats/wifi file in debugfs");
-		return;
-	}
-
-	/*
-	 * wifi_if stats
-	 */
-	nss_top_main.wifi_if_dentry = debugfs_create_file("wifi_if", 0400,
-						nss_top_main.stats_dentry, &nss_top_main, &nss_stats_wifi_if_ops);
-	if (unlikely(nss_top_main.wifi_if_dentry == NULL)) {
-		nss_warning("Failed to create qca-nss-drv/stats/wifi_if file in debugfs");
-		return;
-	}
-
-	nss_top_main.virt_if_dentry = debugfs_create_file("virt_if", 0400,
-						nss_top_main.stats_dentry, &nss_top_main, &nss_stats_virt_if_ops);
-	if (unlikely(nss_top_main.virt_if_dentry == NULL)) {
-		nss_warning("Failed to create qca-nss-drv/stats/virt_if file in debugfs");
-		return;
-	}
-
-	nss_top_main.tx_rx_virt_if_dentry = debugfs_create_file("tx_rx_virt_if", 0400,
-						nss_top_main.stats_dentry, &nss_top_main, &nss_stats_tx_rx_virt_if_ops);
-	if (unlikely(nss_top_main.virt_if_dentry == NULL)) {
-		nss_warning("Failed to create qca-nss-drv/stats/tx_rx_virt_if file in debugfs");
-		return;
-	}
-
-	/*
-	 *  L2TPV2 Stats
-	 */
-	nss_top_main.l2tpv2_dentry = debugfs_create_file("l2tpv2", 0400,
-						nss_top_main.stats_dentry, &nss_top_main, &nss_stats_l2tpv2_ops);
-	if (unlikely(nss_top_main.l2tpv2_dentry == NULL)) {
-		nss_warning("Failed to create qca-nss-drv/stats/l2tpv2 file in debugfs");
-		return;
-	}
-
-	/*
-	 *  Map-t Stats
-	 */
-	nss_top_main.map_t_dentry = debugfs_create_file("map_t", 0400,
-						nss_top_main.stats_dentry, &nss_top_main, &nss_stats_map_t_ops);
-	if (unlikely(nss_top_main.map_t_dentry == NULL)) {
-		nss_warning("Failed to create qca-nss-drv/stats/map_t file in debugfs");
-		return;
-	}
-
-	/*
-	 *  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);
-	if (unlikely(nss_top_main.ppe_dentry == NULL)) {
-		nss_warning("Failed to create qca-nss-drv directory in debugfs");
-		return;
-	}
-
-	nss_top_main.ppe_conn_dentry = debugfs_create_file("connection", 0400,
-						nss_top_main.ppe_dentry, &nss_top_main, &nss_stats_ppe_conn_ops);
-	if (unlikely(nss_top_main.ppe_dentry == NULL)) {
-		nss_warning("Failed to create qca-nss-drv/stats/ppe/connection file in debugfs");
-	}
-
-	nss_top_main.ppe_l3_dentry = debugfs_create_file("l3", 0400,
-						nss_top_main.ppe_dentry, &nss_top_main, &nss_stats_ppe_l3_ops);
-	if (unlikely(nss_top_main.ppe_dentry == NULL)) {
-		nss_warning("Failed to create qca-nss-drv/stats/ppe/l3 file in debugfs");
-	}
-
-	nss_top_main.ppe_l3_dentry = debugfs_create_file("ppe_code", 0400,
-						nss_top_main.ppe_dentry, &nss_top_main, &nss_stats_ppe_code_ops);
-	if (unlikely(nss_top_main.ppe_dentry == NULL)) {
-		nss_warning("Failed to create qca-nss-drv/stats/ppe/ppe_code file in debugfs");
-	}
-
-	/*
-	 * ppe exception and drop code stats
-	 */
-	ppe_code_d = debugfs_create_dir("code", nss_top_main.ppe_dentry);
-	if (unlikely(ppe_code_d == NULL)) {
-		nss_warning("Failed to create qca-nss-drv/stats/ppe/code directory in debugfs");
-		return;
-	}
-
-	ppe_cpu_d = debugfs_create_dir("cpu", ppe_code_d);
-	if (unlikely(ppe_cpu_d == NULL)) {
-		nss_warning("Failed to create qca-nss-drv/stats/ppe/code/cpu directory in debugfs");
-		return;
-	}
-
-	ppe_exception_d = debugfs_create_file("exception", 0400, ppe_cpu_d,
-			&nss_top_main, &nss_stats_ppe_exception_cc_ops);
-	if (unlikely(ppe_exception_d == NULL)) {
-		nss_warning("Failed to create qca-nss-drv/stats/ppe/code/exception file in debugfs");
-		return;
-	}
-
-	ppe_nonexception_d = debugfs_create_file("non-exception", 0400, ppe_cpu_d,
-			&nss_top_main, &nss_stats_ppe_nonexception_cc_ops);
-	if (unlikely(ppe_nonexception_d == NULL)) {
-		nss_warning("Failed to create qca-nss-drv/stats/ppe/code/non-exception file in debugfs");
-		return;
-	}
-
-	ppe_drop_d = debugfs_create_dir("drop", ppe_code_d);
-	if (unlikely(ppe_drop_d == NULL)) {
-		nss_warning("Failed to create qca-nss-drv/stats/ppe/code/drop directory in debugfs");
-		return;
-	}
-
-	for (i = 0; i < NSS_PPE_NUM_PHY_PORTS_MAX; i++) {
-		if (i > 0) {
-			memset(file_name, 0, sizeof(file_name));
-			snprintf(file_name, sizeof(file_name), "%d", i);
-		}
-
-		ppe_port_dc_d  = NULL;
-		ppe_port_dc_d = debugfs_create_file((i == 0) ? "cpu" : file_name, 0400, ppe_drop_d,
-					(void *)(nss_ptr_t)i, &nss_stats_ppe_port_dc_ops);
-		if (unlikely(ppe_port_dc_d == NULL)) {
-			nss_warning("Failed to create qca-nss-drv/stats/ppe/code/drop/%d file in debugfs", i);
-			return;
-		}
-	}
-
-	/*
-	 *  PPTP Stats
-	 */
-	nss_top_main.pptp_dentry = debugfs_create_file("pptp", 0400,
-						nss_top_main.stats_dentry, &nss_top_main, &nss_stats_pptp_ops);
-	if (unlikely(nss_top_main.pptp_dentry == NULL)) {
-		nss_warning("Failed to create qca-nss-drv/stats/pptp file in debugfs");
-	}
-
-	/*
-	 *  DTLS Stats
-	 */
-	nss_top_main.dtls_dentry = debugfs_create_file("dtls", 0400,
-							nss_top_main.stats_dentry,
-							&nss_top_main,
-							&nss_stats_dtls_ops);
-	if (unlikely(nss_top_main.dtls_dentry == NULL)) {
-		nss_warning("Failed to create qca-nss-drv/stats/dtls file in debugfs");
-		return;
-	}
-
-	/*
-	 *  GRE Tunnel Stats
-	 */
-	nss_top_main.gre_tunnel_dentry = debugfs_create_file("gre_tunnel", 0400,
-							nss_top_main.stats_dentry,
-							&nss_top_main,
-							&nss_stats_gre_tunnel_ops);
-	if (unlikely(nss_top_main.gre_tunnel_dentry == NULL)) {
-		nss_warning("Failed to create qca-nss-drv/stats/gre_tunnel file in debugfs");
-		return;
-	}
-
-	/*
-	 * TrustSec TX Stats
-	 */
-	nss_top_main.trustsec_tx_dentry = debugfs_create_file("trustsec_tx", 0400,
-							nss_top_main.stats_dentry,
-							&nss_top_main,
-							&nss_stats_trustsec_tx_ops);
-	if (unlikely(nss_top_main.trustsec_tx_dentry == NULL)) {
-		nss_warning("Failed to create qca-nss-drv/stats/trustsec_tx file in debugfs");
-		return;
-	}
-
-	/*
-	 * WIFILI stats
-	 */
-	nss_top_main.wifili_dentry = debugfs_create_file("wifili", 0400,
-						nss_top_main.stats_dentry,
-						&nss_top_main, &nss_stats_wifili_ops);
-	if (unlikely(nss_top_main.wifili_dentry == NULL)) {
-		nss_warning("Failed to create qca-nss-drv/stats/wifili file in debugfs");
-		return;
-	}
+	nss_stats_create_dentry("gmac", &nss_gmac_stats_ops);
 
 	/*
 	 * Per-project stats
@@ -5125,7 +443,7 @@
 						0400,
 						core_dentry,
 						&(nss_top_main.nss[i]),
-						&nss_stats_wt_ops);
+						&nss_wt_stats_ops);
 		if (unlikely(wt_dentry == NULL)) {
 			nss_warning("Failed to create qca-nss-drv/stats/project/core%d/worker_threads file in debugfs", i);
 			return;
@@ -5134,18 +452,3 @@
 
 	nss_log_init();
 }
-
-/*
- * nss_stats_clean()
- * 	Cleanup NSS statistics files
- */
-void nss_stats_clean(void)
-{
-	/*
-	 * Remove debugfs tree
-	 */
-	if (likely(nss_top_main.top_dentry != NULL)) {
-		debugfs_remove_recursive(nss_top_main.top_dentry);
-		nss_top_main.top_dentry = NULL;
-	}
-}
diff --git a/nss_stats.h b/nss_stats.h
new file mode 100644
index 0000000..b973bab
--- /dev/null
+++ b/nss_stats.h
@@ -0,0 +1,78 @@
+/*
+ **************************************************************************
+ * Copyright (c) 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.
+ * 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_stats.h
+ *	NSS driver stats header file.
+ */
+
+#ifndef __NSS_STATS_H
+#define __NSS_STATS_H
+
+#include <linux/debugfs.h>
+
+/*
+ * Maximum string length:
+ * This should be equal to maximum string size of any stats
+ * inclusive of stats value
+ */
+#define NSS_STATS_MAX_STR_LENGTH 96
+
+/*
+ * Node statistics
+ */
+enum nss_stats_node {
+	NSS_STATS_NODE_RX_PKTS,		/* Accelerated node RX packets */
+	NSS_STATS_NODE_RX_BYTES,	/* Accelerated node RX bytes */
+	NSS_STATS_NODE_TX_PKTS,		/* Accelerated node TX packets */
+	NSS_STATS_NODE_TX_BYTES,	/* Accelerated node TX bytes */
+	NSS_STATS_NODE_RX_QUEUE_0_DROPPED,
+					/* Accelerated node RX Queue 0 dropped */
+	NSS_STATS_NODE_RX_QUEUE_1_DROPPED,
+					/* Accelerated node RX Queue 1 dropped */
+	NSS_STATS_NODE_RX_QUEUE_2_DROPPED,
+					/* Accelerated node RX Queue 2 dropped */
+	NSS_STATS_NODE_RX_QUEUE_3_DROPPED,
+					/* Accelerated node RX Queue 3 dropped */
+
+	NSS_STATS_NODE_MAX,
+};
+
+#define NSS_STATS_DECLARE_FILE_OPERATIONS(name) \
+static const struct file_operations nss_##name##_stats_ops = { \
+	.open = nss_stats_open, \
+	.read = nss_##name##_stats_read, \
+	.llseek = generic_file_llseek, \
+	.release = nss_stats_release, \
+};
+
+/*
+ * Private data for every file descriptor
+ */
+struct nss_stats_data {
+	uint32_t if_num;	/**< Interface number for stats */
+	uint32_t index;		/**< Index for GRE_REDIR stats */
+	uint32_t edma_id;	/**< EDMA port ID or ring ID */
+	struct nss_ctx_instance *nss_ctx;
+				/**< The core for project stats */
+};
+
+int nss_stats_release(struct inode *inode, struct file *filp);
+int nss_stats_open(struct inode *inode, struct file *filp);
+void nss_stats_create_dentry(char *name, const struct file_operations *ops);
+size_t nss_stats_fill_common_stats(uint32_t if_num, char *lbuf, size_t size_wr, size_t size_al);
+
+#endif /* __NSS_STATS_H */
diff --git a/nss_trustsec_tx.c b/nss_trustsec_tx.c
index f9f181b..1795f78 100644
--- a/nss_trustsec_tx.c
+++ b/nss_trustsec_tx.c
@@ -15,6 +15,7 @@
  */
 
 #include "nss_tx_rx_common.h"
+#include "nss_trustsec_tx_stats.h"
 
 #define NSS_TRUSTSEC_TX_TIMEOUT 3000 /* 3 Seconds */
 
@@ -28,37 +29,6 @@
 } ttx;
 
 /*
- * nss_trustsec_tx_node_sync_update()
- *	Update trustsec_tx node stats.
- */
-static void nss_trustsec_tx_sync_update(struct nss_ctx_instance *nss_ctx, struct nss_trustsec_tx_stats_sync_msg *ntsm)
-{
-	struct nss_top_instance *nss_top = nss_ctx->nss_top;
-	int j;
-
-	/*
-	 * Update common node stats
-	 */
-	spin_lock_bh(&nss_top->stats_lock);
-	nss_top->stats_node[NSS_TRUSTSEC_TX_INTERFACE][NSS_STATS_NODE_RX_PKTS] += ntsm->node_stats.rx_packets;
-	nss_top->stats_node[NSS_TRUSTSEC_TX_INTERFACE][NSS_STATS_NODE_RX_BYTES] += ntsm->node_stats.rx_bytes;
-	nss_top->stats_node[NSS_TRUSTSEC_TX_INTERFACE][NSS_STATS_NODE_TX_PKTS] += ntsm->node_stats.tx_packets;
-	nss_top->stats_node[NSS_TRUSTSEC_TX_INTERFACE][NSS_STATS_NODE_TX_BYTES] += ntsm->node_stats.tx_bytes;
-
-	for (j = 0; j < NSS_MAX_NUM_PRI; j++) {
-		nss_top->stats_node[NSS_TRUSTSEC_TX_INTERFACE][NSS_STATS_NODE_RX_QUEUE_0_DROPPED + j] += ntsm->node_stats.rx_dropped[j];
-	}
-
-	/*
-	 * Update trustsec node stats
-	 */
-	nss_top->stats_trustsec_tx[NSS_STATS_TRUSTSEC_TX_INVALID_SRC] += ntsm->invalid_src;
-	nss_top->stats_trustsec_tx[NSS_STATS_TRUSTSEC_TX_UNCONFIGURED_SRC] += ntsm->unconfigured_src;
-	nss_top->stats_trustsec_tx[NSS_STATS_IRUSTSEC_TX_HEADROOM_NOT_ENOUGH] += ntsm->headroom_not_enough;
-	spin_unlock_bh(&nss_top->stats_lock);
-}
-
-/*
  * nss_trustsec_tx_handler()
  * 	Handle NSS -> HLOS messages for trustsec_tx
  */
@@ -93,7 +63,7 @@
 		/*
 		 * Update trustsec_tx statistics.
 		 */
-		nss_trustsec_tx_sync_update(nss_ctx, &npm->msg.stats_sync);
+		nss_trustsec_tx_stats_sync(nss_ctx, &npm->msg.stats_sync);
 		break;
 	}
 
@@ -322,6 +292,8 @@
 
 	nss_core_register_handler(nss_ctx, NSS_TRUSTSEC_TX_INTERFACE, nss_trustsec_tx_handler, NULL);
 
+	nss_trustsec_tx_stats_dentry_create();
+
 	sema_init(&ttx.sem, 1);
 	init_completion(&ttx.complete);
 }
diff --git a/nss_trustsec_tx_stats.c b/nss_trustsec_tx_stats.c
new file mode 100644
index 0000000..5c624e9
--- /dev/null
+++ b/nss_trustsec_tx_stats.c
@@ -0,0 +1,148 @@
+/*
+ **************************************************************************
+ * 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"
+#include "nss_stats.h"
+#include "nss_trustsec_tx_stats.h"
+
+/*
+ * nss_trustsec_tx_stats_str
+ *	Trustsec TX statistics strings
+ */
+static int8_t *nss_trustsec_tx_stats_str[NSS_TRUSTSEC_TX_STATS_MAX] = {
+	"INVALID_SRC",
+	"UNCONFIGURED_SRC",
+	"HEADROOM_NOT_ENOUGH",
+};
+
+/*
+ * trustsec_tx_stats
+ *	Trustsec TX statistics
+ */
+uint64_t trustsec_tx_stats[NSS_TRUSTSEC_TX_STATS_MAX];
+
+/*
+ * Trustsec TX statistics APIs
+ */
+
+/*
+ * nss_trustsec_tx_stats_sync()
+ *	Update trustsec_tx node statistics.
+ */
+void nss_trustsec_tx_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_trustsec_tx_stats_sync_msg *ntsm)
+{
+	struct nss_top_instance *nss_top = nss_ctx->nss_top;
+	int j;
+
+	spin_lock_bh(&nss_top->stats_lock);
+
+	/*
+	 * Update common node stats
+	 */
+	nss_top->stats_node[NSS_TRUSTSEC_TX_INTERFACE][NSS_STATS_NODE_RX_PKTS] += ntsm->node_stats.rx_packets;
+	nss_top->stats_node[NSS_TRUSTSEC_TX_INTERFACE][NSS_STATS_NODE_RX_BYTES] += ntsm->node_stats.rx_bytes;
+	nss_top->stats_node[NSS_TRUSTSEC_TX_INTERFACE][NSS_STATS_NODE_TX_PKTS] += ntsm->node_stats.tx_packets;
+	nss_top->stats_node[NSS_TRUSTSEC_TX_INTERFACE][NSS_STATS_NODE_TX_BYTES] += ntsm->node_stats.tx_bytes;
+
+	for (j = 0; j < NSS_MAX_NUM_PRI; j++) {
+		nss_top->stats_node[NSS_TRUSTSEC_TX_INTERFACE][NSS_STATS_NODE_RX_QUEUE_0_DROPPED + j] += ntsm->node_stats.rx_dropped[j];
+	}
+
+	/*
+	 * Update trustsec node stats
+	 */
+	trustsec_tx_stats[NSS_TRUSTSEC_TX_STATS_INVALID_SRC] += ntsm->invalid_src;
+	trustsec_tx_stats[NSS_TRUSTSEC_TX_STATS_UNCONFIGURED_SRC] += ntsm->unconfigured_src;
+	trustsec_tx_stats[NSS_TRUSTSEC_TX_STATS_HEADROOM_NOT_ENOUGH] += ntsm->headroom_not_enough;
+
+	spin_unlock_bh(&nss_top->stats_lock);
+}
+
+/*
+ * nss_trustsec_tx_stats_read()
+ *	Read trustsec_tx statiistics
+ */
+static ssize_t nss_trustsec_tx_stats_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
+{
+	int32_t i;
+
+	/*
+	 * max output lines = #stats + start tag line + end tag line + three blank lines
+	 */
+	uint32_t max_output_lines = (NSS_STATS_NODE_MAX + 2) + (NSS_TRUSTSEC_TX_STATS_MAX + 3) + 5;
+	size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
+	size_t size_wr = 0;
+	ssize_t bytes_read = 0;
+	uint64_t *stats_shadow;
+
+	char *lbuf = kzalloc(size_al, GFP_KERNEL);
+	if (unlikely(lbuf == NULL)) {
+		nss_warning("Could not allocate memory for local statistics buffer");
+		return 0;
+	}
+
+	stats_shadow = kzalloc(NSS_STATS_NODE_MAX * 8, GFP_KERNEL);
+	if (unlikely(stats_shadow == NULL)) {
+		nss_warning("Could not allocate memory for local shadow buffer");
+		kfree(lbuf);
+		return 0;
+	}
+
+	size_wr = scnprintf(lbuf, size_al, "trustsec_tx stats start:\n\n");
+
+	/*
+	 * Common node stats
+	 */
+	size_wr = nss_stats_fill_common_stats(NSS_TRUSTSEC_TX_INTERFACE, lbuf, size_wr, size_al);
+
+	/*
+	 * TrustSec TX node stats
+	 */
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\ntrustsec tx node stats:\n\n");
+
+	spin_lock_bh(&nss_top_main.stats_lock);
+	for (i = 0; (i < NSS_TRUSTSEC_TX_STATS_MAX); i++) {
+		stats_shadow[i] = trustsec_tx_stats[i];
+	}
+
+	spin_unlock_bh(&nss_top_main.stats_lock);
+
+	for (i = 0; (i < NSS_TRUSTSEC_TX_STATS_MAX); i++) {
+		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
+					"%s = %llu\n", nss_trustsec_tx_stats_str[i], stats_shadow[i]);
+	}
+
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\ntrustsec tx stats end\n\n");
+	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
+	kfree(lbuf);
+	kfree(stats_shadow);
+
+	return bytes_read;
+}
+
+/*
+ * nss_trustsec_tx_stats_ops
+ */
+NSS_STATS_DECLARE_FILE_OPERATIONS(trustsec_tx)
+
+/*
+ * nss_trustsec_tx_stats_dentry_create()
+ *	Create trustsec_tx statistics debug entry.
+ */
+void nss_trustsec_tx_stats_dentry_create(void)
+{
+	nss_stats_create_dentry("trustsec_tx", &nss_trustsec_tx_stats_ops);
+}
diff --git a/nss_trustsec_tx_stats.h b/nss_trustsec_tx_stats.h
new file mode 100644
index 0000000..11a4d8f
--- /dev/null
+++ b/nss_trustsec_tx_stats.h
@@ -0,0 +1,44 @@
+/*
+ **************************************************************************
+ * 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.
+ **************************************************************************
+ */
+
+/*
+ * nss_trustsec_tx_stats.h
+ *      NSS TRUSTSEC TX statistics header file.
+ */
+
+#ifndef __NSS_TRUSTSEC_TX_STATS_H
+#define __NSS_TRUSTSEC_TX_STATS_H
+
+/*
+ * Trustsec TX statistics
+ */
+enum nss_trustsec_tx_stats {
+	NSS_TRUSTSEC_TX_STATS_INVALID_SRC,
+					/* Number of packets with invalid src if */
+	NSS_TRUSTSEC_TX_STATS_UNCONFIGURED_SRC,
+					/* Number of packets with unconfigured src if */
+	NSS_TRUSTSEC_TX_STATS_HEADROOM_NOT_ENOUGH,
+					/* Number of packets with not enough headroom */
+	NSS_TRUSTSEC_TX_STATS_MAX
+};
+
+/*
+ * Trustsec TX statistics APIs
+ */
+extern void nss_trustsec_tx_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_trustsec_tx_stats_sync_msg *ntsm);
+extern void nss_trustsec_tx_stats_dentry_create(void);
+
+#endif /* __NSS_TRUSTSEC_TX_STATS_H */
diff --git a/nss_tx_rx_common.h b/nss_tx_rx_common.h
index e3b9232..5603bdc 100644
--- a/nss_tx_rx_common.h
+++ b/nss_tx_rx_common.h
@@ -53,6 +53,8 @@
 #define NSS_VERIFY_INIT_DONE(x)
 #endif
 
+#define NSS_TX_RX_VIRT_IF_GET_INDEX(if_num)     (if_num - NSS_DYNAMIC_IF_START)
+
 /*
  * Deprecated Redirect
  */
@@ -162,16 +164,11 @@
 	void *app_data;
 };
 
-/**
- * @brief Get stats for redir interface from NSS driver
- *
- * @param if_num Interface number (provided during dynamic_interface allocation)
- * @param i index of stats
- * @param line buffer into which the stats will be copied.
- *
- * @return int32_t Returns 0 if if_num is not in range or the number of bytes copied.
+/*
+ * NSS tx_rx_virt_if statistics APIs
  */
-extern int32_t nss_tx_rx_virt_if_copy_stats(int32_t if_num, int i, char *line);
+extern void nss_tx_rx_virt_if_stats_sync(struct nss_tx_rx_virt_if_handle *handle, struct nss_tx_rx_virt_if_stats *nwis);
+extern void nss_tx_rx_virt_if_stats_dentry_create(void);
 
 /*
  * CB handlers for variour interfaces
diff --git a/nss_tx_rx_virt_if.c b/nss_tx_rx_virt_if.c
index 9d3dc59..4429747 100644
--- a/nss_tx_rx_virt_if.c
+++ b/nss_tx_rx_virt_if.c
@@ -23,7 +23,6 @@
 #include <net/arp.h>
 
 #define NSS_TX_RX_VIRT_IF_TX_TIMEOUT		3000 /* 3 Seconds */
-#define NSS_TX_RX_VIRT_IF_GET_INDEX(if_num)	(if_num-NSS_DYNAMIC_IF_START)
 #define NSS_TX_RX_VIRT_IF_802_3_PKT		0x2
 #define NSS_TX_RX_VIRT_IF_NATIVE_WIFI_PKT 	0x3
 
@@ -32,7 +31,7 @@
 /*
  * Data structure that holds the virtual interface context.
  */
-static struct nss_tx_rx_virt_if_handle *nss_tx_rx_virt_if_handles[NSS_MAX_DYNAMIC_INTERFACES];
+struct nss_tx_rx_virt_if_handle *nss_tx_rx_virt_if_handles[NSS_MAX_DYNAMIC_INTERFACES];
 
 /*
  * Spinlock to protect the global data structure virt_handle.
@@ -40,24 +39,6 @@
 DEFINE_SPINLOCK(nss_tx_rx_virt_if_lock);
 
 /*
- * nss_tx_rx_virt_if_stats_sync()
- *	Sync stats from the NSS FW
- */
-static void nss_tx_rx_virt_if_stats_sync(struct nss_tx_rx_virt_if_handle *handle,
-					struct nss_tx_rx_virt_if_stats *nwis)
-{
-	struct nss_tx_rx_virt_if_stats *stats = &handle->stats;
-
-	stats->node_stats.rx_packets += nwis->node_stats.rx_packets;
-	stats->node_stats.rx_bytes += nwis->node_stats.rx_bytes;
-	stats->node_stats.rx_dropped += nwis->node_stats.rx_dropped;
-	stats->node_stats.tx_packets += nwis->node_stats.tx_packets;
-	stats->node_stats.tx_bytes += nwis->node_stats.tx_bytes;
-	stats->tx_enqueue_failed += nwis->tx_enqueue_failed;
-	stats->shaper_enqueue_failed += nwis->shaper_enqueue_failed;
-}
-
-/*
  * nss_tx_rx_virt_if_msg_handler()
  *	Handle msg responses from the FW on virtual interfaces
  */
@@ -395,7 +376,7 @@
  * nss_tx_rx_virt_if_register_handler_sync()
  * 	register msg handler for redir interface and initialize semaphore and completion.
  */
-static uint32_t nss_tx_rx_virt_if_register_handler(struct nss_tx_rx_virt_if_handle *handle)
+uint32_t nss_tx_rx_virt_if_register_handler(struct nss_tx_rx_virt_if_handle *handle)
 {
 	struct nss_ctx_instance *nss_ctx = (struct nss_ctx_instance *)&nss_top_main.nss[nss_top_main.wlan_handler_id];
 
@@ -416,6 +397,7 @@
 		nrip->sem_init_done = 1;
 	}
 
+	nss_tx_rx_virt_if_stats_dentry_create();
 	return NSS_TX_RX_VIRT_IF_SUCCESS;
 }
 
@@ -664,77 +646,6 @@
 	return status;
 }
 
-/*
- * nss_tx_rx_virt_if_copy_stats()
- *	Copy stats from the redir_if handle to buffer(line)
- */
-int32_t nss_tx_rx_virt_if_copy_stats(int32_t if_num, int i, char *line)
-{
-	int32_t bytes = 0;
-	struct nss_tx_rx_virt_if_stats *stats;
-	int32_t ifnum;
-	uint32_t len = 80;
-	struct nss_tx_rx_virt_if_handle *handle = NULL;
-
-	if (if_num < 0) {
-		nss_warning("invalid if_num\n");
-		return 0;
-	}
-
-	ifnum = NSS_TX_RX_VIRT_IF_GET_INDEX(if_num);
-
-	spin_lock_bh(&nss_tx_rx_virt_if_lock);
-	if (!nss_tx_rx_virt_if_handles[ifnum]) {
-		spin_unlock_bh(&nss_tx_rx_virt_if_lock);
-		goto end;
-	}
-
-	handle = nss_tx_rx_virt_if_handles[ifnum];
-	spin_unlock_bh(&nss_tx_rx_virt_if_lock);
-
-	stats = &handle->stats;
-
-	switch (i) {
-	case 0:
-		bytes = scnprintf(line, len, "rx_packets=%d\n",
-					stats->node_stats.rx_packets);
-		break;
-
-	case 1:
-		bytes = scnprintf(line, len, "rx_bytes=%d\n",
-					stats->node_stats.rx_bytes);
-		break;
-
-	case 2:
-		bytes = scnprintf(line, len, "rx_dropped=%d\n",
-					stats->node_stats.rx_dropped);
-		break;
-
-	case 3:
-		bytes = scnprintf(line, len, "tx_packets=%d\n",
-					stats->node_stats.tx_packets);
-		break;
-
-	case 4:
-		bytes = scnprintf(line, len, "tx_bytes=%d\n",
-					stats->node_stats.tx_bytes);
-		break;
-
-	case 5:
-		bytes = scnprintf(line, len, "tx_enqueue_failed=%d\n",
-						stats->tx_enqueue_failed);
-		break;
-
-	case 6:
-		bytes = scnprintf(line, len, "shaper_enqueue_failed=%d\n",
-						stats->shaper_enqueue_failed);
-		break;
-	}
-
-end:
-	return bytes;
-}
-
 EXPORT_SYMBOL(nss_tx_virt_if_rxbuf);
 EXPORT_SYMBOL(nss_tx_virt_if_rx_nwifibuf);
 EXPORT_SYMBOL(nss_create_virt_if);
diff --git a/nss_tx_rx_virt_if_stats.c b/nss_tx_rx_virt_if_stats.c
new file mode 100644
index 0000000..52bcfd2
--- /dev/null
+++ b/nss_tx_rx_virt_if_stats.c
@@ -0,0 +1,213 @@
+/*
+ **************************************************************************
+ * Copyright (c) 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.
+ * 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_stats.h"
+#include "nss_tx_rx_common.h"
+
+/*
+ * Data structure that holds the virtual interface context.
+ */
+extern struct nss_tx_rx_virt_if_handle *nss_tx_rx_virt_if_handles[NSS_MAX_DYNAMIC_INTERFACES];
+
+/*
+ * Spinlock to protect the global data structure virt_handle.
+ */
+extern spinlock_t nss_tx_rx_virt_if_lock;
+
+/*
+ * nss_tx_rx_virt_if_stats_get()
+ *	Get stats from the redir_if handle to buffer(line)
+ */
+static int32_t nss_tx_rx_virt_if_stats_get(int32_t if_num, int i, char *line)
+{
+	int32_t bytes = 0;
+	struct nss_tx_rx_virt_if_stats *stats;
+	int32_t ifnum;
+	uint32_t len = 80;
+	struct nss_tx_rx_virt_if_handle *handle = NULL;
+
+	if (if_num < 0) {
+		nss_warning("invalid if_num\n");
+		return 0;
+	}
+
+	ifnum = NSS_TX_RX_VIRT_IF_GET_INDEX(if_num);
+
+	spin_lock_bh(&nss_tx_rx_virt_if_lock);
+	if (!nss_tx_rx_virt_if_handles[ifnum]) {
+		spin_unlock_bh(&nss_tx_rx_virt_if_lock);
+		goto end;
+	}
+
+	handle = nss_tx_rx_virt_if_handles[ifnum];
+	spin_unlock_bh(&nss_tx_rx_virt_if_lock);
+
+	stats = &handle->stats;
+
+	switch (i) {
+	case 0:
+		bytes = scnprintf(line, len, "rx_packets=%d\n",
+					stats->node_stats.rx_packets);
+		break;
+
+	case 1:
+		bytes = scnprintf(line, len, "rx_bytes=%d\n",
+					stats->node_stats.rx_bytes);
+		break;
+
+	case 2:
+		bytes = scnprintf(line, len, "rx_dropped=%d\n",
+					stats->node_stats.rx_dropped);
+		break;
+
+	case 3:
+		bytes = scnprintf(line, len, "tx_packets=%d\n",
+					stats->node_stats.tx_packets);
+		break;
+
+	case 4:
+		bytes = scnprintf(line, len, "tx_bytes=%d\n",
+					stats->node_stats.tx_bytes);
+		break;
+
+	case 5:
+		bytes = scnprintf(line, len, "tx_enqueue_failed=%d\n",
+						stats->tx_enqueue_failed);
+		break;
+
+	case 6:
+		bytes = scnprintf(line, len, "shaper_enqueue_failed=%d\n",
+						stats->shaper_enqueue_failed);
+		break;
+	}
+
+end:
+	return bytes;
+}
+
+/*
+ * nss_tx_rx_virt_if_stats_ops()
+ *	Read tx_rx_virt_if statistics
+ */
+static ssize_t nss_tx_rx_virt_if_stats_read(struct file *fp, char __user *ubuf,
+						size_t sz, loff_t *ppos)
+{
+	struct nss_stats_data *data = fp->private_data;
+	struct nss_ctx_instance *nss_ctx = (struct nss_ctx_instance *)&nss_top_main.nss[nss_top_main.wifi_handler_id];
+	int32_t if_num = NSS_DYNAMIC_IF_START;
+	int32_t max_if_num = if_num + NSS_MAX_DYNAMIC_INTERFACES;
+	size_t bytes = 0;
+	ssize_t bytes_read = 0;
+	char line[80];
+	int start, end;
+
+	if (data) {
+		if_num = data->if_num;
+	}
+
+	if (if_num > max_if_num) {
+		return 0;
+	}
+
+	for (; if_num < max_if_num; if_num++) {
+		if (nss_dynamic_interface_get_type(nss_ctx, if_num) != NSS_DYNAMIC_INTERFACE_TYPE_VIRTIF_DEPRECATED)
+			continue;
+
+		bytes = scnprintf(line, sizeof(line), "if_num %d stats start:\n\n", if_num);
+		if ((bytes_read + bytes) > sz)
+			break;
+
+		if (copy_to_user(ubuf + bytes_read, line, bytes) != 0) {
+			bytes_read = -EFAULT;
+			goto end;
+		}
+
+		bytes_read += bytes;
+
+		start = 0;
+		end = 7;
+		while (bytes_read < sz && start < end) {
+			bytes = nss_tx_rx_virt_if_stats_get(if_num, start, line);
+			if (!bytes)
+				break;
+
+			if ((bytes_read + bytes) > sz)
+				break;
+
+			if (copy_to_user(ubuf + bytes_read, line, bytes) != 0) {
+				bytes_read = -EFAULT;
+				goto end;
+			}
+
+			bytes_read += bytes;
+			start++;
+		}
+
+		bytes = scnprintf(line, sizeof(line), "if_num %d stats end:\n\n", if_num);
+		if (bytes_read > (sz - bytes))
+			break;
+
+		if (copy_to_user(ubuf + bytes_read, line, bytes) != 0) {
+			bytes_read = -EFAULT;
+			goto end;
+		}
+
+		bytes_read += bytes;
+	}
+
+	if (bytes_read > 0) {
+		*ppos = bytes_read;
+	}
+
+	if (data) {
+		data->if_num = if_num;
+	}
+
+end:
+	return bytes_read;
+}
+
+/*
+ * nss_tx_rx_virt_if_stats_ops
+ */
+NSS_STATS_DECLARE_FILE_OPERATIONS(tx_rx_virt_if)
+
+/*
+ * nss_tx_rx_virt_if_stats_dentry_create()
+ *	Create tx_rx_virt_if statistics debug entry.
+ */
+void nss_tx_rx_virt_if_stats_dentry_create(void)
+{
+	nss_stats_create_dentry("tx_rx_virt_if", &nss_tx_rx_virt_if_stats_ops);
+}
+
+/*
+ * nss_tx_rx_virt_if_stats_sync()
+ *	Sync stats from the NSS FW
+ */
+void nss_tx_rx_virt_if_stats_sync(struct nss_tx_rx_virt_if_handle *handle,
+					struct nss_tx_rx_virt_if_stats *nwis)
+{
+	struct nss_tx_rx_virt_if_stats *stats = &handle->stats;
+
+	stats->node_stats.rx_packets += nwis->node_stats.rx_packets;
+	stats->node_stats.rx_bytes += nwis->node_stats.rx_bytes;
+	stats->node_stats.rx_dropped += nwis->node_stats.rx_dropped;
+	stats->node_stats.tx_packets += nwis->node_stats.tx_packets;
+	stats->node_stats.tx_bytes += nwis->node_stats.tx_bytes;
+	stats->tx_enqueue_failed += nwis->tx_enqueue_failed;
+	stats->shaper_enqueue_failed += nwis->shaper_enqueue_failed;
+}
diff --git a/nss_virt_if.c b/nss_virt_if.c
index e21a0c7..ec3b48d 100644
--- a/nss_virt_if.c
+++ b/nss_virt_if.c
@@ -20,6 +20,7 @@
  */
 
 #include "nss_tx_rx_common.h"
+#include "nss_virt_if_stats.h"
 #include <net/arp.h>
 
 #define NSS_VIRT_IF_TX_TIMEOUT			3000 /* 3 Seconds */
@@ -30,7 +31,7 @@
 /*
  * Data structure that holds the virtual interface context.
  */
-static struct nss_virt_if_handle *nss_virt_if_handle_t[NSS_MAX_DYNAMIC_INTERFACES];
+struct nss_virt_if_handle *nss_virt_if_handle_t[NSS_MAX_DYNAMIC_INTERFACES];
 
 /*
  * Spinlock to protect the global data structure virt_handle.
@@ -38,24 +39,6 @@
 DEFINE_SPINLOCK(nss_virt_if_lock);
 
 /*
- * nss_virt_if_stats_sync()
- *	Sync stats from the NSS FW
- */
-static void nss_virt_if_stats_sync(struct nss_virt_if_handle *handle,
-					struct nss_virt_if_stats *nwis)
-{
-	struct nss_virt_if_stats *stats = &handle->stats;
-
-	stats->node_stats.rx_packets += nwis->node_stats.rx_packets;
-	stats->node_stats.rx_bytes += nwis->node_stats.rx_bytes;
-	stats->node_stats.rx_dropped += nwis->node_stats.rx_dropped;
-	stats->node_stats.tx_packets += nwis->node_stats.tx_packets;
-	stats->node_stats.tx_bytes += nwis->node_stats.tx_bytes;
-	stats->tx_enqueue_failed += nwis->tx_enqueue_failed;
-	stats->shaper_enqueue_failed += nwis->shaper_enqueue_failed;
-}
-
-/*
  * nss_virt_if_msg_handler()
  *	Handle msg responses from the FW on virtual interfaces
  */
@@ -505,6 +488,7 @@
 		nvip->sem_init_done = 1;
 	}
 
+	nss_virt_if_stats_dentry_create();
 	return NSS_VIRT_IF_SUCCESS;
 }
 
@@ -909,77 +893,6 @@
 EXPORT_SYMBOL(nss_virt_if_unregister);
 
 /*
- * nss_virt_if_copy_stats()
- *	Copy stats from the virt_if handle to buffer(line)
- */
-int32_t nss_virt_if_copy_stats(int32_t if_num, int i, char *line)
-{
-	int32_t bytes = 0;
-	struct nss_virt_if_stats *stats;
-	int32_t ifnum;
-	uint32_t len = 80;
-	struct nss_virt_if_handle *handle = NULL;
-
-	if (if_num < 0) {
-		nss_warning("invalid if_num\n");
-		return 0;
-	}
-
-	ifnum = NSS_VIRT_IF_GET_INDEX(if_num);
-
-	spin_lock_bh(&nss_virt_if_lock);
-	if (!nss_virt_if_handle_t[ifnum]) {
-		spin_unlock_bh(&nss_virt_if_lock);
-		goto end;
-	}
-
-	handle = nss_virt_if_handle_t[ifnum];
-	spin_unlock_bh(&nss_virt_if_lock);
-
-	stats = &handle->stats;
-
-	switch (i) {
-	case 0:
-		bytes = scnprintf(line, len, "rx_packets=%d\n",
-					stats->node_stats.rx_packets);
-		break;
-
-	case 1:
-		bytes = scnprintf(line, len, "rx_bytes=%d\n",
-					stats->node_stats.rx_bytes);
-		break;
-
-	case 2:
-		bytes = scnprintf(line, len, "rx_dropped=%d\n",
-					stats->node_stats.rx_dropped);
-		break;
-
-	case 3:
-		bytes = scnprintf(line, len, "tx_packets=%d\n",
-					stats->node_stats.tx_packets);
-		break;
-
-	case 4:
-		bytes = scnprintf(line, len, "tx_bytes=%d\n",
-					stats->node_stats.tx_bytes);
-		break;
-
-	case 5:
-		bytes = scnprintf(line, len, "tx_enqueue_failed=%d\n",
-						stats->tx_enqueue_failed);
-		break;
-
-	case 6:
-		bytes = scnprintf(line, len, "shaper_enqueue_failed=%d\n",
-						stats->shaper_enqueue_failed);
-		break;
-	}
-
-end:
-	return bytes;
-}
-
-/*
  * nss_virt_if_get_interface_num()
  * Get interface number for a virtual interface
  */
diff --git a/nss_virt_if_stats.c b/nss_virt_if_stats.c
new file mode 100644
index 0000000..5c923dd
--- /dev/null
+++ b/nss_virt_if_stats.c
@@ -0,0 +1,213 @@
+/*
+ **************************************************************************
+ * Copyright (c) 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.
+ * 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_stats.h"
+#include "nss_tx_rx_common.h"
+
+/*
+ * Data structure that holds the virtual interface context.
+ */
+extern struct nss_virt_if_handle *nss_virt_if_handle_t[];
+
+/*
+ * Spinlock to protect the global data structure virt_handle.
+ */
+extern spinlock_t nss_virt_if_lock;
+
+/*
+ * nss_virt_if_stats_get()
+ *	Get stats from the virt_if handle to buffer(line)
+ */
+static int32_t nss_virt_if_stats_get(int32_t if_num, int i, char *line)
+{
+	int32_t bytes = 0;
+	struct nss_virt_if_stats *stats;
+	int32_t ifnum;
+	uint32_t len = 80;
+	struct nss_virt_if_handle *handle = NULL;
+
+	if (if_num < 0) {
+		nss_warning("invalid if_num\n");
+		return 0;
+	}
+
+	ifnum = if_num - NSS_DYNAMIC_IF_START;
+
+	spin_lock_bh(&nss_virt_if_lock);
+	if (!nss_virt_if_handle_t[ifnum]) {
+		spin_unlock_bh(&nss_virt_if_lock);
+		goto end;
+	}
+
+	handle = nss_virt_if_handle_t[ifnum];
+	spin_unlock_bh(&nss_virt_if_lock);
+
+	stats = &handle->stats;
+
+	switch (i) {
+	case 0:
+		bytes = scnprintf(line, len, "rx_packets=%d\n",
+					stats->node_stats.rx_packets);
+		break;
+
+	case 1:
+		bytes = scnprintf(line, len, "rx_bytes=%d\n",
+					stats->node_stats.rx_bytes);
+		break;
+
+	case 2:
+		bytes = scnprintf(line, len, "rx_dropped=%d\n",
+					stats->node_stats.rx_dropped);
+		break;
+
+	case 3:
+		bytes = scnprintf(line, len, "tx_packets=%d\n",
+					stats->node_stats.tx_packets);
+		break;
+
+	case 4:
+		bytes = scnprintf(line, len, "tx_bytes=%d\n",
+					stats->node_stats.tx_bytes);
+		break;
+
+	case 5:
+		bytes = scnprintf(line, len, "tx_enqueue_failed=%d\n",
+						stats->tx_enqueue_failed);
+		break;
+
+	case 6:
+		bytes = scnprintf(line, len, "shaper_enqueue_failed=%d\n",
+						stats->shaper_enqueue_failed);
+		break;
+	}
+
+end:
+	return bytes;
+}
+
+/*
+ * nss_virt_if_stats_read()
+ *	Read virt_if statistics
+ */
+static ssize_t nss_virt_if_stats_read(struct file *fp, char __user *ubuf,
+						size_t sz, loff_t *ppos)
+{
+	struct nss_stats_data *data = fp->private_data;
+	struct nss_ctx_instance *nss_ctx = (struct nss_ctx_instance *)&nss_top_main.nss[nss_top_main.wifi_handler_id];
+	int32_t if_num = NSS_DYNAMIC_IF_START;
+	int32_t max_if_num = if_num + NSS_MAX_DYNAMIC_INTERFACES;
+	size_t bytes = 0;
+	ssize_t bytes_read = 0;
+	char line[80];
+	int start, end;
+
+	if (data) {
+		if_num = data->if_num;
+	}
+
+	if (if_num > max_if_num) {
+		return 0;
+	}
+
+	for (; if_num < max_if_num; if_num++) {
+		if (nss_dynamic_interface_get_type(nss_ctx, if_num) != NSS_DYNAMIC_INTERFACE_TYPE_802_3_REDIR)
+			continue;
+
+		bytes = scnprintf(line, sizeof(line), "if_num %d stats start:\n\n", if_num);
+		if ((bytes_read + bytes) > sz)
+			break;
+
+		if (copy_to_user(ubuf + bytes_read, line, bytes) != 0) {
+			bytes_read = -EFAULT;
+			goto end;
+		}
+
+		bytes_read += bytes;
+
+		start = 0;
+		end = 7;
+		while (bytes_read < sz && start < end) {
+			bytes = nss_virt_if_stats_get(if_num, start, line);
+			if (!bytes)
+				break;
+
+			if ((bytes_read + bytes) > sz)
+				break;
+
+			if (copy_to_user(ubuf + bytes_read, line, bytes) != 0) {
+				bytes_read = -EFAULT;
+				goto end;
+			}
+
+			bytes_read += bytes;
+			start++;
+		}
+
+		bytes = scnprintf(line, sizeof(line), "if_num %d stats end:\n\n", if_num);
+		if (bytes_read > (sz - bytes))
+			break;
+
+		if (copy_to_user(ubuf + bytes_read, line, bytes) != 0) {
+			bytes_read = -EFAULT;
+			goto end;
+		}
+
+		bytes_read += bytes;
+	}
+
+	if (bytes_read > 0) {
+		*ppos = bytes_read;
+	}
+
+	if (data) {
+		data->if_num = if_num;
+	}
+
+end:
+	return bytes_read;
+}
+
+/*
+ * nss_virt_if_stats_ops
+ */
+NSS_STATS_DECLARE_FILE_OPERATIONS(virt_if)
+
+/*
+ * nss_virt_if_stats_dentry_create()
+ *	Create virt_if statistics debug entry.
+ */
+void nss_virt_if_stats_dentry_create(void)
+{
+	nss_stats_create_dentry("virt_if", &nss_virt_if_stats_ops);
+}
+
+/*
+ * nss_virt_if_stats_sync()
+ *	Sync stats from the NSS FW
+ */
+void nss_virt_if_stats_sync(struct nss_virt_if_handle *handle,
+					struct nss_virt_if_stats *nwis)
+{
+	struct nss_virt_if_stats *stats = &handle->stats;
+
+	stats->node_stats.rx_packets += nwis->node_stats.rx_packets;
+	stats->node_stats.rx_bytes += nwis->node_stats.rx_bytes;
+	stats->node_stats.rx_dropped += nwis->node_stats.rx_dropped;
+	stats->node_stats.tx_packets += nwis->node_stats.tx_packets;
+	stats->node_stats.tx_bytes += nwis->node_stats.tx_bytes;
+	stats->tx_enqueue_failed += nwis->tx_enqueue_failed;
+	stats->shaper_enqueue_failed += nwis->shaper_enqueue_failed;
+}
diff --git a/nss_virt_if_stats.h b/nss_virt_if_stats.h
new file mode 100644
index 0000000..d6e4448
--- /dev/null
+++ b/nss_virt_if_stats.h
@@ -0,0 +1,26 @@
+/*
+ ******************************************************************************
+ * 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.
+ * ****************************************************************************
+ */
+
+#ifndef __NSS_VIRT_IF_STATS_H
+#define __NSS_VIRT_IF_STATS_H
+
+/*
+ * Virtual interface statistics APIs
+ */
+extern void nss_virt_if_stats_sync(struct nss_virt_if_handle *handle, struct nss_virt_if_stats *nwis);
+extern void nss_virt_if_stats_dentry_create(void);
+
+#endif /* __NSS_VIRT_IF_STATS_H */
diff --git a/nss_wifi.c b/nss_wifi.c
index fab4c7c..fb2ec65 100644
--- a/nss_wifi.c
+++ b/nss_wifi.c
@@ -15,63 +15,7 @@
  */
 
 #include "nss_tx_rx_common.h"
-
-/*
- * nss_wifi_stats_sync()
- *	Handle the syncing of WIFI stats.
- */
-void nss_wifi_stats_sync(struct nss_ctx_instance *nss_ctx,
-		struct nss_wifi_stats_sync_msg *stats, uint16_t interface)
-{
-	struct nss_top_instance *nss_top = nss_ctx->nss_top;
-	uint32_t radio_id = interface - NSS_WIFI_INTERFACE0;
-	int i = 0;
-
-	if (radio_id >= NSS_MAX_WIFI_RADIO_INTERFACES) {
-		nss_warning("%p: invalid interface: %d", nss_ctx, interface);
-		return;
-	}
-
-	spin_lock_bh(&nss_top->stats_lock);
-
-	/*
-	 * Tx/Rx stats
-	 */
-	nss_top->stats_wifi[radio_id][NSS_STATS_WIFI_RX_PKTS] += stats->node_stats.rx_packets;
-	for (i = 0; i < NSS_MAX_NUM_PRI; i++) {
-		nss_top->stats_wifi[radio_id][NSS_STATS_WIFI_RX_QUEUE_0_DROPPED + i] += stats->node_stats.rx_dropped[i];
-	}
-	nss_top->stats_wifi[radio_id][NSS_STATS_WIFI_TX_PKTS] += stats->node_stats.tx_packets;
-	nss_top->stats_wifi[radio_id][NSS_STATS_WIFI_TX_DROPPED] += stats->tx_transmit_dropped;
-	nss_top->stats_wifi[radio_id][NSS_STATS_WIFI_TX_COMPLETED] += stats->tx_transmit_completions;
-	nss_top->stats_wifi[radio_id][NSS_STATS_WIFI_MGMT_RCV_CNT] += stats->tx_mgmt_rcv_cnt;
-	nss_top->stats_wifi[radio_id][NSS_STATS_WIFI_MGMT_TX_PKTS] += stats->tx_mgmt_pkts;
-	nss_top->stats_wifi[radio_id][NSS_STATS_WIFI_MGMT_TX_DROPPED] += stats->tx_mgmt_dropped;
-	nss_top->stats_wifi[radio_id][NSS_STATS_WIFI_MGMT_TX_COMPLETIONS] += stats->tx_mgmt_completions;
-	nss_top->stats_wifi[radio_id][NSS_STATS_WIFI_TX_INV_PEER_ENQUEUE_CNT] += stats->tx_inv_peer_enq_cnt;
-	nss_top->stats_wifi[radio_id][NSS_STATS_WIFI_RX_INV_PEER_RCV_CNT] += stats->rx_inv_peer_rcv_cnt;
-	nss_top->stats_wifi[radio_id][NSS_STATS_WIFI_RX_PN_CHECK_FAILED] += stats->rx_pn_check_failed;
-	nss_top->stats_wifi[radio_id][NSS_STATS_WIFI_RX_DELIVERED] += stats->rx_pkts_deliverd;
-	nss_top->stats_wifi[radio_id][NSS_STATS_WIFI_RX_BYTES_DELIVERED] += stats->rx_bytes_deliverd;
-	nss_top->stats_wifi[radio_id][NSS_STATS_WIFI_TX_BYTES_COMPLETED] += stats->tx_bytes_transmit_completions;
-	nss_top->stats_wifi[radio_id][NSS_STATS_WIFI_RX_DELIVER_UNALIGNED_DROP_CNT] += stats->rx_deliver_unaligned_drop_cnt;
-
-	for (i = 0; i < NSS_WIFI_TX_NUM_TOS_TIDS; i++) {
-		nss_top->stats_wifi[radio_id][NSS_STATS_WIFI_TIDQ_ENQUEUE_CNT + i] += stats->tidq_enqueue_cnt[i];
-		nss_top->stats_wifi[radio_id][NSS_STATS_WIFI_TIDQ_DEQUEUE_CNT + i] += stats->tidq_dequeue_cnt[i];
-		nss_top->stats_wifi[radio_id][NSS_STATS_WIFI_TIDQ_ENQUEUE_FAIL_CNT + i] += stats->tidq_enqueue_fail_cnt[i];
-		nss_top->stats_wifi[radio_id][NSS_STATS_WIFI_TIDQ_TTL_EXPIRE_CNT + i] += stats->tidq_ttl_expire_cnt[i];
-		nss_top->stats_wifi[radio_id][NSS_STATS_WIFI_TIDQ_DEQUEUE_REQ_CNT + i] += stats->tidq_dequeue_req_cnt[i];
-	}
-
-	nss_top->stats_wifi[radio_id][NSS_STATS_WIFI_RX_HTT_FETCH_CNT] += stats->rx_htt_fetch_cnt;
-	nss_top->stats_wifi[radio_id][NSS_STATS_WIFI_TOTAL_TIDQ_DEPTH] = stats->total_tidq_depth;
-	nss_top->stats_wifi[radio_id][NSS_STATS_WIFI_TOTAL_TIDQ_BYPASS_CNT] += stats->total_tidq_bypass_cnt;
-	nss_top->stats_wifi[radio_id][NSS_STATS_WIFI_GLOBAL_Q_FULL_CNT] += stats->global_q_full_cnt;
-	nss_top->stats_wifi[radio_id][NSS_STATS_WIFI_TIDQ_FULL_CNT] += stats->tidq_full_cnt;
-
-	spin_unlock_bh(&nss_top->stats_lock);
-}
+#include "nss_wifi_stats.h"
 
 /*
  * nss_wifi_get_context()
@@ -100,7 +44,7 @@
 	 * Is this a valid request/response packet?
 	 */
 	if (ncm->type >= NSS_WIFI_MAX_MSG) {
-		nss_warning("%p: received invalid message %d for wifi  interface", nss_ctx, ncm->type);
+		nss_warning("%p: received invalid message %d for wifi interface", nss_ctx, ncm->type);
 		return;
 	}
 
@@ -273,6 +217,8 @@
 	nss_core_register_handler(nss_ctx, NSS_WIFI_INTERFACE0, nss_wifi_handler, NULL);
 	nss_core_register_handler(nss_ctx, NSS_WIFI_INTERFACE1, nss_wifi_handler, NULL);
 	nss_core_register_handler(nss_ctx, NSS_WIFI_INTERFACE2, nss_wifi_handler, NULL);
+
+	nss_wifi_stats_dentry_create();
 }
 
 EXPORT_SYMBOL(nss_wifi_get_context);
diff --git a/nss_wifi_if.c b/nss_wifi_if.c
index 2af86c3..451d457 100644
--- a/nss_wifi_if.c
+++ b/nss_wifi_if.c
@@ -20,6 +20,7 @@
  */
 
 #include "nss_tx_rx_common.h"
+#include "nss_wifi_if_stats.h"
 #include <net/arp.h>
 
 #define NSS_WIFI_IF_TX_TIMEOUT			3000 /* 3 Seconds */
@@ -30,7 +31,7 @@
 /*
  * Data structure that holds the wifi interface context.
  */
-static struct nss_wifi_if_handle *wifi_handle[NSS_MAX_DYNAMIC_INTERFACES];
+struct nss_wifi_if_handle *wifi_handle[NSS_MAX_DYNAMIC_INTERFACES];
 
 /*
  * Spinlock to protect the global data structure wifi_handle.
@@ -38,24 +39,6 @@
 DEFINE_SPINLOCK(wifi_if_lock);
 
 /*
- * nss_wifi_if_stats_sync()
- *	Sync stats from the NSS FW
- */
-static void nss_wifi_if_stats_sync(struct nss_wifi_if_handle *handle,
-					struct nss_wifi_if_stats *nwis)
-{
-	struct nss_wifi_if_stats *stats = &handle->stats;
-
-	stats->node_stats.rx_packets += nwis->node_stats.rx_packets;
-	stats->node_stats.rx_bytes += nwis->node_stats.rx_bytes;
-	stats->node_stats.rx_dropped += nwis->node_stats.rx_dropped;
-	stats->node_stats.tx_packets += nwis->node_stats.tx_packets;
-	stats->node_stats.tx_bytes += nwis->node_stats.tx_bytes;
-	stats->tx_enqueue_failed += nwis->tx_enqueue_failed;
-	stats->shaper_enqueue_failed += nwis->shaper_enqueue_failed;
-}
-
-/*
  * nss_wifi_if_msg_handler()
  *	Handle NSS -> HLOS messages for wifi interface
  */
@@ -159,6 +142,7 @@
 		nwip->sem_init_done = 1;
 	}
 
+	nss_wifi_if_stats_dentry_create();
 	return NSS_WIFI_IF_SUCCESS;
 }
 
@@ -589,68 +573,3 @@
 }
 EXPORT_SYMBOL(nss_wifi_if_tx_buf);
 
-/*
- * nss_wifi_if_copy_stats()
- *	Copy the stats from wifi handle to buffer(line) for if_num.
- */
-int32_t nss_wifi_if_copy_stats(int32_t if_num, int i, char *line)
-{
-	int32_t bytes = 0;
-	struct nss_wifi_if_stats *stats;
-	int32_t ifnum;
-	uint32_t len = 80;
-	struct nss_wifi_if_handle *handle = NULL;
-
-	ifnum = NSS_WIFI_IF_GET_INDEX(if_num);
-
-	spin_lock_bh(&wifi_if_lock);
-	if (!wifi_handle[ifnum]) {
-		spin_unlock_bh(&wifi_if_lock);
-		goto end;
-	}
-
-	handle = wifi_handle[ifnum];
-	spin_unlock_bh(&wifi_if_lock);
-
-	stats = &handle->stats;
-
-	switch (i) {
-	case 0:
-		bytes = scnprintf(line, len, "rx_packets=%d\n",
-					stats->node_stats.rx_packets);
-		break;
-
-	case 1:
-		bytes = scnprintf(line, len, "rx_bytes=%d\n",
-					stats->node_stats.rx_bytes);
-		break;
-
-	case 2:
-		bytes = scnprintf(line, len, "rx_dropped=%d\n",
-					stats->node_stats.rx_dropped);
-		break;
-
-	case 3:
-		bytes = scnprintf(line, len, "tx_packets=%d\n",
-					stats->node_stats.tx_packets);
-		break;
-
-	case 4:
-		bytes = scnprintf(line, len, "tx_bytes=%d\n",
-					stats->node_stats.tx_bytes);
-		break;
-
-	case 5:
-		bytes = scnprintf(line, len, "tx_enqueue_failed=%d\n",
-					stats->tx_enqueue_failed);
-		break;
-
-	case 6:
-		bytes = scnprintf(line, len, "shaper_enqueue_failed=%d\n",
-					stats->shaper_enqueue_failed);
-		break;
-	}
-
-end:
-	return bytes;
-}
diff --git a/nss_wifi_if_stats.c b/nss_wifi_if_stats.c
new file mode 100644
index 0000000..aa0f758
--- /dev/null
+++ b/nss_wifi_if_stats.c
@@ -0,0 +1,207 @@
+/*
+ **************************************************************************
+ * Copyright (c) 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.
+ * 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_stats.h"
+#include "nss_core.h"
+#include "nss_wifi_if.h"
+
+/*
+ * Data structure that holds the wifi interface context.
+ */
+extern struct nss_wifi_if_handle *wifi_handle[];
+
+/*
+ * Spinlock to protect the global data structure wifi_handle.
+ */
+extern spinlock_t wifi_if_lock;
+
+/*
+ * nss_wifi_if_stats_get()
+ *	Get the stats from wifi handle to buffer(line) for if_num.
+ */
+static int32_t nss_wifi_if_stats_get(int32_t if_num, int i, char *line)
+{
+	int32_t bytes = 0;
+	struct nss_wifi_if_stats *stats;
+	int32_t ifnum;
+	uint32_t len = 80;
+	struct nss_wifi_if_handle *handle = NULL;
+
+	ifnum = if_num - NSS_DYNAMIC_IF_START;
+
+	spin_lock_bh(&wifi_if_lock);
+	if (!wifi_handle[ifnum]) {
+		spin_unlock_bh(&wifi_if_lock);
+		goto end;
+	}
+
+	handle = wifi_handle[ifnum];
+	spin_unlock_bh(&wifi_if_lock);
+	stats = &handle->stats;
+
+	switch (i) {
+	case 0:
+		bytes = scnprintf(line, len, "rx_packets=%d\n",
+					stats->node_stats.rx_packets);
+		break;
+
+	case 1:
+		bytes = scnprintf(line, len, "rx_bytes=%d\n",
+					stats->node_stats.rx_bytes);
+		break;
+
+	case 2:
+		bytes = scnprintf(line, len, "rx_dropped=%d\n",
+					stats->node_stats.rx_dropped);
+		break;
+
+	case 3:
+		bytes = scnprintf(line, len, "tx_packets=%d\n",
+					stats->node_stats.tx_packets);
+		break;
+
+	case 4:
+		bytes = scnprintf(line, len, "tx_bytes=%d\n",
+					stats->node_stats.tx_bytes);
+		break;
+
+	case 5:
+		bytes = scnprintf(line, len, "tx_enqueue_failed=%d\n",
+					stats->tx_enqueue_failed);
+		break;
+
+	case 6:
+		bytes = scnprintf(line, len, "shaper_enqueue_failed=%d\n",
+					stats->shaper_enqueue_failed);
+		break;
+	}
+
+end:
+	return bytes;
+}
+
+/*
+ * nss_wifi_if_stats_read()
+ *	Read wifi_if statistics
+ */
+static ssize_t nss_wifi_if_stats_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
+{
+	struct nss_stats_data *data = fp->private_data;
+	struct nss_ctx_instance *nss_ctx = (struct nss_ctx_instance *)&nss_top_main.nss[nss_top_main.wifi_handler_id];
+	int32_t if_num = NSS_DYNAMIC_IF_START;
+	int32_t max_if_num = if_num + NSS_MAX_DYNAMIC_INTERFACES;
+	size_t bytes = 0;
+	ssize_t bytes_read = 0;
+	char line[80];
+	int start, end;
+
+	if (data) {
+		if_num = data->if_num;
+	}
+
+	if (if_num > max_if_num) {
+		return 0;
+	}
+
+	for (; if_num < max_if_num; if_num++) {
+		if (nss_dynamic_interface_get_type(nss_ctx, if_num) != NSS_DYNAMIC_INTERFACE_TYPE_WIFI)
+			continue;
+
+		bytes = scnprintf(line, sizeof(line), "if_num %d stats start:\n\n", if_num);
+		if ((bytes_read + bytes) > sz)
+			break;
+
+		if (copy_to_user(ubuf + bytes_read, line, bytes) != 0) {
+			bytes_read = -EFAULT;
+			goto end;
+		}
+
+		bytes_read += bytes;
+
+		start = 0;
+		end = 7;
+		while (bytes_read < sz && start < end) {
+			bytes = nss_wifi_if_stats_get(if_num, start, line);
+			if (!bytes)
+				break;
+
+			if ((bytes_read + bytes) > sz)
+				break;
+
+			if (copy_to_user(ubuf + bytes_read, line, bytes) != 0) {
+				bytes_read = -EFAULT;
+				goto end;
+			}
+
+			bytes_read += bytes;
+			start++;
+		}
+
+		bytes = scnprintf(line, sizeof(line), "if_num %d stats end:\n\n", if_num);
+		if (bytes_read > (sz - bytes))
+			break;
+
+		if (copy_to_user(ubuf + bytes_read, line, bytes) != 0) {
+			bytes_read = -EFAULT;
+			goto end;
+		}
+
+		bytes_read += bytes;
+	}
+
+	if (bytes_read > 0) {
+		*ppos = bytes_read;
+	}
+
+	if (data) {
+		data->if_num = if_num;
+	}
+
+end:
+	return bytes_read;
+}
+
+/*
+ * nss_wifi_if_stats_ops
+ */
+NSS_STATS_DECLARE_FILE_OPERATIONS(wifi_if)
+
+/*
+ * nss_wifi_if_stats_dentry_create()
+ *	Create wifi_if statistics debug entry.
+ */
+void nss_wifi_if_stats_dentry_create(void)
+{
+	nss_stats_create_dentry("wifi_if", &nss_wifi_if_stats_ops);
+}
+
+/*
+ * nss_wifi_if_stats_sync()
+ *	Sync stats from the NSS FW
+ */
+void nss_wifi_if_stats_sync(struct nss_wifi_if_handle *handle,
+					struct nss_wifi_if_stats *nwis)
+{
+	struct nss_wifi_if_stats *stats = &handle->stats;
+
+	stats->node_stats.rx_packets += nwis->node_stats.rx_packets;
+	stats->node_stats.rx_bytes += nwis->node_stats.rx_bytes;
+	stats->node_stats.rx_dropped += nwis->node_stats.rx_dropped;
+	stats->node_stats.tx_packets += nwis->node_stats.tx_packets;
+	stats->node_stats.tx_bytes += nwis->node_stats.tx_bytes;
+	stats->tx_enqueue_failed += nwis->tx_enqueue_failed;
+	stats->shaper_enqueue_failed += nwis->shaper_enqueue_failed;
+}
diff --git a/nss_wifi_if_stats.h b/nss_wifi_if_stats.h
new file mode 100644
index 0000000..ffc1f83
--- /dev/null
+++ b/nss_wifi_if_stats.h
@@ -0,0 +1,26 @@
+/*
+ ******************************************************************************
+ * 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.
+ * ****************************************************************************
+ */
+
+#ifndef __NSS_WIFI_IF_STATS_H
+#define __NSS_WIFI_IF_STATS_H
+
+/*
+ * wifi interface statistics APIs
+ */
+extern void nss_wifi_if_stats_sync(struct nss_wifi_if_handle *handle, struct nss_wifi_if_stats *nwis);
+extern void nss_wifi_if_stats_dentry_create(void);
+
+#endif /* __NSS_WIFI_IF_STATS_H */
diff --git a/nss_wifi_stats.c b/nss_wifi_stats.c
new file mode 100644
index 0000000..c925f71
--- /dev/null
+++ b/nss_wifi_stats.c
@@ -0,0 +1,220 @@
+/*
+ **************************************************************************
+ * Copyright (c) 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.
+ * 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_stats.h"
+#include "nss_core.h"
+#include "nss_wifi.h"
+#include "nss_wifi_stats.h"
+
+/*
+ * nss_wifi_stats_str
+ * 	Wifi statistics strings
+ */
+static int8_t *nss_wifi_stats_str[NSS_WIFI_STATS_MAX] = {
+	"RX_PACKETS",
+	"RX_QUEUE_0_DROPPED",
+	"RX_QUEUE_1_DROPPED",
+	"RX_QUEUE_2_DROPPED",
+	"RX_QUEUE_3_DROPPED",
+	"TX_PACKETS",
+	"TX_DROPPED",
+	"TX_TRANSMIT_COMPLETED",
+	"TX_MGMT_RECEIVED",
+	"TX_MGMT_TRANSMITTED",
+	"TX_MGMT_DROPPED",
+	"TX_MGMT_COMPLETED",
+	"TX_INV_PEER_ENQ_CNT",
+	"RX_INV_PEER_RCV_CNT",
+	"RX_PN_CHECK_FAILED",
+	"RX_PKTS_DELIVERD",
+	"RX_BYTES_DELIVERED",
+	"TX_BYTES_COMPLETED",
+	"RX_DELIVER_UNALIGNED_DROP_CNT",
+	"TIDQ_ENQUEUE_CNT_0",
+	"TIDQ_ENQUEUE_CNT_1",
+	"TIDQ_ENQUEUE_CNT_2",
+	"TIDQ_ENQUEUE_CNT_3",
+	"TIDQ_ENQUEUE_CNT_4",
+	"TIDQ_ENQUEUE_CNT_5",
+	"TIDQ_ENQUEUE_CNT_6",
+	"TIDQ_ENQUEUE_CNT_7",
+	"TIDQ_DEQUEUE_CNT_0",
+	"TIDQ_DEQUEUE_CNT_1",
+	"TIDQ_DEQUEUE_CNT_2",
+	"TIDQ_DEQUEUE_CNT_3",
+	"TIDQ_DEQUEUE_CNT_4",
+	"TIDQ_DEQUEUE_CNT_5",
+	"TIDQ_DEQUEUE_CNT_6",
+	"TIDQ_DEQUEUE_CNT_7",
+	"TIDQ_ENQUEUE_FAIL_CNT_0",
+	"TIDQ_ENQUEUE_FAIL_CNT_1",
+	"TIDQ_ENQUEUE_FAIL_CNT_2",
+	"TIDQ_ENQUEUE_FAIL_CNT_3",
+	"TIDQ_ENQUEUE_FAIL_CNT_4",
+	"TIDQ_ENQUEUE_FAIL_CNT_5",
+	"TIDQ_ENQUEUE_FAIL_CNT_6",
+	"TIDQ_ENQUEUE_FAIL_CNT_7",
+	"TIDQ_TTL_EXPIRE_CNT_0",
+	"TIDQ_TTL_EXPIRE_CNT_1",
+	"TIDQ_TTL_EXPIRE_CNT_2",
+	"TIDQ_TTL_EXPIRE_CNT_3",
+	"TIDQ_TTL_EXPIRE_CNT_4",
+	"TIDQ_TTL_EXPIRE_CNT_5",
+	"TIDQ_TTL_EXPIRE_CNT_6",
+	"TIDQ_TTL_EXPIRE_CNT_7",
+	"TIDQ_DEQUEUE_REQ_CNT_0",
+	"TIDQ_DEQUEUE_REQ_CNT_1",
+	"TIDQ_DEQUEUE_REQ_CNT_2",
+	"TIDQ_DEQUEUE_REQ_CNT_3",
+	"TIDQ_DEQUEUE_REQ_CNT_4",
+	"TIDQ_DEQUEUE_REQ_CNT_5",
+	"TIDQ_DEQUEUE_REQ_CNT_6",
+	"TIDQ_DEQUEUE_REQ_CNT_7",
+	"TOTAL_TIDQ_DEPTH",
+	"RX_HTT_FETCH_CNT",
+	"TOTAL_TIDQ_BYPASS_CNT",
+	"GLOBAL_Q_FULL_CNT",
+	"TIDQ_FULL_CNT",
+};
+
+uint64_t nss_wifi_stats[NSS_MAX_WIFI_RADIO_INTERFACES][NSS_WIFI_STATS_MAX]; /* WIFI statistics */
+
+/*
+ * nss_wifi_stats_read()
+ *	Read wifi statistics
+ */
+static ssize_t nss_wifi_stats_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
+{
+	uint32_t i, id;
+
+	/*
+	 * max output lines = ((#stats + start tag + one blank) * #WIFI RADIOs) + start/end tag + 3 blank
+	 */
+	uint32_t max_output_lines = ((NSS_WIFI_STATS_MAX + 2) * NSS_MAX_WIFI_RADIO_INTERFACES) + 5;
+	size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
+	size_t size_wr = 0;
+	ssize_t bytes_read = 0;
+	uint64_t *stats_shadow;
+
+	char *lbuf = kzalloc(size_al, GFP_KERNEL);
+	if (unlikely(lbuf == NULL)) {
+		nss_warning("Could not allocate memory for local statistics buffer");
+		return 0;
+	}
+
+	stats_shadow = kzalloc(NSS_WIFI_STATS_MAX * 8, GFP_KERNEL);
+	if (unlikely(stats_shadow == NULL)) {
+		nss_warning("Could not allocate memory for local shadow buffer");
+		kfree(lbuf);
+		return 0;
+	}
+
+	size_wr = scnprintf(lbuf, size_al, "wifi stats start:\n\n");
+
+	for (id = 0; id < NSS_MAX_WIFI_RADIO_INTERFACES; id++) {
+		spin_lock_bh(&nss_top_main.stats_lock);
+		for (i = 0; (i < NSS_WIFI_STATS_MAX); i++) {
+			stats_shadow[i] = nss_wifi_stats[id][i];
+		}
+
+		spin_unlock_bh(&nss_top_main.stats_lock);
+
+		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "WIFI ID: %d\n", id);
+		for (i = 0; (i < NSS_WIFI_STATS_MAX); i++) {
+			size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
+					"%s = %llu\n", nss_wifi_stats_str[i], stats_shadow[i]);
+		}
+		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\n");
+	}
+
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nwifi stats end\n\n");
+	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
+	kfree(lbuf);
+	kfree(stats_shadow);
+
+	return bytes_read;
+}
+
+/*
+ * nss_wifi_stats_ops
+ */
+NSS_STATS_DECLARE_FILE_OPERATIONS(wifi)
+
+/*
+ * nss_wifi_stats_dentry_create()
+ *	Create wifi statistics debug entry.
+ */
+void nss_wifi_stats_dentry_create(void)
+{
+	nss_stats_create_dentry("wifi", &nss_wifi_stats_ops);
+}
+
+/*
+ * nss_wifi_stats_sync()
+ *	Handle the syncing of WIFI stats.
+ */
+void nss_wifi_stats_sync(struct nss_ctx_instance *nss_ctx,
+		struct nss_wifi_stats_sync_msg *stats, uint16_t interface)
+{
+	struct nss_top_instance *nss_top = nss_ctx->nss_top;
+	uint32_t radio_id = interface - NSS_WIFI_INTERFACE0;
+	uint8_t i = 0;
+
+	if (radio_id >= NSS_MAX_WIFI_RADIO_INTERFACES) {
+		nss_warning("%p: invalid interface: %d", nss_ctx, interface);
+		return;
+	}
+
+	spin_lock_bh(&nss_top->stats_lock);
+
+	/*
+	 * Tx/Rx stats
+	 */
+	nss_wifi_stats[radio_id][NSS_WIFI_STATS_RX_PKTS] += stats->node_stats.rx_packets;
+	for (i = 0; i < NSS_MAX_NUM_PRI; i++) {
+		nss_wifi_stats[radio_id][NSS_WIFI_STATS_RX_QUEUE_0_DROPPED + i] += stats->node_stats.rx_dropped[i];
+	}
+	nss_wifi_stats[radio_id][NSS_WIFI_STATS_TX_PKTS] += stats->node_stats.tx_packets;
+	nss_wifi_stats[radio_id][NSS_WIFI_STATS_TX_DROPPED] += stats->tx_transmit_dropped;
+	nss_wifi_stats[radio_id][NSS_WIFI_STATS_TX_COMPLETED] += stats->tx_transmit_completions;
+	nss_wifi_stats[radio_id][NSS_WIFI_STATS_MGMT_RCV_CNT] += stats->tx_mgmt_rcv_cnt;
+	nss_wifi_stats[radio_id][NSS_WIFI_STATS_MGMT_TX_PKTS] += stats->tx_mgmt_pkts;
+	nss_wifi_stats[radio_id][NSS_WIFI_STATS_MGMT_TX_DROPPED] += stats->tx_mgmt_dropped;
+	nss_wifi_stats[radio_id][NSS_WIFI_STATS_MGMT_TX_COMPLETIONS] += stats->tx_mgmt_completions;
+	nss_wifi_stats[radio_id][NSS_WIFI_STATS_TX_INV_PEER_ENQUEUE_CNT] += stats->tx_inv_peer_enq_cnt;
+	nss_wifi_stats[radio_id][NSS_WIFI_STATS_RX_INV_PEER_RCV_CNT] += stats->rx_inv_peer_rcv_cnt;
+	nss_wifi_stats[radio_id][NSS_WIFI_STATS_RX_PN_CHECK_FAILED] += stats->rx_pn_check_failed;
+	nss_wifi_stats[radio_id][NSS_WIFI_STATS_RX_DELIVERED] += stats->rx_pkts_deliverd;
+	nss_wifi_stats[radio_id][NSS_WIFI_STATS_RX_BYTES_DELIVERED] += stats->rx_bytes_deliverd;
+	nss_wifi_stats[radio_id][NSS_WIFI_STATS_TX_BYTES_COMPLETED] += stats->tx_bytes_transmit_completions;
+	nss_wifi_stats[radio_id][NSS_WIFI_STATS_RX_DELIVER_UNALIGNED_DROP_CNT] += stats->rx_deliver_unaligned_drop_cnt;
+
+	for (i = 0; i < NSS_WIFI_TX_NUM_TOS_TIDS; i++) {
+		nss_wifi_stats[radio_id][NSS_WIFI_STATS_TIDQ_ENQUEUE_CNT + i] += stats->tidq_enqueue_cnt[i];
+		nss_wifi_stats[radio_id][NSS_WIFI_STATS_TIDQ_DEQUEUE_CNT + i] += stats->tidq_dequeue_cnt[i];
+		nss_wifi_stats[radio_id][NSS_WIFI_STATS_TIDQ_ENQUEUE_FAIL_CNT + i] += stats->tidq_enqueue_fail_cnt[i];
+		nss_wifi_stats[radio_id][NSS_WIFI_STATS_TIDQ_TTL_EXPIRE_CNT + i] += stats->tidq_ttl_expire_cnt[i];
+		nss_wifi_stats[radio_id][NSS_WIFI_STATS_TIDQ_DEQUEUE_REQ_CNT + i] += stats->tidq_dequeue_req_cnt[i];
+	}
+
+	nss_wifi_stats[radio_id][NSS_WIFI_STATS_RX_HTT_FETCH_CNT] += stats->rx_htt_fetch_cnt;
+	nss_wifi_stats[radio_id][NSS_WIFI_STATS_TOTAL_TIDQ_DEPTH] = stats->total_tidq_depth;
+	nss_wifi_stats[radio_id][NSS_WIFI_STATS_TOTAL_TIDQ_BYPASS_CNT] += stats->total_tidq_bypass_cnt;
+	nss_wifi_stats[radio_id][NSS_WIFI_STATS_GLOBAL_Q_FULL_CNT] += stats->global_q_full_cnt;
+	nss_wifi_stats[radio_id][NSS_WIFI_STATS_TIDQ_FULL_CNT] += stats->tidq_full_cnt;
+
+	spin_unlock_bh(&nss_top->stats_lock);
+}
diff --git a/nss_wifi_stats.h b/nss_wifi_stats.h
new file mode 100644
index 0000000..7827777
--- /dev/null
+++ b/nss_wifi_stats.h
@@ -0,0 +1,62 @@
+/*
+ ******************************************************************************
+ * 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.
+ * ****************************************************************************
+ */
+
+#ifndef __NSS_WIFI_STATS_H
+#define __NSS_WIFI_STATS_H
+
+/*
+ * wifi statistics
+ */
+enum nss_wifi_stats_types {
+	NSS_WIFI_STATS_RX_PKTS,
+	NSS_WIFI_STATS_RX_QUEUE_0_DROPPED,
+	NSS_WIFI_STATS_RX_QUEUE_1_DROPPED,
+	NSS_WIFI_STATS_RX_QUEUE_2_DROPPED,
+	NSS_WIFI_STATS_RX_QUEUE_3_DROPPED,
+	NSS_WIFI_STATS_TX_PKTS,
+	NSS_WIFI_STATS_TX_DROPPED,
+	NSS_WIFI_STATS_TX_COMPLETED,
+	NSS_WIFI_STATS_MGMT_RCV_CNT,
+	NSS_WIFI_STATS_MGMT_TX_PKTS,
+	NSS_WIFI_STATS_MGMT_TX_DROPPED,
+	NSS_WIFI_STATS_MGMT_TX_COMPLETIONS,
+	NSS_WIFI_STATS_TX_INV_PEER_ENQUEUE_CNT,
+	NSS_WIFI_STATS_RX_INV_PEER_RCV_CNT,
+	NSS_WIFI_STATS_RX_PN_CHECK_FAILED,
+	NSS_WIFI_STATS_RX_DELIVERED,
+	NSS_WIFI_STATS_RX_BYTES_DELIVERED,
+	NSS_WIFI_STATS_TX_BYTES_COMPLETED,
+	NSS_WIFI_STATS_RX_DELIVER_UNALIGNED_DROP_CNT,
+	NSS_WIFI_STATS_TIDQ_ENQUEUE_CNT,
+	NSS_WIFI_STATS_TIDQ_DEQUEUE_CNT = NSS_WIFI_STATS_TIDQ_ENQUEUE_CNT + 8,
+	NSS_WIFI_STATS_TIDQ_ENQUEUE_FAIL_CNT = NSS_WIFI_STATS_TIDQ_DEQUEUE_CNT + 8,
+	NSS_WIFI_STATS_TIDQ_TTL_EXPIRE_CNT = NSS_WIFI_STATS_TIDQ_ENQUEUE_FAIL_CNT + 8,
+	NSS_WIFI_STATS_TIDQ_DEQUEUE_REQ_CNT = NSS_WIFI_STATS_TIDQ_TTL_EXPIRE_CNT + 8,
+	NSS_WIFI_STATS_TOTAL_TIDQ_DEPTH = NSS_WIFI_STATS_TIDQ_DEQUEUE_REQ_CNT + 8,
+	NSS_WIFI_STATS_RX_HTT_FETCH_CNT,
+	NSS_WIFI_STATS_TOTAL_TIDQ_BYPASS_CNT,
+	NSS_WIFI_STATS_GLOBAL_Q_FULL_CNT,
+	NSS_WIFI_STATS_TIDQ_FULL_CNT,
+	NSS_WIFI_STATS_MAX,
+};
+
+/*
+ * wifi statistics APIs
+ */
+extern void nss_wifi_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_wifi_stats_sync_msg *stats, uint16_t interface);
+extern void nss_wifi_stats_dentry_create(void);
+
+#endif /* __NSS_WIFI_STATS_H */
diff --git a/nss_wifili.c b/nss_wifili.c
index 3070e87..abb40a3 100644
--- a/nss_wifili.c
+++ b/nss_wifili.c
@@ -15,6 +15,7 @@
  */
 
 #include "nss_tx_rx_common.h"
+#include "nss_wifili_stats.h"
 
 #define NSS_WIFILI_TX_TIMEOUT 1000 /* Millisecond to jiffies*/
 
@@ -31,174 +32,6 @@
 } wifili_pvt;
 
 /*
- * nss_wifili_stats_sync()
- *	Handle the syncing of WIFI stats.
- */
-static void nss_wifili_stats_sync(struct nss_ctx_instance *nss_ctx,
-		struct nss_wifili_stats_sync_msg *wlsoc_stats, uint16_t interface)
-{
-	struct nss_top_instance *nss_top = nss_ctx->nss_top;
-	struct nss_wifili_stats *stats = &nss_top->stats_wifili;
-	struct nss_wifili_device_stats *devstats = &wlsoc_stats->stats;
-	uint32_t index;
-
-	spin_lock_bh(&nss_top->stats_lock);
-
-	for (index = 0; index < NSS_WIFILI_MAX_PDEV_NUM_MSG; index++) {
-		/*
-		 * Rx stats
-		 */
-		stats->stats_txrx[index][NSS_STATS_WIFILI_RX_MSDU_ERROR] +=
-							devstats->rx_data_stats[index].rx_msdu_err;
-		stats->stats_txrx[index][NSS_STATS_WIFILI_RX_INV_PEER_RCV] +=
-							(devstats->rx_data_stats[index].rx_inv_peer +
-							devstats->rx_data_stats[index].rx_scatter_inv_peer);
-		stats->stats_txrx[index][NSS_STATS_WIFILI_RX_WDS_SRCPORT_EXCEPTION] +=
-							devstats->rx_data_stats[index].rx_wds_learn_send;
-		stats->stats_txrx[index][NSS_STATS_WIFILI_RX_WDS_SRCPORT_EXCEPTION_FAIL] +=
-							devstats->rx_data_stats[index].rx_wds_learn_send_fail;
-		stats->stats_txrx[index][NSS_STATS_WIFILI_RX_DELIVERD] +=
-							devstats->rx_data_stats[index].rx_deliver_cnt;
-		stats->stats_txrx[index][NSS_STATS_WIFILI_RX_DELIVER_DROPPED] +=
-							devstats->rx_data_stats[index].rx_deliver_cnt_fail;
-		stats->stats_txrx[index][NSS_STATS_WIFILI_RX_INTRA_BSS_UCAST] +=
-							devstats->rx_data_stats[index].rx_intra_bss_ucast_send;
-		stats->stats_txrx[index][NSS_STATS_WIFILI_RX_INTRA_BSS_UCAST_FAIL] +=
-							devstats->rx_data_stats[index].rx_intra_bss_ucast_send_fail;
-		stats->stats_txrx[index][NSS_STATS_WIFILI_RX_INTRA_BSS_MCAST] +=
-							devstats->rx_data_stats[index].rx_intra_bss_mcast_send;
-		stats->stats_txrx[index][NSS_STATS_WIFILI_RX_INTRA_BSS_MCAST_FAIL] +=
-							devstats->rx_data_stats[index].rx_intra_bss_mcast_send_fail;
-		stats->stats_txrx[index][NSS_STATS_WIFILI_RX_SG_RCV_SEND] +=
-							devstats->rx_data_stats[index].rx_sg_recv_send;
-		stats->stats_txrx[index][NSS_STATS_WIFILI_RX_SG_RCV_FAIL] +=
-							devstats->rx_data_stats[index].rx_sg_recv_fail;
-		stats->stats_txrx[index][NSS_STATS_WIFILI_RX_MCAST_ECHO] +=
-							devstats->rx_data_stats[index].rx_me_pkts;
-
-		/*
-		 * Tx stats
-		 */
-		stats->stats_txrx[index][NSS_STATS_WIFILI_TX_ENQUEUE] +=
-							devstats->tx_data_stats[index].tx_enqueue_cnt;
-		stats->stats_txrx[index][NSS_STATS_WIFILI_TX_ENQUEUE_DROP] +=
-							devstats->tx_data_stats[index].tx_enqueue_dropped;
-		stats->stats_txrx[index][NSS_STATS_WIFILI_TX_DEQUEUE] +=
-							devstats->tx_data_stats[index].tx_dequeue_cnt;
-		stats->stats_txrx[index][NSS_STATS_WIFILI_TX_HW_ENQUEUE_FAIL] +=
-							devstats->tx_data_stats[index].tx_send_fail_cnt;
-		stats->stats_txrx[index][NSS_STATS_WIFILI_TX_SENT_COUNT] +=
-							devstats->tx_data_stats[index].tx_processed_pkt;
-	}
-
-	/*
-	 * update the tcl ring stats
-	 */
-	for (index = 0; index < NSS_WIFILI_MAX_TCL_DATA_RINGS_MSG; index++) {
-		stats->stats_tcl_ring[index][NSS_STATS_WIFILI_TCL_NO_HW_DESC] +=
-							devstats->tcl_stats[index].tcl_no_hw_desc;
-		stats->stats_tcl_ring[index][NSS_STATS_WIFILI_TCL_RING_FULL] +=
-							devstats->tcl_stats[index].tcl_ring_full;
-		stats->stats_tcl_ring[index][NSS_STATS_WIFILI_TCL_RING_SENT] +=
-							devstats->tcl_stats[index].tcl_ring_sent;
-	}
-
-	/*
-	 * update the tcl comp stats
-	 */
-	for (index = 0; index < NSS_WIFILI_MAX_TCL_DATA_RINGS_MSG; index++) {
-		stats->stats_tx_comp[index][NSS_STATS_WIFILI_TX_DESC_FREE_INV_BUFSRC] +=
-								devstats->txcomp_stats[index].invalid_bufsrc;
-		stats->stats_tx_comp[index][NSS_STATS_WIFILI_TX_DESC_FREE_INV_COOKIE] +=
-								devstats->txcomp_stats[index].invalid_cookie;
-		stats->stats_tx_comp[index][NSS_STATS_WIFILI_TX_DESC_FREE_HW_RING_EMPTY] +=
-								devstats->txcomp_stats[index].hw_ring_empty;
-		stats->stats_tx_comp[index][NSS_STATS_WIFILI_TX_DESC_FREE_REAPED] +=
-								devstats->txcomp_stats[index].ring_reaped;
-	}
-
-	/*
-	 * update reo ring stats
-	 */
-	for (index = 0; index < NSS_WIFILI_MAX_REO_DATA_RINGS_MSG; index++) {
-		stats->stats_reo[index][NSS_STATS_WIFILI_REO_ERROR] +=
-								devstats->rxreo_stats[index].ring_error;
-		stats->stats_reo[index][NSS_STATS_WIFILI_REO_REAPED] +=
-								devstats->rxreo_stats[index].ring_reaped;
-		stats->stats_reo[index][NSS_STATS_WIFILI_REO_INV_COOKIE] +=
-								devstats->rxreo_stats[index].invalid_cookie;
-	}
-
-	/*
-	 * update tx sw pool
-	 */
-	for (index = 0; index < NSS_WIFILI_MAX_TXDESC_POOLS_MSG; index++) {
-		stats->stats_tx_desc[index][NSS_STATS_WIFILI_TX_DESC_IN_USE] =
-								devstats->tx_sw_pool_stats[index].desc_alloc;
-		stats->stats_tx_desc[index][NSS_STATS_WIFILI_TX_DESC_ALLOC_FAIL] +=
-								devstats->tx_sw_pool_stats[index].desc_alloc_fail;
-		stats->stats_tx_desc[index][NSS_STATS_WIFILI_TX_DESC_ALREADY_ALLOCATED] +=
-								devstats->tx_sw_pool_stats[index].desc_already_allocated;
-		stats->stats_tx_desc[index][NSS_STATS_WIFILI_TX_DESC_INVALID_FREE] +=
-								devstats->tx_sw_pool_stats[index].desc_invalid_free;
-		stats->stats_tx_desc[index][NSS_STATS_WIFILI_TX_DESC_FREE_SRC_FW] +=
-								devstats->tx_sw_pool_stats[index].tx_rel_src_fw;
-		stats->stats_tx_desc[index][NSS_STATS_WIFILI_TX_DESC_FREE_COMPLETION] +=
-								devstats->tx_sw_pool_stats[index].tx_rel_tx_desc;
-		stats->stats_tx_desc[index][NSS_STATS_WIFILI_TX_DESC_NO_PB] +=
-								devstats->tx_sw_pool_stats[index].tx_rel_no_pb;
-	}
-
-	/*
-	 * update ext tx desc pool stats
-	 */
-	for (index = 0; index < NSS_WIFILI_MAX_TX_EXT_DESC_POOLS_MSG; index++) {
-		stats->stats_ext_tx_desc[index][NSS_STATS_WIFILI_EXT_TX_DESC_IN_USE] =
-								devstats->tx_ext_sw_pool_stats[index].desc_alloc;
-		stats->stats_ext_tx_desc[index][NSS_STATS_WIFILI_EXT_TX_DESC_ALLOC_FAIL] +=
-								devstats->tx_ext_sw_pool_stats[index].desc_alloc_fail;
-		stats->stats_ext_tx_desc[index][NSS_STATS_WIFILI_EXT_TX_DESC_ALREADY_ALLOCATED] +=
-								devstats->tx_ext_sw_pool_stats[index].desc_already_allocated;
-		stats->stats_ext_tx_desc[index][NSS_STATS_WIFILI_EXT_TX_DESC_INVALID_FREE] +=
-								devstats->tx_ext_sw_pool_stats[index].desc_invalid_free;
-	}
-
-	/*
-	 * update rx desc pool stats
-	 */
-	for (index = 0; index < NSS_WIFILI_MAX_PDEV_NUM_MSG; index++) {
-		stats->stats_rx_desc[index][NSS_STATS_WIFILI_RX_DESC_NO_PB] +=
-								devstats->rx_sw_pool_stats[index].rx_no_pb;
-		stats->stats_rx_desc[index][NSS_STATS_WIFILI_RX_DESC_ALLOC_FAIL] +=
-								devstats->rx_sw_pool_stats[index].desc_alloc_fail;
-		stats->stats_rx_desc[index][NSS_STATS_WIFILI_RX_DESC_IN_USE] =
-								devstats->rx_sw_pool_stats[index].desc_alloc;
-	}
-
-	/*
-	 * update rx dma ring stats
-	 */
-	for (index = 0; index < NSS_WIFILI_MAX_PDEV_NUM_MSG; index++) {
-		stats->stats_rxdma[index][NSS_STATS_WIFILI_RXDMA_DESC_UNAVAILABLE] +=
-								devstats->rxdma_stats[index].rx_hw_desc_unavailable;
-		stats->stats_rxdma[index][NSS_STATS_WIFILI_RXDMA_BUF_REPLENISHED] +=
-								devstats->rxdma_stats[index].rx_buf_replenished;
-	}
-
-	/*
-	 * update wbm ring stats
-	 */
-	stats->stats_wbm[NSS_STATS_WIFILI_WBM_SRC_DMA] += devstats->rxwbm_stats.err_src_rxdma;
-	stats->stats_wbm[NSS_STATS_WIFILI_WBM_SRC_DMA_CODE_INV] += devstats->rxwbm_stats.err_src_rxdma_code_inv;
-	stats->stats_wbm[NSS_STATS_WIFILI_WBM_SRC_REO] += devstats->rxwbm_stats.err_src_reo;
-	stats->stats_wbm[NSS_STATS_WIFILI_WBM_SRC_REO_CODE_NULLQ] += devstats->rxwbm_stats.err_src_reo_code_nullq;
-	stats->stats_wbm[NSS_STATS_WIFILI_WBM_SRC_REO_CODE_INV] += devstats->rxwbm_stats.err_src_reo_code_inv;
-	stats->stats_wbm[NSS_STATS_WIFILI_WBM_SRC_INV] += devstats->rxwbm_stats.err_src_invalid;
-	spin_unlock_bh(&nss_top->stats_lock);
-	return;
-}
-
-/*
  * nss_wifili_handler()
  *	Handle NSS -> HLOS messages for wifi
  */
@@ -521,6 +354,8 @@
 	nss_info("nss_wifili_register_handler");
 	nss_core_register_handler(nss_ctx, NSS_WIFILI_INTERFACE, nss_wifili_handler, NULL);
 
+	nss_wifili_stats_dentry_create();
+
 	sema_init(&wifili_pvt.sem, 1);
 	init_completion(&wifili_pvt.complete);
 }
diff --git a/nss_wifili_stats.c b/nss_wifili_stats.c
new file mode 100644
index 0000000..7d02d71
--- /dev/null
+++ b/nss_wifili_stats.c
@@ -0,0 +1,498 @@
+/*
+ **************************************************************************
+ * 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.
+ **************************************************************************
+ */
+
+/*
+ * nss_wifili_stats.c
+ *	NSS wifili statistics APIs
+ */
+
+#include "nss_tx_rx_common.h"
+#include "nss_core.h"
+#include "nss_stats.h"
+#include "nss_wifili_if.h"
+#include "nss_wifili_stats.h"
+
+/*
+ * Maximum string length:
+ * This should be equal to maximum string size of any stats
+ * inclusive of stats value
+ */
+#define NSS_WIFILI_STATS_MAX	(NSS_WIFILI_STATS_TXRX_MAX + NSS_WIFILI_STATS_TCL_MAX + \
+				NSS_WIFILI_STATS_TX_DESC_FREE_MAX + NSS_WIFILI_STATS_REO_MAX + \
+				NSS_WIFILI_STATS_TX_DESC_MAX + NSS_WIFILI_STATS_EXT_TX_DESC_MAX + \
+				NSS_WIFILI_STATS_RX_DESC_MAX + NSS_WIFILI_STATS_RXDMA_DESC_MAX)
+
+/*
+ * Statistics structures
+ */
+struct nss_wifili_stats stats_wifili;
+
+/*
+ * nss_wifili_stats_str_txrx
+ *	wifili txrx statistics
+ */
+static int8_t *nss_wifili_stats_str_txrx[NSS_WIFILI_STATS_TXRX_MAX] = {
+	"WIFILI_RX_MSDU_ERROR",
+	"WIFILI_RX_INV_PEER_RCV",
+	"WIFILI_RX_WDS_SRCPORT_EXCEPTION",
+	"WIFILI_RX_WDS_SRCPORT_EXCEPTION_FAIL",
+	"WIFILI_RX_DELIVERD",
+	"WIFILI_RX_DELIVER_DROPPED",
+	"WIFILI_RX_INTRA_BSS_UCAST",
+	"WIFILI_RX_INTRA_BSS_UCAST_FAIL",
+	"WIFILI_RX_INTRA_BSS_MCAST",
+	"WIFILI_RX_INTRA_BSS_MCAST_FAIL",
+	"WIFILI_RX_SG_RCV_SEND",
+	"WIFILI_RX_SG_RCV_FAIL",
+	"WIFILI_RX_MCAST_ECHO",
+	"WIFILI_TX_ENQUEUE",
+	"WIFILI_TX_ENQUEUE_DROP",
+	"WIFILI_TX_DEQUEUE",
+	"WIFILI_TX_HW_ENQUEUE_FAIL",
+	"WIFILI_TX_SENT_COUNT",
+};
+
+/*
+ * nss_wifili_stats_str_tcl
+ *	wifili tcl stats
+ */
+static int8_t *nss_wifili_stats_str_tcl[NSS_WIFILI_STATS_TCL_MAX] = {
+	"WIFILI_TCL_NO_HW_DESC",
+	"WIFILI_TCL_RING_FULL",
+	"WIFILI_TCL_RING_SENT",
+};
+
+/*
+ * nss_wifili_stats_str_tx_comp
+ *	wifili tx comp stats
+ */
+static int8_t *nss_wifili_stats_str_tx_comp[NSS_WIFILI_STATS_TX_DESC_FREE_MAX] = {
+	"WIFILI_TX_DESC_FREE_INV_BUFSRC",
+	"WIFILI_TX_DESC_FREE_INV_COOKIE",
+	"WIFILI_TX_DESC_FREE_HW_RING_EMPTY",
+	"WIFILI_TX_DESC_FREE_REAPED",
+};
+
+/*
+ * nss_wifili_stats_str_reo
+ *	wifili tx reo stats
+ */
+static int8_t *nss_wifili_stats_str_reo[NSS_WIFILI_STATS_REO_MAX] = {
+	"WIFILI_REO_ERROR",
+	"WIFILI_REO_REAPED",
+	"WIFILI_REO_INV_COOKIE",
+};
+
+/*
+ * nss_wifili_stats_str_txsw_pool
+ *	wifili tx desc stats
+ */
+static int8_t *nss_wifili_stats_str_txsw_pool[NSS_WIFILI_STATS_TX_DESC_MAX] = {
+	"WIFILI_TX_DESC_IN_USE",
+	"WIFILI_TX_DESC_ALLOC_FAIL",
+	"WIFILI_TX_DESC_ALREADY_ALLOCATED",
+	"WIFILI_TX_DESC_INVALID_FREE",
+	"WIFILI_TX_DESC_FREE_SRC_FW",
+	"WIFILI_TX_DESC_FREE_COMPLETION",
+	"WIFILI_TX_DESC_NO_PB",
+};
+
+/*
+ * nss_wifili_stats_str_ext_txsw_pool
+ *	wifili tx ext desc stats
+ */
+static uint8_t *nss_wifili_stats_str_ext_txsw_pool[NSS_WIFILI_STATS_EXT_TX_DESC_MAX] = {
+	"WIFILI_EXT_TX_DESC_IN_USE",
+	"WIFILI_EXT_TX_DESC_ALLOC_FAIL",
+	"WIFILI_EXT_TX_DESC_ALREADY_ALLOCATED",
+	"WIFILI_EXT_TX_DESC_INVALID_FREE",
+};
+
+/*
+ * nss_wifili_stats_str_rxdma_pool
+ *	wifili rx desc stats
+ */
+static int8_t *nss_wifili_stats_str_rxdma_pool[NSS_WIFILI_STATS_RX_DESC_MAX] = {
+	"WIFILI_RX_DESC_NO_PB",
+	"WIFILI_RX_DESC_ALLOC_FAIL",
+	"WIFILI_RX_DESC_IN_USE",
+};
+
+/*
+ * nss_wifili_stats_str_rxdma_ring
+ *	wifili rx dma ring stats
+ */
+static int8_t *nss_wifili_stats_str_rxdma_ring[NSS_WIFILI_STATS_RXDMA_DESC_MAX] = {
+	"WIFILI_RXDMA_HW_DESC_UNAVAILABLE",
+	"WIFILI_RXDMA_BUF_REPLENISHED",
+};
+
+/*
+ * nss_wifili_stats_str_wbm
+ *	wifili wbm ring stats
+ */
+static int8_t *nss_wifili_stats_str_wbm[NSS_WIFILI_STATS_WBM_MAX] = {
+	"WIFILI_WBM_SRC_DMA",
+	"WIFILI_WBM_SRC_DMA_CODE_INV",
+	"WIFILI_WBM_SRC_REO",
+	"WIFILI_WBM_SRC_REO_CODE_NULLQ",
+	"WIFILI_WBM_SRC_REO_CODE_INV",
+	"WIFILI_WBM_SRC_INV",
+};
+
+/*
+ * nss_wifili_stats_read()
+ *	Read wifili statistics
+ */
+static ssize_t nss_wifili_stats_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
+{
+	uint32_t i, j;
+
+	/*
+	 * max output lines = ((#stats + eight blank lines) * #WIFILI #STATS) + start/end tag + 3 blank
+	 */
+	uint32_t max_output_lines = (((NSS_WIFILI_STATS_MAX + 9) * NSS_WIFILI_MAX_PDEV_NUM_MSG)+
+									NSS_WIFILI_STATS_WBM_MAX + 5);
+	size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
+	size_t size_wr = 0;
+	ssize_t bytes_read = 0;
+	uint64_t *stats_shadow;
+
+	char *lbuf = kzalloc(size_al, GFP_KERNEL);
+	if (unlikely(lbuf == NULL)) {
+		nss_warning("Could not allocate memory for local statistics buffer");
+		return 0;
+	}
+
+	/*
+	 * Take max of all wifili stats
+	 *
+	 * NOTE: txrx stats is bigger of all stats
+	 */
+	stats_shadow = kzalloc(NSS_WIFILI_STATS_TXRX_MAX * 8, GFP_KERNEL);
+	if (unlikely(stats_shadow == NULL)) {
+		nss_warning("Could not allocate memory for local shadow buffer");
+		kfree(lbuf);
+		return 0;
+	}
+
+	size_wr = scnprintf(lbuf, size_al, "wifili stats start:\n\n");
+
+	for (i = 0; i < NSS_WIFILI_MAX_PDEV_NUM_MSG; i++) {
+
+		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "WIFILI ID: %d\n", i);
+
+		spin_lock_bh(&nss_top_main.stats_lock);
+		for (j = 0; (j < NSS_WIFILI_STATS_TXRX_MAX); j++) {
+			stats_shadow[j] = stats_wifili.stats_txrx[i][j];
+			size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
+					"%s = %llu\n", nss_wifili_stats_str_txrx[j], stats_shadow[j]);
+		}
+
+		spin_unlock_bh(&nss_top_main.stats_lock);
+		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\n");
+
+		/*
+		 * Fillinng TCL ring stats
+		 */
+		spin_lock_bh(&nss_top_main.stats_lock);
+		for (j = 0; (j < NSS_WIFILI_STATS_TCL_MAX); j++) {
+			stats_shadow[j] = stats_wifili.stats_tcl_ring[i][j];
+			size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
+					"%s = %llu\n", nss_wifili_stats_str_tcl[j], stats_shadow[j]);
+		}
+
+		spin_unlock_bh(&nss_top_main.stats_lock);
+		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\n");
+
+		/*
+		 * Fillinng TCL comp stats
+		 */
+		spin_lock_bh(&nss_top_main.stats_lock);
+		for (j = 0; (j < NSS_WIFILI_STATS_TX_DESC_FREE_MAX); j++) {
+			stats_shadow[j] = stats_wifili.stats_tx_comp[i][j];
+			size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
+					"%s = %llu\n", nss_wifili_stats_str_tx_comp[j], stats_shadow[j]);
+		}
+
+		spin_unlock_bh(&nss_top_main.stats_lock);
+		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\n");
+
+		/*
+		 * Fillinng reo ring stats
+		 */
+		spin_lock_bh(&nss_top_main.stats_lock);
+		for (j = 0; (j < NSS_WIFILI_STATS_REO_MAX); j++) {
+			stats_shadow[j] = stats_wifili.stats_reo[i][j];
+			size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
+					"%s = %llu\n", nss_wifili_stats_str_reo[j], stats_shadow[j]);
+		}
+
+		spin_unlock_bh(&nss_top_main.stats_lock);
+		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\n");
+
+		/*
+		 * Fillinng TX SW Pool
+		 */
+		spin_lock_bh(&nss_top_main.stats_lock);
+		for (j = 0; (j < NSS_WIFILI_STATS_TX_DESC_MAX); j++) {
+			stats_shadow[j] = stats_wifili.stats_tx_desc[i][j];
+			size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
+					"%s = %llu\n", nss_wifili_stats_str_txsw_pool[j], stats_shadow[j]);
+		}
+
+		spin_unlock_bh(&nss_top_main.stats_lock);
+		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\n");
+
+		/*
+		 * Fillinng TX  EXt SW Pool
+		 */
+		spin_lock_bh(&nss_top_main.stats_lock);
+		for (j = 0; (j < NSS_WIFILI_STATS_EXT_TX_DESC_MAX); j++) {
+			stats_shadow[j] = stats_wifili.stats_ext_tx_desc[i][j];
+			size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
+					"%s = %llu\n", nss_wifili_stats_str_ext_txsw_pool[j], stats_shadow[j]);
+		}
+
+		spin_unlock_bh(&nss_top_main.stats_lock);
+		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\n");
+
+		/*
+		 * Fillinng rxdma pool stats
+		 */
+		spin_lock_bh(&nss_top_main.stats_lock);
+		for (j = 0; (j < NSS_WIFILI_STATS_RX_DESC_MAX); j++) {
+			stats_shadow[j] = stats_wifili.stats_rx_desc[i][j];
+			size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
+					"%s = %llu\n", nss_wifili_stats_str_rxdma_pool[j], stats_shadow[j]);
+		}
+
+		spin_unlock_bh(&nss_top_main.stats_lock);
+		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\n");
+
+		/*
+		 * Fillinng rxdma ring stats
+		 */
+		spin_lock_bh(&nss_top_main.stats_lock);
+		for (j = 0; (j < NSS_WIFILI_STATS_RXDMA_DESC_MAX); j++) {
+			stats_shadow[j] = stats_wifili.stats_rxdma[i][j];
+			size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
+					"%s = %llu\n", nss_wifili_stats_str_rxdma_ring[j], stats_shadow[j]);
+		}
+
+		spin_unlock_bh(&nss_top_main.stats_lock);
+		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\n");
+
+	}
+
+	/*
+	 * Fillinng wbm ring stats
+	 */
+	spin_lock_bh(&nss_top_main.stats_lock);
+	for (j = 0; (j < NSS_WIFILI_STATS_WBM_MAX); j++) {
+		stats_shadow[j] = stats_wifili.stats_wbm[j];
+		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
+				"%s = %llu\n", nss_wifili_stats_str_wbm[j], stats_shadow[j]);
+	}
+
+	spin_unlock_bh(&nss_top_main.stats_lock);
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nwifili stats end\n\n");
+
+	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
+	kfree(lbuf);
+	kfree(stats_shadow);
+
+	return bytes_read;
+}
+
+/*
+ * wifili_stats_ops
+ */
+NSS_STATS_DECLARE_FILE_OPERATIONS(wifili)
+
+/*
+ * nss_wifili_stats_dentry_create()
+ *	Create wifili statistics debug entry.
+ */
+void nss_wifili_stats_dentry_create(void)
+{
+	nss_stats_create_dentry("wifili", &nss_wifili_stats_ops);
+}
+
+/*
+ * nss_wifili_stats_sync()
+ *	Handle the syncing of WIFI stats.
+ */
+void nss_wifili_stats_sync(struct nss_ctx_instance *nss_ctx,
+		struct nss_wifili_stats_sync_msg *wlsoc_stats, uint16_t interface)
+{
+	struct nss_top_instance *nss_top = nss_ctx->nss_top;
+	struct nss_wifili_stats *stats = &stats_wifili;
+	struct nss_wifili_device_stats *devstats = &wlsoc_stats->stats;
+	uint32_t index;
+
+	spin_lock_bh(&nss_top->stats_lock);
+
+	for (index = 0; index < NSS_WIFILI_MAX_PDEV_NUM_MSG; index++) {
+		/*
+		 * Rx stats
+		 */
+		stats->stats_txrx[index][NSS_WIFILI_STATS_RX_MSDU_ERROR] +=
+							devstats->rx_data_stats[index].rx_msdu_err;
+		stats->stats_txrx[index][NSS_WIFILI_STATS_RX_INV_PEER_RCV] +=
+							(devstats->rx_data_stats[index].rx_inv_peer +
+							devstats->rx_data_stats[index].rx_scatter_inv_peer);
+		stats->stats_txrx[index][NSS_WIFILI_STATS_RX_WDS_SRCPORT_EXCEPTION] +=
+							devstats->rx_data_stats[index].rx_wds_learn_send;
+		stats->stats_txrx[index][NSS_WIFILI_STATS_RX_WDS_SRCPORT_EXCEPTION_FAIL] +=
+							devstats->rx_data_stats[index].rx_wds_learn_send_fail;
+		stats->stats_txrx[index][NSS_WIFILI_STATS_RX_DELIVERD] +=
+							devstats->rx_data_stats[index].rx_deliver_cnt;
+		stats->stats_txrx[index][NSS_WIFILI_STATS_RX_DELIVER_DROPPED] +=
+							devstats->rx_data_stats[index].rx_deliver_cnt_fail;
+		stats->stats_txrx[index][NSS_WIFILI_STATS_RX_INTRA_BSS_UCAST] +=
+							devstats->rx_data_stats[index].rx_intra_bss_ucast_send;
+		stats->stats_txrx[index][NSS_WIFILI_STATS_RX_INTRA_BSS_UCAST_FAIL] +=
+							devstats->rx_data_stats[index].rx_intra_bss_ucast_send_fail;
+		stats->stats_txrx[index][NSS_WIFILI_STATS_RX_INTRA_BSS_MCAST] +=
+							devstats->rx_data_stats[index].rx_intra_bss_mcast_send;
+		stats->stats_txrx[index][NSS_WIFILI_STATS_RX_INTRA_BSS_MCAST_FAIL] +=
+							devstats->rx_data_stats[index].rx_intra_bss_mcast_send_fail;
+		stats->stats_txrx[index][NSS_WIFILI_STATS_RX_SG_RCV_SEND] +=
+							devstats->rx_data_stats[index].rx_sg_recv_send;
+		stats->stats_txrx[index][NSS_WIFILI_STATS_RX_SG_RCV_FAIL] +=
+							devstats->rx_data_stats[index].rx_sg_recv_fail;
+
+		/*
+		 * Tx stats
+		 */
+		stats->stats_txrx[index][NSS_WIFILI_STATS_TX_ENQUEUE] +=
+							devstats->tx_data_stats[index].tx_enqueue_cnt;
+		stats->stats_txrx[index][NSS_WIFILI_STATS_TX_ENQUEUE_DROP] +=
+							devstats->tx_data_stats[index].tx_enqueue_dropped;
+		stats->stats_txrx[index][NSS_WIFILI_STATS_TX_DEQUEUE] +=
+							devstats->tx_data_stats[index].tx_dequeue_cnt;
+		stats->stats_txrx[index][NSS_WIFILI_STATS_TX_HW_ENQUEUE_FAIL] +=
+							devstats->tx_data_stats[index].tx_send_fail_cnt;
+		stats->stats_txrx[index][NSS_WIFILI_STATS_TX_SENT_COUNT] +=
+							devstats->tx_data_stats[index].tx_processed_pkt;
+	}
+
+	/*
+	 * update the tcl ring stats
+	 */
+	for (index = 0; index < NSS_WIFILI_MAX_TCL_DATA_RINGS_MSG; index++) {
+		stats->stats_tcl_ring[index][NSS_WIFILI_STATS_TCL_NO_HW_DESC] +=
+							devstats->tcl_stats[index].tcl_no_hw_desc;
+		stats->stats_tcl_ring[index][NSS_WIFILI_STATS_TCL_RING_FULL] +=
+							devstats->tcl_stats[index].tcl_ring_full;
+		stats->stats_tcl_ring[index][NSS_WIFILI_STATS_TCL_RING_SENT] +=
+							devstats->tcl_stats[index].tcl_ring_sent;
+	}
+
+	/*
+	 * update the tcl comp stats
+	 */
+	for (index = 0; index < NSS_WIFILI_MAX_TCL_DATA_RINGS_MSG; index++) {
+		stats->stats_tx_comp[index][NSS_WIFILI_STATS_TX_DESC_FREE_INV_BUFSRC] +=
+								devstats->txcomp_stats[index].invalid_bufsrc;
+		stats->stats_tx_comp[index][NSS_WIFILI_STATS_TX_DESC_FREE_INV_COOKIE] +=
+								devstats->txcomp_stats[index].invalid_cookie;
+		stats->stats_tx_comp[index][NSS_WIFILI_STATS_TX_DESC_FREE_HW_RING_EMPTY] +=
+								devstats->txcomp_stats[index].hw_ring_empty;
+		stats->stats_tx_comp[index][NSS_WIFILI_STATS_TX_DESC_FREE_REAPED] +=
+								devstats->txcomp_stats[index].ring_reaped;
+	}
+
+	/*
+	 * update reo ring stats
+	 */
+	for (index = 0; index < NSS_WIFILI_MAX_REO_DATA_RINGS_MSG; index++) {
+		stats->stats_reo[index][NSS_WIFILI_STATS_REO_ERROR] +=
+								devstats->rxreo_stats[index].ring_error;
+		stats->stats_reo[index][NSS_WIFILI_STATS_REO_REAPED] +=
+								devstats->rxreo_stats[index].ring_reaped;
+		stats->stats_reo[index][NSS_WIFILI_STATS_REO_INV_COOKIE] +=
+								devstats->rxreo_stats[index].invalid_cookie;
+	}
+
+	/*
+	 * update tx sw pool
+	 */
+	for (index = 0; index < NSS_WIFILI_MAX_TXDESC_POOLS_MSG; index++) {
+		stats->stats_tx_desc[index][NSS_WIFILI_STATS_TX_DESC_IN_USE] =
+								devstats->tx_sw_pool_stats[index].desc_alloc;
+		stats->stats_tx_desc[index][NSS_WIFILI_STATS_TX_DESC_ALLOC_FAIL] +=
+								devstats->tx_sw_pool_stats[index].desc_alloc_fail;
+		stats->stats_tx_desc[index][NSS_WIFILI_STATS_TX_DESC_ALREADY_ALLOCATED] +=
+								devstats->tx_sw_pool_stats[index].desc_already_allocated;
+		stats->stats_tx_desc[index][NSS_WIFILI_STATS_TX_DESC_INVALID_FREE] +=
+								devstats->tx_sw_pool_stats[index].desc_invalid_free;
+		stats->stats_tx_desc[index][NSS_WIFILI_STATS_TX_DESC_FREE_SRC_FW] +=
+								devstats->tx_sw_pool_stats[index].tx_rel_src_fw;
+		stats->stats_tx_desc[index][NSS_WIFILI_STATS_TX_DESC_FREE_COMPLETION] +=
+								devstats->tx_sw_pool_stats[index].tx_rel_tx_desc;
+		stats->stats_tx_desc[index][NSS_WIFILI_STATS_TX_DESC_NO_PB] +=
+								devstats->tx_sw_pool_stats[index].tx_rel_no_pb;
+	}
+
+	/*
+	 * update ext tx desc pool stats
+	 */
+	for (index = 0; index < NSS_WIFILI_MAX_TX_EXT_DESC_POOLS_MSG; index++) {
+		stats->stats_ext_tx_desc[index][NSS_WIFILI_STATS_EXT_TX_DESC_IN_USE] =
+								devstats->tx_ext_sw_pool_stats[index].desc_alloc;
+		stats->stats_ext_tx_desc[index][NSS_WIFILI_STATS_EXT_TX_DESC_ALLOC_FAIL] +=
+								devstats->tx_ext_sw_pool_stats[index].desc_alloc_fail;
+		stats->stats_ext_tx_desc[index][NSS_WIFILI_STATS_EXT_TX_DESC_ALREADY_ALLOCATED] +=
+								devstats->tx_ext_sw_pool_stats[index].desc_already_allocated;
+		stats->stats_ext_tx_desc[index][NSS_WIFILI_STATS_EXT_TX_DESC_INVALID_FREE] +=
+								devstats->tx_ext_sw_pool_stats[index].desc_invalid_free;
+	}
+
+	/*
+	 * update rx desc pool stats
+	 */
+	for (index = 0; index < NSS_WIFILI_MAX_PDEV_NUM_MSG; index++) {
+		stats->stats_rx_desc[index][NSS_WIFILI_STATS_RX_DESC_NO_PB] +=
+								devstats->rx_sw_pool_stats[index].rx_no_pb;
+		stats->stats_rx_desc[index][NSS_WIFILI_STATS_RX_DESC_ALLOC_FAIL] +=
+								devstats->rx_sw_pool_stats[index].desc_alloc_fail;
+		stats->stats_rx_desc[index][NSS_WIFILI_STATS_RX_DESC_IN_USE] =
+								devstats->rx_sw_pool_stats[index].desc_alloc;
+	}
+
+	/*
+	 * update rx dma ring stats
+	 */
+	for (index = 0; index < NSS_WIFILI_MAX_PDEV_NUM_MSG; index++) {
+		stats->stats_rxdma[index][NSS_WIFILI_STATS_RXDMA_DESC_UNAVAILABLE] +=
+								devstats->rxdma_stats[index].rx_hw_desc_unavailable;
+	}
+
+	/*
+	 * update wbm ring stats
+	 */
+	stats->stats_wbm[NSS_WIFILI_STATS_WBM_SRC_DMA] += devstats->rxwbm_stats.err_src_rxdma;
+	stats->stats_wbm[NSS_WIFILI_STATS_WBM_SRC_DMA_CODE_INV] += devstats->rxwbm_stats.err_src_rxdma_code_inv;
+	stats->stats_wbm[NSS_WIFILI_STATS_WBM_SRC_REO] += devstats->rxwbm_stats.err_src_reo;
+	stats->stats_wbm[NSS_WIFILI_STATS_WBM_SRC_REO_CODE_NULLQ] += devstats->rxwbm_stats.err_src_reo_code_nullq;
+	stats->stats_wbm[NSS_WIFILI_STATS_WBM_SRC_REO_CODE_INV] += devstats->rxwbm_stats.err_src_reo_code_inv;
+	stats->stats_wbm[NSS_WIFILI_STATS_WBM_SRC_INV] += devstats->rxwbm_stats.err_src_invalid;
+	spin_unlock_bh(&nss_top->stats_lock);
+	return;
+}
+
diff --git a/nss_wifili_stats.h b/nss_wifili_stats.h
new file mode 100644
index 0000000..d12eafe
--- /dev/null
+++ b/nss_wifili_stats.h
@@ -0,0 +1,199 @@
+/*
+ **************************************************************************
+ * 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.
+ **************************************************************************
+ */
+
+/*
+ * nss_wifili_stats.h
+ *	NSS wifili statistics header file.
+ */
+
+#ifndef __NSS_WIFILI_STATS_H
+#define __NSS_WIFILI_STATS_H
+
+#include "nss_core.h"
+#include "nss_stats.h"
+#include "nss_wifili_if.h"
+
+/*
+ * wifili txrx statistics
+ *
+ * WARNING: There is a 1:1 mapping between values below and corresponding
+ *	stats string array in nss_stats.c
+ */
+enum nss_wifili_stats_txrx {
+	NSS_WIFILI_STATS_RX_MSDU_ERROR,			/* Number of rx packets received from ring with msdu error */
+	NSS_WIFILI_STATS_RX_INV_PEER_RCV,		/* Number of rx packets with invalid peer id */
+	NSS_WIFILI_STATS_RX_WDS_SRCPORT_EXCEPTION,	/* Number of rx packets exceptioned to host because of src port learn fail */
+	NSS_WIFILI_STATS_RX_WDS_SRCPORT_EXCEPTION_FAIL,	/* Number of rx src port learn fail packets failed to get enqueued to host */
+	NSS_WIFILI_STATS_RX_DELIVERD,			/* Number of packets wifili has given to next node */
+	NSS_WIFILI_STATS_RX_DELIVER_DROPPED,		/* Number of packets which wifili failed to enqueue to next node */
+	NSS_WIFILI_STATS_RX_INTRA_BSS_UCAST,		/* Number of packets which wifili send for intra bss ucast packet */
+	NSS_WIFILI_STATS_RX_INTRA_BSS_UCAST_FAIL,	/* Number of packets which wifili send for intra bss ucast packet failed */
+	NSS_WIFILI_STATS_RX_INTRA_BSS_MCAST,		/* Number of packets which wifili send for intra bss mcast packet */
+	NSS_WIFILI_STATS_RX_INTRA_BSS_MCAST_FAIL,	/* Number of packets which wifili send for intra bss mcast packet failed */
+	NSS_WIFILI_STATS_RX_SG_RCV_SEND,		/* Number of packets sg send */
+	NSS_WIFILI_STATS_RX_SG_RCV_FAIL,		/* Number of packets sg received failure*/
+	NSS_STATS_WIFILI_RX_MCAST_ECHO,			/* Number of multicast echo packets received */
+	NSS_WIFILI_STATS_TX_ENQUEUE,			/* Number of packets that got enqueued to wifili */
+	NSS_WIFILI_STATS_TX_ENQUEUE_DROP,		/* Number of packets that dropped during enqueue to wifili */
+	NSS_WIFILI_STATS_TX_DEQUEUE,			/* Number of packets that are dequeued by wifili */
+	NSS_WIFILI_STATS_TX_HW_ENQUEUE_FAIL,		/* Number of rx packets that NSS wifi offload path could successfully process */
+	NSS_WIFILI_STATS_TX_SENT_COUNT,			/* Number of Tx packets sent to hw */
+	NSS_WIFILI_STATS_TXRX_MAX,			/* Number of max txrx stats*/
+};
+
+/*
+ * wifili tcl stats
+ *
+ * WARNING: There is a 1:1 mapping between values below and corresponding
+ *	stats string array in nss_stats.c
+ */
+enum nss_wifili_stats_tcl {
+	NSS_WIFILI_STATS_TCL_NO_HW_DESC,		/* Number of tcl hw desc*/
+	NSS_WIFILI_STATS_TCL_RING_FULL,			/* Number of times tcl ring full*/
+	NSS_WIFILI_STATS_TCL_RING_SENT,			/* Number of times tcl desc sent*/
+	NSS_WIFILI_STATS_TCL_MAX,			/* Number of max tcl stats*/
+};
+
+/*
+ * wifili tx comp stats
+ *
+ * WARNING: There is a 1:1 mapping between values below and corresponding
+ *  	stats string array in nss_stats.c
+ */
+enum nss_wifili_stats_tx_comp {
+	NSS_WIFILI_STATS_TX_DESC_FREE_INV_BUFSRC,	/* Number of invalid bufsrc packets */
+	NSS_WIFILI_STATS_TX_DESC_FREE_INV_COOKIE,	/* Number of invalid cookie packets */
+	NSS_WIFILI_STATS_TX_DESC_FREE_HW_RING_EMPTY,	/* Number of time times hw ring empty found*/
+	NSS_WIFILI_STATS_TX_DESC_FREE_REAPED,		/* Number of tx packets that are reaped out of tx completion ring */
+	NSS_WIFILI_STATS_TX_DESC_FREE_MAX,		/* Number of tx comp stats */
+};
+
+/*
+ * wifili tx reo stats
+ *
+ * WARNING: There is a 1:1 mapping between values below and corresponding
+ *  	stats string array in nss_stats.c
+ */
+enum nss_wifili_stats_reo {
+	NSS_WIFILI_STATS_REO_ERROR,			/* Number of reo error*/
+	NSS_WIFILI_STATS_REO_REAPED,			/* Number of reo reaped*/
+	NSS_WIFILI_STATS_REO_INV_COOKIE,		/* Number of invalid cookie*/
+	NSS_WIFILI_STATS_REO_MAX,			/* Number of reo stats*/
+};
+
+/*
+ * wifili tx desc stats
+ *
+ * WARNING: There is a 1:1 mapping between values below and corresponding
+ *	stats string array in nss_stats.c
+ */
+enum nss_wifili_stats_txsw_pool {
+	NSS_WIFILI_STATS_TX_DESC_IN_USE,		/* Number of tx packets that are currently in flight */
+	NSS_WIFILI_STATS_TX_DESC_ALLOC_FAIL,		/* Number of tx sw desc alloc failures */
+	NSS_WIFILI_STATS_TX_DESC_ALREADY_ALLOCATED,	/* Number of tx sw desc already allocated*/
+	NSS_WIFILI_STATS_TX_DESC_INVALID_FREE,		/* Number of tx sw desc invalid free*/
+	NSS_WIFILI_STATS_TX_DESC_FREE_SRC_FW,		/* Number of tx desc for which release src is fw */
+	NSS_WIFILI_STATS_TX_DESC_FREE_COMPLETION,	/* Number of tx desc completion*/
+	NSS_WIFILI_STATS_TX_DESC_NO_PB,			/* Number of tx desc pb is null*/
+	NSS_WIFILI_STATS_TX_DESC_MAX,			/* Number of tx desc stats*/
+};
+
+/*
+ * wifili tx ext desc stats
+ *
+ * WARNING: There is a 1:1 mapping between values below and corresponding
+ *	stats string array in nss_stats.c
+ */
+enum nss_wifili_stats_ext_txsw_pool {
+	NSS_WIFILI_STATS_EXT_TX_DESC_IN_USE,		/* Number of ext tx packets that are currently in flight */
+	NSS_WIFILI_STATS_EXT_TX_DESC_ALLOC_FAIL,	/* Number of ext tx sw desc alloc failures */
+	NSS_WIFILI_STATS_EXT_TX_DESC_ALREADY_ALLOCATED,	/* Number of ext tx sw desc already allocated*/
+	NSS_WIFILI_STATS_EXT_TX_DESC_INVALID_FREE,	/* Number of ext tx sw desc invalid free*/
+	NSS_WIFILI_STATS_EXT_TX_DESC_MAX,		/* Number of ext tx desc stats*/
+};
+
+/*
+ * wifili rx desc stats
+ *
+ * WARNING: There is a 1:1 mapping between values below and corresponding
+ *	stats string array in nss_stats.c
+ */
+enum nss_wifili_stats_rxdma_pool {
+	NSS_WIFILI_STATS_RX_DESC_NO_PB,			/* Number of rx desc no pb*/
+	NSS_WIFILI_STATS_RX_DESC_ALLOC_FAIL,		/* Number of rx desc alloc failures */
+	NSS_WIFILI_STATS_RX_DESC_IN_USE,		/* Number of rx desc alloc in use*/
+	NSS_WIFILI_STATS_RX_DESC_MAX,			/* Number of rx desc stats*/
+};
+
+/*
+ * wifili rx dma ring stats
+ *
+ * WARNING: There is a 1:1 mapping between values below and corresponding
+ *	stats string array in nss_stats.c
+ */
+enum nss_wifili_stats_rxdma_ring {
+	NSS_WIFILI_STATS_RXDMA_DESC_UNAVAILABLE, 	/* Number of rx dma desc unavailable */
+	NSS_WIFILI_STATS_RXDMA_BUF_REPLENISHED,		/* Number of rx dma buf replished */
+	NSS_WIFILI_STATS_RXDMA_DESC_MAX,	 	/* Number of rx dma desc stast*/
+};
+
+/*
+ * wifili wbm ring stats
+ *
+ * WARNING: There is a 1:1 mapping between values below and corresponding
+ *	stats string array in nss_stats.c
+ */
+enum nss_wifili_stats_wbm {
+	NSS_WIFILI_STATS_WBM_SRC_DMA,			/* Number of rx invalid src dma*/
+	NSS_WIFILI_STATS_WBM_SRC_DMA_CODE_INV,		/* Number of rx invalid src dma*/
+	NSS_WIFILI_STATS_WBM_SRC_REO,			/* Number of rx invalid src reo*/
+	NSS_WIFILI_STATS_WBM_SRC_REO_CODE_NULLQ,	/* Number of rx invalid reo error with null q*/
+	NSS_WIFILI_STATS_WBM_SRC_REO_CODE_INV,		/* Number of rx invalid reo error with null q*/
+	NSS_WIFILI_STATS_WBM_SRC_INV,			/* Number of rx invalid reo code invalid*/
+	NSS_WIFILI_STATS_WBM_MAX,			/* Number of rx wbm stats*/
+};
+
+/*
+ * NSS wifili stats
+ */
+struct nss_wifili_stats {
+	uint64_t stats_txrx[NSS_WIFILI_MAX_PDEV_NUM_MSG][NSS_WIFILI_STATS_TXRX_MAX];
+							/* Number of txrx stats*/
+	uint64_t stats_tcl_ring[NSS_WIFILI_MAX_TCL_DATA_RINGS_MSG][NSS_WIFILI_STATS_TCL_MAX];
+							/* Tcl stats for each ring*/
+	uint64_t stats_tx_comp[NSS_WIFILI_MAX_TCL_DATA_RINGS_MSG][NSS_WIFILI_STATS_TX_DESC_FREE_MAX];
+							/* Tx comp ring stats*/
+	uint64_t stats_tx_desc[NSS_WIFILI_MAX_TXDESC_POOLS_MSG][NSS_WIFILI_STATS_TX_DESC_MAX];
+							/* Tx desc pool stats*/
+	uint64_t stats_ext_tx_desc[NSS_WIFILI_MAX_TX_EXT_DESC_POOLS_MSG][NSS_WIFILI_STATS_EXT_TX_DESC_MAX];
+							/* Tx ext desc pool stats*/
+	uint64_t stats_reo[NSS_WIFILI_MAX_REO_DATA_RINGS_MSG][NSS_WIFILI_STATS_REO_MAX];
+							/* Rx  reo ring stats*/
+	uint64_t stats_rx_desc[NSS_WIFILI_MAX_PDEV_NUM_MSG][NSS_WIFILI_STATS_RX_DESC_MAX];
+							/* Rx  rx sw pool stats*/
+	uint64_t stats_rxdma[NSS_WIFILI_MAX_PDEV_NUM_MSG][NSS_WIFILI_STATS_RXDMA_DESC_MAX];
+							/* Rx  dma ring stats*/
+	uint64_t stats_wbm[NSS_WIFILI_STATS_WBM_MAX];
+							/* Wbm  error ring stats*/
+};
+
+/*
+ * NSS wifili statistics APIs
+ */
+extern void nss_wifili_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_wifili_stats_sync_msg *wlsoc_stats, uint16_t interface);
+extern void nss_wifili_stats_dentry_create(void);
+
+#endif /* __NSS_WIFILI_STATS_H */