xref: /dpdk/examples/qos_sched/cfg_file.c (revision b53d106d34b5c638f5a2cbdfee0da5bd42d4383f)
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 #ifdef RTE_SCHED_CMAN
233 void set_subport_cman_params(struct rte_sched_subport_params *subport_p,
234 					struct rte_sched_cman_params cman_p)
235 {
236 	int j, k;
237 	subport_p->cman_params->cman_mode = cman_p.cman_mode;
238 
239 	for (j = 0; j < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; j++) {
240 		if (subport_p->cman_params->cman_mode ==
241 					RTE_SCHED_CMAN_RED) {
242 			for (k = 0; k < RTE_COLORS; k++) {
243 				subport_p->cman_params->red_params[j][k].min_th =
244 					cman_p.red_params[j][k].min_th;
245 				subport_p->cman_params->red_params[j][k].max_th =
246 					cman_p.red_params[j][k].max_th;
247 				subport_p->cman_params->red_params[j][k].maxp_inv =
248 					cman_p.red_params[j][k].maxp_inv;
249 				subport_p->cman_params->red_params[j][k].wq_log2 =
250 					cman_p.red_params[j][k].wq_log2;
251 			}
252 		} else {
253 			subport_p->cman_params->pie_params[j].qdelay_ref =
254 				cman_p.pie_params[j].qdelay_ref;
255 			subport_p->cman_params->pie_params[j].dp_update_interval =
256 				cman_p.pie_params[j].dp_update_interval;
257 			subport_p->cman_params->pie_params[j].max_burst =
258 				cman_p.pie_params[j].max_burst;
259 			subport_p->cman_params->pie_params[j].tailq_th =
260 				cman_p.pie_params[j].tailq_th;
261 		}
262 	}
263 }
264 #endif
265 
266 int
267 cfg_load_subport(struct rte_cfgfile *cfg, struct rte_sched_subport_params *subport_params)
268 {
269 	const char *entry;
270 	int i, j, k;
271 
272 	if (!cfg || !subport_params)
273 		return -1;
274 
275 	memset(app_pipe_to_profile, -1, sizeof(app_pipe_to_profile));
276 	memset(active_queues, 0, sizeof(active_queues));
277 	n_active_queues = 0;
278 
279 #ifdef RTE_SCHED_CMAN
280 	struct rte_sched_cman_params cman_params = {
281 		.cman_mode = RTE_SCHED_CMAN_RED,
282 		.red_params = { },
283 	};
284 
285 	if (rte_cfgfile_has_section(cfg, "red")) {
286 		cman_params.cman_mode = RTE_SCHED_CMAN_RED;
287 
288 		for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) {
289 			char str[32];
290 
291 			/* Parse RED min thresholds */
292 			snprintf(str, sizeof(str), "tc %d red min", i);
293 			entry = rte_cfgfile_get_entry(cfg, "red", str);
294 			if (entry) {
295 				char *next;
296 				/* for each packet colour (green, yellow, red) */
297 				for (j = 0; j < RTE_COLORS; j++) {
298 					cman_params.red_params[i][j].min_th
299 						= (uint16_t)strtol(entry, &next, 10);
300 					if (next == NULL)
301 						break;
302 					entry = next;
303 				}
304 			}
305 
306 			/* Parse RED max thresholds */
307 			snprintf(str, sizeof(str), "tc %d red max", i);
308 			entry = rte_cfgfile_get_entry(cfg, "red", str);
309 			if (entry) {
310 				char *next;
311 				/* for each packet colour (green, yellow, red) */
312 				for (j = 0; j < RTE_COLORS; j++) {
313 					cman_params.red_params[i][j].max_th
314 						= (uint16_t)strtol(entry, &next, 10);
315 					if (next == NULL)
316 						break;
317 					entry = next;
318 				}
319 			}
320 
321 			/* Parse RED inverse mark probabilities */
322 			snprintf(str, sizeof(str), "tc %d red inv prob", i);
323 			entry = rte_cfgfile_get_entry(cfg, "red", str);
324 			if (entry) {
325 				char *next;
326 				/* for each packet colour (green, yellow, red) */
327 				for (j = 0; j < RTE_COLORS; j++) {
328 					cman_params.red_params[i][j].maxp_inv
329 						= (uint8_t)strtol(entry, &next, 10);
330 
331 					if (next == NULL)
332 						break;
333 					entry = next;
334 				}
335 			}
336 
337 			/* Parse RED EWMA filter weights */
338 			snprintf(str, sizeof(str), "tc %d red weight", i);
339 			entry = rte_cfgfile_get_entry(cfg, "red", str);
340 			if (entry) {
341 				char *next;
342 				/* for each packet colour (green, yellow, red) */
343 				for (j = 0; j < RTE_COLORS; j++) {
344 					cman_params.red_params[i][j].wq_log2
345 						= (uint8_t)strtol(entry, &next, 10);
346 					if (next == NULL)
347 						break;
348 					entry = next;
349 				}
350 			}
351 		}
352 	}
353 
354 	if (rte_cfgfile_has_section(cfg, "pie")) {
355 		cman_params.cman_mode = RTE_SCHED_CMAN_PIE;
356 
357 		for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) {
358 			char str[32];
359 
360 			/* Parse Queue Delay Ref value */
361 			snprintf(str, sizeof(str), "tc %d qdelay ref", i);
362 			entry = rte_cfgfile_get_entry(cfg, "pie", str);
363 			if (entry)
364 				cman_params.pie_params[i].qdelay_ref =
365 					(uint16_t) atoi(entry);
366 
367 			/* Parse Max Burst value */
368 			snprintf(str, sizeof(str), "tc %d max burst", i);
369 			entry = rte_cfgfile_get_entry(cfg, "pie", str);
370 			if (entry)
371 				cman_params.pie_params[i].max_burst =
372 					(uint16_t) atoi(entry);
373 
374 			/* Parse Update Interval Value */
375 			snprintf(str, sizeof(str), "tc %d update interval", i);
376 			entry = rte_cfgfile_get_entry(cfg, "pie", str);
377 			if (entry)
378 				cman_params.pie_params[i].dp_update_interval =
379 					(uint16_t) atoi(entry);
380 
381 			/* Parse Tailq Threshold Value */
382 			snprintf(str, sizeof(str), "tc %d tailq th", i);
383 			entry = rte_cfgfile_get_entry(cfg, "pie", str);
384 			if (entry)
385 				cman_params.pie_params[i].tailq_th =
386 					(uint16_t) atoi(entry);
387 
388 		}
389 	}
390 #endif /* RTE_SCHED_CMAN */
391 
392 	for (i = 0; i < MAX_SCHED_SUBPORTS; i++) {
393 		char sec_name[CFG_NAME_LEN];
394 		snprintf(sec_name, sizeof(sec_name), "subport %d", i);
395 
396 		if (rte_cfgfile_has_section(cfg, sec_name)) {
397 			entry = rte_cfgfile_get_entry(cfg, sec_name,
398 				"number of pipes per subport");
399 			if (entry)
400 				subport_params[i].n_pipes_per_subport_enabled =
401 					(uint32_t)atoi(entry);
402 
403 			entry = rte_cfgfile_get_entry(cfg, sec_name, "queue sizes");
404 			if (entry) {
405 				char *next;
406 
407 				for (j = 0; j < RTE_SCHED_TRAFFIC_CLASS_BE; j++) {
408 					subport_params[i].qsize[j] =
409 						(uint16_t)strtol(entry, &next, 10);
410 					if (subport_params[i].qsize[j] != 0) {
411 						active_queues[n_active_queues] = j;
412 						n_active_queues++;
413 					}
414 					if (next == NULL)
415 						break;
416 					entry = next;
417 				}
418 
419 				subport_params[i].qsize[RTE_SCHED_TRAFFIC_CLASS_BE] =
420 					(uint16_t)strtol(entry, &next, 10);
421 
422 				for (j = 0; j < RTE_SCHED_BE_QUEUES_PER_PIPE; j++) {
423 					active_queues[n_active_queues] =
424 						RTE_SCHED_TRAFFIC_CLASS_BE + j;
425 					n_active_queues++;
426 				}
427 			}
428 
429 			int n_entries = rte_cfgfile_section_num_entries(cfg, sec_name);
430 			struct rte_cfgfile_entry entries[n_entries];
431 
432 			rte_cfgfile_section_entries(cfg, sec_name, entries, n_entries);
433 
434 			for (j = 0; j < n_entries; j++) {
435 				if (strncmp("pipe", entries[j].name, sizeof("pipe") - 1) == 0) {
436 					int profile;
437 					char *tokens[2] = {NULL, NULL};
438 					int n_tokens;
439 					int begin, end;
440 
441 					profile = atoi(entries[j].value);
442 					n_tokens = rte_strsplit(&entries[j].name[sizeof("pipe")],
443 							strnlen(entries[j].name, CFG_NAME_LEN), tokens, 2, '-');
444 
445 					begin =  atoi(tokens[0]);
446 					if (n_tokens == 2)
447 						end = atoi(tokens[1]);
448 					else
449 						end = begin;
450 
451 					if (end >= MAX_SCHED_PIPES || begin > end)
452 						return -1;
453 
454 					for (k = begin; k <= end; k++) {
455 						char profile_name[CFG_NAME_LEN];
456 
457 						snprintf(profile_name, sizeof(profile_name),
458 								"pipe profile %d", profile);
459 						if (rte_cfgfile_has_section(cfg, profile_name))
460 							app_pipe_to_profile[i][k] = profile;
461 						else
462 							rte_exit(EXIT_FAILURE, "Wrong pipe profile %s\n",
463 									entries[j].value);
464 
465 					}
466 				}
467 			}
468 #ifdef RTE_SCHED_CMAN
469 			set_subport_cman_params(subport_params+i, cman_params);
470 #endif
471 		}
472 	}
473 
474 	return 0;
475 }
476