Merge "[qca-nss-drv] Add PPPoE base node statistics"
diff --git a/exports/nss_pppoe.h b/exports/nss_pppoe.h
index 07f05bb..1df5828 100644
--- a/exports/nss_pppoe.h
+++ b/exports/nss_pppoe.h
@@ -45,14 +45,28 @@
 };
 
 /**
- * nss_pppoe_exception_events
- *	Exception events from the PPPoE handler.
+ * nss_pppoe_session_exception_events
+ *	Session exception events from the PPPoE handler.
  */
-enum nss_pppoe_exception_events {
-	NSS_PPPOE_EXCEPTION_EVENT_WRONG_VERSION_OR_TYPE,
-	NSS_PPPOE_EXCEPTION_EVENT_WRONG_CODE,
-	NSS_PPPOE_EXCEPTION_EVENT_UNSUPPORTED_PPP_PROTOCOL,
-	NSS_PPPOE_EXCEPTION_EVENT_MAX
+enum nss_pppoe_session_exception_events {
+	NSS_PPPOE_SESSION_EXCEPTION_EVENT_WRONG_VERSION_OR_TYPE,
+	NSS_PPPOE_SESSION_EXCEPTION_EVENT_WRONG_CODE,
+	NSS_PPPOE_SESSION_EXCEPTION_EVENT_UNSUPPORTED_PPP_PROTOCOL,
+	NSS_PPPOE_SESSION_EXCEPTION_EVENT_MAX
+};
+
+/**
+ * pppoe_base_exception_events
+ * 	Base node exception events from the PPPoE handler.
+ */
+enum nss_pppoe_base_exception_events {
+	NSS_PPPOE_BASE_EXCEPTION_EVENT_SHORT_PPPOE_HDR_LENGTH,
+	NSS_PPPOE_BASE_EXCEPTION_EVENT_SHORT_PACKET_LENGTH,
+	NSS_PPPOE_BASE_EXCEPTION_EVENT_WRONG_VERSION_OR_TYPE,
+	NSS_PPPOE_BASE_EXCEPTION_EVENT_WRONG_CODE,
+	NSS_PPPOE_BASE_EXCEPTION_EVENT_UNSUPPORTED_PPP_PROTOCOL,
+	NSS_PPPOE_BASE_EXCEPTION_EVENT_DISABLED_BRIDGE_PACKET,
+	NSS_PPPOE_BASE_EXCEPTION_EVENT_MAX
 };
 
 /**
@@ -67,13 +81,32 @@
 };
 
 /**
+ * nss_pppoe_base_stats
+ * 	PPPoE base node synchronization statistics.
+ */
+struct nss_pppoe_base_stats {
+	struct nss_cmn_node_stats node;	/**< Common node statistics. */
+	uint32_t exception[NSS_PPPOE_BASE_EXCEPTION_EVENT_MAX];
+						/**< PPPoE base node exception events. */
+};
+
+/**
+ * nss_pppoe_session_stats
+ * 	PPPoE synchronization statistics per session.
+ */
+struct nss_pppoe_session_stats {
+	struct nss_cmn_node_stats node;	/**< Common node statistics. */
+	uint32_t exception[NSS_PPPOE_SESSION_EXCEPTION_EVENT_MAX];
+						/**< PPPoE session exception events. */
+};
+
+/**
  * nss_pppoe_sync_stats_msg
- *	PPPoE node synchronization statistics.
+ *	PPPoE synchronization statistics.
  */
 struct nss_pppoe_sync_stats_msg {
-	struct nss_cmn_node_stats stats;	/**< Common node statistics. */
-	uint32_t exception_events[NSS_PPPOE_EXCEPTION_EVENT_MAX];
-			/**< PPPoE exception events. */
+	struct nss_pppoe_session_stats session_stats;	/**< Session statistics. */
+	struct nss_pppoe_base_stats base_stats;		/**< Base node statistics. */
 };
 
 /**
diff --git a/nss_pppoe.c b/nss_pppoe.c
index a85c7a2..bee4ca9 100644
--- a/nss_pppoe.c
+++ b/nss_pppoe.c
@@ -25,11 +25,6 @@
 
 #define NSS_PPPOE_TX_TIMEOUT 3000 /* 3 Seconds */
 
-/*
- * Data structures to store pppoe nss debug stats
- */
-static DEFINE_SPINLOCK(nss_pppoe_lock);
-static struct nss_pppoe_stats_session_debug nss_pppoe_debug_stats[NSS_MAX_PPPOE_DYNAMIC_INTERFACES];
 int nss_pppoe_br_accel_mode __read_mostly = NSS_PPPOE_BR_ACCEL_MODE_EN_5T;
 
 /*
@@ -57,28 +52,6 @@
 }
 
 /*
- * nss_pppoe_debug_stats_sync
- *	Per session debug stats for pppoe
- */
-static void nss_pppoe_debug_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_pppoe_sync_stats_msg *stats_msg, uint16_t if_num)
-{
-	int i;
-	spin_lock_bh(&nss_pppoe_lock);
-	for (i = 0; i < NSS_MAX_PPPOE_DYNAMIC_INTERFACES; i++) {
-		if (nss_pppoe_debug_stats[i].if_num == if_num) {
-			nss_pppoe_debug_stats[i].stats[NSS_PPPOE_STATS_RX_PACKETS] += stats_msg->stats.rx_packets;
-			nss_pppoe_debug_stats[i].stats[NSS_PPPOE_STATS_RX_BYTES] += stats_msg->stats.rx_bytes;
-			nss_pppoe_debug_stats[i].stats[NSS_PPPOE_STATS_TX_PACKETS] += stats_msg->stats.tx_packets;
-			nss_pppoe_debug_stats[i].stats[NSS_PPPOE_STATS_TX_BYTES] += stats_msg->stats.tx_bytes;
-			nss_pppoe_debug_stats[i].stats[NSS_PPPOE_STATS_SESSION_WRONG_VERSION_OR_TYPE] += stats_msg->exception_events[NSS_PPPOE_EXCEPTION_EVENT_WRONG_VERSION_OR_TYPE];
-			nss_pppoe_debug_stats[i].stats[NSS_PPPOE_STATS_SESSION_WRONG_CODE] += stats_msg->exception_events[NSS_PPPOE_EXCEPTION_EVENT_WRONG_CODE];
-			nss_pppoe_debug_stats[i].stats[NSS_PPPOE_STATS_SESSION_UNSUPPORTED_PPP_PROTOCOL] += stats_msg->exception_events[NSS_PPPOE_EXCEPTION_EVENT_UNSUPPORTED_PPP_PROTOCOL];
-			break;
-		}
-	}
-	spin_unlock_bh(&nss_pppoe_lock);
-}
-/*
  * nss_pppoe_get_context()
  */
 struct nss_ctx_instance *nss_pppoe_get_context(void)
