xref: /dpdk/examples/qos_sched/cfg_file.c (revision daa02b5cddbb8e11b31d41e2bf7bb1ae64dcae2f)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2014 Intel Corporation
3  */
4 
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <ctype.h>
9 #include <rte_string_fns.h>
10 #include <rte_sched.h>
11 
12 #include "cfg_file.h"
13 #include "main.h"
14 
15 
16 /** when we resize a file structure, how many extra entries
17  * for new sections do we add in */
18 #define CFG_ALLOC_SECTION_BATCH 8
19 /** when we resize a section structure, how many extra entries
20  * for new entries do we add in */
21 #define CFG_ALLOC_ENTRY_BATCH 16
22 
23 uint32_t active_queues[RTE_SCHED_QUEUES_PER_PIPE];
24 uint32_t n_active_queues;
25 
26 int
27 cfg_load_port(struct rte_cfgfile *cfg, struct rte_sched_port_params *port_params)
28 {
29 	const char *entry;
30 
31 	if (!cfg || !port_params)
32 		return -1;
33 
34 	entry = rte_cfgfile_get_entry(cfg, "port", "frame overhead");
35 	if (entry)
36 		port_params->frame_overhead = (uint32_t)atoi(entry);
37 
38 	entry = rte_cfgfile_get_entry(cfg, "port", "number of subports per port");
39 	if (entry)
40 		port_params->n_subports_per_port = (uint32_t)atoi(entry);
41 
42 	return 0;
43 }
44 
45 int
46 cfg_load_pipe(struct rte_cfgfile *cfg, struct rte_sched_pipe_params *pipe_params)
47 {
48 	int i, j;
49 	char *next;
50 	const char *entry;
51 	int profiles;
52 
53 	if (!cfg || !pipe_params)
54 		return -1;
55 
56 	profiles = rte_cfgfile_num_sections(cfg, "pipe profile", sizeof("pipe profile") - 1);
57 	subport_params[0].n_pipe_profiles = profiles;
58 
59 	for (j = 0; j < profiles; j++) {
60 		char pipe_name[32];
61 		snprintf(pipe_name, sizeof(pipe_name), "pipe profile %d", j);
62 
63 		entry = rte_cfgfile_get_entry(cfg, pipe_name, "tb rate");
64 		if (entry)
65 			pipe_params[j].tb_rate = (uint64_t)atoi(entry);
66 
67 		entry = rte_cfgfile_get_entry(cfg, pipe_name, "tb size");
68 		if (entry)
69 			pipe_params[j].tb_size = (uint64_t)atoi(entry);
70 
71 		entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc period");
72 		if (entry)
73 			pipe_params[j].tc_period = (uint64_t)atoi(entry);
74 
75 		entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 0 rate");
76 		if (entry)
77 			pipe_params[j].tc_rate[0] = (uint64_t)atoi(entry);
78 
79 		entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 1 rate");
80 		if (entry)
81 			pipe_params[j].tc_rate[1] = (uint64_t)atoi(entry);
82 
83 		entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 2 rate");
84 		if (entry)
85 			pipe_params[j].tc_rate[2] = (uint64_t)atoi(entry);
86 
87 		entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 3 rate");
88 		if (entry)
89 			pipe_params[j].tc_rate[3] = (uint64_t)atoi(entry);
90 
91 		entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 4 rate");
92 		if (entry)
93 			pipe_params[j].tc_rate[4] = (uint64_t)atoi(entry);
94 
95 		entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 5 rate");
96 		if (entry)
97 			pipe_params[j].tc_rate[5] = (uint64_t)atoi(entry);
98 
99 		entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 6 rate");
100 		if (entry)
101 			pipe_params[j].tc_rate[6] = (uint64_t)atoi(entry);
102 
103 		entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 7 rate");
104 		if (entry)
105 			pipe_params[j].tc_rate[7] = (uint64_t)atoi(entry);
106 
107 		entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 8 rate");
108 		if (entry)
109 			pipe_params[j].tc_rate[8] = (uint64_t)atoi(entry);
110 
111 		entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 9 rate");
112 		if (entry)
113 			pipe_params[j].tc_rate[9] = (uint64_t)atoi(entry);
114 
115 		entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 10 rate");
116 		if (entry)
117 			pipe_params[j].tc_rate[10] = (uint64_t)atoi(entry);
118 
119 		entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 11 rate");
120 		if (entry)
121 			pipe_params[j].tc_rate[11] = (uint64_t)atoi(entry);
122 
123 		entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 12 rate");
124 		if (entry)
125 			pipe_params[j].tc_rate[12] = (uint64_t)atoi(entry);
126 
127 		entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 12 oversubscription weight");
128 		if (entry)
129 			pipe_params[j].tc_ov_weight = (uint8_t)atoi(entry);
130 
131 		entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 12 wrr weights");
132 		if (entry) {
133 			for (i = 0; i < RTE_SCHED_BE_QUEUES_PER_PIPE; i++) {
134 				pipe_params[j].wrr_weights[i] =
135 					(uint8_t)strtol(entry, &next, 10);
136 				if (next == NULL)
137 					break;
138 				entry = next;
139 			}
140 		}
141 	}
142 	return 0;
143 }
144 
145 int
146 cfg_load_subport_profile(struct rte_cfgfile *cfg,
147 	struct rte_sched_subport_profile_params *subport_profile)
148 {
149 	int i;
150 	const char *entry;
151 	int profiles;
152 
153 	if (!cfg || !subport_profile)
154 		return -1;
155 
156 	profiles = rte_cfgfile_num_sections(cfg, "subport profile",
157 					   sizeof("subport profile") - 1);
158 	subport_params[0].n_pipe_profiles = profiles;
159 
160 	for (i = 0; i < profiles; i++) {
161 		char sec_name[32];
162 		snprintf(sec_name, sizeof(sec_name), "subport profile %d", i);
163 
164 		entry = rte_cfgfile_get_entry(cfg, sec_name, "tb rate");
165 		if (entry)
166 			subport_profile[i].tb_rate = (uint64_t)atoi(entry);
167 
168 		entry = rte_cfgfile_get_entry(cfg, sec_name, "tb size");
169 		if (entry)
170 			subport_profile[i].tb_size = (uint64_t)atoi(entry);
171 
172 		entry = rte_cfgfile_get_entry(cfg, sec_name, "tc period");
173 		if (entry)
174 			subport_profile[i].tc_period = (uint64_t)atoi(entry);
175 
176 		entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 0 rate");
177 		if (entry)
178 			subport_profile[i].tc_rate[0] = (uint64_t)atoi(entry);
179 
180 		entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 1 rate");
181 		if (entry)
182 			subport_profile[i].tc_rate[1] = (uint64_t)atoi(entry);
183 
184 		entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 2 rate");
185 		if (entry)
186 			subport_profile[i].tc_rate[2] = (uint64_t)atoi(entry);
187 
188 		entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 3 rate");
189 		if (entry)
190 			subport_profile[i].tc_rate[3] = (uint64_t)atoi(entry);
191 
192 		entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 4 rate");
193 		if (entry)
194 			subport_profile[i].tc_rate[4] = (uint64_t)atoi(entry);
195 
196 		entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 5 rate");
197 		if (entry)
198 			subport_profile[i].tc_rate[5] = (uint64_t)atoi(entry);
199 
200 		entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 6 rate");
201 		if (entry)
202 			subport_profile[i].tc_rate[6] = (uint64_t)atoi(entry);
203 
204 		entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 7 rate");
205 		if (entry)
206 			subport_profile[i].tc_rate[7] = (uint64_t)atoi(entry);
207 
208 		entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 8 rate");
209 		if (entry)
210 			subport_profile[i].tc_rate[8] = (uint64_t)atoi(entry);
211 
212 		entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 9 rate");
213 		if (entry)
214 			subport_profile[i].tc_rate[9] = (uint64_t)atoi(entry);
215 
216 		entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 10 rate");
217 		if (entry)
218 			subport_profile[i].tc_rate[10] = (uint64_t)atoi(entry);
219 
220 		entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 11 rate");
221 		if (entry)
222 			subport_profile[i].tc_rate[11] = (uint64_t)atoi(entry);
223 
224 		entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 12 rate");
225 		if (entry)
226 			subport_profile[i].tc_rate[12] = (uint64_t)atoi(entry);
227 	}
228 
229 	return 0;
230 }
231 
232 int
233 cfg_load_subport(struct rte_cfgfile *cfg, struct rte_sched_subport_params *subport_params)
234 {
235 	const char *entry;
236 	int i, j, k;
237 
238 	if (!cfg || !subport_params)
239 		return -1;
240 
241 	memset(app_pipe_to_profile, -1, sizeof(app_pipe_to_profile));
242 	memset(active_queues, 0, sizeof(active_queues));
243 	n_active_queues = 0;
244 
245 #ifdef RTE_SCHED_RED
246 	char sec_name[CFG_NAME_LEN];
247 	struct rte_red_params red_params[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE][RTE_COLORS];
248 
249 	snprintf(sec_name, sizeof(sec_name), "red");
250 
251 	if (rte_cfgfile_has_section(cfg, sec_name)) {
252 
253 		for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) {
254 			char str[32];
255 
256 			/* Parse WRED min thresholds */
257 			snprintf(str, sizeof(str), "tc %d wred min", i);
258 			entry = rte_cfgfile_get_entry(cfg, sec_name, str);
259 			if (entry) {
260 				char *next;
261 				/* for each packet colour (green, yellow, red) */
262 				for (j = 0; j < RTE_COLORS; j++) {
263 					red_params[i][j].min_th
264 						= (uint16_t)strtol(entry, &next, 10);
265 					if (next == NULL)
266 						break;
267 					entry = next;
268 				}
269 			}
270 
271 			/* Parse WRED max thresholds */
272 			snprintf(str, sizeof(str), "tc %d wred max", i);
273 			entry = rte_cfgfile_get_entry(cfg, "red", str);
274 			if (entry) {
275 				char *next;
276 				/* for each packet colour (green, yellow, red) */
277 				for (j = 0; j < RTE_COLORS; j++) {
278 					red_params[i][j].max_th
279 						= (uint16_t)strtol(entry, &next, 10);
280 					if (next == NULL)
281 						break;
282 					entry = next;
283 				}
284 			}
285 
286 			/* Parse WRED inverse mark probabilities */
287 			snprintf(str, sizeof(str), "tc %d wred inv prob", i);
288 			entry = rte_cfgfile_get_entry(cfg, "red", str);
289 			if (entry) {
290 				char *next;
291 				/* for each packet colour (green, yellow, red) */
292 				for (j = 0; j < RTE_COLORS; j++) {
293 					red_params[i][j].maxp_inv
294 						= (uint8_t)strtol(entry, &next, 10);
295 
296 					if (next == NULL)
297 						break;
298 					entry = next;
299 				}
300 			}
301 
302 			/* Parse WRED EWMA filter weights */
303 			snprintf(str, sizeof(str), "tc %d wred weight", i);
304 			entry = rte_cfgfile_get_entry(cfg, "red", str);
305 			if (entry) {
306 				char *next;
307 				/* for each packet colour (green, yellow, red) */
308 				for (j = 0; j < RTE_COLORS; j++) {
309 					red_params[i][j].wq_log2
310 						= (uint8_t)strtol(entry, &next, 10);
311 					if (next == NULL)
312 						break;
313 					entry = next;
314 				}
315 			}
316 		}
317 	}
318 #endif /* RTE_SCHED_RED */
319 
320 	for (i = 0; i < MAX_SCHED_SUBPORTS; i++) {
321 		char sec_name[CFG_NAME_LEN];
322 		snprintf(sec_name, sizeof(sec_name), "subport %d", i);
323 
324 		if (rte_cfgfile_has_section(cfg, sec_name)) {
325 			entry = rte_cfgfile_get_entry(cfg, sec_name,
326 				"number of pipes per subport");
327 			if (entry)
328 				subport_params[i].n_pipes_per_subport_enabled =
329 					(uint32_t)atoi(entry);
330 
331 			entry = rte_cfgfile_get_entry(cfg, sec_name, "queue sizes");
332 			if (entry) {
333 				char *next;
334 
335 				for (j = 0; j < RTE_SCHED_TRAFFIC_CLASS_BE; j++) {
336 					subport_params[i].qsize[j] =
337 						(uint16_t)strtol(entry, &next, 10);
338 					if (subport_params[i].qsize[j] != 0) {
339 						active_queues[n_active_queues] = j;
340 						n_active_queues++;
341 					}
342 					if (next == NULL)
343 						break;
344 					entry = next;
345 				}
346 
347 				subport_params[i].qsize[RTE_SCHED_TRAFFIC_CLASS_BE] =
348 					(uint16_t)strtol(entry, &next, 10);
349 
350 				for (j = 0; j < RTE_SCHED_BE_QUEUES_PER_PIPE; j++) {
351 					active_queues[n_active_queues] =
352 						RTE_SCHED_TRAFFIC_CLASS_BE + j;
353 					n_active_queues++;
354 				}
355 			}
356 
357 			int n_entries = rte_cfgfile_section_num_entries(cfg, sec_name);
358 			struct rte_cfgfile_entry entries[n_entries];
359 
360 			rte_cfgfile_section_entries(cfg, sec_name, entries, n_entries);
361 
362 			for (j = 0; j < n_entries; j++) {
363 				if (strncmp("pipe", entries[j].name, sizeof("pipe") - 1) == 0) {
364 					int profile;
365 					char *tokens[2] = {NULL, NULL};
366 					int n_tokens;
367 					int begin, end;
368 
369 					profile = atoi(entries[j].value);
370 					n_tokens = rte_strsplit(&entries[j].name[sizeof("pipe")],
371 							strnlen(entries[j].name, CFG_NAME_LEN), tokens, 2, '-');
372 
373 					begin =  atoi(tokens[0]);
374 					if (n_tokens == 2)
375 						end = atoi(tokens[1]);
376 					else
377 						end = begin;
378 
379 					if (end >= MAX_SCHED_PIPES || begin > end)
380 						return -1;
381 
382 					for (k = begin; k <= end; k++) {
383 						char profile_name[CFG_NAME_LEN];
384 
385 						snprintf(profile_name, sizeof(profile_name),
386 								"pipe profile %d", profile);
387 						if (rte_cfgfile_has_section(cfg, profile_name))
388 							app_pipe_to_profile[i][k] = profile;
389 						else
390 							rte_exit(EXIT_FAILURE, "Wrong pipe profile %s\n",
391 									entries[j].value);
392 
393 					}
394 				}
395 			}
396 #ifdef RTE_SCHED_RED
397 			for (j = 0; j < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; j++) {
398 				for (k = 0; k < RTE_COLORS; k++) {
399 					subport_params[i].red_params[j][k].min_th =
400 						red_params[j][k].min_th;
401 					subport_params[i].red_params[j][k].max_th =
402 						red_params[j][k].max_th;
403 					subport_params[i].red_params[j][k].maxp_inv =
404 						red_params[j][k].maxp_inv;
405 					subport_params[i].red_params[j][k].wq_log2 =
406 						red_params[j][k].wq_log2;
407 				}
408 			}
409 #endif
410 		}
411 	}
412 
413 	return 0;
414 }
415