Merge "[qca-nss-drv] Convert PPPoE implementation to clients model"
diff --git a/exports/nss_api_if.h b/exports/nss_api_if.h
index 84d93ff..5a0aaa1 100644
--- a/exports/nss_api_if.h
+++ b/exports/nss_api_if.h
@@ -129,8 +129,8 @@
 		/**< Special interface number for N2H. */
 #define NSS_ETH_RX_INTERFACE (NSS_SPECIAL_IF_START + 2)
 		/**< Special interface number for Ethernet Rx. */
-#define NSS_PPPOE_RX_INTERFACE (NSS_SPECIAL_IF_START + 3)
-		/**< Special interface number for PPPoE sessions. */
+#define NSS_PPPOE_INTERFACE (NSS_SPECIAL_IF_START + 3)
+		/**< Special interface number for PPPoE. */
 #define NSS_IPV4_RX_INTERFACE (NSS_SPECIAL_IF_START + 5)
 		/**< Special interface number for IPv4. */
 #define NSS_IPV6_RX_INTERFACE (NSS_SPECIAL_IF_START + 7)
@@ -343,9 +343,10 @@
 	uint32_t flow_max_window;	/**< Maximum window size (TCP). */
 	uint32_t flow_end;		/**< TCP window end. */
 	uint32_t flow_max_end;		/**< TCP window maximum end. */
-	uint16_t flow_pppoe_session_id;	/**< PPPoE session associated with this flow. */
-	uint8_t flow_pppoe_remote_mac[ETH_ALEN];
-					/**< Remote PPPoE peer MAC address. */
+	uint32_t flow_pppoe_if_exist;
+			/**< Flow direction: PPPoE interface exist flag. */
+	int32_t flow_pppoe_if_num;
+			/**< Flow direction: PPPoE interface number. */
 	uint16_t ingress_vlan_tag;	/**< Ingress VLAN tag expected for this flow. */
 	uint8_t return_window_scale;
 			/**< Window scaling factor of the return direction (TCP). */
@@ -355,10 +356,10 @@
 			/**< Flow end for the return direction. */
 	uint32_t return_max_end;
 			/**< Flow maximum end for the return direction. */
-	uint16_t return_pppoe_session_id;
-			/**< PPPoE session ID for the return direction. */
-	uint8_t return_pppoe_remote_mac[ETH_ALEN];
-			/**< Remote PPPoE peer MAC sddress for the return direction. */
+	uint32_t return_pppoe_if_exist;
+			/**< Return direction: PPPoE interface existence flag. */
+	int32_t return_pppoe_if_num;
+			/**< Return direction: PPPoE interface number. */
 	uint16_t egress_vlan_tag;	/**< Egress VLAN tag expected for this flow. */
 	uint8_t spo_needed;		/**< Indicates whether SPO is required. */
 	uint32_t param_a0;		/**< Custom parameter 0. */
@@ -445,9 +446,10 @@
 	uint32_t flow_max_window;	/**< Maximum window size (TCP). */
 	uint32_t flow_end;		/**< TCP window end. */
 	uint32_t flow_max_end;		/**< TCP window maximum end. */
-	uint16_t flow_pppoe_session_id;	/**< PPPoE session associated with the flow. */
-	uint8_t flow_pppoe_remote_mac[ETH_ALEN];
-			/**< Remote PPPoE peer MAC address. */
+	uint32_t flow_pppoe_if_exist;
+			/**< Flow direction: PPPoE interface existence flag. */
+	int32_t flow_pppoe_if_num;
+			/**< Flow direction: PPPoE interface number. */
 	uint16_t ingress_vlan_tag;
 			/**< Ingress VLAN tag expected for this flow. */
 	uint8_t return_window_scale;
@@ -458,10 +460,10 @@
 			/**< End for the return direction. */
 	uint32_t return_max_end;
 			/**< Maximum end for the return direction. */
-	uint16_t return_pppoe_session_id;
-			/**< PPPoE session associated with the return direction. */
-	uint8_t return_pppoe_remote_mac[ETH_ALEN];
-			/**< Remote PPPoE peer MAC address for the return direction. */
+	uint32_t return_pppoe_if_exist;
+			/**< Return direction: PPPoE interface exist flag. */
+	int32_t return_pppoe_if_num;
+			/**< Return direction: PPPoE interface number. */
 	uint16_t egress_vlan_tag;	/**< Egress VLAN tag expected for this flow. */
 	uint32_t qos_tag;		/**< Deprecated; will be removed soon. */
 	uint32_t flow_qos_tag;		/**< QoS tag value for flow direction. */
@@ -587,9 +589,8 @@
 	uint32_t flow_ident;		/**< Flow identifier (e.g., port). */
 	uint32_t flow_ident_xlate;	/**< Translated flow identifier (e.g., port). */
 	uint16_t flow_mac[3];		/**< Source MAC address for the flow direction. */
-	uint16_t flow_pppoe_session_id;	/**< PPPoE session ID for the flow direction. */
-	uint16_t flow_pppoe_remote_mac[3];
-			/**< PPPoE server MAC address for the flow direction. */
+	uint32_t flow_pppoe_if_exist;	/**< Flow direction: PPPoE interface existence flag. */
+	int32_t flow_pppoe_if_num;	/**< Flow direction: PPPoE interface number. */
 	uint16_t ingress_vlan_tag;	/**< Ingress VLAN tag. */
 	int32_t return_interface;	/**< Return interface number. */
 	uint32_t return_mtu;		/**< MTU for the return interface. */
@@ -598,10 +599,8 @@
 	uint32_t return_ident;		/**< Return identier (e.g., port). */
 	uint32_t return_ident_xlate;	/**< Translated return identifier (e.g., port). */
 	uint16_t return_mac[3];		/**< Source MAC address for the return direction. */
-	uint16_t return_pppoe_session_id;
-			/**< PPPoE session ID for the return direction. */
-	uint16_t return_pppoe_remote_mac[3];
-			/**< PPPoE server MAC address for the return direction. */
+	uint32_t return_pppoe_if_exist;	/**< Return direction: PPPoE interface existence flag. */
+	int32_t return_pppoe_if_num;	/**< Return direction: PPPoE interface number. */
 	uint16_t egress_vlan_tag;	/**< Egress VLAN tag. */
 	uint8_t flags;			/**< Flags indicating the status of the flow. */
 	uint32_t qos_tag;		/**< QoS value of the flow. */
@@ -701,20 +700,16 @@
 	uint32_t flow_ip[4];	/**< Flow IP address. */
 	uint32_t flow_ident;	/**< Flow identifier (e.g., port). */
 	uint16_t flow_mac[3];	/**< Source MAC address for the flow direction. */
-	uint16_t flow_pppoe_session_id;
-			/**< PPPoE session ID for the flow direction. */
-	uint16_t flow_pppoe_remote_mac[3];
-			/**< PPPoE server MAC address for the flow direction. */
+	uint32_t flow_pppoe_if_exist;	/**< Flow direction: PPPoE interface existence flag. */
+	int32_t flow_pppoe_if_num;	/**< Flow direction: PPPoE interface number. */
 	uint16_t ingress_vlan_tag;	/**< Ingress VLAN tag. */
 	int32_t return_interface;	/**< Return interface number. */
 	uint32_t return_mtu;		/**< MTU for the return interface. */
 	uint32_t return_ip[4];		/**< Return IP address. */
 	uint32_t return_ident;		/**< Return identier (e.g., port). */
 	uint16_t return_mac[3];		/**< Source MAC address for the return direction. */
