Merge "[qca-nss-drv]: Set skb queue mapping"
diff --git a/Makefile b/Makefile
index 53cc9ee..697fefb 100644
--- a/Makefile
+++ b/Makefile
@@ -10,6 +10,7 @@
 qca-nss-drv-objs := \
 			nss_bridge.o \
 			nss_c2c_tx.o \
+			nss_c2c_tx_log.o \
 			nss_c2c_tx_stats.o \
 			nss_c2c_rx.o \
 			nss_c2c_rx_stats.o \
@@ -54,6 +55,7 @@
 			nss_lso_rx_stats.o \
 			nss_map_t.o \
 			nss_map_t_stats.o \
+			nss_meminfo.o \
 			nss_n2h.o \
 			nss_n2h_stats.o \
 			nss_oam.o \
diff --git a/exports/arch/nss_fsm9010.h b/exports/arch/nss_fsm9010.h
index d7f57c6..7e47290 100644
--- a/exports/arch/nss_fsm9010.h
+++ b/exports/arch/nss_fsm9010.h
@@ -33,6 +33,9 @@
 #define NSS_H2N_RING_COUNT 4		/**< Number of H2N rings. */
 #define NSS_RING_SIZE	128		/**< Ring size. */
 
+#define NSS_IMEM_START 0xE4000000	/**< NSS IMEM start address. */
+#define NSS_IMEM_SIZE  0x10000		/**< NSS IMEM size. */
+
 /**
  * @}
  */
diff --git a/exports/arch/nss_ipq806x.h b/exports/arch/nss_ipq806x.h
index 4519ffb..216f950 100644
--- a/exports/arch/nss_ipq806x.h
+++ b/exports/arch/nss_ipq806x.h
@@ -33,6 +33,9 @@
 #define NSS_H2N_RING_COUNT 4		/**< Number of H2N rings. */
 #define NSS_RING_SIZE	128		/**< Ring size. */
 
+#define NSS_IMEM_START	0x39000000	/**< NSS IMEM start address. */
+#define NSS_IMEM_SIZE	0x10000		/**< NSS IMEM size per core. */
+
 /**
  * @}
  */
diff --git a/exports/arch/nss_ipq807x.h b/exports/arch/nss_ipq807x.h
index 88be9ee..c8fc26d 100644
--- a/exports/arch/nss_ipq807x.h
+++ b/exports/arch/nss_ipq807x.h
@@ -34,6 +34,9 @@
 #define NSS_H2N_RING_COUNT 11		/**< Number of H2N rings. */
 #define NSS_RING_SIZE	128		/**< Ring size. */
 
+#define NSS_IMEM_START	0x38000000	/**< NSS IMEM start address. */
+#define NSS_IMEM_SIZE	0x30000		/**< NSS IMEM size per core. */
+
 /**
  * @}
  */
diff --git a/exports/arch/nss_ipq807x_64.h b/exports/arch/nss_ipq807x_64.h
index c505c5a..fec7aa5 100644
--- a/exports/arch/nss_ipq807x_64.h
+++ b/exports/arch/nss_ipq807x_64.h
@@ -34,6 +34,9 @@
 #define NSS_H2N_RING_COUNT 11		/**< Number of H2N rings. */
 #define NSS_RING_SIZE	128		/**< Ring size. */
 
+#define NSS_IMEM_START	0x38000000	/**< NSS IMEM start address. */
+#define NSS_IMEM_SIZE	0x30000		/**< NSS IMEM size per core. */
+
 /**
  * @}
  */
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_c2c_tx.h b/exports/nss_c2c_tx.h
index 5fc9362..3b1d9bf 100644
--- a/exports/nss_c2c_tx.h
+++ b/exports/nss_c2c_tx.h
@@ -38,6 +38,16 @@
 };
 
 /**
+ * nss_c2c_tx_msg_error
+ *	Message error types.
+ */
+enum nss_c2c_tx_msg_error {
+	NSS_C2C_TX_MSG_ERROR_NONE,		/**< No error. */
+	NSS_C2C_TX_MSG_ERROR_INVAL_OP,		/**< Invalid operation. */
+	NSS_C2C_TX_MSG_ERROR_MAX		/**< Maximum error type. */
+};
+
+/**
  * nss_c2c_tx_map
  *	Core-to-core transmission queue address and interrupt address.
  */
diff --git a/exports/nss_cmn.h b/exports/nss_cmn.h
index 70d303a..9cf058a 100644
--- a/exports/nss_cmn.h
+++ b/exports/nss_cmn.h
@@ -1,6 +1,6 @@
 /*
  **************************************************************************
- * Copyright (c) 2014, 2016-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014, 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.
@@ -123,7 +123,7 @@
 	NSS_CMN_RESPONSE_EINTERFACE,
 	NSS_CMN_RESPONSE_ELENGTH,
 	NSS_CMN_RESPONSE_EMSG,
-	NSS_CMM_RESPONSE_NOTIFY,
+	NSS_CMN_RESPONSE_NOTIFY,
 	NSS_CMN_RESPONSE_LAST
 };
 
diff --git a/exports/nss_crypto_cmn.h b/exports/nss_crypto_cmn.h
index 95e21e7..544c251 100644
--- a/exports/nss_crypto_cmn.h
+++ b/exports/nss_crypto_cmn.h
@@ -32,7 +32,7 @@
 #define NSS_CRYPTO_CMN_CTX_SPARE 4 /**< Context spare words size. */
 #define NSS_CRYPTO_CMN_VER_WORDS 4 /**< Firmware version words size.*/
 #define NSS_CRYPTO_CIPHER_KEYLEN_MAX 32 /**< Maximum cipher keysize. */
-#define NSS_CRYPTO_AUTH_KEYLEN_MAX 64 /**< Maximum authorization keysize. */
+#define NSS_CRYPTO_AUTH_KEYLEN_MAX 128 /**< Maximum authorization keysize. */
 #define NSS_CRYPTO_NONCE_SIZE_MAX 4 /**< Maximum authorization keysize. */
 
 /**
@@ -233,6 +233,10 @@
 	uint8_t cipher_key[NSS_CRYPTO_CIPHER_KEYLEN_MAX];	/**< Array containing cipher keys. */
 	uint8_t auth_key[NSS_CRYPTO_AUTH_KEYLEN_MAX];	/**< Array containing authorization keys. */
 	uint8_t nonce[NSS_CRYPTO_NONCE_SIZE_MAX];		/**< Nonce value. */
+
+	uint16_t auth_keylen;				/**< Authorization key length. */
+	uint8_t res[2];					/**< Reserved. */
+
 	enum nss_crypto_cmn_algo algo;			/**< Crypto algorithm. */
 	enum nss_crypto_cmn_ctx_flags flags;		/**< Context specific flags. */
 };
diff --git a/exports/nss_dynamic_interface.h b/exports/nss_dynamic_interface.h
index 68d04ad..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,
@@ -73,6 +73,8 @@
 	NSS_DYNAMIC_INTERFACE_TYPE_GRE_REDIR_LAG_US,
 	NSS_DYNAMIC_INTERFACE_TYPE_GRE_REDIR_LAG_DS,
 	NSS_DYNAMIC_INTERFACE_TYPE_GRE_TUNNEL_INNER_EXCEPTION,
+	NSS_DYNAMIC_INTERFACE_TYPE_GRE_REDIR_EXCEPTION_US,
+	NSS_DYNAMIC_INTERFACE_TYPE_GRE_REDIR_EXCEPTION_DS,
 	NSS_DYNAMIC_INTERFACE_TYPE_MAX
 };
 
diff --git a/exports/nss_gre_redir.h b/exports/nss_gre_redir.h
index e0f35e7..65b6728 100644
--- a/exports/nss_gre_redir.h
+++ b/exports/nss_gre_redir.h
@@ -132,6 +132,12 @@
 	 * - 3 -- Use core 3
 	 */
 	uint8_t rps_hint;
+
+	/**
+	 * Flag to indicate validity of RPS hint.
+	 */
+	uint8_t rps_hint_valid;
+
 };
 
 /**
@@ -190,6 +196,8 @@
 	uint32_t split_sg_alloc_fail;			/**< Split processing fail counter due to scatter gather buffer allocation failure. */
 	uint32_t split_linear_copy_fail;		/**< Split processing fail counter due to linear copy fail. */
 	uint32_t split_not_enough_tailroom;		/**< Split processing fail counter due to insufficient tailroom. */
+	uint32_t exception_ds_invalid_dst_drop;		/**< Downstream exception handling fail counter due to invalid destination. */
+	uint32_t decap_eapol_frames;			/**< Decapsulation EAPoL frame counters. */
 };
 
 /**
@@ -204,12 +212,18 @@
 	uint64_t sjack_tx_packets;			/**< SJACK Tx packet counter. */
 	uint64_t offl_rx_pkts[NSS_GRE_REDIR_NUM_RADIO];	/**< Offload Rx packet counter per radio. */
 	uint64_t offl_tx_pkts[NSS_GRE_REDIR_NUM_RADIO];	/**< Offload Tx packet counter per radio. */
+	uint64_t exception_us_rx;			/**< Upstream exception Rx packet counter. */
+	uint64_t exception_us_tx;			/**< Upstream exception Tx packet counter. */
+	uint64_t exception_ds_rx;			/**< Downstream exception Rx packet counter. */
+	uint64_t exception_ds_tx;			/**< Downstream exception Tx packet counter. */
 	uint64_t encap_sg_alloc_drop;			/**< Encapsulation drop counters due to scatter gather buffer allocation failure. */
 	uint64_t decap_fail_drop;			/**< Decapsulation drop counters due to invalid IP header. */
 	uint64_t decap_split_drop;			/**< Decapsulation drop counters due to split flow processing. */
 	uint64_t split_sg_alloc_fail;			/**< Split processing fail counter due to scatter gather buffer allocation failure. */
 	uint64_t split_linear_copy_fail;		/**< Split processing fail counter due to linear copy fail. */
 	uint64_t split_not_enough_tailroom;		/**< Split processing fail counter due to insufficient tailroom. */
+	uint64_t exception_ds_invalid_dst_drop;		/**< Downstream exception handling fail counter due to invalid destination. */
+	uint64_t decap_eapol_frames;			/**< Decapsulation EAPoL frame counters. */
 	uint32_t ref_count;				/**< Reference count for statistics. */
 };
 
@@ -273,6 +287,27 @@
 };
 
 /**
+ * nss_gre_redir_exception_us_metadata
+ *	Metadata information for upstream exception packet.
+ *
+ * Note: Additional fields need to be added by customer as required.
+ */
+struct nss_gre_redir_exception_us_metadata {
+	uint8_t tid;		/**< TID value. */
+};
+
+/**
+ * nss_gre_redir_exception_ds_metadata
+ *	Metadata information for downstream exception packet.
+ *
+ * Note: Additional fields need to be added by customer as required.
+ */
+struct nss_gre_redir_exception_ds_metadata {
+	uint32_t dst_vap_nssif;	/**< Destination VAP interface number. */
+	uint8_t tid;		/**< TID value. */
+};
+
+/**
  * Callback function for receiving GRE tunnel data.
  *
  * @datatypes
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/exports/nss_wifi_vdev.h b/exports/nss_wifi_vdev.h
index efc0e51..32b437b 100644
--- a/exports/nss_wifi_vdev.h
+++ b/exports/nss_wifi_vdev.h
@@ -619,7 +619,8 @@
 	uint32_t dir;		/**< Data direction for metadata. */
 	uint32_t ppdu_id;	/**< PPDU ID. */
 	uint16_t peer_id;	/**< Peer ID. */
-	uint16_t reserved;	/**< Reserve bytes for alignment. */
+	uint8_t first_msdu;	/**< First MSDU. */
+	uint8_t last_msdu;	/**< Last MSDU. */
 };
 
 /**
diff --git a/exports/nss_wifili_if.h b/exports/nss_wifili_if.h
index 0cd27a5..e2574ae 100644
--- a/exports/nss_wifili_if.h
+++ b/exports/nss_wifili_if.h
@@ -68,6 +68,8 @@
 				/**< MEC (Multicast echo check) peer ID. */
 #define NSS_WIFILI_MIC_KEY_LEN 8
 				/**< MIC (Message integrity code) key length. */
+#define NSS_WIFILI_TQM_RR_MAX 7
+				/**< Maximum transmit queue release reasons. */
 
 /**
  * nss_wifili_wme_stream_classes
@@ -134,6 +136,8 @@
 	NSS_WIFILI_PEER_SECURITY_TYPE_MSG,
 	NSS_WIFILI_PEER_NAWDS_ENABLE_MSG,
 	NSS_WIFILI_RADIO_BUF_CFG,
+	NSS_WIFILI_DBDC_REPEATER_SET_MSG,
+	NSS_DBDC_REPEATER_AST_FLUSH_MSG,
 	NSS_WIFILI_MAX_MSG
 };
 
@@ -624,6 +628,27 @@
 };
 
 /**
+ * nss_wifili_dbdc_mode_stats
+ *	Wifili DBDC mode statistics.
+ */
+struct nss_wifili_dbdc_mode_stats {
+	uint32_t dbdc_flush_ast_failed;
+			/**< Number of times DBDC AST flush message send has failed. */
+	uint32_t dbdc_drop_rx_secmcast;
+			/**< Number of packets dropped in DBDC Rx for secondary multicast. */
+	uint32_t dbdc_drop_tx_secmcast;
+			/**< Number of packets dropped in DBDC Tx for secondary multicast. */
+	uint32_t dbdc_drop_rx_alwaysprimary;
+			/**< Number of packets dropped in DBDC Rx for always primary. */
+	uint32_t dbdc_drop_tx_alwaysprimary;
+			/**< Number of packets dropped in DBDC Tx for always primary. */
+	uint32_t dbdc_drop_loop_rx;
+			/**< Number of packets dropped in DBDC Rx for DBDC loop. */
+	uint32_t dbdc_drop_loop_tx;
+			/**< Number of packets dropped in DBDC Tx for DBDC loop. */
+};
+
+/**
  * nss_wifili_device_stats
  * 	Wifili specific statistics.
  */
