Merge "[qca-nss-drv]: Add peer map address and vdev op mode"
diff --git a/Makefile b/Makefile
index debd5fd..a202277 100644
--- a/Makefile
+++ b/Makefile
@@ -34,6 +34,7 @@
 			nss_ipv4.o \
 			nss_ipv4_reasm.o \
 			nss_ipv6.o \
+			nss_ipv6_reasm.o \
 			nss_lag.o \
 			nss_lso_rx.o \
 			nss_phys_if.o \
diff --git a/Makefile.fsm b/Makefile.fsm
index d31cc80..e5603b2 100644
--- a/Makefile.fsm
+++ b/Makefile.fsm
@@ -9,6 +9,7 @@
 qca-nss-drv-objs := \
 			nss_cmn.o \
 			nss_core.o \
+			nss_coredump.o \
 			nss_crypto.o \
 			nss_capwap.o \
 			nss_lso_rx.o \
@@ -21,6 +22,7 @@
 			nss_ipv4.o \
 			nss_ipv4_reasm.o \
 			nss_ipv6.o \
+			nss_ipv6_reasm.o \
 			nss_lag.o \
 			nss_phys_if.o \
 			nss_stats.o \
@@ -30,6 +32,7 @@
 			nss_shaper.o \
 			nss_n2h.o \
 			nss_log.o \
+			nss_profiler.o \
 			nss_eth_rx.o
 
 
diff --git a/exports/nss_api_if.h b/exports/nss_api_if.h
index 1d2c93d..cff1130 100644
--- a/exports/nss_api_if.h
+++ b/exports/nss_api_if.h
@@ -83,7 +83,7 @@
 #define NSS_MAX_PHYSICAL_INTERFACES 4
 #define NSS_MAX_VIRTUAL_INTERFACES 16
 #define NSS_MAX_TUNNEL_INTERFACES 4
-#define NSS_MAX_SPECIAL_INTERFACES 29
+#define NSS_MAX_SPECIAL_INTERFACES 30
 #define NSS_MAX_DYNAMIC_INTERFACES 32
 #define NSS_MAX_WIFI_RADIO_INTERFACES 3
 
@@ -123,13 +123,12 @@
 #define NSS_GRE_REDIR_INTERFACE (NSS_SPECIAL_IF_START + 21) /* Interface Number for GRE REDIR base interface */
 #define NSS_LSO_RX_INTERFACE (NSS_SPECIAL_IF_START + 22) /* Interface number for lso */
 #define NSS_SJACK_INTERFACE (NSS_SPECIAL_IF_START + 23) /* Interface Number for GRE REDIR base interface */
-#define NSS_IPV4_REASM_INTERFACE (NSS_SPECIAL_IF_START + 24) /* Special IF number for IPv4 */
+#define NSS_IPV4_REASM_INTERFACE (NSS_SPECIAL_IF_START + 24) /* Special IF number for IPv4 reassembly */
 #define NSS_DEBUG_INTERFACE (NSS_SPECIAL_IF_START + 25) /* Special IF number for debug interface */
 #define NSS_WIFI_INTERFACE0 (NSS_SPECIAL_IF_START + 26) /* Special Interface Number for WIFI radio 0 */
 #define NSS_WIFI_INTERFACE1 (NSS_SPECIAL_IF_START + 27) /* Special Interface Number for WIFI radi0 1 */
 #define NSS_WIFI_INTERFACE2 (NSS_SPECIAL_IF_START + 28) /* Special Interface Number for WIFI radio 2 */
-
-
+#define NSS_IPV6_REASM_INTERFACE (NSS_SPECIAL_IF_START + 29) /* Special IF number for IPv6 reassembly */
 
 /**
  * This macro converts format for IPv6 address (from Linux to NSS)
diff --git a/exports/nss_ipv4.h b/exports/nss_ipv4.h
index a555ce5..e769cd6 100644
--- a/exports/nss_ipv4.h
+++ b/exports/nss_ipv4.h
@@ -33,7 +33,7 @@
 enum nss_ipv4_message_types {
 	NSS_IPV4_TX_CREATE_RULE_MSG,		/**< IPv4 create rule message */
 	NSS_IPV4_TX_DESTROY_RULE_MSG,		/**< IPv4 destroy rule message */
-	NSS_IPV4_RX_ESTABLISH_RULE_MSG,		/**< IPv4 establish rule message */
+	NSS_IPV4_RX_DEPRECATED0,		/**< Deprecated: NSS_IPV4_RX_ESTABLISH_RULE_MSG */
 	NSS_IPV4_RX_CONN_STATS_SYNC_MSG,	/**< IPv4 connection stats sync message */
 	NSS_IPV4_RX_NODE_STATS_SYNC_MSG,	/**< IPv4 generic statistics sync message */
 	NSS_IPV4_TX_CONN_CFG_RULE_MSG,		/**< IPv4 number of connections supported rule message */
