[dpdk-dev,5/5] rte_sched: allow reading without clearing

Message ID 1432750217-4186-6-git-send-email-stephen@networkplumber.org (mailing list archive)
State Changes Requested, archived
Headers

Commit Message

Stephen Hemminger May 27, 2015, 6:10 p.m. UTC
  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@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(-)
  

Comments

Cristian Dumitrescu June 4, 2015, 5:48 p.m. UTC | #1
> -----Original Message-----
> From: Stephen Hemminger [mailto:stephen@networkplumber.org]
> Sent: Wednesday, May 27, 2015 7:10 PM
> To: Dumitrescu, Cristian
> Cc: dev@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@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.
  
Thomas Monjalon July 9, 2015, 10:51 p.m. UTC | #2
2015-06-04 17:48, Dumitrescu, Cristian:
> From: Stephen Hemminger [mailto:stephen@networkplumber.org]
> > 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@networkplumber.org>
[...]
> > --- 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;
> 
> 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.

Patchwork status is now "Changes requested".
  

Patch

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;