diff --git a/doc/guides/nics/tap.rst b/doc/guides/nics/tap.rst index 3d4564b046..2f7417bddd 100644 --- a/doc/guides/nics/tap.rst +++ b/doc/guides/nics/tap.rst @@ -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 diff --git a/drivers/net/tap/rte_eth_tap.c b/drivers/net/tap/rte_eth_tap.c index 1eafeb07fa..f2a6c33a19 100644 --- a/drivers/net/tap/rte_eth_tap.c +++ b/drivers/net/tap/rte_eth_tap.c @@ -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) { diff --git a/drivers/net/tap/rte_eth_tap.h b/drivers/net/tap/rte_eth_tap.h index 996021e424..5ac93f93e9 100644 --- a/drivers/net/tap/rte_eth_tap.h +++ b/drivers/net/tap/rte_eth_tap.h @@ -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 */