T: add tutorial for new trace
This commit is contained in:
@@ -17,3 +17,4 @@ It is made of two main parts:
|
||||
* [MAC PDUs and wireshark](./T/wireshark.md)
|
||||
* [The *enb* tracer](./T/enb.md)
|
||||
* [The *to_vcd* tracer](./T/to_vcd.md)
|
||||
* [Tutorial: how to create a new trace](./T/howto_new_trace.md)
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
# T tracer - a simple tutorial
|
||||
|
||||
There is a diff file with all modifications:
|
||||
[howto_new_trace.patch](./howto_new_trace.patch).
|
||||
We use tag 2023.w28
|
||||
To use the patch, clone the repository,
|
||||
then in the top directory of openairinterface:
|
||||
```
|
||||
git checkout 2023.w28
|
||||
patch -p1 < common/utils/T/DOC/T/howto_new_trace.patch
|
||||
```
|
||||
|
||||
Then compile nr-softmodem as usual.
|
||||
|
||||
## 1 - create a new trace
|
||||
|
||||
As an example, let's add a new trace to dump LDPC decoding success.
|
||||
|
||||
In the file `common/utils/T/T_messages.txt`
|
||||
we add those two lines:
|
||||
|
||||
```
|
||||
ID = LDPC_OK
|
||||
FORMAT = int,segment : int,nb_segments : int,offset : buffer,data
|
||||
```
|
||||
|
||||
- You create an ID for the new trace.
|
||||
- You give the format as a list of variables with there types.
|
||||
|
||||
Then, in the file `openair1/SCHED_NR/phy_procedures_nr_gNB.c`,
|
||||
in function `nr_postDecode()`, we add, at the place where we want to trace:
|
||||
|
||||
```
|
||||
T(T_LDPC_OK,
|
||||
T_INT(rdata->segment_r),
|
||||
T_INT(rdata->nbSegments),
|
||||
T_INT(rdata->offset),
|
||||
T_BUFFER(ulsch_harq->c[r], rdata->Kr_bytes - (ulsch_harq->F>>3) -((ulsch_harq->C>1)?3:0)));
|
||||
```
|
||||
|
||||
And that's all, the code is instrumented, a trace is created,
|
||||
we now need a tracer to process the trace.
|
||||
|
||||
## 2. create a tracer
|
||||
|
||||
See `trace_ldpc.c` in the attached diff. Read it, there is documentation.
|
||||
To compile, just do `make trace_ldpc` in `common/utils/T/tracer`
|
||||
To use: `cd common/utils/T/tracer; ./trace_ldpc -d ../T_messages.txt`
|
||||
|
||||
Your tracer can do whatever it wants with the data.
|
||||
|
||||
The Makefile has been modified to compile it. See the diff.
|
||||
|
||||
Use it as a basis for your own tracer.
|
||||
You can also look at the other tracers, especially `textlog.c`
|
||||
and `macpdu2wireshark.c` which are the most useful for me to
|
||||
trace/debug the nr-softmodem.
|
||||
|
||||
## 3. available types in a trace
|
||||
|
||||
You trace the code with:
|
||||
|
||||
```
|
||||
T(T_trace_name, T_xxx(variable1), T_xxx(variables2), ...);
|
||||
```
|
||||
|
||||
`T_xxx` can be:
|
||||
|
||||
- `T_INT(variable)`
|
||||
- `T_FLOAT(variable)` (not tested much, may fail)
|
||||
- `T_BUFFER(variable, length)`
|
||||
- `T_STRING(variable)`
|
||||
- `T_PRINTF(format, arg1, ... argn)`
|
||||
|
||||
What is traced is obvious from the name. `T_INT` traces an int for example.
|
||||
|
||||
corresponding type to put in `T_messages.txt`
|
||||
|
||||
- `T_INT`: int
|
||||
- `T_FLOAT`: float
|
||||
- `T_BUFFER`: buffer
|
||||
- `T_STRING`: string
|
||||
- `T_PRINTF`: string
|
||||
|
||||
And that's all.
|
||||
You can add as many traces as you want, just add them in `T_messages.txt`,
|
||||
put the `T()` macro in the code where you want to trace, and modify your
|
||||
tracer to deal with it.
|
||||
|
||||
An alternative to writing your own tracer could be to use `textlog`
|
||||
with `-full` command line and process the text with some external
|
||||
tools.
|
||||
|
||||
It is also possible to record the events in a file using the tracer
|
||||
`record` and then use `replay` to process the recorded file later.
|
||||
@@ -0,0 +1,210 @@
|
||||
diff --git a/common/utils/T/T_messages.txt b/common/utils/T/T_messages.txt
|
||||
index c535f36f5e..1632131ceb 100644
|
||||
--- a/common/utils/T/T_messages.txt
|
||||
+++ b/common/utils/T/T_messages.txt
|
||||
@@ -4,6 +4,9 @@ ID = ENB_MASTER_TICK
|
||||
GROUP = ALL:GENERAL:ENB
|
||||
FORMAT = int,eNB_ID : int,frame : int,subframe
|
||||
|
||||
+ID = LDPC_OK
|
||||
+ FORMAT = int,segment : int,nb_segments : int,offset : buffer,data
|
||||
+
|
||||
#PHY logs
|
||||
ID = ENB_PHY_UL_TICK
|
||||
DESC = eNodeB uplink tick - one tick per ms at start of uplink processing
|
||||
diff --git a/common/utils/T/tracer/CMakeLists.txt b/common/utils/T/tracer/CMakeLists.txt
|
||||
index 02e0e2dc9b..db438c42d3 100644
|
||||
--- a/common/utils/T/tracer/CMakeLists.txt
|
||||
+++ b/common/utils/T/tracer/CMakeLists.txt
|
||||
@@ -57,6 +57,10 @@ target_link_libraries(gnb PRIVATE tracer_utils tracer_filter tracer_gui
|
||||
tracer_logger tracer_view tracer_events)
|
||||
target_link_libraries(gnb PRIVATE png)
|
||||
|
||||
+add_executable(trace_ldpc trace_ldpc.c)
|
||||
+target_link_libraries(trace_ldpc PRIVATE tracer_utils tracer_filter
|
||||
+ tracer_logger tracer_view)
|
||||
+
|
||||
add_subdirectory(filter)
|
||||
add_subdirectory(gui)
|
||||
add_subdirectory(logger)
|
||||
@@ -66,4 +70,4 @@ add_custom_target(T_tools)
|
||||
add_dependencies(T_tools
|
||||
record replay extract_config textlog enb ue vcd macpdu2wireshark
|
||||
extract_input_subframe extract_output_subframe to_vcd extract multi
|
||||
- gnb)
|
||||
+ gnb trace_ldpc)
|
||||
diff --git a/common/utils/T/tracer/Makefile b/common/utils/T/tracer/Makefile
|
||||
index d3c959a689..d13ff1e996 100644
|
||||
--- a/common/utils/T/tracer/Makefile
|
||||
+++ b/common/utils/T/tracer/Makefile
|
||||
@@ -7,4 +7,4 @@ clean:
|
||||
rm -rf tracer_build
|
||||
rm record replay extract_config textlog enb ue vcd macpdu2wireshark \
|
||||
extract_input_subframe extract_output_subframe to_vcd extract multi \
|
||||
- gnb
|
||||
+ gnb trace_ldpc
|
||||
diff --git a/common/utils/T/tracer/trace_ldpc.c b/common/utils/T/tracer/trace_ldpc.c
|
||||
new file mode 100644
|
||||
index 0000000000..00baf34774
|
||||
--- /dev/null
|
||||
+++ b/common/utils/T/tracer/trace_ldpc.c
|
||||
@@ -0,0 +1,143 @@
|
||||
+#include <stdio.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <string.h>
|
||||
+#include <pthread.h>
|
||||
+#include <signal.h>
|
||||
+#include "database.h"
|
||||
+#include "event.h"
|
||||
+#include "handler.h"
|
||||
+#include "logger/logger.h"
|
||||
+#include "utils.h"
|
||||
+#include "event_selector.h"
|
||||
+#include "config.h"
|
||||
+
|
||||
+/* this function sends the activated traces to the nr-softmodem */
|
||||
+void activate_traces(int socket, int number_of_events, int *is_on)
|
||||
+{
|
||||
+ char t = 1;
|
||||
+ if (socket_send(socket, &t, 1) == -1 ||
|
||||
+ socket_send(socket, &number_of_events, sizeof(int)) == -1 ||
|
||||
+ socket_send(socket, is_on, number_of_events * sizeof(int)) == -1)
|
||||
+ abort();
|
||||
+}
|
||||
+
|
||||
+void usage(void)
|
||||
+{
|
||||
+ printf(
|
||||
+"options:\n"
|
||||
+" -d <database file> this option is mandatory\n"
|
||||
+" -ip <host> connect to given IP address (default %s)\n"
|
||||
+" -p <port> connect to given port (default %d)\n",
|
||||
+ DEFAULT_REMOTE_IP,
|
||||
+ DEFAULT_REMOTE_PORT
|
||||
+ );
|
||||
+ exit(1);
|
||||
+}
|
||||
+
|
||||
+int main(int n, char **v)
|
||||
+{
|
||||
+ char *database_filename = NULL;
|
||||
+ void *database;
|
||||
+ char *ip = DEFAULT_REMOTE_IP;
|
||||
+ int port = DEFAULT_REMOTE_PORT;
|
||||
+ int *is_on;
|
||||
+ int number_of_events;
|
||||
+ int i;
|
||||
+ int socket;
|
||||
+ int ldpc_ok_id;
|
||||
+ database_event_format f;
|
||||
+ int segment;
|
||||
+ int nb_segments;
|
||||
+ int offset;
|
||||
+ int data;
|
||||
+
|
||||
+ /* write on a socket fails if the other end is closed and we get SIGPIPE */
|
||||
+ if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) abort();
|
||||
+
|
||||
+ /* parse command line options */
|
||||
+ for (i = 1; i < n; i++) {
|
||||
+ if (!strcmp(v[i], "-h") || !strcmp(v[i], "--help")) usage();
|
||||
+ if (!strcmp(v[i], "-d"))
|
||||
+ { if (i > n-2) usage(); database_filename = v[++i]; continue; }
|
||||
+ if (!strcmp(v[i], "-ip")) { if (i > n-2) usage(); ip = v[++i]; continue; }
|
||||
+ if (!strcmp(v[i], "-p"))
|
||||
+ { if (i > n-2) usage(); port = atoi(v[++i]); continue; }
|
||||
+ usage();
|
||||
+ }
|
||||
+
|
||||
+ if (database_filename == NULL) {
|
||||
+ printf("ERROR: provide a database file (-d)\n");
|
||||
+ exit(1);
|
||||
+ }
|
||||
+
|
||||
+ /* load the database T_messages.txt */
|
||||
+ database = parse_database(database_filename);
|
||||
+ load_config_file(database_filename);
|
||||
+
|
||||
+ /* an array of int for all the events defined in the database is needed */
|
||||
+ number_of_events = number_of_ids(database);
|
||||
+ is_on = calloc(number_of_events, sizeof(int));
|
||||
+ if (is_on == NULL) abort();
|
||||
+
|
||||
+ /* activate the LDPC_OK trace in this array */
|
||||
+ on_off(database, "LDPC_OK", is_on, 1);
|
||||
+
|
||||
+ /* connect to the nr-softmodem */
|
||||
+ socket = connect_to(ip, port);
|
||||
+
|
||||
+ /* activate the trace LDPC_OK in the nr-softmodem */
|
||||
+ activate_traces(socket, number_of_events, is_on);
|
||||
+
|
||||
+ free(is_on);
|
||||
+
|
||||
+ /* get the format of the LDPC_OK trace */
|
||||
+ ldpc_ok_id = event_id_from_name(database, "LDPC_OK");
|
||||
+ f = get_format(database, ldpc_ok_id);
|
||||
+
|
||||
+/* this macro looks for a particular element and checks its type */
|
||||
+#define G(var_name, var_type, var) \
|
||||
+ if (!strcmp(f.name[i], var_name)) { \
|
||||
+ if (strcmp(f.type[i], var_type)) { printf("bad type for %s\n", var_name); exit(1); } \
|
||||
+ var = i; \
|
||||
+ continue; \
|
||||
+ }
|
||||
+
|
||||
+ /* get the elements of the LDPC_OK trace
|
||||
+ * the value is an index in the event, see below
|
||||
+ */
|
||||
+ for (i = 0; i < f.count; i++) {
|
||||
+ G("segment", "int", segment);
|
||||
+ G("nb_segments", "int", nb_segments);
|
||||
+ G("offset", "int", offset);
|
||||
+ G("data", "buffer", data);
|
||||
+ }
|
||||
+
|
||||
+ /* a buffer needed to receive events from the nr-softmodem */
|
||||
+ OBUF ebuf = { osize: 0, omaxsize: 0, obuf: NULL };
|
||||
+
|
||||
+ /* read events */
|
||||
+ while (1) {
|
||||
+ event e;
|
||||
+ e = get_event(socket, &ebuf, database);
|
||||
+ if (e.type == -1) break;
|
||||
+ if (e.type == ldpc_ok_id) {
|
||||
+ /* this is how to access the elements of the LDPC_OK trace.
|
||||
+ * we use e.e[<element>] and then the correct suffix, here
|
||||
+ * it's .i for the integer and .b for the buffer and .bsize
|
||||
+ * for the buffer size
|
||||
+ * see in event.h the structure event_arg
|
||||
+ */
|
||||
+ unsigned char *buf = e.e[data].b;
|
||||
+ printf("get LDPC_OK event segment %d nb_segments %d offset %d buffer length %d = [",
|
||||
+ e.e[segment].i,
|
||||
+ e.e[nb_segments].i,
|
||||
+ e.e[offset].i,
|
||||
+ e.e[data].bsize);
|
||||
+ for (i = 0; i < e.e[data].bsize; i++)
|
||||
+ printf(" %2.2x", buf[i]);
|
||||
+ printf("]\n");
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c
|
||||
index f33106ecaa..129b3606b6 100644
|
||||
--- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c
|
||||
+++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c
|
||||
@@ -255,6 +255,11 @@ static void nr_postDecode(PHY_VARS_gNB *gNB, notifiedFIFO_elt_t *req)
|
||||
ulsch_harq->processedSegments,
|
||||
rdata->nbSegments);
|
||||
if (decodeSuccess) {
|
||||
+ T(T_LDPC_OK,
|
||||
+ T_INT(rdata->segment_r),
|
||||
+ T_INT(rdata->nbSegments),
|
||||
+ T_INT(rdata->offset),
|
||||
+ T_BUFFER(ulsch_harq->c[r], rdata->Kr_bytes - (ulsch_harq->F >> 3) - ((ulsch_harq->C > 1) ? 3 : 0)));
|
||||
memcpy(ulsch_harq->b + rdata->offset, ulsch_harq->c[r], rdata->Kr_bytes - (ulsch_harq->F >> 3) - ((ulsch_harq->C > 1) ? 3 : 0));
|
||||
|
||||
} else {
|
||||
Reference in New Issue
Block a user