sched: add 64-bit counter retrieval API
diff mbox series

Message ID 1531925499-938-1-git-send-email-alan.dewar@att.com
State New
Delegated to: Thomas Monjalon
Headers show
Series
  • sched: add 64-bit counter retrieval API
Related show

Checks

Context Check Description
ci/checkpatch success coding style OK
ci/Intel-compilation success Compilation OK

Commit Message

Alan Dewar July 18, 2018, 2:51 p.m. UTC
From: Alan Dewar <alan.dewar@att.com>

Add new APIs to retrieve counters in 64-bit wide fields.

Signed-off-by: Alan Dewar <alan.dewar@att.com>
---
 lib/librte_sched/rte_sched.c           | 72 ++++++++++++++++++++++++++++++++
 lib/librte_sched/rte_sched.h           | 76 ++++++++++++++++++++++++++++++++++
 lib/librte_sched/rte_sched_version.map |  2 +
 3 files changed, 150 insertions(+)

Comments

Alan Robertson July 23, 2018, 12:33 p.m. UTC | #1
Looks good to me.

Alan.

On Wed, Jul 18, 2018 at 3:51 PM,  <alangordondewar@gmail.com> wrote:
> From: Alan Dewar <alan.dewar@att.com>
>
> Add new APIs to retrieve counters in 64-bit wide fields.
>
> Signed-off-by: Alan Dewar <alan.dewar@att.com>
> ---
>  lib/librte_sched/rte_sched.c           | 72 ++++++++++++++++++++++++++++++++
>  lib/librte_sched/rte_sched.h           | 76 ++++++++++++++++++++++++++++++++++
>  lib/librte_sched/rte_sched_version.map |  2 +
>  3 files changed, 150 insertions(+)
>
> diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c
> index 9269e5c..4396366 100644
> --- a/lib/librte_sched/rte_sched.c
> +++ b/lib/librte_sched/rte_sched.c
> @@ -1070,6 +1070,43 @@ rte_sched_subport_read_stats(struct rte_sched_port *port,
>         return 0;
>  }
>
> +int __rte_experimental
> +rte_sched_subport_read_stats64(struct rte_sched_port *port,
> +                              uint32_t subport_id,
> +                              struct rte_sched_subport_stats64 *stats64,
> +                              uint32_t *tc_ov)
> +{
> +       struct rte_sched_subport *s;
> +       uint32_t tc;
> +
> +       /* Check user parameters */
> +       if (port == NULL || subport_id >= port->n_subports_per_port ||
> +           stats64 == NULL || tc_ov == NULL)
> +               return -1;
> +
> +       s = port->subport + subport_id;
> +
> +       /* Copy subport stats and clear */
> +       for (tc = 0; tc < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; tc++) {
> +               stats64->n_pkts_tc[tc] = s->stats.n_pkts_tc[tc];
> +               stats64->n_pkts_tc_dropped[tc] =
> +                       s->stats.n_pkts_tc_dropped[tc];
> +               stats64->n_bytes_tc[tc] = s->stats.n_bytes_tc[tc];
> +               stats64->n_bytes_tc_dropped[tc] =
> +                       s->stats.n_bytes_tc_dropped[tc];
> +#ifdef RTE_SCHED_RED
> +               stats64->n_pkts_red_dropped[tc] =
> +                       s->stats.n_pkts_red_dropped[tc];
> +#endif
> +       }
> +       memset(&s->stats, 0, sizeof(struct rte_sched_subport_stats));
> +
> +       /* Subport TC oversubscription status */
> +       *tc_ov = s->tc_ov;
> +
> +       return 0;
> +}
> +
>  int
>  rte_sched_queue_read_stats(struct rte_sched_port *port,
>         uint32_t queue_id,
> @@ -1099,6 +1136,41 @@ rte_sched_queue_read_stats(struct rte_sched_port *port,
>         return 0;
>  }
>
> +int __rte_experimental
> +rte_sched_queue_read_stats64(struct rte_sched_port *port,
> +       uint32_t queue_id,
> +       struct rte_sched_queue_stats64 *stats64,
> +       uint16_t *qlen)
> +{
> +       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)) ||
> +               (stats64 == NULL) ||
> +               (qlen == NULL)) {
> +               return -1;
> +       }
> +       q = port->queue + queue_id;
> +       qe = port->queue_extra + queue_id;
> +
> +       /* Copy queue stats and clear */
> +       stats64->n_pkts = qe->stats.n_pkts;
> +       stats64->n_pkts_dropped = qe->stats.n_pkts_dropped;
> +       stats64->n_bytes = qe->stats.n_bytes;
> +       stats64->n_bytes_dropped = qe->stats.n_bytes_dropped;
> +#ifdef RTE_SCHED_RED
> +       stats64->n_pkts_red_dropped = qe->stats.n_pkts_red_dropped;
> +#endif
> +       memset(&qe->stats, 0, sizeof(struct rte_sched_queue_stats));
> +
> +       /* Queue length */
> +       *qlen = q->qw - q->qr;
> +
> +       return 0;
> +}
> +
>  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 84fa896..f37a4d6 100644
> --- a/lib/librte_sched/rte_sched.h
> +++ b/lib/librte_sched/rte_sched.h
> @@ -141,6 +141,25 @@ struct rte_sched_subport_stats {
>  #endif
>  };
>
> +struct rte_sched_subport_stats64 {
> +       /* Packets */
> +       uint64_t n_pkts_tc[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE];
> +       /**< Number of packets successfully written */
> +       uint64_t n_pkts_tc_dropped[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE];
> +       /**< Number of packets dropped */
> +
> +       /* Bytes */
> +       uint64_t n_bytes_tc[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE];
> +       /**< Number of bytes successfully written for each traffic class */
> +       uint64_t n_bytes_tc_dropped[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE];
> +       /**< Number of bytes dropped for each traffic class */
> +
> +#ifdef RTE_SCHED_RED
> +       uint64_t n_pkts_red_dropped[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE];
> +       /**< Number of packets dropped by red */
> +#endif
> +};
> +
>  /*
>   * Pipe configuration parameters. The period and credits_per_period
>   * parameters are measured in bytes, with one byte meaning the time
> @@ -182,6 +201,19 @@ struct rte_sched_queue_stats {
>         uint32_t n_bytes_dropped;        /**< Bytes dropped */
>  };
>
> +struct rte_sched_queue_stats64 {
> +       /* Packets */
> +       uint64_t n_pkts;                 /**< Packets successfully written */
> +       uint64_t n_pkts_dropped;         /**< Packets dropped */
> +#ifdef RTE_SCHED_RED
> +       uint64_t n_pkts_red_dropped;     /**< Packets dropped by RED */
> +#endif
> +
> +       /* Bytes */
> +       uint64_t n_bytes;                /**< Bytes successfully written */
> +       uint64_t n_bytes_dropped;        /**< Bytes dropped */
> +};
> +
>  /** Port configuration parameters. */
>  struct rte_sched_port_params {
>         const char *name;                /**< String to be associated */
> @@ -330,6 +362,28 @@ rte_sched_subport_read_stats(struct rte_sched_port *port,
>         uint32_t *tc_ov);
>
>  /**
> + * Hierarchical scheduler subport statistics 64-bit read
> + *
> + * @param port
> + *   Handle to port scheduler instance
> + * @param subport_id
> + *   Subport ID
> + * @param stats64
> + *   Pointer to pre-allocated subport statistics structure where the 64-bit
> + *   statistics counters should be stored
> + * @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.
> + * @return
> + *   0 upon success, error code otherwise
> + */
> +int __rte_experimental
> +rte_sched_subport_read_stats64(struct rte_sched_port *port,
> +       uint32_t subport_id,
> +       struct rte_sched_subport_stats64 *stats64,
> +       uint32_t *tc_ov);
> +
> +/**
>   * Hierarchical scheduler queue statistics read
>   *
>   * @param port
> @@ -352,6 +406,28 @@ rte_sched_queue_read_stats(struct rte_sched_port *port,
>         uint16_t *qlen);
>
>  /**
> + * Hierarchical scheduler queue statistics 64-bit read
> + *
> + * @param port
> + *   Handle to port scheduler instance
> + * @param queue_id
> + *   Queue ID within port scheduler
> + * @param stats
> + *   Pointer to pre-allocated subport statistics structure where the
> + *   64-bit statistics counters should be stored
> + * @param qlen
> + *   Pointer to pre-allocated variable where the current queue length
> + *   should be stored.
> + * @return
> + *   0 upon success, error code otherwise
> + */
> +int __rte_experimental
> +rte_sched_queue_read_stats64(struct rte_sched_port *port,
> +       uint32_t queue_id,
> +       struct rte_sched_queue_stats64 *stats64,
> +       uint16_t *qlen);
> +
> +/**
>   * Scheduler hierarchy path write to packet descriptor. Typically
>   * called by the packet classification stage.
>   *
> diff --git a/lib/librte_sched/rte_sched_version.map b/lib/librte_sched/rte_sched_version.map
> index 7295887..01bf71a 100644
> --- a/lib/librte_sched/rte_sched_version.map
> +++ b/lib/librte_sched/rte_sched_version.map
> @@ -34,4 +34,6 @@ EXPERIMENTAL {
>         global:
>
>         rte_sched_port_pipe_profile_add;
> +       rte_sched_subport_read_stats64;
> +       rte_sched_queue_read_stats64;
>  };
> --
> 2.7.4
>
Stephen Hemminger July 23, 2018, 4:52 p.m. UTC | #2
On Wed, 18 Jul 2018 15:51:39 +0100
alangordondewar@gmail.com wrote:

> From: Alan Dewar <alan.dewar@att.com>
> 
> Add new APIs to retrieve counters in 64-bit wide fields.
> 
> Signed-off-by: Alan Dewar <alan.dewar@att.com>

Do you want to consider 64 bit counter roll over on 32 bit platform?
The problem is that incrementing an 64 bit value is not atomic on
32 bit cpu. The carry operation can race with reading.

The kernel has special case code to do restartable sequence for
accessing 64 bit counter on 32 bit CPU. These functions become
nop's on 64bit.
Alan Dewar July 25, 2018, 9:02 a.m. UTC | #3
Hi Stephen,

Sorry about the delay in responding to your comment.

Maybe I'm missing something but I don't consider 64-bit counter
rollover to be a problem.
The DPDK QoS stats are just 32-bits wide and are zeroed when read.  So
if we read them frequently enough the 32-bit counters won't wrap.

This new API is just a convenient way to read the 32-bit counters into
variables that are 64-bit wide which allows Vyatta to have a common
API slightly above the DPDK.

I'd hope that at some point in time the DPDK will move to 64-bit
counters, but there may be technical reasons why this can't happen
that I'm not aware of (support for 32-bit CPUs??)

Regards
Alan

On Mon, Jul 23, 2018 at 5:52 PM, Stephen Hemminger
<stephen@networkplumber.org> wrote:
> On Wed, 18 Jul 2018 15:51:39 +0100
> alangordondewar@gmail.com wrote:
>
>> From: Alan Dewar <alan.dewar@att.com>
>>
>> Add new APIs to retrieve counters in 64-bit wide fields.
>>
>> Signed-off-by: Alan Dewar <alan.dewar@att.com>
>
> Do you want to consider 64 bit counter roll over on 32 bit platform?
> The problem is that incrementing an 64 bit value is not atomic on
> 32 bit cpu. The carry operation can race with reading.
>
> The kernel has special case code to do restartable sequence for
> accessing 64 bit counter on 32 bit CPU. These functions become
> nop's on 64bit.

Patch
diff mbox series

diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c
index 9269e5c..4396366 100644
--- a/lib/librte_sched/rte_sched.c
+++ b/lib/librte_sched/rte_sched.c
@@ -1070,6 +1070,43 @@  rte_sched_subport_read_stats(struct rte_sched_port *port,
 	return 0;
 }
 
+int __rte_experimental
+rte_sched_subport_read_stats64(struct rte_sched_port *port,
+			       uint32_t subport_id,
+			       struct rte_sched_subport_stats64 *stats64,
+			       uint32_t *tc_ov)
+{
+	struct rte_sched_subport *s;
+	uint32_t tc;
+
+	/* Check user parameters */
+	if (port == NULL || subport_id >= port->n_subports_per_port ||
+	    stats64 == NULL || tc_ov == NULL)
+		return -1;
+
+	s = port->subport + subport_id;
+
+	/* Copy subport stats and clear */
+	for (tc = 0; tc < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; tc++) {
+		stats64->n_pkts_tc[tc] = s->stats.n_pkts_tc[tc];
+		stats64->n_pkts_tc_dropped[tc] =
+			s->stats.n_pkts_tc_dropped[tc];
+		stats64->n_bytes_tc[tc] = s->stats.n_bytes_tc[tc];
+		stats64->n_bytes_tc_dropped[tc] =
+			s->stats.n_bytes_tc_dropped[tc];
+#ifdef RTE_SCHED_RED
+		stats64->n_pkts_red_dropped[tc] =
+			s->stats.n_pkts_red_dropped[tc];
+#endif
+	}
+	memset(&s->stats, 0, sizeof(struct rte_sched_subport_stats));
+
+	/* Subport TC oversubscription status */
+	*tc_ov = s->tc_ov;
+
+	return 0;
+}
+
 int
 rte_sched_queue_read_stats(struct rte_sched_port *port,
 	uint32_t queue_id,
@@ -1099,6 +1136,41 @@  rte_sched_queue_read_stats(struct rte_sched_port *port,
 	return 0;
 }
 
+int __rte_experimental
+rte_sched_queue_read_stats64(struct rte_sched_port *port,
+	uint32_t queue_id,
+	struct rte_sched_queue_stats64 *stats64,
+	uint16_t *qlen)
+{
+	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)) ||
+		(stats64 == NULL) ||
+		(qlen == NULL)) {
+		return -1;
+	}
+	q = port->queue + queue_id;
+	qe = port->queue_extra + queue_id;
+
+	/* Copy queue stats and clear */
+	stats64->n_pkts = qe->stats.n_pkts;
+	stats64->n_pkts_dropped = qe->stats.n_pkts_dropped;
+	stats64->n_bytes = qe->stats.n_bytes;
+	stats64->n_bytes_dropped = qe->stats.n_bytes_dropped;
+#ifdef RTE_SCHED_RED
+	stats64->n_pkts_red_dropped = qe->stats.n_pkts_red_dropped;
+#endif
+	memset(&qe->stats, 0, sizeof(struct rte_sched_queue_stats));
+
+	/* Queue length */
+	*qlen = q->qw - q->qr;
+
+	return 0;
+}
+
 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 84fa896..f37a4d6 100644
