meter.c (26424B)
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 * File: meter.c 8 * Purpose: Firebolt placeholder for metering, FP metering. 9 */ 10 11 #include <sal/types.h> 12 #include <sal/core/libc.h> 13 14 #include <shared/bitop.h> 15 16 #include <soc/mem.h> 17 #include <soc/debug.h> 18 #include <soc/cm.h> 19 #include <soc/counter.h> 20 #include <soc/drv.h> 21 #include <soc/register.h> 22 #include <soc/memory.h> 23 24 #include <bcm/error.h> 25 26 #include <bcm_int/esw/mbcm.h> 27 #include <bcm_int/esw/firebolt.h> 28 29 30 #define FB_NUM_BUCKET_SIZES 16 31 #define FB_NUM_VALID_BUCKET_SIZES 14 32 33 /* For Firebolt, every token in the bucket is worth one bit. */ 34 /* For metering purposes, kbits means 1000 bits. */ 35 static uint32 fb_bucket_settings[FB_NUM_BUCKET_SIZES] = { 36 0, /* Disabled */ 37 0x00008000/1000, /* 32K tokens */ 38 0x00010000/1000, /* 64K tokens */ 39 0x00020000/1000, /* 128K tokens */ 40 0x00040000/1000, /* 256K tokens */ 41 0x00080000/1000, /* 512K tokens */ 42 0x00100000/1000, /* 1M tokens */ 43 0x00200000/1000, /* 2M tokens */ 44 0x00400000/1000, /* 4M tokens */ 45 0x00800000/1000, /* 8M tokens */ 46 0x01000000/1000, /* 16M tokens */ 47 0x02000000/1000, /* 32M tokens */ 48 0x04000000/1000, /* 64M tokens */ 49 0x08000000/1000, /* 128M tokens */ 50 0, /* N/A */ 51 0 /* N/A */ 52 }; 53 54 /* 55 * Function: 56 * _bcm_fb_kbits_to_bucketsize 57 * Description: 58 * Routine that converts desired burst size into Firebolt style 59 * leaky bucketsize register value. 60 * Parameters: 61 * kbits_burst - Desired size of maximum burst traffic 62 * Returns: 63 * Register bits for BUCKETSIZEf field. 64 * Notes: 65 * None. 66 */ 67 68 uint8 69 _bcm_fb_kbits_to_bucketsize(uint32 kbits_burst) 70 { 71 uint8 i; 72 for (i=0; i< FB_NUM_VALID_BUCKET_SIZES; i++) { 73 if (kbits_burst <= fb_bucket_settings[i]) 74 break; 75 } 76 if (i == FB_NUM_VALID_BUCKET_SIZES) 77 i--; 78 return i; 79 } 80 81 /* 82 * Function: 83 * _bcm_fb_bucketsize_to_kbits 84 * Description: 85 * Routine that converts Firebolt style leaky bucketsize 86 * register value into its associated burst size. 87 * Parameters: 88 * reg_val - BUCKETSIZEf field value 89 * Returns: 90 * Max size burst traffic in kbits. 91 * Notes: 92 * None. 93 */ 94 95 uint32 96 _bcm_fb_bucketsize_to_kbits(uint8 reg_val) 97 { 98 return fb_bucket_settings[reg_val & 0x0F]; 99 } 100 101 #if defined (BCM_FIREBOLT2_SUPPORT) || defined(BCM_RAPTOR_SUPPORT) || \ 102 defined (BCM_TRX_SUPPORT) 103 #define FB2_NUM_BUCKET_RANGES 16 104 #define FB2_BUCKET_MIN_BITS (4 * 1024 * 8) /* 4K bytes */ 105 #define FB2_BUCKET_SEGMENT_GRANULARITY 256 106 #define FB2_BUCKET_SEGMENT_MASK 0xff 107 #define FB2_BUCKET_POWER_SHIFT 8 108 #define FB2_BUCKET_POWER_MASK 0xf 109 #define FB2_BUCKET_ENCODED_MAX 0xfff 110 111 /* 112 * Function: 113 * _bcm_fb2_kbits_to_bucketsize 114 * Description: 115 * Routine that converts desired burst size into Firebolt2 style 116 * leaky bucketsize register value. 117 * Parameters: 118 * kbits_burst - Desired size of maximum burst traffic 119 * Returns: 120 * Register bits for BUCKETSIZEf field. 121 * Notes: 122 * None. 123 */ 124 125 uint32 126 _bcm_fb2_kbits_to_bucket_encoding(uint32 kbits_burst, int linear_mode) 127 { 128 uint32 i; 129 uint32 bits, encoding, bucketsize, bucket_segment_size; 130 131 if (linear_mode) { 132 encoding = (((kbits_burst * 1000) + (FB2_BUCKET_MIN_BITS - 1)) / 133 FB2_BUCKET_MIN_BITS); 134 if (encoding > FB2_BUCKET_ENCODED_MAX) { 135 encoding = FB2_BUCKET_ENCODED_MAX; 136 } 137 return encoding; 138 } else { 139 encoding = kbits_burst ? 1 : 0; /* 0 kbits means disable */ 140 bucketsize = FB2_BUCKET_MIN_BITS; 141 bits = kbits_burst * 1000; 142 143 for (i=0; i<= FB2_NUM_BUCKET_RANGES; i++, bucketsize *= 2) { 144 if (bits <= bucketsize) { 145 if (i > 0) { 146 bucket_segment_size = 147 (1 << (i - 1)) * FB2_BUCKET_MIN_BITS / 148 FB2_BUCKET_SEGMENT_GRANULARITY; 149 encoding = 150 (bits - (bucketsize / 2) + 151 (bucket_segment_size - 1)) / bucket_segment_size; 152 encoding |= (i - 1) << FB2_BUCKET_POWER_SHIFT; 153 } 154 break; 155 } 156 } 157 158 return (i < FB2_NUM_BUCKET_RANGES) ? encoding : 159 FB2_BUCKET_ENCODED_MAX; 160 } 161 } 162 163 /* 164 * Function: 165 * _bcm_fb2_bucketsize_to_kbits 166 * Description: 167 * Routine that converts Firebolt2 style leaky bucketsize 168 * register value into its associated burst size. 169 * Parameters: 170 * reg_val - BUCKETSIZEf field value 171 * Returns: 172 * Max size burst traffic in kbits. 173 * Notes: 174 * None. 175 */ 176 177 uint32 178 _bcm_fb2_bucket_encoding_to_kbits(uint32 reg_val, int linear_mode) 179 { 180 uint32 power, segment, bucketsize; 181 182 if (linear_mode) { 183 return ((reg_val * FB2_BUCKET_MIN_BITS) / 1000); 184 } else { 185 segment = reg_val & FB2_BUCKET_SEGMENT_MASK; 186 power = (reg_val >> FB2_BUCKET_POWER_SHIFT) & FB2_BUCKET_POWER_MASK; 187 188 /* Calculate raw bits */ 189 bucketsize = (1 << power) * 190 (FB2_BUCKET_MIN_BITS / FB2_BUCKET_SEGMENT_GRANULARITY) * 191 (FB2_BUCKET_SEGMENT_GRANULARITY + segment); 192 193 194 /* bits to kbits */ 195 return (bucketsize + (1000 - 1)) / 1000; 196 } 197 } 198 199 #define METER_GRANULARITY_DEFAULT 3 200 #define METER_GRANULARITY_NUM 8 201 #define METER_KBITS_SEC_QUANTUM_MIN 8 /* 8000 bits/second */ 202 #define METER_BITS_BURST_MIN (1024 * 8 / 2) /* 1/2 Kbytes */ 203 #define METER_PACKET_SEC_QUANTUM_MIN 1 204 #define METER_PACKET_MAX_GRAN_FP_EXTRA_MULTIPLE 4 /* 2 extra steps */ 205 #define METER_PACKET_MAX_GRAN_MMU_EXTRA_MULTIPLE 2 /* 1 extra step */ 206 #define METER_PACKET_BURST_MIN 512 /* 0.512 packet, use 1000x */ 207 #define METER_PACKET_BURST_DIVISOR 1000 /* use 1000x for calculation */ 208 #define METER_NL_SEGMENT_GRANULARITY 256 209 #define METER_NL_BUCKET_POWER_SHIFT 8 210 #define METER_NL_BUCKET_RANGE_NUM 16 211 #define METER_NL_BUCKET_SEGMENT_MASK 0xff 212 #define METER_NL_BUCKET_POWER_MASK 0xf 213 #define METER_NL_BUCKET_MAC_ENCODE_MAX 0xff80 214 215 STATIC void 216 _bcm_xgs_granularity_params(int granularity, uint32 flags, 217 uint32 *rate_quantum, uint32 *burst_quantum) 218 { 219 int ix; 220 uint32 gran_multiple = 1; 221 222 for (ix = 0; ix < granularity; ix++) { 223 gran_multiple *= 2; 224 } 225 226 if (flags & _BCM_XGS_METER_FLAG_PACKET_MODE) { 227 if (granularity == (METER_GRANULARITY_NUM - 1)) { 228 if (flags &_BCM_XGS_METER_FLAG_FP_POLICER) { 229 if (!(flags & _BCM_XGS_METER_FLAG_FP_TD2_POLICER)) { 230 gran_multiple *= METER_PACKET_MAX_GRAN_FP_EXTRA_MULTIPLE; 231 } 232 } else { 233 gran_multiple *= METER_PACKET_MAX_GRAN_MMU_EXTRA_MULTIPLE; 234 } 235 } 236 if ((flags & _BCM_XGS_METER_FLAG_FP_TD2_POLICER) 237 && (flags & _BCM_XGS_METER_FLAG_FP_POLICER)) { 238 if ((granularity >= 5) && (granularity <=7)) { 239 for (ix = 0; ix <= (granularity - 5); ix++) { 240 gran_multiple = gran_multiple * 2; 241 } 242 } 243 } 244 *rate_quantum = METER_PACKET_SEC_QUANTUM_MIN * gran_multiple; 245 *burst_quantum = METER_PACKET_BURST_MIN * gran_multiple; 246 247 } else { 248 *rate_quantum = METER_KBITS_SEC_QUANTUM_MIN * gran_multiple; 249 *burst_quantum = METER_BITS_BURST_MIN * gran_multiple; 250 } 251 252 /* 253 * On device with double refresh frequency (double the number of refresh 254 * per second), granularity is half for burst and (per refresh) rate. 255 */ 256 if (flags & _BCM_XGS_METER_FLAG_DOUBLE_REFRESH_FREQ) { 257 *burst_quantum /= 2; 258 } 259 260 if (flags & _BCM_XGS_METER_FLAG_BUCKET_IN_8KB) { 261 if (granularity == 5) { 262 *burst_quantum /= 2; 263 } 264 } 265 /* With Refresh rate of 15.625us, 266 * Minimum Quantum (g=0) | Byte Mode | Pkt Mode | 267 * Rate | 4 kbps | 0.5 pps | 268 * Burst | 512 bytes | 0.512 pkts | 269 * So, calculated rate and burst quantum needs to be adjusted 270 */ 271 if (flags & _BCM_XGS_METER_FLAG_REFRESH_RATE_15p625) { 272 *rate_quantum /= 2; 273 *burst_quantum /= 8; 274 } 275 } 276 277 /* 278 * Function: 279 * _bcm_xgs_kbits_to_bucket_encoding 280 * Description: 281 * Routine that converts desired burst size into Firebolt2 style 282 * leaky bucketsize register value. 283 * Parameters: 284 * kbits_sec - Desired rate of ongoing traffic 285 * kbits_burst - Desired size of maximum burst traffic 286 * flags - paramters indicating capabilities and configuration of meter 287 * refresh_bitsize - number of bits for the refresh rate field 288 * bucket_max_bitsize - number of bits for the bucket max field 289 * refresh_rate - (OUT) calculated value for the refresh rate field 290 * bucket_max - (OUT) calculated value for the bucket max field 291 * granularity - (OUT) calculated value for the granularity field 292 * Returns: 293 * BCM_E_* 294 * Notes: 295 * 296 * bandwidth-shaping mode 297 * gran refresh refresh bucket-size-granularity 298 * byte/refresh kbit/second bits 299 * min <-> max base <-> max 300 * (linear) / (ITU mode) 301 * 0 1/128 8 <-> 0x1ffff8 4096 <-> 0xfff000 / 0xff80000 302 * 1 1/64 16 <-> 0x3ffff0 8192 <-> 0x1ffe000 / 0x1ff00000 303 * 2 1/32 32 <-> 0x7fffe0 16384 <-> 0x3ffc000 / 0x3fe00000 304 * 3 1/16 64 <-> 0xffffc0 32768 <-> 0x7ff8000 / 0x7fc00000 305 * 4 1/8 128 <-> 0x1ffff80 65536 <-> 0xfff0000 / 0xff800000 306 * 5 1/4 256 <-> 0x3ffff00 131072 <-> 0x1ffe0000 / 0x1ff000000 307 * 6 1/2 512 <-> 0x7fffe00 262144 <-> 0x3ffc0000 / 0x3fe000000 308 * 7 1 1024 <-> 0xffffc00 524288 <-> 0x7ff80000 / 0x7fc000000 309 * (max value is based on 18-bit refresh setting and 12-bit burst setting) 310 * 311 * packet-shaping mode (for mmu) 312 * gran refresh refresh bucket-size-granularity 313 * packet/refresh packet/second packet 314 * min <-> max base <-> max 315 * (linear) / (ITU mode) 316 * 0 1/128000 1 <-> 0x3ffff 0.512 <-> 0x830 / 0x82d0 317 * 1 1/64000 2 <-> 0x7fffe 1.024 <-> 0x1061 / 0x105a1 318 * 2 1/32000 4 <-> 0xffffc 2.048 <-> 0x20c2 / 0x20b43 319 * 3 1/16000 8 <-> 0x1ffff8 4.096 <-> 0x4185 / 0x41687 320 * 4 1/8000 16 <-> 0x3ffff0 8.192 <-> 0x830a / 0x82d0e 321 * 5 1/4000 32 <-> 0x7fffe0 16.384 <-> 0x10614 / 0x105a1c 322 * 6 1/2000 64 <-> 0xffffc0 32.768 <-> 0x20c28 / 0x20b439 323 * 7 1/500 256 <-> 0x3ffff00 131.072 <-> 0x830a3 / 0x82d0e5 324 * 325 * packet-shaping mode (for fp) 326 * gran refresh refresh bucket-size-granularity 327 * packet/refresh packet/second packet 328 * min <-> max base <-> max 329 * (linear) / (ITU mode) 330 * 0 1/128000 1 <-> 0x7ffff 0.512 <-> 0x830 / 0x82d0 331 * 1 1/64000 2 <-> 0xffffe 1.024 <-> 0x1061 / 0x105a1 332 * 2 1/32000 4 <-> 0x1ffffc 2.048 <-> 0x20c2 / 0x20b43 333 * 3 1/16000 8 <-> 0x3ffff8 4.096 <-> 0x4185 / 0x41687 334 * 4 1/8000 16 <-> 0x7ffff0 8.192 <-> 0x830a / 0x82d0e 335 * 5 1/4000 32 <-> 0xffffe0 16.384 <-> 0x10614 / 0x105a1c 336 * 6 1/2000 64 <-> 0x1ffffc0 32.768 <-> 0x20c28 / 0x20b439 337 * 7 1/250 512 <-> 0xffffe00 262.144 <-> 0x106147 / 0x105a1ca 338 */ 339 340 int 341 _bcm_xgs_kbits_to_bucket_encoding(uint32 kbits_sec, uint32 kbits_burst, 342 uint32 flags, 343 int refresh_bitsize, 344 int bucket_max_bitsize, 345 uint32 *refresh_rate, uint32 *bucketsize, 346 uint32 *granularity) 347 { 348 int gran, gran_min, gran_max; 349 uint32 i; 350 uint32 burst, encoding, buckettop, bucket_segment_size; 351 uint32 refresh_mask = 0; 352 uint32 bucket_mask = 0; 353 uint32 refresh_max = 0; 354 uint32 bucket_max = 0; 355 uint32 rate_quantum = 0; 356 uint32 burst_quantum = 0; 357 uint32 gran_select = 0; 358 359 if ((refresh_rate == NULL) || (bucketsize == NULL)) { 360 return BCM_E_INTERNAL; 361 } 362 363 if ((kbits_burst == 0) && 364 (!(flags & _BCM_XGS_METER_FLAG_FP_POLICER) && (kbits_sec == 0))) { 365 /* Disabled */ 366 *refresh_rate = 0; 367 *bucketsize = 0; 368 *granularity = METER_GRANULARITY_DEFAULT; 369 return BCM_E_NONE; 370 } 371 372 refresh_mask = 0xffffffff >> (32 - refresh_bitsize); 373 bucket_mask = 0xffffffff >> (32 - bucket_max_bitsize); 374 if (flags & _BCM_XGS_METER_FLAG_PACKET_MODE) { 375 /* Minimum packet burst is .512 packet. We'll work in integers. */ 376 burst = kbits_burst * METER_PACKET_BURST_DIVISOR; 377 } else { 378 if (kbits_burst > (0xffffffff / 1000)) { 379 burst = 0xffffffff; 380 } else { 381 burst = kbits_burst * 1000; 382 } 383 } 384 385 if (flags & _BCM_XGS_METER_FLAG_GRANULARITY) { 386 gran_min = 0; 387 gran_max = METER_GRANULARITY_NUM - 1; 388 } else if (flags & _BCM_XGS_METER_FLAG_GRANULARITY_SELECTIVE) { 389 gran_select = (flags & _BCM_XGS_METER_FLAG_GRANULARITY_SELECT_MASK); 390 gran_select >>= _BCM_XGS_METER_FLAG_GRANULARITY_SELECT_SHIFT; 391 392 gran_min = gran_max = -1; 393 for (i = 0; i < METER_GRANULARITY_NUM; i++) { 394 if ((gran_select & 0x1) && (gran_min < 0)) { 395 gran_min = i; 396 } 397 if (gran_select & 0x1) { 398 gran_max = i; 399 } 400 gran_select >>= 1; 401 } 402 403 /* Can't get min ang max gran, set to default */ 404 if ((gran_min < 0) || (gran_max < 0)) { 405 gran_min = gran_max = METER_GRANULARITY_DEFAULT; 406 } 407 } else { 408 gran_min = gran_max = METER_GRANULARITY_DEFAULT; 409 } 410 411 for (gran = gran_min; gran <= gran_max; gran++) { 412 if (flags & _BCM_XGS_METER_FLAG_GRANULARITY_SELECTIVE) { 413 gran_select = (flags & _BCM_XGS_METER_FLAG_GRANULARITY_SELECT_MASK); 414 gran_select >>= _BCM_XGS_METER_FLAG_GRANULARITY_SELECT_SHIFT; 415 if (!((1 << gran) & gran_select)) { 416 continue; 417 } 418 } 419 420 _bcm_xgs_granularity_params(gran, flags, 421 &rate_quantum, &burst_quantum); 422 refresh_max = refresh_mask * rate_quantum; 423 if (flags & _BCM_XGS_METER_FLAG_NON_LINEAR) { 424 bucket_max = METER_NL_BUCKET_MAC_ENCODE_MAX * burst_quantum; 425 } else { 426 bucket_max = bucket_mask * burst_quantum; 427 } 428 429 if ((kbits_sec <= refresh_max) && (burst <= bucket_max)) { 430 break; 431 } 432 } 433 434 if (gran > gran_max) { 435 /* Saturate! */ 436 gran = gran_max; 437 if (kbits_sec > refresh_max) { 438 kbits_sec = refresh_max; 439 } 440 if (burst > bucket_max) { 441 burst = bucket_max; 442 } 443 } 444 445 *granularity = gran; 446 447 if (kbits_sec > (0xffffffff - (rate_quantum - 1))) { 448 kbits_sec = 0xffffffff - (rate_quantum - 1); 449 } 450 451 if (!rate_quantum) { 452 /* avoid un-expected rate_quantum */ 453 return BCM_E_INTERNAL; 454 } 455 456 *refresh_rate = (kbits_sec + (rate_quantum - 1)) / rate_quantum; 457 if (*refresh_rate > refresh_mask) { 458 *refresh_rate = refresh_mask; 459 } 460 461 if (flags & _BCM_XGS_METER_FLAG_NON_LINEAR) { 462 if (burst <= burst_quantum) { 463 *bucketsize = burst ? 1 : 0; /* 0 kbits means disable */ 464 } else { 465 encoding = bucket_mask; 466 buckettop = burst_quantum; 467 for (i = 0; i < METER_NL_BUCKET_RANGE_NUM; i++, buckettop *= 2) { 468 bucket_segment_size = 469 buckettop / METER_NL_SEGMENT_GRANULARITY; 470 if (burst <= (buckettop * 2 - bucket_segment_size) || 471 (buckettop == 0)) { 472 if (buckettop == 0) { 473 /* Saturate */ 474 buckettop = 0xffffffff; 475 } 476 encoding = 477 (burst - buckettop + (bucket_segment_size - 1)) / 478 bucket_segment_size; 479 encoding |= i << METER_NL_BUCKET_POWER_SHIFT; 480 break; 481 } 482 } 483 *bucketsize = (i < METER_NL_BUCKET_RANGE_NUM) ? encoding : 484 bucket_mask; 485 } 486 } else { 487 encoding = (burst + (burst_quantum - 1)) / burst_quantum; 488 if (encoding > bucket_mask) { 489 encoding = bucket_mask; 490 } 491 *bucketsize = encoding; 492 } 493 return BCM_E_NONE; 494 } 495 496 /* 497 * Function: 498 * _bcm_xgs_bucket_encoding_to_kbits 499 * Description: 500 * Routine that converts Firebolt2 style leaky bucketsize 501 * register value into its associated burst size. 502 * Parameters: 503 * refresh_rate - refresh rate field 504 * bucket_max - bucket max field 505 * granularity - granularity field 506 * flags - paramters indicating capabilities and configuration of meter 507 * kbits_sec - (OUT) Configured rate of ongoing traffic 508 * kbits_burst - (OUT) Configured size of maximum burst traffic 509 * Returns: 510 * Max size burst traffic in kbits. 511 * Notes: 512 * None. 513 */ 514 515 uint32 516 _bcm_xgs_bucket_encoding_to_kbits(uint32 refresh_rate, uint32 bucket_max, 517 uint32 granularity, uint32 flags, 518 uint32 *kbits_sec, uint32 *kbits_burst) 519 { 520 int gran; 521 uint32 power, segment, bucketsize; 522 uint32 rate_quantum, burst_quantum; 523 524 if ((kbits_sec == NULL) || (kbits_burst == NULL)) { 525 return BCM_E_INTERNAL; 526 } 527 528 gran = (flags & _BCM_XGS_METER_FLAG_GRANULARITY) ? granularity : 529 METER_GRANULARITY_DEFAULT; 530 _bcm_xgs_granularity_params(gran, flags, 531 &rate_quantum, &burst_quantum); 532 533 *kbits_sec = refresh_rate * rate_quantum; 534 535 if (flags & _BCM_XGS_METER_FLAG_NON_LINEAR) { 536 if (bucket_max == 0) { /* 0 means disabled */ 537 bucketsize = 0; 538 } else { 539 segment = bucket_max & METER_NL_BUCKET_SEGMENT_MASK; 540 power = (bucket_max >> METER_NL_BUCKET_POWER_SHIFT) & 541 METER_NL_BUCKET_POWER_MASK; 542 543 /* Calculate raw bits */ 544 bucketsize = (1 << power) * 545 (burst_quantum / METER_NL_SEGMENT_GRANULARITY) * 546 (METER_NL_SEGMENT_GRANULARITY + segment); 547 } 548 } else { 549 bucketsize = bucket_max * burst_quantum; 550 } 551 552 if (flags & _BCM_XGS_METER_FLAG_PACKET_MODE) { 553 *kbits_burst = bucketsize / METER_PACKET_BURST_DIVISOR; 554 } else { 555 *kbits_burst = bucketsize / 1000; 556 } 557 558 return BCM_E_NONE; 559 } 560 561 /* 562 * Function: 563 * _bcm_xgs_kbits_to_dual_bucket_encoding 564 * Description: 565 * Routine that converts desired burst size into TRX style 566 * leaky bucketsize register value for dual token bucket policer. 567 * Parameters: 568 * kbits_sec - Desired rate of ongoing traffic 569 * kbits_burst - Desired size of maximum burst traffic 570 * flags - paramters indicating capabilities and configuration of meter 571 * refresh_bitsize - number of bits for the refresh rate field 572 * bucket_max_bitsize - number of bits for the bucket max field 573 * granularity_start - granularity start value to be used for computation 574 * refresh_rate - (OUT) calculated value for the refresh rate field 575 * bucket_max - (OUT) calculated value for the bucket max field 576 * granularity - (OUT) calculated value for the granularity field 577 * Returns: 578 * BCM_E_* 579 */ 580 int 581 _bcm_xgs_kbits_to_dual_bucket_encoding(uint32 kbits_sec, uint32 kbits_burst, 582 uint32 flags, 583 int refresh_bitsize, 584 int bucket_max_bitsize, 585 int granularity_start, 586 uint32 *refresh_rate, uint32 *bucketsize, 587 uint32 *granularity) 588 { 589 int gran, gran_min = 0, gran_max; 590 uint32 burst, encoding; 591 uint32 refresh_mask = 0; 592 uint32 bucket_mask = 0; 593 uint32 refresh_max = 0; 594 uint32 bucket_max = 0; 595 uint32 rate_quantum = 0; 596 uint32 burst_quantum = METER_PACKET_BURST_MIN; 597 598 if ((refresh_rate == NULL) || (bucketsize == NULL)) { 599 return BCM_E_INTERNAL; 600 } 601 602 if ((kbits_burst == 0) && 603 (!(flags & _BCM_XGS_METER_FLAG_FP_POLICER) && (kbits_sec == 0))) { 604 /* Disabled */ 605 *refresh_rate = 0; 606 *bucketsize = 0; 607 *granularity = METER_GRANULARITY_DEFAULT; 608 return BCM_E_NONE; 609 } 610 611 refresh_mask = 0xffffffff >> (32 - refresh_bitsize); 612 bucket_mask = 0xffffffff >> (32 - bucket_max_bitsize); 613 if (flags & _BCM_XGS_METER_FLAG_PACKET_MODE) { 614 /* Minimum packet burst is .512 packet. We'll work in integers. */ 615 burst = kbits_burst * METER_PACKET_BURST_DIVISOR; 616 } else { 617 if (kbits_burst > (0xffffffff / 1000)) { 618 burst = 0xffffffff; 619 } else { 620 burst = kbits_burst * 1000; 621 } 622 } 623 624 gran_min = granularity_start; 625 gran_max = METER_GRANULARITY_NUM - 1; 626 627 for (gran = gran_min; gran <= gran_max; gran++) { 628 _bcm_xgs_granularity_params(gran, flags, 629 &rate_quantum, &burst_quantum); 630 refresh_max = refresh_mask * rate_quantum; 631 bucket_max = bucket_mask * burst_quantum; 632 633 if ((kbits_sec <= refresh_max) && (burst <= bucket_max)) { 634 break; 635 } 636 } 637 638 if (gran > gran_max) { 639 /* Saturate! */ 640 gran = gran_max; 641 if (kbits_sec > refresh_max) { 642 kbits_sec = refresh_max; 643 } 644 if (burst > bucket_max) { 645 burst = bucket_max; 646 } 647 } 648 649 *granularity = gran; 650 651 if (kbits_sec > (0xffffffff - (rate_quantum - 1))) { 652 kbits_sec = 0xffffffff - (rate_quantum - 1); 653 } 654 655 /* Coverity fix : Making sure rate_quantum is above zero in order 656 to avoid divide by zero coverity error */ 657 if (rate_quantum > 0) { 658 *refresh_rate = (kbits_sec + (rate_quantum - 1)) / rate_quantum; 659 } 660 if (*refresh_rate > refresh_mask) { 661 *refresh_rate = refresh_mask; 662 } 663 664 encoding = (burst + (burst_quantum - 1)) / burst_quantum; 665 if (encoding > bucket_mask) { 666 encoding = bucket_mask; 667 } 668 *bucketsize = encoding; 669 return BCM_E_NONE; 670 } 671 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_RAPTOR_SUPPORT || BCM_TRIUMPH_SUPPORT */ 672 673 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || \ 674 defined(BCM_GREYHOUND2_SUPPORT) 675 int 676 _bcm_xgs_kbits_to_bucket_encoding_with_granularity(uint32 kbits_sec, 677 uint32 kbits_burst, 678 uint32 flags, 679 int refresh_bitsize, 680 int bucket_max_bitsize, 681 uint32 *refresh_rate, uint32 *bucketsize, 682 uint32 *granularity) 683 { 684 uint32 i; 685 uint32 burst, encoding, buckettop, bucket_segment_size; 686 uint32 refresh_mask = 0; 687 uint32 bucket_mask = 0; 688 uint32 rate_quantum = 0; 689 uint32 burst_quantum = 0; 690 691 if ((refresh_rate == NULL) || (bucketsize == NULL)) { 692 return BCM_E_INTERNAL; 693 } 694 695 if ((kbits_burst == 0) && 696 (!(flags & _BCM_XGS_METER_FLAG_FP_POLICER) && (kbits_sec == 0))) { 697 /* Disabled */ 698 *refresh_rate = 0; 699 *bucketsize = 0; 700 *granularity = METER_GRANULARITY_DEFAULT; 701 return BCM_E_NONE; 702 } 703 704 refresh_mask = 0xffffffff >> (32 - refresh_bitsize); 705 bucket_mask = 0xffffffff >> (32 - bucket_max_bitsize); 706 if (flags & _BCM_XGS_METER_FLAG_PACKET_MODE) { 707 /* Minimum packet burst is .512 packet. We'll work in integers. */ 708 burst = kbits_burst * METER_PACKET_BURST_DIVISOR; 709 } else { 710 if (kbits_burst > (0xffffffff / 1000)) { 711 burst = 0xffffffff; 712 } else { 713 burst = kbits_burst * 1000; 714 } 715 } 716 717 _bcm_xgs_granularity_params(*granularity, flags, 718 &rate_quantum, &burst_quantum); 719 720 if (kbits_sec > (0xffffffff - (rate_quantum - 1))) { 721 kbits_sec = 0xffffffff - (rate_quantum - 1); 722 } 723 724 *refresh_rate = (kbits_sec + (rate_quantum - 1)) / rate_quantum; 725 if (*refresh_rate > refresh_mask) { 726 *refresh_rate = refresh_mask; 727 } 728 729 if (flags & _BCM_XGS_METER_FLAG_NON_LINEAR) { 730 if (burst <= burst_quantum) { 731 *bucketsize = burst ? 1 : 0; /* 0 kbits means disable */ 732 } else { 733 encoding = bucket_mask; 734 buckettop = burst_quantum; 735 for (i = 0; i < METER_NL_BUCKET_RANGE_NUM; i++, buckettop *= 2) { 736 bucket_segment_size = 737 buckettop / METER_NL_SEGMENT_GRANULARITY; 738 if (burst <= (buckettop * 2 - bucket_segment_size) || 739 (buckettop == 0)) { 740 if (buckettop == 0) { 741 /* Saturate */ 742 buckettop = 0xffffffff; 743 } 744 encoding = 745 (burst - buckettop + (bucket_segment_size - 1)) / 746 bucket_segment_size; 747 encoding |= i << METER_NL_BUCKET_POWER_SHIFT; 748 break; 749 } 750 } 751 *bucketsize = (i < METER_NL_BUCKET_RANGE_NUM) ? encoding : 752 bucket_mask; 753 } 754 } else { 755 encoding = (burst + (burst_quantum - 1)) / burst_quantum; 756 if (encoding > bucket_mask) { 757 encoding = bucket_mask; 758 } 759 *bucketsize = encoding; 760 } 761 return BCM_E_NONE; 762 } 763 #endif /* BCM_KATANA_SUPPORT || BCM_TRIUMPH3_SUPPORT || 764 BCM_GREYHOUND2_SUPPORT */