openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

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 }