vnet: store hw interface speed in kbps instead of using flags
[vpp.git] / src / plugins / dpdk / device / init.c
index 7156e69..fcdc29b 100644 (file)
@@ -46,19 +46,6 @@ dpdk_config_main_t dpdk_config_main;
 
 /* 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,
-            },
-};
-
 static dpdk_port_type_t
 port_type_from_speed_capa (struct rte_eth_dev_info *dev_info)
 {
@@ -87,6 +74,35 @@ port_type_from_speed_capa (struct rte_eth_dev_info *dev_info)
   return VNET_DPDK_PORT_TYPE_UNKNOWN;
 }
 
+static dpdk_port_type_t
+port_type_from_link_speed (u32 link_speed)
+{
+  switch (link_speed)
+    {
+    case ETH_SPEED_NUM_1G:
+      return VNET_DPDK_PORT_TYPE_ETH_1G;
+    case ETH_SPEED_NUM_2_5G:
+      return VNET_DPDK_PORT_TYPE_ETH_2_5G;
+    case ETH_SPEED_NUM_5G:
+      return VNET_DPDK_PORT_TYPE_ETH_5G;
+    case ETH_SPEED_NUM_10G:
+      return VNET_DPDK_PORT_TYPE_ETH_10G;
+    case ETH_SPEED_NUM_20G:
+      return VNET_DPDK_PORT_TYPE_ETH_20G;
+    case ETH_SPEED_NUM_25G:
+      return VNET_DPDK_PORT_TYPE_ETH_25G;
+    case ETH_SPEED_NUM_40G:
+      return VNET_DPDK_PORT_TYPE_ETH_40G;
+    case ETH_SPEED_NUM_50G:
+      return VNET_DPDK_PORT_TYPE_ETH_50G;
+    case ETH_SPEED_NUM_56G:
+      return VNET_DPDK_PORT_TYPE_ETH_56G;
+    case ETH_SPEED_NUM_100G:
+      return VNET_DPDK_PORT_TYPE_ETH_100G;
+    default:
+      return VNET_DPDK_PORT_TYPE_UNKNOWN;
+    }
+}
 
 static u32
 dpdk_flag_change (vnet_main_t * vnm, vnet_hw_interface_t * hi, u32 flags)
@@ -107,9 +123,9 @@ dpdk_flag_change (vnet_main_t * vnm, vnet_hw_interface_t * hi, u32 flags)
       if (xd->flags & DPDK_DEVICE_FLAG_ADMIN_UP)
        {
          if (xd->flags & DPDK_DEVICE_FLAG_PROMISC)
-           rte_eth_promiscuous_enable (xd->device_index);
+           rte_eth_promiscuous_enable (xd->port_id);
          else
-           rte_eth_promiscuous_disable (xd->device_index);
+           rte_eth_promiscuous_disable (xd->port_id);
        }
     }
   else if (ETHERNET_INTERFACE_FLAG_CONFIG_MTU (flags))
@@ -129,12 +145,12 @@ dpdk_device_lock_init (dpdk_device_t * xd)
     {
       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);
+      clib_memset ((void *) xd->lockp[q], 0, CLIB_CACHE_LINE_BYTES);
     }
 }
 
 static struct rte_mempool_ops *
-get_ops_by_name (i8 * ops_name)
+get_ops_by_name (char *ops_name)
 {
   u32 i;
 
@@ -152,7 +168,7 @@ dpdk_ring_alloc (struct rte_mempool *mp)
 {
   u32 rg_flags = 0, count;
   i32 ret;
-  i8 rg_name[RTE_RING_NAMESIZE];
+  char rg_name[RTE_RING_NAMESIZE];
   struct rte_ring *r;
 
   ret = snprintf (rg_name, sizeof (rg_name), RTE_MEMPOOL_MZ_FORMAT, mp->name);
@@ -187,6 +203,18 @@ dpdk_ring_alloc (struct rte_mempool *mp)
   return 0;
 }
 
+static int
+dpdk_port_crc_strip_enabled (dpdk_device_t * xd)
+{
+#if RTE_VERSION < RTE_VERSION_NUM(18, 8, 0, 0)
+  return ! !(xd->port_conf.rxmode.hw_strip_crc);
+#elif RTE_VERSION < RTE_VERSION_NUM(18, 11, 0, 0)
+  return ! !(xd->port_conf.rxmode.offloads & DEV_RX_OFFLOAD_CRC_STRIP);
+#else
+  return !(xd->port_conf.rxmode.offloads & DEV_RX_OFFLOAD_KEEP_CRC);
+#endif
+}
+
 static clib_error_t *
 dpdk_lib_init (dpdk_main_t * dm)
 {
@@ -227,7 +255,8 @@ dpdk_lib_init (dpdk_main_t * dm)
   vec_validate_aligned (dm->devices_by_hqos_cpu, tm->n_vlib_mains - 1,
                        CLIB_CACHE_LINE_BYTES);
 
-  nports = rte_eth_dev_count ();
+  nports = rte_eth_dev_count_avail ();
+
   if (nports < 1)
     {
       dpdk_log_notice ("DPDK drivers found no ports...");
@@ -254,27 +283,41 @@ dpdk_lib_init (dpdk_main_t * dm)
       vnet_buffer (&ptd->buffer_template)->sw_if_index[VLIB_TX] = (u32) ~ 0;
     }
 
-  for (i = 0; i < nports; i++)
+  /* *INDENT-OFF* */
+  RTE_ETH_FOREACH_DEV(i)
     {
       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;
       dpdk_device_config_t *devconf = 0;
       vlib_pci_addr_t pci_addr;
       uword *p = 0;
 
+      if (!rte_eth_dev_is_valid_port(i))
+       continue;
+
       rte_eth_link_get_nowait (i, &l);
       rte_eth_dev_info_get (i, &dev_info);
-      if (dev_info.pci_dev)    /* bonded interface has no pci info */
+
+      if (dev_info.device == 0)
+       {
+         clib_warning ("DPDK bug: missing device info. Skipping %s device",
+                       dev_info.driver_name);
+         continue;
+       }
+
+      pci_dev = dpdk_get_pci_device (&dev_info);
+
+      if (pci_dev)     /* bonded interface has no pci info */
        {
-         pci_addr.domain = dev_info.pci_dev->addr.domain;
-         pci_addr.bus = dev_info.pci_dev->addr.bus;
-         pci_addr.slot = dev_info.pci_dev->addr.devid;
-         pci_addr.function = dev_info.pci_dev->addr.function;
-         p =
-           hash_get (dm->conf->device_config_index_by_pci_addr,
-                     pci_addr.as_u32);
+         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)
@@ -289,12 +332,15 @@ dpdk_lib_init (dpdk_main_t * dm)
       xd->cpu_socket = (i8) rte_eth_dev_socket_id (i);
 
       /* Handle interface naming for devices with multiple ports sharing same PCI ID */
-      if (dev_info.pci_dev)
+      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 (di.pci_dev && pci_addr.as_u32 != last_pci_addr.as_u32 &&
-             memcmp (&dev_info.pci_dev->addr, &di.pci_dev->addr,
+         next_pci_dev = di.device ? RTE_DEV_TO_PCI (di.device) : 0;
+         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");
@@ -319,21 +365,30 @@ dpdk_lib_init (dpdk_main_t * dm)
 
       if (dm->conf->no_multi_seg)
        {
+#if RTE_VERSION < RTE_VERSION_NUM(18, 8, 0, 0)
          xd->tx_conf.txq_flags |= ETH_TXQ_FLAGS_NOMULTSEGS;
-         port_conf_template.rxmode.jumbo_frame = 0;
-         port_conf_template.rxmode.enable_scatter = 0;
+         xd->port_conf.rxmode.jumbo_frame = 0;
+         xd->port_conf.rxmode.enable_scatter = 0;
+#else
+         xd->port_conf.txmode.offloads &= ~DEV_TX_OFFLOAD_MULTI_SEGS;
+         xd->port_conf.rxmode.offloads &= ~DEV_RX_OFFLOAD_JUMBO_FRAME;
+         xd->port_conf.rxmode.offloads &= ~DEV_RX_OFFLOAD_SCATTER;
+#endif
        }
       else
        {
+#if RTE_VERSION < RTE_VERSION_NUM(18, 8, 0, 0)
          xd->tx_conf.txq_flags &= ~ETH_TXQ_FLAGS_NOMULTSEGS;
-         port_conf_template.rxmode.jumbo_frame = 1;
-         port_conf_template.rxmode.enable_scatter = 1;
+         xd->port_conf.rxmode.jumbo_frame = 1;
+         xd->port_conf.rxmode.enable_scatter = 1;
+#else
+         xd->port_conf.txmode.offloads |= DEV_TX_OFFLOAD_MULTI_SEGS;
+         xd->port_conf.rxmode.offloads |= DEV_RX_OFFLOAD_JUMBO_FRAME;
+         xd->port_conf.rxmode.offloads |= DEV_RX_OFFLOAD_SCATTER;
+#endif
          xd->flags |= DPDK_DEVICE_FLAG_MAYBE_MULTISEG;
        }
 
-      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);
 
       if (devconf->num_tx_queues > 0
@@ -349,7 +404,17 @@ dpdk_lib_init (dpdk_main_t * dm)
            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;
+           {
+             u64 unsupported_bits;
+             xd->port_conf.rx_adv_conf.rss_conf.rss_hf = devconf->rss_fn;
+             unsupported_bits = xd->port_conf.rx_adv_conf.rss_conf.rss_hf;
+             unsupported_bits &= ~dev_info.flow_type_rss_offloads;
+             if (unsupported_bits)
+               dpdk_log_warn ("Unsupported RSS hash functions: %U",
+                              format_dpdk_rss_hf_name, unsupported_bits);
+           }
+         xd->port_conf.rx_adv_conf.rss_conf.rss_hf &=
+           dev_info.flow_type_rss_offloads;
        }
       else
        xd->rx_q_used = 1;
@@ -357,8 +422,8 @@ dpdk_lib_init (dpdk_main_t * dm)
       xd->flags |= DPDK_DEVICE_FLAG_PMD;
 
       /* workaround for drivers not setting driver_name */
-      if ((!dev_info.driver_name) && (dev_info.pci_dev))
-       dev_info.driver_name = dev_info.pci_dev->driver->driver.name;
+      if ((!dev_info.driver_name) && (pci_dev))
+       dev_info.driver_name = pci_dev->driver->driver.name;
 
       ASSERT (dev_info.driver_name);
 
@@ -395,7 +460,13 @@ dpdk_lib_init (dpdk_main_t * dm)
 
              if (dm->conf->no_tx_checksum_offload == 0)
                {
-                 xd->tx_conf.txq_flags &= ~ETH_TXQ_FLAGS_NOXSUMS;
+#if RTE_VERSION < RTE_VERSION_NUM(18, 8, 0, 0)
+                 xd->tx_conf.txq_flags &= ~(ETH_TXQ_FLAGS_NOXSUMUDP |
+                                                    ETH_TXQ_FLAGS_NOXSUMTCP);
+#else
+                 xd->port_conf.txmode.offloads |= DEV_TX_OFFLOAD_TCP_CKSUM;
+                 xd->port_conf.txmode.offloads |= DEV_TX_OFFLOAD_UDP_CKSUM;
+#endif
                  xd->flags |=
                    DPDK_DEVICE_FLAG_TX_OFFLOAD |
                    DPDK_DEVICE_FLAG_INTEL_PHDR_CKSUM;
@@ -406,6 +477,7 @@ dpdk_lib_init (dpdk_main_t * dm)
            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;
 
@@ -414,17 +486,29 @@ dpdk_lib_init (dpdk_main_t * dm)
            case VNET_DPDK_PMD_IXGBEVF:
            case VNET_DPDK_PMD_I40EVF:
              xd->port_type = VNET_DPDK_PORT_TYPE_ETH_VF;
+#if RTE_VERSION < RTE_VERSION_NUM(18, 8, 0, 0)
              xd->port_conf.rxmode.hw_strip_crc = 1;
+#elif RTE_VERSION < RTE_VERSION_NUM(18, 11, 0, 0)
+             xd->port_conf.rxmode.offloads |= DEV_RX_OFFLOAD_CRC_STRIP;
+#endif
              break;
 
            case VNET_DPDK_PMD_THUNDERX:
              xd->port_type = VNET_DPDK_PORT_TYPE_ETH_VF;
+#if RTE_VERSION < RTE_VERSION_NUM(18, 8, 0, 0)
              xd->port_conf.rxmode.hw_strip_crc = 1;
+#elif RTE_VERSION < RTE_VERSION_NUM(18, 11, 0, 0)
+             xd->port_conf.rxmode.offloads |= DEV_RX_OFFLOAD_CRC_STRIP;
+#endif
              break;
 
            case VNET_DPDK_PMD_ENA:
              xd->port_type = VNET_DPDK_PORT_TYPE_ETH_VF;
+#if RTE_VERSION < RTE_VERSION_NUM(18, 8, 0, 0)
              xd->port_conf.rxmode.enable_scatter = 0;
+#else
+             xd->port_conf.rxmode.offloads &= ~DEV_RX_OFFLOAD_SCATTER;
+#endif
              break;
 
            case VNET_DPDK_PMD_DPAA2:
@@ -442,7 +526,11 @@ dpdk_lib_init (dpdk_main_t * dm)
              /* Intel Red Rock Canyon */
            case VNET_DPDK_PMD_FM10K:
              xd->port_type = VNET_DPDK_PORT_TYPE_ETH_SWITCH;
+#if RTE_VERSION < RTE_VERSION_NUM(18, 8, 0, 0)
              xd->port_conf.rxmode.hw_strip_crc = 1;
+#elif RTE_VERSION < RTE_VERSION_NUM(18, 11, 0, 0)
+             xd->port_conf.rxmode.offloads |= DEV_RX_OFFLOAD_CRC_STRIP;
+#endif
              break;
 
              /* virtio */
@@ -455,7 +543,11 @@ dpdk_lib_init (dpdk_main_t * dm)
              /* vmxnet3 */
            case VNET_DPDK_PMD_VMXNET3:
              xd->port_type = VNET_DPDK_PORT_TYPE_ETH_1G;
+#if RTE_VERSION < RTE_VERSION_NUM(18, 8, 0, 0)
              xd->tx_conf.txq_flags |= ETH_TXQ_FLAGS_NOMULTSEGS;
+#else
+             xd->port_conf.txmode.offloads |= DEV_TX_OFFLOAD_MULTI_SEGS;
+#endif
              break;
 
            case VNET_DPDK_PMD_AF_PACKET:
@@ -480,6 +572,15 @@ dpdk_lib_init (dpdk_main_t * dm)
              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;
+
+           case VNET_DPDK_PMD_NETVSC:
+             xd->port_type = port_type_from_link_speed (l.link_speed);
+             break;
+
            default:
              xd->port_type = VNET_DPDK_PORT_TYPE_UNKNOWN;
            }
@@ -507,8 +608,8 @@ dpdk_lib_init (dpdk_main_t * dm)
       if (xd->tx_q_used < tm->n_vlib_mains)
        dpdk_device_lock_init (xd);
 
+      xd->port_id = i;
       xd->device_index = xd - dm->devices;
-      ASSERT (i == xd->device_index);
       xd->per_interface_next_index = ~0;
 
       /* assign interface to input thread */
@@ -589,7 +690,7 @@ dpdk_lib_init (dpdk_main_t * dm)
               * 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 &&
+             if (dpdk_port_crc_strip_enabled (xd) &&
                  (dev_info.max_rx_pktlen >= (ETHERNET_MAX_PACKET_BYTES +
                                              sizeof (ethernet_header_t) +
                                              4)))
@@ -602,13 +703,33 @@ dpdk_lib_init (dpdk_main_t * dm)
              max_rx_frame = ETHERNET_MAX_PACKET_BYTES;
              mtu = ETHERNET_MAX_PACKET_BYTES - sizeof (ethernet_header_t);
 
-             if (xd->port_conf.rxmode.hw_strip_crc &&
+             if (dpdk_port_crc_strip_enabled (xd) &&
                  (dev_info.max_rx_pktlen >= (ETHERNET_MAX_PACKET_BYTES + 4)))
                {
                  max_rx_frame += 4;
                }
            }
        }
+
+      if (xd->pmd == VNET_DPDK_PMD_FAILSAFE)
+       {
+         /* 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))
+           {
+             mtu = dev_mtu;
+             max_rx_frame = mtu + sizeof (ethernet_header_t);
+
+             if (dpdk_port_crc_strip_enabled (xd))
+               {
+                 max_rx_frame += 4;
+               }
+           }
+       }
+
       /*Set port rxmode config */
       xd->port_conf.rxmode.max_rx_pkt_len = max_rx_frame;
 
@@ -621,12 +742,10 @@ dpdk_lib_init (dpdk_main_t * dm)
        {
          int i;
          q = 0;
-         /* *INDENT-OFF* */
          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);
          }));