-	uint16_t return_pppoe_session_id;
-			/**< PPPoE session ID for the return direction. */
-	uint16_t return_pppoe_remote_mac[3];
-			/**< PPPoE server MAC address for the return direction. */
+	uint32_t return_pppoe_if_exist;	/**< Return direction: PPPoE interface existence flag. */
+	int32_t return_pppoe_if_num;	/**< Return direction: PPPoE interface number. */
 	uint16_t egress_vlan_tag;	/**< VLAN tag to be inserted for egress direction. */
 	uint8_t flags;			/**< Flags indicating the status of the flow. */
 	uint32_t qos_tag;		/**< QoS value of the flow. */
diff --git a/exports/nss_dynamic_interface.h b/exports/nss_dynamic_interface.h
index 8440456..07f91ff 100644
--- a/exports/nss_dynamic_interface.h
+++ b/exports/nss_dynamic_interface.h
@@ -42,20 +42,20 @@
 	NSS_DYNAMIC_INTERFACE_TYPE_WIFI,
 	NSS_DYNAMIC_INTERFACE_TYPE_VAP,
 	NSS_DYNAMIC_INTERFACE_TYPE_TUNIPIP6,
-	NSS_DYNAMIC_INTERFACE_TYPE_RESERVED_2,
+	NSS_DYNAMIC_INTERFACE_TYPE_PPPOE,
 	NSS_DYNAMIC_INTERFACE_TYPE_VIRTIF_DEPRECATED,
 	NSS_DYNAMIC_INTERFACE_TYPE_L2TPV2,
 	NSS_DYNAMIC_INTERFACE_TYPE_PPTP,
 	NSS_DYNAMIC_INTERFACE_TYPE_PORTID,
 	NSS_DYNAMIC_INTERFACE_TYPE_DTLS,
 	NSS_DYNAMIC_INTERFACE_TYPE_MAP_T,
-	NSS_DYNAMIC_INTERFACE_TYPE_RESERVED_3,
+	NSS_DYNAMIC_INTERFACE_TYPE_RESERVED_2,
 	NSS_DYNAMIC_INTERFACE_TYPE_BRIDGE,
 	NSS_DYNAMIC_INTERFACE_TYPE_VLAN,
 	NSS_DYNAMIC_INTERFACE_TYPE_GRE,
 	NSS_DYNAMIC_INTERFACE_TYPE_WIFILI,
+	NSS_DYNAMIC_INTERFACE_TYPE_RESERVED_3,
 	NSS_DYNAMIC_INTERFACE_TYPE_RESERVED_4,
-	NSS_DYNAMIC_INTERFACE_TYPE_RESERVED_5,
 	NSS_DYNAMIC_INTERFACE_TYPE_GRE_TUNNEL_INNER,
 	NSS_DYNAMIC_INTERFACE_TYPE_GRE_TUNNEL_OUTER,
 	NSS_DYNAMIC_INTERFACE_TYPE_DTLS_CMN_INNER,
diff --git a/exports/nss_ipv4.h b/exports/nss_ipv4.h
index 0d73129..14ff0b5 100644
--- a/exports/nss_ipv4.h
+++ b/exports/nss_ipv4.h
@@ -192,18 +192,17 @@
 
 /**
  * nss_ipv4_pppoe_rule
- *	v4_protocol_tcp_rule
  *	Information for PPPoE connection rules.
  */
 struct nss_ipv4_pppoe_rule {
-	uint16_t flow_pppoe_session_id;
-			/**< PPPoE session ID for the flow direction. */
-	uint16_t flow_pppoe_remote_mac[3];
-			/**< PPPoE Server MAC address for the flow direction. */
-	uint16_t return_pppoe_session_id;
-			/**< PPPoE session ID for the return direction. */
-	uint16_t return_pppoe_remote_mac[3];
-			/**< PPPoE Server MAC address for the return direction. */
+	uint32_t flow_if_exist;
+			/**< PPPoE interface existence flag for the flow direction. */
+	int32_t flow_if_num;
+			/**< PPPoE interface number for the flow direction. */
+	uint32_t return_if_exist;
+			/**< PPPoE interface existence flag for the return direction. */
+	int32_t return_if_num;
+			/**< PPPoE interface number for the return direction. */
 };
 
 /**
@@ -319,7 +318,6 @@
 	NSS_IPV4_CR_INVALID_PNODE_ERROR,
 	NSS_IPV4_CR_MISSING_CONNECTION_RULE_ERROR,
 	NSS_IPV4_CR_BUFFER_ALLOC_FAIL_ERROR,
-	NSS_IPV4_CR_PPPOE_SESSION_CREATION_ERROR,
 	NSS_IPV4_DR_NO_CONNECTION_ENTRY_ERROR,
 	NSS_IPV4_CR_CONN_CFG_ALREADY_CONFIGURED_ERROR,
 	NSS_IPV4_CR_CONN_CFG_NOT_MULTIPLE_OF_QUANTA_ERROR,
@@ -393,8 +391,7 @@
 	uint32_t xlate_src_ident;	/**< Translated flow identifier (e.g., port). */
 	uint32_t egress_vlan_tag[MAX_VLAN_DEPTH];
 					/**< VLAN tag stack for the egress packets. */
-	uint16_t pppoe_session_id;	/**< PPPoE session ID. */
-	uint16_t pppoe_remote_mac[3];	/**< PPPoE server MAC address. */
+	int32_t pppoe_if_num;		/**< PPPoE interface number. */
 	uint32_t if_num;		/**< Interface number. */
 	uint32_t if_mtu;		/**< Interface MTU. */
 	uint16_t if_mac[3];		/**< Interface MAC address. */
@@ -414,8 +411,6 @@
 			/**< Source interface number (virtual or physical). */
 	uint32_t ingress_vlan_tag[MAX_VLAN_DEPTH];
 			/**< VLAN tag stack for the ingress packets. */
-	uint16_t ingress_pppoe_session_id;	/**< PPPoE session ID at ingress. */
-	uint16_t ingress_pppoe_remote_mac[3];	/**< PPPoE server MAC address. */
 	uint32_t qos_tag;			/**< QoS tag for the rule. */
 	uint16_t dest_mac[3];			/**< Destination multicast MAC address. */
 	uint16_t if_count;			/**< Number of destination interfaces. */
@@ -465,9 +460,6 @@
 		/**< Rule for evicting a cache entry. */
 #define NSS_IPV4_RULE_SYNC_REASON_DESTROY 3
 		/**< Rule for destroying a cache entry (requested by the host OS). */
-#define NSS_IPV4_RULE_SYNC_REASON_PPPOE_DESTROY 4
-		/**< Rule for destroying a cache entry that belongs to a specific PPPoE session.
- */
 
 /**
  * nss_ipv4_conn_sync
@@ -497,14 +489,6 @@
 			/**< Tx packet count for the flow interface. */
 	uint32_t flow_tx_byte_count;
 			/**< Tx byte count for the flow interface. */
-	uint16_t flow_pppoe_session_id;
-			/**< PPPoE session ID for the flow interface. */
-
-	/**
-	 * PPPoE remote server MAC address, if there is any, for the flow interface.
-	 */
-	uint16_t flow_pppoe_remote_mac[3];
-
 	uint32_t return_ip;		/**< Return IP address. */
 	uint32_t return_ip_xlate;	/**< Translated return IP address. */
 	uint32_t return_ident;		/**< Return identier (e.g., port). */
@@ -527,14 +511,6 @@
 			/**< Tx packet count for the return interface. */
 	uint32_t return_tx_byte_count;
 			/**< Tx byte count for the return interface. */
-	uint16_t return_pppoe_session_id;
-			/**< PPPoE session ID for the return interface. */
-
-	/**
-	 * PPPoE remote server MAC address (if any) for the return interface.
-	 */
-	uint16_t return_pppoe_remote_mac[3];
-
 	uint32_t inc_ticks;	/**< Number of ticks since the last synchronization. */
 	uint32_t reason;	/**< Reason for the synchronization. */
 
