cos.c (52210B)
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 * COS CLI commands 8 */ 9 10 #include <appl/diag/system.h> 11 #include <appl/diag/parse.h> 12 #include <appl/diag/dport.h> 13 #include <shared/bsl.h> 14 #include <bcm/error.h> 15 #include <bcm/cosq.h> 16 #include <bcm/debug.h> 17 18 #if defined(BCM_TOMAHAWK3_SUPPORT) 19 #define BCM_TH3_COS_COUNT 12 20 #endif 21 22 /* 23 * Manage classes of service 24 */ 25 26 STATIC int 27 _bcm_gport_show_config(int unit, bcm_gport_t port, int numq, 28 uint32 flags, bcm_gport_t sched_gport, void *user_data) 29 { 30 bcm_cos_queue_t cosq; 31 bcm_port_t user_port = PTR_TO_INT(user_data); 32 bcm_port_t local_port = 0; 33 char *mode_name = NULL, *weight_str = "packets"; 34 int mode, weight, weight_max, rv; 35 36 local_port = BCM_GPORT_MODPORT_PORT_GET(port); 37 if ((NUM_MODID(unit) == 2) && (BCM_GPORT_MODPORT_MODID_GET(port) & 1)) { 38 local_port += 32; 39 } 40 if (user_port != local_port) { 41 return BCM_E_NONE; 42 } 43 for (cosq = 0; cosq < 16; cosq++) { 44 rv = bcm_cosq_gport_sched_get(unit, sched_gport, cosq, &mode, &weight); 45 if (rv < 0) { 46 break; 47 } 48 49 switch (mode) { 50 case BCM_COSQ_STRICT: 51 mode_name = "strict"; 52 break; 53 case BCM_COSQ_ROUND_ROBIN: 54 mode_name = "simple round-robin"; 55 break; 56 case BCM_COSQ_WEIGHTED_ROUND_ROBIN: 57 mode_name = "weighted round-robin"; 58 break; 59 case BCM_COSQ_WEIGHTED_FAIR_QUEUING: 60 mode_name = "weighted fair queuing"; 61 break; 62 case BCM_COSQ_BOUNDED_DELAY: 63 mode_name = "weighted round-robin with bounded delay"; 64 break; 65 case BCM_COSQ_DEFICIT_ROUND_ROBIN: 66 mode_name = "deficit round-robin"; 67 weight_str = "Kbytes"; 68 break; 69 default: 70 mode_name = NULL; 71 break; 72 } 73 74 if ((rv = bcm_cosq_sched_weight_max_get(unit, 75 mode, &weight_max)) < 0) { 76 return rv; 77 } 78 79 if (cosq == 0 && mode_name) { 80 cli_out(" VLAN COSQ Schedule mode: %s\n", mode_name); 81 } 82 83 if (mode >= 0 && mode != BCM_COSQ_STRICT) { 84 if (cosq == 0) { 85 cli_out(" VLAN COSQ Weighting (in %s):\n", weight_str); 86 } 87 88 if (weight_max == BCM_COSQ_WEIGHT_UNLIMITED) { 89 cli_out(" VLAN COSQ %d = %u %s\n", 90 cosq, (uint32) weight, weight_str); 91 } else { 92 cli_out(" VLAN COSQ %d = %d %s\n", 93 cosq, weight, weight_str); 94 } 95 } 96 } 97 return BCM_E_NONE; 98 } 99 100 STATIC int 101 _bcm_gport_show_bandwidth(int unit, bcm_gport_t port, int numq, 102 uint32 flags, bcm_gport_t sched_gport, void *user_data) 103 { 104 bcm_cos_queue_t cosq; 105 bcm_port_t user_port = PTR_TO_INT(user_data); 106 bcm_port_t local_port = 0; 107 uint32 kbits_sec_min, kbits_sec_max, bw_flags; 108 109 BCM_IF_ERROR_RETURN( 110 bcm_port_local_get(unit, port, &local_port)); 111 112 if (user_port != local_port) { 113 return BCM_E_NONE; 114 } 115 116 for (cosq = 0; cosq < 16; cosq++) { 117 if (bcm_cosq_gport_bandwidth_get(unit, sched_gport, cosq, 118 &kbits_sec_min, &kbits_sec_max, &bw_flags) == 0) { 119 cli_out(" U %4s | %d | %8d | %8d | %6d\n", 120 BCM_PORT_NAME(unit, local_port), cosq, kbits_sec_min, 121 kbits_sec_max, bw_flags); 122 } 123 } 124 return BCM_E_NONE; 125 } 126 127 STATIC int 128 _bcm_gport_show_discard(int unit, bcm_gport_t port, int numq, 129 uint32 flags, bcm_gport_t sched_gport, void *user_data) 130 { 131 int rv = BCM_E_NONE; 132 bcm_cos_queue_t cosq; 133 bcm_port_t user_port = PTR_TO_INT(user_data); 134 bcm_port_t local_port = 0; 135 int discard_start, discard_slope, discard_time; 136 137 BCM_IF_ERROR_RETURN( 138 bcm_port_local_get(unit, port, &local_port)); 139 140 if (user_port != local_port) { 141 return BCM_E_NONE; 142 } 143 144 for (cosq = 0; cosq < 16; cosq++) { 145 if ((rv = bcm_cosq_discard_port_get(unit, sched_gport, cosq, 146 BCM_COSQ_DISCARD_COLOR_GREEN, 147 &discard_start, &discard_slope, 148 &discard_time)) < 0) { 149 continue; 150 } 151 cli_out(" U %4s | %d | %6d | %2d | %5d ", 152 BCM_PORT_NAME(unit, local_port), cosq, discard_start, 153 discard_slope, discard_time); 154 if ((rv = bcm_cosq_discard_port_get(unit, sched_gport, cosq, 155 BCM_COSQ_DISCARD_COLOR_YELLOW, 156 &discard_start, &discard_slope, 157 &discard_time)) < 0) { 158 cli_out("| ---- | -- | ----- "); 159 } else { 160 cli_out("| %6d | %2d | %5d ", 161 discard_start, discard_slope, discard_time); 162 } 163 if ((rv = bcm_cosq_discard_port_get(unit, sched_gport, cosq, 164 BCM_COSQ_DISCARD_COLOR_RED, 165 &discard_start, &discard_slope, 166 &discard_time)) < 0) { 167 return rv; 168 } 169 cli_out("| %6d | %2d | %5d\n", 170 discard_start, discard_slope, discard_time); 171 } 172 return BCM_E_NONE; 173 } 174 175 cmd_result_t 176 cmd_esw_cos(int unit, args_t *a) 177 { 178 int r; 179 char *subcmd, *c; 180 bcm_cos_queue_t cosq; 181 int* weights; 182 #if defined(BCM_TOMAHAWK3_SUPPORT) 183 int weight_arr_size; 184 #endif 185 int delay = 0; 186 int numq, mode = 0; 187 bcm_cos_t prio; 188 bcm_cos_t lastPrio = 0; 189 parse_table_t pt; 190 cmd_result_t retCode; 191 int discard_ena, discard_cap_avg, gain, drop_prob; 192 int discard_start, discard_end, discard_slope, discard_time; 193 char * discard_color; 194 char* discard_mode; 195 bcm_pbmp_t pbmp; 196 bcm_port_config_t pcfg; 197 soc_port_t p, dport; 198 199 200 if (SOC_IS_TOMAHAWK3(unit)) { 201 #if defined(BCM_TOMAHAWK3_SUPPORT) 202 weights = (int *) sal_alloc( 203 sizeof(int) * BCM_TH3_COS_COUNT, "weights array"); 204 sal_memset(weights, 0, BCM_TH3_COS_COUNT * sizeof(int)); 205 #endif 206 } else { 207 weights = (int *) sal_alloc( 208 sizeof(int) * BCM_COS_COUNT, "weights array"); 209 sal_memset(weights, 0, BCM_COS_COUNT * sizeof(int)); 210 } 211 212 if (!sh_check_attached(ARG_CMD(a), unit)) { 213 if (weights != NULL) { 214 sal_free(weights); 215 weights = NULL; 216 } 217 return CMD_FAIL; 218 } 219 220 if ((subcmd = ARG_GET(a)) == NULL) { 221 if (weights != NULL) { 222 sal_free(weights); 223 weights = NULL; 224 } 225 return CMD_USAGE; 226 } 227 228 c = ARG_CUR(a); 229 230 if ((c) == NULL) { 231 if (sal_strcasecmp(subcmd, "clear") == 0) { 232 if ((r = bcm_cosq_init(unit)) < 0) { 233 goto bcm_err; 234 } 235 if (weights != NULL) { 236 sal_free(weights); 237 weights = NULL; 238 } 239 return CMD_OK; 240 } 241 242 if (sal_strcasecmp(subcmd, "strict") == 0) { 243 if (SOC_IS_TOMAHAWK3(unit)) { 244 #if defined(BCM_TOMAHAWK3_SUPPORT) 245 if ((r = bcm_cosq_sched_config_set(unit, BCM_COSQ_STRICT, 246 BCM_TH3_COS_COUNT, weights)) < 0) 247 { 248 goto bcm_err; 249 } 250 #endif 251 } else { 252 if ((r = bcm_cosq_sched_set(unit, BCM_COSQ_STRICT, 253 weights, 0)) < 0) 254 { 255 goto bcm_err; 256 } 257 } 258 if (weights != NULL) { 259 sal_free(weights); 260 weights = NULL; 261 } 262 return CMD_OK; 263 } 264 265 if (sal_strcasecmp(subcmd, "simple") == 0) { 266 if (SOC_IS_TOMAHAWK3(unit)) { 267 #if defined(BCM_TOMAHAWK3_SUPPORT) 268 if ((r = bcm_cosq_sched_config_set(unit, BCM_COSQ_ROUND_ROBIN, 269 BCM_TH3_COS_COUNT, weights)) < 0) 270 { 271 goto bcm_err; 272 } 273 #endif 274 } else { 275 if ((r = bcm_cosq_sched_set(unit, BCM_COSQ_ROUND_ROBIN, 276 weights, 0)) < 0) 277 { 278 goto bcm_err; 279 } 280 } 281 if (weights != NULL) { 282 sal_free(weights); 283 weights = NULL; 284 } 285 return CMD_OK; 286 } 287 288 } 289 290 if ((r = bcm_cosq_config_get(unit, &numq)) < 0) { 291 goto bcm_err; 292 } 293 294 if (SOC_IS_TOMAHAWK3(unit)) { 295 #if defined(BCM_TOMAHAWK3_SUPPORT) 296 r = bcm_cosq_sched_config_get(unit, BCM_TH3_COS_COUNT, weights, &weight_arr_size, &mode); 297 #endif 298 } else { 299 r = bcm_cosq_sched_get(unit, &mode, weights, &delay); 300 } 301 if (r == BCM_E_UNAVAIL) { 302 r = 0; 303 mode = -1; 304 } else if (r < 0) { 305 goto bcm_err; 306 } 307 308 if (bcm_port_config_get(unit, &pcfg) != BCM_E_NONE) { 309 cli_out("%s: Error: bcm ports not initialized\n", ARG_CMD(a)); 310 if (weights != NULL) { 311 sal_free(weights); 312 weights = NULL; 313 } 314 return CMD_FAIL; 315 } 316 317 if (sal_strcasecmp(subcmd, "port") == 0) { 318 int num_vlanq = 0; 319 bcm_gport_t gport, sched_gport = BCM_GPORT_INVALID; 320 321 if ((subcmd = ARG_GET(a)) == NULL) { 322 if (weights != NULL) { 323 sal_free(weights); 324 weights = NULL; 325 } 326 return CMD_USAGE; 327 } 328 if (sal_strcasecmp(subcmd, "config") == 0) { 329 BCM_PBMP_CLEAR(pbmp); 330 parse_table_init(unit, &pt); 331 parse_table_add(&pt, "Numcos", PQ_DFL|PQ_INT, 332 (void *)( 0), &num_vlanq, NULL); 333 parse_table_add(&pt, "PortBitMap", PQ_DFL|PQ_PBMP|PQ_BCM, 334 (void *)(0), &pbmp, NULL); 335 336 if (!parseEndOk( a, &pt, &retCode)) { 337 if (weights != NULL) { 338 sal_free(weights); 339 weights = NULL; 340 } 341 return retCode; 342 } 343 if (BCM_PBMP_IS_NULL(pbmp)) { 344 cli_out("%s: ERROR: must specify valid port bitmap.\n", 345 ARG_CMD(a)); 346 if (weights != NULL) { 347 sal_free(weights); 348 weights = NULL; 349 } 350 return CMD_FAIL; 351 } 352 353 DPORT_BCM_PBMP_ITER(unit, pbmp, dport, p) { 354 BCM_GPORT_LOCAL_SET(gport, p); 355 r = bcm_cosq_gport_add(unit, gport, num_vlanq, 356 BCM_COSQ_GPORT_SCHEDULER, &sched_gport); 357 if (r < 0) { 358 cli_out("%s: bcm_cosq_gport_add ERROR: port %s: %s\n", 359 ARG_CMD(a), 360 BCM_PORT_NAME(unit, p), 361 bcm_errmsg(r)); 362 if (weights != NULL) { 363 sal_free(weights); 364 weights = NULL; 365 } 366 return CMD_FAIL; 367 } 368 r = bcm_cosq_gport_attach(unit, sched_gport, gport, 8); 369 if (r < 0) { 370 cli_out("%s: bcm_cosq_gport_attach ERROR: port %s: %s\n", 371 ARG_CMD(a), 372 BCM_PORT_NAME(unit, p), 373 bcm_errmsg(r)); 374 if (weights != NULL) { 375 sal_free(weights); 376 weights = NULL; 377 } 378 return CMD_FAIL; 379 } else { 380 cli_out(" Added/Attached GPORT %d (0x%08x) to port %s.\n", 381 sched_gport, sched_gport, BCM_PORT_NAME(unit, p)); 382 } 383 } 384 if (weights != NULL) { 385 sal_free(weights); 386 weights = NULL; 387 } 388 return CMD_OK; 389 } 390 if (sal_strcasecmp(subcmd, "show") == 0) { 391 char *mode_name, *weight_str = "packets"; 392 int weight_max; 393 bcm_pbmp_t temp_pbmp; 394 395 BCM_PBMP_CLEAR(pbmp); 396 parse_table_init(unit, &pt); 397 parse_table_add(&pt, "PortBitMap", PQ_DFL|PQ_PBMP|PQ_BCM, 398 (void *)(0), &pbmp, NULL); 399 400 if (!parseEndOk( a, &pt, &retCode)) { 401 if (c != NULL) { 402 if (weights != NULL) { 403 sal_free(weights); 404 weights = NULL; 405 } 406 return retCode; 407 } 408 } 409 if (BCM_PBMP_IS_NULL(pbmp)) { 410 cli_out("%s: ERROR: must specify valid port bitmap.\n", 411 ARG_CMD(a)); 412 if (weights != NULL) { 413 sal_free(weights); 414 weights = NULL; 415 } 416 return CMD_FAIL; 417 } 418 DPORT_BCM_PBMP_ITER(unit, pbmp, dport, p) { 419 BCM_PBMP_CLEAR(temp_pbmp); 420 SOC_PBMP_PORT_ADD(temp_pbmp, p); 421 422 if (SOC_IS_TOMAHAWK3(unit)) { 423 #if defined(BCM_TOMAHAWK3_SUPPORT) 424 r = bcm_cosq_port_sched_config_get(unit, temp_pbmp, BCM_TH3_COS_COUNT, weights, &weight_arr_size, &mode); 425 #endif 426 } else { 427 r = bcm_cosq_port_sched_get(unit, temp_pbmp, &mode, weights, &delay); 428 } 429 if (r < 0) { 430 goto bcm_err; 431 } 432 cli_out("\n Port %s COS configuration:\n", BCM_PORT_NAME(unit, p)); 433 cli_out(" ------------------------------\n"); 434 435 switch (mode) { 436 case BCM_COSQ_STRICT: 437 mode_name = "strict"; 438 break; 439 case BCM_COSQ_ROUND_ROBIN: 440 mode_name = "simple round-robin"; 441 break; 442 case BCM_COSQ_WEIGHTED_ROUND_ROBIN: 443 mode_name = "weighted round-robin"; 444 break; 445 case BCM_COSQ_WEIGHTED_FAIR_QUEUING: 446 mode_name = "weighted fair queuing"; 447 break; 448 case BCM_COSQ_BOUNDED_DELAY: 449 mode_name = "weighted round-robin with bounded delay"; 450 break; 451 case BCM_COSQ_DEFICIT_ROUND_ROBIN: 452 mode_name = "deficit round-robin"; 453 weight_str = "Kbytes"; 454 break; 455 default: 456 mode_name = NULL; 457 break; 458 } 459 460 if ((r = bcm_cosq_sched_weight_max_get(unit, 461 mode, &weight_max)) < 0) { 462 goto bcm_err; 463 } 464 465 cli_out(" Config (max queues): %d\n", numq); 466 if (mode_name) { 467 cli_out(" Schedule mode: %s\n", mode_name); 468 } 469 470 if (mode == BCM_COSQ_STRICT) { 471 for (cosq = 0; cosq < numq; cosq++) { 472 if (weights[cosq] != BCM_COSQ_WEIGHT_STRICT) { 473 mode = BCM_COSQ_WEIGHTED_ROUND_ROBIN; 474 break; 475 } 476 } 477 } 478 479 if (mode >= 0 && mode != BCM_COSQ_STRICT) { 480 cli_out(" Weighting (in %s):\n", weight_str); 481 482 for (cosq = 0; cosq < numq; cosq++) { 483 if (weight_max == BCM_COSQ_WEIGHT_UNLIMITED) { 484 cli_out(" COSQ %d = %u %s\n", 485 cosq, (uint32) weights[cosq], weight_str); 486 } else { 487 cli_out(" COSQ %d = %d %s\n", 488 cosq, weights[cosq], weight_str); 489 } 490 } 491 BCM_GPORT_LOCAL_SET(gport, p); 492 if (bcm_cosq_gport_sched_get(unit, gport, 8, &mode, &weights[0]) == 0) { 493 cli_out(" COSQ 8 = %d %s (queue for output of S1 scheduler)\n", 494 weights[0], weight_str); 495 } 496 } 497 cli_out(" Priority to queue mappings:\n"); 498 499 for (prio = 0; prio < 8; prio++) { 500 if ((r = bcm_cosq_port_mapping_get(unit, p, prio, &cosq)) < 0) { 501 goto bcm_err; 502 } 503 cli_out(" PRIO %d ==> COSQ %d\n", prio, cosq); 504 } 505 506 /* Only newer XGS3 chips support more than 8 priorities */ 507 for (prio = 8; prio < 16; prio++) { 508 if (bcm_cosq_port_mapping_get(unit, p, prio, &cosq) < 0) { 509 break; 510 } 511 cli_out(" PRIO %d ==> COSQ %d\n", prio, cosq); 512 } 513 514 if (mode == BCM_COSQ_BOUNDED_DELAY) { 515 cli_out(" Bounded delay: %d usec\n", delay); 516 } 517 518 /* Show VLAN cosq config for this port */ 519 (void) bcm_cosq_gport_traverse(unit, _bcm_gport_show_config, INT_TO_PTR(p)); 520 } 521 if (weights != NULL) { 522 sal_free(weights); 523 weights = NULL; 524 } 525 return CMD_OK; 526 } 527 if (sal_strcasecmp(subcmd, "map") == 0) { 528 BCM_PBMP_CLEAR(pbmp); 529 parse_table_init(unit, &pt); 530 parse_table_add(&pt, "PortBitMap", PQ_DFL|PQ_PBMP|PQ_BCM, 531 (void *)(0), &pbmp, NULL); 532 parse_table_add(&pt, "Pri", PQ_DFL|PQ_INT, 533 (void *)(0), &lastPrio, NULL); 534 parse_table_add(&pt, "Queue", PQ_DFL|PQ_INT, 535 (void *)(0), &cosq, NULL); 536 537 if (!parseEndOk( a, &pt, &retCode)) { 538 if (c != NULL) { 539 if (weights != NULL) { 540 sal_free(weights); 541 weights = NULL; 542 } 543 return retCode; 544 } 545 } 546 if (BCM_PBMP_IS_NULL(pbmp)) { 547 cli_out("%s: ERROR: must specify valid port bitmap.\n", 548 ARG_CMD(a)); 549 if (weights != NULL) { 550 sal_free(weights); 551 weights = NULL; 552 } 553 return CMD_FAIL; 554 } else { 555 DPORT_BCM_PBMP_ITER(unit, pbmp, dport, p) { 556 r = bcm_cosq_port_mapping_set(unit, p, lastPrio, cosq); 557 if (r < 0) { 558 cli_out("%s: ERROR: port %s: %s\n", 559 ARG_CMD(a), 560 BCM_PORT_NAME(unit, p), 561 bcm_errmsg(r)); 562 if (weights != NULL) { 563 sal_free(weights); 564 weights = NULL; 565 } 566 return CMD_FAIL; 567 } 568 } 569 } 570 571 if (weights != NULL) { 572 sal_free(weights); 573 weights = NULL; 574 } 575 return CMD_OK; 576 } 577 if (sal_strcasecmp(subcmd, "weight") == 0 || 578 sal_strcasecmp(subcmd, "drr") == 0 || 579 sal_strcasecmp(subcmd, "bounded") == 0 || 580 sal_strcasecmp(subcmd, "delay") == 0 || 581 sal_strcasecmp(subcmd, "strict") == 0 || 582 sal_strcasecmp(subcmd, "simple") == 0 || 583 sal_strcasecmp(subcmd, "fair") == 0) { 584 585 int weight = 0; 586 parse_table_init(unit, &pt); 587 if (sal_strcasecmp(subcmd, "strict") != 0 && 588 sal_strcasecmp(subcmd, "simple") != 0) { 589 parse_table_add(&pt, "Weight", PQ_DFL|PQ_INT, 590 (void *)( 0), &weight, NULL); 591 } 592 parse_table_add(&pt, "Queue", PQ_DFL|PQ_INT, 593 (void *)(0), &cosq, NULL); 594 parse_table_add(&pt, "PortBitMap", PQ_DFL|PQ_PBMP|PQ_BCM, 595 (void *)(0), &pbmp, NULL); 596 parse_table_add(&pt, "Gport", PQ_INT, 597 (void *)BCM_GPORT_INVALID, 598 &sched_gport, 0); 599 600 if (!parseEndOk( a, &pt, &retCode)) { 601 if (weights != NULL) { 602 sal_free(weights); 603 weights = NULL; 604 } 605 return retCode; 606 } 607 608 if (sal_strcasecmp(subcmd, "fair") == 0) { 609 mode = BCM_COSQ_WEIGHTED_FAIR_QUEUING; 610 } else if (sal_strcasecmp(subcmd, "simple") == 0) { 611 mode = BCM_COSQ_ROUND_ROBIN; 612 } else if (sal_strcasecmp(subcmd, "strict") == 0) { 613 mode = BCM_COSQ_STRICT; 614 } else if (sal_strcasecmp(subcmd, "drr") == 0) { 615 mode = BCM_COSQ_DEFICIT_ROUND_ROBIN; 616 } else if (sal_strcasecmp(subcmd, "bounded") == 0) { 617 mode = BCM_COSQ_BOUNDED_DELAY; 618 } else if (sal_strcasecmp(subcmd, "delay") == 0) { 619 mode = BCM_COSQ_BOUNDED_DELAY; 620 } else { 621 mode = BCM_COSQ_WEIGHTED_ROUND_ROBIN; 622 } 623 624 if (sched_gport == BCM_GPORT_INVALID) { 625 if (BCM_PBMP_IS_NULL(pbmp)) { 626 cli_out("%s: ERROR: must specify valid port bitmap.\n", 627 ARG_CMD(a)); 628 if (weights != NULL) { 629 sal_free(weights); 630 weights = NULL; 631 } 632 return CMD_FAIL; 633 } else { 634 DPORT_BCM_PBMP_ITER(unit, pbmp, dport, p) { 635 BCM_GPORT_LOCAL_SET(gport, p); 636 if ((r = bcm_cosq_gport_sched_set(unit, gport, cosq, mode, weight)) < 0) { 637 goto bcm_err; 638 } 639 } 640 } 641 } else { 642 if ((r = bcm_cosq_gport_sched_set(unit, sched_gport, cosq, mode, weight)) < 0) { 643 goto bcm_err; 644 } 645 } 646 if (weights != NULL) { 647 sal_free(weights); 648 weights = NULL; 649 } 650 return CMD_OK; 651 } 652 if (sal_strcasecmp(subcmd, "bandwidth") == 0) { 653 uint32 kbits_sec_min, kbits_sec_max, bw_flags; 654 655 BCM_PBMP_CLEAR(pbmp); 656 discard_color = NULL; 657 parse_table_init(unit, &pt); 658 parse_table_add(&pt, "PortBitMap", PQ_DFL|PQ_PBMP|PQ_BCM, 659 (void *)(0), &pbmp, NULL); 660 parse_table_add(&pt, "Queue", PQ_INT, 661 (void *)( 0), &cosq, NULL); 662 parse_table_add(&pt, "KbpsMIn", PQ_INT, 663 (void *)( 0), &kbits_sec_min, NULL); 664 parse_table_add(&pt, "KbpsMAx", PQ_INT, 665 (void *)( 0), &kbits_sec_max, NULL); 666 parse_table_add(&pt, "Flags", PQ_INT, 667 (void *)( 0), &bw_flags, NULL); 668 parse_table_add(&pt, "Gport", PQ_INT, 669 (void *)BCM_GPORT_INVALID, 670 &sched_gport, 0); 671 672 if (!parseEndOk( a, &pt, &retCode)) { 673 if (weights != NULL) { 674 sal_free(weights); 675 weights = NULL; 676 } 677 return retCode; 678 } 679 680 if (BCM_PBMP_IS_NULL(pbmp)) { 681 cli_out("%s ERROR: empty port bitmap\n", ARG_CMD(a)); 682 if (weights != NULL) { 683 sal_free(weights); 684 weights = NULL; 685 } 686 return CMD_FAIL; 687 } 688 689 if (sched_gport == BCM_GPORT_INVALID) { 690 DPORT_BCM_PBMP_ITER(unit, pbmp, dport, p) { 691 BCM_GPORT_LOCAL_SET(gport, p); 692 if ((r = bcm_cosq_gport_bandwidth_set(unit, gport, cosq, 693 kbits_sec_min, 694 kbits_sec_max, 695 bw_flags)) < 0) { 696 goto bcm_err; 697 } 698 } 699 } else { 700 if ((r = bcm_cosq_gport_bandwidth_set(unit, sched_gport, cosq, 701 kbits_sec_min, 702 kbits_sec_max, 703 bw_flags)) < 0) { 704 goto bcm_err; 705 } 706 } 707 708 if (weights != NULL) { 709 sal_free(weights); 710 weights = NULL; 711 } 712 return CMD_OK; 713 } 714 if (weights != NULL) { 715 sal_free(weights); 716 weights = NULL; 717 } 718 return CMD_OK; 719 } 720 721 if (sal_strcasecmp(subcmd, "show") == 0) { 722 char *mode_name; 723 char *weight_str = "packets"; 724 int weight_max; 725 726 if (c != NULL) { 727 if (weights != NULL) { 728 sal_free(weights); 729 weights = NULL; 730 } 731 return CMD_USAGE; 732 } 733 734 switch (mode) { 735 case BCM_COSQ_STRICT: 736 mode_name = "strict"; 737 break; 738 case BCM_COSQ_ROUND_ROBIN: 739 mode_name = "simple round-robin"; 740 break; 741 case BCM_COSQ_WEIGHTED_ROUND_ROBIN: 742 mode_name = "weighted round-robin"; 743 break; 744 case BCM_COSQ_WEIGHTED_FAIR_QUEUING: 745 mode_name = "weighted fair queuing"; 746 break; 747 case BCM_COSQ_BOUNDED_DELAY: 748 mode_name = "weighted round-robin with bounded delay"; 749 break; 750 case BCM_COSQ_DEFICIT_ROUND_ROBIN: 751 mode_name = "deficit round-robin"; 752 weight_str = "Kbytes"; 753 break; 754 default: 755 mode_name = NULL; 756 break; 757 } 758 759 if ((r = bcm_cosq_sched_weight_max_get(unit, 760 mode, &weight_max)) < 0) { 761 goto bcm_err; 762 } 763 764 cli_out("COS configuration:\n"); 765 cli_out(" Config (max queues): %d\n", numq); 766 if (mode_name) { 767 cli_out(" Schedule mode: %s\n", mode_name); 768 } 769 770 if (mode >= 0 && mode != BCM_COSQ_STRICT) { 771 cli_out(" Weighting (in %s):\n", weight_str); 772 773 for (cosq = 0; cosq < NUM_COS(unit); cosq++) { 774 if (weight_max == BCM_COSQ_WEIGHT_UNLIMITED) { 775 cli_out(" COSQ %d = %u %s\n", 776 cosq, (uint32) weights[cosq], weight_str); 777 } else { 778 cli_out(" COSQ %d = %d %s\n", 779 cosq, weights[cosq], weight_str); 780 } 781 } 782 } 783 784 cli_out(" Priority to queue mappings:\n"); 785 786 for (prio = 0; prio < 8; prio++) { 787 if ((r = bcm_cosq_mapping_get(unit, prio, &cosq)) < 0) { 788 goto bcm_err; 789 } 790 cli_out(" PRIO %d ==> COSQ %d\n", prio, cosq); 791 } 792 793 /* Only newer XGS3 chips support more than 8 priorities */ 794 for (prio = 8; prio < 16; prio++) { 795 if (bcm_cosq_mapping_get(unit, prio, &cosq) < 0) { 796 break; 797 } 798 cli_out(" PRIO %d ==> COSQ %d\n", prio, cosq); 799 } 800 801 if (mode == BCM_COSQ_BOUNDED_DELAY) { 802 cli_out(" Bounded delay: %d usec\n", delay); 803 } 804 805 if (weights != NULL) { 806 sal_free(weights); 807 weights = NULL; 808 } 809 return CMD_OK; 810 } 811 812 if (sal_strcasecmp(subcmd, "config") == 0) { 813 parse_table_init(unit, &pt); 814 parse_table_add(&pt, "Numcos", PQ_DFL|PQ_INT, 815 (void *)( 0), &numq, NULL); 816 817 if (!parseEndOk( a, &pt, &retCode)) { 818 if (weights != NULL) { 819 sal_free(weights); 820 weights = NULL; 821 } 822 return retCode; 823 } 824 825 if ((r = bcm_cosq_config_set(unit, numq)) < 0) { 826 goto bcm_err; 827 } 828 829 if (weights != NULL) { 830 sal_free(weights); 831 weights = NULL; 832 } 833 return CMD_OK; 834 } 835 836 if (sal_strcasecmp(subcmd, "map") == 0) { 837 if ((r = bcm_cosq_mapping_get(unit, lastPrio, &cosq)) < 0) { 838 goto bcm_err; 839 } 840 841 BCM_PBMP_CLEAR(pbmp); 842 parse_table_init(unit, &pt); 843 parse_table_add(&pt, "PortBitMap", PQ_DFL|PQ_PBMP|PQ_BCM, 844 (void *)(0), &pbmp, NULL); 845 parse_table_add(&pt, "Pri", PQ_DFL|PQ_INT, 846 (void *)(0), &lastPrio, NULL); 847 parse_table_add(&pt, "Queue", PQ_DFL|PQ_INT, 848 (void *)(0), &cosq, NULL); 849 850 if (!parseEndOk( a, &pt, &retCode)) { 851 if (weights != NULL) { 852 sal_free(weights); 853 weights = NULL; 854 } 855 return retCode; 856 } 857 858 if (BCM_PBMP_IS_NULL(pbmp)) { 859 if ((r = bcm_cosq_mapping_set(unit, lastPrio, cosq)) < 0) { 860 goto bcm_err; 861 } 862 } else { 863 /* coverity[overrun-local : FALSE] */ 864 DPORT_BCM_PBMP_ITER(unit, pbmp, dport, p) { 865 r = bcm_cosq_port_mapping_set(unit, p, lastPrio, cosq); 866 if (r < 0) { 867 cli_out("%s: ERROR: port %s: %s\n", 868 ARG_CMD(a), 869 BCM_PORT_NAME(unit, p), 870 bcm_errmsg(r)); 871 if (weights != NULL) { 872 sal_free(weights); 873 weights = NULL; 874 } 875 return CMD_FAIL; 876 } 877 } 878 } 879 880 if (weights != NULL) { 881 sal_free(weights); 882 weights = NULL; 883 } 884 return CMD_OK; 885 } 886 887 if (sal_strcasecmp(subcmd, "weight") == 0 || 888 sal_strcasecmp(subcmd, "drr") == 0 || 889 sal_strcasecmp(subcmd, "fair") == 0) { 890 parse_table_init(unit, &pt); 891 parse_table_add(&pt, "W0", PQ_DFL|PQ_INT, 892 (void *)( 0), &weights[0], NULL); 893 parse_table_add(&pt, "W1", PQ_DFL|PQ_INT, 894 (void *)( 0), &weights[1], NULL); 895 parse_table_add(&pt, "W2", PQ_DFL|PQ_INT, 896 (void *)( 0), &weights[2], NULL); 897 parse_table_add(&pt, "W3", PQ_DFL|PQ_INT, 898 (void *)( 0), &weights[3], NULL); 899 parse_table_add(&pt, "W4", PQ_DFL|PQ_INT, 900 (void *)( 0), &weights[4], NULL); 901 parse_table_add(&pt, "W5", PQ_DFL|PQ_INT, 902 (void *)( 0), &weights[5], NULL); 903 parse_table_add(&pt, "W6", PQ_DFL|PQ_INT, 904 (void *)( 0), &weights[6], NULL); 905 parse_table_add(&pt, "W7", PQ_DFL|PQ_INT, 906 (void *)( 0), &weights[7], NULL); 907 if (SOC_IS_TOMAHAWK3(unit)) { 908 #if defined(BCM_TOMAHAWK3_SUPPORT) 909 parse_table_add(&pt, "W8", PQ_DFL|PQ_INT, 910 (void *)( 0), &weights[8], NULL); 911 parse_table_add(&pt, "W9", PQ_DFL|PQ_INT, 912 (void *)( 0), &weights[9], NULL); 913 parse_table_add(&pt, "W10", PQ_DFL|PQ_INT, 914 (void *)( 0), &weights[10], NULL); 915 parse_table_add(&pt, "W11", PQ_DFL|PQ_INT, 916 (void *)( 0), &weights[11], NULL); 917 #endif 918 } 919 920 if (!parseEndOk( a, &pt, &retCode)) { 921 if (weights != NULL) { 922 sal_free(weights); 923 weights = NULL; 924 } 925 return retCode; 926 } 927 928 if (sal_strcasecmp(subcmd, "fair") == 0) { 929 mode = BCM_COSQ_WEIGHTED_FAIR_QUEUING; 930 } else if (sal_strcasecmp(subcmd, "drr") == 0) { 931 mode = BCM_COSQ_DEFICIT_ROUND_ROBIN; 932 } else { 933 mode = BCM_COSQ_WEIGHTED_ROUND_ROBIN; 934 } 935 if (SOC_IS_TOMAHAWK3(unit)) { 936 #if defined(BCM_TOMAHAWK3_SUPPORT) 937 if ((r = bcm_cosq_sched_config_set(unit, mode, BCM_TH3_COS_COUNT, weights)) < 0) { 938 goto bcm_err; 939 } 940 #endif 941 } else { 942 if ((r = bcm_cosq_sched_set(unit, mode, weights, 0)) < 0) { 943 goto bcm_err; 944 } 945 } 946 947 if (weights != NULL) { 948 sal_free(weights); 949 weights = NULL; 950 } 951 return CMD_OK; 952 } 953 954 if (sal_strcasecmp(subcmd, "bounded") == 0 || 955 sal_strcasecmp(subcmd, "delay") == 0) { 956 957 parse_table_init(unit, &pt); 958 parse_table_add(&pt, "W0", PQ_DFL|PQ_INT, 959 (void *)( 0), &weights[0], NULL); 960 parse_table_add(&pt, "W1", PQ_DFL|PQ_INT, 961 (void *)( 0), &weights[1], NULL); 962 parse_table_add(&pt, "W2", PQ_DFL|PQ_INT, 963 (void *)( 0), &weights[2], NULL); 964 parse_table_add(&pt, "W3", PQ_DFL|PQ_INT, 965 (void *)( 0), &weights[3], NULL); 966 parse_table_add(&pt, "W4", PQ_DFL|PQ_INT, 967 (void *)( 0), &weights[4], NULL); 968 parse_table_add(&pt, "W5", PQ_DFL|PQ_INT, 969 (void *)( 0), &weights[5], NULL); 970 parse_table_add(&pt, "W6", PQ_DFL|PQ_INT, 971 (void *)( 0), &weights[6], NULL); 972 parse_table_add(&pt, "W7", PQ_DFL|PQ_INT, 973 (void *)( 0), &weights[7], NULL); 974 if (SOC_IS_TOMAHAWK3(unit)) { 975 #if defined(BCM_TOMAHAWK3_SUPPORT) 976 parse_table_add(&pt, "W8", PQ_DFL|PQ_INT, 977 (void *)( 0), &weights[8], NULL); 978 parse_table_add(&pt, "W9", PQ_DFL|PQ_INT, 979 (void *)( 0), &weights[9], NULL); 980 parse_table_add(&pt, "W10", PQ_DFL|PQ_INT, 981 (void *)( 0), &weights[10], NULL); 982 parse_table_add(&pt, "W11", PQ_DFL|PQ_INT, 983 (void *)( 0), &weights[11], NULL); 984 #endif 985 } 986 parse_table_add(&pt, "Delay", PQ_DFL|PQ_INT, 987 (void *)( 0), &delay, NULL); 988 989 if (!parseEndOk( a, &pt, &retCode)) { 990 if (weights != NULL) { 991 sal_free(weights); 992 weights = NULL; 993 } 994 return retCode; 995 } 996 997 if (SOC_IS_TOMAHAWK3(unit)) { 998 #if defined(BCM_TOMAHAWK3_SUPPORT) 999 if ((r = bcm_cosq_sched_config_set(unit, BCM_COSQ_BOUNDED_DELAY, 1000 BCM_TH3_COS_COUNT, weights)) < 0) { 1001 goto bcm_err; 1002 } 1003 #endif 1004 } else { 1005 if ((r = bcm_cosq_sched_set(unit, 1006 BCM_COSQ_BOUNDED_DELAY, 1007 weights, delay)) < 0) { 1008 goto bcm_err; 1009 } 1010 } 1011 1012 if (weights != NULL) { 1013 sal_free(weights); 1014 weights = NULL; 1015 } 1016 return CMD_OK; 1017 } 1018 1019 if (sal_strcasecmp(subcmd, "discard") == 0) { 1020 uint32 discard_flags = 0; 1021 1022 parse_table_init(unit, &pt); 1023 parse_table_add(&pt, "Enable", PQ_BOOL, 1024 0, &discard_ena, NULL); 1025 parse_table_add(&pt, "CapAvg", PQ_BOOL, 1026 0, &discard_cap_avg, NULL); 1027 1028 if (!parseEndOk( a, &pt, &retCode)) { 1029 if (weights != NULL) { 1030 sal_free(weights); 1031 weights = NULL; 1032 } 1033 return retCode; 1034 } 1035 1036 if (discard_ena) { 1037 discard_flags |= BCM_COSQ_DISCARD_ENABLE; 1038 } 1039 if (discard_cap_avg) { 1040 discard_flags |= BCM_COSQ_DISCARD_CAP_AVERAGE; 1041 } 1042 1043 if ((r = bcm_cosq_discard_set(unit, discard_flags)) < 0) { 1044 goto bcm_err; 1045 } 1046 1047 if (weights != NULL) { 1048 sal_free(weights); 1049 weights = NULL; 1050 } 1051 return CMD_OK; 1052 } 1053 1054 if (sal_strcasecmp(subcmd, "discard_port") == 0) { 1055 uint32 color_flags = 0; 1056 bcm_gport_t sched_gport; 1057 1058 BCM_PBMP_CLEAR(pbmp); 1059 discard_color = NULL; 1060 parse_table_init(unit, &pt); 1061 parse_table_add(&pt, "PortBitMap", PQ_DFL|PQ_PBMP|PQ_BCM, 1062 (void *)(0), &pbmp, NULL); 1063 parse_table_add(&pt, "Queue", PQ_INT, 1064 (void *)( 0), &cosq, NULL); 1065 parse_table_add(&pt, "Color", PQ_STRING, 1066 "green", &discard_color, NULL); 1067 parse_table_add(&pt, "DropSTart", PQ_INT, 1068 (void *)( 0), &discard_start, NULL); 1069 parse_table_add(&pt, "DropSLope", PQ_INT, 1070 (void *)( 0), &discard_slope, NULL); 1071 parse_table_add(&pt, "AvgTime", PQ_INT, 1072 (void *)( 0), &discard_time, NULL); 1073 parse_table_add(&pt, "Gport", PQ_INT, 1074 (void *)BCM_GPORT_INVALID, 1075 &sched_gport, 0); 1076 1077 /* Parse remaining arguments */ 1078 if (0 > parse_arg_eq(a, &pt)) { 1079 cli_out("%s: Error: Invalid option or malformed expression: %s\n", 1080 ARG_CMD(a), ARG_CUR(a)); 1081 parse_arg_eq_done(&pt); 1082 if (weights != NULL) { 1083 sal_free(weights); 1084 weights = NULL; 1085 } 1086 return(CMD_FAIL); 1087 } 1088 1089 if (discard_color != NULL) { 1090 if (!strncmp(discard_color, "r", 1)) { 1091 color_flags = BCM_COSQ_DISCARD_COLOR_RED; 1092 } else if (!strncmp(discard_color, "y", 1)) { 1093 color_flags = BCM_COSQ_DISCARD_COLOR_YELLOW; 1094 } else if (!strncmp(discard_color, "g", 1)) { 1095 color_flags = BCM_COSQ_DISCARD_COLOR_GREEN; 1096 } else { 1097 cli_out("%s ERROR: Invalid color value\n", ARG_CMD(a)); 1098 parse_arg_eq_done(&pt); 1099 if (weights != NULL) { 1100 sal_free(weights); 1101 weights = NULL; 1102 } 1103 return CMD_FAIL; 1104 } 1105 } else { 1106 color_flags = BCM_COSQ_DISCARD_COLOR_GREEN; 1107 } 1108 1109 parse_arg_eq_done(&pt); 1110 1111 if (sched_gport == BCM_GPORT_INVALID) { 1112 if (BCM_PBMP_IS_NULL(pbmp)) { 1113 cli_out("%s ERROR: empty port bitmap\n", ARG_CMD(a)); 1114 if (weights != NULL) { 1115 sal_free(weights); 1116 weights = NULL; 1117 } 1118 return CMD_FAIL; 1119 } 1120 1121 DPORT_BCM_PBMP_ITER(unit, pbmp, dport, p) { 1122 if ((r = bcm_cosq_discard_port_set(unit, p, cosq, color_flags, 1123 discard_start, discard_slope, 1124 discard_time)) < 0) { 1125 goto bcm_err; 1126 } 1127 } 1128 } else { 1129 if ((r = bcm_cosq_discard_port_set(unit, sched_gport, cosq, color_flags, 1130 discard_start, discard_slope, 1131 discard_time)) < 0) { 1132 goto bcm_err; 1133 } 1134 } 1135 1136 if (weights != NULL) { 1137 sal_free(weights); 1138 weights = NULL; 1139 } 1140 return CMD_OK; 1141 } 1142 1143 if (sal_strcasecmp(subcmd, "discard_show") == 0) { 1144 uint32 discard_flags = 0; 1145 bcm_gport_t gport = 0; 1146 bcm_cos_queue_t cosq = 0; 1147 bcm_cosq_gport_discard_t discard; 1148 1149 if (ARG_CNT(a)) { 1150 parse_table_init(unit, &pt); 1151 parse_table_add(&pt, "Gport", PQ_INT, (void *)( 0), &gport, 0); 1152 parse_table_add(&pt, "Queue", PQ_INT, (void *)( 0), &cosq, NULL); 1153 1154 if (!parseEndOk( a, &pt, &retCode)) { 1155 if (weights != NULL) { 1156 sal_free(weights); 1157 weights = NULL; 1158 } 1159 return retCode; 1160 } 1161 1162 if (gport != 0) { 1163 cli_out(" Discard configuration GPORT=%d (%08x), COSQ %d\n", 1164 gport, gport, cosq); 1165 1166 discard.flags = BCM_COSQ_DISCARD_COLOR_GREEN | BCM_COSQ_DISCARD_BYTES; 1167 if (bcm_cosq_gport_discard_get(unit, gport, cosq, &discard) == 0) { 1168 cli_out(" GREEN (bytes) : Min %d, Max %d, Gain %d, DropProb %d, Ena %d, Cap %d\n", 1169 discard.min_thresh, discard.max_thresh, discard.gain, 1170 discard.drop_probability, 1171 (discard.flags & BCM_COSQ_DISCARD_ENABLE) ? 1 : 0, 1172 (discard.flags & BCM_COSQ_DISCARD_CAP_AVERAGE) ? 1 : 0); 1173 } 1174 discard.flags = BCM_COSQ_DISCARD_COLOR_YELLOW | BCM_COSQ_DISCARD_BYTES; 1175 if (bcm_cosq_gport_discard_get(unit, gport, cosq, &discard) == 0) { 1176 cli_out(" YELLOW (bytes) : Min %d, Max %d, Gain %d, DropProb %d, Ena %d, Cap %d\n", 1177 discard.min_thresh, discard.max_thresh, discard.gain, 1178 discard.drop_probability, 1179 (discard.flags & BCM_COSQ_DISCARD_ENABLE) ? 1 : 0, 1180 (discard.flags & BCM_COSQ_DISCARD_CAP_AVERAGE) ? 1 : 0); 1181 } 1182 discard.flags = BCM_COSQ_DISCARD_COLOR_RED | BCM_COSQ_DISCARD_BYTES; 1183 if (bcm_cosq_gport_discard_get(unit, gport, cosq, &discard) == 0) { 1184 cli_out(" RED (bytes) : Min %d, Max %d, Gain %d, DropProb %d, Ena %d, Cap %d\n", 1185 discard.min_thresh, discard.max_thresh, discard.gain, 1186 discard.drop_probability, 1187 (discard.flags & BCM_COSQ_DISCARD_ENABLE) ? 1 : 0, 1188 (discard.flags & BCM_COSQ_DISCARD_CAP_AVERAGE) ? 1 : 0); 1189 } 1190 discard.flags = BCM_COSQ_DISCARD_COLOR_GREEN | BCM_COSQ_DISCARD_PACKETS; 1191 if (bcm_cosq_gport_discard_get(unit, gport, cosq, &discard) == 0) { 1192 cli_out("\n GREEN ( pkts) : Min %d, Max %d, Gain %d, DropProb %d, Ena %d, Cap %d\n", 1193 discard.min_thresh, discard.max_thresh, discard.gain, 1194 discard.drop_probability, 1195 (discard.flags & BCM_COSQ_DISCARD_ENABLE) ? 1 : 0, 1196 (discard.flags & BCM_COSQ_DISCARD_CAP_AVERAGE) ? 1 : 0); 1197 } 1198 discard.flags = BCM_COSQ_DISCARD_COLOR_YELLOW | BCM_COSQ_DISCARD_PACKETS; 1199 if (bcm_cosq_gport_discard_get(unit, gport, cosq, &discard) == 0) { 1200 cli_out(" YELLOW ( pkts) : Min %d, Max %d, Gain %d, DropProb %d, Ena %d, Cap %d\n", 1201 discard.min_thresh, discard.max_thresh, discard.gain, 1202 discard.drop_probability, 1203 (discard.flags & BCM_COSQ_DISCARD_ENABLE) ? 1 : 0, 1204 (discard.flags & BCM_COSQ_DISCARD_CAP_AVERAGE) ? 1 : 0); 1205 } 1206 discard.flags = BCM_COSQ_DISCARD_COLOR_RED | BCM_COSQ_DISCARD_PACKETS; 1207 if (bcm_cosq_gport_discard_get(unit, gport, cosq, &discard) == 0) { 1208 cli_out(" RED ( pkts) : Min %d, Max %d, Gain %d, DropProb %d, Ena %d, Cap %d\n", 1209 discard.min_thresh, discard.max_thresh, discard.gain, 1210 discard.drop_probability, 1211 (discard.flags & BCM_COSQ_DISCARD_ENABLE) ? 1 : 0, 1212 (discard.flags & BCM_COSQ_DISCARD_CAP_AVERAGE) ? 1 : 0); 1213 } 1214 if (weights != NULL) { 1215 sal_free(weights); 1216 weights = NULL; 1217 } 1218 return CMD_OK; 1219 } 1220 } 1221 1222 if ((r = bcm_cosq_discard_get(unit, &discard_flags)) < 0) { 1223 if (r != BCM_E_UNAVAIL) { 1224 goto bcm_err; 1225 } 1226 } 1227 1228 cli_out(" Discard (WRED): discard %s, cap-average %s\n", 1229 (discard_flags & BCM_COSQ_DISCARD_ENABLE) ? 1230 "enabled" : "disabled", 1231 (discard_flags & BCM_COSQ_DISCARD_CAP_AVERAGE) ? 1232 "enabled" : "disabled"); 1233 1234 BCM_PBMP_ASSIGN(pbmp, pcfg.port); 1235 cli_out(" Discard (WRED) port configuration:\n"); 1236 cli_out(" | | gr | gr | gr | ye |" 1237 " ye | ye | re | re | re\n"); 1238 cli_out(" port | q | strt | sl | time | strt |" 1239 " sl | time | strt | sl | time\n"); 1240 DPORT_BCM_PBMP_ITER(unit, pbmp, dport, p) { 1241 cli_out(" -----+---+--------+----+-------+--------+" 1242 "----+-------+--------+----+-------\n"); 1243 for (cosq = 0; cosq < numq; cosq++) { 1244 if ((r = bcm_cosq_discard_port_get(unit, p, cosq, 1245 BCM_COSQ_DISCARD_COLOR_GREEN, 1246 &discard_start, &discard_slope, 1247 &discard_time)) < 0) { 1248 goto bcm_err; 1249 } 1250 cli_out(" %4s | %d | %6d | %2d | %5d ", 1251 BCM_PORT_NAME(unit, p), cosq, discard_start, 1252 discard_slope, discard_time); 1253 if ((r = bcm_cosq_discard_port_get(unit, p, cosq, 1254 BCM_COSQ_DISCARD_COLOR_YELLOW, 1255 &discard_start, &discard_slope, 1256 &discard_time)) < 0) { 1257 cli_out("| ---- | -- | ----- "); 1258 } else { 1259 cli_out("| %6d | %2d | %5d ", 1260 discard_start, discard_slope, discard_time); 1261 } 1262 if ((r = bcm_cosq_discard_port_get(unit, p, cosq, 1263 BCM_COSQ_DISCARD_COLOR_RED, 1264 &discard_start, &discard_slope, 1265 &discard_time)) < 0) { 1266 goto bcm_err; 1267 } 1268 cli_out("| %6d | %2d | %5d\n", 1269 discard_start, discard_slope, discard_time); 1270 } 1271 1272 /* Show VLAN cosq discard settings for this port */ 1273 (void) bcm_cosq_gport_traverse(unit, _bcm_gport_show_discard, INT_TO_PTR(p)); 1274 } 1275 1276 if (weights != NULL) { 1277 sal_free(weights); 1278 weights = NULL; 1279 } 1280 return CMD_OK; 1281 } 1282 1283 if (sal_strcasecmp(subcmd, "discard_gport") == 0) { 1284 uint32 color_flags = 0; 1285 uint32 mode_flags = 0; 1286 bcm_gport_t sched_gport; 1287 bcm_cosq_gport_discard_t discard; 1288 1289 bcm_cosq_gport_discard_t_init(&discard); 1290 discard_color = NULL; 1291 parse_table_init(unit, &pt); 1292 parse_table_add(&pt, "GPort", PQ_INT, 1293 (void *)BCM_GPORT_INVALID, 1294 &sched_gport, 0); 1295 parse_table_add(&pt, "Queue", PQ_INT, 1296 (void *)( 0), &cosq, NULL); 1297 parse_table_add(&pt, "Color", PQ_STRING, 1298 "green", &discard_color, NULL); 1299 parse_table_add(&pt, "DropStart", PQ_INT, 1300 (void *)( 0), &discard_start, NULL); 1301 parse_table_add(&pt, "DropEnd", PQ_INT, 1302 (void *)( 0), &discard_end, NULL); 1303 parse_table_add(&pt, "DropProbability", PQ_INT, 1304 (void *)( 0), &drop_prob, NULL); 1305 parse_table_add(&pt, "GAin", PQ_INT, 1306 (void *)( 0), &gain, NULL); 1307 parse_table_add(&pt, "Enable", PQ_BOOL, 1308 0, &discard_ena, NULL); 1309 parse_table_add(&pt, "CapAvg", PQ_BOOL, 1310 0, &discard_cap_avg, NULL); 1311 parse_table_add(&pt, "Mode", PQ_STRING, 1312 "byte", &discard_mode, NULL); 1313 1314 /* Parse remaining arguments */ 1315 if (0 > parse_arg_eq(a, &pt)) { 1316 cli_out("%s: Error: Invalid option or malformed expression: %s\n", 1317 ARG_CMD(a), ARG_CUR(a)); 1318 parse_arg_eq_done(&pt); 1319 if (weights != NULL) { 1320 sal_free(weights); 1321 weights = NULL; 1322 } 1323 return(CMD_FAIL); 1324 } 1325 1326 if (discard_mode != NULL) { 1327 if (!strncmp(discard_mode, "b", 1)) { 1328 mode_flags = BCM_COSQ_DISCARD_BYTES; 1329 } else if (!strncmp(discard_mode, "p", 1)) { 1330 mode_flags = BCM_COSQ_DISCARD_PACKETS; 1331 } else { 1332 cli_out("%s ERROR: Invalid mode value\n", ARG_CMD(a)); 1333 parse_arg_eq_done(&pt); 1334 if (weights != NULL) { 1335 sal_free(weights); 1336 weights = NULL; 1337 } 1338 return CMD_FAIL; 1339 } 1340 } else { 1341 mode_flags = BCM_COSQ_DISCARD_BYTES; 1342 } 1343 1344 if (discard_color != NULL) { 1345 if (!strncmp(discard_color, "r", 1)) { 1346 color_flags = BCM_COSQ_DISCARD_COLOR_RED; 1347 } else if (!strncmp(discard_color, "y", 1)) { 1348 color_flags = BCM_COSQ_DISCARD_COLOR_YELLOW; 1349 } else if (!strncmp(discard_color, "g", 1)) { 1350 color_flags = BCM_COSQ_DISCARD_COLOR_GREEN; 1351 } else { 1352 cli_out("%s ERROR: Invalid color value\n", ARG_CMD(a)); 1353 parse_arg_eq_done(&pt); 1354 if (weights != NULL) { 1355 sal_free(weights); 1356 weights = NULL; 1357 } 1358 return CMD_FAIL; 1359 } 1360 } else { 1361 color_flags = BCM_COSQ_DISCARD_COLOR_GREEN; 1362 } 1363 if (discard_ena) { 1364 color_flags |= BCM_COSQ_DISCARD_ENABLE; 1365 } 1366 if (discard_cap_avg) { 1367 color_flags |= BCM_COSQ_DISCARD_CAP_AVERAGE; 1368 } 1369 1370 parse_arg_eq_done(&pt); 1371 1372 discard.flags = color_flags | mode_flags; 1373 discard.min_thresh = discard_start; 1374 discard.max_thresh = discard_end; 1375 discard.drop_probability = drop_prob; 1376 discard.gain = gain; 1377 if ((r = bcm_cosq_gport_discard_set(unit, sched_gport, cosq, &discard)) < 0) { 1378 goto bcm_err; 1379 } 1380 1381 if (weights != NULL) { 1382 sal_free(weights); 1383 weights = NULL; 1384 } 1385 return CMD_OK; 1386 } 1387 1388 if (sal_strcasecmp(subcmd, "bandwidth") == 0) { 1389 uint32 kbits_sec_min, kbits_sec_max, bw_flags; 1390 1391 BCM_PBMP_CLEAR(pbmp); 1392 discard_color = NULL; 1393 parse_table_init(unit, &pt); 1394 parse_table_add(&pt, "PortBitMap", PQ_DFL|PQ_PBMP|PQ_BCM, 1395 (void *)(0), &pbmp, NULL); 1396 parse_table_add(&pt, "Queue", PQ_INT, 1397 (void *)( 0), &cosq, NULL); 1398 parse_table_add(&pt, "KbpsMIn", PQ_INT, 1399 (void *)( 0), &kbits_sec_min, NULL); 1400 parse_table_add(&pt, "KbpsMAx", PQ_INT, 1401 (void *)( 0), &kbits_sec_max, NULL); 1402 parse_table_add(&pt, "Flags", PQ_INT, 1403 (void *)( 0), &bw_flags, NULL); 1404 1405 if (!parseEndOk( a, &pt, &retCode)) { 1406 if (weights != NULL) { 1407 sal_free(weights); 1408 weights = NULL; 1409 } 1410 return retCode; 1411 } 1412 1413 if (BCM_PBMP_IS_NULL(pbmp)) { 1414 cli_out("%s ERROR: empty port bitmap\n", ARG_CMD(a)); 1415 if (weights != NULL) { 1416 sal_free(weights); 1417 weights = NULL; 1418 } 1419 return CMD_FAIL; 1420 } 1421 1422 DPORT_BCM_PBMP_ITER(unit, pbmp, dport, p) { 1423 if ((r = bcm_cosq_port_bandwidth_set(unit, p, cosq, 1424 kbits_sec_min, 1425 kbits_sec_max, 1426 bw_flags)) < 0) { 1427 goto bcm_err; 1428 } 1429 } 1430 1431 if (weights != NULL) { 1432 sal_free(weights); 1433 weights = NULL; 1434 } 1435 return CMD_OK; 1436 } 1437 1438 if (sal_strcasecmp(subcmd, "bandwidth_show") == 0) { 1439 uint32 kbits_sec_min, kbits_sec_max, bw_flags; 1440 bcm_gport_t gport; 1441 1442 if (c != NULL) { 1443 if (weights != NULL) { 1444 sal_free(weights); 1445 weights = NULL; 1446 } 1447 return CMD_USAGE; 1448 } 1449 1450 BCM_PBMP_ASSIGN(pbmp, pcfg.port); 1451 cli_out(" COSQ bandwith configuration:\n"); 1452 1453 cli_out(" port | q | KbpsMin | KbpsMax | Flags\n"); 1454 1455 DPORT_BCM_PBMP_ITER(unit, pbmp, dport, p) { 1456 cli_out(" -----+---+----------+----------+-------\n"); 1457 for (cosq = 0; cosq < numq; cosq++) { 1458 if ((r = bcm_cosq_port_bandwidth_get(unit, p, cosq, 1459 &kbits_sec_min, &kbits_sec_max, &bw_flags)) < 0) { 1460 goto bcm_err; 1461 } 1462 cli_out(" %4s | %d | %8d | %8d | %6d\n", 1463 BCM_PORT_NAME(unit, p), cosq, kbits_sec_min, 1464 kbits_sec_max, bw_flags); 1465 } 1466 BCM_GPORT_LOCAL_SET(gport, p); 1467 if ((r = bcm_cosq_gport_bandwidth_get(unit, gport, 8, 1468 &kbits_sec_min, &kbits_sec_max, &bw_flags)) == 0) { 1469 cli_out(" %4s | %d | %8d | %8d | %6d\n", 1470 BCM_PORT_NAME(unit, p), 8, kbits_sec_min, 1471 kbits_sec_max, bw_flags); 1472 } 1473 1474 /* Show VLAN cosq bandwidth for this port */ 1475 (void) bcm_cosq_gport_traverse(unit, _bcm_gport_show_bandwidth, INT_TO_PTR(p)); 1476 } 1477 if (weights != NULL) { 1478 sal_free(weights); 1479 weights = NULL; 1480 } 1481 return CMD_OK; 1482 } 1483 1484 if (weights != NULL) { 1485 sal_free(weights); 1486 weights = NULL; 1487 } 1488 return CMD_USAGE; 1489 1490 bcm_err: 1491 cli_out("%s: ERROR: %s\n", ARG_CMD(a), bcm_errmsg(r)); 1492 if (weights != NULL) { 1493 sal_free(weights); 1494 weights = NULL; 1495 } 1496 return CMD_FAIL; 1497 }