-         /* *INDENT-ON* */
        }
       else
        for (q = 0; q < xd->rx_q_used; q++)
@@ -647,7 +766,7 @@ dpdk_lib_init (dpdk_main_t * dm)
        }
 
       if (dm->conf->no_tx_checksum_offload == 0)
-       if (xd->flags & DPDK_DEVICE_FLAG_TX_OFFLOAD)
+       if (xd->flags & DPDK_DEVICE_FLAG_TX_OFFLOAD && hi != NULL)
          hi->flags |= VNET_HW_INTERFACE_FLAG_SUPPORTS_TX_L4_CKSUM_OFFLOAD;
 
       dpdk_device_setup (xd);
@@ -669,7 +788,7 @@ 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
-       * otherwis in the startup config.
+       * otherwise in the startup config.
        */
       if (xd->pmd == VNET_DPDK_PMD_ENIC)
        {
@@ -684,26 +803,34 @@ dpdk_lib_init (dpdk_main_t * dm)
       if (vlan_strip)
        {
          int vlan_off;
-         vlan_off = rte_eth_dev_get_vlan_offload (xd->device_index);
+         vlan_off = rte_eth_dev_get_vlan_offload (xd->port_id);
          vlan_off |= ETH_VLAN_STRIP_OFFLOAD;
+#if RTE_VERSION < RTE_VERSION_NUM(18, 8, 0, 0)
          xd->port_conf.rxmode.hw_vlan_strip = vlan_off;
-         if (rte_eth_dev_set_vlan_offload (xd->device_index, vlan_off) == 0)
+#else
+          if (vlan_off)
+           xd->port_conf.rxmode.offloads |= DEV_RX_OFFLOAD_VLAN_STRIP;
+         else
+           xd->port_conf.rxmode.offloads &= ~DEV_RX_OFFLOAD_VLAN_STRIP;
+#endif
+         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 (hi)
-       hi->max_l3_packet_bytes[VLIB_RX] = hi->max_l3_packet_bytes[VLIB_TX] =
-         xd->port_conf.rxmode.max_rx_pkt_len - sizeof (ethernet_header_t);
+       hi->max_packet_bytes = xd->port_conf.rxmode.max_rx_pkt_len
+         - sizeof (ethernet_header_t);
       else
        clib_warning ("hi NULL");
 
       if (dm->conf->no_multi_seg)
        mtu = mtu > ETHER_MAX_LEN ? ETHER_MAX_LEN : mtu;
 
-      rte_eth_dev_set_mtu (xd->device_index, mtu);
+      rte_eth_dev_set_mtu (xd->port_id, mtu);
     }
+  /* *INDENT-ON* */
 
   if (nb_desc > dm->conf->num_mbufs)
     dpdk_log_err ("%d mbufs allocated but total rx/tx ring size is %d\n",
@@ -715,6 +842,7 @@ dpdk_lib_init (dpdk_main_t * dm)
 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);
@@ -733,7 +861,7 @@ dpdk_bind_devices_to_uio (dpdk_config_main_t * conf)
       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);
