From 30abbdf8263fba81b0690046a80135013521f6b7 Mon Sep 17 00:00:00 2001
From: frtabu <francois.taburet@nokia-bell-labs.com>
Date: Fri, 29 Sep 2017 02:07:33 +0200
Subject: [PATCH] prepare for telnet server integration

---
 common/config/config_cmdline.c             |   2 +-
 common/utils/telnetsrv/CMakeLists.txt      |  52 ++
 common/utils/telnetsrv/load_telnet.c       |  45 ++
 common/utils/telnetsrv/load_telnet.h       |   5 +
 common/utils/telnetsrv/telnetsrv.c         | 696 +++++++++++++++++++++
 common/utils/telnetsrv/telnetsrv.h         | 108 ++++
 common/utils/telnetsrv/telnetsrv_phycmd.c  | 134 ++++
 common/utils/telnetsrv/telnetsrv_phycmd.h  |  34 +
 common/utils/telnetsrv/telnetsrv_proccmd.c | 226 +++++++
 common/utils/telnetsrv/telnetsrv_proccmd.h |  56 ++
 targets/RT/USER/lte-softmodem.c            |   2 +-
 11 files changed, 1358 insertions(+), 2 deletions(-)
 create mode 100644 common/utils/telnetsrv/CMakeLists.txt
 create mode 100644 common/utils/telnetsrv/load_telnet.c
 create mode 100644 common/utils/telnetsrv/load_telnet.h
 create mode 100644 common/utils/telnetsrv/telnetsrv.c
 create mode 100644 common/utils/telnetsrv/telnetsrv.h
 create mode 100644 common/utils/telnetsrv/telnetsrv_phycmd.c
 create mode 100644 common/utils/telnetsrv/telnetsrv_phycmd.h
 create mode 100644 common/utils/telnetsrv/telnetsrv_proccmd.c
 create mode 100644 common/utils/telnetsrv/telnetsrv_proccmd.h

diff --git a/common/config/config_cmdline.c b/common/config/config_cmdline.c
index c22ecf964a..170f8963cf 100644
--- a/common/config/config_cmdline.c
+++ b/common/config/config_cmdline.c
@@ -54,7 +54,7 @@ char defbool[2]="1";
      } else {        /* boolean value */
          tmpval = defbool;
      }
