blob: 42cc6c5e2cc0115857cc9c00df1a8aefdfe5a2d5 [file] [log] [blame]
Radhakrishna Jiguru1c9b2252013-08-27 23:57:48 +05301/*
2 **************************************************************************
Zac Livingston866b0e22013-10-23 18:14:17 -06003 * Copyright (c) 2013, 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
37/*
38 * Statistics structures
39 */
40
41/*
42 * nss_stats_str_ipv4
43 * IPv4 stats strings
44 */
45static int8_t *nss_stats_str_ipv4[NSS_STATS_IPV4_MAX] = {
46 "rx_pkts",
47 "rx_bytes",
48 "tx_pkts",
49 "tx_bytes",
50 "create_requests",
51 "create_collisions",
52 "create_invalid_interface",
53 "destroy_requests",
54 "destroy_misses",
55 "hash_hits",
56 "hash_reorders",
57 "flushes",
58 "evictions"
59};
60
61/*
62 * nss_stats_str_ipv6
63 * IPv6 stats strings
64 */
65static int8_t *nss_stats_str_ipv6[NSS_STATS_IPV6_MAX] = {
66 "rx_pkts",
67 "rx_bytes",
68 "tx_pkts",
69 "tx_bytes",
70 "create_requests",
71 "create_collisions",
72 "create_invalid_interface",
73 "destroy_requests",
74 "destroy_misses",
75 "hash_hits",
76 "hash_reorders",
77 "flushes",
78 "evictions",
79};
80
81/*
82 * nss_stats_str_pbuf
83 * Pbuf stats strings
84 */
85static int8_t *nss_stats_str_pbuf[NSS_STATS_PBUF_MAX] = {
86 "pbuf_fails",
87 "payload_fails"
88};
89
90/*
91 * nss_stats_str_n2h
92 * N2H stats strings
93 */
94static int8_t *nss_stats_str_n2h[NSS_STATS_N2H_MAX] = {
95 "queue_dropped",
96 "ticks",
97 "worst_ticks",
98 "iterations"
99};
100
101/*
102 * nss_stats_str_drv
103 * Host driver stats strings
104 */
105static int8_t *nss_stats_str_drv[NSS_STATS_DRV_MAX] = {
106 "nbuf_alloc_errors",
107 "tx_queue_full[0]",
108 "tx_queue_full[1]",
109 "tx_buffers_empty",
110 "tx_buffers_pkt",
111 "tx_buffers_cmd",
112 "tx_buffers_crypto",
113 "rx_buffers_empty",
114 "rx_buffers_pkt",
115 "rx_buffers_cmd_resp",
116 "rx_buffers_status_sync",
117 "rx_buffers_crypto",
118 "rx_buffers_virtual"
119};
120
121/*
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530122 * nss_stats_str_pppoe
123 * PPPoE stats strings
124 */
125static int8_t *nss_stats_str_pppoe[NSS_STATS_PPPOE_MAX] = {
126 "create_requests",
127 "create_failures",
128 "destroy_requests",
129 "destroy_misses"
130};
131
132/*
133 * nss_stats_str_gmac
134 * GMAC stats strings
135 */
136static int8_t *nss_stats_str_gmac[NSS_STATS_GMAC_MAX] = {
137 "ticks",
138 "worst_ticks",
139 "iterations"
140};
141
142/*
143 * nss_stats_str_if_host
144 * Interface stats strings for host
145 */
146static int8_t *nss_stats_str_if_host[NSS_STATS_IF_HOST_MAX] = {
147 "rx_packets",
148 "rx_bytes",
149 "tx_packets",
150 "tx_bytes",
151
152};
153
154/*
155 * nss_stats_str_if_ipv4
156 * Interface stats strings for ipv4
157 */
158static int8_t *nss_stats_str_if_ipv4[NSS_STATS_IF_IPV4_MAX] = {
159 "rx_packets",
160 "rx_bytes",
161 "tx_packets",
162 "tx_bytes"
163};
164
165/*
166 * nss_stats_str_if_ipv6
167 * Interface stats strings for ipv6
168 */
169static int8_t *nss_stats_str_if_ipv6[NSS_STATS_IF_IPV6_MAX] = {
170 "rx_packets",
171 "rx_bytes",
172 "tx_packets",
173 "tx_bytes"
174};
175
176/*
177 * nss_stats_str_if_exception_unknown
178 * Interface stats strings for unknown exceptions
179 */
180static int8_t *nss_stats_str_if_exception_unknown[NSS_EXCEPTION_EVENT_UNKNOWN_MAX] = {
181 "UNKNOWN_L2_PROTOCOL"
182};
183
184/*
185 * nss_stats_str_if_exception_ipv4
186 * Interface stats strings for ipv4 exceptions
187 */
188static int8_t *nss_stats_str_if_exception_ipv4[NSS_EXCEPTION_EVENT_IPV4_MAX] = {
189 "IPV4_ICMP_HEADER_INCOMPLETE",
190 "IPV4_ICMP_UNHANDLED_TYPE",
191 "IPV4_ICMP_IPV4_HEADER_INCOMPLETE",
192 "IPV4_ICMP_IPV4_UDP_HEADER_INCOMPLETE",
193 "IPV4_ICMP_IPV4_TCP_HEADER_INCOMPLETE",
194 "IPV4_ICMP_IPV4_UNKNOWN_PROTOCOL",
195 "IPV4_ICMP_NO_ICME",
196 "IPV4_ICMP_FLUSH_TO_HOST",
197 "IPV4_TCP_HEADER_INCOMPLETE",
198 "IPV4_TCP_NO_ICME",
199 "IPV4_TCP_IP_OPTION",
200 "IPV4_TCP_IP_FRAGMENT",
201 "IPV4_TCP_SMALL_TTL",
202 "IPV4_TCP_NEEDS_FRAGMENTATION",
203 "IPV4_TCP_FLAGS",
204 "IPV4_TCP_SEQ_EXCEEDS_RIGHT_EDGE",
205 "IPV4_TCP_SMALL_DATA_OFFS",
206 "IPV4_TCP_BAD_SACK",
207 "IPV4_TCP_BIG_DATA_OFFS",
208 "IPV4_TCP_SEQ_BEFORE_LEFT_EDGE",
209 "IPV4_TCP_ACK_EXCEEDS_RIGHT_EDGE",
210 "IPV4_TCP_ACK_BEFORE_LEFT_EDGE",
211 "IPV4_UDP_HEADER_INCOMPLETE",
212 "IPV4_UDP_NO_ICME",
213 "IPV4_UDP_IP_OPTION",
214 "IPV4_UDP_IP_FRAGMENT",
215 "IPV4_UDP_SMALL_TTL",
216 "IPV4_UDP_NEEDS_FRAGMENTATION",
217 "IPV4_WRONG_TARGET_MAC",
218 "IPV4_HEADER_INCOMPLETE",
219 "IPV4_BAD_TOTAL_LENGTH",
220 "IPV4_BAD_CHECKSUM",
221 "IPV4_NON_INITIAL_FRAGMENT",
222 "IPV4_DATAGRAM_INCOMPLETE",
223 "IPV4_OPTIONS_INCOMPLETE",
224 "IPV4_UNKNOWN_PROTOCOL"
225};
226
227/*
228 * nss_stats_str_if_exception_ipv6
229 * Interface stats strings for ipv6 exceptions
230 */
231static int8_t *nss_stats_str_if_exception_ipv6[NSS_EXCEPTION_EVENT_IPV6_MAX] = {
232 "IPV6_ICMP_HEADER_INCOMPLETE",
233 "IPV6_ICMP_UNHANDLED_TYPE",
234 "IPV6_ICMP_IPV6_HEADER_INCOMPLETE",
235 "IPV6_ICMP_IPV6_UDP_HEADER_INCOMPLETE",
236 "IPV6_ICMP_IPV6_TCP_HEADER_INCOMPLETE",
237 "IPV6_ICMP_IPV6_UNKNOWN_PROTOCOL",
238 "IPV6_ICMP_NO_ICME",
239 "IPV6_ICMP_FLUSH_TO_HOST",
240 "IPV6_TCP_HEADER_INCOMPLETE",
241 "IPV6_TCP_NO_ICME",
242 "IPV6_TCP_SMALL_HOP_LIMIT",
243 "IPV6_TCP_NEEDS_FRAGMENTATION",
244 "IPV6_TCP_FLAGS",
245 "IPV6_TCP_SEQ_EXCEEDS_RIGHT_EDGE",
246 "IPV6_TCP_SMALL_DATA_OFFS",
247 "IPV6_TCP_BAD_SACK",
248 "IPV6_TCP_BIG_DATA_OFFS",
249 "IPV6_TCP_SEQ_BEFORE_LEFT_EDGE",
250 "IPV6_TCP_ACK_EXCEEDS_RIGHT_EDGE",
251 "IPV6_TCP_ACK_BEFORE_LEFT_EDGE",
252 "IPV6_UDP_HEADER_INCOMPLETE",
253 "IPV6_UDP_NO_ICME",
254 "IPV6_UDP_SMALL_HOP_LIMIT",
255 "IPV6_UDP_NEEDS_FRAGMENTATION",
256 "IPV6_WRONG_TARGET_MAC",
257 "IPV6_HEADER_INCOMPLETE",
258 "IPV6_UNKNOWN_PROTOCOL"
259};
260
261/*
262 * nss_stats_str_if_exception_pppoe
263 * Interface stats strings for PPPoE exceptions
264 */
265static int8_t *nss_stats_str_if_exception_pppoe[NSS_EXCEPTION_EVENT_PPPOE_MAX] = {
266 "PPPOE_WRONG_VERSION_OR_TYPE",
267 "PPPOE_WRONG_CODE",
268 "PPPOE_HEADER_INCOMPLETE",
269 "PPPOE_UNSUPPORTED_PPP_PROTOCOL"
270};
271
272/*
273 * nss_stats_ipv4_read()
274 * Read IPV4 stats
275 */
276static ssize_t nss_stats_ipv4_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
277{
278 int32_t i;
279
280 /*
281 * max output lines = #stats + start tag line + end tag line + three blank lines
282 */
283 uint32_t max_output_lines = NSS_STATS_IPV4_MAX + 5;
284 size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
285 size_t size_wr = 0;
286 ssize_t bytes_read = 0;
287 uint64_t *stats_shadow;
288
289 char *lbuf = kzalloc(size_al, GFP_KERNEL);
290 if (unlikely(lbuf == NULL)) {
291 nss_warning("Could not allocate memory for local statistics buffer");
292 return 0;
293 }
294
295 stats_shadow = kzalloc(NSS_STATS_IPV4_MAX * 8, GFP_KERNEL);
296 if (unlikely(stats_shadow == NULL)) {
297 nss_warning("Could not allocate memory for local shadow buffer");
298 return 0;
299 }
300
301 size_wr = scnprintf(lbuf, size_al,"ipv4 stats start:\n\n");
302 spin_lock_bh(&nss_top_main.stats_lock);
303 for (i = 0; (i < NSS_STATS_IPV4_MAX); i++) {
304 stats_shadow[i] = nss_top_main.stats_ipv4[i];
305 }
306
307 spin_unlock_bh(&nss_top_main.stats_lock);
308
309 for (i = 0; (i < NSS_STATS_IPV4_MAX); i++) {
310 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
311 "%s = %llu\n", nss_stats_str_ipv4[i], stats_shadow[i]);
312 }
313
314 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,"\nipv4 stats end\n\n");
315 bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
316 kfree(lbuf);
317 kfree(stats_shadow);
318
319 return bytes_read;
320}
321
322/*
323 * nss_stats_ipv6_read()
324 * Read IPv6 stats
325 */
326static ssize_t nss_stats_ipv6_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
327{
328 int32_t i;
329
330 /*
331 * max output lines = #stats + start tag line + end tag line + three blank lines
332 */
333 uint32_t max_output_lines = NSS_STATS_IPV6_MAX + 5;
334 size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
335 size_t size_wr = 0;
336 ssize_t bytes_read = 0;
337 uint64_t *stats_shadow;
338
339 char *lbuf = kzalloc(size_al, GFP_KERNEL);
340 if (unlikely(lbuf == NULL)) {
341 nss_warning("Could not allocate memory for local statistics buffer");
342 return 0;
343 }
344
345 stats_shadow = kzalloc(NSS_STATS_IPV6_MAX * 8, GFP_KERNEL);
346 if (unlikely(stats_shadow == NULL)) {
347 nss_warning("Could not allocate memory for local shadow buffer");
348 return 0;
349 }
350
351 size_wr = scnprintf(lbuf, size_al,"ipv6 stats start:\n\n");
352 spin_lock_bh(&nss_top_main.stats_lock);
353 for (i = 0; (i < NSS_STATS_IPV6_MAX); i++) {
354 stats_shadow[i] = nss_top_main.stats_ipv6[i];
355 }
356
357 spin_unlock_bh(&nss_top_main.stats_lock);
358
359 for (i = 0; (i < NSS_STATS_IPV6_MAX); i++) {
360 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
361 "%s = %llu\n", nss_stats_str_ipv6[i], stats_shadow[i]);
362 }
363
364 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nipv6 stats end\n\n");
365 bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
366 kfree(lbuf);
367 kfree(stats_shadow);
368
369 return bytes_read;
370}
371
372/*
373 * nss_stats_pbuf_read()
374 * Read pbuf manager stats
375 */
376static ssize_t nss_stats_pbuf_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
377{
378 int32_t i;
379
380 /*
381 * max output lines = #stats + start tag line + end tag line + three blank lines
382 */
383 uint32_t max_output_lines = NSS_STATS_PBUF_MAX + 5;
384 size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
385 size_t size_wr = 0;
386 ssize_t bytes_read = 0;
387 uint64_t *stats_shadow;
388
389 char *lbuf = kzalloc(size_al, GFP_KERNEL);
390 if (unlikely(lbuf == NULL)) {
391 nss_warning("Could not allocate memory for local statistics buffer");
392 return 0;
393 }
394
395 stats_shadow = kzalloc(NSS_STATS_PBUF_MAX * 8, GFP_KERNEL);
396 if (unlikely(stats_shadow == NULL)) {
397 nss_warning("Could not allocate memory for local shadow buffer");
398 return 0;
399 }
400
401 size_wr = scnprintf(lbuf, size_al, "pbuf_mgr stats start:\n\n");
402 spin_lock_bh(&nss_top_main.stats_lock);
403 for (i = 0; (i < NSS_STATS_PBUF_MAX); i++) {
404 stats_shadow[i] = nss_top_main.stats_pbuf[i];
405 }
406
407 spin_unlock_bh(&nss_top_main.stats_lock);
408
409 for (i = 0; (i < NSS_STATS_PBUF_MAX); i++) {
410 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
411 "%s = %llu\n", nss_stats_str_pbuf[i], stats_shadow[i]);
412 }
413
414 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\npbuf_mgr stats end\n\n");
415 bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
416 kfree(lbuf);
417 kfree(stats_shadow);
418
419 return bytes_read;
420}
421
422/*
423 * nss_stats_n2h_read()
424 * Read N2H stats
425 */
426static ssize_t nss_stats_n2h_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
427{
428 int32_t i;
429
430 /*
431 * max output lines = #stats + start tag line + end tag line + three blank lines
432 */
433 uint32_t max_output_lines = NSS_STATS_N2H_MAX + 5;
434 size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
435 size_t size_wr = 0;
436 ssize_t bytes_read = 0;
437 uint64_t *stats_shadow;
438
439 char *lbuf = kzalloc(size_al, GFP_KERNEL);
440 if (unlikely(lbuf == NULL)) {
441 nss_warning("Could not allocate memory for local statistics buffer");
442 return 0;
443 }
444
445 stats_shadow = kzalloc(NSS_STATS_N2H_MAX * 8, GFP_KERNEL);
446 if (unlikely(stats_shadow == NULL)) {
447 nss_warning("Could not allocate memory for local shadow buffer");
448 return 0;
449 }
450
451 size_wr = scnprintf(lbuf, size_al, "n2h stats start:\n\n");
452 spin_lock_bh(&nss_top_main.stats_lock);
453 for (i = 0; (i < NSS_STATS_N2H_MAX); i++) {
454 stats_shadow[i] = nss_top_main.stats_n2h[i];
455 }
456
457 spin_unlock_bh(&nss_top_main.stats_lock);
458
459 for (i = 0; (i < NSS_STATS_N2H_MAX); i++) {
460 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
461 "%s = %llu\n", nss_stats_str_n2h[i], stats_shadow[i]);
462 }
463
464 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nn2h stats end\n\n");
465 bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
466 kfree(lbuf);
467 kfree(stats_shadow);
468
469 return bytes_read;
470}
471
472/*
473 * nss_stats_drv_read()
474 * Read HLOS driver stats
475 */
476static ssize_t nss_stats_drv_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
477{
478 int32_t i;
479
480 /*
481 * max output lines = #stats + start tag line + end tag line + three blank lines
482 */
483 uint32_t max_output_lines = NSS_STATS_DRV_MAX + 5;
484 size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
485 size_t size_wr = 0;
486 ssize_t bytes_read = 0;
487 uint64_t *stats_shadow;
488
489 char *lbuf = kzalloc(size_al, GFP_KERNEL);
490 if (unlikely(lbuf == NULL)) {
491 nss_warning("Could not allocate memory for local statistics buffer");
492 return 0;
493 }
494
495 stats_shadow = kzalloc(NSS_STATS_DRV_MAX * 8, GFP_KERNEL);
496 if (unlikely(stats_shadow == NULL)) {
497 nss_warning("Could not allocate memory for local shadow buffer");
498 return 0;
499 }
500
501 size_wr = scnprintf(lbuf, size_al, "drv stats start:\n\n");
502 spin_lock_bh(&nss_top_main.stats_lock);
503 for (i = 0; (i < NSS_STATS_DRV_MAX); i++) {
504 stats_shadow[i] = nss_top_main.stats_drv[i];
505 }
506
507 spin_unlock_bh(&nss_top_main.stats_lock);
508
509 for (i = 0; (i < NSS_STATS_DRV_MAX); i++) {
510 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
511 "%s = %llu\n", nss_stats_str_drv[i], stats_shadow[i]);
512 }
513
514 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\ndrv stats end\n\n");
515 bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
516 kfree(lbuf);
517 kfree(stats_shadow);
518
519 return bytes_read;
520}
521
522/*
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530523 * nss_stats_pppoe_read()
524 * Read PPPoE stats
525 */
526static ssize_t nss_stats_pppoe_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
527{
528 int32_t i;
529
530 /*
531 * max output lines = #stats + start tag line + end tag line + three blank lines
532 */
533 uint32_t max_output_lines = NSS_STATS_PPPOE_MAX + 5;
534 size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
535 size_t size_wr = 0;
536 ssize_t bytes_read = 0;
537 uint64_t *stats_shadow;
538
539 char *lbuf = kzalloc(size_al, GFP_KERNEL);
540 if (unlikely(lbuf == NULL)) {
541 nss_warning("Could not allocate memory for local statistics buffer");
542 return 0;
543 }
544
545 stats_shadow = kzalloc(NSS_STATS_PPPOE_MAX * 8, GFP_KERNEL);
546 if (unlikely(stats_shadow == NULL)) {
547 nss_warning("Could not allocate memory for local shadow buffer");
548 return 0;
549 }
550
551 size_wr = scnprintf(lbuf, size_al, "pppoe stats start:\n\n");
552 spin_lock_bh(&nss_top_main.stats_lock);
553 for (i = 0; (i < NSS_STATS_PPPOE_MAX); i++) {
554 stats_shadow[i] = nss_top_main.stats_pppoe[i];
555 }
556
557 spin_unlock_bh(&nss_top_main.stats_lock);
558
559 for (i = 0; (i < NSS_STATS_PPPOE_MAX); i++) {
560 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
561 "%s = %llu\n", nss_stats_str_pppoe[i], stats_shadow[i]);
562 }
563
564 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\npppoe stats end\n\n");
565 bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
566 kfree(lbuf);
567 kfree(stats_shadow);
568
569 return bytes_read;
570}
571
572/*
573 * nss_stats_gmac_read()
574 * Read GMAC stats
575 */
576static ssize_t nss_stats_gmac_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
577{
578 uint32_t i, id;
579
580 /*
581 * max output lines = ((#stats + start tag + one blank) * #GMACs) + start/end tag + 3 blank
582 */
583 uint32_t max_output_lines = ((NSS_STATS_GMAC_MAX + 2) * NSS_MAX_PHYSICAL_INTERFACES) + 5;
584 size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
585 size_t size_wr = 0;
586 ssize_t bytes_read = 0;
587 uint64_t *stats_shadow;
588
589 char *lbuf = kzalloc(size_al, GFP_KERNEL);
590 if (unlikely(lbuf == NULL)) {
591 nss_warning("Could not allocate memory for local statistics buffer");
592 return 0;
593 }
594
595 stats_shadow = kzalloc(NSS_STATS_GMAC_MAX * 8, GFP_KERNEL);
596 if (unlikely(stats_shadow == NULL)) {
597 nss_warning("Could not allocate memory for local shadow buffer");
598 return 0;
599 }
600
601 size_wr = scnprintf(lbuf, size_al, "gmac stats start:\n\n");
602
603 for (id = 0; id < NSS_MAX_PHYSICAL_INTERFACES; id++) {
604 spin_lock_bh(&nss_top_main.stats_lock);
605 for (i = 0; (i < NSS_STATS_GMAC_MAX); i++) {
606 stats_shadow[i] = nss_top_main.stats_gmac[id][i];
607 }
608
609 spin_unlock_bh(&nss_top_main.stats_lock);
610
611 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "GMAC ID: %d\n", id);
612 for (i = 0; (i < NSS_STATS_GMAC_MAX); i++) {
613 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
614 "%s = %llu\n", nss_stats_str_gmac[i], stats_shadow[i]);
615 }
616 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,"\n");
617 }
618
619 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\ngmac stats end\n\n");
620 bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
621 kfree(lbuf);
622 kfree(stats_shadow);
623
624 return bytes_read;
625}
626
627/*
628 * nss_stats_if_read()
629 * Read interface stats
630 */
631static ssize_t nss_stats_if_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
632{
Murat Sezgin1e3422d2013-08-20 18:07:45 -0700633 uint32_t i, k, id;
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530634
635 /*
636 * max output lines per interface =
637 * (#ipv4 stats + start tag + blank line) +
638 * (#ipv6 stats + start tag + blank line) +
639 * (#host stats + start tag + blank line) +
640 * (#unknown exception stats + start tag + blank line) +
641 * (#ipv4 exception + start tag + blank line) +
642 * (#ipv6 exception + start tag + blank line) +
643 * (#pppoe exception + start tag + blank line) + interface start tag
644 *
645 * max output lines =
646 * (max output lines per interface * #interfaces) +
647 * (start tag + end tag + 3 blank lines)
648 */
649 uint32_t max_output_lines_interface = ((NSS_STATS_IF_IPV4_MAX + 2) + (NSS_STATS_IF_IPV6_MAX + 2) +
650 (NSS_STATS_IF_HOST_MAX + 2) + (NSS_EXCEPTION_EVENT_UNKNOWN_MAX + 2) +
651 (NSS_EXCEPTION_EVENT_IPV4_MAX + 2) + (NSS_EXCEPTION_EVENT_IPV6_MAX + 2) +
652 (NSS_EXCEPTION_EVENT_PPPOE_MAX + 2)) + 1;
653 size_t size_al = NSS_STATS_MAX_STR_LENGTH * ((max_output_lines_interface * NSS_MAX_NET_INTERFACES) + 5);
654 size_t size_wr = 0;
655 ssize_t bytes_read = 0;
656 uint64_t *stats_shadow;
Murat Sezgin1e3422d2013-08-20 18:07:45 -0700657 uint64_t pppoe_stats_shadow[NSS_PPPOE_NUM_SESSION_PER_INTERFACE][NSS_EXCEPTION_EVENT_PPPOE_MAX];
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530658
659 char *lbuf = kzalloc(size_al, GFP_KERNEL);
660 if (unlikely(lbuf == NULL)) {
661 nss_warning("Could not allocate memory for local statistics buffer");
662 return 0;
663 }
664
665 /*
666 * WARNING: We are only allocating memory for 64 stats counters per stats type
667 * Developers must ensure that number of counters are not more than 64
668 */
669
670 if ( (NSS_STATS_IF_IPV4_MAX > 64) ||
671 (NSS_STATS_IF_IPV6_MAX > 64) ||
672 (NSS_STATS_IF_HOST_MAX > 64) ||
673 (NSS_EXCEPTION_EVENT_UNKNOWN_MAX > 64) ||
674 (NSS_EXCEPTION_EVENT_IPV4_MAX > 64) ||
675 (NSS_EXCEPTION_EVENT_IPV6_MAX > 64) ||
676 (NSS_EXCEPTION_EVENT_PPPOE_MAX > 64)) {
677 nss_warning("Size of shadow stats structure is not enough to copy all stats");
678 }
679
680 stats_shadow = kzalloc(64 * 8, GFP_KERNEL);
681 if (unlikely(stats_shadow == NULL)) {
682 nss_warning("Could not allocate memory for local shadow buffer");
Murat Sezgin1e3422d2013-08-20 18:07:45 -0700683 kfree(lbuf);
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530684 return 0;
685 }
686
687 size_wr = scnprintf(lbuf, size_al, "if stats start:\n\n");
688
689 for (id = 0; id < NSS_MAX_NET_INTERFACES; id++) {
690 /*
691 * Host Stats
692 */
693 spin_lock_bh(&nss_top_main.stats_lock);
694 for (i = 0; (i < NSS_STATS_IF_HOST_MAX); i++) {
695 stats_shadow[i] = nss_top_main.stats_if_host[id][i];
696 }
697
698 spin_unlock_bh(&nss_top_main.stats_lock);
699
700 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "Interface ID: %d\n", id);
701 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "Host:\n");
702 for (i = 0; (i < NSS_STATS_IF_HOST_MAX); i++) {
703 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
704 "%s = %llu\n", nss_stats_str_if_host[i], stats_shadow[i]);
705 }
706
707 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\n");
708
709 /*
710 * IPv4 stats
711 */
712 spin_lock_bh(&nss_top_main.stats_lock);
713 for (i = 0; (i < NSS_STATS_IF_IPV4_MAX); i++) {
714 stats_shadow[i] = nss_top_main.stats_if_ipv4[id][i];
715 }
716
717 spin_unlock_bh(&nss_top_main.stats_lock);
718
719 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "IPv4:\n");
720 for (i = 0; (i < NSS_STATS_IF_IPV4_MAX); i++) {
721 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
722 "%s = %llu\n", nss_stats_str_if_ipv4[i], stats_shadow[i]);
723 }
724
725 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\n");
726
727 /*
728 * IPv6 stats
729 */
730 spin_lock_bh(&nss_top_main.stats_lock);
731 for (i = 0; (i < NSS_STATS_IF_IPV6_MAX); i++) {
732 stats_shadow[i] = nss_top_main.stats_if_ipv6[id][i];
733 }
734
735 spin_unlock_bh(&nss_top_main.stats_lock);
736
737 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "IPv6:\n");
738 for (i = 0; (i < NSS_STATS_IF_IPV6_MAX); i++) {
739 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
740 "%s = %llu\n", nss_stats_str_if_ipv6[i], stats_shadow[i]);
741 }
742
743 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\n");
744
745 /*
746 * Unknown exception stats
747 */
748 spin_lock_bh(&nss_top_main.stats_lock);
749 for (i = 0; (i < NSS_EXCEPTION_EVENT_UNKNOWN_MAX); i++) {
750 stats_shadow[i] = nss_top_main.stats_if_exception_unknown[id][i];
751 }
752
753 spin_unlock_bh(&nss_top_main.stats_lock);
754
755 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "Exception Unknown:\n");
756 for (i = 0; (i < NSS_EXCEPTION_EVENT_UNKNOWN_MAX); i++) {
757 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
758 "%s = %llu\n",
759 nss_stats_str_if_exception_unknown[i],
760 stats_shadow[i]);
761 }
762
763 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\n");
764
765 /*
766 * IPv4 exception stats
767 */
768 spin_lock_bh(&nss_top_main.stats_lock);
769 for (i = 0; (i < NSS_EXCEPTION_EVENT_IPV4_MAX); i++) {
770 stats_shadow[i] = nss_top_main.stats_if_exception_ipv4[id][i];
771 }
772
773 spin_unlock_bh(&nss_top_main.stats_lock);
774
775 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "Exception IPv4:\n");
776 for (i = 0; (i < NSS_EXCEPTION_EVENT_IPV4_MAX); i++) {
777 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
778 "%s = %llu\n",
779 nss_stats_str_if_exception_ipv4[i],
780 stats_shadow[i]);
781 }
782
783 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\n");
784
785 /*
786 * IPv6 exception stats
787 */
788 spin_lock_bh(&nss_top_main.stats_lock);
789 for (i = 0; (i < NSS_EXCEPTION_EVENT_IPV6_MAX); i++) {
790 stats_shadow[i] = nss_top_main.stats_if_exception_ipv6[id][i];
791 }
792
793 spin_unlock_bh(&nss_top_main.stats_lock);
794
795 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "Exception IPv6:\n");
796 for (i = 0; (i < NSS_EXCEPTION_EVENT_IPV6_MAX); i++) {
797 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
798 "%s = %llu\n",
799 nss_stats_str_if_exception_ipv6[i],
800 stats_shadow[i]);
801 }
802 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\n");
803
804
805 /*
806 * Exception PPPoE
807 */
808 spin_lock_bh(&nss_top_main.stats_lock);
Murat Sezgin1e3422d2013-08-20 18:07:45 -0700809 for (k = 0; k < NSS_PPPOE_NUM_SESSION_PER_INTERFACE; k++) {
810 for (i = 0; (i < NSS_EXCEPTION_EVENT_PPPOE_MAX); i++) {
811 pppoe_stats_shadow[k][i] = nss_top_main.stats_if_exception_pppoe[id][k][i];
812 }
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530813 }
814
815 spin_unlock_bh(&nss_top_main.stats_lock);
816
817 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "Exception PPPoE:\n");
Murat Sezgin1e3422d2013-08-20 18:07:45 -0700818 for (k = 0; k < NSS_PPPOE_NUM_SESSION_PER_INTERFACE; k++) {
819 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "%d. Session\n", k);
820 for (i = 0; (i < NSS_EXCEPTION_EVENT_PPPOE_MAX); i++) {
821 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
822 "%s = %llu\n",
823 nss_stats_str_if_exception_pppoe[i],
824 pppoe_stats_shadow[k][i]);
825 }
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530826 }
827 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\n");
828 }
829
830 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nif stats end\n\n");
831 bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
832 kfree(lbuf);
833 kfree(stats_shadow);
834
835 return bytes_read;
836}
837
838
839#define NSS_STATS_DECLARE_FILE_OPERATIONS(name) \
840static const struct file_operations nss_stats_##name##_ops = { \
841 .open = simple_open, \
842 .read = nss_stats_##name##_read, \
843 .llseek = generic_file_llseek, \
844};
845
846/*
847 * nss_ipv4_stats_ops
848 */
849NSS_STATS_DECLARE_FILE_OPERATIONS(ipv4)
850
851/*
852 * ipv6_stats_ops
853 */
854NSS_STATS_DECLARE_FILE_OPERATIONS(ipv6)
855
856/*
857 * pbuf_stats_ops
858 */
859NSS_STATS_DECLARE_FILE_OPERATIONS(pbuf)
860
861/*
862 * n2h_stats_ops
863 */
864NSS_STATS_DECLARE_FILE_OPERATIONS(n2h)
865/*
866 * drv_stats_ops
867 */
868NSS_STATS_DECLARE_FILE_OPERATIONS(drv)
869
870/*
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530871 * pppoe_stats_ops
872 */
873NSS_STATS_DECLARE_FILE_OPERATIONS(pppoe)
874
875/*
876 * gmac_stats_ops
877 */
878NSS_STATS_DECLARE_FILE_OPERATIONS(gmac)
879
880/*
881 * if_stats_ops
882 */
883NSS_STATS_DECLARE_FILE_OPERATIONS(if)
884
885/*
886 * nss_stats_init()
887 * Enable NSS statistics
888 */
889void nss_stats_init(void)
890{
891 /*
892 * NSS driver entry
893 */
894 nss_top_main.top_dentry = debugfs_create_dir("qca-nss-drv", NULL);
895 if (unlikely(nss_top_main.top_dentry == NULL)) {
896 nss_warning("Failed to create qca-nss-drv directory in debugfs");
897
898 /*
899 * Non availability of debugfs directory is not a catastrophy
900 * We can still go ahead with other initialization
901 */
902 return;
903 }
904
905 nss_top_main.stats_dentry = debugfs_create_dir("stats", nss_top_main.top_dentry);
Abhishek Rastogi80f4eb12013-09-24 14:31:21 +0530906 if (unlikely(nss_top_main.stats_dentry == NULL)) {
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530907 nss_warning("Failed to create qca-nss-drv directory in debugfs");
908
909 /*
910 * Non availability of debugfs directory is not a catastrophy
911 * We can still go ahead with rest of initialization
912 */
913 return;
914 }
915
916 /*
917 * Create files to obtain statistics
918 */
919
920 /*
921 * ipv4_stats
922 */
923 nss_top_main.ipv4_dentry = debugfs_create_file("ipv4", 0400,
924 nss_top_main.stats_dentry, &nss_top_main, &nss_stats_ipv4_ops);
925 if (unlikely(nss_top_main.ipv4_dentry == NULL)) {
Abhishek Rastogi80f4eb12013-09-24 14:31:21 +0530926 nss_warning("Failed to create qca-nss-drv/stats/ipv4 file in debugfs");
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530927 return;
928 }
929
930 /*
931 * ipv6_stats
932 */
933 nss_top_main.ipv6_dentry = debugfs_create_file("ipv6", 0400,
934 nss_top_main.stats_dentry, &nss_top_main, &nss_stats_ipv6_ops);
935 if (unlikely(nss_top_main.ipv6_dentry == NULL)) {
Abhishek Rastogi80f4eb12013-09-24 14:31:21 +0530936 nss_warning("Failed to create qca-nss-drv/stats/ipv6 file in debugfs");
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530937 return;
938 }
939
940 /*
941 * pbuf_stats
942 */
943 nss_top_main.pbuf_dentry = debugfs_create_file("pbuf_mgr", 0400,
944 nss_top_main.stats_dentry, &nss_top_main, &nss_stats_pbuf_ops);
945 if (unlikely(nss_top_main.pbuf_dentry == NULL)) {
Abhishek Rastogi80f4eb12013-09-24 14:31:21 +0530946 nss_warning("Failed to create qca-nss-drv/stats/pbuf file in debugfs");
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530947 return;
948 }
949
950 /*
951 * n2h_stats
952 */
953 nss_top_main.n2h_dentry = debugfs_create_file("n2h", 0400,
954 nss_top_main.stats_dentry, &nss_top_main, &nss_stats_n2h_ops);
955 if (unlikely(nss_top_main.n2h_dentry == NULL)) {
956 nss_warning("Failed to create qca-nss-drv/stats/n2h directory in debugfs");
957 return;
958 }
959
960 /*
961 * drv_stats
962 */
963 nss_top_main.drv_dentry = debugfs_create_file("drv", 0400,
964 nss_top_main.stats_dentry, &nss_top_main, &nss_stats_drv_ops);
965 if (unlikely(nss_top_main.drv_dentry == NULL)) {
966 nss_warning("Failed to create qca-nss-drv/stats/drv directory in debugfs");
967 return;
968 }
969
970 /*
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530971 * pppoe_stats
972 */
973 nss_top_main.pppoe_dentry = debugfs_create_file("pppoe", 0400,
974 nss_top_main.stats_dentry, &nss_top_main, &nss_stats_pppoe_ops);
975 if (unlikely(nss_top_main.pppoe_dentry == NULL)) {
Abhishek Rastogi80f4eb12013-09-24 14:31:21 +0530976 nss_warning("Failed to create qca-nss-drv/stats/pppoe file in debugfs");
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530977 return;
978 }
979
980 /*
981 * gmac_stats
982 */
983 nss_top_main.gmac_dentry = debugfs_create_file("gmac", 0400,
984 nss_top_main.stats_dentry, &nss_top_main, &nss_stats_gmac_ops);
985 if (unlikely(nss_top_main.gmac_dentry == NULL)) {
Abhishek Rastogi80f4eb12013-09-24 14:31:21 +0530986 nss_warning("Failed to create qca-nss-drv/stats/gmac file in debugfs");
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530987 return;
988 }
989
990 /*
991 * interface_stats
992 */
993 nss_top_main.if_dentry = debugfs_create_file("interface", 0400,
994 nss_top_main.stats_dentry, &nss_top_main, &nss_stats_if_ops);
995 if (unlikely(nss_top_main.if_dentry == NULL)) {
Abhishek Rastogi80f4eb12013-09-24 14:31:21 +0530996 nss_warning("Failed to create qca-nss-drv/stats/interface file in debugfs");
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530997 return;
998 }
999}
1000
1001
1002/*
1003 * nss_stats_clean()
1004 * Cleanup NSS statistics files
1005 */
1006void nss_stats_clean(void)
1007{
1008 /*
1009 * Remove debugfs tree
1010 */
1011 if (likely(nss_top_main.top_dentry != NULL)) {
1012 debugfs_remove_recursive(nss_top_main.top_dentry);
1013 }
1014}