@@ -217,7 +217,7 @@
 	struct nss_ipv4_vlan_rule vlan_secondary_rule;	/**< Secondary VLAN related accleration parameters */
 
 	/* Response */
-	uint32_t index;					/**< Slot ID for cache stats to host OS */
+	uint32_t reserved;					/**< Reserved field */
 };
 
 /**
@@ -272,37 +272,6 @@
 	uint32_t num_conn;	/**< Number of supported IPv4 connections */
 };
 
-
-/**
- * The NSS IPv4 rule establish structure.
- */
-struct nss_ipv4_rule_establish {
-	uint32_t index;				/**< Slot ID for cache stats to host OS */
-	uint32_t protocol;			/**< Protocol number */
-	int32_t flow_interface;			/**< Flow interface number */
-	uint32_t flow_mtu;			/**< MTU for flow interface */
-	uint32_t flow_ip;			/**< Flow IP address */
-	uint32_t flow_ip_xlate;			/**< Translated flow IP address */
-	uint32_t flow_ident;			/**< Flow ident (e.g. port) */
-	uint32_t flow_ident_xlate;		/**< Translated flow ident (e.g. port) */
-	uint16_t flow_mac[3];			/**< Flow direction source MAC address */
-	uint16_t flow_pppoe_session_id;		/**< Flow direction`s PPPoE session ID. */
-	uint16_t flow_pppoe_remote_mac[3];	/**< Flow direction`s PPPoE Server MAC address */
-	uint16_t ingress_vlan_tag;		/**< Ingress VLAN tag */
-	int32_t return_interface;		/**< Return interface number */
-	uint32_t return_mtu;			/**< MTU for return interface */
-	uint32_t return_ip;			/**< Return IP address */
-	uint32_t return_ip_xlate;		/**< Translated return IP address */
-	uint32_t return_ident;			/**< Return ident (e.g. port) */
-	uint32_t return_ident_xlate;		/**< Translated return ident (e.g. port) */
-	uint16_t return_mac[3];			/**< Return direction source MAC address */
-	uint16_t return_pppoe_session_id;	/**< Return direction's PPPoE session ID. */
-	uint16_t return_pppoe_remote_mac[3];	/**< Return direction's PPPoE Server MAC address */
-	uint16_t egress_vlan_tag;		/**< Egress VLAN tag */
-	uint32_t flags;				/**< Bit flags associated with the rule */
-	uint32_t qos_tag;			/**< QoS Tag */
-};
-
 /**
  * IPv4 rule sync reasons.
  */
