Commit 3a49a44c authored by Robert Schmidt's avatar Robert Schmidt

Merge remote-tracking branch 'origin/t-no-execute-process' into integration_2023_w28

parents bf246a65 630ee18b
......@@ -597,6 +597,15 @@ include_directories("${OPENAIR_DIR}")
# Utilities
###############
# include T directory even if the T is off because T macros are in the code
# no matter what. Note: sone files are generated, so we have both source and
# binary directories
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/common/utils/T
${CMAKE_CURRENT_BINARY_DIR}/common/utils/T)
# set the T_LIB name to T if the target exists, otherwise leave empty
set(T_LIB $<TARGET_NAME_IF_EXISTS:T>)
add_library(HASHTABLE
${OPENAIR_DIR}/common/utils/hashtable/hashtable.c
${OPENAIR_DIR}/common/utils/hashtable/obj_hashtable.c
......@@ -614,6 +623,7 @@ add_library(UTIL
${OPENAIR_DIR}/common/utils/time_meas.c
${OPENAIR_DIR}/common/utils/time_stat.c
)
target_link_libraries(UTIL PUBLIC ${T_LIB})
set(SECURITY_SRC
${OPENAIR3_DIR}/SECU/secu_defs.c
......@@ -1146,8 +1156,6 @@ set(PHY_MEX_UE
${OPENAIR1_DIR}/PHY/LTE_UE_TRANSPORT/dlsch_llr_computation_avx2.c
${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/lte_ue_measurements.c
${OPENAIR_DIR}/common/utils/LOG/log.c
${OPENAIR_DIR}/common/utils/T/T.c
${OPENAIR_DIR}/common/utils/T/local_tracer.c
)
add_library(PHY_MEX ${PHY_MEX_UE})
target_link_libraries(PHY_MEX PRIVATE asn1_lte_rrc_hdrs)
......@@ -1901,51 +1909,12 @@ add_library(oai_iqplayer MODULE
)
set(CMAKE_MODULE_PATH "${OPENAIR_DIR}/cmake_targets/tools/MODULES" "${CMAKE_MODULE_PATH}")
#include T directory even if the T is off because T macros are in the code
#no matter what
include_directories("${OPENAIR_DIR}/common/utils/T")
if (${T_TRACER})
set(T_SOURCE
${OPENAIR_DIR}/common/utils/T/T_IDs.h
${OPENAIR_DIR}/common/utils/T/T.c
${OPENAIR_DIR}/common/utils/T/local_tracer.c)
set(T_LIB "rt")
endif (${T_TRACER})
#Some files in the T directory are generated.
#This rule and the following deal with it.
add_custom_command (
OUTPUT ${OPENAIR_DIR}/common/utils/T/T_IDs.h
COMMAND make check_vcd
WORKING_DIRECTORY ${OPENAIR_DIR}/common/utils/T
DEPENDS ${OPENAIR_DIR}/common/utils/T/T_messages.txt
${OPENAIR_DIR}/common/utils/LOG/vcd_signal_dumper.c
${OPENAIR_DIR}/common/utils/LOG/vcd_signal_dumper.h
)
execute_process (
COMMAND make check_vcd
WORKING_DIRECTORY ${OPENAIR_DIR}/common/utils/T
)
#This rule is specifically needed to generate T files
#before anything else in a project that uses the T.
#See below, there are some 'add_dependencies' showing that.
#Basically we create a custom target and we make other
#targets depend on it. That forces cmake to generate
#T files before anything else.
add_custom_target (
generate_T
DEPENDS ${OPENAIR_DIR}/common/utils/T/T_IDs.h
)
#################################
# add executables for operation
#################################
add_library(minimal_lib
${OPENAIR_DIR}/common/utils/LOG/log.c
${OPENAIR_DIR}/common/utils/minimal_stub.c
${T_SOURCE}
)
target_link_libraries(minimal_lib pthread dl ${T_LIB})
......@@ -1984,7 +1953,6 @@ add_executable(lte-softmodem
${OPENAIR_DIR}/common/utils/lte/ue_power.c
${OPENAIR_DIR}/common/utils/lte/prach_utils.c
${OPENAIR1_DIR}/PHY/TOOLS/phy_scope_interface.c
${T_SOURCE}
)
add_dependencies(lte-softmodem oai_iqplayer)
......@@ -2011,7 +1979,6 @@ add_executable(oairu
${OPENAIR_DIR}/executables/softmodem-common.c
${OPENAIR_DIR}/openair1/SCHED/phy_procedures_lte_common.c
${OPENAIR_DIR}/executables/main_ru.c
${T_SOURCE}
${OPENAIR_DIR}/common/utils/lte/prach_utils.c
)
target_link_libraries(oairu PRIVATE
......@@ -2043,7 +2010,6 @@ add_executable(lte-uesoftmodem
${OPENAIR_DIR}/common/utils/lte/ue_power.c
${OPENAIR_DIR}/common/utils/lte/prach_utils.c
${OPENAIR1_DIR}/PHY/TOOLS/phy_scope_interface.c
${T_SOURCE}
)
if (NOT ${NOS1})
......@@ -2086,7 +2052,6 @@ add_executable(nr-softmodem
${OPENAIR_DIR}/common/utils/nr/nr_common.c
${PHY_INTERFACE_DIR}/queue_t.c
${OPENAIR1_DIR}/PHY/TOOLS/phy_scope_interface.c
${T_SOURCE}
)
target_link_libraries(nr-softmodem PRIVATE
......@@ -2123,13 +2088,12 @@ add_executable(nr-cuup
${OPENAIR2_DIR}/E1AP/e1ap_setup.c
${NR_PDCP_SRC}
${NR_SDAP_SRC}
${T_SOURCE}
)
target_link_libraries(nr-cuup PRIVATE
CONFIG_LIB ITTI SCTP_CLIENT
GTPV1U e1ap e1_pdcp_if f1ap SIMU_ETH
z sctp dl pthread shlib_loader)
z sctp dl pthread shlib_loader ${T_LIB})
target_link_libraries(nr-cuup PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs)
# nr-uesoftmodem is UE implementation
......@@ -2150,7 +2114,6 @@ add_executable(nr-uesoftmodem
${OPENAIR3_DIR}/NAS/UE/nas_ue_task.c
${OPENAIR_DIR}/common/utils/nr/nr_common.c
${OPENAIR1_DIR}/PHY/TOOLS/phy_scope_interface.c
${T_SOURCE}
)
target_link_libraries(nr-uesoftmodem PRIVATE
......@@ -2187,7 +2150,6 @@ target_link_libraries(nr-uesoftmodem PRIVATE
add_executable(dlsim_tm4
${OPENAIR1_DIR}/SIMULATION/LTE_PHY/dlsim_tm4.c
${OPENAIR1_DIR}/PHY/TOOLS/lte_phy_scope_tm4.c
${T_SOURCE}
)
target_link_libraries (dlsim_tm4
-Wl,--start-group SIMU UTIL SCHED_LIB SCHED_RU_LIB PHY ITTI -Wl,--end-group
......@@ -2206,29 +2168,26 @@ target_link_libraries(rftest PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs)
add_executable(polartest
${OPENAIR1_DIR}/PHY/CODING/TESTBENCH/polartest.c
${OPENAIR_DIR}/common/utils/nr/nr_common.c
${T_SOURCE}
)
target_link_libraries(polartest PRIVATE
-Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR PHY_NR_COMMON PHY_NR_UE CONFIG_LIB -Wl,--end-group
m pthread dl
m pthread dl ${T_LIB}
)
add_executable(smallblocktest
${OPENAIR1_DIR}/PHY/CODING/TESTBENCH/smallblocktest.c
${OPENAIR_DIR}/common/utils/nr/nr_common.c
${T_SOURCE}
)
target_link_libraries(smallblocktest PRIVATE
-Wl,--start-group UTIL SIMU PHY_NR PHY_COMMON PHY_NR_COMMON -Wl,--end-group
m pthread dl shlib_loader
m pthread dl shlib_loader ${T_LIB}
)
add_executable(ldpctest
${PHY_NR_CODINGIF}
${OPENAIR1_DIR}/PHY/CODING/TESTBENCH/ldpctest.c
${T_SOURCE}
)
add_dependencies( ldpctest ldpc_orig ldpc_optim ldpc_optim8seg ldpc ldpc_parityCheck)
......@@ -2237,14 +2196,13 @@ if (ENABLE_LDPC_CUDA)
endif()
target_link_libraries(ldpctest PRIVATE
-Wl,--start-group UTIL SIMU PHY_NR PHY_COMMON PHY_NR_COMMON -Wl,--end-group
m pthread dl shlib_loader
m pthread dl shlib_loader ${T_LIB}
)
add_executable(nr_dlschsim
${OPENAIR1_DIR}/SIMULATION/NR_PHY/dlschsim.c
${OPENAIR1_DIR}/SIMULATION/NR_PHY/nr_dummy_functions.c
${OPENAIR_DIR}/common/utils/nr/nr_common.c
${T_SOURCE}
)
target_link_libraries(nr_dlschsim PRIVATE
-Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB CONFIG_LIB MAC_NR_COMMON -Wl,--end-group
......@@ -2256,7 +2214,6 @@ add_executable(nr_pbchsim
${OPENAIR1_DIR}/SIMULATION/NR_PHY/pbchsim.c
${OPENAIR1_DIR}/SIMULATION/NR_PHY/nr_dummy_functions.c
${OPENAIR_DIR}/common/utils/nr/nr_common.c
${T_SOURCE}
)
target_link_libraries(nr_pbchsim PRIVATE
-Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB CONFIG_LIB MAC_NR_COMMON -Wl,--end-group
......@@ -2270,7 +2227,6 @@ add_executable(nr_pucchsim
${OPENAIR1_DIR}/SIMULATION/NR_PHY/pucchsim.c
${OPENAIR1_DIR}/SIMULATION/NR_PHY/nr_dummy_functions.c
${OPENAIR_DIR}/common/utils/nr/nr_common.c
${T_SOURCE}
)
target_link_libraries(nr_pucchsim PRIVATE
-Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB CONFIG_LIB MAC_NR_COMMON -Wl,--end-group
......@@ -2288,7 +2244,6 @@ add_executable(nr_dlsim
${NFAPI_USER_DIR}/nfapi.c
${NFAPI_USER_DIR}/gnb_ind_vars.c
${PHY_INTERFACE_DIR}/queue_t.c
${T_SOURCE}
)
target_link_libraries(nr_dlsim PRIVATE
-Wl,--start-group UTIL SIMU SIMU_ETH PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_NR MAC_UE_NR MAC_NR_COMMON nr_rrc CONFIG_LIB L2_NR HASHTABLE x2ap SECURITY ngap -lz -Wl,--end-group
......@@ -2300,7 +2255,6 @@ add_executable(nr_prachsim
${OPENAIR1_DIR}/SIMULATION/NR_PHY/prachsim.c
${OPENAIR1_DIR}/SIMULATION/NR_PHY/nr_dummy_functions.c
${OPENAIR_DIR}/common/utils/nr/nr_common.c
${T_SOURCE}
)
target_link_libraries(nr_prachsim PRIVATE
-Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_RU PHY_NR_UE MAC_NR_COMMON SCHED_NR_LIB CONFIG_LIB -lz -Wl,--end-group
......@@ -2312,7 +2266,6 @@ add_executable(nr_ulschsim
${OPENAIR1_DIR}/SIMULATION/NR_PHY/nr_dummy_functions.c
${OPENAIR_DIR}/common/utils/nr/nr_common.c
${PHY_INTERFACE_DIR}/queue_t.c
${T_SOURCE}
)
target_link_libraries(nr_ulschsim PRIVATE
-Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB CONFIG_LIB MAC_NR_COMMON -Wl,--end-group
......@@ -2330,7 +2283,6 @@ add_executable(nr_ulsim
${NFAPI_USER_DIR}/nfapi.c
${NFAPI_USER_DIR}/gnb_ind_vars.c
${PHY_INTERFACE_DIR}/queue_t.c
${T_SOURCE}
)
if (ENABLE_LDPC_T1)
......@@ -2350,7 +2302,6 @@ foreach(myExe dlsim dlsim_tm7 ulsim pbchsim scansim mbmssim pdcchsim pucchsim pr
${OPENAIR_DIR}/common/utils/lte/ue_power.c
${OPENAIR_DIR}/common/utils/lte/prach_utils.c
${OPENAIR1_DIR}/PHY/INIT/lte_param_init.c
${T_SOURCE}
${NFAPI_USER_DIR}/nfapi.c
)
target_link_libraries (${myExe} PRIVATE
......@@ -2399,6 +2350,7 @@ if (${T_TRACER})
oai_eth_transpro oai_mobipass coding HASHTABLE UTIL OMG_SUMO
SECURITY SCHED_LIB SCHED_NR_LIB SCHED_RU_LIB SCHED_UE_LIB SCHED_NR_UE_LIB default_sched remote_sched RAL
NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB NFAPI_VNF_LIB NFAPI_USER_LIB
MISC_NFAPI_LTE_LIB MISC_NFAPI_NR_LIB
PHY_COMMON PHY PHY_UE PHY_NR PHY_NR_COMMON PHY_NR_UE PHY_RU PHY_MEX
L2 L2_LTE L2_NR L2_LTE_NR L2_UE NR_L2_UE L2_UE_LTE_NR MAC_NR_COMMON MAC_NR MAC_UE_NR ngap
CN_UTILS GTPV1U SCTP_CLIENT MME_APP LIB_NAS_UE NB_IoT SIMU SIMU_ETH OPENAIR0_LIB
......
......@@ -618,6 +618,7 @@ check_install_oai_software() {
libsctp-dev \
libssl-dev \
libtool \
libxft-dev \
patch \
openssl \
zlib1g-dev \
......@@ -647,6 +648,7 @@ check_install_oai_software() {
lksctp-tools \
lksctp-tools-devel \
libtool \
libXft-devel \
ninja-build \
make \
openssl \
......
......@@ -8,3 +8,4 @@ if(ENABLE_WEBSRV)
add_subdirectory(websrv)
endif()
add_subdirectory(T)
......@@ -51,7 +51,6 @@
#define _GNU_SOURCE
#endif
#include <pthread.h>
#include "T.h"
#include <common/utils/utils.h>
/*----------------------------------------------------------------------------*/
#include <assert.h>
......@@ -414,6 +413,7 @@ int32_t write_file_matlab(const char *fname, const char *vname, void *data, int
#define LOG_F LOG_I /* because LOG_F was originaly to dump a message or buffer but is also used as a regular level...., to dump use LOG_DUMPMSG */
# if T_TRACER
#include "T.h"
/* per component, level dependent macros */
# define LOG_E(c, x...) do { T(T_LEGACY_ ## c ## _ERROR, T_PRINTF(x)) ; if (T_stdout) { if( g_log->log_component[c].level >= OAILOG_ERR ) logRecord_mt(__FILE__, __FUNCTION__, __LINE__,c, OAILOG_ERR, x) ;} } while (0)
# define LOG_W(c, x...) do { T(T_LEGACY_ ## c ## _WARNING, T_PRINTF(x)); if (T_stdout) { if( g_log->log_component[c].level >= OAILOG_WARNING ) logRecord_mt(__FILE__, __FUNCTION__, __LINE__,c, OAILOG_WARNING, x) ;} } while (0)
......
add_executable(genids genids.c)
set_target_properties(genids PROPERTIES RUNTIME_OUTPUT_DIRECTORY .)
add_custom_command(OUTPUT T_IDs.h
COMMAND ./genids ${CMAKE_CURRENT_SOURCE_DIR}/T_messages.txt T_IDs.h
DEPENDS genids
COMMENT "Generating T_IDs.h from T_messages.txt"
)
add_custom_command(OUTPUT T_messages.txt.h
COMMAND xxd -i T_messages.txt ${CMAKE_CURRENT_BINARY_DIR}/T_messages.txt.h
COMMENT "Generating T_messages.txt.h from T_messages.txt"
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)
add_executable(_check_vcd check_vcd.c tracer/database.c tracer/utils.c T_IDs.h T_messages.txt.h)
target_include_directories(_check_vcd PRIVATE
.. ../itti ../../../openair2/COMMON tracer
${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
target_compile_options(_check_vcd PRIVATE -Wall)
target_link_libraries(_check_vcd PRIVATE m pthread)
set_target_properties(_check_vcd PROPERTIES RUNTIME_OUTPUT_DIRECTORY .)
add_custom_target(check_vcd
COMMAND _check_vcd ${CMAKE_CURRENT_SOURCE_DIR}/T_messages.txt ${CMAKE_CURRENT_SOURCE_DIR}/../LOG/vcd_signal_dumper.h
DEPENDS _check_vcd
COMMENT "Checking validity of VCD files"
)
# This rule is specifically needed to generate T files before anything else in
# a project that uses the T.
# See root CMakeLists.txt, there are some 'add_dependencies' showing that.
# Basically we create a custom target and we make other targets depend on it.
# That forces cmake to generate T files before anything else.
add_custom_target(generate_T DEPENDS T_IDs.h check_vcd)
# even if T is off, we need the headers as many targets depend on it
# for this, create an INTERFACE (header-only) library T_headers. To ensure the
# headers have really been created, we make this headers library explicitly
# depend on the generated headers.
add_library(T_headers INTERFACE)
add_dependencies(T_headers T_IDs.h T_messages.txt.h)
target_include_directories(T_headers INTERFACE ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
if(T_TRACER)
add_library(T STATIC T.c local_tracer.c T_IDs.h T_messages.txt.h)
target_link_libraries(T PUBLIC rt)
target_link_libraries(T PRIVATE CONFIG_LIB T_headers)
add_subdirectory(tracer)
endif()
# T tracer
The T tracer is sort of a *framework* to debug and monitor the softmodem.
It is made of two main parts:
* an events' collector integrated to the real-time processing,
* a separate set of programs to receive, record, display, replay and
analyse the events sent by the collector.
## Documentation
* [Basic usage](./T/basic.md)
* [Record](./T/record.md)
* [Replay](./T/replay.md)
* [Multiple tracers](./T/multi.md)
* [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)
# Basic usage of the T
## Compilation
### softmodem side
Simply call `build_oai` the usual way, for example `./build_oai --eNB -w USRP`.
The T tracer is compiled in by default.
### tracer side
Go to the directory `common/utils/T/tracer` and do `make`. This will locally
compile all tracer executables, and place them in `common/utils/T/tracer`. If
you wish to keep source and build separate, go to your existing build directory
(typically `cmake_targets/ran_build/build`), and do `make T_tools` (or `ninja
T_tools`). After that, the executables will be in
`<build-dir>/common/utils/T/tracer`.
In case of failure with one of the following errors:
```shell
/usr/bin/ld: cannot find -lXft
```
or
```shell
-- Checking for module 'xft'
-- No package 'xft' found
CMake Error at /usr/share/cmake-3.16/Modules/FindPkgConfig.cmake:463 (message):
A required package was not found
```
Run:
```shell
sudo apt-get install libxft-dev
```
## Run the softmodem
Run the softmodem with the option `--T_stdout 2` and it will wait for a
tracer to connect to it before processing. (This option is confusing
and may change in the future.)
```shell
cd cmake_targets/ran_build/build
sudo ./lte-softmodem -O [configuration file] --T_stdout 2
```
Additional options can be passed to the softmodem.
The option `--T_nowait` lets the processing start immediately without
first waiting for a tracer.
The option `--T_port [port]` changes the default port used by the
softmodem to wait for a tracer. The default port is 2021.
The option `--T_dont_fork` allows one to use gdb to debug problems
with the softmodem. Note that you then may have some "zombie"
processes after crashes, in which case you can run
`sudo killall -9 lte-softmodem` to get rid of them (`lte-softmodem`
to be replaced by the program you trace, like `lte-softmodem-nos1`
or `oaisim`).
The option `--T_stdout` also accepts values 0 (to disable output
on the terminal and only use the T tracer) and 1 (to disable
the T tracer and only output on the terminal). The default is
1.
## Run a tracer
Go into the directory `common/utils/T/tracer` (or
`cmake_targets/ran_build/build/common/utils/T/tracer`) and run for example the
`enb` tracer:
```shell
./enb -d ../T_messages.txt
```
To trace a remote program, use the `-ip` option. For example,
if you want to trace a program running on `192.168.12.148` do:
```shell
./enb -d ../T_messages.txt -ip 192.168.12.148
```
A graphical user interface will appear with which you can interact to
control the monitoring. See [there](./enb.md) for more documentation
about the `enb` tracer.
It is possible to run several tracers at the same time. See
[here](./multi.md).
![enb_trace](./enb_trace.png)
[source file of this image](./enb_trace.odp)
# 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/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 {
# Multiple tracers
To connect several tracers to the same process, first launch the `multi`
tracer.
Run as:
```shell
cd common/utils/T/tracer
./multi -d ../T_messages.txt
```
Then connect other tracers (`enb`, `textlog`, `to_vcd`, etc.) to the
`multi` tracer.
For example (if you debug the `lte-softmodem`) in one terminal, run:
```shell
cd common/utils/T/tracer
./enb -d ../T_messages.txt -p 2022
```
That will launch the GUI tool to analyze the proper running of the
softmodem.
And in another terminal, run:
```shell
cd common/utils/T/tracer
./to_vcd -d ../T_messages.txt -p 2022 -vcd -o /tmp/openair_dump_eNB.vcd
```
That will dump the VCD traces generated by the softmodem to the
file `/tmp/openair_dump_eNB.vcd`.
The `multi` tracer waits for other tracers to connect to the port 2022.
So you pass `-p 2022` to a tracer so that it connects to the `multi`
tracer. This port can be changed with the `-lp` option.
For example to listen to port 4321, run `multi` as:
```shell
./multi -d ../T_messages.txt -lp 4321
```
Then you would pass `-p 4321` to any tracer for it to connect to `multi`.
As a reminder, to trace `lte-softmodem`, you run it as:
```shell
sudo ./lte-softmodem -O config_file.conf --T_stdout 0
```
The important part is `--T_stdout 0`.
The order to launch the various programs (`multi`, the softmodem, other
tracers) is not important.
# Record
First, read the [basic usage](./basic.md) to compile things.
To record, you use the `record` tracer.
To send a trace to Eurecom, you run (unless we specifically ask you
to activate/deactivate specific traces):
```shell
./record -d ../T_messages.txt -o record.raw -ON -off VCD -off HEAVY -off LEGACY_GROUP_TRACE -off LEGACY_GROUP_DEBUG
```
And then you run the program to trace (`lte-softmodem`, `oaisim`, whatever)
as explained in [basic usage](./basic.md).
To stop the recording, you simply press `control+c` to end `record`.
You send to Eurecom the file `record.raw`. The file `T_messages.txt` is not needed.
To get a list of options, run:
```shell
./record -h
```
The options `-ON`, `-OFF`, `-on` and `-off` are processed in order.
In the example above we first activate all the traces (`-ON`) and then
deactivate specific ones (more precisely, in this particular case:
the *groups* of traces `VCD`, `HEAVY`, `LEGACY_GROUP_TRACE` and
`LEGACY_GROUP_DEBUG`).
You can then [replay](./replay.md) the recorded file or send it to others so they
can analyse things.
# Replay
First, read the [basic usage](./basic.md) to compile things.
Then, read [record](./record.md) to know how to record a trace.
To replay, you use the `replay` program. It will act
as a *tracee* (`lte-softmodem`, `oaisim`, etc.).
Then you use your usual tracer, eg. `enb` or `textlog`.
Since the T is constantly evolving you may need to extract
`T_messages.txt` contained in a trace to be able to process
the trace.
## Example
Download [example.raw](./example.raw). This example contains:
* MAC PDUs as sent and received by the eNodeB
* RRC info messages the eNodeB produced.
First step is to extract `T_messages.txt` from this trace.
```shell
./extract_config -i example.raw > extracted_T_messages.txt
```
Then you use `replay` to act as a regular *tracee*:
```shell
./replay -i example.raw
```
And then, while `replay` is still running, you use the tracer
you want, for example the `textlog` tracer:
```shell
./textlog -d extracted_T_messages.txt -no-gui -ON -full
```
# to_vcd
This tracer is used to dump a VCD trace of the softmodem.
The basic usage is:
```shell
cd common/utils/T/tracer
./to_vcd -d ../T_messages.txt -vcd -o /tmp/openair_dump_eNB.vcd
```
Apart from VCD specific traces, you can dump to VCD other T traces.
Use `-b` and `-l` options. For example, to only log DLSCH scheduler VCD traces, use:
```shell
./to_vcd -d ../T_messages.txt -o /tmp/openair_dump_eNB.vcd -b VCD_FUNCTION_SCHEDULE_DLSCH value mac_schedule_dlsch
```
For more help, run:
```shell
./to_vcd -h
```
# MAC PDUs and wireshark
First, read the [basic usage](./basic.md) to compile things.
It is possible to use `wireshark` to analyse MAC PDUs for UEs,
MIBs, SIBs, and random accesses seen by the eNodeB.
## Live usage
Launch wireshark and listen on the local interface (lo).
Set the filter to `udp.port==9999` and read below
for configuration.
Run the softmodem with the correct command line arguments
(see [basic usage](./basic.md)).
Then run:
```shell
./macpdu2wireshark -d ../T_messages.txt -live
```
For other options of `macpdu2wireshark`, run:
```shell
./macpdu2wireshark -h
```
You can for example disable MIB and SIB logging, or log only
a given number of them.
## Record and replay
You need to record some specific traces. As of 2018-10-30
you have to use the group:
* `WIRESHARK`
That is, run:
```shell
./record -d ../T_messages.txt -o /tmp/record.raw -on WIRESHARK
```
With a recorded trace you then use `macpdu2wireshark`.
## Example
Download [example.raw](example.raw). This example contains
MIBs, SIBs and a connection made by an UE followed by its
disconnection.
First step is to extract `T_messages.txt` from this trace.
```shell
./extract_config -i example.raw > extracted_T_messages.txt
```
Then you run `wireshark`, capture on `lo` and set the
filter to `udp.dstport==9999`.
While `wireshark` is running, you do:
```shell
./macpdu2wireshark -d extracted_T_messages.txt -i example.raw -no-mib -no-sib
```
In `wireshark` you should see something similar to the following:
![wireshark window with dissected MAC PDUs](wireshark.png)
## Configure wireshark for LTE
To dissect the packets, you need to configure `wireshark`.
In the menu, choose `Edit->Preferences`.
In the preference window, unroll `Protocols`.
Go to `UDP` and activate `Try heuristic sub-dissectors first`.
Depending on your version of `wireshark`, you may need to go to `MAC-LTE`
and activate `Try Heuristic LTE-MAC over UDP framing` if this option
is present.
For newer versions (after 2.0 as says wireshark's documentation),
heuristic activation is moved to the `Enabled Protocols` window
(in the menu `Analyze`). In the `enabled protocols` window, search
for `lte` and select `mac_lte_udp` to have `MAC-LTE over UDP`.
You may also want to configure other parameters in `MAC-LTE`,
`RLC-LTE`, `PDCP-LTE`, and maybe others. Check the documentation
of `wireshark`.
It is advised to use a recent version of wireshark (say more than 2.4).
## Configure wireshark for NR
Use a recent version of wireshark. The steps below were done using
version 3.3.2. Maybe some options are different for your version
of wireshark. Adapt as necessary.
First, do the previous steps for LTE.
Then, in the menu, choose `Edit->Preferences`.
In the preference window, unroll `Protocols`.
Go to `MAC-NR`. Select both options (`Attempt to decode BCCH, PCCH and CCCH data using NR RRC dissector`
and `Attempt to dissect LCID 1-3 as srb1-3`).
For `Source of LCID -> drb channel settings` choose option `From static table`.
Then click the `Edit...` button of `LCID -> DRB Mappings Table`.
In the new window, click on `+`. Choose LCID `4`, DRBID `1`, UL RLC Bearer
Type `AM, SN Len=18`, same thing for DL RLC Bearer Type.
Then click OK.
Now, go to `RLC-NR`. Select `Call PDCP dissector for SRB PDUs`.
For `Call PDCP dissector for UL DRB PDUs` choose `18-bit SN`. Same
for DL.
Select `Call RRC dissector for CCCH PDUs`.
You don't need to select `May see RLC headers only` and
`Try to reassemble UM frames`.
Now, go to `PDCP-NR`. Select what you want in there. It's good
to select `Show uncompressed User-Plane data as IP`. Also good
to select `Show unciphered Signalling-Plane data as RRC`.
For `Do sequence number analysis` it can be good to use
`Only-RLC-frames` but anything will do. We don't use ROHC so you
don't need to select `Attempt to decode ROHC data`. And the
layer info to show depends on what you want to analyse.
`Traffic Info` is a good choice.
You are done with the preferences. You can click OK.
Then, in the menu `Analyze`, choose `Enabled Protocols...`. In the new window
search for `nr` and select `mac_nr_udp` to have `MAC-NR over UDP`.
And that's it. Maybe other settings can be changed, but those steps should be
enough for a start.
Note: not all versions of Wireshark correctly dissect encapsulated packets. For instance, we observed that Wireshark v3.4.8 did not call the PDCP dissector for a PDCP PDU split in two RLC SDUs. On the other hand, Wireshark v3.7.0 showed it just fine.
## Alternative to wireshark
While using `macpdu2wireshark` with the `-live` option, it is possible to use `tcpdump` instead of `wireshak` to record MAC PDUs and also other types of traffic (sctp, gtp) in the same output pcap file.
A "catch all" solution is to run:
```
sudo tcpdump -n -iany "udp port 9999 or udp port 2152 or sctp or port 38462 or port 38472 or port 38412 or port 2153" -w /tmp/rec.pcap
```
(This is an example, other solutions are also possible.)
......@@ -20,7 +20,7 @@ T_IDs.h: $(GENIDS) T_messages.txt
check_vcd: T_IDs.h T_messages.txt.h
gcc -Wall -I. -I.. -I../itti -I../../../openair2/COMMON -Itracer -o _check_vcd check_vcd.c tracer/database.c tracer/utils.c -lm -pthread
./_check_vcd || (rm -f ./_check_vcd ./T_IDs.h ./T_messages.txt.h && false)
./_check_vcd T_messages.txt ../LOG/vcd_signal_dumper.h || (rm -f ./_check_vcd ./T_IDs.h ./T_messages.txt.h && false)
rm -f ./_check_vcd
.PHONY: check_vcd
......
......@@ -67,14 +67,17 @@ void err(char *fmt, ...)
exit(1);
}
int main(void)
int main(int argc, char *argv[])
{
/* to disable the checks done by this program, uncomment the following
* line, ie. remove the leading '//'
*/
//return 0;
void *database = parse_database("T_messages.txt");
if (argc != 3) err("usage: %s <T_messages.txt> <vcd_signal_dumper.h>", argv[0]);
char *T_msg_txt = argv[1];
char *vcd_sig_dmp = argv[2];
void *database = parse_database(T_msg_txt);
int number_of_events;
int first_var = -1;
int last_var;
......@@ -212,8 +215,8 @@ int main(void)
* VCD_VARIABLE_ABC or VCD_FUNCTION_XYZ
*/
i = first_var;
in = fopen("../LOG/vcd_signal_dumper.h", "r");
if (in == NULL) err("could not open ../LOG/vcd_signal_dumper.h");
in = fopen(vcd_sig_dmp, "r");
if (in == NULL) err("could not open %s\n", vcd_sig_dmp);
while (1) {
char *x = " VCD_SIGNAL_DUMPER_VARIABLES_";
ssize_t r;
......@@ -253,7 +256,9 @@ int main(void)
err("%s is not correct in T_messages.txt", name);
i++;
}
free(l);
fclose(in);
free_database(database);
if (i != last_fun + 1) err("VCD FUNCTIONS wrong in T_messages.txt");
return 0;
......
add_library(tracer_utils OBJECT config.c database.c event.c handler.c utils.c)
target_link_libraries(tracer_utils PUBLIC m pthread)
add_library(tracer_events OBJECT event_selector.c)
add_executable(record record.c)
target_link_libraries(record PRIVATE tracer_utils)
add_executable(replay replay.c)
target_link_libraries(replay PRIVATE tracer_utils)
add_executable(extract_config extract_config.c)
target_link_libraries(extract_config PRIVATE tracer_utils)
add_executable(extract_input_subframe extract_input_subframe.c)
target_link_libraries(extract_input_subframe PRIVATE tracer_utils)
add_executable(extract_output_subframe extract_output_subframe.c)
target_link_libraries(extract_output_subframe PRIVATE tracer_utils)
add_executable(extract extract.c)
target_link_libraries(extract PRIVATE tracer_utils)
add_executable(textlog textlog.c)
target_link_libraries(textlog PRIVATE tracer_utils tracer_filter tracer_gui
tracer_logger tracer_view tracer_events)
find_library(png png REQUIRED)
add_executable(enb enb.c)
target_link_libraries(enb PRIVATE tracer_utils tracer_filter tracer_gui
tracer_logger tracer_view tracer_events)
target_link_libraries(enb PRIVATE png)
add_executable(ue ue.c)
target_link_libraries(ue PRIVATE tracer_utils tracer_filter tracer_gui
tracer_logger tracer_view tracer_events)
target_link_libraries(ue PRIVATE png)
add_executable(vcd vcd.c)
target_link_libraries(vcd PRIVATE tracer_utils tracer_filter tracer_gui
tracer_logger tracer_view tracer_events)
add_executable(to_vcd to_vcd.c)
target_link_libraries(to_vcd PRIVATE tracer_utils tracer_filter tracer_gui
tracer_logger tracer_view tracer_events)
add_executable(macpdu2wireshark macpdu2wireshark.c)
target_link_libraries(macpdu2wireshark PRIVATE tracer_utils)
add_executable(multi multi.c)
target_link_libraries(multi PRIVATE tracer_utils T)
target_include_directories(multi PRIVATE ..)
add_executable(gnb gnb.c)
target_link_libraries(gnb PRIVATE tracer_utils tracer_filter tracer_gui
tracer_logger tracer_view tracer_events)
target_link_libraries(gnb PRIVATE png)
add_subdirectory(filter)
add_subdirectory(gui)
add_subdirectory(logger)
add_subdirectory(view)
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)
add_dependencies(nr-softmodem T_tools)
add_dependencies(nr-uesoftmodem T_tools)
add_dependencies(lte-softmodem T_tools)
add_dependencies(lte-uesoftmodem T_tools)
......@@ -43,6 +43,14 @@ typedef struct {
buffer value;
} parser;
void *my_bsearch(const void *key, const void *base,
size_t nmemb, size_t size,
int (*compar)(const void *, const void *))
{
if (nmemb == 0) return NULL;
return bsearch(key, base, nmemb, size, compar);
}
void put(buffer *b, int c)
{
if (b->size == b->maxsize) {
......@@ -125,7 +133,7 @@ int string_cmp(const void *_p1, const void *_p2)
id *add_id(database *r, char *idname, int i)
{
if (bsearch(&(id){name:idname}, r->i, r->isize, sizeof(id), id_cmp) != NULL)
if (my_bsearch(&(id){.name=idname}, r->i, r->isize, sizeof(id), id_cmp) != NULL)
{ printf("ERROR: ID '%s' declared more than once\n", idname); exit(1); }
if ((r->isize & 1023) == 0) {
r->i = realloc(r->i, (r->isize + 1024) * sizeof(id));
......@@ -143,14 +151,14 @@ id *add_id(database *r, char *idname, int i)
r->i[r->isize].id = i;
r->isize++;
qsort(r->i, r->isize, sizeof(id), id_cmp);
return (id*)bsearch(&(id){name:idname}, r->i, r->isize, sizeof(id), id_cmp);
return (id*)my_bsearch(&(id){.name=idname}, r->i, r->isize, sizeof(id), id_cmp);
}
group *get_group(database *r, char *group_name)
{
group *ret;
ret = bsearch(&(group){name:group_name},
ret = my_bsearch(&(group){.name=group_name},
r->g, r->gsize, sizeof(group), group_cmp);
if (ret != NULL) return ret;
......@@ -166,7 +174,7 @@ group *get_group(database *r, char *group_name)
qsort(r->g, r->gsize, sizeof(group), group_cmp);
return bsearch(&(group){name:group_name},
return my_bsearch(&(group){.name=group_name},
r->g, r->gsize, sizeof(group), group_cmp);
}
......@@ -182,7 +190,7 @@ void group_add_id(group *g, char *id)
void id_add_group(id *i, char *group)
{
char *g = bsearch(&group, i->groups, i->gsize, sizeof(char *), string_cmp);
char *g = my_bsearch(&group, i->groups, i->gsize, sizeof(char *), string_cmp);
if (g != NULL) return;
if ((i->gsize & 1023) == 0) {
......@@ -392,7 +400,7 @@ void list_groups(void *_d)
static int onoff_id(database *d, char *name, int *a, int onoff)
{
id *i;
i = bsearch(&(id){name:name}, d->i, d->isize, sizeof(id), id_cmp);
i = my_bsearch(&(id){.name=name}, d->i, d->isize, sizeof(id), id_cmp);
if (i == NULL) return 0;
a[i->id] = onoff;
printf("turning %s %s\n", onoff ? "ON" : "OFF", name);
......@@ -403,7 +411,7 @@ static int onoff_group(database *d, char *name, int *a, int onoff)
{
group *g;
int i;
g = bsearch(&(group){name:name}, d->g, d->gsize, sizeof(group), group_cmp);
g = my_bsearch(&(group){.name=name}, d->g, d->gsize, sizeof(group), group_cmp);
if (g == NULL) return 0;
for (i = 0; i < g->size; i++) onoff_id(d, g->ids[i], a, onoff);
return 1;
......@@ -442,7 +450,7 @@ char *event_vcd_name_from_id(void *_database, int id)
int event_id_from_name(void *_database, char *name)
{
database *d = _database;
id *i = (id*)bsearch(&(id){name:name}, d->i, d->isize, sizeof(id), id_cmp);
id *i = (id*)my_bsearch(&(id){.name=name}, d->i, d->isize, sizeof(id), id_cmp);
if (i == NULL)
{ printf("%s:%d: '%s' not found\n", __FILE__, __LINE__, name); abort(); }
return i->id;
......@@ -516,3 +524,31 @@ void database_get_generic_description(void *_d, int id,
PUTC(&o, 0);
*desc = o.obuf;
}
void free_database(void *_d)
{
database *d = _d;
int i;
int j;
free(d->name);
for (i = 0; i < d->isize; i++) {
free(d->i[i].name);
free(d->i[i].desc);
free(d->i[i].groups);
for (j = 0; j < d->i[i].asize; j++) {
free(d->i[i].arg_type[j]);
free(d->i[i].arg_name[j]);
}
free(d->i[i].arg_type);
free(d->i[i].arg_name);
free(d->i[i].vcd_name);
}
free(d->i);
for (i = 0; i < d->gsize; i++) {
free(d->g[i].name);
free(d->g[i].ids);
}
free(d->g);
free(d->id_to_pos);
free(d);
}
......@@ -3,6 +3,7 @@
/* returns an opaque pointer - truly a 'database *', see database.c */
void *parse_database(char *filename);
void free_database(void *database);
void dump_database(void *database);
void list_ids(void *database);
void list_groups(void *database);
......
......@@ -55,8 +55,8 @@ int main(int n, char **v)
int found;
int count = 1;
int check_time = 0;
time_t sec;
long nsec;
time_t sec = 0; /* initialization not necessary but gcc is not happy */
long nsec = 0; /* initialization not necessary but gcc is not happy */
for (i = 1; i < n; i++) {
if (!strcmp(v[i], "-h") || !strcmp(v[i], "--help")) usage();
......
add_library(tracer_filter STATIC filter.c)
target_include_directories(tracer_filter PRIVATE ..)
include(FindPkgConfig)
pkg_check_modules(xft REQUIRED xft)
find_library(X11 X11 REQUIRED)
add_library(tracer_gui STATIC
init.c loop.c toplevel_window.c x.c container.c widget.c
gui.c label.c textarea.c event.c xy_plot.c textlist.c notify.c
positioner.c timeline.c space.c image.c)
target_link_libraries(tracer_gui PRIVATE pthread m ${xft_LIBRARIES} X11)
target_include_directories(tracer_gui PRIVATE ${xft_INCLUDE_DIRS})
......@@ -107,7 +107,7 @@ void send_event(gui *_gui, enum event_type type, ...)
struct gui *g = _gui;
int do_write = 0;
va_list ap;
struct event *e;
struct event *e = NULL; /* initialization not necessary but gcc is not happy */
if (g->queued_events == NULL) do_write = 1;
......
......@@ -2,7 +2,7 @@
#define _X_DEFS_H_
#include <X11/Xlib.h>
#include <Xft.h>
#include <X11/Xft/Xft.h>
struct x_connection {
Display *d;
......
add_library(tracer_logger STATIC
logger.c textlog.c framelog.c ttilog.c timelog.c ticklog.c iqlog.c
iqdotlog.c ticked_ttilog.c throughputlog.c)
target_link_libraries(tracer_logger PRIVATE pthread tracer_filter)
target_include_directories(tracer_logger PRIVATE ..)
......@@ -86,7 +86,7 @@ int main(int n, char **v)
int i;
event_handler *h;
logger *textlog;
gui *g;
gui *g = NULL; /* initialization not necessary but gcc is not happy */
int gui_mode = 0;
view *out;
int gui_active = 1;
......
add_library(tracer_view STATIC
stdout.c textlist.c xy.c tti.c time.c ticktime.c scrolltti.c)
target_link_libraries(tracer_view PRIVATE pthread)
target_include_directories(tracer_view PRIVATE ../logger)
target_include_directories(tracer_view PUBLIC ..)
......@@ -75,7 +75,7 @@ Legacy unmaintained files:
## General
- The [T tracer](https://gitlab.eurecom.fr/oai/openairinterface5g/-/wikis/T/): a generic tracing tool (VCD, Wireshark, GUI, to save for later, ...)
- The [T tracer](../common/utils/T/DOC/T.md): a generic tracing tool (VCD, Wireshark, GUI, to save for later, ...)
- [OPT](../openair2/UTIL/OPT/README.txt): how to trace to wireshark
- The [configuration module](../common/config/DOC/config.md)
- The [logging module](../common/utils/LOG/DOC/log.md)
......
......@@ -40,4 +40,4 @@ RUN /bin/sh oaienv && \
mkdir -p log && \
export CC=/usr/bin/clang && \
export CXX=/usr/bin/clang++ && \
./build_oai --phy_simulators --gNB --eNB --nrUE --UE --ninja --verbose-ci --noavx512 -c --cmake-opt -DCMAKE_C_FLAGS=-Werror --cmake-opt -DCMAKE_CXX_FLAGS=-Werror
./build_oai --phy_simulators --gNB --eNB --nrUE --UE --ninja --verbose-ci --noavx512 --disable-T-Tracer -c --cmake-opt -DCMAKE_C_FLAGS=-Werror --cmake-opt -DCMAKE_CXX_FLAGS=-Werror
......@@ -671,8 +671,6 @@ int32_t nr_rx_pdcch(PHY_VARS_NR_UE *ue,
fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15,
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]) {
uint32_t frame = proc->frame_rx;
uint32_t slot = proc->nr_slot_rx;
NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
uint8_t log2_maxh, aarx;
......@@ -730,11 +728,10 @@ int32_t nr_rx_pdcch(PHY_VARS_NR_UE *ue,
log2_maxh = (log2_approx(avgs) / 2) + 5; //+frame_parms->nb_antennas_rx;
#ifdef UE_DEBUG_TRACE
LOG_D(PHY,"slot %d: pdcch log2_maxh = %d (%d,%d)\n",slot,log2_maxh,avgP[0],avgs);
LOG_D(PHY, "slot %d: pdcch log2_maxh = %d (%d,%d)\n", proc->nr_slot_rx, log2_maxh, avgP[0], avgs);
#endif
#if T_TRACER
T(T_UE_PHY_PDCCH_ENERGY, T_INT(0), T_INT(0), T_INT(frame%1024), T_INT(slot),
T_INT(avgP[0]), T_INT(avgP[1]), T_INT(avgP[2]), T_INT(avgP[3]));
T(T_UE_PHY_PDCCH_ENERGY, T_INT(0), T_INT(0), T_INT(proc->frame_rx % 1024), T_INT(proc->nr_slot_rx), T_INT(avgP[0]), T_INT(avgP[1]), T_INT(avgP[2]), T_INT(avgP[3]));
#endif
LOG_D(PHY,"we enter nr_pdcch_channel_compensation(log2_maxh=%d)\n",log2_maxh);
LOG_D(PHY,"in nr_pdcch_channel_compensation(rxdataF_ext x dl_ch_estimates_ext -> rxdataF_comp)\n");
......
......@@ -200,6 +200,7 @@ void common_signal_procedures_fembms (PHY_VARS_eNB *eNB,int frame, int subframe)
eNB->pbch_configured=0;
}
#if T_TRACER
if (T_ACTIVE(T_ENB_PHY_MIB)) {
/* MIB is stored in reverse in pbch_pdu, reverse it for properly logging */
uint8_t mib[3];
......@@ -209,6 +210,7 @@ void common_signal_procedures_fembms (PHY_VARS_eNB *eNB,int frame, int subframe)
T(T_ENB_PHY_MIB, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe),
T_BUFFER(mib, 3));
}
#endif
generate_pbch_fembms (&eNB->pbch, txdataF, AMP, fp, pbch_pdu, (frame & 15)/4);
} //else if ((subframe == 1) && (fp->frame_type == TDD)) {
//generate_pss (txdataF, AMP, fp, 2, 2);
......@@ -276,6 +278,7 @@ void common_signal_procedures (PHY_VARS_eNB *eNB,int frame, int subframe) {
eNB->pbch_configured=0;
}
#if T_TRACER
if (T_ACTIVE(T_ENB_PHY_MIB)) {
/* MIB is stored in reverse in pbch_pdu, reverse it for properly logging */
uint8_t mib[3];
......@@ -285,6 +288,7 @@ void common_signal_procedures (PHY_VARS_eNB *eNB,int frame, int subframe) {
T(T_ENB_PHY_MIB, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe),
T_BUFFER(mib, 3));
}
#endif
generate_pbch (&eNB->pbch, txdataF, AMP, fp, pbch_pdu, frame & 3);
} else if ((subframe == 1) && (fp->frame_type == TDD)) {
generate_pss (txdataF, AMP, fp, 2, 2);
......
......@@ -99,6 +99,7 @@ void nr_common_signal_procedures (PHY_VARS_gNB *gNB,int frame,int slot,nfapi_nr_
cfg,
fp);
#if T_TRACER
if (T_ACTIVE(T_GNB_PHY_MIB)) {
unsigned char bch[3];
bch[0] = ssb_pdu.ssb_pdu_rel15.bchPayload & 0xff;
......@@ -106,6 +107,7 @@ void nr_common_signal_procedures (PHY_VARS_gNB *gNB,int frame,int slot,nfapi_nr_
bch[2] = (ssb_pdu.ssb_pdu_rel15.bchPayload >> 16) & 0xff;
T(T_GNB_PHY_MIB, T_INT(0) /* module ID */, T_INT(frame), T_INT(slot), T_BUFFER(bch, 3));
}
#endif
// Beam_id is currently used only for FR2
if (fp->freq_range==nr_FR2){
......@@ -135,14 +137,14 @@ void phy_procedures_gNB_TX(processingData_L1tx_t *msgTx,
PHY_VARS_gNB *gNB = msgTx->gNB;
NR_DL_FRAME_PARMS *fp=&gNB->frame_parms;
nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config;
int offset = gNB->CC_id, slot_prs;
int slot_prs = 0;
int txdataF_offset = slot*fp->samples_per_slot_wCP;
prs_config_t *prs_config = NULL;
if ((cfg->cell_config.frame_duplex_type.value == TDD) &&
(nr_slot_select(cfg,frame,slot) == NR_UPLINK_SLOT)) return;
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_TX+offset,1);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_TX + gNB->CC_id, 1);
// clear the transmit data array and beam index for the current slot
for (aa=0; aa<cfg->carrier_config.num_tx_ant.value; aa++) {
......@@ -235,7 +237,7 @@ void phy_procedures_gNB_TX(processingData_L1tx_t *msgTx,
T_INT(aa), T_BUFFER(&gNB->common_vars.txdataF[aa][txdataF_offset], fp->samples_per_slot_wCP*sizeof(int32_t)));
}
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_TX+offset,0);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_TX + gNB->CC_id, 0);
}
static void nr_postDecode(PHY_VARS_gNB *gNB, notifiedFIFO_elt_t *req)
......
......@@ -314,7 +314,6 @@ void nr_ue_measurement_procedures(uint16_t l,
int32_t dl_ch_estimates[][pdsch_est_size]) {
NR_DL_FRAME_PARMS *frame_parms=&ue->frame_parms;
int frame_rx = proc->frame_rx;
int nr_slot_rx = proc->nr_slot_rx;
int gNB_id = proc->gNB_id;
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_MEASUREMENT_PROCEDURES, VCD_FUNCTION_IN);
......@@ -331,14 +330,18 @@ void nr_ue_measurement_procedures(uint16_t l,
#if T_TRACER
if(nr_slot_rx == 0)
T(T_UE_PHY_MEAS, T_INT(gNB_id), T_INT(ue->Mod_id), T_INT(frame_rx%1024), T_INT(nr_slot_rx),
T_INT((int)(10*log10(ue->measurements.rsrp[0])-ue->rx_total_gain_dB)),
T_INT((int)ue->measurements.rx_rssi_dBm[0]),
T_INT((int)(ue->measurements.rx_power_avg_dB[0] - ue->measurements.n0_power_avg_dB)),
T_INT((int)ue->measurements.rx_power_avg_dB[0]),
T_INT((int)ue->measurements.n0_power_avg_dB),
T_INT((int)ue->measurements.wideband_cqi_avg[0]),
T_INT((int)ue->common_vars.freq_offset));
T(T_UE_PHY_MEAS,
T_INT(gNB_id),
T_INT(ue->Mod_id),
T_INT(proc->frame_rx % 1024),
T_INT(nr_slot_rx),
T_INT((int)(10 * log10(ue->measurements.rsrp[0]) - ue->rx_total_gain_dB)),
T_INT((int)ue->measurements.rx_rssi_dBm[0]),
T_INT((int)(ue->measurements.rx_power_avg_dB[0] - ue->measurements.n0_power_avg_dB)),
T_INT((int)ue->measurements.rx_power_avg_dB[0]),
T_INT((int)ue->measurements.n0_power_avg_dB),
T_INT((int)ue->measurements.wideband_cqi_avg[0]),
T_INT((int)ue->common_vars.freq_offset));
#endif
}
......
......@@ -2731,6 +2731,7 @@ int ue_pdcch_procedures(uint8_t eNB_id,
CBA_RNTI,
eNB_id,
0)==0)) {
#if T_TRACER
int harq_pid = subframe2harq_pid(&ue->frame_parms,
pdcch_alloc2ul_frame(&ue->frame_parms,proc->frame_rx,proc->subframe_rx),
pdcch_alloc2ul_subframe(&ue->frame_parms,proc->subframe_rx));
......@@ -2749,6 +2750,7 @@ int ue_pdcch_procedures(uint8_t eNB_id,
pdcch_alloc2ul_subframe(&ue->frame_parms,proc->subframe_rx));
LOG_D(PHY,"[UE %d] Generate UE ULSCH C_RNTI format 0 (subframe %d)\n",ue->Mod_id,subframe_rx);
}
#endif
}
} else if( (dci_alloc_rx[i].rnti == ue->ulsch[eNB_id]->cba_rnti[0]) &&
(dci_alloc_rx[i].format == format0)) {
......
......@@ -902,7 +902,6 @@ int main(int argc, char **argv) {
// moreover you need to init itti with the following line
// however itti will catch all signals, so ctrl-c won't work anymore
// alternatively you can disable ITTI completely in CMakeLists.txt
T_stdout = 1;
if (common_flag == 0) {
switch (N_RB_DL) {
......
......@@ -398,7 +398,6 @@ int main(int argc, char **argv) {
AssertFatal(load_configmodule(argc,argv,CONFIG_ENABLECMDLINEONLY) != NULL, "Cannot load configuration module, exiting\n");
logInit();
set_glog(OAILOG_INFO);
T_stdout = 1;
// enable these lines if you need debug info
// however itti will catch all signals, so ctrl-c won't work anymore
// alternatively you can disable ITTI completely in CMakeLists.txt
......
......@@ -342,7 +342,6 @@ int main(int argc, char **argv)
logInit();
set_glog(loglvl);
T_stdout = 1;
if (snr1set == 0)
snr1 = snr0 + 10;
......
......@@ -610,7 +610,6 @@ int main(int argc, char **argv)
logInit();
set_glog(loglvl);
T_stdout = 1;
/* initialize the sin table */
InitSinLUT();
......
......@@ -478,7 +478,6 @@ int main(int argc, char **argv)
logInit();
set_glog(loglvl);
T_stdout = 1;
if (snr1set==0)
snr1 = snr0+10;
......
......@@ -411,7 +411,6 @@ int main(int argc, char **argv){
// Configure log
logInit();
set_glog(loglvl);
T_stdout = 1;
SET_LOG_DEBUG(PRACH);
// Configure gNB and RU
......
......@@ -377,7 +377,6 @@ int main(int argc, char **argv)
logInit();
set_glog(loglvl);
T_stdout = 1;
if (snr1set == 0)
snr1 = snr0 + 10;
......
......@@ -561,7 +561,6 @@ int main(int argc, char **argv)
logInit();
set_glog(loglvl);
T_stdout = 1;
get_softmodem_params()->phy_test = 1;
get_softmodem_params()->do_ra = 0;
......
pkg_check_modules(bladeRF REQUIRED libbladeRF)
add_library(oai_bladerfdevif MODULE bladerf_lib.c)
target_link_libraries(oai_bladerfdevif PRIVATE bladeRF)
target_link_libraries(oai_bladerfdevif PRIVATE UTIL)
set_target_properties(oai_bladerfdevif PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
add_custom_command(TARGET oai_bladerfdevif POST_BUILD
COMMAND ${CMAKE_COMMAND} -E create_symlink liboai_bladerfdevif.so liboai_device.so
......
......@@ -1131,7 +1131,16 @@ int device_init(openair0_device *device,
printf("[BRF] calibration OK\n");
#endif
bladerf_log_set_verbosity(get_brf_log_level(openair0_cfg->log_level));
/* set log to info, available log levels are:
* - BLADERF_LOG_LEVEL_VERBOSE
* - BLADERF_LOG_LEVEL_DEBUG
* - BLADERF_LOG_LEVEL_INFO
* - BLADERF_LOG_LEVEL_WARNING
* - BLADERF_LOG_LEVEL_ERROR
* - BLADERF_LOG_LEVEL_CRITICAL
* - BLADERF_LOG_LEVEL_SILENT
*/
bladerf_log_set_verbosity(BLADERF_LOG_LEVEL_INFO);
printf("BLADERF: Initializing openair0_device\n");
device->Mod_id = num_devices++;
......@@ -1208,38 +1217,4 @@ struct bladerf * open_bladerf_from_serial(const char *serial)
return dev;
}
}
/*! \brief Get BladeRF log level
* \param log_level log level
* \returns log level of BLADERF device
*/
int get_brf_log_level(int log_level)
{
int level=BLADERF_LOG_LEVEL_INFO;
return BLADERF_LOG_LEVEL_INFO;
switch(log_level) {
case LOG_DEBUG:
level=BLADERF_LOG_LEVEL_DEBUG;
break;
case LOG_INFO:
level= BLADERF_LOG_LEVEL_INFO;
break;
case LOG_WARNING:
level=BLADERF_LOG_LEVEL_WARNING;
break;
case LOG_ERR:
level=BLADERF_LOG_LEVEL_ERROR;
break;
case LOG_CRIT:
level=BLADERF_LOG_LEVEL_CRITICAL;
break;
case LOG_EMERG:
level = BLADERF_LOG_LEVEL_SILENT;
break;
default:
break;
}
return level;
}
/*@}*/
......@@ -24,10 +24,12 @@
* Author: navid nikaein
*/
#ifndef BLADERF_LIB_H
#define BLADERF_LIB_H
#include <libbladeRF.h>
#include "common_lib.h"
#include "LOG/log.h"
/** @addtogroup _BLADERF_PHY_RF_INTERFACE_
* @{
......@@ -109,12 +111,6 @@ int trx_brf_init(openair0_device *device);
*/
openair0_timestamp trx_get_timestamp(openair0_device *device, bladerf_module module);
/*! \brief Get BladeRF log level
* \param log_level log level
* \returns log level of BLADERF device
*/
int get_brf_log_level(int log_level);
/*! \brief bladeRF error report
* \param status
* \returns 0 on success
......@@ -122,3 +118,5 @@ int get_brf_log_level(int log_level);
int brf_error(int status);
/*@}*/
#endif /* BLADERF_LIB_H */
......@@ -45,7 +45,6 @@
#include <netinet/ether.h>
#include <unistd.h>
#include <errno.h>
#include "common/utils/LOG/vcd_signal_dumper.h"
#include <sched.h>
#include "common_lib.h"
......
......@@ -3,7 +3,8 @@ find_package(UHD REQUIRED)
add_library(oai_usrpdevif MODULE usrp_lib.cpp)
#target_include_directories(oai_usrpdevif PRIVATE Boost::boost)
target_link_libraries(oai_usrpdevif uhd)
target_link_libraries(oai_usrpdevif PRIVATE uhd)
target_link_libraries(oai_usrpdevif PRIVATE UTIL)
set_target_properties(oai_usrpdevif PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
add_custom_command(TARGET oai_usrpdevif POST_BUILD
COMMAND ${CMAKE_COMMAND} -E create_symlink liboai_usrpdevif.so liboai_device.so
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment