[qca-nss-drv]: New API support for PPPoE

Addded new API support for PPPoE.
Currently PPPoE rule destroy function is kept as it is,
it calls new API to send msg to NSS. This function and its registration
should be removed once linux kernel dirctly calls new API to
destroy PPPoE rule on NSS.

Change-Id: I5729983d7767d603e15dd5f8f08cd55bb33aebbc
Signed-off-by: Ankit Dhanuka <adhanuka@codeaurora.org>
diff --git a/Makefile b/Makefile
index e2986fc..83a9220 100644
--- a/Makefile
+++ b/Makefile
@@ -37,7 +37,8 @@
 			nss_tun6rd.o \
 			nss_tunipip6.o \
 			nss_virt_if.o \
-			nss_shaper.o
+			nss_shaper.o \
+			nss_pppoe.o
 
 #
 # TODO: Deprecated files should be removed before merge
diff --git a/exports/nss_api_if.h b/exports/nss_api_if.h
index b08cb85..983420f 100644
--- a/exports/nss_api_if.h
+++ b/exports/nss_api_if.h
@@ -46,6 +46,7 @@
 #include "nss_if.h"
 #include "nss_phys_if.h"
 #include "nss_virt_if.h"
+#include "nss_pppoe.h"
 
 /*
  * Interface numbers are reserved in the
diff --git a/exports/nss_pppoe.h b/exports/nss_pppoe.h
new file mode 100644
index 0000000..22b4fb0
--- /dev/null
+++ b/exports/nss_pppoe.h
@@ -0,0 +1,124 @@
+
+/*
+ **************************************************************************
+ * Copyright (c) 2014, 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_pppoe.h
+  * 	NSS TO HLOS interface definitions.
+  */
+
+#ifndef __NSS_PPPOE_H
+#define __NSS_PPPOE_H
+
+/**
+ * PPPoE messages
+ */
+
+/**
+ * PPPoE Request/Response types
+ */
+enum nss_pppoe_metadata_types {
+	NSS_PPPOE_TX_CONN_RULE_DESTROY,
+	NSS_PPPOE_RX_CONN_RULE_SUCCESS,
+	NSS_PPPOE_RX_CONN_STATS_SYNC,
+	NSS_PPPOE_RX_NODE_STATS_SYNC,
+	NSS_PPPOE_MAX,
+};
+
+/**
+ * Exception events from PPPoE handler
+ */
+enum nss_pppoe_exception_events {
+	NSS_PPPOE_EXCEPTION_EVENT_WRONG_VERSION_OR_TYPE,
+	NSS_PPPOE_EXCEPTION_EVENT_WRONG_CODE,
+	NSS_PPPOE_EXCEPTION_EVENT_HEADER_INCOMPLETE,
+	NSS_PPPOE_EXCEPTION_EVENT_UNSUPPORTED_PPP_PROTOCOL,
+	NSS_PPPOE_EXCEPTION_EVENT_INTERFACE_MISMATCH,
+	NSS_PPPOE_EXCEPTION_EVENT_MAX,
+};
+
+/**
+ * The NSS PPPoE rule destruction structure.
+ */
+struct nss_pppoe_rule_destroy_msg {
+	uint16_t pppoe_session_id;	/* PPPoE session ID */
+	uint16_t pppoe_remote_mac[3];	/* PPPoE server MAC address */
+};
+
+/**
+ * The NSS PPPoE rule create success structure.
+ */
+struct nss_pppoe_rule_create_success_msg {
+	uint16_t pppoe_session_id;	/* PPPoE session ID on which stats are based */
+	uint8_t pppoe_remote_mac[ETH_ALEN];
+					/* PPPoE server MAC address */
+};
+
+/**
+ * The NSS PPPoE node stats structure.
+ */
+struct nss_pppoe_node_stats_sync_msg {
+	struct nss_cmn_node_stats node_stats;
+	uint32_t pppoe_session_create_requests;
+					/* PPPoE session create requests */
+	uint32_t pppoe_session_create_failures;
+					/* PPPoE session create failures */
+	uint32_t pppoe_session_destroy_requests;
+					/* PPPoE session destroy requests */
+	uint32_t pppoe_session_destroy_misses;
+					/* PPPoE session destroy failures */
+};
+
+/**
+ * The NSS PPPoE exception statistics sync structure.
+ */
+struct nss_pppoe_conn_stats_sync_msg {
+	uint16_t pppoe_session_id;	/* PPPoE session ID on which stats are based */
+	uint8_t pppoe_remote_mac[ETH_ALEN];
+					/* PPPoE server MAC address */
+	uint32_t exception_events_pppoe[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 */
+};
+
+/**
+ * Message structure to send/receive PPPoE session commands
+ */
+struct nss_pppoe_msg {
+	struct nss_cmn_msg cm;						/* Message Header */
+	union {
+		struct nss_pppoe_rule_destroy_msg pppoe_rule_destroy;	/* Message: destroy pppoe rule */
+		struct nss_pppoe_rule_create_success_msg pppoe_rule_create_success;
+									/* Message: rule status response */
+		struct nss_pppoe_conn_stats_sync_msg pppoe_conn_stats_sync;
+									/* Message: exception statistics sync */
+		struct nss_pppoe_node_stats_sync_msg pppoe_node_stats_sync;
+									/* Message: node statistics sync */
+	} msg;
+};
+
+/**
+ * @brief Send PPPoE messages
+ *
+ * @param nss_ctx NSS context
+ * @param msg NSS PPPoE message
+ *
+ * @return nss_tx_status_t Tx status
+ */
+extern nss_tx_status_t nss_pppoe_tx(struct nss_ctx_instance *nss_ctx, struct nss_pppoe_msg *msg);
+
+#endif /* __NSS_PPPOE_H */
diff --git a/nss_core.h b/nss_core.h
index 1e4a020..3c944d1 100644
--- a/nss_core.h
+++ b/nss_core.h
@@ -544,7 +544,7 @@
 					/* IPv4 protocol exception events per interface */
 	uint64_t stats_if_exception_ipv6[NSS_EXCEPTION_EVENT_IPV6_MAX];
 					/* IPv6 protocol exception events per interface */
-	uint64_t stats_if_exception_pppoe[NSS_MAX_PHYSICAL_INTERFACES][NSS_PPPOE_NUM_SESSION_PER_INTERFACE][NSS_EXCEPTION_EVENT_PPPOE_MAX];
+	uint64_t stats_if_exception_pppoe[NSS_MAX_PHYSICAL_INTERFACES][NSS_PPPOE_NUM_SESSION_PER_INTERFACE][NSS_PPPOE_EXCEPTION_EVENT_MAX];
 					/* PPPoE exception events for per session on per interface */
 	/*
 	 * TODO: Review and update following fields
diff --git a/nss_hlos_if.h b/nss_hlos_if.h
index e679508..68e706d 100644
--- a/nss_hlos_if.h
+++ b/nss_hlos_if.h
@@ -77,92 +77,6 @@
 };
 
 /*
- * PPPoE
- */
-
-/*
- * Request/Response types
- */
-enum nss_pppoe_metadata_types {
-	NSS_TX_METADATA_TYPE_PPPOE_DESTROY_SESSION,
-	NSS_RX_METADATA_TYPE_PPPOE_RULE_STATUS,
-	NSS_RX_METADATA_TYPE_PPPOE_CONN_STATS_SYNC,
-	NSS_RX_METADATA_TYPE_PPPOE_NODE_STATS_SYNC,
-	NSS_METADATA_TYPE_PPPOE_MAX,
-};
-
-/*
- * Exception events from bridge/route handler
- */
-enum exception_events_pppoe {
-	NSS_EXCEPTION_EVENT_PPPOE_WRONG_VERSION_OR_TYPE,
-	NSS_EXCEPTION_EVENT_PPPOE_WRONG_CODE,
-	NSS_EXCEPTION_EVENT_PPPOE_HEADER_INCOMPLETE,
-	NSS_EXCEPTION_EVENT_PPPOE_UNSUPPORTED_PPP_PROTOCOL,
-	NSS_EXCEPTION_EVENT_PPPOE_INTERFACE_MISMATCH,
-	NSS_EXCEPTION_EVENT_PPPOE_MAX,
-};
-
-/*
- * The NSS PPPoE rule destruction structure.
- */
-struct nss_pppoe_destroy {
-	uint16_t pppoe_session_id;	/* PPPoE session ID */
-	uint16_t pppoe_remote_mac[3];	/* PPPoE server MAC address */
-};
-
-/*
- * The NSS PPPoE rule create success structure.
- */
-struct nss_pppoe_rule_status {
-	uint16_t pppoe_session_id;	/* PPPoE session ID on which stats are based */
-	uint8_t pppoe_remote_mac[ETH_ALEN];
-					/* PPPoE server MAC address */
-};
-
-/*
- * The NSS PPPoE node stats structure.
- */
-struct nss_pppoe_node_sync {
-	struct nss_cmn_node_stats node_stats;
-	uint32_t pppoe_session_create_requests;
-					/* PPPoE session create requests */
-	uint32_t pppoe_session_create_failures;
-					/* PPPoE session create failures */
-	uint32_t pppoe_session_destroy_requests;
-					/* PPPoE session destroy requests */
-	uint32_t pppoe_session_destroy_misses;
-					/* PPPoE session destroy failures */
-};
-
-/*
- * The NSS PPPoE exception statistics sync structure.
- */
-struct nss_pppoe_conn_sync {
-	uint16_t pppoe_session_id;	/* PPPoE session ID on which stats are based */
-	uint8_t pppoe_remote_mac[ETH_ALEN];
-					/* PPPoE server MAC address */
-	uint32_t exception_events_pppoe[NSS_EXCEPTION_EVENT_PPPOE_MAX];
-					/* PPPoE exception events */
-	uint32_t index;			/* Per interface array index */
-	uint32_t interface_num;		/* Interface number on which this session is created */
-};
-
-/*
- * Message structure to send/receive PPPoE session commands
- */
-struct nss_pppoe_msg {
-	struct nss_cmn_msg cm;		/* Message Header */
-	union {
-		struct nss_pppoe_destroy destroy;	/* Message: destroy pppoe rule */
-		struct nss_pppoe_rule_status rule_status;	/* Message: rule status response */
-		struct nss_pppoe_conn_sync conn_sync;	/* Message: exception statistics sync */
-		struct nss_pppoe_node_sync node_sync;	/* Message: node statistics sync */
-	} msg;
-};
-
-
-/*
  * C2C message structures
  */
 
diff --git a/nss_pppoe.c b/nss_pppoe.c
new file mode 100644
index 0000000..6cbee89
--- /dev/null
+++ b/nss_pppoe.c
@@ -0,0 +1,281 @@
+/*
+ **************************************************************************
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all copies.
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ **************************************************************************
+ */
+
+/*
+ * nss_pppoe.c
+ *	NSS PPPoE APIs
+ */
+
+#include "nss_tx_rx_common.h"
+#include <linux/ppp_channel.h>
+
+extern void nss_tx_destroy_pppoe_connection_rule(void *ctx, uint16_t pppoe_session_id, uint8_t *pppoe_remote_mac);
+
+/*
+ **********************************
+ Tx APIs
+ **********************************
+ */
+
+/*
+ * nss_pppoe_tx()
+ *	Transmit an PPPoe message to the FW.
+ */
+nss_tx_status_t nss_pppoe_tx(struct nss_ctx_instance *nss_ctx, struct nss_pppoe_msg *nim)
+{
+	struct nss_pppoe_msg *nim2;
+	struct nss_cmn_msg *ncm = &nim->cm;
+	struct sk_buff *nbuf;
+	int32_t status;
+
+	NSS_VERIFY_CTX_MAGIC(nss_ctx);
+
+	if (unlikely(nss_ctx->state != NSS_CORE_STATE_INITIALIZED)) {
+		nss_warning("%p: pppoe msg dropped as core not ready", nss_ctx);
+		return NSS_TX_FAILURE_NOT_READY;
+	}
+
+	/*
+	 * Sanity check the message
+	 */
+	if (ncm->interface != NSS_PPPOE_RX_INTERFACE) {
+		nss_warning("%p: tx request for another interface: %d", 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);
+		return NSS_TX_FAILURE;
+	}
+
+	if (ncm->len > sizeof(struct nss_pppoe_msg)) {
+		nss_warning("%p: message length is invalid: %d", nss_ctx, ncm->len);
+		return NSS_TX_FAILURE;
+	}
+
+	nbuf = dev_alloc_skb(NSS_NBUF_PAYLOAD_SIZE);
+	if (unlikely(!nbuf)) {
+		spin_lock_bh(&nss_ctx->nss_top->stats_lock);
+		nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_NBUF_ALLOC_FAILS]++;
+		spin_unlock_bh(&nss_ctx->nss_top->stats_lock);
+		nss_warning("%p: msg dropped as command allocation failed", nss_ctx);
+		return NSS_TX_FAILURE;
+	}
+
+	/*
+	 * Copy the message to our skb.
+	 */
+	nim2 = (struct nss_pppoe_msg *)skb_put(nbuf, sizeof(struct nss_pppoe_msg));
+	memcpy(nim2, nim, sizeof(struct nss_pppoe_msg));
+
+	status = nss_core_send_buffer(nss_ctx, 0, nbuf, NSS_IF_CMD_QUEUE, H2N_BUFFER_CTRL, 0);
+	if (status != NSS_CORE_STATUS_SUCCESS) {
+		dev_kfree_skb_any(nbuf);
+		nss_warning("%p: unable to enqueue PPPoE msg\n", nss_ctx);
+		return NSS_TX_FAILURE;
+	}
+
+	nss_hal_send_interrupt(nss_ctx->nmap, nss_ctx->h2n_desc_rings[NSS_IF_CMD_QUEUE].desc_ring.int_bit,
+								NSS_REGS_H2N_INTR_STATUS_DATA_COMMAND_QUEUE);
+
+	NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_TX_CMD_REQ]);
+
+	return NSS_TX_SUCCESS;
+}
+
+/*
+ **********************************
+ Rx APIs
+ **********************************
+ */
+
+/*
+ * nss_pppoe_reset_stats()
+ * 	Reset PPPoE stats when session is destroyed.
+ */
+static void nss_pppoe_reset_stats(struct nss_ctx_instance *nss_ctx)
+{
+	uint32_t i, j, k;
+
+	/*
+	 * Reset the PPPoE statistics.
+	 */
+	spin_lock_bh(&nss_ctx->nss_top->stats_lock);
+
+	/*
+	 * TODO: Don't reset all the statistics. Reset only the destroyed session's stats.
+	 */
+	for (i = 0; i < NSS_MAX_PHYSICAL_INTERFACES; i++) {
+		for (j = 0; j < NSS_PPPOE_NUM_SESSION_PER_INTERFACE; j++) {
+			for (k = 0; k < NSS_PPPOE_EXCEPTION_EVENT_MAX; k++) {
+				nss_ctx->nss_top->stats_if_exception_pppoe[i][j][k] = 0;
+			}
+		}
+	}
+
+	nss_ctx->nss_top->stats_pppoe[NSS_STATS_PPPOE_SESSION_CREATE_REQUESTS] = 0;
+	nss_ctx->nss_top->stats_pppoe[NSS_STATS_PPPOE_SESSION_CREATE_FAILURES] = 0;
+	nss_ctx->nss_top->stats_pppoe[NSS_STATS_PPPOE_SESSION_DESTROY_REQUESTS] = 0;
+	nss_ctx->nss_top->stats_pppoe[NSS_STATS_PPPOE_SESSION_DESTROY_MISSES] = 0;
+
+	/*
+	 * TODO: Do we need to unregister the destroy method? The ppp_dev has already gone.
+	 */
+	spin_unlock_bh(&nss_ctx->nss_top->stats_lock);
+}
+
+/*
+ * nss_pppoe_exception_stats_sync()
+ *	Handle the syncing of PPPoE exception statistics.
+ */
+static void nss_pppoe_exception_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_pppoe_conn_stats_sync_msg *npess)
+{
+	struct nss_top_instance *nss_top = nss_ctx->nss_top;
+	uint32_t index = npess->index;
+	uint32_t interface_num = npess->interface_num;
+	uint32_t i;
+
+	spin_lock_bh(&nss_top->stats_lock);
+
+	if (interface_num >= NSS_MAX_PHYSICAL_INTERFACES) {
+		nss_warning("%p: Incorrect interface number %d for PPPoE exception stats", nss_ctx, interface_num);
+		return;
+	}
+
+	/*
+	 * pppoe exception stats
+	 */
+	for (i = 0; i < NSS_PPPOE_EXCEPTION_EVENT_MAX; i++) {
+		nss_top->stats_if_exception_pppoe[interface_num][index][i] += npess->exception_events_pppoe[i];
+	}
+
+	spin_unlock_bh(&nss_top->stats_lock);
+}
+
+/*
+ * nss_pppoe_node_stats_sync()
+ *	Handle the syncing of PPPoE node statistics.
+ */
+static void nss_pppoe_node_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_pppoe_node_stats_sync_msg *npess)
+{
+	struct nss_top_instance *nss_top = nss_ctx->nss_top;
+
+	spin_lock_bh(&nss_top->stats_lock);
+
+	nss_top->stats_node[NSS_PPPOE_RX_INTERFACE][NSS_STATS_NODE_RX_PKTS] += npess->node_stats.rx_packets;
+	nss_top->stats_node[NSS_PPPOE_RX_INTERFACE][NSS_STATS_NODE_RX_BYTES] += npess->node_stats.rx_bytes;
+	nss_top->stats_node[NSS_PPPOE_RX_INTERFACE][NSS_STATS_NODE_RX_DROPPED] += npess->node_stats.rx_dropped;
+	nss_top->stats_node[NSS_PPPOE_RX_INTERFACE][NSS_STATS_NODE_TX_PKTS] += npess->node_stats.tx_packets;
+	nss_top->stats_node[NSS_PPPOE_RX_INTERFACE][NSS_STATS_NODE_TX_BYTES] += npess->node_stats.tx_bytes;
+
+	nss_top->stats_pppoe[NSS_STATS_PPPOE_SESSION_CREATE_REQUESTS] += npess->pppoe_session_create_requests;
+	nss_top->stats_pppoe[NSS_STATS_PPPOE_SESSION_CREATE_FAILURES] += npess->pppoe_session_create_failures;
+	nss_top->stats_pppoe[NSS_STATS_PPPOE_SESSION_DESTROY_REQUESTS] += npess->pppoe_session_destroy_requests;
+	nss_top->stats_pppoe[NSS_STATS_PPPOE_SESSION_DESTROY_MISSES] += npess->pppoe_session_destroy_misses;
+
+	spin_unlock_bh(&nss_top->stats_lock);
+}
+
+/*
+ * nss_pppoe_rule_create_success()
+ *	Handle the PPPoE rule create success message.
+ */
+static void nss_pppoe_rule_create_success(struct nss_ctx_instance *nss_ctx, struct nss_pppoe_rule_create_success_msg *pcs)
+{
+	struct net_device *ppp_dev = ppp_session_to_netdev(pcs->pppoe_session_id, pcs->pppoe_remote_mac);
+
+	if (!ppp_dev) {
+		nss_warning("%p: There is not any PPP devices with SID: %x remote MAC: %x:%x:%x:%x:%x:%x", nss_ctx, pcs->pppoe_session_id,
+			pcs->pppoe_remote_mac[0], pcs->pppoe_remote_mac[1], pcs->pppoe_remote_mac[2],
+			pcs->pppoe_remote_mac[3], pcs->pppoe_remote_mac[4], pcs->pppoe_remote_mac[5]);
+
+		return;
+	}
+
+	/*
+	 * TODO Remove this registration once kernel directly calls nss_pppoe_tx().
+	 */
+	if (!ppp_register_destroy_method(ppp_dev, nss_tx_destroy_pppoe_connection_rule, (void *)nss_ctx)) {
+		nss_warning("%p: Failed to register destroy method", nss_ctx);
+	}
+
+	dev_put(ppp_dev);
+}
+
+/*
+ * nss_pppoe_rx_msg_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)
+{
+	struct nss_pppoe_msg *nim = (struct nss_pppoe_msg *)ncm;
+
+	BUG_ON(ncm->interface != NSS_PPPOE_RX_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);
+		return;
+	}
+
+	if (ncm->len > sizeof(struct nss_pppoe_msg)) {
+		nss_warning("%p: message length is invalid: %d", nss_ctx, ncm->len);
+		return;
+	}
+
+	/*
+	 * Log failures
+	 */
+	nss_core_log_msg_failures(nss_ctx, ncm);
+
+	/*
+	 * Handling PPPoE messages coming from NSS fw.
+	 */
+	switch (nim->cm.type) {
+	case NSS_PPPOE_RX_CONN_RULE_SUCCESS:
+		nss_pppoe_rule_create_success(nss_ctx, &nim->msg.pppoe_rule_create_success);
+		break;
+
+	case NSS_PPPOE_RX_NODE_STATS_SYNC:
+		nss_pppoe_node_stats_sync(nss_ctx, &nim->msg.pppoe_node_stats_sync);
+		break;
+
+	case NSS_PPPOE_RX_CONN_STATS_SYNC:
+		nss_pppoe_exception_stats_sync(nss_ctx, &nim->msg.pppoe_conn_stats_sync);
+		break;
+
+	case NSS_PPPOE_TX_CONN_RULE_DESTROY:
+		if (ncm->response == NSS_CMN_RESPONSE_ACK) {
+			nss_pppoe_reset_stats(nss_ctx);
+		}
+		break;
+
+	default:
+		nss_warning("%p: Received response %d for type %d, interface %d",
+				nss_ctx, ncm->response, ncm->type, ncm->interface);
+	}
+}
+
+/*
+ * nss_pppoe_register_handler()
+ */
+void nss_pppoe_register_handler()
+{
+	nss_core_register_handler(NSS_PPPOE_RX_INTERFACE, nss_pppoe_rx_msg_handler, NULL);
+}
+
diff --git a/nss_stats.c b/nss_stats.c
index 5f7e0c3..a751f12 100644
--- a/nss_stats.c
+++ b/nss_stats.c
@@ -34,7 +34,7 @@
  */
 extern struct nss_top_instance nss_top_main;
 
