Bump DPDK 16.04 to RC4
[vpp.git] / vnet / vnet / devices / dpdk / init.c
1 /*
2  * Copyright (c) 2015 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include <vnet/vnet.h>
16 #include <vppinfra/vec.h>
17 #include <vppinfra/error.h>
18 #include <vppinfra/format.h>
19 #include <vppinfra/bitmap.h>
20
21 #include <vnet/ethernet/ethernet.h>
22 #include <vnet/devices/dpdk/dpdk.h>
23 #include <vlib/unix/physmem.h>
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <unistd.h>
28 #include <sys/stat.h>
29 #include <sys/mount.h>
30 #include <string.h>
31 #include <fcntl.h>
32
33 #include "dpdk_priv.h"
34
35 dpdk_main_t dpdk_main;
36
37 /* force linker to link functions used by vlib and declared weak */
38 void *vlib_weakly_linked_functions[] = {
39   &rte_pktmbuf_init,
40   &rte_pktmbuf_pool_init,
41 };
42
43 #define LINK_STATE_ELOGS        0
44
45 #define DEFAULT_HUGE_DIR "/run/vpp/hugepages"
46 #define VPP_RUN_DIR "/run/vpp"
47
48 /* Port configuration, mildly modified Intel app values */
49
50 static struct rte_eth_conf port_conf_template = {
51   .rxmode = {
52     .split_hdr_size = 0,
53     .header_split   = 0, /**< Header Split disabled */
54     .hw_ip_checksum = 0, /**< IP checksum offload disabled */
55     .hw_vlan_filter = 0, /**< VLAN filtering disabled */
56     .hw_strip_crc   = 1, /**< CRC stripped by hardware */
57   },
58   .txmode = {
59     .mq_mode = ETH_MQ_TX_NONE,
60   },
61 };
62
63 clib_error_t *
64 dpdk_port_setup (dpdk_main_t * dm, dpdk_device_t * xd)
65 {
66   vlib_main_t * vm = vlib_get_main();
67   vlib_buffer_main_t * bm = vm->buffer_main;
68   int rv;
69   int j;
70
71   ASSERT(os_get_cpu_number() == 0);
72
73   if (xd->admin_up) {
74     vnet_hw_interface_set_flags (dm->vnet_main, xd->vlib_hw_if_index, 0);
75     rte_eth_dev_stop (xd->device_index);
76   }
77
78   rv = rte_eth_dev_configure (xd->device_index, xd->rx_q_used,
79                               xd->tx_q_used, &xd->port_conf);
80
81   if (rv < 0)
82     return clib_error_return (0, "rte_eth_dev_configure[%d]: err %d",
83                               xd->device_index, rv);
84
85   /* Set up one TX-queue per worker thread */
86   for (j = 0; j < xd->tx_q_used; j++)
87     {
88       rv = rte_eth_tx_queue_setup(xd->device_index, j, xd->nb_tx_desc,
89                                  xd->cpu_socket, &xd->tx_conf);
90       if (rv < 0)
91         break;
92     }
93
94     if (rv < 0)
95       return clib_error_return (0, "rte_eth_tx_queue_setup[%d]: err %d",
96                                 xd->device_index, rv);
97
98   for (j = 0; j < xd->rx_q_used; j++)
99     {
100
101       rv = rte_eth_rx_queue_setup(xd->device_index, j, xd->nb_rx_desc,
102                                   xd->cpu_socket, 0,
103                                   bm->pktmbuf_pools[xd->cpu_socket_id_by_queue[j]]);
104       if (rv < 0)
105         return clib_error_return (0, "rte_eth_rx_queue_setup[%d]: err %d",
106                                   xd->device_index, rv);
107     }
108
109   if (xd->admin_up) {
110     rte_eth_dev_start (xd->device_index);
111   }
112   return 0;
113 }
114
115 static u32 dpdk_flag_change (vnet_main_t * vnm, 
116                              vnet_hw_interface_t * hi,
117                              u32 flags)
118 {
119   dpdk_main_t * dm = &dpdk_main;
120   dpdk_device_t * xd = vec_elt_at_index (dm->devices, hi->dev_instance);
121   u32 old = 0;
122
123   if (ETHERNET_INTERFACE_FLAG_CONFIG_PROMISC(flags))
124     {
125       old = xd->promisc;
126       xd->promisc = flags & ETHERNET_INTERFACE_FLAG_ACCEPT_ALL;
127       
128       if (xd->admin_up)
129         {
130           if (xd->promisc)
131             rte_eth_promiscuous_enable(xd->device_index);
132           else
133             rte_eth_promiscuous_disable(xd->device_index);
134         }
135     }
136   else if (ETHERNET_INTERFACE_FLAG_CONFIG_MTU(flags))
137     {
138       /*
139        * DAW-FIXME: The Cisco VIC firmware does not provide an api for a
140        *            driver to dynamically change the mtu.  If/when the 
141        *            VIC firmware gets fixed, then this should be removed.
142        */
143       if (xd->pmd == VNET_DPDK_PMD_VICE ||
144           xd->pmd == VNET_DPDK_PMD_ENIC)
145         {
146           struct rte_eth_dev_info dev_info;
147
148           /*
149            * Restore mtu to what has been set by CIMC in the firmware cfg.
150            */
151           rte_eth_dev_info_get(xd->device_index, &dev_info);
152           hi->max_packet_bytes = dev_info.max_rx_pktlen;
153
154           vlib_cli_output (vlib_get_main(), 
155                            "Cisco VIC mtu can only be changed "
156                            "using CIMC then rebooting the server!");
157         }
158       else
159         {
160           int rv;
161       
162           xd->port_conf.rxmode.max_rx_pkt_len = hi->max_packet_bytes;
163
164           if (xd->admin_up)
165             rte_eth_dev_stop (xd->device_index);
166
167     rv = rte_eth_dev_configure
168       (xd->device_index,
169        xd->rx_q_used,
170        xd->tx_q_used,
171        &xd->port_conf);
172
173           if (rv < 0)
174             vlib_cli_output (vlib_get_main(), 
175                              "rte_eth_dev_configure[%d]: err %d",
176                              xd->device_index, rv);
177
178           rte_eth_dev_set_mtu(xd->device_index, hi->max_packet_bytes);
179
180           if (xd->admin_up)
181             rte_eth_dev_start (xd->device_index);
182         }
183     }
184   return old;
185 }
186
187 #ifdef NETMAP
188 extern int rte_netmap_probe(void);
189 #endif
190
191 void
192 dpdk_device_lock_init(dpdk_device_t * xd)
193 {
194   int q;
195   vec_validate(xd->lockp, xd->tx_q_used - 1);
196   for (q = 0; q < xd->tx_q_used; q++)
197     {
198       xd->lockp[q] = clib_mem_alloc_aligned (CLIB_CACHE_LINE_BYTES,
199                                              CLIB_CACHE_LINE_BYTES);
200       memset ((void *) xd->lockp[q], 0, CLIB_CACHE_LINE_BYTES);
201   }
202   xd->need_txlock = 1;
203 }
204
205 void
206 dpdk_device_lock_free(dpdk_device_t * xd)
207 {
208   int q;
209
210   for (q = 0; q < vec_len(xd->lockp); q++)
211     clib_mem_free((void *) xd->lockp[q]);
212   vec_free(xd->lockp);
213   xd->lockp = 0;
214   xd->need_txlock = 0;
215 }
216
217 static clib_error_t *
218 dpdk_lib_init (dpdk_main_t * dm)
219 {
220   u32 nports;
221   u32 nb_desc = 0;
222   int i;
223   clib_error_t * error;
224   vlib_main_t * vm = vlib_get_main();
225   vlib_thread_main_t * tm = vlib_get_thread_main();
226   vnet_sw_interface_t * sw;
227   vnet_hw_interface_t * hi;
228   dpdk_device_t * xd;
229   vlib_thread_registration_t * tr;
230   uword * p;
231
232   u32 next_cpu = 0;
233   u8 af_packet_port_id = 0;
234
235   dm->input_cpu_first_index = 0;
236   dm->input_cpu_count = 1;
237
238   /* find out which cpus will be used for input */
239   p = hash_get_mem (tm->thread_registrations_by_name, "io");
240   tr = p ? (vlib_thread_registration_t *) p[0] : 0;
241
242   if (!tr || tr->count == 0)
243     {
244       /* no io threads, workers doing input */
245       p = hash_get_mem (tm->thread_registrations_by_name, "workers");
246       tr = p ? (vlib_thread_registration_t *) p[0] : 0;
247     }
248   else
249     {
250       dm->have_io_threads = 1;
251     }
252
253   if (tr && tr->count > 0)
254     {
255       dm->input_cpu_first_index = tr->first_index;
256       dm->input_cpu_count = tr->count;
257     }
258
259   vec_validate_aligned (dm->devices_by_cpu, tm->n_vlib_mains - 1,
260                         CLIB_CACHE_LINE_BYTES);
261
262   vec_validate_aligned (dm->workers, tm->n_vlib_mains - 1,
263                         CLIB_CACHE_LINE_BYTES);
264
265 #ifdef NETMAP
266   if(rte_netmap_probe() < 0)
267     return clib_error_return (0, "rte netmap probe failed");
268 #endif
269
270   nports = rte_eth_dev_count();
271   if (nports < 1) 
272     {
273       clib_warning ("DPDK drivers found no ports...");
274     }
275
276   if (CLIB_DEBUG > 0)
277     clib_warning ("DPDK drivers found %d ports...", nports);
278
279   /* 
280    * All buffers are all allocated from the same rte_mempool.
281    * Thus they all have the same number of data bytes.
282    */
283   dm->vlib_buffer_free_list_index = 
284       vlib_buffer_get_or_create_free_list (
285           vm, VLIB_BUFFER_DEFAULT_FREE_LIST_BYTES, "dpdk rx");
286
287   for (i = 0; i < nports; i++)
288     {
289       u8 addr[6];
290       int j;
291       struct rte_eth_dev_info dev_info;
292       clib_error_t * rv;
293       struct rte_eth_link l;
294
295       /* Create vnet interface */
296       vec_add2_aligned (dm->devices, xd, 1, CLIB_CACHE_LINE_BYTES);
297       xd->nb_rx_desc = DPDK_NB_RX_DESC_DEFAULT;
298       xd->nb_tx_desc = DPDK_NB_TX_DESC_DEFAULT;
299       xd->cpu_socket = (i8) rte_eth_dev_socket_id(i);
300       rte_eth_dev_info_get(i, &dev_info);
301
302       memcpy(&xd->tx_conf, &dev_info.default_txconf,
303              sizeof(struct rte_eth_txconf));
304       if (dm->no_multi_seg)
305         {
306           xd->tx_conf.txq_flags |= ETH_TXQ_FLAGS_NOMULTSEGS;
307           port_conf_template.rxmode.jumbo_frame = 0;
308         }
309       else
310         {
311           xd->tx_conf.txq_flags &= ~ETH_TXQ_FLAGS_NOMULTSEGS;
312           port_conf_template.rxmode.jumbo_frame = 1;
313         }
314
315       memcpy(&xd->port_conf, &port_conf_template, sizeof(struct rte_eth_conf));
316
317       xd->tx_q_used = clib_min(dev_info.max_tx_queues, tm->n_vlib_mains);
318
319       if (dm->max_tx_queues)
320         xd->tx_q_used = clib_min(xd->tx_q_used, dm->max_tx_queues);
321
322       if (dm->use_rss > 1 && dev_info.max_rx_queues >= dm->use_rss)
323         {
324           xd->rx_q_used = dm->use_rss;
325           xd->port_conf.rxmode.mq_mode = ETH_MQ_RX_RSS;
326           xd->port_conf.rx_adv_conf.rss_conf.rss_hf = ETH_RSS_IP | ETH_RSS_UDP | ETH_RSS_TCP;
327         }
328       else
329         xd->rx_q_used = 1;
330
331       xd->dev_type = VNET_DPDK_DEV_ETH;
332
333       /* workaround for drivers not setting driver_name */
334       if (!dev_info.driver_name)
335         dev_info.driver_name = dev_info.pci_dev->driver->name;
336       ASSERT(dev_info.driver_name);
337
338       if (!xd->pmd) {
339
340
341 #define _(s,f) else if (!strcmp(dev_info.driver_name, s)) \
342                  xd->pmd = VNET_DPDK_PMD_##f;
343         if (0)
344           ;
345         foreach_dpdk_pmd
346 #undef _
347         else
348           xd->pmd = VNET_DPDK_PMD_UNKNOWN;
349
350
351         switch (xd->pmd) {
352           /* 1G adapters */
353           case VNET_DPDK_PMD_E1000EM:
354           case VNET_DPDK_PMD_IGB:
355           case VNET_DPDK_PMD_IGBVF:
356             xd->port_type = VNET_DPDK_PORT_TYPE_ETH_1G;
357             break;
358
359           /* 10G adapters */
360           case VNET_DPDK_PMD_IXGBE:
361           case VNET_DPDK_PMD_IXGBEVF:
362           case VNET_DPDK_PMD_THUNDERX:
363             xd->port_type = VNET_DPDK_PORT_TYPE_ETH_10G;
364             xd->nb_rx_desc = DPDK_NB_RX_DESC_10GE;
365             xd->nb_tx_desc = DPDK_NB_TX_DESC_10GE;
366             break;
367
368           /* Cisco VIC */
369           case VNET_DPDK_PMD_VICE:
370           case VNET_DPDK_PMD_ENIC:
371             rte_eth_link_get_nowait(i, &l);
372             if (l.link_speed == 40000)
373               {
374                 xd->port_type = VNET_DPDK_PORT_TYPE_ETH_40G;
375                 xd->nb_rx_desc = DPDK_NB_RX_DESC_40GE;
376                 xd->nb_tx_desc = DPDK_NB_TX_DESC_40GE;
377               }
378             else
379               {
380                 xd->port_type = VNET_DPDK_PORT_TYPE_ETH_10G;
381                 xd->nb_rx_desc = DPDK_NB_RX_DESC_10GE;
382                 xd->nb_tx_desc = DPDK_NB_TX_DESC_10GE;
383               }
384             break;
385
386           /* Intel Fortville */
387           case VNET_DPDK_PMD_I40E:
388           case VNET_DPDK_PMD_I40EVF:
389             xd->port_type = VNET_DPDK_PORT_TYPE_ETH_40G;
390             xd->nb_rx_desc = DPDK_NB_RX_DESC_40GE;
391             xd->nb_tx_desc = DPDK_NB_TX_DESC_40GE;
392
393             switch (dev_info.pci_dev->id.device_id) {
394               case I40E_DEV_ID_10G_BASE_T:
395               case I40E_DEV_ID_SFP_XL710:
396                 xd->port_type = VNET_DPDK_PORT_TYPE_ETH_10G;
397                 break;
398               case I40E_DEV_ID_QSFP_A:
399               case I40E_DEV_ID_QSFP_B:
400               case I40E_DEV_ID_QSFP_C:
401                 xd->port_type = VNET_DPDK_PORT_TYPE_ETH_40G;
402                 break;
403               case I40E_DEV_ID_VF:
404                 rte_eth_link_get_nowait(i, &l);
405                 xd->port_type = l.link_speed == 10000 ?
406                   VNET_DPDK_PORT_TYPE_ETH_10G : VNET_DPDK_PORT_TYPE_ETH_40G;
407                 break;
408               default:
409                 xd->port_type = VNET_DPDK_PORT_TYPE_UNKNOWN;
410             }
411             break;
412
413           case VNET_DPDK_PMD_CXGBE:
414             switch (dev_info.pci_dev->id.device_id) {
415               case 0x5410: /* T580-LP-cr */
416                 xd->nb_rx_desc = DPDK_NB_RX_DESC_40GE;
417                 xd->nb_tx_desc = DPDK_NB_TX_DESC_40GE;
418                 xd->port_type = VNET_DPDK_PORT_TYPE_ETH_40G;
419                 break;
420               default:
421                 xd->nb_rx_desc = DPDK_NB_RX_DESC_10GE;
422                 xd->nb_tx_desc = DPDK_NB_TX_DESC_10GE;
423                 xd->port_type = VNET_DPDK_PORT_TYPE_UNKNOWN;
424             }
425             break;
426
427           /* Intel Red Rock Canyon */
428           case VNET_DPDK_PMD_FM10K:
429             xd->port_type = VNET_DPDK_PORT_TYPE_ETH_SWITCH;
430             xd->nb_rx_desc = DPDK_NB_RX_DESC_40GE;
431             xd->nb_tx_desc = DPDK_NB_TX_DESC_40GE;
432             break;
433
434           /* virtio */
435           case VNET_DPDK_PMD_VIRTIO:
436             xd->port_type = VNET_DPDK_PORT_TYPE_ETH_1G;
437             xd->nb_rx_desc = DPDK_NB_RX_DESC_VIRTIO;
438             xd->nb_tx_desc = DPDK_NB_TX_DESC_VIRTIO;
439             break;
440
441           /* vmxnet3 */
442           case VNET_DPDK_PMD_VMXNET3:
443             xd->port_type = VNET_DPDK_PORT_TYPE_ETH_1G;
444             xd->tx_conf.txq_flags |= ETH_TXQ_FLAGS_NOMULTSEGS;
445             break;
446
447           case VNET_DPDK_PMD_AF_PACKET:
448             xd->port_type = VNET_DPDK_PORT_TYPE_AF_PACKET;
449             xd->af_packet_port_id = af_packet_port_id++;
450             break;
451
452           case VNET_DPDK_PMD_BOND:
453             xd->port_type = VNET_DPDK_PORT_TYPE_ETH_BOND;
454             break;
455
456           default:
457             xd->port_type = VNET_DPDK_PORT_TYPE_UNKNOWN;
458         }
459
460   #ifdef NETMAP
461         if(strncmp(dev_info.driver_name, "vale", 4) == 0
462              || strncmp(dev_info.driver_name, "netmap", 6) == 0)
463           {
464             xd->pmd = VNET_DPDK_PMD_NETMAP;
465             xd->port_type = VNET_DPDK_PORT_TYPE_NETMAP;
466           }
467   #endif
468
469       }
470
471       /*
472        * Ensure default mtu is not > the mtu read from the hardware.
473        * Otherwise rte_eth_dev_configure() will fail and the port will
474        * not be available.
475        */
476       if (ETHERNET_MAX_PACKET_BYTES > dev_info.max_rx_pktlen)
477         {
478           /*
479            * This device does not support the platforms's max frame
480            * size. Use it's advertised mru instead.
481            */
482           xd->port_conf.rxmode.max_rx_pkt_len = dev_info.max_rx_pktlen;
483         }
484       else
485         {
486           xd->port_conf.rxmode.max_rx_pkt_len = ETHERNET_MAX_PACKET_BYTES;
487
488           /*
489            * Some platforms do not account for Ethernet FCS (4 bytes) in
490            * MTU calculations. To interop with them increase mru but only
491            * if the device's settings can support it.
492            */
493           if ((dev_info.max_rx_pktlen >= (ETHERNET_MAX_PACKET_BYTES + 4)) &&
494               xd->port_conf.rxmode.hw_strip_crc)
495             {
496               /*
497                * Allow additional 4 bytes (for Ethernet FCS). These bytes are
498                * stripped by h/w and so will not consume any buffer memory.
499                */
500               xd->port_conf.rxmode.max_rx_pkt_len += 4;
501             }
502         }
503
504       /*
505        * DAW-FIXME: VMXNET3 driver doesn't support jumbo / multi-buffer pkts
506        */
507       if (xd->pmd == VNET_DPDK_PMD_VMXNET3)
508         {
509           xd->port_conf.rxmode.max_rx_pkt_len = 1518;
510           xd->port_conf.rxmode.jumbo_frame = 0;
511         }
512
513       if (xd->pmd == VNET_DPDK_PMD_AF_PACKET)
514         {
515           f64 now = vlib_time_now(vm);
516           u32 rnd;
517           rnd = (u32) (now * 1e6);
518           rnd = random_u32 (&rnd);
519           memcpy (addr+2, &rnd, sizeof(rnd));
520           addr[0] = 2;
521           addr[1] = 0xfe;
522         }
523       else
524         rte_eth_macaddr_get(i,(struct ether_addr *)addr);
525
526       if (xd->tx_q_used < tm->n_vlib_mains)
527         dpdk_device_lock_init(xd);
528
529       xd->device_index = xd - dm->devices;
530       ASSERT(i == xd->device_index);
531       xd->per_interface_next_index = ~0;
532
533       /* assign interface to input thread */
534       dpdk_device_and_queue_t * dq;
535       int q;
536
537       for (q = 0; q < xd->rx_q_used; q++)
538         {
539           int cpu = dm->input_cpu_first_index + next_cpu;
540           unsigned lcore = vlib_worker_threads[cpu].dpdk_lcore_id;
541
542           /*
543            * numa node for worker thread handling this queue
544            * needed for taking buffers from the right mempool
545            */
546           vec_validate(xd->cpu_socket_id_by_queue, q);
547           xd->cpu_socket_id_by_queue[q] = rte_lcore_to_socket_id(lcore);
548
549           /*
550            * construct vector of (device,queue) pairs for each worker thread
551            */
552           vec_add2(dm->devices_by_cpu[cpu], dq, 1);
553           dq->device = xd->device_index;
554           dq->queue_id = q;
555
556           next_cpu++;
557           if (next_cpu == dm->input_cpu_count)
558             next_cpu = 0;
559         }
560
561       vec_validate_aligned (xd->tx_vectors, tm->n_vlib_mains,
562                             CLIB_CACHE_LINE_BYTES);
563       for (j = 0; j < tm->n_vlib_mains; j++)
564         {
565           vec_validate_ha (xd->tx_vectors[j], DPDK_TX_RING_SIZE, 
566                            sizeof(tx_ring_hdr_t), CLIB_CACHE_LINE_BYTES);
567           vec_reset_length (xd->tx_vectors[j]);
568         }
569
570       vec_validate_aligned (xd->rx_vectors, xd->rx_q_used,
571                             CLIB_CACHE_LINE_BYTES);
572       for (j = 0; j< xd->rx_q_used; j++)
573         {
574           vec_validate_aligned (xd->rx_vectors[j], VLIB_FRAME_SIZE-1,
575                                 CLIB_CACHE_LINE_BYTES);
576           vec_reset_length (xd->rx_vectors[j]);
577         }
578
579       vec_validate_aligned (xd->frames, tm->n_vlib_mains,
580                             CLIB_CACHE_LINE_BYTES);
581
582       rv = dpdk_port_setup(dm, xd);
583
584       if (rv < 0)
585         return rv;
586
587       /* count the number of descriptors used for this device */
588       nb_desc += xd->nb_rx_desc + xd->nb_tx_desc * xd->tx_q_used;
589
590       error = ethernet_register_interface
591         (dm->vnet_main,
592          dpdk_device_class.index,
593          xd->device_index,
594          /* ethernet address */ addr,
595          &xd->vlib_hw_if_index, 
596          dpdk_flag_change);
597       if (error)
598         return error;
599       
600       sw = vnet_get_hw_sw_interface (dm->vnet_main, xd->vlib_hw_if_index);
601       xd->vlib_sw_if_index = sw->sw_if_index;
602       hi = vnet_get_hw_interface (dm->vnet_main, xd->vlib_hw_if_index);
603
604       /*
605        * DAW-FIXME: The Cisco VIC firmware does not provide an api for a
606        *            driver to dynamically change the mtu.  If/when the 
607        *            VIC firmware gets fixed, then this should be removed.
608        */
609       if (xd->pmd == VNET_DPDK_PMD_VICE ||
610           xd->pmd == VNET_DPDK_PMD_ENIC)
611         {
612           /*
613            * Initialize mtu to what has been set by CIMC in the firmware cfg.
614            */
615           hi->max_packet_bytes = dev_info.max_rx_pktlen;
616           /*
617            * remove vlan tag from VIC port to fix VLAN0 issue.
618            * TODO Handle VLAN tagged traffic
619            */
620           int vlan_off;
621           vlan_off = rte_eth_dev_get_vlan_offload(xd->device_index);
622           vlan_off |= ETH_VLAN_STRIP_OFFLOAD;
623           rte_eth_dev_set_vlan_offload(xd->device_index, vlan_off);
624         }
625       /*
626        * DAW-FIXME: VMXNET3 driver doesn't support jumbo / multi-buffer pkts
627        */
628       else if (xd->pmd == VNET_DPDK_PMD_VMXNET3)
629           hi->max_packet_bytes = 1518;
630
631       hi->max_l3_packet_bytes[VLIB_RX] = hi->max_l3_packet_bytes[VLIB_TX] = 
632               xd->port_conf.rxmode.max_rx_pkt_len - sizeof(ethernet_header_t);
633
634      rte_eth_dev_set_mtu(xd->device_index, hi->max_packet_bytes);
635     }
636
637 #ifdef RTE_LIBRTE_KNI
638   if (dm->num_kni) {
639     clib_warning("Initializing KNI interfaces...");
640     rte_kni_init(dm->num_kni);
641     for (i = 0; i < dm->num_kni; i++)
642     {
643       u8 addr[6];
644       int j;
645
646       /* Create vnet interface */
647       vec_add2_aligned (dm->devices, xd, 1, CLIB_CACHE_LINE_BYTES);
648       xd->dev_type = VNET_DPDK_DEV_KNI;
649
650       xd->device_index = xd - dm->devices;
651       ASSERT(nports + i == xd->device_index);
652       xd->per_interface_next_index = ~0;
653       xd->kni_port_id = i;
654       xd->cpu_socket = -1;
655       hash_set (dm->dpdk_device_by_kni_port_id, i, xd - dm->devices);
656       xd->rx_q_used = 1;
657
658       /* assign interface to input thread */
659       dpdk_device_and_queue_t * dq;
660       vec_add2(dm->devices_by_cpu[dm->input_cpu_first_index], dq, 1);
661       dq->device = xd->device_index;
662       dq->queue_id = 0;
663
664       vec_validate_aligned (xd->tx_vectors, tm->n_vlib_mains,
665                             CLIB_CACHE_LINE_BYTES);
666       for (j = 0; j < tm->n_vlib_mains; j++)
667         {
668           vec_validate_ha (xd->tx_vectors[j], DPDK_TX_RING_SIZE, 
669                            sizeof(tx_ring_hdr_t), CLIB_CACHE_LINE_BYTES);
670           vec_reset_length (xd->tx_vectors[j]);
671         }
672
673       vec_validate_aligned (xd->rx_vectors, xd->rx_q_used,
674                             CLIB_CACHE_LINE_BYTES);
675       for (j = 0; j< xd->rx_q_used; j++)
676         {
677           vec_validate_aligned (xd->rx_vectors[j], VLIB_FRAME_SIZE-1,
678                                 CLIB_CACHE_LINE_BYTES);
679           vec_reset_length (xd->rx_vectors[j]);
680         }
681
682       vec_validate_aligned (xd->frames, tm->n_vlib_mains,
683                             CLIB_CACHE_LINE_BYTES);
684
685       /* FIXME Set up one TX-queue per worker thread */
686
687       {
688         f64 now = vlib_time_now(vm);
689         u32 rnd;
690         rnd = (u32) (now * 1e6);
691         rnd = random_u32 (&rnd);
692
693         memcpy (addr+2, &rnd, sizeof(rnd));
694         addr[0] = 2;
695         addr[1] = 0xfe;
696       }
697
698       error = ethernet_register_interface
699         (dm->vnet_main,
700          dpdk_device_class.index,
701          xd->device_index,
702          /* ethernet address */ addr,
703          &xd->vlib_hw_if_index, 
704          dpdk_flag_change);
705
706       if (error)
707         return error;
708
709       sw = vnet_get_hw_sw_interface (dm->vnet_main, xd->vlib_hw_if_index);
710       xd->vlib_sw_if_index = sw->sw_if_index;
711       hi = vnet_get_hw_interface (dm->vnet_main, xd->vlib_hw_if_index);
712     }
713   }
714 #endif
715
716   if (nb_desc > dm->num_mbufs) 
717     clib_warning ("%d mbufs allocated but total rx/tx ring size is %d\n",
718                   dm->num_mbufs, nb_desc);
719
720   /* init next vhost-user if index */
721   dm->next_vu_if_id = 0;
722
723   return 0;
724 }
725
726 static clib_error_t *
727 write_sys_fs (char * file_name, char * fmt, ...)
728 {
729   u8 * s;
730   int fd;
731
732   fd = open (file_name, O_WRONLY);
733   if (fd < 0)
734     return clib_error_return_unix (0, "open `%s'", file_name);
735
736   va_list va;
737   va_start (va, fmt);
738   s = va_format (0, fmt, &va);
739   va_end (va);
740   vec_add1 (s, 0); // terminate c string
741
742   if (write (fd, s, vec_len (s)) < 0)
743       return clib_error_return_unix (0, "write '%s' to '%s'", s, file_name);
744
745   vec_free (s);
746   close (fd);
747   return 0;
748 }
749
750 #define VIRTIO_PCI_NAME  "virtio-pci"
751
752 static clib_error_t * dpdk_bind_eth_kernel_drivers (vlib_main_t * vm,
753                                                     char * pci_dev_id,
754                                                     char * kernel_driver)
755 {
756   dpdk_main_t * dm = &dpdk_main;
757   unformat_input_t _in;
758   unformat_input_t * in = &_in;
759   clib_error_t * error = 0;
760   u8 * line = 0, * modcmd = 0, * path = 0;
761   u8 * pci_vid = 0, *pci_did = 0, * devname = 0;
762   char *driver_name = kernel_driver;
763   FILE * fp;
764
765   /* 
766    * Bail out now if we're not running as root.
767    * This allows non-privileged use of the packet generator, etc.
768    */
769   if (geteuid() != 0)
770     return 0;
771
772   /*
773    * Get all ethernet pci device numbers for the device type specified.
774    */
775   modcmd = format (0, "lspci -nDd %s | grep 0200 | "
776                    "awk '{ print $1, $3 }'%c", pci_dev_id, 0);
777   if ((fp = popen ((const char *)modcmd, "r")) == NULL)
778     {
779       error = clib_error_return_unix (0, 
780                                       "Unable to get %s ethernet pci devices.",
781                                       pci_dev_id);
782       goto done;
783     }
784
785   vec_validate (line, BUFSIZ);
786   vec_validate (path, BUFSIZ);
787   while (fgets ((char *)line, BUFSIZ, fp) != NULL)
788     {
789       struct stat st;
790       u8 bind_uio = 1;
791       line[strlen ((char *)line) - 1] = 0; // chomp trailing newline.
792
793       unformat_init_string (in, (char *)line, strlen((char *)line) + 1);
794       unformat(in, "%s %s:%s", &devname, &pci_vid, &pci_did);
795       unformat_free (in);
796
797       /*
798        * Blacklist all ethernet interfaces in the 
799        * linux IP routing tables (route --inet --inet6)
800        */
801       if (strstr ((char *)dm->eth_if_blacklist, (char *)devname))
802         continue;
803
804       /*
805        * If there are any devices whitelisted, then blacklist all devices
806        * which are not explicitly whitelisted.
807        */
808       if (dm->eth_if_whitelist && 
809           !strstr ((char *)dm->eth_if_whitelist, (char *)devname))
810         continue;
811
812 #ifdef NETMAP
813       /*
814        * Optimistically open the device as a netmap device.
815        */
816       if (eth_nm_open((char *)devname))
817         continue;
818 #endif
819
820       _vec_len (path) = 0;
821       path = format (path, "/sys/bus/pci/devices/%s/driver/unbind%c",
822                      devname, 0);
823
824       /*
825        * If the device is bound to a driver...
826        */
827       if (stat ((const char *)path, &st) == 0)
828         {
829           u8 * device_path;
830
831           /*
832            * If the interface is not a virtio...
833            */
834          if (!driver_name || strcmp(driver_name, VIRTIO_PCI_NAME))
835            {
836               /*
837                * If it is already bound to driver, don't unbind/bind it.
838                */
839               device_path = format (0, "/sys/bus/pci/drivers/%s/%s/device%c",
840                                     driver_name, devname, 0);
841               if (stat ((const char *)device_path, &st) == 0)
842                 bind_uio = 0;
843
844               vec_free (device_path);
845            }
846           
847           /*
848            * unbind it from the current driver
849            */
850           if (bind_uio)
851             {
852               _vec_len (path) -= 1;
853               path = format (path, "%c", 0);
854               error = write_sys_fs ((char *)path, "%s", devname);
855               if (error)
856                 goto done;
857             }
858         }
859
860       /*
861        * DAW-FIXME: The following bind/unbind dance is necessary for the dpdk
862        *            virtio poll-mode driver to work.  
863        */
864  
865       if (driver_name && !strcmp(driver_name, VIRTIO_PCI_NAME))
866         {
867           /*
868            * bind interface to the native kernel module
869            */
870           _vec_len (path) = 0;
871           path = format (path, "/sys/bus/pci/drivers/%s/bind%c",
872                          driver_name, 0);
873           error = write_sys_fs ((char *)path, "%s", devname);
874           if (error)
875             goto done;
876
877           /*
878            * unbind interface from the native kernel module
879            */
880           _vec_len (path) -= 5;
881           path = format (path, "unbind%c", 0);
882           error = write_sys_fs ((char *)path, "%s", devname);
883           if (error)
884             goto done;
885         }
886
887       /*
888        * bind the interface to igb_uio
889        */
890       if (bind_uio)
891         {
892           _vec_len (path) = 0;
893           path = format (path, "/sys/bus/pci/drivers/%s/new_id%c", driver_name, 0);
894           error = write_sys_fs ((char *) path, "%s %s", pci_vid, pci_did);
895
896           _vec_len (path) = 0;
897           path = format (path, "/sys/bus/pci/drivers/%s/bind%c", driver_name, 0);
898           error = write_sys_fs ((char *) path, "%s", devname);
899           if (error)
900             {
901               error = 0;
902               continue;
903             }
904         }
905     }
906   
907  done:
908   vec_free (line);
909   vec_free (path);
910   vec_free (devname);
911   vec_free (pci_vid);
912   vec_free (pci_did);
913   vec_free (modcmd);
914   pclose (fp);
915   return error;
916 }
917
918 static u32
919 get_node_free_hugepages_num (u32 node, u32 page_size)
920 {
921   FILE * fp;
922   u8 * tmp;
923
924   tmp = format (0, "/sys/devices/system/node/node%u/hugepages/hugepages-%ukB/"
925                 "free_hugepages%c", node, page_size, 0);
926   fp = fopen ((char *) tmp, "r");
927   vec_free(tmp);
928
929   if (fp != NULL)
930     {
931       u8 * buffer = 0;
932       u32 pages_avail = 0;
933
934       vec_validate (buffer, 256-1);
935       if (fgets ((char *)buffer, 256, fp))
936         {
937           unformat_input_t in;
938           unformat_init_string (&in, (char *) buffer, strlen ((char *) buffer));
939           unformat(&in, "%u", &pages_avail);
940           unformat_free (&in);
941         }
942       vec_free(buffer);
943       fclose(fp);
944       return pages_avail;
945     }
946
947   return 0;
948 }
949
950 static clib_error_t *
951 dpdk_config (vlib_main_t * vm, unformat_input_t * input)
952 {
953   clib_error_t * error = 0;
954   dpdk_main_t * dm = &dpdk_main;
955   vlib_thread_main_t * tm = vlib_get_thread_main();
956   u8 * s, * tmp = 0;
957   u8 * pci_dev_id = 0;
958   u8 * rte_cmd = 0, * ethname = 0;
959   FILE * rte_fp;
960   u32 log_level;
961   int ret, i;
962   char * fmt;
963 #ifdef NETMAP
964   int rxrings, txrings, rxslots, txslots, txburst;
965   char * nmnam;
966 #endif
967   unformat_input_t _in;
968   unformat_input_t * in = &_in;
969   u8 no_pci = 0;
970   u8 no_huge = 0;
971   u8 huge_dir = 0;
972   u8 file_prefix = 0;
973   u8 * socket_mem = 0;
974
975   // MATT-FIXME: inverted virtio-vhost logic to use virtio by default
976   dm->use_virtio_vhost = 1;
977
978   while (unformat_check_input(input) != UNFORMAT_END_OF_INPUT)
979     {
980       /* Prime the pump */
981       if (unformat (input, "no-hugetlb"))
982         {
983           vec_add1 (dm->eal_init_args, (u8 *) "no-huge");
984           no_huge = 1;
985         }
986
987       else if (unformat (input, "enable-tcp-udp-checksum"))
988         {
989           dm->buffer_flags_template &= 
990             ~(IP_BUFFER_L4_CHECKSUM_CORRECT | IP_BUFFER_L4_CHECKSUM_COMPUTED);
991         }
992
993       else if (unformat (input, "decimal-interface-names"))
994         dm->interface_name_format_decimal = 1;
995
996       else if (unformat (input, "no-multi-seg"))
997         dm->no_multi_seg = 1;
998
999       else if (unformat (input, "dev %s", &pci_dev_id))
1000         {
1001           if (dm->eth_if_whitelist)
1002             {
1003               /*
1004                * Don't add duplicate device id's.
1005                */
1006               if (strstr ((char *)dm->eth_if_whitelist, (char *)pci_dev_id))
1007                 continue;
1008
1009               _vec_len (dm->eth_if_whitelist) -= 1; // chomp trailing NULL.
1010               dm->eth_if_whitelist = format (dm->eth_if_whitelist, " %s%c",
1011                                              pci_dev_id, 0);
1012             }
1013           else
1014             dm->eth_if_whitelist = format (0, "%s%c", pci_dev_id, 0);
1015         }
1016
1017 #ifdef NETMAP
1018      else if (unformat(input, "netmap %s/%d:%d/%d:%d/%d",
1019                   &nmname, &rxrings, &rxslots, &txrings, &txslots, &txburst)) {
1020         char * rv;
1021         rv = (char *)
1022           eth_nm_args(nmname, rxrings, rxslots, txrings, txslots, txburst);
1023         if (rv) {
1024           error = clib_error_return (0, "%s", rv);
1025           goto done;
1026         }
1027       }else if (unformat(input, "netmap %s", &nmname)) {
1028         char * rv;
1029         rv = (char *)
1030           eth_nm_args(nmname, 0, 0, 0, 0, 0);
1031         if (rv) {
1032           error = clib_error_return (0, "%s", rv);
1033           goto done;
1034         }
1035       }
1036 #endif
1037
1038       else if (unformat (input, "num-mbufs %d", &dm->num_mbufs))
1039         ;
1040       else if (unformat (input, "max-tx-queues %d", &dm->max_tx_queues))
1041         ;
1042       else if (unformat (input, "kni %d", &dm->num_kni))
1043         ;
1044       else if (unformat (input, "uio-driver %s", &dm->uio_driver_name))
1045         ;
1046       else if (unformat (input, "vhost-user-coalesce-frames %d", &dm->vhost_coalesce_frames))
1047         ;
1048       else if (unformat (input, "vhost-user-coalesce-time %f", &dm->vhost_coalesce_time))
1049         ;
1050       else if (unformat (input, "enable-vhost-user"))
1051         dm->use_virtio_vhost = 0;
1052       else if (unformat (input, "rss %d", &dm->use_rss))
1053         ;
1054
1055 #define _(a)                                    \
1056       else if (unformat(input, #a))             \
1057         {                                       \
1058           if (!strncmp(#a, "no-pci", 6))        \
1059             no_pci = 1;                         \
1060           tmp = format (0, "--%s%c", #a, 0);    \
1061           vec_add1 (dm->eal_init_args, tmp);    \
1062         }
1063       foreach_eal_double_hyphen_predicate_arg
1064 #undef _
1065
1066 #define _(a)                                          \
1067         else if (unformat(input, #a " %s", &s))       \
1068           {                                           \
1069             if (!strncmp(#a, "huge-dir", 8))          \
1070               huge_dir = 1;                           \
1071             else if (!strncmp(#a, "file-prefix", 11)) \
1072               file_prefix = 1;                        \
1073             else if (!strncmp(#a, "socket-mem", 10))  \
1074               socket_mem = vec_dup (s);               \
1075             tmp = format (0, "--%s%c", #a, 0);        \
1076             vec_add1 (dm->eal_init_args, tmp);        \
1077             vec_add1 (s, 0);                          \
1078             vec_add1 (dm->eal_init_args, s);          \
1079           }
1080         foreach_eal_double_hyphen_arg
1081 #undef _
1082
1083 #define _(a,b)                                          \
1084           else if (unformat(input, #a " %s", &s))       \
1085             {                                           \
1086               tmp = format (0, "-%s%c", #b, 0);         \
1087               vec_add1 (dm->eal_init_args, tmp);        \
1088               vec_add1 (s, 0);                          \
1089               vec_add1 (dm->eal_init_args, s);          \
1090             }
1091           foreach_eal_single_hyphen_arg
1092 #undef _
1093
1094 #define _(a,b)                                          \
1095             else if (unformat(input, #a " %s", &s))     \
1096               {                                         \
1097                 tmp = format (0, "-%s%c", #b, 0);       \
1098                 vec_add1 (dm->eal_init_args, tmp);      \
1099                 vec_add1 (s, 0);                        \
1100                 vec_add1 (dm->eal_init_args, s);        \
1101                 dm->a##_set_manually = 1;               \
1102               }
1103             foreach_eal_single_hyphen_mandatory_arg
1104 #undef _
1105
1106           else if (unformat(input, "default"))
1107             ;
1108
1109           else
1110             {
1111               error = clib_error_return (0, "unknown input `%U'",
1112                                          format_unformat_error, input);
1113               goto done;
1114             }
1115     }
1116
1117   if (!dm->uio_driver_name)
1118     dm->uio_driver_name = format (0, "igb_uio");
1119
1120   /*
1121    * Use 1G huge pages if available.
1122    */
1123   if (!no_huge && !huge_dir)
1124     {
1125       uword * mem_by_socket = hash_create (0, sizeof (uword));
1126       uword c;
1127       u8 use_1g = 1;
1128       u8 use_2m = 1;
1129       int rv;
1130
1131       umount(DEFAULT_HUGE_DIR);
1132
1133       /* Process "socket-mem" parameter value */
1134       if (vec_len (socket_mem))
1135         {
1136           unformat_input_t in;
1137           unformat_init_vector(&in, socket_mem);
1138           unformat(&in, "%U", unformat_socket_mem, &mem_by_socket);
1139           unformat_free(&in);
1140         }
1141       else
1142         use_1g = 0;
1143
1144       /* check if available enough 1GB pages for each socket */
1145       clib_bitmap_foreach (c, tm->cpu_socket_bitmap, ({
1146          uword * p = hash_get (mem_by_socket, c);
1147          if (p)
1148            {
1149              u32 mem = p[0];
1150              if (mem)
1151                {
1152                  u32 pages_num_1g = mem / 1024;
1153                  u32 pages_num_2m = mem / 2;
1154                  u32 pages_avail;
1155
1156                  pages_avail = get_node_free_hugepages_num(c, 1048576);
1157                  if (!pages_avail || !(pages_avail >= pages_num_1g))
1158                    use_1g = 0;
1159
1160                  pages_avail = get_node_free_hugepages_num(c, 2048);
1161                  if (!pages_avail || !(pages_avail >= pages_num_2m))
1162                    use_2m = 0;
1163               }
1164            }
1165       }));
1166
1167       hash_free (mem_by_socket);
1168
1169       rv = mkdir(VPP_RUN_DIR, 0755);
1170       if (rv && errno != EEXIST)
1171         {
1172           error = clib_error_return (0, "mkdir '%s' failed errno %d",
1173                                      VPP_RUN_DIR, errno);
1174           goto done;
1175         }
1176
1177       rv = mkdir(DEFAULT_HUGE_DIR, 0755);
1178       if (rv && errno != EEXIST)
1179         {
1180           error = clib_error_return (0, "mkdir '%s' failed errno %d",
1181                                      DEFAULT_HUGE_DIR, errno);
1182           goto done;
1183         }
1184
1185       if (use_1g)
1186         {
1187           rv = mount("none", DEFAULT_HUGE_DIR, "hugetlbfs", 0, "pagesize=1G");
1188         }
1189       else if (use_2m)
1190         {
1191           rv = mount("none", DEFAULT_HUGE_DIR, "hugetlbfs", 0, NULL);
1192         }
1193       else
1194         {
1195           return clib_error_return (0, "not enough free huge pages");
1196         }
1197
1198       if (rv)
1199         {
1200           error = clib_error_return (0, "mount failed %d", errno);
1201           goto done;
1202         }
1203
1204       tmp = format (0, "--huge-dir%c", 0);
1205       vec_add1 (dm->eal_init_args, tmp);
1206       tmp = format (0, "%s%c", DEFAULT_HUGE_DIR, 0);
1207       vec_add1 (dm->eal_init_args, tmp);
1208       if (!file_prefix)
1209         {
1210           tmp = format (0, "--file-prefix%c", 0);
1211           vec_add1 (dm->eal_init_args, tmp);
1212           tmp = format (0, "vpp%c", 0);
1213           vec_add1 (dm->eal_init_args, tmp);
1214         }
1215     }
1216
1217   /*
1218    * Blacklist all ethernet interfaces in the linux IP routing tables.
1219    */
1220   dm->eth_if_blacklist = format (0, "%c", 0);
1221   rte_cmd = format (0, "route --inet --inet6 -n|awk '{print $7}'|sort -u|"
1222                     "egrep $(echo $(ls -1d /sys/class/net/*/device|"
1223                     "cut -d/ -f5)|sed -s 's/ /|/g')%c", 0);
1224   if ((rte_fp = popen ((const char *)rte_cmd, "r")) == NULL)
1225     {
1226       error = clib_error_return_unix (0, "Unable to find blacklist ethernet"
1227                                       " interface(s) in linux routing tables.");
1228       goto rte_cmd_err;
1229
1230     }
1231
1232   vec_validate (ethname, BUFSIZ);
1233   while (fgets ((char *)ethname, BUFSIZ, rte_fp) != NULL)
1234     {
1235       FILE *rlnk_fp;
1236       u8 * rlnk_cmd = 0, * devname = 0;
1237
1238       ethname[strlen ((char *)ethname) - 1] = 0; // chomp trailing newline.
1239
1240       rlnk_cmd = format (0, "readlink /sys/class/net/%s%c",
1241                          ethname, 0);
1242
1243       if ((rlnk_fp = popen ((const char *)rlnk_cmd, "r")) == NULL)
1244         {
1245           error = clib_error_return_unix (0, "Unable to read %s link.",
1246                                           ethname);
1247           goto rlnk_cmd_err;
1248         }
1249
1250       vec_validate (devname, BUFSIZ);
1251       while (fgets ((char *)devname, BUFSIZ, rlnk_fp) != NULL)
1252         {
1253           char * pci_id = 0;
1254           
1255           /*
1256            * Extract the device PCI ID name from the link. It is the first
1257            * PCI ID searching backwards from the end of the link pathname.
1258            * For example:
1259            *     readlink /sys/class/net/eth0
1260            *     ../../devices/pci0000:00/0000:00:0a.0/virtio4/net/eth0
1261            */
1262           for (pci_id = (char *)((devname + strlen((char *)devname)));
1263                ((u8 *)pci_id > devname) && *pci_id != '.'; pci_id--)
1264             ;
1265
1266           /*
1267            * Verify that the field found is a valid PCI ID.
1268            */
1269           if ((*(pci_id - 1) == '.') || ((u8 *)(pci_id - 11) < devname) || 
1270               (*(pci_id - 11) != '/') || (*(pci_id - 3) != ':') ||
1271               (*(pci_id - 6) != ':'))
1272             {
1273               devname[strlen ((char *)devname) - 1] = 0; // chomp trailing newline.
1274               clib_warning ("Unable to extract %s PCI ID (0x%llx \"%s\") "
1275                             "from 0x%llx \"%s\"", ethname, pci_id, pci_id,
1276                             devname, devname);
1277               continue;
1278             }
1279
1280           pci_id[2] = 0;
1281           pci_id -= 10;
1282
1283           /* Don't blacklist any interfaces which have been whitelisted.
1284            */
1285           if (dm->eth_if_whitelist &&
1286               strstr ((char *)dm->eth_if_whitelist, (char *)pci_id))
1287               continue;
1288
1289           _vec_len (dm->eth_if_blacklist) -= 1; // chomp trailing NULL.
1290           dm->eth_if_blacklist = format (dm->eth_if_blacklist, " %s%c",
1291                                          pci_id, 0);
1292         }
1293   
1294     rlnk_cmd_err:
1295       pclose (rlnk_fp);
1296       vec_free (rlnk_cmd);
1297       vec_free (devname);
1298     }
1299
1300  rte_cmd_err:
1301   pclose (rte_fp);
1302   vec_free (rte_cmd);
1303   vec_free (ethname);
1304
1305   if (error)
1306     return error;
1307
1308   /* I'll bet that -c and -n must be the first and second args... */
1309   if (!dm->coremask_set_manually)
1310     {
1311       vlib_thread_registration_t * tr;
1312       uword * coremask = 0;
1313       int i;
1314
1315       /* main thread core */
1316       coremask = clib_bitmap_set(coremask, tm->main_lcore, 1);
1317
1318       for (i = 0; i < vec_len (tm->registrations); i++)
1319         {
1320           tr = tm->registrations[i];
1321           coremask = clib_bitmap_or(coremask, tr->coremask);
1322         }
1323
1324       vec_insert (dm->eal_init_args, 2, 1);
1325       dm->eal_init_args[1] = (u8 *) "-c";
1326       tmp = format (0, "%U%c", format_bitmap_hex, coremask, 0);
1327       dm->eal_init_args[2] = tmp;
1328       clib_bitmap_free(coremask);
1329     }
1330
1331   if (!dm->nchannels_set_manually)
1332     {
1333       vec_insert (dm->eal_init_args, 2, 3);
1334       dm->eal_init_args[3] = (u8 *) "-n";
1335       tmp = format (0, "%d", dm->nchannels);
1336       dm->eal_init_args[4] = tmp;
1337     }
1338
1339   /*
1340    * If there are whitelisted devices,
1341    * add the whitelist option & device list to the dpdk arg list...
1342    */
1343   if (dm->eth_if_whitelist)
1344     {
1345       unformat_init_string (in, (char *)dm->eth_if_whitelist,
1346                             vec_len(dm->eth_if_whitelist) - 1);
1347       fmt = "-w%c";
1348     }
1349
1350   /*
1351    * Otherwise add the blacklisted devices to the dpdk arg list.
1352    */
1353   else
1354     {
1355       unformat_init_string (in, (char *)dm->eth_if_blacklist,
1356                             vec_len(dm->eth_if_blacklist) - 1);
1357       fmt = "-b%c";
1358     }
1359
1360   while (unformat_check_input (in) != UNFORMAT_END_OF_INPUT)
1361     {
1362       tmp = format (0, fmt, 0);
1363       vec_add1 (dm->eal_init_args, tmp);
1364       unformat (in, "%s", &pci_dev_id);
1365       vec_add1 (dm->eal_init_args, pci_dev_id);
1366     }
1367
1368   if (no_pci == 0)
1369     {
1370       /*
1371        * Bind Virtio pci devices to the igb_uio kernel driver.
1372        */
1373       error = dpdk_bind_eth_kernel_drivers (vm, "1af4:1000", VIRTIO_PCI_NAME);
1374       if (error)
1375         return error;
1376
1377       /*
1378        * Bind vmxnet3 pci devices to the igb_uio kernel driver.
1379        */
1380       error = dpdk_bind_eth_kernel_drivers (vm, "15ad:07b0",
1381                                             (char *) dm->uio_driver_name);
1382       if (error)
1383         return error;
1384
1385       /*
1386        * Bind Intel ethernet pci devices to igb_uio kernel driver.
1387        */
1388       error = dpdk_bind_eth_kernel_drivers (vm, "8086:",
1389                                             (char *) dm->uio_driver_name);
1390       /*
1391        * Bind Cisco VIC ethernet pci devices to igb_uio kernel driver.
1392        */
1393       error = dpdk_bind_eth_kernel_drivers (vm, "1137:0043",
1394                                             (char *) dm->uio_driver_name);
1395     }
1396
1397   /* set master-lcore */
1398   tmp = format (0, "--master-lcore%c", 0);
1399   vec_add1 (dm->eal_init_args, tmp);
1400   tmp = format (0, "%u%c", tm->main_lcore, 0);
1401   vec_add1 (dm->eal_init_args, tmp);
1402
1403   /* NULL terminate the "argv" vector, in case of stupidity */
1404   vec_add1 (dm->eal_init_args, 0);
1405   _vec_len(dm->eal_init_args) -= 1;
1406
1407   /* Set up DPDK eal and packet mbuf pool early. */
1408
1409   log_level = (CLIB_DEBUG > 0) ? RTE_LOG_DEBUG : RTE_LOG_NOTICE;
1410
1411   rte_set_log_level (log_level);
1412
1413   vm = dm->vlib_main;
1414
1415   /* make copy of args as rte_eal_init tends to mess up with arg array */
1416   for (i = 1; i < vec_len(dm->eal_init_args); i++)
1417     dm->eal_init_args_str = format(dm->eal_init_args_str, "%s ",
1418                                    dm->eal_init_args[i]);
1419
1420   ret = rte_eal_init(vec_len(dm->eal_init_args), (char **) dm->eal_init_args);
1421
1422   /* lazy umount hugepages */
1423   umount2(DEFAULT_HUGE_DIR, MNT_DETACH);
1424
1425   if (ret < 0)
1426     return clib_error_return (0, "rte_eal_init returned %d", ret);
1427
1428   /* Dump the physical memory layout prior to creating the mbuf_pool */
1429   fprintf(stdout, "DPDK physical memory layout:\n");
1430   rte_dump_physmem_layout(stdout);
1431
1432   /* main thread 1st */
1433   error = vlib_buffer_pool_create(vm, dm->num_mbufs, rte_socket_id());
1434   if (error)
1435     return error;
1436
1437   for (i = 0; i < RTE_MAX_LCORE; i++)
1438     {
1439       error = vlib_buffer_pool_create(vm, dm->num_mbufs,
1440                                       rte_lcore_to_socket_id(i));
1441       if (error)
1442         return error;
1443     }
1444
1445   if (dm->use_rss)
1446     {
1447       vlib_node_runtime_t * rt = vlib_node_get_runtime (vm, dpdk_input_node.index);
1448       rt->function = dpdk_input_rss;
1449     }
1450  done:
1451   return error;
1452 }
1453
1454 VLIB_CONFIG_FUNCTION (dpdk_config, "dpdk");
1455
1456 void dpdk_update_link_state (dpdk_device_t * xd, f64 now)
1457 {
1458     vnet_main_t * vnm = vnet_get_main();
1459     struct rte_eth_link prev_link = xd->link;
1460     u32 hw_flags =  0;
1461     u8 hw_flags_chg = 0;
1462
1463     /* only update link state for PMD interfaces */
1464     if (xd->dev_type != VNET_DPDK_DEV_ETH)
1465       return;
1466
1467     xd->time_last_link_update = now ? now : xd->time_last_link_update;
1468     memset(&xd->link, 0, sizeof(xd->link));
1469     rte_eth_link_get_nowait (xd->device_index, &xd->link);
1470
1471     if (LINK_STATE_ELOGS)
1472       {
1473         vlib_main_t * vm = vlib_get_main();
1474         ELOG_TYPE_DECLARE(e) = {
1475           .format = 
1476           "update-link-state: sw_if_index %d, admin_up %d,"
1477           "old link_state %d new link_state %d",
1478           .format_args = "i4i1i1i1",
1479         };
1480
1481         struct { u32 sw_if_index; u8 admin_up; 
1482           u8 old_link_state; u8 new_link_state;} *ed;
1483         ed = ELOG_DATA (&vm->elog_main, e);
1484         ed->sw_if_index = xd->vlib_sw_if_index;
1485         ed->admin_up = xd->admin_up;
1486         ed->old_link_state = (u8)
1487           vnet_hw_interface_is_link_up (vnm, xd->vlib_hw_if_index);
1488         ed->new_link_state = (u8) xd->link.link_status;
1489       }
1490
1491     if ((xd->admin_up == 1) && 
1492         ((xd->link.link_status != 0) ^ 
1493          vnet_hw_interface_is_link_up (vnm, xd->vlib_hw_if_index)))
1494       {
1495         hw_flags_chg = 1;
1496         hw_flags |= (xd->link.link_status ? 
1497                      VNET_HW_INTERFACE_FLAG_LINK_UP: 0);
1498       }
1499
1500     if (hw_flags_chg || (xd->link.link_duplex != prev_link.link_duplex))
1501       {
1502         hw_flags_chg = 1;
1503         switch (xd->link.link_duplex)
1504           {
1505           case ETH_LINK_HALF_DUPLEX:
1506             hw_flags |= VNET_HW_INTERFACE_FLAG_HALF_DUPLEX;
1507             break;
1508           case ETH_LINK_FULL_DUPLEX:
1509             hw_flags |= VNET_HW_INTERFACE_FLAG_FULL_DUPLEX;
1510             break;
1511           default:
1512             break;
1513           }
1514       }
1515 #if RTE_VERSION >= RTE_VERSION_NUM(16, 4, 0, 0)
1516     if (hw_flags_chg || (xd->link.link_speed != prev_link.link_speed))
1517       {
1518         hw_flags_chg = 1;
1519         switch (xd->link.link_speed)
1520           {
1521           case ETH_SPEED_NUM_10M:
1522             hw_flags |= VNET_HW_INTERFACE_FLAG_SPEED_10M;
1523             break;
1524           case ETH_SPEED_NUM_100M:
1525             hw_flags |= VNET_HW_INTERFACE_FLAG_SPEED_100M;
1526             break;
1527           case ETH_SPEED_NUM_1G:
1528             hw_flags |= VNET_HW_INTERFACE_FLAG_SPEED_1G;
1529             break;
1530           case ETH_SPEED_NUM_10G:
1531             hw_flags |= VNET_HW_INTERFACE_FLAG_SPEED_10G;
1532             break;
1533           case ETH_SPEED_NUM_40G:
1534             hw_flags |= VNET_HW_INTERFACE_FLAG_SPEED_40G;
1535             break;
1536     case 0:
1537       break;
1538     default:
1539       clib_warning("unknown link speed %d", xd->link.link_speed);
1540             break;
1541           }
1542       }
1543 #else
1544     if (hw_flags_chg || (xd->link.link_speed != prev_link.link_speed))
1545       {
1546         hw_flags_chg = 1;
1547         switch (xd->link.link_speed)
1548           {
1549           case ETH_LINK_SPEED_10:
1550             hw_flags |= VNET_HW_INTERFACE_FLAG_SPEED_10M;
1551             break;
1552           case ETH_LINK_SPEED_100:
1553             hw_flags |= VNET_HW_INTERFACE_FLAG_SPEED_100M;
1554             break;
1555           case ETH_LINK_SPEED_1000:
1556             hw_flags |= VNET_HW_INTERFACE_FLAG_SPEED_1G;
1557             break;
1558           case ETH_LINK_SPEED_10000:
1559             hw_flags |= VNET_HW_INTERFACE_FLAG_SPEED_10G;
1560             break;
1561           case ETH_LINK_SPEED_40G:
1562             hw_flags |= VNET_HW_INTERFACE_FLAG_SPEED_40G;
1563             break;
1564     case 0:
1565       break;
1566     default:
1567       clib_warning("unknown link speed %d", xd->link.link_speed);
1568             break;
1569           }
1570       }
1571 #endif
1572     if (hw_flags_chg)
1573       {
1574         if (LINK_STATE_ELOGS)
1575           {
1576             vlib_main_t * vm = vlib_get_main();
1577
1578             ELOG_TYPE_DECLARE(e) = {
1579               .format = "update-link-state: sw_if_index %d, new flags %d",
1580               .format_args = "i4i4",
1581             };
1582
1583             struct { u32 sw_if_index; u32 flags; } *ed;
1584             ed = ELOG_DATA (&vm->elog_main, e);
1585             ed->sw_if_index = xd->vlib_sw_if_index;
1586             ed->flags = hw_flags;
1587           }
1588         vnet_hw_interface_set_flags (vnm, xd->vlib_hw_if_index, hw_flags);
1589       }
1590 }
1591
1592 static uword
1593 dpdk_process (vlib_main_t * vm,
1594               vlib_node_runtime_t * rt,
1595               vlib_frame_t * f)
1596 {
1597   clib_error_t * error;
1598   vnet_main_t * vnm = vnet_get_main();
1599   dpdk_main_t * dm = &dpdk_main;
1600   ethernet_main_t * em = &ethernet_main;
1601   dpdk_device_t * xd;
1602   vlib_thread_main_t * tm = vlib_get_thread_main();
1603   void *vu_state;
1604   int i;
1605
1606   error = dpdk_lib_init (dm);
1607
1608   /* 
1609    * Turn on the input node if we found some devices to drive
1610    * and we're not running worker threads or i/o threads
1611    */
1612
1613   if (error == 0 && vec_len(dm->devices) > 0)
1614     {
1615         if (tm->n_vlib_mains == 1)
1616           vlib_node_set_state (vm, dpdk_input_node.index,
1617                                VLIB_NODE_STATE_POLLING);
1618         else if (tm->main_thread_is_io_node)
1619           vlib_node_set_state (vm, dpdk_io_input_node.index,
1620                                VLIB_NODE_STATE_POLLING);
1621         else if (!dm->have_io_threads)
1622           for (i=0; i < tm->n_vlib_mains; i++)
1623             if (vec_len(dm->devices_by_cpu[i]) > 0)
1624               vlib_node_set_state (vlib_mains[i], dpdk_input_node.index,
1625                                    VLIB_NODE_STATE_POLLING);
1626     }
1627
1628   if (error)
1629     clib_error_report (error);
1630
1631   dpdk_vhost_user_process_init(&vu_state);
1632
1633   dm->io_thread_release = 1;
1634
1635   f64 now = vlib_time_now (vm);
1636   vec_foreach (xd, dm->devices)
1637     {
1638       dpdk_update_link_state (xd, now);
1639     }
1640
1641 { // Setup MACs for bond interfaces and their links which was initialized in
1642   // dpdk_port_setup() but needs to be done again here to take effect.
1643   int nports = rte_eth_dev_count();
1644   if (nports > 0) {
1645       for (i = 0; i < nports; i++) {
1646           struct rte_eth_dev_info dev_info;
1647           rte_eth_dev_info_get(i, &dev_info);
1648           if (!dev_info.driver_name)
1649               dev_info.driver_name = dev_info.pci_dev->driver->name;
1650           ASSERT(dev_info.driver_name);
1651           if (strncmp(dev_info.driver_name, "rte_bond_pmd", 12) == 0) {
1652               u8  addr[6]; 
1653               u8  slink[16];
1654               int nlink = rte_eth_bond_slaves_get(i, slink, 16);
1655               if (nlink > 0) {
1656                   vnet_hw_interface_t * bhi;
1657                   ethernet_interface_t * bei;
1658                   /* Get MAC of 1st slave link */
1659                   rte_eth_macaddr_get(slink[0], (struct ether_addr *)addr);
1660                   /* Set MAC of bounded interface to that of 1st slave link */
1661                   rte_eth_bond_mac_address_set(i, (struct ether_addr *)addr);
1662                   /* Populate MAC of bonded interface in VPP hw tables */
1663                   bhi = vnet_get_hw_interface(
1664                       vnm, dm->devices[i].vlib_hw_if_index);
1665                   bei = pool_elt_at_index(em->interfaces, bhi->hw_instance);
1666                   memcpy(bhi->hw_address, addr, 6);
1667                   memcpy(bei->address, addr, 6);
1668                   while (nlink >= 1) { /* for all slave links */
1669                       int slave = slink[--nlink];
1670                       dpdk_device_t * sdev = &dm->devices[slave];
1671                       vnet_hw_interface_t * shi;
1672                       vnet_sw_interface_t * ssi;
1673                       /* Add MAC to all slave links except the first one */
1674                       if (nlink) rte_eth_dev_mac_addr_add(
1675                           slave, (struct ether_addr *)addr, 0);
1676                       /* Set slaves bitmap for bonded interface */
1677                       bhi->bond_info = clib_bitmap_set(
1678                           bhi->bond_info, sdev->vlib_hw_if_index, 1);
1679                       /* Set slave link flags on slave interface */
1680                       shi = vnet_get_hw_interface(vnm, sdev->vlib_hw_if_index);
1681                       ssi = vnet_get_sw_interface(vnm, sdev->vlib_sw_if_index);
1682                       shi->bond_info = VNET_HW_INTERFACE_BOND_INFO_SLAVE;
1683                       ssi->flags |= VNET_SW_INTERFACE_FLAG_BOND_SLAVE;
1684                   }
1685               }
1686           }
1687       }
1688   }
1689 }
1690
1691   while (1)
1692     {
1693       /*
1694        * check each time through the loop in case intervals are changed
1695        */
1696       f64 min_wait = dm->link_state_poll_interval < dm->stat_poll_interval ?
1697                      dm->link_state_poll_interval : dm->stat_poll_interval;
1698
1699       vlib_process_wait_for_event_or_clock (vm, min_wait);
1700
1701       if (dpdk_get_admin_up_down_in_progress())
1702           /* skip the poll if an admin up down is in progress (on any interface) */
1703           continue;
1704
1705       vec_foreach (xd, dm->devices)
1706         {
1707           f64 now = vlib_time_now (vm);
1708           if ((now - xd->time_last_stats_update) >= dm->stat_poll_interval)
1709             dpdk_update_counters (xd, now);
1710           if ((now - xd->time_last_link_update) >= dm->link_state_poll_interval)
1711             dpdk_update_link_state (xd, now);
1712
1713       if (xd->dev_type == VNET_DPDK_DEV_VHOST_USER)
1714           if (dpdk_vhost_user_process_if(vm, xd, vu_state) != 0)
1715               continue;
1716         }
1717     }
1718
1719   dpdk_vhost_user_process_cleanup(vu_state);
1720
1721   return 0; 
1722 }
1723
1724 VLIB_REGISTER_NODE (dpdk_process_node,static) = {
1725     .function = dpdk_process,
1726     .type = VLIB_NODE_TYPE_PROCESS,
1727     .name = "dpdk-process",
1728     .process_log2_n_stack_bytes = 17,
1729 };
1730
1731 int dpdk_set_stat_poll_interval (f64 interval)
1732 {
1733   if (interval < DPDK_MIN_STATS_POLL_INTERVAL)
1734       return (VNET_API_ERROR_INVALID_VALUE);
1735
1736   dpdk_main.stat_poll_interval = interval;
1737
1738   return 0;
1739 }
1740
1741 int dpdk_set_link_state_poll_interval (f64 interval)
1742 {
1743   if (interval < DPDK_MIN_LINK_POLL_INTERVAL)
1744       return (VNET_API_ERROR_INVALID_VALUE);
1745
1746   dpdk_main.link_state_poll_interval = interval;
1747
1748   return 0;
1749 }
1750
1751 clib_error_t *
1752 dpdk_init (vlib_main_t * vm)
1753 {
1754   dpdk_main_t * dm = &dpdk_main;
1755   vlib_node_t * ei;
1756   clib_error_t * error = 0;
1757   vlib_thread_main_t * tm = vlib_get_thread_main();
1758
1759   /* verify that structs are cacheline aligned */
1760   ASSERT(offsetof(dpdk_device_t, cacheline0) == 0);
1761   ASSERT(offsetof(dpdk_device_t, cacheline1) == CLIB_CACHE_LINE_BYTES);
1762   ASSERT(offsetof(dpdk_worker_t, cacheline0) == 0);
1763   ASSERT(offsetof(frame_queue_trace_t, cacheline0) == 0);
1764
1765   dm->vlib_main = vm;
1766   dm->vnet_main = vnet_get_main();
1767
1768   ei = vlib_get_node_by_name (vm, (u8 *) "ethernet-input");
1769   if (ei == 0)
1770       return clib_error_return (0, "ethernet-input node AWOL");
1771
1772   dm->ethernet_input_node_index = ei->index;
1773
1774   dm->nchannels = 4;
1775   dm->num_mbufs = dm->num_mbufs ? dm->num_mbufs : NB_MBUF;
1776   vec_add1 (dm->eal_init_args, (u8 *) "vnet");
1777
1778   dm->dpdk_device_by_kni_port_id = hash_create (0, sizeof (uword));
1779   dm->vu_sw_if_index_by_listener_fd = hash_create (0, sizeof (uword));
1780   dm->vu_sw_if_index_by_sock_fd = hash_create (0, sizeof (uword));
1781
1782   /* $$$ use n_thread_stacks since it's known-good at this point */
1783   vec_validate (dm->recycle, tm->n_thread_stacks - 1);
1784
1785   /* initialize EFD (early fast discard) default settings */
1786   dm->efd.enabled = DPDK_EFD_DISABLED;
1787   dm->efd.queue_hi_thresh = ((DPDK_EFD_DEFAULT_DEVICE_QUEUE_HI_THRESH_PCT *
1788                               DPDK_NB_RX_DESC_10GE)/100);
1789   dm->efd.consec_full_frames_hi_thresh =
1790       DPDK_EFD_DEFAULT_CONSEC_FULL_FRAMES_HI_THRESH;
1791
1792   /* vhost-user coalescence frames defaults */
1793   dm->vhost_coalesce_frames = 32;
1794   dm->vhost_coalesce_time = 1e-3;
1795
1796   /* Default vlib_buffer_t flags, DISABLES tcp/udp checksumming... */
1797   dm->buffer_flags_template = 
1798     (VLIB_BUFFER_TOTAL_LENGTH_VALID 
1799      | IP_BUFFER_L4_CHECKSUM_COMPUTED
1800      | IP_BUFFER_L4_CHECKSUM_CORRECT);
1801
1802   dm->stat_poll_interval = DPDK_STATS_POLL_INTERVAL;
1803   dm->link_state_poll_interval = DPDK_LINK_POLL_INTERVAL;
1804
1805   /* init CLI */
1806   if ((error = vlib_call_init_function (vm, dpdk_cli_init)))
1807     return error;
1808
1809   return error;
1810 }
1811
1812 VLIB_INIT_FUNCTION (dpdk_init);
1813