> Add netdev_dpdk_vhost_txq_flush(), that flushes packets on vHost User
> port queues. Also add netdev_dpdk_vhost_tx_burst() function that
> uses rte_vhost_enqueue_burst() to enqueue burst of packets on vHost User
> ports.
>
> Signed-off-by: Bhanuprakash Bodireddy <bhanuprakash.bodireddy at intel.com>
> Signed-off-by: Antonio Fischetti <antonio.fischetti at intel.com>
> Co-authored-by: Antonio Fischetti <antonio.fischetti at intel.com>
> Acked-by: Eelco Chaudron <echaudro at redhat.com>
> ---
> lib/netdev-dpdk.c | 76
> ++++++++++++++++++++++++++++++++++++++++++++++++++++---
> 1 file changed, 72 insertions(+), 4 deletions(-)
>
> diff --git a/lib/netdev-dpdk.c b/lib/netdev-dpdk.c
> index 50a9a2c..47343e8 100644
> --- a/lib/netdev-dpdk.c
> +++ b/lib/netdev-dpdk.c
> @@ -307,12 +307,22 @@ struct dpdk_tx_queue {
> * pmd threads (see 'concurrent_txq'). */
> int map; /* Mapping of configured vhost-user queues
> * to enabled by guest. */
> - int dpdk_pkt_cnt; /* Number of buffered packets waiting to
> + union {
> + int dpdk_pkt_cnt; /* Number of buffered packets waiting to
> be sent on DPDK tx queue. */
> - struct rte_mbuf *dpdk_burst_pkts[INTERIM_QUEUE_BURST_THRESHOLD];
> + int vhost_pkt_cnt; /* Number of buffered packets waiting to
> + be sent on vhost port. */
> + };
> +
> + union {
> + struct rte_mbuf *dpdk_burst_pkts[INTERIM_QUEUE_BURST_THRESHOLD];
> /* Intermediate queue where packets can
> * be buffered to amortize the cost of
> MMIO
> * writes. */
> + struct dp_packet *vhost_burst_pkts[INTERIM_QUEUE_BURST_THRESHOLD];
> + /* Intermediate queue where packets can
> + * be buffered for vhost ports. */
> + };
> };
>
> /* dpdk has no way to remove dpdk ring ethernet devices
> @@ -1719,6 +1729,63 @@ netdev_dpdk_vhost_update_tx_counters(struct
> netdev_stats *stats,
> }
> }
>
> +static int
> +netdev_dpdk_vhost_tx_burst(struct netdev_dpdk *dev, int qid)
> +{
> + struct dpdk_tx_queue *txq = &dev->tx_q[qid];
> + struct rte_mbuf **cur_pkts = (struct rte_mbuf **)txq->vhost_burst_pkts;
> +
> + int tx_vid = netdev_dpdk_get_vid(dev);
> + int tx_qid = qid * VIRTIO_QNUM + VIRTIO_RXQ;
> + uint32_t sent = 0;
> + uint32_t retries = 0;
> + uint32_t sum, total_pkts;
> +
> + total_pkts = sum = txq->vhost_pkt_cnt;
> + do {
> + uint32_t ret;
> + ret = rte_vhost_enqueue_burst(tx_vid, tx_qid, &cur_pkts[sent], sum);
> + if (OVS_UNLIKELY(!ret)) {
> + /* No packets enqueued - do not retry. */
> + break;
> + } else {
> + /* Packet have been sent */
> + sent += ret;
> +
> + /* 'sum' packet have to be retransmitted */
> + sum -= ret;
> + }
> + } while (sum && (retries++ < VHOST_ENQ_RETRY_NUM));
> +
> + for (int i = 0; i < total_pkts; i++) {
> + dp_packet_delete(txq->vhost_burst_pkts[i]);
> + }
> +
> + /* Reset pkt count */
> + txq->vhost_pkt_cnt = 0;
> +
> + /* 'sum' refers to packets dropped */
> + return sum;
> +}
> +
> +/* Flush the txq if there are any packets available.
> + * dynamic_txqs/concurrent_txq is disabled for vHost User ports as
> + * 'OVS_VHOST_MAX_QUEUE_NUM' txqs are preallocated.
> + */
This comment is completely untrue. You may ignore 'concurrent_txq'
because you *must* lock the queue in any case because of dynamic
txq remapping inside netdev-dpdk. You must take the spinlock for
the 'dev->tx_q[qid % netdev->n_txq].map' before sending packets.
In current implementation you're able to call send and flush
simultaneously for the same queue from different threads because
'flush' doesn't care about queue remapping.
See '__netdev_dpdk_vhost_send' and 'netdev_dpdk_remap_txqs' for
detail.
Additionally, flushing logic will be broken in case of txq remapping
because you may have different underneath queue each time you
trying to send of flush.
Have you ever tested this with multiqueue vhost?
With disabling/enabling queues inside the guest?
Best regards, Ilya Maximets.
> +static int
> +netdev_dpdk_vhost_txq_flush(struct netdev *netdev, int qid,
> + bool concurrent_txq OVS_UNUSED)
> +{
> + struct netdev_dpdk *dev = netdev_dpdk_cast(netdev);
> + struct dpdk_tx_queue *txq = &dev->tx_q[qid];
> +
> + if (OVS_LIKELY(txq->vhost_pkt_cnt)) {
> + netdev_dpdk_vhost_tx_burst(dev, qid);
> + }
> +
> + return 0;
> +}
> +
> static void
> __netdev_dpdk_vhost_send(struct netdev *netdev, int qid,
> struct dp_packet **pkts, int cnt)
> @@ -3432,7 +3499,8 @@ static const struct netdev_class dpdk_vhost_class =
> NULL,
> netdev_dpdk_vhost_reconfigure,
> netdev_dpdk_vhost_rxq_recv,
> - NULL);
> + netdev_dpdk_vhost_txq_flush);
> +
> static const struct netdev_class dpdk_vhost_client_class =
> NETDEV_DPDK_CLASS(
> "dpdkvhostuserclient",
> @@ -3448,7 +3516,7 @@ static const struct netdev_class
> dpdk_vhost_client_class =
> NULL,
> netdev_dpdk_vhost_client_reconfigure,
> netdev_dpdk_vhost_rxq_recv,
> - NULL);
> + netdev_dpdk_vhost_txq_flush);
>
> void
> netdev_dpdk_register(void)
> --
> 2.4.11
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev