[v3,3/4] trace: enable trace operations via telemetry

Message ID 20221025090052.429232-4-david.marchand@redhat.com (mailing list archive)
State Deferred
Delegated to: David Marchand
Headers
Series Telemetry support for traces |

Checks

Context Check Description
ci/checkpatch success coding style OK

Commit Message

David Marchand Oct. 25, 2022, 9 a.m. UTC
  Register telemetry commands to list and configure trace points and later
save traces for a running DPDK application.

Example with testpmd running with two net/null ports (startup command
from devtools/test-null.sh):

--> /trace/list,lib.ethdev.*
{"/trace/list": {"lib.ethdev.configure": false,
    "lib.ethdev.rxq.setup": false,
    "lib.ethdev.txq.setup": false,
    "lib.ethdev.start": false,
    "lib.ethdev.stop": false,
    "lib.ethdev.close": false,
    "lib.ethdev.rx.burst": false,
    "lib.ethdev.tx.burst": false}}

--> /trace/enable,lib.ethdev.st*
{"/trace/enable": {"Count": 2}}
--> /trace/enable,lib.ethdev.st*
{"/trace/enable": {"Count": 0}}

--> /trace/list,lib.ethdev.*
{"/trace/list": {"lib.ethdev.configure": false,
    "lib.ethdev.rxq.setup": false,
    "lib.ethdev.txq.setup": false,
    "lib.ethdev.start": true,
    "lib.ethdev.stop": true,
    "lib.ethdev.close": false,
    "lib.ethdev.rx.burst": false,
    "lib.ethdev.tx.burst": false}}

testpmd> stop
...
testpmd> port stop all
...
testpmd> port start all
...
testpmd> start
...

--> /trace/save
{"/trace/save": {"Status": "OK",
    "Path": ".../dpdk-traces/rte-2022-10-12-AM-10-51-48"}}

$ babeltrace .../dpdk-traces/rte-2022-10-12-AM-10-51-48
[10:51:36.229878723] (+?.?????????) lib.ethdev.stop:
    { cpu_id = 0x0, name = "dpdk-testpmd" }, { port_id = 0x0, ret = 0 }
[10:51:36.229880251] (+0.000001528) lib.ethdev.stop:
    { cpu_id = 0x0, name = "dpdk-testpmd" }, { port_id = 0x1, ret = 0 }
[10:51:40.449359774] (+4.219479523) lib.ethdev.start:
    { cpu_id = 0x0, name = "dpdk-testpmd" }, { port_id = 0x0 }
[10:51:40.449377877] (+0.000018103) lib.ethdev.start:
    { cpu_id = 0x0, name = "dpdk-testpmd" }, { port_id = 0x1 }

--> /trace/disable,*
{"/trace/disable": {"Count": 2}}

Signed-off-by: David Marchand <david.marchand@redhat.com>
Acked-by: Jerin Jacob <jerinj@marvell.com>
---
Changes since v2:
- separated telemetry change in a dedicated patch,
- switched to boolean types,

Changes since v1:
- added a note in the documentation,

---
 doc/guides/prog_guide/trace_lib.rst | 39 +++++++++++++++
 lib/eal/common/eal_common_trace.c   | 78 +++++++++++++++++++++++++++++
 2 files changed, 117 insertions(+)
  

Comments

