Commit 108d9a96 authored by El Mghazli Yacine's avatar El Mghazli Yacine

Merge branch 'websrv' of gitlab.eurecom.fr:oai/openairinterface5g into websrv

parents 6686076f afdbca2a
......@@ -94,14 +94,14 @@ int setparam(char *buff, int debug, telnet_printfunc_t prnt);
int history_cmd(char *buff, int debug, telnet_printfunc_t prnt);
telnetshell_vardef_t telnet_vardef[] = {
{"debug",TELNET_VARTYPE_INT32,&telnetparams.telnetdbg},
{"prio",TELNET_VARTYPE_INT32,&telnetparams.priority},
{"loopc",TELNET_VARTYPE_INT32,&telnetparams.loopcount},
{"loopd",TELNET_VARTYPE_INT32,&telnetparams.loopdelay},
{"phypb",TELNET_VARTYPE_INT32,&telnetparams.phyprntbuff_size},
{"hsize",TELNET_VARTYPE_INT32,&telnetparams.histsize},
{"hfile",TELNET_VARTYPE_STRING,&telnetparams.histfile},
{"",0,NULL}
{"debug",TELNET_VARTYPE_INT32,0,&telnetparams.telnetdbg},
{"prio",TELNET_VARTYPE_INT32,0,&telnetparams.priority},
{"loopc",TELNET_VARTYPE_INT32,0,&telnetparams.loopcount},
{"loopd",TELNET_VARTYPE_INT32,0,&telnetparams.loopdelay},
{"phypb",TELNET_VARTYPE_INT32,0,&telnetparams.phyprntbuff_size},
{"hsize",TELNET_VARTYPE_INT32,0,&telnetparams.histsize},
{"hfile",TELNET_VARTYPE_STRING,TELNET_CHECKVAL_RDONLY,&telnetparams.histfile},
{"",0,0,NULL}
};
telnetshell_cmddef_t telnet_cmdarray[] = {
......@@ -344,46 +344,46 @@ int history_cmd(char *buff, int debug, telnet_printfunc_t prnt) {
/*
generic commands available for all modules loaded by the server
*/
char *telnet_getvarvalue(int moduleindex, int varindex) {
char *telnet_getvarvalue(telnetshell_vardef_t *var, int varindex) {
char *val;
switch(telnetparams.CmdParsers[moduleindex].var[varindex].vartype) {
switch(var[varindex].vartype) {
case TELNET_VARTYPE_INT32:
val=malloc(64);
snprintf(val,64,"%i",*(int32_t *)(telnetparams.CmdParsers[moduleindex].var[varindex].varvalptr));
snprintf(val,64,"%i",*(int32_t *)(var[varindex].varvalptr));
break;
case TELNET_VARTYPE_INT64:
val=malloc(128);
snprintf(val,128,"%lli",(long long)*(int64_t *)(telnetparams.CmdParsers[moduleindex].var[varindex].varvalptr));
snprintf(val,128,"%lli",(long long)*(int64_t *)(var[varindex].varvalptr));
break;
case TELNET_VARTYPE_INT16:
val=malloc(16);
snprintf(val,16,"%hi",*(short *)(telnetparams.CmdParsers[moduleindex].var[varindex].varvalptr));
snprintf(val,16,"%hi",*(short *)(var[varindex].varvalptr));
break;
case TELNET_VARTYPE_INT8:
val=malloc(16);
snprintf(val,16,"%i",(int)(*(int8_t *)(telnetparams.CmdParsers[moduleindex].var[varindex].varvalptr)));
snprintf(val,16,"%i",(int)(*(int8_t *)(var[varindex].varvalptr)));
break;
case TELNET_VARTYPE_UINT:
val=malloc(64);
snprintf(val,64,"%u",*(unsigned int *)(telnetparams.CmdParsers[moduleindex].var[varindex].varvalptr));
snprintf(val,64,"%u",*(unsigned int *)(var[varindex].varvalptr));
break;
case TELNET_VARTYPE_DOUBLE:
val=malloc(32);
snprintf(val,32,"%g\n",*(double *)(telnetparams.CmdParsers[moduleindex].var[varindex].varvalptr));
snprintf(val,32,"%g\n",*(double *)(var[varindex].varvalptr));
break;
case TELNET_VARTYPE_STRING:
val = strdup(*(char **)(telnetparams.CmdParsers[moduleindex].var[varindex].varvalptr));
val = strdup(*(char **)(var[varindex].varvalptr));
break;
default:
val=malloc(64);
snprintf(val,64,"ERR:%s var %i unknown type",telnetparams.CmdParsers[moduleindex].module,varindex);
snprintf(val,64,"ERR:var %i unknown type",varindex);
break;
}
return val;
......@@ -401,7 +401,7 @@ int setgetvar(int moduleindex,char getorset,char *params) {
if (n > 0 && (getorset == 'g' || getorset == 'G')) {
client_printf("%s, %s = ", telnetparams.CmdParsers[moduleindex].module,
telnetparams.CmdParsers[moduleindex].var[i].varname );
char *strval=telnet_getvarvalue(moduleindex, i);
char *strval=telnet_getvarvalue(telnetparams.CmdParsers[moduleindex].var, i);
client_printf("%s\n",strval);
free(strval);
}
......
......@@ -85,10 +85,15 @@ typedef struct telnetsrv_qmsg {
#define TELNET_VARTYPE_DOUBLE 5
#define TELNET_VARTYPE_INT8 6
#define TELNET_VARTYPE_UINT 7
#define TELNET_CHECKVAL_RDONLY 1
#define TELNET_CHECKVAL_BOOL 2
typedef struct variabledef {
char varname[TELNET_CMD_MAXSIZE];
char vartype;
char checkval;
void *varvalptr;
} telnetshell_vardef_t;
......@@ -157,6 +162,6 @@ extern int get_phybsize(void);
#endif
#ifdef WEBSERVERCODE
extern telnetsrv_params_t *get_telnetsrv_params(void);
extern char *telnet_getvarvalue(int moduleindex, int varindex);
extern char *telnet_getvarvalue(telnetshell_vardef_t *var, int varindex);
#endif
#endif
......@@ -39,11 +39,11 @@
telnetshell_vardef_t loader_globalvardef[] = {
{"mainversion",TELNET_VARTYPE_STRING,&(loader_data.mainexec_buildversion)},
{"defpath",TELNET_VARTYPE_STRING,&(loader_data.shlibpath)},
{"maxshlibs",TELNET_VARTYPE_INT32,&(loader_data.maxshlibs)},
{"numshlibs",TELNET_VARTYPE_INT32,&(loader_data.numshlibs)},
{"",0,NULL}
{"mainversion",TELNET_VARTYPE_STRING,TELNET_CHECKVAL_RDONLY, &(loader_data.mainexec_buildversion)},
{"defpath",TELNET_VARTYPE_STRING,TELNET_CHECKVAL_RDONLY,&(loader_data.shlibpath)},
{"maxshlibs",TELNET_VARTYPE_INT32,TELNET_CHECKVAL_RDONLY,&(loader_data.maxshlibs)},
{"numshlibs",TELNET_VARTYPE_INT32,TELNET_CHECKVAL_RDONLY,&(loader_data.numshlibs)},
{"",0,0,NULL}
};
telnetshell_vardef_t *loader_modulesvardef;
......
......@@ -92,7 +92,7 @@ telnetshell_cmddef_t measur_cmdarray[] = {
};
telnetshell_vardef_t measur_vardef[] = {
{"",0,NULL}
{"",0,0,NULL}
};
/* function to be implemented in any telnetsrv_xxx_measurements.c sources
to allow common measurment code to access measurments data */
......
......@@ -53,7 +53,7 @@ telnetshell_vardef_t phy_vardef[] = {
//{"txshift",TELNET_VARTYPE_INT32,NULL},
//{"rachemin",TELNET_VARTYPE_INT32,NULL},
//{"rachdmax",TELNET_VARTYPE_INT32,NULL},
{"",0,NULL}
{"",0,0,NULL}
};
#else
......
......@@ -46,7 +46,7 @@ extern int proccmd_thread(char *buf, int debug, telnet_printfunc_t prnt);
extern int proccmd_exit(char *buf, int debug, telnet_printfunc_t prnt);
extern int proccmd_log(char *buf, int debug, telnet_printfunc_t prnt);
telnetshell_vardef_t proc_vardef[] = {
{"",0,NULL}
{"",0,0,NULL}
};
#define PROCCMD_LOG_HELP_STRING " log sub commands: \n\
show: display current log configuration \n\
......
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)
# telnet server principles
The oai telnet server is implemented in shared libraries to be loaded by the [oai shared library loader](loader). `libtelnetsrv.so ` contains the code common to all oai softmodem executables, where `libtelnetsrv_<app>.so` contains the code specific to the executable identified by `app`.
| `<app>` | executable |
| :-----: | :---------------: |
| enb | `lte-softmodem` |
| gnb | `nr-softmodem` |
| 4Gue | `lte-uesoftmodem` |
| 5Gue | `nr-uesoftmodem` |
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). it also uses the `get_softmodem_function` call to retrieve the running executable id and possibly loads the corresponding `libtelnetsrv_<app>.so`library.
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. This implementation is compatible with all softmodem executables and is in charge of loading any additional `libtelnetsrv_<app> .so` containing code specific to the running executables.
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 and are common to all softmodem executables.
1. `telnetsrv_<XXX\>.h`: include file for the implementation of XXX CLI command. Usually included only in the corresponding `.c`file
1. `telnetsrv_<app>_<XXX>.c`: implementation of \<XXX\> CLI command specific to the executable identified by \<app\>.These sources are used to create `libtelnetsrv_<app>.so` at build time.
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)
# 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-lib telnetsrv
```
This will create the `libtelnetsrv.so` and `libtelnetsrv_<app> file in the `targets/bin` and `cmake_targets/ran_build/build` sub directories of the oai repository. <app> can be "enb", "gnb", "4GUE" or "5GUE", each library containing functions specific to a given executable.
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)
* [measur command](telnetmeasur.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)
......@@ -162,25 +162,22 @@ int websrv_callback_get_mainurl(const struct _u_request * request, struct _u_res
return U_CALLBACK_CONTINUE;
}
/* callback processing module url (<address>/oaisoftmodem/module)*/
int websrv_callback_get_softmodemcmd(const struct _u_request * request, struct _u_response * response, void * user_data) {
char *module=NULL;
telnetsrv_params_t *telnetparams= get_telnetsrv_params();
int r=sscanf(request->http_url+1,"%*[^/]/%*[^/]/%m[^/]",&module);
if (module == NULL || r!=1) {
LOG_E(UTIL,"websrv received %s request, couldn't parse module r=%i\n",request->http_url,r );
return(U_CALLBACK_ERROR);
}
LOG_I(UTIL,"websrv received %s module request\n", module);
/* callback processing module url (<address>/oaisoftmodem/module/variabes)*/
int websrv_callback_get_softmodemvar(const struct _u_request * request, struct _u_response * response, void * user_data) {
cmdparser_t * modulestruct = (cmdparser_t *)user_data;
LOG_I(UTIL,"websrv received %s variables request\n", modulestruct->module);
json_t *moduleactions = json_array();
for (int i=0; telnetparams->CmdParsers[i].var != NULL && telnetparams->CmdParsers[i].cmd != NULL; i++) {
if ( strcmp(telnetparams->CmdParsers[i].module,module)==0) {
for(int j=0; telnetparams->CmdParsers[i].var[j].varvalptr != NULL ; j++) {
char*strval=telnet_getvarvalue(i, j);
char *strbool="false";
json_t *oneaction =json_pack("{s:s,s:s,s:s,s:s}","type","variable","name",telnetparams->CmdParsers[i].var[j].varname,"value",strval,"modifiable",strbool);
for(int j=0; modulestruct->var[j].varvalptr != NULL ; j++) {
char*strval=telnet_getvarvalue(modulestruct->var[j].varvalptr, j);
char *strbool="true";
if (modulestruct->var[j].checkval & TELNET_CHECKVAL_RDONLY)
strbool="false";
json_t *oneaction =json_pack("{s:s,s:s,s:s,s:s}","type","string","name",modulestruct->var[j].varname,"value",strval,"modifiable",strbool);
if (oneaction==NULL) {
LOG_E(UTIL,"websrv cannot encode oneaction %s/%s\n",module,telnetparams->CmdParsers[i].var[j].varname);
LOG_E(UTIL,"websrv cannot encode oneaction %s/%s\n",modulestruct->module,modulestruct->var[j].varname);
} else {
websrv_printjson("oneaction",oneaction);
}
......@@ -188,37 +185,49 @@ int websrv_callback_get_softmodemcmd(const struct _u_request * request, struct _
json_array_append(moduleactions , oneaction);
}
if (moduleactions==NULL) {
LOG_E(UTIL,"websrv cannot encode moduleactions response for %s\n",module);
LOG_E(UTIL,"websrv cannot encode moduleactions response for %s\n",modulestruct->module);
} else {
websrv_printjson("moduleactions",moduleactions);
}
int us=ulfius_add_header_to_response(response,"content-type" ,"application/json");
if (us != U_OK){
ulfius_set_string_body_response(response, 501, "Internal server error (ulfius_add_header_to_response)");
LOG_E(UTIL,"websrv cannot set response header type ulfius error %d \n",us);
}
us=ulfius_set_json_body_response(response, 200, moduleactions);
if (us != U_OK){
ulfius_set_string_body_response(response, 501, "Internal server error (ulfius_set_json_body_response)");
LOG_E(UTIL,"websrv cannot set body response ulfius error %d \n",us);
}
return U_CALLBACK_CONTINUE;
}
/* callback processing module url (<address>/oaisoftmodem/module/commands)*/
int websrv_callback_get_softmodemcmd(const struct _u_request * request, struct _u_response * response, void * user_data) {
cmdparser_t *modulestruct = (cmdparser_t *)user_data;
LOG_I(UTIL,"websrv received %s commands request\n", modulestruct->module);
json_t *modulesubcom = json_array();
for(int j=0; telnetparams->CmdParsers[i].cmd[j].cmdfunc != NULL ; j++) {
json_t *jsstr=json_string(telnetparams->CmdParsers[i].cmd[j].cmdname);
for(int j=0; modulestruct->cmd[j].cmdfunc != NULL ; j++) {
json_t *jsstr=json_string(modulestruct->cmd[j].cmdname);
json_array_append(modulesubcom , jsstr);
}
if (modulesubcom==NULL) {
LOG_E(UTIL,"websrv cannot encode modulesubcom response for %s\n",module);
LOG_E(UTIL,"websrv cannot encode modulesubcom response for %s\n",modulestruct->module);
} else {
websrv_printjson("modulesubcom",modulesubcom);
}
json_t *subc=json_pack("{s:s,s:o}","type","subcommand","name",modulesubcom);
json_array_append(moduleactions , subc);
if (moduleactions!=NULL) {
websrv_printjson("moduleactions",moduleactions);
}
free(module);
int us=ulfius_add_header_to_response(response,"content-type" ,"application/json");
if (us != U_OK){
ulfius_set_string_body_response(response, 501, "Internal server error (ulfius_add_header_to_response)");
LOG_E(UTIL,"websrv cannot set response header type ulfius error %d \n",us);
}
us=ulfius_set_json_body_response(response, 200, moduleactions);
us=ulfius_set_json_body_response(response, 200, modulesubcom);
if (us != U_OK){
ulfius_set_string_body_response(response, 501, "Internal server error (ulfius_set_json_body_response)");
LOG_E(UTIL,"websrv cannot set body response ulfius error %d \n",us);
}
}
}
return U_CALLBACK_CONTINUE;
}
......@@ -226,32 +235,30 @@ int websrv_callback_get_softmodemcmd(const struct _u_request * request, struct _
int websrv_callback_get_softmodemmodules(const struct _u_request * request, struct _u_response * response, void * user_data) {
telnetsrv_params_t *telnetparams= get_telnetsrv_params();
json_t *cmdnames = json_array();
for (int i=0; telnetparams->CmdParsers[i].var != NULL && telnetparams->CmdParsers[i].cmd != NULL; i++) {
json_t *acmd =json_string( telnetparams->CmdParsers[i].module);
json_t *acmd =json_pack( "{s:s}", "name",telnetparams->CmdParsers[i].module);
json_array_append(cmdnames, acmd);
ulfius_add_endpoint_by_val(websrvparams.instance, "GET", "oaisoftmodem/module",telnetparams->CmdParsers[i].module , 0, &websrv_callback_get_softmodemcmd, telnetparams->CmdParsers[i].module );
}
json_t *body=json_pack("{s:o}",
"menu_cmds", cmdnames);
if (body==NULL) {
LOG_E(UTIL,"websrv cannot encode modules body response\n");
} else {
websrv_printjson("modules body",body);
char prefixurl[TELNET_CMD_MAXSIZE+20];
snprintf(prefixurl,TELNET_CMD_MAXSIZE+19,"oaisoftmodem/%s",telnetparams->CmdParsers[i].module);
LOG_I(UTIL,"websrv add endpoints %s/[variables or commands] \n",prefixurl);
ulfius_add_endpoint_by_val(websrvparams.instance, "GET", prefixurl,"variables" , 0, &websrv_callback_get_softmodemvar, &(telnetparams->CmdParsers[i]) );
ulfius_add_endpoint_by_val(websrvparams.instance, "GET", prefixurl,"commands" , 0, &websrv_callback_get_softmodemcmd, &(telnetparams->CmdParsers[i]) );
}
int us=ulfius_add_header_to_response(response,"content-type" ,"application/json");
if (us != U_OK){
ulfius_set_string_body_response(response, 501, "Internal server error (ulfius_add_header_to_response)");
LOG_E(UTIL,"websrv cannot set modules response header type ulfius error %d \n",us);
}
us=ulfius_set_json_body_response(response, 200, body);
us=ulfius_set_json_body_response(response, 200, cmdnames);
if (us != U_OK){
ulfius_set_string_body_response(response, 501, "Internal server error (ulfius_set_json_body_response)");
LOG_E(UTIL,"websrv cannot set modules body response ulfius error %d \n",us);
} else {
websrv_printjson("cmdnames",cmdnames);
}
// ulfius_set_string_body_response(response, 200, cfgfile);
return U_CALLBACK_CONTINUE;
......@@ -261,14 +268,15 @@ int websrv_callback_get_softmodemstatus(const struct _u_request * request, struc
char *cfgfile=CONFIG_GETCONFFILE ;
char *execfunc=get_softmodem_function(NULL);
char *strbool="false";
char *strtype="string";
json_t *moduleactions = json_array();
json_t *body1=json_pack("{s:s,s:s,s:s,s:s}","type","variable","name","config_file", "value",cfgfile, "modifiable",strbool);
json_t *body1=json_pack("{s:s,s:s,s:s,s:s}","name","config_file", "value",cfgfile, "type",strtype,"modifiable",strbool);
if (body1==NULL) {
LOG_E(UTIL,"websrv cannot encode status body1 response\n");
} else {
websrv_printjson("status body1",body1);
}
json_t *body2=json_pack("{s:s,s:s,s:s,s:s}","type","variable","name","config_file", "value",execfunc, "modifiable",strbool);
json_t *body2=json_pack("{s:s,s:s,s:s,s:s}","name","exec_function", "value",execfunc, "type", strtype, "modifiable",strbool);
if (body2==NULL) {
LOG_E(UTIL,"websrv cannot encode status body1 response\n");
} else {
......@@ -316,8 +324,8 @@ int websrv_callback_get_softmodemstatus(const struct _u_request * request, struc
//1: load the frontend code: files contained in the websrvparams.url directory
ulfius_add_endpoint_by_val(websrvparams.instance, "GET", websrvparams.url, NULL, 0, &websrv_callback_get_mainurl, NULL);
//2: build the first page, when receiving the "oaisoftmodem" url
ulfius_add_endpoint_by_val(websrvparams.instance, "GET", "oaisoftmodem", "status", 0, &websrv_callback_get_softmodemstatus, NULL);
ulfius_add_endpoint_by_val(websrvparams.instance, "GET", "oaisoftmodem", "modules", 0, &websrv_callback_get_softmodemmodules, NULL);
ulfius_add_endpoint_by_val(websrvparams.instance, "GET", "oaisoftmodem", "variables", 0, &websrv_callback_get_softmodemstatus, NULL);
ulfius_add_endpoint_by_val(websrvparams.instance, "GET", "oaisoftmodem", "commands", 0, &websrv_callback_get_softmodemmodules, NULL);
//ulfius_add_endpoint_by_val(&instance, "GET", "softmodem", "", 0, &callback_get_empty_response, NULL);
// ulfius_add_endpoint_by_val(&instance, "GET", PREFIX, "/multiple/:multiple/:multiple/:not_multiple", 0, &callback_all_test_foo, NULL);
// ulfius_add_endpoint_by_val(&instance, "POST", PREFIX, NULL, 0, &callback_post_test, NULL);
......
......@@ -45,8 +45,8 @@ static telnetshell_cmddef_t coding_cmdarray[] = {
{"","",NULL},
};
telnetshell_vardef_t coding_vardef[] = {
{"maxiter",TELNET_VARTYPE_INT32,&max_turbo_iterations},
{"",0,NULL}
{"maxiter",TELNET_VARTYPE_INT32,0,&max_turbo_iterations},
{"",0,0,NULL}
};
/* PHY/defs.h contains MODE_DECODE_XXX macros, following table must match */
static char *modedesc[] = {"none","sse","C","avx2"};
......
......@@ -55,7 +55,7 @@ static telnetshell_cmddef_t channelmod_cmdarray[] = {
};
static telnetshell_vardef_t channelmod_vardef[] = {
{"",0,NULL}
{"",0,0,NULL}
};
static double snr_dB=25;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment