Stats changes

Change-Id: Ic808ffd9ca138a9d2debc10a03fb4f4bd6810ec0
Signed-off-by: Abhishek Rastogi <rastogiabhi@codeaurora.org>
diff --git a/Makefile b/Makefile
index 93e6885..aeffeb7 100755
--- a/Makefile
+++ b/Makefile
@@ -19,8 +19,8 @@
 obj-m += qca-nss-drv.o
 qca-nss-drv-objs := nss_init.o nss_core.o nss_stats.o nss_pm.o nss_tx_rx_ipv4.o nss_tx_rx_ipv6.o \
 		    nss_tx_rx_tun6rd.o nss_tx_rx_tunipip6.o nss_tx_rx_virt_if.o nss_tx_rx_phys_if.o \
-		    nss_tx_rx_crypto.o nss_tx_rx_ipsec.o nss_tx_rx_offload.o nss_tx_rx_pppoe.o nss_tx_rx_generic.o \
-		    nss_tx_rx_freq.o
+		    nss_tx_rx_crypto.o nss_tx_rx_ipsec.o nss_tx_rx_n2h.o nss_tx_rx_pppoe.o nss_tx_rx_generic.o \
+		    nss_tx_rx_freq.o nss_tx_rx_eth_rx.o
 
 obj-m += qca-nss-connmgr-ipv4.o
 obj-m += qca-nss-connmgr-ipv6.o
diff --git a/nss_api_if.h b/nss_api_if.h
index 354dc9d..bfd0a89 100755
--- a/nss_api_if.h
+++ b/nss_api_if.h
@@ -69,6 +69,7 @@
  * Special interface numbers
  */
 #define NSS_N2H_INTERFACE (NSS_SPECIAL_IF_START + 0) /* Special IF for N2H */
+#define NSS_ETH_RX_INTERFACE (NSS_SPECIAL_IF_START + 2) /* Special IF for ETH_RX */
 #define NSS_PPPOE_RX_INTERFACE (NSS_SPECIAL_IF_START + 3) /* Special IF for PPPoE sessions */
 #define NSS_IPV4_RX_INTERFACE (NSS_SPECIAL_IF_START + 5) /* Special IF number for IPv4 */
 #define NSS_IPV6_RX_INTERFACE (NSS_SPECIAL_IF_START + 7) /* Special IF number for IPv6 */
diff --git a/nss_core.h b/nss_core.h
index 4f2ab83..423dade 100755
--- a/nss_core.h
+++ b/nss_core.h
@@ -231,34 +231,6 @@
 };
 
 /*
- * Pbuf node statistics
- *
- * WARNING: There is a 1:1 mapping between values below and corresponding
- *	stats string array in nss_stats.c
- */
-enum nss_stats_pbuf {
-	NSS_STATS_PBUF_ALLOC_FAILS = 0,	/* Number of pbuf allocations that have failed */
-	NSS_STATS_PBUF_PAYLOAD_ALLOC_FAILS,
-					/* Number of pbuf allocations that have failed because there were no free payloads */
-	NSS_STATS_PBUF_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 = 0,
-					/* 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_MAX,
-};
-
-/*
  * HLOS driver statistics
  *
  * WARNING: There is a 1:1 mapping between values below and corresponding
@@ -315,53 +287,41 @@
 };
 
 /*
- * Interface host statistics
+ * Node statistics
  *
  * WARNING: There is a 1:1 mapping between values below and corresponding
  *	stats string array in nss_stats.c
  */
-enum nss_stats_if_host {
-	NSS_STATS_IF_HOST_RX_PKTS = 0,	/* Number of RX packets received by host OS */
-	NSS_STATS_IF_HOST_RX_BYTES,	/* Number of RX bytes received by host OS */
-	NSS_STATS_IF_HOST_TX_PKTS,	/* Number of TX packets sent by host OS */
-	NSS_STATS_IF_HOST_TX_BYTES,	/* Number of TX bytes sent by host OS */
-	NSS_STATS_IF_HOST_MAX,
+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_RX_DROPPED,
+					/* Accelerated node RX dropped */
+	NSS_STATS_NODE_TX_PKTS,
+					/* Accelerated node TX packets */
+	NSS_STATS_NODE_TX_BYTES,
+					/* Accelerated node TX bytes */
+	NSS_STATS_NODE_MAX,
 };
 
 /*
- * Interface IPv4 statistics
+ * 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_if_ipv4 {
-	NSS_STATS_IF_IPV4_ACCELERATED_RX_PKTS,
-					/* Accelerated IPv4 RX packets */
-	NSS_STATS_IF_IPV4_ACCELERATED_RX_BYTES,
-					/* Accelerated IPv4 RX bytes */
-	NSS_STATS_IF_IPV4_ACCELERATED_TX_PKTS,
-					/* Accelerated IPv4 TX packets */
-	NSS_STATS_IF_IPV4_ACCELERATED_TX_BYTES,
-					/* Accelerated IPv4 TX bytes */
-	NSS_STATS_IF_IPV4_MAX,
-};
-
-/*
- * Interface IPv6 statistics
- *
- * WARNING: There is a 1:1 mapping between values below and corresponding
- *	stats string array in nss_stats.c
- */
-enum nss_stats_if_ipv6 {
-	NSS_STATS_IF_IPV6_ACCELERATED_RX_PKTS,
-					/* Accelerated IPv6 RX packets */
-	NSS_STATS_IF_IPV6_ACCELERATED_RX_BYTES,
-					/* Accelerated IPv6 RX bytes */
-	NSS_STATS_IF_IPV6_ACCELERATED_TX_PKTS,
-					/* Accelerated IPv6 TX packets */
-	NSS_STATS_IF_IPV6_ACCELERATED_TX_BYTES,
-					/* Accelerated IPv6 TX bytes */
-	NSS_STATS_IF_IPV6_MAX,
+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_ALLOC_FAILS,	/* Number of pbuf allocations that have failed */
+	NSS_STATS_N2H_PAYLOAD_ALLOC_FAILS,
+					/* Number of pbuf allocations that have failed because there were no free payloads */
+	NSS_STATS_N2H_MAX,
 };
 
 /*
@@ -465,6 +425,8 @@
 	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 magic;
 					/* Magic protection */
 };
@@ -482,12 +444,11 @@
 	struct dentry *stats_dentry;	/* Top dentry for nss stats */
 	struct dentry *ipv4_dentry;	/* IPv4 stats dentry */
 	struct dentry *ipv6_dentry;	/* IPv6 stats dentry */
-	struct dentry *pbuf_dentry;	/* Pbuf stats dentry */
+	struct dentry *eth_rx_dentry;	/* ETH_RX stats dentry */
 	struct dentry *n2h_dentry;	/* N2H stats dentry */
 	struct dentry *drv_dentry;	/* HLOS driver stats dentry */
 	struct dentry *pppoe_dentry;	/* PPPOE stats dentry */
 	struct dentry *gmac_dentry;	/* GMAC ethnode stats dentry */
-	struct dentry *if_dentry;	/* Interface pnode stats dentry */
 	struct nss_ctx_instance nss[NSS_MAX_CORES];
 					/* NSS contexts */
 	/*
@@ -539,35 +500,22 @@
 					/* IPv4 statistics */
 	uint64_t stats_ipv6[NSS_STATS_IPV6_MAX];
 					/* IPv6 statistics */
-	uint64_t stats_pbuf[NSS_STATS_PBUF_MAX];
-					/* Pbuf manager statistics */
-	uint64_t stats_n2h[NSS_STATS_N2H_MAX];
-					/* N2H statistics */
 	uint64_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_if_host[NSS_MAX_NET_INTERFACES][NSS_STATS_IF_HOST_MAX];
-					/* Host Tx/Rx statistics per interface */
-	uint64_t stats_if_ipv4[NSS_MAX_NET_INTERFACES][NSS_STATS_IF_IPV4_MAX];
+	uint64_t stats_node[NSS_MAX_NET_INTERFACES][NSS_STATS_NODE_MAX];
 					/* IPv4 statistics per interface */
-	uint64_t stats_if_ipv6[NSS_MAX_NET_INTERFACES][NSS_STATS_IF_IPV6_MAX];
-					/* IPv6 statistics per interface */
-	uint64_t stats_if_exception_unknown[NSS_MAX_NET_INTERFACES][NSS_EXCEPTION_EVENT_UNKNOWN_MAX];
+	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_MAX_NET_INTERFACES][NSS_EXCEPTION_EVENT_IPV4_MAX];
+	uint64_t stats_if_exception_ipv4[NSS_EXCEPTION_EVENT_IPV4_MAX];
 					/* IPv4 protocol exception events per interface */
-	uint64_t stats_if_exception_ipv6[NSS_MAX_NET_INTERFACES][NSS_EXCEPTION_EVENT_IPV6_MAX];
+	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_NET_INTERFACES][NSS_PPPOE_NUM_SESSION_PER_INTERFACE][NSS_EXCEPTION_EVENT_PPPOE_MAX];
+	uint64_t stats_if_exception_pppoe[NSS_MAX_PHYSICAL_INTERFACES][NSS_PPPOE_NUM_SESSION_PER_INTERFACE][NSS_EXCEPTION_EVENT_PPPOE_MAX];
 					/* PPPoE exception events for per session on per interface */
-	uint64_t pe_queue_dropped;	/* Number of packets dropped because the PE queue is too full */
-	uint64_t pe_total_ticks;	/* Total clock ticks spend inside the PE */
-	uint32_t pe_worst_case_ticks;	/* Worst case iteration of the PE in ticks */
-	uint64_t pe_iterations;		/* Number of iterations around the PE */
-
 	/*
 	 * TODO: Review and update following fields
 	 */
