Skip to content

Commit b8374d0

Browse files
mauriciovasquezbernalcloftus
authored andcommitted
netdev-dpdk: add hotplug support
In order to use dpdk ports in ovs they have to be bound to a DPDK compatible driver before ovs is started. This patch adds the possibility to hotplug (or hot-unplug) a device after ovs has been started. The implementation adds two appctl commands: netdev-dpdk/attach and netdev-dpdk/detach After the user attaches a new device, it has to be added to a bridge using the add-port command, similarly, before detaching a device, it has to be removed using the del-port command. Signed-off-by: Mauricio Vasquez B <mauricio.vasquezbernal@studenti.polito.it> Signed-off-by: Ciara Loftus <ciara.loftus@intel.com> Co-authored-by: Ciara Loftus <ciara.loftus@intel.com> Acked-by: Stephen Finucane <stephen@that.guru> # docs only Signed-off-by: Daniele Di Proietto <diproiettod@vmware.com>
1 parent 0fb0372 commit b8374d0

3 files changed

Lines changed: 117 additions & 6 deletions

File tree

Documentation/howto/dpdk.rst

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,33 @@ physical ports which in turn effects the non-tunnel traffic performance.
298298
So it is advised to turn off the Rx checksum offload for non-tunnel traffic use
299299
cases to achieve the best performance.
300300

301+
.. _port-hotplug:
302+
303+
Port Hotplug
304+
------------
305+
306+
OVS supports port hotplugging, allowing the use of ports that were not bound
307+
to DPDK when vswitchd was started.
308+
In order to attach a port, it has to be bound to DPDK using the
309+
``dpdk_nic_bind.py`` script::
310+
311+
$ $DPDK_DIR/tools/dpdk_nic_bind.py --bind=igb_uio 0000:01:00.0
312+
313+
Then it can be attached to OVS::
314+
315+
$ ovs-appctl netdev-dpdk/attach 0000:01:00.0
316+
317+
At this point, the user can create a dpdk port using the ``add-port`` command.
318+
319+
It is also possible to detach a port from ovs, the user has to remove the
320+
port using the del-port command, then it can be detached using::
321+
322+
$ ovs-appctl netdev-dpdk/detach dpdk0
323+
324+
This feature is not supported with VFIO and does not work with some NICs.
325+
For more information please refer to the `DPDK Port Hotplug Framework
326+
<http://dpdk.org/doc/guides/prog_guide/port_hotplug_framework.html#hotplug>`__.
327+
301328
.. _dpdk-ovs-in-guest:
302329

303330
OVS with DPDK Inside VMs

NEWS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ Post-v2.6.0
5555
which set the number of rx and tx descriptors to use for the given port.
5656
* Support for DPDK v16.11.
5757
* Support for rx checksum offload. Refer DPDK HOWTO for details.
58+
* Port Hotplug is now supported.
5859
- Fedora packaging:
5960
* A package upgrade does not automatically restart OVS service.
6061
- ovs-vswitchd/ovs-vsctl:

lib/netdev-dpdk.c

Lines changed: 89 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2357,6 +2357,82 @@ netdev_dpdk_set_admin_state(struct unixctl_conn *conn, int argc,
23572357
unixctl_command_reply(conn, "OK");
23582358
}
23592359

