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