diff options
author | Ben Pfaff <blp@ovn.org> | 2018-01-27 09:26:35 -0800 |
---|---|---|
committer | Ben Pfaff <blp@ovn.org> | 2018-01-27 09:26:35 -0800 |
commit | d67ee81a301eba853e35af0d01dd01f7d853909b (patch) | |
tree | ec09f3ab61f772b4a808adea86b065e0a7fefeb7 /lib | |
parent | 31bd820c1d08ee89b353dab870d09e306758b53b (diff) | |
parent | ac1a9bb93fb1d2d60bae64aa7778a4c4c388c2dd (diff) | |
download | openvswitch-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.c | 5 | ||||
-rw-r--r-- | lib/dpdk.c | 8 | ||||
-rw-r--r-- | lib/dpdk.h | 1 | ||||
-rw-r--r-- | lib/netdev-dpdk.c | 92 |
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); |