dpdk: only look at PCI information on PCI devices

The rte_device is use as a base type of all DPDK devices.
It is not valid to use container_of to find PCI information
unless the bus of the rte_device is pci. Otherwise, the
pointer is looking at some other data, which may or may not
be zero.

This change introduces a helper function to get rte_pci_device
pointer. If device is on PCI bus it returns pointer to
rte_pci_device info, otherwise it returns NULL.

Change-Id: Ia7446006bb93a7a54844969f3b3dd3b918890dfd
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
diff --git a/src/plugins/dpdk/device/cli.c b/src/plugins/dpdk/device/cli.c
index 7e168af..7e20f56 100644
--- a/src/plugins/dpdk/device/cli.c
+++ b/src/plugins/dpdk/device/cli.c
@@ -68,10 +68,10 @@
 
   rte_eth_dev_info_get ((*xd)->port_id, &dev_info);
 
-  pci_dev = RTE_DEV_TO_PCI (dev_info.device);
+  pci_dev = dpdk_get_pci_device (&dev_info);
 
   if (pci_dev)
-    {				/* bonded interface has no pci info */
+    {
       vlib_pci_addr_t pci_addr;
 
       pci_addr.domain = pci_dev->addr.domain;
@@ -1286,7 +1286,7 @@
 
   rte_eth_dev_info_get (xd->port_id, &dev_info);
 
-  pci_dev = RTE_DEV_TO_PCI (dev_info.device);
+  pci_dev = dpdk_get_pci_device (&dev_info);
 
   if (pci_dev)
     {				/* bonded interface has no pci info */
@@ -1481,7 +1481,7 @@
 
   rte_eth_dev_info_get (xd->port_id, &dev_info);
 
-  pci_dev = RTE_DEV_TO_PCI (dev_info.device);
+  pci_dev = dpdk_get_pci_device (&dev_info);
 
   if (pci_dev)
     {				/* bonded interface has no pci info */
diff --git a/src/plugins/dpdk/device/common.c b/src/plugins/dpdk/device/common.c
index 8699dc8..b9ba161 100644
--- a/src/plugins/dpdk/device/common.c
+++ b/src/plugins/dpdk/device/common.c
@@ -345,6 +345,19 @@
   return dpdk_port_state_callback_inline (port_id, type, param);
 }
 
+/* If this device is PCI return pointer to info, otherwise NULL */
+struct rte_pci_device *
+dpdk_get_pci_device (const struct rte_eth_dev_info *info)
+{
+  const struct rte_bus *bus;
+
+  bus = rte_bus_find_by_device (info->device);
+  if (bus && !strcmp (bus->name, "pci"))
+    return RTE_DEV_TO_PCI (info->device);
+  else
+    return NULL;
+}
+
 /*
  * fd.io coding-style-patch-verification: ON
  *
diff --git a/src/plugins/dpdk/device/dpdk.h b/src/plugins/dpdk/device/dpdk.h
index 680425b..cc9b644 100644
--- a/src/plugins/dpdk/device/dpdk.h
+++ b/src/plugins/dpdk/device/dpdk.h
@@ -531,6 +531,9 @@
 clib_error_t *dpdk_buffer_pool_create (vlib_main_t * vm, unsigned num_mbufs,
 				       unsigned socket_id);
 
+struct rte_pci_device *dpdk_get_pci_device (const struct rte_eth_dev_info
+					    *info);
+
 #if CLI_DEBUG
 int dpdk_buffer_validate_trajectory_all (u32 * uninitialized);
 void dpdk_buffer_poison_trajectory_all (void);
diff --git a/src/plugins/dpdk/device/format.c b/src/plugins/dpdk/device/format.c
index a5c8daa..28e8f0a 100644
--- a/src/plugins/dpdk/device/format.c
+++ b/src/plugins/dpdk/device/format.c
@@ -273,9 +273,9 @@
     }
 
   rte_eth_dev_info_get (i, &dev_info);
-  pci_dev = RTE_DEV_TO_PCI (dev_info.device);
+  pci_dev = dpdk_get_pci_device (&dev_info);
 
-  if (pci_dev && dm->devices[i].port_type != VNET_DPDK_PORT_TYPE_FAILSAFE)
+  if (pci_dev)
     ret = format (s, devname_format, device_name, pci_dev->addr.bus,
 		  pci_dev->addr.devid, pci_dev->addr.function);
   else
@@ -575,7 +575,8 @@
       retval = rte_eth_dev_rss_hash_conf_get (xd->port_id, &rss_conf);
       if (retval < 0)
 	clib_warning ("rte_eth_dev_rss_hash_conf_get returned %d", retval);
-      pci = RTE_DEV_TO_PCI (di.device);
+
+      pci = dpdk_get_pci_device (&di);
 
       if (pci)
 	{
diff --git a/src/plugins/dpdk/device/init.c b/src/plugins/dpdk/device/init.c
index 5479f81..086d322 100644
--- a/src/plugins/dpdk/device/init.c
+++ b/src/plugins/dpdk/device/init.c
@@ -278,7 +278,8 @@
 			dev_info.driver_name);
 	  continue;
 	}
-      pci_dev = RTE_DEV_TO_PCI (dev_info.device);
+
+      pci_dev = dpdk_get_pci_device (&dev_info);
 
       if (pci_dev)	/* bonded interface has no pci info */
 	{