Mattias Rönnblom Oct. 25, 2022, 10:18 a.m. UTC | #1
On 2022-10-25 11:00, David Marchand wrote:
> Register telemetry commands to list and configure trace points and later
> save traces for a running DPDK application.
> 
> Example with testpmd running with two net/null ports (startup command
> from devtools/test-null.sh):
> 
> --> /trace/list,lib.ethdev.*
> {"/trace/list": {"lib.ethdev.configure": false,
>      "lib.ethdev.rxq.setup": false,
>      "lib.ethdev.txq.setup": false,
>      "lib.ethdev.start": false,
>      "lib.ethdev.stop": false,
>      "lib.ethdev.close": false,
>      "lib.ethdev.rx.burst": false,
>      "lib.ethdev.tx.burst": false}}
> 
> --> /trace/enable,lib.ethdev.st*
> {"/trace/enable": {"Count": 2}}
> --> /trace/enable,lib.ethdev.st*
> {"/trace/enable": {"Count": 0}}
> 
> --> /trace/list,lib.ethdev.*
> {"/trace/list": {"lib.ethdev.configure": false,
>      "lib.ethdev.rxq.setup": false,
>      "lib.ethdev.txq.setup": false,
>      "lib.ethdev.start": true,
>      "lib.ethdev.stop": true,
>      "lib.ethdev.close": false,
>      "lib.ethdev.rx.burst": false,
>      "lib.ethdev.tx.burst": false}}
> 
> testpmd> stop
> ...
> testpmd> port stop all
> ...
> testpmd> port start all
> ...
> testpmd> start
> ...
> 
> --> /trace/save
> {"/trace/save": {"Status": "OK",
>      "Path": ".../dpdk-traces/rte-2022-10-12-AM-10-51-48"}}
> 
> $ babeltrace .../dpdk-traces/rte-2022-10-12-AM-10-51-48
> [10:51:36.229878723] (+?.?????????) lib.ethdev.stop:
>      { cpu_id = 0x0, name = "dpdk-testpmd" }, { port_id = 0x0, ret = 0 }
> [10:51:36.229880251] (+0.000001528) lib.ethdev.stop:
>      { cpu_id = 0x0, name = "dpdk-testpmd" }, { port_id = 0x1, ret = 0 }
> [10:51:40.449359774] (+4.219479523) lib.ethdev.start:
>      { cpu_id = 0x0, name = "dpdk-testpmd" }, { port_id = 0x0 }
> [10:51:40.449377877] (+0.000018103) lib.ethdev.start:
>      { cpu_id = 0x0, name = "dpdk-testpmd" }, { port_id = 0x1 }
> 
> --> /trace/disable,*
> {"/trace/disable": {"Count": 2}}
> 
> Signed-off-by: David Marchand <david.marchand@redhat.com>
> Acked-by: Jerin Jacob <jerinj@marvell.com>
> ---
> Changes since v2:
> - separated telemetry change in a dedicated patch,
> - switched to boolean types,
> 
> Changes since v1:
> - added a note in the documentation,
> 
> ---
>   doc/guides/prog_guide/trace_lib.rst | 39 +++++++++++++++
>   lib/eal/common/eal_common_trace.c   | 78 +++++++++++++++++++++++++++++
>   2 files changed, 117 insertions(+)
> 
> diff --git a/doc/guides/prog_guide/trace_lib.rst b/doc/guides/prog_guide/trace_lib.rst
> index 9a8f38073d..d0a6bdae4c 100644
> --- a/doc/guides/prog_guide/trace_lib.rst
> +++ b/doc/guides/prog_guide/trace_lib.rst
> @@ -233,6 +233,45 @@ This section steps you through the details of generating trace and viewing it.
>   
>       babeltrace $HOME/dpdk-traces/rte-yyyy-mm-dd-[AP]M-hh-mm-ss/
>   
> +Configuring traces on a running DPDK application
> +------------------------------------------------
> +
> +The DPDK trace library can be configured using the Telemetry interface.
> +
> +Examples::
> +
> +  --> /trace/list,lib.ethdev.*
> +  {"/trace/list": {"lib.ethdev.configure": false,
> +      "lib.ethdev.rxq.setup": false,
> +      "lib.ethdev.txq.setup": false,
> +      "lib.ethdev.start": false,
> +      "lib.ethdev.stop": false,
> +      "lib.ethdev.close": false,
> +      "lib.ethdev.rx.burst": false,
> +      "lib.ethdev.tx.burst": false}}
> +
> +  --> /trace/enable,lib.ethdev.st*
> +  {"/trace/enable": {"Count": 2}}
> +  --> /trace/enable,lib.ethdev.st*
> +  {"/trace/enable": {"Count": 0}}
> +
> +  --> /trace/list,lib.ethdev.*
> +  {"/trace/list": {"lib.ethdev.configure": false,
> +      "lib.ethdev.rxq.setup": false,
> +      "lib.ethdev.txq.setup": false,
> +      "lib.ethdev.start": true,
> +      "lib.ethdev.stop": true,
> +      "lib.ethdev.close": false,
> +      "lib.ethdev.rx.burst": false,
> +      "lib.ethdev.tx.burst": false}}
> +
> +  --> /trace/save
> +  {"/trace/save": {"Status": "OK",
> +      "Path": ".../dpdk-traces/rte-2022-10-12-AM-10-51-48"}}
> +
> +For more information on how to use the Telemetry interface, see
> +the :doc:`../howto/telemetry`.
> +
>   Implementation details
>   ----------------------
>   
> diff --git a/lib/eal/common/eal_common_trace.c b/lib/eal/common/eal_common_trace.c
> index 5caaac8e59..bb26af618a 100644
> --- a/lib/eal/common/eal_common_trace.c
> +++ b/lib/eal/common/eal_common_trace.c
> @@ -12,6 +12,7 @@
>   #include <rte_lcore.h>
>   #include <rte_per_lcore.h>
>   #include <rte_string_fns.h>
> +#include <rte_telemetry.h>
>   
>   #include "eal_trace.h"
>   
> @@ -521,3 +522,80 @@ __rte_trace_point_register(rte_trace_point_t *handle, const char *name,
>   
>   	return -rte_errno;
>   }
> +
> +static int
> +trace_telemetry_enable(const char *cmd __rte_unused,
> +	const char *params, struct rte_tel_data *d)
> +{
> +	unsigned int count;

status is uint32_t.

> +
> +	if (params == NULL || strlen(params) == 0)
> +		return -1;
> +	rte_tel_data_start_dict(d);
> +	count = __atomic_load_n(&trace.status, __ATOMIC_RELAXED);
> +	rte_trace_pattern(params, true);
> +	rte_tel_data_add_dict_int(d, "Count",
> +		__atomic_load_n(&trace.status, __ATOMIC_RELAXED) - count);

Why "Count"? From what I could tell, trace.status tells if tracing is 
enabled or not.

I also don't understand why &trace.status is loaded twice, especially in 
the light that future compilers, that more heavily optimize atomics, 
might merge those two loads into one, resulting in something equivalent to:

rte_tel_data_add_dict_int(d, "Count", 0);

Is one of the loads supposed to be a store (or, lock add, rather), 
enabling the tracing?

Might be worth to wrap all the atomics in functions, making the code 
more clear.

> +	return 0;
> +
> +}
> +
> +static int
> +trace_telemetry_disable(const char *cmd __rte_unused,
> +	const char *params, struct rte_tel_data *d)
> +{
> +	unsigned int count;
> +
> +	if (params == NULL || strlen(params) == 0)
> +		return -1;
> +	rte_tel_data_start_dict(d);
> +	count = __atomic_load_n(&trace.status, __ATOMIC_RELAXED);
> +	rte_trace_pattern(params, false);
> +	rte_tel_data_add_dict_int(d, "Count",
> +		count - __atomic_load_n(&trace.status, __ATOMIC_RELAXED));
> +	return 0;
> +
> +}
> +
> +static int
> +trace_telemetry_list(const char *cmd __rte_unused,
> +	const char *params, struct rte_tel_data *d)
> +{
> +	struct trace_point *tp;
> +
> +	rte_tel_data_start_dict(d);
> +	STAILQ_FOREACH(tp, &tp_list, next) {
> +		if (params != NULL && fnmatch(params, tp->name, 0) != 0)
> +			continue;
> +
> +		rte_tel_data_add_dict_bool(d, tp->name,
> +			rte_trace_point_is_enabled(tp->handle));
> +	}
> +
> +	return 0;
> +}
> +
> +static int
> +trace_telemetry_save(const char *cmd __rte_unused,
> +	const char *params __rte_unused, struct rte_tel_data *d)
> +{
> +	struct trace *trace = trace_obj_get();
> +
> +	rte_tel_data_start_dict(d);
> +	rte_tel_data_add_dict_string(d, "Status", rte_trace_save() == 0 ? "OK" : "KO");
> +	rte_tel_data_add_dict_string(d, "Path", trace->dir);
> +
> +	return 0;
> +}
> +
> +RTE_INIT(trace_telemetry)
> +{
> +	rte_telemetry_register_cmd("/trace/enable", trace_telemetry_enable,
> +		"Enable trace points matching the provided pattern. Parameters: string pattern.");
> +	rte_telemetry_register_cmd("/trace/disable", trace_telemetry_disable,
> +		"Disable trace points matching the provided pattern. Parameters: string pattern.");
> +	rte_telemetry_register_cmd("/trace/list", trace_telemetry_list,
> +		"List trace points. Parameters: string pattern.");
> +	rte_telemetry_register_cmd("/trace/save", trace_telemetry_save,
> +		"Save current traces. Takes no parameter.");
> +}
  

