net/af_xdp: fix zero-copy Tx queue drain
[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 int
233 cfg_load_subport(struct rte_cfgfile *cfg, struct rte_sched_subport_params *subport_params)
234 {
235         const char *entry;
236         int i, j, k;
237
238         if (!cfg || !subport_params)
239                 return -1;
240
241         memset(app_pipe_to_profile, -1, sizeof(app_pipe_to_profile));
242         memset(active_queues, 0, sizeof(active_queues));
243         n_active_queues = 0;
244
245 #ifdef RTE_SCHED_RED
246         char sec_name[CFG_NAME_LEN];
247         struct rte_red_params red_params[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE][RTE_COLORS];
248
249         snprintf(sec_name, sizeof(sec_name), "red");
250
251         if (rte_cfgfile_has_section(cfg, sec_name)) {
252
253                 for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) {
254                         char str[32];
255
256                         /* Parse WRED min thresholds */
257                         snprintf(str, sizeof(str), "tc %d wred min", i);
258                         entry = rte_cfgfile_get_entry(cfg, sec_name, str);
259                         if (entry) {
260                                 char *next;
261                                 /* for each packet colour (green, yellow, red) */
262                                 for (j = 0; j < RTE_COLORS; j++) {
263                                         red_params[i][j].min_th
264                                                 = (uint16_t)strtol(entry, &next, 10);
265                                         if (next == NULL)
266                                                 break;
267                                         entry = next;
268                                 }
269                         }
270
271                         /* Parse WRED max thresholds */
272                         snprintf(str, sizeof(str), "tc %d wred max", i);
273                         entry = rte_cfgfile_get_entry(cfg, "red", str);
274                         if (entry) {
275                                 char *next;
276                                 /* for each packet colour (green, yellow, red) */
277                                 for (j = 0; j < RTE_COLORS; j++) {
278                                         red_params[i][j].max_th
279                                                 = (uint16_t)strtol(entry, &next, 10);
280                                         if (next == NULL)
281                                                 break;
282                                         entry = next;
283                                 }
284                         }
285
286                         /* Parse WRED inverse mark probabilities */
287                         snprintf(str, sizeof(str), "tc %d wred inv prob", i);
288                         entry = rte_cfgfile_get_entry(cfg, "red", str);
289                         if (entry) {
290                                 char *next;
291                                 /* for each packet colour (green, yellow, red) */
292                                 for (j = 0; j < RTE_COLORS; j++) {
293                                         red_params[i][j].maxp_inv
294                                                 = (uint8_t)strtol(entry, &next, 10);
295
296                                         if (next == NULL)
297                                                 break;
298                                         entry = next;
299                                 }
300                         }
301
302                         /* Parse WRED EWMA filter weights */
303                         snprintf(str, sizeof(str), "tc %d wred weight", 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                                         red_params[i][j].wq_log2
310                                                 = (uint8_t)strtol(entry, &next, 10);
311                                         if (next == NULL)
312                                                 break;
313                                         entry = next;
314                                 }
315                         }
316                 }
317         }
318 #endif /* RTE_SCHED_RED */
319
320         for (i = 0; i < MAX_SCHED_SUBPORTS; i++) {
321                 char sec_name[CFG_NAME_LEN];
322                 snprintf(sec_name, sizeof(sec_name), "subport %d", i);
323
324                 if (rte_cfgfile_has_section(cfg, sec_name)) {
325                         entry = rte_cfgfile_get_entry(cfg, sec_name,
326                                 "number of pipes per subport");
327                         if (entry)
328                                 subport_params[i].n_pipes_per_subport_enabled =
329                                         (uint32_t)atoi(entry);
330
331                         entry = rte_cfgfile_get_entry(cfg, sec_name, "queue sizes");
332                         if (entry) {
333                                 char *next;
334
335                                 for (j = 0; j < RTE_SCHED_TRAFFIC_CLASS_BE; j++) {
336                                         subport_params[i].qsize[j] =
337                                                 (uint16_t)strtol(entry, &next, 10);
338                                         if (subport_params[i].qsize[j] != 0) {
339                                                 active_queues[n_active_queues] = j;
340                                                 n_active_queues++;
341                                         }
342                                         if (next == NULL)
343                                                 break;
344                                         entry = next;
345                                 }
346
347                                 subport_params[i].qsize[RTE_SCHED_TRAFFIC_CLASS_BE] =
348                                         (uint16_t)strtol(entry, &next, 10);
349
350                                 for (j = 0; j < RTE_SCHED_BE_QUEUES_PER_PIPE; j++) {
351                                         active_queues[n_active_queues] =
352                                                 RTE_SCHED_TRAFFIC_CLASS_BE + j;
353                                         n_active_queues++;
354                                 }
355                         }
356
357                         int n_entries = rte_cfgfile_section_num_entries(cfg, sec_name);
358                         struct rte_cfgfile_entry entries[n_entries];
359
360                         rte_cfgfile_section_entries(cfg, sec_name, entries, n_entries);
361
362                         for (j = 0; j < n_entries; j++) {
363                                 if (strncmp("pipe", entries[j].name, sizeof("pipe") - 1) == 0) {
364                                         int profile;
365                                         char *tokens[2] = {NULL, NULL};
366                                         int n_tokens;
367                                         int begin, end;
368
369                                         profile = atoi(entries[j].value);
370                                         n_tokens = rte_strsplit(&entries[j].name[sizeof("pipe")],
371                                                         strnlen(entries[j].name, CFG_NAME_LEN), tokens, 2, '-');
372
373                                         begin =  atoi(tokens[0]);
374                                         if (n_tokens == 2)
375                                                 end = atoi(tokens[1]);
376                                         else
377                                                 end = begin;
378
379                                         if (end >= MAX_SCHED_PIPES || begin > end)
380                                                 return -1;
381
382                                         for (k = begin; k <= end; k++) {
383                                                 char profile_name[CFG_NAME_LEN];
384
385                                                 snprintf(profile_name, sizeof(profile_name),
386                                                                 "pipe profile %d", profile);
387                                                 if (rte_cfgfile_has_section(cfg, profile_name))
388                                                         app_pipe_to_profile[i][k] = profile;
389                                                 else
390                                                         rte_exit(EXIT_FAILURE, "Wrong pipe profile %s\n",
391                                                                         entries[j].value);
392
393                                         }
394                                 }
395                         }
396 #ifdef RTE_SCHED_RED
397                         for (j = 0; j < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; j++) {
398                                 for (k = 0; k < RTE_COLORS; k++) {
399                                         subport_params[i].red_params[j][k].min_th =
400                                                 red_params[j][k].min_th;
401                                         subport_params[i].red_params[j][k].max_th =
402                                                 red_params[j][k].max_th;
403                                         subport_params[i].red_params[j][k].maxp_inv =
404                                                 red_params[j][k].maxp_inv;
405                                         subport_params[i].red_params[j][k].wq_log2 =
406                                                 red_params[j][k].wq_log2;
407                                 }
408                         }
409 #endif
410                 }
411         }
412
413         return 0;
414 }