remove useless memzone includes
[dpdk.git] / examples / l2fwd-keepalive / 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 <string.h>
37 #include <stdint.h>
38 #include <inttypes.h>
39 #include <sys/types.h>
40 #include <sys/queue.h>
41 #include <netinet/in.h>
42 #include <setjmp.h>
43 #include <stdarg.h>
44 #include <ctype.h>
45 #include <errno.h>
46 #include <getopt.h>
47 #include <signal.h>
48
49 #include <rte_common.h>
50 #include <rte_log.h>
51 #include <rte_malloc.h>
52 #include <rte_memory.h>
53 #include <rte_memcpy.h>
54 #include <rte_eal.h>
55 #include <rte_launch.h>
56 #include <rte_atomic.h>
57 #include <rte_cycles.h>
58 #include <rte_prefetch.h>
59 #include <rte_lcore.h>
60 #include <rte_per_lcore.h>
61 #include <rte_branch_prediction.h>
62 #include <rte_interrupts.h>
63 #include <rte_pci.h>
64 #include <rte_random.h>
65 #include <rte_debug.h>
66 #include <rte_ether.h>
67 #include <rte_ethdev.h>
68 #include <rte_mempool.h>
69 #include <rte_mbuf.h>
70 #include <rte_timer.h>
71 #include <rte_keepalive.h>
72
73 #include "shm.h"
74
75 #define RTE_LOGTYPE_L2FWD RTE_LOGTYPE_USER1
76
77 #define NB_MBUF   8192
78
79 #define MAX_PKT_BURST 32
80 #define BURST_TX_DRAIN_US 100 /* TX drain every ~100us */
81
82 /*
83  * Configurable number of RX/TX ring descriptors
84  */
85 #define RTE_TEST_RX_DESC_DEFAULT 128
86 #define RTE_TEST_TX_DESC_DEFAULT 512
87 static uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT;
88 static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT;
89
90 /* ethernet addresses of ports */
91 static struct ether_addr l2fwd_ports_eth_addr[RTE_MAX_ETHPORTS];
92
93 /* mask of enabled ports */
94 static uint32_t l2fwd_enabled_port_mask;
95
96 /* list of enabled ports */
97 static uint32_t l2fwd_dst_ports[RTE_MAX_ETHPORTS];
98
99 static unsigned int l2fwd_rx_queue_per_lcore = 1;
100
101 #define MAX_RX_QUEUE_PER_LCORE 16
102 #define MAX_TX_QUEUE_PER_PORT 16
103 struct lcore_queue_conf {
104         unsigned n_rx_port;
105         unsigned rx_port_list[MAX_RX_QUEUE_PER_LCORE];
106 } __rte_cache_aligned;
107 struct lcore_queue_conf lcore_queue_conf[RTE_MAX_LCORE];
108
109 struct rte_eth_dev_tx_buffer *tx_buffer[RTE_MAX_ETHPORTS];
110
111 static const struct rte_eth_conf port_conf = {
112         .rxmode = {
113                 .split_hdr_size = 0,
114                 .header_split   = 0, /**< Header Split disabled */
115                 .hw_ip_checksum = 0, /**< IP checksum offload disabled */
116                 .hw_vlan_filter = 0, /**< VLAN filtering disabled */
117                 .jumbo_frame    = 0, /**< Jumbo Frame Support disabled */
118                 .hw_strip_crc   = 1, /**< CRC stripped by hardware */
119         },
120         .txmode = {
121                 .mq_mode = ETH_MQ_TX_NONE,
122         },
123 };
124
125 struct rte_mempool *l2fwd_pktmbuf_pool = NULL;
126
127 /* Per-port statistics struct */
128 struct l2fwd_port_statistics {
129         uint64_t tx;
130         uint64_t rx;
131         uint64_t dropped;
132 } __rte_cache_aligned;
133 struct l2fwd_port_statistics port_statistics[RTE_MAX_ETHPORTS];
134
135 /* A tsc-based timer responsible for triggering statistics printout */
136 #define TIMER_MILLISECOND 1
137 #define MAX_TIMER_PERIOD 86400 /* 1 day max */
138 static int64_t timer_period = 10 * TIMER_MILLISECOND * 1000; /* 10 seconds */
139 static int64_t check_period = 5; /* default check cycle is 5ms */
140
141 /* Keepalive structure */
142 struct rte_keepalive *rte_global_keepalive_info;
143
144 /* Termination signalling */
145 static int terminate_signal_received;
146
147 /* Termination signal handler */
148 static void handle_sigterm(__rte_unused int value)
149 {
150         terminate_signal_received = 1;
151 }
152
153 /* Print out statistics on packets dropped */
154 static void
155 print_stats(__attribute__((unused)) struct rte_timer *ptr_timer,
156         __attribute__((unused)) void *ptr_data)
157 {
158         uint64_t total_packets_dropped, total_packets_tx, total_packets_rx;
159         uint16_t portid;
160
161         total_packets_dropped = 0;
162         total_packets_tx = 0;
163         total_packets_rx = 0;
164
165         const char clr[] = { 27, '[', '2', 'J', '\0' };
166         const char topLeft[] = { 27, '[', '1', ';', '1', 'H', '\0' };
167
168                 /* Clear screen and move to top left */
169         printf("%s%s", clr, topLeft);
170
171         printf("\nPort statistics ====================================");
172
173         for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) {
174                 /* skip disabled ports */
175                 if ((l2fwd_enabled_port_mask & (1 << portid)) == 0)
176                         continue;
177                 printf("\nStatistics for port %u ------------------------------"
178                            "\nPackets sent: %24"PRIu64
179                            "\nPackets received: %20"PRIu64
180                            "\nPackets dropped: %21"PRIu64,
181                            portid,
182                            port_statistics[portid].tx,
183                            port_statistics[portid].rx,
184                            port_statistics[portid].dropped);
185
186                 total_packets_dropped += port_statistics[portid].dropped;
187                 total_packets_tx += port_statistics[portid].tx;
188                 total_packets_rx += port_statistics[portid].rx;
189         }
190         printf("\nAggregate statistics ==============================="
191                    "\nTotal packets sent: %18"PRIu64
192                    "\nTotal packets received: %14"PRIu64
193                    "\nTotal packets dropped: %15"PRIu64,
194                    total_packets_tx,
195                    total_packets_rx,
196                    total_packets_dropped);
197         printf("\n====================================================\n");
198 }
199
200 static void
201 l2fwd_simple_forward(struct rte_mbuf *m, unsigned portid)
202 {
203         struct ether_hdr *eth;
204         void *tmp;
205         int sent;
206         unsigned dst_port;
207         struct rte_eth_dev_tx_buffer *buffer;
208
209         dst_port = l2fwd_dst_ports[portid];
210         eth = rte_pktmbuf_mtod(m, struct ether_hdr *);
211
212         /* 02:00:00:00:00:xx */
213         tmp = &eth->d_addr.addr_bytes[0];
214         *((uint64_t *)tmp) = 0x000000000002 + ((uint64_t)dst_port << 40);
215
216         /* src addr */
217         ether_addr_copy(&l2fwd_ports_eth_addr[dst_port], &eth->s_addr);
218
219         buffer = tx_buffer[dst_port];
220         sent = rte_eth_tx_buffer(dst_port, 0, buffer, m);
221         if (sent)
222                 port_statistics[dst_port].tx += sent;
223 }
224
225 /* main processing loop */
226 static void
227 l2fwd_main_loop(void)
228 {
229         struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
230         struct rte_mbuf *m;
231         int sent;
232         unsigned lcore_id;
233         uint64_t prev_tsc, diff_tsc, cur_tsc;
234         unsigned i, j, portid, nb_rx;
235         struct lcore_queue_conf *qconf;
236         const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1)
237                 / US_PER_S * BURST_TX_DRAIN_US;
238         struct rte_eth_dev_tx_buffer *buffer;
239
240         prev_tsc = 0;
241
242         lcore_id = rte_lcore_id();
243         qconf = &lcore_queue_conf[lcore_id];
244
245         if (qconf->n_rx_port == 0) {
246                 RTE_LOG(INFO, L2FWD, "lcore %u has nothing to do\n", lcore_id);
247                 return;
248         }
249
250         RTE_LOG(INFO, L2FWD, "entering main loop on lcore %u\n", lcore_id);
251
252         for (i = 0; i < qconf->n_rx_port; i++) {
253
254                 portid = qconf->rx_port_list[i];
255                 RTE_LOG(INFO, L2FWD, " -- lcoreid=%u portid=%u\n", lcore_id,
256                         portid);
257         }
258
259         uint64_t tsc_initial = rte_rdtsc();
260         uint64_t tsc_lifetime = (rand()&0x07) * rte_get_tsc_hz();
261
262         while (!terminate_signal_received) {
263                 /* Keepalive heartbeat */
264                 rte_keepalive_mark_alive(rte_global_keepalive_info);
265
266                 cur_tsc = rte_rdtsc();
267
268                 /*
269                  * Die randomly within 7 secs for demo purposes if
270                  * keepalive enabled
271                  */
272                 if (check_period > 0 && cur_tsc - tsc_initial > tsc_lifetime)
273                         break;
274
275                 /*
276                  * TX burst queue drain
277                  */
278                 diff_tsc = cur_tsc - prev_tsc;
279                 if (unlikely(diff_tsc > drain_tsc)) {
280
281                         for (i = 0; i < qconf->n_rx_port; i++) {
282
283                                 portid = l2fwd_dst_ports[qconf->rx_port_list[i]];
284                                 buffer = tx_buffer[portid];
285
286                                 sent = rte_eth_tx_buffer_flush(portid, 0, buffer);
287                                 if (sent)
288                                         port_statistics[portid].tx += sent;
289
290                         }
291
292                         prev_tsc = cur_tsc;
293                 }
294
295                 /*
296                  * Read packet from RX queues
297                  */
298                 for (i = 0; i < qconf->n_rx_port; i++) {
299
300                         portid = qconf->rx_port_list[i];
301                         nb_rx = rte_eth_rx_burst(portid, 0,
302                                                  pkts_burst, MAX_PKT_BURST);
303
304                         port_statistics[portid].rx += nb_rx;
305
306                         for (j = 0; j < nb_rx; j++) {
307                                 m = pkts_burst[j];
308                                 rte_prefetch0(rte_pktmbuf_mtod(m, void *));
309                                 l2fwd_simple_forward(m, portid);
310                         }
311                 }
312         }
313 }
314
315 static int
316 l2fwd_launch_one_lcore(__attribute__((unused)) void *dummy)
317 {
318         l2fwd_main_loop();
319         return 0;
320 }
321
322 /* display usage */
323 static void
324 l2fwd_usage(const char *prgname)
325 {
326         printf("%s [EAL options] -- -p PORTMASK [-q NQ]\n"
327                "  -p PORTMASK: hexadecimal bitmask of ports to configure\n"
328                "  -q NQ: number of queue (=ports) per lcore (default is 1)\n"
329                "  -K PERIOD: Keepalive check period (5 default; 86400 max)\n"
330                    "  -T PERIOD: statistics will be refreshed each PERIOD seconds (0 to disable, 10 default, 86400 maximum)\n",
331                prgname);
332 }
333
334 static int
335 l2fwd_parse_portmask(const char *portmask)
336 {
337         char *end = NULL;
338         unsigned long pm;
339
340         /* parse hexadecimal string */
341         pm = strtoul(portmask, &end, 16);
342         if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0'))
343                 return -1;
344
345         if (pm == 0)
346                 return -1;
347
348         return pm;
349 }
350
351 static unsigned int
352 l2fwd_parse_nqueue(const char *q_arg)
353 {
354         char *end = NULL;
355         unsigned long n;
356
357         /* parse hexadecimal string */
358         n = strtoul(q_arg, &end, 10);
359         if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0'))
360                 return 0;
361         if (n == 0)
362                 return 0;
363         if (n >= MAX_RX_QUEUE_PER_LCORE)
364                 return 0;
365
366         return n;
367 }
368
369 static int
370 l2fwd_parse_timer_period(const char *q_arg)
371 {
372         char *end = NULL;
373         int n;
374
375         /* parse number string */
376         n = strtol(q_arg, &end, 10);
377         if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0'))
378                 return -1;
379         if (n >= MAX_TIMER_PERIOD)
380                 return -1;
381
382         return n;
383 }
384
385 static int
386 l2fwd_parse_check_period(const char *q_arg)
387 {
388         char *end = NULL;
389         int n;
390
391         /* parse number string */
392         n = strtol(q_arg, &end, 10);
393         if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0'))
394                 return -1;
395         if (n >= MAX_TIMER_PERIOD)
396                 return -1;
397
398         return n;
399 }
400
401 /* Parse the argument given in the command line of the application */
402 static int
403 l2fwd_parse_args(int argc, char **argv)
404 {
405         int opt, ret;
406         char **argvopt;
407         int option_index;
408         char *prgname = argv[0];
409         static struct option lgopts[] = {
410                 {NULL, 0, 0, 0}
411         };
412
413         argvopt = argv;
414
415         while ((opt = getopt_long(argc, argvopt, "p:q:T:K:",
416                                   lgopts, &option_index)) != EOF) {
417
418                 switch (opt) {
419                 /* portmask */
420                 case 'p':
421                         l2fwd_enabled_port_mask = l2fwd_parse_portmask(optarg);
422                         if (l2fwd_enabled_port_mask == 0) {
423                                 printf("invalid portmask\n");
424                                 l2fwd_usage(prgname);
425                                 return -1;
426                         }
427                         break;
428
429                 /* nqueue */
430                 case 'q':
431                         l2fwd_rx_queue_per_lcore = l2fwd_parse_nqueue(optarg);
432                         if (l2fwd_rx_queue_per_lcore == 0) {
433                                 printf("invalid queue number\n");
434                                 l2fwd_usage(prgname);
435                                 return -1;
436                         }
437                         break;
438
439                 /* timer period */
440                 case 'T':
441                         timer_period = l2fwd_parse_timer_period(optarg)
442                                 * (int64_t)(1000 * TIMER_MILLISECOND);
443                         if (timer_period < 0) {
444                                 printf("invalid timer period\n");
445                                 l2fwd_usage(prgname);
446                                 return -1;
447                         }
448                         break;
449
450                 /* Check period */
451                 case 'K':
452                         check_period = l2fwd_parse_check_period(optarg);
453                         if (check_period < 0) {
454                                 printf("invalid check period\n");
455                                 l2fwd_usage(prgname);
456                                 return -1;
457                         }
458                         break;
459
460                 /* long options */
461                 case 0:
462                         l2fwd_usage(prgname);
463                         return -1;
464
465                 default:
466                         l2fwd_usage(prgname);
467                         return -1;
468                 }
469         }
470
471         if (optind >= 0)
472                 argv[optind-1] = prgname;
473
474         ret = optind-1;
475         optind = 1; /* reset getopt lib */
476         return ret;
477 }
478
479 /* Check the link status of all ports in up to 9s, and print them finally */
480 static void
481 check_all_ports_link_status(uint16_t port_num, uint32_t port_mask)
482 {
483 #define CHECK_INTERVAL 100 /* 100ms */
484 #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */
485         uint16_t portid;
486         uint8_t count, all_ports_up, print_flag = 0;
487         struct rte_eth_link link;
488
489         printf("\nChecking link status");
490         fflush(stdout);
491         for (count = 0; count <= MAX_CHECK_TIME; count++) {
492                 all_ports_up = 1;
493                 for (portid = 0; portid < port_num; portid++) {
494                         if ((port_mask & (1 << portid)) == 0)
495                                 continue;
496                         memset(&link, 0, sizeof(link));
497                         rte_eth_link_get_nowait(portid, &link);
498                         /* print link status if flag set */
499                         if (print_flag == 1) {
500                                 if (link.link_status)
501                                         printf(
502                                         "Port%d Link Up. Speed %u Mbps - %s\n",
503                                                 portid, link.link_speed,
504                                 (link.link_duplex == ETH_LINK_FULL_DUPLEX) ?
505                                         ("full-duplex") : ("half-duplex\n"));
506                                 else
507                                         printf("Port %d Link Down\n", portid);
508                                 continue;
509                         }
510                         /* clear all_ports_up flag if any link down */
511                         if (link.link_status == ETH_LINK_DOWN) {
512                                 all_ports_up = 0;
513                                 break;
514                         }
515                 }
516                 /* after finally printing all link status, get out */
517                 if (print_flag == 1)
518                         break;
519
520                 if (all_ports_up == 0) {
521                         printf(".");
522                         fflush(stdout);
523                         rte_delay_ms(CHECK_INTERVAL);
524                 }
525
526                 /* set the print_flag if all ports up or timeout */
527                 if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) {
528                         print_flag = 1;
529                         printf("done\n");
530                 }
531         }
532 }
533
534 static void
535 dead_core(__rte_unused void *ptr_data, const int id_core)
536 {
537         if (terminate_signal_received)
538                 return;
539         printf("Dead core %i - restarting..\n", id_core);
540         if (rte_eal_get_lcore_state(id_core) == FINISHED) {
541                 rte_eal_wait_lcore(id_core);
542                 rte_eal_remote_launch(l2fwd_launch_one_lcore, NULL, id_core);
543         } else {
544                 printf("..false positive!\n");
545         }
546 }
547
548 static void
549 relay_core_state(void *ptr_data, const int id_core,
550         const enum rte_keepalive_state core_state, uint64_t last_alive)
551 {
552         rte_keepalive_relayed_state((struct rte_keepalive_shm *)ptr_data,
553                 id_core, core_state, last_alive);
554 }
555
556 int
557 main(int argc, char **argv)
558 {
559         struct lcore_queue_conf *qconf;
560         struct rte_eth_dev_info dev_info;
561         int ret;
562         uint16_t nb_ports;
563         uint16_t nb_ports_available;
564         uint16_t portid, last_port;
565         unsigned lcore_id, rx_lcore_id;
566         unsigned nb_ports_in_mask = 0;
567         struct sigaction signal_handler;
568         struct rte_keepalive_shm *ka_shm;
569
570         memset(&signal_handler, 0, sizeof(signal_handler));
571         terminate_signal_received = 0;
572         signal_handler.sa_handler = &handle_sigterm;
573         if (sigaction(SIGINT, &signal_handler, NULL) == -1 ||
574                         sigaction(SIGTERM, &signal_handler, NULL) == -1)
575                 rte_exit(EXIT_FAILURE, "SIGNAL\n");
576
577
578         /* init EAL */
579         ret = rte_eal_init(argc, argv);
580         if (ret < 0)
581                 rte_exit(EXIT_FAILURE, "Invalid EAL arguments\n");
582         argc -= ret;
583         argv += ret;
584
585         l2fwd_enabled_port_mask = 0;
586
587         /* parse application arguments (after the EAL ones) */
588         ret = l2fwd_parse_args(argc, argv);
589         if (ret < 0)
590                 rte_exit(EXIT_FAILURE, "Invalid L2FWD arguments\n");
591
592         /* create the mbuf pool */
593         l2fwd_pktmbuf_pool = rte_pktmbuf_pool_create("mbuf_pool", NB_MBUF, 32,
594                 0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id());
595         if (l2fwd_pktmbuf_pool == NULL)
596                 rte_exit(EXIT_FAILURE, "Cannot init mbuf pool\n");
597
598         nb_ports = rte_eth_dev_count();
599         if (nb_ports == 0)
600                 rte_exit(EXIT_FAILURE, "No Ethernet ports - bye\n");
601
602         /* reset l2fwd_dst_ports */
603         for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++)
604                 l2fwd_dst_ports[portid] = 0;
605         last_port = 0;
606
607         /*
608          * Each logical core is assigned a dedicated TX queue on each port.
609          */
610         for (portid = 0; portid < nb_ports; portid++) {
611                 /* skip ports that are not enabled */
612                 if ((l2fwd_enabled_port_mask & (1 << portid)) == 0)
613                         continue;
614
615                 if (nb_ports_in_mask % 2) {
616                         l2fwd_dst_ports[portid] = last_port;
617                         l2fwd_dst_ports[last_port] = portid;
618                 } else
619                         last_port = portid;
620
621                 nb_ports_in_mask++;
622
623                 rte_eth_dev_info_get(portid, &dev_info);
624         }
625         if (nb_ports_in_mask % 2) {
626                 printf("Notice: odd number of ports in portmask.\n");
627                 l2fwd_dst_ports[last_port] = last_port;
628         }
629
630         rx_lcore_id = 1;
631         qconf = NULL;
632
633         /* Initialize the port/queue configuration of each logical core */
634         for (portid = 0; portid < nb_ports; portid++) {
635                 /* skip ports that are not enabled */
636                 if ((l2fwd_enabled_port_mask & (1 << portid)) == 0)
637                         continue;
638
639                 /* get the lcore_id for this port */
640                 while (rte_lcore_is_enabled(rx_lcore_id) == 0 ||
641                        lcore_queue_conf[rx_lcore_id].n_rx_port ==
642                        l2fwd_rx_queue_per_lcore) {
643                         rx_lcore_id++;
644                         if (rx_lcore_id >= RTE_MAX_LCORE)
645                                 rte_exit(EXIT_FAILURE, "Not enough cores\n");
646                 }
647
648                 if (qconf != &lcore_queue_conf[rx_lcore_id])
649                         /* Assigned a new logical core in the loop above. */
650                         qconf = &lcore_queue_conf[rx_lcore_id];
651
652                 qconf->rx_port_list[qconf->n_rx_port] = portid;
653                 qconf->n_rx_port++;
654                 printf("Lcore %u: RX port %u\n",
655                         rx_lcore_id, portid);
656         }
657
658         nb_ports_available = nb_ports;
659
660         /* Initialise each port */
661         for (portid = 0; portid < nb_ports; portid++) {
662                 /* skip ports that are not enabled */
663                 if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) {
664                         printf("Skipping disabled port %u\n", portid);
665                         nb_ports_available--;
666                         continue;
667                 }
668                 /* init port */
669                 printf("Initializing port %u... ", portid);
670                 fflush(stdout);
671                 ret = rte_eth_dev_configure(portid, 1, 1, &port_conf);
672                 if (ret < 0)
673                         rte_exit(EXIT_FAILURE,
674                                 "Cannot configure device: err=%d, port=%u\n",
675                                 ret, portid);
676
677                 ret = rte_eth_dev_adjust_nb_rx_tx_desc(portid, &nb_rxd,
678                                                        &nb_txd);
679                 if (ret < 0)
680                         rte_exit(EXIT_FAILURE,
681                                 "Cannot adjust number of descriptors: err=%d, port=%u\n",
682                                 ret, portid);
683
684                 rte_eth_macaddr_get(portid, &l2fwd_ports_eth_addr[portid]);
685
686                 /* init one RX queue */
687                 fflush(stdout);
688                 ret = rte_eth_rx_queue_setup(portid, 0, nb_rxd,
689                                              rte_eth_dev_socket_id(portid),
690                                              NULL,
691                                              l2fwd_pktmbuf_pool);
692                 if (ret < 0)
693                         rte_exit(EXIT_FAILURE,
694                                 "rte_eth_rx_queue_setup:err=%d, port=%u\n",
695                                 ret, portid);
696
697                 /* init one TX queue on each port */
698                 fflush(stdout);
699                 ret = rte_eth_tx_queue_setup(portid, 0, nb_txd,
700                                 rte_eth_dev_socket_id(portid),
701                                 NULL);
702                 if (ret < 0)
703                         rte_exit(EXIT_FAILURE,
704                                 "rte_eth_tx_queue_setup:err=%d, port=%u\n",
705                                 ret, portid);
706
707                 /* Initialize TX buffers */
708                 tx_buffer[portid] = rte_zmalloc_socket("tx_buffer",
709                                 RTE_ETH_TX_BUFFER_SIZE(MAX_PKT_BURST), 0,
710                                 rte_eth_dev_socket_id(portid));
711                 if (tx_buffer[portid] == NULL)
712                         rte_exit(EXIT_FAILURE, "Cannot allocate buffer for tx on port %u\n",
713                                                 portid);
714
715                 rte_eth_tx_buffer_init(tx_buffer[portid], MAX_PKT_BURST);
716
717                 ret = rte_eth_tx_buffer_set_err_callback(tx_buffer[portid],
718                                 rte_eth_tx_buffer_count_callback,
719                                 &port_statistics[portid].dropped);
720                 if (ret < 0)
721                         rte_exit(EXIT_FAILURE,
722                         "Cannot set error callback for tx buffer on port %u\n",
723                                  portid);
724
725                 /* Start device */
726                 ret = rte_eth_dev_start(portid);
727                 if (ret < 0)
728                         rte_exit(EXIT_FAILURE,
729                                 "rte_eth_dev_start:err=%d, port=%u\n",
730                                   ret, portid);
731
732                 rte_eth_promiscuous_enable(portid);
733
734                 printf("Port %u, MAC address: "
735                         "%02X:%02X:%02X:%02X:%02X:%02X\n\n",
736                         portid,
737                         l2fwd_ports_eth_addr[portid].addr_bytes[0],
738                         l2fwd_ports_eth_addr[portid].addr_bytes[1],
739                         l2fwd_ports_eth_addr[portid].addr_bytes[2],
740                         l2fwd_ports_eth_addr[portid].addr_bytes[3],
741                         l2fwd_ports_eth_addr[portid].addr_bytes[4],
742                         l2fwd_ports_eth_addr[portid].addr_bytes[5]);
743
744                 /* initialize port stats */
745                 memset(&port_statistics, 0, sizeof(port_statistics));
746         }
747
748         if (!nb_ports_available) {
749                 rte_exit(EXIT_FAILURE,
750                         "All available ports are disabled. Please set portmask.\n");
751         }
752
753         check_all_ports_link_status(nb_ports, l2fwd_enabled_port_mask);
754
755         struct rte_timer hb_timer, stats_timer;
756
757         rte_timer_subsystem_init();
758         rte_timer_init(&stats_timer);
759
760         ka_shm = NULL;
761         if (check_period > 0) {
762                 ka_shm = rte_keepalive_shm_create();
763                 if (ka_shm == NULL)
764                         rte_exit(EXIT_FAILURE,
765                                 "rte_keepalive_shm_create() failed");
766                 rte_global_keepalive_info =
767                         rte_keepalive_create(&dead_core, ka_shm);
768                 if (rte_global_keepalive_info == NULL)
769                         rte_exit(EXIT_FAILURE, "init_keep_alive() failed");
770                 rte_keepalive_register_relay_callback(rte_global_keepalive_info,
771                         relay_core_state, ka_shm);
772                 rte_timer_init(&hb_timer);
773                 if (rte_timer_reset(&hb_timer,
774                                 (check_period * rte_get_timer_hz()) / 1000,
775                                 PERIODICAL,
776                                 rte_lcore_id(),
777                                 (void(*)(struct rte_timer*, void*))
778                                 &rte_keepalive_dispatch_pings,
779                                 rte_global_keepalive_info
780                                 ) != 0 )
781                         rte_exit(EXIT_FAILURE, "Keepalive setup failure.\n");
782         }
783         if (timer_period > 0) {
784                 if (rte_timer_reset(&stats_timer,
785                                 (timer_period * rte_get_timer_hz()) / 1000,
786                                 PERIODICAL,
787                                 rte_lcore_id(),
788                                 &print_stats, NULL
789                                 ) != 0 )
790                         rte_exit(EXIT_FAILURE, "Stats setup failure.\n");
791         }
792         /* launch per-lcore init on every slave lcore */
793         RTE_LCORE_FOREACH_SLAVE(lcore_id) {
794                 struct lcore_queue_conf *qconf = &lcore_queue_conf[lcore_id];
795
796                 if (qconf->n_rx_port == 0)
797                         RTE_LOG(INFO, L2FWD,
798                                 "lcore %u has nothing to do\n",
799                                 lcore_id
800                                 );
801                 else {
802                         rte_eal_remote_launch(
803                                 l2fwd_launch_one_lcore,
804                                 NULL,
805                                 lcore_id
806                                 );
807                         rte_keepalive_register_core(rte_global_keepalive_info,
808                                 lcore_id);
809                 }
810         }
811         while (!terminate_signal_received) {
812                 rte_timer_manage();
813                 rte_delay_ms(5);
814                 }
815
816         RTE_LCORE_FOREACH_SLAVE(lcore_id) {
817                 if (rte_eal_wait_lcore(lcore_id) < 0)
818                         return -1;
819         }
820
821         if (ka_shm != NULL)
822                 rte_keepalive_shm_cleanup(ka_shm);
823         return 0;
824 }