f7f99ed4a598bb545c4c776f251517c5ce3f32ae
[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 /* Max size of a single packet */
83 #define MAX_PACKET_SZ           2048
84
85 /* Number of bytes needed for each mbuf */
86 #define MBUF_SZ \
87         (MAX_PACKET_SZ + sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM)
88
89 /* Number of mbufs in mempool that is created */
90 #define NB_MBUF                 (8192 * 16)
91
92 /* How many packets to attempt to read from NIC in one go */
93 #define PKT_BURST_SZ            32
94
95 /* How many objects (mbufs) to keep in per-lcore mempool cache */
96 #define MEMPOOL_CACHE_SZ        PKT_BURST_SZ
97
98 /* Number of RX ring descriptors */
99 #define NB_RXD                  128
100
101 /* Number of TX ring descriptors */
102 #define NB_TXD                  512
103
104 /* Total octets in ethernet header */
105 #define KNI_ENET_HEADER_SIZE    14
106
107 /* Total octets in the FCS */
108 #define KNI_ENET_FCS_SIZE       4
109
110 #define KNI_US_PER_SECOND       1000000
111 #define KNI_SECOND_PER_DAY      86400
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_MQ_TX_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 static rte_atomic32_t kni_stop = RTE_ATOMIC32_INIT(0);
216
217 /* Print out statistics on packets handled */
218 static void
219 print_stats(void)
220 {
221         uint8_t i;
222
223         printf("\n**KNI example application statistics**\n"
224                "======  ==============  ============  ============  ============  ============\n"
225                " Port    Lcore(RX/TX)    rx_packets    rx_dropped    tx_packets    tx_dropped\n"
226                "------  --------------  ------------  ------------  ------------  ------------\n");
227         for (i = 0; i < RTE_MAX_ETHPORTS; i++) {
228                 if (kni_port_info[i].kni == NULL)
229                         continue;
230
231                 printf("%7d %10u/%2u %13"PRIu64" %13"PRIu64" %13"PRIu64" "
232                                                         "%13"PRIu64"\n", i,
233                                         kni_port_info[i].lcore_id_ingress,
234                                         kni_port_info[i].lcore_id_egress,
235                                                 kni_stats[i].rx_packets,
236                                                 kni_stats[i].rx_dropped,
237                                                 kni_stats[i].tx_packets,
238                                                 kni_stats[i].tx_dropped);
239         }
240         printf("======  ==============  ============  ============  ============  ============\n");
241 }
242
243 /* Custom handling of signals to handle stats and kni processing */
244 static void
245 signal_handler(int signum)
246 {
247         /* When we receive a USR1 signal, print stats */
248         if (signum == SIGUSR1) {
249                 print_stats();
250         }
251
252         /* When we receive a USR2 signal, reset stats */
253         if (signum == SIGUSR2) {
254                 memset(&kni_stats, 0, sizeof(kni_stats));
255                 printf("\n**Statistics have been reset**\n");
256                 return;
257         }
258
259         /* When we receive a RTMIN signal, stop kni processing */
260         if (signum == SIGRTMIN) {
261                 printf("SIGRTMIN is received, and the KNI processing is "
262                                                         "going to stop\n");
263                 rte_atomic32_inc(&kni_stop);
264                 return;
265         }
266 }
267
268 static void
269 kni_burst_free_mbufs(struct rte_mbuf **pkts, unsigned num)
270 {
271         unsigned i;
272
273         if (pkts == NULL)
274                 return;
275
276         for (i = 0; i < num; i++) {
277                 rte_pktmbuf_free(pkts[i]);
278                 pkts[i] = NULL;
279         }
280 }
281
282 /**
283  * Interface to burst rx and enqueue mbufs into rx_q
284  */
285 static void
286 kni_ingress(struct rte_kni *kni)
287 {
288         uint8_t port_id = rte_kni_get_port_id(kni);
289         unsigned nb_rx, num;
290         struct rte_mbuf *pkts_burst[PKT_BURST_SZ];
291
292         if (kni == NULL || port_id >= RTE_MAX_ETHPORTS)
293                 return;
294
295         /* Burst rx from eth */
296         nb_rx = rte_eth_rx_burst(port_id, 0, pkts_burst, PKT_BURST_SZ);
297         if (nb_rx > PKT_BURST_SZ) {
298                 RTE_LOG(ERR, APP, "Error receiving from eth\n");
299                 return;
300         }
301
302         /* Burst tx to kni */
303         num = rte_kni_tx_burst(kni, pkts_burst, nb_rx);
304         kni_stats[port_id].rx_packets += num;
305
306         rte_kni_handle_request(kni);
307         if (unlikely(num < nb_rx)) {
308                 /* Free mbufs not tx to kni interface */
309                 kni_burst_free_mbufs(&pkts_burst[num], nb_rx - num);
310                 kni_stats[port_id].rx_dropped += nb_rx - num;
311         }
312 }
313
314 /**
315  * Interface to dequeue mbufs from tx_q and burst tx
316  */
317 static void
318 kni_egress(struct rte_kni *kni)
319 {
320         uint8_t port_id = rte_kni_get_port_id(kni);;
321         unsigned nb_tx, num;
322         struct rte_mbuf *pkts_burst[PKT_BURST_SZ];
323
324         if (kni == NULL || port_id >= RTE_MAX_ETHPORTS)
325                 return;
326
327         /* Burst rx from kni */
328         num = rte_kni_rx_burst(kni, pkts_burst, PKT_BURST_SZ);
329         if (num > PKT_BURST_SZ) {
330                 RTE_LOG(ERR, APP, "Error receiving from KNI\n");
331                 return;
332         }
333
334         /* Burst tx to eth */
335         nb_tx = rte_eth_tx_burst(port_id, 0, pkts_burst, (uint16_t)num);
336         kni_stats[port_id].tx_packets += nb_tx;
337
338         if (unlikely(nb_tx < num)) {
339                 /* Free mbufs not tx to NIC */
340                 kni_burst_free_mbufs(&pkts_burst[nb_tx], num - nb_tx);
341                 kni_stats[port_id].tx_dropped += num - nb_tx;
342         }
343 }
344
345 /* Main processing loop */
346 static int
347 main_loop(__rte_unused void *arg)
348 {
349         uint8_t pid;
350         const unsigned lcore_id = rte_lcore_id();
351         struct rte_kni *kni = kni_lcore_to_kni(lcore_id);
352
353         if (kni != NULL) {
354                 pid = rte_kni_get_port_id(kni);
355                 if (pid >= RTE_MAX_ETHPORTS)
356                         rte_exit(EXIT_FAILURE, "Failure: port id >= %d\n",
357                                                         RTE_MAX_ETHPORTS);
358
359                 if (kni_port_info[pid].lcore_id_ingress == lcore_id) {
360                         /* Running on lcores for input packets */
361                         RTE_LOG(INFO, APP, "Lcore %u is reading from "
362                                                 "port %d\n", lcore_id, pid);
363                         fflush(stdout);
364
365                         /* rx loop */
366                         while (1) {
367                                 int32_t flag = rte_atomic32_read(&kni_stop);
368
369                                 if (flag)
370                                         break;
371                                 kni_ingress(kni);
372                         }
373                 } else if (kni_port_info[pid].lcore_id_egress == lcore_id) {
374                         /* Running on lcores for output packets */
375                         RTE_LOG(INFO, APP, "Lcore %u is writing to port %d\n",
376                                                         lcore_id, pid);
377                         fflush(stdout);
378
379                         /* tx loop */
380                         while (1) {
381                                 int32_t flag = rte_atomic32_read(&kni_stop);
382
383                                 if (flag)
384                                         break;
385                                 kni_egress(kni);
386                         }
387                 }
388         }
389
390         /* fallthrough to here if we don't have any work */
391         RTE_LOG(INFO, APP, "Lcore %u has nothing to do\n", lcore_id);
392
393         return 0;
394 }
395
396 /* Display usage instructions */
397 static void
398 print_usage(const char *prgname)
399 {
400         RTE_LOG(INFO, APP, "\nUsage: %s [EAL options] -- -p PORTMASK "
401                                         "-i IN_CORES -o OUT_CORES\n"
402                    "    -p PORTMASK: hex bitmask of ports to use\n"
403                    "    -i IN_CORES: hex bitmask of cores which read "
404                    "from NIC\n"
405                    "    -o OUT_CORES: hex bitmask of cores which write "
406                    "to NIC\n",
407                    prgname);
408 }
409
410 /* Convert string to unsigned number. 0 is returned if error occurs */
411 static uint32_t
412 parse_unsigned(const char *portmask)
413 {
414         char *end = NULL;
415         unsigned long num;
416
417         num = strtoul(portmask, &end, 16);
418         if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0'))
419                 return 0;
420
421         return (uint32_t)num;
422 }
423
424 static int
425 kni_setup_port_affinities(uint8_t nb_port)
426 {
427         unsigned i;
428         uint32_t in_lcore, out_lcore;
429         uint8_t rx_port = 0, tx_port = 0;
430         uint8_t pid;
431
432         if (nb_port > RTE_MAX_ETHPORTS) {
433                 RTE_LOG(ERR, APP, "The number of ports exceeds the maximum "
434                                         "number of 0x%x\n", RTE_MAX_ETHPORTS);
435                 return -1;
436         }
437
438         RTE_LCORE_FOREACH(i) {
439                 in_lcore = input_cores_mask & (1 << i);
440                 out_lcore = output_cores_mask & (1 << i);
441
442                 /* Check if it is in input lcore or output lcore mask */
443                 if (in_lcore == 0 && out_lcore == 0)
444                         continue;
445
446                 /* Check if it is in both input lcore and output lcore mask */
447                 if (in_lcore != 0 && out_lcore != 0) {
448                         RTE_LOG(ERR, APP, "Lcore 0x%x can not be used in both "
449                                 "input lcore and output lcore mask\n", i);
450                         return -1;
451                 }
452
453                 /* Check if the lcore is enabled or not */
454                 if (rte_lcore_is_enabled(i) == 0) {
455                         RTE_LOG(ERR, APP, "Lcore 0x%x is not enabled\n", i);
456                         return -1;
457                 }
458
459                 if (in_lcore != 0) {
460                         /* It is for packet receiving */
461                         while ((rx_port < nb_port) &&
462                                         ((ports_mask & (1 << rx_port)) == 0))
463                                 rx_port++;
464
465                         if (rx_port >= nb_port) {
466                                 RTE_LOG(ERR, APP, "There is no enough ports "
467                                                 "for ingress lcores\n");
468                                 return -1;
469                         }
470                         kni_port_info[rx_port].lcore_id_ingress = i;
471                         rx_port++;
472                 } else {
473                         /* It is for packet transmitting */
474                         while ((tx_port < nb_port) &&
475                                         ((ports_mask & (1 << tx_port)) == 0))
476                                 tx_port++;
477
478                         if (tx_port >= nb_port) {
479                                 RTE_LOG(ERR, APP, "There is no enough ports "
480                                                 "for engree lcores\n");
481                                 return -1;
482                         }
483                         kni_port_info[tx_port].lcore_id_egress = i;
484                         tx_port++;
485                 }
486         }
487
488         /* Display all the port/lcore affinity */
489         for (pid = 0; pid < nb_port; pid++) {
490                 RTE_LOG(INFO, APP, "Port%d, ingress lcore id: %u, "
491                                                 "egress lcore id: %u\n", pid,
492                                 kni_port_info[pid].lcore_id_ingress,
493                                 kni_port_info[pid].lcore_id_egress);
494         }
495
496         return 0;
497 }
498
499 static struct rte_kni *
500 kni_lcore_to_kni(unsigned lcore_id)
501 {
502         uint8_t pid;
503         struct kni_port_info_t *p = kni_port_info;
504
505         for (pid = 0; pid < RTE_MAX_ETHPORTS; pid++) {
506                 if (p[pid].kni != NULL && (p[pid].lcore_id_ingress == lcore_id
507                                         || p[pid].lcore_id_egress == lcore_id))
508                         return p[pid].kni;
509         }
510
511         return NULL;
512 }
513
514 /* Parse the arguments given in the command line of the application */
515 static void
516 parse_args(int argc, char **argv)
517 {
518         int opt;
519         const char *prgname = argv[0];
520
521         /* Disable printing messages within getopt() */
522         opterr = 0;
523
524         /* Parse command line */
525         while ((opt = getopt(argc, argv, "i:o:p:")) != EOF) {
526                 switch (opt) {
527                 case 'i':
528                         input_cores_mask = parse_unsigned(optarg);
529                         break;
530                 case 'o':
531                         output_cores_mask = parse_unsigned(optarg);
532                         break;
533                 case 'p':
534                         ports_mask = parse_unsigned(optarg);
535                         break;
536                 default:
537                         print_usage(prgname);
538                         rte_exit(EXIT_FAILURE, "Invalid option specified");
539                 }
540         }
541
542         /* Check that options were parsed ok */
543         if (input_cores_mask == 0) {
544                 print_usage(prgname);
545                 rte_exit(EXIT_FAILURE, "IN_CORES not specified correctly");
546         }
547         if (output_cores_mask == 0) {
548                 print_usage(prgname);
549                 rte_exit(EXIT_FAILURE, "OUT_CORES not specified correctly");
550         }
551         if (ports_mask == 0) {
552                 print_usage(prgname);
553                 rte_exit(EXIT_FAILURE, "PORTMASK not specified correctly");
554         }
555 }
556
557 /* Initialise a single port on an Ethernet device */
558 static void
559 init_port(uint8_t port)
560 {
561         int ret;
562
563         /* Initialise device and RX/TX queues */
564         RTE_LOG(INFO, APP, "Initialising port %u ...\n", (unsigned)port);
565         fflush(stdout);
566         ret = rte_eth_dev_configure(port, 1, 1, &port_conf);
567         if (ret < 0)
568                 rte_exit(EXIT_FAILURE, "Could not configure port%u (%d)",
569                             (unsigned)port, ret);
570
571         ret = rte_eth_rx_queue_setup(port, 0, NB_RXD, rte_eth_dev_socket_id(port),
572                                  &rx_conf, pktmbuf_pool);
573         if (ret < 0)
574                 rte_exit(EXIT_FAILURE, "Could not setup up RX queue for "
575                                         "port%u (%d)", (unsigned)port, ret);
576
577         ret = rte_eth_tx_queue_setup(port, 0, NB_TXD, rte_eth_dev_socket_id(port),
578                                  &tx_conf);
579         if (ret < 0)
580                 rte_exit(EXIT_FAILURE, "Could not setup up TX queue for "
581                                         "port%u (%d)", (unsigned)port, ret);
582
583         ret = rte_eth_dev_start(port);
584         if (ret < 0)
585                 rte_exit(EXIT_FAILURE, "Could not start port%u (%d)",
586                                                 (unsigned)port, ret);
587
588         rte_eth_promiscuous_enable(port);
589 }
590
591 /* Check the link status of all ports in up to 9s, and print them finally */
592 static void
593 check_all_ports_link_status(uint8_t port_num, uint32_t port_mask)
594 {
595 #define CHECK_INTERVAL 100 /* 100ms */
596 #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */
597         uint8_t portid, count, all_ports_up, print_flag = 0;
598         struct rte_eth_link link;
599
600         printf("\nChecking link status");
601         fflush(stdout);
602         for (count = 0; count <= MAX_CHECK_TIME; count++) {
603                 all_ports_up = 1;
604                 for (portid = 0; portid < port_num; portid++) {
605                         if ((port_mask & (1 << portid)) == 0)
606                                 continue;
607                         memset(&link, 0, sizeof(link));
608                         rte_eth_link_get_nowait(portid, &link);
609                         /* print link status if flag set */
610                         if (print_flag == 1) {
611                                 if (link.link_status)
612                                         printf("Port %d Link Up - speed %u "
613                                                 "Mbps - %s\n", (uint8_t)portid,
614                                                 (unsigned)link.link_speed,
615                                 (link.link_duplex == ETH_LINK_FULL_DUPLEX) ?
616                                         ("full-duplex") : ("half-duplex\n"));
617                                 else
618                                         printf("Port %d Link Down\n",
619                                                 (uint8_t)portid);
620                                 continue;
621                         }
622                         /* clear all_ports_up flag if any link down */
623                         if (link.link_status == 0) {
624                                 all_ports_up = 0;
625                                 break;
626                         }
627                 }
628                 /* after finally printing all link status, get out */
629                 if (print_flag == 1)
630                         break;
631
632                 if (all_ports_up == 0) {
633                         printf(".");
634                         fflush(stdout);
635                         rte_delay_ms(CHECK_INTERVAL);
636                 }
637
638                 /* set the print_flag if all ports up or timeout */
639                 if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) {
640                         print_flag = 1;
641                         printf("done\n");
642                 }
643         }
644 }
645
646 /* Callback for request of changing MTU */
647 static int
648 kni_change_mtu(uint8_t port_id, unsigned new_mtu)
649 {
650         int ret;
651         struct rte_eth_conf conf;
652
653         if (port_id >= rte_eth_dev_count()) {
654                 RTE_LOG(ERR, APP, "Invalid port id %d\n", port_id);
655                 return -EINVAL;
656         }
657
658         RTE_LOG(INFO, APP, "Change MTU of port %d to %u\n", port_id, new_mtu);
659
660         /* Stop specific port */
661         rte_eth_dev_stop(port_id);
662
663         memcpy(&conf, &port_conf, sizeof(conf));
664         /* Set new MTU */
665         if (new_mtu > ETHER_MAX_LEN)
666                 conf.rxmode.jumbo_frame = 1;
667         else 
668                 conf.rxmode.jumbo_frame = 0;
669
670         /* mtu + length of header + length of FCS = max pkt length */
671         conf.rxmode.max_rx_pkt_len = new_mtu + KNI_ENET_HEADER_SIZE +
672                                                         KNI_ENET_FCS_SIZE;
673         ret = rte_eth_dev_configure(port_id, 1, 1, &conf);
674         if (ret < 0) {
675                 RTE_LOG(ERR, APP, "Fail to reconfigure port %d\n", port_id);
676                 return ret;
677         }
678
679         /* Restart specific port */
680         ret = rte_eth_dev_start(port_id);
681         if (ret < 0) {
682                 RTE_LOG(ERR, APP, "Fail to restart port %d\n", port_id);
683                 return ret;
684         }
685
686         return 0;
687 }
688
689 /* Callback for request of configuring network interface up/down */
690 static int
691 kni_config_network_interface(uint8_t port_id, uint8_t if_up)
692 {
693         int ret = 0;
694
695         if (port_id >= rte_eth_dev_count() || port_id >= RTE_MAX_ETHPORTS) {
696                 RTE_LOG(ERR, APP, "Invalid port id %d\n", port_id);
697                 return -EINVAL;
698         }
699
700         RTE_LOG(INFO, APP, "Configure network interface of %d %s\n",
701                                         port_id, if_up ? "up" : "down");
702
703         if (if_up != 0) { /* Configure network interface up */
704                 rte_eth_dev_stop(port_id);
705                 ret = rte_eth_dev_start(port_id);
706         } else /* Configure network interface down */
707                 rte_eth_dev_stop(port_id);
708
709         if (ret < 0)
710                 RTE_LOG(ERR, APP, "Failed to start port %d\n", port_id);
711
712         return ret;
713 }
714
715 /* Initialise ports/queues etc. and start main loop on each core */
716 int
717 main(int argc, char** argv)
718 {
719         int ret;
720         unsigned i, cfg_ports = 0;
721         uint8_t nb_sys_ports, port;
722
723         /* Associate signal_hanlder function with USR signals */
724         signal(SIGUSR1, signal_handler);
725         signal(SIGUSR2, signal_handler);
726         signal(SIGRTMIN, signal_handler);
727
728         /* Initialise EAL */
729         ret = rte_eal_init(argc, argv);
730         if (ret < 0)
731                 rte_exit(EXIT_FAILURE, "Could not initialise EAL (%d)", ret);
732         argc -= ret;
733         argv += ret;
734
735         /* Parse application arguments (after the EAL ones) */
736         parse_args(argc, argv);
737
738         /* Create the mbuf pool */
739         pktmbuf_pool = rte_mempool_create("mbuf_pool", NB_MBUF, MBUF_SZ,
740                         MEMPOOL_CACHE_SZ,
741                         sizeof(struct rte_pktmbuf_pool_private),
742                         rte_pktmbuf_pool_init, NULL, rte_pktmbuf_init, NULL,
743                         rte_socket_id(), 0);
744         if (pktmbuf_pool == NULL) {
745                 rte_exit(EXIT_FAILURE, "Could not initialise mbuf pool");
746                 return -1;
747         }
748
749         /* Initialise PMD driver(s) */
750         ret = rte_pmd_init_all();
751         if (ret < 0)
752                 rte_exit(EXIT_FAILURE, "Could not initialise PMD (%d)", ret);
753
754         /* Scan PCI bus for recognised devices */
755         ret = rte_eal_pci_probe();
756         if (ret < 0)
757                 rte_exit(EXIT_FAILURE, "Could not probe PCI (%d)", ret);
758
759         /* Get number of ports found in scan */
760         nb_sys_ports = rte_eth_dev_count();
761         if (nb_sys_ports == 0)
762                 rte_exit(EXIT_FAILURE, "No supported Ethernet devices found - "
763                         "check that CONFIG_RTE_LIBRTE_IGB_PMD=y and/or "
764                         "CONFIG_RTE_LIBRTE_IXGBE_PMD=y in the config file");
765         /* Find the number of configured ports in the port mask */
766         for (i = 0; i < sizeof(ports_mask) * 8; i++)
767                 cfg_ports += !! (ports_mask & (1 << i));
768
769         if (cfg_ports > nb_sys_ports)
770                 rte_exit(EXIT_FAILURE, "Port mask requires more ports than "
771                                                                 "available");
772
773         if (kni_setup_port_affinities(nb_sys_ports) < 0)
774                 rte_exit(EXIT_FAILURE, "Fail to setup port affinities\n");      
775
776         /* Initialise each port */
777         for (port = 0; port < nb_sys_ports; port++) {
778                 struct rte_kni *kni;
779
780                 /* Skip ports that are not enabled */
781                 if ((ports_mask & (1 << port)) == 0) {
782                         continue;
783                 }
784                 init_port(port);
785
786                 if (port >= RTE_MAX_ETHPORTS)
787                         rte_exit(EXIT_FAILURE, "Can not use more than "
788                                 "%d ports for kni\n", RTE_MAX_ETHPORTS);
789
790                 kni = rte_kni_create(port, MAX_PACKET_SZ, pktmbuf_pool,
791                                                                 &kni_ops);
792                 if (kni == NULL)
793                         rte_exit(EXIT_FAILURE, "Fail to create kni dev "
794                                                 "for port: %d\n", port);
795                 kni_port_info[port].kni = kni;
796         }
797         check_all_ports_link_status(nb_sys_ports, ports_mask);
798
799         /* Launch per-lcore function on every lcore */
800         rte_eal_mp_remote_launch(main_loop, NULL, CALL_MASTER);
801         RTE_LCORE_FOREACH_SLAVE(i) {
802                 if (rte_eal_wait_lcore(i) < 0)
803                         return -1;
804         }
805
806         for (port = 0; port < nb_sys_ports; port++) {
807                 struct rte_kni *kni = kni_port_info[port].kni;
808
809                 if (kni != NULL)
810                         rte_kni_release(kni);
811         }
812
813         return 0;
814 }
815