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