Merge remote-tracking branch 'origin/develop' into Enhancement-142-OAI_UE_autotest_framework

This commit is contained in:
ROBERT Benoit
2016-12-09 16:06:17 +01:00
284 changed files with 38247 additions and 349 deletions
+140 -10
View File
@@ -622,7 +622,7 @@ add_boolean_option(MESSAGE_CHART_GENERATOR False "For generating sequenc
add_boolean_option(MESSAGE_CHART_GENERATOR_RLC_MAC False "trace RLC-MAC exchanges in sequence diagrams")
add_boolean_option(MESSAGE_CHART_GENERATOR_PHY False "trace some PHY exchanges in sequence diagrams")
add_boolean_option(ENB_AGENT True "enable eNB agent to inteface with a SDN contrller")
add_boolean_option(FLEXRAN_AGENT_SB_IF False "enable FlexRAN agent to inteface with a SDN controller")
########################
# Include order
@@ -818,8 +818,10 @@ include_directories("${OPENAIR_DIR}/targets/ARCH/COMMON")
include_directories("${OPENAIR_DIR}/targets/ARCH/EXMIMO/USERSPACE/LIB/")
include_directories("${OPENAIR_DIR}/targets/ARCH/EXMIMO/DEFS")
include_directories("${OPENAIR2_DIR}/ENB_APP")
include_directories("${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/MAC")
include_directories("${OPENAIR2_DIR}/UTIL/OSA")
include_directories("${OPENAIR2_DIR}/UTIL/LFDS/liblfds6.1.1/liblfds611/inc")
include_directories("${OPENAIR2_DIR}/UTIL/LFDS/liblfds7.0.0/liblfds700/inc")
include_directories("${OPENAIR2_DIR}/UTIL/MEM")
include_directories("${OPENAIR2_DIR}/UTIL/LISTS")
include_directories("${OPENAIR2_DIR}/UTIL/FIFO")
@@ -838,6 +840,94 @@ include_directories("${OPENAIR_DIR}")
# Utilities Library
################
if (FLEXRAN_AGENT_SB_IF)
# set the version of protobuf messages, V3 not supported yet
add_list1_option(FLPT_VERSION V2 "FLPT MSG protobuf grammar version" V2 V3)
if (${FLPT_VERSION} STREQUAL "V2")
set (FLPTDIR V2)
elseif (${FLPT_VERSION} STREQUAL "V3")
set (FLPTDIR V3)
endif(${FLPT_VERSION} STREQUAL "V2")
set(FLPT_MSG_DIR ${OPENAIR2_DIR}/ENB_APP/MESSAGES/${FLPTDIR} )
set(FLPT_MSG_FILES
${FLPT_MSG_DIR}/header.proto
${FLPT_MSG_DIR}/flexran.proto
${FLPT_MSG_DIR}/stats_common.proto
${FLPT_MSG_DIR}/stats_messages.proto
${FLPT_MSG_DIR}/time_common.proto
${FLPT_MSG_DIR}/controller_commands.proto
${FLPT_MSG_DIR}/mac_primitives.proto
${FLPT_MSG_DIR}/config_messages.proto
${FLPT_MSG_DIR}/config_common.proto
${FLPT_MSG_DIR}/control_delegation.proto
)
set(FLPT_C_DIR ${protobuf_generated_dir}/${FLPTDIR})
#message("calling protoc_call=${protoc_call} FLPT_C_DIR=${FLPT_C_DIR} FLPT_MSG_FILES=${FLPT_MSG_FILES}")
execute_process(COMMAND ${protoc_call} ${FLPT_C_DIR} ${FLPT_MSG_DIR} ${FLPT_MSG_FILES})
file(GLOB FLPT_source ${FLPT_C_DIR}/*.c)
set(FLPT_OAI_generated
${FLPT_C_DIR}/header.pb-c.c
${FLPT_C_DIR}/flexran.pb-c.c
${FLPT_C_DIR}/stats_common.pb-c.c
${FLPT_C_DIR}/stats_messages.pb-c.c
${FLPT_C_DIR}/time_common.pb-c.c
${FLPT_C_DIR}/controller_commands.pb-c.c
${FLPT_C_DIR}/mac_primitives.pb-c.c
${FLPT_C_DIR}/config_messages.pb-c.c
${FLPT_C_DIR}/config_common.pb-c.c
${FLPT_C_DIR}/control_delegation.pb-c.c
)
file(GLOB flpt_h ${FLPT_C_DIR}/*.h)
set(flpt_h ${flpt_h} )
add_library(FLPT_MSG
${FLPT_OAI_generated}
${FLPT_source}
)
set(FLPT_MSG_LIB FLPT_MSG)
#message("prpt c dir is : ${FLPT_C_DIR}")
include_directories (${FLPT_C_DIR})
add_library(ASYNC_IF
${OPENAIR2_DIR}/UTIL/ASYNC_IF/socket_link.c
${OPENAIR2_DIR}/UTIL/ASYNC_IF/link_manager.c
${OPENAIR2_DIR}/UTIL/ASYNC_IF/message_queue.c
${OPENAIR2_DIR}/UTIL/ASYNC_IF/ringbuffer_queue.c
)
set(ASYNC_IF_LIB ASYNC_IF)
include_directories(${OPENAIR2_DIR}/UTIL/ASYNC_IF)
add_library(FLEXRAN_AGENT
${OPENAIR2_DIR}/ENB_APP/flexran_agent_handler.c
${OPENAIR2_DIR}/ENB_APP/flexran_agent_common.c
${OPENAIR2_DIR}/ENB_APP/flexran_agent_common_internal.c
${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c
${OPENAIR2_DIR}/ENB_APP/flexran_agent.c
${OPENAIR2_DIR}/ENB_APP/flexran_agent_task_manager.c
${OPENAIR2_DIR}/ENB_APP/flexran_agent_net_comm.c
${OPENAIR2_DIR}/ENB_APP/flexran_agent_async.c
${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c
)
set(FLEXRAN_AGENT_LIB FLEXRAN_AGENT)
#include_directories(${OPENAIR2_DIR}/ENB_APP)
set(PROTOBUF_LIB "protobuf-c")
FIND_PATH(LIBYAML_INCLUDE_DIR NAMES yaml.h)
FIND_LIBRARY(LIBYAML_LIBRARIES NAMES yaml libyaml)
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(Yaml DEFAULT_MSG LIBYAML_LIBRARIES LIBYAML_INCLUDE_DIR)
MARK_AS_ADVANCED(LIBYAML_INCLUDE_DIR LIBYAML_LIBRARIES)
#set(PROTOBUF_LIB "protobuf") #for Cpp
endif()
add_library(HASHTABLE
${OPENAIR_DIR}/common/utils/hashtable/hashtable.c
${OPENAIR_DIR}/common/utils/hashtable/obj_hashtable.c
@@ -1096,7 +1186,17 @@ set (MAC_SRC
${MAC_DIR}/eNB_scheduler_RA.c
${MAC_DIR}/pre_processor.c
${MAC_DIR}/config.c
)
)
if (FLEXRAN_AGENT_SB_IF)
set (MAC_SRC ${MAC_SRC}
${MAC_DIR}/flexran_agent_scheduler_dlsch_ue.c
${MAC_DIR}/flexran_agent_scheduler_dataplane.c
${MAC_DIR}/flexran_agent_scheduler_dlsch_ue_remote.c
)
endif()
set (ENB_APP_SRC
${OPENAIR2_DIR}/ENB_APP/enb_app.c
@@ -1109,6 +1209,14 @@ add_library(L2
${ENB_APP_SRC})
# ${OPENAIR2_DIR}/RRC/L2_INTERFACE/openair_rrc_L2_interface.c)
if (FLEXRAN_AGENT_SB_IF)
#Test for adding a shared library
add_library(default_sched SHARED ${MAC_DIR}/flexran_agent_scheduler_dlsch_ue.c)
add_library(remote_sched SHARED ${MAC_DIR}/flexran_agent_scheduler_dlsch_ue_remote.c)
endif()
# L3 Libs
##########################
@@ -1469,6 +1577,23 @@ add_library(LFDS
${lfds}/lfds611_abstraction/lfds611_abstraction_malloc.c
)
set(lfds7 ${OPENAIR2_DIR}/UTIL/LFDS/liblfds7.0.0/liblfds700/src/)
file(GLOB lfds7_queue ${lfds7}/lfds700_queue/*.c)
file(GLOB lfds7_ring ${lfds7}/lfds700_ringbuffer/*.c)
file(GLOB lfds7_qbss ${lfds7}/lfds700_queue_bounded_singleconsumer_singleproducer/*.c)
file(GLOB lfds7_stack ${lfds7}/lfds700_stack/*.c)
file(GLOB lfds7_freelist ${lfds7}/lfds700_freelist/*.c)
file(GLOB lfds7_btree ${lfds7}/lfds700_btree_addonly_unbalanced/*.c)
file(GLOB lfds7_hash ${lfds7}/lfds700_hash_addonly/*.c)
file(GLOB lfds7_ordered_list ${lfds7}/lfds700_list_addonly_ordered_singlylinked/*.c)
file(GLOB lfds7_unordered_list ${lfds7}/lfds700_list_addonly_singlylinked_unordered/*.c)
file(GLOB lfds7_misc ${lfds7}/lfds700_misc/*.c)
include_directories(${lfds7})
add_library(LFDS7
${lfds7_queue} ${lfds7_ring} ${lfds7_qbss} ${lfds7_stack} ${lfds7_freelist} ${lfds7_btree} ${lfds7_hash} ${lfds7_ordered_list} ${lfds7_unordered_list} ${lfds7_misc}
)
# Simulation library
##########################
add_library(SIMU
@@ -1645,11 +1770,11 @@ add_executable(lte-softmodem
target_link_libraries (lte-softmodem -ldl
-Wl,--start-group
RRC_LIB S1AP_LIB S1AP_ENB GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB PHY LFDS L2 ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${MIH_LIB}
RRC_LIB S1AP_LIB S1AP_ENB GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB PHY LFDS L2 ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${MIH_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${FLEXRAN_AGENT_LIB} LFDS7
-Wl,--end-group )
target_link_libraries (lte-softmodem ${LIBXML2_LIBRARIES})
target_link_libraries (lte-softmodem pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} sctp ${option_HW_lib} ${option_TP_lib} ${XFORMS_LIBRARIES} )
target_link_libraries (lte-softmodem pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} sctp ${option_HW_lib} ${option_TP_lib} ${XFORMS_LIBRARIES} ${PROTOBUF_LIB} ${CMAKE_DL_LIBS} ${LIBYAML_LIBRARIES})
target_link_libraries (lte-softmodem ${LIB_LMS_LIBRARIES})
target_link_libraries (lte-softmodem ${T_LIB})
@@ -1679,11 +1804,11 @@ add_executable(lte-softmodem-nos1
)
target_link_libraries (lte-softmodem-nos1
-Wl,--start-group
RRC_LIB SECU_CN SECU_OSA UTIL HASHTABLE SCHED_LIB PHY LFDS L2 ${MSC_LIB} ${RAL_LIB} ${ITTI_LIB} ${MIH_LIB}
RRC_LIB SECU_CN SECU_OSA UTIL HASHTABLE SCHED_LIB PHY LFDS L2 ${MSC_LIB} ${RAL_LIB} ${ITTI_LIB} ${MIH_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${FLEXRAN_AGENT_LIB} LFDS7
-Wl,--end-group )
target_link_libraries (lte-softmodem-nos1 ${LIBXML2_LIBRARIES})
target_link_libraries (lte-softmodem-nos1 pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} ${option_HW_lib} ${option_TP_lib} ${XFORMS_LIBRARIES} )
target_link_libraries (lte-softmodem-nos1 pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} ${option_HW_lib} ${option_TP_lib} ${XFORMS_LIBRARIES} ${PROTOBUF_LIB} ${CMAKE_DL_LIBS} ${LIBYAML_LIBRARIES})
target_link_libraries (lte-softmodem-nos1 ${LIB_LMS_LIBRARIES})
target_link_libraries (lte-softmodem-nos1 ${T_LIB})
@@ -1824,16 +1949,20 @@ add_executable(oaisim_nos1
target_include_directories(oaisim_nos1 PUBLIC ${OPENAIR_TARGETS}/SIMU/USER)
target_link_libraries (oaisim_nos1
-Wl,--start-group
RRC_LIB X2AP_LIB SECU_CN UTIL HASHTABLE SCHED_LIB PHY LFDS ${MSC_LIB} L2 ${RAL_LIB} SIMU SIMU_ETH SECU_OSA ${ITTI_LIB} ${MIH_LIB}
RRC_LIB X2AP_LIB SECU_CN UTIL HASHTABLE SCHED_LIB PHY LFDS ${MSC_LIB} L2 ${RAL_LIB} SIMU SIMU_ETH SECU_OSA ${ITTI_LIB} ${MIH_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${FLEXRAN_AGENT_LIB} LFDS7
-Wl,--end-group )
target_link_libraries (oaisim_nos1 ${LIBXML2_LIBRARIES} ${LAPACK_LIBRARIES})
target_link_libraries (oaisim_nos1 pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} ${option_HW_lib} ${option_TP_lib}
${ATLAS_LIBRARIES} ${XFORMS_LIBRARIES} ${OPENPGM_LIBRARIES})
target_link_libraries (oaisim_nos1 pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} ${option_HW_lib} ${option_TP_lib}
${ATLAS_LIBRARIES} ${XFORMS_LIBRARIES} ${OPENPGM_LIBRARIES} ${PROTOBUF_LIB} ${CMAKE_DL_LIBS} ${LIBYAML_LIBRARIES})
#Force link with forms, regardless XFORMS option
target_link_libraries (oaisim_nos1 forms)
#message("protobuflib is ${PROTOBUF_LIB}")
target_link_libraries (oaisim_nos1 ${T_LIB})
# Unitary tests for each piece of L1: example, mbmssim is MBMS L1 simulator
#####################################
@@ -1845,7 +1974,8 @@ foreach(myExe dlsim ulsim pbchsim scansim mbmssim pdcchsim pucchsim prachsim syn
${T_SOURCE}
)
target_link_libraries (${myExe}
-Wl,--start-group SIMU UTIL SCHED_LIB PHY LFDS ${ITTI_LIB} -Wl,--end-group
-Wl,--start-group SIMU UTIL SCHED_LIB PHY LFDS ${ITTI_LIB} LFDS7 -Wl,--end-group
pthread m rt ${CONFIG_LIBRARIES} ${ATLAS_LIBRARIES} ${XFORMS_LIBRARIES} ${T_LIB}
)
endforeach(myExe)
+9
View File
@@ -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
@@ -608,7 +608,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
@@ -639,7 +639,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='')
@@ -655,6 +655,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='')
@@ -671,6 +672,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='')
@@ -689,6 +691,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'
@@ -745,7 +749,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)
@@ -765,7 +769,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 != "":
@@ -805,7 +810,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 != "":
@@ -855,8 +861,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'
@@ -906,7 +911,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 != "":
@@ -2495,7 +2500,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..."
File diff suppressed because it is too large Load Diff
+16
View File
@@ -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"
@@ -84,6 +85,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
@@ -172,6 +175,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"
@@ -446,6 +453,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
@@ -589,6 +599,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
@@ -657,6 +670,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
@@ -48,7 +48,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 )
+44
View File
@@ -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
}
+19
View File
@@ -0,0 +1,19 @@
#!/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 "$@"
+21
View File
@@ -0,0 +1,21 @@
#!/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
+2 -2
View File
@@ -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
+206 -54
View File
@@ -24,6 +24,30 @@ typedef struct {
view *pdcpview;
view *rrcview;
view *legacy;
widget *current_ue_label;
widget *prev_ue_button;
widget *next_ue_button;
widget *pusch_iq_ue_xy_plot;
widget *ul_estimate_ue_xy_plot;
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;
logger *pucch1_energy_ue_energy_logger;
logger *pucch_iq_ue_logger;
logger *dl_dci_logger[8];
logger *dl_ack_logger[8];
logger *dl_nack_logger[8];
logger *ul_dci_logger[8];
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 {
@@ -31,6 +55,9 @@ typedef struct {
int *is_on;
int nevents;
pthread_mutex_t lock;
enb_gui *e;
int ue; /* what UE is displayed in the UE specific views */
void *database;
} enb_data;
void is_on_changed(void *_d)
@@ -86,18 +113,109 @@ static void *gui_thread(void *_g)
return NULL;
}
static filter *ticktime_filter(void *database, char *event, int i)
static filter *ticktime_filter(void *database, char *event, int i, int ue)
{
/* filter is "harq_pid == i && UE_id == 0 && eNB_id == 0" */
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(0)),
filter_eq(filter_evarg(database, event, "UE_id"), filter_int(ue)),
filter_eq(filter_evarg(database, event, "eNB_ID"), filter_int(0))));
}
static void enb_main_gui(enb_gui *e, gui *g, event_handler *h, void *database)
static void set_current_ue(gui *g, enb_data *e, int ue)
{
int i;
char s[256];
sprintf(s, "[UE %d] ", ue);
label_set_text(g, e->e->current_ue_label, s);
sprintf(s, "PUSCH IQ [UE %d]", ue);
xy_plot_set_title(g, e->e->pusch_iq_ue_xy_plot, s);
sprintf(s, "UL estimated channel [UE %d]", ue);
xy_plot_set_title(g, e->e->ul_estimate_ue_xy_plot, s);
sprintf(s, "PUCCH1 energy (SR) [UE %d]", ue);
xy_plot_set_title(g, e->e->pucch1_energy_ue_xy_plot, s);
sprintf(s, "PUCCH IQ [UE %d]", 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(
filter_evarg(e->database, "ENB_PHY_PUSCH_IQ", "UE_ID"),
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_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_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_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_int(ue)));
for (i = 0; i < 8; i++) {
logger_set_filter(e->e->dl_dci_logger[i],
ticktime_filter(e->database, "ENB_PHY_DLSCH_UE_DCI", i, ue));
logger_set_filter(e->e->dl_ack_logger[i],
ticktime_filter(e->database, "ENB_PHY_DLSCH_UE_ACK", i, ue));
logger_set_filter(e->e->dl_nack_logger[i],
ticktime_filter(e->database, "ENB_PHY_DLSCH_UE_NACK", i, ue));
logger_set_filter(e->e->ul_dci_logger[i],
ticktime_filter(e->database, "ENB_PHY_ULSCH_UE_DCI", i, ue));
logger_set_filter(e->e->ul_dci_retransmission_logger[i],
ticktime_filter(e->database,
"ENB_PHY_ULSCH_UE_NO_DCI_RETRANSMISSION", i, ue));
logger_set_filter(e->e->ul_ack_logger[i],
ticktime_filter(e->database, "ENB_PHY_ULSCH_UE_ACK", i, 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,
char *notification, widget *w, void *notification_data)
{
int *d = notification_data;
int button = d[0];
enb_data *ed = private;
enb_gui *e = ed->e;
int ue = ed->ue;
if (button != 1) return;
if (w == e->prev_ue_button) { ue--; if (ue < 0) ue = 0; }
if (w == e->next_ue_button) 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,
enb_data *ed)
{
widget *main_window;
widget *top_container;
@@ -113,7 +231,7 @@ static void enb_main_gui(enb_gui *e, gui *g, event_handler *h, void *database)
widget *text;
view *textview;
int i;
widget *w;
widget *w, *w2;
view *v;
logger *l;
@@ -124,7 +242,26 @@ static void enb_main_gui(enb_gui *e, gui *g, event_handler *h, void *database)
line = new_container(g, HORIZONTAL);
widget_add_child(g, top_container, line, -1);
logo = new_image(g, openair_logo_png, openair_logo_png_len);
widget_add_child(g, line, logo, -1);
/* logo + prev/next UE buttons */
col = new_container(g, VERTICAL);
widget_add_child(g, col, logo, -1);
w = new_container(g, HORIZONTAL);
widget_add_child(g, col, w, -1);
w2 = new_label(g, "");
widget_add_child(g, w, w2, -1);
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);
e->prev_ue_button = w2;
w2 = new_label(g, " [next UE] ");
widget_add_child(g, w, w2, -1);
label_set_clickable(g, w2, 1);
e->next_ue_button = w2;
widget_add_child(g, line, col, -1);
input_signal_plot = new_xy_plot(g, 256, 55, "input signal", 20);
widget_add_child(g, line, input_signal_plot, -1);
xy_plot_set_range(g, input_signal_plot, 0, 7680*10, 20, 70);
@@ -138,21 +275,20 @@ static void enb_main_gui(enb_gui *e, gui *g, event_handler *h, void *database)
g, input_signal_plot, new_color(g, "#0c0c72"), XY_LOOP_MODE);
logger_add_view(input_signal_log, input_signal_view);
/* UE 0 PUSCH IQ data */
w = new_xy_plot(g, 55, 55, "PUSCH IQ [UE 0]", 50);
/* UE x PUSCH IQ data */
w = new_xy_plot(g, 55, 55, "", 50);
e->pusch_iq_ue_xy_plot = w;
widget_add_child(g, line, w, -1);
xy_plot_set_range(g, w, -1000, 1000, -1000, 1000);
l = new_iqlog(h, database, "ENB_PHY_PUSCH_IQ", "nb_rb",
"N_RB_UL", "symbols_per_tti", "pusch_comp");
v = new_view_xy(100*12*14,10,g,w,new_color(g,"#000"),XY_FORCED_MODE);
logger_add_view(l, v);
logger_set_filter(l,
filter_eq(
filter_evarg(database, "ENB_PHY_PUSCH_IQ", "UE_ID"),
filter_int(0)));
e->pusch_iq_ue_logger = l;
/* UE 0 estimated UL channel */
w = new_xy_plot(g, 280, 55, "UL estimated channel [UE 0]", 50);
/* UE x estimated UL channel */
w = new_xy_plot(g, 280, 55, "", 50);
e->ul_estimate_ue_xy_plot = w;
widget_add_child(g, line, w, -1);
xy_plot_set_range(g, w, 0, 512*10, -10, 80);
l = new_framelog(h, database,
@@ -161,43 +297,57 @@ static void enb_main_gui(enb_gui *e, gui *g, event_handler *h, void *database)
framelog_set_update_only_at_sf9(l, 0);
v = new_view_xy(512*10, 10, g, w, new_color(g, "#0c0c72"), XY_LOOP_MODE);
logger_add_view(l, v);
logger_set_filter(l,
filter_eq(
filter_evarg(database, "ENB_PHY_UL_CHANNEL_ESTIMATE", "UE_ID"),
filter_int(0)));
e->ul_estimate_ue_logger = l;
/* UE 0 PUCCH energy */
w = new_xy_plot(g, 128, 55, "PUCCH1 energy (SR) [UE 0]", 50);
/* UE x PUCCH energy */
w = new_xy_plot(g, 128, 55, "", 50);
e->pucch1_energy_ue_xy_plot = w;
widget_add_child(g, line, w, -1);
xy_plot_set_range(g, w, 0, 1024*10, -10, 80);
l = new_ttilog(h, database,
"ENB_PHY_PUCCH_1_ENERGY", "frame", "subframe", "threshold", 0);
v = new_view_tti(10, g, w, new_color(g, "#ff0000"));
logger_add_view(l, v);
logger_set_filter(l,
filter_eq(
filter_evarg(database, "ENB_PHY_PUCCH_1_ENERGY", "UE_ID"),
filter_int(0)));
e->pucch1_energy_ue_threshold_logger = l;
l = new_ttilog(h, database,
"ENB_PHY_PUCCH_1_ENERGY", "frame", "subframe", "energy", 1);
v = new_view_tti(10, g, w, new_color(g, "#0c0c72"));
logger_add_view(l, v);
logger_set_filter(l,
filter_eq(
filter_evarg(database, "ENB_PHY_PUCCH_1_ENERGY", "UE_ID"),
filter_int(0)));
e->pucch1_energy_ue_energy_logger = l;
/* UE 0 PUCCH IQ data */
w = new_xy_plot(g, 55, 55, "PUCCH IQ [UE 0]", 50);
/* UE x PUCCH IQ data */
w = new_xy_plot(g, 55, 55, "", 50);
e->pucch_iq_ue_xy_plot = w;
widget_add_child(g, line, w, -1);
xy_plot_set_range(g, w, -100, 100, -100, 100);
xy_plot_set_range(g, w, -2000, 2000, -2000, 2000);
l = new_iqdotlog(h, database, "ENB_PHY_PUCCH_1AB_IQ", "I", "Q");
v = new_view_xy(500, 10, g, w, new_color(g,"#000"), XY_LOOP_MODE);
logger_add_view(l, v);
logger_set_filter(l,
filter_eq(
filter_evarg(database, "ENB_PHY_PUCCH_1AB_IQ", "UE_ID"),
filter_int(0)));
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,
@@ -250,8 +400,8 @@ static void enb_main_gui(enb_gui *e, gui *g, event_handler *h, void *database)
logger_add_view(timelog, subview);
/* harq processes' ticktime view */
widget_add_child(g, top_container,
new_label(g,"DL/UL HARQ (x8) [UE 0]"), -1);
e->dl_ul_harq_ue_label = new_label(g, "");
widget_add_child(g, top_container, e->dl_ul_harq_ue_label, -1);
line = new_container(g, HORIZONTAL);
widget_add_child(g, top_container, line, -1);
timeline_plot = new_timeline(g, 512, 2*8+2, 3);
@@ -271,15 +421,14 @@ static void enb_main_gui(enb_gui *e, gui *g, event_handler *h, void *database)
/* tick on UL view */
subview = new_subview_ticktime(timeview, 9, new_color(g,"#bbb"), 3600*1000);
logger_add_view(timelog, subview);
/* DL harq pids */
/* DL DCI */
for (i = 0; i < 8; i++) {
timelog = new_ticklog(h, database, "ENB_PHY_DLSCH_UE_DCI",
"frame", "subframe");
subview = new_subview_ticktime(timeview, i+1,
new_color(g,"#55f"), 3600*1000);
logger_add_view(timelog, subview);
logger_set_filter(timelog,
ticktime_filter(database, "ENB_PHY_DLSCH_UE_DCI", i));
e->dl_dci_logger[i] = timelog;
}
/* DL ACK */
for (i = 0; i < 8; i++) {
@@ -288,8 +437,7 @@ static void enb_main_gui(enb_gui *e, gui *g, event_handler *h, void *database)
subview = new_subview_ticktime(timeview, i+1,
new_color(g,"#282"), 3600*1000);
logger_add_view(timelog, subview);
logger_set_filter(timelog,
ticktime_filter(database, "ENB_PHY_DLSCH_UE_ACK", i));
e->dl_ack_logger[i] = timelog;
}
/* DL NACK */
for (i = 0; i < 8; i++) {
@@ -298,10 +446,9 @@ static void enb_main_gui(enb_gui *e, gui *g, event_handler *h, void *database)
subview = new_subview_ticktime(timeview, i+1,
new_color(g,"#f22"), 3600*1000);
logger_add_view(timelog, subview);
logger_set_filter(timelog,
ticktime_filter(database, "ENB_PHY_DLSCH_UE_NACK", i));
e->dl_nack_logger[i] = timelog;
}
/* UL harq pids */
/* UL DCI/retransmission without DCI */
for (i = 0; i < 8; i++) {
/* first transmission */
timelog = new_ticklog(h, database, "ENB_PHY_ULSCH_UE_DCI",
@@ -309,17 +456,14 @@ static void enb_main_gui(enb_gui *e, gui *g, event_handler *h, void *database)
subview = new_subview_ticktime(timeview, i+9+1,
new_color(g,"#55f"), 3600*1000);
logger_add_view(timelog, subview);
logger_set_filter(timelog,
ticktime_filter(database, "ENB_PHY_ULSCH_UE_DCI", i));
e->ul_dci_logger[i] = timelog;
/* retransmission */
timelog = new_ticklog(h, database,
"ENB_PHY_ULSCH_UE_NO_DCI_RETRANSMISSION", "frame", "subframe");
subview = new_subview_ticktime(timeview, i+9+1,
new_color(g,"#99f"), 3600*1000);
logger_add_view(timelog, subview);
logger_set_filter(timelog,
ticktime_filter(database,
"ENB_PHY_ULSCH_UE_NO_DCI_RETRANSMISSION", i));
e->ul_dci_retransmission_logger[i] = timelog;
}
/* UL ACK */
for (i = 0; i < 8; i++) {
@@ -328,8 +472,7 @@ static void enb_main_gui(enb_gui *e, gui *g, event_handler *h, void *database)
subview = new_subview_ticktime(timeview, i+9+1,
new_color(g,"#282"), 3600*1000);
logger_add_view(timelog, subview);
logger_set_filter(timelog,
ticktime_filter(database, "ENB_PHY_ULSCH_UE_ACK", i));
e->ul_ack_logger[i] = timelog;
}
/* UL NACK */
for (i = 0; i < 8; i++) {
@@ -338,8 +481,7 @@ static void enb_main_gui(enb_gui *e, gui *g, event_handler *h, void *database)
subview = new_subview_ticktime(timeview, i+9+1,
new_color(g,"#f22"), 3600*1000);
logger_add_view(timelog, subview);
logger_set_filter(timelog,
ticktime_filter(database, "ENB_PHY_ULSCH_UE_NACK", i));
e->ul_nack_logger[i] = timelog;
}
/* phy/mac/rlc/pdcp/rrc textlog */
@@ -416,6 +558,10 @@ static void enb_main_gui(enb_gui *e, gui *g, event_handler *h, void *database)
widget_add_child(g, top_container, text, -1);
container_set_child_growable(g, top_container, text, 1);
e->legacy = new_view_textlist(10000, 10, g, text);
set_current_ue(g, ed, 0);
register_notifier(g, "click", e->prev_ue_button, click, ed);
register_notifier(g, "click", e->next_ue_button, click, ed);
}
void view_add_log(view *v, char *log, event_handler *h, void *database,
@@ -495,7 +641,11 @@ int main(int n, char **v)
g = gui_init();
new_thread(gui_thread, g);
enb_main_gui(&eg, g, h, database);
enb_data.ue = 0;
enb_data.e = &eg;
enb_data.database = database;
enb_main_gui(&eg, g, h, database, &enb_data);
for (i = 0; i < number_of_events; i++) {
logger *textlog;
@@ -639,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;
+30 -1
View File
@@ -13,6 +13,7 @@ struct filter {
} v;
int (*eval)(struct filter *this, event e);
void (*free)(struct filter *this);
};
/****************************************************************************/
@@ -52,7 +53,23 @@ int eval_evarg(struct filter *f, event e)
}
/****************************************************************************/
/* filter construction functions */
/* free memory functions */
/****************************************************************************/
void free_op2(struct filter *f)
{
free_filter(f->v.op2.a);
free_filter(f->v.op2.b);
free(f);
}
void free_noop(struct filter *f)
{
free(f);
}
/****************************************************************************/
/* filter construction/destruction functions */
/****************************************************************************/
filter *filter_and(filter *a, filter *b)
@@ -60,6 +77,7 @@ filter *filter_and(filter *a, filter *b)
struct filter *ret = calloc(1, sizeof(struct filter));
if (ret == NULL) abort();
ret->eval = eval_and;
ret->free = free_op2;
ret->v.op2.a = a;
ret->v.op2.b = b;
return ret;
@@ -70,6 +88,7 @@ filter *filter_eq(filter *a, filter *b)
struct filter *ret = calloc(1, sizeof(struct filter));
if (ret == NULL) abort();
ret->eval = eval_eq;
ret->free = free_op2;
ret->v.op2.a = a;
ret->v.op2.b = b;
return ret;
@@ -80,6 +99,7 @@ filter *filter_int(int v)
struct filter *ret = calloc(1, sizeof(struct filter));
if (ret == NULL) abort();
ret->eval = eval_int;
ret->free = free_noop;
ret->v.v = v;
return ret;
}
@@ -97,6 +117,7 @@ filter *filter_evarg(void *database, char *event_name, char *varname)
f = get_format(database, event_id);
ret->eval = eval_evarg;
ret->free = free_noop;
ret->v.evarg.event_type = event_id;
ret->v.evarg.arg_index = -1;
@@ -114,6 +135,14 @@ filter *filter_evarg(void *database, char *event_name, char *varname)
return ret;
}
void free_filter(filter *_f)
{
struct filter *f;
if (_f == NULL) return;
f = _f;
f->free(f);
}
/****************************************************************************/
/* eval function */
/****************************************************************************/
+2
View File
@@ -12,4 +12,6 @@ filter *filter_evarg(void *database, char *event_name, char *varname);
int filter_eval(filter *f, event e);
void free_filter(filter *f);
#endif /* _FILTER_H_ */
+2 -2
View File
@@ -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)
+10
View File
@@ -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);
@@ -39,6 +44,9 @@ widget *new_space(gui *gui, int width, int height);
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);
@@ -49,6 +57,8 @@ void xy_plot_set_range(gui *gui, widget *this,
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);
+14 -2
View File
@@ -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 {
@@ -141,13 +142,24 @@ struct button_widget {
struct label_widget {
struct widget common;
const char *t;
char *t;
int color;
int width; /* as given by the graphic's backend */
int height; /* as given by the graphic's backend */
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;
+18
View File
@@ -81,3 +81,21 @@ void label_set_clickable(gui *_g, widget *_this, int clickable)
gunlock(g);
}
void label_set_text(gui *_g, widget *_this, char *text)
{
struct gui *g = _g;
struct label_widget *this = _this;
glock(g);
free(this->t);
this->t = strdup(text); if (this->t == NULL) OOM;
x_text_get_dimensions(g->x, DEFAULT_FONT, text,
&this->width, &this->height, &this->baseline);
send_event(g, REPACK, this->common.id);
gunlock(g);
}
+83
View File
@@ -0,0 +1,83 @@
#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);
}
+2 -1
View File
@@ -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:
+228 -7
View File
@@ -1,11 +1,20 @@
#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;
@@ -290,3 +478,36 @@ void xy_plot_get_dimensions(gui *_gui, widget *_this, int *width, int *height)
gunlock(g);
}
void xy_plot_set_title(gui *_gui, widget *_this, char *label)
{
struct gui *g = _gui;
struct xy_plot_widget *this = _this;
glock(g);
free(this->label);
this->label = strdup(label); if (this->label == NULL) OOM;
/* TODO: be sure calling X there is valid wrt "global model" (we are
* not in the "gui thread") */
x_text_get_dimensions(g->x, DEFAULT_FONT, label,
&this->label_width, &this->label_height, &this->label_baseline);
send_event(g, REPACK, this->common.id);
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);
}
+1 -1
View File
@@ -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)
+2
View File
@@ -1,5 +1,6 @@
#include "logger.h"
#include "logger_defs.h"
#include "filter/filter.h"
#include <stdlib.h>
void logger_add_view(logger *_l, view *v)
@@ -13,5 +14,6 @@ void logger_add_view(logger *_l, view *v)
void logger_set_filter(logger *_l, void *filter)
{
struct logger *l = _l;
free_filter(l->filter);
l->filter = filter;
}
+8
View File
@@ -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_ */
@@ -0,0 +1,194 @@
#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;
}
@@ -0,0 +1,196 @@
#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;
}
+11
View File
@@ -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 */
/****************************************************************************/
+1
View File
@@ -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 */
+1 -1
View File
@@ -1,7 +1,7 @@
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)
+100
View File
@@ -0,0 +1,100 @@
#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;
}
+2
View File
@@ -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);
+177 -54
View File
@@ -1,4 +1,8 @@
/*
/* $NetBSD: tree.h,v 1.8 2004/03/28 19:38:30 provos Exp $ */
/* $OpenBSD: tree.h,v 1.7 2002/10/17 21:51:54 art Exp $ */
/* $FreeBSD$ */
/*-
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
* All rights reserved.
*
@@ -26,6 +30,8 @@
#ifndef _SYS_TREE_H_
#define _SYS_TREE_H_
#include <sys/cdefs.h>
/*
* This file defines data structures for different types of trees:
* splay trees and red-black trees.
@@ -63,7 +69,7 @@ struct name { \
#define SPLAY_INIT(root) do { \
(root)->sph_root = NULL; \
} while (0)
} while (/*CONSTCOND*/ 0)
#define SPLAY_ENTRY(type) \
struct { \
@@ -81,32 +87,32 @@ struct { \
SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field); \
SPLAY_RIGHT(tmp, field) = (head)->sph_root; \
(head)->sph_root = tmp; \
} while (0)
} while (/*CONSTCOND*/ 0)
#define SPLAY_ROTATE_LEFT(head, tmp, field) do { \
SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field); \
SPLAY_LEFT(tmp, field) = (head)->sph_root; \
(head)->sph_root = tmp; \
} while (0)
} while (/*CONSTCOND*/ 0)
#define SPLAY_LINKLEFT(head, tmp, field) do { \
SPLAY_LEFT(tmp, field) = (head)->sph_root; \
tmp = (head)->sph_root; \
(head)->sph_root = SPLAY_LEFT((head)->sph_root, field); \
} while (0)
} while (/*CONSTCOND*/ 0)
#define SPLAY_LINKRIGHT(head, tmp, field) do { \
SPLAY_RIGHT(tmp, field) = (head)->sph_root; \
tmp = (head)->sph_root; \
(head)->sph_root = SPLAY_RIGHT((head)->sph_root, field); \
} while (0)
} while (/*CONSTCOND*/ 0)
#define SPLAY_ASSEMBLE(head, node, left, right, field) do { \
SPLAY_RIGHT(left, field) = SPLAY_LEFT((head)->sph_root, field); \
SPLAY_LEFT(right, field) = SPLAY_RIGHT((head)->sph_root, field);\
SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(node, field); \
SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(node, field); \
} while (0)
} while (/*CONSTCOND*/ 0)
/* Generates prototypes and inline functions */
@@ -207,7 +213,7 @@ name##_SPLAY(struct name *head, struct type *elm) \
SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\
__left = __right = &__node; \
\
while ((__comp = (cmp)(elm, (head)->sph_root))) { \
while ((__comp = (cmp)(elm, (head)->sph_root)) != 0) { \
if (__comp < 0) { \
__tmp = SPLAY_LEFT((head)->sph_root, field); \
if (__tmp == NULL) \
@@ -286,7 +292,7 @@ void name##_SPLAY_MINMAX(struct name *head, int __comp) \
(x) != NULL; \
(x) = SPLAY_NEXT(name, head, x))
/* Macros that define a red-back tree */
/* Macros that define a red-black tree */
#define RB_HEAD(name, type) \
struct name { \
struct type *rbh_root; /* root of the tree */ \
@@ -297,7 +303,7 @@ struct name { \
#define RB_INIT(root) do { \
(root)->rbh_root = NULL; \
} while (0)
} while (/*CONSTCOND*/ 0)
#define RB_BLACK 0
#define RB_RED 1
@@ -320,24 +326,24 @@ struct { \
RB_PARENT(elm, field) = parent; \
RB_LEFT(elm, field) = RB_RIGHT(elm, field) = NULL; \
RB_COLOR(elm, field) = RB_RED; \
} while (0)
} while (/*CONSTCOND*/ 0)
#define RB_SET_BLACKRED(black, red, field) do { \
RB_COLOR(black, field) = RB_BLACK; \
RB_COLOR(red, field) = RB_RED; \
} while (0)
} while (/*CONSTCOND*/ 0)
#ifndef RB_AUGMENT
#define RB_AUGMENT(x)
#define RB_AUGMENT(x) do {} while (0)
#endif
#define RB_ROTATE_LEFT(head, elm, tmp, field) do { \
(tmp) = RB_RIGHT(elm, field); \
if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field))) { \
if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field)) != NULL) { \
RB_PARENT(RB_LEFT(tmp, field), field) = (elm); \
} \
RB_AUGMENT(elm); \
if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) { \
if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) != NULL) { \
if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \
RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \
else \
@@ -349,15 +355,15 @@ struct { \
RB_AUGMENT(tmp); \
if ((RB_PARENT(tmp, field))) \
RB_AUGMENT(RB_PARENT(tmp, field)); \
} while (0)
} while (/*CONSTCOND*/ 0)
#define RB_ROTATE_RIGHT(head, elm, tmp, field) do { \
(tmp) = RB_LEFT(elm, field); \
if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field))) { \
if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field)) != NULL) { \
RB_PARENT(RB_RIGHT(tmp, field), field) = (elm); \
} \
RB_AUGMENT(elm); \
if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) { \
if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) != NULL) { \
if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \
RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \
else \
@@ -369,28 +375,66 @@ struct { \
RB_AUGMENT(tmp); \
if ((RB_PARENT(tmp, field))) \
RB_AUGMENT(RB_PARENT(tmp, field)); \
} while (0)
} while (/*CONSTCOND*/ 0)
/* Generates prototypes and inline functions */
#define RB_PROTOTYPE(name, type, field, cmp) \
void name##_RB_INSERT_COLOR(struct name *, struct type *); \
void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\
struct type *name##_RB_REMOVE(struct name *, struct type *); \
struct type *name##_RB_INSERT(struct name *, struct type *); \
struct type *name##_RB_FIND(struct name *, struct type *); \
struct type *name##_RB_NEXT(struct type *); \
struct type *name##_RB_MINMAX(struct name *, int); \
\
#define RB_PROTOTYPE(name, type, field, cmp) \
RB_PROTOTYPE_INTERNAL(name, type, field, cmp,)
#define RB_PROTOTYPE_STATIC(name, type, field, cmp) \
RB_PROTOTYPE_INTERNAL(name, type, field, cmp, __unused static)
#define RB_PROTOTYPE_INTERNAL(name, type, field, cmp, attr) \
RB_PROTOTYPE_INSERT_COLOR(name, type, attr); \
RB_PROTOTYPE_REMOVE_COLOR(name, type, attr); \
RB_PROTOTYPE_INSERT(name, type, attr); \
RB_PROTOTYPE_REMOVE(name, type, attr); \
RB_PROTOTYPE_FIND(name, type, attr); \
RB_PROTOTYPE_NFIND(name, type, attr); \
RB_PROTOTYPE_NEXT(name, type, attr); \
RB_PROTOTYPE_PREV(name, type, attr); \
RB_PROTOTYPE_MINMAX(name, type, attr);
#define RB_PROTOTYPE_INSERT_COLOR(name, type, attr) \
attr void name##_RB_INSERT_COLOR(struct name *, struct type *)
#define RB_PROTOTYPE_REMOVE_COLOR(name, type, attr) \
attr void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *)
#define RB_PROTOTYPE_REMOVE(name, type, attr) \
attr struct type *name##_RB_REMOVE(struct name *, struct type *)
#define RB_PROTOTYPE_INSERT(name, type, attr) \
attr struct type *name##_RB_INSERT(struct name *, struct type *)
#define RB_PROTOTYPE_FIND(name, type, attr) \
attr struct type *name##_RB_FIND(struct name *, struct type *)
#define RB_PROTOTYPE_NFIND(name, type, attr) \
attr struct type *name##_RB_NFIND(struct name *, struct type *)
#define RB_PROTOTYPE_NEXT(name, type, attr) \
attr struct type *name##_RB_NEXT(struct type *)
#define RB_PROTOTYPE_PREV(name, type, attr) \
attr struct type *name##_RB_PREV(struct type *)
#define RB_PROTOTYPE_MINMAX(name, type, attr) \
attr struct type *name##_RB_MINMAX(struct name *, int)
/* Main rb operation.
* Moves node close to the key of elm to top
*/
#define RB_GENERATE(name, type, field, cmp) \
void \
#define RB_GENERATE(name, type, field, cmp) \
RB_GENERATE_INTERNAL(name, type, field, cmp,)
#define RB_GENERATE_STATIC(name, type, field, cmp) \
RB_GENERATE_INTERNAL(name, type, field, cmp, __unused static)
#define RB_GENERATE_INTERNAL(name, type, field, cmp, attr) \
RB_GENERATE_INSERT_COLOR(name, type, field, attr) \
RB_GENERATE_REMOVE_COLOR(name, type, field, attr) \
RB_GENERATE_INSERT(name, type, field, cmp, attr) \
RB_GENERATE_REMOVE(name, type, field, attr) \
RB_GENERATE_FIND(name, type, field, cmp, attr) \
RB_GENERATE_NFIND(name, type, field, cmp, attr) \
RB_GENERATE_NEXT(name, type, field, attr) \
RB_GENERATE_PREV(name, type, field, attr) \
RB_GENERATE_MINMAX(name, type, field, attr)
#define RB_GENERATE_INSERT_COLOR(name, type, field, attr) \
attr void \
name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \
{ \
struct type *parent, *gparent, *tmp; \
while ((parent = RB_PARENT(elm, field)) && \
while ((parent = RB_PARENT(elm, field)) != NULL && \
RB_COLOR(parent, field) == RB_RED) { \
gparent = RB_PARENT(parent, field); \
if (parent == RB_LEFT(gparent, field)) { \
@@ -428,9 +472,10 @@ name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \
} \
} \
RB_COLOR(head->rbh_root, field) = RB_BLACK; \
} \
\
void \
}
#define RB_GENERATE_REMOVE_COLOR(name, type, field, attr) \
attr void \
name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm) \
{ \
struct type *tmp; \
@@ -454,7 +499,8 @@ name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm)
if (RB_RIGHT(tmp, field) == NULL || \
RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK) {\
struct type *oleft; \
if ((oleft = RB_LEFT(tmp, field)))\
if ((oleft = RB_LEFT(tmp, field)) \
!= NULL) \
RB_COLOR(oleft, field) = RB_BLACK;\
RB_COLOR(tmp, field) = RB_RED; \
RB_ROTATE_RIGHT(head, tmp, oleft, field);\
@@ -486,7 +532,8 @@ name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm)
if (RB_LEFT(tmp, field) == NULL || \
RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) {\
struct type *oright; \
if ((oright = RB_RIGHT(tmp, field)))\
if ((oright = RB_RIGHT(tmp, field)) \
!= NULL) \
RB_COLOR(oright, field) = RB_BLACK;\
RB_COLOR(tmp, field) = RB_RED; \
RB_ROTATE_LEFT(head, tmp, oright, field);\
@@ -504,9 +551,10 @@ name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm)
} \
if (elm) \
RB_COLOR(elm, field) = RB_BLACK; \
} \
\
struct type * \
}
#define RB_GENERATE_REMOVE(name, type, field, attr) \
attr struct type * \
name##_RB_REMOVE(struct name *head, struct type *elm) \
{ \
struct type *child, *parent, *old = elm; \
@@ -518,7 +566,7 @@ name##_RB_REMOVE(struct name *head, struct type *elm) \
else { \
struct type *left; \
elm = RB_RIGHT(elm, field); \
while ((left = RB_LEFT(elm, field))) \
while ((left = RB_LEFT(elm, field)) != NULL) \
elm = left; \
child = RB_RIGHT(elm, field); \
parent = RB_PARENT(elm, field); \
@@ -551,7 +599,7 @@ name##_RB_REMOVE(struct name *head, struct type *elm) \
left = parent; \
do { \
RB_AUGMENT(left); \
} while ((left = RB_PARENT(left, field))); \
} while ((left = RB_PARENT(left, field)) != NULL); \
} \
goto color; \
} \
@@ -572,9 +620,10 @@ color: \
name##_RB_REMOVE_COLOR(head, parent, child); \
return (old); \
} \
\
#define RB_GENERATE_INSERT(name, type, field, cmp, attr) \
/* Inserts a node into the RB tree */ \
struct type * \
attr struct type * \
name##_RB_INSERT(struct name *head, struct type *elm) \
{ \
struct type *tmp; \
@@ -599,15 +648,14 @@ name##_RB_INSERT(struct name *head, struct type *elm) \
RB_RIGHT(parent, field) = elm; \
RB_AUGMENT(parent); \
} else \
{ \
RB_ROOT(head) = elm; \
} \
name##_RB_INSERT_COLOR(head, elm); \
return (NULL); \
} \
\
}
#define RB_GENERATE_FIND(name, type, field, cmp, attr) \
/* Finds the node with the same key as elm */ \
struct type * \
attr struct type * \
name##_RB_FIND(struct name *head, struct type *elm) \
{ \
struct type *tmp = RB_ROOT(head); \
@@ -622,9 +670,33 @@ name##_RB_FIND(struct name *head, struct type *elm) \
return (tmp); \
} \
return (NULL); \
} \
\
struct type * \
}
#define RB_GENERATE_NFIND(name, type, field, cmp, attr) \
/* Finds the first node greater than or equal to the search key */ \
attr struct type * \
name##_RB_NFIND(struct name *head, struct type *elm) \
{ \
struct type *tmp = RB_ROOT(head); \
struct type *res = NULL; \
int comp; \
while (tmp) { \
comp = cmp(elm, tmp); \
if (comp < 0) { \
res = tmp; \
tmp = RB_LEFT(tmp, field); \
} \
else if (comp > 0) \
tmp = RB_RIGHT(tmp, field); \
else \
return (tmp); \
} \
return (res); \
}
#define RB_GENERATE_NEXT(name, type, field, attr) \
/* ARGSUSED */ \
attr struct type * \
name##_RB_NEXT(struct type *elm) \
{ \
if (RB_RIGHT(elm, field)) { \
@@ -643,9 +715,33 @@ name##_RB_NEXT(struct type *elm) \
} \
} \
return (elm); \
} \
\
struct type * \
}
#define RB_GENERATE_PREV(name, type, field, attr) \
/* ARGSUSED */ \
attr struct type * \
name##_RB_PREV(struct type *elm) \
{ \
if (RB_LEFT(elm, field)) { \
elm = RB_LEFT(elm, field); \
while (RB_RIGHT(elm, field)) \
elm = RB_RIGHT(elm, field); \
} else { \
if (RB_PARENT(elm, field) && \
(elm == RB_RIGHT(RB_PARENT(elm, field), field))) \
elm = RB_PARENT(elm, field); \
else { \
while (RB_PARENT(elm, field) && \
(elm == RB_LEFT(RB_PARENT(elm, field), field)))\
elm = RB_PARENT(elm, field); \
elm = RB_PARENT(elm, field); \
} \
} \
return (elm); \
}
#define RB_GENERATE_MINMAX(name, type, field, attr) \
attr struct type * \
name##_RB_MINMAX(struct name *head, int val) \
{ \
struct type *tmp = RB_ROOT(head); \
@@ -666,7 +762,9 @@ name##_RB_MINMAX(struct name *head, int val) \
#define RB_INSERT(name, x, y) name##_RB_INSERT(x, y)
#define RB_REMOVE(name, x, y) name##_RB_REMOVE(x, y)
#define RB_FIND(name, x, y) name##_RB_FIND(x, y)
#define RB_NFIND(name, x, y) name##_RB_NFIND(x, y)
#define RB_NEXT(name, x, y) name##_RB_NEXT(y)
#define RB_PREV(name, x, y) name##_RB_PREV(y)
#define RB_MIN(name, x) name##_RB_MINMAX(x, RB_NEGINF)
#define RB_MAX(name, x) name##_RB_MINMAX(x, RB_INF)
@@ -675,4 +773,29 @@ name##_RB_MINMAX(struct name *head, int val) \
(x) != NULL; \
(x) = name##_RB_NEXT(x))
#define RB_FOREACH_FROM(x, name, y) \
for ((x) = (y); \
((x) != NULL) && ((y) = name##_RB_NEXT(x), (x) != NULL); \
(x) = (y))
#define RB_FOREACH_SAFE(x, name, head, y) \
for ((x) = RB_MIN(name, head); \
((x) != NULL) && ((y) = name##_RB_NEXT(x), (x) != NULL); \
(x) = (y))
#define RB_FOREACH_REVERSE(x, name, head) \
for ((x) = RB_MAX(name, head); \
(x) != NULL; \
(x) = name##_RB_PREV(x))
#define RB_FOREACH_REVERSE_FROM(x, name, y) \
for ((x) = (y); \
((x) != NULL) && ((y) = name##_RB_PREV(x), (x) != NULL); \
(x) = (y))
#define RB_FOREACH_REVERSE_SAFE(x, name, head, y) \
for ((x) = RB_MAX(name, head); \
((x) != NULL) && ((y) = name##_RB_PREV(x), (x) != NULL); \
(x) = (y))
#endif /* _SYS_TREE_H_ */
+6 -2
View File
@@ -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;
}
+1
View File
@@ -1,3 +1,4 @@
#!/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
+5
View File
@@ -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
+43 -9
View File
@@ -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;
@@ -760,7 +779,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;
@@ -854,8 +875,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) {
@@ -1119,7 +1144,7 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB,
#endif
if ((fp->frame_type == TDD) && (subframe_select(fp,subframe)!=SF_DL)) return;
if ((fp->frame_type == TDD) && (subframe_select(fp,subframe)==SF_UL)) return;
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_TX+offset,1);
if (do_meas==1) start_meas(&eNB->phy_proc_tx);
@@ -1399,7 +1424,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++)
{
+2
View File
@@ -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
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,122 @@
/*
* 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
@@ -0,0 +1,75 @@
/*
* 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
@@ -0,0 +1,794 @@
/*
* 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.c
* \brief Helper functions for the MAC agent
* \author Xenofon Foukas
* \date 2016
* \version 0.1
*/
#include <string.h>
#include <dlfcn.h>
#include "flexran_agent_mac_internal.h"
Protocol__FlexranMessage * flexran_agent_generate_diff_mac_stats_report(Protocol__FlexranMessage *new_message,
Protocol__FlexranMessage *old_message) {
int i, j;
Protocol__FlexStatsReply *old_report, *new_report;
Protocol__FlexStatsReply *stats_reply_msg = NULL;
Protocol__FlexranMessage *msg = NULL;
Protocol__FlexUeStatsReport **ue_report;
Protocol__FlexUeStatsReport *tmp_ue_report[NUM_MAX_UE];
Protocol__FlexCellStatsReport **cell_report;
Protocol__FlexCellStatsReport *tmp_cell_report[NUM_MAX_UE];
old_report = old_message->stats_reply_msg;
new_report = new_message->stats_reply_msg;
/*Flags to designate changes in various levels of the message*/
int stats_had_changes = 0;
int ue_had_change = 0;
int cell_had_change = 0;
/*See how many and which UE reports should be included in the final stats message*/
int n_ue_report = 0;
int ue_found = 0;
/*Go through each RNTI of the new report and see if it exists in the old one*/
for (i = 0; i < new_report->n_ue_report; i++) {
for (j = 0; j < old_report->n_ue_report; i++) {
if (new_report->ue_report[i]->rnti == old_report->ue_report[j]->rnti) {
ue_found = 1;
/*Need to check if something changed*/
if (compare_ue_stats_reports(new_report->ue_report[i], old_report->ue_report[j]) != 0) {
tmp_ue_report[n_ue_report] = copy_ue_stats_report(new_report->ue_report[i]);
n_ue_report++;
}
break;
}
}
if (!ue_found) {
tmp_ue_report[n_ue_report] = copy_ue_stats_report(new_report->ue_report[i]);
n_ue_report++;
}
ue_found = 0;
}
/*See how many and which cell reports should be included in the final stats message*/
int n_cell_report = 0;
int cell_found = 0;
/*Go through each cell of the new report and see if it exists in the old one*/
for (i = 0; i < new_report->n_cell_report; i++) {
for (j = 0; j < old_report->n_cell_report; i++) {
if (new_report->cell_report[i]->carrier_index == old_report->cell_report[j]->carrier_index) {
cell_found = 1;
/*Need to check if something changed*/
if (compare_cell_stats_reports(new_report->cell_report[i], old_report->cell_report[j]) != 0) {
tmp_cell_report[n_cell_report] = copy_cell_stats_report(new_report->cell_report[i]);
n_cell_report++;
}
break;
}
}
if (!cell_found) {
tmp_cell_report[n_cell_report] = copy_cell_stats_report(new_report->cell_report[i]);
n_cell_report++;
}
cell_found = 0;
}
/*TODO: create the reply message based on the findings*/
/*Create ue report list*/
if (n_ue_report > 0) {
ue_report = malloc(sizeof(Protocol__FlexUeStatsReport *));
for (i = 0; i<n_ue_report; i++) {
ue_report[i] = tmp_ue_report[i];
}
}
/*Create cell report list*/
if (n_cell_report > 0) {
cell_report = malloc(sizeof(Protocol__FlexCellStatsReport *));
for (i = 0; i<n_cell_report; i++) {
cell_report[i] = tmp_cell_report[i];
}
}
if (n_cell_report > 0 || n_ue_report > 0) {
/*Create header*/
int xid = old_report->header->xid;
Protocol__FlexHeader *header;
if (flexran_create_header(xid, PROTOCOL__FLEX_TYPE__FLPT_STATS_REPLY, &header) != 0) {
goto error;
}
stats_reply_msg = malloc(sizeof(Protocol__FlexStatsReply));
protocol__flex_stats_reply__init(stats_reply_msg);
stats_reply_msg->header = header;
stats_reply_msg->n_ue_report = n_ue_report;
stats_reply_msg->ue_report = ue_report;
stats_reply_msg->n_cell_report = n_cell_report;
stats_reply_msg->cell_report = cell_report;
msg = malloc(sizeof(Protocol__FlexranMessage));
if(msg == NULL)
goto error;
protocol__flexran_message__init(msg);
msg->msg_case = PROTOCOL__FLEXRAN_MESSAGE__MSG_STATS_REPLY_MSG;
msg->msg_dir = PROTOCOL__FLEXRAN_DIRECTION__SUCCESSFUL_OUTCOME;
msg->stats_reply_msg = stats_reply_msg;
}
return msg;
error:
return NULL;
}
int compare_ue_stats_reports(Protocol__FlexUeStatsReport *rep1,
Protocol__FlexUeStatsReport *rep2) {
return 1;
}
int compare_cell_stats_reports(Protocol__FlexCellStatsReport *rep1,
Protocol__FlexCellStatsReport *rep2) {
return 1;
}
Protocol__FlexUeStatsReport * copy_ue_stats_report(Protocol__FlexUeStatsReport * original) {
int i;
Protocol__FlexUeStatsReport *copy = malloc(sizeof(Protocol__FlexUeStatsReport));
if (copy == NULL)
goto error;
protocol__flex_ue_stats_report__init(copy);
copy->rnti = original->rnti;
copy->has_rnti = original->has_rnti;
copy->flags = original->flags;
copy->has_flags = original->has_flags;
if (copy->flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_BSR) {
copy->n_bsr = original->n_bsr;
if (copy->n_bsr > 0) {
uint32_t *elem;
elem = (uint32_t *) malloc(sizeof(uint32_t)*copy->n_bsr);
if (elem == NULL)
goto error;
for (i = 0; i < original->n_bsr; i++) {
elem[i] = original->bsr[i];
}
copy->bsr = elem;
}
}
if (copy->flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_PRH) {
copy->has_phr = original->has_phr;
copy->phr = original->phr;
}
if (copy->flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_RLC_BS) {
copy->n_rlc_report = original->n_rlc_report;
if (copy->n_rlc_report > 0) {
Protocol__FlexRlcBsr ** rlc_reports;
rlc_reports = malloc(sizeof(Protocol__FlexRlcBsr) * copy->n_rlc_report);
if (rlc_reports == NULL)
goto error;
for (i = 0; i < copy->n_rlc_report; i++) {
rlc_reports[i] = copy_rlc_report(original->rlc_report[i]);
}
copy->rlc_report = rlc_reports;
}
}
if (copy->flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_MAC_CE_BS) {
copy->has_pending_mac_ces = original->has_pending_mac_ces;
copy->pending_mac_ces = original->pending_mac_ces;
}
if (copy->flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_DL_CQI) {
copy->dl_cqi_report = copy_dl_cqi_report(original->dl_cqi_report);
}
if (copy->flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_PBS) {
/*Copy the Paging Buffer report*/
copy->pbr = copy_paging_buffer_report(original->pbr);
}
if (copy->flags & PROTOCOL__FLEX_UE_STATS_TYPE__FLUST_UL_CQI) {
/*TODO: Copy the UL report*/
copy->ul_cqi_report = copy_ul_cqi_report(original->ul_cqi_report);
}
return copy;
error:
return NULL;
}
Protocol__FlexRlcBsr * copy_rlc_report(Protocol__FlexRlcBsr * original) {
Protocol__FlexRlcBsr * copy = malloc(sizeof(Protocol__FlexRlcBsr));
if (copy == NULL)
goto error;
protocol__flex_rlc_bsr__init(copy);
copy->lc_id = original->lc_id;
copy->has_lc_id = original->has_lc_id;
copy->tx_queue_size = original->tx_queue_size;
copy->has_tx_queue_size = original->has_tx_queue_size;
copy->tx_queue_hol_delay = original->tx_queue_hol_delay;
copy->has_tx_queue_hol_delay = original->has_tx_queue_hol_delay;
copy->retransmission_queue_size = original->retransmission_queue_size;
copy->has_retransmission_queue_size = original->has_retransmission_queue_size;
copy->retransmission_queue_hol_delay = original->retransmission_queue_hol_delay;
copy->has_retransmission_queue_hol_delay = original->has_retransmission_queue_hol_delay;
copy->status_pdu_size = original->status_pdu_size;
copy->has_status_pdu_size = original->has_status_pdu_size;
return copy;
error:
return NULL;
}
Protocol__FlexUlCqiReport * copy_ul_cqi_report(Protocol__FlexUlCqiReport * original) {
int i, j;
//Fill in the full UL CQI report of the UE
Protocol__FlexUlCqiReport *full_ul_report;
full_ul_report = malloc(sizeof(Protocol__FlexUlCqiReport));
if(full_ul_report == NULL) {
goto error;
}
protocol__flex_ul_cqi_report__init(full_ul_report);
//TODO:Set the SFN and SF of the generated report
full_ul_report->sfn_sn = original->sfn_sn;
full_ul_report->has_sfn_sn = original->has_sfn_sn;
full_ul_report->n_cqi_meas = original->n_cqi_meas;
Protocol__FlexUlCqi **ul_report;
ul_report = malloc(sizeof(Protocol__FlexUlCqi *) * full_ul_report->n_cqi_meas);
if(ul_report == NULL)
goto error;
for(i = 0; i++; i < full_ul_report->n_cqi_meas) {
ul_report[i] = malloc(sizeof(Protocol__FlexUlCqi));
if(ul_report[i] == NULL)
goto error;
protocol__flex_ul_cqi__init(ul_report[i]);
ul_report[i]->type = original->cqi_meas[i]->type;
ul_report[i]->has_type = original->cqi_meas[i]->has_type;
ul_report[i]->n_sinr = original->cqi_meas[i]->n_sinr;
uint32_t *sinr_meas;
sinr_meas = (uint32_t *) malloc(sizeof(uint32_t) * ul_report[i]->n_sinr);
if (sinr_meas == NULL)
goto error;
for (j = 0; j < ul_report[i]->n_sinr; j++) {
sinr_meas[j] = original->cqi_meas[i]->sinr[j];
}
ul_report[i]->sinr = sinr_meas;
ul_report[i]->serv_cell_index = original->cqi_meas[i]->serv_cell_index;
ul_report[i]->has_serv_cell_index = original->cqi_meas[i]->has_serv_cell_index;
}
full_ul_report->cqi_meas = ul_report;
return full_ul_report;
error:
return NULL;
}
Protocol__FlexDlCqiReport * copy_dl_cqi_report(Protocol__FlexDlCqiReport * original) {
int i;
/*Copy the DL report*/
Protocol__FlexDlCqiReport * dl_report;
dl_report = malloc(sizeof(Protocol__FlexDlCqiReport));
if (dl_report == NULL)
goto error;
protocol__flex_dl_cqi_report__init(dl_report);
dl_report->sfn_sn = original->sfn_sn;
dl_report->has_sfn_sn = original->has_sfn_sn;
dl_report->n_csi_report = original->n_csi_report;
Protocol__FlexDlCsi **csi_reports;
csi_reports = malloc(sizeof(Protocol__FlexDlCsi *) * dl_report->n_csi_report);
if (csi_reports == NULL)
goto error;
for (i = 0; i < dl_report->n_csi_report; i++) {
csi_reports[i] = copy_csi_report(original->csi_report[i]);
}
dl_report->csi_report = csi_reports;
return dl_report;
error:
/*TODO: Must free memory properly*/
return NULL;
}
Protocol__FlexPagingBufferReport * copy_paging_buffer_report(Protocol__FlexPagingBufferReport *original) {
int i;
Protocol__FlexPagingBufferReport *copy;
copy = malloc(sizeof(Protocol__FlexPagingBufferReport));
if (copy == NULL)
goto error;
protocol__flex_paging_buffer_report__init(copy);
copy->n_paging_info = original->n_paging_info;
Protocol__FlexPagingInfo **p_info;
p_info = malloc(sizeof(Protocol__FlexPagingInfo *) * copy->n_paging_info);
if (p_info == NULL)
goto error;
for (i = 0; i < copy->n_paging_info; i++) {
p_info[i] = malloc(sizeof(Protocol__FlexPagingInfo));
if(p_info[i] == NULL)
goto error;
protocol__flex_paging_info__init(p_info[i]);
p_info[i]->paging_index = original->paging_info[i]->paging_index;
p_info[i]->has_paging_index = original->paging_info[i]->has_paging_index;;
p_info[i]->paging_message_size = original->paging_info[i]->paging_message_size;
p_info[i]->has_paging_message_size = original->paging_info[i]->has_paging_message_size;
p_info[i]->paging_subframe = original->paging_info[i]->paging_subframe;
p_info[i]->has_paging_subframe = original->paging_info[i]->has_paging_subframe;
p_info[i]->carrier_index = original->paging_info[i]->carrier_index;
p_info[i]->has_carrier_index = original->paging_info[i]->has_carrier_index;
}
copy->paging_info = p_info;
return copy;
error:
/*TODO: free memory properly*/
return NULL;
}
Protocol__FlexDlCsi * copy_csi_report(Protocol__FlexDlCsi * original) {
int i, j;
Protocol__FlexDlCsi *copy = malloc(sizeof(Protocol__FlexDlCsi));
if (copy == NULL)
goto error;
protocol__flex_dl_csi__init(copy);
copy->serv_cell_index = original->serv_cell_index;
copy->has_serv_cell_index = original->has_serv_cell_index;
copy->ri = original->ri;
copy->has_ri = original->ri;
copy->type = original->type;
copy->has_type = original->has_type;
copy->report_case = original->report_case;
switch (copy->report_case) {
case PROTOCOL__FLEX_DL_CSI__REPORT_P10CSI:
copy->p10csi->wb_cqi = original->p10csi->wb_cqi;
copy->p10csi->has_wb_cqi = original->p10csi->has_wb_cqi;
break;
case PROTOCOL__FLEX_DL_CSI__REPORT_P11CSI:
copy->p11csi->n_wb_cqi = original->p11csi->n_wb_cqi;
copy->p11csi->wb_cqi = (uint32_t *) malloc(sizeof(uint32_t) * copy->p11csi->n_wb_cqi);
for (i = 0; i < copy->p11csi->n_wb_cqi; i++) {
copy->p11csi->wb_cqi[i] = original->p11csi->wb_cqi[i];
}
copy->p11csi->has_wb_pmi = original->p11csi->has_wb_pmi;
copy->p11csi->wb_pmi = original->p11csi->wb_pmi;
break;
case PROTOCOL__FLEX_DL_CSI__REPORT_P20CSI:
copy->p20csi->has_wb_cqi = original->p20csi->has_wb_cqi;
copy->p20csi->wb_cqi = original->p20csi->wb_cqi;
copy->p20csi->has_sb_cqi = original->p20csi->has_sb_cqi;
copy->p20csi->sb_cqi = original->p20csi->sb_cqi;
copy->p20csi->has_bandwidth_part_index = original->p20csi->has_bandwidth_part_index;
copy->p20csi->bandwidth_part_index = original->p20csi->bandwidth_part_index;
copy->p20csi->has_sb_index = original->p20csi->has_sb_index;
copy->p20csi->sb_index = original->p20csi->sb_index;
break;
case PROTOCOL__FLEX_DL_CSI__REPORT_P21CSI:
copy->p21csi->n_wb_cqi = original->p21csi->n_wb_cqi;
copy->p21csi->wb_cqi = (uint32_t *) malloc(sizeof(uint32_t) * copy->p21csi->n_wb_cqi);
for (i = 0; i < copy->p21csi->n_wb_cqi; i++) {
copy->p21csi->wb_cqi[i] = original->p21csi->wb_cqi[i];
}
copy->p21csi->has_wb_pmi = original->p21csi->has_wb_pmi;
copy->p21csi->wb_pmi = original->p21csi->wb_pmi;
copy->p21csi->n_sb_cqi = original->p21csi->n_sb_cqi;
copy->p21csi->sb_cqi = (uint32_t *) malloc(sizeof(uint32_t) * copy->p21csi->n_sb_cqi);
for (i = 0; i < copy->p21csi->n_sb_cqi; i++) {
copy->p21csi->sb_cqi[i] = original->p21csi->sb_cqi[i];
}
copy->p21csi->has_badwidth_part_index = original->p21csi->has_badwidth_part_index;
copy->p21csi->badwidth_part_index = original->p21csi->badwidth_part_index;
copy->p21csi->has_sb_index = original->p21csi->has_sb_index;
copy->p21csi->sb_index = original->p21csi->sb_index;
break;
case PROTOCOL__FLEX_DL_CSI__REPORT_A12CSI:
copy->a12csi->n_wb_cqi = original->a12csi->n_wb_cqi;
copy->a12csi->wb_cqi = (uint32_t *) malloc(sizeof(uint32_t) * copy->a12csi->n_wb_cqi);
for (i = 0; i < copy->a12csi->n_wb_cqi; i++) {
copy->a12csi->wb_cqi[i] = original->a12csi->wb_cqi[i];
}
copy->a12csi->n_sb_pmi = original->a12csi->n_sb_pmi;
copy->a12csi->sb_pmi = (uint32_t *) malloc(sizeof(uint32_t) * copy->a12csi->n_sb_pmi);
for (i = 0; i < copy->a12csi->n_sb_pmi; i++) {
copy->a12csi->sb_pmi[i] = original->a12csi->sb_pmi[i];
}
break;
case PROTOCOL__FLEX_DL_CSI__REPORT_A22CSI:
copy->a22csi->n_wb_cqi = original->a22csi->n_wb_cqi;
copy->a22csi->wb_cqi = (uint32_t *) malloc(sizeof(uint32_t) * copy->a22csi->n_wb_cqi);
for (i = 0; i < copy->a22csi->n_wb_cqi; i++) {
copy->a22csi->wb_cqi[i] = original->a22csi->wb_cqi[i];
}
copy->a22csi->n_sb_cqi = original->a22csi->n_sb_cqi;
copy->a22csi->sb_cqi = (uint32_t *) malloc(sizeof(uint32_t) * copy->a22csi->n_sb_cqi);
for (i = 0; i < copy->a22csi->n_sb_cqi; i++) {
copy->a22csi->sb_cqi[i] = original->a22csi->sb_cqi[i];
}
copy->a22csi->has_wb_pmi = original->a22csi->has_wb_pmi;
copy->a22csi->wb_pmi = original->a22csi->wb_pmi;
copy->a22csi->has_sb_pmi = original->a22csi->has_sb_pmi;
copy->a22csi->sb_pmi = original->a22csi->sb_pmi;
copy->a22csi->n_sb_list = original->a22csi->n_sb_list;
copy->a22csi->sb_list = (uint32_t *) malloc(sizeof(uint32_t) * copy->a22csi->n_sb_list);
for (i = 0; i < copy->a22csi->n_sb_list; i++) {
copy->a22csi->sb_list[i] = original->a22csi->sb_list[i];
}
break;
case PROTOCOL__FLEX_DL_CSI__REPORT_A20CSI:
copy->a20csi->has_wb_cqi = original->a20csi->has_wb_cqi;
copy->a20csi->wb_cqi = original->a20csi->wb_cqi;
copy->a20csi->has_sb_cqi = original->a20csi->has_sb_cqi;
copy->a20csi->sb_cqi = original->a20csi->sb_cqi;
copy->a20csi->n_sb_list = original->a20csi->n_sb_list;
copy->a20csi->sb_list = (uint32_t *) malloc(sizeof(uint32_t) * copy->a20csi->n_sb_list);
for (i = 0; i < copy->a20csi->n_sb_list; i++) {
copy->a20csi->sb_list[i] = original->a20csi->sb_list[i];
}
break;
case PROTOCOL__FLEX_DL_CSI__REPORT_A30CSI:
copy->a30csi->has_wb_cqi = original->a30csi->has_wb_cqi;
copy->a30csi->wb_cqi = original->a30csi->wb_cqi;
copy->a30csi->n_sb_cqi = original->a30csi->n_sb_cqi;
copy->a30csi->sb_cqi = (uint32_t *) malloc(sizeof(uint32_t) * copy->a30csi->n_sb_cqi);
for (i = 0; i < copy->a30csi->n_sb_cqi; i++) {
copy->a30csi->sb_cqi[i] = original->a30csi->sb_cqi[i];
}
break;
case PROTOCOL__FLEX_DL_CSI__REPORT_A31CSI:
copy->a31csi->n_wb_cqi = original->a31csi->n_wb_cqi;
copy->a31csi->wb_cqi = (uint32_t *) malloc(sizeof(uint32_t) * copy->a31csi->n_wb_cqi);
for (i = 0; i < copy->a31csi->n_wb_cqi; i++) {
copy->a31csi->wb_cqi[i] = original->a31csi->wb_cqi[i];
}
copy->a31csi->has_wb_pmi = original->a31csi->has_wb_pmi;
copy->a31csi->wb_pmi = original->a31csi->wb_pmi;
copy->a31csi->n_sb_cqi = original->a31csi->n_sb_cqi;
copy->a31csi->sb_cqi = malloc(sizeof(Protocol__FlexMsbCqi *) * copy->a31csi->n_sb_cqi);
if (copy->a31csi == NULL) {
goto error;
}
for (i = 0; i < copy->a31csi->n_sb_cqi; i++) {
copy->a31csi->sb_cqi[i] = malloc(sizeof(Protocol__FlexMsbCqi));
if (copy->a31csi->sb_cqi[i] == NULL) {
goto error;
}
protocol__flex_msb_cqi__init(copy->a31csi->sb_cqi[i]);
copy->a31csi->sb_cqi[i]->n_sb_cqi = original->a31csi->sb_cqi[i]->n_sb_cqi;
copy->a31csi->sb_cqi[i]->sb_cqi = (uint32_t *) malloc(sizeof(uint32_t) * copy->a31csi->sb_cqi[i]->n_sb_cqi);
for (j = 0; j < copy->a31csi->sb_cqi[i]->n_sb_cqi; j++) {
copy->a31csi->sb_cqi[i]->sb_cqi[j] = original->a31csi->sb_cqi[i]->sb_cqi[j];
}
}
break;
default:
goto error;
}
return copy;
error:
return NULL;
}
Protocol__FlexCellStatsReport * copy_cell_stats_report(Protocol__FlexCellStatsReport *original) {
Protocol__FlexCellStatsReport * copy = malloc(sizeof(Protocol__FlexCellStatsReport));
if(copy == NULL) {
goto error;
}
protocol__flex_cell_stats_report__init(copy);
copy->carrier_index = original->carrier_index;
copy->has_carrier_index = original->has_carrier_index;
copy->flags = original->flags;
copy->has_flags = original->has_flags;
if(copy->flags & PROTOCOL__FLEX_CELL_STATS_TYPE__FLCST_NOISE_INTERFERENCE) {
copy->noise_inter_report = copy_noise_inter_report(original->noise_inter_report);
}
return copy;
error:
return NULL;
}
Protocol__FlexNoiseInterferenceReport * copy_noise_inter_report(Protocol__FlexNoiseInterferenceReport *original) {
Protocol__FlexNoiseInterferenceReport *ni_report;
ni_report = malloc(sizeof(Protocol__FlexNoiseInterferenceReport));
if(ni_report == NULL) {
goto error;
}
protocol__flex_noise_interference_report__init(ni_report);
// Current frame and subframe number
ni_report->sfn_sf = original->sfn_sf;
ni_report->has_sfn_sf = original->sfn_sf;
// Received interference power in dbm
ni_report->rip = original->rip;
ni_report->has_rip = original->has_rip;
// Thermal noise power in dbm
ni_report->tnp = original->tnp;
ni_report->has_tnp = original->has_tnp;
return ni_report;
error:
return NULL;
}
int parse_mac_config(mid_t mod_id, yaml_parser_t *parser) {
yaml_event_t event;
int done = 0;
int sequence_started = 0;
int mapping_started = 0;
while (!done) {
if (!yaml_parser_parse(parser, &event))
goto error;
switch (event.type) {
case YAML_SEQUENCE_START_EVENT:
LOG_D(ENB_APP, "A sequence just started as expected\n");
sequence_started = 1;
break;
case YAML_SEQUENCE_END_EVENT:
LOG_D(ENB_APP, "A sequence ended\n");
sequence_started = 0;
break;
case YAML_MAPPING_START_EVENT:
if (!sequence_started) {
goto error;
}
LOG_D(ENB_APP, "A mapping started\n");
mapping_started = 1;
break;
case YAML_MAPPING_END_EVENT:
if (!mapping_started) {
goto error;
}
LOG_D(ENB_APP, "A mapping ended\n");
mapping_started = 0;
break;
case YAML_SCALAR_EVENT:
if (!mapping_started) {
goto error;
}
// Check the types of subsystems offered and handle their values accordingly
if (strcmp(event.data.scalar.value, "dl_scheduler") == 0) {
LOG_D(ENB_APP, "This is for the dl_scheduler subsystem\n");
// Call the proper handler
if (parse_dl_scheduler_config(mod_id, parser) == -1) {
LOG_D(ENB_APP, "An error occured\n");
goto error;
}
} else if (strcmp(event.data.scalar.value, "ul_scheduler") == 0) {
// Call the proper handler
LOG_D(ENB_APP, "This is for the ul_scheduler subsystem\n");
goto error;
// TODO
} else if (strcmp(event.data.scalar.value, "ra_scheduler") == 0) {
// Call the proper handler
// TODO
} else if (strcmp(event.data.scalar.value, "page_scheduler") == 0) {
// Call the proper handler
// TODO
} else {
// Unknown subsystem
goto error;
}
break;
default: // We expect nothing else at this level of the hierarchy
goto error;
}
done = (event.type == YAML_SEQUENCE_END_EVENT);
yaml_event_delete(&event);
}
return 0;
error:
yaml_event_delete(&event);
return -1;
}
int parse_dl_scheduler_config(mid_t mod_id, yaml_parser_t *parser) {
yaml_event_t event;
int done = 0;
int mapping_started = 0;
while (!done) {
if (!yaml_parser_parse(parser, &event))
goto error;
switch (event.type) {
// We are expecting a mapping (behavior and parameters)
case YAML_MAPPING_START_EVENT:
LOG_D(ENB_APP, "The mapping of the subsystem started\n");
mapping_started = 1;
break;
case YAML_MAPPING_END_EVENT:
LOG_D(ENB_APP, "The mapping of the subsystem ended\n");
mapping_started = 0;
break;
case YAML_SCALAR_EVENT:
if (!mapping_started) {
goto error;
}
// Check what key needs to be set
if (strcmp(event.data.scalar.value, "behavior") == 0) {
LOG_I(ENB_APP, "Time to set the behavior attribute\n");
yaml_event_delete(&event);
if (!yaml_parser_parse(parser, &event)) {
goto error;
}
if (event.type == YAML_SCALAR_EVENT) {
if (load_dl_scheduler_function(mod_id, event.data.scalar.value) == -1) {
goto error;
}
} else {
goto error;
}
} else if (strcmp(event.data.scalar.value, "parameters") == 0) {
LOG_D(ENB_APP, "Now it is time to set the parameters for this subsystem\n");
if (parse_dl_scheduler_parameters(mod_id, parser) == -1) {
goto error;
}
}
break;
default:
goto error;
}
done = (event.type == YAML_MAPPING_END_EVENT);
yaml_event_delete(&event);
}
return 0;
error:
yaml_event_delete(&event);
return -1;
}
int parse_dl_scheduler_parameters(mid_t mod_id, yaml_parser_t *parser) {
yaml_event_t event;
void *param;
int done = 0;
int mapping_started = 0;
while (!done) {
if (!yaml_parser_parse(parser, &event))
goto error;
switch (event.type) {
// We are expecting a mapping of parameters
case YAML_MAPPING_START_EVENT:
LOG_D(ENB_APP, "The mapping of the parameters started\n");
mapping_started = 1;
break;
case YAML_MAPPING_END_EVENT:
LOG_D(ENB_APP, "The mapping of the parameters ended\n");
mapping_started = 0;
break;
case YAML_SCALAR_EVENT:
if (!mapping_started) {
goto error;
}
// Check what key needs to be set
if (mac_agent_registered[mod_id]) {
LOG_D(ENB_APP, "Setting parameter %s\n", event.data.scalar.value);
param = dlsym(agent_mac_xface[mod_id]->dl_scheduler_loaded_lib,
event.data.scalar.value);
if (param == NULL) {
goto error;
}
apply_parameter_modification(param, parser);
} else {
goto error;
}
break;
default:
goto error;
}
done = (event.type == YAML_MAPPING_END_EVENT);
yaml_event_delete(&event);
}
return 0;
error:
yaml_event_delete(&event);
return -1;
}
int load_dl_scheduler_function(mid_t mod_id, const char *function_name) {
void *lib;
char lib_name[120];
char target[512];
snprintf(lib_name, sizeof(lib_name), "/%s.so", function_name);
strcpy(target, local_cache);
strcat(target, lib_name);
LOG_I(FLEXRAN_AGENT, "Opening pushed code: %s\n", target);
lib = dlopen(target, RTLD_NOW);
if (lib == NULL) {
LOG_I(FLEXRAN_AGENT, "Could not load library\n");
goto error;
}
LOG_I(FLEXRAN_AGENT, "Loading function: %s\n", function_name);
void *loaded_scheduler = dlsym(lib, function_name);
if (loaded_scheduler) {
if (mac_agent_registered[mod_id]) {
agent_mac_xface[mod_id]->flexran_agent_schedule_ue_spec = loaded_scheduler;
if (agent_mac_xface[mod_id]->dl_scheduler_loaded_lib != NULL) {
dlclose(agent_mac_xface[mod_id]->dl_scheduler_loaded_lib);
}
agent_mac_xface[mod_id]->dl_scheduler_loaded_lib = lib;
LOG_I(FLEXRAN_AGENT, "New DL UE scheduler: %s\n", function_name);
}
} else {
LOG_I(FLEXRAN_AGENT, "Scheduler could not be loaded\n");
}
return 0;
error:
return -1;
}
@@ -0,0 +1,106 @@
/*
* 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_*/
@@ -0,0 +1,180 @@
//'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;
}
@@ -0,0 +1,88 @@
//'syntax = "proto2";'
package protocol;
import "config_common.proto";
message flex_cell_config {
optional uint32 phy_cell_id = 1; // The PCI of this cell
optional uint32 cell_id = 2; // The PLMN cell id of this cell
optional uint32 pusch_hopping_offset = 3; // PUSCH resources in RBs for hopping
optional uint32 hopping_mode = 4; // One of the FLHM_* enum values
optional uint32 n_sb = 5; // The number of subbands
optional uint32 phich_resource = 6; // The number of REGs used for PHICH
// One of the FLPR_* enum values
optional uint32 phich_duration = 7; // One of the FLPD_* enum values
optional uint32 init_nr_PDCCH_OFDM_sym = 8; // See TS 36.211, section 6.9
optional flex_si_config si_config = 9; // The SI configuration
optional uint32 dl_bandwidth = 10; // The DL transmission bandwidth in RBs
optional uint32 ul_bandwidth = 11; // The UL transmission bandwidth in RBs
optional uint32 ul_cyclic_prefix_length = 13; // One of the FLUCPL_* enum values
optional uint32 dl_cyclic_prefix_length = 14; // One of the FLDCPL_* enum values
optional uint32 antenna_ports_count = 15; // Number of cell specific antenna ports
optional uint32 duplex_mode = 16; // One of the FLDM_* enum values
optional uint32 subframe_assignment = 17; // DL/UL subframe assignment. TDD only
optional uint32 special_subframe_patterns = 18; // TDD only. See TS 36.211, table 4.2.1
repeated uint32 mbsfn_subframe_config_rfperiod = 19; // The MBSFN radio frame period (Optional)
repeated uint32 mbsfn_subframe_config_rfoffset = 20; // The radio frame offset (Optional)
repeated uint32 mbsfn_subframe_config_sfalloc = 21; // Bitmap indicating the MBSFN subframes (Optional)
optional uint32 prach_config_index = 22; // See TS 36.211, section 5.7.1
optional uint32 prach_freq_offset = 23; // See TS 36.211, section 5.7.1
optional uint32 ra_response_window_size = 24; // The duration of the RA response window in SF
optional uint32 mac_contention_resolution_timer = 25; // Timer for RA
optional uint32 max_HARQ_Msg3Tx = 26; // See TS 36.321
optional uint32 n1PUCCH_AN = 27; // See TS 36.213, section 10.1
optional uint32 deltaPUCCH_shift = 28; // See TS 36.211, section 5.4
optional uint32 nRB_cqi = 29; // See TS 36.211, section 5.4
optional uint32 srs_subframe_config = 30; // See TS 36.211, table 5.5.3.3-1 and 2
optional uint32 srs_bw_config = 31; // See TS 36.211, section 5.5.3.2
optional uint32 srs_mac_up_pts = 32; // Boolean value. See TS 36.211, section 5.5.3.2. TDD only
optional uint32 enable_64QAM = 33; // One of the FLEQ_* enum values
optional uint32 carrier_index = 34; // Carrier component index
}
message flex_ue_config {
optional uint32 rnti = 1;
optional flex_drx_config drx_config = 2; // The DRX configuration (Optional)
optional uint32 time_alignment_timer = 3; // Timer in SF. Control the synchronization
// status of the UE, not the actual advance procedure
// See TS 36.321
optional uint32 meas_gap_config_pattern = 4; // Measurement gap configuration.
// One of the FLMGCP_* enum values
// See TS 36.133
optional uint32 meas_gap_config_sf_offset = 5; // Measurement gap offset if applicable
optional flex_sps_config sps_config = 6; // The SPS configuration (Optional)
optional flex_sr_config sr_config = 7; // The SR configuration (Optional)
optional flex_cqi_config cqi_config = 8; // The CQI configuration (Optional)
optional uint32 transmission_mode = 9; // The UE transmission mode
optional uint64 ue_aggregated_max_bitrate_UL = 10; // Aggregated bit-rate of non-gbr bearer
// per UE. See TS 36.413
optional uint64 ue_aggregated_max_bitrate_DL = 11; // Aggregated bit-rate of non-gbr bearer
// per UE. See TS 36.413
optional flex_ue_capabilities capabilities = 12;
optional uint32 ue_transmission_antenna = 13; // One of the FLUTA_* enum values
optional uint32 tti_bundling = 14; // Boolean value. See TS 36.321
optional uint32 max_HARQ_tx = 15; // The max HARQ retransmission for UL
optional uint32 beta_offset_ACK_index = 16; // See TS 36.213
optional uint32 beta_offset_RI_index = 17; // See TS 36.213
optional uint32 beta_offset_CQI_index = 18; // See TS 36.213
optional uint32 ack_nack_simultaneous_trans = 19;// Boolean. See TS 36.213
optional uint32 simultaneous_ack_nack_cqi = 20; // Boolean. See TS 36.213
optional uint32 aperiodic_cqi_rep_mode = 21; // One of the FLACRM_* enum values
optional uint32 tdd_ack_nack_feedback = 22; // One of the FLTANFM_* enum values
optional uint32 ack_nack_repetition_factor = 23;// See TS 36.213, section 10.1
optional uint32 extended_bsr_size = 24; // Boolean for extended BSR size
optional uint32 ca_support = 25; // Boolean. Support for carrier aggregation
optional uint32 cross_carrier_sched_support = 26; // Boolean value
optional uint32 pcell_carrier_index = 27; // Index of primary cell
repeated flex_scell_config scell_config = 28; // Secondary cells configuration
optional uint32 scell_deactivation_timer = 29;// Deactivation timer for secondary cell
}
message flex_lc_ue_config {
optional uint32 rnti = 1;
repeated flex_lc_config lc_config = 2; // A list of LC configurations for the given UE
}
@@ -0,0 +1,6 @@
//'syntax = "proto2";'
package protocol;
enum flex_control_delegation_type {
FLCDT_MAC_DL_UE_SCHEDULER = 1; // DL UE scheduler delegation
}
@@ -0,0 +1,58 @@
package protocol;
import "mac_primitives.proto";
//
// Body of UE DL MAC scheduling configuration info
//
message flex_dl_data {
optional uint32 rnti = 1;
optional flex_dl_dci dl_dci = 2;
repeated uint32 ce_bitmap = 3; // list of 2 MAC CEs, one for each TB
repeated flex_rlc_pdu rlc_pdu = 4; // list of parameters for the creation of RLC PDUs. One for each lcid
optional uint32 serv_cell_index = 5;
optional uint32 act_deact_ce = 6; //Hex content of MAC CE for Activation/Deactivation in CA
}
//
// Body of the RAR scheduler configuration
//
message flex_dl_rar {
optional uint32 rnti = 1;
optional uint32 grant = 2; // The 20-bit UL grant. TS 36.213, sec 6.2
optional flex_dl_dci rar_dci = 3;
optional uint32 carrier_index = 4; // The carrier index for the RAR
}
//
// Body of the paging/broadcast configuration message
//
message flex_dl_broadcast {
optional uint32 type = 1; // The FLBT_* values
optional uint32 index = 2; // Index of the broadcast message:
// 0 - SIB1,
// 1..31 - Six,
// 32..63 - PCCH (PCCH index obtained from flex_paging_info)
optional flex_dl_dci broad_dci = 3;
optional uint32 carrier_index = 4; // Index of the carrier for broadcast
}
//
// Body of the OFDM symbol count message
//
message flex_pdcch_ofdm_sym_count {
optional uint32 carrier_index = 1;
optional uint32 num_pdcch_ofdm_symbols = 2;
}
//
// Types of commands related enums
//
enum flex_broadcast_type {
FLBT_BCCH = 0;
FLBT_PCCH = 1;
}
+210
View File
@@ -0,0 +1,210 @@
//'syntax = "proto2";'
package protocol;
import "stats_messages.proto";
import "header.proto";
import "time_common.proto";
import "config_messages.proto";
import "controller_commands.proto";
import "control_delegation.proto";
message flexran_message {
optional flexran_direction msg_dir = 100;
oneof msg {
flex_hello hello_msg = 1;
flex_echo_request echo_request_msg = 2;
flex_echo_reply echo_reply_msg = 3;
flex_stats_request stats_request_msg = 4;
flex_stats_reply stats_reply_msg = 5;
flex_sf_trigger sf_trigger_msg = 6;
flex_ul_sr_info ul_sr_info_msg = 7;
flex_enb_config_request enb_config_request_msg = 8;
flex_enb_config_reply enb_config_reply_msg = 9;
flex_ue_config_request ue_config_request_msg = 10;
flex_ue_config_reply ue_config_reply_msg = 11;
flex_lc_config_request lc_config_request_msg = 12;
flex_lc_config_reply lc_config_reply_msg = 13;
flex_dl_mac_config dl_mac_config_msg = 14;
flex_ue_state_change ue_state_change_msg = 15;
flex_control_delegation control_delegation_msg = 16;
flex_agent_reconfiguration agent_reconfiguration_msg = 17;
}
}
enum flexran_direction {
//option allow_alias = true;
NOT_SET = 0;
INITIATING_MESSAGE = 1;
SUCCESSFUL_OUTCOME=2;
UNSUCCESSFUL_OUTCOME=3;
}
enum flexran_err {
option allow_alias = true;
// message errors
NO_ERR = 0;
MSG_DEQUEUING = -1;
MSG_ENQUEUING = -2;
MSG_DECODING = -3;
MSG_ENCODING = -4;
MSG_BUILD = -5;
MSG_NOT_SUPPORTED = -6;
MSG_NOT_HANDLED = -7;
MSG_NOT_VALIDATED = -8;
MSG_OUT_DATED = -9;
// other erros
UNEXPECTED = -100;
}
//
// Maintenance and discovery messages
//
message flex_hello {
optional flex_header header = 1;
}
message flex_echo_request {
optional flex_header header = 1;
extensions 100 to 199;
}
message flex_echo_reply {
optional flex_header header = 1;
extensions 100 to 199;
}
//
// Statistics request and reply message
//
message flex_stats_request {
optional flex_header header = 1;
optional flex_stats_type type = 2;
oneof body {
flex_complete_stats_request complete_stats_request = 3;
flex_cell_stats_request cell_stats_request = 4;
flex_ue_stats_request ue_stats_request = 5;
}
}
message flex_stats_reply {
optional flex_header header = 1;
repeated flex_ue_stats_report ue_report = 2;
repeated flex_cell_stats_report cell_report = 3;
}
//
// Time indication messages
//
message flex_sf_trigger {
optional flex_header header = 1;
optional uint32 sfn_sf = 2;
repeated flex_dl_info dl_info = 3;
repeated flex_ul_info ul_info = 4;
}
//
// Asynchronous messages
//
message flex_ul_sr_info {
optional flex_header header = 1;
optional uint32 sfn_sf = 2;
repeated uint32 rnti = 3;
}
//
// eNB configuration messages
//
message flex_enb_config_request {
optional flex_header header = 1;
}
message flex_enb_config_reply {
optional flex_header header = 1;
optional uint32 eNB_id = 2; // Unique id to distinguish the eNB
repeated flex_cell_config cell_config = 3;
}
message flex_ue_config_request {
optional flex_header header = 1;
}
message flex_ue_config_reply {
optional flex_header header = 1;
repeated flex_ue_config ue_config = 2;
}
message flex_lc_config_request {
optional flex_header header = 1;
}
message flex_lc_config_reply {
optional flex_header header = 1;
repeated flex_lc_ue_config lc_ue_config = 2;
}
//
// Controller command messages
//
message flex_dl_mac_config {
optional flex_header header = 1;
optional uint32 sfn_sf = 2;
repeated flex_dl_data dl_ue_data = 3;
repeated flex_dl_rar dl_rar = 4;
repeated flex_dl_broadcast dl_broadcast = 5;
repeated flex_pdcch_ofdm_sym_count ofdm_sym = 6; // OFDM symbol count for each CC
}
//
// UE state change message
//
message flex_ue_state_change {
optional flex_header header = 1;
optional uint32 type = 2; // One of the FLUESC_* values
optional flex_ue_config config = 3; // Body of the message (based on type)
}
//
// Control delegation message
//
message flex_control_delegation {
optional flex_header header = 1;
optional uint32 delegation_type = 2; // Bitmap of FLCDT_* flags
optional bytes payload = 3; // Byte array of shared lib containing the delegated functions
optional string name = 4; // The delegated functions names ordered based on bitmap flags
}
//
// Agent reconfiguration message
//
message flex_agent_reconfiguration {
optional flex_header header = 1;
optional string policy = 2; // The policy changes using YAML syntax in string format
}
// Extensions of the echo request and reply
// messages for carrying a latency value in ms
message flex_echo_request_latency {
extend flex_echo_request {
optional uint32 latency = 100;
}
}
message flex_echo_reply_latency {
extend flex_echo_reply {
optional uint32 latency = 100;
}
}
+43
View File
@@ -0,0 +1,43 @@
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;
}
@@ -0,0 +1,76 @@
package protocol;
//
// Message containing the DL DCI info
//
message flex_dl_dci {
optional uint32 rnti = 1;
optional uint32 res_alloc = 2; // Type of resource allocation
optional uint32 rb_bitmap = 3; // Bitmap for RB allocation
optional uint32 rb_shift = 4; // See TS 36.214, section 7.1.6.2
repeated uint32 tbs_size = 5; // The size of each TBS
repeated uint32 mcs = 6; // The MCS of each TB
repeated uint32 ndi = 7; // New data indicator of each TB
repeated uint32 rv = 8; // Redundancy version of each TB
optional uint32 cce_index = 9; // CCE index used to send the DCI
optional uint32 aggr_level = 10;
optional uint32 precoding_info = 11; // 2 antenna ports:0..6,
// 4 antenna ports:0..50
optional uint32 format = 12; // DCI format. A FLDCIF_* value
optional uint32 tpc = 13; // TS 36.213, sec 5.1.1.1
optional uint32 harq_process = 14; // HARQ process ID
optional uint32 dai = 15; // TDD only
optional uint32 vrb_format = 16; // One of the FLVRBF_* values
optional uint32 tb_swap = 17; // Boolean. TB to codeword swap flag
optional uint32 sps_release = 18; // Flag value
optional uint32 pdcch_order = 19;
optional uint32 preamble_index = 20; // Only valid if pdcch_order = 1
optional uint32 prach_mask_index = 21; // Only valid if pdcch_order = 1
optional uint32 n_gap = 22; // One of the FLNGV_* values
optional uint32 tbs_idx = 23; // The TBS index for Format 1A
optional uint32 dl_power_offset = 24; // For format 1D
optional uint32 pdcch_power_offset = 25; // DL PDCCH power boosting in dB
optional uint32 cif_present = 26; // Boolean. Indication of CIF field
optional uint32 cif = 27; // CIF for cross-carrier scheduling
}
//
// Messages related to the creation of RLC PDUs
//
message flex_rlc_pdu {
repeated flex_rlc_pdu_tb rlc_pdu_tb = 1; // list of parameters for the creation of RLC PDUs. One for each TB
}
message flex_rlc_pdu_tb {
optional uint32 logical_channel_id = 1;
optional uint32 size = 2; // Maximum RLC PDU to be created in bytes
}
//
// MAC content types related enums
//
enum flex_dci_format {
FLDCIF_1 = 0;
FLDCIF_1A = 1;
FLDCIF_1B = 2;
FLDCIF_1C = 3;
FLDCIF_1D = 4;
FLDCIF_2 = 5;
FLDCIF_2A = 6;
FLDCIF_2B = 7;
FLDCIF_3 = 8;
FLDCIF_3A = 9;
}
enum flex_vrb_format {
FLVRBF_LOCALIZED = 0;
FLVRBF_DISTRIBUTED = 1;
}
enum flex_ngap_val {
FLNGV_1 = 0;
FLNGV_2 = 1;
}
@@ -0,0 +1,182 @@
package protocol;
//
// UE related statistics
//
// RLC buffer status for a specific logical channel of a UE
message flex_rlc_bsr {
optional uint32 lc_id = 1;
optional uint32 tx_queue_size = 2;
optional uint32 tx_queue_hol_delay = 3;
optional uint32 retransmission_queue_size = 4;
optional uint32 retransmission_queue_hol_delay = 5;
optional uint32 status_pdu_size = 6;
}
// Flags for MAC Control Elements
enum flex_ce_type {
FLPCET_TA = 1;
FLPCET_DRX = 2;
FLPCET_CR = 4;
FLPCET_CA = 8;
}
// Types of DL CSI reports
enum flex_csi_type {
FLCSIT_P10 = 0;
FLCSIT_P11 = 1;
FLCSIT_P20 = 2;
FLCSIT_P21 = 3;
FLCSIT_A12 = 4;
FLCSIT_A22 = 5;
FLCSIT_A20 = 6;
FLCSIT_A30 = 7;
FLCSIT_A31 = 8;
}
// CSI type P10
message flex_csi_p10 {
optional uint32 wb_cqi = 1;
}
// CSI type P11
message flex_csi_p11 {
repeated uint32 wb_cqi = 1;
optional uint32 wb_pmi = 2;
}
// CSI type P20
message flex_csi_p20 {
optional uint32 wb_cqi = 1;
optional uint32 sb_cqi = 2;
optional uint32 bandwidth_part_index = 3;
optional uint32 sb_index = 4;
}
// CSI type P21
message flex_csi_p21 {
repeated uint32 wb_cqi = 1;
optional uint32 wb_pmi = 2;
repeated uint32 sb_cqi = 3;
optional uint32 badwidth_part_index = 4;
optional uint32 sb_index = 5;
}
// CSI type A12
message flex_csi_a12 {
repeated uint32 wb_cqi = 1;
repeated uint32 sb_pmi = 2;
}
// CSI type A22
message flex_csi_a22 {
repeated uint32 wb_cqi = 1;
repeated uint32 sb_cqi = 2;
optional uint32 wb_pmi = 3;
optional uint32 sb_pmi = 4;
repeated uint32 sb_list = 5;
}
// CSI type A20
message flex_csi_a20 {
optional uint32 wb_cqi = 1;
optional uint32 sb_cqi = 2;
repeated uint32 sb_list = 3;
}
// CSI type A30
message flex_csi_a30 {
optional uint32 wb_cqi = 1;
repeated uint32 sb_cqi = 2;
}
// CSI type A31
message flex_csi_a31 {
repeated uint32 wb_cqi = 1;
repeated flex_msb_cqi sb_cqi = 2;
optional uint32 wb_pmi = 3;
}
// The CQI for the M-preffered subband
message flex_msb_cqi {
repeated uint32 sb_cqi = 1;
}
// The CSI report of the UE for a specific servCellIndex
message flex_dl_csi {
optional uint32 serv_cell_index = 1;
optional uint32 ri = 2;
optional flex_csi_type type = 3;
oneof report {
flex_csi_p10 p10csi = 4;
flex_csi_p11 p11csi = 5;
flex_csi_p20 p20csi = 6;
flex_csi_p21 p21csi = 7;
flex_csi_a12 a12csi = 8;
flex_csi_a22 a22csi = 9;
flex_csi_a20 a20csi = 10;
flex_csi_a30 a30csi = 11;
flex_csi_a31 a31csi = 12;
}
}
// The full DL CQI report for all CC of a UE
message flex_dl_cqi_report {
optional uint32 sfn_sn = 1;
repeated flex_dl_csi csi_report = 2;
}
// Paging message info
message flex_paging_info {
optional uint32 paging_index = 1;
optional uint32 paging_message_size = 2;
optional uint32 paging_subframe = 3;
optional uint32 carrier_index = 4;
}
// Report for the paging buffer status
message flex_paging_buffer_report {
repeated flex_paging_info paging_info = 1;
}
// The type of UL CQI
enum flex_ul_cqi_type {
FLUCT_SRS = 0;
FLUCT_PUSCH = 1;
FLUCT_PUCCH_1 = 2;
FLUCT_PUCCH_2 = 3;
FLUCT_PRACH = 4;
}
// UL CQI report for a specific UE for a given report type
message flex_ul_cqi {
optional flex_ul_cqi_type type = 1;
repeated uint32 sinr = 2;
optional uint32 serv_cell_index = 3;
}
// Full UL CQI report for a specific UE
message flex_ul_cqi_report {
optional uint32 sfn_sn = 1;
repeated flex_ul_cqi cqi_meas = 2;
repeated flex_pucch_dbm pucch_dbm = 3;
}
message flex_pucch_dbm {
optional int32 p0_pucch_dbm = 1;
optional uint32 serv_cell_index = 2;
}
//
// Cell related statistics
//
// The UL noise and interference report for a UE
message flex_noise_interference_report {
optional uint32 sfn_sf = 1;
optional uint32 rip = 2;
optional uint32 tnp = 3;
optional int32 p0_nominal_pucch = 4;
}
@@ -0,0 +1,86 @@
package protocol;
//import "header.proto";
import "stats_common.proto";
//
// Bodies of statistics report requests
//
message flex_complete_stats_request {
optional flex_stats_report_freq report_frequency = 1;
optional uint32 sf = 2;
optional uint32 cell_report_flags = 3;
optional uint32 ue_report_flags = 4;
}
message flex_cell_stats_request {
repeated uint32 cell = 1;
optional uint32 flags = 2;
}
message flex_ue_stats_request {
repeated uint32 rnti = 1;
optional uint32 flags = 2;
}
//
// Bodies of statistics reports
//
// The full statistics report for a specific cell
message flex_cell_stats_report {
optional uint32 carrier_index = 1;
optional uint32 flags = 2;
optional flex_noise_interference_report noise_inter_report = 3;
}
// Statistics report for a specific UE
message flex_ue_stats_report {
optional uint32 rnti = 1;
optional uint32 flags = 2;
repeated uint32 bsr = 3;
optional uint32 phr = 4;
repeated flex_rlc_bsr rlc_report = 5;
optional uint32 pending_mac_ces = 6;
optional flex_dl_cqi_report dl_cqi_report = 7;
optional flex_paging_buffer_report pbr = 8;
optional flex_ul_cqi_report ul_cqi_report = 9;
}
//
// Types of statistics related enums
//
//Types of statistics requested by the controller
enum flex_stats_type {
FLST_COMPLETE_STATS = 0;
FLST_CELL_STATS = 1;
FLST_UE_STATS = 2;
}
// Report frequency for the requested statistics
enum flex_stats_report_freq {
FLSRF_ONCE = 0;
FLSRF_PERIODICAL = 1;
FLSRF_CONTINUOUS = 2;
FLSRF_OFF = 3;
}
// Flags for cell statistics
enum flex_cell_stats_type {
FLCST_NOISE_INTERFERENCE = 1;
}
// Flags for UE-related statistics
enum flex_ue_stats_type {
FLUST_BSR = 1;
FLUST_PRH = 2;
FLUST_RLC_BS = 4;
FLUST_MAC_CE_BS = 8;
FLUST_DL_CQI = 16;
FLUST_PBS = 32;
FLUST_UL_CQI = 64;
// To be extended with more types of stats
}
@@ -0,0 +1,29 @@
package protocol;
enum flex_harq_status {
FLHS_ACK = 0;
FLHS_NACK = 1;
FLHS_DTX = 2;
}
enum flex_reception_status {
FLRS_OK = 0;
FLRS_NOT_OK = 1;
FLRS_NOT_VALID = 2;
}
message flex_dl_info {
optional uint32 rnti = 1;
optional uint32 harq_process_id = 2;
repeated uint32 harq_status = 3;
optional uint32 serv_cell_index = 4;
}
message flex_ul_info {
optional uint32 rnti = 1;
repeated uint32 ul_reception = 2;
optional uint32 reception_status = 3;
optional uint32 tpc = 4;
optional uint32 serv_cell_index = 5;
}
+14 -2
View File
@@ -49,6 +49,10 @@
# include "gtpv1u_eNB_task.h"
# endif
#if defined(FLEXRAN_AGENT_SB_IF)
# include "flexran_agent.h"
#endif
extern unsigned char NB_eNB_INST;
#endif
@@ -287,7 +291,7 @@ void *eNB_app_task(void *args_p)
itti_mark_task_ready (TASK_ENB_APP);
# if defined(ENABLE_USE_MME)
# if defined(ENABLE_ITTI)
# if defined(OAI_EMU)
enb_nb = oai_emulation.info.nb_enb_local;
enb_id_start = oai_emulation.info.first_enb_local;
@@ -297,7 +301,7 @@ void *eNB_app_task(void *args_p)
"Last eNB index is greater or equal to maximum eNB index (%d/%d)!",
enb_id_end, NUMBER_OF_eNB_MAX);
# endif
# endif
# endif
enb_properties_p = enb_config_get();
@@ -310,6 +314,14 @@ void *eNB_app_task(void *args_p)
configure_rrc(enb_id, enb_properties_p);
}
#if defined (FLEXRAN_AGENT_SB_IF)
for (enb_id = enb_id_start; (enb_id < enb_id_end) ; enb_id++) {
printf("\n start enb agent %d\n", enb_id);
flexran_agent_start(enb_id, enb_properties_p);
}
#endif
# if defined(ENABLE_USE_MME)
/* Try to register each eNB */
registered_enb = 0;
+48
View File
@@ -190,6 +190,12 @@
#define ENB_CONFIG_STRING_ENB_IPV4_ADDR_FOR_S1U "ENB_IPV4_ADDRESS_FOR_S1U"
#define ENB_CONFIG_STRING_ENB_PORT_FOR_S1U "ENB_PORT_FOR_S1U"
#define ENB_CONFIG_STRING_NETWORK_CONTROLLER_CONFIG "NETWORK_CONTROLLER"
#define ENB_CONFIG_STRING_FLEXRAN_AGENT_INTERFACE_NAME "FLEXRAN_AGENT_INTERFACE_NAME"
#define ENB_CONFIG_STRING_FLEXRAN_AGENT_IPV4_ADDRESS "FLEXRAN_AGENT_IPV4_ADDRESS"
#define ENB_CONFIG_STRING_FLEXRAN_AGENT_PORT "FLEXRAN_AGENT_PORT"
#define ENB_CONFIG_STRING_FLEXRAN_AGENT_CACHE "FLEXRAN_AGENT_CACHE"
#define ENB_CONFIG_STRING_RRH_GW_CONFIG "rrh_gw_config"
#define ENB_CONFIG_STRING_RRH_GW_LOCAL_IF_NAME "local_if_name"
#define ENB_CONFIG_STRING_RRH_GW_LOCAL_ADDRESS "local_address"
@@ -335,6 +341,15 @@ void enb_config_display(void)
}
}
#if defined(FLEXRAN_AGENT_SB_IF)
printf( "\nFLEXRAN AGENT CONFIG : \n\n");
printf( "\tInterface name: \t%s:\n",enb_properties.properties[i]->flexran_agent_interface_name);
printf( "\tInterface IP Address: \t%s:\n",enb_properties.properties[i]->flexran_agent_ipv4_address);
printf( "\tInterface PORT: \t%d:\n\n",enb_properties.properties[i]->flexran_agent_port);
printf( "\tCache directory: \t%s:\n",enb_properties.properties[i]->flexran_agent_cache);
#endif
for (j=0; j< enb_properties.properties[i]->nb_cc; j++) {
// CC_ID node function/timing
printf( "\n\tnode_function for CC %d: \t%s:\n",j,eNB_functions[enb_properties.properties[i]->cc_node_function[j]]);
@@ -659,6 +674,10 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP)
char *address = NULL;
char *cidr = NULL;
char *astring = NULL;
char* flexran_agent_interface_name = NULL;
char* flexran_agent_ipv4_address = NULL;
libconfig_int flexran_agent_port = 0;
char* flexran_agent_cache = NULL;
libconfig_int otg_ue_id = 0;
char* otg_app_type = NULL;
char* otg_bg_traffic = NULL;
@@ -2456,6 +2475,35 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP)
}
}
}
// Network Controller
subsetting = config_setting_get_member (setting_enb, ENB_CONFIG_STRING_NETWORK_CONTROLLER_CONFIG);
if (subsetting != NULL) {
if ( (
config_setting_lookup_string( subsetting, ENB_CONFIG_STRING_FLEXRAN_AGENT_INTERFACE_NAME,
(const char **)&flexran_agent_interface_name)
&& config_setting_lookup_string( subsetting, ENB_CONFIG_STRING_FLEXRAN_AGENT_IPV4_ADDRESS,
(const char **)&flexran_agent_ipv4_address)
&& config_setting_lookup_int(subsetting, ENB_CONFIG_STRING_FLEXRAN_AGENT_PORT,
&flexran_agent_port)
&& config_setting_lookup_string( subsetting, ENB_CONFIG_STRING_FLEXRAN_AGENT_CACHE,
(const char **)&flexran_agent_cache)
)
) {
enb_properties.properties[enb_properties_index]->flexran_agent_interface_name = strdup(flexran_agent_interface_name);
cidr = flexran_agent_ipv4_address;
address = strtok(cidr, "/");
enb_properties.properties[enb_properties_index]->flexran_agent_ipv4_address = strdup(address);
/* if (address) {
IPV4_STR_ADDR_TO_INT_NWBO (address, enb_properties.properties[enb_properties_index]->flexran_agent_ipv4_address, "BAD IP ADDRESS FORMAT FOR eNB Agent !\n" );
}*/
enb_properties.properties[enb_properties_index]->flexran_agent_port = flexran_agent_port;
enb_properties.properties[enb_properties_index]->flexran_agent_cache = strdup(flexran_agent_cache);
}
}
// OTG _CONFIG
setting_otg = config_setting_get_member (setting_enb, ENB_CONF_STRING_OTG_CONFIG);
+4
View File
@@ -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;
+319
View File
@@ -0,0 +1,319 @@
/*
* 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.h
* \brief top level flexran agent receive thread and itti task
* \author Xenofon Foukas and Navid Nikaein
* \date 2016
* \version 0.1
*/
#include "flexran_agent_common.h"
#include "log.h"
#include "flexran_agent.h"
#include "flexran_agent_mac_defs.h"
#include "flexran_agent_extern.h"
#include "assertions.h"
#include "flexran_agent_net_comm.h"
#include "flexran_agent_async.h"
//#define TEST_TIMER
flexran_agent_instance_t flexran_agent[NUM_MAX_ENB];
char in_ip[40];
static uint16_t in_port;
char local_cache[40];
void *send_thread(void *args);
void *receive_thread(void *args);
pthread_t new_thread(void *(*f)(void *), void *b);
Protocol__FlexranMessage *flexran_agent_timeout(void* args);
int agent_task_created = 0;
/*
* enb agent task mainly wakes up the tx thread for periodic and oneshot messages to the controller
* and can interact with other itti tasks
*/
void *flexran_agent_task(void *args){
//flexran_agent_instance_t *d = (flexran_agent_instance_t *) args;
Protocol__FlexranMessage *msg;
void *data;
int size;
err_code_t err_code;
int priority;
MessageDef *msg_p = NULL;
const char *msg_name = NULL;
instance_t instance;
int result;
struct flexran_agent_timer_element_s * elem = NULL;
itti_mark_task_ready(TASK_FLEXRAN_AGENT);
do {
// Wait for a message
itti_receive_msg (TASK_FLEXRAN_AGENT, &msg_p);
DevAssert(msg_p != NULL);
msg_name = ITTI_MSG_NAME (msg_p);
instance = ITTI_MSG_INSTANCE (msg_p);
switch (ITTI_MSG_ID(msg_p)) {
case TERMINATE_MESSAGE:
itti_exit_task ();
break;
case MESSAGE_TEST:
LOG_I(FLEXRAN_AGENT, "Received %s\n", ITTI_MSG_NAME(msg_p));
break;
case TIMER_HAS_EXPIRED:
msg = flexran_agent_process_timeout(msg_p->ittiMsg.timer_has_expired.timer_id, msg_p->ittiMsg.timer_has_expired.arg);
if (msg != NULL){
data=flexran_agent_pack_message(msg,&size);
elem = get_timer_entry(msg_p->ittiMsg.timer_has_expired.timer_id);
if (flexran_agent_msg_send(elem->agent_id, FLEXRAN_AGENT_DEFAULT, data, size, priority)) {
err_code = PROTOCOL__FLEXRAN_ERR__MSG_ENQUEUING;
goto error;
}
LOG_D(FLEXRAN_AGENT,"sent message with size %d\n", size);
}
break;
default:
LOG_E(FLEXRAN_AGENT, "Received unexpected message %s\n", msg_name);
break;
}
result = itti_free (ITTI_MSG_ORIGIN_ID(msg_p), msg_p);
AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
continue;
error:
LOG_E(FLEXRAN_AGENT,"flexran_agent_task: error %d occured\n",err_code);
} while (1);
return NULL;
}
void *receive_thread(void *args) {
flexran_agent_instance_t *d = args;
void *data;
int size;
int priority;
err_code_t err_code;
Protocol__FlexranMessage *msg;
while (1) {
while (flexran_agent_msg_recv(d->enb_id, FLEXRAN_AGENT_DEFAULT, &data, &size, &priority) == 0) {
LOG_D(FLEXRAN_AGENT,"received message with size %d\n", size);
// Invoke the message handler
msg=flexran_agent_handle_message(d->enb_id, data, size);
free(data);
// check if there is something to send back to the controller
if (msg != NULL){
data=flexran_agent_pack_message(msg,&size);
if (flexran_agent_msg_send(d->enb_id, FLEXRAN_AGENT_DEFAULT, data, size, priority)) {
err_code = PROTOCOL__FLEXRAN_ERR__MSG_ENQUEUING;
goto error;
}
LOG_D(FLEXRAN_AGENT,"sent message with size %d\n", size);
}
}
}
return NULL;
error:
LOG_E(FLEXRAN_AGENT,"receive_thread: error %d occured\n",err_code);
return NULL;
}
/* utility function to create a thread */
pthread_t new_thread(void *(*f)(void *), void *b) {
pthread_t t;
pthread_attr_t att;
if (pthread_attr_init(&att)){
fprintf(stderr, "pthread_attr_init err\n");
exit(1);
}
struct sched_param sched_param_recv_thread;
sched_param_recv_thread.sched_priority = sched_get_priority_max(SCHED_FIFO) - 1;
pthread_attr_setschedparam(&att, &sched_param_recv_thread);
pthread_attr_setschedpolicy(&att, SCHED_FIFO);
if (pthread_attr_setdetachstate(&att, PTHREAD_CREATE_DETACHED)) {
fprintf(stderr, "pthread_attr_setdetachstate err\n");
exit(1);
}
if (pthread_create(&t, &att, f, b)) {
fprintf(stderr, "pthread_create err\n");
exit(1);
}
if (pthread_attr_destroy(&att)) {
fprintf(stderr, "pthread_attr_destroy err\n");
exit(1);
}
return t;
}
int channel_container_init = 0;
int flexran_agent_start(mid_t mod_id, const Enb_properties_array_t* enb_properties){
int channel_id;
flexran_set_enb_vars(mod_id, RAN_LTE_OAI);
flexran_agent[mod_id].enb_id = mod_id;
/*
* check the configuration
*/
if (enb_properties->properties[mod_id]->flexran_agent_cache != NULL) {
strncpy(local_cache, enb_properties->properties[mod_id]->flexran_agent_cache, sizeof(local_cache));
local_cache[sizeof(local_cache) - 1] = 0;
} else {
strcpy(local_cache, DEFAULT_FLEXRAN_AGENT_CACHE);
}
if (enb_properties->properties[mod_id]->flexran_agent_ipv4_address != NULL) {
strncpy(in_ip, enb_properties->properties[mod_id]->flexran_agent_ipv4_address, sizeof(in_ip) );
in_ip[sizeof(in_ip) - 1] = 0; // terminate string
} else {
strcpy(in_ip, DEFAULT_FLEXRAN_AGENT_IPv4_ADDRESS );
}
if (enb_properties->properties[mod_id]->flexran_agent_port != 0 ) {
in_port = enb_properties->properties[mod_id]->flexran_agent_port;
} else {
in_port = DEFAULT_FLEXRAN_AGENT_PORT ;
}
LOG_I(FLEXRAN_AGENT,"starting enb agent client for module id %d on ipv4 %s, port %d\n",
flexran_agent[mod_id].enb_id,
in_ip,
in_port);
/*
* Initialize the channel container
*/
if (!channel_container_init) {
flexran_agent_init_channel_container();
channel_container_init = 1;
}
/*Create the async channel info*/
flexran_agent_instance_t *channel_info = flexran_agent_async_channel_info(mod_id, in_ip, in_port);
/*Create a channel using the async channel info*/
channel_id = flexran_agent_create_channel((void *) channel_info,
flexran_agent_async_msg_send,
flexran_agent_async_msg_recv,
flexran_agent_async_release);
if (channel_id <= 0) {
goto error;
}
flexran_agent_channel_t *channel = get_channel(channel_id);
if (channel == NULL) {
goto error;
}
/*Register the channel for all underlying agents (use FLEXRAN_AGENT_MAX)*/
flexran_agent_register_channel(mod_id, channel, FLEXRAN_AGENT_MAX);
/*Example of registration for a specific agent(MAC):
*flexran_agent_register_channel(mod_id, channel, FLEXRAN_AGENT_MAC);
*/
/*Initialize the continuous MAC stats update mechanism*/
flexran_agent_init_cont_mac_stats_update(mod_id);
new_thread(receive_thread, &flexran_agent[mod_id]);
/*Initialize and register the mac xface. Must be modified later
*for more flexibility in agent management */
AGENT_MAC_xface *mac_agent_xface = (AGENT_MAC_xface *) malloc(sizeof(AGENT_MAC_xface));
flexran_agent_register_mac_xface(mod_id, mac_agent_xface);
/*
* initilize a timer
*/
flexran_agent_init_timer();
/*
* Initialize the mac agent
*/
flexran_agent_init_mac_agent(mod_id);
/*
* start the enb agent task for tx and interaction with the underlying network function
*/
if (!agent_task_created) {
if (itti_create_task (TASK_FLEXRAN_AGENT, flexran_agent_task, (void *) &flexran_agent[mod_id]) < 0) {
LOG_E(FLEXRAN_AGENT, "Create task for FlexRAN Agent failed\n");
return -1;
}
agent_task_created = 1;
}
LOG_I(FLEXRAN_AGENT,"client ends\n");
return 0;
error:
LOG_I(FLEXRAN_AGENT,"there was an error\n");
return 1;
}
Protocol__FlexranMessage *flexran_agent_timeout(void* args){
// flexran_agent_timer_args_t *timer_args = calloc(1, sizeof(*timer_args));
//memcpy (timer_args, args, sizeof(*timer_args));
flexran_agent_timer_args_t *timer_args = (flexran_agent_timer_args_t *) args;
LOG_I(FLEXRAN_AGENT, "flexran_agent %d timeout\n", timer_args->mod_id);
//LOG_I(FLEXRAN_AGENT, "eNB action %d ENB flags %d \n", timer_args->cc_actions,timer_args->cc_report_flags);
//LOG_I(FLEXRAN_AGENT, "UE action %d UE flags %d \n", timer_args->ue_actions,timer_args->ue_report_flags);
return NULL;
}
+46
View File
@@ -0,0 +1,46 @@
/*
* 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.h
* \brief top level flexran agent
* \author Navid Nikaein and Xenofon Foukas
* \date 2016
* \version 0.1
*/
#ifndef FLEXRAN_AGENT_H_
#define FLEXRAN_AGENT_H_
#include "enb_config.h" // for enb properties
#include "flexran_agent_common.h"
/* Initiation and termination of the eNodeB agent */
int flexran_agent_start(mid_t mod_id, const Enb_properties_array_t* enb_properties);
int flexran_agent_stop(mid_t mod_id);
/*
* enb agent task mainly wakes up the tx thread for periodic and oneshot messages to the controller
* and can interact with other itti tasks
*/
void *flexran_agent_task(void *args);
#endif
+99
View File
@@ -0,0 +1,99 @@
/*
* 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_async.c
* \brief channel implementation for async interface
* \author Xenofon Foukas
* \date 2016
* \version 0.1
*/
#include "flexran_agent_async.h"
#include "flexran_agent_defs.h"
#include "log.h"
flexran_agent_async_channel_t * flexran_agent_async_channel_info(mid_t mod_id, char *dst_ip, uint16_t dst_port) {
flexran_agent_async_channel_t *channel;
channel = (flexran_agent_async_channel_t *) malloc(sizeof(flexran_agent_channel_t));
if (channel == NULL)
goto error;
channel->enb_id = mod_id;
/*Create a socket*/
channel->link = new_link_client(dst_ip, dst_port);
if (channel->link == NULL) goto error;
LOG_I(FLEXRAN_AGENT,"starting enb agent client for module id %d on ipv4 %s, port %d\n",
channel->enb_id,
dst_ip,
dst_port);
/*
* create a message queue
*/
// Set size of queues statically for now
channel->send_queue = new_message_queue(500);
if (channel->send_queue == NULL) goto error;
channel->receive_queue = new_message_queue(500);
if (channel->receive_queue == NULL) goto error;
/*
* create a link manager
*/
channel->manager = create_link_manager(channel->send_queue, channel->receive_queue, channel->link);
if (channel->manager == NULL) goto error;
return channel;
error:
LOG_I(FLEXRAN_AGENT,"there was an error\n");
return 1;
}
int flexran_agent_async_msg_send(void *data, int size, int priority, void *channel_info) {
flexran_agent_async_channel_t *channel;
channel = (flexran_agent_channel_t *)channel_info;
return message_put(channel->send_queue, data, size, priority);
}
int flexran_agent_async_msg_recv(void **data, int *size, int *priority, void *channel_info) {
flexran_agent_async_channel_t *channel;
channel = (flexran_agent_async_channel_t *)channel_info;
return message_get(channel->receive_queue, data, size, priority);
}
void flexran_agent_async_release(flexran_agent_channel_t *channel) {
flexran_agent_async_channel_t *channel_info;
channel_info = (flexran_agent_async_channel_t *) channel->channel_info;
destroy_link_manager(channel_info->manager);
destroy_message_queue(channel_info->send_queue);
destroy_message_queue(channel_info->receive_queue);
close_link(channel_info->link);
free(channel_info);
}
+55
View File
@@ -0,0 +1,55 @@
/*
* 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_async.h
* \brief channel implementation for async interface
* \author Xenofon Foukas
* \date 2016
* \version 0.1
*/
#ifndef FLEXRAN_AGENT_ASYNC_H_
#define FLEXRAN_AGENT_ASYNC_H_
#include "flexran_agent_net_comm.h"
typedef struct {
mid_t enb_id;
socket_link_t *link;
message_queue_t *send_queue;
message_queue_t *receive_queue;
link_manager_t *manager;
} flexran_agent_async_channel_t;
/* Create a new channel for a given destination ip and destination port */
flexran_agent_async_channel_t * flexran_agent_async_channel_info(mid_t mod_id, char *dst_ip, uint16_t dst_port);
/* Send a message to the given channel */
int flexran_agent_async_msg_send(void *data, int size, int priority, void *channel_info);
/* Receive a message from a given channel */
int flexran_agent_async_msg_recv(void **data, int *size, int *priority, void *channel_info);
/* Release a channel */
void flexran_agent_async_release(flexran_agent_channel_t *channel);
#endif /*FLEXRAN_AGENT_ASYNC_H_*/
File diff suppressed because it is too large Load Diff
+496
View File
@@ -0,0 +1,496 @@
/*
* 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_common.h
* \brief common message primitves and utilities
* \author Xenofon Foukas, Mohamed Kassem and Navid Nikaein
* \date 2016
* \version 0.1
*/
#ifndef FLEXRAN_AGENT_COMMON_H_
#define FLEXRAN_AGENT_COMMON_H_
#include <time.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_defs.h"
#include "enb_config.h"
#include "LAYER2/MAC/extern.h"
#include "LAYER2/RLC/rlc.h"
# include "tree.h"
# include "intertask_interface.h"
# include "timer.h"
#define FLEXRAN_VERSION 0
typedef int (*flexran_agent_message_decoded_callback)(
mid_t mod_id,
const void *params,
Protocol__FlexranMessage **msg
);
typedef int (*flexran_agent_message_destruction_callback)(
Protocol__FlexranMessage *msg
);
/**********************************
* FlexRAN protocol messages helper
* functions and generic handlers
**********************************/
/* Helper functions for message (de)serialization */
int flexran_agent_serialize_message(Protocol__FlexranMessage *msg, void **buf, int *size);
int flexran_agent_deserialize_message(void *data, int size, Protocol__FlexranMessage **msg);
/* Serialize message and then destroy the input flexran msg. Should be called when protocol
message is created dynamically */
void * flexran_agent_pack_message(Protocol__FlexranMessage *msg,
uint32_t * size);
/* Calls destructor of the given message */
err_code_t flexran_agent_destroy_flexran_message(Protocol__FlexranMessage *msg);
/* Function to create the header for any FlexRAN protocol message */
int flexran_create_header(xid_t xid, Protocol__FlexType type, Protocol__FlexHeader **header);
/* Hello protocol message constructor and destructor */
int flexran_agent_hello(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg);
int flexran_agent_destroy_hello(Protocol__FlexranMessage *msg);
/* Echo request protocol message constructor and destructor */
int flexran_agent_echo_request(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg);
int flexran_agent_destroy_echo_request(Protocol__FlexranMessage *msg);
/* Echo reply protocol message constructor and destructor */
int flexran_agent_echo_reply(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg);
int flexran_agent_destroy_echo_reply(Protocol__FlexranMessage *msg);
/* eNodeB configuration reply message constructor and destructor */
int flexran_agent_enb_config_reply(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg);
int flexran_agent_destroy_enb_config_reply(Protocol__FlexranMessage *msg);
/* UE configuration reply message constructor and destructor */
int flexran_agent_ue_config_reply(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg);
int flexran_agent_destroy_ue_config_reply(Protocol__FlexranMessage *msg);
/* Logical channel reply configuration message constructor and destructor */
int flexran_agent_lc_config_reply(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg);
int flexran_agent_destroy_lc_config_reply(Protocol__FlexranMessage *msg);
/* eNodeB configuration request message constructor and destructor */
int flexran_agent_enb_config_request(mid_t mod_id, const void* params, Protocol__FlexranMessage **msg);
int flexran_agent_destroy_enb_config_request(Protocol__FlexranMessage *msg);
/* UE configuration request message constructor */
/* TODO: Need to define and implement destructor */
int flexran_agent_destroy_ue_config_request(Protocol__FlexranMessage *msg);
/* Logical channel configuration request message constructor */
/* TODO: Need to define and implement destructor */
int flexran_agent_destroy_lc_config_request(Protocol__FlexranMessage *msg);
/* UE state change message constructor and destructor */
int flexran_agent_ue_state_change(mid_t mod_id, uint32_t rnti, uint8_t state_change);
int flexran_agent_destroy_ue_state_change(Protocol__FlexranMessage *msg);
/* Control delegation message constructor and destructor */
int flexran_agent_control_delegation(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg);
int flexran_agent_destroy_control_delegation(Protocol__FlexranMessage *msg);
/* Policy reconfiguration message constructor and destructor */
int flexran_agent_reconfiguration(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg);
int flexran_agent_destroy_agent_reconfiguration(Protocol__FlexranMessage *msg);
/* FlexRAN protocol message dispatcher function */
Protocol__FlexranMessage* flexran_agent_handle_message (mid_t mod_id,
uint8_t *data,
uint32_t size);
/* Function to be used to send a message to a dispatcher once the appropriate event is triggered. */
Protocol__FlexranMessage *flexran_agent_handle_timed_task(void *args);
/****************************
* get generic info from RAN
****************************/
void flexran_set_enb_vars(mid_t mod_id, ran_name_t ran);
int flexran_get_current_time_ms (mid_t mod_id, int subframe_flag);
/*Return the current frame number
*Could be using implementation specific numbering of frames
*/
unsigned int flexran_get_current_frame(mid_t mod_id);
/*Return the current SFN (0-1023)*/
unsigned int flexran_get_current_system_frame_num(mid_t mod_id);
unsigned int flexran_get_current_subframe(mid_t mod_id);
/*Return the frame and subframe number in compact 16-bit format.
Bits 0-3 subframe, rest for frame. Required by FlexRAN protocol*/
uint16_t flexran_get_sfn_sf (mid_t mod_id);
/* Return a future frame and subframe number that is ahead_of_time
subframes later in compact 16-bit format. Bits 0-3 subframe,
rest for frame */
uint16_t flexran_get_future_sfn_sf(mid_t mod_id, int ahead_of_time);
/* Return the number of attached UEs */
int flexran_get_num_ues(mid_t mod_id);
/* Get the rnti of a UE with id ue_id */
int flexran_get_ue_crnti (mid_t mod_id, mid_t ue_id);
/* Get the RLC buffer status report of a ue for a designated
logical channel id */
int flexran_get_ue_bsr (mid_t mod_id, mid_t ue_id, lcid_t lcid);
/* Get power headroom of UE with id ue_id */
int flexran_get_ue_phr (mid_t mod_id, mid_t ue_id);
/* Get the UE wideband CQI */
int flexran_get_ue_wcqi (mid_t mod_id, mid_t ue_id);
/* Get the transmission queue size for a UE with a channel_id logical channel id */
int flexran_get_tx_queue_size(mid_t mod_id, mid_t ue_id, logical_chan_id_t channel_id);
/* Update the timing advance status (find out whether a timing advance command is required) */
int flexran_update_TA(mid_t mod_id, mid_t ue_id, int CC_id);
/* Return timing advance MAC control element for a designated cell and UE */
int flexran_get_MAC_CE_bitmap_TA(mid_t mod_id, mid_t ue_id, int CC_id);
/* Get the number of active component carriers for a specific UE */
int flexran_get_active_CC(mid_t mod_id, mid_t ue_id);
/* Get the rank indicator for a designated cell and UE */
int flexran_get_current_RI(mid_t mod_id, mid_t ue_id, int CC_id);
/* See TS 36.213, section 10.1 */
int flexran_get_n1pucch_an(mid_t mod_id, int CC_id);
/* See TS 36.211, section 5.4 */
int flexran_get_nRB_CQI(mid_t mod_id, int CC_id);
/* See TS 36.211, section 5.4 */
int flexran_get_deltaPUCCH_Shift(mid_t mod_id, int CC_id);
/* See TS 36.211, section 5.7.1 */
int flexran_get_prach_ConfigIndex(mid_t mod_id, int CC_id);
/* See TS 36.211, section 5.7.1 */
int flexran_get_prach_FreqOffset(mid_t mod_id, int CC_id);
/* See TS 36.321 */
int flexran_get_maxHARQ_Msg3Tx(mid_t mod_id, int CC_id);
/* Get the length of the UL cyclic prefix */
int flexran_get_ul_cyclic_prefix_length(mid_t mod_id, int CC_id);
/* Get the length of the DL cyclic prefix */
int flexran_get_dl_cyclic_prefix_length(mid_t mod_id, int CC_id);
/* Get the physical cell id of a cell */
int flexran_get_cell_id(mid_t mod_id, int CC_id);
/* See TS 36.211, section 5.5.3.2 */
int flexran_get_srs_BandwidthConfig(mid_t mod_id, int CC_id);
/* See TS 36.211, table 5.5.3.3-1 and 2 */
int flexran_get_srs_SubframeConfig(mid_t mod_id, int CC_id);
/* Boolean value. See TS 36.211,
section 5.5.3.2. TDD only */
int flexran_get_srs_MaxUpPts(mid_t mod_id, int CC_id);
/* Get number of DL resource blocks */
int flexran_get_N_RB_DL(mid_t mod_id, int CC_id);
/* Get number of UL resource blocks */
int flexran_get_N_RB_UL(mid_t mod_id, int CC_id);
/* Get number of resource block groups */
int flexran_get_N_RBG(mid_t mod_id, int CC_id);
/* Get DL/UL subframe assignment. TDD only */
int flexran_get_subframe_assignment(mid_t mod_id, int CC_id);
/* TDD only. See TS 36.211, table 4.2.1 */
int flexran_get_special_subframe_assignment(mid_t mod_id, int CC_id);
/* Get the duration of the random access response window in subframes */
int flexran_get_ra_ResponseWindowSize(mid_t mod_id, int CC_id);
/* Get timer used for random access */
int flexran_get_mac_ContentionResolutionTimer(mid_t mod_id, int CC_id);
/* Get type of duplex mode (FDD/TDD) */
int flexran_get_duplex_mode(mid_t mod_id, int CC_id);
/* Get the SI window length */
long flexran_get_si_window_length(mid_t mod_id, int CC_id);
/* Get the number of PDCCH symbols configured for the cell */
int flexran_get_num_pdcch_symb(mid_t mod_id, int CC_id);
/* See TS 36.213, sec 5.1.1.1 */
int flexran_get_tpc(mid_t mod_id, mid_t ue_id);
/* Get the first available HARQ process for a specific cell and UE during
a designated frame and subframe. Returns 0 for success. The id and the
status of the HARQ process are stored in id and status respectively */
int flexran_get_harq(const mid_t mod_id, const uint8_t CC_id, const mid_t ue_id,
const int frame, const uint8_t subframe, int *id, int *round);
/* Uplink power control management*/
int flexran_get_p0_pucch_dbm(mid_t mod_id, mid_t ue_id, int CC_id);
int flexran_get_p0_nominal_pucch(mid_t mod_id, int CC_id);
int flexran_get_p0_pucch_status(mid_t mod_id, mid_t ue_id, int CC_id);
int flexran_update_p0_pucch(mid_t mod_id, mid_t ue_id, int CC_id);
/*
* ************************************
* Get Messages for UE Configuration Reply
* ************************************
*/
/* Get timer in subframes. Controls the synchronization
status of the UE, not the actual timing
advance procedure. See TS 36.321 */
int flexran_get_time_alignment_timer(mid_t mod_id, mid_t ue_id);
/* Get measurement gap configuration. See TS 36.133 */
int flexran_get_meas_gap_config(mid_t mod_id, mid_t ue_id);
/* Get measurement gap configuration offset if applicable */
int flexran_get_meas_gap_config_offset(mid_t mod_id, mid_t ue_id);
/* DL aggregated bit-rate of non-gbr bearer
per UE. See TS 36.413 */
int flexran_get_ue_aggregated_max_bitrate_dl (mid_t mod_id, mid_t ue_id);
/* UL aggregated bit-rate of non-gbr bearer
per UE. See TS 36.413 */
int flexran_get_ue_aggregated_max_bitrate_ul (mid_t mod_id, mid_t ue_id);
/* Only half-duplex support. FDD
operation. Boolean value */
int flexran_get_half_duplex(mid_t ue_id);
/* Support of intra-subframe hopping.
Boolean value */
int flexran_get_intra_sf_hopping(mid_t ue_id);
/* UE support for type 2 hopping with
n_sb>1 */
int flexran_get_type2_sb_1(mid_t ue_id);
/* Get the UE category */
int flexran_get_ue_category(mid_t ue_id);
/* UE support for resource allocation
type 1 */
int flexran_get_res_alloc_type1(mid_t ue_id);
/* Get UE transmission mode */
int flexran_get_ue_transmission_mode(mid_t mod_id, mid_t ue_id);
/* Boolean value. See TS 36.321 */
int flexran_get_tti_bundling(mid_t mod_id, mid_t ue_id);
/* The max HARQ retransmission for UL.
See TS 36.321 */
int flexran_get_maxHARQ_TX(mid_t mod_id, mid_t ue_id);
/* See TS 36.213 */
int flexran_get_beta_offset_ack_index(mid_t mod_id, mid_t ue_id);
/* See TS 36.213 */
int flexran_get_beta_offset_ri_index(mid_t mod_id, mid_t ue_id);
/* See TS 36.213 */
int flexran_get_beta_offset_cqi_index(mid_t mod_id, mid_t ue_id);
/* Boolean. See TS36.213, Section 10.1 */
int flexran_get_simultaneous_ack_nack_cqi(mid_t mod_id, mid_t ue_id);
/* Boolean. See TS 36.213, Section 8.2 */
int flexran_get_ack_nack_simultaneous_trans(mid_t mod_id,mid_t ue_id);
/* Get aperiodic CQI report mode */
int flexran_get_aperiodic_cqi_rep_mode(mid_t mod_id,mid_t ue_id);
/* Get ACK/NACK feedback mode. TDD only */
int flexran_get_tdd_ack_nack_feedback(mid_t mod_id, mid_t ue_id);
/* See TS36.213, section 10.1 */
int flexran_get_ack_nack_repetition_factor(mid_t mod_id, mid_t ue_id);
/* Boolean. Extended buffer status report size */
int flexran_get_extended_bsr_size(mid_t mod_id, mid_t ue_id);
/* Get number of UE transmission antennas */
int flexran_get_ue_transmission_antenna(mid_t mod_id, mid_t ue_id);
/* Get logical channel group of a channel with id lc_id */
int flexran_get_lcg(mid_t ue_id, mid_t lc_id);
/* Get direction of logical channel with id lc_id */
int flexran_get_direction(mid_t ue_id, mid_t lc_id);
/*******************
* timer primitves
*******************/
#define TIMER_NULL -1
#define TIMER_TYPE_INVALIDE -2
#define TIMER_SETUP_FAILED -3
#define TIMER_REMOVED_FAILED -4
#define TIMER_ELEMENT_NOT_FOUND -5
/* Type of the callback executed when the timer expired */
typedef Protocol__FlexranMessage *(*flexran_agent_timer_callback_t)(void*);
typedef enum {
/* oneshot timer: */
FLEXRAN_AGENT_TIMER_TYPE_ONESHOT = 0x0,
/* periodic timer */
FLEXRAN_AGENT_TIMER_TYPE_PERIODIC = 0x1,
/* Inactive state: initial state for any timer. */
FLEXRAN_AGENT_TIMER_TYPE_EVENT_DRIVEN = 0x2,
/* Max number of states available */
FLEXRAN_AGENT_TIMER_TYPE_MAX,
} flexran_agent_timer_type_t;
typedef enum {
/* Inactive state: initial state for any timer. */
FLEXRAN_AGENT_TIMER_STATE_INACTIVE = 0x0,
/* Inactive state: initial state for any timer. */
FLEXRAN_AGENT_TIMER_STATE_ACTIVE = 0x1,
/* Inactive state: initial state for any timer. */
FLEXRAN_AGENT_TIMER_STATE_STOPPED = 0x2,
/* Max number of states available */
FLEXRAN_AGENT_TIMER_STATE_MAX,
} flexran_agent_timer_state_t;
typedef struct flexran_agent_timer_args_s{
mid_t mod_id;
Protocol__FlexranMessage *msg;
} flexran_agent_timer_args_t;
typedef struct flexran_agent_timer_element_s{
RB_ENTRY(flexran_agent_timer_element_s) entry;
agent_id_t agent_id;
instance_t instance;
flexran_agent_timer_type_t type;
flexran_agent_timer_state_t state;
uint32_t interval_sec;
uint32_t interval_usec;
long timer_id; /* Timer id returned by the timer API*/
xid_t xid; /*The id of the task as received by the controller
message*/
flexran_agent_timer_callback_t cb;
flexran_agent_timer_args_t *timer_args;
} flexran_agent_timer_element_t;
typedef struct flexran_agent_timer_instance_s{
RB_HEAD(flexran_agent_map, flexran_agent_timer_element_s) flexran_agent_head;
}flexran_agent_timer_instance_t;
err_code_t flexran_agent_init_timer(void);
/* Create a timer for some agent related event with id xid. Will store the id
of the generated timer in timer_id */
err_code_t flexran_agent_create_timer(uint32_t interval_sec,
uint32_t interval_usec,
agent_id_t agent_id,
instance_t instance,
uint32_t timer_type,
xid_t xid,
flexran_agent_timer_callback_t cb,
void* timer_args,
long *timer_id);
/* Destroy all existing timers */
err_code_t flexran_agent_destroy_timers(void);
/* Destroy the timer with the given timer_id */
err_code_t flexran_agent_destroy_timer(long timer_id);
/* Destroy the timer for task with id xid */
err_code_t flexran_agent_destroy_timer_by_task_id(xid_t xid);
/* Stop a timer */
err_code_t flexran_agent_stop_timer(long timer_id);
/* Restart the given timer */
err_code_t flexran_agent_restart_timer(long *timer_id);
/* Find the timer with the given timer_id */
struct flexran_agent_timer_element_s * get_timer_entry(long timer_id);
/* Obtain the protocol message stored in the given expired timer */
Protocol__FlexranMessage * flexran_agent_process_timeout(long timer_id, void* timer_args);
/* Comparator function comparing two timers. Decides the ordering of the timers */
int flexran_agent_compare_timer(struct flexran_agent_timer_element_s *a, struct flexran_agent_timer_element_s *b);
/*Specify a delay in nanoseconds to timespec and sleep until then*/
void flexran_agent_sleep_until(struct timespec *ts, int delay);
/* RB_PROTOTYPE is for .h files */
RB_PROTOTYPE(flexran_agent_map, flexran_agent_timer_element_s, entry, flexran_agent_compare_timer);
#endif
@@ -0,0 +1,392 @@
/*
* 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_common_internal.c
* \brief internal functions for common message primitves and utilities
* \author Xenofon Foukas
* \date 2016
* \version 0.1
*/
#include <stdlib.h>
#include <string.h>
#include "flexran_agent_common_internal.h"
#include "flexran_agent_mac_internal.h"
int apply_reconfiguration_policy(mid_t mod_id, const char *policy, size_t policy_length) {
yaml_parser_t parser;
yaml_event_t event;
int done = 0;
int mapping_started = 0;
LOG_I(ENB_APP, "Time to apply a new policy \n");
yaml_parser_initialize(&parser);
yaml_parser_set_input_string(&parser, policy, strlen(policy));
while (!done) {
if (!yaml_parser_parse(&parser, &event))
goto error;
switch (event.type) {
case YAML_STREAM_START_EVENT:
case YAML_STREAM_END_EVENT:
case YAML_DOCUMENT_START_EVENT:
case YAML_DOCUMENT_END_EVENT:
break;
case YAML_MAPPING_START_EVENT:
mapping_started = 1;
break;
case YAML_MAPPING_END_EVENT:
mapping_started = 0;
break;
case YAML_SCALAR_EVENT:
// Check the system name and call the proper handler
if (strcmp(event.data.scalar.value, "mac") == 0) {
LOG_D(ENB_APP, "This is intended for the mac system\n");
// Call the mac handler
if (parse_mac_config(mod_id, &parser) == -1) {
goto error;
}
} else if (strcmp(event.data.scalar.value, "rlc") == 0) {
// Call the RLC handler
LOG_D(ENB_APP, "This is intended for the rlc system\n");
// TODO : Just skip it for now
if (skip_system_section(&parser) == -1) {
goto error;
}
} else if (strcmp(event.data.scalar.value, "pdcp") == 0) {
// Call the PDCP handler
LOG_D(ENB_APP, "This is intended for the pdcp system\n");
// TODO : Just skip it for now
if (skip_system_section(&parser) == -1) {
goto error;
}
} else if (strcmp(event.data.scalar.value, "rrc") == 0) {
// Call the RRC handler
LOG_D(ENB_APP, "This is intended for the rrc system\n");
// TODO : Just skip it for now
if (skip_system_section(&parser) == -1) {
goto error;
}
} else {
goto error;
}
break;
default:
// We are not expecting to find any other type of event at this level
// of the hierarchy
yaml_event_delete(&event);
goto error;
}
done = (event.type == YAML_STREAM_END_EVENT);
yaml_event_delete(&event);
}
return 0;
error:
yaml_parser_delete(&parser);
return -1;
}
int skip_system_section(yaml_parser_t *parser) {
yaml_event_t event;
int done = 0;
int sequence_started = 0;
int mapping_started = 0;
while (!done) {
if (!yaml_parser_parse(parser, &event))
goto error;
switch (event.type) {
case YAML_SEQUENCE_START_EVENT:
LOG_D(ENB_APP, "A sequence just started as expected\n");
sequence_started = 1;
break;
case YAML_SEQUENCE_END_EVENT:
LOG_D(ENB_APP, "A sequence ended\n");
sequence_started = 0;
break;
case YAML_MAPPING_START_EVENT:
if (!sequence_started) {
goto error;
}
LOG_D(ENB_APP, "A mapping started\n");
mapping_started = 1;
break;
case YAML_MAPPING_END_EVENT:
if (!mapping_started) {
goto error;
}
LOG_D(ENB_APP, "A mapping ended\n");
mapping_started = 0;
break;
case YAML_SCALAR_EVENT:
if (!mapping_started) {
goto error;
}
// Entered a subsystem section. Let's skip it
if (skip_subsystem_section(parser) == -1) {
goto error;
}
}
done = (event.type == YAML_SEQUENCE_END_EVENT);
yaml_event_delete(&event);
}
return 0;
error:
yaml_event_delete(&event);
return -1;
}
int skip_subsystem_section(yaml_parser_t *parser) {
yaml_event_t event;
int done = 0;
int mapping_started = 0;
while (!done) {
if (!yaml_parser_parse(parser, &event))
goto error;
switch (event.type) {
case YAML_MAPPING_START_EVENT:
LOG_D(ENB_APP, "The mapping of the subsystem started\n");
mapping_started = 1;
break;
case YAML_MAPPING_END_EVENT:
LOG_D(ENB_APP, "The mapping of the subsystem ended\n");
mapping_started = 0;
break;
case YAML_SCALAR_EVENT:
if (!mapping_started) {
goto error;
}
// Check what key needs to be set
if (strcmp(event.data.scalar.value, "behavior") == 0) {
LOG_D(ENB_APP, "Skipping the behavior attribute\n");
yaml_event_delete(&event);
if (!yaml_parser_parse(parser, &event)) {
goto error;
}
if (event.type == YAML_SCALAR_EVENT) {
break;
} else {
goto error;
}
} else if (strcmp(event.data.scalar.value, "parameters") == 0) {
LOG_D(ENB_APP, "Skipping the parameters for this subsystem\n");
if (skip_subsystem_parameters_config(parser) == -1) {
goto error;
}
}
break;
default:
goto error;
}
done = (event.type == YAML_MAPPING_END_EVENT);
yaml_event_delete(&event);
}
return 0;
error:
yaml_event_delete(&event);
return -1;
}
int skip_subsystem_parameters_config(yaml_parser_t *parser) {
yaml_event_t event;
void *param;
int done = 0;
int mapping_started = 0;
while (!done) {
if (!yaml_parser_parse(parser, &event))
goto error;
switch (event.type) {
// We are expecting a mapping of parameters
case YAML_MAPPING_START_EVENT:
LOG_D(ENB_APP, "The mapping of the parameters started\n");
mapping_started = 1;
break;
case YAML_MAPPING_END_EVENT:
LOG_D(ENB_APP, "The mapping of the parameters ended\n");
mapping_started = 0;
break;
case YAML_SCALAR_EVENT:
if (!mapping_started) {
goto error;
}
// Check what key needs to be set
LOG_D(ENB_APP, "Skipping parameter %s\n", event.data.scalar.value);
if (skip_parameter_modification(parser) == -1 ) {
goto error;
}
break;
default:
goto error;
}
done = (event.type == YAML_MAPPING_END_EVENT);
yaml_event_delete(&event);
}
return 0;
error:
yaml_event_delete(&event);
return -1;
}
int skip_parameter_modification(yaml_parser_t *parser) {
yaml_event_t event;
int done = 0;
int is_array = 0;
int i = 0;
while (!done) {
if (!yaml_parser_parse(parser, &event)) {
goto error;
}
// Expecting either a scalar or a sequence
switch (event.type) {
case YAML_SEQUENCE_START_EVENT:
is_array = 1;
break;
case YAML_SCALAR_EVENT:
if ((strcmp(event.data.scalar.tag, YAML_INT_TAG) == 0) ||
(strcmp(event.data.scalar.tag, YAML_FLOAT_TAG) == 0) ||
(strcmp(event.data.scalar.tag, YAML_STR_TAG) == 0) ||
(strcmp(event.data.scalar.tag, YAML_BOOL_TAG) == 0)) {
// Do nothing
} else {
// No other type is supported at the moment, so it should be considered an error
// if we reach here
goto error;
}
if (is_array) {
i++;
} else {
done = 1;
}
break;
case YAML_SEQUENCE_END_EVENT:
done = 1;
break;
default:
goto error;
}
yaml_event_delete(&event);
}
return 0;
error:
yaml_event_delete(&event);
return -1;
}
int apply_parameter_modification(void *parameter, yaml_parser_t *parser) {
yaml_event_t event;
int done = 0;
int is_array = 0;
int i = 0;
char *endptr;
while (!done) {
if (!yaml_parser_parse(parser, &event)) {
goto error;
}
// Expecting either a scalar or a sequence
switch (event.type) {
case YAML_SEQUENCE_START_EVENT:
is_array = 1;
break;
case YAML_SCALAR_EVENT:
if (strcmp(event.data.scalar.tag, YAML_INT_TAG) == 0) {
((int *) parameter)[i] = strtol(event.data.scalar.value, &endptr, 10);
} else if (strcmp(event.data.scalar.tag, YAML_FLOAT_TAG) == 0) {
((float *) parameter)[i] = strtof(event.data.scalar.value, &endptr);
} else if (strcmp(event.data.scalar.tag, YAML_STR_TAG) == 0) {
strncpy(&((char *) parameter)[i], event.data.scalar.value, event.data.scalar.length);
} else if (strcmp(event.data.scalar.tag, YAML_BOOL_TAG) == 0) {
if (strcmp(event.data.scalar.value, "true") == 0) {
((int *) parameter)[i] = 1;
} else {
((int *) parameter)[i] = 0;
}
} else {
// No other type is supported at the moment, so it should be considered an error
// if we reach here
goto error;
}
if (is_array) {
i++;
} else {
done = 1;
}
break;
case YAML_SEQUENCE_END_EVENT:
done = 1;
break;
default:
goto error;
}
yaml_event_delete(&event);
}
return 0;
error:
yaml_event_delete(&event);
return -1;
}
@@ -0,0 +1,56 @@
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.0 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file flexran_agent_common_internal.h
* \brief internal agent functions for common message primitves and utilities
* \author Xenofon Foukas
* \date 2016
* \version 0.1
*/
#ifndef FLEXRAN_AGENT_COMMON_INTERNAL_H_
#define FLEXRAN_AGENT_COMMON_INTERNAL_H_
#include <yaml.h>
#include "flexran_agent_defs.h"
int apply_reconfiguration_policy(mid_t mod_id, const char *policy, size_t policy_length);
int apply_parameter_modification(void *parameter, yaml_parser_t *parser);
// This can be used when parsing for a specific system that is not yet implmeneted
// in order to skip its configuration, without affecting the rest
int skip_system_section(yaml_parser_t *parser);
// This can be used when parsing for a specific subsystem that is not yet implmeneted
// in order to skip its configuration, without affecting the rest
int skip_subsystem_section(yaml_parser_t *parser);
// This can be used when parsing for the parameters of a specific subsystem
//that is not yet implmeneted in order to skip its configuration, without affecting the rest
int skip_subsystem_parameters_config(yaml_parser_t *parser);
// This can be used when configuring the parameters of a specific subsystem
//that is not yet implmeneted in order to skip its configuration, without affecting the rest
int skip_parameter_modification(yaml_parser_t *parser);
#endif
+125
View File
@@ -0,0 +1,125 @@
/*
* 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_defs.h
* \brief FlexRAN agent common definitions
* \author Navid Nikaein and Xenofon Foukas
* \date 2016
* \version 0.1
*/
#ifndef FLEXRAN_AGENT_DEFS_H_
#define FLEXRAN_AGENT_DEFS_H_
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include "link_manager.h"
#define NUM_MAX_ENB 2
#define NUM_MAX_UE 2048
#define DEFAULT_FLEXRAN_AGENT_IPv4_ADDRESS "127.0.0.1"
#define DEFAULT_FLEXRAN_AGENT_PORT 2210
#define DEFAULT_FLEXRAN_AGENT_CACHE "/mnt/oai_agent_cache"
typedef enum {
FLEXRAN_AGENT_DEFAULT=0,
FLEXRAN_AGENT_PHY=1,
FLEXRAN_AGENT_MAC=2,
FLEXRAN_AGENT_RLC=3,
FLEXRAN_AGENT_PDCP=4,
FLEXRAN_AGENT_RRC=5,
FLEXRAN_AGENT_S1AP=6,
FLEXRAN_AGENT_GTP=7,
FLEXRAN_AGENT_X2AP=8,
FLEXRAN_AGENT_MAX=9,
} agent_id_t;
typedef enum {
/* no action */
FLEXRAN_AGENT_ACTION_NONE = 0x0,
/* send action */
FLEXRAN_AGENT_ACTION_SEND = 0x1,
/* apply action */
FLEXRAN_AGENT_ACTION_APPLY = 0x2,
/* clear action */
FLEXRAN_AGENT_ACTION_CLEAR = 0x4,
/* write action */
FLEXRAN_AGENT_ACTION_WRITE = 0x8,
/* filter action */
FLEXRAN_AGENT_ACTION_FILTER = 0x10,
/* preprocess action */
FLEXRAN_AGENT_ACTION_PREPROCESS = 0x20,
/* meter action */
FLEXRAN_AGENT_ACTION_METER = 0x40,
/* Max number of states available */
FLEXRAN_AGENT_ACTION_MAX = 0x7f,
} agent_action_t;
typedef enum {
RAN_LTE_OAI= 0,
/* Max number of states available */
RAN_NAME_MAX = 0x7f,
} ran_name_t;
typedef uint8_t xid_t;
typedef uint8_t mid_t; // module or enb id
typedef uint8_t lcid_t;
typedef int32_t err_code_t;
typedef struct {
/* general info */
/* stats */
uint32_t total_rx_msg;
uint32_t total_tx_msg;
uint32_t rx_msg[NUM_MAX_ENB];
uint32_t tx_msg[NUM_MAX_ENB];
} flexran_agent_info_t;
typedef struct {
mid_t enb_id;
flexran_agent_info_t agent_info;
} flexran_agent_instance_t;
#endif
+48
View File
@@ -0,0 +1,48 @@
/*
* 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 ENB_APP/extern.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_EXTERN_H__
#define __FLEXRAN_AGENT_EXTERN_H__
#include "flexran_agent_defs.h"
#include "flexran_agent_mac_defs.h"
//extern msg_context_t shared_ctxt[NUM_MAX_ENB][FLEXRAN_AGENT_MAX];
/* full path of the local cache for storing VSFs */
extern char local_cache[40];
/* Control module interface for the communication of the MAC Control Module with the agent */
extern AGENT_MAC_xface *agent_mac_xface[NUM_MAX_ENB];
/* Flag indicating whether the VSFs for the MAC control module have been registered */
extern unsigned int mac_agent_registered[NUM_MAX_ENB];
#endif
+189
View File
@@ -0,0 +1,189 @@
/*
* 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_handler.c
* \brief FlexRAN agent tx and rx message handler
* \author Xenofon Foukas and Navid Nikaein
* \date 2016
* \version 0.1
*/
#include "flexran_agent_common.h"
#include "flexran_agent_mac.h"
#include "log.h"
#include "assertions.h"
flexran_agent_message_decoded_callback agent_messages_callback[][3] = {
{flexran_agent_hello, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_HELLO_MSG*/
{flexran_agent_echo_reply, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_ECHO_REQUEST_MSG*/
{0, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_ECHO_REPLY_MSG*/ //Must add handler when receiving echo reply
{flexran_agent_mac_handle_stats, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_STATS_REQUEST_MSG*/
{0, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_STATS_REPLY_MSG*/
{0, 0, 0}, /*PROTOCOK__FLEXRAN_MESSAGE__MSG_SF_TRIGGER_MSG*/
{0, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_UL_SR_INFO_MSG*/
{flexran_agent_enb_config_reply, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_ENB_CONFIG_REQUEST_MSG*/
{0, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_ENB_CONFIG_REPLY_MSG*/
{flexran_agent_ue_config_reply, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_UE_CONFIG_REQUEST_MSG*/
{0, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_UE_CONFIG_REPLY_MSG*/
{flexran_agent_lc_config_reply, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_LC_CONFIG_REQUEST_MSG*/
{0, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_LC_CONFIG_REPLY_MSG*/
{flexran_agent_mac_handle_dl_mac_config, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_DL_MAC_CONFIG_MSG*/
{0, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_UE_STATE_CHANGE_MSG*/
{flexran_agent_control_delegation, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_CONTROL_DELEGATION_MSG*/
{flexran_agent_reconfiguration, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_AGENT_RECONFIGURATION_MSG*/
};
flexran_agent_message_destruction_callback message_destruction_callback[] = {
flexran_agent_destroy_hello,
flexran_agent_destroy_echo_request,
flexran_agent_destroy_echo_reply,
flexran_agent_mac_destroy_stats_request,
flexran_agent_mac_destroy_stats_reply,
flexran_agent_mac_destroy_sf_trigger,
flexran_agent_mac_destroy_sr_info,
flexran_agent_destroy_enb_config_request,
flexran_agent_destroy_enb_config_reply,
flexran_agent_destroy_ue_config_request,
flexran_agent_destroy_ue_config_reply,
flexran_agent_destroy_lc_config_request,
flexran_agent_destroy_lc_config_reply,
flexran_agent_mac_destroy_dl_config,
flexran_agent_destroy_ue_state_change,
flexran_agent_destroy_control_delegation,
flexran_agent_destroy_agent_reconfiguration,
};
static const char *flexran_agent_direction2String[] = {
"", /* not_set */
"originating message", /* originating message */
"successfull outcome", /* successfull outcome */
"unsuccessfull outcome", /* unsuccessfull outcome */
};
Protocol__FlexranMessage* flexran_agent_handle_message (mid_t mod_id,
uint8_t *data,
uint32_t size){
Protocol__FlexranMessage *decoded_message, *reply_message;
err_code_t err_code;
DevAssert(data != NULL);
if (flexran_agent_deserialize_message(data, size, &decoded_message) < 0) {
err_code= PROTOCOL__FLEXRAN_ERR__MSG_DECODING;
goto error;
}
if ((decoded_message->msg_case > sizeof(agent_messages_callback) / (3 * sizeof(flexran_agent_message_decoded_callback))) ||
(decoded_message->msg_dir > PROTOCOL__FLEXRAN_DIRECTION__UNSUCCESSFUL_OUTCOME)){
err_code= PROTOCOL__FLEXRAN_ERR__MSG_NOT_HANDLED;
goto error;
}
if (agent_messages_callback[decoded_message->msg_case-1][decoded_message->msg_dir-1] == NULL) {
err_code= PROTOCOL__FLEXRAN_ERR__MSG_NOT_SUPPORTED;
goto error;
}
err_code = ((*agent_messages_callback[decoded_message->msg_case-1][decoded_message->msg_dir-1])(mod_id, (void *) decoded_message, &reply_message));
if ( err_code < 0 ){
goto error;
} else if (err_code == 1) { //If err_code > 1, we do not want to dispose the message yet
protocol__flexran_message__free_unpacked(decoded_message, NULL);
}
return reply_message;
error:
LOG_E(FLEXRAN_AGENT,"errno %d occured\n",err_code);
return NULL;
}
void * flexran_agent_pack_message(Protocol__FlexranMessage *msg,
uint32_t * size){
void * buffer;
err_code_t err_code = PROTOCOL__FLEXRAN_ERR__NO_ERR;
if (flexran_agent_serialize_message(msg, &buffer, size) < 0 ) {
err_code = PROTOCOL__FLEXRAN_ERR__MSG_ENCODING;
goto error;
}
// free the msg --> later keep this in the data struct and just update the values
//TODO call proper destroy function
err_code = ((*message_destruction_callback[msg->msg_case-1])(msg));
DevAssert(buffer !=NULL);
LOG_D(FLEXRAN_AGENT,"Serilized the enb mac stats reply (size %d)\n", *size);
return buffer;
error :
LOG_E(FLEXRAN_AGENT,"errno %d occured\n",err_code);
return NULL;
}
Protocol__FlexranMessage *flexran_agent_handle_timed_task(void *args) {
err_code_t err_code;
flexran_agent_timer_args_t *timer_args = (flexran_agent_timer_args_t *) args;
Protocol__FlexranMessage *timed_task, *reply_message;
timed_task = timer_args->msg;
err_code = ((*agent_messages_callback[timed_task->msg_case-1][timed_task->msg_dir-1])(timer_args->mod_id, (void *) timed_task, &reply_message));
if ( err_code < 0 ){
goto error;
}
return reply_message;
error:
LOG_E(FLEXRAN_AGENT,"errno %d occured\n",err_code);
return NULL;
}
Protocol__FlexranMessage* flexran_agent_process_timeout(long timer_id, void* timer_args){
struct flexran_agent_timer_element_s *found = get_timer_entry(timer_id);
if (found == NULL ) goto error;
LOG_I(FLEXRAN_AGENT, "Found the entry (%p): timer_id is 0x%lx 0x%lx\n", found, timer_id, found->timer_id);
if (timer_args == NULL)
LOG_W(FLEXRAN_AGENT,"null timer args\n");
return found->cb(timer_args);
error:
LOG_E(FLEXRAN_AGENT, "can't get the timer element\n");
return TIMER_ELEMENT_NOT_FOUND;
}
err_code_t flexran_agent_destroy_flexran_message(Protocol__FlexranMessage *msg) {
return ((*message_destruction_callback[msg->msg_case-1])(msg));
}
+192
View File
@@ -0,0 +1,192 @@
/*
* 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_net_comm.c
* \brief FlexRAN agent network interface abstraction
* \author Xenofon Foukas
* \date 2016
* \version 0.1
*/
#include "flexran_agent_net_comm.h"
#include "log.h"
flexran_agent_channel_t *agent_channel[NUM_MAX_ENB][FLEXRAN_AGENT_MAX];
flexran_agent_channel_instance_t channel_instance;
int flexran_agent_channel_id = 0;
int flexran_agent_msg_send(mid_t mod_id, agent_id_t agent_id, void *data, int size, int priority) {
/*Check if agent id is valid*/
if (agent_id >= FLEXRAN_AGENT_MAX || agent_id < 0) {
goto error;
}
flexran_agent_channel_t *channel;
channel = agent_channel[mod_id][agent_id];
/*Check if agent has a channel registered*/
if (channel == NULL) {
goto error;
}
return channel->msg_send(data, size, priority, channel->channel_info);
error:
LOG_E(FLEXRAN_AGENT, "No channel registered for agent with id %d\n", agent_id);
return -1;
}
int flexran_agent_msg_recv(mid_t mod_id, agent_id_t agent_id, void **data, int *size, int *priority) {
/*Check if agent id is valid*/
if (agent_id >= FLEXRAN_AGENT_MAX || agent_id < 0) {
goto error;
}
flexran_agent_channel_t *channel;
channel = agent_channel[mod_id][agent_id];
/*Check if agent has a channel registered*/
if (channel == NULL) {
goto error;
}
return channel->msg_recv(data, size, priority, channel->channel_info);
error:
LOG_E(FLEXRAN_AGENT, "No channel registered for agent with id %d\n", agent_id);
return -1;
}
int flexran_agent_register_channel(mid_t mod_id, flexran_agent_channel_t *channel, agent_id_t agent_id) {
int i;
if (channel == NULL) {
return -1;
}
if (agent_id == FLEXRAN_AGENT_MAX) {
for (i = 0; i < FLEXRAN_AGENT_MAX; i++) {
agent_channel[mod_id][i] = channel;
}
} else {
agent_channel[mod_id][agent_id] = channel;
}
return 0;
}
void flexran_agent_unregister_channel(mid_t mod_id, agent_id_t agent_id) {
int i;
if (agent_id == FLEXRAN_AGENT_MAX) {
for (i = 0; i < FLEXRAN_AGENT_MAX; i++) {
agent_channel[mod_id][i] = NULL;
}
} else {
agent_channel[mod_id][agent_id] = NULL;
}
}
int flexran_agent_create_channel(void *channel_info,
int (*msg_send)(void *data, int size, int priority, void *channel_info),
int (*msg_recv)(void **data, int *size, int *priority, void *channel_info),
void (*release)(flexran_agent_channel_t *channel)) {
int channel_id = ++flexran_agent_channel_id;
flexran_agent_channel_t *channel = (flexran_agent_channel_t *) malloc(sizeof(flexran_agent_channel_t));
channel->channel_id = channel_id;
channel->channel_info = channel_info;
channel->msg_send = msg_send;
channel->msg_recv = msg_recv;
channel->release = release;
/*element should be a real pointer*/
RB_INSERT(flexran_agent_channel_map, &channel_instance.flexran_agent_head, channel);
LOG_I(FLEXRAN_AGENT,"Created a new channel with id 0x%lx\n", channel->channel_id);
return channel_id;
}
int flexran_agent_destroy_channel(int channel_id) {
int i, j;
/*Check to see if channel exists*/
struct flexran_agent_channel_s *e = NULL;
struct flexran_agent_channel_s search;
memset(&search, 0, sizeof(struct flexran_agent_channel_s));
e = RB_FIND(flexran_agent_channel_map, &channel_instance.flexran_agent_head, &search);
if (e == NULL) {
return -1;
}
/*Unregister the channel from all agents*/
for (i = 0; i < NUM_MAX_ENB; i++) {
for (j = 0; j < FLEXRAN_AGENT_MAX; j++) {
if (agent_channel[i][j] != NULL) {
if (agent_channel[i][j]->channel_id == e->channel_id) {
agent_channel[i][j] == NULL;
}
}
}
}
/*Remove the channel from the tree and free memory*/
RB_REMOVE(flexran_agent_channel_map, &channel_instance.flexran_agent_head, e);
e->release(e);
free(e);
return 0;
}
err_code_t flexran_agent_init_channel_container(void) {
int i, j;
LOG_I(FLEXRAN_AGENT, "init RB tree for channel container\n");
RB_INIT(&channel_instance.flexran_agent_head);
for (i = 0; i < NUM_MAX_ENB; i++) {
for (j = 0; j < FLEXRAN_AGENT_MAX; j++) {
agent_channel[i][j] == NULL;
}
}
return 0;
}
RB_GENERATE(flexran_agent_channel_map, flexran_agent_channel_s, entry, flexran_agent_compare_channel);
int flexran_agent_compare_channel(struct flexran_agent_channel_s *a, struct flexran_agent_channel_s *b) {
if (a->channel_id < b->channel_id) return -1;
if (a->channel_id > b->channel_id) return 1;
// equal timers
return 0;
}
flexran_agent_channel_t * get_channel(int channel_id) {
struct flexran_agent_channel_s search;
memset(&search, 0, sizeof(struct flexran_agent_channel_s));
search.channel_id = channel_id;
return RB_FIND(flexran_agent_channel_map, &channel_instance.flexran_agent_head, &search);
}
+81
View File
@@ -0,0 +1,81 @@
/*
* 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_net_comm.h
* \brief FlexRAN agent network interface abstraction
* \autho Xenofon Foukas
* \date 2016
* \version 0.1
*/
#ifndef FLEXRAN_AGENT_NET_COMM_H_
#define FLEXRAN_AGENT_NET_COMM_H_
#include "flexran_agent_defs.h"
#include "tree.h"
/*Channel related information used for Tx/Rx of protocol messages*/
typedef struct flexran_agent_channel_s {
RB_ENTRY(flexran_agent_channel_s) entry;
int channel_id;
void *channel_info;
/*Callbacks for channel message Tx and Rx*/
int (*msg_send)(void *data, int size, int priority, void *channel_info);
int (*msg_recv)(void **data, int *size, int *priority, void *channel_info);
void (*release)(struct flexran_agent_channel_s *channel);
} flexran_agent_channel_t;
typedef struct flexran_agent_channel_instance_s{
RB_HEAD(flexran_agent_channel_map, flexran_agent_channel_s) flexran_agent_head;
} flexran_agent_channel_instance_t;
/*Send and receive messages using the channel registered for a specific agent*/
int flexran_agent_msg_send(mid_t mod_id, agent_id_t agent_id, void *data, int size, int priority);
int flexran_agent_msg_recv(mid_t mod_id, agent_id_t agent_id, void **data, int *size, int *priority);
/*Register a channel to an agent. Use FLEXRAN_AGENT_MAX to register the
*same channel to all agents*/
int flexran_agent_register_channel(mid_t mod_id, flexran_agent_channel_t *channel, agent_id_t agent_id);
/*Unregister the current channel of an agent. Use FLEXRAN_AGENT_MAX to unregister all channels*/
void flexran_agent_unregister_channel(mid_t mod_id, agent_id_t agent_id);
/*Create a new channel. Returns the id of the new channel or negative number otherwise*/
int flexran_agent_create_channel(void *channel_info,
int (*msg_send)(void *data, int size, int priority, void *channel_info),
int (*msg_recv)(void **data, int *size, int *priority, void *channel_info),
void (*release)(flexran_agent_channel_t *channel));
/*Unregister a channel from all agents and destroy it. Returns 0 in case of success*/
int flexran_agent_destroy_channel(int channel_id);
/*Return an agent communication channel based on its id*/
flexran_agent_channel_t * get_channel(int channel_id);
/*Should be called before performing any channel operations*/
err_code_t flexran_agent_init_channel_container(void);
int flexran_agent_compare_channel(struct flexran_agent_channel_s *a, struct flexran_agent_channel_s *b);
/* RB_PROTOTYPE is for .h files */
RB_PROTOTYPE(flexran_agent_channel_map, flexran_agent_channel_s, entry, flexran_agent_compare_channel);
#endif /*FLEXRAN_AGENT_COMM_H_*/
@@ -0,0 +1,304 @@
/*
* 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_task_manager.h
* \brief Implementation of scheduled tasks manager for the FlexRAN agent
* \author Xenofon Foukas
* \date January 2016
* \version 0.1
* \email: x.foukas@sms.ed.ac.uk
* @ingroup _mac
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "flexran_agent_task_manager.h"
#include "flexran_agent_common.c"
/* Util macros */
#define LEFT(x) (2 * (x) + 1)
#define RIGHT(x) (2 * (x) + 2)
#define PARENT(x) ((x - 1) / 2)
flexran_agent_task_t *flexran_agent_task_create(Protocol__FlexranMessage *msg,
uint16_t frame_num, uint8_t subframe_num) {
flexran_agent_task_t *task = NULL;
task = malloc(sizeof(flexran_agent_task_t));
if (task == NULL)
goto error;
task->frame_num = frame_num;
task->subframe_num = subframe_num;
task->task = msg;
return task;
error:
return NULL;
}
void flexran_agent_task_destroy(flexran_agent_task_t *task) {
if (task == NULL)
return;
/* TODO: must free the task properly */
free(task->task);
free(task);
}
flexran_agent_task_queue_t *flexran_agent_task_queue_init(mid_t mod_id, size_t capacity,
int (*cmp)(mid_t mod_id, const flexran_agent_task_t *t1,
const flexran_agent_task_t *t2)) {
flexran_agent_task_queue_t *queue = NULL;
queue = malloc(sizeof(flexran_agent_task_queue_t));
if (queue == NULL)
goto error;
/* If no comparator was given, use the default one */
if (cmp == NULL)
queue->cmp = _flexran_agent_task_queue_cmp;
else
queue->cmp = cmp;
queue->mod_id = mod_id;
queue->first_frame = 0;
queue->first_subframe = 0;
queue->task = malloc(capacity * sizeof(flexran_agent_task_t *));
if (queue->task == NULL)
goto error;
queue->count = 0;
queue->capacity = capacity;
queue->mutex = malloc(sizeof(pthread_mutex_t));
if (queue->mutex == NULL)
goto error;
if (pthread_mutex_init(queue->mutex, NULL))
goto error;
return queue;
error:
if (queue != NULL) {
free(queue->mutex);
free(queue->task);
free(queue);
}
return NULL;
}
flexran_agent_task_queue_t *flexran_agent_task_queue_default_init(mid_t mod_id) {
return flexran_agent_task_queue_init(mod_id, DEFAULT_CAPACITY, NULL);
}
void flexran_agent_task_queue_destroy(flexran_agent_task_queue_t *queue) {
int i;
if (queue == NULL)
return;
for (i = 0; i < queue->count; i++) {
flexran_agent_task_destroy(queue->task[i]);
}
free(queue->task);
free(queue->mutex);
free(queue);
}
int flexran_agent_task_queue_put(flexran_agent_task_queue_t *queue, flexran_agent_task_t *task) {
size_t i;
flexran_agent_task_t *tmp = NULL;
int realloc_status, err_code;
if (pthread_mutex_lock(queue->mutex)) {
/*TODO*/
err_code = -1;
goto error;
}
if (queue->count >= queue->capacity) {
/*TODO: need to call realloc heap*/
realloc_status = _flexran_agent_task_queue_realloc_heap(queue);
if (realloc_status != HEAP_OK) {
err_code = realloc_status;
goto error;
}
}
queue->task[queue->count] = task;
i = queue->count;
queue->count++;
/*Swap elements to maintain heap properties*/
while(i > 0 && queue->cmp(queue->mod_id, queue->task[i], queue->task[PARENT(i)]) > 0) {
tmp = queue->task[i];
queue->task[i] = queue->task[PARENT(i)];
queue->task[PARENT(i)] = tmp;
i = PARENT(i);
}
if (pthread_mutex_unlock(queue->mutex)) {
// LOG_E(MAC, "%s:%d:%s: fatal error\n", __FILE__, __LINE__, __FUNCTION__);
exit(1);
}
return 0;
error:
/*TODO*/
return err_code;
}
int flexran_agent_task_queue_get_current_task(flexran_agent_task_queue_t *queue, flexran_agent_task_t **task) {
int err_code;
if (pthread_mutex_lock(queue->mutex)) {
/*TODO*/
err_code = -1;
goto error;
}
if (queue->count < 1) {
/* Priority Queue is empty */
err_code = HEAP_EMPTY;
goto error;
}
/* Find current frame and subframe number */
uint16_t curr_frame = flexran_get_current_frame(queue->mod_id);
uint8_t curr_subframe = flexran_get_current_subframe(queue->mod_id);
/* If no task is scheduled for the current subframe, return without any task */
if(queue->task[0]->frame_num != curr_frame || queue->task[0]->subframe_num != curr_subframe) {
*task = NULL;
return 0;
}
/* Otherwise, the first task should be returned */
*task = queue->task[0];
queue->task[0] = queue->task[queue->count-1];
queue->count--;
/* Restore heap property */
_flexran_agent_task_queue_heapify(queue, 0);
/*If queue has no element*/
if (queue->count < 1) {
queue->first_frame = 0;
queue->first_subframe = 0;
} else {
queue->first_frame = queue->task[0]->frame_num;
queue->first_subframe = queue->task[0]->subframe_num;
}
if (pthread_mutex_unlock(queue->mutex)) {
// LOG_E(MAC, "%s:%d:%s: fatal error\n", __FILE__, __LINE__, __FUNCTION__);
exit(1);
}
return HEAP_OK;
error:
/*TODO*/
return err_code;
}
/*Warning: Internal function. Should not be called as API function. Not thread safe*/
void _flexran_agent_task_queue_heapify(flexran_agent_task_queue_t *queue, size_t idx) {
/* left index, right index, largest */
flexran_agent_task_t *tmp = NULL;
size_t l_idx, r_idx, lrg_idx;
l_idx = LEFT(idx);
r_idx = RIGHT(idx);
/* Left child exists, compare left child with its parent */
if (l_idx < queue->count && queue->cmp(queue->mod_id, queue->task[l_idx], queue->task[idx]) > 0) {
lrg_idx = l_idx;
} else {
lrg_idx = idx;
}
/* Right child exists, compare right child with the largest element */
if (r_idx < queue->count && queue->cmp(queue->mod_id, queue->task[r_idx], queue->task[lrg_idx]) > 0) {
lrg_idx = r_idx;
}
/* At this point largest element was determined */
if (lrg_idx != idx) {
/* Swap between the index at the largest element */
tmp = queue->task[lrg_idx];
queue->task[lrg_idx] = queue->task[idx];
queue->task[idx] = tmp;
/* Heapify again */
_flexran_agent_task_queue_heapify(queue, lrg_idx);
}
}
/*Warning: Internal function. Should not be called as API function. Not thread safe*/
int _flexran_agent_task_queue_realloc_heap(flexran_agent_task_queue_t *queue) {
flexran_agent_task_t **resized_task_heap;
if (queue->count >= queue->capacity) {
size_t task_size = sizeof(flexran_agent_task_t);
resized_task_heap = realloc(queue->task, (2*queue->capacity) * task_size);
if (resized_task_heap != NULL) {
queue->capacity *= 2;
queue->task = (flexran_agent_task_t **) resized_task_heap;
return HEAP_OK;
} else return HEAP_REALLOCERROR;
}
return HEAP_NOREALLOC;
}
int _flexran_agent_task_queue_cmp(mid_t mod_id, const flexran_agent_task_t *t1, const flexran_agent_task_t *t2) {
if ((t1->frame_num == t2->frame_num) && (t1->subframe_num == t2->subframe_num))
return 0;
uint16_t curr_frame = flexran_get_current_frame(mod_id);
uint8_t curr_subframe = flexran_get_current_subframe(mod_id);
int f_offset, sf_offset, tmp1, tmp2;
/*Check if the offsets have the same sign and compare the tasks position frame-wise*/
tmp1 = t1->frame_num - curr_frame;
tmp2 = t2->frame_num - curr_frame;
if ((tmp1 >= 0) ^ (tmp2 < 0)) {
f_offset = tmp2 - tmp1;
}
else {
f_offset = tmp1 - tmp2;
}
/*Do the same for the subframe*/
tmp1 = t1->subframe_num - curr_subframe;
tmp2 = t2->subframe_num - curr_subframe;
if ((tmp1 >= 0) ^ (tmp2 < 0))
sf_offset = tmp2 - tmp1;
else
sf_offset = tmp1 - tmp2;
/*Subframe position matters only if f_offset is 0. Multiply f_offset by 100
to be the only comparisson parameter in all other cases */
return f_offset*100 + sf_offset;
}
@@ -0,0 +1,156 @@
/*
* 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_task_manager.h
* \brief Implementation of scheduled tasks manager for the FlexRAN agent
* \author Xenofon Foukas
* \date January 2016
* \version 0.1
* \email: x.foukas@sms.ed.ac.uk
* @ingroup _mac
*/
#ifndef FLEXRAN_AGENT_TASK_MANAGER_
#define FLEXRAN_AGENT_TASK_MANAGER_
#include <stdint.h>
#include <pthread.h>
#include "flexran.pb-c.h"
#include "flexran_agent_common.h"
#ifdef __cplusplus
extern "C" {
#endif
#define DEFAULT_CAPACITY 512
/**
* The structure containing the enb agent task to be executed
*/
typedef struct flexran_agent_task_s {
/* The frame in which the task needs to be executed */
uint16_t frame_num;
/* The subframe in which the task needs to be executed */
uint8_t subframe_num;
/* The task to be executed in the form of a Protocol__FlexranMessage */
Protocol__FlexranMessage *task;
} flexran_agent_task_t;
/**
* Priority Queue Structure for tasks
*/
typedef struct flexran_agent_task_queue_s {
mid_t mod_id;
/* The amount of allocated memory for agent tasks in the heap*/
volatile size_t capacity;
/* The actual size of the tasks heap at a certain time */
volatile size_t count;
/* The earliest frame that has a pending task */
volatile uint16_t first_frame;
/* The earliest subframe within the frame that has a pending task */
volatile uint8_t first_subframe;
/* An array of prioritized tasks stored in a heap */
flexran_agent_task_t **task;
/* A pointer to a comparator function, used to prioritize elements */
int (*cmp)(mid_t mod_id, const flexran_agent_task_t *t1, const flexran_agent_task_t *t2);
pthread_mutex_t *mutex;
} flexran_agent_task_queue_t;
typedef enum {
HEAP_OK = 0,
HEAP_EMPTY,
HEAP_FAILED,
HEAP_REALLOCERROR,
HEAP_NOREALLOC,
HEAP_FATAL,
} heapstatus_e;
/**
* Allocate memory for a task in the queue
*/
flexran_agent_task_t *flexran_agent_task_create(Protocol__FlexranMessage *msg,
uint16_t frame_num, uint8_t subframe_num);
/**
* Free memory for a task of the queue
*/
void flexran_agent_task_destroy(flexran_agent_task_t *task);
/**
* Allocate initial memory for storing the tasks
*/
flexran_agent_task_queue_t *flexran_agent_task_queue_init(mid_t mod_id, size_t capacity,
int (*cmp)(mid_t mod_id, const flexran_agent_task_t *t1,
const flexran_agent_task_t *t2));
/**
* Allocate initial memory for storing the tasks using default parameters
*/
flexran_agent_task_queue_t *flexran_agent_task_queue_default_init(mid_t mod_id);
/**
* De-allocate memory for the tasks queue
*/
void flexran_agent_task_queue_destroy(flexran_agent_task_queue_t *queue);
/**
* Insert task into the queue
*/
int flexran_agent_task_queue_put(flexran_agent_task_queue_t *queue, flexran_agent_task_t *task);
/**
* Remove the task with the highest priority from the queue
* task becomes NULL if there is no task for the current frame and subframe
*/
int flexran_agent_task_queue_get_current_task(flexran_agent_task_queue_t *queue, flexran_agent_task_t **task);
/**
* Check if the top priority task is for a specific frame and subframe
*/
int flexran_agent_task_queue_has_upcoming_task (flexran_agent_task_queue_t *queue,
const uint16_t frame, const uint8_t subframe);
/**
* Restructure heap after modifications
*/
void _flexran_agent_task_queue_heapify(flexran_agent_task_queue_t *queue, size_t idx);
/**
* Reallocate memory once the heap reaches max size
*/
int _flexran_agent_task_queue_realloc_heap(flexran_agent_task_queue_t *queue);
/**
* Compare two agent tasks based on frame and subframe
* returns 0 if tasks t1, t2 have the same priority
* return negative value if t1 needs to be executed after t2
* return positive value if t1 preceeds t2
* Need to give eNB id for the comparisson based on the current frame-subframe
*/
int _flexran_agent_task_queue_cmp(mid_t mod_id, const flexran_agent_task_t *t1, const flexran_agent_task_t *t2);
#ifdef __cplusplus
}
#endif
#endif /*FLEXRAN_AGENT_TASK_MANAGER_*/
+13
View File
@@ -462,6 +462,13 @@ typedef struct {
//
uint32_t total_ulsch_pdus_rx;
/// MAC agent-related stats
/// total number of scheduling decisions
int sched_decisions;
/// missed deadlines
int missed_deadlines;
} eNB_STATS;
/*! \brief eNB statistics for the connected UEs*/
typedef struct {
@@ -602,6 +609,12 @@ typedef struct {
/// Flag to indicate UE has been configured (ACK from RRCConnectionSetup received)
boolean_t configured;
/// MCS from last scheduling
uint8_t mcs[8];
/// TPC from last scheduling
uint8_t oldTPC[8];
// PHY interface info
/// DCI format for DLSCH
+449 -7
View File
@@ -52,12 +52,23 @@
//#include "LAYER2/MAC/pre_processor.c"
#include "pdcp.h"
#if defined(FLEXRAN_AGENT_SB_IF)
//Agent-related headers
#include "flexran_agent_extern.h"
#include "flexran_agent_mac.h"
#include "flexran_agent_mac_proto.h"
#endif
#if defined(ENABLE_ITTI)
# include "intertask_interface.h"
#endif
#define ENABLE_MAC_PAYLOAD_DEBUG
#define DEBUG_eNB_SCHEDULER 1
//efine ENABLE_ENB_AGENT_DL_SCHEDULER
//#define DISABLE_SF_TRIGGER
//#define DISABLE_CONT_STATS
//#define DEBUG_HEADER_PARSING 1
//#define DEBUG_PACKET_TRACE 1
@@ -94,6 +105,10 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
void *DLSCH_dci=NULL;
int size_bits=0,size_bytes=0;
#if defined(FLEXRAN_AGENT_SB_IF)
Protocol__FlexranMessage *msg;
#endif
LOG_D(MAC,"[eNB %d] Frame %d, Subframe %d, entering MAC scheduler (UE_list->head %d)\n",module_idP, frameP, subframeP,UE_list->head);
start_meas(&eNB_mac_inst[module_idP].eNB_scheduler);
@@ -126,8 +141,17 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
eNB_mac_inst[module_idP].UE_list.UE_sched_ctrl[i].cqi_req_timer++;
if (mac_xface->get_eNB_UE_stats(module_idP, CC_id, rnti)==NULL) {
// mac_remove_ue(module_idP, i, frameP, subframeP);
//mac_remove_ue(module_idP, i, frameP, subframeP);
//Inform the controller about the UE deactivation. Should be moved to RRC agent in the future
#if defined(FLEXRAN_AGENT_SB_IF)
if (mac_agent_registered[module_idP]) {
agent_mac_xface[module_idP]->flexran_agent_notify_ue_state_change(module_idP,
rnti,
PROTOCOL__FLEX_UE_STATE_CHANGE_TYPE__FLUESC_DEACTIVATED);
}
#endif
}
else {
// check uplink failure
@@ -309,7 +333,14 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
}
/* #ifndef DISABLE_SF_TRIGGER */
/* //Send subframe trigger to the controller */
/* if (mac_agent_registered[module_idP]) { */
/* agent_mac_xface[module_idP]->flexran_agent_send_sf_trigger(module_idP); */
/* } */
/* #endif */
//if (subframeP%5 == 0)
//#ifdef EXMIMO
PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_idP, ENB_FLAG_YES, NOT_A_RNTI, frameP, subframeP,module_idP);
@@ -363,10 +394,26 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
(mac_xface->frame_parms->tdd_config == 6)) {
//schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,4);//,calibration_flag);
}
#ifndef FLEXRAN_AGENT_SB_IF
schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
#else
if (mac_agent_registered[module_idP]) {
agent_mac_xface[module_idP]->flexran_agent_schedule_ue_spec(
module_idP,
frameP,
subframeP,
mbsfn_status,
&msg);
flexran_apply_dl_scheduling_decisions(module_idP,
frameP,
subframeP,
mbsfn_status,
msg);
flexran_agent_mac_destroy_dl_config(msg);
}
#endif
break;
case 1:
@@ -378,12 +425,16 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
case 0:
case 1:
schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,7);
#ifndef FLEXRAN_AGENT_SB_IF
fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
#endif
break;
case 6:
schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,8);
#ifndef FLEXRAN_AGENT_SB_IF
fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
#endif
break;
default:
@@ -391,8 +442,26 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
}
} else { //FDD
schedule_ulsch(module_idP,frameP,cooperation_flag,1,5);
#ifndef FLEXRAN_AGENT_SB_IF
schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
#else
if (mac_agent_registered[module_idP]) {
agent_mac_xface[module_idP]->flexran_agent_schedule_ue_spec(
module_idP,
frameP,
subframeP,
mbsfn_status,
&msg);
flexran_apply_dl_scheduling_decisions(module_idP,
frameP,
subframeP,
mbsfn_status,
msg);
flexran_agent_mac_destroy_dl_config(msg);
}
#endif
}
break;
@@ -403,8 +472,26 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
// FDD, normal UL/DLSCH
if (mac_xface->frame_parms->frame_type == FDD) { //FDD
schedule_ulsch(module_idP,frameP,cooperation_flag,2,6);
#ifndef FLEXRAN_AGENT_SB_IF
schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
#else
if (mac_agent_registered[module_idP]) {
agent_mac_xface[module_idP]->flexran_agent_schedule_ue_spec(
module_idP,
frameP,
subframeP,
mbsfn_status,
&msg);
flexran_apply_dl_scheduling_decisions(module_idP,
frameP,
subframeP,
mbsfn_status,
msg);
flexran_agent_mac_destroy_dl_config(msg);
}
#endif
}
break;
@@ -421,8 +508,26 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
// no break here!
case 5:
#ifndef FLEXRAN_AGENT_SB_IF
schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
#else
if (mac_agent_registered[module_idP]) {
agent_mac_xface[module_idP]->flexran_agent_schedule_ue_spec(
module_idP,
frameP,
subframeP,
mbsfn_status,
&msg);
flexran_apply_dl_scheduling_decisions(module_idP,
frameP,
subframeP,
mbsfn_status,
msg);
flexran_agent_mac_destroy_dl_config(msg);
}
#endif
break;
default:
@@ -431,8 +536,26 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
} else { //FDD
schedule_ulsch(module_idP,frameP,cooperation_flag,3,7);
#ifndef FLEXRAN_AGENT_SB_IF
schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
#else
if (mac_agent_registered[module_idP]) {
agent_mac_xface[module_idP]->flexran_agent_schedule_ue_spec(
module_idP,
frameP,
subframeP,
mbsfn_status,
&msg);
flexran_apply_dl_scheduling_decisions(module_idP,
frameP,
subframeP,
mbsfn_status,
msg);
flexran_agent_mac_destroy_dl_config(msg);
}
#endif
}
break;
@@ -456,9 +579,26 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
// no break here!
case 5:
#ifndef FLEXRAN_AGENT_SB_IF
schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
#else
if (mac_agent_registered[module_idP]) {
agent_mac_xface[module_idP]->flexran_agent_schedule_ue_spec(
module_idP,
frameP,
subframeP,
mbsfn_status,
&msg);
flexran_apply_dl_scheduling_decisions(module_idP,
frameP,
subframeP,
mbsfn_status,
msg);
flexran_agent_mac_destroy_dl_config(msg);
}
#endif
break;
default:
@@ -468,8 +608,26 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
if (mac_xface->frame_parms->frame_type == FDD) { //FDD
schedule_ulsch(module_idP, frameP, cooperation_flag, 4, 8);
#ifndef FLEXRAN_AGENT_SB_IF
schedule_ue_spec(module_idP, frameP, subframeP, mbsfn_status);
fill_DLSCH_dci(module_idP, frameP, subframeP, mbsfn_status);
#else
if (mac_agent_registered[module_idP]) {
agent_mac_xface[module_idP]->flexran_agent_schedule_ue_spec(
module_idP,
frameP,
subframeP,
mbsfn_status,
&msg);
flexran_apply_dl_scheduling_decisions(module_idP,
frameP,
subframeP,
mbsfn_status,
msg);
flexran_agent_mac_destroy_dl_config(msg);
}
#endif
}
}
@@ -486,15 +644,53 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
if (mac_xface->frame_parms->frame_type == FDD) {
schedule_RA(module_idP,frameP,subframeP,1);
schedule_ulsch(module_idP,frameP,cooperation_flag,5,9);
#ifndef FLEXRAN_AGENT_SB_IF
schedule_ue_spec(module_idP, frameP, subframeP, mbsfn_status);
fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
#else
if (mac_agent_registered[module_idP]) {
agent_mac_xface[module_idP]->flexran_agent_schedule_ue_spec(
module_idP,
frameP,
subframeP,
mbsfn_status,
&msg);
flexran_apply_dl_scheduling_decisions(module_idP,
frameP,
subframeP,
mbsfn_status,
msg);
flexran_agent_mac_destroy_dl_config(msg);
}
#endif
} else if ((mac_xface->frame_parms->tdd_config == 0) || // TDD Config 0
(mac_xface->frame_parms->tdd_config == 6)) { // TDD Config 6
//schedule_ulsch(module_idP,cooperation_flag,subframeP);
#ifndef FLEXRAN_AGENT_SB_IF
fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
#endif
} else {
#ifndef FLEXRAN_AGENT_SB_IF
schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
#else
if (mac_agent_registered[module_idP]) {
agent_mac_xface[module_idP]->flexran_agent_schedule_ue_spec(
module_idP,
frameP,
subframeP,
mbsfn_status,
&msg);
flexran_apply_dl_scheduling_decisions(module_idP,
frameP,
subframeP,
mbsfn_status,
msg);
flexran_agent_mac_destroy_dl_config(msg);
}
#endif
}
break;
@@ -512,25 +708,65 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
case 1:
schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,2);
// schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
#ifndef FLEXRAN_AGENT_SB_IF
fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
#endif
break;
case 6:
schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,3);
// schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
#ifndef FLEXRAN_AGENT_SB_IF
fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
#endif
break;
case 5:
schedule_RA(module_idP,frameP,subframeP,2);
#ifndef FLEXRAN_AGENT_SB_IF
schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
#else
if (mac_agent_registered[module_idP]) {
agent_mac_xface[module_idP]->flexran_agent_schedule_ue_spec(
module_idP,
frameP,
subframeP,
mbsfn_status,
&msg);
flexran_apply_dl_scheduling_decisions(module_idP,
frameP,
subframeP,
mbsfn_status,
msg);
flexran_agent_mac_destroy_dl_config(msg);
}
#endif
break;
case 3:
case 4:
#ifndef FLEXRAN_AGENT_SB_IF
schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
#else
if (mac_agent_registered[module_idP]) {
agent_mac_xface[module_idP]->flexran_agent_schedule_ue_spec(
module_idP,
frameP,
subframeP,
mbsfn_status,
&msg);
flexran_apply_dl_scheduling_decisions(module_idP,
frameP,
subframeP,
mbsfn_status,
msg);
flexran_agent_mac_destroy_dl_config(msg);
}
#endif
break;
default:
@@ -538,8 +774,26 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
}
} else { //FDD
schedule_ulsch(module_idP,frameP,cooperation_flag,6,0);
#ifndef FLEXRAN_AGENT_SB_IF
schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
#else
if (mac_agent_registered[module_idP]) {
agent_mac_xface[module_idP]->flexran_agent_schedule_ue_spec(
module_idP,
frameP,
subframeP,
mbsfn_status,
&msg);
flexran_apply_dl_scheduling_decisions(module_idP,
frameP,
subframeP,
mbsfn_status,
msg);
flexran_agent_mac_destroy_dl_config(msg);
}
#endif
}
break;
@@ -553,13 +807,49 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
case 3:
case 4:
schedule_RA(module_idP,frameP,subframeP,3); // 3 = Msg3 subframeP, not
#ifndef FLEXRAN_AGENT_SB_IF
schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
#else
if (mac_agent_registered[module_idP]) {
agent_mac_xface[module_idP]->flexran_agent_schedule_ue_spec(
module_idP,
frameP,
subframeP,
mbsfn_status,
&msg);
flexran_apply_dl_scheduling_decisions(module_idP,
frameP,
subframeP,
mbsfn_status,
msg);
flexran_agent_mac_destroy_dl_config(msg);
}
#endif
break;
case 5:
#ifndef FLEXRAN_AGENT_SB_IF
schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
#else
if (mac_agent_registered[module_idP]) {
agent_mac_xface[module_idP]->flexran_agent_schedule_ue_spec(
module_idP,
frameP,
subframeP,
mbsfn_status,
&msg);
flexran_apply_dl_scheduling_decisions(module_idP,
frameP,
subframeP,
mbsfn_status,
msg);
flexran_agent_mac_destroy_dl_config(msg);
}
#endif
break;
default:
@@ -567,8 +857,26 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
}
} else { //FDD
schedule_ulsch(module_idP,frameP,cooperation_flag,7,1);
#ifndef FLEXRAN_AGENT_SB_IF
schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
#else
if (mac_agent_registered[module_idP]) {
agent_mac_xface[module_idP]->flexran_agent_schedule_ue_spec(
module_idP,
frameP,
subframeP,
mbsfn_status,
&msg);
flexran_apply_dl_scheduling_decisions(module_idP,
frameP,
subframeP,
mbsfn_status,
msg);
flexran_agent_mac_destroy_dl_config(msg);
}
#endif
}
break;
@@ -587,8 +895,26 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
// schedule_RA(module_idP,subframeP);
schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,2);
#ifndef FLEXRAN_AGENT_SB_IF
schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
#else
if (mac_agent_registered[module_idP]) {
agent_mac_xface[module_idP]->flexran_agent_schedule_ue_spec(
module_idP,
frameP,
subframeP,
mbsfn_status,
&msg);
flexran_apply_dl_scheduling_decisions(module_idP,
frameP,
subframeP,
mbsfn_status,
msg);
flexran_agent_mac_destroy_dl_config(msg);
}
#endif
break;
default:
@@ -596,8 +922,26 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
}
} else { //FDD
schedule_ulsch(module_idP,frameP,cooperation_flag,8,2);
#ifndef FLEXRAN_AGENT_SB_IF
schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
#else
if (mac_agent_registered[module_idP]) {
agent_mac_xface[module_idP]->flexran_agent_schedule_ue_spec(
module_idP,
frameP,
subframeP,
mbsfn_status,
&msg);
flexran_apply_dl_scheduling_decisions(module_idP,
frameP,
subframeP,
mbsfn_status,
msg);
flexran_agent_mac_destroy_dl_config(msg);
}
#endif
}
break;
@@ -610,29 +954,101 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
case 1:
schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,3);
schedule_RA(module_idP,frameP,subframeP,7); // 7 = Msg3 subframeP, not
#ifndef FLEXRAN_AGENT_SB_IF
schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
#else
if (mac_agent_registered[module_idP]) {
agent_mac_xface[module_idP]->flexran_agent_schedule_ue_spec(
module_idP,
frameP,
subframeP,
mbsfn_status,
&msg);
flexran_apply_dl_scheduling_decisions(module_idP,
frameP,
subframeP,
mbsfn_status,
msg);
flexran_agent_mac_destroy_dl_config(msg);
}
#endif
break;
case 3:
case 4:
schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,3);
#ifndef FLEXRAN_AGENT_SB_IF
schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
#else
if (mac_agent_registered[module_idP]) {
agent_mac_xface[module_idP]->flexran_agent_schedule_ue_spec(
module_idP,
frameP,
subframeP,
mbsfn_status,
&msg);
flexran_apply_dl_scheduling_decisions(module_idP,
frameP,
subframeP,
mbsfn_status,
msg);
flexran_agent_mac_destroy_dl_config(msg);
}
#endif
break;
case 6:
schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,4);
//schedule_RA(module_idP,frameP,subframeP);
#ifndef FLEXRAN_AGENT_SB_IF
schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
#else
if (mac_agent_registered[module_idP]) {
agent_mac_xface[module_idP]->flexran_agent_schedule_ue_spec(
module_idP,
frameP,
subframeP,
mbsfn_status,
&msg);
flexran_apply_dl_scheduling_decisions(module_idP,
frameP,
subframeP,
mbsfn_status,
msg);
flexran_agent_mac_destroy_dl_config(msg);
}
#endif
break;
case 2:
case 5:
//schedule_RA(module_idP,frameP,subframeP);
#ifndef FLEXRAN_AGENT_SB_IF
schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
#else
if (mac_agent_registered[module_idP]) {
agent_mac_xface[module_idP]->flexran_agent_schedule_ue_spec(
module_idP,
frameP,
subframeP,
mbsfn_status,
&msg);
flexran_apply_dl_scheduling_decisions(module_idP,
frameP,
subframeP,
mbsfn_status,
msg);
flexran_agent_mac_destroy_dl_config(msg);
}
#endif
break;
default:
@@ -640,8 +1056,26 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
}
} else { //FDD
schedule_ulsch(module_idP,frameP,cooperation_flag,9,3);
#ifndef FLEXRAN_AGENT_SB_IF
schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status);
fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status);
#else
if (mac_agent_registered[module_idP]) {
agent_mac_xface[module_idP]->flexran_agent_schedule_ue_spec(
module_idP,
frameP,
subframeP,
mbsfn_status,
&msg);
flexran_apply_dl_scheduling_decisions(module_idP,
frameP,
subframeP,
mbsfn_status,
msg);
flexran_agent_mac_destroy_dl_config(msg);
}
#endif
}
break;
@@ -654,6 +1088,15 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
for (CC_id=0;CC_id<MAX_NUM_CCs;CC_id++)
allocate_CCEs(module_idP,CC_id,subframeP,0);
#if defined(FLEXRAN_AGENT_SB_IF)
#ifndef DISABLE_CONT_STATS
//Send subframe trigger to the controller
if (mac_agent_registered[module_idP]) {
agent_mac_xface[module_idP]->flexran_agent_send_update_mac_stats(module_idP);
}
#endif
#endif
/*
int dummy=0;
for (i=0;
@@ -673,7 +1116,6 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
DCI_pdu[CC_id]->dci_alloc[i].firstCCE,
DCI_pdu[CC_id]->num_pdcch_symbols);
LOG_D(MAC,"frameP %d, subframeP %d\n",frameP,subframeP);
*/
+1 -1
View File
@@ -664,7 +664,7 @@ void schedule_RA(module_id_t module_idP,frame_t frameP, sub_frame_t subframeP,un
LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d: Checking if Msg4 was acknowledged: \n",
module_idP,CC_id,frameP,subframeP);
// Get candidate harq_pid from PHY
mac_xface->get_ue_active_harq_pid(module_idP,CC_id,RA_template->rnti,frameP,subframeP,&harq_pid,&round,0);
mac_xface->get_ue_active_harq_pid(module_idP,CC_id,RA_template->rnti,frameP,subframeP,&harq_pid,&round,openair_harq_RA);
if (round>0) {
//RA_template->wait_ack_Msg4++;
@@ -146,7 +146,7 @@ rnti_t UE_RNTI(module_id_t mod_idP, int ue_idP)
return (rnti);
}
LOG_E(MAC,"[eNB %d] Couldn't find RNTI for UE %d\n",mod_idP,ue_idP);
LOG_D(MAC,"[eNB %d] Couldn't find RNTI for UE %d\n",mod_idP,ue_idP);
//display_backtrace();
return(NOT_A_RNTI);
}
+1 -1
View File
@@ -781,7 +781,7 @@ void schedule_ulsch_rnti(module_id_t module_idP,
UE_template = &UE_list->UE_template[CC_id][UE_id];
UE_sched_ctrl = &UE_list->UE_sched_ctrl[UE_id];
if (mac_xface->get_ue_active_harq_pid(module_idP,CC_id,rnti,frameP,subframeP,&harq_pid,&round,1) == -1 ) {
if (mac_xface->get_ue_active_harq_pid(module_idP,CC_id,rnti,frameP,subframeP,&harq_pid,&round,openair_harq_UL) == -1 ) {
LOG_W(MAC,"[eNB %d] Scheduler Frame %d, subframeP %d: candidate harq_pid from PHY for UE %d CC %d RNTI %x\n",
module_idP,frameP,subframeP, UE_id, CC_id, rnti);
continue;
+4
View File
@@ -43,12 +43,16 @@
//#include "SIMULATION/simulation_defs.h"
#endif //PHY_EMUL
#include "PHY_INTERFACE/defs.h"
#include "RRC/LITE/defs.h"
extern const uint32_t BSR_TABLE[BSR_TABLE_SIZE];
//extern uint32_t EBSR_Level[63];
extern UE_MAC_INST *UE_mac_inst;
extern eNB_MAC_INST *eNB_mac_inst;
extern eNB_RRC_INST *eNB_rrc_inst;
extern UE_RRC_INST *UE_rrc_inst;
extern UE_MAC_INST *ue_mac_inst;
extern MAC_RLC_XFACE *Mac_rlc_xface;
extern uint8_t Is_rrc_registered;
@@ -0,0 +1,62 @@
/*
* 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_proto.h
* \brief MAC functions for FlexRAN agent
* \author Xenofon Foukas
* \date 2016
* \email: x.foukas@sms.ed.ac.uk
* \version 0.1
* @ingroup _mac
*/
#ifndef __LAYER2_MAC_FLEXRAN_AGENT_MAC_PROTO_H__
#define __LAYER2_MAC_FLEXRAN_AGENT_MAC_PROTO_H__
#include "flexran_agent_defs.h"
#include "header.pb-c.h"
#include "flexran.pb-c.h"
/*
* Default scheduler used by the eNB agent
*/
void flexran_schedule_ue_spec_default(mid_t mod_id, uint32_t frame, uint32_t subframe,
int *mbsfn_flag, Protocol__FlexranMessage **dl_info);
/*
* Data plane function for applying the DL decisions of the scheduler
*/
void flexran_apply_dl_scheduling_decisions(mid_t mod_id, uint32_t frame, uint32_t subframe, int *mbsfn_flag,
const Protocol__FlexranMessage *dl_scheduling_info);
/*
* Data plane function for applying the UE specific DL decisions of the scheduler
*/
void flexran_apply_ue_spec_scheduling_decisions(mid_t mod_id, uint32_t frame, uint32_t subframe, int *mbsfn_flag,
uint32_t n_dl_ue_data, const Protocol__FlexDlData **dl_ue_data);
/*
* Data plane function for filling the DCI structure
*/
void flexran_fill_oai_dci(mid_t mod_id, uint32_t CC_id, uint32_t rnti, const Protocol__FlexDlDci *dl_dci);
#endif
@@ -0,0 +1,537 @@
/*
* 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_scheduler_dataplane.c
* \brief data plane procedures related to eNB scheduling
* \author Xenofon Foukas
* \date 2016
* \email: x.foukas@sms.ed.ac.uk
* \version 0.1
* @ingroup _mac
*/
#include "assertions.h"
#include "PHY/defs.h"
#include "PHY/extern.h"
#include "SCHED/defs.h"
#include "SCHED/extern.h"
#include "LAYER2/MAC/flexran_agent_mac_proto.h"
#include "LAYER2/MAC/defs.h"
#include "LAYER2/MAC/proto.h"
#include "LAYER2/MAC/extern.h"
#include "LAYER2/MAC/flexran_dci_conversions.h"
#include "UTIL/LOG/log.h"
#include "UTIL/LOG/vcd_signal_dumper.h"
#include "UTIL/OPT/opt.h"
#include "OCG.h"
#include "OCG_extern.h"
#include "RRC/LITE/extern.h"
#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"
#include "header.pb-c.h"
#include "flexran.pb-c.h"
#include "SIMULATION/TOOLS/defs.h" // for taus
void flexran_apply_dl_scheduling_decisions(mid_t mod_id,
uint32_t frame,
uint32_t subframe,
int *mbsfn_flag,
const Protocol__FlexranMessage *dl_scheduling_info) {
Protocol__FlexDlMacConfig *mac_config = dl_scheduling_info->dl_mac_config_msg;
// Check if there is anything to schedule for random access
if (mac_config->n_dl_rar > 0) {
/*TODO: call the random access data plane function*/
}
// Check if there is anything to schedule for paging/broadcast
if (mac_config->n_dl_broadcast > 0) {
/*TODO: call the broadcast/paging data plane function*/
}
// Check if there is anything to schedule for the UEs
if (mac_config->n_dl_ue_data > 0) {
flexran_apply_ue_spec_scheduling_decisions(mod_id, frame, subframe, mbsfn_flag,
mac_config->n_dl_ue_data, mac_config->dl_ue_data);
}
}
void flexran_apply_ue_spec_scheduling_decisions(mid_t mod_id,
uint32_t frame,
uint32_t subframe,
int *mbsfn_flag,
uint32_t n_dl_ue_data,
const Protocol__FlexDlData **dl_ue_data) {
uint8_t CC_id;
int UE_id;
int N_RBG[MAX_NUM_CCs];
unsigned char aggregation;
mac_rlc_status_resp_t rlc_status;
unsigned char ta_len=0;
unsigned char header_len = 0, header_len_tmp = 0;
unsigned char sdu_lcids[11],offset,num_sdus=0;
uint16_t nb_rb,nb_rb_temp,total_nb_available_rb[MAX_NUM_CCs],nb_available_rb;
uint16_t TBS,j,sdu_lengths[11],rnti,padding=0,post_padding=0;
unsigned char dlsch_buffer[MAX_DLSCH_PAYLOAD_BYTES];
unsigned char round = 0;
unsigned char harq_pid = 0;
LTE_eNB_UE_stats *eNB_UE_stats = NULL;
uint16_t sdu_length_total = 0;
int mcs;
uint16_t min_rb_unit[MAX_NUM_CCs];
short ta_update = 0;
eNB_MAC_INST *eNB = &eNB_mac_inst[mod_id];
UE_list_t *UE_list = &eNB->UE_list;
LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs];
int32_t normalized_rx_power, target_rx_power;
int32_t tpc=1;
static int32_t tpc_accumulated=0;
UE_sched_ctrl *ue_sched_ctl;
int last_sdu_header_len = 0;
int i;
Protocol__FlexDlData *dl_data;
Protocol__FlexDlDci *dl_dci;
uint32_t rlc_size, n_lc, lcid;
// For each UE-related command
for (i = 0; i < n_dl_ue_data; i++) {
dl_data = dl_ue_data[i];
dl_dci = dl_data->dl_dci;
CC_id = dl_data->serv_cell_index;
frame_parms[CC_id] = mac_xface->get_lte_frame_parms(mod_id, CC_id);
rnti = dl_data->rnti;
UE_id = find_ue(rnti, PHY_vars_eNB_g[mod_id][CC_id]);
ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
eNB_UE_stats = mac_xface->get_eNB_UE_stats(mod_id,CC_id,rnti);
round = dl_dci->rv[0];
harq_pid = dl_dci->harq_process;
// If this is a new transmission
if (round == 0) {
// First we have to deal with the creation of the PDU based on the message instructions
rlc_status.bytes_in_buffer = 0;
TBS = dl_dci->tbs_size[0];
if (dl_data->n_ce_bitmap > 0) {
//Check if there is TA command and set the length appropriately
ta_len = (dl_data->ce_bitmap[0] & PROTOCOL__FLEX_CE_TYPE__FLPCET_TA) ? 1 : 0;
}
num_sdus = 0;
sdu_length_total = 0;
if (ta_len > 0) {
// Reset the measurement
ue_sched_ctl->ta_timer = 20;
eNB_UE_stats->timing_advance_update = 0;
header_len = ta_len;
last_sdu_header_len = ta_len;
}
n_lc = dl_data->n_rlc_pdu;
// Go through each one of the channel commands and create SDUs
for (i = 0; i < n_lc; i++) {
lcid = dl_data->rlc_pdu[i]->rlc_pdu_tb[0]->logical_channel_id;
rlc_size = dl_data->rlc_pdu[i]->rlc_pdu_tb[0]->size;
LOG_D(MAC,"[TEST] [eNB %d] Frame %d, LCID %d, CC_id %d, Requesting %d bytes from RLC (RRC message)\n",
mod_id, frame, lcid, CC_id, rlc_size);
if (rlc_size > 0) {
rlc_status = mac_rlc_status_ind(mod_id,
rnti,
mod_id,
frame,
ENB_FLAG_YES,
MBMS_FLAG_NO,
lcid,
0);
if (rlc_status.bytes_in_buffer > 0) {
if (rlc_size <= 2) {
rlc_size = 3;
}
rlc_status = mac_rlc_status_ind(mod_id,
rnti,
mod_id,
frame,
ENB_FLAG_YES,
MBMS_FLAG_NO,
lcid,
rlc_size); // transport block set size
sdu_lengths[i] = 0;
LOG_D(MAC, "[TEST] RLC can give %d bytes for LCID %d during second call\n", rlc_status.bytes_in_buffer, lcid);
if (rlc_status.bytes_in_buffer > 0) {
sdu_lengths[i] += mac_rlc_data_req(mod_id,
rnti,
mod_id,
frame,
ENB_FLAG_YES,
MBMS_FLAG_NO,
lcid,
(char *)&dlsch_buffer[sdu_length_total]);
LOG_D(MAC,"[eNB %d][LCID %d] CC_id %d Got %d bytes from RLC\n",mod_id, lcid, CC_id, sdu_lengths[i]);
sdu_length_total += sdu_lengths[i];
sdu_lcids[i] = lcid;
UE_list->eNB_UE_stats[CC_id][UE_id].num_pdu_tx[lcid] += 1;
UE_list->eNB_UE_stats[CC_id][UE_id].num_bytes_tx[lcid] += sdu_lengths[i];
if (sdu_lengths[i] <= 128) {
header_len += 2;
last_sdu_header_len = 2;
} else {
header_len += 3;
last_sdu_header_len = 3;
}
num_sdus++;
}
}
}
} // SDU creation end
if (((sdu_length_total + header_len) > 0)) {
// header_len_tmp = header_len;
// If we have only a single SDU, header length becomes 1
if ((num_sdus + ta_len) == 1) {
//if (header_len == 2 || header_len == 3) {
header_len = 1;
} else {
header_len = (header_len - last_sdu_header_len) + 1;
}
// there is a payload
if (((sdu_length_total + header_len) > 0)) {
// If we need a 1 or 2 bit padding or no padding at all
if ((TBS - header_len - sdu_length_total - ta_len) <= 2
|| (TBS - header_len - sdu_length_total - ta_len) > TBS) { //protect from overflow
padding = (TBS - header_len - sdu_length_total - ta_len);
post_padding = 0;
} else { // The last sdu needs to have a length field, since we add padding
padding = 0;
header_len = header_len_tmp;
post_padding = TBS - sdu_length_total - header_len - ta_len - 1; // 1 is for the postpadding header
}
}
ta_update = (ta_len > 0) ? ue_sched_ctl->ta_update : 0;
// If there is nothing to schedule, just leave
if ((sdu_length_total) <= 0) {
return;
}
offset = generate_dlsch_header((unsigned char*)UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0],
num_sdus, //num_sdus
sdu_lengths, //
sdu_lcids,
255, // no drx
ta_update, // timing advance
NULL, // contention res id
padding,
post_padding);
#ifdef DEBUG_eNB_SCHEDULER
LOG_T(MAC,"[eNB %d] First 16 bytes of DLSCH : \n");
for (i=0; i<16; i++) {
LOG_T(MAC,"%x.",dlsch_buffer[i]);
}
LOG_T(MAC,"\n");
#endif
// cycle through SDUs and place in dlsch_buffer
memcpy(&UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0][offset],dlsch_buffer,sdu_length_total);
// memcpy(&eNB_mac_inst[0].DLSCH_pdu[0][0].payload[0][offset],dcch_buffer,sdu_lengths[0]);
// fill remainder of DLSCH with random data
for (j=0; j<(TBS-sdu_length_total-offset); j++) {
UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0][offset+sdu_length_total+j] = (char)(taus()&0xff);
}
//eNB_mac_inst[0].DLSCH_pdu[0][0].payload[0][offset+sdu_lengths[0]+j] = (char)(taus()&0xff);
if (opt_enabled == 1) {
trace_pdu(1, (uint8_t *)UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0],
TBS, mod_id, 3, UE_RNTI(mod_id, UE_id),
eNB->subframe,0,0);
LOG_D(OPT,"[eNB %d][DLSCH] CC_id %d Frame %d rnti %x with size %d\n",
mod_id, CC_id, frame, UE_RNTI(mod_id,UE_id), TBS);
}
// store stats
eNB->eNB_stats[CC_id].dlsch_bytes_tx+=sdu_length_total;
eNB->eNB_stats[CC_id].dlsch_pdus_tx+=1;
UE_list->eNB_UE_stats[CC_id][UE_id].dl_cqi= eNB_UE_stats->DL_cqi[0];
UE_list->eNB_UE_stats[CC_id][UE_id].crnti= rnti;
UE_list->eNB_UE_stats[CC_id][UE_id].rrc_status=mac_eNB_get_rrc_status(mod_id, rnti);
UE_list->eNB_UE_stats[CC_id][UE_id].harq_pid = harq_pid;
UE_list->eNB_UE_stats[CC_id][UE_id].harq_round = round;
//nb_rb = UE_list->UE_template[CC_id][UE_id].nb_rb[harq_pid];
//Find the number of resource blocks and set them to the template for retransmissions
nb_rb = get_min_rb_unit(mod_id, CC_id);
uint16_t stats_tbs = mac_xface->get_TBS_DL(dl_dci->mcs[0], nb_rb);
while (stats_tbs < TBS) {
nb_rb += get_min_rb_unit(mod_id, CC_id);
stats_tbs = mac_xface->get_TBS_DL(dl_dci->mcs[0], nb_rb);
}
UE_list->eNB_UE_stats[CC_id][UE_id].rbs_used = nb_rb;
UE_list->eNB_UE_stats[CC_id][UE_id].total_rbs_used += nb_rb;
UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1=dl_dci->mcs[0];
UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_mcs2=dl_dci->mcs[0];
UE_list->eNB_UE_stats[CC_id][UE_id].TBS = TBS;
UE_list->eNB_UE_stats[CC_id][UE_id].overhead_bytes= TBS - sdu_length_total;
UE_list->eNB_UE_stats[CC_id][UE_id].total_sdu_bytes+= sdu_length_total;
UE_list->eNB_UE_stats[CC_id][UE_id].total_pdu_bytes+= TBS;
UE_list->eNB_UE_stats[CC_id][UE_id].total_num_pdus+=1;
//eNB_UE_stats->dlsch_mcs1 = cqi_to_mcs[eNB_UE_stats->DL_cqi[0]];
//eNB_UE_stats->dlsch_mcs1 = cmin(eNB_UE_stats->dlsch_mcs1, openair_daq_vars.target_ue_dl_mcs);
}
} else {
// No need to create anything apart of DCI in case of retransmission
/*TODO: Must add these */
// eNB_UE_stats->dlsch_trials[round]++;
//UE_list->eNB_UE_stats[CC_id][UE_id].num_retransmission+=1;
//UE_list->eNB_UE_stats[CC_id][UE_id].rbs_used_retx=nb_rb;
//UE_list->eNB_UE_stats[CC_id][UE_id].total_rbs_used_retx+=nb_rb;
//UE_list->eNB_UE_stats[CC_id][UE_id].ncce_used_retx=nCCECC_id];
}
UE_list->UE_template[CC_id][UE_id].oldNDI[dl_dci->harq_process] = dl_dci->ndi[0];
eNB_UE_stats->dlsch_mcs1 = dl_dci->mcs[0];
//Fill the proper DCI of OAI
fill_oai_dci(mod_id, CC_id, rnti, dl_dci);
}
}
void fill_oai_dci(mid_t mod_id, uint32_t CC_id, uint32_t rnti,
const Protocol__FlexDlDci *dl_dci) {
void *DLSCH_dci = NULL;
DCI_PDU *DCI_pdu;
unsigned char round = 0;
unsigned char harq_pid = 0;
LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs];
int size_bits, size_bytes;
eNB_MAC_INST *eNB = &eNB_mac_inst[mod_id];
UE_list_t *UE_list = &eNB->UE_list;
LTE_eNB_UE_stats *eNB_UE_stats = NULL;
int UE_id = find_ue(rnti, PHY_vars_eNB_g[mod_id][CC_id]);
uint32_t format;
harq_pid = dl_dci->harq_process;
round = dl_dci->rv[0];
// Note this code is for a specific DCI format
DLSCH_dci = (void *)UE_list->UE_template[CC_id][UE_id].DLSCH_DCI[harq_pid];
DCI_pdu = &eNB->common_channels[CC_id].DCI_pdu;
frame_parms[CC_id] = mac_xface->get_lte_frame_parms(mod_id, CC_id);
if (dl_dci->has_tpc == 1) {
// Check if tpc has been set and reset measurement */
if ((dl_dci->tpc == 0) || (dl_dci->tpc == 2)) {
eNB_UE_stats = mac_xface->get_eNB_UE_stats(mod_id, CC_id, rnti);
eNB_UE_stats->Po_PUCCH_update = 0;
}
}
switch (frame_parms[CC_id]->N_RB_DL) {
case 6:
if (frame_parms[CC_id]->frame_type == TDD) {
if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1) {
FILL_DCI_TDD_1(DCI1_1_5MHz_TDD_t, DLSCH_dci, dl_dci);
size_bytes = sizeof(DCI1_1_5MHz_TDD_t);
size_bits = sizeof_DCI1_1_5MHz_TDD_t;
} else if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2A) {
//TODO
} else if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1D) {
//TODO
}
} else {
if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1) {
FILL_DCI_FDD_1(DCI1_1_5MHz_FDD_t, DLSCH_dci, dl_dci);
size_bytes = sizeof(DCI1_1_5MHz_FDD_t);
size_bits = sizeof_DCI1_1_5MHz_FDD_t;
} else if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2A) {
//TODO
} else if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1D) {
//TODO
}
}
break;
case 25:
if (frame_parms[CC_id]->frame_type == TDD) {
if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1) {
FILL_DCI_TDD_1(DCI1_5MHz_TDD_t, DLSCH_dci, dl_dci);
size_bytes = sizeof(DCI1_5MHz_TDD_t);
size_bits = sizeof_DCI1_5MHz_TDD_t;
} else if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2A) {
//TODO
} else if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1D) {
//TODO
}
} else {
if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1) {
FILL_DCI_FDD_1(DCI1_5MHz_FDD_t, DLSCH_dci, dl_dci);
size_bytes = sizeof(DCI1_5MHz_FDD_t);
size_bits = sizeof_DCI1_5MHz_FDD_t;
} else if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2A) {
//TODO
} else if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1D) {
//TODO
}
}
break;
case 50:
if (frame_parms[CC_id]->frame_type == TDD) {
if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1) {
FILL_DCI_TDD_1(DCI1_10MHz_TDD_t, DLSCH_dci, dl_dci);
size_bytes = sizeof(DCI1_10MHz_TDD_t);
size_bits = sizeof_DCI1_10MHz_TDD_t;
} else if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2A) {
//TODO
} else if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1D) {
//TODO
}
} else {
if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1) {
FILL_DCI_FDD_1(DCI1_10MHz_FDD_t, DLSCH_dci, dl_dci);
size_bytes = sizeof(DCI1_10MHz_FDD_t);
size_bits = sizeof_DCI1_10MHz_FDD_t;
} else if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2A) {
//TODO
} else if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1D) {
//TODO
}
}
break;
case 100:
if (frame_parms[CC_id]->frame_type == TDD) {
if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1) {
FILL_DCI_TDD_1(DCI1_20MHz_TDD_t, DLSCH_dci, dl_dci);
size_bytes = sizeof(DCI1_20MHz_TDD_t);
size_bits = sizeof_DCI1_20MHz_TDD_t;
} else if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2A) {
//TODO
} else if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1D) {
//TODO
}
} else {
if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1) {
FILL_DCI_FDD_1(DCI1_20MHz_FDD_t, DLSCH_dci, dl_dci);
size_bytes = sizeof(DCI1_20MHz_FDD_t);
size_bits = sizeof_DCI1_20MHz_FDD_t;
} else if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2A) {
//TODO
} else if (dl_dci->format == PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1D) {
//TODO
}
}
break;
}
//Set format to the proper type
switch(dl_dci->format) {
case PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1:
format = format1;
break;
case PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1A:
format = format1A;
break;
case PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1B:
format = format1B;
break;
case PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1C:
format = format1C;
break;
case PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_1D:
format = format1E_2A_M10PRB;
break;
case PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2:
format = format2;
break;
case PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2A:
format = format2A;
break;
case PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_2B:
format = format2B;
break;
case PROTOCOL__FLEX_DCI_FORMAT__FLDCIF_3:
format = 3;
break;
default:
/*TODO: Need to deal with unsupported DCI type*/
return;
}
add_ue_spec_dci(DCI_pdu,
DLSCH_dci,
rnti,
size_bytes,
dl_dci->aggr_level,
size_bits,
format,
0);
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,180 @@
/*
* 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_scheduler_dlsch_ue_remote.c
* \brief procedures related to remote scheduling in the DLSCH transport channel
* \author Xenofon Foukas
* \date 2016
* \email: x.foukas@sms.ed.ac.uk
* \version 0.1
* @ingroup _mac
*/
#include "flexran_agent_common_internal.h"
#include "flexran_agent_scheduler_dlsch_ue_remote.h"
#include "LAYER2/MAC/defs.h"
#include "LAYER2/MAC/extern.h"
struct DlMacConfigHead queue_head;
int queue_initialized = 0;
//uint32_t skip_subframe = 1;
//uint32_t period = 10;
//uint32_t sched [] = {1, 2, 3};
void flexran_schedule_ue_spec_remote(mid_t mod_id, uint32_t frame, uint32_t subframe,
int *mbsfn_flag, Protocol__FlexranMessage **dl_info) {
//if ((subframe == skip_subframe) && (frame % period == 0)) {
// LOG_I(MAC, "Will skip subframe %d %d\n", subframe, frame);
// for (int i = 0; i < 3; i++) {
// LOG_I(MAC, "%d\n", sched[i]);
// }
//}
/* if (frame == 500 && subframe == 1) { */
/* char policy[] = "rrc: \n - ul_scheduler: \n behavior : tester_function\n parameters:\n period: !!int 3\nmac: \n - dl_scheduler: \n parameters: \n period : !!int 40\n skip_subframe : !!int 3\n sched : [!!int 4, !!int 5, !!int 6]"; */
/* apply_reconfiguration_policy(mod_id, policy, strlen(policy)); */
/* } */
eNB_MAC_INST *eNB;
if (!queue_initialized) {
TAILQ_INIT(&queue_head);
queue_initialized = 1;
}
eNB = &eNB_mac_inst[mod_id];
dl_mac_config_element_t *dl_config_elem;
int diff;
LOG_D(MAC, "[TEST] Current frame and subframe %d, %d\n", frame, subframe);
// First we check to see if we have a scheduling decision for this sfn_sf already in our queue
while(queue_head.tqh_first != NULL) {
dl_config_elem = queue_head.tqh_first;
diff = get_sf_difference(mod_id, dl_config_elem->dl_info->dl_mac_config_msg->sfn_sf);
// Check if this decision is for now, for a later or a previous subframe
if ( diff == 0) { // Now
LOG_D(MAC, "Found a decision for this subframe in the queue. Let's use it!\n");
TAILQ_REMOVE(&queue_head, queue_head.tqh_first, configs);
*dl_info = dl_config_elem->dl_info;
free(dl_config_elem);
eNB->eNB_stats[mod_id].sched_decisions++;
return;
} else if (diff < 0) { //previous subframe , delete message and free memory
LOG_D(MAC, "Found a decision for a previous subframe in the queue. Let's get rid of it\n");
TAILQ_REMOVE(&queue_head, queue_head.tqh_first, configs);
flexran_agent_mac_destroy_dl_config(dl_config_elem->dl_info);
free(dl_config_elem);
eNB->eNB_stats[mod_id].sched_decisions++;
eNB->eNB_stats[mod_id].missed_deadlines++;
} else { // next subframe, nothing to do now
LOG_D(MAC, "Found a decision for a future subframe in the queue. Nothing to do now\n");
flexran_agent_mac_create_empty_dl_config(mod_id, dl_info);
return;
}
}
//Done with the local cache. Now we need to check if something new arrived
flexran_agent_get_pending_dl_mac_config(mod_id, dl_info);
while (*dl_info != NULL) {
diff = get_sf_difference(mod_id, (*dl_info)->dl_mac_config_msg->sfn_sf);
if (diff == 0) { // Got a command for this sfn_sf
LOG_D(MAC, "Found a decision for this subframe pending. Let's use it\n");
eNB->eNB_stats[mod_id].sched_decisions++;
return;
} else if (diff < 0) {
LOG_D(MAC, "Found a decision for a previous subframe. Let's get rid of it\n");
flexran_agent_mac_destroy_dl_config(*dl_info);
*dl_info = NULL;
flexran_agent_get_pending_dl_mac_config(mod_id, dl_info);
eNB->eNB_stats[mod_id].sched_decisions++;
eNB->eNB_stats[mod_id].missed_deadlines++;
} else { // Intended for future subframe. Store it in local cache
LOG_D(MAC, "Found a decision for a future subframe in the queue. Let's store it in the cache\n");
dl_mac_config_element_t *e = malloc(sizeof(dl_mac_config_element_t));
e->dl_info = *dl_info;
TAILQ_INSERT_TAIL(&queue_head, e, configs);
flexran_agent_mac_create_empty_dl_config(mod_id, dl_info);
// No need to look for another. Messages arrive ordered
return;
}
}
// We found no pending command, so we will simply pass an empty one
flexran_agent_mac_create_empty_dl_config(mod_id, dl_info);
}
int get_sf_difference(mid_t mod_id, uint32_t sfn_sf) {
int diff_in_subframes;
uint16_t current_frame = flexran_get_current_system_frame_num(mod_id);
uint16_t current_subframe = flexran_get_current_subframe(mod_id);
uint32_t current_sfn_sf = flexran_get_sfn_sf(mod_id);
if (sfn_sf == current_sfn_sf) {
return 0;
}
uint16_t frame_mask = ((1<<12) - 1);
uint16_t frame = (sfn_sf & (frame_mask << 4)) >> 4;
uint16_t sf_mask = ((1<<4) - 1);
uint16_t subframe = (sfn_sf & sf_mask);
LOG_D(MAC, "[TEST] Target frame and subframe %d, %d\n", frame, subframe);
if (frame == current_frame) {
return subframe - current_subframe;
} else if (frame > current_frame) {
diff_in_subframes = ((frame*10)+subframe) - ((current_frame*10)+current_subframe);
// diff_in_subframes = 9 - current_subframe;
//diff_in_subframes += (subframe + 1);
//diff_in_subframes += (frame-2) * 10;
if (diff_in_subframes > SCHED_AHEAD_SUBFRAMES) {
return -1;
} else {
return 1;
}
} else { //frame < current_frame
//diff_in_subframes = 9 - current_subframe;
//diff_in_subframes += (subframe + 1);
//if (frame > 0) {
// diff_in_subframes += (frame - 1) * 10;
//}
//diff_in_subframes += (1023 - current_frame) * 10;
diff_in_subframes = 10240 - ((current_frame*10)+current_subframe) + ((frame*10)+subframe);
if (diff_in_subframes > SCHED_AHEAD_SUBFRAMES) {
return -1;
} else {
return 1;
}
}
}
@@ -0,0 +1,69 @@
/*
* 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_scheduler_dlsch_ue_remote.h
* \brief Local stub for remote scheduler used by the controller
* \author Xenofon Foukas
* \date 2016
* \email: x.foukas@sms.ed.ac.uk
* \version 0.1
* @ingroup _mac
*/
#ifndef __LAYER2_MAC_FLEXRAN_AGENT_SCHEDULER_DLSCH_UE_REMOTE_H__
#define __LAYER2_MAC_FLEXRAN_AGENT_SCHEDULER_DLSCH_UE_REMOTE_H___
#include "flexran.pb-c.h"
#include "header.pb-c.h"
#include "ENB_APP/flexran_agent_defs.h"
#include "flexran_agent_mac.h"
#include "LAYER2/MAC/flexran_agent_mac_proto.h"
#include <sys/queue.h>
// Maximum value of schedule ahead of time
// Required to identify if a dl_command is for the future or not
#define SCHED_AHEAD_SUBFRAMES 20
typedef struct dl_mac_config_element_s {
Protocol__FlexranMessage *dl_info;
TAILQ_ENTRY(dl_mac_config_element_s) configs;
} dl_mac_config_element_t;
TAILQ_HEAD(DlMacConfigHead, dl_mac_config_element_s);
/*
* Default scheduler used by the eNB agent
*/
void flexran_schedule_ue_spec_remote(mid_t mod_id, uint32_t frame, uint32_t subframe,
int *mbsfn_flag, Protocol__FlexranMessage **dl_info);
// Find the difference in subframes from the given subframe
// negative for older value
// 0 for equal
// positive for future value
// Based on
int get_sf_difference(mid_t mod_id, uint32_t sfn_sf);
#endif
@@ -0,0 +1,51 @@
/*
* 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_dci_conversions.h
* \brief Conversion helpers from flexran messages to OAI formats DCI
* \author Xenofon Foukas
* \date 2016
* \version 0.1
*/
#ifndef LAYER2_MAC_FLEXRAN_DCI_CONVERISIONS_H__
#define LAYER2_MAC_DCI_FLEXRAN_CONVERISIONS_H__
#define FILL_DCI_FDD_1(TYPE, DCI, FLEXRAN_DCI) \
((TYPE*)DCI)->harq_pid = FLEXRAN_DCI->harq_process; \
((TYPE*)DCI)->rv = FLEXRAN_DCI->rv[0]; \
((TYPE*)DCI)->rballoc = FLEXRAN_DCI->rb_bitmap; \
((TYPE*)DCI)->rah = FLEXRAN_DCI->res_alloc; \
((TYPE*)DCI)->mcs = FLEXRAN_DCI->mcs[0]; \
((TYPE*)DCI)->TPC = FLEXRAN_DCI->tpc; \
((TYPE*)DCI)->ndi = FLEXRAN_DCI->ndi[0];
#define FILL_DCI_TDD_1(TYPE, DCI, FLEXRAN_DCI) \
((TYPE*)DCI)->harq_pid = FLEXRAN_DCI->harq_process; \
((TYPE*)DCI)->rv = FLEXRAN_DCI->rv[0]; \
((TYPE*)DCI)->dai = FLEXRAN_DCI->dai; \
((TYPE*)DCI)->rballoc = FLEXRAN_DCI->rb_bitmap; \
((TYPE*)DCI)->rah = FLEXRAN_DCI->res_alloc; \
((TYPE*)DCI)->mcs = FLEXRAN_DCI->mcs[0]; \
((TYPE*)DCI)->TPC = FLEXRAN_DCI->tpc; \
((TYPE*)DCI)->ndi = FLEXRAN_DCI->ndi[0];
#endif
+2 -2
View File
@@ -763,7 +763,7 @@ void dlsch_scheduler_pre_processor_reset (int module_idP,
frameP,subframeP,
&ue_sched_ctl->harq_pid[CC_id],
&ue_sched_ctl->round[CC_id],
0);
openair_harq_DL);
if (ue_sched_ctl->ta_timer == 0) {
// WE SHOULD PROTECT the eNB_UE_stats with a mutex here ...
@@ -1028,7 +1028,7 @@ void ulsch_scheduler_pre_processor(module_id_t module_idP,
// This is the actual CC_id in the list
CC_id = UE_list->ordered_ULCCids[n][UE_id];
mac_xface->get_ue_active_harq_pid(module_idP,CC_id,rnti,frameP,subframeP,&harq_pid,&round,1);
mac_xface->get_ue_active_harq_pid(module_idP,CC_id,rnti,frameP,subframeP,&harq_pid,&round,openair_harq_UL);
if(round>0) {
nb_allocated_rbs[CC_id][UE_id] = UE_list->UE_template[CC_id][UE_id].nb_rb_ul[harq_pid];
+2
View File
@@ -28,6 +28,7 @@
*/
#ifndef __LAYER2_MAC_PROTO_H__
#define __LAYER2_MAC_PROTO_H__
/** \addtogroup _mac
* @{
*/
@@ -121,6 +122,7 @@ void fill_DLSCH_dci(module_id_t module_idP,frame_t frameP,sub_frame_t subframe,i
*/
void schedule_ue_spec(module_id_t module_idP,frame_t frameP,sub_frame_t subframe,int *mbsfn_flag);
/** \brief Function for UE/PHY to compute PUSCH transmit power in power-control procedure.
@param Mod_id Module id of UE
@returns Po_NOMINAL_PUSCH (PREAMBLE_RECEIVED_TARGET_POWER+DELTA_PREAMBLE
+4 -2
View File
@@ -115,11 +115,13 @@ int dump_eNB_l2_stats(char *buffer, int length)
for (CC_id=0 ; CC_id < MAX_NUM_CCs; CC_id++) {
eNB->eNB_stats[CC_id].dlsch_bitrate= 0;
len += sprintf(&buffer[len],"eNB %d CC %d Frame %d: Active UEs %d, Available PRBs %d, nCCE %d \n",
len += sprintf(&buffer[len],"eNB %d CC %d Frame %d: Active UEs %d, Available PRBs %d, nCCE %d, Scheduling decisions %d, Missed Deadlines %d \n",
eNB_id, CC_id, eNB->frame,
eNB->eNB_stats[CC_id].num_dlactive_UEs,
eNB->eNB_stats[CC_id].available_prbs,
eNB->eNB_stats[CC_id].available_ncces);
eNB->eNB_stats[CC_id].available_ncces,
eNB->eNB_stats[CC_id].sched_decisions,
eNB->eNB_stats[CC_id].missed_deadlines);
len += sprintf(&buffer[len],"BCCH , NB_TX_MAC = %d, transmitted bytes (TTI %d, total %d) MCS (TTI %d)\n",
eNB->eNB_stats[CC_id].total_num_bcch_pdu,
+27 -3
View File
@@ -93,6 +93,9 @@
#include "SIMULATION/TOOLS/defs.h" // for taus
#if defined(FLEXRAN_AGENT_SB_IF)
#include "flexran_agent_extern.h"
#endif
#define XER_PRINT
#ifdef PHY_EMUL
@@ -644,6 +647,9 @@ void rrc_eNB_emulation_notify_ue_module_id(
// find enb_module_id
for (enb_module_id = 0; enb_module_id < NUMBER_OF_eNB_MAX; enb_module_id++) {
if(enb_module_id>0){ /*FIX LATER*/
return;
}
for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
if (eNB_rrc_inst[enb_module_id].carrier[CC_id].sib1 != NULL) {
if (
@@ -652,7 +658,6 @@ void rrc_eNB_emulation_notify_ue_module_id(
(eNB_rrc_inst[enb_module_id].carrier[CC_id].sib1->cellAccessRelatedInfo.cellIdentity.buf[2] == cell_identity_byte2P) &&
(eNB_rrc_inst[enb_module_id].carrier[CC_id].sib1->cellAccessRelatedInfo.cellIdentity.buf[3] == cell_identity_byte3P)
) {
oai_emulation.info.eNB_ue_module_id_to_rnti[enb_module_id][ue_module_idP] = rntiP;
ue_context_p = rrc_eNB_get_ue_context(
&eNB_rrc_inst[enb_module_id],
rntiP
@@ -662,10 +667,11 @@ void rrc_eNB_emulation_notify_ue_module_id(
oai_emulation.info.eNB_ue_local_uid_to_ue_module_id[enb_module_id][ue_context_p->local_uid] = ue_module_idP;
}
return;
//return;
}
}
}
oai_emulation.info.eNB_ue_module_id_to_rnti[enb_module_id][ue_module_idP] = rntiP;
}
AssertFatal(enb_module_id == NUMBER_OF_eNB_MAX,
@@ -4535,7 +4541,16 @@ rrc_eNB_decode_dcch(
rrc_eNB_process_RRCConnectionReconfigurationComplete(
ctxt_pP,
ue_context_p,
ul_dcch_msg->message.choice.c1.choice.rrcConnectionReconfigurationComplete.rrc_TransactionIdentifier);
ul_dcch_msg->message.choice.c1.choice.rrcConnectionReconfigurationComplete.rrc_TransactionIdentifier);
#if defined(FLEXRAN_AGENT_SB_IF)
//WARNING:Inform the controller about the UE activation. Should be moved to RRC agent in the future
if (mac_agent_registered[ctxt_pP->module_id]) {
agent_mac_xface[ctxt_pP->eNB_index]->flexran_agent_notify_ue_state_change(ctxt_pP->module_id,
ue_context_p->ue_id_rnti,
PROTOCOL__FLEX_UE_STATE_CHANGE_TYPE__FLUESC_UPDATED);
}
#endif
}
#if defined(ENABLE_ITTI)
# if defined(ENABLE_USE_MME)
@@ -4631,6 +4646,15 @@ rrc_eNB_decode_dcch(
ue_context_p->ue_context.Status = RRC_CONNECTED;
LOG_I(RRC, PROTOCOL_RRC_CTXT_UE_FMT" UE State = RRC_CONNECTED \n",
PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP));
#if defined(FLEXRAN_AGENT_SB_IF)
//WARNING:Inform the controller about the UE activation. Should be moved to RRC agent in the future
if (mac_agent_registered[ctxt_pP->module_id]) {
agent_mac_xface[ctxt_pP->eNB_index]->flexran_agent_notify_ue_state_change(ctxt_pP->module_id,
ue_context_p->ue_id_rnti,
PROTOCOL__FLEX_UE_STATE_CHANGE_TYPE__FLUESC_ACTIVATED);
}
#endif
}
}
+254
View File
@@ -0,0 +1,254 @@
/*
* 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 link_manager.c
* \brief this is the implementation of a link manager
* \author Cedric Roux
* \date November 2015
* \version 1.0
* \email: cedric.roux@eurecom.fr
* @ingroup _mac
*/
#include "link_manager.h"
#include "log.h"
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
/* that thread reads messages in the queue and sends them to the link */
static void *link_manager_sender_thread(void *_manager)
{
link_manager_t *manager = _manager;
void *data;
int size;
int priority;
LOG_D(MAC, "starting link manager sender thread\n");
while (manager->run) {
while (message_get(manager->send_queue, &data, &size, &priority) == 0) {
link_send_packet(manager->socket_link, data, size);
free(data);
}
// if (message_get(manager->send_queue, &data, &size, &priority))
// goto error;
//if (link_send_packet(manager->socket_link, data, size))
// goto error;
//free(data);
}
LOG_D(MAC, "link manager sender thread quits\n");
return NULL;
error:
LOG_E(MAC, "%s: error\n", __FUNCTION__);
return NULL;
}
/* that thread receives messages from the link and puts them in the queue */
static void *link_manager_receiver_thread(void *_manager)
{
link_manager_t *manager = _manager;
void *data;
int size;
LOG_D(MAC, "starting link manager receiver thread\n");
while (manager->run) {
if (link_receive_packet(manager->socket_link, &data, &size))
goto error;
/* todo: priority */
if (message_put(manager->receive_queue, data, size, 0))
goto error;
}
LOG_D(MAC, "link manager receiver thread quits\n");
return NULL;
error:
LOG_E(MAC, "%s: error\n", __FUNCTION__);
return NULL;
}
link_manager_t *create_link_manager(
message_queue_t *send_queue,
message_queue_t *receive_queue,
socket_link_t *link)
{
link_manager_t *ret = NULL;
pthread_attr_t attr;
pthread_t t;
LOG_D(MAC, "create new link manager\n");
ret = calloc(1, sizeof(link_manager_t));
if (ret == NULL)
goto error;
ret->send_queue = send_queue;
ret->receive_queue = receive_queue;
ret->socket_link = link;
ret->run = 1;
if (pthread_attr_init(&attr))
goto error;
// Make the async interface threads real-time
//#ifndef LOWLATENCY
struct sched_param sched_param_recv_thread;
struct sched_param sched_param_send_thread;
sched_param_recv_thread.sched_priority = sched_get_priority_max(SCHED_RR) - 1;
pthread_attr_setschedparam(&attr, &sched_param_recv_thread);
pthread_attr_setschedpolicy(&attr, SCHED_RR);
//#endif
if (pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED))
goto error;
if (pthread_create(&t, &attr, link_manager_sender_thread, ret))
goto error;
ret->sender = t;
if (pthread_create(&t, &attr, link_manager_receiver_thread, ret))
/* we should destroy the other thread here */
goto error;
ret->receiver = t;
if (pthread_attr_destroy(&attr))
/* to be clean we should destroy the threads at this point,
* even if in practice we never reach it */
goto error;
return ret;
error:
LOG_E(MAC, "%s: an error occured\n", __FUNCTION__);
free(ret);
return NULL;
}
void destroy_link_manager(link_manager_t *manager)
{
LOG_D(MAC, "destroying link manager\n");
manager->run = 0;
/* todo: force threads to stop (using a dummy message?) */
}
#ifdef SERVER_TEST
#include <string.h>
int main(void)
{
socket_link_t *link;
message_queue_t *send_queue;
message_queue_t *receive_queue;
link_manager_t *manager;
void *data;
int size;
int priority;
printf("starting server\n");
link = new_link_server(2210);
if (link == NULL) goto error;
send_queue = new_message_queue();
if (send_queue == NULL) goto error;
receive_queue = new_message_queue();
if (receive_queue == NULL) goto error;
manager = create_link_manager(send_queue, receive_queue, link);
if (manager == NULL) goto error;
data = strdup("hello"); if (data == NULL) goto error;
if (message_put(send_queue, data, 6, 100)) goto error;
if (message_get(receive_queue, &data, &size, &priority)) goto error;
printf("received message:\n");
printf(" data: %s\n", (char *)data);
printf(" size: %d\n", size);
printf(" priority: %d\n", priority);
printf("server ends\n");
return 0;
error:
printf("there was an error\n");
return 1;
}
#endif
#ifdef CLIENT_TEST
#include <string.h>
#include <unistd.h>
int main(void)
{
socket_link_t *link;
message_queue_t *send_queue;
message_queue_t *receive_queue;
link_manager_t *manager;
void *data;
int size;
int priority;
printf("starting client\n");
link = new_link_client("127.0.0.1", 2210);
if (link == NULL) goto error;
send_queue = new_message_queue();
if (send_queue == NULL) goto error;
receive_queue = new_message_queue();
if (receive_queue == NULL) goto error;
manager = create_link_manager(send_queue, receive_queue, link);
if (manager == NULL) goto error;
if (message_get(receive_queue, &data, &size, &priority)) goto error;
printf("received message:\n");
printf(" data: %s\n", (char *)data);
printf(" size: %d\n", size);
printf(" priority: %d\n", priority);
data = strdup("world"); if (data == NULL) goto error;
if (message_put(send_queue, data, 6, 200)) goto error;
/* let's wait for the message to be sent (unreliable sleep, but does it for the test) */
sleep(1);
printf("client ends\n");
return 0;
error:
printf("there was an error\n");
return 1;
}
#endif
+63
View File
@@ -0,0 +1,63 @@
/*
* 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 link_manager.h
* \brief this is the implementation of a link manager
* \author Cedric Roux
* \date November 2015
* \version 1.0
* \email: cedric.roux@eurecom.fr
* @ingroup _mac
*/
#ifndef LINK_MANAGER_H
#define LINK_MANAGER_H
//#include "message_queue.h"
#include "ringbuffer_queue.h"
#include "socket_link.h"
#include <pthread.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
message_queue_t *send_queue;
message_queue_t *receive_queue;
socket_link_t *socket_link;
pthread_t sender;
pthread_t receiver;
volatile int run;
} link_manager_t;
link_manager_t *create_link_manager(
message_queue_t *send_queue,
message_queue_t *receive_queue,
socket_link_t *link);
void destroy_link_manager(link_manager_t *);
#ifdef __cplusplus
}
#endif
#endif /* LINK_MANAGER_H */
+204
View File
@@ -0,0 +1,204 @@
/*
* 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 message_queue.c
* \brief this is the implementation of a message queue
* \author Cedric Roux
* \date November 2015
* \version 1.0
* \email: cedric.roux@eurecom.fr
* @ingroup _mac
*/
#include "message_queue.h"
#include "log.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
message_queue_t *new_message_queue(void)
{
message_queue_t *ret = NULL;
ret = calloc(1, sizeof(message_queue_t));
if (ret == NULL)
goto error;
ret->mutex = calloc(1, sizeof(pthread_mutex_t));
if (ret->mutex == NULL)
goto error;
if (pthread_mutex_init(ret->mutex, NULL))
goto error;
ret->cond = calloc(1, sizeof(pthread_cond_t));
if (ret->cond == NULL)
goto error;
if (pthread_cond_init(ret->cond, NULL))
goto error;
return ret;
error:
LOG_E(MAC, "%s: an error occured\n", __FUNCTION__);
if (ret != NULL) {
free(ret->mutex);
free(ret->cond);
memset(ret, 0, sizeof(message_queue_t));
free(ret);
}
return NULL;
}
int message_put(message_queue_t *queue, void *data, int size, int priority)
{
message_t *m = NULL;
m = calloc(1, sizeof(message_t));
if (m == NULL)
goto error;
m->data = data;
m->size = size;
m->priority = priority;
m->next = NULL;
if (pthread_mutex_lock(queue->mutex))
goto error;
if (queue->count == 0)
queue->head = m;
else
queue->tail->next = m;
queue->tail = m;
queue->count++;
if (pthread_cond_signal(queue->cond)) {
LOG_E(MAC, "%s:%d:%s: fatal error\n", __FILE__, __LINE__, __FUNCTION__);
pthread_mutex_unlock(queue->mutex);
exit(1);
}
if (pthread_mutex_unlock(queue->mutex)) {
LOG_E(MAC, "%s:%d:%s: fatal error\n", __FILE__, __LINE__, __FUNCTION__);
exit(1);
}
return 0;
error:
free(m);
LOG_E(MAC, "%s: an error occured\n", __FUNCTION__);
return -1;
}
int message_get(message_queue_t *queue, void **data, int *size, int *priority)
{
message_t *m;
if (pthread_mutex_lock(queue->mutex))
goto error;
while (queue->count == 0) {
if (pthread_cond_wait(queue->cond, queue->mutex)) {
pthread_mutex_unlock(queue->mutex);
goto error;
}
}
m = queue->head;
queue->head = queue->head->next;
if (queue->head == NULL)
queue->tail = NULL;
queue->count--;
if (pthread_mutex_unlock(queue->mutex))
goto error;
*data = m->data;
*size = m->size;
*priority = m->priority;
free(m);
return 0;
error:
LOG_E(MAC, "%s: an error occured\n", __FUNCTION__);
return -1;
}
/* when calling this function, the queue must not be used anymore (we don't lock it) */
/* we suppose that the data pointer in messages was allocated by malloc/calloc/realloc */
void destroy_message_queue(message_queue_t *queue)
{
while (queue->head) {
message_t *m = queue->head;
queue->head = queue->head->next;
free(m->data);
memset(m, 0, sizeof(message_t));
free(m);
}
free(queue->mutex);
free(queue->cond);
memset(queue, 0, sizeof(message_queue_t));
free(queue);
}
#ifdef TEST
/* some very basic tests */
int main(void)
{
void *data;
int size;
int priority;
message_queue_t *q;
char *s;
q = new_message_queue();
if (q == NULL) goto error;
if (message_put(q, "hello", 6, 0)) goto error;
if (message_put(q, "world", 6, 1)) goto error;
if (message_get(q, &data, &size, &priority)) goto error;
printf("message:\n data: '%s'\n size: %d\n priority: %d\n",
(char *)data, size, priority);
if (message_get(q, &data, &size, &priority)) goto error;
printf("message:\n data: '%s'\n size: %d\n priority: %d\n",
(char *)data, size, priority);
/* let's put a message before destroying the queue */
s = malloc(10); if (s == NULL) goto error;
sprintf(s, "hello");
if (message_put(q, s, 6, 0)) goto error;
destroy_message_queue(q);
return 0;
error:
printf("error\n");
return 1;
}
#endif
+64
View File
@@ -0,0 +1,64 @@
/*
* 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 message_queue.h
* \brief this is the implementation of a message queue
* \author Cedric Roux
* \date November 2015
* \version 1.0
* \email: cedric.roux@eurecom.fr
* @ingroup _mac
*/
#ifndef MESSAGE_QUEUE_H
#define MESSAGE_QUEUE_H
#include <pthread.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct message_t {
void *data;
int size;
int priority;
struct message_t *next;
} message_t;
typedef struct {
message_t *head;
message_t *tail;
volatile int count;
pthread_mutex_t *mutex;
pthread_cond_t *cond;
} message_queue_t;
message_queue_t *new_message_queue(void);
int message_put(message_queue_t *queue, void *data, int size, int priority);
int message_get(message_queue_t *queue, void **data, int *size, int *priority);
void destroy_message_queue(message_queue_t *queue);
#ifdef __cplusplus
}
#endif
#endif /* MESSAGE_QUEUE_H */
+136
View File
@@ -0,0 +1,136 @@
/*
* 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 ringbuffer_queue.c
* \brief Lock-free ringbuffer used for async message passing of agent
* \author Xenofon Foukas
* \date March 2016
* \version 1.0
* \email: x.foukas@sms.ed.ac.uk
* @ingroup _mac
*/
#include "ringbuffer_queue.h"
#include "log.h"
message_queue_t * new_message_queue(int size) {
message_queue_t *ret = NULL;
ret = calloc(1, sizeof(message_queue_t));
if (ret == NULL)
goto error;
lfds700_misc_library_init_valid_on_current_logical_core();
lfds700_misc_prng_init(&(ret->ps));
ret->ringbuffer_array = malloc(sizeof(struct lfds700_ringbuffer_element) * size);
lfds700_ringbuffer_init_valid_on_current_logical_core(&(ret->ringbuffer_state),
ret->ringbuffer_array,
size,
&(ret->ps),
NULL);
return ret;
error:
LOG_E(MAC, "%s: an error occured\n", __FUNCTION__);
if (ret != NULL) {
free(ret->ringbuffer_array);
memset(ret, 0, sizeof(message_queue_t));
free(ret);
}
return NULL;
}
int message_put(message_queue_t *queue, void *data, int size, int priority) {
struct lfds700_misc_prng_state ls;
enum lfds700_misc_flag overwrite_occurred_flag;
message_t *overwritten_msg;
message_t *m = NULL;
LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
lfds700_misc_prng_init(&ls);
m = calloc(1, sizeof(message_t));
if (m == NULL)
goto error;
m->data = data;
m->size = size;
m->priority = priority;
lfds700_ringbuffer_write(&(queue->ringbuffer_state),
NULL,
(void *) m,
&overwrite_occurred_flag,
NULL,
(void **) &overwritten_msg,
&ls);
if (overwrite_occurred_flag == LFDS700_MISC_FLAG_RAISED) {
free(overwritten_msg->data);
free(overwritten_msg);
}
return 0;
error:
free(m);
LOG_E(MAC, "%s: an error occured\n", __FUNCTION__);
return -1;
}
int message_get(message_queue_t *queue, void **data, int *size, int *priority) {
message_t *m;
struct lfds700_misc_prng_state ls;
LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
lfds700_misc_prng_init(&ls);
if (lfds700_ringbuffer_read(&(queue->ringbuffer_state), NULL, (void **) &m, &ls) == 0) {
return -1;
}
*data = m->data;
*size = m->size;
*priority = m->priority;
free(m);
return 0;
}
message_queue_t destroy_message_queue(message_queue_t *queue) {
struct lfds700_misc_prng_state ls;
message_t *m;
LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
lfds700_misc_prng_init(&ls);
while (lfds700_ringbuffer_read(&(queue->ringbuffer_state), NULL, (void **) &m, &ls) != 0) {
free(m->data);
memset(m, 0, sizeof(message_t));
free(m);
}
free(queue->ringbuffer_array);
memset(queue, 0, sizeof(message_queue_t));
free(queue);
}
+53
View File
@@ -0,0 +1,53 @@
/*
* 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 ringbuffer_queue.h
* \brief Lock-free ringbuffer used for async message passing of agent
* \author Xenofon Foukas
* \date March 2016
* \version 1.0
* \email: x.foukas@sms.ed.ac.uk
* @ingroup _mac
*/
#ifndef RINGBUFFER_QUEUE_H
#define RINGBUFFER_QUEUE_H
#include "liblfds700.h"
typedef struct message_s {
void *data;
int size;
int priority;
} message_t;
typedef struct {
struct lfds700_misc_prng_state ps;
struct lfds700_ringbuffer_element *ringbuffer_array;
struct lfds700_ringbuffer_state ringbuffer_state;
} message_queue_t;
message_queue_t * new_message_queue(int size);
int message_put(message_queue_t *queue, void *data, int size, int priority);
int message_get(message_queue_t *queue, void **data, int *size, int *priority);
message_queue_t destroy_message_queue(message_queue_t *queue);
#endif /* RINGBUFFER_QUEUE_H */
+357
View File
@@ -0,0 +1,357 @@
/*
* 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 socket_link.c
* \brief this is the implementation of a TCP socket ASYNC IF
* \author Cedric Roux
* \date November 2015
* \version 1.0
* \email: cedric.roux@eurecom.fr
* @ingroup _mac
*/
#include "socket_link.h"
#include "log.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <stdint.h>
socket_link_t *new_link_server(int port)
{
socket_link_t *ret = NULL;
int reuse;
struct sockaddr_in addr;
socklen_t addrlen;
int socket_server = -1;
int no_delay;
ret = calloc(1, sizeof(socket_link_t));
if (ret == NULL) {
LOG_E(MAC, "%s:%d: out of memory\n", __FILE__, __LINE__);
goto error;
}
ret->socket_fd = -1;
LOG_D(MAC, "create a new link server socket at port %d\n", port);
socket_server = socket(AF_INET, SOCK_STREAM, 0);
if (socket_server == -1) {
LOG_E(MAC, "%s:%d: socket: %s\n", __FILE__, __LINE__, strerror(errno));
goto error;
}
reuse = 1;
if (setsockopt(socket_server, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) == -1) {
LOG_E(MAC, "%s:%d: setsockopt: %s\n", __FILE__, __LINE__, strerror(errno));
goto error;
}
no_delay = 1;
if (setsockopt(socket_server, IPPROTO_TCP, TCP_NODELAY, &no_delay, sizeof(no_delay)) == -1) {
LOG_E(MAC, "%s:%d: setsockopt: %s\n", __FILE__, __LINE__, strerror(errno));
goto error;
}
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = INADDR_ANY;
if (bind(socket_server, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
LOG_E(MAC, "%s:%d: bind: %s\n", __FILE__, __LINE__, strerror(errno));
goto error;
}
if (listen(socket_server, 5)) {
LOG_E(MAC, "%s:%d: listen: %s\n", __FILE__, __LINE__, strerror(errno));
goto error;
}
addrlen = sizeof(addr);
ret->socket_fd = accept(socket_server, (struct sockaddr *)&addr, &addrlen);
if (ret->socket_fd == -1) {
LOG_E(MAC, "%s:%d: accept: %s\n", __FILE__, __LINE__, strerror(errno));
goto error;
}
close(socket_server);
LOG_D(MAC, "connection from %s:%d\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
return ret;
error:
close(socket_server);
if (ret != NULL) close(ret->socket_fd);
free(ret);
LOG_E(MAC, "ERROR in new_link_server (see above), returning NULL\n");
return NULL;
}
socket_link_t *new_link_client(char *server, int port)
{
socket_link_t *ret = NULL;
struct sockaddr_in addr;
int no_delay;
ret = calloc(1, sizeof(socket_link_t));
if (ret == NULL) {
LOG_E(MAC, "%s:%d: out of memory\n", __FILE__, __LINE__);
goto error;
}
ret->socket_fd = -1;
LOG_D(MAC, "create a new link client socket connecting to %s:%d\n", server, port);
ret->socket_fd = socket(AF_INET, SOCK_STREAM, 0);
if (ret->socket_fd == -1) {
LOG_E(MAC, "%s:%d: socket: %s\n", __FILE__, __LINE__, strerror(errno));
goto error;
}
no_delay = 1;
if (setsockopt(ret->socket_fd, SOL_TCP, TCP_NODELAY, &no_delay, sizeof(no_delay)) == -1) {
LOG_E(MAC, "%s:%d: setsockopt: %s\n", __FILE__, __LINE__, strerror(errno));
goto error;
}
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
if (inet_aton(server, &addr.sin_addr) == 0) {
LOG_E(MAC, "invalid IP address '%s', use a.b.c.d notation\n", server);
goto error;
}
if (connect(ret->socket_fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
LOG_E(MAC, "%s:%d: connect: %s\n", __FILE__, __LINE__, strerror(errno));
goto error;
}
LOG_D(MAC, "connection to %s:%d established\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
return ret;
error:
if (ret != NULL) close(ret->socket_fd);
free(ret);
LOG_E(MAC, "ERROR in new_link_client (see above), returning NULL\n");
return NULL;
}
/*
* return -1 on error and 0 if the sending was fine
*/
static int socket_send(int socket_fd, void *buf, int size)
{
char *s = buf;
int l;
while (size) {
l = send(socket_fd, s, size, MSG_NOSIGNAL);
if (l == -1) goto error;
if (l == 0) { LOG_E(MAC, "%s:%d: this cannot happen, normally...\n", __FILE__, __LINE__); abort(); }
size -= l;
s += l;
}
return 0;
error:
LOG_E(MAC, "socket_send: ERROR: %s\n", strerror(errno));
return -1;
}
/*
* return -1 on error and 0 if the receiving was fine
*/
static int socket_receive(int socket_fd, void *buf, int size)
{
char *s = buf;
int l;
while (size) {
l = read(socket_fd, s, size);
if (l == -1) goto error;
if (l == 0) goto socket_closed;
size -= l;
s += l;
}
return 0;
error:
LOG_E(MAC, "socket_receive: ERROR: %s\n", strerror(errno));
return -1;
socket_closed:
LOG_E(MAC, "socket_receive: socket closed\n");
return -1;
}
/*
* return -1 on error and 0 if the sending was fine
*/
int link_send_packet(socket_link_t *link, void *data, int size)
{
char sizebuf[4];
int32_t s = size;
/* send the size first, maximum is 2^31 bytes */
sizebuf[0] = (s >> 24) & 255;
sizebuf[1] = (s >> 16) & 255;
sizebuf[2] = (s >> 8) & 255;
sizebuf[3] = s & 255;
if (socket_send(link->socket_fd, sizebuf, 4) == -1)
goto error;
link->bytes_sent += 4;
if (socket_send(link->socket_fd, data, size) == -1)
goto error;
link->bytes_sent += size;
link->packets_sent++;
return 0;
error:
return -1;
}
/*
* return -1 on error and 0 if the sending was fine
*/
int link_receive_packet(socket_link_t *link, void **ret_data, int *ret_size)
{
unsigned char sizebuf[4];
int32_t size;
void *data = NULL;
/* received the size first, maximum is 2^31 bytes */
if (socket_receive(link->socket_fd, sizebuf, 4) == -1)
goto error;
size = (sizebuf[0] << 24) |
(sizebuf[1] << 16) |
(sizebuf[2] << 8) |
sizebuf[3];
link->bytes_received += 4;
data = malloc(size);
if (data == NULL) {
LOG_E(MAC, "%s:%d: out of memory\n", __FILE__, __LINE__);
goto error;
}
if (socket_receive(link->socket_fd, data, size) == -1)
goto error;
link->bytes_received += size;
link->packets_received++;
*ret_data = data;
*ret_size = size;
return 0;
error:
free(data);
*ret_data = NULL;
*ret_size = 0;
return -1;
}
/*
* return -1 on error, 0 if all is fine
*/
int close_link(socket_link_t *link)
{
close(link->socket_fd);
memset(link, 0, sizeof(socket_link_t));
free(link);
return 0;
}
#ifdef SERVER_TEST
#include <inttypes.h>
int main(void)
{
void *data;
int size;
socket_link_t *l = new_link_server(2210);
if (l == NULL) { printf("no link created\n"); return 1; }
printf("link is up\n");
printf("server starts sleeping...\n");
/* this sleep is here to test for broken pipe. You can run "nc localhost 2210"
* and interrupt it quickly so that the server gets a 'broken' pipe on the
* following link_send_packet.
*/
sleep(1);
printf("... done\n");
if (link_send_packet(l, "hello\n", 6+1) ||
link_send_packet(l, "world\n", 6+1)) return 1;
if (link_receive_packet(l, &data, &size)) return 1; printf("%s", (char *)data); free(data);
if (link_receive_packet(l, &data, &size)) return 1; printf("%s", (char *)data); free(data);
printf("stats:\n");
printf(" sent packets %"PRIu64"\n", l->packets_sent);
printf(" sent bytes %"PRIu64"\n", l->bytes_sent);
printf(" received packets %"PRIu64"\n", l->packets_received);
printf(" received bytes %"PRIu64"\n", l->bytes_received);
if (close_link(l)) return 1;
printf("link is down\n");
return 0;
}
#endif
#ifdef CLIENT_TEST
#include <inttypes.h>
int main(void)
{
void *data;
int size;
socket_link_t *l = new_link_client("127.0.0.1", 2210);
if (l == NULL) { printf("no link created\n"); return 1; }
printf("link is up\n");
if (link_receive_packet(l, &data, &size)) return 1; printf("%s", (char *)data); free(data);
if (link_receive_packet(l, &data, &size)) return 1; printf("%s", (char *)data); free(data);
if (link_send_packet(l, "bye\n", 4+1) ||
link_send_packet(l, "server\n", 7+1)) return 1;
printf("stats:\n");
printf(" sent packets %"PRIu64"\n", l->packets_sent);
printf(" sent bytes %"PRIu64"\n", l->bytes_sent);
printf(" received packets %"PRIu64"\n", l->packets_received);
printf(" received bytes %"PRIu64"\n", l->bytes_received);
if (close_link(l)) return 1;
printf("link is down\n");
return 0;
}
#endif
+58
View File
@@ -0,0 +1,58 @@
/*
* 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 socket_link.h
* \brief this is the implementation of a TCP socket ASYNC IF
* \author Cedric Roux
* \date November 2015
* \version 1.0
* \email: cedric.roux@eurecom.fr
* @ingroup _mac
*/
#ifndef SOCKET_LINK_H
#define SOCKET_LINK_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
int socket_fd;
uint64_t bytes_sent;
uint64_t packets_sent;
uint64_t bytes_received;
uint64_t packets_received;
} socket_link_t;
socket_link_t *new_link_server(int port);
socket_link_t *new_link_client(char *server, int port);
int link_send_packet(socket_link_t *link, void *data, int size);
int link_receive_packet(socket_link_t *link, void **data, int *size);
int close_link(socket_link_t *link);
#ifdef __cplusplus
}
#endif
#endif /* SOCKET_LINK_H */
@@ -0,0 +1,168 @@
##### paths #####
BINDIR := ../../bin
INCDIR := ../../inc
OBJDIR := ../../obj
SRCDIR := ../../src
##### misc #####
QUIETLY := 1>/dev/null 2>/dev/null
VERSION_NUMBER := 1
MINOR_NUMBER := 0
RELEASE_NUMBER := 0
##### sources, objects and libraries #####
BINNAME := liblfds700
ARFILENAME := $(BINNAME).a
ARPATHNAME := $(BINDIR)/$(ARFILENAME)
SOBASENAME := $(BINNAME).so
SONAME := $(SOBASENAME).$(VERSION_NUMBER)
SOFILENAME := $(SONAME).$(MINOR_NUMBER).$(RELEASE_NUMBER)
SOPATHNAME := $(BINDIR)/$(SOFILENAME)
INCNAME := $(INCDIR)/$(BINNAME).h
SRCDIRS := lfds700_btree_addonly_unbalanced lfds700_freelist lfds700_hash_addonly lfds700_list_addonly_ordered_singlylinked lfds700_list_addonly_singlylinked_unordered lfds700_misc lfds700_queue lfds700_queue_bounded_singleconsumer_singleproducer lfds700_ringbuffer lfds700_stack
SOURCES := lfds700_hash_addonly_cleanup.c lfds700_hash_addonly_get.c lfds700_hash_addonly_init.c lfds700_hash_addonly_insert.c lfds700_hash_addonly_iterate.c lfds700_hash_addonly_query.c \
lfds700_list_addonly_ordered_singlylinked_cleanup.c lfds700_list_addonly_ordered_singlylinked_get.c lfds700_list_addonly_ordered_singlylinked_init.c lfds700_list_addonly_ordered_singlylinked_insert.c lfds700_list_addonly_ordered_singlylinked_query.c \
lfds700_list_addonly_singlylinked_unordered_cleanup.c lfds700_list_addonly_singlylinked_unordered_get.c lfds700_list_addonly_singlylinked_unordered_init.c lfds700_list_addonly_singlylinked_unordered_insert.c lfds700_list_addonly_singlylinked_unordered_query.c \
lfds700_btree_addonly_unbalanced_cleanup.c lfds700_btree_addonly_unbalanced_get.c lfds700_btree_addonly_unbalanced_init.c lfds700_btree_addonly_unbalanced_insert.c lfds700_btree_addonly_unbalanced_query.c \
lfds700_freelist_cleanup.c lfds700_freelist_init.c lfds700_freelist_pop.c lfds700_freelist_push.c lfds700_freelist_query.c \
lfds700_misc_cleanup.c lfds700_misc_globals.c lfds700_misc_init.c lfds700_misc_prng.c lfds700_misc_query.c \
lfds700_queue_cleanup.c lfds700_queue_dequeue.c lfds700_queue_enqueue.c lfds700_queue_init.c lfds700_queue_query.c \
lfds700_queue_bounded_singleconsumer_singleproducer_cleanup.c lfds700_queue_bounded_singleconsumer_singleproducer_dequeue.c lfds700_queue_bounded_singleconsumer_singleproducer_enqueue.c lfds700_queue_bounded_singleconsumer_singleproducer_init.c lfds700_queue_bounded_singleconsumer_singleproducer_query.c \
lfds700_ringbuffer_cleanup.c lfds700_ringbuffer_init.c lfds700_ringbuffer_query.c lfds700_ringbuffer_read.c lfds700_ringbuffer_write.c \
lfds700_stack_cleanup.c lfds700_stack_init.c lfds700_stack_pop.c lfds700_stack_push.c lfds700_stack_query.c
OBJECTS := $(patsubst %.c,$(OBJDIR)/%.o,$(notdir $(SOURCES)))
SYSLIBS :=
##### default paths fix up #####
CPATH := $(subst : ,:,$(SRCDIR):$(INCDIR))
##### tools #####
MAKE := make
MFLAGS :=
DG := gcc
DGFLAGS := -MM -std=gnu89
CC := gcc
CFBASE := -c -fno-strict-aliasing -std=gnu89 -Wall -Werror -Wno-unknown-pragmas -Wno-unused-but-set-variable -Wno-unused-variable
CFCOV := -O0 -ggdb -DCOVERAGE -fprofile-arcs -ftest-coverage
CFDBG := -O0 -ggdb -D_DEBUG
CFPROF := -O0 -ggdb -DPROF -pg
CFREL := -O2 -DNDEBUG -finline-functions
CFTSAN := -O0 -ggdb -DTSAN -fsanitize=thread -fPIC
CFBARE := -ffreestanding -nodefaultlibs -nostdinc -nostdlib
AR := ar
AFLAGS := -rcs
LD := gcc
LFBASE := -pthread -shared -std=gnu89 -Wl,-soname,$(SONAME) -o $(SOPATHNAME) -Wall -Werror
LFCOV := -O0 -fprofile-arcs -ftest-coverage
LFDBG := -O0 -ggdb
LFPROF := -O0 -pg
LFREL := -O2 -s -finline-functions
LFTSAN := -O0 -fsanitize=thread -fPIC
LFBARE := -ffreestanding -nodefaultlibs -nostdinc -nostdlib
##### CPU variants #####
GCCARCH := native
CFBASE += -march=$(GCCARCH)
##### build variants #####
ifeq ($(findstring so,$(MAKECMDGOALS)),so)
CFBASE += -fPIC
endif
CFLAGS += $(CFBASE)
LFLAGS += $(LFBASE)
ifeq ($(MAKECMDGOALS),)
CFLAGS += $(CFDBG)
LFLAGS += $(LFDBG)
endif
ifeq ($(findstring cov,$(MAKECMDGOALS)),cov)
CFLAGS += $(CFCOV)
LFLAGS += $(LFCOV)
SYSLIBS += -lgcov
endif
ifeq ($(findstring dbg,$(MAKECMDGOALS)),dbg)
CFLAGS += $(CFDBG)
LFLAGS += $(LFDBG)
endif
ifeq ($(findstring prof,$(MAKECMDGOALS)),prof)
CFLAGS += $(CFPROF)
LFLAGS += $(LFPROF)
endif
ifeq ($(findstring rel,$(MAKECMDGOALS)),rel)
CFLAGS += $(CFREL)
LFLAGS += $(LFREL)
endif
ifeq ($(findstring tsan,$(MAKECMDGOALS)),tsan)
CFLAGS += $(CFTSAN)
LFLAGS += $(LFTSAN)
endif
ifeq ($(findstring b_,$(MAKECMDGOALS)),b_)
CFLAGS += $(CFBARE)
LFLAGS += $(CFBARE)
endif
##### search paths #####
vpath %.c $(patsubst %,$(SRCDIR)/%:,$(SRCDIRS))
##### implicit rules #####
$(OBJDIR)/%.o : %.c
$(DG) $(DGFLAGS) $< >$(OBJDIR)/$*.d
$(CC) $(CFLAGS) -o $@ $<
##### explicit rules #####
$(ARPATHNAME) : $(OBJECTS)
$(AR) $(AFLAGS) $(ARPATHNAME) $(OBJECTS)
$(SOPATHNAME) : $(OBJECTS)
$(LD) $(LFLAGS) $(OBJECTS) -o $(SOPATHNAME)
@ln -fs $(SOFILENAME) $(BINDIR)/$(SONAME)
@ln -fs $(SOFILENAME) $(BINDIR)/$(SOBASENAME)
##### phony #####
.PHONY : clean bare_ar_cov bare_ar_dbg bare_ar_prof bare_ar_rel bare_ar_tsan bare_so_cov bare_so_dbg bare_so_prof bare_so_rel bare_so_tsan hosted_ar_cov hosted_ar_dbg hosted_ar_prof hosted_ar_rel hosted_ar_tsan hosted_so_cov hosted_so_dbg hosted_so_prof hosted_so_rel hosted_so_tsan
clean :
@rm -f $(BINDIR)/* $(OBJDIR)/*
bare_ar_cov : $(ARPATHNAME) # bare, archive (.a), coverage
bare_ar_dbg : $(ARPATHNAME) # bare, archive (.a), debug
bare_ar_prof : $(ARPATHNAME) # bare, archive (.a), profiling
bare_ar_rel : $(ARPATHNAME) # bare, archive (.a), release
bare_ar_tsan : $(ARPATHNAME) # bare, archive (.a), thread sanitizer
bare_so_cov : $(SOPATHNAME) # bare, shared (.so), coverage
bare_so_dbg : $(SOPATHNAME) # bare, shared (.so), debug
bare_so_prof : $(SOPATHNAME) # bare, shared (.so), profiling
bare_so_rel : $(SOPATHNAME) # bare, shared (.so), release
bare_so_tsan : $(SOPATHNAME) # bare, shared (.so), thread sanitizer
hosted_ar_cov : $(ARPATHNAME) # hosted implementation, archive (.a), coverage
hosted_ar_dbg : $(ARPATHNAME) # hosted implementation, archive (.a), debug
hosted_ar_prof : $(ARPATHNAME) # hosted implementation, archive (.a), profiling
hosted_ar_rel : $(ARPATHNAME) # hosted implementation, archive (.a), release
hosted_ar_tsan : $(ARPATHNAME) # hosted implementation, archive (.a), thread sanitizer
hosted_so_cov : $(SOPATHNAME) # hosted implementation, shared (.so), coverage
hosted_so_dbg : $(SOPATHNAME) # hosted implementation, shared (.so), debug
hosted_so_prof : $(SOPATHNAME) # hosted implementation, shared (.so), profiling
hosted_so_rel : $(SOPATHNAME) # hosted implementation, shared (.so), release
hosted_so_tsan : $(SOPATHNAME) # hosted implementation, shared (.so), thread sanitizer
##### dependencies #####
-include $(DEPENDS)
##### notes #####
# TRD : we use -std=gnu89 for C++ style comments
# hosted implementation differs from bare simply in that <assert.h> ends up being included
@@ -0,0 +1,76 @@
lib-y :=
lib-y += ../../src/lfds700_btree_addonly_unbalanced/lfds700_btree_addonly_unbalanced_cleanup.o
lib-y += ../../src/lfds700_btree_addonly_unbalanced/lfds700_btree_addonly_unbalanced_get.o
lib-y += ../../src/lfds700_btree_addonly_unbalanced/lfds700_btree_addonly_unbalanced_init.o
lib-y += ../../src/lfds700_btree_addonly_unbalanced/lfds700_btree_addonly_unbalanced_insert.o
lib-y += ../../src/lfds700_btree_addonly_unbalanced/lfds700_btree_addonly_unbalanced_query.o
lib-y += ../../src/lfds700_freelist/lfds700_freelist_cleanup.o
lib-y += ../../src/lfds700_freelist/lfds700_freelist_init.o
lib-y += ../../src/lfds700_freelist/lfds700_freelist_pop.o
lib-y += ../../src/lfds700_freelist/lfds700_freelist_push.o
lib-y += ../../src/lfds700_freelist/lfds700_freelist_query.o
lib-y += ../../src/lfds700_hash_addonly/lfds700_hash_addonly_cleanup.o
lib-y += ../../src/lfds700_hash_addonly/lfds700_hash_addonly_get.o
lib-y += ../../src/lfds700_hash_addonly/lfds700_hash_addonly_init.o
lib-y += ../../src/lfds700_hash_addonly/lfds700_hash_addonly_insert.o
lib-y += ../../src/lfds700_hash_addonly/lfds700_hash_addonly_iterate.o
lib-y += ../../src/lfds700_hash_addonly/lfds700_hash_addonly_query.o
lib-y += ../../src/lfds700_list_addonly_ordered_singlylinked/lfds700_list_addonly_ordered_singlylinked_cleanup.o
lib-y += ../../src/lfds700_list_addonly_ordered_singlylinked/lfds700_list_addonly_ordered_singlylinked_get.o
lib-y += ../../src/lfds700_list_addonly_ordered_singlylinked/lfds700_list_addonly_ordered_singlylinked_init.o
lib-y += ../../src/lfds700_list_addonly_ordered_singlylinked/lfds700_list_addonly_ordered_singlylinked_insert.o
lib-y += ../../src/lfds700_list_addonly_ordered_singlylinked/lfds700_list_addonly_ordered_singlylinked_query.o
lib-y += ../../src/lfds700_list_addonly_singlylinked_unordered/lfds700_list_addonly_singlylinked_unordered_cleanup.o
lib-y += ../../src/lfds700_list_addonly_singlylinked_unordered/lfds700_list_addonly_singlylinked_unordered_get.o
lib-y += ../../src/lfds700_list_addonly_singlylinked_unordered/lfds700_list_addonly_singlylinked_unordered_init.o
lib-y += ../../src/lfds700_list_addonly_singlylinked_unordered/lfds700_list_addonly_singlylinked_unordered_insert.o
lib-y += ../../src/lfds700_list_addonly_singlylinked_unordered/lfds700_list_addonly_singlylinked_unordered_query.o
lib-y += ../../src/lfds700_misc/lfds700_misc_cleanup.o
lib-y += ../../src/lfds700_misc/lfds700_misc_globals.o
lib-y += ../../src/lfds700_misc/lfds700_misc_init.o
lib-y += ../../src/lfds700_misc/lfds700_misc_prng.o
lib-y += ../../src/lfds700_misc/lfds700_misc_query.o
lib-y += ../../src/lfds700_queue/lfds700_queue_cleanup.o
lib-y += ../../src/lfds700_queue/lfds700_queue_dequeue.o
lib-y += ../../src/lfds700_queue/lfds700_queue_enqueue.o
lib-y += ../../src/lfds700_queue/lfds700_queue_init.o
lib-y += ../../src/lfds700_queue/lfds700_queue_query.o
lib-y += ../../src/lfds700_queue_bounded_singleconsumer_singleproducer/lfds700_queue_bounded_singleconsumer_singleproducer_cleanup.o
lib-y += ../../src/lfds700_queue_bounded_singleconsumer_singleproducer/lfds700_queue_bounded_singleconsumer_singleproducer_dequeue.o
lib-y += ../../src/lfds700_queue_bounded_singleconsumer_singleproducer/lfds700_queue_bounded_singleconsumer_singleproducer_enqueue.o
lib-y += ../../src/lfds700_queue_bounded_singleconsumer_singleproducer/lfds700_queue_bounded_singleconsumer_singleproducer_init.o
lib-y += ../../src/lfds700_queue_bounded_singleconsumer_singleproducer/lfds700_queue_bounded_singleconsumer_singleproducer_query.o
lib-y += ../../src/lfds700_ringbuffer/lfds700_ringbuffer_cleanup.o
lib-y += ../../src/lfds700_ringbuffer/lfds700_ringbuffer_init.o
lib-y += ../../src/lfds700_ringbuffer/lfds700_ringbuffer_query.o
lib-y += ../../src/lfds700_ringbuffer/lfds700_ringbuffer_read.o
lib-y += ../../src/lfds700_ringbuffer/lfds700_ringbuffer_write.o
lib-y += ../../src/lfds700_stack/lfds700_stack_cleanup.o
lib-y += ../../src/lfds700_stack/lfds700_stack_init.o
lib-y += ../../src/lfds700_stack/lfds700_stack_pop.o
lib-y += ../../src/lfds700_stack/lfds700_stack_push.o
lib-y += ../../src/lfds700_stack/lfds700_stack_query.o
libs-y := ../../bin/
ccflags-y := -I$(src)/../../inc
ccflags-y += -I$(src)/../../inc/liblfds700
ccflags-y += -D_KERNEL_MODE
ccflags-y += -fno-strict-aliasing
ccflags-y += -std=gnu89
ccflags-y += -Wall
ccflags-y += -Werror
ccflags-y += -Wno-unknown-pragmas
ccflags-y += -Wno-unused-but-set-variable
ccflags-y += -Wno-unused-variable
@@ -0,0 +1,14 @@
default:
$(MAKE) -C /lib/modules/`uname -r`/build M=$(PWD)
clean:
$(MAKE) -C /lib/modules/`uname -r`/build M=$(PWD) clean
find ../../src/ -name "*.o" -type f -delete
help:
$(MAKE) -C /lib/modules/`uname -r`/build M=$(PWD) help
modules:
$(MAKE) -C /lib/modules/`uname -r`/build M=$(PWD) modules
@@ -0,0 +1,69 @@
EXPORTS
lfds700_btree_au_init_valid_on_current_logical_core = lfds700_btree_au_init_valid_on_current_logical_core
lfds700_btree_au_cleanup = lfds700_btree_au_cleanup
lfds700_btree_au_insert = lfds700_btree_au_insert
lfds700_btree_au_get_by_absolute_position_and_then_by_relative_position = lfds700_btree_au_get_by_absolute_position_and_then_by_relative_position
lfds700_btree_au_get_by_absolute_position = lfds700_btree_au_get_by_absolute_position
lfds700_btree_au_get_by_relative_position = lfds700_btree_au_get_by_relative_position
lfds700_btree_au_get_by_key = lfds700_btree_au_get_by_key
lfds700_btree_au_query = lfds700_btree_au_query
lfds700_freelist_init_valid_on_current_logical_core = lfds700_freelist_init_valid_on_current_logical_core
lfds700_freelist_cleanup = lfds700_freelist_cleanup
lfds700_freelist_push = lfds700_freelist_push
lfds700_freelist_pop = lfds700_freelist_pop
lfds700_freelist_query = lfds700_freelist_query
lfds700_hash_a_init_valid_on_current_logical_core = lfds700_hash_a_init_valid_on_current_logical_core
lfds700_hash_a_cleanup = lfds700_hash_a_cleanup
lfds700_hash_a_insert = lfds700_hash_a_insert
lfds700_hash_a_get_by_key = lfds700_hash_a_get_by_key
lfds700_hash_a_iterate_init = lfds700_hash_a_iterate_init
lfds700_hash_a_iterate = lfds700_hash_a_iterate
lfds700_hash_a_query = lfds700_hash_a_query
lfds700_list_aos_init_valid_on_current_logical_core = lfds700_list_aos_init_valid_on_current_logical_core
lfds700_list_aos_cleanup = lfds700_list_aos_cleanup
lfds700_list_aos_insert = lfds700_list_aos_insert
lfds700_list_aos_get_by_key = lfds700_list_aos_get_by_key
lfds700_list_aos_query = lfds700_list_aos_query
lfds700_list_asu_init_valid_on_current_logical_core = lfds700_list_asu_init_valid_on_current_logical_core
lfds700_list_asu_cleanup = lfds700_list_asu_cleanup
lfds700_list_asu_insert_at_position = lfds700_list_asu_insert_at_position
lfds700_list_asu_insert_at_start = lfds700_list_asu_insert_at_start
lfds700_list_asu_insert_at_end = lfds700_list_asu_insert_at_end
lfds700_list_asu_insert_after_element = lfds700_list_asu_insert_after_element
lfds700_list_asu_get_by_key = lfds700_list_asu_get_by_key
lfds700_list_asu_query = lfds700_list_asu_query
lfds700_misc_library_init_valid_on_current_logical_core = lfds700_misc_library_init_valid_on_current_logical_core
lfds700_misc_library_cleanup = lfds700_misc_library_cleanup
lfds700_misc_prng_init = lfds700_misc_prng_init
lfds700_misc_query = lfds700_misc_query
lfds700_queue_init_valid_on_current_logical_core = lfds700_queue_init_valid_on_current_logical_core
lfds700_queue_cleanup = lfds700_queue_cleanup
lfds700_queue_enqueue = lfds700_queue_enqueue
lfds700_queue_dequeue = lfds700_queue_dequeue
lfds700_queue_query = lfds700_queue_query
lfds700_queue_bss_init_valid_on_current_logical_core = lfds700_queue_bss_init_valid_on_current_logical_core
lfds700_queue_bss_cleanup = lfds700_queue_bss_cleanup
lfds700_queue_bss_enqueue = lfds700_queue_bss_enqueue
lfds700_queue_bss_dequeue = lfds700_queue_bss_dequeue
lfds700_queue_bss_query = lfds700_queue_bss_query
lfds700_ringbuffer_init_valid_on_current_logical_core = lfds700_ringbuffer_init_valid_on_current_logical_core
lfds700_ringbuffer_cleanup = lfds700_ringbuffer_cleanup
lfds700_ringbuffer_read = lfds700_ringbuffer_read
lfds700_ringbuffer_write = lfds700_ringbuffer_write
lfds700_ringbuffer_query = lfds700_ringbuffer_query
lfds700_stack_init_valid_on_current_logical_core = lfds700_stack_init_valid_on_current_logical_core
lfds700_stack_cleanup = lfds700_stack_cleanup
lfds700_stack_push = lfds700_stack_push
lfds700_stack_pop = lfds700_stack_pop
lfds700_stack_query = lfds700_stack_query
@@ -0,0 +1,114 @@
##### paths #####
BINDIR := ..\..\bin
INCDIR := ..\..\inc
OBJDIR := ..\..\obj
SRCDIR := ..\..\src
##### misc #####
QUIETLY := 1>nul 2>nul
NULL :=
SPACE := $(NULL) # TRD : with a trailing space
##### sources, objects and libraries #####
BINNAME := liblfds700
LIB_BINARY := $(BINDIR)\$(BINNAME).lib
DLL_BINARY := $(BINDIR)\$(BINNAME).dll
SRCDIRS := lfds700_btree_addonly_unbalanced lfds700_freelist lfds700_hash_addonly lfds700_list_addonly_ordered_singlylinked lfds700_list_addonly_singlylinked_unordered lfds700_misc lfds700_queue lfds700_queue_bounded_singleconsumer_singleproducer lfds700_ringbuffer lfds700_stack
SOURCES := lfds700_hash_addonly_cleanup.c lfds700_hash_addonly_get.c lfds700_hash_addonly_init.c lfds700_hash_addonly_insert.c lfds700_hash_addonly_iterate.c lfds700_hash_addonly_query.c \
lfds700_list_addonly_ordered_singlylinked_cleanup.c lfds700_list_addonly_ordered_singlylinked_get.c lfds700_list_addonly_ordered_singlylinked_init.c lfds700_list_addonly_ordered_singlylinked_insert.c lfds700_list_addonly_ordered_singlylinked_query.c \
lfds700_list_addonly_singlylinked_unordered_cleanup.c lfds700_list_addonly_singlylinked_unordered_get.c lfds700_list_addonly_singlylinked_unordered_init.c lfds700_list_addonly_singlylinked_unordered_insert.c lfds700_list_addonly_singlylinked_unordered_query.c \
lfds700_btree_addonly_unbalanced_cleanup.c lfds700_btree_addonly_unbalanced_get.c lfds700_btree_addonly_unbalanced_init.c lfds700_btree_addonly_unbalanced_insert.c lfds700_btree_addonly_unbalanced_query.c \
lfds700_freelist_cleanup.c lfds700_freelist_init.c lfds700_freelist_pop.c lfds700_freelist_push.c lfds700_freelist_query.c \
lfds700_misc_cleanup.c lfds700_misc_globals.c lfds700_misc_init.c lfds700_misc_prng.c lfds700_misc_query.c \
lfds700_queue_cleanup.c lfds700_queue_dequeue.c lfds700_queue_enqueue.c lfds700_queue_init.c lfds700_queue_query.c \
lfds700_queue_bounded_singleconsumer_singleproducer_cleanup.c lfds700_queue_bounded_singleconsumer_singleproducer_dequeue.c lfds700_queue_bounded_singleconsumer_singleproducer_enqueue.c lfds700_queue_bounded_singleconsumer_singleproducer_init.c lfds700_queue_bounded_singleconsumer_singleproducer_query.c \
lfds700_ringbuffer_cleanup.c lfds700_ringbuffer_init.c lfds700_ringbuffer_query.c lfds700_ringbuffer_read.c lfds700_ringbuffer_write.c \
lfds700_stack_cleanup.c lfds700_stack_init.c lfds700_stack_pop.c lfds700_stack_push.c lfds700_stack_query.c
OBJECTS := $(patsubst %.c,$(OBJDIR)/%.obj,$(notdir $(SOURCES)))
SYSLIBS := kernel32.lib
##### default paths fix up #####
INCDIRS := $(patsubst %,%;,$(INCDIR))
INCLUDE += $(subst $(SPACE),,$(INCDIRS))
##### tools #####
MAKE := make
MFLAGS :=
CC := cl
CBASE := /c "-I$(SRCDIR)" "/Fd$(BINDIR)\$(BINNAME).pdb" /D_CRT_SECURE_NO_WARNINGS /DWIN32_LEAN_AND_MEAN /DUNICODE /D_UNICODE /DUNICODE /nologo /W4 /wd 4068 /WX
CFREL := /DNDEBUG /Ox
CFDBG := /D_DEBUG /Gm /Od /Zi
AR := lib
AFLAGS := /nologo /subsystem:console /verbose /wx
LD := link
LFBASE := /def:$(BINNAME).def /dll /nodefaultlib /nologo /nxcompat /subsystem:console /wx
LFREL := /incremental:no
LFDBG := /debug "/pdb:$(BINDIR)\$(BINNAME).pdb"
##### variants #####
CFLAGS := $(CBASE) $(CFDBG) /MTd
ASFLAGS := $(ASBASE) $(ASDBG)
LFLAGS := $(LFBASE) $(LFDBG)
CLIB := libcmtd.lib
ifeq ($(MAKECMDGOALS),librel)
CFLAGS := $(CBASE) $(CFREL) /MT
ASFLAGS := $(ASBASE) $(ASREL)
LFLAGS := $(LFBASE) $(LFREL)
CLIB := libcmt.lib
endif
ifeq ($(MAKECMDGOALS),libdbg)
CFLAGS := $(CBASE) $(CFDBG) /MTd
ASFLAGS := $(ASBASE) $(ASDBG)
LFLAGS := $(LFBASE) $(LFDBG)
CLIB := libcmtd.lib
endif
ifeq ($(MAKECMDGOALS),dllrel)
CFLAGS := $(CBASE) $(CFREL) /MD
ASFLAGS := $(ASBASE) $(ASREL)
LFLAGS := $(LFBASE) $(LFREL)
CLIB := msvcrt.lib
endif
ifeq ($(MAKECMDGOALS),dlldbg)
CFLAGS := $(CBASE) $(CFDBG) /MDd
ASFLAGS := $(ASBASE) $(ASDBG)
LFLAGS := $(LFBASE) $(LFDBG)
CLIB := msvcrtd.lib
endif
##### search paths #####
vpath %.c $(patsubst %,$(SRCDIR)/%;,$(SRCDIRS))
##### implicit rules #####
$(OBJDIR)/%.obj : %.c
$(CC) $(CFLAGS) "/Fo$@" $<
##### explicit rules #####
$(LIB_BINARY) : $(OBJECTS)
$(AR) $(AFLAGS) $(OBJECTS) /out:$(LIB_BINARY)
$(DLL_BINARY) : $(OBJECTS)
$(LD) $(LFLAGS) $(CLIB) $(SYSLIBS) $(OBJECTS) /out:$(DLL_BINARY)
##### phony #####
.PHONY : clean librel libdbg dllrel dlldbg
clean :
@erase /Q $(BINDIR)\$(BINNAME).* $(OBJDIR)\*.obj $(QUIETLY)
dlldbg : $(DLL_BINARY)
dllrel : $(DLL_BINARY)
libdbg : $(LIB_BINARY)
librel : $(LIB_BINARY)
##### notes #####
# /wd 4068 : turn off "unknown pragma" warning
@@ -0,0 +1,69 @@
EXPORTS
lfds700_btree_au_init_valid_on_current_logical_core = lfds700_btree_au_init_valid_on_current_logical_core
lfds700_btree_au_cleanup = lfds700_btree_au_cleanup
lfds700_btree_au_insert = lfds700_btree_au_insert
lfds700_btree_au_get_by_absolute_position_and_then_by_relative_position = lfds700_btree_au_get_by_absolute_position_and_then_by_relative_position
lfds700_btree_au_get_by_absolute_position = lfds700_btree_au_get_by_absolute_position
lfds700_btree_au_get_by_relative_position = lfds700_btree_au_get_by_relative_position
lfds700_btree_au_get_by_key = lfds700_btree_au_get_by_key
lfds700_btree_au_query = lfds700_btree_au_query
lfds700_freelist_init_valid_on_current_logical_core = lfds700_freelist_init_valid_on_current_logical_core
lfds700_freelist_cleanup = lfds700_freelist_cleanup
lfds700_freelist_push = lfds700_freelist_push
lfds700_freelist_pop = lfds700_freelist_pop
lfds700_freelist_query = lfds700_freelist_query
lfds700_hash_a_init_valid_on_current_logical_core = lfds700_hash_a_init_valid_on_current_logical_core
lfds700_hash_a_cleanup = lfds700_hash_a_cleanup
lfds700_hash_a_insert = lfds700_hash_a_insert
lfds700_hash_a_get_by_key = lfds700_hash_a_get_by_key
lfds700_hash_a_iterate_init = lfds700_hash_a_iterate_init
lfds700_hash_a_iterate = lfds700_hash_a_iterate
lfds700_hash_a_query = lfds700_hash_a_query
lfds700_list_aos_init_valid_on_current_logical_core = lfds700_list_aos_init_valid_on_current_logical_core
lfds700_list_aos_cleanup = lfds700_list_aos_cleanup
lfds700_list_aos_insert = lfds700_list_aos_insert
lfds700_list_aos_get_by_key = lfds700_list_aos_get_by_key
lfds700_list_aos_query = lfds700_list_aos_query
lfds700_list_asu_init_valid_on_current_logical_core = lfds700_list_asu_init_valid_on_current_logical_core
lfds700_list_asu_cleanup = lfds700_list_asu_cleanup
lfds700_list_asu_insert_at_position = lfds700_list_asu_insert_at_position
lfds700_list_asu_insert_at_start = lfds700_list_asu_insert_at_start
lfds700_list_asu_insert_at_end = lfds700_list_asu_insert_at_end
lfds700_list_asu_insert_after_element = lfds700_list_asu_insert_after_element
lfds700_list_asu_get_by_key = lfds700_list_asu_get_by_key
lfds700_list_asu_query = lfds700_list_asu_query
lfds700_misc_library_init_valid_on_current_logical_core = lfds700_misc_library_init_valid_on_current_logical_core
lfds700_misc_library_cleanup = lfds700_misc_library_cleanup
lfds700_misc_prng_init = lfds700_misc_prng_init
lfds700_misc_query = lfds700_misc_query
lfds700_queue_init_valid_on_current_logical_core = lfds700_queue_init_valid_on_current_logical_core
lfds700_queue_cleanup = lfds700_queue_cleanup
lfds700_queue_enqueue = lfds700_queue_enqueue
lfds700_queue_dequeue = lfds700_queue_dequeue
lfds700_queue_query = lfds700_queue_query
lfds700_queue_bss_init_valid_on_current_logical_core = lfds700_queue_bss_init_valid_on_current_logical_core
lfds700_queue_bss_cleanup = lfds700_queue_bss_cleanup
lfds700_queue_bss_enqueue = lfds700_queue_bss_enqueue
lfds700_queue_bss_dequeue = lfds700_queue_bss_dequeue
lfds700_queue_bss_query = lfds700_queue_bss_query
lfds700_ringbuffer_init_valid_on_current_logical_core = lfds700_ringbuffer_init_valid_on_current_logical_core
lfds700_ringbuffer_cleanup = lfds700_ringbuffer_cleanup
lfds700_ringbuffer_read = lfds700_ringbuffer_read
lfds700_ringbuffer_write = lfds700_ringbuffer_write
lfds700_ringbuffer_query = lfds700_ringbuffer_query
lfds700_stack_init_valid_on_current_logical_core = lfds700_stack_init_valid_on_current_logical_core
lfds700_stack_cleanup = lfds700_stack_cleanup
lfds700_stack_push = lfds700_stack_push
lfds700_stack_pop = lfds700_stack_pop
lfds700_stack_query = lfds700_stack_query
@@ -0,0 +1,46 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2012
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "liblfds700", "liblfds700.vcxproj", "{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug DLL|Win32 = Debug DLL|Win32
Debug DLL|x64 = Debug DLL|x64
Debug LIB|Win32 = Debug LIB|Win32
Debug LIB|x64 = Debug LIB|x64
Release DLL|Win32 = Release DLL|Win32
Release DLL|x64 = Release DLL|x64
Release LIB|Win32 = Release LIB|Win32
Release LIB|x64 = Release LIB|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug DLL|Win32.ActiveCfg = Debug DLL|Win32
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug DLL|Win32.Build.0 = Debug DLL|Win32
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug DLL|Win32.Deploy.0 = Debug DLL|Win32
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug DLL|x64.ActiveCfg = Debug DLL|x64
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug DLL|x64.Build.0 = Debug DLL|x64
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug DLL|x64.Deploy.0 = Debug DLL|x64
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug LIB|Win32.ActiveCfg = Debug LIB|Win32
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug LIB|Win32.Build.0 = Debug LIB|Win32
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug LIB|Win32.Deploy.0 = Debug LIB|Win32
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug LIB|x64.ActiveCfg = Debug LIB|x64
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug LIB|x64.Build.0 = Debug LIB|x64
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Debug LIB|x64.Deploy.0 = Debug LIB|x64
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release DLL|Win32.ActiveCfg = Release DLL|Win32
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release DLL|Win32.Build.0 = Release DLL|Win32
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release DLL|Win32.Deploy.0 = Release DLL|Win32
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release DLL|x64.ActiveCfg = Release DLL|x64
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release DLL|x64.Build.0 = Release DLL|x64
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release DLL|x64.Deploy.0 = Release DLL|x64
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release LIB|Win32.ActiveCfg = Release LIB|Win32
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release LIB|Win32.Build.0 = Release LIB|Win32
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release LIB|Win32.Deploy.0 = Release LIB|Win32
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release LIB|x64.ActiveCfg = Release LIB|x64
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release LIB|x64.Build.0 = Release LIB|x64
{1E5D7D09-94F2-455D-AE5E-6C7F4C96BCE0}.Release LIB|x64.Deploy.0 = Release LIB|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

Some files were not shown because too many files have changed in this diff Show More