144c730b0SWojciech Liguzinski /* SPDX-License-Identifier: BSD-3-Clause 244c730b0SWojciech Liguzinski * Copyright(c) 2020 Intel Corporation 344c730b0SWojciech Liguzinski */ 444c730b0SWojciech Liguzinski 544c730b0SWojciech Liguzinski #ifndef __RTE_PIE_H_INCLUDED__ 644c730b0SWojciech Liguzinski #define __RTE_PIE_H_INCLUDED__ 744c730b0SWojciech Liguzinski 844c730b0SWojciech Liguzinski /** 944c730b0SWojciech Liguzinski * @file 1044c730b0SWojciech Liguzinski * Proportional Integral controller Enhanced (PIE) 113e4c5be9SThomas Monjalon */ 1244c730b0SWojciech Liguzinski 1344c730b0SWojciech Liguzinski #include <stdint.h> 1444c730b0SWojciech Liguzinski 1544c730b0SWojciech Liguzinski #include <rte_random.h> 1644c730b0SWojciech Liguzinski #include <rte_debug.h> 1744c730b0SWojciech Liguzinski #include <rte_cycles.h> 1844c730b0SWojciech Liguzinski 19*719834a6SMattias Rönnblom #ifdef __cplusplus 20*719834a6SMattias Rönnblom extern "C" { 21*719834a6SMattias Rönnblom #endif 22*719834a6SMattias Rönnblom 2344c730b0SWojciech Liguzinski #define RTE_DQ_THRESHOLD 16384 /**< Queue length threshold (2^14) 2444c730b0SWojciech Liguzinski * to start measurement cycle (bytes) 2544c730b0SWojciech Liguzinski */ 2644c730b0SWojciech Liguzinski #define RTE_DQ_WEIGHT 0.25 /**< Weight (RTE_DQ_THRESHOLD/2^16) to compute dequeue rate */ 2744c730b0SWojciech Liguzinski #define RTE_ALPHA 0.125 /**< Weights in drop probability calculations */ 2844c730b0SWojciech Liguzinski #define RTE_BETA 1.25 /**< Weights in drop probability calculations */ 2944c730b0SWojciech Liguzinski #define RTE_RAND_MAX ~0LLU /**< Max value of the random number */ 3044c730b0SWojciech Liguzinski 3144c730b0SWojciech Liguzinski 3244c730b0SWojciech Liguzinski /** 3344c730b0SWojciech Liguzinski * PIE configuration parameters passed by user 3444c730b0SWojciech Liguzinski */ 3544c730b0SWojciech Liguzinski struct rte_pie_params { 3644c730b0SWojciech Liguzinski uint16_t qdelay_ref; /**< Latency Target (milliseconds) */ 3744c730b0SWojciech Liguzinski uint16_t dp_update_interval; /**< Update interval for drop probability (milliseconds) */ 3844c730b0SWojciech Liguzinski uint16_t max_burst; /**< Max Burst Allowance (milliseconds) */ 3944c730b0SWojciech Liguzinski uint16_t tailq_th; /**< Tailq drop threshold (packet counts) */ 4044c730b0SWojciech Liguzinski }; 4144c730b0SWojciech Liguzinski 4244c730b0SWojciech Liguzinski /** 4344c730b0SWojciech Liguzinski * PIE configuration parameters 4444c730b0SWojciech Liguzinski */ 4544c730b0SWojciech Liguzinski struct rte_pie_config { 4644c730b0SWojciech Liguzinski uint64_t qdelay_ref; /**< Latency Target (in CPU cycles.) */ 4744c730b0SWojciech Liguzinski uint64_t dp_update_interval; /**< Update interval for drop probability (in CPU cycles) */ 4844c730b0SWojciech Liguzinski uint64_t max_burst; /**< Max Burst Allowance (in CPU cycles.) */ 4944c730b0SWojciech Liguzinski uint16_t tailq_th; /**< Tailq drop threshold (packet counts) */ 5044c730b0SWojciech Liguzinski }; 5144c730b0SWojciech Liguzinski 5244c730b0SWojciech Liguzinski /** 5344c730b0SWojciech Liguzinski * PIE run-time data 5444c730b0SWojciech Liguzinski */ 5544c730b0SWojciech Liguzinski struct rte_pie { 5644c730b0SWojciech Liguzinski uint16_t active; /**< Flag for activating/deactivating pie */ 5744c730b0SWojciech Liguzinski uint16_t in_measurement; /**< Flag for activation of measurement cycle */ 5844c730b0SWojciech Liguzinski uint32_t departed_bytes_count; /**< Number of bytes departed in current measurement cycle */ 5944c730b0SWojciech Liguzinski uint64_t start_measurement; /**< Time to start to measurement cycle (in cpu cycles) */ 6044c730b0SWojciech Liguzinski uint64_t last_measurement; /**< Time of last measurement (in cpu cycles) */ 6144c730b0SWojciech Liguzinski uint64_t qlen; /**< Queue length (packets count) */ 6244c730b0SWojciech Liguzinski uint64_t qlen_bytes; /**< Queue length (bytes count) */ 6344c730b0SWojciech Liguzinski uint64_t avg_dq_time; /**< Time averaged dequeue rate (in cpu cycles) */ 6444c730b0SWojciech Liguzinski uint32_t burst_allowance; /**< Current burst allowance (bytes) */ 6544c730b0SWojciech Liguzinski uint64_t qdelay_old; /**< Old queue delay (bytes) */ 6644c730b0SWojciech Liguzinski double drop_prob; /**< Current packet drop probability */ 6744c730b0SWojciech Liguzinski double accu_prob; /**< Accumulated packet drop probability */ 6844c730b0SWojciech Liguzinski }; 6944c730b0SWojciech Liguzinski 7044c730b0SWojciech Liguzinski /** 7144c730b0SWojciech Liguzinski * @brief Initialises run-time data 7244c730b0SWojciech Liguzinski * 7344c730b0SWojciech Liguzinski * @param pie [in,out] data pointer to PIE runtime data 7444c730b0SWojciech Liguzinski * 7544c730b0SWojciech Liguzinski * @return Operation status 7644c730b0SWojciech Liguzinski * @retval 0 success 7744c730b0SWojciech Liguzinski * @retval !0 error 7844c730b0SWojciech Liguzinski */ 7944c730b0SWojciech Liguzinski int 8044c730b0SWojciech Liguzinski rte_pie_rt_data_init(struct rte_pie *pie); 8144c730b0SWojciech Liguzinski 8244c730b0SWojciech Liguzinski /** 8344c730b0SWojciech Liguzinski * @brief Configures a single PIE configuration parameter structure. 8444c730b0SWojciech Liguzinski * 8544c730b0SWojciech Liguzinski * @param pie_cfg [in,out] config pointer to a PIE configuration parameter structure 8644c730b0SWojciech Liguzinski * @param qdelay_ref [in] latency target(milliseconds) 8744c730b0SWojciech Liguzinski * @param dp_update_interval [in] update interval for drop probability (milliseconds) 8844c730b0SWojciech Liguzinski * @param max_burst [in] maximum burst allowance (milliseconds) 8944c730b0SWojciech Liguzinski * @param tailq_th [in] tail drop threshold for the queue (number of packets) 9044c730b0SWojciech Liguzinski * 9144c730b0SWojciech Liguzinski * @return Operation status 9244c730b0SWojciech Liguzinski * @retval 0 success 9344c730b0SWojciech Liguzinski * @retval !0 error 9444c730b0SWojciech Liguzinski */ 9544c730b0SWojciech Liguzinski int 9644c730b0SWojciech Liguzinski rte_pie_config_init(struct rte_pie_config *pie_cfg, 9744c730b0SWojciech Liguzinski const uint16_t qdelay_ref, 9844c730b0SWojciech Liguzinski const uint16_t dp_update_interval, 9944c730b0SWojciech Liguzinski const uint16_t max_burst, 10044c730b0SWojciech Liguzinski const uint16_t tailq_th); 10144c730b0SWojciech Liguzinski 10244c730b0SWojciech Liguzinski /** 10344c730b0SWojciech Liguzinski * @brief Decides packet enqueue when queue is empty 10444c730b0SWojciech Liguzinski * 10544c730b0SWojciech Liguzinski * Note: packet is never dropped in this particular case. 10644c730b0SWojciech Liguzinski * 10744c730b0SWojciech Liguzinski * @param pie_cfg [in] config pointer to a PIE configuration parameter structure 10844c730b0SWojciech Liguzinski * @param pie [in, out] data pointer to PIE runtime data 10944c730b0SWojciech Liguzinski * @param pkt_len [in] packet length in bytes 11044c730b0SWojciech Liguzinski * 11144c730b0SWojciech Liguzinski * @return Operation status 11244c730b0SWojciech Liguzinski * @retval 0 enqueue the packet 11344c730b0SWojciech Liguzinski * @retval !0 drop the packet 11444c730b0SWojciech Liguzinski */ 11544c730b0SWojciech Liguzinski static int 11644c730b0SWojciech Liguzinski rte_pie_enqueue_empty(const struct rte_pie_config *pie_cfg, 11744c730b0SWojciech Liguzinski struct rte_pie *pie, 11844c730b0SWojciech Liguzinski uint32_t pkt_len) 11944c730b0SWojciech Liguzinski { 120948be25cSAli Alnubani RTE_ASSERT(pkt_len != 0); 12144c730b0SWojciech Liguzinski 12244c730b0SWojciech Liguzinski /* Update the PIE qlen parameter */ 12344c730b0SWojciech Liguzinski pie->qlen++; 12444c730b0SWojciech Liguzinski pie->qlen_bytes += pkt_len; 12544c730b0SWojciech Liguzinski 12644c730b0SWojciech Liguzinski /** 12744c730b0SWojciech Liguzinski * If the queue has been idle for a while, turn off PIE and Reset counters 12844c730b0SWojciech Liguzinski */ 12944c730b0SWojciech Liguzinski if ((pie->active == 1) && 13044c730b0SWojciech Liguzinski (pie->qlen < (pie_cfg->tailq_th * 0.1))) { 13144c730b0SWojciech Liguzinski pie->active = 0; 13244c730b0SWojciech Liguzinski pie->in_measurement = 0; 13344c730b0SWojciech Liguzinski } 13444c730b0SWojciech Liguzinski 13544c730b0SWojciech Liguzinski return 0; 13644c730b0SWojciech Liguzinski } 13744c730b0SWojciech Liguzinski 13844c730b0SWojciech Liguzinski /** 13944c730b0SWojciech Liguzinski * @brief make a decision to drop or enqueue a packet based on probability 14044c730b0SWojciech Liguzinski * criteria 14144c730b0SWojciech Liguzinski * 14244c730b0SWojciech Liguzinski * @param pie_cfg [in] config pointer to a PIE configuration parameter structure 14344c730b0SWojciech Liguzinski * @param pie [in, out] data pointer to PIE runtime data 14444c730b0SWojciech Liguzinski * @param time [in] current time (measured in cpu cycles) 14544c730b0SWojciech Liguzinski */ 14644c730b0SWojciech Liguzinski static void 14744c730b0SWojciech Liguzinski _calc_drop_probability(const struct rte_pie_config *pie_cfg, 14844c730b0SWojciech Liguzinski struct rte_pie *pie, uint64_t time) 14944c730b0SWojciech Liguzinski { 15044c730b0SWojciech Liguzinski uint64_t qdelay_ref = pie_cfg->qdelay_ref; 15144c730b0SWojciech Liguzinski 15244c730b0SWojciech Liguzinski /* Note: can be implemented using integer multiply. 15344c730b0SWojciech Liguzinski * DQ_THRESHOLD is power of 2 value. 15444c730b0SWojciech Liguzinski */ 15544c730b0SWojciech Liguzinski uint64_t current_qdelay = pie->qlen * (pie->avg_dq_time >> 14); 15644c730b0SWojciech Liguzinski 15744c730b0SWojciech Liguzinski double p = RTE_ALPHA * (current_qdelay - qdelay_ref) + 15844c730b0SWojciech Liguzinski RTE_BETA * (current_qdelay - pie->qdelay_old); 15944c730b0SWojciech Liguzinski 16044c730b0SWojciech Liguzinski if (pie->drop_prob < 0.000001) 16144c730b0SWojciech Liguzinski p = p * 0.00048828125; /* (1/2048) = 0.00048828125 */ 16244c730b0SWojciech Liguzinski else if (pie->drop_prob < 0.00001) 16344c730b0SWojciech Liguzinski p = p * 0.001953125; /* (1/512) = 0.001953125 */ 16444c730b0SWojciech Liguzinski else if (pie->drop_prob < 0.0001) 16544c730b0SWojciech Liguzinski p = p * 0.0078125; /* (1/128) = 0.0078125 */ 16644c730b0SWojciech Liguzinski else if (pie->drop_prob < 0.001) 16744c730b0SWojciech Liguzinski p = p * 0.03125; /* (1/32) = 0.03125 */ 16844c730b0SWojciech Liguzinski else if (pie->drop_prob < 0.01) 16944c730b0SWojciech Liguzinski p = p * 0.125; /* (1/8) = 0.125 */ 17044c730b0SWojciech Liguzinski else if (pie->drop_prob < 0.1) 17144c730b0SWojciech Liguzinski p = p * 0.5; /* (1/2) = 0.5 */ 17244c730b0SWojciech Liguzinski 17344c730b0SWojciech Liguzinski if (pie->drop_prob >= 0.1 && p > 0.02) 17444c730b0SWojciech Liguzinski p = 0.02; 17544c730b0SWojciech Liguzinski 17644c730b0SWojciech Liguzinski pie->drop_prob += p; 17744c730b0SWojciech Liguzinski 17844c730b0SWojciech Liguzinski double qdelay = qdelay_ref * 0.5; 17944c730b0SWojciech Liguzinski 18044c730b0SWojciech Liguzinski /* Exponentially decay drop prob when congestion goes away */ 18144c730b0SWojciech Liguzinski if ((double)current_qdelay < qdelay && pie->qdelay_old < qdelay) 18244c730b0SWojciech Liguzinski pie->drop_prob *= 0.98; /* 1 - 1/64 is sufficient */ 18344c730b0SWojciech Liguzinski 18444c730b0SWojciech Liguzinski /* Bound drop probability */ 18544c730b0SWojciech Liguzinski if (pie->drop_prob < 0) 18644c730b0SWojciech Liguzinski pie->drop_prob = 0; 18744c730b0SWojciech Liguzinski if (pie->drop_prob > 1) 18844c730b0SWojciech Liguzinski pie->drop_prob = 1; 18944c730b0SWojciech Liguzinski 19044c730b0SWojciech Liguzinski pie->qdelay_old = current_qdelay; 19144c730b0SWojciech Liguzinski pie->last_measurement = time; 19244c730b0SWojciech Liguzinski 19344c730b0SWojciech Liguzinski uint64_t burst_allowance = pie->burst_allowance - pie_cfg->dp_update_interval; 19444c730b0SWojciech Liguzinski 19544c730b0SWojciech Liguzinski pie->burst_allowance = (burst_allowance > 0) ? burst_allowance : 0; 19644c730b0SWojciech Liguzinski } 19744c730b0SWojciech Liguzinski 19844c730b0SWojciech Liguzinski /** 19944c730b0SWojciech Liguzinski * @brief make a decision to drop or enqueue a packet based on probability 20044c730b0SWojciech Liguzinski * criteria 20144c730b0SWojciech Liguzinski * 20244c730b0SWojciech Liguzinski * @param pie_cfg [in] config pointer to a PIE configuration parameter structure 20344c730b0SWojciech Liguzinski * @param pie [in, out] data pointer to PIE runtime data 20444c730b0SWojciech Liguzinski * 20544c730b0SWojciech Liguzinski * @return operation status 20644c730b0SWojciech Liguzinski * @retval 0 enqueue the packet 20744c730b0SWojciech Liguzinski * @retval 1 drop the packet 20844c730b0SWojciech Liguzinski */ 20944c730b0SWojciech Liguzinski static inline int 21044c730b0SWojciech Liguzinski _rte_pie_drop(const struct rte_pie_config *pie_cfg, 21144c730b0SWojciech Liguzinski struct rte_pie *pie) 21244c730b0SWojciech Liguzinski { 213bb421e98SStephen Hemminger uint64_t qdelay = pie_cfg->qdelay_ref / 2; 21444c730b0SWojciech Liguzinski 21544c730b0SWojciech Liguzinski /* PIE is active but the queue is not congested: return 0 */ 21644c730b0SWojciech Liguzinski if (((pie->qdelay_old < qdelay) && (pie->drop_prob < 0.2)) || 21744c730b0SWojciech Liguzinski (pie->qlen <= (pie_cfg->tailq_th * 0.1))) 21844c730b0SWojciech Liguzinski return 0; 21944c730b0SWojciech Liguzinski 22044c730b0SWojciech Liguzinski if (pie->drop_prob == 0) 22144c730b0SWojciech Liguzinski pie->accu_prob = 0; 22244c730b0SWojciech Liguzinski 22344c730b0SWojciech Liguzinski /* For practical reasons, drop probability can be further scaled according 22444c730b0SWojciech Liguzinski * to packet size, but one needs to set a bound to avoid unnecessary bias 22544c730b0SWojciech Liguzinski * Random drop 22644c730b0SWojciech Liguzinski */ 22744c730b0SWojciech Liguzinski pie->accu_prob += pie->drop_prob; 22844c730b0SWojciech Liguzinski 22944c730b0SWojciech Liguzinski if (pie->accu_prob < 0.85) 23044c730b0SWojciech Liguzinski return 0; 23144c730b0SWojciech Liguzinski 23244c730b0SWojciech Liguzinski if (pie->accu_prob >= 8.5) 23344c730b0SWojciech Liguzinski return 1; 23444c730b0SWojciech Liguzinski 23545a192b2SStephen Hemminger if (rte_drand() < pie->drop_prob) { 23644c730b0SWojciech Liguzinski pie->accu_prob = 0; 23744c730b0SWojciech Liguzinski return 1; 23844c730b0SWojciech Liguzinski } 23944c730b0SWojciech Liguzinski 24044c730b0SWojciech Liguzinski /* No drop */ 24144c730b0SWojciech Liguzinski return 0; 24244c730b0SWojciech Liguzinski } 24344c730b0SWojciech Liguzinski 24444c730b0SWojciech Liguzinski /** 2457be78d02SJosh Soref * @brief Decides if new packet should be enqueued or dropped for non-empty queue 24644c730b0SWojciech Liguzinski * 24744c730b0SWojciech Liguzinski * @param pie_cfg [in] config pointer to a PIE configuration parameter structure 24844c730b0SWojciech Liguzinski * @param pie [in,out] data pointer to PIE runtime data 24944c730b0SWojciech Liguzinski * @param pkt_len [in] packet length in bytes 25044c730b0SWojciech Liguzinski * @param time [in] current time (measured in cpu cycles) 25144c730b0SWojciech Liguzinski * 25244c730b0SWojciech Liguzinski * @return Operation status 25344c730b0SWojciech Liguzinski * @retval 0 enqueue the packet 25444c730b0SWojciech Liguzinski * @retval 1 drop the packet based on max threshold criterion 25544c730b0SWojciech Liguzinski * @retval 2 drop the packet based on mark probability criterion 25644c730b0SWojciech Liguzinski */ 25744c730b0SWojciech Liguzinski static inline int 25844c730b0SWojciech Liguzinski rte_pie_enqueue_nonempty(const struct rte_pie_config *pie_cfg, 25944c730b0SWojciech Liguzinski struct rte_pie *pie, 26044c730b0SWojciech Liguzinski uint32_t pkt_len, 26144c730b0SWojciech Liguzinski const uint64_t time) 26244c730b0SWojciech Liguzinski { 26344c730b0SWojciech Liguzinski /* Check queue space against the tail drop threshold */ 26444c730b0SWojciech Liguzinski if (pie->qlen >= pie_cfg->tailq_th) { 26544c730b0SWojciech Liguzinski 26644c730b0SWojciech Liguzinski pie->accu_prob = 0; 26744c730b0SWojciech Liguzinski return 1; 26844c730b0SWojciech Liguzinski } 26944c730b0SWojciech Liguzinski 27044c730b0SWojciech Liguzinski if (pie->active) { 27144c730b0SWojciech Liguzinski /* Update drop probability after certain interval */ 27244c730b0SWojciech Liguzinski if ((time - pie->last_measurement) >= pie_cfg->dp_update_interval) 27344c730b0SWojciech Liguzinski _calc_drop_probability(pie_cfg, pie, time); 27444c730b0SWojciech Liguzinski 27544c730b0SWojciech Liguzinski /* Decide whether packet to be dropped or enqueued */ 27644c730b0SWojciech Liguzinski if (_rte_pie_drop(pie_cfg, pie) && pie->burst_allowance == 0) 27744c730b0SWojciech Liguzinski return 2; 27844c730b0SWojciech Liguzinski } 27944c730b0SWojciech Liguzinski 28044c730b0SWojciech Liguzinski /* When queue occupancy is over a certain threshold, turn on PIE */ 28144c730b0SWojciech Liguzinski if ((pie->active == 0) && 28244c730b0SWojciech Liguzinski (pie->qlen >= (pie_cfg->tailq_th * 0.1))) { 28344c730b0SWojciech Liguzinski pie->active = 1; 28444c730b0SWojciech Liguzinski pie->qdelay_old = 0; 28544c730b0SWojciech Liguzinski pie->drop_prob = 0; 28644c730b0SWojciech Liguzinski pie->in_measurement = 1; 28744c730b0SWojciech Liguzinski pie->departed_bytes_count = 0; 28844c730b0SWojciech Liguzinski pie->avg_dq_time = 0; 28944c730b0SWojciech Liguzinski pie->last_measurement = time; 29044c730b0SWojciech Liguzinski pie->burst_allowance = pie_cfg->max_burst; 29144c730b0SWojciech Liguzinski pie->accu_prob = 0; 29244c730b0SWojciech Liguzinski pie->start_measurement = time; 29344c730b0SWojciech Liguzinski } 29444c730b0SWojciech Liguzinski 29544c730b0SWojciech Liguzinski /* when queue has been idle for a while, turn off PIE and Reset counters */ 29644c730b0SWojciech Liguzinski if (pie->active == 1 && 29744c730b0SWojciech Liguzinski pie->qlen < (pie_cfg->tailq_th * 0.1)) { 29844c730b0SWojciech Liguzinski pie->active = 0; 29944c730b0SWojciech Liguzinski pie->in_measurement = 0; 30044c730b0SWojciech Liguzinski } 30144c730b0SWojciech Liguzinski 30244c730b0SWojciech Liguzinski /* Update PIE qlen parameter */ 30344c730b0SWojciech Liguzinski pie->qlen++; 30444c730b0SWojciech Liguzinski pie->qlen_bytes += pkt_len; 30544c730b0SWojciech Liguzinski 30644c730b0SWojciech Liguzinski /* No drop */ 30744c730b0SWojciech Liguzinski return 0; 30844c730b0SWojciech Liguzinski } 30944c730b0SWojciech Liguzinski 31044c730b0SWojciech Liguzinski /** 3117be78d02SJosh Soref * @brief Decides if new packet should be enqueued or dropped 31244c730b0SWojciech Liguzinski * Updates run time data and gives verdict whether to enqueue or drop the packet. 31344c730b0SWojciech Liguzinski * 31444c730b0SWojciech Liguzinski * @param pie_cfg [in] config pointer to a PIE configuration parameter structure 31544c730b0SWojciech Liguzinski * @param pie [in,out] data pointer to PIE runtime data 31644c730b0SWojciech Liguzinski * @param qlen [in] queue length 31744c730b0SWojciech Liguzinski * @param pkt_len [in] packet length in bytes 31844c730b0SWojciech Liguzinski * @param time [in] current time stamp (measured in cpu cycles) 31944c730b0SWojciech Liguzinski * 32044c730b0SWojciech Liguzinski * @return Operation status 32144c730b0SWojciech Liguzinski * @retval 0 enqueue the packet 3227be78d02SJosh Soref * @retval 1 drop the packet based on drop probability criteria 32344c730b0SWojciech Liguzinski */ 32444c730b0SWojciech Liguzinski static inline int 32544c730b0SWojciech Liguzinski rte_pie_enqueue(const struct rte_pie_config *pie_cfg, 32644c730b0SWojciech Liguzinski struct rte_pie *pie, 32744c730b0SWojciech Liguzinski const unsigned int qlen, 32844c730b0SWojciech Liguzinski uint32_t pkt_len, 32944c730b0SWojciech Liguzinski const uint64_t time) 33044c730b0SWojciech Liguzinski { 33144c730b0SWojciech Liguzinski RTE_ASSERT(pie_cfg != NULL); 33244c730b0SWojciech Liguzinski RTE_ASSERT(pie != NULL); 33344c730b0SWojciech Liguzinski 33444c730b0SWojciech Liguzinski if (qlen != 0) 33544c730b0SWojciech Liguzinski return rte_pie_enqueue_nonempty(pie_cfg, pie, pkt_len, time); 33644c730b0SWojciech Liguzinski else 33744c730b0SWojciech Liguzinski return rte_pie_enqueue_empty(pie_cfg, pie, pkt_len); 33844c730b0SWojciech Liguzinski } 33944c730b0SWojciech Liguzinski 34044c730b0SWojciech Liguzinski /** 34144c730b0SWojciech Liguzinski * @brief PIE rate estimation method 34244c730b0SWojciech Liguzinski * Called on each packet departure. 34344c730b0SWojciech Liguzinski * 34444c730b0SWojciech Liguzinski * @param pie [in] data pointer to PIE runtime data 34544c730b0SWojciech Liguzinski * @param pkt_len [in] packet length in bytes 34644c730b0SWojciech Liguzinski * @param time [in] current time stamp in cpu cycles 34744c730b0SWojciech Liguzinski */ 34844c730b0SWojciech Liguzinski static inline void 34944c730b0SWojciech Liguzinski rte_pie_dequeue(struct rte_pie *pie, 35044c730b0SWojciech Liguzinski uint32_t pkt_len, 35144c730b0SWojciech Liguzinski uint64_t time) 35244c730b0SWojciech Liguzinski { 35344c730b0SWojciech Liguzinski /* Dequeue rate estimation */ 35444c730b0SWojciech Liguzinski if (pie->in_measurement) { 35544c730b0SWojciech Liguzinski pie->departed_bytes_count += pkt_len; 35644c730b0SWojciech Liguzinski 35744c730b0SWojciech Liguzinski /* Start a new measurement cycle when enough packets */ 35844c730b0SWojciech Liguzinski if (pie->departed_bytes_count >= RTE_DQ_THRESHOLD) { 35944c730b0SWojciech Liguzinski uint64_t dq_time = time - pie->start_measurement; 36044c730b0SWojciech Liguzinski 36144c730b0SWojciech Liguzinski if (pie->avg_dq_time == 0) 36244c730b0SWojciech Liguzinski pie->avg_dq_time = dq_time; 36344c730b0SWojciech Liguzinski else 36444c730b0SWojciech Liguzinski pie->avg_dq_time = dq_time * RTE_DQ_WEIGHT + pie->avg_dq_time 36544c730b0SWojciech Liguzinski * (1 - RTE_DQ_WEIGHT); 36644c730b0SWojciech Liguzinski 36744c730b0SWojciech Liguzinski pie->in_measurement = 0; 36844c730b0SWojciech Liguzinski } 36944c730b0SWojciech Liguzinski } 37044c730b0SWojciech Liguzinski 37144c730b0SWojciech Liguzinski /* Start measurement cycle when enough data in the queue */ 37244c730b0SWojciech Liguzinski if ((pie->qlen_bytes >= RTE_DQ_THRESHOLD) && (pie->in_measurement == 0)) { 37344c730b0SWojciech Liguzinski pie->in_measurement = 1; 37444c730b0SWojciech Liguzinski pie->start_measurement = time; 37544c730b0SWojciech Liguzinski pie->departed_bytes_count = 0; 37644c730b0SWojciech Liguzinski } 37744c730b0SWojciech Liguzinski } 37844c730b0SWojciech Liguzinski 37944c730b0SWojciech Liguzinski #ifdef __cplusplus 38044c730b0SWojciech Liguzinski } 38144c730b0SWojciech Liguzinski #endif 38244c730b0SWojciech Liguzinski 38344c730b0SWojciech Liguzinski #endif /* __RTE_PIE_H_INCLUDED__ */ 384