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