LCOV - code coverage report
Current view: top level - vnet/policer - xlate.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 111 454 24.4 %
Date: 2023-07-05 22:20:52 Functions: 7 21 33.3 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2015 Cisco and/or its affiliates.
       3             :  * Licensed under the Apache License, Version 2.0 (the "License");
       4             :  * you may not use this file except in compliance with the License.
       5             :  * You may obtain a copy of the License at:
       6             :  *
       7             :  *     http://www.apache.org/licenses/LICENSE-2.0
       8             :  *
       9             :  * Unless required by applicable law or agreed to in writing, software
      10             :  * distributed under the License is distributed on an "AS IS" BASIS,
      11             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      12             :  * See the License for the specific language governing permissions and
      13             :  * limitations under the License.
      14             :  */
      15             : #include <string.h>
      16             : #include <stddef.h>
      17             : #include <stdio.h>
      18             : #include <assert.h>
      19             : #include <math.h>
      20             : #include <stdint.h>
      21             : 
      22             : #include <vlib/vlib.h>
      23             : #include <vnet/vnet.h>
      24             : 
      25             : #include <vnet/policer/policer.h>
      26             : 
      27             : /* debugs */
      28             : #define QOS_DEBUG_ERROR(msg, args...)                                         \
      29             :   vlib_log_err (vnet_policer_main.log_class, msg, ##args);
      30             : 
      31             : #define QOS_DEBUG_INFO(msg, args...)                                          \
      32             :   vlib_log_info (vnet_policer_main.log_class, msg, ##args);
      33             : 
      34             : #ifndef MIN
      35             : #define MIN(x,y)            (((x)<(y))?(x):(y))
      36             : #endif
      37             : 
      38             : #ifndef MAX
      39             : #define MAX(x,y)            (((x)>(y))?(x):(y))
      40             : #endif
      41             : 
      42             : #define IPE_POLICER_FULL_WRITE_REQUEST_M40AH_OFFSET                   0
      43             : #define IPE_POLICER_FULL_WRITE_REQUEST_M40AH_MASK                     8
      44             : #define IPE_POLICER_FULL_WRITE_REQUEST_M40AH_SHIFT                   24
      45             : 
      46             : #define IPE_POLICER_FULL_WRITE_REQUEST_TYPE_OFFSET                    2
      47             : #define IPE_POLICER_FULL_WRITE_REQUEST_TYPE_MASK                      2
      48             : #define IPE_POLICER_FULL_WRITE_REQUEST_TYPE_SHIFT                    10
      49             : 
      50             : #define IPE_POLICER_FULL_WRITE_REQUEST_CMD_OFFSET                     3
      51             : #define IPE_POLICER_FULL_WRITE_REQUEST_CMD_MASK                       2
      52             : #define IPE_POLICER_FULL_WRITE_REQUEST_CMD_SHIFT                      0
      53             : 
      54             : #define IPE_POLICER_FULL_WRITE_REQUEST_M40AL_OFFSET                   4
      55             : #define IPE_POLICER_FULL_WRITE_REQUEST_M40AL_MASK                    32
      56             : #define IPE_POLICER_FULL_WRITE_REQUEST_M40AL_SHIFT                    0
      57             : 
      58             : #define IPE_POLICER_FULL_WRITE_REQUEST_RFC_OFFSET                     8
      59             : #define IPE_POLICER_FULL_WRITE_REQUEST_RFC_MASK                       2
      60             : #define IPE_POLICER_FULL_WRITE_REQUEST_RFC_SHIFT                     30
      61             : 
      62             : #define IPE_POLICER_FULL_WRITE_REQUEST_AN_OFFSET                      8
      63             : #define IPE_POLICER_FULL_WRITE_REQUEST_AN_MASK                        1
      64             : #define IPE_POLICER_FULL_WRITE_REQUEST_AN_SHIFT                      29
      65             : 
      66             : #define IPE_POLICER_FULL_WRITE_REQUEST_REXP_OFFSET                    8
      67             : #define IPE_POLICER_FULL_WRITE_REQUEST_REXP_MASK                      4
      68             : #define IPE_POLICER_FULL_WRITE_REQUEST_REXP_SHIFT                    22
      69             : 
      70             : #define IPE_POLICER_FULL_WRITE_REQUEST_ARM_OFFSET                     9
      71             : #define IPE_POLICER_FULL_WRITE_REQUEST_ARM_MASK                      11
      72             : #define IPE_POLICER_FULL_WRITE_REQUEST_ARM_SHIFT                     11
      73             : 
      74             : #define IPE_POLICER_FULL_WRITE_REQUEST_PRM_OFFSET                    10
      75             : #define IPE_POLICER_FULL_WRITE_REQUEST_PRM_MASK                      11
      76             : #define IPE_POLICER_FULL_WRITE_REQUEST_PRM_SHIFT                      0
      77             : 
      78             : #define IPE_POLICER_FULL_WRITE_REQUEST_CBLE_OFFSET                   12
      79             : #define IPE_POLICER_FULL_WRITE_REQUEST_CBLE_MASK                      5
      80             : #define IPE_POLICER_FULL_WRITE_REQUEST_CBLE_SHIFT                    27
      81             : 
      82             : #define IPE_POLICER_FULL_WRITE_REQUEST_CBLM_OFFSET                   12
      83             : #define IPE_POLICER_FULL_WRITE_REQUEST_CBLM_MASK                      7
      84             : #define IPE_POLICER_FULL_WRITE_REQUEST_CBLM_SHIFT                    20
      85             : 
      86             : #define IPE_POLICER_FULL_WRITE_REQUEST_EBLE_OFFSET                   13
      87             : #define IPE_POLICER_FULL_WRITE_REQUEST_EBLE_MASK                      5
      88             : #define IPE_POLICER_FULL_WRITE_REQUEST_EBLE_SHIFT                    15
      89             : 
      90             : #define IPE_POLICER_FULL_WRITE_REQUEST_EBLM_OFFSET                   14
      91             : #define IPE_POLICER_FULL_WRITE_REQUEST_EBLM_MASK                      7
      92             : #define IPE_POLICER_FULL_WRITE_REQUEST_EBLM_SHIFT                     8
      93             : 
      94             : #define IPE_POLICER_FULL_WRITE_REQUEST_CB_OFFSET                     16
      95             : #define IPE_POLICER_FULL_WRITE_REQUEST_CB_MASK                       31
      96             : #define IPE_POLICER_FULL_WRITE_REQUEST_CB_SHIFT                       0
      97             : 
      98             : #define IPE_POLICER_FULL_WRITE_REQUEST_EB_OFFSET                     20
      99             : #define IPE_POLICER_FULL_WRITE_REQUEST_EB_MASK                       31
     100             : #define IPE_POLICER_FULL_WRITE_REQUEST_EB_SHIFT                       0
     101             : 
     102             : #define IPE_RFC_RFC2697           0x00000000
     103             : #define IPE_RFC_RFC2698           0x00000001
     104             : #define IPE_RFC_RFC4115           0x00000002
     105             : #define IPE_RFC_MEF5CF1           0x00000003
     106             : 
     107             : /* End of constants copied from sse_ipe_desc_fmt.h */
     108             : 
     109             : /* Misc Policer specific definitions */
     110             : #define QOS_POLICER_FIXED_PKT_SIZE 256
     111             : 
     112             : #define QOS_POL_TICKS_PER_SEC 1000LL /* 1 tick = 1 ms */
     113             : 
     114             : /*
     115             :  * Default burst, in ms (byte format)
     116             :  */
     117             : #define QOS_POL_DEF_BURST_BYTE 100
     118             : 
     119             : /*
     120             :  * Minimum burst needs to be such that the largest packet size is accommodated
     121             :  */
     122             : #define QOS_POL_MIN_BURST_BYTE 9 * 1024
     123             : 
     124             : /*
     125             :  * Flag to indicate if AN is employed or not
     126             :  * 1 - TRUE, 0 - FALSE
     127             :  */
     128             : #define QOS_POL_ALLOW_NEGATIVE 1
     129             : 
     130             : /* Various Macros to take care of policer calculations */
     131             : 
     132             : #define QOS_POL_COMM_BKT_MAX (1 << IPE_POLICER_FULL_WRITE_REQUEST_CB_MASK)
     133             : #define QOS_POL_EXTD_BKT_MAX (1 << IPE_POLICER_FULL_WRITE_REQUEST_EB_MASK)
     134             : 
     135             : #define QOS_POL_RATE_EXP_SIZE      (IPE_POLICER_FULL_WRITE_REQUEST_REXP_MASK)
     136             : #define QOS_POL_RATE_EXP_MAX       ((1 << QOS_POL_RATE_EXP_SIZE) - 1)
     137             : #define QOS_POL_AVG_RATE_MANT_SIZE (IPE_POLICER_FULL_WRITE_REQUEST_ARM_MASK)
     138             : #define QOS_POL_AVG_RATE_MANT_MAX  ((1 << QOS_POL_AVG_RATE_MANT_SIZE) - 1)
     139             : #define QOS_POL_AVG_RATE_MAX                                                  \
     140             :   (QOS_POL_AVG_RATE_MANT_MAX << QOS_POL_RATE_EXP_MAX)
     141             : 
     142             : #define QOS_POL_PEAK_RATE_MANT_SIZE (IPE_POLICER_FULL_WRITE_REQUEST_PRM_MASK)
     143             : #define QOS_POL_PEAK_RATE_MANT_MAX  ((1 << QOS_POL_PEAK_RATE_MANT_SIZE) - 1)
     144             : #define QOS_POL_PEAK_RATE_MAX                                                 \
     145             :   (QOS_POL_PEAK_RATE_MANT_MAX << QOS_POL_RATE_EXP_MAX)
     146             : 
     147             : #define QOS_POL_COMM_BKT_LIMIT_MANT_SIZE                                      \
     148             :   (IPE_POLICER_FULL_WRITE_REQUEST_CBLM_MASK)
     149             : #define QOS_POL_COMM_BKT_LIMIT_MANT_MAX                                       \
     150             :   ((1 << QOS_POL_COMM_BKT_LIMIT_MANT_SIZE) - 1)
     151             : #define QOS_POL_COMM_BKT_LIMIT_EXP_SIZE                                       \
     152             :   (IPE_POLICER_FULL_WRITE_REQUEST_CBLE_MASK)
     153             : #define QOS_POL_COMM_BKT_LIMIT_EXP_MAX                                        \
     154             :   ((1 << QOS_POL_COMM_BKT_LIMIT_EXP_SIZE) - 1)
     155             : #define QOS_POL_COMM_BKT_LIMIT_MAX                                            \
     156             :   ((u64) QOS_POL_COMM_BKT_LIMIT_MANT_MAX                                      \
     157             :    << (u64) QOS_POL_COMM_BKT_LIMIT_EXP_MAX)
     158             : 
     159             : #define QOS_POL_EXTD_BKT_LIMIT_MANT_SIZE                                      \
     160             :   (IPE_POLICER_FULL_WRITE_REQUEST_EBLM_MASK)
     161             : #define QOS_POL_EXTD_BKT_LIMIT_MANT_MAX                                       \
     162             :   ((1 << QOS_POL_EXTD_BKT_LIMIT_MANT_SIZE) - 1)
     163             : #define QOS_POL_EXTD_BKT_LIMIT_EXP_SIZE                                       \
     164             :   (IPE_POLICER_FULL_WRITE_REQUEST_EBLE_MASK)
     165             : #define QOS_POL_EXTD_BKT_LIMIT_EXP_MAX                                        \
     166             :   ((1 << QOS_POL_EXTD_BKT_LIMIT_EXP_SIZE) - 1)
     167             : #define QOS_POL_EXT_BKT_LIMIT_MAX                                             \
     168             :   ((u64) QOS_POL_EXTD_BKT_LIMIT_MANT_MAX                                      \
     169             :    << (u64) QOS_POL_EXTD_BKT_LIMIT_EXP_MAX)
     170             : 
     171             : /*
     172             :  * Rates determine the units of the bucket
     173             :  *    256.114688 Gbps < Rate                      8 byte units
     174             :  *    128.057344 Gbps < Rate <= 256.114688 Gbps   4 byte units
     175             :  *     64.028672 Gbps < Rate <= 128.057344 Gbps   2 byte units
     176             :  *                      Rate <=  64.028672 Gbps   1 byte units
     177             :  *
     178             :  * The code uses bytes per tick as oppose to Gigabits per second.
     179             :  */
     180             : #define RATE256 (256114688000LL / 8LL / QOS_POL_TICKS_PER_SEC)
     181             : #define RATE128 (128057344000LL / 8LL / QOS_POL_TICKS_PER_SEC)
     182             : #define RATE64  (64028672000LL / 8LL / QOS_POL_TICKS_PER_SEC)
     183             : 
     184             : #define RATE_OVER256_UNIT  8LL
     185             : #define RATE_128TO256_UNIT 4LL
     186             : #define RATE_64TO128_UNIT  2LL
     187             : 
     188             : static int
     189          20 : qos_pol_round (u64 numerator, u64 denominator, u64 *rounded_value,
     190             :                qos_round_type_en round_type)
     191             : {
     192          20 :   int rc = 0;
     193             : 
     194          20 :   if (denominator == 0)
     195             :     {
     196           0 :       QOS_DEBUG_ERROR ("Illegal denominator");
     197           0 :       return (EINVAL);
     198             :     }
     199             : 
     200          20 :   switch (round_type)
     201             :     {
     202          20 :     case QOS_ROUND_TO_CLOSEST:
     203          20 :       *rounded_value = ((numerator + (denominator >> 1)) / denominator);
     204          20 :       break;
     205             : 
     206           0 :     case QOS_ROUND_TO_UP:
     207           0 :       *rounded_value = (numerator / denominator);
     208           0 :       if ((*rounded_value * denominator) < numerator)
     209             :         {
     210           0 :           *rounded_value += 1;
     211             :         }
     212           0 :       break;
     213             : 
     214           0 :     case QOS_ROUND_TO_DOWN:
     215           0 :       *rounded_value = (numerator / denominator);
     216           0 :       break;
     217             : 
     218           0 :     case QOS_ROUND_INVALID:
     219             :     default:
     220           0 :       QOS_DEBUG_ERROR ("Illegal round type");
     221           0 :       rc = EINVAL;
     222           0 :       break;
     223             :     }
     224          20 :   return (rc);
     225             : }
     226             : 
     227             : static int
     228           0 : pol_validate_cfg_params (qos_pol_cfg_params_st *cfg)
     229             : {
     230             :   u64 numer, denom, rnd_value;
     231             :   u32 cir_hw, eir_hw;
     232           0 :   int rc = 0;
     233             : 
     234           0 :   if ((cfg->rfc == QOS_POLICER_TYPE_2R3C_RFC_2698) &&
     235           0 :       (cfg->rb.kbps.eir_kbps < cfg->rb.kbps.cir_kbps))
     236             :     {
     237           0 :       QOS_DEBUG_ERROR ("CIR (%u kbps) is greater than PIR (%u kbps)",
     238             :                        cfg->rb.kbps.cir_kbps, cfg->rb.kbps.eir_kbps);
     239           0 :       return (EINVAL);
     240             :     }
     241             : 
     242             :   /*
     243             :    * convert rates to bytes-per-tick
     244             :    */
     245           0 :   numer = (u64) (cfg->rb.kbps.cir_kbps);
     246           0 :   denom = (u64) (8 * QOS_POL_TICKS_PER_SEC) / 1000;
     247           0 :   rc = qos_pol_round (numer, denom, &rnd_value, cfg->rnd_type);
     248           0 :   if (rc != 0)
     249             :     {
     250           0 :       QOS_DEBUG_ERROR ("Unable to convert CIR to bytes/tick format");
     251           0 :       return (rc);
     252             :     }
     253           0 :   cir_hw = (u32) rnd_value;
     254             : 
     255           0 :   numer = (u64) (cfg->rb.kbps.eir_kbps);
     256           0 :   rc = qos_pol_round (numer, denom, &rnd_value, cfg->rnd_type);
     257           0 :   if (rc != 0)
     258             :     {
     259           0 :       QOS_DEBUG_ERROR ("Unable to convert EIR to bytes/tick format");
     260           0 :       return (rc);
     261             :     }
     262           0 :   eir_hw = (u32) rnd_value;
     263             : 
     264           0 :   if (cir_hw > QOS_POL_AVG_RATE_MAX)
     265             :     {
     266           0 :       QOS_DEBUG_ERROR ("hw cir (%u bytes/tick) is greater than the "
     267             :                        "max supported value (%u)",
     268             :                        cir_hw, QOS_POL_AVG_RATE_MAX);
     269           0 :       return (EINVAL);
     270             :     }
     271             : 
     272           0 :   if (eir_hw > QOS_POL_PEAK_RATE_MAX)
     273             :     {
     274           0 :       QOS_DEBUG_ERROR ("hw eir (%u bytes/tick) is greater than the "
     275             :                        "max supported value (%u). Capping it to the max. "
     276             :                        "supported value",
     277             :                        eir_hw, QOS_POL_PEAK_RATE_MAX);
     278           0 :       return (EINVAL);
     279             :     }
     280             :   /*
     281             :    * CIR = 0, with bc != 0 is not allowed
     282             :    */
     283           0 :   if ((cfg->rb.kbps.cir_kbps == 0) && cfg->rb.kbps.cb_bytes)
     284             :     {
     285           0 :       QOS_DEBUG_ERROR ("CIR = 0 with bc != 0");
     286           0 :       return (EINVAL);
     287             :     }
     288             : 
     289           0 :   if ((cfg->rb.kbps.eir_kbps == 0) &&
     290           0 :       (cfg->rfc > QOS_POLICER_TYPE_1R3C_RFC_2697))
     291             :     {
     292           0 :       QOS_DEBUG_ERROR ("EIR = 0 for a 2R3C policer (rfc: %u)", cfg->rfc);
     293           0 :       return (EINVAL);
     294             :     }
     295             : 
     296           0 :   if (cfg->rb.kbps.eir_kbps && (cfg->rfc < QOS_POLICER_TYPE_2R3C_RFC_2698))
     297             :     {
     298           0 :       QOS_DEBUG_ERROR ("EIR: %u kbps for a 1-rate policer (rfc: %u)",
     299             :                        cfg->rb.kbps.eir_kbps, cfg->rfc);
     300           0 :       return (EINVAL);
     301             :     }
     302             : 
     303           0 :   if ((cfg->rfc == QOS_POLICER_TYPE_1R2C) && cfg->rb.kbps.eb_bytes)
     304             :     {
     305           0 :       QOS_DEBUG_ERROR ("For a 1R1B policer, EB burst cannot be > 0");
     306           0 :       return (EINVAL);
     307             :     }
     308             : 
     309           0 :   return (0);
     310             : }
     311             : 
     312             : static void
     313           0 : qos_convert_value_to_exp_mant_fmt (u64 value, u16 max_exp_value,
     314             :                                    u16 max_mant_value, qos_round_type_en type,
     315             :                                    u8 *exp, u32 *mant)
     316             : {
     317             :   u64 rnd_value;
     318             :   u64 temp_mant;
     319             :   u8 temp_exp;
     320             : 
     321             :   /*
     322             :    * Select the lowest possible exp, and the largest possible mant
     323             :    */
     324           0 :   temp_exp = 0;
     325           0 :   temp_mant = value;
     326           0 :   while (temp_exp <= max_exp_value)
     327             :     {
     328           0 :       if (temp_mant <= max_mant_value)
     329             :         {
     330           0 :           break;
     331             :         }
     332             : 
     333           0 :       temp_exp++;
     334           0 :       rnd_value = 0;
     335           0 :       (void) qos_pol_round ((u64) value, (u64) (1 << temp_exp), &rnd_value,
     336             :                             type);
     337           0 :       temp_mant = rnd_value;
     338             :     }
     339             : 
     340           0 :   if (temp_exp > max_exp_value)
     341             :     {
     342             :       /*
     343             :        * CAP mant to its max value, and decrement exp
     344             :        */
     345           0 :       temp_exp--;
     346           0 :       temp_mant = max_mant_value;
     347             :     }
     348             : 
     349           0 :   *exp = temp_exp;
     350           0 :   *mant = (u32) temp_mant;
     351             : 
     352           0 :   QOS_DEBUG_INFO ("value: 0x%llx, mant: %u, exp: %u", value, *mant, *exp);
     353           0 :   return;
     354             : }
     355             : 
     356             : static int
     357           0 : pol_convert_cfg_rates_to_hw (qos_pol_cfg_params_st *cfg,
     358             :                              qos_pol_hw_params_st *hw)
     359             : {
     360           0 :   int rc = 0;
     361             :   u32 cir_hw, eir_hw, hi_mant, hi_rate, cir_rnded, eir_rnded, eir_kbps;
     362             :   u64 numer, denom, rnd_value;
     363             :   u8 exp;
     364             : 
     365             :   /*
     366             :    * convert rates to bytes-per-tick (tick is 1ms)
     367             :    * For rate conversion, the denominator is gonna be the same
     368             :    */
     369           0 :   denom = (u64) ((QOS_POL_TICKS_PER_SEC * 8) / 1000);
     370           0 :   numer = (u64) (cfg->rb.kbps.cir_kbps);
     371           0 :   rc = qos_pol_round (numer, denom, &rnd_value, cfg->rnd_type);
     372           0 :   if (rc != 0)
     373             :     {
     374           0 :       QOS_DEBUG_ERROR ("Rounding error, rate: %d kbps, rounding_type: %d",
     375             :                        cfg->rb.kbps.cir_kbps, cfg->rnd_type);
     376           0 :       return (rc);
     377             :     }
     378           0 :   cir_hw = (u32) rnd_value;
     379             : 
     380           0 :   if (cfg->rb.kbps.cir_kbps && (cir_hw == 0))
     381             :     {
     382             :       /*
     383             :        * After rounding, cir_hw = 0. Bump it up
     384             :        */
     385           0 :       cir_hw = 1;
     386             :     }
     387             : 
     388           0 :   if (cfg->rfc == QOS_POLICER_TYPE_1R2C)
     389             :     {
     390           0 :       eir_kbps = 0;
     391             :     }
     392           0 :   else if (cfg->rfc == QOS_POLICER_TYPE_1R3C_RFC_2697)
     393             :     {
     394           0 :       eir_kbps = cfg->rb.kbps.cir_kbps;
     395             :     }
     396           0 :   else if (cfg->rfc == QOS_POLICER_TYPE_2R3C_RFC_4115)
     397             :     {
     398           0 :       eir_kbps = cfg->rb.kbps.eir_kbps - cfg->rb.kbps.cir_kbps;
     399             :     }
     400             :   else
     401             :     {
     402           0 :       eir_kbps = cfg->rb.kbps.eir_kbps;
     403             :     }
     404             : 
     405           0 :   numer = (u64) eir_kbps;
     406           0 :   rc = qos_pol_round (numer, denom, &rnd_value, cfg->rnd_type);
     407           0 :   if (rc != 0)
     408             :     {
     409           0 :       QOS_DEBUG_ERROR ("Rounding error, rate: %d kbps, rounding_type: %d",
     410             :                        eir_kbps, cfg->rnd_type);
     411           0 :       return (rc);
     412             :     }
     413           0 :   eir_hw = (u32) rnd_value;
     414             : 
     415           0 :   if (eir_kbps && (eir_hw == 0))
     416             :     {
     417             :       /*
     418             :        * After rounding, eir_hw = 0. Bump it up
     419             :        */
     420           0 :       eir_hw = 1;
     421             :     }
     422             : 
     423           0 :   QOS_DEBUG_INFO ("cir_hw: %u bytes/tick, eir_hw: %u bytes/tick", cir_hw,
     424             :                   eir_hw);
     425             : 
     426           0 :   if (cir_hw > eir_hw)
     427             :     {
     428           0 :       hi_rate = cir_hw;
     429             :     }
     430             :   else
     431             :     {
     432           0 :       hi_rate = eir_hw;
     433             :     }
     434             : 
     435           0 :   if ((cir_hw == 0) && (eir_hw == 0))
     436             :     {
     437             :       /*
     438             :        * Both the rates are 0. Use exp = 15, and set the RFC to 4115. Also
     439             :        * set AN = 0
     440             :        */
     441           0 :       exp = (u8) QOS_POL_RATE_EXP_MAX;
     442           0 :       hi_mant = 0;
     443           0 :       hw->rfc = IPE_RFC_RFC4115;
     444           0 :       hw->allow_negative = 0;
     445             :     }
     446             :   else
     447             :     {
     448           0 :       qos_convert_value_to_exp_mant_fmt (hi_rate, (u16) QOS_POL_RATE_EXP_MAX,
     449             :                                          (u16) QOS_POL_AVG_RATE_MANT_MAX,
     450           0 :                                          cfg->rnd_type, &exp, &hi_mant);
     451             :     }
     452             : 
     453           0 :   denom = (1ULL << exp);
     454           0 :   if (hi_rate == eir_hw)
     455             :     {
     456           0 :       hw->peak_rate_man = (u16) hi_mant;
     457           0 :       rc = qos_pol_round ((u64) cir_hw, denom, &rnd_value, cfg->rnd_type);
     458           0 :       hw->avg_rate_man = (u16) rnd_value;
     459             :     }
     460             :   else
     461             :     {
     462           0 :       hw->avg_rate_man = (u16) hi_mant;
     463           0 :       rc = qos_pol_round ((u64) eir_hw, denom, &rnd_value, cfg->rnd_type);
     464           0 :       hw->peak_rate_man = (u16) rnd_value;
     465             :     }
     466           0 :   if (rc != 0)
     467             :     {
     468           0 :       QOS_DEBUG_ERROR ("Rounding error");
     469           0 :       return (rc);
     470             :     }
     471           0 :   hw->rate_exp = exp;
     472             : 
     473           0 :   if ((hw->avg_rate_man == 0) && (cfg->rb.kbps.cir_kbps))
     474             :     {
     475             :       /*
     476             :        * cir was reduced to 0 during rounding. Bump it up
     477             :        */
     478           0 :       hw->avg_rate_man = 1;
     479           0 :       QOS_DEBUG_INFO ("CIR = 0 during rounding. Bump it up to %u "
     480             :                       "bytes/tick",
     481             :                       (hw->avg_rate_man << hw->rate_exp));
     482             :     }
     483             : 
     484           0 :   if ((hw->peak_rate_man == 0) && eir_kbps)
     485             :     {
     486             :       /*
     487             :        * eir was reduced to 0 during rounding. Bump it up
     488             :        */
     489           0 :       hw->peak_rate_man = 1;
     490           0 :       QOS_DEBUG_INFO ("EIR = 0 during rounding. Bump it up to %u "
     491             :                       "bytes/tick",
     492             :                       (hw->peak_rate_man << hw->rate_exp));
     493             :     }
     494             : 
     495           0 :   cir_rnded = (hw->avg_rate_man << hw->rate_exp);
     496           0 :   eir_rnded = (hw->peak_rate_man << hw->rate_exp);
     497             : 
     498           0 :   QOS_DEBUG_INFO ("Configured(rounded) values, cir: %u "
     499             :                   "kbps (mant: %u, exp: %u, rate: %u bytes/tick)",
     500             :                   cfg->rb.kbps.cir_kbps, hw->avg_rate_man, hw->rate_exp,
     501             :                   cir_rnded);
     502             : 
     503           0 :   QOS_DEBUG_INFO ("Configured(rounded) values, eir: %u "
     504             :                   "kbps (mant: %u, exp: %u, rate: %u bytes/tick)",
     505             :                   cfg->rb.kbps.eir_kbps, hw->peak_rate_man, hw->rate_exp,
     506             :                   eir_rnded);
     507             : 
     508           0 :   return (rc);
     509             : }
     510             : 
     511             : /*****
     512             :  * NAME
     513             :  *   pol_get_bkt_max
     514             :  *
     515             :  * PARAMETERS
     516             :  *  rate_hw    - either the average rate or peak rate
     517             :  *  bkt_max    - bit width in the current bucket or extended bucket
     518             :  *
     519             :  * RETURNS
     520             :  *  u64   - maximum token bytes for the current or extended bucket
     521             :  *
     522             :  * DESCRIPTION
     523             :  *  The current bucket or extended bucket fields are in units of either
     524             :  *  1,2,4,8 bytes based on the average or peak rate respective to current
     525             :  *  or extended bucket.
     526             :  *
     527             :  *  To get the actual maximum number of bytes that can be stored in the
     528             :  *  field, the value must be multiplied by the units of either 1,2,4,8
     529             :  *  bytes based on the rate.
     530             :  *****/
     531             : u64
     532           0 : pol_get_bkt_max (u64 rate_hw, u64 bkt_max)
     533             : {
     534           0 :   if (rate_hw <= RATE64)
     535             :     {
     536           0 :       return (bkt_max - 1);
     537             :     }
     538           0 :   else if (rate_hw <= RATE128)
     539             :     {
     540           0 :       return ((bkt_max * RATE_64TO128_UNIT) - RATE_64TO128_UNIT);
     541             :     }
     542           0 :   else if (rate_hw <= RATE256)
     543             :     {
     544           0 :       return ((bkt_max * RATE_128TO256_UNIT) - RATE_128TO256_UNIT);
     545             :     }
     546             :   /* rate must be over 256 */
     547           0 :   return ((bkt_max * RATE_OVER256_UNIT) - RATE_OVER256_UNIT);
     548             : }
     549             : 
     550             : /*****
     551             :  * NAME
     552             :  *   pol_get_bkt_value
     553             :  *
     554             :  * PARAMETERS
     555             :  *  rate_hw    - either the average rate or peak rate
     556             :  *  byte_value - bytes for this token bucket
     557             :  *
     558             :  * RETURNS
     559             :  *  u64   - unit value for the current or extended bucket field
     560             :  *
     561             :  * DESCRIPTION
     562             :  *  The current bucket or extended bucket fields are in units of either
     563             :  *  1,2,4,8 bytes based on the average or peak rate respective to current
     564             :  *  or extended bucket.
     565             :  *
     566             :  *  To get the units that can be stored in the field, the byte value must
     567             :  *  be divided by the units of either 1,2,4,8 bytes based on the rate.
     568             :  *****/
     569             : u64
     570           0 : pol_get_bkt_value (u64 rate_hw, u64 byte_value)
     571             : {
     572           0 :   if (rate_hw <= RATE64)
     573             :     {
     574           0 :       return (byte_value);
     575             :     }
     576           0 :   else if (rate_hw <= RATE128)
     577             :     {
     578           0 :       return (byte_value / RATE_64TO128_UNIT);
     579             :     }
     580           0 :   else if (rate_hw <= RATE256)
     581             :     {
     582           0 :       return (byte_value / RATE_128TO256_UNIT);
     583             :     }
     584             :   /* rate must be over 256 */
     585           0 :   return (byte_value / RATE_OVER256_UNIT);
     586             : }
     587             : 
     588             : static void
     589           0 : pol_rnd_burst_byte_fmt (u64 cfg_burst, u16 max_exp_value, u16 max_mant_value,
     590             :                         u32 max_bkt_value, u32 rate_hw, u8 *exp, u32 *mant,
     591             :                         u32 *bkt_value)
     592             : {
     593           0 :   u64 bkt_max = max_bkt_value;
     594             :   u64 bkt_limit_max;
     595             :   u64 rnd_burst;
     596             :   u64 temp_bkt_value;
     597             : 
     598           0 :   bkt_limit_max = ((u64) max_mant_value << (u64) max_exp_value);
     599           0 :   bkt_max = pol_get_bkt_max (rate_hw, bkt_max);
     600           0 :   bkt_max = MIN (bkt_max, bkt_limit_max);
     601           0 :   if (!cfg_burst)
     602             :     {
     603             :       /*
     604             :        * If configured burst = 0, compute the burst to be 100ms at a given
     605             :        * rate. Note that for rate_hw = 0, exp = mant = 0.
     606             :        */
     607           0 :       cfg_burst = (u64) rate_hw * (u64) QOS_POL_DEF_BURST_BYTE;
     608             :     }
     609             : 
     610           0 :   if (cfg_burst > bkt_max)
     611             :     {
     612           0 :       QOS_DEBUG_ERROR ("burst 0x%llx bytes is greater than the max. "
     613             :                        "supported value 0x%llx bytes. Capping it to the "
     614             :                        "max",
     615             :                        cfg_burst, bkt_max);
     616           0 :       cfg_burst = bkt_max;
     617             :     }
     618             : 
     619           0 :   if (cfg_burst < QOS_POL_MIN_BURST_BYTE)
     620             :     {
     621             :       /*
     622             :        * Bump up the burst value ONLY if the cfg_burst is non-zero AND
     623             :        * less than the min. supported value
     624             :        */
     625           0 :       QOS_DEBUG_INFO ("burst 0x%llx bytes is less than the min "
     626             :                       "supported value %u bytes. Rounding it up to "
     627             :                       "the min",
     628             :                       cfg_burst, QOS_POL_MIN_BURST_BYTE);
     629           0 :       cfg_burst = QOS_POL_MIN_BURST_BYTE;
     630             :     }
     631             : 
     632           0 :   qos_convert_value_to_exp_mant_fmt (cfg_burst, max_exp_value, max_mant_value,
     633             :                                      QOS_ROUND_TO_DOWN, exp, mant);
     634             : 
     635             :   /* Bucket value is based on rate. */
     636           0 :   rnd_burst = ((u64) (*mant) << (u64) (*exp));
     637           0 :   temp_bkt_value = pol_get_bkt_value (rate_hw, rnd_burst);
     638           0 :   *bkt_value = (u32) temp_bkt_value;
     639           0 : }
     640             : 
     641             : static int
     642           0 : pol_convert_cfg_burst_to_hw (qos_pol_cfg_params_st *cfg,
     643             :                              qos_pol_hw_params_st *hw)
     644             : {
     645             :   u8 temp_exp;
     646             :   u32 temp_mant, rate_hw;
     647             :   u64 eb_bytes;
     648             :   u32 bkt_value;
     649             : 
     650             :   /*
     651             :    * compute Committed Burst
     652             :    */
     653           0 :   QOS_DEBUG_INFO ("Compute commit burst ...");
     654           0 :   rate_hw = (hw->avg_rate_man) << (hw->rate_exp);
     655           0 :   pol_rnd_burst_byte_fmt (
     656             :     cfg->rb.kbps.cb_bytes, (u16) QOS_POL_COMM_BKT_LIMIT_EXP_MAX,
     657             :     (u16) QOS_POL_COMM_BKT_LIMIT_MANT_MAX, (u32) QOS_POL_COMM_BKT_MAX, rate_hw,
     658             :     &temp_exp, &temp_mant, &bkt_value);
     659           0 :   QOS_DEBUG_INFO ("Committed burst, burst_limit: 0x%llx mant : %u, "
     660             :                   "exp: %u, rnded: 0x%llx cb:%u bytes",
     661             :                   cfg->rb.kbps.cb_bytes, temp_mant, temp_exp,
     662             :                   ((u64) temp_mant << (u64) temp_exp), bkt_value);
     663             : 
     664           0 :   hw->comm_bkt_limit_exp = temp_exp;
     665           0 :   hw->comm_bkt_limit_man = (u8) temp_mant;
     666           0 :   hw->comm_bkt = bkt_value;
     667             : 
     668             :   /*
     669             :    * compute Exceed Burst
     670             :    */
     671           0 :   QOS_DEBUG_INFO ("Compute exceed burst ...");
     672             : 
     673           0 :   if (cfg->rfc == QOS_POLICER_TYPE_1R2C)
     674             :     {
     675             :       /*
     676             :        * For 1R2C, hw uses 2R3C (RFC-4115). As such, the Exceed Bucket
     677             :        * params are set to 0. Recommendation is to use EB_exp = max_exp (=15)
     678             :        * and EB_mant = 0
     679             :        */
     680           0 :       hw->extd_bkt_limit_exp = (u8) QOS_POL_EXTD_BKT_LIMIT_EXP_MAX;
     681           0 :       hw->extd_bkt_limit_man = 0;
     682           0 :       QOS_DEBUG_INFO (
     683             :         "Excess burst, burst: 0x%llx mant: %u, "
     684             :         "exp: %u, rnded: 0x%llx bytes",
     685             :         cfg->rb.kbps.eb_bytes, hw->extd_bkt_limit_man, hw->extd_bkt_limit_exp,
     686             :         ((u64) hw->extd_bkt_limit_man << (u64) hw->extd_bkt_limit_exp));
     687           0 :       return (0);
     688             :     }
     689             : 
     690           0 :   if (cfg->rfc == QOS_POLICER_TYPE_1R3C_RFC_2697)
     691             :     {
     692           0 :       eb_bytes = cfg->rb.kbps.cb_bytes + cfg->rb.kbps.eb_bytes;
     693             :     }
     694           0 :   else if (cfg->rfc == QOS_POLICER_TYPE_2R3C_RFC_4115)
     695             :     {
     696           0 :       eb_bytes = cfg->rb.kbps.eb_bytes - cfg->rb.kbps.cb_bytes;
     697             :     }
     698             :   else
     699             :     {
     700           0 :       eb_bytes = cfg->rb.kbps.eb_bytes;
     701             :     }
     702             : 
     703           0 :   rate_hw = (hw->peak_rate_man) << (hw->rate_exp);
     704           0 :   pol_rnd_burst_byte_fmt (eb_bytes, (u16) QOS_POL_EXTD_BKT_LIMIT_EXP_MAX,
     705             :                           (u16) QOS_POL_EXTD_BKT_LIMIT_MANT_MAX,
     706             :                           (u32) QOS_POL_EXTD_BKT_MAX, rate_hw, &temp_exp,
     707             :                           &temp_mant, &bkt_value);
     708             : 
     709           0 :   QOS_DEBUG_INFO ("Excess burst, burst_limit: 0x%llx mant: %u, "
     710             :                   "exp: %u, rnded: 0x%llx eb:%u bytes",
     711             :                   cfg->rb.kbps.eb_bytes, temp_mant, temp_exp,
     712             :                   ((u64) temp_mant << (u64) temp_exp), bkt_value);
     713             : 
     714           0 :   hw->extd_bkt_limit_exp = (u8) temp_exp;
     715           0 :   hw->extd_bkt_limit_man = (u8) temp_mant;
     716           0 :   hw->extd_bkt = bkt_value;
     717             : 
     718           0 :   return (0);
     719             : }
     720             : 
     721             : 
     722             : /*
     723             :  * Input: configured parameter values in 'cfg'.
     724             :  * Output: h/w programmable parameter values in 'hw'.
     725             :  * Return: success or failure code.
     726             :  */
     727             : static int
     728           0 : pol_convert_cfg_to_hw_params (qos_pol_cfg_params_st *cfg,
     729             :                               qos_pol_hw_params_st *hw)
     730             : {
     731           0 :   int rc = 0;
     732             : 
     733             :   /*
     734             :    * clear the hw_params
     735             :    */
     736           0 :   clib_memset (hw, 0, sizeof (qos_pol_hw_params_st));
     737             : 
     738           0 :   hw->allow_negative = QOS_POL_ALLOW_NEGATIVE;
     739             : 
     740           0 :   if ((cfg->rfc == QOS_POLICER_TYPE_1R2C) ||
     741           0 :       (cfg->rfc == QOS_POLICER_TYPE_2R3C_RFC_4115))
     742             :     {
     743           0 :       hw->rfc = IPE_RFC_RFC4115;
     744             :     }
     745           0 :   else if (cfg->rfc == QOS_POLICER_TYPE_1R3C_RFC_2697)
     746             :     {
     747           0 :       hw->rfc = IPE_RFC_RFC2697;
     748             :     }
     749           0 :   else if (cfg->rfc == QOS_POLICER_TYPE_2R3C_RFC_2698)
     750             :     {
     751           0 :       hw->rfc = IPE_RFC_RFC2698;
     752             :     }
     753           0 :   else if (cfg->rfc == QOS_POLICER_TYPE_2R3C_RFC_MEF5CF1)
     754             :     {
     755           0 :       hw->rfc = IPE_RFC_MEF5CF1;
     756             :     }
     757             :   else
     758             :     {
     759           0 :       QOS_DEBUG_ERROR ("Invalid RFC type %d\n", cfg->rfc);
     760           0 :       return (EINVAL);
     761             :     }
     762             : 
     763           0 :   rc = pol_convert_cfg_rates_to_hw (cfg, hw);
     764           0 :   if (rc != 0)
     765             :     {
     766           0 :       QOS_DEBUG_ERROR ("Unable to convert config rates to hw. Error: %d", rc);
     767           0 :       return (rc);
     768             :     }
     769             : 
     770           0 :   rc = pol_convert_cfg_burst_to_hw (cfg, hw);
     771           0 :   if (rc != 0)
     772             :     {
     773           0 :       QOS_DEBUG_ERROR ("Unable to convert config burst to hw. Error: %d", rc);
     774           0 :       return (rc);
     775             :     }
     776             : 
     777           0 :   return 0;
     778             : }
     779             : 
     780             : u32
     781          10 : qos_convert_pps_to_kbps (u32 rate_pps)
     782             : {
     783          10 :   u64 numer, rnd_value = 0;
     784             : 
     785          10 :   numer = (u64) ((u64) rate_pps * (u64) QOS_POLICER_FIXED_PKT_SIZE * 8LL);
     786          10 :   (void) qos_pol_round (numer, 1000LL, &rnd_value, QOS_ROUND_TO_CLOSEST);
     787             : 
     788          10 :   return ((u32) rnd_value);
     789             : }
     790             : 
     791             : u32
     792          10 : qos_convert_burst_ms_to_bytes (u32 burst_ms, u32 rate_kbps)
     793             : {
     794          10 :   u64 numer, rnd_value = 0;
     795             : 
     796          10 :   numer = (u64) ((u64) burst_ms * (u64) rate_kbps);
     797             : 
     798          10 :   (void) qos_pol_round (numer, 8LL, &rnd_value, QOS_ROUND_TO_CLOSEST);
     799             : 
     800          10 :   return ((u32) rnd_value);
     801             : }
     802             : 
     803             : 
     804             : /*
     805             :  * Input: configured parameters in 'cfg'.
     806             :  * Output: h/w parameters are returned in 'hw',
     807             :  * Return: Status, success or failure code.
     808             :  */
     809             : int
     810           0 : pol_compute_hw_params (qos_pol_cfg_params_st *cfg, qos_pol_hw_params_st *hw)
     811             : {
     812           0 :   int rc = 0;
     813             : 
     814           0 :   if (!cfg || !hw)
     815             :     {
     816           0 :       QOS_DEBUG_ERROR ("Illegal parameters");
     817           0 :       return (-1);
     818             :     }
     819             : 
     820             :   /*
     821             :    * Validate the police config params being presented to RM
     822             :    */
     823           0 :   rc = pol_validate_cfg_params (cfg);
     824           0 :   if (rc != 0)
     825             :     {
     826           0 :       QOS_DEBUG_ERROR ("Config parameter validation failed. Error: %d", rc);
     827           0 :       return (-1);
     828             :     }
     829             : 
     830             :   /*
     831             :    * first round configured values to h/w supported values. This func
     832             :    * also determines whether 'tick' or 'byte' format
     833             :    */
     834           0 :   rc = pol_convert_cfg_to_hw_params (cfg, hw);
     835           0 :   if (rc != 0)
     836             :     {
     837           0 :       QOS_DEBUG_ERROR ("Unable to convert config params to hw params. "
     838             :                        "Error: %d",
     839             :                        rc);
     840           0 :       return (-1);
     841             :     }
     842             : 
     843           0 :   return 0;
     844             : }
     845             : 
     846             : /*
     847             :  * Return the number of hardware TSC timer ticks per second for the dataplane.
     848             :  * This is approximately, but not exactly, the clock speed.
     849             :  */
     850             : static u64
     851          29 : get_tsc_hz (void)
     852             : {
     853             :   f64 cpu_freq;
     854             : 
     855          29 :   cpu_freq = os_cpu_clock_frequency ();
     856          29 :   return (u64) cpu_freq;
     857             : }
     858             : 
     859             : /*
     860             :  * Convert rates into bytes_per_period and scale.
     861             :  * Return 0 if ok or 1 if error.
     862             :  */
     863             : static int
     864          29 : compute_policer_params (u64 hz,       /* CPU speed in clocks per second */
     865             :                         u64 cir_rate, /* in bytes per second */
     866             :                         u64 pir_rate, /* in bytes per second */
     867             :                         u32 *current_limit,  /* in bytes, output may scale
     868             :                                               * the input
     869             :                                               */
     870             :                         u32 *extended_limit, /* in bytes, output may scale
     871             :                                               * the input
     872             :                                               */
     873             :                         u32 *cir_bytes_per_period, u32 *pir_bytes_per_period,
     874             :                         u32 *scale)
     875             : {
     876             :   double period;
     877             :   double internal_cir_bytes_per_period;
     878             :   double internal_pir_bytes_per_period;
     879             :   u32 max;
     880             :   u32 scale_shift;
     881             :   u32 scale_amount;
     882          29 :   u32 __attribute__ ((unused)) orig_current_limit = *current_limit;
     883             : 
     884             :   /*
     885             :    * Compute period. For 1Ghz-to-8Ghz CPUs, the period will be in
     886             :    * the range of 16 to 116 usec.
     887             :    */
     888          29 :   period = ((double) hz) / ((double) POLICER_TICKS_PER_PERIOD);
     889             : 
     890             :   /* Determine bytes per period for each rate */
     891          29 :   internal_cir_bytes_per_period = (double) cir_rate / period;
     892          29 :   internal_pir_bytes_per_period = (double) pir_rate / period;
     893             : 
     894             :   /*
     895             :    * Scale if possible. Scaling helps rate accuracy, but is constrained
     896             :    * by the scaled rates and limits fitting in 32-bits.
     897             :    * In addition, we need to insure the scaled rate is no larger than
     898             :    * 2^22 tokens per period. This allows the dataplane to ignore overflow
     899             :    * in the tokens-per-period multiplication since it could only
     900             :    * happen if the policer were idle for more than a year.
     901             :    * This is not really a constraint because 100Gbps at 1Ghz is only
     902             :    * 1.6M tokens per period.
     903             :    */
     904             : #define MAX_RATE_SHIFT 10
     905          29 :   max = MAX (*current_limit, *extended_limit);
     906          29 :   max = MAX (max, (u32) internal_cir_bytes_per_period << MAX_RATE_SHIFT);
     907          29 :   max = MAX (max, (u32) internal_pir_bytes_per_period << MAX_RATE_SHIFT);
     908          29 :   scale_shift = __builtin_clz (max);
     909             : 
     910          29 :   scale_amount = 1 << scale_shift;
     911          29 :   *scale = scale_shift;
     912             : 
     913             :   /* Scale the limits */
     914          29 :   *current_limit = *current_limit << scale_shift;
     915          29 :   *extended_limit = *extended_limit << scale_shift;
     916             : 
     917             :   /* Scale the rates */
     918          29 :   internal_cir_bytes_per_period =
     919          29 :     internal_cir_bytes_per_period * ((double) scale_amount);
     920          29 :   internal_pir_bytes_per_period =
     921          29 :     internal_pir_bytes_per_period * ((double) scale_amount);
     922             : 
     923             :   /*
     924             :    * Make sure the new rates are reasonable
     925             :    * Only needed for very low rates with large bursts
     926             :    */
     927          29 :   if (internal_cir_bytes_per_period < 1.0)
     928             :     {
     929           0 :       internal_cir_bytes_per_period = 1.0;
     930             :     }
     931          29 :   if (internal_pir_bytes_per_period < 1.0)
     932             :     {
     933          23 :       internal_pir_bytes_per_period = 1.0;
     934             :     }
     935             : 
     936          29 :   *cir_bytes_per_period = (u32) internal_cir_bytes_per_period;
     937          29 :   *pir_bytes_per_period = (u32) internal_pir_bytes_per_period;
     938             : 
     939          29 :   return 0;
     940             : }
     941             : 
     942             : 
     943             : /*
     944             :  * Input: configured parameters in 'cfg'.
     945             :  * Output: h/w parameters are returned in 'hw',
     946             :  * Return: Status, success or failure code.
     947             :  */
     948             : int
     949          29 : x86_pol_compute_hw_params (qos_pol_cfg_params_st *cfg, policer_t *hw)
     950             : {
     951          29 :   const int BYTES_PER_KBIT = (1000 / 8);
     952             :   u64 hz;
     953             :   u32 cap;
     954             : 
     955          29 :   if (!cfg || !hw)
     956             :     {
     957           0 :       QOS_DEBUG_ERROR ("Illegal parameters");
     958           0 :       return (-1);
     959             :     }
     960             : 
     961          29 :   hz = get_tsc_hz ();
     962          29 :   hw->last_update_time = 0;
     963             : 
     964             :   /*
     965             :    * Cap the bursts to 32-bits. This allows up to almost one second of
     966             :    * burst on a 40GE interface, which should be fine for x86.
     967             :    */
     968          29 :   cap =
     969          29 :     (cfg->rb.kbps.cb_bytes > 0xFFFFFFFF) ? 0xFFFFFFFF : cfg->rb.kbps.cb_bytes;
     970          29 :   hw->current_limit = cap;
     971          29 :   cap =
     972          29 :     (cfg->rb.kbps.eb_bytes > 0xFFFFFFFF) ? 0xFFFFFFFF : cfg->rb.kbps.eb_bytes;
     973          29 :   hw->extended_limit = cap;
     974             : 
     975          29 :   if ((cfg->rb.kbps.cir_kbps == 0) && (cfg->rb.kbps.cb_bytes == 0)
     976           0 :       && (cfg->rb.kbps.eb_bytes == 0))
     977             :     {
     978             :       /* This is a uninitialized, always-violate policer */
     979           0 :       hw->single_rate = 1;
     980           0 :       hw->cir_tokens_per_period = 0;
     981           0 :       return 0;
     982             :     }
     983             : 
     984          29 :   if ((cfg->rfc == QOS_POLICER_TYPE_1R2C) ||
     985          10 :       (cfg->rfc == QOS_POLICER_TYPE_1R3C_RFC_2697))
     986             :     {
     987             :       /* Single-rate policer */
     988          23 :       hw->single_rate = 1;
     989             : 
     990          23 :       if ((cfg->rfc == QOS_POLICER_TYPE_1R2C) && cfg->rb.kbps.eb_bytes)
     991             :         {
     992           0 :           QOS_DEBUG_ERROR ("Policer parameter validation failed -- 1R2C.");
     993           0 :           return (-1);
     994             :         }
     995             : 
     996          23 :       if ((cfg->rb.kbps.cir_kbps == 0) ||
     997          23 :           (cfg->rb.kbps.eir_kbps != 0) ||
     998          23 :           ((cfg->rb.kbps.cb_bytes == 0) && (cfg->rb.kbps.eb_bytes == 0)))
     999             :         {
    1000           0 :           QOS_DEBUG_ERROR ("Policer parameter validation failed -- 1R.");
    1001           0 :           return (-1);
    1002             :         }
    1003             : 
    1004          23 :       if (compute_policer_params (hz,
    1005          23 :                                   (u64) cfg->rb.kbps.cir_kbps *
    1006             :                                   BYTES_PER_KBIT, 0, &hw->current_limit,
    1007             :                                   &hw->extended_limit,
    1008             :                                   &hw->cir_tokens_per_period,
    1009             :                                   &hw->pir_tokens_per_period, &hw->scale))
    1010             :         {
    1011           0 :           QOS_DEBUG_ERROR ("Policer parameter computation failed.");
    1012           0 :           return (-1);
    1013             :         }
    1014             : 
    1015             :     }
    1016           6 :   else if ((cfg->rfc == QOS_POLICER_TYPE_2R3C_RFC_2698) ||
    1017           6 :            (cfg->rfc == QOS_POLICER_TYPE_2R3C_RFC_4115))
    1018             :     {
    1019             :       /* Two-rate policer */
    1020           6 :       if ((cfg->rb.kbps.cir_kbps == 0) || (cfg->rb.kbps.eir_kbps == 0)
    1021           6 :           || (cfg->rb.kbps.eir_kbps < cfg->rb.kbps.cir_kbps)
    1022           6 :           || (cfg->rb.kbps.cb_bytes == 0) || (cfg->rb.kbps.eb_bytes == 0))
    1023             :         {
    1024           0 :           QOS_DEBUG_ERROR ("Config parameter validation failed.");
    1025           0 :           return (-1);
    1026             :         }
    1027             : 
    1028           6 :       if (compute_policer_params (hz,
    1029           6 :                                   (u64) cfg->rb.kbps.cir_kbps *
    1030             :                                   BYTES_PER_KBIT,
    1031           6 :                                   (u64) cfg->rb.kbps.eir_kbps *
    1032             :                                   BYTES_PER_KBIT, &hw->current_limit,
    1033             :                                   &hw->extended_limit,
    1034             :                                   &hw->cir_tokens_per_period,
    1035             :                                   &hw->pir_tokens_per_period, &hw->scale))
    1036             :         {
    1037           0 :           QOS_DEBUG_ERROR ("Policer parameter computation failed.");
    1038           0 :           return (-1);
    1039             :         }
    1040             : 
    1041             :     }
    1042             :   else
    1043             :     {
    1044           0 :       QOS_DEBUG_ERROR (
    1045             :         "Config parameter validation failed. RFC not supported");
    1046           0 :       return (-1);
    1047             :     }
    1048             : 
    1049          29 :   hw->current_bucket = hw->current_limit;
    1050          29 :   hw->extended_bucket = hw->extended_limit;
    1051             : 
    1052          29 :   return 0;
    1053             : }
    1054             : 
    1055             : /*
    1056             :  * Input: configured parameters in 'cfg'.
    1057             :  * Output: physical structure is returned in 'phys',
    1058             :  * Return: Status, success or failure code.
    1059             :  */
    1060             : int
    1061          29 : pol_logical_2_physical (const qos_pol_cfg_params_st *cfg, policer_t *phys)
    1062             : {
    1063             :   int rc;
    1064             :   qos_pol_cfg_params_st kbps_cfg;
    1065             : 
    1066          29 :   clib_memset (phys, 0, sizeof (policer_t));
    1067          29 :   clib_memset (&kbps_cfg, 0, sizeof (qos_pol_cfg_params_st));
    1068             : 
    1069          29 :   if (!cfg)
    1070             :     {
    1071           0 :       QOS_DEBUG_ERROR ("Illegal parameters");
    1072           0 :       return (-1);
    1073             :     }
    1074             : 
    1075          29 :   switch (cfg->rate_type)
    1076             :     {
    1077          24 :     case QOS_RATE_KBPS:
    1078             :       /* copy all the data into kbps_cfg */
    1079          24 :       kbps_cfg.rb.kbps.cir_kbps = cfg->rb.kbps.cir_kbps;
    1080          24 :       kbps_cfg.rb.kbps.eir_kbps = cfg->rb.kbps.eir_kbps;
    1081          24 :       kbps_cfg.rb.kbps.cb_bytes = cfg->rb.kbps.cb_bytes;
    1082          24 :       kbps_cfg.rb.kbps.eb_bytes = cfg->rb.kbps.eb_bytes;
    1083          24 :       break;
    1084           5 :     case QOS_RATE_PPS:
    1085           5 :       kbps_cfg.rb.kbps.cir_kbps =
    1086           5 :         qos_convert_pps_to_kbps (cfg->rb.pps.cir_pps);
    1087           5 :       kbps_cfg.rb.kbps.eir_kbps =
    1088           5 :         qos_convert_pps_to_kbps (cfg->rb.pps.eir_pps);
    1089          10 :       kbps_cfg.rb.kbps.cb_bytes = qos_convert_burst_ms_to_bytes (
    1090           5 :         (u32) cfg->rb.pps.cb_ms, kbps_cfg.rb.kbps.cir_kbps);
    1091          10 :       kbps_cfg.rb.kbps.eb_bytes = qos_convert_burst_ms_to_bytes (
    1092           5 :         (u32) cfg->rb.pps.eb_ms, kbps_cfg.rb.kbps.eir_kbps);
    1093           5 :       break;
    1094           0 :     default:
    1095           0 :       QOS_DEBUG_ERROR ("Illegal rate type");
    1096           0 :       return (-1);
    1097             :     }
    1098             : 
    1099             :   /* rate type is now converted to kbps */
    1100          29 :   kbps_cfg.rate_type = QOS_RATE_KBPS;
    1101          29 :   kbps_cfg.rnd_type = cfg->rnd_type;
    1102          29 :   kbps_cfg.rfc = cfg->rfc;
    1103             : 
    1104          29 :   phys->action[POLICE_CONFORM] = cfg->conform_action.action_type;
    1105          29 :   phys->mark_dscp[POLICE_CONFORM] = cfg->conform_action.dscp;
    1106          29 :   phys->action[POLICE_EXCEED] = cfg->exceed_action.action_type;
    1107          29 :   phys->mark_dscp[POLICE_EXCEED] = cfg->exceed_action.dscp;
    1108          29 :   phys->action[POLICE_VIOLATE] = cfg->violate_action.action_type;
    1109          29 :   phys->mark_dscp[POLICE_VIOLATE] = cfg->violate_action.dscp;
    1110             : 
    1111          29 :   phys->color_aware = cfg->color_aware;
    1112             : 
    1113             :   /* convert logical into hw params which involves qos calculations */
    1114          29 :   rc = x86_pol_compute_hw_params (&kbps_cfg, phys);
    1115          29 :   if (rc == -1)
    1116             :     {
    1117           0 :       QOS_DEBUG_ERROR ("Unable to compute hw param. Error: %d", rc);
    1118           0 :       return (rc);
    1119             :     }
    1120             : 
    1121             :   /* for debugging purposes, the bucket token values can be overwritten */
    1122          29 :   if (cfg->overwrite_bucket)
    1123             :     {
    1124           0 :       phys->current_bucket = cfg->current_bucket;
    1125           0 :       phys->extended_bucket = cfg->extended_bucket;
    1126             :     }
    1127             : 
    1128          29 :   return 0;
    1129             : }
    1130             : 
    1131             : static void
    1132           0 : qos_convert_pol_bucket_to_hw_fmt (policer_t *bkt, qos_pol_hw_params_st *hw_fmt)
    1133             : {
    1134           0 :   clib_memset (hw_fmt, 0, sizeof (qos_pol_hw_params_st));
    1135           0 : }
    1136             : 
    1137             : /*
    1138             :  * Input: h/w programmable parameter values in 'hw'
    1139             :  * Output: configured parameter values in 'cfg'
    1140             :  * Return: Status, success or failure code.
    1141             :  */
    1142             : static int
    1143           0 : pol_convert_hw_to_cfg_params (qos_pol_hw_params_st *hw,
    1144             :                               qos_pol_cfg_params_st *cfg)
    1145             : {
    1146             :   u64 temp_rate;
    1147             : 
    1148           0 :   if ((hw == NULL) || (cfg == NULL))
    1149             :     {
    1150           0 :       return EINVAL;
    1151             :     }
    1152             : 
    1153           0 :   if ((hw->rfc == IPE_RFC_RFC4115) &&
    1154           0 :       (hw->peak_rate_man << hw->rate_exp) == 0 && !(hw->extd_bkt_limit_man))
    1155             :     {
    1156             :       /*
    1157             :        * For a 1R2C, we set EIR = 0, EB = 0
    1158             :        */
    1159           0 :       cfg->rfc = QOS_POLICER_TYPE_1R2C;
    1160             :     }
    1161           0 :   else if (hw->rfc == IPE_RFC_RFC2697)
    1162             :     {
    1163           0 :       cfg->rfc = QOS_POLICER_TYPE_1R3C_RFC_2697;
    1164             :     }
    1165           0 :   else if (hw->rfc == IPE_RFC_RFC2698)
    1166             :     {
    1167           0 :       cfg->rfc = QOS_POLICER_TYPE_2R3C_RFC_2698;
    1168             :     }
    1169           0 :   else if (hw->rfc == IPE_RFC_RFC4115)
    1170             :     {
    1171           0 :       cfg->rfc = QOS_POLICER_TYPE_2R3C_RFC_4115;
    1172             :     }
    1173           0 :   else if (hw->rfc == IPE_RFC_MEF5CF1)
    1174             :     {
    1175           0 :       cfg->rfc = QOS_POLICER_TYPE_2R3C_RFC_MEF5CF1;
    1176             :     }
    1177             :   else
    1178             :     {
    1179           0 :       return EINVAL;
    1180             :     }
    1181             : 
    1182           0 :   temp_rate =
    1183           0 :     (((u64) hw->avg_rate_man << hw->rate_exp) * 8LL * QOS_POL_TICKS_PER_SEC) /
    1184             :     1000;
    1185           0 :   cfg->rb.kbps.cir_kbps = (u32) temp_rate;
    1186             : 
    1187           0 :   temp_rate =
    1188           0 :     (((u64) hw->peak_rate_man << hw->rate_exp) * 8LL * QOS_POL_TICKS_PER_SEC) /
    1189             :     1000;
    1190           0 :   cfg->rb.kbps.eir_kbps = (u32) temp_rate;
    1191             : 
    1192           0 :   cfg->rb.kbps.cb_bytes = ((u64) hw->comm_bkt_limit_man <<
    1193           0 :                            (u64) hw->comm_bkt_limit_exp);
    1194           0 :   cfg->rb.kbps.eb_bytes = ((u64) hw->extd_bkt_limit_man <<
    1195           0 :                            (u64) hw->extd_bkt_limit_exp);
    1196             : 
    1197           0 :   if (cfg->rfc == QOS_POLICER_TYPE_1R3C_RFC_2697)
    1198             :     {
    1199             :       /*
    1200             :        * For 1R3C in the hardware, EB = sum(CB, EB). Also, EIR = CIR. Restore
    1201             :        * values such that the configured params don't reflect this adjustment
    1202             :        */
    1203           0 :       cfg->rb.kbps.eb_bytes = (cfg->rb.kbps.eb_bytes - cfg->rb.kbps.cb_bytes);
    1204           0 :       cfg->rb.kbps.eir_kbps = 0;
    1205             :     }
    1206           0 :   else if (cfg->rfc == QOS_POLICER_TYPE_2R3C_RFC_4115)
    1207             :     {
    1208             :       /*
    1209             :        * For 4115 in the hardware is excess rate and burst, but EA provides
    1210             :        * peak-rate, so adjust it to be eir
    1211             :        */
    1212           0 :       cfg->rb.kbps.eir_kbps += cfg->rb.kbps.cir_kbps;
    1213           0 :       cfg->rb.kbps.eb_bytes += cfg->rb.kbps.cb_bytes;
    1214             :     }
    1215             :   /* h/w conversion to cfg is in kbps */
    1216           0 :   cfg->rate_type = QOS_RATE_KBPS;
    1217           0 :   cfg->overwrite_bucket = 0;
    1218           0 :   cfg->current_bucket = hw->comm_bkt;
    1219           0 :   cfg->extended_bucket = hw->extd_bkt;
    1220             : 
    1221           0 :   QOS_DEBUG_INFO ("configured params, cir: %u kbps, eir: %u kbps, cb "
    1222             :                   "burst: 0x%llx bytes, eb burst: 0x%llx bytes",
    1223             :                   cfg->rb.kbps.cir_kbps, cfg->rb.kbps.eir_kbps,
    1224             :                   cfg->rb.kbps.cb_bytes, cfg->rb.kbps.eb_bytes);
    1225             : 
    1226           0 :   return 0;
    1227             : }
    1228             : 
    1229             : u32
    1230           0 : qos_convert_kbps_to_pps (u32 rate_kbps)
    1231             : {
    1232           0 :   u64 numer, denom, rnd_value = 0;
    1233             : 
    1234           0 :   numer = (u64) ((u64) rate_kbps * 1000LL);
    1235           0 :   denom = (u64) ((u64) QOS_POLICER_FIXED_PKT_SIZE * 8LL);
    1236             : 
    1237           0 :   (void) qos_pol_round (numer, denom, &rnd_value, QOS_ROUND_TO_CLOSEST);
    1238             : 
    1239           0 :   return ((u32) rnd_value);
    1240             : }
    1241             : 
    1242             : u32
    1243           0 : qos_convert_burst_bytes_to_ms (u64 burst_bytes, u32 rate_kbps)
    1244             : {
    1245           0 :   u64 numer, denom, rnd_value = 0;
    1246             : 
    1247           0 :   numer = burst_bytes * 8LL;
    1248           0 :   denom = (u64) rate_kbps;
    1249             : 
    1250           0 :   (void) qos_pol_round (numer, denom, &rnd_value, QOS_ROUND_TO_CLOSEST);
    1251             : 
    1252           0 :   return ((u32) rnd_value);
    1253             : }
    1254             : 
    1255             : /*
    1256             :  * Input: physical structure in 'phys', rate_type in cfg
    1257             :  * Output: configured parameters in 'cfg'.
    1258             :  * Return: Status, success or failure code.
    1259             :  */
    1260             : int
    1261           0 : pol_physical_2_logical (policer_t *phys, qos_pol_cfg_params_st *cfg)
    1262             : {
    1263             :   int rc;
    1264             :   qos_pol_hw_params_st pol_hw;
    1265             :   qos_pol_cfg_params_st kbps_cfg;
    1266             : 
    1267           0 :   clib_memset (&pol_hw, 0, sizeof (qos_pol_hw_params_st));
    1268           0 :   clib_memset (&kbps_cfg, 0, sizeof (qos_pol_cfg_params_st));
    1269             : 
    1270           0 :   if (!phys)
    1271             :     {
    1272           0 :       QOS_DEBUG_ERROR ("Illegal parameters");
    1273           0 :       return (-1);
    1274             :     }
    1275             : 
    1276           0 :   qos_convert_pol_bucket_to_hw_fmt (phys, &pol_hw);
    1277             : 
    1278           0 :   rc = pol_convert_hw_to_cfg_params (&pol_hw, &kbps_cfg);
    1279           0 :   if (rc != 0)
    1280             :     {
    1281           0 :       QOS_DEBUG_ERROR ("Unable to convert hw params to config params. "
    1282             :                        "Error: %d",
    1283             :                        rc);
    1284           0 :       return (-1);
    1285             :     }
    1286             : 
    1287             :   /* check what rate type is required */
    1288           0 :   switch (cfg->rate_type)
    1289             :     {
    1290           0 :     case QOS_RATE_KBPS:
    1291             :       /* copy all the data into kbps_cfg */
    1292           0 :       cfg->rb.kbps.cir_kbps = kbps_cfg.rb.kbps.cir_kbps;
    1293           0 :       cfg->rb.kbps.eir_kbps = kbps_cfg.rb.kbps.eir_kbps;
    1294           0 :       cfg->rb.kbps.cb_bytes = kbps_cfg.rb.kbps.cb_bytes;
    1295           0 :       cfg->rb.kbps.eb_bytes = kbps_cfg.rb.kbps.eb_bytes;
    1296           0 :       break;
    1297           0 :     case QOS_RATE_PPS:
    1298           0 :       cfg->rb.pps.cir_pps =
    1299           0 :         qos_convert_kbps_to_pps (kbps_cfg.rb.kbps.cir_kbps);
    1300           0 :       cfg->rb.pps.eir_pps =
    1301           0 :         qos_convert_kbps_to_pps (kbps_cfg.rb.kbps.eir_kbps);
    1302           0 :       cfg->rb.pps.cb_ms = qos_convert_burst_bytes_to_ms (
    1303             :         kbps_cfg.rb.kbps.cb_bytes, kbps_cfg.rb.kbps.cir_kbps);
    1304           0 :       cfg->rb.pps.eb_ms = qos_convert_burst_bytes_to_ms (
    1305             :         kbps_cfg.rb.kbps.eb_bytes, kbps_cfg.rb.kbps.eir_kbps);
    1306           0 :       break;
    1307           0 :     default:
    1308           0 :       QOS_DEBUG_ERROR ("Illegal rate type");
    1309           0 :       return (-1);
    1310             :     }
    1311             : 
    1312             :   /* cfg->rate_type remains what it was */
    1313           0 :   cfg->rnd_type = kbps_cfg.rnd_type;
    1314           0 :   cfg->rfc = kbps_cfg.rfc;
    1315           0 :   cfg->overwrite_bucket = kbps_cfg.overwrite_bucket;
    1316           0 :   cfg->current_bucket = kbps_cfg.current_bucket;
    1317           0 :   cfg->extended_bucket = kbps_cfg.extended_bucket;
    1318             : 
    1319           0 :   return 0;
    1320             : }
    1321             : 
    1322             : /*
    1323             :  * fd.io coding-style-patch-verification: ON
    1324             :  *
    1325             :  * Local Variables:
    1326             :  * eval: (c-set-style "gnu")
    1327             :  * End:
    1328             :  */

Generated by: LCOV version 1.14