-     printf("cc 0x%08x, %i\n",tmpval,argok);
+     
      switch(cfgoptions->type)
        {
        	case TYPE_STRING:
diff --git a/common/utils/telnetsrv/CMakeLists.txt b/common/utils/telnetsrv/CMakeLists.txt
new file mode 100644
index 0000000000..6e6c21c2db
--- /dev/null
+++ b/common/utils/telnetsrv/CMakeLists.txt
@@ -0,0 +1,52 @@
+cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
+IF(DEFINED ENV{OPENAIR_DIR})
+  message("...using oai source files in $ENV{OPENAIR_DIR}")
+ELSE()
+  message("OPENAIR_DIR is not defined.  You must run \"source oaienv\" from the oai root dir")
+  # exit early 
+  return()
+ENDIF()
+
+
+set(APPROOT . )
+set(OPENAIR_DIR $ENV{OPENAIR_DIR})
+set(OPENAIR_BUILD_DIR $ENV{OPENAIR_DIR}/cmake_targets)
+set(OPENAIR1_DIR $ENV{OPENAIR1_DIR})
+set(OPENAIR2_DIR $ENV{OPENAIR2_DIR})
+set(OPENAIR_PHY_DIR $ENV{OPENAIR1_DIR}/PHY)
+set(OPENAIR_TARGET_DIR $ENV{OPENAIR_DIR}/targets)
+set(OPENAIR_COMMONUTILS_DIR $ENV{OPENAIR_DIR}/common/utils)
+set(OPENAIR2_COMMON_DIR $ENV{OPENAIR_DIR}/openair2/COMMON)
+set(OPENAIR_ASN1INC  ${OPENAIR_BUILD_DIR}/lte_build_oai/build/CMakeFiles/Rel14)
+set(OPENAIR_NFAPIINC $ENV{NFAPI_DIR} )
+
+set(CMAKE_INSTALL_PREFIX $ENV{OPENAIR_TARGETS})
+
+add_definitions (-DRel14  -DCMAKER -DENABLE_FXP -DENABLE_ITTI -DENABLE_NAS_UE_LOGGING -DENABLE_SECURITY  -DENABLE_USE_CPU_EXECUTION_TIME  -DENABLE_USE_MME -DENABLE_VCD -DENB_AGENT -DENB_MODE -DETHERNET=1  -DEXMIMO_IOT -DJUMBO_FRAME  -DLINK_ENB_PDCP_TO_GTPV1U -DLOG_NO_THREAD -DMAC_CONTEXT -DMAX_NUM_CCs=1  -DNAS_BUILT_IN_UE -DNAS_UE  -DNB_ANTENNAS_RX=2 -DNB_ANTENNAS_TX=2 -DNB_ANTENNAS_TXRX=2 -DNEW_FFT -DNO_RRM -DNone=1 -DOAI_NW_DRIVER_USE_NETLINK  -DOPENAIR1 -DOPENAIR2  -DOPENAIR_LTE -DPC_DSP -DPC_TARGET -DPHYSIM  -DPHY_CONTEXT -DPUCCH -DRel10=1  -DS1AP_VERSION=R10   -DTRACE_RLC_MUTEX -DUSER_MODE -DX2AP_VERSION=R11 -DXFORMS -mavx2 -msse4.1 -mssse3)
+add_compile_options( -fPIC -march=native -Ofast)
+
+include_directories( ./ ${OPENAIR_COMMON_DIR} ${OPENAIR_DIR} ${OPENAIR1_DIR} ${OPENAIR2_DIR} ${OPENAIR2_COMMON_DIR} ${OPENAIR2_DIR}/UTIL/LOG 
+                    ${OPENAIR_COMMONUTILS_DIR}/msc ${OPENAIR_COMMONUTILS_DIR}/itti ${OPENAIR_ASN1INC} ${OPENAIR_TARGET_DIR}/COMMON  ${OPENAIR_TARGET_DIR}/ARCH/COMMON
+		    ${OPENAIR_NFAPIINC})
+
+set(TELNETSRV_SOURCE
+    ${APPROOT}/telnetsrv.c
+    ${APPROOT}/telnetsrv_phycmd.c
+    ${APPROOT}/telnetsrv_proccmd.c
+    )
+
+#set(TELNETSRV_ETHDEVCMD_SOURCE
+#    ${APPROOT}/telnetsrv/telnetsrv_ethdevcmd.c
+#    )
+
+
+
+add_library(telnetsrv MODULE ${TELNETSRV_SOURCE} )
+#add_library(telnetsrv_ethdevcmd MODULE ${TELNETSRV_ETHDEVCMD_SOURCE} )
+
+
+install(TARGETS telnetsrv DESTINATION bin)
+
+if (EXISTS "${OPENAIR_BUILD_DIR}/lte_build_oai/build" AND IS_DIRECTORY "${OPENAIR_BUILD_DIR}/lte_build_oai/build")
+     install(TARGETS telnetsrv DESTINATION ${OPENAIR_BUILD_DIR}/lte_build_oai/build)
+endif (EXISTS "${OPENAIR_BUILD_DIR}/lte_build_oai/build" AND IS_DIRECTORY "${OPENAIR_BUILD_DIR}/lte_build_oai/build")
diff --git a/common/utils/telnetsrv/load_telnet.c b/common/utils/telnetsrv/load_telnet.c
new file mode 100644
index 0000000000..850c025313
--- /dev/null
+++ b/common/utils/telnetsrv/load_telnet.c
@@ -0,0 +1,45 @@
+
+/* FT NOKBLF:
+ *  this source is to be linked with the program using the telnet server, it looks for
+ *  the telnet server dynamic library, possibly loads it and calls the telnet server
+ *  init functions
+*/
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <dlfcn.h>
+#include "telnetsrv.h"
+#include "openair1/PHY/defs.h"
+
+int load_telnet(void)
+{
+   void *lib_handle;
+   initfunc_t fpi;
+
+ 
+   lib_handle = dlopen(TELNETSRV_SHAREDLIB, RTLD_LAZY|RTLD_NODELETE|RTLD_GLOBAL);
+   if (!lib_handle) 
+   {
+      printf("[TELNETSRV] telnet server is not loaded: %s\n", dlerror());
+      return -1;
+   } 
+   
+   fpi = dlsym(lib_handle,"init_telnetsrv");
+
+     if (fpi != NULL )
+         {
+	 fpi(cfgfile);
+	 }
+      else
+         {
+         fprintf(stderr,"[TELNETSRV] %s %d Telnet server init function not found %s\n",__FILE__, __LINE__, dlerror());
+         return -1;
+         } 
+	  	 
+
+   dlclose(lib_handle); 
+   return 0;	       
+}
diff --git a/common/utils/telnetsrv/load_telnet.h b/common/utils/telnetsrv/load_telnet.h
new file mode 100644
index 0000000000..73543fe38a
--- /dev/null
+++ b/common/utils/telnetsrv/load_telnet.h
@@ -0,0 +1,5 @@
+#ifndef TELNET_LOAD_H
+#define TELNET_LOAD_H
+#include "telnetsrv.h"
+extern int load_telnet(void);
+#endif
diff --git a/common/utils/telnetsrv/telnetsrv.c b/common/utils/telnetsrv/telnetsrv.c
new file mode 100644
index 0000000000..6d6b84f568
--- /dev/null
+++ b/common/utils/telnetsrv/telnetsrv.c
@@ -0,0 +1,696 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.0  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file common/utils/telnetsrv.c
+ * \brief: implementation of a telnet server
+ * \author Francois TABURET
+ * \date 2017
+ * \version 0.1
+ * \company NOKIA BellLabs France
+ * \email: francois.taburet@nokia-bell-labs.com
+ * \note
+ * \warning
+ */
+#define _GNU_SOURCE
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <pthread.h>
+#include <telnetsrv.h>
+#include <string.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <dlfcn.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+
+#include "common/config/config_userapi.h"
+
+
+#include "telnetsrv_phycmd.h"
+#include "telnetsrv_proccmd.h"	
+static char* telnet_defstatmod[] = {"softmodem","phy"}; 
+static telnetsrv_params_t telnetparams;
+#define TELNETSRV_LISTENADDR 0
+#define TELNETSRV_LISTENPORT 1
+#define TELNETSRV_PRIORITY   2
+#define TELNETSRV_DEBUG      3
+#define TELNETSRV_STATICMOD  7
+#define TELNETSRV_SHRMOD     8
+paramdef_t telnetoptions[] = {
+/*--------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
+/*                                            configuration parameters for telnet utility                                                                             */
+/*   optname                     helpstr                paramflags           XXXptr                               defXXXval               type                 numelt */
+/*--------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
+	{"listenaddr",    "<listen ip address>",         0,                 uptr:&telnetparams.listenaddr,        defstrval:"0.0.0.0",            TYPE_IPV4ADDR,  0 },
+	{"listenport",    "<local port>",                0,                 uptr:&(telnetparams.listenport),      defuintval:9090,                TYPE_UINT,      0 },
+        {"priority",      "<scheduling policy (0-99)",   0,                 uptr:&telnetparams.priority,          defuintval:0,                   TYPE_INT,       0 }, 
+	{"debug",         "<debug level>",               0,                 uptr:NULL,                            defuintval:0,                   TYPE_UINT,      0 },
+	{"loopcount",     "<loop command iterations>",   0,                 uptr:&(telnetparams.loopcount),       defuintval:10,                  TYPE_UINT,      0 },
+	{"loopdelay",     "<loop command delay (ms)>",   0,                 uptr:&(telnetparams.loopdelay),       defuintval:5000,                TYPE_UINT,      0 },
+	{"phypbsize",     "<phy dump buff size (bytes)>",0,                 uptr:&(telnetparams.phyprntbuff_size),defuintval:65000,               TYPE_UINT,      0 },
+        {"staticmod",     "<static modules selection>",  0,                 NULL,                                 defstrlistval:telnet_defstatmod,TYPE_STRINGLIST,1},
+        {"shrmod",        "<static modules selection>",  0,                 NULL,                                 NULL,TYPE_STRINGLIST,0 },
+};
+
+int get_phybsize() {return telnetparams.phyprntbuff_size; };
+int add_telnetcmd(char *modulename,telnetshell_vardef_t *var, telnetshell_cmddef_t *cmd );
+int setoutput(char *buff, int debug, telnet_printfunc_t prnt);
+int setparam(char *buff, int debug, telnet_printfunc_t prnt);
+
+telnetshell_vardef_t telnet_vardef[] = {
+{"debug",TELNET_VARTYPE_INT32,&telnetparams.telnetdbg},
+{"prio",TELNET_VARTYPE_INT32,&telnetparams.priority},
+{"loopc",TELNET_VARTYPE_INT32,&telnetparams.loopcount},
+{"loopd",TELNET_VARTYPE_INT32,&telnetparams.loopdelay},
+{"phypb",TELNET_VARTYPE_INT32,&telnetparams.phyprntbuff_size},
+{"",0,NULL}
+};
+
+telnetshell_cmddef_t  telnet_cmdarray[] = {
+   {"redirlog","[here,file,off]",setoutput},
+   {"param","[prio]",setparam},
+   {"","",NULL},
+};
+
+
+void client_printf(const char *message, ...)
+{
+    va_list va_args;
+    
+    va_start(va_args, message);
+    if (telnetparams.new_socket > 0)
+       {
+       vsnprintf(telnetparams.msgbuff,sizeof(telnetparams.msgbuff)-1,message, va_args);
+       send(telnetparams.new_socket,telnetparams.msgbuff , strlen(telnetparams.msgbuff), MSG_NOSIGNAL);
+       }
+    else
+       {
+       vprintf(message, va_args);
+       }
+    va_end(va_args);
+    return ;
+}
+
+#define NICE_MAX 19
+#define NICE_MIN -20
+void set_sched(pthread_t tid, int pid, int priority)
+{
+int rt; 
+struct sched_param schedp;
+int policy;
+char strpolicy[10];
+
+
+//sched_get_priority_max(SCHED_FIFO)
+if (priority < NICE_MIN)
+   {
+   policy=SCHED_FIFO;
+   sprintf(strpolicy,"%s","fifo");
+   schedp.sched_priority= NICE_MIN - priority ;   
+   }
+else if (priority > NICE_MAX)
+   {
+   policy=SCHED_IDLE;
+   sprintf(strpolicy,"%s","idle");
+   schedp.sched_priority=0;   
+   } 
+else 
+   {
+   policy=SCHED_OTHER;
+   sprintf(strpolicy,"%s","other");
+   schedp.sched_priority=0;   
+   } 
+if( tid != 0)
+  {  
+  rt = pthread_setschedparam(tid, policy, &schedp);
+  }
+else if(pid > 0)
+  {
+  rt = sched_setscheduler( pid, policy,&schedp);
+  }
+if (rt != 0)
+    {
+    client_printf("Error %i: %s modifying sched param to %s:%i, \n",
+                  errno,strerror(errno),strpolicy,schedp.sched_priority); 
+    }
+else
+    {
+    client_printf("policy set to %s, priority %i\n",strpolicy,schedp.sched_priority);
+    }
+
+
+
+if ( policy == SCHED_OTHER)
+   {
+   if ( tid > 0 && tid != pthread_self())
+     {
+     client_printf("setting nice value using a thread id not implemented....\n");    
+     }
+   else if (pid > 0)
+     {
+     errno=0;
+     rt = setpriority(PRIO_PROCESS,pid,priority);
+     if (rt != 0)
+        {
+        client_printf("Error %i: %s calling setpriority, \n",errno,strerror(errno)); 
+        }
+     else
+        {
+        client_printf("nice value set to %i\n",priority);
+        }
+     }
+   }
+}
+
+void set_affinity(pthread_t tid, int pid, int coreid)
+{
+cpu_set_t cpuset;
+int rt;
+
+  CPU_ZERO(&cpuset);
+  CPU_SET(coreid, &cpuset);
+  if (tid > 0)
+     {
+     rt = pthread_setaffinity_np((pthread_t)tid, sizeof(cpu_set_t), &cpuset);
+     }
+  else if (pid > 0)
+     {
+     rt = sched_setaffinity((pid_t)pid, sizeof(cpu_set_t), &cpuset);
+     }
+  if (rt != 0)
+      {
+      client_printf("Error %i: %s calling , xxx_setaffinity...\n",errno,strerror(errno)); 
+      }
+  else
+      {
+      client_printf("thread %i affinity set to %i\n",(pid==0)?(int)tid:pid,coreid);
+      }  
+}
+/*------------------------------------------------------------------------------------*/
+/*
+function implementing telnet server specific commands, parameters of the
+telnet_cmdarray table
+*/
+
+void redirstd(char *newfname,telnet_printfunc_t prnt )
+{
+FILE *fd;
+   fd=freopen(newfname, "w", stdout);
+   if (fd == NULL)
+      {
+      prnt("ERROR: stdout redir to %s error %s",strerror(errno));
+      }
+   fd=freopen(newfname, "w", stderr);
+   if (fd == NULL)
+      {
+      prnt("ERROR: stderr redir to %s error %s",strerror(errno));
+      }
+}
+int setoutput(char *buff, int debug, telnet_printfunc_t prnt)
+{
+
+char cmds[TELNET_MAX_MSGLENGTH/TELNET_CMD_MAXSIZE][TELNET_CMD_MAXSIZE];
+char *logfname;
+char stdout_str[64];
+
+
+#define LOGFILE "logfile.log"
+memset(cmds,0,sizeof(cmds));
+sscanf(buff,"%9s %32s %9s %9s %9s", cmds[0],cmds[1],cmds[2],cmds[3],cmds[4]  );
+if (strncasecmp(cmds[0],"here",4) == 0)
+   {
+   fflush(stdout);
+   sprintf(stdout_str,"/proc/%i/fd/%i",getpid(),telnetparams.new_socket);
+   dup2(telnetparams.new_socket,fileno(stdout));
+//   freopen(stdout_str, "w", stdout);
+//   freopen(stdout_str, "w", stderr);
+   dup2(telnetparams.new_socket,fileno(stderr));
+   prnt("Log output redirected to this terminal (%s)\n",stdout_str);
+   }
+if (strncasecmp(cmds[0],"file",4) == 0)
+   {
+   if (cmds[1][0] == 0)
+      logfname=LOGFILE;
+   else
+      logfname=cmds[1];   
+   fflush(stdout);
+   redirstd(logfname,prnt);
+
+   }   
+if (strncasecmp(cmds[0],"off",3) == 0)
+   {
+   fflush(stdout);
+   redirstd("/dev/tty",prnt); 
+   } 
+
+return CMDSTATUS_FOUND;   
+} /* setoutput */
+
+int setparam(char *buff, int debug, telnet_printfunc_t prnt)
+{
+char cmds[TELNET_MAX_MSGLENGTH/TELNET_CMD_MAXSIZE][TELNET_CMD_MAXSIZE];
+
+
+memset(cmds,0,sizeof(cmds));
+sscanf(buff,"%9s %9s %9s %9s %9s", cmds[0],cmds[1],cmds[2],cmds[3],cmds[4]  );
+if (strncasecmp(cmds[0],"prio",4) == 0)
+   {
+   pthread_attr_t attr;
+   int prio;
+   prio=(int)strtol(cmds[1],NULL,0);
+   if (errno == ERANGE)
+       return CMDSTATUS_VARNOTFOUND;
+   telnetparams.priority = prio;
+   set_sched(pthread_self(),0,prio);
+   return CMDSTATUS_FOUND; 
+   }
+if (strncasecmp(cmds[0],"aff",3) == 0)
+   {
+   int aff;
+   aff=(int)strtol(cmds[1],NULL,0);
+   if (errno == ERANGE)
+       return CMDSTATUS_VARNOTFOUND;
+   set_affinity(pthread_self(),0,aff);
+   return CMDSTATUS_FOUND; 
+   }
+
+return CMDSTATUS_NOTFOUND;   
+} /* setparam */
+/*-------------------------------------------------------------------------------------------------------*/
+/*
+generic commands available for all modules loaded by the server
+*/
+
+int setgetvar(int moduleindex,char getorset,char *params)
+{
+int n,i;
+char varname[TELNET_CMD_MAXSIZE];
+char varval[TELNET_CMD_MAXSIZE];
+
+   memset(varname,0,sizeof(varname));
+   memset(varval,0,sizeof(varval));
+   n = sscanf(params,"%s %s",varname,varval);
+   for ( i=0 ; telnetparams.CmdParsers[moduleindex].var[i].varvalptr != NULL ; i++)
+      {
+      if ( strncasecmp(telnetparams.CmdParsers[moduleindex].var[i].varname,varname,strlen(telnetparams.CmdParsers[moduleindex].var[i].varname)) == 0)
+         {
+	 if (n > 0 && (getorset == 'g' || getorset == 'G'))
+	    {
+	    client_printf("%s, %s = ", telnetparams.CmdParsers[moduleindex].module,
+	               telnetparams.CmdParsers[moduleindex].var[i].varname );
+	    switch(telnetparams.CmdParsers[moduleindex].var[i].vartype)
+	        {
+		case TELNET_VARTYPE_INT32:
+	             client_printf("%i\n",*(int *)(telnetparams.CmdParsers[moduleindex].var[i].varvalptr));
+		break;
+		case TELNET_VARTYPE_INT16:
+	             client_printf("%hi\n",*(short *)(telnetparams.CmdParsers[moduleindex].var[i].varvalptr));
+		break;	
+		case TELNET_VARTYPE_DOUBLE:
+	             client_printf("%g\n",*(double *)(telnetparams.CmdParsers[moduleindex].var[i].varvalptr));
+		break;
+		case TELNET_VARTYPE_PTR:
+	             client_printf("0x%08x\n",*((unsigned int *)(telnetparams.CmdParsers[moduleindex].var[i].varvalptr)));						
+                break;
+		default:
+		     client_printf("unknown type\n");
+		break;
+		}
+	    }
+	 if (n > 1 && (getorset == 's' || getorset == 'S'))
+	    {
+	    client_printf("%s, %s set to \n", telnetparams.CmdParsers[moduleindex].module,
+	           telnetparams.CmdParsers[moduleindex].var[i].varname);
+		   
+	    switch(telnetparams.CmdParsers[moduleindex].var[i].vartype)
+	        {
+		case TELNET_VARTYPE_INT32:
+		     *(int *)(telnetparams.CmdParsers[moduleindex].var[i].varvalptr) = (int)strtol(varval,NULL,0);
+	             client_printf("%i\n",*(int *)(telnetparams.CmdParsers[moduleindex].var[i].varvalptr));
+		break;
+		case TELNET_VARTYPE_INT16:
+		     *(short *)(telnetparams.CmdParsers[moduleindex].var[i].varvalptr) = (short)strtol(varval,NULL,0);
+	             client_printf("%hi\n",*(short *)(telnetparams.CmdParsers[moduleindex].var[i].varvalptr));
+		break;	
+		case TELNET_VARTYPE_DOUBLE:
+		     *(double *)(telnetparams.CmdParsers[moduleindex].var[i].varvalptr) = strtod(varval,NULL);
+	             client_printf("%g\n",*(double *)(telnetparams.CmdParsers[moduleindex].var[i].varvalptr));
+		break;				
+		default:
+		     client_printf("unknown type\n");
+		break;
+		}		   
+	    }		   
+	 }
+      } 
+return CMDSTATUS_VARNOTFOUND;
+}
+/*----------------------------------------------------------------------------------------------------*/
+char *get_time(char *buff,int bufflen)
+{
+
+struct tm  tmstruct;
+time_t now = time (0);
+strftime (buff, bufflen, "%Y-%m-%d %H:%M:%S.000", localtime_r(&now,&tmstruct));
+return buff;
+}
+
+int process_command(char *buf)
+{
+int i,j,k;
+char modulename[TELNET_CMD_MAXSIZE];
+char cmd[TELNET_CMD_MAXSIZE];
+char cmdb[TELNET_MAX_MSGLENGTH];
+char *bufbck;
+int rt;
+
+memset(modulename,0,sizeof(modulename));
+memset(cmd,0,sizeof(cmd));
+memset(cmdb,0,sizeof(cmdb));
+if (strncasecmp(buf,"ex",2) == 0)
+   return CMDSTATUS_EXIT;
+
+if (strncasecmp(buf,"help",4) == 0)
+   {
+   for (i=0; telnetparams.CmdParsers[i].var != NULL && telnetparams.CmdParsers[i].cmd != NULL; i++)
+    {
+     client_printf("   module %i = %s:\n",i,telnetparams.CmdParsers[i].module);
+     for(j=0; telnetparams.CmdParsers[i].var[j].varvalptr != NULL ; j++)
+        {
+	client_printf("      %s [get set] %s <value>\n",
+	       telnetparams.CmdParsers[i].module, telnetparams.CmdParsers[i].var[j].varname);
+	} 
+     for(j=0; telnetparams.CmdParsers[i].cmd[j].cmdfunc != NULL ; j++)
+        {
+	client_printf("      %s %s %s\n",
+	       telnetparams.CmdParsers[i].module,telnetparams.CmdParsers[i].cmd[j].cmdname,
+	       telnetparams.CmdParsers[i].cmd[j].helpstr);
+	} 	
+    }
+   return CMDSTATUS_FOUND;
+   }
+
+memset(modulename,0,sizeof(modulename));
+memset(cmd,0,sizeof(cmd));
+memset(cmdb,0,sizeof(cmdb));  
+bufbck=strdup(buf); 
+rt=CMDSTATUS_NOTFOUND;   
+j = sscanf(buf,"%9s %9s %[^\t\n]",modulename,cmd,cmdb);
+if (telnetparams.telnetdbg > 0)
+    printf("process_command: %i words, module=%s cmd=%s, parameters= %s\n",j,modulename,cmd,cmdb);   
+for (i=0; j>=2 && telnetparams.CmdParsers[i].var != NULL && telnetparams.CmdParsers[i].cmd != NULL; i++)
+    {
+    if ( (strncasecmp(telnetparams.CmdParsers[i].module,modulename,strlen(telnetparams.CmdParsers[i].module)) == 0))
+       {
+        if (strncasecmp(cmd,"getall",7) == 0 )
+	    { 
+            for(j=0; telnetparams.CmdParsers[i].var[j].varvalptr != NULL ; j++)
+               {
+	       setgetvar(i,'g',telnetparams.CmdParsers[i].var[j].varname);
+	       }
+	    rt= CMDSTATUS_FOUND;              
+	    }       
+        else if (strncasecmp(cmd,"get",3) == 0 || strncasecmp(cmd,"set",3) == 0)
+	    {
+            rt= setgetvar(i,cmd[0],cmdb);	    
+	    }	    
+        else
+	    {
+	    for (k=0 ; telnetparams.CmdParsers[i].cmd[k].cmdfunc != NULL ; k++)
+	        {
+	        if (strncasecmp(cmd, telnetparams.CmdParsers[i].cmd[k].cmdname,sizeof(telnetparams.CmdParsers[i].cmd[k].cmdname)) == 0)
+                   {
+	           telnetparams.CmdParsers[i].cmd[k].cmdfunc(cmdb, telnetparams.telnetdbg, client_printf);
+                   rt= CMDSTATUS_FOUND;
+	           }
+		} /* for k */
+	    }/* else */
+	}/* strncmp: module name test */
+     else if (strncasecmp(modulename,"loop",4) == 0 )
+	{
+	int lc;
+        int f = fcntl(telnetparams.new_socket,F_GETFL);
+	fcntl (telnetparams.new_socket, F_SETFL, O_NONBLOCK | f);
+	for(lc=0; lc<telnetparams.loopcount; lc++)
+	   {
+	   char dummybuff[20];
+	   char tbuff[64];
+       int rs;
+	   client_printf(CSI "1J" CSI "1;10H         " STDFMT "%s %i/%i\n",
+	                 get_time(tbuff,sizeof(tbuff)),lc,telnetparams.loopcount );  
+       process_command(bufbck+strlen("loop")+1);
+       usleep(telnetparams.loopdelay * 1000);
+	   rs = read(telnetparams.new_socket,dummybuff,sizeof(dummybuff)); 
+	   if ( rs > 0 )
+	       {
+	       break;
+	       }
+	   }
+	fcntl (telnetparams.new_socket, F_SETFL, f);
+	rt= CMDSTATUS_FOUND;	    
+	} /* loop */
+    } /* for i */
+free(bufbck);
+return rt;
+}
+
+void run_telnetsrv(void) 
+{
+int sock;
+struct sockaddr_in name;
+char buf[TELNET_MAX_MSGLENGTH];
+struct sockaddr cli_addr;
+unsigned int cli_len = sizeof(cli_addr);
+int readc , filled;
+
+int status;
+int optval = 1;
+
+pthread_setname_np(pthread_self(), "telnet");
+set_sched(pthread_self(),0,telnetparams.priority);
+sock = socket(AF_INET, SOCK_STREAM, 0);
+if (sock < 0) 
+    fprintf(stderr,"[TELNETSRV] Error %s on socket call\n",strerror(errno));
+
+setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof optval);
+name.sin_family = AF_INET;
+if (telnetparams.listenaddr == 0)
+    name.sin_addr.s_addr = INADDR_ANY;
+else
+    name.sin_addr.s_addr = telnetparams.listenaddr;
+name.sin_port = htons((unsigned short)(telnetparams.listenport));
+
+if(bind(sock, (void*) &name, sizeof(name))) 
+     fprintf(stderr,"[TELNETSRV] Error %s on bind call\n",strerror(errno));
+if(listen(sock, 1) == -1)
+     fprintf(stderr,"[TELNETSRV] Error %s on listen call\n",strerror(errno));
+
+
+
+printf("\nInitializing telnet server...\n");
+while( (telnetparams.new_socket = accept(sock, &cli_addr, &cli_len)) )
+     {
+     printf("[TELNETSRV] Telnet client connected....\n");
+
+
+    if(telnetparams.new_socket < 0)
+       fprintf(stderr,"[TELNETSRV] Error %s on accept call\n",strerror(errno));
+
+    while(telnetparams.new_socket>0)
+         {
+	 filled = 0;
+	 memset(buf,0,sizeof(buf));
+         while(filled < ( TELNET_MAX_MSGLENGTH-1))
+	     {
+             readc = recv(telnetparams.new_socket, buf+filled, TELNET_MAX_MSGLENGTH-filled-1, 0);
+             if(!readc)
+	        break;
+             filled += readc;
+             if(buf[filled-1] == '\n')
+	        {
+		buf[filled-1] = 0;
+		
+	        break;
+		}
+             }
+         if(!readc)
+	   {
+           printf ("[TELNETSRV] Telnet Client disconnected.\n");
+           break;
+           }
+         if (telnetparams.telnetdbg > 0)
+	    printf("[TELNETSRV] Command received: readc %i filled %i %s\n", readc, filled ,buf);
+	 if (strlen(buf) >= 2 )
+	    {
+            status=process_command(buf);
+	    }
+	 else
+	    status=CMDSTATUS_NOCMD;
+	    
+         if (status != CMDSTATUS_EXIT)
+	    {
+	    if (status == CMDSTATUS_NOTFOUND)
+	       {
+	       char msg[TELNET_MAX_MSGLENGTH + 50];
+	       sprintf(msg,"Error: \n      %s\n is not a softmodem command\n",buf);
+	       send(telnetparams.new_socket, msg, strlen(msg), MSG_NOSIGNAL);
+	       }
+            send(telnetparams.new_socket, TELNET_PROMPT, sizeof(TELNET_PROMPT), MSG_NOSIGNAL);
+	    }
+	 else
+	    {
+	    printf ("[TELNETSRV] Closing telnet connection...\n");
+	    break;
+	    }
+    }
+
+    close(telnetparams.new_socket);
+    printf ("[TELNETSRV] Telnet server waitting for connection...\n");
+    }
+close(sock);
+return;
+}
+
+/*------------------------------------------------------------------------------------------------*/
+/* set_telnetmodule loads the commands delivered with the telnet server
+ *
+ *
+ * 
+*/
+void exec_moduleinit(char *modname)
+{
+void (*fptr)();
+char initfunc[TELNET_CMD_MAXSIZE+9];
+
+       if (strlen(modname) > TELNET_CMD_MAXSIZE)
+	  {
+          fprintf(stderr,"[TELNETSRV] module %s not loaded, name exceeds the %i size limit\n",
+			 modname, TELNET_CMD_MAXSIZE);
+	  return; 
+          }
+       sprintf(initfunc,"add_%s_cmds",modname);
+       fptr = dlsym(RTLD_DEFAULT,initfunc);
+       if ( fptr != NULL)
+          {
+          fptr();
+          }
+       else
+          {
+          fprintf(stderr,"[TELNETSRV] couldn't find %s for module %s \n",initfunc,modname);
+          }
+}
+
+int add_embeddedmodules()
+{
+
+
+
+
+    for(int i=0; i<telnetoptions[TELNETSRV_STATICMOD].numelt;i++)
+       {
+       exec_moduleinit(telnetoptions[TELNETSRV_STATICMOD].strlistptr[i]);
+       }
+}
+
+int add_sharedmodules()
+{
+char initfunc[TELNET_CMD_MAXSIZE+9];
+void (*fptr)();
+
+
+    for(int i=0; i<telnetoptions[TELNETSRV_SHRMOD].numelt;i++)
+       {
+       sprintf(initfunc,"add_%s_cmds",telnetoptions[TELNETSRV_SHRMOD].strlistptr[i]);
+       fptr = dlsym(RTLD_DEFAULT,initfunc);
+       if ( fptr != NULL)
+          {
+          fptr();
+          }
+       else
+          {
+          fprintf(stderr,"[TELNETSRV] couldn't find %s for module %s \n",initfunc,telnetoptions[TELNETSRV_STATICMOD].strlistptr[i]);
+          }
+       }
+}
+
+int init_telnetsrv(char *cfgfile)
+ {
+  void *lib_handle;
+  char** moduleslist; 
+
+   memset(&telnetparams,0,sizeof(telnetparams));
+
+   config_get( telnetoptions,sizeof(telnetoptions)/sizeof(paramdef_t),NULL); 
+
+ 
+   if(pthread_create(&telnetparams.telnet_pthread,NULL, (void *(*)(void *))run_telnetsrv, NULL) != 0)
+     {
+     fprintf(stderr,"[TELNETSRV] Error %s on pthread_create call\n",strerror(errno));
+     return -1;
+     }
+  add_telnetcmd("telnet", telnet_vardef, telnet_cmdarray);
+  add_embeddedmodules();
+  return 0;
+ }
+ 
+/*---------------------------------------------------------------------------------------------*/
+/* add_telnetcmd is used to add a set of commands to the telnet server. A module calls this
+ * function at init time. the telnet server is delivered with a set of commands which
+ * will be loaded or not depending on the telnet section of the config file
+*/
+int add_telnetcmd(char *modulename, telnetshell_vardef_t *var, telnetshell_cmddef_t *cmd)
+ {
+ int i;
+ if( modulename == NULL || var == NULL || cmd == NULL)
+     {
+     fprintf(stderr,"[TELNETSRV] Telnet server, add_telnetcmd: invalid parameters\n");
+     return -1;
+     }
+ for (i=0; i<TELNET_MAXCMD ; i++)
+     {
+     if (telnetparams.CmdParsers[i].var == NULL)
+        {
+        strncpy(telnetparams.CmdParsers[i].module,modulename,sizeof(telnetparams.CmdParsers[i].module)-1);
+        telnetparams.CmdParsers[i].cmd = cmd;
+        telnetparams.CmdParsers[i].var = var;
+        printf("[TELNETSRV] Telnet server: module %i = %s added to shell\n",
+               i,telnetparams.CmdParsers[i].module);
+        break;
+        }
+     }
+  return 0;
+ }
+
+
+
+
+
diff --git a/common/utils/telnetsrv/telnetsrv.h b/common/utils/telnetsrv/telnetsrv.h
new file mode 100644
index 0000000000..5663b44d67
--- /dev/null
+++ b/common/utils/telnetsrv/telnetsrv.h
@@ -0,0 +1,108 @@
+#ifndef TELNETSRV_H
+#define TELNETSRV_H
+
+#define TELNETSRV_SHAREDLIB "libtelnetsrv.so"
+
+#define TELNET_PORT               9090
+#define TELNET_MAX_MSGLENGTH      2048
+#define TELNET_PROMPT             "softmodem> "
+#define TELNET_MAXCMD             20
+#define TELNET_CMD_MAXSIZE        10
+#define TELNET_HELPSTR_SIZE       80
+
+/* status return by the command parser after it analysed user input */
+#define CMDSTATUS_NOCMD       0
+#define CMDSTATUS_EXIT        1
+#define CMDSTATUS_FOUND       2
+#define CMDSTATUS_VARNOTFOUND 3
+#define CMDSTATUS_NOTFOUND    4
+
+/*----------------------------------------------------------------------------*/
+/* structure to be used when adding a module to the telnet server */
+/* This is the second parameter of the add_telnetcmd function, which can be used   */
+/* to add a set of new command to the telnet server shell */
+typedef void(*telnet_printfunc_t)(const char* format, ...);
+typedef int(*cmdfunc_t)(char*, int, telnet_printfunc_t prnt);
+
+typedef struct cmddef {
+    char cmdname[TELNET_CMD_MAXSIZE];
+    char helpstr[TELNET_HELPSTR_SIZE];
+    cmdfunc_t cmdfunc; 
+} telnetshell_cmddef_t;
+
+/*----------------------------------------------------------------------------*/
+/*structure to be used when adding a module to the telnet server */
+/* This is the first parameter of the add_telnetcmd function, which can be used   */
+/* to add a set of new variables which can be got/set from the telnet server shell */
+#define TELNET_VARTYPE_INT32  1
+#define TELNET_VARTYPE_INT16  2
+#define TELNET_VARTYPE_INT64  3
+#define TELNET_VARTYPE_STRING 4
+#define TELNET_VARTYPE_DOUBLE 5
+#define TELNET_VARTYPE_PTR    6
+typedef struct variabledef {
+    char varname[TELNET_CMD_MAXSIZE];
+    char vartype;
+    void *varvalptr;
+} telnetshell_vardef_t;
+
+
+
+/*----------------------------------------------------------------------------*/
+/* internal structure definitions                                             */
+/* cmdparser_t is used to store all modules which have been added to the telnet server.  */
+/* Each time the add_telnetcmd function is used, the internal array cmdparser_t[] of the */
+/* telnet server is populated with the new commands and variables                   */
+typedef struct cmdparser {
+    char module[TELNET_CMD_MAXSIZE];   // module name = first token of the telnet shell command
+    telnetshell_cmddef_t   *cmd;       // array of functions added to the shell
+    telnetshell_vardef_t   *var;       // array of variables added to the shell
+} cmdparser_t;
+
+/* telnetsrv_params_t is an internal structure storing all the current parameters and */
+/* global variables used by the telnet server                                        */
+typedef struct {
+     pthread_t telnet_pthread;       // thread id of the telnet server
+     int telnetdbg;                  // debug level of the server
+     int priority;                   // server running priority
+     int new_socket;                 // socket of the client connection
+     int logfilefd;                  // file id of the log file when log output is redirected to a file
+     int  saved_stdout;              // file id of the previous stdout, used to be able to restore original stdout 
+     cmdparser_t CmdParsers[TELNET_MAXCMD];   // array of registered modules.
+     char msgbuff[TELNET_MAX_MSGLENGTH];      // internal buffer of the client_printf function which is used to print to the client terminal */
+     unsigned int   listenport;           // ip port the telnet server is listening on
+     unsigned int   listenaddr;           // ip address the telnet server is listening on
+     unsigned int   loopcount;            // loop command param: number of loop iteration
+     unsigned int   loopdelay;            // loop command param: delay in ms between 2 iterations
+     unsigned int   phyprntbuff_size;     // for phy module,  dump_eNB_stats function buffer size
+} telnetsrv_params_t;
+
+
+
+typedef int(*addcmdfunc_t)(char*, telnetshell_vardef_t*, telnetshell_cmddef_t*);
+typedef int(*initfunc_t)(char *cfgfile);
+typedef void(*settelnetmodule_t)(char *name, void *ptr); 
+
+/*-------------------------------------------------------------------------------------------*/
+/* 
+VT escape sequence definition, for smarter display....
+*/
+
+#define ESC      "\x1b"
+#define CSI      "\x1b["
+#define BOLD     "\x1b[1m"
+#define RED      "\x1b[31m"
+#define GREEN    "\x1b[32m"
+#define BLUE     "\x1b[34m"
+#define MAGENTA  "\x1b[35m"
+#define CYAN     "\x1b[36m"
+#define STDFMT   "\x1b[0m"
+
+/*---------------------------------------------------------------------------------------------*/
+#ifdef TELNETSERVERCODE
+int add_telnetcmd(char *modulename, telnetshell_vardef_t *var, telnetshell_cmddef_t *cmd);
+void set_sched(pthread_t tid, int pid,int priority);
+void set_affinity(pthread_t tid, int pid, int coreid);
+extern int get_phybsize(); 
+#endif
+#endif
diff --git a/common/utils/telnetsrv/telnetsrv_phycmd.c b/common/utils/telnetsrv/telnetsrv_phycmd.c
new file mode 100644
index 0000000000..692238f68d
--- /dev/null
+++ b/common/utils/telnetsrv/telnetsrv_phycmd.c
@@ -0,0 +1,134 @@
+#define _GNU_SOURCE 
+#include <string.h>
+#include <pthread.h>
+
+
+#define TELNETSERVERCODE
+#include "telnetsrv.h"
+#define TELNETSRV_PHYCMD_MAIN
+#include "telnetsrv_phycmd.h"
+char *prnbuff;
+extern int dump_eNB_stats(PHY_VARS_eNB *eNB, char* buffer, int length);
+
+void init_phytelnet()
+{
+   if (PHY_vars_eNB_g != NULL)
+      printf("init_phytelnet: phy var at 0x%08lx\n",(unsigned long int)PHY_vars_eNB_g);
+   else 
+      fprintf(stderr,"init_phytelnet: phy var not found...\n");
+
+
+
+phy_vardef[TELNETVAR_PHYCC0].varvalptr  = &(PHY_vars_eNB_g[0][0]);
+phy_vardef[TELNETVAR_PHYCC1].varvalptr  = &(PHY_vars_eNB_g[0][1]);
+prnbuff=malloc(get_phybsize() );
+if (prnbuff == NULL)
+   {
+   fprintf(stderr,"Error %s on malloc in init_phytelnet()\n",strerror(errno));
+   }
+}
+
+void display_uestatshead( telnet_printfunc_t prnt)
+{
+prnt("cc  ue  rnti Dmcs Umcs tao  tau   Dbr  Dtb   \n");
+}
+
+void dump_uestats(int debug, telnet_printfunc_t prnt, uint8_t prntflag)
+{
+
+int p;
+
+        p=dump_eNB_stats(PHY_vars_eNB_g[0][0], prnbuff, 0);
+	if(prntflag>=1)
+	   prnt("%s\n",prnbuff);
+	if(debug>=1)
+	   prnt("%i bytes printed\n",p);	   
+
+
+}
+
+void display_uestats(int debug, telnet_printfunc_t prnt, int ue)
+{
+   for (int cc=0; cc<1 ; cc++)
+       {
+ 
+       if ((PHY_vars_eNB_g[0][cc]->dlsch[ue][0]->rnti>0)&&
+          (PHY_vars_eNB_g[0][cc]->UE_stats[ue].mode == PUSCH))
+          {
+          prnt("%02i %04i %04hx %04i %04i %04i %-04i %04i %06i\n",cc, ue,
+               PHY_vars_eNB_g[0][cc]->UE_stats[ue].crnti,
+	       PHY_vars_eNB_g[0][cc]->dlsch[ue][0]->harq_processes[0]->mcs,0,
+//	       PHY_vars_eNB_g[0][cc]->ulsch[ue]->harq_processes[0]->mcs,
+	       PHY_vars_eNB_g[0][cc]->UE_stats[ue].UE_timing_offset,
+	       PHY_vars_eNB_g[0][cc]->UE_stats[ue].timing_advance_update,
+	       PHY_vars_eNB_g[0][cc]->UE_stats[ue].dlsch_bitrate/1000,
+	       PHY_vars_eNB_g[0][cc]->UE_stats[ue].total_TBS/1000
+              );
+	  }
+       }
+}
+
+void display_phycounters(char *buf, int debug, telnet_printfunc_t prnt)
+{    
+   prnt("  DLSCH kb      DLSCH kb/s\n");
+
+   dump_uestats(debug, prnt,0);
+   prnt("  %09i     %06i\n",
+       PHY_vars_eNB_g[0][0]->total_transmitted_bits/1000,
+       PHY_vars_eNB_g[0][0]->total_dlsch_bitrate/1000);
+}
+
+int dump_phyvars(char *buf, int debug, telnet_printfunc_t prnt)
+{
+   
+   
+
+   if (debug > 0)
+       prnt("phy interface module received %s\n",buf);
+   if (strcasestr(buf,"phycnt") != NULL)
+       {
+       display_phycounters(buf, debug, prnt);
+       }
+   if (strcasestr(buf,"uestat") != NULL)
+      {
+      char *cptr=strcasestr(buf+sizeof("uestat"),"UE");
+      display_uestatshead(prnt);
+      if (cptr != NULL)
+         {
+	 int ueidx = strtol( cptr+sizeof("UE"), NULL, 10);
+	 if (ueidx < NUMBER_OF_UE_MAX && ueidx >= 0)
+	    {
+	    display_uestats(debug, prnt,ueidx);
+	    }
+	 } /* if cptr != NULL */
+      else
+         {
+	 for (int ue=0; ue<NUMBER_OF_UE_MAX ; ue++)
+	     {
+	     display_uestats(debug, prnt,ue);
+	     }
+	 } /* else cptr != NULL */
+      } /* uestat */
+   if (strcasestr(buf,"uedump") != NULL)
+       {
+       dump_uestats(debug, prnt,1);
+       }      
+   return 0;
+}
+
+
+
+telnetshell_cmddef_t phy_cmdarray[] = {
+   {"disp","[phycnt,uedump,uestat UE<x>]", dump_phyvars},
+
+   {"","",NULL},
+};
+
+
+/*-------------------------------------------------------------------------------------*/
+void add_phy_cmds()
+{
+
+   init_phytelnet();
+   add_telnetcmd("phy", phy_vardef, phy_cmdarray);
+}
diff --git a/common/utils/telnetsrv/telnetsrv_phycmd.h b/common/utils/telnetsrv/telnetsrv_phycmd.h
new file mode 100644
index 0000000000..9fb13efb8d
--- /dev/null
+++ b/common/utils/telnetsrv/telnetsrv_phycmd.h
@@ -0,0 +1,34 @@
+
+
+#ifdef TELNETSRV_PHYCMD_MAIN
+
+#include "UTIL/LOG/log.h"
+
+#include "openair1/PHY/defs.h"
+
+
+#define TELNETVAR_PHYCC0    0
+#define TELNETVAR_PHYCC1    1
+
+telnetshell_vardef_t phy_vardef[] = {
+{"phycc1",TELNET_VARTYPE_PTR,NULL},
+{"phycc2",TELNET_VARTYPE_PTR,NULL},
+//{"iqmax",TELNET_VARTYPE_INT16,NULL},
+//{"iqmin",TELNET_VARTYPE_INT16,NULL},
+//{"loglvl",TELNET_VARTYPE_INT32,NULL},
+//{"sndslp",TELNET_VARTYPE_INT32,NULL},
+//{"rxrescale",TELNET_VARTYPE_INT32,NULL},
+//{"txshift",TELNET_VARTYPE_INT32,NULL},
+//{"rachemin",TELNET_VARTYPE_INT32,NULL},
+//{"rachdmax",TELNET_VARTYPE_INT32,NULL},
+{"",0,NULL}
+};
+extern PHY_VARS_eNB ***PHY_vars_eNB_g;
+#else
+
+extern void add_phy_cmds();
+
+#endif
+
+/*-------------------------------------------------------------------------------------*/
+
diff --git a/common/utils/telnetsrv/telnetsrv_proccmd.c b/common/utils/telnetsrv/telnetsrv_proccmd.c
new file mode 100644
index 0000000000..d8ae2bfc6e
--- /dev/null
+++ b/common/utils/telnetsrv/telnetsrv_proccmd.c
@@ -0,0 +1,226 @@
+#define _GNU_SOURCE
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <pthread.h>
+#include <string.h>
+#include <stdarg.h>
+#include <dirent.h>
+
+#define READCFG_DYNLOAD
+
+#define TELNETSERVERCODE
+#include "telnetsrv.h"
+#define TELNETSRV_PROCCMD_MAIN
+#include "log.h"
+#include "telnetsrv_proccmd.h"
+
+void decode_procstat(char *record, int debug, telnet_printfunc_t prnt)
+{
+char prntline[160];
+char *procfile_fiels;
+char *strtokptr;
+char *lptr;
+int fieldcnt;
+char toksep[2];
+
+  fieldcnt=0;	  
+  procfile_fiels =strtok_r(record," ",&strtokptr);
+  lptr= prntline;
+/*http://man7.org/linux/man-pages/man5/proc.5.html gives the structure of the stat file */
+ 
+  while( 	procfile_fiels != NULL && fieldcnt < 42)
+    {
+    if (strlen(procfile_fiels) == 0)
+       continue;
+    fieldcnt++;
+    sprintf(toksep," ");
+    switch(fieldcnt)
+       {
+       case 1: /* id */
+           lptr+=sprintf(lptr,"%9.9s ",procfile_fiels);
+           sprintf(toksep,")");
+       break;  
+       case 2: /* name */
+	   lptr+=sprintf(lptr,"%20.20s ",procfile_fiels+1);
+       break;              
+       case 3:   //thread state
+           lptr+=sprintf(lptr,"  %c   ",procfile_fiels[0]);
+       break;
+       case 14:   //time in user mode
+       case 15:   //time in kernel mode
+           lptr+=sprintf(lptr,"%9.9s ",procfile_fiels);
+       break;
+       case 18:   //priority
+       case 19:   //nice	       
+           lptr+=sprintf(lptr,"%3.3s ",procfile_fiels);
+       break;
+       case 23:   //vsize	       
+           lptr+=sprintf(lptr,"%9.9s ",procfile_fiels);
+       break;
+       case 39:   //processor	       
+           lptr+=sprintf(lptr," %2.2s  ",procfile_fiels);
+       break;
+       case 41:   //policy	       
+           lptr+=sprintf(lptr,"%3.3s ",procfile_fiels);
+       break;
+       default:
+       break;	       	       	       	       	       
+       }/* switch on fieldcnr */  
+    procfile_fiels =strtok_r(NULL,toksep,&strtokptr); 
+    } /* while on proc_fields != NULL */
+  prnt("%s\n",prntline); 
+} /*decode_procstat */
+
+void read_statfile(char *fname,int debug, telnet_printfunc_t prnt)
+{
+FILE *procfile;
+char arecord[1024];
+
+    procfile=fopen(fname,"r");
+    if (procfile == NULL)
+       {
+       prnt("Error: Couldn't open %s %i %s\n",fname,errno,strerror(errno));
+       return;
+       }    
+    if ( fgets(arecord,sizeof(arecord),procfile) == NULL)
+       {
+       prnt("Error: Nothing read from %s %i %s\n",fname,errno,strerror(errno));
+       fclose(procfile);
+       return;
+       }    
+    fclose(procfile);
+    decode_procstat(arecord, debug, prnt);
+}
+
+void print_threads(char *buf, int debug, telnet_printfunc_t prnt)
+{
+char aname[256];
+
+DIR *proc_dir;
+struct dirent *entry;
+
+int rt;
+
+    prnt("  id          name            state   USRmod    KRNmod  prio nice   vsize   proc pol \n\n");
+    snprintf(aname, sizeof(aname), "/proc/%d/stat", getpid());
+    read_statfile(aname,debug,prnt);
+    prnt("\n");
+    snprintf(aname, sizeof(aname), "/proc/%d/task", getpid());
+    proc_dir = opendir(aname);
+    if (proc_dir == NULL)
+       {
+       prnt("Error: Couldn't open %s %i %s\n",aname,errno,strerror(errno));
+       return;
+       }
+    
+    while ((entry = readdir(proc_dir)) != NULL)
+        {
+        if(entry->d_name[0] == '.')
+            continue;
+	snprintf(aname, sizeof(aname), "/proc/%d/task/%s/stat", getpid(),entry->d_name);    
+        read_statfile(aname,debug,prnt);      
+        } /* while entry != NULL */
+	closedir(proc_dir);
+} /* print_threads */
+
+
+int proccmd_show(char *buf, int debug, telnet_printfunc_t prnt)
+{
+extern log_t *g_log;   
+   
+   if (debug > 0)
+       prnt(" proccmd_show received %s\n",buf);
+   if (strcasestr(buf,"thread") != NULL)
+       {
+       print_threads(buf,debug,prnt);
+       }
+   if (strcasestr(buf,"loglvl") != NULL) {
+       for (int i=MIN_LOG_COMPONENTS; i < MAX_LOG_COMPONENTS; i++){
+            prnt("\t%s:\t%s\t%s\n",g_log->log_component[i].name, map_int_to_str(log_verbosity_names,g_log->log_component[i].flag),
+	        map_int_to_str(log_level_names,g_log->log_component[i].level));
+       }
+   }
+   return 0;
+} 
+
+int proccmd_thread(char *buf, int debug, telnet_printfunc_t prnt)
+{
+int bv1,bv2;   
+int res;
+char sv1[64]; 
+char tname[32];  
+   bv1=0;
+   bv2=0;
+   sv1[0]=0;
+   if (debug > 0)
+       prnt("proccmd_thread received %s\n",buf);
+   res=sscanf(buf,"%i %9s %i",&bv1,sv1,&bv2);
+   if (debug > 0)
+       prnt(" proccmd_thread: %i params = %i,%s,%i\n",res,bv1,sv1,bv2);   
+   if(res != 3)
+     {
+     prnt("softmodem thread needs 3 params, %i received\n",res);
+     return 0;
+     }
+
+  
+   if (strcasestr(sv1,"prio") != NULL)
+       {
+       set_sched(0,bv1, bv2);
+       }
+   else if (strcasestr(sv1,"aff") != NULL)
+       {
+       set_affinity(0,bv1, bv2);
+       }
+   else
+       {
+       prnt("%s is not a valid thread command\n",sv1);
+       }
+   return 0;
+} 
+int proccmd_exit(char *buf, int debug, telnet_printfunc_t prnt)
+{
+extern void exit_fun(const char* s);   
+   
+   if (debug > 0)
+       prnt("process module received %s\n",buf);
+
+   exit_fun("telnet server received exit command\n");
+   return 0;
+}
+ 
+int proccmd_log(char *buf, int debug, telnet_printfunc_t prnt)
+{
+int idx1=0;
+int idx2=NUM_LOG_LEVEL-1;
+int s = sscanf(buf,"%*s %i-%i",&idx1,&idx2);   
+   
+   if (debug > 0)
+       prnt("process module received %s\n",buf);
+
+   if (strcasestr(buf,"enable") != NULL)
+       {
+       set_glog_onlinelog(1);
+       }
+   if (strcasestr(buf,"disable") != NULL)
+       {
+       set_glog_onlinelog(0);
+       }
+   return 0;
+} 
+/*-------------------------------------------------------------------------------------*/
+
+void add_softmodem_cmds()
+{
+   add_telnetcmd("softmodem",NULL,proc_cmdarray);
+}
diff --git a/common/utils/telnetsrv/telnetsrv_proccmd.h b/common/utils/telnetsrv/telnetsrv_proccmd.h
new file mode 100644
index 0000000000..8a3173e3d1
--- /dev/null
+++ b/common/utils/telnetsrv/telnetsrv_proccmd.h
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.0  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file common/utils/telnetsrv_proccmd.h
+ * \brief: Include file defining telnet commands related to this linux process
+ * \author Francois TABURET
+ * \date 2017
+ * \version 0.1
+ * \company NOKIA BellLabs France
+ * \email: francois.taburet@nokia-bell-labs.com
+ * \note
+ * \warning
+ */
+#include <dlfcn.h>
+#include "telnetsrv.h"
+
+
+#ifdef TELNETSRV_PROCCMD_MAIN
+/* global variable from log.c */
+extern mapping *log_level_names;
+extern mapping *log_verbosity_names;
+
+extern int proccmd_show(char *buf, int debug, telnet_printfunc_t prnt);
+extern int proccmd_thread(char *buf, int debug, telnet_printfunc_t prnt);
+extern int proccmd_exit(char *buf, int debug, telnet_printfunc_t prnt);
+extern int proccmd_log(char *buf, int debug, telnet_printfunc_t prnt);
+
+telnetshell_cmddef_t proc_cmdarray[] = {
+   {"show","loglvl|thread", proccmd_show},
+   {"log","[enable,disable]", proccmd_log},
+   {"thread","<id> aff|prio <aff|prio>", proccmd_thread},
+   {"exit","", proccmd_exit},
+   {"","",NULL},
+};
+#else
+extern void add_proccmd_cmds();
+#endif  /* TELNETSRV_PROCCMD_MAIN */
+
diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c
index 2afb201d7b..c076c3d9b7 100644
--- a/targets/RT/USER/lte-softmodem.c
+++ b/targets/RT/USER/lte-softmodem.c
@@ -50,7 +50,7 @@
 #include "PHY/defs.h"
 #include "common/ran_context.h"
 #include "common/config/config_userapi.h"
-
+#include "common/utils/telnetsrv/load_telnet.h"
 #undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all
 //#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all
 
-- 
GitLab