tailq: remove unneeded inclusions
[dpdk.git] / examples / ip_pipeline / config.c
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2010-2014 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
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <stdint.h>
37 #include <inttypes.h>
38 #include <sys/types.h>
39 #include <string.h>
40 #include <sys/queue.h>
41 #include <stdarg.h>
42 #include <errno.h>
43 #include <getopt.h>
44
45 #include <rte_common.h>
46 #include <rte_byteorder.h>
47 #include <rte_log.h>
48 #include <rte_memory.h>
49 #include <rte_memcpy.h>
50 #include <rte_memzone.h>
51 #include <rte_eal.h>
52 #include <rte_per_lcore.h>
53 #include <rte_launch.h>
54 #include <rte_atomic.h>
55 #include <rte_cycles.h>
56 #include <rte_prefetch.h>
57 #include <rte_lcore.h>
58 #include <rte_per_lcore.h>
59 #include <rte_branch_prediction.h>
60 #include <rte_interrupts.h>
61 #include <rte_pci.h>
62 #include <rte_random.h>
63 #include <rte_debug.h>
64 #include <rte_ether.h>
65 #include <rte_ethdev.h>
66 #include <rte_ring.h>
67 #include <rte_mempool.h>
68 #include <rte_mbuf.h>
69 #include <rte_ip.h>
70 #include <rte_tcp.h>
71 #include <rte_lpm.h>
72 #include <rte_lpm6.h>
73 #include <rte_string_fns.h>
74 #include <rte_cfgfile.h>
75
76 #include "main.h"
77
78 struct app_params app;
79
80 static const char usage[] =
81         "Usage: %s EAL_OPTIONS-- -p PORT_MASK [-f CONFIG_FILE]\n";
82
83 void
84 app_print_usage(char *prgname)
85 {
86         printf(usage, prgname);
87 }
88
89 const char *
90 app_core_type_id_to_string(enum app_core_type id)
91 {
92         switch (id) {
93         case APP_CORE_NONE: return "NONE";
94         case APP_CORE_MASTER: return "MASTER";
95         case APP_CORE_RX: return "RX";
96         case APP_CORE_TX: return "TX";
97         case APP_CORE_PT: return "PT";
98         case APP_CORE_FC: return "FC";
99         case APP_CORE_FW: return "FW";
100         case APP_CORE_RT: return "RT";
101         case APP_CORE_TM: return "TM";
102         case APP_CORE_IPV4_FRAG: return "IPV4_FRAG";
103         case APP_CORE_IPV4_RAS: return "IPV4_RAS";
104         default: return NULL;
105         }
106 }
107
108 int
109 app_core_type_string_to_id(const char *string, enum app_core_type *id)
110 {
111         if (strcmp(string, "NONE") == 0) {
112                 *id = APP_CORE_NONE;
113                 return 0;
114         }
115         if (strcmp(string, "MASTER") == 0) {
116                 *id = APP_CORE_MASTER;
117                 return 0;
118         }
119         if (strcmp(string, "RX") == 0) {
120                 *id = APP_CORE_RX;
121                 return 0;
122         }
123         if (strcmp(string, "TX") == 0) {
124                 *id = APP_CORE_TX;
125                 return 0;
126         }
127         if (strcmp(string, "PT") == 0) {
128                 *id = APP_CORE_PT;
129                 return 0;
130         }
131         if (strcmp(string, "FC") == 0) {
132                 *id = APP_CORE_FC;
133                 return 0;
134         }
135         if (strcmp(string, "FW") == 0) {
136                 *id = APP_CORE_FW;
137                 return 0;
138         }
139         if (strcmp(string, "RT") == 0) {
140                 *id = APP_CORE_RT;
141                 return 0;
142         }
143         if (strcmp(string, "TM") == 0) {
144                 *id = APP_CORE_TM;
145                 return 0;
146         }
147         if (strcmp(string, "IPV4_FRAG") == 0) {
148                 *id = APP_CORE_IPV4_FRAG;
149                 return 0;
150         }
151         if (strcmp(string, "IPV4_RAS") == 0) {
152                 *id = APP_CORE_IPV4_RAS;
153                 return 0;
154         }
155
156         return -1;
157 }
158
159 static uint64_t
160 app_get_core_mask(void)
161 {
162         uint64_t core_mask = 0;
163         uint32_t i;
164
165         for (i = 0; i < RTE_MAX_LCORE; i++) {
166                 if (rte_lcore_is_enabled(i) == 0)
167                         continue;
168
169                 core_mask |= 1LLU << i;
170         }
171
172         return core_mask;
173 }
174
175 static int
176 app_install_coremask(uint64_t core_mask)
177 {
178         uint32_t n_cores, i;
179
180         for (n_cores = 0, i = 0; i < RTE_MAX_LCORE; i++)
181                 if (app.cores[i].core_type != APP_CORE_NONE)
182                         n_cores++;
183
184         if (n_cores != app.n_cores) {
185                 rte_panic("Number of cores in COREMASK should be %u instead "
186                         "of %u\n", n_cores, app.n_cores);
187                 return -1;
188         }
189
190         for (i = 0; i < RTE_MAX_LCORE; i++) {
191                 uint32_t core_id;
192
193                 if (app.cores[i].core_type == APP_CORE_NONE)
194                         continue;
195
196                 core_id = __builtin_ctzll(core_mask);
197                 core_mask &= ~(1LLU << core_id);
198
199                 app.cores[i].core_id = core_id;
200         }
201
202         return 0;
203 }
204 static int
205 app_install_cfgfile(const char *file_name)
206 {
207         struct rte_cfgfile *file;
208         uint32_t n_cores, i;
209
210         memset(app.cores, 0, sizeof(app.cores));
211
212         if (file_name[0] == '\0')
213                 return -1;
214
215         file = rte_cfgfile_load(file_name, 0);
216         if (file == NULL) {
217                 rte_panic("Config file %s not found\n", file_name);
218                 return -1;
219         }
220
221         n_cores = (uint32_t) rte_cfgfile_num_sections(file, "core",
222                 strnlen("core", 5));
223         if (n_cores < app.n_cores) {
224                 rte_panic("Config file parse error: not enough cores specified "
225                         "(%u cores missing)\n", app.n_cores - n_cores);
226                 return -1;
227         }
228         if (n_cores > app.n_cores) {
229                 rte_panic("Config file parse error: too many cores specified "
230                         "(%u cores too many)\n", n_cores - app.n_cores);
231                 return -1;
232         }
233
234         for (i = 0; i < n_cores; i++) {
235                 struct app_core_params *p = &app.cores[i];
236                 char section_name[16];
237                 const char *entry;
238                 uint32_t j;
239
240                 /* [core X] */
241                 snprintf(section_name, sizeof(section_name), "core %u", i);
242                 if (!rte_cfgfile_has_section(file, section_name)) {
243                         rte_panic("Config file parse error: core IDs are not "
244                                 "sequential (core %u missing)\n", i);
245                         return -1;
246                 }
247
248                 /* type */
249                 entry = rte_cfgfile_get_entry(file, section_name, "type");
250                 if (!entry) {
251                         rte_panic("Config file parse error: core %u type not "
252                                 "defined\n", i);
253                         return -1;
254                 }
255                 if ((app_core_type_string_to_id(entry, &p->core_type) != 0) ||
256                     (p->core_type == APP_CORE_NONE)) {
257                         rte_panic("Config file parse error: core %u type "
258                                 "error\n", i);
259                         return -1;
260                 }
261
262                 /* queues in */
263                 entry = rte_cfgfile_get_entry(file, section_name, "queues in");
264                 if (!entry) {
265                         rte_panic("Config file parse error: core %u queues in "
266                                 "not defined\n", i);
267                         return -1;
268                 }
269
270                 for (j = 0; (j < APP_MAX_SWQ_PER_CORE) && (entry != NULL);
271                         j++) {
272                         char *next;
273
274                         p->swq_in[j] =  (uint32_t) strtol(entry, &next, 10);
275                         if (next == entry)
276                                 break;
277                         entry = next;
278                 }
279
280                 if ((j != APP_MAX_SWQ_PER_CORE) || (*entry != '\0')) {
281                         rte_panic("Config file parse error: core %u queues in "
282                                 "error\n", i);
283                         return -1;
284                 }
285
286                 /* queues out */
287                 entry = rte_cfgfile_get_entry(file, section_name, "queues out");
288                 if (!entry) {
289                         rte_panic("Config file parse error: core %u queues out "
290                                 "not defined\n", i);
291                         return -1;
292                 }
293
294                 for (j = 0; (j < APP_MAX_SWQ_PER_CORE) && (entry != NULL);
295                         j++) {
296                         char *next;
297
298                         p->swq_out[j] =  (uint32_t) strtol(entry, &next, 10);
299                         if (next == entry)
300                                 break;
301                         entry = next;
302                 }
303                 if ((j != APP_MAX_SWQ_PER_CORE) || (*entry != '\0')) {
304                         rte_panic("Config file parse error: core %u queues out "
305                                 "error\n", i);
306                         return -1;
307                 }
308         }
309
310         rte_cfgfile_close(file);
311
312         return 0;
313 }
314
315 void app_cores_config_print(void)
316 {
317         uint32_t i;
318
319         for (i = 0; i < RTE_MAX_LCORE; i++) {
320                 struct app_core_params *p = &app.cores[i];
321                 uint32_t j;
322
323                 if (app.cores[i].core_type == APP_CORE_NONE)
324                         continue;
325
326                 printf("---> core %u: id = %u type = %6s [", i, p->core_id,
327                         app_core_type_id_to_string(p->core_type));
328                 for (j = 0; j < APP_MAX_SWQ_PER_CORE; j++)
329                         printf("%2d ", (int) p->swq_in[j]);
330
331                 printf("] [");
332                 for (j = 0; j < APP_MAX_SWQ_PER_CORE; j++)
333                         printf("%2d ", (int) p->swq_out[j]);
334
335                 printf("]\n");
336         }
337 }
338
339 static int
340 app_install_port_mask(const char *arg)
341 {
342         char *end = NULL;
343         uint64_t port_mask;
344         uint32_t i;
345
346         if (arg[0] == '\0')
347                 return -1;
348
349         port_mask = strtoul(arg, &end, 16);
350         if ((end == NULL) || (*end != '\0'))
351                 return -2;
352
353         if (port_mask == 0)
354                 return -3;
355
356         app.n_ports = 0;
357         for (i = 0; i < 64; i++) {
358                 if ((port_mask & (1LLU << i)) == 0)
359                         continue;
360
361                 if (app.n_ports >= APP_MAX_PORTS)
362                         return -4;
363
364                 app.ports[app.n_ports] = i;
365                 app.n_ports++;
366         }
367
368         if (!rte_is_power_of_2(app.n_ports))
369                 return -5;
370
371         return 0;
372 }
373
374 int
375 app_parse_args(int argc, char **argv)
376 {
377         int opt, ret;
378         char **argvopt;
379         int option_index;
380         char *prgname = argv[0];
381         static struct option lgopts[] = {
382                 {NULL, 0, 0, 0}
383         };
384         uint64_t core_mask = app_get_core_mask();
385
386         app.n_cores = __builtin_popcountll(core_mask);
387
388         argvopt = argv;
389         while ((opt = getopt_long(argc, argvopt, "p:f:", lgopts,
390                         &option_index)) != EOF) {
391                 switch (opt) {
392                 case 'p':
393                         if (app_install_port_mask(optarg) != 0)
394                                 rte_panic("PORT_MASK should specify a number "
395                                         "of ports that is power of 2 less or "
396                                         "equal to %u\n", APP_MAX_PORTS);
397                         break;
398
399                 case 'f':
400                         app_install_cfgfile(optarg);
401                         break;
402
403                 default:
404                         return -1;
405                 }
406         }
407
408         app_install_coremask(core_mask);
409
410         app_cores_config_print();
411
412         if (optind >= 0)
413                 argv[optind - 1] = prgname;
414
415         ret = optind - 1;
416         optind = 0; /* reset getopt lib */
417
418         return ret;
419 }