1/* 2 ************************************************************************** 3 * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. 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 */ 16 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 37extern int32_t nss_tx_rx_virt_if_copy_stats(int32_t if_num, int i, char *line); 38 39uint64_t stats_shadow_pppoe_except[NSS_PPPOE_NUM_SESSION_PER_INTERFACE][NSS_PPPOE_EXCEPTION_EVENT_MAX]; 40 41/* 42 * Private data for every file descriptor 43 */ 44struct nss_stats_data { 45 uint32_t if_num; /**< Interface number for stats */ 46 uint32_t index; /**< Index for GRE_REDIR stats */ 47}; 48 49/* 50 * Statistics structures 51 */ 52 53/* 54 * nss_stats_str_ipv4 55 * IPv4 stats strings 56 */ 57static int8_t *nss_stats_str_ipv4[NSS_STATS_IPV4_MAX] = { 58 "rx_pkts", 59 "rx_bytes", 60 "tx_pkts", 61 "tx_bytes", 62 "create_requests", 63 "create_collisions", 64 "create_invalid_interface", 65 "destroy_requests", 66 "destroy_misses", 67 "hash_hits", 68 "hash_reorders", 69 "flushes", 70 "evictions", 71 "fragmentations", 72 "mc_create_requests", 73 "mc_update_requests", 74 "mc_create_invalid_interface", 75 "mc_destroy_requests", 76 "mc_destroy_misses", 77 "mc_flushes", 78}; 79 80/* 81 * nss_stats_str_ipv4_reasm 82 * IPv4 reassembly stats strings 83 */ 84static int8_t *nss_stats_str_ipv4_reasm[NSS_STATS_IPV4_REASM_MAX] = { 85 "evictions", 86 "alloc_fails", 87 "timeouts", 88}; 89 90/* 91 * nss_stats_str_ipv6 92 * IPv6 stats strings 93 */ 94static int8_t *nss_stats_str_ipv6[NSS_STATS_IPV6_MAX] = { 95 "rx_pkts", 96 "rx_bytes", 97 "tx_pkts", 98 "tx_bytes", 99 "create_requests", 100 "create_collisions", 101 "create_invalid_interface", 102 "destroy_requests", 103 "destroy_misses", 104 "hash_hits", 105 "hash_reorders", 106 "flushes", 107 "evictions", 108 "fragmentations", 109 "frag_fails", 110 "mc_create_requests", 111 "mc_update_requests", 112 "mc_create_invalid_interface", 113 "mc_destroy_requests", 114 "mc_destroy_misses", 115 "mc_flushes", 116}; 117 118/* 119 * nss_stats_str_ipv6_reasm 120 * IPv6 reassembly stats strings 121 */ 122static int8_t *nss_stats_str_ipv6_reasm[NSS_STATS_IPV6_REASM_MAX] = { 123 "alloc_fails", 124 "timeouts", 125 "discards", 126}; 127 128/* 129 * nss_stats_str_n2h 130 * N2H stats strings 131 */ 132static int8_t *nss_stats_str_n2h[NSS_STATS_N2H_MAX] = { 133 "queue_dropped", 134 "ticks", 135 "worst_ticks", 136 "iterations", 137 "pbuf_ocm_alloc_fails", 138 "pbuf_ocm_free_count", 139 "pbuf_ocm_total_count", 140 "pbuf_default_alloc_fails", 141 "pbuf_default_free_count", 142 "pbuf_default_total_count", 143 "payload_fails", 144 "payload_free_count", 145 "h2n_control_packets", 146 "h2n_control_bytes", 147 "n2h_control_packets", 148 "n2h_control_bytes", 149 "h2n_data_packets", 150 "h2n_data_bytes", 151 "n2h_data_packets", 152 "n2h_data_bytes", 153 "n2h_tot_payloads", 154 "n2h_data_interface_invalid", 155}; 156 157/* 158 * nss_stats_str_lso_rx 159 * LSO_RX stats strings 160 */ 161static int8_t *nss_stats_str_lso_rx[NSS_STATS_LSO_RX_MAX] = { 162 "tx_dropped", 163 "dropped", 164 "pbuf_alloc_fail", 165 "pbuf_reference_fail" 166}; 167 168/* 169 * nss_stats_str_drv 170 * Host driver stats strings 171 */ 172static int8_t *nss_stats_str_drv[NSS_STATS_DRV_MAX] = { 173 "nbuf_alloc_errors", 174 "tx_queue_full[0]", 175 "tx_queue_full[1]", 176 "tx_buffers_empty", 177 "tx_buffers_pkt", 178 "tx_buffers_cmd", 179 "tx_buffers_crypto", 180 "rx_buffers_empty", 181 "rx_buffers_pkt", 182 "rx_buffers_cmd_resp", 183 "rx_buffers_status_sync", 184 "rx_buffers_crypto", 185 "rx_buffers_virtual", 186 "tx_skb_simple", 187 "tx_skb_nr_frags", 188 "tx_skb_fraglist", 189 "rx_skb_simple", 190 "rx_skb_nr_frags", 191 "rx_skb_fraglist", 192 "rx_bad_desciptor", 193 "nss_skb_count", 194 "rx_chain_seg_processed", 195 "rx_frag_seg_processed" 196}; 197 198/* 199 * nss_stats_str_pppoe 200 * PPPoE stats strings 201 */ 202static int8_t *nss_stats_str_pppoe[NSS_STATS_PPPOE_MAX] = { 203 "create_requests", 204 "create_failures", 205 "destroy_requests", 206 "destroy_misses" 207}; 208 209/* 210 * nss_stats_str_gmac 211 * GMAC stats strings 212 */ 213static int8_t *nss_stats_str_gmac[NSS_STATS_GMAC_MAX] = { 214 "ticks", 215 "worst_ticks", 216 "iterations" 217}; 218 219/* 220 * nss_stats_str_node 221 * Interface stats strings per node 222 */ 223static int8_t *nss_stats_str_node[NSS_STATS_NODE_MAX] = { 224 "rx_packets", 225 "rx_bytes", 226 "rx_dropped", 227 "tx_packets", 228 "tx_bytes" 229}; 230 231/* 232 * nss_stats_str_eth_rx 233 * eth_rx stats strings 234 */ 235static int8_t *nss_stats_str_eth_rx[NSS_STATS_ETH_RX_MAX] = { 236 "ticks", 237 "worst_ticks", 238 "iterations" 239}; 240 241/* 242 * nss_stats_str_if_exception_unknown 243 * Interface stats strings for unknown exceptions 244 */ 245static int8_t *nss_stats_str_if_exception_eth_rx[NSS_EXCEPTION_EVENT_ETH_RX_MAX] = { 246 "UNKNOWN_L3_PROTOCOL", 247 "ETH_HDR_MISSING", 248 "VLAN_MISSING" 249}; 250 251/* 252 * nss_stats_str_if_exception_ipv4 253 * Interface stats strings for ipv4 exceptions 254 */ 255static int8_t *nss_stats_str_if_exception_ipv4[NSS_EXCEPTION_EVENT_IPV4_MAX] = { 256 "IPV4_ICMP_HEADER_INCOMPLETE", 257 "IPV4_ICMP_UNHANDLED_TYPE", 258 "IPV4_ICMP_IPV4_HEADER_INCOMPLETE", 259 "IPV4_ICMP_IPV4_UDP_HEADER_INCOMPLETE", 260 "IPV4_ICMP_IPV4_TCP_HEADER_INCOMPLETE", 261 "IPV4_ICMP_IPV4_UNKNOWN_PROTOCOL", 262 "IPV4_ICMP_NO_ICME", 263 "IPV4_ICMP_FLUSH_TO_HOST", 264 "IPV4_TCP_HEADER_INCOMPLETE", 265 "IPV4_TCP_NO_ICME", 266 "IPV4_TCP_IP_OPTION", 267 "IPV4_TCP_IP_FRAGMENT", 268 "IPV4_TCP_SMALL_TTL", 269 "IPV4_TCP_NEEDS_FRAGMENTATION", 270 "IPV4_TCP_FLAGS", 271 "IPV4_TCP_SEQ_EXCEEDS_RIGHT_EDGE", 272 "IPV4_TCP_SMALL_DATA_OFFS", 273 "IPV4_TCP_BAD_SACK", 274 "IPV4_TCP_BIG_DATA_OFFS", 275 "IPV4_TCP_SEQ_BEFORE_LEFT_EDGE", 276 "IPV4_TCP_ACK_EXCEEDS_RIGHT_EDGE", 277 "IPV4_TCP_ACK_BEFORE_LEFT_EDGE", 278 "IPV4_UDP_HEADER_INCOMPLETE", 279 "IPV4_UDP_NO_ICME", 280 "IPV4_UDP_IP_OPTION", 281 "IPV4_UDP_IP_FRAGMENT", 282 "IPV4_UDP_SMALL_TTL", 283 "IPV4_UDP_NEEDS_FRAGMENTATION", 284 "IPV4_WRONG_TARGET_MAC", 285 "IPV4_HEADER_INCOMPLETE", 286 "IPV4_BAD_TOTAL_LENGTH", 287 "IPV4_BAD_CHECKSUM", 288 "IPV4_NON_INITIAL_FRAGMENT", 289 "IPV4_DATAGRAM_INCOMPLETE", 290 "IPV4_OPTIONS_INCOMPLETE", 291 "IPV4_UNKNOWN_PROTOCOL", 292 "IPV4_ESP_HEADER_INCOMPLETE", 293 "IPV4_ESP_NO_ICME", 294 "IPV4_ESP_IP_OPTION", 295 "IPV4_ESP_IP_FRAGMENT", 296 "IPV4_ESP_SMALL_TTL", 297 "IPV4_ESP_NEEDS_FRAGMENTATION", 298 "IPV4_INGRESS_VID_MISMATCH", 299 "IPV4_INGRESS_VID_MISSING", 300 "IPV4_6RD_NO_ICME", 301 "IPV4_6RD_IP_OPTION", 302 "IPV4_6RD_IP_FRAGMENT", 303 "IPV4_6RD_NEEDS_FRAGMENTATION", 304 "IPV4_DSCP_MARKING_MISMATCH", 305 "IPV4_VLAN_MARKING_MISMATCH", 306 "IPV4_INTERFACE_MISMATCH", 307 "IPV4_GRE_HEADER_INCOMPLETE", 308 "IPV4_GRE_NO_ICME", 309 "IPV4_GRE_IP_OPTION", 310 "IPV4_GRE_IP_FRAGMENT", 311 "IPV4_GRE_SMALL_TTL", 312 "IPV4_GRE_NEEDS_FRAGMENTATION", 313 "IPV4_FRAG_DF_SET", 314 "IPV4_FRAG_FAIL", 315 "IPV4_DESTROY", 316 "IPV4_ICMP_IPV4_UDPLITE_HEADER_INCOMPLETE", 317 "IPV4_UDPLITE_HEADER_INCOMPLETE", 318 "IPV4_UDPLITE_NO_ICME", 319 "IPV4_UDPLITE_IP_OPTION", 320 "IPV4_UDPLITE_IP_FRAGMENT", 321 "IPV4_UDPLITE_SMALL_TTL", 322 "IPV4_UDPLITE_NEEDS_FRAGMENTATION", 323 "IPV4_MC_UDP_NO_ICME", 324 "IPV4_MC_MEM_ALLOC_FAILURE", 325 "IPV4_MC_UPDATE_FAILURE", 326 "IPV4_MC_PBUF_ALLOC_FAILURE" 327}; 328 329/* 330 * nss_stats_str_if_exception_ipv6 331 * Interface stats strings for ipv6 exceptions 332 */ 333static int8_t *nss_stats_str_if_exception_ipv6[NSS_EXCEPTION_EVENT_IPV6_MAX] = { 334 "IPV6_ICMP_HEADER_INCOMPLETE", 335 "IPV6_ICMP_UNHANDLED_TYPE", 336 "IPV6_ICMP_IPV6_HEADER_INCOMPLETE", 337 "IPV6_ICMP_IPV6_UDP_HEADER_INCOMPLETE", 338 "IPV6_ICMP_IPV6_TCP_HEADER_INCOMPLETE", 339 "IPV6_ICMP_IPV6_UNKNOWN_PROTOCOL", 340 "IPV6_ICMP_NO_ICME", 341 "IPV6_ICMP_FLUSH_TO_HOST", 342 "IPV6_TCP_HEADER_INCOMPLETE", 343 "IPV6_TCP_NO_ICME", 344 "IPV6_TCP_SMALL_HOP_LIMIT", 345 "IPV6_TCP_NEEDS_FRAGMENTATION", 346 "IPV6_TCP_FLAGS", 347 "IPV6_TCP_SEQ_EXCEEDS_RIGHT_EDGE", 348 "IPV6_TCP_SMALL_DATA_OFFS", 349 "IPV6_TCP_BAD_SACK", 350 "IPV6_TCP_BIG_DATA_OFFS", 351 "IPV6_TCP_SEQ_BEFORE_LEFT_EDGE", 352 "IPV6_TCP_ACK_EXCEEDS_RIGHT_EDGE", 353 "IPV6_TCP_ACK_BEFORE_LEFT_EDGE", 354 "IPV6_UDP_HEADER_INCOMPLETE", 355 "IPV6_UDP_NO_ICME", 356 "IPV6_UDP_SMALL_HOP_LIMIT", 357 "IPV6_UDP_NEEDS_FRAGMENTATION", 358 "IPV6_WRONG_TARGET_MAC", 359 "IPV6_HEADER_INCOMPLETE", 360 "IPV6_UNKNOWN_PROTOCOL", 361 "IPV6_INGRESS_VID_MISMATCH", 362 "IPV6_INGRESS_VID_MISSING", 363 "IPV6_DSCP_MARKING_MISMATCH", 364 "IPV6_VLAN_MARKING_MISMATCH", 365 "IPV6_INTERFACE_MISMATCH", 366 "IPV6_GRE_NO_ICME", 367 "IPV6_GRE_NEEDS_FRAGMENTATION", 368 "IPV6_GRE_SMALL_HOP_LIMIT", 369 "IPV6_DESTROY", 370 "IPV6_ICMP_IPV6_UDPLITE_HEADER_INCOMPLETE", 371 "IPV6_UDPLITE_HEADER_INCOMPLETE", 372 "IPV6_UDPLITE_NO_ICME", 373 "IPV6_UDPLITE_SMALL_HOP_LIMIT", 374 "IPV6_UDPLITE_NEEDS_FRAGMENTATION", 375 "IPV6_MC_UDP_NO_ICME", 376 "IPV6_MC_MEM_ALLOC_FAILURE", 377 "IPV6_MC_UPDATE_FAILURE", 378 "IPV6_MC_PBUF_ALLOC_FAILURE" 379}; 380 381/* 382 * nss_stats_str_if_exception_pppoe 383 * Interface stats strings for PPPoE exceptions 384 */ 385static int8_t *nss_stats_str_if_exception_pppoe[NSS_PPPOE_EXCEPTION_EVENT_MAX] = { 386 "PPPOE_WRONG_VERSION_OR_TYPE", 387 "PPPOE_WRONG_CODE", 388 "PPPOE_HEADER_INCOMPLETE", 389 "PPPOE_UNSUPPORTED_PPP_PROTOCOL", 390 "PPPOE_INTERFACE_MISMATCH" 391}; 392 393/* 394 * nss_stats_str_wifi 395 * Wifi statistics strings 396 */ 397static int8_t *nss_stats_str_wifi[NSS_STATS_WIFI_MAX] = { 398 "RX_PACKETS", 399 "RX_DROPPED", 400 "TX_PACKETS", 401 "TX_DROPPED", 402 "TX_TRANSMIT_COMPLETED", 403 "TX_MGMT_RECEIVED", 404 "TX_MGMT_TRANSMITTED", 405 "TX_MGMT_DROPPED", 406 "TX_MGMT_COMPLETED", 407 "TX_INV_PEER_ENQ_CNT", 408 "RX_INV_PEER_RCV_CNT", 409 "RX_PN_CHECK_FAILED", 410 "RX_PKTS_DELIVERD", 411}; 412 413/* 414 * nss_stats_ipv4_read() 415 * Read IPV4 stats 416 */ 417static ssize_t nss_stats_ipv4_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos) 418{ 419 int32_t i; 420 /* 421 * max output lines = #stats + start tag line + end tag line + three blank lines 422 */ 423 uint32_t max_output_lines = (NSS_STATS_NODE_MAX + 2) + (NSS_STATS_IPV4_MAX + 3) + (NSS_EXCEPTION_EVENT_IPV4_MAX + 3) + 5; 424 size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines; 425 size_t size_wr = 0; 426 ssize_t bytes_read = 0; 427 uint64_t *stats_shadow; 428 429 char *lbuf = kzalloc(size_al, GFP_KERNEL); 430 if (unlikely(lbuf == NULL)) { 431 nss_warning("Could not allocate memory for local statistics buffer"); 432 return 0; 433 } 434 435 /* 436 * Note: The assumption here is that exception event count is larger than other statistics count for IPv4 437 */ 438 stats_shadow = kzalloc(NSS_EXCEPTION_EVENT_IPV4_MAX * 8, GFP_KERNEL); 439 if (unlikely(stats_shadow == NULL)) { 440 nss_warning("Could not allocate memory for local shadow buffer"); 441 kfree(lbuf); 442 return 0; 443 } 444 445 size_wr = scnprintf(lbuf, size_al, "ipv4 stats start:\n\n"); 446 447 /* 448 * Common node stats 449 */ 450 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "common node stats:\n\n"); 451 spin_lock_bh(&nss_top_main.stats_lock); 452 for (i = 0; (i < NSS_STATS_NODE_MAX); i++) { 453 stats_shadow[i] = nss_top_main.stats_node[NSS_IPV4_RX_INTERFACE][i]; 454 } 455 456 spin_unlock_bh(&nss_top_main.stats_lock); 457 458 for (i = 0; (i < NSS_STATS_NODE_MAX); i++) { 459 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, 460 "%s = %llu\n", nss_stats_str_node[i], stats_shadow[i]); 461 } 462 463 /* 464 * IPv4 node stats 465 */ 466 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nipv4 node stats:\n\n"); 467 468 spin_lock_bh(&nss_top_main.stats_lock); 469 for (i = 0; (i < NSS_STATS_IPV4_MAX); i++) { 470 stats_shadow[i] = nss_top_main.stats_ipv4[i]; 471 } 472 473 spin_unlock_bh(&nss_top_main.stats_lock); 474 475 for (i = 0; (i < NSS_STATS_IPV4_MAX); i++) { 476 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, 477 "%s = %llu\n", nss_stats_str_ipv4[i], stats_shadow[i]); 478 } 479 480 /* 481 * Exception stats 482 */ 483 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nipv4 exception stats:\n\n"); 484 485 spin_lock_bh(&nss_top_main.stats_lock); 486 for (i = 0; (i < NSS_EXCEPTION_EVENT_IPV4_MAX); i++) { 487 stats_shadow[i] = nss_top_main.stats_if_exception_ipv4[i]; 488 } 489 490 spin_unlock_bh(&nss_top_main.stats_lock); 491 492 for (i = 0; (i < NSS_EXCEPTION_EVENT_IPV4_MAX); i++) { 493 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, 494 "%s = %llu\n", nss_stats_str_if_exception_ipv4[i], stats_shadow[i]); 495 } 496 497 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nipv4 stats end\n\n"); 498 bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf)); 499 kfree(lbuf); 500 kfree(stats_shadow); 501 502 return bytes_read; 503} 504 505/* 506 * nss_stats_ipv4_reasm_read() 507 * Read IPV4 reassembly stats 508 */ 509static ssize_t nss_stats_ipv4_reasm_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos) 510{ 511 int32_t i; 512 /* 513 * max output lines = #stats + start tag line + end tag line + three blank lines 514 */ 515 uint32_t max_output_lines = (NSS_STATS_NODE_MAX + 2) + (NSS_STATS_IPV4_REASM_MAX + 3) + 5; 516 size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines; 517 size_t size_wr = 0; 518 ssize_t bytes_read = 0; 519 uint64_t *stats_shadow; 520 521 char *lbuf = kzalloc(size_al, GFP_KERNEL); 522 if (unlikely(lbuf == NULL)) { 523 nss_warning("Could not allocate memory for local statistics buffer"); 524 return 0; 525 } 526 527 stats_shadow = kzalloc(NSS_STATS_IPV4_REASM_MAX * 8, GFP_KERNEL); 528 if (unlikely(stats_shadow == NULL)) { 529 nss_warning("Could not allocate memory for local shadow buffer"); 530 kfree(lbuf); 531 return 0; 532 } 533 534 size_wr = scnprintf(lbuf, size_al, "ipv4 reasm stats start:\n\n"); 535 536 /* 537 * Common node stats 538 */ 539 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "common node stats:\n\n"); 540 spin_lock_bh(&nss_top_main.stats_lock); 541 for (i = 0; (i < NSS_STATS_NODE_MAX); i++) { 542 stats_shadow[i] = nss_top_main.stats_node[NSS_IPV4_REASM_INTERFACE][i]; 543 } 544 545 spin_unlock_bh(&nss_top_main.stats_lock); 546 547 for (i = 0; (i < NSS_STATS_NODE_MAX); i++) { 548 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, 549 "%s = %llu\n", nss_stats_str_node[i], stats_shadow[i]); 550 } 551 552 /* 553 * IPv4 reasm node stats 554 */ 555 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nipv4 reasm node stats:\n\n"); 556 557 spin_lock_bh(&nss_top_main.stats_lock); 558 for (i = 0; (i < NSS_STATS_IPV4_REASM_MAX); i++) { 559 stats_shadow[i] = nss_top_main.stats_ipv4_reasm[i]; 560 } 561 562 spin_unlock_bh(&nss_top_main.stats_lock); 563 564 for (i = 0; (i < NSS_STATS_IPV4_REASM_MAX); i++) { 565 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, 566 "%s = %llu\n", nss_stats_str_ipv4_reasm[i], stats_shadow[i]); 567 } 568 569 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nipv4 reasm stats end\n\n"); 570 bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf)); 571 kfree(lbuf); 572 kfree(stats_shadow); 573 574 return bytes_read; 575} 576 577/* 578 * nss_stats_ipv6_read() 579 * Read IPV6 stats 580 */ 581static ssize_t nss_stats_ipv6_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos) 582{ 583 int32_t i; 584 585 /* 586 * max output lines = #stats + start tag line + end tag line + three blank lines 587 */ 588 uint32_t max_output_lines = (NSS_STATS_NODE_MAX + 2) + (NSS_STATS_IPV6_MAX + 3) + (NSS_EXCEPTION_EVENT_IPV6_MAX + 3) + 5; 589 size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines; 590 size_t size_wr = 0; 591 ssize_t bytes_read = 0; 592 uint64_t *stats_shadow; 593 594 char *lbuf = kzalloc(size_al, GFP_KERNEL); 595 if (unlikely(lbuf == NULL)) { 596 nss_warning("Could not allocate memory for local statistics buffer"); 597 return 0; 598 } 599 600 /* 601 * Note: The assumption here is that exception event count is larger than other statistics count for IPv4 602 */ 603 stats_shadow = kzalloc(NSS_EXCEPTION_EVENT_IPV6_MAX * 8, GFP_KERNEL); 604 if (unlikely(stats_shadow == NULL)) { 605 nss_warning("Could not allocate memory for local shadow buffer"); 606 kfree(lbuf); 607 return 0; 608 } 609 610 size_wr = scnprintf(lbuf, size_al, "ipv6 stats start:\n\n"); 611 612 /* 613 * Common node stats 614 */ 615 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "common node stats:\n\n"); 616 spin_lock_bh(&nss_top_main.stats_lock); 617 for (i = 0; (i < NSS_STATS_NODE_MAX); i++) { 618 stats_shadow[i] = nss_top_main.stats_node[NSS_IPV6_RX_INTERFACE][i]; 619 } 620 621 spin_unlock_bh(&nss_top_main.stats_lock); 622 623 for (i = 0; (i < NSS_STATS_NODE_MAX); i++) { 624 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, 625 "%s = %llu\n", nss_stats_str_node[i], stats_shadow[i]); 626 } 627 628 /* 629 * IPv6 node stats 630 */ 631 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nipv6 node stats:\n\n"); 632 633 spin_lock_bh(&nss_top_main.stats_lock); 634 for (i = 0; (i < NSS_STATS_IPV6_MAX); i++) { 635 stats_shadow[i] = nss_top_main.stats_ipv6[i]; 636 } 637 638 spin_unlock_bh(&nss_top_main.stats_lock); 639 640 for (i = 0; (i < NSS_STATS_IPV6_MAX); i++) { 641 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, 642 "%s = %llu\n", nss_stats_str_ipv6[i], stats_shadow[i]); 643 } 644 645 /* 646 * Exception stats 647 */ 648 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nipv6 exception stats:\n\n"); 649 650 spin_lock_bh(&nss_top_main.stats_lock); 651 for (i = 0; (i < NSS_EXCEPTION_EVENT_IPV6_MAX); i++) { 652 stats_shadow[i] = nss_top_main.stats_if_exception_ipv6[i]; 653 } 654 655 spin_unlock_bh(&nss_top_main.stats_lock); 656 657 for (i = 0; (i < NSS_EXCEPTION_EVENT_IPV6_MAX); i++) { 658 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, 659 "%s = %llu\n", nss_stats_str_if_exception_ipv6[i], stats_shadow[i]); 660 } 661 662 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,"\nipv6 stats end\n\n"); 663 bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf)); 664 kfree(lbuf); 665 kfree(stats_shadow); 666 667 return bytes_read; 668} 669 670/* 671 * nss_stats_ipv6_reasm_read() 672 * Read IPV6 reassembly stats 673 */ 674static ssize_t nss_stats_ipv6_reasm_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos) 675{ 676 int32_t i; 677 /* 678 * max output lines = #stats + start tag line + end tag line + three blank lines 679 */ 680 uint32_t max_output_lines = (NSS_STATS_NODE_MAX + 2) + (NSS_STATS_IPV6_REASM_MAX + 3) + 5; 681 size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines; 682 size_t size_wr = 0; 683 ssize_t bytes_read = 0; 684 uint64_t *stats_shadow; 685 686 char *lbuf = kzalloc(size_al, GFP_KERNEL); 687 if (unlikely(lbuf == NULL)) { 688 nss_warning("Could not allocate memory for local statistics buffer"); 689 return 0; 690 } 691 692 stats_shadow = kzalloc(NSS_STATS_IPV6_REASM_MAX * 8, GFP_KERNEL); 693 if (unlikely(stats_shadow == NULL)) { 694 nss_warning("Could not allocate memory for local shadow buffer"); 695 kfree(lbuf); 696 return 0; 697 } 698 699 size_wr = scnprintf(lbuf, size_al, "ipv6 reasm stats start:\n\n"); 700 701 /* 702 * Common node stats 703 */ 704 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "common node stats:\n\n"); 705 spin_lock_bh(&nss_top_main.stats_lock); 706 for (i = 0; (i < NSS_STATS_NODE_MAX); i++) { 707 stats_shadow[i] = nss_top_main.stats_node[NSS_IPV6_REASM_INTERFACE][i]; 708 } 709 710 spin_unlock_bh(&nss_top_main.stats_lock); 711 712 for (i = 0; (i < NSS_STATS_NODE_MAX); i++) { 713 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, 714 "%s = %llu\n", nss_stats_str_node[i], stats_shadow[i]); 715 } 716 717 /* 718 * Ipv6 reasm node stats 719 */ 720 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nipv6 reasm node stats:\n\n"); 721 722 spin_lock_bh(&nss_top_main.stats_lock); 723 for (i = 0; (i < NSS_STATS_IPV6_REASM_MAX); i++) { 724 stats_shadow[i] = nss_top_main.stats_ipv6_reasm[i]; 725 } 726 727 spin_unlock_bh(&nss_top_main.stats_lock); 728 729 for (i = 0; (i < NSS_STATS_IPV6_REASM_MAX); i++) { 730 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, 731 "%s = %llu\n", nss_stats_str_ipv6_reasm[i], stats_shadow[i]); 732 } 733 734 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nipv6 reasm stats end\n\n"); 735 bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf)); 736 kfree(lbuf); 737 kfree(stats_shadow); 738 739 return bytes_read; 740} 741 742/* 743 * nss_stats_eth_rx_read() 744 * Read ETH_RX stats 745 */ 746static ssize_t nss_stats_eth_rx_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos) 747{ 748 int32_t i; 749 750 /* 751 * max output lines = #stats + start tag line + end tag line + three blank lines 752 */ 753 uint32_t max_output_lines = (NSS_STATS_NODE_MAX + 2) + (NSS_STATS_ETH_RX_MAX + 3) + (NSS_EXCEPTION_EVENT_ETH_RX_MAX + 3) + 5; 754 size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines; 755 size_t size_wr = 0; 756 ssize_t bytes_read = 0; 757 uint64_t *stats_shadow; 758 759 char *lbuf = kzalloc(size_al, GFP_KERNEL); 760 if (unlikely(lbuf == NULL)) { 761 nss_warning("Could not allocate memory for local statistics buffer"); 762 return 0; 763 } 764 765 /* 766 * Note: The assumption here is that we do not have more than 64 stats 767 */ 768 stats_shadow = kzalloc(64 * 8, GFP_KERNEL); 769 if (unlikely(stats_shadow == NULL)) { 770 nss_warning("Could not allocate memory for local shadow buffer"); 771 kfree(lbuf); 772 return 0; 773 } 774 775 size_wr = scnprintf(lbuf, size_al,"eth_rx stats start:\n\n"); 776 777 /* 778 * Common node stats 779 */ 780 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "common node stats:\n\n"); 781 spin_lock_bh(&nss_top_main.stats_lock); 782 for (i = 0; (i < NSS_STATS_NODE_MAX); i++) { 783 stats_shadow[i] = nss_top_main.stats_node[NSS_ETH_RX_INTERFACE][i]; 784 } 785 786 spin_unlock_bh(&nss_top_main.stats_lock); 787 788 for (i = 0; (i < NSS_STATS_NODE_MAX); i++) { 789 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, 790 "%s = %llu\n", nss_stats_str_node[i], stats_shadow[i]); 791 } 792 793 /* 794 * eth_rx node stats 795 */ 796 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\neth_rx node stats:\n\n"); 797 spin_lock_bh(&nss_top_main.stats_lock); 798 for (i = 0; (i < NSS_STATS_ETH_RX_MAX); i++) { 799 stats_shadow[i] = nss_top_main.stats_eth_rx[i]; 800 } 801 802 spin_unlock_bh(&nss_top_main.stats_lock); 803 804 for (i = 0; (i < NSS_STATS_ETH_RX_MAX); i++) { 805 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, 806 "%s = %llu\n", nss_stats_str_eth_rx[i], stats_shadow[i]); 807 } 808 809 /* 810 * Exception stats 811 */ 812 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\neth_rx exception stats:\n\n"); 813 814 spin_lock_bh(&nss_top_main.stats_lock); 815 for (i = 0; (i < NSS_EXCEPTION_EVENT_ETH_RX_MAX); i++) { 816 stats_shadow[i] = nss_top_main.stats_if_exception_eth_rx[i]; 817 } 818 819 spin_unlock_bh(&nss_top_main.stats_lock); 820 821 for (i = 0; (i < NSS_EXCEPTION_EVENT_ETH_RX_MAX); i++) { 822 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, 823 "%s = %llu\n", nss_stats_str_if_exception_eth_rx[i], stats_shadow[i]); 824 } 825 826 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,"\neth_rx stats end\n\n"); 827 bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf)); 828 kfree(lbuf); 829 kfree(stats_shadow); 830 831 return bytes_read; 832} 833 834/* 835 * nss_stats_n2h_read() 836 * Read N2H stats 837 */ 838static ssize_t nss_stats_n2h_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos) 839{ 840 int32_t i; 841 842 /* 843 * max output lines = #stats + start tag line + end tag line + three blank lines 844 */ 845 uint32_t max_output_lines = (NSS_STATS_NODE_MAX + 2) + (NSS_STATS_N2H_MAX + 3) + 5; 846 size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines; 847 size_t size_wr = 0; 848 ssize_t bytes_read = 0; 849 uint64_t *stats_shadow; 850 int max = NSS_STATS_N2H_MAX - NSS_STATS_NODE_MAX; 851 852 char *lbuf = kzalloc(size_al, GFP_KERNEL); 853 if (unlikely(lbuf == NULL)) { 854 nss_warning("Could not allocate memory for local statistics buffer"); 855 return 0; 856 } 857 858 stats_shadow = kzalloc(NSS_STATS_N2H_MAX * 8, GFP_KERNEL); 859 if (unlikely(stats_shadow == NULL)) { 860 nss_warning("Could not allocate memory for local shadow buffer"); 861 kfree(lbuf); 862 return 0; 863 } 864 865 size_wr = scnprintf(lbuf, size_al, "n2h stats start:\n\n"); 866 867 /* 868 * Common node stats 869 */ 870 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "common node stats:\n\n"); 871 spin_lock_bh(&nss_top_main.stats_lock); 872 for (i = 0; (i < NSS_STATS_NODE_MAX); i++) { 873 stats_shadow[i] = nss_top_main.nss[0].stats_n2h[i]; 874 } 875 876 spin_unlock_bh(&nss_top_main.stats_lock); 877 878 for (i = 0; (i < NSS_STATS_NODE_MAX); i++) { 879 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, 880 "%s = %llu\n", nss_stats_str_node[i], stats_shadow[i]); 881 } 882 883 /* 884 * N2H node stats 885 */ 886 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nn2h node stats:\n\n"); 887 spin_lock_bh(&nss_top_main.stats_lock); 888 for (i = NSS_STATS_NODE_MAX; (i < NSS_STATS_N2H_MAX); i++) { 889 stats_shadow[i] = nss_top_main.nss[0].stats_n2h[i]; 890 } 891 892 spin_unlock_bh(&nss_top_main.stats_lock); 893 894 for (i = 0; i < max; i++) { 895 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, 896 "%s = %llu\n", nss_stats_str_n2h[i], stats_shadow[i + NSS_STATS_NODE_MAX]); 897 } 898 899 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nn2h stats end\n\n"); 900 bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf)); 901 kfree(lbuf); 902 kfree(stats_shadow); 903 904 return bytes_read; 905} 906 907/* 908 * nss_stats_lso_rx_read() 909 * Read LSO_RX stats 910 */ 911static ssize_t nss_stats_lso_rx_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos) 912{ 913 int32_t i; 914 915 /* 916 * max output lines = #stats + start tag line + end tag line + three blank lines 917 */ 918 uint32_t max_output_lines = (NSS_STATS_NODE_MAX + 2) + (NSS_STATS_LSO_RX_MAX + 3) + 5; 919 size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines; 920 size_t size_wr = 0; 921 ssize_t bytes_read = 0; 922 uint64_t *stats_shadow; 923 924 char *lbuf = kzalloc(size_al, GFP_KERNEL); 925 if (unlikely(lbuf == NULL)) { 926 nss_warning("Could not allocate memory for local statistics buffer"); 927 return 0; 928 } 929 930 stats_shadow = kzalloc(NSS_STATS_LSO_RX_MAX * 8, GFP_KERNEL); 931 if (unlikely(stats_shadow == NULL)) { 932 nss_warning("Could not allocate memory for local shadow buffer"); 933 kfree(lbuf); 934 return 0; 935 } 936 937 size_wr = scnprintf(lbuf, size_al, "lso_rx stats start:\n\n"); 938 939 /* 940 * Common node stats 941 */ 942 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "common node stats:\n\n"); 943 spin_lock_bh(&nss_top_main.stats_lock); 944 for (i = 0; (i < NSS_STATS_NODE_MAX); i++) { 945 stats_shadow[i] = nss_top_main.stats_node[NSS_LSO_RX_INTERFACE][i]; 946 } 947 948 spin_unlock_bh(&nss_top_main.stats_lock); 949 950 for (i = 0; (i < NSS_STATS_NODE_MAX); i++) { 951 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, 952 "%s = %llu\n", nss_stats_str_node[i], stats_shadow[i]); 953 } 954 955 /* 956 * lso_rx node stats 957 */ 958 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nlso_rx node stats:\n\n"); 959 spin_lock_bh(&nss_top_main.stats_lock); 960 for (i = 0; (i < NSS_STATS_LSO_RX_MAX); i++) { 961 stats_shadow[i] = nss_top_main.stats_lso_rx[i]; 962 } 963 964 spin_unlock_bh(&nss_top_main.stats_lock); 965 966 for (i = 0; i < NSS_STATS_LSO_RX_MAX; i++) { 967 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, 968 "%s = %llu\n", nss_stats_str_lso_rx[i], stats_shadow[i]); 969 } 970 971 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nlso_rx stats end\n\n"); 972 bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf)); 973 kfree(lbuf); 974 kfree(stats_shadow); 975 976 return bytes_read; 977} 978 979/* 980 * nss_stats_drv_read() 981 * Read HLOS driver stats 982 */ 983static ssize_t nss_stats_drv_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos) 984{ 985 int32_t i; 986 987 /* 988 * max output lines = #stats + start tag line + end tag line + three blank lines 989 */ 990 uint32_t max_output_lines = NSS_STATS_DRV_MAX + 5; 991 size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines; 992 size_t size_wr = 0; 993 ssize_t bytes_read = 0; 994 uint64_t *stats_shadow; 995 996 char *lbuf = kzalloc(size_al, GFP_KERNEL); 997 if (unlikely(lbuf == NULL)) { 998 nss_warning("Could not allocate memory for local statistics buffer"); 999 return 0; 1000 } 1001 1002 stats_shadow = kzalloc(NSS_STATS_DRV_MAX * 8, GFP_KERNEL); 1003 if (unlikely(stats_shadow == NULL)) { 1004 nss_warning("Could not allocate memory for local shadow buffer"); 1005 kfree(lbuf); 1006 return 0; 1007 } 1008 1009 size_wr = scnprintf(lbuf, size_al, "drv stats start:\n\n"); 1010 for (i = 0; (i < NSS_STATS_DRV_MAX); i++) { 1011 stats_shadow[i] = NSS_PKT_STATS_READ(&nss_top_main.stats_drv[i]); 1012 } 1013 1014 for (i = 0; (i < NSS_STATS_DRV_MAX); i++) { 1015 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, 1016 "%s = %llu\n", nss_stats_str_drv[i], stats_shadow[i]); 1017 } 1018 1019 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\ndrv stats end\n\n"); 1020 bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf)); 1021 kfree(lbuf); 1022 kfree(stats_shadow); 1023 1024 return bytes_read; 1025} 1026 1027/* 1028 * nss_stats_pppoe_read() 1029 * Read PPPoE stats 1030 */ 1031static ssize_t nss_stats_pppoe_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos) 1032{ 1033 int32_t i, j, k; 1034 1035 /* 1036 * max output lines = #stats + start tag line + end tag line + three blank lines 1037 */ 1038 uint32_t max_output_lines = (NSS_STATS_NODE_MAX + 2) + (NSS_STATS_PPPOE_MAX + 3) + 1039 ((NSS_MAX_PHYSICAL_INTERFACES * NSS_PPPOE_NUM_SESSION_PER_INTERFACE * (NSS_PPPOE_EXCEPTION_EVENT_MAX + 5)) + 3) + 5; 1040 size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines; 1041 size_t size_wr = 0; 1042 ssize_t bytes_read = 0; 1043 uint64_t *stats_shadow; 1044 1045 char *lbuf = kzalloc(size_al, GFP_KERNEL); 1046 if (unlikely(lbuf == NULL)) { 1047 nss_warning("Could not allocate memory for local statistics buffer"); 1048 return 0; 1049 } 1050 1051 stats_shadow = kzalloc(64 * 8, GFP_KERNEL); 1052 if (unlikely(stats_shadow == NULL)) { 1053 nss_warning("Could not allocate memory for local shadow buffer"); 1054 kfree(lbuf); 1055 return 0; 1056 } 1057 1058 size_wr = scnprintf(lbuf, size_al, "pppoe stats start:\n\n"); 1059 1060 /* 1061 * Common node stats 1062 */ 1063 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "common node stats:\n\n"); 1064 spin_lock_bh(&nss_top_main.stats_lock); 1065 for (i = 0; (i < NSS_STATS_NODE_MAX); i++) { 1066 stats_shadow[i] = nss_top_main.stats_node[NSS_PPPOE_RX_INTERFACE][i]; 1067 } 1068 1069 spin_unlock_bh(&nss_top_main.stats_lock); 1070 1071 for (i = 0; (i < NSS_STATS_NODE_MAX); i++) { 1072 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, 1073 "%s = %llu\n", nss_stats_str_node[i], stats_shadow[i]); 1074 } 1075 1076 /* 1077 * PPPoE node stats 1078 */ 1079 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\npppoe node stats:\n\n"); 1080 spin_lock_bh(&nss_top_main.stats_lock); 1081 for (i = 0; (i < NSS_STATS_PPPOE_MAX); i++) { 1082 stats_shadow[i] = nss_top_main.stats_pppoe[i]; 1083 } 1084 1085 spin_unlock_bh(&nss_top_main.stats_lock); 1086 1087 for (i = 0; (i < NSS_STATS_PPPOE_MAX); i++) { 1088 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, 1089 "%s = %llu\n", nss_stats_str_pppoe[i], stats_shadow[i]); 1090 } 1091 1092 /* 1093 * Exception stats 1094 */ 1095 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nException PPPoE:\n\n"); 1096 1097 for (j = 1; j <= NSS_MAX_PHYSICAL_INTERFACES; j++) { 1098 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nInterface %d:\n\n", j); 1099 1100 spin_lock_bh(&nss_top_main.stats_lock); 1101 for (k = 1; k <= NSS_PPPOE_NUM_SESSION_PER_INTERFACE; k++) { 1102 for (i = 0; (i < NSS_PPPOE_EXCEPTION_EVENT_MAX); i++) { 1103 stats_shadow_pppoe_except[k - 1][i] = nss_top_main.stats_if_exception_pppoe[j][k][i]; 1104 } 1105 } 1106 1107 spin_unlock_bh(&nss_top_main.stats_lock); 1108 1109 for (k = 1; k <= NSS_PPPOE_NUM_SESSION_PER_INTERFACE; k++) { 1110 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "%d. Session\n", k); 1111 for (i = 0; (i < NSS_PPPOE_EXCEPTION_EVENT_MAX); i++) { 1112 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, 1113 "%s = %llu\n", 1114 nss_stats_str_if_exception_pppoe[i], 1115 stats_shadow_pppoe_except[k - 1][i]); 1116 } 1117 } 1118 1119 } 1120 1121 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\npppoe stats end\n\n"); 1122 bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf)); 1123 kfree(lbuf); 1124 kfree(stats_shadow); 1125 1126 return bytes_read; 1127} 1128 1129/* 1130 * nss_stats_gmac_read() 1131 * Read GMAC stats 1132 */ 1133static ssize_t nss_stats_gmac_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos) 1134{ 1135 uint32_t i, id; 1136 1137 /* 1138 * max output lines = ((#stats + start tag + one blank) * #GMACs) + start/end tag + 3 blank 1139 */ 1140 uint32_t max_output_lines = ((NSS_STATS_GMAC_MAX + 2) * NSS_MAX_PHYSICAL_INTERFACES) + 5; 1141 size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines; 1142 size_t size_wr = 0; 1143 ssize_t bytes_read = 0; 1144 uint64_t *stats_shadow; 1145 1146 char *lbuf = kzalloc(size_al, GFP_KERNEL); 1147 if (unlikely(lbuf == NULL)) { 1148 nss_warning("Could not allocate memory for local statistics buffer"); 1149 return 0; 1150 } 1151 1152 stats_shadow = kzalloc(NSS_STATS_GMAC_MAX * 8, GFP_KERNEL); 1153 if (unlikely(stats_shadow == NULL)) { 1154 nss_warning("Could not allocate memory for local shadow buffer"); 1155 kfree(lbuf); 1156 return 0; 1157 } 1158 1159 size_wr = scnprintf(lbuf, size_al, "gmac stats start:\n\n"); 1160 1161 for (id = 0; id < NSS_MAX_PHYSICAL_INTERFACES; id++) { 1162 spin_lock_bh(&nss_top_main.stats_lock); 1163 for (i = 0; (i < NSS_STATS_GMAC_MAX); i++) { 1164 stats_shadow[i] = nss_top_main.stats_gmac[id][i]; 1165 } 1166 1167 spin_unlock_bh(&nss_top_main.stats_lock); 1168 1169 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "GMAC ID: %d\n", id); 1170 for (i = 0; (i < NSS_STATS_GMAC_MAX); i++) { 1171 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, 1172 "%s = %llu\n", nss_stats_str_gmac[i], stats_shadow[i]); 1173 } 1174 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,"\n"); 1175 } 1176 1177 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\ngmac stats end\n\n"); 1178 bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf)); 1179 kfree(lbuf); 1180 kfree(stats_shadow); 1181 1182 return bytes_read; 1183} 1184 1185/* 1186 * nss_stats_wifi_read() 1187 * Read wifi statistics 1188 */ 1189static ssize_t nss_stats_wifi_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos) 1190{ 1191 uint32_t i, id; 1192 1193 /* 1194 * max output lines = ((#stats + start tag + one blank) * #WIFI RADIOs) + start/end tag + 3 blank 1195 */ 1196 uint32_t max_output_lines = ((NSS_STATS_WIFI_MAX + 2) * NSS_MAX_WIFI_RADIO_INTERFACES) + 5; 1197 size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines; 1198 size_t size_wr = 0; 1199 ssize_t bytes_read = 0; 1200 uint64_t *stats_shadow; 1201 1202 char *lbuf = kzalloc(size_al, GFP_KERNEL); 1203 if (unlikely(lbuf == NULL)) { 1204 nss_warning("Could not allocate memory for local statistics buffer"); 1205 return 0; 1206 } 1207 1208 stats_shadow = kzalloc(NSS_STATS_WIFI_MAX * 8, GFP_KERNEL); 1209 if (unlikely(stats_shadow == NULL)) { 1210 nss_warning("Could not allocate memory for local shadow buffer"); 1211 kfree(lbuf); 1212 return 0; 1213 } 1214 1215 size_wr = scnprintf(lbuf, size_al, "wifi stats start:\n\n"); 1216 1217 for (id = 0; id < NSS_MAX_WIFI_RADIO_INTERFACES; id++) { 1218 spin_lock_bh(&nss_top_main.stats_lock); 1219 for (i = 0; (i < NSS_STATS_WIFI_MAX); i++) { 1220 stats_shadow[i] = nss_top_main.stats_wifi[id][i]; 1221 } 1222 1223 spin_unlock_bh(&nss_top_main.stats_lock); 1224 1225 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "WIFI ID: %d\n", id); 1226 for (i = 0; (i < NSS_STATS_WIFI_MAX); i++) { 1227 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, 1228 "%s = %llu\n", nss_stats_str_wifi[i], stats_shadow[i]); 1229 } 1230 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr,"\n"); 1231 } 1232 1233 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nwifi stats end\n\n"); 1234 bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf)); 1235 kfree(lbuf); 1236 kfree(stats_shadow); 1237 1238 return bytes_read; 1239} 1240 1241/* 1242 * nss_stats_sjack_read() 1243 * Read SJACK stats 1244 */ 1245static ssize_t nss_stats_sjack_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos) 1246{ 1247 int32_t i; 1248 /* 1249 * max output lines = #stats + start tag line + end tag line + three blank lines 1250 */ 1251 uint32_t max_output_lines = NSS_STATS_NODE_MAX + 5; 1252 size_t size_al = NSS_STATS_MAX_STR_LENGTH * max_output_lines; 1253 size_t size_wr = 0; 1254 ssize_t bytes_read = 0; 1255 uint64_t *stats_shadow; 1256 1257 char *lbuf = kzalloc(size_al, GFP_KERNEL); 1258 if (unlikely(lbuf == NULL)) { 1259 nss_warning("Could not allocate memory for local statistics buffer"); 1260 return 0; 1261 } 1262 1263 stats_shadow = kzalloc(NSS_STATS_NODE_MAX * 8, GFP_KERNEL); 1264 if (unlikely(stats_shadow == NULL)) { 1265 nss_warning("Could not allocate memory for local shadow buffer"); 1266 kfree(lbuf); 1267 return 0; 1268 } 1269 1270 size_wr = scnprintf(lbuf, size_al, "sjack stats start:\n\n"); 1271 1272 /* 1273 * Common node stats 1274 */ 1275 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "common node stats:\n\n"); 1276 spin_lock_bh(&nss_top_main.stats_lock); 1277 for (i = 0; (i < NSS_STATS_NODE_MAX); i++) { 1278 stats_shadow[i] = nss_top_main.stats_node[NSS_SJACK_INTERFACE][i]; 1279 } 1280 1281 spin_unlock_bh(&nss_top_main.stats_lock); 1282 1283 for (i = 0; (i < NSS_STATS_NODE_MAX); i++) { 1284 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, 1285 "%s = %llu\n", nss_stats_str_node[i], stats_shadow[i]); 1286 } 1287 1288 size_wr += scnprintf(lbuf + size_wr, size_al - size_wr, "\nsjack stats end\n\n"); 1289 1290 bytes_read = simple_read_from_buffer(ubuf, sz, ppos, lbuf, strlen(lbuf)); 1291 kfree(lbuf); 1292 kfree(stats_shadow); 1293 1294 return bytes_read; 1295} 1296 1297/* 1298 * Make a row for CAPWAP encap stats. 1299 */ 1300static ssize_t nss_stats_capwap_encap(char *line, int len, int i, struct nss_capwap_tunnel_stats *s) 1301{ 1302 char *header[] = { "packets", "bytes", "fragments", "drop_ref", "drop_ver", "drop_unalign", 1303 "drop_hroom", "drop_dtls", "drop_nwireless", "drop_qfull", "drop_memfail", "unknown" }; 1304 uint64_t tcnt = 0; 1305 1306 switch (i) { 1307 case 0: 1308 tcnt = s->pnode_stats.tx_packets; 1309 break; 1310 case 1: 1311 tcnt = s->pnode_stats.tx_bytes; 1312 break; 1313 case 2: 1314 tcnt = s->tx_segments; 1315 break; 1316 case 3: 1317 tcnt = s->tx_dropped_sg_ref; 1318 break; 1319 case 4: 1320 tcnt = s->tx_dropped_ver_mis; 1321 break; 1322 case 5: 1323 tcnt = s->tx_dropped_unalign; 1324 break; 1325 case 6: 1326 tcnt = s->tx_dropped_hroom; 1327 break; 1328 case 7: 1329 tcnt = s->tx_dropped_dtls; 1330 break; 1331 case 8: 1332 tcnt = s->tx_dropped_nwireless; 1333 break; 1334 case 9: 1335 tcnt = s->tx_queue_full_drops; 1336 break; 1337 case 10: 1338 tcnt = s->tx_mem_failure_drops; 1339 break; 1340 default: 1341 return 0; 1342 } 1343 1344 return (snprintf(line, len, "%s = %llu\n", header[i], tcnt)); 1345} 1346 1347/* 1348 * Make a row for CAPWAP decap stats. 1349 */ 1350static ssize_t nss_stats_capwap_decap(char *line, int len, int i, struct nss_capwap_tunnel_stats *s) 1351{ 1352 char *header[] = { "packets", "bytes", "DTLS_pkts", "fragments", "rx_dropped", "drop_oversize", 1353 "drop_frag_timeout", "drop_frag_dup", "drop_frag_gap", "drop_qfull", "drop_memfail", 1354 "drop_csum", "drop_malformed", "unknown" }; 1355 uint64_t tcnt = 0; 1356 1357 switch(i) { 1358 case 0: 1359 tcnt = s->pnode_stats.rx_packets; 1360 break; 1361 case 1: 1362 tcnt = s->pnode_stats.rx_bytes; 1363 break; 1364 case 2: 1365 tcnt = s->dtls_pkts; 1366 break; 1367 case 3: 1368 tcnt = s->rx_segments; 1369 break; 1370 case 4: 1371 tcnt = s->pnode_stats.rx_dropped; 1372 break; 1373 case 5: 1374 tcnt = s->rx_oversize_drops; 1375 break; 1376 case 6: 1377 tcnt = s->rx_frag_timeout_drops; 1378 break; 1379 case 7: 1380 tcnt = s->rx_dup_frag; 1381 break; 1382 case 8: 1383 tcnt = s->rx_frag_gap_drops; 1384 break; 1385 case 9: 1386 tcnt = s->rx_queue_full_drops; 1387 return (snprintf(line, len, "%s = %llu (n2h = %llu)\n", header[i], tcnt, s->rx_n2h_queue_full_drops)); 1388 case 10: 1389 tcnt = s->rx_mem_failure_drops; 1390 break; 1391 case 11: 1392 tcnt = s->rx_csum_drops; 1393 break; 1394 case 12: 1395 tcnt = s->rx_malformed; 1396 break; 1397 default: 1398 return 0; 1399 } 1400 1401 return (snprintf(line, len, "%s = %llu\n", header[i], tcnt)); 1402} 1403 1404/* 1405 * nss_stats_capwap_read() 1406 * Read CAPWAP stats 1407 */ 1408static ssize_t nss_stats_capwap_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos, uint16_t type) 1409{ 1410 struct nss_stats_data *data = fp->private_data; 1411 ssize_t bytes_read = 0; 1412 struct nss_capwap_tunnel_stats stats; 1413 size_t bytes; 1414 char line[80]; 1415 int start; 1416 uint32_t if_num = NSS_DYNAMIC_IF_START; 1417 uint32_t max_if_num = NSS_DYNAMIC_IF_START + NSS_MAX_DYNAMIC_INTERFACES; 1418 1419 if (data) { 1420 if_num = data->if_num; 1421 } 1422 1423 /* 1424 * If we are done accomodating all the CAPWAP tunnels. 1425 */ 1426 if (if_num > max_if_num) { 1427 return 0; 1428 } 1429 1430 for (; if_num <= max_if_num; if_num++) { 1431 bool isthere; 1432 1433 if (nss_is_dynamic_interface(if_num) == false) { 1434 continue; 1435 } 1436 1437 if (nss_dynamic_interface_get_type(if_num) != NSS_DYNAMIC_INTERFACE_TYPE_CAPWAP) { 1438 continue; 1439 } 1440 1441 /* 1442 * If CAPWAP tunnel does not exists, then isthere will be false. 1443 */ 1444 isthere = nss_capwap_get_stats(if_num, &stats); 1445 if (!isthere) { 1446 continue; 1447 } 1448 1449 bytes = snprintf(line, sizeof(line), "----if_num : %2d----\n", if_num); 1450 if ((bytes_read + bytes) > sz) { 1451 break; 1452 } 1453 1454 if (copy_to_user(ubuf + bytes_read, line, bytes) != 0) { 1455 bytes_read = -EFAULT; 1456 goto fail; 1457 } 1458 bytes_read += bytes; 1459 start = 0; 1460 while (bytes_read < sz) { 1461 if (type == 1) { 1462 bytes = nss_stats_capwap_encap(line, sizeof(line), start, &stats); 1463 } else { 1464 bytes = nss_stats_capwap_decap(line, sizeof(line), start, &stats); 1465 } 1466 1467 /* 1468 * If we don't have any more lines in decap/encap. 1469 */ 1470 if (bytes == 0) { 1471 break; 1472 } 1473 1474 if ((bytes_read + bytes) > sz) 1475 break; 1476 1477 if (copy_to_user(ubuf + bytes_read, line, bytes) != 0) { 1478 bytes_read = -EFAULT; 1479 goto fail; 1480 } 1481 1482 bytes_read += bytes; 1483 start++; 1484 } 1485 } 1486 1487 if (bytes_read > 0) { 1488 *ppos = bytes_read; 1489 } 1490 1491 if (data) { 1492 data->if_num = if_num; 1493 } 1494fail: 1495 return bytes_read; 1496} 1497 1498/* 1499 * nss_stats_capwap_decap_read() 1500 * Read CAPWAP decap stats 1501 */ 1502static ssize_t nss_stats_capwap_decap_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos) 1503{ 1504 return (nss_stats_capwap_read(fp, ubuf, sz, ppos, 0)); 1505} 1506 1507/* 1508 * nss_stats_capwap_encap_read() 1509 * Read CAPWAP encap stats 1510 */ 1511static ssize_t nss_stats_capwap_encap_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos) 1512{ 1513 return (nss_stats_capwap_read(fp, ubuf, sz, ppos, 1)); 1514} 1515 1516/* 1517 * nss_stats_gre_redir() 1518 * Make a row for GRE_REDIR stats. 1519 */ 1520static ssize_t nss_stats_gre_redir(char *line, int len, int i, struct nss_gre_redir_tunnel_stats *s) 1521{ 1522 char *header[] = { "TX Packets", "TX Bytes", "TX Drops", "RX Packets", "RX Bytes", "Rx Drops" }; 1523 uint64_t tcnt = 0; 1524 1525 switch (i) { 1526 case 0: 1527 tcnt = s->node_stats.tx_packets; 1528 break; 1529 case 1: 1530 tcnt = s->node_stats.tx_bytes; 1531 break; 1532 case 2: 1533 tcnt = s->tx_dropped; 1534 break; 1535 case 3: 1536 tcnt = s->node_stats.rx_packets; 1537 break; 1538 case 4: 1539 tcnt = s->node_stats.rx_bytes; 1540 break; 1541 case 5: 1542 tcnt = s->node_stats.rx_dropped; 1543 break; 1544 default: 1545 i = 6; 1546 break; 1547 } 1548 1549 return (snprintf(line, len, "%s = %llu\n", header[i], tcnt)); 1550} 1551 1552/* 1553 * nss_stats_gre_redir_read() 1554 * READ gre_redir tunnel stats. 1555 */ 1556static ssize_t nss_stats_gre_redir_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos) 1557{ 1558 struct nss_stats_data *data = fp->private_data; 1559 ssize_t bytes_read = 0; 1560 struct nss_gre_redir_tunnel_stats stats; 1561 size_t bytes; 1562 char line[80]; 1563 int start, end; 1564 int index = 0; 1565 1566 if (data) { 1567 index = data->index; 1568 } 1569 1570 /* 1571 * If we are done accomodating all the GRE_REDIR tunnels. 1572 */ 1573 if (index >= NSS_GRE_REDIR_MAX_INTERFACES) { 1574 return 0; 1575 } 1576 1577 for (; index < NSS_GRE_REDIR_MAX_INTERFACES; index++) { 1578 bool isthere; 1579 1580 /* 1581 * If gre_redir tunnel does not exists, then isthere will be false. 1582 */ 1583 isthere = nss_gre_redir_get_stats(index, &stats); 1584 if (!isthere) { 1585 continue; 1586 } 1587 1588 bytes = snprintf(line, sizeof(line), "\nTunnel if_num: %2d\n", stats.if_num); 1589 if ((bytes_read + bytes) > sz) { 1590 break; 1591 } 1592 1593 if (copy_to_user(ubuf + bytes_read, line, bytes) != 0) { 1594 bytes_read = -EFAULT; 1595 goto fail; 1596 } 1597 bytes_read += bytes; 1598 start = 0; 1599 end = 6; 1600 while (bytes_read < sz && start < end) { 1601 bytes = nss_stats_gre_redir(line, sizeof(line), start, &stats); 1602 1603 if ((bytes_read + bytes) > sz) 1604 break; 1605 1606 if (copy_to_user(ubuf + bytes_read, line, bytes) != 0) { 1607 bytes_read = -EFAULT; 1608 goto fail; 1609 } 1610 1611 bytes_read += bytes; 1612 start++; 1613 } 1614 } 1615 1616 if (bytes_read > 0) { 1617 *ppos = bytes_read; 1618 } 1619 1620 if (data) { 1621 data->index = index; 1622 } 1623 1624fail: 1625 return bytes_read; 1626} 1627 1628/* 1629 * nss_stats_wifi_if_read() 1630 * Read wifi_if statistics 1631 */ 1632static ssize_t nss_stats_wifi_if_read(struct file *fp, char __user *ubuf, size_t sz, loff_t *ppos) 1633{ 1634 struct nss_stats_data *data = fp->private_data; 1635 int32_t if_num = NSS_DYNAMIC_IF_START; 1636 int32_t max_if_num = if_num + NSS_MAX_DYNAMIC_INTERFACES; 1637 size_t bytes = 0; 1638 ssize_t bytes_read = 0; 1639 char line[80]; 1640 int start, end; 1641 1642 if (data) { 1643 if_num = data->if_num; 1644 } 1645 1646 if (if_num > max_if_num) { 1647 return 0; 1648 } 1649 1650 for (; if_num < max_if_num; if_num++) { 1651 if (nss_dynamic_interface_get_type(if_num) != NSS_DYNAMIC_INTERFACE_TYPE_WIFI) 1652 continue; 1653 1654 bytes = scnprintf(line, sizeof(line), "if_num %d stats start:\n\n", if_num); 1655 if ((bytes_read + bytes) > sz) 1656 break; 1657 1658 if (copy_to_user(ubuf + bytes_read, line, bytes) != 0) { 1659 bytes_read = -EFAULT; 1660 goto end; 1661 } 1662 1663 bytes_read += bytes; 1664 1665 start = 0; 1666 end = 7; 1667 while (bytes_read < sz && start < end) { 1668 bytes = nss_wifi_if_copy_stats(if_num, start, line); 1669 if (!bytes) 1670 break; 1671 1672 if ((bytes_read + bytes) > sz) 1673 break; 1674 1675 if (copy_to_user(ubuf + bytes_read, line, bytes) != 0) { 1676 bytes_read = -EFAULT; 1677 goto end; 1678 } 1679 1680 bytes_read += bytes; 1681 start++; 1682 } 1683 1684 bytes = scnprintf(line, sizeof(line), "if_num %d stats end:\n\n", if_num); 1685 if (bytes_read > (sz - bytes)) 1686 break; 1687 1688 if (copy_to_user(ubuf + bytes_read, line, bytes) != 0) { 1689 bytes_read = -EFAULT; 1690 goto end; 1691 } 1692 1693 bytes_read += bytes; 1694 } 1695 1696 if (bytes_read > 0) { 1697 *ppos = bytes_read; 1698 } 1699 1700 if (data) { 1701 data->if_num = if_num; 1702 } 1703 1704end: 1705 return bytes_read; 1706} 1707 1708/* 1709 * nss_stats_virt_if_read() 1710 * Read virt_if statistics 1711 */ 1712static ssize_t nss_stats_virt_if_read(struct file *fp, char __user *ubuf, 1713 size_t sz, loff_t *ppos) 1714{ 1715 struct nss_stats_data *data = fp->private_data; 1716 int32_t if_num = NSS_DYNAMIC_IF_START; 1717 int32_t max_if_num = if_num + NSS_MAX_DYNAMIC_INTERFACES; 1718 size_t bytes = 0; 1719 ssize_t bytes_read = 0; 1720 char line[80]; 1721 int start, end; 1722 1723 if (data) { 1724 if_num = data->if_num; 1725 } 1726 1727 if (if_num > max_if_num) { 1728 return 0; 1729 } 1730 1731 for (; if_num < max_if_num; if_num++) { 1732 if (nss_dynamic_interface_get_type(if_num) != NSS_DYNAMIC_INTERFACE_TYPE_802_3_REDIR) 1733 continue; 1734 1735 bytes = scnprintf(line, sizeof(line), "if_num %d stats start:\n\n", if_num); 1736 if ((bytes_read + bytes) > sz) 1737 break; 1738 1739 if (copy_to_user(ubuf + bytes_read, line, bytes) != 0) { 1740 bytes_read = -EFAULT; 1741 goto end; 1742 } 1743 1744 bytes_read += bytes; 1745 1746 start = 0; 1747 end = 7; 1748 while (bytes_read < sz && start < end) { 1749 bytes = nss_virt_if_copy_stats(if_num, start, line); 1750 if (!bytes) 1751 break; 1752 1753 if ((bytes_read + bytes) > sz) 1754 break; 1755 1756 if (copy_to_user(ubuf + bytes_read, line, bytes) != 0) { 1757 bytes_read = -EFAULT; 1758 goto end; 1759 } 1760 1761 bytes_read += bytes; 1762 start++; 1763 } 1764 1765 bytes = scnprintf(line, sizeof(line), "if_num %d stats end:\n\n", if_num); 1766 if (bytes_read > (sz - bytes)) 1767 break; 1768 1769 if (copy_to_user(ubuf + bytes_read, line, bytes) != 0) { 1770 bytes_read = -EFAULT; 1771 goto end; 1772 } 1773 1774 bytes_read += bytes; 1775 } 1776 1777 if (bytes_read > 0) { 1778 *ppos = bytes_read; 1779 } 1780 1781 if (data) { 1782 data->if_num = if_num; 1783 } 1784 1785end: 1786 return bytes_read; 1787} 1788 1789/* 1790 * nss_stats_tx_rx_virt_if_read() 1791 * Read tx_rx_virt_if statistics 1792 */ 1793static ssize_t nss_stats_tx_rx_virt_if_read(struct file *fp, char __user *ubuf, 1794 size_t sz, loff_t *ppos) 1795{ 1796 struct nss_stats_data *data = fp->private_data; 1797 int32_t if_num = NSS_DYNAMIC_IF_START; 1798 int32_t max_if_num = if_num + NSS_MAX_DYNAMIC_INTERFACES; 1799 size_t bytes = 0; 1800 ssize_t bytes_read = 0; 1801 char line[80]; 1802 int start, end; 1803 1804 if (data) { 1805 if_num = data->if_num; 1806 } 1807 1808 if (if_num > max_if_num) { 1809 return 0; 1810 } 1811 1812 for (; if_num < max_if_num; if_num++) { 1813 if (nss_dynamic_interface_get_type(if_num) != NSS_DYNAMIC_INTERFACE_TYPE_VIRTIF_DEPRECATED) 1814 continue; 1815 1816 bytes = scnprintf(line, sizeof(line), "if_num %d stats start:\n\n", if_num); 1817 if ((bytes_read + bytes) > sz) 1818 break; 1819 1820 if (copy_to_user(ubuf + bytes_read, line, bytes) != 0) { 1821 bytes_read = -EFAULT; 1822 goto end; 1823 } 1824 1825 bytes_read += bytes; 1826 1827 start = 0; 1828 end = 7; 1829 while (bytes_read < sz && start < end) { 1830 bytes = nss_tx_rx_virt_if_copy_stats(if_num, start, line); 1831 if (!bytes) 1832 break; 1833 1834 if ((bytes_read + bytes) > sz) 1835 break; 1836 1837 if (copy_to_user(ubuf + bytes_read, line, bytes) != 0) { 1838 bytes_read = -EFAULT; 1839 goto end; 1840 } 1841 1842 bytes_read += bytes; 1843 start++; 1844 } 1845 1846 bytes = scnprintf(line, sizeof(line), "if_num %d stats end:\n\n", if_num); 1847 if (bytes_read > (sz - bytes)) 1848 break; 1849 1850 if (copy_to_user(ubuf + bytes_read, line, bytes) != 0) { 1851 bytes_read = -EFAULT; 1852 goto end; 1853 } 1854 1855 bytes_read += bytes; 1856 } 1857 1858 if (bytes_read > 0) { 1859 *ppos = bytes_read; 1860 } 1861 1862 if (data) { 1863 data->if_num = if_num; 1864 } 1865 1866end: 1867 return bytes_read; 1868} 1869 1870/* 1871 * nss_stats_open() 1872 */ 1873static int nss_stats_open(struct inode *inode, struct file *filp) 1874{ 1875 struct nss_stats_data *data = NULL; 1876 1877 data = kzalloc(sizeof(struct nss_stats_data), GFP_KERNEL); 1878 if (!data) { 1879 return -ENOMEM; 1880 } 1881 memset(data, 0, sizeof (struct nss_stats_data)); 1882 data->if_num = NSS_DYNAMIC_IF_START; 1883 data->index = 0; 1884 filp->private_data = data; 1885 1886 return 0; 1887} 1888 1889/* 1890 * nss_stats_release() 1891 */ 1892static int nss_stats_release(struct inode *inode, struct file *filp) 1893{ 1894 struct nss_stats_data *data = filp->private_data; 1895 1896 if (data) { 1897 kfree(data); 1898 } 1899 1900 return 0; 1901} 1902 1903#define NSS_STATS_DECLARE_FILE_OPERATIONS(name) \ 1904static const struct file_operations nss_stats_##name##_ops = { \ 1905 .open = nss_stats_open, \ 1906 .read = nss_stats_##name##_read, \ 1907 .llseek = generic_file_llseek, \ 1908 .release = nss_stats_release, \ 1909}; 1910 1911/* 1912 * nss_ipv4_stats_ops 1913 */ 1914NSS_STATS_DECLARE_FILE_OPERATIONS(ipv4) 1915 1916/* 1917 * ipv4_reasm_stats_ops 1918 */ 1919NSS_STATS_DECLARE_FILE_OPERATIONS(ipv4_reasm) 1920 1921/* 1922 * ipv6_stats_ops 1923 */ 1924NSS_STATS_DECLARE_FILE_OPERATIONS(ipv6) 1925 1926/* 1927 * ipv6_reasm_stats_ops 1928 */ 1929NSS_STATS_DECLARE_FILE_OPERATIONS(ipv6_reasm) 1930 1931/* 1932 * n2h_stats_ops 1933 */ 1934NSS_STATS_DECLARE_FILE_OPERATIONS(n2h) 1935 1936/* 1937 * lso_rx_stats_ops 1938 */ 1939NSS_STATS_DECLARE_FILE_OPERATIONS(lso_rx) 1940 1941/* 1942 * drv_stats_ops 1943 */ 1944NSS_STATS_DECLARE_FILE_OPERATIONS(drv) 1945 1946/* 1947 * pppoe_stats_ops 1948 */ 1949NSS_STATS_DECLARE_FILE_OPERATIONS(pppoe) 1950 1951/* 1952 * gmac_stats_ops 1953 */ 1954NSS_STATS_DECLARE_FILE_OPERATIONS(gmac) 1955 1956/* 1957 * capwap_stats_ops 1958 */ 1959NSS_STATS_DECLARE_FILE_OPERATIONS(capwap_encap) 1960NSS_STATS_DECLARE_FILE_OPERATIONS(capwap_decap) 1961 1962/* 1963 * eth_rx_stats_ops 1964 */ 1965NSS_STATS_DECLARE_FILE_OPERATIONS(eth_rx) 1966 1967/* 1968 * gre_redir_ops 1969 */ 1970NSS_STATS_DECLARE_FILE_OPERATIONS(gre_redir) 1971 1972/* 1973 * sjack_stats_ops 1974 */ 1975NSS_STATS_DECLARE_FILE_OPERATIONS(sjack) 1976 1977NSS_STATS_DECLARE_FILE_OPERATIONS(wifi_if) 1978 1979NSS_STATS_DECLARE_FILE_OPERATIONS(virt_if) 1980 1981NSS_STATS_DECLARE_FILE_OPERATIONS(tx_rx_virt_if) 1982 1983/* 1984 * wifi_stats_ops 1985 */ 1986NSS_STATS_DECLARE_FILE_OPERATIONS(wifi) 1987 1988/* 1989 * nss_stats_init() 1990 * Enable NSS statistics 1991 */ 1992void nss_stats_init(void) 1993{ 1994 /* 1995 * NSS driver entry 1996 */ 1997 nss_top_main.top_dentry = debugfs_create_dir("qca-nss-drv", NULL); 1998 if (unlikely(nss_top_main.top_dentry == NULL)) { 1999 nss_warning("Failed to create qca-nss-drv directory in debugfs"); 2000 2001 /* 2002 * Non availability of debugfs directory is not a catastrophy 2003 * We can still go ahead with other initialization 2004 */ 2005 return; 2006 } 2007 2008 nss_top_main.stats_dentry = debugfs_create_dir("stats", nss_top_main.top_dentry); 2009 if (unlikely(nss_top_main.stats_dentry == NULL)) { 2010 nss_warning("Failed to create qca-nss-drv directory in debugfs"); 2011 2012 /* 2013 * Non availability of debugfs directory is not a catastrophy 2014 * We can still go ahead with rest of initialization 2015 */ 2016 return; 2017 } 2018 2019 /* 2020 * Create files to obtain statistics 2021 */ 2022 2023 /* 2024 * ipv4_stats 2025 */ 2026 nss_top_main.ipv4_dentry = debugfs_create_file("ipv4", 0400, 2027 nss_top_main.stats_dentry, &nss_top_main, &nss_stats_ipv4_ops); 2028 if (unlikely(nss_top_main.ipv4_dentry == NULL)) { 2029 nss_warning("Failed to create qca-nss-drv/stats/ipv4 file in debugfs"); 2030 return; 2031 } 2032 2033 /* 2034 * ipv4_reasm_stats 2035 */ 2036 nss_top_main.ipv4_reasm_dentry = debugfs_create_file("ipv4_reasm", 0400, 2037 nss_top_main.stats_dentry, &nss_top_main, &nss_stats_ipv4_reasm_ops); 2038 if (unlikely(nss_top_main.ipv4_reasm_dentry == NULL)) { 2039 nss_warning("Failed to create qca-nss-drv/stats/ipv4_reasm file in debugfs"); 2040 return; 2041 } 2042 2043 /* 2044 * ipv6_stats 2045 */ 2046 nss_top_main.ipv6_dentry = debugfs_create_file("ipv6", 0400, 2047 nss_top_main.stats_dentry, &nss_top_main, &nss_stats_ipv6_ops); 2048 if (unlikely(nss_top_main.ipv6_dentry == NULL)) { 2049 nss_warning("Failed to create qca-nss-drv/stats/ipv6 file in debugfs"); 2050 return; 2051 } 2052 2053 /* 2054 * ipv6_reasm_stats 2055 */ 2056 nss_top_main.ipv6_reasm_dentry = debugfs_create_file("ipv6_reasm", 0400, 2057 nss_top_main.stats_dentry, &nss_top_main, &nss_stats_ipv6_reasm_ops); 2058 if (unlikely(nss_top_main.ipv6_reasm_dentry == NULL)) { 2059 nss_warning("Failed to create qca-nss-drv/stats/ipv6_reasm file in debugfs"); 2060 return; 2061 } 2062 2063 /* 2064 * eth_rx__stats 2065 */ 2066 nss_top_main.eth_rx_dentry = debugfs_create_file("eth_rx", 0400, 2067 nss_top_main.stats_dentry, &nss_top_main, &nss_stats_eth_rx_ops); 2068 if (unlikely(nss_top_main.eth_rx_dentry == NULL)) { 2069 nss_warning("Failed to create qca-nss-drv/stats/eth_rx file in debugfs"); 2070 return; 2071 } 2072 2073 /* 2074 * n2h_stats 2075 */ 2076 nss_top_main.n2h_dentry = debugfs_create_file("n2h", 0400, 2077 nss_top_main.stats_dentry, &nss_top_main, &nss_stats_n2h_ops); 2078 if (unlikely(nss_top_main.n2h_dentry == NULL)) { 2079 nss_warning("Failed to create qca-nss-drv/stats/n2h directory in debugfs"); 2080 return; 2081 } 2082 2083 /* 2084 * lso_rx_stats 2085 */ 2086 nss_top_main.lso_rx_dentry = debugfs_create_file("lso_rx", 0400, 2087 nss_top_main.stats_dentry, &nss_top_main, &nss_stats_lso_rx_ops); 2088 if (unlikely(nss_top_main.lso_rx_dentry == NULL)) { 2089 nss_warning("Failed to create qca-nss-drv/stats/lso_rx file in debugfs"); 2090 return; 2091 } 2092 2093 /* 2094 * drv_stats 2095 */ 2096 nss_top_main.drv_dentry = debugfs_create_file("drv", 0400, 2097 nss_top_main.stats_dentry, &nss_top_main, &nss_stats_drv_ops); 2098 if (unlikely(nss_top_main.drv_dentry == NULL)) { 2099 nss_warning("Failed to create qca-nss-drv/stats/drv directory in debugfs"); 2100 return; 2101 } 2102 2103 /* 2104 * pppoe_stats 2105 */ 2106 nss_top_main.pppoe_dentry = debugfs_create_file("pppoe", 0400, 2107 nss_top_main.stats_dentry, &nss_top_main, &nss_stats_pppoe_ops); 2108 if (unlikely(nss_top_main.pppoe_dentry == NULL)) { 2109 nss_warning("Failed to create qca-nss-drv/stats/pppoe file in debugfs"); 2110 return; 2111 } 2112 2113 /* 2114 * gmac_stats 2115 */ 2116 nss_top_main.gmac_dentry = debugfs_create_file("gmac", 0400, 2117 nss_top_main.stats_dentry, &nss_top_main, &nss_stats_gmac_ops); 2118 if (unlikely(nss_top_main.gmac_dentry == NULL)) { 2119 nss_warning("Failed to create qca-nss-drv/stats/gmac file in debugfs"); 2120 return; 2121 } 2122 2123 /* 2124 * CAPWAP stats. 2125 */ 2126 nss_top_main.capwap_encap_dentry = debugfs_create_file("capwap_encap", 0400, 2127 nss_top_main.stats_dentry, &nss_top_main, &nss_stats_capwap_encap_ops); 2128 if (unlikely(nss_top_main.capwap_encap_dentry == NULL)) { 2129 nss_warning("Failed to create qca-nss-drv/stats/capwap_encap file in debugfs"); 2130 return; 2131 } 2132 2133 nss_top_main.capwap_decap_dentry = debugfs_create_file("capwap_decap", 0400, 2134 nss_top_main.stats_dentry, &nss_top_main, &nss_stats_capwap_decap_ops); 2135 if (unlikely(nss_top_main.capwap_decap_dentry == NULL)) { 2136 nss_warning("Failed to create qca-nss-drv/stats/capwap_decap file in debugfs"); 2137 return; 2138 } 2139 2140 /* 2141 * GRE_REDIR stats 2142 */ 2143 nss_top_main.gre_redir_dentry = debugfs_create_file("gre_redir", 0400, 2144 nss_top_main.stats_dentry, &nss_top_main, &nss_stats_gre_redir_ops); 2145 if (unlikely(nss_top_main.gre_redir_dentry == NULL)) { 2146 nss_warning("Failed to create qca-nss-drv/stats/gre_redir file in debugfs"); 2147 return; 2148 } 2149 2150 /* 2151 * SJACK stats 2152 */ 2153 nss_top_main.sjack_dentry = debugfs_create_file("sjack", 0400, 2154 nss_top_main.stats_dentry, &nss_top_main, &nss_stats_sjack_ops); 2155 if (unlikely(nss_top_main.sjack_dentry == NULL)) { 2156 nss_warning("Failed to create qca-nss-drv/stats/sjack file in debugfs"); 2157 return; 2158 } 2159 2160 /* 2161 * WIFI stats 2162 */ 2163 nss_top_main.wifi_dentry = debugfs_create_file("wifi", 0400, 2164 nss_top_main.stats_dentry, &nss_top_main, &nss_stats_wifi_ops); 2165 if (unlikely(nss_top_main.wifi_dentry == NULL)) { 2166 nss_warning("Failed to create qca-nss-drv/stats/wifi file in debugfs"); 2167 return; 2168 } 2169 2170 /* 2171 * wifi_if stats 2172 */ 2173 nss_top_main.wifi_if_dentry = debugfs_create_file("wifi_if", 0400, 2174 nss_top_main.stats_dentry, &nss_top_main, &nss_stats_wifi_if_ops); 2175 if (unlikely(nss_top_main.wifi_if_dentry == NULL)) { 2176 nss_warning("Failed to create qca-nss-drv/stats/wifi_if file in debugfs"); 2177 return; 2178 } 2179 2180 nss_top_main.virt_if_dentry = debugfs_create_file("virt_if", 0400, 2181 nss_top_main.stats_dentry, &nss_top_main, &nss_stats_virt_if_ops); 2182 if (unlikely(nss_top_main.virt_if_dentry == NULL)) { 2183 nss_warning("Failed to create qca-nss-drv/stats/virt_if file in debugfs"); 2184 return; 2185 } 2186 2187 nss_top_main.tx_rx_virt_if_dentry = debugfs_create_file("tx_rx_virt_if", 0400, 2188 nss_top_main.stats_dentry, &nss_top_main, &nss_stats_tx_rx_virt_if_ops); 2189 if (unlikely(nss_top_main.virt_if_dentry == NULL)) { 2190 nss_warning("Failed to create qca-nss-drv/stats/tx_rx_virt_if file in debugfs"); 2191 return; 2192 } 2193 2194 nss_log_init(); 2195} 2196 2197 2198/* 2199 * nss_stats_clean() 2200 * Cleanup NSS statistics files 2201 */ 2202void nss_stats_clean(void) 2203{ 2204 /* 2205 * Remove debugfs tree 2206 */ 2207 if (likely(nss_top_main.top_dentry != NULL)) { 2208 debugfs_remove_recursive(nss_top_main.top_dentry); 2209 nss_top_main.top_dentry = NULL; 2210 } 2211} 2212