Branch data Line data Source code
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 : : 14 : : static int rte_red_init_done = 0; /**< Flag to indicate that global initialisation is done */ 15 : : uint32_t rte_red_rand_val = 0; /**< Random value cache */ 16 : : uint32_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 : : */ 22 : : uint16_t rte_red_log2_1_minus_Wq[RTE_RED_WQ_LOG2_NUM]; 23 : : 24 : : /** 25 : : * table[i] = 2^(i/16) * Scale 26 : : */ 27 : : uint16_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 : : */ 33 : : static void 34 : 0 : __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 [ # # ]: 0 : for (i = 0; i < RTE_DIM(rte_red_pow2_frac_inv); i++) { 44 : 0 : double m = (double)i; 45 : : 46 : 0 : 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 [ # # ]: 0 : for (i = RTE_RED_WQ_LOG2_MIN; i <= RTE_RED_WQ_LOG2_MAX; i++) { 54 : 0 : double n = (double)i; 55 : 0 : double Wq = pow(2, -n); 56 : 0 : uint32_t index = i - RTE_RED_WQ_LOG2_MIN; 57 : : 58 : 0 : 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 [ # # ]: 0 : if (rte_red_log2_1_minus_Wq[index] == 0) { 66 : 0 : rte_red_log2_1_minus_Wq[index] = 1; 67 : : } 68 : : } 69 : 0 : } 70 : : 71 : : int 72 : 0 : rte_red_rt_data_init(struct rte_red *red) 73 : : { 74 [ # # ]: 0 : if (red == NULL) 75 : : return -1; 76 : : 77 : 0 : red->avg = 0; 78 : 0 : red->count = 0; 79 : 0 : red->q_time = 0; 80 : 0 : return 0; 81 : : } 82 : : 83 : : int 84 : 0 : rte_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 [ # # ]: 0 : if (red_cfg == NULL) { 91 : : return -1; 92 : : } 93 [ # # ]: 0 : if (max_th > RTE_RED_MAX_TH_MAX) { 94 : : return -2; 95 : : } 96 [ # # ]: 0 : if (min_th >= max_th) { 97 : : return -3; 98 : : } 99 [ # # ]: 0 : if (wq_log2 > RTE_RED_WQ_LOG2_MAX) { 100 : : return -4; 101 : : } 102 [ # # ]: 0 : if (wq_log2 < RTE_RED_WQ_LOG2_MIN) { 103 : : return -5; 104 : : } 105 [ # # ]: 0 : if (maxp_inv < RTE_RED_MAXP_INV_MIN) { 106 : : return -6; 107 : : } 108 [ # # ]: 0 : 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 [ # # ]: 0 : if (!rte_red_init_done) { 116 : 0 : rte_red_rand_seed = rte_rand(); 117 : 0 : rte_red_rand_val = rte_fast_rand(); 118 : 0 : __rte_red_init_tables(); 119 : 0 : rte_red_init_done = 1; 120 : : } 121 : : 122 : 0 : red_cfg->min_th = ((uint32_t) min_th) << (wq_log2 + RTE_RED_SCALING); 123 : 0 : red_cfg->max_th = ((uint32_t) max_th) << (wq_log2 + RTE_RED_SCALING); 124 : 0 : red_cfg->pa_const = (2 * (max_th - min_th) * maxp_inv) << RTE_RED_SCALING; 125 : 0 : red_cfg->maxp_inv = maxp_inv; 126 : 0 : red_cfg->wq_log2 = wq_log2; 127 : : 128 : 0 : return 0; 129 : : }