Merge branch 'RU-RAU-split' of https://gitlab.eurecom.fr/oai/openairinterface5g into RU-RAU-split
Conflicts: openair1/PHY/INIT/lte_init.c openair1/PHY/LTE_TRANSPORT/dlsch_coding.c openair1/PHY/LTE_TRANSPORT/prach.c openair1/SCHED/phy_procedures_lte_eNb.c openair2/ENB_APP/enb_config.c openair2/LAYER2/MAC/defs.h openair2/LAYER2/MAC/eNB_scheduler.c openair2/LAYER2/MAC/eNB_scheduler_RA.c openair2/LAYER2/MAC/eNB_scheduler_bch.c openair2/LAYER2/MAC/eNB_scheduler_primitives.c openair2/LAYER2/MAC/eNB_scheduler_ulsch.c openair2/LAYER2/MAC/rar_tools.c openair2/RRC/LITE/MESSAGES/asn1_msg.c openair2/RRC/LITE/rrc_eNB.c
This commit is contained in:
@@ -29,10 +29,10 @@ typedef struct {
|
||||
#define T_SHM_FILENAME "/T_shm_segment"
|
||||
|
||||
/* number of VCD functions (to be kept up to date! see in T_messages.txt) */
|
||||
#define VCD_NUM_FUNCTIONS 142
|
||||
#define VCD_NUM_FUNCTIONS 172
|
||||
|
||||
/* number of VCD variables (to be kept up to date! see in T_messages.txt) */
|
||||
#define VCD_NUM_VARIABLES 107
|
||||
#define VCD_NUM_VARIABLES 118
|
||||
|
||||
/* first VCD function (to be kept up to date! see in T_messages.txt) */
|
||||
#define VCD_FIRST_FUNCTION ((uintptr_t)T_VCD_FUNCTION_RT_SLEEP)
|
||||
|
||||
@@ -16,63 +16,67 @@ ID = ENB_PHY_DL_TICK
|
||||
ID = ENB_PHY_DLSCH_UE_DCI
|
||||
DESC = eNodeB downlink UE specific DCI as sent by the PHY layer
|
||||
GROUP = ALL:PHY:GRAPHIC:ENB
|
||||
FORMAT = int,eNB_ID : int,frame : int,subframe : int,UE_id : int,rnti : int,dci_format : int,harq_pid : int,mcs : int,TBS
|
||||
FORMAT = int,eNB_ID : int,frame : int,subframe : int,rnti : int,dci_format : int,harq_pid : int,mcs : int,TBS
|
||||
ID = ENB_PHY_DLSCH_UE_ACK
|
||||
DESC = eNodeB downlink UE ACK as seen by the PHY layer in process_HARQ_feedback
|
||||
GROUP = ALL:PHY:GRAPHIC:ENB
|
||||
FORMAT = int,eNB_ID : int,frame : int,subframe : int,UE_id : int,rnti : int,harq_pid
|
||||
FORMAT = int,eNB_ID : int,frame : int,subframe : int,rnti : int,harq_pid
|
||||
ID = ENB_PHY_DLSCH_UE_NACK
|
||||
DESC = eNodeB downlink UE NACK as seen by the PHY layer in process_HARQ_feedback
|
||||
GROUP = ALL:PHY:GRAPHIC:ENB
|
||||
FORMAT = int,eNB_ID : int,frame : int,subframe : int,UE_id : int,rnti : int,harq_pid
|
||||
FORMAT = int,eNB_ID : int,frame : int,subframe : int,rnti : int,harq_pid
|
||||
ID = ENB_PHY_ULSCH_UE_DCI
|
||||
DESC = eNodeB uplink UE specific DCI as sent by the PHY layer
|
||||
GROUP = ALL:PHY:GRAPHIC:ENB
|
||||
FORMAT = int,eNB_ID : int,frame : int,subframe : int,UE_id : int,rnti : int,harq_pid : int,mcs : int,round : int,first_rb : int,nb_rb : int,TBS : int,L : int,firstCCE
|
||||
FORMAT = int,eNB_ID : int,frame : int,subframe : int,rnti : int,harq_pid : int,mcs : int,round : int,first_rb : int,nb_rb : int,TBS : int,L : int,firstCCE
|
||||
ID = ENB_PHY_ULSCH_UE_NO_DCI_RETRANSMISSION
|
||||
DESC = eNodeB uplink UE retransmission due to PHICH NACK (see generate_phich_top)
|
||||
GROUP = ALL:PHY:GRAPHIC:ENB
|
||||
FORMAT = int,eNB_ID : int,frame : int,subframe : int,UE_id : int,rnti : int,harq_pid
|
||||
FORMAT = int,eNB_ID : int,frame : int,subframe : int,rnti : int,harq_pid
|
||||
ID = ENB_PHY_ULSCH_UE_ACK
|
||||
DESC = eNodeB uplink UE ACK as seen by the PHY layer
|
||||
GROUP = ALL:PHY:GRAPHIC:ENB
|
||||
FORMAT = int,eNB_ID : int,frame : int,subframe : int,UE_id : int,rnti : int,harq_pid
|
||||
FORMAT = int,eNB_ID : int,frame : int,subframe : int,rnti : int,harq_pid
|
||||
ID = ENB_PHY_ULSCH_UE_NACK
|
||||
DESC = eNodeB uplink UE NACK as seen by the PHY layer
|
||||
GROUP = ALL:PHY:GRAPHIC:ENB
|
||||
FORMAT = int,eNB_ID : int,frame : int,subframe : int,UE_id : int,rnti : int,harq_pid
|
||||
FORMAT = int,eNB_ID : int,frame : int,subframe : int,rnti : int,harq_pid
|
||||
ID = ENB_PHY_INPUT_SIGNAL
|
||||
DESC = eNodeB received signal in the time domain for a duration of 1ms
|
||||
GROUP = ALL:PHY:GRAPHIC:HEAVY:ENB
|
||||
FORMAT = int,eNB_ID : int,frame : int,subframe : int,antenna : buffer,rxdata
|
||||
ID = ENB_PHY_OUTPUT_SIGNAL
|
||||
DESC = eNodeB sent signal in the time domain for a duration of 1ms
|
||||
GROUP = ALL:PHY:HEAVY:ENB
|
||||
FORMAT = int,eNB_ID : int,CC_id : int,frame : int,subframe : int,antenna : buffer,txdata
|
||||
ID = ENB_PHY_UL_CHANNEL_ESTIMATE
|
||||
DESC = eNodeB channel estimation in the time domain
|
||||
GROUP = ALL:PHY:GRAPHIC:HEAVY:ENB
|
||||
FORMAT = int,eNB_ID : int,UE_ID : int,frame : int,subframe : int,antenna : buffer,chest_t
|
||||
FORMAT = int,eNB_ID : int,rnti : int,frame : int,subframe : int,antenna : buffer,chest_t
|
||||
ID = ENB_PHY_PUSCH_IQ
|
||||
DESC = eNodeB PUSCH received IQ data
|
||||
GROUP = ALL:PHY:GRAPHIC:HEAVY:ENB
|
||||
FORMAT = int,eNB_ID : int,UE_ID : int,frame : int,subframe : int,nb_rb : int,N_RB_UL : int,symbols_per_tti : buffer,pusch_comp
|
||||
FORMAT = int,eNB_ID : int,rnti : int,frame : int,subframe : int,nb_rb : int,N_RB_UL : int,symbols_per_tti : buffer,pusch_comp
|
||||
ID = ENB_PHY_PUCCH_1AB_IQ
|
||||
DESC = eNodeB PUCCH received IQ data
|
||||
GROUP = ALL:PHY:GRAPHIC:HEAVY:ENB
|
||||
FORMAT = int,eNB_ID : int,UE_ID : int,frame : int,subframe : int,I : int,Q
|
||||
FORMAT = int,eNB_ID : int,rnti : int,frame : int,subframe : int,I : int,Q
|
||||
ID = ENB_PHY_PUCCH_1_ENERGY
|
||||
DESC = eNodeB PUCCH 1 energy and threshold
|
||||
GROUP = ALL:PHY:GRAPHIC:HEAVY:ENB
|
||||
FORMAT = int,eNB_ID : int,UE_ID : int,frame : int,subframe : int,energy : int,threshold
|
||||
FORMAT = int,eNB_ID : int,rnti : int,frame : int,subframe : int,energy : int,threshold
|
||||
ID = ENB_PHY_PHICH
|
||||
DESC = eNodeB PHICH
|
||||
GROUP = ALL:PHY:ENB
|
||||
FORMAT = int,eNB_ID : int,frame : int,subframe : int,UE_id : int,rnti : int,harq_pid : int,NGROUP : int,NSF : int,ngroup : int,nseq : int,ACK : int,first_rb : int,n_DMRS
|
||||
FORMAT = int,eNB_ID : int,frame : int,subframe : int,rnti : int,harq_pid : int,NGROUP : int,NSF : int,ngroup : int,nseq : int,ACK : int,first_rb : int,n_DMRS
|
||||
ID = ENB_PHY_MSG3_ALLOCATION
|
||||
DESC = eNodeB Msg3 allocation/reallocation
|
||||
GROUP = ALL:PHY:ENB
|
||||
FORMAT = int,eNB_ID : int,frame : int,subframe : int,UE_id : int,rnti : int,first_transmission : int,Msg3_frame : int,Msg3_subframe
|
||||
FORMAT = int,eNB_ID : int,frame : int,subframe : int,rnti : int,first_transmission : int,Msg3_frame : int,Msg3_subframe
|
||||
ID = ENB_PHY_INITIATE_RA_PROCEDURE
|
||||
DESC = eNodeB initiates a random access procedure after detecting enough energy for one of the preambles
|
||||
GROUP = ALL:PHY:ENB
|
||||
FORMAT = int,eNB_ID : int,frame : int,subframe : int,UE_id : int,preamble : int,energy : int,delay
|
||||
FORMAT = int,eNB_ID : int,frame : int,subframe : int,preamble : int,energy : int,delay
|
||||
|
||||
#MAC logs
|
||||
ID = ENB_MAC_UE_DL_SDU
|
||||
@@ -111,6 +115,10 @@ ID = ENB_MAC_UE_DL_PDU_WITH_DATA
|
||||
DESC = MAC downlink PDU for an UE
|
||||
GROUP = ALL:MAC:ENB
|
||||
FORMAT = int,eNB_ID : int,CC_id : int,rnti : int,frame : int,subframe : int,harq_pid : buffer,data
|
||||
ID = ENB_MAC_SCHEDULING_REQUEST
|
||||
DESC = MAC scheduling request detected for an UE
|
||||
GROUP = ALL:MAC:ENB
|
||||
FORMAT = int,eNB_ID : int,CC_id : int,frame : int,subframe : int,rnti
|
||||
|
||||
#RLC logs
|
||||
ID = ENB_RLC_DL
|
||||
@@ -826,27 +834,27 @@ ID = UE_PHY_DL_TICK
|
||||
ID = UE_PHY_DLSCH_UE_DCI
|
||||
DESC = UE downlink UE specific DCI as sent by the PHY layer
|
||||
GROUP = ALL:PHY:GRAPHIC:UE
|
||||
FORMAT = int,eNB_ID : int,frame : int,subframe : int,UE_id : int,rnti : int,dci_format : int,harq_pid : int,mcs : int,TBS
|
||||
FORMAT = int,eNB_ID : int,frame : int,subframe : int,rnti : int,dci_format : int,harq_pid : int,mcs : int,TBS
|
||||
ID = UE_PHY_DLSCH_UE_ACK
|
||||
DESC = UE downlink UE ACK as seen by the PHY layer in process_HARQ_feedback
|
||||
GROUP = ALL:PHY:GRAPHIC:UE
|
||||
FORMAT = int,eNB_ID : int,frame : int,subframe : int,UE_id : int,rnti : int,harq_pid
|
||||
FORMAT = int,eNB_ID : int,frame : int,subframe : int,rnti : int,harq_pid
|
||||
ID = UE_PHY_DLSCH_UE_NACK
|
||||
DESC = UE downlink UE NACK as seen by the PHY layer in process_HARQ_feedback
|
||||
GROUP = ALL:PHY:GRAPHIC:UE
|
||||
FORMAT = int,eNB_ID : int,frame : int,subframe : int,UE_id : int,rnti : int,harq_pid
|
||||
FORMAT = int,eNB_ID : int,frame : int,subframe : int,rnti : int,harq_pid
|
||||
ID = UE_PHY_ULSCH_UE_DCI
|
||||
DESC = UE uplink UE specific DCI as sent by the PHY layer
|
||||
GROUP = ALL:PHY:GRAPHIC:UE
|
||||
FORMAT = int,eNB_ID : int,frame : int,subframe : int,UE_id : int,rnti : int,harq_pid : int,mcs : int,round : int,first_rb : int,nb_rb : int,TBS
|
||||
FORMAT = int,eNB_ID : int,frame : int,subframe : int,rnti : int,harq_pid : int,mcs : int,round : int,first_rb : int,nb_rb : int,TBS
|
||||
ID = UE_PHY_ULSCH_UE_ACK
|
||||
DESC = UE uplink UE ACK as seen by the PHY layer
|
||||
GROUP = ALL:PHY:GRAPHIC:UE
|
||||
FORMAT = int,eNB_ID : int,frame : int,subframe : int,UE_id : int,rnti : int,harq_pid
|
||||
FORMAT = int,eNB_ID : int,frame : int,subframe : int,rnti : int,harq_pid
|
||||
ID = UE_PHY_ULSCH_UE_NACK
|
||||
DESC = UE uplink UE NACK as seen by the PHY layer
|
||||
GROUP = ALL:PHY:GRAPHIC:UE
|
||||
FORMAT = int,eNB_ID : int,frame : int,subframe : int,UE_id : int,rnti : int,harq_pid
|
||||
FORMAT = int,eNB_ID : int,frame : int,subframe : int,rnti : int,harq_pid
|
||||
ID = UE_PHY_INPUT_SIGNAL
|
||||
DESC = UE received signal in the time domain for a duration of 1ms
|
||||
GROUP = ALL:PHY:GRAPHIC:HEAVY:UE
|
||||
@@ -854,7 +862,7 @@ ID = UE_PHY_INPUT_SIGNAL
|
||||
ID = UE_PHY_DL_CHANNEL_ESTIMATE
|
||||
DESC = UE channel estimation in the time domain
|
||||
GROUP = ALL:PHY:GRAPHIC:HEAVY:UE
|
||||
FORMAT = int,eNB_ID : int,UE_ID : int,frame : int,subframe : int,antenna : buffer,chest_t
|
||||
FORMAT = int,eNB_ID : int,frame : int,subframe : int,antenna : buffer,chest_t
|
||||
ID = UE_PHY_PDCCH_IQ
|
||||
DESC = UE PDCCH received IQ data
|
||||
GROUP = ALL:PHY:GRAPHIC:HEAVY:UE
|
||||
@@ -862,27 +870,27 @@ ID = UE_PHY_PDCCH_IQ
|
||||
ID = UE_PHY_PDCCH_ENERGY
|
||||
DESC = UE PDSCH 1 energy and threshold
|
||||
GROUP = ALL:PHY:GRAPHIC:HEAVY:UE
|
||||
FORMAT = int,eNB_ID : int,UE_ID : int,frame : int,subframe : int,pdcch_ch_level00 : int,pdcch_ch_level01 : int,pdcch_ch_level10: int,pdcch_ch_level11
|
||||
FORMAT = int,eNB_ID : int,frame : int,subframe : int,pdcch_ch_level00 : int,pdcch_ch_level01 : int,pdcch_ch_level10: int,pdcch_ch_level11
|
||||
ID = UE_PHY_PDSCH_IQ
|
||||
DESC = UE PDSCH received IQ data
|
||||
GROUP = ALL:PHY:GRAPHIC:HEAVY:UE
|
||||
FORMAT = int,eNB_ID : int,UE_ID : int,frame : int,subframe : int,nb_rb : int,N_RB_UL : int,symbols_per_tti : buffer,pusch_comp
|
||||
FORMAT = int,eNB_ID : int,frame : int,subframe : int,nb_rb : int,N_RB_UL : int,symbols_per_tti : buffer,pusch_comp
|
||||
ID = UE_PHY_PDSCH_ENERGY
|
||||
DESC = UE PDSCH 1 energy and threshold
|
||||
GROUP = ALL:PHY:GRAPHIC:HEAVY:UE
|
||||
FORMAT = int,eNB_ID : int,UE_ID : int,frame : int,subframe : int,pdsch_ch_level00 : int,pdsch_ch_level01 : int,pdsch_ch_level10: int,pdsch_ch_level11
|
||||
FORMAT = int,eNB_ID : int,frame : int,subframe : int,pdsch_ch_level00 : int,pdsch_ch_level01 : int,pdsch_ch_level10: int,pdsch_ch_level11
|
||||
ID = UE_PHY_PUSCH_TX_POWER
|
||||
DESC = UE PUSCH tx power
|
||||
GROUP = ALL:PHY:GRAPHIC:HEAVY:UE
|
||||
FORMAT = int,eNB_ID : int,UE_id : int,frame : int,subframe : int,p0_pusch : int,ampl: int,g_pusch: int,pl: int,nb_rb
|
||||
FORMAT = int,eNB_ID : int,frame : int,subframe : int,p0_pusch : int,ampl: int,g_pusch: int,pl: int,nb_rb
|
||||
ID = UE_PHY_PUCCH_TX_POWER
|
||||
DESC = UE PDSCH 1 energy and threshold
|
||||
GROUP = ALL:PHY:GRAPHIC:HEAVY:UE
|
||||
FORMAT = int,eNB_ID : int,UE_id : int,frame : int,subframe : int,p0_pucch : int,ampl: int,g_pucch: int,pl
|
||||
FORMAT = int,eNB_ID : int,frame : int,subframe : int,p0_pucch : int,ampl: int,g_pucch: int,pl
|
||||
ID = UE_PHY_MEAS
|
||||
DESC = UE PHY measurements
|
||||
GROUP = ALL:PHY:GRAPHIC:HEAVY:UE
|
||||
FORMAT = int,eNB_ID : int,UE_ID : int,frame : int,subframe : int,rsrp : int,rssi : int,snr: int,rx_power: int,noise_power: int,w_cqi: int,freq_offset
|
||||
FORMAT = int,eNB_ID : int,frame : int,subframe : int,rsrp : int,rssi : int,snr: int,rx_power: int,noise_power: int,w_cqi: int,freq_offset
|
||||
|
||||
#for debug/test - not used
|
||||
ID = first
|
||||
@@ -1350,6 +1358,22 @@ ID = VCD_VARIABLE_UE0_SFN7
|
||||
DESC = VCD variable UE0_SFN7
|
||||
GROUP = ALL:VCD:ENB:VCD_VARIABLE
|
||||
FORMAT = ulong,value
|
||||
ID = VCD_VARIABLE_SEND_IF4_SYMBOL
|
||||
DESC = VCD variable SEND_IF4_SYMBOL
|
||||
GROUP = ALL:VCD:ENB:VCD_VARIABLE
|
||||
FORMAT = ulong,value
|
||||
ID = VCD_VARIABLE_RECV_IF4_SYMBOL
|
||||
DESC = VCD variable RECV_IF4_SYMBOL
|
||||
GROUP = ALL:VCD:ENB:VCD_VARIABLE
|
||||
FORMAT = ulong,value
|
||||
ID = VCD_VARIABLE_SEND_IF5_PKT_ID
|
||||
DESC = VCD variable SEND_IF5_PKT_ID
|
||||
GROUP = ALL:VCD:ENB:VCD_VARIABLE
|
||||
FORMAT = ulong,value
|
||||
ID = VCD_VARIABLE_RECV_IF5_PKT_ID
|
||||
DESC = VCD variable RECV_IF5_PKT_ID
|
||||
GROUP = ALL:VCD:ENB:VCD_VARIABLE
|
||||
FORMAT = ulong,value
|
||||
ID = VCD_VARIABLE_UE_PDCP_FLUSH_SIZE
|
||||
DESC = VCD variable UE_PDCP_FLUSH_SIZE
|
||||
GROUP = ALL:VCD:ENB:UE:VCD_VARIABLE
|
||||
@@ -2061,3 +2085,11 @@ ID = VCD_FUNCTION_RECV_IF5
|
||||
DESC = VCD function RECV_IF5
|
||||
GROUP = ALL:VCD:ENB:VCD_FUNCTION
|
||||
FORMAT = int,value
|
||||
ID = VCD_FUNCTION_TRX_COMPR_IF
|
||||
DESC = VCD function TRX_COMPR_IF
|
||||
GROUP = ALL:VCD:ENB:VCD_FUNCTION
|
||||
FORMAT = int,value
|
||||
ID = VCD_FUNCTION_TRX_DECOMPR_IF
|
||||
DESC = VCD function TRX_DECOMPR_IF
|
||||
GROUP = ALL:VCD:ENB:VCD_FUNCTION
|
||||
FORMAT = int,value
|
||||
|
||||
@@ -5,7 +5,8 @@ CFLAGS=-Wall -g -pthread -DT_TRACER -I.
|
||||
|
||||
LIBS=-lX11 -lm -lpng -lXft
|
||||
|
||||
all: record replay extract_config textlog enb ue vcd macpdu2wireshark
|
||||
all: record replay extract_config textlog enb ue vcd macpdu2wireshark \
|
||||
extract_input_subframe
|
||||
|
||||
record: utils.o record.o database.o config.o
|
||||
$(CC) $(CFLAGS) -o record $^ $(LIBS)
|
||||
@@ -16,6 +17,10 @@ replay: utils.o replay.o
|
||||
extract_config: extract_config.o
|
||||
$(CC) $(CFLAGS) -o extract_config $^ $(LIBS)
|
||||
|
||||
extract_input_subframe: extract_input_subframe.o database.o event.o utils.o \
|
||||
config.o
|
||||
$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
|
||||
|
||||
textlog: utils.o textlog.o database.o event.o handler.o config.o \
|
||||
event_selector.o view/view.a gui/gui.a logger/logger.a \
|
||||
filter/filter.a
|
||||
@@ -58,8 +63,8 @@ filter/filter.a:
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
clean:
|
||||
rm -f *.o core tracer_remote textlog enb vcd record replay
|
||||
rm -f extract_config macpdu2wireshark
|
||||
rm -f *.o core tracer_remote textlog enb ue vcd record replay
|
||||
rm -f extract_config macpdu2wireshark extract_input_subframe
|
||||
cd gui && make clean
|
||||
cd view && make clean
|
||||
cd logger && make clean
|
||||
|
||||
@@ -17,6 +17,40 @@
|
||||
#include "openair_logo.h"
|
||||
#include "config.h"
|
||||
|
||||
/****************************************************************************/
|
||||
/* conversion from rnti to "ue_id" (which does not really exists) */
|
||||
/* the idea is to assign an ue_id to an rnti as soon as we get an event */
|
||||
/* for the rnti */
|
||||
/****************************************************************************/
|
||||
|
||||
int ue_id[65536];
|
||||
int next_ue_id;
|
||||
|
||||
void reset_ue_ids(void)
|
||||
{
|
||||
int i;
|
||||
printf("resetting known UEs\n");
|
||||
for (i = 0; i < 65536; i++) ue_id[i] = -1;
|
||||
next_ue_id = 0;
|
||||
}
|
||||
|
||||
int ue_id_from_rnti(void *_priv, int rnti)
|
||||
{
|
||||
rnti = 0; /* HACK, to be removed */
|
||||
if (rnti < 0 || rnti > 65535) { printf("bad rnti %d\n", rnti); exit(1); }
|
||||
/* rnti not seen yet? give it a new ue_id */
|
||||
if (ue_id[rnti] == -1) {
|
||||
ue_id[rnti] = next_ue_id;
|
||||
next_ue_id++;
|
||||
}
|
||||
return ue_id[rnti];
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/* end of rnti->ue_id conversion */
|
||||
/****************************************************************************/
|
||||
|
||||
|
||||
typedef struct {
|
||||
view *phyview;
|
||||
view *macview;
|
||||
@@ -25,6 +59,7 @@ typedef struct {
|
||||
view *rrcview;
|
||||
view *legacy;
|
||||
widget *current_ue_label;
|
||||
widget *current_ue_button;
|
||||
widget *prev_ue_button;
|
||||
widget *next_ue_button;
|
||||
widget *pusch_iq_ue_xy_plot;
|
||||
@@ -116,11 +151,15 @@ static void *gui_thread(void *_g)
|
||||
static filter *ticktime_filter(void *database, char *event, int i, int ue)
|
||||
{
|
||||
/* filter is "harq_pid == i && UE_id == 0 && eNB_id == 0" */
|
||||
/* we get the UE_id from the rnti */
|
||||
return
|
||||
filter_and(
|
||||
filter_eq(filter_evarg(database, event, "harq_pid"), filter_int(i)),
|
||||
filter_and(
|
||||
filter_eq(filter_evarg(database, event, "UE_id"), filter_int(ue)),
|
||||
filter_eq(
|
||||
filter_evfun(database, ue_id_from_rnti, NULL,
|
||||
filter_evarg(database, event, "rnti")),
|
||||
filter_int(ue)),
|
||||
filter_eq(filter_evarg(database, event, "eNB_ID"), filter_int(0))));
|
||||
}
|
||||
|
||||
@@ -148,23 +187,28 @@ static void set_current_ue(gui *g, enb_data *e, int ue)
|
||||
|
||||
logger_set_filter(e->e->pusch_iq_ue_logger,
|
||||
filter_eq(
|
||||
filter_evarg(e->database, "ENB_PHY_PUSCH_IQ", "UE_ID"),
|
||||
filter_evfun(e->database, ue_id_from_rnti, NULL,
|
||||
filter_evarg(e->database, "ENB_PHY_PUSCH_IQ", "rnti")),
|
||||
filter_int(ue)));
|
||||
logger_set_filter(e->e->ul_estimate_ue_logger,
|
||||
filter_eq(
|
||||
filter_evarg(e->database, "ENB_PHY_UL_CHANNEL_ESTIMATE", "UE_ID"),
|
||||
filter_evfun(e->database, ue_id_from_rnti, NULL,
|
||||
filter_evarg(e->database, "ENB_PHY_UL_CHANNEL_ESTIMATE", "rnti")),
|
||||
filter_int(ue)));
|
||||
logger_set_filter(e->e->pucch1_energy_ue_threshold_logger,
|
||||
filter_eq(
|
||||
filter_evarg(e->database, "ENB_PHY_PUCCH_1_ENERGY", "UE_ID"),
|
||||
filter_evfun(e->database, ue_id_from_rnti, NULL,
|
||||
filter_evarg(e->database, "ENB_PHY_PUCCH_1_ENERGY", "rnti")),
|
||||
filter_int(ue)));
|
||||
logger_set_filter(e->e->pucch1_energy_ue_energy_logger,
|
||||
filter_eq(
|
||||
filter_evarg(e->database, "ENB_PHY_PUCCH_1_ENERGY", "UE_ID"),
|
||||
filter_evfun(e->database, ue_id_from_rnti, NULL,
|
||||
filter_evarg(e->database, "ENB_PHY_PUCCH_1_ENERGY", "rnti")),
|
||||
filter_int(ue)));
|
||||
logger_set_filter(e->e->pucch_iq_ue_logger,
|
||||
filter_eq(
|
||||
filter_evarg(e->database, "ENB_PHY_PUCCH_1AB_IQ", "UE_ID"),
|
||||
filter_evfun(e->database, ue_id_from_rnti, NULL,
|
||||
filter_evarg(e->database, "ENB_PHY_PUCCH_1AB_IQ", "rnti")),
|
||||
filter_int(ue)));
|
||||
for (i = 0; i < 8; i++) {
|
||||
logger_set_filter(e->e->dl_dci_logger[i],
|
||||
@@ -185,11 +229,13 @@ static void set_current_ue(gui *g, enb_data *e, int ue)
|
||||
}
|
||||
logger_set_filter(e->e->dl_mcs_logger,
|
||||
filter_eq(
|
||||
filter_evarg(e->database, "ENB_PHY_DLSCH_UE_DCI", "UE_id"),
|
||||
filter_evfun(e->database, ue_id_from_rnti, NULL,
|
||||
filter_evarg(e->database, "ENB_PHY_DLSCH_UE_DCI", "rnti")),
|
||||
filter_int(ue)));
|
||||
logger_set_filter(e->e->ul_mcs_logger,
|
||||
filter_eq(
|
||||
filter_evarg(e->database, "ENB_PHY_ULSCH_UE_DCI", "UE_id"),
|
||||
filter_evfun(e->database, ue_id_from_rnti, NULL,
|
||||
filter_evarg(e->database, "ENB_PHY_ULSCH_UE_DCI", "rnti")),
|
||||
filter_int(ue)));
|
||||
}
|
||||
|
||||
@@ -205,6 +251,7 @@ static void click(void *private, gui *g,
|
||||
if (button != 1) return;
|
||||
if (w == e->prev_ue_button) { ue--; if (ue < 0) ue = 0; }
|
||||
if (w == e->next_ue_button) ue++;
|
||||
if (w == e->current_ue_button) reset_ue_ids();
|
||||
|
||||
if (pthread_mutex_lock(&ed->lock)) abort();
|
||||
if (ue != ed->ue) {
|
||||
@@ -248,10 +295,12 @@ static void enb_main_gui(enb_gui *e, gui *g, event_handler *h, void *database,
|
||||
widget_add_child(g, col, logo, -1);
|
||||
w = new_container(g, HORIZONTAL);
|
||||
widget_add_child(g, col, w, -1);
|
||||
/* TODO: use button widget, not label widget */
|
||||
w2 = new_label(g, "");
|
||||
widget_add_child(g, w, w2, -1);
|
||||
label_set_clickable(g, w2, 1);
|
||||
e->current_ue_button = w2;
|
||||
e->current_ue_label = w2;
|
||||
/* TODO: use button widget, not label widget */
|
||||
w2 = new_label(g, " [prev UE] ");
|
||||
widget_add_child(g, w, w2, -1);
|
||||
label_set_clickable(g, w2, 1);
|
||||
@@ -590,6 +639,7 @@ static void enb_main_gui(enb_gui *e, gui *g, event_handler *h, void *database,
|
||||
e->legacy = new_view_textlist(10000, 10, g, text);
|
||||
|
||||
set_current_ue(g, ed, 0);
|
||||
register_notifier(g, "click", e->current_ue_button, click, ed);
|
||||
register_notifier(g, "click", e->prev_ue_button, click, ed);
|
||||
register_notifier(g, "click", e->next_ue_button, click, ed);
|
||||
}
|
||||
@@ -628,6 +678,8 @@ int main(int n, char **v)
|
||||
enb_gui eg;
|
||||
enb_data enb_data;
|
||||
|
||||
reset_ue_ids();
|
||||
|
||||
/* write on a socket fails if the other end is closed and we get SIGPIPE */
|
||||
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) abort();
|
||||
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include "database.h"
|
||||
#include "event.h"
|
||||
#include "config.h"
|
||||
|
||||
void usage(void)
|
||||
{
|
||||
printf(
|
||||
"usage: [options] <file> <frame> <subframe>\n"
|
||||
"options:\n"
|
||||
" -d <database file> this option is mandatory\n"
|
||||
" -v verbose\n"
|
||||
);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int main(int n, char **v)
|
||||
{
|
||||
char *database_filename = NULL;
|
||||
void *database;
|
||||
int i;
|
||||
int input_event_id;
|
||||
database_event_format f;
|
||||
char *file = NULL;
|
||||
int fd;
|
||||
int frame = -1, subframe = -1;
|
||||
int frame_arg, subframe_arg, buffer_arg;
|
||||
int verbose = 0;
|
||||
|
||||
for (i = 1; i < n; i++) {
|
||||
if (!strcmp(v[i], "-h") || !strcmp(v[i], "--help")) usage();
|
||||
if (!strcmp(v[i], "-d"))
|
||||
{ if (i > n-2) usage(); database_filename = v[++i]; continue; }
|
||||
if (!strcmp(v[i], "-v")) { verbose = 1; continue; }
|
||||
if (file == NULL) { file = v[i]; continue; }
|
||||
if (frame == -1) { frame = atoi(v[i]); continue; }
|
||||
if (subframe == -1) { subframe = atoi(v[i]); continue; }
|
||||
usage();
|
||||
}
|
||||
if (file == NULL || frame == -1 || subframe == -1) usage();
|
||||
|
||||
if (database_filename == NULL) {
|
||||
printf("ERROR: provide a database file (-d)\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
database = parse_database(database_filename);
|
||||
|
||||
load_config_file(database_filename);
|
||||
|
||||
input_event_id = event_id_from_name(database, "ENB_PHY_INPUT_SIGNAL");
|
||||
f = get_format(database, input_event_id);
|
||||
|
||||
frame_arg = subframe_arg = buffer_arg = -1;
|
||||
for (i = 0; i < f.count; i++) {
|
||||
if (!strcmp(f.name[i], "frame")) {
|
||||
if (frame_arg != -1) goto err;
|
||||
if (strcmp(f.type[i], "int")) goto err;
|
||||
frame_arg = i;
|
||||
}
|
||||
if (!strcmp(f.name[i], "subframe")) {
|
||||
if (subframe_arg != -1) goto err;
|
||||
if (strcmp(f.type[i], "int")) goto err;
|
||||
subframe_arg = i;
|
||||
}
|
||||
if (!strcmp(f.name[i], "rxdata")) {
|
||||
if (buffer_arg != -1) goto err;
|
||||
if (strcmp(f.type[i], "buffer")) goto err;
|
||||
buffer_arg = i;
|
||||
}
|
||||
continue;
|
||||
err:
|
||||
printf("cannot deal with ENB_PHY_INPUT_SIGNAL from database file\n");
|
||||
exit(1);
|
||||
}
|
||||
if (frame_arg == -1 || subframe_arg == -1 || buffer_arg == -1) goto err;
|
||||
|
||||
fd = open(file, O_RDONLY);
|
||||
if (fd == -1) { perror(file); exit(1); }
|
||||
|
||||
/* get wanted frame/subframe */
|
||||
while (1) {
|
||||
char v[T_BUFFER_MAX];
|
||||
event e;
|
||||
e = get_event(fd, v, database);
|
||||
if (e.type == -1) break;
|
||||
if (e.type != input_event_id) continue;
|
||||
if (verbose)
|
||||
printf("input frame %d subframe %d size %d\n",
|
||||
e.e[frame_arg].i, e.e[subframe_arg].i, e.e[buffer_arg].bsize);
|
||||
if (!(frame == e.e[frame_arg].i && subframe == e.e[subframe_arg].i))
|
||||
continue;
|
||||
#if 0
|
||||
for (i = 0; i < e.e[buffer_arg].bsize/2; i++) {
|
||||
short *x = e.e[buffer_arg].b;
|
||||
x[i] *= 14;
|
||||
}
|
||||
#endif
|
||||
fwrite(e.e[buffer_arg].b, e.e[buffer_arg].bsize, 1, stdout);
|
||||
fflush(stdout);
|
||||
return 0;
|
||||
}
|
||||
|
||||
printf("frame %d subframe %d not found\n", frame, subframe);
|
||||
return 0;
|
||||
}
|
||||
@@ -10,6 +10,8 @@ struct filter {
|
||||
struct { struct filter *a, *b; } op2;
|
||||
int v;
|
||||
struct { int event_type; int arg_index; } evarg;
|
||||
struct { int (*fun)(void *priv, int v); void *priv;
|
||||
struct filter *x; } evfun;
|
||||
} v;
|
||||
|
||||
int (*eval)(struct filter *this, event e);
|
||||
@@ -52,6 +54,11 @@ int eval_evarg(struct filter *f, event e)
|
||||
return e.e[f->v.evarg.arg_index].i;
|
||||
}
|
||||
|
||||
int eval_evfun(struct filter *f, event e)
|
||||
{
|
||||
return f->v.evfun.fun(f->v.evfun.priv, f->v.evfun.x->eval(f->v.evfun.x, e));
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/* free memory functions */
|
||||
/****************************************************************************/
|
||||
@@ -63,6 +70,12 @@ void free_op2(struct filter *f)
|
||||
free(f);
|
||||
}
|
||||
|
||||
void free_evfun(struct filter *f)
|
||||
{
|
||||
free_filter(f->v.evfun.x);
|
||||
free(f);
|
||||
}
|
||||
|
||||
void free_noop(struct filter *f)
|
||||
{
|
||||
free(f);
|
||||
@@ -135,6 +148,19 @@ filter *filter_evarg(void *database, char *event_name, char *varname)
|
||||
return ret;
|
||||
}
|
||||
|
||||
filter *filter_evfun(void *database, int (*fun)(void *priv, int v),
|
||||
void *priv, filter *x)
|
||||
{
|
||||
struct filter *ret = calloc(1, sizeof(struct filter));
|
||||
if (ret == NULL) abort();
|
||||
ret->eval = eval_evfun;
|
||||
ret->free = free_evfun;
|
||||
ret->v.evfun.fun = fun;
|
||||
ret->v.evfun.priv = priv;
|
||||
ret->v.evfun.x = x;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void free_filter(filter *_f)
|
||||
{
|
||||
struct filter *f;
|
||||
|
||||
@@ -9,6 +9,8 @@ filter *filter_and(filter *a, filter *b);
|
||||
filter *filter_eq(filter *a, filter *b);
|
||||
filter *filter_int(int v);
|
||||
filter *filter_evarg(void *database, char *event_name, char *varname);
|
||||
filter *filter_evfun(void *database, int (*fun)(void *priv, int v),
|
||||
void *priv, filter *x);
|
||||
|
||||
int filter_eval(filter *f, event e);
|
||||
|
||||
|
||||
@@ -623,7 +623,7 @@ static inline void itti_receive_msg_internal_event_fd(task_id_t task_id, uint8_t
|
||||
read_ret = read (itti_desc.threads[thread_id].task_event_fd, &sem_counter, sizeof(sem_counter));
|
||||
AssertFatal (read_ret == sizeof(sem_counter), "Read from task message FD (%d) failed (%d/%d)!\n", thread_id, (int) read_ret, (int) sizeof(sem_counter));
|
||||
|
||||
|
||||
printf("sem_counter %d task %d\n", (int)sem_counter, task_id);
|
||||
if (lfds611_queue_dequeue (itti_desc.tasks[task_id].message_queue, (void **) &message) == 0) {
|
||||
/* No element in list -> this should not happen */
|
||||
AssertFatal (0, "No message in queue for task %d while there are %d events and some for the messages queue!\n", task_id, epoll_ret);
|
||||
@@ -631,9 +631,13 @@ static inline void itti_receive_msg_internal_event_fd(task_id_t task_id, uint8_t
|
||||
|
||||
AssertFatal(message != NULL, "Message from message queue is NULL!\n");
|
||||
*received_msg = message->msg;
|
||||
|
||||
printf("ITTI: message %s\n", ITTI_MSG_NAME(message->msg));
|
||||
|
||||
result = itti_free (ITTI_MSG_ORIGIN_ID(*received_msg), message);
|
||||
AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
|
||||
|
||||
|
||||
/* Mark that the event has been processed */
|
||||
itti_desc.threads[thread_id].events[i].events &= ~EPOLLIN;
|
||||
return;
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
|
||||
/* FT NOKBLF:
|
||||
* this source is to be linked with the program using the telnet server, it looks for
|
||||
* the telnet server dynamic library, possibly loads it and calls the telnet server
|
||||
* init functions
|
||||
*/
|
||||
#define _GNU_SOURCE
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <dlfcn.h>
|
||||
#include "openair1/PHY/defs.h"
|
||||
#define LOAD_MODULE_SHLIB_MAIN
|
||||
#include "load_module_shlib.h"
|
||||
int load_module_shlib(char *modname)
|
||||
{
|
||||
void *lib_handle;
|
||||
initfunc_t fpi;
|
||||
char *tmpstr;
|
||||
int ret=0;
|
||||
|
||||
tmpstr = malloc(strlen(modname)+16);
|
||||
if (tmpstr == NULL) {
|
||||
fprintf(stderr,"[LOADER] %s %d malloc error loading module %s, %s\n",__FILE__, __LINE__, modname, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
sprintf(tmpstr,"lib%s.so",modname);
|
||||
lib_handle = dlopen(tmpstr, RTLD_LAZY|RTLD_NODELETE|RTLD_GLOBAL);
|
||||
if (!lib_handle) {
|
||||
printf("[LOADER] library %s is not loaded: %s\n", tmpstr,dlerror());
|
||||
ret = -1;
|
||||
} else {
|
||||
sprintf(tmpstr,"init_%s",modname);
|
||||
fpi = dlsym(lib_handle,tmpstr);
|
||||
|
||||
if (fpi != NULL )
|
||||
{
|
||||
fpi();
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,"[LOADER] %s %d %s function not found %s\n",__FILE__, __LINE__, dlerror(),tmpstr);
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (tmpstr != NULL) free(tmpstr);
|
||||
if (lib_handle != NULL) dlclose(lib_handle);
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
#ifndef LOAD_SHLIB_H
|
||||
#define LOAD_SHLIB_H
|
||||
|
||||
|
||||
typedef int(*initfunc_t)(void);
|
||||
#ifdef LOAD_MODULE_SHLIB_MAIN
|
||||
#else
|
||||
extern int load_module_shlib(char *modname);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,59 @@
|
||||
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
|
||||
IF(DEFINED ENV{OPENAIR_DIR})
|
||||
message("...using oai source files in $ENV{OPENAIR_DIR}")
|
||||
ELSE()
|
||||
message("OPENAIR_DIR is not defined. You must run \"source oaienv\" from the oai root dir")
|
||||
# exit early
|
||||
return()
|
||||
ENDIF()
|
||||
|
||||
|
||||
|
||||
set(OPENAIR_DIR $ENV{OPENAIR_DIR})
|
||||
set(APPROOT ${OPENAIR_DIR}/common/utils/telnetsrv )
|
||||
set(OPENAIR_BUILD_DIR $ENV{OPENAIR_DIR}/cmake_targets)
|
||||
set(OPENAIR1_DIR $ENV{OPENAIR1_DIR})
|
||||
set(OPENAIR2_DIR $ENV{OPENAIR2_DIR})
|
||||
set(OPENAIR3_DIR $ENV{OPENAIR3_DIR})
|
||||
set(OPENAIR_PHY_DIR $ENV{OPENAIR1_DIR}/PHY)
|
||||
set(OPENAIR_TARGET_DIR $ENV{OPENAIR_DIR}/targets)
|
||||
set(OPENAIR_COMMONUTILS_DIR $ENV{OPENAIR_DIR}/common/utils)
|
||||
set(OPENAIR2_COMMON_DIR $ENV{OPENAIR_DIR}/openair2/COMMON)
|
||||
set(OPENAIR_ASN1INC ${OPENAIR_BUILD_DIR}/lte_build_oai/build/CMakeFiles/Rel14)
|
||||
set(OPENAIR_NFAPIINC $ENV{NFAPI_DIR} )
|
||||
|
||||
set(CMAKE_INSTALL_PREFIX $ENV{OPENAIR_TARGETS})
|
||||
|
||||
add_definitions (-DRel14 -DCMAKER -DENABLE_FXP -DENABLE_ITTI -DENABLE_NAS_UE_LOGGING -DENABLE_SECURITY -DENABLE_USE_CPU_EXECUTION_TIME -DENABLE_USE_MME -DENABLE_VCD -DENB_AGENT -DENB_MODE -DETHERNET=1 -DEXMIMO_IOT -DJUMBO_FRAME -DLINK_ENB_PDCP_TO_GTPV1U -DLOG_NO_THREAD -DMAC_CONTEXT -DMAX_NUM_CCs=1 -DNAS_BUILT_IN_UE -DNAS_UE -DNB_ANTENNAS_RX=2 -DNB_ANTENNAS_TX=2 -DNB_ANTENNAS_TXRX=2 -DNEW_FFT -DNO_RRM -DNone=1 -DOAI_NW_DRIVER_USE_NETLINK -DOPENAIR1 -DOPENAIR2 -DOPENAIR_LTE -DPC_DSP -DPC_TARGET -DPHYSIM -DPHY_CONTEXT -DPUCCH -DRel10=1 -DS1AP_VERSION=R10 -DTRACE_RLC_MUTEX -DUSER_MODE -DX2AP_VERSION=R11 -DXFORMS -mavx2 -msse4.1 -mssse3)
|
||||
add_compile_options( -fPIC -march=native -Ofast)
|
||||
|
||||
include_directories( ./ ${OPENAIR_COMMON_DIR} ${OPENAIR_DIR} ${OPENAIR1_DIR} ${OPENAIR2_DIR} ${OPENAIR2_COMMON_DIR} ${OPENAIR2_DIR}/UTIL/LOG
|
||||
${OPENAIR_COMMONUTILS_DIR}/msc ${OPENAIR_COMMONUTILS_DIR}/itti ${OPENAIR_COMMONUTILS_DIR}/hashtable ${OPENAIR_COMMONUTILS_DIR} ${OPENAIR_ASN1INC}
|
||||
${OPENAIR2_DIR}/LAYER2/RLC/AM_v9.3.0 ${OPENAIR_COMMONUTILS_DIR}/msc ${OPENAIR_COMMONUTILS_DIR}/itti ${OPENAIR_COMMONUTILS_DIR}/hashtable ${OPENAIR_COMMONUTILS_DIR} ${OPENAIR_ASN1INC}
|
||||
${OPENAIR2_DIR}/LAYER2/RLC ${OPENAIR2_DIR}/UTIL/LISTS ${OPENAIR2_DIR}/UTIL/MEM ${OPENAIR2_DIR}/LAYER2/RLC/UM_v9.3.0
|
||||
${OPENAIR2_DIR}/LAYER2/RLC/TM_v9.3.0 ${OPENAIR2_DIR}/RRC/LITE ${OPENAIR_TARGET_DIR}/COMMON ${OPENAIR_TARGET_DIR}/ARCH/COMMON
|
||||
${OPENAIR3_DIR}/NAS/COMMON/API/NETWORK ${OPENAIR3_DIR}/NAS/COMMON/EMM/MSG/ ${OPENAIR3_DIR}/NAS/COMMON/IES/ ${OPENAIR3_DIR}/NAS/COMMON/UTIL
|
||||
${OPENAIR3_DIR}/NAS/COMMON/ESM/MSG/ ${OPENAIR3_DIR}/GTPV1-U ${OPENAIR3_DIR}/GTPV1-U/nw-gtpv1u/shared ${OPENAIR3_DIR}/GTPV1-U/nw-gtpv1u/include
|
||||
${OPENAIR3_DIR}/UTILS ${OPENAIR_NFAPIINC})
|
||||
|
||||
set(TELNETSRV_SOURCE
|
||||
${APPROOT}/telnetsrv.c
|
||||
${APPROOT}/telnetsrv_phycmd.c
|
||||
${APPROOT}/telnetsrv_proccmd.c
|
||||
)
|
||||
|
||||
#set(TELNETSRV_ETHDEVCMD_SOURCE
|
||||
# ${APPROOT}/telnetsrv/telnetsrv_ethdevcmd.c
|
||||
# )
|
||||
|
||||
|
||||
|
||||
add_library(telnetsrv MODULE ${TELNETSRV_SOURCE} )
|
||||
#add_library(telnetsrv_ethdevcmd MODULE ${TELNETSRV_ETHDEVCMD_SOURCE} )
|
||||
|
||||
|
||||
install(TARGETS telnetsrv DESTINATION bin)
|
||||
|
||||
if (EXISTS "${OPENAIR_BUILD_DIR}/lte_build_oai/build" AND IS_DIRECTORY "${OPENAIR_BUILD_DIR}/lte_build_oai/build")
|
||||
install(TARGETS telnetsrv DESTINATION ${OPENAIR_BUILD_DIR}/lte_build_oai/build)
|
||||
endif (EXISTS "${OPENAIR_BUILD_DIR}/lte_build_oai/build" AND IS_DIRECTORY "${OPENAIR_BUILD_DIR}/lte_build_oai/build")
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
#ifndef TELNETSRV_H
|
||||
#define TELNETSRV_H
|
||||
|
||||
#define TELNETSRV_MODNAME "telnetsrv"
|
||||
|
||||
#define TELNET_PORT 9090
|
||||
#define TELNET_MAX_MSGLENGTH 2048
|
||||
#define TELNET_PROMPT "softmodem> "
|
||||
#define TELNET_MAXCMD 20
|
||||
#define TELNET_CMD_MAXSIZE 10
|
||||
#define TELNET_HELPSTR_SIZE 80
|
||||
|
||||
/* status return by the command parser after it analysed user input */
|
||||
#define CMDSTATUS_NOCMD 0
|
||||
#define CMDSTATUS_EXIT 1
|
||||
#define CMDSTATUS_FOUND 2
|
||||
#define CMDSTATUS_VARNOTFOUND 3
|
||||
#define CMDSTATUS_NOTFOUND 4
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* structure to be used when adding a module to the telnet server */
|
||||
/* This is the second parameter of the add_telnetcmd function, which can be used */
|
||||
/* to add a set of new command to the telnet server shell */
|
||||
typedef void(*telnet_printfunc_t)(const char* format, ...);
|
||||
typedef int(*cmdfunc_t)(char*, int, telnet_printfunc_t prnt);
|
||||
|
||||
typedef struct cmddef {
|
||||
char cmdname[TELNET_CMD_MAXSIZE];
|
||||
char helpstr[TELNET_HELPSTR_SIZE];
|
||||
cmdfunc_t cmdfunc;
|
||||
} telnetshell_cmddef_t;
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/*structure to be used when adding a module to the telnet server */
|
||||
/* This is the first parameter of the add_telnetcmd function, which can be used */
|
||||
/* to add a set of new variables which can be got/set from the telnet server shell */
|
||||
#define TELNET_VARTYPE_INT32 1
|
||||
#define TELNET_VARTYPE_INT16 2
|
||||
#define TELNET_VARTYPE_INT64 3
|
||||
#define TELNET_VARTYPE_STRING 4
|
||||
#define TELNET_VARTYPE_DOUBLE 5
|
||||
#define TELNET_VARTYPE_PTR 6
|
||||
typedef struct variabledef {
|
||||
char varname[TELNET_CMD_MAXSIZE];
|
||||
char vartype;
|
||||
void *varvalptr;
|
||||
} telnetshell_vardef_t;
|
||||
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* internal structure definitions */
|
||||
/* cmdparser_t is used to store all modules which have been added to the telnet server. */
|
||||
/* Each time the add_telnetcmd function is used, the internal array cmdparser_t[] of the */
|
||||
/* telnet server is populated with the new commands and variables */
|
||||
typedef struct cmdparser {
|
||||
char module[TELNET_CMD_MAXSIZE]; // module name = first token of the telnet shell command
|
||||
telnetshell_cmddef_t *cmd; // array of functions added to the shell
|
||||
telnetshell_vardef_t *var; // array of variables added to the shell
|
||||
} cmdparser_t;
|
||||
|
||||
/* telnetsrv_params_t is an internal structure storing all the current parameters and */
|
||||
/* global variables used by the telnet server */
|
||||
typedef struct {
|
||||
pthread_t telnet_pthread; // thread id of the telnet server
|
||||
int telnetdbg; // debug level of the server
|
||||
int priority; // server running priority
|
||||
int new_socket; // socket of the client connection
|
||||
int logfilefd; // file id of the log file when log output is redirected to a file
|
||||
int saved_stdout; // file id of the previous stdout, used to be able to restore original stdout
|
||||
cmdparser_t CmdParsers[TELNET_MAXCMD]; // array of registered modules.
|
||||
char msgbuff[TELNET_MAX_MSGLENGTH]; // internal buffer of the client_printf function which is used to print to the client terminal */
|
||||
unsigned int listenport; // ip port the telnet server is listening on
|
||||
unsigned int listenaddr; // ip address the telnet server is listening on
|
||||
unsigned int loopcount; // loop command param: number of loop iteration
|
||||
unsigned int loopdelay; // loop command param: delay in ms between 2 iterations
|
||||
unsigned int phyprntbuff_size; // for phy module, dump_eNB_stats function buffer size
|
||||
} telnetsrv_params_t;
|
||||
|
||||
|
||||
|
||||
typedef int(*addcmdfunc_t)(char*, telnetshell_vardef_t*, telnetshell_cmddef_t*);
|
||||
|
||||
typedef void(*settelnetmodule_t)(char *name, void *ptr);
|
||||
|
||||
/*-------------------------------------------------------------------------------------------*/
|
||||
/*
|
||||
VT escape sequence definition, for smarter display....
|
||||
*/
|
||||
|
||||
#define ESC "\x1b"
|
||||
#define CSI "\x1b["
|
||||
#define BOLD "\x1b[1m"
|
||||
#define RED "\x1b[31m"
|
||||
#define GREEN "\x1b[32m"
|
||||
#define BLUE "\x1b[34m"
|
||||
#define MAGENTA "\x1b[35m"
|
||||
#define CYAN "\x1b[36m"
|
||||
#define STDFMT "\x1b[0m"
|
||||
|
||||
/*---------------------------------------------------------------------------------------------*/
|
||||
#ifdef TELNETSERVERCODE
|
||||
int add_telnetcmd(char *modulename, telnetshell_vardef_t *var, telnetshell_cmddef_t *cmd);
|
||||
void set_sched(pthread_t tid, int pid,int priority);
|
||||
void set_affinity(pthread_t tid, int pid, int coreid);
|
||||
extern int get_phybsize();
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,111 @@
|
||||
#define _GNU_SOURCE
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
|
||||
|
||||
#define TELNETSERVERCODE
|
||||
#include "telnetsrv.h"
|
||||
#define TELNETSRV_PHYCMD_MAIN
|
||||
#include "telnetsrv_phycmd.h"
|
||||
char *prnbuff;
|
||||
extern int dump_eNB_stats(PHY_VARS_eNB *eNB, char* buffer, int length);
|
||||
|
||||
void init_phytelnet()
|
||||
{
|
||||
prnbuff=malloc(get_phybsize() );
|
||||
if (prnbuff == NULL)
|
||||
{
|
||||
fprintf(stderr,"Error %s on malloc in init_phytelnet()\n",strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
void display_uestatshead( telnet_printfunc_t prnt)
|
||||
{
|
||||
prnt("cc ue rnti Dmcs Umcs tao tau Dbr Dtb \n");
|
||||
}
|
||||
|
||||
void dump_uestats(int debug, telnet_printfunc_t prnt, uint8_t prntflag)
|
||||
{
|
||||
|
||||
int p;
|
||||
|
||||
p=dump_eNB_l2_stats( prnbuff, 0);
|
||||
if(prntflag>=1)
|
||||
prnt("%s\n",prnbuff);
|
||||
if(debug>=1)
|
||||
prnt("%i bytes printed\n",p);
|
||||
|
||||
|
||||
}
|
||||
|
||||
void display_uestats(int debug, telnet_printfunc_t prnt, int ue)
|
||||
{
|
||||
for (int cc=0; cc<1 ; cc++)
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void display_phycounters(char *buf, int debug, telnet_printfunc_t prnt)
|
||||
{
|
||||
prnt(" DLSCH kb DLSCH kb/s\n");
|
||||
|
||||
dump_uestats(debug, prnt,0);
|
||||
|
||||
}
|
||||
|
||||
int dump_phyvars(char *buf, int debug, telnet_printfunc_t prnt)
|
||||
{
|
||||
|
||||
|
||||
|
||||
if (debug > 0)
|
||||
prnt("phy interface module received %s\n",buf);
|
||||
if (strcasestr(buf,"phycnt") != NULL)
|
||||
{
|
||||
display_phycounters(buf, debug, prnt);
|
||||
}
|
||||
if (strcasestr(buf,"uestat") != NULL)
|
||||
{
|
||||
char *cptr=strcasestr(buf+sizeof("uestat"),"UE");
|
||||
display_uestatshead(prnt);
|
||||
if (cptr != NULL)
|
||||
{
|
||||
int ueidx = strtol( cptr+sizeof("UE"), NULL, 10);
|
||||
if (ueidx < NUMBER_OF_UE_MAX && ueidx >= 0)
|
||||
{
|
||||
display_uestats(debug, prnt,ueidx);
|
||||
}
|
||||
} /* if cptr != NULL */
|
||||
else
|
||||
{
|
||||
for (int ue=0; ue<NUMBER_OF_UE_MAX ; ue++)
|
||||
{
|
||||
display_uestats(debug, prnt,ue);
|
||||
}
|
||||
} /* else cptr != NULL */
|
||||
} /* uestat */
|
||||
if (strcasestr(buf,"uedump") != NULL)
|
||||
{
|
||||
dump_uestats(debug, prnt,1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
telnetshell_cmddef_t phy_cmdarray[] = {
|
||||
{"disp","[phycnt,uedump,uestat UE<x>]", dump_phyvars},
|
||||
|
||||
{"","",NULL},
|
||||
};
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------------------*/
|
||||
void add_phy_cmds()
|
||||
{
|
||||
|
||||
init_phytelnet();
|
||||
add_telnetcmd("phy", phy_vardef, phy_cmdarray);
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
|
||||
|
||||
#ifdef TELNETSRV_PHYCMD_MAIN
|
||||
|
||||
#include "UTIL/LOG/log.h"
|
||||
|
||||
|
||||
#include "openair1/PHY/extern.h"
|
||||
|
||||
|
||||
#define TELNETVAR_PHYCC0 0
|
||||
#define TELNETVAR_PHYCC1 1
|
||||
|
||||
telnetshell_vardef_t phy_vardef[] = {
|
||||
{"phycc1",TELNET_VARTYPE_PTR,NULL},
|
||||
{"phycc2",TELNET_VARTYPE_PTR,NULL},
|
||||
//{"iqmax",TELNET_VARTYPE_INT16,NULL},
|
||||
//{"iqmin",TELNET_VARTYPE_INT16,NULL},
|
||||
//{"loglvl",TELNET_VARTYPE_INT32,NULL},
|
||||
//{"sndslp",TELNET_VARTYPE_INT32,NULL},
|
||||
//{"rxrescale",TELNET_VARTYPE_INT32,NULL},
|
||||
//{"txshift",TELNET_VARTYPE_INT32,NULL},
|
||||
//{"rachemin",TELNET_VARTYPE_INT32,NULL},
|
||||
//{"rachdmax",TELNET_VARTYPE_INT32,NULL},
|
||||
{"",0,NULL}
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
extern void add_phy_cmds();
|
||||
|
||||
#endif
|
||||
|
||||
/*-------------------------------------------------------------------------------------*/
|
||||
|
||||
@@ -0,0 +1,230 @@
|
||||
#define _GNU_SOURCE
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <pthread.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#define READCFG_DYNLOAD
|
||||
|
||||
#define TELNETSERVERCODE
|
||||
#include "telnetsrv.h"
|
||||
#define TELNETSRV_PROCCMD_MAIN
|
||||
#include "log.h"
|
||||
#include "telnetsrv_proccmd.h"
|
||||
|
||||
void decode_procstat(char *record, int debug, telnet_printfunc_t prnt)
|
||||
{
|
||||
char prntline[160];
|
||||
char *procfile_fiels;
|
||||
char *strtokptr;
|
||||
char *lptr;
|
||||
int fieldcnt;
|
||||
char toksep[2];
|
||||
|
||||
fieldcnt=0;
|
||||
procfile_fiels =strtok_r(record," ",&strtokptr);
|
||||
lptr= prntline;
|
||||
/*http://man7.org/linux/man-pages/man5/proc.5.html gives the structure of the stat file */
|
||||
|
||||
while( procfile_fiels != NULL && fieldcnt < 42)
|
||||
{
|
||||
if (strlen(procfile_fiels) == 0)
|
||||
continue;
|
||||
fieldcnt++;
|
||||
sprintf(toksep," ");
|
||||
switch(fieldcnt)
|
||||
{
|
||||
case 1: /* id */
|
||||
lptr+=sprintf(lptr,"%9.9s ",procfile_fiels);
|
||||
sprintf(toksep,")");
|
||||
break;
|
||||
case 2: /* name */
|
||||
lptr+=sprintf(lptr,"%20.20s ",procfile_fiels+1);
|
||||
break;
|
||||
case 3: //thread state
|
||||
lptr+=sprintf(lptr," %c ",procfile_fiels[0]);
|
||||
break;
|
||||
case 14: //time in user mode
|
||||
case 15: //time in kernel mode
|
||||
lptr+=sprintf(lptr,"%9.9s ",procfile_fiels);
|
||||
break;
|
||||
case 18: //priority
|
||||
case 19: //nice
|
||||
lptr+=sprintf(lptr,"%3.3s ",procfile_fiels);
|
||||
break;
|
||||
case 23: //vsize
|
||||
lptr+=sprintf(lptr,"%9.9s ",procfile_fiels);
|
||||
break;
|
||||
case 39: //processor
|
||||
lptr+=sprintf(lptr," %2.2s ",procfile_fiels);
|
||||
break;
|
||||
case 41: //policy
|
||||
lptr+=sprintf(lptr,"%3.3s ",procfile_fiels);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}/* switch on fieldcnr */
|
||||
procfile_fiels =strtok_r(NULL,toksep,&strtokptr);
|
||||
} /* while on proc_fields != NULL */
|
||||
prnt("%s\n",prntline);
|
||||
} /*decode_procstat */
|
||||
|
||||
void read_statfile(char *fname,int debug, telnet_printfunc_t prnt)
|
||||
{
|
||||
FILE *procfile;
|
||||
char arecord[1024];
|
||||
|
||||
procfile=fopen(fname,"r");
|
||||
if (procfile == NULL)
|
||||
{
|
||||
prnt("Error: Couldn't open %s %i %s\n",fname,errno,strerror(errno));
|
||||
return;
|
||||
}
|
||||
if ( fgets(arecord,sizeof(arecord),procfile) == NULL)
|
||||
{
|
||||
prnt("Error: Nothing read from %s %i %s\n",fname,errno,strerror(errno));
|
||||
fclose(procfile);
|
||||
return;
|
||||
}
|
||||
fclose(procfile);
|
||||
decode_procstat(arecord, debug, prnt);
|
||||
}
|
||||
|
||||
void print_threads(char *buf, int debug, telnet_printfunc_t prnt)
|
||||
{
|
||||
char aname[256];
|
||||
|
||||
DIR *proc_dir;
|
||||
struct dirent *entry;
|
||||
|
||||
int rt;
|
||||
|
||||
prnt(" id name state USRmod KRNmod prio nice vsize proc pol \n\n");
|
||||
snprintf(aname, sizeof(aname), "/proc/%d/stat", getpid());
|
||||
read_statfile(aname,debug,prnt);
|
||||
prnt("\n");
|
||||
snprintf(aname, sizeof(aname), "/proc/%d/task", getpid());
|
||||
proc_dir = opendir(aname);
|
||||
if (proc_dir == NULL)
|
||||
{
|
||||
prnt("Error: Couldn't open %s %i %s\n",aname,errno,strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
while ((entry = readdir(proc_dir)) != NULL)
|
||||
{
|
||||
if(entry->d_name[0] == '.')
|
||||
continue;
|
||||
snprintf(aname, sizeof(aname), "/proc/%d/task/%s/stat", getpid(),entry->d_name);
|
||||
read_statfile(aname,debug,prnt);
|
||||
} /* while entry != NULL */
|
||||
closedir(proc_dir);
|
||||
} /* print_threads */
|
||||
|
||||
|
||||
int proccmd_show(char *buf, int debug, telnet_printfunc_t prnt)
|
||||
{
|
||||
extern log_t *g_log;
|
||||
|
||||
if (debug > 0)
|
||||
prnt(" proccmd_show received %s\n",buf);
|
||||
if (strcasestr(buf,"thread") != NULL)
|
||||
{
|
||||
print_threads(buf,debug,prnt);
|
||||
}
|
||||
if (strcasestr(buf,"loglvl") != NULL) {
|
||||
for (int i=MIN_LOG_COMPONENTS; i < MAX_LOG_COMPONENTS; i++){
|
||||
prnt("\t%s:\t%s\t%s\n",g_log->log_component[i].name, map_int_to_str(log_verbosity_names,g_log->log_component[i].flag),
|
||||
map_int_to_str(log_level_names,g_log->log_component[i].level));
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int proccmd_thread(char *buf, int debug, telnet_printfunc_t prnt)
|
||||
{
|
||||
int bv1,bv2;
|
||||
int res;
|
||||
char sv1[64];
|
||||
char tname[32];
|
||||
bv1=0;
|
||||
bv2=0;
|
||||
sv1[0]=0;
|
||||
if (debug > 0)
|
||||
prnt("proccmd_thread received %s\n",buf);
|
||||
res=sscanf(buf,"%i %9s %i",&bv1,sv1,&bv2);
|
||||
if (debug > 0)
|
||||
prnt(" proccmd_thread: %i params = %i,%s,%i\n",res,bv1,sv1,bv2);
|
||||
if(res != 3)
|
||||
{
|
||||
prnt("softmodem thread needs 3 params, %i received\n",res);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
if (strcasestr(sv1,"prio") != NULL)
|
||||
{
|
||||
set_sched(0,bv1, bv2);
|
||||
}
|
||||
else if (strcasestr(sv1,"aff") != NULL)
|
||||
{
|
||||
set_affinity(0,bv1, bv2);
|
||||
}
|
||||
else
|
||||
{
|
||||
prnt("%s is not a valid thread command\n",sv1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int proccmd_exit(char *buf, int debug, telnet_printfunc_t prnt)
|
||||
{
|
||||
extern void exit_fun(const char* s);
|
||||
|
||||
if (debug > 0)
|
||||
prnt("process module received %s\n",buf);
|
||||
|
||||
exit_fun("telnet server received exit command\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int proccmd_log(char *buf, int debug, telnet_printfunc_t prnt)
|
||||
{
|
||||
int idx1=0;
|
||||
int idx2=NUM_LOG_LEVEL-1;
|
||||
int s = sscanf(buf,"%*s %i-%i",&idx1,&idx2);
|
||||
|
||||
if (debug > 0)
|
||||
prnt("process module received %s\n",buf);
|
||||
|
||||
if (strcasestr(buf,"enable") != NULL)
|
||||
{
|
||||
set_glog_onlinelog(1);
|
||||
}
|
||||
if (strcasestr(buf,"disable") != NULL)
|
||||
{
|
||||
set_glog_onlinelog(0);
|
||||
}
|
||||
if (strcasestr(buf,"show") != NULL)
|
||||
{
|
||||
proccmd_show("loglvl",debug,prnt);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*-------------------------------------------------------------------------------------*/
|
||||
|
||||
void add_softmodem_cmds()
|
||||
{
|
||||
add_telnetcmd("softmodem",proc_vardef,proc_cmdarray);
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.0 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/*! \file common/utils/telnetsrv_proccmd.h
|
||||
* \brief: Include file defining telnet commands related to this linux process
|
||||
* \author Francois TABURET
|
||||
* \date 2017
|
||||
* \version 0.1
|
||||
* \company NOKIA BellLabs France
|
||||
* \email: francois.taburet@nokia-bell-labs.com
|
||||
* \note
|
||||
* \warning
|
||||
*/
|
||||
#include <dlfcn.h>
|
||||
#include "telnetsrv.h"
|
||||
|
||||
|
||||
#ifdef TELNETSRV_PROCCMD_MAIN
|
||||
/* global variable from log.c */
|
||||
extern mapping *log_level_names;
|
||||
extern mapping *log_verbosity_names;
|
||||
|
||||
extern int proccmd_show(char *buf, int debug, telnet_printfunc_t prnt);
|
||||
extern int proccmd_thread(char *buf, int debug, telnet_printfunc_t prnt);
|
||||
extern int proccmd_exit(char *buf, int debug, telnet_printfunc_t prnt);
|
||||
extern int proccmd_log(char *buf, int debug, telnet_printfunc_t prnt);
|
||||
telnetshell_vardef_t proc_vardef[] = {
|
||||
{"",0,NULL}
|
||||
};
|
||||
|
||||
telnetshell_cmddef_t proc_cmdarray[] = {
|
||||
{"show","loglvl|thread", proccmd_show},
|
||||
{"log","[enable,disable]", proccmd_log},
|
||||
{"thread","<id> aff|prio <aff|prio>", proccmd_thread},
|
||||
{"exit","", proccmd_exit},
|
||||
{"","",NULL},
|
||||
};
|
||||
#else
|
||||
extern void add_proccmd_cmds();
|
||||
#endif /* TELNETSRV_PROCCMD_MAIN */
|
||||
|
||||
Reference in New Issue
Block a user