diff mbox

[ovs-dev,v2,3/4] netdev-dpdk.c: Support to show multi-queue qos info for dpdk datapath

Message ID 1500951228-18646-4-git-send-email-zhaozhanxu@163.com
State Changes Requested
Headers show

Commit Message

zhaozhanxu July 25, 2017, 2:53 a.m. UTC
This patch support command `ovs-appctl -t ovs-vswitchd qos/show vhost-user0`
to show QoS and its queues information.

It adds some functions whitch is pointed by `get_queue_stats`,
`queue_dump_start`, `queue_dump_next` and `queue_dump_done`
of structure `netdev_class` to show queue information.

Signed-off-by: zhaozhanxu <zhaozhanxu@163.com>
---
 lib/netdev-dpdk.c | 155 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 150 insertions(+), 5 deletions(-)

Comments

Stokes, Ian Oct. 17, 2017, 8:53 a.m. UTC | #1
> This patch support command `ovs-appctl -t ovs-vswitchd qos/show vhost-
> user0` to show QoS and its queues information.

As this will work for both DPDK and vhostuser port types I'd consider changing the command above to be a little more general and not specific to vhost-user0.

> 
> It adds some functions whitch is pointed by `get_queue_stats`,
> `queue_dump_start`, `queue_dump_next` and `queue_dump_done` of structure
> `netdev_class` to show queue information.
> 
> Signed-off-by: zhaozhanxu <zhaozhanxu@163.com>
> ---
>  lib/netdev-dpdk.c | 155
> ++++++++++++++++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 150 insertions(+), 5 deletions(-)
> 
> diff --git a/lib/netdev-dpdk.c b/lib/netdev-dpdk.c index 85f077e..641ddfa
> 100644
> --- a/lib/netdev-dpdk.c
> +++ b/lib/netdev-dpdk.c
> @@ -284,6 +284,10 @@ struct dpdk_qos_ops {
>       */
>      int (*qos_queue_get)(struct smap *details, uint32_t queue_id,
>                           const struct qos_conf *conf);
> +
> +    /* Retrieves statistics of QoS Queue configuration into 'details'. */
> +    int (*qos_queue_get_stats)(const struct qos_conf *conf, uint32_t
> queue_id,
> +                               struct netdev_queue_stats *stats);
>  };
> 
>  /* dpdk_qos_ops for each type of user space QoS implementation */ @@ -
> 3079,6 +3083,28 @@ netdev_dpdk_delete_queue(struct netdev *netdev,
> uint32_t queue_id)
>      return 0;
>  }
> 
> +static int
> +netdev_dpdk_get_queue_stats(const struct netdev *netdev, uint32_t
> queue_id,
> +                            struct netdev_queue_stats *stats) {
> +    struct netdev_dpdk *dev = netdev_dpdk_cast(netdev);
> +    struct qos_conf *qos_conf;
> +    int error = 0;
> +
> +    ovs_mutex_lock(&dev->mutex);
> +
> +    qos_conf = ovsrcu_get_protected(struct qos_conf *, &dev->qos_conf);
> +    if (qos_conf && qos_conf->ops && qos_conf->ops->qos_queue_get_stats)
> {
> +        qos_conf->ops->qos_queue_get_stats(qos_conf, queue_id, stats);
> +    } else {
> +        error = EOPNOTSUPP;
> +    }
> +
> +    ovs_mutex_unlock(&dev->mutex);
> +
> +    return error;
> +}
> +
>  /* egress-policer details */
> 
>  struct egress_policer {
> @@ -3088,13 +3114,100 @@ struct egress_policer {
>      struct hmap queue;
>  };
> 
> +struct egress_queue_stats {
> +    uint64_t tx_bytes;
> +    uint64_t tx_packets;
> +    uint64_t tx_errors;
> +
> +    long long int created;
> +};
> +
>  struct egress_queue_policer {
>      struct hmap_node hmap_node;
>      uint32_t queue_id;
>      struct rte_meter_srtcm_params app_srtcm_params;
>      struct rte_meter_srtcm egress_meter;
> +    struct egress_queue_stats stats;
> +};
> +
> +struct netdev_dpdk_queue_state {
> +    uint32_t *queues;
> +    size_t cur_queue;
> +    size_t n_queues;
>  };
> 
> +static int
> +netdev_dpdk_queue_dump_start(const struct netdev *netdev, void
> +**statep) {
> +    struct netdev_dpdk *dev = netdev_dpdk_cast(netdev);
> +    struct qos_conf *qos_conf;
> +    int error = 0;
> +
> +    ovs_mutex_lock(&dev->mutex);
> +
> +    qos_conf = ovsrcu_get_protected(struct qos_conf *, &dev->qos_conf);
> +    if (qos_conf) {
> +        struct netdev_dpdk_queue_state *state;
> +        struct egress_policer *policer =
> +            CONTAINER_OF(qos_conf, struct egress_policer, qos_conf);
> +
> +        *statep = state = xmalloc(sizeof *state);
> +        state->n_queues = hmap_count(&policer->queue);
> +        state->cur_queue = 0;
> +        state->queues = xmalloc(state->n_queues * sizeof
> + *state->queues);
> +
> +        uint32_t i = 0;
> +        struct egress_queue_policer *queue_policer;
> +        HMAP_FOR_EACH (queue_policer, hmap_node, &policer->queue) {
> +            state->queues[i++] = queue_policer->queue_id;
> +        }
> +    } else {
> +        error = EOPNOTSUPP;
> +    }
> +
> +    ovs_mutex_unlock(&dev->mutex);
> +
> +    return error;
> +}
> +
> +static int
> +netdev_dpdk_queue_dump_next(const struct netdev *netdev, void *state_,
> +                            uint32_t *queue_idp, struct smap *details)
> +{
> +    struct netdev_dpdk *dev = netdev_dpdk_cast(netdev);
> +    struct netdev_dpdk_queue_state *state = state_;
> +    struct qos_conf *qos_conf;
> +    int error = EOF;
> +
> +    ovs_mutex_lock(&dev->mutex);
> +
> +    while (state->cur_queue < state->n_queues) {
> +        uint32_t queue_id = state->queues[state->cur_queue++];
> +
> +        qos_conf = ovsrcu_get_protected(struct qos_conf *, &dev-
> >qos_conf);
> +        if (qos_conf && qos_conf->ops && qos_conf->ops->qos_queue_get) {
> +            *queue_idp = queue_id;
> +            error = qos_conf->ops->qos_queue_get(details, queue_id,
> qos_conf);
> +            break;
> +        }
> +    }
> +
> +    ovs_mutex_unlock(&dev->mutex);
> +
> +    return error;
> +}
> +
> +static int
> +netdev_dpdk_queue_dump_done(const struct netdev *netdev OVS_UNUSED,
> +                            void *state_) {
> +    struct netdev_dpdk_queue_state *state = state_;
> +
> +    free(state->queues);
> +    free(state);
> +    return 0;
> +}
> +
>  static struct egress_queue_policer *
>  egress_policer_qos_find_queue(struct egress_policer *policer,
>                                uint32_t queue_id); @@ -3185,7 +3298,11 @@
> egress_policer_pkt_handle(struct egress_policer *policer,
>      if (queue_policer) {
>          if (rte_meter_srtcm_color_blind_check(&queue_policer-
> >egress_meter,
>                                          time, pkt_len) !=
> e_RTE_METER_GREEN) {
> +            queue_policer->stats.tx_errors ++;

Should be drop counted as an error? I would have thought a drop is a drop, an error would be if we couldn't process the packet for a reason.

>              return false;
> +        } else {
> +            queue_policer->stats.tx_bytes += pkt_len;
> +            queue_policer->stats.tx_packets ++;
>          }
>      }
> 
> @@ -3246,6 +3363,8 @@ egress_policer_qos_queue_construct(const struct smap
> *details,
>          hmap_insert(&policer->queue, &queue_policer->hmap_node,
>                      hash_2words(queue_id, 0));
>          queue_policer->queue_id = queue_id;
> +        memset(&queue_policer->stats, 0, sizeof queue_policer->stats);
> +        queue_policer->stats.created = rte_rdtsc();
>      }
>      egress_policer_details_to_param(details, &queue_policer-
> >app_srtcm_params);
>      err = rte_meter_srtcm_config(&queue_policer->egress_meter,
> @@ -3291,6 +3410,31 @@ egress_policer_qos_queue_get(struct smap *details,
> uint32_t queue_id,
>      return 0;
>  }
> 
> +static int
> +egress_policer_qos_queue_get_stats(const struct qos_conf *conf,
> +                                   uint32_t queue_id,
> +                                   struct netdev_queue_stats *stats) {
> +    struct egress_policer *policer =
> +        CONTAINER_OF(conf, struct egress_policer, qos_conf);
> +
> +    struct egress_queue_policer *queue_policer;
> +    queue_policer = egress_policer_qos_find_queue(policer, queue_id);
> +    if (!queue_policer) {
> +        stats->tx_bytes = UINT64_MAX;
> +        stats->tx_packets = UINT64_MAX;
> +        stats->tx_errors = UINT64_MAX;
> +        stats->created = LLONG_MIN;
> +        return -1;
> +    } else {
> +        stats->tx_bytes = queue_policer->stats.tx_bytes;
> +        stats->tx_packets = queue_policer->stats.tx_packets;
> +        stats->tx_errors = queue_policer->stats.tx_errors;
> +        stats->created = queue_policer->stats.created;
> +        return 0;
> +    }
> +}
> +
>  static const struct dpdk_qos_ops egress_policer_ops = {
>      "egress-policer",    /* qos_name */
>      egress_policer_qos_construct,
> @@ -3300,7 +3444,8 @@ static const struct dpdk_qos_ops egress_policer_ops
> = {
>      egress_policer_run,
>      egress_policer_qos_queue_construct,
>      egress_policer_qos_queue_destruct,
> -    egress_policer_qos_queue_get
> +    egress_policer_qos_queue_get,
> +    egress_policer_qos_queue_get_stats
>  };
> 
>  static int
> @@ -3485,10 +3630,10 @@ unlock:
>      netdev_dpdk_get_queue,                                    \
>      netdev_dpdk_set_queue,                                    \
>      netdev_dpdk_delete_queue,                                 \
> -    NULL,                       /* get_queue_stats */         \
> -    NULL,                       /* queue_dump_start */        \
> -    NULL,                       /* queue_dump_next */         \
> -    NULL,                       /* queue_dump_done */         \
> +    netdev_dpdk_get_queue_stats,                              \
> +    netdev_dpdk_queue_dump_start,                             \
> +    netdev_dpdk_queue_dump_next,                              \
> +    netdev_dpdk_queue_dump_done,                              \
>      NULL,                       /* dump_queue_stats */        \
>                                                                \
>      NULL,                       /* set_in4 */                 \
> --
> 2.7.4
> 
> 
> _______________________________________________
> dev mailing list
> dev@openvswitch.org
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
diff mbox

Patch

diff --git a/lib/netdev-dpdk.c b/lib/netdev-dpdk.c
index 85f077e..641ddfa 100644
--- a/lib/netdev-dpdk.c
+++ b/lib/netdev-dpdk.c
@@ -284,6 +284,10 @@  struct dpdk_qos_ops {
      */
     int (*qos_queue_get)(struct smap *details, uint32_t queue_id,
                          const struct qos_conf *conf);
+
+    /* Retrieves statistics of QoS Queue configuration into 'details'. */
+    int (*qos_queue_get_stats)(const struct qos_conf *conf, uint32_t queue_id,
+                               struct netdev_queue_stats *stats);
 };
 
 /* dpdk_qos_ops for each type of user space QoS implementation */
@@ -3079,6 +3083,28 @@  netdev_dpdk_delete_queue(struct netdev *netdev, uint32_t queue_id)
     return 0;
 }
 
+static int
+netdev_dpdk_get_queue_stats(const struct netdev *netdev, uint32_t queue_id,
+                            struct netdev_queue_stats *stats)
+{
+    struct netdev_dpdk *dev = netdev_dpdk_cast(netdev);
+    struct qos_conf *qos_conf;
+    int error = 0;
+
+    ovs_mutex_lock(&dev->mutex);
+
+    qos_conf = ovsrcu_get_protected(struct qos_conf *, &dev->qos_conf);
+    if (qos_conf && qos_conf->ops && qos_conf->ops->qos_queue_get_stats) {
+        qos_conf->ops->qos_queue_get_stats(qos_conf, queue_id, stats);
+    } else {
+        error = EOPNOTSUPP;
+    }
+
+    ovs_mutex_unlock(&dev->mutex);
+
+    return error;
+}
+
 /* egress-policer details */
 
 struct egress_policer {
@@ -3088,13 +3114,100 @@  struct egress_policer {
     struct hmap queue;
 };
 
+struct egress_queue_stats {
+    uint64_t tx_bytes;
+    uint64_t tx_packets;
+    uint64_t tx_errors;
+
+    long long int created;
+};
+
 struct egress_queue_policer {
     struct hmap_node hmap_node;
     uint32_t queue_id;
     struct rte_meter_srtcm_params app_srtcm_params;
     struct rte_meter_srtcm egress_meter;
+    struct egress_queue_stats stats;
+};
+
+struct netdev_dpdk_queue_state {
+    uint32_t *queues;
+    size_t cur_queue;
+    size_t n_queues;
 };
 
+static int
+netdev_dpdk_queue_dump_start(const struct netdev *netdev, void **statep)
+{
+    struct netdev_dpdk *dev = netdev_dpdk_cast(netdev);
+    struct qos_conf *qos_conf;
+    int error = 0;
+
+    ovs_mutex_lock(&dev->mutex);
+
+    qos_conf = ovsrcu_get_protected(struct qos_conf *, &dev->qos_conf);
+    if (qos_conf) {
+        struct netdev_dpdk_queue_state *state;
+        struct egress_policer *policer =
+            CONTAINER_OF(qos_conf, struct egress_policer, qos_conf);
+
+        *statep = state = xmalloc(sizeof *state);
+        state->n_queues = hmap_count(&policer->queue);
+        state->cur_queue = 0;
+        state->queues = xmalloc(state->n_queues * sizeof *state->queues);
+
+        uint32_t i = 0;
+        struct egress_queue_policer *queue_policer;
+        HMAP_FOR_EACH (queue_policer, hmap_node, &policer->queue) {
+            state->queues[i++] = queue_policer->queue_id;
+        }
+    } else {
+        error = EOPNOTSUPP;
+    }
+
+    ovs_mutex_unlock(&dev->mutex);
+
+    return error;
+}
+
+static int
+netdev_dpdk_queue_dump_next(const struct netdev *netdev, void *state_,
+                            uint32_t *queue_idp, struct smap *details)
+{
+    struct netdev_dpdk *dev = netdev_dpdk_cast(netdev);
+    struct netdev_dpdk_queue_state *state = state_;
+    struct qos_conf *qos_conf;
+    int error = EOF;
+
+    ovs_mutex_lock(&dev->mutex);
+
+    while (state->cur_queue < state->n_queues) {
+        uint32_t queue_id = state->queues[state->cur_queue++];
+
+        qos_conf = ovsrcu_get_protected(struct qos_conf *, &dev->qos_conf);
+        if (qos_conf && qos_conf->ops && qos_conf->ops->qos_queue_get) {
+            *queue_idp = queue_id;
+            error = qos_conf->ops->qos_queue_get(details, queue_id, qos_conf);
+            break;
+        }
+    }
+
+    ovs_mutex_unlock(&dev->mutex);
+
+    return error;
+}
+
+static int
+netdev_dpdk_queue_dump_done(const struct netdev *netdev OVS_UNUSED,
+                            void *state_)
+{
+    struct netdev_dpdk_queue_state *state = state_;
+
+    free(state->queues);
+    free(state);
+    return 0;
+}
+
 static struct egress_queue_policer *
 egress_policer_qos_find_queue(struct egress_policer *policer,
                               uint32_t queue_id);
@@ -3185,7 +3298,11 @@  egress_policer_pkt_handle(struct egress_policer *policer,
     if (queue_policer) {
         if (rte_meter_srtcm_color_blind_check(&queue_policer->egress_meter,
                                         time, pkt_len) != e_RTE_METER_GREEN) {
+            queue_policer->stats.tx_errors ++;
             return false;
+        } else {
+            queue_policer->stats.tx_bytes += pkt_len;
+            queue_policer->stats.tx_packets ++;
         }
     }
 
@@ -3246,6 +3363,8 @@  egress_policer_qos_queue_construct(const struct smap *details,
         hmap_insert(&policer->queue, &queue_policer->hmap_node,
                     hash_2words(queue_id, 0));
         queue_policer->queue_id = queue_id;
+        memset(&queue_policer->stats, 0, sizeof queue_policer->stats);
+        queue_policer->stats.created = rte_rdtsc();
     }
     egress_policer_details_to_param(details, &queue_policer->app_srtcm_params);
     err = rte_meter_srtcm_config(&queue_policer->egress_meter,
@@ -3291,6 +3410,31 @@  egress_policer_qos_queue_get(struct smap *details, uint32_t queue_id,
     return 0;
 }
 
+static int
+egress_policer_qos_queue_get_stats(const struct qos_conf *conf,
+                                   uint32_t queue_id,
+                                   struct netdev_queue_stats *stats)
+{
+    struct egress_policer *policer =
+        CONTAINER_OF(conf, struct egress_policer, qos_conf);
+
+    struct egress_queue_policer *queue_policer;
+    queue_policer = egress_policer_qos_find_queue(policer, queue_id);
+    if (!queue_policer) {
+        stats->tx_bytes = UINT64_MAX;
+        stats->tx_packets = UINT64_MAX;
+        stats->tx_errors = UINT64_MAX;
+        stats->created = LLONG_MIN;
+        return -1;
+    } else {
+        stats->tx_bytes = queue_policer->stats.tx_bytes;
+        stats->tx_packets = queue_policer->stats.tx_packets;
+        stats->tx_errors = queue_policer->stats.tx_errors;
+        stats->created = queue_policer->stats.created;
+        return 0;
+    }
+}
+
 static const struct dpdk_qos_ops egress_policer_ops = {
     "egress-policer",    /* qos_name */
     egress_policer_qos_construct,
@@ -3300,7 +3444,8 @@  static const struct dpdk_qos_ops egress_policer_ops = {
     egress_policer_run,
     egress_policer_qos_queue_construct,
     egress_policer_qos_queue_destruct,
-    egress_policer_qos_queue_get
+    egress_policer_qos_queue_get,
+    egress_policer_qos_queue_get_stats
 };
 
 static int
@@ -3485,10 +3630,10 @@  unlock:
     netdev_dpdk_get_queue,                                    \
     netdev_dpdk_set_queue,                                    \
     netdev_dpdk_delete_queue,                                 \
-    NULL,                       /* get_queue_stats */         \
-    NULL,                       /* queue_dump_start */        \
-    NULL,                       /* queue_dump_next */         \
-    NULL,                       /* queue_dump_done */         \
+    netdev_dpdk_get_queue_stats,                              \
+    netdev_dpdk_queue_dump_start,                             \
+    netdev_dpdk_queue_dump_next,                              \
+    netdev_dpdk_queue_dump_done,                              \
     NULL,                       /* dump_queue_stats */        \
                                                               \
     NULL,                       /* set_in4 */                 \