diff --git a/exports/nss_ipv6.h b/exports/nss_ipv6.h
index f949168..772e549 100644
--- a/exports/nss_ipv6.h
+++ b/exports/nss_ipv6.h
@@ -244,14 +244,14 @@
  *	Information for PPPoE connection rules.
  */
 struct nss_ipv6_pppoe_rule {
-	uint16_t flow_pppoe_session_id;
-			/**< PPPoE session ID for the flow direction. */
-	uint16_t flow_pppoe_remote_mac[3];
-			/**< PPPoE Server MAC address for the flow direction. */
-	uint16_t return_pppoe_session_id;
-			/**< PPPoE session ID for the return direction. */
-	uint16_t return_pppoe_remote_mac[3];
-			/**< PPPoE Server MAC address for the return direction. */
+	uint32_t flow_if_exist;
+			/**< PPPoE interface existence flag for the flow direction. */
+	int32_t flow_if_num;
+			/**< PPPoE interface number for the flow direction. */
+	uint32_t return_if_exist;
+			/**< PPPoE interface existence flag for the return direction. */
+	int32_t return_if_num;
+			/**< PPPoE interface number for the return direction. */
 };
 
 /**
@@ -361,8 +361,6 @@
 	NSS_IPV6_CR_INVALID_PNODE_ERROR,		/**< Invalid interface number. */
 	NSS_IPV6_CR_MISSING_CONNECTION_RULE_ERROR,	/**< Missing connection rule. */
 	NSS_IPV6_CR_BUFFER_ALLOC_FAIL_ERROR,		/**< Buffer allocation failed. */
-	NSS_IPV6_CR_PPPOE_SESSION_CREATION_ERROR,
-		/**< Unable to create a PPPoE session. */
 	NSS_IPV6_DR_NO_CONNECTION_ENTRY_ERROR,
 		/**< No connection was found to delete. */
 	NSS_IPV6_CR_CONN_CFG_ALREADY_CONFIGURED_ERROR,
@@ -460,8 +458,7 @@
 
 	uint32_t egress_vlan_tag[MAX_VLAN_DEPTH];
 					/**< VLAN tag stack for the egress packets. */
-	uint16_t pppoe_session_id;	/**< PPPoE session ID. */
-	uint16_t pppoe_remote_mac[3];	/**< PPPoE server MAC address. */
+	int32_t pppoe_if_num;		/**< PPPoE interface number. */
 	uint32_t if_num;		/**< Interface number. */
 	uint32_t if_mtu;		/**< MTU of the interface. */
 	uint16_t if_mac[3];		/**< Interface MAC address. */
@@ -481,8 +478,6 @@
 			/**< Source interface number (virtual or physical). */
 	uint32_t ingress_vlan_tag[MAX_VLAN_DEPTH];
 			/**< VLAN tag stack for the ingress packets. */
-	uint16_t ingress_pppoe_session_id;	/**< PPPoE session ID at ingress. */
-	uint16_t ingress_pppoe_remote_mac[3];	/**< PPPoE server MAC address. */
 	uint32_t qos_tag;		/**< QoS tag for the flow. */
 	uint16_t dest_mac[3];		/**< Destination multicast MAC address. */
 	uint16_t if_count;		/**< Number of destination interfaces. */
@@ -537,11 +532,6 @@
 		/**< Rule for destroying a cache entry (requested by the host OS). */
 
 /**
- * Rule for destroying a cache entry that belongs to a specific PPPoE session.
- */
-#define NSS_IPV6_RULE_SYNC_REASON_PPPOE_DESTROY 4
-
-/**
  * nss_ipv6_conn_sync
  *	IPv6 connection synchronization message.
  */
@@ -563,13 +553,6 @@
 	uint32_t flow_rx_byte_count;	/**< Rx byte count for the flow interface. */
 	uint32_t flow_tx_packet_count;	/**< Tx packet count for the flow interface. */
 	uint32_t flow_tx_byte_count;	/**< Tx byte count for the flow interface. */
-	uint16_t flow_pppoe_session_id;	/**< PPPoE session ID for the flow interface. */
-
-	/**
-	 * PPPoE remote server MAC address (if any) for the flow interface.
-	 */
-	uint16_t flow_pppoe_remote_mac[3];
-
 	uint32_t return_ip[4];		/**< Return IP address. */
 	uint32_t return_ident;		/**< Return identier (e.g., port). */
 	uint32_t return_max_window;
@@ -590,10 +573,6 @@
 			/**< Tx packet count for the return interface. */
 	uint32_t return_tx_byte_count;
 			/**< Tx byte count for the return interface. */
-	uint16_t return_pppoe_session_id;
-			/**< PPPoE session ID for the return interface. */
-	uint16_t return_pppoe_remote_mac[3];
-			/**< PPPoE remote server MAC address (if any) for the return interface. */
 	uint32_t inc_ticks;	/**< Number of ticks since the last synchronization. */
 	uint32_t reason;	/**< Reason for the synchronization. */
 	uint8_t flags;		/**< Bit flags associated with the rule. */
@@ -731,7 +710,7 @@
 		struct nss_ipv6_inquiry_msg inquiry;
 				/**< Inquiry if a connection has been created. */
 		struct nss_ipv6_dscp2pri_cfg_msg dscp2pri_cfg;
-				/**< Configure dscp2pri mapping. */
+				/**< Configure DSCP-to-priority mapping. */
 		struct nss_ipv6_rps_hash_bitmap_cfg_msg rps_hash_bitmap;
 				/**< Configure rps_hash_bitmap. */
 	} msg;			/**< Message payload. */
diff --git a/exports/nss_pppoe.h b/exports/nss_pppoe.h
index d57cb85..644d53b 100644
--- a/exports/nss_pppoe.h
+++ b/exports/nss_pppoe.h
@@ -1,6 +1,6 @@
 /*
  **************************************************************************
- * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2018, 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.
@@ -28,19 +28,19 @@
  */
 
 /**
+ * Maximum number of supported PPPoE sessions.
+ */
+#define NSS_MAX_PPPOE_DYNAMIC_INTERFACES 8
+
+/**
  * nss_pppoe_metadata_types
  *	Message types for PPPoE requests and responses.
- *
- * NSS_PPPOE_RX_DEPRECATED0 and NSS_PPPOE_RX_DEPRECATED1 are deprecated types.
- * They are kept for backward compatibility.
  */
 enum nss_pppoe_metadata_types {
-	NSS_PPPOE_RX_DEPRECATED0,
-	NSS_PPPOE_RX_DEPRECATED1,
-	NSS_PPPOE_RX_CONN_STATS_SYNC,
-	NSS_PPPOE_RX_NODE_STATS_SYNC,
-	NSS_PPPOE_RX_SESSION_RESET,
-	NSS_PPPOE_MAX,
+	NSS_PPPOE_MSG_SESSION_CREATE,
+	NSS_PPPOE_MSG_SESSION_DESTROY,
+	NSS_PPPOE_MSG_SYNC_STATS,
+	NSS_PPPOE_MSG_MAX
 };
 
 /**
@@ -50,52 +50,40 @@
 enum nss_pppoe_exception_events {
 	NSS_PPPOE_EXCEPTION_EVENT_WRONG_VERSION_OR_TYPE,
 	NSS_PPPOE_EXCEPTION_EVENT_WRONG_CODE,
-	NSS_PPPOE_EXCEPTION_EVENT_HEADER_INCOMPLETE,
 	NSS_PPPOE_EXCEPTION_EVENT_UNSUPPORTED_PPP_PROTOCOL,
-	NSS_PPPOE_EXCEPTION_EVENT_DEPRECATED,
-	NSS_PPPOE_EXCEPTION_EVENT_MAX,
+	NSS_PPPOE_EXCEPTION_EVENT_MAX
 };
 
 /**
- * nss_pppoe_node_stats_sync_msg
+ * nss_pppoe_sync_stats_msg
  *	PPPoE node synchronization statistics.
  */
