Files
openairinterface5g/common/utils/telnetsrv/telnetsrv_proccmd.c
T

463 lines
15 KiB
C

/*
* 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 common/utils/telnetsrv/telnetsrv_proccmd.c
* \brief: implementation of telnet commands related to this linux process
* \author Francois TABURET
* \date 2017
* \version 0.1
* \company NOKIA BellLabs France
* \email: francois.taburet@nokia-bell-labs.com
* \note
* \warning
*/
#define _GNU_SOURCE
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <pthread.h>
#include <string.h>
#include <stdarg.h>
#include <dirent.h>
#define READCFG_DYNLOAD
#define TELNETSERVERCODE
#include "telnetsrv.h"
#define TELNETSRV_PROCCMD_MAIN
#include "common/utils/LOG/log.h"
#include "common/config/config_userapi.h"
#include "openair1/PHY/phy_extern.h"
#include "telnetsrv_proccmd.h"
void decode_procstat(char *record, int debug, telnet_printfunc_t prnt)
{
char prntline[160];
char *procfile_fiels;
char *strtokptr;
char *lptr;
int fieldcnt;
char toksep[2];
fieldcnt=0;
procfile_fiels =strtok_r(record," ",&strtokptr);
lptr= prntline;
/*http://man7.org/linux/man-pages/man5/proc.5.html gives the structure of the stat file */
while( procfile_fiels != NULL && fieldcnt < 42) {
long int policy;
if (strlen(procfile_fiels) == 0)
continue;
fieldcnt++;
sprintf(toksep," ");
switch(fieldcnt) {
case 1: /* id */
lptr+=sprintf(lptr,"%9.9s ",procfile_fiels);
sprintf(toksep,")");
break;
case 2: /* name */
lptr+=sprintf(lptr,"%20.20s ",procfile_fiels+1);
break;
case 3: //thread state
lptr+=sprintf(lptr," %c ",procfile_fiels[0]);
break;
case 14: //time in user mode
case 15: //time in kernel mode
lptr+=sprintf(lptr,"%9.9s ",procfile_fiels);
break;
case 18: //priority
case 19: //nice
lptr+=sprintf(lptr,"%3.3s ",procfile_fiels);
break;
case 23: //vsize
lptr+=sprintf(lptr,"%9.9s ",procfile_fiels);
break;
case 39: //processor
lptr+=sprintf(lptr," %2.2s ",procfile_fiels);
break;
case 41: //policy
lptr+=sprintf(lptr,"%3.3s ",procfile_fiels);
policy=strtol(procfile_fiels,NULL,0);
switch(policy) {
case SCHED_FIFO:
lptr+=sprintf(lptr,"%s ","rt: fifo");
break;
case SCHED_OTHER:
lptr+=sprintf(lptr,"%s ","other");
break;
case SCHED_IDLE:
lptr+=sprintf(lptr,"%s ","idle");
break;
case SCHED_BATCH:
lptr+=sprintf(lptr,"%s ","batch");
break;
case SCHED_RR:
lptr+=sprintf(lptr,"%s ","rt: rr");
break;
default:
lptr+=sprintf(lptr,"%s ","????");
break;
}
break;
default:
break;
}/* switch on fieldcnr */
procfile_fiels =strtok_r(NULL,toksep,&strtokptr);
} /* while on proc_fields != NULL */
prnt("%s\n",prntline);
} /*decode_procstat */
void read_statfile(char *fname,int debug, telnet_printfunc_t prnt)
{
FILE *procfile;
char arecord[1024];
procfile=fopen(fname,"r");
if (procfile == NULL)
{
prnt("Error: Couldn't open %s %i %s\n",fname,errno,strerror(errno));
return;
}
if ( fgets(arecord,sizeof(arecord),procfile) == NULL)
{
prnt("Error: Nothing read from %s %i %s\n",fname,errno,strerror(errno));
fclose(procfile);
return;
}
fclose(procfile);
decode_procstat(arecord, debug, prnt);
}
void print_threads(char *buf, int debug, telnet_printfunc_t prnt)
{
char aname[256];
DIR *proc_dir;
struct dirent *entry;
prnt(" id name state USRmod KRNmod prio nice vsize proc pol \n\n");
snprintf(aname, sizeof(aname), "/proc/%d/stat", getpid());
read_statfile(aname,debug,prnt);
prnt("\n");
snprintf(aname, sizeof(aname), "/proc/%d/task", getpid());
proc_dir = opendir(aname);
if (proc_dir == NULL)
{
prnt("Error: Couldn't open %s %i %s\n",aname,errno,strerror(errno));
return;
}
while ((entry = readdir(proc_dir)) != NULL)
{
if(entry->d_name[0] == '.')
continue;
snprintf(aname, sizeof(aname), "/proc/%d/task/%.*s/stat", getpid(),(int)(sizeof(aname)-24),entry->d_name);
read_statfile(aname,debug,prnt);
} /* while entry != NULL */
closedir(proc_dir);
} /* print_threads */
int proccmd_show(char *buf, int debug, telnet_printfunc_t prnt)
{
if (debug > 0)
prnt(" proccmd_show received %s\n",buf);
if (strcasestr(buf,"thread") != NULL) {
print_threads(buf,debug,prnt);
}
if (strcasestr(buf,"loglvl") != NULL) {
prnt("\n component level enabled output\n");
for (int i=MIN_LOG_COMPONENTS; i < MAX_LOG_COMPONENTS; i++) {
if (g_log->log_component[i].name != NULL) {
prnt("%02i %17.17s:%10.10s %s %s\n",i ,g_log->log_component[i].name,
map_int_to_str(log_level_names,(g_log->log_component[i].level>=0)?g_log->log_component[i].level:g_log->log_component[i].savedlevel),
((g_log->log_component[i].level>=0)?"Y":"N"),
((g_log->log_component[i].filelog>0)?g_log->log_component[i].filelog_name:"stdout"));
}
}
}
if (strcasestr(buf,"logopt") != NULL) {
prnt("\n 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("\n module debug dumpfile\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->dump_mask & log_maskmap[i].value)?"Y":"N") );
}
}
if (strcasestr(buf,"config") != NULL) {
prnt("Command line arguments:\n");
for (int i=0; i < config_get_if()->argc; i++) {
prnt(" %02i %s\n",i ,config_get_if()->argv[i]);
}
prnt("Config module flags ( -O <cfg source>:<xxx>:dbgl<flags>): 0x%08x\n", config_get_if()->rtflags);
prnt(" Print config debug msg, params values (flag %u): %s\n",CONFIG_PRINTPARAMS,
((config_get_if()->rtflags & CONFIG_PRINTPARAMS) ? "Y" : "N") );
prnt(" Print config debug msg, memory management(flag %u): %s\n",CONFIG_DEBUGPTR,
((config_get_if()->rtflags & CONFIG_DEBUGPTR) ? "Y" : "N") );
prnt(" Print config debug msg, command line processing (flag %u): %s\n",CONFIG_DEBUGCMDLINE,
((config_get_if()->rtflags & CONFIG_DEBUGCMDLINE) ? "Y" : "N") );
prnt(" Don't exit if param check fails (flag %u): %s\n",CONFIG_NOABORTONCHKF,
((config_get_if()->rtflags & CONFIG_NOABORTONCHKF) ? "Y" : "N") );
prnt("Config source: %s, parameters:\n",CONFIG_GETSOURCE );
for (int i=0; i < config_get_if()->num_cfgP; i++) {
prnt(" %02i %s\n",i ,config_get_if()->cfgP[i]);
}
prnt("Softmodem components:\n");
prnt(" %02i Ru(s)\n", RC.nb_RU);
prnt(" %02i lte RRc(s), %02i NbIoT RRC(s)\n", RC.nb_inst, RC.nb_nb_iot_rrc_inst);
prnt(" %02i lte MACRLC(s), %02i NbIoT MACRLC(s)\n", RC.nb_macrlc_inst, RC.nb_nb_iot_macrlc_inst);
prnt(" %02i lte L1, %02i NbIoT L1\n", RC.nb_L1_inst, RC.nb_nb_iot_L1_inst);
for(int i=0; i<RC.nb_inst; i++) {
prnt(" lte RRC %i: %02i CC(s) \n",i,((RC.nb_CC == NULL)?0:RC.nb_CC[i]));
}
for(int i=0; i<RC.nb_L1_inst; i++) {
prnt(" lte L1 %i: %02i CC(s)\n",i,((RC.nb_L1_CC == NULL)?0:RC.nb_L1_CC[i]));
}
for(int i=0; i<RC.nb_macrlc_inst; i++) {
prnt(" lte macrlc %i: %02i CC(s)\n",i,((RC.nb_mac_CC == NULL)?0:RC.nb_mac_CC[i]));
}
}
return 0;
}
int proccmd_thread(char *buf, int debug, telnet_printfunc_t prnt)
{
int bv1,bv2;
int res;
char sv1[64];
bv1=0;
bv2=0;
sv1[0]=0;
if (debug > 0)
prnt("proccmd_thread received %s\n",buf);
if (strcasestr(buf,"help") != NULL) {
prnt(PROCCMD_THREAD_HELP_STRING);
return 0;
}
res=sscanf(buf,"%i %9s %i",&bv1,sv1,&bv2);
if (debug > 0)
prnt(" proccmd_thread: %i params = %i,%s,%i\n",res,bv1,sv1,bv2);
if(res != 3)
{
prnt("softmodem thread needs 3 params, %i received\n",res);
return 0;
}
if (strcasestr(sv1,"prio") != NULL)
{
set_sched(0,bv1, bv2);
}
else if (strcasestr(sv1,"aff") != NULL)
{
set_affinity(0,bv1, bv2);
}
else
{
prnt("%s is not a valid thread command\n",sv1);
}
return 0;
}
int proccmd_exit(char *buf, int debug, telnet_printfunc_t prnt)
{
if (debug > 0)
prnt("process module received %s\n",buf);
exit_fun("telnet server received exit command\n");
return 0;
}
int proccmd_log(char *buf, int debug, telnet_printfunc_t prnt)
{
int idx1=0;
int idx2=NUM_LOG_LEVEL-1;
char *logsubcmd=NULL;
int s = sscanf(buf,"%ms %i-%i\n",&logsubcmd, &idx1,&idx2);
if (debug > 0)
prnt( "proccmd_log received %s\n s=%i sub command %s\n",buf,s,((logsubcmd==NULL)?"":logsubcmd));
if (s == 1 && logsubcmd != NULL) {
if (strcasestr(logsubcmd,"online") != NULL) {
if (strcasestr(buf,"noonline") != NULL) {
set_glog_onlinelog(0);
prnt("online logging disabled\n",buf);
} else {
set_glog_onlinelog(1);
prnt("online logging enabled\n",buf);
}
}
else if (strcasestr(logsubcmd,"show") != NULL) {
prnt("Available log levels: \n ");
for (int i=0; log_level_names[i].name != NULL; i++)
prnt("%s ",log_level_names[i].name);
prnt("\n\n");
prnt("Available display options: \n ");
for (int i=0; log_options[i].name != NULL; i++)
prnt("%s ",log_options[i].name);
prnt("\n\n");
prnt("Available debug and dump options: \n ");
for (int i=0; log_maskmap[i].name != NULL; i++)
prnt("%s ",log_maskmap[i].name);
prnt("\n\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("module %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,"dump") == 0){
optbit=map_str_to_int(log_maskmap,opt);
if (optbit < 0) {
prnt("module %s unknown\n",opt);
} else {
if (idx1 > 0)
SET_LOG_DUMP(optbit);
else
CLEAR_LOG_DUMP(optbit);
proccmd_show("dbgopt",debug,prnt);
}
}
if (logparam != NULL) free(logparam);
if (opt != NULL) free(opt);
} else if ( s == 3 && logsubcmd != NULL) {
int level, enable,filelog;
char *tmpstr=NULL;
char *logparam=NULL;
int l;
level = OAILOG_DISABLE - 1;
filelog = -1;
enable=-1;
l=sscanf(logsubcmd,"%m[^'_']_%m[^'_']",&logparam,&tmpstr);
if (debug > 0)
prnt("l=%i, %s %s\n",l,((logparam==NULL)?"\"\"":logparam), ((tmpstr==NULL)?"\"\"":tmpstr));
if (l ==2 ) {
if (strcmp(logparam,"level") == 0) {
level=map_str_to_int(log_level_names,tmpstr);
if (level < 0) {
prnt("level %s unknown\n",tmpstr);
level=OAILOG_DISABLE - 1;
}
} else {
prnt("%s%s unknown log sub command \n",logparam, tmpstr);
}
} else if (l ==1 ) {
if (strcmp(logparam,"enable") == 0) {
enable=1;
} else if (strcmp(logparam,"disable") == 0) {
level=OAILOG_DISABLE;
} else if (strcmp(logparam,"file") == 0) {
filelog = 1 ;
} else if (strcmp(logparam,"nofile") == 0) {
filelog = 0 ;
} else {
prnt("%s%s unknown log sub command \n",logparam, tmpstr);
}
} else {
prnt("%s unknown log sub command \n",logsubcmd);
}
if (logparam != NULL) free(logparam);
if (tmpstr != NULL) free(tmpstr);
for (int i=idx1; i<=idx2 ; i++) {
if (level >= OAILOG_DISABLE)
set_log(i, level);
else if ( enable == 1)
set_log(i,g_log->log_component[i].savedlevel);
else if ( filelog == 1 ) {
set_component_filelog(i);
} else if ( filelog == 0 ) {
close_component_filelog(i);
}
}
proccmd_show("loglvl",debug,prnt);
} else {
prnt("%s: wrong log command...\n",buf);
}
return 0;
}
/*-------------------------------------------------------------------------------------*/
void add_softmodem_cmds(void)
{
add_telnetcmd("softmodem",proc_vardef,proc_cmdarray);
}