@@ -321,7 +290,7 @@
  * The NSS IPv4 rule sync structure.
  */
 struct nss_ipv4_conn_sync {
-	uint32_t index;			/**< Slot ID for cache stats to host OS */
+	uint32_t reserved;			/**< Reserved field */
 	uint8_t protocol;		/**< Protocol number */
 	uint32_t flow_ip;		/**< Flow IP address */
 	uint32_t flow_ip_xlate;		/**< Translated flow IP address */
@@ -490,7 +459,6 @@
 	union {
 		struct nss_ipv4_rule_create_msg rule_create;	/**< Message: rule create */
 		struct nss_ipv4_rule_destroy_msg rule_destroy;	/**< Message: rule destroy */
-		struct nss_ipv4_rule_establish rule_establish;	/**< Message: rule establish confirmation */
 		struct nss_ipv4_conn_sync conn_stats;	/**< Message: connection stats sync */
 		struct nss_ipv4_node_sync node_stats;	/**< Message: node stats sync */
 		struct nss_ipv4_rule_conn_cfg_msg rule_conn_cfg;	/**< Message: rule connections supported */
diff --git a/exports/nss_ipv6.h b/exports/nss_ipv6.h
index b56adc3..6f3c190 100644
--- a/exports/nss_ipv6.h
+++ b/exports/nss_ipv6.h
@@ -33,7 +33,7 @@
 enum nss_ipv6_message_types {
 	NSS_IPV6_TX_CREATE_RULE_MSG,		/**< IPv6 create rule message */
 	NSS_IPV6_TX_DESTROY_RULE_MSG,		/**< IPv6 destroy rule message */
-	NSS_IPV6_RX_ESTABLISH_RULE_MSG,		/**< IPv6 establish rule message */
+	NSS_IPV6_RX_DEPRECATED0,		/**< Deprecated: NSS_IPV6_RX_ESTABLISH_RULE_MSG */
 	NSS_IPV6_RX_CONN_STATS_SYNC_MSG,	/**< IPv6 connection stats sync message */
 	NSS_IPV6_RX_NODE_STATS_SYNC_MSG,	/**< IPv6 generic statistics sync message */
 	NSS_IPV6_TX_CONN_CFG_RULE_MSG,		/**< IPv6 connection cfg rule message */
@@ -268,7 +268,7 @@
 	/*
 	 * Response
 	 */
-	uint32_t index;					/**< Slot ID for cache stats to host OS */
+	uint32_t reserved;					/**< Reserved field */
 };
 
 /**
@@ -322,33 +322,6 @@
 };
 
 /**
- * The NSS IPv6 rule establish structure.
- */
-struct nss_ipv6_rule_establish {
-	uint32_t index;				/**< Slot ID for cache stats to host OS */
-	uint8_t protocol;			/**< Protocol number */
-	uint8_t reserved[3];			/**< Reserved to align fields */
-	int32_t flow_interface;			/**< Flow interface number */
-	uint32_t flow_mtu;			/**< MTU for flow interface */
-	uint32_t flow_ip[4];			/**< Flow IP address */
-	uint32_t flow_ident;			/**< Flow ident (e.g. port) */
-	uint16_t flow_mac[3];			/**< Flow direction source MAC address */
-	uint16_t flow_pppoe_session_id;		/**< Flow direction`s PPPoE session ID. */
-	uint16_t flow_pppoe_remote_mac[3];	/**< Flow direction`s PPPoE Server MAC address */
-	uint16_t ingress_vlan_tag;		/**< Ingress VLAN tag */
-	int32_t return_interface;		/**< Return interface number */
-	uint32_t return_mtu;			/**< MTU for return interface */
-	uint32_t return_ip[4];			/**< Return IP address */
-	uint32_t return_ident;			/**< Return ident (e.g. port) */
-	uint16_t return_mac[3];			/**< Return direction source MAC address */
-	uint16_t return_pppoe_session_id;	/**< Return direction's PPPoE session ID. */
-	uint16_t return_pppoe_remote_mac[3];	/**< Return direction's PPPoE Server MAC address */
-	uint16_t egress_vlan_tag;		/**< Egress VLAN tag */
-	uint8_t flags;				/**< Bit flags associated with the rule */
-	uint32_t qos_tag;			/**< QoS Tag */
-};
-
-/**
  * IPv6 rule sync reasons.
  */
 #define NSS_IPV6_RULE_SYNC_REASON_STATS 0
@@ -366,7 +339,7 @@
  * The NSS IPv6 rule sync structure.
  */
 struct nss_ipv6_conn_sync {
-	uint32_t index;			/**< Slot ID for cache stats to host OS */
+	uint32_t reserved;			/**< Reserved field */
 	uint8_t protocol;		/**< Protocol number */
 	uint32_t flow_ip[4];		/**< Flow IP address */
 	uint32_t flow_ident;		/**< Flow ident (e.g. port) */
@@ -454,7 +427,6 @@
 	union {
 		struct nss_ipv6_rule_create_msg rule_create;	/**< Message: rule create */
 		struct nss_ipv6_rule_destroy_msg rule_destroy;	/**< Message: rule destroy */
-		struct nss_ipv6_rule_establish rule_establish;	/**< Message: rule establish confirmation */
 		struct nss_ipv6_conn_sync conn_stats;		/**< Message: stats sync */
 		struct nss_ipv6_node_sync node_stats;		/**< Message: node stats sync */
 		struct nss_ipv6_rule_conn_cfg_msg rule_conn_cfg;/**< Message: rule conn cfg */
diff --git a/exports/nss_pppoe.h b/exports/nss_pppoe.h
index 8cfab8e..f39e425 100644
--- a/exports/nss_pppoe.h
+++ b/exports/nss_pppoe.h
@@ -31,10 +31,11 @@
  * PPPoE Request/Response types
  */
 enum nss_pppoe_metadata_types {
-	NSS_PPPOE_TX_CONN_RULE_DESTROY,
-	NSS_PPPOE_RX_CONN_RULE_SUCCESS,
+	NSS_PPPOE_RX_DEPRECATED0,	/* Deprecated: NSS_PPPOE_TX_CONN_RULE_DESTROY */
+	NSS_PPPOE_RX_DEPRECATED1,	/* Deprecated: NSS_PPPOE_TX_CONN_RULE_SUCCESS */
 	NSS_PPPOE_RX_CONN_STATS_SYNC,
 	NSS_PPPOE_RX_NODE_STATS_SYNC,
+	NSS_PPPOE_RX_SESSION_RESET,
 	NSS_PPPOE_MAX,
 };
 
@@ -51,23 +52,6 @@
 };
 
 /**
- * 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 {
@@ -79,7 +63,15 @@
 	uint32_t pppoe_session_destroy_requests;
 					/* PPPoE session destroy requests */
 	uint32_t pppoe_session_destroy_misses;
-					/* PPPoE session destroy failures */
+					/* PPPoE session destroy misses */
+};
+
+/**
+ * NSS PPPoE session reset message structure.
+ */
+struct nss_pppoe_session_reset_msg {
+	uint32_t interface;
+	uint32_t session_index;
 };
 
 /**
@@ -101,13 +93,12 @@
 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 */
+		struct nss_pppoe_session_reset_msg pppoe_session_reset;
+									/* Message: session reset */
 	} msg;
 };
 
