Merge branch 'develop' into develop-nr
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
# OAI shared library loader
|
||||
|
||||
Shared libraries usage is modularization mechanism which provides the following advantages:
|
||||
1. Prevents including in the main executable code which is not used in a given configuration
|
||||
1. Provides flexibility, several implementation of a given functionality can be chosen at run-time, without any compilation step. For example you can build several devices (USRP, BladeFR, LimeSDR) and choose which one you want to use on the command line or via the configuration.
|
||||
1. Makes code evolution easier: as soon as the shared library interface is clearly defined, you can work on the functionality implemented in a shared library while regularly updating the other components of the code. You can decide to develop your own version of a functionality, decide to deliver it or not, letting the user decide wwhat version he wants to use.
|
||||
|
||||
The main drawback is a performance cost at init time, when loading libraries.
|
||||
|
||||
|
||||
## Documentation
|
||||
|
||||
* [runtime usage](loader/rtusage.md)
|
||||
* [developer usage](loader/devusage.md)
|
||||
* [module architecture](loader/arch.md)
|
||||
|
||||
[oai Wikis home](https://gitlab.eurecom.fr/oai/openairinterface5g/wikis/home)
|
||||
@@ -0,0 +1,7 @@
|
||||
# loader source files
|
||||
|
||||
The oai shared library loader is implemented in two source files, located in [common/utils](https://gitlab.eurecom.fr/oai/openairinterface5g/tree/develop/common/utils)
|
||||
1. [load_module_shlib.c](https://gitlab.eurecom.fr/oai/openairinterface5g/tree/develop/common/utils/load_module_shlib.c) contains the loader implementation
|
||||
1. [load_module_shlib.h](https://gitlab.eurecom.fr/oai/openairinterface5g/tree/develop/common/utils/load_module_shlib.h) is the loader include file containing both private and public data type definitions. It also contain API prototypes.
|
||||
|
||||
[loader home page](../loader.md)
|
||||
@@ -0,0 +1,16 @@
|
||||
The loader objectives are
|
||||
1. provides a common mechanism to prevent an executable to include code that is only used under specific configurations, without rebuilding the code
|
||||
1. Provide a common mechanism to allow to choose between different implementations of a given set of functions, without rebuilding the code
|
||||
|
||||
As a developer you may need to look at these sections:
|
||||
|
||||
* [loading a shared library](devusage/loading.md)
|
||||
* [loader API](devusage/api.md)
|
||||
* [loader public structures](devusage/struct.md)
|
||||
|
||||
Loader usage examples can be found in oai sources:
|
||||
|
||||
* device and transport initialization code: [function `load_lib` in *targets/ARCH/COMMON/__common_lib.c__* ](https://gitlab.eurecom.fr/oai/openairinterface5g/blob/develop/targets/ARCH/COMMON/common_lib.c#L91)
|
||||
* turbo encoder and decoder initialization: [function `load_codinglib`in *openair1/PHY/CODING/__coding_load.c__*](https://gitlab.eurecom.fr/oai/openairinterface5g/blob/develop/openair1/PHY/CODING/coding_load.c#L113)
|
||||
|
||||
[loader home page](../loader.md)
|
||||
@@ -0,0 +1,20 @@
|
||||
Loader API is defined in the [common/utils/load_module_shlib.h](https://gitlab.eurecom.fr/oai/openairinterface5g/blob/develop/common/utils/load_module_shlib.h) include file.
|
||||
```c
|
||||
int load_module_shlib(char *modname,loader_shlibfunc_t *farray, int numf)
|
||||
```
|
||||
* possibly initializes the loader, if it has not been already initialized
|
||||
* Formats the full shared library path, using the `modname` argument and the loader `shlibpath` and `shlibversion`configuration parameters.
|
||||
* loads the shared library, using the dlopen system call
|
||||
* looks for `< modname >_autoinit` symbol, using the `dlsym` system call and possibly call the corresponding function.
|
||||
* looks for `< modname >_checkbuildver` symbol, using the `dlsym` system call and possibly calls the corresponding function. If the return value of this call is `-1`, program execution is stopped. It is the responsibility of the shared library developer to implement or not a `< modname >_checkbuildver` function and to decide if a version mismatch is a fatal condition. The `< modname >_checkbuildver` function must match the `checkverfunc_t` function type. The first argument is the main executable version, as set in the `PACKAGE_VERSION` macro defined in the [oai CMakeLists](https://gitlab.eurecom.fr/oai/openairinterface5g/blob/develop/cmake_targets/CMakeLists.txt#L218), around line 218. The second argument points to the shared library version which should be set by the `< modname >_checkbuildver` function.
|
||||
* If the farray pointer is null, looks for `< modname >_getfarray` symbol, calls the corresponding function when the symbol is found. `< modname >_getfarray` takes one argument, a pointer to a `loader_shlibfunc_t` array, and returns the number of items in this array, as defined by the `getfarrayfunc_t` type. The `loader_shlibfunc_t` array returned by the shared library must be fully filled (both `fname` and `fptr` fields).
|
||||
* looks for the `numf` function symbols listed in the `farray[i].fname` arguments and set the corresponding `farray[i].fptr`function pointers
|
||||
|
||||
|
||||
```c
|
||||
void * get_shlibmodule_fptr(char *modname, char *fname)
|
||||
```
|
||||
Returns a pointer to the symbol `fname`, defined in module `modname`, or `NULL` if the symbol is not found.
|
||||
|
||||
[loader home page](../../loader.md)
|
||||
[loader developer home page](../devusage.md)
|
||||
@@ -0,0 +1,56 @@
|
||||
Implementing a shared library dynamic load using the oai loader is a two steps task:
|
||||
1. define the `loader_shlibfunc_t` array, describing the list of externally available functions implemented in the library. This is the interface of the module.
|
||||
1. Call the `load_module_shlib` function, passing it the previously defined array and the number of items in this array. The first argument to `load_module_shlib` is the name identifying the module, which is also used to format the corresponding library name, as described [here](loader/rtusage#shared-library-names)
|
||||
|
||||
After a successful `load__module_shlib` call, the function pointer of each `loader_shlibfunc_t` array item has been set and can be used to call the corresponding function.
|
||||
|
||||
Typical loader usage looks like:
|
||||
|
||||
```c
|
||||
/* shared library loader include file */
|
||||
#include "common/utils/load_module_shlib.h"
|
||||
.............
|
||||
/*
|
||||
define and initialize the array, describing the list of functions
|
||||
implemented in "mymodule"
|
||||
*/
|
||||
loader_shlibfunc_t mymodule_fdesc[2];
|
||||
mymodule_fdesc[0].fname="mymodule_f1";
|
||||
mymodule_fdesc[1].fname="mymodule_f2";
|
||||
|
||||
/*
|
||||
load the library, it's name must be libmymod.so. Configuration can be
|
||||
used to specify a specific path to look for libmymod.so. Configuration
|
||||
can also specify a version, for example "V1", in this case the loader
|
||||
will look for libmymodV1.so
|
||||
*/
|
||||
ret=load_module_shlib("mymod",mymodule_fdesc, sizeof(mymodule_fdesc)/sizeof(loader_shlibfunc_t));
|
||||
if (ret < 0) {
|
||||
fprintf(stderr,"Library couldn't be loaded\n");
|
||||
} else {
|
||||
/*
|
||||
library has been loaded, we probably want to call some functions...
|
||||
*/
|
||||
ret=((funcf1_t)mymodule_fdesc[0].fptr)();
|
||||
|
||||
..................
|
||||
/*
|
||||
later and/or somewhere else in the code you may want to call function "mymodule_f2"
|
||||
You can use the loader get_shlibmodule_fptr(char *modname, char *fname) function
|
||||
to retrieve the pointer to that function
|
||||
*/
|
||||
funcf2_t *f2;
|
||||
int ret;
|
||||
int intarg1;
|
||||
char *strarg;
|
||||
........................
|
||||
f2 = (funcf2_t)get_shlibmodule_fptr("mymodule", "mymodule_f2")
|
||||
if (f2 != NULL) {
|
||||
ret = f2(intarg1,strarg);
|
||||
}
|
||||
...............
|
||||
```
|
||||
When loading a shared library the loader looks for a symbol named `< module name > _autoinit` and, if it finds it, calls it. The `autoinit` function is called without any argument and the returned value, if any, is not tested.
|
||||
|
||||
[loader home page](../loader.md)
|
||||
[loader developer home page](../../loader/devusage.md)
|
||||
@@ -0,0 +1,10 @@
|
||||
# `loader_shlibfunc_t`structure
|
||||
It is defined in include file [ common/util/load_module_shlib.h ](https://gitlab.eurecom.fr/oai/openairinterface5g/blob/develop/common/utils/load_module_shlib.h#L38). This structure is used to list the symbols that should be searched by the loader when calling the `load_module_shlib` function.
|
||||
|
||||
| Fields | Description | I/O |
|
||||
|:-----------|:------------------------------------------------------------------|----:|
|
||||
| `fname` | symbol name, is passed to the [`dlsym`](http://man7.org/linux/man-pages/man3/dlsym.3.html) system call performed by the loader to get a pointer to the symbol | I |
|
||||
| `fptr` | pointer to the symbol name, set by the loader. `fptr` is defined as a `int (*fptr)(void)` function type | O |
|
||||
|
||||
[loader home page](../../loader.md)
|
||||
[loader developer home page](../devusage.md)
|
||||
@@ -0,0 +1,50 @@
|
||||
## shared library names
|
||||
Shared library full names are built by the loader using the format:
|
||||
> < *path* >/lib< *module name* >< *module version* >.so
|
||||
|
||||
1. the < *module name* > is defined at development time, it comes from the `modname` argument of the `load_module_shlib` call.
|
||||
1. the < *module version* > and < *path* > optional parameters, are defined at run-time, depending on the configuration.
|
||||
|
||||
## loader parameters
|
||||
The loader is using the [configuration module](../../../config/DOC/config.md), and defines global and per library parameters. Global parameters must be specified under the **loader** section and library specific parameters under a **loader.<*module name*>** section. Module specific parameters override the global parameters.
|
||||
### Global loader parameters
|
||||
| name | type | default | description |
|
||||
|:---:|:---:|:---:|:----|
|
||||
| `shlibpath` | `string of char` | `""` | directory path used to look for shared libraries, may be superseded by the library specific `shlibpath`.|
|
||||
| `maxshlibs` | `integer` | 10 | Maximum number of shared libraries the loader can manage. |
|
||||
|
||||
### library specific loader parameters
|
||||
| name | type | default | description |
|
||||
|:---:|:---:|:---:|:----|
|
||||
| `shlibpath` | `string of char` | `""` | directory path used to look for this shared library.|
|
||||
| `shlibversion` | `string of char` | `""` | version to be used to load this shared library.|
|
||||
|
||||
### loader configuration examples
|
||||
|
||||
The following configuration file example just reproduce the default loader parameters:
|
||||
```c
|
||||
loader :
|
||||
{
|
||||
shlibpath = "./";
|
||||
maxshlibs = 10;
|
||||
liboai_device :
|
||||
{
|
||||
shlibpath = "./";
|
||||
shlibversion = "";
|
||||
}
|
||||
};
|
||||
```
|
||||
If you want to load a device called *liboai_device_USRP.so* without writting a specific configuration, you can start the softmodem using the following command:
|
||||
> ./lte-softmodem -O libconfig:/usr/local/oai/openairinterface5g/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.nbiot.band7.tm1.50PRB.usrpb210.conf:dbgl5 --loader.oai_device.shlibversion _USRP
|
||||
|
||||
With this latest example, nn the softmodem logs, you can check that the right device library has been loaded:
|
||||
```bash
|
||||
[LIBCONFIG] loader.oai_device.shlibpath not found in /usr/local/oai/develop-nb-iot-merge/openairinterface5g/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.nbiot.band7.tm1.50PRB.usrpb210.conf
|
||||
[LIBCONFIG] loader.oai_device.shlibversion set to default value ""
|
||||
[LIBCONFIG] loader.oai_device: 1/2 parameters successfully set, (1 to default value)
|
||||
[CONFIG] shlibversion set to _USRP from command line
|
||||
[CONFIG] loader.oai_device 1 options set from command line
|
||||
|
||||
```
|
||||
|
||||
[loader home page](../loader.md)
|
||||
@@ -0,0 +1,110 @@
|
||||
### Adding console traces in oai code
|
||||
#### console messages macros
|
||||
```C
|
||||
LOG_E(<component>,<format>,<argument>,...)
|
||||
LOG_W(<component>,<format>,<argument>,...)
|
||||
LOG_I(<component>,<format>,<argument>,...)
|
||||
LOG_D(<component>,<format>,<argument>,...)
|
||||
LOG_T(<component>,<format>,<argument>,...)
|
||||
)
|
||||
```
|
||||
these macros are used in place of the printf C function. The additionnal ***component*** parameter identifies the functionnal module which generates the message. At run time, the message will only be printed if the configured log level for the component is greater or equal than the macro level used in the code.
|
||||
|
||||
| macro | level letter | level value | level name |
|
||||
|:---------|:---------------|:---------------|----------------:|
|
||||
| LOG_E | E | 0 | error |
|
||||
| LOG_W | W | 1 | warning |
|
||||
| LOG_I | I | 2 | informational |
|
||||
| LOG_D | D | 3 | debug |
|
||||
| LOG_T | T | 4 | trace |
|
||||
|
||||
component list is defined as an `enum` in [log.h](https://gitlab.eurecom.fr/oai/openairinterface5g/blob/develop/common/utils/LOG/log.h). A new component can be defined by adding an item in this type, it must also be defined in the T tracer [T_messages.txt ](https://gitlab.eurecom.fr/oai/openairinterface5g/blob/develop/common/utils/T/T_messages.txt).
|
||||
|
||||
Most oai sources are including LOG macros.
|
||||
|
||||
#### conditional code macros
|
||||
|
||||
```C
|
||||
LOG_DEBUGFLAG(<flag>)
|
||||
```
|
||||
this macro is to be used in if statements. The condition is true if the flag has been set, as described in the [run time usage page](rtusage.md)
|
||||
```C
|
||||
if ( LOG_DEBUGFLAG(<flag>) {
|
||||
/*
|
||||
the code below is only executed if the corresponding
|
||||
<flag>_debug option is set.
|
||||
*/
|
||||
......................
|
||||
......................
|
||||
}
|
||||
```
|
||||
[example in oai code](https://gitlab.eurecom.fr/oai/openairinterface5g/blob/develop/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c#L396)
|
||||
|
||||
#### memory dump macros
|
||||
```C
|
||||
LOG_DUMPFLAG(<flag>)
|
||||
```
|
||||
this macro is to be used in if statements. The condition is true if the flag has been set, as described in the [run time usage page](rtusage.md). It is mainly provided to surround LOG_M macros or direct calls to `log_dump`which otherwise would be unconditionals.
|
||||
```C
|
||||
if ( LOG_DUMPFLAG(<flag>) {
|
||||
/*
|
||||
the code below is only executed if the corresponding
|
||||
<flag>_dump option is set.
|
||||
*/
|
||||
LOG_M(.............
|
||||
LOG_M(.............
|
||||
log_dump(...
|
||||
}
|
||||
|
||||
[example in oai code](https://gitlab.eurecom.fr/oai/openairinterface5g/blob/develop/openair1/PHY/LTE_TRANSPORT/prach.c#L205)
|
||||
#### matlab format dump
|
||||
```C
|
||||
LOG_M(file, vector, data, len, dec, format)
|
||||
```
|
||||
|argument| type| description |
|
||||
|:-----------|:-------|-----------------:|
|
||||
| file | char* |path to the fle which will contain the dump |
|
||||
|vector |char * |name of the dump, printed at the top of the dump file |
|
||||
|data| void *| pointer to the memory to be dumpped |
|
||||
|len | int | length of the data to be dumpped, in `dec` unit|
|
||||
| dec| int | length of each data item.Interpretation depends on format|
|
||||
|format| int | defines the type of data to be dumped|
|
||||
|
||||
This macro can be used to dump a buffer in a format that can be used for analyze via tools like matlab or octave. **It must be surrounded by LOG_DEBUGFLAG or LOG_DUMPFLAG macros, to prevent the dump to be built unconditionally.** The LOG_M macro points to the `write_file_matlab` function implemented in [log.c](https://gitlab.eurecom.fr/oai/openairinterface5g/blob/develop/common/utils/LOG/log.c). **This function should be revisited for more understandable implementation and ease of use (format parameter ???)**
|
||||
[example in oai code](https://gitlab.eurecom.fr/oai/openairinterface5g/blob/develop/openair1/PHY/LTE_TRANSPORT/prach.c#L205)
|
||||
|
||||
#### hexadecimal format dump
|
||||
```C
|
||||
LOG_DUMPMSG(c, f, b, s, x...)
|
||||
```
|
||||
dumps a memory region if the corresponding debug flag `f` is set as explained here [run time usage page](rtusage.md)
|
||||
|
||||
|argument| type| description |
|
||||
|:-----------|:-------|-----------------:|
|
||||
| c | int, component id (in `comp_name_t` enum)| used to print the message, as specified by the s and x arguments |
|
||||
|f |int |flag used to filter the dump depending on the logs configuration. flag list is defined by the LOG_MASKMAP_INIT macro in [log.h](https://gitlab.eurecom.fr/oai/openairinterface5g/blob/develop/common/utils/LOG/log.h) |
|
||||
|b| void *| pointer to the memory to be dumpped |
|
||||
|s | int | length of the data to be dumpped in char|
|
||||
| x...| printf format and arguments| text string to be printed at the top of the dump|
|
||||
|
||||
This macro can be used to conditionaly dump a buffer, bytes by bytes, giving the integer value of each byte in hexadecimal form.
|
||||
[example in oai code](https://gitlab.eurecom.fr/oai/openairinterface5g/blob/develop/openair2/RRC/LTE/rrc_eNB.c#L1181)
|
||||
|
||||
This macro points to the `log_dump` function, implemented in [log.c](https://gitlab.eurecom.fr/oai/openairinterface5g/blob/develop/common/utils/LOG/log.c). This function can also dump buffers containing `double` data via the LOG_UDUMPMSG macro
|
||||
|
||||
```C
|
||||
LOG_UDUMPMSG(c, b, s, f, x...)
|
||||
```
|
||||
|argument| type| description |
|
||||
|:-----------|:-------|-----------------:|
|
||||
| c | int, component id (in `comp_name_t` enum)| used to print the message, as specified by the s and x arguments |
|
||||
|b| void *| pointer to the memory to be dumpped |
|
||||
|s | int | length of the data to be dumpped in char|
|
||||
|f| int | format of dumped data LOG_DUMP_CHAR or LOG_DUMP_DOUBLE|
|
||||
| x...| printf format and arguments| text string to be printed at the top of the dump|
|
||||
|
||||
[example in oai code](https://gitlab.eurecom.fr/oai/openairinterface5g/blob/develop/openair1/SIMULATION/LTE_PHY/dlsim.c#L1974)
|
||||
|
||||
[logging facility developer main page](devusage.md)
|
||||
[logging facility main page](log.md)
|
||||
[oai Wikis home](https://gitlab.eurecom.fr/oai/openairinterface5g/wikis/home)
|
||||
@@ -0,0 +1,12 @@
|
||||
# logging facility source files
|
||||
|
||||
The oai logging facility is implemented in two source files, located in [common/utils/LOG](LOG)
|
||||
1. [log.c](../log.c) contains logging implementation
|
||||
1. [log.h](../log.h) is the logging facility include file containing both private and public data type definitions. It also contain API prototypes.
|
||||
|
||||
The logging facility doesn't create any thread, all api's are executed in the context of the caller. The tracing macro's `LOG_<X>` are all using the logRecord_mt function to output the messages. To keep this function thread safe it must perform a single system call to the output stream. The buffer used to build the message must be specific to the calling thread, which is today enforced by using a variable in the logRecord_mt stack.
|
||||
|
||||
Data used by the logging utility are defined by the `log_t` structure which is allocated at init time, when calling the `logInit` function.
|
||||
|
||||
[logging facility main page](log.md)
|
||||
[oai Wikis home](https://gitlab.eurecom.fr/oai/openairinterface5g/wikis/home)
|
||||
@@ -0,0 +1,49 @@
|
||||
### Initializing and configuring the logging facility
|
||||
|
||||
#### logging facility APIs
|
||||
```C
|
||||
int logInit (void);
|
||||
```
|
||||
Allocate the internal data used by the logging utility, set the configuration, using the [configuration module](../../../config/DOC/config.md)
|
||||
|
||||
```C
|
||||
void logClean (void)
|
||||
```
|
||||
Reset console attributes (color settings) and possibly close opened log files. Logging facility is still usable after this call, the internal data are not freed.
|
||||
|
||||
```C
|
||||
int set_log(int component, int level)
|
||||
void set_glog(int level)
|
||||
```
|
||||
Set a component or all components logiing level. Messages which level is lower than this level are not printed to the console.
|
||||
|
||||
```C
|
||||
void set_glog_onlinelog(int enable)
|
||||
```
|
||||
Enable or disable all logging messages. Even error level messages are discarded, which is not advised. This can be usefull to temporarily workaround high rate of logging messages.
|
||||
|
||||
```C
|
||||
void set_component_filelog(int comp)
|
||||
void close_component_filelog(int comp)
|
||||
```
|
||||
|
||||
Redirect or reset to stdout the output stream used by the logging facility. When the output stream is redirected to a file, it is created under /tmp with a hard-coded filename including the componemt name.
|
||||
|
||||
```C
|
||||
SET_LOG_DEBUG(flag)
|
||||
CLEAR_LOG_DEBUG(flag)
|
||||
SET_LOG_DUMP(flag)
|
||||
CLEAR_LOG_DUMP(flag)
|
||||
```
|
||||
These macros are used to set or clear the corresponding bit flag, trigerring the activation or un-activation of conditional code or memory dumps generation.
|
||||
|
||||
Example of using the logging utility APIs can be found, for initialization and cleanup, in [lte-softmodem.c](../../../../targets/RT/USER/lte-softmodem.c) and in the [telnet server log command implementation](../../telnetsrv/telnetsrv_proccmd.c) for a complete access to the logging facility features.
|
||||
|
||||
#### components and debug flags definitions
|
||||
|
||||
Adding a new component is just adding an item in the `comp_name_t` enum defined in [log.h](../log.h) . You must also declare it in the T Tracer facility [message fefinitions](../../T/T_messages.txt).
|
||||
To add a flag than can then be used for adding conditional code or memory dumps you have to add the flag definition in the `LOG_MASKMAP_INIT` macro, in [log.h](../log.h).
|
||||
|
||||
[logging facility developer main page](devusage.md)
|
||||
[logging facility main page](log.md)
|
||||
[oai Wikis home](https://gitlab.eurecom.fr/oai/openairinterface5g/wikis/home)
|
||||
@@ -0,0 +1,14 @@
|
||||
### logging facility developer usage
|
||||
The logging facility objectives are
|
||||
1. provide a common console tracing mechanism
|
||||
1. Allow a flexible activation of console traces, by configuration or dynamically at any time while code is running.
|
||||
|
||||
Most developpers will only use the log macros to add console messages to the code. The logging facility also provides an api that is used for initialization and configuration.
|
||||
|
||||
[Adding console traces in oaicode](addconsoletrace.md)
|
||||
|
||||
[Configuring the logging facility](configurelog.md)
|
||||
|
||||
|
||||
[logging facility main page](log.md)
|
||||
[oai Wikis home](https://gitlab.eurecom.fr/oai/openairinterface5g/wikis/home)
|
||||
@@ -0,0 +1,19 @@
|
||||
# OAI console logging facility
|
||||
|
||||
oai includes a console logging facility that any component should use when writting informational or debugging messages to the softmodem or uesoftmodem stdout stream.
|
||||
By default, this facility is included at build-time and activated at run-time. The T Tracer and the Logging facility share common options for activation:
|
||||
|
||||
- To disable the logging facility (and T Tracer) at build-time use the *--disable-T-Tracer* switch:
|
||||
|
||||
```bash
|
||||
/build_oai --disable-T-Tracer
|
||||
```
|
||||
- To use the the T-Tracer instead of the console logging facility, use the command line option *T_stdout*. *T_stdout* is a boolean option, which, when set to 0 (false) disable the console logging facility. All stdout messages are then sent to the T-Tracer.
|
||||
|
||||
## Documentation
|
||||
|
||||
* [runtime usage](rtusage.md)
|
||||
* [developer usage](devusage.md)
|
||||
* [module architecture](arch.md)
|
||||
|
||||
[oai Wikis home](https://gitlab.eurecom.fr/oai/openairinterface5g/wikis/home)
|
||||
@@ -0,0 +1,265 @@
|
||||
## configuring the logging facility
|
||||
The logging facility is fully configurable and it uses the [config module](../../../config/config.md) to get its parameters at init time. The [telnet server](../../telnetsrv/DOC/telnetsrv.md) includes a set of commands which can be used to dynamically modify the logging facility behavior
|
||||
|
||||
All logging facility parameters are defined in the log_config section. Some parameters are global to the logging facility, they modify the way messages are printed to stdout. Conversely, some parameters are specific to a component and only modify the behavior for messages issued by a given component. A third type of parameters can be used to activate conditional debug code or dump messages or buffers.
|
||||
|
||||
### global parameters
|
||||
|
||||
| name | type | default | description |
|
||||
|:---:|:---:|:---:|:----|
|
||||
| `global_log_level` | `pre-defined string of char` | `info` | Allows printing of messages up to the specified level. Available levels, from lower to higher are `error`,`warn`,`info`,`debug`,`trace` |
|
||||
| `global_log_online` | `boolean` | 1 (=true) | If false, all console messages are discarded, whatever their level |
|
||||
| `global_log_options` | `list of pre-defined string of char` | | 3 options can be specified to trigger the information added in the header of the message: `nocolor`, disable color usage in log messages, usefull when redirecting logs to a file, where escape sequences used for color selection can be annoying, `level`, add a one letter level id in the message header (T,D,I,W,E for trace, debug, info, warning, error),`thread`, add the thread name in the message header|
|
||||
|
||||
### Component specific parameters
|
||||
| name | type | default | description |
|
||||
|:---:|:---:|:---:|:----|
|
||||
| `<component>_log_level` | `boolean` | global log level, as defined by the `global_log_level ` parameter) |
|
||||
| `<component>_log_infile` | `boolean` | 0 = false| Triggers the redirection of log messages printed by the specified component in a file. The file path and name is /tmp/<componemt>.[extension] the extension is optional and component dependant, it can be `log `, `dat `, `txt `|
|
||||
|
||||
The list of components defined within oai can be retrieved from the [config module](../../../config/config.md) traces, when asking for config module debugging info on the command line:
|
||||
|
||||
```bash
|
||||
./lte-softmodem -O libconfig:<path to config file>:dbgl5
|
||||
|
||||
[LIBCONFIG] log_config.global_log_level: "info"
|
||||
[CONFIG] global_log_online: 1
|
||||
[CONFIG] log_config.global_log_online set to default value
|
||||
[LIBCONFIG] log_config: 3/3 parameters successfully set, (1 to default value)
|
||||
[LIBCONFIG] global_log_options[0]: nocolor
|
||||
[LIBCONFIG] global_log_options[1]: level
|
||||
[LIBCONFIG] global_log_options[2]: thread
|
||||
[CONFIG] log_config 1 options set from command line
|
||||
[LIBCONFIG] log_config.phy_log_level: "info"
|
||||
[LIBCONFIG] log_config.mac_log_level: "info"
|
||||
[CONFIG] log_config.sim_log_level set to default value "info"
|
||||
[CONFIG] log_config.ocg_log_level set to default value "info"
|
||||
[CONFIG] log_config.omg_log_level set to default value "info"
|
||||
[CONFIG] log_config.opt_log_level set to default value "info"
|
||||
[CONFIG] log_config.otg_log_level set to default value "info"
|
||||
[CONFIG] log_config.otg_latency_log_level set to default value "info"
|
||||
[CONFIG] log_config.otg_latency_bg_log_level set to default value "info"
|
||||
[CONFIG] log_config.otg_gp_log_level set to default value "info"
|
||||
[CONFIG] log_config.otg_gp_bg_log_level set to default value "info"
|
||||
[CONFIG] log_config.otg_jitter_log_level set to default value "info"
|
||||
[LIBCONFIG] log_config.rlc_log_level: "info"
|
||||
[LIBCONFIG] log_config.pdcp_log_level: "info"
|
||||
[LIBCONFIG] log_config.rrc_log_level: "info"
|
||||
[CONFIG] log_config.nas_log_level set to default value "info"
|
||||
[CONFIG] log_config.perf_log_level set to default value "info"
|
||||
[CONFIG] log_config.oip_log_level set to default value "info"
|
||||
[CONFIG] log_config.cli_log_level set to default value "info"
|
||||
[CONFIG] log_config.msc_log_level set to default value "info"
|
||||
[CONFIG] log_config.ocm_log_level set to default value "info"
|
||||
[CONFIG] log_config.udp_log_level set to default value "info"
|
||||
[CONFIG] log_config.gtpv1u_log_level set to default value "info"
|
||||
[CONFIG] log_config.comp23?_log_level set to default value "info"
|
||||
[CONFIG] log_config.s1ap_log_level set to default value "info"
|
||||
[CONFIG] log_config.sctp_log_level set to default value "info"
|
||||
[LIBCONFIG] log_config.hw_log_level: "info"
|
||||
[CONFIG] log_config.osa_log_level set to default value "info"
|
||||
[CONFIG] log_config.eral_log_level set to default value "info"
|
||||
[CONFIG] log_config.mral_log_level set to default value "info"
|
||||
[CONFIG] log_config.enb_app_log_level set to default value "info"
|
||||
[CONFIG] log_config.flexran_agent_log_level set to default value "info"
|
||||
[CONFIG] log_config.tmr_log_level set to default value "info"
|
||||
[CONFIG] log_config.usim_log_level set to default value "info"
|
||||
[CONFIG] log_config.localize_log_level set to default value "info"
|
||||
[CONFIG] log_config.x2ap_log_level set to default value "info"
|
||||
[CONFIG] log_config.loader_log_level set to default value "info"
|
||||
[CONFIG] log_config.asn_log_level set to default value "info"
|
||||
[LIBCONFIG] log_config: 38/38 parameters successfully set, (32 to default value)
|
||||
[CONFIG] log_config 0 options set from command line
|
||||
[CONFIG] phy_log_infile: 0
|
||||
[CONFIG] log_config.phy_log_infile set to default value
|
||||
[CONFIG] mac_log_infile: 0
|
||||
[CONFIG] log_config.mac_log_infile set to default value
|
||||
[CONFIG] sim_log_infile: 0
|
||||
[CONFIG] log_config.sim_log_infile set to default value
|
||||
[CONFIG] ocg_log_infile: 0
|
||||
[CONFIG] log_config.ocg_log_infile set to default value
|
||||
[CONFIG] omg_log_infile: 0
|
||||
[CONFIG] log_config.omg_log_infile set to default value
|
||||
[CONFIG] opt_log_infile: 0
|
||||
[CONFIG] log_config.opt_log_infile set to default value
|
||||
[CONFIG] otg_log_infile: 0
|
||||
[CONFIG] log_config.otg_log_infile set to default value
|
||||
[CONFIG] otg_latency_log_infile: 0
|
||||
[CONFIG] log_config.otg_latency_log_infile set to default value
|
||||
[CONFIG] otg_latency_bg_log_infile: 0
|
||||
[CONFIG] log_config.otg_latency_bg_log_infile set to default value
|
||||
[CONFIG] otg_gp_log_infile: 0
|
||||
[CONFIG] log_config.otg_gp_log_infile set to default value
|
||||
[CONFIG] otg_gp_bg_log_infile: 0
|
||||
[CONFIG] log_config.otg_gp_bg_log_infile set to default value
|
||||
[CONFIG] otg_jitter_log_infile: 0
|
||||
[CONFIG] log_config.otg_jitter_log_infile set to default value
|
||||
[CONFIG] rlc_log_infile: 0
|
||||
[CONFIG] log_config.rlc_log_infile set to default value
|
||||
[CONFIG] pdcp_log_infile: 0
|
||||
[CONFIG] log_config.pdcp_log_infile set to default value
|
||||
[CONFIG] rrc_log_infile: 0
|
||||
[CONFIG] log_config.rrc_log_infile set to default value
|
||||
[CONFIG] nas_log_infile: 0
|
||||
[CONFIG] log_config.nas_log_infile set to default value
|
||||
[CONFIG] perf_log_infile: 0
|
||||
[CONFIG] log_config.perf_log_infile set to default value
|
||||
[CONFIG] oip_log_infile: 0
|
||||
[CONFIG] log_config.oip_log_infile set to default value
|
||||
[CONFIG] cli_log_infile: 0
|
||||
[CONFIG] log_config.cli_log_infile set to default value
|
||||
[CONFIG] msc_log_infile: 0
|
||||
[CONFIG] log_config.msc_log_infile set to default value
|
||||
[CONFIG] ocm_log_infile: 0
|
||||
[CONFIG] log_config.ocm_log_infile set to default value
|
||||
[CONFIG] udp_log_infile: 0
|
||||
[CONFIG] log_config.udp_log_infile set to default value
|
||||
[CONFIG] gtpv1u_log_infile: 0
|
||||
[CONFIG] log_config.gtpv1u_log_infile set to default value
|
||||
[CONFIG] comp23?_log_infile: 0
|
||||
[CONFIG] log_config.comp23?_log_infile set to default value
|
||||
[CONFIG] s1ap_log_infile: 0
|
||||
[CONFIG] log_config.s1ap_log_infile set to default value
|
||||
[CONFIG] sctp_log_infile: 0
|
||||
[CONFIG] log_config.sctp_log_infile set to default value
|
||||
[CONFIG] hw_log_infile: 0
|
||||
[CONFIG] log_config.hw_log_infile set to default value
|
||||
[CONFIG] osa_log_infile: 0
|
||||
[CONFIG] log_config.osa_log_infile set to default value
|
||||
[CONFIG] eral_log_infile: 0
|
||||
[CONFIG] log_config.eral_log_infile set to default value
|
||||
[CONFIG] mral_log_infile: 0
|
||||
[CONFIG] log_config.mral_log_infile set to default value
|
||||
[CONFIG] enb_app_log_infile: 0
|
||||
[CONFIG] log_config.enb_app_log_infile set to default value
|
||||
[CONFIG] flexran_agent_log_infile: 0
|
||||
[CONFIG] log_config.flexran_agent_log_infile set to default value
|
||||
[CONFIG] tmr_log_infile: 0
|
||||
[CONFIG] log_config.tmr_log_infile set to default value
|
||||
[CONFIG] usim_log_infile: 0
|
||||
[CONFIG] log_config.usim_log_infile set to default value
|
||||
[CONFIG] localize_log_infile: 0
|
||||
[CONFIG] log_config.localize_log_infile set to default value
|
||||
[CONFIG] x2ap_log_infile: 0
|
||||
[CONFIG] log_config.x2ap_log_infile set to default value
|
||||
[CONFIG] loader_log_infile: 0
|
||||
[CONFIG] log_config.loader_log_infile set to default value
|
||||
[CONFIG] asn_log_infile: 0
|
||||
[CONFIG] log_config.asn_log_infile set to default value
|
||||
[LIBCONFIG] log_config: 38/38 parameters successfully set, (38 to default value)
|
||||
[CONFIG] log_config 0 options set from command line
|
||||
[CONFIG] PRACH_debug: 0
|
||||
[CONFIG] log_config.PRACH_debug set to default value
|
||||
[CONFIG] RU_debug: 0
|
||||
[CONFIG] log_config.RU_debug set to default value
|
||||
[CONFIG] UE_PHYPROC_debug: 0
|
||||
[CONFIG] log_config.UE_PHYPROC_debug set to default value
|
||||
[CONFIG] LTEESTIM_debug: 0
|
||||
[CONFIG] log_config.LTEESTIM_debug set to default value
|
||||
[CONFIG] DLCELLSPEC_debug: 0
|
||||
[CONFIG] log_config.DLCELLSPEC_debug set to default value
|
||||
[CONFIG] ULSCH_debug: 0
|
||||
[CONFIG] log_config.ULSCH_debug set to default value
|
||||
[CONFIG] RRC_debug: 0
|
||||
[CONFIG] log_config.RRC_debug set to default value
|
||||
[CONFIG] PDCP_debug: 0
|
||||
[CONFIG] log_config.PDCP_debug set to default value
|
||||
[CONFIG] DFT_debug: 0
|
||||
[CONFIG] log_config.DFT_debug set to default value
|
||||
[CONFIG] ASN1_debug: 0
|
||||
[CONFIG] log_config.ASN1_debug set to default value
|
||||
[CONFIG] CTRLSOCKET_debug: 0
|
||||
[CONFIG] log_config.CTRLSOCKET_debug set to default value
|
||||
[CONFIG] SECURITY_debug: 0
|
||||
[CONFIG] log_config.SECURITY_debug set to default value
|
||||
[CONFIG] NAS_debug: 0
|
||||
[CONFIG] log_config.NAS_debug set to default value
|
||||
[CONFIG] RLC_debug: 0
|
||||
[CONFIG] log_config.RLC_debug set to default value
|
||||
[CONFIG] UE_TIMING_debug: 0
|
||||
[CONFIG] log_config.UE_TIMING_debug set to default value
|
||||
[LIBCONFIG] log_config: 15/15 parameters successfully set, (15 to default value)
|
||||
[CONFIG] log_config 0 options set from command line
|
||||
[CONFIG] PRACH_dump: 0
|
||||
[CONFIG] log_config.PRACH_dump set to default value
|
||||
[CONFIG] RU_dump: 0
|
||||
[CONFIG] log_config.RU_dump set to default value
|
||||
[CONFIG] UE_PHYPROC_dump: 0
|
||||
[CONFIG] log_config.UE_PHYPROC_dump set to default value
|
||||
[CONFIG] LTEESTIM_dump: 0
|
||||
[CONFIG] log_config.LTEESTIM_dump set to default value
|
||||
[CONFIG] DLCELLSPEC_dump: 0
|
||||
[CONFIG] log_config.DLCELLSPEC_dump set to default value
|
||||
[CONFIG] ULSCH_dump: 0
|
||||
[CONFIG] log_config.ULSCH_dump set to default value
|
||||
[CONFIG] RRC_dump: 0
|
||||
[CONFIG] log_config.RRC_dump set to default value
|
||||
[CONFIG] PDCP_dump: 0
|
||||
[CONFIG] log_config.PDCP_dump set to default value
|
||||
[CONFIG] DFT_dump: 0
|
||||
[CONFIG] log_config.DFT_dump set to default value
|
||||
[CONFIG] ASN1_dump: 0
|
||||
[CONFIG] log_config.ASN1_dump set to default value
|
||||
[CONFIG] CTRLSOCKET_dump: 0
|
||||
[CONFIG] log_config.CTRLSOCKET_dump set to default value
|
||||
[CONFIG] SECURITY_dump: 0
|
||||
[CONFIG] log_config.SECURITY_dump set to default value
|
||||
[CONFIG] NAS_dump: 0
|
||||
[CONFIG] log_config.NAS_dump set to default value
|
||||
[CONFIG] RLC_dump: 0
|
||||
[CONFIG] log_config.RLC_dump set to default value
|
||||
[CONFIG] UE_TIMING_dump: 0
|
||||
[CONFIG] log_config.UE_TIMING_dump set to default value
|
||||
[LIBCONFIG] log_config: 15/15 parameters successfully set, (15 to default value)
|
||||
[CONFIG] log_config 0 options set from command line
|
||||
log init done
|
||||
|
||||
```
|
||||
It can also be retrieved when using the telnet server, as explained [below](### Using the telnet server to configure the logging facility)
|
||||
|
||||
### parameters to activate conditional code
|
||||
| name | type | default | description |
|
||||
|:---:|:---:|:---:|:----|
|
||||
| `<flag>_debug` | `boolean` | 0 = false | Triggers the activation of conditional code identified by the specified flag.
|
||||
| `<flag>_dump` | `boolean` | 0 = false| Triggers buffer dump, on the console in text form or in a file in matlab format, depending on the developper choice and forcasted usage|
|
||||
|
||||
### Using the configuration file to configure the logging facility
|
||||
The following example sets all components log level to info, exept for hw,phy,mac,rlc,pdcp,rrc which log levels are set to error or warning.
|
||||
```bash
|
||||
log_config :
|
||||
{
|
||||
global_log_level ="info";
|
||||
hw_log_level ="error";
|
||||
phy_log_level ="error";
|
||||
mac_log_level ="warn";
|
||||
rlc_log_level ="error"
|
||||
pdcp_log_level ="error";
|
||||
rrc_log_level ="error";
|
||||
};
|
||||
```
|
||||
### Using the command line to configure the logging facility
|
||||
Command line parameter values supersedes values specified in the configuration file.
|
||||
```bash
|
||||
./lte-softmodem -O --log_config.global_log_options nocolor,level,thread --log_config.prach_log_level debug --log_config.PRACH_debug
|
||||
```
|
||||
In this example to get all the debug PRACH messages it is necessary to also set the PRACH_debug flag. This is a choice from the developper.
|
||||
The log messages will be printed whithout color and the header will include the lmessage evel and the thread name:
|
||||
```bash
|
||||
[PHY]I ru thread Time in secs now: 104652566
|
||||
[PHY]I ru thread Time in secs last pps: 91827117
|
||||
[PHY]I ru thread RU 0 rf device ready
|
||||
[PHY]I ru thread RU 0 no asynch_south interface
|
||||
[MAC]E rxtx processing SCHED_MODE=0
|
||||
[PHY]I lte-softmodem PRACH (eNB) : running rx_prach for subframe 1, prach_FreqOffset 2, prach_ConfigIndex 0 , rootSequenceIndex 0
|
||||
[PHY]I lte-softmodem prach_I0 = 0.0 dB
|
||||
[PHY]I rxtx processing max_I0 21, min_I0 0
|
||||
[PHY]I lte-softmodem PRACH (eNB) : running rx_prach for subframe 1, prach_FreqOffset 2, prach_ConfigIndex 0 , rootSequenceIndex 0
|
||||
[PHY]I lte-softmodem PRACH (eNB) : running rx_prach for subframe 1, prach_FreqOffset 2, prach_ConfigIndex 0 , rootSequenceIndex 0
|
||||
```
|
||||
|
||||
### Using the telnet server to configure the logging facility
|
||||
The telnet server includes a `log` command which can be used to dymically modify the logging facility configuration parameters.
|
||||
[telnet server ***softmodem log*** commands](../../telnetsrv/DOC/telnetlog.md)
|
||||
|
||||
[logging facility main page](log.md)
|
||||
[oai Wikis home](https://gitlab.eurecom.fr/oai/openairinterface5g/wikis/home)
|
||||
+103
-33
@@ -39,19 +39,13 @@
|
||||
#include "vcd_signal_dumper.h"
|
||||
#include "assertions.h"
|
||||
|
||||
#if defined(ENABLE_ITTI)
|
||||
#include "intertask_interface.h"
|
||||
#endif
|
||||
|
||||
# include <pthread.h>
|
||||
# include <string.h>
|
||||
#include <linux/prctl.h>
|
||||
#include <pthread.h>
|
||||
#include <string.h>
|
||||
#include <linux/prctl.h>
|
||||
#include "common/config/config_userapi.h"
|
||||
// main log variables
|
||||
|
||||
|
||||
|
||||
|
||||
mapping log_level_names[] = {
|
||||
{"error", OAILOG_ERR},
|
||||
{"warn", OAILOG_WARNING},
|
||||
@@ -75,7 +69,13 @@ char *log_level_highlight_start[] = {LOG_RED, LOG_ORANGE, "", LOG_BLUE, LOG_CYBL
|
||||
char *log_level_highlight_end[] = {LOG_RESET,LOG_RESET,LOG_RESET, LOG_RESET,LOG_RESET}; /*!< \brief Optional end-format strings for highlighting */
|
||||
|
||||
|
||||
int write_file_matlab(const char *fname,const char *vname,void *data,int length,int dec,char format) {
|
||||
int write_file_matlab(const char *fname,
|
||||
const char *vname,
|
||||
void *data,
|
||||
int length,
|
||||
int dec,
|
||||
char format)
|
||||
{
|
||||
FILE *fp=NULL;
|
||||
int i;
|
||||
|
||||
@@ -215,7 +215,8 @@ int write_file_matlab(const char *fname,const char *vname,void *data,int length,
|
||||
}
|
||||
|
||||
/* get log parameters from configuration file */
|
||||
void log_getconfig(log_t *g_log) {
|
||||
void log_getconfig(log_t *g_log)
|
||||
{
|
||||
char *gloglevel = NULL;
|
||||
int consolelog ;
|
||||
paramdef_t logparams_defaults[] = LOG_GLOBALPARAMS_DESC;
|
||||
@@ -309,6 +310,7 @@ void log_getconfig(log_t *g_log) {
|
||||
|
||||
config_get( logparams_debug,(sizeof(log_maskmap)/sizeof(mapping)) - 1,CONFIG_STRING_LOG_PREFIX);
|
||||
config_get( logparams_dump,(sizeof(log_maskmap)/sizeof(mapping)) - 1,CONFIG_STRING_LOG_PREFIX);
|
||||
config_check_unknown_cmdlineopt(CONFIG_STRING_LOG_PREFIX);
|
||||
|
||||
/* set the debug mask according to the debug parameters values */
|
||||
for (int i=0; log_maskmap[i].name != NULL ; i++) {
|
||||
@@ -323,7 +325,10 @@ void log_getconfig(log_t *g_log) {
|
||||
set_glog_onlinelog(consolelog);
|
||||
}
|
||||
|
||||
int register_log_component(char *name, char *fext, int compidx) {
|
||||
int register_log_component(char *name,
|
||||
char *fext,
|
||||
int compidx)
|
||||
{
|
||||
int computed_compidx=compidx;
|
||||
|
||||
if (strlen(fext) > 3) {
|
||||
@@ -346,13 +351,25 @@ int register_log_component(char *name, char *fext, int compidx) {
|
||||
g_log->log_component[computed_compidx].filelog_name = malloc(strlen(name)+16);/* /tmp/<name>.%s */
|
||||
sprintf(g_log->log_component[computed_compidx].filelog_name,"/tmp/%s.%s",name,fext);
|
||||
} else {
|
||||
fprintf(stderr,"{LOG} %s %d Couldn't register componemt %s\n",__FILE__,__LINE__,name);
|
||||
fprintf(stderr,"{LOG} %s %d Couldn't register component %s\n",__FILE__,__LINE__,name);
|
||||
}
|
||||
|
||||
return computed_compidx;
|
||||
}
|
||||
|
||||
int logInit (void) {
|
||||
int isLogInitDone (void)
|
||||
{
|
||||
if (g_log == NULL)
|
||||
return 0;
|
||||
|
||||
if (!(g_log->flag & FLAG_INITIALIZED))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int logInit (void)
|
||||
{
|
||||
int i;
|
||||
g_log = calloc(1, sizeof(log_t));
|
||||
|
||||
@@ -378,7 +395,6 @@ int logInit (void) {
|
||||
register_log_component("OCG","",OCG);
|
||||
register_log_component("PERF","",PERF);
|
||||
register_log_component("OIP","",OIP);
|
||||
register_log_component("CLI","",CLI);
|
||||
register_log_component("MSC","log",MSC);
|
||||
register_log_component("OCM","log",OCM);
|
||||
register_log_component("HW","",HW);
|
||||
@@ -387,6 +403,7 @@ int logInit (void) {
|
||||
register_log_component("mRAL","",RAL_UE);
|
||||
register_log_component("ENB_APP","log",ENB_APP);
|
||||
register_log_component("FLEXRAN_AGENT","log",FLEXRAN_AGENT);
|
||||
register_log_component("PROTO_AGENT","log",PROTO_AGENT);
|
||||
register_log_component("TMR","",TMR);
|
||||
register_log_component("USIM","txt",USIM);
|
||||
register_log_component("SIM","txt",SIM);
|
||||
@@ -396,11 +413,13 @@ int logInit (void) {
|
||||
register_log_component("UDP","",UDP_);
|
||||
register_log_component("GTPV1U","",GTPU);
|
||||
register_log_component("S1AP","",S1AP);
|
||||
register_log_component("X2AP","",X2AP);
|
||||
register_log_component("F1AP","",F1AP);
|
||||
register_log_component("SCTP","",SCTP);
|
||||
register_log_component("X2AP","",X2AP);
|
||||
register_log_component("LOADER","log",LOADER);
|
||||
register_log_component("ASN","log",ASN);
|
||||
register_log_component("NFAPI_VNF","log",NFAPI_VNF);
|
||||
register_log_component("NFAPI_PNF","log",NFAPI_PNF);
|
||||
|
||||
for (int i=0 ; log_level_names[i].name != NULL ; i++)
|
||||
g_log->level2string[i] = toupper(log_level_names[i].name[0]); // uppercased first letter of level name
|
||||
@@ -413,12 +432,15 @@ int logInit (void) {
|
||||
memset(&(g_log->log_component[i]),0,sizeof(log_component_t));
|
||||
}
|
||||
|
||||
g_log->flag = g_log->flag | FLAG_INITIALIZED;
|
||||
printf("log init done\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
char *log_getthreadname(char *threadname, int bufsize) {
|
||||
char *log_getthreadname(char *threadname,
|
||||
int bufsize)
|
||||
{
|
||||
int rt = pthread_getname_np(pthread_self(), threadname,bufsize) ;
|
||||
|
||||
if (rt == 0) {
|
||||
@@ -428,7 +450,12 @@ char *log_getthreadname(char *threadname, int bufsize) {
|
||||
}
|
||||
}
|
||||
|
||||
static int log_header(char *log_buffer, int buffsize, int comp, int level,const char *format) {
|
||||
static int log_header(char *log_buffer,
|
||||
int buffsize,
|
||||
int comp,
|
||||
int level,
|
||||
const char *format)
|
||||
{
|
||||
char threadname[PR_SET_NAME];
|
||||
return snprintf(log_buffer, buffsize, "%s%s[%s]%c %s %s%s",
|
||||
log_level_highlight_end[level],
|
||||
@@ -440,7 +467,14 @@ static int log_header(char *log_buffer, int buffsize, int comp, int level,const
|
||||
log_level_highlight_end[level]);
|
||||
}
|
||||
|
||||
void logRecord_mt(const char *file, const char *func, int line, int comp, int level, const char *format, ... ) {
|
||||
void logRecord_mt(const char *file,
|
||||
const char *func,
|
||||
int line,
|
||||
int comp,
|
||||
int level,
|
||||
const char *format,
|
||||
... )
|
||||
{
|
||||
char log_buffer[MAX_LOG_TOTAL]= {0};
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
@@ -450,7 +484,26 @@ void logRecord_mt(const char *file, const char *func, int line, int comp, int le
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void log_dump(int component, void *buffer, int buffsize,int datatype, const char *format, ... ) {
|
||||
void vlogRecord_mt(const char *file,
|
||||
const char *func,
|
||||
int line,
|
||||
int comp,
|
||||
int level,
|
||||
const char *format,
|
||||
va_list args )
|
||||
{
|
||||
char log_buffer[MAX_LOG_TOTAL];
|
||||
log_header(log_buffer,MAX_LOG_TOTAL,comp, level,format);
|
||||
g_log->log_component[comp].vprint(g_log->log_component[comp].stream,log_buffer, args);
|
||||
}
|
||||
|
||||
void log_dump(int component,
|
||||
void *buffer,
|
||||
int buffsize,
|
||||
int datatype,
|
||||
const char *format,
|
||||
... )
|
||||
{
|
||||
va_list args;
|
||||
char *wbuf;
|
||||
|
||||
@@ -491,7 +544,9 @@ void log_dump(int component, void *buffer, int buffsize,int datatype, const char
|
||||
}
|
||||
}
|
||||
|
||||
int set_log(int component, int level) {
|
||||
int set_log(int component,
|
||||
int level)
|
||||
{
|
||||
/* Checking parameters */
|
||||
DevCheck((component >= MIN_LOG_COMPONENTS) && (component < MAX_LOG_COMPONENTS),
|
||||
component, MIN_LOG_COMPONENTS, MAX_LOG_COMPONENTS);
|
||||
@@ -507,13 +562,15 @@ int set_log(int component, int level) {
|
||||
|
||||
|
||||
|
||||
void set_glog(int level) {
|
||||
void set_glog(int level)
|
||||
{
|
||||
for (int c=0; c< MAX_LOG_COMPONENTS; c++ ) {
|
||||
set_log(c, level);
|
||||
}
|
||||
}
|
||||
|
||||
void set_glog_onlinelog(int enable) {
|
||||
void set_glog_onlinelog(int enable)
|
||||
{
|
||||
for (int c=0; c< MAX_LOG_COMPONENTS; c++ ) {
|
||||
if ( enable ) {
|
||||
g_log->log_component[c].level = g_log->log_component[c].savedlevel;
|
||||
@@ -525,7 +582,8 @@ void set_glog_onlinelog(int enable) {
|
||||
}
|
||||
}
|
||||
}
|
||||
void set_glog_filelog(int enable) {
|
||||
void set_glog_filelog(int enable)
|
||||
{
|
||||
static FILE *fptr;
|
||||
|
||||
if ( enable ) {
|
||||
@@ -549,7 +607,8 @@ void set_glog_filelog(int enable) {
|
||||
}
|
||||
}
|
||||
|
||||
void set_component_filelog(int comp) {
|
||||
void set_component_filelog(int comp)
|
||||
{
|
||||
if (g_log->log_component[comp].stream == NULL || g_log->log_component[comp].stream == stdout) {
|
||||
g_log->log_component[comp].stream = fopen(g_log->log_component[comp].filelog_name,"w");
|
||||
}
|
||||
@@ -558,7 +617,8 @@ void set_component_filelog(int comp) {
|
||||
g_log->log_component[comp].print = fprintf;
|
||||
g_log->log_component[comp].filelog = 1;
|
||||
}
|
||||
void close_component_filelog(int comp) {
|
||||
void close_component_filelog(int comp)
|
||||
{
|
||||
g_log->log_component[comp].filelog = 0;
|
||||
|
||||
if (g_log->log_component[comp].stream != NULL && g_log->log_component[comp].stream != stdout ) {
|
||||
@@ -575,7 +635,9 @@ void close_component_filelog(int comp) {
|
||||
* with string value NULL
|
||||
*/
|
||||
/* map a string to an int. Takes a mapping array and a string as arg */
|
||||
int map_str_to_int(mapping *map, const char *str) {
|
||||
int map_str_to_int(mapping *map,
|
||||
const char *str)
|
||||
{
|
||||
while (1) {
|
||||
if (map->name == NULL) {
|
||||
return(-1);
|
||||
@@ -590,7 +652,9 @@ int map_str_to_int(mapping *map, const char *str) {
|
||||
}
|
||||
|
||||
/* map an int to a string. Takes a mapping array and a value */
|
||||
char *map_int_to_str(mapping *map, int val) {
|
||||
char *map_int_to_str(mapping *map,
|
||||
int val)
|
||||
{
|
||||
while (1) {
|
||||
if (map->name == NULL) {
|
||||
return NULL;
|
||||
@@ -604,7 +668,9 @@ char *map_int_to_str(mapping *map, int val) {
|
||||
}
|
||||
}
|
||||
|
||||
int is_newline( char *str, int size) {
|
||||
int is_newline(char *str,
|
||||
int size)
|
||||
{
|
||||
int i;
|
||||
|
||||
for ( i = 0; i < size; i++ ) {
|
||||
@@ -617,12 +683,16 @@ int is_newline( char *str, int size) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void logClean (void) {
|
||||
void logClean (void)
|
||||
{
|
||||
int i;
|
||||
LOG_UI(PHY,"\n");
|
||||
|
||||
for (i=MIN_LOG_COMPONENTS; i < MAX_LOG_COMPONENTS; i++) {
|
||||
close_component_filelog(i);
|
||||
if(isLogInitDone()) {
|
||||
LOG_UI(PHY,"\n");
|
||||
|
||||
for (i=MIN_LOG_COMPONENTS; i < MAX_LOG_COMPONENTS; i++) {
|
||||
close_component_filelog(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+40
-23
@@ -116,12 +116,11 @@ extern "C" {
|
||||
* @{*/
|
||||
|
||||
|
||||
#define FLAG_NOCOLOR 0x0001 /*!< \brief use colors in log messages, depending on level */
|
||||
#define FLAG_THREAD 0x0008 /*!< \brief display thread name in log messages */
|
||||
#define FLAG_LEVEL 0x0010 /*!< \brief display log level in log messages */
|
||||
#define FLAG_FUNCT 0x0020
|
||||
#define FLAG_FILE_LINE 0x0040
|
||||
#define FLAG_TIME 0x0100
|
||||
#define FLAG_NOCOLOR 0x0001 /*!< \brief use colors in log messages, depending on level */
|
||||
#define FLAG_THREAD 0x0008 /*!< \brief display thread name in log messages */
|
||||
#define FLAG_LEVEL 0x0010 /*!< \brief display log level in log messages */
|
||||
#define FLAG_TIME 0x0100
|
||||
#define FLAG_INITIALIZED 0x8000
|
||||
|
||||
#define SET_LOG_OPTION(O) g_log->flag = (g_log->flag | O)
|
||||
#define CLEAR_LOG_OPTION(O) g_log->flag = (g_log->flag & (~O))
|
||||
@@ -147,6 +146,7 @@ extern "C" {
|
||||
#define DEBUG_CTRLSOCKET (1<<10)
|
||||
#define DEBUG_SECURITY (1<<11)
|
||||
#define DEBUG_NAS (1<<12)
|
||||
#define DEBUG_RLC (1<<13)
|
||||
#define UE_TIMING (1<<20)
|
||||
|
||||
|
||||
@@ -164,6 +164,7 @@ extern "C" {
|
||||
{"CTRLSOCKET", DEBUG_CTRLSOCKET},\
|
||||
{"SECURITY", DEBUG_SECURITY},\
|
||||
{"NAS", DEBUG_NAS},\
|
||||
{"RLC", DEBUG_RLC},\
|
||||
{"UE_TIMING", UE_TIMING},\
|
||||
{NULL,-1}\
|
||||
}
|
||||
@@ -182,7 +183,6 @@ typedef enum {
|
||||
MIN_LOG_COMPONENTS = 0,
|
||||
PHY = MIN_LOG_COMPONENTS,
|
||||
MAC,
|
||||
EMU,
|
||||
SIM,
|
||||
OCG,
|
||||
OMG,
|
||||
@@ -199,13 +199,13 @@ typedef enum {
|
||||
NAS,
|
||||
PERF,
|
||||
OIP,
|
||||
CLI,
|
||||
MSC,
|
||||
OCM,
|
||||
UDP_,
|
||||
GTPU,
|
||||
SPGW,
|
||||
S1AP,
|
||||
F1AP,
|
||||
SCTP,
|
||||
HW,
|
||||
OSA,
|
||||
@@ -216,13 +216,13 @@ typedef enum {
|
||||
TMR,
|
||||
USIM,
|
||||
LOCALIZE,
|
||||
PROTO_AGENT,
|
||||
F1U,
|
||||
X2AP,
|
||||
GNB_APP,
|
||||
NR_RRC,
|
||||
NR_MAC,
|
||||
NR_PHY,
|
||||
LOADER,
|
||||
ASN,
|
||||
NFAPI_VNF,
|
||||
NFAPI_PNF,
|
||||
MAX_LOG_PREDEF_COMPONENTS,
|
||||
}
|
||||
comp_name_t;
|
||||
@@ -289,7 +289,9 @@ extern "C" {
|
||||
# include "log_if.h"
|
||||
/*----------------------------------------------------------------------------*/
|
||||
int logInit (void);
|
||||
int isLogInitDone (void);
|
||||
void logRecord_mt(const char *file, const char *func, int line,int comp, int level, const char *format, ...) __attribute__ ((format (printf, 6, 7)));
|
||||
void vlogRecord_mt(const char *file, const char *func, int line, int comp, int level, const char *format, va_list args );
|
||||
void log_dump(int component, void *buffer, int buffsize,int datatype, const char *format, ... );
|
||||
int set_log(int component, int level);
|
||||
void set_glog(int level);
|
||||
@@ -351,6 +353,8 @@ int32_t write_file_matlab(const char *fname, const char *vname, void *data, int
|
||||
}
|
||||
|
||||
#define LOG_OPTIONS_IDX 2
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------------*/
|
||||
/** @defgroup _debugging debugging macros
|
||||
* @ingroup _macro
|
||||
@@ -367,9 +371,9 @@ int32_t write_file_matlab(const char *fname, const char *vname, void *data, int
|
||||
# define LOG_I(c, x...) do { if (T_stdout) { if( g_log->log_component[c].level >= OAILOG_INFO ) logRecord_mt(__FILE__, __FUNCTION__, __LINE__,c, OAILOG_INFO, x) ;} else { T(T_LEGACY_ ## c ## _INFO, T_PRINTF(x)) ;}} while (0)
|
||||
# define LOG_D(c, x...) do { if (T_stdout) { if( g_log->log_component[c].level >= OAILOG_DEBUG ) logRecord_mt(__FILE__, __FUNCTION__, __LINE__,c, OAILOG_DEBUG, x) ;} else { T(T_LEGACY_ ## c ## _DEBUG, T_PRINTF(x)) ;}} while (0)
|
||||
# define LOG_T(c, x...) do { if (T_stdout) { if( g_log->log_component[c].level >= OAILOG_TRACE ) logRecord_mt(__FILE__, __FUNCTION__, __LINE__,c, OAILOG_TRACE, x) ;} else { T(T_LEGACY_ ## c ## _TRACE, T_PRINTF(x)) ;}} while (0)
|
||||
# define VLOG(c,l, f, args) do { if (T_stdout) { if( g_log->log_component[c].level >= l ) vlogRecord_mt(__FILE__, __FUNCTION__, __LINE__,c, l, f, args) ;} } while (0)
|
||||
/* macro used to dump a buffer or a message as in openair2/RRC/LTE/RRC_eNB.c, replaces LOG_F macro */
|
||||
# define LOG_DUMPMSG(c, f, b, s, x...) do { if(g_log->dump_mask & f) log_dump(c, b, s, LOG_DUMP_CHAR, x) ;} while (0) /* */
|
||||
# define nfapi_log(FILE, FNC, LN, COMP, LVL, F...) do { if (T_stdout) { logRecord_mt(__FILE__, __FUNCTION__, __LINE__,COMP, LVL, F) ;}} while (0) /* */
|
||||
/* bitmask dependant macros, to isolate debugging code */
|
||||
# define LOG_DEBUGFLAG(D) (g_log->debug_mask & D)
|
||||
|
||||
@@ -426,9 +430,12 @@ static __inline__ uint64_t rdtsc(void) {
|
||||
|
||||
extern double cpuf;
|
||||
|
||||
static inline uint64_t checkTCPU(int timeout, char *file, int line) {
|
||||
static __thread uint64_t lastCPUTime=0;
|
||||
static __thread uint64_t last=0;
|
||||
static inline uint64_t checkTCPU(int timeout,
|
||||
char *file,
|
||||
int line)
|
||||
{
|
||||
static uint64_t __thread lastCPUTime=0;
|
||||
static uint64_t __thread last=0;
|
||||
uint64_t cur=rdtsc();
|
||||
struct timespec CPUt;
|
||||
clock_gettime(CLOCK_THREAD_CPUTIME_ID, &CPUt);
|
||||
@@ -448,8 +455,11 @@ static inline uint64_t checkTCPU(int timeout, char *file, int line) {
|
||||
return cur;
|
||||
}
|
||||
|
||||
static inline unsigned long long checkT(int timeout, char *file, int line) {
|
||||
static __thread unsigned long long last=0;
|
||||
static inline unsigned long long checkT(int timeout,
|
||||
char *file,
|
||||
int line)
|
||||
{
|
||||
static unsigned long long __thread last=0;
|
||||
unsigned long long cur=rdtsc();
|
||||
int microCycles=(int)(cpuf*1000);
|
||||
int duration=(int)((cur-last)/microCycles);
|
||||
@@ -468,7 +478,10 @@ typedef struct m {
|
||||
uint64_t maxArray[11];
|
||||
} Meas;
|
||||
|
||||
static inline void printMeas(char *txt, Meas *M, int period) {
|
||||
static inline void printMeas(char *txt,
|
||||
Meas *M,
|
||||
int period)
|
||||
{
|
||||
if (M->iterations%period == 0 ) {
|
||||
char txt2[512];
|
||||
sprintf(txt2,"%s avg=%" PRIu64 " iterations=%" PRIu64 " max=%"
|
||||
@@ -486,13 +499,19 @@ static inline void printMeas(char *txt, Meas *M, int period) {
|
||||
}
|
||||
}
|
||||
|
||||
static inline int cmpint(const void *a, const void *b) {
|
||||
static inline int cmpint(const void *a,
|
||||
const void *b)
|
||||
{
|
||||
uint64_t *aa=(uint64_t *)a;
|
||||
uint64_t *bb=(uint64_t *)b;
|
||||
return (int)(*aa-*bb);
|
||||
}
|
||||
|
||||
static inline void updateTimes(uint64_t start, Meas *M, int period, char *txt) {
|
||||
static inline void updateTimes(uint64_t start,
|
||||
Meas *M,
|
||||
int period,
|
||||
char *txt)
|
||||
{
|
||||
if (start!=0) {
|
||||
uint64_t end=rdtsc();
|
||||
long long diff=(end-start)/(cpuf*1000);
|
||||
@@ -529,5 +548,3 @@ static inline void updateTimes(uint64_t start, Meas *M, int period, char *txt) {
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -190,7 +190,14 @@ const char* eurecomVariablesNames[] = {
|
||||
"enb_thread_rxtx_CPUID",
|
||||
"ru_thread_CPUID",
|
||||
"ru_thread_tx_CPUID",
|
||||
|
||||
"ue0_on_duration_timer",
|
||||
"ue0_drx_inactivity",
|
||||
"ue0_drx_short_cycle",
|
||||
"ue0_short_drx_cycle_number",
|
||||
"ue0_drx_long_cycle",
|
||||
"ue0_drx_retransmission_harq0",
|
||||
"ue0_drx_active_time",
|
||||
"ue0_drx_active_time_condition",
|
||||
/*signal for NR*/
|
||||
"frame_number_TX0_gNB",
|
||||
"frame_number_TX1_gNB",
|
||||
@@ -200,6 +207,7 @@ const char* eurecomVariablesNames[] = {
|
||||
"slot_number_TX1_gNB",
|
||||
"slot_number_RX0_gNB",
|
||||
"slot_number_RX1_gNB"
|
||||
|
||||
};
|
||||
|
||||
const char* eurecomFunctionsNames[] = {
|
||||
|
||||
@@ -167,7 +167,14 @@ typedef enum {
|
||||
VCD_SIGNAL_DUMPER_VARIABLES_CPUID_ENB_THREAD_RXTX,
|
||||
VCD_SIGNAL_DUMPER_VARIABLES_CPUID_RU_THREAD,
|
||||
VCD_SIGNAL_DUMPER_VARIABLES_CPUID_RU_THREAD_TX,
|
||||
|
||||
VCD_SIGNAL_DUMPER_VARIABLES_ON_DURATION_TIMER,
|
||||
VCD_SIGNAL_DUMPER_VARIABLES_DRX_INACTIVITY,
|
||||
VCD_SIGNAL_DUMPER_VARIABLES_DRX_SHORT_CYCLE,
|
||||
VCD_SIGNAL_DUMPER_VARIABLES_SHORT_DRX_CYCLE_NUMBER,
|
||||
VCD_SIGNAL_DUMPER_VARIABLES_DRX_LONG_CYCLE,
|
||||
VCD_SIGNAL_DUMPER_VARIABLES_DRX_RETRANSMISSION_HARQ0,
|
||||
VCD_SIGNAL_DUMPER_VARIABLES_DRX_ACTIVE_TIME,
|
||||
VCD_SIGNAL_DUMPER_VARIABLES_DRX_ACTIVE_TIME_CONDITION,
|
||||
/*signal for NR*/
|
||||
VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_GNB,
|
||||
VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX1_GNB,
|
||||
@@ -178,6 +185,7 @@ typedef enum {
|
||||
VCD_SIGNAL_DUMPER_VARIABLES_SLOT_NUMBER_RX0_GNB,
|
||||
VCD_SIGNAL_DUMPER_VARIABLES_SLOT_NUMBER_RX1_GNB,
|
||||
|
||||
|
||||
VCD_SIGNAL_DUMPER_VARIABLES_END
|
||||
} vcd_signal_dump_variables;
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ T_IDs.h: $(GENIDS) T_messages.txt
|
||||
./$(GENIDS) T_messages.txt T_IDs.h
|
||||
|
||||
check_vcd:
|
||||
gcc -Wall -I. -I.. -I../itti -Itracer -o _check_vcd check_vcd.c tracer/database.c tracer/utils.c -lm -pthread
|
||||
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)
|
||||
rm -f ./_check_vcd
|
||||
|
||||
|
||||
+98
-68
@@ -12,14 +12,16 @@
|
||||
#include "common/config/config_userapi.h"
|
||||
|
||||
#define QUIT(x) do { \
|
||||
printf("T tracer: QUIT: %s\n", x); \
|
||||
exit(1); \
|
||||
} while (0)
|
||||
printf("T tracer: QUIT: %s\n", x); \
|
||||
exit(1); \
|
||||
} while (0)
|
||||
|
||||
/* array used to activate/disactivate a log */
|
||||
static int T_IDs[T_NUMBER_OF_IDS];
|
||||
int *T_active = T_IDs;
|
||||
int T_stdout;
|
||||
|
||||
int T_stdout = 1;
|
||||
|
||||
|
||||
static int T_socket;
|
||||
|
||||
@@ -32,125 +34,159 @@ volatile int *T_freelist_head = &_T_freelist_head;
|
||||
T_cache_t *T_cache;
|
||||
|
||||
#if BASIC_SIMULATOR
|
||||
/* global variables used by T_GET_SLOT, see in T.h */
|
||||
volatile uint64_t T_next_id;
|
||||
volatile uint64_t T_active_id;
|
||||
/* global variables used by T_GET_SLOT, see in T.h */
|
||||
volatile uint64_t T_next_id;
|
||||
volatile uint64_t T_active_id;
|
||||
#endif
|
||||
|
||||
static void get_message(int s)
|
||||
{
|
||||
static void get_message(int s) {
|
||||
char t;
|
||||
int l;
|
||||
int id;
|
||||
int is_on;
|
||||
|
||||
if (read(s, &t, 1) != 1) QUIT("get_message fails");
|
||||
printf("T tracer: got mess %d\n", t);
|
||||
|
||||
printf("T tracer: got mess %d\n", t);
|
||||
|
||||
switch (t) {
|
||||
case 0:
|
||||
/* toggle all those IDs */
|
||||
/* optimze? (too much syscalls) */
|
||||
if (read(s, &l, sizeof(int)) != sizeof(int)) QUIT("get_message fails");
|
||||
while (l) {
|
||||
if (read(s, &id, sizeof(int)) != sizeof(int)) QUIT("get_message fails");
|
||||
T_IDs[id] = 1 - T_IDs[id];
|
||||
l--;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
/* set IDs as given */
|
||||
/* optimize? */
|
||||
if (read(s, &l, sizeof(int)) != sizeof(int)) QUIT("get_message fails");
|
||||
id = 0;
|
||||
while (l) {
|
||||
if (read(s, &is_on, sizeof(int)) != sizeof(int))
|
||||
QUIT("get_message fails");
|
||||
T_IDs[id] = is_on;
|
||||
id++;
|
||||
l--;
|
||||
}
|
||||
break;
|
||||
case 2: break; /* do nothing, this message is to wait for local tracer */
|
||||
case 0:
|
||||
|
||||
/* toggle all those IDs */
|
||||
/* optimze? (too much syscalls) */
|
||||
if (read(s, &l, sizeof(int)) != sizeof(int)) QUIT("get_message fails");
|
||||
|
||||
while (l) {
|
||||
if (read(s, &id, sizeof(int)) != sizeof(int)) QUIT("get_message fails");
|
||||
|
||||
T_IDs[id] = 1 - T_IDs[id];
|
||||
l--;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 1:
|
||||
|
||||
/* set IDs as given */
|
||||
/* optimize? */
|
||||
if (read(s, &l, sizeof(int)) != sizeof(int)) QUIT("get_message fails");
|
||||
|
||||
id = 0;
|
||||
|
||||
while (l) {
|
||||
if (read(s, &is_on, sizeof(int)) != sizeof(int))
|
||||
QUIT("get_message fails");
|
||||
|
||||
T_IDs[id] = is_on;
|
||||
id++;
|
||||
l--;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 2:
|
||||
break; /* do nothing, this message is to wait for local tracer */
|
||||
}
|
||||
}
|
||||
|
||||
static void *T_receive_thread(void *_)
|
||||
{
|
||||
static void *T_receive_thread(void *_) {
|
||||
while (1) get_message(T_socket);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void new_thread(void *(*f)(void *), void *data)
|
||||
{
|
||||
static void new_thread(void *(*f)(void *), void *data) {
|
||||
pthread_t t;
|
||||
pthread_attr_t att;
|
||||
|
||||
if (pthread_attr_init(&att))
|
||||
{ fprintf(stderr, "pthread_attr_init err\n"); exit(1); }
|
||||
if (pthread_attr_setdetachstate(&att, PTHREAD_CREATE_DETACHED))
|
||||
{ fprintf(stderr, "pthread_attr_setdetachstate err\n"); exit(1); }
|
||||
if (pthread_create(&t, &att, f, data))
|
||||
{ fprintf(stderr, "pthread_create err\n"); exit(1); }
|
||||
if (pthread_attr_destroy(&att))
|
||||
{ fprintf(stderr, "pthread_attr_destroy err\n"); exit(1); }
|
||||
if (pthread_attr_init(&att)) {
|
||||
fprintf(stderr, "pthread_attr_init err\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (pthread_attr_setdetachstate(&att, PTHREAD_CREATE_DETACHED)) {
|
||||
fprintf(stderr, "pthread_attr_setdetachstate err\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (pthread_create(&t, &att, f, data)) {
|
||||
fprintf(stderr, "pthread_create err\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (pthread_attr_destroy(&att)) {
|
||||
fprintf(stderr, "pthread_attr_destroy err\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* defined in local_tracer.c */
|
||||
void T_local_tracer_main(int remote_port, int wait_for_tracer,
|
||||
int local_socket, void *shm_array);
|
||||
int local_socket, void *shm_array);
|
||||
|
||||
/* We monitor the tracee and the local tracer processes.
|
||||
* When one dies we forcefully kill the other.
|
||||
*/
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
static void monitor_and_kill(int child1, int child2)
|
||||
{
|
||||
static void monitor_and_kill(int child1, int child2) {
|
||||
int child;
|
||||
int status;
|
||||
|
||||
child = wait(&status);
|
||||
|
||||
if (child == -1) perror("wait");
|
||||
|
||||
kill(child1, SIGKILL);
|
||||
kill(child2, SIGKILL);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void T_init(int remote_port, int wait_for_tracer, int dont_fork)
|
||||
{
|
||||
void T_init(int remote_port, int wait_for_tracer, int dont_fork) {
|
||||
int socket_pair[2];
|
||||
int s;
|
||||
int child1, child2;
|
||||
int i;
|
||||
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, socket_pair))
|
||||
{ perror("socketpair"); abort(); }
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, socket_pair)) {
|
||||
perror("socketpair");
|
||||
abort();
|
||||
}
|
||||
|
||||
/* setup shared memory */
|
||||
T_cache = mmap(NULL, T_CACHE_SIZE * sizeof(T_cache_t),
|
||||
PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
|
||||
if (T_cache == MAP_FAILED)
|
||||
{ perror("mmap"); abort(); }
|
||||
|
||||
if (T_cache == MAP_FAILED) {
|
||||
perror("mmap");
|
||||
abort();
|
||||
}
|
||||
|
||||
/* let's garbage the memory to catch some potential problems
|
||||
* (think multiprocessor sync issues, barriers, etc.)
|
||||
*/
|
||||
memset(T_cache, 0x55, T_CACHE_SIZE * sizeof(T_cache_t));
|
||||
|
||||
for (i = 0; i < T_CACHE_SIZE; i++) T_cache[i].busy = 0;
|
||||
|
||||
/* child1 runs the local tracer and child2 (or main) runs the tracee */
|
||||
child1 = fork();
|
||||
|
||||
if (child1 == -1) abort();
|
||||
|
||||
child1 = fork(); if (child1 == -1) abort();
|
||||
if (child1 == 0) {
|
||||
close(socket_pair[1]);
|
||||
T_local_tracer_main(remote_port, wait_for_tracer, socket_pair[0],
|
||||
T_cache);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
close(socket_pair[0]);
|
||||
|
||||
if (dont_fork == 0) {
|
||||
child2 = fork(); if (child2 == -1) abort();
|
||||
child2 = fork();
|
||||
|
||||
if (child2 == -1) abort();
|
||||
|
||||
if (child2 != 0) {
|
||||
close(socket_pair[1]);
|
||||
munmap(T_cache, T_CACHE_SIZE * sizeof(T_cache_t));
|
||||
@@ -161,27 +197,21 @@ void T_init(int remote_port, int wait_for_tracer, int dont_fork)
|
||||
s = socket_pair[1];
|
||||
/* wait for first message - initial list of active T events */
|
||||
get_message(s);
|
||||
|
||||
T_socket = s;
|
||||
|
||||
new_thread(T_receive_thread, NULL);
|
||||
}
|
||||
|
||||
void T_Config_Init(void)
|
||||
{
|
||||
int T_port; /* by default we wait for the tracer */
|
||||
int T_nowait; /* default port to listen to to wait for the tracer */
|
||||
int T_dont_fork; /* default is to fork, see 'T_init' to understand */
|
||||
|
||||
void T_Config_Init(void) {
|
||||
int T_port=TTRACER_DEFAULT_PORTNUM; /* by default we wait for the tracer */
|
||||
int T_nowait=0; /* default port to listen to to wait for the tracer */
|
||||
int T_dont_fork=0; /* default is to fork, see 'T_init' to understand */
|
||||
paramdef_t ttraceparams[] = CMDLINE_TTRACEPARAMS_DESC;
|
||||
|
||||
/* for a cleaner config file, TTracer params should be defined in a
|
||||
* specific section...
|
||||
*/
|
||||
config_get(ttraceparams,
|
||||
sizeof(ttraceparams) / sizeof(paramdef_t),
|
||||
TTRACER_CONFIG_PREFIX);
|
||||
|
||||
/* compatibility: look for TTracer command line options in root section */
|
||||
config_process_cmdline(ttraceparams,
|
||||
sizeof(ttraceparams) / sizeof(paramdef_t),
|
||||
|
||||
+41
-40
@@ -8,7 +8,7 @@
|
||||
#include "T_defs.h"
|
||||
|
||||
#ifdef T_SEND_TIME
|
||||
#include <time.h>
|
||||
#include <time.h>
|
||||
#endif
|
||||
|
||||
/* T message IDs */
|
||||
@@ -76,13 +76,13 @@
|
||||
T_BUFFER_MAX - T_LOCAL_size, T_PUT_printf_deref x); \
|
||||
if (T_PUT_len < 0) { \
|
||||
printf("%s:%d:%s: you can't read this, or can you?", \
|
||||
__FILE__, __LINE__, __FUNCTION__); \
|
||||
__FILE__, __LINE__, __FUNCTION__); \
|
||||
abort(); \
|
||||
} \
|
||||
if (T_PUT_len >= T_BUFFER_MAX - T_LOCAL_size) { \
|
||||
printf("%s:%d:%s: cannot put argument %d in T macro, not enough space" \
|
||||
", consider increasing T_BUFFER_MAX (%d)\n", \
|
||||
__FILE__, __LINE__, __FUNCTION__, argnum, T_BUFFER_MAX); \
|
||||
", consider increasing T_BUFFER_MAX (%d)\n", \
|
||||
__FILE__, __LINE__, __FUNCTION__, argnum, T_BUFFER_MAX); \
|
||||
abort(); \
|
||||
} \
|
||||
T_LOCAL_size += T_PUT_len + 1; \
|
||||
@@ -97,9 +97,9 @@ struct T_header;
|
||||
/* T macro tricks */
|
||||
extern int T_stdout;
|
||||
#define TN(...) TN_N(__VA_ARGS__,33,32,31,30,29,28,27,26,25,24,23,22,21,\
|
||||
20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)(__VA_ARGS__)
|
||||
20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)(__VA_ARGS__)
|
||||
#define TN_N(n0,n1,n2,n3,n4,n5,n6,n7,n8,n9,n10,n11,n12,n13,n14,n15,n16,n17,\
|
||||
n18,n19,n20,n21,n22,n23,n24,n25,n26,n27,n28,n29,n30,n31,n32,n,...) T##n
|
||||
n18,n19,n20,n21,n22,n23,n24,n25,n26,n27,n28,n29,n30,n31,n32,n,...) T##n
|
||||
#define T(...) do { if (T_stdout == 0) TN(__VA_ARGS__); } while (0)
|
||||
|
||||
/* type used to send arbitrary buffer data */
|
||||
@@ -119,30 +119,30 @@ extern int *T_active;
|
||||
*/
|
||||
#if BASIC_SIMULATOR
|
||||
# define T_GET_SLOT \
|
||||
do { \
|
||||
extern volatile uint64_t T_next_id; \
|
||||
extern volatile uint64_t T_active_id; \
|
||||
uint64_t id; \
|
||||
/* get a ticket */ \
|
||||
id = __sync_fetch_and_add(&T_next_id, 1); \
|
||||
/* wait for our turn */ \
|
||||
while (id != __sync_fetch_and_add(&T_active_id, 0)) /* busy wait */; \
|
||||
/* this is our turn, try to acquire the slot until it's free */ \
|
||||
do { \
|
||||
T_LOCAL_busy = __sync_fetch_and_or(&T_cache[T_LOCAL_slot].busy, 0x01); \
|
||||
if (T_LOCAL_busy & 0x01) usleep(100); \
|
||||
} while (T_LOCAL_busy & 0x01); \
|
||||
/* check that there are still some tickets */ \
|
||||
if (__sync_fetch_and_add(&T_active_id, 0) == 0xffffffffffffffff) { \
|
||||
printf("T: reached the end of times, bye...\n"); \
|
||||
abort(); \
|
||||
} \
|
||||
/* free our ticket, which signals the next waiter that it's its turn */ \
|
||||
(void)__sync_fetch_and_add(&T_active_id, 1); \
|
||||
} while (0)
|
||||
do { \
|
||||
extern volatile uint64_t T_next_id; \
|
||||
extern volatile uint64_t T_active_id; \
|
||||
uint64_t id; \
|
||||
/* get a ticket */ \
|
||||
id = __sync_fetch_and_add(&T_next_id, 1); \
|
||||
/* wait for our turn */ \
|
||||
while (id != __sync_fetch_and_add(&T_active_id, 0)) /* busy wait */; \
|
||||
/* this is our turn, try to acquire the slot until it's free */ \
|
||||
do { \
|
||||
T_LOCAL_busy = __sync_fetch_and_or(&T_cache[T_LOCAL_slot].busy, 0x01); \
|
||||
if (T_LOCAL_busy & 0x01) usleep(100); \
|
||||
} while (T_LOCAL_busy & 0x01); \
|
||||
/* check that there are still some tickets */ \
|
||||
if (__sync_fetch_and_add(&T_active_id, 0) == 0xffffffffffffffff) { \
|
||||
printf("T: reached the end of times, bye...\n"); \
|
||||
abort(); \
|
||||
} \
|
||||
/* free our ticket, which signals the next waiter that it's its turn */ \
|
||||
(void)__sync_fetch_and_add(&T_active_id, 1); \
|
||||
} while (0)
|
||||
#else
|
||||
# define T_GET_SLOT \
|
||||
T_LOCAL_busy = __sync_fetch_and_or(&T_cache[T_LOCAL_slot].busy, 0x01);
|
||||
T_LOCAL_busy = __sync_fetch_and_or(&T_cache[T_LOCAL_slot].busy, 0x01);
|
||||
#endif
|
||||
|
||||
/* used at header of Tn, allocates buffer */
|
||||
@@ -172,8 +172,8 @@ extern int *T_active;
|
||||
#define T_CHECK_SIZE(len, argnum) \
|
||||
if (T_LOCAL_size + (len) > T_BUFFER_MAX) { \
|
||||
printf("%s:%d:%s: cannot put argument %d in T macro, not enough space" \
|
||||
", consider increasing T_BUFFER_MAX (%d)\n", \
|
||||
__FILE__, __LINE__, __FUNCTION__, argnum, T_BUFFER_MAX); \
|
||||
", consider increasing T_BUFFER_MAX (%d)\n", \
|
||||
__FILE__, __LINE__, __FUNCTION__, argnum, T_BUFFER_MAX); \
|
||||
abort(); \
|
||||
}
|
||||
|
||||
@@ -598,20 +598,21 @@ extern int *T_active;
|
||||
|
||||
|
||||
#define TTRACER_CONFIG_PREFIX "TTracer"
|
||||
/*------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
/* configuration parameters for TTRACE utility */
|
||||
/* optname helpstr paramflags XXXptr defXXXval type numelt */
|
||||
/*------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
/*-------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
/* configuration parameters for TTRACE utility */
|
||||
/* optname helpstr paramflags XXXptr defXXXval type numelt */
|
||||
/*-------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
#define TTRACER_DEFAULT_PORTNUM 2021
|
||||
#define CMDLINE_TTRACEPARAMS_DESC { \
|
||||
{"T_port", CONFIG_HLP_TPORT, 0, iptr:&T_port, defintval:2021, TYPE_INT, 0}, \
|
||||
{"T_nowait", CONFIG_HLP_NOTWAIT, PARAMFLAG_BOOL, iptr:&T_nowait, defintval:0, TYPE_INT, 0}, \
|
||||
{"T_dont_fork", CONFIG_HLP_TNOFORK, PARAMFLAG_BOOL, iptr:&T_dont_fork, defintval:0, TYPE_INT, 0}, \
|
||||
{"T_stdout", CONFIG_HLP_STDOUT, PARAMFLAG_BOOL, iptr:&T_stdout, defintval:1, TYPE_INT, 0}, \
|
||||
}
|
||||
{"T_port", CONFIG_HLP_TPORT, 0, iptr:&T_port, defintval:TTRACER_DEFAULT_PORTNUM, TYPE_INT, 0},\
|
||||
{"T_nowait", CONFIG_HLP_NOTWAIT, PARAMFLAG_BOOL, iptr:&T_nowait, defintval:0, TYPE_INT, 0},\
|
||||
{"T_dont_fork", CONFIG_HLP_TNOFORK, PARAMFLAG_BOOL, iptr:&T_dont_fork, defintval:0, TYPE_INT, 0},\
|
||||
{"T_stdout", CONFIG_HLP_STDOUT, PARAMFLAG_BOOL, iptr:&T_stdout, defintval:1, TYPE_INT, 0},\
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* log on stdout */
|
||||
/* log on stdout */
|
||||
void T_init(int remote_port, int wait_for_tracer, int dont_fork);
|
||||
void T_Config_Init(void);
|
||||
#else /* T_TRACER */
|
||||
|
||||
+34
-2
@@ -1,3 +1,35 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/*!\file common/utils/T/T_defs.h
|
||||
* \brief
|
||||
* \author
|
||||
* \date
|
||||
* \version
|
||||
* \company EURECOM
|
||||
* \email
|
||||
* \note
|
||||
* \warning
|
||||
*/
|
||||
|
||||
#ifndef _T_defs_H_
|
||||
#define _T_defs_H_
|
||||
|
||||
@@ -41,10 +73,10 @@ typedef struct {
|
||||
} T_cache_t;
|
||||
|
||||
/* number of VCD functions (to be kept up to date! see in T_messages.txt) */
|
||||
#define VCD_NUM_FUNCTIONS 192//190
|
||||
#define VCD_NUM_FUNCTIONS 192
|
||||
|
||||
/* number of VCD variables (to be kept up to date! see in T_messages.txt) */
|
||||
#define VCD_NUM_VARIABLES 136//128
|
||||
#define VCD_NUM_VARIABLES 144
|
||||
|
||||
/* first VCD function (to be kept up to date! see in T_messages.txt) */
|
||||
#define VCD_FIRST_FUNCTION ((uintptr_t)T_VCD_FUNCTION_RT_SLEEP)
|
||||
|
||||
+145
-20
@@ -75,12 +75,16 @@ ID = ENB_PHY_MSG3_ALLOCATION
|
||||
FORMAT = int,eNB_ID : int,frame : int,subframe : int,rnti : int,first_transmission : int,Msg3_frame : int,Msg3_subframe
|
||||
ID = ENB_PHY_INITIATE_RA_PROCEDURE
|
||||
DESC = eNodeB initiates a random access procedure after detecting enough energy for one of the preambles
|
||||
GROUP = ALL:PHY:ENB
|
||||
GROUP = ALL:PHY:ENB:WIRESHARK
|
||||
FORMAT = int,eNB_ID : int,frame : int,subframe : int,preamble : int,energy : int,delay
|
||||
ID = GNB_PHY_DL_TICK
|
||||
DESC = gNodeB downlink tick - one tick per ms at start of downlink processing
|
||||
GROUP = ALL:PHY:GRAPHIC:GNB
|
||||
FORMAT = int,gNB_ID : int,frame : int,subframe
|
||||
ID = ENB_PHY_MIB
|
||||
DESC = MIB data
|
||||
GROUP = ALL:PHY:ENB:WIRESHARK
|
||||
FORMAT = int,eNB_ID : int,frame : int,subframe : buffer,data
|
||||
|
||||
#MAC logs
|
||||
ID = ENB_MAC_UE_DL_SDU
|
||||
@@ -101,7 +105,7 @@ ID = ENB_MAC_UE_UL_PDU
|
||||
FORMAT = int,eNB_ID : int,CC_id : int,rnti : int,frame : int,subframe : int,harq_pid : int,sdu_length : int,num_ce : int,num_sdu
|
||||
ID = ENB_MAC_UE_UL_PDU_WITH_DATA
|
||||
DESC = MAC uplink UE received PDU
|
||||
GROUP = ALL:MAC:ENB
|
||||
GROUP = ALL:MAC:ENB:WIRESHARK
|
||||
FORMAT = int,eNB_ID : int,CC_id : int,rnti : int,frame : int,subframe : int,harq_pid : int,sdu_length : int,num_ce : int,num_sdu : buffer,data
|
||||
ID = ENB_MAC_UE_UL_SDU
|
||||
DESC = MAC uplink UE received SDU
|
||||
@@ -117,12 +121,16 @@ ID = ENB_MAC_UE_UL_CE
|
||||
FORMAT = int,eNB_ID : int,CC_id : int,rnti : int,frame : int,subframe : int,ce
|
||||
ID = ENB_MAC_UE_DL_PDU_WITH_DATA
|
||||
DESC = MAC downlink PDU for an UE
|
||||
GROUP = ALL:MAC:ENB
|
||||
GROUP = ALL:MAC:ENB:WIRESHARK
|
||||
FORMAT = int,eNB_ID : int,CC_id : int,rnti : int,frame : int,subframe : int,harq_pid : buffer,data
|
||||
ID = ENB_MAC_SCHEDULING_REQUEST
|
||||
DESC = MAC scheduling request detected for an UE
|
||||
GROUP = ALL:MAC:ENB
|
||||
FORMAT = int,eNB_ID : int,CC_id : int,frame : int,subframe : int,rnti
|
||||
ID = ENB_MAC_UE_DL_RAR_PDU_WITH_DATA
|
||||
DESC = MAC downlink PDU for an UE
|
||||
GROUP = ALL:MAC:ENB:WIRESHARK
|
||||
FORMAT = int,eNB_ID : int,CC_id : int,rnti : int,frame : int,subframe : int,harq_pid : buffer,data
|
||||
|
||||
#RLC logs
|
||||
ID = ENB_RLC_DL
|
||||
@@ -709,7 +717,7 @@ ID = LEGACY_OCM_DEBUG
|
||||
FORMAT = string,log
|
||||
ID = LEGACY_OCM_TRACE
|
||||
DESC = OCM legacy logs - trace level
|
||||
GROUP = ALL:LEGACY_OCM:LEGACY_GROUP_TRACE:LEGACY
|
||||
OGROUP = ALL:LEGACY_OCM:LEGACY_GROUP_TRACE:LEGACY
|
||||
FORMAT = string,log
|
||||
|
||||
ID = LEGACY_OIP_INFO
|
||||
@@ -880,6 +888,47 @@ ID = LEGACY_SIM_TRACE
|
||||
GROUP = ALL:LEGACY_SIM:LEGACY_GROUP_TRACE:LEGACY
|
||||
FORMAT = string,log
|
||||
|
||||
ID = LEGACY_NFAPI_VNF_INFO
|
||||
DESC = NFAPI_VNF legacy logs - info level
|
||||
GROUP = ALL:LEGACY_NFAPI_VNF:LEGACY_GROUP_INFO:LEGACY
|
||||
FORMAT = string,log
|
||||
ID = LEGACY_NFAPI_VNF_ERROR
|
||||
DESC = NFAPI_VNF legacy logs - error level
|
||||
GROUP = ALL:LEGACY_NFAPI_VNF:LEGACY_GROUP_ERROR:LEGACY
|
||||
FORMAT = string,log
|
||||
ID = LEGACY_NFAPI_VNF_WARNING
|
||||
DESC = NFAPI_VNF legacy logs - warning level
|
||||
GROUP = ALL:LEGACY_NFAPI_VNF:LEGACY_GROUP_WARNING:LEGACY
|
||||
FORMAT = string,log
|
||||
ID = LEGACY_NFAPI_VNF_DEBUG
|
||||
DESC = NFAPI_VNF legacy logs - debug level
|
||||
GROUP = ALL:LEGACY_NFAPI_VNF:LEGACY_GROUP_DEBUG:LEGACY
|
||||
FORMAT = string,log
|
||||
ID = LEGACY_NFAPI_VNF_TRACE
|
||||
DESC = NFAPI_VNF legacy logs - trace level
|
||||
GROUP = ALL:LEGACY_NFAPI_VNF:LEGACY_GROUP_TRACE:LEGACY
|
||||
FORMAT = string,log
|
||||
|
||||
ID = LEGACY_NFAPI_PNF_INFO
|
||||
DESC = NFAPI_PNF legacy logs - info level
|
||||
GROUP = ALL:LEGACY_NFAPI_PNF:LEGACY_GROUP_INFO:LEGACY
|
||||
FORMAT = string,log
|
||||
ID = LEGACY_NFAPI_PNF_ERROR
|
||||
DESC = NFAPI_PNF legacy logs - error level
|
||||
GROUP = ALL:LEGACY_NFAPI_PNF:LEGACY_GROUP_ERROR:LEGACY
|
||||
FORMAT = string,log
|
||||
ID = LEGACY_NFAPI_PNF_WARNING
|
||||
DESC = NFAPI_PNF legacy logs - warning level
|
||||
GROUP = ALL:LEGACY_NFAPI_PNF:LEGACY_GROUP_WARNING:LEGACY
|
||||
FORMAT = string,log
|
||||
ID = LEGACY_NFAPI_PNF_DEBUG
|
||||
DESC = NFAPI_PNF legacy logs - debug level
|
||||
GROUP = ALL:LEGACY_NFAPI_PNF:LEGACY_GROUP_DEBUG:LEGACY
|
||||
FORMAT = string,log
|
||||
ID = LEGACY_NFAPI_PNF_TRACE
|
||||
DESC = NFAPI_PNF legacy logs - trace level
|
||||
GROUP = ALL:LEGACY_NFAPI_PNF:LEGACY_GROUP_TRACE:LEGACY
|
||||
FORMAT = string,log
|
||||
# this is a bad hack but I won't fix (function util_print_hex_octets
|
||||
# in openairinterface5g/openair2/LAYER2/PDCP_v10.1.0/pdcp_util.c
|
||||
# does funky things with the LOG_x macros but we work on the C pre-processor
|
||||
@@ -925,26 +974,62 @@ ID = LEGACY_componentP_TRACE
|
||||
GROUP = ALL:LEGACY_componentP:LEGACY_GROUP_TRACE:LEGACY
|
||||
FORMAT = string,log
|
||||
|
||||
#needed?
|
||||
ID = LEGACY_CLI_INFO
|
||||
DESC = CLI legacy logs - info level
|
||||
GROUP = ALL:LEGACY_CLI:LEGACY_GROUP_INFO:LEGACY
|
||||
|
||||
|
||||
ID = LEGACY_PROTO_AGENT_DEBUG
|
||||
DESC = PROTO AGENT DEBUG LEVEL
|
||||
GROUP = ALL:LEGACY_PROTO:LEGACY_GROUP_DEBUG:LEGACY
|
||||
FORMAT = string,log
|
||||
ID = LEGACY_CLI_ERROR
|
||||
DESC = CLI legacy logs - error level
|
||||
GROUP = ALL:LEGACY_CLI:LEGACY_GROUP_ERROR:LEGACY
|
||||
|
||||
ID = LEGACY_PROTO_AGENT_INFO
|
||||
DESC = PROTO AGENT INFO LEVEL
|
||||
GROUP = ALL:LEGACY_PROTO:LEGACY_GROUP_INFO:LEGACY
|
||||
FORMAT = string,log
|
||||
ID = LEGACY_CLI_WARNING
|
||||
DESC = CLI legacy logs - warning level
|
||||
GROUP = ALL:LEGACY_CLI:LEGACY_GROUP_WARNING:LEGACY
|
||||
|
||||
ID = LEGACY_PROTO_AGENT_WARNING
|
||||
DESC = PROTO AGENT WARNING LEVEL
|
||||
GROUP = ALL:LEGACY_PROTO:LEGACY_GROUP_WARNING:LEGACY
|
||||
FORMAT = string,log
|
||||
ID = LEGACY_CLI_DEBUG
|
||||
DESC = CLI legacy logs - debug level
|
||||
GROUP = ALL:LEGACY_CLI:LEGACY_GROUP_DEBUG:LEGACY
|
||||
|
||||
ID = LEGACY_PROTO_AGENT_ERROR
|
||||
DESC = PROTO AGENT ERROR LEVEL
|
||||
GROUP = ALL:LEGACY_PROTO:LEGACY_GROUP_ERROR:LEGACY
|
||||
FORMAT = string,log
|
||||
ID = LEGACY_CLI_TRACE
|
||||
DESC = CLI legacy logs - trace level
|
||||
GROUP = ALL:LEGACY_CLI:LEGACY_GROUP_TRACE:LEGACY
|
||||
|
||||
ID = LEGACY_F1U_DEBUG
|
||||
DESC = F1U DEBUG LEVEL
|
||||
GROUP = ALL:LEGACY_F1U:LEGACY_GROUP_DEBUG:LEGACY
|
||||
FORMAT = string,log
|
||||
|
||||
ID = LEGACY_F1U_INFO
|
||||
DESC = F1U INFO LEVEL
|
||||
GROUP = ALL:LEGACY_F1U:LEGACY_GROUP_INFO:LEGACY
|
||||
FORMAT = string,log
|
||||
|
||||
ID = LEGACY_F1U_ERROR
|
||||
DESC = F1U ERROR LEVEL
|
||||
GROUP = ALL:LEGACY_F1U:LEGACY_GROUP_ERROR:LEGACY
|
||||
FORMAT = string,log
|
||||
|
||||
ID = LEGACY_F1AP_TRACE
|
||||
DESC = F1AP TRACE LEVEL
|
||||
GROUP = ALL:LEGACY_F1AP:LEGACY_GROUP_TRACE:LEGACY
|
||||
FORMAT = string,log
|
||||
ID = LEGACY_F1AP_DEBUG
|
||||
DESC = F1AP DEBUG LEVEL
|
||||
GROUP = ALL:LEGACY_F1AP:LEGACY_GROUP_DEBUG:LEGACY
|
||||
FORMAT = string,log
|
||||
ID = LEGACY_F1AP_INFO
|
||||
DESC = F1AP INFO LEVEL
|
||||
GROUP = ALL:LEGACY_F1AP:LEGACY_GROUP_INFO:LEGACY
|
||||
FORMAT = string,log
|
||||
ID = LEGACY_F1AP_WARNING
|
||||
DESC = F1AP WARNING LEVEL
|
||||
GROUP = ALL:LEGACY_F1AP:LEGACY_GROUP_WARNING:LEGACY
|
||||
FORMAT = string,log
|
||||
ID = LEGACY_F1AP_ERROR
|
||||
DESC = F1AP ERROR LEVEL
|
||||
GROUP = ALL:LEGACY_F1AP:LEGACY_GROUP_ERROR:LEGACY
|
||||
FORMAT = string,log
|
||||
|
||||
#################
|
||||
@@ -1679,6 +1764,46 @@ ID = VCD_VARIABLE_CPUID_RU_THREAD_TX
|
||||
GROUP = ALL:VCD:ENB:VCD_VARIABLE
|
||||
FORMAT = ulong,value
|
||||
VCD_NAME = ru_thread_tx_CPUID
|
||||
ID = VCD_VARIABLE_ON_DURATION_TIMER
|
||||
DESC = VCD variable ON_DURATION_TIMER
|
||||
GROUP = ALL:VCD:ENB:VCD_VARIABLE
|
||||
FORMAT = ulong,value
|
||||
VCD_NAME = ue0_on_duration_timer
|
||||
ID = VCD_VARIABLE_DRX_INACTIVITY
|
||||
DESC = VCD variable DRX_INACTIVITY
|
||||
GROUP = ALL:VCD:ENB:VCD_VARIABLE
|
||||
FORMAT = ulong,value
|
||||
VCD_NAME = ue0_drx_inactivity
|
||||
ID = VCD_VARIABLE_DRX_SHORT_CYCLE
|
||||
DESC = VCD variable DRX_SHORT_CYCLE
|
||||
GROUP = ALL:VCD:ENB:VCD_VARIABLE
|
||||
FORMAT = ulong,value
|
||||
VCD_NAME = ue0_drx_short_cycle
|
||||
ID = VCD_VARIABLE_SHORT_DRX_CYCLE_NUMBER
|
||||
DESC = VCD variable SHORT_DRX_CYCLE_NUMBER
|
||||
GROUP = ALL:VCD:ENB:VCD_VARIABLE
|
||||
FORMAT = ulong,value
|
||||
VCD_NAME = ue0_short_drx_cycle_number
|
||||
ID = VCD_VARIABLE_DRX_LONG_CYCLE
|
||||
DESC = VCD variable DRX_LONG_CYCLE
|
||||
GROUP = ALL:VCD:ENB:VCD_VARIABLE
|
||||
FORMAT = ulong,value
|
||||
VCD_NAME = ue0_drx_long_cycle
|
||||
ID = VCD_VARIABLE_DRX_RETRANSMISSION_HARQ0
|
||||
DESC = VCD variable DRX_RETRANSMISSION_HARQ0
|
||||
GROUP = ALL:VCD:ENB:VCD_VARIABLE
|
||||
FORMAT = ulong,value
|
||||
VCD_NAME = ue0_drx_retransmission_harq0
|
||||
ID = VCD_VARIABLE_DRX_ACTIVE_TIME
|
||||
DESC = VCD variable DRX_ACTIVE_TIME
|
||||
GROUP = ALL:VCD:ENB:VCD_VARIABLE
|
||||
FORMAT = ulong,value
|
||||
VCD_NAME = ue0_drx_active_time
|
||||
ID = VCD_VARIABLE_DRX_ACTIVE_TIME_CONDITION
|
||||
DESC = VCD variable DRX_ACTIVE_TIME_CONDITION
|
||||
GROUP = ALL:VCD:ENB:VCD_VARIABLE
|
||||
FORMAT = ulong,value
|
||||
VCD_NAME = ue0_drx_active_time_condition
|
||||
|
||||
#variable for gNB
|
||||
ID = VCD_VARIABLE_FRAME_NUMBER_TX0_GNB
|
||||
|
||||
+92
-35
@@ -8,27 +8,35 @@ char **unique_ids;
|
||||
int unique_ids_size;
|
||||
int unique_ids_maxsize;
|
||||
|
||||
int cmp(const void *p1, const void *p2)
|
||||
{
|
||||
return strcmp(*(char * const *)p1, *(char * const *)p2);
|
||||
int cmp(const void *p1, const void *p2) {
|
||||
return strcmp(*(char *const *)p1, *(char *const *)p2);
|
||||
}
|
||||
|
||||
/* return 1 if s was not already known, 0 if it was */
|
||||
int new_unique_id(char *s, char *input_file)
|
||||
{
|
||||
int new_unique_id(char *s, char *input_file) {
|
||||
if (unique_ids_size)
|
||||
if (bsearch(&s, unique_ids, unique_ids_size, sizeof(char *), cmp) != NULL) {
|
||||
printf("error: ID %s is not unique in %s\n", s, input_file);
|
||||
return 0;
|
||||
}
|
||||
if (bsearch(&s, unique_ids, unique_ids_size, sizeof(char *), cmp) != NULL) {
|
||||
printf("error: ID %s is not unique in %s\n", s, input_file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (unique_ids_size == unique_ids_maxsize) {
|
||||
unique_ids_maxsize += 256;
|
||||
unique_ids = realloc(unique_ids, unique_ids_maxsize * sizeof(char *));
|
||||
if (unique_ids == NULL) { printf("erorr: out of memory\n"); abort(); }
|
||||
|
||||
if (unique_ids == NULL) {
|
||||
printf("error: out of memory\n");
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
unique_ids[unique_ids_size] = strdup(s);
|
||||
if (unique_ids[unique_ids_size] == NULL)
|
||||
{ printf("erorr: out of memory\n"); abort(); }
|
||||
|
||||
if (unique_ids[unique_ids_size] == NULL) {
|
||||
printf("error: out of memory\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
unique_ids_size++;
|
||||
qsort(unique_ids, unique_ids_size, sizeof(char *), cmp);
|
||||
return 1;
|
||||
@@ -38,14 +46,17 @@ char *bufname;
|
||||
int bufname_size;
|
||||
int bufname_maxsize;
|
||||
|
||||
void putname(int c)
|
||||
{
|
||||
void putname(int c) {
|
||||
if (bufname_size == bufname_maxsize) {
|
||||
bufname_maxsize += 256;
|
||||
bufname = realloc(bufname, bufname_maxsize);
|
||||
if (bufname == NULL)
|
||||
{ printf("erorr: memory allocation error\n"); exit(1); }
|
||||
|
||||
if (bufname == NULL) {
|
||||
printf("error: memory allocation error\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
bufname[bufname_size] = c;
|
||||
bufname_size++;
|
||||
}
|
||||
@@ -54,42 +65,54 @@ char *bufvalue;
|
||||
int bufvalue_size;
|
||||
int bufvalue_maxsize;
|
||||
|
||||
void putvalue(int c)
|
||||
{
|
||||
void putvalue(int c) {
|
||||
if (bufvalue_size == bufvalue_maxsize) {
|
||||
bufvalue_maxsize += 256;
|
||||
bufvalue = realloc(bufvalue, bufvalue_maxsize);
|
||||
if (bufvalue == NULL)
|
||||
{ printf("error: memory allocation error\n"); exit(1); }
|
||||
|
||||
if (bufvalue == NULL) {
|
||||
printf("error: memory allocation error\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
bufvalue[bufvalue_size] = c;
|
||||
bufvalue_size++;
|
||||
}
|
||||
|
||||
void smash_spaces(FILE *f)
|
||||
{
|
||||
void smash_spaces(FILE *f) {
|
||||
int c;
|
||||
|
||||
while (1) {
|
||||
c = fgetc(f);
|
||||
|
||||
if (isspace(c)) continue;
|
||||
|
||||
if (c == ' ') continue;
|
||||
|
||||
if (c == '\t') continue;
|
||||
|
||||
if (c == '\n') continue;
|
||||
|
||||
if (c == 10 || c == 13) continue;
|
||||
|
||||
if (c == '#') {
|
||||
while (1) {
|
||||
c = fgetc(f);
|
||||
|
||||
if (c == '\n' || c == EOF) break;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (c != EOF) ungetc(c, f);
|
||||
}
|
||||
|
||||
void get_line(FILE *f, char **name, char **value)
|
||||
{
|
||||
void get_line(FILE *f, char **name, char **value) {
|
||||
int c;
|
||||
bufname_size = 0;
|
||||
bufvalue_size = 0;
|
||||
@@ -97,23 +120,39 @@ void get_line(FILE *f, char **name, char **value)
|
||||
*value = NULL;
|
||||
smash_spaces(f);
|
||||
c = fgetc(f);
|
||||
while (!(c == '=' || isspace(c) || c == EOF)) { putname(c); c = fgetc(f); }
|
||||
|
||||
while (!(c == '=' || isspace(c) || c == EOF)) {
|
||||
putname(c);
|
||||
c = fgetc(f);
|
||||
}
|
||||
|
||||
if (c == EOF) return;
|
||||
|
||||
putname(0);
|
||||
|
||||
while (!(c == EOF || c == '=')) c = fgetc(f);
|
||||
|
||||
if (c == EOF) return;
|
||||
|
||||
smash_spaces(f);
|
||||
c = fgetc(f);
|
||||
while (!(c == 10 || c == 13 || c == EOF)) { putvalue(c); c = fgetc(f); }
|
||||
|
||||
while (!(c == 10 || c == 13 || c == EOF)) {
|
||||
putvalue(c);
|
||||
c = fgetc(f);
|
||||
}
|
||||
|
||||
putvalue(0);
|
||||
|
||||
if (bufname_size <= 1) return;
|
||||
|
||||
if (bufvalue_size <= 1) return;
|
||||
|
||||
*name = bufname;
|
||||
*value = bufvalue;
|
||||
}
|
||||
|
||||
int main(int n, char **v)
|
||||
{
|
||||
int main(int n, char **v) {
|
||||
FILE *in;
|
||||
FILE *out;
|
||||
char *name;
|
||||
@@ -121,36 +160,54 @@ int main(int n, char **v)
|
||||
char *in_name;
|
||||
char *out_name;
|
||||
|
||||
if (n != 3) { printf("error: gimme <source> <dest>\n"); exit(1); }
|
||||
if (n != 3) {
|
||||
printf("error: gimme <source> <dest>\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
n = 0;
|
||||
|
||||
in_name = v[1];
|
||||
out_name = v[2];
|
||||
in = fopen(in_name, "r");
|
||||
|
||||
in = fopen(in_name, "r"); if (in == NULL) { perror(in_name); exit(1); }
|
||||
out = fopen(out_name, "w"); if (out == NULL) { perror(out_name); exit(1); }
|
||||
if (in == NULL) {
|
||||
perror(in_name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
out = fopen(out_name, "w");
|
||||
|
||||
if (out == NULL) {
|
||||
perror(out_name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fprintf(out, "/* generated file, do not edit by hand */\n\n");
|
||||
|
||||
while (1) {
|
||||
get_line(in, &name, &value);
|
||||
|
||||
if (name == NULL) break;
|
||||
|
||||
if (isspace(value[strlen(value)-1])) {
|
||||
printf("error: bad value '%s' (no space at the end please!)\n", value);
|
||||
unlink(out_name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!strcmp(name, "ID")) {
|
||||
if (!new_unique_id(value, in_name)) { unlink(out_name); exit(1); }
|
||||
if (!new_unique_id(value, in_name)) {
|
||||
unlink(out_name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fprintf(out, "#define T_%s T_ID(%d)\n", value, n);
|
||||
n++;
|
||||
}
|
||||
}
|
||||
fprintf(out, "#define T_NUMBER_OF_IDS %d\n", n);
|
||||
|
||||
fprintf(out, "#define T_NUMBER_OF_IDS %d\n", n);
|
||||
fclose(in);
|
||||
fclose(out);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
+154
-94
@@ -31,7 +31,7 @@ typedef struct {
|
||||
int remote_port;
|
||||
pthread_mutex_t lock;
|
||||
pthread_cond_t cond;
|
||||
databuf * volatile head, *tail;
|
||||
databuf *volatile head, *tail;
|
||||
uint64_t memusage;
|
||||
uint64_t last_warning_memusage;
|
||||
} forward_data;
|
||||
@@ -40,80 +40,115 @@ typedef struct {
|
||||
/* utility functions */
|
||||
/****************************************************************************/
|
||||
|
||||
static void new_thread(void *(*f)(void *), void *data)
|
||||
{
|
||||
static void new_thread(void *(*f)(void *), void *data) {
|
||||
pthread_t t;
|
||||
pthread_attr_t att;
|
||||
|
||||
if (pthread_attr_init(&att))
|
||||
{ fprintf(stderr, "pthread_attr_init err\n"); exit(1); }
|
||||
if (pthread_attr_setdetachstate(&att, PTHREAD_CREATE_DETACHED))
|
||||
{ fprintf(stderr, "pthread_attr_setdetachstate err\n"); exit(1); }
|
||||
if (pthread_attr_setstacksize(&att, 10000000))
|
||||
{ fprintf(stderr, "pthread_attr_setstacksize err\n"); exit(1); }
|
||||
if (pthread_create(&t, &att, f, data))
|
||||
{ fprintf(stderr, "pthread_create err\n"); exit(1); }
|
||||
if (pthread_attr_destroy(&att))
|
||||
{ fprintf(stderr, "pthread_attr_destroy err\n"); exit(1); }
|
||||
if (pthread_attr_init(&att)) {
|
||||
fprintf(stderr, "pthread_attr_init err\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (pthread_attr_setdetachstate(&att, PTHREAD_CREATE_DETACHED)) {
|
||||
fprintf(stderr, "pthread_attr_setdetachstate err\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (pthread_attr_setstacksize(&att, 10000000)) {
|
||||
fprintf(stderr, "pthread_attr_setstacksize err\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (pthread_create(&t, &att, f, data)) {
|
||||
fprintf(stderr, "pthread_create err\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (pthread_attr_destroy(&att)) {
|
||||
fprintf(stderr, "pthread_attr_destroy err\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
static int get_connection(char *addr, int port)
|
||||
{
|
||||
static int get_connection(char *addr, int port) {
|
||||
struct sockaddr_in a;
|
||||
socklen_t alen;
|
||||
int s, t;
|
||||
|
||||
printf("T tracer: waiting for connection on %s:%d\n", addr, port);
|
||||
|
||||
s = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (s == -1) { perror("socket"); exit(1); }
|
||||
|
||||
if (s == -1) {
|
||||
perror("socket");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
t = 1;
|
||||
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &t, sizeof(int)))
|
||||
{ perror("setsockopt"); exit(1); }
|
||||
|
||||
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &t, sizeof(int))) {
|
||||
perror("setsockopt");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
a.sin_family = AF_INET;
|
||||
a.sin_port = htons(port);
|
||||
a.sin_addr.s_addr = inet_addr(addr);
|
||||
|
||||
if (bind(s, (struct sockaddr *)&a, sizeof(a))) { perror("bind"); exit(1); }
|
||||
if (listen(s, 5)) { perror("bind"); exit(1); }
|
||||
if (bind(s, (struct sockaddr *)&a, sizeof(a))) {
|
||||
perror("bind");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (listen(s, 5)) {
|
||||
perror("bind");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
alen = sizeof(a);
|
||||
t = accept(s, (struct sockaddr *)&a, &alen);
|
||||
if (t == -1) { perror("accept"); exit(1); }
|
||||
|
||||
if (t == -1) {
|
||||
perror("accept");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
close(s);
|
||||
|
||||
printf("T tracer: connected\n");
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
static void forward(void *_forwarder, char *buf, int size);
|
||||
|
||||
void send_T_messages_txt(void *forwarder)
|
||||
{
|
||||
void send_T_messages_txt(void *forwarder) {
|
||||
char buf[T_BUFFER_MAX];
|
||||
char *T_LOCAL_buf = buf;
|
||||
int T_LOCAL_size;
|
||||
unsigned char *src;
|
||||
int src_len;
|
||||
|
||||
/* trace T_message.txt
|
||||
* Send several messages -1 with content followed by message -2.
|
||||
*/
|
||||
src = T_messages_txt;
|
||||
src_len = T_messages_txt_len;
|
||||
|
||||
while (src_len) {
|
||||
int send_size = src_len;
|
||||
|
||||
if (send_size > T_PAYLOAD_MAXSIZE - sizeof(int))
|
||||
send_size = T_PAYLOAD_MAXSIZE - sizeof(int);
|
||||
|
||||
/* TODO: be careful, we use internal T stuff, to rewrite? */
|
||||
T_LOCAL_size = 0;
|
||||
T_HEADER(T_ID(-1));
|
||||
T_PUT_buffer(1, ((T_buffer){addr:(src), length:(send_size)}));
|
||||
T_PUT_buffer(1, ((T_buffer) {
|
||||
addr:
|
||||
(src), length:
|
||||
(send_size)
|
||||
}));
|
||||
forward(forwarder, buf, T_LOCAL_size);
|
||||
src += send_size;
|
||||
src_len -= send_size;
|
||||
}
|
||||
|
||||
T_LOCAL_size = 0;
|
||||
T_HEADER(T_ID(-2));
|
||||
forward(forwarder, buf, T_LOCAL_size);
|
||||
@@ -123,49 +158,54 @@ void send_T_messages_txt(void *forwarder)
|
||||
/* forward functions */
|
||||
/****************************************************************************/
|
||||
|
||||
static void *data_sender(void *_f)
|
||||
{
|
||||
static void *data_sender(void *_f) {
|
||||
forward_data *f = _f;
|
||||
databuf *cur;
|
||||
char *buf, *b;
|
||||
int size;
|
||||
|
||||
wait:
|
||||
|
||||
if (pthread_mutex_lock(&f->lock)) abort();
|
||||
|
||||
while (f->head == NULL)
|
||||
if (pthread_cond_wait(&f->cond, &f->lock)) abort();
|
||||
|
||||
cur = f->head;
|
||||
buf = cur->d;
|
||||
size = cur->l;
|
||||
f->head = cur->next;
|
||||
f->memusage -= size;
|
||||
|
||||
if (f->head == NULL) f->tail = NULL;
|
||||
|
||||
if (pthread_mutex_unlock(&f->lock)) abort();
|
||||
|
||||
free(cur);
|
||||
goto process;
|
||||
|
||||
process:
|
||||
b = buf;
|
||||
|
||||
if (f->socket_remote != -1)
|
||||
while (size) {
|
||||
int l = write(f->socket_remote, b, size);
|
||||
if (l <= 0) {
|
||||
printf("T tracer: forward error\n");
|
||||
close(f->socket_remote);
|
||||
f->socket_remote = -1;
|
||||
break;
|
||||
while (size) {
|
||||
int l = write(f->socket_remote, b, size);
|
||||
|
||||
if (l <= 0) {
|
||||
printf("T tracer: forward error\n");
|
||||
close(f->socket_remote);
|
||||
f->socket_remote = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
size -= l;
|
||||
b += l;
|
||||
}
|
||||
size -= l;
|
||||
b += l;
|
||||
}
|
||||
|
||||
free(buf);
|
||||
|
||||
goto wait;
|
||||
}
|
||||
|
||||
static void *forward_remote_messages(void *_f)
|
||||
{
|
||||
|
||||
static void *forward_remote_messages(void *_f) {
|
||||
#define PUT(x) do { \
|
||||
if (bufsize == bufmaxsize) { \
|
||||
bufmaxsize += 4096; \
|
||||
@@ -180,7 +220,6 @@ static void *forward_remote_messages(void *_f)
|
||||
int len = l; \
|
||||
while (len) { PUT(*zz); zz++; len--; } \
|
||||
} while (0)
|
||||
|
||||
forward_data *f = _f;
|
||||
int from;
|
||||
int to;
|
||||
@@ -190,43 +229,53 @@ static void *forward_remote_messages(void *_f)
|
||||
int bufsize = 0;
|
||||
int bufmaxsize = 0;
|
||||
char t;
|
||||
|
||||
again:
|
||||
|
||||
while (1) {
|
||||
from = f->socket_remote;
|
||||
to = f->socket_local;
|
||||
|
||||
bufsize = 0;
|
||||
|
||||
/* let's read and process messages */
|
||||
len = read(from, &t, 1); if (len <= 0) goto dead;
|
||||
len = read(from, &t, 1);
|
||||
|
||||
if (len <= 0) goto dead;
|
||||
|
||||
PUT(t);
|
||||
|
||||
switch (t) {
|
||||
case 0:
|
||||
case 1:
|
||||
/* message 0 and 1: get a length and then 'length' numbers */
|
||||
if (read(from, &len, sizeof(int)) != sizeof(int)) goto dead;
|
||||
PUT_BUF(&len, 4);
|
||||
while (len) {
|
||||
if (read(from, &l, sizeof(int)) != sizeof(int)) goto dead;
|
||||
PUT_BUF(&l, 4);
|
||||
len--;
|
||||
}
|
||||
break;
|
||||
case 0:
|
||||
case 1:
|
||||
|
||||
case 2: break;
|
||||
default:
|
||||
printf("%s:%d:%s: unhandled message type %d\n",
|
||||
__FILE__, __LINE__, __FUNCTION__, t);
|
||||
abort();
|
||||
/* message 0 and 1: get a length and then 'length' numbers */
|
||||
if (read(from, &len, sizeof(int)) != sizeof(int)) goto dead;
|
||||
|
||||
PUT_BUF(&len, 4);
|
||||
|
||||
while (len) {
|
||||
if (read(from, &l, sizeof(int)) != sizeof(int)) goto dead;
|
||||
|
||||
PUT_BUF(&l, 4);
|
||||
len--;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 2:
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("%s:%d:%s: unhandled message type %d\n",
|
||||
__FILE__, __LINE__, __FUNCTION__, t);
|
||||
abort();
|
||||
}
|
||||
|
||||
b = buf;
|
||||
|
||||
while (bufsize) {
|
||||
l = write(to, b, bufsize);
|
||||
|
||||
if (l <= 0) abort();
|
||||
|
||||
bufsize -= l;
|
||||
b += l;
|
||||
}
|
||||
@@ -236,71 +285,80 @@ dead:
|
||||
/* socket died, let's stop all traces and wait for another tracer */
|
||||
/* TODO: be careful with those write, they might write less than wanted */
|
||||
buf[0] = 1;
|
||||
|
||||
if (write(to, buf, 1) != 1) abort();
|
||||
|
||||
len = T_NUMBER_OF_IDS;
|
||||
|
||||
if (write(to, &len, sizeof(int)) != sizeof(int)) abort();
|
||||
|
||||
l = 0;
|
||||
|
||||
while (len) {
|
||||
if (write(to, &l, sizeof(int)) != sizeof(int)) abort();
|
||||
|
||||
len--;
|
||||
};
|
||||
|
||||
close(f->socket_remote);
|
||||
|
||||
f->socket_remote = get_connection("0.0.0.0", f->remote_port);
|
||||
|
||||
send_T_messages_txt(f);
|
||||
|
||||
goto again;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *forwarder(int port, int s)
|
||||
{
|
||||
static void *forwarder(int port, int s) {
|
||||
forward_data *f;
|
||||
f = malloc(sizeof(*f));
|
||||
|
||||
f = malloc(sizeof(*f)); if (f == NULL) abort();
|
||||
if (f == NULL) abort();
|
||||
|
||||
pthread_mutex_init(&f->lock, NULL);
|
||||
pthread_cond_init(&f->cond, NULL);
|
||||
|
||||
f->socket_local = s;
|
||||
f->head = f->tail = NULL;
|
||||
|
||||
f->memusage = 0;
|
||||
f->last_warning_memusage = 0;
|
||||
|
||||
printf("T tracer: waiting for remote tracer on port %d\n", port);
|
||||
|
||||
f->remote_port = port;
|
||||
f->socket_remote = get_connection("0.0.0.0", port);
|
||||
send_T_messages_txt(f);
|
||||
|
||||
new_thread(data_sender, f);
|
||||
new_thread(forward_remote_messages, f);
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
static void forward(void *_forwarder, char *buf, int size)
|
||||
{
|
||||
static void forward(void *_forwarder, char *buf, int size) {
|
||||
forward_data *f = _forwarder;
|
||||
int32_t ssize = size;
|
||||
databuf *new;
|
||||
new = malloc(sizeof(*new));
|
||||
|
||||
new = malloc(sizeof(*new)); if (new == NULL) abort();
|
||||
if (new == NULL) abort();
|
||||
|
||||
if (pthread_mutex_lock(&f->lock)) abort();
|
||||
|
||||
new->d = malloc(size + 4); if (new->d == NULL) abort();
|
||||
new->d = malloc(size + 4);
|
||||
|
||||
if (new->d == NULL) abort();
|
||||
|
||||
/* put the size of the message at the head */
|
||||
memcpy(new->d, &ssize, 4);
|
||||
memcpy(new->d+4, buf, size);
|
||||
new->l = size+4;
|
||||
new->next = NULL;
|
||||
if (f->head == NULL) f->head = new;
|
||||
if (f->tail != NULL) f->tail->next = new;
|
||||
f->tail = new;
|
||||
|
||||
if (f->head == NULL) f->head = new;
|
||||
|
||||
if (f->tail != NULL) f->tail->next = new;
|
||||
|
||||
f->tail = new;
|
||||
#if BASIC_SIMULATOR
|
||||
|
||||
/* When runnng the basic simulator, the tracer may be too slow.
|
||||
* Let's not take too much memory in the tracee and
|
||||
* wait if there is too much data to send. 200MB is
|
||||
@@ -308,26 +366,30 @@ static void forward(void *_forwarder, char *buf, int size)
|
||||
*/
|
||||
while (f->memusage > 200 * 1024 * 1024) {
|
||||
if (pthread_cond_signal(&f->cond)) abort();
|
||||
|
||||
if (pthread_mutex_unlock(&f->lock)) abort();
|
||||
|
||||
usleep(1000);
|
||||
|
||||
if (pthread_mutex_lock(&f->lock)) abort();
|
||||
}
|
||||
#endif /* BASIC_SIMULATOR */
|
||||
|
||||
#endif /* BASIC_SIMULATOR */
|
||||
f->memusage += size+4;
|
||||
|
||||
/* warn every 100MB */
|
||||
if (f->memusage > f->last_warning_memusage &&
|
||||
f->memusage - f->last_warning_memusage > 100000000) {
|
||||
f->last_warning_memusage += 100000000;
|
||||
printf("T tracer: WARNING: memory usage is over %"PRIu64"MB\n",
|
||||
f->last_warning_memusage / 1000000);
|
||||
} else
|
||||
if (f->memusage < f->last_warning_memusage &&
|
||||
f->last_warning_memusage - f->memusage > 100000000) {
|
||||
} else if (f->memusage < f->last_warning_memusage &&
|
||||
f->last_warning_memusage - f->memusage > 100000000) {
|
||||
f->last_warning_memusage = (f->memusage/100000000) * 100000000;
|
||||
}
|
||||
|
||||
if (pthread_cond_signal(&f->cond)) abort();
|
||||
|
||||
if (pthread_mutex_unlock(&f->lock)) abort();
|
||||
}
|
||||
|
||||
@@ -335,14 +397,12 @@ static void forward(void *_forwarder, char *buf, int size)
|
||||
/* local functions */
|
||||
/****************************************************************************/
|
||||
|
||||
static void wait_message(void)
|
||||
{
|
||||
static void wait_message(void) {
|
||||
while ((T_local_cache[T_busylist_head].busy & 0x02) == 0) usleep(1000);
|
||||
}
|
||||
|
||||
void T_local_tracer_main(int remote_port, int wait_for_tracer,
|
||||
int local_socket, void *shm_array)
|
||||
{
|
||||
int local_socket, void *shm_array) {
|
||||
int s;
|
||||
int port = remote_port;
|
||||
int dont_wait = wait_for_tracer ? 0 : 1;
|
||||
@@ -350,16 +410,16 @@ void T_local_tracer_main(int remote_port, int wait_for_tracer,
|
||||
|
||||
/* write on a socket fails if the other end is closed and we get SIGPIPE */
|
||||
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
|
||||
printf("local tracer received SIGPIPE\n");
|
||||
abort();
|
||||
printf("local tracer received SIGPIPE\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
T_local_cache = shm_array;
|
||||
|
||||
s = local_socket;
|
||||
|
||||
if (dont_wait) {
|
||||
char t = 2;
|
||||
|
||||
if (write(s, &t, 1) != 1) abort();
|
||||
}
|
||||
|
||||
|
||||
@@ -60,6 +60,11 @@ macpdu2wireshark: macpdu2wireshark.o database.o utils.o handler.o event.o \
|
||||
multi: multi.o utils.o database.o config.o
|
||||
$(CC) $(CFLAGS) -o multi $^ $(LIBS)
|
||||
|
||||
multi.o: ../T_IDs.h
|
||||
|
||||
../T_IDs.h:
|
||||
cd .. && $(MAKE)
|
||||
|
||||
.PHONY: all gui/gui.a view/view.a logger/logger.a filter/filter.a
|
||||
|
||||
gui/gui.a:
|
||||
|
||||
@@ -16,6 +16,8 @@ void usage(void)
|
||||
" -f <name> <value> field 'name' of 'event' has to match 'value'\n"
|
||||
" type of 'name' must be int\n"
|
||||
" (you can use several -f options)\n"
|
||||
" -after <raw time> <nsec> 'event' time has to be greater than this\n"
|
||||
" -count <n> dump 'n' matching events (less if EOF reached)\n"
|
||||
);
|
||||
exit(1);
|
||||
}
|
||||
@@ -51,6 +53,10 @@ int main(int n, char **v)
|
||||
int filter_count = 0;
|
||||
int buffer_arg;
|
||||
int found;
|
||||
int count = 1;
|
||||
int check_time = 0;
|
||||
time_t sec;
|
||||
long nsec;
|
||||
|
||||
for (i = 1; i < n; i++) {
|
||||
if (!strcmp(v[i], "-h") || !strcmp(v[i], "--help")) usage();
|
||||
@@ -63,6 +69,14 @@ int main(int n, char **v)
|
||||
filter_value[filter_count++] = atoi(v[++i]);
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(v[i], "-after")) { if (i>n-3) usage();
|
||||
check_time = 1;
|
||||
sec = atoll(v[++i]);
|
||||
nsec = atol(v[++i]);
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(v[i], "-count"))
|
||||
{ if (i > n-2) usage(); count = atoi(v[++i]); continue; }
|
||||
if (file == NULL) { file = v[i]; continue; }
|
||||
if (event_name == NULL) { event_name = v[i]; continue; }
|
||||
if (buffer_name == NULL) { buffer_name = v[i]; continue; }
|
||||
@@ -111,13 +125,20 @@ int main(int n, char **v)
|
||||
break;
|
||||
if (i != filter_count)
|
||||
continue;
|
||||
if (check_time &&
|
||||
!(e.sending_time.tv_sec > sec ||
|
||||
(e.sending_time.tv_sec == sec && e.sending_time.tv_nsec >= nsec)))
|
||||
continue;
|
||||
if (fwrite(e.e[buffer_arg].b, e.e[buffer_arg].bsize, 1, out) != 1)
|
||||
{ perror(output_file); exit(1); }
|
||||
found = 1;
|
||||
break;
|
||||
found++;
|
||||
if (found == count)
|
||||
break;
|
||||
}
|
||||
|
||||
if (found == 0) printf("ERROR: event not found\n");
|
||||
if (found != count)
|
||||
printf("WARNING: dumped %d events (wanted %d)\n", found, count);
|
||||
|
||||
fclose(out);
|
||||
|
||||
|
||||
@@ -5,62 +5,56 @@
|
||||
#include <string.h>
|
||||
|
||||
unsigned long register_notifier(gui *_g, char *notification, widget *w,
|
||||
notifier handler, void *private)
|
||||
{
|
||||
notifier handler, void *private) {
|
||||
struct gui *g = _g;
|
||||
unsigned long ret;
|
||||
|
||||
glock(g);
|
||||
|
||||
if (g->next_notifier_id == 2UL * 1024 * 1024 * 1024)
|
||||
ERR("%s:%d: report a bug\n", __FILE__, __LINE__);
|
||||
|
||||
g->notifiers = realloc(g->notifiers,
|
||||
(g->notifiers_count+1) * sizeof(struct notifier));
|
||||
(g->notifiers_count+1) * sizeof(struct notifier));
|
||||
|
||||
if (g->notifiers == NULL) abort();
|
||||
|
||||
ret = g->next_notifier_id;
|
||||
|
||||
g->notifiers[g->notifiers_count].handler = handler;
|
||||
g->notifiers[g->notifiers_count].id = g->next_notifier_id;
|
||||
g->next_notifier_id++;
|
||||
g->notifiers[g->notifiers_count].notification = strdup(notification);
|
||||
|
||||
if (g->notifiers[g->notifiers_count].notification == NULL) abort();
|
||||
|
||||
g->notifiers[g->notifiers_count].w = w;
|
||||
g->notifiers[g->notifiers_count].private = private;
|
||||
/* initialize done to 1 so as not to call the handler if it's created
|
||||
* by the call of another one that is in progress
|
||||
*/
|
||||
g->notifiers[g->notifiers_count].done = 1;
|
||||
|
||||
g->notifiers_count++;
|
||||
|
||||
gunlock(g);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void unregister_notifier(gui *_g, unsigned long notifier_id)
|
||||
{
|
||||
void unregister_notifier(gui *_g, unsigned long notifier_id) {
|
||||
struct gui *g = _g;
|
||||
int i;
|
||||
|
||||
glock(g);
|
||||
|
||||
for (i = 0; i < g->notifiers_count; i++)
|
||||
if (g->notifiers[i].id == notifier_id) break;
|
||||
|
||||
if (i == g->notifiers_count)
|
||||
ERR("%s:%d: notifier_id %ld not found\n", __FILE__,__LINE__,notifier_id);
|
||||
ERR("%s:%d: notifier_id %lu not found\n", __FILE__,__LINE__,notifier_id);
|
||||
|
||||
free(g->notifiers[i].notification);
|
||||
|
||||
memmove(g->notifiers + i, g->notifiers + i + 1,
|
||||
(g->notifiers_count-1 - i) * sizeof(struct notifier));
|
||||
|
||||
(g->notifiers_count-1 - i) * sizeof(struct notifier));
|
||||
g->notifiers_count--;
|
||||
g->notifiers = realloc(g->notifiers,
|
||||
g->notifiers_count * sizeof(struct notifier));
|
||||
g->notifiers_count * sizeof(struct notifier));
|
||||
|
||||
if (g->notifiers == NULL) abort();
|
||||
|
||||
gunlock(g);
|
||||
@@ -68,19 +62,19 @@ void unregister_notifier(gui *_g, unsigned long notifier_id)
|
||||
|
||||
/* called with lock ON */
|
||||
void gui_notify(struct gui *g, char *notification, widget *w,
|
||||
void *notification_data)
|
||||
{
|
||||
void *notification_data) {
|
||||
void *private;
|
||||
notifier handler;
|
||||
int i;
|
||||
|
||||
/* this function is not re-entrant, for the moment keep as is
|
||||
* and if the need is there, we'll make a new thread to handle
|
||||
* notifications (or something)
|
||||
* for now let's crash in case of recursive call
|
||||
*/
|
||||
static int inside = 0;
|
||||
|
||||
if (inside) ERR("%s:%d: BUG! contact the authors\n", __FILE__, __LINE__);
|
||||
|
||||
inside = 1;
|
||||
|
||||
/* clear all handlers */
|
||||
@@ -91,26 +85,25 @@ void gui_notify(struct gui *g, char *notification, widget *w,
|
||||
* need to be careful here
|
||||
*/
|
||||
loop:
|
||||
|
||||
for (i = 0; i < g->notifiers_count; i++) {
|
||||
if (g->notifiers[i].done == 1 ||
|
||||
g->notifiers[i].w != w ||
|
||||
strcmp(g->notifiers[i].notification, notification) != 0)
|
||||
continue;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == g->notifiers_count) goto done;
|
||||
|
||||
g->notifiers[i].done = 1;
|
||||
|
||||
handler = g->notifiers[i].handler;
|
||||
private = g->notifiers[i].private;
|
||||
|
||||
gunlock(g);
|
||||
handler(private, g, notification, w, notification_data);
|
||||
glock(g);
|
||||
|
||||
goto loop;
|
||||
|
||||
done:
|
||||
inside = 0;
|
||||
}
|
||||
|
||||
+147
-136
@@ -7,21 +7,19 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
int x_connection_fd(x_connection *_x)
|
||||
{
|
||||
int x_connection_fd(x_connection *_x) {
|
||||
struct x_connection *x = _x;
|
||||
return ConnectionNumber(x->d);
|
||||
}
|
||||
|
||||
static GC create_gc(Display *d, char *color)
|
||||
{
|
||||
static GC create_gc(Display *d, char *color) {
|
||||
GC ret = XCreateGC(d, DefaultRootWindow(d), 0, NULL);
|
||||
XGCValues gcv;
|
||||
XColor rcol, scol;
|
||||
|
||||
XCopyGC(d, DefaultGC(d, DefaultScreen(d)), -1L, ret);
|
||||
|
||||
if (XAllocNamedColor(d, DefaultColormap(d, DefaultScreen(d)),
|
||||
color, &scol, &rcol)) {
|
||||
color, &scol, &rcol)) {
|
||||
gcv.foreground = scol.pixel;
|
||||
XChangeGC(d, ret, GCForeground, &gcv);
|
||||
} else ERR("X: could not allocate color '%s'\n", color);
|
||||
@@ -29,82 +27,81 @@ static GC create_gc(Display *d, char *color)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int x_new_color(x_connection *_x, char *color)
|
||||
{
|
||||
int x_new_color(x_connection *_x, char *color) {
|
||||
struct x_connection *x = _x;
|
||||
x->ncolors++;
|
||||
|
||||
x->colors = realloc(x->colors, x->ncolors * sizeof(GC));
|
||||
if (x->colors == NULL) OOM;
|
||||
x->colors[x->ncolors-1] = create_gc(x->d, color);
|
||||
|
||||
if (x->colors == NULL) OOM;
|
||||
|
||||
x->colors[x->ncolors-1] = create_gc(x->d, color);
|
||||
x->xft_colors = realloc(x->xft_colors, x->ncolors * sizeof(XftColor));
|
||||
|
||||
if (x->xft_colors == NULL) OOM;
|
||||
|
||||
if (XftColorAllocName(x->d, DefaultVisual(x->d, DefaultScreen(x->d)),
|
||||
DefaultColormap(x->d, DefaultScreen(x->d)),
|
||||
color, &x->xft_colors[x->ncolors-1]) == False)
|
||||
DefaultColormap(x->d, DefaultScreen(x->d)),
|
||||
color, &x->xft_colors[x->ncolors-1]) == False)
|
||||
ERR("could not allocate color '%s'\n", color);
|
||||
|
||||
return x->ncolors - 1;
|
||||
}
|
||||
|
||||
int x_new_font(x_connection *_x, char *font)
|
||||
{
|
||||
int x_new_font(x_connection *_x, char *font) {
|
||||
struct x_connection *x = _x;
|
||||
/* TODO: allocate fonts only once */
|
||||
x->nfonts++;
|
||||
x->fonts = realloc(x->fonts, x->nfonts * sizeof(XftFont *));
|
||||
|
||||
if (x->fonts == NULL) OOM;
|
||||
|
||||
x->fonts[x->nfonts-1] = XftFontOpenName(x->d, DefaultScreen(x->d), font);
|
||||
|
||||
if (x->fonts[x->nfonts-1] == NULL)
|
||||
ERR("failed allocating font '%s'\n", font);
|
||||
|
||||
return x->nfonts - 1;
|
||||
}
|
||||
|
||||
x_connection *x_open(void)
|
||||
{
|
||||
x_connection *x_open(void) {
|
||||
struct x_connection *ret;
|
||||
|
||||
ret = calloc(1, sizeof(struct x_connection));
|
||||
|
||||
if (ret == NULL) OOM;
|
||||
|
||||
ret->d = XOpenDisplay(0);
|
||||
LOGD("XOpenDisplay display %p return x_connection %p\n", ret->d, ret);
|
||||
|
||||
if (ret->d == NULL) ERR("error calling XOpenDisplay: no X? you root?\n");
|
||||
|
||||
x_new_color(ret, "white"); /* background color */
|
||||
x_new_color(ret, "black"); /* foreground color */
|
||||
|
||||
x_new_font(ret, "sans-8");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
x_window *x_create_window(x_connection *_x, int width, int height,
|
||||
char *title)
|
||||
{
|
||||
char *title) {
|
||||
struct x_connection *x = _x;
|
||||
struct x_window *ret;
|
||||
|
||||
ret = calloc(1, sizeof(struct x_window));
|
||||
|
||||
if (ret == NULL) OOM;
|
||||
|
||||
ret->w = XCreateSimpleWindow(x->d, DefaultRootWindow(x->d), 0, 0,
|
||||
width, height, 0, WhitePixel(x->d, DefaultScreen(x->d)),
|
||||
WhitePixel(x->d, DefaultScreen(x->d)));
|
||||
width, height, 0, WhitePixel(x->d, DefaultScreen(x->d)),
|
||||
WhitePixel(x->d, DefaultScreen(x->d)));
|
||||
ret->width = width;
|
||||
ret->height = height;
|
||||
|
||||
XStoreName(x->d, ret->w, title);
|
||||
|
||||
ret->p = XCreatePixmap(x->d, ret->w, width, height,
|
||||
DefaultDepth(x->d, DefaultScreen(x->d)));
|
||||
DefaultDepth(x->d, DefaultScreen(x->d)));
|
||||
XFillRectangle(x->d, ret->p, x->colors[BACKGROUND_COLOR],
|
||||
0, 0, width, height);
|
||||
|
||||
0, 0, width, height);
|
||||
ret->xft = XftDrawCreate(x->d, ret->p,
|
||||
DefaultVisual(x->d, DefaultScreen(x->d)),
|
||||
DefaultColormap(x->d, DefaultScreen(x->d)));
|
||||
DefaultVisual(x->d, DefaultScreen(x->d)),
|
||||
DefaultColormap(x->d, DefaultScreen(x->d)));
|
||||
|
||||
if (ret->xft == NULL) ERR("XftDrawCreate failed\n");
|
||||
|
||||
/* enable backing store */
|
||||
@@ -113,23 +110,19 @@ x_window *x_create_window(x_connection *_x, int width, int height,
|
||||
att.backing_store = Always;
|
||||
XChangeWindowAttributes(x->d, ret->w, CWBackingStore, &att);
|
||||
}
|
||||
|
||||
XSelectInput(x->d, ret->w,
|
||||
KeyPressMask |
|
||||
ButtonPressMask |
|
||||
ButtonReleaseMask |
|
||||
PointerMotionMask |
|
||||
ExposureMask |
|
||||
StructureNotifyMask);
|
||||
|
||||
KeyPressMask |
|
||||
ButtonPressMask |
|
||||
ButtonReleaseMask |
|
||||
PointerMotionMask |
|
||||
ExposureMask |
|
||||
StructureNotifyMask);
|
||||
XMapWindow(x->d, ret->w);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
x_image *x_create_image(x_connection *_x, unsigned char *data,
|
||||
int width, int height)
|
||||
{
|
||||
int width, int height) {
|
||||
struct x_connection *x = _x;
|
||||
struct x_image *ret;
|
||||
XImage *ximage;
|
||||
@@ -137,8 +130,9 @@ x_image *x_create_image(x_connection *_x, unsigned char *data,
|
||||
XVisualInfo template;
|
||||
int nvs;
|
||||
Visual *v;
|
||||
ret = calloc(1, sizeof(struct x_image));
|
||||
|
||||
ret = calloc(1, sizeof(struct x_image)); if (ret == NULL) OOM;
|
||||
if (ret == NULL) OOM;
|
||||
|
||||
template.class = TrueColor;
|
||||
template.depth = 24;
|
||||
@@ -146,68 +140,65 @@ x_image *x_create_image(x_connection *_x, unsigned char *data,
|
||||
template.green_mask = 0x00ff00;
|
||||
template.blue_mask = 0x0000ff;
|
||||
template.bits_per_rgb = 8;
|
||||
|
||||
vs = XGetVisualInfo(x->d, VisualDepthMask | VisualClassMask |
|
||||
VisualRedMaskMask | VisualGreenMaskMask | VisualBlueMaskMask |
|
||||
VisualBitsPerRGBMask, &template, &nvs);
|
||||
VisualRedMaskMask | VisualGreenMaskMask | VisualBlueMaskMask |
|
||||
VisualBitsPerRGBMask, &template, &nvs);
|
||||
|
||||
if (vs == NULL) {
|
||||
/* try again with 32 bpp */
|
||||
template.depth = 32;
|
||||
vs = XGetVisualInfo(x->d, VisualDepthMask | VisualClassMask |
|
||||
VisualRedMaskMask | VisualGreenMaskMask | VisualBlueMaskMask |
|
||||
VisualBitsPerRGBMask, &template, &nvs);
|
||||
VisualRedMaskMask | VisualGreenMaskMask | VisualBlueMaskMask |
|
||||
VisualBitsPerRGBMask, &template, &nvs);
|
||||
}
|
||||
|
||||
if (vs == NULL) ERR("no good visual found\n");
|
||||
|
||||
v = vs[0].visual;
|
||||
XFree(vs);
|
||||
|
||||
ximage = XCreateImage(x->d, v, 24, ZPixmap, 0,
|
||||
(char*)data, width, height, 32, 0);
|
||||
(char *)data, width, height, 32, 0);
|
||||
|
||||
if (ximage == NULL) ERR("image creation failed\n");
|
||||
|
||||
ret->p = XCreatePixmap(x->d, DefaultRootWindow(x->d), width, height, 24);
|
||||
|
||||
XPutImage(x->d, ret->p, DefaultGC(x->d, DefaultScreen(x->d)),
|
||||
ximage, 0, 0, 0, 0, width, height);
|
||||
|
||||
ximage, 0, 0, 0, 0, width, height);
|
||||
/* TODO: be sure it's fine to set data to NULL */
|
||||
ximage->data = NULL;
|
||||
XDestroyImage(ximage);
|
||||
|
||||
ret->width = width;
|
||||
ret->height = height;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct toplevel_window_widget *find_x_window(struct gui *g, Window id)
|
||||
{
|
||||
static struct toplevel_window_widget *find_x_window(struct gui *g, Window id) {
|
||||
struct widget_list *cur;
|
||||
struct toplevel_window_widget *w;
|
||||
struct x_window *xw;
|
||||
cur = g->toplevel;
|
||||
|
||||
while (cur) {
|
||||
w = (struct toplevel_window_widget *)cur->item;
|
||||
xw = w->x;
|
||||
|
||||
if (xw->w == id) return w;
|
||||
|
||||
cur = cur->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void x_events(gui *_gui)
|
||||
{
|
||||
void x_events(gui *_gui) {
|
||||
struct gui *g = _gui;
|
||||
struct widget_list *cur;
|
||||
struct x_connection *x = g->x;
|
||||
struct toplevel_window_widget *w;
|
||||
|
||||
LOGD("x_events START\n");
|
||||
/* preprocessing (to "compress" events) */
|
||||
cur = g->toplevel;
|
||||
|
||||
while (cur) {
|
||||
struct x_window *xw;
|
||||
w = (struct toplevel_window_widget *)cur->item;
|
||||
@@ -222,58 +213,84 @@ void x_events(gui *_gui)
|
||||
XEvent ev;
|
||||
XNextEvent(x->d, &ev);
|
||||
LOGD("XEV %d\n", ev.type);
|
||||
|
||||
switch (ev.type) {
|
||||
case MapNotify:
|
||||
case Expose:
|
||||
if ((w = find_x_window(g, ev.xexpose.window)) != NULL) {
|
||||
struct x_window *xw = w->x;
|
||||
xw->redraw = 1;
|
||||
}
|
||||
break;
|
||||
case ConfigureNotify:
|
||||
if ((w = find_x_window(g, ev.xconfigure.window)) != NULL) {
|
||||
struct x_window *xw = w->x;
|
||||
xw->resize = 1;
|
||||
xw->new_width = ev.xconfigure.width;
|
||||
xw->new_height = ev.xconfigure.height;
|
||||
if (xw->new_width < 10) xw->new_width = 10;
|
||||
if (xw->new_height < 10) xw->new_height = 10;
|
||||
LOGD("ConfigureNotify %d %d\n", ev.xconfigure.width, ev.xconfigure.height);
|
||||
}
|
||||
break;
|
||||
case ButtonPress:
|
||||
if ((w = find_x_window(g, ev.xbutton.window)) != NULL) {
|
||||
int key_modifiers = 0;
|
||||
if (ev.xbutton.state & ShiftMask) key_modifiers |= KEY_SHIFT;
|
||||
if (ev.xbutton.state & Mod1Mask) key_modifiers |= KEY_ALT;
|
||||
if (ev.xbutton.state & ControlMask) key_modifiers |= KEY_CONTROL;
|
||||
w->common.button(g, w, ev.xbutton.x, ev.xbutton.y, key_modifiers,
|
||||
ev.xbutton.button, 0);
|
||||
}
|
||||
break;
|
||||
case ButtonRelease:
|
||||
if ((w = find_x_window(g, ev.xbutton.window)) != NULL) {
|
||||
int key_modifiers = 0;
|
||||
if (ev.xbutton.state & ShiftMask) key_modifiers |= KEY_SHIFT;
|
||||
if (ev.xbutton.state & Mod1Mask) key_modifiers |= KEY_ALT;
|
||||
if (ev.xbutton.state & ControlMask) key_modifiers |= KEY_CONTROL;
|
||||
w->common.button(g, w, ev.xbutton.x, ev.xbutton.y, key_modifiers,
|
||||
ev.xbutton.button, 1);
|
||||
}
|
||||
break;
|
||||
default: if (gui_logd) WARN("TODO: X event type %d\n", ev.type); break;
|
||||
case MapNotify:
|
||||
case Expose:
|
||||
if ((w = find_x_window(g, ev.xexpose.window)) != NULL) {
|
||||
struct x_window *xw = w->x;
|
||||
xw->redraw = 1;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case ConfigureNotify:
|
||||
if ((w = find_x_window(g, ev.xconfigure.window)) != NULL) {
|
||||
struct x_window *xw = w->x;
|
||||
xw->resize = 1;
|
||||
xw->new_width = ev.xconfigure.width;
|
||||
xw->new_height = ev.xconfigure.height;
|
||||
|
||||
if (xw->new_width < 10) xw->new_width = 10;
|
||||
|
||||
if (xw->new_height < 10) xw->new_height = 10;
|
||||
|
||||
LOGD("ConfigureNotify %d %d\n", ev.xconfigure.width, ev.xconfigure.height);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case ButtonPress:
|
||||
if ((w = find_x_window(g, ev.xbutton.window)) != NULL) {
|
||||
int key_modifiers = 0;
|
||||
|
||||
if (ev.xbutton.state & ShiftMask) key_modifiers |= KEY_SHIFT;
|
||||
|
||||
if (ev.xbutton.state & Mod1Mask) key_modifiers |= KEY_ALT;
|
||||
|
||||
if (ev.xbutton.state & ControlMask) key_modifiers |= KEY_CONTROL;
|
||||
|
||||
w->common.button(g, w, ev.xbutton.x, ev.xbutton.y, key_modifiers,
|
||||
ev.xbutton.button, 0);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case ButtonRelease:
|
||||
if ((w = find_x_window(g, ev.xbutton.window)) != NULL) {
|
||||
int key_modifiers = 0;
|
||||
|
||||
if (ev.xbutton.state & ShiftMask) key_modifiers |= KEY_SHIFT;
|
||||
|
||||
if (ev.xbutton.state & Mod1Mask) key_modifiers |= KEY_ALT;
|
||||
|
||||
if (ev.xbutton.state & ControlMask) key_modifiers |= KEY_CONTROL;
|
||||
|
||||
w->common.button(g, w, ev.xbutton.x, ev.xbutton.y, key_modifiers,
|
||||
ev.xbutton.button, 1);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
if (gui_logd) WARN("TODO: X event type %d\n", ev.type);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* postprocessing */
|
||||
LOGD("post processing\n");
|
||||
cur = g->toplevel;
|
||||
|
||||
while (cur) {
|
||||
struct toplevel_window_widget *w =
|
||||
(struct toplevel_window_widget *)cur->item;
|
||||
(struct toplevel_window_widget *)cur->item;
|
||||
struct x_window *xw = w->x;
|
||||
|
||||
if (xw->resize) {
|
||||
LOGD("resize old %d %d new %d %d\n", xw->width, xw->height, xw->new_width, xw->new_height);
|
||||
|
||||
if (xw->width != xw->new_width || xw->height != xw->new_height) {
|
||||
w->common.allocate(g, w, 0, 0, xw->new_width, xw->new_height);
|
||||
xw->width = xw->new_width;
|
||||
@@ -281,46 +298,47 @@ void x_events(gui *_gui)
|
||||
XftDrawDestroy(xw->xft);
|
||||
XFreePixmap(x->d, xw->p);
|
||||
xw->p = XCreatePixmap(x->d, xw->w, xw->width, xw->height,
|
||||
DefaultDepth(x->d, DefaultScreen(x->d)));
|
||||
DefaultDepth(x->d, DefaultScreen(x->d)));
|
||||
XFillRectangle(x->d, xw->p, x->colors[BACKGROUND_COLOR],
|
||||
0, 0, xw->width, xw->height);
|
||||
0, 0, xw->width, xw->height);
|
||||
xw->xft = XftDrawCreate(x->d, xw->p,
|
||||
DefaultVisual(x->d, DefaultScreen(x->d)),
|
||||
DefaultColormap(x->d, DefaultScreen(x->d)));
|
||||
DefaultVisual(x->d, DefaultScreen(x->d)),
|
||||
DefaultColormap(x->d, DefaultScreen(x->d)));
|
||||
|
||||
if (xw->xft == NULL) ERR("XftDrawCreate failed\n");
|
||||
|
||||
//xw->repaint = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (xw->repaint) {
|
||||
w->common.paint(g, w);
|
||||
xw->redraw = 1;
|
||||
}
|
||||
|
||||
if (xw->redraw) {
|
||||
struct x_connection *x = g->x;
|
||||
LOGD("XCopyArea w h %d %d\n", xw->width, xw->height);
|
||||
XCopyArea(x->d, xw->p, xw->w, x->colors[1],
|
||||
0, 0, xw->width, xw->height, 0, 0);
|
||||
0, 0, xw->width, xw->height, 0, 0);
|
||||
}
|
||||
|
||||
cur = cur->next;
|
||||
}
|
||||
|
||||
LOGD("x_events DONE\n");
|
||||
}
|
||||
|
||||
void x_flush(x_connection *_x)
|
||||
{
|
||||
void x_flush(x_connection *_x) {
|
||||
struct x_connection *x = _x;
|
||||
XFlush(x->d);
|
||||
}
|
||||
|
||||
void x_text_get_dimensions(x_connection *_c, int font, const char *t,
|
||||
int *width, int *height, int *baseline)
|
||||
{
|
||||
int *width, int *height, int *baseline) {
|
||||
struct x_connection *c = _c;
|
||||
XGlyphInfo ext;
|
||||
|
||||
XftTextExtentsUtf8(c->d, c->fonts[font], (FcChar8 *)t, strlen(t), &ext);
|
||||
|
||||
*width = ext.width;
|
||||
*height = c->fonts[font]->height;
|
||||
*baseline = c->fonts[font]->ascent;
|
||||
@@ -331,63 +349,57 @@ void x_text_get_dimensions(x_connection *_c, int font, const char *t,
|
||||
/***********************************************************************/
|
||||
|
||||
void x_draw_line(x_connection *_c, x_window *_w, int color,
|
||||
int x1, int y1, int x2, int y2)
|
||||
{
|
||||
int x1, int y1, int x2, int y2) {
|
||||
struct x_connection *c = _c;
|
||||
struct x_window *w = _w;
|
||||
XDrawLine(c->d, w->p, c->colors[color], x1, y1, x2, y2);
|
||||
}
|
||||
|
||||
void x_draw_rectangle(x_connection *_c, x_window *_w, int color,
|
||||
int x, int y, int width, int height)
|
||||
{
|
||||
int x, int y, int width, int height) {
|
||||
struct x_connection *c = _c;
|
||||
struct x_window *w = _w;
|
||||
XDrawRectangle(c->d, w->p, c->colors[color], x, y, width, height);
|
||||
}
|
||||
|
||||
void x_fill_rectangle(x_connection *_c, x_window *_w, int color,
|
||||
int x, int y, int width, int height)
|
||||
{
|
||||
int x, int y, int width, int height) {
|
||||
struct x_connection *c = _c;
|
||||
struct x_window *w = _w;
|
||||
XFillRectangle(c->d, w->p, c->colors[color], x, y, width, height);
|
||||
}
|
||||
|
||||
void x_draw_string(x_connection *_c, x_window *_w, int font, int color,
|
||||
int x, int y, const char *t)
|
||||
{
|
||||
int x, int y, const char *t) {
|
||||
struct x_connection *c = _c;
|
||||
struct x_window *w = _w;
|
||||
int tlen = strlen(t);
|
||||
XftDrawStringUtf8(w->xft, &c->xft_colors[color], c->fonts[font],
|
||||
x, y, (const unsigned char *)t, tlen);
|
||||
x, y, (const unsigned char *)t, tlen);
|
||||
}
|
||||
|
||||
void x_draw_clipped_string(x_connection *_c, x_window *_w, int font,
|
||||
int color, int x, int y, const char *t,
|
||||
int clipx, int clipy, int clipwidth, int clipheight)
|
||||
{
|
||||
int color, int x, int y, const char *t,
|
||||
int clipx, int clipy, int clipwidth, int clipheight) {
|
||||
struct x_window *w = _w;
|
||||
|
||||
XRectangle clip = { clipx, clipy, clipwidth, clipheight };
|
||||
|
||||
if (XftDrawSetClipRectangles(w->xft, 0, 0, &clip, 1) == False) abort();
|
||||
|
||||
x_draw_string(_c, _w, font, color, x, y, t);
|
||||
|
||||
if (XftDrawSetClip(w->xft, NULL) == False) abort();
|
||||
}
|
||||
|
||||
void x_draw_image(x_connection *_c, x_window *_w, x_image *_img, int x, int y)
|
||||
{
|
||||
void x_draw_image(x_connection *_c, x_window *_w, x_image *_img, int x, int y) {
|
||||
struct x_connection *c = _c;
|
||||
struct x_window *w = _w;
|
||||
struct x_image *img = _img;
|
||||
|
||||
XCopyArea(c->d, img->p, w->p, DefaultGC(c->d, DefaultScreen(c->d)),
|
||||
0, 0, img->width, img->height, x, y);
|
||||
0, 0, img->width, img->height, x, y);
|
||||
}
|
||||
|
||||
void x_draw(x_connection *_c, x_window *_w)
|
||||
{
|
||||
void x_draw(x_connection *_c, x_window *_w) {
|
||||
struct x_connection *c = _c;
|
||||
struct x_window *w = _w;
|
||||
LOGD("x_draw XCopyArea w h %d %d display %p window %d pixmap %d\n", w->width, w->height, c->d, (int)w->w, (int)w->p);
|
||||
@@ -397,13 +409,13 @@ void x_draw(x_connection *_c, x_window *_w)
|
||||
/* those two special functions are to plot many points
|
||||
* first call x_add_point many times then x_plot_points once
|
||||
*/
|
||||
void x_add_point(x_connection *_c, int x, int y)
|
||||
{
|
||||
void x_add_point(x_connection *_c, int x, int y) {
|
||||
struct x_connection *c = _c;
|
||||
|
||||
if (c->pts_size == c->pts_maxsize) {
|
||||
c->pts_maxsize += 65536;
|
||||
c->pts = realloc(c->pts, c->pts_maxsize * sizeof(XPoint));
|
||||
|
||||
if (c->pts == NULL) OOM;
|
||||
}
|
||||
|
||||
@@ -412,12 +424,11 @@ void x_add_point(x_connection *_c, int x, int y)
|
||||
c->pts_size++;
|
||||
}
|
||||
|
||||
void x_plot_points(x_connection *_c, x_window *_w, int color)
|
||||
{
|
||||
void x_plot_points(x_connection *_c, x_window *_w, int color) {
|
||||
struct x_connection *c = _c;
|
||||
LOGD("x_plot_points %d points\n", c->pts_size);
|
||||
struct x_window *w = _w;
|
||||
XDrawPoints(c->d, w->p, c->colors[color], c->pts, c->pts_size,
|
||||
CoordModeOrigin);
|
||||
CoordModeOrigin);
|
||||
c->pts_size = 0;
|
||||
}
|
||||
|
||||
@@ -130,9 +130,13 @@ static void paint(gui *_gui, widget *_this)
|
||||
this->common.y + FLIP(y),
|
||||
this->common.x + this->vrule_width + 5,
|
||||
this->common.y + FLIP(y));
|
||||
/* do not print out of the widget (take care of top) */
|
||||
y = FLIP(y)-this->label_height/2+this->label_baseline;
|
||||
if (y - this->label_baseline < 0)
|
||||
y = this->label_baseline;
|
||||
x_draw_string(g->x, g->xwin, DEFAULT_FONT, FOREGROUND_COLOR,
|
||||
this->common.x + this->vrule_width - vwidth - 2,
|
||||
this->common.y + FLIP(y)-this->label_height/2+this->label_baseline,
|
||||
this->common.y + y,
|
||||
v);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -3,7 +3,7 @@ CFLAGS=-Wall -g -pthread -DT_TRACER -I. -I..
|
||||
|
||||
LIBS=-lX11 -lm -lpng -lXft
|
||||
|
||||
all: dump_nack_signal time_meas timeplot
|
||||
all: dump_nack_signal time_meas timeplot multi-rru-clean
|
||||
|
||||
dump_nack_signal: ../utils.o ../database.o ../config.o ../event.o \
|
||||
dump_nack_signal.o
|
||||
@@ -16,6 +16,9 @@ time_meas: ../utils.o ../database.o ../config.o ../event.o \
|
||||
timplot: timeplot.o
|
||||
$(CC) $(CFLAGS) -o timeplot $^ $(LIBS)
|
||||
|
||||
multi-rru-clean: ../utils.o ../database.o ../event.o ../config.o multi-rru-clean.o
|
||||
$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
|
||||
|
||||
.PHONY: all
|
||||
|
||||
%.o: %.c
|
||||
|
||||
@@ -7,21 +7,19 @@
|
||||
#include "config.h"
|
||||
#include "../T_defs.h"
|
||||
|
||||
void usage(void)
|
||||
{
|
||||
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
|
||||
"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)
|
||||
{
|
||||
int main(int n, char **v) {
|
||||
char *database_filename = NULL;
|
||||
void *database;
|
||||
char *ip = DEFAULT_REMOTE_IP;
|
||||
@@ -36,11 +34,28 @@ int main(int n, char **v)
|
||||
|
||||
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; }
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
@@ -50,71 +65,92 @@ int main(int n, char **v)
|
||||
}
|
||||
|
||||
database = parse_database(database_filename);
|
||||
|
||||
load_config_file(database_filename);
|
||||
|
||||
number_of_events = number_of_ids(database);
|
||||
is_on = calloc(number_of_events, sizeof(int));
|
||||
|
||||
if (is_on == NULL) abort();
|
||||
|
||||
on_off(database, "ENB_PHY_INPUT_SIGNAL", is_on, 1);
|
||||
on_off(database, "ENB_PHY_ULSCH_UE_NACK", is_on, 1);
|
||||
on_off(database, "ENB_PHY_ULSCH_UE_ACK", is_on, 1);
|
||||
|
||||
ev_input = event_id_from_name(database, "ENB_PHY_INPUT_SIGNAL");
|
||||
ev_nack = event_id_from_name(database, "ENB_PHY_ULSCH_UE_NACK");
|
||||
ev_ack = event_id_from_name(database, "ENB_PHY_ULSCH_UE_ACK");
|
||||
|
||||
socket = connect_to(ip, port);
|
||||
|
||||
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();
|
||||
|
||||
OBUF ebuf = { osize: 0, omaxsize: 0, obuf: NULL };
|
||||
|
||||
char dump[10][T_BUFFER_MAX];
|
||||
event dump_ev[10];
|
||||
FILE *z = fopen("/tmp/dd", "w"); if (z == NULL) abort();
|
||||
FILE *z = fopen("/tmp/dd", "w");
|
||||
|
||||
if (z == NULL) abort();
|
||||
|
||||
while (1) {
|
||||
char *v;
|
||||
event e;
|
||||
e = get_event(socket, &ebuf, database);
|
||||
v = ebuf.obuf;
|
||||
|
||||
if (e.type == -1) break;
|
||||
|
||||
if (e.type == ev_input) {
|
||||
int sf = e.e[2].i;
|
||||
if (ebuf.osize > T_BUFFER_MAX)
|
||||
{ printf("event size too big\n"); exit(1); }
|
||||
|
||||
if (ebuf.osize > T_BUFFER_MAX) {
|
||||
printf("event size too big\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
memcpy(dump[sf], ebuf.obuf, ebuf.osize);
|
||||
dump_ev[sf] = e;
|
||||
printf("input %d/%d\n", e.e[1].i, sf);
|
||||
if (fwrite(dump_ev[sf].e[4].b, dump_ev[sf].e[4].bsize, 1, z) != 1) abort();
|
||||
fflush(z);
|
||||
|
||||
if (fwrite(dump_ev[sf].e[4].b, dump_ev[sf].e[4].bsize, 1, z) != 1) abort();
|
||||
|
||||
fflush(z);
|
||||
}
|
||||
|
||||
if (e.type == ev_nack) {
|
||||
int sf = e.e[2].i;
|
||||
printf("nack %d/%d\n", e.e[1].i, sf);
|
||||
FILE *f = fopen("/tmp/dump.raw", "w"); if (f == NULL) abort();
|
||||
FILE *f = fopen("/tmp/dump.raw", "w");
|
||||
|
||||
if (f == NULL) abort();
|
||||
|
||||
if (fwrite(dump[sf] + ((char *)dump_ev[sf].e[4].b - v),
|
||||
dump_ev[sf].e[4].bsize, 1, f) != 1) abort();
|
||||
dump_ev[sf].e[4].bsize, 1, f) != 1) abort();
|
||||
|
||||
if (fclose(f)) abort();
|
||||
|
||||
printf("dumped... press enter (delta %d)\n", (int)((char *)dump_ev[sf].e[4].b - v));
|
||||
// getchar();
|
||||
// getchar();
|
||||
}
|
||||
|
||||
if (e.type == ev_ack) {
|
||||
int sf = e.e[2].i;
|
||||
printf("ack %d/%d\n", e.e[1].i, sf);
|
||||
FILE *f = fopen("/tmp/dump.raw", "w"); if (f == NULL) abort();
|
||||
FILE *f = fopen("/tmp/dump.raw", "w");
|
||||
|
||||
if (f == NULL) abort();
|
||||
|
||||
if (fwrite(dump[sf] + ((char *)dump_ev[sf].e[4].b - v),
|
||||
dump_ev[sf].e[4].bsize, 1, f) != 1) abort();
|
||||
dump_ev[sf].e[4].bsize, 1, f) != 1) abort();
|
||||
|
||||
if (fclose(f)) abort();
|
||||
|
||||
printf("dumped... press enter (delta %d)\n", (int)((char *)dump_ev[sf].e[4].b - v));
|
||||
// getchar();
|
||||
// getchar();
|
||||
}
|
||||
}
|
||||
if (z)
|
||||
fclose(z);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,230 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "database.h"
|
||||
#include "utils.h"
|
||||
#include "event.h"
|
||||
#include "../T_defs.h"
|
||||
|
||||
void usage(void)
|
||||
{
|
||||
printf(
|
||||
"usage: <number of tags> <input record file> <output curated record file>\n"
|
||||
"options:\n"
|
||||
" -d <database file> this option is mandatory\n"
|
||||
);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#define ERR printf("ERROR: read file %s failed\n", input_filename)
|
||||
|
||||
typedef struct {
|
||||
OBUF b;
|
||||
struct timespec t;
|
||||
int filled;
|
||||
int error;
|
||||
} cache_t;
|
||||
|
||||
void clear_cache(int n, cache_t *c)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < n; i++) {
|
||||
c[i].filled = 0;
|
||||
c[i].error = 0;
|
||||
c[i].b.osize = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void store_in_cache(cache_t *c, int pos, OBUF *b)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < b->osize; i++)
|
||||
PUTC(&c[pos].b, b->obuf[i]);
|
||||
}
|
||||
|
||||
int get_field(database_event_format *f, char *field, char *type)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < f->count; i++)
|
||||
if (!strcmp(f->name[i], field)) {
|
||||
if (strcmp(f->type[i], type)) break;
|
||||
return i;
|
||||
}
|
||||
printf("bad field %s, check that it exists and has type '%s'\n",field,type);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void process_cache(FILE *out, cache_t *c, int n, int frame, int subframe)
|
||||
{
|
||||
int i;
|
||||
struct tm *t;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
if (c[i].filled == 0 || c[i].error == 1)
|
||||
goto error;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
fwrite(c[i].b.obuf, c[i].b.osize, 1, out);
|
||||
|
||||
clear_cache(n, c);
|
||||
return;
|
||||
|
||||
error:
|
||||
printf("ERROR: incorrect data at frame %d subframe %d", frame, subframe);
|
||||
for (i = 0; i < n; i++) if (c[i].filled) {
|
||||
t = localtime(&c[i].t.tv_sec);
|
||||
printf(" [tag %d time %2.2d:%2.2d:%2.2d.%9.9ld]", i,
|
||||
t->tm_hour, t->tm_min, t->tm_sec, c[i].t.tv_nsec);
|
||||
}
|
||||
printf("\n");
|
||||
clear_cache(n, c);
|
||||
}
|
||||
|
||||
int main(int n, char **v)
|
||||
{
|
||||
char *database_filename = NULL;
|
||||
void *database;
|
||||
int channel_estimate_id;
|
||||
int number_of_tags = -1;
|
||||
char *input_filename = NULL;
|
||||
char *output_filename = NULL;
|
||||
int i;
|
||||
FILE *in;
|
||||
FILE *out;
|
||||
database_event_format f;
|
||||
int frame_arg;
|
||||
int subframe_arg;
|
||||
int tag_arg;
|
||||
|
||||
cache_t *cache;
|
||||
int cur_frame = -1;
|
||||
int cur_subframe = -1;
|
||||
int frame;
|
||||
int subframe;
|
||||
int tag;
|
||||
|
||||
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 (number_of_tags == -1) { number_of_tags = atoi(v[i]);
|
||||
if (number_of_tags <= 0) {usage();} continue; }
|
||||
if (input_filename == NULL) { input_filename = v[i]; continue; }
|
||||
if (output_filename == NULL) { output_filename = v[i]; continue; }
|
||||
usage();
|
||||
}
|
||||
|
||||
if (database_filename == NULL) {
|
||||
printf("ERROR: provide a database file (-d)\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (output_filename == NULL || input_filename == NULL || number_of_tags == -1)
|
||||
usage();
|
||||
|
||||
database = parse_database(database_filename);
|
||||
|
||||
channel_estimate_id = event_id_from_name(database, "CALIBRATION_CHANNEL_ESTIMATES");
|
||||
f = get_format(database, channel_estimate_id);
|
||||
|
||||
frame_arg = get_field(&f, "frame", "int");
|
||||
subframe_arg = get_field(&f, "subframe", "int");
|
||||
tag_arg = get_field(&f, "tag", "int");
|
||||
|
||||
in = fopen(input_filename, "r");
|
||||
if (in == NULL) { perror(input_filename); abort(); }
|
||||
out = fopen(output_filename, "w");
|
||||
if (out == NULL) { perror(output_filename); abort(); }
|
||||
|
||||
cache = calloc(number_of_tags, sizeof(cache_t));
|
||||
if (cache == NULL) { perror("malloc"); exit(1); }
|
||||
|
||||
clear_cache(number_of_tags, cache);
|
||||
|
||||
OBUF ebuf = { osize: 0, omaxsize: 0, obuf: NULL };
|
||||
|
||||
while (1) {
|
||||
int type;
|
||||
int32_t length;
|
||||
char *v;
|
||||
int vpos = 0;
|
||||
struct timespec t;
|
||||
char *buf;
|
||||
|
||||
/* read event from file */
|
||||
if (fread(&length, 4, 1, in) != 1) break;
|
||||
if (ebuf.omaxsize < length) {
|
||||
ebuf.omaxsize = (length + 65535) & ~65535;
|
||||
ebuf.obuf = realloc(ebuf.obuf, ebuf.omaxsize);
|
||||
if (ebuf.obuf == NULL) { printf("out of memory\n"); exit(1); }
|
||||
}
|
||||
v = ebuf.obuf;
|
||||
memcpy(v+vpos, &length, 4);
|
||||
vpos += 4;
|
||||
#ifdef T_SEND_TIME
|
||||
if (length < sizeof(struct timespec)) { ERR; break; }
|
||||
if (fread(&t, sizeof(struct timespec), 1, in) != 1) { ERR; break; }
|
||||
memcpy(v+vpos, &t, sizeof(struct timespec));
|
||||
vpos += sizeof(struct timespec);
|
||||
length -= sizeof(struct timespec);
|
||||
#endif
|
||||
if (length < sizeof(int)) { ERR; break; }
|
||||
if (fread(&type, sizeof(int), 1, in) != 1) { ERR; break; }
|
||||
memcpy(v+vpos, &type, sizeof(int));
|
||||
vpos += sizeof(int);
|
||||
length -= sizeof(int);
|
||||
if (length) if (fread(v+vpos, length, 1, in) != 1) { ERR; break; }
|
||||
buf = v + vpos;
|
||||
vpos += length;
|
||||
ebuf.osize = vpos;
|
||||
|
||||
if (type != channel_estimate_id) continue;
|
||||
|
||||
event e;
|
||||
#ifdef T_SEND_TIME
|
||||
e = new_event(t, type, length, buf, database);
|
||||
#else
|
||||
e = new_event(type, length, buf, database);
|
||||
#endif
|
||||
|
||||
frame = e.e[frame_arg].i;
|
||||
subframe = e.e[subframe_arg].i;
|
||||
tag = e.e[tag_arg].i;
|
||||
|
||||
if (tag < 0 || tag >= number_of_tags) {
|
||||
struct tm *tt;
|
||||
tt = localtime(&t.tv_sec);
|
||||
printf("ERROR: invalid tag (%d), skipping event for frame %d subframe %d (time %2.2d:%2.2d:%2.2d.%9.9ld)\n",
|
||||
tag, frame, subframe,
|
||||
tt->tm_hour, tt->tm_min, tt->tm_sec, t.tv_nsec);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cur_frame != frame || cur_subframe != subframe)
|
||||
if (cur_frame != -1)
|
||||
process_cache(out, cache, number_of_tags, cur_frame, cur_subframe);
|
||||
|
||||
cur_frame = frame;
|
||||
cur_subframe = subframe;
|
||||
|
||||
if (cache[tag].filled) {
|
||||
struct tm *tt;
|
||||
tt = localtime(&t.tv_sec);
|
||||
printf("ERROR: tag %d present twice at frame %d subframe %d (time %2.2d:%2.2d:%2.2d.%9.9ld)\n",
|
||||
tag, frame, subframe,
|
||||
tt->tm_hour, tt->tm_min, tt->tm_sec, t.tv_nsec);
|
||||
cache[tag].error = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
store_in_cache(cache, tag, &ebuf);
|
||||
cache[tag].filled = 1;
|
||||
cache[tag].t = t;
|
||||
}
|
||||
|
||||
if (fclose(in)) perror(input_filename);
|
||||
if (fclose(out)) perror(output_filename);
|
||||
free(cache);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -30,6 +30,7 @@ void framelog_set_skip(logger *_this, int skip_delay);
|
||||
void framelog_set_update_only_at_sf9(logger *_this, int update_only_at_sf9);
|
||||
|
||||
void textlog_dump_buffer(logger *_this, int dump_buffer);
|
||||
void textlog_raw_time(logger *_this, int raw_time);
|
||||
|
||||
#include "view/view.h"
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ struct textlog {
|
||||
/* local output buffer */
|
||||
OBUF o;
|
||||
int dump_buffer;
|
||||
int raw_time;
|
||||
};
|
||||
|
||||
static void _event(void *p, event e)
|
||||
@@ -51,9 +52,13 @@ static void _event(void *p, event e)
|
||||
|
||||
#ifdef T_SEND_TIME
|
||||
t = localtime(&e.sending_time.tv_sec);
|
||||
/* round tv_nsec to nearest millisecond */
|
||||
sprintf(tt, "%2.2d:%2.2d:%2.2d.%9.9ld: ", t->tm_hour, t->tm_min, t->tm_sec,
|
||||
e.sending_time.tv_nsec);
|
||||
if (l->raw_time)
|
||||
sprintf(tt, "%2.2d:%2.2d:%2.2d.%9.9ld [%ld]: ",
|
||||
t->tm_hour, t->tm_min, t->tm_sec,
|
||||
e.sending_time.tv_nsec, e.sending_time.tv_sec);
|
||||
else
|
||||
sprintf(tt, "%2.2d:%2.2d:%2.2d.%9.9ld: ", t->tm_hour, t->tm_min, t->tm_sec,
|
||||
e.sending_time.tv_nsec);
|
||||
PUTS(&l->o, tt);
|
||||
#endif
|
||||
|
||||
@@ -215,3 +220,9 @@ void textlog_dump_buffer(logger *_this, int dump_buffer)
|
||||
struct textlog *l = _this;
|
||||
l->dump_buffer = dump_buffer;
|
||||
}
|
||||
|
||||
void textlog_raw_time(logger *_this, int raw_time)
|
||||
{
|
||||
struct textlog *l = _this;
|
||||
l->raw_time = raw_time;
|
||||
}
|
||||
|
||||
@@ -14,6 +14,11 @@
|
||||
#define DEFAULT_IP "127.0.0.1"
|
||||
#define DEFAULT_PORT 9999
|
||||
|
||||
#define DEFAULT_LIVE_IP "127.0.0.1"
|
||||
#define DEFAULT_LIVE_PORT 2021
|
||||
|
||||
#define NO_PREAMBLE -1
|
||||
|
||||
typedef struct {
|
||||
int socket;
|
||||
struct sockaddr_in to;
|
||||
@@ -28,142 +33,241 @@ typedef struct {
|
||||
int dl_frame;
|
||||
int dl_subframe;
|
||||
int dl_data;
|
||||
/* mib */
|
||||
int mib_frame;
|
||||
int mib_subframe;
|
||||
int mib_data;
|
||||
/* RA preamble */
|
||||
int preamble_frame;
|
||||
int preamble_subframe;
|
||||
int preamble_preamble;
|
||||
/* RAR */
|
||||
int rar_rnti;
|
||||
int rar_frame;
|
||||
int rar_subframe;
|
||||
int rar_data;
|
||||
/* config */
|
||||
int no_mib;
|
||||
int no_sib;
|
||||
int max_mib;
|
||||
int max_sib;
|
||||
int live;
|
||||
/* runtime vars */
|
||||
int cur_mib;
|
||||
int cur_sib;
|
||||
} ev_data;
|
||||
|
||||
void ul(void *_d, event e)
|
||||
{
|
||||
ev_data *d = _d;
|
||||
void trace(ev_data *d, int direction, int rnti_type, int rnti,
|
||||
int frame, int subframe, void *buf, int bufsize, int preamble) {
|
||||
ssize_t ret;
|
||||
int fsf;
|
||||
int i;
|
||||
|
||||
d->buf.osize = 0;
|
||||
|
||||
PUTS(&d->buf, MAC_LTE_START_STRING);
|
||||
PUTC(&d->buf, FDD_RADIO);
|
||||
PUTC(&d->buf, DIRECTION_UPLINK);
|
||||
PUTC(&d->buf, C_RNTI);
|
||||
PUTC(&d->buf, direction);
|
||||
PUTC(&d->buf, rnti_type);
|
||||
|
||||
PUTC(&d->buf, MAC_LTE_RNTI_TAG);
|
||||
PUTC(&d->buf, (e.e[d->ul_rnti].i>>8) & 255);
|
||||
PUTC(&d->buf, e.e[d->ul_rnti].i & 255);
|
||||
if (rnti_type == C_RNTI || rnti_type == RA_RNTI) {
|
||||
PUTC(&d->buf, MAC_LTE_RNTI_TAG);
|
||||
PUTC(&d->buf, (rnti>>8) & 255);
|
||||
PUTC(&d->buf, rnti & 255);
|
||||
}
|
||||
|
||||
/* for newer version of wireshark? */
|
||||
fsf = (e.e[d->ul_frame].i << 4) + e.e[d->ul_subframe].i;
|
||||
fsf = (frame << 4) + subframe;
|
||||
/* for older version? */
|
||||
fsf = e.e[d->ul_subframe].i;
|
||||
//fsf = subframe;
|
||||
PUTC(&d->buf, MAC_LTE_FRAME_SUBFRAME_TAG);
|
||||
PUTC(&d->buf, (fsf>>8) & 255);
|
||||
PUTC(&d->buf, fsf & 255);
|
||||
|
||||
if (preamble != NO_PREAMBLE) {
|
||||
PUTC(&d->buf, MAC_LTE_SEND_PREAMBLE_TAG);
|
||||
PUTC(&d->buf, preamble);
|
||||
PUTC(&d->buf, 0); /* rach attempt - always 0 for us (not sure of this) */
|
||||
}
|
||||
|
||||
PUTC(&d->buf, MAC_LTE_PAYLOAD_TAG);
|
||||
for (i = 0; i < e.e[d->ul_data].bsize; i++)
|
||||
PUTC(&d->buf, ((char*)e.e[d->ul_data].b)[i]);
|
||||
|
||||
for (i = 0; i < bufsize; i++)
|
||||
PUTC(&d->buf, ((char *)buf)[i]);
|
||||
|
||||
ret = sendto(d->socket, d->buf.obuf, d->buf.osize, 0,
|
||||
(struct sockaddr *)&d->to, sizeof(struct sockaddr_in));
|
||||
(struct sockaddr *)&d->to, sizeof(struct sockaddr_in));
|
||||
|
||||
if (ret != d->buf.osize) abort();
|
||||
}
|
||||
|
||||
void dl(void *_d, event e)
|
||||
{
|
||||
void ul(void *_d, event e) {
|
||||
ev_data *d = _d;
|
||||
ssize_t ret;
|
||||
int fsf;
|
||||
int i;
|
||||
|
||||
d->buf.osize = 0;
|
||||
|
||||
PUTS(&d->buf, MAC_LTE_START_STRING);
|
||||
PUTC(&d->buf, FDD_RADIO);
|
||||
PUTC(&d->buf, DIRECTION_DOWNLINK);
|
||||
PUTC(&d->buf, C_RNTI);
|
||||
|
||||
PUTC(&d->buf, MAC_LTE_RNTI_TAG);
|
||||
PUTC(&d->buf, (e.e[d->dl_rnti].i>>8) & 255);
|
||||
PUTC(&d->buf, e.e[d->dl_rnti].i & 255);
|
||||
|
||||
/* for newer version of wireshark? */
|
||||
fsf = (e.e[d->dl_frame].i << 4) + e.e[d->dl_subframe].i;
|
||||
/* for older version? */
|
||||
fsf = e.e[d->dl_subframe].i;
|
||||
PUTC(&d->buf, MAC_LTE_FRAME_SUBFRAME_TAG);
|
||||
PUTC(&d->buf, (fsf>>8) & 255);
|
||||
PUTC(&d->buf, fsf & 255);
|
||||
|
||||
PUTC(&d->buf, MAC_LTE_PAYLOAD_TAG);
|
||||
for (i = 0; i < e.e[d->dl_data].bsize; i++)
|
||||
PUTC(&d->buf, ((char*)e.e[d->dl_data].b)[i]);
|
||||
|
||||
ret = sendto(d->socket, d->buf.obuf, d->buf.osize, 0,
|
||||
(struct sockaddr *)&d->to, sizeof(struct sockaddr_in));
|
||||
if (ret != d->buf.osize) abort();
|
||||
trace(d, DIRECTION_UPLINK, C_RNTI, e.e[d->ul_rnti].i,
|
||||
e.e[d->ul_frame].i, e.e[d->ul_subframe].i,
|
||||
e.e[d->ul_data].b, e.e[d->ul_data].bsize,
|
||||
NO_PREAMBLE);
|
||||
}
|
||||
|
||||
void setup_data(ev_data *d, void *database, int ul_id, int dl_id)
|
||||
{
|
||||
void dl(void *_d, event e) {
|
||||
ev_data *d = _d;
|
||||
|
||||
if (e.e[d->dl_rnti].i == 0xffff) {
|
||||
if (d->no_sib) return;
|
||||
|
||||
if (d->max_sib && d->cur_sib == d->max_sib) return;
|
||||
|
||||
d->cur_sib++;
|
||||
}
|
||||
|
||||
trace(d, DIRECTION_DOWNLINK,
|
||||
e.e[d->dl_rnti].i != 0xffff ? C_RNTI : SI_RNTI, e.e[d->dl_rnti].i,
|
||||
e.e[d->dl_frame].i, e.e[d->dl_subframe].i,
|
||||
e.e[d->dl_data].b, e.e[d->dl_data].bsize,
|
||||
NO_PREAMBLE);
|
||||
}
|
||||
|
||||
void mib(void *_d, event e) {
|
||||
ev_data *d = _d;
|
||||
|
||||
if (d->no_mib) return;
|
||||
|
||||
if (d->max_mib && d->cur_mib == d->max_mib) return;
|
||||
|
||||
d->cur_mib++;
|
||||
trace(d, DIRECTION_DOWNLINK, NO_RNTI, 0,
|
||||
e.e[d->mib_frame].i, e.e[d->mib_subframe].i,
|
||||
e.e[d->mib_data].b, e.e[d->mib_data].bsize,
|
||||
NO_PREAMBLE);
|
||||
}
|
||||
|
||||
void preamble(void *_d, event e) {
|
||||
ev_data *d = _d;
|
||||
trace(d, DIRECTION_UPLINK, NO_RNTI, 0,
|
||||
e.e[d->preamble_frame].i, e.e[d->preamble_subframe].i,
|
||||
NULL, 0,
|
||||
e.e[d->preamble_preamble].i);
|
||||
}
|
||||
|
||||
void rar(void *_d, event e) {
|
||||
ev_data *d = _d;
|
||||
trace(d, DIRECTION_DOWNLINK, RA_RNTI, e.e[d->rar_rnti].i,
|
||||
e.e[d->rar_frame].i, e.e[d->rar_subframe].i,
|
||||
e.e[d->rar_data].b, e.e[d->rar_data].bsize,
|
||||
NO_PREAMBLE);
|
||||
}
|
||||
|
||||
void setup_data(ev_data *d, void *database, int ul_id, int dl_id, int mib_id,
|
||||
int preamble_id, int rar_id) {
|
||||
database_event_format f;
|
||||
int i;
|
||||
|
||||
d->ul_rnti = -1;
|
||||
d->ul_frame = -1;
|
||||
d->ul_subframe = -1;
|
||||
d->ul_data = -1;
|
||||
|
||||
d->dl_rnti = -1;
|
||||
d->dl_frame = -1;
|
||||
d->dl_subframe = -1;
|
||||
d->dl_data = -1;
|
||||
|
||||
d->ul_rnti = -1;
|
||||
d->ul_frame = -1;
|
||||
d->ul_subframe = -1;
|
||||
d->ul_data = -1;
|
||||
d->dl_rnti = -1;
|
||||
d->dl_frame = -1;
|
||||
d->dl_subframe = -1;
|
||||
d->dl_data = -1;
|
||||
d->mib_frame = -1;
|
||||
d->mib_subframe = -1;
|
||||
d->mib_data = -1;
|
||||
d->preamble_frame = -1;
|
||||
d->preamble_subframe = -1;
|
||||
d->preamble_preamble = -1;
|
||||
d->rar_rnti = -1;
|
||||
d->rar_frame = -1;
|
||||
d->rar_subframe = -1;
|
||||
d->rar_data = -1;
|
||||
#define G(var_name, var_type, var) \
|
||||
if (!strcmp(f.name[i], var_name)) { \
|
||||
if (strcmp(f.type[i], var_type)) goto error; \
|
||||
var = i; \
|
||||
continue; \
|
||||
}
|
||||
|
||||
/* ul: rnti, frame, subframe, data */
|
||||
f = get_format(database, ul_id);
|
||||
|
||||
for (i = 0; i < f.count; i++) {
|
||||
G("rnti", "int", d->ul_rnti);
|
||||
G("frame", "int", d->ul_frame);
|
||||
G("subframe", "int", d->ul_subframe);
|
||||
G("data", "buffer", d->ul_data);
|
||||
}
|
||||
|
||||
if (d->ul_rnti == -1 || d->ul_frame == -1 || d->ul_subframe == -1 ||
|
||||
d->ul_data == -1) goto error;
|
||||
|
||||
/* dl: rnti, frame, subframe, data */
|
||||
f = get_format(database, dl_id);
|
||||
|
||||
for (i = 0; i < f.count; i++) {
|
||||
G("rnti", "int", d->dl_rnti);
|
||||
G("frame", "int", d->dl_frame);
|
||||
G("subframe", "int", d->dl_subframe);
|
||||
G("data", "buffer", d->dl_data);
|
||||
}
|
||||
|
||||
if (d->dl_rnti == -1 || d->dl_frame == -1 || d->dl_subframe == -1 ||
|
||||
d->dl_data == -1) goto error;
|
||||
|
||||
/* MIB: frame, subframe, data */
|
||||
f = get_format(database, mib_id);
|
||||
|
||||
for (i = 0; i < f.count; i++) {
|
||||
G("frame", "int", d->mib_frame);
|
||||
G("subframe", "int", d->mib_subframe);
|
||||
G("data", "buffer", d->mib_data);
|
||||
}
|
||||
|
||||
if (d->mib_frame == -1 || d->mib_subframe == -1 || d->mib_data == -1)
|
||||
goto error;
|
||||
|
||||
/* preamble: frame, subframe, preamble */
|
||||
f = get_format(database, preamble_id);
|
||||
|
||||
for (i = 0; i < f.count; i++) {
|
||||
G("frame", "int", d->preamble_frame);
|
||||
G("subframe", "int", d->preamble_subframe);
|
||||
G("preamble", "int", d->preamble_preamble);
|
||||
}
|
||||
|
||||
if (d->preamble_frame == -1 || d->preamble_subframe == -1 ||
|
||||
d->preamble_preamble == -1) goto error;
|
||||
|
||||
/* rar: rnti, frame, subframe, data */
|
||||
f = get_format(database, rar_id);
|
||||
|
||||
for (i = 0; i < f.count; i++) {
|
||||
G("rnti", "int", d->rar_rnti);
|
||||
G("frame", "int", d->rar_frame);
|
||||
G("subframe", "int", d->rar_subframe);
|
||||
G("data", "buffer", d->rar_data);
|
||||
}
|
||||
|
||||
if (d->rar_rnti == -1 || d->rar_frame == -1 || d->rar_subframe == -1 ||
|
||||
d->rar_data == -1) goto error;
|
||||
|
||||
#undef G
|
||||
|
||||
return;
|
||||
|
||||
error:
|
||||
printf("bad T_messages.txt\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
void *receiver(void *_d)
|
||||
{
|
||||
void *receiver(void *_d) {
|
||||
ev_data *d = _d;
|
||||
int s;
|
||||
char buf[100000];
|
||||
|
||||
s = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (s == -1) { perror("socket"); abort(); }
|
||||
|
||||
if (bind(s, (struct sockaddr *)&d->to, sizeof(struct sockaddr_in)) == -1)
|
||||
{ perror("bind"); abort(); }
|
||||
if (s == -1) {
|
||||
perror("socket");
|
||||
abort();
|
||||
}
|
||||
|
||||
if (bind(s, (struct sockaddr *)&d->to, sizeof(struct sockaddr_in)) == -1) {
|
||||
perror("bind");
|
||||
abort();
|
||||
}
|
||||
|
||||
while (1) {
|
||||
if (recv(s, buf, 100000, 0) <= 0) abort();
|
||||
@@ -172,43 +276,120 @@ void *receiver(void *_d)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void usage(void)
|
||||
{
|
||||
void usage(void) {
|
||||
printf(
|
||||
"options:\n"
|
||||
" -d <database file> this option is mandatory\n"
|
||||
" -i <dump file> read events from this dump file\n"
|
||||
" -ip <IP address> send packets to this IP address (default %s)\n"
|
||||
" -p <port> send packets to this port (default %d)\n",
|
||||
DEFAULT_IP,
|
||||
DEFAULT_PORT
|
||||
"options:\n"
|
||||
" -d <database file> this option is mandatory\n"
|
||||
" -i <dump file> read events from this dump file\n"
|
||||
" -ip <IP address> send packets to this IP address (default %s)\n"
|
||||
" -p <port> send packets to this port (default %d)\n"
|
||||
" -no-mib do not report MIB\n"
|
||||
" -no-sib do not report SIBs\n"
|
||||
" -max-mib <n> report at maximum n MIB\n"
|
||||
" -max-sib <n> report at maximum n SIBs\n"
|
||||
" -live run live\n"
|
||||
" -live-ip <IP address> tracee's IP address (default %s)\n"
|
||||
" -live-port <port> tracee's port (default %d)\n"
|
||||
"-i and -live are mutually exclusive options. One of them must be provided\n"
|
||||
"but not both.\n",
|
||||
DEFAULT_IP,
|
||||
DEFAULT_PORT,
|
||||
DEFAULT_LIVE_IP,
|
||||
DEFAULT_LIVE_PORT
|
||||
);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int main(int n, char **v)
|
||||
{
|
||||
int main(int n, char **v) {
|
||||
char *database_filename = NULL;
|
||||
char *input_filename = NULL;
|
||||
void *database;
|
||||
event_handler *h;
|
||||
int in;
|
||||
int i;
|
||||
int ul_id, dl_id;
|
||||
int ul_id, dl_id, mib_id = -1, preamble_id, rar_id;
|
||||
ev_data d;
|
||||
char *ip = DEFAULT_IP;
|
||||
int port = DEFAULT_PORT;
|
||||
|
||||
char *live_ip = DEFAULT_LIVE_IP;
|
||||
int live_port = DEFAULT_LIVE_PORT;
|
||||
int live = 0;
|
||||
memset(&d, 0, sizeof(ev_data));
|
||||
|
||||
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], "-i"))
|
||||
{ if (i > n-2) usage(); input_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; }
|
||||
|
||||
if (!strcmp(v[i], "-d")) {
|
||||
if (i > n-2) usage();
|
||||
|
||||
database_filename = v[++i];
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(v[i], "-i")) {
|
||||
if (i > n-2) usage();
|
||||
|
||||
input_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;
|
||||
}
|
||||
|
||||
if (!strcmp(v[i], "-no-mib")) {
|
||||
d.no_mib = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(v[i], "-no-sib")) {
|
||||
d.no_sib = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(v[i], "-max-mib")) {
|
||||
if (i > n-2) usage();
|
||||
|
||||
d.max_mib = atoi(v[++i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(v[i], "-max-sib")) {
|
||||
if (i > n-2) usage();
|
||||
|
||||
d.max_sib = atoi(v[++i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(v[i], "-live")) {
|
||||
live = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(v[i], "-live-ip")) {
|
||||
if (i > n-2) usage();
|
||||
|
||||
live_ip = v[++i];
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(v[i], "-live-port")) {
|
||||
if (i > n-2) usage();
|
||||
|
||||
live_port = atoi(v[++i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
usage();
|
||||
}
|
||||
|
||||
@@ -217,43 +398,91 @@ int main(int n, char **v)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (input_filename == NULL) {
|
||||
printf("ERROR: provide an input file (-i)\n");
|
||||
if (input_filename == NULL && live == 0) {
|
||||
printf("ERROR: provide an input file (-i) or run live (-live)\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
in = open(input_filename, O_RDONLY);
|
||||
if (in == -1) { perror(input_filename); return 1; }
|
||||
if (input_filename != NULL && live != 0) {
|
||||
printf("ERROR: cannot use both -i and -live\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (live == 0) {
|
||||
in = open(input_filename, O_RDONLY);
|
||||
|
||||
if (in == -1) {
|
||||
perror(input_filename);
|
||||
return 1;
|
||||
}
|
||||
} else
|
||||
in = connect_to(live_ip, live_port);
|
||||
|
||||
database = parse_database(database_filename);
|
||||
load_config_file(database_filename);
|
||||
|
||||
h = new_handler(database);
|
||||
|
||||
if (live) {
|
||||
char mt = 1;
|
||||
int number_of_events = number_of_ids(database);
|
||||
int *is_on = calloc(number_of_events, sizeof(int));
|
||||
|
||||
if (is_on == NULL) {
|
||||
printf("ERROR: out of memory\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
on_off(database, "ENB_MAC_UE_UL_PDU_WITH_DATA", is_on, 1);
|
||||
on_off(database, "ENB_MAC_UE_DL_PDU_WITH_DATA", is_on, 1);
|
||||
on_off(database, "ENB_PHY_MIB", is_on, 1);
|
||||
on_off(database, "ENB_PHY_INITIATE_RA_PROCEDURE", is_on, 1);
|
||||
on_off(database, "ENB_MAC_UE_DL_RAR_PDU_WITH_DATA", is_on, 1);
|
||||
|
||||
/* activate selected traces */
|
||||
if (socket_send(in, &mt, 1) == -1 ||
|
||||
socket_send(in, &number_of_events, sizeof(int)) == -1 ||
|
||||
socket_send(in, is_on, number_of_events * sizeof(int)) == -1) {
|
||||
printf("ERROR: socket_send failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
free(is_on);
|
||||
}
|
||||
|
||||
ul_id = event_id_from_name(database, "ENB_MAC_UE_UL_PDU_WITH_DATA");
|
||||
dl_id = event_id_from_name(database, "ENB_MAC_UE_DL_PDU_WITH_DATA");
|
||||
setup_data(&d, database, ul_id, dl_id);
|
||||
|
||||
mib_id = event_id_from_name(database, "ENB_PHY_MIB");
|
||||
preamble_id = event_id_from_name(database, "ENB_PHY_INITIATE_RA_PROCEDURE");
|
||||
rar_id = event_id_from_name(database, "ENB_MAC_UE_DL_RAR_PDU_WITH_DATA");
|
||||
setup_data(&d, database, ul_id, dl_id, mib_id, preamble_id, rar_id);
|
||||
register_handler_function(h, ul_id, ul, &d);
|
||||
register_handler_function(h, dl_id, dl, &d);
|
||||
|
||||
register_handler_function(h, mib_id, mib, &d);
|
||||
register_handler_function(h, preamble_id, preamble, &d);
|
||||
register_handler_function(h, rar_id, rar, &d);
|
||||
d.socket = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (d.socket == -1) { perror("socket"); exit(1); }
|
||||
|
||||
if (d.socket == -1) {
|
||||
perror("socket");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
d.to.sin_family = AF_INET;
|
||||
d.to.sin_port = htons(port);
|
||||
d.to.sin_addr.s_addr = inet_addr(ip);
|
||||
|
||||
new_thread(receiver, &d);
|
||||
|
||||
OBUF ebuf = { osize: 0, omaxsize: 0, obuf: NULL };
|
||||
|
||||
/* read messages */
|
||||
while (1) {
|
||||
event e;
|
||||
e = get_event(in, &ebuf, database);
|
||||
|
||||
if (e.type == -1) break;
|
||||
if (!(e.type == ul_id || e.type == dl_id)) continue;
|
||||
|
||||
if (!(e.type == ul_id || e.type == dl_id || e.type == mib_id ||
|
||||
e.type == preamble_id || e.type == rar_id)) continue;
|
||||
|
||||
handle_event(h, e);
|
||||
}
|
||||
|
||||
|
||||
@@ -52,6 +52,7 @@ void usage(void)
|
||||
" they will be processed in order\n"
|
||||
" by default, all is off\n"
|
||||
" -full also dump buffers' content\n"
|
||||
" -raw-time also prints 'raw time'\n"
|
||||
" -ip <host> connect to given IP address (default %s)\n"
|
||||
" -p <port> connect to given port (default %d)\n"
|
||||
" -x GUI output\n"
|
||||
@@ -91,6 +92,7 @@ int main(int n, char **v)
|
||||
int gui_active = 1;
|
||||
textlog_data textlog_data;
|
||||
int full = 0;
|
||||
int raw_time = 0;
|
||||
|
||||
/* write on a socket fails if the other end is closed and we get SIGPIPE */
|
||||
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) abort();
|
||||
@@ -117,6 +119,7 @@ int main(int n, char **v)
|
||||
if (!strcmp(v[i], "-debug-gui")) { gui_logd = 1; continue; }
|
||||
if (!strcmp(v[i], "-no-gui")) { gui_active = 0; continue; }
|
||||
if (!strcmp(v[i], "-full")) { full = 1; continue; }
|
||||
if (!strcmp(v[i], "-raw-time")) { raw_time = 1; continue; }
|
||||
usage();
|
||||
}
|
||||
|
||||
@@ -162,6 +165,7 @@ int main(int n, char **v)
|
||||
// "ev: {} eNB_id [eNB_ID] frame [frame] subframe [subframe]");
|
||||
logger_add_view(textlog, out);
|
||||
if (full) textlog_dump_buffer(textlog, 1);
|
||||
if (raw_time) textlog_raw_time(textlog, 1);
|
||||
free(name);
|
||||
free(desc);
|
||||
}
|
||||
@@ -187,9 +191,12 @@ int main(int n, char **v)
|
||||
while (1) {
|
||||
event e;
|
||||
e = get_event(textlog_data.socket, &ebuf, database);
|
||||
if (e.type == -1) abort();
|
||||
if (e.type == -1) break;
|
||||
handle_event(h, e);
|
||||
}
|
||||
|
||||
free(on_off_name);
|
||||
free(on_off_action);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
+102
-197
@@ -23,9 +23,6 @@ typedef struct {
|
||||
view *pdcpview;
|
||||
view *rrcview;
|
||||
view *legacy;
|
||||
widget *current_ue_label;
|
||||
widget *prev_ue_button;
|
||||
widget *next_ue_button;
|
||||
widget *pdsch_iq_ue_xy_plot;
|
||||
widget *dl_estimate_ue_xy_plot;
|
||||
widget *pdcch_energy_ue_xy_plot;
|
||||
@@ -121,15 +118,14 @@ static void *gui_thread(void *_g)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static filter *ticktime_filter(void *database, char *event, int i, int ue)
|
||||
static filter *ticktime_filter(void *database, char *event, int i)
|
||||
{
|
||||
/* filter is "harq_pid == i && UE_id == 0 && eNB_id == 0" */
|
||||
/* filter is "harq_pid == i and eNB_id == 0" */
|
||||
return
|
||||
filter_and(
|
||||
filter_eq(filter_evarg(database, event, "harq_pid"), filter_int(i)),
|
||||
filter_and(
|
||||
filter_eq(filter_evarg(database, event, "UE_id"), filter_int(ue)),
|
||||
filter_eq(filter_evarg(database, event, "eNB_ID"), filter_int(0))));
|
||||
filter_eq(filter_evarg(database, event, "eNB_ID"), filter_int(0)));
|
||||
|
||||
}
|
||||
|
||||
static void set_current_ue(gui *g, ue_data *e, int ue)
|
||||
@@ -137,8 +133,6 @@ static void set_current_ue(gui *g, ue_data *e, int ue)
|
||||
int i;
|
||||
char s[256];
|
||||
|
||||
sprintf(s, "[UE %d] ", ue);
|
||||
label_set_text(g, e->e->current_ue_label, s);
|
||||
sprintf(s, "PDSCH IQ [UE %d]", ue);
|
||||
xy_plot_set_title(g, e->e->pdsch_iq_ue_xy_plot, s);
|
||||
sprintf(s, "DL estimated channel [UE %d]", ue);
|
||||
@@ -161,97 +155,24 @@ static void set_current_ue(gui *g, ue_data *e, int ue)
|
||||
xy_plot_set_title(g, e->e->pucch_power_xy_plot, s);
|
||||
sprintf(s, "PHY Measurements [UE %d]", ue);
|
||||
xy_plot_set_title(g, e->e->phy_meas_xy_plot, s);
|
||||
|
||||
logger_set_filter(e->e->pdsch_iq_ue_logger,
|
||||
filter_eq(
|
||||
filter_evarg(e->database, "UE_PHY_PDSCH_IQ", "UE_ID"),
|
||||
filter_int(ue)));
|
||||
logger_set_filter(e->e->dl_estimate_ue_logger,
|
||||
filter_eq(
|
||||
filter_evarg(e->database, "UE_PHY_DL_CHANNEL_ESTIMATE", "UE_ID"),
|
||||
filter_int(ue)));
|
||||
logger_set_filter(e->e->pdcch_energy_logger,
|
||||
filter_eq(
|
||||
filter_evarg(e->database, "UE_PHY_PDCCH_ENERGY", "UE_ID"),
|
||||
filter_int(ue)));
|
||||
logger_set_filter(e->e->pdsch_energy_logger,
|
||||
filter_eq(
|
||||
filter_evarg(e->database, "UE_PHY_PDSCH_ENERGY", "UE_ID"),
|
||||
filter_int(ue)));
|
||||
logger_set_filter(e->e->phy_meas_logger,
|
||||
filter_eq(
|
||||
filter_evarg(e->database, "UE_PHY_MEAS", "UE_ID"),
|
||||
filter_int(ue)));
|
||||
/*logger_set_filter(e->pucch1_energy_ue_energy_logger,
|
||||
filter_eq(
|
||||
filter_evarg(e->database, "ENB_PHY_PUCCH_1_ENERGY", "UE_ID"),
|
||||
filter_int(ue)));*/
|
||||
/*logger_set_filter(e->e->pdcch_iq_ue_logger,
|
||||
filter_eq(
|
||||
filter_evarg(e->database, "UE_PHY_PDCCH_IQ", "UE_ID"),
|
||||
filter_int(ue)));*/
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
logger_set_filter(e->e->dl_dci_logger[i],
|
||||
ticktime_filter(e->database, "UE_PHY_DLSCH_UE_DCI", i, ue));
|
||||
ticktime_filter(e->database, "UE_PHY_DLSCH_UE_DCI", i));
|
||||
logger_set_filter(e->e->dl_ack_logger[i],
|
||||
ticktime_filter(e->database, "UE_PHY_DLSCH_UE_ACK", i, ue));
|
||||
ticktime_filter(e->database, "UE_PHY_DLSCH_UE_ACK", i));
|
||||
logger_set_filter(e->e->dl_nack_logger[i],
|
||||
ticktime_filter(e->database, "UE_PHY_DLSCH_UE_NACK", i, ue));
|
||||
ticktime_filter(e->database, "UE_PHY_DLSCH_UE_NACK", i));
|
||||
logger_set_filter(e->e->ul_dci_logger[i],
|
||||
ticktime_filter(e->database, "UE_PHY_ULSCH_UE_DCI", i, ue));
|
||||
ticktime_filter(e->database, "UE_PHY_ULSCH_UE_DCI", i));
|
||||
/*logger_set_filter(e->ul_dci_retransmission_logger[i],
|
||||
ticktime_filter(e->database,
|
||||
"ENB_PHY_ULSCH_UE_NO_DCI_RETRANSMISSION", i, ue));*/
|
||||
"ENB_PHY_ULSCH_UE_NO_DCI_RETRANSMISSION", i));*/
|
||||
logger_set_filter(e->e->ul_ack_logger[i],
|
||||
ticktime_filter(e->database, "UE_PHY_ULSCH_UE_ACK", i, ue));
|
||||
ticktime_filter(e->database, "UE_PHY_ULSCH_UE_ACK", i));
|
||||
logger_set_filter(e->e->ul_nack_logger[i],
|
||||
ticktime_filter(e->database, "UE_PHY_ULSCH_UE_NACK", i, ue));
|
||||
ticktime_filter(e->database, "UE_PHY_ULSCH_UE_NACK", i));
|
||||
}
|
||||
logger_set_filter(e->e->dl_mcs_logger,
|
||||
filter_eq(
|
||||
filter_evarg(e->database, "UE_PHY_DLSCH_UE_DCI", "UE_id"),
|
||||
filter_int(ue)));
|
||||
logger_set_filter(e->e->ul_mcs_logger,
|
||||
filter_eq(
|
||||
filter_evarg(e->database, "UE_PHY_ULSCH_UE_DCI", "UE_id"),
|
||||
filter_int(ue)));
|
||||
logger_set_filter(e->e->pusch_power_logger,
|
||||
filter_eq(
|
||||
filter_evarg(e->database, "UE_PHY_PUSCH_TX_POWER", "UE_id"),
|
||||
filter_int(ue)));
|
||||
logger_set_filter(e->e->pusch_ampl_logger,
|
||||
filter_eq(
|
||||
filter_evarg(e->database, "UE_PHY_PUSCH_TX_POWER", "UE_id"),
|
||||
filter_int(ue)));
|
||||
logger_set_filter(e->e->pucch_power_logger,
|
||||
filter_eq(
|
||||
filter_evarg(e->database, "UE_PHY_PUCCH_TX_POWER", "UE_id"),
|
||||
filter_int(ue)));
|
||||
logger_set_filter(e->e->pucch_ampl_logger,
|
||||
filter_eq(
|
||||
filter_evarg(e->database, "UE_PHY_PUCCH_TX_POWER", "UE_id"),
|
||||
filter_int(ue)));
|
||||
}
|
||||
|
||||
static void click(void *private, gui *g,
|
||||
char *notification, widget *w, void *notification_data)
|
||||
{
|
||||
int *d = notification_data;
|
||||
int button = d[0];
|
||||
ue_data *ed = private;
|
||||
ue_gui *e = ed->e;
|
||||
int ue = ed->ue;
|
||||
|
||||
if (button != 1) return;
|
||||
if (w == e->prev_ue_button) { ue--; if (ue < 0) ue = 0; }
|
||||
if (w == e->next_ue_button) ue++;
|
||||
|
||||
if (pthread_mutex_lock(&ed->lock)) abort();
|
||||
if (ue != ed->ue) {
|
||||
set_current_ue(g, ed, ue);
|
||||
ed->ue = ue;
|
||||
}
|
||||
if (pthread_mutex_unlock(&ed->lock)) abort();
|
||||
}
|
||||
|
||||
static void ue_main_gui(ue_gui *e, gui *g, event_handler *h, void *database,
|
||||
@@ -271,7 +192,7 @@ static void ue_main_gui(ue_gui *e, gui *g, event_handler *h, void *database,
|
||||
widget *text;
|
||||
view *textview;
|
||||
int i;
|
||||
widget *w, *w2;
|
||||
widget *w;
|
||||
view *v;
|
||||
logger *l;
|
||||
|
||||
@@ -283,24 +204,8 @@ static void ue_main_gui(ue_gui *e, gui *g, event_handler *h, void *database,
|
||||
widget_add_child(g, top_container, line, -1);
|
||||
logo = new_image(g, openair_logo_png, openair_logo_png_len);
|
||||
|
||||
/* logo + prev/next UE buttons */
|
||||
col = new_container(g, VERTICAL);
|
||||
widget_add_child(g, col, logo, -1);
|
||||
w = new_container(g, HORIZONTAL);
|
||||
widget_add_child(g, col, w, -1);
|
||||
w2 = new_label(g, "");
|
||||
widget_add_child(g, w, w2, -1);
|
||||
e->current_ue_label = w2;
|
||||
/* TODO: use button widget, not label widget */
|
||||
w2 = new_label(g, " [prev UE] ");
|
||||
widget_add_child(g, w, w2, -1);
|
||||
label_set_clickable(g, w2, 1);
|
||||
e->prev_ue_button = w2;
|
||||
w2 = new_label(g, " [next UE] ");
|
||||
widget_add_child(g, w, w2, -1);
|
||||
label_set_clickable(g, w2, 1);
|
||||
e->next_ue_button = w2;
|
||||
widget_add_child(g, line, col, -1);
|
||||
/* logo */
|
||||
widget_add_child(g, line, logo, -1);
|
||||
|
||||
input_signal_plot = new_xy_plot(g, 256, 55, "input signal", 20);
|
||||
widget_add_child(g, line, input_signal_plot, -1);
|
||||
@@ -356,80 +261,13 @@ static void ue_main_gui(ue_gui *e, gui *g, event_handler *h, void *database,
|
||||
v = new_view_tti(10, g, w, new_color(g, "#0c720c"));
|
||||
logger_add_view(l, v);
|
||||
e->phy_meas_logger = l;
|
||||
|
||||
/* UE x PDSCH energy */
|
||||
w = new_xy_plot(g, 128, 55, "", 50);
|
||||
e->pdsch_energy_ue_xy_plot = w;
|
||||
|
||||
/* a bit of space */
|
||||
line = new_container(g, HORIZONTAL);
|
||||
widget_add_child(g, top_container, line, -1);
|
||||
w = new_space(g, 1, 10);
|
||||
widget_add_child(g, line, w, -1);
|
||||
xy_plot_set_range(g, w, 0, 1024*10, -10, 80);
|
||||
l = new_ttilog(h, database,
|
||||
"UE_PHY_PDSCH_ENERGY", "frame", "subframe", "pdsch_ch_level00", 1);
|
||||
v = new_view_tti(10, g, w, new_color(g, "#ff0000"));
|
||||
logger_add_view(l, v);
|
||||
e->pdsch_energy_logger = l;
|
||||
l = new_ttilog(h, database,
|
||||
"UE_PHY_PDSCH_ENERGY", "frame", "subframe", "pdsch_ch_level01", 1);
|
||||
v = new_view_tti(10, g, w, new_color(g, "#00ff00"));
|
||||
logger_add_view(l, v);
|
||||
e->pdsch_energy_logger = l;
|
||||
l = new_ttilog(h, database,
|
||||
"UE_PHY_PDSCH_ENERGY", "frame", "subframe", "pdsch_ch_level10", 1);
|
||||
v = new_view_tti(10, g, w, new_color(g, "#0f0f0f"));
|
||||
logger_add_view(l, v);
|
||||
e->pdsch_energy_logger = l;
|
||||
l = new_ttilog(h, database,
|
||||
"UE_PHY_PDSCH_ENERGY", "frame", "subframe", "pdsch_ch_level11", 1);
|
||||
v = new_view_tti(10, g, w, new_color(g, "#0000ff"));
|
||||
logger_add_view(l, v);
|
||||
e->pdsch_energy_logger = l;
|
||||
|
||||
/* UE x PDCCH energy */
|
||||
w = new_xy_plot(g, 128, 55, "", 50);
|
||||
e->pdcch_energy_ue_xy_plot = w;
|
||||
widget_add_child(g, line, w, -1);
|
||||
xy_plot_set_range(g, w, 0, 1024*10, -10, 80);
|
||||
l = new_ttilog(h, database,
|
||||
"UE_PHY_PDCCH_ENERGY", "frame", "subframe", "pdcch_ch_level00", 1);
|
||||
v = new_view_tti(10, g, w, new_color(g, "#ff0000"));
|
||||
logger_add_view(l, v);
|
||||
e->pdcch_energy_logger = l;
|
||||
l = new_ttilog(h, database,
|
||||
"UE_PHY_PDCCH_ENERGY", "frame", "subframe", "pdcch_ch_level01", 1);
|
||||
v = new_view_tti(10, g, w, new_color(g, "#00ff00"));
|
||||
logger_add_view(l, v);
|
||||
e->pdcch_energy_logger = l;
|
||||
l = new_ttilog(h, database,
|
||||
"UE_PHY_PDCCH_ENERGY", "frame", "subframe", "pdcch_ch_level10", 1);
|
||||
v = new_view_tti(10, g, w, new_color(g, "#0f0f0f"));
|
||||
logger_add_view(l, v);
|
||||
e->pdcch_energy_logger = l;
|
||||
l = new_ttilog(h, database,
|
||||
"UE_PHY_PDCCH_ENERGY", "frame", "subframe", "pdcch_ch_level11", 1);
|
||||
v = new_view_tti(10, g, w, new_color(g, "#0000ff"));
|
||||
logger_add_view(l, v);
|
||||
e->pdcch_energy_logger = l;
|
||||
|
||||
/* UE x PDCCH IQ data */
|
||||
w = new_xy_plot(g, 55, 55, "", 50);
|
||||
e->pdcch_iq_ue_xy_plot = w;
|
||||
widget_add_child(g, line, w, -1);
|
||||
xy_plot_set_range(g, w, -100, 100, -100, 100);
|
||||
l = new_iqlog(h, database, "UE_PHY_PDCCH_IQ", "nb_rb",
|
||||
"NB_RB_DL", "symbols_per_tti", "rxdataF_comp");
|
||||
v = new_view_xy(100*12*14,10,g,w,new_color(g,"#000"),XY_FORCED_MODE);
|
||||
logger_add_view(l, v);
|
||||
e->pdcch_iq_ue_logger = l;
|
||||
|
||||
/* UE x PDCCH IQ data */
|
||||
/*w = new_xy_plot(g, 55, 55, "", 50);
|
||||
e->pdcch_iq_ue_xy_plot = w;
|
||||
widget_add_child(g, line, w, -1);
|
||||
xy_plot_set_range(g, w, -2000, 2000, -2000, 2000);
|
||||
l = new_iqdotlog(h, database, "UE_PHY_PDCCH_IQ", "I", "Q");
|
||||
v = new_view_xy(500, 10, g, w, new_color(g,"#000"), XY_LOOP_MODE);
|
||||
logger_add_view(l, v);
|
||||
e->pdcch_iq_ue_logger = l;*/
|
||||
|
||||
|
||||
/* UE x DL mcs */
|
||||
line = new_container(g, HORIZONTAL);
|
||||
widget_add_child(g, top_container, line, -1);
|
||||
@@ -448,7 +286,7 @@ static void ue_main_gui(ue_gui *e, gui *g, event_handler *h, void *database,
|
||||
xy_plot_set_range(g, w, 0, 1024*10, -2, 30);
|
||||
e->ul_mcs_xy_plot = w;
|
||||
widget_add_child(g, line, w, -1);
|
||||
l = new_ticked_ttilog(h, database, "UE_PHY_UL_TICK", "frame", "subframe",
|
||||
l = new_ticked_ttilog(h, database, "UE_PHY_DL_TICK", "frame", "subframe",
|
||||
"UE_PHY_ULSCH_UE_DCI", "mcs", 0, -1);
|
||||
v = new_view_tti(10, g, w, new_color(g, "#0c0c72"));
|
||||
logger_add_view(l, v);
|
||||
@@ -471,7 +309,7 @@ static void ue_main_gui(ue_gui *e, gui *g, event_handler *h, void *database,
|
||||
v = new_view_tti(10, g, w, new_color(g, "#720c0c"));
|
||||
logger_add_view(l, v);
|
||||
e->pusch_ampl_logger = l;
|
||||
|
||||
|
||||
/* UE x PUCCH TX Power */
|
||||
// line = new_container(g, HORIZONTAL);
|
||||
// widget_add_child(g, top_container, line, -1);
|
||||
@@ -489,8 +327,81 @@ static void ue_main_gui(ue_gui *e, gui *g, event_handler *h, void *database,
|
||||
v = new_view_tti(10, g, w, new_color(g, "#720c0c"));
|
||||
logger_add_view(l, v);
|
||||
e->pucch_ampl_logger = l;
|
||||
|
||||
|
||||
|
||||
/* UE x PDSCH energy */
|
||||
w = new_xy_plot(g, 128, 55, "", 50);
|
||||
e->pdsch_energy_ue_xy_plot = w;
|
||||
widget_add_child(g, line, w, -1);
|
||||
xy_plot_set_range(g, w, 0, 1024*10, -10, 80);
|
||||
l = new_ttilog(h, database,
|
||||
"UE_PHY_PDSCH_ENERGY", "frame", "subframe", "pdsch_ch_level00", 1);
|
||||
v = new_view_tti(10, g, w, new_color(g, "#ff0000"));
|
||||
logger_add_view(l, v);
|
||||
e->pdsch_energy_logger = l;
|
||||
l = new_ttilog(h, database,
|
||||
"UE_PHY_PDSCH_ENERGY", "frame", "subframe", "pdsch_ch_level01", 1);
|
||||
v = new_view_tti(10, g, w, new_color(g, "#00ff00"));
|
||||
logger_add_view(l, v);
|
||||
e->pdsch_energy_logger = l;
|
||||
l = new_ttilog(h, database,
|
||||
"UE_PHY_PDSCH_ENERGY", "frame", "subframe", "pdsch_ch_level10", 1);
|
||||
v = new_view_tti(10, g, w, new_color(g, "#0f0f0f"));
|
||||
logger_add_view(l, v);
|
||||
e->pdsch_energy_logger = l;
|
||||
l = new_ttilog(h, database,
|
||||
"UE_PHY_PDSCH_ENERGY", "frame", "subframe", "pdsch_ch_level11", 1);
|
||||
v = new_view_tti(10, g, w, new_color(g, "#0000ff"));
|
||||
logger_add_view(l, v);
|
||||
e->pdsch_energy_logger = l;
|
||||
|
||||
/* UE x PDCCH energy */
|
||||
w = new_xy_plot(g, 128, 55, "", 50);
|
||||
e->pdcch_energy_ue_xy_plot = w;
|
||||
widget_add_child(g, line, w, -1);
|
||||
xy_plot_set_range(g, w, 0, 1024*10, -10, 80);
|
||||
l = new_ttilog(h, database,
|
||||
"UE_PHY_PDCCH_ENERGY", "frame", "subframe", "pdcch_ch_level00", 1);
|
||||
v = new_view_tti(10, g, w, new_color(g, "#ff0000"));
|
||||
logger_add_view(l, v);
|
||||
e->pdcch_energy_logger = l;
|
||||
l = new_ttilog(h, database,
|
||||
"UE_PHY_PDCCH_ENERGY", "frame", "subframe", "pdcch_ch_level01", 1);
|
||||
v = new_view_tti(10, g, w, new_color(g, "#00ff00"));
|
||||
logger_add_view(l, v);
|
||||
e->pdcch_energy_logger = l;
|
||||
l = new_ttilog(h, database,
|
||||
"UE_PHY_PDCCH_ENERGY", "frame", "subframe", "pdcch_ch_level10", 1);
|
||||
v = new_view_tti(10, g, w, new_color(g, "#0f0f0f"));
|
||||
logger_add_view(l, v);
|
||||
e->pdcch_energy_logger = l;
|
||||
l = new_ttilog(h, database,
|
||||
"UE_PHY_PDCCH_ENERGY", "frame", "subframe", "pdcch_ch_level11", 1);
|
||||
v = new_view_tti(10, g, w, new_color(g, "#0000ff"));
|
||||
logger_add_view(l, v);
|
||||
e->pdcch_energy_logger = l;
|
||||
|
||||
/* UE x PDCCH IQ data */
|
||||
w = new_xy_plot(g, 55, 55, "", 50);
|
||||
e->pdcch_iq_ue_xy_plot = w;
|
||||
widget_add_child(g, line, w, -1);
|
||||
xy_plot_set_range(g, w, -100, 100, -100, 100);
|
||||
l = new_iqlog(h, database, "UE_PHY_PDCCH_IQ", "nb_rb",
|
||||
"NB_RB_DL", "symbols_per_tti", "rxdataF_comp");
|
||||
v = new_view_xy(100*12*14,10,g,w,new_color(g,"#000"),XY_FORCED_MODE);
|
||||
logger_add_view(l, v);
|
||||
e->pdcch_iq_ue_logger = l;
|
||||
|
||||
/* UE x PDCCH IQ data */
|
||||
/*w = new_xy_plot(g, 55, 55, "", 50);
|
||||
e->pdcch_iq_ue_xy_plot = w;
|
||||
widget_add_child(g, line, w, -1);
|
||||
xy_plot_set_range(g, w, -2000, 2000, -2000, 2000);
|
||||
l = new_iqdotlog(h, database, "UE_PHY_PDCCH_IQ", "I", "Q");
|
||||
v = new_view_xy(500, 10, g, w, new_color(g,"#000"), XY_LOOP_MODE);
|
||||
logger_add_view(l, v);
|
||||
e->pdcch_iq_ue_logger = l;*/
|
||||
|
||||
|
||||
/* downlink/uplink UE DCIs */
|
||||
widget_add_child(g, top_container,
|
||||
new_label(g,"DL/UL TICK/DCI/ACK/NACK [all UEs]"), -1);
|
||||
@@ -600,14 +511,14 @@ static void ue_main_gui(ue_gui *e, gui *g, event_handler *h, void *database,
|
||||
logger_add_view(timelog, subview);
|
||||
e->ul_dci_logger[i] = timelog;
|
||||
/* retransmission */
|
||||
|
||||
|
||||
timelog = new_ticklog(h, database,
|
||||
"ENB_PHY_ULSCH_UE_NO_DCI_RETRANSMISSION", "frame", "subframe");
|
||||
subview = new_subview_ticktime(timeview, i+9+1,
|
||||
new_color(g,"#99f"), 3600*1000);
|
||||
logger_add_view(timelog, subview);
|
||||
e->ul_dci_retransmission_logger[i] = timelog;
|
||||
|
||||
|
||||
}
|
||||
|
||||
/* UL ACK */
|
||||
@@ -707,8 +618,6 @@ static void ue_main_gui(ue_gui *e, gui *g, event_handler *h, void *database,
|
||||
#endif
|
||||
|
||||
set_current_ue(g, ed, 0);
|
||||
register_notifier(g, "click", e->prev_ue_button, click, ed);
|
||||
register_notifier(g, "click", e->next_ue_button, click, ed);
|
||||
}
|
||||
|
||||
void view_add_log(view *v, char *log, event_handler *h, void *database,
|
||||
@@ -824,13 +733,11 @@ int main(int n, char **v)
|
||||
on_off(database, "UE_PHY_PUSCH_TX_POWER", is_on, 1);
|
||||
on_off(database, "UE_PHY_PUCCH_TX_POWER", is_on, 1);
|
||||
on_off(database, "UE_PHY_MEAS", is_on, 1);
|
||||
|
||||
|
||||
on_off(database, "LEGACY_GROUP_INFO", is_on, 1);
|
||||
on_off(database, "LEGACY_GROUP_ERROR", is_on, 1);
|
||||
on_off(database, "LEGACY_GROUP_WARNING", is_on, 1);
|
||||
|
||||
view_add_log(eg.phyview, "UE_PHY_UL_TICK", h, database, is_on);
|
||||
view_add_log(eg.phyview, "UE_PHY_DL_TICK", h, database, is_on);
|
||||
|
||||
view_add_log(eg.phyview, "UE_PHY_DLSCH_UE_DCI", h, database, is_on);
|
||||
view_add_log(eg.phyview, "UE_PHY_DLSCH_UE_ACK", h, database, is_on);
|
||||
view_add_log(eg.phyview, "UE_PHY_DLSCH_UE_NACK",h, database, is_on);
|
||||
@@ -838,8 +745,6 @@ int main(int n, char **v)
|
||||
view_add_log(eg.phyview, "UE_PHY_ULSCH_UE_ACK", h, database, is_on);
|
||||
view_add_log(eg.phyview, "UE_PHY_ULSCH_UE_NACK", h, database, is_on);
|
||||
|
||||
|
||||
|
||||
/* deactivate those two by default, they are a bit heavy */
|
||||
//on_off(database, "ENB_MAC_UE_UL_SDU_WITH_DATA", is_on, 0);
|
||||
//on_off(database, "ENB_MAC_UE_UL_PDU_WITH_DATA", is_on, 0);
|
||||
|
||||
+100
-67
@@ -9,27 +9,38 @@
|
||||
#include <arpa/inet.h>
|
||||
#include <math.h>
|
||||
|
||||
void new_thread(void *(*f)(void *), void *data)
|
||||
{
|
||||
void new_thread(void *(*f)(void *), void *data) {
|
||||
pthread_t t;
|
||||
pthread_attr_t att;
|
||||
|
||||
if (pthread_attr_init(&att))
|
||||
{ fprintf(stderr, "pthread_attr_init err\n"); exit(1); }
|
||||
if (pthread_attr_setdetachstate(&att, PTHREAD_CREATE_DETACHED))
|
||||
{ fprintf(stderr, "pthread_attr_setdetachstate err\n"); exit(1); }
|
||||
if (pthread_attr_setstacksize(&att, 10000000))
|
||||
{ fprintf(stderr, "pthread_attr_setstacksize err\n"); exit(1); }
|
||||
if (pthread_create(&t, &att, f, data))
|
||||
{ fprintf(stderr, "pthread_create err\n"); exit(1); }
|
||||
if (pthread_attr_destroy(&att))
|
||||
{ fprintf(stderr, "pthread_attr_destroy err\n"); exit(1); }
|
||||
if (pthread_attr_init(&att)) {
|
||||
fprintf(stderr, "pthread_attr_init err\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (pthread_attr_setdetachstate(&att, PTHREAD_CREATE_DETACHED)) {
|
||||
fprintf(stderr, "pthread_attr_setdetachstate err\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (pthread_attr_setstacksize(&att, 10000000)) {
|
||||
fprintf(stderr, "pthread_attr_setstacksize err\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (pthread_create(&t, &att, f, data)) {
|
||||
fprintf(stderr, "pthread_create err\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (pthread_attr_destroy(&att)) {
|
||||
fprintf(stderr, "pthread_attr_destroy err\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void sleepms(int ms)
|
||||
{
|
||||
void sleepms(int ms) {
|
||||
struct timespec t;
|
||||
|
||||
t.tv_sec = ms / 1000;
|
||||
t.tv_nsec = (ms % 1000) * 1000000L;
|
||||
|
||||
@@ -37,12 +48,15 @@ void sleepms(int ms)
|
||||
if (nanosleep(&t, NULL)) abort();
|
||||
}
|
||||
|
||||
void bps(char *out, float v, char *suffix)
|
||||
{
|
||||
void bps(char *out, float v, char *suffix) {
|
||||
static char *bps_unit[4] = { "", "k", "M", "G" };
|
||||
int flog;
|
||||
if (v < 1000) flog = 0; else flog = floor(floor(log10(v)) / 3);
|
||||
|
||||
if (v < 1000) flog = 0;
|
||||
else flog = floor(floor(log10(v)) / 3);
|
||||
|
||||
if (flog > 3) flog = 3;
|
||||
|
||||
v /= pow(10, flog*3);
|
||||
sprintf(out, "%g%s%s", round(v*100)/100, bps_unit[flog], suffix);
|
||||
}
|
||||
@@ -51,25 +65,31 @@ void bps(char *out, float v, char *suffix)
|
||||
/* list */
|
||||
/****************************************************************************/
|
||||
|
||||
list *list_remove_head(list *l)
|
||||
{
|
||||
list *list_remove_head(list *l) {
|
||||
list *ret;
|
||||
|
||||
if (l == NULL) return NULL;
|
||||
|
||||
ret = l->next;
|
||||
|
||||
if (ret != NULL) ret->last = l->last;
|
||||
|
||||
free(l);
|
||||
return ret;
|
||||
}
|
||||
|
||||
list *list_append(list *l, void *data)
|
||||
{
|
||||
list *list_append(list *l, void *data) {
|
||||
list *new = calloc(1, sizeof(list));
|
||||
|
||||
if (new == NULL) abort();
|
||||
|
||||
new->data = data;
|
||||
|
||||
if (l == NULL) {
|
||||
new->last = new;
|
||||
return new;
|
||||
}
|
||||
|
||||
l->last->next = new;
|
||||
l->last = new;
|
||||
return l;
|
||||
@@ -79,88 +99,107 @@ list *list_append(list *l, void *data)
|
||||
/* socket */
|
||||
/****************************************************************************/
|
||||
|
||||
int create_listen_socket(char *addr, int port)
|
||||
{
|
||||
int create_listen_socket(char *addr, int port) {
|
||||
struct sockaddr_in a;
|
||||
int s;
|
||||
int v;
|
||||
|
||||
s = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (s == -1) { perror("socket"); exit(1); }
|
||||
|
||||
if (s == -1) {
|
||||
perror("socket");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
v = 1;
|
||||
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &v, sizeof(int)))
|
||||
{ perror("setsockopt"); exit(1); }
|
||||
|
||||
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &v, sizeof(int))) {
|
||||
perror("setsockopt");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
a.sin_family = AF_INET;
|
||||
a.sin_port = htons(port);
|
||||
a.sin_addr.s_addr = inet_addr(addr);
|
||||
|
||||
if (bind(s, (struct sockaddr *)&a, sizeof(a))) { perror("bind"); exit(1); }
|
||||
if (listen(s, 5)) { perror("listen"); exit(1); }
|
||||
if (bind(s, (struct sockaddr *)&a, sizeof(a))) {
|
||||
perror("bind");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (listen(s, 5)) {
|
||||
perror("listen");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
int socket_accept(int s)
|
||||
{
|
||||
int socket_accept(int s) {
|
||||
struct sockaddr_in a;
|
||||
socklen_t alen;
|
||||
alen = sizeof(a);
|
||||
return accept(s, (struct sockaddr *)&a, &alen);
|
||||
}
|
||||
|
||||
int socket_send(int socket, void *buffer, int size)
|
||||
{
|
||||
int socket_send(int socket, void *buffer, int size) {
|
||||
char *x = buffer;
|
||||
int ret;
|
||||
|
||||
while (size) {
|
||||
ret = write(socket, x, size);
|
||||
|
||||
if (ret <= 0) return -1;
|
||||
|
||||
size -= ret;
|
||||
x += ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int get_connection(char *addr, int port)
|
||||
{
|
||||
int get_connection(char *addr, int port) {
|
||||
int s, t;
|
||||
|
||||
printf("waiting for connection on %s:%d\n", addr, port);
|
||||
|
||||
s = create_listen_socket(addr, port);
|
||||
|
||||
t = socket_accept(s);
|
||||
if (t == -1) { perror("accept"); exit(1); }
|
||||
|
||||
if (t == -1) {
|
||||
perror("accept");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
close(s);
|
||||
|
||||
printf("connected\n");
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
int fullread(int fd, void *_buf, int count)
|
||||
{
|
||||
int fullread(int fd, void *_buf, int count) {
|
||||
char *buf = _buf;
|
||||
int ret = 0;
|
||||
int l;
|
||||
|
||||
while (count) {
|
||||
l = read(fd, buf, count);
|
||||
|
||||
if (l <= 0) return -1;
|
||||
|
||||
count -= l;
|
||||
buf += l;
|
||||
ret += l;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int try_connect_to(char *addr, int port)
|
||||
{
|
||||
int try_connect_to(char *addr, int port) {
|
||||
int s;
|
||||
struct sockaddr_in a;
|
||||
|
||||
s = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (s == -1) { perror("socket"); exit(1); }
|
||||
|
||||
if (s == -1) {
|
||||
perror("socket");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
a.sin_family = AF_INET;
|
||||
a.sin_port = htons(port);
|
||||
@@ -175,14 +214,12 @@ int try_connect_to(char *addr, int port)
|
||||
return s;
|
||||
}
|
||||
|
||||
int connect_to(char *addr, int port)
|
||||
{
|
||||
int connect_to(char *addr, int port) {
|
||||
int s;
|
||||
|
||||
printf("connecting to %s:%d\n", addr, port);
|
||||
|
||||
again:
|
||||
s = try_connect_to(addr, port);
|
||||
|
||||
if (s == -1) {
|
||||
printf("trying again in 1s\n");
|
||||
sleep(1);
|
||||
@@ -196,50 +233,46 @@ again:
|
||||
/* buffer */
|
||||
/****************************************************************************/
|
||||
|
||||
void PUTC(OBUF *o, char c)
|
||||
{
|
||||
void PUTC(OBUF *o, char c) {
|
||||
if (o->osize == o->omaxsize) {
|
||||
o->omaxsize += 512;
|
||||
o->obuf = realloc(o->obuf, o->omaxsize);
|
||||
|
||||
if (o->obuf == NULL) abort();
|
||||
}
|
||||
|
||||
o->obuf[o->osize] = c;
|
||||
o->osize++;
|
||||
}
|
||||
|
||||
void PUTS(OBUF *o, char *s)
|
||||
{
|
||||
void PUTS(OBUF *o, char *s) {
|
||||
while (*s) PUTC(o, *s++);
|
||||
}
|
||||
|
||||
static int clean(char c)
|
||||
{
|
||||
static int clean(char c) {
|
||||
if (!isprint(c)) c = ' ';
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
void PUTS_CLEAN(OBUF *o, char *s)
|
||||
{
|
||||
void PUTS_CLEAN(OBUF *o, char *s) {
|
||||
while (*s) PUTC(o, clean(*s++));
|
||||
}
|
||||
|
||||
void PUTI(OBUF *o, int i)
|
||||
{
|
||||
void PUTI(OBUF *o, int i) {
|
||||
char s[64];
|
||||
sprintf(s, "%d", i);
|
||||
PUTS(o, s);
|
||||
}
|
||||
|
||||
void PUTX2(OBUF *o, int i)
|
||||
{
|
||||
void PUTX2(OBUF *o, int i) {
|
||||
char s[64];
|
||||
sprintf(s, "%2.2x", i);
|
||||
PUTS(o, s);
|
||||
}
|
||||
|
||||
void PUTUL(OBUF *o, unsigned long l)
|
||||
{
|
||||
void PUTUL(OBUF *o, unsigned long l) {
|
||||
char s[128];
|
||||
sprintf(s, "%ld", l);
|
||||
sprintf(s, "%lu", l);
|
||||
PUTS(o, s);
|
||||
}
|
||||
|
||||
@@ -22,9 +22,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <inttypes.h>
|
||||
#ifdef CMAKER
|
||||
#include <platform_types.h>
|
||||
#endif
|
||||
|
||||
#if defined(ENB_MODE)
|
||||
# define display_backtrace()
|
||||
@@ -37,13 +35,11 @@
|
||||
|
||||
void output_log_mem(void);
|
||||
#define _Assert_Exit_ \
|
||||
{ \
|
||||
fprintf(stderr, "\nExiting execution\n"); \
|
||||
display_backtrace(); \
|
||||
fflush(stdout); \
|
||||
fflush(stderr); \
|
||||
exit(EXIT_FAILURE); \
|
||||
}
|
||||
|
||||
#define _Assert_(cOND, aCTION, fORMAT, aRGS...) \
|
||||
do { \
|
||||
|
||||
@@ -31,18 +31,18 @@
|
||||
#include "backtrace.h"
|
||||
|
||||
/* Obtain a backtrace and print it to stdout. */
|
||||
void display_backtrace(void)
|
||||
{
|
||||
void display_backtrace(void) {
|
||||
void *array[10];
|
||||
size_t size;
|
||||
char **strings;
|
||||
size_t i;
|
||||
char* test=getenv("NO_BACKTRACE");
|
||||
if (test!=0) *((int*)0)=0;
|
||||
char *test=getenv("NO_BACKTRACE");
|
||||
|
||||
if (test!=0) *((int *)0)=0;
|
||||
|
||||
size = backtrace(array, 10);
|
||||
strings = backtrace_symbols(array, size);
|
||||
|
||||
printf("Obtained %zd stack frames.\n", size);
|
||||
printf("Obtained %u stack frames.\n", (unsigned int)size);
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
printf("%s\n", strings[i]);
|
||||
@@ -50,8 +50,7 @@ void display_backtrace(void)
|
||||
free(strings);
|
||||
}
|
||||
|
||||
void backtrace_handle_signal(siginfo_t *info)
|
||||
{
|
||||
void backtrace_handle_signal(siginfo_t *info) {
|
||||
display_backtrace();
|
||||
//exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
Executable → Regular
Executable → Regular
+257
-217
@@ -2,9 +2,9 @@
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
@@ -28,17 +28,33 @@
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------------------
|
||||
char* hashtable_rc_code2string(hashtable_rc_t rcP)
|
||||
char *hashtable_rc_code2string(hashtable_rc_t rcP)
|
||||
//-------------------------------------------------------------------------------------------------------------------------------
|
||||
{
|
||||
switch (rcP) {
|
||||
case HASH_TABLE_OK: return "HASH_TABLE_OK";break;
|
||||
case HASH_TABLE_INSERT_OVERWRITTEN_DATA: return "HASH_TABLE_INSERT_OVERWRITTEN_DATA";break;
|
||||
case HASH_TABLE_KEY_NOT_EXISTS: return "HASH_TABLE_KEY_NOT_EXISTS";break;
|
||||
case HASH_TABLE_KEY_ALREADY_EXISTS: return "HASH_TABLE_KEY_ALREADY_EXISTS";break;
|
||||
case HASH_TABLE_BAD_PARAMETER_HASHTABLE: return "HASH_TABLE_BAD_PARAMETER_HASHTABLE";break;
|
||||
default: return "UNKNOWN hashtable_rc_t";
|
||||
}
|
||||
switch (rcP) {
|
||||
case HASH_TABLE_OK:
|
||||
return "HASH_TABLE_OK";
|
||||
break;
|
||||
|
||||
case HASH_TABLE_INSERT_OVERWRITTEN_DATA:
|
||||
return "HASH_TABLE_INSERT_OVERWRITTEN_DATA";
|
||||
break;
|
||||
|
||||
case HASH_TABLE_KEY_NOT_EXISTS:
|
||||
return "HASH_TABLE_KEY_NOT_EXISTS";
|
||||
break;
|
||||
|
||||
case HASH_TABLE_KEY_ALREADY_EXISTS:
|
||||
return "HASH_TABLE_KEY_ALREADY_EXISTS";
|
||||
break;
|
||||
|
||||
case HASH_TABLE_BAD_PARAMETER_HASHTABLE:
|
||||
return "HASH_TABLE_BAD_PARAMETER_HASHTABLE";
|
||||
break;
|
||||
|
||||
default:
|
||||
return "UNKNOWN hashtable_rc_t";
|
||||
}
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------------------
|
||||
/*
|
||||
@@ -46,7 +62,7 @@ char* hashtable_rc_code2string(hashtable_rc_t rcP)
|
||||
* hash_free_int_func() is used when this hashtable is used to store int values as data (pointer = value).
|
||||
*/
|
||||
|
||||
void hash_free_int_func(void* memoryP){}
|
||||
void hash_free_int_func(void *memoryP) {}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------------------
|
||||
/*
|
||||
@@ -55,9 +71,8 @@ void hash_free_int_func(void* memoryP){}
|
||||
* This is a simple/naive hash function which adds the key's ASCII char values. It will probably generate lots of collisions on large hash tables.
|
||||
*/
|
||||
|
||||
static hash_size_t def_hashfunc(const uint64_t keyP)
|
||||
{
|
||||
return (hash_size_t)keyP;
|
||||
static hash_size_t def_hashfunc(const uint64_t keyP) {
|
||||
return (hash_size_t)keyP;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -67,132 +82,147 @@ static hash_size_t def_hashfunc(const uint64_t keyP)
|
||||
* The user can also specify a hash function. If the hashfunc argument is NULL, a default hash function is used.
|
||||
* If an error occurred, NULL is returned. All other values in the returned hash_table_t pointer should be released with hashtable_destroy().
|
||||
*/
|
||||
hash_table_t *hashtable_create(const hash_size_t sizeP, hash_size_t (*hashfuncP)(const hash_key_t ), void (*freefuncP)(void*))
|
||||
{
|
||||
hash_table_t *hashtbl = NULL;
|
||||
hash_table_t *hashtable_create(const hash_size_t sizeP, hash_size_t (*hashfuncP)(const hash_key_t ), void (*freefuncP)(void *)) {
|
||||
hash_table_t *hashtbl = NULL;
|
||||
|
||||
if(!(hashtbl=malloc(sizeof(hash_table_t)))) {
|
||||
return NULL;
|
||||
}
|
||||
if(!(hashtbl=malloc(sizeof(hash_table_t)))) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!(hashtbl->nodes=calloc(sizeP, sizeof(hash_node_t*)))) {
|
||||
free(hashtbl);
|
||||
return NULL;
|
||||
}
|
||||
if(!(hashtbl->nodes=calloc(sizeP, sizeof(hash_node_t *)))) {
|
||||
free(hashtbl);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
hashtbl->size=sizeP;
|
||||
hashtbl->size=sizeP;
|
||||
|
||||
if(hashfuncP) hashtbl->hashfunc=hashfuncP;
|
||||
else hashtbl->hashfunc=def_hashfunc;
|
||||
if(hashfuncP) hashtbl->hashfunc=hashfuncP;
|
||||
else hashtbl->hashfunc=def_hashfunc;
|
||||
|
||||
if(freefuncP) hashtbl->freefunc=freefuncP;
|
||||
else hashtbl->freefunc=free;
|
||||
if(freefuncP) hashtbl->freefunc=freefuncP;
|
||||
else hashtbl->freefunc=free;
|
||||
|
||||
return hashtbl;
|
||||
return hashtbl;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------------------
|
||||
/*
|
||||
* Cleanup
|
||||
* The hashtable_destroy() walks through the linked lists for each possible hash value, and releases the elements. It also releases the nodes array and the hash_table_t.
|
||||
*/
|
||||
hashtable_rc_t hashtable_destroy(hash_table_t * hashtblP)
|
||||
{
|
||||
hash_size_t n;
|
||||
hash_node_t *node, *oldnode;
|
||||
hashtable_rc_t hashtable_destroy(hash_table_t **hashtblP) {
|
||||
hash_size_t n;
|
||||
hash_node_t *node, *oldnode;
|
||||
|
||||
if (hashtblP == NULL) {
|
||||
return HASH_TABLE_BAD_PARAMETER_HASHTABLE;
|
||||
}
|
||||
if (*hashtblP == NULL) {
|
||||
return HASH_TABLE_BAD_PARAMETER_HASHTABLE;
|
||||
}
|
||||
|
||||
for(n=0; n<hashtblP->size; ++n) {
|
||||
node=hashtblP->nodes[n];
|
||||
while(node) {
|
||||
oldnode=node;
|
||||
node=node->next;
|
||||
if (oldnode->data) {
|
||||
hashtblP->freefunc(oldnode->data);
|
||||
}
|
||||
free(oldnode);
|
||||
}
|
||||
}
|
||||
free(hashtblP->nodes);
|
||||
free(hashtblP);
|
||||
hashtblP=NULL;
|
||||
return HASH_TABLE_OK;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------------------
|
||||
hashtable_rc_t hashtable_is_key_exists (const hash_table_t * const hashtblP, const hash_key_t keyP)
|
||||
//-------------------------------------------------------------------------------------------------------------------------------
|
||||
{
|
||||
hash_node_t *node = NULL;
|
||||
hash_size_t hash = 0;
|
||||
for(n=0; n<(*hashtblP)->size; ++n) {
|
||||
node=(*hashtblP)->nodes[n];
|
||||
|
||||
if (hashtblP == NULL) {
|
||||
return HASH_TABLE_BAD_PARAMETER_HASHTABLE;
|
||||
}
|
||||
|
||||
hash=hashtblP->hashfunc(keyP)%hashtblP->size;
|
||||
node=hashtblP->nodes[hash];
|
||||
while(node) {
|
||||
if(node->key == keyP) {
|
||||
return HASH_TABLE_OK;
|
||||
}
|
||||
oldnode=node;
|
||||
node=node->next;
|
||||
|
||||
if (oldnode->data) {
|
||||
(*hashtblP)->freefunc(oldnode->data);
|
||||
}
|
||||
|
||||
free(oldnode);
|
||||
}
|
||||
}
|
||||
|
||||
free((*hashtblP)->nodes);
|
||||
free((*hashtblP));
|
||||
*hashtblP=NULL;
|
||||
return HASH_TABLE_OK;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------------------
|
||||
hashtable_rc_t hashtable_is_key_exists (const hash_table_t *const hashtblP, const hash_key_t keyP)
|
||||
//-------------------------------------------------------------------------------------------------------------------------------
|
||||
{
|
||||
hash_node_t *node = NULL;
|
||||
hash_size_t hash = 0;
|
||||
|
||||
if (hashtblP == NULL) {
|
||||
return HASH_TABLE_BAD_PARAMETER_HASHTABLE;
|
||||
}
|
||||
|
||||
hash=hashtblP->hashfunc(keyP)%hashtblP->size;
|
||||
node=hashtblP->nodes[hash];
|
||||
|
||||
while(node) {
|
||||
if(node->key == keyP) {
|
||||
return HASH_TABLE_OK;
|
||||
}
|
||||
|
||||
node=node->next;
|
||||
}
|
||||
|
||||
return HASH_TABLE_KEY_NOT_EXISTS;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------------------
|
||||
hashtable_rc_t hashtable_apply_funct_on_elements (hash_table_t *const hashtblP, void functP(hash_key_t keyP, void *dataP, void *parameterP), void *parameterP)
|
||||
//-------------------------------------------------------------------------------------------------------------------------------
|
||||
{
|
||||
hash_node_t *node = NULL;
|
||||
unsigned int i = 0;
|
||||
unsigned int num_elements = 0;
|
||||
|
||||
if (hashtblP == NULL) {
|
||||
return HASH_TABLE_BAD_PARAMETER_HASHTABLE;
|
||||
}
|
||||
|
||||
while ((num_elements < hashtblP->num_elements) && (i < hashtblP->size)) {
|
||||
if (hashtblP->nodes[i] != NULL) {
|
||||
node=hashtblP->nodes[i];
|
||||
|
||||
while(node) {
|
||||
num_elements += 1;
|
||||
functP(node->key, node->data, parameterP);
|
||||
node=node->next;
|
||||
}
|
||||
}
|
||||
return HASH_TABLE_KEY_NOT_EXISTS;
|
||||
|
||||
i += 1;
|
||||
}
|
||||
|
||||
return HASH_TABLE_OK;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------------------
|
||||
hashtable_rc_t hashtable_apply_funct_on_elements (hash_table_t *const hashtblP, void functP(hash_key_t keyP, void* dataP, void* parameterP), void* parameterP)
|
||||
hashtable_rc_t hashtable_dump_content (const hash_table_t *const hashtblP, char *const buffer_pP, int *const remaining_bytes_in_buffer_pP )
|
||||
//-------------------------------------------------------------------------------------------------------------------------------
|
||||
{
|
||||
hash_node_t *node = NULL;
|
||||
unsigned int i = 0;
|
||||
unsigned int num_elements = 0;
|
||||
if (hashtblP == NULL) {
|
||||
return HASH_TABLE_BAD_PARAMETER_HASHTABLE;
|
||||
}
|
||||
while ((num_elements < hashtblP->num_elements) && (i < hashtblP->size)) {
|
||||
if (hashtblP->nodes[i] != NULL) {
|
||||
node=hashtblP->nodes[i];
|
||||
while(node) {
|
||||
num_elements += 1;
|
||||
functP(node->key, node->data, parameterP);
|
||||
node=node->next;
|
||||
}
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
return HASH_TABLE_OK;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------------------
|
||||
hashtable_rc_t hashtable_dump_content (const hash_table_t * const hashtblP, char * const buffer_pP, int * const remaining_bytes_in_buffer_pP )
|
||||
//-------------------------------------------------------------------------------------------------------------------------------
|
||||
{
|
||||
hash_node_t *node = NULL;
|
||||
unsigned int i = 0;
|
||||
if (hashtblP == NULL) {
|
||||
hash_node_t *node = NULL;
|
||||
unsigned int i = 0;
|
||||
|
||||
if (hashtblP == NULL) {
|
||||
*remaining_bytes_in_buffer_pP = snprintf(
|
||||
buffer_pP,
|
||||
*remaining_bytes_in_buffer_pP,
|
||||
"HASH_TABLE_BAD_PARAMETER_HASHTABLE");
|
||||
return HASH_TABLE_BAD_PARAMETER_HASHTABLE;
|
||||
}
|
||||
|
||||
while ((i < hashtblP->size) && (*remaining_bytes_in_buffer_pP > 0)) {
|
||||
if (hashtblP->nodes[i] != NULL) {
|
||||
node=hashtblP->nodes[i];
|
||||
|
||||
while(node) {
|
||||
*remaining_bytes_in_buffer_pP = snprintf(
|
||||
buffer_pP,
|
||||
*remaining_bytes_in_buffer_pP,
|
||||
"HASH_TABLE_BAD_PARAMETER_HASHTABLE");
|
||||
return HASH_TABLE_BAD_PARAMETER_HASHTABLE;
|
||||
buffer_pP,
|
||||
*remaining_bytes_in_buffer_pP,
|
||||
"Key 0x%"PRIx64" Element %p\n",
|
||||
node->key,
|
||||
node->data);
|
||||
node=node->next;
|
||||
}
|
||||
}
|
||||
while ((i < hashtblP->size) && (*remaining_bytes_in_buffer_pP > 0)) {
|
||||
if (hashtblP->nodes[i] != NULL) {
|
||||
node=hashtblP->nodes[i];
|
||||
while(node) {
|
||||
*remaining_bytes_in_buffer_pP = snprintf(
|
||||
buffer_pP,
|
||||
*remaining_bytes_in_buffer_pP,
|
||||
"Key 0x%"PRIx64" Element %p\n",
|
||||
node->key,
|
||||
node->data);
|
||||
node=node->next;
|
||||
}
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
return HASH_TABLE_OK;
|
||||
|
||||
i += 1;
|
||||
}
|
||||
|
||||
return HASH_TABLE_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -200,97 +230,110 @@ hashtable_rc_t hashtable_dump_content (const hash_table_t * const hashtblP, char
|
||||
* Adding a new element
|
||||
* To make sure the hash value is not bigger than size, the result of the user provided hash function is used modulo size.
|
||||
*/
|
||||
hashtable_rc_t hashtable_insert(hash_table_t * const hashtblP, const hash_key_t keyP, void *dataP)
|
||||
{
|
||||
hash_node_t *node = NULL;
|
||||
hash_size_t hash = 0;
|
||||
if (hashtblP == NULL) {
|
||||
return HASH_TABLE_BAD_PARAMETER_HASHTABLE;
|
||||
}
|
||||
hash=hashtblP->hashfunc(keyP)%hashtblP->size;
|
||||
hashtable_rc_t hashtable_insert(hash_table_t *const hashtblP, const hash_key_t keyP, void *dataP) {
|
||||
hash_node_t *node = NULL;
|
||||
hash_size_t hash = 0;
|
||||
|
||||
node=hashtblP->nodes[hash];
|
||||
while(node) {
|
||||
if(node->key == keyP) {
|
||||
if (node->data) {
|
||||
hashtblP->freefunc(node->data);
|
||||
}
|
||||
node->data=dataP;
|
||||
return HASH_TABLE_INSERT_OVERWRITTEN_DATA;
|
||||
}
|
||||
node=node->next;
|
||||
if (hashtblP == NULL) {
|
||||
return HASH_TABLE_BAD_PARAMETER_HASHTABLE;
|
||||
}
|
||||
|
||||
hash=hashtblP->hashfunc(keyP)%hashtblP->size;
|
||||
node=hashtblP->nodes[hash];
|
||||
|
||||
while(node) {
|
||||
if(node->key == keyP) {
|
||||
if (node->data) {
|
||||
hashtblP->freefunc(node->data);
|
||||
}
|
||||
|
||||
node->data=dataP;
|
||||
return HASH_TABLE_INSERT_OVERWRITTEN_DATA;
|
||||
}
|
||||
if(!(node=malloc(sizeof(hash_node_t)))) return -1;
|
||||
node->key=keyP;
|
||||
node->data=dataP;
|
||||
if (hashtblP->nodes[hash]) {
|
||||
node->next=hashtblP->nodes[hash];
|
||||
} else {
|
||||
node->next = NULL;
|
||||
}
|
||||
hashtblP->nodes[hash]=node;
|
||||
hashtblP->num_elements += 1;
|
||||
return HASH_TABLE_OK;
|
||||
|
||||
node=node->next;
|
||||
}
|
||||
|
||||
if(!(node=malloc(sizeof(hash_node_t)))) return -1;
|
||||
|
||||
node->key=keyP;
|
||||
node->data=dataP;
|
||||
|
||||
if (hashtblP->nodes[hash]) {
|
||||
node->next=hashtblP->nodes[hash];
|
||||
} else {
|
||||
node->next = NULL;
|
||||
}
|
||||
|
||||
hashtblP->nodes[hash]=node;
|
||||
hashtblP->num_elements += 1;
|
||||
return HASH_TABLE_OK;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------------------
|
||||
/*
|
||||
* To remove an element from the hash table, we just search for it in the linked list for that hash value,
|
||||
* and remove it if it is found. If it was not found, it is an error and -1 is returned.
|
||||
*/
|
||||
hashtable_rc_t hashtable_remove(hash_table_t * const hashtblP, const hash_key_t keyP)
|
||||
{
|
||||
hash_node_t *node, *prevnode=NULL;
|
||||
hash_size_t hash = 0;
|
||||
hashtable_rc_t hashtable_remove(hash_table_t *const hashtblP, const hash_key_t keyP) {
|
||||
hash_node_t *node, *prevnode=NULL;
|
||||
hash_size_t hash = 0;
|
||||
|
||||
if (hashtblP == NULL) {
|
||||
return HASH_TABLE_BAD_PARAMETER_HASHTABLE;
|
||||
if (hashtblP == NULL) {
|
||||
return HASH_TABLE_BAD_PARAMETER_HASHTABLE;
|
||||
}
|
||||
|
||||
hash=hashtblP->hashfunc(keyP)%hashtblP->size;
|
||||
node=hashtblP->nodes[hash];
|
||||
|
||||
while(node) {
|
||||
if(node->key == keyP) {
|
||||
if(prevnode) prevnode->next=node->next;
|
||||
else hashtblP->nodes[hash]=node->next;
|
||||
|
||||
if (node->data) {
|
||||
hashtblP->freefunc(node->data);
|
||||
}
|
||||
|
||||
free(node);
|
||||
hashtblP->num_elements -= 1;
|
||||
return HASH_TABLE_OK;
|
||||
}
|
||||
hash=hashtblP->hashfunc(keyP)%hashtblP->size;
|
||||
node=hashtblP->nodes[hash];
|
||||
while(node) {
|
||||
if(node->key == keyP) {
|
||||
if(prevnode) prevnode->next=node->next;
|
||||
else hashtblP->nodes[hash]=node->next;
|
||||
if (node->data) {
|
||||
hashtblP->freefunc(node->data);
|
||||
}
|
||||
free(node);
|
||||
hashtblP->num_elements -= 1;
|
||||
return HASH_TABLE_OK;
|
||||
}
|
||||
prevnode=node;
|
||||
node=node->next;
|
||||
}
|
||||
return HASH_TABLE_KEY_NOT_EXISTS;
|
||||
|
||||
prevnode=node;
|
||||
node=node->next;
|
||||
}
|
||||
|
||||
return HASH_TABLE_KEY_NOT_EXISTS;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------------------
|
||||
/*
|
||||
* Searching for an element is easy. We just search through the linked list for the corresponding hash value.
|
||||
* NULL is returned if we didn't find it.
|
||||
*/
|
||||
hashtable_rc_t hashtable_get(const hash_table_t * const hashtblP, const hash_key_t keyP, void** dataP)
|
||||
{
|
||||
hash_node_t *node = NULL;
|
||||
hash_size_t hash = 0;
|
||||
hashtable_rc_t hashtable_get(const hash_table_t *const hashtblP, const hash_key_t keyP, void **dataP) {
|
||||
hash_node_t *node = NULL;
|
||||
hash_size_t hash = 0;
|
||||
|
||||
if (hashtblP == NULL) {
|
||||
*dataP = NULL;
|
||||
return HASH_TABLE_BAD_PARAMETER_HASHTABLE;
|
||||
}
|
||||
hash=hashtblP->hashfunc(keyP)%hashtblP->size;
|
||||
/* fprintf(stderr, "hashtable_get() key=%s, hash=%d\n", key, hash);*/
|
||||
|
||||
node=hashtblP->nodes[hash];
|
||||
|
||||
while(node) {
|
||||
if(node->key == keyP) {
|
||||
*dataP = node->data;
|
||||
return HASH_TABLE_OK;
|
||||
}
|
||||
node=node->next;
|
||||
}
|
||||
if (hashtblP == NULL) {
|
||||
*dataP = NULL;
|
||||
return HASH_TABLE_KEY_NOT_EXISTS;
|
||||
return HASH_TABLE_BAD_PARAMETER_HASHTABLE;
|
||||
}
|
||||
|
||||
hash=hashtblP->hashfunc(keyP)%hashtblP->size;
|
||||
/* fprintf(stderr, "hashtable_get() key=%s, hash=%d\n", key, hash);*/
|
||||
node=hashtblP->nodes[hash];
|
||||
|
||||
while(node) {
|
||||
if(node->key == keyP) {
|
||||
*dataP = node->data;
|
||||
return HASH_TABLE_OK;
|
||||
}
|
||||
|
||||
node=node->next;
|
||||
}
|
||||
|
||||
*dataP = NULL;
|
||||
return HASH_TABLE_KEY_NOT_EXISTS;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------------------
|
||||
/*
|
||||
@@ -304,36 +347,33 @@ hashtable_rc_t hashtable_get(const hash_table_t * const hashtblP, const hash_key
|
||||
* After that, we can just free the old table and copy the elements from newtbl to hashtbl.
|
||||
*/
|
||||
|
||||
hashtable_rc_t hashtable_resize(hash_table_t * const hashtblP, const hash_size_t sizeP)
|
||||
{
|
||||
hash_table_t newtbl;
|
||||
hash_size_t n;
|
||||
hash_node_t *node,*next;
|
||||
hashtable_rc_t hashtable_resize(hash_table_t *const hashtblP, const hash_size_t sizeP) {
|
||||
hash_table_t newtbl;
|
||||
hash_size_t n;
|
||||
hash_node_t *node,*next;
|
||||
|
||||
if (hashtblP == NULL) {
|
||||
return HASH_TABLE_BAD_PARAMETER_HASHTABLE;
|
||||
if (hashtblP == NULL) {
|
||||
return HASH_TABLE_BAD_PARAMETER_HASHTABLE;
|
||||
}
|
||||
|
||||
newtbl.size = sizeP;
|
||||
newtbl.hashfunc = hashtblP->hashfunc;
|
||||
|
||||
if(!(newtbl.nodes=calloc(sizeP, sizeof(hash_node_t *)))) return -1;
|
||||
|
||||
for(n=0; n<hashtblP->size; ++n) {
|
||||
for(node=hashtblP->nodes[n]; node; node=next) {
|
||||
next = node->next;
|
||||
hashtable_insert(&newtbl, node->key, node->data);
|
||||
// Lionel GAUTHIER: BAD CODE TO BE REWRITTEN
|
||||
hashtable_remove(hashtblP, node->key);
|
||||
}
|
||||
}
|
||||
|
||||
newtbl.size = sizeP;
|
||||
newtbl.hashfunc = hashtblP->hashfunc;
|
||||
|
||||
if(!(newtbl.nodes=calloc(sizeP, sizeof(hash_node_t*)))) return -1;
|
||||
|
||||
for(n=0; n<hashtblP->size; ++n) {
|
||||
for(node=hashtblP->nodes[n]; node; node=next) {
|
||||
next = node->next;
|
||||
hashtable_insert(&newtbl, node->key, node->data);
|
||||
// Lionel GAUTHIER: BAD CODE TO BE REWRITTEN
|
||||
hashtable_remove(hashtblP, node->key);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
free(hashtblP->nodes);
|
||||
hashtblP->size=newtbl.size;
|
||||
hashtblP->nodes=newtbl.nodes;
|
||||
|
||||
return HASH_TABLE_OK;
|
||||
free(hashtblP->nodes);
|
||||
hashtblP->size=newtbl.size;
|
||||
hashtblP->nodes=newtbl.nodes;
|
||||
return HASH_TABLE_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
@@ -31,41 +31,41 @@ typedef uint64_t hash_key_t;
|
||||
#define HASHTABLE_NOT_A_KEY_VALUE ((uint64_t)-1)
|
||||
|
||||
typedef enum hashtable_return_code_e {
|
||||
HASH_TABLE_OK = 0,
|
||||
HASH_TABLE_INSERT_OVERWRITTEN_DATA = 1,
|
||||
HASH_TABLE_KEY_NOT_EXISTS = 2,
|
||||
HASH_TABLE_KEY_ALREADY_EXISTS = 3,
|
||||
HASH_TABLE_BAD_PARAMETER_HASHTABLE = 4,
|
||||
HASH_TABLE_SYSTEM_ERROR = 5,
|
||||
HASH_TABLE_CODE_MAX
|
||||
HASH_TABLE_OK = 0,
|
||||
HASH_TABLE_INSERT_OVERWRITTEN_DATA = 1,
|
||||
HASH_TABLE_KEY_NOT_EXISTS = 2,
|
||||
HASH_TABLE_KEY_ALREADY_EXISTS = 3,
|
||||
HASH_TABLE_BAD_PARAMETER_HASHTABLE = 4,
|
||||
HASH_TABLE_SYSTEM_ERROR = 5,
|
||||
HASH_TABLE_CODE_MAX
|
||||
} hashtable_rc_t;
|
||||
|
||||
|
||||
typedef struct hash_node_s {
|
||||
hash_key_t key;
|
||||
void *data;
|
||||
struct hash_node_s *next;
|
||||
hash_key_t key;
|
||||
void *data;
|
||||
struct hash_node_s *next;
|
||||
} hash_node_t;
|
||||
|
||||
typedef struct hash_table_s {
|
||||
hash_size_t size;
|
||||
hash_size_t num_elements;
|
||||
struct hash_node_s **nodes;
|
||||
hash_size_t (*hashfunc)(const hash_key_t);
|
||||
void (*freefunc)(void*);
|
||||
hash_size_t size;
|
||||
hash_size_t num_elements;
|
||||
struct hash_node_s **nodes;
|
||||
hash_size_t (*hashfunc)(const hash_key_t);
|
||||
void (*freefunc)(void *);
|
||||
} hash_table_t;
|
||||
|
||||
char* hashtable_rc_code2string(hashtable_rc_t rcP);
|
||||
void hash_free_int_func(void* memoryP);
|
||||
hash_table_t *hashtable_create (const hash_size_t size, hash_size_t (*hashfunc)(const hash_key_t ), void (*freefunc)(void*));
|
||||
hashtable_rc_t hashtable_destroy(hash_table_t * const hashtbl);
|
||||
hashtable_rc_t hashtable_is_key_exists (const hash_table_t * const hashtbl, const uint64_t key);
|
||||
hashtable_rc_t hashtable_apply_funct_on_elements (hash_table_t * const hashtblP, void funct(hash_key_t keyP, void* dataP, void* parameterP), void* parameterP);
|
||||
hashtable_rc_t hashtable_dump_content (const hash_table_t * const hashtblP, char * const buffer_pP, int * const remaining_bytes_in_buffer_pP );
|
||||
hashtable_rc_t hashtable_insert (hash_table_t * const hashtbl, const hash_key_t key, void *data);
|
||||
hashtable_rc_t hashtable_remove (hash_table_t * const hashtbl, const hash_key_t key);
|
||||
hashtable_rc_t hashtable_get (const hash_table_t * const hashtbl, const hash_key_t key, void **dataP);
|
||||
hashtable_rc_t hashtable_resize (hash_table_t * const hashtbl, const hash_size_t size);
|
||||
char *hashtable_rc_code2string(hashtable_rc_t rcP);
|
||||
void hash_free_int_func(void *memoryP);
|
||||
hash_table_t *hashtable_create (const hash_size_t size, hash_size_t (*hashfunc)(const hash_key_t ), void (*freefunc)(void *));
|
||||
hashtable_rc_t hashtable_destroy(hash_table_t **hashtbl);
|
||||
hashtable_rc_t hashtable_is_key_exists (const hash_table_t *const hashtbl, const uint64_t key);
|
||||
hashtable_rc_t hashtable_apply_funct_on_elements (hash_table_t *const hashtblP, void funct(hash_key_t keyP, void *dataP, void *parameterP), void *parameterP);
|
||||
hashtable_rc_t hashtable_dump_content (const hash_table_t *const hashtblP, char *const buffer_pP, int *const remaining_bytes_in_buffer_pP );
|
||||
hashtable_rc_t hashtable_insert (hash_table_t *const hashtbl, const hash_key_t key, void *data);
|
||||
hashtable_rc_t hashtable_remove (hash_table_t *const hashtbl, const hash_key_t key);
|
||||
hashtable_rc_t hashtable_get (const hash_table_t *const hashtbl, const hash_key_t key, void **dataP);
|
||||
hashtable_rc_t hashtable_resize (hash_table_t *const hashtbl, const hash_size_t size);
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
@@ -30,13 +30,12 @@
|
||||
* This is a simple/naive hash function which adds the key's ASCII char values. It will probably generate lots of collisions on large hash tables.
|
||||
*/
|
||||
|
||||
static hash_size_t def_hashfunc(const void *keyP, int key_sizeP)
|
||||
{
|
||||
hash_size_t hash=0;
|
||||
static hash_size_t def_hashfunc(const void *keyP, int key_sizeP) {
|
||||
hash_size_t hash=0;
|
||||
|
||||
while(key_sizeP) hash^=((unsigned char*)keyP)[key_sizeP --];
|
||||
while(key_sizeP) hash^=((unsigned char *)keyP)[key_sizeP --];
|
||||
|
||||
return hash;
|
||||
return hash;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -46,201 +45,221 @@ static hash_size_t def_hashfunc(const void *keyP, int key_sizeP)
|
||||
* The user can also specify a hash function. If the hashfunc argument is NULL, a default hash function is used.
|
||||
* If an error occurred, NULL is returned. All other values in the returned obj_hash_table_t pointer should be released with hashtable_destroy().
|
||||
*/
|
||||
obj_hash_table_t *obj_hashtable_create(hash_size_t sizeP, hash_size_t (*hashfuncP)(const void*, int ), void (*freekeyfuncP)(void*), void (*freedatafuncP)(void*))
|
||||
{
|
||||
obj_hash_table_t *hashtbl;
|
||||
obj_hash_table_t *obj_hashtable_create(hash_size_t sizeP, hash_size_t (*hashfuncP)(const void *, int ), void (*freekeyfuncP)(void *), void (*freedatafuncP)(void *)) {
|
||||
obj_hash_table_t *hashtbl;
|
||||
|
||||
if(!(hashtbl=malloc(sizeof(obj_hash_table_t)))) return NULL;
|
||||
if(!(hashtbl=malloc(sizeof(obj_hash_table_t)))) return NULL;
|
||||
|
||||
if(!(hashtbl->nodes=calloc(sizeP, sizeof(obj_hash_node_t*)))) {
|
||||
free(hashtbl);
|
||||
return NULL;
|
||||
}
|
||||
if(!(hashtbl->nodes=calloc(sizeP, sizeof(obj_hash_node_t *)))) {
|
||||
free(hashtbl);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
hashtbl->size=sizeP;
|
||||
hashtbl->size=sizeP;
|
||||
|
||||
if(hashfuncP) hashtbl->hashfunc=hashfuncP;
|
||||
else hashtbl->hashfunc=def_hashfunc;
|
||||
if(hashfuncP) hashtbl->hashfunc=hashfuncP;
|
||||
else hashtbl->hashfunc=def_hashfunc;
|
||||
|
||||
if(freekeyfuncP) hashtbl->freekeyfunc=freekeyfuncP;
|
||||
else hashtbl->freekeyfunc=free;
|
||||
if(freekeyfuncP) hashtbl->freekeyfunc=freekeyfuncP;
|
||||
else hashtbl->freekeyfunc=free;
|
||||
|
||||
if(freedatafuncP) hashtbl->freedatafunc=freedatafuncP;
|
||||
else hashtbl->freedatafunc=free;
|
||||
if(freedatafuncP) hashtbl->freedatafunc=freedatafuncP;
|
||||
else hashtbl->freedatafunc=free;
|
||||
|
||||
return hashtbl;
|
||||
return hashtbl;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------------------
|
||||
/*
|
||||
* Cleanup
|
||||
* The hashtable_destroy() walks through the linked lists for each possible hash value, and releases the elements. It also releases the nodes array and the obj_hash_table_t.
|
||||
*/
|
||||
hashtable_rc_t obj_hashtable_destroy(obj_hash_table_t *hashtblP)
|
||||
{
|
||||
hash_size_t n;
|
||||
obj_hash_node_t *node, *oldnode;
|
||||
hashtable_rc_t obj_hashtable_destroy(obj_hash_table_t *hashtblP) {
|
||||
hash_size_t n;
|
||||
obj_hash_node_t *node, *oldnode;
|
||||
|
||||
for(n=0; n<hashtblP->size; ++n) {
|
||||
node=hashtblP->nodes[n];
|
||||
while(node) {
|
||||
oldnode=node;
|
||||
node=node->next;
|
||||
hashtblP->freekeyfunc(oldnode->key);
|
||||
hashtblP->freedatafunc(oldnode->data);
|
||||
free(oldnode);
|
||||
}
|
||||
for(n=0; n<hashtblP->size; ++n) {
|
||||
node=hashtblP->nodes[n];
|
||||
|
||||
while(node) {
|
||||
oldnode=node;
|
||||
node=node->next;
|
||||
hashtblP->freekeyfunc(oldnode->key);
|
||||
hashtblP->freedatafunc(oldnode->data);
|
||||
free(oldnode);
|
||||
}
|
||||
free(hashtblP->nodes);
|
||||
free(hashtblP);
|
||||
return HASH_TABLE_OK;
|
||||
}
|
||||
|
||||
free(hashtblP->nodes);
|
||||
free(hashtblP);
|
||||
return HASH_TABLE_OK;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------------------
|
||||
hashtable_rc_t obj_hashtable_is_key_exists (obj_hash_table_t *hashtblP, void* keyP, int key_sizeP)
|
||||
hashtable_rc_t obj_hashtable_is_key_exists (obj_hash_table_t *hashtblP, void *keyP, int key_sizeP)
|
||||
//-------------------------------------------------------------------------------------------------------------------------------
|
||||
{
|
||||
obj_hash_node_t *node;
|
||||
hash_size_t hash;
|
||||
obj_hash_node_t *node;
|
||||
hash_size_t hash;
|
||||
|
||||
if (hashtblP == NULL) {
|
||||
return HASH_TABLE_BAD_PARAMETER_HASHTABLE;
|
||||
if (hashtblP == NULL) {
|
||||
return HASH_TABLE_BAD_PARAMETER_HASHTABLE;
|
||||
}
|
||||
|
||||
hash=hashtblP->hashfunc(keyP, key_sizeP)%hashtblP->size;
|
||||
node=hashtblP->nodes[hash];
|
||||
|
||||
while(node) {
|
||||
if(node->key == keyP) {
|
||||
return HASH_TABLE_OK;
|
||||
} else if (node->key_size == key_sizeP) {
|
||||
if (memcmp(node->key, keyP, key_sizeP) == 0) {
|
||||
return HASH_TABLE_OK;
|
||||
}
|
||||
}
|
||||
hash=hashtblP->hashfunc(keyP, key_sizeP)%hashtblP->size;
|
||||
node=hashtblP->nodes[hash];
|
||||
while(node) {
|
||||
if(node->key == keyP) {
|
||||
return HASH_TABLE_OK;
|
||||
} else if (node->key_size == key_sizeP) {
|
||||
if (memcmp(node->key, keyP, key_sizeP) == 0) {
|
||||
return HASH_TABLE_OK;
|
||||
}
|
||||
}
|
||||
node=node->next;
|
||||
}
|
||||
return HASH_TABLE_KEY_NOT_EXISTS;
|
||||
|
||||
node=node->next;
|
||||
}
|
||||
|
||||
return HASH_TABLE_KEY_NOT_EXISTS;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------------------
|
||||
/*
|
||||
* Adding a new element
|
||||
* To make sure the hash value is not bigger than size, the result of the user provided hash function is used modulo size.
|
||||
*/
|
||||
hashtable_rc_t obj_hashtable_insert(obj_hash_table_t *hashtblP, void* keyP, int key_sizeP, void *dataP)
|
||||
{
|
||||
obj_hash_node_t *node;
|
||||
hash_size_t hash;
|
||||
hashtable_rc_t obj_hashtable_insert(obj_hash_table_t *hashtblP, void *keyP, int key_sizeP, void *dataP) {
|
||||
obj_hash_node_t *node;
|
||||
hash_size_t hash;
|
||||
|
||||
if (hashtblP == NULL) {
|
||||
return HASH_TABLE_BAD_PARAMETER_HASHTABLE;
|
||||
if (hashtblP == NULL) {
|
||||
return HASH_TABLE_BAD_PARAMETER_HASHTABLE;
|
||||
}
|
||||
|
||||
hash=hashtblP->hashfunc(keyP, key_sizeP)%hashtblP->size;
|
||||
node=hashtblP->nodes[hash];
|
||||
|
||||
while(node) {
|
||||
if(node->key == keyP) {
|
||||
if (node->data) {
|
||||
hashtblP->freedatafunc(node->data);
|
||||
}
|
||||
|
||||
node->data=dataP;
|
||||
// waste of memory here (keyP is lost) we should free it now
|
||||
return HASH_TABLE_INSERT_OVERWRITTEN_DATA;
|
||||
}
|
||||
hash=hashtblP->hashfunc(keyP, key_sizeP)%hashtblP->size;
|
||||
node=hashtblP->nodes[hash];
|
||||
while(node) {
|
||||
if(node->key == keyP) {
|
||||
if (node->data) {
|
||||
hashtblP->freedatafunc(node->data);
|
||||
}
|
||||
node->data=dataP;
|
||||
// waste of memory here (keyP is lost) we should free it now
|
||||
return HASH_TABLE_INSERT_OVERWRITTEN_DATA;
|
||||
}
|
||||
node=node->next;
|
||||
}
|
||||
if(!(node=malloc(sizeof(obj_hash_node_t)))) return -1;
|
||||
node->key=keyP;
|
||||
node->data=dataP;
|
||||
if (hashtblP->nodes[hash]) {
|
||||
node->next=hashtblP->nodes[hash];
|
||||
} else {
|
||||
node->next = NULL;
|
||||
}
|
||||
hashtblP->nodes[hash]=node;
|
||||
return HASH_TABLE_OK;
|
||||
|
||||
node=node->next;
|
||||
}
|
||||
|
||||
if(!(node=malloc(sizeof(obj_hash_node_t)))) return -1;
|
||||
|
||||
node->key=keyP;
|
||||
node->data=dataP;
|
||||
|
||||
if (hashtblP->nodes[hash]) {
|
||||
node->next=hashtblP->nodes[hash];
|
||||
} else {
|
||||
node->next = NULL;
|
||||
}
|
||||
|
||||
hashtblP->nodes[hash]=node;
|
||||
return HASH_TABLE_OK;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------------------
|
||||
/*
|
||||
* To remove an element from the hash table, we just search for it in the linked list for that hash value,
|
||||
* and remove it if it is found. If it was not found, it is an error and -1 is returned.
|
||||
*/
|
||||
hashtable_rc_t obj_hashtable_remove(obj_hash_table_t *hashtblP, const void* keyP, int key_sizeP)
|
||||
{
|
||||
obj_hash_node_t *node, *prevnode=NULL;
|
||||
hash_size_t hash;
|
||||
hashtable_rc_t obj_hashtable_remove(obj_hash_table_t *hashtblP, const void *keyP, int key_sizeP) {
|
||||
obj_hash_node_t *node, *prevnode=NULL;
|
||||
hash_size_t hash;
|
||||
|
||||
if (hashtblP == NULL) {
|
||||
return HASH_TABLE_BAD_PARAMETER_HASHTABLE;
|
||||
if (hashtblP == NULL) {
|
||||
return HASH_TABLE_BAD_PARAMETER_HASHTABLE;
|
||||
}
|
||||
|
||||
hash=hashtblP->hashfunc(keyP, key_sizeP)%hashtblP->size;
|
||||
node=hashtblP->nodes[hash];
|
||||
|
||||
while(node) {
|
||||
if ((node->key == keyP) || ((node->key_size == key_sizeP) && (memcmp(node->key, keyP, key_sizeP) == 0))) {
|
||||
if(prevnode) {
|
||||
prevnode->next=node->next;
|
||||
} else {
|
||||
hashtblP->nodes[hash]=node->next;
|
||||
}
|
||||
|
||||
hashtblP->freekeyfunc(node->key);
|
||||
hashtblP->freedatafunc(node->data);
|
||||
free(node);
|
||||
return HASH_TABLE_OK;
|
||||
}
|
||||
|
||||
hash=hashtblP->hashfunc(keyP, key_sizeP)%hashtblP->size;
|
||||
node=hashtblP->nodes[hash];
|
||||
while(node) {
|
||||
if ((node->key == keyP) || ((node->key_size == key_sizeP) && (memcmp(node->key, keyP, key_sizeP) == 0))){
|
||||
if(prevnode) {
|
||||
prevnode->next=node->next;
|
||||
} else {
|
||||
hashtblP->nodes[hash]=node->next;
|
||||
}
|
||||
hashtblP->freekeyfunc(node->key);
|
||||
hashtblP->freedatafunc(node->data);
|
||||
free(node);
|
||||
return HASH_TABLE_OK;
|
||||
}
|
||||
prevnode=node;
|
||||
node=node->next;
|
||||
}
|
||||
return HASH_TABLE_KEY_NOT_EXISTS;
|
||||
prevnode=node;
|
||||
node=node->next;
|
||||
}
|
||||
|
||||
return HASH_TABLE_KEY_NOT_EXISTS;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------------------
|
||||
/*
|
||||
* Searching for an element is easy. We just search through the linked list for the corresponding hash value.
|
||||
* NULL is returned if we didn't find it.
|
||||
*/
|
||||
hashtable_rc_t obj_hashtable_get(obj_hash_table_t *hashtblP, const void* keyP, int key_sizeP, void** dataP)
|
||||
{
|
||||
obj_hash_node_t *node;
|
||||
hash_size_t hash;
|
||||
hashtable_rc_t obj_hashtable_get(obj_hash_table_t *hashtblP, const void *keyP, int key_sizeP, void **dataP) {
|
||||
obj_hash_node_t *node;
|
||||
hash_size_t hash;
|
||||
|
||||
if (hashtblP == NULL) {
|
||||
*dataP = NULL;
|
||||
return HASH_TABLE_BAD_PARAMETER_HASHTABLE;
|
||||
}
|
||||
hash=hashtblP->hashfunc(keyP, key_sizeP)%hashtblP->size;
|
||||
node=hashtblP->nodes[hash];
|
||||
while(node) {
|
||||
if(node->key == keyP) {
|
||||
*dataP = node->data;
|
||||
return HASH_TABLE_OK;
|
||||
} else if (node->key_size == key_sizeP) {
|
||||
if (memcmp(node->key, keyP, key_sizeP) == 0) {
|
||||
*dataP = node->data;
|
||||
return HASH_TABLE_OK;
|
||||
}
|
||||
}
|
||||
node=node->next;
|
||||
}
|
||||
if (hashtblP == NULL) {
|
||||
*dataP = NULL;
|
||||
return HASH_TABLE_KEY_NOT_EXISTS;
|
||||
return HASH_TABLE_BAD_PARAMETER_HASHTABLE;
|
||||
}
|
||||
|
||||
hash=hashtblP->hashfunc(keyP, key_sizeP)%hashtblP->size;
|
||||
node=hashtblP->nodes[hash];
|
||||
|
||||
while(node) {
|
||||
if(node->key == keyP) {
|
||||
*dataP = node->data;
|
||||
return HASH_TABLE_OK;
|
||||
} else if (node->key_size == key_sizeP) {
|
||||
if (memcmp(node->key, keyP, key_sizeP) == 0) {
|
||||
*dataP = node->data;
|
||||
return HASH_TABLE_OK;
|
||||
}
|
||||
}
|
||||
|
||||
node=node->next;
|
||||
}
|
||||
|
||||
*dataP = NULL;
|
||||
return HASH_TABLE_KEY_NOT_EXISTS;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------------------
|
||||
/*
|
||||
* Function to return all keys of an object hash table
|
||||
*/
|
||||
hashtable_rc_t obj_hashtable_get_keys(obj_hash_table_t *hashtblP, void ** keysP, unsigned int *sizeP)
|
||||
{
|
||||
size_t n = 0;
|
||||
obj_hash_node_t *node = NULL;
|
||||
obj_hash_node_t *next = NULL;
|
||||
|
||||
*sizeP = 0;
|
||||
keysP = calloc(hashtblP->num_elements, sizeof(void *));
|
||||
if (keysP) {
|
||||
for(n=0; n<hashtblP->size; ++n) {
|
||||
for(node=hashtblP->nodes[n]; node; node=next) {
|
||||
keysP[*sizeP++] = node->key;
|
||||
next = node->next;
|
||||
}
|
||||
}
|
||||
return HASH_TABLE_OK;
|
||||
hashtable_rc_t obj_hashtable_get_keys(obj_hash_table_t *hashtblP, void **keysP, unsigned int *sizeP) {
|
||||
size_t n = 0;
|
||||
obj_hash_node_t *node = NULL;
|
||||
obj_hash_node_t *next = NULL;
|
||||
*sizeP = 0;
|
||||
keysP = calloc(hashtblP->num_elements, sizeof(void *));
|
||||
|
||||
if (keysP) {
|
||||
for(n=0; n<hashtblP->size; ++n) {
|
||||
for(node=hashtblP->nodes[n]; node; node=next) {
|
||||
keysP[*sizeP++] = node->key;
|
||||
next = node->next;
|
||||
}
|
||||
}
|
||||
return HASH_TABLE_SYSTEM_ERROR;
|
||||
|
||||
// cppcheck-suppress memleak
|
||||
return HASH_TABLE_OK;
|
||||
}
|
||||
|
||||
return HASH_TABLE_SYSTEM_ERROR;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------------------
|
||||
/*
|
||||
@@ -253,34 +272,32 @@ hashtable_rc_t obj_hashtable_get_keys(obj_hash_table_t *hashtblP, void ** keysP,
|
||||
* This allows us to reuse hashtable_insert() and hashtable_remove(), when moving the elements to the new table.
|
||||
* After that, we can just free the old table and copy the elements from newtbl to hashtbl.
|
||||
*/
|
||||
hashtable_rc_t obj_hashtable_resize(obj_hash_table_t *hashtblP, hash_size_t sizeP)
|
||||
{
|
||||
obj_hash_table_t newtbl;
|
||||
hash_size_t n;
|
||||
obj_hash_node_t *node,*next;
|
||||
hashtable_rc_t obj_hashtable_resize(obj_hash_table_t *hashtblP, hash_size_t sizeP) {
|
||||
obj_hash_table_t newtbl;
|
||||
hash_size_t n;
|
||||
obj_hash_node_t *node,*next;
|
||||
|
||||
if (hashtblP == NULL) {
|
||||
return HASH_TABLE_BAD_PARAMETER_HASHTABLE;
|
||||
if (hashtblP == NULL) {
|
||||
return HASH_TABLE_BAD_PARAMETER_HASHTABLE;
|
||||
}
|
||||
|
||||
newtbl.size = sizeP;
|
||||
newtbl.hashfunc = hashtblP->hashfunc;
|
||||
|
||||
if(!(newtbl.nodes=calloc(sizeP, sizeof(obj_hash_node_t *)))) return HASH_TABLE_SYSTEM_ERROR;
|
||||
|
||||
for(n=0; n<hashtblP->size; ++n) {
|
||||
for(node=hashtblP->nodes[n]; node; node=next) {
|
||||
next = node->next;
|
||||
obj_hashtable_insert(&newtbl, node->key, node->key_size, node->data);
|
||||
obj_hashtable_remove(hashtblP, node->key, node->key_size);
|
||||
}
|
||||
}
|
||||
|
||||
newtbl.size = sizeP;
|
||||
newtbl.hashfunc = hashtblP->hashfunc;
|
||||
|
||||
if(!(newtbl.nodes=calloc(sizeP, sizeof(obj_hash_node_t*)))) return HASH_TABLE_SYSTEM_ERROR;
|
||||
|
||||
for(n=0; n<hashtblP->size; ++n) {
|
||||
for(node=hashtblP->nodes[n]; node; node=next) {
|
||||
next = node->next;
|
||||
obj_hashtable_insert(&newtbl, node->key, node->key_size, node->data);
|
||||
obj_hashtable_remove(hashtblP, node->key, node->key_size);
|
||||
}
|
||||
}
|
||||
|
||||
free(hashtblP->nodes);
|
||||
hashtblP->size=newtbl.size;
|
||||
hashtblP->nodes=newtbl.nodes;
|
||||
|
||||
return HASH_TABLE_OK;
|
||||
free(hashtblP->nodes);
|
||||
hashtblP->size=newtbl.size;
|
||||
hashtblP->nodes=newtbl.nodes;
|
||||
return HASH_TABLE_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+19
-85
@@ -23,19 +23,19 @@
|
||||
#include "memory_pools.h"
|
||||
|
||||
#if T_TRACER
|
||||
#include <string.h>
|
||||
#include "T.h"
|
||||
#include <string.h>
|
||||
#include "T.h"
|
||||
#endif
|
||||
|
||||
/*------------------------------------------------------------------------------*/
|
||||
const static int mp_debug = 0;
|
||||
|
||||
# define MP_DEBUG(x, args...) do { if (mp_debug) fprintf(stdout, "[MP][D]"x, ##args); fflush (stdout); } \
|
||||
while(0)
|
||||
while(0)
|
||||
|
||||
/*------------------------------------------------------------------------------*/
|
||||
#ifndef CHARS_TO_UINT32
|
||||
#define CHARS_TO_UINT32(c1, c2, c3, c4) (((c1) << 24) | ((c2) << 16) | ((c3) << 8) | (c4))
|
||||
#define CHARS_TO_UINT32(c1, c2, c3, c4) (((c1) << 24) | ((c2) << 16) | ((c3) << 8) | (c4))
|
||||
#endif
|
||||
|
||||
#define MEMORY_POOL_ITEM_INFO_NUMBER 2
|
||||
@@ -129,33 +129,25 @@ static const pool_start_mark_t POOL_START_MARK = CHARS_TO_UINT32 ('P'
|
||||
static const pools_start_mark_t POOLS_START_MARK = CHARS_TO_UINT32 ('P', 'S', 's', 't');
|
||||
|
||||
/*------------------------------------------------------------------------------*/
|
||||
static inline uint32_t items_group_number_items (items_group_t *items_group)
|
||||
{
|
||||
static inline uint32_t items_group_number_items (items_group_t *items_group) {
|
||||
return items_group->number_plus_one - 1;
|
||||
}
|
||||
|
||||
static inline uint32_t items_group_free_items (items_group_t *items_group)
|
||||
{
|
||||
static inline uint32_t items_group_free_items (items_group_t *items_group) {
|
||||
items_group_positions_t positions;
|
||||
uint32_t free_items;
|
||||
|
||||
positions.all = items_group->positions.all;
|
||||
|
||||
free_items = items_group->number_plus_one + positions.ind.put - positions.ind.get;
|
||||
free_items %= items_group->number_plus_one;
|
||||
|
||||
return free_items;
|
||||
}
|
||||
|
||||
static inline items_group_index_t items_group_get_free_item (items_group_t *items_group)
|
||||
{
|
||||
static inline items_group_index_t items_group_get_free_item (items_group_t *items_group) {
|
||||
items_group_position_t get_raw;
|
||||
items_group_position_t put;
|
||||
items_group_position_t get;
|
||||
items_group_position_t free_items;
|
||||
|
||||
items_group_index_t index = ITEMS_GROUP_INDEX_INVALID;
|
||||
|
||||
/* Get current put position */
|
||||
put = items_group->positions.ind.put % items_group->number_plus_one;
|
||||
/* Get current get position and increase it */
|
||||
@@ -193,11 +185,9 @@ static inline items_group_index_t items_group_get_free_item (items_group_t *item
|
||||
return (index);
|
||||
}
|
||||
|
||||
static inline int items_group_put_free_item (items_group_t *items_group, items_group_index_t index)
|
||||
{
|
||||
static inline int items_group_put_free_item (items_group_t *items_group, items_group_index_t index) {
|
||||
items_group_position_t put_raw;
|
||||
items_group_position_t put;
|
||||
|
||||
/* Get current put position and increase it */
|
||||
put_raw = __sync_fetch_and_add (&items_group->positions.ind.put, 1);
|
||||
put = put_raw % items_group->number_plus_one;
|
||||
@@ -209,70 +199,54 @@ static inline int items_group_put_free_item (items_group_t *items_group, items_g
|
||||
|
||||
AssertError (items_group->indexes[put] <= ITEMS_GROUP_INDEX_INVALID, return (EXIT_FAILURE),
|
||||
"Index at current put position (%d) is not marked as free (%d)!\n", put, items_group->number_plus_one);
|
||||
|
||||
/* Save freed item index at current put position */
|
||||
items_group->indexes[put] = index;
|
||||
return (EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------------*/
|
||||
static inline memory_pools_t *memory_pools_from_handler (memory_pools_handle_t memory_pools_handle)
|
||||
{
|
||||
static inline memory_pools_t *memory_pools_from_handler (memory_pools_handle_t memory_pools_handle) {
|
||||
memory_pools_t *memory_pools;
|
||||
|
||||
/* Recover memory_pools */
|
||||
memory_pools = (memory_pools_t *) memory_pools_handle;
|
||||
/* Sanity check on passed handle */
|
||||
AssertError (memory_pools->start_mark == POOLS_START_MARK, memory_pools = NULL,
|
||||
"Handle %p is not a valid memory pools handle, start mark is missing!\n", memory_pools_handle);
|
||||
|
||||
return (memory_pools);
|
||||
}
|
||||
|
||||
static inline memory_pool_item_t *memory_pool_item_from_handler (memory_pool_item_handle_t memory_pool_item_handle)
|
||||
{
|
||||
static inline memory_pool_item_t *memory_pool_item_from_handler (memory_pool_item_handle_t memory_pool_item_handle) {
|
||||
void *address;
|
||||
memory_pool_item_t *memory_pool_item;
|
||||
|
||||
/* Recover memory_pools */
|
||||
address = memory_pool_item_handle - sizeof(memory_pool_item_start_t);
|
||||
memory_pool_item = (memory_pool_item_t *) address;
|
||||
|
||||
/* Sanity check on passed handle */
|
||||
AssertError (memory_pool_item->start.start_mark == POOL_ITEM_START_MARK, memory_pool_item = NULL,
|
||||
"Handle %p is not a valid memory pool item handle, start mark is missing!\n", memory_pool_item);
|
||||
|
||||
return (memory_pool_item);
|
||||
}
|
||||
|
||||
static inline memory_pool_item_t *memory_pool_item_from_index (memory_pool_t *memory_pool, items_group_index_t index)
|
||||
{
|
||||
static inline memory_pool_item_t *memory_pool_item_from_index (memory_pool_t *memory_pool, items_group_index_t index) {
|
||||
void *address;
|
||||
|
||||
address = (void *) memory_pool->items;
|
||||
address += index * memory_pool->pool_item_size;
|
||||
|
||||
return (address);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------------*/
|
||||
memory_pools_handle_t memory_pools_create (uint32_t pools_number)
|
||||
{
|
||||
memory_pools_handle_t memory_pools_create (uint32_t pools_number) {
|
||||
memory_pools_t *memory_pools;
|
||||
pool_id_t pool;
|
||||
|
||||
AssertFatal (pools_number <= MAX_POOLS_NUMBER, "Too many memory pools requested (%d/%d)!\n", pools_number, MAX_POOLS_NUMBER); /* Limit to a reasonable number of pools */
|
||||
|
||||
/* Allocate memory_pools */
|
||||
memory_pools = malloc (sizeof(memory_pools_t));
|
||||
AssertFatal (memory_pools != NULL, "Memory pools structure allocation failed!\n");
|
||||
|
||||
/* Initialize memory_pools */
|
||||
{
|
||||
memory_pools->start_mark = POOLS_START_MARK;
|
||||
memory_pools->pools_number = pools_number;
|
||||
memory_pools->pools_defined = 0;
|
||||
|
||||
/* Allocate pools */
|
||||
memory_pools->pools = calloc (pools_number, sizeof(memory_pool_t));
|
||||
AssertFatal (memory_pools->pools != NULL, "Memory pools allocation failed!\n");
|
||||
@@ -282,12 +256,10 @@ memory_pools_handle_t memory_pools_create (uint32_t pools_number)
|
||||
memory_pools->pools[pool].start_mark = POOL_START_MARK;
|
||||
}
|
||||
}
|
||||
|
||||
return ((memory_pools_handle_t) memory_pools);
|
||||
}
|
||||
|
||||
char *memory_pools_statistics(memory_pools_handle_t memory_pools_handle)
|
||||
{
|
||||
char *memory_pools_statistics(memory_pools_handle_t memory_pools_handle) {
|
||||
memory_pools_t *memory_pools;
|
||||
pool_id_t pool;
|
||||
char *statistics;
|
||||
@@ -296,13 +268,10 @@ char *memory_pools_statistics(memory_pools_handle_t memory_pools_handle)
|
||||
uint32_t allocated_pools_memory = 0;
|
||||
items_group_t *items_group;
|
||||
uint32_t pool_items_size;
|
||||
|
||||
/* Recover memory_pools */
|
||||
memory_pools = memory_pools_from_handler (memory_pools_handle);
|
||||
AssertFatal (memory_pools != NULL, "Failed to retrieve memory pool for handle %p!\n", memory_pools_handle);
|
||||
|
||||
statistics = malloc(memory_pools->pools_defined * 200);
|
||||
|
||||
printed_chars = sprintf (&statistics[0], "Pool: size, number, minimum, free, address space and memory used in Kbytes\n");
|
||||
|
||||
for (pool = 0; pool < memory_pools->pools_defined; pool++) {
|
||||
@@ -321,32 +290,25 @@ char *memory_pools_statistics(memory_pools_handle_t memory_pools_handle)
|
||||
}
|
||||
|
||||
printed_chars = sprintf (&statistics[printed_chars], "Pools memory %u Kbytes\n", allocated_pools_memory / (1024));
|
||||
|
||||
return (statistics);
|
||||
}
|
||||
|
||||
int memory_pools_add_pool (memory_pools_handle_t memory_pools_handle, uint32_t pool_items_number, uint32_t pool_item_size)
|
||||
{
|
||||
int memory_pools_add_pool (memory_pools_handle_t memory_pools_handle, uint32_t pool_items_number, uint32_t pool_item_size) {
|
||||
memory_pools_t *memory_pools;
|
||||
memory_pool_t *memory_pool;
|
||||
pool_id_t pool;
|
||||
items_group_index_t item_index;
|
||||
memory_pool_item_t *memory_pool_item;
|
||||
|
||||
AssertFatal (pool_items_number <= MAX_POOL_ITEMS_NUMBER, "Too many items for a memory pool (%u/%d)!\n", pool_items_number, MAX_POOL_ITEMS_NUMBER); /* Limit to a reasonable number of items */
|
||||
AssertFatal (pool_item_size <= MAX_POOL_ITEM_SIZE, "Item size is too big for memory pool items (%u/%d)!\n", pool_item_size, MAX_POOL_ITEM_SIZE); /* Limit to a reasonable item size */
|
||||
|
||||
/* Recover memory_pools */
|
||||
memory_pools = memory_pools_from_handler (memory_pools_handle);
|
||||
AssertFatal (memory_pools != NULL, "Failed to retrieve memory pool for handle %p!\n", memory_pools_handle);
|
||||
|
||||
/* Check number of already created pools */
|
||||
AssertFatal (memory_pools->pools_defined < memory_pools->pools_number, "Can not allocate more memory pool (%d)!\n", memory_pools->pools_number);
|
||||
|
||||
/* Select pool */
|
||||
pool = memory_pools->pools_defined;
|
||||
memory_pool = &memory_pools->pools[pool];
|
||||
|
||||
/* Initialize pool */
|
||||
{
|
||||
memory_pool->pool_id = pool;
|
||||
@@ -357,7 +319,6 @@ int memory_pools_add_pool (memory_pools_handle_t memory_pools_handle, uint32_t p
|
||||
memory_pool->items_group_free.minimum = pool_items_number;
|
||||
memory_pool->items_group_free.positions.ind.put = pool_items_number;
|
||||
memory_pool->items_group_free.positions.ind.get = 0;
|
||||
|
||||
/* Allocate free indexes */
|
||||
memory_pool->items_group_free.indexes = malloc(memory_pool->items_group_free.number_plus_one * sizeof(items_group_index_t));
|
||||
AssertFatal (memory_pool->items_group_free.indexes != NULL, "Memory pool indexes allocation failed!\n");
|
||||
@@ -369,7 +330,6 @@ int memory_pools_add_pool (memory_pools_handle_t memory_pools_handle, uint32_t p
|
||||
|
||||
/* Last index is not allocated */
|
||||
memory_pool->items_group_free.indexes[item_index] = ITEMS_GROUP_INDEX_INVALID;
|
||||
|
||||
/* Allocate items */
|
||||
memory_pool->items = calloc (pool_items_number, memory_pool->pool_item_size);
|
||||
AssertFatal (memory_pool->items != NULL, "Memory pool items allocation failed!\n");
|
||||
@@ -383,20 +343,16 @@ int memory_pools_add_pool (memory_pools_handle_t memory_pools_handle, uint32_t p
|
||||
memory_pool_item->data[memory_pool->item_data_number] = POOL_ITEM_END_MARK;
|
||||
}
|
||||
}
|
||||
|
||||
memory_pools->pools_defined ++;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
memory_pool_item_handle_t memory_pools_allocate (memory_pools_handle_t memory_pools_handle, uint32_t item_size, uint16_t info_0, uint16_t info_1)
|
||||
{
|
||||
memory_pool_item_handle_t memory_pools_allocate (memory_pools_handle_t memory_pools_handle, uint32_t item_size, uint16_t info_0, uint16_t info_1) {
|
||||
memory_pools_t *memory_pools;
|
||||
memory_pool_item_t *memory_pool_item;
|
||||
memory_pool_item_handle_t memory_pool_item_handle = NULL;
|
||||
pool_id_t pool;
|
||||
items_group_index_t item_index = ITEMS_GROUP_INDEX_INVALID;
|
||||
|
||||
/* Recover memory_pools */
|
||||
memory_pools = memory_pools_from_handler (memory_pools_handle);
|
||||
AssertError (memory_pools != NULL, {}, "Failed to retrieve memory pool for handle %p!\n", memory_pools_handle);
|
||||
@@ -424,12 +380,10 @@ memory_pool_item_handle_t memory_pools_allocate (memory_pools_handle_t memory_po
|
||||
/* Sanity check on item status, must be free */
|
||||
AssertFatal (memory_pool_item->start.item_status == ITEM_STATUS_FREE, "Item status is not set to free (%d) in pool %u, item %d!\n",
|
||||
memory_pool_item->start.item_status, pool, item_index);
|
||||
|
||||
memory_pool_item->start.item_status = ITEM_STATUS_ALLOCATED;
|
||||
memory_pool_item->start.info[0] = info_0;
|
||||
memory_pool_item->start.info[1] = info_1;
|
||||
memory_pool_item_handle = memory_pool_item->data;
|
||||
|
||||
MP_DEBUG(" Alloc [%2u][%6d]{%6d}, %3u %3u, %6u, %p, %p, %p\n",
|
||||
pool, item_index,
|
||||
items_group_free_items (&memory_pools->pools[pool].items_group_free),
|
||||
@@ -445,8 +399,7 @@ memory_pool_item_handle_t memory_pools_allocate (memory_pools_handle_t memory_po
|
||||
return memory_pool_item_handle;
|
||||
}
|
||||
|
||||
int memory_pools_free (memory_pools_handle_t memory_pools_handle, memory_pool_item_handle_t memory_pool_item_handle, uint16_t info_0)
|
||||
{
|
||||
int memory_pools_free (memory_pools_handle_t memory_pools_handle, memory_pool_item_handle_t memory_pool_item_handle, uint16_t info_0) {
|
||||
memory_pools_t *memory_pools;
|
||||
memory_pool_item_t *memory_pool_item;
|
||||
pool_id_t pool;
|
||||
@@ -455,36 +408,29 @@ int memory_pools_free (memory_pools_handle_t memory_pools_handle, memory_pool_it
|
||||
uint32_t pool_item_size;
|
||||
uint16_t info_1;
|
||||
int result;
|
||||
|
||||
/* Recover memory_pools */
|
||||
memory_pools = memory_pools_from_handler (memory_pools_handle);
|
||||
AssertError (memory_pools != NULL, return (EXIT_FAILURE), "Failed to retrieve memory pools for handle %p!\n", memory_pools_handle);
|
||||
|
||||
/* Recover memory pool item */
|
||||
memory_pool_item = memory_pool_item_from_handler (memory_pool_item_handle);
|
||||
AssertError (memory_pool_item != NULL, return (EXIT_FAILURE), "Failed to retrieve memory pool item for handle %p!\n", memory_pool_item_handle);
|
||||
|
||||
info_1 = memory_pool_item->start.info[1];
|
||||
|
||||
/* Recover pool index */
|
||||
pool = memory_pool_item->start.pool_id;
|
||||
AssertFatal (pool < memory_pools->pools_defined, "Pool index is invalid (%u/%u)!\n", pool, memory_pools->pools_defined);
|
||||
|
||||
item_size = memory_pools->pools[pool].item_data_number;
|
||||
pool_item_size = memory_pools->pools[pool].pool_item_size;
|
||||
item_index = (((void *) memory_pool_item) - ((void *) memory_pools->pools[pool].items)) / pool_item_size;
|
||||
|
||||
MP_DEBUG(" Free [%2u][%6d]{%6d}, %3u %3u, %p, %p, %p, %u\n",
|
||||
pool, item_index,
|
||||
items_group_free_items (&memory_pools->pools[pool].items_group_free),
|
||||
memory_pool_item->start.info[0], info_1,
|
||||
memory_pool_item_handle, memory_pool_item,
|
||||
memory_pools->pools[pool].items, ((uint32_t) (item_size * sizeof(memory_pool_data_t))));
|
||||
|
||||
/* Sanity check on calculated item index */
|
||||
AssertFatal (memory_pool_item == memory_pool_item_from_index(&memory_pools->pools[pool], item_index),
|
||||
"Incorrect memory pool item address (%p, %p) for pool %u, item %d!\n",
|
||||
memory_pool_item, memory_pool_item_from_index(&memory_pools->pools[pool], item_index), pool, item_index);
|
||||
memory_pool_item,(void *)memory_pool_item_from_index(&memory_pools->pools[pool], item_index), pool, item_index);
|
||||
/* Sanity check on end marker, must still be present (no write overflow) */
|
||||
AssertFatal (memory_pool_item->data[item_size] == POOL_ITEM_END_MARK,
|
||||
"Memory pool item is corrupted, end mark is not present for pool %u, item %d!\n", pool, item_index);
|
||||
@@ -492,31 +438,23 @@ int memory_pools_free (memory_pools_handle_t memory_pools_handle, memory_pool_it
|
||||
AssertFatal (memory_pool_item->start.item_status == ITEM_STATUS_ALLOCATED,
|
||||
"Trying to free a non allocated (%x) memory pool item (pool %u, item %d)!\n",
|
||||
memory_pool_item->start.item_status, pool, item_index);
|
||||
|
||||
memory_pool_item->start.item_status = ITEM_STATUS_FREE;
|
||||
|
||||
result = items_group_put_free_item(&memory_pools->pools[pool].items_group_free, item_index);
|
||||
|
||||
AssertError (result == EXIT_SUCCESS, {}, "Failed to free memory pool item (pool %u, item %d)!\n", pool, item_index);
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
void memory_pools_set_info (memory_pools_handle_t memory_pools_handle, memory_pool_item_handle_t memory_pool_item_handle, int index, uint16_t info)
|
||||
{
|
||||
void memory_pools_set_info (memory_pools_handle_t memory_pools_handle, memory_pool_item_handle_t memory_pool_item_handle, int index, uint16_t info) {
|
||||
memory_pools_t *memory_pools;
|
||||
memory_pool_item_t *memory_pool_item;
|
||||
pool_id_t pool;
|
||||
items_group_index_t item_index;
|
||||
uint32_t item_size;
|
||||
uint32_t pool_item_size;
|
||||
|
||||
AssertFatal (index < MEMORY_POOL_ITEM_INFO_NUMBER, "Incorrect info index (%d/%d)!\n", index, MEMORY_POOL_ITEM_INFO_NUMBER);
|
||||
|
||||
/* Recover memory pool item */
|
||||
memory_pool_item = memory_pool_item_from_handler (memory_pool_item_handle);
|
||||
AssertFatal (memory_pool_item != NULL, "Failed to retrieve memory pool item for handle %p!\n", memory_pool_item_handle);
|
||||
|
||||
/* Set info[1] */
|
||||
memory_pool_item->start.info[index] = info;
|
||||
|
||||
@@ -525,26 +463,22 @@ void memory_pools_set_info (memory_pools_handle_t memory_pools_handle, memory_po
|
||||
/* Recover memory_pools */
|
||||
memory_pools = memory_pools_from_handler (memory_pools_handle);
|
||||
AssertFatal (memory_pools != NULL, "Failed to retrieve memory pool for handle %p!\n", memory_pools_handle);
|
||||
|
||||
/* Recover pool index */
|
||||
pool = memory_pool_item->start.pool_id;
|
||||
AssertFatal (pool < memory_pools->pools_defined, "Pool index is invalid (%u/%u)!\n", pool, memory_pools->pools_defined);
|
||||
|
||||
item_size = memory_pools->pools[pool].item_data_number;
|
||||
pool_item_size = memory_pools->pools[pool].pool_item_size;
|
||||
item_index = (((void *) memory_pool_item) - ((void *) memory_pools->pools[pool].items)) / pool_item_size;
|
||||
|
||||
MP_DEBUG(" Info [%2u][%6d]{%6d}, %3u %3u, %p, %p, %p, %u\n",
|
||||
pool, item_index,
|
||||
items_group_free_items (&memory_pools->pools[pool].items_group_free),
|
||||
memory_pool_item->start.info[0], memory_pool_item->start.info[1],
|
||||
memory_pool_item_handle, memory_pool_item,
|
||||
memory_pools->pools[pool].items, ((uint32_t) (item_size * sizeof(memory_pool_data_t))));
|
||||
|
||||
/* Sanity check on calculated item index */
|
||||
AssertFatal (memory_pool_item == memory_pool_item_from_index(&memory_pools->pools[pool], item_index),
|
||||
"Incorrect memory pool item address (%p, %p) for pool %u, item %d!\n",
|
||||
memory_pool_item, memory_pool_item_from_index(&memory_pools->pools[pool], item_index), pool, item_index);
|
||||
memory_pool_item, (void *)memory_pool_item_from_index(&memory_pools->pools[pool], item_index), pool, item_index);
|
||||
/* Sanity check on end marker, must still be present (no write overflow) */
|
||||
AssertFatal (memory_pool_item->data[item_size] == POOL_ITEM_END_MARK,
|
||||
"Memory pool item is corrupted, end mark is not present for pool %u, item %d!\n", pool, item_index);
|
||||
|
||||
+314
-120
@@ -49,7 +49,7 @@
|
||||
|
||||
//-------------------------------
|
||||
|
||||
FILE* g_msc_fd;
|
||||
FILE *g_msc_fd;
|
||||
char g_msc_proto2str[MAX_MSC_PROTOS][MSC_MAX_PROTO_NAME_LENGTH];
|
||||
|
||||
|
||||
@@ -70,15 +70,11 @@ void *msc_task(void *args_p)
|
||||
//------------------------------------------------------------------------------
|
||||
{
|
||||
MessageDef *received_message_p = NULL;
|
||||
// const char *msg_name = NULL;
|
||||
// instance_t instance = 0;
|
||||
// const char *msg_name = NULL;
|
||||
// instance_t instance = 0;
|
||||
long timer_id;
|
||||
|
||||
itti_mark_task_ready(TASK_MSC);
|
||||
|
||||
msc_start_use();
|
||||
|
||||
|
||||
timer_setup(0, // seconds
|
||||
50000, // usec
|
||||
TASK_MSC,
|
||||
@@ -91,20 +87,18 @@ void *msc_task(void *args_p)
|
||||
itti_receive_msg(TASK_MSC, &received_message_p);
|
||||
|
||||
if (received_message_p != NULL) {
|
||||
// msg_name = ITTI_MSG_NAME (received_message_p);
|
||||
// instance = ITTI_MSG_INSTANCE (received_message_p);
|
||||
|
||||
// msg_name = ITTI_MSG_NAME (received_message_p);
|
||||
// instance = ITTI_MSG_INSTANCE (received_message_p);
|
||||
switch (ITTI_MSG_ID(received_message_p)) {
|
||||
|
||||
case TIMER_HAS_EXPIRED: {
|
||||
msc_flush_messages();
|
||||
msc_flush_messages();
|
||||
}
|
||||
break;
|
||||
|
||||
case TERMINATE_MESSAGE: {
|
||||
fprintf(stderr, " *** Exiting MSC thread\n");
|
||||
timer_remove(timer_id);
|
||||
msc_end();
|
||||
msc_end();
|
||||
itti_exit_task();
|
||||
}
|
||||
break;
|
||||
@@ -119,6 +113,7 @@ void *msc_task(void *args_p)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "Task MSC exiting\n");
|
||||
return NULL;
|
||||
}
|
||||
@@ -132,15 +127,16 @@ int msc_init(const msc_env_t envP, const int max_threadsP)
|
||||
void *pointer_p;
|
||||
char msc_filename[256];
|
||||
fprintf(stderr, "Initializing MSC logs\n");
|
||||
rv = snprintf(msc_filename, 256, "/tmp/openair.msc.%i.log", envP); // TODO NAME
|
||||
|
||||
rv = snprintf(msc_filename, 256, "/tmp/openair.msc.%u.log", envP); // TODO NAME
|
||||
if ((0 >= rv) || (256 < rv)){
|
||||
if ((0 >= rv) || (256 < rv)) {
|
||||
fprintf(stderr, "Error in MSC log file name");
|
||||
}
|
||||
|
||||
g_msc_fd = fopen(msc_filename,"w");
|
||||
AssertFatal(g_msc_fd != NULL, "Could not open MSC log file %s : %s", msc_filename, strerror(errno));
|
||||
|
||||
rv = lfds611_stack_new(&g_msc_memory_stack_p, (lfds611_atom_t)max_threadsP + 2);
|
||||
|
||||
if (0 >= rv) {
|
||||
AssertFatal (0, "lfds611_stack_new failed!\n");
|
||||
}
|
||||
@@ -153,190 +149,356 @@ int msc_init(const msc_env_t envP, const int max_threadsP)
|
||||
for (i=0; i < max_threadsP * 30; i++) {
|
||||
pointer_p = malloc(MSC_MAX_MESSAGE_LENGTH);
|
||||
AssertFatal (pointer_p, "malloc failed!\n");
|
||||
rv = lfds611_stack_guaranteed_push( g_msc_memory_stack_p, pointer_p );
|
||||
AssertFatal (rv, "lfds611_stack_guaranteed_push failed for item %u\n", i);
|
||||
rv = lfds611_stack_guaranteed_push( g_msc_memory_stack_p, pointer_p );
|
||||
AssertFatal (rv, "lfds611_stack_guaranteed_push failed for item %d\n", i);
|
||||
}
|
||||
|
||||
for (i = MIN_MSC_PROTOS; i < MAX_MSC_PROTOS; i++) {
|
||||
switch (i) {
|
||||
case MSC_IP_UE:
|
||||
rv = snprintf(&g_msc_proto2str[i][0], MSC_MAX_PROTO_NAME_LENGTH, "IP_UE");
|
||||
if (rv >= MSC_MAX_PROTO_NAME_LENGTH) {g_msc_proto2str[i][MSC_MAX_PROTO_NAME_LENGTH-1] = 0;}
|
||||
|
||||
if (rv >= MSC_MAX_PROTO_NAME_LENGTH) {
|
||||
g_msc_proto2str[i][MSC_MAX_PROTO_NAME_LENGTH-1] = 0;
|
||||
}
|
||||
|
||||
if ((envP == MSC_E_UTRAN) || (envP == MSC_E_UTRAN_LIPA)) {
|
||||
msc_log_declare_proto(i);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case MSC_IP_ENB:
|
||||
rv = snprintf(&g_msc_proto2str[i][0], MSC_MAX_PROTO_NAME_LENGTH, "IP_ENB");
|
||||
if (rv >= MSC_MAX_PROTO_NAME_LENGTH) {g_msc_proto2str[i][MSC_MAX_PROTO_NAME_LENGTH-1] = 0;}
|
||||
|
||||
if (rv >= MSC_MAX_PROTO_NAME_LENGTH) {
|
||||
g_msc_proto2str[i][MSC_MAX_PROTO_NAME_LENGTH-1] = 0;
|
||||
}
|
||||
|
||||
if (envP == MSC_E_UTRAN_LIPA) {
|
||||
msc_log_declare_proto(i);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case MSC_NAS_UE:
|
||||
rv = snprintf(&g_msc_proto2str[i][0], MSC_MAX_PROTO_NAME_LENGTH, "NAS_UE");
|
||||
if (rv >= MSC_MAX_PROTO_NAME_LENGTH) {g_msc_proto2str[i][MSC_MAX_PROTO_NAME_LENGTH-1] = 0;}
|
||||
|
||||
if (rv >= MSC_MAX_PROTO_NAME_LENGTH) {
|
||||
g_msc_proto2str[i][MSC_MAX_PROTO_NAME_LENGTH-1] = 0;
|
||||
}
|
||||
|
||||
if ((envP == MSC_E_UTRAN) || (envP == MSC_E_UTRAN_LIPA)) {
|
||||
msc_log_declare_proto(i);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case MSC_RRC_UE:
|
||||
rv = snprintf(&g_msc_proto2str[i][0], MSC_MAX_PROTO_NAME_LENGTH, "RRC_UE");
|
||||
if (rv >= MSC_MAX_PROTO_NAME_LENGTH) {g_msc_proto2str[i][MSC_MAX_PROTO_NAME_LENGTH-1] = 0;}
|
||||
|
||||
if (rv >= MSC_MAX_PROTO_NAME_LENGTH) {
|
||||
g_msc_proto2str[i][MSC_MAX_PROTO_NAME_LENGTH-1] = 0;
|
||||
}
|
||||
|
||||
if ((envP == MSC_E_UTRAN) || (envP == MSC_E_UTRAN_LIPA)) {
|
||||
msc_log_declare_proto(i);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case MSC_PDCP_UE:
|
||||
rv = snprintf(&g_msc_proto2str[i][0], MSC_MAX_PROTO_NAME_LENGTH, "PDCP_UE");
|
||||
if (rv >= MSC_MAX_PROTO_NAME_LENGTH) {g_msc_proto2str[i][MSC_MAX_PROTO_NAME_LENGTH-1] = 0;}
|
||||
|
||||
if (rv >= MSC_MAX_PROTO_NAME_LENGTH) {
|
||||
g_msc_proto2str[i][MSC_MAX_PROTO_NAME_LENGTH-1] = 0;
|
||||
}
|
||||
|
||||
if ((envP == MSC_E_UTRAN) || (envP == MSC_E_UTRAN_LIPA)) {
|
||||
msc_log_declare_proto(i);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case MSC_RLC_UE:
|
||||
rv = snprintf(&g_msc_proto2str[i][0], MSC_MAX_PROTO_NAME_LENGTH, "RLC_UE");
|
||||
if (rv >= MSC_MAX_PROTO_NAME_LENGTH) {g_msc_proto2str[i][MSC_MAX_PROTO_NAME_LENGTH-1] = 0;}
|
||||
if ((envP == MSC_E_UTRAN) || (envP == MSC_E_UTRAN_LIPA)) {
|
||||
rv = snprintf(&g_msc_proto2str[i][0], MSC_MAX_PROTO_NAME_LENGTH, "RLC_UE");
|
||||
|
||||
if (rv >= MSC_MAX_PROTO_NAME_LENGTH) {
|
||||
g_msc_proto2str[i][MSC_MAX_PROTO_NAME_LENGTH-1] = 0;
|
||||
}
|
||||
|
||||
if ((envP == MSC_E_UTRAN) || (envP == MSC_E_UTRAN_LIPA)) {
|
||||
msc_log_declare_proto(i);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case MSC_MAC_UE:
|
||||
rv = snprintf(&g_msc_proto2str[i][0], MSC_MAX_PROTO_NAME_LENGTH, "MAC_UE");
|
||||
if (rv >= MSC_MAX_PROTO_NAME_LENGTH) {g_msc_proto2str[i][MSC_MAX_PROTO_NAME_LENGTH-1] = 0;}
|
||||
if ((envP == MSC_E_UTRAN) || (envP == MSC_E_UTRAN_LIPA)) {
|
||||
msc_log_declare_proto(i);
|
||||
|
||||
if (rv >= MSC_MAX_PROTO_NAME_LENGTH) {
|
||||
g_msc_proto2str[i][MSC_MAX_PROTO_NAME_LENGTH-1] = 0;
|
||||
}
|
||||
|
||||
if ((envP == MSC_E_UTRAN) || (envP == MSC_E_UTRAN_LIPA)) {
|
||||
msc_log_declare_proto(i);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case MSC_PHY_UE:
|
||||
rv = snprintf(&g_msc_proto2str[i][0], MSC_MAX_PROTO_NAME_LENGTH, "PHY_UE");
|
||||
if (rv >= MSC_MAX_PROTO_NAME_LENGTH) {g_msc_proto2str[i][MSC_MAX_PROTO_NAME_LENGTH-1] = 0;}
|
||||
|
||||
if (rv >= MSC_MAX_PROTO_NAME_LENGTH) {
|
||||
g_msc_proto2str[i][MSC_MAX_PROTO_NAME_LENGTH-1] = 0;
|
||||
}
|
||||
|
||||
if ((envP == MSC_E_UTRAN) || (envP == MSC_E_UTRAN_LIPA)) {
|
||||
msc_log_declare_proto(i);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case MSC_PHY_ENB:
|
||||
rv = snprintf(&g_msc_proto2str[i][0], MSC_MAX_PROTO_NAME_LENGTH, "PHY_ENB");
|
||||
if (rv >= MSC_MAX_PROTO_NAME_LENGTH) {g_msc_proto2str[i][MSC_MAX_PROTO_NAME_LENGTH-1] = 0;}
|
||||
|
||||
if (rv >= MSC_MAX_PROTO_NAME_LENGTH) {
|
||||
g_msc_proto2str[i][MSC_MAX_PROTO_NAME_LENGTH-1] = 0;
|
||||
}
|
||||
|
||||
if ((envP == MSC_E_UTRAN) || (envP == MSC_E_UTRAN_LIPA)) {
|
||||
msc_log_declare_proto(i);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case MSC_MAC_ENB:
|
||||
rv = snprintf(&g_msc_proto2str[i][0], MSC_MAX_PROTO_NAME_LENGTH, "MAC_ENB");
|
||||
if (rv >= MSC_MAX_PROTO_NAME_LENGTH) {g_msc_proto2str[i][MSC_MAX_PROTO_NAME_LENGTH-1] = 0;}
|
||||
|
||||
if (rv >= MSC_MAX_PROTO_NAME_LENGTH) {
|
||||
g_msc_proto2str[i][MSC_MAX_PROTO_NAME_LENGTH-1] = 0;
|
||||
}
|
||||
|
||||
if ((envP == MSC_E_UTRAN) || (envP == MSC_E_UTRAN_LIPA)) {
|
||||
msc_log_declare_proto(i);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case MSC_RLC_ENB:
|
||||
rv = snprintf(&g_msc_proto2str[i][0], MSC_MAX_PROTO_NAME_LENGTH, "RLC_ENB");
|
||||
if (rv >= MSC_MAX_PROTO_NAME_LENGTH) {g_msc_proto2str[i][MSC_MAX_PROTO_NAME_LENGTH-1] = 0;}
|
||||
|
||||
if (rv >= MSC_MAX_PROTO_NAME_LENGTH) {
|
||||
g_msc_proto2str[i][MSC_MAX_PROTO_NAME_LENGTH-1] = 0;
|
||||
}
|
||||
|
||||
if ((envP == MSC_E_UTRAN) || (envP == MSC_E_UTRAN_LIPA)) {
|
||||
msc_log_declare_proto(i);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case MSC_PDCP_ENB:
|
||||
rv = snprintf(&g_msc_proto2str[i][0], MSC_MAX_PROTO_NAME_LENGTH, "PDCP_ENB");
|
||||
if (rv >= MSC_MAX_PROTO_NAME_LENGTH) {g_msc_proto2str[i][MSC_MAX_PROTO_NAME_LENGTH-1] = 0;}
|
||||
|
||||
if (rv >= MSC_MAX_PROTO_NAME_LENGTH) {
|
||||
g_msc_proto2str[i][MSC_MAX_PROTO_NAME_LENGTH-1] = 0;
|
||||
}
|
||||
|
||||
if ((envP == MSC_E_UTRAN) || (envP == MSC_E_UTRAN_LIPA)) {
|
||||
msc_log_declare_proto(i);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case MSC_RRC_ENB:
|
||||
rv = snprintf(&g_msc_proto2str[i][0], MSC_MAX_PROTO_NAME_LENGTH, "RRC_ENB");
|
||||
if (rv >= MSC_MAX_PROTO_NAME_LENGTH) {g_msc_proto2str[i][MSC_MAX_PROTO_NAME_LENGTH-1] = 0;}
|
||||
|
||||
if (rv >= MSC_MAX_PROTO_NAME_LENGTH) {
|
||||
g_msc_proto2str[i][MSC_MAX_PROTO_NAME_LENGTH-1] = 0;
|
||||
}
|
||||
|
||||
if ((envP == MSC_E_UTRAN) || (envP == MSC_E_UTRAN_LIPA)) {
|
||||
msc_log_declare_proto(i);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case MSC_S1AP_ENB:
|
||||
rv = snprintf(&g_msc_proto2str[i][0], MSC_MAX_PROTO_NAME_LENGTH, "S1AP_ENB");
|
||||
if (rv >= MSC_MAX_PROTO_NAME_LENGTH) {g_msc_proto2str[i][MSC_MAX_PROTO_NAME_LENGTH-1] = 0;}
|
||||
|
||||
if (rv >= MSC_MAX_PROTO_NAME_LENGTH) {
|
||||
g_msc_proto2str[i][MSC_MAX_PROTO_NAME_LENGTH-1] = 0;
|
||||
}
|
||||
|
||||
if ((envP == MSC_E_UTRAN) || (envP == MSC_MME_GW) || (envP == MSC_MME)) {
|
||||
msc_log_declare_proto(i);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case MSC_GTPU_ENB:
|
||||
rv = snprintf(&g_msc_proto2str[i][0], MSC_MAX_PROTO_NAME_LENGTH, "GTPU_ENB");
|
||||
if (rv >= MSC_MAX_PROTO_NAME_LENGTH) {g_msc_proto2str[i][MSC_MAX_PROTO_NAME_LENGTH-1] = 0;}
|
||||
|
||||
if (rv >= MSC_MAX_PROTO_NAME_LENGTH) {
|
||||
g_msc_proto2str[i][MSC_MAX_PROTO_NAME_LENGTH-1] = 0;
|
||||
}
|
||||
|
||||
if ((envP == MSC_E_UTRAN) || (envP == MSC_E_UTRAN_LIPA)) {
|
||||
msc_log_declare_proto(i);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case MSC_GTPU_SGW:
|
||||
rv = snprintf(&g_msc_proto2str[i][0], MSC_MAX_PROTO_NAME_LENGTH, "GTPU_SGW");
|
||||
if (rv >= MSC_MAX_PROTO_NAME_LENGTH) {g_msc_proto2str[i][MSC_MAX_PROTO_NAME_LENGTH-1] = 0;}
|
||||
|
||||
if (rv >= MSC_MAX_PROTO_NAME_LENGTH) {
|
||||
g_msc_proto2str[i][MSC_MAX_PROTO_NAME_LENGTH-1] = 0;
|
||||
}
|
||||
|
||||
if ((envP == MSC_MME_GW) || (envP == MSC_E_UTRAN) || (envP == MSC_E_UTRAN_LIPA)) {
|
||||
msc_log_declare_proto(i);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case MSC_S1AP_MME:
|
||||
rv = snprintf(&g_msc_proto2str[i][0], MSC_MAX_PROTO_NAME_LENGTH, "S1AP_MME");
|
||||
if (rv >= MSC_MAX_PROTO_NAME_LENGTH) {g_msc_proto2str[i][MSC_MAX_PROTO_NAME_LENGTH-1] = 0;}
|
||||
|
||||
if (rv >= MSC_MAX_PROTO_NAME_LENGTH) {
|
||||
g_msc_proto2str[i][MSC_MAX_PROTO_NAME_LENGTH-1] = 0;
|
||||
}
|
||||
|
||||
if ((envP == MSC_MME_GW) || (envP == MSC_MME) || (envP == MSC_E_UTRAN) || (envP == MSC_E_UTRAN_LIPA)) {
|
||||
msc_log_declare_proto(i);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case MSC_MMEAPP_MME:
|
||||
rv = snprintf(&g_msc_proto2str[i][0], MSC_MAX_PROTO_NAME_LENGTH, "MME_APP");
|
||||
if (rv >= MSC_MAX_PROTO_NAME_LENGTH) {g_msc_proto2str[i][MSC_MAX_PROTO_NAME_LENGTH-1] = 0;}
|
||||
|
||||
if (rv >= MSC_MAX_PROTO_NAME_LENGTH) {
|
||||
g_msc_proto2str[i][MSC_MAX_PROTO_NAME_LENGTH-1] = 0;
|
||||
}
|
||||
|
||||
if ((envP == MSC_MME_GW) || (envP == MSC_MME)) {
|
||||
msc_log_declare_proto(i);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case MSC_NAS_MME:
|
||||
rv = snprintf(&g_msc_proto2str[i][0], MSC_MAX_PROTO_NAME_LENGTH, "NAS_MME");
|
||||
if (rv >= MSC_MAX_PROTO_NAME_LENGTH) {g_msc_proto2str[i][MSC_MAX_PROTO_NAME_LENGTH-1] = 0;}
|
||||
|
||||
if (rv >= MSC_MAX_PROTO_NAME_LENGTH) {
|
||||
g_msc_proto2str[i][MSC_MAX_PROTO_NAME_LENGTH-1] = 0;
|
||||
}
|
||||
|
||||
msc_log_declare_proto(i);
|
||||
break;
|
||||
|
||||
case MSC_NAS_EMM_MME:
|
||||
rv = snprintf(&g_msc_proto2str[i][0], MSC_MAX_PROTO_NAME_LENGTH, "NAS_EMM");
|
||||
if (rv >= MSC_MAX_PROTO_NAME_LENGTH) {g_msc_proto2str[i][MSC_MAX_PROTO_NAME_LENGTH-1] = 0;}
|
||||
|
||||
if (rv >= MSC_MAX_PROTO_NAME_LENGTH) {
|
||||
g_msc_proto2str[i][MSC_MAX_PROTO_NAME_LENGTH-1] = 0;
|
||||
}
|
||||
|
||||
if ((envP == MSC_MME_GW) || (envP == MSC_MME)) {
|
||||
msc_log_declare_proto(i);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case MSC_NAS_ESM_MME:
|
||||
rv = snprintf(&g_msc_proto2str[i][0], MSC_MAX_PROTO_NAME_LENGTH, "NAS_ESM");
|
||||
if (rv >= MSC_MAX_PROTO_NAME_LENGTH) {g_msc_proto2str[i][MSC_MAX_PROTO_NAME_LENGTH-1] = 0;}
|
||||
|
||||
if (rv >= MSC_MAX_PROTO_NAME_LENGTH) {
|
||||
g_msc_proto2str[i][MSC_MAX_PROTO_NAME_LENGTH-1] = 0;
|
||||
}
|
||||
|
||||
if ((envP == MSC_MME_GW) || (envP == MSC_MME)) {
|
||||
msc_log_declare_proto(i);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case MSC_SP_GWAPP_MME:
|
||||
rv = snprintf(&g_msc_proto2str[i][0], MSC_MAX_PROTO_NAME_LENGTH, "SP_GW_MME");
|
||||
if (rv >= MSC_MAX_PROTO_NAME_LENGTH) {g_msc_proto2str[i][MSC_MAX_PROTO_NAME_LENGTH-1] = 0;}
|
||||
|
||||
if (rv >= MSC_MAX_PROTO_NAME_LENGTH) {
|
||||
g_msc_proto2str[i][MSC_MAX_PROTO_NAME_LENGTH-1] = 0;
|
||||
}
|
||||
|
||||
if (envP == MSC_MME_GW) {
|
||||
msc_log_declare_proto(i);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case MSC_S11_MME:
|
||||
rv = snprintf(&g_msc_proto2str[i][0], MSC_MAX_PROTO_NAME_LENGTH, "S11_MME");
|
||||
if (rv >= MSC_MAX_PROTO_NAME_LENGTH) {g_msc_proto2str[i][MSC_MAX_PROTO_NAME_LENGTH-1] = 0;}
|
||||
|
||||
if (rv >= MSC_MAX_PROTO_NAME_LENGTH) {
|
||||
g_msc_proto2str[i][MSC_MAX_PROTO_NAME_LENGTH-1] = 0;
|
||||
}
|
||||
|
||||
if (envP == MSC_MME) {
|
||||
msc_log_declare_proto(i);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case MSC_S6A_MME:
|
||||
rv = snprintf(&g_msc_proto2str[i][0], MSC_MAX_PROTO_NAME_LENGTH, "S6A");
|
||||
if (rv >= MSC_MAX_PROTO_NAME_LENGTH) {g_msc_proto2str[i][MSC_MAX_PROTO_NAME_LENGTH-1] = 0;}
|
||||
|
||||
if (rv >= MSC_MAX_PROTO_NAME_LENGTH) {
|
||||
g_msc_proto2str[i][MSC_MAX_PROTO_NAME_LENGTH-1] = 0;
|
||||
}
|
||||
|
||||
if ((envP == MSC_MME_GW) || (envP == MSC_MME)) {
|
||||
msc_log_declare_proto(i);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case MSC_HSS:
|
||||
rv = snprintf(&g_msc_proto2str[i][0], MSC_MAX_PROTO_NAME_LENGTH, "HSS");
|
||||
if (rv >= MSC_MAX_PROTO_NAME_LENGTH) {g_msc_proto2str[i][MSC_MAX_PROTO_NAME_LENGTH-1] = 0;}
|
||||
|
||||
if (rv >= MSC_MAX_PROTO_NAME_LENGTH) {
|
||||
g_msc_proto2str[i][MSC_MAX_PROTO_NAME_LENGTH-1] = 0;
|
||||
}
|
||||
|
||||
if ((envP == MSC_MME_GW) || (envP == MSC_MME)) {
|
||||
msc_log_declare_proto(i);
|
||||
}
|
||||
|
||||
break;
|
||||
case MSC_F1AP_CU:
|
||||
rv = snprintf(&g_msc_proto2str[i][0], MSC_MAX_PROTO_NAME_LENGTH, "F1AP_CU");
|
||||
if (rv >= MSC_MAX_PROTO_NAME_LENGTH) {g_msc_proto2str[i][MSC_MAX_PROTO_NAME_LENGTH-1] = 0;}
|
||||
//if ((envP == MSC_E_UTRAN) || (envP == MSC_MME_GW) || (envP == MSC_MME)) {
|
||||
msc_log_declare_proto(i);
|
||||
//}
|
||||
break;
|
||||
case MSC_F1AP_DU:
|
||||
rv = snprintf(&g_msc_proto2str[i][0], MSC_MAX_PROTO_NAME_LENGTH, "F1AP_DU");
|
||||
if (rv >= MSC_MAX_PROTO_NAME_LENGTH) {g_msc_proto2str[i][MSC_MAX_PROTO_NAME_LENGTH-1] = 0;}
|
||||
//if ((envP == MSC_E_UTRAN) || (envP == MSC_MME_GW) || (envP == MSC_MME)) {
|
||||
msc_log_declare_proto(i);
|
||||
//}
|
||||
break;
|
||||
default:
|
||||
rv = snprintf(&g_msc_proto2str[i][0], MSC_MAX_PROTO_NAME_LENGTH, "UNKNOWN");
|
||||
if (rv >= MSC_MAX_PROTO_NAME_LENGTH) {g_msc_proto2str[i][MSC_MAX_PROTO_NAME_LENGTH-1] = 0;}
|
||||
|
||||
if (rv >= MSC_MAX_PROTO_NAME_LENGTH) {
|
||||
g_msc_proto2str[i][MSC_MAX_PROTO_NAME_LENGTH-1] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rv = itti_create_task (TASK_MSC, msc_task, NULL);
|
||||
AssertFatal (rv == 0, "Create task for MSC failed!\n");
|
||||
fprintf(stderr, "Initializing MSC logs Done\n");
|
||||
@@ -359,15 +521,17 @@ void msc_flush_messages(void)
|
||||
int rv;
|
||||
msc_queue_item_t *item_p = NULL;
|
||||
|
||||
while ((rv = lfds611_queue_dequeue( g_msc_message_queue_p, (void**)&item_p )) == 1) {
|
||||
if (NULL != item_p->message_str) {
|
||||
fputs(item_p->message_str, g_msc_fd);
|
||||
// TODO BIN DATA
|
||||
rv = lfds611_stack_guaranteed_push( g_msc_memory_stack_p, item_p->message_str );
|
||||
}
|
||||
// TODO FREE BIN DATA
|
||||
free(item_p);
|
||||
while ((rv = lfds611_queue_dequeue( g_msc_message_queue_p, (void **)&item_p )) == 1) {
|
||||
if (NULL != item_p->message_str) {
|
||||
fputs(item_p->message_str, g_msc_fd);
|
||||
// TODO BIN DATA
|
||||
rv = lfds611_stack_guaranteed_push( g_msc_memory_stack_p, item_p->message_str );
|
||||
}
|
||||
|
||||
// TODO FREE BIN DATA
|
||||
free(item_p);
|
||||
}
|
||||
|
||||
fflush(g_msc_fd);
|
||||
}
|
||||
|
||||
@@ -377,23 +541,27 @@ void msc_end(void)
|
||||
//------------------------------------------------------------------------------
|
||||
{
|
||||
int rv;
|
||||
|
||||
if (NULL != g_msc_fd ) {
|
||||
msc_flush_messages();
|
||||
msc_flush_messages();
|
||||
rv = fflush(g_msc_fd);
|
||||
if (rv != 0) {
|
||||
fprintf(stderr, "Error while flushing stream of MSC log file: %s", strerror(errno));
|
||||
}
|
||||
rv = fclose(g_msc_fd);
|
||||
|
||||
if (rv != 0) {
|
||||
fprintf(stderr, "Error while closing MSC log file: %s", strerror(errno));
|
||||
fprintf(stderr, "Error while flushing stream of MSC log file: %s", strerror(errno));
|
||||
}
|
||||
|
||||
rv = fclose(g_msc_fd);
|
||||
|
||||
if (rv != 0) {
|
||||
fprintf(stderr, "Error while closing MSC log file: %s", strerror(errno));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void msc_log_declare_proto(
|
||||
const msc_proto_t protoP
|
||||
)
|
||||
const msc_proto_t protoP
|
||||
)
|
||||
//------------------------------------------------------------------------------
|
||||
{
|
||||
int rv = 0;
|
||||
@@ -401,47 +569,55 @@ void msc_log_declare_proto(
|
||||
char *char_message_p = NULL;
|
||||
|
||||
if ((MIN_MSC_PROTOS <= protoP) && (MAX_MSC_PROTOS > protoP)) {
|
||||
// may be build a memory pool for that also ?
|
||||
new_item_p = malloc(sizeof(msc_queue_item_t));
|
||||
if (NULL != new_item_p) {
|
||||
// may be build a memory pool for that also ?
|
||||
new_item_p = malloc(sizeof(msc_queue_item_t));
|
||||
|
||||
rv = lfds611_stack_pop(g_msc_memory_stack_p, (void**)&char_message_p);
|
||||
if (0 == rv) {
|
||||
msc_flush_messages();
|
||||
rv = lfds611_stack_pop(g_msc_memory_stack_p, (void**)&char_message_p);
|
||||
}
|
||||
if (1 == rv) {
|
||||
if (NULL != new_item_p) {
|
||||
rv = lfds611_stack_pop(g_msc_memory_stack_p, (void **)&char_message_p);
|
||||
|
||||
if (0 == rv) {
|
||||
msc_flush_messages();
|
||||
rv = lfds611_stack_pop(g_msc_memory_stack_p, (void **)&char_message_p);
|
||||
}
|
||||
|
||||
if (1 == rv) {
|
||||
rv = snprintf(char_message_p, MSC_MAX_MESSAGE_LENGTH, "%"PRIu64" [PROTO] %d %s\n", __sync_fetch_and_add (&g_message_number, 1), protoP, &g_msc_proto2str[protoP][0]);
|
||||
|
||||
if (0 > rv) {
|
||||
fprintf(stderr, "Error while declaring new protocol in MSC: %s", strerror(errno));
|
||||
}
|
||||
|
||||
new_item_p->message_str = char_message_p;
|
||||
new_item_p->message_str_size = rv;
|
||||
new_item_p->message_bin = NULL;
|
||||
new_item_p->message_bin_size = 0;
|
||||
rv = lfds611_queue_enqueue( g_msc_message_queue_p, new_item_p );
|
||||
if (0 == rv) {
|
||||
rv = lfds611_queue_guaranteed_enqueue(g_msc_message_queue_p, new_item_p );
|
||||
if (0 == rv) {
|
||||
|
||||
if (0 == rv) {
|
||||
rv = lfds611_queue_guaranteed_enqueue(g_msc_message_queue_p, new_item_p );
|
||||
|
||||
if (0 == rv) {
|
||||
fprintf(stderr, "Error while lfds611_queue_guaranteed_enqueue message %s in MSC", char_message_p);
|
||||
rv = lfds611_stack_guaranteed_push( g_msc_memory_stack_p, char_message_p );
|
||||
free(new_item_p);
|
||||
}
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
fprintf(stderr, "Error while lfds611_stack_pop()\n");
|
||||
}
|
||||
rv = lfds611_stack_guaranteed_push( g_msc_memory_stack_p, char_message_p );
|
||||
free(new_item_p);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
} else {
|
||||
fprintf(stderr, "Error while lfds611_stack_pop()\n");
|
||||
}
|
||||
|
||||
free(new_item_p);
|
||||
} else {
|
||||
} else {
|
||||
fprintf(stderr, "Error while malloc in MSC");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void msc_log_event(
|
||||
const msc_proto_t protoP,
|
||||
char *format, ...)
|
||||
const msc_proto_t protoP,
|
||||
char *format, ...)
|
||||
//------------------------------------------------------------------------------
|
||||
{
|
||||
va_list args;
|
||||
@@ -450,52 +626,62 @@ void msc_log_event(
|
||||
msc_queue_item_t *new_item_p = NULL;
|
||||
char *char_message_p = NULL;
|
||||
|
||||
|
||||
if ((MIN_MSC_PROTOS > protoP) || (MAX_MSC_PROTOS <= protoP)) {
|
||||
return;
|
||||
return;
|
||||
}
|
||||
new_item_p = malloc(sizeof(msc_queue_item_t));
|
||||
if (NULL != new_item_p) {
|
||||
|
||||
rv = lfds611_stack_pop(g_msc_memory_stack_p, (void**)&char_message_p);
|
||||
new_item_p = malloc(sizeof(msc_queue_item_t));
|
||||
|
||||
if (NULL != new_item_p) {
|
||||
rv = lfds611_stack_pop(g_msc_memory_stack_p, (void **)&char_message_p);
|
||||
|
||||
if (0 == rv) {
|
||||
msc_flush_messages();
|
||||
rv = lfds611_stack_pop(g_msc_memory_stack_p, (void**)&char_message_p);
|
||||
rv = lfds611_stack_pop(g_msc_memory_stack_p, (void **)&char_message_p);
|
||||
}
|
||||
|
||||
if (1 == rv) {
|
||||
rv = snprintf(char_message_p, MSC_MAX_MESSAGE_LENGTH, "%"PRIu64" [EVENT] %d ", __sync_fetch_and_add (&g_message_number, 1), protoP);
|
||||
|
||||
if ((0 > rv) || (MSC_MAX_MESSAGE_LENGTH < rv)) {
|
||||
fprintf(stderr, "Error while logging MSC event : %s", &g_msc_proto2str[protoP][0]);
|
||||
goto error_event;
|
||||
}
|
||||
|
||||
va_start(args, format);
|
||||
rv2 = vsnprintf(&char_message_p[rv],MSC_MAX_MESSAGE_LENGTH - rv, format, args);
|
||||
va_end(args);
|
||||
|
||||
if ((0 > rv2) || ((MSC_MAX_MESSAGE_LENGTH - rv) < rv2)) {
|
||||
fprintf(stderr, "Error while logging MSC event : %s", &g_msc_proto2str[protoP][0]);
|
||||
goto error_event;
|
||||
}
|
||||
|
||||
rv += rv2;
|
||||
rv2 = snprintf(&char_message_p[rv],MSC_MAX_MESSAGE_LENGTH - rv, "\n");
|
||||
|
||||
if ((0 > rv2) || ((MSC_MAX_MESSAGE_LENGTH - rv) < rv2)) {
|
||||
fprintf(stderr, "Error while logging MSC event : %s", &g_msc_proto2str[protoP][0]);
|
||||
goto error_event;
|
||||
}
|
||||
|
||||
rv += rv2;
|
||||
new_item_p->message_str = char_message_p;
|
||||
new_item_p->message_str_size = rv;
|
||||
new_item_p->message_bin = NULL;
|
||||
new_item_p->message_bin_size = 0;
|
||||
rv = lfds611_queue_enqueue( g_msc_message_queue_p, new_item_p );
|
||||
if (0 == rv) {
|
||||
|
||||
if (0 == rv) {
|
||||
fprintf(stderr, "Error while lfds611_queue_guaranteed_enqueue message %s in MSC", char_message_p);
|
||||
rv = lfds611_stack_guaranteed_push( g_msc_memory_stack_p, char_message_p );
|
||||
free(new_item_p);
|
||||
}
|
||||
rv = lfds611_stack_guaranteed_push( g_msc_memory_stack_p, char_message_p );
|
||||
free(new_item_p);
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Error while lfds611_stack_pop()\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
error_event:
|
||||
rv = lfds611_stack_guaranteed_push( g_msc_memory_stack_p, char_message_p );
|
||||
@@ -503,12 +689,12 @@ error_event:
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void msc_log_message(
|
||||
const char * const message_operationP,
|
||||
const msc_proto_t proto1P,
|
||||
const msc_proto_t proto2P,
|
||||
const uint8_t * const bytesP,
|
||||
const unsigned int num_bytes,
|
||||
char *format, ...)
|
||||
const char *const message_operationP,
|
||||
const msc_proto_t proto1P,
|
||||
const msc_proto_t proto2P,
|
||||
const uint8_t *const bytesP,
|
||||
const unsigned int num_bytes,
|
||||
char *format, ...)
|
||||
//------------------------------------------------------------------------------
|
||||
{
|
||||
va_list args;
|
||||
@@ -518,56 +704,65 @@ void msc_log_message(
|
||||
msc_queue_item_t *new_item_p = NULL;
|
||||
char *char_message_p = NULL;
|
||||
|
||||
|
||||
if ((MIN_MSC_PROTOS > proto1P) || (MAX_MSC_PROTOS <= proto1P) ||
|
||||
(MIN_MSC_PROTOS > proto2P) || (MAX_MSC_PROTOS <= proto2P) ) {
|
||||
(MIN_MSC_PROTOS > proto2P) || (MAX_MSC_PROTOS <= proto2P) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
new_item_p = malloc(sizeof(msc_queue_item_t));
|
||||
if (NULL != new_item_p) {
|
||||
|
||||
rv = lfds611_stack_pop(g_msc_memory_stack_p, (void**)&char_message_p);
|
||||
if (NULL != new_item_p) {
|
||||
rv = lfds611_stack_pop(g_msc_memory_stack_p, (void **)&char_message_p);
|
||||
|
||||
if (0 == rv) {
|
||||
msc_flush_messages();
|
||||
rv = lfds611_stack_pop(g_msc_memory_stack_p, (void**)&char_message_p);
|
||||
}
|
||||
rv = lfds611_stack_pop(g_msc_memory_stack_p, (void **)&char_message_p);
|
||||
}
|
||||
|
||||
if (1 == rv) {
|
||||
rv = snprintf(char_message_p, MSC_MAX_MESSAGE_LENGTH, "%"PRIu64" [MESSAGE] %d %s %d %"PRIu64" ",
|
||||
__sync_fetch_and_add (&g_message_number, 1), proto1P, message_operationP, proto2P, mac);
|
||||
__sync_fetch_and_add (&g_message_number, 1), proto1P, message_operationP, proto2P, mac);
|
||||
|
||||
if ((0 > rv) || (MSC_MAX_MESSAGE_LENGTH < rv)) {
|
||||
fprintf(stderr, "Error while logging MSC message : %s/%s", &g_msc_proto2str[proto1P][0], &g_msc_proto2str[proto2P][0]);
|
||||
goto error_event;
|
||||
}
|
||||
|
||||
va_start(args, format);
|
||||
rv2 = vsnprintf(&char_message_p[rv],MSC_MAX_MESSAGE_LENGTH - rv, format, args);
|
||||
va_end(args);
|
||||
|
||||
if ((0 > rv2) || ((MSC_MAX_MESSAGE_LENGTH - rv) < rv2)) {
|
||||
fprintf(stderr, "Error while logging MSC message : %s/%s", &g_msc_proto2str[proto1P][0], &g_msc_proto2str[proto2P][0]);
|
||||
goto error_event;
|
||||
}
|
||||
|
||||
rv += rv2;
|
||||
rv2 = snprintf(&char_message_p[rv],MSC_MAX_MESSAGE_LENGTH - rv, "\n");
|
||||
|
||||
if ((0 > rv2) || ((MSC_MAX_MESSAGE_LENGTH - rv) < rv2)) {
|
||||
fprintf(stderr, "Error while logging MSC message : %s/%s", &g_msc_proto2str[proto1P][0], &g_msc_proto2str[proto2P][0]);
|
||||
goto error_event;
|
||||
}
|
||||
|
||||
rv += rv2;
|
||||
new_item_p->message_str = char_message_p;
|
||||
new_item_p->message_str_size = rv;
|
||||
new_item_p->message_bin = NULL; // TO DO
|
||||
new_item_p->message_bin_size = 0; // TO DO
|
||||
rv = lfds611_queue_enqueue( g_msc_message_queue_p, new_item_p );
|
||||
if (0 == rv) {
|
||||
|
||||
if (0 == rv) {
|
||||
fprintf(stderr, "Error while lfds611_queue_guaranteed_enqueue message %s in MSC", char_message_p);
|
||||
rv = lfds611_stack_guaranteed_push( g_msc_memory_stack_p, char_message_p );
|
||||
free(new_item_p);
|
||||
}
|
||||
rv = lfds611_stack_guaranteed_push( g_msc_memory_stack_p, char_message_p );
|
||||
free(new_item_p);
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Error while lfds611_stack_pop()\n");
|
||||
msc_flush_messages();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
error_event:
|
||||
rv = lfds611_stack_guaranteed_push( g_msc_memory_stack_p, char_message_p );
|
||||
@@ -578,8 +773,7 @@ error_event:
|
||||
// function called when oai loader loads the msc shared lib
|
||||
int msc_autoinit(msc_interface_t *msc_interface)
|
||||
//------------------------------------------------------------------------------
|
||||
{
|
||||
|
||||
{
|
||||
msc_interface->msc_init = msc_init;
|
||||
msc_interface->msc_start_use = msc_start_use;
|
||||
msc_interface->msc_end = msc_end;
|
||||
@@ -587,4 +781,4 @@ int msc_autoinit(msc_interface_t *msc_interface)
|
||||
msc_interface->msc_log_message = msc_log_message;
|
||||
msc_interface->msc_loaded = 1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
+57
-53
@@ -25,46 +25,48 @@
|
||||
#include <stdint.h>
|
||||
|
||||
typedef enum {
|
||||
MIN_MSC_ENV = 0,
|
||||
MSC_E_UTRAN = MIN_MSC_ENV,
|
||||
MSC_E_UTRAN_LIPA,
|
||||
MSC_MME_GW,
|
||||
MSC_MME,
|
||||
MSC_SP_GW,
|
||||
MAX_MSC_ENV
|
||||
MIN_MSC_ENV = 0,
|
||||
MSC_E_UTRAN = MIN_MSC_ENV,
|
||||
MSC_E_UTRAN_LIPA,
|
||||
MSC_MME_GW,
|
||||
MSC_MME,
|
||||
MSC_SP_GW,
|
||||
MAX_MSC_ENV
|
||||
} msc_env_t;
|
||||
|
||||
|
||||
typedef enum {
|
||||
MIN_MSC_PROTOS = 0,
|
||||
MSC_IP_UE = MIN_MSC_PROTOS,
|
||||
MSC_NAS_UE,
|
||||
MSC_RRC_UE,
|
||||
MSC_PDCP_UE,
|
||||
MSC_RLC_UE,
|
||||
MSC_MAC_UE,
|
||||
MSC_PHY_UE,
|
||||
MSC_PHY_ENB,
|
||||
MSC_MAC_ENB,
|
||||
MSC_RLC_ENB,
|
||||
MSC_PDCP_ENB,
|
||||
MSC_RRC_ENB,
|
||||
MSC_IP_ENB,
|
||||
MSC_S1AP_ENB,
|
||||
MSC_GTPU_ENB,
|
||||
MSC_GTPU_SGW,
|
||||
MSC_S1AP_MME,
|
||||
MSC_MMEAPP_MME,
|
||||
MSC_NAS_MME,
|
||||
MSC_NAS_EMM_MME,
|
||||
MSC_NAS_ESM_MME,
|
||||
MSC_SP_GWAPP_MME,
|
||||
MSC_S11_MME,
|
||||
MSC_S6A_MME,
|
||||
MSC_HSS,
|
||||
MAX_MSC_PROTOS,
|
||||
MSC_X2AP_SRC_ENB,
|
||||
MSC_X2AP_TARGET_ENB,
|
||||
MIN_MSC_PROTOS = 0,
|
||||
MSC_IP_UE = MIN_MSC_PROTOS,
|
||||
MSC_NAS_UE,
|
||||
MSC_RRC_UE,
|
||||
MSC_PDCP_UE,
|
||||
MSC_RLC_UE,
|
||||
MSC_MAC_UE,
|
||||
MSC_PHY_UE,
|
||||
MSC_PHY_ENB,
|
||||
MSC_MAC_ENB,
|
||||
MSC_RLC_ENB,
|
||||
MSC_PDCP_ENB,
|
||||
MSC_RRC_ENB,
|
||||
MSC_IP_ENB,
|
||||
MSC_S1AP_ENB,
|
||||
MSC_GTPU_ENB,
|
||||
MSC_GTPU_SGW,
|
||||
MSC_S1AP_MME,
|
||||
MSC_MMEAPP_MME,
|
||||
MSC_NAS_MME,
|
||||
MSC_NAS_EMM_MME,
|
||||
MSC_NAS_ESM_MME,
|
||||
MSC_SP_GWAPP_MME,
|
||||
MSC_S11_MME,
|
||||
MSC_S6A_MME,
|
||||
MSC_HSS,
|
||||
MSC_F1AP_CU,
|
||||
MSC_F1AP_DU,
|
||||
MSC_X2AP_SRC_ENB,
|
||||
MSC_X2AP_TARGET_ENB,
|
||||
MAX_MSC_PROTOS,
|
||||
} msc_proto_t;
|
||||
|
||||
|
||||
@@ -73,22 +75,22 @@ typedef enum {
|
||||
#define MSC_AS_TIME_FMT "%05u:%02u"
|
||||
|
||||
#define MSC_AS_TIME_ARGS(CTXT_Pp) \
|
||||
(CTXT_Pp)->frame, \
|
||||
(CTXT_Pp)->subframe
|
||||
(CTXT_Pp)->frame, \
|
||||
(CTXT_Pp)->subframe
|
||||
|
||||
typedef int(*msc_init_t)(const msc_env_t, const int );
|
||||
typedef void(*msc_start_use_t)(void );
|
||||
typedef void(*msc_end_t)(void);
|
||||
typedef void(*msc_log_event_t)(const msc_proto_t,char *, ...);
|
||||
typedef void(*msc_log_message_t)(const char * const, const msc_proto_t, const msc_proto_t,
|
||||
const uint8_t* const, const unsigned int, char * , ...);
|
||||
typedef void(*msc_log_message_t)(const char *const, const msc_proto_t, const msc_proto_t,
|
||||
const uint8_t *const, const unsigned int, char *, ...);
|
||||
typedef struct msc_interface {
|
||||
int msc_loaded;
|
||||
msc_init_t msc_init;
|
||||
msc_start_use_t msc_start_use;
|
||||
msc_end_t msc_end;
|
||||
msc_log_event_t msc_log_event;
|
||||
msc_log_message_t msc_log_message;
|
||||
int msc_loaded;
|
||||
msc_init_t msc_init;
|
||||
msc_start_use_t msc_start_use;
|
||||
msc_end_t msc_end;
|
||||
msc_log_event_t msc_log_event;
|
||||
msc_log_message_t msc_log_message;
|
||||
} msc_interface_t;
|
||||
|
||||
#ifdef MSC_LIBRARY
|
||||
@@ -99,15 +101,17 @@ void msc_end(void);
|
||||
void msc_log_declare_proto(const msc_proto_t protoP);
|
||||
void msc_log_event(const msc_proto_t protoP,char *format, ...);
|
||||
void msc_log_message(
|
||||
const char * const message_operationP,
|
||||
const msc_proto_t receiverP,
|
||||
const msc_proto_t senderP,
|
||||
const uint8_t* const bytesP,
|
||||
const unsigned int num_bytes,
|
||||
char *format, ...);
|
||||
const char *const message_operationP,
|
||||
const msc_proto_t receiverP,
|
||||
const msc_proto_t senderP,
|
||||
const uint8_t *const bytesP,
|
||||
const unsigned int num_bytes,
|
||||
char *format, ...);
|
||||
|
||||
#else
|
||||
|
||||
#define MESSAGE_CHART_GENERATOR msc_interface.msc_loaded
|
||||
|
||||
msc_interface_t msc_interface;
|
||||
#define MSC_INIT(arg1,arg2) if(msc_interface.msc_loaded) msc_interface.msc_init(arg1,arg2)
|
||||
#define MSC_START_USE if(msc_interface.msc_loaded) msc_interface.msc_start_use
|
||||
@@ -119,4 +123,4 @@ msc_interface_t msc_interface;
|
||||
#define MSC_LOG_TX_MESSAGE_FAILED(sENDER, rECEIVER, bYTES, nUMbYTES, fORMAT, aRGS...) if(msc_interface.msc_loaded) msc_interface.msc_log_message("-x",sENDER, rECEIVER, (const uint8_t *)bYTES, nUMbYTES, fORMAT, ##aRGS)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -13,3 +13,4 @@
|
||||
#include "openair2/COMMON/udp_messages_def.h"
|
||||
#include "openair2/COMMON/gtpv1_u_messages_def.h"
|
||||
#include "openair2/COMMON/flexran_messages_def.h"
|
||||
#include "openair2/COMMON/f1ap_messages_def.h"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Author: Laurent THOMAS, Open Cells
|
||||
copyleft: OpenAirInterface Software Alliance and it's licence
|
||||
copyleft: OpenAirInterface Software Alliance and it's licence
|
||||
*/
|
||||
#include <vector>
|
||||
#include <map>
|
||||
@@ -122,7 +122,7 @@ extern "C" {
|
||||
pthread_mutex_unlock (&t->queue_cond_lock);
|
||||
t->admin.func(NULL);
|
||||
pthread_mutex_lock (&t->queue_cond_lock);
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock (&t->queue_cond_lock);
|
||||
return ret;
|
||||
}
|
||||
@@ -290,12 +290,12 @@ extern "C" {
|
||||
struct sched_param sparam;
|
||||
memset(&sparam, 0, sizeof(sparam));
|
||||
sparam.sched_priority = sched_get_priority_max(SCHED_FIFO)-10;
|
||||
policy = SCHED_FIFO ;
|
||||
policy = SCHED_FIFO ;
|
||||
if (pthread_setschedparam(t->thread, policy, &sparam) != 0) {
|
||||
LOG_E(TMR,"task %s : Failed to set pthread priority\n", itti_get_task_name(task_id) );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Author: Laurent THOMAS, Open Cells
|
||||
Copyleft: OpenAirInterface software alliance and it's licence
|
||||
Copyleft: OpenAirInterface software alliance and it's licence
|
||||
*/
|
||||
#ifndef INTERTASK_INTERFACE_H_
|
||||
#define INTERTASK_INTERFACE_H_
|
||||
@@ -302,6 +302,8 @@ typedef struct {
|
||||
TASK_DEF(TASK_MSC, TASK_PRIORITY_MED, 200, NULL, NULL)\
|
||||
TASK_DEF(TASK_GTPV1_U, TASK_PRIORITY_MED, 1000,NULL, NULL)\
|
||||
TASK_DEF(TASK_UDP, TASK_PRIORITY_MED, 1000, NULL, NULL)\
|
||||
TASK_DEF(TASK_CU_F1, TASK_PRIORITY_MED, 200, NULL, NULL) \
|
||||
TASK_DEF(TASK_DU_F1, TASK_PRIORITY_MED, 200, NULL, NULL) \
|
||||
TASK_DEF(TASK_MAX, TASK_PRIORITY_MED, 200, NULL, NULL)
|
||||
|
||||
#define TASK_DEF(TaskID, pRIO, qUEUEsIZE, FuNc, ThreadFunc) { pRIO, qUEUEsIZE, #TaskID, FuNc, ThreadFunc },
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
# code example of adding a command to the telnet server
|
||||
|
||||
The following example is extracted from [the oai `openair1/PHY/CODING/coding_load.c` file](https://gitlab.eurecom.fr/oai/openairinterface5g/blob/develop/openair1/PHY/CODING/coding_load.c).
|
||||
|
||||
```c
|
||||
/*
|
||||
include the telnet server data structures and API definitions
|
||||
*/
|
||||
#include "common/utils/telnetsrv/telnetsrv.h"
|
||||
|
||||
|
||||
/*
|
||||
define the null terminated array of telnetshell_cmddef_t structures
|
||||
which map each sub-command string to a function implementing it.
|
||||
you may also provide a help string which will be printed when
|
||||
the global help command is used. The prototype for the function
|
||||
implementing sub commands must match the `cmdfunc_t` type defined
|
||||
in `telnetsrv.h`
|
||||
*/
|
||||
static int coding_setmod_cmd(char *buff, int debug, telnet_printfunc_t prnt);
|
||||
static telnetshell_cmddef_t coding_cmdarray[] = {
|
||||
{"mode","[sse,avx2,stdc,none]",coding_setmod_cmd},
|
||||
{"","",NULL},
|
||||
};
|
||||
|
||||
/*
|
||||
define the null terminated list of telnetshell_vardef_t structures defining the
|
||||
variables that can be set and get using the pre-defined get and set command
|
||||
of the telnet server
|
||||
*/
|
||||
telnetshell_vardef_t coding_vardef[] = {
|
||||
{"maxiter",TELNET_VARTYPE_INT32,&max_turbo_iterations},
|
||||
{"",0,NULL}
|
||||
};
|
||||
.................
|
||||
/*
|
||||
look for telnet server, if it is loaded, add the coding commands to it
|
||||
we use the shared library loader API to check the telnet server availibility
|
||||
The telnet server TELNET_ADDCMD_FNAME function takes three arguments:
|
||||
1. The name of the telnet command to be added, here "coding"
|
||||
1. The `coding_cmdarray` list of "coding" sub-commands we defined earlier
|
||||
1. The `coding_varde f`list of variables we defined earlier
|
||||
*/
|
||||
add_telnetcmd_func_t addcmd = (add_telnetcmd_func_t)get_shlibmodule_fptr("telnetsrv", TELNET_ADDCMD_FNAME);
|
||||
if (addcmd != NULL) {
|
||||
addcmd("coding",coding_vardef,coding_cmdarray);
|
||||
.......
|
||||
/*
|
||||
functions implementing the "coding mode" sub command, as defined in
|
||||
the `coding_cmdarray` passed earlier to the TELNET_ADDCMD_FNAME function.
|
||||
This function will be called by the telnet server, when the `coding_cmdarray`
|
||||
command is received from the telnet client
|
||||
*/
|
||||
int coding_setmod_cmd(char *buff, int debug, telnet_printfunc_t prnt)
|
||||
{
|
||||
/*
|
||||
1. buff argument is an input argument, pointer to the string received
|
||||
from the telnet client, the command and sub-command parts are removed
|
||||
In this case it points after "coding setmod" and is of no use as
|
||||
we don't have second level sub-commands.
|
||||
1. debug argument is an input argument set by the telnet server
|
||||
1. prnt arguments is also an input argument, a function pointer, to be used
|
||||
in place of printf to print messages on the telnet client interface. As this function
|
||||
is called by the telnet server stdout points to the main executable console,
|
||||
*/
|
||||
if (debug > 0)
|
||||
prnt( "coding_setmod_cmd received %s\n",buff);
|
||||
|
||||
if (strcasestr(buff,"sse") != NULL) {
|
||||
decoding_setmode(MODE_DECODE_SSE);
|
||||
} else if (strcasestr(buff,"avx2") != NULL) {
|
||||
decoding_setmode(MODE_DECODE_AVX2);
|
||||
} else if (strcasestr(buff,"stdc") != NULL) {
|
||||
decoding_setmode(MODE_DECODE_C);
|
||||
} else if (strcasestr(buff,"none") != NULL) {
|
||||
decoding_setmode(MODE_DECODE_NONE);
|
||||
} else {
|
||||
prnt("%s: wrong setmod parameter...\n",buff);
|
||||
}
|
||||
prnt("Coding and decoding current mode: %s\n",modedesc[curmode]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
..............
|
||||
|
||||
```
|
||||
# telnet server API
|
||||
|
||||
```c
|
||||
int add_telnetcmd(char *modulename, telnetshell_vardef_t *var, telnetshell_cmddef_t *cmd)
|
||||
```
|
||||
Add a command and the `cmd` list of sub-commands to the telnet server. After a successful call to `add_telnetcmd` function, the telnet server calls the function defined for each sub-commands in the null terminated `cmd` array, when the character string received from the telnet client matches the command and sub-command strings.
|
||||
Also adds the list of variables described in the `var` array to the list of variable which can be set and read.
|
||||
The function returns -1 if one argument is NULL.
|
||||
The telnet server is dynamically loaded, to use the `add_telnetcmd` function, the shared library loader API should be used to check the availability of the telnet server and retrieve it's address, as shown in [the example at the top of this page](telnetaddcmd.md#code-example-of-adding-a-command-to-the-telnet-server).
|
||||
|
||||
# telnet server public data types
|
||||
## `telnetshell_vardef_t`structure
|
||||
This structure is used by developers to describe the variables that can be set or read using the get,set and getall sub-commands.
|
||||
|
||||
| Fields | type |Description |
|
||||
|:-----------|:------:|:-----------------------|
|
||||
| `varname` | `char[TELNET_CMD_MAXSIZE]` | variable name, as specified when using the get and set commands. |
|
||||
| `vartype` | `char` | Defines the type of the variable pointed by the `varvalptr`field. Supported values: TELNET_VARTYPE_INT32 TELNET_VARTYPE_INT16 TELNET_VARTYPE_INT64 TELNET_VARTYPE_STRING TELNET_VARTYPE_DOUBLE |
|
||||
| `varvalptr` | `void*` | Defines the type of the variable pointed by the `varvalptr`field |
|
||||
|
||||
## `telnetshell_cmddef_t`structure
|
||||
This structure is used by developers to describe the first level sub-commands to be added to the telnet server.
|
||||
|
||||
| Fields | type |Description |
|
||||
|:-----------|:------:|:-----------------------|
|
||||
| `cmdname` | `char[TELNET_CMD_MAXSIZE]` | command name, as tested by the telnet server to check it should call the `cmdfunc` function |
|
||||
| `helpstr` | `char[TELNET_HELPSTR_SIZE]` | character string to print when the elp`command is received from the telnet client |
|
||||
| `cmdfunc` | `cmdfunc_t` | pointer to the function implementing the `cmdname` sub command. |
|
||||
|
||||
[oai telnet server home](telnetsrv.md)
|
||||
@@ -0,0 +1,21 @@
|
||||
# telnet server principles
|
||||
|
||||
The oai telnet server is implemented in a shared library to be loaded by the [oai shared library loader](loader). The implementation includes a `telnetsrv_autoinit` function which is automatically called at load time, starts the telnet server and registers a first set of commands, which are delivered with the server (telnet, softmodem, loader).
|
||||
|
||||
Currently the telnet server only supports one user connection. The same dedicated thread is used to wait for a user connection and process the input received from this connection.
|
||||
|
||||
The telnet server provides an API which can be used by any oai component to add new CLI commands to the server. A pre-defined command can be used to get or set a list of variables.
|
||||
|
||||
|
||||
|
||||
# telnet server source files
|
||||
|
||||
telnet server source files are located in [common/utils/telnetsrv](https://gitlab.eurecom.fr/oai/openairinterface5g/tree/develop/common/utils/telnetsrv)
|
||||
|
||||
1. [telnetsrv.c](https://gitlab.eurecom.fr/oai/openairinterface5g/tree/develop/common/utils/telnetsrv/telnetsrv.c) contains the telnet server implementation, including the implementation of the telnet CLI command.
|
||||
1. [telnetsrv.h](https://gitlab.eurecom.fr/oai/openairinterface5g/tree/develop/common/utils/telnetsrv/telnetsrv.h) is the telnet server include file containing both private and public data type definitions. It also contains API prototypes for functions that are used to register a new command in the server.
|
||||
1. `telnetsrv\_\<XXX\>.c`: implementation of \<XXX\> CLI command which are delivered with the telnet server.
|
||||
1. `telnetsrv\_\<XXX\>.h`: include file for the implementation of XXX CLI command. Usually included only in the corresponding `.c`file
|
||||
1. [telnetsrv_CMakeLists.txt](https://gitlab.eurecom.fr/oai/openairinterface5g/blob/develop/common/utils/telnetsrv/telnetsrv_CMakeLists.txt): CMakelists file containing the cmake instructions to build the telnet server. this file is included in the [global oai CMakelists](https://gitlab.eurecom.fr/oai/openairinterface5g/blob/develop/cmake_targets/CMakeLists.txt).
|
||||
|
||||
[oai telnet server home](telnetsrv.md)
|
||||
@@ -0,0 +1,21 @@
|
||||
getall command can be used to get the list of variables that can bet set or get from the telnet shell. Knowing the names of the variables they can then be set or read. Setting a variable is not always relevant, the telnet server doesn't provide a mechanism to restrict the set command.
|
||||
|
||||
```bash
|
||||
softmodem> telnet getall
|
||||
telnet, debug = 0
|
||||
telnet, prio = 0
|
||||
telnet, loopc = 10
|
||||
telnet, loopd = 5000
|
||||
telnet, phypb = 65000
|
||||
telnet, hsize = 50
|
||||
telnet, hfile = "oaitelnet.history"
|
||||
softmodem> telnet set loopc 100
|
||||
telnet, loopc set to
|
||||
100
|
||||
softmodem> telnet get loopc
|
||||
telnet, loopc = 100
|
||||
softmodem>
|
||||
|
||||
```
|
||||
[oai telnetserver home](telnetsrv.md)
|
||||
[oai telnetserver usage home](telnetusage.md)
|
||||
@@ -0,0 +1,57 @@
|
||||
# oai telnet server global help
|
||||
|
||||
``` bash
|
||||
alblf@at8020-a:~$ telnet 10.133.10.77 9090
|
||||
Trying 10.133.10.77...
|
||||
Connected to 10.133.10.77.
|
||||
Escape character is '^]'.
|
||||
|
||||
softmodem> help
|
||||
module 0 = telnet:
|
||||
telnet [get set] debug <value>
|
||||
telnet [get set] prio <value>
|
||||
telnet [get set] loopc <value>
|
||||
telnet [get set] loopd <value>
|
||||
telnet [get set] phypb <value>
|
||||
telnet [get set] hsize <value>
|
||||
telnet [get set] hfile <value>
|
||||
telnet redirlog [here,file,off]
|
||||
telnet param [prio]
|
||||
telnet history [list,reset]
|
||||
module 1 = softmodem:
|
||||
softmodem show loglvl|thread|config
|
||||
softmodem log (enter help for details)
|
||||
softmodem thread (enter help for details)
|
||||
softmodem exit
|
||||
module 2 = phy:
|
||||
phy disp [phycnt,uedump,uestat UE<x>]
|
||||
module 3 = loader:
|
||||
loader [get set] mainversion <value>
|
||||
loader [get set] defpath <value>
|
||||
loader [get set] maxshlibs <value>
|
||||
loader [get set] numshlibs <value>
|
||||
loader show [params,modules]
|
||||
module 4 = coding:
|
||||
coding [get set] maxiter <value>
|
||||
coding mode [sse,avx2,stdc,none]
|
||||
softmodem>
|
||||
```
|
||||
|
||||
# oai telnet server, specific commands help
|
||||
|
||||
``` bash
|
||||
softmodem> softmodem log help
|
||||
log sub commands:
|
||||
show: display current log configuration
|
||||
online, noonline: enable or disable console logs
|
||||
enable, disable id1-id2: enable or disable logs for components index id1 to id2
|
||||
level_<level> id1-id2: set log level to <level> for components index id1 to id2
|
||||
level_<verbosity> id1-id2: set log verbosity to <verbosity> for components index id1 to id2
|
||||
use the show command to get the values for <level>, <verbosity> and the list of component indexes that can be used for id1 and id2
|
||||
softmodem>
|
||||
|
||||
|
||||
```
|
||||
|
||||
[oai telnetserver home](telnetsrv.md)
|
||||
[oai telnetserver usage home](telnetusage.md)
|
||||
@@ -0,0 +1,44 @@
|
||||
The telnet server implements a simple history system
|
||||
```bash
|
||||
softmodem> telnet history list
|
||||
1: telnet history list
|
||||
2: telnet history list
|
||||
3: help
|
||||
4: loader show modules
|
||||
5: softmodem show loglvl
|
||||
6: help
|
||||
7: telnet history
|
||||
8: help
|
||||
9: telnet history list
|
||||
10: help
|
||||
11: loader show modules
|
||||
12: softmodem show loglvl
|
||||
13: softmodem log help
|
||||
14: softmodem log disable 0-35
|
||||
15: softmodem log show
|
||||
16: help
|
||||
17: telnet history list
|
||||
18: loader show modules
|
||||
19: softmodem thread show
|
||||
20: help
|
||||
21: softmodem thread help
|
||||
22: softmodem log show
|
||||
23: softmodem log help
|
||||
24: softmodem log level_error 0-4
|
||||
25: loader show modules
|
||||
26: loader show config
|
||||
27: help
|
||||
28: loader show params
|
||||
29: loader show modules
|
||||
softmodem> !28
|
||||
softmodem> loader show params
|
||||
loader parameters:
|
||||
Main executable build version: "Branch: develop-telnet-loader-fixes Abrev. Hash: e56ae69 Date: Fri Mar 9 16:47:08 2018 +0100"
|
||||
Default shared lib path: ""
|
||||
Max number of shared lib : 10
|
||||
softmodem>
|
||||
|
||||
```
|
||||
|
||||
[oai telnetserver home](telnetsrv.md)
|
||||
[oai telnetserver usage home](telnetusage.md)
|
||||
@@ -0,0 +1,47 @@
|
||||
loader command can be used to check loader configuration parameters and the list of loaded shared libraries and for each library the list of available functions.
|
||||
|
||||
```bash
|
||||
softmodem> loader show params
|
||||
loader parameters:
|
||||
Main executable build version: "Branch: develop-telnet-loader-fixes Abrev. Hash: e56ae69 Date: Fri Mar 9 16:47:08 2018 +0100"
|
||||
Default shared lib path: ""
|
||||
Max number of shared lib : 10
|
||||
softmodem> loader show modules
|
||||
4 shared lib have been dynamicaly loaded by the oai loader
|
||||
Module 0: telnetsrv
|
||||
Shared library build version: "Branch: develop-telnet-loader-fixes Abrev. Hash: e56ae69 Date: Fri Mar 9 16:47:08 2018 +0100"
|
||||
Shared library path: "libtelnetsrv.so"
|
||||
1 function pointers registered:
|
||||
function 0 add_telnetcmd at 0x7ff8b772a2b0
|
||||
Module 1: NB_IoT
|
||||
Shared library build version: ""
|
||||
Shared library path: "libNB_IoT.so"
|
||||
1 function pointers registered:
|
||||
function 0 RCConfig_NbIoT at 0x7ff8b6b1b390
|
||||
Module 2: coding
|
||||
Shared library build version: "Branch: develop-telnet-loader-fixes Abrev. Hash: e56ae69 Date: Fri Mar 9 16:47:08 2018 +0100"
|
||||
Shared library path: "libcoding.so"
|
||||
13 function pointers registered:
|
||||
function 0 init_td8 at 0x7ff8adde63a0
|
||||
function 1 init_td16 at 0x7ff8adde9760
|
||||
function 2 init_td16avx2 at 0x7ff8addec050
|
||||
function 3 phy_threegpplte_turbo_decoder8 at 0x7ff8adde6780
|
||||
function 4 phy_threegpplte_turbo_decoder16 at 0x7ff8adde9a90
|
||||
function 5 phy_threegpplte_turbo_decoder_scalar at 0x7ff8addef4a0
|
||||
function 6 phy_threegpplte_turbo_decoder16avx2 at 0x7ff8addec530
|
||||
function 7 free_td8 at 0x7ff8adde61d0
|
||||
function 8 free_td16 at 0x7ff8adde9590
|
||||
function 9 free_td16avx2 at 0x7ff8addebe80
|
||||
function 10 threegpplte_turbo_encoder_sse at 0x7ff8adde45b0
|
||||
function 11 threegpplte_turbo_encoder at 0x7ff8adde4a30
|
||||
function 12 init_encoder_sse at 0x7ff8adde49d0
|
||||
Module 3: oai_device
|
||||
Shared library build version: ""
|
||||
Shared library path: "liboai_device_usrp.so"
|
||||
1 function pointers registered:
|
||||
function 0 device_init at 0x7ff8ac16a7a0
|
||||
softmodem>
|
||||
```
|
||||
|
||||
[oai telnetserver home](telnetsrv.md)
|
||||
[oai telnetserver usage home](telnetusage.md)
|
||||
@@ -0,0 +1,96 @@
|
||||
The log command can be used to get the status of the log parameters and to dynamically modify these parameters. The log command has its own [help](telnethelp.md#oai-telnet-server-specific-commands-help)
|
||||
```bash
|
||||
softmodem> softmodem log disable 0-35
|
||||
log level/verbosity comp 0 PHY set to info / medium (disabled)
|
||||
log level/verbosity comp 1 MAC set to info / medium (disabled)
|
||||
log level/verbosity comp 2 EMU set to info / medium (disabled)
|
||||
log level/verbosity comp 3 OCG set to info / medium (disabled)
|
||||
log level/verbosity comp 4 OMG set to info / medium (disabled)
|
||||
log level/verbosity comp 5 OPT set to info / medium (disabled)
|
||||
log level/verbosity comp 6 OTG set to info / medium (disabled)
|
||||
log level/verbosity comp 7 OTG_LATENCY set to info / medium (disabled)
|
||||
log level/verbosity comp 8 OTG_LATENCY_BG set to info / medium (disabled)
|
||||
log level/verbosity comp 9 OTG_GP set to info / medium (disabled)
|
||||
log level/verbosity comp 10 OTG_GP_BG set to info / medium (disabled)
|
||||
log level/verbosity comp 11 OTG_JITTER set to info / medium (disabled)
|
||||
log level/verbosity comp 12 RLC set to info / medium (disabled)
|
||||
log level/verbosity comp 13 PDCP set to info / medium (disabled)
|
||||
log level/verbosity comp 14 RRC set to info / medium (disabled)
|
||||
log level/verbosity comp 15 NAS set to info / medium (disabled)
|
||||
log level/verbosity comp 16 PERF set to info / medium (disabled)
|
||||
log level/verbosity comp 17 OIP set to info / medium (disabled)
|
||||
log level/verbosity comp 18 CLI set to info / medium (disabled)
|
||||
log level/verbosity comp 19 MSC set to info / medium (disabled)
|
||||
log level/verbosity comp 20 OCM set to info / medium (disabled)
|
||||
log level/verbosity comp 21 UDP set to info / medium (disabled)
|
||||
log level/verbosity comp 22 GTPV1U set to info / medium (disabled)
|
||||
log level/verbosity comp 23 comp23? set to info / medium (disabled)
|
||||
log level/verbosity comp 24 S1AP set to info / medium (disabled)
|
||||
log level/verbosity comp 25 SCTP set to info / medium (disabled)
|
||||
log level/verbosity comp 26 HW set to info / medium (disabled)
|
||||
log level/verbosity comp 27 OSA set to info / medium (disabled)
|
||||
log level/verbosity comp 28 eRAL set to info / medium (disabled)
|
||||
log level/verbosity comp 29 mRAL set to info / medium (disabled)
|
||||
log level/verbosity comp 30 ENB_APP set to info / medium (disabled)
|
||||
log level/verbosity comp 31 FLEXRAN_AGENT set to info / medium (disabled)
|
||||
log level/verbosity comp 32 TMR set to info / medium (disabled)
|
||||
log level/verbosity comp 33 USIM set to info / medium (disabled)
|
||||
log level/verbosity comp 34 LOCALIZE set to info / medium (disabled)
|
||||
log level/verbosity comp 35 RRH set to info / medium (disabled)
|
||||
softmodem> softmodem log show
|
||||
Available log levels:
|
||||
emerg alert crit error warn notice info debug file trace
|
||||
Available verbosity:
|
||||
none low medium high full
|
||||
component verbosity level enabled
|
||||
00 PHY: medium info N
|
||||
01 MAC: medium info N
|
||||
02 EMU: medium info N
|
||||
03 OCG: medium info N
|
||||
04 OMG: medium info N
|
||||
05 OPT: medium info N
|
||||
06 OTG: medium info N
|
||||
07 OTG_LATENCY: medium info N
|
||||
08 OTG_LATENCY_BG: medium info N
|
||||
09 OTG_GP: medium info N
|
||||
10 OTG_GP_BG: medium info N
|
||||
11 OTG_JITTER: medium info N
|
||||
12 RLC: medium info N
|
||||
13 PDCP: medium info N
|
||||
14 RRC: medium info N
|
||||
15 NAS: medium info N
|
||||
16 PERF: medium info N
|
||||
17 OIP: medium info N
|
||||
18 CLI: medium info N
|
||||
19 MSC: medium info N
|
||||
20 OCM: medium info N
|
||||
21 UDP: medium info N
|
||||
22 GTPV1U: medium info N
|
||||
23 comp23?: medium info N
|
||||
24 S1AP: medium info N
|
||||
25 SCTP: medium info N
|
||||
26 HW: medium info N
|
||||
27 OSA: medium info N
|
||||
28 eRAL: medium info N
|
||||
29 mRAL: medium info N
|
||||
30 ENB_APP: medium info N
|
||||
31 FLEXRAN_AGENT: medium info N
|
||||
32 TMR: medium info N
|
||||
33 USIM: medium info N
|
||||
34 LOCALIZE: medium info N
|
||||
35 RRH: medium info N
|
||||
36 comp36?: medium info Y
|
||||
37 LOADER: medium alert Y
|
||||
softmodem> softmodem log level_error 0-4
|
||||
log level/verbosity comp 0 PHY set to error / medium (enabled)
|
||||
log level/verbosity comp 1 MAC set to error / medium (enabled)
|
||||
log level/verbosity comp 2 EMU set to error / medium (enabled)
|
||||
log level/verbosity comp 3 OCG set to error / medium (enabled)
|
||||
log level/verbosity comp 4 OMG set to error / medium (enabled)
|
||||
softmodem> exit
|
||||
Connection closed by foreign host.
|
||||
```
|
||||
|
||||
[oai telnetserver home](telnetsrv.md)
|
||||
[oai telnetserver usage home](telnetusage.md)
|
||||
[oai Wikis home](https://gitlab.eurecom.fr/oai/openairinterface5g/wikis/home)
|
||||
@@ -0,0 +1,40 @@
|
||||
The telnet server includes a **_loop_** command that can be used to iterate a given command. The number of iterations and the delay, in ms between two iterations can be modified, as shown in the following example:
|
||||
|
||||
```bash
|
||||
softmodem> telnet get loopc
|
||||
telnet, loopc = 10
|
||||
softmodem> telnet get loopd
|
||||
telnet, loopd = 2000
|
||||
softmodem> telnet set loopd 1000
|
||||
telnet, loopd set to
|
||||
1000
|
||||
softmodem> loop softmodem show thread
|
||||
2018-03-27 17:58:49.000 2/10
|
||||
id name state USRmod KRNmod prio nice vsize proc pol
|
||||
|
||||
3946 lte-softmodem S 20005 9440 20 0 236560384 2 0 other
|
||||
|
||||
3946 lte-softmodem S 7 95 20 0 236560384 2 0 other
|
||||
3948 telnet R 0 0 20 0 236560384 2 0 other
|
||||
3949 ITTI acceptor S 2 9 20 0 236560384 2 0 other
|
||||
3951 ITTI 12 S 2 2 20 0 236560384 7 0 other
|
||||
3952 ITTI 11 S 0 0 20 0 236560384 0 0 other
|
||||
3953 ITTI 9 S 0 0 20 0 236560384 1 0 other
|
||||
3954 ITTI 7 S 0 0 20 0 236560384 7 0 other
|
||||
3955 ITTI 8 S 0 0 20 0 236560384 7 0 other
|
||||
3956 ITTI 4 S 35 0 20 0 236560384 2 0 other
|
||||
3957 ru_thread S 15366 3072 -10 0 236560384 0 2 rt: rr
|
||||
3958 ru_thread_prach S 0 0 -10 0 236560384 7 1 rt: fifo
|
||||
3959 fep_thread S 1874 123 -10 0 236560384 5 1 rt: fifo
|
||||
3960 feptx_thread S 1554 101 -10 0 236560384 7 1 rt: fifo
|
||||
3969 ru_thread S 0 0 -10 0 236560384 0 2 rt: rr
|
||||
3970 ru_thread S 1313 5522 -10 0 236560384 5 2 rt: rr
|
||||
3971 ru_thread S 4 6 -10 0 236560384 1 2 rt: rr
|
||||
3972 lte-softmodem S 318 9 -10 0 236560384 7 1 rt: fifo
|
||||
3973 lte-softmodem S 6 13 -10 0 236560384 4 1 rt: fifo
|
||||
|
||||
```
|
||||
A **_loop_** command can be interrupted by pressing the **_enter_** key till getting the prompt.
|
||||
|
||||
[oai telnetserver home](telnetsrv.md)
|
||||
[oai telnetserver usage home](telnetusage.md)
|
||||
@@ -0,0 +1,7 @@
|
||||
The oai embedded telnet server is an optional monitoring and debugging tool. It provides a simple Command Line Interface to the oai softmem. New commands can easily be added by developers to the telnet server.
|
||||
|
||||
* [Using the telnet server](telnetusage.md)
|
||||
* [Adding commands to the oai telnet server](telnetaddcmd.md)
|
||||
* [telnet server architecture ](telnetarch.md)
|
||||
|
||||
[oai Wikis home](https://gitlab.eurecom.fr/oai/openairinterface5g/wikis/home)
|
||||
@@ -0,0 +1,39 @@
|
||||
# starting the softmodem with the telnet server
|
||||
By default the embedded telnet server, which is implemented in a shared library, is not built. It can be built after compiling the softmodem executable using the `build_oai` script:
|
||||
|
||||
```bash
|
||||
cd \<oai repository\>/openairinterface5g
|
||||
source oaienv
|
||||
cd cmake_targets
|
||||
./build_oai --build-telnetsrv
|
||||
```
|
||||
|
||||
This will create the `libtelnetsrv.so` file in the `targets/bin` and `cmake_targets/lte_build_oai/build` sub directories of the oai repository.
|
||||
|
||||
When starting the softmodem, you must specify the **_\-\-telnetsrv_** option to load and start the telnet server. The telnet server is loaded via the [oai shared library loader](loader).
|
||||
|
||||
# using the Command Line Interface
|
||||
By default the telnet server listen on all the ip addresses configured on the system and on port 9090. This behavior can be changed using the `listenaddr` and `listenport` parameters.
|
||||
The telnet server includes a basic help, listing available commands and some commands also provide a specific detailed help sub-command.
|
||||
Below are examples of telnet sessions:
|
||||
|
||||
* [getting help](telnethelp.md)
|
||||
* [using the history](telnethist.md)
|
||||
* [using the get and set commands](telnetgetset.md)
|
||||
* [using the loop command](telnetloop.md)
|
||||
* [loader command](telnetloader.md)
|
||||
* [log command](telnetlog.md)
|
||||
|
||||
# telnet server parameters
|
||||
The telnet server is using the [oai configuration module](Config/Rtusage). Telnet parameters must be specified in the `telnetsrv` section. Some parameters can be modified via the telnet telnet server command, as specified in the last column of the following table.
|
||||
|
||||
| name | type | default | description | dynamic |
|
||||
|:---:|:---:|:---:|:----|:----:|
|
||||
| `listenaddr` | `ipV4 address, ascii format` | "0.0.0.0" | local address the server is listening on| N |
|
||||
| `listenport` | `integer` | 9090 | port number the server is listening on | N |
|
||||
| `loopcount` | `integer` | 10 | number of iterations for the loop command | Y |
|
||||
| `loopdelay` | `integer` | 5000 | delay (in ms) between 2 loop command iterations | Y |
|
||||
| `histfile` | `character string` | "oaitelnet.history" | file used for command history persistency | Y |
|
||||
| `histfsize` | `integer` | 50 | maximum number of commands saved in the history | Y |
|
||||
|
||||
[oai telnet server home](telnetsrv.md)
|
||||
+576
-596
File diff suppressed because it is too large
Load Diff
@@ -69,7 +69,8 @@ typedef struct cmddef {
|
||||
#define TELNET_VARTYPE_INT64 3
|
||||
#define TELNET_VARTYPE_STRING 4
|
||||
#define TELNET_VARTYPE_DOUBLE 5
|
||||
//#define TELNET_VARTYPE_PTR 6
|
||||
#define TELNET_VARTYPE_INT8 6
|
||||
#define TELNET_VARTYPE_UINT 7
|
||||
typedef struct variabledef {
|
||||
char varname[TELNET_CMD_MAXSIZE];
|
||||
char vartype;
|
||||
|
||||
@@ -9,6 +9,7 @@ set(TELNETSRV_SOURCE
|
||||
${TELNETROOT}/telnetsrv_phycmd.c
|
||||
${TELNETROOT}/telnetsrv_proccmd.c
|
||||
${TELNETROOT}/telnetsrv_loader.c
|
||||
${TELNETROOT}/telnetsrv_measurements.c
|
||||
)
|
||||
|
||||
#set(TELNETSRV_ETHDEVCMD_SOURCE
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/*! \file common/utils/telnetsrv/telnetsrv_cpumeasur_def.h
|
||||
* \brief: definitions of macro used to initialize the telnet_ltemeasurdef_t
|
||||
* \ strucures arrays which are then used by the display functions
|
||||
* \ in telnetsrv_measurements.c.
|
||||
* \author Francois TABURET
|
||||
* \date 2019
|
||||
* \version 0.1
|
||||
* \company NOKIA BellLabs France
|
||||
* \email: francois.taburet@nokia-bell-labs.com
|
||||
* \note
|
||||
* \warning
|
||||
*/
|
||||
|
||||
|
||||
#define CPU_PHYENB_MEASURE \
|
||||
{ \
|
||||
{"phy_proc_tx", &(phyvars->phy_proc_tx),0},\
|
||||
{"phy_proc_rx", &(phyvars->phy_proc_rx),0},\
|
||||
{"rx_prach", &(phyvars->rx_prach),0},\
|
||||
{"ofdm_mod", &(phyvars->ofdm_mod_stats),0},\
|
||||
{"dlsch_common_and_dci", &(phyvars->dlsch_common_and_dci),0},\
|
||||
{"dlsch_ue_specific", &(phyvars->dlsch_ue_specific),0},\
|
||||
{"dlsch_encoding", &(phyvars->dlsch_encoding_stats),0},\
|
||||
{"dlsch_modulation", &(phyvars->dlsch_modulation_stats),0},\
|
||||
{"dlsch_scrambling", &(phyvars->dlsch_scrambling_stats),0},\
|
||||
{"dlsch_rate_matching", &(phyvars->dlsch_rate_matching_stats),0},\
|
||||
{"dlsch_turbo_encod_prep", &(phyvars->dlsch_turbo_encoding_preperation_stats),0},\
|
||||
{"dlsch_turbo_encod_segm", &(phyvars->dlsch_turbo_encoding_segmentation_stats),0},\
|
||||
{"dlsch_turbo_encod", &(phyvars->dlsch_turbo_encoding_stats),0},\
|
||||
{"dlsch_turbo_encod_waiting", &(phyvars->dlsch_turbo_encoding_waiting_stats),0},\
|
||||
{"dlsch_turbo_encod_signal", &(phyvars->dlsch_turbo_encoding_signal_stats),0},\
|
||||
{"dlsch_turbo_encod_main", &(phyvars->dlsch_turbo_encoding_main_stats),0},\
|
||||
{"dlsch_turbo_encod_wakeup0", &(phyvars->dlsch_turbo_encoding_wakeup_stats0),0},\
|
||||
{"dlsch_turbo_encod_wakeup1", &(phyvars->dlsch_turbo_encoding_wakeup_stats1),0},\
|
||||
{"dlsch_interleaving", &(phyvars->dlsch_interleaving_stats),0},\
|
||||
{"rx_dft", &(phyvars->rx_dft_stats),0},\
|
||||
{"ulsch_channel_estimation", &(phyvars->ulsch_channel_estimation_stats),0},\
|
||||
{"ulsch_freq_offset_estimation", &(phyvars->ulsch_freq_offset_estimation_stats),0},\
|
||||
{"ulsch_decoding", &(phyvars->ulsch_decoding_stats),0},\
|
||||
{"ulsch_demodulation", &(phyvars->ulsch_demodulation_stats),0},\
|
||||
{"ulsch_rate_unmatching", &(phyvars->ulsch_rate_unmatching_stats),0},\
|
||||
{"ulsch_turbo_decoding", &(phyvars->ulsch_turbo_decoding_stats),0},\
|
||||
{"ulsch_deinterleaving", &(phyvars->ulsch_deinterleaving_stats),0},\
|
||||
{"ulsch_demultiplexing", &(phyvars->ulsch_demultiplexing_stats),0},\
|
||||
{"ulsch_llr", &(phyvars->ulsch_llr_stats),0},\
|
||||
{"ulsch_tc_init", &(phyvars->ulsch_tc_init_stats),0},\
|
||||
{"ulsch_tc_alpha", &(phyvars->ulsch_tc_alpha_stats),0},\
|
||||
{"ulsch_tc_beta", &(phyvars->ulsch_tc_beta_stats),0},\
|
||||
{"ulsch_tc_gamma", &(phyvars->ulsch_tc_gamma_stats),0},\
|
||||
{"ulsch_tc_ext", &(phyvars->ulsch_tc_ext_stats),0},\
|
||||
{"ulsch_tc_intl1", &(phyvars->ulsch_tc_intl1_stats),0},\
|
||||
{"ulsch_tc_intl2", &(phyvars->ulsch_tc_intl2_stats),0},\
|
||||
}
|
||||
|
||||
#define CPU_MACENB_MEASURE \
|
||||
{ \
|
||||
{"eNB_scheduler", &(macvars->eNB_scheduler),0},\
|
||||
{"schedule_si", &(macvars->schedule_si),0},\
|
||||
{"schedule_ra", &(macvars->schedule_ra),0},\
|
||||
{"schedule_ulsch", &(macvars->schedule_ulsch),0},\
|
||||
{"fill_DLSCH_dci", &(macvars->fill_DLSCH_dci),0},\
|
||||
{"schedule_dlsch_pre", &(macvars->schedule_dlsch_preprocessor),0},\
|
||||
{"schedule_dlsch", &(macvars->schedule_dlsch),0},\
|
||||
{"schedule_mch", &(macvars->schedule_mch),0},\
|
||||
{"rx_ulsch_sdu", &(macvars->rx_ulsch_sdu),0},\
|
||||
{"schedule_pch", &(macvars->schedule_pch),0},\
|
||||
}
|
||||
|
||||
#define CPU_PDCPENB_MEASURE \
|
||||
{ \
|
||||
{"pdcp_run", &(pdcpvars->pdcp_run),0},\
|
||||
{"data_req", &(pdcpvars->data_req),0},\
|
||||
{"data_ind", &(pdcpvars->data_ind),0},\
|
||||
{"apply_security", &(pdcpvars->apply_security),0},\
|
||||
{"validate_security", &(pdcpvars->validate_security),0},\
|
||||
{"pdcp_ip", &(pdcpvars->pdcp_ip),0},\
|
||||
{"ip_pdcp", &(pdcpvars->ip_pdcp),0},\
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/*! \file common/utils/telnetsrv/telnetsrv_ltemeasur_def.h
|
||||
* \brief: definitions of macro used to initialize the telnet_ltemeasurdef_t
|
||||
* \ strucures arrays which are then used by the display functions
|
||||
* \ in telnetsrv_measurements.c.
|
||||
* \author Francois TABURET
|
||||
* \date 2019
|
||||
* \version 0.1
|
||||
* \company NOKIA BellLabs France
|
||||
* \email: francois.taburet@nokia-bell-labs.com
|
||||
* \note
|
||||
* \warning
|
||||
*/
|
||||
|
||||
|
||||
#define LTEMAC_MEASURE \
|
||||
{ \
|
||||
{"total_num_bcch_pdu", &(macstatptr->total_num_bcch_pdu),TELNET_VARTYPE_INT32,0},\
|
||||
{"bcch_buffer", &(macstatptr->bcch_buffer),TELNET_VARTYPE_INT32,0},\
|
||||
{"total_bcch_buffer", &(macstatptr->total_bcch_buffer),TELNET_VARTYPE_INT32,0},\
|
||||
{"bcch_mcs", &(macstatptr->bcch_mcs),TELNET_VARTYPE_INT32,0},\
|
||||
{"total_num_ccch_pdu", &(macstatptr->total_num_ccch_pdu),TELNET_VARTYPE_INT32,0},\
|
||||
{"ccch_buffer", &(macstatptr->ccch_buffer),TELNET_VARTYPE_INT32,0},\
|
||||
{"total_ccch_buffer", &(macstatptr->total_ccch_buffer),TELNET_VARTYPE_INT32,0},\
|
||||
{"ccch_mcs", &(macstatptr->ccch_mcs),TELNET_VARTYPE_INT32,0},\
|
||||
{"total_num_pcch_pdu", &(macstatptr->total_num_pcch_pdu),TELNET_VARTYPE_INT32,0},\
|
||||
{"pcch_buffer", &(macstatptr->pcch_buffer),TELNET_VARTYPE_INT32,0},\
|
||||
{"total_pcch_buffer", &(macstatptr->total_pcch_buffer),TELNET_VARTYPE_INT32,0},\
|
||||
{"pcch_mcs", &(macstatptr->pcch_mcs),TELNET_VARTYPE_INT32,0},\
|
||||
{"num_dlactive_UEs", &(macstatptr->num_dlactive_UEs),TELNET_VARTYPE_INT16,0},\
|
||||
{"available_prbs", &(macstatptr->available_prbs),TELNET_VARTYPE_INT16,0},\
|
||||
{"total_available_prbs", &(macstatptr->total_available_prbs),TELNET_VARTYPE_INT32,0},\
|
||||
{"available_ncces", &(macstatptr->available_ncces),TELNET_VARTYPE_INT16,0},\
|
||||
{"dlsch_bitrate", &(macstatptr->dlsch_bitrate),TELNET_VARTYPE_INT32,0},\
|
||||
{"dlsch_bytes_tx", &(macstatptr->dlsch_bytes_tx),TELNET_VARTYPE_INT32,0},\
|
||||
{"dlsch_pdus_tx", &(macstatptr->dlsch_pdus_tx),TELNET_VARTYPE_INT32,0},\
|
||||
{"total_dlsch_bitrate", &(macstatptr->total_dlsch_bitrate),TELNET_VARTYPE_INT32,0},\
|
||||
{"total_dlsch_bytes_tx", &(macstatptr->total_dlsch_bytes_tx),TELNET_VARTYPE_INT32,0},\
|
||||
{"total_dlsch_pdus_tx", &(macstatptr->total_dlsch_pdus_tx),TELNET_VARTYPE_INT32,0},\
|
||||
{"ulsch_bitrate", &(macstatptr->ulsch_bitrate),TELNET_VARTYPE_INT32,0},\
|
||||
{"ulsch_bytes_rx", &(macstatptr->ulsch_bytes_rx),TELNET_VARTYPE_INT32,0},\
|
||||
{"ulsch_pdus_rx", &(macstatptr->ulsch_pdus_rx),TELNET_VARTYPE_INT32,0},\
|
||||
{"total_ulsch_bitrate", &(macstatptr->total_ulsch_bitrate),TELNET_VARTYPE_INT32,0},\
|
||||
{"total_ulsch_bytes_rx", &(macstatptr->total_ulsch_bytes_rx),TELNET_VARTYPE_INT32,0},\
|
||||
{"total_ulsch_pdus_rx", &(macstatptr->total_ulsch_pdus_rx),TELNET_VARTYPE_INT32,0},\
|
||||
{"sched_decisions", &(macstatptr->sched_decisions),TELNET_VARTYPE_INT32,0},\
|
||||
{"missed_deadlines", &(macstatptr->missed_deadlines),TELNET_VARTYPE_INT32,0},\
|
||||
}
|
||||
|
||||
#define LTEMAC_UEMEASURE \
|
||||
{ \
|
||||
{"dlsch_mcs1", &(macuestatptr->dlsch_mcs1),TELNET_VARTYPE_INT8,0},\
|
||||
{"dlsch_mcs2", &(macuestatptr->dlsch_mcs2),TELNET_VARTYPE_INT8,0},\
|
||||
{"rbs_used", &(macuestatptr->rbs_used),TELNET_VARTYPE_INT32,0},\
|
||||
{"rbs_used_retx", &(macuestatptr->rbs_used_retx),TELNET_VARTYPE_INT16,0},\
|
||||
{"total_rbs_used", &(macuestatptr->total_rbs_used),TELNET_VARTYPE_INT16,0},\
|
||||
{"ncce_used", &(macuestatptr->ncce_used),TELNET_VARTYPE_INT16,0},\
|
||||
{"ncce_used_retx", &(macuestatptr->ncce_used_retx),TELNET_VARTYPE_INT16,0},\
|
||||
{"TBS", &(macuestatptr->TBS),TELNET_VARTYPE_INT32,0},\
|
||||
{"total_pdu_bytes", &(macuestatptr->total_pdu_bytes),TELNET_VARTYPE_INT64,0},\
|
||||
{"total_num_pdus", &(macuestatptr->total_num_pdus),TELNET_VARTYPE_INT32,0},\
|
||||
{"overhead_bytes", &(macuestatptr->overhead_bytes),TELNET_VARTYPE_INT64,0},\
|
||||
{"crnti", &(macuestatptr->crnti),TELNET_VARTYPE_INT16,0},\
|
||||
{"normalized_rx_power", &(macuestatptr->normalized_rx_power),TELNET_VARTYPE_INT32,0},\
|
||||
{"target_rx_power", &(macuestatptr->target_rx_power),TELNET_VARTYPE_INT32,0},\
|
||||
{"ulsch_mcs1", &(macuestatptr->ulsch_mcs1),TELNET_VARTYPE_INT8,0},\
|
||||
{"ulsch_mcs2", &(macuestatptr->ulsch_mcs2),TELNET_VARTYPE_INT8,0},\
|
||||
{"rbs_used_rx", &(macuestatptr->rbs_used_rx),TELNET_VARTYPE_INT32,0},\
|
||||
{"rbs_used_retx_rx", &(macuestatptr->rbs_used_retx_rx),TELNET_VARTYPE_INT32,0},\
|
||||
{"total_rbs_used_rx", &(macuestatptr->total_rbs_used_rx),TELNET_VARTYPE_INT32,0},\
|
||||
{"ulsch_TBS", &(macuestatptr->ulsch_TBS),TELNET_VARTYPE_INT32,0},\
|
||||
{"total_pdu_bytes_rx", &(macuestatptr->total_pdu_bytes_rx),TELNET_VARTYPE_INT64,0},\
|
||||
{"total_num_pdus_rx", &(macuestatptr->total_num_pdus_rx),TELNET_VARTYPE_INT32,0},\
|
||||
{"num_errors_rx", &(macuestatptr->num_errors_rx),TELNET_VARTYPE_INT32,0},\
|
||||
}
|
||||
|
||||
#define LTE_RLCMEASURE \
|
||||
{ \
|
||||
{"rlc_mode", NULL, TELNET_VARTYPE_UINT, 0},\
|
||||
{"tx_pdcp_sdu", NULL, TELNET_VARTYPE_UINT, 0},\
|
||||
{"tx_pdcp_bytes", NULL, TELNET_VARTYPE_UINT, 0},\
|
||||
{"tx_pdcp_sdu_discarded", NULL, TELNET_VARTYPE_UINT, 0},\
|
||||
{"tx_pdcp_bytes_discarded", NULL, TELNET_VARTYPE_UINT, 0},\
|
||||
{"tx_data_pdu", NULL, TELNET_VARTYPE_UINT, 0},\
|
||||
{"tx_data_bytes", NULL, TELNET_VARTYPE_UINT, 0},\
|
||||
{"tx_retransmit_pdu_by_status", NULL, TELNET_VARTYPE_UINT, 0},\
|
||||
{"tx_retransmit_bytes_by_status", NULL, TELNET_VARTYPE_UINT, 0},\
|
||||
{"tx_retransmit_pdu", NULL, TELNET_VARTYPE_UINT, 0},\
|
||||
{"tx_retransmit_bytes", NULL, TELNET_VARTYPE_UINT, 0},\
|
||||
{"tx_control_pdu", NULL, TELNET_VARTYPE_UINT, 0},\
|
||||
{"tx_control_bytes", NULL, TELNET_VARTYPE_UINT, 0},\
|
||||
{"rx_pdcp_sdu", NULL, TELNET_VARTYPE_UINT, 0},\
|
||||
{"rx_pdcp_bytes", NULL, TELNET_VARTYPE_UINT, 0},\
|
||||
{"rx_data_pdus_duplicate", NULL, TELNET_VARTYPE_UINT, 0},\
|
||||
{"rx_data_bytes_duplicate", NULL, TELNET_VARTYPE_UINT, 0},\
|
||||
{"rx_data_pdu", NULL, TELNET_VARTYPE_UINT, 0},\
|
||||
{"rx_data_bytes", NULL, TELNET_VARTYPE_UINT, 0},\
|
||||
{"rx_data_pdu_dropped", NULL, TELNET_VARTYPE_UINT, 0},\
|
||||
{"rx_data_bytes_dropped", NULL, TELNET_VARTYPE_UINT, 0},\
|
||||
{"rx_data_pdu_out_of_window", NULL, TELNET_VARTYPE_UINT, 0},\
|
||||
{"rx_data_bytes_out_of_window", NULL, TELNET_VARTYPE_UINT, 0},\
|
||||
{"rx_control_pdu", NULL, TELNET_VARTYPE_UINT, 0},\
|
||||
{"rx_control_bytes", NULL, TELNET_VARTYPE_UINT, 0},\
|
||||
{"timer_reorder_tout", NULL, TELNET_VARTYPE_UINT, 0},\
|
||||
{"timer_poll_retrans_tout", NULL, TELNET_VARTYPE_UINT, 0},\
|
||||
{"timer_status_prohibit_tout", NULL, TELNET_VARTYPE_UINT, 0},\
|
||||
}
|
||||
@@ -0,0 +1,316 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/*! \file common/utils/telnetsrv/telnetsrv_measurements.c
|
||||
* \brief: implementation of telnet commands related to measurments
|
||||
* \author Francois TABURET
|
||||
* \date 2019
|
||||
* \version 0.1
|
||||
* \company NOKIA BellLabs France
|
||||
* \email: francois.taburet@nokia-bell-labs.com
|
||||
* \note
|
||||
* \warning
|
||||
*/
|
||||
#define _GNU_SOURCE
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
|
||||
|
||||
|
||||
#define TELNETSERVERCODE
|
||||
#include "telnetsrv.h"
|
||||
#define TELNETSRV_MEASURMENTS_MAIN
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "common/config/config_userapi.h"
|
||||
#include "telnetsrv_measurements.h"
|
||||
#include "telnetsrv_ltemeasur_def.h"
|
||||
#include "telnetsrv_cpumeasur_def.h"
|
||||
#include "openair2/LAYER2/MAC/mac.h"
|
||||
#include "openair1/PHY/phy_extern.h"
|
||||
|
||||
void measurcmd_display_macstats(telnet_printfunc_t prnt);
|
||||
void measurcmd_display_macstats_ue(telnet_printfunc_t prnt);
|
||||
void measurcmd_display_rlcstats(telnet_printfunc_t prnt);
|
||||
void measurcmd_display_phycpu(telnet_printfunc_t prnt);
|
||||
void measurcmd_display_maccpu(telnet_printfunc_t prnt);
|
||||
void measurcmd_display_pdcpcpu(telnet_printfunc_t prnt);
|
||||
|
||||
|
||||
static telnet_measurgroupdef_t measurgroups[] = {
|
||||
{"enb", GROUP_LTESTATS,0, measurcmd_display_macstats, {NULL}},
|
||||
{"enbues",GROUP_LTESTATS,0, measurcmd_display_macstats_ue,{NULL}},
|
||||
{"rlc", GROUP_LTESTATS,0, measurcmd_display_rlcstats, {NULL}},
|
||||
{"phycpu",GROUP_CPUSTATS,0, measurcmd_display_phycpu, {NULL}},
|
||||
{"maccpu",GROUP_CPUSTATS,0, measurcmd_display_maccpu, {NULL}},
|
||||
{"pdcpcpu",GROUP_CPUSTATS,0, measurcmd_display_pdcpcpu, {NULL}},
|
||||
};
|
||||
#define TELNET_NUM_MEASURGROUPS (sizeof(measurgroups)/sizeof(telnet_measurgroupdef_t))
|
||||
|
||||
static int eNB_id =0;
|
||||
static char *grouptypes[] = {"ltestats","cpustats"};
|
||||
static double cpufreq;
|
||||
#define TELNET_NUM_MEASURTYPES (sizeof(grouptypes)/sizeof(char *))
|
||||
|
||||
#define HDR "---------------------------------"
|
||||
|
||||
void measurcmd_display_groups(telnet_printfunc_t prnt) {
|
||||
prnt(" %*s %10s %s\n",TELNET_MAXMEASURNAME_LEN-1,"name","type","nombre de mesures");
|
||||
|
||||
for(int i=0; i<TELNET_NUM_MEASURGROUPS; i++)
|
||||
prnt("%02d %*s %10s %i\n",i,TELNET_MAXMEASURNAME_LEN-1,measurgroups[i].groupname,
|
||||
grouptypes[measurgroups[i].type], measurgroups[i].size);
|
||||
} /* measurcmd_display_groups */
|
||||
/*----------------------------------------------------------------------------------------------------*/
|
||||
/* cpu measurements functions */
|
||||
void measurcmd_display_cpumeasures(telnet_printfunc_t prnt, telnet_cpumeasurdef_t *cpumeasure, int cpumeasure_size) {
|
||||
for (int i=0; i<cpumeasure_size; i++) {
|
||||
prnt("%02d %*s: %15.3f us; %15d %s",i,TELNET_MAXMEASURNAME_LEN-1,(cpumeasure+i)->statname,
|
||||
((cpumeasure+i)->astatptr->trials!=0)?(((cpumeasure+i)->astatptr->diff)/((cpumeasure+i)->astatptr->trials))/cpufreq/1000:0,
|
||||
(cpumeasure+i)->astatptr->trials, ((i%2)==1)?"|\n":" | " );
|
||||
}
|
||||
|
||||
prnt("\n\n");
|
||||
} /* measurcmd_display_measures */
|
||||
|
||||
#define PRINT_CPUMEAS_STATE ((cpumeas(CPUMEAS_GETSTATE))?"enabled":"disabled")
|
||||
void measurcmd_display_phycpu(telnet_printfunc_t prnt) {
|
||||
PHY_VARS_eNB *phyvars = RC.eNB[eNB_id][0];
|
||||
telnet_cpumeasurdef_t cpumeasur[]=CPU_PHYENB_MEASURE;
|
||||
prnt("%s cpu (%1.1g GHz) measurements: PHY (cpustats %s) %s\n",HDR,cpufreq,
|
||||
PRINT_CPUMEAS_STATE,HDR);
|
||||
measurcmd_display_cpumeasures(prnt, cpumeasur, sizeof(cpumeasur)/sizeof(telnet_cpumeasurdef_t));
|
||||
}
|
||||
|
||||
void measurcmd_display_maccpu(telnet_printfunc_t prnt) {
|
||||
eNB_MAC_INST *macvars = RC.mac[eNB_id];
|
||||
telnet_cpumeasurdef_t cpumeasur[]=CPU_MACENB_MEASURE;
|
||||
prnt("%s cpu (%1.1g GHz) measurements: MAC (cpustats %s) %s\n",HDR,cpufreq,
|
||||
PRINT_CPUMEAS_STATE,HDR);
|
||||
measurcmd_display_cpumeasures(prnt, cpumeasur, sizeof(cpumeasur)/sizeof(telnet_cpumeasurdef_t));
|
||||
}
|
||||
|
||||
void measurcmd_display_pdcpcpu(telnet_printfunc_t prnt) {
|
||||
pdcp_stats_t *pdcpvars = &(eNB_pdcp_stats[eNB_id]);
|
||||
telnet_cpumeasurdef_t cpumeasur[]=CPU_PDCPENB_MEASURE;
|
||||
prnt("%s cpu (%1.1g GHz) measurements: PDCP (cpustats %s) %s \n",HDR,cpufreq,
|
||||
PRINT_CPUMEAS_STATE,HDR);
|
||||
measurcmd_display_cpumeasures(prnt, cpumeasur, sizeof(cpumeasur)/sizeof(telnet_cpumeasurdef_t));
|
||||
}
|
||||
/*----------------------------------------------------------------------------------------------------*/
|
||||
/* lte measurements functions */
|
||||
uint64_t measurcmd_getstatvalue(telnet_ltemeasurdef_t *measur,telnet_printfunc_t prnt) {
|
||||
uint64_t val;
|
||||
|
||||
switch(measur->vtyp) {
|
||||
case TELNET_VARTYPE_INT64:
|
||||
val = (uint64_t)(*((uint64_t *)(measur->vptr)));
|
||||
break;
|
||||
|
||||
case TELNET_VARTYPE_INT32:
|
||||
val = (uint64_t)(*((uint32_t *)(measur->vptr)));
|
||||
break;
|
||||
|
||||
case TELNET_VARTYPE_INT16:
|
||||
val = (uint64_t)(*((uint16_t *)(measur->vptr)));
|
||||
break;
|
||||
|
||||
case TELNET_VARTYPE_INT8:
|
||||
val = (uint64_t)(*((uint8_t *)(measur->vptr)));
|
||||
break;
|
||||
|
||||
case TELNET_VARTYPE_UINT:
|
||||
val = (uint64_t)(*((unsigned int *)(measur->vptr)));
|
||||
break;
|
||||
|
||||
default:
|
||||
prnt("%s %i: unknown type \n",measur->statname,measur->vtyp);
|
||||
val = (uint64_t)(*((uint64_t *)(measur->vptr)));
|
||||
break;
|
||||
}
|
||||
|
||||
return val;
|
||||
} /* measurcmd_getstatvalue */
|
||||
|
||||
void measurcmd_display_measures(telnet_printfunc_t prnt, telnet_ltemeasurdef_t *statsptr, int stats_size) {
|
||||
for (int i=0; i<stats_size; i++) {
|
||||
prnt("%*s = %15llu%s",TELNET_MAXMEASURNAME_LEN-1,statsptr[i].statname,
|
||||
measurcmd_getstatvalue(&(statsptr[i]),prnt), ((i%3)==2)?"\n":" ");
|
||||
}
|
||||
|
||||
prnt("\n\n");
|
||||
} /* measurcmd_display_measures */
|
||||
|
||||
void measurcmd_display_macstats_ue(telnet_printfunc_t prnt) {
|
||||
UE_list_t *UE_list = &(RC.mac[eNB_id]->UE_list);
|
||||
|
||||
for (int UE_id=UE_list->head; UE_id>=0; UE_id=UE_list->next[UE_id]) {
|
||||
for (int i=0; i<UE_list->numactiveCCs[UE_id]; i++) {
|
||||
int CC_id = UE_list->ordered_CCids[i][UE_id];
|
||||
prnt("%s UE %i Id %i CCid %i %s\n",HDR,i,UE_id,CC_id,HDR);
|
||||
eNB_UE_STATS *macuestatptr = &(UE_list->eNB_UE_stats[CC_id][UE_id]);
|
||||
telnet_ltemeasurdef_t statsptr[]=LTEMAC_UEMEASURE;
|
||||
measurcmd_display_measures(prnt, statsptr, sizeof(statsptr)/sizeof(telnet_ltemeasurdef_t));
|
||||
}
|
||||
}
|
||||
} /* measurcmd_display_macstats_ue */
|
||||
|
||||
void measurcmd_display_macstats(telnet_printfunc_t prnt) {
|
||||
for (int CC_id=0 ; CC_id < MAX_NUM_CCs; CC_id++) {
|
||||
eNB_STATS *macstatptr=&(RC.mac[eNB_id]->eNB_stats[CC_id]);
|
||||
telnet_ltemeasurdef_t statsptr[]=LTEMAC_MEASURE;
|
||||
prnt("%s eNB %i mac stats CC %i frame %u %s\n",
|
||||
HDR, eNB_id, CC_id, RC.mac[eNB_id]->frame,HDR);
|
||||
measurcmd_display_measures(prnt,statsptr,sizeof(statsptr)/sizeof(telnet_ltemeasurdef_t));
|
||||
}
|
||||
} /* measurcmd_display_macstats */
|
||||
|
||||
|
||||
void measurcmd_display_one_rlcstat(telnet_printfunc_t prnt, int UE_id, telnet_ltemeasurdef_t *statsptr, int num_rlcmeasure, unsigned int *rlcstats,
|
||||
char *rbid_str, protocol_ctxt_t *ctxt, const srb_flag_t srb_flagP, const rb_id_t rb_idP)
|
||||
|
||||
{
|
||||
int rlc_status = rlc_stat_req(ctxt,srb_flagP,rb_idP,
|
||||
rlcstats, rlcstats+1, rlcstats+2, rlcstats+3, rlcstats+4, rlcstats+5,
|
||||
rlcstats+6, rlcstats+7, rlcstats+8, rlcstats+9, rlcstats+10, rlcstats+11,
|
||||
rlcstats+12, rlcstats+13, rlcstats+14, rlcstats+15, rlcstats+16, rlcstats+17,
|
||||
rlcstats+18, rlcstats+19, rlcstats+20, rlcstats+21, rlcstats+22, rlcstats+23,
|
||||
rlcstats+24, rlcstats+25, rlcstats+26, rlcstats+27);
|
||||
|
||||
if (rlc_status == RLC_OP_STATUS_OK) {
|
||||
prnt("%s UE %i RLC %s mode %s %s\n",HDR,UE_id, rbid_str,
|
||||
(rlcstats[0]==RLC_MODE_AM)? "AM": (rlcstats[0]==RLC_MODE_UM)?"UM":"NONE",HDR);
|
||||
measurcmd_display_measures(prnt, statsptr, num_rlcmeasure);
|
||||
}
|
||||
} /* status measurcmd_rlc_stat_req */
|
||||
|
||||
|
||||
void measurcmd_display_rlcstats(telnet_printfunc_t prnt) {
|
||||
protocol_ctxt_t ctxt;
|
||||
UE_list_t *UE_list = &(RC.mac[eNB_id]->UE_list);
|
||||
telnet_ltemeasurdef_t statsptr[]=LTE_RLCMEASURE;
|
||||
int num_rlcmeasure = sizeof(statsptr)/sizeof(telnet_ltemeasurdef_t );
|
||||
unsigned int *rlcstats = malloc(num_rlcmeasure*sizeof(unsigned int));
|
||||
eNB_MAC_INST *eNB = RC.mac[eNB_id];
|
||||
|
||||
for(int i=0; i <num_rlcmeasure ; i++) {
|
||||
statsptr[i].vptr = rlcstats + i;
|
||||
}
|
||||
|
||||
for (int UE_id=UE_list->head; UE_id>=0; UE_id=UE_list->next[UE_id]) {
|
||||
#define NB_eNB_INST 1
|
||||
PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt,eNB_id, ENB_FLAG_YES,UE_list->eNB_UE_stats[0][UE_id].crnti,
|
||||
eNB->frame,eNB->subframe,eNB_id);
|
||||
measurcmd_display_one_rlcstat(prnt, UE_id, statsptr, num_rlcmeasure, rlcstats, "DCCH", &ctxt, SRB_FLAG_YES, DCCH);
|
||||
measurcmd_display_one_rlcstat(prnt, UE_id, statsptr, num_rlcmeasure, rlcstats, "DTCH", &ctxt, SRB_FLAG_NO, DTCH-2);
|
||||
}
|
||||
} /* measurcmd_display_macstats_ue */
|
||||
|
||||
/*------------------------------------------------------------------------------------------------------------------------*/
|
||||
/* function called by the telnet server when measur command is entered */
|
||||
int measurcmd_show(char *buf, int debug, telnet_printfunc_t prnt) {
|
||||
char *subcmd=NULL;
|
||||
int idx1, idx2;
|
||||
int badcmd=1;
|
||||
|
||||
if (debug > 0)
|
||||
prnt(" measurcmd_show received %s\n",buf);
|
||||
|
||||
// char tmp[20480];
|
||||
// dump_eNB_l2_stats(tmp, 0);
|
||||
// prnt("%s\n",tmp);
|
||||
int s = sscanf(buf,"%ms %i-%i\n",&subcmd, &idx1,&idx2);
|
||||
|
||||
if (s>0) {
|
||||
if ( strcmp(subcmd,"groups") == 0) {
|
||||
measurcmd_display_groups(prnt);
|
||||
badcmd=0;
|
||||
} else {
|
||||
for (int i=0; i<TELNET_NUM_MEASURTYPES; i++) {
|
||||
if(strcmp(subcmd,grouptypes[i]) == 0) {
|
||||
for(int j=0; j<TELNET_NUM_MEASURGROUPS; j++) {
|
||||
if(i == measurgroups[j].type) {
|
||||
badcmd=0;
|
||||
measurgroups[j].displayfunc(prnt);
|
||||
}
|
||||
} /* for j...*/
|
||||
}
|
||||
}/* for i...*/
|
||||
|
||||
for (int i=0; i<TELNET_NUM_MEASURGROUPS; i++) {
|
||||
if(strcmp(subcmd,measurgroups[i].groupname) == 0) {
|
||||
measurgroups[i].displayfunc(prnt);
|
||||
badcmd=0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(subcmd);
|
||||
} /* s>0 */
|
||||
|
||||
if (badcmd) {
|
||||
prnt("%s: unknown measur command\n",buf);
|
||||
}
|
||||
|
||||
return CMDSTATUS_FOUND;
|
||||
}
|
||||
|
||||
|
||||
int measurcmd_cpustats(char *buf, int debug, telnet_printfunc_t prnt) {
|
||||
char *subcmd=NULL;
|
||||
int idx1, idx2;
|
||||
int badcmd=1;
|
||||
|
||||
if (debug > 0)
|
||||
prnt(" measurcmd_show received %s\n",buf);
|
||||
|
||||
int s = sscanf(buf,"%ms %i-%i\n",&subcmd, &idx1,&idx2);
|
||||
|
||||
if (s>0) {
|
||||
if ( strcmp(subcmd,"enable") == 0) {
|
||||
cpumeas(CPUMEAS_ENABLE);
|
||||
badcmd=0;
|
||||
} else if ( strcmp(subcmd,"disable") == 0) {
|
||||
cpumeas(CPUMEAS_DISABLE);
|
||||
badcmd=0;
|
||||
}
|
||||
}
|
||||
|
||||
if (badcmd) {
|
||||
prnt("Cpu measurments state: %s\n",PRINT_CPUMEAS_STATE);
|
||||
}
|
||||
|
||||
free(subcmd);
|
||||
return CMDSTATUS_FOUND;
|
||||
}
|
||||
/*-------------------------------------------------------------------------------------*/
|
||||
|
||||
/* function called at telnet server init to add the measur command */
|
||||
void add_measur_cmds(void) {
|
||||
add_telnetcmd("measur",measur_vardef,measur_cmdarray);
|
||||
cpufreq = get_cpu_freq_GHz();
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
|
||||
/*! \file common/utils/telnetsrv/telnetsrv_measurements.h
|
||||
* \brief: Include file defining constants, structures and function prototypes
|
||||
* \ used to implement the measurements functionality of the telnet server
|
||||
* \author Francois TABURET
|
||||
* \date 2019
|
||||
* \version 0.1
|
||||
* \company NOKIA BellLabs France
|
||||
* \email: francois.taburet@nokia-bell-labs.com
|
||||
* \note
|
||||
* \warning
|
||||
*/
|
||||
#include <dlfcn.h>
|
||||
#include "telnetsrv.h"
|
||||
#include "openair1/PHY/defs_eNB.h"
|
||||
#ifdef TELNETSRV_MEASURMENTS_MAIN
|
||||
|
||||
|
||||
#define TELNET_MAXMEASURNAME_LEN 30
|
||||
#define TELNET_MAXMEASURGROUPS 10
|
||||
|
||||
telnetshell_vardef_t measur_vardef[] = {
|
||||
{"",0,NULL}
|
||||
};
|
||||
|
||||
typedef struct cpumeasurdef {
|
||||
char statname[TELNET_MAXMEASURNAME_LEN];
|
||||
time_stats_t *astatptr;
|
||||
unsigned int statemask;
|
||||
} telnet_cpumeasurdef_t;
|
||||
|
||||
typedef struct ltemeasurdef {
|
||||
char statname[TELNET_MAXMEASURNAME_LEN];
|
||||
void *vptr;
|
||||
char vtyp;
|
||||
unsigned int statemask;
|
||||
} telnet_ltemeasurdef_t;
|
||||
|
||||
#define GROUP_LTESTATS 0
|
||||
#define GROUP_CPUSTATS 1
|
||||
typedef void(*measur_dislayfunc_t)(telnet_printfunc_t prnt);
|
||||
typedef struct mesurgroupdef {
|
||||
char groupname[TELNET_MAXMEASURNAME_LEN];
|
||||
unsigned char type;
|
||||
unsigned char size;
|
||||
measur_dislayfunc_t displayfunc;
|
||||
union {
|
||||
telnet_cpumeasurdef_t *cpustats;
|
||||
telnet_ltemeasurdef_t *ltestats;
|
||||
};
|
||||
} telnet_measurgroupdef_t;
|
||||
|
||||
#define MACSTATS_NAME(valptr) #valptr
|
||||
#define LTEMAC_MEASURGROUP_NAME "ltemac"
|
||||
#define PHYCPU_MEASURGROUP_NAME "phycpu"
|
||||
|
||||
int measurcmd_show(char *buf, int debug, telnet_printfunc_t prnt);
|
||||
int measurcmd_cpustats(char *buf, int debug, telnet_printfunc_t prnt);
|
||||
telnetshell_cmddef_t measur_cmdarray[] = {
|
||||
{"show", "groups | <group name>" , measurcmd_show},
|
||||
{"cpustats","[enable | disable]",measurcmd_cpustats},
|
||||
{"","",NULL}
|
||||
};
|
||||
|
||||
#else
|
||||
extern void add_measur_cmds(void);
|
||||
#endif /* TELNETSRV_MEASURCMD_MAIN */
|
||||
@@ -183,7 +183,7 @@ struct dirent *entry;
|
||||
{
|
||||
if(entry->d_name[0] == '.')
|
||||
continue;
|
||||
snprintf(aname, sizeof(aname), "/proc/%d/task/%s/stat", getpid(),entry->d_name);
|
||||
snprintf(aname, sizeof(aname), "/proc/%d/task/%.*s/stat", getpid(),(int)(sizeof(aname)-24),entry->d_name);
|
||||
read_statfile(aname,debug,prnt);
|
||||
} /* while entry != NULL */
|
||||
closedir(proc_dir);
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
#ifndef _TIME_UTILS_H_
|
||||
#define _TIME_UTILS_H_
|
||||
|
||||
#include <time.h>
|
||||
#include <stdint.h>
|
||||
|
||||
static inline int64_t clock_difftime_ns(struct timespec start, struct timespec end)
|
||||
{
|
||||
struct timespec temp;
|
||||
int64_t temp_ns;
|
||||
|
||||
if ((end.tv_nsec-start.tv_nsec)<0) {
|
||||
temp.tv_sec = end.tv_sec-start.tv_sec-1;
|
||||
temp.tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec;
|
||||
} else {
|
||||
temp.tv_sec = end.tv_sec-start.tv_sec;
|
||||
temp.tv_nsec = end.tv_nsec-start.tv_nsec;
|
||||
}
|
||||
temp_ns = (int64_t)(temp.tv_sec) * (int64_t)1000000000 + (temp.tv_nsec);
|
||||
return temp_ns;
|
||||
}
|
||||
|
||||
#endif /* _TIME_UTILS_H_ */
|
||||
Reference in New Issue
Block a user