Merge remote-tracking branch 'origin/develop' into develop-nr

Conflicts:
	ci-scripts/Jenkinsfile-gitlab
	ci-scripts/buildOnVM.sh
	ci-scripts/checkCodingFormattingRules.sh
	ci-scripts/createVM.sh
	ci-scripts/destroyAllRunningVM.sh
	ci-scripts/reportBuildLocally.sh
	cmake_targets/CMakeLists.txt
	cmake_targets/build_oai
	cmake_targets/tools/build_helper
	common/utils/LOG/log.h
	openair1/PHY/LTE_ESTIMATION/lte_sync_timefreq.c
	openair1/PHY/TOOLS/file_output.c
	openair1/PHY/TOOLS/lte_dfts.c
	openair1/PHY/TOOLS/tools_defs.h
	openair1/PHY/defs_eNB.h
	openair1/PHY/impl_defs_lte.h
	openair1/SCHED_UE/phy_procedures_lte_ue.c
	openair2/COMMON/platform_constants.h
	openair2/COMMON/platform_types.h
	openair2/LAYER2/MAC/eNB_scheduler.c
	openair2/LAYER2/MAC/main.c
	openair2/RRC/LTE/L2_interface.c
	openair2/RRC/LTE/MESSAGES/asn1_msg.c
	openair2/RRC/LTE/MESSAGES/asn1_msg_NB_IoT.c
	openair2/RRC/LTE/rrc_UE.c
	openair2/RRC/LTE/rrc_eNB.c
	openair2/RRC/LTE/rrc_eNB_S1AP.c
	openair2/UTIL/LOG/log.c
	openair3/S1AP/s1ap_common.h
	openair3/S1AP/s1ap_eNB.c
	openair3/S1AP/s1ap_eNB_context_management_procedures.c
	openair3/S1AP/s1ap_eNB_decoder.c
	openair3/S1AP/s1ap_eNB_decoder.h
	openair3/S1AP/s1ap_eNB_handlers.c
	openair3/S1AP/s1ap_eNB_nas_procedures.c
	openair3/S1AP/s1ap_eNB_overload.c
	openair3/S1AP/s1ap_eNB_trace.c
	openair3/TEST/EPC_TEST/play_scenario_decode.c
	openair3/TEST/EPC_TEST/play_scenario_s1ap.c
	openair3/TEST/EPC_TEST/play_scenario_s1ap_compare_ie.c
	targets/COMMON/openairinterface5g_limits.h
	targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf
	targets/RT/USER/lte-ran.c
	targets/RT/USER/lte-ru.c
	targets/RT/USER/lte-ue.c
	targets/SIMU/USER/oaisim_functions.c