diff --git a/nss_core.h b/nss_core.h
index fbc373c..26b1439 100755
--- a/nss_core.h
+++ b/nss_core.h
@@ -162,11 +162,8 @@
  * INFO: These numbers are based on previous generation chip
  *	These may change in future
  */
-#define NSS_PPPOE_NUM_SESSION_PER_INTERFACE 8
+#define NSS_PPPOE_NUM_SESSION_PER_INTERFACE 4
 					/* Number of maximum simultaneous PPPoE sessions per physical interface */
-#define NSS_PPPOE_NUM_SESSION_TOTAL (NSS_MAX_PHYSICAL_INTERFACES * NSS_PPPOE_NUM_SESSION_PER_INTERFACE)
-					/* Number of total PPPoE sessions */
-
 
 /*
  * NSS Frequency Defines and Values
@@ -325,6 +322,22 @@
 };
 
 /*
+ * IPv6 reasm node statistics
+ *
+ * WARNING: There is a 1:1 mapping between values below and corresponding
+ *	stats string array in nss_stats.c
+ */
+enum nss_stats_ipv6_reasm {
+	NSS_STATS_IPV6_REASM_ALLOC_FAILS = 0,
+					/* Number of fragment queue allocation failures */
+	NSS_STATS_IPV6_REASM_TIMEOUTS,
+					/* Number of expired fragment queues */
+	NSS_STATS_IPV6_REASM_DISCARDS,
+					/* Number of fragment queues discarded due to malformed fragments*/
+	NSS_STATS_IPV6_REASM_MAX,
+};
+
+/*
  * HLOS driver statistics
  *
  * WARNING: There is a 1:1 mapping between values below and corresponding
@@ -639,8 +652,10 @@
 	struct dentry *stats_dentry;	/* Top dentry for nss stats */
 	struct dentry *ipv4_dentry;	/* IPv4 stats dentry */
 	struct dentry *ipv4_reasm_dentry;
-					/* IPv4 stats dentry */
+					/* IPv4 reassembly stats dentry */
 	struct dentry *ipv6_dentry;	/* IPv6 stats dentry */
+	struct dentry *ipv6_reasm_dentry;
+					/* IPv6 reassembly stats dentry */
 	struct dentry *eth_rx_dentry;	/* ETH_RX stats dentry */
 	struct dentry *n2h_dentry;	/* N2H stats dentry */
 	struct dentry *lso_rx_dentry;	/* LSO_RX stats dentry */
@@ -666,6 +681,7 @@
 	uint8_t ipv4_handler_id;
 	uint8_t ipv4_reasm_handler_id;
 	uint8_t ipv6_handler_id;
+	uint8_t ipv6_reasm_handler_id;
 	uint8_t crypto_handler_id;
 	uint8_t ipsec_handler_id;
 	uint8_t wlan_handler_id;
@@ -735,6 +751,8 @@
 					/* IPv4 reasm statistics */
 	uint64_t stats_ipv6[NSS_STATS_IPV6_MAX];
 					/* IPv6 statistics */
+	uint64_t stats_ipv6_reasm[NSS_STATS_IPV6_REASM_MAX];
+					/* IPv6 reasm statistics */
 	uint64_t stats_lso_rx[NSS_STATS_LSO_RX_MAX];
 					/* LSO_RX statistics */
 	atomic64_t stats_drv[NSS_STATS_DRV_MAX];
@@ -755,8 +773,8 @@
 					/* 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_PPPOE_EXCEPTION_EVENT_MAX];
-					/* PPPoE exception events for per session on per interface */
+	uint64_t stats_if_exception_pppoe[NSS_MAX_PHYSICAL_INTERFACES + 1][NSS_PPPOE_NUM_SESSION_PER_INTERFACE + 1][NSS_PPPOE_EXCEPTION_EVENT_MAX];
+					/* PPPoE exception events for per session on per interface. Interface and session indexes start with 1. */
 #if (NSS_DT_SUPPORT == 1)
 	void *nss_fpb_base;			/* Virtual address of FPB base */
 	bool nss_hal_common_init_done;
@@ -889,8 +907,9 @@
 	uint32_t load_addr;				/* Load address of NSS firmware */
 	enum nss_feature_enabled turbo_frequency;	/* Does this core support turbo frequencies */
 	enum nss_feature_enabled ipv4_enabled;		/* Does this core handle IPv4? */
-	enum nss_feature_enabled ipv4_reasm_enabled;	/* Does this core handle IPv4? */
+	enum nss_feature_enabled ipv4_reasm_enabled;	/* Does this core handle IPv4 reassembly? */
 	enum nss_feature_enabled ipv6_enabled;		/* Does this core handle IPv6? */
