[v5,3/9] sched : add dynamic config of subport bandwidth

Message ID 20200930192434.47793-4-savinay.dharmappa@intel.com (mailing list archive)
State Superseded, archived
Delegated to: Thomas Monjalon
Headers
Series Enable dynamic config of subport bandwidth |

Checks

Context Check Description
ci/checkpatch success coding style OK

Commit Message

Savinay Dharmappa Sept. 30, 2020, 7:24 p.m. UTC
  This patch adds support for dynamic config of subport bandwidth.

Signed-off-by: Savinay Dharmappa <savinay.dharmappa@intel.com>
Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com>
---
 lib/librte_sched/rte_sched.c | 219 +++++++++++++++++++++++++++++++++++
 lib/librte_sched/rte_sched.h |  23 ++++
 2 files changed, 242 insertions(+)
  

Patch

diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c
index 895b40d72..54940c451 100644
--- a/lib/librte_sched/rte_sched.c
+++ b/lib/librte_sched/rte_sched.c
@@ -174,6 +174,8 @@  struct rte_sched_subport {
 	/* Statistics */
 	struct rte_sched_subport_stats stats __rte_cache_aligned;
 
+	/* subport profile */
+	uint32_t profile;
 	/* Subport pipes */
 	uint32_t n_pipes_per_subport_enabled;
 	uint32_t n_pipe_profiles;
@@ -1155,6 +1157,49 @@  rte_sched_free_memory(struct rte_sched_port *port, uint32_t n_subports)
 	rte_free(port);
 }
 
