To check the link status, we use inotify to check if the file /sys/class/net/tapX/flags is modified.
Signed-off-by: Jianfeng Tan <jianfeng....@intel.com> --- drivers/net/virtio/virtio_ethdev.c | 27 ++++++++++++++++-------- drivers/net/virtio/virtio_user/virtio_user_dev.c | 24 +++++++++++++++++++++ drivers/net/virtio/virtio_user/virtio_user_dev.h | 2 ++ drivers/net/virtio/virtio_user_ethdev.c | 16 ++++++++++++++ 4 files changed, 60 insertions(+), 9 deletions(-) diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c index 58b20eb..1069219 100644 --- a/drivers/net/virtio/virtio_ethdev.c +++ b/drivers/net/virtio/virtio_ethdev.c @@ -1292,10 +1292,9 @@ virtio_configure_intr(struct rte_eth_dev *dev) } } - /* Re-register callback to update max_intr */ - rte_intr_callback_unregister(dev->intr_handle, - virtio_interrupt_handler, - dev); + /* Temporarily register callback as rte_intr_enable will use max_intr of + * intr_handle on intr_sources. + */ rte_intr_callback_register(dev->intr_handle, virtio_interrupt_handler, dev); @@ -1322,6 +1321,9 @@ virtio_configure_intr(struct rte_eth_dev *dev) return -1; } + rte_intr_callback_unregister(dev->intr_handle, + virtio_interrupt_handler, + dev); return 0; } @@ -1335,6 +1337,13 @@ virtio_init_device(struct rte_eth_dev *eth_dev, uint64_t req_features) struct rte_pci_device *pci_dev = NULL; int ret; + /* Callback could have been registered by last initialization, + * unregister it. + */ + rte_intr_callback_unregister(eth_dev->intr_handle, + virtio_interrupt_handler, + eth_dev); + /* Reset the device although not necessary at startup */ vtpci_reset(hw); @@ -1436,6 +1445,11 @@ virtio_init_device(struct rte_eth_dev *eth_dev, uint64_t req_features) eth_dev->data->port_id, pci_dev->id.vendor_id, pci_dev->id.device_id); + /* Setup interrupt callback */ + if (eth_dev->data->dev_flags & RTE_ETH_DEV_INTR_LSC) + rte_intr_callback_register(eth_dev->intr_handle, + virtio_interrupt_handler, eth_dev); + return 0; } @@ -1546,11 +1560,6 @@ eth_virtio_dev_init(struct rte_eth_dev *eth_dev) if (ret < 0) return ret; - /* Setup interrupt callback */ - if (eth_dev->data->dev_flags & RTE_ETH_DEV_INTR_LSC) - rte_intr_callback_register(eth_dev->intr_handle, - virtio_interrupt_handler, eth_dev); - return 0; } diff --git a/drivers/net/virtio/virtio_user/virtio_user_dev.c b/drivers/net/virtio/virtio_user/virtio_user_dev.c index 2d79818..a331c37 100644 --- a/drivers/net/virtio/virtio_user/virtio_user_dev.c +++ b/drivers/net/virtio/virtio_user/virtio_user_dev.c @@ -42,6 +42,7 @@ #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> +#include <sys/inotify.h> #include "vhost.h" #include "virtio_user_dev.h" @@ -160,6 +161,24 @@ virtio_user_fill_intr_handle(struct virtio_user_dev *dev, uint8_t portid) eth_dev->intr_handle->type = RTE_INTR_HANDLE_VDEV; if (dev->vhostfd >= 0) eth_dev->intr_handle->fd = dev->vhostfd; + else { + char path[PATH_MAX]; + + snprintf(path, PATH_MAX, "/sys/class/net/%s/flags", dev->ifname); + + dev->fd_inotify = inotify_init1(IN_NONBLOCK); + if (dev->fd_inotify == -1) + return; + + if (inotify_add_watch(dev->fd_inotify, path, IN_MODIFY) == -1) { + close(dev->fd_inotify); + dev->fd_inotify = -1; + return; + } + + dev->fd_tap_flags = open(path, O_RDONLY); + eth_dev->intr_handle->fd = dev->fd_inotify; + } } int @@ -219,6 +238,11 @@ int virtio_user_stop_device(struct virtio_user_dev *dev) for (i = 0; i < dev->max_queue_pairs; ++i) dev->ops->enable_qp(dev, i, 0); + if (dev->fd_inotify >= 0) + close(dev->fd_inotify); + if (dev->fd_tap_flags >= 0) + close(dev->fd_tap_flags); + free(dev->ifname); dev->ifname = NULL; diff --git a/drivers/net/virtio/virtio_user/virtio_user_dev.h b/drivers/net/virtio/virtio_user/virtio_user_dev.h index 3b529f0..dba8254 100644 --- a/drivers/net/virtio/virtio_user/virtio_user_dev.h +++ b/drivers/net/virtio/virtio_user/virtio_user_dev.h @@ -47,6 +47,8 @@ struct virtio_user_dev { char *ifname; int *vhostfds; int *tapfds; + int fd_inotify; + int fd_tap_flags; /* for both vhost_user and vhost_kernel */ int callfds[VIRTIO_MAX_VIRTQUEUES * 2 + 1]; diff --git a/drivers/net/virtio/virtio_user_ethdev.c b/drivers/net/virtio/virtio_user_ethdev.c index 14f4a5c..f2dd505 100644 --- a/drivers/net/virtio/virtio_user_ethdev.c +++ b/drivers/net/virtio/virtio_user_ethdev.c @@ -95,6 +95,22 @@ virtio_user_read_dev_config(struct virtio_hw *hw, size_t offset, dev->status |= VIRTIO_NET_S_LINK_UP; } fcntl(dev->vhostfd, F_SETFL, flags & (~O_NONBLOCK)); + } else { + uint64_t flags = 0; + + while (read(dev->fd_inotify, buf, sizeof buf) > 0) {}; + + lseek(dev->fd_tap_flags, 0, SEEK_SET); + if (read(dev->fd_tap_flags, buf, 128) > 0) { + char *end; + + flags = strtoll(buf, &end, 16); + } + + if (flags & 1) + dev->status |= VIRTIO_NET_S_LINK_UP; + else + dev->status &= (~VIRTIO_NET_S_LINK_UP); } *(uint16_t *)dst = dev->status; } -- 2.7.4