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