+static int
+rte_sched_subport_profile_config(struct rte_sched_port *port,
+	uint32_t subport_id,
+	uint32_t subport_profile_id)
+{
+	int i;
+	struct rte_sched_subport_profile *params;
+	struct rte_sched_subport *s;
+
+	/* Subport profile exceeds the max limit */
+	if (subport_profile_id >= port->n_max_subport_profiles) {
+		RTE_LOG(ERR, SCHED, "%s: "
+		"Number of subport profile exceeds the max limit\n",
+		 __func__);
+		return -EINVAL;
+	}
+
+	params =  port->subport_profiles + subport_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 = subport_profile_id;
+
+	rte_sched_port_log_subport_profile(port, subport_profile_id);
+
+	return 0;
+}
+
 int
 rte_sched_subport_config(struct rte_sched_port *port,
 	uint32_t subport_id,
@@ -1344,6 +1389,180 @@  rte_sched_subport_config(struct rte_sched_port *port,
 	return 0;
 }
 
+int
+rte_dynamic_sched_subport_config(struct rte_sched_port *port,
+	uint32_t subport_id,
+	struct rte_sched_subport_params *params,
+	uint32_t subport_profile_id)
+{
+	struct rte_sched_subport *s = NULL;
+	uint32_t n_subports = subport_id;
+	uint32_t n_subport_pipe_queues, i;
+	uint32_t size0, size1, bmp_mem_size;
+	int status;
+
+	/* Check user parameters */
+	if (port == NULL) {
+		RTE_LOG(ERR, SCHED,
+			"%s: Incorrect value for parameter port\n", __func__);
+		return 0;
+	}
+
+	if (subport_id >= port->n_subports_per_port) {
+		RTE_LOG(ERR, SCHED,
+			"%s: Incorrect value for subport id\n", __func__);
+
+		rte_sched_free_memory(port, n_subports);
+		return -EINVAL;
+	}
+
+
+	if (port->subports[subport_id] == NULL) {
+
+		status = rte_sched_subport_check_params(params,
+			port->n_pipes_per_subport,
+			port->rate);
+
+		if (status != 0) {
+			RTE_LOG(NOTICE, SCHED,
+				"%s: Port scheduler params check failed (%d)\n",
+				__func__, status);
+
+			rte_sched_free_memory(port, n_subports);
+			return -EINVAL;
+		}
+
+		/* Determine the amount of memory to allocate */
+		size0 = sizeof(struct rte_sched_subport);
+		size1 = rte_sched_subport_get_array_base(params,
+					e_RTE_SCHED_SUBPORT_ARRAY_TOTAL);
+
+		/* Allocate memory to store the data structures */
+		s = rte_zmalloc_socket("subport_params", size0 + size1,
+			RTE_CACHE_LINE_SIZE, port->socket);
+		if (s == NULL) {
+			RTE_LOG(ERR, SCHED,
+				"%s: Memory allocation fails\n", __func__);
+
+			rte_sched_free_memory(port, n_subports);
+			return -ENOMEM;
+		}
+
+		n_subports++;
+
+		/* Port */
+		port->subports[subport_id] = s;
+
+		s->tb_time = port->time;
+
+		subport_profile_id = 0;
+
+		/* compile time checks */
+		RTE_BUILD_BUG_ON(RTE_SCHED_PORT_N_GRINDERS == 0);
+		RTE_BUILD_BUG_ON(RTE_SCHED_PORT_N_GRINDERS &
+			(RTE_SCHED_PORT_N_GRINDERS - 1));
+
+		/* User parameters */
+		s->n_pipes_per_subport_enabled =
+			params->n_pipes_per_subport_enabled;
+		memcpy(s->qsize, params->qsize, sizeof(params->qsize));
+		s->n_pipe_profiles = params->n_pipe_profiles;
+		s->n_max_pipe_profiles = params->n_max_pipe_profiles;
+
+#ifdef RTE_SCHED_RED
+		for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) {
+			uint32_t j;
+
+			for (j = 0; j < RTE_COLORS; j++) {
+			/* if min/max are both zero, then RED is disabled */
+				if ((params->red_params[i][j].min_th |
+				     params->red_params[i][j].max_th) == 0) {
+					continue;
+				}
+
+				if (rte_red_config_init(&s->red_config[i][j],
+				    params->red_params[i][j].wq_log2,
+				    params->red_params[i][j].min_th,
+				    params->red_params[i][j].max_th,
+				    params->red_params[i][j].maxp_inv) != 0) {
+					rte_sched_free_memory(port, n_subports);
+
+					RTE_LOG(NOTICE, SCHED,
+					"%s: RED configuration init fails\n",
+					__func__);
+					return -EINVAL;
+				}
+			}
+		}
+#endif
+
+		/* Scheduling loop detection */
+		s->pipe_loop = RTE_SCHED_PIPE_INVALID;
+		s->pipe_exhaustion = 0;
+
+		/* Grinders */
+		s->busy_grinders = 0;
+
+		/* Queue base calculation */
+		rte_sched_subport_config_qsize(s);
+
+		/* Large data structures */
+		s->pipe = (struct rte_sched_pipe *)
+			(s->memory + rte_sched_subport_get_array_base(params,
+			e_RTE_SCHED_SUBPORT_ARRAY_PIPE));
+		s->queue = (struct rte_sched_queue *)
+			(s->memory + rte_sched_subport_get_array_base(params,
+			e_RTE_SCHED_SUBPORT_ARRAY_QUEUE));
+		s->queue_extra = (struct rte_sched_queue_extra *)
+			(s->memory + rte_sched_subport_get_array_base(params,
+			e_RTE_SCHED_SUBPORT_ARRAY_QUEUE_EXTRA));
+		s->pipe_profiles = (struct rte_sched_pipe_profile *)
+			(s->memory + rte_sched_subport_get_array_base(params,
+			e_RTE_SCHED_SUBPORT_ARRAY_PIPE_PROFILES));
+		s->bmp_array =  s->memory +
+			rte_sched_subport_get_array_base(params,
+			e_RTE_SCHED_SUBPORT_ARRAY_BMP_ARRAY);
+		s->queue_array = (struct rte_mbuf **)
+			(s->memory + rte_sched_subport_get_array_base(params,
+			e_RTE_SCHED_SUBPORT_ARRAY_QUEUE_ARRAY));
+
+		/* Pipe profile table */
+		rte_sched_subport_config_pipe_profile_table(s, params,
+							port->rate);
+
+		/* Bitmap */
+		n_subport_pipe_queues = rte_sched_subport_pipe_queues(s);
+		bmp_mem_size = rte_bitmap_get_memory_footprint(
+							n_subport_pipe_queues);
+		s->bmp = rte_bitmap_init(n_subport_pipe_queues, s->bmp_array,
+					bmp_mem_size);
+		if (s->bmp == NULL) {
+			RTE_LOG(ERR, SCHED,
+				"%s: Subport bitmap init error\n", __func__);
+
+			rte_sched_free_memory(port, n_subports);
+			return -EINVAL;
+		}
+
+		for (i = 0; i < RTE_SCHED_PORT_N_GRINDERS; i++)
+			s->grinder_base_bmp_pos[i] = RTE_SCHED_PIPE_INVALID;
+
+#ifdef RTE_SCHED_SUBPORT_TC_OV
+		/* TC oversubscription */
+		s->tc_ov_wm_min = port->mtu;
+		s->tc_ov_wm = s->tc_ov_wm_max;
+		s->tc_ov_period_id = 0;
+		s->tc_ov = 0;
+		s->tc_ov_n = 0;
+		s->tc_ov_rate = 0;
+#endif
+	}
+
+	rte_sched_subport_profile_config(port, subport_id, subport_profile_id);
+
+	return 0;
+}
+
 int
 rte_sched_pipe_config(struct rte_sched_port *port,
 	uint32_t subport_id,
diff --git a/lib/librte_sched/rte_sched.h b/lib/librte_sched/rte_sched.h
index 3d823692c..3ecb0e9c3 100644
--- a/lib/librte_sched/rte_sched.h
+++ b/lib/librte_sched/rte_sched.h
@@ -376,6 +376,29 @@  rte_sched_subport_config(struct rte_sched_port *port,
 	uint32_t subport_id,
 	struct rte_sched_subport_params *params);
 
+/**
+ * Hierarchical scheduler subport configuration.
+ * Note that this function is also used at runtime
+ * to configure subport bandwidth profile.
+ * @param port
+ *   Handle to port scheduler instance
+ * @param subport_id
+ *   Subport ID
+ * @param params
+ *   Subport configuration parameters.
+ *   This parameter should be set to NULL, to
+ *   configure the subport bandwidth profile
+ *   at runtime.
+ * @param subport_profile_id
+ *   ID of profile configured for subport
+ * @return
+ *   0 upon success, error code otherwise
+ */
+int
+rte_dynamic_sched_subport_config(struct rte_sched_port *port,
+	uint32_t subport_id,
+	struct rte_sched_subport_params *params,
+	uint32_t subport_profile_id);
 /**
  * Hierarchical scheduler pipe configuration
  *