MTU assigning to itself (Coverity)
[vpp.git] / src / plugins / dpdk / device / init.c
old mode 100755 (executable)
new mode 100644 (file)
index aca57a0..66678e6
@@ -37,6 +37,8 @@
 
 #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;
 
@@ -105,9 +107,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))
@@ -132,7 +134,7 @@ dpdk_device_lock_init (dpdk_device_t * xd)
 }
 
 static struct rte_mempool_ops *
-get_ops_by_name (i8 * ops_name)
+get_ops_by_name (char *ops_name)
 {
   u32 i;
 
@@ -150,7 +152,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);
@@ -205,8 +207,8 @@ dpdk_lib_init (dpdk_main_t * dm)
   uword *p_hqos;
 
   u32 next_hqos_cpu = 0;
-  u8 af_packet_port_id = 0;
-  u8 bond_ether_port_id = 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;
@@ -225,7 +227,12 @@ dpdk_lib_init (dpdk_main_t * dm)
   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...");
@@ -252,24 +259,42 @@ 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 RTE_VERSION < RTE_VERSION_NUM(18, 5, 0, 0)
+      pci_dev = dev_info.pci_dev;
+#else
+      if (dev_info.device == 0)
        {
-         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;
+         clib_warning ("DPDK bug: missing device info. Skipping  %s device",
+                       dev_info.driver_name);
+         continue;
+       }
+      pci_dev = RTE_DEV_TO_PCI (dev_info.device);
+#endif
+
+      if (pci_dev)     /* bonded interface has no pci info */
+       {
+         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);
@@ -287,12 +312,19 @@ 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,
+#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");
@@ -355,8 +387,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);
 
@@ -386,9 +418,6 @@ dpdk_lib_init (dpdk_main_t * dm)
            case VNET_DPDK_PMD_IXGBE:
            case VNET_DPDK_PMD_I40E:
              xd->port_type = port_type_from_speed_capa (&dev_info);
-#if 0
-             xd->port_conf.fdir_conf.mode = RTE_FDIR_MODE_PERFECT;
-#endif
              xd->supported_flow_actions = VNET_FLOW_ACTION_MARK |
                VNET_FLOW_ACTION_REDIRECT_TO_NODE |
                VNET_FLOW_ACTION_BUFFER_ADVANCE |
@@ -461,12 +490,12 @@ dpdk_lib_init (dpdk_main_t * dm)
 
            case VNET_DPDK_PMD_AF_PACKET:
              xd->port_type = VNET_DPDK_PORT_TYPE_AF_PACKET;
-             xd->port_id = af_packet_port_id++;
+             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->port_id = bond_ether_port_id++;
+             xd->bond_instance_num = bond_ether_instance_num++;
              break;
 
            case VNET_DPDK_PMD_VIRTIO_USER:
@@ -477,6 +506,15 @@ dpdk_lib_init (dpdk_main_t * dm)
              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;
            }
@@ -504,8 +542,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 */
@@ -606,6 +644,26 @@ dpdk_lib_init (dpdk_main_t * dm)
                }
            }
        }
+
+      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 (xd->port_conf.rxmode.hw_strip_crc)
+               {
+                 max_rx_frame += 4;
+               }
+           }
+       }
+
       /*Set port rxmode config */
       xd->port_conf.rxmode.max_rx_pkt_len = max_rx_frame;
 
@@ -618,12 +676,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++)
@@ -639,7 +695,7 @@ dpdk_lib_init (dpdk_main_t * dm)
        * ethernet_register_interface() above*/
       if (hi)
        {
-         hi->max_packet_bytes = max_rx_frame;
+         hi->max_packet_bytes = mtu;
          hi->max_supported_packet_bytes = max_rx_frame;
        }
 
@@ -681,23 +737,27 @@ 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;
          xd->port_conf.rxmode.hw_vlan_strip = vlan_off;
-         if (rte_eth_dev_set_vlan_offload (xd->device_index, vlan_off) == 0)
+         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");
 
-      rte_eth_dev_set_mtu (xd->device_index, mtu);
+      if (dm->conf->no_multi_seg)
+       mtu = mtu > ETHER_MAX_LEN ? ETHER_MAX_LEN : 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",
@@ -771,6 +831,9 @@ dpdk_bind_devices_to_uio (dpdk_config_main_t * conf)
     /* Amazen Elastic Network Adapter */
     else if (d->vendor_id == 0x1d0f && d->device_id >= 0xec20 && d->device_id <= 0xec21)
       ;
+    /* Cavium Network Adapter */
+    else if (d->vendor_id == 0x177d && d->device_id == 0x9712)
+      ;
     /* Mellanox  */
     else if (d->vendor_id == 0x15b3 && d->device_id >= 0x1013 && d->device_id <= 0x101a)
       {
@@ -1368,7 +1431,7 @@ dpdk_update_link_state (dpdk_device_t * xd, f64 now)
 
   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);
+  rte_eth_link_get_nowait (xd->port_id, &xd->link);
 
   if (LINK_STATE_ELOGS)
     {
@@ -1500,6 +1563,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);
 
@@ -1523,13 +1587,26 @@ 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.
      */
+#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)
       {
-       for (i = 0; i < nports; i++)
+       /* *INDENT-OFF* */
+       RTE_ETH_FOREACH_DEV(i)
          {
-           xd = &dm->devices[i];
-           ASSERT (i == xd->device_index);
+           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];
@@ -1547,7 +1624,7 @@ dpdk_process (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f)
 
                    /* Set MAC of bounded interface to that of 1st slave link */
                    dpdk_log_info ("Set MAC for bond port %d BondEthernet%d",
-                                  i, xd->port_id);
+                                  i, xd->bond_instance_num);
                    rv = rte_eth_bond_mac_address_set
                      (i, (struct ether_addr *) addr);
                    if (rv)
@@ -1563,9 +1640,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];
@@ -1604,18 +1678,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* */
       }
   }
 
@@ -1671,6 +1740,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 ();