remove useless memzone includes
[dpdk.git] / examples / l3fwd / main.c
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2010-2016 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 #include <signal.h>
45 #include <stdbool.h>
46
47 #include <rte_common.h>
48 #include <rte_vect.h>
49 #include <rte_byteorder.h>
50 #include <rte_log.h>
51 #include <rte_memory.h>
52 #include <rte_memcpy.h>
53 #include <rte_eal.h>
54 #include <rte_launch.h>
55 #include <rte_atomic.h>
56 #include <rte_cycles.h>
57 #include <rte_prefetch.h>
58 #include <rte_lcore.h>
59 #include <rte_per_lcore.h>
60 #include <rte_branch_prediction.h>
61 #include <rte_interrupts.h>
62 #include <rte_pci.h>
63 #include <rte_random.h>
64 #include <rte_debug.h>
65 #include <rte_ether.h>
66 #include <rte_ethdev.h>
67 #include <rte_mempool.h>
68 #include <rte_mbuf.h>
69 #include <rte_ip.h>
70 #include <rte_tcp.h>
71 #include <rte_udp.h>
72 #include <rte_string_fns.h>
73 #include <rte_cpuflags.h>
74
75 #include <cmdline_parse.h>
76 #include <cmdline_parse_etheraddr.h>
77
78 #include "l3fwd.h"
79
80 /*
81  * Configurable number of RX/TX ring descriptors
82  */
83 #define RTE_TEST_RX_DESC_DEFAULT 128
84 #define RTE_TEST_TX_DESC_DEFAULT 512
85
86 #define MAX_TX_QUEUE_PER_PORT RTE_MAX_ETHPORTS
87 #define MAX_RX_QUEUE_PER_PORT 128
88
89 #define MAX_LCORE_PARAMS 1024
90
91 /* Static global variables used within this file. */
92 static uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT;
93 static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT;
94
95 /**< Ports set in promiscuous mode off by default. */
96 static int promiscuous_on;
97
98 /* Select Longest-Prefix or Exact match. */
99 static int l3fwd_lpm_on;
100 static int l3fwd_em_on;
101
102 static int numa_on = 1; /**< NUMA is enabled by default. */
103 static int parse_ptype; /**< Parse packet type using rx callback, and */
104                         /**< disabled by default */
105
106 /* Global variables. */
107
108 volatile bool force_quit;
109
110 /* ethernet addresses of ports */
111 uint64_t dest_eth_addr[RTE_MAX_ETHPORTS];
112 struct ether_addr ports_eth_addr[RTE_MAX_ETHPORTS];
113
114 xmm_t val_eth[RTE_MAX_ETHPORTS];
115
116 /* mask of enabled ports */
117 uint32_t enabled_port_mask;
118
119 /* Used only in exact match mode. */
120 int ipv6; /**< ipv6 is false by default. */
121 uint32_t hash_entry_number = HASH_ENTRY_NUMBER_DEFAULT;
122
123 struct lcore_conf lcore_conf[RTE_MAX_LCORE];
124
125 struct lcore_params {
126         uint16_t port_id;
127         uint8_t queue_id;
128         uint8_t lcore_id;
129 } __rte_cache_aligned;
130
131 static struct lcore_params lcore_params_array[MAX_LCORE_PARAMS];
132 static struct lcore_params lcore_params_array_default[] = {
133         {0, 0, 2},
134         {0, 1, 2},
135         {0, 2, 2},
136         {1, 0, 2},
137         {1, 1, 2},
138         {1, 2, 2},
139         {2, 0, 2},
140         {3, 0, 3},
141         {3, 1, 3},
142 };
143
144 static struct lcore_params * lcore_params = lcore_params_array_default;
145 static uint16_t nb_lcore_params = sizeof(lcore_params_array_default) /
146                                 sizeof(lcore_params_array_default[0]);
147
148 static struct rte_eth_conf port_conf = {
149         .rxmode = {
150                 .mq_mode = ETH_MQ_RX_RSS,
151                 .max_rx_pkt_len = ETHER_MAX_LEN,
152                 .split_hdr_size = 0,
153                 .header_split   = 0, /**< Header Split disabled */
154                 .hw_ip_checksum = 1, /**< IP checksum offload enabled */
155                 .hw_vlan_filter = 0, /**< VLAN filtering disabled */
156                 .jumbo_frame    = 0, /**< Jumbo Frame Support disabled */
157                 .hw_strip_crc   = 1, /**< CRC stripped by hardware */
158         },
159         .rx_adv_conf = {
160                 .rss_conf = {
161                         .rss_key = NULL,
162                         .rss_hf = ETH_RSS_IP,
163                 },
164         },
165         .txmode = {
166                 .mq_mode = ETH_MQ_TX_NONE,
167         },
168 };
169
170 static struct rte_mempool * pktmbuf_pool[NB_SOCKETS];
171
172 struct l3fwd_lkp_mode {
173         void  (*setup)(int);
174         int   (*check_ptype)(int);
175         rte_rx_callback_fn cb_parse_ptype;
176         int   (*main_loop)(void *);
177         void* (*get_ipv4_lookup_struct)(int);
178         void* (*get_ipv6_lookup_struct)(int);
179 };
180
181 static struct l3fwd_lkp_mode l3fwd_lkp;
182
183 static struct l3fwd_lkp_mode l3fwd_em_lkp = {
184         .setup                  = setup_hash,
185         .check_ptype            = em_check_ptype,
186         .cb_parse_ptype         = em_cb_parse_ptype,
187         .main_loop              = em_main_loop,
188         .get_ipv4_lookup_struct = em_get_ipv4_l3fwd_lookup_struct,
189         .get_ipv6_lookup_struct = em_get_ipv6_l3fwd_lookup_struct,
190 };
191
192 static struct l3fwd_lkp_mode l3fwd_lpm_lkp = {
193         .setup                  = setup_lpm,
194         .check_ptype            = lpm_check_ptype,
195         .cb_parse_ptype         = lpm_cb_parse_ptype,
196         .main_loop              = lpm_main_loop,
197         .get_ipv4_lookup_struct = lpm_get_ipv4_l3fwd_lookup_struct,
198         .get_ipv6_lookup_struct = lpm_get_ipv6_l3fwd_lookup_struct,
199 };
200
201 /*
202  * Setup lookup methods for forwarding.
203  * Currently exact-match and longest-prefix-match
204  * are supported ones.
205  */
206 static void
207 setup_l3fwd_lookup_tables(void)
208 {
209         /* Setup HASH lookup functions. */
210         if (l3fwd_em_on)
211                 l3fwd_lkp = l3fwd_em_lkp;
212         /* Setup LPM lookup functions. */
213         else
214                 l3fwd_lkp = l3fwd_lpm_lkp;
215 }
216
217 static int
218 check_lcore_params(void)
219 {
220         uint8_t queue, lcore;
221         uint16_t i;
222         int socketid;
223
224         for (i = 0; i < nb_lcore_params; ++i) {
225                 queue = lcore_params[i].queue_id;
226                 if (queue >= MAX_RX_QUEUE_PER_PORT) {
227                         printf("invalid queue number: %hhu\n", queue);
228                         return -1;
229                 }
230                 lcore = lcore_params[i].lcore_id;
231                 if (!rte_lcore_is_enabled(lcore)) {
232                         printf("error: lcore %hhu is not enabled in lcore mask\n", lcore);
233                         return -1;
234                 }
235                 if ((socketid = rte_lcore_to_socket_id(lcore) != 0) &&
236                         (numa_on == 0)) {
237                         printf("warning: lcore %hhu is on socket %d with numa off \n",
238                                 lcore, socketid);
239                 }
240         }
241         return 0;
242 }
243
244 static int
245 check_port_config(const unsigned nb_ports)
246 {
247         uint16_t portid;
248         uint16_t i;
249
250         for (i = 0; i < nb_lcore_params; ++i) {
251                 portid = lcore_params[i].port_id;
252                 if ((enabled_port_mask & (1 << portid)) == 0) {
253                         printf("port %u is not enabled in port mask\n", portid);
254                         return -1;
255                 }
256                 if (portid >= nb_ports) {
257                         printf("port %u is not present on the board\n", portid);
258                         return -1;
259                 }
260         }
261         return 0;
262 }
263
264 static uint8_t
265 get_port_n_rx_queues(const uint16_t port)
266 {
267         int queue = -1;
268         uint16_t i;
269
270         for (i = 0; i < nb_lcore_params; ++i) {
271                 if (lcore_params[i].port_id == port) {
272                         if (lcore_params[i].queue_id == queue+1)
273                                 queue = lcore_params[i].queue_id;
274                         else
275                                 rte_exit(EXIT_FAILURE, "queue ids of the port %d must be"
276                                                 " in sequence and must start with 0\n",
277                                                 lcore_params[i].port_id);
278                 }
279         }
280         return (uint8_t)(++queue);
281 }
282
283 static int
284 init_lcore_rx_queues(void)
285 {
286         uint16_t i, nb_rx_queue;
287         uint8_t lcore;
288
289         for (i = 0; i < nb_lcore_params; ++i) {
290                 lcore = lcore_params[i].lcore_id;
291                 nb_rx_queue = lcore_conf[lcore].n_rx_queue;
292                 if (nb_rx_queue >= MAX_RX_QUEUE_PER_LCORE) {
293                         printf("error: too many queues (%u) for lcore: %u\n",
294                                 (unsigned)nb_rx_queue + 1, (unsigned)lcore);
295                         return -1;
296                 } else {
297                         lcore_conf[lcore].rx_queue_list[nb_rx_queue].port_id =
298                                 lcore_params[i].port_id;
299                         lcore_conf[lcore].rx_queue_list[nb_rx_queue].queue_id =
300                                 lcore_params[i].queue_id;
301                         lcore_conf[lcore].n_rx_queue++;
302                 }
303         }
304         return 0;
305 }
306
307 /* display usage */
308 static void
309 print_usage(const char *prgname)
310 {
311         printf("%s [EAL options] --"
312                 " -p PORTMASK"
313                 " [-P]"
314                 " [-E]"
315                 " [-L]"
316                 " --config (port,queue,lcore)[,(port,queue,lcore)]"
317                 " [--eth-dest=X,MM:MM:MM:MM:MM:MM]"
318                 " [--enable-jumbo [--max-pkt-len PKTLEN]]"
319                 " [--no-numa]"
320                 " [--hash-entry-num]"
321                 " [--ipv6]"
322                 " [--parse-ptype]\n\n"
323
324                 "  -p PORTMASK: Hexadecimal bitmask of ports to configure\n"
325                 "  -P : Enable promiscuous mode\n"
326                 "  -E : Enable exact match\n"
327                 "  -L : Enable longest prefix match (default)\n"
328                 "  --config (port,queue,lcore): Rx queue configuration\n"
329                 "  --eth-dest=X,MM:MM:MM:MM:MM:MM: Ethernet destination for port X\n"
330                 "  --enable-jumbo: Enable jumbo frames\n"
331                 "  --max-pkt-len: Under the premise of enabling jumbo,\n"
332                 "                 maximum packet length in decimal (64-9600)\n"
333                 "  --no-numa: Disable numa awareness\n"
334                 "  --hash-entry-num: Specify the hash entry number in hexadecimal to be setup\n"
335                 "  --ipv6: Set if running ipv6 packets\n"
336                 "  --parse-ptype: Set to use software to analyze packet type\n\n",
337                 prgname);
338 }
339
340 static int
341 parse_max_pkt_len(const char *pktlen)
342 {
343         char *end = NULL;
344         unsigned long len;
345
346         /* parse decimal string */
347         len = strtoul(pktlen, &end, 10);
348         if ((pktlen[0] == '\0') || (end == NULL) || (*end != '\0'))
349                 return -1;
350
351         if (len == 0)
352                 return -1;
353
354         return len;
355 }
356
357 static int
358 parse_portmask(const char *portmask)
359 {
360         char *end = NULL;
361         unsigned long pm;
362
363         /* parse hexadecimal string */
364         pm = strtoul(portmask, &end, 16);
365         if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0'))
366                 return -1;
367
368         if (pm == 0)
369                 return -1;
370
371         return pm;
372 }
373
374 static int
375 parse_hash_entry_number(const char *hash_entry_num)
376 {
377         char *end = NULL;
378         unsigned long hash_en;
379         /* parse hexadecimal string */
380         hash_en = strtoul(hash_entry_num, &end, 16);
381         if ((hash_entry_num[0] == '\0') || (end == NULL) || (*end != '\0'))
382                 return -1;
383
384         if (hash_en == 0)
385                 return -1;
386
387         return hash_en;
388 }
389
390 static int
391 parse_config(const char *q_arg)
392 {
393         char s[256];
394         const char *p, *p0 = q_arg;
395         char *end;
396         enum fieldnames {
397                 FLD_PORT = 0,
398                 FLD_QUEUE,
399                 FLD_LCORE,
400                 _NUM_FLD
401         };
402         unsigned long int_fld[_NUM_FLD];
403         char *str_fld[_NUM_FLD];
404         int i;
405         unsigned size;
406
407         nb_lcore_params = 0;
408
409         while ((p = strchr(p0,'(')) != NULL) {
410                 ++p;
411                 if((p0 = strchr(p,')')) == NULL)
412                         return -1;
413
414                 size = p0 - p;
415                 if(size >= sizeof(s))
416                         return -1;
417
418                 snprintf(s, sizeof(s), "%.*s", size, p);
419                 if (rte_strsplit(s, sizeof(s), str_fld, _NUM_FLD, ',') != _NUM_FLD)
420                         return -1;
421                 for (i = 0; i < _NUM_FLD; i++){
422                         errno = 0;
423                         int_fld[i] = strtoul(str_fld[i], &end, 0);
424                         if (errno != 0 || end == str_fld[i] || int_fld[i] > 255)
425                                 return -1;
426                 }
427                 if (nb_lcore_params >= MAX_LCORE_PARAMS) {
428                         printf("exceeded max number of lcore params: %hu\n",
429                                 nb_lcore_params);
430                         return -1;
431                 }
432                 lcore_params_array[nb_lcore_params].port_id =
433                         (uint8_t)int_fld[FLD_PORT];
434                 lcore_params_array[nb_lcore_params].queue_id =
435                         (uint8_t)int_fld[FLD_QUEUE];
436                 lcore_params_array[nb_lcore_params].lcore_id =
437                         (uint8_t)int_fld[FLD_LCORE];
438                 ++nb_lcore_params;
439         }
440         lcore_params = lcore_params_array;
441         return 0;
442 }
443
444 static void
445 parse_eth_dest(const char *optarg)
446 {
447         uint16_t portid;
448         char *port_end;
449         uint8_t c, *dest, peer_addr[6];
450
451         errno = 0;
452         portid = strtoul(optarg, &port_end, 10);
453         if (errno != 0 || port_end == optarg || *port_end++ != ',')
454                 rte_exit(EXIT_FAILURE,
455                 "Invalid eth-dest: %s", optarg);
456         if (portid >= RTE_MAX_ETHPORTS)
457                 rte_exit(EXIT_FAILURE,
458                 "eth-dest: port %d >= RTE_MAX_ETHPORTS(%d)\n",
459                 portid, RTE_MAX_ETHPORTS);
460
461         if (cmdline_parse_etheraddr(NULL, port_end,
462                 &peer_addr, sizeof(peer_addr)) < 0)
463                 rte_exit(EXIT_FAILURE,
464                 "Invalid ethernet address: %s\n",
465                 port_end);
466         dest = (uint8_t *)&dest_eth_addr[portid];
467         for (c = 0; c < 6; c++)
468                 dest[c] = peer_addr[c];
469         *(uint64_t *)(val_eth + portid) = dest_eth_addr[portid];
470 }
471
472 #define MAX_JUMBO_PKT_LEN  9600
473 #define MEMPOOL_CACHE_SIZE 256
474
475 static const char short_options[] =
476         "p:"  /* portmask */
477         "P"   /* promiscuous */
478         "L"   /* enable long prefix match */
479         "E"   /* enable exact match */
480         ;
481
482 #define CMD_LINE_OPT_CONFIG "config"
483 #define CMD_LINE_OPT_ETH_DEST "eth-dest"
484 #define CMD_LINE_OPT_NO_NUMA "no-numa"
485 #define CMD_LINE_OPT_IPV6 "ipv6"
486 #define CMD_LINE_OPT_ENABLE_JUMBO "enable-jumbo"
487 #define CMD_LINE_OPT_HASH_ENTRY_NUM "hash-entry-num"
488 #define CMD_LINE_OPT_PARSE_PTYPE "parse-ptype"
489 enum {
490         /* long options mapped to a short option */
491
492         /* first long only option value must be >= 256, so that we won't
493          * conflict with short options */
494         CMD_LINE_OPT_MIN_NUM = 256,
495         CMD_LINE_OPT_CONFIG_NUM,
496         CMD_LINE_OPT_ETH_DEST_NUM,
497         CMD_LINE_OPT_NO_NUMA_NUM,
498         CMD_LINE_OPT_IPV6_NUM,
499         CMD_LINE_OPT_ENABLE_JUMBO_NUM,
500         CMD_LINE_OPT_HASH_ENTRY_NUM_NUM,
501         CMD_LINE_OPT_PARSE_PTYPE_NUM,
502 };
503
504 static const struct option lgopts[] = {
505         {CMD_LINE_OPT_CONFIG, 1, 0, CMD_LINE_OPT_CONFIG_NUM},
506         {CMD_LINE_OPT_ETH_DEST, 1, 0, CMD_LINE_OPT_ETH_DEST_NUM},
507         {CMD_LINE_OPT_NO_NUMA, 0, 0, CMD_LINE_OPT_NO_NUMA_NUM},
508         {CMD_LINE_OPT_IPV6, 0, 0, CMD_LINE_OPT_IPV6_NUM},
509         {CMD_LINE_OPT_ENABLE_JUMBO, 0, 0, CMD_LINE_OPT_ENABLE_JUMBO_NUM},
510         {CMD_LINE_OPT_HASH_ENTRY_NUM, 1, 0, CMD_LINE_OPT_HASH_ENTRY_NUM_NUM},
511         {CMD_LINE_OPT_PARSE_PTYPE, 0, 0, CMD_LINE_OPT_PARSE_PTYPE_NUM},
512         {NULL, 0, 0, 0}
513 };
514
515 /*
516  * This expression is used to calculate the number of mbufs needed
517  * depending on user input, taking  into account memory for rx and
518  * tx hardware rings, cache per lcore and mtable per port per lcore.
519  * RTE_MAX is used to ensure that NB_MBUF never goes below a minimum
520  * value of 8192
521  */
522 #define NB_MBUF RTE_MAX(        \
523         (nb_ports*nb_rx_queue*nb_rxd +          \
524         nb_ports*nb_lcores*MAX_PKT_BURST +      \
525         nb_ports*n_tx_queue*nb_txd +            \
526         nb_lcores*MEMPOOL_CACHE_SIZE),          \
527         (unsigned)8192)
528
529 /* Parse the argument given in the command line of the application */
530 static int
531 parse_args(int argc, char **argv)
532 {
533         int opt, ret;
534         char **argvopt;
535         int option_index;
536         char *prgname = argv[0];
537
538         argvopt = argv;
539
540         /* Error or normal output strings. */
541         const char *str1 = "L3FWD: Invalid portmask";
542         const char *str2 = "L3FWD: Promiscuous mode selected";
543         const char *str3 = "L3FWD: Exact match selected";
544         const char *str4 = "L3FWD: Longest-prefix match selected";
545         const char *str5 = "L3FWD: Invalid config";
546         const char *str6 = "L3FWD: NUMA is disabled";
547         const char *str7 = "L3FWD: IPV6 is specified";
548         const char *str8 =
549                 "L3FWD: Jumbo frame is enabled - disabling simple TX path";
550         const char *str9 = "L3FWD: Invalid packet length";
551         const char *str10 = "L3FWD: Set jumbo frame max packet len to ";
552         const char *str11 = "L3FWD: Invalid hash entry number";
553         const char *str12 =
554                 "L3FWD: LPM and EM are mutually exclusive, select only one";
555         const char *str13 = "L3FWD: LPM or EM none selected, default LPM on";
556
557         while ((opt = getopt_long(argc, argvopt, short_options,
558                                 lgopts, &option_index)) != EOF) {
559
560                 switch (opt) {
561                 /* portmask */
562                 case 'p':
563                         enabled_port_mask = parse_portmask(optarg);
564                         if (enabled_port_mask == 0) {
565                                 printf("%s\n", str1);
566                                 print_usage(prgname);
567                                 return -1;
568                         }
569                         break;
570
571                 case 'P':
572                         printf("%s\n", str2);
573                         promiscuous_on = 1;
574                         break;
575
576                 case 'E':
577                         printf("%s\n", str3);
578                         l3fwd_em_on = 1;
579                         break;
580
581                 case 'L':
582                         printf("%s\n", str4);
583                         l3fwd_lpm_on = 1;
584                         break;
585
586                 /* long options */
587                 case CMD_LINE_OPT_CONFIG_NUM:
588                         ret = parse_config(optarg);
589                         if (ret) {
590                                 printf("%s\n", str5);
591                                 print_usage(prgname);
592                                 return -1;
593                         }
594                         break;
595
596                 case CMD_LINE_OPT_ETH_DEST_NUM:
597                         parse_eth_dest(optarg);
598                         break;
599
600                 case CMD_LINE_OPT_NO_NUMA_NUM:
601                         printf("%s\n", str6);
602                         numa_on = 0;
603                         break;
604
605                 case CMD_LINE_OPT_IPV6_NUM:
606                         printf("%sn", str7);
607                         ipv6 = 1;
608                         break;
609
610                 case CMD_LINE_OPT_ENABLE_JUMBO_NUM: {
611                         struct option lenopts = {
612                                 "max-pkt-len", required_argument, 0, 0
613                         };
614
615                         printf("%s\n", str8);
616                         port_conf.rxmode.jumbo_frame = 1;
617
618                         /*
619                          * if no max-pkt-len set, use the default
620                          * value ETHER_MAX_LEN.
621                          */
622                         if (getopt_long(argc, argvopt, "",
623                                         &lenopts, &option_index) == 0) {
624                                 ret = parse_max_pkt_len(optarg);
625                                 if ((ret < 64) ||
626                                         (ret > MAX_JUMBO_PKT_LEN)) {
627                                         printf("%s\n", str9);
628                                         print_usage(prgname);
629                                         return -1;
630                                 }
631                                 port_conf.rxmode.max_rx_pkt_len = ret;
632                         }
633                         printf("%s %u\n", str10,
634                                 (unsigned int)port_conf.rxmode.max_rx_pkt_len);
635                         break;
636                 }
637
638                 case CMD_LINE_OPT_HASH_ENTRY_NUM_NUM:
639                         ret = parse_hash_entry_number(optarg);
640                         if ((ret > 0) && (ret <= L3FWD_HASH_ENTRIES)) {
641                                 hash_entry_number = ret;
642                         } else {
643                                 printf("%s\n", str11);
644                                 print_usage(prgname);
645                                 return -1;
646                         }
647                         break;
648
649                 case CMD_LINE_OPT_PARSE_PTYPE_NUM:
650                         printf("soft parse-ptype is enabled\n");
651                         parse_ptype = 1;
652                         break;
653
654                 default:
655                         print_usage(prgname);
656                         return -1;
657                 }
658         }
659
660         /* If both LPM and EM are selected, return error. */
661         if (l3fwd_lpm_on && l3fwd_em_on) {
662                 printf("%s\n", str12);
663                 return -1;
664         }
665
666         /*
667          * Nothing is selected, pick longest-prefix match
668          * as default match.
669          */
670         if (!l3fwd_lpm_on && !l3fwd_em_on) {
671                 l3fwd_lpm_on = 1;
672                 printf("%s\n", str13);
673         }
674
675         /*
676          * ipv6 and hash flags are valid only for
677          * exact macth, reset them to default for
678          * longest-prefix match.
679          */
680         if (l3fwd_lpm_on) {
681                 ipv6 = 0;
682                 hash_entry_number = HASH_ENTRY_NUMBER_DEFAULT;
683         }
684
685         if (optind >= 0)
686                 argv[optind-1] = prgname;
687
688         ret = optind-1;
689         optind = 1; /* reset getopt lib */
690         return ret;
691 }
692
693 static void
694 print_ethaddr(const char *name, const struct ether_addr *eth_addr)
695 {
696         char buf[ETHER_ADDR_FMT_SIZE];
697         ether_format_addr(buf, ETHER_ADDR_FMT_SIZE, eth_addr);
698         printf("%s%s", name, buf);
699 }
700
701 static int
702 init_mem(unsigned nb_mbuf)
703 {
704         struct lcore_conf *qconf;
705         int socketid;
706         unsigned lcore_id;
707         char s[64];
708
709         for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
710                 if (rte_lcore_is_enabled(lcore_id) == 0)
711                         continue;
712
713                 if (numa_on)
714                         socketid = rte_lcore_to_socket_id(lcore_id);
715                 else
716                         socketid = 0;
717
718                 if (socketid >= NB_SOCKETS) {
719                         rte_exit(EXIT_FAILURE,
720                                 "Socket %d of lcore %u is out of range %d\n",
721                                 socketid, lcore_id, NB_SOCKETS);
722                 }
723
724                 if (pktmbuf_pool[socketid] == NULL) {
725                         snprintf(s, sizeof(s), "mbuf_pool_%d", socketid);
726                         pktmbuf_pool[socketid] =
727                                 rte_pktmbuf_pool_create(s, nb_mbuf,
728                                         MEMPOOL_CACHE_SIZE, 0,
729                                         RTE_MBUF_DEFAULT_BUF_SIZE, socketid);
730                         if (pktmbuf_pool[socketid] == NULL)
731                                 rte_exit(EXIT_FAILURE,
732                                         "Cannot init mbuf pool on socket %d\n",
733                                         socketid);
734                         else
735                                 printf("Allocated mbuf pool on socket %d\n",
736                                         socketid);
737
738                         /* Setup either LPM or EM(f.e Hash).  */
739                         l3fwd_lkp.setup(socketid);
740                 }
741                 qconf = &lcore_conf[lcore_id];
742                 qconf->ipv4_lookup_struct =
743                         l3fwd_lkp.get_ipv4_lookup_struct(socketid);
744                 qconf->ipv6_lookup_struct =
745                         l3fwd_lkp.get_ipv6_lookup_struct(socketid);
746         }
747         return 0;
748 }
749
750 /* Check the link status of all ports in up to 9s, and print them finally */
751 static void
752 check_all_ports_link_status(uint16_t port_num, uint32_t port_mask)
753 {
754 #define CHECK_INTERVAL 100 /* 100ms */
755 #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */
756         uint16_t portid;
757         uint8_t count, all_ports_up, print_flag = 0;
758         struct rte_eth_link link;
759
760         printf("\nChecking link status");
761         fflush(stdout);
762         for (count = 0; count <= MAX_CHECK_TIME; count++) {
763                 if (force_quit)
764                         return;
765                 all_ports_up = 1;
766                 for (portid = 0; portid < port_num; portid++) {
767                         if (force_quit)
768                                 return;
769                         if ((port_mask & (1 << portid)) == 0)
770                                 continue;
771                         memset(&link, 0, sizeof(link));
772                         rte_eth_link_get_nowait(portid, &link);
773                         /* print link status if flag set */
774                         if (print_flag == 1) {
775                                 if (link.link_status)
776                                         printf(
777                                         "Port%d Link Up. Speed %u Mbps -%s\n",
778                                                 portid, link.link_speed,
779                                 (link.link_duplex == ETH_LINK_FULL_DUPLEX) ?
780                                         ("full-duplex") : ("half-duplex\n"));
781                                 else
782                                         printf("Port %d Link Down\n", portid);
783                                 continue;
784                         }
785                         /* clear all_ports_up flag if any link down */
786                         if (link.link_status == ETH_LINK_DOWN) {
787                                 all_ports_up = 0;
788                                 break;
789                         }
790                 }
791                 /* after finally printing all link status, get out */
792                 if (print_flag == 1)
793                         break;
794
795                 if (all_ports_up == 0) {
796                         printf(".");
797                         fflush(stdout);
798                         rte_delay_ms(CHECK_INTERVAL);
799                 }
800
801                 /* set the print_flag if all ports up or timeout */
802                 if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) {
803                         print_flag = 1;
804                         printf("done\n");
805                 }
806         }
807 }
808
809 static void
810 signal_handler(int signum)
811 {
812         if (signum == SIGINT || signum == SIGTERM) {
813                 printf("\n\nSignal %d received, preparing to exit...\n",
814                                 signum);
815                 force_quit = true;
816         }
817 }
818
819 static int
820 prepare_ptype_parser(uint16_t portid, uint16_t queueid)
821 {
822         if (parse_ptype) {
823                 printf("Port %d: softly parse packet type info\n", portid);
824                 if (rte_eth_add_rx_callback(portid, queueid,
825                                             l3fwd_lkp.cb_parse_ptype,
826                                             NULL))
827                         return 1;
828
829                 printf("Failed to add rx callback: port=%d\n", portid);
830                 return 0;
831         }
832
833         if (l3fwd_lkp.check_ptype(portid))
834                 return 1;
835
836         printf("port %d cannot parse packet type, please add --%s\n",
837                portid, CMD_LINE_OPT_PARSE_PTYPE);
838         return 0;
839 }
840
841 int
842 main(int argc, char **argv)
843 {
844         struct lcore_conf *qconf;
845         struct rte_eth_dev_info dev_info;
846         struct rte_eth_txconf *txconf;
847         int ret;
848         unsigned nb_ports;
849         uint16_t queueid, portid;
850         unsigned lcore_id;
851         uint32_t n_tx_queue, nb_lcores;
852         uint8_t nb_rx_queue, queue, socketid;
853
854         /* init EAL */
855         ret = rte_eal_init(argc, argv);
856         if (ret < 0)
857                 rte_exit(EXIT_FAILURE, "Invalid EAL parameters\n");
858         argc -= ret;
859         argv += ret;
860
861         force_quit = false;
862         signal(SIGINT, signal_handler);
863         signal(SIGTERM, signal_handler);
864
865         /* pre-init dst MACs for all ports to 02:00:00:00:00:xx */
866         for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) {
867                 dest_eth_addr[portid] =
868                         ETHER_LOCAL_ADMIN_ADDR + ((uint64_t)portid << 40);
869                 *(uint64_t *)(val_eth + portid) = dest_eth_addr[portid];
870         }
871
872         /* parse application arguments (after the EAL ones) */
873         ret = parse_args(argc, argv);
874         if (ret < 0)
875                 rte_exit(EXIT_FAILURE, "Invalid L3FWD parameters\n");
876
877         if (check_lcore_params() < 0)
878                 rte_exit(EXIT_FAILURE, "check_lcore_params failed\n");
879
880         ret = init_lcore_rx_queues();
881         if (ret < 0)
882                 rte_exit(EXIT_FAILURE, "init_lcore_rx_queues failed\n");
883
884         nb_ports = rte_eth_dev_count();
885
886         if (check_port_config(nb_ports) < 0)
887                 rte_exit(EXIT_FAILURE, "check_port_config failed\n");
888
889         nb_lcores = rte_lcore_count();
890
891         /* Setup function pointers for lookup method. */
892         setup_l3fwd_lookup_tables();
893
894         /* initialize all ports */
895         for (portid = 0; portid < nb_ports; portid++) {
896                 /* skip ports that are not enabled */
897                 if ((enabled_port_mask & (1 << portid)) == 0) {
898                         printf("\nSkipping disabled port %d\n", portid);
899                         continue;
900                 }
901
902                 /* init port */
903                 printf("Initializing port %d ... ", portid );
904                 fflush(stdout);
905
906                 nb_rx_queue = get_port_n_rx_queues(portid);
907                 n_tx_queue = nb_lcores;
908                 if (n_tx_queue > MAX_TX_QUEUE_PER_PORT)
909                         n_tx_queue = MAX_TX_QUEUE_PER_PORT;
910                 printf("Creating queues: nb_rxq=%d nb_txq=%u... ",
911                         nb_rx_queue, (unsigned)n_tx_queue );
912                 ret = rte_eth_dev_configure(portid, nb_rx_queue,
913                                         (uint16_t)n_tx_queue, &port_conf);
914                 if (ret < 0)
915                         rte_exit(EXIT_FAILURE,
916                                 "Cannot configure device: err=%d, port=%d\n",
917                                 ret, portid);
918
919                 ret = rte_eth_dev_adjust_nb_rx_tx_desc(portid, &nb_rxd,
920                                                        &nb_txd);
921                 if (ret < 0)
922                         rte_exit(EXIT_FAILURE,
923                                  "Cannot adjust number of descriptors: err=%d, "
924                                  "port=%d\n", ret, portid);
925
926                 rte_eth_macaddr_get(portid, &ports_eth_addr[portid]);
927                 print_ethaddr(" Address:", &ports_eth_addr[portid]);
928                 printf(", ");
929                 print_ethaddr("Destination:",
930                         (const struct ether_addr *)&dest_eth_addr[portid]);
931                 printf(", ");
932
933                 /*
934                  * prepare src MACs for each port.
935                  */
936                 ether_addr_copy(&ports_eth_addr[portid],
937                         (struct ether_addr *)(val_eth + portid) + 1);
938
939                 /* init memory */
940                 ret = init_mem(NB_MBUF);
941                 if (ret < 0)
942                         rte_exit(EXIT_FAILURE, "init_mem failed\n");
943
944                 /* init one TX queue per couple (lcore,port) */
945                 queueid = 0;
946                 for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
947                         if (rte_lcore_is_enabled(lcore_id) == 0)
948                                 continue;
949
950                         if (numa_on)
951                                 socketid =
952                                 (uint8_t)rte_lcore_to_socket_id(lcore_id);
953                         else
954                                 socketid = 0;
955
956                         printf("txq=%u,%d,%d ", lcore_id, queueid, socketid);
957                         fflush(stdout);
958
959                         rte_eth_dev_info_get(portid, &dev_info);
960                         txconf = &dev_info.default_txconf;
961                         if (port_conf.rxmode.jumbo_frame)
962                                 txconf->txq_flags = 0;
963                         ret = rte_eth_tx_queue_setup(portid, queueid, nb_txd,
964                                                      socketid, txconf);
965                         if (ret < 0)
966                                 rte_exit(EXIT_FAILURE,
967                                         "rte_eth_tx_queue_setup: err=%d, "
968                                         "port=%d\n", ret, portid);
969
970                         qconf = &lcore_conf[lcore_id];
971                         qconf->tx_queue_id[portid] = queueid;
972                         queueid++;
973
974                         qconf->tx_port_id[qconf->n_tx_port] = portid;
975                         qconf->n_tx_port++;
976                 }
977                 printf("\n");
978         }
979
980         for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
981                 if (rte_lcore_is_enabled(lcore_id) == 0)
982                         continue;
983                 qconf = &lcore_conf[lcore_id];
984                 printf("\nInitializing rx queues on lcore %u ... ", lcore_id );
985                 fflush(stdout);
986                 /* init RX queues */
987                 for(queue = 0; queue < qconf->n_rx_queue; ++queue) {
988                         portid = qconf->rx_queue_list[queue].port_id;
989                         queueid = qconf->rx_queue_list[queue].queue_id;
990
991                         if (numa_on)
992                                 socketid =
993                                 (uint8_t)rte_lcore_to_socket_id(lcore_id);
994                         else
995                                 socketid = 0;
996
997                         printf("rxq=%d,%d,%d ", portid, queueid, socketid);
998                         fflush(stdout);
999
1000                         ret = rte_eth_rx_queue_setup(portid, queueid, nb_rxd,
1001                                         socketid,
1002                                         NULL,
1003                                         pktmbuf_pool[socketid]);
1004                         if (ret < 0)
1005                                 rte_exit(EXIT_FAILURE,
1006                                 "rte_eth_rx_queue_setup: err=%d, port=%d\n",
1007                                 ret, portid);
1008                 }
1009         }
1010
1011         printf("\n");
1012
1013         /* start ports */
1014         for (portid = 0; portid < nb_ports; portid++) {
1015                 if ((enabled_port_mask & (1 << portid)) == 0) {
1016                         continue;
1017                 }
1018                 /* Start device */
1019                 ret = rte_eth_dev_start(portid);
1020                 if (ret < 0)
1021                         rte_exit(EXIT_FAILURE,
1022                                 "rte_eth_dev_start: err=%d, port=%d\n",
1023                                 ret, portid);
1024
1025                 /*
1026                  * If enabled, put device in promiscuous mode.
1027                  * This allows IO forwarding mode to forward packets
1028                  * to itself through 2 cross-connected  ports of the
1029                  * target machine.
1030                  */
1031                 if (promiscuous_on)
1032                         rte_eth_promiscuous_enable(portid);
1033         }
1034
1035         printf("\n");
1036
1037         for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
1038                 if (rte_lcore_is_enabled(lcore_id) == 0)
1039                         continue;
1040                 qconf = &lcore_conf[lcore_id];
1041                 for (queue = 0; queue < qconf->n_rx_queue; ++queue) {
1042                         portid = qconf->rx_queue_list[queue].port_id;
1043                         queueid = qconf->rx_queue_list[queue].queue_id;
1044                         if (prepare_ptype_parser(portid, queueid) == 0)
1045                                 rte_exit(EXIT_FAILURE, "ptype check fails\n");
1046                 }
1047         }
1048
1049
1050         check_all_ports_link_status(nb_ports, enabled_port_mask);
1051
1052         ret = 0;
1053         /* launch per-lcore init on every lcore */
1054         rte_eal_mp_remote_launch(l3fwd_lkp.main_loop, NULL, CALL_MASTER);
1055         RTE_LCORE_FOREACH_SLAVE(lcore_id) {
1056                 if (rte_eal_wait_lcore(lcore_id) < 0) {
1057                         ret = -1;
1058                         break;
1059                 }
1060         }
1061
1062         /* stop ports */
1063         for (portid = 0; portid < nb_ports; portid++) {
1064                 if ((enabled_port_mask & (1 << portid)) == 0)
1065                         continue;
1066                 printf("Closing port %d...", portid);
1067                 rte_eth_dev_stop(portid);
1068                 rte_eth_dev_close(portid);
1069                 printf(" Done\n");
1070         }
1071         printf("Bye...\n");
1072
1073         return ret;
1074 }