Merge remote-tracking branch 'origin/telnet-ci' into integration_2022_wk11

This commit is contained in:
Robert Schmidt
2023-03-14 15:24:33 +01:00
12 changed files with 211 additions and 34 deletions
+6 -1
View File
@@ -54,8 +54,13 @@ add_library(telnetsrv_5Gue MODULE telnetsrv_5Gue_measurements.c)
add_dependencies(telnetsrv telnetsrv_5Gue)
target_link_libraries(telnetsrv_5Gue PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
message(STATUS "Add CI specific telnet functions in libtelnetsrv_ci.so")
add_library(telnetsrv_ci MODULE telnetsrv_ci.c)
target_link_libraries(telnetsrv_ci PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
add_dependencies(telnetsrv telnetsrv_ci)
# all libraries should be written to root build dir
set_target_properties(telnetsrv telnetsrv_enb telnetsrv_5Gue
set_target_properties(telnetsrv telnetsrv_enb telnetsrv_5Gue telnetsrv_ci
PROPERTIES LIBRARY_OUTPUT_DIRECTORY ../../..
)
+9 -3
View File
@@ -8,7 +8,7 @@ By default the embedded telnet server, which is implemented in a shared library,
./build_oai --build-lib telnetsrv
```
This will create the `libtelnetsrv.so` and `libtelnetsrv_<app> file in the `cmake_targets/ran_build/build` subdirectory of the oai repository. <app> can be "enb", "gnb", "4GUE" or "5GUE", each library containing functions specific to a given executable.
This will create the `libtelnetsrv.so` and `libtelnetsrv_<app>` file in the `cmake_targets/ran_build/build` subdirectory of the oai repository. `<app>` can be "enb", "gnb", "4GUE", "5GUE", or "ci", 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).
@@ -32,9 +32,15 @@ The telnet server is using the [oai configuration module](Config/Rtusage). Telne
|:---:|:---:|:---:|:----|:----:|
| `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 |
| `listenstdin` | `integer` (bool) | 0 | enable input from stdin via additional thread | N |
| `policy` | `integer` | 0 | scheduling priority for telnet (0-99) | 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 |
| `histfile` | `string` | "oaitelnet.history" | file used for command history persistency | Y |
| `histsize` | `integer` | 50 | maximum number of commands saved in the history | Y |
| `logfile` | `string` | `oaisoftmodem.log` | output file to which to redirect
| `phypbsize` | `integer` | 65000 | string buffer size to dump phy stats | Y |
| `staticmod` | `string` | (empty) | additional internally defined telnet modules (`--telnetsrv.staticmod X`, comma-separated) to load on startup. The modules should define a function `add_X_cmds()` in which the module can register telnet commands | N |
| `shrmod` | `string` | (empty) | additional shared object files `telnetsrv_X.so` (`--telnetsrv.shrmod X`, comma-separated) to load on startup. The shared object(s) should define a function `add_X_cmds()` in which the shared object can register telnet commands | N |
[oai telnet server home](telnetsrv.md)
+15 -16
View File
@@ -821,14 +821,14 @@ void poll_telnetcmdq(void *qid, void *arg) {
*
*
*/
void exec_moduleinit(char *modname) {
static bool exec_moduleinit(char *modname) {
void (*fptr)(void);
char initfunc[TELNET_CMD_MAXSIZE+10];
if (strlen(modname) > TELNET_CMD_MAXSIZE) {
fprintf(stderr,"[TELNETSRV] module %s not loaded, name exceeds the %i size limit\n",
modname, TELNET_CMD_MAXSIZE);
return;
return false;
}
sprintf(initfunc,"add_%s_cmds",modname);
@@ -836,37 +836,35 @@ void exec_moduleinit(char *modname) {
if ( fptr != NULL) {
fptr();
} else {
fprintf(stderr,"[TELNETSRV] couldn't find %s for module %s \n",initfunc,modname);
return true;
}
fprintf(stderr, "[TELNETSRV] couldn't find %s for module %s \n", initfunc, modname);
return false;
}
int add_embeddedmodules(void) {
int ret=0;
int pindex = config_paramidx_fromname(telnetoptions,sizeof(telnetoptions)/sizeof(paramdef_t), TELNETSRV_OPTNAME_STATICMOD);
for(int i=0; i<telnetoptions[pindex].numelt; i++) {
ret++;
exec_moduleinit(telnetoptions[pindex].strlistptr[i]);
bool success = exec_moduleinit(telnetoptions[pindex].strlistptr[i]);
if (success)
ret++;
}
return ret;
}
int add_sharedmodules(void) {
char initfunc[TELNET_CMD_MAXSIZE+9];
void (*fptr)(void);
int ret=0;
int pindex = config_paramidx_fromname(telnetoptions,sizeof(telnetoptions)/sizeof(paramdef_t), TELNETSRV_OPTNAME_SHRMOD);
for(int i=0; i<telnetoptions[pindex].numelt; i++) {
sprintf(initfunc,"add_%s_cmds",telnetoptions[pindex].strlistptr[i]);
fptr = dlsym(RTLD_DEFAULT,initfunc);
if ( fptr != NULL) {
fptr();
char *name = telnetoptions[pindex].strlistptr[i];
char libname[256];
snprintf(libname, sizeof(libname), "telnetsrv_%s", name);
load_module_shlib(libname, NULL, 0, NULL);
bool success = exec_moduleinit(name);
if (success)
ret++;
} else {
fprintf(stderr,"[TELNETSRV] couldn't find %s for module %s \n",initfunc,telnetoptions[pindex].strlistptr[i]);
}
}
return ret;
@@ -890,6 +888,7 @@ int telnetsrv_autoinit(void) {
add_telnetcmd("telnet", telnet_vardef, telnet_cmdarray);
add_embeddedmodules();
add_sharedmodules();
if ( telnetparams.listenstdin ) {
if(pthread_create(&telnetparams.telnetclt_pthread,NULL, (void *(*)(void *))run_telnetclt, NULL) != 0) {
fprintf(stderr,"[TELNETSRV] Error %s on pthread_create f() run_telnetclt \n",strerror(errno));
+133
View File
@@ -0,0 +1,133 @@
/*
* 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
*/
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include "openair2/RRC/NR/rrc_gNB_UE_context.h"
#include "openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h"
#include "openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h"
#define TELNETSERVERCODE
#include "telnetsrv.h"
#define ERROR_MSG_RET(mSG, aRGS...) do { prnt(mSG, ##aRGS); return 1; } while (0)
static int get_single_ue_rnti(void)
{
NR_UE_info_t *ue = NULL;
UE_iterator(RC.nrmac[0]->UE_info.list, it) {
if (it && ue)
return -1;
if (it)
ue = it;
}
if (!ue)
return -1;
// verify it exists in RRC as well
rrc_gNB_ue_context_t *rrcue = rrc_gNB_get_ue_context(RC.nrrrc[0], ue->rnti);
if (!rrcue)
return -1;
return ue->rnti;
}
int get_single_rnti(char *buf, int debug, telnet_printfunc_t prnt)
{
if (buf)
ERROR_MSG_RET("no parameter allowed\n");
int rnti = get_single_ue_rnti();
if (rnti < 1)
ERROR_MSG_RET("different number of UEs\n");
prnt("single UE RNTI %04x\n", rnti);
return 0;
}
int get_reestab_count(char *buf, int debug, telnet_printfunc_t prnt)
{
int rnti = -1;
if (!buf) {
rnti = get_single_ue_rnti();
if (rnti < 1)
ERROR_MSG_RET("no UE found\n");
} else {
rnti = strtol(buf, NULL, 16);
if (rnti < 1 || rnti >= 0xfffe)
ERROR_MSG_RET("RNTI needs to be [1,0xfffe]\n");
}
rrc_gNB_ue_context_t *ue = rrc_gNB_get_ue_context(RC.nrrrc[0], rnti);
if (!ue)
ERROR_MSG_RET("could not find UE with RNTI %04x\n", rnti);
prnt("UE RNTI %04x reestab %d reconf_after_reestab %d\n",
rnti,
ue->ue_context.ue_reestablishment_counter,
ue->ue_context.ue_reconfiguration_after_reestablishment_counter);
return 0;
}
int trigger_reestab(char *buf, int debug, telnet_printfunc_t prnt)
{
int rnti = -1;
if (!buf) {
rnti = get_single_ue_rnti();
if (rnti < 1)
ERROR_MSG_RET("no UE found\n");
} else {
rnti = strtol(buf, NULL, 16);
if (rnti < 1 || rnti >= 0xfffe)
ERROR_MSG_RET("RNTI needs to be [1,0xfffe]\n");
}
// verify it exists in RRC as well
rrc_gNB_ue_context_t *rrcue = rrc_gNB_get_ue_context(RC.nrrrc[0], rnti);
if (!rrcue)
ERROR_MSG_RET("could not find UE with RNTI %04x\n", rnti);
nr_rlc_remove_ue(rnti);
prnt("force-remove UE RNTI %04x from RLC to trigger reestablishment\n", rnti);
return 0;
}
static telnetshell_cmddef_t cicmds[] = {
{"get_single_rnti", "", get_single_rnti},
{"force_reestab", "[rnti(hex,opt)]", trigger_reestab},
{"get_reestab_count", "[rnti(hex,opt)]", get_reestab_count},
{"", "", NULL},
};
static telnetshell_vardef_t civars[] = {
{"", 0, 0, NULL}
};
void add_ci_cmds(void) {
add_telnetcmd("ci", civars, cicmds);
}