blob: bcefadd89026af1031e5c711279859ddc9183a40 [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/*
120 * nss_stats_str_drv
121 * Host driver stats strings
122 */
123static int8_t *nss_stats_str_drv[NSS_STATS_DRV_MAX] = {
124 "nbuf_alloc_errors",
125 "tx_queue_full[0]",
126 "tx_queue_full[1]",
127 "tx_buffers_empty",
128 "tx_buffers_pkt",
129 "tx_buffers_cmd",
130 "tx_buffers_crypto",
131 "rx_buffers_empty",
132 "rx_buffers_pkt",
133 "rx_buffers_cmd_resp",
134 "rx_buffers_status_sync",
135 "rx_buffers_crypto",
136 "rx_buffers_virtual"
137};
138
139/*
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530140 * nss_stats_str_pppoe
141 * PPPoE stats strings
142 */
143static int8_t *nss_stats_str_pppoe[NSS_STATS_PPPOE_MAX] = {
144 "create_requests",
145 "create_failures",
146 "destroy_requests",
147 "destroy_misses"
148};
149
150/*
151 * nss_stats_str_gmac
152 * GMAC stats strings
153 */
154static int8_t *nss_stats_str_gmac[NSS_STATS_GMAC_MAX] = {
155 "ticks",
156 "worst_ticks",
157 "iterations"
158};
159
160/*
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530161 * nss_stats_str_node
162 * Interface stats strings per node
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530163 */
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530164static int8_t *nss_stats_str_node[NSS_STATS_NODE_MAX] = {
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530165 "rx_packets",
166 "rx_bytes",
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530167 "rx_dropped",
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530168 "tx_packets",
169 "tx_bytes"
170};
171
172/*
Murat Sezgin99dab642014-08-28 14:40:34 -0700173 * nss_stats_str_eth_rx
174 * eth_rx stats strings
175 */
176static int8_t *nss_stats_str_eth_rx[NSS_STATS_ETH_RX_MAX] = {
177 "ticks",
178 "worst_ticks",
179 "iterations"
180};
181
182/*
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530183 * nss_stats_str_if_exception_unknown
184 * Interface stats strings for unknown exceptions
185 */
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530186static int8_t *nss_stats_str_if_exception_eth_rx[NSS_EXCEPTION_EVENT_ETH_RX_MAX] = {
187 "UNKNOWN_L3_PROTOCOL"
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530188};
189
190/*
191 * nss_stats_str_if_exception_ipv4
192 * Interface stats strings for ipv4 exceptions
193 */
194static int8_t *nss_stats_str_if_exception_ipv4[NSS_EXCEPTION_EVENT_IPV4_MAX] = {
195 "IPV4_ICMP_HEADER_INCOMPLETE",
196 "IPV4_ICMP_UNHANDLED_TYPE",
197 "IPV4_ICMP_IPV4_HEADER_INCOMPLETE",
198 "IPV4_ICMP_IPV4_UDP_HEADER_INCOMPLETE",
199 "IPV4_ICMP_IPV4_TCP_HEADER_INCOMPLETE",
200 "IPV4_ICMP_IPV4_UNKNOWN_PROTOCOL",
201 "IPV4_ICMP_NO_ICME",
202 "IPV4_ICMP_FLUSH_TO_HOST",
203 "IPV4_TCP_HEADER_INCOMPLETE",
204 "IPV4_TCP_NO_ICME",
205 "IPV4_TCP_IP_OPTION",
206 "IPV4_TCP_IP_FRAGMENT",
207 "IPV4_TCP_SMALL_TTL",
208 "IPV4_TCP_NEEDS_FRAGMENTATION",
209 "IPV4_TCP_FLAGS",
210 "IPV4_TCP_SEQ_EXCEEDS_RIGHT_EDGE",
211 "IPV4_TCP_SMALL_DATA_OFFS",
212 "IPV4_TCP_BAD_SACK",
213 "IPV4_TCP_BIG_DATA_OFFS",
214 "IPV4_TCP_SEQ_BEFORE_LEFT_EDGE",
215 "IPV4_TCP_ACK_EXCEEDS_RIGHT_EDGE",
216 "IPV4_TCP_ACK_BEFORE_LEFT_EDGE",
217 "IPV4_UDP_HEADER_INCOMPLETE",
218 "IPV4_UDP_NO_ICME",
219 "IPV4_UDP_IP_OPTION",
220 "IPV4_UDP_IP_FRAGMENT",
221 "IPV4_UDP_SMALL_TTL",
222 "IPV4_UDP_NEEDS_FRAGMENTATION",
223 "IPV4_WRONG_TARGET_MAC",
224 "IPV4_HEADER_INCOMPLETE",
225 "IPV4_BAD_TOTAL_LENGTH",
226 "IPV4_BAD_CHECKSUM",
227 "IPV4_NON_INITIAL_FRAGMENT",
228 "IPV4_DATAGRAM_INCOMPLETE",
229 "IPV4_OPTIONS_INCOMPLETE",
Radha krishna Simha Jiguru59a1a1c2014-01-27 18:29:40 +0530230 "IPV4_UNKNOWN_PROTOCOL",
231 "IPV4_ESP_HEADER_INCOMPLETE",
232 "IPV4_ESP_NO_ICME",
233 "IPV4_ESP_IP_OPTION",
234 "IPV4_ESP_IP_FRAGMENT",
235 "IPV4_ESP_SMALL_TTL",
236 "IPV4_ESP_NEEDS_FRAGMENTATION",
237 "IPV4_INGRESS_VID_MISMATCH",
Thomas Wu8d6f4b22014-06-09 14:46:18 -0700238 "IPV4_INGRESS_VID_MISSING",
Radha krishna Simha Jiguru59a1a1c2014-01-27 18:29:40 +0530239 "IPV4_6RD_NO_ICME",
240 "IPV4_6RD_IP_OPTION",
241 "IPV4_6RD_IP_FRAGMENT",
Murat Sezgin0c0561d2014-04-09 18:55:58 -0700242 "IPV4_6RD_NEEDS_FRAGMENTATION",
243 "IPV4_DSCP_MARKING_MISMATCH",
Murat Sezgin7c5956a2014-05-12 09:59:51 -0700244 "IPV4_VLAN_MARKING_MISMATCH",
Thomas Wu8d6f4b22014-06-09 14:46:18 -0700245 "IPV4_INTERFACE_MISMATCH",
Radha krishna Simha Jiguru00cfe562014-10-21 16:22:12 +0530246 "IPV4_GRE_HEADER_INCOMPLETE",
247 "IPV4_GRE_NO_ICME",
248 "IPV4_GRE_IP_OPTION",
249 "IPV4_GRE_IP_FRAGMENT",
250 "IPV4_GRE_SMALL_TTL",
251 "IPV4_GRE_NEEDS_FRAGMENTATION",
Selin Dag60ea2b22014-11-05 09:36:22 -0800252 "IPV4_FRAG_DF_SET",
253 "IPV4_FRAG_FAIL",
Thomas Wu8d6f4b22014-06-09 14:46:18 -0700254 "IPV4_DESTROY"
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530255};
256
257/*
258 * nss_stats_str_if_exception_ipv6
259 * Interface stats strings for ipv6 exceptions
260 */
261static int8_t *nss_stats_str_if_exception_ipv6[NSS_EXCEPTION_EVENT_IPV6_MAX] = {
262 "IPV6_ICMP_HEADER_INCOMPLETE",
263 "IPV6_ICMP_UNHANDLED_TYPE",
264 "IPV6_ICMP_IPV6_HEADER_INCOMPLETE",
265 "IPV6_ICMP_IPV6_UDP_HEADER_INCOMPLETE",
266 "IPV6_ICMP_IPV6_TCP_HEADER_INCOMPLETE",
267 "IPV6_ICMP_IPV6_UNKNOWN_PROTOCOL",
268 "IPV6_ICMP_NO_ICME",
269 "IPV6_ICMP_FLUSH_TO_HOST",
270 "IPV6_TCP_HEADER_INCOMPLETE",
271 "IPV6_TCP_NO_ICME",
272 "IPV6_TCP_SMALL_HOP_LIMIT",
273 "IPV6_TCP_NEEDS_FRAGMENTATION",
274 "IPV6_TCP_FLAGS",
275 "IPV6_TCP_SEQ_EXCEEDS_RIGHT_EDGE",
276 "IPV6_TCP_SMALL_DATA_OFFS",
277 "IPV6_TCP_BAD_SACK",
278 "IPV6_TCP_BIG_DATA_OFFS",
279 "IPV6_TCP_SEQ_BEFORE_LEFT_EDGE",
280 "IPV6_TCP_ACK_EXCEEDS_RIGHT_EDGE",
281 "IPV6_TCP_ACK_BEFORE_LEFT_EDGE",
282 "IPV6_UDP_HEADER_INCOMPLETE",
283 "IPV6_UDP_NO_ICME",
284 "IPV6_UDP_SMALL_HOP_LIMIT",
285 "IPV6_UDP_NEEDS_FRAGMENTATION",
286 "IPV6_WRONG_TARGET_MAC",
287 "IPV6_HEADER_INCOMPLETE",
Radha krishna Simha Jiguru59a1a1c2014-01-27 18:29:40 +0530288 "IPV6_UNKNOWN_PROTOCOL",
Murat Sezgin0c0561d2014-04-09 18:55:58 -0700289 "IPV6_INGRESS_VID_MISMATCH",
Thomas Wu8d6f4b22014-06-09 14:46:18 -0700290 "IPV6_INGRESS_VID_MISSING",
Murat Sezgin0c0561d2014-04-09 18:55:58 -0700291 "IPV6_DSCP_MARKING_MISMATCH",
292 "IPV6_VLAN_MARKING_MISMATCH",
Thomas Wu8d6f4b22014-06-09 14:46:18 -0700293 "IPV6_INTERFACE_MISMATCH",
294 "IPV6_DESTROY"
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530295};
296
297/*
298 * nss_stats_str_if_exception_pppoe
299 * Interface stats strings for PPPoE exceptions
300 */
Ankit Dhanukaa1569ce2014-05-13 19:58:06 +0530301static int8_t *nss_stats_str_if_exception_pppoe[NSS_PPPOE_EXCEPTION_EVENT_MAX] = {
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530302 "PPPOE_WRONG_VERSION_OR_TYPE",
303 "PPPOE_WRONG_CODE",
304 "PPPOE_HEADER_INCOMPLETE",
Murat Sezgin7c5956a2014-05-12 09:59:51 -0700305 "PPPOE_UNSUPPORTED_PPP_PROTOCOL",
306 "PPPOE_INTERFACE_MISMATCH"
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530307};
308
309/*
310 * nss_stats_ipv4_read()
311 * Read IPV4 stats
312 */
313static ssize_t nss_stats_ipv4_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
314{
315 int32_t i;
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530316 /*
317 * max output lines = #stats + start tag line + end tag line + three blank lines
318 */
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530319 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 +0530320 size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
321 size_t size_wr = 0;
322 ssize_t bytes_read = 0;
323 uint64_t *stats_shadow;
324
325 char *lbuf = kzalloc(size_al, GFP_KERNEL);
326 if (unlikely(lbuf == NULL)) {
327 nss_warning("Could not allocate memory for local statistics buffer");
328 return 0;
329 }
330
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530331 /*
332 * Note: The assumption here is that exception event count is larger than other statistics count for IPv4
333 */
334 stats_shadow = kzalloc(NSS_EXCEPTION_EVENT_IPV4_MAX * 8, GFP_KERNEL);
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530335 if (unlikely(stats_shadow == NULL)) {
336 nss_warning("Could not allocate memory for local shadow buffer");
337 return 0;
338 }
339
Abhishek Rastogia1a07972014-04-01 19:43:33 +0530340 size_wr = scnprintf(lbuf, size_al, "ipv4 stats start:\n\n");
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530341
342 /*
343 * Common node stats
344 */
Abhishek Rastogia1a07972014-04-01 19:43:33 +0530345 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "common node stats:\n\n");
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530346 spin_lock_bh(&nss_top_main.stats_lock);
347 for (i = 0; (i < NSS_STATS_NODE_MAX); i++) {
348 stats_shadow[i] = nss_top_main.stats_node[NSS_IPV4_RX_INTERFACE][i];
349 }
350
351 spin_unlock_bh(&nss_top_main.stats_lock);
352
353 for (i = 0; (i < NSS_STATS_NODE_MAX); i++) {
354 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
355 "%s = %llu\n", nss_stats_str_node[i], stats_shadow[i]);
356 }
357
358 /*
359 * IPv4 node stats
360 */
Abhishek Rastogia1a07972014-04-01 19:43:33 +0530361 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nipv4 node stats:\n\n");
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530362
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530363 spin_lock_bh(&nss_top_main.stats_lock);
364 for (i = 0; (i < NSS_STATS_IPV4_MAX); i++) {
365 stats_shadow[i] = nss_top_main.stats_ipv4[i];
366 }
367
368 spin_unlock_bh(&nss_top_main.stats_lock);
369
370 for (i = 0; (i < NSS_STATS_IPV4_MAX); i++) {
371 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
372 "%s = %llu\n", nss_stats_str_ipv4[i], stats_shadow[i]);
373 }
374
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530375 /*
376 * Exception stats
377 */
Abhishek Rastogia1a07972014-04-01 19:43:33 +0530378 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nipv4 exception stats:\n\n");
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530379
380 spin_lock_bh(&nss_top_main.stats_lock);
381 for (i = 0; (i < NSS_EXCEPTION_EVENT_IPV4_MAX); i++) {
382 stats_shadow[i] = nss_top_main.stats_if_exception_ipv4[i];
383 }
384
385 spin_unlock_bh(&nss_top_main.stats_lock);
386
387 for (i = 0; (i < NSS_EXCEPTION_EVENT_IPV4_MAX); i++) {
388 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
389 "%s = %llu\n", nss_stats_str_if_exception_ipv4[i], stats_shadow[i]);
390 }
391
Abhishek Rastogia1a07972014-04-01 19:43:33 +0530392 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nipv4 stats end\n\n");
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530393 bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
394 kfree(lbuf);
395 kfree(stats_shadow);
396
397 return bytes_read;
398}
399
400/*
Selin Dag6d9b0c12014-11-04 18:27:21 -0800401 * nss_stats_ipv4_reasm_read()
402 * Read IPV4 reassembly stats
403 */
404static ssize_t nss_stats_ipv4_reasm_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
405{
406 int32_t i;
407 /*
408 * max output lines = #stats + start tag line + end tag line + three blank lines
409 */
410 uint32_t max_output_lines = (NSS_STATS_NODE_MAX + 2) + (NSS_STATS_IPV4_REASM_MAX + 3) + 5;
411 size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
412 size_t size_wr = 0;
413 ssize_t bytes_read = 0;
414 uint64_t *stats_shadow;
415
416 char *lbuf = kzalloc(size_al, GFP_KERNEL);
417 if (unlikely(lbuf == NULL)) {
418 nss_warning("Could not allocate memory for local statistics buffer");
419 return 0;
420 }
421
422 stats_shadow = kzalloc(NSS_STATS_IPV4_REASM_MAX * 8, GFP_KERNEL);
423 if (unlikely(stats_shadow == NULL)) {
424 nss_warning("Could not allocate memory for local shadow buffer");
425 return 0;
426 }
427
428 size_wr = scnprintf(lbuf, size_al, "ipv4 reasm stats start:\n\n");
429
430 /*
431 * Common node stats
432 */
433 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "common node stats:\n\n");
434 spin_lock_bh(&nss_top_main.stats_lock);
435 for (i = 0; (i < NSS_STATS_NODE_MAX); i++) {
436 stats_shadow[i] = nss_top_main.stats_node[NSS_IPV4_REASM_INTERFACE][i];
437 }
438
439 spin_unlock_bh(&nss_top_main.stats_lock);
440
441 for (i = 0; (i < NSS_STATS_NODE_MAX); i++) {
442 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
443 "%s = %llu\n", nss_stats_str_node[i], stats_shadow[i]);
444 }
445
446 /*
447 * IPv4 reasm node stats
448 */
449 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nipv4 reasm node stats:\n\n");
450
451 spin_lock_bh(&nss_top_main.stats_lock);
452 for (i = 0; (i < NSS_STATS_IPV4_REASM_MAX); i++) {
453 stats_shadow[i] = nss_top_main.stats_ipv4_reasm[i];
454 }
455
456 spin_unlock_bh(&nss_top_main.stats_lock);
457
458 for (i = 0; (i < NSS_STATS_IPV4_REASM_MAX); i++) {
459 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
460 "%s = %llu\n", nss_stats_str_ipv4_reasm[i], stats_shadow[i]);
461 }
462
463 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nipv4 reasm stats end\n\n");
464 bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
465 kfree(lbuf);
466 kfree(stats_shadow);
467
468 return bytes_read;
469}
470
471/*
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530472 * nss_stats_ipv6_read()
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530473 * Read IPV6 stats
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530474 */
475static ssize_t nss_stats_ipv6_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
476{
477 int32_t i;
478
479 /*
480 * max output lines = #stats + start tag line + end tag line + three blank lines
481 */
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530482 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 +0530483 size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
484 size_t size_wr = 0;
485 ssize_t bytes_read = 0;
486 uint64_t *stats_shadow;
487
488 char *lbuf = kzalloc(size_al, GFP_KERNEL);
489 if (unlikely(lbuf == NULL)) {
490 nss_warning("Could not allocate memory for local statistics buffer");
491 return 0;
492 }
493
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530494 /*
495 * Note: The assumption here is that exception event count is larger than other statistics count for IPv4
496 */
497 stats_shadow = kzalloc(NSS_EXCEPTION_EVENT_IPV6_MAX * 8, GFP_KERNEL);
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530498 if (unlikely(stats_shadow == NULL)) {
499 nss_warning("Could not allocate memory for local shadow buffer");
500 return 0;
501 }
502
Abhishek Rastogia1a07972014-04-01 19:43:33 +0530503 size_wr = scnprintf(lbuf, size_al, "ipv6 stats start:\n\n");
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530504
505 /*
506 * Common node stats
507 */
Abhishek Rastogia1a07972014-04-01 19:43:33 +0530508 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "common node stats:\n\n");
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530509 spin_lock_bh(&nss_top_main.stats_lock);
510 for (i = 0; (i < NSS_STATS_NODE_MAX); i++) {
511 stats_shadow[i] = nss_top_main.stats_node[NSS_IPV6_RX_INTERFACE][i];
512 }
513
514 spin_unlock_bh(&nss_top_main.stats_lock);
515
516 for (i = 0; (i < NSS_STATS_NODE_MAX); i++) {
517 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
518 "%s = %llu\n", nss_stats_str_node[i], stats_shadow[i]);
519 }
520
521 /*
522 * IPv6 node stats
523 */
Abhishek Rastogia1a07972014-04-01 19:43:33 +0530524 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nipv6 node stats:\n\n");
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530525
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530526 spin_lock_bh(&nss_top_main.stats_lock);
527 for (i = 0; (i < NSS_STATS_IPV6_MAX); i++) {
528 stats_shadow[i] = nss_top_main.stats_ipv6[i];
529 }
530
531 spin_unlock_bh(&nss_top_main.stats_lock);
532
533 for (i = 0; (i < NSS_STATS_IPV6_MAX); i++) {
534 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
535 "%s = %llu\n", nss_stats_str_ipv6[i], stats_shadow[i]);
536 }
537
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530538 /*
539 * Exception stats
540 */
Abhishek Rastogia1a07972014-04-01 19:43:33 +0530541 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nipv6 exception stats:\n\n");
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530542
543 spin_lock_bh(&nss_top_main.stats_lock);
544 for (i = 0; (i < NSS_EXCEPTION_EVENT_IPV6_MAX); i++) {
545 stats_shadow[i] = nss_top_main.stats_if_exception_ipv6[i];
546 }
547
548 spin_unlock_bh(&nss_top_main.stats_lock);
549
550 for (i = 0; (i < NSS_EXCEPTION_EVENT_IPV6_MAX); i++) {
551 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
552 "%s = %llu\n", nss_stats_str_if_exception_ipv6[i], stats_shadow[i]);
553 }
554
555 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,"\nipv6 stats end\n\n");
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530556 bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
557 kfree(lbuf);
558 kfree(stats_shadow);
559
560 return bytes_read;
561}
562
563/*
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530564 * nss_stats_eth_rx_read()
565 * Read ETH_RX stats
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530566 */
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530567static 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 +0530568{
569 int32_t i;
570
571 /*
572 * max output lines = #stats + start tag line + end tag line + three blank lines
573 */
Murat Sezgin99dab642014-08-28 14:40:34 -0700574 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 +0530575 size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
576 size_t size_wr = 0;
577 ssize_t bytes_read = 0;
578 uint64_t *stats_shadow;
579
580 char *lbuf = kzalloc(size_al, GFP_KERNEL);
581 if (unlikely(lbuf == NULL)) {
582 nss_warning("Could not allocate memory for local statistics buffer");
583 return 0;
584 }
585
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530586 /*
587 * Note: The assumption here is that we do not have more than 64 stats
588 */
589 stats_shadow = kzalloc(64 * 8, GFP_KERNEL);
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530590 if (unlikely(stats_shadow == NULL)) {
591 nss_warning("Could not allocate memory for local shadow buffer");
592 return 0;
593 }
594
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530595 size_wr = scnprintf(lbuf, size_al,"eth_rx stats start:\n\n");
596
597 /*
598 * Common node stats
599 */
Abhishek Rastogia1a07972014-04-01 19:43:33 +0530600 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "common node stats:\n\n");
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530601 spin_lock_bh(&nss_top_main.stats_lock);
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530602 for (i = 0; (i < NSS_STATS_NODE_MAX); i++) {
603 stats_shadow[i] = nss_top_main.stats_node[NSS_ETH_RX_INTERFACE][i];
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530604 }
605
606 spin_unlock_bh(&nss_top_main.stats_lock);
607
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530608 for (i = 0; (i < NSS_STATS_NODE_MAX); i++) {
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530609 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530610 "%s = %llu\n", nss_stats_str_node[i], stats_shadow[i]);
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530611 }
612
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530613 /*
Murat Sezgin99dab642014-08-28 14:40:34 -0700614 * eth_rx node stats
615 */
616 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\neth_rx node stats:\n\n");
617 spin_lock_bh(&nss_top_main.stats_lock);
618 for (i = 0; (i < NSS_STATS_ETH_RX_MAX); i++) {
619 stats_shadow[i] = nss_top_main.stats_eth_rx[i];
620 }
621
622 spin_unlock_bh(&nss_top_main.stats_lock);
623
624 for (i = 0; (i < NSS_STATS_ETH_RX_MAX); i++) {
625 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
626 "%s = %llu\n", nss_stats_str_eth_rx[i], stats_shadow[i]);
627 }
628
629 /*
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530630 * Exception stats
631 */
Abhishek Rastogia1a07972014-04-01 19:43:33 +0530632 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\neth_rx exception stats:\n\n");
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530633
634 spin_lock_bh(&nss_top_main.stats_lock);
635 for (i = 0; (i < NSS_EXCEPTION_EVENT_ETH_RX_MAX); i++) {
636 stats_shadow[i] = nss_top_main.stats_if_exception_eth_rx[i];
637 }
638
639 spin_unlock_bh(&nss_top_main.stats_lock);
640
641 for (i = 0; (i < NSS_EXCEPTION_EVENT_ETH_RX_MAX); i++) {
642 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
643 "%s = %llu\n", nss_stats_str_if_exception_eth_rx[i], stats_shadow[i]);
644 }
645
646 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,"\neth_rx stats end\n\n");
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530647 bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
648 kfree(lbuf);
649 kfree(stats_shadow);
650
651 return bytes_read;
652}
653
654/*
655 * nss_stats_n2h_read()
656 * Read N2H stats
657 */
658static ssize_t nss_stats_n2h_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
659{
660 int32_t i;
661
662 /*
663 * max output lines = #stats + start tag line + end tag line + three blank lines
664 */
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530665 uint32_t max_output_lines = (NSS_STATS_NODE_MAX + 2) + (NSS_STATS_N2H_MAX + 3) + 5;
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530666 size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
667 size_t size_wr = 0;
668 ssize_t bytes_read = 0;
669 uint64_t *stats_shadow;
Murat Sezgin0c0561d2014-04-09 18:55:58 -0700670 int max = NSS_STATS_N2H_MAX - NSS_STATS_NODE_MAX;
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530671
672 char *lbuf = kzalloc(size_al, GFP_KERNEL);
673 if (unlikely(lbuf == NULL)) {
674 nss_warning("Could not allocate memory for local statistics buffer");
675 return 0;
676 }
677
678 stats_shadow = kzalloc(NSS_STATS_N2H_MAX * 8, GFP_KERNEL);
679 if (unlikely(stats_shadow == NULL)) {
680 nss_warning("Could not allocate memory for local shadow buffer");
681 return 0;
682 }
683
684 size_wr = scnprintf(lbuf, size_al, "n2h stats start:\n\n");
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530685
686 /*
687 * Common node stats
688 */
Abhishek Rastogia1a07972014-04-01 19:43:33 +0530689 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "common node stats:\n\n");
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530690 spin_lock_bh(&nss_top_main.stats_lock);
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530691 for (i = 0; (i < NSS_STATS_NODE_MAX); i++) {
692 stats_shadow[i] = nss_top_main.nss[0].stats_n2h[i];
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530693 }
694
695 spin_unlock_bh(&nss_top_main.stats_lock);
696
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530697 for (i = 0; (i < NSS_STATS_NODE_MAX); i++) {
698 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
699 "%s = %llu\n", nss_stats_str_node[i], stats_shadow[i]);
700 }
701
702 /*
703 * N2H node stats
704 */
Abhishek Rastogia1a07972014-04-01 19:43:33 +0530705 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nn2h node stats:\n\n");
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530706 spin_lock_bh(&nss_top_main.stats_lock);
707 for (i = NSS_STATS_NODE_MAX; (i < NSS_STATS_N2H_MAX); i++) {
708 stats_shadow[i] = nss_top_main.nss[0].stats_n2h[i];
709 }
710
711 spin_unlock_bh(&nss_top_main.stats_lock);
712
Murat Sezgin0c0561d2014-04-09 18:55:58 -0700713 for (i = 0; i < max; i++) {
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530714 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
Murat Sezgin0c0561d2014-04-09 18:55:58 -0700715 "%s = %llu\n", nss_stats_str_n2h[i], stats_shadow[i + NSS_STATS_NODE_MAX]);
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530716 }
717
718 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nn2h stats end\n\n");
719 bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
720 kfree(lbuf);
721 kfree(stats_shadow);
722
723 return bytes_read;
724}
725
726/*
727 * nss_stats_drv_read()
728 * Read HLOS driver stats
729 */
730static ssize_t nss_stats_drv_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
731{
732 int32_t i;
733
734 /*
735 * max output lines = #stats + start tag line + end tag line + three blank lines
736 */
737 uint32_t max_output_lines = NSS_STATS_DRV_MAX + 5;
738 size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
739 size_t size_wr = 0;
740 ssize_t bytes_read = 0;
741 uint64_t *stats_shadow;
742
743 char *lbuf = kzalloc(size_al, GFP_KERNEL);
744 if (unlikely(lbuf == NULL)) {
745 nss_warning("Could not allocate memory for local statistics buffer");
746 return 0;
747 }
748
749 stats_shadow = kzalloc(NSS_STATS_DRV_MAX * 8, GFP_KERNEL);
750 if (unlikely(stats_shadow == NULL)) {
751 nss_warning("Could not allocate memory for local shadow buffer");
752 return 0;
753 }
754
755 size_wr = scnprintf(lbuf, size_al, "drv stats start:\n\n");
756 spin_lock_bh(&nss_top_main.stats_lock);
757 for (i = 0; (i < NSS_STATS_DRV_MAX); i++) {
758 stats_shadow[i] = nss_top_main.stats_drv[i];
759 }
760
761 spin_unlock_bh(&nss_top_main.stats_lock);
762
763 for (i = 0; (i < NSS_STATS_DRV_MAX); i++) {
764 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
765 "%s = %llu\n", nss_stats_str_drv[i], stats_shadow[i]);
766 }
767
768 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\ndrv stats end\n\n");
769 bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
770 kfree(lbuf);
771 kfree(stats_shadow);
772
773 return bytes_read;
774}
775
776/*
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530777 * nss_stats_pppoe_read()
778 * Read PPPoE stats
779 */
780static ssize_t nss_stats_pppoe_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
781{
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530782 int32_t i, j, k;
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530783
784 /*
785 * max output lines = #stats + start tag line + end tag line + three blank lines
786 */
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530787 uint32_t max_output_lines = (NSS_STATS_NODE_MAX + 2) + (NSS_STATS_PPPOE_MAX + 3) +
Ankit Dhanukaa1569ce2014-05-13 19:58:06 +0530788 ((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 +0530789 size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
790 size_t size_wr = 0;
791 ssize_t bytes_read = 0;
792 uint64_t *stats_shadow;
793
794 char *lbuf = kzalloc(size_al, GFP_KERNEL);
795 if (unlikely(lbuf == NULL)) {
796 nss_warning("Could not allocate memory for local statistics buffer");
797 return 0;
798 }
799
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530800 stats_shadow = kzalloc(64 * 8, GFP_KERNEL);
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530801 if (unlikely(stats_shadow == NULL)) {
802 nss_warning("Could not allocate memory for local shadow buffer");
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530803 kfree(lbuf);
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530804 return 0;
805 }
806
807 size_wr = scnprintf(lbuf, size_al, "pppoe stats start:\n\n");
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530808
809 /*
810 * Common node stats
811 */
Abhishek Rastogia1a07972014-04-01 19:43:33 +0530812 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "common node stats:\n\n");
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530813 spin_lock_bh(&nss_top_main.stats_lock);
814 for (i = 0; (i < NSS_STATS_NODE_MAX); i++) {
815 stats_shadow[i] = nss_top_main.stats_node[NSS_PPPOE_RX_INTERFACE][i];
816 }
817
818 spin_unlock_bh(&nss_top_main.stats_lock);
819
820 for (i = 0; (i < NSS_STATS_NODE_MAX); i++) {
821 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
822 "%s = %llu\n", nss_stats_str_node[i], stats_shadow[i]);
823 }
824
825 /*
826 * PPPoE node stats
827 */
Abhishek Rastogia1a07972014-04-01 19:43:33 +0530828 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "pppoe node stats:\n\n");
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530829 spin_lock_bh(&nss_top_main.stats_lock);
830 for (i = 0; (i < NSS_STATS_PPPOE_MAX); i++) {
831 stats_shadow[i] = nss_top_main.stats_pppoe[i];
832 }
833
834 spin_unlock_bh(&nss_top_main.stats_lock);
835
836 for (i = 0; (i < NSS_STATS_PPPOE_MAX); i++) {
837 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
838 "%s = %llu\n", nss_stats_str_pppoe[i], stats_shadow[i]);
839 }
840
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530841 /*
842 * Exception stats
843 */
844 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nException PPPoE:\n\n");
845
846 for (j = 0; j < NSS_MAX_PHYSICAL_INTERFACES; j++) {
847 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nInterface %d:\n\n", j);
848
849 spin_lock_bh(&nss_top_main.stats_lock);
850 for (k = 0; k < NSS_PPPOE_NUM_SESSION_PER_INTERFACE; k++) {
Ankit Dhanukaa1569ce2014-05-13 19:58:06 +0530851 for (i = 0; (i < NSS_PPPOE_EXCEPTION_EVENT_MAX); i++) {
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530852 stats_shadow_pppoe_except[k][i] = nss_top_main.stats_if_exception_pppoe[j][k][i];
853 }
854 }
855
856 spin_unlock_bh(&nss_top_main.stats_lock);
857
858 for (k = 0; k < NSS_PPPOE_NUM_SESSION_PER_INTERFACE; k++) {
859 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "%d. Session\n", k);
Ankit Dhanukaa1569ce2014-05-13 19:58:06 +0530860 for (i = 0; (i < NSS_PPPOE_EXCEPTION_EVENT_MAX); i++) {
Abhishek Rastogi84d95d02014-03-26 19:31:31 +0530861 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
862 "%s = %llu\n",
863 nss_stats_str_if_exception_pppoe[i],
864 stats_shadow_pppoe_except[k][i]);
865 }
866 }
867
868 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\npppoe stats end\n\n");
869 }
870
Abhishek Rastogi38cffff2013-06-02 11:25:47 +0530871 bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
872 kfree(lbuf);
873 kfree(stats_shadow);
874
875 return bytes_read;
876}
877
878/*
879 * nss_stats_gmac_read()
880 * Read GMAC stats
881 */
882static ssize_t nss_stats_gmac_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
883{
884 uint32_t i, id;
885
886 /*
887 * max output lines = ((#stats + start tag + one blank) * #GMACs) + start/end tag + 3 blank
888 */
889 uint32_t max_output_lines = ((NSS_STATS_GMAC_MAX + 2) * NSS_MAX_PHYSICAL_INTERFACES) + 5;
890 size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines;
891 size_t size_wr = 0;
892 ssize_t bytes_read = 0;
893 uint64_t *stats_shadow;
894
895 char *lbuf = kzalloc(size_al, GFP_KERNEL);
896 if (unlikely(lbuf == NULL)) {
897 nss_warning("Could not allocate memory for local statistics buffer");
898 return 0;
899 }
900
901 stats_shadow = kzalloc(NSS_STATS_GMAC_MAX * 8, GFP_KERNEL);
902 if (unlikely(stats_shadow == NULL)) {
903 nss_warning("Could not allocate memory for local shadow buffer");
904 return 0;
905 }
906
907 size_wr = scnprintf(lbuf, size_al, "gmac stats start:\n\n");
908
909 for (id = 0; id < NSS_MAX_PHYSICAL_INTERFACES; id++) {
910 spin_lock_bh(&nss_top_main.stats_lock);
911 for (i = 0; (i < NSS_STATS_GMAC_MAX); i++) {
912 stats_shadow[i] = nss_top_main.stats_gmac[id][i];
913 }
914
915 spin_unlock_bh(&nss_top_main.stats_lock);
916
917 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "GMAC ID: %d\n", id);
918 for (i = 0; (i < NSS_STATS_GMAC_MAX); i++) {
919 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,
920 "%s = %llu\n", nss_stats_str_gmac[i], stats_shadow[i]);
921 }
922 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,"\n");
923 }
924
925 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\ngmac stats end\n\n");
926 bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf));
927 kfree(lbuf);
928 kfree(stats_shadow);
929
930 return bytes_read;
931}
932
Saurabh Misra09dddeb2014-09-30 16:38:07 -0700933/*
934 * Make a row for CAPWAP encap stats.
935 */
936static ssize_t nss_stats_capwap_encap(char *line, int len, int i, struct nss_capwap_tunnel_stats *s)
937{
938 char *header[] = { "TX Packets", "TX Bytes", "TX Drops", "Fragments", "QFull", "MemFail", "Unknown" };
939 uint64_t tcnt = 0;
940
941 switch (i) {
942 case 0:
943 tcnt = s->pnode_stats.tx_packets;
944 break;
945 case 1:
946 tcnt = s->pnode_stats.tx_bytes;
947 break;
948 case 2:
949 tcnt = s->tx_dropped;
950 break;
951 case 3:
952 tcnt = s->tx_segments;
953 break;
954 case 4:
955 tcnt = s->tx_queue_full_drops;
956 break;
957 case 5:
958 tcnt = s->tx_mem_failure_drops;
959 break;
960 default:
961 i = 6;
962 break;
963 }
964
965 return (snprintf(line, len, "%14s %llu\n", header[i], tcnt));
966}
967
968/*
969 * Make a row for CAPWAP decap stats.
970 */
971static ssize_t nss_stats_capwap_decap(char *line, int len, int i, struct nss_capwap_tunnel_stats *s)
972{
973 char *header[] = { "RX Packets", "RX Bytes", "RX Dropped", "DTLS pkts", "Fragments", "OSzDrop", "FTimeout", "FDup", "QFull", "MemFail", "Unknown" };
974 uint64_t tcnt = 0;
975
976 switch(i) {
977 case 0:
978 tcnt = s->pnode_stats.rx_packets;
979 break;
980 case 1:
981 tcnt = s->pnode_stats.rx_bytes;
982 break;
983 case 2:
984 tcnt = s->pnode_stats.rx_dropped;
985 break;
986 case 3:
987 tcnt = s->dtls_pkts;
988 break;
989 case 4:
990 tcnt = s->rx_segments;
991 break;
992 case 5:
993 tcnt = s->oversize_drops;
994 break;
995 case 6:
996 tcnt = s->frag_timeout_drops;
997 break;
998 case 7:
999 tcnt = s->rx_dup_frag;
1000 break;
1001 case 8:
1002 tcnt = s->rx_queue_full_drops;
1003 return (snprintf(line, len, "%14s: %llu (n2h: %llu)\n", header[i], tcnt, s->rx_n2h_queue_full_drops));
1004 case 9:
1005 tcnt = s->rx_mem_failure_drops;
1006 break;
1007 default:
1008 i = 10;
1009 break;
1010 }
1011
1012 return (snprintf(line, len, "%14s: %llu\n", header[i], tcnt));
1013}
1014
1015/*
1016 * nss_stats_capwap_read()
1017 * Read CAPWAP stats
1018 */
1019static ssize_t nss_stats_capwap_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos, uint16_t type)
1020{
1021 struct nss_stats_data *data = fp->private_data;
1022 ssize_t bytes_read = 0;
1023 struct nss_capwap_tunnel_stats stats;
1024 size_t bytes;
1025 char line[80];
1026 int start, end;
1027 uint32_t if_num = NSS_DYNAMIC_IF_START;
1028 uint32_t max_if_num = NSS_DYNAMIC_IF_START + NSS_MAX_DYNAMIC_INTERFACES;
1029
1030 if (data) {
1031 if_num = data->if_num;
1032 }
1033
1034 /*
1035 * If we are done accomodating all the CAPWAP tunnels.
1036 */
1037 if (if_num > max_if_num) {
1038 return 0;
1039 }
1040
1041 for (; if_num <= max_if_num; if_num++) {
1042 bool isthere;
1043
1044 if (nss_is_dynamic_interface(if_num) == false) {
1045 continue;
1046 }
1047
1048 if (nss_dynamic_interface_get_type(if_num) != NSS_DYNAMIC_INTERFACE_TYPE_CAPWAP) {
1049 continue;
1050 }
1051
1052 /*
1053 * If CAPWAP tunnel does not exists, then isthere will be false.
1054 */
1055 isthere = nss_capwap_get_stats(if_num, &stats);
1056 if (!isthere) {
1057 continue;
1058 }
1059
1060 bytes = snprintf(line, sizeof(line), "(%2d) %9s %s\n", if_num, "Stats", "Total");
1061 if ((bytes_read + bytes) > sz) {
1062 break;
1063 }
1064
1065 if (copy_to_user(ubuf + bytes_read, line, bytes) != 0) {
1066 bytes_read = -EFAULT;
1067 goto fail;
1068 }
1069 bytes_read += bytes;
1070 start = 0;
1071 if (type == 1) {
1072 end = 5; /* encap */
1073 } else {
1074 end = 9; /* decap */
1075 }
1076 while (bytes_read < sz && start < end) {
1077 if (type == 1) {
1078 bytes = nss_stats_capwap_encap(line, sizeof(line), start, &stats);
1079 } else {
1080 bytes = nss_stats_capwap_decap(line, sizeof(line), start, &stats);
1081 }
1082
1083 if ((bytes_read + bytes) > sz)
1084 break;
1085
1086 if (copy_to_user(ubuf + bytes_read, line, bytes) != 0) {
1087 bytes_read = -EFAULT;
1088 goto fail;
1089 }
1090
1091 bytes_read += bytes;
1092 start++;
1093 }
1094 }
1095
1096 if (bytes_read > 0) {
1097 *ppos = bytes_read;
1098 }
1099
1100 if (data) {
1101 data->if_num = if_num;
1102 }
1103fail:
1104 return bytes_read;
1105}
1106
1107/*
1108 * nss_stats_capwap_decap_read()
1109 * Read CAPWAP decap stats
1110 */
1111static ssize_t nss_stats_capwap_decap_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
1112{
1113 return (nss_stats_capwap_read(fp, ubuf, sz, ppos, 0));
1114}
1115
1116/*
1117 * nss_stats_capwap_encap_read()
1118 * Read CAPWAP encap stats
1119 */
1120static ssize_t nss_stats_capwap_encap_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos)
1121{
1122 return (nss_stats_capwap_read(fp, ubuf, sz, ppos, 1));
1123}
1124
1125/*
1126 * nss_stats_open()
1127 */
1128static int nss_stats_open(struct inode *inode, struct file *filp)
1129{
1130 struct nss_stats_data *data = NULL;
1131
1132 data = kzalloc(sizeof(struct nss_stats_data), GFP_KERNEL);
1133 if (!data) {
1134 return -ENOMEM;
1135 }
1136 memset(data, 0, sizeof (struct nss_stats_data));
1137 data->if_num = NSS_DYNAMIC_IF_START;
1138 filp->private_data = data;
1139
1140 return 0;
1141}
1142
1143/*
1144 * nss_stats_release()
1145 */
1146static int nss_stats_release(struct inode *inode, struct file *filp)
1147{
1148 struct nss_stats_data *data = filp->private_data;
1149
1150 if (data) {
1151 kfree(data);
1152 }
1153
1154 return 0;
1155}
1156
Abhishek Rastogi38cffff2013-06-02 11:25:47 +05301157#define NSS_STATS_DECLARE_FILE_OPERATIONS(name) \
1158static const struct file_operations nss_stats_##name##_ops = { \
Saurabh Misra09dddeb2014-09-30 16:38:07 -07001159 .open = nss_stats_open, \
Abhishek Rastogi38cffff2013-06-02 11:25:47 +05301160 .read = nss_stats_##name##_read, \
1161 .llseek = generic_file_llseek, \
Saurabh Misra09dddeb2014-09-30 16:38:07 -07001162 .release = nss_stats_release, \
Abhishek Rastogi38cffff2013-06-02 11:25:47 +05301163};
1164
1165/*
1166 * nss_ipv4_stats_ops
1167 */
1168NSS_STATS_DECLARE_FILE_OPERATIONS(ipv4)
1169
1170/*
Selin Dag6d9b0c12014-11-04 18:27:21 -08001171 * ipv4_reasm_stats_ops
1172 */
1173NSS_STATS_DECLARE_FILE_OPERATIONS(ipv4_reasm)
1174
1175/*
Abhishek Rastogi38cffff2013-06-02 11:25:47 +05301176 * ipv6_stats_ops
1177 */
1178NSS_STATS_DECLARE_FILE_OPERATIONS(ipv6)
1179
1180/*
Abhishek Rastogi38cffff2013-06-02 11:25:47 +05301181 * n2h_stats_ops
1182 */
1183NSS_STATS_DECLARE_FILE_OPERATIONS(n2h)
1184/*
1185 * drv_stats_ops
1186 */
1187NSS_STATS_DECLARE_FILE_OPERATIONS(drv)
1188
1189/*
Abhishek Rastogi38cffff2013-06-02 11:25:47 +05301190 * pppoe_stats_ops
1191 */
1192NSS_STATS_DECLARE_FILE_OPERATIONS(pppoe)
1193
1194/*
1195 * gmac_stats_ops
1196 */
1197NSS_STATS_DECLARE_FILE_OPERATIONS(gmac)
1198
1199/*
Saurabh Misra09dddeb2014-09-30 16:38:07 -07001200 * capwap_stats_ops
1201 */
1202NSS_STATS_DECLARE_FILE_OPERATIONS(capwap_encap)
1203NSS_STATS_DECLARE_FILE_OPERATIONS(capwap_decap)
1204
1205/*
Abhishek Rastogi84d95d02014-03-26 19:31:31 +05301206 * eth_rx_stats_ops
Abhishek Rastogi38cffff2013-06-02 11:25:47 +05301207 */
Abhishek Rastogi84d95d02014-03-26 19:31:31 +05301208NSS_STATS_DECLARE_FILE_OPERATIONS(eth_rx)
Abhishek Rastogi38cffff2013-06-02 11:25:47 +05301209
1210/*
1211 * nss_stats_init()
1212 * Enable NSS statistics
1213 */
1214void nss_stats_init(void)
1215{
1216 /*
1217 * NSS driver entry
1218 */
1219 nss_top_main.top_dentry = debugfs_create_dir("qca-nss-drv", NULL);
1220 if (unlikely(nss_top_main.top_dentry == NULL)) {
1221 nss_warning("Failed to create qca-nss-drv directory in debugfs");
1222
1223 /*
1224 * Non availability of debugfs directory is not a catastrophy
1225 * We can still go ahead with other initialization
1226 */
1227 return;
1228 }
1229
1230 nss_top_main.stats_dentry = debugfs_create_dir("stats", nss_top_main.top_dentry);
Abhishek Rastogi80f4eb12013-09-24 14:31:21 +05301231 if (unlikely(nss_top_main.stats_dentry == NULL)) {
Abhishek Rastogi38cffff2013-06-02 11:25:47 +05301232 nss_warning("Failed to create qca-nss-drv directory in debugfs");
1233
1234 /*
1235 * Non availability of debugfs directory is not a catastrophy
1236 * We can still go ahead with rest of initialization
1237 */
1238 return;
1239 }
1240
1241 /*
1242 * Create files to obtain statistics
1243 */
1244
1245 /*
1246 * ipv4_stats
1247 */
1248 nss_top_main.ipv4_dentry = debugfs_create_file("ipv4", 0400,
1249 nss_top_main.stats_dentry, &nss_top_main, &nss_stats_ipv4_ops);
1250 if (unlikely(nss_top_main.ipv4_dentry == NULL)) {
Abhishek Rastogi80f4eb12013-09-24 14:31:21 +05301251 nss_warning("Failed to create qca-nss-drv/stats/ipv4 file in debugfs");
Abhishek Rastogi38cffff2013-06-02 11:25:47 +05301252 return;
1253 }
1254
1255 /*
Selin Dag6d9b0c12014-11-04 18:27:21 -08001256 * ipv4_reasm_stats
1257 */
1258 nss_top_main.ipv4_reasm_dentry = debugfs_create_file("ipv4_reasm", 0400,
1259 nss_top_main.stats_dentry, &nss_top_main, &nss_stats_ipv4_reasm_ops);
1260 if (unlikely(nss_top_main.ipv4_reasm_dentry == NULL)) {
1261 nss_warning("Failed to create qca-nss-drv/stats/ipv4_reasm file in debugfs");
1262 return;
1263 }
1264
1265 /*
Abhishek Rastogi38cffff2013-06-02 11:25:47 +05301266 * ipv6_stats
1267 */
1268 nss_top_main.ipv6_dentry = debugfs_create_file("ipv6", 0400,
1269 nss_top_main.stats_dentry, &nss_top_main, &nss_stats_ipv6_ops);
1270 if (unlikely(nss_top_main.ipv6_dentry == NULL)) {
Abhishek Rastogi80f4eb12013-09-24 14:31:21 +05301271 nss_warning("Failed to create qca-nss-drv/stats/ipv6 file in debugfs");
Abhishek Rastogi38cffff2013-06-02 11:25:47 +05301272 return;
1273 }
1274
1275 /*
Abhishek Rastogi84d95d02014-03-26 19:31:31 +05301276 * ipv6_stats
Abhishek Rastogi38cffff2013-06-02 11:25:47 +05301277 */
Abhishek Rastogi84d95d02014-03-26 19:31:31 +05301278 nss_top_main.eth_rx_dentry = debugfs_create_file("eth_rx", 0400,
1279 nss_top_main.stats_dentry, &nss_top_main, &nss_stats_eth_rx_ops);
1280 if (unlikely(nss_top_main.eth_rx_dentry == NULL)) {
1281 nss_warning("Failed to create qca-nss-drv/stats/eth_rx file in debugfs");
Abhishek Rastogi38cffff2013-06-02 11:25:47 +05301282 return;
1283 }
1284
1285 /*
1286 * n2h_stats
1287 */
1288 nss_top_main.n2h_dentry = debugfs_create_file("n2h", 0400,
1289 nss_top_main.stats_dentry, &nss_top_main, &nss_stats_n2h_ops);
1290 if (unlikely(nss_top_main.n2h_dentry == NULL)) {
1291 nss_warning("Failed to create qca-nss-drv/stats/n2h directory in debugfs");
1292 return;
1293 }
1294
1295 /*
1296 * drv_stats
1297 */
1298 nss_top_main.drv_dentry = debugfs_create_file("drv", 0400,
1299 nss_top_main.stats_dentry, &nss_top_main, &nss_stats_drv_ops);
1300 if (unlikely(nss_top_main.drv_dentry == NULL)) {
1301 nss_warning("Failed to create qca-nss-drv/stats/drv directory in debugfs");
1302 return;
1303 }
1304
1305 /*
Abhishek Rastogi38cffff2013-06-02 11:25:47 +05301306 * pppoe_stats
1307 */
1308 nss_top_main.pppoe_dentry = debugfs_create_file("pppoe", 0400,
1309 nss_top_main.stats_dentry, &nss_top_main, &nss_stats_pppoe_ops);
1310 if (unlikely(nss_top_main.pppoe_dentry == NULL)) {
Abhishek Rastogi80f4eb12013-09-24 14:31:21 +05301311 nss_warning("Failed to create qca-nss-drv/stats/pppoe file in debugfs");
Abhishek Rastogi38cffff2013-06-02 11:25:47 +05301312 return;
1313 }
1314
1315 /*
1316 * gmac_stats
1317 */
1318 nss_top_main.gmac_dentry = debugfs_create_file("gmac", 0400,
1319 nss_top_main.stats_dentry, &nss_top_main, &nss_stats_gmac_ops);
1320 if (unlikely(nss_top_main.gmac_dentry == NULL)) {
Abhishek Rastogi80f4eb12013-09-24 14:31:21 +05301321 nss_warning("Failed to create qca-nss-drv/stats/gmac file in debugfs");
Abhishek Rastogi38cffff2013-06-02 11:25:47 +05301322 return;
1323 }
Saurabh Misra09dddeb2014-09-30 16:38:07 -07001324
1325 /*
1326 * CAPWAP stats.
1327 */
1328 nss_top_main.capwap_encap_dentry = debugfs_create_file("capwap_encap", 0400,
1329 nss_top_main.stats_dentry, &nss_top_main, &nss_stats_capwap_encap_ops);
1330 if (unlikely(nss_top_main.capwap_encap_dentry == NULL)) {
1331 nss_warning("Failed to create qca-nss-drv/stats/capwap_encap file in debugfs");
1332 return;
1333 }
1334
1335 nss_top_main.capwap_decap_dentry = debugfs_create_file("capwap_decap", 0400,
1336 nss_top_main.stats_dentry, &nss_top_main, &nss_stats_capwap_decap_ops);
1337 if (unlikely(nss_top_main.capwap_decap_dentry == NULL)) {
1338 nss_warning("Failed to create qca-nss-drv/stats/capwap_decap file in debugfs");
1339 return;
1340 }
Abhishek Rastogi38cffff2013-06-02 11:25:47 +05301341}
1342
1343
1344/*
1345 * nss_stats_clean()
1346 * Cleanup NSS statistics files
1347 */
1348void nss_stats_clean(void)
1349{
1350 /*
1351 * Remove debugfs tree
1352 */
1353 if (likely(nss_top_main.top_dentry != NULL)) {
1354 debugfs_remove_recursive(nss_top_main.top_dentry);
1355 }
1356}