-uint64_t stats_shadow_pppoe_except[NSS_PPPOE_NUM_SESSION_PER_INTERFACE][NSS_EXCEPTION_EVENT_PPPOE_MAX];
+uint64_t stats_shadow_pppoe_except[NSS_PPPOE_NUM_SESSION_PER_INTERFACE][NSS_PPPOE_EXCEPTION_EVENT_MAX];
 
 /*
  * Statistics structures
@@ -253,7 +253,7 @@
  * nss_stats_str_if_exception_pppoe
  *	Interface stats strings for PPPoE exceptions
  */
-static int8_t *nss_stats_str_if_exception_pppoe[NSS_EXCEPTION_EVENT_PPPOE_MAX] = {
+static int8_t *nss_stats_str_if_exception_pppoe[NSS_PPPOE_EXCEPTION_EVENT_MAX] = {
 	"PPPOE_WRONG_VERSION_OR_TYPE",
 	"PPPOE_WRONG_CODE",
 	"PPPOE_HEADER_INCOMPLETE",
@@ -653,7 +653,7 @@
 	 * max output lines = #stats + start tag line + end tag line + three blank lines
 	 */
 	uint32_t max_output_lines = (NSS_STATS_NODE_MAX + 2) + (NSS_STATS_PPPOE_MAX + 3) +
-					((NSS_MAX_PHYSICAL_INTERFACES * NSS_PPPOE_NUM_SESSION_PER_INTERFACE * (NSS_EXCEPTION_EVENT_PPPOE_MAX + 5)) + 3) + 5;
+					((NSS_MAX_PHYSICAL_INTERFACES * NSS_PPPOE_NUM_SESSION_PER_INTERFACE * (NSS_PPPOE_EXCEPTION_EVENT_MAX + 5)) + 3) + 5;
 	size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
 	size_t size_wr = 0;
 	ssize_t bytes_read = 0;
@@ -716,7 +716,7 @@
 
 		spin_lock_bh(&nss_top_main.stats_lock);
 		for (k = 0; k < NSS_PPPOE_NUM_SESSION_PER_INTERFACE; k++) {
-			for (i = 0; (i < NSS_EXCEPTION_EVENT_PPPOE_MAX); i++) {
+			for (i = 0; (i < NSS_PPPOE_EXCEPTION_EVENT_MAX); i++) {
 				stats_shadow_pppoe_except[k][i] = nss_top_main.stats_if_exception_pppoe[j][k][i];
 			}
 		}
@@ -725,7 +725,7 @@
 
 		for (k = 0; k < NSS_PPPOE_NUM_SESSION_PER_INTERFACE; k++) {
 			size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "%d. Session\n", k);
-			for (i = 0; (i < NSS_EXCEPTION_EVENT_PPPOE_MAX); i++) {
+			for (i = 0; (i < NSS_PPPOE_EXCEPTION_EVENT_MAX); i++) {
 				size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
 						"%s = %llu\n",
 						nss_stats_str_if_exception_pppoe[i],
diff --git a/nss_tx_rx_pppoe.c b/nss_tx_rx_pppoe.c
index c02ca48..cb2aec0 100644
--- a/nss_tx_rx_pppoe.c
+++ b/nss_tx_rx_pppoe.c
@@ -23,223 +23,38 @@
 #include <linux/ppp_channel.h>
 
 /*
- **********************************
- Tx APIs
- **********************************
- */
-
-/*
  * nss_tx_destroy_pppoe_connection_rule)
  *	Destroy PPoE connection rule associated with the session ID and remote server MAC address.
  */
-static void nss_tx_destroy_pppoe_connection_rule(void *ctx, uint16_t pppoe_session_id, uint8_t *pppoe_remote_mac)
+void nss_tx_destroy_pppoe_connection_rule(void *ctx, uint16_t pppoe_session_id, uint8_t *pppoe_remote_mac)
 {
 	struct nss_ctx_instance *nss_ctx = (struct nss_ctx_instance *) ctx;
-	struct nss_top_instance *nss_top = nss_ctx->nss_top;
-	struct sk_buff *nbuf;
-	int32_t status;
-	struct nss_pppoe_msg *npm;
-	struct nss_pppoe_destroy *nprd;
+	struct nss_pppoe_msg npm;
+	struct nss_pppoe_rule_destroy_msg *nprd;
 	uint16_t *pppoe_remote_mac_uint16_t = (uint16_t *)pppoe_remote_mac;
-	uint32_t i, j, k;
+	int32_t status;
 
+	/*
+	 * TODO Remove this function once linux kernel directly calls nss_pppoe_tx()
+	 */
 	nss_info("%p: Destroy all PPPoE rules of session ID: %x remote MAC: %x:%x:%x:%x:%x:%x", nss_ctx, pppoe_session_id,
 			pppoe_remote_mac[0], pppoe_remote_mac[1], pppoe_remote_mac[2],
 			pppoe_remote_mac[3], pppoe_remote_mac[4], pppoe_remote_mac[5]);
 
-	NSS_VERIFY_CTX_MAGIC(nss_ctx);
-	if (unlikely(nss_ctx->state != NSS_CORE_STATE_INITIALIZED)) {
-		nss_warning("%p: 'Destroy all rules by PPPoE session dropped as core not ready", nss_ctx);
-		return;
-	}
+	nss_cmn_msg_init(&npm.cm, NSS_PPPOE_RX_INTERFACE, NSS_PPPOE_TX_CONN_RULE_DESTROY,
+			sizeof(struct nss_pppoe_rule_destroy_msg), NULL, NULL);
 
-	nbuf = dev_alloc_skb(NSS_NBUF_PAYLOAD_SIZE);
-	if (unlikely(!nbuf)) {
-		spin_lock_bh(&nss_ctx->nss_top->stats_lock);
-		nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_NBUF_ALLOC_FAILS]++;
-		spin_unlock_bh(&nss_ctx->nss_top->stats_lock);
-		nss_warning("%p: 'Destroy all rules by PPPoE session dropped as command allocation failed", nss_ctx);
-		return;
-	}
+	nprd = &npm.msg.pppoe_rule_destroy;
 
-	npm = (struct nss_pppoe_msg *)skb_put(nbuf, sizeof(struct nss_pppoe_msg));
-	npm->cm.interface = NSS_PPPOE_RX_INTERFACE;
-	npm->cm.version = NSS_HLOS_MESSAGE_VERSION;
-	npm->cm.type = NSS_TX_METADATA_TYPE_PPPOE_DESTROY_SESSION;
-	npm->cm.len = sizeof(struct nss_pppoe_destroy);
-
-	nprd = &npm->msg.destroy;
 	nprd->pppoe_session_id = pppoe_session_id;
 	nprd->pppoe_remote_mac[0] = pppoe_remote_mac_uint16_t[0];
 	nprd->pppoe_remote_mac[1] = pppoe_remote_mac_uint16_t[1];
 	nprd->pppoe_remote_mac[2] = pppoe_remote_mac_uint16_t[2];
 
-	status = nss_core_send_buffer(nss_ctx, 0, nbuf, NSS_IF_CMD_QUEUE, H2N_BUFFER_CTRL, 0);
-	if (status != NSS_CORE_STATUS_SUCCESS) {
-		dev_kfree_skb_any(nbuf);
-		nss_warning("%p: Unable to enqueue 'Destroy all rules by PPPoE session\n", nss_ctx);
-		return;
+	status = nss_pppoe_tx(nss_ctx, &npm);
+	if (status != NSS_TX_SUCCESS) {
+		nss_warning("%p: Not able to send destroy pppoe rule msg to NSS %x\n", nss_ctx, status);
 	}
-
-	nss_hal_send_interrupt(nss_ctx->nmap, nss_ctx->h2n_desc_rings[NSS_IF_CMD_QUEUE].desc_ring.int_bit,
-								NSS_REGS_H2N_INTR_STATUS_DATA_COMMAND_QUEUE);
-
-	NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_TX_CMD_REQ]);
-
-	/*
-	 * Reset the PPPoE statistics.
-	 */
-	spin_lock_bh(&nss_top->stats_lock);
-
-	/*
-	 * TODO: Don't reset all the statistics. Reset only the destroyed session's stats.
-	 */
-	for (i = 0; i < NSS_MAX_PHYSICAL_INTERFACES; i++) {
-		for (j = 0; j < NSS_PPPOE_NUM_SESSION_PER_INTERFACE; j++) {
-			for (k = 0; k < NSS_EXCEPTION_EVENT_PPPOE_MAX; k++) {
-				nss_top->stats_if_exception_pppoe[i][j][k] = 0;
-			}
-		}
-	}
-
-	nss_top->stats_pppoe[NSS_STATS_PPPOE_SESSION_CREATE_REQUESTS] = 0;
-	nss_top->stats_pppoe[NSS_STATS_PPPOE_SESSION_CREATE_FAILURES] = 0;
-	nss_top->stats_pppoe[NSS_STATS_PPPOE_SESSION_DESTROY_REQUESTS] = 0;
-	nss_top->stats_pppoe[NSS_STATS_PPPOE_SESSION_DESTROY_MISSES] = 0;
-
-	/*
-	 * TODO: Do we need to unregister the destroy method? The ppp_dev has already gone.
-	 */
-	spin_unlock_bh(&nss_top->stats_lock);
-}
-
-/*
- **********************************
- Rx APIs
- **********************************
- */
-
-/*
- * nss_rx_metadata_pppoe_exception_stats_sync()
- *	Handle the syncing of PPPoE exception statistics.
- */
-static void nss_rx_metadata_pppoe_exception_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_pppoe_conn_sync *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) {
-		nss_warning("%p: Incorrect interface number %d for PPPoE exception stats", nss_ctx, interface_num);
-		return;
-	}
-
-	/*
-	 * pppoe exception stats
-	 */
-	for (i = 0; i < NSS_EXCEPTION_EVENT_PPPOE_MAX; i++) {
-		nss_top->stats_if_exception_pppoe[interface_num][index][i] += npess->exception_events_pppoe[i];
-	}
-
-	spin_unlock_bh(&nss_top->stats_lock);
-}
-
-/*
- * nss_rx_metadata_pppoe_node_stats_sync()
- *	Handle the syncing of PPPoE node statistics.
- */
-static void nss_rx_metadata_pppoe_node_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_pppoe_node_sync *npess)
-{
-	struct nss_top_instance *nss_top = nss_ctx->nss_top;
-
-	spin_lock_bh(&nss_top->stats_lock);
-
-	nss_top->stats_node[NSS_PPPOE_RX_INTERFACE][NSS_STATS_NODE_RX_PKTS] += npess->node_stats.rx_packets;
-	nss_top->stats_node[NSS_PPPOE_RX_INTERFACE][NSS_STATS_NODE_RX_BYTES] += npess->node_stats.rx_bytes;
-	nss_top->stats_node[NSS_PPPOE_RX_INTERFACE][NSS_STATS_NODE_RX_DROPPED] += npess->node_stats.rx_dropped;
-	nss_top->stats_node[NSS_PPPOE_RX_INTERFACE][NSS_STATS_NODE_TX_PKTS] += npess->node_stats.tx_packets;
-	nss_top->stats_node[NSS_PPPOE_RX_INTERFACE][NSS_STATS_NODE_TX_BYTES] += npess->node_stats.tx_bytes;
-
-	nss_top->stats_pppoe[NSS_STATS_PPPOE_SESSION_CREATE_REQUESTS] += npess->pppoe_session_create_requests;
-	nss_top->stats_pppoe[NSS_STATS_PPPOE_SESSION_CREATE_FAILURES] += npess->pppoe_session_create_failures;
-	nss_top->stats_pppoe[NSS_STATS_PPPOE_SESSION_DESTROY_REQUESTS] += npess->pppoe_session_destroy_requests;
-	nss_top->stats_pppoe[NSS_STATS_PPPOE_SESSION_DESTROY_MISSES] += npess->pppoe_session_destroy_misses;
-
-	spin_unlock_bh(&nss_top->stats_lock);
-}
-
-/*
- * nss_rx_metadata_pppoe_rule_create_success()
- *	Handle the PPPoE rule create success message.
- */
-static void nss_rx_metadata_pppoe_rule_create_success(struct nss_ctx_instance *nss_ctx, struct nss_pppoe_rule_status *pcs)
-{
-	struct net_device *ppp_dev = ppp_session_to_netdev(pcs->pppoe_session_id, pcs->pppoe_remote_mac);
-
-	if (!ppp_dev) {
-		nss_warning("%p: There is not any PPP devices with SID: %x remote MAC: %x:%x:%x:%x:%x:%x", nss_ctx, pcs->pppoe_session_id,
-			pcs->pppoe_remote_mac[0], pcs->pppoe_remote_mac[1], pcs->pppoe_remote_mac[2],
-			pcs->pppoe_remote_mac[3], pcs->pppoe_remote_mac[4], pcs->pppoe_remote_mac[5]);
-
-		return;
-	}
-
-	if (!ppp_register_destroy_method(ppp_dev, nss_tx_destroy_pppoe_connection_rule, (void *)nss_ctx)) {
-		nss_warning("%p: Failed to register destroy method", nss_ctx);
-	}
-
-	dev_put(ppp_dev);
-}
-
-/*
- * nss_rx_pppoe_interface_handler()
- *	Handle NSS -> HLOS messages for PPPoE sessions
- */
-static void nss_rx_pppoe_interface_handler(struct nss_ctx_instance *nss_ctx, struct nss_cmn_msg *ncm, __attribute__((unused))void *app_data)
-{
-	struct nss_pppoe_msg *npm = (struct nss_pppoe_msg *)ncm;
-
-	/*
-	 * Is this a valid request/response packet?
-	 */
-	if (npm->cm.type >= NSS_METADATA_TYPE_PPPOE_MAX) {
-		nss_warning("%p: received invalid message %d for PPPoE interface", nss_ctx, npm->cm.type);
-		return;
-	}
-
-	switch (npm->cm.type) {
-	case NSS_RX_METADATA_TYPE_PPPOE_CONN_STATS_SYNC:
-		nss_rx_metadata_pppoe_exception_stats_sync(nss_ctx, &npm->msg.conn_sync);
-		break;
-
-	case NSS_RX_METADATA_TYPE_PPPOE_NODE_STATS_SYNC:
-		nss_rx_metadata_pppoe_node_stats_sync(nss_ctx, &npm->msg.node_sync);
-		break;
-
-	case NSS_RX_METADATA_TYPE_PPPOE_RULE_STATUS:
-		nss_rx_metadata_pppoe_rule_create_success(nss_ctx, &npm->msg.rule_status);
-		break;
-
-	default:
-		if (ncm->response != NSS_CMN_RESPONSE_ACK) {
-			/*
-			 * Check response
-			 */
-			nss_info("%p: Received response %d for type %d, interface %d",
-						nss_ctx, ncm->response, ncm->type, ncm->interface);
-		}
-	}
-}
-
-/*
- * nss_phys_if_register_handler()
- */
-void nss_pppoe_register_handler()
-{
-	nss_core_register_handler(NSS_PPPOE_RX_INTERFACE, nss_rx_pppoe_interface_handler, NULL);
 }
 
 EXPORT_SYMBOL(nss_tx_destroy_pppoe_connection_rule);