+	enum nss_feature_enabled ipv6_reasm_enabled;	/* Does this core handle IPv6 reassembly? */
 	enum nss_feature_enabled l2switch_enabled;	/* Does this core handle L2 switch? */
 	enum nss_feature_enabled crypto_enabled;	/* Does this core handle crypto? */
 	enum nss_feature_enabled ipsec_enabled;		/* Does this core handle IPsec? */
diff --git a/nss_hal/fsm9010/nss_hal_pvt.c b/nss_hal/fsm9010/nss_hal_pvt.c
index f6d0b52..77c77a4 100644
--- a/nss_hal/fsm9010/nss_hal_pvt.c
+++ b/nss_hal/fsm9010/nss_hal_pvt.c
@@ -457,6 +457,11 @@
 		nss_ipv6_register_handler();
 	}
 
+	if (npd->ipv6_reasm_enabled == NSS_FEATURE_ENABLED) {
+		nss_top->ipv6_reasm_handler_id = nss_dev->id;
+		nss_ipv6_reasm_register_handler();
+	}
+
 	if (npd->crypto_enabled == NSS_FEATURE_ENABLED) {
 		nss_top->crypto_enabled = 1;
 		nss_top->crypto_handler_id = nss_dev->id;
diff --git a/nss_hal/fsm9010/nss_regs.h b/nss_hal/fsm9010/nss_regs.h
index e66d2b3..fd016b4 100644
--- a/nss_hal/fsm9010/nss_regs.h
+++ b/nss_hal/fsm9010/nss_regs.h
@@ -64,6 +64,14 @@
 #define NSS_REGS_N2H_INTR_STATUS_DATA_QUEUE_1	    	0x0004
 #define NSS_REGS_N2H_INTR_STATUS_EMPTY_BUFFERS_SOS	0x0400
 #define NSS_REGS_N2H_INTR_STATUS_TX_UNBLOCKED		0x0800
+/*
+ * 15 cannot be use for N2H (Okay for H2N)
+ * single H2N_..._COREDUMP_START is enough because QGIC2 split it to
+ * two NSS core; however needs two N2H_..._COREDUMP_END_X because both
+ * cores may generate interrupt simultaneously.
+ */
+#define NSS_REGS_N2H_INTR_STATUS_COREDUMP_END_0		(1 << 14)
+#define NSS_REGS_N2H_INTR_STATUS_COREDUMP_END_1		(1 << 13)
 
 /*
  * Defines for H2N interrupts
@@ -73,7 +81,6 @@
 #define NSS_REGS_H2N_INTR_STATUS_RESET			0x0400	/** Unused */
 #define NSS_REGS_H2N_INTR_STATUS_TX_UNBLOCKED		0x0800
 #define NSS_REGS_H2N_INTR_STATUS_COREDUMP_START		(1 << 15)
-#define NSS_REGS_H2N_INTR_STATUS_COREDUMP_END		(1 << 14)
 
 /*
  * clock source for NSS cores
diff --git a/nss_hal/ipq806x/nss_hal_pvt.c b/nss_hal/ipq806x/nss_hal_pvt.c
index 27c337e..8e059ab 100644
--- a/nss_hal/ipq806x/nss_hal_pvt.c
+++ b/nss_hal/ipq806x/nss_hal_pvt.c
@@ -1341,6 +1341,11 @@
 		nss_ipv6_register_handler();
 	}
 
+	if (npd->ipv6_reasm_enabled == NSS_FEATURE_ENABLED) {
+		nss_top->ipv6_reasm_handler_id = nss_dev->id;
+		nss_ipv6_reasm_register_handler();
+	}
+
 	if (npd->crypto_enabled == NSS_FEATURE_ENABLED) {
 		nss_top->crypto_enabled = 1;
 		nss_top->crypto_handler_id = nss_dev->id;
diff --git a/nss_hal/ipq806x/nss_regs.h b/nss_hal/ipq806x/nss_regs.h
index 290eb2c..4192599 100755
--- a/nss_hal/ipq806x/nss_regs.h
+++ b/nss_hal/ipq806x/nss_regs.h
@@ -1,6 +1,6 @@
 /*
  **************************************************************************
- * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013, 2015 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.
diff --git a/nss_hlos_if.h b/nss_hlos_if.h
index 258bd20..036e47e 100755
--- a/nss_hlos_if.h
+++ b/nss_hlos_if.h
@@ -142,7 +142,7 @@
  */
 struct nss_ipv4_reasm_stats_sync {
 	struct nss_cmn_node_stats node_stats;
-					/* Common node stats for N2H */
+					/* Common node stats for ipv4_reasm */
 	uint32_t ipv4_reasm_evictions;
 	uint32_t ipv4_reasm_alloc_fails;
 	uint32_t ipv4_reasm_timeouts;
@@ -166,6 +166,34 @@
 };
 
 /*
+ * IPv6 reasm node stats
+ */
+struct nss_ipv6_reasm_stats_sync {
+	struct nss_cmn_node_stats node_stats;
+					/* Common node stats for ipv6_reasm */
+	uint32_t ipv6_reasm_alloc_fails;
+	uint32_t ipv6_reasm_timeouts;
+	uint32_t ipv6_reasm_discards;
+};
+
+/*
+ * IPv6 reasm message types
+ */
+enum nss_ipv6_reasm_message_types {
+	NSS_IPV6_REASM_STATS_SYNC_MSG,
+};
+
+/*
+ * IPv6 reassembly message structure
+ */
+struct nss_ipv6_reasm_msg {
+	struct nss_cmn_msg cm;
+	union {
+		struct nss_ipv6_reasm_stats_sync stats_sync;
+	} msg;
+};
+
+/*
  * Generic interface messages
  */
 enum nss_generic_metadata_types {
diff --git a/nss_ipv6_reasm.c b/nss_ipv6_reasm.c
new file mode 100644
index 0000000..2e384b0
--- /dev/null
+++ b/nss_ipv6_reasm.c
@@ -0,0 +1,83 @@
+/*
+ **************************************************************************
+ * Copyright (c) 2015, 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_ipv6_reasm.c
+ *	NSS IPv6 Reassembly APIs
+ */
+#include "nss_tx_rx_common.h"
+
+/*
+ * nss_ipv6_reasm_stats_sync()
+ *	Update driver specific information from the messsage.
+ */
+static void nss_ipv6_reasm_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_ipv6_reasm_stats_sync *nirs)
+{
+	struct nss_top_instance *nss_top = nss_ctx->nss_top;
+
+	spin_lock_bh(&nss_top->stats_lock);
+
+	/*
+	 * Common node stats
+	 */
+	nss_top->stats_node[NSS_IPV6_REASM_INTERFACE][NSS_STATS_NODE_RX_PKTS] += nirs->node_stats.rx_packets;
+	nss_top->stats_node[NSS_IPV6_REASM_INTERFACE][NSS_STATS_NODE_RX_BYTES] += nirs->node_stats.rx_bytes;
+	nss_top->stats_node[NSS_IPV6_REASM_INTERFACE][NSS_STATS_NODE_RX_DROPPED] += nirs->node_stats.rx_dropped;
+	nss_top->stats_node[NSS_IPV6_REASM_INTERFACE][NSS_STATS_NODE_TX_PKTS] += nirs->node_stats.tx_packets;
+	nss_top->stats_node[NSS_IPV6_REASM_INTERFACE][NSS_STATS_NODE_TX_BYTES] += nirs->node_stats.tx_bytes;
+
+	/*
+	 * IPv6 reasm node stats
+	 */
+	nss_top->stats_ipv6_reasm[NSS_STATS_IPV6_REASM_ALLOC_FAILS] += nirs->ipv6_reasm_alloc_fails;
+	nss_top->stats_ipv6_reasm[NSS_STATS_IPV6_REASM_TIMEOUTS] += nirs->ipv6_reasm_timeouts;
+	nss_top->stats_ipv6_reasm[NSS_STATS_IPV6_REASM_DISCARDS] += nirs->ipv6_reasm_discards;
+
+	spin_unlock_bh(&nss_top->stats_lock);
+}
+
+/*
+ * nss_ipv6_reasm_msg_handler()
+ *	Handle NSS -> HLOS messages for IPv6 reasm
+ */
+static void nss_ipv6_reasm_msg_handler(struct nss_ctx_instance *nss_ctx, struct nss_cmn_msg *ncm, __attribute__((unused))void *app_data)
+{
+	struct nss_ipv6_reasm_msg *nim = (struct nss_ipv6_reasm_msg *)ncm;
+
+	BUG_ON(ncm->interface != NSS_IPV6_REASM_INTERFACE);
+
+	switch (nim->cm.type) {
+	case NSS_IPV6_REASM_STATS_SYNC_MSG:
+		/*
+		* Update driver statistics on node sync.
+		*/
+		nss_ipv6_reasm_stats_sync(nss_ctx, &nim->msg.stats_sync);
+		break;
+	default:
+		nss_warning("IPv6 reasm received an unknown message type");
+	}
+}
+
+/*
+ * nss_ipv6_reasm_register_handler()
+ *	Register our handler to receive messages for this interface
+ */
+void nss_ipv6_reasm_register_handler(void)
+{
+	if (nss_core_register_handler(NSS_IPV6_REASM_INTERFACE, nss_ipv6_reasm_msg_handler, NULL) != NSS_CORE_STATUS_SUCCESS) {
+		nss_warning("IPv6 reasm handler failed to register");
+	}
+}
diff --git a/nss_pppoe.c b/nss_pppoe.c
index 1313182..50c7f93 100644
--- a/nss_pppoe.c
+++ b/nss_pppoe.c
@@ -93,32 +93,22 @@
  */
 
 /*
- * nss_pppoe_reset_session_stats()
- * 	Reset PPPoE stats when session is destroyed.
+ * nss_pppoe_session_reset()
+ * 	Reset PPPoE session when session is destroyed.
  */
-static void nss_pppoe_reset_session_stats(struct nss_ctx_instance *nss_ctx)
+static void nss_pppoe_session_reset(struct nss_ctx_instance *nss_ctx, struct nss_pppoe_session_reset_msg *npsr)
 {
-	uint32_t i, j, k;
+	uint32_t i;
+	uint32_t interface = npsr->interface;
+	uint32_t session_index = npsr->session_index;
 
 	/*
-	 * Reset the PPPoE statistics.
+	 * Reset the PPPoE statistics for this specific session.
 	 */
 	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;
-			}
-		}
+	for (i = 0; i < NSS_PPPOE_EXCEPTION_EVENT_MAX; i++) {
+		nss_ctx->nss_top->stats_if_exception_pppoe[interface][session_index][i] = 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);
 }
 