diff --git a/nss_hlos_if.h b/nss_hlos_if.h
index 48fb714..a4b89c8 100755
--- a/nss_hlos_if.h
+++ b/nss_hlos_if.h
@@ -49,6 +49,17 @@
 };
 
 /*
+ * Common per node stats structure
+ */
+struct nss_cmn_node_stats {
+	uint32_t rx_packets;		/* Number of packets received */
+	uint32_t rx_bytes;		/* Number of bytes received */
+	uint32_t rx_dropped;		/* Number of receive drops due to queue full */
+	uint32_t tx_packets;		/* Number of packets transmitted */
+	uint32_t tx_bytes;		/* Number of bytes transmitted */
+};
+
+/*
  * IPv4 bridge/route rule messages
  */
 
@@ -56,7 +67,8 @@
 	NSS_IPV4_TX_CREATE_RULE_MSG,
 	NSS_IPV4_TX_DESTROY_RULE_MSG,
 	NSS_IPV4_RX_ESTABLISH_RULE_MSG,
-	NSS_IPV4_RX_SYNC_MSG,
+	NSS_IPV4_RX_CONN_STATS_SYNC_MSG,
+	NSS_IPV4_RX_NODE_STATS_SYNC_MSG,
 	NSS_IPV4_MAX_MSG_TYPES,
 };
 
@@ -252,9 +264,9 @@
 					/* Sync is to destroy a cache entry which belongs to a particular PPPoE session */
 
 /*
- * The NSS IPv4 rule sync structure.
+ * The NSS IPv4 connection sync structure.
  */
-struct nss_ipv4_rule_sync {
+struct nss_ipv4_conn_sync {
 	uint32_t index;			/* Slot ID for cache stats to host OS */
 	uint32_t flow_max_window;	/* Flow direction's largest seen window */
 	uint32_t flow_end;		/* Flow direction's largest seen sequence + segment length */
@@ -287,6 +299,90 @@
 };
 
 /*
+ * Exception events from bridge/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_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_MAX
+};
+
+/*
+ * IPv4 node statistics structure
+ */
+struct nss_ipv4_node_sync {
+	struct nss_cmn_node_stats node_stats;
+				/* Common node stats for IPv4 */
+	uint32_t ipv4_connection_create_requests;
+				/* Number of IPv4 connection create requests */
+	uint32_t ipv4_connection_create_collisions;
+				/* Number of IPv4 connection create requests that collided with existing entries */
+	uint32_t ipv4_connection_create_invalid_interface;
+				/* Number of IPv4 connection create requests that had invalid interface */
+	uint32_t ipv4_connection_destroy_requests;
+				/* Number of IPv4 connection destroy requests */
+	uint32_t ipv4_connection_destroy_misses;
+				/* Number of IPv4 connection destroy requests that missed the cache */
+	uint32_t ipv4_connection_hash_hits;
+				/* Number of IPv4 connection hash hits */
+	uint32_t ipv4_connection_hash_reorders;
+				/* Number of IPv4 connection hash reorders */
+	uint32_t ipv4_connection_flushes;
+				/* Number of IPv4 connection flushes */
+	uint32_t ipv4_connection_evictions;
+				/* Number of IPv4 connection evictions */
+	uint32_t exception_events[NSS_EXCEPTION_EVENT_IPV4_MAX];
+				/* Number of IPv4 exception events */
+};
+
+/*
  * Message structure to send/receive IPv4 bridge/route commands
  */
 struct nss_ipv4_msg {
@@ -295,7 +391,8 @@
 		struct nss_ipv4_rule_create_msg rule_create;	/* Message: rule create */
 		struct nss_ipv4_rule_destroy_msg rule_destroy;	/* Message: rule destroy */
 		struct nss_ipv4_rule_establish rule_establish;	/* Message: rule establish confirmation */
-		struct nss_ipv4_rule_sync rule_sync;	/* Message: stats sync */
+		struct nss_ipv4_conn_sync conn_stats;	/* Message: connection stats sync */
+		struct nss_ipv4_node_sync node_stats;	/* Message: node stats sync */
 	} msg;
 };
 
@@ -303,11 +400,12 @@
  * IPv6 bridge/route rule messages
  */
 
- enum nss_ipv6_metadata_types {
+enum nss_ipv6_metadata_types {
 	NSS_IPV6_TX_CREATE_RULE_MSG,
 	NSS_IPV6_TX_DESTROY_RULE_MSG,
 	NSS_IPV6_RX_ESTABLISH_RULE_MSG,
-	NSS_IPV6_RX_SYNC_MSG,
+	NSS_IPV6_RX_CONN_STATS_SYNC_MSG,
+	NSS_IPV6_RX_NODE_STATS_SYNC_MSG,
 	NSS_IPV6_MAX_MSG_TYPES,
 };
 
@@ -497,7 +595,7 @@
 /*
  * The NSS IPv6 rule sync structure.
  */
-struct nss_ipv6_rule_sync {
+struct nss_ipv6_conn_sync {
 	uint32_t index;			/* Slot ID for cache stats to host OS */
 	uint32_t flow_max_window;	/* Flow direction's largest seen window */
 	uint32_t flow_end;		/* Flow direction's largest seen sequence + segment length */
@@ -530,6 +628,71 @@
 };
 
 /*
+ * Exception events from IPv6 bridge/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_DSCP_MARKING_MISMATCH,
+	NSS_EXCEPTION_EVENT_IPV6_VLAN_MARKING_MISMATCH,
+	NSS_EXCEPTION_EVENT_IPV6_MAX
+};
+
+/*
+ * NSS IPv6 node stats sync structure
+ */
+struct nss_ipv6_node_sync {
+	struct nss_cmn_node_stats node_stats;
+				/* Common node stats for IPv6 */
+	uint32_t ipv6_connection_create_requests;
+				/* Number of IPv6 connection create requests */
+	uint32_t ipv6_connection_create_collisions;
+				/* Number of IPv6 connection create requests that collided with existing entries */
+	uint32_t ipv6_connection_create_invalid_interface;
+				/* Number of IPv6 connection create requests that had invalid interface */
+	uint32_t ipv6_connection_destroy_requests;
+				/* Number of IPv6 connection destroy requests */
+	uint32_t ipv6_connection_destroy_misses;
+				/* Number of IPv6 connection destroy requests that missed the cache */
+	uint32_t ipv6_connection_hash_hits;
+				/* Number of IPv6 connection hash hits */
+	uint32_t ipv6_connection_hash_reorders;
+				/* Number of IPv6 connection hash reorders */
+	uint32_t ipv6_connection_flushes;
+				/* Number of IPv6 connection flushes */
+	uint32_t ipv6_connection_evictions;
+				/* Number of IPv6 connection evictions */
+	uint32_t exception_events[NSS_EXCEPTION_EVENT_IPV6_MAX];
+				/* Number of IPv6 exception events */
+};
+
+/*
  * Message structure to send/receive IPv6 bridge/route commands
  */
 struct nss_ipv6_msg {
@@ -538,7 +701,8 @@
 		struct nss_ipv6_rule_create_msg rule_create;	/* Message: rule create */
 		struct nss_ipv6_rule_destroy_msg rule_destroy;	/* Message: rule destroy */
 		struct nss_ipv6_rule_establish rule_establish;	/* Message: rule establish confirmation */
-		struct nss_ipv6_rule_sync rule_sync;	/* Message: stats sync */
+		struct nss_ipv6_conn_sync conn_stats;	/* Message: stats sync */
+		struct nss_ipv6_node_sync node_stats;	/* Message: node stats sync */
 	} msg;
 };
 
@@ -582,6 +746,46 @@
 };
 
 /*
+ * 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_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 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;
+};
+
+/*
  * PPPoE
  */
 
@@ -591,8 +795,9 @@
 enum nss_pppoe_metadata_types {
 	NSS_TX_METADATA_TYPE_PPPOE_DESTROY_SESSION,
 	NSS_RX_METADATA_TYPE_PPPOE_RULE_STATUS,
-	NSS_RX_METADATA_TYPE_PPPOE_STATS_SYNC,
-	NSS_METADATA_TYPE_PPPOE_MAX
+	NSS_RX_METADATA_TYPE_PPPOE_CONN_STATS_SYNC,
+	NSS_RX_METADATA_TYPE_PPPOE_NODE_STATS_SYNC,
+	NSS_METADATA_TYPE_PPPOE_MAX,
 };
 
 /*
@@ -606,7 +811,6 @@
 	NSS_EXCEPTION_EVENT_PPPOE_MAX,
 };
 
-
 /*
  * The NSS PPPoE rule destruction structure.
  */
@@ -625,9 +829,24 @@
 };
 
 /*
+ * The NSS PPPoE node stats structure.
+ */
+struct nss_pppoe_node_sync {
+	struct nss_cmn_node_stats node_stats;
+	uint32_t pppoe_session_create_requests;
+					/* PPPoE session create requests */
+	uint32_t pppoe_session_create_failures;
+					/* PPPoE session create failures */
+	uint32_t pppoe_session_destroy_requests;
+					/* PPPoE session destroy requests */
+	uint32_t pppoe_session_destroy_misses;
+					/* PPPoE session destroy failures */
+};
+
+/*
  * The NSS PPPoE exception statistics sync structure.
  */
