rate.c (12675B)
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 * Rate CLI commands 8 * 9 * Note: the "rate" controls Storm Control, as opposed to packet rate 10 * control (bcm_port_rate_*). 11 */ 12 13 #include <appl/diag/system.h> 14 #include <appl/diag/parse.h> 15 #include <appl/diag/dport.h> 16 #include <shared/bsl.h> 17 #include <bcm/init.h> 18 #include <bcm/error.h> 19 #include <bcm/rate.h> 20 #include <bcm/debug.h> 21 22 #include <soc/drv.h> 23 #define _DFT_MAGIC_NUMBER -123456798 24 25 /* 26 * Manage packet rate controls 27 */ 28 cmd_result_t 29 cmd_esw_rate(int unit, args_t *a) 30 { 31 int limit = _DFT_MAGIC_NUMBER; /* magic number */ 32 int fRateBCast; 33 int fRateMCast; 34 int fRateDLF; 35 int fmask = 0; 36 int flags = 0; 37 int r; 38 parse_table_t pt; 39 bcm_pbmp_t pbmp; 40 bcm_port_config_t pcfg; 41 int limitGet = FALSE; 42 int bRateSet, mRateSet,dlfRateSet; 43 int bRateFlGet, mRateFlGet, dlfRateFlGet; 44 int bRateLmGet, mRateLmGet, dlfRateLmGet; 45 int displayOnly = 0; 46 soc_port_t p, dport; 47 48 if (!sh_check_attached(ARG_CMD(a), unit)) { 49 return CMD_FAIL; 50 } 51 52 if (bcm_port_config_get(unit, &pcfg) != BCM_E_NONE) { 53 cli_out("%s: Error: bcm ports not initialized\n", ARG_CMD(a)); 54 return CMD_FAIL; 55 } 56 57 pbmp = pcfg.all; /* All ports by default */ 58 limit = _DFT_MAGIC_NUMBER; 59 fRateBCast = _DFT_MAGIC_NUMBER; 60 fRateMCast = _DFT_MAGIC_NUMBER; 61 fRateDLF = _DFT_MAGIC_NUMBER; 62 63 if (ARG_CNT(a)) { 64 parse_table_init(unit, &pt); 65 parse_table_add(&pt, "PortBitMap", PQ_DFL|PQ_PBMP|PQ_BCM, 66 (void *)0, &pbmp, 0); 67 parse_table_add(&pt, "Limit", PQ_DFL|PQ_HEX, 68 INT_TO_PTR(limit) , &limit, 0); 69 parse_table_add(&pt, "Bcast", PQ_DFL|PQ_BOOL, 70 (void *)0, &fRateBCast, 0); 71 parse_table_add(&pt, "Mcast", PQ_BOOL, 72 INT_TO_PTR(fRateMCast), &fRateMCast, 0); 73 parse_table_add(&pt, "Dlf", PQ_DFL|PQ_BOOL, 74 INT_TO_PTR(fRateDLF), &fRateDLF, 0); 75 76 if (parse_arg_eq(a, &pt) < 0) { 77 cli_out("%s: Error: Unknown option: %s\n", ARG_CMD(a), ARG_CUR(a)); 78 parse_arg_eq_done(&pt); 79 return(CMD_FAIL); 80 } 81 parse_arg_eq_done(&pt); 82 fmask = flags = 0; 83 84 /* Verify what is being changed */ 85 if (fRateBCast != _DFT_MAGIC_NUMBER) { 86 fmask |= BCM_RATE_BCAST; 87 if (fRateBCast == TRUE) { 88 flags |= BCM_RATE_BCAST; 89 } 90 } 91 if (fRateMCast != _DFT_MAGIC_NUMBER) { 92 fmask |= BCM_RATE_MCAST; 93 if (fRateMCast == TRUE) { 94 flags |= BCM_RATE_MCAST; 95 } 96 } 97 if (fRateDLF != _DFT_MAGIC_NUMBER) { 98 fmask |= BCM_RATE_DLF; 99 if (fRateDLF == TRUE) { 100 flags |= BCM_RATE_DLF; 101 } 102 } 103 if (limit < 0 && limit != _DFT_MAGIC_NUMBER) { 104 cli_out("Error: Negative rate limit: %d is not " 105 "allowed\n", (int)limit); 106 } 107 108 /* Check whether original value shall be read back */ 109 if (fmask == 0 && limit == _DFT_MAGIC_NUMBER) { 110 /* only PBM is specified */ 111 displayOnly = TRUE; 112 } else if (limit == _DFT_MAGIC_NUMBER) { 113 limitGet = TRUE; 114 } 115 116 } else { 117 displayOnly = TRUE; 118 } 119 120 if (displayOnly) { 121 cli_out("Current settings:\n"); 122 123 DPORT_BCM_PBMP_ITER(unit, pbmp, dport, p) { 124 cli_out("%4s:",BCM_PORT_NAME(unit, p)); 125 if ((r = bcm_rate_bcast_get(unit, &limit, &flags, p)) < 0) { 126 cli_out(" Bcast = UNKNOWN, %s;", bcm_errmsg(r)); 127 } else if (flags == BCM_RATE_BCAST) { 128 cli_out(" Bcast= TRUE,Limit=%d;", limit); 129 } else { 130 cli_out(" Bcast=FALSE ;"); 131 } 132 if ((r = bcm_rate_mcast_get(unit, &limit, &flags, p)) < 0) { 133 cli_out(" Mcast=UNKNOWN, %s;", bcm_errmsg(r)); 134 } else if (flags == BCM_RATE_MCAST) { 135 cli_out(" Mcast= TRUE,Limit=%d;", limit); 136 } else { 137 cli_out(" Mcast=FALSE ;"); 138 } 139 if ((r = bcm_rate_dlfbc_get(unit, &limit, &flags, p)) < 0) { 140 cli_out(" Dlf=UNKNOWN, %s;", bcm_errmsg(r)); 141 } else if (flags == BCM_RATE_DLF) { 142 cli_out(" Dlfbc= TRUE,Limit=%d;", limit); 143 } else { 144 cli_out(" Dlfbc=FALSE ;"); 145 } 146 cli_out("\n"); 147 } 148 return(CMD_OK); 149 } 150 151 bRateSet = mRateSet = dlfRateSet = FALSE; 152 bRateFlGet = mRateFlGet = dlfRateFlGet = FALSE; 153 bRateLmGet = mRateLmGet = dlfRateLmGet = FALSE; 154 fRateBCast = fRateMCast = fRateDLF = 0; 155 156 if (!fmask) { 157 if (limitGet == FALSE) { 158 /* only new limit specified */ 159 bRateSet = mRateSet = dlfRateSet = TRUE; 160 bRateFlGet = mRateFlGet = dlfRateFlGet = TRUE; 161 } 162 } else { 163 if ((fmask & BCM_RATE_BCAST)) { 164 bRateSet = TRUE; 165 fRateBCast = flags & BCM_RATE_BCAST; 166 if (fRateBCast && limitGet) { 167 bRateLmGet = TRUE; 168 } 169 } 170 if ((fmask & BCM_RATE_MCAST)) { 171 mRateSet = TRUE; 172 fRateMCast = flags & BCM_RATE_MCAST; 173 if (fRateMCast && limitGet) { 174 mRateLmGet = TRUE; 175 } 176 } 177 if ((fmask & BCM_RATE_DLF)) { 178 dlfRateSet = TRUE; 179 fRateDLF = flags & BCM_RATE_DLF; 180 if (fRateDLF && limitGet) { 181 dlfRateLmGet = TRUE; 182 } 183 } 184 } 185 186 /* Set new config in ports */ 187 /* coverity[overrun-local] */ 188 DPORT_BCM_PBMP_ITER(unit, pbmp, dport, p) { 189 /* Brocast meter */ 190 if (bRateSet) { 191 int limitPro, flagPro; 192 int oriLimit, oriFlag; 193 int r = 0; 194 195 if (bRateFlGet || bRateLmGet) { 196 if ((r = bcm_rate_bcast_get(unit, &oriLimit, &oriFlag, p)) < 0) { 197 cli_out("%4s Error: can not get Brocast limit info: %s\n", 198 BCM_PORT_NAME(unit, p), bcm_errmsg(r)); 199 } 200 } 201 202 limitPro = (!r && bRateLmGet)? oriLimit : limit; 203 flagPro = (!r && bRateFlGet)? oriFlag : fRateBCast; 204 205 if (!r && (r = bcm_rate_bcast_set(unit, 206 limitPro, flagPro, p)) < 0) { 207 cli_out("%4s Error: can not set Broadcast rate: %s\n", 208 BCM_PORT_NAME(unit, p), bcm_errmsg(r)); 209 } 210 } 211 /* Mcast meter control */ 212 if (mRateSet) { 213 int limitPro, flagPro; 214 int oriLimit, oriFlag; 215 int r = 0; 216 217 if (mRateFlGet || mRateLmGet) { 218 if ((r = bcm_rate_mcast_get(unit, &oriLimit, &oriFlag, p)) < 0) { 219 cli_out("%4s Error: can not get Mcast limit info: %s\n", 220 BCM_PORT_NAME(unit, p), bcm_errmsg(r)); 221 } 222 } 223 224 limitPro = (!r && mRateLmGet)? oriLimit : limit; 225 flagPro = (!r && mRateFlGet)? oriFlag : fRateMCast; 226 227 if (!r && (r = bcm_rate_mcast_set(unit, 228 limitPro, flagPro, p)) < 0) { 229 cli_out("%4s Error: can not set Mcast rate: %s\n", 230 BCM_PORT_NAME(unit, p), bcm_errmsg(r)); 231 } 232 } 233 /* Dlf meter */ 234 if (dlfRateSet) { 235 int limitPro, flagPro; 236 int oriLimit, oriFlag; 237 int r = 0; 238 239 if (dlfRateFlGet || dlfRateLmGet) { 240 if ((r = bcm_rate_dlfbc_get(unit, &oriLimit, &oriFlag, p)) < 0) { 241 cli_out("%4s Error: can not get DLF limit info: %s\n", 242 BCM_PORT_NAME(unit, p), bcm_errmsg(r)); 243 } 244 } 245 246 limitPro = (!r && dlfRateLmGet)? oriLimit : limit; 247 flagPro = (!r && dlfRateFlGet)? oriFlag : fRateDLF; 248 249 if (!r && (r = bcm_rate_dlfbc_set(unit, 250 limitPro, flagPro, p)) < 0) { 251 cli_out("%4s Error: can not set DLF rate: %s\n", 252 BCM_PORT_NAME(unit, p), bcm_errmsg(r)); 253 } 254 } 255 } 256 return CMD_OK; 257 } 258 259 /* 260 * Function: 261 * cmd_bw_rate 262 * Purpose: 263 * Set/display of bandwidth rate mitiring limits. 264 * Parameters: 265 * unit - SOC unit # 266 * args - pointer to comand line arguments 267 * Returns: 268 * CMD_OK/CMD_FAIL 269 */ 270 char cmd_bw_rate_usage[] = 271 "Set/Display port bandwidth rate limiting.\n" 272 "Parameters: <pbm> flags rate max_burst\n\t" 273 " flag is one of the bcast | mcast | dlf\n\t" 274 " rate and max_burst are values in kilobits (1000 bits) per second\n"; 275 276 cmd_result_t 277 cmd_bw_rate(int unit, args_t *a) 278 { 279 bcm_pbmp_t pbm; 280 bcm_port_config_t pcfg; 281 soc_port_t p, dport; 282 int flags = 0; 283 int rv; 284 uint32 rate = 0xFFFFFFFF; 285 uint32 burst = 0xFFFFFFFF; 286 char *c; 287 288 289 if (!sh_check_attached(ARG_CMD(a), unit)) { 290 return CMD_FAIL; 291 } 292 293 /* Check for metering capabilities */ 294 if (! soc_feature(unit, soc_feature_storm_control)) { 295 cli_out("%s: Error: bandwidth limit unavailable for this device\n", 296 ARG_CMD(a)); 297 return CMD_OK; 298 } 299 300 if (bcm_port_config_get(unit, &pcfg) != BCM_E_NONE) { 301 cli_out("%s: Error: bcm ports not initialized\n", ARG_CMD(a)); 302 return CMD_FAIL; 303 } 304 305 if ((c = ARG_GET(a)) == NULL) { 306 cli_out("%s: Error: unspecified port bitmap: %s\n", 307 ARG_CMD(a), c); 308 return CMD_FAIL; 309 } else if (parse_bcm_pbmp(unit, c, &pbm) < 0) { 310 cli_out("%s: Error: unrecognized port bitmap: %s\n", 311 ARG_CMD(a), c); 312 return CMD_FAIL; 313 } 314 315 /* Apply PortRate only to those ports which support it */ 316 BCM_PBMP_AND(pbm, pcfg.e); 317 if (BCM_PBMP_IS_NULL(pbm)) { 318 cli_out("No ports specified.\n"); 319 return CMD_OK; 320 } 321 322 /* retrieving the flags */ 323 if ((c = ARG_GET(a)) != NULL) { 324 /* Get user provided flag */ 325 if (0 == sal_strncasecmp(c, "bcast", sal_strlen(c))){ 326 flags = BCM_RATE_BCAST; 327 } else if (0 == sal_strncasecmp(c, "mcast", sal_strlen(c))) { 328 flags = BCM_RATE_MCAST; 329 } else if (0 == sal_strncasecmp(c, "dlf", sal_strlen(c))) { 330 flags = BCM_RATE_DLF; 331 } else { 332 cli_out("%s: Error: unrecognized rate type: %s\n", 333 ARG_CMD(a), c); 334 return CMD_FAIL; 335 } 336 } 337 else { 338 cli_out("%s: Error: missing rate type: %s need bcast or mcast or dlf\n", 339 ARG_CMD(a), c); 340 return CMD_FAIL; 341 } 342 343 /* Set or get */ 344 if ((c = ARG_GET(a)) == NULL) { /* Get part */ 345 /* coverity[overrun-local] */ 346 DPORT_BCM_PBMP_ITER(unit, pbm, dport, p) { 347 rv = bcm_rate_bandwidth_get(unit, p, flags, &rate, &burst); 348 if (rv < 0 ) { 349 cli_out("%s port %s: ERROR: bcm_rate_bandwidth_get: " 350 "%s\n", 351 ARG_CMD(a), BCM_PORT_NAME(unit, p), bcm_errmsg(rv)); 352 return CMD_FAIL; 353 } 354 if (rate) { 355 cli_out("%4s:", BCM_PORT_NAME(unit, p)); 356 if (rate < 64) { 357 cli_out("\tBandwidth meter: ? kbps ? kbits max burst.\n"); 358 } else { 359 cli_out("\tBandwidth meter: " 360 "%8d kbps %8d kbits max burst.\n", 361 rate, burst); 362 } 363 } 364 } 365 } else { /* Set Part */ 366 rate = parse_integer(c); 367 if ((c = ARG_GET(a)) != NULL) { 368 burst = parse_integer(c); 369 } else { 370 cli_out("%s: Error: missing port burst size\n", 371 ARG_CMD(a)); 372 return CMD_FAIL; 373 } 374 DPORT_BCM_PBMP_ITER(unit, pbm, dport, p) { 375 rv = bcm_rate_bandwidth_set(unit, p, flags, rate, burst); 376 if (rv < 0) { 377 cli_out("%s: ERROR: bcm_port_rate_ingress_set: %s\n", 378 ARG_CMD(a), bcm_errmsg(rv)); 379 return CMD_FAIL; 380 } 381 } 382 } 383 384 return CMD_OK; 385 } 386