examples/qos_sched: support PIE congestion management
[dpdk.git] / examples / qos_sched / cfg_file.c
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 }