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