@@ -170,79 +160,12 @@
 	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;
+	nss_top->stats_pppoe[NSS_STATS_PPPOE_SESSION_DESTROY_REQUESTS] += npess->pppoe_session_destroy_requests;
 
 	spin_unlock_bh(&nss_top->stats_lock);
 }
 
 /*
- * nss_pppoe_destroy_connection_rule()
- * Destroy PPoE connection rule associated with the session ID and remote server MAC address.
- */
-
-/*
- * TODO: This API should be deprecated soon and removed.
- */
-static void nss_pppoe_destroy_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_pppoe_msg npm;
-	struct nss_pppoe_rule_destroy_msg *nprd;
-	uint16_t *pppoe_remote_mac_uint16_t = (uint16_t *)pppoe_remote_mac;
-	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_pppoe_msg_init(&npm, NSS_PPPOE_RX_INTERFACE, NSS_PPPOE_TX_CONN_RULE_DESTROY,
-			sizeof(struct nss_pppoe_rule_destroy_msg), NULL, NULL);
-
-	nprd = &npm.msg.pppoe_rule_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_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_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)
-{
-#if (NSS_PPP_SUPPORT == 1)
-	struct net_device *ppp_dev = pppoe_get_and_hold_netdev_from_session_info(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_pppoe_destroy_connection_rule, (void *)nss_ctx)) {
-		nss_warning("%p: Failed to register destroy method", nss_ctx);
-	}
-
-	dev_put(ppp_dev);
-#endif
-}
-
-/*
  * nss_pppoe_rx_msg_handler()
  *	Handle NSS -> HLOS messages for PPPoE
  */
