net/tap: add persist option

The TAP device only lasts as long as the DPDK application that opened
it is running. This behavior is bad if the DPDK application needs
to be updated transparently without disturbing other services
using the tap device.

Add a persist feature to the TAP device. If this flag is set, the
kernel network device remains even if after the application has exited.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
Reviewed-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
This commit is contained in:
Stephen Hemminger 2022-08-09 12:34:11 -07:00 committed by Andrew Rybchenko
parent 8772bbfa71
commit 9b4b4d95bc
3 changed files with 38 additions and 8 deletions

View File

@ -83,6 +83,12 @@ can utilize that stack to handle the network protocols. Plus you would be able
to address the interface using an IP address assigned to the internal
interface.
Normally, when the DPDK application exits,
the TAP device is marked down and is removed.
But this behaviour can be overridden by the use of the persist flag, example::
--vdev=net_tap0,iface=tap0,persist ...
The TUN PMD allows user to create a TUN device on host. The PMD allows user
to transmit and receive packets via DPDK API calls with L3 header and payload.
The devices in host can be accessed via ``ifconfig`` or ``ip`` command. TUN

View File

@ -55,6 +55,7 @@
#define ETH_TAP_REMOTE_ARG "remote"
#define ETH_TAP_MAC_ARG "mac"
#define ETH_TAP_MAC_FIXED "fixed"
#define ETH_TAP_PERSIST_ARG "persist"
#define ETH_TAP_USR_MAC_FMT "xx:xx:xx:xx:xx:xx"
#define ETH_TAP_CMP_MAC_FMT "0123456789ABCDEFabcdef"
@ -93,6 +94,7 @@ static const char *valid_arguments[] = {
ETH_TAP_IFACE_ARG,
ETH_TAP_REMOTE_ARG,
ETH_TAP_MAC_ARG,
ETH_TAP_PERSIST_ARG,
NULL
};
@ -141,11 +143,14 @@ static int tap_intr_handle_set(struct rte_eth_dev *dev, int set);
* @param[in] is_keepalive
* Keepalive flag
*
* @param[in] persistent
* Mark device as persistent
*
* @return
* -1 on failure, fd on success
*/
static int
tun_alloc(struct pmd_internals *pmd, int is_keepalive)
tun_alloc(struct pmd_internals *pmd, int is_keepalive, int persistent)
{
struct ifreq ifr;
#ifdef IFF_MULTI_QUEUE
@ -195,6 +200,14 @@ tun_alloc(struct pmd_internals *pmd, int is_keepalive)
goto error;
}
/* Keep the device after application exit */
if (persistent && ioctl(fd, TUNSETPERSIST, 1) < 0) {
TAP_LOG(WARNING,
"Unable to set persist %s: %s",
ifr.ifr_name, strerror(errno));
goto error;
}
/*
* Name passed to kernel might be wildcard like dtun%d
* and need to find the resulting device.
@ -974,6 +987,7 @@ tap_mp_req_start_rxtx(const struct rte_mp_msg *request, __rte_unused const void
static int
tap_dev_stop(struct rte_eth_dev *dev)
{
struct pmd_internals *pmd = dev->data->dev_private;
int i;
for (i = 0; i < dev->data->nb_tx_queues; i++)
@ -982,7 +996,8 @@ tap_dev_stop(struct rte_eth_dev *dev)
dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED;
tap_intr_handle_set(dev, 0);
tap_link_set_down(dev);
if (!pmd->persist)
tap_link_set_down(dev);
return 0;
}
@ -1166,7 +1181,8 @@ tap_dev_close(struct rte_eth_dev *dev)
return 0;
}
tap_link_set_down(dev);
if (!internals->persist)
tap_link_set_down(dev);
if (internals->nlsk_fd != -1) {
tap_flow_flush(dev, NULL);
tap_flow_implicit_flush(internals, NULL);
@ -1554,7 +1570,7 @@ tap_setup_queue(struct rte_eth_dev *dev,
pmd->name, *other_fd, dir, qid, *fd);
} else {
/* Both RX and TX fds do not exist (equal -1). Create fd */
*fd = tun_alloc(pmd, 0);
*fd = tun_alloc(pmd, 0, 0);
if (*fd < 0) {
*fd = -1; /* restore original value */
TAP_LOG(ERR, "%s: tun_alloc() failed.", pmd->name);
@ -1959,7 +1975,7 @@ static const struct eth_dev_ops ops = {
static int
eth_dev_tap_create(struct rte_vdev_device *vdev, const char *tap_name,
char *remote_iface, struct rte_ether_addr *mac_addr,
enum rte_tuntap_type type)
enum rte_tuntap_type type, int persist)
{
int numa_node = rte_socket_id();
struct rte_eth_dev *dev;
@ -2051,7 +2067,7 @@ eth_dev_tap_create(struct rte_vdev_device *vdev, const char *tap_name,
* This keep-alive file descriptor will guarantee that the TUN device
* exists even when all of its queues are closed
*/
pmd->ka_fd = tun_alloc(pmd, 1);
pmd->ka_fd = tun_alloc(pmd, 1, persist);
if (pmd->ka_fd == -1) {
TAP_LOG(ERR, "Unable to create %s interface", tuntap_name);
goto error_exit;
@ -2071,6 +2087,9 @@ eth_dev_tap_create(struct rte_vdev_device *vdev, const char *tap_name,
goto error_exit;
}
/* Make network device persist after application exit */
pmd->persist = persist;
/*
* Set up everything related to rte_flow:
* - netlink socket
@ -2361,7 +2380,7 @@ rte_pmd_tun_probe(struct rte_vdev_device *dev)
TAP_LOG(DEBUG, "Initializing pmd_tun for %s", name);
ret = eth_dev_tap_create(dev, tun_name, remote_iface, 0,
ETH_TUNTAP_TYPE_TUN);
ETH_TUNTAP_TYPE_TUN, 0);
leave:
if (ret == -1) {
@ -2491,6 +2510,7 @@ rte_pmd_tap_probe(struct rte_vdev_device *dev)
struct rte_ether_addr user_mac = { .addr_bytes = {0} };
struct rte_eth_dev *eth_dev;
int tap_devices_count_increased = 0;
int persist = 0;
name = rte_vdev_device_name(dev);
params = rte_vdev_device_args(dev);
@ -2574,6 +2594,9 @@ rte_pmd_tap_probe(struct rte_vdev_device *dev)
if (ret == -1)
goto leave;
}
if (rte_kvargs_count(kvlist, ETH_TAP_PERSIST_ARG) == 1)
persist = 1;
}
}
pmd_link.link_speed = speed;
@ -2592,7 +2615,7 @@ rte_pmd_tap_probe(struct rte_vdev_device *dev)
tap_devices_count++;
tap_devices_count_increased = 1;
ret = eth_dev_tap_create(dev, tap_name, remote_iface, &user_mac,
ETH_TUNTAP_TYPE_TAP);
ETH_TUNTAP_TYPE_TAP, persist);
leave:
if (ret == -1) {

View File

@ -80,6 +80,7 @@ struct pmd_internals {
int flower_support; /* 1 if kernel supports, else 0 */
int flower_vlan_support; /* 1 if kernel supports, else 0 */
int rss_enabled; /* 1 if RSS is enabled, else 0 */
int persist; /* 1 if keep link up, else 0 */
/* implicit rules set when RSS is enabled */
int map_fd; /* BPF RSS map fd */
int bpf_fd[RTE_PMD_TAP_MAX_QUEUES];/* List of bpf fds per queue */