From mboxrd@z Thu Jan 1 00:00:00 1970 From: Xiao Wang Subject: [PATCH v4 2/3] net/virtio: add packet injection method Date: Thu, 4 Jan 2018 07:59:37 -0800 Message-ID: <1515081578-30649-3-git-send-email-xiao.w.wang@intel.com> References: <1515051700-117262-3-git-send-email-xiao.w.wang@intel.com> <1515081578-30649-1-git-send-email-xiao.w.wang@intel.com> Cc: dev@dpdk.org, yliu@fridaylinux.org, stephen@networkplumber.org, Xiao Wang To: tiwei.bie@intel.com Return-path: Received: from mga03.intel.com (mga03.intel.com [134.134.136.65]) by dpdk.org (Postfix) with ESMTP id 4EADE1B013 for ; Thu, 4 Jan 2018 08:24:06 +0100 (CET) In-Reply-To: <1515081578-30649-1-git-send-email-xiao.w.wang@intel.com> List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" This patch adds dev_pause, dev_resume and inject_pkts api to allow driver to pause the worker thread and inject special packets into Tx queue. The next patch will be based on this. Signed-off-by: Xiao Wang --- drivers/net/virtio/virtio_ethdev.c | 44 +++++++++++++++++++++++++++++++++ drivers/net/virtio/virtio_ethdev.h | 6 +++++ drivers/net/virtio/virtio_pci.h | 7 ++++++ drivers/net/virtio/virtio_rxtx.c | 2 +- drivers/net/virtio/virtio_rxtx_simple.c | 2 +- 5 files changed, 59 insertions(+), 2 deletions(-) diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c index ac73950..6745de7 100644 --- a/drivers/net/virtio/virtio_ethdev.c +++ b/drivers/net/virtio/virtio_ethdev.c @@ -55,6 +55,7 @@ #include #include #include +#include #include "virtio_ethdev.h" #include "virtio_pci.h" @@ -1249,6 +1250,45 @@ static int virtio_dev_xstats_get_names(struct rte_eth_dev *dev, return 0; } +int +virtio_dev_pause(struct rte_eth_dev *dev) +{ + struct virtio_hw *hw = dev->data->dev_private; + + rte_spinlock_lock(&hw->state_lock); + + if (hw->started == 0) { + rte_spinlock_unlock(&hw->state_lock); + return -1; + } + hw->started = 0; + /* + * Prevent the worker thread from touching queues to avoid contention, + * 1 ms should be enough for the ongoing Tx function to finish. + */ + rte_delay_ms(1); + return 0; +} + +void +virtio_dev_resume(struct rte_eth_dev *dev) +{ + struct virtio_hw *hw = dev->data->dev_private; + + hw->started = 1; + rte_spinlock_unlock(&hw->state_lock); +} + +void +virtio_inject_pkts(struct rte_eth_dev *dev, struct virtnet_tx *txvq, + struct rte_mbuf **buf, int count) +{ + struct virtio_hw *hw = dev->data->dev_private; + + hw->special_buf = buf; + dev->tx_pkt_burst(txvq, buf, count); +} + /* * Process Virtio Config changed interrupt and call the callback * if link state changed. @@ -1786,6 +1826,8 @@ static int eth_virtio_pci_remove(struct rte_pci_device *pci_dev) return -EBUSY; } + rte_spinlock_init(&hw->state_lock); + hw->use_simple_rx = 1; hw->use_simple_tx = 1; @@ -1952,12 +1994,14 @@ static void virtio_dev_free_mbufs(struct rte_eth_dev *dev) PMD_INIT_LOG(DEBUG, "stop"); + rte_spinlock_lock(&hw->state_lock); if (intr_conf->lsc || intr_conf->rxq) virtio_intr_disable(dev); hw->started = 0; memset(&link, 0, sizeof(link)); virtio_dev_atomic_write_link_status(dev, &link); + rte_spinlock_unlock(&hw->state_lock); } static int diff --git a/drivers/net/virtio/virtio_ethdev.h b/drivers/net/virtio/virtio_ethdev.h index 2039bc5..e973de3 100644 --- a/drivers/net/virtio/virtio_ethdev.h +++ b/drivers/net/virtio/virtio_ethdev.h @@ -37,6 +37,7 @@ #include #include "virtio_pci.h" +#include "virtio_rxtx.h" #define SPEED_10 10 #define SPEED_100 100 @@ -121,4 +122,9 @@ uint16_t virtio_xmit_pkts_simple(void *tx_queue, struct rte_mbuf **tx_pkts, void virtio_interrupt_handler(void *param); +int virtio_dev_pause(struct rte_eth_dev *dev); +void virtio_dev_resume(struct rte_eth_dev *dev); +void virtio_inject_pkts(struct rte_eth_dev *dev, + struct virtnet_tx *txvq, struct rte_mbuf **buf, int count); + #endif /* _VIRTIO_ETHDEV_H_ */ diff --git a/drivers/net/virtio/virtio_pci.h b/drivers/net/virtio/virtio_pci.h index 3c5ce66..8d91320 100644 --- a/drivers/net/virtio/virtio_pci.h +++ b/drivers/net/virtio/virtio_pci.h @@ -270,6 +270,13 @@ struct virtio_hw { struct virtio_pci_common_cfg *common_cfg; struct virtio_net_config *dev_cfg; void *virtio_user_dev; + /* + * App management thread and virtio interrupt handler thread + * both can change the 'started' flag, this lock is meant to + * avoid such a contention. + */ + rte_spinlock_t state_lock; + struct rte_mbuf **special_buf; struct virtqueue **vqs; }; diff --git a/drivers/net/virtio/virtio_rxtx.c b/drivers/net/virtio/virtio_rxtx.c index 6a24fde..1438f05 100644 --- a/drivers/net/virtio/virtio_rxtx.c +++ b/drivers/net/virtio/virtio_rxtx.c @@ -1017,7 +1017,7 @@ uint16_t nb_used, nb_tx = 0; int error; - if (unlikely(hw->started == 0)) + if (unlikely(hw->started == 0) && tx_pkts != hw->special_buf) return nb_tx; if (unlikely(nb_pkts < 1)) diff --git a/drivers/net/virtio/virtio_rxtx_simple.c b/drivers/net/virtio/virtio_rxtx_simple.c index b5bc1c4..b3f5d2e 100644 --- a/drivers/net/virtio/virtio_rxtx_simple.c +++ b/drivers/net/virtio/virtio_rxtx_simple.c @@ -99,7 +99,7 @@ int __attribute__((cold)) uint16_t desc_idx_max = (vq->vq_nentries >> 1) - 1; uint16_t nb_tx = 0; - if (unlikely(hw->started == 0)) + if (unlikely(hw->started == 0) && tx_pkts != hw->special_buf) return nb_tx; nb_used = VIRTQUEUE_NUSED(vq); -- 1.8.3.1