#include <vlib/unix/unix.h>
#include <vlib/log.h>
+#include <vnet/vnet.h>
#include <vnet/ethernet/ethernet.h>
+#include <vnet/interface/rx_queue_funcs.h>
+#include <vnet/interface/tx_queue_funcs.h>
+#include <dpdk/buffer.h>
#include <dpdk/device/dpdk.h>
+#include <dpdk/cryptodev/cryptodev.h>
#include <vlib/pci/pci.h>
+#include <vlib/vmbus/vmbus.h>
#include <rte_ring.h>
+#include <rte_vect.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mount.h>
#include <string.h>
#include <fcntl.h>
+#include <dirent.h>
#include <dpdk/device/dpdk_priv.h>
-#define ETHER_MAX_LEN 1518 /**< Maximum frame len, including CRC. */
-
dpdk_main_t dpdk_main;
dpdk_config_main_t dpdk_config_main;
#define LINK_STATE_ELOGS 0
-/* Port configuration, mildly modified Intel app values */
-
-static struct rte_eth_conf port_conf_template = {
- .rxmode = {
- .split_hdr_size = 0,
- .header_split = 0, /**< Header Split disabled */
- .hw_ip_checksum = 0, /**< IP checksum offload disabled */
- .hw_vlan_filter = 0, /**< VLAN filtering disabled */
- .hw_strip_crc = 0, /**< CRC stripped by hardware */
- },
- .txmode = {
- .mq_mode = ETH_MQ_TX_NONE,
- },
+/* dev_info.speed_capa -> interface name mapppings */
+const struct
+{
+ u32 link_speed;
+ const char *pfx;
+} if_name_prefixes[] = {
+ /* sorted, higher speed first */
+ { RTE_ETH_LINK_SPEED_200G, "TwoHundredGigabitEthernet" },
+ { RTE_ETH_LINK_SPEED_100G, "HundredGigabitEthernet" },
+ { RTE_ETH_LINK_SPEED_56G, "FiftySixGigabitEthernet" },
+ { RTE_ETH_LINK_SPEED_50G, "FiftyGigabitEthernet" },
+ { RTE_ETH_LINK_SPEED_40G, "FortyGigabitEthernet" },
+ { RTE_ETH_LINK_SPEED_25G, "TwentyFiveGigabitEthernet" },
+ { RTE_ETH_LINK_SPEED_20G, "TwentyGigabitEthernet" },
+ { RTE_ETH_LINK_SPEED_10G, "TenGigabitEthernet" },
+ { RTE_ETH_LINK_SPEED_5G, "FiveGigabitEthernet" },
+ { RTE_ETH_LINK_SPEED_2_5G, "TwoDotFiveGigabitEthernet" },
+ { RTE_ETH_LINK_SPEED_1G, "GigabitEthernet" },
};
-static dpdk_port_type_t
-port_type_from_speed_capa (struct rte_eth_dev_info *dev_info)
+static clib_error_t *
+dpdk_set_max_frame_size (vnet_main_t *vnm, vnet_hw_interface_t *hi,
+ u32 frame_size)
{
+ dpdk_main_t *dm = &dpdk_main;
+ dpdk_device_t *xd = vec_elt_at_index (dm->devices, hi->dev_instance);
+ int rv;
+ u32 mtu;
- if (dev_info->speed_capa & ETH_LINK_SPEED_100G)
- return VNET_DPDK_PORT_TYPE_ETH_100G;
- else if (dev_info->speed_capa & ETH_LINK_SPEED_56G)
- return VNET_DPDK_PORT_TYPE_ETH_56G;
- else if (dev_info->speed_capa & ETH_LINK_SPEED_50G)
- return VNET_DPDK_PORT_TYPE_ETH_50G;
- else if (dev_info->speed_capa & ETH_LINK_SPEED_40G)
- return VNET_DPDK_PORT_TYPE_ETH_40G;
- else if (dev_info->speed_capa & ETH_LINK_SPEED_25G)
- return VNET_DPDK_PORT_TYPE_ETH_25G;
- else if (dev_info->speed_capa & ETH_LINK_SPEED_20G)
- return VNET_DPDK_PORT_TYPE_ETH_20G;
- else if (dev_info->speed_capa & ETH_LINK_SPEED_10G)
- return VNET_DPDK_PORT_TYPE_ETH_10G;
- else if (dev_info->speed_capa & ETH_LINK_SPEED_5G)
- return VNET_DPDK_PORT_TYPE_ETH_5G;
- else if (dev_info->speed_capa & ETH_LINK_SPEED_2_5G)
- return VNET_DPDK_PORT_TYPE_ETH_2_5G;
- else if (dev_info->speed_capa & ETH_LINK_SPEED_1G)
- return VNET_DPDK_PORT_TYPE_ETH_1G;
-
- return VNET_DPDK_PORT_TYPE_UNKNOWN;
-}
+ mtu = frame_size - xd->driver_frame_overhead;
+ rv = rte_eth_dev_set_mtu (xd->port_id, mtu);
+
+ if (rv < 0)
+ {
+ dpdk_log_err ("[%u] rte_eth_dev_set_mtu failed (mtu %u, rv %d)",
+ xd->port_id, mtu, rv);
+ switch (rv)
+ {
+ case -ENOTSUP:
+ return vnet_error (VNET_ERR_UNSUPPORTED,
+ "dpdk driver doesn't support MTU change");
+ case -EBUSY:
+ return vnet_error (VNET_ERR_BUSY, "port is running");
+ case -EINVAL:
+ return vnet_error (VNET_ERR_INVALID_VALUE, "invalid MTU");
+ default:
+ return vnet_error (VNET_ERR_BUG,
+ "unexpected return value %d returned from "
+ "rte_eth_dev_set_mtu(...)",
+ rv);
+ }
+ }
+ else
+ dpdk_log_debug ("[%u] max_frame_size set to %u by setting MTU to %u",
+ xd->port_id, frame_size, mtu);
+
+ return 0;
+}
static u32
dpdk_flag_change (vnet_main_t * vnm, vnet_hw_interface_t * hi, u32 flags)
{
dpdk_main_t *dm = &dpdk_main;
dpdk_device_t *xd = vec_elt_at_index (dm->devices, hi->dev_instance);
- u32 old = 0;
+ u32 old = (xd->flags & DPDK_DEVICE_FLAG_PROMISC) != 0;
- if (ETHERNET_INTERFACE_FLAG_CONFIG_PROMISC (flags))
+ switch (flags)
{
- old = (xd->flags & DPDK_DEVICE_FLAG_PROMISC) != 0;
-
- if (flags & ETHERNET_INTERFACE_FLAG_ACCEPT_ALL)
- xd->flags |= DPDK_DEVICE_FLAG_PROMISC;
- else
- xd->flags &= ~DPDK_DEVICE_FLAG_PROMISC;
-
- if (xd->flags & DPDK_DEVICE_FLAG_ADMIN_UP)
- {
- if (xd->flags & DPDK_DEVICE_FLAG_PROMISC)
- rte_eth_promiscuous_enable (xd->port_id);
- else
- rte_eth_promiscuous_disable (xd->port_id);
- }
+ case ETHERNET_INTERFACE_FLAG_DEFAULT_L3:
+ /* set to L3/non-promisc mode */
+ dpdk_device_flag_set (xd, DPDK_DEVICE_FLAG_PROMISC, 0);
+ break;
+ case ETHERNET_INTERFACE_FLAG_ACCEPT_ALL:
+ dpdk_device_flag_set (xd, DPDK_DEVICE_FLAG_PROMISC, 1);
+ break;
+ default:
+ return ~0;
}
- else if (ETHERNET_INTERFACE_FLAG_CONFIG_MTU (flags))
+
+ if (xd->flags & DPDK_DEVICE_FLAG_ADMIN_UP)
{
- xd->port_conf.rxmode.max_rx_pkt_len = hi->max_packet_bytes;
- dpdk_device_setup (xd);
+ if (xd->flags & DPDK_DEVICE_FLAG_PROMISC)
+ rte_eth_promiscuous_enable (xd->port_id);
+ else
+ rte_eth_promiscuous_disable (xd->port_id);
}
+
return old;
}
-static void
-dpdk_device_lock_init (dpdk_device_t * xd)
+/* The function check_l3cache helps check if Level 3 cache exists or not on current CPUs
+ return value 1: exist.
+ return value 0: not exist.
+*/
+static int
+check_l3cache ()
{
- int q;
- vec_validate (xd->lockp, xd->tx_q_used - 1);
- for (q = 0; q < xd->tx_q_used; q++)
- {
- xd->lockp[q] = clib_mem_alloc_aligned (CLIB_CACHE_LINE_BYTES,
- CLIB_CACHE_LINE_BYTES);
- memset ((void *) xd->lockp[q], 0, CLIB_CACHE_LINE_BYTES);
- }
-}
-static struct rte_mempool_ops *
-get_ops_by_name (char *ops_name)
-{
- u32 i;
+ struct dirent *dp;
+ clib_error_t *err;
+ const char *sys_cache_dir = "/sys/devices/system/cpu/cpu0/cache";
+ DIR *dir_cache = opendir (sys_cache_dir);
- for (i = 0; i < rte_mempool_ops_table.num_ops; i++)
+ if (dir_cache == NULL)
+ return -1;
+
+ while ((dp = readdir (dir_cache)) != NULL)
{
- if (!strcmp (ops_name, rte_mempool_ops_table.ops[i].name))
- return &rte_mempool_ops_table.ops[i];
+ if (dp->d_type == DT_DIR)
+ {
+ u8 *p = NULL;
+ int level_cache = -1;
+
+ p = format (p, "%s/%s/%s%c", sys_cache_dir, dp->d_name, "level", 0);
+ if ((err = clib_sysfs_read ((char *) p, "%d", &level_cache)))
+ clib_error_free (err);
+
+ if (level_cache == 3)
+ {
+ closedir (dir_cache);
+ return 1;
+ }
+ }
}
+ if (dir_cache != NULL)
+ closedir (dir_cache);
+
return 0;
}
-static int
-dpdk_ring_alloc (struct rte_mempool *mp)
+static dpdk_device_config_t *
+dpdk_find_startup_config (struct rte_eth_dev_info *di)
{
- u32 rg_flags = 0, count;
- i32 ret;
- char rg_name[RTE_RING_NAMESIZE];
- struct rte_ring *r;
-
- ret = snprintf (rg_name, sizeof (rg_name), RTE_MEMPOOL_MZ_FORMAT, mp->name);
- if (ret < 0 || ret >= (i32) sizeof (rg_name))
- return -ENAMETOOLONG;
-
- /* ring flags */
- if (mp->flags & MEMPOOL_F_SP_PUT)
- rg_flags |= RING_F_SP_ENQ;
- if (mp->flags & MEMPOOL_F_SC_GET)
- rg_flags |= RING_F_SC_DEQ;
-
- count = rte_align32pow2 (mp->size + 1);
- /*
- * Allocate the ring that will be used to store objects.
- * Ring functions will return appropriate errors if we are
- * running as a secondary process etc., so no checks made
- * in this function for that condition.
- */
- /* XXX can we get memory from the right socket? */
- r = clib_mem_alloc_aligned (rte_ring_get_memsize (count),
- CLIB_CACHE_LINE_BYTES);
-
- /* XXX rte_ring_lookup will not work */
-
- ret = rte_ring_init (r, rg_name, count, rg_flags);
- if (ret)
- return ret;
-
- mp->pool_data = r;
+ dpdk_main_t *dm = &dpdk_main;
+ struct rte_pci_device *pci_dev;
+ struct rte_vmbus_device *vmbus_dev;
+ vlib_pci_addr_t pci_addr;
+ vlib_vmbus_addr_t vmbus_addr;
+ uword *p = 0;
- return 0;
+ if ((pci_dev = dpdk_get_pci_device (di)))
+ {
+ pci_addr.domain = pci_dev->addr.domain;
+ pci_addr.bus = pci_dev->addr.bus;
+ pci_addr.slot = pci_dev->addr.devid;
+ pci_addr.function = pci_dev->addr.function;
+ p =
+ hash_get (dm->conf->device_config_index_by_pci_addr, pci_addr.as_u32);
+ }
+
+ if ((vmbus_dev = dpdk_get_vmbus_device (di)))
+ {
+ unformat_input_t input_vmbus;
+#if RTE_VERSION >= RTE_VERSION_NUM(22, 11, 0, 0)
+ const char *dev_name = rte_dev_name (di->device);
+#else
+ const char *dev_name = di->device->name;
+#endif
+ unformat_init_string (&input_vmbus, dev_name, strlen (dev_name));
+ if (unformat (&input_vmbus, "%U", unformat_vlib_vmbus_addr, &vmbus_addr))
+ p = mhash_get (&dm->conf->device_config_index_by_vmbus_addr,
+ &vmbus_addr);
+ unformat_free (&input_vmbus);
+ }
+
+ if (p)
+ return pool_elt_at_index (dm->conf->dev_confs, p[0]);
+ return &dm->conf->default_devconf;
}
static clib_error_t *
dpdk_lib_init (dpdk_main_t * dm)
{
- u32 nports;
- u32 mtu, max_rx_frame;
- u32 nb_desc = 0;
- int i;
- clib_error_t *error;
- vlib_main_t *vm = vlib_get_main ();
+ vnet_main_t *vnm = vnet_get_main ();
+ u16 port_id;
vlib_thread_main_t *tm = vlib_get_thread_main ();
vnet_device_main_t *vdm = &vnet_device_main;
vnet_sw_interface_t *sw;
vnet_hw_interface_t *hi;
dpdk_device_t *xd;
- vlib_pci_addr_t last_pci_addr;
- u32 last_pci_addr_port = 0;
- vlib_thread_registration_t *tr_hqos;
- uword *p_hqos;
-
- u32 next_hqos_cpu = 0;
- u8 af_packet_instance_num = 0;
- u8 bond_ether_instance_num = 0;
- last_pci_addr.as_u32 = ~0;
-
- dm->hqos_cpu_first_index = 0;
- dm->hqos_cpu_count = 0;
-
- /* find out which cpus will be used for I/O TX */
- p_hqos = hash_get_mem (tm->thread_registrations_by_name, "hqos-threads");
- tr_hqos = p_hqos ? (vlib_thread_registration_t *) p_hqos[0] : 0;
-
- if (tr_hqos && tr_hqos->count > 0)
- {
- dm->hqos_cpu_first_index = tr_hqos->first_index;
- dm->hqos_cpu_count = tr_hqos->count;
- }
-
- vec_validate_aligned (dm->devices_by_hqos_cpu, tm->n_vlib_mains - 1,
- CLIB_CACHE_LINE_BYTES);
-
-#if RTE_VERSION < RTE_VERSION_NUM(18, 5, 0, 0)
- nports = rte_eth_dev_count ();
-#else
- nports = rte_eth_dev_count_avail ();
-#endif
-
- if (nports < 1)
- {
- dpdk_log_notice ("DPDK drivers found no ports...");
- }
-
- if (CLIB_DEBUG > 0)
- dpdk_log_notice ("DPDK drivers found %d ports...", nports);
-
- if (dm->conf->enable_tcp_udp_checksum)
- dm->buffer_flags_template &= ~(VNET_BUFFER_F_L4_CHECKSUM_CORRECT
- | VNET_BUFFER_F_L4_CHECKSUM_COMPUTED);
+ char *if_num_fmt;
/* vlib_buffer_t template */
vec_validate_aligned (dm->per_thread_data, tm->n_vlib_mains - 1,
CLIB_CACHE_LINE_BYTES);
- for (i = 0; i < tm->n_vlib_mains; i++)
+ for (int i = 0; i < tm->n_vlib_mains; i++)
{
- vlib_buffer_free_list_t *fl;
dpdk_per_thread_data_t *ptd = vec_elt_at_index (dm->per_thread_data, i);
- fl = vlib_buffer_get_free_list (vm,
- VLIB_BUFFER_DEFAULT_FREE_LIST_INDEX);
- vlib_buffer_init_for_free_list (&ptd->buffer_template, fl);
- ptd->buffer_template.flags = dm->buffer_flags_template;
+ clib_memset (&ptd->buffer_template, 0, sizeof (vlib_buffer_t));
vnet_buffer (&ptd->buffer_template)->sw_if_index[VLIB_TX] = (u32) ~ 0;
}
- /* *INDENT-OFF* */
- RTE_ETH_FOREACH_DEV(i)
+ if_num_fmt =
+ dm->conf->interface_name_format_decimal ? "%d/%d/%d" : "%x/%x/%x";
+
+ /* device config defaults */
+ dm->default_port_conf.n_rx_desc = DPDK_NB_RX_DESC_DEFAULT;
+ dm->default_port_conf.n_tx_desc = DPDK_NB_TX_DESC_DEFAULT;
+ dm->default_port_conf.n_rx_queues = 1;
+ dm->default_port_conf.n_tx_queues = tm->n_vlib_mains;
+ dm->default_port_conf.rss_hf =
+ RTE_ETH_RSS_IP | RTE_ETH_RSS_UDP | RTE_ETH_RSS_TCP;
+ dm->default_port_conf.max_lro_pkt_size = DPDK_MAX_LRO_SIZE_DEFAULT;
+
+ if ((clib_mem_get_default_hugepage_size () == 2 << 20) &&
+ check_l3cache () == 0)
+ dm->default_port_conf.n_rx_desc = dm->default_port_conf.n_tx_desc = 512;
+
+ RTE_ETH_FOREACH_DEV (port_id)
{
u8 addr[6];
- u8 vlan_strip = 0;
- struct rte_eth_dev_info dev_info;
- struct rte_pci_device *pci_dev;
- struct rte_eth_link l;
+ int rv, q;
+ struct rte_eth_dev_info di;
dpdk_device_config_t *devconf = 0;
- vlib_pci_addr_t pci_addr;
- uword *p = 0;
+ vnet_eth_interface_registration_t eir = {};
+ dpdk_driver_t *dr;
+ i8 numa_node;
- if (!rte_eth_dev_is_valid_port(i))
+ if (!rte_eth_dev_is_valid_port (port_id))
continue;
- rte_eth_link_get_nowait (i, &l);
- rte_eth_dev_info_get (i, &dev_info);
-
-#if RTE_VERSION < RTE_VERSION_NUM(18, 5, 0, 0)
- pci_dev = dev_info.pci_dev;
-#else
- if (dev_info.device == 0)
+ if ((rv = rte_eth_dev_info_get (port_id, &di)) != 0)
{
- clib_warning ("DPDK bug: missing device info. Skipping %s device",
- dev_info.driver_name);
+ dpdk_log_warn ("[%u] failed to get device info. skipping device.",
+ port_id);
continue;
}
- pci_dev = RTE_DEV_TO_PCI (dev_info.device);
-#endif
- if (pci_dev) /* bonded interface has no pci info */
+ if (di.device == 0)
{
- pci_addr.domain = pci_dev->addr.domain;
- pci_addr.bus = pci_dev->addr.bus;
- pci_addr.slot = pci_dev->addr.devid;
- pci_addr.function = pci_dev->addr.function;
- p =
- hash_get (dm->conf->device_config_index_by_pci_addr,
- pci_addr.as_u32);
- }
-
- if (p)
- devconf = pool_elt_at_index (dm->conf->dev_confs, p[0]);
- else
- devconf = &dm->conf->default_devconf;
-
- /* Create vnet interface */
- vec_add2_aligned (dm->devices, xd, 1, CLIB_CACHE_LINE_BYTES);
- xd->nb_rx_desc = DPDK_NB_RX_DESC_DEFAULT;
- xd->nb_tx_desc = DPDK_NB_TX_DESC_DEFAULT;
- xd->cpu_socket = (i8) rte_eth_dev_socket_id (i);
-
- /* Handle interface naming for devices with multiple ports sharing same PCI ID */
- if (pci_dev)
- {
- struct rte_eth_dev_info di = { 0 };
- struct rte_pci_device *next_pci_dev;
- rte_eth_dev_info_get (i + 1, &di);
-#if RTE_VERSION < RTE_VERSION_NUM(18, 5, 0, 0)
- next_pci_dev = di.pci_dev;
-#else
- next_pci_dev = di.device ? RTE_DEV_TO_PCI (di.device) : 0;
-#endif
- if (pci_dev && next_pci_dev &&
- pci_addr.as_u32 != last_pci_addr.as_u32 &&
- memcmp (&pci_dev->addr, &next_pci_dev->addr,
- sizeof (struct rte_pci_addr)) == 0)
- {
- xd->interface_name_suffix = format (0, "0");
- last_pci_addr.as_u32 = pci_addr.as_u32;
- last_pci_addr_port = i;
- }
- else if (pci_addr.as_u32 == last_pci_addr.as_u32)
- {
- xd->interface_name_suffix =
- format (0, "%u", i - last_pci_addr_port);
- }
- else
- {
- last_pci_addr.as_u32 = ~0;
- }
+ dpdk_log_warn ("[%u] missing device info. Skipping '%s' device",
+ port_id, di.driver_name);
+ continue;
}
- else
- last_pci_addr.as_u32 = ~0;
- clib_memcpy (&xd->tx_conf, &dev_info.default_txconf,
- sizeof (struct rte_eth_txconf));
+ devconf = dpdk_find_startup_config (&di);
- if (dm->conf->no_multi_seg)
+ /* If device is blacklisted, we should skip it */
+ if (devconf->is_blacklisted)
{
- xd->tx_conf.txq_flags |= ETH_TXQ_FLAGS_NOMULTSEGS;
- port_conf_template.rxmode.jumbo_frame = 0;
- port_conf_template.rxmode.enable_scatter = 0;
- }
- else
- {
- xd->tx_conf.txq_flags &= ~ETH_TXQ_FLAGS_NOMULTSEGS;
- port_conf_template.rxmode.jumbo_frame = 1;
- port_conf_template.rxmode.enable_scatter = 1;
- xd->flags |= DPDK_DEVICE_FLAG_MAYBE_MULTISEG;
+ dpdk_log_notice ("[%d] Device %s blacklisted. Skipping...", port_id,
+ di.driver_name);
+ continue;
}
- clib_memcpy (&xd->port_conf, &port_conf_template,
- sizeof (struct rte_eth_conf));
-
- xd->tx_q_used = clib_min (dev_info.max_tx_queues, tm->n_vlib_mains);
+ vec_add2_aligned (dm->devices, xd, 1, CLIB_CACHE_LINE_BYTES);
+ xd->port_id = port_id;
+ xd->device_index = xd - dm->devices;
+ xd->per_interface_next_index = ~0;
- if (devconf->num_tx_queues > 0
- && devconf->num_tx_queues < xd->tx_q_used)
- xd->tx_q_used = clib_min (xd->tx_q_used, devconf->num_tx_queues);
+ clib_memcpy (&xd->conf, &dm->default_port_conf,
+ sizeof (dpdk_port_conf_t));
- if (devconf->num_rx_queues > 1
- && dev_info.max_rx_queues >= devconf->num_rx_queues)
+ /* find driver datea for this PMD */
+ if ((dr = dpdk_driver_find (di.driver_name, &xd->if_desc)))
{
- xd->rx_q_used = devconf->num_rx_queues;
- xd->port_conf.rxmode.mq_mode = ETH_MQ_RX_RSS;
- if (devconf->rss_fn == 0)
- xd->port_conf.rx_adv_conf.rss_conf.rss_hf =
- ETH_RSS_IP | ETH_RSS_UDP | ETH_RSS_TCP;
- else
- xd->port_conf.rx_adv_conf.rss_conf.rss_hf = devconf->rss_fn;
+ xd->driver = dr;
+ xd->supported_flow_actions = dr->supported_flow_actions;
+ xd->conf.disable_rss = dr->mq_mode_none;
+ xd->conf.disable_rx_scatter = dr->disable_rx_scatter;
+ xd->conf.enable_rxq_int = dr->enable_rxq_int;
+ if (dr->use_intel_phdr_cksum)
+ dpdk_device_flag_set (xd, DPDK_DEVICE_FLAG_INTEL_PHDR_CKSUM, 1);
+ if (dr->int_unmaskable)
+ dpdk_device_flag_set (xd, DPDK_DEVICE_FLAG_INT_UNMASKABLE, 1);
}
else
- xd->rx_q_used = 1;
-
- xd->flags |= DPDK_DEVICE_FLAG_PMD;
-
- /* workaround for drivers not setting driver_name */
- if ((!dev_info.driver_name) && (pci_dev))
- dev_info.driver_name = pci_dev->driver->driver.name;
-
- ASSERT (dev_info.driver_name);
-
- if (!xd->pmd)
- {
-
-
-#define _(s,f) else if (dev_info.driver_name && \
- !strcmp(dev_info.driver_name, s)) \
- xd->pmd = VNET_DPDK_PMD_##f;
- if (0)
- ;
- foreach_dpdk_pmd
-#undef _
- else
- xd->pmd = VNET_DPDK_PMD_UNKNOWN;
-
- xd->port_type = VNET_DPDK_PORT_TYPE_UNKNOWN;
- xd->nb_rx_desc = DPDK_NB_RX_DESC_DEFAULT;
- xd->nb_tx_desc = DPDK_NB_TX_DESC_DEFAULT;
-
- switch (xd->pmd)
- {
- /* Drivers with valid speed_capa set */
- case VNET_DPDK_PMD_E1000EM:
- case VNET_DPDK_PMD_IGB:
- case VNET_DPDK_PMD_IXGBE:
- case VNET_DPDK_PMD_I40E:
- xd->port_type = port_type_from_speed_capa (&dev_info);
- xd->supported_flow_actions = VNET_FLOW_ACTION_MARK |
- VNET_FLOW_ACTION_REDIRECT_TO_NODE |
- VNET_FLOW_ACTION_BUFFER_ADVANCE |
- VNET_FLOW_ACTION_COUNT | VNET_FLOW_ACTION_DROP;
-
- if (dm->conf->no_tx_checksum_offload == 0)
- {
- xd->tx_conf.txq_flags &= ~ETH_TXQ_FLAGS_NOXSUMS;
- xd->flags |=
- DPDK_DEVICE_FLAG_TX_OFFLOAD |
- DPDK_DEVICE_FLAG_INTEL_PHDR_CKSUM;
- }
-
-
- break;
- case VNET_DPDK_PMD_CXGBE:
- case VNET_DPDK_PMD_MLX4:
- case VNET_DPDK_PMD_MLX5:
- case VNET_DPDK_PMD_QEDE:
- xd->port_type = port_type_from_speed_capa (&dev_info);
- break;
-
- /* SR-IOV VFs */
- case VNET_DPDK_PMD_IGBVF:
- case VNET_DPDK_PMD_IXGBEVF:
- case VNET_DPDK_PMD_I40EVF:
- xd->port_type = VNET_DPDK_PORT_TYPE_ETH_VF;
- xd->port_conf.rxmode.hw_strip_crc = 1;
- break;
-
- case VNET_DPDK_PMD_THUNDERX:
- xd->port_type = VNET_DPDK_PORT_TYPE_ETH_VF;
- xd->port_conf.rxmode.hw_strip_crc = 1;
- break;
-
- case VNET_DPDK_PMD_ENA:
- xd->port_type = VNET_DPDK_PORT_TYPE_ETH_VF;
- xd->port_conf.rxmode.enable_scatter = 0;
- break;
-
- case VNET_DPDK_PMD_DPAA2:
- xd->port_type = VNET_DPDK_PORT_TYPE_ETH_10G;
- break;
-
- /* Cisco VIC */
- case VNET_DPDK_PMD_ENIC:
- if (l.link_speed == 40000)
- xd->port_type = VNET_DPDK_PORT_TYPE_ETH_40G;
- else
- xd->port_type = VNET_DPDK_PORT_TYPE_ETH_10G;
- break;
-
- /* Intel Red Rock Canyon */
- case VNET_DPDK_PMD_FM10K:
- xd->port_type = VNET_DPDK_PORT_TYPE_ETH_SWITCH;
- xd->port_conf.rxmode.hw_strip_crc = 1;
- break;
-
- /* virtio */
- case VNET_DPDK_PMD_VIRTIO:
- xd->port_type = VNET_DPDK_PORT_TYPE_ETH_1G;
- xd->nb_rx_desc = DPDK_NB_RX_DESC_VIRTIO;
- xd->nb_tx_desc = DPDK_NB_TX_DESC_VIRTIO;
- break;
-
- /* vmxnet3 */
- case VNET_DPDK_PMD_VMXNET3:
- xd->port_type = VNET_DPDK_PORT_TYPE_ETH_1G;
- xd->tx_conf.txq_flags |= ETH_TXQ_FLAGS_NOMULTSEGS;
- break;
-
- case VNET_DPDK_PMD_AF_PACKET:
- xd->port_type = VNET_DPDK_PORT_TYPE_AF_PACKET;
- xd->af_packet_instance_num = af_packet_instance_num++;
- break;
-
- case VNET_DPDK_PMD_BOND:
- xd->port_type = VNET_DPDK_PORT_TYPE_ETH_BOND;
- xd->bond_instance_num = bond_ether_instance_num++;
- break;
-
- case VNET_DPDK_PMD_VIRTIO_USER:
- xd->port_type = VNET_DPDK_PORT_TYPE_VIRTIO_USER;
- break;
-
- case VNET_DPDK_PMD_VHOST_ETHER:
- xd->port_type = VNET_DPDK_PORT_TYPE_VHOST_ETHER;
- break;
-
- case VNET_DPDK_PMD_LIOVF_ETHER:
- xd->port_type = VNET_DPDK_PORT_TYPE_ETH_VF;
- break;
-
- case VNET_DPDK_PMD_FAILSAFE:
- xd->port_type = VNET_DPDK_PORT_TYPE_FAILSAFE;
- xd->port_conf.intr_conf.lsc = 1;
- break;
-
- default:
- xd->port_type = VNET_DPDK_PORT_TYPE_UNKNOWN;
- }
-
- if (devconf->num_rx_desc)
- xd->nb_rx_desc = devconf->num_rx_desc;
-
- if (devconf->num_tx_desc)
- xd->nb_tx_desc = devconf->num_tx_desc;
- }
+ dpdk_log_warn ("[%u] unknown driver '%s'", port_id, di.driver_name);
- if (xd->pmd == VNET_DPDK_PMD_AF_PACKET)
+ if (devconf->name)
{
- f64 now = vlib_time_now (vm);
- u32 rnd;
- rnd = (u32) (now * 1e6);
- rnd = random_u32 (&rnd);
- clib_memcpy (addr + 2, &rnd, sizeof (rnd));
- addr[0] = 2;
- addr[1] = 0xfe;
+ xd->name = devconf->name;
}
else
- rte_eth_macaddr_get (i, (struct ether_addr *) addr);
-
- if (xd->tx_q_used < tm->n_vlib_mains)
- dpdk_device_lock_init (xd);
-
- xd->port_id = i;
- xd->device_index = xd - dm->devices;
- xd->per_interface_next_index = ~0;
-
- /* assign interface to input thread */
- int q;
-
- if (devconf->hqos_enabled)
{
- xd->flags |= DPDK_DEVICE_FLAG_HQOS;
-
- int cpu;
- if (devconf->hqos.hqos_thread_valid)
+ struct rte_pci_device *pci_dev;
+ if (dr && dr->interface_name_prefix)
{
- if (devconf->hqos.hqos_thread >= dm->hqos_cpu_count)
- return clib_error_return (0, "invalid HQoS thread index");
-
- cpu = dm->hqos_cpu_first_index + devconf->hqos.hqos_thread;
+ /* prefix override by driver */
+ xd->name = format (xd->name, "%s", dr->interface_name_prefix);
}
else
{
- if (dm->hqos_cpu_count == 0)
- return clib_error_return (0, "no HQoS threads available");
-
- cpu = dm->hqos_cpu_first_index + next_hqos_cpu;
+ /* interface name prefix from speed_capa */
+ u64 mask = ~((if_name_prefixes[0].link_speed << 1) - 1);
- next_hqos_cpu++;
- if (next_hqos_cpu == dm->hqos_cpu_count)
- next_hqos_cpu = 0;
+ if (di.speed_capa & mask)
+ dpdk_log_warn ("[%u] unknown speed capability 0x%x reported",
+ xd->port_id, di.speed_capa & mask);
- devconf->hqos.hqos_thread_valid = 1;
- devconf->hqos.hqos_thread = cpu;
+ for (int i = 0; i < ARRAY_LEN (if_name_prefixes); i++)
+ if (if_name_prefixes[i].link_speed & di.speed_capa)
+ {
+ xd->name =
+ format (xd->name, "%s", if_name_prefixes[i].pfx);
+ break;
+ }
+ if (xd->name == 0)
+ xd->name = format (xd->name, "Ethernet");
}
- dpdk_device_and_queue_t *dq;
- vec_add2 (dm->devices_by_hqos_cpu[cpu], dq, 1);
- dq->device = xd->device_index;
- dq->queue_id = 0;
+ if (dr && dr->interface_number_from_port_id)
+ xd->name = format (xd->name, "%u", port_id);
+ else if ((pci_dev = dpdk_get_pci_device (&di)))
+ xd->name = format (xd->name, if_num_fmt, pci_dev->addr.bus,
+ pci_dev->addr.devid, pci_dev->addr.function);
+ else
+ xd->name = format (xd->name, "%u", port_id);
}
- /* count the number of descriptors used for this device */
- nb_desc += xd->nb_rx_desc + xd->nb_tx_desc * xd->tx_q_used;
-
- error = ethernet_register_interface
- (dm->vnet_main, dpdk_device_class.index, xd->device_index,
- /* ethernet address */ addr,
- &xd->hw_if_index, dpdk_flag_change);
- if (error)
- return error;
+ /* Handle representor devices that share the same PCI ID */
+ if ((di.switch_info.domain_id != RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID) &&
+ (di.switch_info.port_id != (uint16_t) -1))
+ xd->name = format (xd->name, "/%d", di.switch_info.port_id);
- /*
- * Ensure default mtu is not > the mtu read from the hardware.
- * Otherwise rte_eth_dev_configure() will fail and the port will
- * not be available.
- * Calculate max_frame_size and mtu supported by NIC
- */
- if (ETHERNET_MAX_PACKET_BYTES > dev_info.max_rx_pktlen)
+ /* number of RX and TX queues */
+ if (devconf->num_tx_queues > 0)
{
- /*
- * This device does not support the platforms's max frame
- * size. Use it's advertised mru instead.
- */
- max_rx_frame = dev_info.max_rx_pktlen;
- mtu = dev_info.max_rx_pktlen - sizeof (ethernet_header_t);
+ if (di.max_tx_queues < devconf->num_tx_queues)
+ dpdk_log_warn ("[%u] Configured number of TX queues (%u) is "
+ "bigger than maximum supported (%u)",
+ port_id, devconf->num_tx_queues, di.max_tx_queues);
+ xd->conf.n_tx_queues = devconf->num_tx_queues;
}
- else
- {
- /* VPP treats MTU and max_rx_pktlen both equal to
- * ETHERNET_MAX_PACKET_BYTES, if dev_info.max_rx_pktlen >=
- * ETHERNET_MAX_PACKET_BYTES + sizeof(ethernet_header_t)
- */
- if (dev_info.max_rx_pktlen >= (ETHERNET_MAX_PACKET_BYTES +
- sizeof (ethernet_header_t)))
- {
- mtu = ETHERNET_MAX_PACKET_BYTES;
- max_rx_frame = ETHERNET_MAX_PACKET_BYTES;
-
- /*
- * Some platforms do not account for Ethernet FCS (4 bytes) in
- * MTU calculations. To interop with them increase mru but only
- * if the device's settings can support it.
- */
- if (xd->port_conf.rxmode.hw_strip_crc &&
- (dev_info.max_rx_pktlen >= (ETHERNET_MAX_PACKET_BYTES +
- sizeof (ethernet_header_t) +
- 4)))
- {
- max_rx_frame += 4;
- }
- }
- else
- {
- max_rx_frame = ETHERNET_MAX_PACKET_BYTES;
- mtu = ETHERNET_MAX_PACKET_BYTES - sizeof (ethernet_header_t);
- if (xd->port_conf.rxmode.hw_strip_crc &&
- (dev_info.max_rx_pktlen >= (ETHERNET_MAX_PACKET_BYTES + 4)))
- {
- max_rx_frame += 4;
- }
- }
- }
+ xd->conf.n_tx_queues = clib_min (di.max_tx_queues, xd->conf.n_tx_queues);
- if (xd->pmd == VNET_DPDK_PMD_FAILSAFE)
+ if (devconf->num_rx_queues > 1 &&
+ di.max_rx_queues >= devconf->num_rx_queues)
{
- /* failsafe device numerables are reported with active device only,
- * need to query the mtu for current device setup to overwrite
- * reported value.
- */
- uint16_t dev_mtu;
- if (!rte_eth_dev_get_mtu (i, &dev_mtu))
+ xd->conf.n_rx_queues = devconf->num_rx_queues;
+ if (devconf->rss_fn)
{
- mtu = dev_mtu;
- max_rx_frame = mtu + sizeof (ethernet_header_t);
-
- if (xd->port_conf.rxmode.hw_strip_crc)
- {
- max_rx_frame += 4;
- }
+ u64 unsupported_bits;
+ xd->conf.rss_hf = devconf->rss_fn;
+ unsupported_bits = xd->conf.rss_hf;
+ unsupported_bits &= ~di.flow_type_rss_offloads;
+ if (unsupported_bits)
+ dpdk_log_warn ("Unsupported RSS hash functions: %U",
+ format_dpdk_rss_hf_name, unsupported_bits);
}
+ xd->conf.rss_hf &= di.flow_type_rss_offloads;
+ dpdk_log_debug ("[%u] rss_hf: %U", port_id, format_dpdk_rss_hf_name,
+ xd->conf.rss_hf);
}
- /*Set port rxmode config */
- xd->port_conf.rxmode.max_rx_pkt_len = max_rx_frame;
-
- sw = vnet_get_hw_sw_interface (dm->vnet_main, xd->hw_if_index);
+#ifndef RTE_VLAN_HLEN
+#define RTE_VLAN_HLEN 4
+#endif
+ xd->driver_frame_overhead =
+ RTE_ETHER_HDR_LEN + 2 * RTE_VLAN_HLEN + RTE_ETHER_CRC_LEN;
+#if RTE_VERSION >= RTE_VERSION_NUM(21, 11, 0, 0)
+ q = di.max_rx_pktlen - di.max_mtu;
+
+ /* attempt to protect from bogus value provided by pmd */
+ if (q < (2 * xd->driver_frame_overhead) && q > 0 &&
+ di.max_mtu != UINT16_MAX)
+ xd->driver_frame_overhead = q;
+ dpdk_log_debug ("[%u] min_mtu: %u, max_mtu: %u, min_rx_bufsize: %u, "
+ "max_rx_pktlen: %u, max_lro_pkt_size: %u",
+ xd->port_id, di.min_mtu, di.max_mtu, di.min_rx_bufsize,
+ di.max_rx_pktlen, di.max_lro_pkt_size);
+#endif
+ dpdk_log_debug ("[%u] driver frame overhead is %u", port_id,
+ xd->driver_frame_overhead);
+
+ /* number of RX and TX tescriptors */
+ if (devconf->num_rx_desc)
+ xd->conf.n_rx_desc = devconf->num_rx_desc;
+ else if (dr && dr->n_rx_desc)
+ xd->conf.n_rx_desc = dr->n_rx_desc;
+
+ if (devconf->num_tx_desc)
+ xd->conf.n_tx_desc = devconf->num_tx_desc;
+ else if (dr && dr->n_tx_desc)
+ xd->conf.n_tx_desc = dr->n_tx_desc;
+
+ dpdk_log_debug (
+ "[%u] n_rx_queues: %u n_tx_queues: %u n_rx_desc: %u n_tx_desc: %u",
+ port_id, xd->conf.n_rx_queues, xd->conf.n_tx_queues,
+ xd->conf.n_rx_desc, xd->conf.n_tx_desc);
+
+ vec_validate_aligned (xd->rx_queues, xd->conf.n_rx_queues - 1,
+ CLIB_CACHE_LINE_BYTES);
+ vec_validate_aligned (xd->tx_queues, xd->conf.n_tx_queues - 1,
+ CLIB_CACHE_LINE_BYTES);
+
+ rte_eth_macaddr_get (port_id, (void *) addr);
+
+ /* create interface */
+ eir.dev_class_index = dpdk_device_class.index;
+ eir.dev_instance = xd->device_index;
+ eir.address = addr;
+ eir.cb.flag_change = dpdk_flag_change;
+ eir.cb.set_max_frame_size = dpdk_set_max_frame_size;
+ xd->hw_if_index = vnet_eth_register_interface (vnm, &eir);
+ hi = vnet_get_hw_interface (vnm, xd->hw_if_index);
+ numa_node = (i8) rte_eth_dev_socket_id (port_id);
+ if (numa_node == SOCKET_ID_ANY)
+ /* numa_node is not set, default to 0 */
+ hi->numa_node = xd->cpu_socket = 0;
+ else
+ hi->numa_node = xd->cpu_socket = numa_node;
+ sw = vnet_get_hw_sw_interface (vnm, xd->hw_if_index);
xd->sw_if_index = sw->sw_if_index;
- vnet_hw_interface_set_input_node (dm->vnet_main, xd->hw_if_index,
- dpdk_input_node.index);
+ dpdk_log_debug ("[%u] interface %s created", port_id, hi->name);
+
+ if (devconf->tag)
+ vnet_set_sw_interface_tag (vnm, devconf->tag, sw->sw_if_index);
+
+ ethernet_set_flags (vnm, xd->hw_if_index,
+ ETHERNET_INTERFACE_FLAG_DEFAULT_L3);
+ /* assign worker threads */
+ vnet_hw_if_set_input_node (vnm, xd->hw_if_index, dpdk_input_node.index);
if (devconf->workers)
{
- int i;
+ int j;
q = 0;
- clib_bitmap_foreach (i, devconf->workers, ({
- vnet_hw_interface_assign_rx_thread (dm->vnet_main, xd->hw_if_index, q++,
- vdm->first_worker_thread_index + i);
- }));
+ clib_bitmap_foreach (j, devconf->workers)
+ {
+ dpdk_rx_queue_t *rxq = vec_elt_at_index (xd->rx_queues, q);
+ rxq->queue_index = vnet_hw_if_register_rx_queue (
+ vnm, xd->hw_if_index, q++, vdm->first_worker_thread_index + j);
+ }
}
else
- for (q = 0; q < xd->rx_q_used; q++)
+ for (q = 0; q < xd->conf.n_rx_queues; q++)
{
- vnet_hw_interface_assign_rx_thread (dm->vnet_main, xd->hw_if_index, q, /* any */
- ~1);
+ dpdk_rx_queue_t *rxq = vec_elt_at_index (xd->rx_queues, q);
+ rxq->queue_index = vnet_hw_if_register_rx_queue (
+ vnm, xd->hw_if_index, q, VNET_HW_IF_RXQ_THREAD_ANY);
}
- /*Get vnet hardware interface */
- hi = vnet_get_hw_interface (dm->vnet_main, xd->hw_if_index);
-
- /*Override default max_packet_bytes and max_supported_bytes set in
- * ethernet_register_interface() above*/
- if (hi)
+ for (q = 0; q < xd->conf.n_tx_queues; q++)
{
- hi->max_packet_bytes = mtu;
- hi->max_supported_packet_bytes = max_rx_frame;
+ dpdk_tx_queue_t *txq = vec_elt_at_index (xd->tx_queues, q);
+ txq->queue_index =
+ vnet_hw_if_register_tx_queue (vnm, xd->hw_if_index, q);
}
- if (dm->conf->no_tx_checksum_offload == 0)
- if (xd->flags & DPDK_DEVICE_FLAG_TX_OFFLOAD)
- hi->flags |= VNET_HW_INTERFACE_FLAG_SUPPORTS_TX_L4_CKSUM_OFFLOAD;
-
- dpdk_device_setup (xd);
-
- if (vec_len (xd->errors))
- dpdk_log_err ("setup failed for device %U. Errors:\n %U",
- format_dpdk_device_name, i,
- format_dpdk_device_errors, xd);
-
- if (devconf->hqos_enabled)
+ for (q = 0; q < tm->n_vlib_mains; q++)
{
- clib_error_t *rv;
- rv = dpdk_port_setup_hqos (xd, &devconf->hqos);
- if (rv)
- return rv;
+ u32 qi = xd->tx_queues[q % xd->conf.n_tx_queues].queue_index;
+ vnet_hw_if_tx_queue_assign_thread (vnm, qi, q);
}
- /*
- * For cisco VIC vNIC, set default to VLAN strip enabled, unless
- * specified otherwise in the startup config.
- * For other NICs default to VLAN strip disabled, unless specified
- * otherwis in the startup config.
- */
- if (xd->pmd == VNET_DPDK_PMD_ENIC)
+ if (devconf->tso == DPDK_DEVICE_TSO_ON)
{
- if (devconf->vlan_strip_offload != DPDK_DEVICE_VLAN_STRIP_OFF)
- vlan_strip = 1; /* remove vlan tag from VIC port by default */
+ /*tcp_udp checksum must be enabled*/
+ if (xd->conf.enable_tcp_udp_checksum == 0)
+ dpdk_log_warn ("[%u] TCP/UDP checksum offload must be enabled",
+ xd->port_id);
+ else if ((di.tx_offload_capa & RTE_ETH_TX_OFFLOAD_TCP_TSO) == 0)
+ dpdk_log_warn ("[%u] TSO not supported by device", xd->port_id);
else
- dpdk_log_warn ("VLAN strip disabled for interface\n");
+ xd->conf.enable_tso = 1;
}
- else if (devconf->vlan_strip_offload == DPDK_DEVICE_VLAN_STRIP_ON)
- vlan_strip = 1;
- if (vlan_strip)
- {
- int vlan_off;
- vlan_off = rte_eth_dev_get_vlan_offload (xd->port_id);
- vlan_off |= ETH_VLAN_STRIP_OFFLOAD;
- xd->port_conf.rxmode.hw_vlan_strip = vlan_off;
- if (rte_eth_dev_set_vlan_offload (xd->port_id, vlan_off) == 0)
- dpdk_log_info ("VLAN strip enabled for interface\n");
- else
- dpdk_log_warn ("VLAN strip cannot be supported by interface\n");
- }
+ if (devconf->max_lro_pkt_size)
+ xd->conf.max_lro_pkt_size = devconf->max_lro_pkt_size;
- if (hi)
- hi->max_packet_bytes = xd->port_conf.rxmode.max_rx_pkt_len
- - sizeof (ethernet_header_t);
- else
- clib_warning ("hi NULL");
+ dpdk_device_setup (xd);
- if (dm->conf->no_multi_seg)
- mtu = mtu > ETHER_MAX_LEN ? ETHER_MAX_LEN : mtu;
+ /* rss queues should be configured after dpdk_device_setup() */
+ if (devconf->rss_queues)
+ {
+ if (vnet_hw_interface_set_rss_queues (vnet_get_main (), hi,
+ devconf->rss_queues))
+ dpdk_log_warn ("[%u] Failed to set rss queues", port_id);
+ }
- rte_eth_dev_set_mtu (xd->port_id, mtu);
+ if (vec_len (xd->errors))
+ dpdk_log_err ("[%u] setup failed Errors:\n %U", port_id,
+ format_dpdk_device_errors, xd);
}
- /* *INDENT-ON* */
- if (nb_desc > dm->conf->num_mbufs)
- dpdk_log_err ("%d mbufs allocated but total rx/tx ring size is %d\n",
- dm->conf->num_mbufs, nb_desc);
+ for (int i = 0; i < vec_len (dm->devices); i++)
+ vnet_hw_if_update_runtime_data (vnm, dm->devices[i].hw_if_index);
return 0;
}
static void
dpdk_bind_devices_to_uio (dpdk_config_main_t * conf)
{
+ vlib_main_t *vm = vlib_get_main ();
clib_error_t *error;
u8 *pci_addr = 0;
int num_whitelisted = vec_len (conf->dev_confs);
vlib_pci_device_info_t *d = 0;
vlib_pci_addr_t *addr = 0, *addrs;
+ int i;
addrs = vlib_pci_get_all_dev_addrs ();
/* *INDENT-OFF* */
vlib_pci_free_device_info (d);
d = 0;
}
- d = vlib_pci_get_device_info (addr, &error);
+ d = vlib_pci_get_device_info (vm, addr, &error);
if (error)
{
- clib_error_report (error);
+ vlib_log_warn (dpdk_main.log_default, "%U", format_clib_error, error);
+ clib_error_free (error);
continue;
}
uword * p = hash_get (conf->device_config_index_by_pci_addr, addr->as_u32);
if (!p)
- continue;
+ {
+ skipped_pci:
+ continue;
+ }
devconf = pool_elt_at_index (conf->dev_confs, p[0]);
}
+ /* Enforce Device blacklist by vendor and device */
+ for (i = 0; i < vec_len (conf->blacklist_by_pci_vendor_and_device); i++)
+ {
+ u16 vendor, device;
+ vendor = (u16)(conf->blacklist_by_pci_vendor_and_device[i] >> 16);
+ device = (u16)(conf->blacklist_by_pci_vendor_and_device[i] & 0xFFFF);
+ if (d->vendor_id == vendor && d->device_id == device)
+ {
+ /*
+ * Expected case: device isn't whitelisted,
+ * so blacklist it...
+ */
+ if (devconf == 0)
+ {
+ /* Device is blacklisted */
+ pool_get (conf->dev_confs, devconf);
+ hash_set (conf->device_config_index_by_pci_addr, addr->as_u32,
+ devconf - conf->dev_confs);
+ devconf->pci_addr.as_u32 = addr->as_u32;
+ devconf->dev_addr_type = VNET_DEV_ADDR_PCI;
+ devconf->is_blacklisted = 1;
+ goto skipped_pci;
+ }
+ else /* explicitly whitelisted, ignore the device blacklist */
+ break;
+ }
+ }
+
/* virtio */
if (d->vendor_id == 0x1af4 &&
(d->device_id == VIRTIO_PCI_LEGACY_DEVICEID_NET ||
;
/* vmxnet3 */
else if (d->vendor_id == 0x15ad && d->device_id == 0x07b0)
- ;
+ {
+ /*
+ * For vmxnet3 PCI, unless it is explicitly specified in the whitelist,
+ * the default is to put it in the blacklist.
+ */
+ if (devconf == 0)
+ {
+ pool_get (conf->dev_confs, devconf);
+ hash_set (conf->device_config_index_by_pci_addr, addr->as_u32,
+ devconf - conf->dev_confs);
+ devconf->pci_addr.as_u32 = addr->as_u32;
+ devconf->is_blacklisted = 1;
+ }
+ }
/* all Intel network devices */
else if (d->vendor_id == 0x8086 && d->device_class == PCI_CLASS_NETWORK_ETHERNET)
;
/* all Intel QAT devices VFs */
- else if (d->vendor_id == 0x8086 && d->device_class == PCI_CLASS_PROCESSOR_CO &&
- (d->device_id == 0x0443 || d->device_id == 0x37c9 || d->device_id == 0x19e3))
+ else if (d->vendor_id == 0x8086 &&
+ d->device_class == PCI_CLASS_PROCESSOR_CO &&
+ (d->device_id == 0x0443 || d->device_id == 0x18a1 ||
+ d->device_id == 0x19e3 || d->device_id == 0x37c9 ||
+ d->device_id == 0x6f55 || d->device_id == 0x18ef ||
+ d->device_id == 0x4941))
;
/* Cisco VIC */
- else if (d->vendor_id == 0x1137 && d->device_id == 0x0043)
+ else if (d->vendor_id == 0x1137 &&
+ (d->device_id == 0x0043 || d->device_id == 0x0071))
;
/* Chelsio T4/T5 */
else if (d->vendor_id == 0x1425 && (d->device_id & 0xe000) == 0x4000)
;
- /* Amazen Elastic Network Adapter */
+ /* Amazon Elastic Network Adapter */
else if (d->vendor_id == 0x1d0f && d->device_id >= 0xec20 && d->device_id <= 0xec21)
;
/* Cavium Network Adapter */
/* Cavium FastlinQ QL41000 Series */
else if (d->vendor_id == 0x1077 && d->device_id >= 0x8070 && d->device_id <= 0x8090)
;
- /* Mellanox */
+ /* Mellanox CX3, CX3VF */
+ else if (d->vendor_id == 0x15b3 && d->device_id >= 0x1003 && d->device_id <= 0x1004)
+ {
+ continue;
+ }
+ /* Mellanox CX4, CX4VF, CX4LX, CX4LXVF, CX5, CX5VF, CX5EX, CX5EXVF */
else if (d->vendor_id == 0x15b3 && d->device_id >= 0x1013 && d->device_id <= 0x101a)
{
continue;
}
+ /* Mellanox CX6, CX6VF, CX6DX, CX6DXVF, CX6LX */
+ else if (d->vendor_id == 0x15b3 &&
+ (d->device_id >= 0x101b && d->device_id <= 0x101f))
+ {
+ continue;
+ }
+ /* Mellanox CX7 */
+ else if (d->vendor_id == 0x15b3 && d->device_id == 0x1021)
+ {
+ continue;
+ }
+ /* Broadcom NetXtreme S, and E series only */
+ else if (d->vendor_id == 0x14e4 &&
+ ((d->device_id >= 0x16c0 &&
+ d->device_id != 0x16c6 && d->device_id != 0x16c7 &&
+ d->device_id != 0x16dd && d->device_id != 0x16f7 &&
+ d->device_id != 0x16fd && d->device_id != 0x16fe &&
+ d->device_id != 0x170d && d->device_id != 0x170c &&
+ d->device_id != 0x170e && d->device_id != 0x1712 &&
+ d->device_id != 0x1713) ||
+ (d->device_id == 0x1604 || d->device_id == 0x1605 ||
+ d->device_id == 0x1614 || d->device_id == 0x1606 ||
+ d->device_id == 0x1609 || d->device_id == 0x1614)))
+ ;
+ /* Google vNIC */
+ else if (d->vendor_id == 0x1ae0 && d->device_id == 0x0042)
+ ;
else
{
dpdk_log_warn ("Unsupported PCI device 0x%04x:0x%04x found "
continue;
}
- error = vlib_pci_bind_to_uio (addr, (char *) conf->uio_driver_name);
+ error = vlib_pci_bind_to_uio (vm, addr, (char *) conf->uio_driver_name,
+ conf->uio_bind_force);
+
+ if (error)
+ {
+ if (devconf == 0)
+ {
+ pool_get (conf->dev_confs, devconf);
+ hash_set (conf->device_config_index_by_pci_addr, addr->as_u32,
+ devconf - conf->dev_confs);
+ devconf->pci_addr.as_u32 = addr->as_u32;
+ }
+ devconf->dev_addr_type = VNET_DEV_ADDR_PCI;
+ devconf->is_blacklisted = 1;
+ clib_error_report (error);
+ }
+ }
+ /* *INDENT-ON* */
+ vec_free (pci_addr);
+ vlib_pci_free_device_info (d);
+}
+
+static void
+dpdk_bind_vmbus_devices_to_uio (dpdk_config_main_t * conf)
+{
+ clib_error_t *error;
+ vlib_vmbus_addr_t *addrs, *addr = 0;
+ int num_whitelisted = vec_len (conf->dev_confs);
+ int i;
+
+ addrs = vlib_vmbus_get_all_dev_addrs ();
+
+ /* *INDENT-OFF* */
+ vec_foreach (addr, addrs)
+ {
+ dpdk_device_config_t *devconf = 0;
+ if (num_whitelisted)
+ {
+ uword *p =
+ mhash_get (&conf->device_config_index_by_vmbus_addr, addr);
+ if (!p)
+ {
+ /* No devices blacklisted, but have whitelisted. blacklist all
+ * non-whitelisted */
+ pool_get (conf->dev_confs, devconf);
+ mhash_set (&conf->device_config_index_by_vmbus_addr, addr,
+ devconf - conf->dev_confs, 0);
+ devconf->vmbus_addr = *addr;
+ devconf->dev_addr_type = VNET_DEV_ADDR_VMBUS;
+ devconf->is_blacklisted = 1;
+ skipped_vmbus:
+ continue;
+ }
+
+ devconf = pool_elt_at_index (conf->dev_confs, p[0]);
+ }
+
+ /* Enforce Device blacklist by vmbus_addr */
+ for (i = 0; i < vec_len (conf->blacklist_by_vmbus_addr); i++)
+ {
+ vlib_vmbus_addr_t *a1 = &conf->blacklist_by_vmbus_addr[i];
+ vlib_vmbus_addr_t *a2 = addr;
+ if (memcmp (a1, a2, sizeof (vlib_vmbus_addr_t)) == 0)
+ {
+ if (devconf == 0)
+ {
+ /* Device not whitelisted */
+ pool_get (conf->dev_confs, devconf);
+ mhash_set (&conf->device_config_index_by_vmbus_addr, addr,
+ devconf - conf->dev_confs, 0);
+ devconf->vmbus_addr = *addr;
+ devconf->dev_addr_type = VNET_DEV_ADDR_VMBUS;
+ devconf->is_blacklisted = 1;
+ goto skipped_vmbus;
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+
+ error = vlib_vmbus_bind_to_uio (addr);
+ if (error)
+ {
+ if (devconf == 0)
+ {
+ pool_get (conf->dev_confs, devconf);
+ mhash_set (&conf->device_config_index_by_vmbus_addr, addr,
+ devconf - conf->dev_confs, 0);
+ devconf->vmbus_addr = *addr;
+ }
+ devconf->dev_addr_type = VNET_DEV_ADDR_VMBUS;
+ devconf->is_blacklisted = 1;
+ clib_error_report (error);
+ }
+ }
+ /* *INDENT-ON* */
+}
+
+uword
+unformat_max_simd_bitwidth (unformat_input_t *input, va_list *va)
+{
+ uword *max_simd_bitwidth = va_arg (*va, uword *);
- if (error)
- {
- if (devconf == 0)
- {
- pool_get (conf->dev_confs, devconf);
- hash_set (conf->device_config_index_by_pci_addr, addr->as_u32,
- devconf - conf->dev_confs);
- devconf->pci_addr.as_u32 = addr->as_u32;
- }
- devconf->is_blacklisted = 1;
- clib_error_report (error);
- }
- }
- /* *INDENT-ON* */
- vec_free (pci_addr);
- vlib_pci_free_device_info (d);
+ while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (!unformat (input, "%u", max_simd_bitwidth))
+ goto error;
+
+ if (*max_simd_bitwidth != DPDK_MAX_SIMD_BITWIDTH_256 &&
+ *max_simd_bitwidth != DPDK_MAX_SIMD_BITWIDTH_512)
+ goto error;
+ }
+ return 1;
+error:
+ return 0;
}
static clib_error_t *
-dpdk_device_config (dpdk_config_main_t * conf, vlib_pci_addr_t pci_addr,
- unformat_input_t * input, u8 is_default)
+dpdk_device_config (dpdk_config_main_t *conf, void *addr,
+ dpdk_device_addr_type_t addr_type, unformat_input_t *input,
+ u8 is_default)
{
clib_error_t *error = 0;
uword *p;
- dpdk_device_config_t *devconf;
+ dpdk_device_config_t *devconf = 0;
unformat_input_t sub_input;
if (is_default)
{
devconf = &conf->default_devconf;
}
- else
+ else if (addr_type == VNET_DEV_ADDR_PCI)
{
- p = hash_get (conf->device_config_index_by_pci_addr, pci_addr.as_u32);
+ p = hash_get (conf->device_config_index_by_pci_addr,
+ ((vlib_pci_addr_t *) (addr))->as_u32);
if (!p)
{
pool_get (conf->dev_confs, devconf);
- hash_set (conf->device_config_index_by_pci_addr, pci_addr.as_u32,
+ hash_set (conf->device_config_index_by_pci_addr,
+ ((vlib_pci_addr_t *) (addr))->as_u32,
devconf - conf->dev_confs);
}
else
return clib_error_return (0,
"duplicate configuration for PCI address %U",
- format_vlib_pci_addr, &pci_addr);
+ format_vlib_pci_addr, addr);
+ }
+ else if (addr_type == VNET_DEV_ADDR_VMBUS)
+ {
+ p = mhash_get (&conf->device_config_index_by_vmbus_addr,
+ (vlib_vmbus_addr_t *) (addr));
+
+ if (!p)
+ {
+ pool_get (conf->dev_confs, devconf);
+ mhash_set (&conf->device_config_index_by_vmbus_addr, addr,
+ devconf - conf->dev_confs, 0);
+ }
+ else
+ return clib_error_return (
+ 0, "duplicate configuration for VMBUS address %U",
+ format_vlib_vmbus_addr, addr);
}
- devconf->pci_addr.as_u32 = pci_addr.as_u32;
- devconf->hqos_enabled = 0;
- dpdk_device_config_hqos_default (&devconf->hqos);
+ if (addr_type == VNET_DEV_ADDR_PCI)
+ {
+ devconf->pci_addr.as_u32 = ((vlib_pci_addr_t *) (addr))->as_u32;
+ devconf->tso = DPDK_DEVICE_TSO_DEFAULT;
+ devconf->dev_addr_type = VNET_DEV_ADDR_PCI;
+ }
+ else if (addr_type == VNET_DEV_ADDR_VMBUS)
+ {
+ devconf->vmbus_addr = *((vlib_vmbus_addr_t *) (addr));
+ devconf->tso = DPDK_DEVICE_TSO_DEFAULT;
+ devconf->dev_addr_type = VNET_DEV_ADDR_VMBUS;
+ }
if (!input)
return 0;
;
else if (unformat (input, "num-tx-desc %u", &devconf->num_tx_desc))
;
+ else if (unformat (input, "name %v", &devconf->name))
+ ;
+ else if (unformat (input, "tag %s", &devconf->tag))
+ ;
else if (unformat (input, "workers %U", unformat_bitmap_list,
&devconf->workers))
;
if (error)
break;
}
- else if (unformat (input, "vlan-strip-offload off"))
- devconf->vlan_strip_offload = DPDK_DEVICE_VLAN_STRIP_OFF;
- else if (unformat (input, "vlan-strip-offload on"))
- devconf->vlan_strip_offload = DPDK_DEVICE_VLAN_STRIP_ON;
- else
- if (unformat
- (input, "hqos %U", unformat_vlib_cli_sub_input, &sub_input))
+ else if (unformat (input, "tso on"))
{
- devconf->hqos_enabled = 1;
- error = unformat_hqos (&sub_input, &devconf->hqos);
- if (error)
- break;
+ devconf->tso = DPDK_DEVICE_TSO_ON;
}
- else if (unformat (input, "hqos"))
+ else if (unformat (input, "tso off"))
{
- devconf->hqos_enabled = 1;
+ devconf->tso = DPDK_DEVICE_TSO_OFF;
}
+ else if (unformat (input, "devargs %s", &devconf->devargs))
+ ;
+ else if (unformat (input, "rss-queues %U",
+ unformat_bitmap_list, &devconf->rss_queues))
+ ;
+ else if (unformat (input, "max-lro-pkt-size %u",
+ &devconf->max_lro_pkt_size))
+ ;
else
{
error = clib_error_return (0, "unknown input `%U'",
else if (devconf->workers &&
clib_bitmap_count_set_bits (devconf->workers) !=
devconf->num_rx_queues)
- error =
- clib_error_return (0,
- "%U: number of worker threadds must be "
- "equal to number of rx queues", format_vlib_pci_addr,
- &pci_addr);
+ error = clib_error_return (0,
+ "%U: number of worker threads must be "
+ "equal to number of rx queues",
+ format_vlib_pci_addr, addr);
return error;
}
n = read (uf->file_descriptor, s + len, n_try);
if (n < 0 && errno != EAGAIN)
return clib_error_return_unix (0, "read");
- _vec_len (s) = len + (n < 0 ? 0 : n);
+ vec_set_len (s, len + (n < 0 ? 0 : n));
}
unformat_init_vector (&input, s);
while (unformat_user (&input, unformat_line, &line))
{
- dpdk_log_notice ("%v", line);
+ int skip = 0;
+ vec_add1 (line, 0);
+
+ /* unfortunatelly DPDK polutes log with this error messages
+ * even when we pass --in-memory which means no secondary process */
+ if (strstr ((char *) line, "WARNING! Base virtual address hint"))
+ skip = 1;
+ else if (strstr ((char *) line, "This may cause issues with mapping "
+ "memory into secondary processes"))
+ skip = 1;
+ vec_pop (line);
+ if (!skip)
+ dpdk_log_notice ("%v", line);
vec_free (line);
}
static clib_error_t *
dpdk_config (vlib_main_t * vm, unformat_input_t * input)
{
+ dpdk_main_t *dm = &dpdk_main;
clib_error_t *error = 0;
dpdk_config_main_t *conf = &dpdk_config_main;
vlib_thread_main_t *tm = vlib_get_thread_main ();
dpdk_device_config_t *devconf;
- vlib_pci_addr_t pci_addr;
+ vlib_pci_addr_t pci_addr = { 0 };
+ vlib_vmbus_addr_t vmbus_addr = { 0 };
unformat_input_t sub_input;
- uword x;
+ uword default_hugepage_sz, x;
u8 *s, *tmp = 0;
- u32 log_level;
int ret, i;
int num_whitelisted = 0;
+ int eal_no_hugetlb = 0;
u8 no_pci = 0;
- u8 no_huge = 0;
- u8 huge_dir = 0;
+ u8 no_vmbus = 0;
u8 file_prefix = 0;
u8 *socket_mem = 0;
u8 *huge_dir_path = 0;
+ u32 vendor, device, domain, bus, func;
+ void *fmt_func;
+ void *fmt_addr;
huge_dir_path =
format (0, "%s/hugepages%c", vlib_unix_get_runtime_dir (), 0);
conf->device_config_index_by_pci_addr = hash_create (0, sizeof (uword));
- log_level = RTE_LOG_NOTICE;
+ mhash_init (&conf->device_config_index_by_vmbus_addr, sizeof (uword),
+ sizeof (vlib_vmbus_addr_t));
while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
{
if (unformat (input, "no-hugetlb"))
{
vec_add1 (conf->eal_init_args, (u8 *) "--no-huge");
- no_huge = 1;
+ eal_no_hugetlb = 1;
}
+ else if (unformat (input, "telemetry"))
+ conf->enable_telemetry = 1;
else if (unformat (input, "enable-tcp-udp-checksum"))
- conf->enable_tcp_udp_checksum = 1;
-
+ {
+ dm->default_port_conf.enable_tcp_udp_checksum = 1;
+ if (unformat (input, "enable-outer-checksum-offload"))
+ dm->default_port_conf.enable_outer_checksum_offload = 1;
+ }
else if (unformat (input, "no-tx-checksum-offload"))
- conf->no_tx_checksum_offload = 1;
+ dm->default_port_conf.disable_tx_checksum_offload = 1;
else if (unformat (input, "decimal-interface-names"))
conf->interface_name_format_decimal = 1;
- else if (unformat (input, "log-level %U", unformat_dpdk_log_level, &x))
- log_level = x;
-
else if (unformat (input, "no-multi-seg"))
- conf->no_multi_seg = 1;
-
+ dm->default_port_conf.disable_multi_seg = 1;
+ else if (unformat (input, "enable-lro"))
+ dm->default_port_conf.enable_lro = 1;
+ else if (unformat (input, "max-simd-bitwidth %U",
+ unformat_max_simd_bitwidth, &conf->max_simd_bitwidth))
+ ;
else if (unformat (input, "dev default %U", unformat_vlib_cli_sub_input,
&sub_input))
{
error =
- dpdk_device_config (conf, (vlib_pci_addr_t) (u32) ~ 1, &sub_input,
- 1);
+ dpdk_device_config (conf, 0, VNET_DEV_ADDR_ANY, &sub_input, 1);
if (error)
return error;
(input, "dev %U %U", unformat_vlib_pci_addr, &pci_addr,
unformat_vlib_cli_sub_input, &sub_input))
{
- error = dpdk_device_config (conf, pci_addr, &sub_input, 0);
+ error = dpdk_device_config (conf, &pci_addr, VNET_DEV_ADDR_PCI,
+ &sub_input, 0);
if (error)
return error;
}
else if (unformat (input, "dev %U", unformat_vlib_pci_addr, &pci_addr))
{
- error = dpdk_device_config (conf, pci_addr, 0, 0);
+ error =
+ dpdk_device_config (conf, &pci_addr, VNET_DEV_ADDR_PCI, 0, 0);
+
+ if (error)
+ return error;
+
+ num_whitelisted++;
+ }
+ else if (unformat (input, "dev %U %U", unformat_vlib_vmbus_addr,
+ &vmbus_addr, unformat_vlib_cli_sub_input, &sub_input))
+ {
+ error = dpdk_device_config (conf, &vmbus_addr, VNET_DEV_ADDR_VMBUS,
+ &sub_input, 0);
+
+ if (error)
+ return error;
+
+ num_whitelisted++;
+ }
+ else if (unformat (input, "dev %U", unformat_vlib_vmbus_addr,
+ &vmbus_addr))
+ {
+ error =
+ dpdk_device_config (conf, &vmbus_addr, VNET_DEV_ADDR_VMBUS, 0, 0);
if (error)
return error;
num_whitelisted++;
}
- else if (unformat (input, "num-mbufs %d", &conf->num_mbufs))
- ;
else if (unformat (input, "uio-driver %s", &conf->uio_driver_name))
;
+ else if (unformat (input, "uio-bind-force"))
+ conf->uio_bind_force = 1;
else if (unformat (input, "socket-mem %s", &socket_mem))
;
else if (unformat (input, "no-pci"))
tmp = format (0, "--no-pci%c", 0);
vec_add1 (conf->eal_init_args, tmp);
}
+ else if (unformat (input, "blacklist %U", unformat_vlib_vmbus_addr,
+ &vmbus_addr))
+ {
+ vec_add1 (conf->blacklist_by_vmbus_addr, vmbus_addr);
+ }
+ else
+ if (unformat
+ (input, "blacklist %x:%x:%x.%x", &domain, &bus, &device, &func))
+ {
+ tmp = format (0, "-b%c", 0);
+ vec_add1 (conf->eal_init_args, tmp);
+ tmp =
+ format (0, "%04x:%02x:%02x.%x%c", domain, bus, device, func, 0);
+ vec_add1 (conf->eal_init_args, tmp);
+ }
+ else if (unformat (input, "blacklist %x:%x", &vendor, &device))
+ {
+ u32 blacklist_entry;
+ if (vendor > 0xFFFF)
+ return clib_error_return (0, "blacklist PCI vendor out of range");
+ if (device > 0xFFFF)
+ return clib_error_return (0, "blacklist PCI device out of range");
+ blacklist_entry = (vendor << 16) | (device & 0xffff);
+ vec_add1 (conf->blacklist_by_pci_vendor_and_device,
+ blacklist_entry);
+ }
+ else if (unformat (input, "no-vmbus"))
+ {
+ no_vmbus = 1;
+ tmp = format (0, "--no-vmbus%c", 0);
+ vec_add1 (conf->eal_init_args, tmp);
+ }
#define _(a) \
else if (unformat(input, #a)) \
#define _(a) \
else if (unformat(input, #a " %s", &s)) \
{ \
- if (!strncmp(#a, "huge-dir", 8)) \
- huge_dir = 1; \
- else if (!strncmp(#a, "file-prefix", 11)) \
+ if (!strncmp(#a, "file-prefix", 11)) \
file_prefix = 1; \
tmp = format (0, "--%s%c", #a, 0); \
vec_add1 (conf->eal_init_args, tmp); \
vec_add1 (conf->eal_init_args, s); \
}
foreach_eal_single_hyphen_arg
-#undef _
-#define _(a,b) \
- else if (unformat(input, #a " %s", &s)) \
- { \
- tmp = format (0, "-%s%c", #b, 0); \
- vec_add1 (conf->eal_init_args, tmp); \
- vec_add1 (s, 0); \
- vec_add1 (conf->eal_init_args, s); \
- conf->a##_set_manually = 1; \
- }
- foreach_eal_single_hyphen_mandatory_arg
#undef _
else if (unformat (input, "default"))
;
else if (unformat_skip_white_space (input))
;
- else
- {
- error = clib_error_return (0, "unknown input `%U'",
+ else return clib_error_return (0, "unknown input `%U'",
format_unformat_error, input);
- goto done;
- }
}
if (!conf->uio_driver_name)
conf->uio_driver_name = format (0, "auto%c", 0);
- /*
- * Use 1G huge pages if available.
- */
- if (!no_huge && !huge_dir)
+ if (eal_no_hugetlb == 0)
{
- u32 x, *mem_by_socket = 0;
- uword c = 0;
- int rv;
+ vec_add1 (conf->eal_init_args, (u8 *) "--in-memory");
- umount ((char *) huge_dir_path);
-
- /* Process "socket-mem" parameter value */
- if (vec_len (socket_mem))
- {
- unformat_input_t in;
- unformat_init_vector (&in, socket_mem);
- while (unformat_check_input (&in) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (&in, "%u,", &x))
- ;
- else if (unformat (&in, "%u", &x))
- ;
- else if (unformat (&in, ","))
- x = 0;
- else
- break;
-
- vec_add1 (mem_by_socket, x);
- }
- /* Note: unformat_free vec_frees(in.buffer), aka socket_mem... */
- unformat_free (&in);
- socket_mem = 0;
- }
- else
- {
- /* *INDENT-OFF* */
- clib_bitmap_foreach (c, tm->cpu_socket_bitmap, (
- {
- vec_validate(mem_by_socket, c);
- mem_by_socket[c] = 64; /* default per-socket mem */
- }
- ));
- /* *INDENT-ON* */
- }
+ default_hugepage_sz = clib_mem_get_default_hugepage_size ();
/* *INDENT-OFF* */
- clib_bitmap_foreach (c, tm->cpu_socket_bitmap, (
- {
+ clib_bitmap_foreach (x, tm->cpu_socket_bitmap)
+ {
clib_error_t *e;
+ uword n_pages;
+ /* preallocate at least 16MB of hugepages per socket,
+ if more is needed it is up to consumer to preallocate more */
+ n_pages = round_pow2 ((uword) 16 << 20, default_hugepage_sz);
+ n_pages /= default_hugepage_sz;
- vec_validate(mem_by_socket, c);
-
- e = clib_sysfs_prealloc_hugepages(c, 2 << 10, mem_by_socket[c] / 2);
- if (e)
+ if ((e = clib_sysfs_prealloc_hugepages(x, 0, n_pages)))
clib_error_report (e);
- }));
+ }
/* *INDENT-ON* */
-
- if (mem_by_socket == 0)
- {
- error = clib_error_return (0, "mem_by_socket NULL");
- goto done;
- }
- _vec_len (mem_by_socket) = c + 1;
-
- /* regenerate socket_mem string */
- vec_foreach_index (x, mem_by_socket)
- socket_mem = format (socket_mem, "%s%u",
- socket_mem ? "," : "", mem_by_socket[x]);
- socket_mem = format (socket_mem, "%c", 0);
-
- vec_free (mem_by_socket);
-
- error = vlib_unix_recursive_mkdir ((char *) huge_dir_path);
- if (error)
- {
- goto done;
- }
-
- rv = mount ("none", (char *) huge_dir_path, "hugetlbfs", 0, NULL);
-
- if (rv)
- {
- error = clib_error_return (0, "mount failed %d", errno);
- goto done;
- }
-
- tmp = format (0, "--huge-dir%c", 0);
- vec_add1 (conf->eal_init_args, tmp);
- tmp = format (0, "%s%c", huge_dir_path, 0);
- vec_add1 (conf->eal_init_args, tmp);
- if (!file_prefix)
- {
- tmp = format (0, "--file-prefix%c", 0);
- vec_add1 (conf->eal_init_args, tmp);
- tmp = format (0, "vpp%c", 0);
- vec_add1 (conf->eal_init_args, tmp);
- }
}
- if (error)
- return error;
-
- /* I'll bet that -c and -n must be the first and second args... */
- if (!conf->coremask_set_manually)
+ /* on/off dpdk's telemetry thread */
+ if (conf->enable_telemetry == 0)
{
- vlib_thread_registration_t *tr;
- uword *coremask = 0;
- int i;
-
- /* main thread core */
- coremask = clib_bitmap_set (coremask, tm->main_lcore, 1);
-
- for (i = 0; i < vec_len (tm->registrations); i++)
- {
- tr = tm->registrations[i];
- coremask = clib_bitmap_or (coremask, tr->coremask);
- }
-
- vec_insert (conf->eal_init_args, 2, 1);
- conf->eal_init_args[1] = (u8 *) "-c";
- tmp = format (0, "%U%c", format_bitmap_hex, coremask, 0);
- conf->eal_init_args[2] = tmp;
- clib_bitmap_free (coremask);
+ vec_add1 (conf->eal_init_args, (u8 *) "--no-telemetry");
}
- if (!conf->nchannels_set_manually)
+ if (!file_prefix)
{
- vec_insert (conf->eal_init_args, 2, 3);
- conf->eal_init_args[3] = (u8 *) "-n";
- tmp = format (0, "%d", conf->nchannels);
- conf->eal_init_args[4] = tmp;
+ tmp = format (0, "--file-prefix%c", 0);
+ vec_add1 (conf->eal_init_args, tmp);
+ tmp = format (0, "vpp%c", 0);
+ vec_add1 (conf->eal_init_args, tmp);
}
if (no_pci == 0 && geteuid () == 0)
dpdk_bind_devices_to_uio (conf);
+ if (no_vmbus == 0 && geteuid () == 0)
+ dpdk_bind_vmbus_devices_to_uio (conf);
+
#define _(x) \
if (devconf->x == 0 && conf->default_devconf.x > 0) \
devconf->x = conf->default_devconf.x ;
- /* *INDENT-OFF* */
- pool_foreach (devconf, conf->dev_confs, ({
+ pool_foreach (devconf, conf->dev_confs) {
/* default per-device config items */
foreach_dpdk_device_config_item
+ /* copy tso config from default device */
+ _ (tso)
+
+ /* copy tso config from default device */
+ _ (devargs)
+
+ /* copy rss_queues config from default device */
+ _ (rss_queues)
+
+ /* assume that default is PCI */
+ fmt_func = format_vlib_pci_addr;
+ fmt_addr = &devconf->pci_addr;
+
+ if (devconf->dev_addr_type == VNET_DEV_ADDR_VMBUS)
+ {
+ fmt_func = format_vlib_vmbus_addr;
+ fmt_addr = &devconf->vmbus_addr;
+ }
+
/* add DPDK EAL whitelist/blacklist entry */
if (num_whitelisted > 0 && devconf->is_blacklisted == 0)
{
- tmp = format (0, "-w%c", 0);
- vec_add1 (conf->eal_init_args, tmp);
- tmp = format (0, "%U%c", format_vlib_pci_addr, &devconf->pci_addr, 0);
+ tmp = format (0, "-a%c", 0);
vec_add1 (conf->eal_init_args, tmp);
+ if (devconf->devargs)
+ {
+ tmp =
+ format (0, "%U,%s%c", fmt_func, fmt_addr, devconf->devargs, 0);
+ }
+ else
+ {
+ tmp = format (0, "%U%c", fmt_func, fmt_addr, 0);
+ }
+ vec_add1 (conf->eal_init_args, tmp);
}
else if (num_whitelisted == 0 && devconf->is_blacklisted != 0)
{
tmp = format (0, "-b%c", 0);
vec_add1 (conf->eal_init_args, tmp);
- tmp = format (0, "%U%c", format_vlib_pci_addr, &devconf->pci_addr, 0);
+ tmp = format (0, "%U%c", fmt_func, fmt_addr, 0);
vec_add1 (conf->eal_init_args, tmp);
}
- }));
- /* *INDENT-ON* */
+ }
#undef _
- /* set master-lcore */
- tmp = format (0, "--master-lcore%c", 0);
- vec_add1 (conf->eal_init_args, tmp);
- tmp = format (0, "%u%c", tm->main_lcore, 0);
- vec_add1 (conf->eal_init_args, tmp);
-
- /* set socket-mem */
- if (!no_huge)
- {
- tmp = format (0, "--socket-mem%c", 0);
- vec_add1 (conf->eal_init_args, tmp);
- tmp = format (0, "%s%c", socket_mem, 0);
- vec_add1 (conf->eal_init_args, tmp);
- }
+ if (socket_mem)
+ clib_warning ("socket-mem argument is deprecated");
/* NULL terminate the "argv" vector, in case of stupidity */
vec_add1 (conf->eal_init_args, 0);
- _vec_len (conf->eal_init_args) -= 1;
+ vec_dec_len (conf->eal_init_args, 1);
/* Set up DPDK eal and packet mbuf pool early. */
- rte_log_set_global_level (log_level);
int log_fds[2] = { 0 };
if (pipe (log_fds) == 0)
{
- FILE *f = fdopen (log_fds[1], "a");
- if (f && rte_openlog_stream (f) == 0)
+ if (fcntl (log_fds[0], F_SETFL, O_NONBLOCK) == 0 &&
+ fcntl (log_fds[1], F_SETFL, O_NONBLOCK) == 0)
+ {
+ FILE *f = fdopen (log_fds[1], "a");
+ if (f && rte_openlog_stream (f) == 0)
+ {
+ clib_file_t t = { 0 };
+ t.read_function = dpdk_log_read_ready;
+ t.file_descriptor = log_fds[0];
+ t.description = format (0, "DPDK logging pipe");
+ clib_file_add (&file_main, &t);
+ }
+ }
+ else
{
- clib_file_t t = { 0 };
- t.read_function = dpdk_log_read_ready;
- t.file_descriptor = log_fds[0];
- t.description = format (0, "DPDK logging pipe");
- clib_file_add (&file_main, &t);
+ close (log_fds[0]);
+ close (log_fds[1]);
}
}
conf->eal_init_args_str = format (conf->eal_init_args_str, "%s ",
conf->eal_init_args[i]);
- dpdk_log_warn ("EAL init args: %s", conf->eal_init_args_str);
+ vec_terminate_c_string (conf->eal_init_args_str);
+
+ dpdk_log_notice ("EAL init args: %s", conf->eal_init_args_str);
ret = rte_eal_init (vec_len (conf->eal_init_args),
(char **) conf->eal_init_args);
+ if (ret < 0)
+ return clib_error_return (0, "rte_eal_init returned %d", ret);
+
+ /* enable the AVX-512 vPMDs in DPDK */
+ if (clib_cpu_supports_avx512_bitalg () &&
+ conf->max_simd_bitwidth == DPDK_MAX_SIMD_BITWIDTH_DEFAULT)
+ rte_vect_set_max_simd_bitwidth (RTE_VECT_SIMD_512);
+ else if (conf->max_simd_bitwidth != DPDK_MAX_SIMD_BITWIDTH_DEFAULT)
+ rte_vect_set_max_simd_bitwidth (conf->max_simd_bitwidth ==
+ DPDK_MAX_SIMD_BITWIDTH_256 ?
+ RTE_VECT_SIMD_256 :
+ RTE_VECT_SIMD_512);
/* lazy umount hugepages */
umount2 ((char *) huge_dir_path, MNT_DETACH);
rmdir ((char *) huge_dir_path);
vec_free (huge_dir_path);
- if (ret < 0)
- return clib_error_return (0, "rte_eal_init returned %d", ret);
-
- /* set custom ring memory allocator */
- {
- struct rte_mempool_ops *ops = NULL;
-
- ops = get_ops_by_name ("ring_sp_sc");
- ops->alloc = dpdk_ring_alloc;
-
- ops = get_ops_by_name ("ring_mp_sc");
- ops->alloc = dpdk_ring_alloc;
-
- ops = get_ops_by_name ("ring_sp_mc");
- ops->alloc = dpdk_ring_alloc;
-
- ops = get_ops_by_name ("ring_mp_mc");
- ops->alloc = dpdk_ring_alloc;
- }
-
/* main thread 1st */
- error = dpdk_buffer_pool_create (vm, conf->num_mbufs, rte_socket_id ());
- if (error)
+ if ((error = dpdk_buffer_pools_create (vm)))
return error;
- for (i = 0; i < RTE_MAX_LCORE; i++)
- {
- error = dpdk_buffer_pool_create (vm, conf->num_mbufs,
- rte_lcore_to_socket_id (i));
- if (error)
- return error;
- }
-
-done:
- return error;
+ return 0;
}
VLIB_CONFIG_FUNCTION (dpdk_config, "dpdk");
u32 hw_flags = 0;
u8 hw_flags_chg = 0;
- /* only update link state for PMD interfaces */
- if ((xd->flags & DPDK_DEVICE_FLAG_PMD) == 0)
- return;
-
xd->time_last_link_update = now ? now : xd->time_last_link_update;
- memset (&xd->link, 0, sizeof (xd->link));
+ clib_memset (&xd->link, 0, sizeof (xd->link));
rte_eth_link_get_nowait (xd->port_id, &xd->link);
if (LINK_STATE_ELOGS)
{
- vlib_main_t *vm = vlib_get_main ();
ELOG_TYPE_DECLARE (e) =
{
.format =
u8 old_link_state;
u8 new_link_state;
} *ed;
- ed = ELOG_DATA (&vm->elog_main, e);
+ ed = ELOG_DATA (&vlib_global_main.elog_main, e);
ed->sw_if_index = xd->sw_if_index;
ed->admin_up = (xd->flags & DPDK_DEVICE_FLAG_ADMIN_UP) != 0;
ed->old_link_state = (u8)
ed->new_link_state = (u8) xd->link.link_status;
}
- if ((xd->flags & (DPDK_DEVICE_FLAG_ADMIN_UP | DPDK_DEVICE_FLAG_BOND_SLAVE))
- && ((xd->link.link_status != 0) ^
- vnet_hw_interface_is_link_up (vnm, xd->hw_if_index)))
- {
- hw_flags_chg = 1;
- hw_flags |= (xd->link.link_status ? VNET_HW_INTERFACE_FLAG_LINK_UP : 0);
- }
+ hw_flags_chg = ((xd->link.link_duplex != prev_link.link_duplex) ||
+ (xd->link.link_status != prev_link.link_status));
+
+ if (xd->link.link_speed != prev_link.link_speed)
+ vnet_hw_interface_set_link_speed (vnm, xd->hw_if_index,
+ (xd->link.link_speed == UINT32_MAX) ?
+ UINT32_MAX :
+ xd->link.link_speed * 1000);
- if (hw_flags_chg || (xd->link.link_duplex != prev_link.link_duplex))
+ if (hw_flags_chg)
{
- hw_flags_chg = 1;
+ if (xd->link.link_status)
+ hw_flags |= VNET_HW_INTERFACE_FLAG_LINK_UP;
+
switch (xd->link.link_duplex)
{
- case ETH_LINK_HALF_DUPLEX:
+ case RTE_ETH_LINK_HALF_DUPLEX:
hw_flags |= VNET_HW_INTERFACE_FLAG_HALF_DUPLEX;
break;
- case ETH_LINK_FULL_DUPLEX:
+ case RTE_ETH_LINK_FULL_DUPLEX:
hw_flags |= VNET_HW_INTERFACE_FLAG_FULL_DUPLEX;
break;
default:
break;
}
- }
- if (hw_flags_chg || (xd->link.link_speed != prev_link.link_speed))
- {
- hw_flags_chg = 1;
- switch (xd->link.link_speed)
- {
- case ETH_SPEED_NUM_10M:
- hw_flags |= VNET_HW_INTERFACE_FLAG_SPEED_10M;
- break;
- case ETH_SPEED_NUM_100M:
- hw_flags |= VNET_HW_INTERFACE_FLAG_SPEED_100M;
- break;
- case ETH_SPEED_NUM_1G:
- hw_flags |= VNET_HW_INTERFACE_FLAG_SPEED_1G;
- break;
- case ETH_SPEED_NUM_2_5G:
- hw_flags |= VNET_HW_INTERFACE_FLAG_SPEED_2_5G;
- break;
- case ETH_SPEED_NUM_5G:
- hw_flags |= VNET_HW_INTERFACE_FLAG_SPEED_5G;
- break;
- case ETH_SPEED_NUM_10G:
- hw_flags |= VNET_HW_INTERFACE_FLAG_SPEED_10G;
- break;
- case ETH_SPEED_NUM_20G:
- hw_flags |= VNET_HW_INTERFACE_FLAG_SPEED_20G;
- break;
- case ETH_SPEED_NUM_25G:
- hw_flags |= VNET_HW_INTERFACE_FLAG_SPEED_25G;
- break;
- case ETH_SPEED_NUM_40G:
- hw_flags |= VNET_HW_INTERFACE_FLAG_SPEED_40G;
- break;
- case ETH_SPEED_NUM_50G:
- hw_flags |= VNET_HW_INTERFACE_FLAG_SPEED_50G;
- break;
- case ETH_SPEED_NUM_56G:
- hw_flags |= VNET_HW_INTERFACE_FLAG_SPEED_56G;
- break;
- case ETH_SPEED_NUM_100G:
- hw_flags |= VNET_HW_INTERFACE_FLAG_SPEED_100G;
- break;
- case 0:
- break;
- default:
- dpdk_log_warn ("unknown link speed %d", xd->link.link_speed);
- break;
- }
- }
- if (hw_flags_chg)
- {
+
if (LINK_STATE_ELOGS)
{
- vlib_main_t *vm = vlib_get_main ();
-
ELOG_TYPE_DECLARE (e) =
{
.format =
u32 sw_if_index;
u32 flags;
} *ed;
- ed = ELOG_DATA (&vm->elog_main, e);
+ ed = ELOG_DATA (&vlib_global_main.elog_main, e);
ed->sw_if_index = xd->sw_if_index;
ed->flags = hw_flags;
}
dpdk_process (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f)
{
clib_error_t *error;
- vnet_main_t *vnm = vnet_get_main ();
dpdk_main_t *dm = &dpdk_main;
- ethernet_main_t *em = ðernet_main;
dpdk_device_t *xd;
vlib_thread_main_t *tm = vlib_get_thread_main ();
- int i;
- int j;
+ vlib_worker_thread_barrier_sync (vm);
error = dpdk_lib_init (dm);
if (error)
clib_error_report (error);
+ if (dpdk_cryptodev_init)
+ {
+ error = dpdk_cryptodev_init (vm);
+ if (error)
+ {
+ vlib_log_warn (dpdk_main.log_cryptodev, "%U", format_clib_error,
+ error);
+ clib_error_free (error);
+ }
+ }
+
+ vlib_worker_thread_barrier_release (vm);
tm->worker_thread_release = 1;
f64 now = vlib_time_now (vm);
dpdk_update_link_state (xd, now);
}
- {
- /*
- * Extra set up for bond interfaces:
- * 1. Setup MACs for bond interfaces and their slave links which was set
- * in dpdk_device_setup() but needs to be done again here to take
- * effect.
- * 2. Set up info and register slave link state change callback handling.
- * 3. Set up info for bond interface related CLI support.
- */
-#if RTE_VERSION < RTE_VERSION_NUM(18, 5, 0, 0)
- int nports = rte_eth_dev_count ();
-#else
- int nports = rte_eth_dev_count_avail ();
-#endif
- if (nports > 0)
- {
- /* *INDENT-OFF* */
- RTE_ETH_FOREACH_DEV(i)
- {
- xd = NULL;
- for (j = 0; j < nports; j++)
- {
- if (dm->devices[j].port_id == i)
- {
- xd = &dm->devices[j];
- }
- }
- ASSERT (xd != NULL);
-
- if (xd->pmd == VNET_DPDK_PMD_BOND)
- {
- u8 addr[6];
- dpdk_portid_t slink[16];
- int nlink = rte_eth_bond_slaves_get (i, slink, 16);
- if (nlink > 0)
- {
- vnet_hw_interface_t *bhi;
- ethernet_interface_t *bei;
- int rv;
-
- /* Get MAC of 1st slave link */
- rte_eth_macaddr_get
- (slink[0], (struct ether_addr *) addr);
-
- /* Set MAC of bounded interface to that of 1st slave link */
- dpdk_log_info ("Set MAC for bond port %d BondEthernet%d",
- i, xd->bond_instance_num);
- rv = rte_eth_bond_mac_address_set
- (i, (struct ether_addr *) addr);
- if (rv)
- dpdk_log_warn ("Set MAC addr failure rv=%d", rv);
-
- /* Populate MAC of bonded interface in VPP hw tables */
- bhi = vnet_get_hw_interface
- (vnm, dm->devices[i].hw_if_index);
- bei = pool_elt_at_index
- (em->interfaces, bhi->hw_instance);
- clib_memcpy (bhi->hw_address, addr, 6);
- clib_memcpy (bei->address, addr, 6);
-
- /* Init l3 packet size allowed on bonded interface */
- bhi->max_packet_bytes = ETHERNET_MAX_PACKET_BYTES;
- while (nlink >= 1)
- { /* for all slave links */
- int slave = slink[--nlink];
- dpdk_device_t *sdev = &dm->devices[slave];
- vnet_hw_interface_t *shi;
- vnet_sw_interface_t *ssi;
- ethernet_interface_t *sei;
- /* Add MAC to all slave links except the first one */
- if (nlink)
- {
- dpdk_log_info ("Add MAC for slave port %d",
- slave);
- rv = rte_eth_dev_mac_addr_add
- (slave, (struct ether_addr *) addr, 0);
- if (rv)
- dpdk_log_warn ("Add MAC addr failure rv=%d",
- rv);
- }
- /* Setup slave link state change callback handling */
- rte_eth_dev_callback_register
- (slave, RTE_ETH_EVENT_INTR_LSC,
- dpdk_port_state_callback, NULL);
- dpdk_device_t *sxd = &dm->devices[slave];
- sxd->flags |= DPDK_DEVICE_FLAG_BOND_SLAVE;
- sxd->bond_port = i;
- /* Set slaves bitmap for bonded interface */
- bhi->bond_info = clib_bitmap_set
- (bhi->bond_info, sdev->hw_if_index, 1);
- /* Set MACs and slave link flags on slave interface */
- shi = vnet_get_hw_interface (vnm, sdev->hw_if_index);
- ssi = vnet_get_sw_interface (vnm, sdev->sw_if_index);
- sei = pool_elt_at_index
- (em->interfaces, shi->hw_instance);
- shi->bond_info = VNET_HW_INTERFACE_BOND_INFO_SLAVE;
- ssi->flags |= VNET_SW_INTERFACE_FLAG_BOND_SLAVE;
- clib_memcpy (shi->hw_address, addr, 6);
- clib_memcpy (sei->address, addr, 6);
- /* Set l3 packet size allowed as the lowest of slave */
- if (bhi->max_packet_bytes > shi->max_packet_bytes)
- bhi->max_packet_bytes = shi->max_packet_bytes;
- }
- }
- }
- }
- /* *INDENT-ON* */
- }
- }
-
while (1)
{
/*
{
dpdk_main_t *dm = &dpdk_main;
clib_error_t *error = 0;
- vlib_thread_main_t *tm = vlib_get_thread_main ();
/* verify that structs are cacheline aligned */
STATIC_ASSERT (offsetof (dpdk_device_t, cacheline0) == 0,
"Data in cache line 0 is bigger than cache line size");
STATIC_ASSERT (offsetof (frame_queue_trace_t, cacheline0) == 0,
"Cache line marker must be 1st element in frame_queue_trace_t");
- STATIC_ASSERT (RTE_CACHE_LINE_SIZE == 1 << CLIB_LOG2_CACHE_LINE_BYTES,
- "DPDK RTE CACHE LINE SIZE does not match with 1<<CLIB_LOG2_CACHE_LINE_BYTES");
- dm->vlib_main = vm;
- dm->vnet_main = vnet_get_main ();
+ dpdk_cli_reference ();
+
dm->conf = &dpdk_config_main;
- dm->conf->nchannels = 4;
- dm->conf->num_mbufs = dm->conf->num_mbufs ? dm->conf->num_mbufs : NB_MBUF;
vec_add1 (dm->conf->eal_init_args, (u8 *) "vnet");
- vec_validate (dm->recycle, tm->n_thread_stacks - 1);
-
- /* Default vlib_buffer_t flags, DISABLES tcp/udp checksumming... */
- dm->buffer_flags_template =
- (VLIB_BUFFER_TOTAL_LENGTH_VALID | VLIB_BUFFER_EXT_HDR_VALID
- | VNET_BUFFER_F_L4_CHECKSUM_COMPUTED |
- VNET_BUFFER_F_L4_CHECKSUM_CORRECT | VNET_BUFFER_F_L2_HDR_OFFSET_VALID);
-
dm->stat_poll_interval = DPDK_STATS_POLL_INTERVAL;
dm->link_state_poll_interval = DPDK_LINK_POLL_INTERVAL;
- /* init CLI */
- if ((error = vlib_call_init_function (vm, dpdk_cli_init)))
- return error;
-
dm->log_default = vlib_log_register_class ("dpdk", 0);
+ dm->log_cryptodev = vlib_log_register_class ("dpdk", "cryptodev");
return error;
}
VLIB_INIT_FUNCTION (dpdk_init);
+static clib_error_t *
+dpdk_worker_thread_init (vlib_main_t *vm)
+{
+ if (rte_thread_register () < 0)
+ clib_panic ("dpdk: cannot register thread %u - %s", vm->thread_index,
+ rte_strerror (rte_errno));
+ return 0;
+}
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
+VLIB_WORKER_INIT_FUNCTION (dpdk_worker_thread_init);