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