-struct nss_pppoe_exception_stats_sync {
+struct nss_pppoe_conn_sync {
 	uint16_t pppoe_session_id;	/* PPPoE session ID on which stats are based */
 	uint8_t pppoe_remote_mac[ETH_ALEN];
 					/* PPPoE server MAC address */
@@ -645,7 +864,8 @@
 	union {
 		struct nss_pppoe_destroy destroy;	/* Message: destroy pppoe rule */
 		struct nss_pppoe_rule_status rule_status;	/* Message: rule status response */
-		struct nss_pppoe_exception_stats_sync stats_sync;	/* Message: statistics sync */
+		struct nss_pppoe_conn_sync conn_sync;	/* Message: exception statistics sync */
+		struct nss_pppoe_node_sync node_sync;	/* Message: node statistics sync */
 	} msg;
 };
 
@@ -802,7 +1022,7 @@
  * Message structure to send/receive phys i/f commands
  */
 struct nss_c2c_msg {
-	struct nss_cmn_msg cm;              /* Message Header */
+	struct nss_cmn_msg cm;		/* Message Header */
 	union {
 		struct nss_c2c_tx_map tx_map;
 	} msg;
@@ -815,230 +1035,33 @@
 /*
  * Request/Response types
  */
-enum nss_offload_stats_metadata_types {
-	NSS_RX_METADATA_TYPE_PER_INTERFACE_STATS_SYNC,
-	NSS_RX_METADATA_TYPE_NSS_OFFLOAD_STATS_SYNC,
-	NSS_METADATA_TYPE_OFFLOAD_STATS_MAX
+enum nss_n2h_metadata_types {
+	NSS_RX_METADATA_TYPE_N2H_STATS_SYNC,
+	NSS_METADATA_TYPE_N2H_MAX,
 };
 
 /*
- * Exception events from bridge/route handler
+ * The NSS N2H statistics sync structure.
  */
-enum exception_events_unknown {
-	NSS_EXCEPTION_EVENT_UNKNOWN_L2_PROTOCOL,
-	NSS_EXCEPTION_EVENT_UNKNOWN_MAX
-};
-
-/*
- * Exception events from bridge/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_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_MAX
-};
-
-/*
- * Exception events from PE
- */
-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_DSCP_MARKING_MISMATCH,
-	NSS_EXCEPTION_EVENT_IPV6_VLAN_MARKING_MISMATCH,
-	NSS_EXCEPTION_EVENT_IPV6_MAX
-};
-
-/*
- * The NSS per-interface statistics sync structure.
- */
-struct nss_per_if_stats_sync {
-	uint32_t interface;		/* Interface number */
-	uint32_t rx_packets;		/* Number of packets received */
-	uint32_t rx_bytes;		/* Number of bytes received */
-	uint32_t tx_packets;		/* Number of packets transmitted */
-	uint32_t tx_bytes;		/* Number of bytes transmitted */
-	uint32_t rx_errors;		/* Number of receive errors */
-	uint32_t tx_errors;		/* Number of transmit errors */
-	uint32_t tx_dropped;		/* Number of TX dropped packets */
-	uint32_t collisions;		/* Number of TX and RX collisions */
-	uint32_t host_rx_packets;	/* Number of RX packets received by host OS */
-	uint32_t host_rx_bytes;		/* Number of RX bytes received by host OS */
-	uint32_t host_tx_packets;	/* Number of TX packets sent by host OS */
-	uint32_t host_tx_bytes;		/* Number of TX bytes sent by host OS */
-	uint32_t rx_length_errors;	/* Number of RX length errors */
-	uint32_t rx_overflow_errors;	/* Number of RX overflow errors */
-	uint32_t rx_crc_errors;		/* Number of RX CRC errors */
-	uint32_t exception_events_unknown[NSS_EXCEPTION_EVENT_UNKNOWN_MAX];
-					/* Number of unknown protocol exception events */
-	uint32_t exception_events_ipv4[NSS_EXCEPTION_EVENT_IPV4_MAX];
-					/* Number of IPv4 exception events */
-	uint32_t exception_events_ipv6[NSS_EXCEPTION_EVENT_IPV6_MAX];
-					/* Number of IPv6 exception events */
-};
-
-/*
- * The NSS NSS statistics sync structure.
- */
-struct nss_offload_stats_sync {
-	uint32_t ipv4_connection_create_requests;
-					/* Number of IPv4 connection create requests */
-	uint32_t ipv4_connection_create_collisions;
-					/* Number of IPv4 connection create requests that collided with existing entries */
-	uint32_t ipv4_connection_create_invalid_interface;
-					/* Number of IPv4 connection create requests that had invalid interface */
-	uint32_t ipv4_connection_destroy_requests;
-					/* Number of IPv4 connection destroy requests */
-	uint32_t ipv4_connection_destroy_misses;
-					/* Number of IPv4 connection destroy requests that missed the cache */
-	uint32_t ipv4_connection_hash_hits;
-					/* Number of IPv4 connection hash hits */
-	uint32_t ipv4_connection_hash_reorders;
-					/* Number of IPv4 connection hash reorders */
-	uint32_t ipv4_connection_flushes;
-					/* Number of IPv4 connection flushes */
-	uint32_t ipv4_connection_evictions;
-					/* Number of IPv4 connection evictions */
-	uint32_t ipv6_connection_create_requests;
-					/* Number of IPv6 connection create requests */
-	uint32_t ipv6_connection_create_collisions;
-					/* Number of IPv6 connection create requests that collided with existing entries */
-	uint32_t ipv6_connection_create_invalid_interface;
-					/* Number of IPv6 connection create requests that had invalid interface */
-	uint32_t ipv6_connection_destroy_requests;
-					/* Number of IPv6 connection destroy requests */
-	uint32_t ipv6_connection_destroy_misses;
-					/* Number of IPv6 connection destroy requests that missed the cache */
-	uint32_t ipv6_connection_hash_hits;
-					/* Number of IPv6 connection hash hits */
-	uint32_t ipv6_connection_hash_reorders;
-					/* Number of IPv6 connection hash reorders */
-	uint32_t ipv6_connection_flushes;
-					/* Number of IPv6 connection flushes */
-	uint32_t ipv6_connection_evictions;
-					/* Number of IPv6 connection evictions */
-	uint32_t l2switch_create_requests;
-					/* Number of l2 switch entry create requests */
-	uint32_t l2switch_create_collisions;
-					/* Number of l2 switch entry create requests that collided with existing entries */
-	uint32_t l2switch_create_invalid_interface;
-					/* Number of l2 switch entry create requests that had invalid interface */
-	uint32_t l2switch_destroy_requests;
-					/* Number of l2 switch entry destroy requests */
-	uint32_t l2switch_destroy_misses;
-					/* Number of l2 switch entry destroy requests that missed the cache */
-	uint32_t l2switch_hash_hits;	/* Number of l2 switch entry hash hits */
-	uint32_t l2switch_hash_reorders;/* Number of l2 switch entry hash reorders */
-	uint32_t l2switch_flushes;	/* Number of l2 switch entry flushes */
-	uint32_t l2switch_evictions;	/* Number of l2 switch entry evictions */
-	uint32_t pppoe_session_create_requests;
-					/* Number of PPPoE session create requests */
-	uint32_t pppoe_session_create_failures;
-					/* Number of PPPoE session create failures */
-	uint32_t pppoe_session_destroy_requests;
-					/* Number of PPPoE session destroy requests */
-	uint32_t pppoe_session_destroy_misses;
-					/* Number of PPPoE session destroy requests that missed the cache */
-	uint32_t pe_queue_dropped;	/* Number of packets dropped because the PE queue is too full */
-	uint32_t pe_total_ticks;	/* Total clock ticks spend inside the PE */
-	uint32_t pe_worst_case_ticks;	/* Worst case iteration of the PE in ticks */
-	uint32_t pe_iterations;		/* Number of iterations around the PE */
-	uint32_t except_queue_dropped;	/* Number of packets dropped because the exception queue is too full */
-	uint32_t except_total_ticks;	/* Total clock ticks spend inside the PE */
-	uint32_t except_worst_case_ticks;
-					/* Worst case iteration of the exception path in ticks */
-	uint32_t except_iterations;	/* Number of iterations around the PE */
-	uint32_t l2switch_queue_dropped;/* Number of packets dropped because the L2 switch queue is too full */
-	uint32_t l2switch_total_ticks;	/* Total clock ticks spend inside the L2 switch */
-	uint32_t l2switch_worst_case_ticks;
-					/* Worst case iteration of the L2 switch in ticks */
-	uint32_t l2switch_iterations;	/* Number of iterations around the L2 switch */
+struct nss_n2h_stats_sync {
+	struct nss_cmn_node_stats node_stats;
+					/* Common node stats for N2H */
+	uint32_t queue_dropped;		/* Number of packets dropped because the PE queue is too full */
+	uint32_t total_ticks;		/* Total clock ticks spend inside the PE */
+	uint32_t worst_case_ticks;	/* Worst case iteration of the PE in ticks */
+	uint32_t iterations;		/* Number of iterations around the PE */
 	uint32_t pbuf_alloc_fails;	/* Number of pbuf allocations that have failed */
-	uint32_t pbuf_payload_alloc_fails;
-					/* Number of pbuf allocations that have failed because there were no free payloads */
+	uint32_t payload_alloc_fails;
+					/* Number of payload allocations that have failed */
 };
 
 /*
  * Message structure to send/receive phys i/f commands
  */
-struct nss_offload_msg {
+struct nss_n2h_msg {
 	struct nss_cmn_msg cm;			/* Message Header */
 	union {
-		struct nss_per_if_stats_sync per_if_stats_sync;		/* Message: interface stats sync */
-		struct nss_offload_stats_sync offload_stats_sync;	/* Message: offload stats sync */
+		struct nss_n2h_stats_sync stats_sync;	/* Message: N2H stats sync */
 	} msg;
 };
 
diff --git a/nss_init.c b/nss_init.c
index 629ca41..67f355e 100755
--- a/nss_init.c
+++ b/nss_init.c
@@ -289,7 +289,8 @@
 		nss_top->ipv4_handler_id = nss_dev->id;
 		nss_ipv4_register_handler();
 		nss_pppoe_register_handler();
-		nss_offload_stats_register_handler();
+		nss_eth_rx_register_handler();
+		nss_n2h_register_handler();
 	}
 
 	if (npd->ipv6_enabled == NSS_FEATURE_ENABLED) {
diff --git a/nss_stats.c b/nss_stats.c
index 20644ef..cc743be 100755
--- a/nss_stats.c
+++ b/nss_stats.c
@@ -34,6 +34,8 @@
  */
 extern struct nss_top_instance nss_top_main;
 
+uint64_t stats_shadow_pppoe_except[NSS_PPPOE_NUM_SESSION_PER_INTERFACE][NSS_EXCEPTION_EVENT_PPPOE_MAX];
+
 /*
  * Statistics structures
  */
@@ -79,15 +81,6 @@
 };
 
 /*
- * nss_stats_str_pbuf
- *	Pbuf stats strings
- */
-static int8_t *nss_stats_str_pbuf[NSS_STATS_PBUF_MAX] = {
-	"pbuf_fails",
-	"payload_fails"
-};
-
-/*
  * nss_stats_str_n2h
  *	N2H stats strings
  */
@@ -96,6 +89,8 @@
 	"ticks",
 	"worst_ticks",
 	"iterations"
+	"pbuf_fails",
+	"payload_fails"
 };
 
 /*
@@ -140,35 +135,13 @@
 };
 
 /*
- * nss_stats_str_if_host
- *	Interface stats strings for host
+ * nss_stats_str_node
+ *	Interface stats strings per node
  */
-static int8_t *nss_stats_str_if_host[NSS_STATS_IF_HOST_MAX] = {
+static int8_t *nss_stats_str_node[NSS_STATS_NODE_MAX] = {
 	"rx_packets",
 	"rx_bytes",
-	"tx_packets",
-	"tx_bytes",
-
-};
-
-/*
- * nss_stats_str_if_ipv4
- *	Interface stats strings for ipv4
- */
-static int8_t *nss_stats_str_if_ipv4[NSS_STATS_IF_IPV4_MAX] = {
-	"rx_packets",
-	"rx_bytes",
-	"tx_packets",
-	"tx_bytes"
-};
-
-/*
- * nss_stats_str_if_ipv6
- *	Interface stats strings for ipv6
- */
-static int8_t *nss_stats_str_if_ipv6[NSS_STATS_IF_IPV6_MAX] = {
-	"rx_packets",
-	"rx_bytes",
+	"rx_dropped",
 	"tx_packets",
 	"tx_bytes"
 };
@@ -177,8 +150,8 @@
  * nss_stats_str_if_exception_unknown
  *	Interface stats strings for unknown exceptions
  */
-static int8_t *nss_stats_str_if_exception_unknown[NSS_EXCEPTION_EVENT_UNKNOWN_MAX] = {
-	"UNKNOWN_L2_PROTOCOL"
+static int8_t *nss_stats_str_if_exception_eth_rx[NSS_EXCEPTION_EVENT_ETH_RX_MAX] = {
+	"UNKNOWN_L3_PROTOCOL"
 };
 
 /*
@@ -292,7 +265,7 @@
 	/*
 	 * max output lines = #stats + start tag line + end tag line + three blank lines
 	 */
-	uint32_t max_output_lines = NSS_STATS_IPV4_MAX + 5;
+	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;
@@ -304,13 +277,38 @@
 		return 0;
 	}
 
-	stats_shadow = kzalloc(NSS_STATS_IPV4_MAX * 8, GFP_KERNEL);
+	/*
+	 * 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");
 		return 0;
 	}
 
 	size_wr = scnprintf(lbuf, size_al,"ipv4 stats start:\n\n");
+
+	/*
+	 * Common node stats
+	 */
+	size_wr += scnprintf(lbuf, size_al,"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];
+	}
+
+	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 node stats
+	 */
+	size_wr += scnprintf(lbuf, size_al,"\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];
@@ -323,6 +321,23 @@
 					"%s = %llu\n", nss_stats_str_ipv4[i], stats_shadow[i]);
 	}
 
+	/*
+	 * Exception stats
+	 */
+	size_wr += scnprintf(lbuf, size_al,"\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);
@@ -333,7 +348,7 @@
 
 /*
  * nss_stats_ipv6_read()
- *	Read IPv6 stats
+ *	Read IPV6 stats
  */
 static ssize_t nss_stats_ipv6_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
 {
@@ -342,7 +357,7 @@
 	/*
 	 * max output lines = #stats + start tag line + end tag line + three blank lines
 	 */
-	uint32_t max_output_lines = NSS_STATS_IPV6_MAX + 5;
+	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;
@@ -354,13 +369,38 @@
 		return 0;
 	}
 
-	stats_shadow = kzalloc(NSS_STATS_IPV6_MAX * 8, GFP_KERNEL);
+	/*
+	 * 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");
 		return 0;
 	}
 
 	size_wr = scnprintf(lbuf, size_al,"ipv6 stats start:\n\n");
+
+	/*
+	 * Common node stats
+	 */
+	size_wr += scnprintf(lbuf, size_al,"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_al,"\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];
@@ -373,7 +413,24 @@
 					"%s = %llu\n", nss_stats_str_ipv6[i], stats_shadow[i]);
 	}
 
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nipv6 stats end\n\n");
+	/*
+	 * Exception stats
+	 */
+	size_wr += scnprintf(lbuf, size_al,"\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);
@@ -382,17 +439,17 @@
 }
 
 /*
- * nss_stats_pbuf_read()
- *	Read pbuf manager stats
+ * nss_stats_eth_rx_read()
+ *	Read ETH_RX stats
  */
-static ssize_t nss_stats_pbuf_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
+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_PBUF_MAX + 5;
+	uint32_t max_output_lines = (NSS_STATS_NODE_MAX + 2) + (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;
@@ -404,26 +461,51 @@
 		return 0;
 	}
 
-	stats_shadow = kzalloc(NSS_STATS_PBUF_MAX * 8, GFP_KERNEL);
+	/*
+	 * 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");
 		return 0;
 	}
 
-	size_wr = scnprintf(lbuf, size_al, "pbuf_mgr stats start:\n\n");
+	size_wr = scnprintf(lbuf, size_al,"eth_rx stats start:\n\n");
+
+	/*
+	 * Common node stats
+	 */
+	size_wr += scnprintf(lbuf, size_al,"common node stats:\n\n");
 	spin_lock_bh(&nss_top_main.stats_lock);
-	for (i = 0; (i < NSS_STATS_PBUF_MAX); i++) {
-		stats_shadow[i] = nss_top_main.stats_pbuf[i];
+	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_PBUF_MAX); i++) {
+	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_pbuf[i], stats_shadow[i]);
+					"%s = %llu\n", nss_stats_str_node[i], stats_shadow[i]);
 	}
 
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\npbuf_mgr stats end\n\n");
+	/*
+	 * Exception stats
+	 */
+	size_wr += scnprintf(lbuf, size_al,"\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);
@@ -442,7 +524,7 @@
 	/*
 	 * max output lines = #stats + start tag line + end tag line + three blank lines
 	 */
-	uint32_t max_output_lines = NSS_STATS_N2H_MAX + 5;
+	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;
@@ -461,14 +543,35 @@
 	}
 
 	size_wr = scnprintf(lbuf, size_al, "n2h stats start:\n\n");
