#include <sys/mount.h>
#include <string.h>
#include <fcntl.h>
+#include <dirent.h>
#include <dpdk/device/dpdk_priv.h>
return !(xd->port_conf.rxmode.offloads & DEV_RX_OFFLOAD_KEEP_CRC);
}
+/* The funciton 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 ()
+{
+
+ 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);
+
+ if (dir_cache == NULL)
+ return -1;
+
+ while ((dp = readdir (dir_cache)) != NULL)
+ {
+ if (dp->d_type == DT_DIR)
+ {
+ u8 *p = NULL;
+ int level_cache = -1;
+
+ p = format (p, "%s/%s/%s", sys_cache_dir, dp->d_name, "level");
+ 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 clib_error_t *
dpdk_lib_init (dpdk_main_t * dm)
{
struct rte_eth_dev_info dev_info;
struct rte_pci_device *pci_dev;
struct rte_eth_link l;
+ dpdk_portid_t next_port_id;
dpdk_device_config_t *devconf = 0;
vlib_pci_addr_t pci_addr;
uword *p = 0;
devconf = &dm->conf->default_devconf;
/* Handle interface naming for devices with multiple ports sharing same PCI ID */
- if (pci_dev)
+ if (pci_dev &&
+ ((next_port_id = rte_eth_find_next (i + 1)) != RTE_MAX_ETHPORTS))
{
struct rte_eth_dev_info di = { 0 };
struct rte_pci_device *next_pci_dev;
- rte_eth_dev_info_get (i + 1, &di);
+ rte_eth_dev_info_get (next_port_id, &di);
next_pci_dev = di.device ? RTE_DEV_TO_PCI (di.device) : 0;
- if (pci_dev && next_pci_dev &&
+ if (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)
case VNET_DPDK_PMD_IGB:
case VNET_DPDK_PMD_IXGBE:
case VNET_DPDK_PMD_I40E:
+ case VNET_DPDK_PMD_ICE:
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_REDIRECT_TO_QUEUE |
VNET_FLOW_ACTION_BUFFER_ADVANCE |
VNET_FLOW_ACTION_COUNT | VNET_FLOW_ACTION_DROP;
if (devconf->num_rx_desc)
xd->nb_rx_desc = devconf->num_rx_desc;
+ else {
+
+ /* If num_rx_desc is not specified by VPP user, the current CPU is working
+ with 2M page and has no L3 cache, default num_rx_desc is changed to 512
+ from original 1024 to help reduce TLB misses.
+ */
+ if ((clib_mem_get_default_hugepage_size () == 2 << 20)
+ && check_l3cache() == 0)
+ xd->nb_rx_desc = 512;
+ }
if (devconf->num_tx_desc)
xd->nb_tx_desc = devconf->num_tx_desc;
- }
+ else {
+
+ /* If num_tx_desc is not specified by VPP user, the current CPU is working
+ with 2M page and has no L3 cache, default num_tx_desc is changed to 512
+ from original 1024 to help reduce TLB misses.
+ */
+ if ((clib_mem_get_default_hugepage_size () == 2 << 20)
+ && check_l3cache() == 0)
+ xd->nb_tx_desc = 512;
+ }
+ }
if (xd->pmd == VNET_DPDK_PMD_AF_PACKET)
{
}
/*
- * 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
+ * A note on Cisco VIC (PMD_ENIC) and VLAN:
+ *
+ * With Cisco VIC vNIC, every ingress packet is tagged. On a
+ * trunk vNIC (C series "standalone" server), packets on no VLAN
+ * are tagged with vlan 0. On an access vNIC (standalone or B
+ * series "blade" server), packets on the default/native VLAN
+ * are tagged with that vNIC's VLAN. VPP expects these packets
+ * to be untagged, and previously enabled VLAN strip on VIC by
+ * default. But it also broke vlan sub-interfaces.
+ *
+ * The VIC adapter has "untag default vlan" ingress VLAN rewrite
+ * mode, which removes tags from these packets. VPP now includes
+ * a local patch for the enic driver to use this untag mode, so
+ * enabling vlan stripping is no longer needed. In future, the
+ * driver + dpdk will have an API to set the mode after
+ * rte_eal_init. Then, this note and local patch will be
+ * removed.
+ */
+
+ /*
+ * VLAN stripping: default to VLAN strip disabled, unless specified
* otherwise in the startup config.
*/
- if (xd->pmd == VNET_DPDK_PMD_ENIC)
- {
- if (devconf->vlan_strip_offload != DPDK_DEVICE_VLAN_STRIP_OFF)
- vlan_strip = 1; /* remove vlan tag from VIC port by default */
- else
- dpdk_log_warn ("VLAN strip disabled for interface\n");
- }
- else if (devconf->vlan_strip_offload == DPDK_DEVICE_VLAN_STRIP_ON)
+ if (devconf->vlan_strip_offload == DPDK_DEVICE_VLAN_STRIP_ON)
vlan_strip = 1;
if (vlan_strip)
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");
+ dpdk_cli_reference ();
+
dm->vlib_main = vm;
dm->vnet_main = vnet_get_main ();
dm->conf = &dpdk_config_main;
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);
return error;
VLIB_INIT_FUNCTION (dpdk_init);
-
/*
* fd.io coding-style-patch-verification: ON
*