@@ -760,7 +888,20 @@ dpdk_bind_devices_to_uio (dpdk_config_main_t * conf)
       ;
     /* 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)
       ;
@@ -780,7 +921,15 @@ dpdk_bind_devices_to_uio (dpdk_config_main_t * conf)
     /* Cavium Network Adapter */
     else if (d->vendor_id == 0x177d && d->device_id == 0x9712)
       ;
-    /* Mellanox  */
+    /* Cavium FastlinQ QL41000 Series */
+    else if (d->vendor_id == 0x1077 && d->device_id >= 0x8070 && d->device_id <= 0x8090)
+      ;
+    /* Mellanox mlx4 */
+    else if (d->vendor_id == 0x15b3 && d->device_id >= 0x1003 && d->device_id <= 0x1004)
+      {
+        continue;
+      }
+    /* Mellanox mlx5 */
     else if (d->vendor_id == 0x15b3 && d->device_id >= 0x1013 && d->device_id <= 0x101a)
       {
         continue;
@@ -793,7 +942,7 @@ dpdk_bind_devices_to_uio (dpdk_config_main_t * conf)
         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);
 
     if (error)
       {
@@ -906,7 +1055,7 @@ dpdk_device_config (dpdk_config_main_t * conf, vlib_pci_addr_t pci_addr,
           devconf->num_rx_queues)
     error =
       clib_error_return (0,
-                        "%U: number of worker threadds must be "
+                        "%U: number of worker threads must be "
                         "equal to number of rx queues", format_vlib_pci_addr,
                         &pci_addr);
 
@@ -948,7 +1097,6 @@ static clib_error_t *
 dpdk_config (vlib_main_t * vm, unformat_input_t * input)
 {
   clib_error_t *error = 0;
-  dpdk_main_t *dm = &dpdk_main;
   dpdk_config_main_t *conf = &dpdk_config_main;
   vlib_thread_main_t *tm = vlib_get_thread_main ();
   dpdk_device_config_t *devconf;
@@ -956,7 +1104,6 @@ dpdk_config (vlib_main_t * vm, unformat_input_t * input)
   unformat_input_t sub_input;
   uword x;
   u8 *s, *tmp = 0;
-  u8 *rte_cmd = 0, *ethname = 0;
   u32 log_level;
   int ret, i;
   int num_whitelisted = 0;
@@ -978,7 +1125,7 @@ dpdk_config (vlib_main_t * vm, unformat_input_t * input)
       /* Prime the pump */
       if (unformat (input, "no-hugetlb"))
        {
-         vec_add1 (conf->eal_init_args, (u8 *) "no-huge");
+         vec_add1 (conf->eal_init_args, (u8 *) "--no-huge");
          no_huge = 1;
        }
 
@@ -1028,6 +1175,8 @@ dpdk_config (vlib_main_t * vm, unformat_input_t * input)
 
          num_whitelisted++;
        }
+      else if (unformat (input, "num-mem-channels %d", &conf->nchannels))
+       conf->nchannels_set_manually = 0;
       else if (unformat (input, "num-mbufs %d", &conf->num_mbufs))
        ;
       else if (unformat (input, "uio-driver %s", &conf->uio_driver_name))
@@ -1040,8 +1189,6 @@ dpdk_config (vlib_main_t * vm, unformat_input_t * input)
          tmp = format (0, "--no-pci%c", 0);
          vec_add1 (conf->eal_init_args, tmp);
        }
