xref: /dpdk/examples/qos_sched/cfg_file.c (revision 92e9fe0d87b1e27306167b56a0c90c471966c630)
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 struct rte_sched_cman_params cman_params;
27 
parse_u64(const char * entry,uint64_t * val)28 int parse_u64(const char *entry, uint64_t *val)
29 {
30 	char *endptr;
31 	if (!entry || !val)
32 		return -EINVAL;
33 
34 	errno = 0;
35 
36 	*val = strtoull(entry, &endptr, 0);
37 	if (errno == EINVAL || errno == ERANGE || *endptr != '\0')
38 		return -EINVAL;
39 
40 	return 0;
41 }
42 
43 int
cfg_load_port(struct rte_cfgfile * cfg,struct rte_sched_port_params * port_params)44 cfg_load_port(struct rte_cfgfile *cfg, struct rte_sched_port_params *port_params)
45 {
46 	const char *entry;
47 
48 	if (!cfg || !port_params)
49 		return -1;
50 
51 	entry = rte_cfgfile_get_entry(cfg, "port", "frame overhead");
52 	if (entry)
53 		port_params->frame_overhead = (uint32_t)atoi(entry);
54 
55 	entry = rte_cfgfile_get_entry(cfg, "port", "number of subports per port");
56 	if (entry)
57 		port_params->n_subports_per_port = (uint32_t)atoi(entry);
58 
59 	return 0;
60 }
61 
62 int
cfg_load_pipe(struct rte_cfgfile * cfg,struct rte_sched_pipe_params * pipe_params)63 cfg_load_pipe(struct rte_cfgfile *cfg, struct rte_sched_pipe_params *pipe_params)
64 {
65 	int i, j, ret = 0;
66 	char *next;
67 	const char *entry;
68 	int profiles;
69 
70 	if (!cfg || !pipe_params)
71 		return -1;
72 
73 	profiles = rte_cfgfile_num_sections(cfg, "pipe profile", sizeof("pipe profile") - 1);
74 	subport_params[0].n_pipe_profiles = profiles;
75 
76 	for (j = 0; j < profiles; j++) {
77 		char pipe_name[32];
78 		snprintf(pipe_name, sizeof(pipe_name), "pipe profile %d", j);
79 
80 		entry = rte_cfgfile_get_entry(cfg, pipe_name, "tb rate");
81 		ret = parse_u64(entry, &pipe_params[j].tb_rate);
82 		if (ret)
83 			return ret;
84 
85 		entry = rte_cfgfile_get_entry(cfg, pipe_name, "tb size");
86 		ret = parse_u64(entry, &pipe_params[j].tb_size);
87 		if (ret)
88 			return ret;
89 
90 		entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc period");
91 		ret = parse_u64(entry, &pipe_params[j].tc_period);
92 		if (ret)
93 			return ret;
94 
95 		entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 0 rate");
96 		ret = parse_u64(entry, &pipe_params[j].tc_rate[0]);
97 		if (ret)
98 			return ret;
99 
100 		entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 1 rate");
101 		ret = parse_u64(entry, &pipe_params[j].tc_rate[1]);
102 		if (ret)
103 			return ret;
104 
105 		entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 2 rate");
106 		ret = parse_u64(entry, &pipe_params[j].tc_rate[2]);
107 		if (ret)
108 			return ret;
109 
110 		entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 3 rate");
111 		ret = parse_u64(entry, &pipe_params[j].tc_rate[3]);
112 		if (ret)
113 			return ret;
114 
115 		entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 4 rate");
116 		ret = parse_u64(entry, &pipe_params[j].tc_rate[4]);
117 		if (ret)
118 			return ret;
119 
120 		entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 5 rate");
121 		ret = parse_u64(entry, &pipe_params[j].tc_rate[5]);
122 		if (ret)
123 			return ret;
124 
125 		entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 6 rate");
126 		ret = parse_u64(entry, &pipe_params[j].tc_rate[6]);
127 		if (ret)
128 			return ret;
129 
130 		entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 7 rate");
131 		ret = parse_u64(entry, &pipe_params[j].tc_rate[7]);
132 		if (ret)
133 			return ret;
134 
135 		entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 8 rate");
136 		ret = parse_u64(entry, &pipe_params[j].tc_rate[8]);
137 		if (ret)
138 			return ret;
139 
140 		entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 9 rate");
141 		ret = parse_u64(entry, &pipe_params[j].tc_rate[9]);
142 		if (ret)
143 			return ret;
144 
145 		entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 10 rate");
146 		ret = parse_u64(entry, &pipe_params[j].tc_rate[10]);
147 		if (ret)
148 			return ret;
149 
150 		entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 11 rate");
151 		ret = parse_u64(entry, &pipe_params[j].tc_rate[11]);
152 		if (ret)
153 			return ret;
154 
155 		entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 12 rate");
156 		ret = parse_u64(entry, &pipe_params[j].tc_rate[12]);
157 		if (ret)
158 			return ret;
159 
160 		entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 12 oversubscription weight");
161 		if (entry)
162 			pipe_params[j].tc_ov_weight = (uint8_t)atoi(entry);
163 
164 		entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 12 wrr weights");
165 		if (entry) {
166 			for (i = 0; i < RTE_SCHED_BE_QUEUES_PER_PIPE; i++) {
167 				pipe_params[j].wrr_weights[i] =
168 					(uint8_t)strtol(entry, &next, 10);
169 				if (next == NULL)
170 					break;
171 				entry = next;
172 			}
173 		}
174 	}
175 	return 0;
176 }
177 
178 int
cfg_load_subport_profile(struct rte_cfgfile * cfg,struct rte_sched_subport_profile_params * subport_profile)179 cfg_load_subport_profile(struct rte_cfgfile *cfg,
180 	struct rte_sched_subport_profile_params *subport_profile)
181 {
182 	int i, ret = 0;
183 	const char *entry;
184 	int profiles;
185 
186 	if (!cfg || !subport_profile)
187 		return -1;
188 
189 	profiles = rte_cfgfile_num_sections(cfg, "subport profile",
190 					   sizeof("subport profile") - 1);
191 	port_params.n_subport_profiles = profiles;
192 
193 	for (i = 0; i < profiles; i++) {
194 		char sec_name[32];
195 		snprintf(sec_name, sizeof(sec_name), "subport profile %d", i);
196 
197 		entry = rte_cfgfile_get_entry(cfg, sec_name, "tb rate");
198 		ret = parse_u64(entry, &subport_profile[i].tb_rate);
199 		if (ret)
200 			return ret;
201 
202 		entry = rte_cfgfile_get_entry(cfg, sec_name, "tb size");
203 		ret = parse_u64(entry, &subport_profile[i].tb_size);
204 		if (ret)
205 			return ret;
206 
207 		entry = rte_cfgfile_get_entry(cfg, sec_name, "tc period");
208 		ret = parse_u64(entry, &subport_profile[i].tc_period);
209 		if (ret)
210 			return ret;
211 
212 		entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 0 rate");
213 		ret = parse_u64(entry, &subport_profile[i].tc_rate[0]);
214 		if (ret)
215 			return ret;
216 
217 		entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 1 rate");
218 		ret = parse_u64(entry, &subport_profile[i].tc_rate[1]);
219 		if (ret)
220 			return ret;
221 
222 		entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 2 rate");
223 		ret = parse_u64(entry, &subport_profile[i].tc_rate[2]);
224 		if (ret)
225 			return ret;
226 
227 		entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 3 rate");
228 		ret = parse_u64(entry, &subport_profile[i].tc_rate[3]);
229 		if (ret)
230 			return ret;
231 
232 		entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 4 rate");
233 		ret = parse_u64(entry, &subport_profile[i].tc_rate[4]);
234 		if (ret)
235 			return ret;
236 
237 		entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 5 rate");
238 		ret = parse_u64(entry, &subport_profile[i].tc_rate[5]);
239 		if (ret)
240 			return ret;
241 
242 		entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 6 rate");
243 		ret = parse_u64(entry, &subport_profile[i].tc_rate[6]);
244 		if (ret)
245 			return ret;
246 
247 		entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 7 rate");
248 		ret = parse_u64(entry, &subport_profile[i].tc_rate[7]);
249 		if (ret)
250 			return ret;
251 
252 		entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 8 rate");
253 		ret = parse_u64(entry, &subport_profile[i].tc_rate[8]);
254 		if (ret)
255 			return ret;
256 
257 		entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 9 rate");
258 		ret = parse_u64(entry, &subport_profile[i].tc_rate[9]);
259 		if (ret)
260 			return ret;
261 
262 		entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 10 rate");
263 		ret = parse_u64(entry, &subport_profile[i].tc_rate[10]);
264 		if (ret)
265 			return ret;
266 
267 		entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 11 rate");
268 		ret = parse_u64(entry, &subport_profile[i].tc_rate[11]);
269 		if (ret)
270 			return ret;
271 
272 		entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 12 rate");
273 		ret = parse_u64(entry, &subport_profile[i].tc_rate[12]);
274 		if (ret)
275 			return ret;
276 	}
277 
278 	return 0;
279 }
280 
281 int
cfg_load_subport(struct rte_cfgfile * cfg,struct rte_sched_subport_params * subport_params)282 cfg_load_subport(struct rte_cfgfile *cfg, struct rte_sched_subport_params *subport_params)
283 {
284 	bool cman_enabled = false;
285 	const char *entry;
286 	int i, j, k;
287 
288 	if (!cfg || !subport_params)
289 		return -1;
290 
291 	memset(app_pipe_to_profile, -1, sizeof(app_pipe_to_profile));
292 	memset(active_queues, 0, sizeof(active_queues));
293 	n_active_queues = 0;
294 
295 	if (rte_cfgfile_has_section(cfg, "red")) {
296 		cman_params.cman_mode = RTE_SCHED_CMAN_RED;
297 		cman_enabled = true;
298 
299 		for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) {
300 			char str[32];
301 
302 			/* Parse RED min thresholds */
303 			snprintf(str, sizeof(str), "tc %d red min", 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 					cman_params.red_params[i][j].min_th
310 						= (uint16_t)strtol(entry, &next, 10);
311 					if (next == NULL)
312 						break;
313 					entry = next;
314 				}
315 			}
316 
317 			/* Parse RED max thresholds */
318 			snprintf(str, sizeof(str), "tc %d red max", i);
319 			entry = rte_cfgfile_get_entry(cfg, "red", str);
320 			if (entry) {
321 				char *next;
322 				/* for each packet colour (green, yellow, red) */
323 				for (j = 0; j < RTE_COLORS; j++) {
324 					cman_params.red_params[i][j].max_th
325 						= (uint16_t)strtol(entry, &next, 10);
326 					if (next == NULL)
327 						break;
328 					entry = next;
329 				}
330 			}
331 
332 			/* Parse RED inverse mark probabilities */
333 			snprintf(str, sizeof(str), "tc %d red inv prob", i);
334 			entry = rte_cfgfile_get_entry(cfg, "red", str);
335 			if (entry) {
336 				char *next;
337 				/* for each packet colour (green, yellow, red) */
338 				for (j = 0; j < RTE_COLORS; j++) {
339 					cman_params.red_params[i][j].maxp_inv
340 						= (uint8_t)strtol(entry, &next, 10);
341 
342 					if (next == NULL)
343 						break;
344 					entry = next;
345 				}
346 			}
347 
348 			/* Parse RED EWMA filter weights */
349 			snprintf(str, sizeof(str), "tc %d red weight", i);
350 			entry = rte_cfgfile_get_entry(cfg, "red", str);
351 			if (entry) {
352 				char *next;
353 				/* for each packet colour (green, yellow, red) */
354 				for (j = 0; j < RTE_COLORS; j++) {
355 					cman_params.red_params[i][j].wq_log2
356 						= (uint8_t)strtol(entry, &next, 10);
357 					if (next == NULL)
358 						break;
359 					entry = next;
360 				}
361 			}
362 		}
363 	}
364 
365 	if (rte_cfgfile_has_section(cfg, "pie")) {
366 		cman_params.cman_mode = RTE_SCHED_CMAN_PIE;
367 		cman_enabled = true;
368 
369 		for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) {
370 			char str[32];
371 
372 			/* Parse Queue Delay Ref value */
373 			snprintf(str, sizeof(str), "tc %d qdelay ref", i);
374 			entry = rte_cfgfile_get_entry(cfg, "pie", str);
375 			if (entry)
376 				cman_params.pie_params[i].qdelay_ref =
377 					(uint16_t) atoi(entry);
378 
379 			/* Parse Max Burst value */
380 			snprintf(str, sizeof(str), "tc %d max burst", i);
381 			entry = rte_cfgfile_get_entry(cfg, "pie", str);
382 			if (entry)
383 				cman_params.pie_params[i].max_burst =
384 					(uint16_t) atoi(entry);
385 
386 			/* Parse Update Interval Value */
387 			snprintf(str, sizeof(str), "tc %d update interval", i);
388 			entry = rte_cfgfile_get_entry(cfg, "pie", str);
389 			if (entry)
390 				cman_params.pie_params[i].dp_update_interval =
391 					(uint16_t) atoi(entry);
392 
393 			/* Parse Tailq Threshold Value */
394 			snprintf(str, sizeof(str), "tc %d tailq th", i);
395 			entry = rte_cfgfile_get_entry(cfg, "pie", str);
396 			if (entry)
397 				cman_params.pie_params[i].tailq_th =
398 					(uint16_t) atoi(entry);
399 
400 		}
401 	}
402 
403 	for (i = 0; i < MAX_SCHED_SUBPORTS; i++) {
404 		char sec_name[CFG_NAME_LEN];
405 		snprintf(sec_name, sizeof(sec_name), "subport %d", i);
406 
407 		if (rte_cfgfile_has_section(cfg, sec_name)) {
408 			entry = rte_cfgfile_get_entry(cfg, sec_name,
409 				"number of pipes per subport");
410 			if (entry)
411 				subport_params[i].n_pipes_per_subport_enabled =
412 					(uint32_t)atoi(entry);
413 
414 			entry = rte_cfgfile_get_entry(cfg, sec_name, "queue sizes");
415 			if (entry) {
416 				char *next;
417 
418 				for (j = 0; j < RTE_SCHED_TRAFFIC_CLASS_BE; j++) {
419 					subport_params[i].qsize[j] =
420 						(uint16_t)strtol(entry, &next, 10);
421 					if (subport_params[i].qsize[j] != 0) {
422 						active_queues[n_active_queues] = j;
423 						n_active_queues++;
424 					}
425 					if (next == NULL)
426 						break;
427 					entry = next;
428 				}
429 
430 				subport_params[i].qsize[RTE_SCHED_TRAFFIC_CLASS_BE] =
431 					(uint16_t)strtol(entry, &next, 10);
432 
433 				for (j = 0; j < RTE_SCHED_BE_QUEUES_PER_PIPE; j++) {
434 					active_queues[n_active_queues] =
435 						RTE_SCHED_TRAFFIC_CLASS_BE + j;
436 					n_active_queues++;
437 				}
438 			}
439 
440 			int n_entries = rte_cfgfile_section_num_entries(cfg, sec_name);
441 			struct rte_cfgfile_entry entries[n_entries];
442 
443 			rte_cfgfile_section_entries(cfg, sec_name, entries, n_entries);
444 
445 			for (j = 0; j < n_entries; j++) {
446 				if (strncmp("pipe", entries[j].name, sizeof("pipe") - 1) == 0) {
447 					int profile;
448 					char *tokens[2] = {NULL, NULL};
449 					int n_tokens;
450 					int begin, end;
451 
452 					profile = atoi(entries[j].value);
453 					n_tokens = rte_strsplit(&entries[j].name[sizeof("pipe")],
454 							strnlen(entries[j].name, CFG_NAME_LEN), tokens, 2, '-');
455 
456 					begin =  atoi(tokens[0]);
457 					if (n_tokens == 2)
458 						end = atoi(tokens[1]);
459 					else
460 						end = begin;
461 
462 					if (end >= MAX_SCHED_PIPES || begin > end)
463 						return -1;
464 
465 					for (k = begin; k <= end; k++) {
466 						char profile_name[CFG_NAME_LEN];
467 
468 						snprintf(profile_name, sizeof(profile_name),
469 								"pipe profile %d", profile);
470 						if (rte_cfgfile_has_section(cfg, profile_name))
471 							app_pipe_to_profile[i][k] = profile;
472 						else
473 							rte_exit(EXIT_FAILURE, "Wrong pipe profile %s\n",
474 									entries[j].value);
475 
476 					}
477 				}
478 			}
479 			if (cman_enabled)
480 				subport_params[i].cman_params = &cman_params;
481 		}
482 	}
483 
484 	return 0;
485 }
486