vnet: store hw interface speed in kbps instead of using flags
[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/ethernet/ethernet.h>
25 #include <dpdk/device/dpdk.h>
26 #include <vlib/pci/pci.h>
27
28 #include <rte_ring.h>
29
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <unistd.h>
33 #include <sys/stat.h>
34 #include <sys/mount.h>
35 #include <string.h>
36 #include <fcntl.h>
37
38 #include <dpdk/device/dpdk_priv.h>
39
40 #define ETHER_MAX_LEN   1518  /**< Maximum frame len, including CRC. */
41
42 dpdk_main_t dpdk_main;
43 dpdk_config_main_t dpdk_config_main;
44
45 #define LINK_STATE_ELOGS        0
46
47 /* Port configuration, mildly modified Intel app values */
48
49 static dpdk_port_type_t
50 port_type_from_speed_capa (struct rte_eth_dev_info *dev_info)
51 {
52
53   if (dev_info->speed_capa & ETH_LINK_SPEED_100G)
54     return VNET_DPDK_PORT_TYPE_ETH_100G;
55   else if (dev_info->speed_capa & ETH_LINK_SPEED_56G)
56     return VNET_DPDK_PORT_TYPE_ETH_56G;
57   else if (dev_info->speed_capa & ETH_LINK_SPEED_50G)
58     return VNET_DPDK_PORT_TYPE_ETH_50G;
59   else if (dev_info->speed_capa & ETH_LINK_SPEED_40G)
60     return VNET_DPDK_PORT_TYPE_ETH_40G;
61   else if (dev_info->speed_capa & ETH_LINK_SPEED_25G)
62     return VNET_DPDK_PORT_TYPE_ETH_25G;
63   else if (dev_info->speed_capa & ETH_LINK_SPEED_20G)
64     return VNET_DPDK_PORT_TYPE_ETH_20G;
65   else if (dev_info->speed_capa & ETH_LINK_SPEED_10G)
66     return VNET_DPDK_PORT_TYPE_ETH_10G;
67   else if (dev_info->speed_capa & ETH_LINK_SPEED_5G)
68     return VNET_DPDK_PORT_TYPE_ETH_5G;
69   else if (dev_info->speed_capa & ETH_LINK_SPEED_2_5G)
70     return VNET_DPDK_PORT_TYPE_ETH_2_5G;
71   else if (dev_info->speed_capa & ETH_LINK_SPEED_1G)
72     return VNET_DPDK_PORT_TYPE_ETH_1G;
73
74   return VNET_DPDK_PORT_TYPE_UNKNOWN;
75 }
76
77 static dpdk_port_type_t
78 port_type_from_link_speed (u32 link_speed)
79 {
80   switch (link_speed)
81     {
82     case ETH_SPEED_NUM_1G:
83       return VNET_DPDK_PORT_TYPE_ETH_1G;
84     case ETH_SPEED_NUM_2_5G:
85       return VNET_DPDK_PORT_TYPE_ETH_2_5G;
86     case ETH_SPEED_NUM_5G:
87       return VNET_DPDK_PORT_TYPE_ETH_5G;
88     case ETH_SPEED_NUM_10G:
89       return VNET_DPDK_PORT_TYPE_ETH_10G;
90     case ETH_SPEED_NUM_20G:
91       return VNET_DPDK_PORT_TYPE_ETH_20G;
92     case ETH_SPEED_NUM_25G:
93       return VNET_DPDK_PORT_TYPE_ETH_25G;
94     case ETH_SPEED_NUM_40G:
95       return VNET_DPDK_PORT_TYPE_ETH_40G;
96     case ETH_SPEED_NUM_50G:
97       return VNET_DPDK_PORT_TYPE_ETH_50G;
98     case ETH_SPEED_NUM_56G:
99       return VNET_DPDK_PORT_TYPE_ETH_56G;
100     case ETH_SPEED_NUM_100G:
101       return VNET_DPDK_PORT_TYPE_ETH_100G;
102     default:
103       return VNET_DPDK_PORT_TYPE_UNKNOWN;
104     }
105 }
106
107 static u32
108 dpdk_flag_change (vnet_main_t * vnm, vnet_hw_interface_t * hi, u32 flags)
109 {
110   dpdk_main_t *dm = &dpdk_main;
111   dpdk_device_t *xd = vec_elt_at_index (dm->devices, hi->dev_instance);
112   u32 old = 0;
113
114   if (ETHERNET_INTERFACE_FLAG_CONFIG_PROMISC (flags))
115     {
116       old = (xd->flags & DPDK_DEVICE_FLAG_PROMISC) != 0;
117
118       if (flags & ETHERNET_INTERFACE_FLAG_ACCEPT_ALL)
119         xd->flags |= DPDK_DEVICE_FLAG_PROMISC;
120       else
121         xd->flags &= ~DPDK_DEVICE_FLAG_PROMISC;
122
123       if (xd->flags & DPDK_DEVICE_FLAG_ADMIN_UP)
124         {
125           if (xd->flags & DPDK_DEVICE_FLAG_PROMISC)
126             rte_eth_promiscuous_enable (xd->port_id);
127           else
128             rte_eth_promiscuous_disable (xd->port_id);
129         }
130     }
131   else if (ETHERNET_INTERFACE_FLAG_CONFIG_MTU (flags))
132     {
133       xd->port_conf.rxmode.max_rx_pkt_len = hi->max_packet_bytes;
134       dpdk_device_setup (xd);
135     }
136   return old;
137 }
138
139 static void
140 dpdk_device_lock_init (dpdk_device_t * xd)
141 {
142   int q;
143   vec_validate (xd->lockp, xd->tx_q_used - 1);
144   for (q = 0; q < xd->tx_q_used; q++)
145     {
146       xd->lockp[q] = clib_mem_alloc_aligned (CLIB_CACHE_LINE_BYTES,
147                                              CLIB_CACHE_LINE_BYTES);
148       clib_memset ((void *) xd->lockp[q], 0, CLIB_CACHE_LINE_BYTES);
149     }
150 }
151
152 static struct rte_mempool_ops *
153 get_ops_by_name (char *ops_name)
154 {
155   u32 i;
156
157   for (i = 0; i < rte_mempool_ops_table.num_ops; i++)
158     {
159       if (!strcmp (ops_name, rte_mempool_ops_table.ops[i].name))
160         return &rte_mempool_ops_table.ops[i];
161     }
162
163   return 0;
164 }
165
166 static int
167 dpdk_ring_alloc (struct rte_mempool *mp)
168 {
169   u32 rg_flags = 0, count;
170   i32 ret;
171   char rg_name[RTE_RING_NAMESIZE];
172   struct rte_ring *r;
173
174   ret = snprintf (rg_name, sizeof (rg_name), RTE_MEMPOOL_MZ_FORMAT, mp->name);
175   if (ret < 0 || ret >= (i32) sizeof (rg_name))
176     return -ENAMETOOLONG;
177
178   /* ring flags */
179   if (mp->flags & MEMPOOL_F_SP_PUT)
180     rg_flags |= RING_F_SP_ENQ;
181   if (mp->flags & MEMPOOL_F_SC_GET)
182     rg_flags |= RING_F_SC_DEQ;
183
184   count = rte_align32pow2 (mp->size + 1);
185   /*
186    * Allocate the ring that will be used to store objects.
187    * Ring functions will return appropriate errors if we are
188    * running as a secondary process etc., so no checks made
189    * in this function for that condition.
190    */
191   /* XXX can we get memory from the right socket? */
192   r = clib_mem_alloc_aligned (rte_ring_get_memsize (count),
193                               CLIB_CACHE_LINE_BYTES);
194
195   /* XXX rte_ring_lookup will not work */
196
197   ret = rte_ring_init (r, rg_name, count, rg_flags);
198   if (ret)
199     return ret;
200
201   mp->pool_data = r;
202
203   return 0;
204 }
205
206 static int
207 dpdk_port_crc_strip_enabled (dpdk_device_t * xd)
208 {
209 #if RTE_VERSION < RTE_VERSION_NUM(18, 8, 0, 0)
210   return ! !(xd->port_conf.rxmode.hw_strip_crc);
211 #elif RTE_VERSION < RTE_VERSION_NUM(18, 11, 0, 0)
212   return ! !(xd->port_conf.rxmode.offloads & DEV_RX_OFFLOAD_CRC_STRIP);
213 #else
214   return !(xd->port_conf.rxmode.offloads & DEV_RX_OFFLOAD_KEEP_CRC);
215 #endif
216 }
217
218 static clib_error_t *
219 dpdk_lib_init (dpdk_main_t * dm)
220 {
221   u32 nports;
222   u32 mtu, max_rx_frame;
223   u32 nb_desc = 0;
224   int i;
225   clib_error_t *error;
226   vlib_main_t *vm = vlib_get_main ();
227   vlib_thread_main_t *tm = vlib_get_thread_main ();
228   vnet_device_main_t *vdm = &vnet_device_main;
229   vnet_sw_interface_t *sw;
230   vnet_hw_interface_t *hi;
231   dpdk_device_t *xd;
232   vlib_pci_addr_t last_pci_addr;
233   u32 last_pci_addr_port = 0;
234   vlib_thread_registration_t *tr_hqos;
235   uword *p_hqos;
236
237   u32 next_hqos_cpu = 0;
238   u8 af_packet_instance_num = 0;
239   u8 bond_ether_instance_num = 0;
240   last_pci_addr.as_u32 = ~0;
241
242   dm->hqos_cpu_first_index = 0;
243   dm->hqos_cpu_count = 0;
244
245   /* find out which cpus will be used for I/O TX */
246   p_hqos = hash_get_mem (tm->thread_registrations_by_name, "hqos-threads");
247   tr_hqos = p_hqos ? (vlib_thread_registration_t *) p_hqos[0] : 0;
248
249   if (tr_hqos && tr_hqos->count > 0)
250     {
251       dm->hqos_cpu_first_index = tr_hqos->first_index;
252       dm->hqos_cpu_count = tr_hqos->count;
253     }
254
255   vec_validate_aligned (dm->devices_by_hqos_cpu, tm->n_vlib_mains - 1,
256                         CLIB_CACHE_LINE_BYTES);
257
258   nports = rte_eth_dev_count_avail ();
259
260   if (nports < 1)
261     {
262       dpdk_log_notice ("DPDK drivers found no ports...");
263     }
264
265   if (CLIB_DEBUG > 0)
266     dpdk_log_notice ("DPDK drivers found %d ports...", nports);
267
268   if (dm->conf->enable_tcp_udp_checksum)
269     dm->buffer_flags_template &= ~(VNET_BUFFER_F_L4_CHECKSUM_CORRECT
270                                    | VNET_BUFFER_F_L4_CHECKSUM_COMPUTED);
271
272   /* vlib_buffer_t template */
273   vec_validate_aligned (dm->per_thread_data, tm->n_vlib_mains - 1,
274                         CLIB_CACHE_LINE_BYTES);
275   for (i = 0; i < tm->n_vlib_mains; i++)
276     {
277       vlib_buffer_free_list_t *fl;
278       dpdk_per_thread_data_t *ptd = vec_elt_at_index (dm->per_thread_data, i);
279       fl = vlib_buffer_get_free_list (vm,
280                                       VLIB_BUFFER_DEFAULT_FREE_LIST_INDEX);
281       vlib_buffer_init_for_free_list (&ptd->buffer_template, fl);
282       ptd->buffer_template.flags = dm->buffer_flags_template;
283       vnet_buffer (&ptd->buffer_template)->sw_if_index[VLIB_TX] = (u32) ~ 0;
284     }
285
286   /* *INDENT-OFF* */
287   RTE_ETH_FOREACH_DEV(i)
288     {
289       u8 addr[6];
290       u8 vlan_strip = 0;
291       struct rte_eth_dev_info dev_info;
292       struct rte_pci_device *pci_dev;
293       struct rte_eth_link l;
294       dpdk_device_config_t *devconf = 0;
295       vlib_pci_addr_t pci_addr;
296       uword *p = 0;
297
298       if (!rte_eth_dev_is_valid_port(i))
299         continue;
300
301       rte_eth_link_get_nowait (i, &l);
302       rte_eth_dev_info_get (i, &dev_info);
303
304       if (dev_info.device == 0)
305         {
306           clib_warning ("DPDK bug: missing device info. Skipping %s device",
307                         dev_info.driver_name);
308           continue;
309         }
310
311       pci_dev = dpdk_get_pci_device (&dev_info);
312
313       if (pci_dev)      /* bonded interface has no pci info */
314         {
315           pci_addr.domain = pci_dev->addr.domain;
316           pci_addr.bus = pci_dev->addr.bus;
317           pci_addr.slot = pci_dev->addr.devid;
318           pci_addr.function = pci_dev->addr.function;
319           p = hash_get (dm->conf->device_config_index_by_pci_addr,
320                         pci_addr.as_u32);
321         }
322
323       if (p)
324         devconf = pool_elt_at_index (dm->conf->dev_confs, p[0]);
325       else
326         devconf = &dm->conf->default_devconf;
327
328       /* Create vnet interface */
329       vec_add2_aligned (dm->devices, xd, 1, CLIB_CACHE_LINE_BYTES);
330       xd->nb_rx_desc = DPDK_NB_RX_DESC_DEFAULT;
331       xd->nb_tx_desc = DPDK_NB_TX_DESC_DEFAULT;
332       xd->cpu_socket = (i8) rte_eth_dev_socket_id (i);
333
334       /* Handle interface naming for devices with multiple ports sharing same PCI ID */
335       if (pci_dev)
336         {
337           struct rte_eth_dev_info di = { 0 };
338           struct rte_pci_device *next_pci_dev;
339           rte_eth_dev_info_get (i + 1, &di);
340           next_pci_dev = di.device ? RTE_DEV_TO_PCI (di.device) : 0;
341           if (pci_dev && next_pci_dev &&
342               pci_addr.as_u32 != last_pci_addr.as_u32 &&
343               memcmp (&pci_dev->addr, &next_pci_dev->addr,
344                       sizeof (struct rte_pci_addr)) == 0)
345             {
346               xd->interface_name_suffix = format (0, "0");
347               last_pci_addr.as_u32 = pci_addr.as_u32;
348               last_pci_addr_port = i;
349             }
350           else if (pci_addr.as_u32 == last_pci_addr.as_u32)
351             {
352               xd->interface_name_suffix =
353                 format (0, "%u", i - last_pci_addr_port);
354             }
355           else
356             {
357               last_pci_addr.as_u32 = ~0;
358             }
359         }
360       else
361         last_pci_addr.as_u32 = ~0;
362
363       clib_memcpy (&xd->tx_conf, &dev_info.default_txconf,
364                    sizeof (struct rte_eth_txconf));
365
366       if (dm->conf->no_multi_seg)
367         {
368 #if RTE_VERSION < RTE_VERSION_NUM(18, 8, 0, 0)
369           xd->tx_conf.txq_flags |= ETH_TXQ_FLAGS_NOMULTSEGS;
370           xd->port_conf.rxmode.jumbo_frame = 0;
371           xd->port_conf.rxmode.enable_scatter = 0;
372 #else
373           xd->port_conf.txmode.offloads &= ~DEV_TX_OFFLOAD_MULTI_SEGS;
374           xd->port_conf.rxmode.offloads &= ~DEV_RX_OFFLOAD_JUMBO_FRAME;
375           xd->port_conf.rxmode.offloads &= ~DEV_RX_OFFLOAD_SCATTER;
376 #endif
377         }
378       else
379         {
380 #if RTE_VERSION < RTE_VERSION_NUM(18, 8, 0, 0)
381           xd->tx_conf.txq_flags &= ~ETH_TXQ_FLAGS_NOMULTSEGS;
382           xd->port_conf.rxmode.jumbo_frame = 1;
383           xd->port_conf.rxmode.enable_scatter = 1;
384 #else
385           xd->port_conf.txmode.offloads |= DEV_TX_OFFLOAD_MULTI_SEGS;
386           xd->port_conf.rxmode.offloads |= DEV_RX_OFFLOAD_JUMBO_FRAME;
387           xd->port_conf.rxmode.offloads |= DEV_RX_OFFLOAD_SCATTER;
388 #endif
389           xd->flags |= DPDK_DEVICE_FLAG_MAYBE_MULTISEG;
390         }
391
392       xd->tx_q_used = clib_min (dev_info.max_tx_queues, tm->n_vlib_mains);
393
394       if (devconf->num_tx_queues > 0
395           && devconf->num_tx_queues < xd->tx_q_used)
396         xd->tx_q_used = clib_min (xd->tx_q_used, devconf->num_tx_queues);
397
398       if (devconf->num_rx_queues > 1
399           && dev_info.max_rx_queues >= devconf->num_rx_queues)
400         {
401           xd->rx_q_used = devconf->num_rx_queues;
402           xd->port_conf.rxmode.mq_mode = ETH_MQ_RX_RSS;
403           if (devconf->rss_fn == 0)
404             xd->port_conf.rx_adv_conf.rss_conf.rss_hf =
405               ETH_RSS_IP | ETH_RSS_UDP | ETH_RSS_TCP;
406           else
407             {
408               u64 unsupported_bits;
409               xd->port_conf.rx_adv_conf.rss_conf.rss_hf = devconf->rss_fn;
410               unsupported_bits = xd->port_conf.rx_adv_conf.rss_conf.rss_hf;
411               unsupported_bits &= ~dev_info.flow_type_rss_offloads;
412               if (unsupported_bits)
413                 dpdk_log_warn ("Unsupported RSS hash functions: %U",
414                                format_dpdk_rss_hf_name, unsupported_bits);
415             }
416           xd->port_conf.rx_adv_conf.rss_conf.rss_hf &=
417             dev_info.flow_type_rss_offloads;
418         }
419       else
420         xd->rx_q_used = 1;
421
422       xd->flags |= DPDK_DEVICE_FLAG_PMD;
423
424       /* workaround for drivers not setting driver_name */
425       if ((!dev_info.driver_name) && (pci_dev))
426         dev_info.driver_name = pci_dev->driver->driver.name;
427
428       ASSERT (dev_info.driver_name);
429
430       if (!xd->pmd)
431         {
432
433
434 #define _(s,f) else if (dev_info.driver_name &&                 \
435                         !strcmp(dev_info.driver_name, s))       \
436                  xd->pmd = VNET_DPDK_PMD_##f;
437           if (0)
438             ;
439           foreach_dpdk_pmd
440 #undef _
441             else
442             xd->pmd = VNET_DPDK_PMD_UNKNOWN;
443
444           xd->port_type = VNET_DPDK_PORT_TYPE_UNKNOWN;
445           xd->nb_rx_desc = DPDK_NB_RX_DESC_DEFAULT;
446           xd->nb_tx_desc = DPDK_NB_TX_DESC_DEFAULT;
447
448           switch (xd->pmd)
449             {
450               /* Drivers with valid speed_capa set */
451             case VNET_DPDK_PMD_E1000EM:
452             case VNET_DPDK_PMD_IGB:
453             case VNET_DPDK_PMD_IXGBE:
454             case VNET_DPDK_PMD_I40E:
455               xd->port_type = port_type_from_speed_capa (&dev_info);
456               xd->supported_flow_actions = VNET_FLOW_ACTION_MARK |
457                 VNET_FLOW_ACTION_REDIRECT_TO_NODE |
458                 VNET_FLOW_ACTION_BUFFER_ADVANCE |
459                 VNET_FLOW_ACTION_COUNT | VNET_FLOW_ACTION_DROP;
460
461               if (dm->conf->no_tx_checksum_offload == 0)
462                 {
463 #if RTE_VERSION < RTE_VERSION_NUM(18, 8, 0, 0)
464                   xd->tx_conf.txq_flags &= ~(ETH_TXQ_FLAGS_NOXSUMUDP |
465                                                      ETH_TXQ_FLAGS_NOXSUMTCP);
466 #else
467                   xd->port_conf.txmode.offloads |= DEV_TX_OFFLOAD_TCP_CKSUM;
468                   xd->port_conf.txmode.offloads |= DEV_TX_OFFLOAD_UDP_CKSUM;
469 #endif
470                   xd->flags |=
471                     DPDK_DEVICE_FLAG_TX_OFFLOAD |
472                     DPDK_DEVICE_FLAG_INTEL_PHDR_CKSUM;
473                 }
474
475
476               break;
477             case VNET_DPDK_PMD_CXGBE:
478             case VNET_DPDK_PMD_MLX4:
479             case VNET_DPDK_PMD_MLX5:
480             case VNET_DPDK_PMD_QEDE:
481               xd->port_type = port_type_from_speed_capa (&dev_info);
482               break;
483
484               /* SR-IOV VFs */
485             case VNET_DPDK_PMD_IGBVF:
486             case VNET_DPDK_PMD_IXGBEVF:
487             case VNET_DPDK_PMD_I40EVF:
488               xd->port_type = VNET_DPDK_PORT_TYPE_ETH_VF;
489 #if RTE_VERSION < RTE_VERSION_NUM(18, 8, 0, 0)
490               xd->port_conf.rxmode.hw_strip_crc = 1;
491 #elif RTE_VERSION < RTE_VERSION_NUM(18, 11, 0, 0)
492               xd->port_conf.rxmode.offloads |= DEV_RX_OFFLOAD_CRC_STRIP;
493 #endif
494               break;
495
496             case VNET_DPDK_PMD_THUNDERX:
497               xd->port_type = VNET_DPDK_PORT_TYPE_ETH_VF;
498 #if RTE_VERSION < RTE_VERSION_NUM(18, 8, 0, 0)
499               xd->port_conf.rxmode.hw_strip_crc = 1;
500 #elif RTE_VERSION < RTE_VERSION_NUM(18, 11, 0, 0)
501               xd->port_conf.rxmode.offloads |= DEV_RX_OFFLOAD_CRC_STRIP;
502 #endif
503               break;
504
505             case VNET_DPDK_PMD_ENA:
506               xd->port_type = VNET_DPDK_PORT_TYPE_ETH_VF;
507 #if RTE_VERSION < RTE_VERSION_NUM(18, 8, 0, 0)
508               xd->port_conf.rxmode.enable_scatter = 0;
509 #else
510               xd->port_conf.rxmode.offloads &= ~DEV_RX_OFFLOAD_SCATTER;
511 #endif
512               break;
513
514             case VNET_DPDK_PMD_DPAA2:
515               xd->port_type = VNET_DPDK_PORT_TYPE_ETH_10G;
516               break;
517
518               /* Cisco VIC */
519             case VNET_DPDK_PMD_ENIC:
520               if (l.link_speed == 40000)
521                 xd->port_type = VNET_DPDK_PORT_TYPE_ETH_40G;
522               else
523                 xd->port_type = VNET_DPDK_PORT_TYPE_ETH_10G;
524               break;
525
526               /* Intel Red Rock Canyon */
527             case VNET_DPDK_PMD_FM10K:
528               xd->port_type = VNET_DPDK_PORT_TYPE_ETH_SWITCH;
529 #if RTE_VERSION < RTE_VERSION_NUM(18, 8, 0, 0)
530               xd->port_conf.rxmode.hw_strip_crc = 1;
531 #elif RTE_VERSION < RTE_VERSION_NUM(18, 11, 0, 0)
532               xd->port_conf.rxmode.offloads |= DEV_RX_OFFLOAD_CRC_STRIP;
533 #endif
534               break;
535
536               /* virtio */
537             case VNET_DPDK_PMD_VIRTIO:
538               xd->port_type = VNET_DPDK_PORT_TYPE_ETH_1G;
539               xd->nb_rx_desc = DPDK_NB_RX_DESC_VIRTIO;
540               xd->nb_tx_desc = DPDK_NB_TX_DESC_VIRTIO;
541               break;
542
543               /* vmxnet3 */
544             case VNET_DPDK_PMD_VMXNET3:
545               xd->port_type = VNET_DPDK_PORT_TYPE_ETH_1G;
546 #if RTE_VERSION < RTE_VERSION_NUM(18, 8, 0, 0)
547               xd->tx_conf.txq_flags |= ETH_TXQ_FLAGS_NOMULTSEGS;
548 #else
549               xd->port_conf.txmode.offloads |= DEV_TX_OFFLOAD_MULTI_SEGS;
550 #endif
551               break;
552
553             case VNET_DPDK_PMD_AF_PACKET:
554               xd->port_type = VNET_DPDK_PORT_TYPE_AF_PACKET;
555               xd->af_packet_instance_num = af_packet_instance_num++;
556               break;
557
558             case VNET_DPDK_PMD_BOND:
559               xd->port_type = VNET_DPDK_PORT_TYPE_ETH_BOND;
560               xd->bond_instance_num = bond_ether_instance_num++;
561               break;
562
563             case VNET_DPDK_PMD_VIRTIO_USER:
564               xd->port_type = VNET_DPDK_PORT_TYPE_VIRTIO_USER;
565               break;
566
567             case VNET_DPDK_PMD_VHOST_ETHER:
568               xd->port_type = VNET_DPDK_PORT_TYPE_VHOST_ETHER;
569               break;
570
571             case VNET_DPDK_PMD_LIOVF_ETHER:
572               xd->port_type = VNET_DPDK_PORT_TYPE_ETH_VF;
573               break;
574
575             case VNET_DPDK_PMD_FAILSAFE:
576               xd->port_type = VNET_DPDK_PORT_TYPE_FAILSAFE;
577               xd->port_conf.intr_conf.lsc = 1;
578               break;
579
580             case VNET_DPDK_PMD_NETVSC:
581               xd->port_type = port_type_from_link_speed (l.link_speed);
582               break;
583
584             default:
585               xd->port_type = VNET_DPDK_PORT_TYPE_UNKNOWN;
586             }
587
588           if (devconf->num_rx_desc)
589             xd->nb_rx_desc = devconf->num_rx_desc;
590
591           if (devconf->num_tx_desc)
592             xd->nb_tx_desc = devconf->num_tx_desc;
593         }
594
595       if (xd->pmd == VNET_DPDK_PMD_AF_PACKET)
596         {
597           f64 now = vlib_time_now (vm);
598           u32 rnd;
599           rnd = (u32) (now * 1e6);
600           rnd = random_u32 (&rnd);
601           clib_memcpy (addr + 2, &rnd, sizeof (rnd));
602           addr[0] = 2;
603           addr[1] = 0xfe;
604         }
605       else
606         rte_eth_macaddr_get (i, (struct ether_addr *) addr);
607
608       if (xd->tx_q_used < tm->n_vlib_mains)
609         dpdk_device_lock_init (xd);
610
611       xd->port_id = i;
612       xd->device_index = xd - dm->devices;
613       xd->per_interface_next_index = ~0;
614
615       /* assign interface to input thread */
616       int q;
617
618       if (devconf->hqos_enabled)
619         {
620           xd->flags |= DPDK_DEVICE_FLAG_HQOS;
621
622           int cpu;
623           if (devconf->hqos.hqos_thread_valid)
624             {
625               if (devconf->hqos.hqos_thread >= dm->hqos_cpu_count)
626                 return clib_error_return (0, "invalid HQoS thread index");
627
628               cpu = dm->hqos_cpu_first_index + devconf->hqos.hqos_thread;
629             }
630           else
631             {
632               if (dm->hqos_cpu_count == 0)
633                 return clib_error_return (0, "no HQoS threads available");
634
635               cpu = dm->hqos_cpu_first_index + next_hqos_cpu;
636
637               next_hqos_cpu++;
638               if (next_hqos_cpu == dm->hqos_cpu_count)
639                 next_hqos_cpu = 0;
640
641               devconf->hqos.hqos_thread_valid = 1;
642               devconf->hqos.hqos_thread = cpu;
643             }
644
645           dpdk_device_and_queue_t *dq;
646           vec_add2 (dm->devices_by_hqos_cpu[cpu], dq, 1);
647           dq->device = xd->device_index;
648           dq->queue_id = 0;
649         }
650
651       /* count the number of descriptors used for this device */
652       nb_desc += xd->nb_rx_desc + xd->nb_tx_desc * xd->tx_q_used;
653
654       error = ethernet_register_interface
655         (dm->vnet_main, dpdk_device_class.index, xd->device_index,
656          /* ethernet address */ addr,
657          &xd->hw_if_index, dpdk_flag_change);
658       if (error)
659         return error;
660
661       /*
662        * Ensure default mtu is not > the mtu read from the hardware.
663        * Otherwise rte_eth_dev_configure() will fail and the port will
664        * not be available.
665        * Calculate max_frame_size and mtu supported by NIC
666        */
667       if (ETHERNET_MAX_PACKET_BYTES > dev_info.max_rx_pktlen)
668         {
669           /*
670            * This device does not support the platforms's max frame
671            * size. Use it's advertised mru instead.
672            */
673           max_rx_frame = dev_info.max_rx_pktlen;
674           mtu = dev_info.max_rx_pktlen - sizeof (ethernet_header_t);
675         }
676       else
677         {
678           /* VPP treats MTU and max_rx_pktlen both equal to
679            * ETHERNET_MAX_PACKET_BYTES, if dev_info.max_rx_pktlen >=
680            * ETHERNET_MAX_PACKET_BYTES + sizeof(ethernet_header_t)
681            */
682           if (dev_info.max_rx_pktlen >= (ETHERNET_MAX_PACKET_BYTES +
683                                          sizeof (ethernet_header_t)))
684             {
685               mtu = ETHERNET_MAX_PACKET_BYTES;
686               max_rx_frame = ETHERNET_MAX_PACKET_BYTES;
687
688               /*
689                * Some platforms do not account for Ethernet FCS (4 bytes) in
690                * MTU calculations. To interop with them increase mru but only
691                * if the device's settings can support it.
692                */
693               if (dpdk_port_crc_strip_enabled (xd) &&
694                   (dev_info.max_rx_pktlen >= (ETHERNET_MAX_PACKET_BYTES +
695                                               sizeof (ethernet_header_t) +
696                                               4)))
697                 {
698                   max_rx_frame += 4;
699                 }
700             }
701           else
702             {
703               max_rx_frame = ETHERNET_MAX_PACKET_BYTES;
704               mtu = ETHERNET_MAX_PACKET_BYTES - sizeof (ethernet_header_t);
705
706               if (dpdk_port_crc_strip_enabled (xd) &&
707                   (dev_info.max_rx_pktlen >= (ETHERNET_MAX_PACKET_BYTES + 4)))
708                 {
709                   max_rx_frame += 4;
710                 }
711             }
712         }
713
714       if (xd->pmd == VNET_DPDK_PMD_FAILSAFE)
715         {
716           /* failsafe device numerables are reported with active device only,
717            * need to query the mtu for current device setup to overwrite
718            * reported value.
719            */
720           uint16_t dev_mtu;
721           if (!rte_eth_dev_get_mtu (i, &dev_mtu))
722             {
723               mtu = dev_mtu;
724               max_rx_frame = mtu + sizeof (ethernet_header_t);
725
726               if (dpdk_port_crc_strip_enabled (xd))
727                 {
728                   max_rx_frame += 4;
729                 }
730             }
731         }
732
733       /*Set port rxmode config */
734       xd->port_conf.rxmode.max_rx_pkt_len = max_rx_frame;
735
736       sw = vnet_get_hw_sw_interface (dm->vnet_main, xd->hw_if_index);
737       xd->sw_if_index = sw->sw_if_index;
738       vnet_hw_interface_set_input_node (dm->vnet_main, xd->hw_if_index,
739                                         dpdk_input_node.index);
740
741       if (devconf->workers)
742         {
743           int i;
744           q = 0;
745           clib_bitmap_foreach (i, devconf->workers, ({
746             vnet_hw_interface_assign_rx_thread (dm->vnet_main, xd->hw_if_index, q++,
747                                              vdm->first_worker_thread_index + i);
748           }));
749         }
750       else
751         for (q = 0; q < xd->rx_q_used; q++)
752           {
753             vnet_hw_interface_assign_rx_thread (dm->vnet_main, xd->hw_if_index, q,      /* any */
754                                                 ~1);
755           }
756
757       /*Get vnet hardware interface */
758       hi = vnet_get_hw_interface (dm->vnet_main, xd->hw_if_index);
759
760       /*Override default max_packet_bytes and max_supported_bytes set in
761        * ethernet_register_interface() above*/
762       if (hi)
763         {
764           hi->max_packet_bytes = mtu;
765           hi->max_supported_packet_bytes = max_rx_frame;
766         }
767
768       if (dm->conf->no_tx_checksum_offload == 0)
769         if (xd->flags & DPDK_DEVICE_FLAG_TX_OFFLOAD && hi != NULL)
770           hi->flags |= VNET_HW_INTERFACE_FLAG_SUPPORTS_TX_L4_CKSUM_OFFLOAD;
771
772       dpdk_device_setup (xd);
773
774       if (vec_len (xd->errors))
775         dpdk_log_err ("setup failed for device %U. Errors:\n  %U",
776                       format_dpdk_device_name, i,
777                       format_dpdk_device_errors, xd);
778
779       if (devconf->hqos_enabled)
780         {
781           clib_error_t *rv;
782           rv = dpdk_port_setup_hqos (xd, &devconf->hqos);
783           if (rv)
784             return rv;
785         }
786
787       /*
788        * For cisco VIC vNIC, set default to VLAN strip enabled, unless
789        * specified otherwise in the startup config.
790        * For other NICs default to VLAN strip disabled, unless specified
791        * otherwise in the startup config.
792        */
793       if (xd->pmd == VNET_DPDK_PMD_ENIC)
794         {
795           if (devconf->vlan_strip_offload != DPDK_DEVICE_VLAN_STRIP_OFF)
796             vlan_strip = 1;     /* remove vlan tag from VIC port by default */
797           else
798             dpdk_log_warn ("VLAN strip disabled for interface\n");
799         }
800       else if (devconf->vlan_strip_offload == DPDK_DEVICE_VLAN_STRIP_ON)
801         vlan_strip = 1;
802
803       if (vlan_strip)
804         {
805           int vlan_off;
806           vlan_off = rte_eth_dev_get_vlan_offload (xd->port_id);
807           vlan_off |= ETH_VLAN_STRIP_OFFLOAD;
808 #if RTE_VERSION < RTE_VERSION_NUM(18, 8, 0, 0)
809           xd->port_conf.rxmode.hw_vlan_strip = vlan_off;
810 #else
811           if (vlan_off)
812             xd->port_conf.rxmode.offloads |= DEV_RX_OFFLOAD_VLAN_STRIP;
813           else
814             xd->port_conf.rxmode.offloads &= ~DEV_RX_OFFLOAD_VLAN_STRIP;
815 #endif
816           if (rte_eth_dev_set_vlan_offload (xd->port_id, vlan_off) == 0)
817             dpdk_log_info ("VLAN strip enabled for interface\n");
818           else
819             dpdk_log_warn ("VLAN strip cannot be supported by interface\n");
820         }
821
822       if (hi)
823         hi->max_packet_bytes = xd->port_conf.rxmode.max_rx_pkt_len
824           - sizeof (ethernet_header_t);
825       else
826         clib_warning ("hi NULL");
827
828       if (dm->conf->no_multi_seg)
829         mtu = mtu > ETHER_MAX_LEN ? ETHER_MAX_LEN : mtu;
830
831       rte_eth_dev_set_mtu (xd->port_id, mtu);
832     }
833   /* *INDENT-ON* */
834
835   if (nb_desc > dm->conf->num_mbufs)
836     dpdk_log_err ("%d mbufs allocated but total rx/tx ring size is %d\n",
837                   dm->conf->num_mbufs, nb_desc);
838
839   return 0;
840 }
841
842 static void
843 dpdk_bind_devices_to_uio (dpdk_config_main_t * conf)
844 {
845   vlib_main_t *vm = vlib_get_main ();
846   clib_error_t *error;
847   u8 *pci_addr = 0;
848   int num_whitelisted = vec_len (conf->dev_confs);
849   vlib_pci_device_info_t *d = 0;
850   vlib_pci_addr_t *addr = 0, *addrs;
851
852   addrs = vlib_pci_get_all_dev_addrs ();
853   /* *INDENT-OFF* */
854   vec_foreach (addr, addrs)
855     {
856     dpdk_device_config_t * devconf = 0;
857     vec_reset_length (pci_addr);
858     pci_addr = format (pci_addr, "%U%c", format_vlib_pci_addr, addr, 0);
859     if (d)
860     {
861       vlib_pci_free_device_info (d);
862       d = 0;
863       }
864     d = vlib_pci_get_device_info (vm, addr, &error);
865     if (error)
866     {
867       clib_error_report (error);
868       continue;
869     }
870
871     if (d->device_class != PCI_CLASS_NETWORK_ETHERNET && d->device_class != PCI_CLASS_PROCESSOR_CO)
872       continue;
873
874     if (num_whitelisted)
875       {
876         uword * p = hash_get (conf->device_config_index_by_pci_addr, addr->as_u32);
877
878         if (!p)
879           continue;
880
881         devconf = pool_elt_at_index (conf->dev_confs, p[0]);
882       }
883
884     /* virtio */
885     if (d->vendor_id == 0x1af4 &&
886             (d->device_id == VIRTIO_PCI_LEGACY_DEVICEID_NET ||
887              d->device_id == VIRTIO_PCI_MODERN_DEVICEID_NET))
888       ;
889     /* vmxnet3 */
890     else if (d->vendor_id == 0x15ad && d->device_id == 0x07b0)
891       {
892         /*
893          * For vmxnet3 PCI, unless it is explicitly specified in the whitelist,
894          * the default is to put it in the blacklist.
895          */
896         if (devconf == 0)
897           {
898             pool_get (conf->dev_confs, devconf);
899             hash_set (conf->device_config_index_by_pci_addr, addr->as_u32,
900                       devconf - conf->dev_confs);
901             devconf->pci_addr.as_u32 = addr->as_u32;
902             devconf->is_blacklisted = 1;
903           }
904       }
905     /* all Intel network devices */
906     else if (d->vendor_id == 0x8086 && d->device_class == PCI_CLASS_NETWORK_ETHERNET)
907       ;
908     /* all Intel QAT devices VFs */
909     else if (d->vendor_id == 0x8086 && d->device_class == PCI_CLASS_PROCESSOR_CO &&
910         (d->device_id == 0x0443 || d->device_id == 0x37c9 || d->device_id == 0x19e3))
911       ;
912     /* Cisco VIC */
913     else if (d->vendor_id == 0x1137 && d->device_id == 0x0043)
914       ;
915     /* Chelsio T4/T5 */
916     else if (d->vendor_id == 0x1425 && (d->device_id & 0xe000) == 0x4000)
917       ;
918     /* Amazen Elastic Network Adapter */
919     else if (d->vendor_id == 0x1d0f && d->device_id >= 0xec20 && d->device_id <= 0xec21)
920       ;
921     /* Cavium Network Adapter */
922     else if (d->vendor_id == 0x177d && d->device_id == 0x9712)
923       ;
924     /* Cavium FastlinQ QL41000 Series */
925     else if (d->vendor_id == 0x1077 && d->device_id >= 0x8070 && d->device_id <= 0x8090)
926       ;
927     /* Mellanox mlx4 */
928     else if (d->vendor_id == 0x15b3 && d->device_id >= 0x1003 && d->device_id <= 0x1004)
929       {
930         continue;
931       }
932     /* Mellanox mlx5 */
933     else if (d->vendor_id == 0x15b3 && d->device_id >= 0x1013 && d->device_id <= 0x101a)
934       {
935         continue;
936       }
937     else
938       {
939         dpdk_log_warn ("Unsupported PCI device 0x%04x:0x%04x found "
940                       "at PCI address %s\n", (u16) d->vendor_id, (u16) d->device_id,
941                       pci_addr);
942         continue;
943       }
944
945     error = vlib_pci_bind_to_uio (vm, addr, (char *) conf->uio_driver_name);
946
947     if (error)
948       {
949         if (devconf == 0)
950           {
951             pool_get (conf->dev_confs, devconf);
952             hash_set (conf->device_config_index_by_pci_addr, addr->as_u32,
953                       devconf - conf->dev_confs);
954             devconf->pci_addr.as_u32 = addr->as_u32;
955           }
956         devconf->is_blacklisted = 1;
957         clib_error_report (error);
958       }
959   }
960   /* *INDENT-ON* */
961   vec_free (pci_addr);
962   vlib_pci_free_device_info (d);
963 }
964
965 static clib_error_t *
966 dpdk_device_config (dpdk_config_main_t * conf, vlib_pci_addr_t pci_addr,
967                     unformat_input_t * input, u8 is_default)
968 {
969   clib_error_t *error = 0;
970   uword *p;
971   dpdk_device_config_t *devconf;
972   unformat_input_t sub_input;
973
974   if (is_default)
975     {
976       devconf = &conf->default_devconf;
977     }
978   else
979     {
980       p = hash_get (conf->device_config_index_by_pci_addr, pci_addr.as_u32);
981
982       if (!p)
983         {
984           pool_get (conf->dev_confs, devconf);
985           hash_set (conf->device_config_index_by_pci_addr, pci_addr.as_u32,
986                     devconf - conf->dev_confs);
987         }
988       else
989         return clib_error_return (0,
990                                   "duplicate configuration for PCI address %U",
991                                   format_vlib_pci_addr, &pci_addr);
992     }
993
994   devconf->pci_addr.as_u32 = pci_addr.as_u32;
995   devconf->hqos_enabled = 0;
996   dpdk_device_config_hqos_default (&devconf->hqos);
997
998   if (!input)
999     return 0;
1000
1001   unformat_skip_white_space (input);
1002   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1003     {
1004       if (unformat (input, "num-rx-queues %u", &devconf->num_rx_queues))
1005         ;
1006       else if (unformat (input, "num-tx-queues %u", &devconf->num_tx_queues))
1007         ;
1008       else if (unformat (input, "num-rx-desc %u", &devconf->num_rx_desc))
1009         ;
1010       else if (unformat (input, "num-tx-desc %u", &devconf->num_tx_desc))
1011         ;
1012       else if (unformat (input, "workers %U", unformat_bitmap_list,
1013                          &devconf->workers))
1014         ;
1015       else
1016         if (unformat
1017             (input, "rss %U", unformat_vlib_cli_sub_input, &sub_input))
1018         {
1019           error = unformat_rss_fn (&sub_input, &devconf->rss_fn);
1020           if (error)
1021             break;
1022         }
1023       else if (unformat (input, "vlan-strip-offload off"))
1024         devconf->vlan_strip_offload = DPDK_DEVICE_VLAN_STRIP_OFF;
1025       else if (unformat (input, "vlan-strip-offload on"))
1026         devconf->vlan_strip_offload = DPDK_DEVICE_VLAN_STRIP_ON;
1027       else
1028         if (unformat
1029             (input, "hqos %U", unformat_vlib_cli_sub_input, &sub_input))
1030         {
1031           devconf->hqos_enabled = 1;
1032           error = unformat_hqos (&sub_input, &devconf->hqos);
1033           if (error)
1034             break;
1035         }
1036       else if (unformat (input, "hqos"))
1037         {
1038           devconf->hqos_enabled = 1;
1039         }
1040       else
1041         {
1042           error = clib_error_return (0, "unknown input `%U'",
1043                                      format_unformat_error, input);
1044           break;
1045         }
1046     }
1047
1048   if (error)
1049     return error;
1050
1051   if (devconf->workers && devconf->num_rx_queues == 0)
1052     devconf->num_rx_queues = clib_bitmap_count_set_bits (devconf->workers);
1053   else if (devconf->workers &&
1054            clib_bitmap_count_set_bits (devconf->workers) !=
1055            devconf->num_rx_queues)
1056     error =
1057       clib_error_return (0,
1058                          "%U: number of worker threads must be "
1059                          "equal to number of rx queues", format_vlib_pci_addr,
1060                          &pci_addr);
1061
1062   return error;
1063 }
1064
1065 static clib_error_t *
1066 dpdk_log_read_ready (clib_file_t * uf)
1067 {
1068   unformat_input_t input;
1069   u8 *line, *s = 0;
1070   int n, n_try;
1071
1072   n = n_try = 4096;
1073   while (n == n_try)
1074     {
1075       uword len = vec_len (s);
1076       vec_resize (s, len + n_try);
1077
1078       n = read (uf->file_descriptor, s + len, n_try);
1079       if (n < 0 && errno != EAGAIN)
1080         return clib_error_return_unix (0, "read");
1081       _vec_len (s) = len + (n < 0 ? 0 : n);
1082     }
1083
1084   unformat_init_vector (&input, s);
1085
1086   while (unformat_user (&input, unformat_line, &line))
1087     {
1088       dpdk_log_notice ("%v", line);
1089       vec_free (line);
1090     }
1091
1092   unformat_free (&input);
1093   return 0;
1094 }
1095
1096 static clib_error_t *
1097 dpdk_config (vlib_main_t * vm, unformat_input_t * input)
1098 {
1099   clib_error_t *error = 0;
1100   dpdk_config_main_t *conf = &dpdk_config_main;
1101   vlib_thread_main_t *tm = vlib_get_thread_main ();
1102   dpdk_device_config_t *devconf;
1103   vlib_pci_addr_t pci_addr;
1104   unformat_input_t sub_input;
1105   uword x;
1106   u8 *s, *tmp = 0;
1107   u32 log_level;
1108   int ret, i;
1109   int num_whitelisted = 0;
1110   u8 no_pci = 0;
1111   u8 no_huge = 0;
1112   u8 huge_dir = 0;
1113   u8 file_prefix = 0;
1114   u8 *socket_mem = 0;
1115   u8 *huge_dir_path = 0;
1116
1117   huge_dir_path =
1118     format (0, "%s/hugepages%c", vlib_unix_get_runtime_dir (), 0);
1119
1120   conf->device_config_index_by_pci_addr = hash_create (0, sizeof (uword));
1121   log_level = RTE_LOG_NOTICE;
1122
1123   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1124     {
1125       /* Prime the pump */
1126       if (unformat (input, "no-hugetlb"))
1127         {
1128           vec_add1 (conf->eal_init_args, (u8 *) "--no-huge");
1129           no_huge = 1;
1130         }
1131
1132       else if (unformat (input, "enable-tcp-udp-checksum"))
1133         conf->enable_tcp_udp_checksum = 1;
1134
1135       else if (unformat (input, "no-tx-checksum-offload"))
1136         conf->no_tx_checksum_offload = 1;
1137
1138       else if (unformat (input, "decimal-interface-names"))
1139         conf->interface_name_format_decimal = 1;
1140
1141       else if (unformat (input, "log-level %U", unformat_dpdk_log_level, &x))
1142         log_level = x;
1143
1144       else if (unformat (input, "no-multi-seg"))
1145         conf->no_multi_seg = 1;
1146
1147       else if (unformat (input, "dev default %U", unformat_vlib_cli_sub_input,
1148                          &sub_input))
1149         {
1150           error =
1151             dpdk_device_config (conf, (vlib_pci_addr_t) (u32) ~ 1, &sub_input,
1152                                 1);
1153
1154           if (error)
1155             return error;
1156         }
1157       else
1158         if (unformat
1159             (input, "dev %U %U", unformat_vlib_pci_addr, &pci_addr,
1160              unformat_vlib_cli_sub_input, &sub_input))
1161         {
1162           error = dpdk_device_config (conf, pci_addr, &sub_input, 0);
1163
1164           if (error)
1165             return error;
1166
1167           num_whitelisted++;
1168         }
1169       else if (unformat (input, "dev %U", unformat_vlib_pci_addr, &pci_addr))
1170         {
1171           error = dpdk_device_config (conf, pci_addr, 0, 0);
1172
1173           if (error)
1174             return error;
1175
1176           num_whitelisted++;
1177         }
1178       else if (unformat (input, "num-mem-channels %d", &conf->nchannels))
1179         conf->nchannels_set_manually = 0;
1180       else if (unformat (input, "num-mbufs %d", &conf->num_mbufs))
1181         ;
1182       else if (unformat (input, "uio-driver %s", &conf->uio_driver_name))
1183         ;
1184       else if (unformat (input, "socket-mem %s", &socket_mem))
1185         ;
1186       else if (unformat (input, "no-pci"))
1187         {
1188           no_pci = 1;
1189           tmp = format (0, "--no-pci%c", 0);
1190           vec_add1 (conf->eal_init_args, tmp);
1191         }
1192
1193 #define _(a)                                    \
1194       else if (unformat(input, #a))             \
1195         {                                       \
1196           tmp = format (0, "--%s%c", #a, 0);    \
1197           vec_add1 (conf->eal_init_args, tmp);    \
1198         }
1199       foreach_eal_double_hyphen_predicate_arg
1200 #undef _
1201 #define _(a)                                          \
1202         else if (unformat(input, #a " %s", &s))       \
1203           {                                           \
1204             if (!strncmp(#a, "huge-dir", 8))          \
1205               huge_dir = 1;                           \
1206             else if (!strncmp(#a, "file-prefix", 11)) \
1207               file_prefix = 1;                        \
1208             tmp = format (0, "--%s%c", #a, 0);        \
1209             vec_add1 (conf->eal_init_args, tmp);      \
1210             vec_add1 (s, 0);                          \
1211             if (!strncmp(#a, "vdev", 4))              \
1212               if (strstr((char*)s, "af_packet"))      \
1213                 clib_warning ("af_packet obsoleted. Use CLI 'create host-interface'."); \
1214             vec_add1 (conf->eal_init_args, s);        \
1215           }
1216         foreach_eal_double_hyphen_arg
1217 #undef _
1218 #define _(a,b)                                          \
1219           else if (unformat(input, #a " %s", &s))       \
1220             {                                           \
1221               tmp = format (0, "-%s%c", #b, 0);         \
1222               vec_add1 (conf->eal_init_args, tmp);      \
1223               vec_add1 (s, 0);                          \
1224               vec_add1 (conf->eal_init_args, s);        \
1225             }
1226         foreach_eal_single_hyphen_arg
1227 #undef _
1228 #define _(a,b)                                          \
1229             else if (unformat(input, #a " %s", &s))     \
1230               {                                         \
1231                 tmp = format (0, "-%s%c", #b, 0);       \
1232                 vec_add1 (conf->eal_init_args, tmp);    \
1233                 vec_add1 (s, 0);                        \
1234                 vec_add1 (conf->eal_init_args, s);      \
1235                 conf->a##_set_manually = 1;             \
1236               }
1237         foreach_eal_single_hyphen_mandatory_arg
1238 #undef _
1239         else if (unformat (input, "default"))
1240         ;
1241
1242       else if (unformat_skip_white_space (input))
1243         ;
1244       else
1245         {
1246           error = clib_error_return (0, "unknown input `%U'",
1247                                      format_unformat_error, input);
1248           goto done;
1249         }
1250     }
1251
1252   if (!conf->uio_driver_name)
1253     conf->uio_driver_name = format (0, "auto%c", 0);
1254
1255   /*
1256    * Use 1G huge pages if available.
1257    */
1258   if (!no_huge && !huge_dir)
1259     {
1260       u32 x, *mem_by_socket = 0;
1261       uword c = 0;
1262       int rv;
1263
1264       umount ((char *) huge_dir_path);
1265
1266       /* Process "socket-mem" parameter value */
1267       if (vec_len (socket_mem))
1268         {
1269           unformat_input_t in;
1270           unformat_init_vector (&in, socket_mem);
1271           while (unformat_check_input (&in) != UNFORMAT_END_OF_INPUT)
1272             {
1273               if (unformat (&in, "%u,", &x))
1274                 ;
1275               else if (unformat (&in, "%u", &x))
1276                 ;
1277               else if (unformat (&in, ","))
1278                 x = 0;
1279               else
1280                 break;
1281
1282               vec_add1 (mem_by_socket, x);
1283             }
1284           /* Note: unformat_free vec_frees(in.buffer), aka socket_mem... */
1285           unformat_free (&in);
1286           socket_mem = 0;
1287         }
1288       else
1289         {
1290           /* *INDENT-OFF* */
1291           clib_bitmap_foreach (c, tm->cpu_socket_bitmap, (
1292             {
1293               vec_validate(mem_by_socket, c);
1294               mem_by_socket[c] = 64; /* default per-socket mem */
1295             }
1296           ));
1297           /* *INDENT-ON* */
1298         }
1299
1300       uword default_hugepage_sz = clib_mem_get_default_hugepage_size ();
1301       /* *INDENT-OFF* */
1302       clib_bitmap_foreach (c, tm->cpu_socket_bitmap, (
1303         {
1304           clib_error_t *e;
1305           uword n_pages;
1306           vec_validate(mem_by_socket, c);
1307           n_pages = round_pow2 ((uword) mem_by_socket[c]<<20,
1308                                 default_hugepage_sz);
1309           n_pages /= default_hugepage_sz;
1310
1311           if ((e = clib_sysfs_prealloc_hugepages(c, 0, n_pages)))
1312             clib_error_report (e);
1313       }));
1314       /* *INDENT-ON* */
1315
1316       if (mem_by_socket == 0)
1317         {
1318           error = clib_error_return (0, "mem_by_socket NULL");
1319           goto done;
1320         }
1321       _vec_len (mem_by_socket) = c + 1;
1322
1323       /* regenerate socket_mem string */
1324       vec_foreach_index (x, mem_by_socket)
1325         socket_mem = format (socket_mem, "%s%u",
1326                              socket_mem ? "," : "", mem_by_socket[x]);
1327       socket_mem = format (socket_mem, "%c", 0);
1328
1329       vec_free (mem_by_socket);
1330
1331       error = vlib_unix_recursive_mkdir ((char *) huge_dir_path);
1332       if (error)
1333         {
1334           goto done;
1335         }
1336
1337       rv = mount ("none", (char *) huge_dir_path, "hugetlbfs", 0, NULL);
1338
1339       if (rv)
1340         {
1341           error = clib_error_return (0, "mount failed %d", errno);
1342           goto done;
1343         }
1344
1345       tmp = format (0, "--huge-dir%c", 0);
1346       vec_add1 (conf->eal_init_args, tmp);
1347       tmp = format (0, "%s%c", huge_dir_path, 0);
1348       vec_add1 (conf->eal_init_args, tmp);
1349       if (!file_prefix)
1350         {
1351           tmp = format (0, "--file-prefix%c", 0);
1352           vec_add1 (conf->eal_init_args, tmp);
1353           tmp = format (0, "vpp%c", 0);
1354           vec_add1 (conf->eal_init_args, tmp);
1355         }
1356     }
1357
1358   if (error)
1359     return error;
1360
1361   /* I'll bet that -c and -n must be the first and second args... */
1362   if (!conf->coremask_set_manually)
1363     {
1364       vlib_thread_registration_t *tr;
1365       uword *coremask = 0;
1366       int i;
1367
1368       /* main thread core */
1369       coremask = clib_bitmap_set (coremask, tm->main_lcore, 1);
1370
1371       for (i = 0; i < vec_len (tm->registrations); i++)
1372         {
1373           tr = tm->registrations[i];
1374           coremask = clib_bitmap_or (coremask, tr->coremask);
1375         }
1376
1377       vec_insert (conf->eal_init_args, 2, 1);
1378       conf->eal_init_args[1] = (u8 *) "-c";
1379       tmp = format (0, "%U%c", format_bitmap_hex, coremask, 0);
1380       conf->eal_init_args[2] = tmp;
1381       clib_bitmap_free (coremask);
1382     }
1383
1384   if (!conf->nchannels_set_manually)
1385     {
1386       vec_insert (conf->eal_init_args, 2, 3);
1387       conf->eal_init_args[3] = (u8 *) "-n";
1388       tmp = format (0, "%d", conf->nchannels);
1389       conf->eal_init_args[4] = tmp;
1390     }
1391
1392   if (no_pci == 0 && geteuid () == 0)
1393     dpdk_bind_devices_to_uio (conf);
1394
1395 #define _(x) \
1396     if (devconf->x == 0 && conf->default_devconf.x > 0) \
1397       devconf->x = conf->default_devconf.x ;
1398
1399   /* *INDENT-OFF* */
1400   pool_foreach (devconf, conf->dev_confs, ({
1401
1402     /* default per-device config items */
1403     foreach_dpdk_device_config_item
1404
1405     /* add DPDK EAL whitelist/blacklist entry */
1406     if (num_whitelisted > 0 && devconf->is_blacklisted == 0)
1407       {
1408         tmp = format (0, "-w%c", 0);
1409         vec_add1 (conf->eal_init_args, tmp);
1410         tmp = format (0, "%U%c", format_vlib_pci_addr, &devconf->pci_addr, 0);
1411         vec_add1 (conf->eal_init_args, tmp);
1412       }
1413     else if (num_whitelisted == 0 && devconf->is_blacklisted != 0)
1414       {
1415         tmp = format (0, "-b%c", 0);
1416         vec_add1 (conf->eal_init_args, tmp);
1417         tmp = format (0, "%U%c", format_vlib_pci_addr, &devconf->pci_addr, 0);
1418         vec_add1 (conf->eal_init_args, tmp);
1419       }
1420   }));
1421   /* *INDENT-ON* */
1422
1423 #undef _
1424
1425   /* set master-lcore */
1426   tmp = format (0, "--master-lcore%c", 0);
1427   vec_add1 (conf->eal_init_args, tmp);
1428   tmp = format (0, "%u%c", tm->main_lcore, 0);
1429   vec_add1 (conf->eal_init_args, tmp);
1430
1431   /* set socket-mem */
1432   if (!no_huge)
1433     {
1434       tmp = format (0, "--socket-mem%c", 0);
1435       vec_add1 (conf->eal_init_args, tmp);
1436       tmp = format (0, "%s%c", socket_mem, 0);
1437       vec_add1 (conf->eal_init_args, tmp);
1438     }
1439
1440   /* NULL terminate the "argv" vector, in case of stupidity */
1441   vec_add1 (conf->eal_init_args, 0);
1442   _vec_len (conf->eal_init_args) -= 1;
1443
1444   /* Set up DPDK eal and packet mbuf pool early. */
1445
1446   rte_log_set_global_level (log_level);
1447   int log_fds[2] = { 0 };
1448   if (pipe (log_fds) == 0)
1449     {
1450       if (fcntl (log_fds[1], F_SETFL, O_NONBLOCK) == 0)
1451         {
1452           FILE *f = fdopen (log_fds[1], "a");
1453           if (f && rte_openlog_stream (f) == 0)
1454             {
1455               clib_file_t t = { 0 };
1456               t.read_function = dpdk_log_read_ready;
1457               t.file_descriptor = log_fds[0];
1458               t.description = format (0, "DPDK logging pipe");
1459               clib_file_add (&file_main, &t);
1460             }
1461         }
1462       else
1463         {
1464           close (log_fds[0]);
1465           close (log_fds[1]);
1466         }
1467     }
1468
1469   vm = vlib_get_main ();
1470
1471   /* make copy of args as rte_eal_init tends to mess up with arg array */
1472   for (i = 1; i < vec_len (conf->eal_init_args); i++)
1473     conf->eal_init_args_str = format (conf->eal_init_args_str, "%s ",
1474                                       conf->eal_init_args[i]);
1475
1476   dpdk_log_warn ("EAL init args: %s", conf->eal_init_args_str);
1477   ret = rte_eal_init (vec_len (conf->eal_init_args),
1478                       (char **) conf->eal_init_args);
1479
1480   /* lazy umount hugepages */
1481   umount2 ((char *) huge_dir_path, MNT_DETACH);
1482   rmdir ((char *) huge_dir_path);
1483   vec_free (huge_dir_path);
1484
1485   if (ret < 0)
1486     return clib_error_return (0, "rte_eal_init returned %d", ret);
1487
1488   /* set custom ring memory allocator */
1489   {
1490     struct rte_mempool_ops *ops = NULL;
1491
1492     ops = get_ops_by_name ("ring_sp_sc");
1493     ops->alloc = dpdk_ring_alloc;
1494
1495     ops = get_ops_by_name ("ring_mp_sc");
1496     ops->alloc = dpdk_ring_alloc;
1497
1498     ops = get_ops_by_name ("ring_sp_mc");
1499     ops->alloc = dpdk_ring_alloc;
1500
1501     ops = get_ops_by_name ("ring_mp_mc");
1502     ops->alloc = dpdk_ring_alloc;
1503   }
1504
1505   /* main thread 1st */
1506   error = dpdk_buffer_pool_create (vm, conf->num_mbufs, rte_socket_id ());
1507   if (error)
1508     return error;
1509
1510   for (i = 0; i < RTE_MAX_LCORE; i++)
1511     {
1512       error = dpdk_buffer_pool_create (vm, conf->num_mbufs,
1513                                        rte_lcore_to_socket_id (i));
1514       if (error)
1515         return error;
1516     }
1517
1518 done:
1519   return error;
1520 }
1521
1522 VLIB_CONFIG_FUNCTION (dpdk_config, "dpdk");
1523
1524 void
1525 dpdk_update_link_state (dpdk_device_t * xd, f64 now)
1526 {
1527   vnet_main_t *vnm = vnet_get_main ();
1528   struct rte_eth_link prev_link = xd->link;
1529   u32 hw_flags = 0;
1530   u8 hw_flags_chg = 0;
1531
1532   /* only update link state for PMD interfaces */
1533   if ((xd->flags & DPDK_DEVICE_FLAG_PMD) == 0)
1534     return;
1535
1536   xd->time_last_link_update = now ? now : xd->time_last_link_update;
1537   clib_memset (&xd->link, 0, sizeof (xd->link));
1538   rte_eth_link_get_nowait (xd->port_id, &xd->link);
1539
1540   if (LINK_STATE_ELOGS)
1541     {
1542       vlib_main_t *vm = vlib_get_main ();
1543       ELOG_TYPE_DECLARE (e) =
1544       {
1545       .format =
1546           "update-link-state: sw_if_index %d, admin_up %d,"
1547           "old link_state %d new link_state %d",.format_args = "i4i1i1i1",};
1548
1549       struct
1550       {
1551         u32 sw_if_index;
1552         u8 admin_up;
1553         u8 old_link_state;
1554         u8 new_link_state;
1555       } *ed;
1556       ed = ELOG_DATA (&vm->elog_main, e);
1557       ed->sw_if_index = xd->sw_if_index;
1558       ed->admin_up = (xd->flags & DPDK_DEVICE_FLAG_ADMIN_UP) != 0;
1559       ed->old_link_state = (u8)
1560         vnet_hw_interface_is_link_up (vnm, xd->hw_if_index);
1561       ed->new_link_state = (u8) xd->link.link_status;
1562     }
1563
1564   if ((xd->flags & (DPDK_DEVICE_FLAG_ADMIN_UP | DPDK_DEVICE_FLAG_BOND_SLAVE))
1565       && ((xd->link.link_status != 0) ^
1566           vnet_hw_interface_is_link_up (vnm, xd->hw_if_index)))
1567     {
1568       hw_flags_chg = 1;
1569       hw_flags |= (xd->link.link_status ? VNET_HW_INTERFACE_FLAG_LINK_UP : 0);
1570     }
1571
1572   if (hw_flags_chg || (xd->link.link_duplex != prev_link.link_duplex))
1573     {
1574       hw_flags_chg = 1;
1575       switch (xd->link.link_duplex)
1576         {
1577         case ETH_LINK_HALF_DUPLEX:
1578           hw_flags |= VNET_HW_INTERFACE_FLAG_HALF_DUPLEX;
1579           break;
1580         case ETH_LINK_FULL_DUPLEX:
1581           hw_flags |= VNET_HW_INTERFACE_FLAG_FULL_DUPLEX;
1582           break;
1583         default:
1584           break;
1585         }
1586     }
1587   if (xd->link.link_speed != prev_link.link_speed)
1588     vnet_hw_interface_set_link_speed (vnm, xd->hw_if_index,
1589                                       xd->link.link_speed * 1000);
1590
1591   if (hw_flags_chg)
1592     {
1593       if (LINK_STATE_ELOGS)
1594         {
1595           vlib_main_t *vm = vlib_get_main ();
1596
1597           ELOG_TYPE_DECLARE (e) =
1598           {
1599           .format =
1600               "update-link-state: sw_if_index %d, new flags %d",.format_args
1601               = "i4i4",};
1602
1603           struct
1604           {
1605             u32 sw_if_index;
1606             u32 flags;
1607           } *ed;
1608           ed = ELOG_DATA (&vm->elog_main, e);
1609           ed->sw_if_index = xd->sw_if_index;
1610           ed->flags = hw_flags;
1611         }
1612       vnet_hw_interface_set_flags (vnm, xd->hw_if_index, hw_flags);
1613     }
1614 }
1615
1616 static uword
1617 dpdk_process (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f)
1618 {
1619   clib_error_t *error;
1620   vnet_main_t *vnm = vnet_get_main ();
1621   dpdk_main_t *dm = &dpdk_main;
1622   ethernet_main_t *em = &ethernet_main;
1623   dpdk_device_t *xd;
1624   vlib_thread_main_t *tm = vlib_get_thread_main ();
1625   int i;
1626   int j;
1627
1628   error = dpdk_lib_init (dm);
1629
1630   if (error)
1631     clib_error_report (error);
1632
1633   tm->worker_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   {
1642     /*
1643      * Extra set up for bond interfaces:
1644      *  1. Setup MACs for bond interfaces and their slave links which was set
1645      *     in dpdk_device_setup() but needs to be done again here to take
1646      *     effect.
1647      *  2. Set up info and register slave link state change callback handling.
1648      *  3. Set up info for bond interface related CLI support.
1649      */
1650     int nports = rte_eth_dev_count_avail ();
1651     if (nports > 0)
1652       {
1653         /* *INDENT-OFF* */
1654         RTE_ETH_FOREACH_DEV(i)
1655           {
1656             xd = NULL;
1657             for (j = 0; j < nports; j++)
1658               {
1659                 if (dm->devices[j].port_id == i)
1660                   {
1661                     xd = &dm->devices[j];
1662                   }
1663               }
1664             if (xd != NULL && xd->pmd == VNET_DPDK_PMD_BOND)
1665               {
1666                 u8 addr[6];
1667                 dpdk_portid_t slink[16];
1668                 int nlink = rte_eth_bond_slaves_get (i, slink, 16);
1669                 if (nlink > 0)
1670                   {
1671                     vnet_hw_interface_t *bhi;
1672                     ethernet_interface_t *bei;
1673                     int rv;
1674
1675                     /* Get MAC of 1st slave link */
1676                     rte_eth_macaddr_get
1677                       (slink[0], (struct ether_addr *) addr);
1678
1679                     /* Set MAC of bounded interface to that of 1st slave link */
1680                     dpdk_log_info ("Set MAC for bond port %d BondEthernet%d",
1681                                    i, xd->bond_instance_num);
1682                     rv = rte_eth_bond_mac_address_set
1683                       (i, (struct ether_addr *) addr);
1684                     if (rv)
1685                       dpdk_log_warn ("Set MAC addr failure rv=%d", rv);
1686
1687                     /* Populate MAC of bonded interface in VPP hw tables */
1688                     bhi = vnet_get_hw_interface
1689                       (vnm, dm->devices[i].hw_if_index);
1690                     bei = pool_elt_at_index
1691                       (em->interfaces, bhi->hw_instance);
1692                     clib_memcpy (bhi->hw_address, addr, 6);
1693                     clib_memcpy (bei->address, addr, 6);
1694
1695                     /* Init l3 packet size allowed on bonded interface */
1696                     bhi->max_packet_bytes = ETHERNET_MAX_PACKET_BYTES;
1697                     while (nlink >= 1)
1698                       {         /* for all slave links */
1699                         int slave = slink[--nlink];
1700                         dpdk_device_t *sdev = &dm->devices[slave];
1701                         vnet_hw_interface_t *shi;
1702                         vnet_sw_interface_t *ssi;
1703                         ethernet_interface_t *sei;
1704                         /* Add MAC to all slave links except the first one */
1705                         if (nlink)
1706                           {
1707                             dpdk_log_info ("Add MAC for slave port %d",
1708                                            slave);
1709                             rv = rte_eth_dev_mac_addr_add
1710                               (slave, (struct ether_addr *) addr, 0);
1711                             if (rv)
1712                               dpdk_log_warn ("Add MAC addr failure rv=%d",
1713                                              rv);
1714                           }
1715                         /* Setup slave link state change callback handling */
1716                         rte_eth_dev_callback_register
1717                           (slave, RTE_ETH_EVENT_INTR_LSC,
1718                            dpdk_port_state_callback, NULL);
1719                         dpdk_device_t *sxd = &dm->devices[slave];
1720                         sxd->flags |= DPDK_DEVICE_FLAG_BOND_SLAVE;
1721                         sxd->bond_port = i;
1722                         /* Set slaves bitmap for bonded interface */
1723                         bhi->bond_info = clib_bitmap_set
1724                           (bhi->bond_info, sdev->hw_if_index, 1);
1725                         /* Set MACs and slave link flags on slave interface */
1726                         shi = vnet_get_hw_interface (vnm, sdev->hw_if_index);
1727                         ssi = vnet_get_sw_interface (vnm, sdev->sw_if_index);
1728                         sei = pool_elt_at_index
1729                           (em->interfaces, shi->hw_instance);
1730                         shi->bond_info = VNET_HW_INTERFACE_BOND_INFO_SLAVE;
1731                         ssi->flags |= VNET_SW_INTERFACE_FLAG_BOND_SLAVE;
1732                         clib_memcpy (shi->hw_address, addr, 6);
1733                         clib_memcpy (sei->address, addr, 6);
1734                         /* Set l3 packet size allowed as the lowest of slave */
1735                         if (bhi->max_packet_bytes > shi->max_packet_bytes)
1736                           bhi->max_packet_bytes = shi->max_packet_bytes;
1737                       }
1738                   }
1739               }
1740           }
1741         /* *INDENT-ON* */
1742       }
1743   }
1744
1745   while (1)
1746     {
1747       /*
1748        * check each time through the loop in case intervals are changed
1749        */
1750       f64 min_wait = dm->link_state_poll_interval < dm->stat_poll_interval ?
1751         dm->link_state_poll_interval : dm->stat_poll_interval;
1752
1753       vlib_process_wait_for_event_or_clock (vm, min_wait);
1754
1755       if (dm->admin_up_down_in_progress)
1756         /* skip the poll if an admin up down is in progress (on any interface) */
1757         continue;
1758
1759       vec_foreach (xd, dm->devices)
1760       {
1761         f64 now = vlib_time_now (vm);
1762         if ((now - xd->time_last_stats_update) >= dm->stat_poll_interval)
1763           dpdk_update_counters (xd, now);
1764         if ((now - xd->time_last_link_update) >= dm->link_state_poll_interval)
1765           dpdk_update_link_state (xd, now);
1766
1767       }
1768     }
1769
1770   return 0;
1771 }
1772
1773 /* *INDENT-OFF* */
1774 VLIB_REGISTER_NODE (dpdk_process_node,static) = {
1775     .function = dpdk_process,
1776     .type = VLIB_NODE_TYPE_PROCESS,
1777     .name = "dpdk-process",
1778     .process_log2_n_stack_bytes = 17,
1779 };
1780 /* *INDENT-ON* */
1781
1782 static clib_error_t *
1783 dpdk_init (vlib_main_t * vm)
1784 {
1785   dpdk_main_t *dm = &dpdk_main;
1786   clib_error_t *error = 0;
1787
1788   /* verify that structs are cacheline aligned */
1789   STATIC_ASSERT (offsetof (dpdk_device_t, cacheline0) == 0,
1790                  "Cache line marker must be 1st element in dpdk_device_t");
1791   STATIC_ASSERT (offsetof (dpdk_device_t, cacheline1) ==
1792                  CLIB_CACHE_LINE_BYTES,
1793                  "Data in cache line 0 is bigger than cache line size");
1794   STATIC_ASSERT (offsetof (frame_queue_trace_t, cacheline0) == 0,
1795                  "Cache line marker must be 1st element in frame_queue_trace_t");
1796   STATIC_ASSERT (RTE_CACHE_LINE_SIZE == 1 << CLIB_LOG2_CACHE_LINE_BYTES,
1797                  "DPDK RTE CACHE LINE SIZE does not match with 1<<CLIB_LOG2_CACHE_LINE_BYTES");
1798
1799   dm->vlib_main = vm;
1800   dm->vnet_main = vnet_get_main ();
1801   dm->conf = &dpdk_config_main;
1802
1803   dm->conf->nchannels = 4;
1804   dm->conf->num_mbufs = dm->conf->num_mbufs ? dm->conf->num_mbufs : NB_MBUF;
1805   vec_add1 (dm->conf->eal_init_args, (u8 *) "vnet");
1806
1807   /* Default vlib_buffer_t flags, DISABLES tcp/udp checksumming... */
1808   dm->buffer_flags_template =
1809     (VLIB_BUFFER_TOTAL_LENGTH_VALID | VLIB_BUFFER_EXT_HDR_VALID
1810      | VNET_BUFFER_F_L4_CHECKSUM_COMPUTED |
1811      VNET_BUFFER_F_L4_CHECKSUM_CORRECT | VNET_BUFFER_F_L2_HDR_OFFSET_VALID);
1812
1813   dm->stat_poll_interval = DPDK_STATS_POLL_INTERVAL;
1814   dm->link_state_poll_interval = DPDK_LINK_POLL_INTERVAL;
1815
1816   /* init CLI */
1817   if ((error = vlib_call_init_function (vm, dpdk_cli_init)))
1818     return error;
1819
1820   dm->log_default = vlib_log_register_class ("dpdk", 0);
1821
1822   return error;
1823 }
1824
1825 VLIB_INIT_FUNCTION (dpdk_init);
1826
1827
1828 /*
1829  * fd.io coding-style-patch-verification: ON
1830  *
1831  * Local Variables:
1832  * eval: (c-set-style "gnu")
1833  * End:
1834  */