Now, we just show the stats of every queue.

But for the user, the total values of every stat may are valuable.

Signed-off-by: Xuan Zhuo <xuanz...@linux.alibaba.com>
---
 drivers/net/virtio_net.c | 72 ++++++++++++++++++++++++++++++++++------
 1 file changed, 61 insertions(+), 11 deletions(-)

diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 595ed549eb61..ec141723f210 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -3293,6 +3293,7 @@ static int virtnet_set_channels(struct net_device *dev,
        return err;
 }
 
+/* qid == -1: for rx/tx queue total field */
 static void virtnet_get_stats_string(struct virtnet_info *vi, int type, int 
qid, u8 **data)
 {
        struct virtnet_stats_map *m;
@@ -3315,14 +3316,23 @@ static void virtnet_get_stats_string(struct 
virtnet_info *vi, int type, int qid,
                        else
                                tp = "_hw";
 
-                       if (type == VIRTNET_STATS_Q_TYPE_RX)
-                               ethtool_sprintf(&p, "rx_queue%s_%u_%s", tp, 
qid, m->desc[j].desc);
-
-                       else if (type == VIRTNET_STATS_Q_TYPE_TX)
-                               ethtool_sprintf(&p, "tx_queue%s_%u_%s", tp, 
qid, m->desc[j].desc);
-
-                       else if (type == VIRTNET_STATS_Q_TYPE_CQ)
+                       if (type == VIRTNET_STATS_Q_TYPE_RX) {
+                               if (qid < 0)
+                                       ethtool_sprintf(&p, "rx%s_%s", tp, 
m->desc[j].desc);
+                               else
+                                       ethtool_sprintf(&p, "rx_queue%s_%u_%s", 
tp, qid,
+                                                       m->desc[j].desc);
+
+                       } else if (type == VIRTNET_STATS_Q_TYPE_TX) {
+                               if (qid < 0)
+                                       ethtool_sprintf(&p, "tx%s_%s", tp, 
m->desc[j].desc);
+                               else
+                                       ethtool_sprintf(&p, "tx_queue%s_%u_%s", 
tp, qid,
+                                                       m->desc[j].desc);
+
+                       } else if (type == VIRTNET_STATS_Q_TYPE_CQ) {
                                ethtool_sprintf(&p, "cq%s_%s", tp, 
m->desc[j].desc);
+                       }
                }
        }
 
@@ -3379,6 +3389,38 @@ static void virtnet_stats_ctx_init(struct virtnet_info 
*vi,
        }
 }
 
+static void stats_sum_queue(u64 *sum, u32 num, u64 *q_value, u32 q_num)
+{
+       u32 step = num;
+       int i, j;
+       u64 *p;
+
+       for (i = 0; i < num; ++i) {
+               p = sum + i;
+               *p = 0;
+
+               for (j = 0; j < q_num; ++j)
+                       *p += *(q_value + i + j * step);
+       }
+}
+
+static void virtnet_fill_total_fields(struct virtnet_info *vi,
+                                     struct virtnet_stats_ctx *ctx)
+{
+       u64 *data, *first_rx_q, *first_tx_q;
+
+       first_rx_q = ctx->data + ctx->num_rx + ctx->num_tx + ctx->num_cq;
+       first_tx_q = first_rx_q + vi->curr_queue_pairs * ctx->num_rx;
+
+       data = ctx->data;
+
+       stats_sum_queue(data, ctx->num_rx, first_rx_q, vi->curr_queue_pairs);
+
+       data = ctx->data + ctx->num_rx;
+
+       stats_sum_queue(data, ctx->num_tx, first_tx_q, vi->curr_queue_pairs);
+}
+
 static void virtnet_fill_stats(struct virtnet_info *vi, u32 qid,
                               struct virtnet_stats_ctx *ctx,
                               const u8 *base, bool from_driver, u8 type)
@@ -3390,14 +3432,17 @@ static void virtnet_fill_stats(struct virtnet_info *vi, 
u32 qid,
        u64 offset;
        int i, j;
 
+       /* skip the total fields of pairs */
+       offset = ctx->num_rx + ctx->num_tx;
+
        if (qid == vi->max_queue_pairs * 2) {
-               offset = 0;
                queue_type = VIRTNET_STATS_Q_TYPE_CQ;
        } else if (qid % 2) {
-               offset = ctx->num_cq + ctx->num_rx * vi->curr_queue_pairs + 
ctx->num_tx * (qid / 2);
+               offset += ctx->num_cq + ctx->num_rx * vi->curr_queue_pairs +
+                       ctx->num_tx * (qid / 2);
                queue_type = VIRTNET_STATS_Q_TYPE_TX;
        } else {
-               offset = ctx->num_cq + ctx->num_rx * (qid / 2);
+               offset += ctx->num_cq + ctx->num_rx * (qid / 2);
                queue_type = VIRTNET_STATS_Q_TYPE_RX;
        }
 
@@ -3516,6 +3561,9 @@ static void virtnet_get_strings(struct net_device *dev, 
u32 stringset, u8 *data)
 
        switch (stringset) {
        case ETH_SS_STATS:
+               virtnet_get_stats_string(vi, VIRTNET_STATS_Q_TYPE_RX, -1, &p);
+               virtnet_get_stats_string(vi, VIRTNET_STATS_Q_TYPE_TX, -1, &p);
+
                virtnet_get_stats_string(vi, VIRTNET_STATS_Q_TYPE_CQ, 0, &p);
 
                for (i = 0; i < vi->curr_queue_pairs; ++i)
@@ -3557,7 +3605,7 @@ static int virtnet_get_sset_count(struct net_device *dev, 
int sset)
 
                pair_count = ctx.num_rx + ctx.num_tx;
 
-               return ctx.num_cq + vi->curr_queue_pairs * pair_count;
+               return pair_count + ctx.num_cq + vi->curr_queue_pairs * 
pair_count;
        default:
                return -EOPNOTSUPP;
        }
@@ -3590,6 +3638,8 @@ static void virtnet_get_ethtool_stats(struct net_device 
*dev,
                        virtnet_fill_stats(vi, i * 2 + 1, &ctx, stats_base, 
true, 0);
                } while (u64_stats_fetch_retry(&sq->stats.syncp, start));
        }
+
+       virtnet_fill_total_fields(vi, &ctx);
 }
 
 static void virtnet_get_channels(struct net_device *dev,
-- 
2.32.0.3.g01195cf9f


Reply via email to