+
+	/*
+	 * Common node stats
+	 */
+	size_wr += scnprintf(lbuf, size_al,"common node stats:\n\n");
 	spin_lock_bh(&nss_top_main.stats_lock);
-	for (i = 0; (i < NSS_STATS_N2H_MAX); i++) {
-		stats_shadow[i] = nss_top_main.stats_n2h[i];
+	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_N2H_MAX); i++) {
+	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_al,"\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 = NSS_STATS_NODE_MAX; (i < NSS_STATS_N2H_MAX); i++) {
 		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
 					"%s = %llu\n", nss_stats_str_n2h[i], stats_shadow[i]);
 	}
@@ -537,12 +640,13 @@
  */
 static ssize_t nss_stats_pppoe_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
 {
-	int32_t i;
+	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_PPPOE_MAX + 5;
+	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_EXCEPTION_EVENT_PPPOE_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;
@@ -554,13 +658,35 @@
 		return 0;
 	}
 
-	stats_shadow = kzalloc(NSS_STATS_PPPOE_MAX * 8, GFP_KERNEL);
+	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_al, "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_al, "pppoe 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];
@@ -573,7 +699,36 @@
 					"%s = %llu\n", nss_stats_str_pppoe[i], stats_shadow[i]);
 	}
 
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\npppoe stats end\n\n");
+	/*
+	 * Exception stats
+	 */
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nException PPPoE:\n\n");
+
+	for (j = 0; 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 = 0; k < NSS_PPPOE_NUM_SESSION_PER_INTERFACE; k++) {
+			for (i = 0; (i < NSS_EXCEPTION_EVENT_PPPOE_MAX); i++) {
+				stats_shadow_pppoe_except[k][i] = nss_top_main.stats_if_exception_pppoe[j][k][i];
+			}
+		}
+
+		spin_unlock_bh(&nss_top_main.stats_lock);
+
+		for (k = 0; 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_EXCEPTION_EVENT_PPPOE_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][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);
@@ -636,228 +791,6 @@
 	return bytes_read;
 }
 