@@ -274,24 +197,15 @@
 	 * 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_session_stats(nss_ctx);
-		}
+	case NSS_PPPOE_RX_SESSION_RESET:
+		nss_pppoe_session_reset(nss_ctx, &nim->msg.pppoe_session_reset);
 		break;
-
 	default:
 		nss_warning("%p: Received response %d for type %d, interface %d",
 				nss_ctx, ncm->response, ncm->type, ncm->interface);
diff --git a/nss_stats.c b/nss_stats.c
index 5819965..375fa99 100644
--- a/nss_stats.c
+++ b/nss_stats.c
@@ -114,6 +114,16 @@
 };
 
 /*
+ * nss_stats_str_ipv6_reasm
+ *	IPv6 reassembly stats strings
+ */
+static int8_t *nss_stats_str_ipv6_reasm[NSS_STATS_IPV6_REASM_MAX] = {
+	"alloc_fails",
+	"timeouts",
+	"discards",
+};
+
+/*
  * nss_stats_str_n2h
  *	N2H stats strings
  */
@@ -654,6 +664,78 @@
 }
 
 /*
+ * nss_stats_ipv6_reasm_read()
+ *	Read IPV6 reassembly stats
+ */
+static ssize_t nss_stats_ipv6_reasm_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
+{
+	int32_t i;
+	/*
+	 * max output lines = #stats + start tag line + end tag line + three blank lines
+	 */
+	uint32_t max_output_lines = (NSS_STATS_NODE_MAX + 2) + (NSS_STATS_IPV6_REASM_MAX + 3) + 5;
+	size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
+	size_t size_wr = 0;
+	ssize_t bytes_read = 0;
+	uint64_t *stats_shadow;
+
+	char *lbuf = kzalloc(size_al, GFP_KERNEL);
+	if (unlikely(lbuf == NULL)) {
+		nss_warning("Could not allocate memory for local statistics buffer");
+		return 0;
+	}
+
+	stats_shadow = kzalloc(NSS_STATS_IPV6_REASM_MAX * 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, "ipv6 reasm stats start:\n\n");
+
+	/*
+	 * Common node stats
+	 */
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "common node stats:\n\n");
+	spin_lock_bh(&nss_top_main.stats_lock);
+	for (i = 0; (i < NSS_STATS_NODE_MAX); i++) {
+		stats_shadow[i] = nss_top_main.stats_node[NSS_IPV6_REASM_INTERFACE][i];
+	}
+
+	spin_unlock_bh(&nss_top_main.stats_lock);
+
+	for (i = 0; (i < NSS_STATS_NODE_MAX); i++) {
+		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
+					"%s = %llu\n", nss_stats_str_node[i], stats_shadow[i]);
+	}
+
+	/*
+	 * Ipv6 reasm node stats
+	 */
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nipv6 reasm node stats:\n\n");
+
+	spin_lock_bh(&nss_top_main.stats_lock);
+	for (i = 0; (i < NSS_STATS_IPV6_REASM_MAX); i++) {
+		stats_shadow[i] = nss_top_main.stats_ipv6_reasm[i];
+	}
+
+	spin_unlock_bh(&nss_top_main.stats_lock);
+
+	for (i = 0; (i < NSS_STATS_IPV6_REASM_MAX); i++) {
+		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
+					"%s = %llu\n", nss_stats_str_ipv6_reasm[i], stats_shadow[i]);
+	}
+
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nipv6 reasm stats end\n\n");
+	bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
+	kfree(lbuf);
+	kfree(stats_shadow);
+
+	return bytes_read;
+}
+
+/*
  * nss_stats_eth_rx_read()
  *	Read ETH_RX stats
  */
