mirror of
https://github.com/openvswitch/ovs
synced 2025-08-30 05:47:55 +00:00
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>
This commit is contained in:
parent
0fb03722ff
commit
b8374d0d04
@ -298,6 +298,33 @@ physical ports which in turn effects the non-tunnel traffic performance.
|
|||||||
So it is advised to turn off the Rx checksum offload for non-tunnel traffic use
|
So it is advised to turn off the Rx checksum offload for non-tunnel traffic use
|
||||||
cases to achieve the best performance.
|
cases to achieve the best performance.
|
||||||
|
|
||||||
|
.. _port-hotplug:
|
||||||
|
|
||||||
|
Port Hotplug
|
||||||
|
------------
|
||||||
|
|
||||||
|
OVS supports port hotplugging, allowing the use of ports that were not bound
|
||||||
|
to DPDK when vswitchd was started.
|
||||||
|
In order to attach a port, it has to be bound to DPDK using the
|
||||||
|
``dpdk_nic_bind.py`` script::
|
||||||
|
|
||||||
|
$ $DPDK_DIR/tools/dpdk_nic_bind.py --bind=igb_uio 0000:01:00.0
|
||||||
|
|
||||||
|
Then it can be attached to OVS::
|
||||||
|
|
||||||
|
$ ovs-appctl netdev-dpdk/attach 0000:01:00.0
|
||||||
|
|
||||||
|
At this point, the user can create a dpdk port using the ``add-port`` command.
|
||||||
|
|
||||||
|
It is also possible to detach a port from ovs, the user has to remove the
|
||||||
|
port using the del-port command, then it can be detached using::
|
||||||
|
|
||||||
|
$ ovs-appctl netdev-dpdk/detach dpdk0
|
||||||
|
|
||||||
|
This feature is not supported with VFIO and does not work with some NICs.
|
||||||
|
For more information please refer to the `DPDK Port Hotplug Framework
|
||||||
|
<http://dpdk.org/doc/guides/prog_guide/port_hotplug_framework.html#hotplug>`__.
|
||||||
|
|
||||||
.. _dpdk-ovs-in-guest:
|
.. _dpdk-ovs-in-guest:
|
||||||
|
|
||||||
OVS with DPDK Inside VMs
|
OVS with DPDK Inside VMs
|
||||||
|
1
NEWS
1
NEWS
@ -55,6 +55,7 @@ Post-v2.6.0
|
|||||||
which set the number of rx and tx descriptors to use for the given port.
|
which set the number of rx and tx descriptors to use for the given port.
|
||||||
* Support for DPDK v16.11.
|
* Support for DPDK v16.11.
|
||||||
* Support for rx checksum offload. Refer DPDK HOWTO for details.
|
* Support for rx checksum offload. Refer DPDK HOWTO for details.
|
||||||
|
* Port Hotplug is now supported.
|
||||||
- Fedora packaging:
|
- Fedora packaging:
|
||||||
* A package upgrade does not automatically restart OVS service.
|
* A package upgrade does not automatically restart OVS service.
|
||||||
- ovs-vswitchd/ovs-vsctl:
|
- ovs-vswitchd/ovs-vsctl:
|
||||||
|
@ -2357,6 +2357,82 @@ netdev_dpdk_set_admin_state(struct unixctl_conn *conn, int argc,
|
|||||||
unixctl_command_reply(conn, "OK");
|
unixctl_command_reply(conn, "OK");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
netdev_dpdk_attach(struct unixctl_conn *conn, int argc OVS_UNUSED,
|
||||||
|
const char *argv[], void *aux OVS_UNUSED)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
char *response;
|
||||||
|
uint8_t port_id;
|
||||||
|
|
||||||
|
ovs_mutex_lock(&dpdk_mutex);
|
||||||
|
|
||||||
|
ret = rte_eth_dev_attach(argv[1], &port_id);
|
||||||
|
if (ret < 0) {
|
||||||
|
response = xasprintf("Error attaching device '%s'", argv[1]);
|
||||||
|
ovs_mutex_unlock(&dpdk_mutex);
|
||||||
|
unixctl_command_reply_error(conn, response);
|
||||||
|
free(response);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
response = xasprintf("Device '%s' has been attached as 'dpdk%d'",
|
||||||
|
argv[1], port_id);
|
||||||
|
|
||||||
|
ovs_mutex_unlock(&dpdk_mutex);
|
||||||
|
unixctl_command_reply(conn, response);
|
||||||
|
free(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
netdev_dpdk_detach(struct unixctl_conn *conn, int argc OVS_UNUSED,
|
||||||
|
const char *argv[], void *aux OVS_UNUSED)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
char *response;
|
||||||
|
unsigned int parsed_port;
|
||||||
|
uint8_t port_id;
|
||||||
|
char devname[RTE_ETH_NAME_MAX_LEN];
|
||||||
|
|
||||||
|
ovs_mutex_lock(&dpdk_mutex);
|
||||||
|
|
||||||
|
ret = dpdk_dev_parse_name(argv[1], "dpdk", &parsed_port);
|
||||||
|
if (ret) {
|
||||||
|
response = xasprintf("'%s' is not a valid port", argv[1]);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
port_id = parsed_port;
|
||||||
|
|
||||||
|
struct netdev *netdev = netdev_from_name(argv[1]);
|
||||||
|
if (netdev) {
|
||||||
|
netdev_close(netdev);
|
||||||
|
response = xasprintf("Port '%s' is being used. Remove it before"
|
||||||
|
"detaching", argv[1]);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
rte_eth_dev_close(port_id);
|
||||||
|
|
||||||
|
ret = rte_eth_dev_detach(port_id, devname);
|
||||||
|
if (ret < 0) {
|
||||||
|
response = xasprintf("Port '%s' can not be detached", argv[1]);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
response = xasprintf("Port '%s' has been detached", argv[1]);
|
||||||
|
|
||||||
|
ovs_mutex_unlock(&dpdk_mutex);
|
||||||
|
unixctl_command_reply(conn, response);
|
||||||
|
free(response);
|
||||||
|
return;
|
||||||
|
|
||||||
|
error:
|
||||||
|
ovs_mutex_unlock(&dpdk_mutex);
|
||||||
|
unixctl_command_reply_error(conn, response);
|
||||||
|
free(response);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set virtqueue flags so that we do not receive interrupts.
|
* Set virtqueue flags so that we do not receive interrupts.
|
||||||
*/
|
*/
|
||||||
@ -2632,6 +2708,12 @@ netdev_dpdk_class_init(void)
|
|||||||
unixctl_command_register("netdev-dpdk/set-admin-state",
|
unixctl_command_register("netdev-dpdk/set-admin-state",
|
||||||
"[netdev] up|down", 1, 2,
|
"[netdev] up|down", 1, 2,
|
||||||
netdev_dpdk_set_admin_state, NULL);
|
netdev_dpdk_set_admin_state, NULL);
|
||||||
|
unixctl_command_register("netdev-dpdk/attach",
|
||||||
|
"pci address of device", 1, 1,
|
||||||
|
netdev_dpdk_attach, NULL);
|
||||||
|
unixctl_command_register("netdev-dpdk/detach",
|
||||||
|
"port", 1, 1,
|
||||||
|
netdev_dpdk_detach, NULL);
|
||||||
|
|
||||||
ovsthread_once_done(&once);
|
ovsthread_once_done(&once);
|
||||||
}
|
}
|
||||||
@ -2668,7 +2750,7 @@ dpdk_ring_create(const char dev_name[], unsigned int port_no,
|
|||||||
{
|
{
|
||||||
struct dpdk_ring *ring_pair;
|
struct dpdk_ring *ring_pair;
|
||||||
char *ring_name;
|
char *ring_name;
|
||||||
int err;
|
int port_id;
|
||||||
|
|
||||||
ring_pair = dpdk_rte_mzalloc(sizeof *ring_pair);
|
ring_pair = dpdk_rte_mzalloc(sizeof *ring_pair);
|
||||||
if (!ring_pair) {
|
if (!ring_pair) {
|
||||||
@ -2698,19 +2780,20 @@ dpdk_ring_create(const char dev_name[], unsigned int port_no,
|
|||||||
return ENOMEM;
|
return ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = rte_eth_from_rings(dev_name, &ring_pair->cring_rx, 1,
|
port_id = rte_eth_from_rings(dev_name, &ring_pair->cring_rx, 1,
|
||||||
&ring_pair->cring_tx, 1, SOCKET0);
|
&ring_pair->cring_tx, 1, SOCKET0);
|
||||||
|
|
||||||
if (err < 0) {
|
if (port_id < 0) {
|
||||||
rte_free(ring_pair);
|
rte_free(ring_pair);
|
||||||
return ENODEV;
|
return ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
ring_pair->user_port_id = port_no;
|
ring_pair->user_port_id = port_no;
|
||||||
ring_pair->eth_port_id = rte_eth_dev_count() - 1;
|
ring_pair->eth_port_id = port_id;
|
||||||
|
*eth_port_id = port_id;
|
||||||
|
|
||||||
ovs_list_push_back(&dpdk_ring_list, &ring_pair->list_node);
|
ovs_list_push_back(&dpdk_ring_list, &ring_pair->list_node);
|
||||||
|
|
||||||
*eth_port_id = ring_pair->eth_port_id;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user