> 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 <[email protected]> > --- > 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 > [email protected] > https://mail.openvswitch.org/mailman/listinfo/ovs-dev _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
