[dpdk-dev] [RFC PATCH 1/2] sched: add dynamic config of subport bandwidth profile

Singh, Jasvinder jasvinder.singh at intel.com
Thu Jul 16 10:14:28 CEST 2020



> -----Original Message-----
> From: Dharmappa, Savinay <savinay.dharmappa at intel.com>
> Sent: Wednesday, July 15, 2020 7:28 PM
> To: Dharmappa, Savinay <savinay.dharmappa at intel.com>; Singh, Jasvinder
> <jasvinder.singh at intel.com>; dev at dpdk.org
> Subject: [RFC PATCH 1/2] sched: add dynamic config of subport bandwidth
> profile
> 
> This patch modifies the subport level data structures and add new API to
> allow dynamic configuration of the subport bandwidth profile.
> 
> Signed-off-by: Savinay Dharmappa <savinay.dharmappa at intel.com>
> Signed-off-by: Jasvinder Singh <jasvinder.singh at intel.com>
> ---
>  lib/librte_sched/rte_sched.c           | 486 ++++++++++++++++++++++++---------
>  lib/librte_sched/rte_sched.h           |  82 +++++-
>  lib/librte_sched/rte_sched_version.map |   2 +
>  3 files changed, 424 insertions(+), 146 deletions(-)
> 
> diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index
> c0983dd..5bb0d2b 100644
> --- a/lib/librte_sched/rte_sched.c
> +++ b/lib/librte_sched/rte_sched.c
> @@ -2,6 +2,7 @@
>   * Copyright(c) 2010-2014 Intel Corporation
>   */
> 
> +#include <stdint.h>
>  #include <stdio.h>
>  #include <string.h>
> 
> @@ -101,6 +102,16 @@ enum grinder_state {
>  	e_GRINDER_READ_MBUF
>  };
> 
> +struct rte_sched_subport_profile {
> +	/* Token bucket (TB) */
> +	uint64_t tb_period;
> +	uint64_t tb_credits_per_period;
> +	uint64_t tb_size;
> +
> +	uint64_t
> tc_credits_per_period[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE];
> +	uint64_t tc_period;
> +};
> +
>  struct rte_sched_grinder {
>  	/* Pipe cache */
>  	uint16_t pcache_qmask[RTE_SCHED_GRINDER_PCACHE_SIZE];
> @@ -113,6 +124,7 @@ struct rte_sched_grinder {
>  	uint32_t productive;
>  	uint32_t pindex;
>  	struct rte_sched_subport *subport;
> +	struct rte_sched_subport_profile *subport_params;
>  	struct rte_sched_pipe *pipe;
>  	struct rte_sched_pipe_profile *pipe_params;
> 
> @@ -139,18 +151,13 @@ struct rte_sched_grinder {  };
> 
>  struct rte_sched_subport {
> -	/* Token bucket (TB) */
> +
>  	uint64_t tb_time; /* time of last update */
> -	uint64_t tb_period;
> -	uint64_t tb_credits_per_period;
> -	uint64_t tb_size;
>  	uint64_t tb_credits;
> 
>  	/* Traffic classes (TCs) */
>  	uint64_t tc_time; /* time of next update */
> -	uint64_t
> tc_credits_per_period[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE];
>  	uint64_t tc_credits[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE];
> -	uint64_t tc_period;
> 
>  	/* TC oversubscription */
>  	uint64_t tc_ov_wm;
> @@ -164,6 +171,8 @@ struct rte_sched_subport {
>  	/* Statistics */
>  	struct rte_sched_subport_stats stats __rte_cache_aligned;
> 
> +	/* subport profile flag */
> +	uint32_t profile;
>  	/* Subport pipes */
>  	uint32_t n_pipes_per_subport_enabled;
>  	uint32_t n_pipe_profiles;
> @@ -212,6 +221,8 @@ struct rte_sched_port {
>  	uint16_t pipe_queue[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE];
>  	uint8_t pipe_tc[RTE_SCHED_QUEUES_PER_PIPE];
>  	uint8_t tc_queue[RTE_SCHED_QUEUES_PER_PIPE];
> +	uint32_t n_subport_profiles;
> +	uint32_t n_max_subport_profiles;
>  	uint64_t rate;
>  	uint32_t mtu;
>  	uint32_t frame_overhead;
> @@ -229,6 +240,7 @@ struct rte_sched_port {
>  	uint32_t subport_id;
> 
>  	/* Large data structures */
> +	struct rte_sched_subport_profile *subport_profiles;
>  	struct rte_sched_subport *subports[0] __rte_cache_aligned;  }
> __rte_cache_aligned;
> 
> @@ -375,8 +387,60 @@ pipe_profile_check(struct rte_sched_pipe_params
> *params,  }
> 
>  static int
> +subport_profile_check(struct rte_sched_subport_profile_params *params,
> +	uint64_t rate)
> +{
> +	uint32_t i;
> +
> +	/* Check user parameters */
> +	if (params == NULL) {
> +		RTE_LOG(ERR, SCHED,
> +			"%s: Incorrect value for parameter params\n",
> __func__);
> +		return -EINVAL;
> +	}
> +
> +	if (params->tb_rate == 0 || params->tb_rate > rate) {
> +		RTE_LOG(ERR, SCHED,
> +			"%s: Incorrect value for tb rate\n", __func__);
> +		return -EINVAL;
> +	}
> +
> +	if (params->tb_size == 0) {
> +		RTE_LOG(ERR, SCHED,
> +			"%s: Incorrect value for tb size\n", __func__);
> +		return -EINVAL;
> +	}
> +
> +	for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) {
> +		uint64_t tc_rate = params->tc_rate[i];
> +
> +		if (tc_rate == 0 || (tc_rate > params->tb_rate)) {
> +			RTE_LOG(ERR, SCHED,
> +				"%s: Incorrect value for tc rate\n", __func__);
> +			return -EINVAL;
> +		}
> +	}
> +
> +	if (params->tc_rate[RTE_SCHED_TRAFFIC_CLASS_BE] == 0) {
> +		RTE_LOG(ERR, SCHED,
> +			"%s: Incorrect tc rate(best effort)\n", __func__);
> +		return -EINVAL;
> +	}
> +
> +	if (params->tc_period == 0) {
> +		RTE_LOG(ERR, SCHED,
> +			"%s: Incorrect value for tc period\n", __func__);
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +static int
>  rte_sched_port_check_params(struct rte_sched_port_params *params)  {
> +	uint32_t i;
> +
>  	if (params == NULL) {
>  		RTE_LOG(ERR, SCHED,
>  			"%s: Incorrect value for parameter params\n",
> __func__); @@ -413,6 +477,29 @@ rte_sched_port_check_params(struct
> rte_sched_port_params *params)
>  		return -EINVAL;
>  	}
> 
> +	if (params->subport_profiles == NULL ||
> +		params->n_subport_profiles == 0 ||
> +		params->n_max_subport_profiles == 0 ||
> +		params->n_subport_profiles > params-
> >n_max_subport_profiles) {
> +		RTE_LOG(ERR, SCHED,
> +		"%s: Incorrect value for subport profiles\n", __func__);
> +		return -EINVAL;
> +	}
> +
> +	for (i = 0; i < params->n_subport_profiles; i++) {
> +		struct rte_sched_subport_profile_params *p =
> +						params->subport_profiles + i;
> +		int status;
> +
> +		status = subport_profile_check(p, params->rate);
> +		if (status != 0) {
> +			RTE_LOG(ERR, SCHED,
> +			"%s: subport profile check failed(%d)\n",
> +			__func__, status);
> +			return -EINVAL;
> +		}
> +	}
> +
>  	/* n_pipes_per_subport: non-zero, power of 2 */
>  	if (params->n_pipes_per_subport == 0 ||
>  	    !rte_is_power_of_2(params->n_pipes_per_subport)) { @@ -554,6
> +641,42 @@ rte_sched_port_log_pipe_profile(struct rte_sched_subport
> *subport, uint32_t i)
>  		p->wrr_cost[0], p->wrr_cost[1], p->wrr_cost[2], p-
> >wrr_cost[3]);  }
> 
> +static void
> +rte_sched_port_log_subport_profile(struct rte_sched_port *port,
> +uint32_t i) {
> +	struct rte_sched_subport_profile *p = port->subport_profiles + i;
> +
> +	RTE_LOG(DEBUG, SCHED, "Low level config for subport profile
> %u:\n"
> +	"Token bucket: period = %"PRIu64", credits per period = %"PRIu64",\
> +	size = %"PRIu64"\n"
> +	"Traffic classes: period = %"PRIu64",\n"
> +	"credits per period = [%"PRIu64", %"PRIu64", %"PRIu64", %"PRIu64
> +	" %"PRIu64", %"PRIu64", %"PRIu64", %"PRIu64", %"PRIu64",
> %"PRIu64
> +	" %"PRIu64", %"PRIu64", %"PRIu64"]\n",
> +	i,
> +
> +	/* Token bucket */
> +	p->tb_period,
> +	p->tb_credits_per_period,
> +	p->tb_size,
> +
> +	/* Traffic classes */
> +	p->tc_period,
> +	p->tc_credits_per_period[0],
> +	p->tc_credits_per_period[1],
> +	p->tc_credits_per_period[2],
> +	p->tc_credits_per_period[3],
> +	p->tc_credits_per_period[4],
> +	p->tc_credits_per_period[5],
> +	p->tc_credits_per_period[6],
> +	p->tc_credits_per_period[7],
> +	p->tc_credits_per_period[8],
> +	p->tc_credits_per_period[9],
> +	p->tc_credits_per_period[10],
> +	p->tc_credits_per_period[11],
> +	p->tc_credits_per_period[12]);
> +}
> +
>  static inline uint64_t
>  rte_sched_time_ms_to_bytes(uint64_t time_ms, uint64_t rate)  { @@ -623,6
> +746,37 @@ rte_sched_pipe_profile_convert(struct rte_sched_subport
> *subport,  }
> 
>  static void
> +rte_sched_subport_profile_convert(struct
> rte_sched_subport_profile_params *src,
> +	struct rte_sched_subport_profile *dst,
> +	uint64_t rate)
> +{
> +	uint32_t i;
> +
> +	/* Token Bucket */
> +	if (src->tb_rate == rate) {
> +		dst->tb_credits_per_period = 1;
> +		dst->tb_period = 1;
> +	} else {
> +		double tb_rate = (double) src->tb_rate
> +				/ (double) rate;
> +		double d = RTE_SCHED_TB_RATE_CONFIG_ERR;
> +
> +		rte_approx_64(tb_rate, d, &dst->tb_credits_per_period,
> +			&dst->tb_period);
> +	}
> +
> +	dst->tb_size = src->tb_size;
> +
> +	/* Traffic Classes */
> +	dst->tc_period = rte_sched_time_ms_to_bytes(src->tc_period, rate);
> +
> +	for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++)
> +		dst->tc_credits_per_period[i]
> +			= rte_sched_time_ms_to_bytes(src->tc_period,
> +				src->tc_rate[i]);
> +}
> +
> +static void
>  rte_sched_subport_config_pipe_profile_table(struct rte_sched_subport
> *subport,
>  	struct rte_sched_subport_params *params, uint32_t rate)  { @@ -
> 646,6 +800,24 @@ rte_sched_subport_config_pipe_profile_table(struct
> rte_sched_subport *subport,
>  	}
>  }
> 
> +static void
> +rte_sched_port_config_subport_profile_table(struct rte_sched_port *port,
> +	struct rte_sched_port_params *params,
> +	uint64_t rate)
> +{
> +	uint32_t i;
> +
> +	for (i = 0; i < port->n_subport_profiles; i++) {
> +		struct rte_sched_subport_profile_params *src
> +				= params->subport_profiles + i;
> +		struct rte_sched_subport_profile *dst
> +				= port->subport_profiles + i;
> +
> +		rte_sched_subport_profile_convert(src, dst, rate);
> +		rte_sched_port_log_subport_profile(port, i);
> +	}
> +}
> +
>  static int
>  rte_sched_subport_check_params(struct rte_sched_subport_params
> *params,
>  	uint32_t n_max_pipes_per_subport,
> @@ -660,18 +832,6 @@ rte_sched_subport_check_params(struct
> rte_sched_subport_params *params,
>  		return -EINVAL;
>  	}
> 
> -	if (params->tb_rate == 0 || params->tb_rate > rate) {
> -		RTE_LOG(ERR, SCHED,
> -			"%s: Incorrect value for tb rate\n", __func__);
> -		return -EINVAL;
> -	}
> -
> -	if (params->tb_size == 0) {
> -		RTE_LOG(ERR, SCHED,
> -			"%s: Incorrect value for tb size\n", __func__);
> -		return -EINVAL;
> -	}
> -
>  	/* qsize: if non-zero, power of 2,
>  	 * no bigger than 32K (due to 16-bit read/write pointers)
>  	 */
> @@ -685,32 +845,12 @@ rte_sched_subport_check_params(struct
> rte_sched_subport_params *params,
>  		}
>  	}
> 
> -	for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) {
> -		uint64_t tc_rate = params->tc_rate[i];
> -		uint16_t qsize = params->qsize[i];
> -
> -		if ((qsize == 0 && tc_rate != 0) ||
> -			(qsize != 0 && tc_rate == 0) ||
> -			(tc_rate > params->tb_rate)) {
> -			RTE_LOG(ERR, SCHED,
> -				"%s: Incorrect value for tc rate\n", __func__);
> -			return -EINVAL;
> -		}
> -	}
> -
> -	if (params->qsize[RTE_SCHED_TRAFFIC_CLASS_BE] == 0 ||
> -		params->tc_rate[RTE_SCHED_TRAFFIC_CLASS_BE] == 0) {
> +	if (params->qsize[RTE_SCHED_TRAFFIC_CLASS_BE] == 0) {
>  		RTE_LOG(ERR, SCHED,
>  			"%s: Incorrect qsize or tc rate(best effort)\n",
> __func__);
>  		return -EINVAL;
>  	}
> 
> -	if (params->tc_period == 0) {
> -		RTE_LOG(ERR, SCHED,
> -			"%s: Incorrect value for tc period\n", __func__);
> -		return -EINVAL;
> -	}
> -
>  	/* n_pipes_per_subport: non-zero, power of 2 */
>  	if (params->n_pipes_per_subport_enabled == 0 ||
>  		params->n_pipes_per_subport_enabled >
> n_max_pipes_per_subport || @@ -792,7 +932,7 @@ struct rte_sched_port
> *  rte_sched_port_config(struct rte_sched_port_params *params)  {
>  	struct rte_sched_port *port = NULL;
> -	uint32_t size0, size1;
> +	uint32_t size0, size1, size2;
>  	uint32_t cycles_per_byte;
>  	uint32_t i, j;
>  	int status;
> @@ -807,10 +947,21 @@ rte_sched_port_config(struct
> rte_sched_port_params *params)
> 
>  	size0 = sizeof(struct rte_sched_port);
>  	size1 = params->n_subports_per_port * sizeof(struct
> rte_sched_subport *);
> +	size2 = params->n_max_subport_profiles *
> +		sizeof(struct rte_sched_subport_profile);
> 
>  	/* Allocate memory to store the data structures */
> -	port = rte_zmalloc_socket("qos_params", size0 + size1,
> RTE_CACHE_LINE_SIZE,
> -		params->socket);
> +	port = rte_zmalloc_socket("qos_params", size0 + size1,
> +				 RTE_CACHE_LINE_SIZE, params->socket);
> +	if (port == NULL) {
> +		RTE_LOG(ERR, SCHED, "%s: Memory allocation fails\n",
> __func__);
> +
> +		return NULL;
> +	}
> +
> +	/* Allocate memory to store the subport profile */
> +	port->subport_profiles  = rte_zmalloc_socket("subport_profile",
> size2,
> +					RTE_CACHE_LINE_SIZE, params-
> >socket);
>  	if (port == NULL) {
>  		RTE_LOG(ERR, SCHED, "%s: Memory allocation fails\n",
> __func__);
> 
> @@ -819,6 +970,8 @@ rte_sched_port_config(struct
> rte_sched_port_params *params)
> 
>  	/* User parameters */
>  	port->n_subports_per_port = params->n_subports_per_port;
> +	port->n_subport_profiles = params->n_subport_profiles;
> +	port->n_max_subport_profiles = params->n_max_subport_profiles;
>  	port->n_pipes_per_subport = params->n_pipes_per_subport;
>  	port->n_pipes_per_subport_log2 =
>  			__builtin_ctz(params->n_pipes_per_subport);
> @@ -849,6 +1002,9 @@ rte_sched_port_config(struct
> rte_sched_port_params *params)
>  	port->time_cpu_bytes = 0;
>  	port->time = 0;
> 
> +	/* Subport profile table */
> +	rte_sched_port_config_subport_profile_table(port, params, port-
> >rate);
> +
>  	cycles_per_byte = (rte_get_tsc_hz() << RTE_SCHED_TIME_SHIFT)
>  		/ params->rate;
>  	port->inv_cycles_per_byte = rte_reciprocal_value(cycles_per_byte);
> @@ -907,48 +1063,6 @@ rte_sched_port_free(struct rte_sched_port *port)
> }
> 
>  static void
> -rte_sched_port_log_subport_config(struct rte_sched_port *port, uint32_t i)
> -{
> -	struct rte_sched_subport *s = port->subports[i];
> -
> -	RTE_LOG(DEBUG, SCHED, "Low level config for subport %u:\n"
> -		"	Token bucket: period = %"PRIu64", credits per period
> = %"PRIu64
> -		", size = %"PRIu64"\n"
> -		"	Traffic classes: period = %"PRIu64"\n"
> -		"	credits per period = [%"PRIu64", %"PRIu64",
> %"PRIu64", %"PRIu64
> -		", %"PRIu64", %"PRIu64", %"PRIu64", %"PRIu64", %"PRIu64",
> %"PRIu64
> -		", %"PRIu64", %"PRIu64", %"PRIu64"]\n"
> -		"	Best effort traffic class oversubscription: wm min =
> %"PRIu64
> -		", wm max = %"PRIu64"\n",
> -		i,
> -
> -		/* Token bucket */
> -		s->tb_period,
> -		s->tb_credits_per_period,
> -		s->tb_size,
> -
> -		/* Traffic classes */
> -		s->tc_period,
> -		s->tc_credits_per_period[0],
> -		s->tc_credits_per_period[1],
> -		s->tc_credits_per_period[2],
> -		s->tc_credits_per_period[3],
> -		s->tc_credits_per_period[4],
> -		s->tc_credits_per_period[5],
> -		s->tc_credits_per_period[6],
> -		s->tc_credits_per_period[7],
> -		s->tc_credits_per_period[8],
> -		s->tc_credits_per_period[9],
> -		s->tc_credits_per_period[10],
> -		s->tc_credits_per_period[11],
> -		s->tc_credits_per_period[12],
> -
> -		/* Best effort traffic class oversubscription */
> -		s->tc_ov_wm_min,
> -		s->tc_ov_wm_max);
> -}
> -
> -static void
>  rte_sched_free_memory(struct rte_sched_port *port, uint32_t n_subports)
> {
>  	uint32_t i;
> @@ -1021,33 +1135,7 @@ rte_sched_subport_config(struct rte_sched_port
> *port,
>  	/* Port */
>  	port->subports[subport_id] = s;
> 
> -	/* Token Bucket (TB) */
> -	if (params->tb_rate == port->rate) {
> -		s->tb_credits_per_period = 1;
> -		s->tb_period = 1;
> -	} else {
> -		double tb_rate = ((double) params->tb_rate) / ((double)
> port->rate);
> -		double d = RTE_SCHED_TB_RATE_CONFIG_ERR;
> -
> -		rte_approx_64(tb_rate, d, &s->tb_credits_per_period, &s-
> >tb_period);
> -	}
> -
> -	s->tb_size = params->tb_size;
>  	s->tb_time = port->time;
> -	s->tb_credits = s->tb_size / 2;
> -
> -	/* Traffic Classes (TCs) */
> -	s->tc_period = rte_sched_time_ms_to_bytes(params->tc_period,
> port->rate);
> -	for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) {
> -		if (params->qsize[i])
> -			s->tc_credits_per_period[i]
> -				= rte_sched_time_ms_to_bytes(params-
> >tc_period,
> -					params->tc_rate[i]);
> -	}
> -	s->tc_time = port->time + s->tc_period;
> -	for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++)
> -		if (params->qsize[i])
> -			s->tc_credits[i] = s->tc_credits_per_period[i];
> 
>  	/* compile time checks */
>  	RTE_BUILD_BUG_ON(RTE_SCHED_PORT_N_GRINDERS == 0); @@ -
> 1137,8 +1225,6 @@ rte_sched_subport_config(struct rte_sched_port *port,
> #ifdef RTE_SCHED_SUBPORT_TC_OV
>  	/* TC oversubscription */
>  	s->tc_ov_wm_min = port->mtu;
> -	s->tc_ov_wm_max = rte_sched_time_ms_to_bytes(params-
> >tc_period,
> -						     s->pipe_tc_be_rate_max);
>  	s->tc_ov_wm = s->tc_ov_wm_max;
>  	s->tc_ov_period_id = 0;
>  	s->tc_ov = 0;
> @@ -1146,7 +1232,54 @@ rte_sched_subport_config(struct rte_sched_port
> *port,
>  	s->tc_ov_rate = 0;
>  #endif
> 
> -	rte_sched_port_log_subport_config(port, subport_id);
> +	return 0;
> +}
> +
> +int
> +rte_sched_subport_profile_config(struct rte_sched_port *port,
> +	uint32_t subport_id,
> +	uint32_t profile_id)
> +{
> +	int i;
> +	struct rte_sched_subport_profile *params;
> +	uint32_t n_subports = subport_id + 1;
> +	struct rte_sched_subport *s;
> +
> +	if (port == NULL) {
> +		RTE_LOG(ERR, SCHED,
> +			"%s: Incorrect value for parameter port\n",
> __func__);
> +		return -EINVAL;
> +	}
> +
> +	if (subport_id >= port->n_subports_per_port) {
> +		RTE_LOG(ERR, SCHED,
> +			"%s: Incorrect value for parameter subport id\n",
> __func__);
> +
> +		rte_sched_free_memory(port, n_subports);
> +		return -EINVAL;
> +	}
> +
> +	params =  port->subport_profiles + profile_id;
> +
> +	s = port->subports[subport_id];
> +
> +	s->tb_credits = params->tb_size / 2;
> +
> +	s->tc_time = port->time + params->tc_period;
> +
> +	for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++)
> +		if (s->qsize[i])
> +			s->tc_credits[i] = params->tc_credits_per_period[i];
> +		else
> +			params->tc_credits_per_period[i] = 0;
> +
> +#ifdef RTE_SCHED_SUBPORT_TC_OV
> +	s->tc_ov_wm_max = rte_sched_time_ms_to_bytes(params-
> >tc_period,
> +						     s->pipe_tc_be_rate_max);
> +#endif
> +	s->profile = profile_id;
> +
> +	rte_sched_port_log_subport_profile(port, profile_id);
> 
>  	return 0;
>  }
> @@ -1158,6 +1291,7 @@ rte_sched_pipe_config(struct rte_sched_port
> *port,
>  	int32_t pipe_profile)
>  {
>  	struct rte_sched_subport *s;
> +	struct rte_sched_subport_profile *sp;
>  	struct rte_sched_pipe *p;
>  	struct rte_sched_pipe_profile *params;
>  	uint32_t n_subports = subport_id + 1;
> @@ -1198,14 +1332,16 @@ rte_sched_pipe_config(struct rte_sched_port
> *port,
>  		return -EINVAL;
>  	}
> 
> +	sp = port->subport_profiles + s->profile;
> +
>  	/* Handle the case when pipe already has a valid configuration */
>  	p = s->pipe + pipe_id;
>  	if (p->tb_time) {
>  		params = s->pipe_profiles + p->profile;
> 
>  		double subport_tc_be_rate =
> -			(double) s-
> >tc_credits_per_period[RTE_SCHED_TRAFFIC_CLASS_BE]
> -			/ (double) s->tc_period;
> +		(double) sp-
> >tc_credits_per_period[RTE_SCHED_TRAFFIC_CLASS_BE]
> +		/ (double) sp->tc_period;
>  		double pipe_tc_be_rate =
>  			(double) params-
> >tc_credits_per_period[RTE_SCHED_TRAFFIC_CLASS_BE]
>  			/ (double) params->tc_period;
> @@ -1247,8 +1383,8 @@ rte_sched_pipe_config(struct rte_sched_port
> *port,
>  	{
>  		/* Subport best effort tc oversubscription */
>  		double subport_tc_be_rate =
> -			(double) s-
> >tc_credits_per_period[RTE_SCHED_TRAFFIC_CLASS_BE]
> -			/ (double) s->tc_period;
> +		(double) sp-
> >tc_credits_per_period[RTE_SCHED_TRAFFIC_CLASS_BE]
> +			/ (double) sp->tc_period;
>  		double pipe_tc_be_rate =
>  			(double) params-
> >tc_credits_per_period[RTE_SCHED_TRAFFIC_CLASS_BE]
>  			/ (double) params->tc_period;
> @@ -1260,8 +1396,9 @@ rte_sched_pipe_config(struct rte_sched_port
> *port,
> 
>  		if (s->tc_ov != tc_be_ov) {
>  			RTE_LOG(DEBUG, SCHED,
> -				"Subport %u Best effort TC oversubscription
> is ON (%.4lf < %.4lf)\n",
> -				subport_id, subport_tc_be_rate, s-
> >tc_ov_rate);
> +			"Subport %u Best effort TC oversubscription is ON \
> +			(%.4lf < %.4lf)\n",
> +			subport_id, subport_tc_be_rate, s->tc_ov_rate);
>  		}
>  		p->tc_ov_period_id = s->tc_ov_period_id;
>  		p->tc_ov_credits = s->tc_ov_wm;
> @@ -1335,6 +1472,72 @@ rte_sched_subport_pipe_profile_add(struct
> rte_sched_port *port,
>  	return 0;
>  }
> 
> +int
> +rte_sched_port_subport_profile_add(struct rte_sched_port *port,
> +	struct rte_sched_subport_profile_params *params,
> +	uint32_t *subport_profile_id)
> +{
> +	int status;
> +	uint32_t i;
> +	struct rte_sched_subport_profile *dst;
> +
> +	/* Port */
> +	if (port == NULL) {
> +		RTE_LOG(ERR, SCHED,
> +		"%s: Incorrect value for parameter port\n", __func__);
> +		return -EINVAL;
> +	}
> +
> +	if (params == NULL) {
> +		RTE_LOG(ERR, SCHED,
> +		"%s: Incorrect value for parameter profile\n", __func__);
> +		return -EINVAL;
> +	}
> +
> +	if (subport_profile_id == NULL) {
> +		RTE_LOG(ERR, SCHED,
> +		"%s: Incorrect value for parameter \
> +		subport_profile_id\n", __func__);
> +		return -EINVAL;
> +	}
> +
> +	dst = port->subport_profiles + port->n_subport_profiles;
> +
> +	/* Subport profiles exceeds the max limit */
> +	if (port->n_subport_profiles >= port->n_max_subport_profiles) {
> +		RTE_LOG(ERR, SCHED,
> +		"%s: Number of subport profiles exceeds \
> +		the max limit\n", __func__);
> +		return -EINVAL;
> +	}
> +
> +	status = subport_profile_check(params, port->rate);
> +	if (status != 0) {
> +		RTE_LOG(ERR, SCHED,
> +		"%s: subport profile check failed(%d)\n", __func__, status);
> +		return -EINVAL;
> +	}
> +
> +	rte_sched_subport_profile_convert(params, dst, port->rate);
> +
> +	/* Subport profile should not exists */
> +	for (i = 0; i < port->n_subport_profiles; i++)
> +		if (memcmp(port->subport_profiles + i,
> +		    params, sizeof(*params)) == 0) {
> +			RTE_LOG(ERR, SCHED,
> +			"%s: subport profile exists\n", __func__);
> +			return -EINVAL;
> +		}
> +
> +	/* Subport profile commit */
> +	*subport_profile_id = port->n_subport_profiles;
> +	port->n_subport_profiles++;
> +
> +	rte_sched_port_log_subport_profile(port, *subport_profile_id);
> +
> +	return 0;
> +}
> +
>  static inline uint32_t
>  rte_sched_port_qindex(struct rte_sched_port *port,
>  	uint32_t subport,
> @@ -1970,14 +2173,18 @@ grinder_credits_update(struct rte_sched_port
> *port,
>  	struct rte_sched_grinder *grinder = subport->grinder + pos;
>  	struct rte_sched_pipe *pipe = grinder->pipe;
>  	struct rte_sched_pipe_profile *params = grinder->pipe_params;
> +	struct rte_sched_subport_profile *subport_params =
> +						grinder->subport_params;
>  	uint64_t n_periods;
>  	uint32_t i;
> 
>  	/* Subport TB */
> -	n_periods = (port->time - subport->tb_time) / subport->tb_period;
> -	subport->tb_credits += n_periods * subport->tb_credits_per_period;
> -	subport->tb_credits = RTE_MIN(subport->tb_credits, subport-
> >tb_size);
> -	subport->tb_time += n_periods * subport->tb_period;
> +	n_periods = (port->time - subport->tb_time) / subport_params-
> >tb_period;
> +	subport->tb_credits += n_periods *
> +			       subport_params->tb_credits_per_period;
> +	subport->tb_credits = RTE_MIN(subport->tb_credits,
> +				      subport_params->tb_size);
> +	subport->tb_time += n_periods * subport_params->tb_period;
> 
>  	/* Pipe TB */
>  	n_periods = (port->time - pipe->tb_time) / params->tb_period; @@ -
> 1988,9 +2195,10 @@ grinder_credits_update(struct rte_sched_port *port,
>  	/* Subport TCs */
>  	if (unlikely(port->time >= subport->tc_time)) {
>  		for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++)
> -			subport->tc_credits[i] = subport-
> >tc_credits_per_period[i];
> +			subport->tc_credits[i] =
> +				subport_params->tc_credits_per_period[i];
> 
> -		subport->tc_time = port->time + subport->tc_period;
> +		subport->tc_time = port->time + subport_params->tc_period;
>  	}
> 
>  	/* Pipe TCs */
> @@ -2008,6 +2216,8 @@ static inline uint64_t
> grinder_tc_ov_credits_update(struct rte_sched_port *port,
>  	struct rte_sched_subport *subport)
>  {
> +	struct rte_sched_subport_profile *subport_params =
> +						grinder->subport_params;
>  	uint64_t
> tc_ov_consumption[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE];
>  	uint64_t tc_consumption = 0, tc_ov_consumption_max;
>  	uint64_t tc_ov_wm = subport->tc_ov_wm; @@ -2018,16 +2228,17
> @@ grinder_tc_ov_credits_update(struct rte_sched_port *port,
> 
>  	for (i = 0; i < RTE_SCHED_TRAFFIC_CLASS_BE; i++) {
>  		tc_ov_consumption[i] =
> -			subport->tc_credits_per_period[i] - subport-
> >tc_credits[i];
> +			subport_params->tc_credits_per_period[i] -
> +						subport->tc_credits[i];
>  		tc_consumption += tc_ov_consumption[i];
>  	}
> 
>  	tc_ov_consumption[RTE_SCHED_TRAFFIC_CLASS_BE] =
> -		subport-
> >tc_credits_per_period[RTE_SCHED_TRAFFIC_CLASS_BE] -
> +	subport_params-
> >tc_credits_per_period[RTE_SCHED_TRAFFIC_CLASS_BE] -
>  		subport->tc_credits[RTE_SCHED_TRAFFIC_CLASS_BE];
> 
>  	tc_ov_consumption_max =
> -		subport-
> >tc_credits_per_period[RTE_SCHED_TRAFFIC_CLASS_BE] -
> +	subport_params-
> >tc_credits_per_period[RTE_SCHED_TRAFFIC_CLASS_BE] -
>  			tc_consumption;
> 
>  	if (tc_ov_consumption[RTE_SCHED_TRAFFIC_CLASS_BE] > @@ -
> 2053,14 +2264,18 @@ grinder_credits_update(struct rte_sched_port *port,
>  	struct rte_sched_grinder *grinder = subport->grinder + pos;
>  	struct rte_sched_pipe *pipe = grinder->pipe;
>  	struct rte_sched_pipe_profile *params = grinder->pipe_params;
> +	struct rte_sched_subport_profile *subport_params =
> +						grinder->subport_params;
>  	uint64_t n_periods;
>  	uint32_t i;
> 
>  	/* Subport TB */
> -	n_periods = (port->time - subport->tb_time) / subport->tb_period;
> -	subport->tb_credits += n_periods * subport->tb_credits_per_period;
> -	subport->tb_credits = RTE_MIN(subport->tb_credits, subport-
> >tb_size);
> -	subport->tb_time += n_periods * subport->tb_period;
> +	n_periods = (port->time - subport->tb_time) / subport_params-
> >tb_period;
> +	subport->tb_credits += n_periods *
> +				subport_params->tb_credits_per_period;
> +	subport->tb_credits = RTE_MIN(subport->tb_credits,
> +				subport_params->tb_size);
> +	subport->tb_time += n_periods * subport_params->tb_period;
> 
>  	/* Pipe TB */
>  	n_periods = (port->time - pipe->tb_time) / params->tb_period; @@ -
> 2073,9 +2288,10 @@ grinder_credits_update(struct rte_sched_port *port,
>  		subport->tc_ov_wm = grinder_tc_ov_credits_update(port,
> subport);
> 
>  		for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++)
> -			subport->tc_credits[i] = subport-
> >tc_credits_per_period[i];
> +			subport->tc_credits[i] =
> +				subport_params->tc_credits_per_period[i];
> 
> -		subport->tc_time = port->time + subport->tc_period;
> +		subport->tc_time = port->time + subport_params->tc_period;
>  		subport->tc_ov_period_id++;
>  	}
> 
> @@ -2598,6 +2814,8 @@ grinder_handle(struct rte_sched_port *port,
>  		struct rte_sched_pipe *pipe = grinder->pipe;
> 
>  		grinder->pipe_params = subport->pipe_profiles + pipe-
> >profile;
> +		grinder->subport_params = port->subport_profiles +
> +					  subport->profile;
>  		grinder_prefetch_tc_queue_arrays(subport, pos);
>  		grinder_credits_update(port, subport, pos);
> 
> diff --git a/lib/librte_sched/rte_sched.h b/lib/librte_sched/rte_sched.h index
> 8a5a93c..7623919 100644
> --- a/lib/librte_sched/rte_sched.h
> +++ b/lib/librte_sched/rte_sched.h
> @@ -149,18 +149,6 @@ struct rte_sched_pipe_params {
>   * byte.
>   */
>  struct rte_sched_subport_params {
> -	/** Token bucket rate (measured in bytes per second) */
> -	uint64_t tb_rate;
> -
> -	/** Token bucket size (measured in credits) */
> -	uint64_t tb_size;
> -
> -	/** Traffic class rates (measured in bytes per second) */
> -	uint64_t tc_rate[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE];
> -
> -	/** Enforcement period for rates (measured in milliseconds) */
> -	uint64_t tc_period;
> -
>  	/** Number of subport pipes.
>  	 * The subport can enable/allocate fewer pipes than the maximum
>  	 * number set through struct
> port_params::n_max_pipes_per_subport,
> @@ -192,6 +180,20 @@ struct rte_sched_subport_params {  #endif  };
> 
> +struct rte_sched_subport_profile_params {
> +	/** Token bucket rate (measured in bytes per second) */
> +	uint64_t tb_rate;
> +
> +	/** Token bucket size (measured in credits) */
> +	uint64_t tb_size;
> +
> +	/** Traffic class rates (measured in bytes per second) */
> +	uint64_t tc_rate[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE];
> +
> +	/** Enforcement period for rates (measured in milliseconds) */
> +	uint64_t tc_period;
> +};
> +
>  /** Subport statistics */
>  struct rte_sched_subport_stats {
>  	/** Number of packets successfully written */ @@ -254,6 +256,17
> @@ struct rte_sched_port_params {
>  	/** Number of subports */
>  	uint32_t n_subports_per_port;
> 
> +	/** subport profile table.
> +	 * Every pipe is configured using one of the profiles from this table.
> +	 */
> +	struct rte_sched_subport_profile_params *subport_profiles;
> +
> +	/** Profiles in the pipe profile table */
> +	uint32_t n_subport_profiles;
> +
> +	/** Max allowed profiles in the pipe profile table */
> +	uint32_t n_max_subport_profiles;
> +
>  	/** Maximum number of subport pipes.
>  	 * This parameter is used to reserve a fixed number of bits
>  	 * in struct rte_mbuf::sched.queue_id for the pipe_id for all @@ -
> 312,6 +325,29 @@ rte_sched_subport_pipe_profile_add(struct
> rte_sched_port *port,
>  	uint32_t *pipe_profile_id);
> 
>  /**
> + * @warning
> + * @b EXPERIMENTAL: this API may change without prior notice.
> + *
> + * Hierarchical scheduler subport bandwidth profile add
> + * Note that this function is safe to use in runtime for adding new
> + * subport bandwidth profile as it doesn't have any impact on
> +hiearchical
> + * structure of the scheduler.
> + * @param port
> + *   Handle to port scheduler instance
> + * @param struct rte_sched_subport_profile
> + *   Subport bandwidth profile
> + * @param subport_profile_d
> + *   Subport profile id
> + * @return
> + *   0 upon success, error code otherwise
> + */
> +__rte_experimental
> +int
> +rte_sched_port_subport_profile_add(struct rte_sched_port *port,
> +	struct rte_sched_subport_profile_params *profile,
> +	uint32_t *subport_profile_id);
> +
> +/**
>   * Hierarchical scheduler subport configuration
>   *
>   * @param port
> @@ -329,6 +365,28 @@ rte_sched_subport_config(struct rte_sched_port
> *port,
>  	struct rte_sched_subport_params *params);
> 
>  /**
> + * @warning
> + * @b EXPERIMENTAL: this API may change without prior notice.
> + *
> + * Hierarchical scheduler subport profile configuration
> + * Note that this function is safe to use in runtime for applying any
> +specific
> + * subport bandwidth profile as it doesn't have any impact on
> +hiearchical
> + * structure of the scheduler.
> + * @param port
> + *   Handle to port scheduler instance
> + * @param subport_id
> + *   Subport ID
> + * @param profile_d
> + *   Subport profile id
> + * @return
> + *   0 upon success, error code otherwise
> + */
> +__rte_experimental
> +int
> +rte_sched_subport_profile_config(struct rte_sched_port *port,
> +	uint32_t subport_id,
> +	uint32_t profile_id);
> +/**
>   * Hierarchical scheduler pipe configuration
>   *
>   * @param port
> diff --git a/lib/librte_sched/rte_sched_version.map
> b/lib/librte_sched/rte_sched_version.map
> index cefd990..c02a223 100644
> --- a/lib/librte_sched/rte_sched_version.map
> +++ b/lib/librte_sched/rte_sched_version.map
> @@ -28,4 +28,6 @@ EXPERIMENTAL {
>  	global:
> 
>  	rte_sched_subport_pipe_profile_add;
> +	rte_sched_port_subport_profile_add;
> +	rte_sched_subport_profile_config;
>  };
> --
> 2.7.4

+ Cristian


More information about the dev mailing list