Merge remote-tracking branch 'origin/develop' into Enhancement-142-OAI_UE_autotest_framework
This commit is contained in:
+140
-10
@@ -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)
|
||||
|
||||
@@ -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
@@ -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 )
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
Executable
+19
@@ -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 "$@"
|
||||
Executable
+21
@@ -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
|
||||
@@ -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
@@ -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 = ⪚
|
||||
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;
|
||||
|
||||
@@ -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 */
|
||||
/****************************************************************************/
|
||||
|
||||
@@ -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,8 +2,8 @@ CC=gcc
|
||||
CFLAGS=-Wall -g -pthread -I/usr/include/X11/Xft -I/usr/include/freetype2
|
||||
|
||||
OBJS=init.o loop.o toplevel_window.o x.o container.o widget.o \
|
||||
gui.o label.o event.o xy_plot.o textlist.o notify.o positioner.o \
|
||||
timeline.o space.o image.o
|
||||
gui.o label.o textarea.o event.o xy_plot.o textlist.o notify.o \
|
||||
positioner.o timeline.o space.o image.o
|
||||
|
||||
gui.a: $(OBJS)
|
||||
ar cr gui.a $(OBJS)
|
||||
|
||||
@@ -14,6 +14,10 @@ typedef void widget;
|
||||
|
||||
#define DEFAULT_FONT 0
|
||||
|
||||
/* tic type for XY plot */
|
||||
#define XY_PLOT_DEFAULT_TICK 0
|
||||
#define XY_PLOT_SCROLL_TICK 1
|
||||
|
||||
/* key modifiers */
|
||||
#define KEY_SHIFT (1<<0)
|
||||
#define KEY_CONTROL (1<<1)
|
||||
@@ -30,6 +34,7 @@ widget *new_toplevel_window(gui *gui, int width, int height, char *title);
|
||||
widget *new_container(gui *gui, int vertical);
|
||||
widget *new_positioner(gui *gui);
|
||||
widget *new_label(gui *gui, const char *text);
|
||||
widget *new_textarea(gui *gui, int width, int height, int maxsize);
|
||||
widget *new_xy_plot(gui *gui, int width, int height, char *label,
|
||||
int vruler_width);
|
||||
widget *new_textlist(gui *gui, int width, int nlines, int background_color);
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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:
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <ctype.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <math.h>
|
||||
|
||||
void new_thread(void *(*f)(void *), void *data)
|
||||
{
|
||||
@@ -36,6 +37,16 @@ void sleepms(int ms)
|
||||
if (nanosleep(&t, NULL)) abort();
|
||||
}
|
||||
|
||||
void bps(char *out, float v, char *suffix)
|
||||
{
|
||||
static char *bps_unit[4] = { "", "k", "M", "G" };
|
||||
int flog;
|
||||
if (v < 1000) flog = 0; else flog = floor(floor(log10(v)) / 3);
|
||||
if (flog > 3) flog = 3;
|
||||
v /= pow(10, flog*3);
|
||||
sprintf(out, "%g%s%s", round(v*100)/100, bps_unit[flog], suffix);
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/* list */
|
||||
/****************************************************************************/
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
void new_thread(void *(*f)(void *), void *data);
|
||||
void sleepms(int ms);
|
||||
void bps(char *out, float v, char *suffix);
|
||||
|
||||
/****************************************************************************/
|
||||
/* list */
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
@@ -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_ */
|
||||
|
||||
@@ -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,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
|
||||
|
||||
|
||||
@@ -69,6 +69,11 @@ enum openair_SYNCH_STATUS {
|
||||
openair_SCHED_EXIT
|
||||
};
|
||||
|
||||
enum openair_HARQ_TYPE {
|
||||
openair_harq_DL = 0,
|
||||
openair_harq_UL,
|
||||
openair_harq_RA
|
||||
};
|
||||
|
||||
#define DAQ_AGC_ON 1
|
||||
#define DAQ_AGC_OFF 0
|
||||
|
||||
@@ -21,11 +21,11 @@
|
||||
|
||||
/*! \file phy_procedures_lte_eNB.c
|
||||
* \brief Implementation of eNB procedures from 36.213 LTE specifications
|
||||
* \author R. Knopp, F. Kaltenberger, N. Nikaein
|
||||
* \author R. Knopp, F. Kaltenberger, N. Nikaein, X. Foukas
|
||||
* \date 2011
|
||||
* \version 0.1
|
||||
* \company Eurecom
|
||||
* \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr,navid.nikaein@eurecom.fr
|
||||
* \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr,navid.nikaein@eurecom.fr, x.foukas@sms.ed.ac.uk
|
||||
* \note
|
||||
* \warning
|
||||
*/
|
||||
@@ -61,6 +61,14 @@
|
||||
# include "intertask_interface.h"
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(FLEXRAN_AGENT_SB_IF)
|
||||
//Agent-related headers
|
||||
#include "ENB_APP/flexran_agent_extern.h"
|
||||
#include "ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.h"
|
||||
#include "LAYER2/MAC/flexran_agent_mac_proto.h"
|
||||
#endif
|
||||
|
||||
//#define DIAG_PHY
|
||||
|
||||
#define NS_PER_SLOT 500000
|
||||
@@ -221,7 +229,7 @@ int8_t find_next_ue_index(PHY_VARS_eNB *eNB)
|
||||
return(-1);
|
||||
}
|
||||
|
||||
int get_ue_active_harq_pid(const uint8_t Mod_id,const uint8_t CC_id,const uint16_t rnti, const int frame, const uint8_t subframe,uint8_t *harq_pid,uint8_t *round,const uint8_t ul_flag)
|
||||
int get_ue_active_harq_pid(const uint8_t Mod_id,const uint8_t CC_id,const uint16_t rnti, const int frame, const uint8_t subframe,uint8_t *harq_pid,uint8_t *round,const uint8_t harq_flag)
|
||||
{
|
||||
LTE_eNB_DLSCH_t *DLSCH_ptr;
|
||||
LTE_eNB_ULSCH_t *ULSCH_ptr;
|
||||
@@ -235,9 +243,20 @@ int get_ue_active_harq_pid(const uint8_t Mod_id,const uint8_t CC_id,const uint16
|
||||
return(-1);
|
||||
}
|
||||
|
||||
if (ul_flag == 0) {// this is a DL request
|
||||
if ((harq_flag == openair_harq_DL) || (harq_flag == openair_harq_RA)) {// this is a DL request
|
||||
|
||||
DLSCH_ptr = PHY_vars_eNB_g[Mod_id][CC_id]->dlsch[(uint32_t)UE_id][0];
|
||||
|
||||
if (harq_flag == openair_harq_RA) {
|
||||
if (DLSCH_ptr->harq_processes[0] != NULL) {
|
||||
*harq_pid = 0;
|
||||
*round = DLSCH_ptr->harq_processes[0]->round;
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* let's go synchronous for the moment - maybe we can change at some point */
|
||||
i = (frame * 10 + subframe) % 8;
|
||||
|
||||
@@ -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++)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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));
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
@@ -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_*/
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
*/
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
@@ -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];
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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 */
|
||||
@@ -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
|
||||
@@ -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 */
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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 */
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
|
||||
+69
@@ -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
|
||||
|
||||
+114
@@ -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
|
||||
|
||||
|
||||
+69
@@ -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
|
||||
|
||||
+46
@@ -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
Reference in New Issue
Block a user