HXPS feature will enable steering Tx packets on transmist
queues based on their hashes. In order to test the feature,
it is needed to be able to get the per-queue statistics for
Vhost-user ports.

This patch introduces "bytes", "packets" and "error"
per-queue custom statistics for Vhost-user ports.

Suggested-by David Marchand <[email protected]>
Signed-off-by: Maxime Coquelin <[email protected]>
---
 lib/netdev-dpdk.c | 143 +++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 135 insertions(+), 8 deletions(-)

diff --git a/lib/netdev-dpdk.c b/lib/netdev-dpdk.c
index ca92c947a..e80d5b4ab 100644
--- a/lib/netdev-dpdk.c
+++ b/lib/netdev-dpdk.c
@@ -192,6 +192,13 @@ static const struct vhost_device_ops virtio_net_device_ops 
=
     .guest_notified = vhost_guest_notified,
 };
 
+/* Custome software per-queue stats for Vhost ports */
+struct netdev_dpdk_vhost_q_stats {
+    uint64_t bytes;
+    uint64_t packets;
+    uint64_t errors;
+};
+
 /* Custom software stats for dpdk ports */
 struct netdev_dpdk_sw_stats {
     /* No. of retries when unable to transmit. */
@@ -206,6 +213,10 @@ struct netdev_dpdk_sw_stats {
     uint64_t rx_qos_drops;
     /* Packet drops in HWOL processing. */
     uint64_t tx_invalid_hwol_drops;
+    /* Per-queue Vhost Tx stats */
+    struct netdev_dpdk_vhost_q_stats *txq;
+    /* Per-queue Vhost Rx stats */
+    struct netdev_dpdk_vhost_q_stats *rxq;
 };
 
 enum dpdk_dev_type {
@@ -1276,6 +1287,13 @@ common_construct(struct netdev *netdev, dpdk_port_t 
port_no,
     dev->sw_stats = xzalloc(sizeof *dev->sw_stats);
     dev->sw_stats->tx_retries = (dev->type == DPDK_DEV_VHOST) ? 0 : UINT64_MAX;
 
+    if (dev->type == DPDK_DEV_VHOST) {
+        dev->sw_stats->txq = xcalloc(netdev->n_txq,
+                                     sizeof *dev->sw_stats->txq);
+        dev->sw_stats->rxq = xcalloc(netdev->n_rxq,
+                                     sizeof *dev->sw_stats->rxq);
+    }
+
     return 0;
 }
 
@@ -2353,17 +2371,21 @@ netdev_dpdk_vhost_update_rx_size_counters(struct 
netdev_stats *stats,
 }
 
 static inline void
-netdev_dpdk_vhost_update_rx_counters(struct netdev_dpdk *dev,
+netdev_dpdk_vhost_update_rx_counters(struct netdev_dpdk *dev, int qid,
                                      struct dp_packet **packets, int count,
                                      int qos_drops)
 {
     struct netdev_stats *stats = &dev->stats;
+    struct netdev_dpdk_vhost_q_stats *q_stats = &dev->sw_stats->rxq[qid];
     struct dp_packet *packet;
     unsigned int packet_size;
     int i;
 
     stats->rx_packets += count;
+    q_stats->packets += count;
     stats->rx_dropped += qos_drops;
+    q_stats->errors += qos_drops;
+
     for (i = 0; i < count; i++) {
         packet = packets[i];
         packet_size = dp_packet_size(packet);
@@ -2374,6 +2396,7 @@ netdev_dpdk_vhost_update_rx_counters(struct netdev_dpdk 
*dev,
              * further processing. */
             stats->rx_errors++;
             stats->rx_length_errors++;
+            q_stats->errors++;
             continue;
         }
 
@@ -2385,6 +2408,7 @@ netdev_dpdk_vhost_update_rx_counters(struct netdev_dpdk 
*dev,
         }
 
         stats->rx_bytes += packet_size;
+        q_stats->bytes += packet_size;
     }
 
     if (OVS_UNLIKELY(qos_drops)) {
@@ -2437,7 +2461,7 @@ netdev_dpdk_vhost_rxq_recv(struct netdev_rxq *rxq,
     }
 
     rte_spinlock_lock(&dev->stats_lock);
-    netdev_dpdk_vhost_update_rx_counters(dev, batch->packets,
+    netdev_dpdk_vhost_update_rx_counters(dev, qid, batch->packets,
                                          nb_rx, qos_drops);
     rte_spinlock_unlock(&dev->stats_lock);
 
@@ -2551,7 +2575,7 @@ netdev_dpdk_filter_packet_len(struct netdev_dpdk *dev, 
struct rte_mbuf **pkts,
 }
 
 static inline void
-netdev_dpdk_vhost_update_tx_counters(struct netdev_dpdk *dev,
+netdev_dpdk_vhost_update_tx_counters(struct netdev_dpdk *dev, int qid,
                                      struct dp_packet **packets,
                                      int attempted,
                                      struct netdev_dpdk_sw_stats *sw_stats_add)
@@ -2561,14 +2585,20 @@ netdev_dpdk_vhost_update_tx_counters(struct netdev_dpdk 
*dev,
                   sw_stats_add->tx_failure_drops +
                   sw_stats_add->tx_invalid_hwol_drops;
     struct netdev_stats *stats = &dev->stats;
+    struct netdev_dpdk_vhost_q_stats *q_stats = &dev->sw_stats->txq[qid];
     int sent = attempted - dropped;
     int i;
 
     stats->tx_packets += sent;
+    q_stats->packets += sent;
     stats->tx_dropped += dropped;
+    q_stats->errors += dropped;
 
     for (i = 0; i < sent; i++) {
-        stats->tx_bytes += dp_packet_size(packets[i]);
+        uint64_t bytes = dp_packet_size(packets[i]);
+
+        stats->tx_bytes += bytes;
+        q_stats->bytes += bytes;
     }
 
     if (OVS_UNLIKELY(dropped || sw_stats_add->tx_retries)) {
@@ -2656,7 +2686,7 @@ __netdev_dpdk_vhost_send(struct netdev *netdev, int qid,
     sw_stats_add.tx_retries = MIN(retries, max_retries);
 
     rte_spinlock_lock(&dev->stats_lock);
-    netdev_dpdk_vhost_update_tx_counters(dev, pkts, total_packets,
+    netdev_dpdk_vhost_update_tx_counters(dev, qid, pkts, total_packets,
                                          &sw_stats_add);
     rte_spinlock_unlock(&dev->stats_lock);
 
@@ -3286,6 +3316,72 @@ netdev_dpdk_get_sw_custom_stats(const struct netdev 
*netdev,
     return 0;
 }
 
+static int
+netdev_dpdk_vhost_get_custom_stats(const struct netdev *netdev,
+                                struct netdev_custom_stats *custom_stats)
+{
+    struct netdev_dpdk *dev = netdev_dpdk_cast(netdev);
+    int sw_stats_size, i, j;
+
+    netdev_dpdk_get_sw_custom_stats(netdev, custom_stats);
+
+    ovs_mutex_lock(&dev->mutex);
+
+    sw_stats_size = custom_stats->size;
+    custom_stats->size += netdev->n_rxq * sizeof(*dev->sw_stats->rxq) /
+                          sizeof(uint64_t);
+    custom_stats->size += netdev->n_txq * sizeof(*dev->sw_stats->txq) /
+                          sizeof(uint64_t);
+
+    custom_stats->counters = xrealloc(custom_stats->counters,
+                                      custom_stats->size *
+                                      sizeof *custom_stats->counters);
+
+    j = 0;
+    for (i = 0; i < netdev->n_rxq; i++) {
+        snprintf(custom_stats->counters[sw_stats_size + j++].name,
+                NETDEV_CUSTOM_STATS_NAME_SIZE, "rx_q%d_bytes", i);
+        snprintf(custom_stats->counters[sw_stats_size + j++].name,
+                NETDEV_CUSTOM_STATS_NAME_SIZE, "rx_q%d_packets", i);
+        snprintf(custom_stats->counters[sw_stats_size + j++].name,
+                NETDEV_CUSTOM_STATS_NAME_SIZE, "rx_q%d_errors", i);
+    }
+
+    for (i = 0; i < netdev->n_txq; i++) {
+        snprintf(custom_stats->counters[sw_stats_size + j++].name,
+                NETDEV_CUSTOM_STATS_NAME_SIZE, "tx_q%d_bytes", i);
+        snprintf(custom_stats->counters[sw_stats_size + j++].name,
+                NETDEV_CUSTOM_STATS_NAME_SIZE, "tx_q%d_packets", i);
+        snprintf(custom_stats->counters[sw_stats_size + j++].name,
+                NETDEV_CUSTOM_STATS_NAME_SIZE, "tx_q%d_errors", i);
+    }
+
+    rte_spinlock_lock(&dev->stats_lock);
+
+    j = 0;
+    for (i = 0; i < netdev->n_rxq; i++) {
+        struct netdev_dpdk_vhost_q_stats *rxq_stats = &dev->sw_stats->rxq[i];
+
+        custom_stats->counters[sw_stats_size + j++].value = rxq_stats->bytes;
+        custom_stats->counters[sw_stats_size + j++].value = rxq_stats->packets;
+        custom_stats->counters[sw_stats_size + j++].value = rxq_stats->errors;
+    }
+
+    for (i = 0; i < netdev->n_txq; i++) {
+        struct netdev_dpdk_vhost_q_stats *txq_stats = &dev->sw_stats->txq[i];
+
+        custom_stats->counters[sw_stats_size + j++].value = txq_stats->bytes;
+        custom_stats->counters[sw_stats_size + j++].value = txq_stats->packets;
+        custom_stats->counters[sw_stats_size + j++].value = txq_stats->errors;
+    }
+
+    rte_spinlock_unlock(&dev->stats_lock);
+
+    ovs_mutex_unlock(&dev->mutex);
+
+    return 0;
+}
+
 static int
 netdev_dpdk_get_features(const struct netdev *netdev,
                          enum netdev_features *current,
@@ -5043,9 +5139,12 @@ static int
 dpdk_vhost_reconfigure_helper(struct netdev_dpdk *dev)
     OVS_REQUIRES(dev->mutex)
 {
+    int old_n_txq = dev->up.n_txq;
+    int old_n_rxq = dev->up.n_rxq;
+    int err;
+
     dev->up.n_txq = dev->requested_n_txq;
     dev->up.n_rxq = dev->requested_n_rxq;
-    int err;
 
     /* Always keep RX queue 0 enabled for implementations that won't
      * report vring states. */
@@ -5063,6 +5162,34 @@ dpdk_vhost_reconfigure_helper(struct netdev_dpdk *dev)
 
     netdev_dpdk_remap_txqs(dev);
 
+    if (dev->up.n_txq != old_n_txq) {
+        struct netdev_dpdk_vhost_q_stats *old_txq_stats, *new_txq_stats;
+
+        new_txq_stats = xcalloc(dev->up.n_txq, sizeof *dev->sw_stats->txq);
+        rte_spinlock_lock(&dev->stats_lock);
+        old_txq_stats = dev->sw_stats->txq;
+        memcpy(new_txq_stats, old_txq_stats,
+                MIN(dev->up.n_txq, old_n_txq) * sizeof *dev->sw_stats->txq);
+        dev->sw_stats->txq = new_txq_stats;
+        rte_spinlock_unlock(&dev->stats_lock);
+        free(old_txq_stats);
+
+    }
+
+    if (dev->up.n_rxq != old_n_rxq) {
+        struct netdev_dpdk_vhost_q_stats *old_rxq_stats, *new_rxq_stats;
+
+        new_rxq_stats = xcalloc(dev->up.n_rxq, sizeof *dev->sw_stats->rxq);
+        rte_spinlock_lock(&dev->stats_lock);
+        old_rxq_stats = dev->sw_stats->rxq;
+        memcpy(new_rxq_stats, old_rxq_stats,
+                MIN(dev->up.n_rxq, old_n_rxq) * sizeof *dev->sw_stats->rxq);
+        dev->sw_stats->rxq = new_rxq_stats;
+        rte_spinlock_unlock(&dev->stats_lock);
+        free(old_rxq_stats);
+
+    }
+
     err = netdev_dpdk_mempool_configure(dev);
     if (!err) {
         /* A new mempool was created or re-used. */
@@ -5467,7 +5594,7 @@ static const struct netdev_class dpdk_vhost_class = {
     .send = netdev_dpdk_vhost_send,
     .get_carrier = netdev_dpdk_vhost_get_carrier,
     .get_stats = netdev_dpdk_vhost_get_stats,
-    .get_custom_stats = netdev_dpdk_get_sw_custom_stats,
+    .get_custom_stats = netdev_dpdk_vhost_get_custom_stats,
     .get_status = netdev_dpdk_vhost_user_get_status,
     .reconfigure = netdev_dpdk_vhost_reconfigure,
     .rxq_recv = netdev_dpdk_vhost_rxq_recv,
@@ -5483,7 +5610,7 @@ static const struct netdev_class dpdk_vhost_client_class 
= {
     .send = netdev_dpdk_vhost_send,
     .get_carrier = netdev_dpdk_vhost_get_carrier,
     .get_stats = netdev_dpdk_vhost_get_stats,
-    .get_custom_stats = netdev_dpdk_get_sw_custom_stats,
+    .get_custom_stats = netdev_dpdk_vhost_get_custom_stats,
     .get_status = netdev_dpdk_vhost_user_get_status,
     .reconfigure = netdev_dpdk_vhost_client_reconfigure,
     .rxq_recv = netdev_dpdk_vhost_rxq_recv,
-- 
2.31.1

_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to