counter.c (61968B)
1 /* 2 * 3 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 4 * 5 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 6 * 7 * Counter CLI support 8 */ 9 10 #include <appl/diag/system.h> 11 #include <appl/diag/dport.h> 12 #include <shared/bsl.h> 13 #include <bcm/stat.h> 14 #include <bcm/error.h> 15 #include <soc/mem.h> 16 17 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 18 #include <bcm_int/esw/trident2.h> 19 #endif 20 21 22 #define SOC_CNAME_MAX 20 23 24 /* 25 * Data structure for saving the previous value of counters so we can 26 * tell which counters that have changed since last shown. 27 */ 28 29 STATIC uint64 *counter_val[SOC_MAX_NUM_DEVICES]; 30 static int prev_counter_interval[SOC_MAX_NUM_DEVICES]; 31 32 STATIC void 33 counter_val_set(int unit, soc_port_t port, soc_reg_t ctr_reg, 34 int ar_idx, uint64 val) 35 { 36 static int n; 37 int ind = 0; 38 soc_counter_non_dma_t *non_dma; 39 40 if (counter_val[unit] == NULL) { 41 n = SOC_CONTROL(unit)->counter_n32 + SOC_CONTROL(unit)->counter_n64 + 42 SOC_CONTROL(unit)->counter_n64_non_dma; 43 counter_val[unit] = sal_alloc(n * sizeof (uint64), "save_ctrs"); 44 if (counter_val[unit] == NULL) { 45 return; 46 } 47 sal_memset(counter_val[unit], 0, n * sizeof (uint64)); 48 } 49 50 if (port != SOC_PORT_INVALID) { 51 if (ctr_reg >= SOC_COUNTER_NON_DMA_START && 52 ctr_reg < SOC_COUNTER_NON_DMA_END) { 53 if (ar_idx < 0) { 54 if (SOC_CONTROL(unit)->counter_non_dma == NULL) { 55 return; 56 } 57 non_dma = &SOC_CONTROL(unit)-> 58 counter_non_dma[ctr_reg - SOC_COUNTER_NON_DMA_START]; 59 for (ar_idx = 0; ar_idx < non_dma->entries_per_port; ar_idx++) { 60 counter_val_set(unit, port, ctr_reg, ar_idx, val); 61 } 62 return; 63 } 64 } 65 ind = soc_counter_idx_get(unit, ctr_reg, ar_idx, port); 66 } 67 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 68 /*when port is invalid, rely on ar_idx to get ind*/ 69 else if (SOC_IS_TRIDENT2PLUS(unit) && 70 (ctr_reg >= SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_UC && 71 ctr_reg <= SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_UC)) { 72 ind = soc_counter_idx_get(unit, ctr_reg, -1, SOC_PORT_MIN(unit, all)); 73 ind += ar_idx; 74 } 75 #endif 76 if (ctr_reg >= SOC_COUNTER_TABLE_FIELD_END) { 77 LOG_INFO(BSL_LS_APPL_COUNTER, 78 (BSL_META_U(unit, 79 "cval_set: Illegal counter index -- " 80 "ar_idx=%d p=%d idx=%d vh=%d vl=%d\n"), 81 ar_idx, port, ind, 82 COMPILER_64_HI(val), 83 COMPILER_64_LO(val))); 84 } else if (SOC_REG_IS_COUNTER_TABLE(unit, ctr_reg)) { 85 LOG_INFO(BSL_LS_APPL_COUNTER, 86 (BSL_META_U(unit, 87 "cval_set: %s ar_idx=%d p=%d idx=%d vh=%d vl=%d\n"), 88 SOC_FIELD_NAME(unit, ctr_reg - SOC_COUNTER_TABLE_FIELD_START), 89 ar_idx, port, ind, 90 COMPILER_64_HI(val), 91 COMPILER_64_LO(val))); 92 } else if (ctr_reg >= SOC_COUNTER_NON_DMA_START && 93 ctr_reg < SOC_COUNTER_NON_DMA_END) { 94 non_dma = 95 &SOC_CONTROL(unit)->counter_non_dma[ctr_reg - 96 SOC_COUNTER_NON_DMA_START]; 97 LOG_INFO(BSL_LS_APPL_COUNTER, 98 (BSL_META_U(unit, 99 "cval_set: %s ar_idx=%d p=%d idx=%d vh=%d vl=%d\n"), 100 non_dma->cname, 101 ar_idx, port, ind, 102 COMPILER_64_HI(val), 103 COMPILER_64_LO(val))); 104 } else if (ctr_reg >= NUM_SOC_REG) { 105 return; 106 } else { 107 LOG_INFO(BSL_LS_APPL_COUNTER, 108 (BSL_META_U(unit, 109 "cval_set: %s ar_idx=%d p=%d idx=%d vh=%d vl=%d\n"), 110 SOC_REG_NAME(unit, ctr_reg), 111 ar_idx, port, ind, 112 COMPILER_64_HI(val), 113 COMPILER_64_LO(val))); 114 } 115 116 /* Unsupported non-DMA counters will return out-of-range index (-1) */ 117 if (ind >= 0 && ind < n) { 118 counter_val[unit][ind] = val; 119 } 120 } 121 122 void 123 counter_val_set_by_port(int unit, soc_pbmp_t pbmp, uint64 val) 124 { 125 int i; 126 soc_port_t port, dport; 127 soc_reg_t ctr_reg; 128 soc_cmap_t *cmap; 129 130 /* coverity[overrun-local] */ 131 DPORT_SOC_PBMP_ITER(unit, pbmp, dport, port) { 132 /* Non-DMA counters */ 133 for (i = SOC_COUNTER_NON_DMA_START; i < SOC_COUNTER_NON_DMA_END; i++) { 134 /* coverity[overrun-call] */ 135 counter_val_set(unit, port, i, -1, val); 136 } 137 /* DMA counters */ 138 cmap = soc_port_cmap_get(unit, port); 139 if (cmap == NULL) { 140 continue; 141 } 142 for (i = 0; i < cmap->cmap_size; i++) { 143 ctr_reg = cmap->cmap_base[i].reg; 144 if (ctr_reg != INVALIDr) { 145 counter_val_set(unit, port, ctr_reg, -1, val); 146 } 147 } 148 } 149 } 150 151 STATIC void 152 counter_val_get(int unit, soc_port_t port, soc_reg_t ctr_reg, 153 int ar_idx, uint64 *val) 154 { 155 int ind = 0; 156 soc_counter_non_dma_t *non_dma; 157 158 if (counter_val[unit] == NULL) { 159 COMPILER_64_SET(*val, 0, 0); 160 } else { 161 if (port != SOC_PORT_INVALID) { 162 ind = soc_counter_idx_get(unit, ctr_reg, ar_idx, port); 163 } 164 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 165 /*when port is invalid, rely on ar_idx to get ind*/ 166 else if (SOC_IS_TRIDENT2PLUS(unit) && 167 (ctr_reg >= SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_UC && 168 ctr_reg <= SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_UC)) { 169 ind = soc_counter_idx_get(unit, ctr_reg, -1, SOC_PORT_MIN(unit, all)); 170 ind += ar_idx; 171 } 172 #endif 173 #if defined(BCM_TOMAHAWK3_SUPPORT) 174 /*when port is invalid, rely on ar_idx to get ind*/ 175 else if (SOC_IS_TOMAHAWK3(unit) && 176 (ctr_reg >= SOC_COUNTER_NON_DMA_PRIQ_DROP_PKT && 177 ctr_reg <= SOC_COUNTER_NON_DMA_HDRM_POOL_DROP_PKT)) { 178 ind = soc_counter_idx_get(unit, ctr_reg, -1, SOC_PORT_MIN(unit, all)); 179 ind += ar_idx; 180 } 181 #endif 182 183 *val = counter_val[unit][ind]; 184 185 if (ctr_reg >= SOC_COUNTER_NON_DMA_END) { 186 LOG_INFO(BSL_LS_APPL_COUNTER, 187 (BSL_META_U(unit, 188 "cval_get: Illegal counter index -- " 189 "ar_idx=%d p=%d idx=%d vh=%d vl=%d\n"), 190 ar_idx, port, ind, 191 COMPILER_64_HI(*val), 192 COMPILER_64_LO(*val))); 193 194 } else if (ctr_reg >= SOC_COUNTER_NON_DMA_START && 195 ctr_reg < SOC_COUNTER_NON_DMA_END) { 196 non_dma = 197 &SOC_CONTROL(unit)->counter_non_dma[ctr_reg - 198 SOC_COUNTER_NON_DMA_START]; 199 LOG_INFO(BSL_LS_APPL_COUNTER, 200 (BSL_META_U(unit, 201 "cval_get: %s ar_idx=%d p=%d idx=%d vh=%d vl=%d\n"), 202 non_dma->cname, 203 ar_idx, port, ind, 204 COMPILER_64_HI(*val), 205 COMPILER_64_LO(*val))); 206 } else { 207 LOG_INFO(BSL_LS_APPL_COUNTER, 208 (BSL_META_U(unit, 209 "cval_get: %s ar_idx=%d p=%d idx=%d vh=%d vl=%d\n"), 210 SOC_REG_NAME(unit, ctr_reg), 211 ar_idx, port, ind, 212 COMPILER_64_HI(*val), 213 COMPILER_64_LO(*val))); 214 } 215 } 216 } 217 218 /* 219 * Function: 220 * do_resync_counters 221 * Purpose: 222 * Resynchronize the previous counter values (stored in counter_val) 223 * with the actual counters. 224 */ 225 226 int 227 do_resync_counters(int unit, soc_pbmp_t pbmp) 228 { 229 soc_port_t port, dport; 230 int i; 231 soc_cmap_t *cmap; 232 soc_reg_t reg; 233 uint64 val; 234 int ar_idx; 235 236 /* coverity[overrun-local] */ 237 DPORT_SOC_PBMP_ITER(unit, pbmp, dport, port) { 238 /* Non-DMA counters */ 239 for (i = SOC_COUNTER_NON_DMA_START; i < SOC_COUNTER_NON_DMA_END; i++) { 240 /* coverity[overrun-call] */ 241 if (soc_counter_get(unit, port, i, -1, &val) == SOC_E_NONE ) 242 counter_val_set(unit, port, i, -1, val); 243 } 244 /* DMA counters */ 245 cmap = soc_port_cmap_get(unit, port); 246 for (i = 0; i < cmap->cmap_size; i++) { 247 reg = cmap->cmap_base[i].reg; 248 if (reg != INVALIDr) { 249 if (!SOC_REG_IS_COUNTER_TABLE(unit, reg) && 250 (SOC_REG_INFO(unit, reg).flags & SOC_REG_FLAG_ARRAY)) { 251 for (ar_idx = 0; 252 ar_idx < SOC_REG_INFO(unit, reg).numels; 253 ar_idx++) { 254 if (soc_counter_get(unit, port, reg, ar_idx, &val) == SOC_E_NONE ) 255 counter_val_set(unit, port, reg, ar_idx, val); 256 } 257 } else { 258 if (soc_counter_get(unit, port, reg, 0, &val) == SOC_E_NONE ) 259 counter_val_set(unit, port, reg, 0, val); 260 } 261 } 262 } 263 } 264 265 return 0; 266 } 267 268 /* 269 * do_show_counters 270 * 271 * Displays counters for specified register(s) and port(s). 272 * 273 * SHOW_CTR_HEX displays values in hex instead of decimal. 274 * 275 * SHOW_CTR_RAW displays only the counter value, not the register 276 * name or delta. 277 * 278 * SHOW_CTR_CHANGED: includes counters that have changed since the 279 * last call to do_show_counters(). 280 * 281 * SHOW_CTR_NOT_CHANGED: includes counters that have not changed since 282 * the last call to do_show_counters(). 283 * 284 * NOTE: to get any output, you need at least one of the above two flags. 285 * 286 * SHOW_CTR_ZERO: includes counters that are zero. 287 * 288 * SHOW_CTR_NOT_ZERO: includes counters that are not zero. 289 * 290 * NOTE: to get any output, you need at least one of the above two flags. 291 * 292 * SHOW_CTR_ED: 293 * Show only those registers marked as Error/Discard. 294 * 295 * Columns will remain lined up properly until the following maximum 296 * limits are exceeded: 297 * 298 * Current count: 99,999,999,999,999,999 299 * Increment: +99,999,999,999,999 300 * Rate: 999,999,999,999/s 301 */ 302 303 void 304 do_show_counter(int unit, soc_port_t port, soc_reg_t ctr_reg, 305 int ar_idx, int flags) 306 { 307 soc_counter_non_dma_t *non_dma; 308 uint64 val, prev_val, diff, rate; 309 int num_entries; 310 int changed; 311 int is_ed_cntr, is_mmu_status; 312 int tabwidth = soc_property_get(unit, spn_DIAG_TABS, 8); 313 int commachr = soc_property_get(unit, spn_DIAG_COMMA, ','); 314 int bit_position = 0; 315 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 316 char flex_que_name[10]; 317 int queue_mode; 318 /*This flag SHOW_CTR_ALL_QUEUE is used in TD2+ to show flex assigned queues 319 (endpoint queue and service queue) */ 320 soc_port_t port_backup = port; 321 if (flags & SHOW_CTR_ALL_QUEUE) { 322 /*make port an invalid port to rely on ar_idx to get counter index*/ 323 port = SOC_PORT_INVALID; 324 } 325 #endif 326 327 is_ed_cntr = FALSE; 328 is_mmu_status = FALSE; 329 if(ctr_reg >= SOC_COUNTER_TABLE_FIELD_START) { 330 ; 331 } else if (ctr_reg >= SOC_COUNTER_NON_DMA_START && 332 ctr_reg < SOC_COUNTER_NON_DMA_END) { 333 if (SOC_CONTROL(unit)->counter_non_dma == NULL) { 334 return; 335 } 336 non_dma = &SOC_CONTROL(unit)-> 337 counter_non_dma[ctr_reg - SOC_COUNTER_NON_DMA_START]; 338 if (non_dma->flags & 339 (_SOC_COUNTER_NON_DMA_PEAK | _SOC_COUNTER_NON_DMA_CURRENT)) { 340 is_mmu_status = TRUE; 341 } 342 if (ar_idx < 0) { 343 num_entries = 344 port < 0 ? non_dma->num_entries : non_dma->entries_per_port; 345 for (ar_idx = 0; ar_idx < num_entries; ar_idx++) { 346 do_show_counter(unit, port, ctr_reg, ar_idx, flags); 347 } 348 return; 349 } 350 } else { 351 is_ed_cntr = SOC_REG_INFO(unit, ctr_reg).flags & SOC_REG_FLAG_ED_CNTR; 352 353 if (!(SOC_REG_INFO(unit, ctr_reg).flags & SOC_REG_FLAG_ARRAY)) { 354 ar_idx = 0; 355 } else { 356 if (ar_idx < 0) { /* Set all elts of array */ 357 for (ar_idx = 0; ar_idx < SOC_REG_INFO(unit, ctr_reg).numels; 358 ar_idx++) { 359 do_show_counter(unit, port, ctr_reg, ar_idx, flags); 360 } 361 return; 362 } 363 } 364 } 365 366 /*if port is an invalid port, will rely on ar_idx to get counter index*/ 367 if (soc_counter_get(unit, port, ctr_reg, ar_idx, &val) < 0) { 368 return; 369 } 370 counter_val_get(unit, port, ctr_reg, ar_idx, &prev_val); 371 /* Need to clear prev_val which stored in counter_val(SW) if current counter val < prev_val. 372 * It only happen when soc counter is clear(ex: init all) but here counter_val not clear */ 373 if (COMPILER_64_LT(val, prev_val)) { 374 COMPILER_64_ZERO(prev_val); 375 counter_val_set(unit, port, ctr_reg, ar_idx, prev_val); 376 } 377 378 diff = val; 379 COMPILER_64_SUB_64(diff, prev_val); 380 381 if (COMPILER_64_IS_ZERO(diff)) { 382 changed = 0; 383 } else { 384 counter_val_set(unit, port, ctr_reg, ar_idx, val); 385 changed = 1; 386 } 387 388 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 389 /*recover port info*/ 390 if (flags & SHOW_CTR_ALL_QUEUE) { 391 port = port_backup; 392 } 393 #endif 394 soc_counter_get_rate(unit, port, ctr_reg, ar_idx, &rate); 395 396 if ((( changed && (flags & SHOW_CTR_CHANGED)) || 397 (!changed && (flags & SHOW_CTR_SAME))) && 398 (( COMPILER_64_IS_ZERO(val) && (flags & SHOW_CTR_Z)) || 399 (!COMPILER_64_IS_ZERO(val) && (flags & SHOW_CTR_NZ))) && 400 ((!(flags & SHOW_CTR_ED) || 401 ((flags & SHOW_CTR_ED) && is_ed_cntr))) && 402 ((!(flags & SHOW_CTR_MS) && !is_mmu_status)|| 403 (((flags & SHOW_CTR_MS) && is_mmu_status))) 404 ) { 405 /* size of line must be equal or more then sum of cname, buf_val, 406 buf_diff and buf_rate. */ 407 /* The size of tabby must be greater than size of line */ 408 409 char tabby[130], line[120]; 410 char cname[32]; 411 char buf_val[32], buf_diff[32], buf_rate[32]; 412 413 if (ctr_reg >= SOC_COUNTER_NON_DMA_START && 414 ctr_reg < SOC_COUNTER_NON_DMA_END) { 415 /* Non-DMA Counters */ 416 non_dma = &SOC_CONTROL(unit)->counter_non_dma[ctr_reg - 417 SOC_COUNTER_NON_DMA_START]; 418 if(!(SOC_PBMP_MEMBER(non_dma->pbmp, port))) { 419 /* Not a dma port member; don't show counters */ 420 return; 421 } 422 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 423 if (flags & SHOW_CTR_ALL_QUEUE) { 424 /* coverity[check_return : FALSE] */ 425 bcm_esw_port_control_get(unit, port, 426 bcmPortControlCustomerQueuing, &queue_mode); 427 if (queue_mode == 4) { 428 sal_strcpy(flex_que_name, "EP_"); 429 sal_memcpy(cname, flex_que_name, 3); 430 bit_position = 3; 431 } else if (queue_mode == 3) { 432 sal_strcpy(flex_que_name, "SV_"); 433 sal_memcpy(cname, flex_que_name, 3); 434 bit_position = 3; 435 } else { 436 return; 437 } 438 } 439 #endif 440 if(sal_strlen(non_dma->cname) > SOC_CNAME_MAX) { 441 /* Truncate Name to fit in line */ 442 sal_memcpy(cname, non_dma->cname, SOC_CNAME_MAX); 443 if (non_dma->entries_per_port > 1) { 444 sal_sprintf(&cname[SOC_CNAME_MAX], "(%d).%s", 445 ar_idx, 446 SOC_PORT_NAME(unit, port)); 447 } else if (non_dma->entries_per_port == 1) { 448 sal_sprintf(&cname[SOC_CNAME_MAX], ".%s", 449 SOC_PORT_NAME(unit, port)); 450 } else { 451 sal_sprintf(&cname[SOC_CNAME_MAX], "(%d)", 452 ar_idx); 453 } 454 } else { 455 if (non_dma->entries_per_port > 1) { 456 sal_sprintf(&cname[bit_position], "%s(%d).%s", non_dma->cname, ar_idx, 457 SOC_PORT_NAME(unit, port)); 458 } else if (non_dma->entries_per_port == 1) { 459 sal_sprintf(&cname[bit_position], "%s.%s", non_dma->cname, 460 SOC_PORT_NAME(unit, port)); 461 } else { 462 sal_sprintf(&cname[bit_position], "%s(%d)", non_dma->cname, ar_idx); 463 } 464 } 465 } else { 466 /* Counter Tables */ 467 if(ctr_reg >= SOC_COUNTER_TABLE_FIELD_START) { 468 sal_sprintf(cname, "%s.%s", 469 SOC_FIELD_NAME(unit, (ctr_reg - SOC_COUNTER_TABLE_FIELD_START)), 470 SOC_PORT_NAME(unit, port)); 471 472 /* DMA Counters */ 473 } else if (sal_strlen(SOC_REG_NAME(unit, ctr_reg)) > SOC_CNAME_MAX) { 474 #if !defined(SOC_NO_ALIAS) 475 if (SOC_REG_ALIAS(unit, ctr_reg) 476 && *SOC_REG_ALIAS(unit, ctr_reg) 477 && sal_strlen(SOC_REG_ALIAS(unit, ctr_reg)) <= SOC_CNAME_MAX) { 478 if (SOC_REG_INFO(unit, ctr_reg).flags & SOC_REG_FLAG_ARRAY) { 479 sal_sprintf(cname, "%s(%d).%s", 480 SOC_REG_ALIAS(unit, ctr_reg), 481 ar_idx, 482 SOC_PORT_NAME(unit, port)); 483 } else { 484 sal_sprintf(cname, "%s.%s", 485 SOC_REG_ALIAS(unit, ctr_reg), 486 SOC_PORT_NAME(unit, port)); 487 } 488 } else 489 #endif /* !defined(SOC_NO_ALIAS) */ 490 { 491 sal_memcpy(cname, SOC_REG_NAME(unit, ctr_reg), SOC_CNAME_MAX); 492 /* Truncate Name to fit in line */ 493 if (SOC_REG_INFO(unit, ctr_reg).flags & SOC_REG_FLAG_ARRAY) { 494 sal_sprintf(&cname[SOC_CNAME_MAX], "(%d).%s", 495 ar_idx, 496 SOC_PORT_NAME(unit, port)); 497 } else { 498 sal_sprintf(&cname[SOC_CNAME_MAX], ".%s", 499 SOC_PORT_NAME(unit, port)); 500 } 501 } 502 } else { 503 if (SOC_REG_INFO(unit, ctr_reg).flags & SOC_REG_FLAG_ARRAY) { 504 sal_sprintf(cname, "%s(%d).%s", 505 SOC_REG_NAME(unit, ctr_reg), 506 ar_idx, 507 SOC_PORT_NAME(unit, port)); 508 } else { 509 sal_sprintf(cname, "%s.%s", 510 SOC_REG_NAME(unit, ctr_reg), 511 SOC_PORT_NAME(unit, port)); 512 } 513 } 514 } 515 516 if (flags & SHOW_CTR_RAW) { 517 if (flags & SHOW_CTR_HEX) { 518 sal_sprintf(line, "0x%08x%08x", 519 COMPILER_64_HI(val), COMPILER_64_LO(val)); 520 } else { 521 format_uint64_decimal(buf_val, val, 0); 522 sal_sprintf(line, "%s", buf_val); 523 } 524 } else { 525 if (flags & SHOW_CTR_HEX) { 526 if (is_mmu_status) { 527 sal_sprintf(line, "%-22s: 0x%08x%08x", 528 cname, 529 COMPILER_64_HI(val), COMPILER_64_LO(val)); 530 } else { 531 sal_sprintf(line, "%-22s: 0x%08x%08x +0x%08x%08x 0x%08x%08x/s", 532 cname, 533 COMPILER_64_HI(val), COMPILER_64_LO(val), 534 COMPILER_64_HI(diff), COMPILER_64_LO(diff), 535 COMPILER_64_HI(rate), COMPILER_64_LO(rate)); 536 } 537 } else { 538 if (is_mmu_status) { 539 format_uint64_decimal(buf_val, val, commachr); 540 sal_sprintf(line, "%-28s:%22s", cname, buf_val); 541 } else { 542 format_uint64_decimal(buf_val, val, commachr); 543 buf_diff[0] = '+'; 544 format_uint64_decimal(buf_diff + 1, diff, commachr); 545 sal_sprintf(line, "%-28s:%22s%20s", 546 cname, buf_val, buf_diff); 547 if (!COMPILER_64_IS_ZERO(rate)) { 548 format_uint64_decimal(buf_rate, rate, commachr); 549 sal_sprintf(line + sal_strlen(line), "%16s/s", buf_rate); 550 } 551 } 552 } 553 } 554 555 /* 556 * Display is tremendously faster with tabify. 557 * Set diag_tab property to desired value, or 0 to turn it off. 558 */ 559 560 tabify_line(tabby, line, tabwidth); 561 562 cli_out("%s\n", tabby); 563 } 564 } 565 566 int 567 do_show_counters(int unit, soc_reg_t ctr_reg, soc_pbmp_t pbmp, int flags) 568 { 569 soc_control_t *soc = SOC_CONTROL(unit); 570 soc_counter_non_dma_t *non_dma; 571 soc_port_t port, dport; 572 int i; 573 soc_cmap_t *cmap; 574 soc_reg_t reg; 575 int numregs; 576 char pfmt[SOC_PBMP_FMT_LEN]; 577 578 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 579 int j, array_count = 0; 580 int *ar_idx_array = NULL; 581 soc_port_t *port_array = NULL; 582 #endif 583 584 /* coverity[overrun-local] */ 585 DPORT_SOC_PBMP_ITER(unit, pbmp, dport, port) { 586 /* coverity[overrun-call] */ 587 cmap = soc_port_cmap_get(unit, port); 588 if (!cmap) { 589 cli_out("NOTE: Unit %d: No counter map found for port %d\n", unit, port); 590 continue; 591 } 592 numregs = cmap->cmap_size; 593 594 if (ctr_reg != INVALIDr) { 595 /* coverity[negative_returns] : FALSE */ 596 do_show_counter(unit, port, ctr_reg, -1, flags); 597 } else { 598 for (i = 0; i < numregs; i++) { 599 reg = cmap->cmap_base[i].reg; 600 if (reg != INVALIDr) { 601 do_show_counter(unit, port, reg, 602 cmap->cmap_base[i].index, flags); 603 } 604 } 605 for (i = SOC_COUNTER_NON_DMA_START; i < SOC_COUNTER_NON_DMA_END; 606 i++) { 607 non_dma = &SOC_CONTROL(unit)-> 608 counter_non_dma[i - SOC_COUNTER_NON_DMA_START]; 609 if (non_dma->entries_per_port == 0) { 610 continue; 611 } 612 /* coverity[negative_returns] : FALSE */ 613 do_show_counter(unit, port, i, -1, flags); 614 } 615 } 616 } 617 if (ctr_reg == INVALIDr) { 618 for (i = SOC_COUNTER_NON_DMA_START; i < SOC_COUNTER_NON_DMA_END; i++) { 619 non_dma = &SOC_CONTROL(unit)-> 620 counter_non_dma[i - SOC_COUNTER_NON_DMA_START]; 621 if (non_dma->entries_per_port != 0) { 622 continue; 623 } 624 if (non_dma->flags & _SOC_COUNTER_NON_DMA_NO_SHOW_C) { 625 /* Counter not present for diag show c output */ 626 continue; 627 } 628 /* coverity[negative_returns] : FALSE */ 629 do_show_counter(unit, -1, i, -1, flags); 630 } 631 } 632 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 633 if (SOC_IS_TRIDENT2PLUS(unit)) { 634 flags |= SHOW_CTR_ALL_QUEUE; 635 ar_idx_array = sal_alloc(sizeof(int) * 2960, 636 "cosq hw index when show counter"); 637 if (NULL == ar_idx_array) { 638 return BCM_E_MEMORY; 639 } 640 port_array = sal_alloc(sizeof(soc_port_t) * 2960, 641 "port array of mmu queues when show counter"); 642 if (NULL == port_array) { 643 sal_free(ar_idx_array); 644 return BCM_E_MEMORY; 645 } 646 _bcm_td2_cosq_hw_idx_get(unit, 2960, port_array, ar_idx_array,&array_count); 647 for (i = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_UC; 648 i <= SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_UC; i++) { 649 for (j = 0; j < array_count; j++){ 650 do_show_counter(unit, port_array[j], i, ar_idx_array[j], flags); 651 } 652 } 653 sal_free(ar_idx_array); 654 sal_free(port_array); 655 } 656 #endif 657 658 SOC_PBMP_REMOVE(pbmp, soc->counter_pbmp); 659 if (soc->counter_interval == 0) { 660 cli_out("NOTE: counter collection is not running\n"); 661 } else if (SOC_PBMP_NOT_NULL(pbmp)) { 662 cli_out("NOTE: counter collection is not active for ports %s\n", 663 SOC_PBMP_FMT(pbmp, pfmt)); 664 } 665 666 return 0; 667 } 668 669 /* 670 * Counter collection configuration 671 */ 672 673 cmd_result_t 674 cmd_esw_counter(int unit, args_t *a) 675 { 676 soc_control_t *soc = SOC_CONTROL(unit); 677 soc_pbmp_t pbmp; 678 int usec, dma, r; 679 parse_table_t pt; 680 uint32 flags; 681 int sync = 0; 682 683 if (!sh_check_attached(ARG_CMD(a), unit)) { 684 return CMD_FAIL; 685 } 686 687 688 flags = soc->counter_flags; 689 usec = soc->counter_interval; 690 SOC_PBMP_ASSIGN(pbmp, soc->counter_pbmp); 691 dma = (flags & SOC_COUNTER_F_DMA) != 0; 692 693 parse_table_init(unit, &pt); 694 parse_table_add(&pt, "Interval", PQ_DFL|PQ_INT, 695 (void *)( 0), &usec, NULL); 696 parse_table_add(&pt, "PortBitMap", PQ_DFL|PQ_PBMP, 697 (void *)(0), &pbmp, NULL); 698 parse_table_add(&pt, "DMA", PQ_DFL|PQ_BOOL, 699 INT_TO_PTR(dma), &dma, NULL); 700 701 if (!ARG_CNT(a)) { /* Display settings */ 702 cli_out("Current settings:\n"); 703 parse_eq_format(&pt); 704 parse_arg_eq_done(&pt); 705 return(CMD_OK); 706 } 707 708 if (parse_arg_eq(a, &pt) < 0) { 709 cli_out("%s: Error: Unknown option: %s\n", ARG_CMD(a), ARG_CUR(a)); 710 parse_arg_eq_done(&pt); 711 return(CMD_FAIL); 712 } 713 parse_arg_eq_done(&pt); 714 715 if (ARG_CNT(a) > 0 && !sal_strcasecmp(_ARG_CUR(a), "on")) { 716 usec = prev_counter_interval[unit]; 717 ARG_NEXT(a); 718 } 719 720 if (ARG_CNT(a) > 0 && !sal_strcasecmp(_ARG_CUR(a), "off")) { 721 ARG_NEXT(a); 722 usec = 0; 723 } 724 725 if (ARG_CNT(a) > 0 && !sal_strcasecmp(_ARG_CUR(a), "sync")) { 726 ARG_NEXT(a); 727 sync = 1; 728 } 729 730 if (sync) { 731 /* Sync driver info to HW */ 732 if ((r = soc_counter_sync(unit)) < 0) { 733 cli_out("%s: Error: Could not sync counters: %s\n", 734 ARG_CMD(a), soc_errmsg(r)); 735 return CMD_FAIL; 736 } 737 /* Sync diag info with driver */ 738 do_resync_counters(unit, pbmp); 739 return CMD_OK; 740 } 741 742 if (soc_feature(unit, soc_feature_cpuport_stat_dma)) { 743 soc_pbmp_t temp_pbmp; 744 SOC_PBMP_CLEAR(temp_pbmp); 745 SOC_PBMP_OR(temp_pbmp, PBMP_PORT_ALL(unit)); 746 SOC_PBMP_OR(temp_pbmp, PBMP_CMIC(unit)); 747 SOC_PBMP_AND(pbmp, temp_pbmp); 748 } else { 749 SOC_PBMP_AND(pbmp, PBMP_PORT_ALL(unit)); 750 } 751 752 if (dma) { 753 flags |= SOC_COUNTER_F_DMA; 754 } else { 755 flags &= ~SOC_COUNTER_F_DMA; 756 } 757 758 if (usec > 0) { 759 r = soc_counter_start(unit, flags, usec, pbmp); 760 } else { 761 uint32 flags; 762 pbmp_t pbmp; 763 int prev_interval; 764 765 r = soc_counter_status(unit, &flags, 766 &prev_interval, &pbmp); 767 if (r < 0 || prev_interval <= 0) { 768 prev_interval = SOC_COUNTER_INTERVAL_DEFAULT; 769 } 770 prev_counter_interval[unit] = prev_interval; 771 r = soc_counter_stop(unit); 772 } 773 774 if (r < 0) { 775 cli_out("%s: Error: Could not set counter mode: %s\n", 776 ARG_CMD(a), soc_errmsg(r)); 777 return CMD_FAIL; 778 } 779 780 return CMD_OK; 781 } 782 783 /* 784 * routines for custom stats 785 */ 786 787 788 #define COL_SZ 0x05 789 790 #define RDBGC 0x01 791 #define TDBGC 0x02 792 #define BOTH 0x03 793 794 #define SET_FLAGS 0x01 795 #define LIST_FLAGS 0x02 796 #define SHOW_FLAGS 0x03 797 #define SHOW_COUNTERS 0x04 798 #define SHOW_TABLE 0x05 799 800 #define ERROR_SET_FLAGS(_err) \ 801 if (cmd_type == SET_FLAGS) { \ 802 cli_out("Error: " _err); \ 803 return CMD_FAIL; \ 804 } 805 806 char *head = 807 "\n+------------------Programmable Statistics Counters[Port %4s]-------\ 808 -----------+"; 809 char *menu = 810 "\n| Type | No. | Value | Enabled For \ 811 |"; 812 char *line = 813 "\n+-------------------------------------------------------------------\ 814 ------------+"; 815 char *trg_s = "\n| | | | "; 816 817 char *stat_names[] = BCM_STAT_NAME_INITIALIZER; 818 typedef struct trig_name_s { 819 char *name; 820 char *about; 821 } trig_name_t; 822 823 trig_name_t _trig_names[] = { 824 {"RIPD4", " Rx IPv4 L3 discard packets"}, 825 {"RIPC4", " Good rx L3 (V4 packets) includes tunneled"}, 826 {"RIPHE4", " Rx IPv4 header error packets"}, 827 {"IMRP4", " Routed IPv4 multicast packets"}, 828 {"RIPD6", " Rx IPv6 L3 discard packet"}, 829 {"RIPC6", " Good rx L3 (V6 packets) includes tunneled"}, 830 {"RIPHE6", " Rx IPv6 header error packets"}, 831 {"IMRP6", " Routed IPv6 multicast packets"}, 832 {"RDISC", " IBP discard and CBP full"}, 833 {"RUC", " Good rx unicast (L2+L3) packets"}, 834 {"RPORTD", 835 " Packets droppped when ingress port is not in forwarding state"}, 836 {"PDISC", 837 " Rx policy discard - DST_DISCARD, SRC_DISCARD, RATE_CONTROL"}, 838 {"IMBP", " Bridged multicast packets"}, 839 {"RFILDR", " Packets dropped by FP"}, 840 {"RIMDR", " Multicast (L2+L3) packets that are dropped"}, 841 {"RDROP", " Port bitmap zero drop condition"}, 842 {"IRPSE", " HiGig IPIC pause rx"}, 843 {"IRHOL", " HiGig End-to-End HOL rx packets"}, 844 {"IRIBP", " HiGig End-to-End IBP rx packets"}, 845 {"DSL3HE", " DOS L3 header error packets"}, 846 {"IUNKHDR", " Unknown HiGig header type packet"}, 847 {"DSL4HE", " DOS L4 header error packets"}, 848 {"IMIRROR", " HiGig mirror packet"}, 849 {"DSICMP", " DOS ICMP error packets"}, 850 {"DSFRAG", " DOS fragment error packets"}, 851 {"MTUERR", 852 " Packets trapped to CPU due to egress L3 MTU violation"}, 853 {"RTUN", " Number of tunnel packets received"}, 854 {"RTUNE", " Rx tunnel error packets"}, 855 {"VLANDR", " Rx VLAN drops"}, 856 {"RHGUC", " Rx HiGig lookup UC cases"}, 857 {"RHGMC", " Rx HiGig lookup MC cases"}, 858 {"MPLS", " Received MPLS Packets"}, 859 {"MACLMT", " packets dropped due to MAC Limit is hit"}, 860 {"MPLSERR", " Received MPLS Packets with Error"}, 861 {"URPFERR", " L3 src URPF check Fail"}, 862 {"HGHDRE", " Higig Header error packets"}, 863 {"MCIDXE", " Multicast Index error packets"}, 864 {"LAGLUP", " LAG failover loopback packets"}, 865 {"LAGLUPD", " LAG backup port down"}, 866 {"PARITYD", " Parity error packets"}, 867 {"VFPDR", " VLAN FP drop case"}, 868 {"URPF", " Unicast RPF drop case"}, 869 {"DSTDISCARDROP", " L2/L3 lookup DST_DISCARD drop"}, 870 {"CLASSBASEDMOVEDROP", " Class based station movement drop"}, 871 {"MACLMT_NODROP", " Mac limit exceeded and packet not dropped"}, 872 {"MACSAEQUALMACDA", " Dos Attack L2 Packets"}, 873 {"MACLMT_DROP", " Mac limit exceeded and packet dropped"}, 874 {"TGIP4", " Tx Good IPv4 L3 UC packets"}, 875 {"TIPD4", " Tx IPv4 L3 UC Aged and Drop packets"}, 876 {"TGIPMC4", " Tx Good IPv4 IPMC packets"}, 877 {"TIPMCD4", " Tx IPv4 IPMC Aged and Drop packets"}, 878 {"TGIP6", " Tx Good IPv6 L3 UC packets"}, 879 {"TIPD6", " Tx IPv6 L3 UC Aged and Drop Packets"}, 880 {"TGIPMC6", " Tx Good IPv6 IPMC packets"}, 881 {"TIPMCD6", " Tx IPv6 IPMC Aged and Drop packets"}, 882 {"TTNL", " Tx Tunnel packets"}, 883 {"TTNLE", " Tx Tunnel error packets"}, 884 {"TTTLD", " Pkts dropped due to TTL threshold counter"}, 885 {"TCFID", 886 " Pkts dropped when CFI set & pkt is untagged or L3 \ 887 switched for IPMC"}, 888 {"TVLAN", " Tx VLAN tagged packets"}, 889 {"TVLAND", " Pkts dropped due to invalid VLAN counter"}, 890 {"TVXLTMD", " Pkts dropped due to miss in VXLT table counter"}, 891 {"TSTGD", 892 " Pkts dropped due to Spanning Tree State not in forwarding \ 893 state"}, 894 {"TAGED", " Pkts dropped due to packet aged counter"}, 895 {"TL2MCD", " L2 MC packet drop counter"}, 896 {"TPKTD", " Pkts dropped due to any condition"}, 897 {"TMIRR", " mirroring flag"}, 898 {"TSIPL", " SIP Link Local Drop flag"}, 899 {"THGUC", " Higig Lookedup L3UC Pkts"}, 900 {"THGMC", " Higig Lookedup L3MC Pkts"}, 901 {"THIGIG2", " Unknown HiGig2 Drop"}, 902 {"THGI", " Unknown HiGig drop"}, 903 {"TL2_MTU", " L2 MTU fail drop"}, 904 {"TPARITY_ERR", " Parity Error drop"}, 905 {"TIP_LEN_FAIL", " IP Length check fail drop"}, 906 {"TMTUD", " EBAD_MTU_DROP"}, 907 {"TSLLD", " ESIP_LINK_LOCAL"}, 908 {"TL2MPLS", " L2_MPLS_ENCAP_TX"}, 909 {"TL3MPLS", " L3_MPLS_ENCAP_TX"}, 910 {"TMPLS", " MPLS_TX"}, 911 {"MODIDTOOLARGEDROP"," MODID greater than 31 drop counter"}, 912 {"PKTMODTOOLARGEDROP"," Byte additions too large drop counter"}, 913 {"RX_SYMBOL", " Fabric I/F => Rx Errors (e.g.8B10B)"}, 914 {"TIME_ALIGNMENT_EVEN", " Fabric I/F => Time Alignment (even)"}, 915 {"TIME_ALIGNMENT_ODD", " Fabric I/F => Time Alignment (odd)"}, 916 {"BIT_INTERLEAVED_PARITY_EVEN", " Fabric I/F => BIP (even)"}, 917 {"BIT_INTERLEAVED_PARITY_ODD", " Fabric I/F => BIP (odd)"}, 918 {"FcmPortClass3RxFrames", " FCOE L3 RX frames"}, 919 {"FcmPortClass3RxDiscards", " FCOE L3 RX discarded frames "}, 920 {"FcmPortClass3TxFrames", " FCOE L3 TX frames "}, 921 {"FcmPortClass2RxFrames", " FCOE L2 RX frames "}, 922 {"FcmPortClass2RxDiscards", " FCOE L2 RX discarded frames "}, 923 {"FcmPortClass2TxFrames", " FCOE L2 TX frames "}, 924 {"NonHGoE", " Non HGoE Rx frames on an HGoE port"}, 925 {"HGoE", " HGoE Rx frames"}, 926 {"PROTSWITCHINGDROP", " Pkts Dropped due to Protection switching in EPIPE"}, 927 {"VNTAG_ERROR", " Rx VNTAG error packets"}, 928 {"NIV_FORWARDING_DROP", " Rx NIV/PE packets dropped due to forwarding error"}, 929 {"IFP_PFC_DROP", " Original ingress packets dropped due to IFP PfcTx action"}, 930 {"TECN_TABLE_DROP", " Tx Egress packets dropped due to ECN error"}, 931 {"TNIV_PRUNE_DROP", " Tx Egress NIV/PE packets dropped due to pruning check"}, 932 {"RxHigigLoopbackDrop", " HiGig loopback packets dropped"}, 933 {"RxHigigUnknownOpcodeDrop", " HiGig unknown opcode"}, 934 {"RxIpInIpDrop", " IPinIP tunnel process failure"}, 935 {"RxMimDrop", " MiM tunnel process failure"}, 936 {"RxTunnelInterfaceError", 937 " IPMC tunnel incoming interface is incorrect"}, 938 {"RxMplsControlWordInvalid", " MPLS invalid control word"}, 939 {"RxMplsGalNotBosDrop", " MPLS Generic Label is not BOS"}, 940 {"RxMplsPayloadInvalid", " MPLS invalid payload"}, 941 {"RxMplsEntropyDrop", " MPLS Entropy label in unallowed range"}, 942 {"RxMplsLabelLookupMiss", " MPLS label lookup miss"}, 943 {"RxMplsActionInvalid", " MPLS invalid action"}, 944 {"RxTunnelTtlError", " Tunnel TTL check failure"}, 945 {"RxTunnelShimError", " Tunnel shim header error"}, 946 {"RxTunnelObjectValidationFail", " Tunnel termination failure"}, 947 {"RxVlanMismatch", " VLAN ID invalid"}, 948 {"RxVlanMemberMismatch", " Ingress port not in VLAN membership"}, 949 {"RxTpidMismatch", " VLAN TPID mismatch"}, 950 {"RxPrivateVlanMismatch", " PVLAN VID mismatch"}, 951 {"RxMacIpBindError", " MAC to IP bind check failure"}, 952 {"RxVlanTranslate2LookupMiss", " VLAN Translate2 lookup miss"}, 953 {"RxL3TunnelLookupMiss", " L3 Tunnel lookup miss"}, 954 {"RxMplsLookupMiss", " MPLS lookup miss"}, 955 {"RxVlanTranslate1LookupMiss", " VLAN Translate1 lookup miss"}, 956 {"RxFcoeVftDrop", " FVT header error"}, 957 {"RxFcoeSrcBindError", " FCOE source bind check failure"}, 958 {"RxFcoeSrcFpmaError", " Source FPMA prefix check failure"}, 959 {"RxVfiP2pDrop", 960 " Packets arrived from a VP that is not programmed \ 961 in PT2PT connection"}, 962 {"RxStgDrop", " STP not in forwarding state"}, 963 {"RxCompositeError", 964 " HW related error like lookup table with parity error"}, 965 {"RxBpduDrop", " BPUD packets dropped"}, 966 {"RxProtocolDrop", " Protocol packets dropped"}, 967 {"RxUnknownMacSaDrop", " Unknown MACSA packets dropped "}, 968 {"RxSrcRouteDrop", " MACSA is multicast(bit 40 == 1)"}, 969 {"RxL2SrcDiscardDrop", " L2 SRC_DISCARD drop"}, 970 {"RxL2SrcStaticMoveDrop", " Port movement of static L2 addr"}, 971 {"RxL2DstDiscardDrop", " L2 DST_DISCARD drop"}, 972 {"RxL3DisableDrop", " V4/V6 L3_ENABLE unset drop"}, 973 {"RxMacSaEqual0Drop", " Packets dropped due to MACSA == 0"}, 974 {"RxVlanCrossConnectOrNonUnicastDrop", 975 " L2 forwarding lookup miss or PBT non unicast packets drop"}, 976 {"RxTimeSyncDrop", " Network time sync packets dropped"}, 977 {"RxIpmcDrop", " IPMC process failure"}, 978 {"RxMyStationDrop", " MY_STATION.DISCARD drop"}, 979 {"RxPrivateVlanVpFilterDrop", " Packets dropped based on src/dst VP type"}, 980 {"RxL3DstDiscardDrop", " L3 DST_DISCARD drop"}, 981 {"RxTunnelDecapEcnError", " Tunnel decap ECN error"}, 982 {"RxL3SrcDiscardDrop", " L3 SRC_DISCARD drop"}, 983 {"RxFcoeZoneLookupMiss", " FCOE_ZONE lookup miss"}, 984 {"RxL3TtlError", " L3 TTL check failure"}, 985 {"RxL3HeaderError", " L3 header error"}, 986 {"RxL2HeaderError", " L2 header error"}, 987 {"RxL3DstLookupDrop", 988 " IPMC processing drop, or L3_DESTINATION == 0 for L3UC packets"}, 989 {"RxL2TtlError", " L2 ZONE TTL check failure"}, 990 {"RxL2RpfError", 991 " Incoming port/lag/svp check failure"}, 992 {"RxTagUntagDiscardDrop", " PORT_DIS_UNTAG/PORT_DIS_TAG drop"}, 993 {"RxStormControlDrop", " Storm control metering drop"}, 994 {"RxFcoeZoneError", " FCOE_ZONE check failure"}, 995 {"RxFieldChangeL2NoRedirectDrop", 996 " Change L2 fields without deploying redirect action drop"}, 997 {"RxNextHopDrop", " NEXT_HOP drop"}, 998 {"RxNatDrop", " NAT process failure"}, 999 {"IngressProtectionDataDrop", " Protection data drop"}, 1000 {"RxSrcKnockoutDrop", " SGPP == DGPP or SVP == DVP, etc"}, 1001 {"RxMplsSeqNumberError", " MPLS control word sequence number error"}, 1002 {"RxBlockMaskDrop", " Bitmap of ports blocked"}, 1003 {"RxDlbRhResolutionError", " DLB or RH resolution error"}, 1004 {"TxFwdDomainNotFoundDrop", " Forwarding domain not found"}, 1005 {"TxNotFwdDomainMemberDrop", " Not forwarding domain member"}, 1006 {"TxIpmcL2SrcPortPruneDrop", " IPMC L2 self port drop"}, 1007 {"TxNonUnicastPruneDrop", " Non unicast pruning"}, 1008 {"TxSvpRemoveDrop", " Virtual port pruning"}, 1009 {"TxVplagPruneDrop", " VPLAG pruning"}, 1010 {"TxSplitHorizonDrop", " Split horizon check failure"}, 1011 {"TxMmuPurgeDrop", " Packets dropped due to MMU purge"}, 1012 {"TxStgDisableDrop", " Packets dropped due to STG disabled"}, 1013 {"TxEgressPortDrop", " EGR_LPORT_PROFILE.DROP"}, 1014 {"TxEgressFilterDrop", " Packets dropped by EFP"}, 1015 {"TxVisibilityDrop", " Visibility packets dropped"} 1016 }; 1017 1018 /* 1019 * Function: 1020 * get_counter 1021 * Description: 1022 * Get numeric counter value from input string. 1023 * Parameters: 1024 * c - Input string. 1025 * rx_tx - Counter type (RX/TX)? 1026 * counter - Counter value to be returned. 1027 * Returns: 1028 * SUCCESS(0)/ FAILURE(-1). 1029 */ 1030 static int 1031 get_counter(char *c, int rx_tx, int *counter) 1032 { 1033 int i; 1034 int n; 1035 1036 i = 0; 1037 n = 0; 1038 1039 while (isdigit((unsigned) c[i])) { 1040 n = n * 10 + c[i++] - '0'; 1041 } 1042 1043 if (n < 0 || c[i]) { 1044 return -1; 1045 } 1046 1047 if (rx_tx == RDBGC) { 1048 n += snmpBcmCustomReceive0; 1049 if (n < snmpBcmCustomReceive0 || n >= snmpBcmCustomTransmit0) { 1050 return -1; 1051 } 1052 } else if (rx_tx == TDBGC) { 1053 n += snmpBcmCustomTransmit0; 1054 if (n < snmpBcmCustomTransmit0 || n >= snmpValCount) { 1055 return -1; 1056 } 1057 } 1058 1059 *counter = n; 1060 return 0; 1061 1062 } 1063 1064 /* 1065 * Function: 1066 * set_triggers 1067 * Description: 1068 * Set triggers for given counter. 1069 * Parameters: 1070 * unit - StrataSwitch PCI device unit number. 1071 * port - port number. 1072 * counter - counter number. 1073 * a - argc/argv (sorta) structure for parsing arguments. 1074 * Returns: 1075 * None. 1076 */ 1077 static int 1078 set_triggers(int unit, int port, uint32 counter, args_t * a) 1079 { 1080 1081 char *c; 1082 char act = 5; 1083 int cur_config = 0; 1084 int rv = 0; 1085 uint32 trig_typ = 0; 1086 1087 while ((c = ARG_GET(a)) != NULL) { 1088 if (c[0] == '+') { 1089 act = 1; /* add */ 1090 c++; 1091 } else if (c[0] == '-') { 1092 act = 2; /* remove */ 1093 c++; 1094 } 1095 for (trig_typ = 0; trig_typ < bcmDbgCntNum; trig_typ++) { 1096 if (parse_cmp(_trig_names[trig_typ].name, c, '\0')) { 1097 break; 1098 } 1099 } 1100 1101 if (trig_typ == bcmDbgCntNum) { 1102 cli_out("%s Not available: see CustomSTAT LS\n", c); 1103 continue; 1104 } 1105 1106 switch (act) { 1107 case 1: 1108 rv = bcm_stat_custom_add(unit, port, counter, trig_typ); 1109 break; 1110 case 2: 1111 rv = bcm_stat_custom_delete(unit, port, counter, trig_typ); 1112 break; 1113 default: /* toggle */ 1114 rv = bcm_stat_custom_check(unit, port, 1115 counter, trig_typ, &cur_config); 1116 if (BCM_SUCCESS(rv)) { 1117 if (cur_config == 1) { 1118 rv = bcm_stat_custom_delete(unit, port, counter, 1119 trig_typ); 1120 } else { 1121 rv = bcm_stat_custom_add(unit, port, counter, 1122 trig_typ); 1123 } 1124 } 1125 } 1126 1127 if (BCM_FAILURE(rv)) { 1128 cli_out("\t%18s\t%s %s (stat %d, port %d): %s\n", "-", 1129 stat_names[counter], _trig_names[trig_typ].name, 1130 counter, port, bcm_errmsg(rv)); 1131 } 1132 } 1133 return rv; 1134 } 1135 1136 /* 1137 * Function: 1138 * cstat_flags_show 1139 * Description: 1140 * Show programmed triggers for given counter. 1141 * Parameters: 1142 * unit - StrataSwitch PCI device unit number. 1143 * pbmp - Bitmap of ports. 1144 * rx_tx - counter type. 1145 * counter - counter number. 1146 * -1 means all. 1147 * Returns: 1148 * None. 1149 */ 1150 static void 1151 cstat_flags_show(int unit, bcm_pbmp_t pbmp, int rx_tx, int counter) 1152 { 1153 uint32 count_index; 1154 uint32 start; 1155 uint32 end; 1156 int port, dport; 1157 int title; 1158 int i = 0; 1159 int rv = 0; 1160 int trig_typ = 0; 1161 int cur_config = 0; 1162 1163 if (rx_tx == RDBGC) { 1164 port = 0; 1165 cli_out("Custom Receive stats are enabled for following triggers\n"); 1166 cli_out("[Triggers are common for all ports]\n"); 1167 1168 start = (counter == -1) ? snmpBcmCustomReceive0 : counter; 1169 end = (counter == -1) ? snmpBcmCustomTransmit0 : counter + 1; 1170 1171 for (count_index = start; count_index < end; count_index++) { 1172 title = 1; 1173 for (trig_typ = 0, i = 0; trig_typ < bcmDbgCntNum; trig_typ++) { 1174 cur_config = 0; 1175 rv = bcm_stat_custom_check(unit, port, count_index, 1176 trig_typ, &cur_config); 1177 if (BCM_SUCCESS(rv) && cur_config) { 1178 if (title) { 1179 cli_out("\n%23s-\n\t\t", stat_names[count_index]); 1180 title = 0; 1181 } 1182 cli_out("%s%s", _trig_names[trig_typ].name, 1183 !((i + 1) % 5) ? "\n\t\t" : " "); 1184 i++; 1185 } else { 1186 continue; 1187 } 1188 } 1189 } 1190 cli_out("\n"); 1191 return; 1192 } 1193 1194 if (rx_tx == TDBGC) { 1195 start = (counter == -1) ? snmpBcmCustomTransmit0 : counter; 1196 end = (counter == -1) ? snmpValCount : counter + 1; 1197 cli_out("Custom Transmit stats are enabled for following triggers\n"); 1198 /* coverity[overrun-local] */ 1199 DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) { 1200 BCM_PBMP_CLEAR(pbmp); 1201 cli_out("[Triggers are common for all ports]\n"); 1202 for (count_index = start; count_index < end; count_index++) { 1203 title = 1; 1204 for (trig_typ = 0, i = 0; trig_typ < bcmDbgCntNum; 1205 trig_typ++) { 1206 cur_config = 0; 1207 rv = bcm_stat_custom_check(unit, port, count_index, 1208 trig_typ, &cur_config); 1209 if (BCM_SUCCESS(rv) && cur_config) { 1210 if (title) { 1211 cli_out("\n%23s-\n\t\t", 1212 stat_names[count_index]); 1213 title = 0; 1214 } 1215 cli_out("%s%s", _trig_names[trig_typ].name, 1216 !((i + 1) % 5) ? "\n\t\t" : " "); 1217 i++; 1218 } else { 1219 continue; 1220 } 1221 } 1222 } 1223 } 1224 cli_out("\n"); 1225 return; 1226 } 1227 1228 } 1229 1230 /* 1231 * Function: 1232 * cstat_stats_show 1233 * Description: 1234 * Show programmable counters. 1235 * Parameters: 1236 * unit - StrataSwitch PCI device unit number. 1237 * pbmp - Bitmap of ports. 1238 * rx_tx - counter type to be displayed. 1239 * counter - counter number to be displayed. 1240 * -1 means all. 1241 * Returns: 1242 * SUCCESS(0)/FAILURE(-1). 1243 */ 1244 static int 1245 cstat_stats_show(int unit, bcm_pbmp_t pbmp, int rx_tx, int counter) 1246 { 1247 uint32 count_index; 1248 uint32 start; 1249 uint32 end; 1250 uint32 title; 1251 uint64 value; 1252 int port, dport; 1253 int rv = 0; 1254 1255 cli_out("%s Custom Statistics :\n", rx_tx == RDBGC ? "RX" : "TX"); 1256 1257 /* coverity[overrun-local] */ 1258 DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) { 1259 switch (rx_tx) { 1260 case RDBGC: 1261 start = (counter == -1) ? snmpBcmCustomReceive0 : counter; 1262 end = (counter == -1) ? snmpBcmCustomTransmit0 : 1263 counter + 1; 1264 title = 1; 1265 for (count_index = start; count_index < end; count_index++) { 1266 rv = bcm_stat_get(unit, port, count_index, &value); 1267 if (BCM_FAILURE(rv)) { 1268 cli_out("\t%18s\t%s (stat %d): %s\n", "-", 1269 stat_names[count_index], count_index, 1270 bcm_errmsg(rv)); 1271 continue; 1272 } 1273 if (COMPILER_64_IS_ZERO(value)) { 1274 continue; 1275 } 1276 if (title) { 1277 cli_out(" %s:\n", SOC_PORT_NAME(unit, port)); 1278 title = 0; 1279 } 1280 if (COMPILER_64_HI(value) == 0) { 1281 cli_out(" %18u\t%s (stat %d)\n", 1282 COMPILER_64_LO(value), 1283 stat_names[count_index], count_index); 1284 } else { 1285 cli_out(" 0x%08x%08x\t%s (stat %d)\n", 1286 COMPILER_64_HI(value), 1287 COMPILER_64_LO(value), 1288 stat_names[count_index], count_index); 1289 } 1290 } 1291 break; 1292 case TDBGC: 1293 start = (counter == -1) ? snmpBcmCustomTransmit0 : counter; 1294 end = (counter == -1) ? snmpValCount : counter + 1; 1295 title = 1; 1296 for (count_index = start; count_index < end; count_index++) { 1297 rv = (bcm_stat_get(unit, port, count_index, &value)); 1298 if (BCM_FAILURE(rv)) { 1299 cli_out("\t%18s\t%s (stat %d): %s\n", "-", 1300 stat_names[count_index], count_index, 1301 bcm_errmsg(rv)); 1302 continue; 1303 } 1304 if (COMPILER_64_IS_ZERO(value)) { 1305 continue; 1306 } 1307 if (title) { 1308 cli_out(" %s:\n", SOC_PORT_NAME(unit, port)); 1309 title = 0; 1310 } 1311 if (COMPILER_64_HI(value) == 0) { 1312 cli_out(" %18u\t%s (stat %d)\n", 1313 COMPILER_64_LO(value), 1314 stat_names[count_index], count_index); 1315 } else { 1316 cli_out(" 0x%08x%08x\t%s (stat %d)\n", 1317 COMPILER_64_HI(value), 1318 COMPILER_64_LO(value), 1319 stat_names[count_index], count_index); 1320 } 1321 } 1322 break; 1323 default: 1324 cli_out("Invalid custom stats: valid values [RX,TX]\n"); 1325 return -1; 1326 } 1327 } 1328 cli_out("\n"); 1329 return rv; 1330 } 1331 1332 /* 1333 * Function: 1334 * cstat_flags_set 1335 * Description: 1336 * Set triggers for counters. 1337 * Parameters: 1338 * unit - StrataSwitch PCI device unit number. 1339 * pbmp - Bitmap of ports. 1340 * rx_tx - trigger type to be set. 1341 * counter - counter number to be programmed. 1342 * a - argc/argv (sorta) structure for parsing arguments. 1343 * Returns: 1344 * SUCCESS(0)/FAILURE(-1). 1345 */ 1346 static int 1347 cstat_flags_set(int unit, bcm_pbmp_t pbmp, int rx_tx, int counter, 1348 args_t * a) 1349 { 1350 1351 int flags_index; 1352 bcm_port_t port, dport; 1353 uint32 count_index; 1354 uint32 start; 1355 uint32 end; 1356 1357 if (!ARG_CUR(a)) { 1358 cli_out("Error: No input triggers\n"); 1359 return -1; 1360 } 1361 /* 1362 * save index of first flag 1363 */ 1364 flags_index = a->a_arg; 1365 1366 /* coverity[overrun-local] */ 1367 DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) { 1368 switch (rx_tx) { 1369 case RDBGC: 1370 start = (counter == -1) ? snmpBcmCustomReceive3 : counter; 1371 end = (counter == -1) ? snmpBcmCustomTransmit0 : 1372 counter + 1; 1373 for (count_index = start; count_index < end; count_index++) { 1374 a->a_arg = flags_index; 1375 set_triggers(unit, port, count_index, a); 1376 } 1377 break; 1378 case TDBGC: 1379 start = (counter == -1) ? snmpBcmCustomTransmit6 : counter; 1380 end = (counter == -1) ? snmpBcmCustomTransmit12 : counter + 1; 1381 for (count_index = start; count_index < end; count_index++) { 1382 a->a_arg = flags_index; 1383 set_triggers(unit, port, count_index, a); 1384 } 1385 break; 1386 default: 1387 cli_out("Error: Invalid custom stats: valid values [RX,TX]\n"); 1388 return -1; 1389 } 1390 break; 1391 } 1392 return 0; 1393 } 1394 1395 /* 1396 * Function: 1397 * list_flags 1398 * Description: 1399 * Display the triggers available for current device. 1400 * Parameters: 1401 * unit - StrataSwitch PCI device unit number. 1402 * about - (0/1) whether to display short description of each trigger? 1403 * rx_tx - trigger type to be displayed. 1404 * Returns: 1405 * None. 1406 */ 1407 static void 1408 list_flags(int unit, int about, int rx_tx) 1409 { 1410 int trig_typ; 1411 int res; 1412 int loop; 1413 int dummy_port = SOC_PORT_MIN(unit, port); 1414 1415 cli_out("Custom stat\n"); 1416 if (rx_tx == RDBGC || rx_tx == BOTH) { 1417 cli_out(" Available Rx trigger flags :\n "); 1418 for (trig_typ = 0, loop = 0; trig_typ < bcmDbgCntNum; trig_typ++) { 1419 if (BCM_SUCCESS(bcm_stat_custom_check(unit, dummy_port, 1420 snmpBcmCustomReceive0, 1421 trig_typ, &res))) { 1422 if (!about) { 1423 cli_out("%-19s%s", _trig_names[trig_typ].name, 1424 !((loop + 1) % 4) ? "\n " : ""); 1425 } else { 1426 cli_out("%s%s\n ", _trig_names[trig_typ].name, 1427 _trig_names[trig_typ].about); 1428 } 1429 loop++; 1430 } 1431 } 1432 cli_out("\n"); 1433 } 1434 1435 if (rx_tx == TDBGC || rx_tx == BOTH) { 1436 cli_out(" Available Tx trigger flags :\n "); 1437 for (trig_typ = 0, loop = 0; trig_typ < bcmDbgCntNum; trig_typ++) { 1438 if (BCM_SUCCESS(bcm_stat_custom_check(unit, dummy_port, 1439 snmpBcmCustomTransmit0, 1440 trig_typ, &res))) { 1441 if (!about) { 1442 cli_out("%-19s%s", _trig_names[trig_typ].name, 1443 !((loop + 1) % 4) ? "\n " : ""); 1444 } else { 1445 cli_out("%s%s\n ", _trig_names[trig_typ].name, 1446 _trig_names[trig_typ].about); 1447 } 1448 loop++; 1449 } 1450 } 1451 cli_out("\n"); 1452 } 1453 } 1454 1455 /* 1456 * Function: 1457 * display_val 1458 * Description: 1459 * Display value of counter. 1460 * Parameters: 1461 * val - Value to be displayed. 1462 * count_index - Index of counter. 1463 * Returns: 1464 * None. 1465 */ 1466 static void 1467 display_val(uint64 val, int count_index) 1468 { 1469 1470 char *typ_s; 1471 char *no_s; 1472 1473 typ_s = " "; 1474 no_s = " "; 1475 1476 if (count_index >= snmpBcmCustomTransmit0) { 1477 if (count_index == snmpBcmCustomTransmit0) { 1478 typ_s = "TX"; 1479 } 1480 if (count_index < snmpBcmCustomTransmit6) { 1481 no_s = "(R)"; 1482 } 1483 count_index -= snmpBcmCustomTransmit0; 1484 } else { 1485 if (count_index == snmpBcmCustomReceive0) { 1486 typ_s = "RX"; 1487 } 1488 if (count_index < snmpBcmCustomReceive3) { 1489 no_s = "(R)"; 1490 } 1491 count_index -= snmpBcmCustomReceive0; 1492 } 1493 1494 cli_out("\n| %s |%2d%s|", typ_s, count_index, no_s); 1495 1496 if (COMPILER_64_HI(val) == 0) { 1497 cli_out("%19u| ", COMPILER_64_LO((val))); 1498 } else { 1499 cli_out(" 0x%08x%08x| ", COMPILER_64_HI(val), COMPILER_64_LO(val)); 1500 } 1501 } 1502 1503 /* 1504 * Function: 1505 * list_table 1506 * Description: 1507 * Display the counters and triggers in tabular format. 1508 * Parameters: 1509 * unit - StrataSwitch PCI device unit number. 1510 * pbmp - Bitmap of ports. 1511 * show_zero - (0/1) Whether to include counters which are zero? 1512 * Returns: 1513 * None. 1514 */ 1515 static void 1516 list_table(int unit, bcm_pbmp_t pbmp, int show_zero) 1517 { 1518 1519 int n; 1520 int i; 1521 int j; 1522 int rv; 1523 int trig; 1524 int port = 0; 1525 int dport; 1526 int conf; 1527 int val_f; 1528 int title; 1529 int mid; 1530 int end; 1531 char *blnk = " "; 1532 uint64 value; 1533 1534 /* coverity[overrun-local] */ 1535 DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) { 1536 title = 1; 1537 mid = 1; 1538 end = 0; 1539 for (n = snmpBcmCustomReceive0; n < snmpValCount; n++) { 1540 rv = bcm_stat_get(unit, port, n, &value); 1541 if (BCM_FAILURE(rv)) { 1542 continue; 1543 } 1544 if (!show_zero && (COMPILER_64_IS_ZERO(value))) { 1545 continue; 1546 } 1547 if (title) { 1548 /* coverity[non_const_printf_format_string] */ 1549 cli_out(head, SOC_PORT_NAME(unit, (port))); 1550 cli_out("%s%s", menu, line); 1551 title = 0; 1552 end = 1; 1553 } 1554 if (n >= snmpBcmCustomTransmit0 && mid) { 1555 cli_out("%s", line); 1556 mid = 0; 1557 } 1558 val_f = 1; 1559 j = 0; 1560 for (trig = 0, i = 0; trig < bcmDbgCntNum; trig++) { 1561 conf = 0; 1562 rv = bcm_stat_custom_check(unit, port, n, trig, &conf); 1563 if (BCM_SUCCESS(rv) && conf) { 1564 if (val_f) { 1565 display_val(value, n); 1566 val_f = 0; 1567 } 1568 if (!((i + 1) % COL_SZ)) { 1569 cli_out("%.*s|%s", (int) (sal_strlen(blnk) - j), 1570 blnk, trg_s); 1571 j = 0; 1572 } 1573 cli_out("%s ", _trig_names[trig].name); 1574 j = j + sal_strlen(_trig_names[trig].name) + 1; 1575 i++; 1576 } 1577 } 1578 if (j) { 1579 cli_out("%.*s|", (int) (sal_strlen(blnk) - j), blnk); 1580 } 1581 } 1582 if (end) { 1583 cli_out("%s", line); 1584 end = 0; 1585 cli_out("\n\n"); 1586 } 1587 } 1588 1589 } /* end of list_table */ 1590 1591 /* 1592 * Function: 1593 * cmd_esw_custom_stat 1594 * Description: 1595 * Main function to process CustomSTAT command. 1596 * Parameters: 1597 * unit - StrataSwitch PCI device unit number. 1598 * a - argc/argv (sorta) structure for parsing arguments. 1599 * Returns: 1600 * Result of command processing, SUCCESS, FAIL or print command usage. 1601 */ 1602 cmd_result_t 1603 cmd_esw_custom_stat(int unit, args_t * a) 1604 { 1605 1606 bcm_pbmp_t pbmp; 1607 uint32 cmd_type; /* show flags, set flags, show counters */ 1608 char *c; 1609 int rx_tx; 1610 int rv = 0; 1611 int counter; /* selected DBGC map, input */ 1612 int display_zero; 1613 int display_info; 1614 1615 if (!sh_check_attached(ARG_CMD(a), unit)) { 1616 return CMD_FAIL; 1617 } 1618 1619 BCM_PBMP_CLEAR(pbmp); 1620 BCM_PBMP_PORT_ADD(pbmp, 0); /* ge0 */ 1621 counter = -1; /* all counters */ 1622 cmd_type = SHOW_TABLE; 1623 rx_tx = BOTH; 1624 display_zero = FALSE; 1625 display_info = FALSE; 1626 1627 if (!(c = ARG_GET(a))) { 1628 goto do_stat_command; 1629 } else { 1630 if (!sal_strcasecmp(c, "ls")) { 1631 cmd_type = LIST_FLAGS; 1632 } else if (!sal_strcasecmp(c, "info")) { 1633 cmd_type = LIST_FLAGS; 1634 display_info = TRUE; 1635 } else if (!sal_strcasecmp(c, "set")) { 1636 cmd_type = SET_FLAGS; 1637 c = ARG_GET(a); 1638 } else if (!sal_strcasecmp(c, "get")) { 1639 cmd_type = SHOW_FLAGS; 1640 c = ARG_GET(a); 1641 } else if (!sal_strcasecmp(c, "raw")) { 1642 cmd_type = SHOW_COUNTERS; 1643 c = ARG_GET(a); 1644 } 1645 } 1646 1647 /* 1648 * no input pbm 1649 */ 1650 if (!c) { 1651 ERROR_SET_FLAGS("No input port\n"); 1652 goto do_stat_command; 1653 } else if (cmd_type != LIST_FLAGS) { 1654 if (parse_bcm_pbmp(unit, c, &pbmp) < 0) { 1655 cli_out("%s: Error: unrecognized port bitmap: %s\n", ARG_CMD(a), 1656 c); 1657 return CMD_FAIL; 1658 } 1659 } 1660 1661 /* 1662 * RX/TX ? 1663 */ 1664 if (!(c = ARG_GET(a))) { 1665 ERROR_SET_FLAGS("No input type[rx|tx]\n"); 1666 goto do_stat_command; 1667 } else { 1668 if (!sal_strcasecmp(c, "rx")) { 1669 rx_tx = RDBGC; 1670 } else if (!sal_strcasecmp(c, "tx")) { 1671 rx_tx = TDBGC; 1672 } else if (sal_toupper((int)c[0]) == 'Z') { 1673 display_zero = TRUE; 1674 goto do_stat_command; 1675 } else { 1676 cli_out("Invalid input '%s'\n", c); 1677 return CMD_FAIL; 1678 } 1679 1680 /* coverity[new_values] */ 1681 if (cmd_type == LIST_FLAGS) { 1682 goto do_stat_command; 1683 } 1684 } 1685 1686 /* 1687 * counter bitmap 1688 */ 1689 if (!(c = ARG_GET(a))) { 1690 ERROR_SET_FLAGS("No input counter\n"); 1691 goto do_stat_command; 1692 } else { 1693 if (!sal_strcasecmp(c, "all")) { 1694 goto do_stat_command; 1695 } else if (!get_counter(c, rx_tx, &counter)) { 1696 goto do_stat_command; 1697 } else { 1698 cli_out("Invalid counter\n"); 1699 return CMD_FAIL; 1700 } 1701 } 1702 1703 do_stat_command: 1704 switch (cmd_type) { 1705 case SHOW_FLAGS: 1706 if (rx_tx == BOTH) { 1707 cstat_flags_show(unit, pbmp, RDBGC, counter); 1708 cstat_flags_show(unit, pbmp, TDBGC, counter); 1709 } else { 1710 cstat_flags_show(unit, pbmp, rx_tx, counter); 1711 } 1712 break; 1713 case SHOW_COUNTERS: 1714 if (rx_tx == BOTH) { 1715 rv = cstat_stats_show(unit, pbmp, RDBGC, counter); 1716 rv = cstat_stats_show(unit, pbmp, TDBGC, counter); 1717 } else { 1718 rv = cstat_stats_show(unit, pbmp, rx_tx, counter); 1719 } 1720 break; 1721 case SHOW_TABLE: 1722 list_table(unit, pbmp, display_zero); 1723 break; 1724 case SET_FLAGS: 1725 rv = cstat_flags_set(unit, pbmp, rx_tx, counter, a); 1726 break; 1727 case LIST_FLAGS: 1728 list_flags(unit, display_info, rx_tx); 1729 break; 1730 /* coverity[dead_error_begin] */ 1731 default: 1732 /* 1733 * should not reach here 1734 */ 1735 return CMD_FAIL; 1736 } 1737 1738 if (rv < 0) { 1739 return CMD_FAIL; 1740 } 1741 1742 return CMD_OK; 1743 1744 } 1745