Skip to content

Commit

Permalink
Merge branch 'dpdk_merge' of https://github.com/istokes/ovs into HEAD
Browse files Browse the repository at this point in the history
  • Loading branch information
blp committed Jan 27, 2018
2 parents 31bd820 + ac1a9bb commit d67ee81
Show file tree
Hide file tree
Showing 8 changed files with 115 additions and 18 deletions.
12 changes: 12 additions & 0 deletions Documentation/howto/dpdk.rst
Expand Up @@ -48,6 +48,18 @@ number of dpdk devices found in the log file::
$ ovs-vsctl add-port br0 dpdk-p1 -- set Interface dpdk-p1 type=dpdk \
options:dpdk-devargs=0000:01:00.1

Some NICs (i.e. Mellanox ConnectX-3) have only one PCI address associated
with multiple ports. Using a PCI device like above won't work. Instead, below
usage is suggested::

$ ovs-vsctl add-port br0 dpdk-p0 -- set Interface dpdk-p0 type=dpdk \
options:dpdk-devargs="class=eth,mac=00:11:22:33:44:55:01"
$ ovs-vsctl add-port br0 dpdk-p1 -- set Interface dpdk-p1 type=dpdk \
options:dpdk-devargs="class=eth,mac=00:11:22:33:44:55:02"

Note: such syntax won't support hotplug. The hotplug is supposed to work with
future DPDK release, v18.05.

After the DPDK ports get added to switch, a polling thread continuously polls
DPDK devices and consumes 100% of the core, as can be checked from ``top`` and
``ps`` commands::
Expand Down
12 changes: 12 additions & 0 deletions Documentation/intro/install/dpdk.rst
Expand Up @@ -643,6 +643,18 @@ Limitations

.. _DPDK release notes: http://dpdk.org/doc/guides/rel_notes/release_17_11.html

- Upper bound MTU: DPDK device drivers differ in how the L2 frame for a
given MTU value is calculated e.g. i40e driver includes 2 x vlan headers in
MTU overhead, em driver includes 1 x vlan header, ixgbe driver does not
include a vlan header in overhead. Currently it is not possible for OVS
DPDK to know what upper bound MTU value is supported for a given device.
As such OVS DPDK must provision for the case where the L2 frame for a given
MTU includes 2 x vlan headers. This reduces the upper bound MTU value for
devices that do not include vlan headers in their L2 frames by 8 bytes e.g.
ixgbe devices upper bound MTU is reduced from 9710 to 9702. This work
around is temporary and is expected to be removed once a method is provided
by DPDK to query the upper bound MTU value for a given device.

Reporting Bugs
--------------

Expand Down
5 changes: 5 additions & 0 deletions lib/dpdk-stub.c
Expand Up @@ -54,3 +54,8 @@ dpdk_vhost_iommu_enabled(void)
{
return false;
}

void
print_dpdk_version(void)
{
}
8 changes: 8 additions & 0 deletions lib/dpdk.c
Expand Up @@ -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>
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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());
}
1 change: 1 addition & 0 deletions lib/dpdk.h
Expand Up @@ -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 */
92 changes: 75 additions & 17 deletions lib/netdev-dpdk.c
Expand Up @@ -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 *
Expand Down Expand Up @@ -1104,6 +1106,7 @@ netdev_dpdk_destruct(struct netdev *netdev)
}
}

netdev_dpdk_clear_xstats(dev);
free(dev->devargs);
common_destruct(dev);

Expand Down Expand Up @@ -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. */
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -1336,30 +1341,70 @@ netdev_dpdk_lookup_by_port_id(dpdk_port_t port_id)
return NULL;
}

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;
}

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion utilities/ovs-ctl.in
Expand Up @@ -72,7 +72,7 @@ set_hostname () {
set_system_ids () {
set ovs_vsctl set Open_vSwitch .

OVS_VERSION=`ovs-vswitchd --version | sed 's/.*) //;1q'`
OVS_VERSION=`ovs-vswitchd --version | awk '/Open vSwitch/{print $NF}'`
set "$@" ovs-version="$OVS_VERSION"

case $SYSTEM_ID in
Expand Down
1 change: 1 addition & 0 deletions vswitchd/ovs-vswitchd.c
Expand Up @@ -187,6 +187,7 @@ parse_options(int argc, char *argv[], char **unixctl_pathp)

case 'V':
ovs_print_version(0, 0);
print_dpdk_version();
exit(EXIT_SUCCESS);

case OPT_MLOCKALL:
Expand Down

0 comments on commit d67ee81

Please sign in to comment.