-struct nss_pppoe_node_stats_sync_msg {
-	struct nss_cmn_node_stats node_stats;	/**< Common node statistics. */
-	uint32_t pppoe_session_create_requests;
-			/**< 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 misses. */
-};
-
-/**
- * nss_pppoe_session_reset_msg
- *	Reset message information for a PPPoE session.
- */
-struct nss_pppoe_session_reset_msg {
-	uint32_t interface;	/**< NSS interface number. */
-	uint32_t session_index;	/**< Index of the session in the NSS PPPoE session array. */
-};
-
-/**
- * nss_pppoe_conn_stats_sync_msg
- *	Synchronized statistics message for a PPPoE exception.
- */
-struct nss_pppoe_conn_stats_sync_msg {
-	uint16_t pppoe_session_id;
-			/**< PPPoE session ID on which statistics are based. */
-	uint8_t pppoe_remote_mac[ETH_ALEN];
-			/**< PPPoE server MAC address. */
-	uint32_t exception_events_pppoe[NSS_PPPOE_EXCEPTION_EVENT_MAX];
+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. */
-	uint32_t index;
-			/**< Per-interface array index. */
-	uint32_t interface_num;
-			/**< Interface number on which this session is created. */
+};
+
+/**
+ * nss_pppoe_destroy_msg
+ *	PPPoE session destroy message.
+ */
+struct nss_pppoe_destroy_msg {
+	uint16_t session_id;		/**< PPPoE session identification number. */
+	uint8_t server_mac[ETH_ALEN];	/**< PPPoE server MAC address. */
+	uint8_t local_mac[ETH_ALEN];	/**< Local physical interface MAC address. */
+};
+
+/**
+ * nss_pppoe_create_msg
+ *	PPPoE session create message.
+ */
+struct nss_pppoe_create_msg {
+	int32_t phy_if_num;		/**< Physical interface NSS interface number. */
+	uint32_t mtu;			/**< PPPoE interface MTU value. */
+	uint8_t server_mac[ETH_ALEN];	/**< PPPoE server MAC address. */
+	uint8_t local_mac[ETH_ALEN];	/**< Local physical interface MAC address. */
+	uint16_t session_id;		/**< PPPoE session identification number. */
 };
 
 /**
@@ -109,18 +97,29 @@
 	 * Payload of a PPPoE message.
 	 */
 	union {
-		struct nss_pppoe_conn_stats_sync_msg pppoe_conn_stats_sync;
-				/**< Synchronized statistics for an exception. */
-		struct nss_pppoe_node_stats_sync_msg pppoe_node_stats_sync;
-				/**< Synchronized statistics for a node. */
-		struct nss_pppoe_session_reset_msg pppoe_session_reset;
-				/**< Reset a session. */
-	} msg;			/**< Message payload. */
+		struct nss_pppoe_create_msg create;
+					/**< Session create message. */
+		struct nss_pppoe_destroy_msg destroy;
+					/**< Session destroy message. */
+		struct nss_pppoe_sync_stats_msg sync_stats;
+					/**< Session statistics message. */
+	} msg;				/**< Message payload. */
 };
 
 /**
- * nss_pppoe_tx
- *	Sends a PPPoE message to the NSS firmware.
+ * Callback function for receiving PPPoE messages.
+ *
+ * @datatypes
+ * nss_pppoe_msg
+ *
+ * @param[in] app_data  Pointer to the application context of the message.
+ * @param[in] msg       Pointer to the message data.
+ */
+typedef void (*nss_pppoe_msg_callback_t)(void *app_data, struct nss_pppoe_msg *msg);
+
+/**
+ * nss_pppoe_tx_msg_sync
+ *	Sends a PPPoE message synchronously to NSS.
  *
  * @datatypes
  * nss_ctx_instance \n
@@ -132,28 +131,86 @@
  * @return
  * Status of the Tx operation.
  */
-extern nss_tx_status_t nss_pppoe_tx(struct nss_ctx_instance *nss_ctx, struct nss_pppoe_msg *msg);
+extern nss_tx_status_t nss_pppoe_tx_msg_sync(struct nss_ctx_instance *nss_ctx,
+						struct nss_pppoe_msg *msg);
+
+/**
+ * nss_register_pppoe_session_if
+ *	Registers the PPPoE session interface with the NSS for sending and
+ *	receiving messages.
+ *
+ * @datatypes
+ * nss_pppoe_msg_callback_t \n
+ * net_device
+ *
+ * @param[in] if_num                 NSS interface number.
+ * @param[in] notification_callback  Callback for the message.
+ * @param[in] netdev                 Pointer to the associated network device.
+ * @param[in] features               Socket buffer types supported by this interface.
+ * @param[in] app_ctx                Pointer to the application context of the message.
+ *
+ * @return
+ * Pointer to the NSS core context.
+ */
+extern struct nss_ctx_instance *nss_register_pppoe_session_if(uint32_t if_num,
+						       nss_pppoe_msg_callback_t notification_callback,
+						       struct net_device *netdev, uint32_t features, void *app_ctx);
+
+/**
+ * nss_unregister_pppoe_session_if
+ *	Deregisters the PPPoE session interface from the NSS.
+ *
+ * @param[in] if_num  NSS interface number.
+. *
+ * @return
+ * None.
+ *
+ * @dependencies
+ * The tunnel interface must have been previously registered.
+ */
+extern void nss_unregister_pppoe_session_if(uint32_t if_num);
+
+/**
+ * nss_pppoe_get_context
+ *	Gets the PPPoE context used in PPPoE transmit message.
+ *
+ * @return
+ * Pointer to the NSS core context.
+ */
+extern struct nss_ctx_instance *nss_pppoe_get_context(void);
+
+/**
+ * nss_pppoe_debug_stats_get
+ *	Gets NSS session debug statistics.
+ *
+ * @param[out] stats_mem  Pointer to the memory address, which must be large
+ *                         enough to hold all the statistics.
+ *
+ * @return
+ * None.
+ */
+extern void nss_pppoe_debug_stats_get(void *stats_mem);
 
 /**
  * nss_pppoe_msg_init
- *	Initializes a PPPoE-specific message.
+ *	Initializes a PPPoE message.
  *
  * @datatypes
  * nss_pppoe_msg
  *
- * @param[in,out] npm       Pointer to the NSS Profiler message.
- * @param[in]     if_num    NSS interface number.
+ * @param[in,out] ncm       Pointer to the message.
+ * @param[in]     if_num    Interface number
  * @param[in]     type      Type of message.
- * @param[in]     len       Size of the message.
- * @param[in]     cb        Pointer to the callback message.
+ * @param[in]     len       Size of the payload.
+ * @param[in]     cb        Pointer to the message callback.
  * @param[in]     app_data  Pointer to the application context of the message.
  *
  * @return
  * None.
  */
