DPDK patches and discussions
 help / color / mirror / Atom feed
* [PATCH v3 0/5] latencystats: cleanups
       [not found] <0240408195036.182545-1-stephen@networkplumber.org>
@ 2024-04-17 17:07 ` Stephen Hemminger
  2024-04-17 17:07   ` [PATCH v3 1/5] latencystats: replace use of VLA Stephen Hemminger
                     ` (4 more replies)
  0 siblings, 5 replies; 14+ messages in thread
From: Stephen Hemminger @ 2024-04-17 17:07 UTC (permalink / raw)
  To: dev; +Cc: Stephen Hemminger

Latencystats uses variable length array and floating point when they
are not necessary to acheive the same result. While testing also noticed
that the code was computing wrong values on my test system, and that
include files were missing.

Stephen Hemminger (5):
  latencystats: replace use of VLA
  latencystats: handle fractional cycles per ns
  latencystats: do not use floating point
  latencystats: fix log messages
  latencystats: include file cleanup

 lib/latencystats/rte_latencystats.c | 175 +++++++++++++++-------------
 1 file changed, 92 insertions(+), 83 deletions(-)

-- 
2.43.0


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH v3 1/5] latencystats: replace use of VLA
  2024-04-17 17:07 ` [PATCH v3 0/5] latencystats: cleanups Stephen Hemminger
@ 2024-04-17 17:07   ` Stephen Hemminger
  2024-04-17 18:03     ` Morten Brørup
  2024-04-18  0:00     ` Tyler Retzlaff
  2024-04-17 17:07   ` [PATCH v3 2/5] latencystats: handle fractional cycles per ns Stephen Hemminger
                     ` (3 subsequent siblings)
  4 siblings, 2 replies; 14+ messages in thread
From: Stephen Hemminger @ 2024-04-17 17:07 UTC (permalink / raw)
  To: dev; +Cc: Stephen Hemminger, Reshma Pattan

The temporary array latencystats is not needed if the algorithm
is converted into one pass.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 lib/latencystats/rte_latencystats.c | 31 +++++++++++++++--------------
 1 file changed, 16 insertions(+), 15 deletions(-)

diff --git a/lib/latencystats/rte_latencystats.c b/lib/latencystats/rte_latencystats.c
index 4ea9b0d75b..9b345bfb33 100644
--- a/lib/latencystats/rte_latencystats.c
+++ b/lib/latencystats/rte_latencystats.c
@@ -157,9 +157,9 @@ calc_latency(uint16_t pid __rte_unused,
 		uint16_t nb_pkts,
 		void *_ __rte_unused)
 {
-	unsigned int i, cnt = 0;
+	unsigned int i;
 	uint64_t now;
-	float latency[nb_pkts];
+	float latency;
 	static float prev_latency;
 	/*
 	 * Alpha represents degree of weighting decrease in EWMA,
@@ -169,13 +169,14 @@ calc_latency(uint16_t pid __rte_unused,
 	const float alpha = 0.2;
 
 	now = rte_rdtsc();
-	for (i = 0; i < nb_pkts; i++) {
-		if (pkts[i]->ol_flags & timestamp_dynflag)
-			latency[cnt++] = now - *timestamp_dynfield(pkts[i]);
-	}
 
 	rte_spinlock_lock(&glob_stats->lock);
-	for (i = 0; i < cnt; i++) {
+	for (i = 0; i < nb_pkts; i++) {
+		if (!(pkts[i]->ol_flags & timestamp_dynflag))
+			continue;
+
+		latency = now - *timestamp_dynfield(pkts[i]);
+
 		/*
 		 * The jitter is calculated as statistical mean of interpacket
 		 * delay variation. The "jitter estimate" is computed by taking
@@ -187,22 +188,22 @@ calc_latency(uint16_t pid __rte_unused,
 		 * Reference: Calculated as per RFC 5481, sec 4.1,
 		 * RFC 3393 sec 4.5, RFC 1889 sec.
 		 */
-		glob_stats->jitter +=  (fabsf(prev_latency - latency[i])
+		glob_stats->jitter +=  (fabsf(prev_latency - latency)
 					- glob_stats->jitter)/16;
 		if (glob_stats->min_latency == 0)
-			glob_stats->min_latency = latency[i];
-		else if (latency[i] < glob_stats->min_latency)
-			glob_stats->min_latency = latency[i];
-		else if (latency[i] > glob_stats->max_latency)
-			glob_stats->max_latency = latency[i];
+			glob_stats->min_latency = latency;
+		else if (latency < glob_stats->min_latency)
+			glob_stats->min_latency = latency;
+		else if (latency > glob_stats->max_latency)
+			glob_stats->max_latency = latency;
 		/*
 		 * The average latency is measured using exponential moving
 		 * average, i.e. using EWMA
 		 * https://en.wikipedia.org/wiki/Moving_average
 		 */
 		glob_stats->avg_latency +=
-			alpha * (latency[i] - glob_stats->avg_latency);
-		prev_latency = latency[i];
+			alpha * (latency - glob_stats->avg_latency);
+		prev_latency = latency;
 	}
 	rte_spinlock_unlock(&glob_stats->lock);
 
-- 
2.43.0


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH v3 2/5] latencystats: handle fractional cycles per ns
  2024-04-17 17:07 ` [PATCH v3 0/5] latencystats: cleanups Stephen Hemminger
  2024-04-17 17:07   ` [PATCH v3 1/5] latencystats: replace use of VLA Stephen Hemminger
@ 2024-04-17 17:07   ` Stephen Hemminger
  2024-04-18  0:03     ` Tyler Retzlaff
  2024-04-17 17:07   ` [PATCH v3 3/5] latencystats: do not use floating point Stephen Hemminger
                     ` (2 subsequent siblings)
  4 siblings, 1 reply; 14+ messages in thread
From: Stephen Hemminger @ 2024-04-17 17:07 UTC (permalink / raw)
  To: dev; +Cc: Stephen Hemminger, Reshma Pattan

The timer_hz is not always an integral number of nanoseconds.
For examples, cycles per nanoseconds on my test system is 2.8.
Fix by using floating point where needed.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 lib/latencystats/rte_latencystats.c | 12 +++++-------
 1 file changed, 5 insertions(+), 7 deletions(-)

diff --git a/lib/latencystats/rte_latencystats.c b/lib/latencystats/rte_latencystats.c
index 9b345bfb33..fe8c3c563a 100644
--- a/lib/latencystats/rte_latencystats.c
+++ b/lib/latencystats/rte_latencystats.c
@@ -19,10 +19,10 @@
 #define NS_PER_SEC 1E9
 
 /** Clock cycles per nano second */
-static uint64_t
+static float
 latencystat_cycles_per_ns(void)
 {
-	return rte_get_timer_hz() / NS_PER_SEC;
+	return (double)rte_get_timer_hz() / NS_PER_SEC;
 }
 
 RTE_LOG_REGISTER_DEFAULT(latencystat_logtype, INFO);
@@ -89,8 +89,7 @@ rte_latencystats_update(void)
 	for (i = 0; i < NUM_LATENCY_STATS; i++) {
 		stats_ptr = RTE_PTR_ADD(glob_stats,
 				lat_stats_strings[i].offset);
-		values[i] = (uint64_t)floor((*stats_ptr)/
-				latencystat_cycles_per_ns());
+		values[i] = floor(*stats_ptr / latencystat_cycles_per_ns());
 	}
 
 	ret = rte_metrics_update_values(RTE_METRICS_GLOBAL,
@@ -112,8 +111,7 @@ rte_latencystats_fill_values(struct rte_metric_value *values)
 		stats_ptr = RTE_PTR_ADD(glob_stats,
 				lat_stats_strings[i].offset);
 		values[i].key = i;
-		values[i].value = (uint64_t)floor((*stats_ptr)/
-						latencystat_cycles_per_ns());
+		values[i].value = floor(*stats_ptr / latencystat_cycles_per_ns());
 	}
 }
 
@@ -237,7 +235,7 @@ rte_latencystats_init(uint64_t app_samp_intvl,
 
 	glob_stats = mz->addr;
 	rte_spinlock_init(&glob_stats->lock);
-	samp_intvl = app_samp_intvl * latencystat_cycles_per_ns();
+	samp_intvl = floor(app_samp_intvl * latencystat_cycles_per_ns());
 
 	/** Register latency stats with stats library */
 	for (i = 0; i < NUM_LATENCY_STATS; i++)
-- 
2.43.0


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH v3 3/5] latencystats: do not use floating point
  2024-04-17 17:07 ` [PATCH v3 0/5] latencystats: cleanups Stephen Hemminger
  2024-04-17 17:07   ` [PATCH v3 1/5] latencystats: replace use of VLA Stephen Hemminger
  2024-04-17 17:07   ` [PATCH v3 2/5] latencystats: handle fractional cycles per ns Stephen Hemminger