-/*
- * nss_stats_if_read()
- *	Read interface stats
- */
-static ssize_t nss_stats_if_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
-{
-	uint32_t i, k, id;
-	void *ifctx;
-
-	/*
-	 * max output lines per interface =
-	 * (#ipv4 stats + start tag + blank line) +
-	 * (#ipv6 stats + start tag + blank line) +
-	 * (#host stats + start tag + blank line) +
-	 * (#unknown exception stats + start tag + blank line) +
-	 * (#ipv4 exception + start tag + blank line) +
-	 * (#ipv6 exception + start tag + blank line) +
-	 * (#pppoe exception + start tag + blank line) + interface start tag
-	 *
-	 * max output lines =
-	 * (max output lines per interface * #interfaces) +
-	 * (start tag + end tag + 3 blank lines)
-	 */
-	uint32_t max_output_lines_interface = ((NSS_STATS_IF_IPV4_MAX + 2) + (NSS_STATS_IF_IPV6_MAX + 2) +
-					(NSS_STATS_IF_HOST_MAX + 2) + (NSS_EXCEPTION_EVENT_UNKNOWN_MAX + 2) +
-					(NSS_EXCEPTION_EVENT_IPV4_MAX + 2) + (NSS_EXCEPTION_EVENT_IPV6_MAX + 2) +
-					(NSS_EXCEPTION_EVENT_PPPOE_MAX + 2)) + 1;
-	size_t size_al = NSS_STATS_MAX_STR_LENGTH * ((max_output_lines_interface * NSS_MAX_NET_INTERFACES) + 5);
-	size_t size_wr = 0;
-	ssize_t bytes_read = 0;
-	uint64_t *stats_shadow;
-	uint64_t pppoe_stats_shadow[NSS_PPPOE_NUM_SESSION_PER_INTERFACE][NSS_EXCEPTION_EVENT_PPPOE_MAX];
-
-	char *lbuf = kzalloc(size_al, GFP_KERNEL);
-	if (unlikely(lbuf == NULL)) {
-		nss_warning("Could not allocate memory for local statistics buffer");
-		return 0;
-	}
-
-	/*
-	 * WARNING: We are only allocating memory for 64 stats counters per stats type
-	 *		Developers must ensure that number of counters are not more than 64
-	 */
-
-	if ( (NSS_STATS_IF_IPV4_MAX > 64) ||
-			(NSS_STATS_IF_IPV6_MAX > 64) ||
-			(NSS_STATS_IF_HOST_MAX > 64) ||
-			(NSS_EXCEPTION_EVENT_UNKNOWN_MAX > 64) ||
-			(NSS_EXCEPTION_EVENT_IPV4_MAX > 64) ||
-			(NSS_EXCEPTION_EVENT_IPV6_MAX > 64) ||
-			(NSS_EXCEPTION_EVENT_PPPOE_MAX > 64)) {
-		nss_warning("Size of shadow stats structure is not enough to copy all 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, "if stats start:\n\n");
-
-	for (id = NSS_DEVICE_IF_START; id < NSS_MAX_DEVICE_INTERFACES; id++) {
-
-		spin_lock_bh(&nss_top_main.lock);
-		ifctx = nss_top_main.if_ctx[id];
-		spin_unlock_bh(&nss_top_main.lock);
-
-		if (!ifctx) {
-			continue;
-		}
-
-		/*
-		 * Host Stats
-		 */
-		spin_lock_bh(&nss_top_main.stats_lock);
-		for (i = 0; (i < NSS_STATS_IF_HOST_MAX); i++) {
-			stats_shadow[i] = nss_top_main.stats_if_host[id][i];
-		}
-
-		spin_unlock_bh(&nss_top_main.stats_lock);
-
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "Interface ID: %d\n", id);
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "Host:\n");
-		for (i = 0; (i < NSS_STATS_IF_HOST_MAX); i++) {
-			size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
-					"%s = %llu\n", nss_stats_str_if_host[i], stats_shadow[i]);
-		}
-
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\n");
-
-		/*
-		 * IPv4 stats
-		 */
-		spin_lock_bh(&nss_top_main.stats_lock);
-		for (i = 0; (i < NSS_STATS_IF_IPV4_MAX); i++) {
-			stats_shadow[i] = nss_top_main.stats_if_ipv4[id][i];
-		}
-
-		spin_unlock_bh(&nss_top_main.stats_lock);
-
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "IPv4:\n");
-		for (i = 0; (i < NSS_STATS_IF_IPV4_MAX); i++) {
-			size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
-					"%s = %llu\n", nss_stats_str_if_ipv4[i], stats_shadow[i]);
-		}
-
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\n");
-
-		/*
-		 * IPv6 stats
-		 */
-		spin_lock_bh(&nss_top_main.stats_lock);
-		for (i = 0; (i < NSS_STATS_IF_IPV6_MAX); i++) {
-			stats_shadow[i] = nss_top_main.stats_if_ipv6[id][i];
-		}
-
-		spin_unlock_bh(&nss_top_main.stats_lock);
-
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "IPv6:\n");
-		for (i = 0; (i < NSS_STATS_IF_IPV6_MAX); i++) {
-			size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
-					"%s = %llu\n", nss_stats_str_if_ipv6[i], stats_shadow[i]);
-		}
-
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\n");
-
-		/*
-		 * Unknown exception stats
-		 */
-		spin_lock_bh(&nss_top_main.stats_lock);
-		for (i = 0; (i < NSS_EXCEPTION_EVENT_UNKNOWN_MAX); i++) {
-			stats_shadow[i] = nss_top_main.stats_if_exception_unknown[id][i];
-		}
-
-		spin_unlock_bh(&nss_top_main.stats_lock);
-
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "Exception Unknown:\n");
-		for (i = 0; (i < NSS_EXCEPTION_EVENT_UNKNOWN_MAX); i++) {
-			size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
-					"%s = %llu\n",
-					nss_stats_str_if_exception_unknown[i],
-					stats_shadow[i]);
-		}
-
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\n");
-
-		/*
-		 * IPv4 exception stats
-		 */
-		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[id][i];
-		}
-
-		spin_unlock_bh(&nss_top_main.stats_lock);
-
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "Exception IPv4:\n");
-		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, "\n");
-
-		/*
-		 * IPv6 exception stats
-		 */
-		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[id][i];
-		}
-
-		spin_unlock_bh(&nss_top_main.stats_lock);
-
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "Exception IPv6:\n");
-		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, "\n");
-
-
-		/*
-		 * Exception PPPoE
-		 */
-		spin_lock_bh(&nss_top_main.stats_lock);
-		for (k = 0; k < NSS_PPPOE_NUM_SESSION_PER_INTERFACE; k++) {
-			for (i = 0; (i < NSS_EXCEPTION_EVENT_PPPOE_MAX); i++) {
-				pppoe_stats_shadow[k][i] = nss_top_main.stats_if_exception_pppoe[id][k][i];
-			}
-		}
-
-		spin_unlock_bh(&nss_top_main.stats_lock);
-
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "Exception PPPoE:\n");
-		for (k = 0; 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_EXCEPTION_EVENT_PPPOE_MAX); i++) {
-				size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
-						"%s = %llu\n",
-						nss_stats_str_if_exception_pppoe[i],
-						pppoe_stats_shadow[k][i]);
-			}
-		}
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\n");
-	}
-
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nif stats end\n\n");
-	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
-	kfree(lbuf);
-	kfree(stats_shadow);
-
-	return bytes_read;
-}
-
-
 #define NSS_STATS_DECLARE_FILE_OPERATIONS(name) \
 static const struct file_operations nss_stats_##name##_ops = { \
 	.open = simple_open, \
@@ -876,11 +809,6 @@
 NSS_STATS_DECLARE_FILE_OPERATIONS(ipv6)
 
 /*
- * pbuf_stats_ops
- */
-NSS_STATS_DECLARE_FILE_OPERATIONS(pbuf)
-
-/*
  * n2h_stats_ops
  */
 NSS_STATS_DECLARE_FILE_OPERATIONS(n2h)
@@ -900,9 +828,9 @@
 NSS_STATS_DECLARE_FILE_OPERATIONS(gmac)
 
 /*
- * if_stats_ops
+ * eth_rx_stats_ops
  */
-NSS_STATS_DECLARE_FILE_OPERATIONS(if)
+NSS_STATS_DECLARE_FILE_OPERATIONS(eth_rx)
 
 /*
  * nss_stats_init()
@@ -960,12 +888,12 @@
 	}
 
 	/*
-	 * pbuf_stats
+	 * ipv6_stats
 	 */
-	nss_top_main.pbuf_dentry = debugfs_create_file("pbuf_mgr", 0400,
-						nss_top_main.stats_dentry, &nss_top_main, &nss_stats_pbuf_ops);
-	if (unlikely(nss_top_main.pbuf_dentry == NULL)) {
-		nss_warning("Failed to create qca-nss-drv/stats/pbuf file in debugfs");
+	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;
 	}
 
@@ -1008,16 +936,6 @@
 		nss_warning("Failed to create qca-nss-drv/stats/gmac file in debugfs");
 		return;
 	}
-
-	/*
-	 * interface_stats
-	 */
-	nss_top_main.if_dentry = debugfs_create_file("interface", 0400,
-						nss_top_main.stats_dentry, &nss_top_main, &nss_stats_if_ops);
-	if (unlikely(nss_top_main.if_dentry == NULL)) {
-		nss_warning("Failed to create qca-nss-drv/stats/interface file in debugfs");
-		return;
-	}
 }
 
 
diff --git a/nss_tx_rx_common.h b/nss_tx_rx_common.h
index 86455b8..d95c604 100755
--- a/nss_tx_rx_common.h
+++ b/nss_tx_rx_common.h
@@ -65,11 +65,12 @@
 extern void nss_ipsec_register_handler(void);
 extern void nss_ipv4_register_handler(void);
 extern void nss_ipv6_register_handler(void);
-extern void nss_offload_stats_register_handler(void);
+extern void nss_n2h_register_handler(void);
 extern void nss_phys_if_register_handler(uint32_t if_num);
 extern void nss_tun6rd_register_handler(void);
 extern void nss_tunipip6_register_handler(void);
 extern void nss_pppoe_register_handler(void);
 extern void nss_core_freq_register_handler(void);