@@ -648,6 +673,8 @@
 									/**< Rx DMA ring statistics. */
 	struct nss_wifili_rx_wbm_ring_stats rxwbm_stats;
 									/**< WBM ring statistics. */
+	struct nss_wifili_dbdc_mode_stats dbdc_stats;
+									/**< DBDC mode statistics. */
 };
 
 /**
@@ -688,10 +715,7 @@
  *	Tx peer dropped packets.
  */
 struct nss_wifili_tx_dropped {
-	uint32_t fw_discard;		/**< Discarded by firmware. */
-	uint32_t fw_discard_retired;	/**< Firmware discard retired. */
-	uint32_t fw_discard_untransmitted;	/**< Firmware discard untransmitted. */
-	uint32_t mpdu_age_out;		/**< Number of PDU aged out. */
+	uint32_t drop_stats[NSS_WIFILI_TQM_RR_MAX];	/**< Discarded by firmware. */
 };
 
 /**
@@ -707,6 +731,8 @@
 	uint32_t tx_mcast_bytes;        /**< Total number of multicast bytes sent. */
 	uint32_t tx_ucast_cnt;          /**< Total number of unicast packets sent. */
 	uint32_t tx_ucast_bytes;        /**< Total number of unicast bytes sent. */
+	uint32_t tx_bcast_bytes;        /**< Total number of broadcast bytes sent. */
+	uint32_t tx_bcast_cnt;          /**< Total number of broadcast packets sent. */
 	struct nss_wifili_tx_dropped dropped;	/**< Tx peer dropped. */
 };
 
@@ -734,6 +760,10 @@
 	uint32_t rx_recvd_bytes;		/**< Total Rx received count. */
 	uint32_t nawds_mcast_drop;		/**< Total NAWDS drop count. */
 	uint32_t nawds_mcast_drop_bytes;	/**< Total NAWDS drop count. */
+	uint32_t rx_intra_bss_pkts_num;		/**< Total Intra-BSS packets received. */
+	uint32_t rx_intra_bss_pkts_bytes;	/**< Total Intra-BSS bytes received. */
+	uint32_t rx_intra_bss_fail_num;		/**< Total Intra-BSS packets failed. */
+	uint32_t rx_intra_bss_fail_bytes;	/**< Total Intra-BSS bytes received. */
 };
 
 /**
@@ -844,6 +874,14 @@
 };
 
 /**
+ * nss_wifili_dbdc_repeater_set_msg
+ *	Wifili DBDC repeater set message.
+ */
+struct nss_wifili_dbdc_repeater_set_msg {
+	uint32_t is_dbdc_en;			/**< DBDC enable flag. */
+};
+
+/**
  * nss_wifili_reo_tidq_msg
  *	REO TID queue setup message.
  */
@@ -943,6 +981,8 @@
 				/**< Wifili peer security message. */
 		struct nss_wifili_peer_nawds_enable_msg nawdsmsg;
 				/**< Wifili peer enable NAWDS message. */
+		struct nss_wifili_dbdc_repeater_set_msg dbdcrptrmsg;
+				/**< Wifili DBDC repeater enable message. */
 	} msg;			/**< Message payload. */
 };
 
diff --git a/nss_bridge.c b/nss_bridge.c
index 7967db0..3ded205 100644
--- a/nss_bridge.c
+++ b/nss_bridge.c
@@ -62,7 +62,7 @@
 	 * Update the callback and app_data for NOTIFY messages, IPv4 sends all notify messages
 	 * to the same callback/app_data.
 	 */
