Merge branch 'RU-RAU-split' of https://gitlab.eurecom.fr/oai/openairinterface5g into RU-RAU-split

Conflicts:
	openair1/PHY/INIT/lte_init.c
	openair1/PHY/LTE_TRANSPORT/dlsch_coding.c
	openair1/PHY/LTE_TRANSPORT/prach.c
	openair1/SCHED/phy_procedures_lte_eNb.c
	openair2/ENB_APP/enb_config.c
	openair2/LAYER2/MAC/defs.h
	openair2/LAYER2/MAC/eNB_scheduler.c
	openair2/LAYER2/MAC/eNB_scheduler_RA.c
	openair2/LAYER2/MAC/eNB_scheduler_bch.c
	openair2/LAYER2/MAC/eNB_scheduler_primitives.c
	openair2/LAYER2/MAC/eNB_scheduler_ulsch.c
	openair2/LAYER2/MAC/rar_tools.c
	openair2/RRC/LITE/MESSAGES/asn1_msg.c
	openair2/RRC/LITE/rrc_eNB.c
This commit is contained in:
Raymond Knopp
2017-10-10 22:09:13 -07:00
194 changed files with 23003 additions and 16060 deletions
+163
View File
@@ -0,0 +1,163 @@
/*
* 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.0 (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/config/cmdline/config_libconfig.c
* \brief configuration module, command line parsing implementation
* \author Francois TABURET
* \date 2017
* \version 0.1
* \company NOKIA BellLabs France
* \email: francois.taburet@nokia-bell-labs.com
* \note
* \warning
*/
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include "config_userapi.h"
int processoption(paramdef_t *cfgoptions, char *value)
{
char *tmpval = value;
int optisset=0;
char defbool[2]="1";
if ( value == NULL) {
if( (cfgoptions->paramflags &PARAMFLAG_BOOL) == 0 ) { /* not a boolean, argument required */
fprintf(stderr,"[CONFIG] command line, option %s requires an argument\n",cfgoptions->optname);
return 0;
} else { /* boolean value option without argument, set value to true*/
tmpval = defbool;
}
}
switch(cfgoptions->type)
{
case TYPE_STRING:
config_check_valptr(cfgoptions, (char **)(cfgoptions->strptr), sizeof(char *));
config_check_valptr(cfgoptions, cfgoptions->strptr, strlen(tmpval+1));
sprintf(*(cfgoptions->strptr), "%s",tmpval);
printf_cmdl("[CONFIG] %s set to %s from command line\n", cfgoptions->optname, tmpval);
optisset=1;
break;
case TYPE_STRINGLIST:
break;
case TYPE_UINT32:
case TYPE_INT32:
case TYPE_UINT16:
case TYPE_INT16:
case TYPE_UINT8:
case TYPE_INT8:
config_check_valptr(cfgoptions, (char **)&(cfgoptions->iptr),sizeof(int32_t));
config_assign_int(cfgoptions,cfgoptions->optname,(int32_t)strtol(tmpval,NULL,0));
optisset=1;
break;
case TYPE_UINT64:
case TYPE_INT64:
config_check_valptr(cfgoptions, (char **)&(cfgoptions->i64ptr),sizeof(uint64_t));
*(cfgoptions->i64ptr)=strtoll(tmpval,NULL,0);
printf_cmdl("[CONFIG] %s set to %lli from command line\n", cfgoptions->optname, (long long)*(cfgoptions->i64ptr));
optisset=1;
break;
case TYPE_UINTARRAY:
case TYPE_INTARRAY:
break;
case TYPE_DOUBLE:
config_check_valptr(cfgoptions, (char **)&(cfgoptions->dblptr),sizeof(double));
*(cfgoptions->dblptr) = strtof(tmpval,NULL);
printf_cmdl("[CONFIG] %s set to %lf from command line\n", cfgoptions->optname, *(cfgoptions->dblptr));
optisset=1;
break;
case TYPE_IPV4ADDR:
break;
default:
fprintf(stderr,"[CONFIG] command line, %s type %i not supported\n",cfgoptions->optname, cfgoptions->type);
break;
} /* switch on param type */
if (optisset == 1) {
cfgoptions->paramflags = cfgoptions->paramflags | PARAMFLAG_PARAMSET;
}
return optisset;
}
int config_process_cmdline(paramdef_t *cfgoptions,int numoptions, char *prefix)
{
char **p = config_get_if()->argv;
int c = config_get_if()->argc;
int j;
char *pp;
char *cfgpath;
j = (prefix ==NULL) ? 0 : strlen(prefix);
cfgpath = malloc( j + MAX_OPTNAME_SIZE +1);
if (cfgpath == NULL) {
fprintf(stderr,"[CONFIG] %s %i malloc error, %s\n", __FILE__, __LINE__,strerror(errno));
return -1;
}
j=0;
p++;
c--;
while (c > 0 && *p != NULL) {
if (strcmp(*p, "-h") == 0 || strcmp(*p, "--help") == 0 ) {
config_printhelp(cfgoptions,numoptions);
}
if (*p[0] == '-') {
for(int i=0;i<numoptions;i++) {
if ( ( cfgoptions[i].paramflags & PARAMFLAG_DISABLECMDLINE) != 0) {
continue;
}
if (prefix != NULL) {
sprintf(cfgpath,"%s.%s",prefix,cfgoptions[i].optname);
} else {
sprintf(cfgpath,"%s",cfgoptions[i].optname);
}
if ( ((strlen(*p) == 2) && (strcmp(*p + 1,cfgpath) == 0)) ||
((strlen(*p) > 2) && (strcmp(*p + 2,cfgpath ) == 0 )) ) {
pp = *(p+1);
if ( ( pp != NULL ) && (c>1) && (pp[0]!= '-') ) {
j += processoption(&(cfgoptions[i]), pp);
} else {
j += processoption(&(cfgoptions[i]), NULL);
}
break;
}
} /* for */
} /* if (*p[0] == '-') */
p++;
c--;
} /* fin du while */
printf_cmdl("[CONFIG] %s %i options set from command line\n",((prefix == NULL) ? "":prefix),j);
free(cfgpath);
return j;
} /* parse_cmdline*/
+226
View File
@@ -0,0 +1,226 @@
/*
* 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.0 (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/config/config_load_configmodule.c
* \brief configuration module, load the shared library implementing the configuration module
* \author Francois TABURET
* \date 2017
* \version 0.1
* \company NOKIA BellLabs France
* \email: francois.taburet@nokia-bell-labs.com
* \note
* \warning
*/
#define _GNU_SOURCE
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <dlfcn.h>
#define CONFIG_LOADCONFIG_MAIN
#include "config_load_configmodule.h"
#include "config_userapi.h"
#define CONFIG_SHAREDLIBFORMAT "libparams_%s.so"
int load_config_sharedlib(configmodule_interface_t *cfgptr)
{
void *lib_handle;
char fname[128];
char libname[FILENAME_MAX];
int st;
st=0;
sprintf(libname,CONFIG_SHAREDLIBFORMAT,cfgptr->cfgmode);
lib_handle = dlopen(libname,RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE);
if (!lib_handle) {
fprintf(stderr,"[CONFIG] %s %d Error calling dlopen(%s): %s\n",__FILE__, __LINE__, libname,dlerror());
st = -1;
} else {
sprintf (fname,"config_%s_init",cfgptr->cfgmode);
cfgptr->init = dlsym(lib_handle,fname);
if (cfgptr->init == NULL ) {
printf("[CONFIG] %s %d no function %s for config mode %s\n",
__FILE__, __LINE__,fname, cfgptr->cfgmode);
} else {
st=cfgptr->init(cfgptr->cfgP,cfgptr->num_cfgP);
printf("[CONFIG] function %s returned %i\n",
fname, st);
}
sprintf (fname,"config_%s_get",cfgptr->cfgmode);
cfgptr->get = dlsym(lib_handle,fname);
if (cfgptr->get == NULL ) {
printf("[CONFIG] %s %d no function %s for config mode %s\n",
__FILE__, __LINE__,fname, cfgptr->cfgmode);
st = -1;
}
sprintf (fname,"config_%s_getlist",cfgptr->cfgmode);
cfgptr->getlist = dlsym(lib_handle,fname);
if (cfgptr->getlist == NULL ) {
printf("[CONFIG] %s %d no function %s for config mode %s\n",
__FILE__, __LINE__,fname, cfgptr->cfgmode);
st = -1;
}
sprintf (fname,"config_%s_end",cfgptr->cfgmode);
cfgptr->end = dlsym(lib_handle,fname);
if (cfgptr->getlist == NULL ) {
printf("[CONFIG] %s %d no function %s for config mode %s\n",
__FILE__, __LINE__,fname, cfgptr->cfgmode);
}
}
return st;
}
/*-----------------------------------------------------------------------------------*/
/* from here: interface implementtion of the configuration module */
configmodule_interface_t *load_configmodule(int argc, char **argv)
{
char *cfgparam=NULL;
char *modeparams=NULL;
char *cfgmode=NULL;
char *strtokctx=NULL;
char *atoken;
uint32_t tmpflags=0;
int i;
/* first parse the command line to look for the -O option */
opterr=0;
for (i = 0;i<argc;i++) {
if (strlen(argv[i]) < 2) continue;
if ( argv[i][1] == 'O' && i < (argc -1)) {
cfgparam = argv[i+1];
}
if ( argv[i][1] == 'h' ) {
tmpflags = CONFIG_HELP;
}
}
optind=1;
/* look for the OAI_CONFIGMODULE environement variable */
if ( cfgparam == NULL ) {
cfgparam = getenv("OAI_CONFIGMODULE");
}
/* default */
if (cfgparam == NULL) {
cfgparam = "libconfig:oaisoftmodem.conf";
}
/* parse the config parameters to set the config source */
i = sscanf(cfgparam,"%m[^':']:%ms",&cfgmode,&modeparams);
if (i< 0) {
fprintf(stderr,"[CONFIG] %s, %d, sscanf error parsing config source %s: %s\n", __FILE__, __LINE__,cfgparam, strerror(errno));
cfgmode=strdup("libconfig");
modeparams = strdup("oaisoftmodem.conf");
}
else if ( i == 1 ) {
/* -O argument doesn't contain ":" separator, assume -O <conf file> option, default cfgmode to libconfig
with one parameter, the path to the configuration file */
modeparams=cfgmode;
cfgmode=strdup("libconfig");
}
cfgptr = malloc(sizeof(configmodule_interface_t));
memset(cfgptr,0,sizeof(configmodule_interface_t));
cfgptr->rtflags = cfgptr->rtflags | tmpflags;
cfgptr->argc = argc;
cfgptr->argv = argv;
cfgptr->cfgmode=strdup(cfgmode);
cfgptr->num_cfgP=0;
atoken=strtok_r(modeparams,":",&strtokctx);
while ( cfgptr->num_cfgP< CONFIG_MAX_OOPT_PARAMS && atoken != NULL) {
/* look for debug level in the config parameters, it is commom to all config mode
and will be removed frome the parameter array passed to the shared module */
char *aptr;
aptr=strcasestr(atoken,"dbgl");
if (aptr != NULL) {
cfgptr->rtflags = cfgptr->rtflags | strtol(aptr+4,NULL,0);
} else {
cfgptr->cfgP[cfgptr->num_cfgP] = strdup(atoken);
cfgptr->num_cfgP++;
}
atoken = strtok_r(NULL,":",&strtokctx);
}
printf("[CONFIG] get parameters from %s ",cfgmode);
for (i=0;i<cfgptr->num_cfgP; i++) {
printf("%s ",cfgptr->cfgP[i]);
}
printf("\n");
i=load_config_sharedlib(cfgptr);
if (i< 0) {
fprintf(stderr,"[CONFIG] %s %d config module %s couldn't be loaded\n", __FILE__, __LINE__,cfgmode);
cfgptr->rtflags = cfgptr->rtflags | CONFIG_HELP | CONFIG_ABORT;
} else {
printf("[CONFIG] config module %s loaded\n",cfgmode);
Config_Params[CONFIGPARAM_DEBUGFLAGS_IDX].uptr=&(cfgptr->rtflags);
config_get(Config_Params,CONFIG_PARAMLENGTH(Config_Params), CONFIG_SECTIONNAME );
}
if (modeparams != NULL) free(modeparams);
if (cfgmode != NULL) free(cfgmode);
if (CONFIG_ISFLAGSET(CONFIG_ABORT)) config_printhelp(Config_Params,CONFIG_PARAMLENGTH(Config_Params));
return cfgptr;
}
void end_configmodule()
{
if (cfgptr != NULL) {
if (cfgptr->end != NULL) {
printf ("[CONFIG] calling config module end function...\n");
cfgptr->end();
}
if( cfgptr->cfgmode != NULL) free(cfgptr->cfgmode);
printf ("[CONFIG] free %u config parameter pointers\n",cfgptr->num_cfgP);
for (int i=0; i<cfgptr->num_cfgP; i++) {
if ( cfgptr->cfgP[i] != NULL) free(cfgptr->cfgP[i]);
}
printf ("[CONFIG] free %u config value pointers\n",cfgptr->numptrs);
for(int i=0; i<cfgptr->numptrs ; i++) {
if (cfgptr->ptrs[i] != NULL) {
free(cfgptr->ptrs[i]);
}
cfgptr->ptrs[i]=NULL;
}
free(cfgptr);
cfgptr=NULL;
}
}
+103
View File
@@ -0,0 +1,103 @@
/*
* 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.0 (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/config/config_load_configmodule.h
* \brief: configuration module, include file to be used by the source code calling the
* configuration module initialization
* \author Francois TABURET
* \date 2017
* \version 0.1
* \company NOKIA BellLabs France
* \email: francois.taburet@nokia-bell-labs.com
* \note
* \warning
*/
#ifndef INCLUDE_CONFIG_LOADCONFIGMODULE_H
#define INCLUDE_CONFIG_LOADCONFIGMODULE_H
#include <string.h>
#include <stdlib.h>
#include "common/config/config_paramdesc.h"
#define CONFIG_MAX_OOPT_PARAMS 10 // maximum number of parameters in the -O option (-O <cfgmode>:P1:P2...
#define CONFIG_MAX_ALLOCATEDPTRS 1024 // maximum number of parameters that can be dynamicaly allocated in the config module
/* rtflags bit position definitions */
#define CONFIG_PRINTPARAMS 1 // print parameters values while processing
#define CONFIG_DEBUGPTR 2 // print memory allocation/free debug messages
#define CONFIG_DEBUGCMDLINE 4 // print command line processing messages
#define CONFIG_HELP 8 // print help message
#define CONFIG_ABORT 16 // config failed,abort execution
typedef int(*configmodule_initfunc_t)(char *cfgP[],int numP);
typedef int(*configmodule_getfunc_t)(paramdef_t *,int numparams, char *prefix);
typedef int(*configmodule_getlistfunc_t)(paramlist_def_t *, paramdef_t *,int numparams, char *prefix);
typedef void(*configmodule_endfunc_t)(void);
typedef struct configmodule_interface
{
int argc;
char **argv;
char *cfgmode;
int num_cfgP;
char *cfgP[CONFIG_MAX_OOPT_PARAMS];
configmodule_initfunc_t init;
configmodule_getfunc_t get;
configmodule_getlistfunc_t getlist;
configmodule_endfunc_t end;
uint32_t numptrs;
uint32_t rtflags;
char *ptrs[CONFIG_MAX_ALLOCATEDPTRS];
} configmodule_interface_t;
#ifdef CONFIG_LOADCONFIG_MAIN
configmodule_interface_t *cfgptr=NULL;
static char config_helpstr [] = "\n lte-softmodem -O [config mode]<:dbg[debugflags]> \n \
debugflags can also be defined in the config_libconfig section of the config file\n \
debugflags: mask, 1->print parameters, 2->print memory allocations debug messages\n \
4->print command line processing debug messages\n ";
#define CONFIG_SECTIONNAME "config"
#define CONFIGPARAM_DEBUGFLAGS_IDX 0
static paramdef_t Config_Params[] = {
/*-----------------------------------------------------------------------------------------------------------------------*/
/* config parameters for config module */
/* optname helpstr paramflags XXXptr defXXXval type numelt */
/*-----------------------------------------------------------------------------------------------------------------------*/
{"debugflags", config_helpstr, 0, uptr:NULL, defintval:0, TYPE_MASK, 0},
};
#else
extern configmodule_interface_t *cfgptr;
#endif
#define printf_params(...) if ( (cfgptr->rtflags & CONFIG_PRINTPARAMS) != 0 ) { printf ( __VA_ARGS__ ); }
#define printf_ptrs(...) if ( (cfgptr->rtflags & CONFIG_DEBUGPTR) != 0 ) { printf ( __VA_ARGS__ ); }
#define printf_cmdl(...) if ( (cfgptr->rtflags & CONFIG_DEBUGCMDLINE) != 0 ) { printf ( __VA_ARGS__ ); }
extern configmodule_interface_t *load_configmodule(int argc, char **argv);
extern void end_configmodule(void);
#endif /* INCLUDE_CONFIG_LOADCONFIGMODULE_H */
+120
View File
@@ -0,0 +1,120 @@
/*
* 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.0 (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/config/config_paramdesc.h
* \brief configuration module, include file describing parameters, common to all implementations
* \author Francois TABURET
* \date 2017
* \version 0.1
* \company NOKIA BellLabs France
* \email: francois.taburet@nokia-bell-labs.com
* \note
* \warning
*/
#include <stdint.h>
#ifndef INCLUDE_CONFIG_PARAMDESC_H
#define INCLUDE_CONFIG_PARAMDESC_H
#define MAX_OPTNAME_SIZE 64
/* parameter flags definitions */
/* Flags to be used by calling modules in their parameters definitions to modify config module behavior*/
#define PARAMFLAG_MANDATORY (1 << 0) // parameter must be explicitely set, default value ignored
#define PARAMFLAG_DISABLECMDLINE (1 << 1) // parameter cannot bet set from comand line
#define PARAMFLAG_DONOTREAD (1 << 2) // parameter must be ignored in get function
#define PARAMFLAG_NOFREE (1 << 3) // don't free parameter in end function
#define PARAMFLAG_BOOL (1 << 4) // integer param can be 0 or 1
/* Flags used by config modules to return info to calling modules and/or to for internal usage*/
#define PARAMFLAG_MALLOCINCONFIG (1 << 15) // parameter allocated in config module
#define PARAMFLAG_PARAMSET (1 << 16) // parameter has been explicitely set in get functions
#define PARAMFLAG_PARAMSETDEF (1 << 17) // parameter has been set to default value in get functions
typedef struct paramdef
{
char optname[MAX_OPTNAME_SIZE]; /* parameter name, can be used as long command line option */
char *helpstr; /* help string */
unsigned int paramflags; /* value is a "ored" combination of above PARAMFLAG_XXXX values */
union { /* pointer to the parameter value, completed by the config module */
char **strptr;
char **strlistptr;
uint8_t *u8ptr;
char *i8ptr;
uint16_t *u16ptr;
int16_t *i16ptr;
uint32_t *uptr;
int32_t *iptr;
uint64_t *u64ptr;
int64_t *i64ptr;
double *dblptr;
} ;
union { /* default parameter value, to be used when PARAMFLAG_MANDATORY is not specified */
char *defstrval;
char **defstrlistval;
uint32_t defuintval;
int defintval;
uint64_t defint64val;
int *defintarrayval;
double defdblval;
} ;
char type; /* parameter value type, as listed below as TYPE_XXXX macro */
int numelt; /* number of elements in a list or array parameters or max size of string value */
} paramdef_t;
#define TYPE_INT TYPE_INT32
#define TYPE_UINT TYPE_UINT32
#define TYPE_STRING 1
#define TYPE_INT8 2
#define TYPE_UINT8 3
#define TYPE_INT16 4
#define TYPE_UINT16 5
#define TYPE_INT32 6
#define TYPE_UINT32 7
#define TYPE_INT64 8
#define TYPE_UINT64 9
#define TYPE_MASK 10
#define TYPE_DOUBLE 16
#define TYPE_IPV4ADDR 20
#define TYPE_STRINGLIST 50
#define TYPE_INTARRAY 51
#define TYPE_UINTARRAY 52
#define TYPE_LIST 55
#define ANY_IPV4ADDR_STRING "0.0.0.0"
typedef struct paramlist_def {
char listname[MAX_OPTNAME_SIZE];
paramdef_t **paramarray;
int numelt ;
} paramlist_def_t;
/* macro helpers for module users */
#define CONFIG_PARAMLENGTH(A) (sizeof(A)/sizeof(paramdef_t))
#endif /* INCLUDE_CONFIG_PARAMDESC_H */
+149
View File
@@ -0,0 +1,149 @@
/*
* 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.0 (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/config/config_userapi.c
* \brief configuration module, api implementation to access configuration parameters
* \author Francois TABURET
* \date 2017
* \version 0.1
* \company NOKIA BellLabs France
* \email: francois.taburet@nokia-bell-labs.com
* \note
* \warning
*/
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <dlfcn.h>
#include "config_userapi.h"
configmodule_interface_t *config_get_if(void)
{
if (cfgptr == NULL) {
fprintf(stderr,"[CONFIG] %s %d config module not initialized\n",__FILE__, __LINE__);
exit(-1);
}
return cfgptr;
}
char * config_check_valptr(paramdef_t *cfgoptions, char **ptr, int length)
{
printf_ptrs("-- %s 0x%08lx %i\n",cfgoptions->optname,(uintptr_t)(*ptr),length);
if (*ptr == NULL) {
*ptr = malloc(length);
if ( *ptr != NULL) {
memset(*ptr,0,length);
if ( (cfgoptions->paramflags & PARAMFLAG_NOFREE) != 0) {
config_get_if()->ptrs[config_get_if()->numptrs] = *ptr;
config_get_if()->numptrs++;
}
} else {
fprintf (stderr,"[CONFIG] %s %d malloc error\n",__FILE__, __LINE__);
exit(-1);
}
}
return *ptr;
}
void config_assign_int(paramdef_t *cfgoptions, char *fullname, int val)
{
int tmpval=val;
if ( ((cfgoptions->paramflags &PARAMFLAG_BOOL) != 0) && tmpval >1) {
tmpval =1;
}
switch (cfgoptions->type) {
case TYPE_UINT8:
*(cfgoptions->u8ptr) = (uint8_t)tmpval;
printf_params("[CONFIG] %s: %u\n", fullname, (uint8_t)tmpval);
break;
case TYPE_INT8:
*(cfgoptions->i8ptr) = (int8_t)tmpval;
printf_params("[CONFIG] %s: %i\n", fullname, (int8_t)tmpval);
break;
case TYPE_UINT16:
*(cfgoptions->u16ptr) = (uint16_t)tmpval;
printf_params("[CONFIG] %s: %hu\n", fullname, (uint16_t)tmpval);
break;
case TYPE_INT16:
*(cfgoptions->i16ptr) = (int16_t)tmpval;
printf_params("[CONFIG] %s: %hi\n", fullname, (int16_t)tmpval);
break;
case TYPE_UINT32:
*(cfgoptions->uptr) = (uint32_t)tmpval;
printf_params("[CONFIG] %s: %u\n", fullname, (uint32_t)tmpval);
break;
case TYPE_MASK:
*(cfgoptions->uptr) = *(cfgoptions->uptr) | (uint32_t)tmpval;
printf_params("[CONFIG] %s: 0x%08x\n", fullname, (uint32_t)tmpval);
break;
case TYPE_INT32:
*(cfgoptions->iptr) = (int32_t)tmpval;
printf_params("[CONFIG] %s: %i\n", fullname, (int32_t)tmpval);
break;
default:
fprintf (stderr,"[CONFIG] %s %i type %i non integer parameter %s not assigned\n",__FILE__, __LINE__,cfgoptions->type,fullname);
break;
}
}
void config_printhelp(paramdef_t *params,int numparams)
{
for (int i=0 ; i<numparams ; i++) {
if ( params[i].helpstr != NULL) {
printf("%s%s: %s",
(strlen(params[i].optname) <= 1) ? "-" : "--",
params[i].optname,
params[i].helpstr);
}
}
}
int config_get(paramdef_t *params,int numparams, char *prefix)
{
int ret= -1;
if (CONFIG_ISFLAGSET(CONFIG_ABORT)) {
fprintf(stderr,"[CONFIG] config_get skipped, config module not properly initialized\n");
return ret;
}
configmodule_interface_t *cfgif = config_get_if();
if (cfgif != NULL) {
ret = config_get_if()->get(params, numparams,prefix);
if (ret >= 0) {
config_process_cmdline(params,numparams,prefix);
}
return ret;
}
return ret;
}
int config_isparamset(paramdef_t *params,int paramidx)
{
if ((params[paramidx].paramflags & PARAMFLAG_PARAMSET) != 0) {
return 1;
} else {
return 0;
}
}
+61
View File
@@ -0,0 +1,61 @@
/*
* 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.0 (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/config/config_userapi.h
* \brief: configuration module, include file to be used by the source code calling the
* configuration module to access configuration parameters
* \author Francois TABURET
* \date 2017
* \version 0.1
* \company NOKIA BellLabs France
* \email: francois.taburet@nokia-bell-labs.com
* \note
* \warning
*/
#ifndef INCLUDE_CONFIG_USERAPI_H
#define INCLUDE_CONFIG_USERAPI_H
#include "config_load_configmodule.h"
#ifdef __cplusplus
extern "C"
{
#endif
#define CONFIG_GETSOURCE ( (config_get_if()==NULL) ? NULL : config_get_if()->cfgmode )
#define CONFIG_GETNUMP ( (config_get_if()==NULL) ? 0 : config_get_if()->num_cfgP )
#define CONFIG_GETP(P) ( (config_get_if()==NULL) ? NULL : config_get_if()->cfgP[P] )
#define CONFIG_ISFLAGSET(P) ( (config_get_if()==NULL) ? 0 : !!(config_get_if()->rtflags & P))
extern configmodule_interface_t *config_get_if(void);
extern char * config_check_valptr(paramdef_t *cfgoptions, char **ptr, int length) ;
extern void config_printhelp(paramdef_t *,int numparams);
extern int config_process_cmdline(paramdef_t *params,int numparams, char *prefix);
extern int config_get(paramdef_t *params,int numparams, char *prefix);
extern int config_isparamset(paramdef_t *params,int paramidx);
extern void config_assign_int(paramdef_t *cfgoptions, char *fullname, int val);
extern int config_process_cmdline(paramdef_t *cfgoptions,int numoptions, char *prefix);
#define config_getlist config_get_if()->getlist
#define CONFIG_GETCONFFILE (config_get_if()->cfgP[0])
#ifdef __cplusplus
}
#endif
#endif
+368
View File
@@ -0,0 +1,368 @@
#define _GNU_SOURCE
#include <libconfig.h>
#include <string.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include "config_libconfig.h"
#include "config_libconfig_private.h"
#include "../config_userapi.h"
#include "errno.h"
#if ( LIBCONFIG_VER_MAJOR == 1 && LIBCONFIG_VER_MINOR < 5)
#define config_setting_lookup config_lookup_from
#endif
void config_libconfig_end(void );
int read_strlist(paramdef_t *cfgoptions,config_setting_t *setting, char *cfgpath)
{
const char *str;
int st;
cfgoptions->numelt=config_setting_length(setting);
cfgoptions->strlistptr=malloc(sizeof(char *) * (cfgoptions->numelt));
st=0;
for (int i=0; i< cfgoptions->numelt && cfgoptions->strlistptr != NULL; i++) {
str=config_setting_get_string_elem(setting,i);
if (str==NULL) {
printf("[LIBCONFIG] %s%i not found in config file\n", cfgoptions->optname,i);
} else {
cfgoptions->strlistptr[i]=malloc(strlen(str)+1);
sprintf(cfgoptions->strlistptr[i],"%s",str);
st++;
printf_params("[LIBCONFIG] %s%i: %s\n", cfgpath,i,cfgoptions->strlistptr[i]);
}
}
return st;
}
int read_intarray(paramdef_t *cfgoptions,config_setting_t *setting, char *cfgpath)
{
cfgoptions->numelt=config_setting_length(setting);
if (cfgoptions->numelt > 0) {
cfgoptions->iptr=malloc(sizeof(int) * (cfgoptions->numelt));
for (int i=0; i< cfgoptions->numelt && cfgoptions->iptr != NULL; i++) {
cfgoptions->iptr[i]=config_setting_get_int_elem(setting,i);
printf_params("[LIBCONFIG] %s[%i]: %i\n", cfgpath,i,cfgoptions->iptr[i]);
} /* for loop on array element... */
}
return cfgoptions->numelt;
}
int config_libconfig_get(paramdef_t *cfgoptions,int numoptions, char *prefix )
{
config_setting_t *setting;
char *str;
int i,u;
long long int llu;
double dbl;
int rst;
int status=0;
int notfound;
int defval;
int fatalerror=0;
char *cfgpath; /* listname.[listindex].paramname */
int numdefvals=0;
i = (prefix ==NULL) ? 0 : strlen(prefix);
cfgpath = malloc( i+ MAX_OPTNAME_SIZE +1);
if (cfgpath == NULL) {
fprintf(stderr,"[LIBCONFIG] %s %i malloc error, %s\n", __FILE__, __LINE__,strerror(errno));
return -1;
}
for(i=0;i<numoptions;i++) {
if (prefix != NULL) {
sprintf(cfgpath,"%s.%s",prefix,cfgoptions[i].optname);
} else {
sprintf(cfgpath,"%s",cfgoptions[i].optname);
}
if( (cfgoptions->paramflags & PARAMFLAG_DONOTREAD) != 0) {
printf_params("[LIBCONFIG] %s.%s ignored\n", cfgpath,cfgoptions[i].optname );
continue;
}
notfound=0;
defval=0;
switch(cfgoptions[i].type)
{
case TYPE_STRING:
if ( config_lookup_string(&(libconfig_privdata.cfg),cfgpath, (const char **)&str)) {
if ( cfgoptions[i].numelt > 0 && str != NULL && strlen(str) >= cfgoptions[i].numelt ) {
fprintf(stderr,"[LIBCONFIG] %s: %s exceeds maximum length of %i bytes, value truncated\n",
cfgpath,str,cfgoptions[i].numelt);
str[strlen(str)-1] = 0;
}
config_check_valptr(&(cfgoptions[i]), (char **)(&(cfgoptions[i].strptr)), sizeof(char *));
config_check_valptr(&(cfgoptions[i]), cfgoptions[i].strptr, strlen(str)+1);
sprintf( *(cfgoptions[i].strptr) , "%s", str);
printf_params("[LIBCONFIG] %s: %s\n", cfgpath,*(cfgoptions[i].strptr) );
} else {
if( cfgoptions[i].defstrval != NULL) {
defval=1;
config_check_valptr(&(cfgoptions[i]), (char **)(&(cfgoptions[i].strptr)), sizeof(char *));
config_check_valptr(&(cfgoptions[i]), cfgoptions[i].strptr, strlen(cfgoptions[i].defstrval)+1);
sprintf(*(cfgoptions[i].strptr), "%s",cfgoptions[i].defstrval);
printf_params("[LIBCONFIG] %s set to default value %s\n", cfgpath, *(cfgoptions[i].strptr));
} else {
notfound=1;
}
}
break;
case TYPE_STRINGLIST:
setting = config_setting_lookup (config_root_setting(&(libconfig_privdata.cfg)),cfgpath );
if ( setting != NULL) {
read_strlist(&cfgoptions[i],setting,cfgpath);
} else {
if( cfgoptions[i].defstrlistval != NULL) {
cfgoptions[i].strlistptr=cfgoptions[i].defstrlistval;
defval=1;
for(int j=0; j<cfgoptions[i].numelt; j++)
printf_params("[LIBCONFIG] %s%i set to default value %s\n", cfgpath,j, cfgoptions[i].strlistptr[j]);
} else {
notfound=1;
}
}
break;
case TYPE_UINT8:
case TYPE_INT8:
case TYPE_UINT16:
case TYPE_INT16:
case TYPE_UINT32:
case TYPE_INT32:
case TYPE_MASK:
config_check_valptr(&(cfgoptions[i]), (char **)(&(cfgoptions[i].iptr)),sizeof(int32_t));
if ( config_lookup_int(&(libconfig_privdata.cfg),cfgpath, &u)) {
config_assign_int(&(cfgoptions[i]),cfgpath,u);
} else {
if( ((cfgoptions[i].paramflags & PARAMFLAG_MANDATORY) == 0)) {
config_assign_int(&(cfgoptions[i]),cfgpath,cfgoptions[i].defintval);
defval=1;
printf_params("[LIBCONFIG] %s set to default value\n", cfgpath);
} else {
notfound=1;
}
}
break;
case TYPE_UINT64:
case TYPE_INT64:
config_check_valptr(&(cfgoptions[i]), (char **)&(cfgoptions[i].i64ptr),sizeof(long long));
if ( config_lookup_int64(&(libconfig_privdata.cfg),cfgpath, &llu)) {
if(cfgoptions[i].type==TYPE_UINT64) {
*(cfgoptions[i].u64ptr) = (uint64_t)llu;
printf_params("[LIBCONFIG] %s: %llu\n", cfgpath,(long long unsigned)(*(cfgoptions[i].u64ptr)) );
} else {
*(cfgoptions[i].iptr) = llu;
printf_params("[LIBCONFIG] %s: %lli\n", cfgpath,(long long unsigned)(*(cfgoptions[i].i64ptr)) );
}
} else {
if( ((cfgoptions[i].paramflags & PARAMFLAG_MANDATORY) == 0)) {
*(cfgoptions[i].u64ptr)=cfgoptions[i].defuintval;
defval=1;
printf_params("[LIBCONFIG] %s set to default value %llu\n", cfgpath, (long long unsigned)(*(cfgoptions[i].u64ptr)));
} else {
notfound=1;
}
}
break;
case TYPE_UINTARRAY:
case TYPE_INTARRAY:
setting = config_setting_lookup (config_root_setting(&(libconfig_privdata.cfg)),cfgpath );
if ( setting != NULL) {
read_intarray(&cfgoptions[i],setting,cfgpath);
} else {
if( cfgoptions[i].defintarrayval != NULL) {
config_check_valptr(&(cfgoptions[i]),(char **)&(cfgoptions[i].iptr), sizeof(int32_t));
cfgoptions[i].iptr=cfgoptions[i].defintarrayval;
defval=1;
for (int j=0; j<cfgoptions[i].numelt ; j++) {
printf_params("[LIBCONFIG] %s[%i] set to default value %i\n", cfgpath,j,(int)cfgoptions[i].iptr[j]);
}
} else {
notfound=1;
}
}
break;
case TYPE_DOUBLE:
config_check_valptr(&(cfgoptions[i]), (char **)&(cfgoptions[i].dblptr),sizeof(double));
if ( config_lookup_float(&(libconfig_privdata.cfg),cfgpath, &dbl)) {
*(cfgoptions[i].dblptr) = dbl;
printf_params("[LIBCONFIG] %s: %lf\n", cfgpath,*(cfgoptions[i].dblptr) );
} else {
if( ((cfgoptions[i].paramflags & PARAMFLAG_MANDATORY) == 0)) {
*(cfgoptions[i].u64ptr)=cfgoptions[i].defdblval;
defval=1;
printf_params("[LIBCONFIG] %s set to default value %lf\n", cfgpath, *(cfgoptions[i].dblptr));
} else {
notfound=1;
}
}
break;
case TYPE_IPV4ADDR:
config_check_valptr(&(cfgoptions[i]),(char **)&(cfgoptions[i].uptr), sizeof(int));
if ( !config_lookup_string(&(libconfig_privdata.cfg),cfgpath, (const char **)&str)) {
str=cfgoptions[i].defstrval;
defval=1;
printf_params("[LIBCONFIG] %s set to default value %s\n", cfgpath, str);
}
if (str != NULL) {
rst=inet_pton(AF_INET, str,cfgoptions[i].uptr );
if (rst == 1 && *(cfgoptions[i].uptr) > 0) {
printf_params("[LIBCONFIG] %s: %s\n", cfgpath,str );
} else {
if ( strncmp(str,ANY_IPV4ADDR_STRING,sizeof(ANY_IPV4ADDR_STRING)) == 0) {
printf_params("[LIBCONFIG] %s:%s (INADDR_ANY) \n",cfgpath,str);
*cfgoptions[i].uptr=INADDR_ANY;
} else {
fprintf(stderr,"[LIBCONFIG] %s not valid for %s \n", str, cfgpath);
fatalerror=1;
}
}
} else {
notfound=1;
}
break;
case TYPE_LIST:
setting = config_setting_lookup (config_root_setting(&(libconfig_privdata.cfg)),cfgpath );
if ( setting) {
cfgoptions[i].numelt=config_setting_length(setting);
} else {
notfound=1;
}
break;
default:
fprintf(stderr,"[LIBCONFIG] %s type %i not supported\n", cfgpath,cfgoptions[i].type);
fatalerror=1;
break;
} /* switch on param type */
if( notfound == 1) {
printf("[LIBCONFIG] %s not found in %s ", cfgpath,libconfig_privdata.configfile );
if ( (cfgoptions[i].paramflags & PARAMFLAG_MANDATORY) != 0) {
fatalerror=1;
printf(" mandatory parameter missing\n");
} else {
printf("\n");
}
} else {
if (defval == 1) {
numdefvals++;
cfgoptions[i].paramflags = cfgoptions[i].paramflags | PARAMFLAG_PARAMSETDEF;
} else {
cfgoptions[i].paramflags = cfgoptions[i].paramflags | PARAMFLAG_PARAMSET;
}
status++;
}
} /* for loop on options */
printf("[LIBCONFIG] %s: %i/%i parameters successfully set, (%i to default value)\n",
((prefix == NULL)?"(root)":prefix),
status,numoptions,numdefvals );
if (fatalerror == 1) {
fprintf(stderr,"[LIBCONFIG] fatal errors found when processing %s \n", libconfig_privdata.configfile );
config_libconfig_end();
end_configmodule();
}
free(cfgpath);
return status;
}
int config_libconfig_getlist(paramlist_def_t *ParamList,
paramdef_t *params, int numparams, char *prefix)
{
config_setting_t *setting;
int i,j,status;
char *listpath=NULL;
char cfgpath[MAX_OPTNAME_SIZE*2 + 6]; /* prefix.listname.[listindex] */
if (prefix != NULL)
{
i=asprintf(&listpath ,"%s.%s",prefix,ParamList->listname);
}
else
{
i=asprintf(&listpath ,"%s",ParamList->listname);
}
setting = config_lookup(&(libconfig_privdata.cfg), listpath);
if ( setting) {
status = ParamList->numelt = config_setting_length(setting);
printf_params("[LIBCONFIG] %i %s in config file %s \n",
ParamList->numelt,listpath,libconfig_privdata.configfile );
} else {
printf("[LIBCONFIG] list %s not found in config file %s \n",
listpath,libconfig_privdata.configfile );
ParamList->numelt= 0;
status = -1;
}
if (ParamList->numelt > 0 && params != NULL) {
ParamList->paramarray = malloc(ParamList->numelt * sizeof(paramdef_t *));
if ( ParamList->paramarray != NULL) {
config_get_if()->ptrs[config_get_if()->numptrs] = (char *)(ParamList->paramarray);
config_get_if()->numptrs++;
} else {
fprintf (stderr,"[LIBCONFIG] %s %d malloc error\n",__FILE__, __LINE__);
exit(-1);
}
for (i=0 ; i < ParamList->numelt ; i++) {
ParamList->paramarray[i] = malloc(numparams * sizeof(paramdef_t));
if ( ParamList->paramarray[i] != NULL) {
config_get_if()->ptrs[config_get_if()->numptrs] = (char *)(ParamList->paramarray[i]);
config_get_if()->numptrs++;
} else {
fprintf (stderr,"[LIBCONFIG] %s %d malloc error\n",__FILE__, __LINE__);
exit(-1);
}
memcpy(ParamList->paramarray[i], params, sizeof(paramdef_t)*numparams);
for (j=0;j<numparams;j++) {
ParamList->paramarray[i][j].strptr = NULL ;
}
sprintf(cfgpath,"%s.[%i]",listpath,i);
config_libconfig_get(ParamList->paramarray[i], numparams, cfgpath );
} /* for i... */
} /* ParamList->numelt > 0 && params != NULL */
if (listpath != NULL)
free(listpath);
return status;
}
int config_libconfig_init(char *cfgP[], int numP)
{
config_init(&(libconfig_privdata.cfg));
libconfig_privdata.configfile = strdup((char *)cfgP[0]);
config_get_if()->numptrs=0;
memset(config_get_if()->ptrs,0,sizeof(void *) * CONFIG_MAX_ALLOCATEDPTRS);
/* Read the file. If there is an error, report it and exit. */
if(! config_read_file(&(libconfig_privdata.cfg), libconfig_privdata.configfile)) {
fprintf(stderr,"[LIBCONFIG] %s %d file %s - %d - %s\n",__FILE__, __LINE__,
libconfig_privdata.configfile, config_error_line(&(libconfig_privdata.cfg)),
config_error_text(&(libconfig_privdata.cfg)));
config_destroy(&(libconfig_privdata.cfg));
printf( "\n");
return -1;
}
return 0;
}
void config_libconfig_end(void )
{
config_destroy(&(libconfig_privdata.cfg));
if ( libconfig_privdata.configfile != NULL ) {
free(libconfig_privdata.configfile);
}
}
@@ -0,0 +1,54 @@
/*
* 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.0 (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/config/libconfig/config_libconfig.c
* \brief configuration module, include file for libconfig implementation
* \author Francois TABURET
* \date 2017
* \version 0.1
* \company NOKIA BellLabs France
* \email: francois.taburet@nokia-bell-labs.com
* \note
* \warning
*/
#ifndef INCLUDE_CONFIG_LIBCONFIG_H
#define INCLUDE_CONFIG_LIBCONFIG_H
#ifdef __cplusplus
extern "C"
{
#endif
#include "common/config/config_paramdesc.h"
typedef struct libconfig_privatedata {
char *configfile;
config_t cfg;
} libconfig_privatedata_t;
#ifdef __cplusplus
}
#endif
#endif /* INCLUDE_CONFIG_LIBCONFIG_H */
@@ -0,0 +1,39 @@
/*
* 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.0 (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/config/libconfig/config_libconfig_private.h
* \brief configuration module, include file for libconfig implementation
* \author Francois TABURET
* \date 2017
* \version 0.1
* \company NOKIA BellLabs France
* \email: francois.taburet@nokia-bell-labs.com
* \note
* \warning
*/
static libconfig_privatedata_t libconfig_privdata;
+2
View File
@@ -56,6 +56,8 @@ typedef struct {
int *nb_CC;
/// Number of MACRLC instances in this node
int nb_macrlc_inst;
/// Number of component carriers per instance in this node
int *nb_mac_CC;
/// Number of L1 instances in this node
int nb_L1_inst;
/// Number of Component Carriers per instance in this node
+2 -2
View File
@@ -29,10 +29,10 @@ typedef struct {
#define T_SHM_FILENAME "/T_shm_segment"
/* number of VCD functions (to be kept up to date! see in T_messages.txt) */
#define VCD_NUM_FUNCTIONS 142
#define VCD_NUM_FUNCTIONS 172
/* number of VCD variables (to be kept up to date! see in T_messages.txt) */
#define VCD_NUM_VARIABLES 107
#define VCD_NUM_VARIABLES 118
/* 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)
+59 -27
View File
@@ -16,63 +16,67 @@ ID = ENB_PHY_DL_TICK
ID = ENB_PHY_DLSCH_UE_DCI
DESC = eNodeB downlink UE specific DCI as sent by the PHY layer
GROUP = ALL:PHY:GRAPHIC:ENB
FORMAT = int,eNB_ID : int,frame : int,subframe : int,UE_id : int,rnti : int,dci_format : int,harq_pid : int,mcs : int,TBS
FORMAT = int,eNB_ID : int,frame : int,subframe : int,rnti : int,dci_format : int,harq_pid : int,mcs : int,TBS
ID = ENB_PHY_DLSCH_UE_ACK
DESC = eNodeB downlink UE ACK as seen by the PHY layer in process_HARQ_feedback
GROUP = ALL:PHY:GRAPHIC:ENB
FORMAT = int,eNB_ID : int,frame : int,subframe : int,UE_id : int,rnti : int,harq_pid
FORMAT = int,eNB_ID : int,frame : int,subframe : int,rnti : int,harq_pid
ID = ENB_PHY_DLSCH_UE_NACK
DESC = eNodeB downlink UE NACK as seen by the PHY layer in process_HARQ_feedback
GROUP = ALL:PHY:GRAPHIC:ENB
FORMAT = int,eNB_ID : int,frame : int,subframe : int,UE_id : int,rnti : int,harq_pid
FORMAT = int,eNB_ID : int,frame : int,subframe : int,rnti : int,harq_pid
ID = ENB_PHY_ULSCH_UE_DCI
DESC = eNodeB uplink UE specific DCI as sent by the PHY layer
GROUP = ALL:PHY:GRAPHIC:ENB
FORMAT = int,eNB_ID : int,frame : int,subframe : int,UE_id : int,rnti : int,harq_pid : int,mcs : int,round : int,first_rb : int,nb_rb : int,TBS : int,L : int,firstCCE
FORMAT = int,eNB_ID : int,frame : int,subframe : int,rnti : int,harq_pid : int,mcs : int,round : int,first_rb : int,nb_rb : int,TBS : int,L : int,firstCCE
ID = ENB_PHY_ULSCH_UE_NO_DCI_RETRANSMISSION
DESC = eNodeB uplink UE retransmission due to PHICH NACK (see generate_phich_top)
GROUP = ALL:PHY:GRAPHIC:ENB
FORMAT = int,eNB_ID : int,frame : int,subframe : int,UE_id : int,rnti : int,harq_pid
FORMAT = int,eNB_ID : int,frame : int,subframe : int,rnti : int,harq_pid
ID = ENB_PHY_ULSCH_UE_ACK
DESC = eNodeB uplink UE ACK as seen by the PHY layer
GROUP = ALL:PHY:GRAPHIC:ENB
FORMAT = int,eNB_ID : int,frame : int,subframe : int,UE_id : int,rnti : int,harq_pid
FORMAT = int,eNB_ID : int,frame : int,subframe : int,rnti : int,harq_pid
ID = ENB_PHY_ULSCH_UE_NACK
DESC = eNodeB uplink UE NACK as seen by the PHY layer
GROUP = ALL:PHY:GRAPHIC:ENB
FORMAT = int,eNB_ID : int,frame : int,subframe : int,UE_id : int,rnti : int,harq_pid
FORMAT = int,eNB_ID : int,frame : int,subframe : int,rnti : int,harq_pid
ID = ENB_PHY_INPUT_SIGNAL
DESC = eNodeB received signal in the time domain for a duration of 1ms
GROUP = ALL:PHY:GRAPHIC:HEAVY:ENB
FORMAT = int,eNB_ID : int,frame : int,subframe : int,antenna : buffer,rxdata
ID = ENB_PHY_OUTPUT_SIGNAL
DESC = eNodeB sent signal in the time domain for a duration of 1ms
GROUP = ALL:PHY:HEAVY:ENB
FORMAT = int,eNB_ID : int,CC_id : int,frame : int,subframe : int,antenna : buffer,txdata
ID = ENB_PHY_UL_CHANNEL_ESTIMATE
DESC = eNodeB channel estimation in the time domain
GROUP = ALL:PHY:GRAPHIC:HEAVY:ENB
FORMAT = int,eNB_ID : int,UE_ID : int,frame : int,subframe : int,antenna : buffer,chest_t
FORMAT = int,eNB_ID : int,rnti : int,frame : int,subframe : int,antenna : buffer,chest_t
ID = ENB_PHY_PUSCH_IQ
DESC = eNodeB PUSCH received IQ data
GROUP = ALL:PHY:GRAPHIC:HEAVY:ENB
FORMAT = int,eNB_ID : int,UE_ID : int,frame : int,subframe : int,nb_rb : int,N_RB_UL : int,symbols_per_tti : buffer,pusch_comp
FORMAT = int,eNB_ID : int,rnti : int,frame : int,subframe : int,nb_rb : int,N_RB_UL : int,symbols_per_tti : buffer,pusch_comp
ID = ENB_PHY_PUCCH_1AB_IQ
DESC = eNodeB PUCCH received IQ data
GROUP = ALL:PHY:GRAPHIC:HEAVY:ENB
FORMAT = int,eNB_ID : int,UE_ID : int,frame : int,subframe : int,I : int,Q
FORMAT = int,eNB_ID : int,rnti : int,frame : int,subframe : int,I : int,Q
ID = ENB_PHY_PUCCH_1_ENERGY
DESC = eNodeB PUCCH 1 energy and threshold
GROUP = ALL:PHY:GRAPHIC:HEAVY:ENB
FORMAT = int,eNB_ID : int,UE_ID : int,frame : int,subframe : int,energy : int,threshold
FORMAT = int,eNB_ID : int,rnti : int,frame : int,subframe : int,energy : int,threshold
ID = ENB_PHY_PHICH
DESC = eNodeB PHICH
GROUP = ALL:PHY:ENB
FORMAT = int,eNB_ID : int,frame : int,subframe : int,UE_id : int,rnti : int,harq_pid : int,NGROUP : int,NSF : int,ngroup : int,nseq : int,ACK : int,first_rb : int,n_DMRS
FORMAT = int,eNB_ID : int,frame : int,subframe : int,rnti : int,harq_pid : int,NGROUP : int,NSF : int,ngroup : int,nseq : int,ACK : int,first_rb : int,n_DMRS
ID = ENB_PHY_MSG3_ALLOCATION
DESC = eNodeB Msg3 allocation/reallocation
GROUP = ALL:PHY:ENB
FORMAT = int,eNB_ID : int,frame : int,subframe : int,UE_id : int,rnti : int,first_transmission : int,Msg3_frame : int,Msg3_subframe
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
FORMAT = int,eNB_ID : int,frame : int,subframe : int,UE_id : int,preamble : int,energy : int,delay
FORMAT = int,eNB_ID : int,frame : int,subframe : int,preamble : int,energy : int,delay
#MAC logs
ID = ENB_MAC_UE_DL_SDU
@@ -111,6 +115,10 @@ ID = ENB_MAC_UE_DL_PDU_WITH_DATA
DESC = MAC downlink PDU for an UE
GROUP = ALL:MAC:ENB
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
#RLC logs
ID = ENB_RLC_DL
@@ -826,27 +834,27 @@ ID = UE_PHY_DL_TICK
ID = UE_PHY_DLSCH_UE_DCI
DESC = UE downlink UE specific DCI as sent by the PHY layer
GROUP = ALL:PHY:GRAPHIC:UE
FORMAT = int,eNB_ID : int,frame : int,subframe : int,UE_id : int,rnti : int,dci_format : int,harq_pid : int,mcs : int,TBS
FORMAT = int,eNB_ID : int,frame : int,subframe : int,rnti : int,dci_format : int,harq_pid : int,mcs : int,TBS
ID = UE_PHY_DLSCH_UE_ACK
DESC = UE downlink UE ACK as seen by the PHY layer in process_HARQ_feedback
GROUP = ALL:PHY:GRAPHIC:UE
FORMAT = int,eNB_ID : int,frame : int,subframe : int,UE_id : int,rnti : int,harq_pid
FORMAT = int,eNB_ID : int,frame : int,subframe : int,rnti : int,harq_pid
ID = UE_PHY_DLSCH_UE_NACK
DESC = UE downlink UE NACK as seen by the PHY layer in process_HARQ_feedback
GROUP = ALL:PHY:GRAPHIC:UE
FORMAT = int,eNB_ID : int,frame : int,subframe : int,UE_id : int,rnti : int,harq_pid
FORMAT = int,eNB_ID : int,frame : int,subframe : int,rnti : int,harq_pid
ID = UE_PHY_ULSCH_UE_DCI
DESC = UE uplink UE specific DCI as sent by the PHY layer
GROUP = ALL:PHY:GRAPHIC:UE
FORMAT = int,eNB_ID : int,frame : int,subframe : int,UE_id : int,rnti : int,harq_pid : int,mcs : int,round : int,first_rb : int,nb_rb : int,TBS
FORMAT = int,eNB_ID : int,frame : int,subframe : int,rnti : int,harq_pid : int,mcs : int,round : int,first_rb : int,nb_rb : int,TBS
ID = UE_PHY_ULSCH_UE_ACK
DESC = UE uplink UE ACK as seen by the PHY layer
GROUP = ALL:PHY:GRAPHIC:UE
FORMAT = int,eNB_ID : int,frame : int,subframe : int,UE_id : int,rnti : int,harq_pid
FORMAT = int,eNB_ID : int,frame : int,subframe : int,rnti : int,harq_pid
ID = UE_PHY_ULSCH_UE_NACK
DESC = UE uplink UE NACK as seen by the PHY layer
GROUP = ALL:PHY:GRAPHIC:UE
FORMAT = int,eNB_ID : int,frame : int,subframe : int,UE_id : int,rnti : int,harq_pid
FORMAT = int,eNB_ID : int,frame : int,subframe : int,rnti : int,harq_pid
ID = UE_PHY_INPUT_SIGNAL
DESC = UE received signal in the time domain for a duration of 1ms
GROUP = ALL:PHY:GRAPHIC:HEAVY:UE
@@ -854,7 +862,7 @@ ID = UE_PHY_INPUT_SIGNAL
ID = UE_PHY_DL_CHANNEL_ESTIMATE
DESC = UE channel estimation in the time domain
GROUP = ALL:PHY:GRAPHIC:HEAVY:UE
FORMAT = int,eNB_ID : int,UE_ID : int,frame : int,subframe : int,antenna : buffer,chest_t
FORMAT = int,eNB_ID : int,frame : int,subframe : int,antenna : buffer,chest_t
ID = UE_PHY_PDCCH_IQ
DESC = UE PDCCH received IQ data
GROUP = ALL:PHY:GRAPHIC:HEAVY:UE
@@ -862,27 +870,27 @@ ID = UE_PHY_PDCCH_IQ
ID = UE_PHY_PDCCH_ENERGY
DESC = UE PDSCH 1 energy and threshold
GROUP = ALL:PHY:GRAPHIC:HEAVY:UE
FORMAT = int,eNB_ID : int,UE_ID : int,frame : int,subframe : int,pdcch_ch_level00 : int,pdcch_ch_level01 : int,pdcch_ch_level10: int,pdcch_ch_level11
FORMAT = int,eNB_ID : int,frame : int,subframe : int,pdcch_ch_level00 : int,pdcch_ch_level01 : int,pdcch_ch_level10: int,pdcch_ch_level11
ID = UE_PHY_PDSCH_IQ
DESC = UE PDSCH received IQ data
GROUP = ALL:PHY:GRAPHIC:HEAVY:UE
FORMAT = int,eNB_ID : int,UE_ID : int,frame : int,subframe : int,nb_rb : int,N_RB_UL : int,symbols_per_tti : buffer,pusch_comp
FORMAT = int,eNB_ID : int,frame : int,subframe : int,nb_rb : int,N_RB_UL : int,symbols_per_tti : buffer,pusch_comp
ID = UE_PHY_PDSCH_ENERGY
DESC = UE PDSCH 1 energy and threshold
GROUP = ALL:PHY:GRAPHIC:HEAVY:UE
FORMAT = int,eNB_ID : int,UE_ID : int,frame : int,subframe : int,pdsch_ch_level00 : int,pdsch_ch_level01 : int,pdsch_ch_level10: int,pdsch_ch_level11
FORMAT = int,eNB_ID : int,frame : int,subframe : int,pdsch_ch_level00 : int,pdsch_ch_level01 : int,pdsch_ch_level10: int,pdsch_ch_level11
ID = UE_PHY_PUSCH_TX_POWER
DESC = UE PUSCH tx power
GROUP = ALL:PHY:GRAPHIC:HEAVY:UE
FORMAT = int,eNB_ID : int,UE_id : int,frame : int,subframe : int,p0_pusch : int,ampl: int,g_pusch: int,pl: int,nb_rb
FORMAT = int,eNB_ID : int,frame : int,subframe : int,p0_pusch : int,ampl: int,g_pusch: int,pl: int,nb_rb
ID = UE_PHY_PUCCH_TX_POWER
DESC = UE PDSCH 1 energy and threshold
GROUP = ALL:PHY:GRAPHIC:HEAVY:UE
FORMAT = int,eNB_ID : int,UE_id : int,frame : int,subframe : int,p0_pucch : int,ampl: int,g_pucch: int,pl
FORMAT = int,eNB_ID : int,frame : int,subframe : int,p0_pucch : int,ampl: int,g_pucch: int,pl
ID = UE_PHY_MEAS
DESC = UE PHY measurements
GROUP = ALL:PHY:GRAPHIC:HEAVY:UE
FORMAT = int,eNB_ID : int,UE_ID : int,frame : int,subframe : int,rsrp : int,rssi : int,snr: int,rx_power: int,noise_power: int,w_cqi: int,freq_offset
FORMAT = int,eNB_ID : int,frame : int,subframe : int,rsrp : int,rssi : int,snr: int,rx_power: int,noise_power: int,w_cqi: int,freq_offset
#for debug/test - not used
ID = first
@@ -1350,6 +1358,22 @@ ID = VCD_VARIABLE_UE0_SFN7
DESC = VCD variable UE0_SFN7
GROUP = ALL:VCD:ENB:VCD_VARIABLE
FORMAT = ulong,value
ID = VCD_VARIABLE_SEND_IF4_SYMBOL
DESC = VCD variable SEND_IF4_SYMBOL
GROUP = ALL:VCD:ENB:VCD_VARIABLE
FORMAT = ulong,value
ID = VCD_VARIABLE_RECV_IF4_SYMBOL
DESC = VCD variable RECV_IF4_SYMBOL
GROUP = ALL:VCD:ENB:VCD_VARIABLE
FORMAT = ulong,value
ID = VCD_VARIABLE_SEND_IF5_PKT_ID
DESC = VCD variable SEND_IF5_PKT_ID
GROUP = ALL:VCD:ENB:VCD_VARIABLE
FORMAT = ulong,value
ID = VCD_VARIABLE_RECV_IF5_PKT_ID
DESC = VCD variable RECV_IF5_PKT_ID
GROUP = ALL:VCD:ENB:VCD_VARIABLE
FORMAT = ulong,value
ID = VCD_VARIABLE_UE_PDCP_FLUSH_SIZE
DESC = VCD variable UE_PDCP_FLUSH_SIZE
GROUP = ALL:VCD:ENB:UE:VCD_VARIABLE
@@ -2061,3 +2085,11 @@ ID = VCD_FUNCTION_RECV_IF5
DESC = VCD function RECV_IF5
GROUP = ALL:VCD:ENB:VCD_FUNCTION
FORMAT = int,value
ID = VCD_FUNCTION_TRX_COMPR_IF
DESC = VCD function TRX_COMPR_IF
GROUP = ALL:VCD:ENB:VCD_FUNCTION
FORMAT = int,value
ID = VCD_FUNCTION_TRX_DECOMPR_IF
DESC = VCD function TRX_DECOMPR_IF
GROUP = ALL:VCD:ENB:VCD_FUNCTION
FORMAT = int,value
+8 -3
View File
@@ -5,7 +5,8 @@ CFLAGS=-Wall -g -pthread -DT_TRACER -I.
LIBS=-lX11 -lm -lpng -lXft
all: record replay extract_config textlog enb ue vcd macpdu2wireshark
all: record replay extract_config textlog enb ue vcd macpdu2wireshark \
extract_input_subframe
record: utils.o record.o database.o config.o
$(CC) $(CFLAGS) -o record $^ $(LIBS)
@@ -16,6 +17,10 @@ replay: utils.o replay.o
extract_config: extract_config.o
$(CC) $(CFLAGS) -o extract_config $^ $(LIBS)
extract_input_subframe: extract_input_subframe.o database.o event.o utils.o \
config.o
$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
textlog: utils.o textlog.o database.o event.o handler.o config.o \
event_selector.o view/view.a gui/gui.a logger/logger.a \
filter/filter.a
@@ -58,8 +63,8 @@ filter/filter.a:
$(CC) $(CFLAGS) -c -o $@ $<
clean:
rm -f *.o core tracer_remote textlog enb vcd record replay
rm -f extract_config macpdu2wireshark
rm -f *.o core tracer_remote textlog enb ue vcd record replay
rm -f extract_config macpdu2wireshark extract_input_subframe
cd gui && make clean
cd view && make clean
cd logger && make clean
+61 -9
View File
@@ -17,6 +17,40 @@
#include "openair_logo.h"
#include "config.h"
/****************************************************************************/
/* conversion from rnti to "ue_id" (which does not really exists) */
/* the idea is to assign an ue_id to an rnti as soon as we get an event */
/* for the rnti */
/****************************************************************************/
int ue_id[65536];
int next_ue_id;
void reset_ue_ids(void)
{
int i;
printf("resetting known UEs\n");
for (i = 0; i < 65536; i++) ue_id[i] = -1;
next_ue_id = 0;
}
int ue_id_from_rnti(void *_priv, int rnti)
{
rnti = 0; /* HACK, to be removed */
if (rnti < 0 || rnti > 65535) { printf("bad rnti %d\n", rnti); exit(1); }
/* rnti not seen yet? give it a new ue_id */
if (ue_id[rnti] == -1) {
ue_id[rnti] = next_ue_id;
next_ue_id++;
}
return ue_id[rnti];
}
/****************************************************************************/
/* end of rnti->ue_id conversion */
/****************************************************************************/
typedef struct {
view *phyview;
view *macview;
@@ -25,6 +59,7 @@ typedef struct {
view *rrcview;
view *legacy;
widget *current_ue_label;
widget *current_ue_button;
widget *prev_ue_button;
widget *next_ue_button;
widget *pusch_iq_ue_xy_plot;
@@ -116,11 +151,15 @@ static void *gui_thread(void *_g)
static filter *ticktime_filter(void *database, char *event, int i, int ue)
{
/* filter is "harq_pid == i && UE_id == 0 && eNB_id == 0" */
/* we get the UE_id from the rnti */
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_evfun(database, ue_id_from_rnti, NULL,
filter_evarg(database, event, "rnti")),
filter_int(ue)),
filter_eq(filter_evarg(database, event, "eNB_ID"), filter_int(0))));
}
@@ -148,23 +187,28 @@ static void set_current_ue(gui *g, enb_data *e, int ue)
logger_set_filter(e->e->pusch_iq_ue_logger,
filter_eq(
filter_evarg(e->database, "ENB_PHY_PUSCH_IQ", "UE_ID"),
filter_evfun(e->database, ue_id_from_rnti, NULL,
filter_evarg(e->database, "ENB_PHY_PUSCH_IQ", "rnti")),
filter_int(ue)));
logger_set_filter(e->e->ul_estimate_ue_logger,
filter_eq(
filter_evarg(e->database, "ENB_PHY_UL_CHANNEL_ESTIMATE", "UE_ID"),
filter_evfun(e->database, ue_id_from_rnti, NULL,
filter_evarg(e->database, "ENB_PHY_UL_CHANNEL_ESTIMATE", "rnti")),
filter_int(ue)));
logger_set_filter(e->e->pucch1_energy_ue_threshold_logger,
filter_eq(
filter_evarg(e->database, "ENB_PHY_PUCCH_1_ENERGY", "UE_ID"),
filter_evfun(e->database, ue_id_from_rnti, NULL,
filter_evarg(e->database, "ENB_PHY_PUCCH_1_ENERGY", "rnti")),
filter_int(ue)));
logger_set_filter(e->e->pucch1_energy_ue_energy_logger,
filter_eq(
filter_evarg(e->database, "ENB_PHY_PUCCH_1_ENERGY", "UE_ID"),
filter_evfun(e->database, ue_id_from_rnti, NULL,
filter_evarg(e->database, "ENB_PHY_PUCCH_1_ENERGY", "rnti")),
filter_int(ue)));
logger_set_filter(e->e->pucch_iq_ue_logger,
filter_eq(
filter_evarg(e->database, "ENB_PHY_PUCCH_1AB_IQ", "UE_ID"),
filter_evfun(e->database, ue_id_from_rnti, NULL,
filter_evarg(e->database, "ENB_PHY_PUCCH_1AB_IQ", "rnti")),
filter_int(ue)));
for (i = 0; i < 8; i++) {
logger_set_filter(e->e->dl_dci_logger[i],
@@ -185,11 +229,13 @@ static void set_current_ue(gui *g, enb_data *e, int ue)
}
logger_set_filter(e->e->dl_mcs_logger,
filter_eq(
filter_evarg(e->database, "ENB_PHY_DLSCH_UE_DCI", "UE_id"),
filter_evfun(e->database, ue_id_from_rnti, NULL,
filter_evarg(e->database, "ENB_PHY_DLSCH_UE_DCI", "rnti")),
filter_int(ue)));
logger_set_filter(e->e->ul_mcs_logger,
filter_eq(
filter_evarg(e->database, "ENB_PHY_ULSCH_UE_DCI", "UE_id"),
filter_evfun(e->database, ue_id_from_rnti, NULL,
filter_evarg(e->database, "ENB_PHY_ULSCH_UE_DCI", "rnti")),
filter_int(ue)));
}
@@ -205,6 +251,7 @@ static void click(void *private, gui *g,
if (button != 1) return;
if (w == e->prev_ue_button) { ue--; if (ue < 0) ue = 0; }
if (w == e->next_ue_button) ue++;
if (w == e->current_ue_button) reset_ue_ids();
if (pthread_mutex_lock(&ed->lock)) abort();
if (ue != ed->ue) {
@@ -248,10 +295,12 @@ static void enb_main_gui(enb_gui *e, gui *g, event_handler *h, void *database,
widget_add_child(g, col, logo, -1);
w = new_container(g, HORIZONTAL);
widget_add_child(g, col, w, -1);
/* TODO: use button widget, not label widget */
w2 = new_label(g, "");
widget_add_child(g, w, w2, -1);
label_set_clickable(g, w2, 1);
e->current_ue_button = w2;
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);
@@ -590,6 +639,7 @@ static void enb_main_gui(enb_gui *e, gui *g, event_handler *h, void *database,
e->legacy = new_view_textlist(10000, 10, g, text);
set_current_ue(g, ed, 0);
register_notifier(g, "click", e->current_ue_button, click, ed);
register_notifier(g, "click", e->prev_ue_button, click, ed);
register_notifier(g, "click", e->next_ue_button, click, ed);
}
@@ -628,6 +678,8 @@ int main(int n, char **v)
enb_gui eg;
enb_data enb_data;
reset_ue_ids();
/* write on a socket fails if the other end is closed and we get SIGPIPE */
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) abort();
@@ -0,0 +1,109 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include "database.h"
#include "event.h"
#include "config.h"
void usage(void)
{
printf(
"usage: [options] <file> <frame> <subframe>\n"
"options:\n"
" -d <database file> this option is mandatory\n"
" -v verbose\n"
);
exit(1);
}
int main(int n, char **v)
{
char *database_filename = NULL;
void *database;
int i;
int input_event_id;
database_event_format f;
char *file = NULL;
int fd;
int frame = -1, subframe = -1;
int frame_arg, subframe_arg, buffer_arg;
int verbose = 0;
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], "-v")) { verbose = 1; continue; }
if (file == NULL) { file = v[i]; continue; }
if (frame == -1) { frame = atoi(v[i]); continue; }
if (subframe == -1) { subframe = atoi(v[i]); continue; }
usage();
}
if (file == NULL || frame == -1 || subframe == -1) usage();
if (database_filename == NULL) {
printf("ERROR: provide a database file (-d)\n");
exit(1);
}
database = parse_database(database_filename);
load_config_file(database_filename);
input_event_id = event_id_from_name(database, "ENB_PHY_INPUT_SIGNAL");
f = get_format(database, input_event_id);
frame_arg = subframe_arg = buffer_arg = -1;
for (i = 0; i < f.count; i++) {
if (!strcmp(f.name[i], "frame")) {
if (frame_arg != -1) goto err;
if (strcmp(f.type[i], "int")) goto err;
frame_arg = i;
}
if (!strcmp(f.name[i], "subframe")) {
if (subframe_arg != -1) goto err;
if (strcmp(f.type[i], "int")) goto err;
subframe_arg = i;
}
if (!strcmp(f.name[i], "rxdata")) {
if (buffer_arg != -1) goto err;
if (strcmp(f.type[i], "buffer")) goto err;
buffer_arg = i;
}
continue;
err:
printf("cannot deal with ENB_PHY_INPUT_SIGNAL from database file\n");
exit(1);
}
if (frame_arg == -1 || subframe_arg == -1 || buffer_arg == -1) goto err;
fd = open(file, O_RDONLY);
if (fd == -1) { perror(file); exit(1); }
/* get wanted frame/subframe */
while (1) {
char v[T_BUFFER_MAX];
event e;
e = get_event(fd, v, database);
if (e.type == -1) break;
if (e.type != input_event_id) continue;
if (verbose)
printf("input frame %d subframe %d size %d\n",
e.e[frame_arg].i, e.e[subframe_arg].i, e.e[buffer_arg].bsize);
if (!(frame == e.e[frame_arg].i && subframe == e.e[subframe_arg].i))
continue;
#if 0
for (i = 0; i < e.e[buffer_arg].bsize/2; i++) {
short *x = e.e[buffer_arg].b;
x[i] *= 14;
}
#endif
fwrite(e.e[buffer_arg].b, e.e[buffer_arg].bsize, 1, stdout);
fflush(stdout);
return 0;
}
printf("frame %d subframe %d not found\n", frame, subframe);
return 0;
}
+26
View File
@@ -10,6 +10,8 @@ struct filter {
struct { struct filter *a, *b; } op2;
int v;
struct { int event_type; int arg_index; } evarg;
struct { int (*fun)(void *priv, int v); void *priv;
struct filter *x; } evfun;
} v;
int (*eval)(struct filter *this, event e);
@@ -52,6 +54,11 @@ int eval_evarg(struct filter *f, event e)
return e.e[f->v.evarg.arg_index].i;
}
int eval_evfun(struct filter *f, event e)
{
return f->v.evfun.fun(f->v.evfun.priv, f->v.evfun.x->eval(f->v.evfun.x, e));
}
/****************************************************************************/
/* free memory functions */
/****************************************************************************/
@@ -63,6 +70,12 @@ void free_op2(struct filter *f)
free(f);
}
void free_evfun(struct filter *f)
{
free_filter(f->v.evfun.x);
free(f);
}
void free_noop(struct filter *f)
{
free(f);
@@ -135,6 +148,19 @@ filter *filter_evarg(void *database, char *event_name, char *varname)
return ret;
}
filter *filter_evfun(void *database, int (*fun)(void *priv, int v),
void *priv, filter *x)
{
struct filter *ret = calloc(1, sizeof(struct filter));
if (ret == NULL) abort();
ret->eval = eval_evfun;
ret->free = free_evfun;
ret->v.evfun.fun = fun;
ret->v.evfun.priv = priv;
ret->v.evfun.x = x;
return ret;
}
void free_filter(filter *_f)
{
struct filter *f;
+2
View File
@@ -9,6 +9,8 @@ filter *filter_and(filter *a, filter *b);
filter *filter_eq(filter *a, filter *b);
filter *filter_int(int v);
filter *filter_evarg(void *database, char *event_name, char *varname);
filter *filter_evfun(void *database, int (*fun)(void *priv, int v),
void *priv, filter *x);
int filter_eval(filter *f, event e);
+5 -1
View File
@@ -623,7 +623,7 @@ static inline void itti_receive_msg_internal_event_fd(task_id_t task_id, uint8_t
read_ret = read (itti_desc.threads[thread_id].task_event_fd, &sem_counter, sizeof(sem_counter));
AssertFatal (read_ret == sizeof(sem_counter), "Read from task message FD (%d) failed (%d/%d)!\n", thread_id, (int) read_ret, (int) sizeof(sem_counter));
printf("sem_counter %d task %d\n", (int)sem_counter, task_id);
if (lfds611_queue_dequeue (itti_desc.tasks[task_id].message_queue, (void **) &message) == 0) {
/* No element in list -> this should not happen */
AssertFatal (0, "No message in queue for task %d while there are %d events and some for the messages queue!\n", task_id, epoll_ret);
@@ -631,9 +631,13 @@ static inline void itti_receive_msg_internal_event_fd(task_id_t task_id, uint8_t
AssertFatal(message != NULL, "Message from message queue is NULL!\n");
*received_msg = message->msg;
printf("ITTI: message %s\n", ITTI_MSG_NAME(message->msg));
result = itti_free (ITTI_MSG_ORIGIN_ID(*received_msg), message);
AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
/* Mark that the event has been processed */
itti_desc.threads[thread_id].events[i].events &= ~EPOLLIN;
return;
+52
View File
@@ -0,0 +1,52 @@
/* FT NOKBLF:
* this source is to be linked with the program using the telnet server, it looks for
* the telnet server dynamic library, possibly loads it and calls the telnet server
* init functions
*/
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#include <dlfcn.h>
#include "openair1/PHY/defs.h"
#define LOAD_MODULE_SHLIB_MAIN
#include "load_module_shlib.h"
int load_module_shlib(char *modname)
{
void *lib_handle;
initfunc_t fpi;
char *tmpstr;
int ret=0;
tmpstr = malloc(strlen(modname)+16);
if (tmpstr == NULL) {
fprintf(stderr,"[LOADER] %s %d malloc error loading module %s, %s\n",__FILE__, __LINE__, modname, strerror(errno));
return -1;
}
sprintf(tmpstr,"lib%s.so",modname);
lib_handle = dlopen(tmpstr, RTLD_LAZY|RTLD_NODELETE|RTLD_GLOBAL);
if (!lib_handle) {
printf("[LOADER] library %s is not loaded: %s\n", tmpstr,dlerror());
ret = -1;
} else {
sprintf(tmpstr,"init_%s",modname);
fpi = dlsym(lib_handle,tmpstr);
if (fpi != NULL )
{
fpi();
}
else
{
fprintf(stderr,"[LOADER] %s %d %s function not found %s\n",__FILE__, __LINE__, dlerror(),tmpstr);
ret = -1;
}
}
if (tmpstr != NULL) free(tmpstr);
if (lib_handle != NULL) dlclose(lib_handle);
return ret;
}
+11
View File
@@ -0,0 +1,11 @@
#ifndef LOAD_SHLIB_H
#define LOAD_SHLIB_H
typedef int(*initfunc_t)(void);
#ifdef LOAD_MODULE_SHLIB_MAIN
#else
extern int load_module_shlib(char *modname);
#endif
#endif
+59
View File
@@ -0,0 +1,59 @@
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
IF(DEFINED ENV{OPENAIR_DIR})
message("...using oai source files in $ENV{OPENAIR_DIR}")
ELSE()
message("OPENAIR_DIR is not defined. You must run \"source oaienv\" from the oai root dir")
# exit early
return()
ENDIF()
set(OPENAIR_DIR $ENV{OPENAIR_DIR})
set(APPROOT ${OPENAIR_DIR}/common/utils/telnetsrv )
set(OPENAIR_BUILD_DIR $ENV{OPENAIR_DIR}/cmake_targets)
set(OPENAIR1_DIR $ENV{OPENAIR1_DIR})
set(OPENAIR2_DIR $ENV{OPENAIR2_DIR})
set(OPENAIR3_DIR $ENV{OPENAIR3_DIR})
set(OPENAIR_PHY_DIR $ENV{OPENAIR1_DIR}/PHY)
set(OPENAIR_TARGET_DIR $ENV{OPENAIR_DIR}/targets)
set(OPENAIR_COMMONUTILS_DIR $ENV{OPENAIR_DIR}/common/utils)
set(OPENAIR2_COMMON_DIR $ENV{OPENAIR_DIR}/openair2/COMMON)
set(OPENAIR_ASN1INC ${OPENAIR_BUILD_DIR}/lte_build_oai/build/CMakeFiles/Rel14)
set(OPENAIR_NFAPIINC $ENV{NFAPI_DIR} )
set(CMAKE_INSTALL_PREFIX $ENV{OPENAIR_TARGETS})
add_definitions (-DRel14 -DCMAKER -DENABLE_FXP -DENABLE_ITTI -DENABLE_NAS_UE_LOGGING -DENABLE_SECURITY -DENABLE_USE_CPU_EXECUTION_TIME -DENABLE_USE_MME -DENABLE_VCD -DENB_AGENT -DENB_MODE -DETHERNET=1 -DEXMIMO_IOT -DJUMBO_FRAME -DLINK_ENB_PDCP_TO_GTPV1U -DLOG_NO_THREAD -DMAC_CONTEXT -DMAX_NUM_CCs=1 -DNAS_BUILT_IN_UE -DNAS_UE -DNB_ANTENNAS_RX=2 -DNB_ANTENNAS_TX=2 -DNB_ANTENNAS_TXRX=2 -DNEW_FFT -DNO_RRM -DNone=1 -DOAI_NW_DRIVER_USE_NETLINK -DOPENAIR1 -DOPENAIR2 -DOPENAIR_LTE -DPC_DSP -DPC_TARGET -DPHYSIM -DPHY_CONTEXT -DPUCCH -DRel10=1 -DS1AP_VERSION=R10 -DTRACE_RLC_MUTEX -DUSER_MODE -DX2AP_VERSION=R11 -DXFORMS -mavx2 -msse4.1 -mssse3)
add_compile_options( -fPIC -march=native -Ofast)
include_directories( ./ ${OPENAIR_COMMON_DIR} ${OPENAIR_DIR} ${OPENAIR1_DIR} ${OPENAIR2_DIR} ${OPENAIR2_COMMON_DIR} ${OPENAIR2_DIR}/UTIL/LOG
${OPENAIR_COMMONUTILS_DIR}/msc ${OPENAIR_COMMONUTILS_DIR}/itti ${OPENAIR_COMMONUTILS_DIR}/hashtable ${OPENAIR_COMMONUTILS_DIR} ${OPENAIR_ASN1INC}
${OPENAIR2_DIR}/LAYER2/RLC/AM_v9.3.0 ${OPENAIR_COMMONUTILS_DIR}/msc ${OPENAIR_COMMONUTILS_DIR}/itti ${OPENAIR_COMMONUTILS_DIR}/hashtable ${OPENAIR_COMMONUTILS_DIR} ${OPENAIR_ASN1INC}
${OPENAIR2_DIR}/LAYER2/RLC ${OPENAIR2_DIR}/UTIL/LISTS ${OPENAIR2_DIR}/UTIL/MEM ${OPENAIR2_DIR}/LAYER2/RLC/UM_v9.3.0
${OPENAIR2_DIR}/LAYER2/RLC/TM_v9.3.0 ${OPENAIR2_DIR}/RRC/LITE ${OPENAIR_TARGET_DIR}/COMMON ${OPENAIR_TARGET_DIR}/ARCH/COMMON
${OPENAIR3_DIR}/NAS/COMMON/API/NETWORK ${OPENAIR3_DIR}/NAS/COMMON/EMM/MSG/ ${OPENAIR3_DIR}/NAS/COMMON/IES/ ${OPENAIR3_DIR}/NAS/COMMON/UTIL
${OPENAIR3_DIR}/NAS/COMMON/ESM/MSG/ ${OPENAIR3_DIR}/GTPV1-U ${OPENAIR3_DIR}/GTPV1-U/nw-gtpv1u/shared ${OPENAIR3_DIR}/GTPV1-U/nw-gtpv1u/include
${OPENAIR3_DIR}/UTILS ${OPENAIR_NFAPIINC})
set(TELNETSRV_SOURCE
${APPROOT}/telnetsrv.c
${APPROOT}/telnetsrv_phycmd.c
${APPROOT}/telnetsrv_proccmd.c
)
#set(TELNETSRV_ETHDEVCMD_SOURCE
# ${APPROOT}/telnetsrv/telnetsrv_ethdevcmd.c
# )
add_library(telnetsrv MODULE ${TELNETSRV_SOURCE} )
#add_library(telnetsrv_ethdevcmd MODULE ${TELNETSRV_ETHDEVCMD_SOURCE} )
install(TARGETS telnetsrv DESTINATION bin)
if (EXISTS "${OPENAIR_BUILD_DIR}/lte_build_oai/build" AND IS_DIRECTORY "${OPENAIR_BUILD_DIR}/lte_build_oai/build")
install(TARGETS telnetsrv DESTINATION ${OPENAIR_BUILD_DIR}/lte_build_oai/build)
endif (EXISTS "${OPENAIR_BUILD_DIR}/lte_build_oai/build" AND IS_DIRECTORY "${OPENAIR_BUILD_DIR}/lte_build_oai/build")
+696
View File
@@ -0,0 +1,696 @@
/*
* 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.0 (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.c
* \brief: implementation of a telnet server
* \author Francois TABURET
* \date 2017
* \version 0.1
* \company NOKIA BellLabs France
* \email: francois.taburet@nokia-bell-labs.com
* \note
* \warning
*/
#define _GNU_SOURCE
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <pthread.h>
#include <telnetsrv.h>
#include <string.h>
#include <stdarg.h>
#include <unistd.h>
#include <fcntl.h>
#include <dlfcn.h>
#include <sys/time.h>
#include <sys/resource.h>
#include "common/config/config_userapi.h"
#include "telnetsrv_phycmd.h"
#include "telnetsrv_proccmd.h"
static char* telnet_defstatmod[] = {"softmodem","phy"};
static telnetsrv_params_t telnetparams;
#define TELNETSRV_LISTENADDR 0
#define TELNETSRV_LISTENPORT 1
#define TELNETSRV_PRIORITY 2
#define TELNETSRV_DEBUG 3
#define TELNETSRV_STATICMOD 7
#define TELNETSRV_SHRMOD 8
paramdef_t telnetoptions[] = {
/*--------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
/* configuration parameters for telnet utility */
/* optname helpstr paramflags XXXptr defXXXval type numelt */
/*--------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
{"listenaddr", "<listen ip address>", 0, uptr:&telnetparams.listenaddr, defstrval:"0.0.0.0", TYPE_IPV4ADDR, 0 },
{"listenport", "<local port>", 0, uptr:&(telnetparams.listenport), defuintval:9090, TYPE_UINT, 0 },
{"priority", "<scheduling policy (0-99)", 0, uptr:&telnetparams.priority, defuintval:0, TYPE_INT, 0 },
{"debug", "<debug level>", 0, uptr:NULL, defuintval:0, TYPE_UINT, 0 },
{"loopcount", "<loop command iterations>", 0, uptr:&(telnetparams.loopcount), defuintval:10, TYPE_UINT, 0 },
{"loopdelay", "<loop command delay (ms)>", 0, uptr:&(telnetparams.loopdelay), defuintval:5000, TYPE_UINT, 0 },
{"phypbsize", "<phy dump buff size (bytes)>",0, uptr:&(telnetparams.phyprntbuff_size),defuintval:65000, TYPE_UINT, 0 },
{"staticmod", "<static modules selection>", 0, NULL, defstrlistval:telnet_defstatmod,TYPE_STRINGLIST,1},
{"shrmod", "<static modules selection>", 0, NULL, NULL,TYPE_STRINGLIST,0 },
};
int get_phybsize() {return telnetparams.phyprntbuff_size; };
int add_telnetcmd(char *modulename,telnetshell_vardef_t *var, telnetshell_cmddef_t *cmd );
int setoutput(char *buff, int debug, telnet_printfunc_t prnt);
int setparam(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},
{"",0,NULL}
};
telnetshell_cmddef_t telnet_cmdarray[] = {
{"redirlog","[here,file,off]",setoutput},
{"param","[prio]",setparam},
{"","",NULL},
};
void client_printf(const char *message, ...)
{
va_list va_args;
va_start(va_args, message);
if (telnetparams.new_socket > 0)
{
vsnprintf(telnetparams.msgbuff,sizeof(telnetparams.msgbuff)-1,message, va_args);
send(telnetparams.new_socket,telnetparams.msgbuff , strlen(telnetparams.msgbuff), MSG_NOSIGNAL);
}
else
{
vprintf(message, va_args);
}
va_end(va_args);
return ;
}
#define NICE_MAX 19
#define NICE_MIN -20
void set_sched(pthread_t tid, int pid, int priority)
{
int rt;
struct sched_param schedp;
int policy;
char strpolicy[10];
//sched_get_priority_max(SCHED_FIFO)
if (priority < NICE_MIN)
{
policy=SCHED_FIFO;
sprintf(strpolicy,"%s","fifo");
schedp.sched_priority= NICE_MIN - priority ;
}
else if (priority > NICE_MAX)
{
policy=SCHED_IDLE;
sprintf(strpolicy,"%s","idle");
schedp.sched_priority=0;
}
else
{
policy=SCHED_OTHER;
sprintf(strpolicy,"%s","other");
schedp.sched_priority=0;
}
if( tid != 0)
{
rt = pthread_setschedparam(tid, policy, &schedp);
}
else if(pid > 0)
{
rt = sched_setscheduler( pid, policy,&schedp);
}
if (rt != 0)
{
client_printf("Error %i: %s modifying sched param to %s:%i, \n",
errno,strerror(errno),strpolicy,schedp.sched_priority);
}
else
{
client_printf("policy set to %s, priority %i\n",strpolicy,schedp.sched_priority);
}
if ( policy == SCHED_OTHER)
{
if ( tid > 0 && tid != pthread_self())
{
client_printf("setting nice value using a thread id not implemented....\n");
}
else if (pid > 0)
{
errno=0;
rt = setpriority(PRIO_PROCESS,pid,priority);
if (rt != 0)
{
client_printf("Error %i: %s calling setpriority, \n",errno,strerror(errno));
}
else
{
client_printf("nice value set to %i\n",priority);
}
}
}
}
void set_affinity(pthread_t tid, int pid, int coreid)
{
cpu_set_t cpuset;
int rt;
CPU_ZERO(&cpuset);
CPU_SET(coreid, &cpuset);
if (tid > 0)
{
rt = pthread_setaffinity_np((pthread_t)tid, sizeof(cpu_set_t), &cpuset);
}
else if (pid > 0)
{
rt = sched_setaffinity((pid_t)pid, sizeof(cpu_set_t), &cpuset);
}
if (rt != 0)
{
client_printf("Error %i: %s calling , xxx_setaffinity...\n",errno,strerror(errno));
}
else
{
client_printf("thread %i affinity set to %i\n",(pid==0)?(int)tid:pid,coreid);
}
}
/*------------------------------------------------------------------------------------*/
/*
function implementing telnet server specific commands, parameters of the
telnet_cmdarray table
*/
void redirstd(char *newfname,telnet_printfunc_t prnt )
{
FILE *fd;
fd=freopen(newfname, "w", stdout);
if (fd == NULL)
{
prnt("ERROR: stdout redir to %s error %s",strerror(errno));
}
fd=freopen(newfname, "w", stderr);
if (fd == NULL)
{
prnt("ERROR: stderr redir to %s error %s",strerror(errno));
}
}
int setoutput(char *buff, int debug, telnet_printfunc_t prnt)
{
char cmds[TELNET_MAX_MSGLENGTH/TELNET_CMD_MAXSIZE][TELNET_CMD_MAXSIZE];
char *logfname;
char stdout_str[64];
#define LOGFILE "logfile.log"
memset(cmds,0,sizeof(cmds));
sscanf(buff,"%9s %32s %9s %9s %9s", cmds[0],cmds[1],cmds[2],cmds[3],cmds[4] );
if (strncasecmp(cmds[0],"here",4) == 0)
{
fflush(stdout);
sprintf(stdout_str,"/proc/%i/fd/%i",getpid(),telnetparams.new_socket);
dup2(telnetparams.new_socket,fileno(stdout));
// freopen(stdout_str, "w", stdout);
// freopen(stdout_str, "w", stderr);
dup2(telnetparams.new_socket,fileno(stderr));
prnt("Log output redirected to this terminal (%s)\n",stdout_str);
}
if (strncasecmp(cmds[0],"file",4) == 0)
{
if (cmds[1][0] == 0)
logfname=LOGFILE;
else
logfname=cmds[1];
fflush(stdout);
redirstd(logfname,prnt);
}
if (strncasecmp(cmds[0],"off",3) == 0)
{
fflush(stdout);
redirstd("/dev/tty",prnt);
}
return CMDSTATUS_FOUND;
} /* setoutput */
int setparam(char *buff, int debug, telnet_printfunc_t prnt)
{
char cmds[TELNET_MAX_MSGLENGTH/TELNET_CMD_MAXSIZE][TELNET_CMD_MAXSIZE];
memset(cmds,0,sizeof(cmds));
sscanf(buff,"%9s %9s %9s %9s %9s", cmds[0],cmds[1],cmds[2],cmds[3],cmds[4] );
if (strncasecmp(cmds[0],"prio",4) == 0)
{
pthread_attr_t attr;
int prio;
prio=(int)strtol(cmds[1],NULL,0);
if (errno == ERANGE)
return CMDSTATUS_VARNOTFOUND;
telnetparams.priority = prio;
set_sched(pthread_self(),0,prio);
return CMDSTATUS_FOUND;
}
if (strncasecmp(cmds[0],"aff",3) == 0)
{
int aff;
aff=(int)strtol(cmds[1],NULL,0);
if (errno == ERANGE)
return CMDSTATUS_VARNOTFOUND;
set_affinity(pthread_self(),0,aff);
return CMDSTATUS_FOUND;
}
return CMDSTATUS_NOTFOUND;
} /* setparam */
/*-------------------------------------------------------------------------------------------------------*/
/*
generic commands available for all modules loaded by the server
*/
int setgetvar(int moduleindex,char getorset,char *params)
{
int n,i;
char varname[TELNET_CMD_MAXSIZE];
char varval[TELNET_CMD_MAXSIZE];
memset(varname,0,sizeof(varname));
memset(varval,0,sizeof(varval));
n = sscanf(params,"%s %s",varname,varval);
for ( i=0 ; telnetparams.CmdParsers[moduleindex].var[i].varvalptr != NULL ; i++)
{
if ( strncasecmp(telnetparams.CmdParsers[moduleindex].var[i].varname,varname,strlen(telnetparams.CmdParsers[moduleindex].var[i].varname)) == 0)
{
if (n > 0 && (getorset == 'g' || getorset == 'G'))
{
client_printf("%s, %s = ", telnetparams.CmdParsers[moduleindex].module,
telnetparams.CmdParsers[moduleindex].var[i].varname );
switch(telnetparams.CmdParsers[moduleindex].var[i].vartype)
{
case TELNET_VARTYPE_INT32:
client_printf("%i\n",*(int *)(telnetparams.CmdParsers[moduleindex].var[i].varvalptr));
break;
case TELNET_VARTYPE_INT16:
client_printf("%hi\n",*(short *)(telnetparams.CmdParsers[moduleindex].var[i].varvalptr));
break;
case TELNET_VARTYPE_DOUBLE:
client_printf("%g\n",*(double *)(telnetparams.CmdParsers[moduleindex].var[i].varvalptr));
break;
case TELNET_VARTYPE_PTR:
client_printf("0x%08x\n",*((unsigned int *)(telnetparams.CmdParsers[moduleindex].var[i].varvalptr)));
break;
default:
client_printf("unknown type\n");
break;
}
}
if (n > 1 && (getorset == 's' || getorset == 'S'))
{
client_printf("%s, %s set to \n", telnetparams.CmdParsers[moduleindex].module,
telnetparams.CmdParsers[moduleindex].var[i].varname);
switch(telnetparams.CmdParsers[moduleindex].var[i].vartype)
{
case TELNET_VARTYPE_INT32:
*(int *)(telnetparams.CmdParsers[moduleindex].var[i].varvalptr) = (int)strtol(varval,NULL,0);
client_printf("%i\n",*(int *)(telnetparams.CmdParsers[moduleindex].var[i].varvalptr));
break;
case TELNET_VARTYPE_INT16:
*(short *)(telnetparams.CmdParsers[moduleindex].var[i].varvalptr) = (short)strtol(varval,NULL,0);
client_printf("%hi\n",*(short *)(telnetparams.CmdParsers[moduleindex].var[i].varvalptr));
break;
case TELNET_VARTYPE_DOUBLE:
*(double *)(telnetparams.CmdParsers[moduleindex].var[i].varvalptr) = strtod(varval,NULL);
client_printf("%g\n",*(double *)(telnetparams.CmdParsers[moduleindex].var[i].varvalptr));
break;
default:
client_printf("unknown type\n");
break;
}
}
}
}
return CMDSTATUS_VARNOTFOUND;
}
/*----------------------------------------------------------------------------------------------------*/
char *get_time(char *buff,int bufflen)
{
struct tm tmstruct;
time_t now = time (0);
strftime (buff, bufflen, "%Y-%m-%d %H:%M:%S.000", localtime_r(&now,&tmstruct));
return buff;
}
int process_command(char *buf)
{
int i,j,k;
char modulename[TELNET_CMD_MAXSIZE];
char cmd[TELNET_CMD_MAXSIZE];
char cmdb[TELNET_MAX_MSGLENGTH];
char *bufbck;
int rt;
memset(modulename,0,sizeof(modulename));
memset(cmd,0,sizeof(cmd));
memset(cmdb,0,sizeof(cmdb));
if (strncasecmp(buf,"ex",2) == 0)
return CMDSTATUS_EXIT;
if (strncasecmp(buf,"help",4) == 0)
{
for (i=0; telnetparams.CmdParsers[i].var != NULL && telnetparams.CmdParsers[i].cmd != NULL; i++)
{
client_printf(" module %i = %s:\n",i,telnetparams.CmdParsers[i].module);
for(j=0; telnetparams.CmdParsers[i].var[j].varvalptr != NULL ; j++)
{
client_printf(" %s [get set] %s <value>\n",
telnetparams.CmdParsers[i].module, telnetparams.CmdParsers[i].var[j].varname);
}
for(j=0; telnetparams.CmdParsers[i].cmd[j].cmdfunc != NULL ; j++)
{
client_printf(" %s %s %s\n",
telnetparams.CmdParsers[i].module,telnetparams.CmdParsers[i].cmd[j].cmdname,
telnetparams.CmdParsers[i].cmd[j].helpstr);
}
}
return CMDSTATUS_FOUND;
}
memset(modulename,0,sizeof(modulename));
memset(cmd,0,sizeof(cmd));
memset(cmdb,0,sizeof(cmdb));
bufbck=strdup(buf);
rt=CMDSTATUS_NOTFOUND;
j = sscanf(buf,"%9s %9s %[^\t\n]",modulename,cmd,cmdb);
if (telnetparams.telnetdbg > 0)
printf("process_command: %i words, module=%s cmd=%s, parameters= %s\n",j,modulename,cmd,cmdb);
for (i=0; j>=2 && telnetparams.CmdParsers[i].var != NULL && telnetparams.CmdParsers[i].cmd != NULL; i++)
{
if ( (strncasecmp(telnetparams.CmdParsers[i].module,modulename,strlen(telnetparams.CmdParsers[i].module)) == 0))
{
if (strncasecmp(cmd,"getall",7) == 0 )
{
for(j=0; telnetparams.CmdParsers[i].var[j].varvalptr != NULL ; j++)
{
setgetvar(i,'g',telnetparams.CmdParsers[i].var[j].varname);
}
rt= CMDSTATUS_FOUND;
}
else if (strncasecmp(cmd,"get",3) == 0 || strncasecmp(cmd,"set",3) == 0)
{
rt= setgetvar(i,cmd[0],cmdb);
}
else
{
for (k=0 ; telnetparams.CmdParsers[i].cmd[k].cmdfunc != NULL ; k++)
{
if (strncasecmp(cmd, telnetparams.CmdParsers[i].cmd[k].cmdname,sizeof(telnetparams.CmdParsers[i].cmd[k].cmdname)) == 0)
{
telnetparams.CmdParsers[i].cmd[k].cmdfunc(cmdb, telnetparams.telnetdbg, client_printf);
rt= CMDSTATUS_FOUND;
}
} /* for k */
}/* else */
}/* strncmp: module name test */
else if (strncasecmp(modulename,"loop",4) == 0 )
{
int lc;
int f = fcntl(telnetparams.new_socket,F_GETFL);
fcntl (telnetparams.new_socket, F_SETFL, O_NONBLOCK | f);
for(lc=0; lc<telnetparams.loopcount; lc++)
{
char dummybuff[20];
char tbuff[64];
int rs;
client_printf(CSI "1J" CSI "1;10H " STDFMT "%s %i/%i\n",
get_time(tbuff,sizeof(tbuff)),lc,telnetparams.loopcount );
process_command(bufbck+strlen("loop")+1);
usleep(telnetparams.loopdelay * 1000);
rs = read(telnetparams.new_socket,dummybuff,sizeof(dummybuff));
if ( rs > 0 )
{
break;
}
}
fcntl (telnetparams.new_socket, F_SETFL, f);
rt= CMDSTATUS_FOUND;
} /* loop */
} /* for i */
free(bufbck);
return rt;
}
void run_telnetsrv(void)
{
int sock;
struct sockaddr_in name;
char buf[TELNET_MAX_MSGLENGTH];
struct sockaddr cli_addr;
unsigned int cli_len = sizeof(cli_addr);
int readc , filled;
int status;
int optval = 1;
pthread_setname_np(pthread_self(), "telnet");
set_sched(pthread_self(),0,telnetparams.priority);
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0)
fprintf(stderr,"[TELNETSRV] Error %s on socket call\n",strerror(errno));
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof optval);
name.sin_family = AF_INET;
if (telnetparams.listenaddr == 0)
name.sin_addr.s_addr = INADDR_ANY;
else
name.sin_addr.s_addr = telnetparams.listenaddr;
name.sin_port = htons((unsigned short)(telnetparams.listenport));
if(bind(sock, (void*) &name, sizeof(name)))
fprintf(stderr,"[TELNETSRV] Error %s on bind call\n",strerror(errno));
if(listen(sock, 1) == -1)
fprintf(stderr,"[TELNETSRV] Error %s on listen call\n",strerror(errno));
printf("\nInitializing telnet server...\n");
while( (telnetparams.new_socket = accept(sock, &cli_addr, &cli_len)) )
{
printf("[TELNETSRV] Telnet client connected....\n");
if(telnetparams.new_socket < 0)
fprintf(stderr,"[TELNETSRV] Error %s on accept call\n",strerror(errno));
while(telnetparams.new_socket>0)
{
filled = 0;
memset(buf,0,sizeof(buf));
while(filled < ( TELNET_MAX_MSGLENGTH-1))
{
readc = recv(telnetparams.new_socket, buf+filled, TELNET_MAX_MSGLENGTH-filled-1, 0);
if(!readc)
break;
filled += readc;
if(buf[filled-1] == '\n')
{
buf[filled-1] = 0;
break;
}
}
if(!readc)
{
printf ("[TELNETSRV] Telnet Client disconnected.\n");
break;
}
if (telnetparams.telnetdbg > 0)
printf("[TELNETSRV] Command received: readc %i filled %i %s\n", readc, filled ,buf);
if (strlen(buf) >= 2 )
{
status=process_command(buf);
}
else
status=CMDSTATUS_NOCMD;
if (status != CMDSTATUS_EXIT)
{
if (status == CMDSTATUS_NOTFOUND)
{
char msg[TELNET_MAX_MSGLENGTH + 50];
sprintf(msg,"Error: \n %s\n is not a softmodem command\n",buf);
send(telnetparams.new_socket, msg, strlen(msg), MSG_NOSIGNAL);
}
send(telnetparams.new_socket, TELNET_PROMPT, sizeof(TELNET_PROMPT), MSG_NOSIGNAL);
}
else
{
printf ("[TELNETSRV] Closing telnet connection...\n");
break;
}
}
close(telnetparams.new_socket);
printf ("[TELNETSRV] Telnet server waitting for connection...\n");
}
close(sock);
return;
}
/*------------------------------------------------------------------------------------------------*/
/* set_telnetmodule loads the commands delivered with the telnet server
*
*
*
*/
void exec_moduleinit(char *modname)
{
void (*fptr)();
char initfunc[TELNET_CMD_MAXSIZE+9];
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;
}
sprintf(initfunc,"add_%s_cmds",modname);
fptr = dlsym(RTLD_DEFAULT,initfunc);
if ( fptr != NULL)
{
fptr();
}
else
{
fprintf(stderr,"[TELNETSRV] couldn't find %s for module %s \n",initfunc,modname);
}
}
int add_embeddedmodules()
{
for(int i=0; i<telnetoptions[TELNETSRV_STATICMOD].numelt;i++)
{
exec_moduleinit(telnetoptions[TELNETSRV_STATICMOD].strlistptr[i]);
}
}
int add_sharedmodules()
{
char initfunc[TELNET_CMD_MAXSIZE+9];
void (*fptr)();
for(int i=0; i<telnetoptions[TELNETSRV_SHRMOD].numelt;i++)
{
sprintf(initfunc,"add_%s_cmds",telnetoptions[TELNETSRV_SHRMOD].strlistptr[i]);
fptr = dlsym(RTLD_DEFAULT,initfunc);
if ( fptr != NULL)
{
fptr();
}
else
{
fprintf(stderr,"[TELNETSRV] couldn't find %s for module %s \n",initfunc,telnetoptions[TELNETSRV_STATICMOD].strlistptr[i]);
}
}
}
int init_telnetsrv(char *cfgfile)
{
void *lib_handle;
char** moduleslist;
memset(&telnetparams,0,sizeof(telnetparams));
config_get( telnetoptions,sizeof(telnetoptions)/sizeof(paramdef_t),NULL);
if(pthread_create(&telnetparams.telnet_pthread,NULL, (void *(*)(void *))run_telnetsrv, NULL) != 0)
{
fprintf(stderr,"[TELNETSRV] Error %s on pthread_create call\n",strerror(errno));
return -1;
}
add_telnetcmd("telnet", telnet_vardef, telnet_cmdarray);
add_embeddedmodules();
return 0;
}
/*---------------------------------------------------------------------------------------------*/
/* add_telnetcmd is used to add a set of commands to the telnet server. A module calls this
* function at init time. the telnet server is delivered with a set of commands which
* will be loaded or not depending on the telnet section of the config file
*/
int add_telnetcmd(char *modulename, telnetshell_vardef_t *var, telnetshell_cmddef_t *cmd)
{
int i;
if( modulename == NULL || var == NULL || cmd == NULL)
{
fprintf(stderr,"[TELNETSRV] Telnet server, add_telnetcmd: invalid parameters\n");
return -1;
}
for (i=0; i<TELNET_MAXCMD ; i++)
{
if (telnetparams.CmdParsers[i].var == NULL)
{
strncpy(telnetparams.CmdParsers[i].module,modulename,sizeof(telnetparams.CmdParsers[i].module)-1);
telnetparams.CmdParsers[i].cmd = cmd;
telnetparams.CmdParsers[i].var = var;
printf("[TELNETSRV] Telnet server: module %i = %s added to shell\n",
i,telnetparams.CmdParsers[i].module);
break;
}
}
return 0;
}
+108
View File
@@ -0,0 +1,108 @@
#ifndef TELNETSRV_H
#define TELNETSRV_H
#define TELNETSRV_MODNAME "telnetsrv"
#define TELNET_PORT 9090
#define TELNET_MAX_MSGLENGTH 2048
#define TELNET_PROMPT "softmodem> "
#define TELNET_MAXCMD 20
#define TELNET_CMD_MAXSIZE 10
#define TELNET_HELPSTR_SIZE 80
/* status return by the command parser after it analysed user input */
#define CMDSTATUS_NOCMD 0
#define CMDSTATUS_EXIT 1
#define CMDSTATUS_FOUND 2
#define CMDSTATUS_VARNOTFOUND 3
#define CMDSTATUS_NOTFOUND 4
/*----------------------------------------------------------------------------*/
/* structure to be used when adding a module to the telnet server */
/* This is the second parameter of the add_telnetcmd function, which can be used */
/* to add a set of new command to the telnet server shell */
typedef void(*telnet_printfunc_t)(const char* format, ...);
typedef int(*cmdfunc_t)(char*, int, telnet_printfunc_t prnt);
typedef struct cmddef {
char cmdname[TELNET_CMD_MAXSIZE];
char helpstr[TELNET_HELPSTR_SIZE];
cmdfunc_t cmdfunc;
} telnetshell_cmddef_t;
/*----------------------------------------------------------------------------*/
/*structure to be used when adding a module to the telnet server */
/* This is the first parameter of the add_telnetcmd function, which can be used */
/* to add a set of new variables which can be got/set from the telnet server shell */
#define TELNET_VARTYPE_INT32 1
#define TELNET_VARTYPE_INT16 2
#define TELNET_VARTYPE_INT64 3
#define TELNET_VARTYPE_STRING 4
#define TELNET_VARTYPE_DOUBLE 5
#define TELNET_VARTYPE_PTR 6
typedef struct variabledef {
char varname[TELNET_CMD_MAXSIZE];
char vartype;
void *varvalptr;
} telnetshell_vardef_t;
/*----------------------------------------------------------------------------*/
/* internal structure definitions */
/* cmdparser_t is used to store all modules which have been added to the telnet server. */
/* Each time the add_telnetcmd function is used, the internal array cmdparser_t[] of the */
/* telnet server is populated with the new commands and variables */
typedef struct cmdparser {
char module[TELNET_CMD_MAXSIZE]; // module name = first token of the telnet shell command
telnetshell_cmddef_t *cmd; // array of functions added to the shell
telnetshell_vardef_t *var; // array of variables added to the shell
} cmdparser_t;
/* telnetsrv_params_t is an internal structure storing all the current parameters and */
/* global variables used by the telnet server */
typedef struct {
pthread_t telnet_pthread; // thread id of the telnet server
int telnetdbg; // debug level of the server
int priority; // server running priority
int new_socket; // socket of the client connection
int logfilefd; // file id of the log file when log output is redirected to a file
int saved_stdout; // file id of the previous stdout, used to be able to restore original stdout
cmdparser_t CmdParsers[TELNET_MAXCMD]; // array of registered modules.
char msgbuff[TELNET_MAX_MSGLENGTH]; // internal buffer of the client_printf function which is used to print to the client terminal */
unsigned int listenport; // ip port the telnet server is listening on
unsigned int listenaddr; // ip address the telnet server is listening on
unsigned int loopcount; // loop command param: number of loop iteration
unsigned int loopdelay; // loop command param: delay in ms between 2 iterations
unsigned int phyprntbuff_size; // for phy module, dump_eNB_stats function buffer size
} telnetsrv_params_t;
typedef int(*addcmdfunc_t)(char*, telnetshell_vardef_t*, telnetshell_cmddef_t*);
typedef void(*settelnetmodule_t)(char *name, void *ptr);
/*-------------------------------------------------------------------------------------------*/
/*
VT escape sequence definition, for smarter display....
*/
#define ESC "\x1b"
#define CSI "\x1b["
#define BOLD "\x1b[1m"
#define RED "\x1b[31m"
#define GREEN "\x1b[32m"
#define BLUE "\x1b[34m"
#define MAGENTA "\x1b[35m"
#define CYAN "\x1b[36m"
#define STDFMT "\x1b[0m"
/*---------------------------------------------------------------------------------------------*/
#ifdef TELNETSERVERCODE
int add_telnetcmd(char *modulename, telnetshell_vardef_t *var, telnetshell_cmddef_t *cmd);
void set_sched(pthread_t tid, int pid,int priority);
void set_affinity(pthread_t tid, int pid, int coreid);
extern int get_phybsize();
#endif
#endif
+111
View File
@@ -0,0 +1,111 @@
#define _GNU_SOURCE
#include <string.h>
#include <pthread.h>
#define TELNETSERVERCODE
#include "telnetsrv.h"
#define TELNETSRV_PHYCMD_MAIN
#include "telnetsrv_phycmd.h"
char *prnbuff;
extern int dump_eNB_stats(PHY_VARS_eNB *eNB, char* buffer, int length);
void init_phytelnet()
{
prnbuff=malloc(get_phybsize() );
if (prnbuff == NULL)
{
fprintf(stderr,"Error %s on malloc in init_phytelnet()\n",strerror(errno));
}
}
void display_uestatshead( telnet_printfunc_t prnt)
{
prnt("cc ue rnti Dmcs Umcs tao tau Dbr Dtb \n");
}
void dump_uestats(int debug, telnet_printfunc_t prnt, uint8_t prntflag)
{
int p;
p=dump_eNB_l2_stats( prnbuff, 0);
if(prntflag>=1)
prnt("%s\n",prnbuff);
if(debug>=1)
prnt("%i bytes printed\n",p);
}
void display_uestats(int debug, telnet_printfunc_t prnt, int ue)
{
for (int cc=0; cc<1 ; cc++)
{
}
}
void display_phycounters(char *buf, int debug, telnet_printfunc_t prnt)
{
prnt(" DLSCH kb DLSCH kb/s\n");
dump_uestats(debug, prnt,0);
}
int dump_phyvars(char *buf, int debug, telnet_printfunc_t prnt)
{
if (debug > 0)
prnt("phy interface module received %s\n",buf);
if (strcasestr(buf,"phycnt") != NULL)
{
display_phycounters(buf, debug, prnt);
}
if (strcasestr(buf,"uestat") != NULL)
{
char *cptr=strcasestr(buf+sizeof("uestat"),"UE");
display_uestatshead(prnt);
if (cptr != NULL)
{
int ueidx = strtol( cptr+sizeof("UE"), NULL, 10);
if (ueidx < NUMBER_OF_UE_MAX && ueidx >= 0)
{
display_uestats(debug, prnt,ueidx);
}
} /* if cptr != NULL */
else
{
for (int ue=0; ue<NUMBER_OF_UE_MAX ; ue++)
{
display_uestats(debug, prnt,ue);
}
} /* else cptr != NULL */
} /* uestat */
if (strcasestr(buf,"uedump") != NULL)
{
dump_uestats(debug, prnt,1);
}
return 0;
}
telnetshell_cmddef_t phy_cmdarray[] = {
{"disp","[phycnt,uedump,uestat UE<x>]", dump_phyvars},
{"","",NULL},
};
/*-------------------------------------------------------------------------------------*/
void add_phy_cmds()
{
init_phytelnet();
add_telnetcmd("phy", phy_vardef, phy_cmdarray);
}
+35
View File
@@ -0,0 +1,35 @@
#ifdef TELNETSRV_PHYCMD_MAIN
#include "UTIL/LOG/log.h"
#include "openair1/PHY/extern.h"
#define TELNETVAR_PHYCC0 0
#define TELNETVAR_PHYCC1 1
telnetshell_vardef_t phy_vardef[] = {
{"phycc1",TELNET_VARTYPE_PTR,NULL},
{"phycc2",TELNET_VARTYPE_PTR,NULL},
//{"iqmax",TELNET_VARTYPE_INT16,NULL},
//{"iqmin",TELNET_VARTYPE_INT16,NULL},
//{"loglvl",TELNET_VARTYPE_INT32,NULL},
//{"sndslp",TELNET_VARTYPE_INT32,NULL},
//{"rxrescale",TELNET_VARTYPE_INT32,NULL},
//{"txshift",TELNET_VARTYPE_INT32,NULL},
//{"rachemin",TELNET_VARTYPE_INT32,NULL},
//{"rachdmax",TELNET_VARTYPE_INT32,NULL},
{"",0,NULL}
};
#else
extern void add_phy_cmds();
#endif
/*-------------------------------------------------------------------------------------*/
+230
View File
@@ -0,0 +1,230 @@
#define _GNU_SOURCE
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <pthread.h>
#include <string.h>
#include <stdarg.h>
#include <dirent.h>
#define READCFG_DYNLOAD
#define TELNETSERVERCODE
#include "telnetsrv.h"
#define TELNETSRV_PROCCMD_MAIN
#include "log.h"
#include "telnetsrv_proccmd.h"
void decode_procstat(char *record, int debug, telnet_printfunc_t prnt)
{
char prntline[160];
char *procfile_fiels;
char *strtokptr;
char *lptr;
int fieldcnt;
char toksep[2];
fieldcnt=0;
procfile_fiels =strtok_r(record," ",&strtokptr);
lptr= prntline;
/*http://man7.org/linux/man-pages/man5/proc.5.html gives the structure of the stat file */
while( procfile_fiels != NULL && fieldcnt < 42)
{
if (strlen(procfile_fiels) == 0)
continue;
fieldcnt++;
sprintf(toksep," ");
switch(fieldcnt)
{
case 1: /* id */
lptr+=sprintf(lptr,"%9.9s ",procfile_fiels);
sprintf(toksep,")");
break;
case 2: /* name */
lptr+=sprintf(lptr,"%20.20s ",procfile_fiels+1);
break;
case 3: //thread state
lptr+=sprintf(lptr," %c ",procfile_fiels[0]);
break;
case 14: //time in user mode
case 15: //time in kernel mode
lptr+=sprintf(lptr,"%9.9s ",procfile_fiels);
break;
case 18: //priority
case 19: //nice
lptr+=sprintf(lptr,"%3.3s ",procfile_fiels);
break;
case 23: //vsize
lptr+=sprintf(lptr,"%9.9s ",procfile_fiels);
break;
case 39: //processor
lptr+=sprintf(lptr," %2.2s ",procfile_fiels);
break;
case 41: //policy
lptr+=sprintf(lptr,"%3.3s ",procfile_fiels);
break;
default:
break;
}/* switch on fieldcnr */
procfile_fiels =strtok_r(NULL,toksep,&strtokptr);
} /* while on proc_fields != NULL */
prnt("%s\n",prntline);
} /*decode_procstat */
void read_statfile(char *fname,int debug, telnet_printfunc_t prnt)
{
FILE *procfile;
char arecord[1024];
procfile=fopen(fname,"r");
if (procfile == NULL)
{
prnt("Error: Couldn't open %s %i %s\n",fname,errno,strerror(errno));
return;
}
if ( fgets(arecord,sizeof(arecord),procfile) == NULL)
{
prnt("Error: Nothing read from %s %i %s\n",fname,errno,strerror(errno));
fclose(procfile);
return;
}
fclose(procfile);
decode_procstat(arecord, debug, prnt);
}
void print_threads(char *buf, int debug, telnet_printfunc_t prnt)
{
char aname[256];
DIR *proc_dir;
struct dirent *entry;
int rt;
prnt(" id name state USRmod KRNmod prio nice vsize proc pol \n\n");
snprintf(aname, sizeof(aname), "/proc/%d/stat", getpid());
read_statfile(aname,debug,prnt);
prnt("\n");
snprintf(aname, sizeof(aname), "/proc/%d/task", getpid());
proc_dir = opendir(aname);
if (proc_dir == NULL)
{
prnt("Error: Couldn't open %s %i %s\n",aname,errno,strerror(errno));
return;
}
while ((entry = readdir(proc_dir)) != NULL)
{
if(entry->d_name[0] == '.')
continue;
snprintf(aname, sizeof(aname), "/proc/%d/task/%s/stat", getpid(),entry->d_name);
read_statfile(aname,debug,prnt);
} /* while entry != NULL */
closedir(proc_dir);
} /* print_threads */
int proccmd_show(char *buf, int debug, telnet_printfunc_t prnt)
{
extern log_t *g_log;
if (debug > 0)
prnt(" proccmd_show received %s\n",buf);
if (strcasestr(buf,"thread") != NULL)
{
print_threads(buf,debug,prnt);
}
if (strcasestr(buf,"loglvl") != NULL) {
for (int i=MIN_LOG_COMPONENTS; i < MAX_LOG_COMPONENTS; i++){
prnt("\t%s:\t%s\t%s\n",g_log->log_component[i].name, map_int_to_str(log_verbosity_names,g_log->log_component[i].flag),
map_int_to_str(log_level_names,g_log->log_component[i].level));
}
}
return 0;
}
int proccmd_thread(char *buf, int debug, telnet_printfunc_t prnt)
{
int bv1,bv2;
int res;
char sv1[64];
char tname[32];
bv1=0;
bv2=0;
sv1[0]=0;
if (debug > 0)
prnt("proccmd_thread received %s\n",buf);
res=sscanf(buf,"%i %9s %i",&bv1,sv1,&bv2);
if (debug > 0)
prnt(" proccmd_thread: %i params = %i,%s,%i\n",res,bv1,sv1,bv2);
if(res != 3)
{
prnt("softmodem thread needs 3 params, %i received\n",res);
return 0;
}
if (strcasestr(sv1,"prio") != NULL)
{
set_sched(0,bv1, bv2);
}
else if (strcasestr(sv1,"aff") != NULL)
{
set_affinity(0,bv1, bv2);
}
else
{
prnt("%s is not a valid thread command\n",sv1);
}
return 0;
}
int proccmd_exit(char *buf, int debug, telnet_printfunc_t prnt)
{
extern void exit_fun(const char* s);
if (debug > 0)
prnt("process module received %s\n",buf);
exit_fun("telnet server received exit command\n");
return 0;
}
int proccmd_log(char *buf, int debug, telnet_printfunc_t prnt)
{
int idx1=0;
int idx2=NUM_LOG_LEVEL-1;
int s = sscanf(buf,"%*s %i-%i",&idx1,&idx2);
if (debug > 0)
prnt("process module received %s\n",buf);
if (strcasestr(buf,"enable") != NULL)
{
set_glog_onlinelog(1);
}
if (strcasestr(buf,"disable") != NULL)
{
set_glog_onlinelog(0);
}
if (strcasestr(buf,"show") != NULL)
{
proccmd_show("loglvl",debug,prnt);
}
return 0;
}
/*-------------------------------------------------------------------------------------*/
void add_softmodem_cmds()
{
add_telnetcmd("softmodem",proc_vardef,proc_cmdarray);
}
@@ -0,0 +1,59 @@
/*
* 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.0 (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_proccmd.h
* \brief: Include file defining telnet commands related to this linux process
* \author Francois TABURET
* \date 2017
* \version 0.1
* \company NOKIA BellLabs France
* \email: francois.taburet@nokia-bell-labs.com
* \note
* \warning
*/
#include <dlfcn.h>
#include "telnetsrv.h"
#ifdef TELNETSRV_PROCCMD_MAIN
/* global variable from log.c */
extern mapping *log_level_names;
extern mapping *log_verbosity_names;
extern int proccmd_show(char *buf, int debug, telnet_printfunc_t prnt);
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}
};
telnetshell_cmddef_t proc_cmdarray[] = {
{"show","loglvl|thread", proccmd_show},
{"log","[enable,disable]", proccmd_log},
{"thread","<id> aff|prio <aff|prio>", proccmd_thread},
{"exit","", proccmd_exit},
{"","",NULL},
};
#else
extern void add_proccmd_cmds();
#endif /* TELNETSRV_PROCCMD_MAIN */