+extern void nss_eth_rx_register_handler(void);
 
 #endif /* __NSS_TX_RX_COMMON_H */
diff --git a/nss_tx_rx_eth_rx.c b/nss_tx_rx_eth_rx.c
new file mode 100755
index 0000000..c6c1d04
--- /dev/null
+++ b/nss_tx_rx_eth_rx.c
@@ -0,0 +1,92 @@
+/*
+ **************************************************************************
+ * Copyright (c) 2013, 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_tx_rx_eth_rx.c
+ *	NSS ETH_RX APIs
+ */
+
+#include "nss_tx_rx_common.h"
+
+/*
+ **********************************
+ Rx APIs
+ **********************************
+ */
+
+/*
+ * nss_rx_metadata_eth_rx_node_stats_sync()
+ *	Handle the syncing of PPPoE node statistics.
+ */
+static void nss_rx_metadata_eth_rx_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_RX_DROPPED] += nens->node_stats.rx_dropped;
+	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_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_rx_eth_rx_interface_handler()
+ *	Handle NSS -> HLOS messages for ETH_RX node
+ */
+static void nss_rx_eth_rx_interface_handler(struct nss_ctx_instance *nss_ctx, struct nss_cmn_msg *ncm, __attribute__((unused))void *app_data)
+{
+	struct nss_eth_rx_msg *nem = (struct nss_eth_rx_msg *)ncm;
+
+	/*
+	 * Is this a valid request/response packet?
+	 */
+	if (nem->cm.type >= NSS_METADATA_TYPE_ETH_RX_MAX) {
+		nss_warning("%p: received invalid message %d for eth_rx interface", nss_ctx, nem->cm.type);
+		return;
+	}
+
+	switch (nem->cm.type) {
+	case NSS_RX_METADATA_TYPE_ETH_RX_STATS_SYNC:
+		nss_rx_metadata_eth_rx_stats_sync(nss_ctx, &nem->msg.node_sync);
+		break;
+
+	default:
+		if (ncm->response != NSS_CMN_RESPONSE_ACK) {
+			/*
+			 * Check response
+			 */
+			nss_info("%p: Received response %d for type %d, interface %d",
+						nss_ctx, ncm->response, ncm->type, ncm->interface);
+		}
+	}
+}
+
+/*
+ * nss_eth_rx_register_handler()
+ */
+void nss_eth_rx_register_handler()
+{
+	nss_core_register_handler(NSS_ETH_RX_INTERFACE, nss_rx_eth_rx_interface_handler, NULL);
+}
diff --git a/nss_tx_rx_ipv4.c b/nss_tx_rx_ipv4.c
index 30badf5..f9d76a1 100755
--- a/nss_tx_rx_ipv4.c
+++ b/nss_tx_rx_ipv4.c
@@ -404,45 +404,45 @@
  * nss_rx_metadata_ipv4_rule_sync()
  *	Handle the syncing of an IPv4 rule.
  */