Patch

diff --git a/doc/guides/prog_guide/trace_lib.rst b/doc/guides/prog_guide/trace_lib.rst
index 9a8f38073d..d0a6bdae4c 100644
--- a/doc/guides/prog_guide/trace_lib.rst
+++ b/doc/guides/prog_guide/trace_lib.rst
@@ -233,6 +233,45 @@  This section steps you through the details of generating trace and viewing it.
 
     babeltrace $HOME/dpdk-traces/rte-yyyy-mm-dd-[AP]M-hh-mm-ss/
 
+Configuring traces on a running DPDK application
+------------------------------------------------
+
+The DPDK trace library can be configured using the Telemetry interface.
+
+Examples::
+
+  --> /trace/list,lib.ethdev.*
+  {"/trace/list": {"lib.ethdev.configure": false,
+      "lib.ethdev.rxq.setup": false,
+      "lib.ethdev.txq.setup": false,
+      "lib.ethdev.start": false,
+      "lib.ethdev.stop": false,
+      "lib.ethdev.close": false,
+      "lib.ethdev.rx.burst": false,
+      "lib.ethdev.tx.burst": false}}
+
+  --> /trace/enable,lib.ethdev.st*
+  {"/trace/enable": {"Count": 2}}
+  --> /trace/enable,lib.ethdev.st*
+  {"/trace/enable": {"Count": 0}}
+
+  --> /trace/list,lib.ethdev.*
+  {"/trace/list": {"lib.ethdev.configure": false,
+      "lib.ethdev.rxq.setup": false,
+      "lib.ethdev.txq.setup": false,
+      "lib.ethdev.start": true,
+      "lib.ethdev.stop": true,
+      "lib.ethdev.close": false,
+      "lib.ethdev.rx.burst": false,
+      "lib.ethdev.tx.burst": false}}
+
+  --> /trace/save
+  {"/trace/save": {"Status": "OK",
+      "Path": ".../dpdk-traces/rte-2022-10-12-AM-10-51-48"}}
+
+For more information on how to use the Telemetry interface, see
+the :doc:`../howto/telemetry`.
+
 Implementation details
 ----------------------
 