-      else if (unformat (input, "poll-sleep %d", &dm->poll_sleep_usec))
-       ;
 
 #define _(a)                                    \
       else if (unformat(input, #a))             \
@@ -1150,15 +1297,18 @@ dpdk_config (vlib_main_t * vm, unformat_input_t * input)
          /* *INDENT-ON* */
        }
 
+      uword default_hugepage_sz = clib_mem_get_default_hugepage_size ();
       /* *INDENT-OFF* */
       clib_bitmap_foreach (c, tm->cpu_socket_bitmap, (
         {
          clib_error_t *e;
-
+         uword n_pages;
          vec_validate(mem_by_socket, c);
+         n_pages = round_pow2 ((uword) mem_by_socket[c]<<20,
+                               default_hugepage_sz);
+         n_pages /= default_hugepage_sz;
 
-         e = clib_sysfs_prealloc_hugepages(c, 2 << 10, mem_by_socket[c] / 2);
-         if (e)
+         if ((e = clib_sysfs_prealloc_hugepages(c, 0, n_pages)))
            clib_error_report (e);
       }));
       /* *INDENT-ON* */
@@ -1205,9 +1355,6 @@ dpdk_config (vlib_main_t * vm, unformat_input_t * input)
        }
     }
 
-  vec_free (rte_cmd);
-  vec_free (ethname);
-
   if (error)
     return error;
 