@@ -990,7 +1072,7 @@
 	/*
 	 * PPPoE node stats
 	 */
-	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "pppoe node stats:\n\n");
+	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_STATS_PPPOE_MAX); i++) {
 		stats_shadow[i] = nss_top_main.stats_pppoe[i];
@@ -1008,31 +1090,31 @@
 	 */
 	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nException PPPoE:\n\n");
 
-	for (j = 0; j < NSS_MAX_PHYSICAL_INTERFACES; j++) {
+	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 = 0; k < NSS_PPPOE_NUM_SESSION_PER_INTERFACE; k++) {
+		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][i] = nss_top_main.stats_if_exception_pppoe[j][k][i];
+				stats_shadow_pppoe_except[k - 1][i] = nss_top_main.stats_if_exception_pppoe[j][k][i];
 			}
 		}
 
 		spin_unlock_bh(&nss_top_main.stats_lock);
 
-		for (k = 0; k < NSS_PPPOE_NUM_SESSION_PER_INTERFACE; k++) {
+		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_stats_str_if_exception_pppoe[i],
-						stats_shadow_pppoe_except[k][i]);
+						stats_shadow_pppoe_except[k - 1][i]);
 			}
 		}
 
-		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\npppoe stats end\n\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));
 	kfree(lbuf);
 	kfree(stats_shadow);
@@ -1596,6 +1678,11 @@
 NSS_STATS_DECLARE_FILE_OPERATIONS(ipv6)
 
 /*
+ * ipv6_reasm_stats_ops
+ */
+NSS_STATS_DECLARE_FILE_OPERATIONS(ipv6_reasm)
+
+/*
  * n2h_stats_ops
  */
 NSS_STATS_DECLARE_FILE_OPERATIONS(n2h)
@@ -1712,7 +1799,17 @@
 	}
 
 	/*
-	 * ipv6_stats
+	 * ipv6_reasm_stats
+	 */
+	nss_top_main.ipv6_reasm_dentry = debugfs_create_file("ipv6_reasm", 0400,
+						nss_top_main.stats_dentry, &nss_top_main, &nss_stats_ipv6_reasm_ops);
+	if (unlikely(nss_top_main.ipv6_reasm_dentry == NULL)) {
+		nss_warning("Failed to create qca-nss-drv/stats/ipv6_reasm file in debugfs");
+		return;
+	}
+
+	/*
+	 * eth_rx__stats
 	 */
 	nss_top_main.eth_rx_dentry = debugfs_create_file("eth_rx", 0400,
 						nss_top_main.stats_dentry, &nss_top_main, &nss_stats_eth_rx_ops);
diff --git a/nss_tx_rx_common.h b/nss_tx_rx_common.h
index 2182a57..7beb8e3 100644
--- a/nss_tx_rx_common.h
+++ b/nss_tx_rx_common.h
@@ -69,6 +69,7 @@
 extern void nss_ipv4_register_handler(void);
 extern void nss_ipv4_reasm_register_handler(void);
 extern void nss_ipv6_register_handler(void);
+extern void nss_ipv6_reasm_register_handler(void);
 extern void nss_n2h_register_handler(void);
 extern void nss_tunipip6_register_handler(void);
 extern void nss_pppoe_register_handler(void);