-extern void nss_pppoe_msg_init(struct nss_pppoe_msg *npm, uint16_t if_num, uint32_t type, uint32_t len,
+extern void nss_pppoe_msg_init(struct nss_pppoe_msg *ncm,
+				uint16_t if_num, uint32_t type, uint32_t len,
 				void *cb, void *app_data);
-
 /**
  * @}
  */
diff --git a/nss_core.h b/nss_core.h
index 113cd13..82897c9 100644
--- a/nss_core.h
+++ b/nss_core.h
@@ -217,13 +217,9 @@
 #define NSS_TX_UNBLOCKED_PROCESSING_WEIGHT 1
 
 /*
- * Statistics struct
- *
  * INFO: These numbers are based on previous generation chip
  *	These may change in future
  */
-#define NSS_PPPOE_NUM_SESSION_PER_INTERFACE 4
-					/* Number of maximum simultaneous PPPoE sessions per physical interface */
 
 /*
  * NSS Frequency Defines and Values
@@ -559,6 +555,7 @@
 	uint8_t wifi_handler_id;
 	uint8_t ppe_handler_id;
 	uint8_t pptp_handler_id;
+	uint8_t pppoe_handler_id;
 	uint8_t l2tpv2_handler_id;
 	uint8_t dtls_handler_id;
 	uint8_t gre_handler_id;
@@ -618,6 +615,8 @@
 					/* ipip6 tunnel interface event callback function */
 	nss_pptp_msg_callback_t pptp_msg_callback;
 					/* PPTP tunnel interface event callback function */
+	nss_pppoe_msg_callback_t pppoe_msg_callback;
+					/* PPPoE interface event callback function */
 	struct nss_shaper_bounce_registrant bounce_interface_registrants[NSS_MAX_NET_INTERFACES];
 					/* Registrants for interface shaper bounce operations */
 	struct nss_shaper_bounce_registrant bounce_bridge_registrants[NSS_MAX_NET_INTERFACES];
diff --git a/nss_hal/nss_hal.c b/nss_hal/nss_hal.c
index 55fa32f..e51bfbd 100644
--- a/nss_hal/nss_hal.c
+++ b/nss_hal/nss_hal.c
@@ -357,9 +357,6 @@
 	if (npd->ipv4_enabled == NSS_FEATURE_ENABLED) {
 		nss_top->ipv4_handler_id = nss_dev->id;
 		nss_ipv4_register_handler();
-		if (npd->pppoe_enabled == NSS_FEATURE_ENABLED) {
-			nss_pppoe_register_handler(nss_ctx);
-		}
 
 		nss_top->edma_handler_id = nss_dev->id;
 		nss_edma_register_handler();
@@ -421,6 +418,11 @@
 		nss_top->tun6rd_handler_id = nss_dev->id;
 	}
 
+	if (npd->pppoe_enabled == NSS_FEATURE_ENABLED) {
+		nss_top->pppoe_handler_id = nss_dev->id;
+		nss_pppoe_register_handler();
+	}
+
 	if (npd->pptp_enabled == NSS_FEATURE_ENABLED) {
 		nss_top->pptp_handler_id = nss_dev->id;
 		nss_pptp_register_handler();
diff --git a/nss_ipv4_log.c b/nss_ipv4_log.c
index 468e65e..0eed33a 100644
--- a/nss_ipv4_log.c
+++ b/nss_ipv4_log.c
@@ -46,7 +46,6 @@
 	"Invalid interface number",
 	"Missing connection rule",
 	"Buffer allocation failure",
-	"Unable to create PPPoE session",
 	"No connection found to delete",
 	"Conn cfg already done once",
 	"Conn cfg input is not multiple of quanta",
@@ -82,10 +81,10 @@
 		"egress_outer_vlan_tag: %u\n"
 		"rule_flags: %x\n"
 		"valid_flags: %x\n"
-		"return_pppoe_session_id: %u\n"
-		"return_pppoe_remote_mac: %pM\n"
-		"flow_pppoe_session_id: %u\n"
-		"flow_pppoe_remote_mac: %pM\n"
+		"return_pppoe_if_exist: %u\n"
+		"return_pppoe_if_num: %u\n"
+		"flow_pppoe_if_exist: %u\n"
+		"flow_pppoe_if_num: %u\n"
 		"flow_qos_tag: %x (%u)\n"
 		"return_qos_tag: %x (%u)\n"
 		"flow_dscp: %x\n"
@@ -108,10 +107,10 @@
 		nircm->vlan_secondary_rule.egress_vlan_tag,
 		nircm->rule_flags,
 		nircm->valid_flags,
-		nircm->pppoe_rule.return_pppoe_session_id,
-		nircm->pppoe_rule.return_pppoe_remote_mac,
-		nircm->pppoe_rule.flow_pppoe_session_id,
-		nircm->pppoe_rule.flow_pppoe_remote_mac,
+		nircm->pppoe_rule.return_if_exist,
+		nircm->pppoe_rule.return_if_num,
+		nircm->pppoe_rule.flow_if_exist,
+		nircm->pppoe_rule.flow_if_num,
 		nircm->qos_rule.flow_qos_tag, nircm->qos_rule.flow_qos_tag,
 		nircm->qos_rule.return_qos_tag, nircm->qos_rule.return_qos_tag,
 		nircm->dscp_rule.flow_dscp,
diff --git a/nss_ipv6_log.c b/nss_ipv6_log.c
index 2681fff..c1cc076 100644
--- a/nss_ipv6_log.c
+++ b/nss_ipv6_log.c
@@ -57,7 +57,6 @@
 	"Invalid interface number",
 	"Missing connection rule",
 	"Buffer allocation failure",
-	"Unable to create PPPoE session",
 	"No connection found to delete",
 	"Conn cfg already done once",
 	"Conn cfg input is not multiple of quanta",
@@ -97,10 +96,10 @@
 		"egress_outer_vlan_tag: %u\n"
 		"rule_flags: %x\n"
 		"valid_flags: %x\n"
-		"return_pppoe_session_id: %u\n"
-		"return_pppoe_remote_mac: %pM\n"
-		"flow_pppoe_session_id: %u\n"
-		"flow_pppoe_remote_mac: %pM\n"
+		"return_pppoe_if_exist: %u\n"
+		"return_pppoe_if_num: %u\n"
+		"flow_pppoe_if_exist: %u\n"
+		"flow_pppoe_if_num: %u\n"
 		"flow_qos_tag: %x (%u)\n"
 		"return_qos_tag: %x (%u)\n"
 		"flow_dscp: %x\n"
@@ -121,10 +120,10 @@
 		nircm->vlan_secondary_rule.egress_vlan_tag,
 		nircm->rule_flags,
 		nircm->valid_flags,
-		nircm->pppoe_rule.return_pppoe_session_id,
-		nircm->pppoe_rule.return_pppoe_remote_mac,
-		nircm->pppoe_rule.flow_pppoe_session_id,
-		nircm->pppoe_rule.flow_pppoe_remote_mac,
+		nircm->pppoe_rule.return_if_exist,
+		nircm->pppoe_rule.return_if_num,
+		nircm->pppoe_rule.flow_if_exist,
+		nircm->pppoe_rule.flow_if_num,
 		nircm->qos_rule.flow_qos_tag, nircm->qos_rule.flow_qos_tag,
 		nircm->qos_rule.return_qos_tag, nircm->qos_rule.return_qos_tag,
 		nircm->dscp_rule.flow_dscp,
diff --git a/nss_pppoe.c b/nss_pppoe.c
index c89d016..4f142e9 100644
--- a/nss_pppoe.c
+++ b/nss_pppoe.c
@@ -20,59 +20,134 @@
  */
 
 #include "nss_tx_rx_common.h"
-#include <linux/if_pppox.h>
 #include "nss_pppoe_stats.h"
 
+#define NSS_PPPOE_TX_TIMEOUT 3000 /* 3 Seconds */
+
 /*
- * nss_pppoe_tx()
- *	Transmit an PPPoe message to the FW.
+ * Data structures to store pppoe nss debug stats
  */
-nss_tx_status_t nss_pppoe_tx(struct nss_ctx_instance *nss_ctx, struct nss_pppoe_msg *nim)
+static DEFINE_SPINLOCK(nss_pppoe_lock);
+static struct nss_pppoe_stats_session_debug nss_pppoe_debug_stats[NSS_MAX_PPPOE_DYNAMIC_INTERFACES];
+
+/*
+ * Private data structure
+ */
+static struct nss_pppoe_pvt {
+	struct semaphore sem;
+	struct completion complete;
+	int response;
+	void *cb;
+	void *app_data;
+} pppoe_pvt;
+
+/*
+ * 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)
 {
-	struct nss_cmn_msg *ncm = &nim->cm;
+	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)
+{
+	return (struct nss_ctx_instance *)&nss_top_main.nss[nss_top_main.pppoe_handler_id];
+}
+EXPORT_SYMBOL(nss_pppoe_get_context);
+
+/*
+ * nss_pppoe_tx_msg()
+ *	Transmit a PPPoE message to NSS firmware
+ */
+static nss_tx_status_t nss_pppoe_tx_msg(struct nss_ctx_instance *nss_ctx, struct nss_pppoe_msg *msg)
+{
+	struct nss_cmn_msg *ncm = &msg->cm;
 
 	/*
 	 * Sanity check the message
 	 */
-	if (ncm->interface != NSS_PPPOE_RX_INTERFACE) {
-		nss_warning("%p: tx request for another interface: %d", nss_ctx, ncm->interface);
+	if (!nss_is_dynamic_interface(ncm->interface)) {
+		nss_warning("%p: tx request for non dynamic interface: %d\n", nss_ctx, ncm->interface);
 		return NSS_TX_FAILURE;
 	}
 
-	if (ncm->type > NSS_PPPOE_MAX) {
-		nss_warning("%p: message type out of range: %d", nss_ctx, ncm->type);
+	if (nss_dynamic_interface_get_type(nss_pppoe_get_context(), ncm->interface) != NSS_DYNAMIC_INTERFACE_TYPE_PPPOE) {
+		nss_warning("%p: tx request for not PPPoE interface: %d\n", nss_ctx, ncm->interface);
 		return NSS_TX_FAILURE;
 	}
 
-	return nss_core_send_cmd(nss_ctx, nim, sizeof(*nim), NSS_NBUF_PAYLOAD_SIZE);
+	if (ncm->type >= NSS_PPPOE_MSG_MAX) {
+		nss_warning("%p: message type out of range: %d\n", nss_ctx, ncm->type);
+		return NSS_TX_FAILURE;
+	}
+
+	return nss_core_send_cmd(nss_ctx, msg, sizeof(*msg), NSS_NBUF_PAYLOAD_SIZE);
 }
 
 /*
- **********************************
- Rx APIs
- **********************************
+ * nss_pppoe_sync_msg_callback()
+ *	Callback to handle the completion of NSS->HLOS messages.
  */
+static void nss_pppoe_sync_msg_callback(void *app_data, struct nss_pppoe_msg *npm)
+{
+	nss_pppoe_msg_callback_t callback = (nss_pppoe_msg_callback_t)pppoe_pvt.cb;
+	void *data = pppoe_pvt.app_data;
+
+	pppoe_pvt.cb = NULL;
+	pppoe_pvt.app_data = NULL;
+
+	pppoe_pvt.response = NSS_TX_SUCCESS;
+	if (npm->cm.response != NSS_CMN_RESPONSE_ACK) {
+		nss_warning("pppoe Error response %d\n", npm->cm.response);
+		pppoe_pvt.response = NSS_TX_FAILURE;
+	}
+
+	if (callback) {
+		callback(data, npm);
+	}
+
+	complete(&pppoe_pvt.complete);
+}
 
 /*
- * nss_pppoe_rx_msg_handler()
+ * nss_pppoe_handler()
  *	Handle NSS -> HLOS messages for PPPoE
  */
-static void nss_pppoe_rx_msg_handler(struct nss_ctx_instance *nss_ctx, struct nss_cmn_msg *ncm, __attribute__((unused))void *app_data)
+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;
+	void *ctx;
+	nss_pppoe_msg_callback_t cb;
 
-	BUG_ON(ncm->interface != NSS_PPPOE_RX_INTERFACE);
+	BUG_ON(!(nss_is_dynamic_interface(ncm->interface) || ncm->interface == NSS_PPPOE_INTERFACE));
 
 	/*
 	 * Sanity check the message type
 	 */
-	if (ncm->type > NSS_PPPOE_MAX) {
-		nss_warning("%p: message type out of range: %d", nss_ctx, ncm->type);
+	if (ncm->type >= NSS_PPPOE_MSG_MAX) {
+		nss_warning("%p: message type out of range: %d\n", nss_ctx, ncm->type);
 		return;
 	}
 
 	if (nss_cmn_get_msg_len(ncm) > sizeof(struct nss_pppoe_msg)) {
-		nss_warning("%p: message length is invalid: %d", nss_ctx, nss_cmn_get_msg_len(ncm));
+		nss_warning("%p: message length is invalid: %d\n", nss_ctx, nss_cmn_get_msg_len(ncm));
 		return;
 	}
 
@@ -85,37 +160,202 @@
 	 * Handling PPPoE messages coming from NSS fw.
 	 */
 	switch (nim->cm.type) {
-	case NSS_PPPOE_RX_NODE_STATS_SYNC:
-		nss_pppoe_stats_node_sync(nss_ctx, &nim->msg.pppoe_node_stats_sync);
-		break;
-	case NSS_PPPOE_RX_CONN_STATS_SYNC:
-		nss_pppoe_stats_exception_sync(nss_ctx, &nim->msg.pppoe_conn_stats_sync);
-		break;
-	case NSS_PPPOE_RX_SESSION_RESET:
-		nss_pppoe_stats_session_reset(nss_ctx, &nim->msg.pppoe_session_reset);
+	case NSS_PPPOE_MSG_SYNC_STATS:
+		nss_pppoe_debug_stats_sync(nss_ctx, &nim->msg.sync_stats, ncm->interface);
 		break;
 	default:
-		nss_warning("%p: Received response %d for type %d, interface %d",
+		nss_warning("%p: Received response %d for type %d, interface %d\n",
 				nss_ctx, ncm->response, ncm->type, ncm->interface);
 	}
+
+	/*
+	 * Update the callback and app_data for NOTIFY messages, pppoe sends all notify messages
+	 * to the same callback/app_data.
+	 */
+	if (ncm->response == NSS_CMN_RESPONSE_NOTIFY) {
+		ncm->cb = (nss_ptr_t)nss_ctx->nss_top->pppoe_msg_callback;
+		ncm->app_data = (nss_ptr_t)nss_ctx->subsys_dp_register[ncm->interface].app_data;
+	}
+
+	/*
+	 * Log failures
+	 */
+	nss_core_log_msg_failures(nss_ctx, ncm);
+
+	/*
+	 * Do we have a call back
+	 */
+	if (!ncm->cb) {
+		return;
+	}
+
+	/*
+	 * callback
+	 */
+	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);
+}
+
+/*
+ * nss_pppoe_tx_msg_sync()
+ */
+nss_tx_status_t nss_pppoe_tx_msg_sync(struct nss_ctx_instance *nss_ctx,
+						struct nss_pppoe_msg *msg)
+{
+	nss_tx_status_t status;
+	int ret = 0;
+
+	down(&pppoe_pvt.sem);
+	pppoe_pvt.cb = (void *)msg->cm.cb;
+	pppoe_pvt.app_data = (void *)msg->cm.app_data;
+
+	msg->cm.cb = (nss_ptr_t)nss_pppoe_sync_msg_callback;
+	msg->cm.app_data = (nss_ptr_t)NULL;
+
+	status = nss_pppoe_tx_msg(nss_ctx, msg);
+	if (status != NSS_TX_SUCCESS) {
+		nss_warning("%p: nss_pppoe_tx_msg failed\n", nss_ctx);
+		up(&pppoe_pvt.sem);
+		return status;
+	}
+
+	ret = wait_for_completion_timeout(&pppoe_pvt.complete, msecs_to_jiffies(NSS_PPPOE_TX_TIMEOUT));
+	if (!ret) {
+		nss_warning("%p: PPPoE msg tx failed due to timeout\n", nss_ctx);
+		pppoe_pvt.response = NSS_TX_FAILURE;
+	}
+
+	status = pppoe_pvt.response;
+	up(&pppoe_pvt.sem);
+	return status;
+}
+EXPORT_SYMBOL(nss_pppoe_tx_msg_sync);
+
+/*
+ * nss_register_pppoe_session_if()
+ */
+struct nss_ctx_instance *nss_register_pppoe_session_if(uint32_t if_num,
+						       nss_pppoe_msg_callback_t notification_callback,
+						       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) {
+		return NULL;
+	}
+
+	nss_core_register_subsys_dp(nss_ctx, if_num, NULL, NULL, app_ctx, netdev, features);
+
+	nss_top_main.pppoe_msg_callback = notification_callback;
+
+	nss_core_register_handler(nss_ctx, if_num, nss_pppoe_handler, NULL);
+
+	return nss_ctx;
+}
+EXPORT_SYMBOL(nss_register_pppoe_session_if);
+
+/*
+ * nss_unregister_pppoe_session_if()
+ */
+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_core_unregister_subsys_dp(nss_ctx, if_num);
+
+	nss_top_main.pppoe_msg_callback = NULL;
+
+	nss_core_unregister_handler(nss_ctx, if_num);
+
+}
+EXPORT_SYMBOL(nss_unregister_pppoe_session_if);
+
+/*
  * nss_pppoe_register_handler()
  */
-void nss_pppoe_register_handler(struct nss_ctx_instance *nss_ctx)
+void nss_pppoe_register_handler(void)
 {
-	nss_core_register_handler(nss_ctx, NSS_PPPOE_RX_INTERFACE, nss_pppoe_rx_msg_handler, NULL);
+	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);
 
 	nss_pppoe_stats_dentry_create();
 }
 
 /*
  * nss_pppoe_msg_init()
- *	Initialize pppoe message.
  */
 void nss_pppoe_msg_init(struct nss_pppoe_msg *npm, uint16_t if_num, uint32_t type, uint32_t len,
 			void *cb, void *app_data)
 {
 	nss_cmn_msg_init(&npm->cm, if_num, type, len, (void *)cb, app_data);
+
 }
+EXPORT_SYMBOL(nss_pppoe_msg_init);
diff --git a/nss_pppoe_stats.c b/nss_pppoe_stats.c
index e95582e..c5c95af 100644
--- a/nss_pppoe_stats.c
+++ b/nss_pppoe_stats.c
@@ -1,6 +1,6 @@
 /*
  **************************************************************************
- * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2018, 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,50 +18,36 @@
 #include "nss_core.h"
 #include "nss_pppoe_stats.h"
 
-uint64_t nss_pppoe_stats[NSS_PPPOE_STATS_MAX];
-uint64_t nss_pppoe_stats_exception[NSS_MAX_PHYSICAL_INTERFACES + 1][NSS_PPPOE_NUM_SESSION_PER_INTERFACE + 1][NSS_PPPOE_EXCEPTION_EVENT_MAX];
-
 /*
  * nss_pppoe_stats_str
  *	PPPoE stats strings
  */
-static int8_t *nss_pppoe_stats_str[NSS_PPPOE_STATS_MAX] = {
-	"create_requests",
-	"create_failures",
-	"destroy_requests",
-	"destroy_misses"
-};
-
-/*
- * nss_pppoe_stats_exception_str
- *	Interface stats strings for PPPoE exceptions
- */
-static int8_t *nss_pppoe_stats_exception_str[NSS_PPPOE_EXCEPTION_EVENT_MAX] = {
-	"PPPOE_WRONG_VERSION_OR_TYPE",
-	"PPPOE_WRONG_CODE",
-	"PPPOE_HEADER_INCOMPLETE",
-	"PPPOE_UNSUPPORTED_PPP_PROTOCOL",
-	"PPPOE_DEPRECATED"
+static int8_t *nss_pppoe_stats_debug_str[NSS_PPPOE_STATS_SESSION_MAX] = {
+	"RX_PACKETS",
+	"RX_BYTES",
+	"TX_PACKETS",
+	"TX_BYTES",
+	"WRONG_VERSION_OR_TYPE",
+	"WRONG_CODE",
+	"UNSUPPORTED_PPP_PROTOCOL",
 };
 
 /*
  * nss_pppoe_stats_read()
- *	Read PPPoE stats
+ *	Read pppoe statistics
  */
 static ssize_t nss_pppoe_stats_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
 {
-	uint64_t stats_shadow_pppoe_except[NSS_PPPOE_NUM_SESSION_PER_INTERFACE][NSS_PPPOE_EXCEPTION_EVENT_MAX];
-	int32_t i, j, k;
 
-	/*
-	 * max output lines = #stats + start tag line + end tag line + three blank lines
-	 */
-	uint32_t max_output_lines = (NSS_STATS_NODE_MAX + 2) + (NSS_PPPOE_STATS_MAX + 3) +
-					((NSS_MAX_PHYSICAL_INTERFACES * NSS_PPPOE_NUM_SESSION_PER_INTERFACE * (NSS_PPPOE_EXCEPTION_EVENT_MAX + 5)) + 3) + 5;
+	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;
 	size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
 	size_t size_wr = 0;
 	ssize_t bytes_read = 0;
-	uint64_t *stats_shadow;
+	struct 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);
 	if (unlikely(lbuf == NULL)) {
@@ -69,65 +55,44 @@
 		return 0;
 	}
 
-	stats_shadow = kzalloc(64 * 8, GFP_KERNEL);
-	if (unlikely(stats_shadow == NULL)) {
-		nss_warning("Could not allocate memory for local shadow buffer");
-		kfree(lbuf);
-		return 0;
-	}
-
-	size_wr = scnprintf(lbuf, size_al, "pppoe stats start:\n\n");
-
-	size_wr = nss_stats_fill_common_stats(NSS_PPPOE_RX_INTERFACE, lbuf, size_wr, size_al);
+	memset(&pppoe_session_stats, 0, sizeof(struct nss_pppoe_stats_session_debug) * NSS_MAX_PPPOE_DYNAMIC_INTERFACES);
 
 	/*
-	 * PPPoE node stats
+	 * Get all stats
 	 */
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\npppoe node stats:\n\n");
-	spin_lock_bh(&nss_top_main.stats_lock);
-	for (i = 0; (i < NSS_PPPOE_STATS_MAX); i++) {
-		stats_shadow[i] = nss_pppoe_stats[i];
-	}
-	spin_unlock_bh(&nss_top_main.stats_lock);
-
-	for (i = 0; (i < NSS_PPPOE_STATS_MAX); i++) {
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
-					"%s = %llu\n", nss_pppoe_stats_str[i], stats_shadow[i]);
-	}
+	nss_pppoe_debug_stats_get((void *)&pppoe_session_stats);
 
 	/*
-	 * Exception stats
+	 * Session stats
 	 */
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nException PPPoE:\n\n");
-
-	for (j = 1; j <= NSS_MAX_PHYSICAL_INTERFACES; j++) {
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nInterface %d:\n\n", j);
-
-		spin_lock_bh(&nss_top_main.stats_lock);
-		for (k = 1; k <= NSS_PPPOE_NUM_SESSION_PER_INTERFACE; k++) {
-			for (i = 0; (i < NSS_PPPOE_EXCEPTION_EVENT_MAX); i++) {
-				stats_shadow_pppoe_except[k - 1][i] = nss_pppoe_stats_exception[j][k][i];
-			}
-		}
-		spin_unlock_bh(&nss_top_main.stats_lock);
-
-		for (k = 1; k <= NSS_PPPOE_NUM_SESSION_PER_INTERFACE; k++) {
-			size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "%d. Session\n", k);
-			for (i = 0; (i < NSS_PPPOE_EXCEPTION_EVENT_MAX); i++) {
-				size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
-						"%s = %llu\n",
-						nss_pppoe_stats_exception_str[i],
-						stats_shadow_pppoe_except[k - 1][i]);
-			}
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\npppoe session stats start:\n\n");
+	for (id = 0; id < NSS_MAX_PPPOE_DYNAMIC_INTERFACES; id++) {
+		if (!pppoe_session_stats[id].valid) {
+			break;
 		}
 
+		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);
+		}
+
+		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]);
+		}
+		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\n");
 	}
 
