New upstream version 18.02
[deb_dpdk.git] / examples / ip_pipeline / config_parse_tm.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2015 Intel Corporation
3  */
4 #include <stdint.h>
5 #include <stdlib.h>
6 #include <stdio.h>
7 #include <ctype.h>
8 #include <getopt.h>
9 #include <errno.h>
10 #include <stdarg.h>
11 #include <string.h>
12 #include <libgen.h>
13 #include <unistd.h>
14
15 #include <rte_errno.h>
16 #include <rte_cfgfile.h>
17 #include <rte_string_fns.h>
18
19 #include "app.h"
20
21 static int
22 tm_cfgfile_load_sched_port(
23         struct rte_cfgfile *file,
24         struct rte_sched_port_params *port_params)
25 {
26         const char *entry;
27         int j;
28
29         entry = rte_cfgfile_get_entry(file, "port", "frame overhead");
30         if (entry)
31                 port_params->frame_overhead = (uint32_t)atoi(entry);
32
33         entry = rte_cfgfile_get_entry(file, "port", "mtu");
34         if (entry)
35                 port_params->mtu = (uint32_t)atoi(entry);
36
37         entry = rte_cfgfile_get_entry(file,
38                 "port",
39                 "number of subports per port");
40         if (entry)
41                 port_params->n_subports_per_port = (uint32_t) atoi(entry);
42
43         entry = rte_cfgfile_get_entry(file,
44                 "port",
45                 "number of pipes per subport");
46         if (entry)
47                 port_params->n_pipes_per_subport = (uint32_t) atoi(entry);
48
49         entry = rte_cfgfile_get_entry(file, "port", "queue sizes");
50         if (entry) {
51                 char *next;
52
53                 for (j = 0; j < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; j++) {
54                         port_params->qsize[j] = (uint16_t)
55                                 strtol(entry, &next, 10);
56                         if (next == NULL)
57                                 break;
58                         entry = next;
59                 }
60         }
61
62 #ifdef RTE_SCHED_RED
63         for (j = 0; j < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; j++) {
64                 char str[32];
65
66                 /* Parse WRED min thresholds */
67                 snprintf(str, sizeof(str), "tc %" PRId32 " wred min", j);
68                 entry = rte_cfgfile_get_entry(file, "red", str);
69                 if (entry) {
70                         char *next;
71                         int k;
72
73                         /* for each packet colour (green, yellow, red) */
74                         for (k = 0; k < e_RTE_METER_COLORS; k++) {
75                                 port_params->red_params[j][k].min_th
76                                         = (uint16_t)strtol(entry, &next, 10);
77                                 if (next == NULL)
78                                         break;
79                                 entry = next;
80                         }
81                 }
82
83                 /* Parse WRED max thresholds */
84                 snprintf(str, sizeof(str), "tc %" PRId32 " wred max", j);
85                 entry = rte_cfgfile_get_entry(file, "red", str);
86                 if (entry) {
87                         char *next;
88                         int k;
89
90                         /* for each packet colour (green, yellow, red) */
91                         for (k = 0; k < e_RTE_METER_COLORS; k++) {
92                                 port_params->red_params[j][k].max_th
93                                         = (uint16_t)strtol(entry, &next, 10);
94                                 if (next == NULL)
95                                         break;
96                                 entry = next;
97                         }
98                 }
99
100                 /* Parse WRED inverse mark probabilities */
101                 snprintf(str, sizeof(str), "tc %" PRId32 " wred inv prob", j);
102                 entry = rte_cfgfile_get_entry(file, "red", str);
103                 if (entry) {
104                         char *next;
105                         int k;
106
107                         /* for each packet colour (green, yellow, red) */
108                         for (k = 0; k < e_RTE_METER_COLORS; k++) {
109                                 port_params->red_params[j][k].maxp_inv
110                                         = (uint8_t)strtol(entry, &next, 10);
111
112                                 if (next == NULL)
113                                         break;
114                                 entry = next;
115                         }
116                 }
117
118                 /* Parse WRED EWMA filter weights */
119                 snprintf(str, sizeof(str), "tc %" PRId32 " wred weight", j);
120                 entry = rte_cfgfile_get_entry(file, "red", str);
121                 if (entry) {
122                         char *next;
123                         int k;
124
125                         /* for each packet colour (green, yellow, red) */
126                         for (k = 0; k < e_RTE_METER_COLORS; k++) {
127                                 port_params->red_params[j][k].wq_log2
128                                         = (uint8_t)strtol(entry, &next, 10);
129                                 if (next == NULL)
130                                         break;
131                                 entry = next;
132                         }
133                 }
134         }
135 #endif /* RTE_SCHED_RED */
136
137         return 0;
138 }
139
140 static int
141 tm_cfgfile_load_sched_pipe(
142         struct rte_cfgfile *file,
143         struct rte_sched_port_params *port_params,
144         struct rte_sched_pipe_params *pipe_params)
145 {
146         int i, j;
147         char *next;
148         const char *entry;
149         int profiles;
150
151         profiles = rte_cfgfile_num_sections(file,
152                 "pipe profile", sizeof("pipe profile") - 1);
153         port_params->n_pipe_profiles = profiles;
154
155         for (j = 0; j < profiles; j++) {
156                 char pipe_name[32];
157
158                 snprintf(pipe_name, sizeof(pipe_name),
159                         "pipe profile %" PRId32, j);
160
161                 entry = rte_cfgfile_get_entry(file, pipe_name, "tb rate");
162                 if (entry)
163                         pipe_params[j].tb_rate = (uint32_t) atoi(entry);
164
165                 entry = rte_cfgfile_get_entry(file, pipe_name, "tb size");
166                 if (entry)
167                         pipe_params[j].tb_size = (uint32_t) atoi(entry);
168
169                 entry = rte_cfgfile_get_entry(file, pipe_name, "tc period");
170                 if (entry)
171                         pipe_params[j].tc_period = (uint32_t) atoi(entry);
172
173                 entry = rte_cfgfile_get_entry(file, pipe_name, "tc 0 rate");
174                 if (entry)
175                         pipe_params[j].tc_rate[0] = (uint32_t) atoi(entry);
176
177                 entry = rte_cfgfile_get_entry(file, pipe_name, "tc 1 rate");
178                 if (entry)
179                         pipe_params[j].tc_rate[1] = (uint32_t) atoi(entry);
180
181                 entry = rte_cfgfile_get_entry(file, pipe_name, "tc 2 rate");
182                 if (entry)
183                         pipe_params[j].tc_rate[2] = (uint32_t) atoi(entry);
184
185                 entry = rte_cfgfile_get_entry(file, pipe_name, "tc 3 rate");
186                 if (entry)
187                         pipe_params[j].tc_rate[3] = (uint32_t) atoi(entry);
188
189 #ifdef RTE_SCHED_SUBPORT_TC_OV
190                 entry = rte_cfgfile_get_entry(file, pipe_name,
191                         "tc 3 oversubscription weight");
192                 if (entry)
193                         pipe_params[j].tc_ov_weight = (uint8_t)atoi(entry);
194 #endif
195
196                 entry = rte_cfgfile_get_entry(file,
197                         pipe_name,
198                         "tc 0 wrr weights");
199                 if (entry)
200                         for (i = 0; i < RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS; i++) {
201                                 pipe_params[j].wrr_weights[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE*0 + i] =
202                                         (uint8_t) strtol(entry, &next, 10);
203                                 if (next == NULL)
204                                         break;
205                                 entry = next;
206                         }
207
208                 entry = rte_cfgfile_get_entry(file, pipe_name, "tc 1 wrr weights");
209                 if (entry)
210                         for (i = 0; i < RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS; i++) {
211                                 pipe_params[j].wrr_weights[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE*1 + i] =
212                                         (uint8_t) strtol(entry, &next, 10);
213                                 if (next == NULL)
214                                         break;
215                                 entry = next;
216                         }
217
218                 entry = rte_cfgfile_get_entry(file, pipe_name, "tc 2 wrr weights");
219                 if (entry)
220                         for (i = 0; i < RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS; i++) {
221                                 pipe_params[j].wrr_weights[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE*2 + i] =
222                                         (uint8_t) strtol(entry, &next, 10);
223                                 if (next == NULL)
224                                         break;
225                                 entry = next;
226                         }
227
228                 entry = rte_cfgfile_get_entry(file, pipe_name, "tc 3 wrr weights");
229                 if (entry)
230                         for (i = 0; i < RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS; i++) {
231                                 pipe_params[j].wrr_weights[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE*3 + i] =
232                                         (uint8_t) strtol(entry, &next, 10);
233                                 if (next == NULL)
234                                         break;
235                                 entry = next;
236                         }
237         }
238         return 0;
239 }
240
241 static int
242 tm_cfgfile_load_sched_subport(
243         struct rte_cfgfile *file,
244         struct rte_sched_subport_params *subport_params,
245         int *pipe_to_profile)
246 {
247         const char *entry;
248         int i, j, k;
249
250         for (i = 0; i < APP_MAX_SCHED_SUBPORTS; i++) {
251                 char sec_name[CFG_NAME_LEN];
252
253                 snprintf(sec_name, sizeof(sec_name),
254                         "subport %" PRId32, i);
255
256                 if (rte_cfgfile_has_section(file, sec_name)) {
257                         entry = rte_cfgfile_get_entry(file,
258                                 sec_name,
259                                 "tb rate");
260                         if (entry)
261                                 subport_params[i].tb_rate =
262                                         (uint32_t) atoi(entry);
263
264                         entry = rte_cfgfile_get_entry(file,
265                                 sec_name,
266                                 "tb size");
267                         if (entry)
268                                 subport_params[i].tb_size =
269                                         (uint32_t) atoi(entry);
270
271                         entry = rte_cfgfile_get_entry(file,
272                                 sec_name,
273                                 "tc period");
274                         if (entry)
275                                 subport_params[i].tc_period =
276                                         (uint32_t) atoi(entry);
277
278                         entry = rte_cfgfile_get_entry(file,
279                                 sec_name,
280                                 "tc 0 rate");
281                         if (entry)
282                                 subport_params[i].tc_rate[0] =
283                                         (uint32_t) atoi(entry);
284
285                         entry = rte_cfgfile_get_entry(file,
286                                 sec_name,
287                                 "tc 1 rate");
288                         if (entry)
289                                 subport_params[i].tc_rate[1] =
290                                         (uint32_t) atoi(entry);
291
292                         entry = rte_cfgfile_get_entry(file,
293                                 sec_name,
294                                 "tc 2 rate");
295                         if (entry)
296                                 subport_params[i].tc_rate[2] =
297                                         (uint32_t) atoi(entry);
298
299                         entry = rte_cfgfile_get_entry(file,
300                                 sec_name,
301                                 "tc 3 rate");
302                         if (entry)
303                                 subport_params[i].tc_rate[3] =
304                                         (uint32_t) atoi(entry);
305
306                         int n_entries = rte_cfgfile_section_num_entries(file,
307                                 sec_name);
308                         struct rte_cfgfile_entry entries[n_entries];
309
310                         rte_cfgfile_section_entries(file,
311                                 sec_name,
312                                 entries,
313                                 n_entries);
314
315                         for (j = 0; j < n_entries; j++)
316                                 if (strncmp("pipe",
317                                         entries[j].name,
318                                         sizeof("pipe") - 1) == 0) {
319                                         int profile;
320                                         char *tokens[2] = {NULL, NULL};
321                                         int n_tokens;
322                                         int begin, end;
323                                         char name[CFG_NAME_LEN + 1];
324
325                                         profile = atoi(entries[j].value);
326                                         strncpy(name,
327                                                 entries[j].name,
328                                                 sizeof(name));
329                                         n_tokens = rte_strsplit(
330                                                 &name[sizeof("pipe")],
331                                                 strnlen(name, CFG_NAME_LEN),
332                                                         tokens, 2, '-');
333
334                                         begin =  atoi(tokens[0]);
335                                         if (n_tokens == 2)
336                                                 end = atoi(tokens[1]);
337                                         else
338                                                 end = begin;
339
340                                         if ((end >= APP_MAX_SCHED_PIPES) ||
341                                                 (begin > end))
342                                                 return -1;
343
344                                         for (k = begin; k <= end; k++) {
345                                                 char profile_name[CFG_NAME_LEN];
346
347                                                 snprintf(profile_name,
348                                                         sizeof(profile_name),
349                                                         "pipe profile %" PRId32,
350                                                         profile);
351                                                 if (rte_cfgfile_has_section(file, profile_name))
352                                                         pipe_to_profile[i * APP_MAX_SCHED_PIPES + k] = profile;
353                                                 else
354                                                         rte_exit(EXIT_FAILURE,
355                                                                 "Wrong pipe profile %s\n",
356                                                                 entries[j].value);
357                                         }
358                                 }
359                 }
360         }
361
362         return 0;
363 }
364
365 static int
366 tm_cfgfile_load(struct app_pktq_tm_params *tm)
367 {
368         struct rte_cfgfile *file;
369         uint32_t i;
370
371         memset(tm->sched_subport_params, 0, sizeof(tm->sched_subport_params));
372         memset(tm->sched_pipe_profiles, 0, sizeof(tm->sched_pipe_profiles));
373         memset(&tm->sched_port_params, 0, sizeof(tm->sched_port_params));
374         for (i = 0; i < APP_MAX_SCHED_SUBPORTS * APP_MAX_SCHED_PIPES; i++)
375                 tm->sched_pipe_to_profile[i] = -1;
376
377         tm->sched_port_params.pipe_profiles = &tm->sched_pipe_profiles[0];
378
379         if (tm->file_name[0] == '\0')
380                 return -1;
381
382         file = rte_cfgfile_load(tm->file_name, 0);
383         if (file == NULL)
384                 return -1;
385
386         tm_cfgfile_load_sched_port(file,
387                 &tm->sched_port_params);
388         tm_cfgfile_load_sched_subport(file,
389                 tm->sched_subport_params,
390                 tm->sched_pipe_to_profile);
391         tm_cfgfile_load_sched_pipe(file,
392                 &tm->sched_port_params,
393                 tm->sched_pipe_profiles);
394
395         rte_cfgfile_close(file);
396         return 0;
397 }
398
399 int
400 app_config_parse_tm(struct app_params *app)
401 {
402         uint32_t i;
403
404         for (i = 0; i < RTE_DIM(app->tm_params); i++) {
405                 struct app_pktq_tm_params *p = &app->tm_params[i];
406                 int status;
407
408                 if (!APP_PARAM_VALID(p))
409                         break;
410
411                 status = tm_cfgfile_load(p);
412                 APP_CHECK(status == 0,
413                         "Parse error for %s configuration file \"%s\"\n",
414                         p->name,
415                         p->file_name);
416         }
417
418         return 0;
419 }