Merge branch 'develop' into feature-59-tm4
Conflicts: openair1/PHY/TOOLS/lte_phy_scope.c
This commit is contained in:
+3
-2
@@ -8,6 +8,7 @@ job1:
|
||||
- echo $EXTERNAL_SHARE_DIR
|
||||
- echo $SHELL
|
||||
- git rev-parse --abbrev-ref HEAD
|
||||
- git_repo=`git config --get remote.origin.url`
|
||||
- git_head=`git rev-parse HEAD`
|
||||
- echo $git_head
|
||||
- tmp=`git show-ref --head | grep $git_head`
|
||||
@@ -23,8 +24,8 @@ job1:
|
||||
- echo $NRUNS_LTE_SOFTMODEM
|
||||
- echo $TIMEOUT_CMD
|
||||
- mkdir -p $OPENAIR_DIR/cmake_targets/autotests/log
|
||||
- python $OPENAIR_DIR/cmake_targets/autotests/run_exec_lte-softmodem_tests.py -c -5GRepoHeadVersion $git_head -n $NFS_SHARE_DIR -u $OAI_USER -p $OAI_PASS $OAI_EXTRA_ARGS -g "$OAI_TEST_CASE_GROUP">& $OPENAIR_DIR/cmake_targets/autotests/python_autotest_cleanup.log
|
||||
- python $OPENAIR_DIR/cmake_targets/autotests/run_exec_lte-softmodem_tests.py -r -5GRepoHeadVersion $git_head -n $NFS_SHARE_DIR -u $OAI_USER -p $OAI_PASS `echo $OAI_EXTRA_ARGS` -g "$OAI_TEST_CASE_GROUP" --nrun_lte_softmodem $NRUNS_LTE_SOFTMODEM --timeout_cmd $TIMEOUT_CMD >& $OPENAIR_DIR/cmake_targets/autotests/python_autotest.log
|
||||
- python $OPENAIR_DIR/cmake_targets/autotests/run_exec_lte-softmodem_tests.py -c -5GRepo $git_repo -5GRepoHeadVersion $git_head -n $NFS_SHARE_DIR -u $OAI_USER -p $OAI_PASS $OAI_EXTRA_ARGS -g "$OAI_TEST_CASE_GROUP">& $OPENAIR_DIR/cmake_targets/autotests/python_autotest_cleanup.log
|
||||
- python $OPENAIR_DIR/cmake_targets/autotests/run_exec_lte-softmodem_tests.py -r -5GRepo $git_repo -5GRepoHeadVersion $git_head -n $NFS_SHARE_DIR -u $OAI_USER -p $OAI_PASS `echo $OAI_EXTRA_ARGS` -g "$OAI_TEST_CASE_GROUP" --nrun_lte_softmodem $NRUNS_LTE_SOFTMODEM --timeout_cmd $TIMEOUT_CMD >& $OPENAIR_DIR/cmake_targets/autotests/python_autotest.log
|
||||
- mv $OPENAIR_DIR/cmake_targets/autotests/python_autotest.log $OPENAIR_DIR/cmake_targets/autotests/log/python_autotest.log
|
||||
- mv $OPENAIR_DIR/cmake_targets/autotests/python_autotest_cleanup.log $OPENAIR_DIR/cmake_targets/autotests/log/python_autotest_cleanup.log
|
||||
- sshpass -p "$OAI_PASS" rsync -az -e "ssh -o StrictHostKeyChecking=no " --rsync-path="mkdir -p $NFS_TEST_RESULTS_DIR && rsync" $OPENAIR_DIR/cmake_targets/autotests/log $OAI_USER@localhost:$NFS_TEST_RESULTS_DIR
|
||||
|
||||
@@ -177,42 +177,65 @@ add_definitions(-DCMAKER)
|
||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS} -g -DMALLOC_CHECK_=3")
|
||||
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS} -g -DMALLOC_CHECK_=3 -O2")
|
||||
|
||||
Message("RF_BOARD is ${RF_BOARD}")
|
||||
# Below has been put in comment because does not work with
|
||||
# SVN authentication.
|
||||
#
|
||||
#find_package(Subversion)
|
||||
#if(SUBVERSION_FOUND)
|
||||
# Subversion_WC_INFO(${OPENAIR_DIR} openair)
|
||||
# set (FIRMWARE_VERSION "${openair_WC_REVISION} - ${openair_WC_LAST_CHANGED_DATE}")
|
||||
# Subversion_WC_LOG(${OPENAIR_DIR} Project)
|
||||
#else()
|
||||
# set (FIRMWARE_VERSION "No svn information")
|
||||
#endif()
|
||||
#add_definitions("-DFIRMWARE_VERSION=\"${FIRMWARE_VERSION}\"")
|
||||
|
||||
set(GIT_BRANCH "UNKNOWN")
|
||||
set(GIT_COMMIT_HASH "UNKNOWN")
|
||||
set(GIT_COMMIT_DATE "UNKNOWN")
|
||||
|
||||
|
||||
find_package(Git)
|
||||
if(GIT_FOUND)
|
||||
message("git found: ${GIT_EXECUTABLE}")
|
||||
# Get the current working branch
|
||||
execute_process(
|
||||
COMMAND git rev-parse --abbrev-ref HEAD
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
OUTPUT_VARIABLE GIT_BRANCH
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
|
||||
# Get the latest abbreviated commit hash of the working branch
|
||||
execute_process(
|
||||
COMMAND git log -1 --format=%h
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
OUTPUT_VARIABLE GIT_COMMIT_HASH
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
|
||||
# Get the latest commit date of the working branch
|
||||
execute_process(
|
||||
COMMAND git log -1 --format=%cd
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
OUTPUT_VARIABLE GIT_COMMIT_DATE
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
endif()
|
||||
|
||||
|
||||
# Below is a hard-coded info
|
||||
set (FIRMWARE_VERSION "No svn information")
|
||||
add_definitions("-DFIRMWARE_VERSION=\"${FIRMWARE_VERSION}\"")
|
||||
add_definitions("-DPACKAGE_VERSION=\"${FIRMWARE_VERSION}\"")
|
||||
add_definitions("-DPACKAGE_BUGREPORT=\"OpenAirInterface web site\"")
|
||||
add_definitions("-DPACKAGE_VERSION=\"Branch: ${GIT_BRANCH} Abrev. Hash: ${GIT_COMMIT_HASH} Date: ${GIT_COMMIT_DATE}\"")
|
||||
add_definitions("-DPACKAGE_BUGREPORT=\"openair4g-devel@lists.eurecom.fr\"")
|
||||
|
||||
|
||||
|
||||
# Debug related options
|
||||
#########################################
|
||||
add_boolean_option(MSG_PRINT False "print debug messages")
|
||||
add_boolean_option(DISABLE_XER_PRINT False "print XER Format")
|
||||
add_boolean_option(XER_PRINT False "print XER Format")
|
||||
add_boolean_option(RRC_MSG_PRINT False "print RRC messages")
|
||||
add_boolean_option(PDCP_MSG_PRINT False "print PDCP messages to /tmp/pdcp.log")
|
||||
add_boolean_option(DEBUG_PDCP_PAYLOAD False "print PDCP PDU to stdout") # if true, make sure that global and PDCP log levels are trace
|
||||
add_boolean_option(ASN_DEBUG False "ASN1 coder/decoder Debug")
|
||||
add_boolean_option(EMIT_ASN_DEBUG False "ASN1 coder/decoder Debug")
|
||||
add_boolean_option(MSG_PRINT False "print debug messages")
|
||||
add_boolean_option(DISABLE_XER_PRINT False "print XER Format")
|
||||
add_boolean_option(XER_PRINT False "print XER Format")
|
||||
add_boolean_option(RRC_MSG_PRINT False "print RRC messages")
|
||||
add_boolean_option(PDCP_MSG_PRINT False "print PDCP messages to /tmp/pdcp.log")
|
||||
add_boolean_option(DEBUG_PDCP_PAYLOAD False "print PDCP PDU to stdout") # if true, make sure that global and PDCP log levels are trace
|
||||
add_boolean_option(DEBUG_MAC_INTERFACE False "print MAC-RLC PDU exchange to stdout") # if true, make sure that global and PDCP log levels are trace
|
||||
add_boolean_option(TRACE_RLC_PAYLOAD False "print RLC PDU to stdout") # if true, make sure that global and PDCP log levels are trace
|
||||
add_boolean_option(TEST_OMG False "???")
|
||||
add_boolean_option(DEBUG_OMG False "???")
|
||||
add_boolean_option(XFORMS False "This adds the possibility to see the signal oscilloscope")
|
||||
add_boolean_option(PRINT_STATS False "This adds the possibility to see the status")
|
||||
add_boolean_option(TRACE_RLC_PAYLOAD False "print RLC PDU to stdout") # if true, make sure that global and PDCP log levels are trace
|
||||
add_boolean_option(TEST_OMG False "???")
|
||||
add_boolean_option(DEBUG_OMG False "???")
|
||||
add_boolean_option(XFORMS False "This adds the possibility to see the signal oscilloscope")
|
||||
add_boolean_option(PRINT_STATS False "This adds the possibility to see the status")
|
||||
|
||||
add_boolean_option(DEBUG_CONSOLE False "makes debugging easier, disables stdout/stderr buffering")
|
||||
|
||||
@@ -323,6 +346,7 @@ set(S1AP_OAI_generated
|
||||
${S1AP_C_DIR}/s1ap_decoder.c
|
||||
${S1AP_C_DIR}/s1ap_encoder.c
|
||||
${S1AP_C_DIR}/s1ap_xer_print.c
|
||||
${S1AP_C_DIR}/s1ap_compare.c
|
||||
${S1AP_C_DIR}/s1ap_ies_defs.h
|
||||
)
|
||||
file(GLOB s1ap_h ${S1AP_C_DIR}/*.h)
|
||||
@@ -1088,7 +1112,6 @@ add_library(CN_UTILS
|
||||
${OPENAIR3_DIR}/UTILS/conversions.c
|
||||
${OPENAIR3_DIR}/UTILS/enum_string.c
|
||||
${OPENAIR3_DIR}/UTILS/log.c
|
||||
${OPENAIR3_DIR}/UTILS/mme_config.c
|
||||
${OPENAIR3_DIR}/UTILS/mcc_mnc_itu.c
|
||||
)
|
||||
|
||||
@@ -1429,6 +1452,9 @@ include(FindPkgConfig)
|
||||
pkg_search_module(LIBXML2 libxml-2.0 REQUIRED)
|
||||
include_directories(${LIBXML2_INCLUDE_DIRS})
|
||||
|
||||
pkg_search_module(LIBXSLT libxslt REQUIRED)
|
||||
include_directories(${LIBXSLT_INCLUDE_DIRS})
|
||||
|
||||
pkg_search_module(OPENSSL openssl REQUIRED)
|
||||
include_directories(${OPENSSL_INCLUDE_DIRS})
|
||||
|
||||
@@ -1720,6 +1746,7 @@ endforeach(myExe)
|
||||
|
||||
add_executable(test_epc_generate_scenario
|
||||
${OPENAIR3_DIR}/TEST/EPC_TEST/generate_scenario.c
|
||||
${OPENAIR3_DIR}/TEST/EPC_TEST/generate_scenario.h
|
||||
${OPENAIR2_DIR}/ENB_APP/enb_config.h
|
||||
${OPENAIR2_DIR}/COMMON/commonDef.h
|
||||
${OPENAIR2_DIR}/COMMON/messages_def.h
|
||||
@@ -1728,7 +1755,28 @@ add_executable(test_epc_generate_scenario
|
||||
${OPENAIR_BIN_DIR}/messages_xml.h
|
||||
)
|
||||
target_link_libraries (test_epc_generate_scenario
|
||||
-Wl,--start-group RRC_LIB S1AP_LIB S1AP_ENB X2AP_LIB GTPV1U LIB_NAS_UE SECU_CN UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB PHY LFDS ${MSC_LIB} L2 -Wl,--end-group pthread m rt crypt sctp ${LIBXML2_LIBRARIES} ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} ${CONFIG_LIBRARIES}
|
||||
-Wl,--start-group RRC_LIB S1AP_LIB S1AP_ENB X2AP_LIB GTPV1U LIB_NAS_UE SECU_CN UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB PHY LFDS ${ITTI_LIB} ${MSC_LIB} L2 -Wl,--end-group pthread m rt crypt sctp ${LIBXML2_LIBRARIES} ${LIBXSLT_LIBRARIES} ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} ${CONFIG_LIBRARIES}
|
||||
)
|
||||
|
||||
add_executable(test_epc_play_scenario
|
||||
${OPENAIR3_DIR}/TEST/EPC_TEST/play_scenario.c
|
||||
${OPENAIR3_DIR}/TEST/EPC_TEST/play_scenario_decode.c
|
||||
${OPENAIR3_DIR}/TEST/EPC_TEST/play_scenario_display.c
|
||||
${OPENAIR3_DIR}/TEST/EPC_TEST/play_scenario_fsm.c
|
||||
${OPENAIR3_DIR}/TEST/EPC_TEST/play_scenario_parse.c
|
||||
${OPENAIR3_DIR}/TEST/EPC_TEST/play_scenario_s1ap.c
|
||||
${OPENAIR3_DIR}/TEST/EPC_TEST/play_scenario_s1ap_compare_ie.c
|
||||
${OPENAIR3_DIR}/TEST/EPC_TEST/play_scenario_s1ap_eNB_defs.h
|
||||
${OPENAIR3_DIR}/TEST/EPC_TEST/play_scenario_sctp.c
|
||||
${OPENAIR3_DIR}/TEST/EPC_TEST/play_scenario.h
|
||||
${OPENAIR2_DIR}/COMMON/commonDef.h
|
||||
${OPENAIR2_DIR}/COMMON/messages_def.h
|
||||
${OPENAIR2_DIR}/COMMON/messages_types.h
|
||||
${OPENAIR_BIN_DIR}/messages_xml.h
|
||||
)
|
||||
target_include_directories(test_epc_play_scenario PUBLIC /usr/local/share/asn1c)
|
||||
target_link_libraries (test_epc_play_scenario
|
||||
-Wl,--start-group RRC_LIB S1AP_LIB X2AP_LIB GTPV1U LIB_NAS_UE SECU_CN UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB PHY LFDS ${ITTI_LIB} ${MSC_LIB} -Wl,--end-group pthread m rt crypt sctp ${LIBXML2_LIBRARIES} ${LIBXSLT_LIBRARIES} ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} ${CONFIG_LIBRARIES}
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -189,6 +189,22 @@ Obj.# Case# Test# Description
|
||||
01 75 04 Band 7 FDD 10MHz DL Throughput for 300 sec for 1TX/1RX
|
||||
01 75 05 Band 7 FDD 20MHz DL Throughput for 300 sec for 1TX/1RX
|
||||
|
||||
01 80 00 lte-softmodem + RRH tests with BladeRF RF as eNB and ALU EPC w/ Bandrich COTS UE for TX/1RX
|
||||
01 80 00 Band 7 FDD 5MHz UL Throughput for 300 sec for 1TX/1RX
|
||||
01 80 01 Band 7 FDD 10MHz UL Throughput for 300 sec for 1TX/1RX
|
||||
01 80 02 Band 7 FDD 20MHz UL Throughput for 300 sec for 1TX/1RX
|
||||
01 80 03 Band 7 FDD 5MHz DL Throughput for 300 sec for 1TX/1RX
|
||||
01 80 04 Band 7 FDD 10MHz DL Throughput for 300 sec for 1TX/1RX
|
||||
01 80 05 Band 7 FDD 20MHz DL Throughput for 300 sec for 1TX/1RX
|
||||
|
||||
01 85 00 lte-softmodem + RRH tests with USRP X310 RF as eNB and ALU EPC w/ Bandrich COTS UE for TX/1RX
|
||||
01 85 00 Band 7 FDD 5MHz UL Throughput for 300 sec for 1TX/1RX
|
||||
01 85 01 Band 7 FDD 10MHz UL Throughput for 300 sec for 1TX/1RX
|
||||
01 85 02 Band 7 FDD 20MHz UL Throughput for 300 sec for 1TX/1RX
|
||||
01 85 03 Band 7 FDD 5MHz DL Throughput for 300 sec for 1TX/1RX
|
||||
01 85 04 Band 7 FDD 10MHz DL Throughput for 300 sec for 1TX/1RX
|
||||
01 85 05 Band 7 FDD 20MHz DL Throughput for 300 sec for 1TX/1RX
|
||||
|
||||
|
||||
01 64 lte-softmodem-noS1 tests
|
||||
|
||||
|
||||
@@ -388,6 +388,7 @@ until [ -z "$1" ]
|
||||
-g | --run-group)
|
||||
RUN_GROUP=1
|
||||
test_case_group=$2
|
||||
test_case_group=`sed "s/\+/\*/g" <<< "${test_case_group}"` # Replace + with * for bash string substituion
|
||||
echo_info "Will execute test cases only in group $test_case_group"
|
||||
shift 2;;
|
||||
-p)
|
||||
@@ -423,9 +424,17 @@ rm -fr $tmpfile
|
||||
xml_conf="$OPENAIR_DIR/cmake_targets/autotests/test_case_list.xml"
|
||||
|
||||
test_case_list=`xmlstarlet sel -T -t -m /testCaseList/testCase -s A:N:- "@id" -v "@id" -n $xml_conf`
|
||||
test_case_excl_list=`xmlstarlet sel -t -v "/testCaseList/TestCaseExclusionList" $xml_conf`
|
||||
echo "Test Case Exclusion List = $test_case_excl_list "
|
||||
|
||||
test_case_excl_list=`sed "s/\+/\*/g" <<< "$test_case_excl_list" ` # Replace + with * for bash string substituion
|
||||
|
||||
read -a test_case_excl_array <<< "$test_case_excl_list"
|
||||
|
||||
echo "test_case_list = $test_case_list"
|
||||
|
||||
echo "Test Case Exclusion List = $test_case_excl_list \n"
|
||||
|
||||
readarray -t test_case_array <<<"$test_case_list"
|
||||
|
||||
read -a test_case_group_array <<< "$test_case_group"
|
||||
@@ -447,6 +456,15 @@ for search_expr in "${test_case_array[@]}"
|
||||
flag_run_test_case=1
|
||||
fi
|
||||
|
||||
for search_excl in "${test_case_excl_array[@]}"
|
||||
do
|
||||
if [[ $search_expr == $search_excl ]];then
|
||||
flag_run_test_case=0
|
||||
echo_info "Test case $search_expr match found in test case excl group. Will skip the test case for execution..."
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
|
||||
#We skip this test case if it is not in the group list
|
||||
if [ "$flag_run_test_case" -ne "1" ]; then
|
||||
|
||||
@@ -216,7 +216,7 @@ def sftp_module (username, password, hostname, ports, paramList,logfile):
|
||||
# \brief bash script stub put at the end of scripts to terminate it
|
||||
# \param timeout_cmd terminate script after timeout_cmd seconds
|
||||
# \param terminate_missing_procs if True terminate all the processes launched by script if one of them terminates prematurely (due to error)
|
||||
def finalize_deploy_script (timeout_cmd, terminate_missing_procs='True'):
|
||||
def finalize_deploy_script (timeout_cmd, terminate_missing_procs='False'):
|
||||
cmd = 'declare -i timeout_cmd='+str(timeout_cmd) + '\n'
|
||||
if terminate_missing_procs == 'True':
|
||||
cmd = cmd + """
|
||||
@@ -1105,6 +1105,7 @@ pw =''
|
||||
i = 0
|
||||
dlsim=0
|
||||
localshell=0
|
||||
GitOAI5GRepo=''
|
||||
GitOAI5GRepoBranch=''
|
||||
GitOAI5GHeadVersion=''
|
||||
user=''
|
||||
@@ -1141,6 +1142,9 @@ while i < len (sys.argv):
|
||||
i = i +1
|
||||
elif arg == '-c':
|
||||
cleanUpRemoteMachines=True
|
||||
elif arg == '-5GRepo':
|
||||
GitOAI5GRepo = sys.argv[i+1]
|
||||
i = i +1
|
||||
elif arg == '-5GRepoBranch':
|
||||
GitOAI5GRepoBranch = sys.argv[i+1]
|
||||
i = i +1
|
||||
@@ -1190,6 +1194,7 @@ while i < len (sys.argv):
|
||||
print "-r: Remove the log directory in autotests"
|
||||
print "-g: Run test cases in a group"
|
||||
print "-c: Run cleanup scripts on remote machines and exit"
|
||||
print "-5GRepo: Repository for OAI 5G to use to run tests (overrides GitOAI5GRepo in test_case_list.xml)"
|
||||
print "-5GRepoBranch: Branch for OAI 5G Repository to run tests (overrides the branch in test_case_list.xml)"
|
||||
print "-5GRepoHeadVersion: Head commit on which to run tests (overrides the branch in test_case_list.xml)"
|
||||
print "-u: use the user name passed as argument"
|
||||
@@ -1278,7 +1283,9 @@ if MachineList =='':
|
||||
MachineList = xmlRoot.findtext('MachineList',default='')
|
||||
NFSResultsShare = xmlRoot.findtext('NFSResultsShare',default='')
|
||||
GitOpenaircnRepo = xmlRoot.findtext('GitOpenair-cnRepo',default='')
|
||||
GitOAI5GRepo = xmlRoot.findtext('GitOAI5GRepo',default='')
|
||||
|
||||
if GitOAI5GRepo == '':
|
||||
GitOAI5GRepo = xmlRoot.findtext('GitOAI5GRepo',default='')
|
||||
|
||||
if GitOAI5GRepoBranch == '':
|
||||
GitOAI5GRepoBranch = xmlRoot.findtext('GitOAI5GRepoBranch',default='')
|
||||
@@ -1394,15 +1401,15 @@ for oai in oai_list:
|
||||
#cmd = cmd + 'mkdir -p ' + logdir + '\n'
|
||||
cmd = cmd + 'cd '+ logdir + '\n'
|
||||
cmd = cmd + 'git config --global http.sslVerify false \n'
|
||||
cmd = cmd + 'git clone --depth 1 '+ GitOAI5GRepo + ' -b ' + GitOAI5GRepoBranch +' \n'
|
||||
cmd = cmd + 'git clone '+ GitOpenaircnRepo + ' -b ' +GitOpenaircnRepoBranch + ' \n'
|
||||
cmd = cmd + 'git clone '+ GitOAI5GRepo +' \n'
|
||||
cmd = cmd + 'git clone '+ GitOpenaircnRepo + ' \n'
|
||||
cmd = cmd + 'cd ' + logdirOAI5GRepo + '\n'
|
||||
cmd = cmd + 'git checkout ' + GitOAI5GRepoBranch + '\n'
|
||||
#cmd = cmd + 'git checkout ' + GitOAI5GHeadVersion + '\n'
|
||||
cmd = cmd + 'git_head=`git ls-remote |grep \'' + GitOAI5GRepoBranch + '\'` \n'
|
||||
cmd = cmd + 'git_head=($git_head) \n'
|
||||
cmd = cmd + 'git_head=${git_head[0]} \n'
|
||||
cmd = cmd + 'echo \"GitOAI5GHeadVersion_remote = $git_head\"'
|
||||
cmd = cmd + 'echo \"GitOAI5GHeadVersion_remote = $git_head\" \n'
|
||||
cmd = cmd + 'echo \"GitOAI5GHeadVersion_local = ' + GitOAI5GHeadVersion + '\" \n'
|
||||
if flag_skip_git_head_check==True:
|
||||
cmd = cmd + 'echo \"skipping GitHead check...\" \n '
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,11 +1,13 @@
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
set ( CMAKE_BUILD_TYPE "RelWithDebInfo" )
|
||||
set ( ASN_DEBUG False)
|
||||
set ( ADDR_CONF False )
|
||||
set ( DEBUG_OMG False )
|
||||
set ( DISABLE_XER_PRINT False )
|
||||
set ( DRIVER2013 True )
|
||||
set ( EMOS False )
|
||||
set ( EMIT_ASN_DEBUG False )
|
||||
set ( ENABLE_FXP True )
|
||||
set ( ENABLE_ITTI True )
|
||||
set ( ENABLE_NAS_UE_LOGGING True )
|
||||
@@ -47,9 +49,9 @@ set ( OAI_EMU False )
|
||||
set ( OAISIM False )
|
||||
set ( OAI_NW_DRIVER_TYPE_ETHERNET False )
|
||||
set ( OAI_NW_DRIVER_USE_NETLINK True )
|
||||
set ( OPENAIR1 False )
|
||||
set ( OPENAIR2 False )
|
||||
set ( OPENAIR_LTE F )
|
||||
set ( OPENAIR1 True )
|
||||
set ( OPENAIR2 True )
|
||||
set ( OPENAIR_LTE True )
|
||||
set ( PACKAGE_NAME "epc_test" )
|
||||
set ( PBS_SIM False )
|
||||
set ( PDCP_USE_NETLINK True )
|
||||
@@ -74,4 +76,4 @@ set ( SMBV False )
|
||||
set ( TEST_OMG False )
|
||||
set ( USE_MME "R10" )
|
||||
set ( USER_MODE True )
|
||||
set ( XER_PRINT False )
|
||||
set ( XER_PRINT True )
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
################################################################################
|
||||
# file build_helper
|
||||
# brief
|
||||
# author Laurent Thomas
|
||||
# authors Laurent Thomas, Lionel GAUTHIER
|
||||
#
|
||||
#######################################
|
||||
SUDO='sudo -E'
|
||||
@@ -269,7 +269,9 @@ check_install_oai_software() {
|
||||
pydb \
|
||||
wvdial \
|
||||
python-numpy \
|
||||
sshpass
|
||||
sshpass \
|
||||
libxslt1-dev
|
||||
|
||||
$SUDO update-alternatives --set liblapack.so /usr/lib/atlas-base/atlas/liblapack.so
|
||||
if [ `lsb_release -rs` = '12.04' ] ; then
|
||||
install_nettle_from_source
|
||||
@@ -288,13 +290,15 @@ install_asn1c_from_source(){
|
||||
asn1_install_dir=$OPENAIR_DIR/cmake_targets/log/asn1c_install_log.txt
|
||||
echo_info "\nInstalling ASN1. The log file for ASN1 installation is here: $asn1_install_dir "
|
||||
(
|
||||
rm -rf /tmp/asn1c-r1516
|
||||
$SUDO rm -rf /tmp/asn1c-r1516
|
||||
mkdir -p /tmp/asn1c-r1516
|
||||
cd /tmp/asn1c-r1516
|
||||
svn co https://github.com/vlm/asn1c/trunk /tmp/asn1c-r1516 -r 1516
|
||||
patch -p0 < $OPENAIR_DIR/openair3/S1AP/MESSAGES/ASN1/asn1cpatch.p0
|
||||
patch -p0 < $OPENAIR_DIR/openair3/S1AP/MESSAGES/ASN1/asn1cpatch_2.p0
|
||||
patch -p0 < $OPENAIR_DIR/openair2/RRC/LITE/MESSAGES/asn1c/asn1cpatch.p0
|
||||
rm -rf /tmp/asn1c-r1516/*
|
||||
svn co https://github.com/vlm/asn1c/trunk /tmp/asn1c-r1516 -r 1516 > /tmp/log_compile_asn1c
|
||||
patch -p0 < $OPENAIR_DIR/openair3/S1AP/MESSAGES/ASN1/asn1cpatch.p0 >> /tmp/log_compile_asn1c
|
||||
patch -p0 < $OPENAIR_DIR/openair3/S1AP/MESSAGES/ASN1/asn1cpatch_2.p0 >> /tmp/log_compile_asn1c
|
||||
patch -p0 < $OPENAIR_DIR/openair2/RRC/LITE/MESSAGES/asn1c/asn1cpatch.p0 >> /tmp/log_compile_asn1c
|
||||
patch -p0 < $OPENAIR_DIR/openair3/S1AP/MESSAGES/ASN1/asn1cpatch_3.p0 >> /tmp/log_compile_asn1c
|
||||
./configure
|
||||
make -j`nproc`
|
||||
$SUDO make install
|
||||
@@ -324,7 +328,6 @@ install_nas_tools() {
|
||||
}
|
||||
|
||||
|
||||
|
||||
################################
|
||||
# set_openair_env
|
||||
###############################
|
||||
@@ -397,4 +400,4 @@ if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
|
||||
fi
|
||||
|
||||
return $stat
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
# Contact Information
|
||||
# OpenAirInterface Admin: openair_admin@eurecom.fr
|
||||
# OpenAirInterface Tech : openair_tech@eurecom.fr
|
||||
# OpenAirInterface Dev : openair4g-devel@eurecom.fr
|
||||
# OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr
|
||||
#
|
||||
# Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
|
||||
#
|
||||
@@ -121,6 +121,7 @@ function main()
|
||||
echo "Cleaning TEST_EPC"
|
||||
fi
|
||||
rm -f $OPENAIR_DIR/targets/bin/test_epc_generate_scenario
|
||||
rm -f $OPENAIR_DIR/targets/bin/test_epc_play_scenario
|
||||
rm -Rf build 2>&1
|
||||
mkdir -m 777 -p -v build
|
||||
fi
|
||||
@@ -140,6 +141,13 @@ function main()
|
||||
compilations \
|
||||
epc_test test_epc_generate_scenario \
|
||||
test_epc_generate_scenario $dbin/test_epc_generate_scenario
|
||||
|
||||
compilations \
|
||||
epc_test test_epc_play_scenario \
|
||||
test_epc_play_scenario $dbin/test_epc_play_scenario
|
||||
|
||||
$SUDO cp -upv test_epc_generate_scenario /usr/local/bin
|
||||
$SUDO cp -upv test_epc_play_scenario /usr/local/bin
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -56,6 +56,7 @@ function help()
|
||||
echo_error "Mandatory arguments to long options are mandatory for short options too."
|
||||
echo_error " -g, --gdb Run with GDB."
|
||||
echo_error " -h, --help Print this help."
|
||||
echo_error " -e, --ulsch-max-errors num-errs maximum allowed number of uplink errors"
|
||||
echo_error " -f, --rf-config-file filename RF specific configuration file"
|
||||
echo_error " -K, --itti-dump-file filename ITTI dump file containing all ITTI events occuring during EPC runtime.(can omit file name if last argument)"
|
||||
echo_error " -M, --target-dl-mcs mcs Downlink target MCS."
|
||||
@@ -138,6 +139,12 @@ function main()
|
||||
shift;
|
||||
exit 0
|
||||
;;
|
||||
-e | --ulsch-max-errors)
|
||||
ulsch_max_errors=$2
|
||||
echo "setting --ulsch-max-errors to $ulsch_max_errors"
|
||||
exe_arguments="$exe_arguments --ulsch-max-errors=$ulsch_max_errors"
|
||||
shift 2;
|
||||
;;
|
||||
-f | --rf-config-file)
|
||||
rf_config_file=$2
|
||||
# can omit file name if last arg on the line
|
||||
|
||||
@@ -777,6 +777,7 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form,
|
||||
fl_set_xyplot_data(form->pdsch_llr,bit,llr,coded_bits_per_codeword0,"","","");
|
||||
}
|
||||
|
||||
|
||||
// PDSCH I/Q of MF Output
|
||||
if (pdsch_comp!=NULL) {
|
||||
ind=0;
|
||||
|
||||
@@ -48,7 +48,19 @@ Description Contains global common definitions
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef signed char boolean_t;
|
||||
|
||||
#if !defined(TRUE)
|
||||
#define TRUE (boolean_t)0x01
|
||||
#endif
|
||||
|
||||
#if !defined(FALSE)
|
||||
#define FALSE (boolean_t)0x00
|
||||
#endif
|
||||
|
||||
#define BOOL_NOT(b) (b^TRUE)
|
||||
|
||||
#define NAS_UE_ID_FMT "0x%06x"
|
||||
|
||||
@@ -59,13 +71,6 @@ Description Contains global common definitions
|
||||
#define RETURNok (0)
|
||||
#define RETURNerror (-1)
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE (0)
|
||||
#endif
|
||||
#ifndef TRUE
|
||||
#define TRUE (1)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Name of the environment variable which defines the default directory
|
||||
* where the NAS application is executed and where are located files
|
||||
|
||||
@@ -112,7 +112,7 @@ typedef struct net_ip_address_s {
|
||||
unsigned ipv4:1;
|
||||
unsigned ipv6:1;
|
||||
char ipv4_address[16];
|
||||
char ipv6_address[40];
|
||||
char ipv6_address[46];
|
||||
} net_ip_address_t;
|
||||
|
||||
typedef uint64_t bitrate_t;
|
||||
|
||||
@@ -265,7 +265,7 @@ static const eutra_band_t eutra_bands[] = {
|
||||
|
||||
Enb_properties_array_t enb_properties;
|
||||
|
||||
static void enb_config_display(void)
|
||||
void enb_config_display(void)
|
||||
{
|
||||
int i,j;
|
||||
|
||||
|
||||
@@ -264,6 +264,7 @@ typedef struct Enb_properties_array_s {
|
||||
Enb_properties_t *properties[MAX_ENB];
|
||||
} Enb_properties_array_t;
|
||||
|
||||
void enb_config_display(void);
|
||||
const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP);
|
||||
|
||||
const Enb_properties_array_t *enb_config_get(void);
|
||||
|
||||
@@ -60,6 +60,8 @@
|
||||
# include "DRB-ToAddModList.h"
|
||||
# include "SRB-ToAddMod.h"
|
||||
# include "SRB-ToAddModList.h"
|
||||
# include "DRB-ToReleaseList.h"
|
||||
|
||||
#ifdef Rel10
|
||||
#include "PMCH-InfoList-r9.h"
|
||||
#endif
|
||||
|
||||
@@ -51,10 +51,6 @@
|
||||
#include "UTIL/OPT/opt.h"
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef HAVE_STRNDUP
|
||||
char * strndup (const char *s, size_t size);
|
||||
#endif
|
||||
|
||||
static int oai_emulation_; /*!< \brief indicating that the parsing position is now within OAI_Emulation_*/
|
||||
|
||||
static int environment_system_config_; /*!< \brief indicating that the parsing position is now within Envi_Config_*/
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -36,7 +36,7 @@ def outputHeaderToFile(f, filename):
|
||||
f.write("""/*******************************************************************************
|
||||
|
||||
Eurecom OpenAirInterface
|
||||
Copyright(c) 1999 - 2013 Eurecom
|
||||
Copyright(c) 1999 - 2015 Eurecom
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms and conditions of the GNU General Public License,
|
||||
@@ -250,20 +250,31 @@ for key in iesDefs:
|
||||
asn1cStruct = re.sub('Item', 'List', asn1cStruct)
|
||||
keylowerunderscore = re.sub('-', '_', key.lower())
|
||||
firstlower = re.sub('Item', 'List', re.sub('enb', 'eNB', lowerFirstCamelWord(asn1cStruct)))
|
||||
|
||||
f.write("/* %s in iesDefs not in ieofielist.values() */\n" % (key))
|
||||
f.write("/** \\brief Decode function for %s ies.\n" % (key))
|
||||
if len(iesDefs[key]["ies"]) != 0:
|
||||
f.write(" * \\param %s Pointer to ASN1 structure in which data will be stored\n" % (lowerFirstCamelWord(re.sub('-', '_', key))))
|
||||
f.write(" * \\param any_p Pointer to the ANY value to decode.\n")
|
||||
f.write(" **/\n")
|
||||
f.write("int %s_decode_%s(\n" % (fileprefix, keylowerunderscore))
|
||||
|
||||
if len(iesDefs[key]["ies"]) != 0:
|
||||
f.write(" %s_t *%s,\n" % (re.sub('-', '_', key), lowerFirstCamelWord(re.sub('-', '_', key))))
|
||||
f.write(" ANY_t *any_p);\n\n")
|
||||
|
||||
f.write("/* %s in iesDefs not in ieofielist.values() */\n" % (key))
|
||||
f.write("/** \\brief Compare function for %s ies.\n" % (key))
|
||||
f.write(" * \\param %s Pointer to the ASN1 structure.\n" % (firstlower))
|
||||
f.write(" * \\param %s Pointer to the ASN1 structure.\n" % (firstlower))
|
||||
f.write(" **/\n")
|
||||
f.write("asn_comp_rval_t * %s_compare_%s(\n" % (fileprefix, keylowerunderscore))
|
||||
f.write(" %s_t *%s1,\n" % (re.sub('-', '_', key), lowerFirstCamelWord(re.sub('-', '_', key))))
|
||||
f.write(" %s_t *%s2);\n\n" % (re.sub('-', '_', key), lowerFirstCamelWord(re.sub('-', '_', key))))
|
||||
|
||||
if len(iesDefs[key]["ies"]) == 0:
|
||||
continue
|
||||
|
||||
f.write("/* %s in iesDefs not in ieofielist.values() */\n" % (key))
|
||||
f.write("/** \\brief Encode function for %s ies.\n" % (key))
|
||||
f.write(" * \\param %s Pointer to the ASN1 structure.\n" % (firstlower))
|
||||
f.write(" * \\param %s Pointer to the IES structure.\n" % (lowerFirstCamelWord(re.sub('-', '_', key))))
|
||||
@@ -272,16 +283,19 @@ for key in iesDefs:
|
||||
f.write(" %s_t *%s,\n" % (asn1cStruct, firstlower))
|
||||
f.write(" %s_t *%s);\n\n" % (re.sub('-', '_', key), lowerFirstCamelWord(re.sub('-', '_', key))))
|
||||
|
||||
|
||||
for key in iesDefs:
|
||||
if key not in ieofielist.values():
|
||||
continue
|
||||
asn1cStruct = re.sub('-', '_', re.sub('IEs', '', key))
|
||||
asn1cStruct = re.sub('Item', 'List', asn1cStruct)
|
||||
firstlower = re.sub('Item', 'List', re.sub('enb', 'eNB', lowerFirstCamelWord(asn1cStruct)))
|
||||
f.write("/* %s in iesDefs in ieofielist.values() */\n" % (key))
|
||||
f.write("/** \\brief Encode function for %s ies.\n" % (key))
|
||||
f.write(" * \\param %s Pointer to the ASN1 structure.\n" % (firstlower))
|
||||
f.write(" * \\param %s Pointer to the IES structure.\n" % (lowerFirstCamelWord(re.sub('-', '_', key))))
|
||||
f.write(" **/\n")
|
||||
f.write("/* %s in iesDefs in ieofielist.values() */\n" % (key))
|
||||
f.write("int %s_encode_%s(\n" % (fileprefix, firstlower.lower()))
|
||||
f.write(" %s_t *%s,\n" % (asn1cStruct, firstlower))
|
||||
f.write(" %sIEs_t *%sIEs);\n\n" % (asn1cStruct, firstlower))
|
||||
@@ -289,9 +303,19 @@ for key in iesDefs:
|
||||
f.write(" * \\param any_p Pointer to the ANY value to decode.\n")
|
||||
f.write(" * \\param callback Callback function called when any_p is successfully decoded.\n")
|
||||
f.write(" **/\n")
|
||||
f.write("/* %s in iesDefs in ieofielist.values() */\n" % (key))
|
||||
f.write("int %s_decode_%s(\n" % (fileprefix, firstlower.lower()))
|
||||
f.write(" %sIEs_t *%sIEs,\n" % (asn1cStruct, firstlower))
|
||||
f.write(" %s_t *%s);\n\n" % (asn1cStruct, lowerFirstCamelWord(asn1cStruct)))
|
||||
f.write("/** \\brief Compare function for %s ies.\n" % (key))
|
||||
f.write(" * \\param %s Pointer to the IES structure.\n" % (firstlower))
|
||||
f.write(" * \\param %s Pointer to the IES structure.\n" % (firstlower))
|
||||
f.write(" **/\n")
|
||||
f.write("asn_comp_rval_t * %s_compare_%s(\n" % (fileprefix, firstlower.lower()))
|
||||
f.write(" %sIEs_t *%s1,\n" % (asn1cStruct, firstlower))
|
||||
f.write(" %sIEs_t *%s2);\n\n" % (asn1cStruct, firstlower))
|
||||
|
||||
|
||||
|
||||
for key in iesDefs:
|
||||
asn1cStruct = re.sub('-', '_', re.sub('IEs', '', key))
|
||||
@@ -704,3 +728,170 @@ for (key, value) in iesDefs.items():
|
||||
#f.write("cb_failed:\n")
|
||||
#f.write(" return er;\n")
|
||||
f.write("}\n\n")
|
||||
|
||||
|
||||
#Generate xer print functions
|
||||
f = open(outdir + fileprefix + '_compare.c', 'w')
|
||||
outputHeaderToFile(f, filename)
|
||||
f.write("#include <stdlib.h>\n")
|
||||
f.write("#include <stdio.h>\n\n")
|
||||
f.write("#include <asn_application.h>\n#include <asn_internal.h>\n\n")
|
||||
f.write("#include \"%s_common.h\"\n#include \"%s_ies_defs.h\"\n" % (fileprefix, fileprefix))
|
||||
f.write("#include \"%s-ProtocolIE-ID.h\"\n\n" % (fileprefix_first_upper))
|
||||
|
||||
|
||||
for key in iesDefs:
|
||||
if key in ieofielist.values():
|
||||
continue
|
||||
structName = re.sub('ies', '', key)
|
||||
asn1cStruct = re.sub('-', '_', re.sub('IEs', '', key))
|
||||
asn1cStruct = re.sub('Item', 'List', asn1cStruct)
|
||||
if asn1cStruct.rfind('_') == len(asn1cStruct) - 1:
|
||||
asn1cStruct = asn1cStruct[:-1]
|
||||
asn1cStructfirstlower = asn1cStruct[:1].lower() + asn1cStruct[1:]
|
||||
firstwordlower = re.sub('Item', 'List', re.sub('enb', 'eNB', lowerFirstCamelWord(asn1cStruct)))
|
||||
|
||||
iesaccess = ""
|
||||
if key not in ieofielist.values():
|
||||
iesaccess = "%s_ies." % (firstwordlower)
|
||||
|
||||
keyName = re.sub('-', '_', key)
|
||||
keyupperunderscore = keyName.upper()
|
||||
# No IE to encode...
|
||||
if len(iesDefs[key]["ies"]) == 0:
|
||||
continue
|
||||
|
||||
f.write("asn_comp_rval_t * %s_compare_%s(\n" % (fileprefix, re.sub('-', '_', structName.lower())))
|
||||
f.write(" %s_t *%s1,\n" % (re.sub('-', '_', key), lowerFirstCamelWord(re.sub('-', '_', key))))
|
||||
f.write(" %s_t *%s2) {\n\n" % (re.sub('-', '_', key), lowerFirstCamelWord(re.sub('-', '_', key))))
|
||||
|
||||
f.write(" asn_comp_rval_t *rv = NULL;\n\n")
|
||||
f.write(" asn_comp_rval_t *rv2 = NULL;\n\n")
|
||||
|
||||
f.write(" assert(%s1 != NULL);\n" % (lowerFirstCamelWord(re.sub('-', '_', key))));
|
||||
f.write(" assert(%s2 != NULL);\n" % (lowerFirstCamelWord(re.sub('-', '_', key))));
|
||||
|
||||
loop = 0
|
||||
for ie in iesDefs[key]["ies"]:
|
||||
iename = re.sub('-', '_', re.sub('id-', '', ie[0]))
|
||||
ienameunderscore = re.sub('-', '_', iename)
|
||||
ienamefirstwordlower = lowerFirstCamelWord(iename)
|
||||
ieupperunderscore = re.sub('-', '_', re.sub('id-', '', ie[0])).upper()
|
||||
ietypeunderscore = re.sub('-', '_', ie[2])
|
||||
|
||||
if ie[3] != "mandatory":
|
||||
|
||||
loop = loop + 1
|
||||
if loop == 1:
|
||||
#f.write(" %s_IE_t *ie1 = NULL;\n" % (fileprefix_first_upper))
|
||||
#f.write(" %s_IE_t *ie2 = NULL;\n" % (fileprefix_first_upper))
|
||||
f.write(" if (%s1->presenceMask != %s2->presenceMask) {rv=calloc(1,sizeof(asn_comp_rval_t));rv->name = asn_DEF_%s.name;rv->structure1 = %s1;rv->structure2 = %s2;rv->err_code = COMPARE_ERR_CODE_VALUE_NULL; return rv;}\n" % (lowerFirstCamelWord(re.sub('-', '_', key)), lowerFirstCamelWord(re.sub('-', '_', key)), ietypeunderscore, lowerFirstCamelWord(re.sub('-', '_', key)), lowerFirstCamelWord(re.sub('-', '_', key))))
|
||||
|
||||
if ie[3] == "optional":
|
||||
f.write(" /* Optional field */\n")
|
||||
elif ie[3] == "conditional":
|
||||
f.write(" /* Conditional field */\n")
|
||||
f.write(" if (%s1->presenceMask & %s_%s_PRESENT) {\n" % (lowerFirstCamelWord(re.sub('-', '_', key)), keyupperunderscore, ieupperunderscore))
|
||||
|
||||
|
||||
if ie[2] in ieofielist.keys():
|
||||
f.write(" /* collection field */\n")
|
||||
f.write(" rv2 = %s_compare_%s(&%s1->%s, &%s2->%s);\n" % (fileprefix, ietypeunderscore.lower(), lowerFirstCamelWord(re.sub('-', '_', key)), ienamefirstwordlower, lowerFirstCamelWord(re.sub('-', '_', key)), ienamefirstwordlower ))
|
||||
f.write(" if(rv2) {")
|
||||
f.write(" if (NULL == rv) {")
|
||||
f.write(" rv = rv2;")
|
||||
f.write(" } else {")
|
||||
f.write(" rv2->next = rv;")
|
||||
f.write(" rv = rv2;")
|
||||
f.write(" }")
|
||||
f.write(" rv2 = NULL;")
|
||||
f.write(" }")
|
||||
else:
|
||||
f.write(" /* simple field */\n")
|
||||
f.write(" rv2 = asn_DEF_%s.compare(&asn_DEF_%s, &%s1->%s, &asn_DEF_%s, &%s2->%s); \n" % (ietypeunderscore, ietypeunderscore, lowerFirstCamelWord(re.sub('-', '_', key)), ienamefirstwordlower, ietypeunderscore, lowerFirstCamelWord(re.sub('-', '_', key)), ienamefirstwordlower ))
|
||||
f.write(" if (rv2) {")
|
||||
f.write(" if (NULL == rv) {")
|
||||
f.write(" rv = rv2;")
|
||||
f.write(" } else {")
|
||||
f.write(" rv2->next = rv;")
|
||||
f.write(" rv = rv2;")
|
||||
f.write(" }")
|
||||
f.write(" rv2 = NULL;")
|
||||
f.write(" if (!rv->name) rv->name = asn_DEF_%s.name;" % (ietypeunderscore))
|
||||
f.write(" }")
|
||||
|
||||
f.write(" assert(0);\n");
|
||||
f.write(" }\n\n")
|
||||
|
||||
else:
|
||||
if ie[2] in ieofielist.keys():
|
||||
f.write(" /* Mandatory collection field */\n")
|
||||
f.write(" rv2 = %s_compare_%s(&%s1->%s, &%s2->%s);\n" % (fileprefix, ietypeunderscore.lower(), lowerFirstCamelWord(re.sub('-', '_', key)), ienamefirstwordlower, lowerFirstCamelWord(re.sub('-', '_', key)), ienamefirstwordlower ))
|
||||
f.write(" if (rv2) {\n")
|
||||
f.write(" if (NULL == rv) {\n")
|
||||
f.write(" rv = rv2;\n")
|
||||
f.write(" } else {\n")
|
||||
f.write(" rv2->next = rv;\n")
|
||||
f.write(" rv = rv2;\n")
|
||||
f.write(" }\n")
|
||||
f.write(" rv2 = NULL;\n")
|
||||
f.write(" }\n")
|
||||
|
||||
else:
|
||||
f.write(" /* Mandatory simple field */\n")
|
||||
f.write(" rv2 = asn_DEF_%s.compare(&asn_DEF_%s, &%s1->%s, &asn_DEF_%s, &%s2->%s);\n" % (ietypeunderscore, ietypeunderscore, lowerFirstCamelWord(re.sub('-', '_', key)), ienamefirstwordlower, ietypeunderscore, lowerFirstCamelWord(re.sub('-', '_', key)), ienamefirstwordlower ))
|
||||
f.write(" if(rv2) {\n")
|
||||
f.write(" if (NULL == rv) {\n")
|
||||
f.write(" rv = rv2;\n")
|
||||
f.write(" } else {\n")
|
||||
f.write(" rv2->next = rv;\n")
|
||||
f.write(" rv = rv2;\n")
|
||||
f.write(" }\n")
|
||||
f.write(" rv2 = NULL;\n")
|
||||
f.write(" if (!rv->name) rv->name = asn_DEF_%s.name;\n" % (ietypeunderscore))
|
||||
f.write(" }\n")
|
||||
f.write(" return rv;\n")
|
||||
f.write("}\n\n")
|
||||
|
||||
for (key, value) in iesDefs.items():
|
||||
if key not in ieofielist.values():
|
||||
continue
|
||||
|
||||
ie = value["ies"][0]
|
||||
ietypeunderscore = re.sub('-', '_', ie[2])
|
||||
asn1cStruct = re.sub('-', '_', re.sub('IEs', '', re.sub('-IEs', '', key)))
|
||||
asn1cStruct = re.sub('Item', 'List', asn1cStruct)
|
||||
firstwordlower = re.sub('Item', 'List', re.sub('enb', 'eNB', lowerFirstCamelWord(asn1cStruct)))
|
||||
|
||||
for (i, j) in ieofielist.items():
|
||||
if j == key:
|
||||
break
|
||||
|
||||
f.write("extern asn_TYPE_descriptor_t asn_DEF_%s;\n" % (ietypeunderscore))
|
||||
|
||||
f.write("asn_comp_rval_t * %s_compare_%s(\n" % (fileprefix, re.sub('-', '_', i).lower()))
|
||||
f.write(" %sIEs_t *%sIEs1,\n" % (re.sub('-', '_', i), lowerFirstCamelWord(re.sub('-', '_', i))))
|
||||
f.write(" %sIEs_t *%sIEs2) {\n\n" % (re.sub('-', '_', i), lowerFirstCamelWord(re.sub('-', '_', i))))
|
||||
f.write(" int i;\n")
|
||||
f.write(" asn_comp_rval_t *rv = NULL;\n\n")
|
||||
f.write(" asn_comp_rval_t *rv2 = NULL;\n\n")
|
||||
|
||||
|
||||
f.write(" assert(%sIEs1 != NULL);\n" % (lowerFirstCamelWord(re.sub('-', '_', i))));
|
||||
f.write(" assert(%sIEs2 != NULL);\n\n" % (lowerFirstCamelWord(re.sub('-', '_', i))));
|
||||
|
||||
f.write(" for (i = 0; i < %sIEs1->%s.count; i++) {\n" % (lowerFirstCamelWord(re.sub('-', '_', i)), re.sub('IEs', '', lowerFirstCamelWord(re.sub('-', '_', key)))))
|
||||
f.write(" rv2 = asn_DEF_%s.compare(&asn_DEF_%s, %sIEs1->%s.array[i], &asn_DEF_%s, %sIEs2->%s.array[i]);\n" % (ietypeunderscore, ietypeunderscore, lowerFirstCamelWord(re.sub('-', '_', i)), re.sub('IEs', '', lowerFirstCamelWord(re.sub('-', '_', key))), ietypeunderscore, lowerFirstCamelWord(re.sub('-', '_', i)), re.sub('IEs', '', lowerFirstCamelWord(re.sub('-', '_', key)))))
|
||||
f.write(" if(rv2) {")
|
||||
f.write(" if (NULL == rv) {")
|
||||
f.write(" rv = rv2;")
|
||||
f.write(" } else {")
|
||||
f.write(" rv2->next = rv;")
|
||||
f.write(" rv = rv2;")
|
||||
f.write(" }")
|
||||
f.write(" rv2 = NULL;")
|
||||
f.write(" }")
|
||||
f.write(" }\n")
|
||||
f.write(" return rv;\n")
|
||||
f.write("}\n\n")
|
||||
|
||||
|
||||
@@ -72,9 +72,9 @@ s1ap_eNB_config_t s1ap_config;
|
||||
static int s1ap_eNB_generate_s1_setup_request(
|
||||
s1ap_eNB_instance_t *instance_p, s1ap_eNB_mme_data_t *s1ap_mme_data_p);
|
||||
|
||||
static
|
||||
|
||||
void s1ap_eNB_handle_register_eNB(instance_t instance, s1ap_register_enb_req_t *s1ap_register_eNB);
|
||||
static
|
||||
|
||||
void s1ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_association_resp_t *sctp_new_association_resp);
|
||||
|
||||
uint32_t s1ap_generate_eNB_id(void)
|
||||
@@ -150,7 +150,7 @@ static void s1ap_eNB_register_mme(s1ap_eNB_instance_t *instance_p,
|
||||
itti_send_msg_to_task(TASK_SCTP, instance_p->instance, message_p);
|
||||
}
|
||||
|
||||
static
|
||||
|
||||
void s1ap_eNB_handle_register_eNB(instance_t instance, s1ap_register_enb_req_t *s1ap_register_eNB)
|
||||
{
|
||||
s1ap_eNB_instance_t *new_instance;
|
||||
@@ -210,7 +210,6 @@ void s1ap_eNB_handle_register_eNB(instance_t instance, s1ap_register_enb_req_t *
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void s1ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_association_resp_t *sctp_new_association_resp)
|
||||
{
|
||||
s1ap_eNB_instance_t *instance_p;
|
||||
|
||||
@@ -100,6 +100,7 @@ static STAILQ_HEAD(sctp_cnx_list_head, sctp_cnx_list_elm_s) sctp_cnx_list;
|
||||
static uint16_t sctp_nb_cnx = 0;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
struct sctp_cnx_list_elm_s *sctp_get_cnx(int32_t assoc_id, int sd)
|
||||
{
|
||||
struct sctp_cnx_list_elm_s *elm;
|
||||
@@ -119,6 +120,7 @@ struct sctp_cnx_list_elm_s *sctp_get_cnx(int32_t assoc_id, int sd)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void
|
||||
sctp_handle_new_association_req(
|
||||
const instance_t instance,
|
||||
@@ -388,6 +390,7 @@ sctp_handle_new_association_req(
|
||||
sd, sctp_nb_cnx, assoc_id);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void sctp_send_data(
|
||||
instance_t instance,
|
||||
task_id_t task_id,
|
||||
@@ -430,6 +433,7 @@ void sctp_send_data(
|
||||
sctp_cnx->assoc_id);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static int sctp_close_association(
|
||||
const instance_t instance,
|
||||
const task_id_t requestor,
|
||||
@@ -456,6 +460,7 @@ static int sctp_close_association(
|
||||
return 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static int sctp_create_new_listener(
|
||||
const instance_t instance,
|
||||
const task_id_t requestor,
|
||||
@@ -580,6 +585,7 @@ err:
|
||||
return -1;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static inline
|
||||
void
|
||||
sctp_eNB_accept_associations(
|
||||
@@ -646,6 +652,7 @@ sctp_eNB_accept_associations(
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static inline
|
||||
void
|
||||
sctp_eNB_read_from_socket(
|
||||
@@ -770,6 +777,7 @@ sctp_eNB_read_from_socket(
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void
|
||||
sctp_eNB_flush_sockets(
|
||||
struct epoll_event *events, int nb_events)
|
||||
@@ -799,6 +807,7 @@ sctp_eNB_flush_sockets(
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void *sctp_eNB_task(void *arg)
|
||||
{
|
||||
int nb_events;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+174
@@ -0,0 +1,174 @@
|
||||
Active_eNBs = ( "eNB_Eurecom_LTEBox");
|
||||
# Asn1_verbosity, choice in: none, info, annoying
|
||||
Asn1_verbosity = "none";
|
||||
|
||||
eNBs =
|
||||
(
|
||||
{
|
||||
////////// Identification parameters:
|
||||
eNB_ID = 0xe00;
|
||||
|
||||
cell_type = "CELL_MACRO_ENB";
|
||||
|
||||
eNB_name = "eNB_Eurecom_LTEBox";
|
||||
|
||||
// Tracking area code, 0x0000 and 0xfffe are reserved values
|
||||
tracking_area_code = "1";
|
||||
|
||||
mobile_country_code = "208";
|
||||
|
||||
mobile_network_code = "95";
|
||||
|
||||
////////// Physical parameters:
|
||||
|
||||
component_carriers = (
|
||||
{
|
||||
frame_type = "FDD";
|
||||
tdd_config = 3;
|
||||
tdd_config_s = 0;
|
||||
prefix_type = "NORMAL";
|
||||
eutra_band = 7;
|
||||
downlink_frequency = 2660000000L;
|
||||
uplink_frequency_offset = -120000000;
|
||||
Nid_cell = 0;
|
||||
N_RB_DL = 25;
|
||||
Nid_cell_mbsfn = 0;
|
||||
nb_antennas_tx = 1;
|
||||
nb_antennas_rx = 1;
|
||||
tx_gain = 90;
|
||||
rx_gain = 120;
|
||||
prach_root = 0;
|
||||
prach_config_index = 0;
|
||||
prach_high_speed = "DISABLE";
|
||||
prach_zero_correlation = 1;
|
||||
prach_freq_offset = 2;
|
||||
pucch_delta_shift = 1;
|
||||
pucch_nRB_CQI = 1;
|
||||
pucch_nCS_AN = 0;
|
||||
pucch_n1_AN = 32;
|
||||
pdsch_referenceSignalPower = -26;
|
||||
pdsch_p_b = 0;
|
||||
pusch_n_SB = 1;
|
||||
pusch_enable64QAM = "DISABLE";
|
||||
pusch_hoppingMode = "interSubFrame";
|
||||
pusch_hoppingOffset = 0;
|
||||
pusch_groupHoppingEnabled = "ENABLE";
|
||||
pusch_groupAssignment = 0;
|
||||
pusch_sequenceHoppingEnabled = "DISABLE";
|
||||
pusch_nDMRS1 = 1;
|
||||
phich_duration = "NORMAL";
|
||||
phich_resource = "ONESIXTH";
|
||||
srs_enable = "DISABLE";
|
||||
/* srs_BandwidthConfig =;
|
||||
srs_SubframeConfig =;
|
||||
srs_ackNackST =;
|
||||
srs_MaxUpPts =;*/
|
||||
|
||||
pusch_p0_Nominal = -90;
|
||||
pusch_alpha = "AL1";
|
||||
pucch_p0_Nominal = -108;
|
||||
msg3_delta_Preamble = 6;
|
||||
pucch_deltaF_Format1 = "deltaF2";
|
||||
pucch_deltaF_Format1b = "deltaF3";
|
||||
pucch_deltaF_Format2 = "deltaF0";
|
||||
pucch_deltaF_Format2a = "deltaF0";
|
||||
pucch_deltaF_Format2b = "deltaF0";
|
||||
|
||||
rach_numberOfRA_Preambles = 64;
|
||||
rach_preamblesGroupAConfig = "DISABLE";
|
||||
/*
|
||||
rach_sizeOfRA_PreamblesGroupA = ;
|
||||
rach_messageSizeGroupA = ;
|
||||
rach_messagePowerOffsetGroupB = ;
|
||||
*/
|
||||
rach_powerRampingStep = 4;
|
||||
rach_preambleInitialReceivedTargetPower = -108;
|
||||
rach_preambleTransMax = 10;
|
||||
rach_raResponseWindowSize = 10;
|
||||
rach_macContentionResolutionTimer = 48;
|
||||
rach_maxHARQ_Msg3Tx = 4;
|
||||
|
||||
pcch_default_PagingCycle = 128;
|
||||
pcch_nB = "oneT";
|
||||
bcch_modificationPeriodCoeff = 2;
|
||||
ue_TimersAndConstants_t300 = 1000;
|
||||
ue_TimersAndConstants_t301 = 1000;
|
||||
ue_TimersAndConstants_t310 = 1000;
|
||||
ue_TimersAndConstants_t311 = 10000;
|
||||
ue_TimersAndConstants_n310 = 20;
|
||||
ue_TimersAndConstants_n311 = 1;
|
||||
}
|
||||
);
|
||||
|
||||
srb1_parameters :
|
||||
{
|
||||
# timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500]
|
||||
timer_poll_retransmit = 80;
|
||||
|
||||
# timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200]
|
||||
timer_reordering = 35;
|
||||
|
||||
# timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500]
|
||||
timer_status_prohibit = 0;
|
||||
|
||||
# poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)]
|
||||
poll_pdu = 4;
|
||||
|
||||
# poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)]
|
||||
poll_byte = 99999;
|
||||
|
||||
# max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32]
|
||||
max_retx_threshold = 4;
|
||||
}
|
||||
|
||||
# ------- SCTP definitions
|
||||
SCTP :
|
||||
{
|
||||
# Number of streams to use in input/output
|
||||
SCTP_INSTREAMS = 2;
|
||||
SCTP_OUTSTREAMS = 2;
|
||||
};
|
||||
|
||||
|
||||
////////// MME parameters:
|
||||
mme_ip_address = ( { ipv4 = "192.188.2.2";
|
||||
ipv6 = "192:168:30::17";
|
||||
active = "yes";
|
||||
preference = "ipv4";
|
||||
}
|
||||
);
|
||||
|
||||
NETWORK_INTERFACES :
|
||||
{
|
||||
ENB_INTERFACE_NAME_FOR_S1_MME = "tun2";
|
||||
ENB_IPV4_ADDRESS_FOR_S1_MME = "192.188.2.2/24";
|
||||
|
||||
ENB_INTERFACE_NAME_FOR_S1U = "lo";
|
||||
ENB_IPV4_ADDRESS_FOR_S1U = "127.0.0.1/24";
|
||||
ENB_PORT_FOR_S1U = 2153; # Spec 2152
|
||||
};
|
||||
|
||||
log_config :
|
||||
{
|
||||
global_log_level ="info";
|
||||
global_log_verbosity ="medium";
|
||||
hw_log_level ="info";
|
||||
hw_log_verbosity ="medium";
|
||||
phy_log_level ="info";
|
||||
phy_log_verbosity ="medium";
|
||||
mac_log_level ="info";
|
||||
mac_log_verbosity ="high";
|
||||
rlc_log_level ="info";
|
||||
rlc_log_verbosity ="medium";
|
||||
pdcp_log_level ="info";
|
||||
pdcp_log_verbosity ="medium";
|
||||
rrc_log_level ="info";
|
||||
rrc_log_verbosity ="medium";
|
||||
gtpu_log_level ="info";
|
||||
gtpu_log_verbosity ="medium";
|
||||
udp_log_level ="info";
|
||||
udp_log_verbosity ="medium";
|
||||
};
|
||||
|
||||
}
|
||||
);
|
||||
@@ -36,18 +36,33 @@
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <libconfig.h>
|
||||
#include <inttypes.h>
|
||||
#include <getopt.h>
|
||||
#include <libgen.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <libxml/xmlmemory.h>
|
||||
#include <libxml/debugXML.h>
|
||||
#include <libxml/HTMLtree.h>
|
||||
#include <libxml/xmlIO.h>
|
||||
#include <libxml/DOCBparser.h>
|
||||
#include <libxml/xinclude.h>
|
||||
#include <libxml/catalog.h>
|
||||
#include <libxslt/xslt.h>
|
||||
#include <libxslt/xsltInternals.h>
|
||||
#include <libxslt/transform.h>
|
||||
#include <libxslt/xsltutils.h>
|
||||
|
||||
#include "assertions.h"
|
||||
#include "enb_config.h"
|
||||
#include "generate_scenario.h"
|
||||
#include "s1ap_eNB.h"
|
||||
#if defined(ENABLE_ITTI)
|
||||
# include "intertask_interface.h"
|
||||
#endif
|
||||
|
||||
#define EPC_TEST_SCENARIO_MAX_ENB 2
|
||||
#include "intertask_interface.h"
|
||||
|
||||
#define ENB_CONFIG_STRING_ACTIVE_ENBS "Active_eNBs"
|
||||
|
||||
@@ -79,29 +94,201 @@
|
||||
#define ENB_CONFIG_STRING_ENB_PORT_FOR_S1U "ENB_PORT_FOR_S1U"
|
||||
|
||||
|
||||
#define ENB_CONFIG_MAX_XSLT_PARAMS 32
|
||||
|
||||
Enb_properties_array_t g_enb_properties;
|
||||
char *g_test_dir = NULL;
|
||||
char *g_pdml_in_origin = NULL;
|
||||
extern int xmlLoadExtDtdDefaultValue;
|
||||
|
||||
#define GENERATE_PDML_FILE 1
|
||||
#define GENERATE_SCENARIO 2
|
||||
|
||||
#define GS_IS_FILE 1
|
||||
#define GS_IS_DIR 2
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// test if file exist in current directory
|
||||
int is_file_exists( const char const * file_nameP, const char const *file_roleP)
|
||||
{
|
||||
struct stat s;
|
||||
int err = stat(file_nameP, &s);
|
||||
if(-1 == err) {
|
||||
if(ENOENT == errno) {
|
||||
fprintf(stderr, "Please provide a valid %s, %s does not exist\n", file_roleP, file_nameP);
|
||||
} else {
|
||||
perror("stat");
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
if(S_ISREG(s.st_mode)) {
|
||||
return GS_IS_FILE;
|
||||
} else if(S_ISDIR(s.st_mode)) {
|
||||
return GS_IS_DIR;
|
||||
} else {
|
||||
fprintf(stderr, "Please provide a valid test %s, %s exists but is not found valid\n", file_roleP, file_nameP);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
int strip_extension(char *in_filename)
|
||||
{
|
||||
static const uint8_t name_min_len = 1;
|
||||
static const uint8_t max_ext_len = 5; // .pdml !
|
||||
fprintf(stdout, "strip_extension %s\n", in_filename);
|
||||
|
||||
if (NULL != in_filename) {
|
||||
/* Check chars starting at end of string to find last '.' */
|
||||
for (ssize_t i = strlen(in_filename); i >= name_min_len; i--) {
|
||||
if (in_filename[i] == '.') {
|
||||
in_filename[i] = '\0';
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
// return number of splitted items
|
||||
int split_path( char * pathP, char *** resP)
|
||||
{
|
||||
char * saveptr1;
|
||||
char * p = strtok_r (pathP, "/", &saveptr1);
|
||||
int n_spaces = 0;
|
||||
|
||||
/// split string and append tokens to 'res'
|
||||
while (p) {
|
||||
*resP = realloc (*resP, sizeof (char*) * ++n_spaces);
|
||||
AssertFatal (*resP, "realloc failed");
|
||||
(*resP)[n_spaces-1] = p;
|
||||
p = strtok_r (NULL, "/", &saveptr1);
|
||||
}
|
||||
return n_spaces;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
int generate_test_scenario(const char const * test_nameP, const char const * pdml_in_basenameP)
|
||||
//------------------------------------------------------------------------------
|
||||
{
|
||||
//int fd_pdml_in;
|
||||
xsltStylesheetPtr cur = NULL;
|
||||
xmlDocPtr doc, res;
|
||||
FILE *test_scenario_file = NULL;
|
||||
const char test_scenario_filename[NAME_MAX];
|
||||
const char *params[2*ENB_CONFIG_MAX_XSLT_PARAMS];
|
||||
int nb_params = 0;
|
||||
int i,j;
|
||||
char astring[1024];
|
||||
char *astring2 = NULL;
|
||||
struct in_addr addr;
|
||||
|
||||
memset(test_scenario_filename, 0, sizeof(test_scenario_filename));
|
||||
memset(astring, 0, sizeof(astring));
|
||||
if (getcwd(astring, sizeof(astring)) != NULL) {
|
||||
fprintf(stdout, "working in %s directory\n", astring);
|
||||
} else {
|
||||
perror("getcwd() error");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
xmlSubstituteEntitiesDefault(1);
|
||||
xmlLoadExtDtdDefaultValue = 1;
|
||||
cur = xsltParseStylesheetFile("/usr/share/oai/xsl/generic_scenario.xsl");
|
||||
if (NULL == cur) {
|
||||
AssertFatal (0, "Could not parse stylesheet file /usr/share/oai/xsl/generic_scenario.xsl!\n");
|
||||
} else {
|
||||
fprintf(stdout, "XSLT style sheet: /usr/share/oai/xsl/generic_scenario.xsl\n");
|
||||
}
|
||||
|
||||
doc = xmlParseFile(pdml_in_basenameP);
|
||||
if (NULL == doc) {
|
||||
AssertFatal (0, "Could not parse pdml file %s!\n", pdml_in_basenameP);
|
||||
} else {
|
||||
fprintf(stdout, "pdml file: %s\n", pdml_in_basenameP);
|
||||
}
|
||||
params[nb_params++] = "test_name";
|
||||
sprintf(astring, "%s", pdml_in_basenameP);
|
||||
if (strip_extension(astring) > 0) {
|
||||
astring2 = strdup(astring);
|
||||
sprintf(astring, "\"%s\"", astring2);
|
||||
free(astring2);
|
||||
astring2 = NULL;
|
||||
} else {
|
||||
fprintf(stderr, "Assigning test name failed: %s\n", astring);
|
||||
}
|
||||
params[nb_params++] = strdup(astring);
|
||||
|
||||
for (i = 0; i < g_enb_properties.number; i++) {
|
||||
// eNB S1-C IPv4 address
|
||||
sprintf(astring, "enb%d_s1c", i);
|
||||
params[nb_params++] = strdup(astring);
|
||||
addr.s_addr = g_enb_properties.properties[i]->enb_ipv4_address_for_S1_MME;
|
||||
sprintf(astring, "\"%s\"", inet_ntoa(addr));
|
||||
params[nb_params++] = strdup(astring);
|
||||
|
||||
// MME S1-C IPv4 address
|
||||
for (j = 0; j < g_enb_properties.properties[i]->nb_mme; j++) {
|
||||
sprintf(astring, "mme%d_s1c_%d", i, j);
|
||||
params[nb_params++] = strdup(astring);
|
||||
AssertFatal (g_enb_properties.properties[i]->mme_ip_address[j].ipv4_address,
|
||||
"Only support MME IPv4 address\n");
|
||||
sprintf(astring, "\"%s\"", g_enb_properties.properties[i]->mme_ip_address[j].ipv4_address);
|
||||
params[nb_params++] = strdup(astring);
|
||||
}
|
||||
}
|
||||
params[nb_params] = NULL;
|
||||
res = xsltApplyStylesheet(cur, doc, params);
|
||||
if (NULL != res) {
|
||||
// since pdml filename is not relative (no path), just filename in current directory we can safely remove
|
||||
sprintf(test_scenario_filename,"%s",pdml_in_basenameP);
|
||||
if (strip_extension(test_scenario_filename) > 0) {
|
||||
strcat(test_scenario_filename, ".xml");
|
||||
test_scenario_file = fopen( test_scenario_filename, "w+");
|
||||
if (NULL != test_scenario_file) {
|
||||
xsltSaveResultToFile(test_scenario_file, res, cur);
|
||||
fclose(test_scenario_file);
|
||||
fprintf(stdout, "Wrote test scenario to %s\n", test_scenario_filename);
|
||||
} else {
|
||||
fprintf(stderr, "Error in fopen(%s)\n", test_scenario_filename);
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Error in strip_extension()\n");
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Error in xsltApplyStylesheet()\n");
|
||||
}
|
||||
xsltFreeStylesheet(cur);
|
||||
xmlFreeDoc(res);
|
||||
xmlFreeDoc(doc);
|
||||
|
||||
xsltCleanupGlobals();
|
||||
xmlCleanupParser();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static void enb_config_display(void)
|
||||
//------------------------------------------------------------------------------
|
||||
{
|
||||
int i,j;
|
||||
int i;
|
||||
|
||||
printf( "\n----------------------------------------------------------------------\n");
|
||||
printf( " ENB CONFIG FILE CONTENT LOADED (TBC):\n");
|
||||
printf( " ENB CONFIG FILE CONTENT LOADED:\n");
|
||||
printf( "----------------------------------------------------------------------\n");
|
||||
for (i = 0; i < g_enb_properties.number; i++) {
|
||||
printf( "ENB CONFIG for instance %u:\n\n", i);
|
||||
printf( "\teNB name: \t%s:\n",g_enb_properties.properties[i]->eNB_name);
|
||||
printf( "\teNB ID: \t%"PRIu32":\n",g_enb_properties.properties[i]->eNB_id);
|
||||
printf( "\tCell type: \t%s:\n",g_enb_properties.properties[i]->cell_type == CELL_MACRO_ENB ? "CELL_MACRO_ENB":"CELL_HOME_ENB");
|
||||
printf( "\tTAC: \t%"PRIu16":\n",g_enb_properties.properties[i]->tac);
|
||||
printf( "\tMCC: \t%"PRIu16":\n",g_enb_properties.properties[i]->mcc);
|
||||
printf( "\teNB name: \t%s\n",g_enb_properties.properties[i]->eNB_name);
|
||||
printf( "\teNB ID: \t%"PRIu32"\n",g_enb_properties.properties[i]->eNB_id);
|
||||
printf( "\tCell type: \t%s\n",g_enb_properties.properties[i]->cell_type == CELL_MACRO_ENB ? "CELL_MACRO_ENB":"CELL_HOME_ENB");
|
||||
printf( "\tTAC: \t%"PRIu16"\n",g_enb_properties.properties[i]->tac);
|
||||
printf( "\tMCC: \t%"PRIu16"\n",g_enb_properties.properties[i]->mcc);
|
||||
|
||||
if (g_enb_properties.properties[i]->mnc_digit_length == 3) {
|
||||
printf( "\tMNC: \t%03"PRIu16":\n",g_enb_properties.properties[i]->mnc);
|
||||
printf( "\tMNC: \t%03"PRIu16"\n",g_enb_properties.properties[i]->mnc);
|
||||
} else {
|
||||
printf( "\tMNC: \t%02"PRIu16":\n",g_enb_properties.properties[i]->mnc);
|
||||
printf( "\tMNC: \t%02"PRIu16"\n",g_enb_properties.properties[i]->mnc);
|
||||
}
|
||||
printf( "\n--------------------------------------------------------\n");
|
||||
}
|
||||
@@ -114,13 +301,12 @@ static void enb_config_display(void)
|
||||
#define libconfig_int int
|
||||
#endif
|
||||
//------------------------------------------------------------------------------
|
||||
const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP)
|
||||
void enb_config_init(const char const * lib_config_file_name_pP)
|
||||
//------------------------------------------------------------------------------
|
||||
{
|
||||
config_t cfg;
|
||||
config_setting_t *setting = NULL;
|
||||
config_setting_t *subsetting = NULL;
|
||||
config_setting_t *setting_srb1 = NULL;
|
||||
config_setting_t *setting_mme_addresses = NULL;
|
||||
config_setting_t *setting_mme_address = NULL;
|
||||
config_setting_t *setting_enb = NULL;
|
||||
@@ -128,8 +314,6 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP)
|
||||
int enb_properties_index = 0;
|
||||
int num_enbs = 0;
|
||||
int num_mme_address = 0;
|
||||
int num_otg_elements =0;
|
||||
int num_component_carriers =0;
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
int parse_errors = 0;
|
||||
@@ -139,12 +323,6 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP)
|
||||
const char* enb_name = NULL;
|
||||
const char* mcc = 0;
|
||||
const char* mnc = 0;
|
||||
const char* frame_type = NULL;
|
||||
const char* prefix_type = NULL;
|
||||
libconfig_int Nid_cell = 0;
|
||||
|
||||
libconfig_int my_int;
|
||||
|
||||
char* ipv4 = NULL;
|
||||
char* ipv6 = NULL;
|
||||
char* active = NULL;
|
||||
@@ -157,21 +335,20 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP)
|
||||
char* enb_ipv4_address_for_S1_MME = NULL;
|
||||
char *address = NULL;
|
||||
char *cidr = NULL;
|
||||
char *astring = NULL;
|
||||
|
||||
|
||||
AssertFatal (lib_config_file_name_pP != NULL,
|
||||
"Bad parameter lib_config_file_name_pP %s , must reference a valid eNB config file\n",
|
||||
lib_config_file_name_pP);
|
||||
|
||||
memset((char*)active_enb, 0 , EPC_TEST_SCENARIO_MAX_ENB * sizeof(char*));
|
||||
|
||||
config_init(&cfg);
|
||||
|
||||
if (lib_config_file_name_pP != NULL) {
|
||||
/* Read the file. If there is an error, report it and exit. */
|
||||
if (! config_read_file(&cfg, lib_config_file_name_pP)) {
|
||||
config_destroy(&cfg);
|
||||
AssertFatal (0, "Failed to parse eNB configuration file %s!\n", lib_config_file_name_pP);
|
||||
}
|
||||
} else {
|
||||
/* Read the file. If there is an error, report it and exit. */
|
||||
if (! config_read_file(&cfg, lib_config_file_name_pP)) {
|
||||
config_destroy(&cfg);
|
||||
AssertFatal (0, "No eNB configuration file provided!\n");
|
||||
AssertFatal (0, "Failed to parse eNB configuration file %s!\n", lib_config_file_name_pP);
|
||||
}
|
||||
|
||||
// Get list of active eNBs, (only these will be configured)
|
||||
@@ -195,7 +372,7 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP)
|
||||
setting = config_lookup(&cfg, ENB_CONFIG_STRING_ENB_LIST);
|
||||
|
||||
if (setting != NULL) {
|
||||
enb_properties_index = 0;
|
||||
enb_properties_index = g_enb_properties.number;
|
||||
parse_errors = 0;
|
||||
num_enbs = config_setting_length(setting);
|
||||
|
||||
@@ -332,31 +509,19 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP)
|
||||
IPV4_STR_ADDR_TO_INT_NWBO ( address, g_enb_properties.properties[enb_properties_index]->enb_ipv4_address_for_S1_MME, "BAD IP ADDRESS FORMAT FOR eNB S1_MME !\n" );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // if (subsetting != NULL) {
|
||||
enb_properties_index += 1;
|
||||
} // if (strcmp(active_enb[j], enb_name) == 0)
|
||||
} // for (j=0; j < num_enb_properties; j++)
|
||||
} // for (i = 0; i < num_enbs; i++)
|
||||
} // if (setting != NULL) {
|
||||
|
||||
g_enb_properties.number = num_enb_properties;
|
||||
g_enb_properties.number += num_enb_properties;
|
||||
|
||||
AssertError (enb_properties_index == num_enb_properties, parse_errors ++,
|
||||
"Failed to parse eNB configuration file %s, mismatch between %u active eNBs and %u corresponding defined eNBs !\n",
|
||||
lib_config_file_name_pP, num_enb_properties, enb_properties_index);
|
||||
|
||||
AssertFatal (parse_errors == 0,
|
||||
"Failed to parse eNB configuration file %s, found %d error%s !\n",
|
||||
lib_config_file_name_pP, parse_errors, parse_errors > 1 ? "s" : "");
|
||||
enb_config_display();
|
||||
return &g_enb_properties;
|
||||
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
const Enb_properties_array_t *enb_config_get(void)
|
||||
//------------------------------------------------------------------------------
|
||||
{
|
||||
return &g_enb_properties;
|
||||
}
|
||||
|
||||
|
||||
@@ -366,19 +531,41 @@ static void usage (
|
||||
char *argv[])
|
||||
//------------------------------------------------------------------------------
|
||||
{
|
||||
fprintf (stdout, "Please report any bug to: openair4g-devel@lists.eurecom.fr\n\n");
|
||||
fprintf (stdout, "Please report any bug to: %s\n",PACKAGE_BUGREPORT);
|
||||
fprintf (stdout, "Usage: %s [options]\n\n", argv[0]);
|
||||
fprintf (stdout, "Available options:\n");
|
||||
fprintf (stdout, "\t--help, -h Print this help and return\n");
|
||||
fprintf (stdout, "\t--test-dir <path>\n");
|
||||
fprintf (stdout, " Set the test directory where pdml and original enb(s) config files are located\n");
|
||||
fprintf (stdout, " See README in openair3/TEST/EPC_TEST\n");
|
||||
fprintf (stdout, "\t--new-enb-conf-file <file>\n");
|
||||
fprintf (stdout, " Provide an updated eNB config file for generating a copy of the original test\n");
|
||||
fprintf (stdout, " This option is set as many times as there are some eNB in the original test\n");
|
||||
fprintf (stdout, "\n");
|
||||
fprintf (stdout, "Mandatory options:\n");
|
||||
fprintf (stdout, "\t-c | --enb-conf-file <file> Provide the old eNB config file for generating a copy of the original test\n");
|
||||
fprintf (stdout, "\t-d | --test-dir <dir> Directory where a set of files related to a particular test are located\n");
|
||||
fprintf (stdout, "\t-p | --pdml <file> File name (with no path) in 'test-dir' directory of an original scenario that has to be reworked (IP addresses) with new testbed\n");
|
||||
fprintf (stdout, "\n");
|
||||
fprintf (stdout, "Other options:\n");
|
||||
fprintf (stdout, "\t-h | --help Print this help and return\n");
|
||||
fprintf (stdout, "\t-v | --version Print informations about the version of this executable\n");
|
||||
fprintf (stdout, "\n");
|
||||
fprintf (stdout, "Example of generate_scenario use case: \n");
|
||||
fprintf (stdout, "\n");
|
||||
fprintf (stdout, " Generate a generix xml scenario from a captured pcap file: \n");
|
||||
fprintf (stdout, " +---------------------+ \n");
|
||||
fprintf (stdout, " |captured pcap-ng file| \n");
|
||||
fprintf (stdout, " +----------+----------+ \n");
|
||||
fprintf (stdout, " |\n");
|
||||
fprintf (stdout, " mme_test_s1_pcap2pdml --pcap_file <`captured pcap-ng file`>\n");
|
||||
fprintf (stdout, " |\n");
|
||||
fprintf (stdout, " +--------V----------+ +--------------------+\n");
|
||||
fprintf (stdout, " |'pdml-in-orig' file| |'enb-conf-file' file|\n");
|
||||
fprintf (stdout, " +--------+----------+ +--------------------+\n");
|
||||
fprintf (stdout, " | |\n");
|
||||
fprintf (stdout, " +----------------------------+\n");
|
||||
fprintf (stdout, " |\n");
|
||||
fprintf (stdout, " generate_scenario -d <dir> -p <'pdml-in-orig' file> -c <'enb-conf-file' file> \n");
|
||||
fprintf (stdout, " |\n");
|
||||
fprintf (stdout, " +------------V--------------+\n");
|
||||
fprintf (stdout, " +'xml-test-scenario' file |\n");
|
||||
fprintf (stdout, " +---------------------------+\n");
|
||||
fprintf (stdout, "\n");
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
int
|
||||
config_parse_opt_line (
|
||||
@@ -387,65 +574,119 @@ config_parse_opt_line (
|
||||
//------------------------------------------------------------------------------
|
||||
{
|
||||
int option;
|
||||
char *enb_config_file_name = NULL;
|
||||
char *test_dir = NULL;
|
||||
int rv = 0;
|
||||
char *enb_config_file_name = NULL;
|
||||
char *pdml_in_file_name = NULL;
|
||||
char *test_dir_name = NULL;
|
||||
|
||||
enum long_option_e {
|
||||
LONG_OPTION_START = 0x100, /* Start after regular single char options */
|
||||
LONG_OPTION_ENB_CONF_FILE,
|
||||
LONG_OPTION_PDML,
|
||||
LONG_OPTION_TEST_DIR,
|
||||
LONG_OPTION_NEW_ENB_CONF_FILE,
|
||||
LONG_OPTION_HELP,
|
||||
LONG_OPTION_VERSION,
|
||||
};
|
||||
|
||||
static struct option long_options[] = {
|
||||
{"test-dir", required_argument, 0, LONG_OPTION_TEST_DIR},
|
||||
{"new-enb-conf-file", required_argument, 0, LONG_OPTION_NEW_ENB_CONF_FILE},
|
||||
{"help", required_argument, 0, LONG_OPTION_HELP},
|
||||
{"enb-conf-file", required_argument, 0, LONG_OPTION_ENB_CONF_FILE},
|
||||
{"pdml ", required_argument, 0, LONG_OPTION_PDML},
|
||||
{"test-dir", required_argument, 0, LONG_OPTION_TEST_DIR},
|
||||
{"help", no_argument, 0, LONG_OPTION_HELP},
|
||||
{"version", no_argument, 0, LONG_OPTION_VERSION},
|
||||
{NULL, 0, NULL, 0}
|
||||
};
|
||||
|
||||
/*
|
||||
* Parsing command line
|
||||
*/
|
||||
while ((option = getopt_long (argc, argv, "h", long_options, NULL)) != -1) {
|
||||
while ((option = getopt_long (argc, argv, "vhp:n:c:s:d:", long_options, NULL)) != -1) {
|
||||
switch (option) {
|
||||
case LONG_OPTION_TEST_DIR:
|
||||
case LONG_OPTION_ENB_CONF_FILE:
|
||||
case 'c':
|
||||
if (optarg) {
|
||||
test_dir = strdup(optarg);
|
||||
printf("TEST DIRECTORY IS %s\n", test_dir);
|
||||
}
|
||||
break;
|
||||
|
||||
case LONG_OPTION_NEW_ENB_CONF_FILE:
|
||||
if (optarg) {
|
||||
enb_config_file_name = strdup(optarg);
|
||||
enb_config_file_name = optarg;
|
||||
printf("eNB config file name is %s\n", enb_config_file_name);
|
||||
enb_config_init(enb_config_file_name);
|
||||
rv |= GENERATE_SCENARIO;
|
||||
}
|
||||
break;
|
||||
|
||||
case LONG_OPTION_PDML:
|
||||
case 'p':
|
||||
if (optarg) {
|
||||
test_dir = strdup(optarg);
|
||||
printf("TEST DIRECTORY IS %s\n", test_dir);
|
||||
pdml_in_file_name = strdup(optarg);
|
||||
printf("PDML input file name is %s\n", pdml_in_file_name);
|
||||
rv |= GENERATE_SCENARIO;
|
||||
}
|
||||
break;
|
||||
|
||||
case LONG_OPTION_TEST_DIR:
|
||||
case 'd':
|
||||
if (optarg) {
|
||||
test_dir_name = strdup(optarg);
|
||||
if (is_file_exists(test_dir_name, "test dirname") != GS_IS_DIR) {
|
||||
fprintf(stderr, "Please provide a valid test dirname, %s is not a valid directory name\n", test_dir_name);
|
||||
exit(1);
|
||||
}
|
||||
printf("Test dir name is %s\n", test_dir_name);
|
||||
}
|
||||
break;
|
||||
|
||||
case LONG_OPTION_VERSION:
|
||||
case 'v':
|
||||
printf("Version %s\n", PACKAGE_VERSION);
|
||||
exit (0);
|
||||
break;
|
||||
|
||||
case LONG_OPTION_HELP:
|
||||
case 'h': /* Fall through */
|
||||
case 'h':
|
||||
default:
|
||||
usage (argc, argv);
|
||||
exit (0);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
if (NULL == test_dir_name) {
|
||||
fprintf(stderr, "Please provide a valid test dirname\n");
|
||||
exit(1);
|
||||
}
|
||||
g_test_dir = test_dir_name; test_dir_name = NULL;
|
||||
if (chdir(g_test_dir) != 0) {
|
||||
fprintf(stderr, "Error: chdir %s returned %s\n", g_test_dir, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
if (rv & GENERATE_SCENARIO) {
|
||||
if (NULL == enb_config_file_name) {
|
||||
fprintf(stderr, "Error: please provide the original eNB config file name that should be in %s\n", g_test_dir);
|
||||
}
|
||||
if (is_file_exists(enb_config_file_name, "ENB config file") != GS_IS_FILE) {
|
||||
fprintf(stderr, "Error: eNB config file name %s is not found in dir %s\n", enb_config_file_name, g_test_dir);
|
||||
}
|
||||
enb_config_init(enb_config_file_name);
|
||||
//enb_config_display();
|
||||
|
||||
if (NULL == pdml_in_file_name) {
|
||||
fprintf(stderr, "Error: please provide the PDML file name that should be in %s\n", g_test_dir);
|
||||
}
|
||||
if (is_file_exists(pdml_in_file_name, "PDML file") != GS_IS_FILE) {
|
||||
fprintf(stderr, "Error: PDML file name %s is not found in dir %s\n", pdml_in_file_name, g_test_dir);
|
||||
}
|
||||
g_pdml_in_origin = pdml_in_file_name; pdml_in_file_name = NULL;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
int main( int argc, char **argv )
|
||||
//------------------------------------------------------------------------------
|
||||
{
|
||||
int actions = 0;
|
||||
|
||||
memset((char*) &g_enb_properties, 0 , sizeof(g_enb_properties));
|
||||
config_parse_opt_line (argc, argv); //Command-line options
|
||||
|
||||
actions = config_parse_opt_line (argc, argv); //Command-line options
|
||||
if (actions & GENERATE_SCENARIO) {
|
||||
generate_test_scenario(g_test_dir, g_pdml_in_origin);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
/*******************************************************************************
|
||||
OpenAirInterface
|
||||
Copyright(c) 1999 - 2014 Eurecom
|
||||
|
||||
OpenAirInterface is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
|
||||
OpenAirInterface is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenAirInterface.The full GNU General Public License is
|
||||
included in this distribution in the file called "COPYING". If not,
|
||||
see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Contact Information
|
||||
OpenAirInterface Admin: openair_admin@eurecom.fr
|
||||
OpenAirInterface Tech : openair_tech@eurecom.fr
|
||||
OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr
|
||||
|
||||
Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
/*
|
||||
generate_scenario.h
|
||||
-------------------
|
||||
AUTHOR : Lionel GAUTHIER
|
||||
COMPANY : EURECOM
|
||||
EMAIL : Lionel.Gauthier@eurecom.fr
|
||||
*/
|
||||
|
||||
#ifndef GENERATE_SCENARIO_H_
|
||||
#define GENERATE_SCENARIO_H_
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "commonDef.h"
|
||||
#include "platform_types.h"
|
||||
#include "platform_constants.h"
|
||||
#include "PHY/impl_defs_lte.h"
|
||||
#include "s1ap_messages_types.h"
|
||||
#ifdef CMAKER
|
||||
#include "SystemInformationBlockType2.h"
|
||||
#else
|
||||
#include "RRC/LITE/MESSAGES/SystemInformationBlockType2.h"
|
||||
#endif
|
||||
|
||||
#define IPV4_STR_ADDR_TO_INT_NWBO(AdDr_StR,NwBo,MeSsAgE ) do {\
|
||||
struct in_addr inp;\
|
||||
if ( inet_aton(AdDr_StR, &inp ) < 0 ) {\
|
||||
AssertFatal (0, MeSsAgE);\
|
||||
} else {\
|
||||
NwBo = inp.s_addr;\
|
||||
}\
|
||||
} while (0);
|
||||
|
||||
/** @defgroup _enb_app ENB APP
|
||||
* @ingroup _oai2
|
||||
* @{
|
||||
*/
|
||||
|
||||
// Hard to find a defined value for max enb...
|
||||
#define EPC_TEST_SCENARIO_MAX_ENB 4
|
||||
|
||||
|
||||
typedef struct mme_ip_address_s {
|
||||
unsigned ipv4:1;
|
||||
unsigned ipv6:1;
|
||||
unsigned active:1;
|
||||
char *ipv4_address;
|
||||
char *ipv6_address;
|
||||
} mme_ip_address_t;
|
||||
|
||||
typedef struct Enb_properties_s {
|
||||
/* Unique eNB_id to identify the eNB within EPC.
|
||||
* For macro eNB ids this field should be 20 bits long.
|
||||
* For home eNB ids this field should be 28 bits long.
|
||||
*/
|
||||
uint32_t eNB_id;
|
||||
|
||||
/* The type of the cell */
|
||||
enum cell_type_e cell_type;
|
||||
|
||||
/* Optional name for the cell
|
||||
* NOTE: the name can be NULL (i.e no name) and will be cropped to 150
|
||||
* characters.
|
||||
*/
|
||||
char *eNB_name;
|
||||
|
||||
/* Tracking area code */
|
||||
uint16_t tac;
|
||||
|
||||
/* Mobile Country Code
|
||||
* Mobile Network Code
|
||||
*/
|
||||
uint16_t mcc;
|
||||
uint16_t mnc;
|
||||
uint8_t mnc_digit_length;
|
||||
|
||||
/* Nb of MME to connect to */
|
||||
uint8_t nb_mme;
|
||||
/* List of MME to connect to */
|
||||
mme_ip_address_t mme_ip_address[S1AP_MAX_NB_MME_IP_ADDRESS];
|
||||
|
||||
int sctp_in_streams;
|
||||
int sctp_out_streams;
|
||||
|
||||
char *enb_interface_name_for_S1U;
|
||||
in_addr_t enb_ipv4_address_for_S1U;
|
||||
tcp_udp_port_t enb_port_for_S1U;
|
||||
|
||||
char *enb_interface_name_for_S1_MME;
|
||||
in_addr_t enb_ipv4_address_for_S1_MME;
|
||||
|
||||
} Enb_properties_t;
|
||||
|
||||
typedef struct Enb_properties_array_s {
|
||||
int number;
|
||||
Enb_properties_t *properties[EPC_TEST_SCENARIO_MAX_ENB];
|
||||
} Enb_properties_array_t;
|
||||
|
||||
void enb_config_init(const char const * lib_config_file_name_pP);
|
||||
|
||||
#endif /* ENB_CONFIG_H_ */
|
||||
/** @} */
|
||||
@@ -1,92 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
import sys
|
||||
import subprocess
|
||||
import re
|
||||
import socket
|
||||
import datetime
|
||||
from datetime import date
|
||||
import os, errno
|
||||
import argparse
|
||||
import tempfile
|
||||
from lxml import etree
|
||||
from xml.dom.minidom import parse, parseString
|
||||
|
||||
#####################
|
||||
# program arguments
|
||||
#####################
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--pcap_file", "-p", type=str,help="input pcap file to be translated")
|
||||
args = parser.parse_args()
|
||||
|
||||
#####################
|
||||
# get xml document from pcap
|
||||
#####################
|
||||
orig_pcap_file_name = args.pcap_file.strip()
|
||||
orig_pdml_string = subprocess.check_output(["tshark", '-T', 'pdml', '-r', orig_pcap_file_name])
|
||||
|
||||
orig_dom = parseString(orig_pdml_string)
|
||||
|
||||
#####################
|
||||
# filtering unwanted packets
|
||||
#####################
|
||||
#cases = orig_etree.findall(".//proto[@name='sctp']")
|
||||
packets = orig_dom.getElementsByTagName("packet")
|
||||
for packet in packets:
|
||||
found_sctp = False
|
||||
found_s1ap = False
|
||||
protos = packet.getElementsByTagName("proto")
|
||||
for proto in protos:
|
||||
attrs = proto.attributes
|
||||
urlnode = attrs['name']
|
||||
if urlnode.nodeValue == 'sctp':
|
||||
found_sctp = True
|
||||
elif urlnode.nodeValue == 's1ap':
|
||||
found_s1ap = True
|
||||
elif urlnode.nodeValue == 'geninfo':
|
||||
packet.removeChild(proto)
|
||||
elif urlnode.nodeValue == 'eth':
|
||||
packet.removeChild(proto)
|
||||
if found_sctp == False:
|
||||
# hopefully it seems to work (remove iterated packet)
|
||||
packet.parentNode.removeChild(packet)
|
||||
|
||||
#####################
|
||||
# dom to xml string
|
||||
#####################
|
||||
filtered_pdml_string = orig_dom.toxml()
|
||||
cleaned_pdml_string = ""
|
||||
#####################
|
||||
# remove blank lines in xml string
|
||||
#####################
|
||||
lines = filtered_pdml_string.splitlines()
|
||||
for line in lines:
|
||||
if line[:-1]:
|
||||
cleaned_pdml_string += line + '\r\n'
|
||||
#print "'%s'" % cleaned_pdml_string
|
||||
#####################
|
||||
# write pdml string to pdml file
|
||||
#####################
|
||||
out_pdml_file_name = os.path.dirname(orig_pcap_file_name) + os.path.splitext(os.path.basename(orig_pcap_file_name))[0] + '.pdml'
|
||||
out_file = open(out_pdml_file_name, "w")
|
||||
out_file.write(cleaned_pdml_string)
|
||||
out_file.close()
|
||||
|
||||
############################################################
|
||||
# DECEIVING HTML BONUS: DO NOT SEEM TO WORK CORRECTLY IN FIREFOX
|
||||
# DID NOT INVESTIGATE
|
||||
#####################
|
||||
# write xml string to html file
|
||||
#####################
|
||||
xsl_root = etree.fromstring(open('/usr/share/wireshark/pdml2html.xsl').read())
|
||||
transform = etree.XSLT(xsl_root)
|
||||
xml_root = etree.fromstring(cleaned_pdml_string)
|
||||
trans_root = transform(xml_root)
|
||||
filtered_html_string = etree.tostring(trans_root)
|
||||
#####################
|
||||
# write html string to html file
|
||||
#####################
|
||||
out_html_file_name = os.path.dirname(orig_pcap_file_name) + os.path.splitext(os.path.basename(orig_pcap_file_name))[0] + '.html'
|
||||
out_file = open(out_html_file_name, "w")
|
||||
out_file.write(filtered_html_string)
|
||||
out_file.close()
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,508 @@
|
||||
/*******************************************************************************
|
||||
OpenAirInterface
|
||||
Copyright(c) 1999 - 2014 Eurecom
|
||||
|
||||
OpenAirInterface is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
|
||||
OpenAirInterface is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenAirInterface.The full GNU General Public License is
|
||||
included in this distribution in the file called "COPYING". If not,
|
||||
see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Contact Information
|
||||
OpenAirInterface Admin: openair_admin@eurecom.fr
|
||||
OpenAirInterface Tech : openair_tech@eurecom.fr
|
||||
OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr
|
||||
|
||||
Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
/*
|
||||
play_scenario.h
|
||||
-------------------
|
||||
AUTHOR : Lionel GAUTHIER
|
||||
COMPANY : EURECOM
|
||||
EMAIL : Lionel.Gauthier@eurecom.fr
|
||||
*/
|
||||
|
||||
#ifndef PLAY_SCENARIO_H_
|
||||
#define PLAY_SCENARIO_H_
|
||||
# include <time.h>
|
||||
# include <stdint.h>
|
||||
# include <libxml/tree.h>
|
||||
# include <libxml/xpath.h>
|
||||
# include <netinet/in.h>
|
||||
|
||||
#include "S1AP-PDU.h"
|
||||
#include "s1ap_ies_defs.h"
|
||||
#include "play_scenario_s1ap_eNB_defs.h"
|
||||
#include "hashtable.h"
|
||||
#include "asn_compare.h"
|
||||
|
||||
#define ET_XPATH_EXPRESSION_MAX_LENGTH 400
|
||||
|
||||
|
||||
// powers of 2
|
||||
#define ET_BIT_MASK_MATCH_SCTP_STREAM 1
|
||||
#define ET_BIT_MASK_MATCH_SCTP_SSN 2
|
||||
//#define ET_BIT_MASK_MATCH_S1AP_ 2
|
||||
|
||||
#define MAX_ENB 16
|
||||
|
||||
#define ENB_CONFIG_STRING_ACTIVE_ENBS "Active_eNBs"
|
||||
|
||||
#define ENB_CONFIG_STRING_ENB_LIST "eNBs"
|
||||
#define ENB_CONFIG_STRING_ENB_ID "eNB_ID"
|
||||
#define ENB_CONFIG_STRING_CELL_TYPE "cell_type"
|
||||
#define ENB_CONFIG_STRING_ENB_NAME "eNB_name"
|
||||
|
||||
#define ENB_CONFIG_STRING_TRACKING_AREA_CODE "tracking_area_code"
|
||||
#define ENB_CONFIG_STRING_MOBILE_COUNTRY_CODE "mobile_country_code"
|
||||
#define ENB_CONFIG_STRING_MOBILE_NETWORK_CODE "mobile_network_code"
|
||||
|
||||
|
||||
#define ENB_CONFIG_STRING_MME_IP_ADDRESS "mme_ip_address"
|
||||
#define ENB_CONFIG_STRING_MME_IPV4_ADDRESS "ipv4"
|
||||
#define ENB_CONFIG_STRING_MME_IPV6_ADDRESS "ipv6"
|
||||
#define ENB_CONFIG_STRING_MME_IP_ADDRESS_ACTIVE "active"
|
||||
#define ENB_CONFIG_STRING_MME_IP_ADDRESS_PREFERENCE "preference"
|
||||
|
||||
#define ENB_CONFIG_STRING_SCTP_CONFIG "SCTP"
|
||||
#define ENB_CONFIG_STRING_SCTP_INSTREAMS "SCTP_INSTREAMS"
|
||||
#define ENB_CONFIG_STRING_SCTP_OUTSTREAMS "SCTP_OUTSTREAMS"
|
||||
|
||||
#define ENB_CONFIG_STRING_NETWORK_INTERFACES_CONFIG "NETWORK_INTERFACES"
|
||||
#define ENB_CONFIG_STRING_ENB_INTERFACE_NAME_FOR_S1_MME "ENB_INTERFACE_NAME_FOR_S1_MME"
|
||||
#define ENB_CONFIG_STRING_ENB_IPV4_ADDRESS_FOR_S1_MME "ENB_IPV4_ADDRESS_FOR_S1_MME"
|
||||
#define ENB_CONFIG_STRING_ENB_INTERFACE_NAME_FOR_S1U "ENB_INTERFACE_NAME_FOR_S1U"
|
||||
#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"
|
||||
|
||||
|
||||
typedef struct shift_packet_s {
|
||||
unsigned int frame_number; // original frame number
|
||||
int shift_seconds;
|
||||
int shift_microseconds;
|
||||
int single; // shift timing only for this packet (not also following packets)
|
||||
struct shift_packet_s *next;
|
||||
} shift_packet_t;
|
||||
|
||||
|
||||
typedef struct mme_ip_address_s {
|
||||
unsigned ipv4:1;
|
||||
unsigned ipv6:1;
|
||||
unsigned active:1;
|
||||
char *ipv4_address;
|
||||
char *ipv6_address;
|
||||
} mme_ip_address_t;
|
||||
|
||||
#define IPV4_STR_ADDR_TO_INT_NWBO(AdDr_StR,NwBo,MeSsAgE ) do {\
|
||||
struct in_addr inp;\
|
||||
if ( inet_aton(AdDr_StR, &inp ) < 0 ) {\
|
||||
AssertFatal (0, MeSsAgE);\
|
||||
} else {\
|
||||
NwBo = inp.s_addr;\
|
||||
}\
|
||||
} while (0);
|
||||
|
||||
|
||||
typedef struct Enb_properties_s {
|
||||
/* Unique eNB_id to identify the eNB within EPC.
|
||||
* For macro eNB ids this field should be 20 bits long.
|
||||
* For home eNB ids this field should be 28 bits long.
|
||||
*/
|
||||
uint32_t eNB_id;
|
||||
|
||||
/* The type of the cell */
|
||||
enum cell_type_e cell_type;
|
||||
|
||||
/* Optional name for the cell
|
||||
* NOTE: the name can be NULL (i.e no name) and will be cropped to 150
|
||||
* characters.
|
||||
*/
|
||||
char *eNB_name;
|
||||
|
||||
/* Tracking area code */
|
||||
uint16_t tac;
|
||||
|
||||
/* Mobile Country Code
|
||||
* Mobile Network Code
|
||||
*/
|
||||
uint16_t mcc;
|
||||
uint16_t mnc;
|
||||
uint8_t mnc_digit_length;
|
||||
|
||||
|
||||
|
||||
/* Physical parameters */
|
||||
|
||||
int16_t Nid_cell[1+MAX_NUM_CCs];// for testing, change later
|
||||
/* Nb of MME to connect to */
|
||||
uint8_t nb_mme;
|
||||
/* List of MME to connect to */
|
||||
mme_ip_address_t mme_ip_address[S1AP_MAX_NB_MME_IP_ADDRESS];
|
||||
|
||||
int sctp_in_streams;
|
||||
int sctp_out_streams;
|
||||
|
||||
char *enb_interface_name_for_S1U;
|
||||
in_addr_t enb_ipv4_address_for_S1U;
|
||||
tcp_udp_port_t enb_port_for_S1U;
|
||||
|
||||
char *enb_interface_name_for_S1_MME;
|
||||
in_addr_t enb_ipv4_address_for_S1_MME;
|
||||
|
||||
} Enb_properties_t;
|
||||
|
||||
typedef struct Enb_properties_array_s {
|
||||
int number;
|
||||
Enb_properties_t *properties[MAX_ENB];
|
||||
} Enb_properties_array_t;
|
||||
|
||||
# define ET_ENB_REGISTER_RETRY_DELAY 3
|
||||
# define ET_FSM_STATE_WAITING_RX_EVENT_DELAY_SEC 15
|
||||
|
||||
typedef enum {
|
||||
ET_PACKET_STATUS_START = 0,
|
||||
ET_PACKET_STATUS_NONE = ET_PACKET_STATUS_START,
|
||||
ET_PACKET_STATUS_NOT_TAKEN_IN_ACCOUNT,
|
||||
ET_PACKET_STATUS_SCHEDULED_FOR_SENDING,
|
||||
ET_PACKET_STATUS_SENT,
|
||||
ET_PACKET_STATUS_SCHEDULED_FOR_RECEIVING,
|
||||
ET_PACKET_STATUS_RECEIVED,
|
||||
ET_PACKET_STATUS_END
|
||||
} et_packet_status_t;
|
||||
|
||||
typedef enum {
|
||||
ET_FSM_STATE_START = 0,
|
||||
ET_FSM_STATE_NULL = ET_FSM_STATE_START,
|
||||
ET_FSM_STATE_CONNECTING_S1C,
|
||||
ET_FSM_STATE_WAITING_RX_EVENT,
|
||||
ET_FSM_STATE_WAITING_TX_EVENT,
|
||||
ET_FSM_STATE_RUNNING,
|
||||
ET_FSM_STATE_END
|
||||
} et_fsm_state_t;
|
||||
|
||||
enum COMPARE_ERR_CODE_e;
|
||||
|
||||
typedef enum {
|
||||
ET_ERROR_MATCH_START = COMPARE_ERR_CODE_END,
|
||||
ET_ERROR_MATCH_PACKET_SCTP_CHUNK_TYPE = ET_ERROR_MATCH_START,
|
||||
ET_ERROR_MATCH_PACKET_SCTP_PPID,
|
||||
ET_ERROR_MATCH_PACKET_SCTP_ASSOC_ID,
|
||||
ET_ERROR_MATCH_PACKET_SCTP_STREAM_ID,
|
||||
ET_ERROR_MATCH_PACKET_SCTP_SSN,
|
||||
ET_ERROR_MATCH_PACKET_S1AP_PRESENT,
|
||||
ET_ERROR_MATCH_PACKET_S1AP_PROCEDURE_CODE,
|
||||
ET_ERROR_MATCH_PACKET_S1AP_CRITICALITY,
|
||||
ET_ERROR_MATCH_END
|
||||
} et_error_match_code_t;
|
||||
|
||||
|
||||
|
||||
|
||||
typedef enum {
|
||||
ET_PACKET_ACTION_S1C_START = 0,
|
||||
ET_PACKET_ACTION_S1C_NULL = ET_PACKET_ACTION_S1C_START,
|
||||
ET_PACKET_ACTION_S1C_SEND,
|
||||
ET_PACKET_ACTION_S1C_RECEIVE,
|
||||
ET_PACKET_ACTION_S1C_END
|
||||
} et_packet_action_t;
|
||||
|
||||
// from kernel source file 3.19/include/linux/sctp.h
|
||||
typedef enum {
|
||||
SCTP_CID_DATA = 0,
|
||||
SCTP_CID_INIT = 1,
|
||||
SCTP_CID_INIT_ACK = 2,
|
||||
SCTP_CID_SACK = 3,
|
||||
SCTP_CID_HEARTBEAT = 4,
|
||||
SCTP_CID_HEARTBEAT_ACK = 5,
|
||||
SCTP_CID_ABORT = 6,
|
||||
SCTP_CID_SHUTDOWN = 7,
|
||||
SCTP_CID_SHUTDOWN_ACK = 8,
|
||||
SCTP_CID_ERROR = 9,
|
||||
SCTP_CID_COOKIE_ECHO = 10,
|
||||
SCTP_CID_COOKIE_ACK = 11,
|
||||
SCTP_CID_ECN_ECNE = 12,
|
||||
SCTP_CID_ECN_CWR = 13,
|
||||
SCTP_CID_SHUTDOWN_COMPLETE = 14,
|
||||
|
||||
/* AUTH Extension Section 4.1 */
|
||||
SCTP_CID_AUTH = 0x0F,
|
||||
|
||||
/* PR-SCTP Sec 3.2 */
|
||||
SCTP_CID_FWD_TSN = 0xC0,
|
||||
|
||||
/* Use hex, as defined in ADDIP sec. 3.1 */
|
||||
SCTP_CID_ASCONF = 0xC1,
|
||||
SCTP_CID_ASCONF_ACK = 0x80,
|
||||
} sctp_cid_t; /* enum */
|
||||
|
||||
typedef enum {
|
||||
TEST_S1AP_PDU_TYPE_START = 0,
|
||||
TEST_S1AP_PDU_TYPE_UNKNOWN = TEST_S1AP_PDU_TYPE_START,
|
||||
TEST_S1AP_PDU_TYPE_INITIATING,
|
||||
TEST_S1AP_PDU_TYPE_SUCCESSFUL_OUTCOME,
|
||||
TEST_S1AP_PDU_TYPE_UNSUCCESSFUL_OUTCOME,
|
||||
TEST_S1AP_PDU_TYPE_END
|
||||
} et_s1ap_pdu_type_t;
|
||||
|
||||
|
||||
typedef struct et_s1ap_s {
|
||||
//et_s1ap_pdu_type_t pdu_type;
|
||||
S1AP_PDU_t pdu; // decoded ASN1 C type: choice of initiatingMessage, successfulOutcome, unsuccessfulOutcome
|
||||
uint16_t xml_stream_pos_offset;
|
||||
uint16_t binary_stream_pos;
|
||||
uint16_t binary_stream_allocated_size;
|
||||
uint8_t *binary_stream;
|
||||
s1ap_message message; // decoded message: information elements
|
||||
xmlDocPtr doc; // XML representation of the S1AP PDU
|
||||
} et_s1ap_t;
|
||||
|
||||
|
||||
// from kernel source file 3.19/include/linux/sctp.h, Big Endians
|
||||
typedef struct sctp_datahdr_s {
|
||||
uint32_t tsn;
|
||||
uint16_t stream;
|
||||
uint16_t ssn;
|
||||
uint32_t ppid;
|
||||
uint32_t assoc_id; // filled when running scenario
|
||||
et_s1ap_t payload;
|
||||
} sctp_datahdr_t;
|
||||
|
||||
// from kernel source file 3.19/include/linux/sctp.h, Big Endians
|
||||
typedef struct sctp_inithdr {
|
||||
uint32_t init_tag;
|
||||
uint32_t a_rwnd;
|
||||
uint16_t num_outbound_streams;
|
||||
uint16_t num_inbound_streams;
|
||||
uint32_t initial_tsn;
|
||||
uint8_t params[0];
|
||||
} sctp_inithdr_t;
|
||||
|
||||
typedef sctp_inithdr_t sctp_initackhdr_t;
|
||||
|
||||
typedef struct et_sctp_hdr_s {
|
||||
unsigned int src_port;
|
||||
unsigned int dst_port;
|
||||
sctp_cid_t chunk_type;
|
||||
union {
|
||||
sctp_datahdr_t data_hdr;
|
||||
sctp_inithdr_t init_hdr;
|
||||
sctp_initackhdr_t init_ack_hdr;
|
||||
} u;
|
||||
} et_sctp_hdr_t;
|
||||
|
||||
typedef struct et_ip_s {
|
||||
unsigned int address_family; // AF_INET, AF_INET6
|
||||
union {
|
||||
struct in6_addr ipv6;
|
||||
in_addr_t ipv4;
|
||||
}address;
|
||||
char str[INET6_ADDRSTRLEN+1];
|
||||
}et_ip_t;
|
||||
|
||||
typedef struct et_ip_hdr_s {
|
||||
et_ip_t src;
|
||||
et_ip_t dst;
|
||||
} et_ip_hdr_t;
|
||||
|
||||
typedef struct et_packet_s {
|
||||
et_packet_action_t action;
|
||||
struct timeval time_relative_to_first_packet;
|
||||
struct timeval time_relative_to_last_sent_packet;
|
||||
struct timeval time_relative_to_last_received_packet;
|
||||
unsigned int original_frame_number;
|
||||
unsigned int packet_number;
|
||||
instance_t enb_instance;
|
||||
et_ip_hdr_t ip_hdr;
|
||||
et_sctp_hdr_t sctp_hdr;
|
||||
struct et_packet_s *next;
|
||||
|
||||
//scenario running vars
|
||||
et_packet_status_t status;
|
||||
long timer_id; // ITTI timer id for waiting rx packets
|
||||
struct timeval timestamp_packet; // timestamp when rx or tx packet
|
||||
}et_packet_t;
|
||||
|
||||
|
||||
typedef struct sctp_epoll_s {
|
||||
/* Array of events monitored by the task.
|
||||
* By default only one fd is monitored (the one used to received messages
|
||||
* from other tasks).
|
||||
* More events can be suscribed later by the task itself.
|
||||
*/
|
||||
struct epoll_event *events;
|
||||
|
||||
int epoll_nb_events;
|
||||
|
||||
} thread_desc_t;
|
||||
|
||||
typedef struct et_scenario_s {
|
||||
xmlChar *name;
|
||||
et_packet_t *list_packet;
|
||||
//--------------------------
|
||||
// playing scenario
|
||||
//--------------------------
|
||||
Enb_properties_array_t *enb_properties;
|
||||
uint32_t register_enb_pending;
|
||||
uint32_t registered_enb;
|
||||
long enb_register_retry_timer_id;
|
||||
|
||||
|
||||
hash_table_t *hash_mme2association_id;
|
||||
hash_table_t *hash_old_ue_mme_id2ue_mme_id;
|
||||
struct timeval time_last_tx_packet; // Time last sent packet
|
||||
struct timeval time_last_rx_packet; // Time last packet received with all previous scenario RX packet received.
|
||||
et_packet_t *last_rx_packet; // Last packet received with all previous scenario RX packet received.
|
||||
et_packet_t *last_tx_packet; // Last sent packet
|
||||
et_packet_t *next_packet; // Next packet to be handled in the scenario (RX or TX packet)
|
||||
|
||||
int timer_count;
|
||||
} et_scenario_t;
|
||||
|
||||
|
||||
typedef enum {
|
||||
ET_EVENT_START = 0,
|
||||
ET_EVENT_INIT = ET_EVENT_START,
|
||||
ET_EVENT_S1C_CONNECTED,
|
||||
ET_EVENT_RX_SCTP_EVENT,
|
||||
ET_EVENT_RX_S1AP,
|
||||
ET_EVENT_RX_PACKET_TIME_OUT,
|
||||
ET_EVENT_TX_TIMED_PACKET,
|
||||
ET_EVENT_TICK,
|
||||
ET_EVENT_END
|
||||
} et_event_code_t;
|
||||
|
||||
typedef struct et_event_init_s {
|
||||
et_scenario_t *scenario;
|
||||
} et_event_init_t;
|
||||
|
||||
typedef struct et_event_s1ap_data_ind_s {
|
||||
sctp_datahdr_t sctp_datahdr;
|
||||
} et_event_s1ap_data_ind_t;
|
||||
|
||||
typedef struct et_event_s1ap_data_req_s {
|
||||
|
||||
} et_event_s1ap_data_req_t;
|
||||
|
||||
typedef struct et_event_s {
|
||||
et_event_code_t code;
|
||||
union {
|
||||
et_event_init_t init;
|
||||
et_event_s1ap_data_ind_t s1ap_data_ind;
|
||||
et_packet_t *tx_timed_packet;
|
||||
et_packet_t *rx_packet_time_out;
|
||||
} u;
|
||||
} et_event_t;
|
||||
|
||||
inline void et_free_pointer(void *p) {if (NULL != p) {free(p); p=NULL;}};
|
||||
|
||||
//-------------------------
|
||||
void et_free_packet(et_packet_t* packet);
|
||||
void et_free_scenario(et_scenario_t* scenario);
|
||||
//-------------------------
|
||||
void et_display_packet_s1ap_data(const et_s1ap_t * const s1ap);
|
||||
void et_display_packet_sctp_init(const sctp_inithdr_t * const sctp);
|
||||
void et_display_packet_sctp_initack(const sctp_initackhdr_t * const sctp);
|
||||
void et_display_packet_sctp_data(const sctp_datahdr_t * const sctp);
|
||||
void et_display_packet_sctp(const et_sctp_hdr_t * const sctp);
|
||||
void et_display_packet_ip(const et_ip_hdr_t * const ip);
|
||||
void et_display_packet(const et_packet_t * const packet);
|
||||
void et_display_scenario(const et_scenario_t * const scenario);
|
||||
//-------------------------
|
||||
int et_s1ap_decode_initiating_message(s1ap_message *message, S1ap_InitiatingMessage_t *initiating_p);
|
||||
int et_s1ap_decode_successful_outcome(s1ap_message *message, S1ap_SuccessfulOutcome_t *successfullOutcome_p);
|
||||
int et_s1ap_decode_unsuccessful_outcome(s1ap_message *message, S1ap_UnsuccessfulOutcome_t *unSuccessfullOutcome_p);
|
||||
int et_s1ap_decode_pdu(S1AP_PDU_t * const pdu, s1ap_message * const message, const uint8_t * const buffer, const uint32_t length);
|
||||
void et_decode_s1ap(et_s1ap_t * const s1ap);
|
||||
//-------------------------
|
||||
int et_s1ap_eNB_compare_assoc_id( struct s1ap_eNB_mme_data_s *p1, struct s1ap_eNB_mme_data_s *p2);
|
||||
uint32_t et_s1ap_generate_eNB_id(void);
|
||||
uint16_t et_s1ap_eNB_fetch_add_global_cnx_id(void);
|
||||
void et_s1ap_eNB_prepare_internal_data(void);
|
||||
void et_s1ap_eNB_insert_new_instance(s1ap_eNB_instance_t *new_instance_p);
|
||||
struct s1ap_eNB_mme_data_s *et_s1ap_eNB_get_MME(s1ap_eNB_instance_t *instance_p,int32_t assoc_id, uint16_t cnx_id);
|
||||
s1ap_eNB_instance_t *et_s1ap_eNB_get_instance(instance_t instance);
|
||||
void et_s1ap_eNB_itti_send_sctp_data_req(instance_t instance, int32_t assoc_id, uint8_t *buffer,uint32_t buffer_length, uint16_t stream);
|
||||
int et_handle_s1ap_mismatch_mme_ue_s1ap_id(et_packet_t * const spacket, et_packet_t * const rx_packet);
|
||||
asn_comp_rval_t* et_s1ap_is_matching(et_s1ap_t * const s1ap1, et_s1ap_t * const s1ap2, const uint32_t constraints);
|
||||
et_packet_t* et_build_packet_from_s1ap_data_ind(et_event_s1ap_data_ind_t * const s1ap_data_ind);
|
||||
int et_scenario_set_packet_received(et_packet_t * const packet);
|
||||
int et_s1ap_process_rx_packet(et_event_s1ap_data_ind_t * const sctp_data_ind);
|
||||
void et_s1ap_eNB_handle_sctp_data_ind(sctp_data_ind_t * const sctp_data_ind);
|
||||
void et_s1ap_eNB_register_mme(s1ap_eNB_instance_t *instance_p,
|
||||
net_ip_address_t *mme_ip_address,
|
||||
net_ip_address_t *local_ip_addr,
|
||||
uint16_t in_streams,
|
||||
uint16_t out_streams);
|
||||
void et_s1ap_handle_s1_setup_message(s1ap_eNB_mme_data_t *mme_desc_p, int sctp_shutdown);
|
||||
void et_s1ap_eNB_handle_register_eNB(instance_t instance, s1ap_register_enb_req_t *s1ap_register_eNB);
|
||||
void et_s1ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_association_resp_t *sctp_new_association_resp);
|
||||
void * et_s1ap_eNB_task(void *arg);
|
||||
//-------------------------
|
||||
int et_generate_xml_scenario(
|
||||
const char const * xml_in_dir_name,
|
||||
const char const * xml_in_scenario_filename,
|
||||
const char const * enb_config_filename,
|
||||
char const * tsml_out_scenario_filename);
|
||||
//-------------------------
|
||||
void timeval_add (struct timeval * const result, const struct timeval * const a, const struct timeval * const b);
|
||||
int timeval_subtract (struct timeval * const result, struct timeval * const a, struct timeval * const b);
|
||||
void et_scenario_wait_rx_packet(et_packet_t * const packet);
|
||||
void et_scenario_schedule_tx_packet(et_packet_t * packet);
|
||||
et_fsm_state_t et_scenario_fsm_notify_event_state_running(et_event_t event);
|
||||
et_fsm_state_t et_scenario_fsm_notify_event_state_waiting_tx(et_event_t event);
|
||||
et_fsm_state_t et_scenario_fsm_notify_event_state_waiting_rx(et_event_t event);
|
||||
et_fsm_state_t et_scenario_fsm_notify_event_state_connecting_s1c(et_event_t event);
|
||||
et_fsm_state_t et_scenario_fsm_notify_event_state_null(et_event_t event);
|
||||
et_fsm_state_t et_scenario_fsm_notify_event(et_event_t event);
|
||||
//-------------------------
|
||||
void et_parse_s1ap(xmlDocPtr doc, const xmlNode const *s1ap_node, et_s1ap_t * const s1ap);
|
||||
void et_parse_sctp_data_chunk(xmlDocPtr doc, const xmlNode const *sctp_node, sctp_datahdr_t * const sctp_hdr);
|
||||
void et_parse_sctp_init_chunk(xmlDocPtr doc, const xmlNode const *sctp_node, sctp_inithdr_t * const sctp_hdr);
|
||||
void et_parse_sctp_init_ack_chunk(xmlDocPtr doc, const xmlNode const *sctp_node, sctp_initackhdr_t * const sctp_hdr);
|
||||
void et_parse_sctp(xmlDocPtr doc, const xmlNode const *sctp_node, et_sctp_hdr_t * const sctp_hdr);
|
||||
et_packet_t* et_parse_xml_packet(xmlDocPtr doc, xmlNodePtr node);
|
||||
et_scenario_t* et_generate_scenario(const char * const et_scenario_filename);
|
||||
//-------------------------
|
||||
asn_comp_rval_t * et_s1ap_ies_is_matching(const S1AP_PDU_PR present, s1ap_message * const m1, s1ap_message * const m2, const uint32_t constraints);
|
||||
void update_xpath_node_mme_ue_s1ap_id(et_s1ap_t * const s1ap, xmlNode *node, const S1ap_MME_UE_S1AP_ID_t new_id);
|
||||
void update_xpath_nodes_mme_ue_s1ap_id(et_s1ap_t * const s1ap_payload, xmlNodeSetPtr nodes, const S1ap_MME_UE_S1AP_ID_t new_id);
|
||||
int et_s1ap_update_mme_ue_s1ap_id(et_packet_t * const packet, const S1ap_MME_UE_S1AP_ID_t old_id, const S1ap_MME_UE_S1AP_ID_t new_id);
|
||||
//-------------------------
|
||||
asn_comp_rval_t * et_sctp_data_is_matching(sctp_datahdr_t * const sctp1, sctp_datahdr_t * const sctp2, const uint32_t constraints);
|
||||
asn_comp_rval_t * et_sctp_is_matching(et_sctp_hdr_t * const sctp1, et_sctp_hdr_t * const sctp2, const uint32_t constraints);
|
||||
//------------------------------------------------------------------------------
|
||||
void et_print_hex_octets(const unsigned char * const byte_stream, const unsigned long int num);
|
||||
int et_is_file_exists ( const char const * file_nameP, const char const *file_roleP);
|
||||
int et_strip_extension( char *in_filename);
|
||||
void et_get_shift_arg( char * line_argument, shift_packet_t * const shift);
|
||||
int et_split_path ( char * pathP, char *** resP);
|
||||
void et_display_node ( xmlNodePtr node, unsigned int indent);
|
||||
void et_display_tree ( xmlNodePtr node, unsigned int indent);
|
||||
char * et_ip2ip_str(const et_ip_t * const ip);
|
||||
int et_compare_et_ip_to_net_ip_address(const et_ip_t * const ip, const net_ip_address_t * const net_ip);
|
||||
int et_hex2data(unsigned char * const data, const unsigned char * const hexstring, const unsigned int len);
|
||||
sctp_cid_t et_chunk_type_str2cid(const xmlChar * const chunk_type_str);
|
||||
const char * const et_chunk_type_cid2str(const sctp_cid_t chunk_type);
|
||||
const char * const et_error_match2str(const int err);
|
||||
et_packet_action_t et_action_str2et_action_t(const xmlChar * const action);
|
||||
void et_ip_str2et_ip(const xmlChar * const ip_str, et_ip_t * const ip);
|
||||
void et_enb_config_init(const char const * lib_config_file_name_pP);
|
||||
const Enb_properties_array_t *et_enb_config_get(void);
|
||||
void et_eNB_app_register(const Enb_properties_array_t *enb_properties);
|
||||
void *et_eNB_app_task(void *args_p);
|
||||
int et_play_scenario(et_scenario_t* const scenario, const struct shift_packet_s *shifts);
|
||||
|
||||
#endif /* PLAY_SCENARIO_H_ */
|
||||
@@ -0,0 +1,214 @@
|
||||
/*******************************************************************************
|
||||
OpenAirInterface
|
||||
Copyright(c) 1999 - 2014 Eurecom
|
||||
|
||||
OpenAirInterface is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
|
||||
OpenAirInterface is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenAirInterface.The full GNU General Public License is
|
||||
included in this distribution in the file called "COPYING". If not,
|
||||
see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Contact Information
|
||||
OpenAirInterface Admin: openair_admin@eurecom.fr
|
||||
OpenAirInterface Tech : openair_tech@eurecom.fr
|
||||
OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr
|
||||
|
||||
Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
/*
|
||||
play_scenario_decode.c
|
||||
-------------------
|
||||
AUTHOR : Lionel GAUTHIER
|
||||
COMPANY : EURECOM
|
||||
EMAIL : Lionel.Gauthier@eurecom.fr
|
||||
*/
|
||||
|
||||
#include "intertask_interface.h"
|
||||
#include "platform_types.h"
|
||||
#include "s1ap_ies_defs.h"
|
||||
#include "s1ap_eNB_decoder.h"
|
||||
#include "assertions.h"
|
||||
#include "play_scenario.h"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
int et_s1ap_decode_initiating_message(s1ap_message *message, S1ap_InitiatingMessage_t *initiating_p)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
DevAssert(initiating_p != NULL);
|
||||
|
||||
message->procedureCode = initiating_p->procedureCode;
|
||||
message->criticality = initiating_p->criticality;
|
||||
|
||||
switch(initiating_p->procedureCode) {
|
||||
case S1ap_ProcedureCode_id_downlinkNASTransport:
|
||||
ret = s1ap_decode_s1ap_downlinknastransporties(&message->msg.s1ap_DownlinkNASTransportIEs,&initiating_p->value);
|
||||
break;
|
||||
|
||||
case S1ap_ProcedureCode_id_InitialContextSetup:
|
||||
ret = s1ap_decode_s1ap_initialcontextsetuprequesties(&message->msg.s1ap_InitialContextSetupRequestIEs, &initiating_p->value);
|
||||
break;
|
||||
|
||||
case S1ap_ProcedureCode_id_UEContextRelease:
|
||||
ret = s1ap_decode_s1ap_uecontextreleasecommandies(&message->msg.s1ap_UEContextReleaseCommandIEs, &initiating_p->value);
|
||||
break;
|
||||
|
||||
case S1ap_ProcedureCode_id_Paging:
|
||||
ret = s1ap_decode_s1ap_pagingies(&message->msg.s1ap_PagingIEs, &initiating_p->value);
|
||||
break;
|
||||
|
||||
case S1ap_ProcedureCode_id_uplinkNASTransport:
|
||||
ret = s1ap_decode_s1ap_uplinknastransporties (&message->msg.s1ap_UplinkNASTransportIEs, &initiating_p->value);
|
||||
break;
|
||||
|
||||
case S1ap_ProcedureCode_id_S1Setup:
|
||||
ret = s1ap_decode_s1ap_s1setuprequesties (&message->msg.s1ap_S1SetupRequestIEs, &initiating_p->value);
|
||||
break;
|
||||
|
||||
case S1ap_ProcedureCode_id_initialUEMessage:
|
||||
ret = s1ap_decode_s1ap_initialuemessageies (&message->msg.s1ap_InitialUEMessageIEs, &initiating_p->value);
|
||||
break;
|
||||
|
||||
case S1ap_ProcedureCode_id_UEContextReleaseRequest:
|
||||
ret = s1ap_decode_s1ap_uecontextreleaserequesties (&message->msg.s1ap_UEContextReleaseRequestIEs, &initiating_p->value);
|
||||
break;
|
||||
|
||||
case S1ap_ProcedureCode_id_UECapabilityInfoIndication:
|
||||
ret = s1ap_decode_s1ap_uecapabilityinfoindicationies (&message->msg.s1ap_UECapabilityInfoIndicationIEs, &initiating_p->value);
|
||||
break;
|
||||
|
||||
case S1ap_ProcedureCode_id_NASNonDeliveryIndication:
|
||||
ret = s1ap_decode_s1ap_nasnondeliveryindication_ies (&message->msg.s1ap_NASNonDeliveryIndication_IEs, &initiating_p->value);
|
||||
break;
|
||||
|
||||
default:
|
||||
AssertFatal( 0 , "Unknown procedure ID (%d) for initiating message\n",
|
||||
(int)initiating_p->procedureCode);
|
||||
return -1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
int et_s1ap_decode_successful_outcome(s1ap_message *message, S1ap_SuccessfulOutcome_t *successfullOutcome_p)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
DevAssert(successfullOutcome_p != NULL);
|
||||
|
||||
message->procedureCode = successfullOutcome_p->procedureCode;
|
||||
message->criticality = successfullOutcome_p->criticality;
|
||||
|
||||
switch(successfullOutcome_p->procedureCode) {
|
||||
case S1ap_ProcedureCode_id_S1Setup:
|
||||
ret = s1ap_decode_s1ap_s1setupresponseies(
|
||||
&message->msg.s1ap_S1SetupResponseIEs, &successfullOutcome_p->value);
|
||||
break;
|
||||
|
||||
case S1ap_ProcedureCode_id_InitialContextSetup:
|
||||
ret = s1ap_decode_s1ap_initialcontextsetupresponseies (&message->msg.s1ap_InitialContextSetupResponseIEs, &successfullOutcome_p->value);
|
||||
break;
|
||||
|
||||
case S1ap_ProcedureCode_id_UEContextRelease:
|
||||
ret = s1ap_decode_s1ap_uecontextreleasecompleteies (&message->msg.s1ap_UEContextReleaseCompleteIEs, &successfullOutcome_p->value);
|
||||
break;
|
||||
|
||||
default:
|
||||
AssertFatal(0, "Unknown procedure ID (%d) for successfull outcome message\n",
|
||||
(int)successfullOutcome_p->procedureCode);
|
||||
return -1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
int et_s1ap_decode_unsuccessful_outcome(s1ap_message *message, S1ap_UnsuccessfulOutcome_t *unSuccessfullOutcome_p)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
DevAssert(unSuccessfullOutcome_p != NULL);
|
||||
|
||||
message->procedureCode = unSuccessfullOutcome_p->procedureCode;
|
||||
message->criticality = unSuccessfullOutcome_p->criticality;
|
||||
|
||||
switch(unSuccessfullOutcome_p->procedureCode) {
|
||||
case S1ap_ProcedureCode_id_S1Setup:
|
||||
ret = s1ap_decode_s1ap_s1setupfailureies(&message->msg.s1ap_S1SetupFailureIEs, &unSuccessfullOutcome_p->value);
|
||||
break;
|
||||
|
||||
case S1ap_ProcedureCode_id_InitialContextSetup:
|
||||
ret = s1ap_decode_s1ap_initialcontextsetupfailureies (&message->msg.s1ap_InitialContextSetupFailureIEs, &unSuccessfullOutcome_p->value);
|
||||
break;
|
||||
|
||||
default:
|
||||
AssertFatal(0,"Unknown procedure ID (%d) for unsuccessfull outcome message\n",
|
||||
(int)unSuccessfullOutcome_p->procedureCode);
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
int et_s1ap_decode_pdu(S1AP_PDU_t * const pdu, s1ap_message * const message, const uint8_t * const buffer, const uint32_t length)
|
||||
{
|
||||
asn_dec_rval_t dec_ret;
|
||||
|
||||
DevAssert(buffer != NULL);
|
||||
|
||||
memset((void *)pdu, 0, sizeof(S1AP_PDU_t));
|
||||
|
||||
dec_ret = aper_decode(NULL,
|
||||
&asn_DEF_S1AP_PDU,
|
||||
(void **)&pdu,
|
||||
buffer,
|
||||
length,
|
||||
0,
|
||||
0);
|
||||
|
||||
if (dec_ret.code != RC_OK) {
|
||||
S1AP_ERROR("Failed to decode pdu\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
message->direction = pdu->present;
|
||||
|
||||
switch(pdu->present) {
|
||||
case S1AP_PDU_PR_initiatingMessage:
|
||||
return et_s1ap_decode_initiating_message(message,
|
||||
&pdu->choice.initiatingMessage);
|
||||
|
||||
case S1AP_PDU_PR_successfulOutcome:
|
||||
return et_s1ap_decode_successful_outcome(message,
|
||||
&pdu->choice.successfulOutcome);
|
||||
|
||||
case S1AP_PDU_PR_unsuccessfulOutcome:
|
||||
return et_s1ap_decode_unsuccessful_outcome(message,
|
||||
&pdu->choice.unsuccessfulOutcome);
|
||||
|
||||
default:
|
||||
AssertFatal(0, "Unknown presence (%d) or not implemented\n", (int)pdu->present);
|
||||
break;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void et_decode_s1ap(et_s1ap_t * const s1ap)
|
||||
{
|
||||
if (NULL != s1ap) {
|
||||
if (et_s1ap_decode_pdu(&s1ap->pdu, &s1ap->message, s1ap->binary_stream, s1ap->binary_stream_allocated_size) < 0) {
|
||||
AssertFatal (0, "ERROR %s() Cannot decode S1AP message!\n", __FUNCTION__);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,314 @@
|
||||
/*******************************************************************************
|
||||
OpenAirInterface
|
||||
Copyright(c) 1999 - 2014 Eurecom
|
||||
|
||||
OpenAirInterface is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
|
||||
OpenAirInterface is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenAirInterface.The full GNU General Public License is
|
||||
included in this distribution in the file called "COPYING". If not,
|
||||
see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Contact Information
|
||||
OpenAirInterface Admin: openair_admin@eurecom.fr
|
||||
OpenAirInterface Tech : openair_tech@eurecom.fr
|
||||
OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr
|
||||
|
||||
Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
/*
|
||||
play_scenario_display.c
|
||||
-------------------
|
||||
AUTHOR : Lionel GAUTHIER
|
||||
COMPANY : EURECOM
|
||||
EMAIL : Lionel.Gauthier@eurecom.fr
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "intertask_interface.h"
|
||||
#include "platform_types.h"
|
||||
#include "assertions.h"
|
||||
#include "s1ap_ies_defs.h"
|
||||
#include "s1ap_eNB_decoder.h"
|
||||
#include "play_scenario.h"
|
||||
//-----------------------------------------------------------------------------
|
||||
void et_print_hex_octets(const unsigned char * const byte_stream, const unsigned long int num)
|
||||
{
|
||||
unsigned long octet_index = 0;
|
||||
|
||||
if (byte_stream == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
fprintf(stdout, "+-----+-------------------------------------------------+\n");
|
||||
fprintf(stdout, "| | 0 1 2 3 4 5 6 7 8 9 a b c d e f |\n");
|
||||
fprintf(stdout, "+-----+-------------------------------------------------+\n");
|
||||
|
||||
for (octet_index = 0; octet_index < num; octet_index++) {
|
||||
if ((octet_index % 16) == 0) {
|
||||
if (octet_index != 0) {
|
||||
fprintf(stdout, " |\n");
|
||||
}
|
||||
|
||||
fprintf(stdout, " %04ld |", octet_index);
|
||||
}
|
||||
|
||||
/*
|
||||
* Print every single octet in hexadecimal form
|
||||
*/
|
||||
fprintf(stdout, " %02x", byte_stream[octet_index]);
|
||||
/*
|
||||
* Align newline and pipes according to the octets in groups of 2
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
* Append enough spaces and put final pipe
|
||||
*/
|
||||
unsigned char index;
|
||||
|
||||
for (index = octet_index; index < 16; ++index) {
|
||||
fprintf(stdout, " ");
|
||||
}
|
||||
|
||||
fprintf(stdout, " |\n");
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void et_display_node(xmlNodePtr node, unsigned int indent)
|
||||
{
|
||||
int i = 0;
|
||||
if (node->type == XML_ELEMENT_NODE) {
|
||||
xmlChar *path = xmlGetNodePath(node);
|
||||
for (i=0; i<indent; i++) {
|
||||
printf(" ");
|
||||
}
|
||||
if (node->children != NULL && node->children->type == XML_TEXT_NODE) {
|
||||
xmlChar *content = xmlNodeGetContent(node);
|
||||
printf("%s -> %s\n", path, content);
|
||||
xmlFree(content);
|
||||
} else {
|
||||
printf("%s\n", path);
|
||||
}
|
||||
xmlFree(path);
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void et_display_tree(xmlNodePtr node, unsigned int indent)
|
||||
{
|
||||
xmlNode *cur_node = NULL;
|
||||
|
||||
for (cur_node = node; cur_node; cur_node = cur_node->next) {
|
||||
if (cur_node->type == XML_ELEMENT_NODE) {
|
||||
et_display_node(cur_node, indent);
|
||||
}
|
||||
et_display_tree(cur_node->children, indent++);
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void et_display_packet_s1ap_data(const et_s1ap_t * const s1ap)
|
||||
{
|
||||
char *message_string = NULL;
|
||||
|
||||
if (s1ap) {
|
||||
message_string = calloc(20000, sizeof(char));
|
||||
AssertFatal (NULL != message_string, "ERROR malloc()failed!\n");
|
||||
s1ap_string_total_size = 0;
|
||||
switch(s1ap->pdu.present) {
|
||||
case S1AP_PDU_PR_initiatingMessage:
|
||||
switch(s1ap->pdu.choice.initiatingMessage.procedureCode) {
|
||||
case S1ap_ProcedureCode_id_downlinkNASTransport: s1ap_xer_print_s1ap_downlinknastransport(s1ap_xer__print2sp, message_string, (s1ap_message *)&s1ap->message);break;
|
||||
case S1ap_ProcedureCode_id_InitialContextSetup: s1ap_xer_print_s1ap_initialcontextsetuprequest(s1ap_xer__print2sp, message_string, (s1ap_message *)&s1ap->message);break;
|
||||
case S1ap_ProcedureCode_id_UEContextRelease: s1ap_xer_print_s1ap_uecontextreleasecommand(s1ap_xer__print2sp, message_string, (s1ap_message *)&s1ap->message);break;
|
||||
case S1ap_ProcedureCode_id_Paging: s1ap_xer_print_s1ap_paging(s1ap_xer__print2sp, message_string, (s1ap_message *)&s1ap->message);break;
|
||||
case S1ap_ProcedureCode_id_uplinkNASTransport: s1ap_xer_print_s1ap_uplinknastransport(s1ap_xer__print2sp, message_string, (s1ap_message *)&s1ap->message);break;
|
||||
case S1ap_ProcedureCode_id_S1Setup: s1ap_xer_print_s1ap_s1setuprequest(s1ap_xer__print2sp, message_string, (s1ap_message *)&s1ap->message);break;
|
||||
case S1ap_ProcedureCode_id_initialUEMessage: s1ap_xer_print_s1ap_initialuemessage(s1ap_xer__print2sp, message_string, (s1ap_message *)&s1ap->message);break;
|
||||
case S1ap_ProcedureCode_id_UEContextReleaseRequest: s1ap_xer_print_s1ap_uecontextreleaserequest(s1ap_xer__print2sp, message_string, (s1ap_message *)&s1ap->message);break;
|
||||
case S1ap_ProcedureCode_id_UECapabilityInfoIndication:s1ap_xer_print_s1ap_uecapabilityinfoindication(s1ap_xer__print2sp, message_string, (s1ap_message *)&s1ap->message);break;
|
||||
case S1ap_ProcedureCode_id_NASNonDeliveryIndication: s1ap_xer_print_s1ap_nasnondeliveryindication_(s1ap_xer__print2sp, message_string, (s1ap_message *)&s1ap->message);break;
|
||||
default:
|
||||
AssertFatal( 0 , "Unknown procedure ID (%d) for initiating message\n",
|
||||
(int)s1ap->pdu.choice.initiatingMessage.procedureCode);
|
||||
}
|
||||
break;
|
||||
case S1AP_PDU_PR_successfulOutcome:
|
||||
switch(s1ap->pdu.choice.successfulOutcome.procedureCode) {
|
||||
case S1ap_ProcedureCode_id_S1Setup: s1ap_xer_print_s1ap_s1setupresponse(s1ap_xer__print2sp, message_string, (s1ap_message *)&s1ap->message);break;
|
||||
case S1ap_ProcedureCode_id_InitialContextSetup: s1ap_xer_print_s1ap_initialcontextsetupresponse(s1ap_xer__print2sp, message_string, (s1ap_message *)&s1ap->message);break;
|
||||
case S1ap_ProcedureCode_id_UEContextRelease: s1ap_xer_print_s1ap_uecontextreleasecomplete(s1ap_xer__print2sp, message_string, (s1ap_message *)&s1ap->message);break;
|
||||
default:
|
||||
AssertFatal(0, "Unknown procedure ID (%d) for successfull outcome message\n",
|
||||
(int)s1ap->pdu.choice.successfulOutcome.procedureCode);
|
||||
}
|
||||
break;
|
||||
|
||||
case S1AP_PDU_PR_unsuccessfulOutcome:
|
||||
switch(s1ap->pdu.choice.unsuccessfulOutcome.procedureCode) {
|
||||
case S1ap_ProcedureCode_id_S1Setup: s1ap_xer_print_s1ap_s1setupfailure(s1ap_xer__print2sp, message_string, (s1ap_message *)&s1ap->message);break;
|
||||
case S1ap_ProcedureCode_id_InitialContextSetup: s1ap_xer_print_s1ap_initialcontextsetupfailure(s1ap_xer__print2sp, message_string, (s1ap_message *)&s1ap->message);break;
|
||||
default:
|
||||
et_free_pointer(message_string);
|
||||
AssertFatal(0,"Unknown procedure ID (%d) for unsuccessfull outcome message\n",
|
||||
(int)s1ap->pdu.choice.unsuccessfulOutcome.procedureCode);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
AssertFatal(0, "Unknown presence (%d) or not implemented\n", (int)s1ap->pdu.present);
|
||||
break;
|
||||
}
|
||||
fprintf(stdout, "\t\tSCTP.data XML dump:\n%s\n", message_string);
|
||||
et_free_pointer(message_string);
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void et_display_packet_sctp_init(const sctp_inithdr_t * const sctp)
|
||||
{
|
||||
|
||||
if (sctp) {
|
||||
fprintf(stdout, "\t\tSCTP.init.init_tag : %u\n", sctp->init_tag);
|
||||
fprintf(stdout, "\t\tSCTP.init.a_rwnd : %u\n", sctp->a_rwnd);
|
||||
fprintf(stdout, "\t\tSCTP.init.num_inbound_streams : %u\n", sctp->num_inbound_streams);
|
||||
fprintf(stdout, "\t\tSCTP.init.num_outbound_streams : %u\n", sctp->num_outbound_streams);
|
||||
fprintf(stdout, "\t\tSCTP.init.initial_tsn : %u\n", sctp->initial_tsn);
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void et_display_packet_sctp_initack(const sctp_initackhdr_t * const sctp)
|
||||
{
|
||||
|
||||
if (sctp) {
|
||||
fprintf(stdout, "\t\tSCTP.initack.init_tag : %u\n", sctp->init_tag);
|
||||
fprintf(stdout, "\t\tSCTP.initack.a_rwnd : %u\n", sctp->a_rwnd);
|
||||
fprintf(stdout, "\t\tSCTP.initack.num_inbound_streams : %u\n", sctp->num_inbound_streams);
|
||||
fprintf(stdout, "\t\tSCTP.initack.num_outbound_streams : %u\n", sctp->num_outbound_streams);
|
||||
fprintf(stdout, "\t\tSCTP.initack.initial_tsn : %u\n", sctp->initial_tsn);
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void et_display_packet_sctp_data(const sctp_datahdr_t * const sctp)
|
||||
{
|
||||
if (sctp) {
|
||||
fprintf(stdout, "\t\tSCTP.data.tsn : %u\n", sctp->tsn);
|
||||
fprintf(stdout, "\t\tSCTP.data.stream : %u\n", sctp->stream);
|
||||
fprintf(stdout, "\t\tSCTP.data.ssn : %u\n", sctp->ssn);
|
||||
fprintf(stdout, "\t\tSCTP.data.ppid : %u\n", sctp->ppid);
|
||||
if (sctp->ppid == 18) {
|
||||
et_display_packet_s1ap_data(&sctp->payload);
|
||||
}
|
||||
fprintf(stdout, "\t\tSCTP.data.binary_stream_allocated_size : %u\n", sctp->payload.binary_stream_allocated_size);
|
||||
if (NULL != sctp->payload.binary_stream) {
|
||||
fprintf(stdout, "\t\tSCTP.data.binary_stream :\n");
|
||||
et_print_hex_octets(sctp->payload.binary_stream, sctp->payload.binary_stream_allocated_size);
|
||||
} else {
|
||||
fprintf(stdout, "\t\tSCTP.data.binary_stream : NULL\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void et_display_packet_sctp(const et_sctp_hdr_t * const sctp)
|
||||
{
|
||||
if (sctp) {
|
||||
fprintf(stdout, "\t\tSCTP.src_port : %u\n", sctp->src_port);
|
||||
fprintf(stdout, "\t\tSCTP.dst_port : %u\n", sctp->dst_port);
|
||||
fprintf(stdout, "\t\tSCTP.chunk_type : %s\n", et_chunk_type_cid2str(sctp->chunk_type));
|
||||
switch (sctp->chunk_type) {
|
||||
case SCTP_CID_DATA:
|
||||
et_display_packet_sctp_data(&sctp->u.data_hdr);
|
||||
break;
|
||||
case SCTP_CID_INIT:
|
||||
et_display_packet_sctp_initack(&sctp->u.init_hdr);
|
||||
break;
|
||||
case SCTP_CID_INIT_ACK:
|
||||
et_display_packet_sctp_initack(&sctp->u.init_ack_hdr);
|
||||
break;
|
||||
default:
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void et_display_packet_ip(const et_ip_hdr_t * const ip)
|
||||
{
|
||||
if (ip) {
|
||||
fprintf(stdout, "\t\tSource address : %s\n", et_ip2ip_str(&ip->src));
|
||||
fprintf(stdout, "\t\tDestination address : %s\n", et_ip2ip_str(&ip->dst));
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void et_display_packet(const et_packet_t * const packet)
|
||||
{
|
||||
if (packet) {
|
||||
fprintf(stdout, "-------------------------------------------------------------------------------\n");
|
||||
fprintf(stdout, "\tPacket:\tnum %u | original frame number %u \n", packet->packet_number, packet->original_frame_number);
|
||||
fprintf(stdout, "\tPacket:\ttime relative to 1st packet %ld.%06lu\n",
|
||||
packet->time_relative_to_first_packet.tv_sec, packet->time_relative_to_first_packet.tv_usec);
|
||||
fprintf(stdout, "\tPacket:\ttime relative to last tx packet %ld.%06lu\n",
|
||||
packet->time_relative_to_last_sent_packet.tv_sec, packet->time_relative_to_last_sent_packet.tv_usec);
|
||||
fprintf(stdout, "\tPacket:\ttime relative to last_received packet %ld.%06lu\n",
|
||||
packet->time_relative_to_last_received_packet.tv_sec, packet->time_relative_to_last_received_packet.tv_usec);
|
||||
|
||||
switch(packet->action) {
|
||||
case ET_PACKET_ACTION_S1C_SEND:
|
||||
fprintf(stdout, "\tPacket:\tAction SEND\n");
|
||||
break;
|
||||
case ET_PACKET_ACTION_S1C_RECEIVE:
|
||||
fprintf(stdout, "\tPacket:\tAction RECEIVE\n");
|
||||
break;
|
||||
default:
|
||||
fprintf(stdout, "\tPacket:\tAction UNKNOWN\n");
|
||||
}
|
||||
switch(packet->status) {
|
||||
case ET_PACKET_STATUS_NONE:
|
||||
fprintf(stdout, "\tPacket:\tStatus NONE\n");
|
||||
break;
|
||||
case ET_PACKET_STATUS_NOT_TAKEN_IN_ACCOUNT:
|
||||
fprintf(stdout, "\tPacket:\tStatus NOT_TAKEN_IN_ACCOUNT\n");
|
||||
break;
|
||||
case ET_PACKET_STATUS_SCHEDULED_FOR_SENDING:
|
||||
fprintf(stdout, "\tPacket:\tStatus SCHEDULED_FOR_SENDING\n");
|
||||
break;
|
||||
case ET_PACKET_STATUS_SENT:
|
||||
fprintf(stdout, "\tPacket:\tStatus SENT\n");
|
||||
break;
|
||||
case ET_PACKET_STATUS_SCHEDULED_FOR_RECEIVING:
|
||||
fprintf(stdout, "\tPacket:\tStatus SCHEDULED_FOR_RECEIVING\n");
|
||||
break;
|
||||
case ET_PACKET_STATUS_RECEIVED:
|
||||
fprintf(stdout, "\tPacket:\tStatus RECEIVED\n");
|
||||
break;
|
||||
default:
|
||||
fprintf(stdout, "\tPacket:\tStatus UNKNOWN\n");
|
||||
}
|
||||
et_display_packet_ip(&packet->ip_hdr);
|
||||
et_display_packet_sctp(&packet->sctp_hdr);
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void et_display_scenario(const et_scenario_t * const scenario)
|
||||
{
|
||||
et_packet_t *packet = NULL;
|
||||
if (scenario) {
|
||||
fprintf(stdout, "Scenario: %s\n", (scenario->name != NULL) ? (char*)scenario->name:"UNKNOWN NAME");
|
||||
packet = scenario->list_packet;
|
||||
while (packet) {
|
||||
et_display_packet(packet);
|
||||
packet = packet->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,567 @@
|
||||
/*******************************************************************************
|
||||
OpenAirInterface
|
||||
Copyright(c) 1999 - 2014 Eurecom
|
||||
|
||||
OpenAirInterface is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
|
||||
OpenAirInterface is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenAirInterface.The full GNU General Public License is
|
||||
included in this distribution in the file called "COPYING". If not,
|
||||
see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Contact Information
|
||||
OpenAirInterface Admin: openair_admin@eurecom.fr
|
||||
OpenAirInterface Tech : openair_tech@eurecom.fr
|
||||
OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr
|
||||
|
||||
Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
/*
|
||||
play_scenario_fsm.c
|
||||
-------------------
|
||||
AUTHOR : Lionel GAUTHIER
|
||||
COMPANY : EURECOM
|
||||
EMAIL : Lionel.Gauthier@eurecom.fr
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <sys/time.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include "intertask_interface.h"
|
||||
#include "platform_types.h"
|
||||
#include "assertions.h"
|
||||
#include "play_scenario.h"
|
||||
#include "s1ap_ies_defs.h"
|
||||
#include "play_scenario_s1ap_eNB_defs.h"
|
||||
#include "timer.h"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
extern int g_max_speed;
|
||||
//------------------------------------------------------------------------------
|
||||
et_scenario_t *g_scenario = NULL;
|
||||
pthread_mutex_t g_fsm_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
et_fsm_state_t g_fsm_state = ET_FSM_STATE_NULL;
|
||||
uint32_t g_constraints = ET_BIT_MASK_MATCH_SCTP_STREAM | ET_BIT_MASK_MATCH_SCTP_SSN;
|
||||
//------------------------------------------------------------------------------
|
||||
// it is assumed that if a time is negative tv_sec and tv_usec are both negative
|
||||
void timeval_add (struct timeval * const result, const struct timeval * const a, const struct timeval * const b)
|
||||
{
|
||||
AssertFatal(((a->tv_sec <= 0) && (a->tv_usec <= 0)) || ((a->tv_sec >= 0) && (a->tv_usec >= 0)), " Bad time format arg a\n");
|
||||
AssertFatal(((b->tv_sec <= 0) && (b->tv_usec <= 0)) || ((b->tv_sec >= 0) && (b->tv_usec >= 0)), " Bad time format arg b\n");
|
||||
// may happen overflows but were are not dealing with very large timings
|
||||
long long int r = a->tv_usec + b->tv_usec + (a->tv_sec + b->tv_sec) * 1000000;
|
||||
result->tv_sec = r / (long long int)1000000;
|
||||
result->tv_usec = r % (long long int)1000000;
|
||||
if ((result != a) && (result != b)) {
|
||||
LOG_D(ENB_APP, "timeval_add(%ld.%06d, %ld.%06d)=%ld.%06d\n", a->tv_sec, a->tv_usec, b->tv_sec, b->tv_usec, result->tv_sec, result->tv_usec);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// it is assumed that if a time is negative tv_sec and tv_usec are both negative
|
||||
// return true if result is positive
|
||||
int timeval_subtract (struct timeval * const result, struct timeval * const a, struct timeval * const b)
|
||||
{
|
||||
AssertFatal(((a->tv_sec <= 0) && (a->tv_usec <= 0)) || ((a->tv_sec >= 0) && (a->tv_usec >= 0)), " Bad time format arg a\n");
|
||||
AssertFatal(((b->tv_sec <= 0) && (b->tv_usec <= 0)) || ((b->tv_sec >= 0) && (b->tv_usec >= 0)), " Bad time format arg b\n");
|
||||
// may happen overflows but were are not dealing with very large timings
|
||||
long long int r = a->tv_usec - b->tv_usec + (a->tv_sec - b->tv_sec) * 1000000;
|
||||
result->tv_sec = r / (long long int)1000000;
|
||||
result->tv_usec = r % (long long int)1000000;
|
||||
if ((result != a) && (result != b)) {
|
||||
LOG_D(ENB_APP, "timeval_subtract(%ld.%06d, %ld.%06d)=%ld.%06d\n", a->tv_sec, a->tv_usec, b->tv_sec, b->tv_usec, result->tv_sec, result->tv_usec);
|
||||
}
|
||||
return (result->tv_sec >= 0) && (result->tv_usec >= 0);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void et_scenario_wait_rx_packet(et_packet_t * const packet)
|
||||
{
|
||||
packet->status = ET_PACKET_STATUS_SCHEDULED_FOR_RECEIVING;
|
||||
g_fsm_state = ET_FSM_STATE_WAITING_RX_EVENT;
|
||||
if (timer_setup (ET_FSM_STATE_WAITING_RX_EVENT_DELAY_SEC, 0, TASK_S1AP, INSTANCE_DEFAULT, TIMER_ONE_SHOT,
|
||||
packet, &packet->timer_id) < 0) {
|
||||
AssertFatal(0, " Can not start waiting RX event timer\n");
|
||||
}
|
||||
g_scenario->timer_count++;
|
||||
LOG_D(ENB_APP, "Waiting RX packet num %d original frame number %u\n", packet->packet_number, packet->original_frame_number);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void et_scenario_schedule_tx_packet(et_packet_t * packet)
|
||||
{
|
||||
s1ap_eNB_instance_t *s1ap_eNB_instance = NULL;
|
||||
struct timeval now = { .tv_sec = 0, .tv_usec = 0 };
|
||||
struct timeval offset_last_tx_packet = { .tv_sec = 0, .tv_usec = 0 };
|
||||
struct timeval offset_last_rx_packet = { .tv_sec = 0, .tv_usec = 0 };
|
||||
struct timeval offset_tx_rx = { .tv_sec = 0, .tv_usec = 0 };
|
||||
struct timeval offset = { .tv_sec = 0, .tv_usec = 0 };
|
||||
int last_packet_was_rx = 0;
|
||||
int we_are_too_late = 0;
|
||||
int original_frame_number = -1;
|
||||
|
||||
AssertFatal(NULL != packet, "packet argument is NULL");
|
||||
s1ap_eNB_instance = et_s1ap_eNB_get_instance(packet->enb_instance);
|
||||
AssertFatal(NULL != s1ap_eNB_instance, "Cannot get s1ap_eNB_instance_t for eNB instance %d", packet->enb_instance);
|
||||
|
||||
LOG_D(ENB_APP, "%s\n", __FUNCTION__);
|
||||
g_fsm_state = ET_FSM_STATE_WAITING_TX_EVENT;
|
||||
|
||||
switch (packet->sctp_hdr.chunk_type) {
|
||||
case SCTP_CID_DATA:
|
||||
// check if we can send it now
|
||||
// TODO: BUG we have to discard in scenario all packets that cannot be processed (SACK, COOKIEs, etc)
|
||||
AssertFatal(gettimeofday(&now, NULL) == 0, "gettimeofday failed");
|
||||
timeval_subtract(&offset_last_tx_packet,&now,&g_scenario->time_last_tx_packet);
|
||||
timeval_subtract(&offset_last_rx_packet,&now,&g_scenario->time_last_rx_packet);
|
||||
LOG_D(ENB_APP, "offset_last_tx_packet=%ld.%06d\n", offset_last_tx_packet.tv_sec, offset_last_tx_packet.tv_usec);
|
||||
LOG_D(ENB_APP, "offset_last_rx_packet=%ld.%06d\n", offset_last_rx_packet.tv_sec, offset_last_rx_packet.tv_usec);
|
||||
|
||||
last_packet_was_rx = timeval_subtract(&offset_tx_rx,&offset_last_tx_packet,&offset_last_rx_packet);
|
||||
if (last_packet_was_rx) {
|
||||
LOG_D(ENB_APP, "last_packet_was_rx\n");
|
||||
we_are_too_late = timeval_subtract(&offset,&offset_last_rx_packet,&packet->time_relative_to_last_received_packet);
|
||||
LOG_D(ENB_APP, "we_are_too_late=%d, offset=%ld.%06d\n", we_are_too_late, offset.tv_sec, offset.tv_usec);
|
||||
} else {
|
||||
LOG_D(ENB_APP, "last_packet_was_tx\n");
|
||||
we_are_too_late = timeval_subtract(&offset,&offset_last_tx_packet,&packet->time_relative_to_last_sent_packet);
|
||||
LOG_D(ENB_APP, "we_are_too_late=%d, offset=%ld.%06d\n", we_are_too_late, offset.tv_sec, offset.tv_usec);
|
||||
}
|
||||
if ((0 == we_are_too_late) && (0 == g_max_speed)){
|
||||
// set timer
|
||||
if ((offset.tv_sec <= 0) || (offset.tv_usec <= 0)){
|
||||
offset.tv_sec = -offset.tv_sec;
|
||||
offset.tv_usec = -offset.tv_usec;
|
||||
}
|
||||
|
||||
LOG_D(ENB_APP, "Send packet num %u original frame number %u in %ld.%06d sec\n",
|
||||
packet->packet_number, packet->original_frame_number, offset.tv_sec, offset.tv_usec);
|
||||
|
||||
packet->status = ET_PACKET_STATUS_SCHEDULED_FOR_SENDING;
|
||||
if (timer_setup (offset.tv_sec, offset.tv_usec, TASK_S1AP, INSTANCE_DEFAULT, TIMER_ONE_SHOT,packet, &packet->timer_id) < 0) {
|
||||
AssertFatal(0, " Can not start TX event timer\n");
|
||||
}
|
||||
g_scenario->timer_count++;
|
||||
// Done g_fsm_state = ET_FSM_STATE_WAITING_TX_EVENT;
|
||||
} else {
|
||||
// send immediately
|
||||
AssertFatal(0 == gettimeofday(&packet->timestamp_packet, NULL), "gettimeofday() Failed");
|
||||
original_frame_number = packet->original_frame_number;
|
||||
do {
|
||||
g_scenario->time_last_tx_packet.tv_sec = packet->timestamp_packet.tv_sec;
|
||||
g_scenario->time_last_tx_packet.tv_usec = packet->timestamp_packet.tv_usec;
|
||||
|
||||
LOG_D(ENB_APP, "Sending packet num %d original frame number %u immediately\n",packet->packet_number, packet->original_frame_number);
|
||||
et_s1ap_eNB_itti_send_sctp_data_req(
|
||||
packet->enb_instance,
|
||||
packet->sctp_hdr.u.data_hdr.assoc_id,
|
||||
packet->sctp_hdr.u.data_hdr.payload.binary_stream,
|
||||
packet->sctp_hdr.u.data_hdr.payload.binary_stream_allocated_size,
|
||||
packet->sctp_hdr.u.data_hdr.stream);
|
||||
packet->status = ET_PACKET_STATUS_SENT;
|
||||
g_scenario->next_packet = g_scenario->next_packet->next;
|
||||
packet = packet->next;
|
||||
} while ((NULL != packet) && (packet->original_frame_number == original_frame_number));
|
||||
g_fsm_state = ET_FSM_STATE_RUNNING;
|
||||
}
|
||||
break;
|
||||
case SCTP_CID_INIT:
|
||||
case SCTP_CID_INIT_ACK:
|
||||
AssertFatal(0, "Invalid case TX packet SCTP_CID_INIT or SCTP_CID_INIT_ACK");
|
||||
break;
|
||||
default:
|
||||
AssertFatal(0, "Invalid case TX packet SCTP_CID %d", packet->sctp_hdr.chunk_type);
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
et_fsm_state_t et_scenario_fsm_notify_event_state_running(et_event_t event)
|
||||
{
|
||||
|
||||
switch (event.code){
|
||||
case ET_EVENT_TICK:
|
||||
while (NULL != g_scenario->next_packet) {
|
||||
LOG_D(ENB_APP, "EVENT_TICK: Considering packet num %d original frame number %u\n", g_scenario->next_packet->packet_number, g_scenario->next_packet->original_frame_number);
|
||||
switch (g_scenario->next_packet->sctp_hdr.chunk_type) {
|
||||
case SCTP_CID_DATA :
|
||||
// no init in this scenario, may be sub-scenario
|
||||
if (g_scenario->next_packet->action == ET_PACKET_ACTION_S1C_SEND) {
|
||||
if (g_scenario->next_packet->status == ET_PACKET_STATUS_NONE) {
|
||||
et_scenario_schedule_tx_packet(g_scenario->next_packet);
|
||||
pthread_mutex_unlock(&g_fsm_lock);
|
||||
|
||||
et_event_t continue_event;
|
||||
continue_event.code = ET_EVENT_TICK;
|
||||
et_scenario_fsm_notify_event(continue_event);
|
||||
|
||||
return g_fsm_state;
|
||||
} else if (g_scenario->next_packet->status != ET_PACKET_STATUS_SCHEDULED_FOR_SENDING) {
|
||||
AssertFatal(0, "Invalid packet status %d", g_scenario->next_packet->status);
|
||||
}
|
||||
} else if (g_scenario->next_packet->action == ET_PACKET_ACTION_S1C_RECEIVE) {
|
||||
if (g_scenario->next_packet->status == ET_PACKET_STATUS_RECEIVED) {
|
||||
g_scenario->next_packet = g_scenario->next_packet->next;
|
||||
|
||||
} else if (g_scenario->next_packet->status == ET_PACKET_STATUS_NONE) {
|
||||
et_scenario_wait_rx_packet(g_scenario->next_packet);
|
||||
pthread_mutex_unlock(&g_fsm_lock);
|
||||
return g_fsm_state;
|
||||
} else {
|
||||
AssertFatal(0, "Invalid packet status %d", g_scenario->next_packet->status);
|
||||
}
|
||||
} else {
|
||||
AssertFatal(0, "Invalid packet action %d", g_scenario->next_packet->action);
|
||||
}
|
||||
break;
|
||||
|
||||
case SCTP_CID_INIT:
|
||||
case SCTP_CID_INIT_ACK:
|
||||
case SCTP_CID_HEARTBEAT:
|
||||
case SCTP_CID_HEARTBEAT_ACK:
|
||||
case SCTP_CID_COOKIE_ECHO:
|
||||
case SCTP_CID_COOKIE_ACK:
|
||||
case SCTP_CID_ECN_ECNE:
|
||||
case SCTP_CID_ECN_CWR:
|
||||
LOG_D(ENB_APP, "EVENT_TICK: Ignoring packet num %d SCTP CID %s\n",
|
||||
g_scenario->next_packet->packet_number,
|
||||
et_chunk_type_cid2str(g_scenario->next_packet->sctp_hdr.chunk_type));
|
||||
g_scenario->next_packet->status = ET_PACKET_STATUS_NOT_TAKEN_IN_ACCOUNT;
|
||||
g_scenario->next_packet = g_scenario->next_packet->next;
|
||||
break;
|
||||
|
||||
case SCTP_CID_ABORT:
|
||||
case SCTP_CID_SHUTDOWN:
|
||||
case SCTP_CID_SHUTDOWN_ACK:
|
||||
case SCTP_CID_ERROR:
|
||||
case SCTP_CID_SHUTDOWN_COMPLETE:
|
||||
AssertFatal(0, "The scenario should be cleaned (packet %s cannot be processed at this time)",
|
||||
et_chunk_type_cid2str(g_scenario->next_packet->sctp_hdr.chunk_type));
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG_D(ENB_APP, "EVENT_TICK: Ignoring packet num %d SCTP CID %s\n",
|
||||
g_scenario->next_packet->packet_number,
|
||||
et_chunk_type_cid2str(g_scenario->next_packet->sctp_hdr.chunk_type));
|
||||
g_scenario->next_packet->status = ET_PACKET_STATUS_NOT_TAKEN_IN_ACCOUNT;
|
||||
g_scenario->next_packet = g_scenario->next_packet->next;
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "No Packet found in this scenario: %s\n", g_scenario->name);
|
||||
g_fsm_state = ET_FSM_STATE_NULL;
|
||||
pthread_mutex_unlock(&g_fsm_lock);
|
||||
if (0 == g_scenario->timer_count) {
|
||||
fprintf(stderr, "End of scenario: %s\n", g_scenario->name);
|
||||
fflush(stderr);
|
||||
fflush(stdout);
|
||||
return 0;
|
||||
//exit(0);
|
||||
}
|
||||
fprintf(stderr, "Remaining timers running: %d\n", g_scenario->timer_count);
|
||||
return g_fsm_state;
|
||||
break;
|
||||
case ET_EVENT_RX_PACKET_TIME_OUT:
|
||||
AssertFatal(0, "Event ET_EVENT_RX_PACKET_TIME_OUT not handled in FSM state ET_FSM_STATE_RUNNING");
|
||||
break;
|
||||
case ET_EVENT_TX_TIMED_PACKET:
|
||||
AssertFatal(0, "Event ET_EVENT_TX_TIMED_PACKET not handled in FSM state ET_FSM_STATE_RUNNING");
|
||||
break;
|
||||
case ET_EVENT_RX_S1AP:
|
||||
et_s1ap_process_rx_packet(&event.u.s1ap_data_ind);
|
||||
break;
|
||||
default:
|
||||
AssertFatal(0, "Case event %d not handled in ET_FSM_STATE_RUNNING", event.code);
|
||||
}
|
||||
pthread_mutex_unlock(&g_fsm_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
et_fsm_state_t et_scenario_fsm_notify_event_state_waiting_tx(et_event_t event)
|
||||
{
|
||||
int rv = 0;
|
||||
int original_frame_number = -1;
|
||||
et_packet_t *packet = NULL;
|
||||
|
||||
switch (event.code){
|
||||
case ET_EVENT_TICK:
|
||||
fprintf(stdout, "EVENT_TICK: waiting for tx event\n");
|
||||
break;
|
||||
|
||||
case ET_EVENT_RX_S1AP:
|
||||
rv = et_s1ap_process_rx_packet(&event.u.s1ap_data_ind);
|
||||
break;
|
||||
|
||||
case ET_EVENT_TX_TIMED_PACKET:
|
||||
// send immediately
|
||||
packet = event.u.tx_timed_packet;
|
||||
AssertFatal(0 == gettimeofday(&packet->timestamp_packet, NULL), "gettimeofday() Failed");
|
||||
|
||||
original_frame_number = packet->original_frame_number;
|
||||
do {
|
||||
g_scenario->time_last_tx_packet.tv_sec = packet->timestamp_packet.tv_sec;
|
||||
g_scenario->time_last_tx_packet.tv_usec = packet->timestamp_packet.tv_usec;
|
||||
|
||||
LOG_D(ENB_APP, "Sending packet num %d original frame number %u immediately\n",packet->packet_number, packet->original_frame_number);
|
||||
et_s1ap_eNB_itti_send_sctp_data_req(
|
||||
packet->enb_instance,
|
||||
packet->sctp_hdr.u.data_hdr.assoc_id,
|
||||
packet->sctp_hdr.u.data_hdr.payload.binary_stream,
|
||||
packet->sctp_hdr.u.data_hdr.payload.binary_stream_allocated_size,
|
||||
packet->sctp_hdr.u.data_hdr.stream);
|
||||
packet->status = ET_PACKET_STATUS_SENT;
|
||||
packet = packet->next;
|
||||
g_scenario->next_packet = packet;
|
||||
} while ( (NULL != packet) && (packet->original_frame_number == original_frame_number));
|
||||
g_fsm_state = ET_FSM_STATE_RUNNING;
|
||||
break;
|
||||
|
||||
case ET_EVENT_RX_PACKET_TIME_OUT:
|
||||
default:
|
||||
AssertFatal(0, "Case event %d not handled in ET_FSM_STATE_WAITING_TX", event.code);
|
||||
}
|
||||
pthread_mutex_unlock(&g_fsm_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
et_fsm_state_t et_scenario_fsm_notify_event_state_waiting_rx(et_event_t event)
|
||||
{
|
||||
int rv = 0;
|
||||
switch (event.code){
|
||||
case ET_EVENT_TICK:
|
||||
fprintf(stdout, "EVENT_TICK: waiting for rx event\n");
|
||||
break;
|
||||
|
||||
case ET_EVENT_RX_PACKET_TIME_OUT:
|
||||
fprintf(stderr, "Error The following packet is not received:\n");
|
||||
//et_display_packet(event.u.rx_packet_time_out);
|
||||
AssertFatal(0, "Waited packet not received");
|
||||
break;
|
||||
|
||||
case ET_EVENT_RX_S1AP:
|
||||
rv = et_s1ap_process_rx_packet(&event.u.s1ap_data_ind);
|
||||
// waited packet
|
||||
if (rv == 0) {
|
||||
g_fsm_state = ET_FSM_STATE_RUNNING;
|
||||
}
|
||||
break;
|
||||
|
||||
case ET_EVENT_TX_TIMED_PACKET:
|
||||
default:
|
||||
AssertFatal(0, "Case event %d not handled in ET_FSM_STATE_WAITING_RX", event.code);
|
||||
}
|
||||
pthread_mutex_unlock(&g_fsm_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
et_fsm_state_t et_scenario_fsm_notify_event_state_connecting_s1c(et_event_t event)
|
||||
{
|
||||
|
||||
switch (event.code){
|
||||
case ET_EVENT_TICK:
|
||||
break;
|
||||
|
||||
case ET_EVENT_S1C_CONNECTED:
|
||||
// hack simulate we have been able to get the right timing values for STCP connect
|
||||
AssertFatal(gettimeofday(&g_scenario->time_last_rx_packet, NULL) == 0, "gettimeofday failed");
|
||||
|
||||
while (NULL != g_scenario->next_packet) {
|
||||
switch (g_scenario->next_packet->sctp_hdr.chunk_type) {
|
||||
case SCTP_CID_DATA :
|
||||
// no init in this scenario, may be sub-scenario
|
||||
if (g_scenario->next_packet->action == ET_PACKET_ACTION_S1C_SEND) {
|
||||
et_scenario_schedule_tx_packet(g_scenario->next_packet);
|
||||
pthread_mutex_unlock(&g_fsm_lock);
|
||||
|
||||
et_event_t continue_event;
|
||||
continue_event.code = ET_EVENT_TICK;
|
||||
et_scenario_fsm_notify_event(continue_event);
|
||||
|
||||
return g_fsm_state;
|
||||
} else if (g_scenario->next_packet->action == ET_PACKET_ACTION_S1C_RECEIVE) {
|
||||
if (g_scenario->next_packet->status == ET_PACKET_STATUS_RECEIVED) {
|
||||
g_scenario->last_rx_packet = g_scenario->next_packet;
|
||||
g_scenario->time_last_rx_packet = g_scenario->last_rx_packet->timestamp_packet;
|
||||
g_scenario->next_packet = g_scenario->next_packet->next;
|
||||
|
||||
} else if (g_scenario->next_packet->status == ET_PACKET_STATUS_NONE) {
|
||||
et_scenario_wait_rx_packet(g_scenario->next_packet);
|
||||
pthread_mutex_unlock(&g_fsm_lock);
|
||||
return g_fsm_state;
|
||||
} else {
|
||||
AssertFatal(0, "Invalid packet status %d", g_scenario->next_packet->status);
|
||||
}
|
||||
} else {
|
||||
AssertFatal(0, "Invalid packet action %d", g_scenario->next_packet->action);
|
||||
}
|
||||
break;
|
||||
|
||||
case SCTP_CID_INIT:
|
||||
case SCTP_CID_INIT_ACK:
|
||||
case SCTP_CID_HEARTBEAT:
|
||||
case SCTP_CID_HEARTBEAT_ACK:
|
||||
case SCTP_CID_COOKIE_ECHO:
|
||||
case SCTP_CID_COOKIE_ACK:
|
||||
case SCTP_CID_ECN_ECNE:
|
||||
case SCTP_CID_ECN_CWR:
|
||||
g_scenario->next_packet->status = ET_PACKET_STATUS_NOT_TAKEN_IN_ACCOUNT;
|
||||
g_scenario->next_packet = g_scenario->next_packet->next;
|
||||
break;
|
||||
|
||||
case SCTP_CID_ABORT:
|
||||
case SCTP_CID_SHUTDOWN:
|
||||
case SCTP_CID_SHUTDOWN_ACK:
|
||||
case SCTP_CID_ERROR:
|
||||
case SCTP_CID_SHUTDOWN_COMPLETE:
|
||||
AssertFatal(0, "The scenario should be cleaned (packet %s cannot be processed at this time)",
|
||||
et_chunk_type_cid2str(g_scenario->next_packet->sctp_hdr.chunk_type));
|
||||
break;
|
||||
|
||||
default:
|
||||
g_scenario->next_packet->status = ET_PACKET_STATUS_NOT_TAKEN_IN_ACCOUNT;
|
||||
g_scenario->next_packet = g_scenario->next_packet->next;
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "No Packet found in this scenario: %s\n", g_scenario->name);
|
||||
g_fsm_state = ET_FSM_STATE_NULL;
|
||||
pthread_mutex_unlock(&g_fsm_lock);
|
||||
if (0 == g_scenario->timer_count) {
|
||||
fprintf(stderr, "End of scenario: %s\n", g_scenario->name);
|
||||
fflush(stderr);
|
||||
fflush(stdout);
|
||||
exit(0);
|
||||
}
|
||||
fprintf(stderr, "Remaining timers running: %d\n", g_scenario->timer_count);
|
||||
return g_fsm_state;
|
||||
break;
|
||||
|
||||
default:
|
||||
AssertFatal(0, "Case event %d not handled in ET_FSM_STATE_CONNECTING_S1C", event.code);
|
||||
}
|
||||
pthread_mutex_unlock(&g_fsm_lock);
|
||||
return 0;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
et_fsm_state_t et_scenario_fsm_notify_event_state_null(et_event_t event)
|
||||
{
|
||||
switch (event.code){
|
||||
case ET_EVENT_TICK:
|
||||
break;
|
||||
|
||||
case ET_EVENT_INIT:
|
||||
AssertFatal(NULL == g_scenario, "Current scenario not ended");
|
||||
g_scenario = event.u.init.scenario;
|
||||
g_scenario->next_packet = g_scenario->list_packet;
|
||||
g_scenario->last_rx_packet = NULL;
|
||||
g_scenario->last_tx_packet = NULL;
|
||||
|
||||
while (NULL != g_scenario->next_packet) {
|
||||
switch (g_scenario->next_packet->sctp_hdr.chunk_type) {
|
||||
|
||||
case SCTP_CID_DATA :
|
||||
// no init in this scenario, may be sub-scenario, ...
|
||||
if (g_scenario->next_packet->action == ET_PACKET_ACTION_S1C_SEND) {
|
||||
et_scenario_schedule_tx_packet(g_scenario->next_packet);
|
||||
pthread_mutex_unlock(&g_fsm_lock);
|
||||
|
||||
et_event_t continue_event;
|
||||
continue_event.code = ET_EVENT_TICK;
|
||||
et_scenario_fsm_notify_event(continue_event);
|
||||
|
||||
return g_fsm_state;
|
||||
} else if (g_scenario->next_packet->action == ET_PACKET_ACTION_S1C_RECEIVE) {
|
||||
if (g_scenario->next_packet->status == ET_PACKET_STATUS_RECEIVED) {
|
||||
g_scenario->last_rx_packet = g_scenario->next_packet;
|
||||
g_scenario->time_last_rx_packet = g_scenario->last_rx_packet->timestamp_packet;
|
||||
g_scenario->next_packet = g_scenario->next_packet->next;
|
||||
|
||||
} else if (g_scenario->next_packet->status == ET_PACKET_STATUS_NONE) {
|
||||
et_scenario_wait_rx_packet(g_scenario->next_packet);
|
||||
pthread_mutex_unlock(&g_fsm_lock);
|
||||
return g_fsm_state;
|
||||
} else {
|
||||
AssertFatal(0, "Invalid packet status %d", g_scenario->next_packet->status);
|
||||
}
|
||||
} else {
|
||||
AssertFatal(0, "Invalid packet action %d", g_scenario->next_packet->action);
|
||||
}
|
||||
break;
|
||||
|
||||
case SCTP_CID_INIT:
|
||||
case SCTP_CID_INIT_ACK:
|
||||
g_scenario->enb_properties = (Enb_properties_array_t *)et_enb_config_get();
|
||||
g_scenario->hash_old_ue_mme_id2ue_mme_id = hashtable_create (256,NULL,NULL);
|
||||
g_scenario->hash_mme2association_id = hashtable_create (256,NULL,NULL);
|
||||
// Try to register each eNB
|
||||
g_scenario->registered_enb = 0;
|
||||
g_fsm_state = ET_FSM_STATE_CONNECTING_S1C;
|
||||
AssertFatal(gettimeofday(&g_scenario->time_last_tx_packet, NULL) == 0, "gettimeofday failed");
|
||||
et_eNB_app_register (g_scenario->enb_properties);
|
||||
pthread_mutex_unlock(&g_fsm_lock);
|
||||
return g_fsm_state;
|
||||
break;
|
||||
|
||||
case SCTP_CID_HEARTBEAT:
|
||||
case SCTP_CID_HEARTBEAT_ACK:
|
||||
case SCTP_CID_COOKIE_ECHO:
|
||||
case SCTP_CID_COOKIE_ACK:
|
||||
case SCTP_CID_ECN_ECNE:
|
||||
case SCTP_CID_ECN_CWR:
|
||||
g_scenario->next_packet->status = ET_PACKET_STATUS_NOT_TAKEN_IN_ACCOUNT;
|
||||
g_scenario->next_packet = g_scenario->next_packet->next;
|
||||
break;
|
||||
|
||||
case SCTP_CID_ABORT:
|
||||
case SCTP_CID_SHUTDOWN:
|
||||
case SCTP_CID_SHUTDOWN_ACK:
|
||||
case SCTP_CID_ERROR:
|
||||
case SCTP_CID_SHUTDOWN_COMPLETE:
|
||||
AssertFatal(0, "The scenario should be cleaned (packet %s cannot be processed at this time)",
|
||||
et_chunk_type_cid2str(g_scenario->next_packet->sctp_hdr.chunk_type));
|
||||
break;
|
||||
|
||||
default:
|
||||
g_scenario->next_packet->status = ET_PACKET_STATUS_NOT_TAKEN_IN_ACCOUNT;
|
||||
g_scenario->next_packet = g_scenario->next_packet->next;
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "No Useful packet found in this scenario: %s\n", g_scenario->name);
|
||||
g_fsm_state = ET_FSM_STATE_NULL;
|
||||
pthread_mutex_unlock(&g_fsm_lock);
|
||||
return g_fsm_state;
|
||||
break;
|
||||
|
||||
default:
|
||||
AssertFatal(0, "Case event %d not handled in ET_FSM_STATE_NULL", event.code);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
et_fsm_state_t et_scenario_fsm_notify_event(et_event_t event)
|
||||
{
|
||||
AssertFatal((event.code >= ET_EVENT_START) && (event.code < ET_EVENT_END), "Unknown et_event_t.code %d", event.code);
|
||||
|
||||
pthread_mutex_lock(&g_fsm_lock);
|
||||
switch (g_fsm_state){
|
||||
case ET_FSM_STATE_NULL: return et_scenario_fsm_notify_event_state_null(event); break;
|
||||
case ET_FSM_STATE_CONNECTING_S1C: return et_scenario_fsm_notify_event_state_connecting_s1c(event); break;
|
||||
case ET_FSM_STATE_WAITING_TX_EVENT: return et_scenario_fsm_notify_event_state_waiting_tx(event); break;
|
||||
case ET_FSM_STATE_WAITING_RX_EVENT: return et_scenario_fsm_notify_event_state_waiting_rx(event); break;
|
||||
case ET_FSM_STATE_RUNNING: return et_scenario_fsm_notify_event_state_running(event); break;
|
||||
default:
|
||||
AssertFatal(0, "Case fsm_state %d not handled", g_fsm_state);
|
||||
}
|
||||
pthread_mutex_unlock(&g_fsm_lock);
|
||||
return g_fsm_state;
|
||||
}
|
||||
@@ -0,0 +1,600 @@
|
||||
/*******************************************************************************
|
||||
OpenAirInterface
|
||||
Copyright(c) 1999 - 2014 Eurecom
|
||||
|
||||
OpenAirInterface is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
|
||||
OpenAirInterface is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenAirInterface.The full GNU General Public License is
|
||||
included in this distribution in the file called "COPYING". If not,
|
||||
see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Contact Information
|
||||
OpenAirInterface Admin: openair_admin@eurecom.fr
|
||||
OpenAirInterface Tech : openair_tech@eurecom.fr
|
||||
OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr
|
||||
|
||||
Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
/*
|
||||
play_scenario_parse.c
|
||||
-------------------
|
||||
AUTHOR : Lionel GAUTHIER
|
||||
COMPANY : EURECOM
|
||||
EMAIL : Lionel.Gauthier@eurecom.fr
|
||||
*/
|
||||
|
||||
#include <libxml/xmlmemory.h>
|
||||
#include <libxml/debugXML.h>
|
||||
#include <libxml/xmlIO.h>
|
||||
#include <libxml/DOCBparser.h>
|
||||
#include <libxml/xinclude.h>
|
||||
#include <libxml/catalog.h>
|
||||
#include <libxml/xmlreader.h>
|
||||
#include <libxslt/xslt.h>
|
||||
#include <libxslt/xsltInternals.h>
|
||||
#include <libxslt/transform.h>
|
||||
#include <libxslt/xsltutils.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "intertask_interface.h"
|
||||
#include "platform_types.h"
|
||||
#include "assertions.h"
|
||||
#include "play_scenario.h"
|
||||
//------------------------------------------------------------------------------
|
||||
#define ENB_CONFIG_MAX_XSLT_PARAMS 32
|
||||
//------------------------------------------------------------------------------
|
||||
extern Enb_properties_array_t g_enb_properties;
|
||||
//------------------------------------------------------------------------------
|
||||
void et_parse_s1ap(xmlDocPtr doc, const xmlNode const *s1ap_node, et_s1ap_t * const s1ap)
|
||||
{
|
||||
xmlNodePtr cur_node = NULL;
|
||||
xmlChar *xml_char = NULL;
|
||||
xmlChar *xml_char2 = NULL;
|
||||
unsigned int size = 0;
|
||||
int rc = 0;
|
||||
unsigned int go_deeper_in_tree = 1;
|
||||
|
||||
if ((NULL != s1ap_node) && (NULL != s1ap)) {
|
||||
// see http://www.xmlsoft.org/html/libxml-tree.html#xmlCopyNode
|
||||
if (NULL == s1ap->doc) {
|
||||
xmlUnlinkNode(s1ap_node);
|
||||
//cur_node = xmlCopyNodeList(s1ap_node);
|
||||
// arg2: if 1 do a recursive copy (properties, namespaces and children when applicable) if 2 copy properties and namespaces (when applicable)
|
||||
//cur_node = xmlCopyNode(s1ap_node, 1);
|
||||
//AssertFatal(NULL != cur_node, "xmlCopyNode Failed");
|
||||
s1ap->doc = xmlNewDoc(BAD_CAST "1.0");
|
||||
xmlDocSetRootElement(s1ap->doc, s1ap_node);
|
||||
}
|
||||
|
||||
for (cur_node = (xmlNode *)s1ap_node; cur_node; cur_node = cur_node->next) {
|
||||
go_deeper_in_tree = 1;
|
||||
if ((!xmlStrcmp(cur_node->name, (const xmlChar *)"field"))) {
|
||||
// do not get hidden fields
|
||||
xml_char = xmlGetProp((xmlNode *)cur_node, (const xmlChar *)"hide");
|
||||
if (NULL != xml_char) {
|
||||
if ((!xmlStrcmp(xml_char, (const xmlChar *)"yes"))) {
|
||||
go_deeper_in_tree = 0;
|
||||
}
|
||||
xmlFree(xml_char);
|
||||
}
|
||||
if (0 < go_deeper_in_tree) {
|
||||
// first get size
|
||||
xml_char = xmlGetProp((xmlNode *)cur_node, (const xmlChar *)"size");
|
||||
if (NULL != xml_char) {
|
||||
size = strtoul((const char *)xml_char, NULL, 0);
|
||||
xmlFree(xml_char);
|
||||
// second: try to get value (always hex)
|
||||
xml_char = xmlGetProp((xmlNode *)cur_node, (const xmlChar *)"value");
|
||||
if (NULL != xml_char) {
|
||||
xml_char2 = xmlGetProp((xmlNode *)cur_node, (const xmlChar *)"name");
|
||||
fprintf(stdout, "s1ap %p field name %s size %d value %s\n",s1ap, xml_char2, size, xml_char);
|
||||
xmlFree(xml_char2);
|
||||
// if success to get value, do not parse children
|
||||
//AssertFatal ((xmlStrlen(xml_char) == size), "ERROR %s() mismatch in size %d and strlen %d\n", __FUNCTION__, size, xmlStrlen(xml_char));
|
||||
//if (xmlStrlen(xml_char) == size) {
|
||||
AssertFatal ((s1ap->binary_stream_pos+xmlStrlen(xml_char)/2) <= s1ap->binary_stream_allocated_size,
|
||||
"ERROR in buffer size: binary_stream_pos %d xmlStrlen(xml_char)/2=%d\n", s1ap->binary_stream_pos, xmlStrlen(xml_char)/2);
|
||||
rc = et_hex2data( &s1ap->binary_stream[s1ap->binary_stream_pos], xml_char, xmlStrlen(xml_char));
|
||||
s1ap->binary_stream_pos += xmlStrlen(xml_char)/2;
|
||||
//et_display_node(cur_node, 0);
|
||||
AssertFatal (rc >= 0, "ERROR in converting hex string %s len %d size %d rc %d\n", xml_char, xmlStrlen(xml_char), size, rc);
|
||||
go_deeper_in_tree = 0;
|
||||
//}
|
||||
xmlFree(xml_char);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (0 < go_deeper_in_tree) {
|
||||
et_parse_s1ap(doc, cur_node->children, s1ap);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void et_parse_sctp_data_chunk(xmlDocPtr doc, const xmlNode const *sctp_node, sctp_datahdr_t * const sctp_hdr)
|
||||
{
|
||||
xmlNode *cur_node = NULL;
|
||||
xmlChar *xml_char = NULL;
|
||||
xmlChar *xml_char2 = NULL;
|
||||
|
||||
if ((NULL != sctp_node) && (NULL != sctp_hdr)) {
|
||||
xml_char = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"name");
|
||||
if (NULL != xml_char) {
|
||||
if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.data_payload_proto_id"))) {
|
||||
xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"show");
|
||||
if (NULL != xml_char2) {
|
||||
sctp_hdr->ppid = strtoul((const char *)xml_char2, NULL, 0);
|
||||
xmlFree(xml_char2);
|
||||
}
|
||||
} else if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.data_sid"))) {
|
||||
xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"show");
|
||||
if (NULL != xml_char2) {
|
||||
sctp_hdr->stream = strtoul((const char *)xml_char2, NULL, 16);
|
||||
xmlFree(xml_char2);
|
||||
}
|
||||
} else if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.data_tsn"))) {
|
||||
xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"show");
|
||||
if (NULL != xml_char2) {
|
||||
sctp_hdr->tsn = strtoul((const char *)xml_char2, NULL, 0);
|
||||
xmlFree(xml_char2);
|
||||
}
|
||||
} else if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.data_ssn"))) {
|
||||
xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"show");
|
||||
if (NULL != xml_char2) {
|
||||
sctp_hdr->ssn = strtoul((const char *)xml_char2, NULL, 0);
|
||||
xmlFree(xml_char2);
|
||||
}
|
||||
}
|
||||
xmlFree(xml_char);
|
||||
}
|
||||
for (cur_node = sctp_node->children; cur_node; cur_node = cur_node->next) {
|
||||
et_parse_sctp_data_chunk(doc, cur_node, sctp_hdr);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void et_parse_sctp_init_chunk(xmlDocPtr doc, const xmlNode const *sctp_node, sctp_inithdr_t * const sctp_hdr)
|
||||
{
|
||||
xmlNode *cur_node = NULL;
|
||||
xmlChar *xml_char = NULL;
|
||||
xmlChar *xml_char2 = NULL;
|
||||
|
||||
if ((NULL != sctp_node) && (NULL != sctp_hdr)) {
|
||||
xml_char = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"name");
|
||||
if (NULL != xml_char) {
|
||||
if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.init_nr_out_streams"))) {
|
||||
xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"value");
|
||||
if (NULL != xml_char2) {
|
||||
sctp_hdr->num_outbound_streams = strtoul((const char *)xml_char2, NULL, 0);
|
||||
xmlFree(xml_char2);
|
||||
}
|
||||
} else if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.init_nr_in_streams"))) {
|
||||
xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"value");
|
||||
if (NULL != xml_char2) {
|
||||
sctp_hdr->num_inbound_streams = strtoul((const char *)xml_char2, NULL, 0);
|
||||
xmlFree(xml_char2);
|
||||
}
|
||||
} else if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.init_credit"))) {
|
||||
xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"value");
|
||||
if (NULL != xml_char2) {
|
||||
sctp_hdr->a_rwnd = strtoul((const char *)xml_char2, NULL, 0);
|
||||
xmlFree(xml_char2);
|
||||
}
|
||||
} else if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.init_initial_tsn"))) {
|
||||
xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"show");
|
||||
if (NULL != xml_char2) {
|
||||
sctp_hdr->initial_tsn = strtoul((const char *)xml_char2, NULL, 0);
|
||||
xmlFree(xml_char2);
|
||||
}
|
||||
} else if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.init_initiate_tag"))) {
|
||||
xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"show");
|
||||
if (NULL != xml_char2) {
|
||||
sctp_hdr->init_tag = strtoul((const char *)xml_char2, NULL, 16);
|
||||
xmlFree(xml_char2);
|
||||
}
|
||||
}
|
||||
xmlFree(xml_char);
|
||||
}
|
||||
for (cur_node = sctp_node->children; cur_node; cur_node = cur_node->next) {
|
||||
et_parse_sctp_init_chunk(doc, cur_node, sctp_hdr);
|
||||
}
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void et_parse_sctp_init_ack_chunk(xmlDocPtr doc, const xmlNode const *sctp_node, sctp_initackhdr_t * const sctp_hdr)
|
||||
{
|
||||
xmlNode *cur_node = NULL;
|
||||
xmlChar *xml_char = NULL;
|
||||
xmlChar *xml_char2 = NULL;
|
||||
|
||||
if ((NULL != sctp_node) && (NULL != sctp_hdr)) {
|
||||
xml_char = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"name");
|
||||
if (NULL != xml_char) {
|
||||
if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.initack_nr_out_streams"))) {
|
||||
xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"value");
|
||||
if (NULL != xml_char2) {
|
||||
sctp_hdr->num_outbound_streams = strtoul((const char *)xml_char2, NULL, 0);
|
||||
xmlFree(xml_char2);
|
||||
}
|
||||
} else if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.initack_nr_in_streams"))) {
|
||||
xml_char2 = xmlGetProp((xmlNode *)(xmlNode *)sctp_node, (const xmlChar *)"value");
|
||||
if (NULL != xml_char2) {
|
||||
sctp_hdr->num_inbound_streams = strtoul((const char *)xml_char2, NULL, 0);
|
||||
xmlFree(xml_char2);
|
||||
}
|
||||
} else if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.initack_credit"))) {
|
||||
xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"value");
|
||||
if (NULL != xml_char2) {
|
||||
sctp_hdr->a_rwnd = strtoul((const char *)xml_char2, NULL, 0);
|
||||
xmlFree(xml_char2);
|
||||
}
|
||||
} else if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.initack_initial_tsn"))) {
|
||||
xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"show");
|
||||
if (NULL != xml_char2) {
|
||||
sctp_hdr->initial_tsn = strtoul((const char *)xml_char2, NULL, 0);
|
||||
xmlFree(xml_char2);
|
||||
}
|
||||
} else if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.initack_initiate_tag"))) {
|
||||
xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"show");
|
||||
if (NULL != xml_char2) {
|
||||
sctp_hdr->init_tag = strtoul((const char *)xml_char2, NULL, 16);
|
||||
xmlFree(xml_char2);
|
||||
}
|
||||
}
|
||||
xmlFree(xml_char);
|
||||
}
|
||||
for (cur_node = sctp_node->children; cur_node; cur_node = cur_node->next) {
|
||||
et_parse_sctp_init_ack_chunk(doc, cur_node, sctp_hdr);
|
||||
}
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void et_parse_sctp(xmlDocPtr doc, const xmlNode const *sctp_node, et_sctp_hdr_t * const sctp_hdr)
|
||||
{
|
||||
xmlNode *cur_node = NULL;
|
||||
xmlChar *xml_char = NULL;
|
||||
xmlChar *xml_char2 = NULL;
|
||||
|
||||
if ((NULL != sctp_node) && (NULL != sctp_hdr)) {
|
||||
if ((!xmlStrcmp(sctp_node->name, (const xmlChar *)"proto"))) {
|
||||
xml_char = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"name");
|
||||
if (NULL != xml_char) {
|
||||
if ((!xmlStrcmp(xml_char, (const xmlChar *)"s1ap"))) {
|
||||
xmlFree(xml_char);
|
||||
xml_char = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"pos");
|
||||
if (NULL != xml_char) {
|
||||
sctp_hdr->u.data_hdr.payload.xml_stream_pos_offset = strtoul((const char *)xml_char, NULL, 0);
|
||||
xmlFree(xml_char);
|
||||
|
||||
xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"size");
|
||||
if (NULL != xml_char2) {
|
||||
sctp_hdr->u.data_hdr.payload.binary_stream_allocated_size = strtoul((const char *)xml_char2, NULL, 0);
|
||||
sctp_hdr->u.data_hdr.payload.binary_stream = calloc(1, sctp_hdr->u.data_hdr.payload.binary_stream_allocated_size);
|
||||
sctp_hdr->u.data_hdr.payload.binary_stream_pos = 0;
|
||||
fprintf(stdout, "Allocating payload of sctp_hdr %p %u bytes\n", sctp_hdr, sctp_hdr->u.data_hdr.payload.binary_stream_allocated_size);
|
||||
xmlFree(xml_char2);
|
||||
}
|
||||
et_parse_s1ap(doc, sctp_node, &sctp_hdr->u.data_hdr.payload);
|
||||
et_decode_s1ap(&sctp_hdr->u.data_hdr.payload);
|
||||
return;
|
||||
}
|
||||
}
|
||||
xmlFree(xml_char);
|
||||
}
|
||||
}
|
||||
//if ((cur_node->type == XML_ATTRIBUTE_NODE) || (cur_node->type == XML_ELEMENT_NODE)) {
|
||||
xml_char = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"name");
|
||||
if (NULL != xml_char) {
|
||||
if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.srcport"))) {
|
||||
xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"value");
|
||||
if (NULL != xml_char2) {
|
||||
sctp_hdr->src_port = strtoul((const char *)xml_char2, NULL, 16);
|
||||
xmlFree(xml_char2);
|
||||
}
|
||||
} else if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.dstport"))) {
|
||||
xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"value");
|
||||
if (NULL != xml_char2) {
|
||||
sctp_hdr->dst_port = strtoul((const char *)xml_char2, NULL, 16);
|
||||
xmlFree(xml_char2);
|
||||
}
|
||||
} else if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp.chunk_type"))) {
|
||||
xml_char2 = xmlGetProp((xmlNode *)sctp_node, (const xmlChar *)"value");
|
||||
if (NULL != xml_char2) {
|
||||
sctp_hdr->chunk_type = strtoul((const char *)xml_char2, NULL, 0);
|
||||
xmlFree(xml_char2);
|
||||
switch (sctp_hdr->chunk_type) {
|
||||
case SCTP_CID_DATA:
|
||||
et_parse_sctp_data_chunk(doc, sctp_node->parent, &sctp_hdr->u.data_hdr);
|
||||
break;
|
||||
case SCTP_CID_INIT:
|
||||
et_parse_sctp_init_chunk(doc, sctp_node->parent, &sctp_hdr->u.init_hdr);
|
||||
break;
|
||||
case SCTP_CID_INIT_ACK:
|
||||
et_parse_sctp_init_ack_chunk(doc, sctp_node->parent, &sctp_hdr->u.init_ack_hdr);
|
||||
break;
|
||||
default:
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (cur_node = sctp_node->children; cur_node; cur_node = cur_node->next) {
|
||||
et_parse_sctp(doc, cur_node, sctp_hdr);
|
||||
}
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void et_packet_shift_timing(et_packet_t * const packet, const struct timeval * const shift)
|
||||
{
|
||||
timeval_add(&packet->time_relative_to_first_packet, &packet->time_relative_to_first_packet, shift);
|
||||
AssertFatal((packet->time_relative_to_first_packet.tv_sec >= 0) && (packet->time_relative_to_first_packet.tv_usec >= 0),
|
||||
"Bad timing result time_relative_to_first_packet=%d.%d packet num %u, original frame number %u",
|
||||
packet->time_relative_to_first_packet.tv_sec,
|
||||
packet->time_relative_to_first_packet.tv_usec,
|
||||
packet->packet_number,
|
||||
packet->original_frame_number);
|
||||
|
||||
timeval_add(&packet->time_relative_to_last_received_packet, &packet->time_relative_to_last_received_packet, shift);
|
||||
AssertFatal((packet->time_relative_to_last_received_packet.tv_sec >= 0) && (packet->time_relative_to_last_received_packet.tv_usec >= 0),
|
||||
"Bad timing result time_relative_to_last_received_packet=%d.%d packet num %u, original frame number %u",
|
||||
packet->time_relative_to_last_received_packet.tv_sec,
|
||||
packet->time_relative_to_last_received_packet.tv_usec,
|
||||
packet->packet_number,
|
||||
packet->original_frame_number);
|
||||
|
||||
timeval_add(&packet->time_relative_to_last_sent_packet, &packet->time_relative_to_last_sent_packet, shift);
|
||||
AssertFatal((packet->time_relative_to_last_sent_packet.tv_sec >= 0) && (packet->time_relative_to_last_sent_packet.tv_usec >= 0),
|
||||
"Bad timing result time_relative_to_last_sent_packet=%d.%d packet num %u, original frame number %u",
|
||||
packet->time_relative_to_last_sent_packet.tv_sec,
|
||||
packet->time_relative_to_last_sent_packet.tv_usec,
|
||||
packet->packet_number,
|
||||
packet->original_frame_number);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
et_packet_t* et_parse_xml_packet(xmlDocPtr doc, xmlNodePtr node)
|
||||
{
|
||||
|
||||
et_packet_t *packet = NULL;
|
||||
xmlNode *cur_node = NULL;
|
||||
xmlChar *xml_char = NULL;
|
||||
float afloat = (float)0.0;
|
||||
static struct timeval initial_time = { .tv_sec = 0, .tv_usec = 0 };
|
||||
static struct timeval relative_last_sent_packet = { .tv_sec = 0, .tv_usec = 0 };
|
||||
static struct timeval relative_last_received_packet = { .tv_sec = 0, .tv_usec = 0 };
|
||||
static char first_packet = 1;
|
||||
static char first_sent_packet = 1;
|
||||
static char first_received_packet = 1;
|
||||
static unsigned int packet_number = 1;
|
||||
|
||||
|
||||
if (NULL != node) {
|
||||
packet = calloc(1, sizeof(*packet));
|
||||
|
||||
xml_char = xmlGetProp(node, (const xmlChar *)"action");
|
||||
packet->action = et_action_str2et_action_t(xml_char);
|
||||
packet->status = ET_PACKET_STATUS_NONE;
|
||||
xmlFree(xml_char);
|
||||
packet->packet_number = packet_number++;
|
||||
|
||||
for (cur_node = node->children; cur_node; cur_node = cur_node->next) {
|
||||
//if (cur_node->type == XML_ELEMENT_NODE) {
|
||||
if ((!xmlStrcmp(cur_node->name, (const xmlChar *)"frame.time_relative"))) {
|
||||
xml_char = xmlGetProp((xmlNode *)cur_node, (const xmlChar *)"value");
|
||||
afloat = atof((const char*)xml_char);
|
||||
xmlFree(xml_char);
|
||||
fprintf(stdout, "Parsing packet frame.time_relative: %f\n", afloat);
|
||||
packet->time_relative_to_first_packet.tv_sec = (int)afloat;
|
||||
packet->time_relative_to_first_packet.tv_usec = (int)((afloat - packet->time_relative_to_first_packet.tv_sec)*1000000.0);
|
||||
|
||||
if (first_packet > 0) {
|
||||
initial_time = packet->time_relative_to_first_packet;
|
||||
packet->time_relative_to_first_packet.tv_sec = 0;
|
||||
packet->time_relative_to_first_packet.tv_usec = 0;
|
||||
first_packet = 0;
|
||||
} else {
|
||||
timersub(&packet->time_relative_to_first_packet, &initial_time,
|
||||
&packet->time_relative_to_first_packet);
|
||||
}
|
||||
} else if ((!xmlStrcmp(cur_node->name, (const xmlChar *)"frame.number"))) {
|
||||
xml_char = xmlGetProp((xmlNode *)cur_node, (const xmlChar *)"value");
|
||||
packet->original_frame_number = strtoul((const char *)xml_char, NULL, 0);
|
||||
fprintf(stdout, "Parsing packet frame.number: %u\n", packet->original_frame_number);
|
||||
xmlFree(xml_char);
|
||||
} else if ((!xmlStrcmp(cur_node->name, (const xmlChar *)"ip.src"))) {
|
||||
xml_char = xmlNodeListGetString(doc, cur_node->xmlChildrenNode, 1);
|
||||
et_ip_str2et_ip(xml_char, &packet->ip_hdr.src);
|
||||
xmlFree(xml_char);
|
||||
} else if ((!xmlStrcmp(cur_node->name, (const xmlChar *)"ip.dst"))) {
|
||||
xml_char = xmlNodeListGetString(doc, cur_node->xmlChildrenNode, 1);
|
||||
et_ip_str2et_ip(xml_char, &packet->ip_hdr.dst);
|
||||
xmlFree(xml_char);
|
||||
} else if ((!xmlStrcmp(cur_node->name, (const xmlChar *)"proto"))) {
|
||||
xml_char = xmlGetProp((xmlNode *)cur_node, (const xmlChar *)"name");
|
||||
if (NULL != xml_char) {
|
||||
if ((!xmlStrcmp(xml_char, (const xmlChar *)"sctp"))) {
|
||||
et_parse_sctp(doc, cur_node, &packet->sctp_hdr);
|
||||
}
|
||||
xmlFree(xml_char);
|
||||
}
|
||||
} else if ((!xmlStrcmp(cur_node->name, (const xmlChar *)"eNB.instance"))) {
|
||||
xml_char = xmlGetProp((xmlNode *)cur_node, (const xmlChar *)"value");
|
||||
packet->enb_instance = strtoul((const char *)xml_char, NULL, 0);
|
||||
xmlFree(xml_char);
|
||||
}
|
||||
//}
|
||||
}
|
||||
}
|
||||
return packet;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
et_scenario_t* et_generate_scenario(
|
||||
const char * const tsml_out_scenario_filename)
|
||||
{
|
||||
xmlDocPtr doc = NULL;
|
||||
xmlNodePtr root = NULL;
|
||||
xmlNodePtr node = NULL;
|
||||
xmlChar *xml_char = NULL;
|
||||
et_scenario_t *scenario = NULL;
|
||||
et_packet_t *last_packet = NULL;
|
||||
et_packet_t *packet = NULL;
|
||||
et_packet_t **next_packet = NULL;
|
||||
|
||||
doc = xmlParseFile(tsml_out_scenario_filename);
|
||||
if (NULL == doc) {
|
||||
AssertFatal (0, "Could not parse scenario xml file %s!\n", tsml_out_scenario_filename);
|
||||
} else {
|
||||
fprintf(stdout, "Test scenario file to play: %s\n", tsml_out_scenario_filename);
|
||||
//xmlDebugDumpDocument(NULL, doc);
|
||||
}
|
||||
|
||||
// Get root
|
||||
root = xmlDocGetRootElement(doc);
|
||||
if (NULL != root) {
|
||||
if ((!xmlStrcmp(root->name, (const xmlChar *)"scenario"))) {
|
||||
xml_char = xmlGetProp(root, (const xmlChar *)"name");
|
||||
printf("scenario name: %s\n", xml_char);
|
||||
scenario = calloc(1, sizeof(*scenario));
|
||||
scenario->name = xml_char; // nodup nofree
|
||||
|
||||
next_packet = &scenario->list_packet;
|
||||
for (node = root->children; node != NULL; node = node->next) {
|
||||
if ((!xmlStrcmp(node->name, (const xmlChar *)"packet"))) {
|
||||
packet = et_parse_xml_packet(doc, node);
|
||||
if (NULL != packet) {
|
||||
// special case: S1AP same frame for 2 packets
|
||||
if (NULL != last_packet) {
|
||||
if (last_packet->original_frame_number == packet->original_frame_number) {
|
||||
// updating because these informations are not in 2nd sctp header (same IP packet)
|
||||
packet->sctp_hdr.dst_port = last_packet->sctp_hdr.dst_port;
|
||||
packet->sctp_hdr.src_port = last_packet->sctp_hdr.src_port;
|
||||
}
|
||||
}
|
||||
*next_packet = packet;
|
||||
next_packet = &packet->next;
|
||||
} else {
|
||||
fprintf(stdout, "WARNING omitted packet\n");
|
||||
}
|
||||
}
|
||||
last_packet = packet;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Empty xml document\n");
|
||||
}
|
||||
xmlFreeDoc(doc);
|
||||
xmlCleanupParser();
|
||||
return scenario;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
int et_generate_xml_scenario(
|
||||
const char const * xml_in_dir_name,
|
||||
const char const * xml_in_scenario_filename,
|
||||
const char const * enb_config_filename,
|
||||
char const * tsml_out_scenario_filename)
|
||||
//------------------------------------------------------------------------------
|
||||
{
|
||||
//int fd_pdml_in;
|
||||
xsltStylesheetPtr cur = NULL;
|
||||
xmlDocPtr doc, res;
|
||||
FILE *play_scenario_file = NULL;
|
||||
const char *params[2*ENB_CONFIG_MAX_XSLT_PARAMS];
|
||||
int nb_params = 0;
|
||||
int i,j;
|
||||
char astring[1024];
|
||||
struct in_addr addr;
|
||||
int ret = 0;
|
||||
|
||||
memset(astring, 0, sizeof(astring));
|
||||
if (getcwd(astring, sizeof(astring)) != NULL) {
|
||||
fprintf(stdout, "working in %s directory\n", astring);
|
||||
} else {
|
||||
perror("getcwd() ERROR");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
xmlSubstituteEntitiesDefault(1);
|
||||
xmlLoadExtDtdDefaultValue = 1;
|
||||
cur = xsltParseStylesheetFile((const xmlChar *)"/usr/share/oai/xsl/play_scenario.xsl");
|
||||
if (NULL == cur) {
|
||||
AssertFatal (0, "Could not parse stylesheet file /usr/share/oai/xsl/play_scenario.xsl!\n");
|
||||
} else {
|
||||
fprintf(stdout, "XSLT style sheet: /usr/share/oai/xsl/play_scenario.xsl\n");
|
||||
}
|
||||
|
||||
doc = xmlParseFile(xml_in_scenario_filename);
|
||||
if (NULL == doc) {
|
||||
AssertFatal (0, "Could not parse scenario xml file %s!\n", xml_in_scenario_filename);
|
||||
} else {
|
||||
fprintf(stdout, "Test scenario file: %s\n", xml_in_scenario_filename);
|
||||
}
|
||||
|
||||
for (i = 0; i < g_enb_properties.number; i++) {
|
||||
// eNB S1-C IPv4 address
|
||||
sprintf(astring, "enb%d_s1c", i);
|
||||
params[nb_params++] = strdup(astring);
|
||||
addr.s_addr = g_enb_properties.properties[i]->enb_ipv4_address_for_S1_MME;
|
||||
sprintf(astring, "\"%s\"", inet_ntoa(addr));
|
||||
params[nb_params++] = strdup(astring);
|
||||
|
||||
// MME S1-C IPv4 address
|
||||
for (j = 0; j < g_enb_properties.properties[i]->nb_mme; j++) {
|
||||
sprintf(astring, "mme%d_s1c_%d", i, j);
|
||||
params[nb_params++] = strdup(astring);
|
||||
AssertFatal (g_enb_properties.properties[i]->mme_ip_address[j].ipv4_address,
|
||||
"Only support MME IPv4 address\n");
|
||||
sprintf(astring, "\"%s\"", g_enb_properties.properties[i]->mme_ip_address[j].ipv4_address);
|
||||
params[nb_params++] = strdup(astring);
|
||||
}
|
||||
}
|
||||
params[nb_params] = NULL;
|
||||
res = xsltApplyStylesheet(cur, doc, params);
|
||||
if (NULL != res) {
|
||||
sprintf((char *)tsml_out_scenario_filename,"%s",xml_in_scenario_filename);
|
||||
if (et_strip_extension((char *)tsml_out_scenario_filename) > 0) {
|
||||
strcat((char *)tsml_out_scenario_filename, ".tsml");
|
||||
play_scenario_file = fopen( tsml_out_scenario_filename, "w+");
|
||||
if (NULL != play_scenario_file) {
|
||||
xsltSaveResultToFile(play_scenario_file, res, cur);
|
||||
fclose(play_scenario_file);
|
||||
fprintf(stdout, "Wrote test scenario to %s\n", tsml_out_scenario_filename);
|
||||
} else {
|
||||
fprintf(stderr, "ERROR in fopen(%s)\n", tsml_out_scenario_filename);
|
||||
ret = -1;
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "ERROR in strip_extension()\n");
|
||||
ret = -1;
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "ERROR in xsltApplyStylesheet()\n");
|
||||
ret = -1;
|
||||
}
|
||||
xsltFreeStylesheet(cur);
|
||||
xmlFreeDoc(doc);
|
||||
xmlFreeDoc(res);
|
||||
|
||||
xsltCleanupGlobals();
|
||||
xmlCleanupParser();
|
||||
return ret;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,634 @@
|
||||
/*******************************************************************************
|
||||
OpenAirInterface
|
||||
Copyright(c) 1999 - 2014 Eurecom
|
||||
|
||||
OpenAirInterface is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
|
||||
OpenAirInterface is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenAirInterface.The full GNU General Public License is
|
||||
included in this distribution in the file called "COPYING". If not,
|
||||
see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Contact Information
|
||||
OpenAirInterface Admin: openair_admin@eurecom.fr
|
||||
OpenAirInterface Tech : openair_tech@eurecom.fr
|
||||
OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr
|
||||
|
||||
Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
/*
|
||||
play_scenario_s1ap_compare_ie.c
|
||||
-------------------
|
||||
AUTHOR : Lionel GAUTHIER
|
||||
COMPANY : EURECOM
|
||||
EMAIL : Lionel.Gauthier@eurecom.fr
|
||||
*/
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stdarg.h>
|
||||
#include <unistd.h>
|
||||
#include <crypt.h>
|
||||
#include <errno.h>
|
||||
#include <libxml/tree.h>
|
||||
#include <libxml/parser.h>
|
||||
#include <libxml/xpath.h>
|
||||
#include <libxml/xpathInternals.h>
|
||||
#include "tree.h"
|
||||
#include "queue.h"
|
||||
|
||||
|
||||
#include "intertask_interface.h"
|
||||
#include "timer.h"
|
||||
#include "platform_types.h"
|
||||
#include "assertions.h"
|
||||
#include "conversions.h"
|
||||
#include "s1ap_common.h"
|
||||
#include "play_scenario_s1ap_eNB_defs.h"
|
||||
#include "play_scenario.h"
|
||||
#include "msc.h"
|
||||
//------------------------------------------------------------------------------
|
||||
extern et_scenario_t *g_scenario;
|
||||
extern uint32_t g_constraints;
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
asn_comp_rval_t * et_s1ap_ies_is_matching(const S1AP_PDU_PR present, s1ap_message * const m1, s1ap_message * const m2, const uint32_t constraints)
|
||||
{
|
||||
asn_comp_rval_t *ret = NULL;
|
||||
AssertFatal(m1 != NULL, "bad parameter m1");
|
||||
AssertFatal(m2 != NULL, "bad parameter m2");
|
||||
AssertFatal((present == S1AP_PDU_PR_initiatingMessage) ||
|
||||
(present == S1AP_PDU_PR_successfulOutcome) ||
|
||||
(present == S1AP_PDU_PR_unsuccessfulOutcome) , "Bad parameter S1AP_PDU_PR present ");
|
||||
AssertFatal( m1->procedureCode == m2->procedureCode, "Bad parameters: no matching procedure codes");
|
||||
|
||||
|
||||
// some cases can never occur since uplink only.
|
||||
switch (m1->procedureCode) {
|
||||
case S1ap_ProcedureCode_id_HandoverPreparation:
|
||||
if (present == S1AP_PDU_PR_initiatingMessage) {
|
||||
ret = s1ap_compare_s1ap_handoverrequiredies(
|
||||
&m1->msg.s1ap_HandoverRequiredIEs,
|
||||
&m2->msg.s1ap_HandoverRequiredIEs);
|
||||
} else {
|
||||
ret = s1ap_compare_s1ap_handovercommandies(
|
||||
&m1->msg.s1ap_HandoverCommandIEs,
|
||||
&m2->msg.s1ap_HandoverCommandIEs);
|
||||
}
|
||||
break;
|
||||
|
||||
case S1ap_ProcedureCode_id_HandoverResourceAllocation:
|
||||
if (present == S1AP_PDU_PR_initiatingMessage) {
|
||||
ret = s1ap_compare_s1ap_handoverrequesties(
|
||||
&m1->msg.s1ap_HandoverRequestIEs,
|
||||
&m2->msg.s1ap_HandoverRequestIEs);
|
||||
} else if (present == S1AP_PDU_PR_successfulOutcome) {
|
||||
ret = s1ap_compare_s1ap_handoverrequestacknowledgeies(
|
||||
&m1->msg.s1ap_HandoverRequestAcknowledgeIEs,
|
||||
&m2->msg.s1ap_HandoverRequestAcknowledgeIEs);
|
||||
} else if (present == S1AP_PDU_PR_unsuccessfulOutcome) {
|
||||
ret = s1ap_compare_s1ap_handoverfailureies(
|
||||
&m1->msg.s1ap_HandoverFailureIEs,
|
||||
&m2->msg.s1ap_HandoverFailureIEs);
|
||||
}
|
||||
break;
|
||||
|
||||
case S1ap_ProcedureCode_id_HandoverNotification:
|
||||
ret = s1ap_compare_s1ap_handovernotifyies(
|
||||
&m1->msg.s1ap_HandoverNotifyIEs,
|
||||
&m2->msg.s1ap_HandoverNotifyIEs);
|
||||
break;
|
||||
|
||||
case S1ap_ProcedureCode_id_PathSwitchRequest:
|
||||
ret = s1ap_compare_s1ap_pathswitchrequesties(
|
||||
&m1->msg.s1ap_PathSwitchRequestIEs,
|
||||
&m2->msg.s1ap_PathSwitchRequestIEs);
|
||||
break;
|
||||
|
||||
case S1ap_ProcedureCode_id_HandoverCancel:
|
||||
ret = s1ap_compare_s1ap_handovercancelies(
|
||||
&m1->msg.s1ap_HandoverCancelIEs,
|
||||
&m2->msg.s1ap_HandoverCancelIEs);
|
||||
break;
|
||||
|
||||
case S1ap_ProcedureCode_id_E_RABSetup:
|
||||
if (present == S1AP_PDU_PR_initiatingMessage) {
|
||||
ret = s1ap_compare_s1ap_e_rabsetuprequesties(
|
||||
&m1->msg.s1ap_E_RABSetupRequestIEs,
|
||||
&m2->msg.s1ap_E_RABSetupRequestIEs);
|
||||
} else {
|
||||
ret = s1ap_compare_s1ap_e_rabsetupresponseies(
|
||||
&m1->msg.s1ap_E_RABSetupResponseIEs,
|
||||
&m2->msg.s1ap_E_RABSetupResponseIEs);
|
||||
}
|
||||
break;
|
||||
|
||||
case S1ap_ProcedureCode_id_E_RABModify:
|
||||
if (present == S1AP_PDU_PR_initiatingMessage) {
|
||||
ret = s1ap_compare_s1ap_e_rabmodifyrequesties(
|
||||
&m1->msg.s1ap_E_RABModifyRequestIEs,
|
||||
&m2->msg.s1ap_E_RABModifyRequestIEs);
|
||||
} else {
|
||||
ret = s1ap_compare_s1ap_e_rabmodifyresponseies(
|
||||
&m1->msg.s1ap_E_RABModifyResponseIEs,
|
||||
&m2->msg.s1ap_E_RABModifyResponseIEs);
|
||||
}
|
||||
break;
|
||||
|
||||
case S1ap_ProcedureCode_id_E_RABRelease:
|
||||
if (present == S1AP_PDU_PR_initiatingMessage) {
|
||||
ret = s1ap_compare_s1ap_e_rabreleasecommandies(
|
||||
&m1->msg.s1ap_E_RABReleaseCommandIEs,
|
||||
&m2->msg.s1ap_E_RABReleaseCommandIEs);
|
||||
} else {
|
||||
ret = s1ap_compare_s1ap_e_rabreleaseresponseies(
|
||||
&m1->msg.s1ap_E_RABReleaseResponseIEs,
|
||||
&m2->msg.s1ap_E_RABReleaseResponseIEs);
|
||||
}
|
||||
break;
|
||||
|
||||
case S1ap_ProcedureCode_id_E_RABReleaseIndication:
|
||||
ret = s1ap_compare_s1ap_e_rabreleaseindicationies(
|
||||
&m1->msg.s1ap_E_RABReleaseIndicationIEs,
|
||||
&m2->msg.s1ap_E_RABReleaseIndicationIEs);
|
||||
break;
|
||||
|
||||
case S1ap_ProcedureCode_id_InitialContextSetup:
|
||||
if (present == S1AP_PDU_PR_initiatingMessage) {
|
||||
ret = s1ap_compare_s1ap_initialcontextsetuprequesties(
|
||||
&m1->msg.s1ap_InitialContextSetupRequestIEs,
|
||||
&m2->msg.s1ap_InitialContextSetupRequestIEs);
|
||||
} else {
|
||||
ret = s1ap_compare_s1ap_initialcontextsetupresponseies(
|
||||
&m1->msg.s1ap_InitialContextSetupResponseIEs,
|
||||
&m2->msg.s1ap_InitialContextSetupResponseIEs);
|
||||
}
|
||||
break;
|
||||
|
||||
case S1ap_ProcedureCode_id_Paging:
|
||||
ret = s1ap_compare_s1ap_pagingies(
|
||||
&m1->msg.s1ap_PagingIEs,
|
||||
&m2->msg.s1ap_PagingIEs);
|
||||
break;
|
||||
|
||||
case S1ap_ProcedureCode_id_downlinkNASTransport:
|
||||
ret = s1ap_compare_s1ap_downlinknastransporties(
|
||||
&m1->msg.s1ap_DownlinkNASTransportIEs,
|
||||
&m2->msg.s1ap_DownlinkNASTransportIEs);
|
||||
break;
|
||||
|
||||
case S1ap_ProcedureCode_id_initialUEMessage:
|
||||
ret = s1ap_compare_s1ap_initialuemessageies(
|
||||
&m1->msg.s1ap_InitialUEMessageIEs,
|
||||
&m2->msg.s1ap_InitialUEMessageIEs);
|
||||
break;
|
||||
|
||||
case S1ap_ProcedureCode_id_uplinkNASTransport:
|
||||
ret = s1ap_compare_s1ap_uplinknastransporties(
|
||||
&m1->msg.s1ap_UplinkNASTransportIEs,
|
||||
&m2->msg.s1ap_UplinkNASTransportIEs);
|
||||
break;
|
||||
|
||||
case S1ap_ProcedureCode_id_Reset:
|
||||
ret = s1ap_compare_s1ap_reseties(
|
||||
&m1->msg.s1ap_ResetIEs,
|
||||
&m2->msg.s1ap_ResetIEs);
|
||||
break;
|
||||
|
||||
case S1ap_ProcedureCode_id_ErrorIndication:
|
||||
ret = s1ap_compare_s1ap_errorindicationies(
|
||||
&m1->msg.s1ap_ErrorIndicationIEs,
|
||||
&m2->msg.s1ap_ErrorIndicationIEs);
|
||||
break;
|
||||
|
||||
case S1ap_ProcedureCode_id_NASNonDeliveryIndication:
|
||||
ret = s1ap_compare_s1ap_nasnondeliveryindication_ies(
|
||||
&m1->msg.s1ap_NASNonDeliveryIndication_IEs,
|
||||
&m2->msg.s1ap_NASNonDeliveryIndication_IEs);
|
||||
break;
|
||||
|
||||
case S1ap_ProcedureCode_id_S1Setup:
|
||||
if (present == S1AP_PDU_PR_initiatingMessage) {
|
||||
ret = s1ap_compare_s1ap_s1setuprequesties(
|
||||
&m1->msg.s1ap_S1SetupRequestIEs,
|
||||
&m2->msg.s1ap_S1SetupRequestIEs);
|
||||
} else if (present == S1AP_PDU_PR_successfulOutcome) {
|
||||
ret = s1ap_compare_s1ap_s1setupresponseies(
|
||||
&m1->msg.s1ap_S1SetupResponseIEs,
|
||||
&m2->msg.s1ap_S1SetupResponseIEs);
|
||||
} else if (present == S1AP_PDU_PR_unsuccessfulOutcome) {
|
||||
ret = s1ap_compare_s1ap_s1setupfailureies(
|
||||
&m1->msg.s1ap_S1SetupFailureIEs,
|
||||
&m2->msg.s1ap_S1SetupFailureIEs);
|
||||
}
|
||||
break;
|
||||
|
||||
case S1ap_ProcedureCode_id_UEContextReleaseRequest:
|
||||
ret = s1ap_compare_s1ap_uecontextreleaserequesties(
|
||||
&m1->msg.s1ap_UEContextReleaseRequestIEs,
|
||||
&m2->msg.s1ap_UEContextReleaseRequestIEs);
|
||||
break;
|
||||
|
||||
case S1ap_ProcedureCode_id_DownlinkS1cdma2000tunneling:
|
||||
ret = s1ap_compare_s1ap_downlinks1cdma2000tunnelingies(
|
||||
&m1->msg.s1ap_DownlinkS1cdma2000tunnelingIEs,
|
||||
&m2->msg.s1ap_DownlinkS1cdma2000tunnelingIEs);
|
||||
break;
|
||||
|
||||
case S1ap_ProcedureCode_id_UplinkS1cdma2000tunneling:
|
||||
ret = s1ap_compare_s1ap_uplinks1cdma2000tunnelingies(
|
||||
&m1->msg.s1ap_UplinkS1cdma2000tunnelingIEs,
|
||||
&m2->msg.s1ap_UplinkS1cdma2000tunnelingIEs);
|
||||
break;
|
||||
|
||||
case S1ap_ProcedureCode_id_UEContextModification:
|
||||
if (present == S1AP_PDU_PR_initiatingMessage) {
|
||||
ret = s1ap_compare_s1ap_uecontextmodificationrequesties(
|
||||
&m1->msg.s1ap_UEContextModificationRequestIEs,
|
||||
&m2->msg.s1ap_UEContextModificationRequestIEs);
|
||||
} else if (present == S1AP_PDU_PR_successfulOutcome) {
|
||||
ret = s1ap_compare_s1ap_uecontextmodificationresponseies(
|
||||
&m1->msg.s1ap_UEContextModificationResponseIEs,
|
||||
&m2->msg.s1ap_UEContextModificationResponseIEs);
|
||||
} else if (present == S1AP_PDU_PR_unsuccessfulOutcome) {
|
||||
ret = s1ap_compare_s1ap_uecontextmodificationfailureies(
|
||||
&m1->msg.s1ap_UEContextModificationFailureIEs,
|
||||
&m2->msg.s1ap_UEContextModificationFailureIEs);
|
||||
}
|
||||
break;
|
||||
|
||||
case S1ap_ProcedureCode_id_UECapabilityInfoIndication:
|
||||
ret = s1ap_compare_s1ap_uecapabilityinfoindicationies(
|
||||
&m1->msg.s1ap_UECapabilityInfoIndicationIEs,
|
||||
&m2->msg.s1ap_UECapabilityInfoIndicationIEs);
|
||||
break;
|
||||
|
||||
case S1ap_ProcedureCode_id_UEContextRelease:
|
||||
if (present == S1AP_PDU_PR_initiatingMessage) {
|
||||
ret = s1ap_compare_s1ap_uecontextreleasecommandies(
|
||||
&m1->msg.s1ap_UEContextReleaseCommandIEs,
|
||||
&m2->msg.s1ap_UEContextReleaseCommandIEs);
|
||||
} else {
|
||||
ret = s1ap_compare_s1ap_uecontextreleasecompleteies(
|
||||
&m1->msg.s1ap_UEContextReleaseCompleteIEs,
|
||||
&m2->msg.s1ap_UEContextReleaseCompleteIEs);
|
||||
}
|
||||
break;
|
||||
|
||||
case S1ap_ProcedureCode_id_eNBStatusTransfer:
|
||||
ret = s1ap_compare_s1ap_enbstatustransferies(
|
||||
&m1->msg.s1ap_ENBStatusTransferIEs,
|
||||
&m2->msg.s1ap_ENBStatusTransferIEs);
|
||||
break;
|
||||
|
||||
case S1ap_ProcedureCode_id_MMEStatusTransfer:
|
||||
ret = s1ap_compare_s1ap_mmestatustransferies(
|
||||
&m1->msg.s1ap_MMEStatusTransferIEs,
|
||||
&m2->msg.s1ap_MMEStatusTransferIEs);
|
||||
break;
|
||||
|
||||
case S1ap_ProcedureCode_id_DeactivateTrace:
|
||||
ret = s1ap_compare_s1ap_deactivatetraceies(
|
||||
&m1->msg.s1ap_DeactivateTraceIEs,
|
||||
&m2->msg.s1ap_DeactivateTraceIEs);
|
||||
break;
|
||||
|
||||
case S1ap_ProcedureCode_id_TraceStart:
|
||||
ret = s1ap_compare_s1ap_tracestarties(
|
||||
&m1->msg.s1ap_TraceStartIEs,
|
||||
&m2->msg.s1ap_TraceStartIEs);
|
||||
break;
|
||||
|
||||
case S1ap_ProcedureCode_id_TraceFailureIndication:
|
||||
ret = s1ap_compare_s1ap_tracefailureindicationies(
|
||||
&m1->msg.s1ap_TraceFailureIndicationIEs,
|
||||
&m2->msg.s1ap_TraceFailureIndicationIEs);
|
||||
break;
|
||||
|
||||
case S1ap_ProcedureCode_id_ENBConfigurationUpdate:
|
||||
if (present == S1AP_PDU_PR_initiatingMessage) {
|
||||
ret = s1ap_compare_s1ap_enbconfigurationupdateies(
|
||||
&m1->msg.s1ap_ENBConfigurationUpdateIEs,
|
||||
&m2->msg.s1ap_ENBConfigurationUpdateIEs);
|
||||
} else if (present == S1AP_PDU_PR_successfulOutcome) {
|
||||
ret = s1ap_compare_s1ap_enbconfigurationupdateacknowledgeies(
|
||||
&m1->msg.s1ap_ENBConfigurationUpdateAcknowledgeIEs,
|
||||
&m2->msg.s1ap_ENBConfigurationUpdateAcknowledgeIEs);
|
||||
} else {
|
||||
ret = s1ap_compare_s1ap_enbconfigurationupdatefailureies(
|
||||
&m1->msg.s1ap_ENBConfigurationUpdateFailureIEs,
|
||||
&m2->msg.s1ap_ENBConfigurationUpdateFailureIEs);
|
||||
}
|
||||
break;
|
||||
|
||||
case S1ap_ProcedureCode_id_MMEConfigurationUpdate:
|
||||
if (present == S1AP_PDU_PR_initiatingMessage) {
|
||||
ret = s1ap_compare_s1ap_mmeconfigurationupdateies(
|
||||
&m1->msg.s1ap_MMEConfigurationUpdateIEs,
|
||||
&m2->msg.s1ap_MMEConfigurationUpdateIEs);
|
||||
} else if (present == S1AP_PDU_PR_successfulOutcome) {
|
||||
ret = s1ap_compare_s1ap_mmeconfigurationupdateacknowledgeies(
|
||||
&m1->msg.s1ap_MMEConfigurationUpdateAcknowledgeIEs,
|
||||
&m2->msg.s1ap_MMEConfigurationUpdateAcknowledgeIEs);
|
||||
} else {
|
||||
ret = s1ap_compare_s1ap_mmeconfigurationupdatefailureies(
|
||||
&m1->msg.s1ap_MMEConfigurationUpdateFailureIEs,
|
||||
&m2->msg.s1ap_MMEConfigurationUpdateFailureIEs);
|
||||
}
|
||||
break;
|
||||
|
||||
case S1ap_ProcedureCode_id_LocationReportingControl:
|
||||
ret = s1ap_compare_s1ap_locationreportingcontrolies(
|
||||
&m1->msg.s1ap_LocationReportingControlIEs,
|
||||
&m2->msg.s1ap_LocationReportingControlIEs);
|
||||
break;
|
||||
|
||||
case S1ap_ProcedureCode_id_LocationReportingFailureIndication:
|
||||
ret = s1ap_compare_s1ap_locationreportingfailureindicationies(
|
||||
&m1->msg.s1ap_LocationReportingFailureIndicationIEs,
|
||||
&m2->msg.s1ap_LocationReportingFailureIndicationIEs);
|
||||
break;
|
||||
|
||||
case S1ap_ProcedureCode_id_LocationReport:
|
||||
ret = s1ap_compare_s1ap_locationreporties(
|
||||
&m1->msg.s1ap_LocationReportIEs,
|
||||
&m2->msg.s1ap_LocationReportIEs);
|
||||
break;
|
||||
|
||||
case S1ap_ProcedureCode_id_OverloadStart:
|
||||
ret = s1ap_compare_s1ap_overloadstarties(
|
||||
&m1->msg.s1ap_OverloadStartIEs,
|
||||
&m2->msg.s1ap_OverloadStartIEs);
|
||||
break;
|
||||
|
||||
case S1ap_ProcedureCode_id_OverloadStop:
|
||||
ret = s1ap_compare_s1ap_overloadstopies(
|
||||
&m1->msg.s1ap_OverloadStopIEs,
|
||||
&m2->msg.s1ap_OverloadStopIEs);
|
||||
break;
|
||||
|
||||
case S1ap_ProcedureCode_id_WriteReplaceWarning:
|
||||
if (present == S1AP_PDU_PR_initiatingMessage) {
|
||||
ret = s1ap_compare_s1ap_writereplacewarningrequesties(
|
||||
&m1->msg.s1ap_WriteReplaceWarningRequestIEs,
|
||||
&m2->msg.s1ap_WriteReplaceWarningRequestIEs);
|
||||
} else {
|
||||
ret = s1ap_compare_s1ap_writereplacewarningresponseies(
|
||||
&m1->msg.s1ap_WriteReplaceWarningResponseIEs,
|
||||
&m2->msg.s1ap_WriteReplaceWarningResponseIEs);
|
||||
}
|
||||
break;
|
||||
|
||||
case S1ap_ProcedureCode_id_eNBDirectInformationTransfer:
|
||||
ret = s1ap_compare_s1ap_enbdirectinformationtransferies(
|
||||
&m1->msg.s1ap_ENBDirectInformationTransferIEs,
|
||||
&m2->msg.s1ap_ENBDirectInformationTransferIEs);
|
||||
break;
|
||||
|
||||
case S1ap_ProcedureCode_id_MMEDirectInformationTransfer:
|
||||
|
||||
ret = s1ap_compare_s1ap_mmedirectinformationtransferies(
|
||||
&m1->msg.s1ap_MMEDirectInformationTransferIEs,
|
||||
&m2->msg.s1ap_MMEDirectInformationTransferIEs);
|
||||
break;
|
||||
|
||||
case S1ap_ProcedureCode_id_PrivateMessage:
|
||||
case S1ap_ProcedureCode_id_eNBConfigurationTransfer:
|
||||
case S1ap_ProcedureCode_id_MMEConfigurationTransfer:
|
||||
AssertFatal(0, "TODO");
|
||||
break;
|
||||
|
||||
case S1ap_ProcedureCode_id_CellTrafficTrace:
|
||||
ret = s1ap_compare_s1ap_celltraffictraceies(
|
||||
&m1->msg.s1ap_CellTrafficTraceIEs,
|
||||
&m2->msg.s1ap_CellTrafficTraceIEs);
|
||||
break;
|
||||
|
||||
case S1ap_ProcedureCode_id_Kill:
|
||||
if (present == S1AP_PDU_PR_initiatingMessage) {
|
||||
ret = s1ap_compare_s1ap_killrequesties(
|
||||
&m1->msg.s1ap_KillRequestIEs,
|
||||
&m2->msg.s1ap_KillRequestIEs);
|
||||
} else {
|
||||
ret = s1ap_compare_s1ap_killresponseies(
|
||||
&m1->msg.s1ap_KillResponseIEs,
|
||||
&m2->msg.s1ap_KillResponseIEs);
|
||||
}
|
||||
break;
|
||||
|
||||
case S1ap_ProcedureCode_id_downlinkUEAssociatedLPPaTransport:
|
||||
ret = s1ap_compare_s1ap_downlinkueassociatedlppatransport_ies(
|
||||
&m1->msg.s1ap_DownlinkUEAssociatedLPPaTransport_IEs,
|
||||
&m2->msg.s1ap_DownlinkUEAssociatedLPPaTransport_IEs);
|
||||
break;
|
||||
|
||||
case S1ap_ProcedureCode_id_uplinkUEAssociatedLPPaTransport:
|
||||
ret = s1ap_compare_s1ap_uplinkueassociatedlppatransport_ies(
|
||||
&m1->msg.s1ap_UplinkUEAssociatedLPPaTransport_IEs,
|
||||
&m2->msg.s1ap_UplinkUEAssociatedLPPaTransport_IEs);
|
||||
break;
|
||||
|
||||
case S1ap_ProcedureCode_id_downlinkNonUEAssociatedLPPaTransport:
|
||||
ret = s1ap_compare_s1ap_downlinknonueassociatedlppatransport_ies(
|
||||
&m1->msg.s1ap_DownlinkNonUEAssociatedLPPaTransport_IEs,
|
||||
&m2->msg.s1ap_DownlinkNonUEAssociatedLPPaTransport_IEs);
|
||||
break;
|
||||
|
||||
case S1ap_ProcedureCode_id_uplinkNonUEAssociatedLPPaTransport:
|
||||
ret = s1ap_compare_s1ap_uplinknonueassociatedlppatransport_ies(
|
||||
&m1->msg.s1ap_UplinkNonUEAssociatedLPPaTransport_IEs,
|
||||
&m2->msg.s1ap_UplinkNonUEAssociatedLPPaTransport_IEs);
|
||||
break;
|
||||
|
||||
default:
|
||||
AssertFatal(0, "Unknown procedure code %ld", m1->procedureCode);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void update_xpath_node_mme_ue_s1ap_id(et_s1ap_t * const s1ap, xmlNode *node, const S1ap_MME_UE_S1AP_ID_t new_id)
|
||||
{
|
||||
xmlNode *cur_node = NULL;
|
||||
xmlAttrPtr attr = NULL;
|
||||
xmlChar *xml_char = NULL;
|
||||
int size = 0;
|
||||
int pos = 0;
|
||||
int go_deeper_in_tree = 1;
|
||||
//S1AP_INFO("%s() mme_ue_s1ap_id %u\n", __FUNCTION__, new_id);
|
||||
|
||||
// modify
|
||||
for (cur_node = (xmlNode *)node; cur_node; cur_node = cur_node->next) {
|
||||
go_deeper_in_tree = 1;
|
||||
if ((!xmlStrcmp(cur_node->name, (const xmlChar *)"field"))) {
|
||||
// do not get hidden fields
|
||||
xml_char = xmlGetProp((xmlNode *)cur_node, (const xmlChar *)"hide");
|
||||
if (NULL != xml_char) {
|
||||
if ((!xmlStrcmp(xml_char, (const xmlChar *)"yes"))) {
|
||||
go_deeper_in_tree = 0;
|
||||
}
|
||||
xmlFree(xml_char);
|
||||
}
|
||||
if (0 < go_deeper_in_tree) {
|
||||
// first get size
|
||||
xml_char = xmlGetProp((xmlNode *)cur_node, (const xmlChar *)"pos");
|
||||
if (NULL != xml_char) {
|
||||
pos = strtoul((const char *)xml_char, NULL, 0);
|
||||
pos -= s1ap->xml_stream_pos_offset;
|
||||
AssertFatal(pos >= 0, "Bad pos %d xml_stream_pos_offset %d", pos, s1ap->xml_stream_pos_offset);
|
||||
xmlFree(xml_char);
|
||||
xml_char = xmlGetProp((xmlNode *)cur_node, (const xmlChar *)"size");
|
||||
if (NULL != xml_char) {
|
||||
const xmlChar value_d[32];
|
||||
const xmlChar value_h[20];
|
||||
const xmlChar showname[64];
|
||||
int ret = 0;
|
||||
int pos2 = 0;
|
||||
unsigned long int uli = 0;
|
||||
char hex[3] = {0,0,0};
|
||||
char *end_ptr = NULL;
|
||||
|
||||
size = strtoul((const char *)xml_char, NULL, 0);
|
||||
xmlFree(xml_char);
|
||||
// second: try to set value (always hex)
|
||||
ret = snprintf((char *)value_d, 32, "%ld", new_id);
|
||||
AssertFatal((ret > 0) && (ret < 32), "Could not convert int to dec str");
|
||||
ret = snprintf((char *)value_h, 20, "C0%08X", new_id);
|
||||
AssertFatal((ret > 0) && (ret < 20), "Could not convert int to hex str");
|
||||
ret = snprintf((char *)showname, 64, "MME-UE-S1AP-ID: %d", new_id);
|
||||
AssertFatal((ret > 0) && (ret < 64), "Could not convert int to dec str");
|
||||
|
||||
attr = xmlSetProp((xmlNode *)cur_node, (const xmlChar *)"value", value_h);
|
||||
attr = xmlSetProp((xmlNode *)cur_node, (const xmlChar *)"show", value_d);
|
||||
attr = xmlSetProp((xmlNode *)cur_node, (const xmlChar *)"showname", showname);
|
||||
//TODO update s1ap->binary_stream @pos with new_id_hex, size
|
||||
AssertFatal((pos+size) < s1ap->binary_stream_allocated_size, "Rewrite of mme_ue_s1ap_id out of bounds of binary_stream");
|
||||
//avoid endianess issues
|
||||
do {
|
||||
hex[0] = value_h[pos2++];
|
||||
hex[1] = value_h[pos2++];
|
||||
hex[2] = '\0';
|
||||
end_ptr = hex;
|
||||
uli = strtoul(hex, &end_ptr, 16);
|
||||
AssertFatal((uli != ULONG_MAX) && (end_ptr != NULL) && (*end_ptr == '\0'), "Conversion of hexstring %s failed returned %ld errno %d", hex, uli, errno);
|
||||
s1ap->binary_stream[pos++] = (unsigned char)uli;
|
||||
} while (pos2 < (2*5));
|
||||
// update ASN1
|
||||
et_decode_s1ap(s1ap);
|
||||
//S1AP_INFO("Updated ASN1 for %s\n", showname);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (0 < go_deeper_in_tree) {
|
||||
update_xpath_node_mme_ue_s1ap_id(s1ap, cur_node->children, new_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* update_xpath_nodes:
|
||||
* @nodes: the nodes set.
|
||||
* @value: the new value for the node(s)
|
||||
*
|
||||
* Prints the @nodes content to @output.
|
||||
* From http://www.xmlsoft.org/examples/#xpath2.c
|
||||
*/
|
||||
void update_xpath_nodes_mme_ue_s1ap_id(et_s1ap_t * const s1ap_payload, xmlNodeSetPtr nodes, const S1ap_MME_UE_S1AP_ID_t new_id)
|
||||
{
|
||||
int size = 0;
|
||||
int i = 0;
|
||||
xmlNode *s1ap_node = NULL;
|
||||
|
||||
size = (nodes) ? nodes->nodeNr : 0;
|
||||
//S1AP_DEBUG("%s() num nodes %u\n", __FUNCTION__, size);
|
||||
|
||||
/*
|
||||
* NOTE: the nodes are processed in reverse order, i.e. reverse document
|
||||
* order because xmlNodeSetContent can actually free up descendant
|
||||
* of the node and such nodes may have been selected too ! Handling
|
||||
* in reverse order ensure that descendant are accessed first, before
|
||||
* they get removed. Mixing XPath and modifications on a tree must be
|
||||
* done carefully !
|
||||
*/
|
||||
for(i = size - 1; i >= 0; i--) {
|
||||
s1ap_node = nodes->nodeTab[i];
|
||||
AssertFatal(NULL != s1ap_node, "One element of resultset of XPATH expression is NULL\n");
|
||||
update_xpath_node_mme_ue_s1ap_id(s1ap_payload, s1ap_node, new_id);
|
||||
/*
|
||||
* All the elements returned by an XPath query are pointers to
|
||||
* elements from the tree *except* namespace nodes where the XPath
|
||||
* semantic is different from the implementation in libxml2 tree.
|
||||
* As a result when a returned node set is freed when
|
||||
* xmlXPathFreeObject() is called, that routine must check the
|
||||
* element type. But node from the returned set may have been removed
|
||||
* by xmlNodeSetContent() resulting in access to freed data.
|
||||
* This can be exercised by running valgrind
|
||||
* There is 2 ways around it:
|
||||
* - make a copy of the pointers to the nodes from the result set
|
||||
* then call xmlXPathFreeObject() and then modify the nodes
|
||||
* or
|
||||
* - remove the reference to the modified nodes from the node set
|
||||
* as they are processed, if they are not namespace nodes.
|
||||
*/
|
||||
if (nodes->nodeTab[i]->type != XML_NAMESPACE_DECL) {
|
||||
nodes->nodeTab[i] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
int et_s1ap_update_mme_ue_s1ap_id(et_packet_t * const packet, const S1ap_MME_UE_S1AP_ID_t old_id, const S1ap_MME_UE_S1AP_ID_t new_id)
|
||||
{
|
||||
|
||||
|
||||
xmlChar xpath_expression[ET_XPATH_EXPRESSION_MAX_LENGTH];
|
||||
int ret = 0;
|
||||
xmlDocPtr doc = NULL;
|
||||
xmlXPathContextPtr xpath_ctx = NULL;
|
||||
xmlXPathObjectPtr xpath_obj = NULL;
|
||||
|
||||
//S1AP_DEBUG("%s() packet num %u original frame number %u, mme_ue_s1ap_id %u -> %u\n", __FUNCTION__, packet->packet_number, packet->original_frame_number, old_id, new_id);
|
||||
|
||||
ret = snprintf(xpath_expression, ET_XPATH_EXPRESSION_MAX_LENGTH, "//field[@name=\"s1ap.MME_UE_S1AP_ID\"][@show=\"%u\"]", old_id);
|
||||
AssertFatal((ret > 0) && (ret < ET_XPATH_EXPRESSION_MAX_LENGTH), "Could not build XPATH expression err=%d", ret);
|
||||
|
||||
doc = packet->sctp_hdr.u.data_hdr.payload.doc;
|
||||
// Create xpath evaluation context
|
||||
xpath_ctx = xmlXPathNewContext(doc);
|
||||
if(xpath_ctx == NULL) {
|
||||
fprintf(stderr,"Error: unable to create new XPath context\n");
|
||||
xmlFreeDoc(doc);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
// Evaluate xpath expression
|
||||
xpath_obj = xmlXPathEvalExpression(xpath_expression, xpath_ctx);
|
||||
xmlXPathFreeContext(xpath_ctx);
|
||||
AssertFatal(xpath_obj != NULL, "Unable to evaluate XPATH expression \"%s\"\n", xpath_expression);
|
||||
|
||||
if(xmlXPathNodeSetIsEmpty(xpath_obj->nodesetval)){
|
||||
xmlXPathFreeObject(xpath_obj);
|
||||
S1AP_DEBUG("%s() No match \"%s\"packet num %u original frame number %u, mme_ue_s1ap_id %u -> %u\n",
|
||||
__FUNCTION__, xpath_expression, packet->packet_number, packet->original_frame_number, old_id, new_id);
|
||||
return -1;
|
||||
}
|
||||
// update selected nodes
|
||||
update_xpath_nodes_mme_ue_s1ap_id(&packet->sctp_hdr.u.data_hdr.payload, xpath_obj->nodesetval, new_id);
|
||||
|
||||
// Cleanup of XPath data
|
||||
xmlXPathFreeObject(xpath_obj);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,250 @@
|
||||
/*******************************************************************************
|
||||
OpenAirInterface
|
||||
Copyright(c) 1999 - 2014 Eurecom
|
||||
|
||||
OpenAirInterface is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
|
||||
OpenAirInterface is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenAirInterface.The full GNU General Public License is
|
||||
included in this distribution in the file called "COPYING". If not,
|
||||
see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Contact Information
|
||||
OpenAirInterface Admin: openair_admin@eurecom.fr
|
||||
OpenAirInterface Tech : openair_tech@eurecom.fr
|
||||
OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr
|
||||
|
||||
Address : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "queue.h"
|
||||
#include "tree.h"
|
||||
|
||||
#include "sctp_eNB_defs.h"
|
||||
|
||||
#ifndef PLAY_SCENARIO_S1AP_ENB_DEFS_H_
|
||||
#define PLAY_SCENARIO_S1AP_ENB_DEFS_H_
|
||||
|
||||
#define ENB_TAC (1)
|
||||
#define ENB_MCC (208)
|
||||
#define ENB_MNC (92)
|
||||
|
||||
#define ENB_NAME "Eurecom ENB"
|
||||
#define ENB_NAME_FORMAT (ENB_NAME" %u")
|
||||
|
||||
#define S1AP_PORT_NUMBER (36412)
|
||||
#define S1AP_SCTP_PPID (18)
|
||||
|
||||
#define X2AP_PORT_NUMBER (36422)
|
||||
#define X2AP_SCTP_PPID (27)
|
||||
|
||||
#define S1AP_ENB_NAME_LENGTH_MAX (150)
|
||||
|
||||
typedef enum {
|
||||
/* Disconnected state: initial state for any association. */
|
||||
S1AP_ENB_STATE_DISCONNECTED = 0x0,
|
||||
/* State waiting for S1 Setup response message if eNB is MME accepted or
|
||||
* S1 Setup failure if MME rejects the eNB.
|
||||
*/
|
||||
S1AP_ENB_STATE_WAITING = 0x1,
|
||||
/* The eNB is successfully connected to MME, UE contexts can be created. */
|
||||
S1AP_ENB_STATE_CONNECTED = 0x2,
|
||||
/* The MME has sent an overload start message. Once the MME disables the
|
||||
* OVERLOAD marker, the state of the association will be
|
||||
* S1AP_ENB_STATE_CONNECTED.
|
||||
*/
|
||||
S1AP_ENB_OVERLOAD = 0x3,
|
||||
/* Max number of states available */
|
||||
S1AP_ENB_STATE_MAX,
|
||||
} s1ap_eNB_state_t;
|
||||
|
||||
|
||||
/* If the Overload Action IE in the OVERLOAD START message is set to
|
||||
* - “reject all RRC connection establishments for non-emergency mobile
|
||||
* originated data transfer “ (i.e. reject traffic corresponding to RRC cause
|
||||
* “mo-data “ (TS 36.331 [16])), or
|
||||
* - “reject all RRC connection establishments for signalling “ (i.e. reject
|
||||
* traffic corresponding to RRC cause “modata” and “mo-signalling”
|
||||
* (TS 36.331 [16])),or
|
||||
* - “only permit RRC connection establishments for emergency sessions and
|
||||
* mobile terminated services” (i.e. only permit traffic corresponding to RRC
|
||||
* cause “emergency” and “mt-Access” (TS 36.331 [16])).
|
||||
*
|
||||
* NOTE: When the Overload Action IE is set to “only permit RRC connection
|
||||
* establishments for emergency sessions and mobile terminated services”,
|
||||
* emergency calls with RRC cause “highPriorityAcess” from high priority users
|
||||
* are rejected (TS 24.301 [24]).
|
||||
*/
|
||||
typedef enum {
|
||||
S1AP_OVERLOAD_REJECT_MO_DATA = 0x0,
|
||||
S1AP_OVERLOAD_REJECT_ALL_SIGNALLING = 0x1,
|
||||
S1AP_OVERLOAD_ONLY_EMERGENCY_AND_MT = 0x2,
|
||||
S1AP_NO_OVERLOAD = 0x3,
|
||||
S1AP_OVERLOAD_MAX,
|
||||
} s1ap_overload_state_t;
|
||||
|
||||
/* Served PLMN identity element */
|
||||
struct plmn_identity_s {
|
||||
uint16_t mcc;
|
||||
uint16_t mnc;
|
||||
uint8_t mnc_digit_length;
|
||||
STAILQ_ENTRY(plmn_identity_s) next;
|
||||
};
|
||||
|
||||
/* Served group id element */
|
||||
struct served_group_id_s {
|
||||
uint16_t mme_group_id;
|
||||
STAILQ_ENTRY(served_group_id_s) next;
|
||||
};
|
||||
|
||||
/* Served mme code for a particular MME */
|
||||
struct mme_code_s {
|
||||
uint8_t mme_code;
|
||||
STAILQ_ENTRY(mme_code_s) next;
|
||||
};
|
||||
|
||||
/* Served gummei element */
|
||||
struct served_gummei_s {
|
||||
/* Number of MME served PLMNs */
|
||||
uint8_t nb_served_plmns;
|
||||
/* List of served PLMNs by MME */
|
||||
STAILQ_HEAD(served_plmns_s, plmn_identity_s) served_plmns;
|
||||
|
||||
/* Number of group id in list */
|
||||
uint8_t nb_group_id;
|
||||
/* Served group id list */
|
||||
STAILQ_HEAD(served_group_ids_s, served_group_id_s) served_group_ids;
|
||||
|
||||
/* Number of MME code */
|
||||
uint8_t nb_mme_code;
|
||||
/* MME Code to uniquely identify an MME within an MME pool area */
|
||||
STAILQ_HEAD(mme_codes_s, mme_code_s) mme_codes;
|
||||
|
||||
/* Next GUMMEI element */
|
||||
STAILQ_ENTRY(served_gummei_s) next;
|
||||
};
|
||||
|
||||
struct s1ap_eNB_instance_s;
|
||||
|
||||
/* This structure describes association of a eNB to a MME */
|
||||
typedef struct s1ap_eNB_mme_data_s {
|
||||
/* MME descriptors tree, ordered by sctp assoc id */
|
||||
RB_ENTRY(s1ap_eNB_mme_data_s) entry;
|
||||
|
||||
/* This is the optional name provided by the MME */
|
||||
char *mme_name;
|
||||
net_ip_address_t mme_net_ip_address; // useful for joining assoc_id and ip address of packets
|
||||
|
||||
/* List of served GUMMEI per MME. There is one GUMMEI per RAT with a max
|
||||
* number of 8 RATs but in our case only one is used. The LTE related pool
|
||||
* configuration is included on the first place in the list.
|
||||
*/
|
||||
STAILQ_HEAD(served_gummeis_s, served_gummei_s) served_gummei;
|
||||
|
||||
/* Relative processing capacity of an MME with respect to the other MMEs
|
||||
* in the pool in order to load-balance MMEs within a pool as defined
|
||||
* in TS 23.401.
|
||||
*/
|
||||
uint8_t relative_mme_capacity;
|
||||
|
||||
/* Current MME overload information (if any). */
|
||||
s1ap_overload_state_t overload_state;
|
||||
/* Current eNB->MME S1AP association state */
|
||||
s1ap_eNB_state_t state;
|
||||
|
||||
/* Next usable stream for UE signalling */
|
||||
int32_t nextstream;
|
||||
|
||||
/* Number of input/ouput streams */
|
||||
uint16_t in_streams;
|
||||
uint16_t out_streams;
|
||||
|
||||
/* Connexion id used between SCTP/S1AP */
|
||||
uint16_t cnx_id;
|
||||
|
||||
/* SCTP association id */
|
||||
int32_t assoc_id;
|
||||
|
||||
/* Only meaningfull in virtual mode */
|
||||
struct s1ap_eNB_instance_s *s1ap_eNB_instance;
|
||||
} s1ap_eNB_mme_data_t;
|
||||
|
||||
typedef struct s1ap_eNB_instance_s {
|
||||
/* Next s1ap eNB association.
|
||||
* Only used for virtual mode.
|
||||
*/
|
||||
STAILQ_ENTRY(s1ap_eNB_instance_s) s1ap_eNB_entries;
|
||||
|
||||
/* Number of MME requested by eNB (tree size) */
|
||||
uint32_t s1ap_mme_nb;
|
||||
/* Number of MME for which association is pending */
|
||||
uint32_t s1ap_mme_pending_nb;
|
||||
/* Number of MME successfully associated to eNB */
|
||||
uint32_t s1ap_mme_associated_nb;
|
||||
/* Tree of S1AP MME associations ordered by association ID */
|
||||
RB_HEAD(s1ap_mme_map, s1ap_eNB_mme_data_s) s1ap_mme_head;
|
||||
|
||||
/* TODO: add a map ordered by relative MME capacity */
|
||||
|
||||
/* Tree of UE ordered by eNB_ue_s1ap_id's */
|
||||
RB_HEAD(s1ap_ue_map, s1ap_eNB_ue_context_s) s1ap_ue_head;
|
||||
|
||||
/* For virtual mode, mod_id as defined in the rest of the L1/L2 stack */
|
||||
instance_t instance;
|
||||
|
||||
/* Displayable name of eNB */
|
||||
char *eNB_name;
|
||||
net_ip_address_t s1c_net_ip_address;
|
||||
|
||||
/* Unique eNB_id to identify the eNB within EPC.
|
||||
* In our case the eNB is a macro eNB so the id will be 20 bits long.
|
||||
* For Home eNB id, this field should be 28 bits long.
|
||||
*/
|
||||
uint32_t eNB_id;
|
||||
/* The type of the cell */
|
||||
enum cell_type_e cell_type;
|
||||
|
||||
/* Tracking area code */
|
||||
uint16_t tac;
|
||||
|
||||
/* Mobile Country Code
|
||||
* Mobile Network Code
|
||||
*/
|
||||
uint16_t mcc;
|
||||
uint16_t mnc;
|
||||
uint8_t mnc_digit_length;
|
||||
|
||||
} s1ap_eNB_instance_t;
|
||||
|
||||
typedef struct {
|
||||
/* List of served eNBs
|
||||
* Only used for virtual mode
|
||||
*/
|
||||
STAILQ_HEAD(s1ap_eNB_instances_head_s, s1ap_eNB_instance_s) s1ap_eNB_instances_head;
|
||||
/* Nb of registered eNBs */
|
||||
uint8_t nb_registered_eNBs;
|
||||
|
||||
/* Generate a unique connexion id used between S1AP and SCTP */
|
||||
uint16_t global_cnx_id;
|
||||
} s1ap_eNB_internal_data_t;
|
||||
|
||||
int s1ap_eNB_compare_assoc_id(
|
||||
struct s1ap_eNB_mme_data_s *p1, struct s1ap_eNB_mme_data_s *p2);
|
||||
|
||||
/* Generate the tree management functions */
|
||||
RB_PROTOTYPE(s1ap_mme_map, s1ap_eNB_mme_data_s, entry,
|
||||
s1ap_eNB_compare_assoc_id);
|
||||
|
||||
#endif /* PLAY_SCENARIO_S1AP_ENB_DEFS_H_ */
|
||||
@@ -0,0 +1,112 @@
|
||||
/*******************************************************************************
|
||||
OpenAirInterface
|
||||
Copyright(c) 1999 - 2014 Eurecom
|
||||
|
||||
OpenAirInterface is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
|
||||
OpenAirInterface is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenAirInterface.The full GNU General Public License is
|
||||
included in this distribution in the file called "COPYING". If not,
|
||||
see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Contact Information
|
||||
OpenAirInterface Admin: openair_admin@eurecom.fr
|
||||
OpenAirInterface Tech : openair_tech@eurecom.fr
|
||||
OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr
|
||||
|
||||
Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
/*
|
||||
play_scenario_sctp.c
|
||||
-------------------
|
||||
AUTHOR : Lionel GAUTHIER
|
||||
COMPANY : EURECOM
|
||||
EMAIL : Lionel.Gauthier@eurecom.fr
|
||||
*/
|
||||
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include "intertask_interface.h"
|
||||
#include "platform_types.h"
|
||||
#include "assertions.h"
|
||||
#include "play_scenario.h"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
asn_comp_rval_t * et_sctp_data_is_matching(sctp_datahdr_t * const sctp1, sctp_datahdr_t * const sctp2, const uint32_t constraints)
|
||||
{
|
||||
asn_comp_rval_t *rv = NULL;
|
||||
// no comparison for ports
|
||||
if (sctp1->ppid != sctp2->ppid) {
|
||||
S1AP_WARN("No Matching SCTP PPID %u %u\n", sctp1->ppid, sctp2->ppid);
|
||||
rv = calloc(1, sizeof(asn_comp_rval_t));
|
||||
rv->err_code = ET_ERROR_MATCH_PACKET_SCTP_PPID;
|
||||
return rv;
|
||||
}
|
||||
if (sctp1->assoc_id != sctp2->assoc_id) {
|
||||
S1AP_WARN("No Matching SCTP assoc id %u %u\n", sctp1->assoc_id, sctp2->assoc_id);
|
||||
rv = calloc(1, sizeof(asn_comp_rval_t));
|
||||
rv->err_code = ET_ERROR_MATCH_PACKET_SCTP_ASSOC_ID;
|
||||
return rv;
|
||||
}
|
||||
if (sctp1->stream != sctp2->stream) {
|
||||
if (constraints & ET_BIT_MASK_MATCH_SCTP_STREAM) {
|
||||
rv = calloc(1, sizeof(asn_comp_rval_t));
|
||||
rv->err_code = ET_ERROR_MATCH_PACKET_SCTP_STREAM_ID;
|
||||
return rv;
|
||||
} else {
|
||||
S1AP_WARN("No Matching SCTP stream %u %u\n", sctp1->stream, sctp2->stream);
|
||||
}
|
||||
}
|
||||
// We do not have SSN from lower layers
|
||||
// if (sctp1->ssn != sctp2->ssn) {
|
||||
// if (constraints & ET_BIT_MASK_MATCH_SCTP_SSN) {
|
||||
// rv = calloc(1, sizeof(asn_comp_rval_t));
|
||||
// rv->err_code = ET_ERROR_MATCH_PACKET_SCTP_SSN;
|
||||
// return rv;
|
||||
// } else {
|
||||
// S1AP_WARN("No Matching SCTP STREAM SN %u %u\n", sctp1->ssn, sctp2->ssn);
|
||||
// }
|
||||
// }
|
||||
return et_s1ap_is_matching(&sctp1->payload, &sctp2->payload, constraints);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
asn_comp_rval_t * et_sctp_is_matching(et_sctp_hdr_t * const sctp1, et_sctp_hdr_t * const sctp2, const uint32_t constraints)
|
||||
{
|
||||
// no comparison for ports
|
||||
asn_comp_rval_t *rv = NULL;
|
||||
if (sctp1->chunk_type != sctp2->chunk_type){
|
||||
S1AP_WARN("No Matching chunk_type %u %u\n", sctp1->chunk_type, sctp2->chunk_type);
|
||||
rv = calloc(1, sizeof(asn_comp_rval_t));
|
||||
rv->err_code = ET_ERROR_MATCH_PACKET_SCTP_CHUNK_TYPE;
|
||||
return rv;
|
||||
}
|
||||
switch (sctp1->chunk_type) {
|
||||
case SCTP_CID_DATA:
|
||||
return et_sctp_data_is_matching(&sctp1->u.data_hdr, &sctp2->u.data_hdr, constraints);
|
||||
break;
|
||||
|
||||
case SCTP_CID_INIT:
|
||||
AssertFatal(0, "Not needed now");
|
||||
break;
|
||||
case SCTP_CID_INIT_ACK:
|
||||
AssertFatal(0, "Not needed now");
|
||||
break;
|
||||
default:
|
||||
AssertFatal(0, "Not needed now cid %d", sctp1->chunk_type);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -275,7 +275,6 @@ do { \
|
||||
(bITsTRING)->size = 3; \
|
||||
(bITsTRING)->bits_unused = 4; \
|
||||
} while(0)
|
||||
/*
|
||||
/* TS 36.413 v10.9.0 section 9.2.1.38:
|
||||
* E-UTRAN CGI/Cell Identity
|
||||
* The leftmost bits of the Cell
|
||||
|
||||
@@ -1080,6 +1080,7 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) {
|
||||
device->trx_set_freq_func = trx_brf_set_freq;
|
||||
device->trx_set_gains_func = trx_brf_set_gains;
|
||||
device->openair0_cfg = openair0_cfg;
|
||||
device->priv = (void *)brf;
|
||||
|
||||
calibrate_rf(device);
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ eNBs =
|
||||
nb_antennas_tx = 1;
|
||||
nb_antennas_rx = 1;
|
||||
tx_gain = 90;
|
||||
rx_gain = 125;
|
||||
rx_gain = 107;
|
||||
prach_root = 0;
|
||||
prach_config_index = 0;
|
||||
prach_high_speed = "DISABLE";
|
||||
|
||||
@@ -130,10 +130,12 @@ eNBs =
|
||||
};
|
||||
|
||||
////////// MME parameters:
|
||||
mme_ip_address = ( {ipv4 = "192.170.0.1";
|
||||
ipv6="192:168:30::17";
|
||||
active="yes";
|
||||
preference="ipv4";});
|
||||
mme_ip_address = ( { ipv4 = "192.170.0.1";
|
||||
ipv6 = "192:168:30::17";
|
||||
active = "yes";
|
||||
preference = "ipv4";
|
||||
}
|
||||
);
|
||||
|
||||
NETWORK_INTERFACES :
|
||||
{
|
||||
@@ -141,6 +143,7 @@ eNBs =
|
||||
ENB_IPV4_ADDRESS_FOR_S1_MME = "192.170.0.2/24";
|
||||
|
||||
ENB_INTERFACE_NAME_FOR_S1U = "eth0:4";
|
||||
ENB_IPV4_ADDRESS_FOR_S1U = "192.170.1.2/24";
|
||||
ENB_IPV4_ADDRESS_FOR_S1U = "192.170.0.2/24";
|
||||
ENB_PORT_FOR_S1U = 2152; # Spec 2152
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user