diff --git a/lib/eal/common/eal_common_trace.c b/lib/eal/common/eal_common_trace.c
index 5caaac8e59..bb26af618a 100644
--- a/lib/eal/common/eal_common_trace.c
+++ b/lib/eal/common/eal_common_trace.c
@@ -12,6 +12,7 @@ 
 #include <rte_lcore.h>
 #include <rte_per_lcore.h>
 #include <rte_string_fns.h>
+#include <rte_telemetry.h>
 
 #include "eal_trace.h"
 
@@ -521,3 +522,80 @@  __rte_trace_point_register(rte_trace_point_t *handle, const char *name,
 
 	return -rte_errno;
 }
+
+static int
+trace_telemetry_enable(const char *cmd __rte_unused,
+	const char *params, struct rte_tel_data *d)
+{
+	unsigned int count;
+
+	if (params == NULL || strlen(params) == 0)
+		return -1;
+	rte_tel_data_start_dict(d);
+	count = __atomic_load_n(&trace.status, __ATOMIC_RELAXED);
+	rte_trace_pattern(params, true);
+	rte_tel_data_add_dict_int(d, "Count",
+		__atomic_load_n(&trace.status, __ATOMIC_RELAXED) - count);
+	return 0;
+
+}
+
+static int
+trace_telemetry_disable(const char *cmd __rte_unused,
+	const char *params, struct rte_tel_data *d)
+{
+	unsigned int count;
+
+	if (params == NULL || strlen(params) == 0)
+		return -1;
+	rte_tel_data_start_dict(d);
+	count = __atomic_load_n(&trace.status, __ATOMIC_RELAXED);
+	rte_trace_pattern(params, false);
+	rte_tel_data_add_dict_int(d, "Count",
+		count - __atomic_load_n(&trace.status, __ATOMIC_RELAXED));
+	return 0;
+
+}
+
+static int
+trace_telemetry_list(const char *cmd __rte_unused,
+	const char *params, struct rte_tel_data *d)
+{
+	struct trace_point *tp;
+
+	rte_tel_data_start_dict(d);
+	STAILQ_FOREACH(tp, &tp_list, next) {
+		if (params != NULL && fnmatch(params, tp->name, 0) != 0)
+			continue;
+
+		rte_tel_data_add_dict_bool(d, tp->name,
+			rte_trace_point_is_enabled(tp->handle));
+	}
+
+	return 0;
+}
+
+static int
+trace_telemetry_save(const char *cmd __rte_unused,
+	const char *params __rte_unused, struct rte_tel_data *d)
+{
+	struct trace *trace = trace_obj_get();
+
+	rte_tel_data_start_dict(d);
+	rte_tel_data_add_dict_string(d, "Status", rte_trace_save() == 0 ? "OK" : "KO");
+	rte_tel_data_add_dict_string(d, "Path", trace->dir);
+
+	return 0;
+}
+
+RTE_INIT(trace_telemetry)
+{
+	rte_telemetry_register_cmd("/trace/enable", trace_telemetry_enable,
+		"Enable trace points matching the provided pattern. Parameters: string pattern.");
+	rte_telemetry_register_cmd("/trace/disable", trace_telemetry_disable,
+		"Disable trace points matching the provided pattern. Parameters: string pattern.");
+	rte_telemetry_register_cmd("/trace/list", trace_telemetry_list,
+		"List trace points. Parameters: string pattern.");
+	rte_telemetry_register_cmd("/trace/save", trace_telemetry_save,
+		"Save current traces. Takes no parameter.");
+}