-	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));
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\npppoe session stats end\n");
+	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, size_wr);
+
 	kfree(lbuf);
-	kfree(stats_shadow);
-
 	return bytes_read;
 }
 
@@ -145,78 +110,3 @@
 	nss_stats_create_dentry("pppoe", &nss_pppoe_stats_ops);
 }
 
-/*
- * nss_pppoe_stats_node_sync()
- *	Handle the syncing of PPPoE node statistics.
- */
-void nss_pppoe_stats_node_sync(struct nss_ctx_instance *nss_ctx, struct nss_pppoe_node_stats_sync_msg *npess)
-{
-	struct nss_top_instance *nss_top = nss_ctx->nss_top;
-	int j;
-
-	spin_lock_bh(&nss_top->stats_lock);
-
-	nss_top->stats_node[NSS_PPPOE_RX_INTERFACE][NSS_STATS_NODE_RX_PKTS] += npess->node_stats.rx_packets;
-	nss_top->stats_node[NSS_PPPOE_RX_INTERFACE][NSS_STATS_NODE_RX_BYTES] += npess->node_stats.rx_bytes;
-	nss_top->stats_node[NSS_PPPOE_RX_INTERFACE][NSS_STATS_NODE_TX_PKTS] += npess->node_stats.tx_packets;
-	nss_top->stats_node[NSS_PPPOE_RX_INTERFACE][NSS_STATS_NODE_TX_BYTES] += npess->node_stats.tx_bytes;
-
-	for (j = 0; j < NSS_MAX_NUM_PRI; j++) {
-		nss_top->stats_node[NSS_PPPOE_RX_INTERFACE][NSS_STATS_NODE_RX_QUEUE_0_DROPPED + j] += npess->node_stats.rx_dropped[j];
-	}
-
-	nss_pppoe_stats[NSS_PPPOE_STATS_SESSION_CREATE_REQUESTS] += npess->pppoe_session_create_requests;
-	nss_pppoe_stats[NSS_PPPOE_STATS_SESSION_CREATE_FAILURES] += npess->pppoe_session_create_failures;
-	nss_pppoe_stats[NSS_PPPOE_STATS_SESSION_DESTROY_REQUESTS] += npess->pppoe_session_destroy_requests;
-	nss_pppoe_stats[NSS_PPPOE_STATS_SESSION_DESTROY_REQUESTS] += npess->pppoe_session_destroy_requests;
-
-	spin_unlock_bh(&nss_top->stats_lock);
-}
-
-/*
- * nss_pppoe_stats_session_reset()
- * 	Reset PPPoE session when session is destroyed.
- */
-void nss_pppoe_stats_session_reset(struct nss_ctx_instance *nss_ctx, struct nss_pppoe_session_reset_msg *npsr)
-{
-	uint32_t i;
-	uint32_t interface = npsr->interface;
-	uint32_t session_index = npsr->session_index;
-
-	/*
-	 * Reset the PPPoE statistics for this specific session.
-	 */
-	spin_lock_bh(&nss_ctx->nss_top->stats_lock);
-	for (i = 0; i < NSS_PPPOE_EXCEPTION_EVENT_MAX; i++) {
-		nss_pppoe_stats_exception[interface][session_index][i] = 0;
-	}
-	spin_unlock_bh(&nss_ctx->nss_top->stats_lock);
-}
-
-/*
- * nss_pppoe_stats_exception_sync()
- *	Handle the syncing of PPPoE exception statistics.
- */
-void nss_pppoe_stats_exception_sync(struct nss_ctx_instance *nss_ctx, struct nss_pppoe_conn_stats_sync_msg *npess)
-{
-	struct nss_top_instance *nss_top = nss_ctx->nss_top;
-	uint32_t index = npess->index;
-	uint32_t interface_num = npess->interface_num;
-	uint32_t i;
-
-	spin_lock_bh(&nss_top->stats_lock);
-
-	if (interface_num >= NSS_MAX_PHYSICAL_INTERFACES) {
-		spin_unlock_bh(&nss_top->stats_lock);
-		nss_warning("%p: Incorrect interface number %d for PPPoE exception stats", nss_ctx, interface_num);
-		return;
-	}
-
-	/*
-	 * pppoe exception stats
-	 */
-	for (i = 0; i < NSS_PPPOE_EXCEPTION_EVENT_MAX; i++) {
-		nss_pppoe_stats_exception[interface_num][index][i] += npess->exception_events_pppoe[i];
-	}
-	spin_unlock_bh(&nss_top->stats_lock);
-}
diff --git a/nss_pppoe_stats.h b/nss_pppoe_stats.h
index dc33f7b..358e7a2 100644
--- a/nss_pppoe_stats.h
+++ b/nss_pppoe_stats.h
@@ -20,24 +20,31 @@
 /*
  * PPPoE statistics
  */
