xref: /dpdk/lib/sched/rte_pie.h (revision 719834a6849e1daf4a70ff7742bbcc3ae7e25607)
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