[qca-nss-drv] Add IPv4 reassembly stats

Add ipv4 reassembly stats to debugfs.

Change-Id: I4973d7e76b8c13c7e7d73444441454ef06a31cb9
Depends-on: 20267
Signed-off-by: Selin Dag <sdag@codeaurora.org>
diff --git a/nss_stats.c b/nss_stats.c
index 726ac87..3875c63 100644
--- a/nss_stats.c
+++ b/nss_stats.c
@@ -1,6 +1,6 @@
 /*
  **************************************************************************
- * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * 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.
@@ -68,6 +68,16 @@
 };
 
 /*
+ * nss_stats_str_ipv4_reasm
+ *	IPv4 reassembly stats strings
+ */
+static int8_t *nss_stats_str_ipv4_reasm[NSS_STATS_IPV4_REASM_MAX] = {
+	"evictions",
+	"alloc_fails",
+	"timeouts",
+};
+
+/*
  * nss_stats_str_ipv6
  *	IPv6 stats strings
  */
@@ -385,6 +395,77 @@
 }
 
 /*
+ * nss_stats_ipv4_reasm_read()
+ *	Read IPV4 reassembly stats
+ */
+static ssize_t nss_stats_ipv4_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_IPV4_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_IPV4_REASM_MAX * 8, GFP_KERNEL);
+	if (unlikely(stats_shadow == NULL)) {
+		nss_warning("Could not allocate memory for local shadow buffer");
+		return 0;
+	}
+
+	size_wr = scnprintf(lbuf, size_al, "ipv4 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_IPV4_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]);
+	}
+
+	/*
+	 * IPv4 reasm node stats
+	 */
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nipv4 reasm node stats:\n\n");
+
+	spin_lock_bh(&nss_top_main.stats_lock);
+	for (i = 0; (i < NSS_STATS_IPV4_REASM_MAX); i++) {
+		stats_shadow[i] = nss_top_main.stats_ipv4_reasm[i];
+	}
+
+	spin_unlock_bh(&nss_top_main.stats_lock);
+
+	for (i = 0; (i < NSS_STATS_IPV4_REASM_MAX); i++) {
+		size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
+					"%s = %llu\n", nss_stats_str_ipv4_reasm[i], stats_shadow[i]);
+	}
+
+	size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nipv4 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_ipv6_read()
  *	Read IPV6 stats
  */
@@ -1084,6 +1165,11 @@
 NSS_STATS_DECLARE_FILE_OPERATIONS(ipv4)
 
 /*
+ * ipv4_reasm_stats_ops
+ */
+NSS_STATS_DECLARE_FILE_OPERATIONS(ipv4_reasm)
+
+/*
  * ipv6_stats_ops
  */
 NSS_STATS_DECLARE_FILE_OPERATIONS(ipv6)
@@ -1164,6 +1250,16 @@
 	}
 
 	/*
+	 * ipv4_reasm_stats
+	 */
+	nss_top_main.ipv4_reasm_dentry = debugfs_create_file("ipv4_reasm", 0400,
+						nss_top_main.stats_dentry, &nss_top_main, &nss_stats_ipv4_reasm_ops);
+	if (unlikely(nss_top_main.ipv4_reasm_dentry == NULL)) {
+		nss_warning("Failed to create qca-nss-drv/stats/ipv4_reasm file in debugfs");
+		return;
+	}
+
+	/*
 	 * ipv6_stats
 	 */
 	nss_top_main.ipv6_dentry = debugfs_create_file("ipv6", 0400,