update copyright date to 2013
[dpdk.git] / examples / kni / main.c
1 /*-
2  *   BSD LICENSE
3  * 
4  *   Copyright(c) 2010-2013 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
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <stdint.h>
38 #include <inttypes.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 <netinet/in.h>
46 #include <linux/if.h>
47 #include <linux/if_tun.h>
48 #include <fcntl.h>
49 #include <sys/ioctl.h>
50 #include <unistd.h>
51 #include <signal.h>
52
53 #include <rte_common.h>
54 #include <rte_log.h>
55 #include <rte_memory.h>
56 #include <rte_memcpy.h>
57 #include <rte_memzone.h>
58 #include <rte_tailq.h>
59 #include <rte_eal.h>
60 #include <rte_per_lcore.h>
61 #include <rte_launch.h>
62 #include <rte_atomic.h>
63 #include <rte_lcore.h>
64 #include <rte_branch_prediction.h>
65 #include <rte_interrupts.h>
66 #include <rte_pci.h>
67 #include <rte_debug.h>
68 #include <rte_ether.h>
69 #include <rte_ethdev.h>
70 #include <rte_ring.h>
71 #include <rte_log.h>
72 #include <rte_mempool.h>
73 #include <rte_mbuf.h>
74 #include <rte_string_fns.h>
75 #include <rte_cycles.h>
76 #include <rte_malloc.h>
77 #include <rte_kni.h>
78
79 /* Macros for printing using RTE_LOG */
80 #define RTE_LOGTYPE_APP RTE_LOGTYPE_USER1
81
82 /* NUMA socket to allocate mbuf pool on */
83 #define SOCKET                  0
84
85 /* Max size of a single packet */
86 #define MAX_PACKET_SZ           2048
87
88 /* Number of bytes needed for each mbuf */
89 #define MBUF_SZ \
90         (MAX_PACKET_SZ + sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM)
91
92 /* Number of mbufs in mempool that is created */
93 #define NB_MBUF                 (8192 * 16)
94
95 /* How many packets to attempt to read from NIC in one go */
96 #define PKT_BURST_SZ            32
97
98 /* How many objects (mbufs) to keep in per-lcore mempool cache */
99 #define MEMPOOL_CACHE_SZ        PKT_BURST_SZ
100
101 /* Number of RX ring descriptors */
102 #define NB_RXD                  128
103
104 /* Number of TX ring descriptors */
105 #define NB_TXD                  512
106
107 /* Total octets in ethernet header */
108 #define KNI_ENET_HEADER_SIZE    14
109
110 /* Total octets in the FCS */
111 #define KNI_ENET_FCS_SIZE       4
112
113 /*
114  * RX and TX Prefetch, Host, and Write-back threshold values should be
115  * carefully set for optimal performance. Consult the network
116  * controller's datasheet and supporting DPDK documentation for guidance
117  * on how these parameters should be set.
118  */
119 /* RX ring configuration */
120 static const struct rte_eth_rxconf rx_conf = {
121         .rx_thresh = {
122                 .pthresh = 8,   /* Ring prefetch threshold */
123                 .hthresh = 8,   /* Ring host threshold */
124                 .wthresh = 4,   /* Ring writeback threshold */
125         },
126         .rx_free_thresh = 0,    /* Immediately free RX descriptors */
127 };
128
129 /*
130  * These default values are optimized for use with the Intel(R) 82599 10 GbE
131  * Controller and the DPDK ixgbe PMD. Consider using other values for other
132  * network controllers and/or network drivers.
133  */
134 /* TX ring configuration */
135 static const struct rte_eth_txconf tx_conf = {
136         .tx_thresh = {
137                 .pthresh = 36,  /* Ring prefetch threshold */
138                 .hthresh = 0,   /* Ring host threshold */
139                 .wthresh = 0,   /* Ring writeback threshold */
140         },
141         .tx_free_thresh = 0,    /* Use PMD default values */
142         .tx_rs_thresh = 0,      /* Use PMD default values */
143 };
144
145 /* Options for configuring ethernet port */
146 static struct rte_eth_conf port_conf = {
147         .rxmode = {
148                 .header_split = 0,      /* Header Split disabled */
149                 .hw_ip_checksum = 0,    /* IP checksum offload disabled */
150                 .hw_vlan_filter = 0,    /* VLAN filtering disabled */
151                 .jumbo_frame = 0,       /* Jumbo Frame Support disabled */
152                 .hw_strip_crc = 0,      /* CRC stripped by hardware */
153         },
154         .txmode = {
155                 .mq_mode = ETH_DCB_NONE,
156         },
157 };
158
159 /* Mempool for mbufs */
160 static struct rte_mempool * pktmbuf_pool = NULL;
161
162 /* Mask of enabled ports */
163 static uint32_t ports_mask = 0;
164
165 /* Mask of cores that read from NIC and write to tap */
166 static uint32_t input_cores_mask = 0;
167
168 /* Mask of cores that read from tap and write to NIC */
169 static uint32_t output_cores_mask = 0;
170
171 /* Structure type for recording kni interface specific stats */
172 struct kni_interface_stats {
173         /* number of pkts received from NIC, and sent to KNI */
174         uint64_t rx_packets;
175
176         /* number of pkts received from NIC, but failed to send to KNI */
177         uint64_t rx_dropped;
178
179         /* number of pkts received from KNI, and sent to NIC */
180         uint64_t tx_packets;
181
182         /* number of pkts received from KNI, but failed to send to NIC */
183         uint64_t tx_dropped;
184 };
185
186 /* Structure type for recording port specific information */
187 struct kni_port_info_t {
188         /* lcore id for ingress */
189         unsigned lcore_id_ingress;
190
191         /* lcore id for egress */
192         unsigned lcore_id_egress;
193
194         /* pointer to kni interface */
195         struct rte_kni *kni;
196 };
197
198 /* kni port specific information array*/
199 static struct kni_port_info_t kni_port_info[RTE_MAX_ETHPORTS];
200
201 /* kni device statistics array */
202 static struct kni_interface_stats kni_stats[RTE_MAX_ETHPORTS];
203
204 /* Get the pointer to kni interface */
205 static struct rte_kni * kni_lcore_to_kni(unsigned lcore_id);
206
207 static int kni_change_mtu(uint8_t port_id, unsigned new_mtu);
208 static int kni_config_network_interface(uint8_t port_id, uint8_t if_up);
209
210 static struct rte_kni_ops kni_ops = {
211         .change_mtu = kni_change_mtu,
212         .config_network_if = kni_config_network_interface,
213 };
214
215 /* Print out statistics on packets handled */
216 static void
217 print_stats(void)
218 {
219         uint8_t i;
220
221         printf("\n**KNI example application statistics**\n"
222                "======  ==============  ============  ============  ============  ============\n"
223                " Port    Lcore(RX/TX)    rx_packets    rx_dropped    tx_packets    tx_dropped\n"
224                "------  --------------  ------------  ------------  ------------  ------------\n");
225         for (i = 0; i < RTE_MAX_ETHPORTS; i++) {
226                 if (kni_port_info[i].kni == NULL)
227                         continue;
228
229                 printf("%7d %10u/%2u %13"PRIu64" %13"PRIu64" %13"PRIu64" "
230                                                         "%13"PRIu64"\n", i,
231                                         kni_port_info[i].lcore_id_ingress,
232                                         kni_port_info[i].lcore_id_egress,
233                                                 kni_stats[i].rx_packets,
234                                                 kni_stats[i].rx_dropped,
235                                                 kni_stats[i].tx_packets,
236                                                 kni_stats[i].tx_dropped);
237         }
238         printf("======  ==============  ============  ============  ============  ============\n");
239 }
240
241 /* Custom handling of signals to handle stats */
242 static void
243 signal_handler(int signum)
244 {
245         /* When we receive a USR1 signal, print stats */
246         if (signum == SIGUSR1) {
247                 print_stats();
248         }
249
250         /* When we receive a USR2 signal, reset stats */
251         if (signum == SIGUSR2) {
252                 memset(&kni_stats, 0, sizeof(kni_stats));
253                 printf("\n**Statistics have been reset**\n");
254                 return;
255         }
256 }
257
258 static void
259 kni_burst_free_mbufs(struct rte_mbuf **pkts, unsigned num)
260 {
261         unsigned i;
262
263         if (pkts == NULL)
264                 return;
265
266         for (i = 0; i < num; i++) {
267                 rte_pktmbuf_free(pkts[i]);
268                 pkts[i] = NULL;
269         }
270 }
271
272 /**
273  * Interface to burst rx and enqueue mbufs into rx_q
274  */
275 static void
276 kni_ingress(struct rte_kni *kni)
277 {
278         uint8_t port_id = rte_kni_get_port_id(kni);
279         unsigned nb_rx, num;
280         struct rte_mbuf *pkts_burst[PKT_BURST_SZ];
281
282         if (kni == NULL || port_id >= RTE_MAX_ETHPORTS)
283                 return;
284
285         /* Burst rx from eth */
286         nb_rx = rte_eth_rx_burst(port_id, 0, pkts_burst, PKT_BURST_SZ);
287         if (nb_rx > PKT_BURST_SZ) {
288                 RTE_LOG(ERR, APP, "Error receiving from eth\n");
289                 return;
290         }
291
292         /* Burst tx to kni */
293         num = rte_kni_tx_burst(kni, pkts_burst, nb_rx);
294         kni_stats[port_id].rx_packets += num;
295
296         if (unlikely(num < nb_rx)) {
297                 /* Free mbufs not tx to kni interface */
298                 kni_burst_free_mbufs(&pkts_burst[num], nb_rx - num);
299                 kni_stats[port_id].rx_dropped += nb_rx - num;
300         }
301 }
302
303 /**
304  * Interface to dequeue mbufs from tx_q and burst tx
305  */
306 static void
307 kni_egress(struct rte_kni *kni)
308 {
309         uint8_t port_id = rte_kni_get_port_id(kni);;
310         unsigned nb_tx, num;
311         struct rte_mbuf *pkts_burst[PKT_BURST_SZ];
312
313         if (kni == NULL || port_id >= RTE_MAX_ETHPORTS)
314                 return;
315
316         /* Burst rx from kni */
317         num = rte_kni_rx_burst(kni, pkts_burst, PKT_BURST_SZ);
318         if (num > PKT_BURST_SZ) {
319                 RTE_LOG(ERR, APP, "Error receiving from KNI\n");
320                 return;
321         }
322
323         /* Burst tx to eth */
324         nb_tx = rte_eth_tx_burst(port_id, 0, pkts_burst, (uint16_t)num);
325         kni_stats[port_id].tx_packets += nb_tx;
326
327         if (unlikely(nb_tx < num)) {
328                 /* Free mbufs not tx to NIC */
329                 kni_burst_free_mbufs(&pkts_burst[nb_tx], num - nb_tx);
330                 kni_stats[port_id].tx_dropped += num - nb_tx;
331         }
332 }
333
334 /* Main processing loop */
335 static __attribute__((noreturn)) int
336 main_loop(__rte_unused void *arg)
337 {
338         uint8_t pid;
339         const unsigned lcore_id = rte_lcore_id();
340         struct rte_kni *kni = kni_lcore_to_kni(lcore_id);
341
342         if (kni == NULL) {
343                 RTE_LOG(INFO, APP, "Lcore %u has nothing to do\n", lcore_id);
344                 for (;;)
345                         ; /* loop doing nothing */
346         } else {
347                 pid = rte_kni_get_port_id(kni);
348                 if (pid >= RTE_MAX_ETHPORTS)
349                         rte_exit(EXIT_FAILURE, "Failure: port id >= %d\n",
350                                                         RTE_MAX_ETHPORTS);
351
352                 if (kni_port_info[pid].lcore_id_ingress == lcore_id) {
353                         /* Running on lcores for input packets */
354                         RTE_LOG(INFO, APP, "Lcore %u is reading from "
355                                                 "port %d\n", lcore_id, pid);
356                         fflush(stdout);
357
358                         /* rx loop */
359                         while (1)
360                                 kni_ingress(kni);
361                 } else if (kni_port_info[pid].lcore_id_egress == lcore_id) {
362                         /* Running on lcores for output packets */
363                         RTE_LOG(INFO, APP, "Lcore %u is writing to port %d\n",
364                                                         lcore_id, pid);
365                         fflush(stdout);
366
367                         /* tx loop */
368                         while (1)
369                                 kni_egress(kni);
370                 } else {
371                         RTE_LOG(INFO, APP, "Lcore %u has nothing to do\n",
372                                                                 lcore_id);
373                         for (;;)
374                                 ; /* loop doing nothing */
375                 }
376         }
377 }
378
379 /* Display usage instructions */
380 static void
381 print_usage(const char *prgname)
382 {
383         RTE_LOG(INFO, APP, "\nUsage: %s [EAL options] -- -p PORTMASK "
384                                         "-i IN_CORES -o OUT_CORES\n"
385                    "    -p PORTMASK: hex bitmask of ports to use\n"
386                    "    -i IN_CORES: hex bitmask of cores which read "
387                    "from NIC\n"
388                    "    -o OUT_CORES: hex bitmask of cores which write to NIC\n",
389                    prgname);
390 }
391
392 /* Convert string to unsigned number. 0 is returned if error occurs */
393 static uint32_t
394 parse_unsigned(const char *portmask)
395 {
396         char *end = NULL;
397         unsigned long num;
398
399         num = strtoul(portmask, &end, 16);
400         if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0'))
401                 return 0;
402
403         return (uint32_t)num;
404 }
405
406 static int
407 kni_setup_port_affinities(uint8_t nb_port)
408 {
409         unsigned i;
410         uint32_t in_lcore, out_lcore;
411         uint8_t rx_port = 0, tx_port = 0;
412         uint8_t pid;
413
414         if (nb_port > RTE_MAX_ETHPORTS) {
415                 RTE_LOG(ERR, APP, "The number of ports exceeds the maximum "
416                                         "number of 0x%x\n", RTE_MAX_ETHPORTS);
417                 return -1;
418         }
419
420         RTE_LCORE_FOREACH(i) {
421                 in_lcore = input_cores_mask & (1 << i);
422                 out_lcore = output_cores_mask & (1 << i);
423
424                 /* Check if it is in input lcore or output lcore mask */
425                 if (in_lcore == 0 && out_lcore == 0)
426                         continue;
427
428                 /* Check if it is in both input lcore and output lcore mask */
429                 if (in_lcore != 0 && out_lcore != 0) {
430                         RTE_LOG(ERR, APP, "Lcore 0x%x can not be used in both "
431                                 "input lcore and output lcore mask\n", i);
432                         return -1;
433                 }
434
435                 /* Check if the lcore is enabled or not */
436                 if (rte_lcore_is_enabled(i) == 0) {
437                         RTE_LOG(ERR, APP, "Lcore 0x%x is not enabled\n", i);
438                         return -1;
439                 }
440
441                 if (in_lcore != 0) {
442                         /* It is be for packet receiving */
443                         while ((rx_port < nb_port) &&
444                                         ((ports_mask & (1 << rx_port)) == 0))
445                                 rx_port++;
446
447                         if (rx_port >= nb_port) {
448                                 RTE_LOG(ERR, APP, "There is no enough ports "
449                                                 "for ingress lcores\n");
450                                 return -1;
451                         }
452                         kni_port_info[rx_port].lcore_id_ingress = i;
453                         rx_port++;
454                 } else {
455                         /* It is for packet transmitting */
456                         while ((tx_port < nb_port) &&
457                                         ((ports_mask & (1 << tx_port)) == 0))
458                                 tx_port++;
459
460                         if (tx_port >= nb_port) {
461                                 RTE_LOG(ERR, APP, "There is no enough ports "
462                                                 "for engree lcores\n");
463                                 return -1;
464                         }
465                         kni_port_info[tx_port].lcore_id_egress = i;
466                         tx_port++;
467                 }
468         }
469
470         /* Display all the port/lcore affinity */
471         for (pid = 0; pid < nb_port; pid++) {
472                 RTE_LOG(INFO, APP, "Port%d, ingress lcore id: %u, "
473                                                 "egress lcore id: %u\n", pid,
474                                 kni_port_info[pid].lcore_id_ingress,
475                                 kni_port_info[pid].lcore_id_egress);
476         }
477
478         return 0;
479 }
480
481 static struct rte_kni *
482 kni_lcore_to_kni(unsigned lcore_id)
483 {
484         uint8_t pid;
485         struct kni_port_info_t *p = kni_port_info;
486
487         for (pid = 0; pid < RTE_MAX_ETHPORTS; pid++) {
488                 if (p[pid].kni != NULL && (p[pid].lcore_id_ingress == lcore_id
489                                         || p[pid].lcore_id_egress == lcore_id))
490                         return p[pid].kni;
491         }
492
493         return NULL;
494 }
495
496 /* Parse the arguments given in the command line of the application */
497 static void
498 parse_args(int argc, char **argv)
499 {
500         int opt;
501         const char *prgname = argv[0];
502
503         /* Disable printing messages within getopt() */
504         opterr = 0;
505
506         /* Parse command line */
507         while ((opt = getopt(argc, argv, "i:o:p:")) != EOF) {
508                 switch (opt) {
509                 case 'i':
510                         input_cores_mask = parse_unsigned(optarg);
511                         break;
512                 case 'o':
513                         output_cores_mask = parse_unsigned(optarg);
514                         break;
515                 case 'p':
516                         ports_mask = parse_unsigned(optarg);
517                         break;
518                 default:
519                         print_usage(prgname);
520                         rte_exit(EXIT_FAILURE, "Invalid option specified");
521                 }
522         }
523
524         /* Check that options were parsed ok */
525         if (input_cores_mask == 0) {
526                 print_usage(prgname);
527                 rte_exit(EXIT_FAILURE, "IN_CORES not specified correctly");
528         }
529         if (output_cores_mask == 0) {
530                 print_usage(prgname);
531                 rte_exit(EXIT_FAILURE, "OUT_CORES not specified correctly");
532         }
533         if (ports_mask == 0) {
534                 print_usage(prgname);
535                 rte_exit(EXIT_FAILURE, "PORTMASK not specified correctly");
536         }
537 }
538
539 /* Initialise a single port on an Ethernet device */
540 static void
541 init_port(uint8_t port)
542 {
543         int ret;
544
545         /* Initialise device and RX/TX queues */
546         RTE_LOG(INFO, APP, "Initialising port %u ...\n", (unsigned)port);
547         fflush(stdout);
548         ret = rte_eth_dev_configure(port, 1, 1, &port_conf);
549         if (ret < 0)
550                 rte_exit(EXIT_FAILURE, "Could not configure port%u (%d)",
551                             (unsigned)port, ret);
552
553         ret = rte_eth_rx_queue_setup(port, 0, NB_RXD, SOCKET, &rx_conf,
554                                      pktmbuf_pool);
555         if (ret < 0)
556                 rte_exit(EXIT_FAILURE, "Could not setup up RX queue for "
557                                         "port%u (%d)", (unsigned)port, ret);
558
559         ret = rte_eth_tx_queue_setup(port, 0, NB_TXD, SOCKET, &tx_conf);
560         if (ret < 0)
561                 rte_exit(EXIT_FAILURE, "Could not setup up TX queue for "
562                                         "port%u (%d)", (unsigned)port, ret);
563
564         ret = rte_eth_dev_start(port);
565         if (ret < 0)
566                 rte_exit(EXIT_FAILURE, "Could not start port%u (%d)",
567                                                 (unsigned)port, ret);
568
569         rte_eth_promiscuous_enable(port);
570 }
571
572 /* Check the link status of all ports in up to 9s, and print them finally */
573 static void
574 check_all_ports_link_status(uint8_t port_num, uint32_t port_mask)
575 {
576 #define CHECK_INTERVAL 100 /* 100ms */
577 #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */
578         uint8_t portid, count, all_ports_up, print_flag = 0;
579         struct rte_eth_link link;
580
581         printf("\nChecking link status");
582         fflush(stdout);
583         for (count = 0; count <= MAX_CHECK_TIME; count++) {
584                 all_ports_up = 1;
585                 for (portid = 0; portid < port_num; portid++) {
586                         if ((port_mask & (1 << portid)) == 0)
587                                 continue;
588                         memset(&link, 0, sizeof(link));
589                         rte_eth_link_get_nowait(portid, &link);
590                         /* print link status if flag set */
591                         if (print_flag == 1) {
592                                 if (link.link_status)
593                                         printf("Port %d Link Up - speed %u "
594                                                 "Mbps - %s\n", (uint8_t)portid,
595                                                 (unsigned)link.link_speed,
596                                 (link.link_duplex == ETH_LINK_FULL_DUPLEX) ?
597                                         ("full-duplex") : ("half-duplex\n"));
598                                 else
599                                         printf("Port %d Link Down\n",
600                                                 (uint8_t)portid);
601                                 continue;
602                         }
603                         /* clear all_ports_up flag if any link down */
604                         if (link.link_status == 0) {
605                                 all_ports_up = 0;
606                                 break;
607                         }
608                 }
609                 /* after finally printing all link status, get out */
610                 if (print_flag == 1)
611                         break;
612
613                 if (all_ports_up == 0) {
614                         printf(".");
615                         fflush(stdout);
616                         rte_delay_ms(CHECK_INTERVAL);
617                 }
618
619                 /* set the print_flag if all ports up or timeout */
620                 if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) {
621                         print_flag = 1;
622                         printf("done\n");
623                 }
624         }
625 }
626
627 /* Callback for request of changing MTU */
628 static int
629 kni_change_mtu(uint8_t port_id, unsigned new_mtu)
630 {
631         int ret;
632         struct rte_eth_conf conf;
633
634         if (port_id >= rte_eth_dev_count()) {
635                 RTE_LOG(ERR, APP, "Invalid port id %d\n", port_id);
636                 return -EINVAL;
637         }
638
639         RTE_LOG(INFO, APP, "Change MTU of port %d to %u\n", port_id, new_mtu);
640
641         /* Stop specific port */
642         rte_eth_dev_stop(port_id);
643
644         memcpy(&conf, &port_conf, sizeof(conf));
645         /* Set new MTU */
646         if (new_mtu > ETHER_MAX_LEN)
647                 conf.rxmode.jumbo_frame = 1;
648         else 
649                 conf.rxmode.jumbo_frame = 0;
650
651         /* mtu + length of header + length of FCS = max pkt length */
652         conf.rxmode.max_rx_pkt_len = new_mtu + KNI_ENET_HEADER_SIZE +
653                                                         KNI_ENET_FCS_SIZE;
654         ret = rte_eth_dev_configure(port_id, 1, 1, &conf);
655         if (ret < 0) {
656                 RTE_LOG(ERR, APP, "Fail to reconfigure port %d\n", port_id);
657                 return ret;
658         }
659
660         /* Restart specific port */
661         ret = rte_eth_dev_start(port_id);
662         if (ret < 0) {
663                 RTE_LOG(ERR, APP, "Fail to restart port %d\n", port_id);
664                 return ret;
665         }
666
667         return 0;
668 }
669
670 /* Callback for request of configuring network interface up/down */
671 static int
672 kni_config_network_interface(uint8_t port_id, uint8_t if_up)
673 {
674         int ret = 0;
675
676         if (port_id >= rte_eth_dev_count() || port_id >= RTE_MAX_ETHPORTS) {
677                 RTE_LOG(ERR, APP, "Invalid port id %d\n", port_id);
678                 return -EINVAL;
679         }
680
681         RTE_LOG(INFO, APP, "Configure network interface of %d %s\n",
682                                         port_id, if_up ? "up" : "down");
683
684         if (if_up != 0) { /* Configure network interface up */
685                 rte_eth_dev_stop(port_id);
686                 ret = rte_eth_dev_start(port_id);
687         } else /* Configure network interface down */
688                 rte_eth_dev_stop(port_id);
689
690         if (ret < 0)
691                 RTE_LOG(ERR, APP, "Failed to start port %d\n", port_id);
692
693         return ret;
694 }
695
696 /* Initialise ports/queues etc. and start main loop on each core */
697 int
698 main(int argc, char** argv)
699 {
700         int ret;
701         unsigned i, cfg_ports = 0;
702         uint8_t nb_sys_ports, port;
703
704         /* Associate signal_hanlder function with USR signals */
705         signal(SIGUSR1, signal_handler);
706         signal(SIGUSR2, signal_handler);
707
708         /* Initialise EAL */
709         ret = rte_eal_init(argc, argv);
710         if (ret < 0)
711                 rte_exit(EXIT_FAILURE, "Could not initialise EAL (%d)", ret);
712         argc -= ret;
713         argv += ret;
714
715         /* Parse application arguments (after the EAL ones) */
716         parse_args(argc, argv);
717
718         /* Create the mbuf pool */
719         pktmbuf_pool = rte_mempool_create("mbuf_pool", NB_MBUF, MBUF_SZ,
720                         MEMPOOL_CACHE_SZ,
721                         sizeof(struct rte_pktmbuf_pool_private),
722                         rte_pktmbuf_pool_init, NULL, rte_pktmbuf_init, NULL,
723                         SOCKET, 0);
724         if (pktmbuf_pool == NULL) {
725                 rte_exit(EXIT_FAILURE, "Could not initialise mbuf pool");
726                 return -1;
727         }
728
729         /* Initialise PMD driver(s) */
730         ret = rte_pmd_init_all();
731         if (ret < 0)
732                 rte_exit(EXIT_FAILURE, "Could not initialise PMD (%d)", ret);
733
734         /* Scan PCI bus for recognised devices */
735         ret = rte_eal_pci_probe();
736         if (ret < 0)
737                 rte_exit(EXIT_FAILURE, "Could not probe PCI (%d)", ret);
738
739         /* Get number of ports found in scan */
740         nb_sys_ports = rte_eth_dev_count();
741         if (nb_sys_ports == 0)
742                 rte_exit(EXIT_FAILURE, "No supported Ethernet devices found - "
743                         "check that CONFIG_RTE_LIBRTE_IGB_PMD=y and/or "
744                         "CONFIG_RTE_LIBRTE_IXGBE_PMD=y in the config file");
745         /* Find the number of configured ports in the port mask */
746         for (i = 0; i < sizeof(ports_mask) * 8; i++)
747                 cfg_ports += !! (ports_mask & (1 << i));
748
749         if (cfg_ports > nb_sys_ports)
750                 rte_exit(EXIT_FAILURE, "Port mask requires more ports than "
751                                                                 "available");
752
753         if (kni_setup_port_affinities(nb_sys_ports) < 0)
754                 rte_exit(EXIT_FAILURE, "Fail to setup port affinities\n");      
755
756         /* Initialise each port */
757         for (port = 0; port < nb_sys_ports; port++) {
758                 struct rte_kni *kni;
759
760                 /* Skip ports that are not enabled */
761                 if ((ports_mask & (1 << port)) == 0) {
762                         continue;
763                 }
764                 init_port(port);
765
766                 if (port >= RTE_MAX_ETHPORTS)
767                         rte_exit(EXIT_FAILURE, "Can not use more than "
768                                 "%d ports for kni\n", RTE_MAX_ETHPORTS);
769
770                 kni = rte_kni_create(port, MAX_PACKET_SZ, pktmbuf_pool,
771                                                                 &kni_ops);
772                 if (kni == NULL)
773                         rte_exit(EXIT_FAILURE, "Fail to create kni dev "
774                                                 "for port: %d\n", port);
775                 kni_port_info[port].kni = kni;
776         }
777         check_all_ports_link_status(nb_sys_ports, ports_mask);
778
779         /* Launch per-lcore function on every lcore */
780         rte_eal_mp_remote_launch(main_loop, NULL, CALL_MASTER);
781         RTE_LCORE_FOREACH_SLAVE(i) {
782                 if (rte_eal_wait_lcore(i) < 0)
783                         return -1;
784         }
785
786         return 0;
787 }
788