-	if (ncm->response == NSS_CMM_RESPONSE_NOTIFY) {
+	if (ncm->response == NSS_CMN_RESPONSE_NOTIFY) {
 		ncm->cb = (nss_ptr_t)nss_ctx->nss_top->bridge_callback;
 		ncm->app_data = (nss_ptr_t)nss_ctx->nss_top->bridge_ctx;
 	}
diff --git a/nss_c2c_rx.c b/nss_c2c_rx.c
index 1f83684..732a288 100644
--- a/nss_c2c_rx.c
+++ b/nss_c2c_rx.c
@@ -74,7 +74,7 @@
 	 * Update the callback and app_data for NOTIFY messages
 	 * TODO: Add notify callbacks for c2c_rx
 	 */
-	if (ncm->response == NSS_CMM_RESPONSE_NOTIFY) {
+	if (ncm->response == NSS_CMN_RESPONSE_NOTIFY) {
 		return;
 	}
 
diff --git a/nss_c2c_tx.c b/nss_c2c_tx.c
index 54df97a..02ddbc1 100644
--- a/nss_c2c_tx.c
+++ b/nss_c2c_tx.c
@@ -21,6 +21,7 @@
 
 #include "nss_tx_rx_common.h"
 #include "nss_c2c_tx_stats.h"
+#include "nss_c2c_tx_log.h"
 
 /*
  * Notify data structure
@@ -70,13 +71,17 @@
 	}
 
 	/*
+	 * Trace messages.
+	 */
+	nss_c2c_tx_log_rx_msg(nctm);
+
+	/*
 	 * Log failures
 	 */
 	nss_core_log_msg_failures(nss_ctx, ncm);
 
 	switch (nctm->cm.type) {
 	case NSS_C2C_TX_MSG_TYPE_TX_MAP:
-		nss_info("%p: NSS c2c_tx tx_map configuration received:\n", nss_ctx);
 		break;
 
 	case NSS_C2C_TX_MSG_TYPE_STATS:
@@ -87,7 +92,7 @@
 	/*
 	 * Update the callback and app_data for NOTIFY messages
 	 */
-	if (ncm->response == NSS_CMM_RESPONSE_NOTIFY) {
+	if (ncm->response == NSS_CMN_RESPONSE_NOTIFY) {
 		ncm->cb = (nss_ptr_t)nss_c2c_tx_notify[nss_ctx->id].c2c_tx_callback;
 		ncm->app_data = (nss_ptr_t)nss_c2c_tx_notify[nss_ctx->id].app_data;
 	}
@@ -139,6 +144,11 @@
 		return NSS_TX_FAILURE;
 	}
 
+	/*
+	 * Trace messages.
+	 */
+	nss_c2c_tx_log_tx_msg(nctm);
+
 	return nss_core_send_cmd(nss_ctx, nctm, sizeof(*nctm), NSS_NBUF_PAYLOAD_SIZE);
 }
 EXPORT_SYMBOL(nss_c2c_tx_tx_msg);
diff --git a/nss_c2c_tx_log.c b/nss_c2c_tx_log.c
new file mode 100644
index 0000000..6b6dd3a
--- /dev/null
+++ b/nss_c2c_tx_log.c
@@ -0,0 +1,121 @@
+/*
+ **************************************************************************
+ * Copyright (c) 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.
+ * 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_c2c_tx_log.c
+ *	NSS C2C TX logger file.
+ */
+
+#include "nss_core.h"
+
+/*
+ * nss_c2c_tx_log_message_types_str
+ *	C2C TX message strings
+ */
+static int8_t *nss_c2c_tx_log_message_types_str[NSS_C2C_TX_MSG_TYPE_MAX] __maybe_unused = {
+	"C2C TX Stats message",
+	"C2C TX Map Message",
+};
+
+/*
+ * nss_c2c_tx_log_error_response_types_str
+ *	Strings for error types for c2c_tx messages
+ */
+static int8_t *nss_c2c_tx_log_error_response_types_str[NSS_C2C_TX_MSG_ERROR_MAX] __maybe_unused = {
+	"No error",
+	"Invalid Operation"
+};
+
+/*
+ * nss_c2c_tx_map_msg()()
+ *	Log NSS C2C TX Map message.
+ */
+static void nss_c2c_tx_map_msg(struct nss_c2c_tx_msg *nctm)
+{
+	struct nss_c2c_tx_map *nctmm __maybe_unused = &nctm->msg.map;
+	nss_trace("%p: NSS C2C TX Map message: \n"
+		"C2C Receiver Queue Start Address: %d\n"
+		"C2C Interrupt Register Address: %d\n",
+		nctm,
+		nctmm->tx_map, nctmm->c2c_intr_addr);
+}
+
+/*
+ * nss_c2c_tx_log_verbose()
+ *	Log message contents.
+ */
+static void nss_c2c_tx_log_verbose(struct nss_c2c_tx_msg *nctm)
+{
+	switch (nctm->cm.type) {
+	case NSS_C2C_TX_MSG_TYPE_TX_MAP:
+		nss_c2c_tx_map_msg(nctm);
+		break;
+
+	default:
+		nss_trace("%p: Invalid message type\n", nctm);
+		break;
+	}
+}
+
+/*
+ * nss_c2c_tx_log_tx_msg()
+ *	Log messages transmitted to FW.
+ */
+void nss_c2c_tx_log_tx_msg(struct nss_c2c_tx_msg *nctm)
+{
+	if (nctm->cm.type >= NSS_C2C_TX_MSG_TYPE_MAX) {
+		nss_info("%p: Invalid message type\n", nctm);
+		return;
+	}
+
+	nss_info("%p: type[%d]:%s\n", nctm, nctm->cm.type, nss_c2c_tx_log_message_types_str[nctm->cm.type]);
+	nss_c2c_tx_log_verbose(nctm);
+}
+
+/*
+ * nss_c2c_tx_log_rx_msg()
+ *	Log messages received from FW.
+ */
+void nss_c2c_tx_log_rx_msg(struct nss_c2c_tx_msg *nctm)
+{
+	if (nctm->cm.response >= NSS_CMN_RESPONSE_LAST) {
+		nss_warning("%p: Invalid response\n", nctm);
+		return;
+	}
+
+	if (nctm->cm.response == NSS_CMN_RESPONSE_NOTIFY || (nctm->cm.response == NSS_CMN_RESPONSE_ACK)) {
+		nss_info("%p: type[%d]:%s, response[%d]:%s\n", nctm, nctm->cm.type,
+			nss_c2c_tx_log_message_types_str[nctm->cm.type],
+			nctm->cm.response, nss_cmn_response_str[nctm->cm.response]);
+		goto verbose;
+	}
+
+	if (nctm->cm.error >= NSS_C2C_TX_MSG_ERROR_MAX) {
+		nss_warning("%p: msg failure - type[%d]:%s, response[%d]:%s, error[%d]:Invalid error\n",
+			nctm, nctm->cm.type, nss_c2c_tx_log_message_types_str[nctm->cm.type],
+			nctm->cm.response, nss_cmn_response_str[nctm->cm.response],
+			nctm->cm.error);
+		goto verbose;
+	}
+
+	nss_info("%p: msg nack - type[%d]:%s, response[%d]:%s, error[%d]:%s\n",
+		nctm, nctm->cm.type, nss_c2c_tx_log_message_types_str[nctm->cm.type],
+		nctm->cm.response, nss_cmn_response_str[nctm->cm.response],
+		nctm->cm.error, nss_c2c_tx_log_error_response_types_str[nctm->cm.error]);
+
+verbose:
+	nss_c2c_tx_log_verbose(nctm);
+}
diff --git a/nss_c2c_tx_log.h b/nss_c2c_tx_log.h
new file mode 100644
index 0000000..e6ec47e
--- /dev/null
+++ b/nss_c2c_tx_log.h
@@ -0,0 +1,36 @@
+/*
+ ******************************************************************************
+ * Copyright (c) 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.
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ * ****************************************************************************
+ */
+
+#ifndef __NSS_C2C_TX_LOG_H
+#define __NSS_C2C_TX_LOG_H
+/*
+ * nss_c2c_tx_log.h
+ *	NSS C2C TX Log Header File
+ */
+
+/*
+ * nss_c2c_tx_log_tx_msg
+ *	Logs an C2C TX message that is sent to the NSS firmware.
+ */
+void nss_c2c_tx_log_tx_msg(struct nss_c2c_tx_msg *nctm);
+
+/*
+ * nss_c2c_tx_log_rx_msg
+ *	Logs an IPv4 message that is received from the NSS firmware.
+ */
+void nss_c2c_tx_log_rx_msg(struct nss_c2c_tx_msg *nctm);
+
+#endif /* __NSS_C2C_TX_LOG_H */
diff --git a/nss_capwap.c b/nss_capwap.c
index 4bac682..f6603fc 100644
--- a/nss_capwap.c
+++ b/nss_capwap.c
@@ -211,7 +211,7 @@
 	/*
 	 * Update the callback and app_data for NOTIFY messages.
 	 */
-	if (ncm->response == NSS_CMM_RESPONSE_NOTIFY) {
+	if (ncm->response == NSS_CMN_RESPONSE_NOTIFY) {
 		ncm->cb = (nss_ptr_t)nss_capwap_get_msg_callback(ncm->interface, (void **)&ncm->app_data);
 	}
 
diff --git a/nss_core.c b/nss_core.c
index e5be8f8..244b87e 100644
--- a/nss_core.c
+++ b/nss_core.c
@@ -1274,7 +1274,8 @@
 	struct n2h_descriptor *desc;
 	struct n2h_descriptor *next_cache_desc;
 	struct nss_ctx_instance *nss_ctx = int_ctx->nss_ctx;
-	struct nss_if_mem_map *if_map = (struct nss_if_mem_map *)nss_ctx->vmap;
+	struct nss_meminfo_ctx *mem_ctx = &nss_ctx->meminfo_ctx;
+	struct nss_if_mem_map *if_map = mem_ctx->if_map;
 
 	qid = nss_core_cause_to_queue(cause);
 
@@ -1879,7 +1880,8 @@
 static void nss_core_handle_cause_nonqueue(struct int_ctx_instance *int_ctx, uint32_t cause, int16_t weight)
 {
 	struct nss_ctx_instance *nss_ctx = int_ctx->nss_ctx;
-	struct nss_if_mem_map *if_map = (struct nss_if_mem_map *)(nss_ctx->vmap);
+	struct nss_meminfo_ctx *mem_ctx = &nss_ctx->meminfo_ctx;
+	struct nss_if_mem_map *if_map = mem_ctx->if_map;
 	uint16_t max_buf_size = (uint16_t) nss_ctx->max_buf_size;
 	uint32_t c2c_intr_addr1, c2c_intr_addr2;
 	int32_t i;
@@ -2635,7 +2637,8 @@
 	struct h2n_desc_if_instance *desc_if = &h2n_desc_ring->desc_ring;
 	struct h2n_descriptor *desc_ring;
 	struct h2n_descriptor *desc;
-	struct nss_if_mem_map *if_map = (struct nss_if_mem_map *)nss_ctx->vmap;
+	struct nss_meminfo_ctx *mem_ctx = &nss_ctx->meminfo_ctx;
+	struct nss_if_mem_map *if_map = mem_ctx->if_map;
 	uint16_t mss = 0;
 	bool is_bounce = ((buffer_type == H2N_BUFFER_SHAPER_BOUNCE_INTERFACE) || (buffer_type == H2N_BUFFER_SHAPER_BOUNCE_BRIDGE));
 
diff --git a/nss_core.h b/nss_core.h
index 693b59a..82897c9 100644
--- a/nss_core.h
+++ b/nss_core.h
@@ -40,6 +40,7 @@
 #include "nss_oam.h"
 #include "nss_data_plane.h"
 #include "nss_stats.h"
+#include "nss_meminfo.h"
 
 /*
  * XXX:can't add this to api_if.h till the deprecated
@@ -216,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
@@ -490,12 +487,7 @@
 	uint32_t vphys;			/* Phys mem pointer to virtual register map */
 	uint32_t qgic_phys;		/* Phys mem pointer to QGIC register map */
 	uint32_t load;			/* Load address for this core */
-	unsigned long n2h_ring;		/* Allocated n2h ring buffer */
-	unsigned long h2n_ring;		/* Allocated h2n ring buffer */
-	uint32_t n2h_ring_dma;		/* DMA Address of the n2h_ring */
-	uint32_t h2n_ring_dma;		/* DMA Address of the h2n_ring */
-	uint32_t n2h_ring_total_size;	/* Total size of the n2h_ring */
-	uint32_t h2n_ring_total_size;	/* Total size of the h2n_ring */
+	struct nss_meminfo_ctx meminfo_ctx;	/* Meminfo context */
 	enum nss_core_state state;	/* State of NSS core */
 	uint32_t c2c_start;		/* C2C start address */
 	struct int_ctx_instance int_ctx[NSS_MAX_IRQ_PER_CORE];
@@ -563,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;
@@ -622,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];
@@ -862,7 +857,7 @@
  */
 static inline void nss_core_log_msg_failures(struct nss_ctx_instance *nss_ctx, struct nss_cmn_msg *ncm)
 {
-	if ((ncm->response == NSS_CMN_RESPONSE_ACK) || (ncm->response == NSS_CMM_RESPONSE_NOTIFY)) {
+	if ((ncm->response == NSS_CMN_RESPONSE_ACK) || (ncm->response == NSS_CMN_RESPONSE_NOTIFY)) {
 		return;
 	}
 
diff --git a/nss_crypto.c b/nss_crypto.c
index 664c5d6..409c53d 100644
--- a/nss_crypto.c
+++ b/nss_crypto.c
@@ -86,7 +86,7 @@
 		return;
 	}
 
-	if (ncm->response == NSS_CMM_RESPONSE_NOTIFY) {
+	if (ncm->response == NSS_CMN_RESPONSE_NOTIFY) {
 		ncm->cb = (nss_ptr_t)nss_crypto_get_msg_callback(nss_ctx, &crypto_ctx);
 		ncm->app_data = (nss_ptr_t)crypto_ctx;
 	}
diff --git a/nss_crypto_cmn.c b/nss_crypto_cmn.c
index 564ba2e..cf5dfb4 100644
--- a/nss_crypto_cmn.c
+++ b/nss_crypto_cmn.c
@@ -81,7 +81,7 @@
 		return;
 	}
 
-	if (ncm->response == NSS_CMM_RESPONSE_NOTIFY) {
+	if (ncm->response == NSS_CMN_RESPONSE_NOTIFY) {
 		ncm->cb = (nss_ptr_t)nss_ctx->nss_top->crypto_cmn_msg_callback;
 		ncm->app_data = (nss_ptr_t)nss_ctx->nss_top->crypto_ctx;
 	}
diff --git a/nss_dtls.c b/nss_dtls.c
index f693fa1..ec8b2be 100644
--- a/nss_dtls.c
+++ b/nss_dtls.c
@@ -185,7 +185,7 @@
 	/*
 	 * Update the callback and app_data for NOTIFY messages
 	 */
-	if (ncm->response == NSS_CMM_RESPONSE_NOTIFY) {
+	if (ncm->response == NSS_CMN_RESPONSE_NOTIFY) {
 		ncm->cb = (nss_ptr_t)nss_ctx->nss_top->dtls_msg_callback;
 		ncm->app_data = (nss_ptr_t)nss_ctx->subsys_dp_register[ncm->interface].app_data;
 	}
@@ -366,6 +366,7 @@
 	}
 
 	nss_core_register_subsys_dp(nss_ctx, if_num, cb, NULL, app_ctx, netdev, features);
+	nss_ctx->subsys_dp_register[if_num].type = NSS_DYNAMIC_INTERFACE_TYPE_DTLS;
 
 	nss_top_main.dtls_msg_callback = ev_cb;
 	nss_core_register_handler(nss_ctx, if_num, nss_dtls_handler, app_ctx);
diff --git a/nss_dtls_cmn.c b/nss_dtls_cmn.c
index 050244d..69db971 100644
--- a/nss_dtls_cmn.c
+++ b/nss_dtls_cmn.c
@@ -167,7 +167,7 @@
 	/*
 	 * Update the callback and app_data for NOTIFY messages
 	 */
-	if (ncm->response == NSS_CMM_RESPONSE_NOTIFY) {
+	if (ncm->response == NSS_CMN_RESPONSE_NOTIFY) {
 		ncm->cb = (nss_ptr_t)nss_top_main.if_rx_msg_callback[ncm->interface];
 		ncm->app_data = (nss_ptr_t)nss_ctx->nss_rx_interface_handlers[nss_ctx->id][ncm->interface].app_data;
 	}
diff --git a/nss_dtls_stats.c b/nss_dtls_stats.c
index a15e716..13b9aae 100644
--- a/nss_dtls_stats.c
+++ b/nss_dtls_stats.c
@@ -25,7 +25,10 @@
 static int8_t *nss_dtls_stats_session_str[NSS_DTLS_STATS_SESSION_MAX] = {
 	"RX_PKTS",
 	"TX_PKTS",
-	"RX_DROPPED",
+	"RX_DROPPED_0",
+	"RX_DROPPED_1",
+	"RX_DROPPED_2",
+	"RX_DROPPED_3",
 	"RX_AUTH_DONE",
 	"TX_AUTH_DONE",
 	"RX_CIPHER_DONE",
diff --git a/nss_edma.c b/nss_edma.c
index 0abb48e..57feb1c 100644
--- a/nss_edma.c
+++ b/nss_edma.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.
@@ -72,7 +72,7 @@
 	 * Update the callback and app_data for NOTIFY messages, edma sends all notify messages
 	 * to the same callback/app_data.
 	 */
-	if (nem->cm.response == NSS_CMM_RESPONSE_NOTIFY) {
+	if (nem->cm.response == NSS_CMN_RESPONSE_NOTIFY) {
 		ncm->cb = (nss_ptr_t)nss_ctx->nss_top->edma_callback;
 		ncm->app_data = (nss_ptr_t)nss_ctx->nss_top->edma_ctx;
 	}
diff --git a/nss_gre.c b/nss_gre.c
index 2edb466..e262154 100644
--- a/nss_gre.c
+++ b/nss_gre.c
@@ -101,7 +101,7 @@
 	 * Update the callback and app_data for NOTIFY messages, gre sends all notify messages
 	 * to the same callback/app_data.
 	 */
-	if (ncm->response == NSS_CMM_RESPONSE_NOTIFY) {
+	if (ncm->response == NSS_CMN_RESPONSE_NOTIFY) {
 		ncm->cb = (nss_ptr_t)nss_ctx->nss_top->gre_msg_callback;
 		ncm->app_data = (nss_ptr_t)nss_ctx->subsys_dp_register[ncm->interface].app_data;
 	}
diff --git a/nss_gre_redir.c b/nss_gre_redir.c
index 80d89b9..c899873 100644
--- a/nss_gre_redir.c
+++ b/nss_gre_redir.c
@@ -66,7 +66,9 @@
 	return type == NSS_DYNAMIC_INTERFACE_TYPE_GRE_REDIR_WIFI_HOST_INNER ||
 			type == NSS_DYNAMIC_INTERFACE_TYPE_GRE_REDIR_WIFI_OFFL_INNER ||
 			type == NSS_DYNAMIC_INTERFACE_TYPE_GRE_REDIR_SJACK_INNER ||
-			type == NSS_DYNAMIC_INTERFACE_TYPE_GRE_REDIR_OUTER;
+			type == NSS_DYNAMIC_INTERFACE_TYPE_GRE_REDIR_OUTER ||
+			type == NSS_DYNAMIC_INTERFACE_TYPE_GRE_REDIR_EXCEPTION_US ||
+			type == NSS_DYNAMIC_INTERFACE_TYPE_GRE_REDIR_EXCEPTION_DS;
 }
 
 /*
@@ -128,12 +130,24 @@
 		tun_stats[i].split_sg_alloc_fail += ngss->split_sg_alloc_fail;
 		tun_stats[i].split_linear_copy_fail += ngss->split_linear_copy_fail;
 		tun_stats[i].split_not_enough_tailroom += ngss->split_not_enough_tailroom;
+		tun_stats[i].decap_eapol_frames += ngss->decap_eapol_frames;
 		tun_stats[i].node_stats.rx_dropped[0] += nss_cmn_rx_dropped_sum(&(ngss->node_stats));
 		for (j = 0; j < NSS_GRE_REDIR_NUM_RADIO; j++) {
 			tun_stats[i].offl_rx_pkts[j] += ngss->offl_rx_pkts[j];
 		}
 
 		break;
+
+	case NSS_DYNAMIC_INTERFACE_TYPE_GRE_REDIR_EXCEPTION_US:
+		tun_stats[i].exception_us_rx += ngss->node_stats.rx_packets;
+		tun_stats[i].exception_us_tx += ngss->node_stats.tx_packets;
+		break;
+
+	case NSS_DYNAMIC_INTERFACE_TYPE_GRE_REDIR_EXCEPTION_DS:
+		tun_stats[i].exception_ds_rx += ngss->node_stats.rx_packets;
+		tun_stats[i].exception_ds_tx += ngss->node_stats.tx_packets;
+		tun_stats[i].exception_ds_invalid_dst_drop += ngss->exception_ds_invalid_dst_drop;
+		break;
 	}
 
 	spin_unlock_bh(&nss_gre_redir_stats_lock);
@@ -173,7 +187,7 @@
 	 * Update the callback and app_data for NOTIFY messages, gre sends all notify messages
 	 * to the same callback/app_data.
 	 */
-	if (ncm->response == NSS_CMM_RESPONSE_NOTIFY) {
+	if (ncm->response == NSS_CMN_RESPONSE_NOTIFY) {
 		ncm->cb = (nss_ptr_t)nss_ctx->nss_top->if_rx_msg_callback[ncm->interface];
 		ncm->app_data = (nss_ptr_t)nss_ctx->nss_rx_interface_handlers[nss_ctx->id][ncm->interface].app_data;
 	}
@@ -296,7 +310,9 @@
 	if ((type != NSS_DYNAMIC_INTERFACE_TYPE_GRE_REDIR_WIFI_HOST_INNER) &&
 			(type != NSS_DYNAMIC_INTERFACE_TYPE_GRE_REDIR_WIFI_OFFL_INNER) &&
 			(type != NSS_DYNAMIC_INTERFACE_TYPE_GRE_REDIR_SJACK_INNER) &&
-			(type != NSS_DYNAMIC_INTERFACE_TYPE_GRE_REDIR_OUTER)) {
+			(type != NSS_DYNAMIC_INTERFACE_TYPE_GRE_REDIR_OUTER) &&
+			(type != NSS_DYNAMIC_INTERFACE_TYPE_GRE_REDIR_EXCEPTION_US) &&
+			(type != NSS_DYNAMIC_INTERFACE_TYPE_GRE_REDIR_EXCEPTION_DS)) {
 
 		nss_warning("%p: Unknown type %u\n", dev, type);
 		return -1;
@@ -548,7 +564,8 @@
 	 * type GRE_REDIR_WIFI_HOST_INNER.
 	 */
 	type = nss_dynamic_interface_get_type(nss_ctx, if_num);
-	if (type != NSS_DYNAMIC_INTERFACE_TYPE_GRE_REDIR_WIFI_HOST_INNER) {
+	if (!((type == NSS_DYNAMIC_INTERFACE_TYPE_GRE_REDIR_WIFI_HOST_INNER)
+		|| (type == NSS_DYNAMIC_INTERFACE_TYPE_GRE_REDIR_EXCEPTION_DS))) {
 		nss_warning("%p: Unknown type for interface %u\n", nss_ctx, type);
 		return NSS_TX_FAILURE_BAD_PARAM;
 	}
diff --git a/nss_gre_redir_lag_ds.c b/nss_gre_redir_lag_ds.c
index 10c518f..5bed7ba 100644
--- a/nss_gre_redir_lag_ds.c
+++ b/nss_gre_redir_lag_ds.c
@@ -142,7 +142,7 @@
 	 * Update the callback and app_data for NOTIFY messages, gre sends all notify messages
 	 * to the same callback/app_data.
 	 */
-	if (ncm->response == NSS_CMM_RESPONSE_NOTIFY) {
+	if (ncm->response == NSS_CMN_RESPONSE_NOTIFY) {
 		ncm->cb = (nss_ptr_t)nss_ctx->nss_top->if_rx_msg_callback[ncm->interface];
 		ncm->app_data = (nss_ptr_t)nss_ctx->nss_rx_interface_handlers[nss_ctx->id][ncm->interface].app_data;
 	}
diff --git a/nss_gre_redir_lag_us.c b/nss_gre_redir_lag_us.c
index df0e47f..18690a4 100644
--- a/nss_gre_redir_lag_us.c
+++ b/nss_gre_redir_lag_us.c
@@ -216,7 +216,7 @@
 	 * Update the callback and app_data for NOTIFY messages, GRE sends all notify messages
 	 * to the same callback/app_data.
 	 */
-	if (ncm->response == NSS_CMM_RESPONSE_NOTIFY) {
+	if (ncm->response == NSS_CMN_RESPONSE_NOTIFY) {
 		ncm->cb = (nss_ptr_t)nss_ctx->nss_top->if_rx_msg_callback[ncm->interface];
 		ncm->app_data = (nss_ptr_t)nss_ctx->nss_rx_interface_handlers[nss_ctx->id][ncm->interface].app_data;
 	}
diff --git a/nss_gre_redir_stats.c b/nss_gre_redir_stats.c
index cb60c1b..f94f64c 100644
--- a/nss_gre_redir_stats.c
+++ b/nss_gre_redir_stats.c
@@ -34,12 +34,18 @@
 	"RX Sjack packets",
 	"TX Offload Packets",
 	"RX Offload Packets",
+	"US exception RX Packets",
+	"US exception TX Packets",
+	"DS exception RX Packets",
+	"DS exception TX Packets",
 	"Encap SG alloc drop",
 	"Decap fail drop",
 	"Decap split drop",
 	"Split SG alloc fail",
 	"Split linear copy fail",
-	"Split not enough tailroom"
+	"Split not enough tailroom",
+	"Decap eapol frames",
+	"exception ds invalid dst"
 };
 
 /*
@@ -89,6 +95,18 @@
 			tcnt += snprintf(line + tcnt, len - tcnt, "%s = %llu\n", name, s->offl_rx_pkts[j]);
 		}
 		return tcnt;
+	case NSS_GRE_REDIR_STATS_EXCEPTION_US_RX_PKTS:
+		tcnt = s->exception_us_rx;
+		return snprintf(line, len, "%s = %llu\n", nss_gre_redir_stats_str[i], tcnt);
+	case NSS_GRE_REDIR_STATS_EXCEPTION_US_TX_PKTS:
+		tcnt = s->exception_us_tx;
+		return snprintf(line, len, "%s = %llu\n", nss_gre_redir_stats_str[i], tcnt);
+	case NSS_GRE_REDIR_STATS_EXCEPTION_DS_RX_PKTS:
+		tcnt = s->exception_ds_rx;
+		return snprintf(line, len, "%s = %llu\n", nss_gre_redir_stats_str[i], tcnt);
+	case NSS_GRE_REDIR_STATS_EXCEPTION_DS_TX_PKTS:
+		tcnt = s->exception_ds_tx;
+		return snprintf(line, len, "%s = %llu\n", nss_gre_redir_stats_str[i], tcnt);
 	case NSS_GRE_REDIR_STATS_ENCAP_SG_ALLOC_DROP:
 		tcnt = s->encap_sg_alloc_drop;
 		return snprintf(line, len, "%s = %llu\n", nss_gre_redir_stats_str[i], tcnt);
@@ -106,7 +124,13 @@
 		return snprintf(line, len, "%s = %llu\n", nss_gre_redir_stats_str[i], tcnt);
 	case NSS_GRE_REDIR_STATS_SPLIT_NOT_ENOUGH_TAILROOM:
 		tcnt = s->split_not_enough_tailroom;
-		return snprintf(line, len, "%s = %llu\n Offload stats ens.\n", nss_gre_redir_stats_str[i], tcnt);
+		return snprintf(line, len, "%s = %llu\n", nss_gre_redir_stats_str[i], tcnt);
+	case NSS_GRE_REDIR_STATS_EXCEPTION_DS_INVALID_DST_DROP:
+		tcnt = s->exception_ds_invalid_dst_drop;
+		return snprintf(line, len, "%s = %llu\n", nss_gre_redir_stats_str[i], tcnt);
+	case NSS_GRE_REDIR_STATS_DECAP_EAPOL_FRAMES:
+		tcnt = s->decap_eapol_frames;
+		return snprintf(line, len, "%s = %llu\n Offload stats end.\n", nss_gre_redir_stats_str[i], tcnt);
 	default:
 		nss_warning("Unknown stats type %d.\n", i);
 		return 0;
diff --git a/nss_gre_redir_stats.h b/nss_gre_redir_stats.h
index d27e6c2..2951eb7 100644
--- a/nss_gre_redir_stats.h
+++ b/nss_gre_redir_stats.h
@@ -31,12 +31,18 @@
 	NSS_GRE_REDIR_STATS_SJACK_RX_PKTS,
 	NSS_GRE_REDIR_STATS_OFFLOAD_TX_PKTS,
 	NSS_GRE_REDIR_STATS_OFFLOAD_RX_PKTS,
+	NSS_GRE_REDIR_STATS_EXCEPTION_US_RX_PKTS,
+	NSS_GRE_REDIR_STATS_EXCEPTION_US_TX_PKTS,
+	NSS_GRE_REDIR_STATS_EXCEPTION_DS_RX_PKTS,
+	NSS_GRE_REDIR_STATS_EXCEPTION_DS_TX_PKTS,
 	NSS_GRE_REDIR_STATS_ENCAP_SG_ALLOC_DROP,
 	NSS_GRE_REDIR_STATS_DECAP_FAIL_DROP,
 	NSS_GRE_REDIR_STATS_DECAP_SPLIT_DROP,
 	NSS_GRE_REDIR_STATS_SPLIT_SG_ALLOC_FAIL,
 	NSS_GRE_REDIR_STATS_SPLIT_LINEAR_COPY_FAIL,
 	NSS_GRE_REDIR_STATS_SPLIT_NOT_ENOUGH_TAILROOM,
+	NSS_GRE_REDIR_STATS_EXCEPTION_DS_INVALID_DST_DROP,
+	NSS_GRE_REDIR_STATS_DECAP_EAPOL_FRAMES,
 	NSS_GRE_REDIR_STATS_MAX
 };
 
diff --git a/nss_gre_tunnel.c b/nss_gre_tunnel.c
index b2ea700..aa6aa22 100644
--- a/nss_gre_tunnel.c
+++ b/nss_gre_tunnel.c
@@ -89,7 +89,7 @@
 	/*
 	 * Update the callback and app_data for NOTIFY messages
 	 */
-	if (ncm->response == NSS_CMM_RESPONSE_NOTIFY) {
+	if (ncm->response == NSS_CMN_RESPONSE_NOTIFY) {
 		ncm->cb = (nss_ptr_t)nss_ctx->nss_top->gre_tunnel_msg_callback;
 		ncm->app_data = (nss_ptr_t)nss_ctx->subsys_dp_register[ncm->interface].app_data;
 	}
diff --git a/nss_hal/ipq807x/nss_hal_pvt.c b/nss_hal/ipq807x/nss_hal_pvt.c
index d9521ec..e4646b0 100644
--- a/nss_hal/ipq807x/nss_hal_pvt.c
+++ b/nss_hal/ipq807x/nss_hal_pvt.c
@@ -651,6 +651,8 @@
 	struct int_ctx_instance *int_ctx = &nss_ctx->int_ctx[irq_num];
 	int err = -1, irq = npd->irq[irq_num];
 
+	irq_set_status_flags(irq, IRQ_DISABLE_UNLAZY);
+
 	if (irq_num == NSS_HAL_N2H_INTR_PURPOSE_EMPTY_BUFFER_SOS) {
 		netif_napi_add(int_ctx->ndev, &int_ctx->napi, nss_core_handle_napi_non_queue, NSS_EMPTY_BUFFER_SOS_PROCESSING_WEIGHT);
 		int_ctx->cause = NSS_N2H_INTR_EMPTY_BUFFERS_SOS;
diff --git a/nss_hal/nss_hal.c b/nss_hal/nss_hal.c
index 82e34b5..88ff1a1 100644
--- a/nss_hal/nss_hal.c
+++ b/nss_hal/nss_hal.c
@@ -23,6 +23,7 @@
 #include <linux/version.h>
 #include <linux/firmware.h>
 #include <linux/of.h>
+#include <linux/irq.h>
 
 #include "nss_hal.h"
 #include "nss_arch.h"
@@ -143,6 +144,7 @@
 static void nss_hal_clean_up_netdevice(struct int_ctx_instance *int_ctx)
 {
 	if (int_ctx->irq) {
+		irq_clear_status_flags(int_ctx->irq, IRQ_DISABLE_UNLAZY);
 		free_irq(int_ctx->irq, int_ctx);
 		int_ctx->irq = 0;
 	}
@@ -212,110 +214,6 @@
 }
 
 /*
- * nss_hal_free_rings()
- *	Free n2h/h2n rings
- */
-static void nss_hal_free_rings(struct nss_ctx_instance *nss_ctx)
-{
-	if (nss_ctx->n2h_ring) {
-		if (!dma_mapping_error(nss_ctx->dev, nss_ctx->n2h_ring_dma)) {
-			dma_unmap_single(nss_ctx->dev, nss_ctx->n2h_ring_dma, nss_ctx->n2h_ring_total_size, DMA_FROM_DEVICE);
-		}
-		free_pages(nss_ctx->n2h_ring, get_order(nss_ctx->n2h_ring_total_size));
-		nss_ctx->n2h_ring = 0;
-	}
-
-	if (nss_ctx->h2n_ring) {
-		if (!dma_mapping_error(nss_ctx->dev, nss_ctx->h2n_ring_dma)) {
-			dma_unmap_single(nss_ctx->dev, nss_ctx->h2n_ring_dma, nss_ctx->h2n_ring_total_size, DMA_FROM_DEVICE);
-		}
-		free_pages(nss_ctx->h2n_ring, get_order(nss_ctx->h2n_ring_total_size));
-		nss_ctx->h2n_ring = 0;
-	}
-}
-
-/*
- * nss_hal_alloc_rings()
- *	Allocate n2h/h2n rings
- */
-static int nss_hal_alloc_rings(struct nss_ctx_instance *nss_ctx)
-{
-	struct nss_if_mem_map *if_map = (struct nss_if_mem_map *)(nss_ctx->vmap);
-	int i;
-
-	/*
-	 * TODO: We are purposely reserving 2 descriptor size between each ring
-	 * to avoid unexpected cache behavior. This needs to be investigated
-	 * further.
-	 */
-	nss_ctx->n2h_ring_total_size = sizeof(struct n2h_descriptor) * NSS_N2H_RING_COUNT * (NSS_RING_SIZE + 2);
-	nss_ctx->h2n_ring_total_size = sizeof(struct h2n_descriptor) * NSS_H2N_RING_COUNT * (NSS_RING_SIZE + 2);
-
-	nss_ctx->n2h_ring = __get_free_pages(GFP_KERNEL | __GFP_NOWARN | __GFP_ZERO, get_order(nss_ctx->n2h_ring_total_size));
-	if (!nss_ctx->n2h_ring) {
-		nss_info_always("%p: failed to alloc n2h_rings\n", nss_ctx);
-		return -ENOMEM;
-	}
-
-	nss_ctx->n2h_ring_dma = dma_map_single(nss_ctx->dev, (void *)nss_ctx->n2h_ring, nss_ctx->n2h_ring_total_size, DMA_TO_DEVICE);
-	if (dma_mapping_error(nss_ctx->dev, nss_ctx->n2h_ring_dma)) {
-		nss_info_always("%p: failed to map n2h_rings\n", nss_ctx);
-		goto clean_up;
-	}
-
-	nss_ctx->h2n_ring = __get_free_pages(GFP_KERNEL | __GFP_NOWARN | __GFP_ZERO, get_order(nss_ctx->h2n_ring_total_size));
-	if (!nss_ctx->h2n_ring) {
-		nss_info_always("%p: failed to alloc h2n_rings\n", nss_ctx);
-		goto clean_up;
-	}
-
-	nss_ctx->h2n_ring_dma = dma_map_single(nss_ctx->dev, (void *)nss_ctx->h2n_ring, nss_ctx->h2n_ring_total_size, DMA_TO_DEVICE);
-	if (dma_mapping_error(nss_ctx->dev, nss_ctx->h2n_ring_dma)) {
-		nss_info_always("%p: failed to map h2n_rings\n", nss_ctx);
-		goto clean_up;
-	}
-
-	/*
-	 * N2H ring settings
-	 */
-	if_map->n2h_rings = NSS_N2H_RING_COUNT;
-	for (i = 0; i < NSS_N2H_RING_COUNT; i++) {
-		struct hlos_n2h_desc_ring *n2h_desc_ring = &nss_ctx->n2h_desc_ring[i];
-		n2h_desc_ring->desc_ring.desc = (struct n2h_descriptor *)(nss_ctx->n2h_ring + i * sizeof(struct n2h_descriptor) * (NSS_RING_SIZE + 2));
-		n2h_desc_ring->desc_ring.size = NSS_RING_SIZE;
-		n2h_desc_ring->hlos_index = if_map->n2h_hlos_index[i];
-
-		if_map->n2h_desc_if[i].size = NSS_RING_SIZE;
-		if_map->n2h_desc_if[i].desc_addr = nss_ctx->n2h_ring_dma + i * sizeof(struct n2h_descriptor) * (NSS_RING_SIZE + 2);
-		nss_info("%p: N2H ring %d, size %d, addr = %x\n", nss_ctx, i, if_map->n2h_desc_if[i].size, if_map->n2h_desc_if[i].desc_addr);
-	}
-
-	/*
-	 * H2N ring settings
-	 */
-	if_map->h2n_rings = NSS_H2N_RING_COUNT;
-	for (i = 0; i < NSS_H2N_RING_COUNT; i++) {
-		struct hlos_h2n_desc_rings *h2n_desc_ring = &nss_ctx->h2n_desc_rings[i];
-		h2n_desc_ring->desc_ring.desc = (struct h2n_descriptor *)(nss_ctx->h2n_ring + i * sizeof(struct h2n_descriptor) * (NSS_RING_SIZE + 2));
-		h2n_desc_ring->desc_ring.size = NSS_RING_SIZE;
-		h2n_desc_ring->hlos_index = if_map->h2n_hlos_index[i];
-		spin_lock_init(&h2n_desc_ring->lock);
-
-		if_map->h2n_desc_if[i].size = NSS_RING_SIZE;
-		if_map->h2n_desc_if[i].desc_addr = nss_ctx->h2n_ring_dma + i * sizeof(struct h2n_descriptor) * (NSS_RING_SIZE + 2);
-		nss_info("%p: H2N ring %d, size %d, addr = %x\n", nss_ctx, i, if_map->h2n_desc_if[i].size, if_map->h2n_desc_if[i].desc_addr);
-	}
-
-	NSS_CORE_DMA_CACHE_MAINT(if_map, sizeof(struct nss_if_mem_map), DMA_TO_DEVICE);
-	NSS_CORE_DSB();
-
-	return 0;
-clean_up:
-	nss_hal_free_rings(nss_ctx);
-	return -ENOMEM;
-}
-
-/*
  * nss_hal_probe()
  *	HLOS device probe callback
  */
@@ -417,9 +315,8 @@
 	nss_info("%d:ctx=%p, vphys=%x, vmap=%p, nphys=%x, nmap=%p", nss_ctx->id,
 			nss_ctx, nss_ctx->vphys, nss_ctx->vmap, nss_ctx->nphys, nss_ctx->nmap);
 
-	err = nss_hal_alloc_rings(nss_ctx);
-	if (err) {
-		nss_warning("%p: failed to allocate data/cmd rings\n", nss_ctx);
+	if (!nss_meminfo_init(nss_ctx)) {
+		nss_info_always("%p: meminfo init failed\n", nss_ctx);
 		goto err_init;
 	}
 
@@ -462,9 +359,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();
@@ -526,6 +420,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();
@@ -694,8 +593,6 @@
 		nss_hal_clean_up_netdevice(&nss_ctx->int_ctx[i]);
 	}
 
-	nss_hal_free_rings(nss_ctx);
-
 err_init:
 	if (nss_dev->dev.of_node) {
 		if (npd->nmap) {
@@ -752,8 +649,6 @@
 	fab_scaling_unregister(nss_core0_clk);
 #endif
 
-	nss_hal_free_rings(nss_ctx);
-
 	if (nss_dev->dev.of_node) {
 		if (nss_ctx->nmap) {
 			iounmap(nss_ctx->nmap);
diff --git a/nss_ipsec.c b/nss_ipsec.c
index 9767218..139499d 100644
--- a/nss_ipsec.c
+++ b/nss_ipsec.c
@@ -141,7 +141,7 @@
 	 * Is this a notification? if, yes then fill up the callback and app_data from
 	 * locally stored state
 	 */
-	if (ncm->response == NSS_CMM_RESPONSE_NOTIFY) {
+	if (ncm->response == NSS_CMN_RESPONSE_NOTIFY) {
 		ncm->cb = nss_ipsec_get_msg_callback(nss_ctx, if_num);
 		ncm->app_data = nss_ipsec_get_msg_ctx(nss_ctx, if_num);
 	}
diff --git a/nss_ipv4.c b/nss_ipv4.c
index 965d87e..ccd2a43 100644
--- a/nss_ipv4.c
+++ b/nss_ipv4.c
@@ -126,7 +126,7 @@
 	 * Update the callback and app_data for NOTIFY messages, IPv4 sends all notify messages
 	 * to the same callback/app_data.
 	 */
-	if (nim->cm.response == NSS_CMM_RESPONSE_NOTIFY) {
+	if (nim->cm.response == NSS_CMN_RESPONSE_NOTIFY) {
 		ncm->cb = (nss_ptr_t)nss_ctx->nss_top->ipv4_callback;
 		ncm->app_data = (nss_ptr_t)nss_ctx->nss_top->ipv4_ctx;
 	}
diff --git a/nss_ipv4_log.c b/nss_ipv4_log.c
index 0f5d067..0eed33a 100644
--- a/nss_ipv4_log.c
+++ b/nss_ipv4_log.c
@@ -1,6 +1,6 @@
 /*
  **************************************************************************
- * Copyright (c) 2016, 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.
@@ -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,
@@ -327,7 +326,7 @@
 		return;
 	}
 
-	if (nim->cm.response == NSS_CMM_RESPONSE_NOTIFY || (nim->cm.response == NSS_CMN_RESPONSE_ACK)) {
+	if (nim->cm.response == NSS_CMN_RESPONSE_NOTIFY || (nim->cm.response == NSS_CMN_RESPONSE_ACK)) {
 		nss_info("%p: type[%d]:%s, response[%d]:%s\n", nim, nim->cm.type,
 			nss_ipv4_log_message_types_str[nim->cm.type],
 			nim->cm.response, nss_cmn_response_str[nim->cm.response]);
diff --git a/nss_ipv6.c b/nss_ipv6.c
index 61c2ed1..850ba49 100644
--- a/nss_ipv6.c
+++ b/nss_ipv6.c
@@ -128,7 +128,7 @@
 	 * Update the callback and app_data for NOTIFY messages, IPv6 sends all notify messages
 	 * to the same callback/app_data.
 	 */
-	if (nim->cm.response == NSS_CMM_RESPONSE_NOTIFY) {
+	if (nim->cm.response == NSS_CMN_RESPONSE_NOTIFY) {
 		ncm->cb = (nss_ptr_t)nss_ctx->nss_top->ipv6_callback;
 		ncm->app_data = (nss_ptr_t)nss_ctx->nss_top->ipv6_ctx;
 	}
diff --git a/nss_ipv6_log.c b/nss_ipv6_log.c
index 02e6d59..c1cc076 100644
--- a/nss_ipv6_log.c
+++ b/nss_ipv6_log.c
@@ -1,6 +1,6 @@
 /*
  **************************************************************************
- * Copyright (c) 2016, 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.
@@ -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,
@@ -359,7 +358,7 @@
 		return;
 	}
 
-	if (nim->cm.response == NSS_CMM_RESPONSE_NOTIFY || (nim->cm.response == NSS_CMN_RESPONSE_ACK)) {
+	if (nim->cm.response == NSS_CMN_RESPONSE_NOTIFY || (nim->cm.response == NSS_CMN_RESPONSE_ACK)) {
 		nss_info("%p: type[%d]: %s, response[%d]: %s\n", nim, nim->cm.type,
 			nss_ipv6_log_message_types_str[nim->cm.type],
 			nim->cm.response, nss_cmn_response_str[nim->cm.response]);
diff --git a/nss_l2tpv2.c b/nss_l2tpv2.c
index af2c7c7..b874b01 100644
--- a/nss_l2tpv2.c
+++ b/nss_l2tpv2.c
@@ -110,7 +110,7 @@
 	 * Update the callback and app_data for NOTIFY messages, l2tpv2 sends all notify messages
 	 * to the same callback/app_data.
 	 */
-	if (ncm->response == NSS_CMM_RESPONSE_NOTIFY) {
+	if (ncm->response == NSS_CMN_RESPONSE_NOTIFY) {
 		ncm->cb = (nss_ptr_t)nss_ctx->nss_top->l2tpv2_msg_callback;
 	}
 
diff --git a/nss_lag.c b/nss_lag.c
index 625ce4d..23aa0da 100644
--- a/nss_lag.c
+++ b/nss_lag.c
@@ -165,7 +165,7 @@
 	 * Update the callback and app_data for NOTIFY messages.
 	 * LAG sends all notify messages to the same callback.
 	 */
-	if (ncm->response == NSS_CMM_RESPONSE_NOTIFY) {
+	if (ncm->response == NSS_CMN_RESPONSE_NOTIFY) {
 		ncm->cb = (nss_ptr_t)nss_ctx->nss_top->lag_event_callback;
 	}
 
diff --git a/nss_log.c b/nss_log.c
index d9b0ba2..4cf0795 100644
--- a/nss_log.c
+++ b/nss_log.c
@@ -354,7 +354,7 @@
 	/*
 	 * Update the callback and app_data for NOTIFY messages.
 	 */
-	if (ncm->response == NSS_CMM_RESPONSE_NOTIFY) {
+	if (ncm->response == NSS_CMN_RESPONSE_NOTIFY) {
 		ncm->cb = (nss_ptr_t)nss_debug_interface_cb;
 		ncm->app_data = (nss_ptr_t)nss_debug_interface_app_data;
 	}
diff --git a/nss_map_t.c b/nss_map_t.c
index f316dad..30ecf2a 100644
--- a/nss_map_t.c
+++ b/nss_map_t.c
@@ -148,7 +148,7 @@
 	 * Update the callback and app_data for NOTIFY messages, map_t sends all notify messages
 	 * to the same callback/app_data.
 	 */
-	if (ncm->response == NSS_CMM_RESPONSE_NOTIFY) {
+	if (ncm->response == NSS_CMN_RESPONSE_NOTIFY) {
 		ncm->cb = (nss_ptr_t)nss_ctx->nss_top->map_t_msg_callback;
 		ncm->app_data = (nss_ptr_t)nss_ctx->subsys_dp_register[ncm->interface].app_data;
 	}
diff --git a/nss_meminfo.c b/nss_meminfo.c
new file mode 100644
index 0000000..2028948
--- /dev/null
+++ b/nss_meminfo.c
@@ -0,0 +1,685 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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_meminfo.c
+ *	NSS meminfo subsystem
+ */
+
+#include <linux/seq_file_net.h>
+#include "nss_tx_rx_common.h"
+#include "nss_core.h"
+#include "nss_arch.h"
+#include "nss_meminfo.h"
+
+/*
+ * Store user configuration
+ */
+static char nss_meminfo_user_config[NSS_MEMINFO_USER_CONFIG_MAXLEN];
+module_param_string(meminfo_user_config, nss_meminfo_user_config,
+		    NSS_MEMINFO_USER_CONFIG_MAXLEN, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
+MODULE_PARM_DESC(nss_meminfo_user_config, "meminfo user configuration");
+
+static bool nss_meminfo_debugfs_exist;
+
+/*
+ * Name table of memory type presented to user.
+ */
+char *nss_meminfo_memtype_table[NSS_MEMINFO_MEMTYPE_MAX] = {"IMEM", "SDRAM"};
+
+/*
+ * nss_meminfo_alloc_sdram()
+ *	Allocate a SDRAM block.
+ */
+static unsigned long nss_meminfo_alloc_sdram(struct nss_ctx_instance *nss_ctx, uint32_t size)
+{
+	unsigned long addr = 0;
+
+	/*
+	 * kmalloc() return cache line aligned buffer.
+	 */
+	addr = (unsigned long)kmalloc(size, GFP_KERNEL | __GFP_ZERO);
+	if (!addr)
+		nss_info_always("%p: failed to alloc a sdram block of size %u\n", nss_ctx, size);
+
+	return addr;
+}
+
+/*
+ * nss_meminfo_free_sdram()
+ *	Free SDRAM memory.
+ */
+static inline void nss_meminfo_free_sdram(struct nss_ctx_instance *nss_ctx, uint32_t dma_addr,
+						unsigned long kern_addr, uint32_t size)
+{
+	/*
+	 * Unmap it since every SDRAM memory had been mapped.
+	 */
+	dma_unmap_single(nss_ctx->dev, dma_addr, size, DMA_FROM_DEVICE);
+	kfree((void *)kern_addr);
+}
+
+/*
+ * nss_meminfo_alloc_imem()
+ *	Allocate an IMEM block in a sequential way.
+ */
+static uint32_t nss_meminfo_alloc_imem(struct nss_ctx_instance *nss_ctx, uint32_t size, int alignment)
+{
+	struct nss_meminfo_ctx *mem_ctx = &nss_ctx->meminfo_ctx;
+	uint32_t new_tail;
+	uint32_t addr = 0;
+	int mask;
+
+	mask = alignment - 1;
+
+	/*
+	 * Alignment has to be a power of 2.
+	 */
+	nss_assert(!(alignment & mask));
+
+	new_tail = mem_ctx->imem_tail;
+
+	/*
+	 * Align up the address if it not aligned.
+	 */
+	if (new_tail & mask)
+		new_tail = (new_tail + mask) & ~mask;
+
+	if (size > (mem_ctx->imem_end - new_tail)) {
+		nss_info_always("%p: failed to alloc an IMEM block of size %u\n", nss_ctx, size);
+		return addr;
+	}
+
+	addr = new_tail;
+	mem_ctx->imem_tail = new_tail + size;
+
+	return addr;
+}
+
+/*
+ * nss_meminfo_free_imem()
+ *	Free an IMEM block. Ignore the padding bytes for alignment requirement.
+ */
+static void nss_meminfo_free_imem(struct nss_ctx_instance *nss_ctx, uint32_t addr, uint32_t size)
+{
+	struct nss_meminfo_ctx *mem_ctx = &nss_ctx->meminfo_ctx;
+	mem_ctx->imem_tail -= size;
+}
+
+/*
+ * nss_meminfo_if_user_overwrite()
+ *	Return user configured memory type. Otherwise, return -1.
+ */
+static int nss_meminfo_if_user_overwrite(struct nss_ctx_instance *nss_ctx, const char *name)
+{
+	char *user_config;
+	char **mtype_table;
+	char needle[NSS_MEMINFO_BLOCK_NAME_MAXLEN + 6];
+	char user_choice[NSS_MEMINFO_MEMTYPE_NAME_MAXLEN];
+	int i;
+	char *p;
+
+	user_config = nss_meminfo_user_config;
+	mtype_table = nss_meminfo_memtype_table;
+
+	snprintf(needle, sizeof(needle), "<%1d, %s, ", nss_ctx->id, name);
+
+	p = strstr(user_config, needle);
+	if (!p)
+		return -1;
+
+	p += strlen(needle);
+
+	for (i = 0; i < NSS_MEMINFO_MEMTYPE_NAME_MAXLEN - 1; i++) {
+		/*
+		 * Each user config is like <core_id, object_name, memory_type>,
+		 * it starts with '<' and ends with '>'.
+		 */
+		if (*p == '>' || *p == '\0')
+			break;
+		user_choice[i] = *p;
+		p++;
+	}
+
+	user_choice[i] = '\0';
+
+	for (i = 0; i < NSS_MEMINFO_MEMTYPE_MAX; i++)
+		if (!strcmp(mtype_table[i], user_choice))
+			return i;
+
+	return -1;
+}
+
+/*
+ * nss_meminfo_free_block_lists()
+ *	Free block node and memory associated with each each memory object.
+ */
+static void nss_meminfo_free_block_lists(struct nss_ctx_instance *nss_ctx)
+{
+	struct nss_meminfo_ctx *mem_ctx;
+	struct nss_meminfo_block_list *l;
+	int i;
+
+	mem_ctx = &nss_ctx->meminfo_ctx;
+	for (i = 0; i < NSS_MEMINFO_MEMTYPE_MAX; i++) {
+		struct nss_meminfo_block *b;
+		l = &mem_ctx->block_lists[i];
+		b = l->head;
+		while (b) {
+			struct nss_meminfo_block *tmp;
+			/*
+			 * Free IMEM/SDRAM memory.
+			 */
+			switch (i) {
+			case NSS_MEMINFO_MEMTYPE_IMEM:
+				nss_meminfo_free_imem(nss_ctx, b->dma_addr, b->size);
+				break;
+			case NSS_MEMINFO_MEMTYPE_SDRAM:
+				nss_meminfo_free_sdram(nss_ctx, b->dma_addr, b->kern_addr, b->size);
+				break;
+			}
+
+			/*
+			 * Free the struct nss_meminfo_block itself.
+			 */
+			tmp = b;
+			b = b->next;
+			kfree(tmp);
+		}
+	}
+}
+
+/*
+ * nss_meminfo_init_block_lists()
+ *	Initialize block lists and allocate memory for each block.
+ */
+static bool nss_meminfo_init_block_lists(struct nss_ctx_instance *nss_ctx)
+{
+	struct nss_meminfo_ctx *mem_ctx;
+	struct nss_meminfo_block_list *l;
+	struct nss_meminfo_request *r;
+	struct nss_meminfo_map *map;
+	int mtype;
+	unsigned long kern_addr;
+	uint32_t dma_addr;
+	int i;
+
+	mem_ctx = &nss_ctx->meminfo_ctx;
+
+	/*
+	 * Fill memory type for each block list.
+	 */
+	for (i = 0; i < NSS_MEMINFO_MEMTYPE_MAX; i++)
+		mem_ctx->block_lists[i].memtype = i;
+
+	map = &mem_ctx->meminfo_map;
+
+	/*
+	 * Loop through all meminfo requests by checking the per-request magic.
+	 */
+	for (r = map->requests; r->magic == NSS_MEMINFO_REQUEST_MAGIC; r++) {
+		struct nss_meminfo_block *b = (struct nss_meminfo_block *)
+						kmalloc(sizeof(struct nss_meminfo_block), GFP_KERNEL);
+		if (!b) {
+			nss_info_always("%p: failed to allocate meminfo block\n", nss_ctx);
+			goto cleanup;
+		}
+
+		b->index = map->num_requests++;
+		b->size = r->size;
+
+		/*
+		 * Look up the user-defined memory type.
+		 * Return user-defined memory type if exists. Otherwise, return -1.
+		 */
+		mtype = nss_meminfo_if_user_overwrite(nss_ctx, r->name);
+		if (mtype == -1)
+			mtype = r->memtype_default;
+		r->memtype_user = mtype;
+
+		switch (mtype) {
+		case NSS_MEMINFO_MEMTYPE_IMEM:
+			/*
+			 * Return SoC real address for IMEM as DMA address.
+			 */
+			dma_addr = nss_meminfo_alloc_imem(nss_ctx, r->size, r->alignment);
+			if (!dma_addr) {
+				nss_info_always("%p: failed to alloc IMEM block\n", nss_ctx);
+				goto cleanup;
+			}
+
+			/*
+			 * Calulate offset to the kernel address (vmap) where the
+			 * whole IMEM is mapped onto instead of calling ioremap().
+			 */
+			kern_addr = (unsigned long)nss_ctx->vmap + dma_addr - nss_ctx->vphys;
+			break;
+		case NSS_MEMINFO_MEMTYPE_SDRAM:
+			kern_addr = nss_meminfo_alloc_sdram(nss_ctx, r->size);
+			if (!kern_addr) {
+				nss_info_always("%p: failed to alloc SDRAM block\n", nss_ctx);
+				goto cleanup;
+			}
+
+			dma_addr = dma_map_single(nss_ctx->dev, (void *)kern_addr, r->size, DMA_TO_DEVICE);
+			if (unlikely(dma_mapping_error(nss_ctx->dev, dma_addr))) {
+				nss_info_always("%p: failed to map SDRAM block\n", nss_ctx);
+				goto cleanup;
+			}
+			break;
+		default:
+			nss_info_always("%p: %d unsupported memory type\n", nss_ctx, mtype);
+			goto cleanup;
+		}
+
+		/*
+		 * Update the request with DMA address for the memory that only be used by FW.
+		 */
+		r->addr = dma_addr;
+
+		/*
+		 * nss_if_mem_map settings
+		 */
+		if (!strcmp(r->name, "nss_if_mem_map_inst")) {
+			mem_ctx->if_map_memtype = mtype;
+			mem_ctx->if_map_dma = dma_addr;
+			mem_ctx->if_map = (struct nss_if_mem_map *)kern_addr;
+		}
+
+		/*
+		 * Flush the updated meminfo request.
+		 */
+		NSS_CORE_DMA_CACHE_MAINT(r, sizeof(struct nss_meminfo_request), DMA_TO_DEVICE);
+		NSS_CORE_DSB();
+
+		/*
+		 * Update the list
+		 */
+		l = &mem_ctx->block_lists[mtype];
+		l->num_blks++;
+		l->total_size += r->size;
+
+		b->next = l->head;
+		l->head = b;
+	}
+
+	/*
+	 * Verify memory map end magic
+	 */
+	if (*((uint16_t *)r) != NSS_MEMINFO_MAP_END_MAGIC)
+		goto cleanup;
+
+	return true;
+
+cleanup:
+	nss_meminfo_free_block_lists(nss_ctx);
+	return false;
+}
+
+/*
+ * nss_meminfo_init_imem()
+ *	Initialize IMEM information.
+ */
+static void nss_meminfo_init_imem(struct nss_ctx_instance *nss_ctx)
+{
+	struct nss_meminfo_ctx *mem_ctx = &nss_ctx->meminfo_ctx;
+
+	mem_ctx->imem_head = NSS_IMEM_START + NSS_IMEM_SIZE * nss_ctx->id;
+	mem_ctx->imem_end = mem_ctx->imem_head + NSS_IMEM_SIZE;
+	mem_ctx->imem_tail = mem_ctx->imem_head;
+
+	nss_info("%p: IMEM init: head: 0x%x end: 0x%x tail: 0x%x\n", nss_ctx,
+		 mem_ctx->imem_head, mem_ctx->imem_end, mem_ctx->imem_tail);
+}
+
+
+/*
+ * nss_meminfo_allocate_n2h_h2n_rings()
+ *	Allocate N2H/H2N rings.
+ */
+static bool nss_meminfo_allocate_n2h_h2n_rings(struct nss_ctx_instance *nss_ctx,
+						struct nss_meminfo_n2h_h2n_info *info)
+{
+	switch (info->memtype) {
+	case NSS_MEMINFO_MEMTYPE_SDRAM:
+		info->kern_addr = nss_meminfo_alloc_sdram(nss_ctx, info->total_size);
+		if (!info->kern_addr)
+			return false;
+
+		info->dma_addr = dma_map_single(nss_ctx->dev, (void *)info->kern_addr,
+						info->total_size, DMA_TO_DEVICE);
+		if (unlikely(dma_mapping_error(nss_ctx->dev, info->dma_addr))) {
+			kfree((void *)info->kern_addr);
+			return false;
+		}
+		break;
+	case NSS_MEMINFO_MEMTYPE_IMEM:
+		info->dma_addr = nss_meminfo_alloc_imem(nss_ctx, info->total_size, L1_CACHE_BYTES);
+		if (!info->dma_addr)
+			return false;
+
+		info->kern_addr = (unsigned long)(nss_ctx->vmap) + info->dma_addr - nss_ctx->vphys;
+		break;
+	default:
+		return false;
+	}
+
+	return true;
+}
+
+/*
+ * nss_meminfo_configure_n2h_h2n_rings()
+ *	Configure N2H/H2N rings and if_map.
+ */
+static bool nss_meminfo_configure_n2h_h2n_rings(struct nss_ctx_instance *nss_ctx)
+{
+	struct nss_meminfo_ctx *mem_ctx = &nss_ctx->meminfo_ctx;
+	struct nss_meminfo_n2h_h2n_info *h2n_info;
+	struct nss_meminfo_n2h_h2n_info *n2h_info;
+	struct nss_if_mem_map *if_map;
+	int i;
+	int mtype;
+
+	h2n_info = &mem_ctx->h2n_info;
+	n2h_info = &mem_ctx->n2h_info;
+
+	/*
+	 * Check memory type. SDRAM is the default option.
+	 */
+	mtype = nss_meminfo_if_user_overwrite(nss_ctx, "h2n_rings");
+	if (mtype == -1)
+		mtype = NSS_MEMINFO_MEMTYPE_SDRAM;
+
+	h2n_info->memtype = mtype;
+
+	mtype = nss_meminfo_if_user_overwrite(nss_ctx, "n2h_rings");
+	if (mtype == -1)
+		mtype = NSS_MEMINFO_MEMTYPE_SDRAM;
+
+	n2h_info->memtype = mtype;
+
+	n2h_info->total_size = sizeof(struct n2h_descriptor) * NSS_N2H_RING_COUNT * (NSS_RING_SIZE + 2);
+	h2n_info->total_size = sizeof(struct h2n_descriptor) * NSS_H2N_RING_COUNT * (NSS_RING_SIZE + 2);
+
+	/*
+	 * N2H ring allocations
+	 */
+	if (!(nss_meminfo_allocate_n2h_h2n_rings(nss_ctx, n2h_info))) {
+		nss_info_always("%p: failed to allocate/map n2h rings\n", nss_ctx);
+		return false;
+	}
+
+	/*
+	 * H2N ring allocations
+	 */
+	if (!(nss_meminfo_allocate_n2h_h2n_rings(nss_ctx, h2n_info))) {
+		nss_info_always("%p: failed to allocate/map h2n_rings\n", nss_ctx);
+		goto cleanup;
+	}
+
+	/*
+	 * Bring a fresh copy of if_map from memory in order to read it correctly.
+	 */
+	if_map = mem_ctx->if_map;
+	NSS_CORE_DMA_CACHE_MAINT((void *)if_map, sizeof(struct nss_if_mem_map), DMA_FROM_DEVICE);
+	NSS_CORE_DSB();
+
+	if_map->n2h_rings = NSS_N2H_RING_COUNT;
+	if_map->h2n_rings = NSS_H2N_RING_COUNT;
+
+	/*
+	 * N2H ring settings
+	 */
+	for (i = 0; i < NSS_N2H_RING_COUNT; i++) {
+		struct hlos_n2h_desc_ring *n2h_desc_ring = &nss_ctx->n2h_desc_ring[i];
+		n2h_desc_ring->desc_ring.desc = (struct n2h_descriptor *)(n2h_info->kern_addr + i * sizeof(struct n2h_descriptor) * (NSS_RING_SIZE + 2));
+		n2h_desc_ring->desc_ring.size = NSS_RING_SIZE;
+		n2h_desc_ring->hlos_index = if_map->n2h_hlos_index[i];
+
+		if_map->n2h_desc_if[i].size = NSS_RING_SIZE;
+		if_map->n2h_desc_if[i].desc_addr = n2h_info->dma_addr + i * sizeof(struct n2h_descriptor) * (NSS_RING_SIZE + 2);
+		nss_info("%p: N2H ring %d, size %d, addr = %x\n", nss_ctx, i, if_map->n2h_desc_if[i].size, if_map->n2h_desc_if[i].desc_addr);
+	}
+
+	/*
+	 * H2N ring settings
+	 */
+	for (i = 0; i < NSS_H2N_RING_COUNT; i++) {
+		struct hlos_h2n_desc_rings *h2n_desc_ring = &nss_ctx->h2n_desc_rings[i];
+		h2n_desc_ring->desc_ring.desc = (struct h2n_descriptor *)(h2n_info->kern_addr + i * sizeof(struct h2n_descriptor) * (NSS_RING_SIZE + 2));
+		h2n_desc_ring->desc_ring.size = NSS_RING_SIZE;
+		h2n_desc_ring->hlos_index = if_map->h2n_hlos_index[i];
+		spin_lock_init(&h2n_desc_ring->lock);
+
+		if_map->h2n_desc_if[i].size = NSS_RING_SIZE;
+		if_map->h2n_desc_if[i].desc_addr = h2n_info->dma_addr + i * sizeof(struct h2n_descriptor) * (NSS_RING_SIZE + 2);
+		nss_info("%p: H2N ring %d, size %d, addr = %x\n", nss_ctx, i, if_map->h2n_desc_if[i].size, if_map->h2n_desc_if[i].desc_addr);
+	}
+
+	/*
+	 * Flush the updated nss_if_mem_map.
+	 */
+	NSS_CORE_DMA_CACHE_MAINT((void *)if_map, sizeof(struct nss_if_mem_map), DMA_TO_DEVICE);
+	NSS_CORE_DSB();
+
+	return true;
+
+cleanup:
+	if (n2h_info->memtype == NSS_MEMINFO_MEMTYPE_SDRAM)
+		nss_meminfo_free_sdram(nss_ctx, n2h_info->dma_addr, n2h_info->kern_addr, n2h_info->total_size);
+	else
+		nss_meminfo_free_imem(nss_ctx, n2h_info->dma_addr, n2h_info->total_size);
+
+	nss_meminfo_free_block_lists(nss_ctx);
+	return false;
+}
+
+/*
+ * nss_meminfo_config_show()
+ *	function to show meinfo configuration per core.
+ */
+static int nss_meminfo_config_show(struct seq_file *seq, void *v)
+{
+	struct nss_ctx_instance *nss_ctx;
+	struct nss_meminfo_ctx *mem_ctx;
+	struct nss_meminfo_n2h_h2n_info *n2h_info;
+	struct nss_meminfo_n2h_h2n_info *h2n_info;
+	struct nss_meminfo_map *map;
+	struct nss_meminfo_request *r;
+	int nss_id;
+	int i;
+
+	/*
+	 * i_private is passed to us by debug_fs_create()
+	 */
+	nss_id = (int)(nss_ptr_t)seq->private;
+	if (nss_id < 0 || nss_id >= NSS_MAX_CORES) {
+		nss_warning("nss_id: %d is not valid\n", nss_id);
+		return -ENODEV;
+	}
+
+	nss_ctx = &nss_top_main.nss[nss_id];
+	NSS_VERIFY_CTX_MAGIC(nss_ctx);
+
+	mem_ctx = &nss_ctx->meminfo_ctx;
+	map = &mem_ctx->meminfo_map;
+	n2h_info = &mem_ctx->n2h_info;
+	h2n_info = &mem_ctx->h2n_info;
+
+	seq_printf(seq, "%-5s %-32s %-7s %-7s %-10s %-10s\n",
+			"Index", "Name", "Default", "User", "Size", "DMA Addr");
+	seq_printf(seq, "%-5s %-32s %-7s %-7s 0x%-8x 0x%-8x\n",
+			"N/A", "n2h_rings", "SDRAM",
+			nss_meminfo_memtype_table[n2h_info->memtype],
+			n2h_info->total_size, n2h_info->dma_addr);
+	seq_printf(seq, "%-5s %-32s %-7s %-7s 0x%-8x 0x%-8x\n",
+			"N/A", "h2n_rings", "SDRAM",
+			nss_meminfo_memtype_table[h2n_info->memtype],
+			h2n_info->total_size, h2n_info->dma_addr);
+
+	r = map->requests;
+	for (i = 0; i < map->num_requests; i++) {
+		seq_printf(seq, "%-5d %-32s %-7s %-7s 0x%-8x 0x%-8x\n",
+				i, r[i].name,
+				nss_meminfo_memtype_table[r[i].memtype_default],
+				nss_meminfo_memtype_table[r[i].memtype_user],
+				r[i].size, r[i].addr);
+	}
+
+	seq_printf(seq, "Available IMEM: 0x%x\n", mem_ctx->imem_end - mem_ctx->imem_tail);
+	seq_printf(seq, "How to configure? \n");
+	seq_printf(seq, "Overwrite the /etc/modules.d/32-qca-nss-drv with following contents then reboot\n\n");
+	seq_printf(seq, "qca-nss-drv meminfo_user_config=\"<core_id, name, memory_type>, ..\"\n\n");
+	seq_printf(seq, "For example, <1, h2n_rings, IMEM> stands for: h2n_rings of core 1 is on IMEM\n");
+
+	return 0;
+}
+
+/*
+ * nss_meminfo_debugfs_file_open()
+ *	function to open meminfo debugfs.
+ */
+static int nss_meminfo_debugfs_file_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, nss_meminfo_config_show, inode->i_private);
+}
+
+static struct file_operations nss_meminfo_debugfs_ops = {
+	.owner   = THIS_MODULE,
+	.open    = nss_meminfo_debugfs_file_open,
+	.read    = seq_read,
+	.llseek  = seq_lseek,
+	.release = single_release,
+};
+
+/*
+ * nss_meminfo_init_debugfs()
+ *	Init meminfo debugfs.
+ */
+static void nss_meminfo_init_debugfs(struct nss_ctx_instance *nss_ctx)
+{
+	int i;
+	struct dentry *meminfo_main_dentry;
+	struct dentry *meminfo_core_dentries[NSS_MAX_CORES];
+
+	if (nss_meminfo_debugfs_exist)
+		return;
+
+	/*
+	 * Create directory for showing meminfo configuration of each core.
+	 */
+	meminfo_main_dentry = debugfs_create_dir("meminfo", nss_top_main.top_dentry);
+	if (unlikely(!meminfo_main_dentry)) {
+		nss_warning("Failed to create qca-nss-drv/meminfo directory in debugfs\n");
+		return;
+	}
+
+	for (i = 0; i < NSS_MAX_CORES; i++) {
+		char file[10];
+		snprintf(file, sizeof(file), "core%d", i);
+		meminfo_core_dentries[i] = debugfs_create_file(file, 0400, meminfo_main_dentry,
+						(void *)(nss_ptr_t)i, &nss_meminfo_debugfs_ops);
+		if (unlikely(!meminfo_core_dentries[i])) {
+			int j;
+			for (j = 0; j < i; j++)
+				debugfs_remove(meminfo_core_dentries[j]);
+			debugfs_remove(meminfo_main_dentry);
+			nss_warning("Failed to create qca-nss-drv/meminfo/%s file in debugfs", file);
+			return;
+		}
+	}
+
+	nss_meminfo_debugfs_exist = true;
+	nss_info("nss meminfo user config: %s\n", nss_meminfo_user_config);
+}
+
+/*
+ * nss_meminfo_init
+ *	Initilization
+ *
+ */
+bool nss_meminfo_init(struct nss_ctx_instance *nss_ctx)
+{
+	struct nss_meminfo_ctx *mem_ctx;
+	uint32_t *meminfo_start;
+	struct nss_meminfo_map *map;
+
+	NSS_VERIFY_CTX_MAGIC(nss_ctx);
+	mem_ctx = &nss_ctx->meminfo_ctx;
+
+	/*
+	 * meminfo_start is the label where the start address of meminfo map is stored.
+	 */
+	meminfo_start = (uint32_t *)ioremap_nocache(nss_ctx->load + NSS_MEMINFO_MAP_START_OFFSET,
+							NSS_MEMINFO_RESERVE_AREA_SIZE);
+	if (!meminfo_start) {
+		nss_info_always("%p: cannot remap meminfo start\n", nss_ctx);
+		return false;
+	}
+
+	/*
+	 * Check meminfo start magic
+	 */
+	if ((uint16_t)meminfo_start[0] != NSS_MEMINFO_RESERVE_AREA_MAGIC) {
+		nss_info_always("%p: failed to verify meminfo start magic\n", nss_ctx);
+		return false;
+	}
+
+	map = &mem_ctx->meminfo_map;
+	map->start = (uint32_t *)ioremap_cache(meminfo_start[1], NSS_MEMINFO_MAP_SIZE);
+	if (!map->start) {
+		nss_info_always("%p: failed to remap meminfo map\n", nss_ctx);
+		return false;
+	}
+
+	/*
+	 * Check meminfo map magic
+	 */
+	if ((uint16_t)map->start[0] != NSS_MEMINFO_MAP_START_MAGIC) {
+		nss_info_always("%p: failed to verify meminfo map magic\n", nss_ctx);
+		return false;
+	}
+
+	/*
+	 * Meminfo map settings
+	 */
+	map->num_requests = 0;
+	map->requests = (struct nss_meminfo_request *)(map->start + 1);
+
+	/*
+	 * Init IMEM
+	 */
+	nss_meminfo_init_imem(nss_ctx);
+
+	/*
+	 * Init meminfo block lists
+	 */
+	if (!nss_meminfo_init_block_lists(nss_ctx)) {
+		nss_info_always("%p: failed to initialize meminfo block lists\n", nss_ctx);
+		return false;
+	}
+
+	/*
+	 * Configure N2H/H2N rings and nss_if_mem_map
+	 */
+	if (!nss_meminfo_configure_n2h_h2n_rings(nss_ctx))
+		return false;
+
+	nss_meminfo_init_debugfs(nss_ctx);
+
+	nss_info_always("%p: meminfo init succeed\n", nss_ctx);
+	return true;
+}
diff --git a/nss_meminfo.h b/nss_meminfo.h
new file mode 100644
index 0000000..bd7a8d7
--- /dev/null
+++ b/nss_meminfo.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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_meminfo.h
+ *	nss meminfo header file.
+ */
+
+#ifndef __NSS_MEMINFO_H
+#define __NSS_MEMINFO_H
+
+#define NSS_MEMINFO_RESERVE_AREA_SIZE	0x1000	/* Size of reserved space in firmware start code aligned to one page */
+#define NSS_MEMINFO_RESERVE_AREA_MAGIC	0x9526	/* Magic at the beginning of reserved space */
+#define NSS_MEMINFO_MAP_START_OFFSET	8	/* Offset of memory map start address in reserved space */
+#define NSS_MEMINFO_MAP_SIZE		0x1000	/* Size of memory map per core aligned to one page */
+#define NSS_MEMINFO_MAP_START_MAGIC	0x9527
+#define NSS_MEMINFO_REQUEST_MAGIC	0X9528
+#define NSS_MEMINFO_MAP_END_MAGIC	0x9529
+#define NSS_MEMINFO_BLOCK_NAME_MAXLEN	48
+#define NSS_MEMINFO_MEMTYPE_NAME_MAXLEN	32
+#define NSS_MEMINFO_USER_CONFIG_MAXLEN	1024
+
+/*
+ * Memory types available
+ */
+enum nss_meminfo_memtype {
+	NSS_MEMINFO_MEMTYPE_IMEM,	/* NSS-IMEM also called TCM */
+	NSS_MEMINFO_MEMTYPE_SDRAM,	/* SDRAM also called DDR */
+	NSS_MEMINFO_MEMTYPE_MAX
+};
+
+/*
+ * Memory request
+ * Firmware package defines each request asking host to feed the request.
+ */
+struct nss_meminfo_request {
+	uint16_t magic;					/* Request magic */
+	char name[NSS_MEMINFO_BLOCK_NAME_MAXLEN];	/* Memory block name */
+	uint16_t memtype_default;			/* Memory type requested */
+	uint16_t memtype_user;				/* User-defined memory type */
+	uint32_t alignment;				/* Alignment requirement */
+	uint32_t size;					/* Size requested */
+	uint32_t addr;					/* Memory block address got from host */
+};
+
+/*
+ * Memory map
+ * It starts with a magic then an array of memory request and end with a checksum.
+ * Firmware creates the map for host to parse.
+ */
+struct nss_meminfo_map {
+	uint32_t *start;				/* Start address */
+	uint32_t num_requests;				/* Number of requests */
+	struct nss_meminfo_request *requests;		/* Start of Request array */
+};
+
+/*
+ * Memory block
+ * Block node for each request.
+ */
+struct nss_meminfo_block {
+	struct nss_meminfo_block *next;	/* Next block in the same list */
+	uint32_t index;			/* Index to request array */
+	uint32_t size;			/* Size of memory block */
+	uint32_t dma_addr;		/* DMA address */
+	unsigned long kern_addr;	/* Kernel address */
+};
+
+/*
+ * Memory block list
+ * List of block node of same memory type.
+ */
+struct nss_meminfo_block_list {
+	enum nss_meminfo_memtype memtype;	/* memory type */
+	uint32_t num_blks;			/* Number of blocks */
+	uint32_t total_size;			/* Size of all memory blocks in this list */
+	struct nss_meminfo_block *head;		/* list head */
+};
+
+/*
+ * H2N/N2H rings information
+ */
+struct nss_meminfo_n2h_h2n_info {
+	enum nss_meminfo_memtype memtype;	/* Memory type */
+	uint32_t total_size;			/* Total size */
+	uint32_t dma_addr;			/* DMA address */
+	unsigned long kern_addr;		/* Kernel address */
+};
+
+/*
+ * Memory context
+ */
+struct nss_meminfo_ctx {
+	struct nss_meminfo_n2h_h2n_info n2h_info;	/* N2H rings info*/
+	struct nss_meminfo_n2h_h2n_info h2n_info;	/* H2N rings info */
+	uint32_t imem_head;				/* IMEM start address */
+	uint32_t imem_end;				/* IMEM end address */
+	uint32_t imem_tail;				/* IMEM data end */
+	struct nss_if_mem_map *if_map;			/* nss_if_mem_map_inst virtual address */
+	uint32_t if_map_dma;				/* nss_if_mem_map_inst physical address */
+	enum nss_meminfo_memtype if_map_memtype;	/* Memory type for nss_if_mem_map */
+	struct nss_meminfo_map meminfo_map;		/* Meminfo map */
+	struct nss_meminfo_block_list block_lists[NSS_MEMINFO_MEMTYPE_MAX];
+							/* Block lists for each memory type */
+};
+
+bool nss_meminfo_init(struct nss_ctx_instance *nss_ctx);
+#endif
diff --git a/nss_n2h.c b/nss_n2h.c
index 052282a..d962fa1 100644
--- a/nss_n2h.c
+++ b/nss_n2h.c
@@ -107,10 +107,10 @@
 	 * Update the callback and app_data for NOTIFY messages, n2h sends all notify messages
 	 * to the same callback/app_data.
 	 */
-	if (nnm->cm.response == NSS_CMM_RESPONSE_NOTIFY) {
+	if (nnm->cm.response == NSS_CMN_RESPONSE_NOTIFY) {
 		/*
 		 * Place holder for the user to create right call
-		 * back and app data when response is NSS_CMM_RESPONSE_NOTIFY
+		 * back and app data when response is NSS_CMN_RESPONSE_NOTIFY
 		 */
 		ncm->cb = (nss_ptr_t)nss_n2h_rd[nss_ctx->id].n2h_callback;
 		ncm->app_data = (nss_ptr_t)nss_n2h_rd[nss_ctx->id].app_data;
diff --git a/nss_oam.c b/nss_oam.c
index 57d7992..1e31c1b 100644
--- a/nss_oam.c
+++ b/nss_oam.c
@@ -53,7 +53,7 @@
 	 */
 	nss_core_log_msg_failures(nss_ctx, ncm);
 
-	if (ncm->response == NSS_CMM_RESPONSE_NOTIFY) {
+	if (ncm->response == NSS_CMN_RESPONSE_NOTIFY) {
 		ncm->cb = (nss_ptr_t)nss_top_main.oam_callback;
 		ncm->app_data = (nss_ptr_t)nss_top_main.oam_ctx;
 	}
diff --git a/nss_phys_if.c b/nss_phys_if.c
index a657439..8414285 100644
--- a/nss_phys_if.c
+++ b/nss_phys_if.c
@@ -117,7 +117,7 @@
 	 * Update the callback and app_data for NOTIFY messages, IPv4 sends all notify messages
 	 * to the same callback/app_data.
 	 */
-	if (ncm->response == NSS_CMM_RESPONSE_NOTIFY) {
+	if (ncm->response == NSS_CMN_RESPONSE_NOTIFY) {
 		ncm->cb = (nss_ptr_t)nss_ctx->nss_top->phys_if_msg_callback[ncm->interface];
 		ncm->app_data = (nss_ptr_t)nss_ctx->subsys_dp_register[ncm->interface].ndev;
 	}
diff --git a/nss_portid.c b/nss_portid.c
index 746363e..41c5967 100644
--- a/nss_portid.c
+++ b/nss_portid.c
@@ -81,7 +81,7 @@
 	 * Update the callback and app_data for NOTIFY messages, portid sends all notify messages
 	 * to the same callback/app_data.
 	 */
-	if (ncm->response == NSS_CMM_RESPONSE_NOTIFY) {
+	if (ncm->response == NSS_CMN_RESPONSE_NOTIFY) {
 		ncm->cb = (nss_ptr_t)nss_ctx->nss_top->if_rx_msg_callback[ncm->interface];
 		ncm->app_data = (nss_ptr_t)nss_ctx->subsys_dp_register[ncm->interface].ndev;
 	}
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_pptp.c b/nss_pptp.c
index 4102001..91515e2 100644
--- a/nss_pptp.c
+++ b/nss_pptp.c
@@ -142,7 +142,7 @@
 	 * Update the callback and app_data for NOTIFY messages, pptp sends all notify messages
 	 * to the same callback/app_data.
 	 */
-	if (ncm->response == NSS_CMM_RESPONSE_NOTIFY) {
+	if (ncm->response == NSS_CMN_RESPONSE_NOTIFY) {
 		ncm->cb = (nss_ptr_t)nss_ctx->nss_top->pptp_msg_callback;
 		ncm->app_data =  (nss_ptr_t)nss_ctx->subsys_dp_register[ncm->interface].app_data;
 	}
diff --git a/nss_profiler.c b/nss_profiler.c
index f0fb428..50261b4 100644
--- a/nss_profiler.c
+++ b/nss_profiler.c
@@ -56,7 +56,7 @@
 	/*
 	 * status per request callback
 	 */
-	if (ncm->response != NSS_CMM_RESPONSE_NOTIFY && ncm->cb) {
+	if (ncm->response != NSS_CMN_RESPONSE_NOTIFY && ncm->cb) {
 		nss_info("%p: reply CB %p for %d %d\n", nss_ctx, (void *)ncm->cb, ncm->type, ncm->response);
 		cb = (nss_profiler_callback_t)ncm->cb;
 	}
diff --git a/nss_qrfs.c b/nss_qrfs.c
index e3d1b54..0f694dd 100644
--- a/nss_qrfs.c
+++ b/nss_qrfs.c
@@ -80,7 +80,7 @@
 	/*
 	 * Update the callback and app_data for NOTIFY messages
 	 */
-	if (ncm->response == NSS_CMM_RESPONSE_NOTIFY) {
+	if (ncm->response == NSS_CMN_RESPONSE_NOTIFY) {
 		ncm->cb = (nss_ptr_t)nss_qrfs_notify[nss_ctx->id].qrfs_callback;
 		ncm->app_data = (nss_ptr_t)nss_qrfs_notify[nss_ctx->id].app_data;
 	}
diff --git a/nss_sjack.c b/nss_sjack.c
index d0b13d7..d9ded99 100644
--- a/nss_sjack.c
+++ b/nss_sjack.c
@@ -47,7 +47,7 @@
 	 * Update the callback and app_data for NOTIFY messages, sjack sends all notify messages
 	 * to the same callback/app_data.
 	 */
-	if (ncm->response == NSS_CMM_RESPONSE_NOTIFY) {
+	if (ncm->response == NSS_CMN_RESPONSE_NOTIFY) {
 		ncm->cb = (nss_ptr_t)nss_ctx->nss_top->if_rx_msg_callback[ncm->interface];
 	}
 
diff --git a/nss_trustsec_tx.c b/nss_trustsec_tx.c
index a76bb5f..842fd53 100644
--- a/nss_trustsec_tx.c
+++ b/nss_trustsec_tx.c
@@ -71,7 +71,7 @@
 	 * Update the callback and app_data for NOTIFY messages, trustsec_tx sends all notify messages
 	 * to the same callback/app_data.
 	 */
-	if (ncm->response == NSS_CMM_RESPONSE_NOTIFY) {
+	if (ncm->response == NSS_CMN_RESPONSE_NOTIFY) {
 		ncm->cb = (nss_ptr_t)nss_ctx->nss_top->if_rx_msg_callback[ncm->interface];
 		ncm->app_data = (nss_ptr_t)nss_ctx->subsys_dp_register[ncm->interface].ndev;
 	}
diff --git a/nss_tun6rd.c b/nss_tun6rd.c
index fb8f67b..1900034 100644
--- a/nss_tun6rd.c
+++ b/nss_tun6rd.c
@@ -46,7 +46,7 @@
  	 * Update the callback and app_data for NOTIFY messages, tun6rd sends all notify messages
  	 * to the same callback/app_data.
  	 */
-	if (ncm->response == NSS_CMM_RESPONSE_NOTIFY) {
+	if (ncm->response == NSS_CMN_RESPONSE_NOTIFY) {
 		ncm->cb = (nss_ptr_t)nss_ctx->nss_top->tun6rd_msg_callback;
 	}
 
diff --git a/nss_tunipip6.c b/nss_tunipip6.c
index f318728..b29c58f 100644
--- a/nss_tunipip6.c
+++ b/nss_tunipip6.c
@@ -54,7 +54,7 @@
 	 * Update the callback and app_data for NOTIFY messages, tun6rd sends all notify messages
 	 * to the same callback/app_data.
 	 */
-	if (ncm->response == NSS_CMM_RESPONSE_NOTIFY) {
+	if (ncm->response == NSS_CMN_RESPONSE_NOTIFY) {
 		ncm->cb = (nss_ptr_t)nss_ctx->nss_top->tunipip6_msg_callback;
 	}
 
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);
diff --git a/nss_tx_rx_virt_if.c b/nss_tx_rx_virt_if.c
index a59f469..947d2fb 100644
--- a/nss_tx_rx_virt_if.c
+++ b/nss_tx_rx_virt_if.c
@@ -1,6 +1,6 @@
 /*
  **************************************************************************
- * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-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.
@@ -99,7 +99,7 @@
 	 * Update the callback and app_data for NOTIFY messages, IPv4 sends all notify messages
 	 * to the same callback/app_data.
 	 */
-	if (ncm->response == NSS_CMM_RESPONSE_NOTIFY) {
+	if (ncm->response == NSS_CMN_RESPONSE_NOTIFY) {
 		ncm->cb = (nss_ptr_t)nss_ctx->nss_top->if_rx_msg_callback[ncm->interface];
 		ncm->app_data = (nss_ptr_t)nss_ctx->subsys_dp_register[ncm->interface].ndev;
 	}
diff --git a/nss_virt_if.c b/nss_virt_if.c
index b790c02..03476ce 100644
--- a/nss_virt_if.c
+++ b/nss_virt_if.c
@@ -120,7 +120,7 @@
 	 * Update the callback and app_data for NOTIFY messages, IPv4 sends all notify messages
 	 * to the same callback/app_data.
 	 */
-	if (ncm->response == NSS_CMM_RESPONSE_NOTIFY) {
+	if (ncm->response == NSS_CMN_RESPONSE_NOTIFY) {
 		ncm->cb = (nss_ptr_t)nss_ctx->nss_top->if_rx_msg_callback[ncm->interface];
 		ncm->app_data = (nss_ptr_t)nss_ctx->subsys_dp_register[ncm->interface].ndev;
 	}
diff --git a/nss_vlan.c b/nss_vlan.c
index e259d68..40b2623 100644
--- a/nss_vlan.c
+++ b/nss_vlan.c
@@ -83,7 +83,7 @@
 	 * Update the callback and app_data for NOTIFY messages, vlan sends all notify messages
 	 * to the same callback/app_data.
 	 */
-	if (ncm->response == NSS_CMM_RESPONSE_NOTIFY) {
+	if (ncm->response == NSS_CMN_RESPONSE_NOTIFY) {
 		ncm->cb = (nss_ptr_t)nss_ctx->nss_top->vlan_callback;
 		ncm->app_data = (nss_ptr_t)app_data;
 	}
diff --git a/nss_wifi.c b/nss_wifi.c
index 6e8ba04..cffd3d3 100644
--- a/nss_wifi.c
+++ b/nss_wifi.c
@@ -69,7 +69,7 @@
 	 * Update the callback and app_data for NOTIFY messages, wifi sends all notify messages
 	 * to the same callback/app_data.
 	 */
-	if (ncm->response == NSS_CMM_RESPONSE_NOTIFY) {
+	if (ncm->response == NSS_CMN_RESPONSE_NOTIFY) {
 		ncm->cb = (nss_ptr_t)nss_ctx->nss_top->wifi_msg_callback;
 	}
 
diff --git a/nss_wifi_if.c b/nss_wifi_if.c
index e90351f..e695f1e 100644
--- a/nss_wifi_if.c
+++ b/nss_wifi_if.c
@@ -1,6 +1,6 @@
 /*
  **************************************************************************
- * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-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.
@@ -97,7 +97,7 @@
 	/*
 	 * Update the callback and app_data for NOTIFY messages.
 	 */
-	if (nwim->cm.response == NSS_CMM_RESPONSE_NOTIFY) {
+	if (nwim->cm.response == NSS_CMN_RESPONSE_NOTIFY) {
 		ncm->cb = (nss_ptr_t)handle->cb;
 		ncm->app_data = (nss_ptr_t)handle->app_data;
 	}
diff --git a/nss_wifi_vdev.c b/nss_wifi_vdev.c
index 9ff294a..a04fd6d 100644
--- a/nss_wifi_vdev.c
+++ b/nss_wifi_vdev.c
@@ -55,7 +55,7 @@
 
 	}
 
-	if (ncm->response == NSS_CMM_RESPONSE_NOTIFY) {
+	if (ncm->response == NSS_CMN_RESPONSE_NOTIFY) {
 		ncm->cb = (nss_ptr_t)nss_ctx->nss_top->if_rx_msg_callback[ncm->interface];
 		ncm->app_data = (nss_ptr_t)nss_ctx->subsys_dp_register[ncm->interface].ndev;
 	}
diff --git a/nss_wifili.c b/nss_wifili.c
index 493874f..e0400b9 100644
--- a/nss_wifili.c
+++ b/nss_wifili.c
@@ -74,7 +74,7 @@
 	 * Update the callback and app_data for notify messages, wifili sends all notify messages
 	 * to the same callback/app_data.
 	 */
-	if (ncm->response == NSS_CMM_RESPONSE_NOTIFY) {
+	if (ncm->response == NSS_CMN_RESPONSE_NOTIFY) {
 		ncm->cb = (nss_ptr_t)nss_ctx->nss_top->wifili_msg_callback;
 	}
 
diff --git a/nss_wifili_stats.c b/nss_wifili_stats.c
index 607ca5d..6219abe 100644
--- a/nss_wifili_stats.c
+++ b/nss_wifili_stats.c
@@ -118,6 +118,7 @@
 	"WIFILI_TX_DESC_FREE_SRC_FW",
 	"WIFILI_TX_DESC_FREE_COMPLETION",
 	"WIFILI_TX_DESC_NO_PB",
+	"WIFILI_TX_DESC_QUEUELIMIT_DROP",
 };
 
 /*
@@ -477,6 +478,8 @@
 								devstats->tx_sw_pool_stats[index].tx_rel_tx_desc;
 		stats->stats_tx_desc[index][NSS_WIFILI_STATS_TX_DESC_NO_PB] +=
 								devstats->tx_sw_pool_stats[index].tx_rel_no_pb;
+		stats->stats_tx_desc[index][NSS_WIFILI_STATS_TX_QUEUELIMIT_DROP] +=
+								devstats->tx_sw_pool_stats[index].tx_queue_limit_drop;
 	}
 
 	/*
diff --git a/nss_wifili_stats.h b/nss_wifili_stats.h
index afe2694..043f84e 100644
--- a/nss_wifili_stats.h
+++ b/nss_wifili_stats.h
@@ -122,6 +122,7 @@
 	NSS_WIFILI_STATS_TX_DESC_FREE_SRC_FW,		/* Number of tx desc for which release src is fw */
 	NSS_WIFILI_STATS_TX_DESC_FREE_COMPLETION,	/* Number of tx desc completion*/
 	NSS_WIFILI_STATS_TX_DESC_NO_PB,			/* Number of tx desc pb is null*/
+	NSS_WIFILI_STATS_TX_QUEUELIMIT_DROP,	/* Number of tx dropped because of queue limit */
 	NSS_WIFILI_STATS_TX_DESC_MAX,			/* Number of tx desc stats*/
 };