-enum nss_pppoe_stats_types {
-	NSS_PPPOE_STATS_SESSION_CREATE_REQUESTS = 0,
-					/* Number of PPPoE session create requests */
-	NSS_PPPOE_STATS_SESSION_CREATE_FAILURES,
-					/* Number of PPPoE session create failures */
-	NSS_PPPOE_STATS_SESSION_DESTROY_REQUESTS,
-					/* Number of PPPoE session destroy requests */
-	NSS_PPPOE_STATS_SESSION_DESTROY_MISSES,
-					/* Number of PPPoE session destroy requests that missed the cache */
-	NSS_PPPOE_STATS_MAX,
+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_node_sync(struct nss_ctx_instance *nss_ctx, struct nss_pppoe_node_stats_sync_msg *npess);
-extern void nss_pppoe_stats_session_reset(struct nss_ctx_instance *nss_ctx, struct nss_pppoe_session_reset_msg *npsr);
-extern void nss_pppoe_stats_exception_sync(struct nss_ctx_instance *nss_ctx, struct nss_pppoe_conn_stats_sync_msg *npess);
 extern void nss_pppoe_stats_dentry_create(void);
 
 #endif /* __NSS_PPPOE_STATS_H */
diff --git a/nss_tx_rx_common.h b/nss_tx_rx_common.h
index 1e62f1c..b559326 100644
--- a/nss_tx_rx_common.h
+++ b/nss_tx_rx_common.h
@@ -185,7 +185,7 @@
 extern void nss_ipv6_reasm_register_handler(void);
 extern void nss_n2h_register_handler(struct nss_ctx_instance *nss_ctx);
 extern void nss_tunipip6_register_handler(void);
-extern void nss_pppoe_register_handler(struct nss_ctx_instance *nss_ctx);
+extern void nss_pppoe_register_handler(void);
 extern void nss_freq_register_handler(void);
 extern void nss_eth_rx_register_handler(struct nss_ctx_instance *nss_ctx);
 extern void nss_edma_register_handler(void);