@@ -1282,10 +1429,13 @@ dpdk_config (vlib_main_t * vm, unformat_input_t * input)
   vec_add1 (conf->eal_init_args, tmp);
 
   /* set socket-mem */
-  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 (!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);
+    }
 
   /* NULL terminate the "argv" vector, in case of stupidity */
   vec_add1 (conf->eal_init_args, 0);
@@ -1297,14 +1447,22 @@ dpdk_config (vlib_main_t * vm, unformat_input_t * input)
   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[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]);
        }
     }
 
@@ -1376,8 +1534,8 @@ dpdk_update_link_state (dpdk_device_t * xd, f64 now)
     return;
 
   xd->time_last_link_update = now ? now : xd->time_last_link_update;
-  memset (&xd->link, 0, sizeof (xd->link));
-  rte_eth_link_get_nowait (xd->device_index, &xd->link);
+  clib_memset (&xd->link, 0, sizeof (xd->link));
+  rte_eth_link_get_nowait (xd->port_id, &xd->link);
 
   if (LINK_STATE_ELOGS)
     {
@@ -1426,54 +1584,10 @@ dpdk_update_link_state (dpdk_device_t * xd, f64 now)
          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 (xd->link.link_speed != prev_link.link_speed)
+    vnet_hw_interface_set_link_speed (vnm, xd->hw_if_index,
+                                     xd->link.link_speed * 1000);
+
   if (hw_flags_chg)
     {
       if (LINK_STATE_ELOGS)
@@ -1509,6 +1623,7 @@ dpdk_process (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f)
   dpdk_device_t *xd;
   vlib_thread_main_t *tm = vlib_get_thread_main ();
   int i;
+  int j;
 
   error = dpdk_lib_init (dm);
 
@@ -1532,14 +1647,21 @@ dpdk_process (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f)
      *  2. Set up info and register slave link state change callback handling.
      *  3. Set up info for bond interface related CLI support.
      */
-    int nports = rte_eth_dev_count ();
+    int nports = rte_eth_dev_count_avail ();
     if (nports > 0)
       {
-       for (i = 0; i < nports; i++)
+       /* *INDENT-OFF* */
+       RTE_ETH_FOREACH_DEV(i)
          {
-           xd = &dm->devices[i];
-           ASSERT (i == xd->device_index);
-           if (xd->pmd == VNET_DPDK_PMD_BOND)
+           xd = NULL;
+           for (j = 0; j < nports; j++)
+             {
+               if (dm->devices[j].port_id == i)
+                 {
+                   xd = &dm->devices[j];
+                 }
+             }
+           if (xd != NULL && xd->pmd == VNET_DPDK_PMD_BOND)
              {
                u8 addr[6];
                dpdk_portid_t slink[16];
@@ -1572,9 +1694,6 @@ dpdk_process (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f)
 
                    /* Init l3 packet size allowed on bonded interface */
                    bhi->max_packet_bytes = ETHERNET_MAX_PACKET_BYTES;
-                   bhi->max_l3_packet_bytes[VLIB_RX] =
-                     bhi->max_l3_packet_bytes[VLIB_TX] =
-                     ETHERNET_MAX_PACKET_BYTES - sizeof (ethernet_header_t);
                    while (nlink >= 1)
                      {         /* for all slave links */
                        int slave = slink[--nlink];
@@ -1613,18 +1732,13 @@ dpdk_process (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f)
                        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_l3_packet_bytes[VLIB_RX] >
-                           shi->max_l3_packet_bytes[VLIB_RX])
-                         bhi->max_l3_packet_bytes[VLIB_RX] =
-                           bhi->max_l3_packet_bytes[VLIB_TX] =
-                           shi->max_l3_packet_bytes[VLIB_RX];
-                       /* Set max 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* */
       }
   }
 
@@ -1670,7 +1784,6 @@ dpdk_init (vlib_main_t * vm)
 {
   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,
@@ -1680,6 +1793,8 @@ dpdk_init (vlib_main_t * vm)
                 "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 ();
@@ -1689,8 +1804,6 @@ dpdk_init (vlib_main_t * vm)
   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