> -----Original Message----- > From: Stephen Hemminger [mailto:stephen at networkplumber.org] > Sent: Wednesday, May 27, 2015 7:10 PM > To: Dumitrescu, Cristian > Cc: dev at dpdk.org; Stephen Hemminger > Subject: [PATCH 5/5] rte_sched: allow reading without clearing > > The rte_sched statistics API should allow reading statistics without > clearing. Make auto-clear optional. In this version, this is handled > by deprecating the old API and adding a new one. > > Signed-off-by: Stephen Hemminger <stephen at networkplumber.org> > --- > app/test/test_sched.c | 4 +-- > lib/librte_sched/rte_sched.c | 65 > +++++++++++++++++++++------------- > lib/librte_sched/rte_sched.h | 37 ++++++++++++++----- > lib/librte_sched/rte_sched_version.map | 2 ++ > 4 files changed, 74 insertions(+), 34 deletions(-) > > diff --git a/app/test/test_sched.c b/app/test/test_sched.c > index c7239f8..03f89b4 100644 > --- a/app/test/test_sched.c > +++ b/app/test/test_sched.c > @@ -198,13 +198,13 @@ test_sched(void) > > struct rte_sched_subport_stats subport_stats; > uint32_t tc_ov; > - rte_sched_subport_read_stats(port, SUBPORT, &subport_stats, > &tc_ov); > + rte_sched_subport_stats(port, SUBPORT, &subport_stats, &tc_ov, > 1); > #if 0 > TEST_ASSERT_EQUAL(subport_stats.n_pkts_tc[TC-1], 10, "Wrong > subport stats\n"); > #endif > struct rte_sched_queue_stats queue_stats; > uint16_t qlen; > - rte_sched_queue_read_stats(port, QUEUE, &queue_stats, &qlen); > + rte_sched_queue_stats(port, QUEUE, &queue_stats, &qlen, 1); > #if 0 > TEST_ASSERT_EQUAL(queue_stats.n_pkts, 10, "Wrong queue > stats\n"); > #endif > diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c > index 9c9419d..b4d7edd 100644 > --- a/lib/librte_sched/rte_sched.c > +++ b/lib/librte_sched/rte_sched.c > @@ -965,61 +965,78 @@ rte_sched_port_pkt_read_color(const struct > rte_mbuf *pkt) > } > > int > -rte_sched_subport_read_stats(struct rte_sched_port *port, > - uint32_t subport_id, > - struct rte_sched_subport_stats *stats, > - uint32_t *tc_ov) > +rte_sched_subport_stats(struct rte_sched_port *port, uint32_t > subport_id, > + struct rte_sched_subport_stats *stats, > + uint32_t *tc_ov, int clear) > { > struct rte_sched_subport *s; > > /* Check user parameters */ > - if ((port == NULL) || > - (subport_id >= port->n_subports_per_port) || > - (stats == NULL) || > - (tc_ov == NULL)) { > + if (port == NULL || subport_id >= port->n_subports_per_port) > return -1; > - } > + > s = port->subport + subport_id; > > /* Copy subport stats and clear */ > - memcpy(stats, &s->stats, sizeof(struct rte_sched_subport_stats)); > - memset(&s->stats, 0, sizeof(struct rte_sched_subport_stats)); > + if (stats) > + *stats = s->stats; > + if (clear) > + memset(&s->stats, 0, sizeof(struct > rte_sched_subport_stats)); > > /* Subport TC ovesubscription status */ > - *tc_ov = s->tc_ov; > + if (tc_ov) > + *tc_ov = s->tc_ov; > > return 0; > } > > +/* Deprecated API, always clears */ > int > -rte_sched_queue_read_stats(struct rte_sched_port *port, > - uint32_t queue_id, > - struct rte_sched_queue_stats *stats, > - uint16_t *qlen) > +rte_sched_subport_read_stats(struct rte_sched_port *port, uint32_t > subport_id, > + struct rte_sched_subport_stats *stats, > + uint32_t *tc_ov) > +{ > + return rte_sched_subport_stats(port, subport_id, stats, tc_ov, 1); > +} > + > +int > +rte_sched_queue_stats(struct rte_sched_port *port, uint32_t queue_id, > + struct rte_sched_queue_stats *stats, > + uint16_t *qlen, int clear) > { > struct rte_sched_queue *q; > struct rte_sched_queue_extra *qe; > > /* Check user parameters */ > - if ((port == NULL) || > - (queue_id >= rte_sched_port_queues_per_port(port)) || > - (stats == NULL) || > - (qlen == NULL)) { > + if (port == NULL || queue_id >= > rte_sched_port_queues_per_port(port)) > return -1; > - } > + > q = port->queue + queue_id; > qe = port->queue_extra + queue_id; > > /* Copy queue stats and clear */ > - memcpy(stats, &qe->stats, sizeof(struct rte_sched_queue_stats)); > - memset(&qe->stats, 0, sizeof(struct rte_sched_queue_stats)); > + if (stats) > + *stats = qe->stats; > + if (clear) > + memset(&qe->stats, 0, sizeof(struct > rte_sched_queue_stats)); > > /* Queue length */ > - *qlen = q->qw - q->qr; > + if (qlen) > + *qlen = q->qw - q->qr; > > return 0; > } > > +/* Deprecated API, always clears */ > +int > +rte_sched_queue_read_stats(struct rte_sched_port *port, > + uint32_t queue_id, > + struct rte_sched_queue_stats *stats, > + uint16_t *qlen) > +{ > + return rte_sched_queue_stats(port, queue_id, stats, qlen, 1); > +} > + > static inline uint32_t > rte_sched_port_qindex(struct rte_sched_port *port, uint32_t subport, > uint32_t pipe, uint32_t traffic_class, uint32_t queue) > { > diff --git a/lib/librte_sched/rte_sched.h b/lib/librte_sched/rte_sched.h > index f7c0b8e..053454c 100644 > --- a/lib/librte_sched/rte_sched.h > +++ b/lib/librte_sched/rte_sched.h > @@ -300,14 +300,24 @@ rte_sched_port_get_memory_footprint(struct > rte_sched_port_params *params); > * @param tc_ov > * Pointer to pre-allocated 4-entry array where the oversubscription status > for > * each of the 4 subport traffic classes should be stored. > + * @parm clear > + * Reset statistics after read > + * > * @return > * 0 upon success, error code otherwise > */ > int > -rte_sched_subport_read_stats(struct rte_sched_port *port, > - uint32_t subport_id, > - struct rte_sched_subport_stats *stats, > - uint32_t *tc_ov); > +rte_sched_subport_stats(struct rte_sched_port *port, uint32_t > subport_id, > + struct rte_sched_subport_stats *stats, > + uint32_t *tc_ov, int clear); > + > +/* Note: use rte_sched_subport_stats() instead, > + * which allows separate read and clear. > + */ > +int > +rte_sched_subport_read_stats(struct rte_sched_port *port, uint32_t > subport_id, > + struct rte_sched_subport_stats *stats, > + uint32_t *tc_ov) __attribute__((deprecated)); > > /** > * Hierarchical scheduler queue statistics read > @@ -321,14 +331,25 @@ rte_sched_subport_read_stats(struct > rte_sched_port *port, > * counters should be stored > * @param qlen > * Pointer to pre-allocated variable where the current queue length should > be stored. > + * @parm clear > + * Reset statistics after read > * @return > * 0 upon success, error code otherwise > */ > int > -rte_sched_queue_read_stats(struct rte_sched_port *port, > - uint32_t queue_id, > - struct rte_sched_queue_stats *stats, > - uint16_t *qlen); > +rte_sched_queue_stats(struct rte_sched_port *port, > + uint32_t queue_id, > + struct rte_sched_queue_stats *stats, > + uint16_t *qlen, int clear); > + > + > +/* Note: use rte_sched_queue_stats() instead > + * which allows separate read and clear. > + */ > +int > +rte_sched_queue_read_stats(struct rte_sched_port *port, uint32_t > queue_id, > + struct rte_sched_queue_stats *stats, > + uint16_t *qlen) __attribute__((deprecated)); > > /** > * Scheduler hierarchy path write to packet descriptor. Typically called by > the > diff --git a/lib/librte_sched/rte_sched_version.map > b/lib/librte_sched/rte_sched_version.map > index 6626a74..cdbaeb7 100644 > --- a/lib/librte_sched/rte_sched_version.map > +++ b/lib/librte_sched/rte_sched_version.map > @@ -14,8 +14,10 @@ DPDK_2.0 { > rte_sched_port_enqueue; > rte_sched_port_free; > rte_sched_port_get_memory_footprint; > + rte_sched_queue_stats; > rte_sched_queue_read_stats; > rte_sched_subport_config; > + rte_sched_subport_stats; > rte_sched_subport_read_stats; > rte_sched_port_pkt_write; > rte_sched_port_pkt_read_tree_path; > -- > 2.1.4
If we plan to obsolete API function rte_sched_queue_read_stats() and have people use the new API function rte_sched_queue_stats(), we should replace every usage of the obsolete function with call to new function. We need to do this in examples/qos_sched and app/test.