X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fplugins%2Fdpdk%2Fdevice%2Fcommon.c;h=a837714e75b3ecd7f8da1e13463702c43daa6956;hb=19ff0c369;hp=11b0538fc462ecdecee521bb6ce7c3b29a77334e;hpb=048acfbd9ee6c0d476ffd87db9c1c744f3040e25;p=vpp.git diff --git a/src/plugins/dpdk/device/common.c b/src/plugins/dpdk/device/common.c index 11b0538fc46..a837714e75b 100644 --- a/src/plugins/dpdk/device/common.c +++ b/src/plugins/dpdk/device/common.c @@ -16,12 +16,14 @@ #include #include #include -#include +#include +#include #include #include #include #include +#include #include #include #include @@ -42,6 +44,7 @@ dpdk_device_setup (dpdk_device_t * xd) dpdk_main_t *dm = &dpdk_main; vlib_main_t *vm = vlib_get_main (); vnet_main_t *vnm = vnet_get_main (); + vlib_thread_main_t *tm = vlib_get_thread_main (); vnet_sw_interface_t *sw = vnet_get_sw_interface (vnm, xd->sw_if_index); vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, xd->hw_if_index); struct rte_eth_dev_info dev_info; @@ -96,7 +99,8 @@ dpdk_device_setup (dpdk_device_t * xd) goto error; } - /* Set up one TX-queue per worker thread */ + vec_validate_aligned (xd->tx_queues, xd->tx_q_used - 1, + CLIB_CACHE_LINE_BYTES); for (j = 0; j < xd->tx_q_used; j++) { rv = @@ -111,17 +115,18 @@ dpdk_device_setup (dpdk_device_t * xd) &xd->tx_conf); if (rv < 0) dpdk_device_error (xd, "rte_eth_tx_queue_setup", rv); + + if (xd->tx_q_used < tm->n_vlib_mains) + clib_spinlock_init (&vec_elt (xd->tx_queues, j).lock); } - vec_validate_aligned (xd->buffer_pool_for_queue, xd->rx_q_used - 1, + vec_validate_aligned (xd->rx_queues, xd->rx_q_used - 1, CLIB_CACHE_LINE_BYTES); for (j = 0; j < xd->rx_q_used; j++) { - uword tidx = vnet_get_device_input_thread_index (dm->vnet_main, - xd->hw_if_index, j); - unsigned lcore = vlib_worker_threads[tidx].cpu_id; - u16 socket_id = rte_lcore_to_socket_id (lcore); - u8 bpidx = vlib_buffer_pool_get_default_for_numa (vm, socket_id); + dpdk_rx_queue_t *rxq = vec_elt_at_index (xd->rx_queues, j); + u8 bpidx = vlib_buffer_pool_get_default_for_numa ( + vm, vnet_hw_if_get_rx_queue_numa_node (vnm, rxq->queue_index)); vlib_buffer_pool_t *bp = vlib_get_buffer_pool (vm, bpidx); struct rte_mempool *mp = dpdk_mempool_by_buffer_pool_index[bpidx]; @@ -133,7 +138,7 @@ dpdk_device_setup (dpdk_device_t * xd) rv = rte_eth_rx_queue_setup (xd->port_id, j, xd->nb_rx_desc, SOCKET_ID_ANY, 0, mp); - xd->buffer_pool_for_queue[j] = bp->index; + rxq->buffer_pool_index = bp->index; if (rv < 0) dpdk_device_error (xd, "rte_eth_rx_queue_setup", rv); @@ -157,6 +162,79 @@ error: sw->flags |= VNET_SW_INTERFACE_FLAG_ERROR; } +static clib_error_t * +dpdk_rx_read_ready (clib_file_t *uf) +{ + vnet_main_t *vnm = vnet_get_main (); + dpdk_main_t *dm = &dpdk_main; + u32 qidx = uf->private_data; + vnet_hw_if_rx_queue_t *rxq = vnet_hw_if_get_rx_queue (vnm, qidx); + dpdk_device_t *xd = vec_elt_at_index (dm->devices, rxq->dev_instance); + + u64 b; + CLIB_UNUSED (ssize_t size) = read (uf->file_descriptor, &b, sizeof (b)); + if (rxq->mode != VNET_HW_IF_RX_MODE_POLLING) + { + vnet_hw_if_rx_queue_set_int_pending (vnm, uf->private_data); + rte_eth_dev_rx_intr_enable (xd->port_id, rxq->queue_id); + } + + return 0; +} + +static void +dpdk_setup_interrupts (dpdk_device_t *xd) +{ + vnet_main_t *vnm = vnet_get_main (); + vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, xd->hw_if_index); + if (!hi) + return; + + if (!xd->port_conf.intr_conf.rxq) + return; + + /* Probe for interrupt support */ + if (rte_eth_dev_rx_intr_enable (xd->port_id, 0)) + { + dpdk_log_info ("probe for interrupt mode for device %U. Failed.\n", + format_dpdk_device_name, xd->port_id); + } + else + { + xd->flags |= DPDK_DEVICE_FLAG_INT_SUPPORTED; + rte_eth_dev_rx_intr_disable (xd->port_id, 0); + dpdk_log_info ("Probe for interrupt mode for device %U. Success.\n", + format_dpdk_device_name, xd->port_id); + } + + if (xd->flags & DPDK_DEVICE_FLAG_INT_SUPPORTED) + { + hi->flags |= VNET_HW_INTERFACE_FLAG_SUPPORTS_INT_MODE; + for (int q = 0; q < xd->rx_q_used; q++) + { + dpdk_rx_queue_t *rxq = vec_elt_at_index (xd->rx_queues, q); + clib_file_t f = { 0 }; + rxq->efd = rte_eth_dev_rx_intr_ctl_q_get_fd (xd->port_id, q); + if (rxq->efd < 0) + { + xd->flags &= ~DPDK_DEVICE_FLAG_INT_SUPPORTED; + hi->flags &= ~VNET_HW_INTERFACE_FLAG_SUPPORTS_INT_MODE; + break; + } + f.read_function = dpdk_rx_read_ready; + f.flags = UNIX_FILE_EVENT_EDGE_TRIGGERED; + f.file_descriptor = rxq->efd; + f.private_data = rxq->queue_index; + f.description = + format (0, "%U queue %u", format_dpdk_device_name, xd->port_id, q); + rxq->clib_file_index = clib_file_add (&file_main, &f); + vnet_hw_if_set_rx_queue_file_index (vnm, rxq->queue_index, + rxq->clib_file_index); + } + } + vnet_hw_if_update_runtime_data (vnm, xd->hw_if_index); +} + void dpdk_device_start (dpdk_device_t * xd) { @@ -173,11 +251,11 @@ dpdk_device_start (dpdk_device_t * xd) return; } + dpdk_setup_interrupts (xd); + if (xd->default_mac_address) - rv = - rte_eth_dev_default_mac_addr_set (xd->port_id, - (struct ether_addr *) - xd->default_mac_address); + rv = rte_eth_dev_default_mac_addr_set (xd->port_id, + (void *) xd->default_mac_address); if (rv) dpdk_device_error (xd, "rte_eth_dev_default_mac_addr_set", rv); @@ -257,6 +335,19 @@ dpdk_get_pci_device (const struct rte_eth_dev_info *info) return NULL; } +/* If this device is VMBUS return pointer to info, otherwise NULL */ +struct rte_vmbus_device * +dpdk_get_vmbus_device (const struct rte_eth_dev_info *info) +{ + const struct rte_bus *bus; + + bus = rte_bus_find_by_device (info->device); + if (bus && !strcmp (bus->name, "vmbus")) + return container_of (info->device, struct rte_vmbus_device, device); + else + return NULL; +} + /* * fd.io coding-style-patch-verification: ON *