dpdk/lib/sched/rte_red.c
<<
>>
Prefs
   1/* SPDX-License-Identifier: BSD-3-Clause
   2 * Copyright(c) 2010-2014 Intel Corporation
   3 */
   4
   5#include <math.h>
   6#include "rte_red.h"
   7#include <rte_random.h>
   8#include <rte_common.h>
   9
  10#ifdef __INTEL_COMPILER
  11#pragma warning(disable:2259) /* conversion may lose significant bits */
  12#endif
  13
  14static int rte_red_init_done = 0;     /**< Flag to indicate that global initialisation is done */
  15uint32_t rte_red_rand_val = 0;        /**< Random value cache */
  16uint32_t rte_red_rand_seed = 0;       /**< Seed for random number generation */
  17
  18/**
  19 * table[i] = log2(1-Wq) * Scale * -1
  20 *       Wq = 1/(2^i)
  21 */
  22uint16_t rte_red_log2_1_minus_Wq[RTE_RED_WQ_LOG2_NUM];
  23
  24/**
  25 * table[i] = 2^(i/16) * Scale
  26 */
  27uint16_t rte_red_pow2_frac_inv[16];
  28
  29/**
  30 * @brief Initialize tables used to compute average
  31 *        queue size when queue is empty.
  32 */
  33static void
  34__rte_red_init_tables(void)
  35{
  36        uint32_t i = 0;
  37        double scale = 0.0;
  38        double table_size = 0.0;
  39
  40        scale = (double)(1 << RTE_RED_SCALING);
  41        table_size = (double)(RTE_DIM(rte_red_pow2_frac_inv));
  42
  43        for (i = 0; i < RTE_DIM(rte_red_pow2_frac_inv); i++) {
  44                double m = (double)i;
  45
  46                rte_red_pow2_frac_inv[i] = (uint16_t) round(scale / pow(2, m / table_size));
  47        }
  48
  49        scale = 1024.0;
  50
  51        RTE_ASSERT(RTE_RED_WQ_LOG2_NUM == RTE_DIM(rte_red_log2_1_minus_Wq));
  52
  53        for (i = RTE_RED_WQ_LOG2_MIN; i <= RTE_RED_WQ_LOG2_MAX; i++) {
  54                double n = (double)i;
  55                double Wq = pow(2, -n);
  56                uint32_t index = i - RTE_RED_WQ_LOG2_MIN;
  57
  58                rte_red_log2_1_minus_Wq[index] = (uint16_t) round(-1.0 * scale * log2(1.0 - Wq));
  59                /**
  60                * Table entry of zero, corresponds to a Wq of zero
  61                * which is not valid (avg would remain constant no
  62                * matter how long the queue is empty). So we have
  63                * to check for zero and round up to one.
  64                */
  65                if (rte_red_log2_1_minus_Wq[index] == 0) {
  66                        rte_red_log2_1_minus_Wq[index] = 1;
  67                }
  68        }
  69}
  70
  71int
  72rte_red_rt_data_init(struct rte_red *red)
  73{
  74        if (red == NULL)
  75                return -1;
  76
  77        red->avg = 0;
  78        red->count = 0;
  79        red->q_time = 0;
  80        return 0;
  81}
  82
  83int
  84rte_red_config_init(struct rte_red_config *red_cfg,
  85        const uint16_t wq_log2,
  86        const uint16_t min_th,
  87        const uint16_t max_th,
  88        const uint16_t maxp_inv)
  89{
  90        if (red_cfg == NULL) {
  91                return -1;
  92        }
  93        if (max_th > RTE_RED_MAX_TH_MAX) {
  94                return -2;
  95        }
  96        if (min_th >= max_th) {
  97                return -3;
  98        }
  99        if (wq_log2 > RTE_RED_WQ_LOG2_MAX) {
 100                return -4;
 101        }
 102        if (wq_log2 < RTE_RED_WQ_LOG2_MIN) {
 103                return -5;
 104        }
 105        if (maxp_inv < RTE_RED_MAXP_INV_MIN) {
 106                return -6;
 107        }
 108        if (maxp_inv > RTE_RED_MAXP_INV_MAX) {
 109                return -7;
 110        }
 111
 112        /**
 113         *  Initialize the RED module if not already done
 114         */
 115        if (!rte_red_init_done) {
 116                rte_red_rand_seed = rte_rand();
 117                rte_red_rand_val = rte_fast_rand();
 118                __rte_red_init_tables();
 119                rte_red_init_done = 1;
 120        }
 121
 122        red_cfg->min_th = ((uint32_t) min_th) << (wq_log2 + RTE_RED_SCALING);
 123        red_cfg->max_th = ((uint32_t) max_th) << (wq_log2 + RTE_RED_SCALING);
 124        red_cfg->pa_const = (2 * (max_th - min_th) * maxp_inv) << RTE_RED_SCALING;
 125        red_cfg->maxp_inv = maxp_inv;
 126        red_cfg->wq_log2 = wq_log2;
 127
 128        return 0;
 129}
 130