Commit e470e2d3 authored by Florian Kaltenberger's avatar Florian Kaltenberger

Merge remote-tracking branch 'origin/develop' into feature-21-TM7-tmp

Conflicts:
	targets/RT/USER/lte-enb.c
parents 41582eb3 bf5bf8ba
This diff is collapsed.
......@@ -268,6 +268,15 @@ Obj.# Case# Test# Description
02 55 22 Band 7 FDD 10MHz DL Throughput (TCP) for 300 sec for 2TX/2RX (TM2)
02 55 23 Band 7 FDD 20MHz DL Throughput (TCP) for 300 sec for 2TX/2RX (TM2)
02 57 lte-softmodem tests with USRP B210 RF as eNB and OAI EPC (eNB and EPC are on different machines) w/ OAI UE
02 57 00 Band 7 FDD 5MHz UL Throughput for 300 sec for 1TX/1RX
02 57 01 Band 7 FDD 10MHz UL Throughput for 300 sec for 1TX/1RX
02 57 02 Band 7 FDD 20MHz UL Throughput for 300 sec for 1TX/1RX
02 57 03 Band 7 FDD 5MHz DL Throughput for 300 sec for 1TX/1RX
02 57 04 Band 7 FDD 10MHz DL Throughput for 300 sec for 1TX/1RX
02 57 05 Band 7 FDD 20MHz DL Throughput for 300 sec for 1TX/1RX
01 64 lte-softmodem-noS1 tests
02 Functional test case
......
......@@ -552,7 +552,7 @@ def wait_testcaseclass_generic_threads(threadListGeneric, timeout = 1):
# \param CleanupAluLteBox string that contains commands to stop ALU Bell Labs LTEBox (specified in test_case_list.xml)
# \param ExmimoRfStop command to stop EXMIMO Card
# \param nruns_lte-softmodem global parameter to override number of runs (nruns) within the test case
def handle_testcaseclass_softmodem (testcase, oldprogramList, logdirOAI5GRepo , logdirOpenaircnRepo, MachineList, user, password, CleanUpAluLteBox, ExmimoRfStop, nruns_lte_softmodem, timeout_cmd):
def handle_testcaseclass_softmodem (testcase, oldprogramList, logdirOAI5GRepo , logdirOpenaircnRepo, MachineList, user, password, CleanUpAluLteBox, ExmimoRfStop, nruns_lte_softmodem, GitOAI5GRepoBranch, GitOpenaircnRepoBranch,timeout_cmd):
#We ignore the password sent to this function for secuirity reasons for password present in log files
#It is recommended to add a line in /etc/sudoers that looks something like below. The line below will run sudo without password prompt
# your_user_name ALL=(ALL:ALL) NOPASSWD: ALL
......@@ -583,7 +583,7 @@ def handle_testcaseclass_softmodem (testcase, oldprogramList, logdirOAI5GRepo ,
RRH_main_exec = testcase.findtext('RRH_main_exec',default='')
RRH_main_exec_args = testcase.findtext('RRH_main_exec_args',default='')
RRH_terminate_missing_procs = testcase.findtext('RRH_terminate_missing_procs',default='False')
RRH_branch = testcase.findtext('RRH_branch',default=GitOAI5GRepoBranch)
eNBMachine = testcase.findtext('eNB',default='')
eNB_config_file = testcase.findtext('eNB_config_file',default='')
......@@ -599,6 +599,7 @@ def handle_testcaseclass_softmodem (testcase, oldprogramList, logdirOAI5GRepo ,
eNB_search_expr_true = testcase.findtext('eNB_search_expr_true','')
if re.compile('\w+').match(eNB_search_expr_true) != None:
eNB_search_expr_true = eNB_search_expr_true + ' duration=' + str(timeout_cmd-90) + 's'
eNB_branch = testcase.findtext('eNB_branch',default=GitOAI5GRepoBranch)
UEMachine = testcase.findtext('UE',default='')
UE_config_file = testcase.findtext('UE_config_file',default='')
......@@ -615,6 +616,7 @@ def handle_testcaseclass_softmodem (testcase, oldprogramList, logdirOAI5GRepo ,
UE_stop_script = testcase.findtext('UE_stop_script','')
if re.compile('\w+').match(UE_search_expr_true) != None:
UE_search_expr_true = UE_search_expr_true + ' duration=' + str(timeout_cmd-90) + 's'
UE_branch = testcase.findtext('UE_branch',default=GitOAI5GRepoBranch)
EPCMachine = testcase.findtext('EPC',default='')
EPC_config_file = testcase.findtext('EPC_config_file',default='')
......@@ -633,6 +635,8 @@ def handle_testcaseclass_softmodem (testcase, oldprogramList, logdirOAI5GRepo ,
EPC_traffic_exec_args = testcase.findtext('EPC_traffic_exec_args',default='')
EPC_terminate_missing_procs = testcase.findtext('EPC_terminate_missing_procs',default='False')
EPC_search_expr_true = testcase.findtext('EPC_search_expr_true','')
EPC_branch = testcase.findtext('EPC_branch',default=GitOpenaircnRepoBranch)
if re.compile('\w+').match(EPC_search_expr_true) != None:
EPC_search_expr_true = EPC_search_expr_true + ' duration=' + str(timeout_cmd-90) + 's'
......@@ -689,7 +693,7 @@ def handle_testcaseclass_softmodem (testcase, oldprogramList, logdirOAI5GRepo ,
logdir_local_testcase = logdir_local + '/cmake_targets/autotests/log/'+ testcasename + '/run_' + str(run)
#Make the log directory of test case
if RRHMachine != '':
cmd = 'rm -fr ' + logdir_RRH + ' ; mkdir -p ' + logdir_RRH
cmd = 'rm -fr ' + logdir_RRH + ' ; mkdir -p ' + logdir_RRH
result = oai_RRH.send_recv(cmd)
cmd = 'rm -fr ' + logdir_eNB + ' ; mkdir -p ' + logdir_eNB
result = oai_eNB.send_recv(cmd)
......@@ -709,7 +713,8 @@ def handle_testcaseclass_softmodem (testcase, oldprogramList, logdirOAI5GRepo ,
logfile_task_RRH_out = logdir_RRH + '/RRH_task_out' + '_' + str(run) + '_.log'
logfile_task_RRH = logdir_local_testcase + '/RRH_task' + '_' + str(run) + '_.log'
task_RRH_compile = ' ( uname -a ; date \n'
task_RRH_compile = task_RRH_compile + 'cd ' + logdirOAI5GRepo + ' ; source oaienv ; source cmake_targets/tools/build_helper \n'
task_RRH_compile = task_RRH_compile + 'cd ' + logdirOAI5GRepo + '; git reset --hard HEAD ; git checkout ' + RRH_branch + ' ; source oaienv \n'
task_RRH_compile = task_RRH_compile + ' source cmake_targets/tools/build_helper \n'
task_RRH_compile = task_RRH_compile + 'env |grep OPENAIR \n'
task_RRH_compile = task_RRH_compile + update_config_file(oai_RRH, RRH_config_file, logdirOAI5GRepo, '$OPENAIR_DIR/cmake_targets/autotests/tools/search_repl.py') + '\n'
if RRH_compile_prog != "":
......@@ -749,7 +754,8 @@ def handle_testcaseclass_softmodem (testcase, oldprogramList, logdirOAI5GRepo ,
logfile_pcap_tmp_eNB = '/tmp/' + '/eNB_tshark' + '_' + str(run) + '_.pcap'
task_eNB_compile = ' ( uname -a ; date \n'
task_eNB_compile = task_eNB_compile + 'cd ' + logdirOAI5GRepo + ' ; source oaienv ; source cmake_targets/tools/build_helper \n'
task_eNB_compile = task_eNB_compile + 'cd ' + logdirOAI5GRepo + '; git reset --hard HEAD ; git checkout ' + eNB_branch + ' ; source oaienv \n'
task_eNB_compile = task_eNB_compile + ' source cmake_targets/tools/build_helper \n'
task_eNB_compile = task_eNB_compile + 'env |grep OPENAIR \n'
task_eNB_compile = task_eNB_compile + update_config_file(oai_eNB, eNB_config_file, logdirOAI5GRepo, '$OPENAIR_DIR/cmake_targets/autotests/tools/search_repl.py') + '\n'
if eNB_compile_prog != "":
......@@ -799,8 +805,7 @@ def handle_testcaseclass_softmodem (testcase, oldprogramList, logdirOAI5GRepo ,
task_UE_compile = ' ( uname -a ; date \n'
task_UE_compile = task_UE_compile + 'array_exec_pid=()' + '\n'
task_UE_compile = task_UE_compile + 'cd ' + logdirOAI5GRepo + '\n'
task_UE_compile = task_UE_compile + 'source oaienv \n'
task_UE_compile = task_UE_compile + 'cd ' + logdirOAI5GRepo + '; git reset --hard HEAD ; git checkout ' + UE_branch + ' ; source oaienv \n'
task_UE_compile = task_UE_compile + 'source cmake_targets/tools/build_helper \n'
task_UE_compile = task_UE_compile + 'env |grep OPENAIR \n'
task_UE_compile = task_UE_compile + update_config_file(oai_UE, UE_config_file, logdirOAI5GRepo, '$OPENAIR_DIR/cmake_targets/autotests/tools/search_repl.py') + '\n'
......@@ -850,7 +855,7 @@ def handle_testcaseclass_softmodem (testcase, oldprogramList, logdirOAI5GRepo ,
task_EPC_compile = ' ( uname -a ; date \n'
task_EPC_compile = task_EPC_compile + 'array_exec_pid=()' + '\n'
task_EPC_compile = task_EPC_compile + 'cd ' + logdirOpenaircnRepo + ' ; source oaienv \n'
task_EPC_compile = task_EPC_compile + 'cd ' + logdirOpenaircnRepo + '; git reset --hard HEAD ; git checkout ' + EPC_branch + ' ; source oaienv \n'
task_EPC_compile = task_EPC_compile + update_config_file(oai_EPC, EPC_config_file, logdirOpenaircnRepo, logdirOpenaircnRepo+'/TEST/autotests/tools/search_repl.py') + '\n'
task_EPC_compile = task_EPC_compile + 'source BUILD/TOOLS/build_helper \n'
if EPC_compile_prog != "":
......@@ -2203,7 +2208,7 @@ for testcase in testcaseList:
print "eNBMachine : " + eNBMachine + "UEMachine : " + UEMachine + "EPCMachine : " + EPCMachine + "MachineList : " + ','.join(MachineList)
print "testcasename = " + testcasename + " class = " + testcaseclass
#cleanOldProgramsAllMachines(oai_list, CleanUpOldProgs, CleanUpAluLteBox, ExmimoRfStop)
handle_testcaseclass_softmodem (testcase, CleanUpOldProgs, logdirOAI5GRepo, logdirOpenaircnRepo, MachineList, user, pw, CleanUpAluLteBox, ExmimoRfStop, nruns_lte_softmodem, Timeout_cmd )
handle_testcaseclass_softmodem (testcase, CleanUpOldProgs, logdirOAI5GRepo, logdirOpenaircnRepo, MachineList, user, pw, CleanUpAluLteBox, ExmimoRfStop, nruns_lte_softmodem, GitOAI5GRepoBranch, GitOpenaircnRepoBranch, Timeout_cmd )
#The lines below are copied from below to trace the failure of some of the machines in test setup. These lines below need to be removed in long term
print "Creating xml file for overall results..."
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -35,6 +35,7 @@ source $THIS_SCRIPT_PATH/tools/build_helper
MSC_GEN="False"
XFORMS="True"
FLEXRAN_AGENT_SB_IF="True"
PRINT_STATS="False"
VCD_TIMING="False"
DEADLINE_SCHEDULER_FLAG_USER="False"
......@@ -83,6 +84,8 @@ Options
Makes the UE specific parts (ue_ip, usim, nvram)
--RRH
Makes the RRH
-a | --agent
Enables agent for software-defined control of the eNB
-r | --3gpp-release
default is Rel10,
Rel8 limits the implementation to 3GPP Release 8 version
......@@ -169,6 +172,10 @@ function main() {
eNB=1
echo_info "Will compile eNB"
shift;;
-a | --agent)
FLEXRAN_AGENT=1
echo_info "Will compile eNB with agent support"
shift;;
--UE)
UE=1
echo_info "Will compile UE"
......@@ -439,6 +446,9 @@ function main() {
echo "set ( CMAKE_BUILD_TYPE $CMAKE_BUILD_TYPE )" >> $cmake_file
echo "set ( CFLAGS_PROCESSOR_USER \"$CFLAGS_PROCESSOR_USER\" )" >> $cmake_file
echo "set ( XFORMS $XFORMS )" >> $cmake_file
if [ "$FLEXRAN_AGENT" = "1" ] ; then
echo "set ( FLEXRAN_AGENT_SB_IF $FLEXRAN_AGENT_SB_IF )" >> $cmake_file
fi
echo "set ( RRC_ASN1_VERSION \"${REL}\")" >> $cmake_file
echo "set ( ENABLE_VCD_FIFO $VCD_TIMING )" >> $cmake_file
echo "set ( RF_BOARD \"${HW}\")" >> $cmake_file
......@@ -581,6 +591,9 @@ function main() {
echo "set ( CMAKE_BUILD_TYPE $CMAKE_BUILD_TYPE )" >> $cmake_file
echo "set ( CFLAGS_PROCESSOR_USER \"$CFLAGS_PROCESSOR_USER\" )" >> $cmake_file
echo "set ( XFORMS $XFORMS )" >> $cmake_file
if [ "$FLEXRAN_AGENT" = "1" ] ; then
echo "set ( FLEXRAN_AGENT_SB_IF $FLEXRAN_AGENT_SB_IF )" >> $cmake_file
fi
echo "set ( PRINT_STATS $PRINT_STATS )" >> $cmake_file
echo "set ( RRC_ASN1_VERSION \"${REL}\")" >> $cmake_file
echo "set ( ENABLE_VCD_FIFO $VCD_TIMING )" >> $cmake_file
......@@ -649,6 +662,9 @@ function main() {
cp $DIR/oaisim_mme_build_oai/CMakeLists.template $cmake_file
echo "set ( CMAKE_BUILD_TYPE $CMAKE_BUILD_TYPE )" >> $cmake_file
echo "set ( XFORMS $XFORMS )" >> $cmake_file
if [ "$FLEXRAN_AGENT" = "1" ] ; then
echo "set ( FLEXRAN_AGENT_SB_IF $FLEXRAN_AGENT_SB_IF )" >> $cmake_file
fi
echo "set ( RRC_ASN1_VERSION \"${REL}\")" >> $cmake_file
echo "set ( ENABLE_VCD_FIFO $VCD_TIMING )" >> $cmake_file
echo "set ( T_TRACER $T_TRACER )" >> $cmake_file
......
......@@ -47,7 +47,7 @@ set ( NEW_FFT True )
set ( NO_RRM True )
set ( OAI_EMU True )
set ( OAISIM True )
set ( OAI_NW_DRIVER_TYPE_ETHERNET True )
set ( OAI_NW_DRIVER_TYPE_ETHERNET False )
set ( OAI_NW_DRIVER_USE_NETLINK True )
set ( OPENAIR1 True )
set ( OPENAIR2 True )
......
......@@ -163,6 +163,42 @@ compilations() {
# External packages installers
############################################
install_protobuf_from_source(){
protobuf_install_log=$OPENAIR_DIR/cmake_targets/log/protobuf_install_log.txt
echo_info "\nInstalling Google Protobuf from sources. The log file for Protobuf installation is here: $protobuf_install_log "
(
cd /tmp
echo "Downloading protobuf"
rm -rf /tmp/protobuf-2.6.1.tar.gz* /tmp/protobuf-2.6.1
wget https://github.com/google/protobuf/releases/download/v2.6.1/protobuf-2.6.1.tar.gz
tar -xzvf protobuf-2.6.1.tar.gz
cd protobuf-2.6.1/
./configure
echo "Compiling protobuf"
make -j`nproc`
$SUDO make install
$SUDO ldconfig
) >& $protobuf_install_log
}
install_protobuf_c_from_source(){
protobuf_c_install_log=$OPENAIR_DIR/cmake_targets/log/protobuf_c_install_log.txt
echo_info "\nInstalling Google Protobuf_C from sources. The log file for Protobuf_C installation is here: $protobuf_c_install_log "
(
cd /tmp
echo "Downloading protobuf-c"
rm -rf /tmp/protobuf-c
git clone https://github.com/protobuf-c/protobuf-c.git
cd protobuf-c
./autogen.sh
./configure
echo "Compiling protobuf-c"
make -j`nproc`
$SUDO make install
$SUDO ldconfig
) >& $protobuf_c_install_log
}
check_install_usrp_uhd_driver(){
#first we remove old installation
$SUDO apt-get remove -y uhd || true
......@@ -324,6 +360,7 @@ check_install_oai_software() {
xmlstarlet \
python-pip \
pydb \
libyaml-dev \
wget
$SUDO update-alternatives --set liblapack.so /usr/lib/atlas-base/atlas/liblapack.so
......@@ -337,6 +374,10 @@ check_install_oai_software() {
$SUDO apt-get install -y libgnutls-dev
install_asn1c_from_source
$SUDO rm -fr /opt/ssh
$SUDO git clone https://gist.github.com/2190472.git /opt/ssh
install_protobuf_from_source
install_protobuf_c_from_source
}
### Remove Nettle installation which was done from sources
......@@ -361,6 +402,7 @@ remove_nettle_from_source() {
cd nettle-2.5/
./configure --disable-openssl --enable-shared --prefix=/usr
$SUDO make uninstall || true
$SUDO ldconfig
) >& $nettle_uninstall_log
}
......@@ -384,6 +426,7 @@ remove_gnutls_from_source(){
cd gnutls-3.1.23/
./configure --prefix=/usr
$SUDO make uninstall || true
$SUDO ldconfig
)>& $gnutls_uninstall_log
}
......@@ -398,6 +441,7 @@ install_asn1c_from_source(){
make -j`nproc`
$SUDO make install
cd -
$SUDO ldconfig
) > $asn1_install_log 2>&1
}
......
#!/bin/bash
function main()
{
mkdir -p $1
#echo generate protobuf messages inside $1 $2
c_out=$1
shift
proto_path=$1
shift
protoc-c --c_out=$c_out --proto_path=$proto_path $*
#protoc --cpp_out=$c_out --proto_path=$proto_path $*
}
main "$@"
#!/usr/bin/env bash
CACHE_DIR=/mnt/oai_agent_cache
if [ ! -d $CACHE_DIR ]; then
echo "Creating cache dir in $CACHE_DIR"
sudo mkdir $CACHE_DIR
fi
if grep -qs "$CACHE_DIR" /proc/mounts; then
echo "Agent cache is already mounted"
else
echo "Agent cache was not mounted"
echo "Mounting..."
sudo mount -o size=100m -t tmpfs none "$CACHE_DIR"
if [ $? -eq 0 ]; then
echo "Mount success"
else
echo "Something went wrong with the mount"
fi
fi
......@@ -16,7 +16,7 @@ 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
FORMAT = int,eNB_ID : int,frame : int,subframe : int,UE_id : 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
......@@ -28,7 +28,7 @@ ID = ENB_PHY_DLSCH_UE_NACK
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
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
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
......
......@@ -32,6 +32,8 @@ typedef struct {
widget *pucch1_energy_ue_xy_plot;
widget *pucch_iq_ue_xy_plot;
widget *dl_ul_harq_ue_label;
widget *dl_mcs_xy_plot;
widget *ul_mcs_xy_plot;
logger *pusch_iq_ue_logger;
logger *ul_estimate_ue_logger;
logger *pucch1_energy_ue_threshold_logger;
......@@ -44,6 +46,8 @@ typedef struct {
logger *ul_dci_retransmission_logger[8];
logger *ul_ack_logger[8];
logger *ul_nack_logger[8];
logger *dl_mcs_logger;
logger *ul_mcs_logger;
} enb_gui;
typedef struct {
......@@ -137,6 +141,10 @@ static void set_current_ue(gui *g, enb_data *e, int ue)
xy_plot_set_title(g, e->e->pucch_iq_ue_xy_plot, s);
sprintf(s, "DL/UL HARQ (x8) [UE %d]", ue);
label_set_text(g, e->e->dl_ul_harq_ue_label, s);
sprintf(s, "DL MCS [UE %d]", ue);
xy_plot_set_title(g, e->e->dl_mcs_xy_plot, s);
sprintf(s, "UL MCS [UE %d]", ue);
xy_plot_set_title(g, e->e->ul_mcs_xy_plot, s);
logger_set_filter(e->e->pusch_iq_ue_logger,
filter_eq(
......@@ -175,6 +183,14 @@ static void set_current_ue(gui *g, enb_data *e, int ue)
logger_set_filter(e->e->ul_nack_logger[i],
ticktime_filter(e->database, "ENB_PHY_ULSCH_UE_NACK", i, ue));
}
logger_set_filter(e->e->dl_mcs_logger,
filter_eq(
filter_evarg(e->database, "ENB_PHY_DLSCH_UE_DCI", "UE_id"),
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_int(ue)));
}
static void click(void *private, gui *g,
......@@ -190,8 +206,12 @@ static void click(void *private, gui *g,
if (w == e->prev_ue_button) { ue--; if (ue < 0) ue = 0; }
if (w == e->next_ue_button) ue++;
if (ue != ed->ue) set_current_ue(g, ed, ue);
ed->ue = ue;
if (pthread_mutex_lock(&ed->lock)) abort();
if (ue != ed->ue) {
set_current_ue(g, ed, ue);
ed->ue = ue;
}
if (pthread_mutex_unlock(&ed->lock)) abort();
}
static void enb_main_gui(enb_gui *e, gui *g, event_handler *h, void *database,
......@@ -305,6 +325,30 @@ static void enb_main_gui(enb_gui *e, gui *g, event_handler *h, void *database,
logger_add_view(l, v);
e->pucch_iq_ue_logger = l;
/* UE x DL mcs */
line = new_container(g, HORIZONTAL);
widget_add_child(g, top_container, line, -1);
w = new_xy_plot(g, 128, 55, "", 20);
xy_plot_set_range(g, w, 0, 1024*10, -2, 30);
e->dl_mcs_xy_plot = w;
widget_add_child(g, line, w, -1);
l = new_ticked_ttilog(h, database, "ENB_PHY_DL_TICK", "frame", "subframe",
"ENB_PHY_DLSCH_UE_DCI", "mcs", 0, -1);
v = new_view_tti(10, g, w, new_color(g, "#0c0c72"));
logger_add_view(l, v);
e->dl_mcs_logger = l;
/* UE x UL mcs */
w = new_xy_plot(g, 128, 55, "", 20);
xy_plot_set_range(g, w, 0, 1024*10, -2, 30);
e->ul_mcs_xy_plot = w;
widget_add_child(g, line, w, -1);
l = new_ticked_ttilog(h, database, "ENB_PHY_DL_TICK", "frame", "subframe",
"ENB_PHY_ULSCH_UE_DCI", "mcs", 0, -1);
v = new_view_tti(10, g, w, new_color(g, "#0c0c72"));
logger_add_view(l, v);
e->ul_mcs_logger = l;
/* downlink/uplink UE DCIs */
widget_add_child(g, top_container,
new_label(g,"DL/UL TICK/DCI/ACK/NACK [all UEs]"), -1);
......@@ -745,7 +789,9 @@ restart:
event e;
e = get_event(enb_data.socket, v, database);
if (e.type == -1) goto restart;
if (pthread_mutex_lock(&enb_data.lock)) abort();
handle_event(h, e);
if (pthread_mutex_unlock(&enb_data.lock)) abort();
}
return 0;
......
......@@ -2,8 +2,8 @@ CC=gcc
CFLAGS=-Wall -g -pthread -I/usr/include/X11/Xft -I/usr/include/freetype2
OBJS=init.o loop.o toplevel_window.o x.o container.o widget.o \
gui.o label.o event.o xy_plot.o textlist.o notify.o positioner.o \
timeline.o space.o image.o
gui.o label.o textarea.o event.o xy_plot.o textlist.o notify.o \
positioner.o timeline.o space.o image.o
gui.a: $(OBJS)
ar cr gui.a $(OBJS)
......
......@@ -14,6 +14,10 @@ typedef void widget;
#define DEFAULT_FONT 0
/* tic type for XY plot */
#define XY_PLOT_DEFAULT_TICK 0
#define XY_PLOT_SCROLL_TICK 1
/* key modifiers */
#define KEY_SHIFT (1<<0)
#define KEY_CONTROL (1<<1)
......@@ -30,6 +34,7 @@ widget *new_toplevel_window(gui *gui, int width, int height, char *title);
widget *new_container(gui *gui, int vertical);
widget *new_positioner(gui *gui);
widget *new_label(gui *gui, const char *text);
widget *new_textarea(gui *gui, int width, int height, int maxsize);
widget *new_xy_plot(gui *gui, int width, int height, char *label,
int vruler_width);
widget *new_textlist(gui *gui, int width, int nlines, int background_color);
......@@ -41,6 +46,8 @@ widget *new_image(gui *gui, unsigned char *data, int length);
void label_set_clickable(gui *gui, widget *label, int clickable);
void label_set_text(gui *gui, widget *label, char *text);
void textarea_set_text(gui *gui, widget *textarea, char *text);
void container_set_child_growable(gui *_gui, widget *_this,
widget *child, int growable);
......@@ -51,6 +58,7 @@ void xy_plot_set_points(gui *gui, widget *this,
int plot, int npoints, float *x, float *y);
void xy_plot_get_dimensions(gui *gui, widget *this, int *width, int *height);
void xy_plot_set_title(gui *gui, widget *this, char *label);
void xy_plot_set_tick_type(gui *gui, widget *this, int type);
void textlist_add(gui *gui, widget *this, const char *text, int position,
int color);
......
......@@ -31,7 +31,7 @@ extern int volatile gui_logd;
enum widget_type {
TOPLEVEL_WINDOW, CONTAINER, POSITIONER, TEXT_LIST, XY_PLOT, BUTTON, LABEL,
TIMELINE, SPACE, IMAGE
TEXTAREA, TIMELINE, SPACE, IMAGE
};
struct widget_list;
......@@ -117,6 +117,7 @@ struct xy_plot_widget {
int wanted_height;
struct xy_plot_plot *plots;
int nplots;
int tick_type;
};
struct timeline_subline {
......@@ -148,6 +149,17 @@ struct label_widget {
int baseline; /* as given by the graphic's backend */
};
struct textarea_widget {
struct widget common;
char *t;
int tmaxsize;
int color;
int wanted_width;
int wanted_height;
int baseline; /* as given by the graphic's backend */
int text_width; /* as given by the graphic's backend */
};
struct space_widget {
struct widget common;
int wanted_width;
......
#include "gui.h"
#include "gui_defs.h"
#include "x.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static void paint(gui *_gui, widget *_w)
{
struct gui *g = _gui;
struct textarea_widget *t = _w;
LOGD("PAINT textarea '%s'\n", t->t);
x_fill_rectangle(g->x, g->xwin, BACKGROUND_COLOR,
t->common.x, t->common.y,
t->common.width, t->common.height);
x_draw_clipped_string(g->x, g->xwin, DEFAULT_FONT, t->color,
t->common.x + t->common.width - t->text_width,
t->common.y + t->baseline, t->t,
t->common.x, t->common.y,
t->common.width, t->common.height);
}
static void hints(gui *_gui, widget *_w, int *width, int *height)
{
struct textarea_widget *t = _w;
LOGD("HINTS textarea '%s'\n", t->t);
*width = t->wanted_width;
*height = t->wanted_height;
}
widget *new_textarea(gui *_gui, int width, int height, int maxsize)
{
struct gui *g = _gui;
struct textarea_widget *w;
int _;
glock(g);
w = new_widget(g, TEXTAREA, sizeof(struct textarea_widget));
w->t = calloc(maxsize, 1);
if (w->t == NULL) OOM;
w->tmaxsize = maxsize;
w->wanted_width = width;
w->wanted_height = height;
w->color = FOREGROUND_COLOR;
w->text_width = 0;
x_text_get_dimensions(g->x, DEFAULT_FONT, "jlM",
&_, &_, &w->baseline);
w->common.paint = paint;
w->common.hints = hints;
gunlock(g);
return w;
}
/*************************************************************************/
/* public functions */
/*************************************************************************/
void textarea_set_text(gui *_g, widget *_this, char *text)
{
struct gui *g = _g;
struct textarea_widget *this = _this;
int _;
int len = strlen(text);
if (len >= this->tmaxsize) {
fprintf(stderr, "ERROR: string '%s' too big for textarea\n", text);
return;
}
glock(g);
strcpy(this->t, text);
x_text_get_dimensions(g->x, DEFAULT_FONT, text,
&this->text_width, &_, &this->baseline);
send_event(g, DIRTY, this->common.id);
gunlock(g);
}
......@@ -265,7 +265,7 @@ void widget_dirty(gui *_gui, widget *_this)
static const char *names[] = {
"TOPLEVEL_WINDOW", "CONTAINER", "POSITIONER", "TEXT_LIST",
"XY_PLOT", "BUTTON", "LABEL", "TIMELINE", "SPACE", "IMAGE"
"XY_PLOT", "BUTTON", "LABEL", "TEXTAREA", "TIMELINE", "SPACE", "IMAGE"
};
const char *widget_name(enum widget_type type)
{
......@@ -277,6 +277,7 @@ const char *widget_name(enum widget_type type)
case XY_PLOT:
case BUTTON:
case LABEL:
case TEXTAREA:
case TIMELINE:
case SPACE:
case IMAGE:
......
#include "gui.h"
#include "gui_defs.h"
#include "x.h"
#include "../utils.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#if 0
/* this version behaves differently when you resize the XY plot. Say
* you increase the size. The old (smaller) view is put at the center
* of the new view. Everything inside keeps the same size/aspect ratio.
* The other version below resizes the old view so that it fully occupies
* the new view. It may introduce aspect ratio changes, but usage seems
* to suggest it's a better behaviour.
*/
static void paint(gui *_gui, widget *_this)
{
struct gui *g = _gui;
......@@ -70,9 +79,9 @@ static void paint(gui *_gui, widget *_this)
*/
char v[64];
int vwidth, dummy;
float x = (k * ticstep - allocated_xmin) /
(allocated_xmax - allocated_xmin) *
(allocated_plot_width - 1);
int x = (k * ticstep - allocated_xmin) /
(allocated_xmax - allocated_xmin) *
(allocated_plot_width - 1);
x_draw_line(g->x, g->xwin, FOREGROUND_COLOR,
this->common.x + this->vrule_width + x,
this->common.y + this->common.height - this->label_height * 2,
......@@ -85,7 +94,7 @@ static void paint(gui *_gui, widget *_this)
this->common.y + this->common.height - this->label_height * 2 +
this->label_baseline,
v);
LOGD("tic k %d val %g x %g\n", k, k * ticstep, x);
LOGD("tic k %d val %g x %d\n", k, k * ticstep, x);
}
/* vertical tics */
......@@ -112,9 +121,9 @@ static void paint(gui *_gui, widget *_this)
for (k = kmin; k <= kmax; k++) {
char v[64];
int vwidth, dummy;
float y = (k * ticstep - allocated_ymin) /
(allocated_ymax - allocated_ymin) *
(allocated_plot_height - 1);
int y = (k * ticstep - allocated_ymin) /
(allocated_ymax - allocated_ymin) *
(allocated_plot_height - 1);
sprintf(v, "%g", k * ticstep);
x_text_get_dimensions(g->x, DEFAULT_FONT, v, &vwidth, &dummy, &dummy);
x_draw_line(g->x, g->xwin, FOREGROUND_COLOR,
......@@ -155,6 +164,184 @@ static void paint(gui *_gui, widget *_this)
x_plot_points(g->x, g->xwin, this->plots[n].color);
}
}
#endif
static void paint(gui *_gui, widget *_this)
{
struct gui *g = _gui;
struct xy_plot_widget *this = _this;
int allocated_plot_width;
int allocated_plot_height;
float pxsize;
float ticdist;
float tic;
float ticstep;
int k, kmin, kmax;
float allocated_xmin, allocated_xmax;
float allocated_ymin, allocated_ymax;
int i;
int n;
char v[64];
int vwidth, dummy;
# define FLIP(v) (-(v) + allocated_plot_height-1)
LOGD("PAINT xy plot xywh %d %d %d %d\n", this->common.x, this->common.y, this->common.width, this->common.height);
//x_draw_rectangle(g->x, g->xwin, 1, this->common.x, this->common.y, this->common.width, this->common.height);
allocated_plot_width = this->common.width - this->vrule_width;
allocated_plot_height = this->common.height - this->label_height * 2;
if (allocated_plot_width <= 1 || allocated_plot_height <= 1) {
WARN("PAINT xy plot: width (%d) or height (%d) is wrong, not painting\n",
this->common.width, this->common.height);
return;
}
/* plot zone */
/* TODO: refine height - height of hrule text may be != from label */
x_draw_rectangle(g->x, g->xwin, 1,
this->common.x + this->vrule_width,
this->common.y,
this->common.width - this->vrule_width -1, /* -1 to see right border */
this->common.height - this->label_height * 2);
/* horizontal tics */
pxsize = (this->xmax - this->xmin) / allocated_plot_width;
ticdist = 100;
tic = floor(log10(ticdist * pxsize));
ticstep = powf(10, tic);
allocated_xmin = this->xmin;
allocated_xmax = this->xmax;
/* adjust tic if too tight */
LOGD("pre x ticstep %g\n", ticstep);
while (1) {
if (ticstep / (allocated_xmax - allocated_xmin)
* (allocated_plot_width - 1) > 40) break;
ticstep *= 2;
}
LOGD("post x ticstep %g\n", ticstep);
LOGD("xmin/max %g %g width allocated %d alloc xmin/max %g %g ticstep %g\n", this->xmin, this->xmax, allocated_plot_width, allocated_xmin, allocated_xmax, ticstep);
kmin = ceil(allocated_xmin / ticstep);
kmax = floor(allocated_xmax / ticstep);
for (k = kmin; k <= kmax; k++) {
/*
(k * ticstep - allocated_xmin) / (allocated_max - allocated_xmin) =
(x - 0) / (allocated_plot_width-1 - 0)
*/
int x = (k * ticstep - allocated_xmin) /
(allocated_xmax - allocated_xmin) *
(allocated_plot_width - 1);
int px;
x_draw_line(g->x, g->xwin, FOREGROUND_COLOR,
this->common.x + this->vrule_width + x,
this->common.y + this->common.height - this->label_height * 2,
this->common.x + this->vrule_width + x,
this->common.y + this->common.height - this->label_height * 2 - 5);
sprintf(v, "%g", k * ticstep);
x_text_get_dimensions(g->x, DEFAULT_FONT, v, &vwidth, &dummy, &dummy);
/* do not draw after the widget ('width-1' for if we use 'width'
* it is still off by 1 pixel for whatever reason) */
px = this->vrule_width + x - vwidth/2;
if (px + vwidth > this->common.width-1)
px = this->common.width-1 - vwidth;
x_draw_string(g->x, g->xwin, DEFAULT_FONT, FOREGROUND_COLOR,
this->common.x + px,
this->common.y + this->common.height - this->label_height * 2 +
this->label_baseline,
v);
LOGD("tic k %d val %g x %d\n", k, k * ticstep, x);
}
/* vertical tics */
allocated_ymin = this->ymin;
allocated_ymax = this->ymax;
switch (this->tick_type) {
case XY_PLOT_DEFAULT_TICK:
pxsize = (this->ymax - this->ymin) / allocated_plot_height;
ticdist = 30;
tic = floor(log10(ticdist * pxsize));
ticstep = powf(10, tic);
/* adjust tic if too tight */
LOGD("pre y ticstep %g\n", ticstep);
while (1) {
if (ticstep / (allocated_ymax - allocated_ymin)
* (allocated_plot_height - 1) > 20) break;
ticstep *= 2;
}
LOGD("post y ticstep %g\n", ticstep);
LOGD("ymin/max %g %g height allocated %d alloc "
"ymin/max %g %g ticstep %g\n", this->ymin, this->ymax,
allocated_plot_height, allocated_ymin, allocated_ymax, ticstep);
kmin = ceil(allocated_ymin / ticstep);
kmax = floor(allocated_ymax / ticstep);
for (k = kmin; k <= kmax; k++) {
int y = (k * ticstep - allocated_ymin) /
(allocated_ymax - allocated_ymin) *
(allocated_plot_height - 1);
sprintf(v, "%g", k * ticstep);
x_text_get_dimensions(g->x, DEFAULT_FONT, v, &vwidth, &dummy, &dummy);
x_draw_line(g->x, g->xwin, FOREGROUND_COLOR,
this->common.x + this->vrule_width,
this->common.y + FLIP(y),
this->common.x + this->vrule_width + 5,
this->common.y + FLIP(y));
x_draw_string(g->x, g->xwin, DEFAULT_FONT, FOREGROUND_COLOR,
this->common.x + this->vrule_width - vwidth - 2,
this->common.y + FLIP(y)-this->label_height/2+this->label_baseline,
v);
}
break;
case XY_PLOT_SCROLL_TICK:
/* print only max value, formatted using 'bps' for readability */
bps(v, this->ymax, "");
x_text_get_dimensions(g->x, DEFAULT_FONT, v, &vwidth, &dummy, &dummy);
x_draw_string(g->x, g->xwin, DEFAULT_FONT, FOREGROUND_COLOR,
this->common.x + this->vrule_width - vwidth - 2,
this->common.y + +this->label_baseline,
v);
/* vertically divide into 5 */
for (k = 1; k < 5; k++) {
int y = round((k * (allocated_plot_height - 1)) / 5.);
x_draw_line(g->x, g->xwin, FOREGROUND_COLOR,
this->common.x + this->vrule_width,
this->common.y + y,
this->common.x + this->vrule_width + 5,
this->common.y + y);
}
break;
} /* swich (this->tick_type) */
/* label at bottom, in the middle */
x_draw_string(g->x, g->xwin, DEFAULT_FONT, FOREGROUND_COLOR,
this->common.x + (this->common.width - this->label_width) / 2,
this->common.y + this->common.height - this->label_height
+ this->label_baseline,
this->label);
for (n = 0; n < this->nplots; n++) {
/* points */
float ax, bx, ay, by;
ax = (allocated_plot_width-1) / (allocated_xmax - allocated_xmin);
bx = -ax * allocated_xmin;
ay = (allocated_plot_height-1) / (allocated_ymax - allocated_ymin);
by = -ay * allocated_ymin;
for (i = 0; i < this->plots[n].npoints; i++) {
int x, y;
x = ax * this->plots[n].x[i] + bx;
y = ay * this->plots[n].y[i] + by;
if (x >= 0 && x < allocated_plot_width &&
y >= 0 && y < allocated_plot_height)
x_add_point(g->x,
this->common.x + this->vrule_width + x,
this->common.y + FLIP(y));
}
x_plot_points(g->x, g->xwin, this->plots[n].color);
}
}
static void hints(gui *_gui, widget *_w, int *width, int *height)
{
......@@ -191,6 +378,7 @@ widget *new_xy_plot(gui *_gui, int width, int height, char *label,
w->ymax = 1;
w->plots = NULL;
w->nplots = 0;
w->tick_type = XY_PLOT_DEFAULT_TICK;
w->common.paint = paint;
w->common.hints = hints;
......@@ -309,3 +497,17 @@ void xy_plot_set_title(gui *_gui, widget *_this, char *label)
gunlock(g);
}
void xy_plot_set_tick_type(gui *_gui, widget *_this, int type)
{
struct gui *g = _gui;
struct xy_plot_widget *this = _this;
glock(g);
this->tick_type = type;
send_event(g, DIRTY, this->common.id);
gunlock(g);
}
......@@ -2,7 +2,7 @@ CC=gcc
CFLAGS=-Wall -g -pthread -I..
OBJS=logger.o textlog.o framelog.o ttilog.o timelog.o ticklog.o iqlog.o \
iqdotlog.o
iqdotlog.o ticked_ttilog.o throughputlog.o
logger.a: $(OBJS)
ar cr logger.a $(OBJS)
......
......@@ -10,6 +10,13 @@ logger *new_textlog(void *event_handler, void *database,
logger *new_ttilog(void *event_handler, void *database,
char *event_name, char *frame_varname, char *subframe_varname,
char *data_varname, int convert_to_dB);
logger *new_ticked_ttilog(void *event_handler, void *database,
char *tick_event_name, char *frame_varname, char *subframe_varname,
char *event_name, char *data_varname,
int convert_to_dB, float empty_value);
logger *new_throughputlog(void *event_handler, void *database,
char *tick_event_name, char *frame_varname, char *subframe_varname,
char *event_name, char *data_varname);
logger *new_timelog(void *event_handler, void *database, char *event_name);
logger *new_ticklog(void *event_handler, void *database,
char *event_name, char *frame_name, char *subframe_name);
......@@ -28,5 +35,6 @@ void textlog_dump_buffer(logger *_this, int dump_buffer);
void logger_add_view(logger *l, view *v);
void logger_set_filter(logger *l, void *filter);
void ticked_ttilog_set_tick_filter(logger *l, void *filter);
#endif /* _LOGGER_H_ */
#include "logger.h"
#include "logger_defs.h"
#include "event.h"
#include "database.h"
#include "handler.h"
#include "filter/filter.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
struct throughputlog {
struct logger common;
void *database;
int tick_frame_arg;
int tick_subframe_arg;
int data_frame_arg;
int data_subframe_arg;
int data_arg;
int last_tick_frame;
int last_tick_subframe;
unsigned long bits[1000];
unsigned long total;
int insert_point;
char *tick_event_name;
unsigned long tick_handler_id;
/* tick filter - NULL is no filter set */
void *tick_filter;
};
static void _event(void *p, event e)
{
struct throughputlog *l = p;
int frame;
int subframe;
unsigned long value;
if (l->common.filter != NULL && filter_eval(l->common.filter, e) == 0)
return;
frame = e.e[l->data_frame_arg].i;
subframe = e.e[l->data_subframe_arg].i;
if (frame != l->last_tick_frame || subframe != l->last_tick_subframe) {
printf("WARNING: %s:%d: data comes without previous tick!\n",
__FILE__, __LINE__);
return;
}
switch (e.e[l->data_arg].type) {
case EVENT_INT: value = e.e[l->data_arg].i; break;
case EVENT_ULONG: value = e.e[l->data_arg].ul; break;
default: printf("%s:%d: unsupported type\n", __FILE__, __LINE__); abort();
}
l->total += value;
l->bits[l->insert_point] += value;
}
static void _tick_event(void *p, event e)
{
struct throughputlog *l = p;
int i;
int frame;
int subframe;
if (l->tick_filter != NULL && filter_eval(l->tick_filter, e) == 0)
return;
frame = e.e[l->tick_frame_arg].i;
subframe = e.e[l->tick_subframe_arg].i;
for (i = 0; i < l->common.vsize; i++)
l->common.v[i]->append(l->common.v[i], frame, subframe, (double)l->total);
l->insert_point = (l->insert_point + 1) % 1000;
l->total -= l->bits[l->insert_point];
l->bits[l->insert_point] = 0;
l->last_tick_frame = frame;
l->last_tick_subframe = subframe;
}
logger *new_throughputlog(event_handler *h, void *database,
char *tick_event_name, char *frame_varname, char *subframe_varname,
char *event_name, char *data_varname)
{
struct throughputlog *ret;
int event_id;
database_event_format f;
int i;
ret = calloc(1, sizeof(struct throughputlog)); if (ret == NULL) abort();
ret->common.event_name = strdup(event_name);
if (ret->common.event_name == NULL) abort();
ret->database = database;
ret->tick_event_name = strdup(tick_event_name);
if (ret->tick_event_name == NULL) abort();
/* tick event */
event_id = event_id_from_name(database, tick_event_name);
ret->tick_handler_id=register_handler_function(h,event_id,_tick_event,ret);
f = get_format(database, event_id);
/* look for frame and subframe */
ret->tick_frame_arg = -1;
ret->tick_subframe_arg = -1;
for (i = 0; i < f.count; i++) {
if (!strcmp(f.name[i], frame_varname)) ret->tick_frame_arg = i;
if (!strcmp(f.name[i], subframe_varname)) ret->tick_subframe_arg = i;
}
if (ret->tick_frame_arg == -1) {
printf("%s:%d: frame argument '%s' not found in event '%s'\n",
__FILE__, __LINE__, frame_varname, event_name);
abort();
}
if (ret->tick_subframe_arg == -1) {
printf("%s:%d: subframe argument '%s' not found in event '%s'\n",
__FILE__, __LINE__, subframe_varname, event_name);
abort();
}
if (strcmp(f.type[ret->tick_frame_arg], "int") != 0) {
printf("%s:%d: argument '%s' has wrong type (should be 'int')\n",
__FILE__, __LINE__, frame_varname);
abort();
}
if (strcmp(f.type[ret->tick_subframe_arg], "int") != 0) {
printf("%s:%d: argument '%s' has wrong type (should be 'int')\n",
__FILE__, __LINE__, subframe_varname);
abort();
}
/* data event */
event_id = event_id_from_name(database, event_name);
ret->common.handler_id = register_handler_function(h,event_id,_event,ret);
f = get_format(database, event_id);
/* look for frame, subframe and data args */
ret->data_frame_arg = -1;
ret->data_subframe_arg = -1;
ret->data_arg = -1;
for (i = 0; i < f.count; i++) {
if (!strcmp(f.name[i], frame_varname)) ret->data_frame_arg = i;
if (!strcmp(f.name[i], subframe_varname)) ret->data_subframe_arg = i;
if (!strcmp(f.name[i], data_varname)) ret->data_arg = i;
}
if (ret->data_frame_arg == -1) {
printf("%s:%d: frame argument '%s' not found in event '%s'\n",
__FILE__, __LINE__, frame_varname, event_name);
abort();
}
if (ret->data_subframe_arg == -1) {
printf("%s:%d: subframe argument '%s' not found in event '%s'\n",
__FILE__, __LINE__, subframe_varname, event_name);
abort();
}
if (ret->data_arg == -1) {
printf("%s:%d: data argument '%s' not found in event '%s'\n",
__FILE__, __LINE__, data_varname, event_name);
abort();
}
if (strcmp(f.type[ret->data_frame_arg], "int") != 0) {
printf("%s:%d: argument '%s' has wrong type (should be 'int')\n",
__FILE__, __LINE__, frame_varname);
abort();
}
if (strcmp(f.type[ret->data_subframe_arg], "int") != 0) {
printf("%s:%d: argument '%s' has wrong type (should be 'int')\n",
__FILE__, __LINE__, subframe_varname);
abort();
}
if (strcmp(f.type[ret->data_arg], "int") != 0 &&
strcmp(f.type[ret->data_arg], "float") != 0) {
printf("%s:%d: argument '%s' has wrong type"
" (should be 'int' or 'float')\n",
__FILE__, __LINE__, data_varname);
abort();
}
return ret;
}
void throughputlog_set_tick_filter(logger *_l, void *filter)
{
struct throughputlog *l = (struct throughputlog *)_l;
free(l->tick_filter);
l->tick_filter = filter;
}
#include "logger.h"
#include "logger_defs.h"
#include "event.h"
#include "database.h"
#include "handler.h"
#include "filter/filter.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
struct ticked_ttilog {
struct logger common;
void *database;
int tick_frame_arg;
int tick_subframe_arg;
int data_frame_arg;
int data_subframe_arg;
int data_arg;
int convert_to_dB;
int last_tick_frame;
int last_tick_subframe;
float last_value;
float empty_value;
char *tick_event_name;
unsigned long tick_handler_id;
/* tick filter - NULL is no filter set */
void *tick_filter;
};
static void _event(void *p, event e)
{
struct ticked_ttilog *l = p;
int frame;
int subframe;
float value;
if (l->common.filter != NULL && filter_eval(l->common.filter, e) == 0)
return;
frame = e.e[l->data_frame_arg].i;
subframe = e.e[l->data_subframe_arg].i;
if (frame != l->last_tick_frame || subframe != l->last_tick_subframe) {
printf("WARNING: %s:%d: data comes without previous tick!\n",
__FILE__, __LINE__);
return;
}
switch (e.e[l->data_arg].type) {
case EVENT_INT: value = e.e[l->data_arg].i; break;
case EVENT_ULONG: value = e.e[l->data_arg].ul; break;
default: printf("%s:%d: unsupported type\n", __FILE__, __LINE__); abort();
}
if (l->convert_to_dB) value = 10 * log10(value);
l->last_value = value;
}
static void _tick_event(void *p, event e)
{
struct ticked_ttilog *l = p;
int i;
int frame;
int subframe;
if (l->tick_filter != NULL && filter_eval(l->tick_filter, e) == 0)
return;
frame = e.e[l->tick_frame_arg].i;
subframe = e.e[l->tick_subframe_arg].i;
for (i = 0; i < l->common.vsize; i++)
l->common.v[i]->append(l->common.v[i], frame, subframe, l->last_value);
l->last_value = l->empty_value;
l->last_tick_frame = frame;
l->last_tick_subframe = subframe;
}
logger *new_ticked_ttilog(event_handler *h, void *database,
char *tick_event_name, char *frame_varname, char *subframe_varname,
char *event_name, char *data_varname,
int convert_to_dB, float empty_value)
{
struct ticked_ttilog *ret;
int event_id;
database_event_format f;
int i;
ret = calloc(1, sizeof(struct ticked_ttilog)); if (ret == NULL) abort();
ret->common.event_name = strdup(event_name);
if (ret->common.event_name == NULL) abort();
ret->database = database;
ret->convert_to_dB = convert_to_dB;
ret->tick_event_name = strdup(tick_event_name);
if (ret->tick_event_name == NULL) abort();
ret->empty_value = empty_value;
ret->last_value = empty_value;
/* tick event */
event_id = event_id_from_name(database, tick_event_name);
ret->tick_handler_id=register_handler_function(h,event_id,_tick_event,ret);
f = get_format(database, event_id);
/* look for frame and subframe */
ret->tick_frame_arg = -1;
ret->tick_subframe_arg = -1;
for (i = 0; i < f.count; i++) {
if (!strcmp(f.name[i], frame_varname)) ret->tick_frame_arg = i;
if (!strcmp(f.name[i], subframe_varname)) ret->tick_subframe_arg = i;
}
if (ret->tick_frame_arg == -1) {
printf("%s:%d: frame argument '%s' not found in event '%s'\n",
__FILE__, __LINE__, frame_varname, event_name);
abort();
}
if (ret->tick_subframe_arg == -1) {
printf("%s:%d: subframe argument '%s' not found in event '%s'\n",
__FILE__, __LINE__, subframe_varname, event_name);
abort();
}
if (strcmp(f.type[ret->tick_frame_arg], "int") != 0) {
printf("%s:%d: argument '%s' has wrong type (should be 'int')\n",
__FILE__, __LINE__, frame_varname);
abort();
}
if (strcmp(f.type[ret->tick_subframe_arg], "int") != 0) {
printf("%s:%d: argument '%s' has wrong type (should be 'int')\n",
__FILE__, __LINE__, subframe_varname);
abort();
}
/* data event */
event_id = event_id_from_name(database, event_name);
ret->common.handler_id = register_handler_function(h,event_id,_event,ret);
f = get_format(database, event_id);
/* look for frame, subframe and data args */
ret->data_frame_arg = -1;
ret->data_subframe_arg = -1;
ret->data_arg = -1;
for (i = 0; i < f.count; i++) {
if (!strcmp(f.name[i], frame_varname)) ret->data_frame_arg = i;
if (!strcmp(f.name[i], subframe_varname)) ret->data_subframe_arg = i;
if (!strcmp(f.name[i], data_varname)) ret->data_arg = i;
}
if (ret->data_frame_arg == -1) {
printf("%s:%d: frame argument '%s' not found in event '%s'\n",
__FILE__, __LINE__, frame_varname, event_name);
abort();
}
if (ret->data_subframe_arg == -1) {
printf("%s:%d: subframe argument '%s' not found in event '%s'\n",
__FILE__, __LINE__, subframe_varname, event_name);
abort();
}
if (ret->data_arg == -1) {
printf("%s:%d: data argument '%s' not found in event '%s'\n",
__FILE__, __LINE__, data_varname, event_name);
abort();
}
if (strcmp(f.type[ret->data_frame_arg], "int") != 0) {
printf("%s:%d: argument '%s' has wrong type (should be 'int')\n",
__FILE__, __LINE__, frame_varname);
abort();
}
if (strcmp(f.type[ret->data_subframe_arg], "int") != 0) {
printf("%s:%d: argument '%s' has wrong type (should be 'int')\n",
__FILE__, __LINE__, subframe_varname);
abort();
}
if (strcmp(f.type[ret->data_arg], "int") != 0 &&
strcmp(f.type[ret->data_arg], "float") != 0) {
printf("%s:%d: argument '%s' has wrong type"
" (should be 'int' or 'float')\n",
__FILE__, __LINE__, data_varname);
abort();
}
return ret;
}
void ticked_ttilog_set_tick_filter(logger *_l, void *filter)
{
struct ticked_ttilog *l = (struct ticked_ttilog *)_l;
free(l->tick_filter);
l->tick_filter = filter;
}
......@@ -7,6 +7,7 @@
#include <ctype.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <math.h>
void new_thread(void *(*f)(void *), void *data)
{
......@@ -36,6 +37,16 @@ void sleepms(int ms)
if (nanosleep(&t, NULL)) abort();
}
void bps(char *out, float v, char *suffix)
{
static char *bps_unit[4] = { "", "k", "M", "G" };
int flog;
if (v < 1000) flog = 0; else flog = floor(floor(log10(v)) / 3);
if (flog > 3) flog = 3;
v /= pow(10, flog*3);
sprintf(out, "%g%s%s", round(v*100)/100, bps_unit[flog], suffix);
}
/****************************************************************************/
/* list */
/****************************************************************************/
......
......@@ -3,6 +3,7 @@
void new_thread(void *(*f)(void *), void *data);
void sleepms(int ms);
void bps(char *out, float v, char *suffix);
/****************************************************************************/
/* list */
......
CC=gcc
CFLAGS=-Wall -g -pthread -I.. -I../logger
OBJS=stdout.o textlist.o xy.o tti.o time.o ticktime.o
OBJS=stdout.o textlist.o xy.o tti.o time.o ticktime.o scrolltti.o
view.a: $(OBJS)
ar cr view.a $(OBJS)
......
#include "view.h"
#include "../utils.h"
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <stdarg.h>
#include <string.h>
#include <math.h>
struct scrolltti {
view common;
gui *g;
widget *w;
widget *throughput_textarea;
int plot;
float refresh_rate;
pthread_mutex_t lock;
unsigned long data[1000];
unsigned long total; /* sum data[0..999] to have smoother value printed */
float xout[1000];
float yout[1000];
int insert_point;
};
/* this array is used to get Y range 1000, 2000, 5000, 10000, ... */
static int tolog[11] = { -1, 1, 2, 5, 5, 5, 10, 10, 10, 10, 10 };
static void *scrolltti_thread(void *_this)
{
struct scrolltti *this = _this;
int i;
int p;
float max, mlog;
char o[64];
while (1) {
if (pthread_mutex_lock(&this->lock)) abort();
/* TODO: optimize */
p = this->insert_point;
max = 0;
for (i = 0; i < 1000; i++) {
this->xout[i] = i;
this->yout[i] = this->data[p];
if (this->data[p] > max) max = this->data[p];
p = (p + 1) % 1000;
}
bps(o, this->total/1000., "b/s");
textarea_set_text(this->g, this->throughput_textarea, o);
/* for Y range we want 1000, 2000, 5000, 10000, 20000, 50000, etc. */
if (max < 1000) max = 1000;
mlog = pow(10, floor(log10(max)));
max = tolog[(int)ceil(max/mlog)] * mlog;
xy_plot_set_range(this->g, this->w, 0, 1000, 0, max);
xy_plot_set_points(this->g, this->w, this->plot,
1000, this->xout, this->yout);
if (pthread_mutex_unlock(&this->lock)) abort();
sleepms(1000/this->refresh_rate);
}
return 0;
}
static void clear(view *this)
{
/* TODO */
}
static void append(view *_this, int frame, int subframe, double value)
{
struct scrolltti *this = (struct scrolltti *)_this;
if (pthread_mutex_lock(&this->lock)) abort();
this->total -= this->data[this->insert_point];
this->data[this->insert_point] = value;
this->total += this->data[this->insert_point];
this->insert_point = (this->insert_point + 1) % 1000;
if (pthread_mutex_unlock(&this->lock)) abort();
}
view *new_view_scrolltti(float refresh_rate, gui *g, widget *w, int color,
widget *throughput_textarea)
{
struct scrolltti *ret = calloc(1, sizeof(struct scrolltti));
if (ret == NULL) abort();
ret->common.clear = clear;
ret->common.append = (void (*)(view *, ...))append;
ret->refresh_rate = refresh_rate;
ret->g = g;
ret->w = w;
ret->throughput_textarea = throughput_textarea;
ret->plot = xy_plot_new_plot(g, w, color);
if (pthread_mutex_init(&ret->lock, NULL)) abort();
new_thread(scrolltti_thread, ret);
return (view *)ret;
}
......@@ -19,6 +19,8 @@ view *new_view_xy(int length, float refresh_rate, gui *g, widget *w,
int color, enum xy_mode mode);
view *new_view_tti(float refresh_rate, gui *g, widget *w,
int color);
view *new_view_scrolltti(float refresh_rate, gui *g, widget *w,
int color, widget *throughput_label);
view *new_view_time(int number_of_seconds, float refresh_rate,
gui *g, widget *w);
view *new_subview_time(view *time, int line, int color, int size);
......
This diff is collapsed.
......@@ -86,8 +86,8 @@ int timer_handle_signal(siginfo_t *info)
timer_p = (struct timer_elm_s *)info->si_ptr;
// LG: To many traces for msc timer:
// TMR_DEBUG("Timer with id 0x%lx has expired\n", (long)timer_p->timer);
TMR_DEBUG("Timer with id 0x%lx has expired\n", (long)timer_p->timer);
task_id = timer_p->task_id;
instance = timer_p->instance;
message_p = itti_alloc_new_message(TASK_TIMER, TIMER_HAS_EXPIRED);
......@@ -120,6 +120,10 @@ int timer_handle_signal(siginfo_t *info)
return -1;
}
#if defined(ENB_AGENT_SB_IF)
#endif
return 0;
}
......
#!/bin/sh
echo "building ctags for openair1 and openair2 ..."
ctags -e -R --exclude=openair1/DOCS/ --exclude=openair2/DOCS/ --exclude=openair2/RRC/CELLULAR/ --exclude=openair2/NAS/DRIVER/CELLULAR/ --exclude=openair2/SIMULATION/ --exclude=targets/DOCS/ --exclude=targets/PROJECTS/ openair1 openair2 openair3 targets cmake_targets common
......@@ -69,6 +69,11 @@ enum openair_SYNCH_STATUS {
openair_SCHED_EXIT
};
enum openair_HARQ_TYPE {
openair_harq_DL = 0,
openair_harq_UL,
openair_harq_RA
};
#define DAQ_AGC_ON 1
#define DAQ_AGC_OFF 0
......
......@@ -21,11 +21,11 @@
/*! \file phy_procedures_lte_eNB.c
* \brief Implementation of eNB procedures from 36.213 LTE specifications
* \author R. Knopp, F. Kaltenberger, N. Nikaein
* \author R. Knopp, F. Kaltenberger, N. Nikaein, X. Foukas
* \date 2011
* \version 0.1
* \company Eurecom
* \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr,navid.nikaein@eurecom.fr
* \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr,navid.nikaein@eurecom.fr, x.foukas@sms.ed.ac.uk
* \note
* \warning
*/
......@@ -61,6 +61,14 @@
# include "intertask_interface.h"
#endif
#if defined(FLEXRAN_AGENT_SB_IF)
//Agent-related headers
#include "ENB_APP/flexran_agent_extern.h"
#include "ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.h"
#include "LAYER2/MAC/flexran_agent_mac_proto.h"
#endif
//#define DIAG_PHY
#define NS_PER_SLOT 500000
......@@ -221,7 +229,7 @@ int8_t find_next_ue_index(PHY_VARS_eNB *eNB)
return(-1);
}
int get_ue_active_harq_pid(const uint8_t Mod_id,const uint8_t CC_id,const uint16_t rnti, const int frame, const uint8_t subframe,uint8_t *harq_pid,uint8_t *round,const uint8_t ul_flag)
int get_ue_active_harq_pid(const uint8_t Mod_id,const uint8_t CC_id,const uint16_t rnti, const int frame, const uint8_t subframe,uint8_t *harq_pid,uint8_t *round,const uint8_t harq_flag)
{
LTE_eNB_DLSCH_t *DLSCH_ptr;
LTE_eNB_ULSCH_t *ULSCH_ptr;
......@@ -235,9 +243,20 @@ int get_ue_active_harq_pid(const uint8_t Mod_id,const uint8_t CC_id,const uint16
return(-1);
}
if (ul_flag == 0) {// this is a DL request
if ((harq_flag == openair_harq_DL) || (harq_flag == openair_harq_RA)) {// this is a DL request
DLSCH_ptr = PHY_vars_eNB_g[Mod_id][CC_id]->dlsch[(uint32_t)UE_id][0];
if (harq_flag == openair_harq_RA) {
if (DLSCH_ptr->harq_processes[0] != NULL) {
*harq_pid = 0;
*round = DLSCH_ptr->harq_processes[0]->round;
return 0;
} else {
return -1;
}
}
/* let's go synchronous for the moment - maybe we can change at some point */
i = (frame * 10 + subframe) % 8;
......@@ -763,7 +782,9 @@ void generate_eNB_dlsch_params(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,DCI_ALLOC
T(T_ENB_PHY_DLSCH_UE_DCI, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe), T_INT(UE_id),
T_INT(dci_alloc->rnti), T_INT(dci_alloc->format),
T_INT(eNB->dlsch[(int)UE_id][0]->current_harq_pid));
T_INT(eNB->dlsch[(int)UE_id][0]->current_harq_pid),
T_INT(eNB->dlsch[(int)UE_id][0]->harq_processes[eNB->dlsch[(int)UE_id][0]->current_harq_pid]->mcs),
T_INT(eNB->dlsch[(int)UE_id][0]->harq_processes[eNB->dlsch[(int)UE_id][0]->current_harq_pid]->TBS));
eNB->dlsch[(uint8_t)UE_id][0]->nCCE[subframe] = dci_alloc->firstCCE;
......@@ -857,8 +878,12 @@ void generate_eNB_ulsch_params(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,DCI_ALLOC
eNB->ulsch[(uint32_t)UE_id]->harq_processes[harq_pid]->subframe_scheduling_flag = 1;
T(T_ENB_PHY_ULSCH_UE_DCI, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe), T_INT(UE_id),
T_INT(dci_alloc->rnti), T_INT(harq_pid));
T_INT(dci_alloc->rnti), T_INT(harq_pid),
T_INT(eNB->ulsch[(uint32_t)UE_id]->harq_processes[harq_pid]->mcs),
T_INT(eNB->ulsch[(uint32_t)UE_id]->harq_processes[harq_pid]->round),
T_INT(eNB->ulsch[(uint32_t)UE_id]->harq_processes[harq_pid]->first_rb),
T_INT(eNB->ulsch[(uint32_t)UE_id]->harq_processes[harq_pid]->nb_rb),
T_INT(eNB->ulsch[(uint32_t)UE_id]->harq_processes[harq_pid]->TBS));
}
void pdsch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,LTE_eNB_DLSCH_t *dlsch, LTE_eNB_DLSCH_t *dlsch1,LTE_eNB_UE_stats *ue_stats,int ra_flag,int num_pdcch_symbols) {
......@@ -1410,7 +1435,16 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB,
eNB->dlsch_ra->active = 0;
}
#if defined(FLEXRAN_AGENT_SB_IF)
#ifndef DISABLE_SF_TRIGGER
//Send subframe trigger to the controller
if (mac_agent_registered[eNB->Mod_id]) {
agent_mac_xface[eNB->Mod_id]->flexran_agent_send_sf_trigger(eNB->Mod_id);
}
#endif
#endif
// Now scan UE specific DLSCH
for (UE_id=0; UE_id<NUMBER_OF_UE_MAX; UE_id++)
{
......
......@@ -55,6 +55,8 @@ TASK_DEF(TASK_X2AP, TASK_PRIORITY_MED, 200)
TASK_DEF(TASK_SCTP, TASK_PRIORITY_MED, 200)
/// eNB APP task
TASK_DEF(TASK_ENB_APP, TASK_PRIORITY_MED, 200)
/// eNB Agent task
TASK_DEF(TASK_FLEXRAN_AGENT, TASK_PRIORITY_MED, 200)
// UE tasks and sub-tasks:
//// Layer 2 and Layer 1 sub-tasks
......
This diff is collapsed.
/*
* 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 flexran_agent_mac.h
* \brief FlexRAN agent message handler APIs for MAC layer
* \author Xenofon Foukas, Mohamed Kassem and Navid Nikaein
* \date 2016
* \version 0.1
*/
#ifndef FLEXRAN_AGENT_MAC_H_
#define FLEXRAN_AGENT_MAC_H_
#include "header.pb-c.h"
#include "flexran.pb-c.h"
#include "stats_messages.pb-c.h"
#include "stats_common.pb-c.h"
#include "flexran_agent_common.h"
#include "flexran_agent_extern.h"
/* These types will be used to give
instructions for the type of stats reports
we need to create */
typedef struct {
uint16_t ue_rnti;
uint32_t ue_report_flags; /* Indicates the report elements
required for this UE id. See
FlexRAN specification 1.2.4.2 */
} ue_report_type_t;
typedef struct {
uint16_t cc_id;
uint32_t cc_report_flags; /* Indicates the report elements
required for this CC index. See
FlexRAN specification 1.2.4.3 */
} cc_report_type_t;
typedef struct {
int nr_ue;
ue_report_type_t *ue_report_type;
int nr_cc;
cc_report_type_t *cc_report_type;
} report_config_t;
typedef struct stats_request_config_s{
uint8_t report_type;
uint8_t report_frequency;
uint16_t period; /*In number of subframes*/
report_config_t *config;
} stats_request_config_t;
/* Initialization function for the agent structures etc */
void flexran_agent_init_mac_agent(mid_t mod_id);
int flexran_agent_mac_handle_stats(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg);
/* Statistics request protocol message constructor and destructor */
int flexran_agent_mac_stats_request(mid_t mod_id, xid_t xid, const stats_request_config_t *report_config, Protocol__FlexranMessage **msg);
int flexran_agent_mac_destroy_stats_request(Protocol__FlexranMessage *msg);
/* Statistics reply protocol message constructor and destructor */
int flexran_agent_mac_stats_reply(mid_t mod_id, xid_t xid, const report_config_t *report_config, Protocol__FlexranMessage **msg);
int flexran_agent_mac_destroy_stats_reply(Protocol__FlexranMessage *msg);
/* Scheduling request information protocol message constructor and estructor */
int flexran_agent_mac_sr_info(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg);
int flexran_agent_mac_destroy_sr_info(Protocol__FlexranMessage *msg);
/* Subframe trigger protocol msssage constructor and destructor */
int flexran_agent_mac_sf_trigger(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg);
int flexran_agent_mac_destroy_sf_trigger(Protocol__FlexranMessage *msg);
/* DL MAC scheduling decision protocol message constructor (empty command) and destructor */
int flexran_agent_mac_create_empty_dl_config(mid_t mod_id, Protocol__FlexranMessage **msg);
int flexran_agent_mac_destroy_dl_config(Protocol__FlexranMessage *msg);
int flexran_agent_mac_handle_dl_mac_config(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg);
/**********************************
* FlexRAN agent - technology mac API
**********************************/
/*Inform controller about received scheduling requests during a subframe*/
void flexran_agent_send_sr_info(mid_t mod_id);
/*Inform the controller about the current UL/DL subframe*/
void flexran_agent_send_sf_trigger(mid_t mod_id);
/// Send to the controller all the mac stat updates that occured during this subframe
/// based on the stats request configuration
void flexran_agent_send_update_mac_stats(mid_t mod_id);
/// Provide to the scheduler a pending dl_mac_config message
void flexran_agent_get_pending_dl_mac_config(mid_t mod_id, Protocol__FlexranMessage **msg);
/*Register technology specific interface callbacks*/
int flexran_agent_register_mac_xface(mid_t mod_id, AGENT_MAC_xface *xface);
/*Unregister technology specific callbacks*/
int flexran_agent_unregister_mac_xface(mid_t mod_id, AGENT_MAC_xface*xface);
#endif
/*
* 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 flexran_agent_mac_defs.h
* \brief FlexRAN agent - mac interface primitives
* \author Xenofon Foukas
* \date 2016
* \version 0.1
* \mail x.foukas@sms.ed.ac.uk
*/
#ifndef __FLEXRAN_AGENT_MAC_PRIMITIVES_H__
#define __FLEXRAN_AGENT_MAC_PRIMITIVES_H__
#include "flexran_agent_defs.h"
#include "flexran.pb-c.h"
#include "header.pb-c.h"
#define RINGBUFFER_SIZE 100
/* FLEXRAN AGENT-MAC Interface */
typedef struct {
//msg_context_t *agent_ctxt;
/// Inform the controller about the scheduling requests received during the subframe
void (*flexran_agent_send_sr_info)(mid_t mod_id);
/// Inform the controller about the current UL/DL subframe
void (*flexran_agent_send_sf_trigger)(mid_t mod_id);
/// Send to the controller all the mac stat updates that occured during this subframe
/// based on the stats request configuration
void (*flexran_agent_send_update_mac_stats)(mid_t mod_id);
/// Provide to the scheduler a pending dl_mac_config message
void (*flexran_agent_get_pending_dl_mac_config)(mid_t mod_id,
Protocol__FlexranMessage **msg);
/// Run the UE DL scheduler and fill the Protocol__FlexranMessage. Assumes that
/// dl_info is already initialized as flex_dl_mac_config and fills the
/// flex_dl_data part of it
void (*flexran_agent_schedule_ue_spec)(mid_t mod_id, uint32_t frame, uint32_t subframe,
int *mbsfn_flag, Protocol__FlexranMessage **dl_info);
/// Notify the controller for a state change of a particular UE, by sending the proper
/// UE state change message (ACTIVATION, DEACTIVATION, HANDOVER)
void (*flexran_agent_notify_ue_state_change)(mid_t mod_id, uint32_t rnti,
uint32_t state_change);
void *dl_scheduler_loaded_lib;
/*TODO: Fill in with the rest of the MAC layer technology specific callbacks (UL/DL scheduling, RACH info etc)*/
} AGENT_MAC_xface;
#endif
/*
* 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 flexran_agent_mac_internal.h
* \brief Implementation specific definitions for the FlexRAN MAC agent
* \author Xenofon Foukas
* \date 2016
* \version 0.1
*/
#ifndef FLEXRAN_AGENT_MAC_INTERNAL_H_
#define FLEXRAN_AGENT_MAC_INTERNAL_H_
#include <pthread.h>
#include <yaml.h>
#include "flexran_agent_mac.h"
#include "flexran_agent_common.h"
#include "flexran_agent_defs.h"
/*This will be used for producing continuous status updates for the MAC
*Needs to be thread-safe
*/
typedef struct {
/*Flag showing if continuous mac stats update is enabled*/
uint8_t is_initialized;
volatile uint8_t cont_update;
xid_t xid;
Protocol__FlexranMessage *stats_req;
Protocol__FlexranMessage *prev_stats_reply;
pthread_mutex_t *mutex;
} mac_stats_updates_context_t;
/*Array holding the last stats reports for each eNB. Used for continuous reporting*/
mac_stats_updates_context_t mac_stats_context[NUM_MAX_ENB];
/*Functions to initialize and destroy the struct required for the
*continuous stats update report*/
err_code_t flexran_agent_init_cont_mac_stats_update(mid_t mod_id);
err_code_t flexran_agent_destroy_cont_mac_stats_update(mid_t mod_id);
/*Enable/Disable the continuous stats update service for the MAC*/
err_code_t flexran_agent_enable_cont_mac_stats_update(mid_t mod_id, xid_t xid,
stats_request_config_t *stats_req);
err_code_t flexran_agent_disable_cont_mac_stats_update(mid_t mod_id);
Protocol__FlexranMessage * flexran_agent_generate_diff_mac_stats_report(Protocol__FlexranMessage *new_report,
Protocol__FlexranMessage *old_report);
Protocol__FlexUeStatsReport * copy_ue_stats_report(Protocol__FlexUeStatsReport * original);
Protocol__FlexCellStatsReport * copy_cell_stats_report(Protocol__FlexCellStatsReport *original);
Protocol__FlexRlcBsr * copy_rlc_report(Protocol__FlexRlcBsr * original);
Protocol__FlexUlCqiReport * copy_ul_cqi_report(Protocol__FlexUlCqiReport * original);
Protocol__FlexDlCqiReport * copy_dl_cqi_report(Protocol__FlexDlCqiReport * original);
Protocol__FlexPagingBufferReport * copy_paging_buffer_report(Protocol__FlexPagingBufferReport *original);
Protocol__FlexDlCsi * copy_csi_report(Protocol__FlexDlCsi * original);
Protocol__FlexNoiseInterferenceReport * copy_noise_inter_report(Protocol__FlexNoiseInterferenceReport *original);
int compare_ue_stats_reports(Protocol__FlexUeStatsReport *rep1,
Protocol__FlexUeStatsReport *rep2);
int compare_cell_stats_reports(Protocol__FlexCellStatsReport *rep1,
Protocol__FlexCellStatsReport *rep2);
/* Functions for parsing the MAC agent policy reconfiguration command */
int parse_mac_config(mid_t mod_id, yaml_parser_t *parser);
int parse_dl_scheduler_config(mid_t mod_id, yaml_parser_t *parser);
int parse_dl_scheduler_parameters(mid_t mod_id, yaml_parser_t *parser);
int load_dl_scheduler_function(mid_t mod_id, const char *function_name);
#endif /*FLEXRAN_AGENT_MAC_INTERNAL_H_*/
//'syntax = "proto2";'
package protocol;
//
// Cell config related structures and enums
//
message flex_si_config {
optional uint32 sfn = 1;
optional uint32 sib1_length = 2; // The length of SIB1 in bytes
optional uint32 si_window_length = 3; // The scheduling window for all SIs in SF
repeated flex_si_message si_message = 4; // List of SI messages to be sent.
// The index identifies the type of an SI message
// 0 - SIB1
// 1..31 - SIx
// 32..63 - PCCH
}
message flex_si_message {
optional uint32 periodicity = 1; // Periodicity of SI msg in radio frames
optional uint32 length = 2; // The length of the SI message in bytes
}
enum flex_hopping_mode {
FLHM_INTER = 0;
FLHM_INTERINTRA = 1;
}
enum flex_phich_resource {
FLPR_ONE_SIXTH = 0;
FLPR_HALF = 1;
FLPR_ONE = 2;
FLPR_TWO = 3;
}
enum flex_phich_duration {
FLPD_NORMAL = 0;
FLPD_EXTENDED = 1;
}
enum flex_ul_cyclic_prefix_length {
FLUCPL_NORMAL = 0;
FLUCPL_EXTENDED = 1;
}
enum flex_dl_cyclic_prefix_length {
FLDCPL_NORMAL = 0;
FLDCPL_EXTENDED = 1;
}
enum flex_duplex_mode {
FLDM_TDD = 0;
FLDM_FDD = 1;
}
enum flex_qam {
FLEQ_MOD_16QAM = 0;
FLEQ_MOD_64QAM = 1;
}
//
// UE config related structures and enums
//
message flex_drx_config {
optional uint32 on_duration_timer = 1; // Timer in SF. See TS 36.321
optional uint32 drx_inactivity_timer = 2; // Timer in SF. See TS 36.321
optional uint32 drx_retransmission_timer = 3; // Timer in SF. See TS 36.321
optional uint32 long_drx_cycle = 4; // In SF. See TS 36.321
optional uint32 long_drx_cycle_start_offset = 5;// See TS 36.321
optional uint32 short_drx_cycle = 6; // In SF
optional uint32 drx_short_cycle_timer = 7; // Timer in subframes. See TS 36.321
}
message flex_sps_config {
optional uint32 semi_persistent_sched_interval_UL = 1; // SPS UL scheduling interval in SF
optional uint32 semi_persistent_sched_interval_DL = 2; // SPS DL scheduling interval in SF
optional uint32 num_of_conf_sps_proc = 3; // Number of SPS HARQ processes. See TS 36.321
repeated uint32 n1_PUCCH_AN_persistent_element = 4;// See TS36.213. Ignored when config is used
// as part of FLPT_SET_UE_CONFIG
optional uint32 implicit_release_after = 5; // number of empty transmissions before release of SPS
}
message flex_sr_config {
optional uint32 sr_action = 1; // Indicates if SR config should be changed or released
// One of the FLSRA_* enum values
optional uint32 sched_interval = 2; // SR scheduling interval in SF
optional uint32 dsr_trans_max = 3; // See TS 36.213
}
message flex_cqi_config {
optional uint32 cqi_action = 1; // Indicats if CQI changed or released.
// One of the FLSRA_* enum values
optional uint32 cqi_sched_interval = 2; // CQI scheduling interval in SF
optional uint32 ri_sched_interval = 3; // RI scheduling interval in SF
}
message flex_ue_capabilities {
optional uint32 half_duplex = 1; // Boolean value. Only half duplex support. FDD operation
optional uint32 intra_SF_hopping = 2; // Support for intra-subframe hopping. Boolean value
optional uint32 type2_sb_1 = 3; // Support for type 2 hopping with n_sb > 1
optional uint32 ue_category = 4;
optional uint32 res_alloc_type1 = 5; // Boolean value. UE support for resource allocation type 1
}
message flex_scell_config {
optional uint32 carrier_index = 1; // Id of the carrier component
optional uint32 scell_index = 2; // Index of this Scell (RRC SCellIndex)
optional uint32 use_ccs = 3; // Boolean value. Indicates if cross-carrier scheduling
// is used by this SCell
optional uint32 sched_cell_index = 4; // Index of the cell responsible for scheduling
// this SCell if cross-carrier scheduling is enabled
optional uint32 pdsch_start = 5; // Starting OFDM symbol of PDSCH data region for this SCell
}
enum flex_meas_gap_config_pattern {
FLMGCP_GP1 = 0;
FLMGCP_GP2 = 1;
FLMGCP_OFF = 2;
}
enum flex_setup_release_action {
FLSRA_SETUP = 0;
FLSRA_RELEASE = 1;
}
enum flex_ue_transmission_antenna {
FLUTA_NONE = 0;
FLUTA_OPEN_LOOP = 1;
FLUTA_CLOSED_LOOP = 2;
}
enum flex_aperiodic_cqi_report_mode {
FLACRM_RM12 = 0;
FLACRM_RM20 = 1;
FLACRM_RM22 = 2;
FLACRM_RM30 = 3;
FLACRM_RM31 = 4;
FLACRM_NONE = 5;
}
enum flex_tdd_ack_nack_feedback_mode {
FLTANFM_BUNDLING = 0;
FLTANFM_MULTIPLEXING = 1;
}
//
// Logical channel config related structures and enums
//
message flex_lc_config {
optional uint32 lcid = 1; // The logical channel id
optional uint32 lcg = 2; // The logical channel group (0..3) the LC is mapped to
optional uint32 direction = 3; // The LC direction. One of the FLLCD_* enum values
optional uint32 qos_bearer_type = 4;// GBR or NGBR bearer. One of the FLQBT_* enum values
optional uint32 qci = 5; // The QCI defined in TS 23.203, coded as defined in TS 36.413
// One less than the actual QCI value
optional uint64 e_RAB_max_bitrate_UL = 6; // In bps (GBR only)
optional uint64 e_RAB_max_bitrate_DL = 7; // In bps (GBR only)
optional uint64 e_RAB_guaranteed_bitrate_UL = 8; // In bps (GBR only)
optional uint64 e_RAB_guaranteed_bitrate_DL = 9; // In bps (GBR only)
}
enum flex_lc_direction {
FLLCD_UL = 0;
FLLCD_DL = 1;
FLLCD_BOTH = 2;
}
enum flex_qos_bearer_type {
FLQBT_NON_GBR = 0;
FLQBT_GBR = 1;
}
enum flex_ue_state_change_type {
FLUESC_UPDATED = 0;
FLUESC_ACTIVATED = 1;
FLUESC_DEACTIVATED = 2;
FLUESC_MOVED = 3;
}
\ No newline at end of file
This diff is collapsed.
//'syntax = "proto2";'
package protocol;
enum flex_control_delegation_type {
FLCDT_MAC_DL_UE_SCHEDULER = 1; // DL UE scheduler delegation
}
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
package protocol;
message flex_header {
optional uint32 version = 1;
optional uint32 type = 2;
optional uint32 xid = 4;
}
enum flex_type {
// Discovery and maintenance messages
FLPT_HELLO = 0;
FLPT_ECHO_REQUEST = 1;
FLPT_ECHO_REPLY = 2;
// Statistics and measurement messages
FLPT_STATS_REQUEST = 3;
FLPT_STATS_REPLY = 4;
// Time indication messages
FLPT_SF_TRIGGER = 5;
// Asynchronous messages
FLPT_UL_SR_INFO = 6;
// eNB configuration messages
FLPT_GET_ENB_CONFIG_REQUEST = 7;
FLPT_GET_ENB_CONFIG_REPLY = 8;
FLPT_GET_UE_CONFIG_REQUEST = 9;
FLPT_GET_UE_CONFIG_REPLY = 10;
FLPT_GET_LC_CONFIG_REQUEST = 11;
FLPT_GET_LC_CONFIG_REPLY = 12;
//Controller command messages
FLPT_DL_MAC_CONFIG = 13;
// UE state change messages
FLPT_UE_STATE_CHANGE = 14;
// Control delegation messages
FLPT_DELEGATE_CONTROL = 15;
FLPT_RECONFIGURE_AGENT = 16;
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -228,6 +228,10 @@ typedef struct Enb_properties_s {
char *enb_interface_name_for_S1_MME;
in_addr_t enb_ipv4_address_for_S1_MME;
char *flexran_agent_interface_name;
in_addr_t flexran_agent_ipv4_address;
tcp_udp_port_t flexran_agent_port;
char *flexran_agent_cache;
/* Nb of RRH to connect to */
uint8_t nb_rrh_gw;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment