summaryrefslogtreecommitdiffstats
path: root/vnet
diff options
context:
space:
mode:
Diffstat (limited to 'vnet')
-rw-r--r--vnet/vnet/devices/dpdk/init.c358
1 files changed, 57 insertions, 301 deletions
diff --git a/vnet/vnet/devices/dpdk/init.c b/vnet/vnet/devices/dpdk/init.c
index 179386970cc..716377c198f 100644
--- a/vnet/vnet/devices/dpdk/init.c
+++ b/vnet/vnet/devices/dpdk/init.c
@@ -21,6 +21,8 @@
#include <vnet/ethernet/ethernet.h>
#include <vnet/devices/dpdk/dpdk.h>
#include <vlib/unix/physmem.h>
+#include <vlib/pci/pci.h>
+#include <vlib/unix/pci.h>
#include <stdio.h>
#include <stdlib.h>
@@ -723,196 +725,62 @@ dpdk_lib_init (dpdk_main_t * dm)
return 0;
}
-static clib_error_t *
-write_sys_fs (char * file_name, char * fmt, ...)
-{
- u8 * s;
- int fd;
-
- fd = open (file_name, O_WRONLY);
- if (fd < 0)
- return clib_error_return_unix (0, "open `%s'", file_name);
-
- va_list va;
- va_start (va, fmt);
- s = va_format (0, fmt, &va);
- va_end (va);
- vec_add1 (s, 0); // terminate c string
-
- if (write (fd, s, vec_len (s)) < 0)
- return clib_error_return_unix (0, "write '%s' to '%s'", s, file_name);
-
- vec_free (s);
- close (fd);
- return 0;
-}
-
-#define VIRTIO_PCI_NAME "virtio-pci"
-
-static clib_error_t * dpdk_bind_eth_kernel_drivers (vlib_main_t * vm,
- char * pci_dev_id,
- char * kernel_driver)
+static void
+dpdk_bind_devices_to_uio (dpdk_main_t * dm)
{
- dpdk_main_t * dm = &dpdk_main;
- unformat_input_t _in;
- unformat_input_t * in = &_in;
- clib_error_t * error = 0;
- u8 * line = 0, * modcmd = 0, * path = 0;
- u8 * pci_vid = 0, *pci_did = 0, * devname = 0;
- char *driver_name = kernel_driver;
- FILE * fp;
-
- /*
- * Bail out now if we're not running as root.
- * This allows non-privileged use of the packet generator, etc.
- */
- if (geteuid() != 0)
- return 0;
-
- /*
- * Get all ethernet pci device numbers for the device type specified.
- */
- modcmd = format (0, "lspci -nDd %s | grep 0200 | "
- "awk '{ print $1, $3 }'%c", pci_dev_id, 0);
- if ((fp = popen ((const char *)modcmd, "r")) == NULL)
- {
- error = clib_error_return_unix (0,
- "Unable to get %s ethernet pci devices.",
- pci_dev_id);
- goto done;
- }
-
- vec_validate (line, BUFSIZ);
- vec_validate (path, BUFSIZ);
- while (fgets ((char *)line, BUFSIZ, fp) != NULL)
- {
- struct stat st;
- u8 bind_uio = 1;
- line[strlen ((char *)line) - 1] = 0; // chomp trailing newline.
-
- unformat_init_string (in, (char *)line, strlen((char *)line) + 1);
- unformat(in, "%s %s:%s", &devname, &pci_vid, &pci_did);
- unformat_free (in);
-
- /*
- * Blacklist all ethernet interfaces in the
- * linux IP routing tables (route --inet --inet6)
- */
- if (strstr ((char *)dm->eth_if_blacklist, (char *)devname))
- continue;
-
- /*
- * If there are any devices whitelisted, then blacklist all devices
- * which are not explicitly whitelisted.
- */
- if (dm->eth_if_whitelist &&
- !strstr ((char *)dm->eth_if_whitelist, (char *)devname))
- continue;
-
-#ifdef NETMAP
- /*
- * Optimistically open the device as a netmap device.
- */
- if (eth_nm_open((char *)devname))
+ linux_pci_main_t * pm = &linux_pci_main;
+ clib_error_t * error;
+ vlib_pci_device_t * d;
+ pci_config_header_t * c;
+ u8 * pci_addr = 0;
+
+ pool_foreach (d, pm->pci_devs, ({
+ c = &d->config0.header;
+ vec_reset_length (pci_addr);
+ pci_addr = format (pci_addr, "%U%c", format_vlib_pci_addr, &d->bus_address, 0);
+
+ if (c->device_class != PCI_CLASS_NETWORK_ETHERNET)
+ continue;
+
+ /* if whitelist exists process only whitelisted devices */
+ if (dm->eth_if_whitelist &&
+ !strstr ((char *) dm->eth_if_whitelist, (char *) pci_addr))
+ continue;
+
+ /* virtio */
+ if (c->vendor_id == 0x1af4 && c->device_id == 0x1000)
+ ;
+ /* vmxnet3 */
+ else if (c->vendor_id == 0x15ad && c->device_id == 0x07b0)
+ ;
+ /* all Intel devices */
+ else if (c->vendor_id == 0x8086)
+ ;
+ /* Cisco VIC */
+ else if (c->vendor_id == 0x1137 && c->device_id == 0x0043)
+ ;
+ /* Chelsio T4/T5 */
+ else if (c->vendor_id == 0x1425 && (c->device_id & 0xe000) == 0x4000)
+ ;
+ else
+ {
+ clib_warning ("Unsupported Ethernet PCI device 0x%04x:0x%04x found "
+ "at PCI address %s\n", (u16) c->vendor_id, (u16) c->device_id,
+ pci_addr);
continue;
-#endif
-
- _vec_len (path) = 0;
- path = format (path, "/sys/bus/pci/devices/%s/driver/unbind%c",
- devname, 0);
-
- /*
- * If the device is bound to a driver...
- */
- if (stat ((const char *)path, &st) == 0)
- {
- u8 * device_path;
-
- /*
- * If the interface is not a virtio...
- */
- if (!driver_name || strcmp(driver_name, VIRTIO_PCI_NAME))
- {
- /*
- * If it is already bound to driver, don't unbind/bind it.
- */
- device_path = format (0, "/sys/bus/pci/drivers/%s/%s/device%c",
- driver_name, devname, 0);
- if (stat ((const char *)device_path, &st) == 0)
- bind_uio = 0;
-
- vec_free (device_path);
- }
-
- /*
- * unbind it from the current driver
- */
- if (bind_uio)
- {
- _vec_len (path) -= 1;
- path = format (path, "%c", 0);
- error = write_sys_fs ((char *)path, "%s", devname);
- if (error)
- goto done;
- }
- }
-
- /*
- * DAW-FIXME: The following bind/unbind dance is necessary for the dpdk
- * virtio poll-mode driver to work.
- */
-
- if (driver_name && !strcmp(driver_name, VIRTIO_PCI_NAME))
- {
- /*
- * bind interface to the native kernel module
- */
- _vec_len (path) = 0;
- path = format (path, "/sys/bus/pci/drivers/%s/bind%c",
- driver_name, 0);
- error = write_sys_fs ((char *)path, "%s", devname);
- if (error)
- goto done;
+ }
- /*
- * unbind interface from the native kernel module
- */
- _vec_len (path) -= 5;
- path = format (path, "unbind%c", 0);
- error = write_sys_fs ((char *)path, "%s", devname);
- if (error)
- goto done;
- }
+ error = vlib_pci_bind_to_uio (d, (char *) dm->uio_driver_name);
- /*
- * bind the interface to igb_uio
- */
- if (bind_uio)
- {
- _vec_len (path) = 0;
- path = format (path, "/sys/bus/pci/drivers/%s/new_id%c", driver_name, 0);
- error = write_sys_fs ((char *) path, "%s %s", pci_vid, pci_did);
-
- _vec_len (path) = 0;
- path = format (path, "/sys/bus/pci/drivers/%s/bind%c", driver_name, 0);
- error = write_sys_fs ((char *) path, "%s", devname);
- if (error)
- {
- error = 0;
- continue;
- }
- }
- }
-
- done:
- vec_free (line);
- vec_free (path);
- vec_free (devname);
- vec_free (pci_vid);
- vec_free (pci_did);
- vec_free (modcmd);
- pclose (fp);
- return error;
+ if (error)
+ {
+ if (!dm->eth_if_whitelist)
+ dm->eth_if_blacklist = format (dm->eth_if_blacklist, "%U ",
+ format_vlib_pci_addr, &d->bus_address);
+ clib_error_report (error);
+ }
+ }));
+ vec_free (pci_addr);
}
static u32
@@ -956,7 +824,6 @@ dpdk_config (vlib_main_t * vm, unformat_input_t * input)
u8 * s, * tmp = 0;
u8 * pci_dev_id = 0;
u8 * rte_cmd = 0, * ethname = 0;
- FILE * rte_fp;
u32 log_level;
int ret, i;
char * fmt;
@@ -1214,91 +1081,6 @@ dpdk_config (vlib_main_t * vm, unformat_input_t * input)
}
}
- /*
- * Blacklist all ethernet interfaces in the linux IP routing tables.
- */
- dm->eth_if_blacklist = format (0, "%c", 0);
- rte_cmd = format (0, "route --inet --inet6 -n|awk '{print $7}'|sort -u|"
- "egrep $(echo $(ls -1d /sys/class/net/*/device|"
- "cut -d/ -f5)|sed -s 's/ /|/g')%c", 0);
- if ((rte_fp = popen ((const char *)rte_cmd, "r")) == NULL)
- {
- error = clib_error_return_unix (0, "Unable to find blacklist ethernet"
- " interface(s) in linux routing tables.");
- goto rte_cmd_err;
-
- }
-
- vec_validate (ethname, BUFSIZ);
- while (fgets ((char *)ethname, BUFSIZ, rte_fp) != NULL)
- {
- FILE *rlnk_fp;
- u8 * rlnk_cmd = 0, * devname = 0;
-
- ethname[strlen ((char *)ethname) - 1] = 0; // chomp trailing newline.
-
- rlnk_cmd = format (0, "readlink /sys/class/net/%s%c",
- ethname, 0);
-
- if ((rlnk_fp = popen ((const char *)rlnk_cmd, "r")) == NULL)
- {
- error = clib_error_return_unix (0, "Unable to read %s link.",
- ethname);
- goto rlnk_cmd_err;
- }
-
- vec_validate (devname, BUFSIZ);
- while (fgets ((char *)devname, BUFSIZ, rlnk_fp) != NULL)
- {
- char * pci_id = 0;
-
- /*
- * Extract the device PCI ID name from the link. It is the first
- * PCI ID searching backwards from the end of the link pathname.
- * For example:
- * readlink /sys/class/net/eth0
- * ../../devices/pci0000:00/0000:00:0a.0/virtio4/net/eth0
- */
- for (pci_id = (char *)((devname + strlen((char *)devname)));
- ((u8 *)pci_id > devname) && *pci_id != '.'; pci_id--)
- ;
-
- /*
- * Verify that the field found is a valid PCI ID.
- */
- if ((*(pci_id - 1) == '.') || ((u8 *)(pci_id - 11) < devname) ||
- (*(pci_id - 11) != '/') || (*(pci_id - 3) != ':') ||
- (*(pci_id - 6) != ':'))
- {
- devname[strlen ((char *)devname) - 1] = 0; // chomp trailing newline.
- clib_warning ("Unable to extract %s PCI ID (0x%llx \"%s\") "
- "from 0x%llx \"%s\"", ethname, pci_id, pci_id,
- devname, devname);
- continue;
- }
-
- pci_id[2] = 0;
- pci_id -= 10;
-
- /* Don't blacklist any interfaces which have been whitelisted.
- */
- if (dm->eth_if_whitelist &&
- strstr ((char *)dm->eth_if_whitelist, (char *)pci_id))
- continue;
-
- _vec_len (dm->eth_if_blacklist) -= 1; // chomp trailing NULL.
- dm->eth_if_blacklist = format (dm->eth_if_blacklist, " %s%c",
- pci_id, 0);
- }
-
- rlnk_cmd_err:
- pclose (rlnk_fp);
- vec_free (rlnk_cmd);
- vec_free (devname);
- }
-
- rte_cmd_err:
- pclose (rte_fp);
vec_free (rte_cmd);
vec_free (ethname);
@@ -1336,6 +1118,9 @@ dpdk_config (vlib_main_t * vm, unformat_input_t * input)
dm->eal_init_args[4] = tmp;
}
+ if (no_pci == 0 && geteuid() == 0)
+ dpdk_bind_devices_to_uio(dm);
+
/*
* If there are whitelisted devices,
* add the whitelist option & device list to the dpdk arg list...
@@ -1365,35 +1150,6 @@ dpdk_config (vlib_main_t * vm, unformat_input_t * input)
vec_add1 (dm->eal_init_args, pci_dev_id);
}
- if (no_pci == 0)
- {
- /*
- * Bind Virtio pci devices to the igb_uio kernel driver.
- */
- error = dpdk_bind_eth_kernel_drivers (vm, "1af4:1000", VIRTIO_PCI_NAME);
- if (error)
- return error;
-
- /*
- * Bind vmxnet3 pci devices to the igb_uio kernel driver.
- */
- error = dpdk_bind_eth_kernel_drivers (vm, "15ad:07b0",
- (char *) dm->uio_driver_name);
- if (error)
- return error;
-
- /*
- * Bind Intel ethernet pci devices to igb_uio kernel driver.
- */
- error = dpdk_bind_eth_kernel_drivers (vm, "8086:",
- (char *) dm->uio_driver_name);
- /*
- * Bind Cisco VIC ethernet pci devices to igb_uio kernel driver.
- */
- error = dpdk_bind_eth_kernel_drivers (vm, "1137:0043",
- (char *) dm->uio_driver_name);
- }
-
/* set master-lcore */
tmp = format (0, "--master-lcore%c", 0);
vec_add1 (dm->eal_init_args, tmp);