@@ -150,7 +123,7 @@
  */
 static void nss_pppoe_handler(struct nss_ctx_instance *nss_ctx, struct nss_cmn_msg *ncm, __attribute__((unused))void *app_data)
 {
-	struct nss_pppoe_msg *nim = (struct nss_pppoe_msg *)ncm;
+	struct nss_pppoe_msg *npm = (struct nss_pppoe_msg *)ncm;
 	void *ctx;
 	nss_pppoe_msg_callback_t cb;
 
@@ -159,7 +132,7 @@
 	/*
 	 * Trace Messages
 	 */
-	nss_pppoe_log_rx_msg(nim);
+	nss_pppoe_log_rx_msg(npm);
 
 	/*
 	 * Sanity check the message type
@@ -182,9 +155,9 @@
 	/*
 	 * Handling PPPoE messages coming from NSS fw.
 	 */
-	switch (nim->cm.type) {
+	switch (npm->cm.type) {
 	case NSS_PPPOE_MSG_SYNC_STATS:
-		nss_pppoe_debug_stats_sync(nss_ctx, &nim->msg.sync_stats, ncm->interface);
+		nss_pppoe_stats_sync(nss_ctx, &npm->msg.sync_stats, ncm->interface);
 		break;
 	default:
 		nss_warning("%p: Received response %d for type %d, interface %d\n",
@@ -218,31 +191,7 @@
 	cb = (nss_pppoe_msg_callback_t)ncm->cb;
 	ctx = (void *)ncm->app_data;
 
-	cb(ctx, nim);
-}
-
-/*
- * nss_pppoe_debug_stats_get()
- *	Get session pppoe statistics.
- */
-void nss_pppoe_debug_stats_get(void *stats_mem)
-{
-	struct nss_pppoe_stats_session_debug *stats = (struct nss_pppoe_stats_session_debug *)stats_mem;
-	int i;
-
-	if (!stats) {
-		nss_warning("No memory to copy pppoe session stats\n");
-		return;
-	}
-
-	spin_lock_bh(&nss_pppoe_lock);
-	for (i = 0; i < NSS_MAX_PPPOE_DYNAMIC_INTERFACES; i++) {
-		if (nss_pppoe_debug_stats[i].valid) {
-			memcpy(stats, &nss_pppoe_debug_stats[i], sizeof(struct nss_pppoe_stats_session_debug));
-			stats++;
-		}
-	}
-	spin_unlock_bh(&nss_pppoe_lock);
+	cb(ctx, npm);
 }
 
 /*
@@ -349,23 +298,11 @@
 						       struct net_device *netdev, uint32_t features, void *app_ctx)
 {
 	struct nss_ctx_instance *nss_ctx = nss_pppoe_get_context();
-	int i = 0;
 
 	nss_assert(nss_ctx);
 	nss_assert(nss_is_dynamic_interface(if_num));
 
-	spin_lock_bh(&nss_pppoe_lock);
-	for (i = 0; i < NSS_MAX_PPPOE_DYNAMIC_INTERFACES; i++) {
-		if (!nss_pppoe_debug_stats[i].valid) {
-			nss_pppoe_debug_stats[i].valid = true;
-			nss_pppoe_debug_stats[i].if_num = if_num;
-			nss_pppoe_debug_stats[i].if_index = netdev->ifindex;
-			break;
-		}
-	}
-	spin_unlock_bh(&nss_pppoe_lock);
-
-	if (i == NSS_MAX_PPPOE_DYNAMIC_INTERFACES) {
+	if (!nss_pppoe_stats_pppoe_session_init(if_num, netdev)) {
 		return NULL;
 	}
 
@@ -385,20 +322,11 @@
 void nss_unregister_pppoe_session_if(uint32_t if_num)
 {
 	struct nss_ctx_instance *nss_ctx = nss_pppoe_get_context();
-	int i;
 
 	nss_assert(nss_ctx);
 	nss_assert(nss_is_dynamic_interface(if_num));
 
-	spin_lock_bh(&nss_pppoe_lock);
-	for (i = 0; i < NSS_MAX_PPPOE_DYNAMIC_INTERFACES; i++) {
-		if (nss_pppoe_debug_stats[i].if_num == if_num) {
-			nss_pppoe_debug_stats[i].valid = false;
-			nss_pppoe_debug_stats[i].if_num = 0;
-			nss_pppoe_debug_stats[i].if_index = 0;
-		}
-	}
-	spin_unlock_bh(&nss_pppoe_lock);
+	nss_pppoe_stats_pppoe_session_deinit(if_num);
 
 	nss_core_unregister_subsys_dp(nss_ctx, if_num);
 
@@ -480,19 +408,9 @@
  */
 void nss_pppoe_register_handler(void)
 {
-	int i;
-
 	nss_info("nss_pppoe_register_handler\n");
 	nss_core_register_handler(nss_pppoe_get_context(), NSS_PPPOE_INTERFACE, nss_pppoe_handler, NULL);
 
-	spin_lock_bh(&nss_pppoe_lock);
-	for (i = 0; i < NSS_MAX_PPPOE_DYNAMIC_INTERFACES; i++) {
-		nss_pppoe_debug_stats[i].valid = false;
-		nss_pppoe_debug_stats[i].if_num = 0;
-		nss_pppoe_debug_stats[i].if_index = 0;
-	}
-	spin_unlock_bh(&nss_pppoe_lock);
-
 	sema_init(&pppoe_pvt.sem, 1);
 	init_completion(&pppoe_pvt.complete);
 
diff --git a/nss_pppoe_stats.c b/nss_pppoe_stats.c
index c5c95af..b7cc748 100644
--- a/nss_pppoe_stats.c
+++ b/nss_pppoe_stats.c
@@ -1,6 +1,6 @@
 /*
  **************************************************************************
- * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
  * above copyright notice and this permission notice appear in all copies.
@@ -16,13 +16,73 @@
 
 #include "nss_stats.h"
 #include "nss_core.h"
-#include "nss_pppoe_stats.h"
 
 /*
- * nss_pppoe_stats_str
- *	PPPoE stats strings
+ * Lock used for PPPoE statistics
  */
-static int8_t *nss_pppoe_stats_debug_str[NSS_PPPOE_STATS_SESSION_MAX] = {
+static DEFINE_SPINLOCK(nss_pppoe_stats_lock);
+
+/*
+ * PPPoE per session statistics
+ */
+enum nss_pppoe_stats_session {
+	NSS_PPPOE_STATS_SESSION_RX_PACKETS,
+	NSS_PPPOE_STATS_SESSION_RX_BYTES,
+	NSS_PPPOE_STATS_SESSION_TX_PACKETS,
+	NSS_PPPOE_STATS_SESSION_TX_BYTES,
+	NSS_PPPOE_STATS_SESSION_WRONG_VERSION_OR_TYPE,
+	NSS_PPPOE_STATS_SESSION_WRONG_CODE,
+	NSS_PPPOE_STATS_SESSION_UNSUPPORTED_PPP_PROTOCOL,
+	NSS_PPPOE_STATS_SESSION_MAX
+};
+
+/*
+ * PPPoE base node statistics
+ */
+enum nss_pppoe_stats_base {
+	NSS_PPPOE_STATS_BASE_RX_PACKETS,
+	NSS_PPPOE_STATS_BASE_RX_BYTES,
+	NSS_PPPOE_STATS_BASE_TX_PACKETS,
+	NSS_PPPOE_STATS_BASE_TX_BYTES,
+	NSS_PPPOE_STATS_BASE_RX_QUEUE_0_DROPPED,
+	NSS_PPPOE_STATS_BASE_RX_QUEUE_1_DROPPED,
+	NSS_PPPOE_STATS_BASE_RX_QUEUE_2_DROPPED,
+	NSS_PPPOE_STATS_BASE_RX_QUEUE_3_DROPPED,
+	NSS_PPPOE_STATS_BASE_SHORT_PPPOE_HDR_LENGTH,
+	NSS_PPPOE_STATS_BASE_SHORT_PACKET_LENGTH,
+	NSS_PPPOE_STATS_BASE_WRONG_VERSION_OR_TYPE,
+	NSS_PPPOE_STATS_BASE_WRONG_CODE,
+	NSS_PPPOE_STATS_BASE_UNSUPPORTED_PPP_PROTOCOL,
+	NSS_PPPOE_STATS_BASE_DISABLED_BRIDGE_PACKET,
+	NSS_PPPOE_STATS_BASE_MAX
+};
+
+/*
+ * PPPoE session stats structure for debug interface
+ */
+struct nss_pppoe_stats_session_stats {
+	uint64_t stats[NSS_PPPOE_STATS_SESSION_MAX];
+						/* stats for the session */
+	int32_t if_index;	/* net device index for the session */
+	uint32_t if_num;	/* nss interface number */
+	bool valid;			/* dynamic interface valid flag */
+};
+
+/*
+ * PPPoE interface stats structure for base node and sessions
+ */
+struct nss_pppoe_stats {
+	uint64_t base_stats[NSS_PPPOE_STATS_BASE_MAX];
+						/* Base node stats */
+	struct nss_pppoe_stats_session_stats session_stats[NSS_MAX_PPPOE_DYNAMIC_INTERFACES];
+					/* Per session stats */
+};
+
+/*
+ * nss_pppoe_stats_session_str
+ *	PPPoE session stats strings
+ */
+static int8_t *nss_pppoe_stats_session_str[NSS_PPPOE_STATS_SESSION_MAX] = {
 	"RX_PACKETS",
 	"RX_BYTES",
 	"TX_PACKETS",
@@ -33,6 +93,32 @@
 };
 
 /*
+ * nss_pppoe_stats_base_str
+ * 	PPPoE base node stats strings
+ */
+static int8_t *nss_pppoe_stats_base_str[NSS_PPPOE_STATS_BASE_MAX] = {
+	"RX_PACKETS",
+	"RX_BYTES",
+	"TX_PACKETS",
+	"TX_BYTES",
+	"RX_DROPPED[0]",
+	"RX_DROPPED[1]",
+	"RX_DROPPED[2]",
+	"RX_DROPPED[3]",
+	"SHORT_PPPOE_HDR_LENGTH",
+	"SHORT_PACKET_LENGTH",
+	"WRONG_VERSION_OR_TYPE",
+	"WRONG_CODE",
+	"UNSUPPORTED_PPP_PROTOCOL",
+	"DISABLED_BRIDGE_PACKET"
+};
+
+/*
+ * Global PPPoE stats decleration.
+ */
+static struct nss_pppoe_stats pppoe_stats;
+
+/*
  * nss_pppoe_stats_read()
  *	Read pppoe statistics
  */
@@ -41,12 +127,11 @@
 
 	uint32_t max_output_lines = 2 /* header & footer for session stats */
 					+ NSS_MAX_PPPOE_DYNAMIC_INTERFACES * (NSS_PPPOE_STATS_SESSION_MAX + 2) /*session stats */
-					+ 2;
+					+ 2 + NSS_PPPOE_STATS_BASE_MAX + 2;
 	size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
 	size_t size_wr = 0;
 	ssize_t bytes_read = 0;
 	struct net_device *dev;
-	struct nss_pppoe_stats_session_debug pppoe_session_stats[NSS_MAX_PPPOE_DYNAMIC_INTERFACES];
 	int id, i;
 
 	char *lbuf = kzalloc(size_al, GFP_KERNEL);
@@ -55,38 +140,40 @@
 		return 0;
 	}
 
-	memset(&pppoe_session_stats, 0, sizeof(struct nss_pppoe_stats_session_debug) * NSS_MAX_PPPOE_DYNAMIC_INTERFACES);
-
 	/*
-	 * Get all stats
+	 * Base node stats
 	 */
-	nss_pppoe_debug_stats_get((void *)&pppoe_session_stats);
+	size_wr = scnprintf(lbuf + size_wr, size_al - size_wr, "\npppoe base node stats start:\n\n");
+	for (i = 0; i < NSS_PPPOE_STATS_BASE_MAX; i++) {
+		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
+				     "\t%s = %llu\n", nss_pppoe_stats_base_str[i],
+				      pppoe_stats.base_stats[i]);
+	}
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\npppoe base node stats end:\n\n");
 
 	/*
 	 * Session stats
 	 */
 	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\npppoe session stats start:\n\n");
 	for (id = 0; id < NSS_MAX_PPPOE_DYNAMIC_INTERFACES; id++) {
-		if (!pppoe_session_stats[id].valid) {
-			break;
+		if (!pppoe_stats.session_stats[id].valid) {
+			continue;
 		}
 
-		dev = dev_get_by_index(&init_net, pppoe_session_stats[id].if_index);
-		if (likely(dev)) {
-			size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "%d. nss interface id=%d, netdevice=%s\n", id,
-					pppoe_session_stats[id].if_num, dev->name);
-			dev_put(dev);
-		} else {
-			size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "%d. nss interface id=%d\n", id,
-					pppoe_session_stats[id].if_num);
+		dev = dev_get_by_index(&init_net, pppoe_stats.session_stats[id].if_index);
+		if (unlikely(!dev)) {
+			continue;
 		}
 
+		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "%d. nss interface id=%d, netdevice=%s\n", id,
+				pppoe_stats.session_stats[id].if_num, dev->name);
+		dev_put(dev);
+
 		for (i = 0; i < NSS_PPPOE_STATS_SESSION_MAX; i++) {
 			size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
-					     "\t%s = %llu\n", nss_pppoe_stats_debug_str[i],
-					      pppoe_session_stats[id].stats[i]);
+					     "\t%s = %llu\n", nss_pppoe_stats_session_str[i],
+					      pppoe_stats.session_stats[id].stats[i]);
 		}
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\n");
 	}
 
 	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\npppoe session stats end\n");
