blob: 487469021f9b514a76aaf0d8f875686a260512c3 [file] [log] [blame]
Radhakrishna Jiguru1c9b2252013-08-27 23:57:48 +05301/*
2 **************************************************************************
Selin Dag6d9b0c12014-11-04 18:27:21 -08003 * Copyright (c) 2014, The Linux Foundation. All rights reserved.
Radhakrishna Jiguru1c9b2252013-08-27 23:57:48 +05304 * Permission to use, copy, modify, and/or distribute this software for
5 * any purpose with or without fee is hereby granted, provided that the
6 * above copyright notice and this permission notice appear in all copies.
7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
10 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
13 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14 **************************************************************************
15 */
Abhishek Rastogi38cffff2013-06-02 11:25:47 +053016
17/*
18 * nss_stats.c
19 * NSS stats APIs
20 *
21 */
22
23#include "nss_core.h"
24
25/*
26 * Maximum string length:
27 * This should be equal to maximum string size of any stats
28 * inclusive of stats value
29 */
30#define NSS_STATS_MAX_STR_LENGTH 96
31
32/*
33 * Global variables/extern declarations
34 */
35extern struct nss_top_instance nss_top_main;
36
Ankit Dhanukaa1569ce2014-05-13 19:58:06 +053037uint64_t stats_shadow_pppoe_except[NSS_PPPOE_NUM_SESSION_PER_INTERFACE][NSS_PPPOE_EXCEPTION_EVENT_MAX];
Abhishek Rastogi84d95d02014-03-26 19:31:31 +053038
Abhishek Rastogi38cffff2013-06-02 11:25:47 +053039/*
Saurabh Misra09dddeb2014-09-30 16:38:07 -070040 * Private data for every file descriptor
41 */
42struct nss_stats_data {
43 uint32_t if_num; /**< Interface number for CAPWAP stats */
44};
45
46/*
Abhishek Rastogi38cffff2013-06-02 11:25:47 +053047 * Statistics structures
48 */
49
50/*
51 * nss_stats_str_ipv4
52 * IPv4 stats strings
53 */
54static int8_t *nss_stats_str_ipv4[NSS_STATS_IPV4_MAX] = {
55 "rx_pkts",
56 "rx_bytes",
57 "tx_pkts",
58 "tx_bytes",
59 "create_requests",
60 "create_collisions",
61 "create_invalid_interface",
62 "destroy_requests",
63 "destroy_misses",
64 "hash_hits",
65 "hash_reorders",
66 "flushes",
Selin Dag60ea2b22014-11-05 09:36:22 -080067 "evictions",
68 "fragmentations"
Abhishek Rastogi38cffff2013-06-02 11:25:47 +053069};
70
71/*
Selin Dag6d9b0c12014-11-04 18:27:21 -080072 * nss_stats_str_ipv4_reasm
73 * IPv4 reassembly stats strings
74 */
75static int8_t *nss_stats_str_ipv4_reasm[NSS_STATS_IPV4_REASM_MAX] = {
76 "evictions",
77 "alloc_fails",
78 "timeouts",
79};
80
81/*
Abhishek Rastogi38cffff2013-06-02 11:25:47 +053082 * nss_stats_str_ipv6
83 * IPv6 stats strings
84 */
85static int8_t *nss_stats_str_ipv6[NSS_STATS_IPV6_MAX] = {
86 "rx_pkts",
87 "rx_bytes",
88 "tx_pkts",
89 "tx_bytes",
90 "create_requests",
91 "create_collisions",
92 "create_invalid_interface",
93 "destroy_requests",
94 "destroy_misses",
95 "hash_hits",
96 "hash_reorders",
97 "flushes",
98 "evictions",
99};
100
101/*
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530102 * nss_stats_str_n2h
103 * N2H stats strings
104 */
105static int8_t *nss_stats_str_n2h[NSS_STATS_N2H_MAX] = {
106 "queue_dropped",
107 "ticks",
108 "worst_ticks",
Murat Sezgin0c0561d2014-04-09 18:55:58 -0700109 "iterations",
Thomas Wu3fd8dd72014-06-11 15:57:05 -0700110 "pbuf_ocm_alloc_fails",
111 "pbuf_ocm_free_count",
112 "pbuf_ocm_total_count",
113 "pbuf_default_alloc_fails",
114 "pbuf_default_free_count",
115 "pbuf_default_total_count",
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530116 "payload_fails"
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530117};
118
119/*
Thomas Wuc3e382c2014-10-29 15:35:13 -0700120 * nss_stats_str_lso_rx
121 * LSO_RX stats strings
122 */
123static int8_t *nss_stats_str_lso_rx[NSS_STATS_LSO_RX_MAX] = {
124 "tx_dropped",
125 "dropped",
126 "pbuf_alloc_fail",
127 "pbuf_reference_fail"
128};
129
130/*
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530131 * nss_stats_str_drv
132 * Host driver stats strings
133 */
134static int8_t *nss_stats_str_drv[NSS_STATS_DRV_MAX] = {
135 "nbuf_alloc_errors",
136 "tx_queue_full[0]",
137 "tx_queue_full[1]",
138 "tx_buffers_empty",
139 "tx_buffers_pkt",
140 "tx_buffers_cmd",
141 "tx_buffers_crypto",
142 "rx_buffers_empty",
143 "rx_buffers_pkt",
144 "rx_buffers_cmd_resp",
145 "rx_buffers_status_sync",
146 "rx_buffers_crypto",
147 "rx_buffers_virtual"
148};
149
150/*
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530151 * nss_stats_str_pppoe
152 * PPPoE stats strings
153 */
154static int8_t *nss_stats_str_pppoe[NSS_STATS_PPPOE_MAX] = {
155 "create_requests",
156 "create_failures",
157 "destroy_requests",
158 "destroy_misses"
159};
160
161/*
162 * nss_stats_str_gmac
163 * GMAC stats strings
164 */
165static int8_t *nss_stats_str_gmac[NSS_STATS_GMAC_MAX] = {
166 "ticks",
167 "worst_ticks",
168 "iterations"
169};
170
171/*
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530172 * nss_stats_str_node
173 * Interface stats strings per node
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530174 */
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530175static int8_t *nss_stats_str_node[NSS_STATS_NODE_MAX] = {
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530176 "rx_packets",
177 "rx_bytes",
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530178 "rx_dropped",
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530179 "tx_packets",
180 "tx_bytes"
181};
182
183/*
Murat Sezgin99dab642014-08-28 14:40:34 -0700184 * nss_stats_str_eth_rx
185 * eth_rx stats strings
186 */
187static int8_t *nss_stats_str_eth_rx[NSS_STATS_ETH_RX_MAX] = {
188 "ticks",
189 "worst_ticks",
190 "iterations"
191};
192
193/*
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530194 * nss_stats_str_if_exception_unknown
195 * Interface stats strings for unknown exceptions
196 */
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530197static int8_t *nss_stats_str_if_exception_eth_rx[NSS_EXCEPTION_EVENT_ETH_RX_MAX] = {
198 "UNKNOWN_L3_PROTOCOL"
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530199};
200
201/*
202 * nss_stats_str_if_exception_ipv4
203 * Interface stats strings for ipv4 exceptions
204 */
205static int8_t *nss_stats_str_if_exception_ipv4[NSS_EXCEPTION_EVENT_IPV4_MAX] = {
206 "IPV4_ICMP_HEADER_INCOMPLETE",
207 "IPV4_ICMP_UNHANDLED_TYPE",
208 "IPV4_ICMP_IPV4_HEADER_INCOMPLETE",
209 "IPV4_ICMP_IPV4_UDP_HEADER_INCOMPLETE",
210 "IPV4_ICMP_IPV4_TCP_HEADER_INCOMPLETE",
211 "IPV4_ICMP_IPV4_UNKNOWN_PROTOCOL",
212 "IPV4_ICMP_NO_ICME",
213 "IPV4_ICMP_FLUSH_TO_HOST",
214 "IPV4_TCP_HEADER_INCOMPLETE",
215 "IPV4_TCP_NO_ICME",
216 "IPV4_TCP_IP_OPTION",
217 "IPV4_TCP_IP_FRAGMENT",
218 "IPV4_TCP_SMALL_TTL",
219 "IPV4_TCP_NEEDS_FRAGMENTATION",
220 "IPV4_TCP_FLAGS",
221 "IPV4_TCP_SEQ_EXCEEDS_RIGHT_EDGE",
222 "IPV4_TCP_SMALL_DATA_OFFS",
223 "IPV4_TCP_BAD_SACK",
224 "IPV4_TCP_BIG_DATA_OFFS",
225 "IPV4_TCP_SEQ_BEFORE_LEFT_EDGE",
226 "IPV4_TCP_ACK_EXCEEDS_RIGHT_EDGE",
227 "IPV4_TCP_ACK_BEFORE_LEFT_EDGE",
228 "IPV4_UDP_HEADER_INCOMPLETE",
229 "IPV4_UDP_NO_ICME",
230 "IPV4_UDP_IP_OPTION",
231 "IPV4_UDP_IP_FRAGMENT",
232 "IPV4_UDP_SMALL_TTL",
233 "IPV4_UDP_NEEDS_FRAGMENTATION",
234 "IPV4_WRONG_TARGET_MAC",
235 "IPV4_HEADER_INCOMPLETE",
236 "IPV4_BAD_TOTAL_LENGTH",
237 "IPV4_BAD_CHECKSUM",
238 "IPV4_NON_INITIAL_FRAGMENT",
239 "IPV4_DATAGRAM_INCOMPLETE",
240 "IPV4_OPTIONS_INCOMPLETE",
Radha krishna Simha Jiguru59a1a1c2014-01-27 18:29:40 +0530241 "IPV4_UNKNOWN_PROTOCOL",
242 "IPV4_ESP_HEADER_INCOMPLETE",
243 "IPV4_ESP_NO_ICME",
244 "IPV4_ESP_IP_OPTION",
245 "IPV4_ESP_IP_FRAGMENT",
246 "IPV4_ESP_SMALL_TTL",
247 "IPV4_ESP_NEEDS_FRAGMENTATION",
248 "IPV4_INGRESS_VID_MISMATCH",
Thomas Wu8d6f4b22014-06-09 14:46:18 -0700249 "IPV4_INGRESS_VID_MISSING",
Radha krishna Simha Jiguru59a1a1c2014-01-27 18:29:40 +0530250 "IPV4_6RD_NO_ICME",
251 "IPV4_6RD_IP_OPTION",
252 "IPV4_6RD_IP_FRAGMENT",
Murat Sezgin0c0561d2014-04-09 18:55:58 -0700253 "IPV4_6RD_NEEDS_FRAGMENTATION",
254 "IPV4_DSCP_MARKING_MISMATCH",
Murat Sezgin7c5956a2014-05-12 09:59:51 -0700255 "IPV4_VLAN_MARKING_MISMATCH",
Thomas Wu8d6f4b22014-06-09 14:46:18 -0700256 "IPV4_INTERFACE_MISMATCH",
Radha krishna Simha Jiguru00cfe562014-10-21 16:22:12 +0530257 "IPV4_GRE_HEADER_INCOMPLETE",
258 "IPV4_GRE_NO_ICME",
259 "IPV4_GRE_IP_OPTION",
260 "IPV4_GRE_IP_FRAGMENT",
261 "IPV4_GRE_SMALL_TTL",
262 "IPV4_GRE_NEEDS_FRAGMENTATION",
Selin Dag60ea2b22014-11-05 09:36:22 -0800263 "IPV4_FRAG_DF_SET",
264 "IPV4_FRAG_FAIL",
Thomas Wu8d6f4b22014-06-09 14:46:18 -0700265 "IPV4_DESTROY"
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530266};
267
268/*
269 * nss_stats_str_if_exception_ipv6
270 * Interface stats strings for ipv6 exceptions
271 */
272static int8_t *nss_stats_str_if_exception_ipv6[NSS_EXCEPTION_EVENT_IPV6_MAX] = {
273 "IPV6_ICMP_HEADER_INCOMPLETE",
274 "IPV6_ICMP_UNHANDLED_TYPE",
275 "IPV6_ICMP_IPV6_HEADER_INCOMPLETE",
276 "IPV6_ICMP_IPV6_UDP_HEADER_INCOMPLETE",
277 "IPV6_ICMP_IPV6_TCP_HEADER_INCOMPLETE",
278 "IPV6_ICMP_IPV6_UNKNOWN_PROTOCOL",
279 "IPV6_ICMP_NO_ICME",
280 "IPV6_ICMP_FLUSH_TO_HOST",
281 "IPV6_TCP_HEADER_INCOMPLETE",
282 "IPV6_TCP_NO_ICME",
283 "IPV6_TCP_SMALL_HOP_LIMIT",
284 "IPV6_TCP_NEEDS_FRAGMENTATION",
285 "IPV6_TCP_FLAGS",
286 "IPV6_TCP_SEQ_EXCEEDS_RIGHT_EDGE",
287 "IPV6_TCP_SMALL_DATA_OFFS",
288 "IPV6_TCP_BAD_SACK",
289 "IPV6_TCP_BIG_DATA_OFFS",
290 "IPV6_TCP_SEQ_BEFORE_LEFT_EDGE",
291 "IPV6_TCP_ACK_EXCEEDS_RIGHT_EDGE",
292 "IPV6_TCP_ACK_BEFORE_LEFT_EDGE",
293 "IPV6_UDP_HEADER_INCOMPLETE",
294 "IPV6_UDP_NO_ICME",
295 "IPV6_UDP_SMALL_HOP_LIMIT",
296 "IPV6_UDP_NEEDS_FRAGMENTATION",
297 "IPV6_WRONG_TARGET_MAC",
298 "IPV6_HEADER_INCOMPLETE",
Radha krishna Simha Jiguru59a1a1c2014-01-27 18:29:40 +0530299 "IPV6_UNKNOWN_PROTOCOL",
Murat Sezgin0c0561d2014-04-09 18:55:58 -0700300 "IPV6_INGRESS_VID_MISMATCH",
Thomas Wu8d6f4b22014-06-09 14:46:18 -0700301 "IPV6_INGRESS_VID_MISSING",
Murat Sezgin0c0561d2014-04-09 18:55:58 -0700302 "IPV6_DSCP_MARKING_MISMATCH",
303 "IPV6_VLAN_MARKING_MISMATCH",
Thomas Wu8d6f4b22014-06-09 14:46:18 -0700304 "IPV6_INTERFACE_MISMATCH",
305 "IPV6_DESTROY"
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530306};
307
308/*
309 * nss_stats_str_if_exception_pppoe
310 * Interface stats strings for PPPoE exceptions
311 */
Ankit Dhanukaa1569ce2014-05-13 19:58:06 +0530312static int8_t *nss_stats_str_if_exception_pppoe[NSS_PPPOE_EXCEPTION_EVENT_MAX] = {
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530313 "PPPOE_WRONG_VERSION_OR_TYPE",
314 "PPPOE_WRONG_CODE",
315 "PPPOE_HEADER_INCOMPLETE",
Murat Sezgin7c5956a2014-05-12 09:59:51 -0700316 "PPPOE_UNSUPPORTED_PPP_PROTOCOL",
317 "PPPOE_INTERFACE_MISMATCH"
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530318};
319
320/*
321 * nss_stats_ipv4_read()
322 * Read IPV4 stats
323 */
324static ssize_t nss_stats_ipv4_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
325{
326 int32_t i;
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530327 /*
328 * max output lines = #stats + start tag line + end tag line + three blank lines
329 */
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530330 uint32_t max_output_lines = (NSS_STATS_NODE_MAX + 2) + (NSS_STATS_IPV4_MAX + 3) + (NSS_EXCEPTION_EVENT_IPV4_MAX + 3) + 5;
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530331 size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
332 size_t size_wr = 0;
333 ssize_t bytes_read = 0;
334 uint64_t *stats_shadow;
335
336 char *lbuf = kzalloc(size_al, GFP_KERNEL);
337 if (unlikely(lbuf == NULL)) {
338 nss_warning("Could not allocate memory for local statistics buffer");
339 return 0;
340 }
341
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530342 /*
343 * Note: The assumption here is that exception event count is larger than other statistics count for IPv4
344 */
345 stats_shadow = kzalloc(NSS_EXCEPTION_EVENT_IPV4_MAX * 8, GFP_KERNEL);
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530346 if (unlikely(stats_shadow == NULL)) {
347 nss_warning("Could not allocate memory for local shadow buffer");
348 return 0;
349 }
350
Abhishek Rastogia1a07972014-04-01 19:43:33 +0530351 size_wr = scnprintf(lbuf, size_al, "ipv4 stats start:\n\n");
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530352
353 /*
354 * Common node stats
355 */
Abhishek Rastogia1a07972014-04-01 19:43:33 +0530356 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "common node stats:\n\n");
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530357 spin_lock_bh(&nss_top_main.stats_lock);
358 for (i = 0; (i < NSS_STATS_NODE_MAX); i++) {
359 stats_shadow[i] = nss_top_main.stats_node[NSS_IPV4_RX_INTERFACE][i];
360 }
361
362 spin_unlock_bh(&nss_top_main.stats_lock);
363
364 for (i = 0; (i < NSS_STATS_NODE_MAX); i++) {
365 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
366 "%s = %llu\n", nss_stats_str_node[i], stats_shadow[i]);
367 }
368
369 /*
370 * IPv4 node stats
371 */
Abhishek Rastogia1a07972014-04-01 19:43:33 +0530372 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nipv4 node stats:\n\n");
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530373
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530374 spin_lock_bh(&nss_top_main.stats_lock);
375 for (i = 0; (i < NSS_STATS_IPV4_MAX); i++) {
376 stats_shadow[i] = nss_top_main.stats_ipv4[i];
377 }
378
379 spin_unlock_bh(&nss_top_main.stats_lock);
380
381 for (i = 0; (i < NSS_STATS_IPV4_MAX); i++) {
382 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
383 "%s = %llu\n", nss_stats_str_ipv4[i], stats_shadow[i]);
384 }
385
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530386 /*
387 * Exception stats
388 */
Abhishek Rastogia1a07972014-04-01 19:43:33 +0530389 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nipv4 exception stats:\n\n");
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530390
391 spin_lock_bh(&nss_top_main.stats_lock);
392 for (i = 0; (i < NSS_EXCEPTION_EVENT_IPV4_MAX); i++) {
393 stats_shadow[i] = nss_top_main.stats_if_exception_ipv4[i];
394 }
395
396 spin_unlock_bh(&nss_top_main.stats_lock);
397
398 for (i = 0; (i < NSS_EXCEPTION_EVENT_IPV4_MAX); i++) {
399 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
400 "%s = %llu\n", nss_stats_str_if_exception_ipv4[i], stats_shadow[i]);
401 }
402
Abhishek Rastogia1a07972014-04-01 19:43:33 +0530403 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nipv4 stats end\n\n");
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530404 bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
405 kfree(lbuf);
406 kfree(stats_shadow);
407
408 return bytes_read;
409}
410
411/*
Selin Dag6d9b0c12014-11-04 18:27:21 -0800412 * nss_stats_ipv4_reasm_read()
413 * Read IPV4 reassembly stats
414 */
415static ssize_t nss_stats_ipv4_reasm_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
416{
417 int32_t i;
418 /*
419 * max output lines = #stats + start tag line + end tag line + three blank lines
420 */
421 uint32_t max_output_lines = (NSS_STATS_NODE_MAX + 2) + (NSS_STATS_IPV4_REASM_MAX + 3) + 5;
422 size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
423 size_t size_wr = 0;
424 ssize_t bytes_read = 0;
425 uint64_t *stats_shadow;
426
427 char *lbuf = kzalloc(size_al, GFP_KERNEL);
428 if (unlikely(lbuf == NULL)) {
429 nss_warning("Could not allocate memory for local statistics buffer");
430 return 0;
431 }
432
433 stats_shadow = kzalloc(NSS_STATS_IPV4_REASM_MAX * 8, GFP_KERNEL);
434 if (unlikely(stats_shadow == NULL)) {
435 nss_warning("Could not allocate memory for local shadow buffer");
436 return 0;
437 }
438
439 size_wr = scnprintf(lbuf, size_al, "ipv4 reasm stats start:\n\n");
440
441 /*
442 * Common node stats
443 */
444 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "common node stats:\n\n");
445 spin_lock_bh(&nss_top_main.stats_lock);
446 for (i = 0; (i < NSS_STATS_NODE_MAX); i++) {
447 stats_shadow[i] = nss_top_main.stats_node[NSS_IPV4_REASM_INTERFACE][i];
448 }
449
450 spin_unlock_bh(&nss_top_main.stats_lock);
451
452 for (i = 0; (i < NSS_STATS_NODE_MAX); i++) {
453 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
454 "%s = %llu\n", nss_stats_str_node[i], stats_shadow[i]);
455 }
456
457 /*
458 * IPv4 reasm node stats
459 */
460 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nipv4 reasm node stats:\n\n");
461
462 spin_lock_bh(&nss_top_main.stats_lock);
463 for (i = 0; (i < NSS_STATS_IPV4_REASM_MAX); i++) {
464 stats_shadow[i] = nss_top_main.stats_ipv4_reasm[i];
465 }
466
467 spin_unlock_bh(&nss_top_main.stats_lock);
468
469 for (i = 0; (i < NSS_STATS_IPV4_REASM_MAX); i++) {
470 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
471 "%s = %llu\n", nss_stats_str_ipv4_reasm[i], stats_shadow[i]);
472 }
473
474 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nipv4 reasm stats end\n\n");
475 bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
476 kfree(lbuf);
477 kfree(stats_shadow);
478
479 return bytes_read;
480}
481
482/*
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530483 * nss_stats_ipv6_read()
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530484 * Read IPV6 stats
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530485 */
486static ssize_t nss_stats_ipv6_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
487{
488 int32_t i;
489
490 /*
491 * max output lines = #stats + start tag line + end tag line + three blank lines
492 */
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530493 uint32_t max_output_lines = (NSS_STATS_NODE_MAX + 2) + (NSS_STATS_IPV6_MAX + 3) + (NSS_EXCEPTION_EVENT_IPV6_MAX + 3) + 5;
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530494 size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
495 size_t size_wr = 0;
496 ssize_t bytes_read = 0;
497 uint64_t *stats_shadow;
498
499 char *lbuf = kzalloc(size_al, GFP_KERNEL);
500 if (unlikely(lbuf == NULL)) {
501 nss_warning("Could not allocate memory for local statistics buffer");
502 return 0;
503 }
504
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530505 /*
506 * Note: The assumption here is that exception event count is larger than other statistics count for IPv4
507 */
508 stats_shadow = kzalloc(NSS_EXCEPTION_EVENT_IPV6_MAX * 8, GFP_KERNEL);
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530509 if (unlikely(stats_shadow == NULL)) {
510 nss_warning("Could not allocate memory for local shadow buffer");
511 return 0;
512 }
513
Abhishek Rastogia1a07972014-04-01 19:43:33 +0530514 size_wr = scnprintf(lbuf, size_al, "ipv6 stats start:\n\n");
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530515
516 /*
517 * Common node stats
518 */
Abhishek Rastogia1a07972014-04-01 19:43:33 +0530519 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "common node stats:\n\n");
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530520 spin_lock_bh(&nss_top_main.stats_lock);
521 for (i = 0; (i < NSS_STATS_NODE_MAX); i++) {
522 stats_shadow[i] = nss_top_main.stats_node[NSS_IPV6_RX_INTERFACE][i];
523 }
524
525 spin_unlock_bh(&nss_top_main.stats_lock);
526
527 for (i = 0; (i < NSS_STATS_NODE_MAX); i++) {
528 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
529 "%s = %llu\n", nss_stats_str_node[i], stats_shadow[i]);
530 }
531
532 /*
533 * IPv6 node stats
534 */
Abhishek Rastogia1a07972014-04-01 19:43:33 +0530535 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nipv6 node stats:\n\n");
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530536
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530537 spin_lock_bh(&nss_top_main.stats_lock);
538 for (i = 0; (i < NSS_STATS_IPV6_MAX); i++) {
539 stats_shadow[i] = nss_top_main.stats_ipv6[i];
540 }
541
542 spin_unlock_bh(&nss_top_main.stats_lock);
543
544 for (i = 0; (i < NSS_STATS_IPV6_MAX); i++) {
545 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
546 "%s = %llu\n", nss_stats_str_ipv6[i], stats_shadow[i]);
547 }
548
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530549 /*
550 * Exception stats
551 */
Abhishek Rastogia1a07972014-04-01 19:43:33 +0530552 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nipv6 exception stats:\n\n");
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530553
554 spin_lock_bh(&nss_top_main.stats_lock);
555 for (i = 0; (i < NSS_EXCEPTION_EVENT_IPV6_MAX); i++) {
556 stats_shadow[i] = nss_top_main.stats_if_exception_ipv6[i];
557 }
558
559 spin_unlock_bh(&nss_top_main.stats_lock);
560
561 for (i = 0; (i < NSS_EXCEPTION_EVENT_IPV6_MAX); i++) {
562 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
563 "%s = %llu\n", nss_stats_str_if_exception_ipv6[i], stats_shadow[i]);
564 }
565
566 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,"\nipv6 stats end\n\n");
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530567 bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
568 kfree(lbuf);
569 kfree(stats_shadow);
570
571 return bytes_read;
572}
573
574/*
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530575 * nss_stats_eth_rx_read()
576 * Read ETH_RX stats
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530577 */
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530578static ssize_t nss_stats_eth_rx_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530579{
580 int32_t i;
581
582 /*
583 * max output lines = #stats + start tag line + end tag line + three blank lines
584 */
Murat Sezgin99dab642014-08-28 14:40:34 -0700585 uint32_t max_output_lines = (NSS_STATS_NODE_MAX + 2) + (NSS_STATS_ETH_RX_MAX + 3) + (NSS_EXCEPTION_EVENT_ETH_RX_MAX + 3) + 5;
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530586 size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
587 size_t size_wr = 0;
588 ssize_t bytes_read = 0;
589 uint64_t *stats_shadow;
590
591 char *lbuf = kzalloc(size_al, GFP_KERNEL);
592 if (unlikely(lbuf == NULL)) {
593 nss_warning("Could not allocate memory for local statistics buffer");
594 return 0;
595 }
596
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530597 /*
598 * Note: The assumption here is that we do not have more than 64 stats
599 */
600 stats_shadow = kzalloc(64 * 8, GFP_KERNEL);
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530601 if (unlikely(stats_shadow == NULL)) {
602 nss_warning("Could not allocate memory for local shadow buffer");
603 return 0;
604 }
605
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530606 size_wr = scnprintf(lbuf, size_al,"eth_rx stats start:\n\n");
607
608 /*
609 * Common node stats
610 */
Abhishek Rastogia1a07972014-04-01 19:43:33 +0530611 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "common node stats:\n\n");
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530612 spin_lock_bh(&nss_top_main.stats_lock);
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530613 for (i = 0; (i < NSS_STATS_NODE_MAX); i++) {
614 stats_shadow[i] = nss_top_main.stats_node[NSS_ETH_RX_INTERFACE][i];
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530615 }
616
617 spin_unlock_bh(&nss_top_main.stats_lock);
618
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530619 for (i = 0; (i < NSS_STATS_NODE_MAX); i++) {
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530620 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530621 "%s = %llu\n", nss_stats_str_node[i], stats_shadow[i]);
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530622 }
623
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530624 /*
Murat Sezgin99dab642014-08-28 14:40:34 -0700625 * eth_rx node stats
626 */
627 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\neth_rx node stats:\n\n");
628 spin_lock_bh(&nss_top_main.stats_lock);
629 for (i = 0; (i < NSS_STATS_ETH_RX_MAX); i++) {
630 stats_shadow[i] = nss_top_main.stats_eth_rx[i];
631 }
632
633 spin_unlock_bh(&nss_top_main.stats_lock);
634
635 for (i = 0; (i < NSS_STATS_ETH_RX_MAX); i++) {
636 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
637 "%s = %llu\n", nss_stats_str_eth_rx[i], stats_shadow[i]);
638 }
639
640 /*
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530641 * Exception stats
642 */
Abhishek Rastogia1a07972014-04-01 19:43:33 +0530643 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\neth_rx exception stats:\n\n");
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530644
645 spin_lock_bh(&nss_top_main.stats_lock);
646 for (i = 0; (i < NSS_EXCEPTION_EVENT_ETH_RX_MAX); i++) {
647 stats_shadow[i] = nss_top_main.stats_if_exception_eth_rx[i];
648 }
649
650 spin_unlock_bh(&nss_top_main.stats_lock);
651
652 for (i = 0; (i < NSS_EXCEPTION_EVENT_ETH_RX_MAX); i++) {
653 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
654 "%s = %llu\n", nss_stats_str_if_exception_eth_rx[i], stats_shadow[i]);
655 }
656
657 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,"\neth_rx stats end\n\n");
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530658 bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
659 kfree(lbuf);
660 kfree(stats_shadow);
661
662 return bytes_read;
663}
664
665/*
666 * nss_stats_n2h_read()
667 * Read N2H stats
668 */
669static ssize_t nss_stats_n2h_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
670{
671 int32_t i;
672
673 /*
674 * max output lines = #stats + start tag line + end tag line + three blank lines
675 */
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530676 uint32_t max_output_lines = (NSS_STATS_NODE_MAX + 2) + (NSS_STATS_N2H_MAX + 3) + 5;
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530677 size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
678 size_t size_wr = 0;
679 ssize_t bytes_read = 0;
680 uint64_t *stats_shadow;
Murat Sezgin0c0561d2014-04-09 18:55:58 -0700681 int max = NSS_STATS_N2H_MAX - NSS_STATS_NODE_MAX;
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530682
683 char *lbuf = kzalloc(size_al, GFP_KERNEL);
684 if (unlikely(lbuf == NULL)) {
685 nss_warning("Could not allocate memory for local statistics buffer");
686 return 0;
687 }
688
689 stats_shadow = kzalloc(NSS_STATS_N2H_MAX * 8, GFP_KERNEL);
690 if (unlikely(stats_shadow == NULL)) {
691 nss_warning("Could not allocate memory for local shadow buffer");
692 return 0;
693 }
694
695 size_wr = scnprintf(lbuf, size_al, "n2h stats start:\n\n");
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530696
697 /*
698 * Common node stats
699 */
Abhishek Rastogia1a07972014-04-01 19:43:33 +0530700 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "common node stats:\n\n");
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530701 spin_lock_bh(&nss_top_main.stats_lock);
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530702 for (i = 0; (i < NSS_STATS_NODE_MAX); i++) {
703 stats_shadow[i] = nss_top_main.nss[0].stats_n2h[i];
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530704 }
705
706 spin_unlock_bh(&nss_top_main.stats_lock);
707
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530708 for (i = 0; (i < NSS_STATS_NODE_MAX); i++) {
709 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
710 "%s = %llu\n", nss_stats_str_node[i], stats_shadow[i]);
711 }
712
713 /*
714 * N2H node stats
715 */
Abhishek Rastogia1a07972014-04-01 19:43:33 +0530716 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nn2h node stats:\n\n");
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530717 spin_lock_bh(&nss_top_main.stats_lock);
718 for (i = NSS_STATS_NODE_MAX; (i < NSS_STATS_N2H_MAX); i++) {
719 stats_shadow[i] = nss_top_main.nss[0].stats_n2h[i];
720 }
721
722 spin_unlock_bh(&nss_top_main.stats_lock);
723
Murat Sezgin0c0561d2014-04-09 18:55:58 -0700724 for (i = 0; i < max; i++) {
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530725 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
Murat Sezgin0c0561d2014-04-09 18:55:58 -0700726 "%s = %llu\n", nss_stats_str_n2h[i], stats_shadow[i + NSS_STATS_NODE_MAX]);
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530727 }
728
729 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nn2h stats end\n\n");
730 bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
731 kfree(lbuf);
732 kfree(stats_shadow);
733
734 return bytes_read;
735}
736
737/*
Thomas Wuc3e382c2014-10-29 15:35:13 -0700738 * nss_stats_lso_rx_read()
739 * Read LSO_RX stats
740 */
741static ssize_t nss_stats_lso_rx_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
742{
743 int32_t i;
744
745 /*
746 * max output lines = #stats + start tag line + end tag line + three blank lines
747 */
748 uint32_t max_output_lines = (NSS_STATS_NODE_MAX + 2) + (NSS_STATS_LSO_RX_MAX + 3) + 5;
749 size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
750 size_t size_wr = 0;
751 ssize_t bytes_read = 0;
752 uint64_t *stats_shadow;
753
754 char *lbuf = kzalloc(size_al, GFP_KERNEL);
755 if (unlikely(lbuf == NULL)) {
756 nss_warning("Could not allocate memory for local statistics buffer");
757 return 0;
758 }
759
760 stats_shadow = kzalloc(NSS_STATS_LSO_RX_MAX * 8, GFP_KERNEL);
761 if (unlikely(stats_shadow == NULL)) {
762 nss_warning("Could not allocate memory for local shadow buffer");
763 return 0;
764 }
765
766 size_wr = scnprintf(lbuf, size_al, "lso_rx stats start:\n\n");
767
768 /*
769 * Common node stats
770 */
771 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "common node stats:\n\n");
772 spin_lock_bh(&nss_top_main.stats_lock);
773 for (i = 0; (i < NSS_STATS_NODE_MAX); i++) {
774 stats_shadow[i] = nss_top_main.stats_node[NSS_LSO_RX_INTERFACE][i];
775 }
776
777 spin_unlock_bh(&nss_top_main.stats_lock);
778
779 for (i = 0; (i < NSS_STATS_NODE_MAX); i++) {
780 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
781 "%s = %llu\n", nss_stats_str_node[i], stats_shadow[i]);
782 }
783
784 /*
785 * lso_rx node stats
786 */
787 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nlso_rx node stats:\n\n");
788 spin_lock_bh(&nss_top_main.stats_lock);
789 for (i = 0; (i < NSS_STATS_LSO_RX_MAX); i++) {
790 stats_shadow[i] = nss_top_main.stats_lso_rx[i];
791 }
792
793 spin_unlock_bh(&nss_top_main.stats_lock);
794
795 for (i = 0; i < NSS_STATS_LSO_RX_MAX; i++) {
796 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
797 "%s = %llu\n", nss_stats_str_lso_rx[i], stats_shadow[i]);
798 }
799
800 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nlso_rx stats end\n\n");
801 bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
802 kfree(lbuf);
803 kfree(stats_shadow);
804
805 return bytes_read;
806}
807
808/*
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530809 * nss_stats_drv_read()
810 * Read HLOS driver stats
811 */
812static ssize_t nss_stats_drv_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
813{
814 int32_t i;
815
816 /*
817 * max output lines = #stats + start tag line + end tag line + three blank lines
818 */
819 uint32_t max_output_lines = NSS_STATS_DRV_MAX + 5;
820 size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
821 size_t size_wr = 0;
822 ssize_t bytes_read = 0;
823 uint64_t *stats_shadow;
824
825 char *lbuf = kzalloc(size_al, GFP_KERNEL);
826 if (unlikely(lbuf == NULL)) {
827 nss_warning("Could not allocate memory for local statistics buffer");
828 return 0;
829 }
830
831 stats_shadow = kzalloc(NSS_STATS_DRV_MAX * 8, GFP_KERNEL);
832 if (unlikely(stats_shadow == NULL)) {
833 nss_warning("Could not allocate memory for local shadow buffer");
834 return 0;
835 }
836
837 size_wr = scnprintf(lbuf, size_al, "drv stats start:\n\n");
838 spin_lock_bh(&nss_top_main.stats_lock);
839 for (i = 0; (i < NSS_STATS_DRV_MAX); i++) {
840 stats_shadow[i] = nss_top_main.stats_drv[i];
841 }
842
843 spin_unlock_bh(&nss_top_main.stats_lock);
844
845 for (i = 0; (i < NSS_STATS_DRV_MAX); i++) {
846 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
847 "%s = %llu\n", nss_stats_str_drv[i], stats_shadow[i]);
848 }
849
850 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\ndrv stats end\n\n");
851 bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
852 kfree(lbuf);
853 kfree(stats_shadow);
854
855 return bytes_read;
856}
857
858/*
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530859 * nss_stats_pppoe_read()
860 * Read PPPoE stats
861 */
862static ssize_t nss_stats_pppoe_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
863{
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530864 int32_t i, j, k;
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530865
866 /*
867 * max output lines = #stats + start tag line + end tag line + three blank lines
868 */
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530869 uint32_t max_output_lines = (NSS_STATS_NODE_MAX + 2) + (NSS_STATS_PPPOE_MAX + 3) +
Ankit Dhanukaa1569ce2014-05-13 19:58:06 +0530870 ((NSS_MAX_PHYSICAL_INTERFACES * NSS_PPPOE_NUM_SESSION_PER_INTERFACE * (NSS_PPPOE_EXCEPTION_EVENT_MAX + 5)) + 3) + 5;
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530871 size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
872 size_t size_wr = 0;
873 ssize_t bytes_read = 0;
874 uint64_t *stats_shadow;
875
876 char *lbuf = kzalloc(size_al, GFP_KERNEL);
877 if (unlikely(lbuf == NULL)) {
878 nss_warning("Could not allocate memory for local statistics buffer");
879 return 0;
880 }
881
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530882 stats_shadow = kzalloc(64 * 8, GFP_KERNEL);
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530883 if (unlikely(stats_shadow == NULL)) {
884 nss_warning("Could not allocate memory for local shadow buffer");
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530885 kfree(lbuf);
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530886 return 0;
887 }
888
889 size_wr = scnprintf(lbuf, size_al, "pppoe stats start:\n\n");
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530890
891 /*
892 * Common node stats
893 */
Abhishek Rastogia1a07972014-04-01 19:43:33 +0530894 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "common node stats:\n\n");
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530895 spin_lock_bh(&nss_top_main.stats_lock);
896 for (i = 0; (i < NSS_STATS_NODE_MAX); i++) {
897 stats_shadow[i] = nss_top_main.stats_node[NSS_PPPOE_RX_INTERFACE][i];
898 }
899
900 spin_unlock_bh(&nss_top_main.stats_lock);
901
902 for (i = 0; (i < NSS_STATS_NODE_MAX); i++) {
903 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
904 "%s = %llu\n", nss_stats_str_node[i], stats_shadow[i]);
905 }
906
907 /*
908 * PPPoE node stats
909 */
Abhishek Rastogia1a07972014-04-01 19:43:33 +0530910 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "pppoe node stats:\n\n");
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530911 spin_lock_bh(&nss_top_main.stats_lock);
912 for (i = 0; (i < NSS_STATS_PPPOE_MAX); i++) {
913 stats_shadow[i] = nss_top_main.stats_pppoe[i];
914 }
915
916 spin_unlock_bh(&nss_top_main.stats_lock);
917
918 for (i = 0; (i < NSS_STATS_PPPOE_MAX); i++) {
919 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
920 "%s = %llu\n", nss_stats_str_pppoe[i], stats_shadow[i]);
921 }
922
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530923 /*
924 * Exception stats
925 */
926 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nException PPPoE:\n\n");
927
928 for (j = 0; j < NSS_MAX_PHYSICAL_INTERFACES; j++) {
929 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nInterface %d:\n\n", j);
930
931 spin_lock_bh(&nss_top_main.stats_lock);
932 for (k = 0; k < NSS_PPPOE_NUM_SESSION_PER_INTERFACE; k++) {
Ankit Dhanukaa1569ce2014-05-13 19:58:06 +0530933 for (i = 0; (i < NSS_PPPOE_EXCEPTION_EVENT_MAX); i++) {
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530934 stats_shadow_pppoe_except[k][i] = nss_top_main.stats_if_exception_pppoe[j][k][i];
935 }
936 }
937
938 spin_unlock_bh(&nss_top_main.stats_lock);
939
940 for (k = 0; k < NSS_PPPOE_NUM_SESSION_PER_INTERFACE; k++) {
941 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "%d. Session\n", k);
Ankit Dhanukaa1569ce2014-05-13 19:58:06 +0530942 for (i = 0; (i < NSS_PPPOE_EXCEPTION_EVENT_MAX); i++) {
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530943 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
944 "%s = %llu\n",
945 nss_stats_str_if_exception_pppoe[i],
946 stats_shadow_pppoe_except[k][i]);
947 }
948 }
949
950 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\npppoe stats end\n\n");
951 }
952
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530953 bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
954 kfree(lbuf);
955 kfree(stats_shadow);
956
957 return bytes_read;
958}
959
960/*
961 * nss_stats_gmac_read()
962 * Read GMAC stats
963 */
964static ssize_t nss_stats_gmac_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
965{
966 uint32_t i, id;
967
968 /*
969 * max output lines = ((#stats + start tag + one blank) * #GMACs) + start/end tag + 3 blank
970 */
971 uint32_t max_output_lines = ((NSS_STATS_GMAC_MAX + 2) * NSS_MAX_PHYSICAL_INTERFACES) + 5;
972 size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
973 size_t size_wr = 0;
974 ssize_t bytes_read = 0;
975 uint64_t *stats_shadow;
976
977 char *lbuf = kzalloc(size_al, GFP_KERNEL);
978 if (unlikely(lbuf == NULL)) {
979 nss_warning("Could not allocate memory for local statistics buffer");
980 return 0;
981 }
982
983 stats_shadow = kzalloc(NSS_STATS_GMAC_MAX * 8, GFP_KERNEL);
984 if (unlikely(stats_shadow == NULL)) {
985 nss_warning("Could not allocate memory for local shadow buffer");
986 return 0;
987 }
988
989 size_wr = scnprintf(lbuf, size_al, "gmac stats start:\n\n");
990
991 for (id = 0; id < NSS_MAX_PHYSICAL_INTERFACES; id++) {
992 spin_lock_bh(&nss_top_main.stats_lock);
993 for (i = 0; (i < NSS_STATS_GMAC_MAX); i++) {
994 stats_shadow[i] = nss_top_main.stats_gmac[id][i];
995 }
996
997 spin_unlock_bh(&nss_top_main.stats_lock);
998
999 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "GMAC ID: %d\n", id);
1000 for (i = 0; (i < NSS_STATS_GMAC_MAX); i++) {
1001 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
1002 "%s = %llu\n", nss_stats_str_gmac[i], stats_shadow[i]);
1003 }
1004 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,"\n");
1005 }
1006
1007 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\ngmac stats end\n\n");
1008 bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
1009 kfree(lbuf);
1010 kfree(stats_shadow);
1011
1012 return bytes_read;
1013}
1014
Saurabh Misra09dddeb2014-09-30 16:38:07 -07001015/*
1016 * Make a row for CAPWAP encap stats.
1017 */
1018static ssize_t nss_stats_capwap_encap(char *line, int len, int i, struct nss_capwap_tunnel_stats *s)
1019{
1020 char *header[] = { "TX Packets", "TX Bytes", "TX Drops", "Fragments", "QFull", "MemFail", "Unknown" };
1021 uint64_t tcnt = 0;
1022
1023 switch (i) {
1024 case 0:
1025 tcnt = s->pnode_stats.tx_packets;
1026 break;
1027 case 1:
1028 tcnt = s->pnode_stats.tx_bytes;
1029 break;
1030 case 2:
1031 tcnt = s->tx_dropped;
1032 break;
1033 case 3:
1034 tcnt = s->tx_segments;
1035 break;
1036 case 4:
1037 tcnt = s->tx_queue_full_drops;
1038 break;
1039 case 5:
1040 tcnt = s->tx_mem_failure_drops;
1041 break;
1042 default:
1043 i = 6;
1044 break;
1045 }
1046
1047 return (snprintf(line, len, "%14s %llu\n", header[i], tcnt));
1048}
1049
1050/*
1051 * Make a row for CAPWAP decap stats.
1052 */
1053static ssize_t nss_stats_capwap_decap(char *line, int len, int i, struct nss_capwap_tunnel_stats *s)
1054{
1055 char *header[] = { "RX Packets", "RX Bytes", "RX Dropped", "DTLS pkts", "Fragments", "OSzDrop", "FTimeout", "FDup", "QFull", "MemFail", "Unknown" };
1056 uint64_t tcnt = 0;
1057
1058 switch(i) {
1059 case 0:
1060 tcnt = s->pnode_stats.rx_packets;
1061 break;
1062 case 1:
1063 tcnt = s->pnode_stats.rx_bytes;
1064 break;
1065 case 2:
1066 tcnt = s->pnode_stats.rx_dropped;
1067 break;
1068 case 3:
1069 tcnt = s->dtls_pkts;
1070 break;
1071 case 4:
1072 tcnt = s->rx_segments;
1073 break;
1074 case 5:
1075 tcnt = s->oversize_drops;
1076 break;
1077 case 6:
1078 tcnt = s->frag_timeout_drops;
1079 break;
1080 case 7:
1081 tcnt = s->rx_dup_frag;
1082 break;
1083 case 8:
1084 tcnt = s->rx_queue_full_drops;
1085 return (snprintf(line, len, "%14s: %llu (n2h: %llu)\n", header[i], tcnt, s->rx_n2h_queue_full_drops));
1086 case 9:
1087 tcnt = s->rx_mem_failure_drops;
1088 break;
1089 default:
1090 i = 10;
1091 break;
1092 }
1093
1094 return (snprintf(line, len, "%14s: %llu\n", header[i], tcnt));
1095}
1096
1097/*
1098 * nss_stats_capwap_read()
1099 * Read CAPWAP stats
1100 */
1101static ssize_t nss_stats_capwap_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos, uint16_t type)
1102{
1103 struct nss_stats_data *data = fp->private_data;
1104 ssize_t bytes_read = 0;
1105 struct nss_capwap_tunnel_stats stats;
1106 size_t bytes;
1107 char line[80];
1108 int start, end;
1109 uint32_t if_num = NSS_DYNAMIC_IF_START;
1110 uint32_t max_if_num = NSS_DYNAMIC_IF_START + NSS_MAX_DYNAMIC_INTERFACES;
1111
1112 if (data) {
1113 if_num = data->if_num;
1114 }
1115
1116 /*
1117 * If we are done accomodating all the CAPWAP tunnels.
1118 */
1119 if (if_num > max_if_num) {
1120 return 0;
1121 }
1122
1123 for (; if_num <= max_if_num; if_num++) {
1124 bool isthere;
1125
1126 if (nss_is_dynamic_interface(if_num) == false) {
1127 continue;
1128 }
1129
1130 if (nss_dynamic_interface_get_type(if_num) != NSS_DYNAMIC_INTERFACE_TYPE_CAPWAP) {
1131 continue;
1132 }
1133
1134 /*
1135 * If CAPWAP tunnel does not exists, then isthere will be false.
1136 */
1137 isthere = nss_capwap_get_stats(if_num, &stats);
1138 if (!isthere) {
1139 continue;
1140 }
1141
1142 bytes = snprintf(line, sizeof(line), "(%2d) %9s %s\n", if_num, "Stats", "Total");
1143 if ((bytes_read + bytes) > sz) {
1144 break;
1145 }
1146
1147 if (copy_to_user(ubuf + bytes_read, line, bytes) != 0) {
1148 bytes_read = -EFAULT;
1149 goto fail;
1150 }
1151 bytes_read += bytes;
1152 start = 0;
1153 if (type == 1) {
1154 end = 5; /* encap */
1155 } else {
1156 end = 9; /* decap */
1157 }
1158 while (bytes_read < sz && start < end) {
1159 if (type == 1) {
1160 bytes = nss_stats_capwap_encap(line, sizeof(line), start, &stats);
1161 } else {
1162 bytes = nss_stats_capwap_decap(line, sizeof(line), start, &stats);
1163 }
1164
1165 if ((bytes_read + bytes) > sz)
1166 break;
1167
1168 if (copy_to_user(ubuf + bytes_read, line, bytes) != 0) {
1169 bytes_read = -EFAULT;
1170 goto fail;
1171 }
1172
1173 bytes_read += bytes;
1174 start++;
1175 }
1176 }
1177
1178 if (bytes_read > 0) {
1179 *ppos = bytes_read;
1180 }
1181
1182 if (data) {
1183 data->if_num = if_num;
1184 }
1185fail:
1186 return bytes_read;
1187}
1188
1189/*
1190 * nss_stats_capwap_decap_read()
1191 * Read CAPWAP decap stats
1192 */
1193static ssize_t nss_stats_capwap_decap_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
1194{
1195 return (nss_stats_capwap_read(fp, ubuf, sz, ppos, 0));
1196}
1197
1198/*
1199 * nss_stats_capwap_encap_read()
1200 * Read CAPWAP encap stats
1201 */
1202static ssize_t nss_stats_capwap_encap_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
1203{
1204 return (nss_stats_capwap_read(fp, ubuf, sz, ppos, 1));
1205}
1206
1207/*
1208 * nss_stats_open()
1209 */
1210static int nss_stats_open(struct inode *inode, struct file *filp)
1211{
1212 struct nss_stats_data *data = NULL;
1213
1214 data = kzalloc(sizeof(struct nss_stats_data), GFP_KERNEL);
1215 if (!data) {
1216 return -ENOMEM;
1217 }
1218 memset(data, 0, sizeof (struct nss_stats_data));
1219 data->if_num = NSS_DYNAMIC_IF_START;
1220 filp->private_data = data;
1221
1222 return 0;
1223}
1224
1225/*
1226 * nss_stats_release()
1227 */
1228static int nss_stats_release(struct inode *inode, struct file *filp)
1229{
1230 struct nss_stats_data *data = filp->private_data;
1231
1232 if (data) {
1233 kfree(data);
1234 }
1235
1236 return 0;
1237}
1238
Abhishek Rastogi38cffff2013-06-02 11:25:47 +05301239#define NSS_STATS_DECLARE_FILE_OPERATIONS(name) \
1240static const struct file_operations nss_stats_##name##_ops = { \
Saurabh Misra09dddeb2014-09-30 16:38:07 -07001241 .open = nss_stats_open, \
Abhishek Rastogi38cffff2013-06-02 11:25:47 +05301242 .read = nss_stats_##name##_read, \
1243 .llseek = generic_file_llseek, \
Saurabh Misra09dddeb2014-09-30 16:38:07 -07001244 .release = nss_stats_release, \
Abhishek Rastogi38cffff2013-06-02 11:25:47 +05301245};
1246
1247/*
1248 * nss_ipv4_stats_ops
1249 */
1250NSS_STATS_DECLARE_FILE_OPERATIONS(ipv4)
1251
1252/*
Selin Dag6d9b0c12014-11-04 18:27:21 -08001253 * ipv4_reasm_stats_ops
1254 */
1255NSS_STATS_DECLARE_FILE_OPERATIONS(ipv4_reasm)
1256
1257/*
Abhishek Rastogi38cffff2013-06-02 11:25:47 +05301258 * ipv6_stats_ops
1259 */
1260NSS_STATS_DECLARE_FILE_OPERATIONS(ipv6)
1261
1262/*
Abhishek Rastogi38cffff2013-06-02 11:25:47 +05301263 * n2h_stats_ops
1264 */
1265NSS_STATS_DECLARE_FILE_OPERATIONS(n2h)
Thomas Wuc3e382c2014-10-29 15:35:13 -07001266
1267/*
1268 * lso_rx_stats_ops
1269 */
1270NSS_STATS_DECLARE_FILE_OPERATIONS(lso_rx)
1271
Abhishek Rastogi38cffff2013-06-02 11:25:47 +05301272/*
1273 * drv_stats_ops
1274 */
1275NSS_STATS_DECLARE_FILE_OPERATIONS(drv)
1276
1277/*
Abhishek Rastogi38cffff2013-06-02 11:25:47 +05301278 * pppoe_stats_ops
1279 */
1280NSS_STATS_DECLARE_FILE_OPERATIONS(pppoe)
1281
1282/*
1283 * gmac_stats_ops
1284 */
1285NSS_STATS_DECLARE_FILE_OPERATIONS(gmac)
1286
1287/*
Saurabh Misra09dddeb2014-09-30 16:38:07 -07001288 * capwap_stats_ops
1289 */
1290NSS_STATS_DECLARE_FILE_OPERATIONS(capwap_encap)
1291NSS_STATS_DECLARE_FILE_OPERATIONS(capwap_decap)
1292
1293/*
Abhishek Rastogi84d95d02014-03-26 19:31:31 +05301294 * eth_rx_stats_ops
Abhishek Rastogi38cffff2013-06-02 11:25:47 +05301295 */
Abhishek Rastogi84d95d02014-03-26 19:31:31 +05301296NSS_STATS_DECLARE_FILE_OPERATIONS(eth_rx)
Abhishek Rastogi38cffff2013-06-02 11:25:47 +05301297
1298/*
1299 * nss_stats_init()
1300 * Enable NSS statistics
1301 */
1302void nss_stats_init(void)
1303{
1304 /*
1305 * NSS driver entry
1306 */
1307 nss_top_main.top_dentry = debugfs_create_dir("qca-nss-drv", NULL);
1308 if (unlikely(nss_top_main.top_dentry == NULL)) {
1309 nss_warning("Failed to create qca-nss-drv directory in debugfs");
1310
1311 /*
1312 * Non availability of debugfs directory is not a catastrophy
1313 * We can still go ahead with other initialization
1314 */
1315 return;
1316 }
1317
1318 nss_top_main.stats_dentry = debugfs_create_dir("stats", nss_top_main.top_dentry);
Abhishek Rastogi80f4eb12013-09-24 14:31:21 +05301319 if (unlikely(nss_top_main.stats_dentry == NULL)) {
Abhishek Rastogi38cffff2013-06-02 11:25:47 +05301320 nss_warning("Failed to create qca-nss-drv directory in debugfs");
1321
1322 /*
1323 * Non availability of debugfs directory is not a catastrophy
1324 * We can still go ahead with rest of initialization
1325 */
1326 return;
1327 }
1328
1329 /*
1330 * Create files to obtain statistics
1331 */
1332
1333 /*
1334 * ipv4_stats
1335 */
1336 nss_top_main.ipv4_dentry = debugfs_create_file("ipv4", 0400,
1337 nss_top_main.stats_dentry, &nss_top_main, &nss_stats_ipv4_ops);
1338 if (unlikely(nss_top_main.ipv4_dentry == NULL)) {
Abhishek Rastogi80f4eb12013-09-24 14:31:21 +05301339 nss_warning("Failed to create qca-nss-drv/stats/ipv4 file in debugfs");
Abhishek Rastogi38cffff2013-06-02 11:25:47 +05301340 return;
1341 }
1342
1343 /*
Selin Dag6d9b0c12014-11-04 18:27:21 -08001344 * ipv4_reasm_stats
1345 */
1346 nss_top_main.ipv4_reasm_dentry = debugfs_create_file("ipv4_reasm", 0400,
1347 nss_top_main.stats_dentry, &nss_top_main, &nss_stats_ipv4_reasm_ops);
1348 if (unlikely(nss_top_main.ipv4_reasm_dentry == NULL)) {
1349 nss_warning("Failed to create qca-nss-drv/stats/ipv4_reasm file in debugfs");
1350 return;
1351 }
1352
1353 /*
Abhishek Rastogi38cffff2013-06-02 11:25:47 +05301354 * ipv6_stats
1355 */
1356 nss_top_main.ipv6_dentry = debugfs_create_file("ipv6", 0400,
1357 nss_top_main.stats_dentry, &nss_top_main, &nss_stats_ipv6_ops);
1358 if (unlikely(nss_top_main.ipv6_dentry == NULL)) {
Abhishek Rastogi80f4eb12013-09-24 14:31:21 +05301359 nss_warning("Failed to create qca-nss-drv/stats/ipv6 file in debugfs");
Abhishek Rastogi38cffff2013-06-02 11:25:47 +05301360 return;
1361 }
1362
1363 /*
Abhishek Rastogi84d95d02014-03-26 19:31:31 +05301364 * ipv6_stats
Abhishek Rastogi38cffff2013-06-02 11:25:47 +05301365 */
Abhishek Rastogi84d95d02014-03-26 19:31:31 +05301366 nss_top_main.eth_rx_dentry = debugfs_create_file("eth_rx", 0400,
1367 nss_top_main.stats_dentry, &nss_top_main, &nss_stats_eth_rx_ops);
1368 if (unlikely(nss_top_main.eth_rx_dentry == NULL)) {
1369 nss_warning("Failed to create qca-nss-drv/stats/eth_rx file in debugfs");
Abhishek Rastogi38cffff2013-06-02 11:25:47 +05301370 return;
1371 }
1372
1373 /*
1374 * n2h_stats
1375 */
1376 nss_top_main.n2h_dentry = debugfs_create_file("n2h", 0400,
1377 nss_top_main.stats_dentry, &nss_top_main, &nss_stats_n2h_ops);
1378 if (unlikely(nss_top_main.n2h_dentry == NULL)) {
1379 nss_warning("Failed to create qca-nss-drv/stats/n2h directory in debugfs");
1380 return;
1381 }
1382
1383 /*
Thomas Wuc3e382c2014-10-29 15:35:13 -07001384 * lso_rx_stats
1385 */
1386 nss_top_main.lso_rx_dentry = debugfs_create_file("lso_rx", 0400,
1387 nss_top_main.stats_dentry, &nss_top_main, &nss_stats_lso_rx_ops);
1388 if (unlikely(nss_top_main.lso_rx_dentry == NULL)) {
1389 nss_warning("Failed to create qca-nss-drv/stats/lso_rx file in debugfs");
1390 return;
1391 }
1392
1393 /*
Abhishek Rastogi38cffff2013-06-02 11:25:47 +05301394 * drv_stats
1395 */
1396 nss_top_main.drv_dentry = debugfs_create_file("drv", 0400,
1397 nss_top_main.stats_dentry, &nss_top_main, &nss_stats_drv_ops);
1398 if (unlikely(nss_top_main.drv_dentry == NULL)) {
1399 nss_warning("Failed to create qca-nss-drv/stats/drv directory in debugfs");
1400 return;
1401 }
1402
1403 /*
Abhishek Rastogi38cffff2013-06-02 11:25:47 +05301404 * pppoe_stats
1405 */
1406 nss_top_main.pppoe_dentry = debugfs_create_file("pppoe", 0400,
1407 nss_top_main.stats_dentry, &nss_top_main, &nss_stats_pppoe_ops);
1408 if (unlikely(nss_top_main.pppoe_dentry == NULL)) {
Abhishek Rastogi80f4eb12013-09-24 14:31:21 +05301409 nss_warning("Failed to create qca-nss-drv/stats/pppoe file in debugfs");
Abhishek Rastogi38cffff2013-06-02 11:25:47 +05301410 return;
1411 }
1412
1413 /*
1414 * gmac_stats
1415 */
1416 nss_top_main.gmac_dentry = debugfs_create_file("gmac", 0400,
1417 nss_top_main.stats_dentry, &nss_top_main, &nss_stats_gmac_ops);
1418 if (unlikely(nss_top_main.gmac_dentry == NULL)) {
Abhishek Rastogi80f4eb12013-09-24 14:31:21 +05301419 nss_warning("Failed to create qca-nss-drv/stats/gmac file in debugfs");
Abhishek Rastogi38cffff2013-06-02 11:25:47 +05301420 return;
1421 }
Saurabh Misra09dddeb2014-09-30 16:38:07 -07001422
1423 /*
1424 * CAPWAP stats.
1425 */
1426 nss_top_main.capwap_encap_dentry = debugfs_create_file("capwap_encap", 0400,
1427 nss_top_main.stats_dentry, &nss_top_main, &nss_stats_capwap_encap_ops);
1428 if (unlikely(nss_top_main.capwap_encap_dentry == NULL)) {
1429 nss_warning("Failed to create qca-nss-drv/stats/capwap_encap file in debugfs");
1430 return;
1431 }
1432
1433 nss_top_main.capwap_decap_dentry = debugfs_create_file("capwap_decap", 0400,
1434 nss_top_main.stats_dentry, &nss_top_main, &nss_stats_capwap_decap_ops);
1435 if (unlikely(nss_top_main.capwap_decap_dentry == NULL)) {
1436 nss_warning("Failed to create qca-nss-drv/stats/capwap_decap file in debugfs");
1437 return;
1438 }
Abhishek Rastogi38cffff2013-06-02 11:25:47 +05301439}
1440
1441
1442/*
1443 * nss_stats_clean()
1444 * Cleanup NSS statistics files
1445 */
1446void nss_stats_clean(void)
1447{
1448 /*
1449 * Remove debugfs tree
1450 */
1451 if (likely(nss_top_main.top_dentry != NULL)) {
1452 debugfs_remove_recursive(nss_top_main.top_dentry);
1453 }
1454}