The configuration module provides an api that other oai components can use to get parameters at init time. It defines a parameter structure, used to describe parameters attributes (for example name and type). The same structure includes a pointer to the variable where the configuration module writes the parameter value, at run time, when calling config_get or config_getlist functions. For each parameter a function to check the value can be specified and pre-defined functions are provided for some common parameter validations (integer in a range or in a list, string in a list). The module also include a mechanism to check that no unknown options have been entered on the command line
1. Allow easy parameters management in oai, helping the development of a flexible, modularized and fully configurable softmodem.
1. Use a common configuration API in all oai modules
1. Allow development of alternative configuration sources without modifying the oai code. Today the only delivered configuration source is the libconfig format configuration file.
As a developer you may need to look at these sections:
*[add parameters in an existing section](config/devusage/addaparam)
*[add a parameter set, in a new section](config/devusage/addparamset)
*[configuration module API](config/devusage/api)
*[configuration module public structures](config/devusage/struct)
Whatever your need is, configuration module usage examples can be found in oai sources:
* complex example, using all the configuration module functionalities, including parameter checking:
[NB-IoT configuration code](https://gitlab.eurecom.fr/oai/openairinterface5g/blob/develop/openair2/ENB_APP/NB_IoT_config.c) and [NB-IoT configuration include file](https://gitlab.eurecom.fr/oai/openairinterface5g/blob/develop/openair2/ENB_APP/NB_IoT_paramdef.h)
* very simple example, just reading a parameter set corresponding to a dedicated section: the telnetsrv_autoinit function in [common/utils/telnetsrv/telnetsrv.c, around line 726](https://gitlab.eurecom.fr/oai/openairinterface5g/blob/develop/common/utils/telnetsrv/telnetsrv.c#L726)
* an example with run-time definition of parameters, in the logging sub-system: the log_getconfig function at the top of [openair2/UTIL/LOG/log.c](https://gitlab.eurecom.fr/oai/openairinterface5g/blob/develop/openair2/UTIL/LOG/log.c)
To add a new parameter in an existing section you insert an item in a `paramdef_t` array, which describes the parameters to be read in the existing `config_get` call. You also need to increment the numparams argument.
The corresponding configuration file may now include opt2 parameter in the somesection section:
```c
somesection=
{
opt1=3;
opt2="abcd";
};
```
In these examples the variables used to retrieve the parameters values are pointed by the `uptr` or `strptr` fields of the `paramdef_t` structure. After the `config_get` call `varopt1` and `varopt2` have been set to the value specified in the config file. It is also possible to specify a `NULL` value to the `< XXX >ptr` fields, which are then allocated by the config module and possibly free when calling `config_end()`, if the `PARAMFLAG_NOFREE` bit has not been set in the `paramflags` field.
The configuration module provides a mechanism to check the parameter value read from the configuration source. The following functions are implemented:
1. Check an integer parameter against a list of authorized values
1. Check an integer parameter against a list of authorized values and set the parameter to a new value
1. Check an integer parameter against a range
1. Check a C string parameter against a list of authorized values
1. Check a C string parameter against a list of authorized values and set the parameter to a new integer value
A `checkedparam_t` structure array provides the parameter verification procedures:
```c
/*
definition of the verification to be done on param opt1 and opt2.
opt1 is an integer option we must be set to 0,2,3,4 or 7 in the
config source.
if opt1 is set to 0 in the config file, it will be set to 1, etc
opt2 is C string option with the authorize values "zero","oneThird","twoThird","one"
When you need a specific verification algorithm, you can provide your own verification function and use it in place of the available ones, in the `checkedparam_t` union. If no existing structure definition match your need, you can enhance the configuration module. You then have to add a new verification function in https://gitlab.eurecom.fr/oai/openairinterface5g/blob/develop/common/config/config_userapi.c and add a new structure definition in the `checkedparam_t` type defined in https://gitlab.eurecom.fr/oai/openairinterface5g/blob/develop/common/config/config_paramdesc.h
[Configuration module developer main page](config/devusage)
The configuration module maps a configuration file section to a `paramdef_t` structure array. One `config_get` call can be used to return the values of all the parameters described in the `paramdef_t` array.
Retrieving a single occurence of a parameter set ( a group in the libconfig terminology) is just a two steps task:
1. describe the parameters in a `paramdef_t` array
In oai some parameters set may be instantiated a variable number of occurrences. In a configuration file this is mapped to lists of group of parameters, with this syntax:
```c
NB-IoT_MACRLCs=
/* start list element 1 */
(
/* start a group of parameters */
{
num_cc=2;
.....
remote_s_portd=55001;
}
),
/* start list element 2 */
(
/* start a group of parameters */
{
num_cc=1;
......
remote_s_portd=65001;
}
);
```
The configuration module provides the `config_getlist` call to support lists of group of parameters. Below is a commented code example, using the config_getlist call.
* Parses the command line options, looking for the –O argument
* Loads the `libparams_<configsource>.so` (today `libparams_libconfig.so`) shared library
* Looks for `config_<config source>_init` symbol and calls it , passing it an array of string corresponding to the « : » separated strings used in the –O option
* Looks for `config_<config source>_get`, `config_<config source>_getlist` and `config_<config source>_end` symbols which are the three functions a configuration library should implement. Get and getlist are mandatory, end is optional.
* Stores all the necessary information in a `configmodule_interface_t structure`, which is of no use for caller as long as we only use one configuration source.
```c
voidEnd_configmodule(void)
```
* Free memory which has been allocated by the configuration module since its initialization.
* Possibly calls the `config_<config source>_end` function
* Reads as many parameters as described in params, they must all be in the same configuration file section
* Calls the `config_<config source>_get` function
* Calls the `config_process_cmdline` function
*`params` points to an array of `paramdef_t` structures which describes the parameters to be read, possibly including a pointer to a checking function. The following bits can possibly be set in the `paramflags` mask before calling
-`PARAMFLAG_MANDATORY`: -1 is returned if the parameter is not explicitly defined in the config source.
-`PARAMFLAG_DISABLECMDLINE`: parameter cannot be modified via the command line
-`PARAMFLAG_DONOTREAD`: ignore the parameter, can be used at run-time, to alter a pre-defined `paramdef_t` array which is used in several `config_get` or/and `config_getlist` calls.
-`PARAMFLAG_NOFREE`: do not free the memory possibly allocated by the config module to store the value of the parameter. Default behavior is for the config module to free the memory it has allocated when the `config_end` function is called.
-`PARAMFLAG_BOOL`: Only relevant for integer types. tell the config module that when processing the command line, the corresponding option can be specified without any arggument and that in this case it must set the value to 1.
*`params` is also used as an output parameter, `< XXX >ptr >` field is used by the config module to store the value it has read. The following bits can possibly be set in the `paramflags` mask after the call:
-`PARAMFLAG_MALLOCINCONFIG`: memory has been allocated for the ` < XXX >ptr > ` field
-`PARAMFLAG_PARAMSET`: parameter has been found in the config source, it is not set to default value.
-`PARAMFLAG_PARAMSET`: parameter has been set to its default value
*`numparams` is the number of entries in the params array
*`prefix` is a character string to be appended to the parameters name, it defines the parameters position in the configuration file hierarchy (the section name in libconfig terminology).
* The returned value is the number of parameters which have been assigned a value or -1 if a severe error occured
* Reads multiple occurrences of a parameters array
* Calls the `config_<config source>_get` function for each list occurrence
*`params` points to an array of `paramdef_t` structures which describes the parameters in each occurrence of the list
*`ParamList` points to a structure, where `paramarray` field points to an array of `paramdef_t` structure, allocated by the function. It is used to return the values of the parameters.
* The returned value is the number of occurrences in the list or -1 in case of severe error
[Configuration module developer main page](config/devusage)
It is defined in include file [ common/config/config_paramdesc.h ](https://gitlab.eurecom.fr/oai/openairinterface5g/blob/develop/common/config/config_paramdesc.h#L103). This structure is used by developers to describe parameters and by the configuration module to return parameters value. A pointer to a `paramdef_t` array is passed to `config_get` and `config_getlist` calls to instruct the configuration module what parameters it should read.
| `optname` | parameter name, as used when looking for it in the config source, 63 bytes max (64 with trailing \0) | I |
| `helstr` | pointer to a C string printed when using --help on the command line | I |
| `strptr``strlistptr``u8ptr``i8ptr``u16ptr``i16ptr``uptr``iptr``u64ptr``i64ptr``dblptr``voidptr` | a pointer to a variable where the parameter value(s) will be returned. This field is an anonymous union, the supported pointer types have been built to avoid type mismatch warnings at compile time. | O |
| `defstrval``defstrlistval``defuintval``defintval``defint64val``defintarrayval``defdblval` | this field is an anonymous union, it can be used to define the default value for the parameter. It is ignored if `PARAMFLAG_MANDATORY` is set in the `paramflags` field.| I |
| `type` | Supported parameter types are defined as integer macros. Supported simple types are `TYPE_STRING`, parameter value is returned in `strptr` field, `TYPE_INT8``TYPE_UINT8``TYPE_INT16``TYPE_UINT16``TYPE_INT32``TYPE_UINT32``TYPE_INT64``TYPE_UINT64`, parameter value is returned in the corresponding uXptr or iXptr, `TYPE_MASK`, value is returned in `u32ptr`, `TYPE_DOUBLE` value is returned in `dblptr`, `TYPE_IPV4ADDR` value is returned in binary, network bytes order in `u32ptr` field. `TYPE_STRINGLIST`, `TYPE_INTARRAY` and `TYPE_UINTARRAY` are multiple values types. Multiple values are returned in respectively, `strlistptr`, `iptr` and `uptr` fields which then point to arrays. The `numelt` field gives the number of item in the array. | I |
| `numelt` | For `TYPE_STRING` where `strptr` points to a preallocated string, this field must contain the size in bytes of the available memory. For all multiple values types, this field contains the number of values in the value field.| I/O |
| `chkPptr` | possible pointer to the structure containing the info used to check parameter values | I |
| `processedvalue` | When `chkPptr` is not `ǸULL`, is used to return a value, computed from the original parameter, as read from the configuration source. | O |
# `paramlist_def_t`structure
It is defined in include file [ common/config/config_paramdesc.h ](https://gitlab.eurecom.fr/oai/openairinterface5g/blob/develop/common/config/config_paramdesc.h#L160).
It is used as an argument to `config_getlist` calls, to get values of multiple occurrences of group of parameters.
| `listname` | Name of the section containing the list, 63 bytes max (64 with trailing \0). It is used to prefix each paramater name when looking for its value. In the libconfig syntax, the parameter name full path build by the configuration module is: listname.[occurence index].optname. | I |
| `paramarray` | Pointer to an array of `ǹumelt``paramdef_t` pointers. It is allocated by the configuration module and is used to return the parameters values. All input fields of each `paramdef_t` occurence are a copy of the `paramdef_t` argument passed to the `config_getlist` call. | O |
| `numelt` | Number of items in the `paramarray` field | O |
# `checkedparam_t` union
It is defined in include file [ common/config/config_paramdesc.h ](https://gitlab.eurecom.fr/oai/openairinterface5g/blob/develop/common/config/config_paramdesc.h#L62).
This union of structures is used to provide a parameter checking mechanism. Each `paramdef_t` instance may include a pointer to a `checkedparam_t`structure which is then used by the configuration module to check the value it got from the config source.
Each structure in the union provides one parameter verification method, which returns `-1` when the verification fails. Currently the following structures are defined in the `checkedparam_t` union:
| `s1` | check an integer against a list of authorized values |
| `s1a` | check an integer against a list of authorized values and set the parameter value to another integer depending on the read value|
| `s2` | check an integer against an authorized range, defined by its min and max value|
| `s3` | check a string against a list of authorized values |
| `s3a` | check a string against a list of authorized values and set the parameter value to an integer depending on the read value|
| `s4` | generic structure, to be used to provide a specific, not defined in the configuration module, verification algorithm |
each of these structures provide the required fields to perform the specified parameter check. The first field is a pointer to a function, taking one argument, the `paramdef_t` structure describing the parameter to be checked. This function is called by the configuration module, in the `config_get` call , after the parameter value has been set, it then uses the other fields of the structure to perform the check.
The configuration module provides an implementation of the functions to be used to check parameters, qs described below.
| `f1a` | pointer to the checking function. Initialize to `config_check_modify_integer` to use the config module implementation |
| `okintval` | array of `CONFIG_MAX_NUMCHECKVAL` integers containing the authorized values |
| `setintval` | array of `CONFIG_MAX_NUMCHECKVAL` integers containing the values to be used for the parameter. The configuration module implementation set the parameter value to `setintval[i]` when the configured value is `okintval[i]` |
| `num_okintval` | number of used values in `okintval` and `setintval` |
| `f3a` | pointer to the checking function. Initialize to `config_checkstr_assign_integer` to use the config module implementation |
| `okstrval` | array of `CONFIG_MAX_NUMCHECKVAL` C string pointers containing the authorized values |
| `setintval` | array of `CONFIG_MAX_NUMCHECKVAL` integers containing the values to be used for the parameter. The configuration module implementation set the parameter value to `setintval[i]` when the configured value is `okstrval[i]` |
| `num_okstrval` | number of used values in `okintval` and `setintval` |
| `f4` or `f5` | pointer to the checking function. they are generic structures to be used when no existing structure provides the required parameter verification. `f4` takes one argument, the `paramdef_t` structure corresponding to the parameter to be checked (`int (*f4)(paramdef_t *param)`), `f5` taxes no argument (`void (*checkfunc)(void)`) |
[Configuration module developer main page](config/devusage)
-O is the only mandatory command line option to start the eNodeb softmodem (lte-softmodem executable), it is used to specify the configuration source with the associated parameters:
The configuration module can also be used without a configuration source, ie to only parse the command line. In this case the -O switch is optional. This mode is used in the ue-softmodem executable and by the phy_simulators executables (ulsim, dlsim)
Currently the available config sources are:
-**libconfig**: libconfig file. [libconfig file format](http://www.hyperrealm.com/libconfig/libconfig_manual.html#Configuration-Files) Parameter1 is the file path and parameter 2 can be used to specify the level of console messages printed by the configuration module.
-**cmdlineonly**: command line only, the default mode for lte-uesoftmodem and the phy simiulators. In this case -O may be used to specify the config module debug level.
The debug level is a mask:
* bit 1: print parameters values
* bit 2: print memory allocation/free performed by the config module
* bit 3: print command line processing messages
* bit 4: disable execution abort when parameters checking fails
As a oai user, you may have to use bit 1 (dbgl1) , to check your configuration and get the full name of a parameter you would like to modify on the command line. Other bits are for developers usage, (dbgl7 will print all debug messages).
```bash
$ ./lte-softmodem -O libconfig:<config>:dbgl1
```
```bash
$ ./lte-uesoftmodem -O cmdlineonly:dbgl1
```
For the lte-softmodem (the eNodeB) The config source parameter defaults to libconfig, preserving the initial -O option format. In this case you cannot specify the debug level.
```bash
$ ./lte-softmodem -O <config>
```
Configuration file parameters, except for the configuration file path, can be specified in a **config** section in the configuration file:
```
config:
{
debugflags = 1;
}
```
Configuration files examples can be found in the targets/PROJECTS/GENERIC-LTE-EPC/CONF sub-directory of the oai source tree. To minimize the number of configuration file to maintain, any parameter can also be specified on the command line. For example to modify the lte bandwidth to 20 MHz where the configuration file specifies 10MHz you can enter:
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.
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.
1. Allow easy parameters management in oai, helping the development of a flexible, modularized and fully configurable softmodem.
1. Use a common configuration API in all oai modules
1. Allow development of alternative configuration sources without modifying the oai code. Today the only delivered configuration source is the libconfig format configuration file.
As a developer you may need to look at these sections:
*[loading a shared library](loader/devusage/loading)
*[loader API](loader/devusage/api)
*[loader public structures](loader/devusage/struct)
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 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.
* 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
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_tmymodule_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
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.
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.
| `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 |
1. the <*modulename*> is defined at development time, it comes from the `modname` argument of the `load_module_shlib` call.
1. the <*moduleversion*> and <*path*> optional parameters, are defined at run-time, depending on the configuration.
## loader parameters
The loader is using the [configuration module](config), 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:
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
# 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
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#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. |
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).
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.
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
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#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)
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
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)
*[Adding commands to the oai telnet server](telnetaddcmd)
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)
*[using the history](telnethist)
*[using the get and set commands](telnetgetset)
*[using the loop command](telnetloop)
*[loader command](telnetloader)
*[log command](telnetlog)
# 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 |