-static void nss_rx_metadata_ipv4_rule_sync(struct nss_ctx_instance *nss_ctx, struct nss_ipv4_rule_sync *nirs)
+static void nss_rx_metadata_ipv4_conn_sync(struct nss_ctx_instance *nss_ctx, struct nss_ipv4_conn_sync *nics)
 {
 	struct nss_top_instance *nss_top = nss_ctx->nss_top;
 	struct nss_ipv4_cb_params nicp;
 	struct net_device *pppoe_dev = NULL;
 
 	nicp.reason = NSS_IPV4_CB_REASON_SYNC;
-	nicp.params.sync.index = nirs->index;
-	nicp.params.sync.flow_max_window = nirs->flow_max_window;
-	nicp.params.sync.flow_end = nirs->flow_end;
-	nicp.params.sync.flow_max_end = nirs->flow_max_end;
-	nicp.params.sync.flow_rx_packet_count = nirs->flow_rx_packet_count;
-	nicp.params.sync.flow_rx_byte_count = nirs->flow_rx_byte_count;
-	nicp.params.sync.flow_tx_packet_count = nirs->flow_tx_packet_count;
-	nicp.params.sync.flow_tx_byte_count = nirs->flow_tx_byte_count;
-	nicp.params.sync.return_max_window = nirs->return_max_window;
-	nicp.params.sync.return_end = nirs->return_end;
-	nicp.params.sync.return_max_end = nirs->return_max_end;
-	nicp.params.sync.return_rx_packet_count = nirs->return_rx_packet_count;
-	nicp.params.sync.return_rx_byte_count = nirs->return_rx_byte_count;
-	nicp.params.sync.return_tx_packet_count = nirs->return_tx_packet_count;
-	nicp.params.sync.return_tx_byte_count = nirs->return_tx_byte_count;
+	nicp.params.sync.index = nics->index;
+	nicp.params.sync.flow_max_window = nics->flow_max_window;
+	nicp.params.sync.flow_end = nics->flow_end;
+	nicp.params.sync.flow_max_end = nics->flow_max_end;
+	nicp.params.sync.flow_rx_packet_count = nics->flow_rx_packet_count;
+	nicp.params.sync.flow_rx_byte_count = nics->flow_rx_byte_count;
+	nicp.params.sync.flow_tx_packet_count = nics->flow_tx_packet_count;
+	nicp.params.sync.flow_tx_byte_count = nics->flow_tx_byte_count;
+	nicp.params.sync.return_max_window = nics->return_max_window;
+	nicp.params.sync.return_end = nics->return_end;
+	nicp.params.sync.return_max_end = nics->return_max_end;
+	nicp.params.sync.return_rx_packet_count = nics->return_rx_packet_count;
+	nicp.params.sync.return_rx_byte_count = nics->return_rx_byte_count;
+	nicp.params.sync.return_tx_packet_count = nics->return_tx_packet_count;
+	nicp.params.sync.return_tx_byte_count = nics->return_tx_byte_count;
 
-	nicp.params.sync.qos_tag = nirs->qos_tag;
+	nicp.params.sync.qos_tag = nics->qos_tag;
 
 	nicp.params.sync.flags = 0;
-	if (nirs->flags & NSS_IPV4_RULE_CREATE_FLAG_NO_SEQ_CHECK) {
+	if (nics->flags & NSS_IPV4_RULE_CREATE_FLAG_NO_SEQ_CHECK) {
 		nicp.params.sync.flags |= NSS_IPV4_CREATE_FLAG_NO_SEQ_CHECK;
 	}
 
-	if (nirs->flags & NSS_IPV4_RULE_CREATE_FLAG_BRIDGE_FLOW) {
+	if (nics->flags & NSS_IPV4_RULE_CREATE_FLAG_BRIDGE_FLOW) {
 		nicp.params.sync.flags |= NSS_IPV4_CREATE_FLAG_BRIDGE_FLOW;
 	}
 
-	if (nirs->flags & NSS_IPV4_RULE_CREATE_FLAG_ROUTED) {
+	if (nics->flags & NSS_IPV4_RULE_CREATE_FLAG_ROUTED) {
 		nicp.params.sync.flags |= NSS_IPV4_CREATE_FLAG_ROUTED;
 	}
 
-	switch (nirs->reason) {
+	switch (nics->reason) {
 	case NSS_IPV4_RULE_SYNC_REASON_STATS:
 		nicp.params.sync.reason = NSS_IPV4_SYNC_REASON_STATS;
 		break;
@@ -460,7 +460,7 @@
 		break;
 
 	default:
-		nss_warning("Bad ipv4 sync reason: %d\n", nirs->reason);
+		nss_warning("Bad ipv4 sync reason: %d\n", nics->reason);
 		return;
 	}
 
@@ -471,7 +471,7 @@
 	 * time bases don't cause truncation errors.
 	 */
 	nss_assert(HZ <= 100000);
-	nicp.params.sync.delta_jiffies = ((nirs->inc_ticks * HZ) + (MSEC_PER_SEC / 2)) / MSEC_PER_SEC;
+	nicp.params.sync.delta_jiffies = ((nics->inc_ticks * HZ) + (MSEC_PER_SEC / 2)) / MSEC_PER_SEC;
 
 	/*
 	 * Call IPv4 manager callback function
@@ -487,28 +487,28 @@
 	 */
 	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;
+	nss_top->stats_ipv4[NSS_STATS_IPV4_ACCELERATED_RX_PKTS] += nics->flow_rx_packet_count + nics->return_rx_packet_count;
+	nss_top->stats_ipv4[NSS_STATS_IPV4_ACCELERATED_RX_BYTES] += nics->flow_rx_byte_count + nics->return_rx_byte_count;
+	nss_top->stats_ipv4[NSS_STATS_IPV4_ACCELERATED_TX_PKTS] += nics->flow_tx_packet_count + nics->return_tx_packet_count;
+	nss_top->stats_ipv4[NSS_STATS_IPV4_ACCELERATED_TX_BYTES] += nics->flow_tx_byte_count + nics->return_tx_byte_count;
 
 	/*
 	 * Update the PPPoE interface stats, if there is any PPPoE session on the interfaces.
 	 */
-	if (nirs->flow_pppoe_session_id) {
-		pppoe_dev = ppp_session_to_netdev(nirs->flow_pppoe_session_id, (uint8_t *)nirs->flow_pppoe_remote_mac);
+	if (nics->flow_pppoe_session_id) {
+		pppoe_dev = ppp_session_to_netdev(nics->flow_pppoe_session_id, (uint8_t *)nics->flow_pppoe_remote_mac);
 		if (pppoe_dev) {
-			ppp_update_stats(pppoe_dev, nirs->flow_rx_packet_count, nirs->flow_rx_byte_count,
-					nirs->flow_tx_packet_count, nirs->flow_tx_byte_count);
+			ppp_update_stats(pppoe_dev, nics->flow_rx_packet_count, nics->flow_rx_byte_count,
+					nics->flow_tx_packet_count, nics->flow_tx_byte_count);
 			dev_put(pppoe_dev);
 		}
 	}
 
-	if (nirs->return_pppoe_session_id) {
-		pppoe_dev = ppp_session_to_netdev(nirs->return_pppoe_session_id, (uint8_t *)nirs->return_pppoe_remote_mac);
+	if (nics->return_pppoe_session_id) {
+		pppoe_dev = ppp_session_to_netdev(nics->return_pppoe_session_id, (uint8_t *)nics->return_pppoe_remote_mac);
 		if (pppoe_dev) {
-			ppp_update_stats(pppoe_dev, nirs->return_rx_packet_count, nirs->return_rx_byte_count,
-					nirs->return_tx_packet_count, nirs->return_tx_byte_count);
+			ppp_update_stats(pppoe_dev, nics->return_rx_packet_count, nics->return_rx_byte_count,
+					nics->return_tx_packet_count, nics->return_tx_byte_count);
 			dev_put(pppoe_dev);
 		}
 	}
@@ -521,6 +521,41 @@
 }
 
 /*
+ * nss_rx_metadata_ipv4_node_stats_sync()
+ *	Handle the syncing of an IPv4 node stats.
+ */
+static void nss_rx_metadata_ipv4_node_stats_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;
+
+	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_RX_DROPPED] += nins->node_stats.rx_dropped;
+	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;
+
+	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;
+
+
+	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_rx_ipv4_interface_handler()
  *	Handle NSS -> HLOS messages for IPv4 bridge/route
  */
@@ -541,8 +576,12 @@
 		nss_rx_metadata_ipv4_rule_establish(nss_ctx, &nim->msg.rule_establish);
 		break;
 
-	case NSS_IPV4_RX_SYNC_MSG:
-		nss_rx_metadata_ipv4_rule_sync(nss_ctx, &nim->msg.rule_sync);
+	case NSS_IPV4_RX_CONN_STATS_SYNC_MSG:
+		nss_rx_metadata_ipv4_conn_sync(nss_ctx, &nim->msg.conn_stats);
+		break;
+
+	case NSS_IPV4_RX_NODE_STATS_SYNC_MSG:
+		nss_rx_metadata_ipv4_node_stats_sync(nss_ctx, &nim->msg.node_stats);
 		break;
 
 	default:
diff --git a/nss_tx_rx_ipv6.c b/nss_tx_rx_ipv6.c
index eb11ac5..08c452a 100755
--- a/nss_tx_rx_ipv6.c
+++ b/nss_tx_rx_ipv6.c
@@ -404,48 +404,48 @@
 }
 
 /*
- * nss_rx_metadata_ipv6_rule_sync()
- *	Handle the syncing of an IPv6 rule.
+ * nss_rx_metadata_ipv6_conn_sync()
+ *	Handle the syncing of an IPv6 connection.
  */
-static void nss_rx_metadata_ipv6_rule_sync(struct nss_ctx_instance *nss_ctx, struct nss_ipv6_rule_sync *nirs)
+static void nss_rx_metadata_ipv6_conn_sync(struct nss_ctx_instance *nss_ctx, struct nss_ipv6_conn_sync *nics)
 {
 	struct nss_top_instance *nss_top = nss_ctx->nss_top;
 	struct nss_ipv6_cb_params nicp;
 	struct net_device *pppoe_dev = NULL;
 
 	nicp.reason = NSS_IPV6_CB_REASON_SYNC;
-	nicp.params.sync.index = nirs->index;
-	nicp.params.sync.flow_max_window = nirs->flow_max_window;
-	nicp.params.sync.flow_end = nirs->flow_end;
-	nicp.params.sync.flow_max_end = nirs->flow_max_end;
-	nicp.params.sync.flow_rx_packet_count = nirs->flow_rx_packet_count;
-	nicp.params.sync.flow_rx_byte_count = nirs->flow_rx_byte_count;
-	nicp.params.sync.flow_tx_packet_count = nirs->flow_tx_packet_count;
-	nicp.params.sync.flow_tx_byte_count = nirs->flow_tx_byte_count;
-	nicp.params.sync.return_max_window = nirs->return_max_window;
-	nicp.params.sync.return_end = nirs->return_end;
-	nicp.params.sync.return_max_end = nirs->return_max_end;
-	nicp.params.sync.return_rx_packet_count = nirs->return_rx_packet_count;
-	nicp.params.sync.return_rx_byte_count = nirs->return_rx_byte_count;
-	nicp.params.sync.return_tx_packet_count = nirs->return_tx_packet_count;
-	nicp.params.sync.return_tx_byte_count = nirs->return_tx_byte_count;
+	nicp.params.sync.index = nics->index;
+	nicp.params.sync.flow_max_window = nics->flow_max_window;
+	nicp.params.sync.flow_end = nics->flow_end;
+	nicp.params.sync.flow_max_end = nics->flow_max_end;
+	nicp.params.sync.flow_rx_packet_count = nics->flow_rx_packet_count;
+	nicp.params.sync.flow_rx_byte_count = nics->flow_rx_byte_count;
+	nicp.params.sync.flow_tx_packet_count = nics->flow_tx_packet_count;
+	nicp.params.sync.flow_tx_byte_count = nics->flow_tx_byte_count;
+	nicp.params.sync.return_max_window = nics->return_max_window;
+	nicp.params.sync.return_end = nics->return_end;
+	nicp.params.sync.return_max_end = nics->return_max_end;
+	nicp.params.sync.return_rx_packet_count = nics->return_rx_packet_count;
+	nicp.params.sync.return_rx_byte_count = nics->return_rx_byte_count;
+	nicp.params.sync.return_tx_packet_count = nics->return_tx_packet_count;
+	nicp.params.sync.return_tx_byte_count = nics->return_tx_byte_count;
 
-	nicp.params.sync.qos_tag = nirs->qos_tag;
+	nicp.params.sync.qos_tag = nics->qos_tag;
 
 	nicp.params.sync.flags = 0;
-	if (nirs->flags & NSS_IPV6_RULE_CREATE_FLAG_NO_SEQ_CHECK) {
+	if (nics->flags & NSS_IPV6_RULE_CREATE_FLAG_NO_SEQ_CHECK) {
 		nicp.params.sync.flags |= NSS_IPV6_CREATE_FLAG_NO_SEQ_CHECK;
 	}
 
-	if (nirs->flags & NSS_IPV6_RULE_CREATE_FLAG_BRIDGE_FLOW) {
+	if (nics->flags & NSS_IPV6_RULE_CREATE_FLAG_BRIDGE_FLOW) {
 		nicp.params.sync.flags |= NSS_IPV6_CREATE_FLAG_BRIDGE_FLOW;
 	}
 
-	if (nirs->flags & NSS_IPV6_RULE_CREATE_FLAG_ROUTED) {
+	if (nics->flags & NSS_IPV6_RULE_CREATE_FLAG_ROUTED) {
 		nicp.params.sync.flags |= NSS_IPV6_CREATE_FLAG_ROUTED;
 	}
 
-	switch(nirs->reason) {
+	switch(nics->reason) {
 	case NSS_IPV6_RULE_SYNC_REASON_FLUSH:
 	case NSS_IPV6_RULE_SYNC_REASON_DESTROY:
 	case NSS_IPV6_RULE_SYNC_REASON_EVICT:
@@ -457,7 +457,7 @@
 		break;
 
 	default:
-		nss_warning("Bad ipv6 sync reason: %d\n", nirs->reason);
+		nss_warning("Bad ipv6 sync reason: %d\n", nics->reason);
 		return;
 	}
 
@@ -468,7 +468,7 @@
 	 * time bases don't cause truncation errors.
 	 */
 	nss_assert(HZ <= 100000);
-	nicp.params.sync.delta_jiffies = ((nirs->inc_ticks * HZ) + (MSEC_PER_SEC / 2)) / MSEC_PER_SEC;
+	nicp.params.sync.delta_jiffies = ((nics->inc_ticks * HZ) + (MSEC_PER_SEC / 2)) / MSEC_PER_SEC;
 
 	/*
 	 * Call IPv6 manager callback function
@@ -484,28 +484,28 @@
 	 */
 	spin_lock_bh(&nss_top->stats_lock);
 
-	nss_top->stats_ipv6[NSS_STATS_IPV6_ACCELERATED_RX_PKTS] += nirs->flow_rx_packet_count + nirs->return_rx_packet_count;
-	nss_top->stats_ipv6[NSS_STATS_IPV6_ACCELERATED_RX_BYTES] += nirs->flow_rx_byte_count + nirs->return_rx_byte_count;
-	nss_top->stats_ipv6[NSS_STATS_IPV6_ACCELERATED_TX_PKTS] += nirs->flow_tx_packet_count + nirs->return_tx_packet_count;
-	nss_top->stats_ipv6[NSS_STATS_IPV6_ACCELERATED_TX_BYTES] += nirs->flow_tx_byte_count + nirs->return_tx_byte_count;
+	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;
 
 	/*
 	 * Update the PPPoE interface stats, if there is any PPPoE session on the interfaces.
 	 */
-	if (nirs->flow_pppoe_session_id) {
-		pppoe_dev = ppp_session_to_netdev(nirs->flow_pppoe_session_id, (uint8_t *)nirs->flow_pppoe_remote_mac);
+	if (nics->flow_pppoe_session_id) {
+		pppoe_dev = ppp_session_to_netdev(nics->flow_pppoe_session_id, (uint8_t *)nics->flow_pppoe_remote_mac);
 		if (pppoe_dev) {
-			ppp_update_stats(pppoe_dev, nirs->flow_rx_packet_count, nirs->flow_rx_byte_count,
-					nirs->flow_tx_packet_count, nirs->flow_tx_byte_count);
+			ppp_update_stats(pppoe_dev, nics->flow_rx_packet_count, nics->flow_rx_byte_count,
+					nics->flow_tx_packet_count, nics->flow_tx_byte_count);
 			dev_put(pppoe_dev);
 		}
 	}
 
-	if (nirs->return_pppoe_session_id) {
-		pppoe_dev = ppp_session_to_netdev(nirs->return_pppoe_session_id, (uint8_t *)nirs->return_pppoe_remote_mac);
+	if (nics->return_pppoe_session_id) {
+		pppoe_dev = ppp_session_to_netdev(nics->return_pppoe_session_id, (uint8_t *)nics->return_pppoe_remote_mac);
 		if (pppoe_dev) {
-			ppp_update_stats(pppoe_dev, nirs->return_rx_packet_count, nirs->return_rx_byte_count,
-				nirs->return_tx_packet_count, nirs->return_tx_byte_count);
+			ppp_update_stats(pppoe_dev, nics->return_rx_packet_count, nics->return_rx_byte_count,
+				nics->return_tx_packet_count, nics->return_tx_byte_count);
 			dev_put(pppoe_dev);
 		}
 	}
@@ -518,6 +518,40 @@
 }
 
 /*
+ * nss_rx_metadata_ipv6_node_stats_sync()
+ *	Handle the syncing of an IPv6 connection.
+ */
+static void nss_rx_metadata_ipv6_node_stats_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;
+
+	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_RX_DROPPED] += nins->node_stats.rx_dropped;
+	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;
+
+	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;
+
+	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_rx_ipv6_interface_handler()
  *	Handle NSS -> HLOS messages for IPv6 bridge/route
  */
@@ -538,10 +572,15 @@
 		nss_rx_metadata_ipv6_rule_establish(nss_ctx, &nim->msg.rule_establish);
 		break;
 
-	case NSS_IPV6_RX_SYNC_MSG:
-		nss_rx_metadata_ipv6_rule_sync(nss_ctx, &nim->msg.rule_sync);
+	case NSS_IPV6_RX_CONN_STATS_SYNC_MSG:
+		nss_rx_metadata_ipv6_conn_sync(nss_ctx, &nim->msg.conn_stats);
 		break;
 
+	case NSS_IPV6_RX_NODE_STATS_SYNC_MSG:
+		nss_rx_metadata_ipv6_node_stats_sync(nss_ctx, &nim->msg.node_stats);
+		break;
+
+
 	default:
 		if (ncm->response != NSS_CMN_RESPONSE_ACK) {
 			/*
diff --git a/nss_tx_rx_n2h.c b/nss_tx_rx_n2h.c
new file mode 100755
index 0000000..b26e9aa
--- /dev/null
+++ b/nss_tx_rx_n2h.c
@@ -0,0 +1,104 @@
+/*
+ **************************************************************************
+ * Copyright (c) 2013, 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_tx_rx_n2h.c
+ *	NSS N2H node APIs
+ */
+
+#include "nss_tx_rx_common.h"
+
+/*
+ **********************************
+ Rx APIs
+ **********************************
+ */
+
+/*
+ * nss_rx_metadata_n2h_stats_sync()
+ *	Handle the syncing of NSS statistics.
+ */
+static void nss_rx_metadata_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;
+
+	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_RX_DROPPED] += nnss->node_stats.rx_dropped;
+	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;
+
+	/*
+	 * General N2H stats
+	 */
+	nss_ctx->stats_n2h[NSS_STATS_N2H_QUEUE_DROPPED] += nnss->node_stats.rx_packets;
+	nss_ctx->stats_n2h[NSS_STATS_N2H_TOTAL_TICKS] += nnss->node_stats.rx_bytes;
+	nss_ctx->stats_n2h[NSS_STATS_N2H_WORST_CASE_TICKS] += nnss->node_stats.rx_dropped;
+	nss_ctx->stats_n2h[NSS_STATS_N2H_ITERATIONS] += nnss->node_stats.tx_packets;
+
+	/*
+	 * pbuf/payload mgr stats
+	 */
+	nss_ctx->stats_n2h[NSS_STATS_N2H_PBUF_ALLOC_FAILS] += nnss->pbuf_alloc_fails;
+	nss_ctx->stats_n2h[NSS_STATS_N2H_PAYLOAD_ALLOC_FAILS] += nnss->payload_alloc_fails;
+
+	spin_unlock_bh(&nss_top->stats_lock);
+}
+
+/*
+ * nss_rx_n2h_interface_handler()
+ *	Handle NSS -> HLOS messages for N2H node
+ */
+static void nss_rx_n2h_interface_handler(struct nss_ctx_instance *nss_ctx, struct nss_cmn_msg *ncm, __attribute__((unused))void *app_data)
+{
+	struct nss_n2h_msg *nnm = (struct nss_n2h_msg *)ncm;
+
+	/*
+	 * Is this a valid request/response packet?
+	 */
+	if (nnm->cm.type >= NSS_METADATA_TYPE_N2H_MAX) {
+		nss_warning("%p: received invalid message %d for Offload stats interface", nss_ctx, nnm->cm.type);
+		return;
+	}
+
+	switch (nnm->cm.type) {
+	case NSS_RX_METADATA_TYPE_N2H_STATS_SYNC:
+		nss_rx_metadata_n2h_stats_sync(nss_ctx, &nnm->msg.stats_sync);
+		break;
+
+	default:
+		if (ncm->response != NSS_CMN_RESPONSE_ACK) {
+			/*
+			 * Check response
+			 */
+			nss_info("%p: Received response %d for type %d, interface %d",
+						nss_ctx, ncm->response, ncm->type, ncm->interface);
+		}
+	}
+}
+
+/*
+ * nss_n2h_register_handler()
+ */
+void nss_n2h_register_handler()
+{
+	nss_core_register_handler(NSS_N2H_INTERFACE, nss_rx_n2h_interface_handler, NULL);
+}
diff --git a/nss_tx_rx_pppoe.c b/nss_tx_rx_pppoe.c
index aade1f5..5b32ed9 100755
--- a/nss_tx_rx_pppoe.c
+++ b/nss_tx_rx_pppoe.c
@@ -90,10 +90,11 @@
 	 * Reset the PPPoE statistics.
 	 */
 	spin_lock_bh(&nss_top->stats_lock);
+
 	/*
 	 * TODO: Don't reset all the statistics. Reset only the destroyed session's stats.
 	 */
-	for (i = 0; i < NSS_MAX_NET_INTERFACES; i++) {
+	for (i = 0; i < NSS_MAX_PHYSICAL_INTERFACES; i++) {
 		for (j = 0; j < NSS_PPPOE_NUM_SESSION_PER_INTERFACE; j++) {
 			for (k = 0; k < NSS_EXCEPTION_EVENT_PPPOE_MAX; k++) {
 				nss_top->stats_if_exception_pppoe[i][j][k] = 0;
@@ -122,9 +123,8 @@
  * nss_rx_metadata_pppoe_exception_stats_sync()
  *	Handle the syncing of PPPoE exception statistics.
  */
-static void nss_rx_metadata_pppoe_exception_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_pppoe_exception_stats_sync *npess)
+static void nss_rx_metadata_pppoe_exception_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_pppoe_conn_sync *npess)
 {
-	/* Place holder */
 	struct nss_top_instance *nss_top = nss_ctx->nss_top;
 	uint32_t index = npess->index;
 	uint32_t interface_num = npess->interface_num;
@@ -132,6 +132,14 @@
 
 	spin_lock_bh(&nss_top->stats_lock);
 
+	if (interface_num >= NSS_MAX_PHYSICAL_INTERFACES) {
+		nss_warning("%p: Incorrect interface number %d for PPPoE exception stats", nss_ctx, interface_num)
+		return;
+	}
+
+	/*
+	 * pppoe exception stats
+	 */
 	for (i = 0; i < NSS_EXCEPTION_EVENT_PPPOE_MAX; i++) {
 		nss_top->stats_if_exception_pppoe[interface_num][index][i] += npess->exception_events_pppoe[i];
 	}
@@ -140,6 +148,30 @@
 }
 
 /*
+ * nss_rx_metadata_pppoe_node_stats_sync()
+ *	Handle the syncing of PPPoE node statistics.
+ */
+static void nss_rx_metadata_pppoe_node_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_pppoe_node_sync *npess)
+{
+	struct nss_top_instance *nss_top = nss_ctx->nss_top;
+
+	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_RX_DROPPED] += npess->node_stats.rx_dropped;
+	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;
+
+	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_MISSES] += npess->pppoe_session_destroy_misses;
+
+	spin_unlock_bh(&nss_top->stats_lock);
+}
+
+/*
  * nss_rx_metadata_pppoe_rule_create_success()
  *	Handle the PPPoE rule create success message.
  */
@@ -179,8 +211,12 @@
 	}
 
 	switch (npm->cm.type) {
-	case NSS_RX_METADATA_TYPE_PPPOE_STATS_SYNC:
-		nss_rx_metadata_pppoe_exception_stats_sync(nss_ctx, &npm->msg.stats_sync);
+	case NSS_RX_METADATA_TYPE_PPPOE_CONN_STATS_SYNC:
+		nss_rx_metadata_pppoe_exception_stats_sync(nss_ctx, &npm->msg.conn_sync);
+		break;
+
+	case NSS_RX_METADATA_TYPE_PPPOE_NODE_STATS_SYNC:
+		nss_rx_metadata_pppoe_node_stats_sync(nss_ctx, &npm->msg.node_sync);
 		break;
 
 	case NSS_RX_METADATA_TYPE_PPPOE_RULE_STATUS: