From 91329928016106bb57999c0c2c4d1c1741f5d07b Mon Sep 17 00:00:00 2001 From: Robert Schmidt <robert.schmidt@openairinterface.org> Date: Mon, 3 Jul 2023 17:34:48 +0200 Subject: [PATCH] T: add tutorial for new trace --- common/utils/T/DOC/T.md | 1 + common/utils/T/DOC/T/howto_new_trace.md | 95 ++++++++++ common/utils/T/DOC/T/howto_new_trace.patch | 210 +++++++++++++++++++++ 3 files changed, 306 insertions(+) create mode 100644 common/utils/T/DOC/T/howto_new_trace.md create mode 100644 common/utils/T/DOC/T/howto_new_trace.patch diff --git a/common/utils/T/DOC/T.md b/common/utils/T/DOC/T.md index acc06a057f..e1ba0bae34 100644 --- a/common/utils/T/DOC/T.md +++ b/common/utils/T/DOC/T.md @@ -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) diff --git a/common/utils/T/DOC/T/howto_new_trace.md b/common/utils/T/DOC/T/howto_new_trace.md new file mode 100644 index 0000000000..b8dafb4c49 --- /dev/null +++ b/common/utils/T/DOC/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. diff --git a/common/utils/T/DOC/T/howto_new_trace.patch b/common/utils/T/DOC/T/howto_new_trace.patch new file mode 100644 index 0000000000..47bbc66138 --- /dev/null +++ b/common/utils/T/DOC/T/howto_new_trace.patch @@ -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 { -- 2.26.2