summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorBen Pfaff <blp@ovn.org>2018-01-27 09:26:35 -0800
committerBen Pfaff <blp@ovn.org>2018-01-27 09:26:35 -0800
commitd67ee81a301eba853e35af0d01dd01f7d853909b (patch)
treeec09f3ab61f772b4a808adea86b065e0a7fefeb7 /lib
parent31bd820c1d08ee89b353dab870d09e306758b53b (diff)
parentac1a9bb93fb1d2d60bae64aa7778a4c4c388c2dd (diff)
downloadopenvswitch-d67ee81a301eba853e35af0d01dd01f7d853909b.tar.gz
Merge branch 'dpdk_merge' of https://github.com/istokes/ovs into HEAD
Diffstat (limited to 'lib')
-rw-r--r--lib/dpdk-stub.c5
-rw-r--r--lib/dpdk.c8
-rw-r--r--lib/dpdk.h1
-rw-r--r--lib/netdev-dpdk.c92
4 files changed, 89 insertions, 17 deletions
diff --git a/lib/dpdk-stub.c b/lib/dpdk-stub.c
index 36021807c..041cd0cbb 100644
--- a/lib/dpdk-stub.c
+++ b/lib/dpdk-stub.c
@@ -54,3 +54,8 @@ dpdk_vhost_iommu_enabled(void)
{
return false;
}
+
+void
+print_dpdk_version(void)
+{
+}
diff --git a/lib/dpdk.c b/lib/dpdk.c
index 6710d10fc..3f5a55fc1 100644
--- a/lib/dpdk.c
+++ b/lib/dpdk.c
@@ -24,6 +24,7 @@
#include <rte_log.h>
#include <rte_memzone.h>
+#include <rte_version.h>
#ifdef DPDK_PDUMP
#include <rte_mempool.h>
#include <rte_pdump.h>
@@ -471,6 +472,7 @@ dpdk_init(const struct smap *ovs_other_config)
static struct ovsthread_once once_enable = OVSTHREAD_ONCE_INITIALIZER;
if (ovsthread_once_start(&once_enable)) {
+ VLOG_INFO("Using %s", rte_version());
VLOG_INFO("DPDK Enabled - initializing...");
dpdk_init__(ovs_other_config);
enabled = true;
@@ -501,3 +503,9 @@ dpdk_set_lcore_id(unsigned cpu)
ovs_assert(cpu != NON_PMD_CORE_ID);
RTE_PER_LCORE(_lcore_id) = cpu;
}
+
+void
+print_dpdk_version(void)
+{
+ puts(rte_version());
+}
diff --git a/lib/dpdk.h b/lib/dpdk.h
index dc58d968a..b04153591 100644
--- a/lib/dpdk.h
+++ b/lib/dpdk.h
@@ -38,5 +38,6 @@ void dpdk_init(const struct smap *ovs_other_config);
void dpdk_set_lcore_id(unsigned cpu);
const char *dpdk_get_vhost_sock_dir(void);
bool dpdk_vhost_iommu_enabled(void);
+void print_dpdk_version(void);
#endif /* dpdk.h */
diff --git a/lib/netdev-dpdk.c b/lib/netdev-dpdk.c
index ac2e38e7e..d41f5aa51 100644
--- a/lib/netdev-dpdk.c
+++ b/lib/netdev-dpdk.c
@@ -452,6 +452,8 @@ struct netdev_rxq_dpdk {
static void netdev_dpdk_destruct(struct netdev *netdev);
static void netdev_dpdk_vhost_destruct(struct netdev *netdev);
+static void netdev_dpdk_clear_xstats(struct netdev_dpdk *dev);
+
int netdev_dpdk_get_vid(const struct netdev_dpdk *dev);
struct ingress_policer *
@@ -1104,6 +1106,7 @@ netdev_dpdk_destruct(struct netdev *netdev)
}
}
+ netdev_dpdk_clear_xstats(dev);
free(dev->devargs);
common_destruct(dev);
@@ -1169,7 +1172,7 @@ netdev_dpdk_dealloc(struct netdev *netdev)
}
static void
-netdev_dpdk_clear_xstats(struct netdev_dpdk *dev) OVS_REQUIRES(dev->mutex)
+netdev_dpdk_clear_xstats(struct netdev_dpdk *dev)
{
/* If statistics are already allocated, we have to
* reconfigure, as port_id could have been changed. */
@@ -1274,6 +1277,8 @@ netdev_dpdk_configure_xstats(struct netdev_dpdk *dev)
VLOG_WARN("Can't get XSTATS IDs for port: %"PRIu8,
dev->port_id);
}
+
+ free(rte_xstats);
}
}
} else {
@@ -1337,29 +1342,69 @@ netdev_dpdk_lookup_by_port_id(dpdk_port_t port_id)
}
static dpdk_port_t
+netdev_dpdk_get_port_by_mac(const char *mac_str)
+{
+ dpdk_port_t port_id;
+ struct eth_addr mac, port_mac;
+
+ if (!eth_addr_from_string(mac_str, &mac)) {
+ VLOG_ERR("invalid mac: %s", mac_str);
+ return DPDK_ETH_PORT_ID_INVALID;
+ }
+
+ RTE_ETH_FOREACH_DEV (port_id) {
+ struct ether_addr ea;
+
+ rte_eth_macaddr_get(port_id, &ea);
+ memcpy(port_mac.ea, ea.addr_bytes, ETH_ADDR_LEN);
+ if (eth_addr_equals(mac, port_mac)) {
+ return port_id;
+ }
+ }
+
+ return DPDK_ETH_PORT_ID_INVALID;
+}
+
+/*
+ * Normally, a PCI id is enough for identifying a specific DPDK port.
+ * However, for some NICs having multiple ports sharing the same PCI
+ * id, using PCI id won't work then.
+ *
+ * To fix that, here one more method is introduced: "class=eth,mac=$MAC".
+ *
+ * Note that the compatibility is fully kept: user can still use the
+ * PCI id for adding ports (when it's enough for them).
+ */
+static dpdk_port_t
netdev_dpdk_process_devargs(struct netdev_dpdk *dev,
const char *devargs, char **errp)
{
- /* Get the name up to the first comma. */
- char *name = xmemdup0(devargs, strcspn(devargs, ","));
+ char *name;
dpdk_port_t new_port_id = DPDK_ETH_PORT_ID_INVALID;
- if (rte_eth_dev_get_port_by_name(name, &new_port_id)
- || !rte_eth_dev_is_valid_port(new_port_id)) {
- /* Device not found in DPDK, attempt to attach it */
- if (!rte_eth_dev_attach(devargs, &new_port_id)) {
- /* Attach successful */
- dev->attached = true;
- VLOG_INFO("Device '%s' attached to DPDK", devargs);
- } else {
- /* Attach unsuccessful */
- new_port_id = DPDK_ETH_PORT_ID_INVALID;
- VLOG_WARN_BUF(errp, "Error attaching device '%s' to DPDK",
- devargs);
+ if (strncmp(devargs, "class=eth,mac=", 14) == 0) {
+ new_port_id = netdev_dpdk_get_port_by_mac(&devargs[14]);
+ } else {
+ name = xmemdup0(devargs, strcspn(devargs, ","));
+ if (rte_eth_dev_get_port_by_name(name, &new_port_id)
+ || !rte_eth_dev_is_valid_port(new_port_id)) {
+ /* Device not found in DPDK, attempt to attach it */
+ if (!rte_eth_dev_attach(devargs, &new_port_id)) {
+ /* Attach successful */
+ dev->attached = true;
+ VLOG_INFO("Device '%s' attached to DPDK", devargs);
+ } else {
+ /* Attach unsuccessful */
+ new_port_id = DPDK_ETH_PORT_ID_INVALID;
+ }
}
+ free(name);
+ }
+
+ if (new_port_id == DPDK_ETH_PORT_ID_INVALID) {
+ VLOG_WARN_BUF(errp, "Error attaching device '%s' to DPDK", devargs);
}
- free(name);
return new_port_id;
}
@@ -2134,7 +2179,18 @@ netdev_dpdk_set_mtu(struct netdev *netdev, int mtu)
{
struct netdev_dpdk *dev = netdev_dpdk_cast(netdev);
- if (MTU_TO_FRAME_LEN(mtu) > NETDEV_DPDK_MAX_PKT_LEN
+ /* XXX: Ensure that the overall frame length of the requested MTU does not
+ * surpass the NETDEV_DPDK_MAX_PKT_LEN. DPDK device drivers differ in how
+ * the L2 frame length is calculated for a given MTU when
+ * rte_eth_dev_set_mtu(mtu) is called e.g. i40e driver includes 2 x vlan
+ * headers, the em driver includes 1 x vlan header, the ixgbe driver does
+ * not include vlan headers. As such we should use
+ * MTU_TO_MAX_FRAME_LEN(mtu) which includes an additional 2 x vlan headers
+ * (8 bytes) for comparison. This avoids a failure later with
+ * rte_eth_dev_set_mtu(). This approach should be used until DPDK provides
+ * a method to retrieve the upper bound MTU for a given device.
+ */
+ if (MTU_TO_MAX_FRAME_LEN(mtu) > NETDEV_DPDK_MAX_PKT_LEN
|| mtu < ETHER_MIN_MTU) {
VLOG_WARN("%s: unsupported MTU %d\n", dev->up.name, mtu);
return EINVAL;
@@ -2359,6 +2415,8 @@ netdev_dpdk_get_custom_stats(const struct netdev *netdev,
* reconfigured */
netdev_dpdk_clear_xstats(dev);
}
+
+ free(values);
}
ovs_mutex_unlock(&dev->mutex);