This commit is contained in:
Raymond Knopp
2018-08-25 18:20:44 +02:00
686 changed files with 259126 additions and 776966 deletions
+93 -28
View File
@@ -29,18 +29,50 @@
* \note
* \warning
*/
#define _GNU_SOURCE
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#include "config_userapi.h"
void parse_stringlist(paramdef_t *cfgoptions, char *val)
{
char *atoken;
char *tokctx;
char *tmpval=strdup(val);
int numelt=0;
cfgoptions->numelt=0;
atoken=strtok_r(tmpval, ",",&tokctx);
while(atoken != NULL) {
numelt++ ;
atoken=strtok_r(NULL, ",",&tokctx);
}
free(tmpval);
config_check_valptr(cfgoptions,(char **)&(cfgoptions->strlistptr), sizeof(char *) * numelt);
cfgoptions->numelt=numelt;
atoken=strtok_r(val, ",",&tokctx);
for( int i=0; i<cfgoptions->numelt && atoken != NULL ; i++) {
config_check_valptr(cfgoptions,&(cfgoptions->strlistptr[i]),strlen(atoken)+1);
sprintf(cfgoptions->strlistptr[i],"%s",atoken);
printf_params("[LIBCONFIG] %s[%i]: %s\n", cfgoptions->optname,i,cfgoptions->strlistptr[i]);
atoken=strtok_r(NULL, ",",&tokctx);
}
cfgoptions->numelt=numelt;
}
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);
@@ -63,6 +95,7 @@ char defbool[2]="1";
break;
case TYPE_STRINGLIST:
parse_stringlist(cfgoptions,tmpval);
break;
case TYPE_UINT32:
case TYPE_INT32:
@@ -103,15 +136,15 @@ char defbool[2]="1";
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;
int i,j;
char *pp;
char *cfgpath;
@@ -122,42 +155,74 @@ char *cfgpath;
return -1;
}
j=0;
p++;
c--;
while (c > 0 && *p != NULL) {
if (strcmp(*p, "-h") == 0 || strcmp(*p, "--help") == 0 ) {
config_printhelp(cfgoptions,numoptions);
j = 0;
i = 0;
while (c > 0 ) {
char *oneargv = strdup(config_get_if()->argv[i]); /* we use strtok_r which modifies its string paramater, and we don't want argv to be modified */
/* first check help options, either --help, -h or --help_<section> */
if (strncmp(oneargv, "-h",2) == 0 || strncmp(oneargv, "--help",6) == 0 ) {
char *tokctx;
pp=strtok_r(oneargv, "_",&tokctx);
if (pp == NULL || strcasecmp(pp,config_get_if()->argv[i] ) == 0 ) {
if( prefix == NULL) {
config_printhelp(cfgoptions,numoptions);
if ( ! ( CONFIG_ISFLAGSET(CONFIG_NOEXITONHELP)))
exit_fun("[CONFIG] Exiting after displaying help\n");
}
} else {
pp=strtok_r(NULL, " ",&tokctx);
if ( prefix != NULL && pp != NULL && strncasecmp(prefix,pp,strlen(pp)) == 0 ) {
printf ("Help for %s section:\n",prefix);
config_printhelp(cfgoptions,numoptions);
if ( ! (CONFIG_ISFLAGSET(CONFIG_NOEXITONHELP))) {
fprintf(stderr,"[CONFIG] %s %i section %s:", __FILE__, __LINE__, prefix);
exit_fun(" Exiting after displaying help\n");
}
}
}
}
if (*p[0] == '-') {
for(int i=0;i<numoptions;i++) {
if ( ( cfgoptions[i].paramflags & PARAMFLAG_DISABLECMDLINE) != 0) {
/* now, check for non help options */
if (oneargv[0] == '-') {
for(int n=0;n<numoptions;n++) {
if ( ( cfgoptions[n].paramflags & PARAMFLAG_DISABLECMDLINE) != 0) {
continue;
}
if (prefix != NULL) {
sprintf(cfgpath,"%s.%s",prefix,cfgoptions[i].optname);
sprintf(cfgpath,"%s.%s",prefix,cfgoptions[n].optname);
} else {
sprintf(cfgpath,"%s",cfgoptions[i].optname);
sprintf(cfgpath,"%s",cfgoptions[n].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);
}
if ( ((strlen(oneargv) == 2) && (strcmp(oneargv + 1,cfgpath) == 0)) || /* short option, one "-" */
((strlen(oneargv) > 2) && (strcmp(oneargv + 2,cfgpath ) == 0 )) ) {
char *valptr=NULL;
int ret;
if (c > 0) {
pp = config_get_if()->argv[i+1];
if (pp != NULL ) {
ret = strlen(pp);
if (ret > 0 ) {
if (pp[0] != '-')
valptr=pp;
else if ( ret > 1 && pp[0] == '-' && isdigit(pp[1]) )
valptr=pp;
}
}
}
j += processoption(&(cfgoptions[n]), valptr);
if ( valptr != NULL ) {
i++;
c--;
}
break;
}
} /* for */
} /* if (*p[0] == '-') */
p++;
} /* for n... */
} /* if (oneargv[0] == '-') */
free(oneargv);
i++;
c--;
} /* fin du while */
printf_cmdl("[CONFIG] %s %i options set from command line\n",((prefix == NULL) ? "":prefix),j);
printf_cmdl("[CONFIG] %s %i options set from command line\n",((prefix == NULL) ? "(root)":prefix),j);
free(cfgpath);
return j;
} /* parse_cmdline*/
+104 -20
View File
@@ -97,7 +97,77 @@ int st;
}
/*-----------------------------------------------------------------------------------*/
/* from here: interface implementtion of the configuration module */
int nooptfunc(void) {
return 0;
};
int config_cmdlineonly_getlist(paramlist_def_t *ParamList,
paramdef_t *params, int numparams, char *prefix)
{
ParamList->numelt = 0;
return 0;
}
int config_cmdlineonly_get(paramdef_t *cfgoptions,int numoptions, char *prefix )
{
int defval;
int fatalerror=0;
int numdefvals=0;
for(int i=0;i<numoptions;i++) {
defval=0;
switch(cfgoptions[i].type) {
case TYPE_STRING:
defval=config_setdefault_string(&(cfgoptions[i]), prefix);
break;
case TYPE_STRINGLIST:
defval=config_setdefault_stringlist(&(cfgoptions[i]), prefix);
break;
case TYPE_UINT8:
case TYPE_INT8:
case TYPE_UINT16:
case TYPE_INT16:
case TYPE_UINT32:
case TYPE_INT32:
case TYPE_MASK:
defval=config_setdefault_int(&(cfgoptions[i]), prefix);
break;
case TYPE_UINT64:
case TYPE_INT64:
defval=config_setdefault_int64(&(cfgoptions[i]), prefix);
break;
case TYPE_UINTARRAY:
case TYPE_INTARRAY:
defval=config_setdefault_intlist(&(cfgoptions[i]), prefix);
break;
case TYPE_DOUBLE:
defval=config_setdefault_double(&(cfgoptions[i]), prefix);
break;
case TYPE_IPV4ADDR:
defval=config_setdefault_ipv4addr(&(cfgoptions[i]), prefix);
break;
default:
fprintf(stderr,"[CONFIG] %s.%s type %i not supported\n",prefix, cfgoptions[i].optname,cfgoptions[i].type);
fatalerror=1;
break;
} /* switch on param type */
if (defval == 1) {
numdefvals++;
cfgoptions[i].paramflags = cfgoptions[i].paramflags | PARAMFLAG_PARAMSETDEF;
}
} /* for loop on options */
printf("[CONFIG] %s: %i/%i parameters successfully set \n",
((prefix == NULL)?"(root)":prefix),
numdefvals,numoptions );
if (fatalerror == 1) {
fprintf(stderr,"[CONFIG] fatal errors found when assigning %s parameters \n",
prefix);
}
return numdefvals;
}
configmodule_interface_t *load_configmodule(int argc, char **argv)
{
@@ -110,17 +180,19 @@ 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' ) {
if ( strstr(argv[i], "help_config") != NULL ) {
config_printhelp(Config_Params,CONFIG_PARAMLENGTH(Config_Params));
exit(0);
}
if ( (strcmp(argv[i]+1, "h") == 0) || (strstr(argv[i]+1, "help_") != NULL ) ) {
tmpflags = CONFIG_HELP;
}
}
optind=1;
/* look for the OAI_CONFIGMODULE environement variable */
if ( cfgparam == NULL ) {
@@ -129,21 +201,25 @@ int i;
/* default */
if (cfgparam == NULL) {
tmpflags = tmpflags | CONFIG_NOOOPT;
cfgparam = DEFAULT_CFGMODE ":" DEFAULT_CFGFILENAME;
}
tmpflags = tmpflags | CONFIG_NOOOPT;
if (strstr(argv[0],"uesoftmodem") == NULL) {
cfgparam = CONFIG_LIBCONFIGFILE ":" DEFAULT_CFGFILENAME;
} else {
cfgparam = CONFIG_CMDLINEONLY ":dbgl0" ;
}
}
/* 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(DEFAULT_CFGMODE);
modeparams = strdup(DEFAULT_CFGFILENAME);
exit(-1);
}
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(DEFAULT_CFGMODE);
cfgmode=strdup(CONFIG_LIBCONFIGFILE);
}
cfgptr = malloc(sizeof(configmodule_interface_t));
@@ -153,7 +229,6 @@ int i;
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) {
@@ -176,24 +251,33 @@ int i;
for (i=0;i<cfgptr->num_cfgP; i++) {
printf("%s ",cfgptr->cfgP[i]);
}
printf("\n");
printf(", debug flags: 0x%08x\n",cfgptr->rtflags);
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;
if (strstr(cfgparam,CONFIG_CMDLINEONLY) == NULL) {
i=load_config_sharedlib(cfgptr);
if (i == 0) {
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 );
} else {
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 );
cfgptr->init = (configmodule_initfunc_t)nooptfunc;
cfgptr->get = config_cmdlineonly_get;
cfgptr->getlist = config_cmdlineonly_getlist;
cfgptr->end = (configmodule_endfunc_t)nooptfunc;
}
if (modeparams != NULL) free(modeparams);
if (cfgmode != NULL) free(cfgmode);
if (CONFIG_ISFLAGSET(CONFIG_ABORT)) config_printhelp(Config_Params,CONFIG_PARAMLENGTH(Config_Params));
if (CONFIG_ISFLAGSET(CONFIG_ABORT)) {
config_printhelp(Config_Params,CONFIG_PARAMLENGTH(Config_Params));
// exit(-1);
}
return cfgptr;
}
+15 -13
View File
@@ -41,17 +41,19 @@
#define CONFIG_MAX_ALLOCATEDPTRS 1024 // maximum number of parameters that can be dynamicaly allocated in the config module
/* default values for configuration module parameters */
#define DEFAULT_CFGMODE "libconfig" // use libconfig file
#define DEFAULT_CFGFILENAME "oai.conf" // default config file
#define CONFIG_LIBCONFIGFILE "libconfig" // use libconfig file
#define CONFIG_CMDLINEONLY "cmdline" // use only command line options
#define DEFAULT_CFGFILENAME "oai.conf" // default config file
/* rtflags bit position definitions */
#define CONFIG_PRINTPARAMS 1 // print parameters values while processing
#define CONFIG_DEBUGPTR 1<<1 // print memory allocation/free debug messages
#define CONFIG_DEBUGCMDLINE 1<<2 // print command line processing messages
#define CONFIG_NOABORTONCHKF 1<<3 // disable abort execution when parameter checking function fails
#define CONFIG_HELP 1<<20 // print help message
#define CONFIG_ABORT 1<<21 // config failed,abort execution
#define CONFIG_NOOOPT 1<<22 // no -O option found when parsing command line
#define CONFIG_PRINTPARAMS 1 // print parameters values while processing
#define CONFIG_DEBUGPTR (1<<1) // print memory allocation/free debug messages
#define CONFIG_DEBUGCMDLINE (1<<2) // print command line processing messages
#define CONFIG_NOABORTONCHKF (1<<3) // disable abort execution when parameter checking function fails
#define CONFIG_NOEXITONHELP (1<<19) // do not exit after printing help
#define CONFIG_HELP (1<<20) // print help message
#define CONFIG_ABORT (1<<21) // config failed,abort execution
#define CONFIG_NOOOPT (1<<22) // no -O option found when parsing command line
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);
@@ -75,7 +77,7 @@ typedef struct configmodule_interface
#ifdef CONFIG_LOADCONFIG_MAIN
configmodule_interface_t *cfgptr=NULL;
static char config_helpstr [] = "\n lte-softmodem -O [config mode]<:dbg[debugflags]> \n \
static char config_helpstr [] = "\n lte-softmodem -O [config mode]<:dbgl[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 ";
@@ -97,9 +99,9 @@ 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__ ); }
#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);
+3
View File
@@ -148,7 +148,10 @@ typedef struct paramdef
#define TYPE_MASK 10
#define TYPE_DOUBLE 16
#define TYPE_IPV4ADDR 20
#define TYPE_LASTSCALAR 25
#define PARAM_ISLISTORARRAY(P) (P->type > TYPE_LASTSCALAR )
#define PARAM_ISSCALAR(P) (P->type < TYPE_LASTSCALAR )
#define TYPE_STRINGLIST 50
#define TYPE_INTARRAY 51
+140 -6
View File
@@ -35,6 +35,8 @@
#include <unistd.h>
#include <errno.h>
#include <dlfcn.h>
#include <arpa/inet.h>
#include "config_userapi.h"
extern void exit_fun(const char* s); // lte-softmodem clean exit function
@@ -50,10 +52,30 @@ configmodule_interface_t *config_get_if(void)
char * config_check_valptr(paramdef_t *cfgoptions, char **ptr, int length)
{
if (ptr == NULL ) {
ptr = malloc(sizeof(char *));
if (ptr != NULL) {
*ptr=NULL;
cfgoptions->strptr=ptr;
if ( (cfgoptions->paramflags & PARAMFLAG_NOFREE) == 0) {
config_get_if()->ptrs[config_get_if()->numptrs] = (char *)ptr;
config_get_if()->numptrs++;
}
} else {
fprintf(stderr, "[CONFIG] %s %d option %s, cannot allocate pointer: %s \n",
__FILE__, __LINE__, cfgoptions->optname, strerror(errno));
exit(-1);
}
}
printf_ptrs("[CONFIG] %s ptr: 0x%08lx requested size: %i\n",cfgoptions->optname,(uintptr_t)(ptr),length);
if(cfgoptions->numelt > 0) { /* already allocated */
return *ptr;
if(cfgoptions->numelt > 0 && PARAM_ISSCALAR(cfgoptions) ) { /* already allocated */
if (*ptr != NULL) {
return *ptr;
} else {
fprintf(stderr,"[CONFIG] %s %d option %s, definition error: value pointer is NULL, declared as %i bytes allocated\n",
__FILE__, __LINE__,cfgoptions->optname, cfgoptions->numelt);
exit(-1);
}
}
if (*ptr == NULL) {
@@ -75,7 +97,7 @@ char * config_check_valptr(paramdef_t *cfgoptions, char **ptr, int length)
void config_assign_int(paramdef_t *cfgoptions, char *fullname, int val)
{
int tmpval=val;
if ( ((cfgoptions->paramflags &PARAMFLAG_BOOL) != 0) && tmpval >1) {
if ( ((cfgoptions->paramflags &PARAMFLAG_BOOL) != 0) && tmpval >0) {
tmpval =1;
}
switch (cfgoptions->type) {
@@ -160,7 +182,7 @@ int st=0;
}
}
if (st != 0) {
fprintf(stderr,"[CONFIG] config_execcheck: %i parameters with wrong value\n", -st);
fprintf(stderr,"[CONFIG] config_execcheck: section %s %i parameters with wrong value\n", prefix, -st);
if ( CONFIG_ISFLAGSET(CONFIG_NOABORTONCHKF) == 0) {
exit_fun("exit because configuration failed\n");
}
@@ -173,7 +195,7 @@ 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");
fprintf(stderr,"[CONFIG] config_get, section %s skipped, config module not properly initialized\n",prefix);
return ret;
}
configmodule_interface_t *cfgif = config_get_if();
@@ -283,3 +305,115 @@ int config_checkstr_assign_integer(paramdef_t *param)
return -1;
}
int config_setdefault_string(paramdef_t *cfgoptions, char *prefix)
{
int status = 0;
if( cfgoptions->defstrval != NULL) {
status=1;
if (cfgoptions->numelt == 0 ) {
config_check_valptr(cfgoptions, (char **)(cfgoptions->strptr), sizeof(char *));
config_check_valptr(cfgoptions, cfgoptions->strptr, strlen(cfgoptions->defstrval)+1);
sprintf(*(cfgoptions->strptr), "%s",cfgoptions->defstrval);
printf_params("[CONFIG] %s.%s set to default value \"%s\"\n", ((prefix == NULL) ? "" : prefix), cfgoptions->optname, *(cfgoptions->strptr));
} else {
sprintf((char *)*(cfgoptions->strptr), "%s",cfgoptions->defstrval);
printf_params("[CONFIG] %s.%s set to default value \"%s\"\n", ((prefix == NULL) ? "" : prefix), cfgoptions->optname, (char *)*(cfgoptions->strptr));
}
}
return status;
}
int config_setdefault_stringlist(paramdef_t *cfgoptions, char *prefix)
{
int status = 0;
if( cfgoptions->defstrlistval != NULL) {
cfgoptions->strlistptr=cfgoptions->defstrlistval;
status=1;
for(int j=0; j<cfgoptions->numelt; j++)
printf_params("[CONFIG] %s.%s[%i] set to default value %s\n", ((prefix == NULL) ? "" : prefix), cfgoptions->optname,j, cfgoptions->strlistptr[j]);
}
return status;
}
int config_setdefault_int(paramdef_t *cfgoptions, char *prefix)
{
int status = 0;
config_check_valptr(cfgoptions, (char **)(&(cfgoptions->iptr)),sizeof(int32_t));
if( ((cfgoptions->paramflags & PARAMFLAG_MANDATORY) == 0)) {
config_assign_int(cfgoptions,cfgoptions->optname,cfgoptions->defintval);
status=1;
printf_params("[CONFIG] %s.%s set to default value\n", ((prefix == NULL) ? "" : prefix), cfgoptions->optname);
}
return status;
}
int config_setdefault_int64(paramdef_t *cfgoptions, char *prefix)
{
int status = 0;
config_check_valptr(cfgoptions, (char **)&(cfgoptions->i64ptr),sizeof(long long));
if( ((cfgoptions->paramflags & PARAMFLAG_MANDATORY) == 0)) {
*(cfgoptions->u64ptr)=cfgoptions->defuintval;
status=1;
printf_params("[CONFIG] %s.%s set to default value %llu\n", ((prefix == NULL) ? "" : prefix), cfgoptions->optname, (long long unsigned)(*(cfgoptions->u64ptr)));
}
return status;
}
int config_setdefault_intlist(paramdef_t *cfgoptions, char *prefix)
{
int status = 0;
if( cfgoptions->defintarrayval != NULL) {
config_check_valptr(cfgoptions,(char **)&(cfgoptions->iptr), sizeof(int32_t*));
cfgoptions->iptr=cfgoptions->defintarrayval;
status=1;
for (int j=0; j<cfgoptions->numelt ; j++) {
printf_params("[CONFIG] %s[%i] set to default value %i\n",cfgoptions->optname ,j,(int)cfgoptions->iptr[j]);
}
}
return status;
}
int config_setdefault_double(paramdef_t *cfgoptions, char *prefix)
{
int status = 0;
config_check_valptr(cfgoptions, (char **)&(cfgoptions->dblptr),sizeof(double));
if( ((cfgoptions->paramflags & PARAMFLAG_MANDATORY) == 0)) {
*(cfgoptions->u64ptr)=cfgoptions->defdblval;
status=1;
printf_params("[CONFIG] %s set to default value %lf\n",cfgoptions->optname , *(cfgoptions->dblptr));
}
return status;
}
int config_assign_ipv4addr(paramdef_t *cfgoptions, char *ipv4addr)
{
config_check_valptr(cfgoptions,(char **)&(cfgoptions->uptr), sizeof(int));
int rst=inet_pton(AF_INET, ipv4addr ,cfgoptions->uptr );
if (rst == 1 && *(cfgoptions->uptr) > 0) {
printf_params("[CONFIG] %s: %s\n",cfgoptions->optname, ipv4addr);
return 1;
} else {
if ( strncmp(ipv4addr,ANY_IPV4ADDR_STRING,sizeof(ANY_IPV4ADDR_STRING)) == 0) {
printf_params("[CONFIG] %s:%s (INADDR_ANY) \n",cfgoptions->optname,ipv4addr);
*cfgoptions->uptr=INADDR_ANY;
return 1;
} else {
fprintf(stderr,"[CONFIG] %s not valid for %s \n", ipv4addr, cfgoptions->optname);
return -1;
}
}
return 0;
}
int config_setdefault_ipv4addr(paramdef_t *cfgoptions, char *prefix)
{
int status = 0;
if (cfgoptions->defstrval != NULL) {
status = config_assign_ipv4addr(cfgoptions, cfgoptions->defstrval);
}
return status;
}
+15
View File
@@ -38,10 +38,15 @@
extern "C"
{
#endif
/* get rid of "exit_fun undeclared" warning */
extern void exit_fun(const char* s);
#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))
#define CONFIG_SETRTFLAG(P) if (config_get_if()) { config_get_if()->rtflags |= P; }
#define CONFIG_CLEARRTFLAG(P) if (config_get_if()) { config_get_if()->rtflags &= (~P); }
#define CONFIG_ISPARAMFLAGSET(P,F) ( !!(P.paramflags & F))
/* utility functions, to be used by configuration module and/or configuration libraries */
extern configmodule_interface_t *config_get_if(void);
@@ -50,6 +55,7 @@ extern void config_printhelp(paramdef_t *,int numparams);
extern int config_process_cmdline(paramdef_t *params,int numparams, char *prefix);
extern void config_assign_processedint(paramdef_t *cfgoption, int val);
extern void config_assign_int(paramdef_t *cfgoptions, char *fullname, int val);
extern int config_assign_ipv4addr(paramdef_t *cfgoptions, char *ipv4addr);
/* apis to get parameters, to be used by oai modules, at configuration time */
extern int config_get(paramdef_t *params,int numparams, char *prefix);
@@ -66,6 +72,15 @@ extern int config_check_intrange(paramdef_t *param);
extern int config_check_strval(paramdef_t *param);
extern int config_checkstr_assign_integer(paramdef_t *param);
/* functions to set a parameter to its default value */
extern int config_setdefault_string(paramdef_t *cfgoptions, char *prefix);
extern int config_setdefault_stringlist(paramdef_t *cfgoptions, char *prefix);
extern int config_setdefault_int(paramdef_t *cfgoptions, char *prefix);
extern int config_setdefault_int64(paramdef_t *cfgoptions, char *prefix);
extern int config_setdefault_intlist(paramdef_t *cfgoptions, char *prefix);
extern int config_setdefault_double(paramdef_t *cfgoptions, char *prefix);
extern int config_setdefault_ipv4addr(paramdef_t *cfgoptions, char *prefix);
#define CONFIG_GETCONFFILE (config_get_if()->cfgP[0])
#ifdef __cplusplus
+17 -81
View File
@@ -129,8 +129,6 @@ int config_libconfig_get(paramdef_t *cfgoptions,int numoptions, char *prefix )
switch(cfgoptions[i].type)
{
case TYPE_STRING:
printf("call config_lookup_string for '%s' %p\n", cfgpath, &(libconfig_privdata.cfg)); fflush(stdout);
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",
@@ -138,7 +136,7 @@ printf("call config_lookup_string for '%s' %p\n", cfgpath, &(libconfig_privdata.
str[strlen(str)-1] = 0;
}
if (cfgoptions[i].numelt == 0 ) {
config_check_valptr(&(cfgoptions[i]), (char **)(&(cfgoptions[i].strptr)), sizeof(char *));
// 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) );
@@ -147,21 +145,7 @@ printf("call config_lookup_string for '%s' %p\n", cfgpath, &(libconfig_privdata.
printf_params("[LIBCONFIG] %s: \"%s\"\n", cfgpath,(char *)cfgoptions[i].strptr );
}
} else {
if( cfgoptions[i].defstrval != NULL) {
defval=1;
if (cfgoptions[i].numelt == 0 ) {
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 {
sprintf((char *)*(cfgoptions[i].strptr), "%s",cfgoptions[i].defstrval);
printf_params("[LIBCONFIG] %s set to default value \"%s\"\n", cfgpath, (char *)*(cfgoptions[i].strptr));
}
} else {
notfound=1;
}
defval=config_setdefault_string(&(cfgoptions[i]),prefix);
}
break;
case TYPE_STRINGLIST:
@@ -169,14 +153,7 @@ printf("call config_lookup_string for '%s' %p\n", cfgpath, &(libconfig_privdata.
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;
}
defval=config_setdefault_stringlist(&(cfgoptions[i]),prefix);
}
break;
case TYPE_UINT8:
@@ -186,23 +163,17 @@ printf("call config_lookup_string for '%s' %p\n", cfgpath, &(libconfig_privdata.
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_check_valptr(&(cfgoptions[i]), (char **)(&(cfgoptions[i].iptr)),sizeof(int32_t));
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;
}
defval=config_setdefault_int(&(cfgoptions[i]),prefix);
}
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)) {
config_check_valptr(&(cfgoptions[i]), (char **)&(cfgoptions[i].i64ptr),sizeof(long long));
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)) );
@@ -211,13 +182,7 @@ printf("call config_lookup_string for '%s' %p\n", cfgpath, &(libconfig_privdata.
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;
}
defval=config_setdefault_int64(&(cfgoptions[i]),prefix);
}
break;
case TYPE_UINTARRAY:
@@ -226,57 +191,28 @@ printf("call config_lookup_string for '%s' %p\n", cfgpath, &(libconfig_privdata.
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;
}
defval=config_setdefault_intlist(&(cfgoptions[i]),prefix);
}
break;
case TYPE_DOUBLE:
config_check_valptr(&(cfgoptions[i]), (char **)&(cfgoptions[i].dblptr),sizeof(double));
if ( config_lookup_float(&(libconfig_privdata.cfg),cfgpath, &dbl)) {
config_check_valptr(&(cfgoptions[i]), (char **)&(cfgoptions[i].dblptr),sizeof(double));
*(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;
}
defval=config_setdefault_double(&(cfgoptions[i]),prefix);
}
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;
}
defval=config_setdefault_ipv4addr(&(cfgoptions[i]),prefix);
} else {
rst=config_assign_ipv4addr(cfgoptions, str);
if (rst < 0) {
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 );
+27
View File
@@ -0,0 +1,27 @@
VCD Plugin v0.1
The VCD plugin outputs signals to a .vcd file which is readable by gtkwave (http://en.wikipedia.org/wiki/GTKWave).
Signals may have two types:
- Variables to dump the state of a variable (range 0..2^64 - 1).
- Functions to log function usage (implies two call to VCD API: IN and OUT)
This module is always built in, but is only used when -V oaisim option is added.
The VCD file generated is called openair_vcd_dump.vcd and is located in the execution folder.
Usage:
1) To dump function usage:
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(FUNCTION_NAME, VCD_FUNCTION_IN); at start of function
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(FUNCTION_NAME, VCD_FUNCTION_OUT); at end of function
FUNCTION_NAME should be defined in the enum in vcd_signal_dumper.h and the function name should be addded at the right place in the vcd_signal_dumper.c file.
2) To dump a variable:
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VARIABLE_NAME, value); where VARIABLE_NAME is defined as described above for functions and value is the state of the variable at log time.
TODO list:
- Add support for signed variables
- Create more than two module (for now: one for variable, one for functions)
- Integrate date in filename
- Use a more accurate clock (if necessary) or use a host specific clock (for other systems than Linux)
Useful link:
http://www.beyondttl.com/vcd.php
+707
View File
@@ -0,0 +1,707 @@
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file log.c
* \brief log implementaion
* \author Navid Nikaein
* \date 2009 - 2014
* \version 0.5
* @ingroup util
*/
#define _GNU_SOURCE /* required for pthread_getname_np */
//#define LOG_TEST 1
#define COMPONENT_LOG
#define COMPONENT_LOG_IF
#include <ctype.h>
#define LOG_MAIN
#include "log.h"
#include "vcd_signal_dumper.h"
#include "assertions.h"
#if defined(ENABLE_ITTI)
# include "intertask_interface.h"
#endif
# include <pthread.h>
# include <string.h>
#include <linux/prctl.h>
#include "common/config/config_userapi.h"
// main log variables
mapping log_level_names[] = {
{"error", OAILOG_ERR},
{"file", OAILOG_FILE},
{"warn", OAILOG_WARNING},
{"info", OAILOG_INFO},
{"debug", OAILOG_DEBUG},
{"trace", OAILOG_TRACE},
{NULL, -1}
};
mapping log_options[] = {
{"nocolor", FLAG_NOCOLOR },
{"level", FLAG_LEVEL },
{"thread", FLAG_THREAD },
{NULL,-1}
};
mapping log_maskmap[] = {
{"prach", DEBUG_PRACH},
{"RU", DEBUG_RU},
{"LTEESTIM", DEBUG_LTEESTIM},
{"ctrlsocket", DEBUG_CTRLSOCKET},
{"UE_PHYPROC", DEBUG_UE_PHYPROC},
{"UE_TIMING", UE_TIMING},
{NULL,-1}
};
char *log_level_highlight_start[] = {LOG_RED, LOG_GREEN, LOG_ORANGE, "", LOG_BLUE, LOG_CYBL}; /*!< \brief Optional start-format strings for highlighting */
char *log_level_highlight_end[] = {LOG_RESET,LOG_RESET,LOG_RESET,LOG_RESET, LOG_RESET,LOG_RESET}; /*!< \brief Optional end-format strings for highlighting */
int write_file_matlab(const char *fname,const char *vname,void *data,int length,int dec,char format)
{
FILE *fp=NULL;
int i;
if (data == NULL)
return -1;
//printf("Writing %d elements of type %d to %s\n",length,format,fname);
if (format == 10 || format ==11 || format == 12 || format == 13 || format == 14) {
fp = fopen(fname,"a+");
} else if (format != 10 && format !=11 && format != 12 && format != 13 && format != 14) {
fp = fopen(fname,"w+");
}
if (fp== NULL) {
printf("[OPENAIR][FILE OUTPUT] Cannot open file %s\n",fname);
return(-1);
}
if (format != 10 && format !=11 && format != 12 && format != 13 && format != 14)
fprintf(fp,"%s = [",vname);
switch (format) {
case 0: // real 16-bit
for (i=0; i<length; i+=dec) {
fprintf(fp,"%d\n",((short *)data)[i]);
}
break;
case 1: // complex 16-bit
case 13:
case 14:
case 15:
for (i=0; i<length<<1; i+=(2*dec)) {
fprintf(fp,"%d + j*(%d)\n",((short *)data)[i],((short *)data)[i+1]);
}
break;
case 2: // real 32-bit
for (i=0; i<length; i+=dec) {
fprintf(fp,"%d\n",((int *)data)[i]);
}
break;
case 3: // complex 32-bit
for (i=0; i<length<<1; i+=(2*dec)) {
fprintf(fp,"%d + j*(%d)\n",((int *)data)[i],((int *)data)[i+1]);
}
break;
case 4: // real 8-bit
for (i=0; i<length; i+=dec) {
fprintf(fp,"%d\n",((char *)data)[i]);
}
break;
case 5: // complex 8-bit
for (i=0; i<length<<1; i+=(2*dec)) {
fprintf(fp,"%d + j*(%d)\n",((char *)data)[i],((char *)data)[i+1]);
}
break;
case 6: // real 64-bit
for (i=0; i<length; i+=dec) {
fprintf(fp,"%lld\n",((long long*)data)[i]);
}
break;
case 7: // real double
for (i=0; i<length; i+=dec) {
fprintf(fp,"%g\n",((double *)data)[i]);
}
break;
case 8: // complex double
for (i=0; i<length<<1; i+=2*dec) {
fprintf(fp,"%g + j*(%g)\n",((double *)data)[i], ((double *)data)[i+1]);
}
break;
case 9: // real unsigned 8-bit
for (i=0; i<length; i+=dec) {
fprintf(fp,"%d\n",((unsigned char *)data)[i]);
}
break;
case 10 : // case eren 16 bit complex :
for (i=0; i<length<<1; i+=(2*dec)) {
if((i < 2*(length-1)) && (i > 0))
fprintf(fp,"%d + j*(%d),",((short *)data)[i],((short *)data)[i+1]);
else if (i == 2*(length-1))
fprintf(fp,"%d + j*(%d);",((short *)data)[i],((short *)data)[i+1]);
else if (i == 0)
fprintf(fp,"\n%d + j*(%d),",((short *)data)[i],((short *)data)[i+1]);
}
break;
case 11 : //case eren 16 bit real for channel magnitudes:
for (i=0; i<length; i+=dec) {
if((i <(length-1))&& (i > 0))
fprintf(fp,"%d,",((short *)data)[i]);
else if (i == (length-1))
fprintf(fp,"%d;",((short *)data)[i]);
else if (i == 0)
fprintf(fp,"\n%d,",((short *)data)[i]);
}
printf("\n eren: length :%d",length);
break;
case 12 : // case eren for log2_maxh real unsigned 8 bit
fprintf(fp,"%d \n",((unsigned char *)&data)[0]);
break;
}
if (format != 10 && format !=11 && format !=12 && format != 13 && format != 15) {
fprintf(fp,"];\n");
fclose(fp);
return(0);
} else if (format == 10 || format ==11 || format == 12 || format == 13 || format == 15) {
fclose(fp);
return(0);
}
return 0;
}
/* get log parameters from configuration file */
void log_getconfig(log_t *g_log) {
char *gloglevel = NULL;
int level;
paramdef_t logparams_defaults[] = LOG_GLOBALPARAMS_DESC;
paramdef_t logparams_level[MAX_LOG_PREDEF_COMPONENTS];
paramdef_t logparams_logfile[MAX_LOG_PREDEF_COMPONENTS];
paramdef_t logparams_debug[sizeof(log_maskmap)/sizeof(mapping)];
paramdef_t logparams_matlab[sizeof(log_maskmap)/sizeof(mapping)];
int ret = config_get( logparams_defaults,sizeof(logparams_defaults)/sizeof(paramdef_t),CONFIG_STRING_LOG_PREFIX);
if (ret <0) {
fprintf(stderr,"[LOG] init aborted, configuration couldn't be performed");
return;
}
for(int i=0; i<logparams_defaults[LOG_OPTIONS_IDX].numelt ; i++) {
for(int j=0; log_options[j].name != NULL ; j++) {
if (strcmp(logparams_defaults[LOG_OPTIONS_IDX].strlistptr[i],log_options[j].name) == 0) {
g_log->flag = g_log->flag | log_options[j].value;
break;
} else if (log_options[j+1].name == NULL){
fprintf(stderr,"Unknown log option: %s\n",logparams_defaults[LOG_OPTIONS_IDX].strlistptr[i]);
exit(-1);
}
}
}
/* build the parameter array for setting per component log level and infile options */
memset(logparams_level, 0, sizeof(paramdef_t)*MAX_LOG_PREDEF_COMPONENTS);
memset(logparams_logfile, 0, sizeof(paramdef_t)*MAX_LOG_PREDEF_COMPONENTS);
for (int i=MIN_LOG_COMPONENTS; i < MAX_LOG_PREDEF_COMPONENTS; i++) {
if(g_log->log_component[i].name == NULL) {
g_log->log_component[i].name = malloc(16);
sprintf((char *)g_log->log_component[i].name,"comp%i?",i);
logparams_logfile[i].paramflags = PARAMFLAG_DONOTREAD;
logparams_level[i].paramflags = PARAMFLAG_DONOTREAD;
}
sprintf(logparams_level[i].optname, LOG_CONFIG_LEVEL_FORMAT, g_log->log_component[i].name);
sprintf(logparams_logfile[i].optname, LOG_CONFIG_LOGFILE_FORMAT, g_log->log_component[i].name);
/* workaround: all log options in existing configuration files use lower case component names
where component names include uppercase char in log.h.... */
for (int j=0 ; j<strlen(logparams_level[i].optname); j++)
logparams_level[i].optname[j] = tolower(logparams_level[i].optname[j]);
for (int j=0 ; j<strlen(logparams_level[i].optname); j++)
logparams_logfile[i].optname[j] = tolower(logparams_logfile[i].optname[j]);
/* */
logparams_level[i].defstrval = gloglevel;
logparams_logfile[i].defuintval = 0;
logparams_logfile[i].numelt = 0;
logparams_level[i].numelt = 0;
logparams_level[i].type = TYPE_STRING;
logparams_logfile[i].type = TYPE_UINT;
logparams_logfile[i].paramflags = logparams_logfile[i].paramflags|PARAMFLAG_BOOL;
}
/* read the per component parameters */
config_get( logparams_level, MAX_LOG_PREDEF_COMPONENTS,CONFIG_STRING_LOG_PREFIX);
config_get( logparams_logfile, MAX_LOG_PREDEF_COMPONENTS,CONFIG_STRING_LOG_PREFIX);
/* now set the log levels and infile option, according to what we read */
for (int i=MIN_LOG_COMPONENTS; i < MAX_LOG_PREDEF_COMPONENTS; i++) {
level = map_str_to_int(log_level_names, *(logparams_level[i].strptr));
set_log(i, level,1);
if (*(logparams_logfile[i].uptr) == 1)
set_component_filelog(i);
}
/* build then read the debug and matlab parameter array */
for (int i=0;log_maskmap[i].name != NULL ; i++) {
sprintf(logparams_debug[i].optname, LOG_CONFIG_DEBUG_FORMAT, log_maskmap[i].name);
sprintf(logparams_matlab[i].optname, LOG_CONFIG_MATLAB_FORMAT, log_maskmap[i].name);
logparams_debug[i].defuintval = 0;
logparams_debug[i].type = TYPE_UINT;
logparams_debug[i].paramflags = PARAMFLAG_BOOL;
logparams_debug[i].uptr = NULL;
logparams_debug[i].chkPptr = NULL;
logparams_debug[i].numelt = 0;
logparams_matlab[i].defuintval = 0;
logparams_matlab[i].type = TYPE_UINT;
logparams_matlab[i].paramflags = PARAMFLAG_BOOL;
logparams_matlab[i].uptr = NULL;
logparams_matlab[i].chkPptr = NULL;
logparams_matlab[i].numelt = 0;
}
config_get( logparams_debug,(sizeof(log_maskmap)/sizeof(mapping)) - 1 ,CONFIG_STRING_LOG_PREFIX);
config_get( logparams_matlab,(sizeof(log_maskmap)/sizeof(mapping)) - 1 ,CONFIG_STRING_LOG_PREFIX);
/* set the debug mask according to the debug parameters values */
for (int i=0; log_maskmap[i].name != NULL ; i++) {
if (*(logparams_debug[i].uptr) )
g_log->debug_mask = g_log->debug_mask | log_maskmap[i].value;
if (*(logparams_matlab[i].uptr) )
g_log->matlab_mask = g_log->matlab_mask | log_maskmap[i].value;
}
}
int register_log_component(char *name, char *fext, int compidx)
{
int computed_compidx=compidx;
if (strlen(fext) > 3) {
fext[3]=0; /* limit log file extension to 3 chars */
}
if (compidx < 0) { /* this is not a pre-defined component */
for (int i = MAX_LOG_PREDEF_COMPONENTS; i< MAX_LOG_COMPONENTS; i++) {
if (g_log->log_component[i].name == NULL) {
computed_compidx=i;
break;
}
}
}
if (computed_compidx >= 0 && computed_compidx <MAX_LOG_COMPONENTS) {
g_log->log_component[computed_compidx].name = strdup(name);
g_log->log_component[computed_compidx].level = LOG_ERR;
g_log->log_component[computed_compidx].interval = 1;
g_log->log_component[computed_compidx].stream = NULL;
g_log->log_component[computed_compidx].filelog = 0;
g_log->log_component[computed_compidx].filelog_name = malloc(strlen(name)+16);/* /tmp/<name>.%s rounded to ^2 */
sprintf(g_log->log_component[computed_compidx].filelog_name,"/tmp/%s.%s",name,fext);
} else {
fprintf(stderr,"{LOG} %s %d Couldn't register componemt %s\n",__FILE__,__LINE__,name);
}
return computed_compidx;
}
int logInit (void)
{
int i;
g_log = calloc(1, sizeof(log_t));
if (g_log == NULL) {
perror ("cannot allocated memory for log generation module \n");
exit(EXIT_FAILURE);
}
memset(g_log,0,sizeof(log_t));
register_log_component("PHY","log",PHY);
register_log_component("MAC","log",MAC);
register_log_component("OPT","log",OPT);
register_log_component("RLC","log",RLC);
register_log_component("PDCP","log",PDCP);
register_log_component("RRC","log",RRC);
register_log_component("OMG","csv",OMG);
register_log_component("OTG","log",OTG);
register_log_component("OTG_LATENCY","dat",OTG_LATENCY);
register_log_component("OTG_LATENCY_BG","dat",OTG_LATENCY_BG);
register_log_component("OTG_GP","dat",OTG_GP);
register_log_component("OTG_GP_BG","dat",OTG_GP_BG);
register_log_component("OTG_JITTER","dat",OTG_JITTER);
register_log_component("OCG","",OCG);
register_log_component("PERF","",PERF);
register_log_component("OIP","",OIP);
register_log_component("CLI","",CLI);
register_log_component("MSC","log",MSC);
register_log_component("OCM","log",OCM);
register_log_component("HW","",HW);
register_log_component("OSA","",OSA);
register_log_component("eRAL","",RAL_ENB);
register_log_component("mRAL","",RAL_UE);
register_log_component("ENB_APP","log",ENB_APP);
register_log_component("FLEXRAN_AGENT","log",FLEXRAN_AGENT);
register_log_component("TMR","",TMR);
register_log_component("USIM","txt",USIM);
register_log_component("SIM","txt",SIM);
/* following log component are used for the localization*/
register_log_component("LOCALIZE","log",LOCALIZE);
register_log_component("NAS","log",NAS);
register_log_component("UDP","",UDP_);
register_log_component("GTPV1U","",GTPU);
register_log_component("S1AP","",S1AP);
register_log_component("SCTP","",SCTP);
register_log_component("RRH","",RRH);
g_log->level2string[OAILOG_ERR] = "E"; // ERROR
g_log->level2string[OAILOG_WARNING] = "W"; // WARNING
g_log->level2string[OAILOG_INFO] = "I"; //INFO
g_log->level2string[OAILOG_DEBUG] = "D"; // DEBUG
g_log->level2string[OAILOG_FILE] = "F"; // file
g_log->level2string[OAILOG_TRACE] = "T"; // TRACE
g_log->onlinelog = 1; //online log file
g_log->filelog = 0;
g_log->filelog_name = "/tmp/openair.log";
log_getconfig(g_log);
// could put a loop here to check for all comps
for (i=MIN_LOG_COMPONENTS; i < MAX_LOG_COMPONENTS; i++) {
if (g_log->log_component[i].filelog == 1 ) {
g_log->log_component[i].stream = fopen(g_log->log_component[i].filelog_name,"w");
g_log->log_component[i].fwrite = vfprintf;
} else if (g_log->log_component[i].filelog == 1 ) {
g_log->log_component[i].stream = fopen(g_log->filelog_name,"w");
g_log->log_component[i].fwrite = vfprintf;
} else if (g_log->onlinelog == 1 ) {
g_log->log_component[i].stream = stdout;
g_log->log_component[i].fwrite = vfprintf;
}
}
// set all unused component items to 0, they are for non predefined components
for (i=MAX_LOG_PREDEF_COMPONENTS; i < MAX_LOG_COMPONENTS; i++) {
memset(&(g_log->log_component[i]),0,sizeof(log_component_t));
}
printf("log init done\n");
return 0;
}
char *log_getthreadname(char *threadname, int bufsize) {
int rt = pthread_getname_np(pthread_self(), threadname,bufsize) ;
if (rt == 0)
{
return threadname;
} else {
return "thread?";
}
}
void logRecord_mt(const char *file, const char *func, int line, int comp, int level, const char* format, ... )
{
char threadname[PR_SET_NAME];
char log_buffer[MAX_LOG_TOTAL];
va_list args;
va_start(args, format);
snprintf(log_buffer, MAX_LOG_TOTAL , "%s%s[%s]%s %s %s",
log_level_highlight_end[level],
( (g_log->flag & FLAG_NOCOLOR)?"":log_level_highlight_start[level]),
g_log->log_component[comp].name,
( (g_log->flag & FLAG_LEVEL)?g_log->level2string[level]:""),
( (g_log->flag & FLAG_THREAD)?log_getthreadname(threadname,PR_SET_NAME+1):""),
format);
g_log->log_component[comp].fwrite(g_log->log_component[comp].stream,log_buffer, args);
va_end(args);
}
int set_log(int component, int level, int interval)
{
/* Checking parameters */
DevCheck((component >= MIN_LOG_COMPONENTS) && (component < MAX_LOG_COMPONENTS),
component, MIN_LOG_COMPONENTS, MAX_LOG_COMPONENTS);
DevCheck((level < NUM_LOG_LEVEL) && (level >= OAILOG_ERR), level, NUM_LOG_LEVEL,
OAILOG_ERR);
DevCheck((interval >= 0) && (interval <= 0xFF), interval, 0, 0xFF);
g_log->log_component[component].level = level;
g_log->log_component[component].interval = interval;
return 0;
}
void set_glog(int level)
{
for (int c=0; c< MAX_LOG_COMPONENTS; c++ ) {
g_log->log_component[c].level = level;
}
}
void set_glog_onlinelog(int enable)
{
g_log->onlinelog = enable;
}
void set_glog_filelog(int enable)
{
g_log->filelog = enable;
}
void set_component_filelog(int comp)
{
if (g_log->log_component[comp].filelog == 0) {
g_log->log_component[comp].filelog = 1;
if (g_log->log_component[comp].stream == NULL) {
g_log->log_component[comp].stream = fopen(g_log->log_component[comp].filelog_name,"w");
}
}
}
/*
* for the two functions below, the passed array must have a final entry
* with string value NULL
*/
/* map a string to an int. Takes a mapping array and a string as arg */
int map_str_to_int(mapping *map, const char *str)
{
while (1) {
if (map->name == NULL) {
return(-1);
}
if (!strcmp(map->name, str)) {
return(map->value);
}
map++;
}
}
/* map an int to a string. Takes a mapping array and a value */
char *map_int_to_str(mapping *map, int val)
{
while (1) {
if (map->name == NULL) {
return NULL;
}
if (map->value == val) {
return map->name;
}
map++;
}
}
int is_newline( char *str, int size)
{
int i;
for ( i = 0; i < size; i++ ) {
if ( str[i] == '\n' ) {
return 1;
}
}
/* if we get all the way to here, there must not have been a newline! */
return 0;
}
void logClean (void)
{
int i;
LOG_I(PHY,"\n");
for (i=MIN_LOG_COMPONENTS; i < MAX_LOG_COMPONENTS; i++) {
if (g_log->log_component[i].stream != NULL) {
fclose(g_log->log_component[i].stream);
}
}
}
#ifdef LOG_TEST
int main(int argc, char *argv[])
{
logInit();
test_log();
return 1;
}
int test_log(void)
{
LOG_ENTER(MAC); // because the default level is DEBUG
LOG_I(EMU, "1 Starting OAI logs version %s Build date: %s on %s\n",
BUILD_VERSION, BUILD_DATE, BUILD_HOST);
LOG_D(MAC, "1 debug MAC \n");
LOG_W(MAC, "1 warning MAC \n");
set_log(EMU, OAILOG_INFO, FLAG_ONLINE);
set_log(MAC, OAILOG_WARNING, 0);
LOG_I(EMU, "2 Starting OAI logs version %s Build date: %s on %s\n",
BUILD_VERSION, BUILD_DATE, BUILD_HOST);
LOG_E(MAC, "2 error MAC\n");
LOG_D(MAC, "2 debug MAC \n");
LOG_W(MAC, "2 warning MAC \n");
LOG_I(MAC, "2 info MAC \n");
set_log(MAC, OAILOG_NOTICE, 1);
LOG_ENTER(MAC);
LOG_I(EMU, "3 Starting OAI logs version %s Build date: %s on %s\n",
BUILD_VERSION, BUILD_DATE, BUILD_HOST);
LOG_D(MAC, "3 debug MAC \n");
LOG_W(MAC, "3 warning MAC \n");
LOG_I(MAC, "3 info MAC \n");
set_log(MAC, LOG_DEBUG,1);
set_log(EMU, LOG_DEBUG,1);
LOG_ENTER(MAC);
LOG_I(EMU, "4 Starting OAI logs version %s Build date: %s on %s\n",
BUILD_VERSION, BUILD_DATE, BUILD_HOST);
LOG_D(MAC, "4 debug MAC \n");
LOG_W(MAC, "4 warning MAC \n");
LOG_I(MAC, "4 info MAC \n");
set_log(MAC, LOG_DEBUG,0);
set_log(EMU, LOG_DEBUG,0);
LOG_I(LOG, "5 Starting OAI logs version %s Build date: %s on %s\n",
BUILD_VERSION, BUILD_DATE, BUILD_HOST);
LOG_D(MAC, "5 debug MAC \n");
LOG_W(MAC, "5 warning MAC \n");
LOG_I(MAC, "5 info MAC \n");
set_log(MAC, LOG_TRACE,0X07F);
set_log(EMU, LOG_TRACE,0X07F);
LOG_ENTER(MAC);
LOG_I(LOG, "6 Starting OAI logs version %s Build date: %s on %s\n",
BUILD_VERSION, BUILD_DATE, BUILD_HOST);
LOG_D(MAC, "6 debug MAC \n");
LOG_W(MAC, "6 warning MAC \n");
LOG_I(MAC, "6 info MAC \n");
LOG_EXIT(MAC);
return 0;
}
#endif
+492
View File
@@ -0,0 +1,492 @@
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file log.h
* \brief openair log generator (OLG) for
* \author Navid Nikaein
* \date 2009 - 2014
* \version 0.5
* @ingroup util
*/
#ifndef __LOG_H__
# define __LOG_H__
/*--- INCLUDES ---------------------------------------------------------------*/
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdarg.h>
#include <time.h>
#include <stdint.h>
#ifndef __STDC_FORMAT_MACROS
#define __STDC_FORMAT_MACROS
#endif
#include <inttypes.h>
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <pthread.h>
#include "T.h"
/*----------------------------------------------------------------------------*/
#ifdef __cplusplus
extern "C" {
#endif
/** @defgroup _LOG LOG Generator
* @{*/
/* @}*/
/** @defgroup _macro Macro Definition
* @ingroup _LOG
* @brief these macros are used in the code of LOG
* @{*/
/* @}*/
/** @defgroup _max_length Maximum Length of LOG
* @ingroup _macro
* @brief the macros that describe the maximum length of LOG
* @{*/
#define MAX_LOG_TOTAL 1500 /*!< \brief the maximum length of a log */
/* @}*/
/** @defgroup _log_level Message levels defined by LOG
* @ingroup _macro
* @brief LOG defines 9 levels of messages for users. Importance of these levels decrease gradually from 0 to 8
* @{*/
# define OAILOG_ERR 0 /*!< \brief critical error conditions, impact on "must have" fuctinalities */
# define OAILOG_FILE 1 /*!< \brief important informational messages, but everything OK */
# define OAILOG_WARNING 2 /*!< \brief warning conditions, shouldn't happen but doesn't impact "must have" functionalities */
# define OAILOG_INFO 3 /*!< \brief informational messages most people don't need, shouldn't impact real-time behavior */
# define OAILOG_DEBUG 4 /*!< \brief first level debug-level messages, for developers , may impact real-time behavior */
# define OAILOG_TRACE 5 /*!< \brief second level debug-level messages, for developers ,likely impact real-time behavior*/
#define NUM_LOG_LEVEL 6 /*!< \brief the number of message levels users have with LOG */
/* @}*/
/** @defgroup _log_format Defined log format
* @ingroup _macro
* @brief Macro of log formats defined by LOG
* @{*/
/* .log_format = 0x13 uncolored standard messages
* .log_format = 0x93 colored standard messages */
/* keep white space in first position; switching it to 0 allows colors to be disabled*/
#define LOG_RED "\033[1;31m" /*!< \brief VT100 sequence for bold red foreground */
#define LOG_GREEN "\033[32m" /*!< \brief VT100 sequence for green foreground */
#define LOG_ORANGE "\033[93m" /*!< \brief VT100 sequence for orange foreground */
#define LOG_BLUE "\033[34m" /*!< \brief VT100 sequence for blue foreground */
#define LOG_CYBL "\033[40;36m" /*!< \brief VT100 sequence for cyan foreground on black background */
#define LOG_RESET "\033[0m" /*!< \brief VT100 sequence for reset (black) foreground */
/* @}*/
/** @defgroup _syslog_conf Macros for write in syslog.conf
* @ingroup _macro
* @brief Macros used to write lines (local/remote) in syslog.conf
* @{*/
#define FLAG_NOCOLOR 0x0001 /*!< \brief use colors in log messages, depending on level */
#define FLAG_THREAD 0x0008 /*!< \brief display thread name in log messages */
#define FLAG_LEVEL 0x0010 /*!< \brief display log level in log messages */
#define FLAG_FUNCT 0x0020
#define FLAG_FILE_LINE 0x0040
#define FLAG_TIME 0x0100
#define SET_LOG_OPTION(O) g_log->flag = (g_log->flag | O)
#define CLEAR_LOG_OPTION(O) g_log->flag = (g_log->flag & (~O))
/** @defgroup macros to identify a debug entity
* @ingroup each macro is a bit mask where the unique bit set identifies an entity to be debugged
* it allows to dynamically activate or not blocks of code
* @brief
* @{*/
#define DEBUG_PRACH (1<<0)
#define DEBUG_RU (1<<1)
#define DEBUG_UE_PHYPROC (1<<2)
#define DEBUG_LTEESTIM (1<<3)
#define DEBUG_CTRLSOCKET (1<<10)
#define UE_TIMING (1<<20)
#define SET_LOG_DEBUG(O) g_log->debug_mask = (g_log->debug_mask | O)
#define CLEAR_LOG_DEBUG(O) g_log->debug_mask = (g_log->debug_mask & (~O))
#define SET_LOG_MATLAB(O) g_log->matlab_mask = (g_log->matlab_mask | O)
#define CLEAR_LOG_MATLAB(O) g_log->matlab_mask = (g_log->matlab_mask & (~O))
typedef enum {
MIN_LOG_COMPONENTS = 0,
PHY = MIN_LOG_COMPONENTS,
MAC,
SIM,
OCG,
OMG,
OPT,
OTG,
OTG_LATENCY,
OTG_LATENCY_BG,
OTG_GP,
OTG_GP_BG,
OTG_JITTER,
RLC,
PDCP,
RRC,
NAS,
PERF,
OIP,
CLI,
MSC,
OCM,
UDP_,
GTPU,
SPGW,
S1AP,
SCTP,
HW,
OSA,
RAL_ENB,
RAL_UE,
ENB_APP,
FLEXRAN_AGENT,
TMR,
USIM,
LOCALIZE,
RRH,
X2AP,
GNB_APP,
NR_RRC,
NR_MAC,
NR_PHY,
MAX_LOG_COMPONENTS,
LOADER,
MAX_LOG_PREDEF_COMPONENTS,
}
comp_name_t;
#define MAX_LOG_DYNALLOC_COMPONENTS 20
#define MAX_LOG_COMPONENTS (MAX_LOG_PREDEF_COMPONENTS + MAX_LOG_DYNALLOC_COMPONENTS)
typedef struct {
char *name; /*!< \brief string name of item */
int value; /*!< \brief integer value of mapping */
} mapping;
typedef int(*log_write_func_t)(FILE *stream, const char *format, va_list ap );
typedef struct {
const char *name;
int level;
int flag;
int interval;
int filelog;
char *filelog_name;
FILE *stream;
log_write_func_t fwrite;
/* SR: make the log buffer component relative */
char log_buffer[MAX_LOG_TOTAL];
} log_component_t;
typedef struct {
log_component_t log_component[MAX_LOG_COMPONENTS];
char* level2string[NUM_LOG_LEVEL];
int onlinelog;
int flag;
int filelog;
char* filelog_name;
uint64_t debug_mask;
uint64_t matlab_mask;
} log_t;
#if defined(ENABLE_ITTI)
typedef enum log_instance_type_e {
LOG_INSTANCE_UNKNOWN,
LOG_INSTANCE_ENB,
LOG_INSTANCE_UE,
} log_instance_type_t;
void log_set_instance_type (log_instance_type_t instance);
#endif
#ifdef LOG_MAIN
log_t *g_log;
#else
#ifdef __cplusplus
extern "C" {
#endif
extern log_t *g_log;
#ifdef __cplusplus
}
#endif
#endif
/*--- INCLUDES ---------------------------------------------------------------*/
# include "log_if.h"
/*----------------------------------------------------------------------------*/
int logInit (void);
void logRecord_mt(const char *file, const char *func, int line,int comp, int level, const char *format, ...) __attribute__ ((format (printf, 6, 7)));
int set_log(int component, int level, int interval);
void set_glog(int level);
void set_glog_onlinelog(int enable);
void set_glog_filelog(int enable);
void set_component_filelog(int comp);
int map_str_to_int(mapping *map, const char *str);
char *map_int_to_str(mapping *map, int val);
void logClean (void);
int is_newline( char *str, int size);
int register_log_component(char *name, char *fext, int compidx);
/* @}*/
/*!\fn int32_t write_file_matlab(const char *fname, const char *vname, void *data, int length, int dec, char format);
\brief Write output file from signal data
@param fname output file name
@param vname output vector name (for MATLAB/OCTAVE)
@param data point to data
@param length length of data vector to output
@param dec decimation level
@param format data format (0 = real 16-bit, 1 = complex 16-bit,2 real 32-bit, 3 complex 32-bit,4 = real 8-bit, 5 = complex 8-bit)
*/
int32_t write_file_matlab(const char *fname, const char *vname, void *data, int length, int dec, char format);
/*----------------macro definitions for reading log configuration from the config module */
#define CONFIG_STRING_LOG_PREFIX "log_config"
#define LOG_CONFIG_STRING_GLOBAL_LOG_LEVEL "global_log_level"
#define LOG_CONFIG_STRING_GLOBAL_LOG_ONLINE "global_log_online"
#define LOG_CONFIG_STRING_GLOBAL_LOG_INFILE "global_log_infile"
#define LOG_CONFIG_STRING_GLOBAL_LOG_OPTIONS "global_log_options"
#define LOG_CONFIG_LEVEL_FORMAT "%s_log_level"
#define LOG_CONFIG_LOGFILE_FORMAT "%s_log_infile"
#define LOG_CONFIG_DEBUG_FORMAT "%s_debug"
#define LOG_CONFIG_MATLAB_FORMAT "%s_matlab"
#define LOG_CONFIG_HELP_OPTIONS " list of comma separated options to enable log module behavior. Available options: \n"\
" nocolor: disable color usage in log messages\n"\
" level: add log level indication in log messages\n"\
" thread: add threads names in log messages\n"
/*------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
/* LOG globalconfiguration parameters */
/* optname help paramflags XXXptr defXXXval type numelt */
/*------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
#define LOG_GLOBALPARAMS_DESC { \
{LOG_CONFIG_STRING_GLOBAL_LOG_LEVEL, "Default log level for all componemts\n", 0, strptr:(char **)&gloglevel, defstrval:log_level_names[2].name, TYPE_STRING, 0}, \
{LOG_CONFIG_STRING_GLOBAL_LOG_ONLINE, "Default console output option, for all components\n", 0, iptr:&(g_log->onlinelog), defintval:1, TYPE_INT, 0}, \
{LOG_CONFIG_STRING_GLOBAL_LOG_OPTIONS, LOG_CONFIG_HELP_OPTIONS, 0, strlistptr:NULL, defstrlistval:NULL, TYPE_STRINGLIST,0} \
}
#define LOG_OPTIONS_IDX 2
/*----------------------------------------------------------------------------------*/
/** @defgroup _debugging debugging macros
* @ingroup _macro
* @brief Macro used to call logIt function with different message levels
* @{*/
// debugging macros(g_log->log_component[component].interval?logRecord_mt(__FILE__, __FUNCTION__, __LINE__, component, level, format, ##args):(void)0)
# if T_TRACER
/* per component, level dependant macros */
# define LOG_I(c, x...) do { if (T_stdout) { if( g_log->log_component[c].level >= OAILOG_INFO ) logRecord_mt(__FILE__, __FUNCTION__, __LINE__,c, OAILOG_INFO, x) ;} else { T(T_LEGACY_ ## c ## _INFO, T_PRINTF(x)) ;}} while (0)
# define LOG_W(c, x...) do { if (T_stdout) { if( g_log->log_component[c].level >= OAILOG_WARNING) logRecord_mt(__FILE__, __FUNCTION__, __LINE__,c, OAILOG_WARNING, x) ;} else { T(T_LEGACY_ ## c ## _WARNING, T_PRINTF(x)) ;}} while (0)
# define LOG_E(c, x...) do { if (T_stdout) { if( g_log->log_component[c].level >= OAILOG_ERR ) logRecord_mt(__FILE__, __FUNCTION__, __LINE__,c, OAILOG_ERR, x) ;} else { T(T_LEGACY_ ## c ## _ERROR, T_PRINTF(x)) ;}} while (0)
# define LOG_D(c, x...) do { if (T_stdout) { if( g_log->log_component[c].level >= OAILOG_DEBUG ) logRecord_mt(__FILE__, __FUNCTION__, __LINE__,c, OAILOG_DEBUG, x) ;} else { T(T_LEGACY_ ## c ## _DEBUG, T_PRINTF(x)) ;}} while (0)
# define LOG_T(c, x...) do { if (T_stdout) { if( g_log->log_component[c].level >= OAILOG_TRACE ) logRecord_mt(__FILE__, __FUNCTION__, __LINE__,c, OAILOG_TRACE, x) ;} else { T(T_LEGACY_ ## c ## _TRACE, T_PRINTF(x)) ;}} while (0)
# define LOG_F(c, x...) do { if (T_stdout) { if( g_log->log_component[c].level >= OAILOG_FILE ) logRecord_mt(__FILE__, __FUNCTION__, __LINE__,c, OAILOG_FILE, x) ;}} while (0) /* */
# define nfapi_log(FILE, FNC, LN, COMP, LVL, F...) do { if (T_stdout) { logRecord_mt(__FILE__, __FUNCTION__, __LINE__,COMP, LVL, F) ;}} while (0) /* */
/* bitmask dependant macros, to isolate debugging code */
# define LOG_DEBUG_BEGIN(D) if (g_log->debug_mask & D) {
# define LOG_DEBUG_END }
/* bitmask dependant macros, to generate matlab files */
# define LOG_M_BEGIN(D) if (g_log->matlab_mask & D) {
# define LOG_M_END }
# define LOG_M(file, vector, data, len, dec, format) do { write_file_matlab(file, vector, data, len, dec, format);} while(0)/* */
/* define variable only used in LOG macro's */
# define LOG_VAR(A,B) A B
# else /* T_TRACER: remove all debugging and tracing messages, except errors */
# define LOG_I(c, x...) /* */
# define LOG_W(c, x...) /* */
# define LOG_E(c, x...) /* */
# define LOG_D(c, x...) /* */
# define LOG_T(c, x...) /* */
# define LOG_F(c, x...) /* */
# define nfapi_log(FILE, FNC, LN, COMP, LVL, FMT...)
# define LOG_DEBUG_BEGIN(D) if (0) {
# define LOG_DEBUG_END }
# define LOG_M_BEGIN(D) if (0) {
# define LOG_M_END }
# define LOG_M(file, vector, data, len, dec, format)
# define LOG_VAR(A,B)
# endif /* T_TRACER */
/* avoid warnings for variables only used in LOG macro's but set outside debug section */
#define LOG_USEDINLOG_VAR(A,B) __attribute__((unused)) A B
/* unfiltered macros, usefull for simulators or messages at init time, before log is configured */
#define LOG_UM(file, vector, data, len, dec, format) do { write_file_matlab(file, vector, data, len, dec, format);} while(0)
#define LOG_UI(c, x...) do {logRecord_mt(__FILE__, __FUNCTION__, __LINE__,c, OAILOG_INFO, x) ; } while(0)
/* @}*/
/** @defgroup _useful_functions useful functions in LOG
* @ingroup _macro
* @brief Macro of some useful functions defined by LOG
* @{*/
#define LOG_ENTER(c) do {LOG_T(c, "Entering\n");}while(0) /*!< \brief Macro to log a message with severity DEBUG when entering a function */
#define LOG_EXIT(c) do {LOG_T(c,"Exiting\n"); return;}while(0) /*!< \brief Macro to log a message with severity TRACE when exiting a function */
#define LOG_RETURN(c,x) do {uint32_t __rv;__rv=(unsigned int)(x);LOG_T(c,"Returning %08x\n", __rv);return((typeof(x))__rv);}while(0) /*!< \brief Macro to log a function exit, including integer value, then to return a value to the calling function */
/* @}*/
static __inline__ uint64_t rdtsc(void) {
uint32_t a, d;
__asm__ volatile ("rdtsc" : "=a" (a), "=d" (d));
return (((uint64_t)d)<<32) | ((uint64_t)a);
}
#define DEBUG_REALTIME 1
#if DEBUG_REALTIME
extern double cpuf;
static inline uint64_t checkTCPU(int timeout, char * file, int line) {
static __thread uint64_t lastCPUTime=0;
static __thread uint64_t last=0;
uint64_t cur=rdtsc();
struct timespec CPUt;
clock_gettime(CLOCK_THREAD_CPUTIME_ID, &CPUt);
uint64_t CPUTime=CPUt.tv_sec*1000*1000+CPUt.tv_nsec/1000;
double microCycles=(double)(cpuf*1000);
int duration=(int)((cur-last)/microCycles);
if ( last!=0 && duration > timeout ) {
//struct timespec ts;
//clock_gettime(CLOCK_MONOTONIC, &ts);
printf("%s:%d lte-ue delay %d (exceed %d), CPU for this period: %lld\n", file, line,
duration, timeout, (long long)CPUTime-lastCPUTime );
}
last=cur;
lastCPUTime=CPUTime;
return cur;
}
static inline unsigned long long checkT(int timeout, char * file, int line) {
static __thread unsigned long long last=0;
unsigned long long cur=rdtsc();
int microCycles=(int)(cpuf*1000);
int duration=(int)((cur-last)/microCycles);
if ( last!=0 && duration > timeout )
printf("%s:%d lte-ue delay %d (exceed %d)\n", file, line,
duration, timeout);
last=cur;
return cur;
}
typedef struct m {
uint64_t iterations;
uint64_t sum;
uint64_t maxArray[11];
} Meas;
static inline void printMeas(char * txt, Meas *M, int period) {
if (M->iterations%period == 0 ) {
char txt2[512];
sprintf(txt2,"%s avg=%" PRIu64 " iterations=%" PRIu64 " max=%"
PRIu64 ":%" PRIu64 ":%" PRIu64 ":%" PRIu64 ":%" PRIu64 ":%" PRIu64 ":%" PRIu64 ":%" PRIu64 ":%" PRIu64 ":%" PRIu64 "\n",
txt,
M->sum/M->iterations,
M->iterations,
M->maxArray[1],M->maxArray[2], M->maxArray[3],M->maxArray[4], M->maxArray[5],
M->maxArray[6],M->maxArray[7], M->maxArray[8],M->maxArray[9],M->maxArray[10]);
#if DISABLE_LOG_X
printf("%s",txt2);
#else
LOG_W(PHY, "%s",txt2);
#endif
}
}
static inline int cmpint(const void* a, const void* b) {
uint64_t* aa=(uint64_t*)a;
uint64_t* bb=(uint64_t*)b;
return (int)(*aa-*bb);
}
static inline void updateTimes(uint64_t start, Meas *M, int period, char * txt) {
if (start!=0) {
uint64_t end=rdtsc();
long long diff=(end-start)/(cpuf*1000);
M->maxArray[0]=diff;
M->sum+=diff;
M->iterations++;
qsort(M->maxArray, 11, sizeof(uint64_t), cmpint);
printMeas(txt,M,period);
}
}
#define check(a) do { checkT(a,__FILE__,__LINE__); } while (0)
#define checkcpu(a) do { checkTCPU(a,__FILE__,__LINE__); } while (0)
#define initRefTimes(a) static __thread Meas a= {0}
#define pickTime(a) uint64_t a=rdtsc()
#define readTime(a) a
#define initStaticTime(a) static __thread uint64_t a={0}
#define pickStaticTime(a) do { a=rdtsc(); } while (0)
#else
#define check(a) do {} while (0)
#define checkcpu(a) do {} while (0)
#define initRefTimes(a) do {} while (0)
#define initStaticTime(a) do {} while (0)
#define pickTime(a) do {} while (0)
#define readTime(a) 0
#define pickStaticTime(a) do {} while (0)
#define updateTimes(a,b,c,d) do {} while (0)
#define printMeas(a,b,c) do {} while (0)
#endif
#ifdef __cplusplus
}
#endif
#endif
@@ -19,16 +19,12 @@
* contact@openairinterface.org
*/
#ifndef INTERTASK_INTERFACE_DUMP_H_
#define INTERTASK_INTERFACE_DUMP_H_
#include"log.h"
int itti_dump_queue_message(task_id_t sender_task, message_number_t message_number, MessageDef *message_p, const char *message_name,
const uint32_t message_size);
extern log_t *g_log;
int itti_dump_init(const char * const messages_definition_xml, const char * const dump_file_name);
void itti_dump_exit(void);
extern mapping log_level_names[];
extern mapping log_options[];
extern mapping log_maskmap[];
void itti_dump_thread_use_ring_buffer(void);
#endif /* INTERTASK_INTERFACE_DUMP_H_ */
+34
View File
@@ -0,0 +1,34 @@
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file log_if.h
* \brief log interface
* \author Navid Nikaein
* \date 2009 - 2014
* \version 0.3
* \warning This component can be runned only in user-space
* @ingroup routing
*/
// LTS: kept this file for compatibility
// this file was probably a trial to separate internal functions and external ones
// but it has never been finished, most source code include directly log.h (not log_if.h)
#include "log.h"
+823
View File
@@ -0,0 +1,823 @@
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file vcd_signal_dumper.c
* \brief Dump functions calls and variables to VCD file. Use GTKWave to display this file.
* \author S. Roux
* \maintainer: navid nikaein
* \date 2012 - 2104
* \version 0.1
* \company Eurecom
* \email: navid.nikaein@eurecom.fr
* \note
* \warning
*/
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdarg.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <error.h>
#include <time.h>
#include <unistd.h>
#include "assertions.h"
#include "signals.h"
#include "vcd_signal_dumper.h"
#define VCDSIGNALDUMPER_VERSION_MAJOR 0
#define VCDSIGNALDUMPER_VERSION_MINOR 1
// Global variable. If the VCD option is set at execution time, output VCD trace. Otherwise this module has no effect.
int ouput_vcd = 0;
struct vcd_module_s {
const char *name;
int number_of_signals;
const char **signals_names;
vcd_signal_type signal_type;
int signal_size;
} vcd_module_s;
const char* eurecomVariablesNames[] = {
"frame_number_TX0_eNB",
"frame_number_TX1_eNB",
"frame_number_RX0_eNB",
"frame_number_RX1_eNB",
"subframe_number_TX0_eNB",
"subframe_number_TX1_eNB",
"subframe_number_RX0_eNB",
"subframe_number_RX1_eNB",
"frame_number_TX0_RU",
"frame_number_TX1_RU",
"frame_number_RX0_RU",
"frame_number_RX1_RU",
"subframe_number_TX0_RU",
"subframe_number_TX1_RU",
"subframe_number_RX0_RU",
"subframe_number_RX1_RU",
"runtime_TX_eNB",
"runtime_RX_eNB",
"frame_number_TX0_UE",
"frame_number_TX1_UE",
"frame_number_RX0_UE",
"frame_number_RX1_UE",
"subframe_TX0_UE",
"subframe_TX1_UE",
"subframe_RX0_UE",
"subframe_RX1_UE",
"ue_rx_offset",
"diff2",
"hw_subframe",
"hw_frame",
"hw_subframe_rx",
"hw_frame_rx",
"txcnt",
"rxcnt",
"trx_ts",
"trx_tst",
"trx_ts_ue",
"trx_tst_ue",
"trx_write_flags",
"tx_ts",
"rx_ts",
"hw_cnt_rx",
"lhw_cnt_rx",
"hw_cnt_tx",
"lhw_cnt_tx",
"pck_rx",
"pck_tx",
"rx_seq_num",
"rx_seq_num_prv",
"tx_seq_num",
"cnt",
"dummy_dump",
"itti_send_msg",
"itti_poll_msg",
"itti_recv_msg",
"itti_alloc_msg",
"mp_alloc",
"mp_free",
"ue_inst_cnt_rx",
"ue_inst_cnt_tx",
"dci_info",
"ue0_BSR",
"ue0_BO",
"ue0_scheduled",
"ue0_timing_advance",
"ue0_SR_ENERGY",
"ue0_SR_THRES",
"ue0_rssi0",
"ue0_rssi1",
"ue0_rssi2",
"ue0_rssi3",
"ue0_rssi4",
"ue0_rssi5",
"ue0_rssi6",
"ue0_rssi7",
"ue0_res0",
"ue0_res1",
"ue0_res2",
"ue0_res3",
"ue0_res4",
"ue0_res5",
"ue0_res6",
"ue0_res7",
"ue0_MCS0",
"ue0_MCS1",
"ue0_MCS2",
"ue0_MCS3",
"ue0_MCS4",
"ue0_MCS5",
"ue0_MCS6",
"ue0_MCS7",
"ue0_RB0",
"ue0_RB1",
"ue0_RB2",
"ue0_RB3",
"ue0_RB4",
"ue0_RB5",
"ue0_RB6",
"ue0_RB7",
"ue0_ROUND0",
"ue0_ROUND1",
"ue0_ROUND2",
"ue0_ROUND3",
"ue0_ROUND4",
"ue0_ROUND5",
"ue0_ROUND6",
"ue0_ROUND7",
"ue0_SFN0",
"ue0_SFN1",
"ue0_SFN2",
"ue0_SFN3",
"ue0_SFN4",
"ue0_SFN5",
"ue0_SFN6",
"ue0_SFN7",
"send_if4_symbol",
"recv_if4_symbol",
"send_if5_pkt_id",
"recv_if5_pkt_id",
"ue_pdcp_flush_size",
"ue_pdcp_flush_err",
"ue0_trx_read_ns",
"ue0_trx_write_ns",
"ue0_trx_read_ns_missing",
"ue0_trx_write_ns_missing",
"enb_thread_rxtx_CPUID",
"ru_thread_CPUID",
"ru_thread_tx_CPUID"
};
const char* eurecomFunctionsNames[] = {
/* softmodem signals */
"rt_sleep",
"trx_read",
"trx_write",
"trx_read_ue",
"trx_write_ue",
"trx_read_if",
"trx_write_if",
"eNB_thread_rxtx0",
"eNB_thread_rxtx1",
"ue_thread_synch",
"ue_thread_rxtx0",
"ue_thread_rxtx1",
"trx_read_sf9",
"trx_write_sf9",
"ue_signal_cond_rxtx0",
"ue_signal_cond_rxtx1",
"ue_wait_cond_rxtx0",
"ue_wait_cond_rxtx1",
"ue_lock_mutex_rxtx_for_cond_wait0",
"ue_lock_mutex_rxtx_for_cond_wait1",
"ue_lock_mutex_rxtx_for_cnt_decrement0",
"ue_lock_mutex_rxtx_for_cnt_decrement1",
"ue_lock_mutex_rxtx_for_cnt_increment0",
"ue_lock_mutex_rxtx_for_cnt_increment1",
/* simulation signals */
"do_DL_sig",
"do_UL_sig",
"UE_trx_read",
/* RRH signals */
"eNB_tx",
"eNB_rx",
"eNB_trx",
"eNB_tm",
"eNB_rx_sleep",
"eNB_tx_sleep",
"eNB_proc_sleep",
"trx_read_rf",
"trx_write_rf",
/* PHY signals */
"ue_synch",
"ue_slot_fep",
"ue_rrc_measurements",
"ue_gain_control",
"ue_adjust_synch",
"lte_ue_measurement_procedures",
"lte_ue_pdcch_procedures",
"lte_ue_pbch_procedures",
"phy_procedures_eNb_tx0",
"phy_procedures_eNb_tx1",
"phy_procedures_ru_feprx0",
"phy_procedures_ru_feprx1",
"phy_procedures_ru_feptx_ofdm0",
"phy_procedures_ru_feptx_ofdm1",
"phy_procedures_ru_feptx_prec0",
"phy_procedures_ru_feptx_prec1",
"phy_procedures_eNb_rx_uespec0",
"phy_procedures_eNb_rx_uespec1",
"phy_procedures_ue_tx",
"phy_procedures_ue_rx",
"phy_procedures_ue_tx_ulsch_uespec",
"phy_procedures_ue_tx_pucch",
"phy_procedures_ue_tx_ulsch_common",
"phy_procedures_ue_tx_prach",
"phy_procedures_ue_tx_ulsch_rar",
"phy_procedures_eNB_lte",
"phy_procedures_UE_lte",
"pdsch_thread",
"dlsch_thread0",
"dlsch_thread1",
"dlsch_thread2",
"dlsch_thread3",
"dlsch_thread4",
"dlsch_thread5",
"dlsch_thread6",
"dlsch_thread7",
"dlsch_decoding0",
"dlsch_decoding1",
"dlsch_decoding2",
"dlsch_decoding3",
"dlsch_decoding4",
"dlsch_decoding5",
"dlsch_decoding6",
"dlsch_decoding7",
"rx_pdcch",
"dci_decoding",
"rx_phich",
"pdsch_procedures",
"pdsch_procedures_si",
"pdsch_procedures_p",
"pdsch_procedures_ra",
"phy_ue_config_sib2",
"macxface_phy_config_sib1_eNB",
"macxface_phy_config_sib2_eNB",
"macxface_phy_config_dedicated_eNB",
"phy_ue_compute_prach",
"phy_enb_ulsch_msg3",
"phy_enb_ulsch_decoding0",
"phy_enb_ulsch_decoding1",
"phy_enb_ulsch_decoding2",
"phy_enb_ulsch_decoding3",
"phy_enb_ulsch_decoding4",
"phy_enb_ulsch_decoding5",
"phy_enb_ulsch_decoding6",
"phy_enb_ulsch_decoding7",
"phy_enb_sfgen",
"phy_enb_prach_rx",
"phy_ru_prach_rx",
"phy_enb_pdcch_tx",
"phy_enb_rs_tx",
"phy_ue_generate_prach",
"phy_ue_ulsch_modulation",
"phy_ue_ulsch_encoding",
#if 1 // add for debugging losing PDSCH immediately before and after reporting CQI
"phy_ue_ulsch_encoding_fill_cqi",
#endif
"phy_ue_ulsch_scrambling",
"phy_eNB_dlsch_modulation",
"phy_eNB_dlsch_encoding",
"phy_eNB_dlsch_encoding_w",
"phy_eNB_dlsch_scrambling",
"phy_eNB_beam_precoding",
"phy_eNB_ofdm_mod_l",
/* MAC signals */
"macxface_macphy_init",
"macxface_macphy_exit",
"macxface_eNB_dlsch_ulsch_scheduler",
"macxface_fill_rar",
"macxface_terminate_ra_proc",
"macxface_initiate_ra_proc",
"macxface_cancel_ra_proc",
"macxface_get_dci_sdu",
"macxface_get_dlsch_sdu",
"macxface_rx_sdu",
"macxface_mrbch_phy_sync_failure",
"macxface_SR_indication",
"mac_dlsch_preprocessor",
"mac_schedule_dlsch",
"mac_fill_dlsch_dci",
"macxface_out_of_sync_ind",
"macxface_ue_decode_si",
"macxface_ue_decode_pcch",
"macxface_ue_decode_ccch",
"macxface_ue_decode_bcch",
"macxface_ue_send_sdu",
"macxface_ue_get_sdu",
"macxface_ue_get_rach",
"macxface_ue_process_rar",
"macxface_ue_scheduler",
"macxface_ue_get_sr",
"ue_send_mch_sdu",
/*RLC signals */
"rlc_data_req",
// "rlc_data_ind", // this calls "pdcp_data_ind",
"mac_rlc_status_ind",
"mac_rlc_data_req",
"mac_rlc_data_ind",
"rlc_um_try_reassembly",
"rlc_um_check_timer_dar_time_out",
"rlc_um_receive_process_dar",
/* PDCP signals */
"pdcp_run",
"pdcp_data_req",
"pdcp_data_ind",
"pdcp_apply_security",
"pdcp_validate_security",
"pdcp_fifo_read",
"pdcp_fifo_read_buffer",
"pdcp_fifo_flush",
"pdcp_fifo_flush_buffer",
/* RRC signals */
"rrc_rx_tx",
"rrc_mac_config_req",
"rrc_ue_decode_sib1",
"rrc_ue_decode_si",
/* GTPV1U signals */
"gtpv1u_enb_task",
"gtpv1u_process_udp_req",
"gtpv1u_process_tunnel_data_req",
/* UDP signals */
"udp_enb_task",
/* MISC signals */
"emu_transport",
"log_record",
"itti_enqueue_message",
"itti_dump_enqueue_message",
"itti_dump_enqueue_message_malloc",
"itti_relay_thread",
"test",
/* IF4/IF5 signals */
"send_if4",
"recv_if4",
"send_if5",
"recv_if5",
"compress_if",
"decompress_if",
"nfapi_subframe",
"generate_pcfich",
"generate_dci0",
"generate_dlsch",
"generate_phich",
"pdcch_scrambling",
"pdcch_modulation",
"pdcch_interleaving",
"pdcch_tx",
};
struct vcd_module_s vcd_modules[] = {
{ "variables", VCD_SIGNAL_DUMPER_VARIABLES_END, eurecomVariablesNames, VCD_WIRE, 64 },
{ "functions", VCD_SIGNAL_DUMPER_FUNCTIONS_END, eurecomFunctionsNames, VCD_WIRE, 1 },
// { "ue_procedures_functions", VCD_SIGNAL_DUMPER_UE_PROCEDURES_FUNCTIONS_END, eurecomUEFunctionsNames, VCD_WIRE, 1 },
};
FILE *vcd_fd = NULL;
static inline unsigned long long int vcd_get_time(void);
#if defined(ENABLE_USE_CPU_EXECUTION_TIME)
struct timespec g_time_start;
#endif
#if defined(ENABLE_VCD_FIFO)
# define VCD_POLL_DELAY (500) // Poll delay in micro-seconds
# define VCD_MAX_WAIT_DELAY (200 * 1000) // Maximum data ready wait delay in micro-seconds
# define VCD_FIFO_NB_ELEMENTS (1 << 24) // Must be a power of 2
# define VCD_FIFO_MASK (VCD_FIFO_NB_ELEMENTS - 1)
typedef struct vcd_queue_user_data_s {
uint32_t log_id;
vcd_signal_dumper_modules module;
union data_u {
struct function_s {
vcd_signal_dump_functions function_name;
vcd_signal_dump_in_out in_out;
} function;
struct variable_s {
vcd_signal_dump_variables variable_name;
unsigned long value;
} variable;
} data;
long long unsigned int time;
} vcd_queue_user_data_t;
typedef struct vcd_fifo_s {
vcd_queue_user_data_t user_data[VCD_FIFO_NB_ELEMENTS];
volatile uint32_t write_index;
volatile uint32_t read_index;
} vcd_fifo_t;
vcd_fifo_t vcd_fifo;
pthread_t vcd_dumper_thread;
#endif
#define BYTE_SIZE 8
#define NIBBLE_SIZE 4
static void uint64_to_binary(uint64_t value, char *binary)
{
static const char * const nibbles_start[] = {
"", "1", "10", "11",
"100", "101", "110", "111",
"1000", "1001", "1010", "1011",
"1100", "1101", "1110", "1111",
};
static const char * const nibbles[] = {
"0000", "0001", "0010", "0011",
"0100", "0101", "0110", "0111",
"1000", "1001", "1010", "1011",
"1100", "1101", "1110", "1111",
};
int nibble;
int nibble_value;
int nibble_size;
int zero = 1;
for (nibble = 0; nibble < (sizeof (uint64_t) * (BYTE_SIZE / NIBBLE_SIZE)); nibble++) {
nibble_value = value >> ((sizeof (uint64_t) * BYTE_SIZE) - NIBBLE_SIZE);
if (zero) {
if (nibble_value > 0) {
zero = 0;
nibble_size = strlen(nibbles_start[nibble_value]);
memcpy (binary, nibbles_start[nibble_value], nibble_size);
binary += nibble_size;
}
} else {
memcpy (binary, nibbles[nibble_value], NIBBLE_SIZE);
binary += NIBBLE_SIZE;
}
value <<= NIBBLE_SIZE;
}
/* Add a '0' if the value was null */
if (zero) {
binary[0] = '0';
binary ++;
}
/* Add a null value at the end of the string */
binary[0] = '\0';
}
#if defined(ENABLE_VCD_FIFO)
inline static uint32_t vcd_get_write_index(void)
{
uint32_t write_index;
uint32_t read_index;
/* Get current write index and increment it (atomic operation) */
write_index = __sync_fetch_and_add(&vcd_fifo.write_index, 1);
/* Wrap index */
write_index &= VCD_FIFO_MASK;
/* Check FIFO overflow (increase VCD_FIFO_NB_ELEMENTS if this assert is triggered) */
DevCheck((read_index = vcd_fifo.read_index, ((write_index + 1) & VCD_FIFO_MASK) != read_index), write_index, read_index, VCD_FIFO_NB_ELEMENTS);
return write_index;
}
void *vcd_dumper_thread_rt(void *args)
{
vcd_queue_user_data_t *data;
char binary_string[(sizeof (uint64_t) * BYTE_SIZE) + 1];
struct sched_param sched_param;
uint32_t data_ready_wait;
# if defined(ENABLE_ITTI)
signal_mask();
# endif
sched_param.sched_priority = sched_get_priority_min(SCHED_FIFO) + 1;
sched_setscheduler(0, SCHED_FIFO, &sched_param);
while(1) {
if (vcd_fifo.read_index == (vcd_fifo.write_index & VCD_FIFO_MASK)) {
/* No element -> sleep a while */
usleep(VCD_POLL_DELAY);
} else {
data = &vcd_fifo.user_data[vcd_fifo.read_index];
data_ready_wait = 0;
while (data->module == VCD_SIGNAL_DUMPER_MODULE_FREE) {
/* Check wait delay (increase VCD_MAX_WAIT_DELAY if this assert is triggered and that no thread is locked) */
DevCheck(data_ready_wait < VCD_MAX_WAIT_DELAY, data_ready_wait, VCD_MAX_WAIT_DELAY, 0);
/* data is not yet ready, wait for it to be completed */
data_ready_wait += VCD_POLL_DELAY;
usleep(VCD_POLL_DELAY);
}
switch (data->module) {
case VCD_SIGNAL_DUMPER_MODULE_VARIABLES:
if (vcd_fd != NULL) {
int variable_name;
variable_name = (int)data->data.variable.variable_name;
fprintf(vcd_fd, "#%llu\n", data->time);
/* Set variable to value */
uint64_to_binary(data->data.variable.value, binary_string);
fprintf(vcd_fd, "b%s %s_w\n", binary_string,
eurecomVariablesNames[variable_name]);
}
break;
case VCD_SIGNAL_DUMPER_MODULE_FUNCTIONS:
if (vcd_fd != NULL) {
int function_name;
function_name = (int)data->data.function.function_name;
fprintf(vcd_fd, "#%llu\n", data->time);
/* Check if we are entering or leaving the function ( 0 = leaving, 1 = entering) */
if (data->data.function.in_out == VCD_FUNCTION_IN)
/* Set event to 1 */
fprintf(vcd_fd, "1%s_w\n", eurecomFunctionsNames[function_name]);
else
fprintf(vcd_fd, "0%s_w\n", eurecomFunctionsNames[function_name]);
fflush(vcd_fd);
}
break;
default:
DevParam(data->module, 0, 0);
break;
}
data->module = VCD_SIGNAL_DUMPER_MODULE_FREE;
vcd_fifo.read_index = (vcd_fifo.read_index + 1) & VCD_FIFO_MASK;
}
}
return NULL;
}
#endif
void vcd_signal_dumper_init(char *filename)
{
if (ouput_vcd) {
// char filename[] = "/tmp/openair_vcd_dump.vcd";
if ((vcd_fd = fopen(filename, "w+")) == NULL) {
perror("vcd_signal_dumper_init: cannot open file");
return;
}
#if defined(ENABLE_USE_CPU_EXECUTION_TIME)
clock_gettime(CLOCK_MONOTONIC, &g_time_start);
#endif
vcd_signal_dumper_create_header();
#if defined(ENABLE_VCD_FIFO)
vcd_fifo.write_index = 0;
vcd_fifo.read_index = 0;
fprintf(stderr, "[VCD] Creating dumper thread\n");
if (pthread_create(&vcd_dumper_thread, NULL, vcd_dumper_thread_rt, NULL) < 0) {
fprintf(stderr, "vcd_signal_dumper_init: Failed to create thread: %s\n",
strerror(errno));
ouput_vcd = 0;
return;
}
#endif
}
}
void vcd_signal_dumper_close(void)
{
if (ouput_vcd) {
#if defined(ENABLE_VCD_FIFO)
#else
if (vcd_fd != NULL) {
fclose(vcd_fd);
vcd_fd = NULL;
}
#endif
}
}
static inline void vcd_signal_dumper_print_time_since_start(void)
{
if (vcd_fd != NULL) {
#if defined(ENABLE_USE_CPU_EXECUTION_TIME)
struct timespec time;
long long unsigned int nanosecondsSinceStart;
long long unsigned int secondsSinceStart;
clock_gettime(CLOCK_MONOTONIC, &time);
/* Get current execution time in nanoseconds */
nanosecondsSinceStart = (long long unsigned int)((time.tv_nsec - g_time_start.tv_nsec));
secondsSinceStart = (long long unsigned int)time.tv_sec - (long long unsigned int)g_time_start.tv_sec;
/* Write time in nanoseconds */
fprintf(vcd_fd, "#%llu\n", nanosecondsSinceStart + (secondsSinceStart * 1000000000UL));
#endif
}
}
static inline unsigned long long int vcd_get_time(void)
{
#if defined(ENABLE_USE_CPU_EXECUTION_TIME)
struct timespec time;
clock_gettime(CLOCK_MONOTONIC, &time);
return (long long unsigned int)((time.tv_nsec - g_time_start.tv_nsec)) +
((long long unsigned int)time.tv_sec - (long long unsigned int)g_time_start.tv_sec) * 1000000000UL;
#endif
}
void vcd_signal_dumper_create_header(void)
{
if (ouput_vcd) {
struct tm *pDate;
time_t intps;
intps = time(NULL);
pDate = localtime(&intps);
if (vcd_fd != NULL) {
int i, j;
fprintf(vcd_fd, "$date\n\t%s$end\n", asctime(pDate));
// Display version
fprintf(vcd_fd, "$version\n\tVCD plugin ver%d.%d\n$end\n", VCDSIGNALDUMPER_VERSION_MAJOR, VCDSIGNALDUMPER_VERSION_MINOR);
// Init timescale, here = 1ns
fprintf(vcd_fd, "$timescale 1 ns $end\n");
/* Initialize each module definition */
for(i = 0; i < sizeof(vcd_modules) / sizeof(struct vcd_module_s); i++) {
struct vcd_module_s *module;
module = &vcd_modules[i];
fprintf(vcd_fd, "$scope module %s $end\n", module->name);
/* Declare each signal as defined in array */
for (j = 0; j < module->number_of_signals; j++) {
const char *signal_name;
signal_name = module->signals_names[j];
if (VCD_WIRE == module->signal_type) {
fprintf(vcd_fd, "$var wire %d %s_w %s $end\n", module->signal_size, signal_name, signal_name);
} else if (VCD_REAL == module->signal_type) {
fprintf(vcd_fd, "$var real %d %s_r %s $end\n", module->signal_size, signal_name, signal_name);
} else {
// Handle error here
}
}
fprintf(vcd_fd, "$upscope $end\n");
}
/* Init variables and functions to 0 */
fprintf(vcd_fd, "$dumpvars\n");
for(i = 0; i < sizeof(vcd_modules) / sizeof(struct vcd_module_s); i++) {
struct vcd_module_s *module;
module = &vcd_modules[i];
/* Declare each signal as defined in array */
for (j = 0; j < module->number_of_signals; j++) {
const char *signal_name;
signal_name = module->signals_names[j];
if (VCD_WIRE == module->signal_type) {
if (module->signal_size > 1) {
fprintf(vcd_fd, "b0 %s_w $end\n", signal_name);
} else {
fprintf(vcd_fd, "0%s_w $end\n", signal_name);
}
} else if (VCD_REAL == module->signal_type) {
fprintf(vcd_fd, "r0 %s_r $end\n", signal_name);
} else {
// Handle error here
}
}
}
fprintf(vcd_fd, "$end\n");
fprintf(vcd_fd, "$enddefinitions $end\n\n");
//fflush(vcd_fd);
}
}
}
void vcd_signal_dumper_dump_variable_by_name(vcd_signal_dump_variables variable_name,
unsigned long value)
{
DevCheck((0 <= variable_name) && (variable_name < VCD_SIGNAL_DUMPER_VARIABLES_END),
variable_name, VCD_SIGNAL_DUMPER_VARIABLES_END, 0);
if (ouput_vcd) {
#if defined(ENABLE_VCD_FIFO)
uint32_t write_index = vcd_get_write_index();
vcd_fifo.user_data[write_index].time = vcd_get_time();
vcd_fifo.user_data[write_index].data.variable.variable_name = variable_name;
vcd_fifo.user_data[write_index].data.variable.value = value;
vcd_fifo.user_data[write_index].module = VCD_SIGNAL_DUMPER_MODULE_VARIABLES; // Set when all other fields are set to validate the user_data
#else
char binary_string[(sizeof (uint64_t) * BYTE_SIZE) + 1];
if (vcd_fd != NULL) {
vcd_signal_dumper_print_time_since_start();
/* Set variable to value */
uint64_to_binary(value, binary_string);
fprintf(vcd_fd, "b%s %s_w\n", binary_string, eurecomVariablesNames[variable_name]);
//fflush(vcd_fd);
}
#endif
}
}
void vcd_signal_dumper_dump_function_by_name(vcd_signal_dump_functions function_name,
vcd_signal_dump_in_out in_out)
{
DevCheck((0 <= function_name) && (function_name < VCD_SIGNAL_DUMPER_FUNCTIONS_END),
function_name, VCD_SIGNAL_DUMPER_FUNCTIONS_END, 0);
if (ouput_vcd) {
#if defined(ENABLE_VCD_FIFO)
uint32_t write_index = vcd_get_write_index();
vcd_fifo.user_data[write_index].time = vcd_get_time();
vcd_fifo.user_data[write_index].data.function.function_name = function_name;
vcd_fifo.user_data[write_index].data.function.in_out = in_out;
vcd_fifo.user_data[write_index].module = VCD_SIGNAL_DUMPER_MODULE_FUNCTIONS; // Set when all other fields are set to validate the user_data
#else
if (vcd_fd != NULL) {
vcd_signal_dumper_print_time_since_start();
/* Check if we are entering or leaving the function ( 0 = leaving, 1 = entering) */
if (in_out == VCD_FUNCTION_IN)
/* Set event to 1 */
fprintf(vcd_fd, "1%s_w\n", eurecomFunctionsNames[function_name]);
else
fprintf(vcd_fd, "0%s_w\n", eurecomFunctionsNames[function_name]);
//fflush(vcd_fd);
}
#endif
}
}
+460
View File
@@ -0,0 +1,460 @@
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file vcd_signal_dumper.h
* \brief Output functions call to VCD file which is readable by gtkwave.
* \author ROUX Sebastien
* \author S. Roux
* \maintainer: navid nikaein
* \date 2012 - 2104
* \version 0.1
* \company Eurecom
* \email: navid.nikaein@eurecom.fr
* \note
* \warning
*/
#ifndef VCD_SIGNAL_DUMPER_H_
#define VCD_SIGNAL_DUMPER_H_
//#define ENABLE_USE_CPU_EXECUTION_TIME
/* WARNING: if you edit the enums below, update also string definitions in vcd_signal_dumper.c */
typedef enum {
VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_ENB=0,
VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX1_ENB,
VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_ENB,
VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX1_ENB,
VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX0_ENB,
VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX1_ENB,
VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX0_ENB,
VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX1_ENB,
VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU,
VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX1_RU,
VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_RU,
VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX1_RU,
VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX0_RU,
VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX1_RU,
VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX0_RU,
VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX1_RU,
VCD_SIGNAL_DUMPER_VARIABLES_RUNTIME_TX_ENB,
VCD_SIGNAL_DUMPER_VARIABLES_RUNTIME_RX_ENB,
VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_UE,
VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX1_UE,
VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_UE,
VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX1_UE,
VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX0_UE,
VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX1_UE,
VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX0_UE,
VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX1_UE,
VCD_SIGNAL_DUMPER_VARIABLES_UE_RX_OFFSET,
VCD_SIGNAL_DUMPER_VARIABLES_DIFF,
VCD_SIGNAL_DUMPER_VARIABLES_HW_SUBFRAME,
VCD_SIGNAL_DUMPER_VARIABLES_HW_FRAME,
VCD_SIGNAL_DUMPER_VARIABLES_HW_SUBFRAME_RX,
VCD_SIGNAL_DUMPER_VARIABLES_HW_FRAME_RX,
VCD_SIGNAL_DUMPER_VARIABLES_TXCNT,
VCD_SIGNAL_DUMPER_VARIABLES_RXCNT,
VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS,
VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST,
VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS_UE,
VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST_UE,
VCD_SIGNAL_DUMPER_VARIABLES_TRX_WRITE_FLAGS,
VCD_SIGNAL_DUMPER_VARIABLES_TX_TS,
VCD_SIGNAL_DUMPER_VARIABLES_RX_TS,
VCD_SIGNAL_DUMPER_VARIABLES_RX_HWCNT,
VCD_SIGNAL_DUMPER_VARIABLES_RX_LHWCNT,
VCD_SIGNAL_DUMPER_VARIABLES_TX_HWCNT,
VCD_SIGNAL_DUMPER_VARIABLES_TX_LHWCNT,
VCD_SIGNAL_DUMPER_VARIABLES_RX_PCK,
VCD_SIGNAL_DUMPER_VARIABLES_TX_PCK,
VCD_SIGNAL_DUMPER_VARIABLES_RX_SEQ_NUM,
VCD_SIGNAL_DUMPER_VARIABLES_RX_SEQ_NUM_PRV,
VCD_SIGNAL_DUMPER_VARIABLES_TX_SEQ_NUM,
VCD_SIGNAL_DUMPER_VARIABLES_CNT,
VCD_SIGNAL_DUMPER_VARIABLES_DUMMY_DUMP,
VCD_SIGNAL_DUMPER_VARIABLES_ITTI_SEND_MSG,
VCD_SIGNAL_DUMPER_VARIABLES_ITTI_POLL_MSG,
VCD_SIGNAL_DUMPER_VARIABLES_ITTI_RECV_MSG,
VCD_SIGNAL_DUMPER_VARIABLES_ITTI_ALLOC_MSG,
VCD_SIGNAL_DUMPER_VARIABLES_MP_ALLOC,
VCD_SIGNAL_DUMPER_VARIABLES_MP_FREE,
VCD_SIGNAL_DUMPER_VARIABLES_UE_INST_CNT_RX,
VCD_SIGNAL_DUMPER_VARIABLES_UE_INST_CNT_TX,
VCD_SIGNAL_DUMPER_VARIABLES_DCI_INFO,
VCD_SIGNAL_DUMPER_VARIABLES_UE0_BSR,
VCD_SIGNAL_DUMPER_VARIABLES_UE0_BO,
VCD_SIGNAL_DUMPER_VARIABLES_UE0_SCHEDULED,
VCD_SIGNAL_DUMPER_VARIABLES_UE0_TIMING_ADVANCE,
VCD_SIGNAL_DUMPER_VARIABLES_UE0_SR_ENERGY,
VCD_SIGNAL_DUMPER_VARIABLES_UE0_SR_THRES,
VCD_SIGNAL_DUMPER_VARIABLES_UE0_RSSI0,
VCD_SIGNAL_DUMPER_VARIABLES_UE0_RSSI1,
VCD_SIGNAL_DUMPER_VARIABLES_UE0_RSSI2,
VCD_SIGNAL_DUMPER_VARIABLES_UE0_RSSI3,
VCD_SIGNAL_DUMPER_VARIABLES_UE0_RSSI4,
VCD_SIGNAL_DUMPER_VARIABLES_UE0_RSSI5,
VCD_SIGNAL_DUMPER_VARIABLES_UE0_RSSI6,
VCD_SIGNAL_DUMPER_VARIABLES_UE0_RSSI7,
VCD_SIGNAL_DUMPER_VARIABLES_UE0_RES0,
VCD_SIGNAL_DUMPER_VARIABLES_UE0_RES1,
VCD_SIGNAL_DUMPER_VARIABLES_UE0_RES2,
VCD_SIGNAL_DUMPER_VARIABLES_UE0_RES3,
VCD_SIGNAL_DUMPER_VARIABLES_UE0_RES4,
VCD_SIGNAL_DUMPER_VARIABLES_UE0_RES5,
VCD_SIGNAL_DUMPER_VARIABLES_UE0_RES6,
VCD_SIGNAL_DUMPER_VARIABLES_UE0_RES7,
VCD_SIGNAL_DUMPER_VARIABLES_UE0_MCS0,
VCD_SIGNAL_DUMPER_VARIABLES_UE0_MCS1,
VCD_SIGNAL_DUMPER_VARIABLES_UE0_MCS2,
VCD_SIGNAL_DUMPER_VARIABLES_UE0_MCS3,
VCD_SIGNAL_DUMPER_VARIABLES_UE0_MCS4,
VCD_SIGNAL_DUMPER_VARIABLES_UE0_MCS5,
VCD_SIGNAL_DUMPER_VARIABLES_UE0_MCS6,
VCD_SIGNAL_DUMPER_VARIABLES_UE0_MCS7,
VCD_SIGNAL_DUMPER_VARIABLES_UE0_RB0,
VCD_SIGNAL_DUMPER_VARIABLES_UE0_RB1,
VCD_SIGNAL_DUMPER_VARIABLES_UE0_RB2,
VCD_SIGNAL_DUMPER_VARIABLES_UE0_RB3,
VCD_SIGNAL_DUMPER_VARIABLES_UE0_RB4,
VCD_SIGNAL_DUMPER_VARIABLES_UE0_RB5,
VCD_SIGNAL_DUMPER_VARIABLES_UE0_RB6,
VCD_SIGNAL_DUMPER_VARIABLES_UE0_RB7,
VCD_SIGNAL_DUMPER_VARIABLES_UE0_ROUND0,
VCD_SIGNAL_DUMPER_VARIABLES_UE0_ROUND1,
VCD_SIGNAL_DUMPER_VARIABLES_UE0_ROUND2,
VCD_SIGNAL_DUMPER_VARIABLES_UE0_ROUND3,
VCD_SIGNAL_DUMPER_VARIABLES_UE0_ROUND4,
VCD_SIGNAL_DUMPER_VARIABLES_UE0_ROUND5,
VCD_SIGNAL_DUMPER_VARIABLES_UE0_ROUND6,
VCD_SIGNAL_DUMPER_VARIABLES_UE0_ROUND7,
VCD_SIGNAL_DUMPER_VARIABLES_UE0_SFN0,
VCD_SIGNAL_DUMPER_VARIABLES_UE0_SFN1,
VCD_SIGNAL_DUMPER_VARIABLES_UE0_SFN2,
VCD_SIGNAL_DUMPER_VARIABLES_UE0_SFN3,
VCD_SIGNAL_DUMPER_VARIABLES_UE0_SFN4,
VCD_SIGNAL_DUMPER_VARIABLES_UE0_SFN5,
VCD_SIGNAL_DUMPER_VARIABLES_UE0_SFN6,
VCD_SIGNAL_DUMPER_VARIABLES_UE0_SFN7,
VCD_SIGNAL_DUMPER_VARIABLES_SEND_IF4_SYMBOL,
VCD_SIGNAL_DUMPER_VARIABLES_RECV_IF4_SYMBOL,
VCD_SIGNAL_DUMPER_VARIABLES_SEND_IF5_PKT_ID,
VCD_SIGNAL_DUMPER_VARIABLES_RECV_IF5_PKT_ID,
VCD_SIGNAL_DUMPER_VARIABLES_UE_PDCP_FLUSH_SIZE,
VCD_SIGNAL_DUMPER_VARIABLES_UE_PDCP_FLUSH_ERR,
VCD_SIGNAL_DUMPER_VARIABLES_UE0_TRX_READ_NS,
VCD_SIGNAL_DUMPER_VARIABLES_UE0_TRX_WRITE_NS,
VCD_SIGNAL_DUMPER_VARIABLES_UE0_TRX_READ_NS_MISSING,
VCD_SIGNAL_DUMPER_VARIABLES_UE0_TRX_WRITE_NS_MISSING,
VCD_SIGNAL_DUMPER_VARIABLES_CPUID_ENB_THREAD_RXTX,
VCD_SIGNAL_DUMPER_VARIABLES_CPUID_RU_THREAD,
VCD_SIGNAL_DUMPER_VARIABLES_CPUID_RU_THREAD_TX,
VCD_SIGNAL_DUMPER_VARIABLES_END
} vcd_signal_dump_variables;
typedef enum {
/* softmodem signals */
VCD_SIGNAL_DUMPER_FUNCTIONS_RT_SLEEP=0,
VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ,
VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE,
VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ_UE,
VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_UE,
VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ_IF,
VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_IF,
VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0,
VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX1,
VCD_SIGNAL_DUMPER_FUNCTIONS_UE_THREAD_SYNCH,
VCD_SIGNAL_DUMPER_FUNCTIONS_UE_THREAD_RXTX0,
VCD_SIGNAL_DUMPER_FUNCTIONS_UE_THREAD_RXTX1,
VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ_SF9,
VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_SF9,
VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SIGNAL_COND_RXTX0,
VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SIGNAL_COND_RXTX1,
VCD_SIGNAL_DUMPER_FUNCTIONS_UE_WAIT_COND_RXTX0,
VCD_SIGNAL_DUMPER_FUNCTIONS_UE_WAIT_COND_RXTX1,
VCD_SIGNAL_DUMPER_FUNCTIONS_UE_LOCK_MUTEX_RXTX_FOR_COND_WAIT0,
VCD_SIGNAL_DUMPER_FUNCTIONS_UE_LOCK_MUTEX_RXTX_FOR_COND_WAIT1,
VCD_SIGNAL_DUMPER_FUNCTIONS_UE_LOCK_MUTEX_RXTX_FOR_CNT_DECREMENT0,
VCD_SIGNAL_DUMPER_FUNCTIONS_UE_LOCK_MUTEX_RXTX_FOR_CNT_DECREMENT1,
VCD_SIGNAL_DUMPER_FUNCTIONS_UE_LOCK_MUTEX_RXTX_FOR_CNT_INCREMENT0,
VCD_SIGNAL_DUMPER_FUNCTIONS_UE_LOCK_MUTEX_RXTX_FOR_CNT_INCREMENT1,
/* SIMULATION signals */
VCD_SIGNAL_DUMPER_FUNCTIONS_SIM_DO_DL_SIGNAL,
VCD_SIGNAL_DUMPER_FUNCTIONS_SIM_DO_UL_SIGNAL,
VCD_SIGNAL_DUMPER_FUNCTIONS_SIM_UE_TRX_READ,
/* RRH signals */
VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_TX,
VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_RX,
VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_TRX,
VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_TM,
VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_RX_SLEEP,
VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_TX_SLEEP,
VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_SLEEP,
VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ_RF,
VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_RF,
/* PHY signals */
VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SYNCH,
VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP,
VCD_SIGNAL_DUMPER_FUNCTIONS_UE_RRC_MEASUREMENTS,
VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GAIN_CONTROL,
VCD_SIGNAL_DUMPER_FUNCTIONS_UE_ADJUST_SYNCH,
VCD_SIGNAL_DUMPER_FUNCTIONS_UE_MEASUREMENT_PROCEDURES,
VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PDCCH_PROCEDURES,
VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PBCH_PROCEDURES,
VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_TX,
VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_TX1,
VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPRX,
VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPRX1,
VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM,
VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM1,
VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_PREC,
VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_PREC1,
VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC,
VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC1,
VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX,
VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX,
VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_ULSCH_UESPEC,
VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_PUCCH,
VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_ULSCH_COMMON,
VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_PRACH,
VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_ULSCH_RAR,
VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_LTE,
VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_LTE,
VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_THREAD,
VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_THREAD0,
VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_THREAD1,
VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_THREAD2,
VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_THREAD3,
VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_THREAD4,
VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_THREAD5,
VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_THREAD6,
VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_THREAD7,
VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_DECODING0,
VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_DECODING1,
VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_DECODING2,
VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_DECODING3,
VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_DECODING4,
VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_DECODING5,
VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_DECODING6,
VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_DECODING7,
VCD_SIGNAL_DUMPER_FUNCTIONS_RX_PDCCH,
VCD_SIGNAL_DUMPER_FUNCTIONS_DCI_DECODING,
VCD_SIGNAL_DUMPER_FUNCTIONS_RX_PHICH,
VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC,
VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_SI,
VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_P,
VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_RA,
VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_UE_CONFIG_SIB2,
VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_CONFIG_SIB1_ENB,
VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_CONFIG_SIB2_ENB,
VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_CONFIG_DEDICATED_ENB,
VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_UE_COMPUTE_PRACH,
VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_ULSCH_MSG3,
VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_ULSCH_DECODING0,
VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_ULSCH_DECODING1,
VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_ULSCH_DECODING2,
VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_ULSCH_DECODING3,
VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_ULSCH_DECODING4,
VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_ULSCH_DECODING5,
VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_ULSCH_DECODING6,
VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_ULSCH_DECODING7,
VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_SFGEN,
VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PRACH_RX,
VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_RU_PRACH_RX,
VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PDCCH_TX,
VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_RS_TX,
VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GENERATE_PRACH,
VCD_SIGNAL_DUMPER_FUNCTIONS_UE_ULSCH_MODULATION,
VCD_SIGNAL_DUMPER_FUNCTIONS_UE_ULSCH_ENCODING,
#if 1 // add for debugging losing PDSCH immediately before and after reporting CQI
VCD_SIGNAL_DUMPER_FUNCTIONS_UE_ULSCH_ENCODING_FILL_CQI,
#endif
VCD_SIGNAL_DUMPER_FUNCTIONS_UE_ULSCH_SCRAMBLING,
VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_MODULATION,
VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING,
VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING_W,
VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_SCRAMBLING,
VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_BEAM_PRECODING,
VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_OFDM_MODULATION,
/* MAC signals */
VCD_SIGNAL_DUMPER_FUNCTIONS_MACPHY_INIT,
VCD_SIGNAL_DUMPER_FUNCTIONS_MACPHY_EXIT,
VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ULSCH_SCHEDULER,
VCD_SIGNAL_DUMPER_FUNCTIONS_FILL_RAR,
VCD_SIGNAL_DUMPER_FUNCTIONS_TERMINATE_RA_PROC,
VCD_SIGNAL_DUMPER_FUNCTIONS_INITIATE_RA_PROC,
VCD_SIGNAL_DUMPER_FUNCTIONS_CANCEL_RA_PROC,
VCD_SIGNAL_DUMPER_FUNCTIONS_GET_DCI_SDU,
VCD_SIGNAL_DUMPER_FUNCTIONS_GET_DLSCH_SDU,
VCD_SIGNAL_DUMPER_FUNCTIONS_RX_SDU,
VCD_SIGNAL_DUMPER_FUNCTIONS_MRBCH_PHY_SYNC_FAILURE,
VCD_SIGNAL_DUMPER_FUNCTIONS_SR_INDICATION,
VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_PREPROCESSOR,
VCD_SIGNAL_DUMPER_FUNCTIONS_SCHEDULE_DLSCH, // schedule_ue_spec
VCD_SIGNAL_DUMPER_FUNCTIONS_FILL_DLSCH_DCI,
VCD_SIGNAL_DUMPER_FUNCTIONS_OUT_OF_SYNC_IND,
VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_SI,
VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_PCCH,
VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_CCCH,
VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_BCCH,
VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_SDU,
VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GET_SDU,
VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GET_RACH,
VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PROCESS_RAR,
VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SCHEDULER,
VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GET_SR,
VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_MCH_SDU,
/* RLC signals */
VCD_SIGNAL_DUMPER_FUNCTIONS_RLC_DATA_REQ,
// VCD_SIGNAL_DUMPER_FUNCTIONS_RLC_DATA_IND,
VCD_SIGNAL_DUMPER_FUNCTIONS_MAC_RLC_STATUS_IND,
VCD_SIGNAL_DUMPER_FUNCTIONS_MAC_RLC_DATA_REQ,
VCD_SIGNAL_DUMPER_FUNCTIONS_MAC_RLC_DATA_IND,
VCD_SIGNAL_DUMPER_FUNCTIONS_RLC_UM_TRY_REASSEMBLY,
VCD_SIGNAL_DUMPER_FUNCTIONS_RLC_UM_CHECK_TIMER_DAR_TIME_OUT,
VCD_SIGNAL_DUMPER_FUNCTIONS_RLC_UM_RECEIVE_PROCESS_DAR,
/* PDCP signals */
VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_RUN,
VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,
VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,
VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_APPLY_SECURITY,
VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_VALIDATE_SECURITY,
VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_FIFO_READ,
VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_FIFO_READ_BUFFER,
VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_FIFO_FLUSH,
VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_FIFO_FLUSH_BUFFER,
/* RRC signals */
VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX,
VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_MAC_CONFIG,
VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_UE_DECODE_SIB1,
VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_UE_DECODE_SI,
/* GTPV1U signals */
VCD_SIGNAL_DUMPER_FUNCTIONS_GTPV1U_ENB_TASK,
VCD_SIGNAL_DUMPER_FUNCTIONS_GTPV1U_PROCESS_UDP_REQ,
VCD_SIGNAL_DUMPER_FUNCTIONS_GTPV1U_PROCESS_TUNNEL_DATA_REQ,
/* UDP signals */
VCD_SIGNAL_DUMPER_FUNCTIONS_UDP_ENB_TASK,
/* MISC signals */
VCD_SIGNAL_DUMPER_FUNCTIONS_EMU_TRANSPORT,
VCD_SIGNAL_DUMPER_FUNCTIONS_LOG_RECORD,
VCD_SIGNAL_DUMPER_FUNCTIONS_ITTI_ENQUEUE_MESSAGE,
VCD_SIGNAL_DUMPER_FUNCTIONS_ITTI_DUMP_ENQUEUE_MESSAGE,
VCD_SIGNAL_DUMPER_FUNCTIONS_ITTI_DUMP_ENQUEUE_MESSAGE_MALLOC,
VCD_SIGNAL_DUMPER_FUNCTIONS_ITTI_RELAY_THREAD,
VCD_SIGNAL_DUMPER_FUNCTIONS_TEST,
/* IF4/IF5 signals */
VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4,
VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4,
VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5,
VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF5,
VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_COMPR_IF,
VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_DECOMPR_IF,
VCD_SIGNAL_DUMPER_FUNCTIONS_NFAPI,
VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_PCFICH,
VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_DCI0,
VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_DLSCH,
VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_PHICH,
VCD_SIGNAL_DUMPER_FUNCTIONS_PDCCH_SCRAMBLING,
VCD_SIGNAL_DUMPER_FUNCTIONS_PDCCH_MODULATION,
VCD_SIGNAL_DUMPER_FUNCTIONS_PDCCH_INTERLEAVING,
VCD_SIGNAL_DUMPER_FUNCTIONS_PDCCH_TX,
VCD_SIGNAL_DUMPER_FUNCTIONS_END
} vcd_signal_dump_functions;
typedef enum {
VCD_SIGNAL_DUMPER_MODULE_FREE = 0,
VCD_SIGNAL_DUMPER_MODULE_VARIABLES,
VCD_SIGNAL_DUMPER_MODULE_FUNCTIONS,
// VCD_SIGNAL_DUMPER_MODULE_UE_PROCEDURES_FUNCTIONS,
} vcd_signal_dumper_modules;
typedef enum {
VCD_FUNCTION_OUT,
VCD_FUNCTION_IN,
VCD_FUNCTION_LAST,
} vcd_signal_dump_in_out;
typedef enum {
VCD_REAL, // REAL = variable
VCD_WIRE, // WIRE = Function
} vcd_signal_type;
/*!
* \brief Init function for the vcd dumper.
* @param None
*/
void vcd_signal_dumper_init(char* filename);
/*!
* \brief Close file descriptor.
* @param None
*/
void vcd_signal_dumper_close(void);
/*!
* \brief Create header for VCD file.
* @param None
*/
void vcd_signal_dumper_create_header(void);
/*!
* \brief Dump state of a variable
* @param Name of the variable to dump (see the corresponding enum)
* @param Value of the variable to dump (type: unsigned long)
*/
void vcd_signal_dumper_dump_variable_by_name(vcd_signal_dump_variables variable_name,
unsigned long value);
/*!
* \brief Dump function usage
* @param Name Function name to dump (see the corresponding enum)
* @param State: either VCD_FUNCTION_START or VCD_FUNCTION_END
*/
void vcd_signal_dumper_dump_function_by_name(vcd_signal_dump_functions function_name,
vcd_signal_dump_in_out function_in_out);
extern int ouput_vcd;
#if T_TRACER
#include "T.h"
#define VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(var, val) T_VCD_VARIABLE(var, val)
#define VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(var, val) T_VCD_FUNCTION(var, val)
#else
#define VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(var, val)
#define VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(var, val)
#endif /* T_TRACER */
#endif /* !defined (VCD_SIGNAL_DUMPER_H_) */
+1
View File
@@ -15,4 +15,5 @@ tracer/to_vcd
tracer/extract_input_subframe
tracer/extract_output_subframe
tracer/extract
tracer/multi
tracee/tracee
+12 -3
View File
@@ -13,11 +13,20 @@ $(GENIDS): $(GENIDS_OBJS)
$(CC) $(CFLAGS) -c -o $@ $<
T_messages.txt.h: T_messages.txt
xxd -i T_messages.txt > T_messages.txt.h
xxd -i T_messages.txt T_messages.txt.h
T_IDs.h: $(GENIDS) T_messages.txt
./$(GENIDS) T_messages.txt T_IDs.h
check_vcd:
gcc -Wall -I. -I.. -I../itti -Itracer -o _check_vcd check_vcd.c tracer/database.c tracer/utils.c -lm -pthread
./_check_vcd || (rm -f ./_check_vcd ./T_IDs.h ./T_messages.txt.h && false)
rm -f ./_check_vcd
.PHONY: check_vcd
clean:
rm -f *.o $(GENIDS) core T_IDs.h T_messages.txt.h
cd tracer && make clean
rm -f *.o $(GENIDS) core T_IDs.h T_messages.txt.h _check_vcd
cleanall: clean
cd tracer && $(MAKE) clean
+50 -13
View File
@@ -9,6 +9,8 @@
#include <fcntl.h>
#include <sys/socket.h>
#include "common/config/config_userapi.h"
#define QUIT(x) do { \
printf("T tracer: QUIT: %s\n", x); \
exit(1); \
@@ -17,6 +19,7 @@
/* array used to activate/disactivate a log */
static int T_IDs[T_NUMBER_OF_IDS];
int *T_active = T_IDs;
int T_stdout;
static int T_socket;
@@ -28,6 +31,12 @@ volatile int _T_freelist_head;
volatile int *T_freelist_head = &_T_freelist_head;
T_cache_t *T_cache;
#if BASIC_SIMULATOR
/* global variables used by T_GET_SLOT, see in T.h */
volatile uint64_t T_next_id;
volatile uint64_t T_active_id;
#endif
static void get_message(int s)
{
char t;
@@ -88,7 +97,7 @@ static void new_thread(void *(*f)(void *), void *data)
/* defined in local_tracer.c */
void T_local_tracer_main(int remote_port, int wait_for_tracer,
int local_socket);
int local_socket, void *shm_array);
/* We monitor the tracee and the local tracer processes.
* When one dies we forcefully kill the other.
@@ -111,18 +120,31 @@ void T_init(int remote_port, int wait_for_tracer, int dont_fork)
{
int socket_pair[2];
int s;
int T_shm_fd;
int child1, child2;
int i;
if (socketpair(AF_UNIX, SOCK_STREAM, 0, socket_pair))
{ perror("socketpair"); abort(); }
/* setup shared memory */
T_cache = mmap(NULL, T_CACHE_SIZE * sizeof(T_cache_t),
PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
if (T_cache == MAP_FAILED)
{ perror("mmap"); abort(); }
/* let's garbage the memory to catch some potential problems
* (think multiprocessor sync issues, barriers, etc.)
*/
memset(T_cache, 0x55, T_CACHE_SIZE * sizeof(T_cache_t));
for (i = 0; i < T_CACHE_SIZE; i++) T_cache[i].busy = 0;
/* child1 runs the local tracer and child2 (or main) runs the tracee */
child1 = fork(); if (child1 == -1) abort();
if (child1 == 0) {
close(socket_pair[1]);
T_local_tracer_main(remote_port, wait_for_tracer, socket_pair[0]);
T_local_tracer_main(remote_port, wait_for_tracer, socket_pair[0],
T_cache);
exit(0);
}
close(socket_pair[0]);
@@ -131,6 +153,7 @@ void T_init(int remote_port, int wait_for_tracer, int dont_fork)
child2 = fork(); if (child2 == -1) abort();
if (child2 != 0) {
close(socket_pair[1]);
munmap(T_cache, T_CACHE_SIZE * sizeof(T_cache_t));
monitor_and_kill(child1, child2);
}
}
@@ -141,15 +164,29 @@ void T_init(int remote_port, int wait_for_tracer, int dont_fork)
T_socket = s;
/* setup shared memory */
T_shm_fd = shm_open(T_SHM_FILENAME, O_RDWR /*| O_SYNC*/, 0666);
shm_unlink(T_SHM_FILENAME);
if (T_shm_fd == -1) { perror(T_SHM_FILENAME); abort(); }
T_cache = mmap(NULL, T_CACHE_SIZE * sizeof(T_cache_t),
PROT_READ | PROT_WRITE, MAP_SHARED, T_shm_fd, 0);
if (T_cache == NULL)
{ perror(T_SHM_FILENAME); abort(); }
close(T_shm_fd);
new_thread(T_receive_thread, NULL);
}
void T_Config_Init(void)
{
int T_port; /* by default we wait for the tracer */
int T_nowait; /* default port to listen to to wait for the tracer */
int T_dont_fork; /* default is to fork, see 'T_init' to understand */
paramdef_t ttraceparams[] = CMDLINE_TTRACEPARAMS_DESC;
/* for a cleaner config file, TTracer params should be defined in a
* specific section...
*/
config_get(ttraceparams,
sizeof(ttraceparams) / sizeof(paramdef_t),
TTRACER_CONFIG_PREFIX);
/* compatibility: look for TTracer command line options in root section */
config_process_cmdline(ttraceparams,
sizeof(ttraceparams) / sizeof(paramdef_t),
NULL);
if (T_stdout == 0)
T_init(T_port, 1-T_nowait, T_dont_fork);
}
+63 -50
View File
@@ -14,6 +14,7 @@
/* T message IDs */
#include "T_IDs.h"
#define T_ACTIVE_STDOUT 2
/* known type - this is where you add new types */
#define T_INT(x) int, (x)
@@ -94,12 +95,12 @@ struct T_header;
#define T_ID(x) ((struct T_header *)(uintptr_t)(x))
/* T macro tricks */
extern int T_stdout;
#define TN(...) TN_N(__VA_ARGS__,33,32,31,30,29,28,27,26,25,24,23,22,21,\
20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)(__VA_ARGS__)
#define TN_N(n0,n1,n2,n3,n4,n5,n6,n7,n8,n9,n10,n11,n12,n13,n14,n15,n16,n17,\
n18,n19,n20,n21,n22,n23,n24,n25,n26,n27,n28,n29,n30,n31,n32,n,...) T##n
#define T(...) TN(__VA_ARGS__)
#define T(...) do { if (T_stdout == 0) TN(__VA_ARGS__); } while (0)
/* type used to send arbitrary buffer data */
typedef struct {
@@ -109,16 +110,52 @@ typedef struct {
extern volatile int *T_freelist_head;
extern T_cache_t *T_cache;
extern int *T_active;
/* When running the basic simulator, we may fill the T cache too fast.
* Let's serialize write accesses to the T cache. For that, we use a
* 'ticket' mechanism. To acquire a T slot the caller needs to own the
* current active ticket. We also wait for the slot to be free if
* it is already in use.
*/
#if BASIC_SIMULATOR
# define T_GET_SLOT \
do { \
extern volatile uint64_t T_next_id; \
extern volatile uint64_t T_active_id; \
uint64_t id; \
/* get a ticket */ \
id = __sync_fetch_and_add(&T_next_id, 1); \
/* wait for our turn */ \
while (id != __sync_fetch_and_add(&T_active_id, 0)) /* busy wait */; \
/* this is our turn, try to acquire the slot until it's free */ \
do { \
T_LOCAL_busy = __sync_fetch_and_or(&T_cache[T_LOCAL_slot].busy, 0x01); \
if (T_LOCAL_busy & 0x01) usleep(100); \
} while (T_LOCAL_busy & 0x01); \
/* check that there are still some tickets */ \
if (__sync_fetch_and_add(&T_active_id, 0) == 0xffffffffffffffff) { \
printf("T: reached the end of times, bye...\n"); \
abort(); \
} \
/* free our ticket, which signals the next waiter that it's its turn */ \
(void)__sync_fetch_and_add(&T_active_id, 1); \
} while (0)
#else
# define T_GET_SLOT \
T_LOCAL_busy = __sync_fetch_and_or(&T_cache[T_LOCAL_slot].busy, 0x01);
#endif
/* used at header of Tn, allocates buffer */
#define T_LOCAL_DATA \
char *T_LOCAL_buf; \
int T_LOCAL_size = 0; \
int T_LOCAL_slot; \
int T_LOCAL_busy; \
T_LOCAL_slot = __sync_fetch_and_add(T_freelist_head, 1) \
& (T_CACHE_SIZE - 1); \
(void)__sync_fetch_and_and(T_freelist_head, T_CACHE_SIZE - 1); \
if (T_cache[T_LOCAL_slot].busy) { \
T_GET_SLOT; \
if (T_LOCAL_busy & 0x01) { \
printf("%s:%d:%s: T cache is full - consider increasing its size\n", \
__FILE__, __LINE__, __FUNCTION__); \
abort(); \
@@ -130,7 +167,7 @@ extern T_cache_t *T_cache;
#define T_COMMIT() \
T_cache[T_LOCAL_slot].length = T_LOCAL_size; \
__sync_synchronize(); \
T_cache[T_LOCAL_slot].busy = 1; \
(void)__sync_fetch_and_or(&T_cache[T_LOCAL_slot].busy, 0x02);
#define T_CHECK_SIZE(len, argnum) \
if (T_LOCAL_size + (len) > T_BUFFER_MAX) { \
@@ -140,50 +177,6 @@ extern T_cache_t *T_cache;
abort(); \
}
#if 0
#define T_PUT(type, var, argnum) \
do { \
if (T_LOCAL_size + sizeof(var) > T_BUFFER_MAX) { \
printf("%s:%d:%s: cannot put argument %d in T macro, not enough space" \
", consider increasing T_BUFFER_MAX (%d)\n", \
__FILE__, __LINE__, __FUNCTION__, argnum, T_BUFFER_MAX); \
abort(); \
} \
memcpy(T_LOCAL_buf + T_LOCAL_size, &var, sizeof(var)); \
T_LOCAL_size += sizeof(var); \
} while (0)
#endif
#if 0
#define T_PROCESS(x, argnum) \
do { \
T_PUT(typeof(x), x, argnum); \
} while (0)
#endif
#if 0
#define T_PROCESS(x, argnum) \
do { \
if (__builtin_types_compatible_p(typeof(x), int)) \
{ T_PUT(int, (intptr_t)(x), argnum); printf("int\n"); } \
else if (__builtin_types_compatible_p(typeof(x), short)) \
{ T_PUT(short, (intptr_t)(x), argnum); printf("short\n"); } \
else if (__builtin_types_compatible_p(typeof(x), float)) \
{ T_PUT(float, (x), argnum); printf("float\n"); } \
else if (__builtin_types_compatible_p(typeof(x), char *)) \
{ T_PUT(char *, (char *)(intptr_t)(x), argnum); printf("char *\n"); } \
else if (__builtin_types_compatible_p(typeof(x), float *)) \
{ T_PUT(float *, (float *)(intptr_t)(x), argnum); printf("float *\n"); } \
else if (__builtin_types_compatible_p(typeof(x), void *)) \
{ T_PUT(void *, (void *)(intptr_t)(x), argnum); printf("void *\n"); } \
else { \
printf("%s:%d:%s: unsupported type for argument %d in T macro\n", \
__FILE__, __LINE__, __FUNCTION__, argnum); \
abort(); \
} \
} while (0)
#endif
/* we have 4 versions of T_HEADER:
* - bad quality C++ version with time
* - good quality C version with time
@@ -597,10 +590,30 @@ extern T_cache_t *T_cache;
} \
} while (0)
extern int *T_active;
#define CONFIG_HLP_TPORT "tracer port\n"
#define CONFIG_HLP_NOTWAIT "don't wait for tracer, start immediately\n"
#define CONFIG_HLP_TNOFORK "to ease debugging with gdb\n"
#define CONFIG_HLP_STDOUT "print log messges on console\n"
#define TTRACER_CONFIG_PREFIX "TTracer"
/*------------------------------------------------------------------------------------------------------------------------------------------*/
/* configuration parameters for TTRACE utility */
/* optname helpstr paramflags XXXptr defXXXval type numelt */
/*------------------------------------------------------------------------------------------------------------------------------------------*/
#define CMDLINE_TTRACEPARAMS_DESC { \
{"T_port", CONFIG_HLP_TPORT, 0, iptr:&T_port, defintval:2021, TYPE_INT, 0}, \
{"T_nowait", CONFIG_HLP_NOTWAIT, PARAMFLAG_BOOL, iptr:&T_nowait, defintval:0, TYPE_INT, 0}, \
{"T_dont_fork", CONFIG_HLP_TNOFORK, PARAMFLAG_BOOL, iptr:&T_dont_fork, defintval:0, TYPE_INT, 0}, \
{"T_stdout", CONFIG_HLP_STDOUT, PARAMFLAG_BOOL, iptr:&T_stdout, defintval:1, TYPE_INT, 0}, \
}
/* log on stdout */
void T_init(int remote_port, int wait_for_tracer, int dont_fork);
void T_Config_Init(void);
#else /* T_TRACER */
/* if T_TRACER is not defined or is 0, the T is deactivated */
+18 -6
View File
@@ -8,10 +8,20 @@
#define T_MAX_ARGS 16
/* maximum size of a message - increase if needed */
#define T_BUFFER_MAX (1024*64)
#if BASIC_SIMULATOR
/* let's have 100 RBs functional for the basic simulator */
# define T_BUFFER_MAX (1024*64*2)
#else
# define T_BUFFER_MAX (1024*64)
#endif
/* size of the local cache for messages (must be pow(2,something)) */
#define T_CACHE_SIZE (8192 * 2)
#if BASIC_SIMULATOR
/* we don't need much space for the basic simulator */
# define T_CACHE_SIZE 1024
#else
# define T_CACHE_SIZE (8192 * 2)
#endif
/* maximum number of bytes a message can contain */
#ifdef T_SEND_TIME
@@ -21,18 +31,20 @@
#endif
typedef struct {
/* 'busy' is a bit field
* bit 0: 1 means that slot is acquired by writer
* bit 1: 1 means that slot is ready for consumption
*/
volatile int busy;
char buffer[T_BUFFER_MAX];
int length;
} T_cache_t;
#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 187
#define VCD_NUM_FUNCTIONS 190
/* number of VCD variables (to be kept up to date! see in T_messages.txt) */
#define VCD_NUM_VARIABLES 131
#define VCD_NUM_VARIABLES 128
/* 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)
File diff suppressed because it is too large Load Diff
+249
View File
@@ -0,0 +1,249 @@
/*
* To disable the checks done by this program, see below at the beginning
* of the function 'main'.
*/
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include "database.h"
#define T_TRACER 1
#include "T.h"
/* VCD specific defines and includes
* If the codebase changes, it may need to be updated
*/
#define ENB_MODE
#define ENABLE_USE_CPU_EXECUTION_TIME
#include "../LOG/vcd_signal_dumper.c"
void err(char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
void err(char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
printf("\x1b[31m");
printf("error: ");
vprintf(fmt, ap);
printf("\n"
"\x1b[33m\n"
"You probably added a VCD trace (variable or function) but you did not\n"
"update T_messages.txt and/or T_defs.h in common/utils/T/\n"
"\n"
"Be sure to add the new trace to T_messages.txt, at the right place in the\n"
"file. Do not forget to define VCD_NAME with an identical value as found\n"
"in the array eurecomVariablesNames or eurecomFunctionsNames.\n"
"\n"
"Be sure to update VCD_NUM_FUNCTIONS, VCD_NUM_VARIABLES, VCD_FIRST_FUNCTION\n"
"and VCD_FIRST_VARIABLE in T_defs.h\n"
"\n"
"The same procedure has to be followed when you delete a VCD trace.\n"
"Delete it in T_messages.txt as well and update T_defs.h\n"
"\n"
"You can disable those VCD checks at development time.\n"
"To disable the VCD checks see the file common/utils/T/check_vcd.c\n"
"Do not push any modification that disables the VCD checks to the\n"
"main repository.\n");
printf("\x1b[m\n");
va_end(ap);
exit(1);
}
int main(void)
{
/* to disable the checks done by this program, uncomment the following
* line, ie. remove the leading '//'
*/
//return 0;
void *database = parse_database("T_messages.txt");
int number_of_events;
int first_var = -1;
int last_var;
int first_fun = -1;
int last_fun;
char *prefix;
int prefix_len;
char *name;
char *vcd_name;
int i;
FILE *in;
char *l = NULL;
size_t lsize;
if (database == NULL) err("something wrong with T_messages.txt");
/* check the value of VCD_NUM_FUNCTIONS */
if (VCD_NUM_FUNCTIONS != sizeof(eurecomFunctionsNames) / sizeof(char *))
err("VCD_NUM_FUNCTIONS (%d) must be equal to %zd",
VCD_NUM_FUNCTIONS,
sizeof(eurecomFunctionsNames) / sizeof(char *));
/* check the value of VCD_NUM_VARIABLES */
if (VCD_NUM_VARIABLES != sizeof(eurecomVariablesNames) / sizeof(char *))
err("VCD_NUM_VARIABLES (%d) must be equal to %zd",
VCD_NUM_VARIABLES,
sizeof(eurecomVariablesNames) / sizeof(char *));
number_of_events = number_of_ids(database);
if (number_of_events == 0) err("no event defined in T_messages.txt");
/* T_messages.txt ends with VCD VARIABLES followed by VCD FUNCTIONS
* followed by nothing.
* Let's check.
*/
/* check VCD VARIABLES traces in T_messages.txt */
prefix = "VCD_VARIABLE_";
prefix_len = strlen(prefix);
for (i = 0; i < number_of_events; i++) {
name = event_name_from_id(database, i);
if (strncmp(name, prefix, prefix_len)) continue;
first_var = i;
break;
}
if (first_var == -1)
err("no VCD_VARIABLE_ found in T_messages.txt");
for (; i < number_of_events; i++) {
name = event_name_from_id(database, i);
if (strncmp(name, prefix, prefix_len)) break;
}
last_var = i-1;
/* check VCD FUNCTIONS traces in T_messages.txt */
if (i == number_of_events)
err("no VCD_FUNCTION_ found in T_messages.txt");
prefix = "VCD_FUNCTION_";
prefix_len = strlen(prefix);
first_fun = i;
name = event_name_from_id(database, i);
if (strncmp(name, prefix, prefix_len))
err("last VCD_VARIABLE_ not followed by a VCD_FUNCTION_ in T_messages.txt");
for (; i < number_of_events; i++) {
name = event_name_from_id(database, i);
if (strncmp(name, prefix, prefix_len)) break;
}
if (i != number_of_events)
err("T_messages.txt does not end with a VCD_FUNCTION_ trace");
last_fun = i-1;
if (first_var != (unsigned)VCD_FIRST_VARIABLE)
err("VCD_FIRST_VARIABLE is not correct in T_defs.h");
if (first_fun != (unsigned)VCD_FIRST_FUNCTION)
err("VCD_FIRST_FUNCTION is not correct in T_defs.h");
if (last_var-first_var+1 != VCD_NUM_VARIABLES)
err("VCD_NUM_VARIABLES is not correct in T_defs.h");
if (last_fun-first_fun+1 != VCD_NUM_FUNCTIONS)
err("VCD_NUM_FUNCTIONS is not correct in T_defs.h");
/* check that VCD_NAME is identical to
* eurecomVariablesNames[x]/eurecomFunctionsNames[x]
*/
prefix = "VCD_VARIABLE_";
prefix_len = strlen(prefix);
for (i = 0; i < number_of_events; i++) {
name = event_name_from_id(database, i);
if (strncmp(name, prefix, prefix_len)) continue;
vcd_name = event_vcd_name_from_id(database, i);
if (vcd_name == NULL)
err("%s has no VCD_NAME in T_messages.txt", name);
if (strcmp(vcd_name, eurecomVariablesNames[i - first_var]))
err("%s has a wrong VCD_NAME in T_messages.txt", name);
}
prefix = "VCD_FUNCTION_";
prefix_len = strlen(prefix);
for (i = 0; i < number_of_events; i++) {
name = event_name_from_id(database, i);
if (strncmp(name, prefix, prefix_len)) continue;
vcd_name = event_vcd_name_from_id(database, i);
if (vcd_name == NULL)
err("%s has no VCD_NAME in T_messages.txt", name);
if (strcmp(vcd_name, eurecomFunctionsNames[i - first_fun]))
err("%s has a wrong VCD_NAME in T_messages.txt", name);
}
/* check IDs - these checks are difficult because we parse
* common/utils/LOG/vcd_signal_dumper.h which is expected to
* be formatted as is:
* - define vcd_signal_dump_variables then vcd_signal_dump_functions
* - one VCD_XXXX per line starting with two spaces
* followed by ',' or '=' with no space in between
* - no #ifdef / #if is taken into account
* - we require VCD_SIGNAL_DUMPER_VARIABLES_END and
* VCD_SIGNAL_DUMPER_FUNCTIONS_END at the end of each array,
* each on a line of its own with two spaces before and nothing after.
*
* If these checks fail, consider formatting
* common/utils/LOG/vcd_signal_dumper.h as expected here, if
* it makes sense of course. Otherwise, change the code below.
*
* In common/utils/LOG/vcd_signal_dumper.h a valid name is
* either VCD_SIGNAL_DUMPER_VARIABLES_ABC or
* VCD_SIGNAL_DUMPER_FUNCTIONS_XYZ
* and in T_messages.txt the corresponding name has to be
* VCD_VARIABLE_ABC or VCD_FUNCTION_XYZ
*/
i = first_var;
in = fopen("../LOG/vcd_signal_dumper.h", "r");
if (in == NULL) err("could not open ../LOG/vcd_signal_dumper.h");
while (1) {
char *x = " VCD_SIGNAL_DUMPER_VARIABLES_";
ssize_t r;
free(l);
l = NULL;
lsize = 0;
r = getline(&l, &lsize, in);
if (r == -1) break;
if (!strcmp(l, " VCD_SIGNAL_DUMPER_VARIABLES_END\n")) break;
/* remove ',' or '=' if found */
{ char *s=l; while (*s) { if (*s==','||*s=='=') { *s=0; break; } s++; } }
if (strncmp(l, x, strlen(x))) continue;
if (!(i >= first_var && i <= last_var))
err("T_messages.txt is not correct with respect to VCD VARIABLES");
name = event_name_from_id(database, i);
if (strcmp(l+strlen(x), name+strlen("VCD_VARIABLE_")))
err("%s is not correct in T_messages.txt", name);
i++;
}
if (i != last_var + 1) err("VCD VARIABLES wrong in T_messages.txt");
while (1) {
char *x = " VCD_SIGNAL_DUMPER_FUNCTIONS_";
ssize_t r;
free(l);
l = NULL;
lsize = 0;
r = getline(&l, &lsize, in);
if (r == -1) break;
if (!strcmp(l, " VCD_SIGNAL_DUMPER_FUNCTIONS_END\n")) break;
/* remove ',' or '=' if found */
{ char *s=l; while (*s) { if (*s==','||*s=='=') { *s=0; break; } s++; } }
if (strncmp(l, x, strlen(x))) continue;
if (!(i >= first_fun && i <= last_fun))
err("T_messages.txt is not correct with respect to VCD FUNCTIONS");
name = event_name_from_id(database, i);
if (strcmp(l+strlen(x), name+strlen("VCD_FUNCTION_")))
err("%s is not correct in T_messages.txt", name);
i++;
}
fclose(in);
if (i != last_fun + 1) err("VCD FUNCTIONS wrong in T_messages.txt");
return 0;
}
+11 -10
View File
@@ -14,21 +14,21 @@ int cmp(const void *p1, const void *p2)
}
/* return 1 if s was not already known, 0 if it was */
int new_unique_id(char *s)
int new_unique_id(char *s, char *input_file)
{
if (unique_ids_size)
if (bsearch(&s, unique_ids, unique_ids_size, sizeof(char *), cmp) != NULL) {
printf("FATAL: ID %s is not unique\n", s);
printf("error: ID %s is not unique in %s\n", s, input_file);
return 0;
}
if (unique_ids_size == unique_ids_maxsize) {
unique_ids_maxsize += 256;
unique_ids = realloc(unique_ids, unique_ids_maxsize * sizeof(char *));
if (unique_ids == NULL) { printf("out of memory\n"); abort(); }
if (unique_ids == NULL) { printf("erorr: out of memory\n"); abort(); }
}
unique_ids[unique_ids_size] = strdup(s);
if (unique_ids[unique_ids_size] == NULL)
{ printf("out of memory\n"); abort(); }
{ printf("erorr: out of memory\n"); abort(); }
unique_ids_size++;
qsort(unique_ids, unique_ids_size, sizeof(char *), cmp);
return 1;
@@ -43,7 +43,8 @@ void putname(int c)
if (bufname_size == bufname_maxsize) {
bufname_maxsize += 256;
bufname = realloc(bufname, bufname_maxsize);
if (bufname == NULL) { printf("memory allocation error\n"); exit(1); }
if (bufname == NULL)
{ printf("erorr: memory allocation error\n"); exit(1); }
}
bufname[bufname_size] = c;
bufname_size++;
@@ -58,7 +59,8 @@ void putvalue(int c)
if (bufvalue_size == bufvalue_maxsize) {
bufvalue_maxsize += 256;
bufvalue = realloc(bufvalue, bufvalue_maxsize);
if (bufvalue == NULL) { printf("memory allocation error\n"); exit(1); }
if (bufvalue == NULL)
{ printf("error: memory allocation error\n"); exit(1); }
}
bufvalue[bufvalue_size] = c;
bufvalue_size++;
@@ -119,7 +121,7 @@ int main(int n, char **v)
char *in_name;
char *out_name;
if (n != 3) { printf("gimme <source> <dest>\n"); exit(1); }
if (n != 3) { printf("error: gimme <source> <dest>\n"); exit(1); }
n = 0;
@@ -134,14 +136,13 @@ int main(int n, char **v)
while (1) {
get_line(in, &name, &value);
if (name == NULL) break;
printf("name '%s' value '%s'\n", name, value);
if (isspace(value[strlen(value)-1])) {
printf("bad value '%s' (no space at the end please!)\n", value);
printf("error: bad value '%s' (no space at the end please!)\n", value);
unlink(out_name);
exit(1);
}
if (!strcmp(name, "ID")) {
if (!new_unique_id(value)) { unlink(out_name); exit(1); }
if (!new_unique_id(value, in_name)) { unlink(out_name); exit(1); }
fprintf(out, "#define T_%s T_ID(%d)\n", value, n);
n++;
}
+22 -24
View File
@@ -300,6 +300,20 @@ static void forward(void *_forwarder, char *buf, int size)
if (f->tail != NULL) f->tail->next = new;
f->tail = new;
#if BASIC_SIMULATOR
/* When runnng the basic simulator, the tracer may be too slow.
* Let's not take too much memory in the tracee and
* wait if there is too much data to send. 200MB is
* arbitrary.
*/
while (f->memusage > 200 * 1024 * 1024) {
if (pthread_cond_signal(&f->cond)) abort();
if (pthread_mutex_unlock(&f->lock)) abort();
usleep(1000);
if (pthread_mutex_lock(&f->lock)) abort();
}
#endif /* BASIC_SIMULATOR */
f->memusage += size+4;
/* warn every 100MB */
if (f->memusage > f->last_warning_memusage &&
@@ -323,31 +337,11 @@ static void forward(void *_forwarder, char *buf, int size)
static void wait_message(void)
{
while (T_local_cache[T_busylist_head].busy == 0) usleep(1000);
}
static void init_shm(void)
{
int i;
int s = shm_open(T_SHM_FILENAME, O_RDWR | O_CREAT /*| O_SYNC*/, 0666);
if (s == -1) { perror(T_SHM_FILENAME); abort(); }
if (ftruncate(s, T_CACHE_SIZE * sizeof(T_cache_t)))
{ perror(T_SHM_FILENAME); abort(); }
T_local_cache = mmap(NULL, T_CACHE_SIZE * sizeof(T_cache_t),
PROT_READ | PROT_WRITE, MAP_SHARED, s, 0);
if (T_local_cache == NULL)
{ perror(T_SHM_FILENAME); abort(); }
close(s);
/* let's garbage the memory to catch some potential problems
* (think multiprocessor sync issues, barriers, etc.)
*/
memset(T_local_cache, 0x55, T_CACHE_SIZE * sizeof(T_cache_t));
for (i = 0; i < T_CACHE_SIZE; i++) T_local_cache[i].busy = 0;
while ((T_local_cache[T_busylist_head].busy & 0x02) == 0) usleep(1000);
}
void T_local_tracer_main(int remote_port, int wait_for_tracer,
int local_socket)
int local_socket, void *shm_array)
{
int s;
int port = remote_port;
@@ -355,9 +349,13 @@ void T_local_tracer_main(int remote_port, int wait_for_tracer,
void *f;
/* write on a socket fails if the other end is closed and we get SIGPIPE */
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) abort();
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
printf("local tracer received SIGPIPE\n");
abort();
}
T_local_cache = shm_array;
init_shm();
s = local_socket;
if (dont_wait) {
+14 -11
View File
@@ -7,7 +7,7 @@ LIBS=-lm
XLIBS=-lX11 -lpng -lXft
all: record replay extract_config textlog enb ue vcd macpdu2wireshark \
extract_input_subframe extract_output_subframe to_vcd extract
extract_input_subframe extract_output_subframe to_vcd extract multi
record: utils.o record.o database.o config.o
$(CC) $(CFLAGS) -o record $^ $(LIBS)
@@ -57,19 +57,22 @@ macpdu2wireshark: macpdu2wireshark.o database.o utils.o handler.o event.o \
config.o
$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
multi: multi.o utils.o database.o config.o
$(CC) $(CFLAGS) -o multi $^ $(LIBS)
.PHONY: all gui/gui.a view/view.a logger/logger.a filter/filter.a
gui/gui.a:
cd gui && make
cd gui && $(MAKE)
view/view.a:
cd view && make
cd view && $(MAKE)
logger/logger.a:
cd logger && make
cd logger && $(MAKE)
filter/filter.a:
cd filter && make
cd filter && $(MAKE)
%.o: %.c
$(CC) $(CFLAGS) -c -o $@ $<
@@ -77,9 +80,9 @@ filter/filter.a:
clean:
rm -f *.o core tracer_remote textlog enb ue vcd record replay
rm -f extract_config macpdu2wireshark extract_input_subframe
rm -f extract_output_subframe to_vcd extract
cd gui && make clean
cd view && make clean
cd logger && make clean
cd filter && make clean
cd hacks && make clean
rm -f extract_output_subframe to_vcd extract multi
cd gui && $(MAKE) clean
cd view && $(MAKE) clean
cd logger && $(MAKE) clean
cd filter && $(MAKE) clean
cd hacks && $(MAKE) clean
+6
View File
@@ -60,3 +60,9 @@ void verify_config(void)
abort();
}
}
void get_local_config(char **txt, int *len)
{
*txt = local;
*len = local_size;
}
+1
View File
@@ -5,5 +5,6 @@ void clear_remote_config(void);
void append_received_config_chunk(char *buf, int length);
void load_config_file(char *filename);
void verify_config(void);
void get_local_config(char **txt, int *len);
#endif /* _CONFIG_H_ */
+15
View File
@@ -13,6 +13,7 @@ typedef struct {
char **arg_type;
char **arg_name;
int asize;
char *vcd_name;
int id;
} id;
@@ -138,6 +139,7 @@ id *add_id(database *r, char *idname, int i)
r->i[r->isize].arg_type = NULL;
r->i[r->isize].arg_name = NULL;
r->i[r->isize].asize = 0;
r->i[r->isize].vcd_name = NULL;
r->i[r->isize].id = i;
r->isize++;
qsort(r->i, r->isize, sizeof(id), id_cmp);
@@ -224,6 +226,12 @@ void add_desc(id *i, char *desc)
i->desc = strdup(desc); if (i->desc == NULL) abort();
}
void add_vcd_name(id *i, char *vcd_name)
{
if (i == NULL) {printf("ERROR: VCD_NAME line before ID line\n");exit(1);}
i->vcd_name = strdup(vcd_name); if (i->vcd_name == NULL) abort();
}
char *format_get_next_token(char **cur)
{
char *start;
@@ -320,6 +328,7 @@ void *parse_database(char *filename)
if (!strcmp(name, "GROUP")) add_groups(r, last_id, value);
if (!strcmp(name, "DESC")) add_desc(last_id, value);
if (!strcmp(name, "FORMAT")) add_format(last_id, value);
if (!strcmp(name, "VCD_NAME")) add_vcd_name(last_id, value);
}
fclose(in);
@@ -424,6 +433,12 @@ char *event_name_from_id(void *_database, int id)
return d->i[d->id_to_pos[id]].name;
}
char *event_vcd_name_from_id(void *_database, int id)
{
database *d = _database;
return d->i[d->id_to_pos[id]].vcd_name;
}
int event_id_from_name(void *_database, char *name)
{
database *d = _database;
+1
View File
@@ -8,6 +8,7 @@ void list_ids(void *database);
void list_groups(void *database);
void on_off(void *d, char *item, int *a, int onoff);
char *event_name_from_id(void *database, int id);
char *event_vcd_name_from_id(void *_database, int id);
int event_id_from_name(void *database, char *name);
int number_of_ids(void *database);
int database_get_ids(void *database, char ***ids);
+4 -3
View File
@@ -12,7 +12,6 @@
#include "gui/gui.h"
#include "filter/filter.h"
#include "utils.h"
#include "../T_defs.h"
#include "event_selector.h"
#include "openair_logo.h"
#include "config.h"
@@ -875,8 +874,11 @@ int main(int n, char **v)
if (pthread_mutex_init(&enb_data.lock, NULL)) abort();
setup_event_selector(g, database, is_on, is_on_changed, &enb_data);
OBUF ebuf = { osize: 0, omaxsize: 0, obuf: NULL };
restart:
clear_remote_config();
if (enb_data.socket != -1) close(enb_data.socket);
enb_data.socket = connect_to(ip, port);
/* send the first message - activate selected traces */
@@ -884,9 +886,8 @@ restart:
/* read messages */
while (1) {
char v[T_BUFFER_MAX];
event e;
e = get_event(enb_data.socket, v, database);
e = get_event(enb_data.socket, &ebuf, database);
if (e.type == -1) goto restart;
if (pthread_mutex_lock(&enb_data.lock)) abort();
handle_event(h, e);
+11 -5
View File
@@ -6,7 +6,7 @@
#include <stdlib.h>
#include <string.h>
event get_event(int socket, char *event_buffer, void *database)
event get_event(int socket, OBUF *event_buffer, void *database)
{
#ifdef T_SEND_TIME
struct timespec t;
@@ -29,17 +29,23 @@ again:
#endif
if (fullread(socket, &type, sizeof(int)) == -1) goto read_error;
length -= sizeof(int);
if (fullread(socket, event_buffer, length) == -1) goto read_error;
if (event_buffer->omaxsize < length) {
event_buffer->omaxsize = (length + 65535) & ~65535;
event_buffer->obuf = realloc(event_buffer->obuf, event_buffer->omaxsize);
if (event_buffer->obuf == NULL) { printf("out of memory\n"); exit(1); }
}
if (fullread(socket, event_buffer->obuf, length) == -1) goto read_error;
event_buffer->osize = length;
if (type == -1) append_received_config_chunk(event_buffer, length);
if (type == -1) append_received_config_chunk(event_buffer->obuf, length);
if (type == -2) verify_config();
if (type == -1 || type == -2) goto again;
#ifdef T_SEND_TIME
return new_event(t, type, length, event_buffer, database);
return new_event(t, type, length, event_buffer->obuf, database);
#else
return new_event(type, length, event_buffer, database);
return new_event(type, length, event_buffer->obuf, database);
#endif
read_error:
+2 -1
View File
@@ -1,6 +1,7 @@
#ifndef _EVENT_H_
#define _EVENT_H_
#include "utils.h"
#include "../T_defs.h"
#ifdef T_SEND_TIME
#include <time.h>
@@ -37,7 +38,7 @@ typedef struct {
int ecount;
} event;
event get_event(int s, char *v, void *d);
event get_event(int s, OBUF *v, void *d);
#ifdef T_SEND_TIME
event new_event(struct timespec sending_time, int type,
+3 -2
View File
@@ -99,10 +99,11 @@ int main(int n, char **v)
found = 0;
OBUF ebuf = { osize: 0, omaxsize: 0, obuf: NULL };
while (1) {
char v[T_BUFFER_MAX];
event e;
e = get_event(fd, v, database);
e = get_event(fd, &ebuf, database);
if (e.type == -1) break;
if (e.type != input_event_id) continue;
for (i = 0; i < filter_count; i++)
+10 -1
View File
@@ -1,6 +1,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "utils.h"
#include "../T_defs.h"
void usage(void)
@@ -35,14 +36,22 @@ int main(int n, char **v)
in = fopen(input_filename, "r");
if (in == NULL) { perror(input_filename); abort(); }
OBUF ebuf = { osize: 0, omaxsize: 0, obuf: NULL };
while (1) {
int type;
int32_t length;
char v[T_BUFFER_MAX];
char *v;
int vpos = 0;
/* read event from file */
if (fread(&length, 4, 1, in) != 1) break;
if (ebuf.omaxsize < length) {
ebuf.omaxsize = (length + 65535) & ~65535;
ebuf.obuf = realloc(ebuf.obuf, ebuf.omaxsize);
if (ebuf.obuf == NULL) { printf("out of memory\n"); exit(1); }
}
v = ebuf.obuf;
memcpy(v+vpos, &length, 4);
vpos += 4;
#ifdef T_SEND_TIME
@@ -104,11 +104,12 @@ err:
fd = open(file, O_RDONLY);
if (fd == -1) { perror(file); exit(1); }
OBUF ebuf = { osize: 0, omaxsize: 0, obuf: NULL };
/* get wanted frame/subframe */
while (1) {
char v[T_BUFFER_MAX];
event e;
e = get_event(fd, v, database);
e = get_event(fd, &ebuf, database);
if (e.type == -1) break;
if (e.type != input_event_id) continue;
if (verbose)
@@ -116,12 +117,7 @@ err:
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
if (fwrite(e.e[buffer_arg].b, e.e[buffer_arg].bsize, 1, out) != 1)
{ perror(output_file); exit(1); }
processed_subframes++;
@@ -100,10 +100,12 @@ err:
int last_frame = -1;
int last_subframe = -1;
int subframe_written = 0;
OBUF ebuf = { osize: 0, omaxsize: 0, obuf: NULL };
while (1) {
char v[T_BUFFER_MAX];
event e;
e = get_event(fd, v, database);
e = get_event(fd, &ebuf, database);
if (e.type == -1) break;
if (e.type != output_event_id) continue;
if (verbose)
@@ -122,12 +124,6 @@ err:
}
last_frame = frame;
last_subframe = subframe;
#if 0
for (i = 0; i < e.e[buffer_arg].bsize/2; i++) {
short *x = e.e[buffer_arg].b;
x[i] *= 14;
}
#endif
if (verbose)
printf("save output frame %d subframe %d size %d\n",
e.e[frame_arg].i, e.e[subframe_arg].i, e.e[buffer_arg].bsize);
-6
View File
@@ -22,13 +22,7 @@ int main(void)
widget_add_child(g, c1, c2, 0);
plot = new_xy_plot(g, 100, 100, "xy plot test", 30);
#if 0
c2 = new_container(g, HORIZONTAL);
widget_add_child(g, c2, plot, -1);
widget_add_child(g, c1, c2, -1);
#else
widget_add_child(g, c1, plot, -1);
#endif
tlcol = new_color(g, "#ddf");
tl = new_textlist(g, 300, 10, tlcol);
-22
View File
@@ -124,20 +124,6 @@ x_window *x_create_window(x_connection *_x, int width, int height,
XMapWindow(x->d, ret->w);
#if 0
/* wait for window to be mapped */
LOGD("wait for map\n");
while (1) {
XEvent ev;
//XWindowEvent(x->d, ret->w, StructureNotifyMask, &ev);
XWindowEvent(x->d, ret->w, ExposureMask, &ev);
LOGD("got ev %d\n", ev.type);
//if (ev.type == MapNotify) break;
if (ev.type == Expose) break;
}
LOGD("XXX create connection %p window %p (win id %d pixmap %d) w h %d %d\n", x, ret, (int)ret->w, (int)ret->p, width, height);
#endif
return ret;
}
@@ -265,14 +251,6 @@ void x_events(gui *_gui)
ev.xbutton.button, 1);
}
break;
#if 0
case MapNotify:
if ((w = find_x_window(g, ev.xmap.window)) != NULL) {
struct x_window *xw = w->x;
xw->repaint = 1;
}
break;
#endif
default: if (gui_logd) WARN("TODO: X event type %d\n", ev.type); break;
}
}
-159
View File
@@ -7,165 +7,6 @@
#include <string.h>
#include <math.h>
#if 0
/* this version behaves differently when you resize the XY plot. Say
* you increase the size. The old (smaller) view is put at the center
* of the new view. Everything inside keeps the same size/aspect ratio.
* The other version below resizes the old view so that it fully occupies
* the new view. It may introduce aspect ratio changes, but usage seems
* to suggest it's a better behaviour.
*/
static void paint(gui *_gui, widget *_this)
{
struct gui *g = _gui;
struct xy_plot_widget *this = _this;
int wanted_plot_width, allocated_plot_width;
int wanted_plot_height, allocated_plot_height;
float pxsize;
float ticdist;
float tic;
float ticstep;
int k, kmin, kmax;
float allocated_xmin, allocated_xmax;
float allocated_ymin, allocated_ymax;
float center;
int i;
int n;
# define FLIP(v) (-(v) + allocated_plot_height-1)
LOGD("PAINT xy plot xywh %d %d %d %d\n", this->common.x, this->common.y, this->common.width, this->common.height);
//x_draw_rectangle(g->x, g->xwin, 1, this->common.x, this->common.y, this->common.width, this->common.height);
wanted_plot_width = this->wanted_width;
allocated_plot_width = this->common.width - this->vrule_width;
wanted_plot_height = this->wanted_height;
allocated_plot_height = this->common.height - this->label_height * 2;
/* plot zone */
/* TODO: refine height - height of hrule text may be != from label */
x_draw_rectangle(g->x, g->xwin, 1,
this->common.x + this->vrule_width,
this->common.y,
this->common.width - this->vrule_width -1, /* -1 to see right border */
this->common.height - this->label_height * 2);
/* horizontal tics */
pxsize = (this->xmax - this->xmin) / wanted_plot_width;
ticdist = 100;
tic = floor(log10(ticdist * pxsize));
ticstep = powf(10, tic);
center = (this->xmax + this->xmin) / 2;
allocated_xmin = center - ((this->xmax - this->xmin) *
allocated_plot_width / wanted_plot_width) / 2;
allocated_xmax = center + ((this->xmax - this->xmin) *
allocated_plot_width / wanted_plot_width) / 2;
/* adjust tic if too tight */
LOGD("pre x ticstep %g\n", ticstep);
while (1) {
if (ticstep / (allocated_xmax - allocated_xmin)
* (allocated_plot_width - 1) > 40) break;
ticstep *= 2;
}
LOGD("post x ticstep %g\n", ticstep);
LOGD("xmin/max %g %g width wanted allocated %d %d alloc xmin/max %g %g ticstep %g\n", this->xmin, this->xmax, wanted_plot_width, allocated_plot_width, allocated_xmin, allocated_xmax, ticstep);
kmin = ceil(allocated_xmin / ticstep);
kmax = floor(allocated_xmax / ticstep);
for (k = kmin; k <= kmax; k++) {
/*
(k * ticstep - allocated_xmin) / (allocated_max - allocated_xmin) =
(x - 0) / (allocated_plot_width-1 - 0)
*/
char v[64];
int vwidth, dummy;
int x = (k * ticstep - allocated_xmin) /
(allocated_xmax - allocated_xmin) *
(allocated_plot_width - 1);
x_draw_line(g->x, g->xwin, FOREGROUND_COLOR,
this->common.x + this->vrule_width + x,
this->common.y + this->common.height - this->label_height * 2,
this->common.x + this->vrule_width + x,
this->common.y + this->common.height - this->label_height * 2 - 5);
sprintf(v, "%g", k * ticstep);
x_text_get_dimensions(g->x, DEFAULT_FONT, v, &vwidth, &dummy, &dummy);
x_draw_string(g->x, g->xwin, DEFAULT_FONT, FOREGROUND_COLOR,
this->common.x + this->vrule_width + x - vwidth/2,
this->common.y + this->common.height - this->label_height * 2 +
this->label_baseline,
v);
LOGD("tic k %d val %g x %d\n", k, k * ticstep, x);
}
/* vertical tics */
pxsize = (this->ymax - this->ymin) / wanted_plot_height;
ticdist = 30;
tic = floor(log10(ticdist * pxsize));
ticstep = powf(10, tic);
center = (this->ymax + this->ymin) / 2;
allocated_ymin = center - ((this->ymax - this->ymin) *
allocated_plot_height / wanted_plot_height) / 2;
allocated_ymax = center + ((this->ymax - this->ymin) *
allocated_plot_height / wanted_plot_height) / 2;
/* adjust tic if too tight */
LOGD("pre y ticstep %g\n", ticstep);
while (1) {
if (ticstep / (allocated_ymax - allocated_ymin)
* (allocated_plot_height - 1) > 20) break;
ticstep *= 2;
}
LOGD("post y ticstep %g\n", ticstep);
LOGD("ymin/max %g %g height wanted allocated %d %d alloc ymin/max %g %g ticstep %g\n", this->ymin, this->ymax, wanted_plot_height, allocated_plot_height, allocated_ymin, allocated_ymax, ticstep);
kmin = ceil(allocated_ymin / ticstep);
kmax = floor(allocated_ymax / ticstep);
for (k = kmin; k <= kmax; k++) {
char v[64];
int vwidth, dummy;
int y = (k * ticstep - allocated_ymin) /
(allocated_ymax - allocated_ymin) *
(allocated_plot_height - 1);
sprintf(v, "%g", k * ticstep);
x_text_get_dimensions(g->x, DEFAULT_FONT, v, &vwidth, &dummy, &dummy);
x_draw_line(g->x, g->xwin, FOREGROUND_COLOR,
this->common.x + this->vrule_width,
this->common.y + FLIP(y),
this->common.x + this->vrule_width + 5,
this->common.y + FLIP(y));
x_draw_string(g->x, g->xwin, DEFAULT_FONT, FOREGROUND_COLOR,
this->common.x + this->vrule_width - vwidth - 2,
this->common.y + FLIP(y) - this->label_height/2+this->label_baseline,
v);
}
/* label at bottom, in the middle */
x_draw_string(g->x, g->xwin, DEFAULT_FONT, FOREGROUND_COLOR,
this->common.x + (this->common.width - this->label_width) / 2,
this->common.y + this->common.height - this->label_height
+ this->label_baseline,
this->label);
for (n = 0; n < this->nplots; n++) {
/* points */
float ax, bx, ay, by;
ax = (allocated_plot_width-1) / (allocated_xmax - allocated_xmin);
bx = -ax * allocated_xmin;
ay = (allocated_plot_height-1) / (allocated_ymax - allocated_ymin);
by = -ay * allocated_ymin;
for (i = 0; i < this->plots[n].npoints; i++) {
int x, y;
x = ax * this->plots[n].x[i] + bx;
y = ay * this->plots[n].y[i] + by;
if (x >= 0 && x < allocated_plot_width &&
y >= 0 && y < allocated_plot_height)
x_add_point(g->x,
this->common.x + this->vrule_width + x,
this->common.y + FLIP(y));
}
x_plot_points(g->x, g->xwin, this->plots[n].color);
}
}
#endif
static void paint(gui *_gui, widget *_this)
{
struct gui *g = _gui;
@@ -73,17 +73,22 @@ int main(int n, char **v)
socket_send(socket, is_on, number_of_events * sizeof(int)) == -1)
abort();
OBUF ebuf = { osize: 0, omaxsize: 0, obuf: NULL };
char dump[10][T_BUFFER_MAX];
event dump_ev[10];
FILE *z = fopen("/tmp/dd", "w"); if (z == NULL) abort();
while (1) {
char v[T_BUFFER_MAX];
char *v;
event e;
e = get_event(socket, v, database);
e = get_event(socket, &ebuf, database);
v = ebuf.obuf;
if (e.type == -1) break;
if (e.type == ev_input) {
int sf = e.e[2].i;
memcpy(dump[sf], v, T_BUFFER_MAX);
if (ebuf.osize > T_BUFFER_MAX)
{ printf("event size too big\n"); exit(1); }
memcpy(dump[sf], ebuf.obuf, ebuf.osize);
dump_ev[sf] = e;
printf("input %d/%d\n", e.e[1].i, sf);
if (fwrite(dump_ev[sf].e[4].b, dump_ev[sf].e[4].bsize, 1, z) != 1) abort();
+3 -2
View File
@@ -84,11 +84,12 @@ int main(int n, char **v)
socket_send(socket, is_on, number_of_events * sizeof(int)) == -1)
abort();
OBUF ebuf = { osize: 0, omaxsize: 0, obuf: NULL };
while (1) {
char v[T_BUFFER_MAX];
event e;
int on_off;
e = get_event(socket, v, database);
e = get_event(socket, &ebuf, database);
if (e.type == -1) break;
if (e.type != ev_fun)
{ printf("unhandled event %d\n", e.type); continue; }
-36
View File
@@ -20,42 +20,6 @@ struct iqlog {
int max_length;
};
#if 0
/* this function passes all received IQ samples to the views */
static void _event(void *p, event e)
{
struct iqlog *l = p;
int i;
void *buffer;
int bsize;
int nsamples;
if (l->common.filter != NULL && filter_eval(l->common.filter, e) == 0)
return;
buffer = e.e[l->buffer_arg].b;
bsize = e.e[l->buffer_arg].bsize;
nsamples = bsize / (2*sizeof(int16_t));
if (nsamples > l->max_length) {
l->i = realloc(l->i, nsamples * sizeof(float));
if (l->i == NULL) abort();
l->q = realloc(l->q, nsamples * sizeof(float));
if (l->q == NULL) abort();
l->max_length = nsamples;
}
for (i = 0; i < nsamples; i++) {
l->i[i] = ((int16_t *)buffer)[i*2];
l->q[i] = ((int16_t *)buffer)[i*2+1];
}
for (i = 0; i < l->common.vsize; i++)
l->common.v[i]->append(l->common.v[i], l->i, l->q, nsamples);
}
#endif
static void _event(void *p, event e)
{
struct iqlog *l = p;
+3 -2
View File
@@ -246,11 +246,12 @@ int main(int n, char **v)
new_thread(receiver, &d);
OBUF ebuf = { osize: 0, omaxsize: 0, obuf: NULL };
/* read messages */
while (1) {
char v[T_BUFFER_MAX];
event e;
e = get_event(in, v, database);
e = get_event(in, &ebuf, database);
if (e.type == -1) break;
if (!(e.type == ul_id || e.type == dl_id)) continue;
handle_event(h, e);
+385
View File
@@ -0,0 +1,385 @@
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <poll.h>
#include <sys/socket.h>
#include <unistd.h>
#include "database.h"
#include "utils.h"
#include "../T.h"
#include "config.h"
#define DEFAULT_LOCAL_PORT 2022
typedef struct {
int id; /* increases at each new tracer's connection */
int s; /* socket */
int *is_on; /* local vision of is_on for this tracer */
int poll_id; /* -1: invalid, otherwise index in fds array */
} ti_t;
typedef struct {
ti_t *ti; /* data for tracers */
int ti_size;
int ti_maxsize;
} multi_t;
void set_is_on(int *is_on, int pos, int val)
{
if (val) is_on[pos]++; else is_on[pos]--;
/* TODO: remove check? */
if (is_on[pos] < 0) { printf("%s:%d:nonono\n",__FILE__,__LINE__); abort(); }
}
int send_messages_txt(int s, char *T_messages_txt, int T_messages_txt_len)
{
char buf[T_BUFFER_MAX];
char *T_LOCAL_buf = buf;
int32_t T_LOCAL_size;
unsigned char *src;
int src_len;
/* trace T_message.txt
* Send several messages -1 with content followed by message -2.
*/
src = (unsigned char *)T_messages_txt;
src_len = T_messages_txt_len;
while (src_len) {
int send_size = src_len;
if (send_size > T_PAYLOAD_MAXSIZE - sizeof(int))
send_size = T_PAYLOAD_MAXSIZE - sizeof(int);
/* TODO: be careful, we use internal T stuff, to rewrite? */
T_LOCAL_size = 0;
T_HEADER(T_ID(-1));
T_PUT_buffer(1, ((T_buffer){addr:(src), length:(send_size)}));
if (socket_send(s, &T_LOCAL_size, 4) == -1) return -1;
if (socket_send(s, buf, T_LOCAL_size) == -1) return -1;
src += send_size;
src_len -= send_size;
}
T_LOCAL_size = 0;
T_HEADER(T_ID(-2));
if (socket_send(s, &T_LOCAL_size, 4) == -1) return -1;
return socket_send(s, buf, T_LOCAL_size);
}
void new_tracer(multi_t *m, int s, int is_on_size, char *t, int t_size, int id)
{
if (send_messages_txt(s, t, t_size) == -1) {
printf("error sending T_messages.txt to new tracer %d => remove tracer\n",
id);
return;
}
if (m->ti_size == m->ti_maxsize) {
m->ti_maxsize += 64;
m->ti = realloc(m->ti, m->ti_maxsize * sizeof(ti_t));
if (m->ti == NULL) abort();
}
m->ti[m->ti_size].id = id;
m->ti[m->ti_size].s = s;
m->ti[m->ti_size].is_on = calloc(is_on_size, sizeof(int));
if (m->ti[m->ti_size].is_on == NULL) abort();
m->ti[m->ti_size].poll_id = -1;
m->ti_size++;
}
void remove_tracer(multi_t *m, int t)
{
free(m->ti[t].is_on);
shutdown(m->ti[t].s, SHUT_RDWR);
close(m->ti[t].s);
m->ti_size--;
memmove(&m->ti[t], &m->ti[t+1], (m->ti_size - t) * sizeof(ti_t));
}
int send_is_on(int socket, int number_of_events, int *is_on)
{
int i;
char mt = 1;
if (socket_send(socket, &mt, 1) == -1 ||
socket_send(socket, &number_of_events, sizeof(int)) == -1) return -1;
for (i = 0; i < number_of_events; i++) {
int v = is_on[i] ? 1 : 0;
if (socket_send(socket, &v, sizeof(int)) == -1) return -1;
}
return 0;
}
int read_tracee(int s, OBUF *ebuf, int *_type, int32_t *_length)
{
int type;
int32_t length;
char *v;
int vpos = 0;
if (fullread(s, &length, 4) == -1) return -1;
if (ebuf->omaxsize < length) {
ebuf->omaxsize = (length + 65535) & ~65535;
ebuf->obuf = realloc(ebuf->obuf, ebuf->omaxsize);
if (ebuf->obuf == NULL) { printf("out of memory\n"); exit(1); }
}
v = ebuf->obuf;
memcpy(v+vpos, &length, 4);
vpos += 4;
#ifdef T_SEND_TIME
if (fullread(s,v+vpos,sizeof(struct timespec))==-1) return -1;
vpos += sizeof(struct timespec);
length -= sizeof(struct timespec);
#endif
if (fullread(s, &type, sizeof(int)) == -1) return -1;
memcpy(v+vpos, &type, sizeof(int));
vpos += sizeof(int);
length -= sizeof(int);
if (fullread(s, v+vpos, length) == -1) return -1;
vpos += length;
ebuf->osize = vpos;
*_type = type;
*_length = length;
return 0;
}
void forward_event(multi_t *m, int number_of_events, OBUF *ebuf, int type)
{
int i;
if (type < 0 || type >= number_of_events)
{ printf("error: bad type of event to forward %d\n", type); abort(); }
for (i = 0; i < m->ti_size; i++) {
if (!m->ti[i].is_on[type]) continue;
if (socket_send(m->ti[i].s, ebuf->obuf, ebuf->osize) == -1)
printf("warning: error forwarding event to tracer %d\n", m->ti[i].id);
}
}
int connect_to_tracee(char *ip, int port, int number_of_events, int *is_on)
{
int s;
printf("connecting to %s:%d\n", ip, port);
s = try_connect_to(ip, port);
if (s == -1) return -1;
if (send_is_on(s, number_of_events, is_on) == -1) {
shutdown(s, SHUT_RDWR);
close(s);
return -1;
}
return s;
}
void usage(void)
{
printf(
"options:\n"
" -d <database file> this option is mandatory\n"
" -ip <host> connect to given IP address (default %s)\n"
" -p <port> connect to given port (default %d)\n"
" -lp <port> listen on local port (default %d)\n",
DEFAULT_REMOTE_IP,
DEFAULT_REMOTE_PORT,
DEFAULT_LOCAL_PORT
);
exit(1);
}
int main(int n, char **v)
{
char *database_filename = NULL;
void *database;
char *ip = DEFAULT_REMOTE_IP;
int port = DEFAULT_REMOTE_PORT;
int local_port = DEFAULT_LOCAL_PORT;
int *is_on;
int number_of_events;
int i, j;
char *T_messages_txt;
int T_messages_txt_len;
int l; /* listen socket for tracers' connections */
int s = -1; /* socket connected to tracee. -1 if not connected */
multi_t m;
int is_on_changed;
int current_nfd;
struct pollfd *fds = NULL;
int next_id = 0;
memset(&m, 0, sizeof(m));
/* write on a socket fails if the other end is closed and we get SIGPIPE */
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) abort();
for (i = 1; i < n; i++) {
if (!strcmp(v[i], "-h") || !strcmp(v[i], "--help")) usage();
if (!strcmp(v[i], "-d"))
{ if (i > n-2) usage(); database_filename = v[++i]; continue; }
if (!strcmp(v[i], "-ip")) { if (i > n-2) usage(); ip = v[++i]; continue; }
if (!strcmp(v[i], "-p"))
{ if (i > n-2) usage(); port = atoi(v[++i]); continue; }
if (!strcmp(v[i], "-lp"))
{ if (i > n-2) usage(); local_port = atoi(v[++i]); continue; }
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);
get_local_config(&T_messages_txt, &T_messages_txt_len);
number_of_events = number_of_ids(database);
is_on = calloc(number_of_events, sizeof(int));
if (is_on == NULL) abort();
/* create listener socket */
l = create_listen_socket("0.0.0.0", local_port);
OBUF ebuf = { osize: 0, omaxsize: 0, obuf: NULL };
current_nfd = 0;
while (1) {
int nfd;
int timeout;
if (s == -1) s = connect_to_tracee(ip, port, number_of_events, is_on);
/* poll on s (if there), l, and all tracers' sockets */
nfd = 1 + (s != -1) + m.ti_size;
if (nfd != current_nfd) {
current_nfd = nfd;
free(fds);
fds = calloc(nfd, sizeof(struct pollfd));
if (fds == NULL) { perror("calloc"); exit(1); }
}
i = 0;
fds[i].fd = l;
fds[i].events = POLLIN;
i++;
if (s != -1) {
fds[i].fd = s;
fds[i].events = POLLIN;
i++;
}
for (j = 0; j < m.ti_size; j++) {
m.ti[j].poll_id = i;
fds[i].fd = m.ti[j].s;
fds[i].events = POLLIN;
i++;
}
if (s == -1) timeout = 1000; else timeout = -1;
if (poll(fds, nfd, timeout) == -1) { perror("poll"); exit(1); }
if (fds[0].revents & ~POLLIN) {
printf("TODO: error on listen socket?\n");
exit(1);
}
/* new tracer connecting? */
if (fds[0].revents & POLLIN) {
int t;
printf("tracer %d connecting\n", next_id);
t = socket_accept(l);
if (t == -1) perror("accept");
else new_tracer(&m, t, number_of_events,
T_messages_txt, T_messages_txt_len, next_id);
next_id++;
}
if (s != -1 && fds[1].revents & ~POLLIN) {
printf("TODO: error on tracee socket?\n");
exit(1);
}
/* data from tracee */
if (s != -1 && fds[1].revents & POLLIN) {
int type;
int32_t length;
if (read_tracee(s, &ebuf, &type, &length) == -1) {
clear_remote_config();
shutdown(s, SHUT_RDWR);
close(s);
s = -1;
} else {
if (type == -1)
append_received_config_chunk(ebuf.obuf+ebuf.osize-length, length);
else if (type == -2) verify_config();
else forward_event(&m, number_of_events, &ebuf, type);
}
}
/* status of each tracer */
is_on_changed = 0;
for (j = 0; j < m.ti_size; j++) {
int l;
int s;
int *t_is_on;
if (m.ti[j].poll_id == -1) continue;
i = m.ti[j].poll_id;
s = m.ti[j].s;
t_is_on = m.ti[j].is_on;
if (fds[i].revents & (POLLHUP | POLLERR)) goto tracer_error;
/* error? */
if (fds[i].revents & ~POLLIN) {
printf("TODO: error with tracer?\n");
exit(1);
}
/* data in */
if (fds[i].revents & POLLIN) {
char t;
int len;
int v;
if (fullread(s, &t, 1) != 1) goto tracer_error;
switch (t) {
case 0:
is_on_changed = 1;
if (fullread(s, &len, sizeof(int)) == -1) goto tracer_error;
for (l = 0; l < len; l++) {
if (fullread(s, &v, sizeof(int)) == -1) goto tracer_error;
if (v < 0 || v >= number_of_events) goto tracer_error;
t_is_on[v] = 1 - t_is_on[v];
set_is_on(is_on, v, t_is_on[v]);
}
break;
case 1:
is_on_changed = 1;
if (fullread(s, &len, sizeof(int)) == -1) goto tracer_error;
if (len < 0 || len > number_of_events) goto tracer_error;
for (l = 0; l < len; l++) {
if (fullread(s, &v, sizeof(int)) == -1) goto tracer_error;
if (v < 0 || v > 1) goto tracer_error;
if (t_is_on[l] != v) set_is_on(is_on, l, v);
t_is_on[l] = v;
}
break;
case 2: break;
default: printf("error: unhandled message type %d\n", t); //abort();
}
}
continue;
tracer_error:
printf("remove tracer %d\n", m.ti[j].id);
for (l = 0; l < number_of_events; l++)
if (m.ti[j].is_on[l]) { is_on_changed = 1; set_is_on(is_on, l, 0); }
remove_tracer(&m, j);
j--;
}
if (is_on_changed && s != -1)
if (send_is_on(s, number_of_events, is_on) == -1) {
clear_remote_config();
shutdown(s, SHUT_RDWR);
close(s);
s = -1;
}
}
return 0;
}
-249
View File
@@ -56,176 +56,6 @@
#define SC_RNTI 9
#define G_RNTI 10
#if 0
typedef enum mac_lte_oob_event {
ltemac_send_preamble,
ltemac_send_sr,
ltemac_sr_failure
} mac_lte_oob_event;
typedef enum mac_lte_dl_retx {
dl_retx_no,
dl_retx_yes,
dl_retx_unknown
} mac_lte_dl_retx;
typedef enum mac_lte_crc_status {
crc_fail = 0,
crc_success = 1,
crc_high_code_rate = 2,
crc_pdsch_lost = 3,
crc_duplicate_nonzero_rv = 4,
crc_false_dci = 5
} mac_lte_crc_status;
typedef enum mac_lte_carrier_id {
carrier_id_primary,
carrier_id_secondary_1,
carrier_id_secondary_2,
carrier_id_secondary_3,
carrier_id_secondary_4
} mac_lte_carrier_id;
typedef enum mac_lte_ce_mode {
no_ce_mode = 0,
ce_mode_a = 1,
ce_mode_b = 2
} mac_lte_ce_mode;
typedef enum mac_lte_nb_mode {
no_nb_mode = 0,
nb_mode = 1
} mac_lte_nb_mode;
/* Context info attached to each LTE MAC frame */
typedef struct mac_lte_info
{
/* Needed for decode */
guint8 radioType;
guint8 direction;
guint8 rntiType;
/* Extra info to display */
guint16 rnti;
guint16 ueid;
/* Timing info */
guint16 sysframeNumber;
guint16 subframeNumber;
/* Optional field. More interesting for TDD (FDD is always -4 subframeNumber) */
gboolean subframeNumberOfGrantPresent;
guint16 subframeNumberOfGrant;
/* Flag set only if doing PHY-level data test - i.e. there may not be a
well-formed MAC PDU so just show as raw data */
gboolean isPredefinedData;
/* Length of DL PDU or UL grant size in bytes */
guint16 length;
/* 0=newTx, 1=first-retx, etc */
guint8 reTxCount;
guint8 isPHICHNACK; /* FALSE=PDCCH retx grant, TRUE=PHICH NACK */
/* UL only. Indicates if the R10 extendedBSR-Sizes parameter is set */
gboolean isExtendedBSRSizes;
/* UL only. Indicates if the R10 simultaneousPUCCH-PUSCH parameter is set for PCell */
gboolean isSimultPUCCHPUSCHPCell;
/* UL only. Indicates if the R10 extendedBSR-Sizes parameter is set for PSCell */
gboolean isSimultPUCCHPUSCHPSCell;
/* Status of CRC check. For UE it is DL only. For eNodeB it is UL
only. For an analyzer, it is present for both DL and UL. */
gboolean crcStatusValid;
mac_lte_crc_status crcStatus;
/* Carrier ID */
mac_lte_carrier_id carrierId;
/* DL only. Is this known to be a retransmission? */
mac_lte_dl_retx dl_retx;
/* DL only. CE mode to be used for RAR decoding */
mac_lte_ce_mode ceMode;
/* DL and UL. NB-IoT mode of the UE */
mac_lte_nb_mode nbMode;
/* More Physical layer info (see direction above for which side of union to use) */
union {
struct mac_lte_ul_phy_info
{
guint8 present; /* Remaining UL fields are present and should be displayed */
guint8 modulation_type;
guint8 tbs_index;
guint8 resource_block_length;
guint8 resource_block_start;
guint8 harq_id;
gboolean ndi;
} ul_info;
struct mac_lte_dl_phy_info
{
guint8 present; /* Remaining DL fields are present and should be displayed */
guint8 dci_format;
guint8 resource_allocation_type;
guint8 aggregation_level;
guint8 mcs_index;
guint8 redundancy_version_index;
guint8 resource_block_length;
guint8 harq_id;
gboolean ndi;
guint8 transport_block; /* 0..1 */
} dl_info;
} detailed_phy_info;
/* Relating to out-of-band events */
/* N.B. dissector will only look to these fields if length is 0... */
mac_lte_oob_event oob_event;
guint8 rapid;
guint8 rach_attempt_number;
#define MAX_SRs 20
guint16 number_of_srs;
guint16 oob_ueid[MAX_SRs];
guint16 oob_rnti[MAX_SRs];
} mac_lte_info;
typedef struct mac_lte_tap_info {
/* Info from context */
guint16 rnti;
guint16 ueid;
guint8 rntiType;
guint8 isPredefinedData;
gboolean crcStatusValid;
mac_lte_crc_status crcStatus;
guint8 direction;
guint8 isPHYRetx;
guint16 ueInTTI;
nstime_t mac_lte_time;
/* Number of bytes (which part is used depends upon context settings) */
guint32 single_number_of_bytes;
guint32 bytes_for_lcid[11];
guint32 sdus_for_lcid[11];
guint8 number_of_rars;
guint8 number_of_paging_ids;
/* Number of padding bytes includes padding subheaders and trailing padding */
guint16 padding_bytes;
guint16 raw_length;
} mac_lte_tap_info;
/* Accessor function to check if a frame was considered to be ReTx */
int is_mac_lte_frame_retx(packet_info *pinfo, guint8 direction);
#endif
/*****************************************************************/
/* UDP framing format */
/* ----------------------- */
@@ -309,82 +139,3 @@ int is_mac_lte_frame_retx(packet_info *pinfo, guint8 direction);
continues until the end of the frame) */
#define MAC_LTE_PAYLOAD_TAG 0x01
#if 0
/* Type to store parameters for configuring LCID->RLC channel settings for DRB */
/* Some are optional, and may not be seen (e.g. on reestablishment) */
typedef struct drb_mapping_t
{
guint16 ueid; /* Mandatory */
guint8 drbid; /* Mandatory */
gboolean lcid_present;
guint8 lcid; /* Part of LogicalChannelConfig - optional */
gboolean rlcMode_present;
guint8 rlcMode; /* Part of RLC config - optional */
gboolean rlc_ul_ext_li_field; /* Part of RLC config - optional */
gboolean rlc_dl_ext_li_field; /* Part of RLC config - optional */
gboolean rlc_ul_ext_am_sn; /* Part of RLC config - optional */
gboolean rlc_dl_ext_am_sn; /* Part of RLC config - optional */
gboolean um_sn_length_present;
guint8 um_sn_length; /* Part of RLC config - optional */
gboolean ul_priority_present;
guint8 ul_priority; /* Part of LogicalChannelConfig - optional */
gboolean pdcp_sn_size_present;
guint8 pdcp_sn_size; /* Part of pdcp-Config - optional */
} drb_mapping_t;
/* Set details of an LCID -> drb channel mapping. To be called from
configuration protocol (e.g. RRC) */
void set_mac_lte_channel_mapping(drb_mapping_t *drb_mapping);
/* Dedicated DRX config. Used to verify that a sensible config is given.
Also, beginning to configure MAC with this config and (optionally) show
DRX config and state (cycles/timers) attached to each UL/DL PDU! */
typedef struct drx_config_t {
gboolean configured;
guint32 frameNum;
guint32 previousFrameNum;
guint32 onDurationTimer;
guint32 inactivityTimer;
guint32 retransmissionTimer;
guint32 longCycle;
guint32 cycleOffset;
/* Optional Short cycle */
gboolean shortCycleConfigured;
guint32 shortCycle;
guint32 shortCycleTimer;
} drx_config_t;
/* Functions to set/release up dedicated DRX config */
void set_mac_lte_drx_config(guint16 ueid, drx_config_t *drx_config, packet_info *pinfo);
void set_mac_lte_drx_config_release(guint16 ueid, packet_info *pinfo);
/* RRC can tell this dissector which RAPIDs are Group A, Group A&B */
void set_mac_lte_rapid_ranges(guint groupA, guint all_RA);
/* RRC can indicate whether extended BSR sizes are used */
void set_mac_lte_extended_bsr_sizes(guint16 ueid, gboolean use_ext_bsr_sizes, packet_info *pinfo);
/* RRC can indicate whether simultaneous PUCCH/PUSCH is used */
typedef enum {
SIMULT_PUCCH_PUSCH_PCELL = 0,
SIMULT_PUCCH_PUSCH_PSCELL
} simult_pucch_pusch_cell_type;
void set_mac_lte_simult_pucch_pusch(guint16 ueid, simult_pucch_pusch_cell_type cell_type, gboolean use_simult_pucch_pusch, packet_info *pinfo);
/* Functions to be called from outside this module (e.g. in a plugin, where mac_lte_info
isn't available) to get/set per-packet data */
WS_DLL_PUBLIC
mac_lte_info *get_mac_lte_proto_data(packet_info *pinfo);
WS_DLL_PUBLIC
void set_mac_lte_proto_data(packet_info *pinfo, mac_lte_info *p_mac_lte_info);
/* Function to attempt to populate p_mac_lte_info using framing definition above */
gboolean dissect_mac_lte_context_fields(struct mac_lte_info *p_mac_lte_info, tvbuff_t *tvb,
gint *p_offset);
#endif
+9 -1
View File
@@ -123,14 +123,22 @@ int main(int n, char **v)
if (signal(SIGINT, force_stop) == SIG_ERR) abort();
if (signal(SIGTSTP, force_stop) == SIG_ERR) abort();
OBUF ebuf = { osize: 0, omaxsize: 0, obuf: NULL };
/* read messages */
while (run) {
int type;
int32_t length;
char v[T_BUFFER_MAX];
char *v;
int vpos = 0;
if (fullread(socket, &length, 4) == -1) goto read_error;
if (ebuf.omaxsize < length) {
ebuf.omaxsize = (length + 65535) & ~65535;
ebuf.obuf = realloc(ebuf.obuf, ebuf.omaxsize);
if (ebuf.obuf == NULL) { printf("out of memory\n"); exit(1); }
}
v = ebuf.obuf;
memcpy(v+vpos, &length, 4);
vpos += 4;
#ifdef T_SEND_TIME
+9 -1
View File
@@ -136,14 +136,22 @@ int main(int n, char **v)
new_thread(get_message_thread, &socket);
OBUF ebuf = { osize: 0, omaxsize: 0, obuf: NULL };
while (1) {
int type;
int32_t length;
char v[T_BUFFER_MAX];
char *v;
int vpos = 0;
/* read event from file */
if (fread(&length, 4, 1, in) != 1) break;
if (ebuf.omaxsize < length) {
ebuf.omaxsize = (length + 65535) & ~65535;
ebuf.obuf = realloc(ebuf.obuf, ebuf.omaxsize);
if (ebuf.obuf == NULL) { printf("out of memory\n"); exit(1); }
}
v = ebuf.obuf;
memcpy(v+vpos, &length, 4);
vpos += 4;
#ifdef T_SEND_TIME
+3 -3
View File
@@ -10,7 +10,6 @@
#include "view/view.h"
#include "gui/gui.h"
#include "utils.h"
#include "../T_defs.h"
#include "event_selector.h"
#include "config.h"
@@ -182,11 +181,12 @@ int main(int n, char **v)
/* send the first message - activate selected traces */
is_on_changed(&textlog_data);
OBUF ebuf = { osize: 0, omaxsize: 0, obuf: NULL };
/* read messages */
while (1) {
char v[T_BUFFER_MAX];
event e;
e = get_event(textlog_data.socket, v, database);
e = get_event(textlog_data.socket, &ebuf, database);
if (e.type == -1) abort();
handle_event(h, e);
}
+101 -19
View File
@@ -12,7 +12,14 @@
#include "logger/logger.h"
#include "view/view.h"
enum var_type {
DEFAULT,
VCD_FUNCTION,
VCD_VARIABLE
};
typedef struct {
enum var_type type;
char *event;
char *arg;
char *vcd_name;
@@ -44,16 +51,39 @@ void vcd_write_header(vcd_vars *v, int n)
"$version\n"
" to_vcd\n"
"$end\n"
"$timescale 1ns $end\n"
"$timescale 1ns $end\n") <= 0) abort();
if (fprintf(out,
"$scope module logic $end\n") <= 0) abort();
for (i = 0; i < n; i++)
if (v[i].type == DEFAULT)
if (fprintf(out, "$var wire %d %s %s $end\n",
v[i].boolean ? 1 : 64,
v[i].vcd_name, v[i].vcd_name) <= 0) abort();
if (fprintf(out,
"$upscope $end\n") <= 0) abort();
if (fprintf(out,
"$scope module functions $end\n") <= 0) abort();
for (i = 0; i < n; i++)
if (v[i].type == VCD_FUNCTION)
if (fprintf(out, "$var wire %d %s %s $end\n",
v[i].boolean ? 1 : 64,
v[i].vcd_name, v[i].vcd_name) <= 0) abort();
if (fprintf(out,
"$upscope $end\n") <= 0) abort();
if (fprintf(out,
"$scope module variables $end\n") <= 0) abort();
for (i = 0; i < n; i++)
if (fprintf(out, "$var wire %d %s %s $end\n",
v[i].boolean ? 1 : 64,
v[i].vcd_name, v[i].vcd_name) <= 0) abort();
if (v[i].type == VCD_VARIABLE)
if (fprintf(out, "$var wire %d %s %s $end\n",
v[i].boolean ? 1 : 64,
v[i].vcd_name, v[i].vcd_name) <= 0) abort();
if (fprintf(out,
"$upscope $end\n") <= 0) abort();
if (fprintf(out,
"$upscope $end\n"
"$enddefinitions $end\n"
"$dumpvars\n") <= 0) abort();
@@ -174,7 +204,8 @@ void usage(void)
" -ip <host> connect to given IP address (default %s)\n"
" -p <port> connect to given port (default %d)\n"
" -b <event> <arg> <vcd name> trace as binary (0 off, anything else on)\n"
" -l <event> <arg> <vcd name> trace as uint64_t\n",
" -l <event> <arg> <vcd name> trace as uint64_t\n"
" -vcd trace all VCD variables and functions\n",
DEFAULT_REMOTE_IP,
DEFAULT_REMOTE_PORT
);
@@ -192,6 +223,21 @@ void force_stop(int x)
run = 0;
}
vcd_vars *add_var(vcd_vars *vars, int nvars,
char *event, char *arg, char *vcd_name, int is_boolean, enum var_type t)
{
if (nvars % 64 == 0) {
vars = realloc(vars, (nvars+64) * sizeof(vcd_vars));
if (vars == NULL) abort();
}
vars[nvars].type = t;
vars[nvars].event = event;
vars[nvars].arg = arg;
vars[nvars].vcd_name = vcd_name;
vars[nvars].boolean = is_boolean;
return vars;
}
int main(int n, char **v)
{
char *output_filename = NULL;
@@ -202,11 +248,12 @@ int main(int n, char **v)
int *is_on;
int number_of_events;
int i;
vcd_vars vars[n];
vcd_vars *vars = NULL;
int nvars = 0;
view *vcd_view;
event_handler *h;
logger *textlog;
int all_vcd = 0;
/* write on a socket fails if the other end is closed and we get SIGPIPE */
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) abort();
@@ -221,19 +268,22 @@ int main(int n, char **v)
if (!strcmp(v[i], "-p"))
{ if (i > n-2) usage(); port = atoi(v[++i]); continue; }
if (!strcmp(v[i], "-b")) { if(i>n-4)usage();
vars[nvars].event = v[++i];
vars[nvars].arg = v[++i];
vars[nvars].vcd_name = v[++i];
vars[nvars++].boolean = 1;
char *event = v[++i];
char *arg = v[++i];
char *vcd_name = v[++i];
vars = add_var(vars, nvars, event, arg, vcd_name, 1, DEFAULT);
nvars++;
continue;
}
if (!strcmp(v[i], "-l")) { if(i>n-4)usage();
vars[nvars].event = v[++i];
vars[nvars].arg = v[++i];
vars[nvars].vcd_name = v[++i];
vars[nvars++].boolean = 0;
char *event = v[++i];
char *arg = v[++i];
char *vcd_name = v[++i];
vars = add_var(vars, nvars, event, arg, vcd_name, 0, DEFAULT);
nvars++;
continue;
}
if (!strcmp(v[i], "-vcd")) { all_vcd = 1; continue; }
usage();
}
@@ -260,11 +310,42 @@ int main(int n, char **v)
/* create the view */
vcd_view = new_view_vcd();
if (all_vcd) {
/* activate all VCD traces */
for (i = 0; i < number_of_events; i++) {
int is_boolean;
enum var_type type;
int prefix_length;
char *name = event_name_from_id(database, i);
char *vcd_name;
char *var_prefix = "VCD_VARIABLE_";
char *fun_prefix = "VCD_FUNCTION_";
if (!strncmp(name, var_prefix, strlen(var_prefix))) {
prefix_length = strlen(var_prefix);
is_boolean = 0;
type = VCD_VARIABLE;
} else if (!strncmp(name, fun_prefix, strlen(fun_prefix))) {
prefix_length = strlen(fun_prefix);
is_boolean = 1;
type = VCD_FUNCTION;
} else
continue;
vcd_name = event_vcd_name_from_id(database, i);
if (vcd_name == NULL) {
vcd_name = name+prefix_length;
printf("WARNING: ID %s does not define VCD_NAME in the file %s, using %s\n",
name, database_filename, vcd_name);
}
vars = add_var(vars, nvars,
name, "value", vcd_name, is_boolean, type);
nvars++;
}
}
/* setup traces */
for (i = 0; i < nvars; i++) {
char format[256];
if (strlen(vars[i].arg) > 256-3) abort();
if (strlen(vars[i].vcd_name) > 256-1) abort();
if (strlen(vars[i].arg) + strlen(vars[i].vcd_name) > 256-16) abort();
sprintf(format, "%c [%s] %s",
vars[i].boolean ? 'b' : 'l',
vars[i].arg,
@@ -287,11 +368,12 @@ int main(int n, char **v)
if (signal(SIGINT, force_stop) == SIG_ERR) abort();
if (signal(SIGTSTP, force_stop) == SIG_ERR) abort();
OBUF ebuf = { osize: 0, omaxsize: 0, obuf: NULL };
/* read messages */
while (run) {
char v[T_BUFFER_MAX];
event e;
e = get_event(socket, v, database);
e = get_event(socket, &ebuf, database);
if (e.type == -1) { printf("disconnected? let's quit gently\n"); break; }
handle_event(h, e);
}
+4 -3
View File
@@ -12,7 +12,6 @@
#include "gui/gui.h"
#include "filter/filter.h"
#include "utils.h"
#include "../T_defs.h"
#include "event_selector.h"
#include "openair_logo.h"
#include "config.h"
@@ -854,8 +853,11 @@ int main(int n, char **v)
if (pthread_mutex_init(&ue_data.lock, NULL)) abort();
setup_event_selector(g, database, is_on, is_on_changed, &ue_data);
OBUF ebuf = { osize: 0, omaxsize: 0, obuf: NULL };
restart:
clear_remote_config();
if (ue_data.socket != -1) close(ue_data.socket);
ue_data.socket = connect_to(ip, port);
/* send the first message - activate selected traces */
@@ -863,9 +865,8 @@ restart:
/* read messages */
while (1) {
char v[T_BUFFER_MAX];
event e;
e = get_event(ue_data.socket, v, database);
e = get_event(ue_data.socket, &ebuf, database);
if (e.type == -1) goto restart;
if (pthread_mutex_lock(&ue_data.lock)) abort();
handle_event(h, e);
+48 -19
View File
@@ -79,6 +79,36 @@ list *list_append(list *l, void *data)
/* socket */
/****************************************************************************/
int create_listen_socket(char *addr, int port)
{
struct sockaddr_in a;
int s;
int v;
s = socket(AF_INET, SOCK_STREAM, 0);
if (s == -1) { perror("socket"); exit(1); }
v = 1;
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &v, sizeof(int)))
{ perror("setsockopt"); exit(1); }
a.sin_family = AF_INET;
a.sin_port = htons(port);
a.sin_addr.s_addr = inet_addr(addr);
if (bind(s, (struct sockaddr *)&a, sizeof(a))) { perror("bind"); exit(1); }
if (listen(s, 5)) { perror("listen"); exit(1); }
return s;
}
int socket_accept(int s)
{
struct sockaddr_in a;
socklen_t alen;
alen = sizeof(a);
return accept(s, (struct sockaddr *)&a, &alen);
}
int socket_send(int socket, void *buffer, int size)
{
char *x = buffer;
@@ -94,26 +124,13 @@ int socket_send(int socket, void *buffer, int size)
int get_connection(char *addr, int port)
{
struct sockaddr_in a;
socklen_t alen;
int s, t;
printf("waiting for connection on %s:%d\n", addr, port);
s = socket(AF_INET, SOCK_STREAM, 0);
if (s == -1) { perror("socket"); exit(1); }
t = 1;
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &t, sizeof(int)))
{ perror("setsockopt"); exit(1); }
s = create_listen_socket(addr, port);
a.sin_family = AF_INET;
a.sin_port = htons(port);
a.sin_addr.s_addr = inet_addr(addr);
if (bind(s, (struct sockaddr *)&a, sizeof(a))) { perror("bind"); exit(1); }
if (listen(s, 5)) { perror("bind"); exit(1); }
alen = sizeof(a);
t = accept(s, (struct sockaddr *)&a, &alen);
t = socket_accept(s);
if (t == -1) { perror("accept"); exit(1); }
close(s);
@@ -137,14 +154,11 @@ int fullread(int fd, void *_buf, int count)
return ret;
}
int connect_to(char *addr, int port)
int try_connect_to(char *addr, int port)
{
int s;
struct sockaddr_in a;
printf("connecting to %s:%d\n", addr, port);
again:
s = socket(AF_INET, SOCK_STREAM, 0);
if (s == -1) { perror("socket"); exit(1); }
@@ -155,6 +169,21 @@ again:
if (connect(s, (struct sockaddr *)&a, sizeof(a)) == -1) {
perror("connect");
close(s);
return -1;
}
return s;
}
int connect_to(char *addr, int port)
{
int s;
printf("connecting to %s:%d\n", addr, port);
again:
s = try_connect_to(addr, port);
if (s == -1) {
printf("trying again in 1s\n");
sleep(1);
goto again;
+3
View File
@@ -24,11 +24,14 @@ list *list_append(list *l, void *data);
#define DEFAULT_REMOTE_IP "127.0.0.1"
#define DEFAULT_REMOTE_PORT 2021
int create_listen_socket(char *addr, int port);
int socket_accept(int s);
/* socket_send: return 0 if okay, -1 on error */
int socket_send(int socket, void *buffer, int size);
int get_connection(char *addr, int port);
/* fullread: return length read if okay (that is: 'count'), -1 on error */
int fullread(int fd, void *_buf, int count);
int try_connect_to(char *addr, int port);
int connect_to(char *addr, int port);
/****************************************************************************/
+3 -3
View File
@@ -10,7 +10,6 @@
#include "view/view.h"
#include "gui/gui.h"
#include "utils.h"
#include "../T_defs.h"
#include "event_selector.h"
#include "config.h"
@@ -188,11 +187,12 @@ int main(int n, char **v)
/* send the first message - activate selected traces */
is_on_changed(&vcd_data);
OBUF ebuf = { osize: 0, omaxsize: 0, obuf: NULL };
/* read messages */
while (1) {
char v[T_BUFFER_MAX];
event e;
e = get_event(vcd_data.socket, v, database);
e = get_event(vcd_data.socket, &ebuf, database);
if (e.type == -1) abort();
handle_event(h, e);
}
+2 -1
View File
@@ -95,7 +95,7 @@ hash_table_t *hashtable_create(const hash_size_t sizeP, hash_size_t (*hashfuncP)
* Cleanup
* The hashtable_destroy() walks through the linked lists for each possible hash value, and releases the elements. It also releases the nodes array and the hash_table_t.
*/
hashtable_rc_t hashtable_destroy(hash_table_t * const hashtblP)
hashtable_rc_t hashtable_destroy(hash_table_t * hashtblP)
{
hash_size_t n;
hash_node_t *node, *oldnode;
@@ -117,6 +117,7 @@ hashtable_rc_t hashtable_destroy(hash_table_t * const hashtblP)
}
free(hashtblP->nodes);
free(hashtblP);
hashtblP=NULL;
return HASH_TABLE_OK;
}
//-------------------------------------------------------------------------------------------------------------------------------
+1
View File
@@ -35,6 +35,7 @@
#ifndef ASSERTIONS_H_
#define ASSERTIONS_H_
void output_log_mem(void);
#define _Assert_Exit_ \
{ \
fprintf(stderr, "\nExiting execution\n"); \
+29 -47
View File
@@ -39,7 +39,6 @@
#include "assertions.h"
#include "intertask_interface.h"
#include "intertask_interface_dump.h"
#if T_TRACER
#include "T.h"
@@ -328,22 +327,17 @@ int itti_send_msg_to_task(task_id_t destination_task_id, instance_t instance, Me
/* Increment the global message number */
message_number = itti_increment_message_number ();
#if 0
/* itti dump is disabled */
itti_dump_queue_message (origin_task_id, message_number, message, itti_desc.messages_info[message_id].name,
sizeof(MessageHeader) + message->ittiMsgHeader.ittiMsgSize);
#endif
if (destination_task_id != TASK_UNKNOWN) {
if (itti_desc.threads[destination_thread_id].task_state == TASK_STATE_ENDED) {
ITTI_DEBUG(ITTI_DEBUG_ISSUES, " Message %s, number %lu with priority %d can not be sent from %s to queue (%u:%s), ended destination task!\n",
itti_desc.messages_info[message_id].name,
message_number,
priority,
itti_get_task_name(origin_task_id),
destination_task_id,
itti_get_task_name(destination_task_id));
if (itti_desc.threads[destination_thread_id].task_state == TASK_STATE_ENDED ||
itti_desc.threads[destination_thread_id].task_state == TASK_STATE_NOT_CONFIGURED) {
ITTI_DEBUG(ITTI_DEBUG_ISSUES, " Message %s, number %lu with priority %d can not be sent from %s to queue (%u:%s), unconfigured or ended destination task!\n",
itti_desc.messages_info[message_id].name,
message_number,
priority,
itti_get_task_name(origin_task_id),
destination_task_id,
itti_get_task_name(destination_task_id));
} else {
if(!emulate_rf){
/* We cannot send a message if the task is not running */
@@ -429,22 +423,17 @@ int itti_try_send_msg_to_task(task_id_t destination_task_id, instance_t instance
/* Increment the global message number */
message_number = itti_increment_message_number ();
#if 0
/* itti dump is disabled */
itti_dump_queue_message (origin_task_id, message_number, message, itti_desc.messages_info[message_id].name,
sizeof(MessageHeader) + message->ittiMsgHeader.ittiMsgSize);
#endif
if (destination_task_id != TASK_UNKNOWN) {
if (itti_desc.threads[destination_thread_id].task_state == TASK_STATE_ENDED) {
ITTI_DEBUG(ITTI_DEBUG_ISSUES, " Message %s, number %lu with priority %d can not be sent from %s to queue (%u:%s), ended destination task!\n",
itti_desc.messages_info[message_id].name,
message_number,
priority,
itti_get_task_name(origin_task_id),
destination_task_id,
itti_get_task_name(destination_task_id));
if (itti_desc.threads[destination_thread_id].task_state == TASK_STATE_ENDED ||
itti_desc.threads[destination_thread_id].task_state == TASK_STATE_NOT_CONFIGURED) {
ITTI_DEBUG(ITTI_DEBUG_ISSUES, " Message %s, number %lu with priority %d can not be sent from %s to queue (%u:%s), unconfigured or ended destination task!\n",
itti_desc.messages_info[message_id].name,
message_number,
priority,
itti_get_task_name(origin_task_id),
destination_task_id,
itti_get_task_name(destination_task_id));
} else {
/* We cannot send a message if the task is not running */
AssertFatal (itti_desc.threads[destination_thread_id].task_state == TASK_STATE_READY,
@@ -727,15 +716,18 @@ void itti_mark_task_ready(task_id_t task_id)
AssertFatal (thread_id < itti_desc.thread_max, "Thread id (%d) is out of range (%d)!\n", thread_id, itti_desc.thread_max);
#if 0
/* itti dump is disabled */
/* Register the thread in itti dump */
itti_dump_thread_use_ring_buffer();
#endif
/* Mark the thread as using LFDS queue */
lfds611_queue_use(itti_desc.tasks[task_id].message_queue);
#if defined(UE_EXPANSION) || defined(RTAI)
/* Assign low priority to created threads */
{
struct sched_param sched_param;
sched_param.sched_priority = sched_get_priority_min(SCHED_FIFO) + 1;
sched_setscheduler(0, SCHED_FIFO, &sched_param);
}
#endif
itti_desc.threads[thread_id].task_state = TASK_STATE_READY;
itti_desc.ready_tasks ++;
@@ -753,7 +745,7 @@ void itti_exit_task(void)
#if defined(OAI_EMU) || defined(RTAI)
if (task_id > TASK_UNKNOWN) {
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLE_ITTI_RECV_MSG,
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_ITTI_RECV_MSG,
__sync_and_and_fetch (&itti_desc.vcd_receive_msg, ~(1L << task_id)));
}
#endif
@@ -777,7 +769,7 @@ void itti_terminate_tasks(task_id_t task_id)
}
int itti_init(task_id_t task_max, thread_id_t thread_max, MessagesIds messages_id_max, const task_info_t *tasks_info,
const message_info_t *messages_info, const char * const messages_definition_xml, const char * const dump_file_name)
const message_info_t *messages_info)
{
task_id_t task_id;
thread_id_t thread_id;
@@ -862,11 +854,6 @@ int itti_init(task_id_t task_max, thread_id_t thread_max, MessagesIds messages_i
itti_desc.wait_tasks = 0;
itti_desc.created_tasks = 0;
itti_desc.ready_tasks = 0;
#if 0
/* itti dump is disabled */
itti_dump_init (messages_definition_xml, dump_file_name);
#endif
CHECK_INIT_RETURN(timer_init ());
return 0;
@@ -931,11 +918,6 @@ void itti_wait_tasks_end(void)
ITTI_DEBUG(ITTI_DEBUG_ISSUES, " Some threads are still running, force exit\n");
exit (0);
}
#if 0
/* itti dump is disabled */
itti_dump_exit();
#endif
}
void itti_send_terminate_message(task_id_t task_id)
@@ -1,790 +0,0 @@
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/** @brief Intertask Interface Signal Dumper
* Allows users to connect their itti_analyzer to this process and dump
* signals exchanged between tasks.
* @author Sebastien Roux <sebastien.roux@eurecom.fr>
*/
#define _GNU_SOURCE // required for pthread_setname_np()
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <error.h>
#include <sched.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <sys/eventfd.h>
#include "assertions.h"
#include "liblfds611.h"
#include "itti_types.h"
#include "intertask_interface.h"
#include "intertask_interface_dump.h"
#if T_TRACER
#include "T.h"
#endif
static const int itti_dump_debug = 0; // 0x8 | 0x4 | 0x2;
# define ITTI_DUMP_DEBUG(m, x, args...) do { if ((m) & itti_dump_debug) fprintf(stdout, "[ITTI_DUMP][D]"x, ##args); } \
while(0)
#define ITTI_DUMP_ERROR(x, args...) do { fprintf(stdout, "[ITTI_DUMP][E]"x, ##args); } \
while(0)
typedef struct itti_dump_queue_item_s {
MessageDef *data;
uint32_t data_size;
uint32_t message_number;
uint32_t message_type;
uint32_t message_size;
} itti_dump_queue_item_t;
typedef struct {
int sd;
uint32_t last_message_number;
} itti_client_desc_t;
typedef struct itti_desc_s {
/* Asynchronous thread that write to file/accept new clients */
pthread_t itti_acceptor_thread;
pthread_attr_t attr;
/* List of messages to dump.
* NOTE: we limit the size of this queue to retain only the last exchanged
* messages. The size can be increased by setting up the ITTI_QUEUE_MAX_ELEMENTS
* in mme_default_values.h or by putting a custom in the configuration file.
*/
struct lfds611_ringbuffer_state *itti_message_queue;
int nb_connected;
/* Event fd used to notify new messages (semaphore) */
int event_fd;
int itti_listen_socket;
itti_client_desc_t itti_clients[ITTI_DUMP_MAX_CON];
} itti_desc_t;
typedef struct {
itti_socket_header_t socket_header;
itti_signal_header_t signal_header;
/* Message payload is added here, this struct is used as an header */
} itti_dump_message_t;
typedef struct {
itti_socket_header_t socket_header;
} itti_statistic_message_t;
static const itti_message_types_t itti_dump_xml_definition_end = ITTI_DUMP_XML_DEFINITION_END;
static const itti_message_types_t itti_dump_message_type_end = ITTI_DUMP_MESSAGE_TYPE_END;
static itti_desc_t itti_dump_queue;
static FILE *dump_file = NULL;
static int itti_dump_running = 1;
static volatile uint32_t pending_messages = 0;
/*------------------------------------------------------------------------------*/
static int itti_dump_send_message(int sd, itti_dump_queue_item_t *message)
{
itti_dump_message_t *new_message;
ssize_t bytes_sent = 0, total_sent = 0;
uint8_t *data_ptr;
/* Allocate memory for message header and payload */
size_t size = sizeof(itti_dump_message_t) + message->data_size + sizeof(itti_message_types_t);
AssertFatal (sd > 0, "Socket descriptor (%d) is invalid!\n", sd);
AssertFatal (message != NULL, "Message is NULL!\n");
new_message = malloc(size);
AssertFatal (new_message != NULL, "New message allocation failed!\n");
/* Preparing the header */
new_message->socket_header.message_size = size;
new_message->socket_header.message_type = ITTI_DUMP_MESSAGE_TYPE;
/* Adds message number in unsigned decimal ASCII format */
snprintf(new_message->signal_header.message_number_char, sizeof(new_message->signal_header.message_number_char),
MESSAGE_NUMBER_CHAR_FORMAT, message->message_number);
new_message->signal_header.message_number_char[sizeof(new_message->signal_header.message_number_char) - 1] = '\n';
/* Appends message payload */
memcpy(&new_message[1], message->data, message->data_size);
memcpy(((void *) &new_message[1]) + message->data_size, &itti_dump_message_type_end, sizeof(itti_message_types_t));
data_ptr = (uint8_t *)&new_message[0];
do {
bytes_sent = send(sd, &data_ptr[total_sent], size - total_sent, 0);
if (bytes_sent < 0) {
ITTI_DUMP_ERROR("[%d] Failed to send %zu bytes to socket (%d:%s)\n",
sd, size, errno, strerror(errno));
free(new_message);
return -1;
}
total_sent += bytes_sent;
} while (total_sent != size);
free(new_message);
return total_sent;
}
static int itti_dump_fwrite_message(itti_dump_queue_item_t *message)
{
itti_dump_message_t new_message_header;
if ((dump_file != NULL) && (message != NULL)) {
new_message_header.socket_header.message_size = message->message_size + sizeof(itti_dump_message_t) + sizeof(itti_message_types_t);
new_message_header.socket_header.message_type = message->message_type;
snprintf(new_message_header.signal_header.message_number_char, sizeof(new_message_header.signal_header.message_number_char),
MESSAGE_NUMBER_CHAR_FORMAT, message->message_number);
new_message_header.signal_header.message_number_char[sizeof(new_message_header.signal_header.message_number_char) - 1] = '\n';
fwrite (&new_message_header, sizeof(itti_dump_message_t), 1, dump_file);
fwrite (message->data, message->data_size, 1, dump_file);
fwrite (&itti_dump_message_type_end, sizeof(itti_message_types_t), 1, dump_file);
fflush (dump_file);
return (1);
}
return (0);
}
static int itti_dump_send_xml_definition(const int sd, const char *message_definition_xml,
const uint32_t message_definition_xml_length)
{
itti_socket_header_t *itti_dump_message;
/* Allocate memory for message header and payload */
size_t itti_dump_message_size;
ssize_t bytes_sent = 0, total_sent = 0;
uint8_t *data_ptr;
AssertFatal (sd > 0, "Socket descriptor (%d) is invalid!\n", sd);
AssertFatal (message_definition_xml != NULL, "Message definition XML is NULL!\n");
itti_dump_message_size = sizeof(itti_socket_header_t) + message_definition_xml_length + sizeof(itti_message_types_t);
itti_dump_message = calloc(1, itti_dump_message_size);
ITTI_DUMP_DEBUG(0x2, "[%d] Sending XML definition message of size %zu to observer peer\n",
sd, itti_dump_message_size);
itti_dump_message->message_size = itti_dump_message_size;
itti_dump_message->message_type = ITTI_DUMP_XML_DEFINITION;
/* Copying message definition */
memcpy (&itti_dump_message[1], message_definition_xml, message_definition_xml_length);
memcpy (((void *) &itti_dump_message[1]) + message_definition_xml_length, &itti_dump_xml_definition_end, sizeof(itti_message_types_t));
data_ptr = (uint8_t *)&itti_dump_message[0];
do {
bytes_sent = send(sd, &data_ptr[total_sent], itti_dump_message_size - total_sent, 0);
if (bytes_sent < 0) {
ITTI_DUMP_ERROR("[%d] Failed to send %zu bytes to socket (%d:%s)\n",
sd, itti_dump_message_size, errno, strerror(errno));
free(itti_dump_message);
return -1;
}
total_sent += bytes_sent;
} while (total_sent != itti_dump_message_size);
free(itti_dump_message);
return 0;
}
static void itti_dump_user_data_delete_function(void *user_data, void *user_state)
{
(void)user_state; // UNUSED
if (user_data != NULL) {
itti_dump_queue_item_t *item;
task_id_t task_id;
int result;
item = (itti_dump_queue_item_t *)user_data;
if (item->data != NULL) {
task_id = ITTI_MSG_ORIGIN_ID(item->data);
result = itti_free(task_id, item->data);
AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
} else {
task_id = TASK_UNKNOWN;
}
result = itti_free(task_id, item);
AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
}
}
static int itti_dump_enqueue_message(itti_dump_queue_item_t *new, uint32_t message_size,
uint32_t message_type)
{
struct lfds611_freelist_element *new_queue_element = NULL;
int overwrite_flag;
AssertFatal (new != NULL, "Message to queue is NULL!\n");
new->message_type = message_type;
new->message_size = message_size;
ITTI_DUMP_DEBUG (0x1, " itti_dump_enqueue_message: lfds611_ringbuffer_get_write_element\n");
new_queue_element = lfds611_ringbuffer_get_write_element (itti_dump_queue.itti_message_queue, &new_queue_element, &overwrite_flag);
if (overwrite_flag != 0) {
// no free element available: overwrite a non read one => data loss!
void *old = NULL;
lfds611_freelist_get_user_data_from_element(new_queue_element, &old);
ITTI_DUMP_DEBUG (0x4, " overwrite_flag set, freeing old data %p %p\n", new_queue_element, old);
itti_dump_user_data_delete_function (old, NULL);
}
lfds611_freelist_set_user_data_in_element(new_queue_element, new);
lfds611_ringbuffer_put_write_element(itti_dump_queue.itti_message_queue, new_queue_element);
if (overwrite_flag == 0) {
{
ssize_t write_ret;
eventfd_t sem_counter = 1;
/* Call to write for an event fd must be of 8 bytes */
write_ret = write(itti_dump_queue.event_fd, &sem_counter, sizeof(sem_counter));
AssertFatal (write_ret == sizeof(sem_counter), "Write to dump event failed (%d/%d)!\n", (int) write_ret, (int) sizeof(sem_counter));
}
// add one to pending_messages, atomically
__sync_fetch_and_add (&pending_messages, 1);
}
ITTI_DUMP_DEBUG (0x2, " Added element to queue %p %p, pending %u, type %u\n", new_queue_element, new, pending_messages, message_type);
return 0;
}
static void itti_dump_socket_exit(void)
{
close(itti_dump_queue.event_fd);
close(itti_dump_queue.itti_listen_socket);
/* Leave the thread as we detected end signal */
pthread_exit(NULL);
}
static int itti_dump_flush_ring_buffer(int flush_all)
{
struct lfds611_freelist_element *element = NULL;
void *user_data;
int j;
int consumer;
/* Check if there is a least one consumer */
consumer = 0;
if (dump_file != NULL) {
consumer = 1;
} else {
for (j = 0; j < ITTI_DUMP_MAX_CON; j++) {
if (itti_dump_queue.itti_clients[j].sd > 0) {
consumer = 1;
break;
}
}
}
if (consumer > 0) {
do {
/* Acquire the ring element */
lfds611_ringbuffer_get_read_element(itti_dump_queue.itti_message_queue, &element);
// subtract one from pending_messages, atomically
__sync_fetch_and_sub (&pending_messages, 1);
if (element == NULL) {
if (flush_all != 0) {
flush_all = 0;
} else {
AssertFatal (0, "Dump event with no data!\n");
}
} else {
/* Retrieve user part of the message */
lfds611_freelist_get_user_data_from_element(element, &user_data);
ITTI_DUMP_DEBUG (0x2, " removed element from queue %p %p, pending %u\n", element, user_data, pending_messages);
if (((itti_dump_queue_item_t *)user_data)->message_type == ITTI_DUMP_EXIT_SIGNAL) {
lfds611_ringbuffer_put_read_element(itti_dump_queue.itti_message_queue, element);
itti_dump_socket_exit();
}
/* Write message to file */
itti_dump_fwrite_message((itti_dump_queue_item_t *)user_data);
/* Send message to remote analyzer */
for (j = 0; j < ITTI_DUMP_MAX_CON; j++) {
if (itti_dump_queue.itti_clients[j].sd > 0) {
itti_dump_send_message(itti_dump_queue.itti_clients[j].sd,
(itti_dump_queue_item_t *)user_data);
}
}
itti_dump_user_data_delete_function (user_data, NULL);
lfds611_freelist_set_user_data_in_element(element, NULL);
/* We have finished with this element, reinsert it in the ring buffer */
lfds611_ringbuffer_put_read_element(itti_dump_queue.itti_message_queue, element);
}
} while(flush_all
);
}
return (consumer);
}
static int itti_dump_handle_new_connection(int sd, const char *xml_definition, uint32_t xml_definition_length)
{
if (itti_dump_queue.nb_connected < ITTI_DUMP_MAX_CON) {
uint8_t i;
for (i = 0; i < ITTI_DUMP_MAX_CON; i++) {
/* Let's find a place to store the new client */
if (itti_dump_queue.itti_clients[i].sd == -1) {
break;
}
}
ITTI_DUMP_DEBUG(0x2, " Found place to store new connection: %d\n", i);
AssertFatal (i < ITTI_DUMP_MAX_CON, "No more connection available (%d/%d) for socked %d!\n", i, ITTI_DUMP_MAX_CON, sd);
ITTI_DUMP_DEBUG(0x2, " Socket %d accepted\n", sd);
/* Send the XML message definition */
if (itti_dump_send_xml_definition(sd, xml_definition, xml_definition_length) < 0) {
AssertError (0, {}, "Failed to send XML definition!\n");
close (sd);
return -1;
}
itti_dump_queue.itti_clients[i].sd = sd;
itti_dump_queue.nb_connected++;
} else {
ITTI_DUMP_DEBUG(0x2, " Socket %d rejected\n", sd);
/* We have reached max number of users connected...
* Reject the connection.
*/
close (sd);
return -1;
}
return 0;
}
static void *itti_dump_socket(void *arg_p)
{
uint32_t message_definition_xml_length;
char *message_definition_xml;
int rc;
int itti_listen_socket, max_sd;
int on = 1;
fd_set read_set, working_set;
struct sockaddr_in servaddr; /* socket address structure */
struct timeval *timeout_p = NULL;
ITTI_DUMP_DEBUG(0x2, " Creating TCP dump socket on port %u\n", ITTI_PORT);
message_definition_xml = (char *)arg_p;
AssertFatal (message_definition_xml != NULL, "Message definition XML is NULL!\n");
message_definition_xml_length = strlen(message_definition_xml) + 1;
if ((itti_listen_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
ITTI_DUMP_ERROR(" ocket creation failed (%d:%s)\n", errno, strerror(errno));
pthread_exit(NULL);
}
/* Allow socket reuse */
rc = setsockopt(itti_listen_socket, SOL_SOCKET, SO_REUSEADDR,
(char *)&on, sizeof(on));
if (rc < 0) {
ITTI_DUMP_ERROR(" setsockopt SO_REUSEADDR failed (%d:%s)\n", errno, strerror(errno));
close(itti_listen_socket);
pthread_exit(NULL);
}
/* Set socket to be non-blocking.
* NOTE: sockets accepted will inherit this option.
*/
rc = ioctl(itti_listen_socket, FIONBIO, (char *)&on);
if (rc < 0) {
ITTI_DUMP_ERROR(" ioctl FIONBIO (non-blocking) failed (%d:%s)\n", errno, strerror(errno));
close(itti_listen_socket);
pthread_exit(NULL);
}
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(ITTI_PORT);
if (bind(itti_listen_socket, (struct sockaddr *) &servaddr,
sizeof(servaddr)) < 0) {
ITTI_DUMP_ERROR(" Bind failed (%d:%s)\n", errno, strerror(errno));
pthread_exit(NULL);
}
if (listen(itti_listen_socket, 5) < 0) {
ITTI_DUMP_ERROR(" Listen failed (%d:%s)\n", errno, strerror(errno));
pthread_exit(NULL);
}
FD_ZERO(&read_set);
/* Add the listener */
FD_SET(itti_listen_socket, &read_set);
/* Add the event fd */
FD_SET(itti_dump_queue.event_fd, &read_set);
/* Max of both sd */
max_sd = itti_listen_socket > itti_dump_queue.event_fd ? itti_listen_socket : itti_dump_queue.event_fd;
itti_dump_queue.itti_listen_socket = itti_listen_socket;
/* Loop waiting for incoming connects or for incoming data
* on any of the connected sockets.
*/
while (1) {
int desc_ready;
int client_socket = -1;
int i;
memcpy(&working_set, &read_set, sizeof(read_set));
timeout_p = NULL;
/* No timeout: select blocks till a new event has to be handled
* on sd's.
*/
rc = select(max_sd + 1, &working_set, NULL, NULL, timeout_p);
if (rc < 0) {
ITTI_DUMP_ERROR(" select failed (%d:%s)\n", errno, strerror(errno));
pthread_exit(NULL);
} else if (rc == 0) {
/* Timeout */
if (itti_dump_flush_ring_buffer(1) == 0) {
if (itti_dump_running) {
ITTI_DUMP_DEBUG (0x4, " No messages consumers, waiting ...\n");
usleep(100 * 1000);
} else {
itti_dump_socket_exit();
}
}
}
desc_ready = rc;
for (i = 0; i <= max_sd && desc_ready > 0; i++) {
if (FD_ISSET(i, &working_set)) {
desc_ready -= 1;
if (i == itti_dump_queue.event_fd) {
/* Notification of new element to dump from other tasks */
eventfd_t sem_counter;
ssize_t read_ret;
/* Read will always return 1 for kernel versions > 2.6.30 */
read_ret = read (itti_dump_queue.event_fd, &sem_counter, sizeof(sem_counter));
if (read_ret < 0) {
ITTI_DUMP_ERROR(" Failed read for semaphore: %s\n", strerror(errno));
pthread_exit(NULL);
}
AssertFatal (read_ret == sizeof(sem_counter), "Failed to read from dump event FD (%d/%d)!\n", (int) read_ret, (int) sizeof(sem_counter));
if (itti_dump_flush_ring_buffer(0) == 0) {
if (itti_dump_running) {
ITTI_DUMP_DEBUG (0x4, " No messages consumers, waiting ...\n");
usleep(100 * 1000);
{
ssize_t write_ret;
sem_counter = 1;
/* Call to write for an event fd must be of 8 bytes */
write_ret = write(itti_dump_queue.event_fd, &sem_counter, sizeof(sem_counter));
AssertFatal (write_ret == sizeof(sem_counter), "Failed to write to dump event FD (%d/%d)!\n", (int) write_ret, (int) sem_counter);
}
} else {
itti_dump_socket_exit();
}
} else {
ITTI_DUMP_DEBUG(0x1, " Write element to file\n");
}
} else
if (i == itti_listen_socket) {
do {
client_socket = accept(itti_listen_socket, NULL, NULL);
if (client_socket < 0) {
if (errno == EWOULDBLOCK || errno == EAGAIN) {
/* No more new connection */
ITTI_DUMP_DEBUG(0x2, " No more new connection\n");
continue;
} else {
ITTI_DUMP_ERROR(" accept failed (%d:%s)\n", errno, strerror(errno));
pthread_exit(NULL);
}
}
if (itti_dump_handle_new_connection(client_socket, message_definition_xml,
message_definition_xml_length) == 0) {
/* The socket has been accepted.
* We have to update the set to include this new sd.
*/
FD_SET(client_socket, &read_set);
if (client_socket > max_sd)
max_sd = client_socket;
}
} while(client_socket != -1);
} else {
/* For now the MME itti dumper should not receive data
* other than connection oriented (CLOSE).
*/
uint8_t j;
ITTI_DUMP_DEBUG(0x2, " Socket %d disconnected\n", i);
/* Close the socket and update info related to this connection */
close(i);
for (j = 0; j < ITTI_DUMP_MAX_CON; j++) {
if (itti_dump_queue.itti_clients[j].sd == i)
break;
}
/* In case we don't find the matching sd in list of known
* connections -> assert.
*/
AssertFatal (j < ITTI_DUMP_MAX_CON, "Connection index not found (%d/%d) for socked %d!\n", j, ITTI_DUMP_MAX_CON, i);
/* Re-initialize the socket to -1 so we can accept new
* incoming connections.
*/
itti_dump_queue.itti_clients[j].sd = -1;
itti_dump_queue.itti_clients[j].last_message_number = 0;
itti_dump_queue.nb_connected--;
/* Remove the socket from the FD set and update the max sd */
FD_CLR(i, &read_set);
if (i == max_sd) {
if (itti_dump_queue.nb_connected == 0) {
/* No more new connection max_sd = itti_listen_socket */
max_sd = itti_listen_socket;
} else {
while (FD_ISSET(max_sd, &read_set) == 0) {
max_sd -= 1;
}
}
}
}
}
}
}
return NULL;
}
/*------------------------------------------------------------------------------*/
int itti_dump_queue_message(task_id_t sender_task,
message_number_t message_number,
MessageDef *message_p,
const char *message_name,
const uint32_t message_size)
{
if (itti_dump_running) {
itti_dump_queue_item_t *new;
AssertFatal (message_name != NULL, "Message name is NULL!\n");
AssertFatal (message_p != NULL, "Message is NULL!\n");
new = itti_malloc(sender_task, TASK_MAX, sizeof(itti_dump_queue_item_t));
new->data = itti_malloc(sender_task, TASK_MAX, message_size);
memcpy(new->data, message_p, message_size);
new->data_size = message_size;
new->message_number = message_number;
itti_dump_enqueue_message(new, message_size, ITTI_DUMP_MESSAGE_TYPE);
}
return 0;
}
/* This function should be called by each thread that will use the ring buffer */
void itti_dump_thread_use_ring_buffer(void)
{
lfds611_ringbuffer_use(itti_dump_queue.itti_message_queue);
}
int itti_dump_init(const char * const messages_definition_xml, const char * const dump_file_name)
{
int i, ret;
struct sched_param scheduler_param;
scheduler_param.sched_priority = sched_get_priority_min(SCHED_FIFO) + 1;
if (dump_file_name != NULL) {
dump_file = fopen(dump_file_name, "wb");
if (dump_file == NULL) {
ITTI_DUMP_ERROR(" can not open dump file \"%s\" (%d:%s)\n", dump_file_name, errno, strerror(errno));
} else {
/* Output the XML to file */
uint32_t message_size = strlen(messages_definition_xml) + 1;
itti_socket_header_t header;
header.message_size = sizeof(itti_socket_header_t) + message_size + sizeof(itti_message_types_t);
header.message_type = ITTI_DUMP_XML_DEFINITION;
fwrite (&header, sizeof(itti_socket_header_t), 1, dump_file);
fwrite (messages_definition_xml, message_size, 1, dump_file);
fwrite (&itti_dump_xml_definition_end, sizeof(itti_message_types_t), 1, dump_file);
fflush (dump_file);
}
}
memset(&itti_dump_queue, 0, sizeof(itti_desc_t));
ITTI_DUMP_DEBUG(0x2, " Creating new ring buffer for itti dump of %u elements\n",
ITTI_QUEUE_MAX_ELEMENTS);
if (lfds611_ringbuffer_new(&itti_dump_queue.itti_message_queue,
ITTI_QUEUE_MAX_ELEMENTS,
NULL,
NULL) != 1) {
/* Always assert on this condition */
AssertFatal (0, " Failed to create ring buffer!\n");
}
itti_dump_queue.event_fd = eventfd(0, EFD_SEMAPHORE);
if (itti_dump_queue.event_fd == -1) {
/* Always assert on this condition */
AssertFatal (0, "eventfd failed: %s!\n", strerror(errno));
}
itti_dump_queue.nb_connected = 0;
for(i = 0; i < ITTI_DUMP_MAX_CON; i++) {
itti_dump_queue.itti_clients[i].sd = -1;
itti_dump_queue.itti_clients[i].last_message_number = 0;
}
/* initialized with default attributes */
ret = pthread_attr_init(&itti_dump_queue.attr);
if (ret < 0) {
AssertFatal (0, "pthread_attr_init failed (%d:%s)!\n", errno, strerror(errno));
}
ret = pthread_attr_setschedpolicy(&itti_dump_queue.attr, SCHED_FIFO);
if (ret < 0) {
AssertFatal (0, "pthread_attr_setschedpolicy (SCHED_IDLE) failed (%d:%s)!\n", errno, strerror(errno));
}
ret = pthread_attr_setschedparam(&itti_dump_queue.attr, &scheduler_param);
if (ret < 0) {
AssertFatal (0, "pthread_attr_setschedparam failed (%d:%s)!\n", errno, strerror(errno));
}
ret = pthread_create(&itti_dump_queue.itti_acceptor_thread, &itti_dump_queue.attr,
&itti_dump_socket, (void *)messages_definition_xml);
if (ret < 0) {
AssertFatal (0, "pthread_create failed (%d:%s)!\n", errno, strerror(errno));
}
pthread_setname_np( itti_dump_queue.itti_acceptor_thread, "ITTI acceptor" );
return 0;
}
void itti_dump_exit(void)
{
void *arg;
itti_dump_queue_item_t *new;
new = itti_malloc(TASK_UNKNOWN, TASK_UNKNOWN, sizeof(itti_dump_queue_item_t));
memset(new, 0, sizeof(itti_dump_queue_item_t));
/* Set a flag to stop recording message */
itti_dump_running = 0;
/* Send the exit signal to other thread */
itti_dump_enqueue_message(new, 0, ITTI_DUMP_EXIT_SIGNAL);
ITTI_DUMP_DEBUG(0x2, " waiting for dumper thread to finish\n");
/* wait for the thread to terminate */
pthread_join(itti_dump_queue.itti_acceptor_thread, &arg);
ITTI_DUMP_DEBUG(0x2, " dumper thread correctly exited\n");
if (dump_file != NULL) {
/* Synchronise file and then close it */
fclose(dump_file);
dump_file = NULL;
}
if (itti_dump_queue.itti_message_queue) {
lfds611_ringbuffer_delete(itti_dump_queue.itti_message_queue,
itti_dump_user_data_delete_function, NULL);
}
}
+1 -6
View File
@@ -41,10 +41,6 @@
#ifndef CHECK_PROTOTYPE_ONLY
const char * const messages_definition_xml = {
#include "messages_xml.h"
};
/* Map task id to printable name. */
const task_info_t tasks_info[] = {
{0, TASK_UNKNOWN, 0, 0, "TASK_UNKNOWN"},
@@ -71,8 +67,7 @@ const message_info_t messages_info[] = {
* \param messages_info Pointer on messages information as created by this include file
**/
int itti_init(task_id_t task_max, thread_id_t thread_max, MessagesIds messages_id_max, const task_info_t *tasks_info,
const message_info_t *messages_info, const char * const messages_definition_xml,
const char * const dump_file_name);
const message_info_t *messages_info);
#endif /* INTERTASK_INTERFACE_INIT_H_ */
/* @} */
+2 -2
View File
@@ -42,8 +42,8 @@
#include "log.h"
#if defined (LOG_D) && defined (LOG_E)
# define SIG_DEBUG(x, args...) LOG_D(EMU, x, ##args)
# define SIG_ERROR(x, args...) LOG_E(EMU, x, ##args)
# define SIG_DEBUG(x, args...) LOG_D(RRC, x, ##args)
# define SIG_ERROR(x, args...) LOG_E(RRC, x, ##args)
#endif
#ifndef SIG_DEBUG
@@ -740,25 +740,6 @@ int xml_parse_buffer(char *xml_buffer, const int size) {
return xml_parse_doc(doc);
}
#if 0 /* Not used anymore */
int xml_parse_file(const char *filename) {
xmlDocPtr doc; /* the resulting document tree */
if (filename == NULL) {
return RC_NULL_POINTER;
}
doc = xmlReadFile (filename, NULL, 0);
if (doc == NULL) {
ui_notification_dialog(GTK_MESSAGE_ERROR, FALSE, "parse messages format definition", "Failed to parse file \"%s\"", filename);
return RC_FAIL;
}
return xml_parse_doc(doc);
}
#endif
static int update_filters() {
types_t *types;
+1 -1
View File
@@ -32,7 +32,7 @@
#ifdef TELNETSRV_LOADER_MAIN
#include "UTIL/LOG/log.h"
#include "common/utils/LOG/log.h"
#include "common/utils/load_module_shlib.h"
+2 -2
View File
@@ -32,10 +32,10 @@
#ifdef TELNETSRV_PHYCMD_MAIN
#include "UTIL/LOG/log.h"
#include "common/utils/LOG/log.h"
#include "openair1/PHY/extern.h"
#include "openair1/PHY/phy_extern.h"
#define TELNETVAR_PHYCC0 0
+88 -20
View File
@@ -52,10 +52,9 @@
#define TELNETSERVERCODE
#include "telnetsrv.h"
#define TELNETSRV_PROCCMD_MAIN
#include "log.h"
#include "log_extern.h"
#include "common/utils/LOG/log.h"
#include "common/config/config_userapi.h"
#include "openair1/PHY/extern.h"
#include "openair1/PHY/phy_extern.h"
#include "telnetsrv_proccmd.h"
void decode_procstat(char *record, int debug, telnet_printfunc_t prnt)
@@ -193,7 +192,6 @@ struct dirent *entry;
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);
@@ -201,12 +199,28 @@ extern log_t *g_log;
print_threads(buf,debug,prnt);
}
if (strcasestr(buf,"loglvl") != NULL) {
prnt("component verbosity level enabled\n");
prnt(" component level enabled\n");
for (int i=MIN_LOG_COMPONENTS; i < MAX_LOG_COMPONENTS; i++) {
prnt("%02i %17.17s:%10.10s%10.10s %s\n",i ,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),
((g_log->log_component[i].interval>0)?"Y":"N") );
if (g_log->log_component[i].name != NULL) {
prnt("%02i %17.17s:%10.10s %s\n",i ,g_log->log_component[i].name,
map_int_to_str(log_level_names,g_log->log_component[i].level),
((g_log->log_component[i].interval>0)?"Y":"N") );
}
}
}
if (strcasestr(buf,"logopt") != NULL) {
prnt(" option enabled\n");
for (int i=0; log_options[i].name != NULL; i++) {
prnt("%02i %17.17s %10.10s \n",i ,log_options[i].name,
((g_log->flag & log_options[i].value)?"Y":"N") );
}
}
if (strcasestr(buf,"dbgopt") != NULL) {
prnt(" option debug matlab\n");
for (int i=0; log_maskmap[i].name != NULL ; i++) {
prnt("%02i %17.17s %5.5s %5.5s\n",i ,log_maskmap[i].name,
((g_log->debug_mask & log_maskmap[i].value)?"Y":"N"),
((g_log->matlab_mask & log_maskmap[i].value)?"Y":"N") );
}
}
if (strcasestr(buf,"config") != NULL) {
@@ -323,24 +337,76 @@ int s = sscanf(buf,"%ms %i-%i\n",&logsubcmd, &idx1,&idx2);
prnt("Available log levels: \n ");
for (int i=0; log_level_names[i].name != NULL; i++)
prnt("%s ",log_level_names[i].name);
prnt("\nAvailable verbosity: \n ");
for (int i=0; log_verbosity_names[i].name != NULL; i++)
prnt("%s ",log_verbosity_names[i].name);
prnt("\n");
prnt("Available display options: \n ");
for (int i=0; log_options[i].name != NULL; i++)
prnt("%s ",log_options[i].name);
prnt("\n");
prnt("Available debug or matlab options: \n ");
for (int i=0; log_maskmap[i].name != NULL; i++)
prnt("%s ",log_maskmap[i].name);
prnt("\n");
proccmd_show("loglvl",debug,prnt);
proccmd_show("logopt",debug,prnt);
proccmd_show("dbgopt",debug,prnt);
}
else if (strcasestr(logsubcmd,"help") != NULL) {
prnt(PROCCMD_LOG_HELP_STRING);
} else {
prnt("%s: wrong log command...\n",logsubcmd);
}
} else if ( s == 2 && logsubcmd != NULL) {
char *opt=NULL;
char *logparam=NULL;
int l;
int optbit;
l=sscanf(logsubcmd,"%m[^'_']_%ms",&logparam,&opt);
if (l == 2 && strcmp(logparam,"print") == 0){
optbit=map_str_to_int(log_options,opt);
if (optbit < 0) {
prnt("option %s unknown\n",opt);
} else {
if (idx1 > 0)
SET_LOG_OPTION(optbit);
else
CLEAR_LOG_OPTION(optbit);
proccmd_show("logopt",debug,prnt);
}
}
else if (l == 2 && strcmp(logparam,"debug") == 0){
optbit=map_str_to_int(log_maskmap,opt);
if (optbit < 0) {
prnt("debug flag %s unknown\n",opt);
} else {
if (idx1 > 0)
SET_LOG_DEBUG(optbit);
else
CLEAR_LOG_DEBUG(optbit);
proccmd_show("dbgopt",debug,prnt);
}
}
else if (l == 2 && strcmp(logparam,"matlab") == 0){
optbit=map_str_to_int(log_maskmap,opt);
if (optbit < 0) {
prnt("matlab flag %s unknown\n",opt);
} else {
if (idx1 > 0)
SET_LOG_MATLAB(optbit);
else
CLEAR_LOG_MATLAB(optbit);
proccmd_show("dbgopt",debug,prnt);
}
}
if (logparam != NULL) free(logparam);
if (opt != NULL) free(opt);
} else if ( s == 3 && logsubcmd != NULL) {
int level, verbosity, interval;
int level, interval;
char *tmpstr=NULL;
char *logparam=NULL;
int l;
level = verbosity = interval = -1;
level = interval = -1;
l=sscanf(logsubcmd,"%m[^'_']_%m[^'_']",&logparam,&tmpstr);
if (debug > 0)
prnt("l=%i, %s %s\n",l,((logparam==NULL)?"\"\"":logparam), ((tmpstr==NULL)?"\"\"":tmpstr));
@@ -348,9 +414,6 @@ int s = sscanf(buf,"%ms %i-%i\n",&logsubcmd, &idx1,&idx2);
if (strcmp(logparam,"level") == 0) {
level=map_str_to_int(log_level_names,tmpstr);
if (level < 0) prnt("level %s unknown\n",tmpstr);
} else if (strcmp(logparam,"verbos") == 0) {
verbosity=map_str_to_int(log_verbosity_names,tmpstr);
if (verbosity < 0) prnt("verbosity %s unknown\n",tmpstr);
} else {
prnt("%s%s unknown log sub command \n",logparam, tmpstr);
}
@@ -368,11 +431,16 @@ int s = sscanf(buf,"%ms %i-%i\n",&logsubcmd, &idx1,&idx2);
if (logparam != NULL) free(logparam);
if (tmpstr != NULL) free(tmpstr);
for (int i=idx1; i<=idx2 ; i++) {
set_comp_log(i, level, verbosity, interval);
prnt("log level/verbosity comp %i %s set to %s / %s (%s)\n",
if (level < 0) {
level=g_log->log_component[i].level;
}
if (interval < 0) {
interval=g_log->log_component[i].interval;
}
set_log(i, level, interval);
prnt("log level comp %i %s set to %s (%s)\n",
i,((g_log->log_component[i].name==NULL)?"":g_log->log_component[i].name),
map_int_to_str(log_level_names,g_log->log_component[i].level),
map_int_to_str(log_verbosity_names,g_log->log_component[i].flag),
((g_log->log_component[i].interval>0)?"enabled":"disabled"));
+6 -3
View File
@@ -49,9 +49,12 @@ telnetshell_vardef_t proc_vardef[] = {
online, noonline: enable or disable console logs \n\
enable, disable id1-id2: enable or disable logs for components index id1 to id2 \n\
level_<level> id1-id2: set log level to <level> for components index id1 to id2 \n\
level_<verbosity> id1-id2: set log verbosity to <verbosity> for components index id1 to id2 \n\
use the show command to get the values for <level>, <verbosity> and the list of component indexes \
that can be used for id1 and id2 \n"
use the show command to get the authorized values for <level> and the list of component \
indexes that can be used for id1 and id2 \n\
print_<opt> <0|1> disable or enable the \"opt\" log option, use the show command to get \
the available options\n\
matlab_<opt> debug_<func> disable or enable the debug code or matlab file generation \
for \"func\" function. use the show command to get the available options\n"
#define PROCCMD_THREAD_HELP_STRING " thread sub commands: \n\
<thread id> aff <core> : set affinity of thread <thread id> to core <core> \n\