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