dpdk: limit number of TX queues to max supported
[vpp.git] / src / plugins / dpdk / device / 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 #include <vppinfra/linux/sysfs.h>
21 #include <vlib/unix/unix.h>
22 #include <vlib/log.h>
23
24 #include <vnet/vnet.h>
25 #include <vnet/ethernet/ethernet.h>
26 #include <vnet/interface/rx_queue_funcs.h>
27 #include <dpdk/buffer.h>
28 #include <dpdk/device/dpdk.h>
29 #include <dpdk/cryptodev/cryptodev.h>
30 #include <vlib/pci/pci.h>
31 #include <vlib/vmbus/vmbus.h>
32
33 #include <rte_ring.h>
34 #include <rte_vect.h>
35
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <unistd.h>
39 #include <sys/stat.h>
40 #include <sys/mount.h>
41 #include <string.h>
42 #include <fcntl.h>
43 #include <dirent.h>
44
45 #include <dpdk/device/dpdk_priv.h>
46
47 dpdk_main_t dpdk_main;
48 dpdk_config_main_t dpdk_config_main;
49
50 #define LINK_STATE_ELOGS        0
51
52 /* dev_info.speed_capa -> interface name mapppings */
53 const struct
54 {
55   u32 link_speed;
56   const char *pfx;
57 } if_name_prefixes[] = {
58   /* sorted, higher speed first */
59   { ETH_LINK_SPEED_200G, "TwoHundredGigabitEthernet" },
60   { ETH_LINK_SPEED_100G, "HundredGigabitEthernet" },
61   { ETH_LINK_SPEED_56G, "FiftySixGigabitEthernet" },
62   { ETH_LINK_SPEED_50G, "FiftyGigabitEthernet" },
63   { ETH_LINK_SPEED_40G, "FortyGigabitEthernet" },
64   { ETH_LINK_SPEED_25G, "TwentyFiveGigabitEthernet" },
65   { ETH_LINK_SPEED_20G, "TwentyGigabitEthernet" },
66   { ETH_LINK_SPEED_10G, "TenGigabitEthernet" },
67   { ETH_LINK_SPEED_5G, "FiveGigabitEthernet" },
68   { ETH_LINK_SPEED_2_5G, "TwoDotFiveGigabitEthernet" },
69   { ETH_LINK_SPEED_1G, "GigabitEthernet" },
70 };
71
72 static clib_error_t *
73 dpdk_set_max_frame_size (vnet_main_t *vnm, vnet_hw_interface_t *hi,
74                          u32 frame_size)
75 {
76   dpdk_main_t *dm = &dpdk_main;
77   dpdk_device_t *xd = vec_elt_at_index (dm->devices, hi->dev_instance);
78   int rv;
79   u32 mtu;
80
81   mtu = frame_size - xd->driver_frame_overhead;
82
83   rv = rte_eth_dev_set_mtu (xd->port_id, mtu);
84
85   if (rv < 0)
86     {
87       dpdk_log_err ("[%u] rte_eth_dev_set_mtu failed (mtu %u, rv %d)",
88                     xd->port_id, mtu, rv);
89       switch (rv)
90         {
91         case -ENOTSUP:
92           return vnet_error (VNET_ERR_UNSUPPORTED,
93                              "dpdk driver doesn't support MTU change");
94         case -EBUSY:
95           return vnet_error (VNET_ERR_BUSY, "port is running");
96         case -EINVAL:
97           return vnet_error (VNET_ERR_INVALID_VALUE, "invalid MTU");
98         default:
99           return vnet_error (VNET_ERR_BUG,
100                              "unexpected return value %d returned from "
101                              "rte_eth_dev_set_mtu(...)",
102                              rv);
103         }
104     }
105   else
106     dpdk_log_debug ("[%u] max_frame_size set to %u by setting MTU to %u",
107                     xd->port_id, frame_size, mtu);
108
109   return 0;
110 }
111
112 static u32
113 dpdk_flag_change (vnet_main_t * vnm, vnet_hw_interface_t * hi, u32 flags)
114 {
115   dpdk_main_t *dm = &dpdk_main;
116   dpdk_device_t *xd = vec_elt_at_index (dm->devices, hi->dev_instance);
117   u32 old = (xd->flags & DPDK_DEVICE_FLAG_PROMISC) != 0;
118
119   switch (flags)
120     {
121     case ETHERNET_INTERFACE_FLAG_DEFAULT_L3:
122       /* set to L3/non-promisc mode */
123       dpdk_device_flag_set (xd, DPDK_DEVICE_FLAG_PROMISC, 0);
124       break;
125     case ETHERNET_INTERFACE_FLAG_ACCEPT_ALL:
126       dpdk_device_flag_set (xd, DPDK_DEVICE_FLAG_PROMISC, 1);
127       break;
128     default:
129       return ~0;
130     }
131
132   if (xd->flags & DPDK_DEVICE_FLAG_ADMIN_UP)
133     {
134       if (xd->flags & DPDK_DEVICE_FLAG_PROMISC)
135         rte_eth_promiscuous_enable (xd->port_id);
136       else
137         rte_eth_promiscuous_disable (xd->port_id);
138     }
139
140   return old;
141 }
142
143 /* The function check_l3cache helps check if Level 3 cache exists or not on current CPUs
144   return value 1: exist.
145   return value 0: not exist.
146 */
147 static int
148 check_l3cache ()
149 {
150
151   struct dirent *dp;
152   clib_error_t *err;
153   const char *sys_cache_dir = "/sys/devices/system/cpu/cpu0/cache";
154   DIR *dir_cache = opendir (sys_cache_dir);
155
156   if (dir_cache == NULL)
157     return -1;
158
159   while ((dp = readdir (dir_cache)) != NULL)
160     {
161       if (dp->d_type == DT_DIR)
162         {
163           u8 *p = NULL;
164           int level_cache = -1;
165
166           p = format (p, "%s/%s/%s%c", sys_cache_dir, dp->d_name, "level", 0);
167           if ((err = clib_sysfs_read ((char *) p, "%d", &level_cache)))
168             clib_error_free (err);
169
170           if (level_cache == 3)
171             {
172               closedir (dir_cache);
173               return 1;
174             }
175         }
176     }
177
178   if (dir_cache != NULL)
179     closedir (dir_cache);
180
181   return 0;
182 }
183
184 static dpdk_device_config_t *
185 dpdk_find_startup_config (struct rte_eth_dev_info *di)
186 {
187   dpdk_main_t *dm = &dpdk_main;
188   struct rte_pci_device *pci_dev;
189   struct rte_vmbus_device *vmbus_dev;
190   vlib_pci_addr_t pci_addr;
191   vlib_vmbus_addr_t vmbus_addr;
192   uword *p = 0;
193
194   if ((pci_dev = dpdk_get_pci_device (di)))
195     {
196       pci_addr.domain = pci_dev->addr.domain;
197       pci_addr.bus = pci_dev->addr.bus;
198       pci_addr.slot = pci_dev->addr.devid;
199       pci_addr.function = pci_dev->addr.function;
200       p =
201         hash_get (dm->conf->device_config_index_by_pci_addr, pci_addr.as_u32);
202     }
203
204   if ((vmbus_dev = dpdk_get_vmbus_device (di)))
205     {
206       unformat_input_t input_vmbus;
207       unformat_init_string (&input_vmbus, di->device->name,
208                             strlen (di->device->name));
209       if (unformat (&input_vmbus, "%U", unformat_vlib_vmbus_addr, &vmbus_addr))
210         p = mhash_get (&dm->conf->device_config_index_by_vmbus_addr,
211                        &vmbus_addr);
212       unformat_free (&input_vmbus);
213     }
214
215   if (p)
216     return pool_elt_at_index (dm->conf->dev_confs, p[0]);
217   return &dm->conf->default_devconf;
218 }
219
220 static clib_error_t *
221 dpdk_lib_init (dpdk_main_t * dm)
222 {
223   vnet_main_t *vnm = vnet_get_main ();
224   u16 port_id;
225   vlib_thread_main_t *tm = vlib_get_thread_main ();
226   vnet_device_main_t *vdm = &vnet_device_main;
227   vnet_sw_interface_t *sw;
228   vnet_hw_interface_t *hi;
229   dpdk_device_t *xd;
230   char *if_num_fmt;
231
232   /* vlib_buffer_t template */
233   vec_validate_aligned (dm->per_thread_data, tm->n_vlib_mains - 1,
234                         CLIB_CACHE_LINE_BYTES);
235   for (int i = 0; i < tm->n_vlib_mains; i++)
236     {
237       dpdk_per_thread_data_t *ptd = vec_elt_at_index (dm->per_thread_data, i);
238       clib_memset (&ptd->buffer_template, 0, sizeof (vlib_buffer_t));
239       vnet_buffer (&ptd->buffer_template)->sw_if_index[VLIB_TX] = (u32) ~ 0;
240     }
241
242   if_num_fmt =
243     dm->conf->interface_name_format_decimal ? "%d/%d/%d" : "%x/%x/%x";
244
245   /* device config defaults */
246   dm->default_port_conf.n_rx_desc = DPDK_NB_RX_DESC_DEFAULT;
247   dm->default_port_conf.n_tx_desc = DPDK_NB_TX_DESC_DEFAULT;
248   dm->default_port_conf.n_rx_queues = 1;
249   dm->default_port_conf.n_tx_queues = tm->n_vlib_mains;
250   dm->default_port_conf.rss_hf = ETH_RSS_IP | ETH_RSS_UDP | ETH_RSS_TCP;
251   dm->default_port_conf.max_lro_pkt_size = DPDK_MAX_LRO_SIZE_DEFAULT;
252
253   if ((clib_mem_get_default_hugepage_size () == 2 << 20) &&
254       check_l3cache () == 0)
255     dm->default_port_conf.n_rx_desc = dm->default_port_conf.n_tx_desc = 512;
256
257   RTE_ETH_FOREACH_DEV (port_id)
258     {
259       u8 addr[6];
260       int rv, q;
261       struct rte_eth_dev_info di;
262       dpdk_device_config_t *devconf = 0;
263       vnet_eth_interface_registration_t eir = {};
264       dpdk_driver_t *dr;
265
266       if (!rte_eth_dev_is_valid_port (port_id))
267         continue;
268
269       if ((rv = rte_eth_dev_info_get (port_id, &di)) != 0)
270         {
271           dpdk_log_warn ("[%u] failed to get device info. skipping device.",
272                          port_id);
273           continue;
274         }
275
276       if (di.device == 0)
277         {
278           dpdk_log_warn ("[%u] missing device info. Skipping '%s' device",
279                          port_id, di.driver_name);
280           continue;
281         }
282
283       devconf = dpdk_find_startup_config (&di);
284
285       /* If device is blacklisted, we should skip it */
286       if (devconf->is_blacklisted)
287         {
288           dpdk_log_notice ("[%d] Device %s blacklisted. Skipping...", port_id,
289                            di.driver_name);
290           continue;
291         }
292
293       vec_add2_aligned (dm->devices, xd, 1, CLIB_CACHE_LINE_BYTES);
294       xd->port_id = port_id;
295       xd->device_index = xd - dm->devices;
296       xd->per_interface_next_index = ~0;
297
298       clib_memcpy (&xd->conf, &dm->default_port_conf,
299                    sizeof (dpdk_port_conf_t));
300
301       /* find driver datea for this PMD */
302       if ((dr = dpdk_driver_find (di.driver_name, &xd->if_desc)))
303         {
304           xd->driver = dr;
305           xd->supported_flow_actions = dr->supported_flow_actions;
306           xd->conf.disable_rss = dr->mq_mode_none;
307           xd->conf.disable_rx_scatter = dr->disable_rx_scatter;
308           if (dr->use_intel_phdr_cksum)
309             dpdk_device_flag_set (xd, DPDK_DEVICE_FLAG_INTEL_PHDR_CKSUM, 1);
310           if (dr->int_unmaskable)
311             dpdk_device_flag_set (xd, DPDK_DEVICE_FLAG_INT_UNMASKABLE, 1);
312         }
313       else
314         dpdk_log_warn ("[%u] unknown driver '%s'", port_id, di.driver_name);
315
316       if (devconf->name)
317         {
318           xd->name = devconf->name;
319         }
320       else
321         {
322           struct rte_pci_device *pci_dev;
323           if (dr && dr->interface_name_prefix)
324             {
325               /* prefix override by driver */
326               xd->name = format (xd->name, "%s", dr->interface_name_prefix);
327             }
328           else
329             {
330               /* interface name prefix from speed_capa */
331               u64 mask = ~((if_name_prefixes[0].link_speed << 1) - 1);
332
333               if (di.speed_capa & mask)
334                 dpdk_log_warn ("[%u] unknown speed capability 0x%x reported",
335                                xd->port_id, di.speed_capa & mask);
336
337               for (int i = 0; i < ARRAY_LEN (if_name_prefixes); i++)
338                 if (if_name_prefixes[i].link_speed & di.speed_capa)
339                   {
340                     xd->name =
341                       format (xd->name, "%s", if_name_prefixes[i].pfx);
342                     break;
343                   }
344               if (xd->name == 0)
345                 xd->name = format (xd->name, "Ethernet");
346             }
347
348           if (dr && dr->interface_number_from_port_id)
349             xd->name = format (xd->name, "%u", port_id);
350           else if ((pci_dev = dpdk_get_pci_device (&di)))
351             xd->name = format (xd->name, if_num_fmt, pci_dev->addr.bus,
352                                pci_dev->addr.devid, pci_dev->addr.function);
353           else
354             xd->name = format (xd->name, "%u", port_id);
355         }
356
357       /* Handle representor devices that share the same PCI ID */
358       if ((di.switch_info.domain_id != RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID) &&
359           (di.switch_info.port_id != (uint16_t) -1))
360         xd->name = format (xd->name, "/%d", di.switch_info.port_id);
361
362       /* number of RX and TX queues */
363       if (devconf->num_tx_queues > 0)
364         {
365           if (di.max_tx_queues < devconf->num_tx_queues)
366             dpdk_log_warn ("[%u] Configured number of TX queues (%u) is "
367                            "bigger than maximum supported (%u)",
368                            port_id, devconf->num_tx_queues, di.max_tx_queues);
369           xd->conf.n_tx_queues = devconf->num_tx_queues;
370         }
371
372       xd->conf.n_tx_queues = clib_min (di.max_tx_queues, xd->conf.n_tx_queues);
373
374       if (devconf->num_rx_queues > 1 &&
375           di.max_rx_queues >= devconf->num_rx_queues)
376         {
377           xd->conf.n_rx_queues = devconf->num_rx_queues;
378           if (devconf->rss_fn)
379             {
380               u64 unsupported_bits;
381               xd->conf.rss_hf = devconf->rss_fn;
382               unsupported_bits = xd->conf.rss_hf;
383               unsupported_bits &= ~di.flow_type_rss_offloads;
384               if (unsupported_bits)
385                 dpdk_log_warn ("Unsupported RSS hash functions: %U",
386                                format_dpdk_rss_hf_name, unsupported_bits);
387             }
388           xd->conf.rss_hf &= di.flow_type_rss_offloads;
389           dpdk_log_debug ("[%u] rss_hf: %U", port_id, format_dpdk_rss_hf_name,
390                           xd->conf.rss_hf);
391         }
392
393       xd->driver_frame_overhead =
394         RTE_ETHER_HDR_LEN + 2 * RTE_VLAN_HLEN + RTE_ETHER_CRC_LEN;
395 #if RTE_VERSION >= RTE_VERSION_NUM(21, 11, 0, 0)
396       q = di.max_rx_pktlen - di.max_mtu;
397
398       if (q < xd->driver_frame_overhead && q > 0)
399         xd->driver_frame_overhead = q;
400       dpdk_log_debug ("[%u] min_mtu: %u, max_mtu: %u, min_rx_bufsize: %u, "
401                       "max_rx_pktlen: %u, max_lro_pkt_size: %u",
402                       xd->port_id, di.min_mtu, di.max_mtu, di.min_rx_bufsize,
403                       di.max_rx_pktlen, di.max_lro_pkt_size);
404 #endif
405       dpdk_log_debug ("[%u] driver frame overhead is %u", port_id,
406                       xd->driver_frame_overhead);
407
408       /* number of RX and TX tescriptors */
409       if (devconf->num_rx_desc)
410         xd->conf.n_rx_desc = devconf->num_rx_desc;
411       else if (dr && dr->n_rx_desc)
412         xd->conf.n_rx_desc = dr->n_rx_desc;
413
414       if (devconf->num_tx_desc)
415         xd->conf.n_tx_desc = devconf->num_tx_desc;
416       else if (dr && dr->n_tx_desc)
417         xd->conf.n_tx_desc = dr->n_tx_desc;
418
419       dpdk_log_debug (
420         "[%u] n_rx_queues: %u n_tx_queues: %u n_rx_desc: %u n_tx_desc: %u",
421         port_id, xd->conf.n_rx_queues, xd->conf.n_tx_queues,
422         xd->conf.n_rx_desc, xd->conf.n_tx_desc);
423
424       vec_validate_aligned (xd->rx_queues, xd->conf.n_rx_queues - 1,
425                             CLIB_CACHE_LINE_BYTES);
426
427       rte_eth_macaddr_get (port_id, (void *) addr);
428
429       /* create interface */
430       eir.dev_class_index = dpdk_device_class.index;
431       eir.dev_instance = xd->device_index;
432       eir.address = addr;
433       eir.cb.flag_change = dpdk_flag_change;
434       eir.cb.set_max_frame_size = dpdk_set_max_frame_size;
435       xd->hw_if_index = vnet_eth_register_interface (vnm, &eir);
436       hi = vnet_get_hw_interface (vnm, xd->hw_if_index);
437       hi->numa_node = xd->cpu_socket = (i8) rte_eth_dev_socket_id (port_id);
438       sw = vnet_get_hw_sw_interface (vnm, xd->hw_if_index);
439       xd->sw_if_index = sw->sw_if_index;
440       dpdk_log_debug ("[%u] interface %s created", port_id, hi->name);
441
442       ethernet_set_flags (vnm, xd->hw_if_index,
443                           ETHERNET_INTERFACE_FLAG_DEFAULT_L3);
444
445       /* assign worker threads */
446       vnet_hw_if_set_input_node (vnm, xd->hw_if_index, dpdk_input_node.index);
447       if (devconf->workers)
448         {
449           int j;
450           q = 0;
451           clib_bitmap_foreach (j, devconf->workers)
452             {
453               dpdk_rx_queue_t *rxq = vec_elt_at_index (xd->rx_queues, q);
454               rxq->queue_index = vnet_hw_if_register_rx_queue (
455                 vnm, xd->hw_if_index, q++, vdm->first_worker_thread_index + j);
456             }
457         }
458       else
459         for (q = 0; q < xd->conf.n_rx_queues; q++)
460           {
461             dpdk_rx_queue_t *rxq = vec_elt_at_index (xd->rx_queues, q);
462             rxq->queue_index = vnet_hw_if_register_rx_queue (
463               vnm, xd->hw_if_index, q, VNET_HW_IF_RXQ_THREAD_ANY);
464           }
465
466       if (devconf->tso == DPDK_DEVICE_TSO_ON)
467         {
468           /*tcp_udp checksum must be enabled*/
469           if (xd->conf.enable_tcp_udp_checksum == 0)
470             dpdk_log_warn ("[%u] TCP/UDP checksum offload must be enabled",
471                            xd->port_id);
472           else if ((di.tx_offload_capa & DEV_TX_OFFLOAD_TCP_TSO) == 0)
473             dpdk_log_warn ("[%u] TSO not supported by device", xd->port_id);
474           else
475             xd->conf.enable_tso = 1;
476         }
477
478       if (devconf->max_lro_pkt_size)
479         xd->conf.max_lro_pkt_size = devconf->max_lro_pkt_size;
480
481       dpdk_device_setup (xd);
482
483       /* rss queues should be configured after dpdk_device_setup() */
484       if (devconf->rss_queues)
485         {
486           if (vnet_hw_interface_set_rss_queues (vnet_get_main (), hi,
487                                                 devconf->rss_queues))
488             dpdk_log_warn ("[%u] Failed to set rss queues", port_id);
489         }
490
491       if (vec_len (xd->errors))
492         dpdk_log_err ("[%u] setup failed Errors:\n  %U", port_id,
493                       format_dpdk_device_errors, xd);
494     }
495
496   for (int i = 0; i < vec_len (dm->devices); i++)
497     vnet_hw_if_update_runtime_data (vnm, dm->devices[i].hw_if_index);
498
499   return 0;
500 }
501
502 static void
503 dpdk_bind_devices_to_uio (dpdk_config_main_t * conf)
504 {
505   vlib_main_t *vm = vlib_get_main ();
506   clib_error_t *error;
507   u8 *pci_addr = 0;
508   int num_whitelisted = vec_len (conf->dev_confs);
509   vlib_pci_device_info_t *d = 0;
510   vlib_pci_addr_t *addr = 0, *addrs;
511   int i;
512
513   addrs = vlib_pci_get_all_dev_addrs ();
514   /* *INDENT-OFF* */
515   vec_foreach (addr, addrs)
516     {
517     dpdk_device_config_t * devconf = 0;
518     vec_reset_length (pci_addr);
519     pci_addr = format (pci_addr, "%U%c", format_vlib_pci_addr, addr, 0);
520     if (d)
521     {
522       vlib_pci_free_device_info (d);
523       d = 0;
524       }
525     d = vlib_pci_get_device_info (vm, addr, &error);
526     if (error)
527     {
528       vlib_log_warn (dpdk_main.log_default, "%U", format_clib_error, error);
529       clib_error_free (error);
530       continue;
531     }
532
533     if (d->device_class != PCI_CLASS_NETWORK_ETHERNET && d->device_class != PCI_CLASS_PROCESSOR_CO)
534       continue;
535
536     if (num_whitelisted)
537       {
538         uword * p = hash_get (conf->device_config_index_by_pci_addr, addr->as_u32);
539
540         if (!p)
541           {
542           skipped_pci:
543             continue;
544           }
545
546         devconf = pool_elt_at_index (conf->dev_confs, p[0]);
547       }
548
549     /* Enforce Device blacklist by vendor and device */
550     for (i = 0; i < vec_len (conf->blacklist_by_pci_vendor_and_device); i++)
551       {
552         u16 vendor, device;
553         vendor = (u16)(conf->blacklist_by_pci_vendor_and_device[i] >> 16);
554         device = (u16)(conf->blacklist_by_pci_vendor_and_device[i] & 0xFFFF);
555         if (d->vendor_id == vendor && d->device_id == device)
556           {
557             /*
558              * Expected case: device isn't whitelisted,
559              * so blacklist it...
560              */
561             if (devconf == 0)
562               {
563                 /* Device is blacklisted */
564                 pool_get (conf->dev_confs, devconf);
565                 hash_set (conf->device_config_index_by_pci_addr, addr->as_u32,
566                           devconf - conf->dev_confs);
567                 devconf->pci_addr.as_u32 = addr->as_u32;
568                 devconf->dev_addr_type = VNET_DEV_ADDR_PCI;
569                 devconf->is_blacklisted = 1;
570                 goto skipped_pci;
571               }
572             else /* explicitly whitelisted, ignore the device blacklist  */
573               break;
574           }
575       }
576
577     /* virtio */
578     if (d->vendor_id == 0x1af4 &&
579             (d->device_id == VIRTIO_PCI_LEGACY_DEVICEID_NET ||
580              d->device_id == VIRTIO_PCI_MODERN_DEVICEID_NET))
581       ;
582     /* vmxnet3 */
583     else if (d->vendor_id == 0x15ad && d->device_id == 0x07b0)
584       {
585         /*
586          * For vmxnet3 PCI, unless it is explicitly specified in the whitelist,
587          * the default is to put it in the blacklist.
588          */
589         if (devconf == 0)
590           {
591             pool_get (conf->dev_confs, devconf);
592             hash_set (conf->device_config_index_by_pci_addr, addr->as_u32,
593                       devconf - conf->dev_confs);
594             devconf->pci_addr.as_u32 = addr->as_u32;
595             devconf->is_blacklisted = 1;
596           }
597       }
598     /* all Intel network devices */
599     else if (d->vendor_id == 0x8086 && d->device_class == PCI_CLASS_NETWORK_ETHERNET)
600       ;
601     /* all Intel QAT devices VFs */
602     else if (d->vendor_id == 0x8086 && d->device_class == PCI_CLASS_PROCESSOR_CO &&
603         (d->device_id == 0x0443 || d->device_id == 0x18a1 || d->device_id == 0x19e3 ||
604         d->device_id == 0x37c9 || d->device_id == 0x6f55))
605       ;
606     /* Cisco VIC */
607     else if (d->vendor_id == 0x1137 &&
608         (d->device_id == 0x0043 || d->device_id == 0x0071))
609       ;
610     /* Chelsio T4/T5 */
611     else if (d->vendor_id == 0x1425 && (d->device_id & 0xe000) == 0x4000)
612       ;
613     /* Amazon Elastic Network Adapter */
614     else if (d->vendor_id == 0x1d0f && d->device_id >= 0xec20 && d->device_id <= 0xec21)
615       ;
616     /* Cavium Network Adapter */
617     else if (d->vendor_id == 0x177d && d->device_id == 0x9712)
618       ;
619     /* Cavium FastlinQ QL41000 Series */
620     else if (d->vendor_id == 0x1077 && d->device_id >= 0x8070 && d->device_id <= 0x8090)
621       ;
622     /* Mellanox CX3, CX3VF */
623     else if (d->vendor_id == 0x15b3 && d->device_id >= 0x1003 && d->device_id <= 0x1004)
624       {
625         continue;
626       }
627     /* Mellanox CX4, CX4VF, CX4LX, CX4LXVF, CX5, CX5VF, CX5EX, CX5EXVF */
628     else if (d->vendor_id == 0x15b3 && d->device_id >= 0x1013 && d->device_id <= 0x101a)
629       {
630         continue;
631       }
632     /* Mellanox CX6, CX6VF, CX6DX, CX6DXVF */
633     else if (d->vendor_id == 0x15b3 && d->device_id >= 0x101b && d->device_id <= 0x101e)
634       {
635         continue;
636       }
637     /* Broadcom NetXtreme S, and E series only */
638     else if (d->vendor_id == 0x14e4 &&
639         ((d->device_id >= 0x16c0 &&
640                 d->device_id != 0x16c6 && d->device_id != 0x16c7 &&
641                 d->device_id != 0x16dd && d->device_id != 0x16f7 &&
642                 d->device_id != 0x16fd && d->device_id != 0x16fe &&
643                 d->device_id != 0x170d && d->device_id != 0x170c &&
644                 d->device_id != 0x170e && d->device_id != 0x1712 &&
645                 d->device_id != 0x1713) ||
646         (d->device_id == 0x1604 || d->device_id == 0x1605 ||
647          d->device_id == 0x1614 || d->device_id == 0x1606 ||
648          d->device_id == 0x1609 || d->device_id == 0x1614)))
649       ;
650     else
651       {
652         dpdk_log_warn ("Unsupported PCI device 0x%04x:0x%04x found "
653                       "at PCI address %s\n", (u16) d->vendor_id, (u16) d->device_id,
654                       pci_addr);
655         continue;
656       }
657
658     error = vlib_pci_bind_to_uio (vm, addr, (char *) conf->uio_driver_name);
659
660     if (error)
661       {
662         if (devconf == 0)
663           {
664             pool_get (conf->dev_confs, devconf);
665             hash_set (conf->device_config_index_by_pci_addr, addr->as_u32,
666                       devconf - conf->dev_confs);
667             devconf->pci_addr.as_u32 = addr->as_u32;
668           }
669         devconf->dev_addr_type = VNET_DEV_ADDR_PCI;
670         devconf->is_blacklisted = 1;
671         clib_error_report (error);
672       }
673   }
674   /* *INDENT-ON* */
675   vec_free (pci_addr);
676   vlib_pci_free_device_info (d);
677 }
678
679 static void
680 dpdk_bind_vmbus_devices_to_uio (dpdk_config_main_t * conf)
681 {
682   clib_error_t *error;
683   vlib_vmbus_addr_t *addrs, *addr = 0;
684   int num_whitelisted = vec_len (conf->dev_confs);
685   int i;
686
687   addrs = vlib_vmbus_get_all_dev_addrs ();
688
689   /* *INDENT-OFF* */
690   vec_foreach (addr, addrs)
691     {
692       dpdk_device_config_t *devconf = 0;
693       if (num_whitelisted)
694         {
695           uword *p =
696             mhash_get (&conf->device_config_index_by_vmbus_addr, addr);
697           if (!p)
698             {
699               /* No devices blacklisted, but have whitelisted. blacklist all
700                * non-whitelisted */
701               pool_get (conf->dev_confs, devconf);
702               mhash_set (&conf->device_config_index_by_vmbus_addr, addr,
703                          devconf - conf->dev_confs, 0);
704               devconf->vmbus_addr = *addr;
705               devconf->dev_addr_type = VNET_DEV_ADDR_VMBUS;
706               devconf->is_blacklisted = 1;
707             skipped_vmbus:
708               continue;
709             }
710
711           devconf = pool_elt_at_index (conf->dev_confs, p[0]);
712         }
713
714       /* Enforce Device blacklist by vmbus_addr */
715       for (i = 0; i < vec_len (conf->blacklist_by_vmbus_addr); i++)
716         {
717           vlib_vmbus_addr_t *a1 = &conf->blacklist_by_vmbus_addr[i];
718           vlib_vmbus_addr_t *a2 = addr;
719           if (memcmp (a1, a2, sizeof (vlib_vmbus_addr_t)) == 0)
720             {
721               if (devconf == 0)
722                 {
723                   /* Device not whitelisted */
724                   pool_get (conf->dev_confs, devconf);
725                   mhash_set (&conf->device_config_index_by_vmbus_addr, addr,
726                              devconf - conf->dev_confs, 0);
727                   devconf->vmbus_addr = *addr;
728                   devconf->dev_addr_type = VNET_DEV_ADDR_VMBUS;
729                   devconf->is_blacklisted = 1;
730                   goto skipped_vmbus;
731                 }
732               else
733                 {
734                   break;
735                 }
736             }
737         }
738
739       error = vlib_vmbus_bind_to_uio (addr);
740       if (error)
741         {
742           if (devconf == 0)
743             {
744               pool_get (conf->dev_confs, devconf);
745               mhash_set (&conf->device_config_index_by_vmbus_addr, addr,
746                          devconf - conf->dev_confs, 0);
747               devconf->vmbus_addr = *addr;
748             }
749           devconf->dev_addr_type = VNET_DEV_ADDR_VMBUS;
750           devconf->is_blacklisted = 1;
751           clib_error_report (error);
752         }
753     }
754   /* *INDENT-ON* */
755 }
756
757 uword
758 unformat_max_simd_bitwidth (unformat_input_t *input, va_list *va)
759 {
760   uword *max_simd_bitwidth = va_arg (*va, uword *);
761
762   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
763     {
764       if (!unformat (input, "%u", max_simd_bitwidth))
765         goto error;
766
767       if (*max_simd_bitwidth != DPDK_MAX_SIMD_BITWIDTH_256 &&
768           *max_simd_bitwidth != DPDK_MAX_SIMD_BITWIDTH_512)
769         goto error;
770     }
771   return 1;
772 error:
773   return 0;
774 }
775
776 static clib_error_t *
777 dpdk_device_config (dpdk_config_main_t *conf, void *addr,
778                     dpdk_device_addr_type_t addr_type, unformat_input_t *input,
779                     u8 is_default)
780 {
781   clib_error_t *error = 0;
782   uword *p;
783   dpdk_device_config_t *devconf = 0;
784   unformat_input_t sub_input;
785
786   if (is_default)
787     {
788       devconf = &conf->default_devconf;
789     }
790   else if (addr_type == VNET_DEV_ADDR_PCI)
791     {
792       p = hash_get (conf->device_config_index_by_pci_addr,
793                     ((vlib_pci_addr_t *) (addr))->as_u32);
794
795       if (!p)
796         {
797           pool_get (conf->dev_confs, devconf);
798           hash_set (conf->device_config_index_by_pci_addr,
799                     ((vlib_pci_addr_t *) (addr))->as_u32,
800                     devconf - conf->dev_confs);
801         }
802       else
803         return clib_error_return (0,
804                                   "duplicate configuration for PCI address %U",
805                                   format_vlib_pci_addr, addr);
806     }
807   else if (addr_type == VNET_DEV_ADDR_VMBUS)
808     {
809       p = mhash_get (&conf->device_config_index_by_vmbus_addr,
810                      (vlib_vmbus_addr_t *) (addr));
811
812       if (!p)
813         {
814           pool_get (conf->dev_confs, devconf);
815           mhash_set (&conf->device_config_index_by_vmbus_addr, addr,
816                      devconf - conf->dev_confs, 0);
817         }
818       else
819         return clib_error_return (
820           0, "duplicate configuration for VMBUS address %U",
821           format_vlib_vmbus_addr, addr);
822     }
823
824   if (addr_type == VNET_DEV_ADDR_PCI)
825     {
826       devconf->pci_addr.as_u32 = ((vlib_pci_addr_t *) (addr))->as_u32;
827       devconf->tso = DPDK_DEVICE_TSO_DEFAULT;
828       devconf->dev_addr_type = VNET_DEV_ADDR_PCI;
829     }
830   else if (addr_type == VNET_DEV_ADDR_VMBUS)
831     {
832       devconf->vmbus_addr = *((vlib_vmbus_addr_t *) (addr));
833       devconf->tso = DPDK_DEVICE_TSO_DEFAULT;
834       devconf->dev_addr_type = VNET_DEV_ADDR_VMBUS;
835     }
836
837   if (!input)
838     return 0;
839
840   unformat_skip_white_space (input);
841   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
842     {
843       if (unformat (input, "num-rx-queues %u", &devconf->num_rx_queues))
844         ;
845       else if (unformat (input, "num-tx-queues %u", &devconf->num_tx_queues))
846         ;
847       else if (unformat (input, "num-rx-desc %u", &devconf->num_rx_desc))
848         ;
849       else if (unformat (input, "num-tx-desc %u", &devconf->num_tx_desc))
850         ;
851       else if (unformat (input, "name %v", &devconf->name))
852         ;
853       else if (unformat (input, "workers %U", unformat_bitmap_list,
854                          &devconf->workers))
855         ;
856       else
857         if (unformat
858             (input, "rss %U", unformat_vlib_cli_sub_input, &sub_input))
859         {
860           error = unformat_rss_fn (&sub_input, &devconf->rss_fn);
861           if (error)
862             break;
863         }
864       else if (unformat (input, "tso on"))
865         {
866           devconf->tso = DPDK_DEVICE_TSO_ON;
867         }
868       else if (unformat (input, "tso off"))
869         {
870           devconf->tso = DPDK_DEVICE_TSO_OFF;
871         }
872       else if (unformat (input, "devargs %s", &devconf->devargs))
873         ;
874       else if (unformat (input, "rss-queues %U",
875                          unformat_bitmap_list, &devconf->rss_queues))
876         ;
877       else if (unformat (input, "max-lro-pkt-size %u",
878                          &devconf->max_lro_pkt_size))
879         ;
880       else
881         {
882           error = clib_error_return (0, "unknown input `%U'",
883                                      format_unformat_error, input);
884           break;
885         }
886     }
887
888   if (error)
889     return error;
890
891   if (devconf->workers && devconf->num_rx_queues == 0)
892     devconf->num_rx_queues = clib_bitmap_count_set_bits (devconf->workers);
893   else if (devconf->workers &&
894            clib_bitmap_count_set_bits (devconf->workers) !=
895            devconf->num_rx_queues)
896     error = clib_error_return (0,
897                                "%U: number of worker threads must be "
898                                "equal to number of rx queues",
899                                format_vlib_pci_addr, addr);
900
901   return error;
902 }
903
904 static clib_error_t *
905 dpdk_log_read_ready (clib_file_t * uf)
906 {
907   unformat_input_t input;
908   u8 *line, *s = 0;
909   int n, n_try;
910
911   n = n_try = 4096;
912   while (n == n_try)
913     {
914       uword len = vec_len (s);
915       vec_resize (s, len + n_try);
916
917       n = read (uf->file_descriptor, s + len, n_try);
918       if (n < 0 && errno != EAGAIN)
919         return clib_error_return_unix (0, "read");
920       _vec_len (s) = len + (n < 0 ? 0 : n);
921     }
922
923   unformat_init_vector (&input, s);
924
925   while (unformat_user (&input, unformat_line, &line))
926     {
927       int skip = 0;
928       vec_add1 (line, 0);
929
930       /* unfortunatelly DPDK polutes log with this error messages
931        * even when we pass --in-memory which means no secondary process */
932       if (strstr ((char *) line, "WARNING! Base virtual address hint"))
933         skip = 1;
934       else if (strstr ((char *) line, "This may cause issues with mapping "
935                                       "memory into secondary processes"))
936         skip = 1;
937       vec_pop (line);
938       if (!skip)
939         dpdk_log_notice ("%v", line);
940       vec_free (line);
941     }
942
943   unformat_free (&input);
944   return 0;
945 }
946
947 static clib_error_t *
948 dpdk_config (vlib_main_t * vm, unformat_input_t * input)
949 {
950   dpdk_main_t *dm = &dpdk_main;
951   clib_error_t *error = 0;
952   dpdk_config_main_t *conf = &dpdk_config_main;
953   vlib_thread_main_t *tm = vlib_get_thread_main ();
954   dpdk_device_config_t *devconf;
955   vlib_pci_addr_t pci_addr = { 0 };
956   vlib_vmbus_addr_t vmbus_addr = { 0 };
957   unformat_input_t sub_input;
958   uword default_hugepage_sz, x;
959   u8 *s, *tmp = 0;
960   int ret, i;
961   int num_whitelisted = 0;
962   int eal_no_hugetlb = 0;
963   u8 no_pci = 0;
964   u8 no_vmbus = 0;
965   u8 file_prefix = 0;
966   u8 *socket_mem = 0;
967   u8 *huge_dir_path = 0;
968   u32 vendor, device, domain, bus, func;
969
970   huge_dir_path =
971     format (0, "%s/hugepages%c", vlib_unix_get_runtime_dir (), 0);
972
973   conf->device_config_index_by_pci_addr = hash_create (0, sizeof (uword));
974   mhash_init (&conf->device_config_index_by_vmbus_addr, sizeof (uword),
975               sizeof (vlib_vmbus_addr_t));
976
977   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
978     {
979       /* Prime the pump */
980       if (unformat (input, "no-hugetlb"))
981         {
982           vec_add1 (conf->eal_init_args, (u8 *) "--no-huge");
983           eal_no_hugetlb = 1;
984         }
985       else if (unformat (input, "telemetry"))
986         conf->enable_telemetry = 1;
987
988       else if (unformat (input, "enable-tcp-udp-checksum"))
989         {
990           dm->default_port_conf.enable_tcp_udp_checksum = 1;
991           if (unformat (input, "enable-outer-checksum-offload"))
992             dm->default_port_conf.enable_outer_checksum_offload = 1;
993         }
994       else if (unformat (input, "no-tx-checksum-offload"))
995         dm->default_port_conf.disable_tx_checksum_offload = 1;
996
997       else if (unformat (input, "decimal-interface-names"))
998         conf->interface_name_format_decimal = 1;
999
1000       else if (unformat (input, "no-multi-seg"))
1001         dm->default_port_conf.disable_multi_seg = 1;
1002       else if (unformat (input, "enable-lro"))
1003         dm->default_port_conf.enable_lro = 1;
1004       else if (unformat (input, "max-simd-bitwidth %U",
1005                          unformat_max_simd_bitwidth, &conf->max_simd_bitwidth))
1006         ;
1007       else if (unformat (input, "dev default %U", unformat_vlib_cli_sub_input,
1008                          &sub_input))
1009         {
1010           error =
1011             dpdk_device_config (conf, 0, VNET_DEV_ADDR_ANY, &sub_input, 1);
1012
1013           if (error)
1014             return error;
1015         }
1016       else
1017         if (unformat
1018             (input, "dev %U %U", unformat_vlib_pci_addr, &pci_addr,
1019              unformat_vlib_cli_sub_input, &sub_input))
1020         {
1021           error = dpdk_device_config (conf, &pci_addr, VNET_DEV_ADDR_PCI,
1022                                       &sub_input, 0);
1023
1024           if (error)
1025             return error;
1026
1027           num_whitelisted++;
1028         }
1029       else if (unformat (input, "dev %U", unformat_vlib_pci_addr, &pci_addr))
1030         {
1031           error =
1032             dpdk_device_config (conf, &pci_addr, VNET_DEV_ADDR_PCI, 0, 0);
1033
1034           if (error)
1035             return error;
1036
1037           num_whitelisted++;
1038         }
1039       else if (unformat (input, "dev %U %U", unformat_vlib_vmbus_addr,
1040                          &vmbus_addr, unformat_vlib_cli_sub_input, &sub_input))
1041         {
1042           error = dpdk_device_config (conf, &vmbus_addr, VNET_DEV_ADDR_VMBUS,
1043                                       &sub_input, 0);
1044
1045           if (error)
1046             return error;
1047
1048           num_whitelisted++;
1049         }
1050       else if (unformat (input, "dev %U", unformat_vlib_vmbus_addr,
1051                          &vmbus_addr))
1052         {
1053           error =
1054             dpdk_device_config (conf, &vmbus_addr, VNET_DEV_ADDR_VMBUS, 0, 0);
1055
1056           if (error)
1057             return error;
1058
1059           num_whitelisted++;
1060         }
1061       else if (unformat (input, "uio-driver %s", &conf->uio_driver_name))
1062         ;
1063       else if (unformat (input, "socket-mem %s", &socket_mem))
1064         ;
1065       else if (unformat (input, "no-pci"))
1066         {
1067           no_pci = 1;
1068           tmp = format (0, "--no-pci%c", 0);
1069           vec_add1 (conf->eal_init_args, tmp);
1070         }
1071       else if (unformat (input, "blacklist %U", unformat_vlib_vmbus_addr,
1072                          &vmbus_addr))
1073         {
1074           vec_add1 (conf->blacklist_by_vmbus_addr, vmbus_addr);
1075         }
1076       else
1077         if (unformat
1078             (input, "blacklist %x:%x:%x.%x", &domain, &bus, &device, &func))
1079         {
1080           tmp = format (0, "-b%c", 0);
1081           vec_add1 (conf->eal_init_args, tmp);
1082           tmp =
1083             format (0, "%04x:%02x:%02x.%x%c", domain, bus, device, func, 0);
1084           vec_add1 (conf->eal_init_args, tmp);
1085         }
1086       else if (unformat (input, "blacklist %x:%x", &vendor, &device))
1087         {
1088           u32 blacklist_entry;
1089           if (vendor > 0xFFFF)
1090             return clib_error_return (0, "blacklist PCI vendor out of range");
1091           if (device > 0xFFFF)
1092             return clib_error_return (0, "blacklist PCI device out of range");
1093           blacklist_entry = (vendor << 16) | (device & 0xffff);
1094           vec_add1 (conf->blacklist_by_pci_vendor_and_device,
1095                     blacklist_entry);
1096         }
1097       else if (unformat (input, "no-vmbus"))
1098         {
1099           no_vmbus = 1;
1100           tmp = format (0, "--no-vmbus%c", 0);
1101           vec_add1 (conf->eal_init_args, tmp);
1102         }
1103
1104 #define _(a)                                    \
1105       else if (unformat(input, #a))             \
1106         {                                       \
1107           tmp = format (0, "--%s%c", #a, 0);    \
1108           vec_add1 (conf->eal_init_args, tmp);    \
1109         }
1110       foreach_eal_double_hyphen_predicate_arg
1111 #undef _
1112 #define _(a)                                          \
1113         else if (unformat(input, #a " %s", &s))       \
1114           {                                           \
1115             if (!strncmp(#a, "file-prefix", 11)) \
1116               file_prefix = 1;                        \
1117             tmp = format (0, "--%s%c", #a, 0);        \
1118             vec_add1 (conf->eal_init_args, tmp);      \
1119             vec_add1 (s, 0);                          \
1120             if (!strncmp(#a, "vdev", 4))              \
1121               if (strstr((char*)s, "af_packet"))      \
1122                 clib_warning ("af_packet obsoleted. Use CLI 'create host-interface'."); \
1123             vec_add1 (conf->eal_init_args, s);        \
1124           }
1125         foreach_eal_double_hyphen_arg
1126 #undef _
1127 #define _(a,b)                                          \
1128           else if (unformat(input, #a " %s", &s))       \
1129             {                                           \
1130               tmp = format (0, "-%s%c", #b, 0);         \
1131               vec_add1 (conf->eal_init_args, tmp);      \
1132               vec_add1 (s, 0);                          \
1133               vec_add1 (conf->eal_init_args, s);        \
1134             }
1135         foreach_eal_single_hyphen_arg
1136 #undef _
1137         else if (unformat (input, "default"))
1138         ;
1139
1140       else if (unformat_skip_white_space (input))
1141         ;
1142       else
1143         {
1144           error = clib_error_return (0, "unknown input `%U'",
1145                                      format_unformat_error, input);
1146           goto done;
1147         }
1148     }
1149
1150   if (!conf->uio_driver_name)
1151     conf->uio_driver_name = format (0, "auto%c", 0);
1152
1153   if (eal_no_hugetlb == 0)
1154     {
1155       vec_add1 (conf->eal_init_args, (u8 *) "--in-memory");
1156
1157       default_hugepage_sz = clib_mem_get_default_hugepage_size ();
1158
1159       /* *INDENT-OFF* */
1160       clib_bitmap_foreach (x, tm->cpu_socket_bitmap)
1161         {
1162           clib_error_t *e;
1163           uword n_pages;
1164           /* preallocate at least 16MB of hugepages per socket,
1165             if more is needed it is up to consumer to preallocate more */
1166           n_pages = round_pow2 ((uword) 16 << 20, default_hugepage_sz);
1167           n_pages /= default_hugepage_sz;
1168
1169           if ((e = clib_sysfs_prealloc_hugepages(x, 0, n_pages)))
1170             clib_error_report (e);
1171         }
1172       /* *INDENT-ON* */
1173     }
1174
1175   /* on/off dpdk's telemetry thread */
1176   if (conf->enable_telemetry == 0)
1177     {
1178       vec_add1 (conf->eal_init_args, (u8 *) "--no-telemetry");
1179     }
1180
1181   if (!file_prefix)
1182     {
1183       tmp = format (0, "--file-prefix%c", 0);
1184       vec_add1 (conf->eal_init_args, tmp);
1185       tmp = format (0, "vpp%c", 0);
1186       vec_add1 (conf->eal_init_args, tmp);
1187     }
1188
1189   if (error)
1190     return error;
1191
1192   if (no_pci == 0 && geteuid () == 0)
1193     dpdk_bind_devices_to_uio (conf);
1194
1195   if (no_vmbus == 0 && geteuid () == 0)
1196     dpdk_bind_vmbus_devices_to_uio (conf);
1197
1198 #define _(x) \
1199     if (devconf->x == 0 && conf->default_devconf.x > 0) \
1200       devconf->x = conf->default_devconf.x ;
1201
1202   pool_foreach (devconf, conf->dev_confs)  {
1203
1204     /* default per-device config items */
1205     foreach_dpdk_device_config_item
1206
1207       /* copy tso config from default device */
1208       _ (tso)
1209
1210       /* copy tso config from default device */
1211       _ (devargs)
1212
1213       /* copy rss_queues config from default device */
1214       _ (rss_queues)
1215
1216       /* add DPDK EAL whitelist/blacklist entry */
1217       if (num_whitelisted > 0 && devconf->is_blacklisted == 0 &&
1218           devconf->dev_addr_type == VNET_DEV_ADDR_PCI)
1219     {
1220           tmp = format (0, "-a%c", 0);
1221           vec_add1 (conf->eal_init_args, tmp);
1222           if (devconf->devargs)
1223           {
1224             tmp = format (0, "%U,%s%c", format_vlib_pci_addr,
1225                           &devconf->pci_addr, devconf->devargs, 0);
1226           }
1227           else
1228           {
1229             tmp = format (0, "%U%c", format_vlib_pci_addr, &devconf->pci_addr, 0);
1230           }
1231           vec_add1 (conf->eal_init_args, tmp);
1232     }
1233     else if (num_whitelisted == 0 && devconf->is_blacklisted != 0 &&
1234              devconf->dev_addr_type == VNET_DEV_ADDR_PCI)
1235     {
1236           tmp = format (0, "-b%c", 0);
1237           vec_add1 (conf->eal_init_args, tmp);
1238           tmp = format (0, "%U%c", format_vlib_pci_addr, &devconf->pci_addr, 0);
1239           vec_add1 (conf->eal_init_args, tmp);
1240     }
1241   }
1242
1243 #undef _
1244
1245   if (socket_mem)
1246     clib_warning ("socket-mem argument is deprecated");
1247
1248   /* NULL terminate the "argv" vector, in case of stupidity */
1249   vec_add1 (conf->eal_init_args, 0);
1250   _vec_len (conf->eal_init_args) -= 1;
1251
1252   /* Set up DPDK eal and packet mbuf pool early. */
1253
1254   int log_fds[2] = { 0 };
1255   if (pipe (log_fds) == 0)
1256     {
1257       if (fcntl (log_fds[1], F_SETFL, O_NONBLOCK) == 0)
1258         {
1259           FILE *f = fdopen (log_fds[1], "a");
1260           if (f && rte_openlog_stream (f) == 0)
1261             {
1262               clib_file_t t = { 0 };
1263               t.read_function = dpdk_log_read_ready;
1264               t.file_descriptor = log_fds[0];
1265               t.description = format (0, "DPDK logging pipe");
1266               clib_file_add (&file_main, &t);
1267             }
1268         }
1269       else
1270         {
1271           close (log_fds[0]);
1272           close (log_fds[1]);
1273         }
1274     }
1275
1276   vm = vlib_get_main ();
1277
1278   /* make copy of args as rte_eal_init tends to mess up with arg array */
1279   for (i = 1; i < vec_len (conf->eal_init_args); i++)
1280     conf->eal_init_args_str = format (conf->eal_init_args_str, "%s ",
1281                                       conf->eal_init_args[i]);
1282
1283   vec_terminate_c_string (conf->eal_init_args_str);
1284
1285   dpdk_log_notice ("EAL init args: %s", conf->eal_init_args_str);
1286   ret = rte_eal_init (vec_len (conf->eal_init_args),
1287                       (char **) conf->eal_init_args);
1288
1289   /* enable the AVX-512 vPMDs in DPDK */
1290   if (clib_cpu_supports_avx512_bitalg () &&
1291       conf->max_simd_bitwidth == DPDK_MAX_SIMD_BITWIDTH_DEFAULT)
1292     rte_vect_set_max_simd_bitwidth (RTE_VECT_SIMD_512);
1293   else if (conf->max_simd_bitwidth != DPDK_MAX_SIMD_BITWIDTH_DEFAULT)
1294     rte_vect_set_max_simd_bitwidth (conf->max_simd_bitwidth ==
1295                                         DPDK_MAX_SIMD_BITWIDTH_256 ?
1296                                       RTE_VECT_SIMD_256 :
1297                                       RTE_VECT_SIMD_512);
1298
1299   /* lazy umount hugepages */
1300   umount2 ((char *) huge_dir_path, MNT_DETACH);
1301   rmdir ((char *) huge_dir_path);
1302   vec_free (huge_dir_path);
1303
1304   if (ret < 0)
1305     return clib_error_return (0, "rte_eal_init returned %d", ret);
1306
1307   /* main thread 1st */
1308   if ((error = dpdk_buffer_pools_create (vm)))
1309     return error;
1310
1311 done:
1312   return error;
1313 }
1314
1315 VLIB_CONFIG_FUNCTION (dpdk_config, "dpdk");
1316
1317 void
1318 dpdk_update_link_state (dpdk_device_t * xd, f64 now)
1319 {
1320   vnet_main_t *vnm = vnet_get_main ();
1321   struct rte_eth_link prev_link = xd->link;
1322   u32 hw_flags = 0;
1323   u8 hw_flags_chg = 0;
1324
1325   xd->time_last_link_update = now ? now : xd->time_last_link_update;
1326   clib_memset (&xd->link, 0, sizeof (xd->link));
1327   rte_eth_link_get_nowait (xd->port_id, &xd->link);
1328
1329   if (LINK_STATE_ELOGS)
1330     {
1331       ELOG_TYPE_DECLARE (e) =
1332       {
1333       .format =
1334           "update-link-state: sw_if_index %d, admin_up %d,"
1335           "old link_state %d new link_state %d",.format_args = "i4i1i1i1",};
1336
1337       struct
1338       {
1339         u32 sw_if_index;
1340         u8 admin_up;
1341         u8 old_link_state;
1342         u8 new_link_state;
1343       } *ed;
1344       ed = ELOG_DATA (&vlib_global_main.elog_main, e);
1345       ed->sw_if_index = xd->sw_if_index;
1346       ed->admin_up = (xd->flags & DPDK_DEVICE_FLAG_ADMIN_UP) != 0;
1347       ed->old_link_state = (u8)
1348         vnet_hw_interface_is_link_up (vnm, xd->hw_if_index);
1349       ed->new_link_state = (u8) xd->link.link_status;
1350     }
1351
1352   if ((xd->link.link_duplex != prev_link.link_duplex))
1353     {
1354       hw_flags_chg = 1;
1355       switch (xd->link.link_duplex)
1356         {
1357         case ETH_LINK_HALF_DUPLEX:
1358           hw_flags |= VNET_HW_INTERFACE_FLAG_HALF_DUPLEX;
1359           break;
1360         case ETH_LINK_FULL_DUPLEX:
1361           hw_flags |= VNET_HW_INTERFACE_FLAG_FULL_DUPLEX;
1362           break;
1363         default:
1364           break;
1365         }
1366     }
1367   if (xd->link.link_speed != prev_link.link_speed)
1368     vnet_hw_interface_set_link_speed (vnm, xd->hw_if_index,
1369                                       xd->link.link_speed * 1000);
1370
1371   if (xd->link.link_status != prev_link.link_status)
1372     {
1373       hw_flags_chg = 1;
1374
1375       if (xd->link.link_status)
1376         hw_flags |= VNET_HW_INTERFACE_FLAG_LINK_UP;
1377     }
1378
1379   if (hw_flags_chg)
1380     {
1381       if (LINK_STATE_ELOGS)
1382         {
1383           ELOG_TYPE_DECLARE (e) =
1384           {
1385           .format =
1386               "update-link-state: sw_if_index %d, new flags %d",.format_args
1387               = "i4i4",};
1388
1389           struct
1390           {
1391             u32 sw_if_index;
1392             u32 flags;
1393           } *ed;
1394           ed = ELOG_DATA (&vlib_global_main.elog_main, e);
1395           ed->sw_if_index = xd->sw_if_index;
1396           ed->flags = hw_flags;
1397         }
1398       vnet_hw_interface_set_flags (vnm, xd->hw_if_index, hw_flags);
1399     }
1400 }
1401
1402 static uword
1403 dpdk_process (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f)
1404 {
1405   clib_error_t *error;
1406   dpdk_main_t *dm = &dpdk_main;
1407   dpdk_device_t *xd;
1408   vlib_thread_main_t *tm = vlib_get_thread_main ();
1409
1410   error = dpdk_lib_init (dm);
1411
1412   if (error)
1413     clib_error_report (error);
1414
1415   if (dpdk_cryptodev_init)
1416     {
1417       error = dpdk_cryptodev_init (vm);
1418       if (error)
1419         {
1420           vlib_log_warn (dpdk_main.log_cryptodev, "%U", format_clib_error,
1421                          error);
1422           clib_error_free (error);
1423         }
1424     }
1425
1426   tm->worker_thread_release = 1;
1427
1428   f64 now = vlib_time_now (vm);
1429   vec_foreach (xd, dm->devices)
1430   {
1431     dpdk_update_link_state (xd, now);
1432   }
1433
1434   while (1)
1435     {
1436       /*
1437        * check each time through the loop in case intervals are changed
1438        */
1439       f64 min_wait = dm->link_state_poll_interval < dm->stat_poll_interval ?
1440         dm->link_state_poll_interval : dm->stat_poll_interval;
1441
1442       vlib_process_wait_for_event_or_clock (vm, min_wait);
1443
1444       if (dm->admin_up_down_in_progress)
1445         /* skip the poll if an admin up down is in progress (on any interface) */
1446         continue;
1447
1448       vec_foreach (xd, dm->devices)
1449       {
1450         f64 now = vlib_time_now (vm);
1451         if ((now - xd->time_last_stats_update) >= dm->stat_poll_interval)
1452           dpdk_update_counters (xd, now);
1453         if ((now - xd->time_last_link_update) >= dm->link_state_poll_interval)
1454           dpdk_update_link_state (xd, now);
1455
1456       }
1457     }
1458
1459   return 0;
1460 }
1461
1462 /* *INDENT-OFF* */
1463 VLIB_REGISTER_NODE (dpdk_process_node,static) = {
1464     .function = dpdk_process,
1465     .type = VLIB_NODE_TYPE_PROCESS,
1466     .name = "dpdk-process",
1467     .process_log2_n_stack_bytes = 17,
1468 };
1469 /* *INDENT-ON* */
1470
1471 static clib_error_t *
1472 dpdk_init (vlib_main_t * vm)
1473 {
1474   dpdk_main_t *dm = &dpdk_main;
1475   clib_error_t *error = 0;
1476
1477   /* verify that structs are cacheline aligned */
1478   STATIC_ASSERT (offsetof (dpdk_device_t, cacheline0) == 0,
1479                  "Cache line marker must be 1st element in dpdk_device_t");
1480   STATIC_ASSERT (offsetof (dpdk_device_t, cacheline1) ==
1481                  CLIB_CACHE_LINE_BYTES,
1482                  "Data in cache line 0 is bigger than cache line size");
1483   STATIC_ASSERT (offsetof (frame_queue_trace_t, cacheline0) == 0,
1484                  "Cache line marker must be 1st element in frame_queue_trace_t");
1485
1486   dpdk_cli_reference ();
1487
1488   dm->conf = &dpdk_config_main;
1489
1490   vec_add1 (dm->conf->eal_init_args, (u8 *) "vnet");
1491
1492   dm->stat_poll_interval = DPDK_STATS_POLL_INTERVAL;
1493   dm->link_state_poll_interval = DPDK_LINK_POLL_INTERVAL;
1494
1495   dm->log_default = vlib_log_register_class ("dpdk", 0);
1496   dm->log_cryptodev = vlib_log_register_class ("dpdk", "cryptodev");
1497
1498   return error;
1499 }
1500
1501 VLIB_INIT_FUNCTION (dpdk_init);
1502
1503 static clib_error_t *
1504 dpdk_worker_thread_init (vlib_main_t *vm)
1505 {
1506   if (rte_thread_register () < 0)
1507     clib_panic ("dpdk: cannot register thread %u - %s", vm->thread_index,
1508                 rte_strerror (rte_errno));
1509   return 0;
1510 }
1511
1512 VLIB_WORKER_INIT_FUNCTION (dpdk_worker_thread_init);