--- a/lib/librte_sched/rte_sched.h
+++ b/lib/librte_sched/rte_sched.h
@@ -141,6 +141,25 @@  struct rte_sched_subport_stats {
 #endif
 };
 
+struct rte_sched_subport_stats64 {
+	/* Packets */
+	uint64_t n_pkts_tc[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE];
+	/**< Number of packets successfully written */
+	uint64_t n_pkts_tc_dropped[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE];
+	/**< Number of packets dropped */
+
+	/* Bytes */
+	uint64_t n_bytes_tc[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE];
+	/**< Number of bytes successfully written for each traffic class */
+	uint64_t n_bytes_tc_dropped[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE];
+	/**< Number of bytes dropped for each traffic class */
+
+#ifdef RTE_SCHED_RED
+	uint64_t n_pkts_red_dropped[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE];
+	/**< Number of packets dropped by red */
+#endif
+};
+
 /*
  * Pipe configuration parameters. The period and credits_per_period
  * parameters are measured in bytes, with one byte meaning the time
@@ -182,6 +201,19 @@  struct rte_sched_queue_stats {
 	uint32_t n_bytes_dropped;        /**< Bytes dropped */
 };
 
+struct rte_sched_queue_stats64 {
+	/* Packets */
+	uint64_t n_pkts;                 /**< Packets successfully written */
+	uint64_t n_pkts_dropped;         /**< Packets dropped */
+#ifdef RTE_SCHED_RED
+	uint64_t n_pkts_red_dropped;	 /**< Packets dropped by RED */
+#endif
+
+	/* Bytes */
+	uint64_t n_bytes;                /**< Bytes successfully written */
+	uint64_t n_bytes_dropped;        /**< Bytes dropped */
+};
+
 /** Port configuration parameters. */
 struct rte_sched_port_params {
 	const char *name;                /**< String to be associated */
@@ -330,6 +362,28 @@  rte_sched_subport_read_stats(struct rte_sched_port *port,
 	uint32_t *tc_ov);
 
 /**
+ * Hierarchical scheduler subport statistics 64-bit read
+ *
+ * @param port
+ *   Handle to port scheduler instance
+ * @param subport_id
+ *   Subport ID
+ * @param stats64
+ *   Pointer to pre-allocated subport statistics structure where the 64-bit
+ *   statistics counters should be stored
+ * @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.
+ * @return
+ *   0 upon success, error code otherwise
+ */
+int __rte_experimental
+rte_sched_subport_read_stats64(struct rte_sched_port *port,
+	uint32_t subport_id,
+	struct rte_sched_subport_stats64 *stats64,
+	uint32_t *tc_ov);
+
+/**
  * Hierarchical scheduler queue statistics read
  *
  * @param port
@@ -352,6 +406,28 @@  rte_sched_queue_read_stats(struct rte_sched_port *port,
 	uint16_t *qlen);
 
 /**
+ * Hierarchical scheduler queue statistics 64-bit read
+ *
+ * @param port
+ *   Handle to port scheduler instance
+ * @param queue_id
+ *   Queue ID within port scheduler
+ * @param stats
+ *   Pointer to pre-allocated subport statistics structure where the
+ *   64-bit statistics counters should be stored
+ * @param qlen
+ *   Pointer to pre-allocated variable where the current queue length
+ *   should be stored.
+ * @return
+ *   0 upon success, error code otherwise
+ */
+int __rte_experimental
+rte_sched_queue_read_stats64(struct rte_sched_port *port,
+	uint32_t queue_id,
+	struct rte_sched_queue_stats64 *stats64,
+	uint16_t *qlen);
+
+/**
  * Scheduler hierarchy path write to packet descriptor. Typically
  * called by the packet classification stage.
  *
diff --git a/lib/librte_sched/rte_sched_version.map b/lib/librte_sched/rte_sched_version.map
index 7295887..01bf71a 100644
--- a/lib/librte_sched/rte_sched_version.map
+++ b/lib/librte_sched/rte_sched_version.map
@@ -34,4 +34,6 @@  EXPERIMENTAL {
 	global:
 
 	rte_sched_port_pipe_profile_add;
+	rte_sched_subport_read_stats64;
+	rte_sched_queue_read_stats64;
 };