2360+
static void
2361+
netdev_dpdk_attach(struct unixctl_conn *conn, int argc OVS_UNUSED,
2362+
const char *argv[], void *aux OVS_UNUSED)
2363+
{
2364+
int ret;
2365+
char *response;
2366+
uint8_t port_id;
2367+
2368+
ovs_mutex_lock(&dpdk_mutex);
2369+
2370+
ret = rte_eth_dev_attach(argv[1], &port_id);
2371+
if (ret < 0) {
2372+
response = xasprintf("Error attaching device '%s'", argv[1]);
2373+
ovs_mutex_unlock(&dpdk_mutex);
2374+
unixctl_command_reply_error(conn, response);
2375+
free(response);
2376+
return;
2377+
}
2378+
2379+
response = xasprintf("Device '%s' has been attached as 'dpdk%d'",
2380+
argv[1], port_id);
2381+
2382+
ovs_mutex_unlock(&dpdk_mutex);
2383+
unixctl_command_reply(conn, response);
2384+
free(response);
2385+
}
2386+
2387+
static void
2388+
netdev_dpdk_detach(struct unixctl_conn *conn, int argc OVS_UNUSED,
2389+
const char *argv[], void *aux OVS_UNUSED)
2390+
{
2391+
int ret;
2392+
char *response;
2393+
unsigned int parsed_port;
2394+
uint8_t port_id;
2395+
char devname[RTE_ETH_NAME_MAX_LEN];
2396+
2397+
ovs_mutex_lock(&dpdk_mutex);
2398+
2399+
ret = dpdk_dev_parse_name(argv[1], "dpdk", &parsed_port);
2400+
if (ret) {
2401+
response = xasprintf("'%s' is not a valid port", argv[1]);
2402+
goto error;
2403+
}
2404+
2405+
port_id = parsed_port;
2406+
2407+
struct netdev *netdev = netdev_from_name(argv[1]);
2408+
if (netdev) {
2409+
netdev_close(netdev);
2410+
response = xasprintf("Port '%s' is being used. Remove it before"
2411+
"detaching", argv[1]);
2412+
goto error;
2413+
}
2414+
2415+
rte_eth_dev_close(port_id);
2416+
2417+
ret = rte_eth_dev_detach(port_id, devname);
2418+
if (ret < 0) {
2419+
response = xasprintf("Port '%s' can not be detached", argv[1]);
2420+
goto error;
2421+
}
2422+
2423+
response = xasprintf("Port '%s' has been detached", argv[1]);
2424+
2425+
ovs_mutex_unlock(&dpdk_mutex);
2426+
unixctl_command_reply(conn, response);
2427+
free(response);
2428+
return;
2429+
2430+
error:
2431+
ovs_mutex_unlock(&dpdk_mutex);
2432+
unixctl_command_reply_error(conn, response);
2433+
free(response);
2434+
}
2435+
23602436
/*
23612437
* Set virtqueue flags so that we do not receive interrupts.
23622438
*/
@@ -2632,6 +2708,12 @@ netdev_dpdk_class_init(void)
26322708
unixctl_command_register("netdev-dpdk/set-admin-state",
26332709
"[netdev] up|down", 1, 2,
26342710
netdev_dpdk_set_admin_state, NULL);
2711+
unixctl_command_register("netdev-dpdk/attach",
2712+
"pci address of device", 1, 1,
2713+
netdev_dpdk_attach, NULL);
2714+
unixctl_command_register("netdev-dpdk/detach",
2715+
"port", 1, 1,
2716+
netdev_dpdk_detach, NULL);
26352717

26362718
ovsthread_once_done(&once);
26372719
}
@@ -2668,7 +2750,7 @@ dpdk_ring_create(const char dev_name[], unsigned int port_no,
26682750
{
26692751
struct dpdk_ring *ring_pair;
26702752
char *ring_name;
2671-
int err;
2753+
int port_id;
26722754

26732755
ring_pair = dpdk_rte_mzalloc(sizeof *ring_pair);
26742756
if (!ring_pair) {
@@ -2698,19 +2780,20 @@ dpdk_ring_create(const char dev_name[], unsigned int port_no,
26982780
return ENOMEM;
26992781
}
27002782

2701-
err = rte_eth_from_rings(dev_name, &ring_pair->cring_rx, 1,
2702-
&ring_pair->cring_tx, 1, SOCKET0);
2783+
port_id = rte_eth_from_rings(dev_name, &ring_pair->cring_rx, 1,
2784+
&ring_pair->cring_tx, 1, SOCKET0);
27032785

2704-
if (err < 0) {
2786+
if (port_id < 0) {
27052787
rte_free(ring_pair);
27062788
return ENODEV;
27072789
}
27082790

27092791
ring_pair->user_port_id = port_no;
2710-
ring_pair->eth_port_id = rte_eth_dev_count() - 1;
2792+
ring_pair->eth_port_id = port_id;
2793+
*eth_port_id = port_id;
2794+
27112795
ovs_list_push_back(&dpdk_ring_list, &ring_pair->list_node);
27122796

2713-
*eth_port_id = ring_pair->eth_port_id;
27142797
return 0;
27152798
}
27162799

0 commit comments

Comments
 (0)