Skip to content

Commit

Permalink
netdev-dpdk: fix port addition for ports sharing same PCI id
Browse files Browse the repository at this point in the history
Some NICs have only one PCI address associated with multiple ports. This
patch extends the dpdk-devargs option's format to cater for such devices.

To achieve that, this patch uses a new syntax that will be adapted and
implemented in future DPDK release (likely, v18.05):
    http://dpdk.org/ml/archives/dev/2017-December/084234.html

And since it's the DPDK duty to parse the (complete and full) syntax
and this patch is more likely to serve as an intermediate workaround,
here I take a simpler and shorter syntax from it (note it's allowed to
have only one category being provided):
    class=eth,mac=00:11:22:33:44:55:66

Also, old compatibility is kept. Users can still go on with using the
PCI id to add a port (if that's enough for them). Meaning, this patch
will not break anything.

This patch is basically based on the one from Ciara:
    https://mail.openvswitch.org/pipermail/ovs-dev/2017-October/339496.html

Cc: Loftus Ciara <ciara.loftus@intel.com>
Cc: Thomas Monjalon <thomas@monjalon.net>
Cc: Kevin Traynor <ktraynor@redhat.com>
Signed-off-by: Yuanhan Liu <yliu@fridaylinux.org>
Signed-off-by: Ian Stokes <ian.stokes@intel.com>
  • Loading branch information
yuanhanliu authored and istokes committed Jan 26, 2018
1 parent f6f5055 commit 5e75881
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 15 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
70 changes: 55 additions & 15 deletions lib/netdev-dpdk.c
Expand Up @@ -1336,30 +1336,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

0 comments on commit 5e75881

Please sign in to comment.