init / exit function ordering
[vpp.git] / src / plugins / dpdk / device / init.c
index 0999641..22ea659 100644 (file)
@@ -36,6 +36,7 @@
 #include <sys/mount.h>
 #include <string.h>
 #include <fcntl.h>
+#include <dirent.h>
 
 #include <dpdk/device/dpdk_priv.h>
 
@@ -157,6 +158,47 @@ dpdk_port_crc_strip_enabled (dpdk_device_t * xd)
   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)
 {
@@ -229,6 +271,7 @@ 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;
@@ -274,13 +317,14 @@ dpdk_lib_init (dpdk_main_t * dm)
        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)
@@ -388,9 +432,11 @@ dpdk_lib_init (dpdk_main_t * dm)
            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;
 
@@ -499,10 +545,30 @@ dpdk_lib_init (dpdk_main_t * dm)
 
          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)
        {
@@ -694,19 +760,30 @@ dpdk_lib_init (dpdk_main_t * dm)
        }
 
       /*
-       * 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)
@@ -1657,6 +1734,8 @@ dpdk_init (vlib_main_t * vm)
   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;
@@ -1674,10 +1753,6 @@ dpdk_init (vlib_main_t * vm)
   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;
@@ -1685,7 +1760,6 @@ dpdk_init (vlib_main_t * vm)
 
 VLIB_INIT_FUNCTION (dpdk_init);
 
-
 /*
  * fd.io coding-style-patch-verification: ON
  *