New upstream version 17.11.4
[deb_dpdk.git] / examples / ip_pipeline / config_parse_tm.c
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 #include <stdint.h>
34 #include <stdlib.h>
35 #include <stdio.h>
36 #include <ctype.h>
37 #include <getopt.h>
38 #include <errno.h>
39 #include <stdarg.h>
40 #include <string.h>
41 #include <libgen.h>
42 #include <unistd.h>
43
44 #include <rte_errno.h>
45 #include <rte_cfgfile.h>
46 #include <rte_string_fns.h>
47
48 #include "app.h"
49
50 static int
51 tm_cfgfile_load_sched_port(
52         struct rte_cfgfile *file,
53         struct rte_sched_port_params *port_params)
54 {
55         const char *entry;
56         int j;
57
58         entry = rte_cfgfile_get_entry(file, "port", "frame overhead");
59         if (entry)
60                 port_params->frame_overhead = (uint32_t)atoi(entry);
61
62         entry = rte_cfgfile_get_entry(file, "port", "mtu");
63         if (entry)
64                 port_params->mtu = (uint32_t)atoi(entry);
65
66         entry = rte_cfgfile_get_entry(file,
67                 "port",
68                 "number of subports per port");
69         if (entry)
70                 port_params->n_subports_per_port = (uint32_t) atoi(entry);
71
72         entry = rte_cfgfile_get_entry(file,
73                 "port",
74                 "number of pipes per subport");
75         if (entry)
76                 port_params->n_pipes_per_subport = (uint32_t) atoi(entry);
77
78         entry = rte_cfgfile_get_entry(file, "port", "queue sizes");
79         if (entry) {
80                 char *next;
81
82                 for (j = 0; j < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; j++) {
83                         port_params->qsize[j] = (uint16_t)
84                                 strtol(entry, &next, 10);
85                         if (next == NULL)
86                                 break;
87                         entry = next;
88                 }
89         }
90
91 #ifdef RTE_SCHED_RED
92         for (j = 0; j < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; j++) {
93                 char str[32];
94
95                 /* Parse WRED min thresholds */
96                 snprintf(str, sizeof(str), "tc %" PRId32 " wred min", j);
97                 entry = rte_cfgfile_get_entry(file, "red", str);
98                 if (entry) {
99                         char *next;
100                         int k;
101
102                         /* for each packet colour (green, yellow, red) */
103                         for (k = 0; k < e_RTE_METER_COLORS; k++) {
104                                 port_params->red_params[j][k].min_th
105                                         = (uint16_t)strtol(entry, &next, 10);
106                                 if (next == NULL)
107                                         break;
108                                 entry = next;
109                         }
110                 }
111
112                 /* Parse WRED max thresholds */
113                 snprintf(str, sizeof(str), "tc %" PRId32 " wred max", j);
114                 entry = rte_cfgfile_get_entry(file, "red", str);
115                 if (entry) {
116                         char *next;
117                         int k;
118
119                         /* for each packet colour (green, yellow, red) */
120                         for (k = 0; k < e_RTE_METER_COLORS; k++) {
121                                 port_params->red_params[j][k].max_th
122                                         = (uint16_t)strtol(entry, &next, 10);
123                                 if (next == NULL)
124                                         break;
125                                 entry = next;
126                         }
127                 }
128
129                 /* Parse WRED inverse mark probabilities */
130                 snprintf(str, sizeof(str), "tc %" PRId32 " wred inv prob", j);
131                 entry = rte_cfgfile_get_entry(file, "red", str);
132                 if (entry) {
133                         char *next;
134                         int k;
135
136                         /* for each packet colour (green, yellow, red) */
137                         for (k = 0; k < e_RTE_METER_COLORS; k++) {
138                                 port_params->red_params[j][k].maxp_inv
139                                         = (uint8_t)strtol(entry, &next, 10);
140
141                                 if (next == NULL)
142                                         break;
143                                 entry = next;
144                         }
145                 }
146
147                 /* Parse WRED EWMA filter weights */
148                 snprintf(str, sizeof(str), "tc %" PRId32 " wred weight", j);
149                 entry = rte_cfgfile_get_entry(file, "red", str);
150                 if (entry) {
151                         char *next;
152                         int k;
153
154                         /* for each packet colour (green, yellow, red) */
155                         for (k = 0; k < e_RTE_METER_COLORS; k++) {
156                                 port_params->red_params[j][k].wq_log2
157                                         = (uint8_t)strtol(entry, &next, 10);
158                                 if (next == NULL)
159                                         break;
160                                 entry = next;
161                         }
162                 }
163         }
164 #endif /* RTE_SCHED_RED */
165
166         return 0;
167 }
168
169 static int
170 tm_cfgfile_load_sched_pipe(
171         struct rte_cfgfile *file,
172         struct rte_sched_port_params *port_params,
173         struct rte_sched_pipe_params *pipe_params)
174 {
175         int i, j;
176         char *next;
177         const char *entry;
178         int profiles;
179
180         profiles = rte_cfgfile_num_sections(file,
181                 "pipe profile", sizeof("pipe profile") - 1);
182         port_params->n_pipe_profiles = profiles;
183
184         for (j = 0; j < profiles; j++) {
185                 char pipe_name[32];
186
187                 snprintf(pipe_name, sizeof(pipe_name),
188                         "pipe profile %" PRId32, j);
189
190                 entry = rte_cfgfile_get_entry(file, pipe_name, "tb rate");
191                 if (entry)
192                         pipe_params[j].tb_rate = (uint32_t) atoi(entry);
193
194                 entry = rte_cfgfile_get_entry(file, pipe_name, "tb size");
195                 if (entry)
196                         pipe_params[j].tb_size = (uint32_t) atoi(entry);
197
198                 entry = rte_cfgfile_get_entry(file, pipe_name, "tc period");
199                 if (entry)
200                         pipe_params[j].tc_period = (uint32_t) atoi(entry);
201
202                 entry = rte_cfgfile_get_entry(file, pipe_name, "tc 0 rate");
203                 if (entry)
204                         pipe_params[j].tc_rate[0] = (uint32_t) atoi(entry);
205
206                 entry = rte_cfgfile_get_entry(file, pipe_name, "tc 1 rate");
207                 if (entry)
208                         pipe_params[j].tc_rate[1] = (uint32_t) atoi(entry);
209
210                 entry = rte_cfgfile_get_entry(file, pipe_name, "tc 2 rate");
211                 if (entry)
212                         pipe_params[j].tc_rate[2] = (uint32_t) atoi(entry);
213
214                 entry = rte_cfgfile_get_entry(file, pipe_name, "tc 3 rate");
215                 if (entry)
216                         pipe_params[j].tc_rate[3] = (uint32_t) atoi(entry);
217
218 #ifdef RTE_SCHED_SUBPORT_TC_OV
219                 entry = rte_cfgfile_get_entry(file, pipe_name,
220                         "tc 3 oversubscription weight");
221                 if (entry)
222                         pipe_params[j].tc_ov_weight = (uint8_t)atoi(entry);
223 #endif
224
225                 entry = rte_cfgfile_get_entry(file,
226                         pipe_name,
227                         "tc 0 wrr weights");
228                 if (entry)
229                         for (i = 0; i < RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS; i++) {
230                                 pipe_params[j].wrr_weights[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE*0 + i] =
231                                         (uint8_t) strtol(entry, &next, 10);
232                                 if (next == NULL)
233                                         break;
234                                 entry = next;
235                         }
236
237                 entry = rte_cfgfile_get_entry(file, pipe_name, "tc 1 wrr weights");
238                 if (entry)
239                         for (i = 0; i < RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS; i++) {
240                                 pipe_params[j].wrr_weights[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE*1 + i] =
241                                         (uint8_t) strtol(entry, &next, 10);
242                                 if (next == NULL)
243                                         break;
244                                 entry = next;
245                         }
246
247                 entry = rte_cfgfile_get_entry(file, pipe_name, "tc 2 wrr weights");
248                 if (entry)
249                         for (i = 0; i < RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS; i++) {
250                                 pipe_params[j].wrr_weights[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE*2 + i] =
251                                         (uint8_t) strtol(entry, &next, 10);
252                                 if (next == NULL)
253                                         break;
254                                 entry = next;
255                         }
256
257                 entry = rte_cfgfile_get_entry(file, pipe_name, "tc 3 wrr weights");
258                 if (entry)
259                         for (i = 0; i < RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS; i++) {
260                                 pipe_params[j].wrr_weights[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE*3 + i] =
261                                         (uint8_t) strtol(entry, &next, 10);
262                                 if (next == NULL)
263                                         break;
264                                 entry = next;
265                         }
266         }
267         return 0;
268 }
269
270 static int
271 tm_cfgfile_load_sched_subport(
272         struct rte_cfgfile *file,
273         struct rte_sched_subport_params *subport_params,
274         int *pipe_to_profile)
275 {
276         const char *entry;
277         int i, j, k;
278
279         for (i = 0; i < APP_MAX_SCHED_SUBPORTS; i++) {
280                 char sec_name[CFG_NAME_LEN];
281
282                 snprintf(sec_name, sizeof(sec_name),
283                         "subport %" PRId32, i);
284
285                 if (rte_cfgfile_has_section(file, sec_name)) {
286                         entry = rte_cfgfile_get_entry(file,
287                                 sec_name,
288                                 "tb rate");
289                         if (entry)
290                                 subport_params[i].tb_rate =
291                                         (uint32_t) atoi(entry);
292
293                         entry = rte_cfgfile_get_entry(file,
294                                 sec_name,
295                                 "tb size");
296                         if (entry)
297                                 subport_params[i].tb_size =
298                                         (uint32_t) atoi(entry);
299
300                         entry = rte_cfgfile_get_entry(file,
301                                 sec_name,
302                                 "tc period");
303                         if (entry)
304                                 subport_params[i].tc_period =
305                                         (uint32_t) atoi(entry);
306
307                         entry = rte_cfgfile_get_entry(file,
308                                 sec_name,
309                                 "tc 0 rate");
310                         if (entry)
311                                 subport_params[i].tc_rate[0] =
312                                         (uint32_t) atoi(entry);
313
314                         entry = rte_cfgfile_get_entry(file,
315                                 sec_name,
316                                 "tc 1 rate");
317                         if (entry)
318                                 subport_params[i].tc_rate[1] =
319                                         (uint32_t) atoi(entry);
320
321                         entry = rte_cfgfile_get_entry(file,
322                                 sec_name,
323                                 "tc 2 rate");
324                         if (entry)
325                                 subport_params[i].tc_rate[2] =
326                                         (uint32_t) atoi(entry);
327
328                         entry = rte_cfgfile_get_entry(file,
329                                 sec_name,
330                                 "tc 3 rate");
331                         if (entry)
332                                 subport_params[i].tc_rate[3] =
333                                         (uint32_t) atoi(entry);
334
335                         int n_entries = rte_cfgfile_section_num_entries(file,
336                                 sec_name);
337                         struct rte_cfgfile_entry entries[n_entries];
338
339                         rte_cfgfile_section_entries(file,
340                                 sec_name,
341                                 entries,
342                                 n_entries);
343
344                         for (j = 0; j < n_entries; j++)
345                                 if (strncmp("pipe",
346                                         entries[j].name,
347                                         sizeof("pipe") - 1) == 0) {
348                                         int profile;
349                                         char *tokens[2] = {NULL, NULL};
350                                         int n_tokens;
351                                         int begin, end;
352                                         char name[CFG_NAME_LEN + 1];
353
354                                         profile = atoi(entries[j].value);
355                                         memcpy(name,
356                                                 entries[j].name,
357                                                 sizeof(name));
358                                         n_tokens = rte_strsplit(
359                                                 &name[sizeof("pipe")],
360                                                 strnlen(name, CFG_NAME_LEN),
361                                                         tokens, 2, '-');
362
363                                         begin =  atoi(tokens[0]);
364                                         if (n_tokens == 2)
365                                                 end = atoi(tokens[1]);
366                                         else
367                                                 end = begin;
368
369                                         if ((end >= APP_MAX_SCHED_PIPES) ||
370                                                 (begin > end))
371                                                 return -1;
372
373                                         for (k = begin; k <= end; k++) {
374                                                 char profile_name[CFG_NAME_LEN];
375
376                                                 snprintf(profile_name,
377                                                         sizeof(profile_name),
378                                                         "pipe profile %" PRId32,
379                                                         profile);
380                                                 if (rte_cfgfile_has_section(file, profile_name))
381                                                         pipe_to_profile[i * APP_MAX_SCHED_PIPES + k] = profile;
382                                                 else
383                                                         rte_exit(EXIT_FAILURE,
384                                                                 "Wrong pipe profile %s\n",
385                                                                 entries[j].value);
386                                         }
387                                 }
388                 }
389         }
390
391         return 0;
392 }
393
394 static int
395 tm_cfgfile_load(struct app_pktq_tm_params *tm)
396 {
397         struct rte_cfgfile *file;
398         uint32_t i;
399
400         memset(tm->sched_subport_params, 0, sizeof(tm->sched_subport_params));
401         memset(tm->sched_pipe_profiles, 0, sizeof(tm->sched_pipe_profiles));
402         memset(&tm->sched_port_params, 0, sizeof(tm->sched_port_params));
403         for (i = 0; i < APP_MAX_SCHED_SUBPORTS * APP_MAX_SCHED_PIPES; i++)
404                 tm->sched_pipe_to_profile[i] = -1;
405
406         tm->sched_port_params.pipe_profiles = &tm->sched_pipe_profiles[0];
407
408         if (tm->file_name[0] == '\0')
409                 return -1;
410
411         file = rte_cfgfile_load(tm->file_name, 0);
412         if (file == NULL)
413                 return -1;
414
415         tm_cfgfile_load_sched_port(file,
416                 &tm->sched_port_params);
417         tm_cfgfile_load_sched_subport(file,
418                 tm->sched_subport_params,
419                 tm->sched_pipe_to_profile);
420         tm_cfgfile_load_sched_pipe(file,
421                 &tm->sched_port_params,
422                 tm->sched_pipe_profiles);
423
424         rte_cfgfile_close(file);
425         return 0;
426 }
427
428 int
429 app_config_parse_tm(struct app_params *app)
430 {
431         uint32_t i;
432
433         for (i = 0; i < RTE_DIM(app->tm_params); i++) {
434                 struct app_pktq_tm_params *p = &app->tm_params[i];
435                 int status;
436
437                 if (!APP_PARAM_VALID(p))
438                         break;
439
440                 status = tm_cfgfile_load(p);
441                 APP_CHECK(status == 0,
442                         "Parse error for %s configuration file \"%s\"\n",
443                         p->name,
444                         p->file_name);
445         }
446
447         return 0;
448 }