@@ -97,6 +184,96 @@
 }
 
 /*
+ * nss_pppoe_stats_pppoe_session_init()
+ *	Initialize the session statistics.
+ */
+bool nss_pppoe_stats_pppoe_session_init(uint32_t if_num, struct net_device *dev)
+{
+	int i;
+
+	spin_lock_bh(&nss_pppoe_stats_lock);
+	for (i = 0; i < NSS_MAX_PPPOE_DYNAMIC_INTERFACES; i++) {
+		if (!pppoe_stats.session_stats[i].valid) {
+			pppoe_stats.session_stats[i].valid = true;
+			pppoe_stats.session_stats[i].if_num = if_num;
+			pppoe_stats.session_stats[i].if_index = dev->ifindex;
+			spin_unlock_bh(&nss_pppoe_stats_lock);
+			return true;
+		}
+	}
+	spin_unlock_bh(&nss_pppoe_stats_lock);
+
+	return false;
+}
+
+/*
+ * nss_pppoe_stats_pppoe_session_deinit()
+ *	De-initialize the session's stats.
+ */
+void nss_pppoe_stats_pppoe_session_deinit(uint32_t if_num)
+{
+	int i;
+
+	spin_lock_bh(&nss_pppoe_stats_lock);
+	for (i = 0; i < NSS_MAX_PPPOE_DYNAMIC_INTERFACES; i++) {
+		if (pppoe_stats.session_stats[i].if_num == if_num) {
+			memset(&pppoe_stats.session_stats[i], 0, sizeof(pppoe_stats.session_stats[i]));
+		}
+	}
+	spin_unlock_bh(&nss_pppoe_stats_lock);
+}
+
+/*
+ * nss_pppoe_stats_sync
+ *	Per session debug stats for pppoe
+ */
+void nss_pppoe_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_pppoe_sync_stats_msg *stats_msg, uint16_t if_num)
+{
+	int i;
+	spin_lock_bh(&nss_pppoe_stats_lock);
+	for (i = 0; i < NSS_MAX_PPPOE_DYNAMIC_INTERFACES; i++) {
+		if (pppoe_stats.session_stats[i].if_num == if_num) {
+			int j;
+
+			/*
+			 * Sync PPPoE session stats.
+			 */
+			pppoe_stats.session_stats[i].stats[NSS_PPPOE_STATS_SESSION_RX_PACKETS] += stats_msg->session_stats.node.rx_packets;
+			pppoe_stats.session_stats[i].stats[NSS_PPPOE_STATS_SESSION_RX_BYTES] += stats_msg->session_stats.node.rx_bytes;
+			pppoe_stats.session_stats[i].stats[NSS_PPPOE_STATS_SESSION_TX_PACKETS] += stats_msg->session_stats.node.tx_packets;
+			pppoe_stats.session_stats[i].stats[NSS_PPPOE_STATS_SESSION_TX_BYTES] += stats_msg->session_stats.node.tx_bytes;
+			pppoe_stats.session_stats[i].stats[NSS_PPPOE_STATS_SESSION_WRONG_VERSION_OR_TYPE] += stats_msg->session_stats.exception[NSS_PPPOE_SESSION_EXCEPTION_EVENT_WRONG_VERSION_OR_TYPE];
+			pppoe_stats.session_stats[i].stats[NSS_PPPOE_STATS_SESSION_WRONG_CODE] += stats_msg->session_stats.exception[NSS_PPPOE_SESSION_EXCEPTION_EVENT_WRONG_CODE];
+			pppoe_stats.session_stats[i].stats[NSS_PPPOE_STATS_SESSION_UNSUPPORTED_PPP_PROTOCOL] += stats_msg->session_stats.exception[NSS_PPPOE_SESSION_EXCEPTION_EVENT_UNSUPPORTED_PPP_PROTOCOL];
+
+			/*
+			 * Sync PPPoE base node stats coming with this session's stats.
+			 */
+			pppoe_stats.base_stats[NSS_PPPOE_STATS_BASE_RX_PACKETS] += stats_msg->base_stats.node.rx_packets;
+			pppoe_stats.base_stats[NSS_PPPOE_STATS_BASE_RX_BYTES] += stats_msg->base_stats.node.rx_bytes;
+			pppoe_stats.base_stats[NSS_PPPOE_STATS_BASE_TX_PACKETS] += stats_msg->base_stats.node.tx_packets;
+			pppoe_stats.base_stats[NSS_PPPOE_STATS_BASE_TX_BYTES] += stats_msg->base_stats.node.tx_bytes;
+
+			for (j = 0; j < NSS_MAX_NUM_PRI; j++) {
+				pppoe_stats.base_stats[NSS_PPPOE_STATS_BASE_RX_QUEUE_0_DROPPED + j] += stats_msg->base_stats.node.rx_dropped[j];
+			}
+
+			/*
+			 * Sync PPPoE base exception stats coming with this session's stats.
+			 */
+			pppoe_stats.base_stats[NSS_PPPOE_STATS_BASE_SHORT_PPPOE_HDR_LENGTH] += stats_msg->base_stats.exception[NSS_PPPOE_BASE_EXCEPTION_EVENT_SHORT_PPPOE_HDR_LENGTH];
+			pppoe_stats.base_stats[NSS_PPPOE_STATS_BASE_SHORT_PACKET_LENGTH] += stats_msg->base_stats.exception[NSS_PPPOE_BASE_EXCEPTION_EVENT_SHORT_PACKET_LENGTH];
+			pppoe_stats.base_stats[NSS_PPPOE_STATS_BASE_WRONG_VERSION_OR_TYPE] += stats_msg->base_stats.exception[NSS_PPPOE_BASE_EXCEPTION_EVENT_WRONG_VERSION_OR_TYPE];
+			pppoe_stats.base_stats[NSS_PPPOE_STATS_BASE_WRONG_CODE] += stats_msg->base_stats.exception[NSS_PPPOE_BASE_EXCEPTION_EVENT_WRONG_CODE];
+			pppoe_stats.base_stats[NSS_PPPOE_STATS_BASE_UNSUPPORTED_PPP_PROTOCOL] += stats_msg->base_stats.exception[NSS_PPPOE_BASE_EXCEPTION_EVENT_UNSUPPORTED_PPP_PROTOCOL];
+			pppoe_stats.base_stats[NSS_PPPOE_STATS_BASE_DISABLED_BRIDGE_PACKET] += stats_msg->base_stats.exception[NSS_PPPOE_BASE_EXCEPTION_EVENT_DISABLED_BRIDGE_PACKET];
+			break;
+		}
+	}
+	spin_unlock_bh(&nss_pppoe_stats_lock);
+}
+
+/*
  * nss_pppoe_stats_ops
  */
 NSS_STATS_DECLARE_FILE_OPERATIONS(pppoe)
