meter.c (14703B)
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: Trident placeholder for metering, FP metering. 9 */ 10 11 #include <soc/defs.h> 12 #if defined(BCM_TRIDENT_SUPPORT) 13 14 #include <sal/core/libc.h> 15 #include <bcm_int/esw/trident.h> 16 17 #define METER_GRANULARITY_DEFAULT 3 18 #define METER_GRANULARITY_NUM 8 19 #define METER_KBITS_SEC_QUANTUM_MIN 8 /* 8000 bits/second */ 20 #define METER_BITS_BURST_MIN (256 * 8) /* 256 bytes */ 21 #define METER_PACKET_SEC_QUANTUM_MIN 1 22 #define METER_MMU_PACKET_BURST_MIN 256 /* 0.256 packet, use 1000x */ 23 #define METER_FP_PACKET_BURST_MIN 512 /* 0.512 packet, use 1000x */ 24 #define METER_PACKET_BURST_DIVISOR 1000 /* use 1000x for calculation */ 25 #define METER_NL_SEGMENT_GRANULARITY 256 26 #define METER_NL_BUCKET_POWER_SHIFT 8 27 #define METER_NL_BUCKET_RANGE_NUM 16 28 #define METER_NL_BUCKET_SEGMENT_MASK 0xff 29 #define METER_NL_BUCKET_POWER_MASK 0xf 30 #define METER_NL_BUCKET_MAC_ENCODE_MAX 0xff80 /* 2 ** 0xf * (1 + 0xff/256) */ 31 32 STATIC void 33 _bcm_td_granularity_params(int unit, int granularity, uint32 flags, 34 uint32 *rate_unit_size, uint32 *burst_unit_size) 35 { 36 uint32 gran_multiple; 37 static const uint32 fp_pkt_mode_gran_multiple[] = { 38 1, 2, 4, 8, 16, 32, 64, 512 39 }; 40 static const uint32 mmu_pkt_mode_gran_multiple[] = { 41 1, 2, 4, 8, 16, 64, 256, 1024 42 }; 43 44 if (flags & _BCM_TD_METER_FLAG_PACKET_MODE) { 45 if (flags &_BCM_TD_METER_FLAG_FP_POLICER) { 46 gran_multiple = fp_pkt_mode_gran_multiple[granularity]; 47 *burst_unit_size = METER_FP_PACKET_BURST_MIN * gran_multiple; 48 } else { 49 gran_multiple = mmu_pkt_mode_gran_multiple[granularity]; 50 *burst_unit_size = METER_MMU_PACKET_BURST_MIN * gran_multiple; 51 } 52 *rate_unit_size = METER_PACKET_SEC_QUANTUM_MIN * gran_multiple; 53 } else { 54 gran_multiple = 1 << granularity; 55 *rate_unit_size = METER_KBITS_SEC_QUANTUM_MIN * gran_multiple; 56 *burst_unit_size = METER_BITS_BURST_MIN * gran_multiple; 57 } 58 } 59 60 /* 61 * Function: 62 * _bcm_td_kbits_to_bucket_encoding 63 * Description: 64 * Routine that converts desired burst size into leaky bucketsize 65 * register value. 66 * Parameters: 67 * rate_quantum - Desired rate of ongoing traffic 68 * burst_quantum - Desired size of maximum burst traffic 69 * flags - paramters indicating capabilities and configuration of meter 70 * refresh_bitsize - number of bits for the refresh rate field 71 * bucket_max_bitsize - number of bits for the bucket max field 72 * refresh_rate - (OUT) calculated value for the refresh rate field 73 * bucket_max - (OUT) calculated value for the bucket max field 74 * granularity - (OUT) calculated value for the granularity field 75 * Returns: 76 * BCM_E_* 77 * Notes: 78 * 79 * bandwidth(byte) mode 80 * gran refresh refresh bucket-size-granularity 81 * byte/refresh kbit/second bits 82 * min <-> max base <-> max 83 * (linear) / (ITU mode) 84 * 0 1/128 8 <-> 0x1ffff8 2048 <-> 0x7ff800 / 0x7fc0000 85 * 1 1/64 16 <-> 0x3ffff0 4096 <-> 0xfff000 / 0xff80000 86 * 2 1/32 32 <-> 0x7fffe0 8192 <-> 0x1ffe000 / 0x1ff00000 87 * 3 1/16 64 <-> 0xffffc0 16384 <-> 0x3ffc000 / 0x3fe00000 88 * 4 1/8 128 <-> 0x1ffff80 32768 <-> 0x7ff8000 / 0x7fc00000 89 * 5 1/4 256 <-> 0x3ffff00 65536 <-> 0xfff0000 / 0xff800000 90 * 6 1/2 512 <-> 0x7fffe00 131072 <-> 0x1ffe0000 / 0x1ff000000 91 * 7 1 1024 <-> 0xffffc00 262144 <-> 0x3ffc0000 / 0x3fe000000 92 * (max value is based on 18-bit refresh setting and 12-bit burst setting) 93 * 94 * packet-shapinp mode (for trident mmu) 95 * gran refresh refresh bucket-size-granularity 96 * packet/refresh packet/second packet 97 * min <-> max base <-> max 98 * (linear) / (ITU mode) 99 * 0 1/256000 1 <-> 0x3ffff 0.256 <-> 0x418 / 0x4168 100 * 1 1/128000 2 <-> 0x7fffe 0.512 <-> 0x830 / 0x82d0 101 * 2 1/64000 4 <-> 0xffffc 1.024 <-> 0x1061 / 0x105a1 102 * 3 1/32000 8 <-> 0x1ffff8 2.048 <-> 0x20c2 / 0x20b43 103 * 4 1/16000 16 <-> 0x3ffff0 4.096 <-> 0x4185 / 0x41687 104 * 5 1/4000 64 <-> 0xffffc0 16.384 <-> 0x10614 / 0x105a1c 105 * 6 1/1000 256 <-> 0x3ffff00 65.536 <-> 0x41851 / 0x416872 106 * 7 1/250 1024 <-> 0xffffc00 262.144 <-> 0x106147 / 0x105a1ca 107 * 108 * packet-policing mode (for trident fp) 109 * gran refresh refresh bucket-size-granularity 110 * packet/refresh packet/second packet 111 * min <-> max base <-> max 112 * (linear) / (ITU mode) 113 * 0 1/128000 1 <-> 0x7ffff 0.512 <-> 0x830 / 0x82d0 114 * 1 1/64000 2 <-> 0xffffe 1.024 <-> 0x1061 / 0x105a1 115 * 2 1/32000 4 <-> 0x1ffffc 2.048 <-> 0x20c2 / 0x20b43 116 * 3 1/16000 8 <-> 0x3ffff8 4.096 <-> 0x4185 / 0x41687 117 * 4 1/8000 16 <-> 0x7ffff0 8.192 <-> 0x830a / 0x82d0e 118 * 5 1/4000 32 <-> 0xffffe0 16.384 <-> 0x10614 / 0x105a1c 119 * 6 1/2000 64 <-> 0x1ffffc0 32.768 <-> 0x20c28 / 0x20b439 120 * 7 1/250 512 <-> 0xffffe00 262.144 <-> 0x106147 / 0x105a1ca 121 */ 122 int 123 _bcm_td_rate_to_bucket_encoding(int unit, uint32 rate_quantum, 124 uint32 burst_quantum, uint32 flags, 125 int refresh_bitsize, int bucket_max_bitsize, 126 uint32 *refresh_rate, uint32 *bucketsize, 127 uint32 *granularity) 128 { 129 int gran, gran_min, gran_max; 130 uint32 i; 131 uint32 burst, encoding, buckettop, bucket_segment_size; 132 uint32 refresh_mask = 0; 133 uint32 bucket_mask = 0; 134 uint32 refresh_max = 0; 135 uint32 bucket_max = 0; 136 uint32 rate_unit_size = 0; 137 uint32 burst_unit_size = 0; 138 139 if ((refresh_rate == NULL) || (bucketsize == NULL)) { 140 return BCM_E_INTERNAL; 141 } 142 143 if ((burst_quantum == 0) && 144 (!(flags & _BCM_TD_METER_FLAG_FP_POLICER) && (rate_quantum == 0))) { 145 /* Disabled */ 146 *refresh_rate = 0; 147 *bucketsize = 0; 148 *granularity = METER_GRANULARITY_DEFAULT; 149 return BCM_E_NONE; 150 } 151 152 refresh_mask = 0xffffffff >> (32 - refresh_bitsize); 153 bucket_mask = 0xffffffff >> (32 - bucket_max_bitsize); 154 if (flags & _BCM_TD_METER_FLAG_PACKET_MODE) { 155 /* Minimum packet burst is .512 packet. We'll work in integers. */ 156 burst = burst_quantum * METER_PACKET_BURST_DIVISOR; 157 } else { 158 if (burst_quantum > (0xffffffff / 1000)) { 159 burst = 0xffffffff; 160 } else { 161 burst = burst_quantum * 1000; 162 } 163 } 164 165 gran_min = 0; 166 gran_max = METER_GRANULARITY_NUM - 1; 167 168 for (gran = gran_min; gran <= gran_max; gran++) { 169 _bcm_td_granularity_params(unit, gran, flags, &rate_unit_size, 170 &burst_unit_size); 171 refresh_max = refresh_mask * rate_unit_size; 172 if (flags & _BCM_TD_METER_FLAG_NON_LINEAR) { 173 bucket_max = METER_NL_BUCKET_MAC_ENCODE_MAX * burst_unit_size; 174 } else { 175 bucket_max = (bucket_mask + 1) * burst_unit_size; 176 } 177 178 if ((rate_quantum <= refresh_max) && (burst <= bucket_max)) { 179 break; 180 } 181 } 182 183 if (gran > gran_max) { 184 /* Saturate! */ 185 gran = gran_max; 186 if (rate_quantum > refresh_max) { 187 rate_quantum = refresh_max; 188 } 189 if (burst > bucket_max) { 190 burst = bucket_max; 191 } 192 } 193 194 *granularity = gran; 195 196 if (rate_quantum > (0xffffffff - (rate_unit_size - 1))) { 197 rate_quantum = 0xffffffff - (rate_unit_size - 1); 198 } 199 200 *refresh_rate = (rate_quantum + (rate_unit_size - 1)) / rate_unit_size; 201 if (*refresh_rate > refresh_mask) { 202 *refresh_rate = refresh_mask; 203 } 204 205 if (flags & _BCM_TD_METER_FLAG_NON_LINEAR) { 206 if (burst <= burst_unit_size) { 207 *bucketsize = burst ? 1 : 0; /* 0 kbits means disable */ 208 } else { 209 encoding = bucket_mask; 210 buckettop = burst_unit_size; 211 for (i = 0; i < METER_NL_BUCKET_RANGE_NUM; i++, buckettop *= 2) { 212 bucket_segment_size = 213 buckettop / METER_NL_SEGMENT_GRANULARITY; 214 if (burst <= (buckettop * 2 - bucket_segment_size) || 215 (buckettop == 0)) { 216 if (buckettop == 0) { 217 /* Saturate */ 218 buckettop = 0xffffffff; 219 } 220 encoding = 221 (burst - buckettop + (bucket_segment_size - 1)) / 222 bucket_segment_size; 223 encoding |= i << METER_NL_BUCKET_POWER_SHIFT; 224 break; 225 } 226 } 227 *bucketsize = (i < METER_NL_BUCKET_RANGE_NUM) ? encoding : 228 bucket_mask; 229 } 230 } else { 231 encoding = (burst + (burst_unit_size - 1)) / burst_unit_size; 232 if (encoding > bucket_mask) { 233 encoding = bucket_mask; 234 } 235 *bucketsize = encoding; 236 } 237 return BCM_E_NONE; 238 } 239 240 /* 241 * Function: 242 * _bcm_td_bucket_encoding_to_rate 243 * Description: 244 * Routine that converts leaky bucketsize 245 * register value into its associated burst size. 246 * Parameters: 247 * refresh_rate - refresh rate field 248 * bucket_max - bucket max field 249 * granularity - granularity field 250 * flags - paramters indicating capabilities and configuration of meter 251 * rate_quantum - (OUT) Configured rate of ongoing traffic 252 * burst_quantum - (OUT) Configured size of maximum burst traffic 253 * Returns: 254 * Max size burst traffic in kbits. 255 * Notes: 256 * None. 257 */ 258 259 uint32 260 _bcm_td_bucket_encoding_to_rate(int unit, uint32 refresh_rate, 261 uint32 bucket_max, uint32 granularity, 262 uint32 flags, uint32 *rate_quantum, 263 uint32 *burst_quantum) 264 { 265 int gran; 266 uint32 power, segment, bucketsize; 267 uint32 rate_unit_size, burst_unit_size; 268 269 if ((rate_quantum == NULL) || (burst_quantum == NULL)) { 270 return BCM_E_INTERNAL; 271 } 272 273 gran = granularity; 274 _bcm_td_granularity_params(unit, gran, flags, &rate_unit_size, 275 &burst_unit_size); 276 277 *rate_quantum = refresh_rate * rate_unit_size; 278 279 if (flags & _BCM_TD_METER_FLAG_NON_LINEAR) { 280 if (bucket_max == 0) { /* 0 means disabled */ 281 bucketsize = 0; 282 } else { 283 segment = bucket_max & METER_NL_BUCKET_SEGMENT_MASK; 284 power = (bucket_max >> METER_NL_BUCKET_POWER_SHIFT) & 285 METER_NL_BUCKET_POWER_MASK; 286 287 /* Calculate raw bits */ 288 bucketsize = (1 << power) * 289 (burst_unit_size / METER_NL_SEGMENT_GRANULARITY) * 290 (METER_NL_SEGMENT_GRANULARITY + segment); 291 } 292 } else { 293 bucketsize = bucket_max * burst_unit_size; 294 } 295 296 if (flags & _BCM_TD_METER_FLAG_PACKET_MODE) { 297 *burst_quantum = bucketsize / METER_PACKET_BURST_DIVISOR; 298 } else { 299 *burst_quantum = bucketsize / 1000; 300 } 301 302 return BCM_E_NONE; 303 } 304 305 uint32 _bcm_td_default_burst_size(int unit, int port, uint32 kbits_sec) 306 { 307 soc_info_t *si = &SOC_INFO(unit); 308 int proposed1, proposed2, proposed, max_port_speed; 309 int mtu = 9216, numq; 310 311 max_port_speed = (IS_CPU_PORT(unit,port))? 1000 : si->port_speed_max[port]; 312 /* adjuct the max port speed for TD2 flex port*/ 313 if (SOC_IS_TRIDENT2(unit) && 314 !IS_CPU_PORT(unit,port)) { 315 if (si->port_num_lanes[port] > 0) { 316 max_port_speed = si->port_num_lanes[port] * 10000; 317 } else { 318 max_port_speed = 0; 319 } 320 } 321 /*adjust TH loopback port MAX speed = 100G*/ 322 #ifdef BCM_TOMAHAWK_SUPPORT 323 if (SOC_IS_TOMAHAWKX(unit) && 324 IS_LB_PORT(unit, port)) { 325 max_port_speed = 100000; 326 } 327 #endif /* BCM_TOMAHAWK_SUPPORT */ 328 max_port_speed *= 1000; 329 330 if (max_port_speed <= 0) { 331 return 0; 332 } 333 334 numq = IS_HG_PORT(unit, port) ? 10 : 8; 335 if (max_port_speed > kbits_sec) { 336 proposed1 = (mtu * numq)/(max_port_speed/kbits_sec); 337 } else { 338 if (((max_port_speed + kbits_sec - 1)/kbits_sec) == 0) { 339 return 0; 340 } 341 proposed1 = (mtu * numq)/((max_port_speed + kbits_sec - 1)/kbits_sec); 342 } 343 344 proposed2 = kbits_sec/(8 * 256); 345 346 proposed = (proposed1 > proposed2) ? proposed1 : proposed2; 347 proposed = (proposed * 8)/1000; 348 return (proposed > 0) ? proposed : 1; 349 } 350 351 uint32 _bcm_td_default_burst_size_by_weight(int unit, 352 int port, 353 uint32 kbits_sec, 354 int port_weights) 355 { 356 soc_info_t *si = &SOC_INFO(unit); 357 int proposed1, proposed2, proposed, max_port_speed; 358 int mtu = 9216, numq; 359 360 max_port_speed = (IS_CPU_PORT(unit,port))? 1000 : si->port_speed_max[port]; 361 /* adjuct the max port speed for TD2 flex port*/ 362 if (SOC_IS_TRIDENT2(unit) && 363 !IS_CPU_PORT(unit,port)) { 364 if (si->port_num_lanes[port] > 0) { 365 max_port_speed = si->port_num_lanes[port] * 10000; 366 } else { 367 max_port_speed = 0; 368 } 369 } 370 max_port_speed *= 1000; 371 372 if (max_port_speed <= 0) { 373 return 0; 374 } 375 376 if ((port_weights > 0) && SOC_IS_TRIDENT2(unit)) { 377 numq = port_weights; 378 } else { 379 numq = IS_HG_PORT(unit, port) ? 10 : 8; 380 } 381 if (max_port_speed > kbits_sec) { 382 proposed1 = (mtu * numq)/(max_port_speed/kbits_sec); 383 } else { 384 if (((max_port_speed + kbits_sec - 1)/kbits_sec) == 0) { 385 return 0; 386 } 387 proposed1 = (mtu * numq)/((max_port_speed + kbits_sec - 1)/kbits_sec); 388 } 389 390 proposed2 = kbits_sec/(8 * 256); 391 392 proposed = (proposed1 > proposed2) ? proposed1 : proposed2; 393 proposed = (proposed * 8)/1000; 394 return (proposed > 0) ? proposed : 1; 395 } 396 #else /* BCM_TRIDENT_SUPPORT */ 397 int _td_meter_not_empty; 398 #endif /* BCM_TRIDENT_SUPPORT */