From: Jianfeng Tan Date: Fri, 31 Mar 2017 19:44:58 +0000 (+0000) Subject: net/virtio-user: support LSC X-Git-Tag: spdx-start~3901 X-Git-Url: http://git.droids-corp.org/?p=dpdk.git;a=commitdiff_plain;h=ef53b60300393c5d98c8d55a54b5e45a38cc914d net/virtio-user: support LSC So far, virtio-user with vhost-user as the backend can only support client mode. So when vhost user backend is down, i.e., unix socket connection is broken, the connection cannot be re-connected. We will forcely set the link state to be down. Note: virtio-user with vhost-kernel as the backend still cannot support lsc now as we fail to find a way to monitor the backend, tap device, up/down events. Signed-off-by: Jianfeng Tan Acked-by: Yuanhan Liu --- diff --git a/doc/guides/rel_notes/release_17_05.rst b/doc/guides/rel_notes/release_17_05.rst index d7ea0df133..f3e152bc12 100644 --- a/doc/guides/rel_notes/release_17_05.rst +++ b/doc/guides/rel_notes/release_17_05.rst @@ -163,11 +163,12 @@ New Features * **Added interrupt mode support for virtio-user.** - Implemented Rxq interrupt mode support for virtio-user as a virtual + Implemented Rxq interrupt mode and LSC support for virtio-user as a virtual device. Supported cases: * Rxq interrupt for virtio-user + vhost-user as the backend. * Rxq interrupt for virtio-user + vhost-kernel as the backend. + * LSC interrupt for virtio-user + vhost-user as the backend. Resolved Issues @@ -224,6 +225,11 @@ Known Issues Also, make sure to start the actual text at the margin. ========================================================= +* **LSC interrupt cannot work for virtio-user + vhost-kernel.** + + LSC interrupt cannot be detected when setting the backend, tap device, + up/down as we fail to find a way to monitor such event. + API Changes ----------- diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c index d9986ab52e..6a9568f2c4 100644 --- a/drivers/net/virtio/virtio_ethdev.c +++ b/drivers/net/virtio/virtio_ethdev.c @@ -1205,7 +1205,7 @@ virtio_negotiate_features(struct virtio_hw *hw, uint64_t req_features) * Process Virtio Config changed interrupt and call the callback * if link state changed. */ -static void +void virtio_interrupt_handler(struct rte_intr_handle *handle, void *param) { diff --git a/drivers/net/virtio/virtio_ethdev.h b/drivers/net/virtio/virtio_ethdev.h index aa78adc2b8..4009c4d91d 100644 --- a/drivers/net/virtio/virtio_ethdev.h +++ b/drivers/net/virtio/virtio_ethdev.h @@ -113,4 +113,6 @@ uint16_t virtio_xmit_pkts_simple(void *tx_queue, struct rte_mbuf **tx_pkts, int eth_virtio_dev_init(struct rte_eth_dev *eth_dev); +void virtio_interrupt_handler(struct rte_intr_handle *handle, void *param); + #endif /* _VIRTIO_ETHDEV_H_ */ diff --git a/drivers/net/virtio/virtio_user_ethdev.c b/drivers/net/virtio/virtio_user_ethdev.c index 7da9f6f675..35717f7fe9 100644 --- a/drivers/net/virtio/virtio_user_ethdev.c +++ b/drivers/net/virtio/virtio_user_ethdev.c @@ -34,10 +34,14 @@ #include #include #include +#include +#include +#include #include #include #include +#include #include "virtio_ethdev.h" #include "virtio_logs.h" @@ -49,6 +53,17 @@ #define virtio_user_get_dev(hw) \ ((struct virtio_user_dev *)(hw)->virtio_user_dev) +static void +virtio_user_delayed_handler(void *param) +{ + struct virtio_hw *hw = (struct virtio_hw *)param; + struct rte_eth_dev *dev = &rte_eth_devices[hw->port_id]; + + rte_intr_callback_unregister(dev->intr_handle, + virtio_interrupt_handler, + dev); +} + static void virtio_user_read_dev_config(struct virtio_hw *hw, size_t offset, void *dst, int length) @@ -63,8 +78,37 @@ virtio_user_read_dev_config(struct virtio_hw *hw, size_t offset, return; } - if (offset == offsetof(struct virtio_net_config, status)) + if (offset == offsetof(struct virtio_net_config, status)) { + char buf[128]; + + if (dev->vhostfd >= 0) { + int r; + int flags; + + flags = fcntl(dev->vhostfd, F_GETFL); + fcntl(dev->vhostfd, F_SETFL, flags | O_NONBLOCK); + r = recv(dev->vhostfd, buf, 128, MSG_PEEK); + if (r == 0 || (r < 0 && errno != EAGAIN)) { + dev->status &= (~VIRTIO_NET_S_LINK_UP); + PMD_DRV_LOG(ERR, "virtio-user port %u is down", + hw->port_id); + /* Only client mode is available now. Once the + * connection is broken, it can never be up + * again. Besides, this function could be called + * in the process of interrupt handling, + * callback cannot be unregistered here, set an + * alarm to do it. + */ + rte_eal_alarm_set(1, + virtio_user_delayed_handler, + (void *)hw); + } else { + dev->status |= VIRTIO_NET_S_LINK_UP; + } + fcntl(dev->vhostfd, F_SETFL, flags & (~O_NONBLOCK)); + } *(uint16_t *)dst = dev->status; + } if (offset == offsetof(struct virtio_net_config, max_virtqueue_pairs)) *(uint16_t *)dst = dev->max_queue_pairs; @@ -325,7 +369,11 @@ virtio_user_eth_dev_alloc(const char *name) hw->port_id = data->port_id; dev->port_id = data->port_id; virtio_hw_internal[hw->port_id].vtpci_ops = &virtio_user_ops; - hw->use_msix = 0; + /* + * MSIX is required to enable LSC (see virtio_init_device). + * Here just pretend that we support msix. + */ + hw->use_msix = 1; hw->modern = 0; hw->use_simple_rxtx = 0; hw->virtio_user_dev = dev;