@ 2024-04-17 17:07   ` Stephen Hemminger
  2024-04-18  0:10     ` Tyler Retzlaff
  2024-04-17 17:07   ` [PATCH v3 4/5] latencystats: fix log messages Stephen Hemminger
  2024-04-17 17:07   ` [PATCH v3 5/5] latencystats: include file cleanup Stephen Hemminger
  4 siblings, 1 reply; 14+ messages in thread
From: Stephen Hemminger @ 2024-04-17 17:07 UTC (permalink / raw)
  To: dev; +Cc: Stephen Hemminger, Reshma Pattan

The cycle counts do not need to be stored as floating point.
Instead keep track of latency in cycles, and convert to
nanoseconds when read.

Change Exponential Weighted Moving Average weight from .2 to .25
to avoid use of floating point for that.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 lib/latencystats/rte_latencystats.c | 37 +++++++++++------------------
 1 file changed, 14 insertions(+), 23 deletions(-)

diff --git a/lib/latencystats/rte_latencystats.c b/lib/latencystats/rte_latencystats.c
index fe8c3c563a..11bd0ea4ae 100644
--- a/lib/latencystats/rte_latencystats.c
+++ b/lib/latencystats/rte_latencystats.c
@@ -47,10 +47,10 @@ static uint64_t timer_tsc;
 static uint64_t prev_tsc;
 
 struct rte_latency_stats {
-	float min_latency; /**< Minimum latency in nano seconds */
-	float avg_latency; /**< Average latency in nano seconds */
-	float max_latency; /**< Maximum latency in nano seconds */
-	float jitter; /** Latency variation */
+	uint64_t min_latency; /**< Minimum latency */
+	uint64_t avg_latency; /**< Average latency */
+	uint64_t max_latency; /**< Maximum latency */
+	uint64_t jitter; /** Latency variation */
 	rte_spinlock_t lock; /** Latency calculation lock */
 };
 