diff --git a/nss_pppoe_stats.h b/nss_pppoe_stats.h
index 358e7a2..70d65a3 100644
--- a/nss_pppoe_stats.h
+++ b/nss_pppoe_stats.h
@@ -1,6 +1,6 @@
 /*
  ******************************************************************************
- * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017, 2019 The Linux Foundation. All rights reserved.
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
  * above copyright notice and this permission notice appear in all copies.
@@ -18,33 +18,10 @@
 #define __NSS_PPPOE_STATS_H
 
 /*
- * PPPoE statistics
- */
-enum nss_pppoe_stats_session {
-	NSS_PPPOE_STATS_RX_PACKETS,
-	NSS_PPPOE_STATS_RX_BYTES,
-	NSS_PPPOE_STATS_TX_PACKETS,
-	NSS_PPPOE_STATS_TX_BYTES,
-	NSS_PPPOE_STATS_SESSION_WRONG_VERSION_OR_TYPE,
-	NSS_PPPOE_STATS_SESSION_WRONG_CODE,
-	NSS_PPPOE_STATS_SESSION_UNSUPPORTED_PPP_PROTOCOL,
-	NSS_PPPOE_STATS_SESSION_MAX
-};
-
-/*
- * PPPoE session stats structure for debug interface
- */
-struct nss_pppoe_stats_session_debug {
-	uint64_t stats[NSS_PPPOE_STATS_SESSION_MAX];
-				/* stats for the session */
-	int32_t if_index;	/* net device index for the session */
-	uint32_t if_num;	/* nss interface number */
-	bool valid;		/* dynamic interface valid flag */
-};
-
-/*
  * PPPoE statistics APIs
  */
 extern void nss_pppoe_stats_dentry_create(void);
-
+extern void nss_pppoe_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_pppoe_sync_stats_msg *stats_msg, uint16_t if_num);
+extern bool nss_pppoe_stats_pppoe_session_init(uint32_t if_num, struct net_device *dev);
+extern void nss_pppoe_stats_pppoe_session_deinit(uint32_t if_num);
 #endif /* __NSS_PPPOE_STATS_H */