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

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 */