@@ -82,13 +82,12 @@ int32_t
 rte_latencystats_update(void)
 {
 	unsigned int i;
-	float *stats_ptr = NULL;
 	uint64_t values[NUM_LATENCY_STATS] = {0};
 	int ret;
 
 	for (i = 0; i < NUM_LATENCY_STATS; i++) {
-		stats_ptr = RTE_PTR_ADD(glob_stats,
-				lat_stats_strings[i].offset);
+		const uint64_t *stats_ptr = RTE_PTR_ADD(glob_stats,
+							lat_stats_strings[i].offset);
 		values[i] = floor(*stats_ptr / latencystat_cycles_per_ns());
 	}
 
@@ -105,11 +104,10 @@ static void
 rte_latencystats_fill_values(struct rte_metric_value *values)
 {
 	unsigned int i;
-	float *stats_ptr = NULL;
 
 	for (i = 0; i < NUM_LATENCY_STATS; i++) {
-		stats_ptr = RTE_PTR_ADD(glob_stats,
-				lat_stats_strings[i].offset);
+		const uint64_t *stats_ptr = RTE_PTR_ADD(glob_stats,
+							lat_stats_strings[i].offset);
 		values[i].key = i;
 		values[i].value = floor(*stats_ptr / latencystat_cycles_per_ns());
 	}
@@ -156,15 +154,8 @@ calc_latency(uint16_t pid __rte_unused,
 		void *_ __rte_unused)
 {
 	unsigned int i;
-	uint64_t now;
-	float latency;
-	static float prev_latency;
-	/*
-	 * Alpha represents degree of weighting decrease in EWMA,
-	 * a constant smoothing factor between 0 and 1. The value
-	 * is used below for measuring average latency.
-	 */
-	const float alpha = 0.2;
+	uint64_t now, latency;
+	static uint64_t prev_latency;
 
 	now = rte_rdtsc();
 
@@ -186,8 +177,7 @@ calc_latency(uint16_t pid __rte_unused,
 		 * Reference: Calculated as per RFC 5481, sec 4.1,
 		 * RFC 3393 sec 4.5, RFC 1889 sec.
 		 */
-		glob_stats->jitter +=  (fabsf(prev_latency - latency)
-					- glob_stats->jitter)/16;
+		glob_stats->jitter += ((prev_latency - latency) - glob_stats->jitter) / 16;
 		if (glob_stats->min_latency == 0)
 			glob_stats->min_latency = latency;
 		else if (latency < glob_stats->min_latency)
@@ -198,9 +188,10 @@ calc_latency(uint16_t pid __rte_unused,
 		 * The average latency is measured using exponential moving
 		 * average, i.e. using EWMA
 		 * https://en.wikipedia.org/wiki/Moving_average
+		 *
+		 * Alpha is .25
 		 */
-		glob_stats->avg_latency +=
-			alpha * (latency - glob_stats->avg_latency);
+		glob_stats->avg_latency += (latency - glob_stats->avg_latency) / 4;
 		prev_latency = latency;
 	}
 	rte_spinlock_unlock(&glob_stats->lock);
-- 
2.43.0


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH v3 4/5] latencystats: fix log messages
  2024-04-17 17:07 ` [PATCH v3 0/5] latencystats: cleanups Stephen Hemminger
                     ` (2 preceding siblings ...)
  2024-04-17 17:07   ` [PATCH v3 3/5] latencystats: do not use floating point Stephen Hemminger
@ 2024-04-17 17:07   ` Stephen Hemminger
  2024-04-18  0:13     ` Tyler Retzlaff
  2024-04-17 17:07   ` [PATCH v3 5/5] latencystats: include file cleanup Stephen Hemminger
  4 siblings, 1 reply; 14+ messages in thread
From: Stephen Hemminger @ 2024-04-17 17:07 UTC (permalink / raw)
  To: dev; +Cc: Stephen Hemminger, Reshma Pattan

All messages that because of an error should be at log level
NOTICE or above. Do not break log messages across lines.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 lib/latencystats/rte_latencystats.c | 30 ++++++++++++++---------------
 1 file changed, 15 insertions(+), 15 deletions(-)

diff --git a/lib/latencystats/rte_latencystats.c b/lib/latencystats/rte_latencystats.c
index 11bd0ea4ae..62038a9f5d 100644
--- a/lib/latencystats/rte_latencystats.c
+++ b/lib/latencystats/rte_latencystats.c
@@ -235,7 +235,7 @@ rte_latencystats_init(uint64_t app_samp_intvl,
 	latency_stats_index = rte_metrics_reg_names(ptr_strings,
 							NUM_LATENCY_STATS);
 	if (latency_stats_index < 0) {
-		LATENCY_STATS_LOG(DEBUG,
+		LATENCY_STATS_LOG(ERR,
 			"Failed to register latency stats names");
 		return -1;
 	}
@@ -255,7 +255,7 @@ rte_latencystats_init(uint64_t app_samp_intvl,
 
 		ret = rte_eth_dev_info_get(pid, &dev_info);
 		if (ret != 0) {
-			LATENCY_STATS_LOG(INFO,
+			LATENCY_STATS_LOG(NOTICE,
 				"Error during getting device (port %u) info: %s",
 				pid, strerror(-ret));
 
@@ -267,18 +267,18 @@ rte_latencystats_init(uint64_t app_samp_intvl,
 			cbs->cb = rte_eth_add_first_rx_callback(pid, qid,
 					add_time_stamps, user_cb);
 			if (!cbs->cb)
-				LATENCY_STATS_LOG(INFO, "Failed to "
-					"register Rx callback for pid=%d, "
-					"qid=%d", pid, qid);
+				LATENCY_STATS_LOG(NOTICE,
+					"Failed to register Rx callback for pid=%u, qid=%u",
+					pid, qid);
 		}
 		for (qid = 0; qid < dev_info.nb_tx_queues; qid++) {
 			cbs = &tx_cbs[pid][qid];
 			cbs->cb =  rte_eth_add_tx_callback(pid, qid,
 					calc_latency, user_cb);
 			if (!cbs->cb)
-				LATENCY_STATS_LOG(INFO, "Failed to "
-					"register Tx callback for pid=%d, "
-					"qid=%d", pid, qid);
+				LATENCY_STATS_LOG(NOTICE,
+					"Failed to register Tx callback for pid=%u, qid=%u",
+					pid, qid);
 		}
 	}
 	return 0;
@@ -299,7 +299,7 @@ rte_latencystats_uninit(void)
 
 		ret = rte_eth_dev_info_get(pid, &dev_info);
 		if (ret != 0) {
-			LATENCY_STATS_LOG(INFO,
+			LATENCY_STATS_LOG(NOTICE,
 				"Error during getting device (port %u) info: %s",
 				pid, strerror(-ret));
 
@@ -310,17 +310,17 @@ rte_latencystats_uninit(void)
 			cbs = &rx_cbs[pid][qid];
 			ret = rte_eth_remove_rx_callback(pid, qid, cbs->cb);
 			if (ret)
-				LATENCY_STATS_LOG(INFO, "failed to "
-					"remove Rx callback for pid=%d, "
-					"qid=%d", pid, qid);
+				LATENCY_STATS_LOG(NOTICE,
+					"Failed to remove Rx callback for pid=%u, qid=%u",
+					pid, qid);
 		}
 		for (qid = 0; qid < dev_info.nb_tx_queues; qid++) {
 			cbs = &tx_cbs[pid][qid];
 			ret = rte_eth_remove_tx_callback(pid, qid, cbs->cb);
 			if (ret)
-				LATENCY_STATS_LOG(INFO, "failed to "
-					"remove Tx callback for pid=%d, "
-					"qid=%d", pid, qid);
+				LATENCY_STATS_LOG(NOTICE,
+					"Failed to remove Tx callback for pid=%u, qid=%u",
+					pid, qid);
 		}
 	}
 
-- 
2.43.0


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH v3 5/5] latencystats: include file cleanup
  2024-04-17 17:07 ` [PATCH v3 0/5] latencystats: cleanups Stephen Hemminger
                     ` (3 preceding siblings ...)
  2024-04-17 17:07   ` [PATCH v3 4/5] latencystats: fix log messages Stephen Hemminger
@ 2024-04-17 17:07   ` Stephen Hemminger
  2024-04-17 17:30     ` Bruce Richardson
  4 siblings, 1 reply; 14+ messages in thread
From: Stephen Hemminger @ 2024-04-17 17:07 UTC (permalink / raw)
  To: dev; +Cc: Stephen Hemminger, Reshma Pattan

Include what is used here.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 lib/latencystats/rte_latencystats.c | 85 ++++++++++++++++++-----------
 1 file changed, 52 insertions(+), 33 deletions(-)

diff --git a/lib/latencystats/rte_latencystats.c b/lib/latencystats/rte_latencystats.c
index 62038a9f5d..31e7a6eb88 100644
--- a/lib/latencystats/rte_latencystats.c
+++ b/lib/latencystats/rte_latencystats.c
@@ -2,16 +2,25 @@
  * Copyright(c) 2018 Intel Corporation
  */
 
+#include <errno.h>
 #include <math.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <string.h>
 
-#include <rte_string_fns.h>
-#include <rte_mbuf_dyn.h>
-#include <rte_log.h>
+#include <rte_common.h>
 #include <rte_cycles.h>
+#include <rte_eal.h>
+#include <rte_errno.h>
 #include <rte_ethdev.h>
-#include <rte_metrics.h>
-#include <rte_memzone.h>
 #include <rte_lcore.h>
+#include <rte_log.h>
+#include <rte_mbuf.h>
+#include <rte_mbuf_dyn.h>
+#include <rte_memzone.h>
+#include <rte_metrics.h>
+#include <rte_spinlock.h>
+#include <rte_string_fns.h>
 
 #include "rte_latencystats.h"
 
@@ -148,14 +157,15 @@ add_time_stamps(uint16_t pid __rte_unused,
 
 static uint16_t
 calc_latency(uint16_t pid __rte_unused,
-		uint16_t qid __rte_unused,
-		struct rte_mbuf **pkts,
-		uint16_t nb_pkts,
-		void *_ __rte_unused)
+	     uint16_t qid __rte_unused,
+	     struct rte_mbuf **pkts,
+	     uint16_t nb_pkts,
+	     void *_ __rte_unused)
 {
 	unsigned int i;
 	uint64_t now, latency;
 	static uint64_t prev_latency;
+	static bool first_sample = true;
 
 	now = rte_rdtsc();
 
@@ -166,32 +176,41 @@ calc_latency(uint16_t pid __rte_unused,
 
 		latency = now - *timestamp_dynfield(pkts[i]);
 
-		/*
-		 * The jitter is calculated as statistical mean of interpacket
-		 * delay variation. The "jitter estimate" is computed by taking
-		 * the absolute values of the ipdv sequence and applying an
-		 * exponential filter with parameter 1/16 to generate the
-		 * estimate. i.e J=J+(|D(i-1,i)|-J)/16. Where J is jitter,
-		 * D(i-1,i) is difference in latency of two consecutive packets
-		 * i-1 and i.
-		 * Reference: Calculated as per RFC 5481, sec 4.1,
-		 * RFC 3393 sec 4.5, RFC 1889 sec.
-		 */
-		glob_stats->jitter += ((prev_latency - latency) - glob_stats->jitter) / 16;
-		if (glob_stats->min_latency == 0)
-			glob_stats->min_latency = latency;
-		else if (latency < glob_stats->min_latency)
+		if (first_sample) {
+			first_sample = false;
+
 			glob_stats->min_latency = latency;
-		else if (latency > glob_stats->max_latency)
 			glob_stats->max_latency = latency;
-		/*
-		 * The average latency is measured using exponential moving
-		 * average, i.e. using EWMA
-		 * https://en.wikipedia.org/wiki/Moving_average
-		 *
-		 * Alpha is .25
-		 */
-		glob_stats->avg_latency += (latency - glob_stats->avg_latency) / 4;
+			glob_stats->avg_latency = latency;
+			glob_stats->jitter = 0;
+		} else {
+			/*
+			 * The jitter is calculated as statistical mean of interpacket
+			 * delay variation. The "jitter estimate" is computed by taking
+			 * the absolute values of the ipdv sequence and applying an
+			 * exponential filter with parameter 1/16 to generate the
+			 * estimate. i.e J=J+(|D(i-1,i)|-J)/16. Where J is jitter,
+			 * D(i-1,i) is difference in latency of two consecutive packets
+			 * i-1 and i.
+			 * Reference: Calculated as per RFC 5481, sec 4.1,
+			 * RFC 3393 sec 4.5, RFC 1889 sec.
+			 */
+			glob_stats->jitter += ((prev_latency - latency)
+					       - glob_stats->jitter) / 16;
+			if (latency < glob_stats->min_latency)
+				glob_stats->min_latency = latency;
+			if (latency > glob_stats->max_latency)
+				glob_stats->max_latency = latency;
+			/*
+			 * The average latency is measured using exponential moving
+			 * average, i.e. using EWMA
+			 * https://en.wikipedia.org/wiki/Moving_average
+			 *
+			 * Alpha is .25
+			 */
+			glob_stats->avg_latency += (latency - glob_stats->avg_latency) / 4;
+		}
+
 		prev_latency = latency;
 	}
 	rte_spinlock_unlock(&glob_stats->lock);
-- 
2.43.0


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v3 5/5] latencystats: include file cleanup
  2024-04-17 17:07   ` [PATCH v3 5/5] latencystats: include file cleanup Stephen Hemminger
@ 2024-04-17 17:30     ` Bruce Richardson
  2024-04-17 18:13       ` Stephen Hemminger
  0 siblings, 1 reply; 14+ messages in thread
From: Bruce Richardson @ 2024-04-17 17:30 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: dev, Reshma Pattan

On Wed, Apr 17, 2024 at 10:07:27AM -0700, Stephen Hemminger wrote:
> Include what is used here.
> 
There are more changes in this patch than just includes cleanup.

> Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
> ---
>  lib/latencystats/rte_latencystats.c | 85 ++++++++++++++++++-----------
>  1 file changed, 52 insertions(+), 33 deletions(-)
> 
> diff --git a/lib/latencystats/rte_latencystats.c b/lib/latencystats/rte_latencystats.c
> index 62038a9f5d..31e7a6eb88 100644
> --- a/lib/latencystats/rte_latencystats.c
> +++ b/lib/latencystats/rte_latencystats.c
> @@ -2,16 +2,25 @@
>   * Copyright(c) 2018 Intel Corporation
>   */
>  
> +#include <errno.h>
>  #include <math.h>
> +#include <stdbool.h>
> +#include <stddef.h>
> +#include <string.h>
>  
> -#include <rte_string_fns.h>
> -#include <rte_mbuf_dyn.h>
> -#include <rte_log.h>
> +#include <rte_common.h>
>  #include <rte_cycles.h>
> +#include <rte_eal.h>
> +#include <rte_errno.h>
>  #include <rte_ethdev.h>
> -#include <rte_metrics.h>
> -#include <rte_memzone.h>
>  #include <rte_lcore.h>
> +#include <rte_log.h>
> +#include <rte_mbuf.h>
> +#include <rte_mbuf_dyn.h>
> +#include <rte_memzone.h>
> +#include <rte_metrics.h>
> +#include <rte_spinlock.h>
> +#include <rte_string_fns.h>
>  
>  #include "rte_latencystats.h"
>  
> @@ -148,14 +157,15 @@ add_time_stamps(uint16_t pid __rte_unused,
>  
>  static uint16_t
>  calc_latency(uint16_t pid __rte_unused,
> -		uint16_t qid __rte_unused,
> -		struct rte_mbuf **pkts,
> -		uint16_t nb_pkts,
> -		void *_ __rte_unused)
> +	     uint16_t qid __rte_unused,
> +	     struct rte_mbuf **pkts,
> +	     uint16_t nb_pkts,
> +	     void *_ __rte_unused)
>  {
>  	unsigned int i;
>  	uint64_t now, latency;
>  	static uint64_t prev_latency;
> +	static bool first_sample = true;
>  
>  	now = rte_rdtsc();
>  
> @@ -166,32 +176,41 @@ calc_latency(uint16_t pid __rte_unused,
>  
>  		latency = now - *timestamp_dynfield(pkts[i]);
>  
> -		/*
> -		 * The jitter is calculated as statistical mean of interpacket
> -		 * delay variation. The "jitter estimate" is computed by taking
> -		 * the absolute values of the ipdv sequence and applying an
> -		 * exponential filter with parameter 1/16 to generate the
> -		 * estimate. i.e J=J+(|D(i-1,i)|-J)/16. Where J is jitter,
> -		 * D(i-1,i) is difference in latency of two consecutive packets
> -		 * i-1 and i.
> -		 * Reference: Calculated as per RFC 5481, sec 4.1,
> -		 * RFC 3393 sec 4.5, RFC 1889 sec.
> -		 */
> -		glob_stats->jitter += ((prev_latency - latency) - glob_stats->jitter) / 16;
> -		if (glob_stats->min_latency == 0)
> -			glob_stats->min_latency = latency;
> -		else if (latency < glob_stats->min_latency)
> +		if (first_sample) {
> +			first_sample = false;
> +
>  			glob_stats->min_latency = latency;
> -		else if (latency > glob_stats->max_latency)
>  			glob_stats->max_latency = latency;
> -		/*
> -		 * The average latency is measured using exponential moving
> -		 * average, i.e. using EWMA
> -		 * https://en.wikipedia.org/wiki/Moving_average
> -		 *
> -		 * Alpha is .25
> -		 */
> -		glob_stats->avg_latency += (latency - glob_stats->avg_latency) / 4;
> +			glob_stats->avg_latency = latency;
> +			glob_stats->jitter = 0;
> +		} else {
> +			/*
> +			 * The jitter is calculated as statistical mean of interpacket
> +			 * delay variation. The "jitter estimate" is computed by taking
> +			 * the absolute values of the ipdv sequence and applying an
> +			 * exponential filter with parameter 1/16 to generate the
> +			 * estimate. i.e J=J+(|D(i-1,i)|-J)/16. Where J is jitter,
> +			 * D(i-1,i) is difference in latency of two consecutive packets
> +			 * i-1 and i.
> +			 * Reference: Calculated as per RFC 5481, sec 4.1,
> +			 * RFC 3393 sec 4.5, RFC 1889 sec.
> +			 */
> +			glob_stats->jitter += ((prev_latency - latency)
> +					       - glob_stats->jitter) / 16;
> +			if (latency < glob_stats->min_latency)
> +				glob_stats->min_latency = latency;
> +			if (latency > glob_stats->max_latency)
> +				glob_stats->max_latency = latency;
> +			/*
> +			 * The average latency is measured using exponential moving
> +			 * average, i.e. using EWMA
> +			 * https://en.wikipedia.org/wiki/Moving_average
> +			 *
> +			 * Alpha is .25
> +			 */
> +			glob_stats->avg_latency += (latency - glob_stats->avg_latency) / 4;
> +		}
> +
>  		prev_latency = latency;
>  	}
>  	rte_spinlock_unlock(&glob_stats->lock);
> -- 
> 2.43.0
> 

^ permalink raw reply	[flat|nested] 14+ messages in thread

* RE: [PATCH v3 1/5] latencystats: replace use of VLA
  2024-04-17 17:07   ` [PATCH v3 1/5] latencystats: replace use of VLA Stephen Hemminger
@ 2024-04-17 18:03     ` Morten Brørup
  2024-04-17 18:13       ` Stephen Hemminger
  2024-04-18  0:00     ` Tyler Retzlaff
  1 sibling, 1 reply; 14+ messages in thread
From: Morten Brørup @ 2024-04-17 18:03 UTC (permalink / raw)
  To: Stephen Hemminger, dev; +Cc: Reshma Pattan

> From: Stephen Hemminger [mailto:stephen@networkplumber.org]
> Sent: Wednesday, 17 April 2024 19.07
> 
> The temporary array latencystats is not needed if the algorithm
> is converted into one pass.
> 
> Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
> ---
>  lib/latencystats/rte_latencystats.c | 31 +++++++++++++++--------------
>  1 file changed, 16 insertions(+), 15 deletions(-)
> 
> diff --git a/lib/latencystats/rte_latencystats.c
> b/lib/latencystats/rte_latencystats.c
> index 4ea9b0d75b..9b345bfb33 100644
> --- a/lib/latencystats/rte_latencystats.c
> +++ b/lib/latencystats/rte_latencystats.c
> @@ -157,9 +157,9 @@ calc_latency(uint16_t pid __rte_unused,
>  		uint16_t nb_pkts,
>  		void *_ __rte_unused)
>  {
> -	unsigned int i, cnt = 0;
> +	unsigned int i;
>  	uint64_t now;
> -	float latency[nb_pkts];
> +	float latency;
>  	static float prev_latency;
>  	/*
>  	 * Alpha represents degree of weighting decrease in EWMA,
> @@ -169,13 +169,14 @@ calc_latency(uint16_t pid __rte_unused,
>  	const float alpha = 0.2;
> 
>  	now = rte_rdtsc();
> -	for (i = 0; i < nb_pkts; i++) {
> -		if (pkts[i]->ol_flags & timestamp_dynflag)
> -			latency[cnt++] = now - *timestamp_dynfield(pkts[i]);
> -	}
> 
>  	rte_spinlock_lock(&glob_stats->lock);
> -	for (i = 0; i < cnt; i++) {
> +	for (i = 0; i < nb_pkts; i++) {
> +		if (!(pkts[i]->ol_flags & timestamp_dynflag))
> +			continue;
> +
> +		latency = now - *timestamp_dynfield(pkts[i]);
> +
>  		/*
>  		 * The jitter is calculated as statistical mean of
> interpacket
>  		 * delay variation. The "jitter estimate" is computed by
> taking
> @@ -187,22 +188,22 @@ calc_latency(uint16_t pid __rte_unused,
>  		 * Reference: Calculated as per RFC 5481, sec 4.1,
>  		 * RFC 3393 sec 4.5, RFC 1889 sec.
>  		 */
> -		glob_stats->jitter +=  (fabsf(prev_latency - latency[i])
> +		glob_stats->jitter +=  (fabsf(prev_latency - latency)
>  					- glob_stats->jitter)/16;
>  		if (glob_stats->min_latency == 0)

You could add unlikely() to this comparison. It should only happen once in a lifetime.

> -			glob_stats->min_latency = latency[i];
> -		else if (latency[i] < glob_stats->min_latency)
> -			glob_stats->min_latency = latency[i];
> -		else if (latency[i] > glob_stats->max_latency)
> -			glob_stats->max_latency = latency[i];
> +			glob_stats->min_latency = latency;

In theory, glob_stats->max_latency should also be initialized with the first sample value here.

> +		else if (latency < glob_stats->min_latency)
> +			glob_stats->min_latency = latency;
> +		else if (latency > glob_stats->max_latency)
> +			glob_stats->max_latency = latency;

The min/max comparisons are also unlikely.

>  		/*
>  		 * The average latency is measured using exponential moving
>  		 * average, i.e. using EWMA
>  		 * https://en.wikipedia.org/wiki/Moving_average
>  		 */
>  		glob_stats->avg_latency +=
> -			alpha * (latency[i] - glob_stats->avg_latency);
> -		prev_latency = latency[i];
> +			alpha * (latency - glob_stats->avg_latency);
> +		prev_latency = latency;
>  	}
>  	rte_spinlock_unlock(&glob_stats->lock);
> 
> --
> 2.43.0

With or without suggested changes,
Acked-by: Morten Brørup <mb@smartsharesystems.com>


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v3 1/5] latencystats: replace use of VLA
  2024-04-17 18:03     ` Morten Brørup
@ 2024-04-17 18:13       ` Stephen Hemminger
  0 siblings, 0 replies; 14+ messages in thread
From: Stephen Hemminger @ 2024-04-17 18:13 UTC (permalink / raw)
  To: Morten Brørup; +Cc: dev, Reshma Pattan

On Wed, 17 Apr 2024 20:03:55 +0200
Morten Brørup <mb@smartsharesystems.com> wrote:

> In theory, glob_stats->max_latency should also be initialized with the first sample value here.

The last patch does that. 
It was merge of two patches, will split up in next version.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v3 5/5] latencystats: include file cleanup
  2024-04-17 17:30     ` Bruce Richardson
@ 2024-04-17 18:13       ` Stephen Hemminger
  0 siblings, 0 replies; 14+ messages in thread
From: Stephen Hemminger @ 2024-04-17 18:13 UTC (permalink / raw)
  To: Bruce Richardson; +Cc: dev, Reshma Pattan

On Wed, 17 Apr 2024 18:30:38 +0100
Bruce Richardson <bruce.richardson@intel.com> wrote:

> On Wed, Apr 17, 2024 at 10:07:27AM -0700, Stephen Hemminger wrote:
> > Include what is used here.
> >   
> There are more changes in this patch than just includes cleanup.


Sorry got two squashed on a rebase

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v3 1/5] latencystats: replace use of VLA
  2024-04-17 17:07   ` [PATCH v3 1/5] latencystats: replace use of VLA Stephen Hemminger
  2024-04-17 18:03     ` Morten Brørup
@ 2024-04-18  0:00     ` Tyler Retzlaff
  1 sibling, 0 replies; 14+ messages in thread
From: Tyler Retzlaff @ 2024-04-18  0:00 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: dev, Reshma Pattan

On Wed, Apr 17, 2024 at 10:07:23AM -0700, Stephen Hemminger wrote:
> The temporary array latencystats is not needed if the algorithm
> is converted into one pass.
> 
> Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
> ---

if this series is merged first, my series here
https://patchwork.dpdk.org/project/dpdk/patch/1713397319-26135-6-git-send-email-roretzla@linux.microsoft.com/
can just have the latencystats patch dropped, since this series carries
the preferred change.

thanks Stephen!

Acked-by: Tyler Retzlaff <roretzla@linux.microsoft.com>


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v3 2/5] latencystats: handle fractional cycles per ns
  2024-04-17 17:07   ` [PATCH v3 2/5] latencystats: handle fractional cycles per ns Stephen Hemminger
@ 2024-04-18  0:03     ` Tyler Retzlaff
  0 siblings, 0 replies; 14+ messages in thread
From: Tyler Retzlaff @ 2024-04-18  0:03 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: dev, Reshma Pattan

On Wed, Apr 17, 2024 at 10:07:24AM -0700, Stephen Hemminger wrote:
> The timer_hz is not always an integral number of nanoseconds.
> For examples, cycles per nanoseconds on my test system is 2.8.
> Fix by using floating point where needed.
> 
> Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
> ---
>  lib/latencystats/rte_latencystats.c | 12 +++++-------
>  1 file changed, 5 insertions(+), 7 deletions(-)
> 
> diff --git a/lib/latencystats/rte_latencystats.c b/lib/latencystats/rte_latencystats.c
> index 9b345bfb33..fe8c3c563a 100644
> --- a/lib/latencystats/rte_latencystats.c
> +++ b/lib/latencystats/rte_latencystats.c
> @@ -19,10 +19,10 @@
>  #define NS_PER_SEC 1E9
>  
>  /** Clock cycles per nano second */
> -static uint64_t
> +static float
>  latencystat_cycles_per_ns(void)
>  {
> -	return rte_get_timer_hz() / NS_PER_SEC;
> +	return (double)rte_get_timer_hz() / NS_PER_SEC;
>  }

my feeling is this will generate a warning on msvc later double ->
float.


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v3 3/5] latencystats: do not use floating point
  2024-04-17 17:07   ` [PATCH v3 3/5] latencystats: do not use floating point Stephen Hemminger
@ 2024-04-18  0:10     ` Tyler Retzlaff
  0 siblings, 0 replies; 14+ messages in thread
From: Tyler Retzlaff @ 2024-04-18  0:10 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: dev, Reshma Pattan

On Wed, Apr 17, 2024 at 10:07:25AM -0700, Stephen Hemminger wrote:
> The cycle counts do not need to be stored as floating point.
> Instead keep track of latency in cycles, and convert to
> nanoseconds when read.
> 
> Change Exponential Weighted Moving Average weight from .2 to .25
> to avoid use of floating point for that.
> 
> Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
> ---
>  lib/latencystats/rte_latencystats.c | 37 +++++++++++------------------
>  1 file changed, 14 insertions(+), 23 deletions(-)
> 
> diff --git a/lib/latencystats/rte_latencystats.c b/lib/latencystats/rte_latencystats.c
> index fe8c3c563a..11bd0ea4ae 100644
> --- a/lib/latencystats/rte_latencystats.c
> +++ b/lib/latencystats/rte_latencystats.c
> @@ -47,10 +47,10 @@ static uint64_t timer_tsc;
>  static uint64_t prev_tsc;
>  
>  struct rte_latency_stats {
> -	float min_latency; /**< Minimum latency in nano seconds */
> -	float avg_latency; /**< Average latency in nano seconds */
> -	float max_latency; /**< Maximum latency in nano seconds */
> -	float jitter; /** Latency variation */
> +	uint64_t min_latency; /**< Minimum latency */
> +	uint64_t avg_latency; /**< Average latency */
> +	uint64_t max_latency; /**< Maximum latency */
> +	uint64_t jitter; /** Latency variation */
>  	rte_spinlock_t lock; /** Latency calculation lock */
>  };
>  
> @@ -82,13 +82,12 @@ int32_t
>  rte_latencystats_update(void)
>  {
>  	unsigned int i;
> -	float *stats_ptr = NULL;
>  	uint64_t values[NUM_LATENCY_STATS] = {0};
>  	int ret;
>  
>  	for (i = 0; i < NUM_LATENCY_STATS; i++) {
> -		stats_ptr = RTE_PTR_ADD(glob_stats,
> -				lat_stats_strings[i].offset);
> +		const uint64_t *stats_ptr = RTE_PTR_ADD(glob_stats,
> +							lat_stats_strings[i].offset);
>  		values[i] = floor(*stats_ptr / latencystat_cycles_per_ns());

will this need a cast to uint64_t?

>  	}
>  
> @@ -105,11 +104,10 @@ static void
>  rte_latencystats_fill_values(struct rte_metric_value *values)
>  {
>  	unsigned int i;
> -	float *stats_ptr = NULL;
>  
>  	for (i = 0; i < NUM_LATENCY_STATS; i++) {
> -		stats_ptr = RTE_PTR_ADD(glob_stats,
> -				lat_stats_strings[i].offset);
> +		const uint64_t *stats_ptr = RTE_PTR_ADD(glob_stats,
> +							lat_stats_strings[i].offset);
>  		values[i].key = i;
>  		values[i].value = floor(*stats_ptr / latencystat_cycles_per_ns());
>  	}
> @@ -156,15 +154,8 @@ calc_latency(uint16_t pid __rte_unused,
>  		void *_ __rte_unused)
>  {
>  	unsigned int i;
> -	uint64_t now;
> -	float latency;
> -	static float prev_latency;
> -	/*
> -	 * Alpha represents degree of weighting decrease in EWMA,
> -	 * a constant smoothing factor between 0 and 1. The value
> -	 * is used below for measuring average latency.
> -	 */
> -	const float alpha = 0.2;
> +	uint64_t now, latency;
> +	static uint64_t prev_latency;
>  

if this is merged i can abandon this series
https://patchwork.dpdk.org/project/dpdk/list/?series=31747

Acked-by: Tyler Retzlaff <roretzla@linux.microsoft.com>


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v3 4/5] latencystats: fix log messages
  2024-04-17 17:07   ` [PATCH v3 4/5] latencystats: fix log messages Stephen Hemminger
@ 2024-04-18  0:13     ` Tyler Retzlaff
  0 siblings, 0 replies; 14+ messages in thread
From: Tyler Retzlaff @ 2024-04-18  0:13 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: dev, Reshma Pattan

On Wed, Apr 17, 2024 at 10:07:26AM -0700, Stephen Hemminger wrote:
> All messages that because of an error should be at log level
> NOTICE or above. Do not break log messages across lines.
> 
> Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
> ---
>  lib/latencystats/rte_latencystats.c | 30 ++++++++++++++---------------
>  1 file changed, 15 insertions(+), 15 deletions(-)
> 
> diff --git a/lib/latencystats/rte_latencystats.c b/lib/latencystats/rte_latencystats.c
> index 11bd0ea4ae..62038a9f5d 100644
> --- a/lib/latencystats/rte_latencystats.c
> +++ b/lib/latencystats/rte_latencystats.c
> @@ -235,7 +235,7 @@ rte_latencystats_init(uint64_t app_samp_intvl,
>  	latency_stats_index = rte_metrics_reg_names(ptr_strings,
>  							NUM_LATENCY_STATS);
>  	if (latency_stats_index < 0) {
> -		LATENCY_STATS_LOG(DEBUG,
> +		LATENCY_STATS_LOG(ERR,
>  			"Failed to register latency stats names");
>  		return -1;
>  	}
> @@ -255,7 +255,7 @@ rte_latencystats_init(uint64_t app_samp_intvl,
>  
>  		ret = rte_eth_dev_info_get(pid, &dev_info);
>  		if (ret != 0) {
> -			LATENCY_STATS_LOG(INFO,
> +			LATENCY_STATS_LOG(NOTICE,
>  				"Error during getting device (port %u) info: %s",

nit: the level is notice, but the message says 'Error' same in a couple
of other instances below. arguably fine so you can ignore me.

>  				pid, strerror(-ret));
>  
> @@ -267,18 +267,18 @@ rte_latencystats_init(uint64_t app_samp_intvl,
>  			cbs->cb = rte_eth_add_first_rx_callback(pid, qid,
>  					add_time_stamps, user_cb);
>  			if (!cbs->cb)
> -				LATENCY_STATS_LOG(INFO, "Failed to "
> -					"register Rx callback for pid=%d, "
> -					"qid=%d", pid, qid);
> +				LATENCY_STATS_LOG(NOTICE,
> +					"Failed to register Rx callback for pid=%u, qid=%u",
> +					pid, qid);
>  		}
>  		for (qid = 0; qid < dev_info.nb_tx_queues; qid++) {
>  			cbs = &tx_cbs[pid][qid];
>  			cbs->cb =  rte_eth_add_tx_callback(pid, qid,
>  					calc_latency, user_cb);
>  			if (!cbs->cb)
> -				LATENCY_STATS_LOG(INFO, "Failed to "
> -					"register Tx callback for pid=%d, "
> -					"qid=%d", pid, qid);
> +				LATENCY_STATS_LOG(NOTICE,
> +					"Failed to register Tx callback for pid=%u, qid=%u",
> +					pid, qid);
>  		}
>  	}
>  	return 0;
> @@ -299,7 +299,7 @@ rte_latencystats_uninit(void)
>  
>  		ret = rte_eth_dev_info_get(pid, &dev_info);
>  		if (ret != 0) {
> -			LATENCY_STATS_LOG(INFO,
> +			LATENCY_STATS_LOG(NOTICE,
>  				"Error during getting device (port %u) info: %s",
>  				pid, strerror(-ret));
>  
> @@ -310,17 +310,17 @@ rte_latencystats_uninit(void)
>  			cbs = &rx_cbs[pid][qid];
>  			ret = rte_eth_remove_rx_callback(pid, qid, cbs->cb);
>  			if (ret)
> -				LATENCY_STATS_LOG(INFO, "failed to "
> -					"remove Rx callback for pid=%d, "
> -					"qid=%d", pid, qid);
> +				LATENCY_STATS_LOG(NOTICE,
> +					"Failed to remove Rx callback for pid=%u, qid=%u",
> +					pid, qid);
>  		}
>  		for (qid = 0; qid < dev_info.nb_tx_queues; qid++) {
>  			cbs = &tx_cbs[pid][qid];
>  			ret = rte_eth_remove_tx_callback(pid, qid, cbs->cb);
>  			if (ret)
> -				LATENCY_STATS_LOG(INFO, "failed to "
> -					"remove Tx callback for pid=%d, "
> -					"qid=%d", pid, qid);
> +				LATENCY_STATS_LOG(NOTICE,
> +					"Failed to remove Tx callback for pid=%u, qid=%u",
> +					pid, qid);
>  		}
>  	}
>  
> -- 

Acked-by: Tyler Retzlaff <roretzla@linux.microsoft.com>


^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2024-04-18  0:13 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <0240408195036.182545-1-stephen@networkplumber.org>
2024-04-17 17:07 ` [PATCH v3 0/5] latencystats: cleanups Stephen Hemminger
2024-04-17 17:07   ` [PATCH v3 1/5] latencystats: replace use of VLA Stephen Hemminger
2024-04-17 18:03     ` Morten Brørup
2024-04-17 18:13       ` Stephen Hemminger
2024-04-18  0:00     ` Tyler Retzlaff
2024-04-17 17:07   ` [PATCH v3 2/5] latencystats: handle fractional cycles per ns Stephen Hemminger
2024-04-18  0:03     ` Tyler Retzlaff
2024-04-17 17:07   ` [PATCH v3 3/5] latencystats: do not use floating point Stephen Hemminger
2024-04-18  0:10     ` Tyler Retzlaff
2024-04-17 17:07   ` [PATCH v3 4/5] latencystats: fix log messages Stephen Hemminger
2024-04-18  0:13     ` Tyler Retzlaff
2024-04-17 17:07   ` [PATCH v3 5/5] latencystats: include file cleanup Stephen Hemminger
2024-04-17 17:30     ` Bruce Richardson
2024-04-17 18:13       ` Stephen Hemminger

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).