diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f095acc16..b03726ab01 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,34 @@ # RELEASE NOTES: # +## [v2.0.0](https://gitlab.eurecom.fr/oai/openairinterface5g/-/tags/v2.0.0) -> August 2023. ## + +This release adds support for 5G and maintains previous features: +* 5G SA in gNB + - PHY, MAC, RLC, PDCP, SDAP, RRC layers + - 2x2 MIMO and 256-QAM for UL/DL + - 15 and 30 kHz subcarrier spacings; 10-100 MHz bandwidths + - Up to 800Mbps throughput or 5ms latency + - F1, basic E1, 5G FAPI (SCF 222.10.02), split 8 split options + - Handling of up to 16 UEs + - RRC procedures for connection setup, multiple PDU sessions, reestablishment +* 5G SA in UE + - PHY, MAC, RLC, PDCP, SDAP, RRC layers + - 2x2 MIMO and 256-QAM for UL/DL + - 15 and 30 kHz subcarrier spacings; 10-100 MHz bandwidths + - Custom FAPI-like MAC/PHY interface + - RRC procedures for connection setup and cell measurement +* Basic 5G NSA in gNB + - X2 sgNB Addition Request between OAI eNB and gNB +* 4G eNB and UE + - Bugfixes in fairRR scheduler (eNB) + - Non-standard F1 midhaul removed (eNB) + - FlexRAN removed (eNB) + - Sync fixes (UE) +* LTE-M supported +* Support for AW2S devices, RFsimulator channel emulation support + +For more information on supported features, please refer to the [feature set](doc/FEATURE_SET.md). + ## [v1.2.1](https://gitlab.eurecom.fr/oai/openairinterface5g/-/tags/v1.2.1) -> February 2020. ## * Bug fix for mutex lock for wake-up signal diff --git a/CMakeLists.txt b/CMakeLists.txt index aa9f0c4685..6d06d30c17 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -256,8 +256,11 @@ add_definitions("-DPACKAGE_BUGREPORT=\"openair4g-devel@lists.eurecom.fr\"") # Debug related options ######################################### -add_boolean_option(DEBUG_ASN1 False "ASN1 coder/decoder Debug" OFF) -#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, not found in code, commented out, to be removed +add_boolean_option(DEBUG_ASN1 False "Enable ASN1 debug logs" OFF) +# asn1c skeletons have hardcoded this flag to make customized debug logs +# OAI uses this feature to re-use OAI LOG_I(ASN1, ...) +# see common/utils/config.h +add_boolean_option(TRACE_ASN1C_ENC_DEC OFF "Enable ASN1 encoder/decoder debug traces via OAI logging system" ON) add_boolean_option(T_TRACER True "Activate the T tracer, a debugging/monitoring framework" ON) add_boolean_option(UE_AUTOTEST_TRACE False "Activate UE autotest specific logs" ON) add_boolean_option(UE_DEBUG_TRACE False "Activate UE debug trace" ON) @@ -267,12 +270,6 @@ set (OCP_ITTI ${OPENAIR_DIR}/common/utils/ocp_itti) add_library(ITTI ${OCP_ITTI}/intertask_interface.cpp) target_link_libraries(ITTI PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs) -# asn1c skeletons have hardcoded this flag to make customized debug logs -# OAI uses this feature to re-use OAI LOG_I(ASN1, ...) -if (DEBUG_ASN1C) - add_definitions(-DHAVE_CONFIG_H) -endif() - # asn1c skeletons need this add_definitions(-DHAVE_NETINET_IN_H) @@ -626,7 +623,7 @@ add_library(UTIL ${OPENAIR_DIR}/common/utils/time_meas.c ${OPENAIR_DIR}/common/utils/time_stat.c ) -target_link_libraries(UTIL PUBLIC ${T_LIB}) +target_link_libraries(UTIL PUBLIC ${T_LIB} pthread) set(SECURITY_SRC ${OPENAIR3_DIR}/SECU/secu_defs.c @@ -1187,18 +1184,6 @@ set(RLC_V2 ${OPENAIR2_DIR}/LAYER2/rlc_v2/rlc_sdu.c ) -set(NR_RLC_SRC - ${OPENAIR2_DIR}/LAYER2/nr_rlc/asn1_utils.c - ${OPENAIR2_DIR}/LAYER2/nr_rlc/nr_rlc_entity.c - ${OPENAIR2_DIR}/LAYER2/nr_rlc/nr_rlc_entity_am.c - ${OPENAIR2_DIR}/LAYER2/nr_rlc/nr_rlc_entity_tm.c - ${OPENAIR2_DIR}/LAYER2/nr_rlc/nr_rlc_entity_um.c - ${OPENAIR2_DIR}/LAYER2/nr_rlc/nr_rlc_oai_api.c - ${OPENAIR2_DIR}/LAYER2/nr_rlc/nr_rlc_pdu.c - ${OPENAIR2_DIR}/LAYER2/nr_rlc/nr_rlc_sdu.c - ${OPENAIR2_DIR}/LAYER2/nr_rlc/nr_rlc_ue_manager.c - ) - set(NR_PDCP_SRC ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_oai_api.c ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_ue_manager.c @@ -1256,7 +1241,6 @@ set(L2_LTE_SRC ) set(L2_NR_SRC - ${NR_RLC_SRC} ${NR_PDCP_SRC} ${NR_SDAP_SRC} ${NR_RRC_DIR}/rrc_gNB.c @@ -1294,7 +1278,6 @@ set(L2_RRC_SRC_UE ) set(NR_L2_SRC_UE - ${NR_RLC_SRC} ${NR_PDCP_SRC} ${NR_SDAP_SRC} ${NR_UE_RRC_DIR}/L2_interface_ue.c @@ -1447,13 +1430,12 @@ add_library(e1_pdcp_if target_link_libraries(e1_pdcp_if PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) -target_link_libraries(L2_NR PRIVATE f1ap x2ap s1ap ngap nr_rrc e1ap) +target_link_libraries(L2_NR PRIVATE f1ap x2ap s1ap ngap nr_rrc e1ap nr_rlc) if(E2_AGENT) target_link_libraries(L2_NR PUBLIC e2_agent e2_ran_func) target_compile_definitions(L2_NR PRIVATE E2_AGENT) endif() - add_library(L2_LTE_NR ${L2_RRC_SRC} ${MAC_SRC} @@ -1482,7 +1464,7 @@ endif() target_link_libraries(L2_UE PRIVATE asn1_lte_rrc_hdrs) add_library( NR_L2_UE ${NR_L2_SRC_UE} ${MAC_NR_SRC_UE} ) -target_link_libraries(NR_L2_UE PRIVATE f1ap) +target_link_libraries(NR_L2_UE PRIVATE f1ap nr_rlc) target_link_libraries(NR_L2_UE PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) add_library(MAC_NR_COMMON @@ -2450,6 +2432,16 @@ make_driver(ue_ip ${OPENAIR2_DIR}/NETWORK_DRIVER/UE_IP ${ue_ip_src}) include(${OPENAIR1_DIR}/PHY/CODING/nrLDPC_decoder/nrLDPC_tools/CMakeLists.txt) +set(ENABLE_TESTS OFF CACHE STRING "Activate build of tests") +set_property(CACHE ENABLE_TESTS PROPERTY TYPE BOOL) +if(ENABLE_TESTS) + # activates globally adding tests such that they can be run using ctest + enable_testing() + # meta-target: each test is supposed to add_dependencies(tests ${NEWTEST}) + # then, it is possible to build and execute all tests using "ninja tests && ctest" + add_custom_target(tests) +endif() + add_subdirectory(common) add_subdirectory(doc) add_subdirectory(openair1) diff --git a/README.md b/README.md index 70614fd72d..249e4cc965 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,10 @@ Supported OS Fedora 37

+

+ GitLab Release (custom instance) +

+

diff --git a/ci-scripts/Jenkinsfile-GitLab-Container b/ci-scripts/Jenkinsfile-GitLab-Container index 61b3774d0f..93b3d38d75 100644 --- a/ci-scripts/Jenkinsfile-GitLab-Container +++ b/ci-scripts/Jenkinsfile-GitLab-Container @@ -103,7 +103,6 @@ pipeline { gitCommitAuthorEmailAddr = sh returnStdout: true, script: 'git log -n1 --pretty=format:%ae ${GIT_COMMIT}' gitCommitAuthorEmailAddr = gitCommitAuthorEmailAddr.trim() echo "GitLab Usermail is ${gitCommitAuthorEmailAddr}" - sh "git log -n1 --pretty=format:\"%s\" > .git/CI_COMMIT_MSG" } } } @@ -288,7 +287,7 @@ pipeline { when { expression {do4Gtest} } steps { script { - triggerSlaveJob ('RAN-LTE-FDD-LTEBOX-Container', 'RAN-LTE-FDD-LTEBOX-Container') + triggerSlaveJob ('RAN-LTE-FDD-LTEBOX-Container', 'LTE-FDD-LTEBOX-Container') } } post { @@ -304,11 +303,32 @@ pipeline { } } } + // Pipeline to test OAI LTE-UE + stage ("LTE-B200-FDD-OAIUE-OAICN4G-Container") { + when { expression {do4Gtest} } + steps { + script { + triggerSlaveJob ('RAN-LTE-FDD-OAIUE-OAICN4G-Container', 'LTE-FDD-OAIUE-OAICN4G-Container') + } + } + post { + always { + script { + finalizeSlaveJob('RAN-LTE-FDD-OAIUE-OAICN4G-Container') + } + } + failure { + script { + currentBuild.result = 'FAILURE' + } + } + } + } stage ("LTE-B200-TDD-LTEBOX-Container") { when { expression {do4Gtest} } steps { script { - triggerSlaveJob ('RAN-LTE-TDD-LTEBOX-Container', 'RAN-LTE-TDD-LTEBOX-Container') + triggerSlaveJob ('RAN-LTE-TDD-LTEBOX-Container', 'LTE-TDD-LTEBOX-Container') } } post { @@ -468,7 +488,7 @@ pipeline { when { expression {do5Gtest} } steps { script { - triggerSlaveJob ('RAN-SA-OAIUE-CN5G', 'RAN-SA-OAIUE-CN5G') + triggerSlaveJob ('RAN-SA-OAIUE-CN5G', 'SA-OAIUE-CN5G') } } post { @@ -504,24 +524,6 @@ pipeline { } } post { - always { - script { - def eSubject = JOB_NAME + ' - Build # ' + BUILD_ID + ' - ' + currentBuild.result + '!' - def eBody = "Hi,\n\n" - eBody += "Here are attached HTML report files for " + JOB_NAME + " - Build # " + BUILD_ID + " - " + currentBuild.result + "!\n\n" - eBody += "Regards,\n" - eBody += "OAI CI Team" - emailext attachmentsPattern: '*results*.html', - body: eBody, - replyTo: 'no-reply@openairinterface.org', - subject: eSubject, - to: gitCommitAuthorEmailAddr - - if (fileExists('.git/CI_COMMIT_MSG')) { - sh "rm -f .git/CI_COMMIT_MSG" - } - } - } success { script { def message = "OAI " + JOB_NAME + " build (" + BUILD_ID + "): passed (" + BUILD_URL + ")" diff --git a/ci-scripts/ci_ueinfra.yaml b/ci-scripts/ci_ueinfra.yaml index 7cef916dd2..9ddee1d779 100644 --- a/ci-scripts/ci_ueinfra.yaml +++ b/ci-scripts/ci_ueinfra.yaml @@ -49,75 +49,75 @@ adb_ue_2: amarisoft_ue: Host: amariue - InitScript: /root/NV18-06-2022/lteue-linux-2023-03-17/lteue /root/oaicicd/ran_sa_aw2s_asue/aw2s-multi-20897-2x2.cfg & - TermScript: /root/NV18-06-2022/lteue-linux-2023-03-17/doc/ws.js -t 10 127.0.0.1:9002 '{"message":"quit"}' || killall -KILL lteue-avx2 + InitScript: /root/2023-06-10/lteue-linux-2023-06-10/lteue /root/oaicicd/ran_sa_aw2s_asue/aw2s-multi-20897-2x2.cfg & + TermScript: /root/2023-06-10/libs/ws.js -t 10 127.0.0.1:9002 '{"message":"quit"}' || killall -KILL lteue-avx2 amarisoft_ue_1: Host: amariue - AttachScript: /root/NV18-06-2022/lteue-linux-2023-03-17/doc/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":1}' - DetachScript: /root/NV18-06-2022/lteue-linux-2023-03-17/doc/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":1}' + AttachScript: /root/2023-06-10/libs/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":1}' + DetachScript: /root/2023-06-10/libs/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":1}' NetworkScript: ip netns exec ue1 ip a show dev pdn0 CmdPrefix: ip netns exec ue1 MTU: 1500 amarisoft_ue_2: Host: amariue - AttachScript: /root/NV18-06-2022/lteue-linux-2023-03-17/doc/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":2}' - DetachScript: /root/NV18-06-2022/lteue-linux-2023-03-17/doc/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":2}' + AttachScript: /root/2023-06-10/libs/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":2}' + DetachScript: /root/2023-06-10/libs/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":2}' NetworkScript: ip netns exec ue2 ip a show dev pdn0 CmdPrefix: ip netns exec ue2 MTU: 1500 amarisoft_ue_3: Host: amariue - AttachScript: /root/NV18-06-2022/lteue-linux-2023-03-17/doc/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":3}' - DetachScript: /root/NV18-06-2022/lteue-linux-2023-03-17/doc/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":3}' + AttachScript: /root/2023-06-10/libs/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":3}' + DetachScript: /root/2023-06-10/libs/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":3}' NetworkScript: ip netns exec ue3 ip a show dev pdn0 CmdPrefix: ip netns exec ue3 MTU: 1500 amarisoft_ue_4: Host: amariue - AttachScript: /root/NV18-06-2022/lteue-linux-2023-03-17/doc/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":4}' - DetachScript: /root/NV18-06-2022/lteue-linux-2023-03-17/doc/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":4}' + AttachScript: /root/2023-06-10/libs/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":4}' + DetachScript: /root/2023-06-10/libs/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":4}' NetworkScript: ip netns exec ue4 ip a show dev pdn0 CmdPrefix: ip netns exec ue4 MTU: 1500 amarisoft_ue_5: Host: amariue - AttachScript: /root/NV18-06-2022/lteue-linux-2023-03-17/doc/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":5}' - DetachScript: /root/NV18-06-2022/lteue-linux-2023-03-17/doc/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":5}' + AttachScript: /root/2023-06-10/libs/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":5}' + DetachScript: /root/2023-06-10/libs/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":5}' NetworkScript: ip netns exec ue5 ip a show dev pdn0 CmdPrefix: ip netns exec ue5 MTU: 1500 amarisoft_ue_6: Host: amariue - AttachScript: /root/NV18-06-2022/lteue-linux-2023-03-17/doc/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":6}' - DetachScript: /root/NV18-06-2022/lteue-linux-2023-03-17/doc/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":6}' + AttachScript: /root/2023-06-10/libs/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":6}' + DetachScript: /root/2023-06-10/libs/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":6}' NetworkScript: ip netns exec ue6 ip a show dev pdn0 CmdPrefix: ip netns exec ue6 MTU: 1500 amarisoft_ue_7: Host: amariue - AttachScript: /root/NV18-06-2022/lteue-linux-2023-03-17/doc/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":7}' - DetachScript: /root/NV18-06-2022/lteue-linux-2023-03-17/doc/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":7}' + AttachScript: /root/2023-06-10/libs/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":7}' + DetachScript: /root/2023-06-10/libs/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":7}' NetworkScript: ip netns exec ue7 ip a show dev pdn0 CmdPrefix: ip netns exec ue7 MTU: 1500 amarisoft_ue_8: Host: amariue - AttachScript: /root/NV18-06-2022/lteue-linux-2023-03-17/doc/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":8}' - DetachScript: /root/NV18-06-2022/lteue-linux-2023-03-17/doc/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":8}' + AttachScript: /root/2023-06-10/libs/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":8}' + DetachScript: /root/2023-06-10/libs/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":8}' NetworkScript: ip netns exec ue8 ip a show dev pdn0 CmdPrefix: ip netns exec ue8 MTU: 1500 amarisoft_ue_9: Host: amariue - AttachScript: /root/NV18-06-2022/lteue-linux-2023-03-17/doc/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":9}' - DetachScript: /root/NV18-06-2022/lteue-linux-2023-03-17/doc/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":9}' + AttachScript: /root/2023-06-10/libs/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":9}' + DetachScript: /root/2023-06-10/libs/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":9}' NetworkScript: ip netns exec ue9 ip a show dev pdn0 CmdPrefix: ip netns exec ue9 MTU: 1500 amarisoft_ue_10: Host: amariue - AttachScript: /root/NV18-06-2022/lteue-linux-2023-03-17/doc/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":10}' - DetachScript: /root/NV18-06-2022/lteue-linux-2023-03-17/doc/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":10}' + AttachScript: /root/2023-06-10/libs/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":10}' + DetachScript: /root/2023-06-10/libs/ws.js 127.0.0.1:9002 '{"message":"power_off","ue_id":10}' NetworkScript: ip netns exec ue10 ip a show dev pdn0 CmdPrefix: ip netns exec ue10 MTU: 1500 @@ -130,6 +130,13 @@ oai_ue_caracal: IF: oaitun_ue1 MTU: 1500 +lte_oai_ue_carabe: + Host: carabe + NetworkScript: docker exec lte-b200-ue-fdd-10Mhz-tm1 ip a show dev oaitun_ue1 + CmdPrefix: docker exec lte-b200-ue-fdd-10Mhz-tm1 + IF: oaitun_ue1 + MTU: 1500 + rfsim5g_gnb_nos1: Host: localhost NetworkScript: docker exec rfsim5g-oai-gnb ip a show dev oaitun_enb1 diff --git a/ci-scripts/cls_containerize.py b/ci-scripts/cls_containerize.py index 9a54f258eb..88de9d135d 100644 --- a/ci-scripts/cls_containerize.py +++ b/ci-scripts/cls_containerize.py @@ -742,6 +742,7 @@ class Containerize(): if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') + logging.debug('\u001B[1m Pulling image(s) on server: ' + lIpAddr + '\u001B[0m') myCmd = cls_cmd.getConnection(lIpAddr) imagePrefix = 'porcepix.sboai.cs.eurecom.fr' response = myCmd.run(f'docker login -u oaicicd -p oaicicd {imagePrefix}') @@ -903,7 +904,7 @@ class Containerize(): cnt = 0 while (cnt < 20): mySSH.command('docker logs ' + containerName + ' | egrep --text --color=never -i "wait|sync|Starting"', '\$', 30) - result = re.search('got sync|Starting F1AP at CU|Got sync|Waiting for RUs to be configured', mySSH.getBefore()) + result = re.search('got sync|Starting E1AP at CU UP|Starting F1AP at CU|Got sync|Waiting for RUs to be configured', mySSH.getBefore()) if result is None: time.sleep(6) cnt += 1 @@ -1005,7 +1006,7 @@ class Containerize(): HTML.CreateHtmlTestRow('N/A', 'KO', CONST.ENB_PROCESS_NOLOGFILE_TO_ANALYZE) self.exitStatus = 1 # use function for UE log analysis, when oai-nr-ue container is used - elif 'oai-nr-ue' in services: + elif 'oai-nr-ue' in services or 'lte_ue0' in services: self.exitStatus == 0 logging.debug('\u001B[1m Analyzing UE logfile ' + filename + ' \u001B[0m') logStatus = cls_oaicitest.OaiCiTest().AnalyzeLogFile_UE(f'{filename}', HTML, RAN) diff --git a/ci-scripts/cls_oai_html.py b/ci-scripts/cls_oai_html.py index 48a88a8590..81b01cd530 100644 --- a/ci-scripts/cls_oai_html.py +++ b/ci-scripts/cls_oai_html.py @@ -469,8 +469,8 @@ class HTMLManagement(): self.htmlFile.write(' ') else: self.htmlFile.write(' ') - for i in infoList: - self.htmlFile.write(f'
{i}
') + for i in infoList: # add custom style to have elements side-by-side to reduce need for vertical space + self.htmlFile.write(f'
{i}
') self.htmlFile.write(' ') self.htmlFile.write(' \n') diff --git a/ci-scripts/cls_oaicitest.py b/ci-scripts/cls_oaicitest.py index 06ae655f37..b0fa28d76c 100644 --- a/ci-scripts/cls_oaicitest.py +++ b/ci-scripts/cls_oaicitest.py @@ -43,7 +43,7 @@ import logging import datetime import signal import statistics as stat -from multiprocessing import Process, Lock, SimpleQueue +from multiprocessing import SimpleQueue import concurrent.futures #import our libs @@ -494,15 +494,6 @@ class OaiCiTest(): messages = [f.result() for f in futures] HTML.CreateHtmlTestRowQueue('NA', 'OK', messages) - def ping_iperf_wrong_exit(self, lock, UE_IPAddress, device_id, statusQueue, message): - logging.error(f"ue {device_id} {UE_IPAddress}: {message}") - lock.acquire() - statusQueue.put(-1) - statusQueue.put(device_id) - statusQueue.put(UE_IPAddress) - statusQueue.put(message) - lock.release() - def Ping_common(self, EPC, ue, RAN): # Launch ping on the EPC side (true for ltebox and old open-air-cn) ping_status = 0 @@ -617,7 +608,7 @@ class OaiCiTest(): def Iperf_ComputeModifiedBW(self, idx, ue_num): result = re.search('-b (?P[0-9\.]+)[KMG]', str(self.iperf_args)) if result is None: - logging.debug('\u001B[1;37;41m Iperf bandwidth Not Found! \u001B[0m') + logging.error('\u001B[1;37;41m Iperf bandwidth Not Found! \u001B[0m') sys.exit(1) iperf_bandwidth = result.group('iperf_bandwidth') if self.iperf_profile == 'balanced': @@ -635,11 +626,11 @@ class OaiCiTest(): iperf_bandwidth_str_new = f"-b {'%.2f' % iperf_bandwidth_new}" result = re.sub(iperf_bandwidth_str, iperf_bandwidth_str_new, str(self.iperf_args)) if result is None: - logging.debug('\u001B[1;37;41m Calculate Iperf bandwidth Failed! \u001B[0m') + logging.error('\u001B[1;37;41m Calculate Iperf bandwidth Failed! \u001B[0m') sys.exit(1) return result - def Iperf_analyzeV2TCPOutput(self, lock, UE_IPAddress, device_id, statusQueue, iperf_real_options,EPC,SSH, filename): + def Iperf_analyzeV2TCPOutput(self, SSH, filename): SSH.command(f'awk -f /tmp/tcp_iperf_stats.awk {filename}', '\$', 5) result = re.search('Avg Bitrate : (?P[0-9\.]+ Mbits\/sec) Max Bitrate : (?P[0-9\.]+ Mbits\/sec) Min Bitrate : (?P[0-9\.]+ Mbits\/sec)', SSH.getBefore()) @@ -647,44 +638,34 @@ class OaiCiTest(): avgbitrate = result.group('average') maxbitrate = result.group('maximum') minbitrate = result.group('minimum') - lock.acquire() - logging.debug(f'\u001B[1;37;44m TCP iperf result ({UE_IPAddress}) \u001B[0m') msg = 'TCP Stats :\n' if avgbitrate is not None: - logging.debug(f'\u001B[1;34m Avg Bitrate : {avgbitrate} \u001B[0m') msg += f'Avg Bitrate : {avgbitrate} \n' if maxbitrate is not None: - logging.debug(f'\u001B[1;34m Max Bitrate : {maxbitrate} \u001B[0m') msg += f'Max Bitrate : {maxbitrate} \n' if minbitrate is not None: - logging.debug(f'\u001B[1;34m Min Bitrate : {minbitrate} \u001B[0m') msg += f'Min Bitrate : {minbitrate} \n' - statusQueue.put(0) - statusQueue.put(device_id) - statusQueue.put(UE_IPAddress) - statusQueue.put(msg) - lock.release() + return (True, msg) - return 0 + return (False, "could not analyze log file") - def Iperf_analyzeV2Output(self, lock, UE_IPAddress, device_id, statusQueue, iperf_real_options,EPC,SSH): + def Iperf_analyzeV2Output(self, iperf_real_options, EPC, SSH): result = re.search('-u', str(iperf_real_options)) if result is None: - logging.debug('Into Iperf_analyzeV2TCPOutput client') filename = f'{EPC.SourceCodePath}/scripts/iperf_{self.testCase_id}_{device_id}.log' - response = self.Iperf_analyzeV2TCPOutput(lock, UE_IPAddress, device_id, statusQueue, iperf_real_options, EPC, SSH, filename) - logging.debug(f'Iperf_analyzeV2TCPOutput response returned value = {response}') + response = self.Iperf_analyzeV2TCPOutput(SSH, filename) return response result = re.search('Server Report:', SSH.getBefore()) if result is None: result = re.search('read failed: Connection refused', SSH.getBefore()) if result is not None: - logging.debug('\u001B[1;37;41m Could not connect to iperf server! \u001B[0m') + msg = 'Could not connect to iperf server!' + return (False, msg) else: - logging.debug('\u001B[1;37;41m Server Report and Connection refused Not Found! \u001B[0m') - return -1 + msg = 'Server Report and Connection refused Not Found!' + return (False, msg) # Computing the requested bandwidth in float result = re.search('-b (?P[0-9\.]+)[KMG]', str(iperf_real_options)) if result is not None: @@ -708,14 +689,11 @@ class OaiCiTest(): bitrate = result.group('bitrate') packetloss = result.group('packetloss') jitter = result.group('jitter') - lock.acquire() - logging.debug(f'\u001B[1;37;44m iperf result {UE_IPAddress} \u001B[0m') + iperfStatus = True msg = f'Req Bitrate : {req_bandwidth} \n' - logging.debug(f'\u001B[1;34m Req Bitrate : {req_bandwidth} \u001B[0m') if bitrate is not None: msg += f'Bitrate : {bitrate} \n' - logging.debug(f'\u001B[1;34m Bitrate : {bitrate} \u001B[0m') result = re.search('(?P[0-9\.]+) [KMG]bits/sec', str(bitrate)) if result is not None: actual_bw = float(str(result.group('real_bw'))) @@ -731,50 +709,37 @@ class OaiCiTest(): br_loss = 100 * actual_bw / req_bw bitperf = '%.2f ' % br_loss msg += f'Bitrate Perf: {bitperf} %\n' - logging.debug(f'\u001B[1;34m Bitrate Perf: {bitperf} %\u001B[0m') if packetloss is not None: msg += f'Packet Loss : {packetloss} %\n' - logging.debug(f'\u001B[1;34m Packet Loss : {packetloss} %\u001B[0m') if float(packetloss) > float(self.iperf_packetloss_threshold): msg += 'Packet Loss too high!\n' - logging.debug('\u001B[1;37;41m Packet Loss too high \u001B[0m') iperfStatus = False if jitter is not None: msg += f'Jitter : {jitter} \n' - logging.debug(f'\u001B[1;34m Jitter : {jitter} \u001B[0m') - if (iperfStatus): - statusQueue.put(0) - else: - statusQueue.put(-1) - statusQueue.put(device_id) - statusQueue.put(UE_IPAddress) - statusQueue.put(msg) - lock.release() - return 0 + + return (iperfStatus, msg) else: - return -2 + return (False, "could not analyze server log") - def Iperf_analyzeV2BIDIR(self, lock, UE_IPAddress, device_id, statusQueue,server_filename,client_filename): + def Iperf_analyzeV2BIDIR(self, server_filename, client_filename): #check the 2 files are here if (not os.path.isfile(client_filename)) or (not os.path.isfile(server_filename)): - self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, 'Bidir TCP : Client or Server Log File not present') - return + return (False, 'Bidir TCP: Client or Server Log File not present') #check the 2 files size if (os.path.getsize(client_filename)==0) and (os.path.getsize(server_filename)==0): - self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, 'Bidir TCP : Client and Server Log File are empty') - return + return (False, 'Bidir TCP: Client and Server Log File are empty') - report_msg='TCP BIDIR Report:\n' + report_msg = '' #if client is not empty, all the info is in, otherwise we ll use the server file to get some partial info client_filesize = os.path.getsize(client_filename) if client_filesize == 0: report_msg+="Client file (UE) present but !!! EMPTY !!!\n" - report_msg+="Partial report from server file\n" + report_msg+="Partial report from server file" filename = server_filename else : - report_msg+="Report from client file (UE)\n" + report_msg+="Report from client file (UE)" filename = client_filename report=[] #used to check if relevant lines were found @@ -784,32 +749,19 @@ class OaiCiTest(): result = re.search(rf'^\[\s+\d+\](?P\[.+\]).*\s+(?P[0-9\.]+ [KMG]bits\/sec).*\s+(?P\bsender|receiver\b)', str(line)) if result is not None: report.append(str(line)) - report_msg+=result.group('role') + ' ' + result.group('direction')+ '\t = ' +result.group('bitrate')+'\n' - if len(report)>0: - lock.acquire() - statusQueue.put(0) - statusQueue.put(device_id) - statusQueue.put(UE_IPAddress) - statusQueue.put(report_msg) - logging.debug(f'\u001B[1;37;45m TCP Bidir Iperf Result ({UE_IPAddress}) \u001B[0m') - for rLine in report_msg.split('\n'): - logging.debug(f'\u001B[1;35m {rLine} \u001B[0m') - lock.release() - else: - self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, 'Bidir TCP : Could not analyze from Log file') + report_msg += f"\n{result.group('role')} {result.group('direction')}\t: {result.group('bitrate')}" + if len(report) == 0: + return (False, 'Bidir TCP: Could not analyze from Log file') + return (True, report_msg) - - def Iperf_analyzeV2Server(self, lock, UE_IPAddress, device_id, statusQueue, iperf_real_options, filename,type): + def Iperf_analyzeV2Server(self, iperf_real_options, filename, type): if (not os.path.isfile(filename)): - self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, 'Could not analyze from server log') - return + return (False, 'Could not analyze from server log') # Computing the requested bandwidth in float result = re.search('-b (?P[0-9\.]+)[KMG]', str(iperf_real_options)) if result is None: - logging.debug('Iperf bandwidth Not Found!') - self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, 'Could not compute Iperf bandwidth!') - return + return (False, 'Could not compute Iperf bandwidth!') else: req_bandwidth = result.group('iperf_bandwidth') req_bw = float(req_bandwidth) @@ -856,6 +808,8 @@ class OaiCiTest(): br_sum = curr_br + br_sum ji_sum = float(ji[0]) + ji_sum + server_file.close() + if (row_idx > 0): br_sum = br_sum / row_idx ji_sum = ji_sum / row_idx @@ -876,87 +830,25 @@ class OaiCiTest(): pl = float(100 * pl_sum / ps_sum) packetloss = '%2.1f ' % (pl) packetloss += '%' - #checking packet loss compliance - if float(pl) > float(self.iperf_packetloss_threshold): - pal_too_high_msg = 'Packet Loss too high : tested = '+packetloss+', target = '+self.iperf_packetloss_threshold+'%' - else: - pal_too_high_msg='Packet Loss value is within acceptance range' - #checking bitrate perf compliance - if float(br_loss) < float(self.iperf_bitrate_threshold): - bit_too_low_msg = 'Bitrate too low : tested = '+bitperf+', target = '+self.iperf_bitrate_threshold+'%' - else: - bit_too_low_msg='Bitrate perf value is within acceptance range' - lock.acquire() - if (float(br_loss) < float(self.iperf_bitrate_threshold)) and (float(pl) > float(self.iperf_packetloss_threshold)): - statusQueue.put(-1) - elif (float(br_loss) < float(self.iperf_bitrate_threshold)) or (float(pl) > float(self.iperf_packetloss_threshold)): - statusQueue.put(1) - else: - statusQueue.put(0) - statusQueue.put(device_id) - statusQueue.put(UE_IPAddress) + + result = float(br_loss) >= float(self.iperf_bitrate_threshold) and float(pl) <= float(self.iperf_packetloss_threshold) req_msg = f'Req Bitrate : {req_bandwidth}' bir_msg = f'Bitrate : {bitrate}' brl_msg = f'Bitrate Perf: {bitperf}' + if float(br_loss) < float(self.iperf_bitrate_threshold): + brl_msg += f' (too low! <{self.iperf_bitrate_threshold}%)' jit_msg = f'Jitter : {jitter}' pal_msg = f'Packet Loss : {packetloss}' - statusQueue.put(f'{req_msg}\n{bir_msg}\n{brl_msg}\n{jit_msg}\n{pal_msg}\n{pal_too_high_msg}\n{bit_too_low_msg}\n') - logging.debug(f'\u001B[1;37;45m iperf result ({UE_IPAddress}) \u001B[0m') - logging.debug(f'\u001B[1;35m {req_msg} \u001B[0m') - logging.debug(f'\u001B[1;35m {bir_msg} \u001B[0m') - logging.debug(f'\u001B[1;35m {brl_msg} \u001B[0m') - logging.debug(f'\u001B[1;35m {jit_msg} \u001B[0m') - logging.debug(f'\u001B[1;35m {pal_msg} \u001B[0m') - logging.debug(f'\u001B[1;35m {pal_too_high_msg} \u001B[0m') - logging.debug(f'\u001B[1;35m {bit_too_low_msg} \u001B[0m') - lock.release() + if float(pl) > float(self.iperf_packetloss_threshold): + pal_msg += f' (too high! >{self.iperf_packetloss_threshold}%)' + return (result, f'{req_msg}\n{bir_msg}\n{brl_msg}\n{jit_msg}\n{pal_msg}') else: - self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, 'Could not analyze from server log') + return (False, 'Could not analyze from server log') - server_file.close() - - - def Iperf_analyzeV3Output(self, lock, UE_IPAddress, device_id, statusQueue,SSH): - - result = re.search('(?P[0-9\.]+ [KMG]bits\/sec) +(?:|[0-9\.]+ ms +\d+\/\d+ \((?P[0-9\.]+)%\)) +(?:|receiver)\r\n(?:|\[ *\d+\] Sent \d+ datagrams)\r\niperf Done\.', SSH.getBefore()) - if result is None: - result = re.search('(?Piperf: error - [a-zA-Z0-9 :]+)', SSH.getBefore()) - lock.acquire() - statusQueue.put(-1) - statusQueue.put(device_id) - statusQueue.put(UE_IPAddress) - if result is not None: - logging.debug(f"\u001B[1;37;41m {result.group('error')} \u001B[0m") - statusQueue.put(result.group('error')) - else: - logging.debug('\u001B[1;37;41m Bitrate and/or Packet Loss Not Found! \u001B[0m') - statusQueue.put('Bitrate and/or Packet Loss Not Found!') - lock.release() - - bitrate = result.group('bitrate') - packetloss = result.group('packetloss') - lock.acquire() - logging.debug(f'\u001B[1;37;44m iperf result ({UE_IPAddress}) \u001B[0m') - logging.debug(f'\u001B[1;34m Bitrate : {bitrate} \u001B[0m') - msg = f'Bitrate : {bitrate} \n' - iperfStatus = True - if packetloss is not None: - logging.debug(f'\u001B[1;34m Packet Loss : {packetloss} %\u001B[0m') - msg += f'Packet Loss : {packetloss} %\n' - if float(packetloss) > float(self.iperf_packetloss_threshold): - logging.debug('\u001B[1;37;41m Packet Loss too high \u001B[0m') - msg += 'Packet Loss too high!\n' - iperfStatus = False - if (iperfStatus): - statusQueue.put(0) - else: - statusQueue.put(-1) - statusQueue.put(device_id) - statusQueue.put(UE_IPAddress) - statusQueue.put(msg) - lock.release() - - def Iperf_Module(self, lock, statusQueue, EPC, ue, RAN, idx, ue_num): + def Iperf_Module(self, EPC, ue, RAN, idx, ue_num): + ueIP = ue.getIP() + if not ueIP: + return (False, f"UE {ue.getName()} has no IP address") SSH = sshconnection.SSHConnection() server_filename = f'iperf_server_{self.testCase_id}_{ue.getName()}.log' client_filename = f'iperf_client_{self.testCase_id}_{ue.getName()}.log' @@ -987,16 +879,18 @@ class OaiCiTest(): # hack: the ADB UEs don't have iperf in $PATH, so we need to hardcode for the moment iperf_ue = '/data/local/tmp/iperf' if re.search('adb', ue.getName()) else 'iperf' + ue_header = f'UE {ue.getName()} ({ueIP})' + if self.iperf_direction == "DL": logging.debug("Iperf in DL requested") cmd = cls_cmd.getConnection(ue.getHost()) cmd.run(f'rm {server_filename}') - cmd.run(f'{ue.getCmdPrefix()} {iperf_ue} -s -B {ue.getIP()} {udpSwitch} -i 1 -t {iperf_time * 1.5} {port} &> /tmp/{server_filename} &') + cmd.run(f'{ue.getCmdPrefix()} {iperf_ue} -s -B {ueIP} {udpSwitch} -i 1 -t {iperf_time * 1.5} {port} &> /tmp/{server_filename} &') cmd.close() cmd = cls_cmd.getConnection(EPC.IPAddress) cmd.run(f'rm {EPC.SourceCodePath}/{client_filename}') - cmd.run(f'{cn_iperf_prefix} iperf -c {ue.getIP()} {iperf_opt} {port} &> {EPC.SourceCodePath}/{client_filename}', timeout=iperf_time * 1.5) + cmd.run(f'{cn_iperf_prefix} iperf -c {ueIP} {iperf_opt} {port} &> {EPC.SourceCodePath}/{client_filename}', timeout=iperf_time * 1.5) cmd.copyin(f'{EPC.SourceCodePath}/{client_filename}', client_filename) cmd.close() @@ -1005,10 +899,10 @@ class OaiCiTest(): cmd.close() if udpIperf: - self.Iperf_analyzeV2Server(lock, ue.getIP(), ue.getName(), statusQueue, iperf_opt, server_filename, 1) + status, msg = self.Iperf_analyzeV2Server(iperf_opt, server_filename, 1) else: cmd = cls_cmd.getConnection(EPC.IPAddress) - self.Iperf_analyzeV2TCPOutput(lock, ue.getIP(), ue.getName(), statusQueue, iperf_opt, EPC, cmd, f"{EPC.SourceCodePath}/{client_filename}") + status, msg = self.Iperf_analyzeV2TCPOutput(cmd, f"{EPC.SourceCodePath}/{client_filename}") cmd.close() elif self.iperf_direction == "UL": @@ -1020,7 +914,7 @@ class OaiCiTest(): cmd = cls_cmd.getConnection(ue.getHost()) cmd.run(f'rm /tmp/{client_filename}') - cmd.run(f'{ue.getCmdPrefix()} {iperf_ue} -B {ue.getIP()} -c {cn_target_ip} {iperf_opt} {port} &> /tmp/{client_filename}', timeout=iperf_time*1.5) + cmd.run(f'{ue.getCmdPrefix()} {iperf_ue} -B {ueIP} -c {cn_target_ip} {iperf_opt} {port} &> /tmp/{client_filename}', timeout=iperf_time*1.5) cmd.copyin(f'/tmp/{client_filename}', client_filename) cmd.close() @@ -1029,10 +923,10 @@ class OaiCiTest(): cmd.close() if udpIperf: - self.Iperf_analyzeV2Server(lock, ue.getIP(), ue.getName(), statusQueue, iperf_opt, server_filename, 1) + status, msg = self.Iperf_analyzeV2Server(iperf_opt, server_filename, 1) else: cmd = cls_cmd.getConnection(ue.getHost()) - self.Iperf_analyzeV2TCPOutput(lock, ue.getIP(), ue.getName(), statusQueue, iperf_opt, EPC, cmd, f"/tmp/{client_filename}") + status, msg = self.Iperf_analyzeV2TCPOutput(cmd, f"/tmp/{client_filename}") cmd.close() elif self.iperf_direction=="BIDIR": @@ -1044,7 +938,7 @@ class OaiCiTest(): cmd = cls_cmd.getConnection(ue.getHost()) cmd.run(f'rm /tmp/{client_filename}') - cmd.run(f'iperf3 -B {ue.getIP()} -c {cn_target_ip} {iperf_opt} {port} &> /tmp/{client_filename}', timeout=iperf_time*1.5) + cmd.run(f'iperf3 -B {ueIP} -c {cn_target_ip} {iperf_opt} {port} &> /tmp/{client_filename}', timeout=iperf_time*1.5) cmd.copyin(f'/tmp/{client_filename}', client_filename) cmd.close() @@ -1052,129 +946,32 @@ class OaiCiTest(): cmd.copyin(f'{EPC.SourceCodePath}/{server_filename}', server_filename) cmd.close() - self.Iperf_analyzeV2BIDIR(lock, ue.getHost(), ue.getName(), statusQueue, server_filename, client_filename) + status, msg = self.Iperf_analyzeV2BIDIR(server_filename, client_filename) elif self.iperf_direction == "IPERF3": cmd = cls_cmd.getConnection(ue.getHost()) cmd.run(f'rm /tmp/{server_filename}', reportNonZero=False) port = f'{5002+idx}' - cmd.run(f'{ue.getCmdPrefix()} iperf3 -B {ue.getIP()} -c {cn_target_ip} -p {port} {iperf_opt} --get-server-output &> /tmp/{server_filename}', timeout=iperf_time*1.5) + cmd.run(f'{ue.getCmdPrefix()} iperf3 -B {ueIP} -c {cn_target_ip} -p {port} {iperf_opt} --get-server-output &> /tmp/{server_filename}', timeout=iperf_time*1.5) cmd.copyin(f'/tmp/{server_filename}', server_filename) cmd.close() if udpIperf: - self.Iperf_analyzeV2Server(lock, ue.getIP(), ue.getName(), statusQueue, iperf_opt, server_filename, 1) + status, msg = self.Iperf_analyzeV2Server(iperf_opt, server_filename, 1) else: cmd = cls_cmd.getConnection(EPC.IPAddress) - self.Iperf_analyzeV2TCPOutput(lock, ue.getIP(), ue.getName(), statusQueue, iperf_opt, EPC, cmd, f'/tmp/{server_filename}') + status, msg = self.Iperf_analyzeV2TCPOutput(cmd, f'/tmp/{server_filename}') cmd.close() else : raise Exception("Incorrect or missing IPERF direction in XML") + logging.info(f'\u001B[1;37;45m iperf result for {ue_header}\u001B[0m') + for l in msg.split('\n'): + logging.info(f'\u001B[1;35m {l} \u001B[0m') + return (status, f'{ue_header}\n{msg}') + def IperfNoS1(self,HTML,RAN,EPC,CONTAINERS): - SSH = sshconnection.SSHConnection() - if RAN.eNBIPAddress == '' or RAN.eNBUserName == '' or RAN.eNBPassword == '' or self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '': - HELP.GenericHelp(CONST.Version) - sys.exit('Insufficient Parameter') - check_eNB = True - check_OAI_UE = True - server_on_enb = re.search('-R', str(self.iperf_args)) - if server_on_enb is not None: - iServerIPAddr = RAN.eNBIPAddress - iServerUser = RAN.eNBUserName - iServerPasswd = RAN.eNBPassword - iClientIPAddr = self.UEIPAddress - iClientUser = self.UEUserName - iClientPasswd = self.UEPassword - else: - iServerIPAddr = self.UEIPAddress - iServerUser = self.UEUserName - iServerPasswd = self.UEPassword - iClientIPAddr = RAN.eNBIPAddress - iClientUser = RAN.eNBUserName - iClientPasswd = RAN.eNBPassword - if self.iperf_options != 'sink': - # Starting the iperf server - SSH.open(iServerIPAddr, iServerUser, iServerPasswd) - # args SHALL be "-c client -u any" - # -c 10.0.1.2 -u -b 1M -t 30 -i 1 -fm -B 10.0.1.1 - # -B 10.0.1.1 -u -s -i 1 -fm - server_options = re.sub('-u.*$', '-u -s -i 1 -fm', str(self.iperf_args)) - server_options = server_options.replace('-c','-B') - SSH.command(f'rm -f /tmp/tmp_iperf_server_{self.testCase_id}.log', '\$', 5) - SSH.command(f'echo $USER; nohup iperf {server_options} > /tmp/tmp_iperf_server_{self.testCase_id}.log 2>&1 &', iServerUser, 5) - time.sleep(0.5) - SSH.close() - - # Starting the iperf client - modified_options = self.Iperf_ComputeModifiedBW(0, 1) - modified_options = modified_options.replace('-R','') - iperf_time = self.Iperf_ComputeTime() - SSH.open(iClientIPAddr, iClientUser, iClientPasswd) - SSH.command(f'rm -f /tmp/tmp_iperf_{self.testCase_id}.log', '\$', 5) - iperf_status = SSH.command(f'stdbuf -o0 iperf {modified_options} 2>&1 | stdbuf -o0 tee /tmp/tmp_iperf_{self.testCase_id}.log', '\$', int(iperf_time)*5.0) - status_queue = SimpleQueue() - lock = Lock() - if iperf_status < 0: - message = 'iperf on OAI UE crashed due to TIMEOUT !' - logging.debug(f'\u001B[1;37;41m {message} \u001B[0m') - clientStatus = -2 - else: - if self.iperf_options == 'sink': - clientStatus = 0 - status_queue.put(0) - status_queue.put('OAI-UE') - status_queue.put('10.0.1.2') - status_queue.put('Sink Test : no check') - else: - clientStatus = self.Iperf_analyzeV2Output(lock, '10.0.1.2', 'OAI-UE', status_queue, modified_options, EPC,SSH) - SSH.close() - - # Stopping the iperf server - if self.iperf_options != 'sink': - SSH.open(iServerIPAddr, iServerUser, iServerPasswd) - SSH.command('killall --signal SIGKILL iperf', '\$', 5) - time.sleep(0.5) - SSH.close() - - if (clientStatus == -1): - if (os.path.isfile(f'iperf_server_{self.testCase_id}.log')): - os.remove(f'iperf_server_{self.testCase_id}.log') - SSH.copyin(iServerIPAddr, iServerUser, iServerPasswd, f'/tmp/tmp_iperf_server_{self.testCase_id}.log', f'iperf_server_{self.testCase_id}_OAI-UE.log') - filename=f'iperf_server_{self.testCase_id}_OAI-UE.log' - self.Iperf_analyzeV2Server(lock, '10.0.1.2', 'OAI-UE', status_queue, modified_options,filename,0) - - # copying on the EPC server for logCollection - if (clientStatus == -1): - copyin_res = SSH.copyin(iServerIPAddr, iServerUser, iServerPasswd, f'/tmp/tmp_iperf_server_{self.testCase_id}.log', f'iperf_server_{self.testCase_id}_OAI-UE.log') - if (copyin_res == 0): - SSH.copyout(EPC.IPAddress, EPC.UserName, EPC.Password, f'iperf_server_{self.testCase_id}_OAI-UE.log', f'{EPC.SourceCodePath}/scripts') - copyin_res = SSH.copyin(iClientIPAddr, iClientUser, iClientPasswd, f'/tmp/tmp_iperf_{self.testCase_id}.log', f'iperf_{self.testCase_id}_OAI-UE.log') - if (copyin_res == 0): - SSH.copyout(EPC.IPAddress, EPC.UserName, EPC.Password, f'iperf_{self.testCase_id}_OAI-UE.log', f'{EPC.SourceCodePath}/scripts') - iperf_noperf = False - if status_queue.empty(): - iperf_status = False - else: - iperf_status = True - messages = [] - while (not status_queue.empty()): - count = status_queue.get() - if (count < 0): - iperf_status = False - if (count > 0): - iperf_noperf = True - device_id = status_queue.get() - ip_addr = status_queue.get() - message = status_queue.get() - messages.append(f'UE ({device_id})\nIP Address : {ip_addr}\n{message}') - if (iperf_noperf and iperf_status): - HTML.CreateHtmlTestRowQueue(self.iperf_args, 'PERF NOT MET', messages) - elif (iperf_status): - HTML.CreateHtmlTestRowQueue(self.iperf_args, 'OK', messages) - else: - HTML.CreateHtmlTestRowQueue(self.iperf_args, 'KO', messages) - self.AutoTerminateUEandeNB(HTML,RAN,EPC,CONTAINERS) + raise 'IperfNoS1 not implemented' def Iperf(self,HTML,RAN,EPC,CONTAINERS): result = re.search('noS1', str(RAN.Initialize_eNB_args)) @@ -1187,64 +984,18 @@ class OaiCiTest(): logging.debug(f'Iperf: iperf_args "{self.iperf_args}" iperf_direction "{self.iperf_direction}" iperf_packetloss_threshold "{self.iperf_packetloss_threshold}" iperf_bitrate_threshold "{self.iperf_bitrate_threshold}" iperf_profile "{self.iperf_profile}" iperf_options "{self.iperf_options}"') - ues = [] - for ue_name in self.ue_ids: - ue = cls_module_ue.Module_UE(ue_name) - if not ue.getIP(): - logging.error("no IP addresses returned") - HTML.CreateHtmlTestRow(self.ping_args, 'KO', CONST.UE_IP_ADDRESS_ISSUE) - self.AutoTerminateUEandeNB(HTML,RAN,EPC,CONTAINERS) - ues.append(ue) + ues = [cls_module_ue.Module_UE(n.strip()) for n in self.ue_ids] logging.debug(ues) - - self.dummyIperfVersion = '2.0.10' - #cmd = 'iperf --version' - #logging.debug(cmd + '\n') - #iperfStdout = subprocess.check_output(cmd, shell=True, universal_newlines=True) - #result = re.search('iperf version 2.0.5', str(iperfStdout.strip())) - #if result is not None: - # dummyIperfVersion = '2.0.5' - #result = re.search('iperf version 2.0.10', str(iperfStdout.strip())) - #if result is not None: - # dummyIperfVersion = '2.0.10' - multi_jobs = [] - ue_num = len(ues) - i = 0 - lock = Lock() - status_queue = SimpleQueue() - for ue in ues: - p = Process(target = self.Iperf_Module ,args = (lock, status_queue, EPC, ue, RAN, i, ue_num)) - p.daemon = True - p.start() - multi_jobs.append(p) - i = i + 1 - for job in multi_jobs: - job.join() - - if (status_queue.empty()): - HTML.CreateHtmlTestRow(self.iperf_args, 'KO', CONST.ALL_PROCESSES_OK) - self.AutoTerminateUEandeNB(HTML,RAN,EPC,CONTAINERS) + with concurrent.futures.ThreadPoolExecutor() as executor: + futures = [executor.submit(self.Iperf_Module, EPC, ue, RAN, i, len(ues)) for i, ue in enumerate(ues)] + results = [f.result() for f in futures] + # each result in results is a tuple, first member goes to successes, second to messages + successes, messages = map(list, zip(*results)) + if len(successes) == len(ues) and all(successes): + HTML.CreateHtmlTestRowQueue(self.iperf_args, 'OK', messages) else: - iperf_status = True - iperf_noperf = False - messages = [] - while (not status_queue.empty()): - count = status_queue.get() - if (count < 0): - iperf_status = False - if (count > 0): - iperf_noperf = True - device_id = status_queue.get() - ip_addr = status_queue.get() - msg = status_queue.get() - messages.append(f'UE ({device_id})\nIP Address : {ip_addr}\n{msg}') - if (iperf_noperf and iperf_status): - HTML.CreateHtmlTestRowQueue(self.iperf_args, 'PERF NOT MET', messages) - elif (iperf_status): - HTML.CreateHtmlTestRowQueue(self.iperf_args, 'OK', messages) - else: - HTML.CreateHtmlTestRowQueue(self.iperf_args, 'KO', messages) - self.AutoTerminateUEandeNB(HTML,RAN,EPC,CONTAINERS) + HTML.CreateHtmlTestRowQueue(self.iperf_args, 'KO', messages) + self.AutoTerminateUEandeNB(HTML,RAN,EPC,CONTAINERS) def AnalyzeLogFile_UE(self, UElogFile,HTML,RAN): if (not os.path.isfile(f'./{UElogFile}')): diff --git a/ci-scripts/conf_files/enb.band38.lte_2x2.100prb.usrpn310.conf b/ci-scripts/conf_files/enb.band38.lte_2x2.100prb.usrpn310.conf index 2042768933..53c4027662 100644 --- a/ci-scripts/conf_files/enb.band38.lte_2x2.100prb.usrpn310.conf +++ b/ci-scripts/conf_files/enb.band38.lte_2x2.100prb.usrpn310.conf @@ -237,7 +237,7 @@ RUs = ( max_pdschReferenceSignalPower = -27; max_rxgain = 75; eNB_instances = [0]; - sdr_addrs = "mgmt_addr=172.21.19.13,addr=192.168.10.2"; + sdr_addrs = "mgmt_addr=172.21.19.13,addr=192.168.80.250"; } ); diff --git a/ci-scripts/conf_files/enb.band38.lte_2x2_tm2.100prb.usrpn310.conf b/ci-scripts/conf_files/enb.band38.lte_2x2_tm2.100prb.usrpn310.conf index e50c1acfe8..e9cb3ee327 100644 --- a/ci-scripts/conf_files/enb.band38.lte_2x2_tm2.100prb.usrpn310.conf +++ b/ci-scripts/conf_files/enb.band38.lte_2x2_tm2.100prb.usrpn310.conf @@ -237,7 +237,7 @@ RUs = ( max_pdschReferenceSignalPower = -27; max_rxgain = 75; eNB_instances = [0]; - sdr_addrs = "mgmt_addr=172.21.19.13,addr=192.168.10.2"; + sdr_addrs = "mgmt_addr=172.21.19.13,addr=192.168.80.250"; } ); diff --git a/ci-scripts/conf_files/enb.band38.nsa_2x2.100prb.usrpn310.conf b/ci-scripts/conf_files/enb.band38.nsa_2x2.100prb.usrpn310.conf index 1afb9386b7..bc2cc8f61b 100644 --- a/ci-scripts/conf_files/enb.band38.nsa_2x2.100prb.usrpn310.conf +++ b/ci-scripts/conf_files/enb.band38.nsa_2x2.100prb.usrpn310.conf @@ -237,7 +237,7 @@ RUs = ( max_pdschReferenceSignalPower = -27; max_rxgain = 75; eNB_instances = [0]; - sdr_addrs = "mgmt_addr=172.21.19.13,addr=192.168.10.2"; + sdr_addrs = "mgmt_addr=172.21.19.13,addr=192.168.80.250"; } ); diff --git a/ci-scripts/conf_files/gnb-cucp.sa.f1.quectel.conf b/ci-scripts/conf_files/gnb-cucp.sa.f1.quectel.conf new file mode 100644 index 0000000000..c403de1b64 --- /dev/null +++ b/ci-scripts/conf_files/gnb-cucp.sa.f1.quectel.conf @@ -0,0 +1,219 @@ +Active_gNBs = ( "gNB-OAI"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; +Num_Threads_PUSCH = 8; +sa = 1; + +gNBs = +( + { + ////////// Identification parameters: + gNB_CU_ID = 0xe00; + +# cell_type = "CELL_MACRO_GNB"; + + gNB_name = "gNB-OAI"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + plmn_list = ({ mcc = 222; mnc = 01; mnc_length = 2; snssaiList = ({ sst = 1, sd = 0xffffff }) }); + + + nr_cellid = 12345678L; + force_256qam_off = 1; + + tr_s_preference = "f1"; + + local_s_if_name = "eth0"; + local_s_address = "192.168.68.194"; + remote_s_address = "192.168.68.195"; + local_s_portc = 501; + local_s_portd = 2153; + remote_s_portc = 500; + remote_s_portd = 2153; + ssb_SubcarrierOffset = 0; + min_rxtxtime = 6; + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # this is 3600 MHz + 43 PRBs@30kHz SCS (same as initial BWP) + absoluteFrequencySSB = 641280; + dl_frequencyBand = 78; + # this is 3600 MHz + dl_absoluteFrequencyPointA = 640008; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 106; + #initialDownlinkBWP + #genericParameters + # this is RBstart=27,L=48 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 28875; # 6366 12925 12956 28875 12952 +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 11; + initialDLBWPsearchSpaceZero = 0; + + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 78; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 106; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 28875; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 98; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 13; + preambleReceivedTargetPower = -96; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; +#ra_ReponseWindow +#1,2,4,8,10,20,40,80 + ra_ResponseWindow = 4; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 14; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 1, +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant =-90; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -90; +# ssb_PositionsInBurs_BitmapPR +# 1=short, 2=medium, 3=long + ssb_PositionsInBurst_PR = 2; + ssb_PositionsInBurst_Bitmap = 1; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 1; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 1; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 6; + nrofDownlinkSlots = 7; + nrofDownlinkSymbols = 6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; + + ssPBCH_BlockPower = -25; + } + + ); + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// AMF parameters: + amf_ip_address = ( { ipv4 = "172.21.16.137"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + E1_INTERFACE = + ( + { + type = "cp"; + ipv4_cucp = "192.168.68.194"; + port_cucp = 38462; + ipv4_cuup = "192.168.68.196"; + port_cuup = 38462; + } + ) + + NETWORK_INTERFACES : + { + GNB_INTERFACE_NAME_FOR_NG_AMF = "eth0"; + GNB_IPV4_ADDRESS_FOR_NG_AMF = "192.168.68.194"; + }; + } +); + +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + +log_config : { + global_log_level = "info"; +}; diff --git a/ci-scripts/conf_files/gnb-cuup.sa.f1.quectel.conf b/ci-scripts/conf_files/gnb-cuup.sa.f1.quectel.conf new file mode 100644 index 0000000000..535ef68bd0 --- /dev/null +++ b/ci-scripts/conf_files/gnb-cuup.sa.f1.quectel.conf @@ -0,0 +1,78 @@ +Active_gNBs = ( "gNB-OAI"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; +sa = 1; + +gNBs = +( + { + ////////// Identification parameters: + gNB_CU_ID = 0xe00; + +# cell_type = "CELL_MACRO_GNB"; + + gNB_name = "gNB-OAI"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + plmn_list = ({ mcc = 222; mnc = 01; mnc_length = 2; snssaiList = ({ sst = 1, sd = 0xffffff }) }); + + + tr_s_preference = "f1"; + + local_s_if_name = "lo"; + local_s_address = "192.168.68.196"; + remote_s_address = "192.168.68.195"; + local_s_portc = 501; + local_s_portd = 2153; + remote_s_portc = 500; + remote_s_portd = 2153; + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + E1_INTERFACE = + ( + { + type = "up"; + ipv4_cucp = "192.168.68.194"; + ipv4_cuup = "192.168.68.196"; + } + ) + + NETWORK_INTERFACES : + { + GNB_INTERFACE_NAME_FOR_NG_AMF = "demo-oai"; + GNB_IPV4_ADDRESS_FOR_NG_AMF = "192.168.68.196"; + GNB_INTERFACE_NAME_FOR_NGU = "demo-oai"; + GNB_IPV4_ADDRESS_FOR_NGU = "192.168.68.196"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + } +); + +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + +log_config: { + global_log_level = "info"; +}; diff --git a/ci-scripts/conf_files/gnb-du.sa.band78.106prb.usrpb200.conf b/ci-scripts/conf_files/gnb-du.sa.band78.106prb.usrpb200.conf index 26b2a4f111..b30bf92370 100644 --- a/ci-scripts/conf_files/gnb-du.sa.band78.106prb.usrpb200.conf +++ b/ci-scripts/conf_files/gnb-du.sa.band78.106prb.usrpb200.conf @@ -218,15 +218,6 @@ THREAD_STRUCT = ( } ); - log_config : - { - global_log_level ="info"; - hw_log_level ="info"; - phy_log_level ="info"; - mac_log_level ="info"; - rlc_log_level ="info"; - pdcp_log_level ="info"; - rrc_log_level ="info"; - f1ap_log_level ="debug"; - ngap_log_level ="debug"; - }; +log_config : { + global_log_level = "info"; +}; diff --git a/ci-scripts/conf_files/lteue.usim-ci-magma.conf b/ci-scripts/conf_files/lteue.usim-ci-magma.conf new file mode 100644 index 0000000000..0be59ed51d --- /dev/null +++ b/ci-scripts/conf_files/lteue.usim-ci-magma.conf @@ -0,0 +1,45 @@ +# List of known PLMNS +PLMN: { + PLMN0: { + FULLNAME="OpenAirInterface"; + SHORTNAME="OAICN"; + MNC="92"; + MCC="208"; + }; +}; + +UE0: +{ + USER: { + IMEI="356113022094149"; + MANUFACTURER="OAI"; + MODEL="LTE SoftModem"; + PIN="0000"; + }; + + SIM: { + MSIN="1000000003"; + USIM_API_K="fec86ba6eb707ed08905757b1bb44b8f"; + OPC="c42449363bbad02b66d16bc975d77cc1"; + MSISDN="001011234561010"; + }; + + # Home PLMN Selector with Access Technology + HPLMN= "20892"; + + # User controlled PLMN Selector with Access Technology + UCPLMN_LIST = (); + + # Operator PLMN List + OPLMN_LIST = ("20892"); + + # Operator controlled PLMN Selector with Access Technology + OCPLMN_LIST = (); + + # Forbidden plmns + FPLMN_LIST = (); + + # Equivalent home plmns + EHPLMN_LIST = (); + +}; diff --git a/ci-scripts/doGitLabMerge.sh b/ci-scripts/doGitLabMerge.sh index c4aa9157de..c0d6121314 100755 --- a/ci-scripts/doGitLabMerge.sh +++ b/ci-scripts/doGitLabMerge.sh @@ -135,8 +135,6 @@ then exit $STATUS fi -git log -n1 --pretty=format:\"%s\" > .git/CI_COMMIT_MSG - git merge --ff $TARGET_COMMIT_ID -m "Temporary merge for CI" STATUS=`git status | egrep -c "You have unmerged paths.|fix conflicts"` diff --git a/ci-scripts/epc.py b/ci-scripts/epc.py index 3505e9bdc2..af4699688d 100644 --- a/ci-scripts/epc.py +++ b/ci-scripts/epc.py @@ -643,7 +643,7 @@ class EPCManagement(): mySSH = SSH.SSHConnection() mySSH.open(self.IPAddress, self.UserName, self.Password) mySSH.command('docker-compose --version', '\$', 5) - result = re.search('docker-compose version 1', mySSH.getBefore()) + result = re.search('docker-compose version 1|Docker Compose version v2', mySSH.getBefore()) if result is None: mySSH.close() HTML.CreateHtmlTestRow(self.Type, 'KO', CONST.INVALID_PARAMETER) @@ -659,6 +659,7 @@ class EPCManagement(): mySSH.command('if [ -d ' + self.SourceCodePath + '/scripts ]; then echo ' + self.Password + ' | sudo -S rm -Rf ' + self.SourceCodePath + '/scripts ; fi', '\$', 5) mySSH.command('if [ -d ' + self.SourceCodePath + '/logs ]; then echo ' + self.Password + ' | sudo -S rm -Rf ' + self.SourceCodePath + '/logs ; fi', '\$', 5) mySSH.command('mkdir -p ' + self.SourceCodePath + '/scripts ' + self.SourceCodePath + '/logs', '\$', 5) + mySSH.command('rm -f ' + self.SourceCodePath + '/*.log', '\$', 5) # deploying and configuring the cassandra database # container names and services are currently hard-coded. diff --git a/ci-scripts/xml_files/container_lte_b200_fdd_05Mhz_tm1.xml b/ci-scripts/xml_files/container_lte_b200_fdd_05Mhz_tm1.xml index 7d43346bd6..3c4a0d006e 100644 --- a/ci-scripts/xml_files/container_lte_b200_fdd_05Mhz_tm1.xml +++ b/ci-scripts/xml_files/container_lte_b200_fdd_05Mhz_tm1.xml @@ -120,6 +120,7 @@ Replaces xml_files/enb_usrp210_band7_test_05mhz_tm1.xml iperf (5MHz - DL/15Mbps/UDP)(30 sec)(balanced profile) -u -b 15M -t 30 -i 1 50 + 50 DL adb_ue_1 adb_ue_2 @@ -178,6 +179,7 @@ Replaces xml_files/enb_usrp210_band7_test_05mhz_tm1.xml iperf (5MHz - UL/9Mbps/UDP)(30 sec)(single-ue profile) -u -b 9M -t 30 -i 1 50 + 50 single-ue UL adb_ue_1 diff --git a/ci-scripts/xml_files/container_lte_b200_fdd_05Mhz_tm1_if4_5.xml b/ci-scripts/xml_files/container_lte_b200_fdd_05Mhz_tm1_if4_5.xml index df544ab529..0f4b6535ef 100644 --- a/ci-scripts/xml_files/container_lte_b200_fdd_05Mhz_tm1_if4_5.xml +++ b/ci-scripts/xml_files/container_lte_b200_fdd_05Mhz_tm1_if4_5.xml @@ -128,6 +128,7 @@ iperf (5MHz - DL/15Mbps/UDP)(30 sec)(balanced profile) -u -b 15M -t 30 -i 1 50 + 50 DL adb_ue_1 adb_ue_2 @@ -156,6 +157,7 @@ iperf (5MHz - UL/9Mbps/UDP)(30 sec)(balanced profile) -u -b 9M -t 30 -i 1 50 + 50 balanced UL adb_ue_1 adb_ue_2 @@ -166,6 +168,7 @@ iperf (5MHz - UL/9Mbps/UDP)(30 sec)(single-ue profile) -u -b 9M -t 30 -i 1 50 + 50 single-ue UL adb_ue_1 diff --git a/ci-scripts/xml_files/container_lte_b200_fdd_10Mhz_tm1.xml b/ci-scripts/xml_files/container_lte_b200_fdd_10Mhz_tm1.xml index f8e7d5ab12..6fd083a2e8 100644 --- a/ci-scripts/xml_files/container_lte_b200_fdd_10Mhz_tm1.xml +++ b/ci-scripts/xml_files/container_lte_b200_fdd_10Mhz_tm1.xml @@ -114,6 +114,7 @@ Replaces xml_files/enb_usrp210_band7_test_10mhz_tm1.xml iperf (10MHz - DL/30Mbps/UDP)(30 sec)(balanced profile) -u -b 30M -t 30 -i 1 50 + 50 balanced DL adb_ue_1 adb_ue_2 diff --git a/ci-scripts/xml_files/container_lte_b200_fdd_10Mhz_tm1_cdrx.xml b/ci-scripts/xml_files/container_lte_b200_fdd_10Mhz_tm1_cdrx.xml index 66ee0ffb42..01be9676be 100644 --- a/ci-scripts/xml_files/container_lte_b200_fdd_10Mhz_tm1_cdrx.xml +++ b/ci-scripts/xml_files/container_lte_b200_fdd_10Mhz_tm1_cdrx.xml @@ -107,6 +107,7 @@ Replaces xml_files/enb_usrp210_band7_test_10mhz_tm1.xml iperf (10MHz - DL/30Mbps/UDP)(30 sec)(balanced profile) -u -b 30M -t 30 -i 1 50 + 50 balanced DL adb_ue_1 adb_ue_2 diff --git a/ci-scripts/xml_files/container_lte_b200_fdd_10Mhz_tm1_oaiue.xml b/ci-scripts/xml_files/container_lte_b200_fdd_10Mhz_tm1_oaiue.xml new file mode 100644 index 0000000000..4d42fb4153 --- /dev/null +++ b/ci-scripts/xml_files/container_lte_b200_fdd_10Mhz_tm1_oaiue.xml @@ -0,0 +1,174 @@ + + + test-fdd-10-tm1 + Test-FDD-10MHz-TM1 + tasks + +100000 +100001 +111110 +111111 +030111 +000001 +030311 +000002 +040511 040613 040616 040651 +030411 +000001 +030211 +200000 +200001 + + + + + Pull_Local_Registry + Pull Images from Local Registry + 0 + oai-enb + + + Pull_Local_Registry + Pull Images from Local Registry + 1 + oai-lte-ue + + + Custom_Command + Disable Sleep States (hutch) + hutch + sudo cpupower idle-set -D 0 + + + Custom_Command + Disable Sleep States (carabe) + carabe + sudo cpupower idle-set -D 0 + + + Custom_Command + Enable Sleep States (hutch) + hutch + sudo cpupower idle-set -E + + + Custom_Command + Enable Sleep States (carabe) + carabe + sudo cpupower idle-set -E + + + + Deploy_Object + Deploy eNB (FDD/Band7/10MHz/B200) in a container + ci-scripts/yaml_files/lte_b200_fdd_10Mhz_tm1_magma + 0 + 0 + + + + Deploy_Object + Deploy LTE-UE (FDD/Band7/10MHz/B200) in a container + ci-scripts/yaml_files/lte_b200_fdd_10Mhz_oai_ue_magma + 1 + 1 + + + + IdleSleep + Sleep + 5 + + + + IdleSleep + Sleep + 10 + + + + Undeploy_Object + Undeploy eNB + ci-scripts/yaml_files/lte_b200_fdd_10Mhz_tm1_magma + 0 + 0 + + + + Undeploy_Object + Undeploy LTE-UE + ci-scripts/yaml_files/lte_b200_fdd_10Mhz_oai_ue_magma + 1 + 1 + + + + Ping + ping (10MHz - 20 sec) + -c 20 192.168.61.200 + 5 + lte_oai_ue_carabe + + + + Iperf + iperf (10MHz - DL/10Mbps/UDP)(30 sec)(balanced profile) + -u -b 10M -t 30 -i 1 + 50 + single-ue + DL + lte_oai_ue_carabe + + + + Iperf + iperf (10MHz - DL/TCP)(30 sec)(single-ue profile) + -t 30 -i 1 -fm + 50 + single-ue + DL + lte_oai_ue_carabe + + + + Iperf + iperf (10MHz - UL/10Mbps/UDP)(30 sec)(balanced profile) + -u -b 10M -t 30 -i 1 + 50 + single-ue + UL + lte_oai_ue_carabe + + + + Iperf + iperf (10MHz - UL/TCP)(30 sec)(balanced profile) + -t 30 -i 1 -fm + 50 + balanced + UL + lte_oai_ue_carabe + + + diff --git a/ci-scripts/xml_files/container_lte_b200_fdd_10Mhz_tm1_oaiue_cleanup.xml b/ci-scripts/xml_files/container_lte_b200_fdd_10Mhz_tm1_oaiue_cleanup.xml new file mode 100644 index 0000000000..33df87d924 --- /dev/null +++ b/ci-scripts/xml_files/container_lte_b200_fdd_10Mhz_tm1_oaiue_cleanup.xml @@ -0,0 +1,45 @@ + + + images-clean-up + Images Clean-Up + trash + +222222 +333333 + + + + + Clean_Test_Server_Images + Clean Test Images on eNB Test Server + 0 + + + + Clean_Test_Server_Images + Clean Test Images on LTE-UE Test Server + 1 + + + diff --git a/ci-scripts/xml_files/container_lte_b200_fdd_20Mhz_tm1.xml b/ci-scripts/xml_files/container_lte_b200_fdd_20Mhz_tm1.xml index 1c6cf4b647..8bb2dfafc9 100644 --- a/ci-scripts/xml_files/container_lte_b200_fdd_20Mhz_tm1.xml +++ b/ci-scripts/xml_files/container_lte_b200_fdd_20Mhz_tm1.xml @@ -113,6 +113,7 @@ Replaces xml_files/enb_usrp210_band7_test_10mhz_tm1.xml iperf (20MHz - DL/70Mbps/UDP)(30 sec)(balanced profile) -u -b 70M -t 30 -i 1 50 + 50 balanced DL adb_ue_1 adb_ue_2 diff --git a/ci-scripts/xml_files/container_lte_b200_tdd_05Mhz_tm1.xml b/ci-scripts/xml_files/container_lte_b200_tdd_05Mhz_tm1.xml index f926d1a056..d181fd1a0d 100644 --- a/ci-scripts/xml_files/container_lte_b200_tdd_05Mhz_tm1.xml +++ b/ci-scripts/xml_files/container_lte_b200_tdd_05Mhz_tm1.xml @@ -121,6 +121,7 @@ Replaces xml_files/enb_usrp210_band40_test_05mhz_tm1.xml iperf (5MHz - DL/6.5Mbps/UDP)(30 sec)(balanced) -u -b 6.5M -t 30 -i 1 50 + 50 balanced DL adb_ue_1 adb_ue_2 diff --git a/ci-scripts/xml_files/container_lte_b200_tdd_05Mhz_tm1_if4_5.xml b/ci-scripts/xml_files/container_lte_b200_tdd_05Mhz_tm1_if4_5.xml index b71cc555e6..1c87cefe82 100644 --- a/ci-scripts/xml_files/container_lte_b200_tdd_05Mhz_tm1_if4_5.xml +++ b/ci-scripts/xml_files/container_lte_b200_tdd_05Mhz_tm1_if4_5.xml @@ -129,6 +129,7 @@ iperf (5MHz - DL/6.5Mbps/UDP)(30 sec)(balanced) -u -b 6.5M -t 30 -i 1 50 + 50 balanced DL adb_ue_1 adb_ue_2 diff --git a/ci-scripts/xml_files/container_lte_b200_tdd_10Mhz_tm1.xml b/ci-scripts/xml_files/container_lte_b200_tdd_10Mhz_tm1.xml index 93e51242fc..ef9239fe86 100644 --- a/ci-scripts/xml_files/container_lte_b200_tdd_10Mhz_tm1.xml +++ b/ci-scripts/xml_files/container_lte_b200_tdd_10Mhz_tm1.xml @@ -111,6 +111,7 @@ Replaces xml_files/enb_usrp210_band40_test_10mhz_tm1.xml iperf (10MHz - DL/13.5Mbps/UDP)(30 sec)(balanced) -u -b 13.5M -t 30 -i 1 50 + 50 balanced DL adb_ue_1 adb_ue_2 diff --git a/ci-scripts/xml_files/container_lte_b200_tdd_20Mhz_tm1_default_scheduler.xml b/ci-scripts/xml_files/container_lte_b200_tdd_20Mhz_tm1_default_scheduler.xml index d229be48b5..0fae91af5f 100644 --- a/ci-scripts/xml_files/container_lte_b200_tdd_20Mhz_tm1_default_scheduler.xml +++ b/ci-scripts/xml_files/container_lte_b200_tdd_20Mhz_tm1_default_scheduler.xml @@ -113,6 +113,7 @@ Replaces xml_files/enb_usrp210_band40_test_20mhz_tm1_default_scheduler.xml iperf (20MHz - DL/27.5Mbps/UDP)(30 sec)(balanced) -u -b 27.5M -t 30 -i 1 50 + 50 balanced DL adb_ue_1 adb_ue_2 @@ -123,6 +124,7 @@ Replaces xml_files/enb_usrp210_band40_test_20mhz_tm1_default_scheduler.xml iperf (20MHz - DL/27.5Mbps/UDP)(30 sec)(single-ue) -u -b 27.5M -t 30 -i 1 50 + 50 single-ue DL adb_ue_1 @@ -133,6 +135,7 @@ Replaces xml_files/enb_usrp210_band40_test_20mhz_tm1_default_scheduler.xml iperf (20MHz - DL/27.5Mbps/UDP)(30 sec)(unbalanced) -u -b 27.5M -t 30 -i 1 50 + 50 unbalanced DL adb_ue_1 adb_ue_2 diff --git a/ci-scripts/xml_files/container_sa_e1_b200_quectel.xml b/ci-scripts/xml_files/container_sa_e1_b200_quectel.xml new file mode 100644 index 0000000000..41358c1022 --- /dev/null +++ b/ci-scripts/xml_files/container_sa_e1_b200_quectel.xml @@ -0,0 +1,166 @@ + + + TEST-SA-FR1-F1-E1-B200 + 40 MHz TDD F1+E1 SA + tasks + 1 + + 333333 + 300000 + 310000 + 330101 + 330102 + 330103 + 310001 + 350000 + 370001 + 370000 + 370002 + 310011 + 310002 + 330201 + 200000 + + + + + Pull_Local_Registry + Pull Images from Local Registry + 0 + oai-gnb oai-nr-cuup + + + + Initialize_UE + Initialize Quectel + idefix + + + Terminate_UE + Terminate Quectel + idefix + + + Attach_UE + Attach Quectel + idefix + + + Detach_UE + Detach Quectel + idefix + + + + Deploy_Object + Deploy gNB-CU-CP in a container + ci-scripts/yaml_files/sa_e1_b200_gnb + 0 + 0 + gnb_cucp + + + + Deploy_Object + Deploy gNB-CU-UP in a container + ci-scripts/yaml_files/sa_e1_b200_gnb + 0 + 0 + gnb_cuup + + + + Deploy_Object + Deploy gNB-DU (TDD/Band78/40MHz/B200) in a container + ci-scripts/yaml_files/sa_e1_b200_gnb + 0 + 0 + gnb_du_tdd + + + + Custom_Command + Disable Sleep States + ofqot + sudo cpupower idle-set -D 0 + + + Custom_Command + Enable Sleep States + ofqot + sudo cpupower idle-set -E + + + + Ping + Ping: 20pings in 20sec + idefix + -c 20 %cn_ip% + 1 + 25 + + + + Iperf + iperf (DL/80Mbps/UDP)(30 sec) + -u -b 80M -t 30 -i 1 -fm + DL + idefix + 10 + 95 + single-ue + + + + Iperf + iperf (UL/8Mbps/UDP)(30 sec) + -u -b 8M -t 30 -i 1 -fm + UL + idefix + 1 + 95 + single-ue + + + + Iperf + iperf (BIDIR TCP)(10 sec)(single-ue profile) + -t 20 --bidir + BIDIR + idefix + single-ue + + + + Undeploy_Object + Undeploy CU-DU + ci-scripts/yaml_files/sa_e1_b200_gnb + 0 + 0 + 10,100,100,100 + 10,100,100,100 + + + + diff --git a/ci-scripts/xml_files/container_sa_e1_b200_terminate.xml b/ci-scripts/xml_files/container_sa_e1_b200_terminate.xml new file mode 100644 index 0000000000..ad902e838a --- /dev/null +++ b/ci-scripts/xml_files/container_sa_e1_b200_terminate.xml @@ -0,0 +1,48 @@ + + + TEST-SA-FR1-F1-E1-B200-terminate + Tear-down + tasks + 1 + + 330201 + 222222 + + + + + Undeploy_Object + Undeploy CU-CP/CU-UP/DU + ci-scripts/yaml_files/sa_e1_b200_gnb + 0 + 0 + + + + Clean_Test_Server_Images + Clean Test Images on Test Server + 0 + + + diff --git a/ci-scripts/xml_files/container_sa_f1_b200_quectel.xml b/ci-scripts/xml_files/container_sa_f1_b200_quectel.xml index 532d9eaef4..a20ea8845e 100644 --- a/ci-scripts/xml_files/container_sa_f1_b200_quectel.xml +++ b/ci-scripts/xml_files/container_sa_f1_b200_quectel.xml @@ -42,19 +42,15 @@ 110011 110001 150000 + 170001 + 170000 + 170002 110011 110002 100001 130201 200000 - @@ -159,19 +155,19 @@ Iperf - iperf (DL/125Mbps/UDP)(60 sec)(single-ue profile) - -u -b 125M -t 60 -i 1 -fm + iperf (DL/80Mbps/UDP)(30 sec) + -u -b 80M -t 30 -i 1 -fm DL idefix - 25 - 80 + 10 + 95 single-ue Iperf - iperf (UL/8Mbps/UDP)(60 sec)(single-ue profile) - -u -b 8M -t 60 -i 1 -fm + iperf (UL/8Mbps/UDP)(30 sec) + -u -b 8M -t 30 -i 1 -fm UL idefix 1 @@ -181,8 +177,8 @@ Iperf - iperf (BIDIR TCP)(10 sec)(single-ue profile) - -t 10 --bidir + iperf (BIDIR TCP)(20 sec)(single-ue profile) + -t 20 --bidir BIDIR idefix single-ue @@ -194,8 +190,8 @@ ci-scripts/yaml_files/sa_f1_b200_gnb 0 0 - 1,100,100,100 - 1,100,100,100 + 10,100,100,100 + 10,100,100,100 diff --git a/ci-scripts/xml_files/container_sa_f1_b200_terminate.xml b/ci-scripts/xml_files/container_sa_f1_b200_terminate.xml index cd8445f9ce..f5b13beaed 100644 --- a/ci-scripts/xml_files/container_sa_f1_b200_terminate.xml +++ b/ci-scripts/xml_files/container_sa_f1_b200_terminate.xml @@ -27,7 +27,6 @@ 1 230201 - 222222 @@ -39,10 +38,4 @@ 0 - - Clean_Test_Server_Images - Clean Test Images on Test Server - 0 - - diff --git a/ci-scripts/xml_files/lte_oai_cn_deploy.xml b/ci-scripts/xml_files/lte_oai_cn_deploy.xml new file mode 100644 index 0000000000..0279c1f3b3 --- /dev/null +++ b/ci-scripts/xml_files/lte_oai_cn_deploy.xml @@ -0,0 +1,39 @@ + + + epc-deploy-tab + EPC-Deploy + log-in + + 000100 + + + + + + Deploy_EPC + Deploy all EPC containers + yaml_files/magma_lte_20892 + + + diff --git a/ci-scripts/xml_files/lte_oai_cn_undeploy.xml b/ci-scripts/xml_files/lte_oai_cn_undeploy.xml new file mode 100644 index 0000000000..76192efea1 --- /dev/null +++ b/ci-scripts/xml_files/lte_oai_cn_undeploy.xml @@ -0,0 +1,38 @@ + + + epc-undeploy-tab + EPC-Undeploy + log-out + + 000200 + + + + + + Undeploy_EPC + Undeploy all EPC containers + + + diff --git a/ci-scripts/yaml_files/lte_b200_fdd_10Mhz_oai_ue_magma/docker-compose.yml b/ci-scripts/yaml_files/lte_b200_fdd_10Mhz_oai_ue_magma/docker-compose.yml new file mode 100644 index 0000000000..74dbb2058e --- /dev/null +++ b/ci-scripts/yaml_files/lte_b200_fdd_10Mhz_oai_ue_magma/docker-compose.yml @@ -0,0 +1,21 @@ +version: '3.8' + +services: + lte_ue0: + image: oai-lte-ue:latest + privileged: true + container_name: lte-b200-ue-fdd-10Mhz-tm1 + environment: + USE_B2XX: 'yes' + USE_ADDITIONAL_OPTIONS: -C 2680000000 -r 50 --ue-rxgain 120 --ue-txgain 0 --ue-max-power 0 --ue-scan-carrier --log_config.global_log_options level,nocolor,time + volumes: + - ../../conf_files/lteue.usim-ci-magma.conf:/opt/oai-lte-ue/etc/ue_usim.conf + - /dev:/dev + network_mode: "host" + healthcheck: + # pgrep does NOT work + test: /bin/bash -c "ps aux | grep -v grep | grep -c softmodem" + interval: 10s + timeout: 5s + retries: 5 + diff --git a/ci-scripts/yaml_files/lte_b200_fdd_10Mhz_tm1_magma/docker-compose.yml b/ci-scripts/yaml_files/lte_b200_fdd_10Mhz_tm1_magma/docker-compose.yml new file mode 100644 index 0000000000..70a1fd23b2 --- /dev/null +++ b/ci-scripts/yaml_files/lte_b200_fdd_10Mhz_tm1_magma/docker-compose.yml @@ -0,0 +1,20 @@ +version: '3.8' + +services: + enb_mono_fdd: + image: oai-enb:latest + privileged: true + container_name: lte-b200-enb-fdd-10Mhz-tm1 + environment: + USE_B2XX: 'yes' + USE_ADDITIONAL_OPTIONS: --RUs.[0].max_rxgain 120 --eNBs.[0].mme_ip_address.[0].ipv4 192.168.61.195 --log_config.global_log_options level,nocolor,time,line_num,function + volumes: + - ../../conf_files/enb.band7.50prb.usrpb200.tm1.conf:/opt/oai-enb/etc/enb.conf + - /dev:/dev + network_mode: "host" + healthcheck: + # pgrep does NOT work + test: /bin/bash -c "ps aux | grep -v grep | grep -c softmodem" + interval: 10s + timeout: 5s + retries: 5 diff --git a/ci-scripts/yaml_files/magma_lte_20892/docker-compose.yml b/ci-scripts/yaml_files/magma_lte_20892/docker-compose.yml new file mode 100644 index 0000000000..eef386304c --- /dev/null +++ b/ci-scripts/yaml_files/magma_lte_20892/docker-compose.yml @@ -0,0 +1,198 @@ +version: '3.8' + +services: + cassandra: + image: cassandra:2.1 + container_name: prod-cassandra + networks: + private_net: + ipv4_address: 192.168.68.2 + environment: + CASSANDRA_CLUSTER_NAME: "OAI HSS Cluster" + CASSANDRA_ENDPOINT_SNITCH: GossipingPropertyFileSnitch + healthcheck: + test: /bin/bash -c "nodetool status" + interval: 10s + timeout: 5s + retries: 5 + + db_init: + image: cassandra:2.1 + container_name: prod-db-init + depends_on: [cassandra] + deploy: + restart_policy: + condition: on-failure + max_attempts: 10 + networks: + private_net: + ipv4_address: 192.168.68.4 + volumes: + - ./oai_db.cql:/home/oai_db.cql + entrypoint: /bin/bash -c "cqlsh --file /home/oai_db.cql 192.168.68.2 && echo 'OK'" + + oai_hss: + image: oaisoftwarealliance/oai-hss:develop + container_name: prod-oai-hss + privileged: true + depends_on: [cassandra] + networks: + private_net: + ipv4_address: 192.168.68.3 + public_net: + ipv4_address: 192.168.61.194 + environment: + TZ: Europe/Paris + REALM: openairinterface.org + HSS_FQDN: hss.openairinterface.org + PREFIX: /openair-hss/etc + cassandra_Server_IP: 192.168.68.2 + OP_KEY: 1006020f0a478bf6b699f15c062e42b3 + LTE_K: FEC86BA6EB707ED08905757B1BB44B8F + APN1: oai.ipv4 + APN2: oai2.ipv4 + FIRST_IMSI: 208921000000001 + NB_USERS: 10 + healthcheck: + test: /bin/bash -c "pgrep oai_hss" + interval: 10s + timeout: 5s + retries: 5 + + redis: + image: redis:6.0.5 + container_name: prod-redis + privileged: true + networks: + public_net: + ipv4_address: 192.168.61.198 + volumes: + - ./redis_extern.conf:/usr/local/etc/redis/redis.conf + entrypoint: /bin/bash -c "redis-server /usr/local/etc/redis/redis.conf" + healthcheck: + test: /bin/bash -c "redis-cli -h 192.168.61.198 -p 6380 ping" + interval: 10s + timeout: 5s + retries: 5 + + magma_mme: + image: magma-mme:production + container_name: prod-magma-mme + hostname: mme + privileged: true + depends_on: [oai_hss, redis] + networks: + public_net: + ipv4_address: 192.168.61.195 + environment: + TZ: Europe/Paris + REALM: openairinterface.org + PREFIX: /openair-mme/etc + HSS_HOSTNAME: hss + HSS_FQDN: hss.openairinterface.org + HSS_REALM: openairinterface.org + MME_FQDN: mme.openairinterface.org + FEATURES: mme_oai + volumes: + - ./mme_fd.sprint.conf:/magma-mme/etc/mme_fd.conf.tmplt + - ./mme.conf:/magma-mme/etc/mme.conf + - ./entrypoint.sh:/magma-mme/bin/entrypoint.sh + entrypoint: /bin/bash -c "/magma-mme/bin/entrypoint.sh" + healthcheck: + test: /bin/bash -c "pgrep oai_mme" + interval: 10s + timeout: 5s + retries: 5 + + oai_spgwc: + image: oaisoftwarealliance/oai-spgwc:develop + privileged: true + depends_on: [magma_mme] + container_name: prod-oai-spgwc + networks: + public_net: + ipv4_address: 192.168.61.196 + environment: + TZ: Europe/Paris + SGW_INTERFACE_NAME_FOR_S11: eth0 + PGW_INTERFACE_NAME_FOR_SX: eth0 + DEFAULT_DNS_IPV4_ADDRESS: 172.21.3.100 + DEFAULT_DNS_SEC_IPV4_ADDRESS: 8.8.4.4 + PUSH_PROTOCOL_OPTION: 'true' + APN_NI_1: oai.ipv4 + APN_NI_2: oai2.ipv4 + DEFAULT_APN_NI_1: oai.ipv4 + UE_IP_ADDRESS_POOL_1: '12.1.1.2 - 12.1.1.254' + UE_IP_ADDRESS_POOL_2: '12.0.0.2 - 12.0.0.254' + MCC: '208' + MNC: '92' + MNC03: '092' + TAC: 1 + GW_ID: 1 + REALM: openairinterface.org + UE_MTU_IPV4: 1500 + healthcheck: + test: /bin/bash -c "pgrep oai_spgwc" + interval: 10s + timeout: 5s + retries: 5 + + oai_spgwu: + image: oaisoftwarealliance/oai-spgwu-tiny:develop + privileged: true + container_name: prod-oai-spgwu-tiny + depends_on: [oai_spgwc] + networks: + public_net: + ipv4_address: 192.168.61.197 + environment: + TZ: Europe/Paris + PID_DIRECTORY: /var/run + INSTANCE: 1 + SGW_INTERFACE_NAME_FOR_S1U_S12_S4_UP: eth0 + PGW_INTERFACE_NAME_FOR_SGI: eth0 + SGW_INTERFACE_NAME_FOR_SX: eth0 + SPGWC0_IP_ADDRESS: 192.168.61.196 + NETWORK_UE_IP: '12.1.1.0/24' + NETWORK_UE_NAT_OPTION: 'yes' + MCC: '208' + MNC: '92' + MNC03: '092' + TAC: 1 + GW_ID: 1 + REALM: openairinterface.org + healthcheck: + test: /bin/bash -c "pgrep oai_spgwu" + interval: 10s + timeout: 5s + retries: 5 + + trf_gen: + image: oaisoftwarealliance/trf-gen-cn5g:focal + privileged: true + container_name: prod-trf-gen + networks: + public_net: + ipv4_address: 192.168.61.200 + entrypoint: /bin/bash -c "ip route add 12.1.1.0/24 via 192.168.61.197 dev eth0; sleep infinity" + healthcheck: + test: /bin/bash -c "ip route | grep '12.1.1.0'" + interval: 10s + timeout: 5s + retries: 5 + +networks: + private_net: + name: prod-oai-private-net + ipam: + config: + - subnet: 192.168.68.0/26 + driver_opts: + com.docker.network.bridge.name: "oai-priv-net" + public_net: + name: prod-oai-public-net + ipam: + config: + - subnet: 192.168.61.192/26 + driver_opts: + com.docker.network.bridge.name: "oai-pub-net" diff --git a/ci-scripts/yaml_files/magma_lte_20892/entrypoint.sh b/ci-scripts/yaml_files/magma_lte_20892/entrypoint.sh new file mode 100755 index 0000000000..859ff7d98f --- /dev/null +++ b/ci-scripts/yaml_files/magma_lte_20892/entrypoint.sh @@ -0,0 +1,36 @@ +#!/bin/bash + +INSTANCE=1 +PREFIX='/magma-mme/etc' +MY_REALM='openairinterface.org' + +declare -A MME_CONF + +pushd $PREFIX +MME_CONF[@MME_S6A_IP_ADDR@]="192.168.61.195" +MME_CONF[@INSTANCE@]=$INSTANCE +MME_CONF[@PREFIX@]=$PREFIX +MME_CONF[@REALM@]=$MY_REALM +MME_CONF[@MME_FQDN@]="mme.${MME_CONF[@REALM@]}" +MME_CONF[@HSS_HOSTNAME@]='hss' +MME_CONF[@HSS_FQDN@]="${MME_CONF[@HSS_HOSTNAME@]}.${MME_CONF[@REALM@]}" +MME_CONF[@HSS_IP_ADDR@]="192.168.61.194" + +cp mme_fd.conf.tmplt $PREFIX/mme_fd.conf + +for K in "${!MME_CONF[@]}"; do + egrep -lRZ "$K" $PREFIX/mme_fd.conf | xargs -0 -l sed -i -e "s|$K|${MME_CONF[$K]}|g" + ret=$?;[[ ret -ne 0 ]] && echo "Tried to replace $K with ${MME_CONF[$K]}" +done + +sed -i -e "s@etc/freeDiameter@etc@" /magma-mme/etc/mme_fd.conf +sed -i -e "s@bind: 127.0.0.1@bind: 192.168.61.198@" /etc/magma/redis.yml +# Generate freeDiameter certificate +popd +cd /magma-mme/scripts +./check_mme_s6a_certificate $PREFIX mme.${MME_CONF[@REALM@]} + +cd /magma-mme +nohup /magma-mme/bin/sctpd > /var/log/sctpd.log 2>&1 & +sleep 5 +/magma-mme/bin/oai_mme -c /magma-mme/etc/mme.conf diff --git a/ci-scripts/yaml_files/magma_lte_20892/mme.conf b/ci-scripts/yaml_files/magma_lte_20892/mme.conf new file mode 100644 index 0000000000..38f53ed354 --- /dev/null +++ b/ci-scripts/yaml_files/magma_lte_20892/mme.conf @@ -0,0 +1,133 @@ +# generated by generate_mme_config_script.py +MME : +{ + REALM = "openairinterface.org" + PID_DIRECTORY = "/var/run"; + MAXENB = 8; # power of 2 + MAXUE = 16; # power of 2 + RELATIVE_CAPACITY = 10; + + EMERGENCY_ATTACH_SUPPORTED = "no"; + UNAUTHENTICATED_IMSI_SUPPORTED = "no"; + + # EPS network feature support + EPS_NETWORK_FEATURE_SUPPORT_IMS_VOICE_OVER_PS_SESSION_IN_S1 = "no"; # DO NOT CHANGE + EPS_NETWORK_FEATURE_SUPPORT_EMERGENCY_BEARER_SERVICES_IN_S1_MODE = "no"; # DO NOT CHANGE + EPS_NETWORK_FEATURE_SUPPORT_LOCATION_SERVICES_VIA_EPC = "no"; # DO NOT CHANGE + EPS_NETWORK_FEATURE_SUPPORT_EXTENDED_SERVICE_REQUEST = "no"; # DO NOT CHANGE + + # Display statistics about whole system (expressed in seconds) + MME_STATISTIC_TIMER = 10; + IP_CAPABILITY = "IPV4"; # UE PDN_TYPE + USE_STATELESS = ""; + + INTERTASK_INTERFACE : + { + # max queue size per task + ITTI_QUEUE_SIZE = 2000000; + }; + + S6A : + { + S6A_CONF = "/magma-mme/etc/mme_fd.conf"; # YOUR MME freeDiameter config file path + HSS_HOSTNAME = "hss.openairinterface.org"; + HSS_REALM = "openairinterface.org"; + }; + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 8; + SCTP_OUTSTREAMS = 8; + }; + + # ------- S1AP definitions + S1AP : + { + # outcome drop timer value (seconds) + S1AP_OUTCOME_TIMER = 10; + }; + + # ------- MME served GUMMEIs + GUMMEI_LIST = ( + { MCC="208" ; MNC="92"; MME_GID="32768" ; MME_CODE="3"; } + ); + + # ------- MME served TAIs + TAI_LIST = ( + {MCC="208" ; MNC="92"; TAC = "1"; } + ); + + TAC_LIST = ( + {MCC="208" ; MNC="92"; TAC = "1"; } + ); + + CSFB : + { + NON_EPS_SERVICE_CONTROL = "OFF"; + CSFB_MCC = "208"; + CSFB_MNC = "92"; + LAC = "1"; + }; + NAS : + { + ORDERED_SUPPORTED_INTEGRITY_ALGORITHM_LIST = [ "EIA2" , "EIA1" , "EIA0" ]; + ORDERED_SUPPORTED_CIPHERING_ALGORITHM_LIST = [ "EEA0" , "EEA1" , "EEA2" ]; + T3402 = 1 # in minutes (default is 12 minutes) + T3412 = 54 # in minutes (default is 54 minutes, network dependent) + T3422 = 6 # in seconds (default is 6s) + T3450 = 6 # in seconds (default is 6s) + T3460 = 6 # in seconds (default is 6s) + T3470 = 6 # in seconds (default is 6s) + T3485 = 8 # UNUSED in seconds (default is 8s) + T3486 = 8 # UNUSED in seconds (default is 8s) + T3489 = 4 # UNUSED in seconds (default is 4s) + T3495 = 8 # UNUSED in seconds (default is 8s) + }; + + SGS : + { + TS6_1 = 10 # in seconds (default is 10s) + TS8 = 4 # in seconds (default is 4s) + TS9 = 2 # in seconds (default is 4s) + TS10 = 4 # in seconds (default is 4s) + TS13 = 4 # in seconds (default is 4s) + }; + + NETWORK_INTERFACES : + { + MME_INTERFACE_NAME_FOR_S1_MME = "eth0"; + MME_IPV4_ADDRESS_FOR_S1_MME = "192.168.61.195/24"; + MME_INTERFACE_NAME_FOR_S11_MME = "eth0"; + MME_IPV4_ADDRESS_FOR_S11_MME = "192.168.61.195/24"; + MME_PORT_FOR_S11_MME = 2123; + }; + + LOGGING : + { + OUTPUT = "CONSOLE"; + THREAD_SAFE = "no"; + COLOR = "no"; + + SCTP_LOG_LEVEL = "ERROR"; + GTPV1U_LOG_LEVEL = "INFO"; + SPGW_APP_LOG_LEVEL = "INFO"; + UDP_LOG_LEVEL = "INFO"; + S1AP_LOG_LEVEL = "DEBUG"; + NAS_LOG_LEVEL = "INFO"; + MME_APP_LOG_LEVEL = "DEBUG"; + GTPV2C_LOG_LEVEL = "INFO"; + S11_LOG_LEVEL = "DEBUG"; + S6A_LOG_LEVEL = "DEBUG"; + UTIL_LOG_LEVEL = "INFO"; + ITTI_LOG_LEVEL = "ERROR"; + MME_SCENARIO_PLAYER_LOG_LEVEL = "ERROR"; + ASN1_VERBOSITY = "INFO"; + }; + + S-GW : + { + SGW_IPV4_ADDRESS_FOR_S11 = "192.168.61.196"; + }; +}; diff --git a/ci-scripts/yaml_files/magma_lte_20892/mme_fd.sprint.conf b/ci-scripts/yaml_files/magma_lte_20892/mme_fd.sprint.conf new file mode 100644 index 0000000000..6f87ed8c2b --- /dev/null +++ b/ci-scripts/yaml_files/magma_lte_20892/mme_fd.sprint.conf @@ -0,0 +1,169 @@ +# -------- Local --------- + +# Uncomment if the framework cannot resolv it. +Identity = "@MME_FQDN@"; +Realm = "@REALM@"; + +# TLS configuration (see previous section) +TLS_Cred = "@PREFIX@/freeDiameter/mme.cert.pem", + "@PREFIX@/freeDiameter/mme.key.pem"; +TLS_CA = "@PREFIX@/freeDiameter/mme.cacert.pem"; + +# Disable use of TCP protocol (only listen and connect in SCTP) +# Default : TCP enabled +No_SCTP; + +# This option is ignored if freeDiameter is compiled with DISABLE_SCTP option. +# Prefer TCP instead of SCTP for establishing new connections. +# This setting may be overwritten per peer in peer configuration blocs. +# Default : SCTP is attempted first. +Prefer_TCP; + + +No_IPv6; + +# Overwrite the number of SCTP streams. This value should be kept low, +# especially if you are using TLS over SCTP, because it consumes a lot of +# resources in that case. See tickets 19 and 27 for some additional details on +# this. +# Limit the number of SCTP streams +SCTP_streams = 3; + + +# By default, freeDiameter acts as a Diameter Relay Agent by forwarding all +# messages it cannot handle locally. This parameter disables this behavior. +NoRelay; + +# Use RFC3588 method for TLS protection, where TLS is negociated after CER/CEA exchange is completed +# on the unsecure connection. The alternative is RFC6733 mechanism, where TLS protects also the +# CER/CEA exchange on a dedicated secure port. +# This parameter only affects outgoing connections. +# The setting can be also defined per-peer (see Peers configuration section). +# Default: use RFC6733 method with separate port for TLS. + +#TLS_old_method; + +AppServThreads = 4; + +# Specify the addresses on which to bind the listening server. This must be +# specified if the framework is unable to auto-detect these addresses, or if the +# auto-detected values are incorrect. Note that the list of addresses is sent +# in CER or CEA message, so one should pay attention to this parameter if some +# adresses should be kept hidden. +ListenOn = "@MME_S6A_IP_ADDR@"; + +Port = 3870; +SecPort = 5870; + +# -------- Extensions --------- + +# Uncomment (and create rtd.conf) to specify routing table for this peer. +#LoadExtension = "/usr/local/lib/freeDiameter/rt_default.fdx" : "rtd.conf"; + +#LoadExtension = "/usr/local/lib/freeDiameter/_sample.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/app_acct.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/app_diameap.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/app_radgw.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/app_redirect.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/app_sip.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/dbg_interactive.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/dbg_monitor.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/dbg_msg_dumps.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/dbg_msg_timings.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/dbg_rt.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_3gpp2_avps.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/dict_CreditControl.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/dict_CxDx.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/dict_Gx.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/dict_NAS.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/dict_Ro.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/dict_Rx.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/dict_S6mS6n.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/dict_SGd.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/dict_SLh.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/dict_Sd.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/dict_Sh.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/dict_T4.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/dict_T6aT6bT7.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/dict_Tsp.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/dict_dcca.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/dict_dcca_3gpp.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/dict_dcca_starent.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_draftload_avps.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/dict_eap.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_etsi283034_avps.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/dict_legacy_xml.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/dict_mip6a.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/dict_mip6i.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/dict_nas_mipv6.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/dict_nasreq.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_rfc4004_avps.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_rfc4006bis_avps.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_rfc4072_avps.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_rfc4590_avps.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_rfc5447_avps.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_rfc5580_avps.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_rfc5777_avps.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_rfc5778_avps.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_rfc6734_avps.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_rfc6942_avps.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_rfc7155_avps.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_rfc7683_avps.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_rfc7944_avps.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/dict_sip.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29061_avps.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29128_avps.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29154_avps.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29173_avps.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29212_avps.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29214_avps.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29215_avps.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29217_avps.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29229_avps.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29272_avps.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29273_avps.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29329_avps.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29336_avps.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29337_avps.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29338_avps.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29343_avps.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29344_avps.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29345_avps.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29368_avps.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_ts29468_avps.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_ts32299_avps.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/rt_busypeers.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/rt_default.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/rt_ereg.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/rt_ignore_dh.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/rt_load_balance.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/rt_randomize.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/rt_redirect.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/test_acct.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/test_app.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/test_hss.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/test_netemul.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/test_rt_any.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/test_sip.fdx"; +#LoadExtension = "/usr/local/lib/freeDiameter/dict_Rf.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_S6as6d.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_S6t.fdx"; +LoadExtension = "/usr/local/lib/freeDiameter/dict_S6c.fdx"; + + +# -------- Peers --------- + +# The framework will actively attempt to establish and maintain a connection +# with the peers listed here. +# For only accepting incoming connections, see the acl_wl.fx extension. + +# ConnectPeer +# Declare a remote peer to which this peer must maintain a connection. +# In addition, this allows specifying non-default parameters for this peer only +# (for example disable SCTP with this peer, or use RFC3588-flavour TLS). +# Note that by default, if a peer is not listed as a ConnectPeer entry, an +# incoming connection from this peer will be rejected. If you want to accept +# incoming connections from other peers, see the acl_wl.fdx? extension which +# allows exactly this. + +ConnectPeer= "@HSS_FQDN@" { ConnectTo = "@HSS_IP_ADDR@"; No_SCTP ; No_IPv6; Prefer_TCP; No_TLS; port = 3868;}; diff --git a/ci-scripts/yaml_files/magma_lte_20892/redis_extern.conf b/ci-scripts/yaml_files/magma_lte_20892/redis_extern.conf new file mode 100644 index 0000000000..565524080a --- /dev/null +++ b/ci-scripts/yaml_files/magma_lte_20892/redis_extern.conf @@ -0,0 +1,33 @@ +# +# Copyright (c) 2016-present, Facebook, Inc. +# All rights reserved. +# +# This source code is licensed under the BSD-style license found in the +# LICENSE file in the root directory of this source tree. An additional grant +# of patent rights can be found in the PATENTS file in the same directory. + +# Jinja template for Redis configuration +# See the default config file for options and explanations: +# https://github.com/antirez/redis/blob/unstable/redis.conf + +# TODO: make sensible, production-aware config decisions + +bind 192.168.61.198 +port 6380 + +daemonize no +loglevel notice + +timeout 0 +databases 1 + +dbfilename redis_dump.rdb +dir /data + +# Save the DB on disk + +save 900 1 + +save 300 10 + +save 60 1000 diff --git a/ci-scripts/yaml_files/sa_e1_b200_gnb/docker-compose.yml b/ci-scripts/yaml_files/sa_e1_b200_gnb/docker-compose.yml new file mode 100644 index 0000000000..5b6e03db16 --- /dev/null +++ b/ci-scripts/yaml_files/sa_e1_b200_gnb/docker-compose.yml @@ -0,0 +1,68 @@ +version: '3.8' + +services: + gnb_cucp: + image: oai-gnb:latest + privileged: true + container_name: sa-cucp-gnb + environment: + USE_ADDITIONAL_OPTIONS: --sa --log_config.global_log_options level,nocolor,time,line_num,function + volumes: + - ../../conf_files/gnb-cucp.sa.f1.quectel.conf:/opt/oai-gnb/etc/gnb.conf + networks: + public_net: + ipv4_address: 192.168.68.194 + healthcheck: + # pgrep does NOT work + test: /bin/bash -c "ps aux | grep -v grep | grep -c softmodem" + interval: 10s + timeout: 5s + retries: 5 + + gnb_cuup: + image: oai-nr-cuup:latest + privileged: true + container_name: sa-cuup-gnb + environment: + USE_ADDITIONAL_OPTIONS: --sa --log_config.global_log_options level,nocolor,time,line_num,function + volumes: + - ../../conf_files/gnb-cuup.sa.f1.quectel.conf:/opt/oai-gnb/etc/gnb.conf + networks: + public_net: + ipv4_address: 192.168.68.196 + healthcheck: + # pgrep does NOT work + test: /bin/bash -c "ps aux | grep -v grep | grep -c nr-cuup" + interval: 10s + timeout: 5s + retries: 5 + + gnb_du_tdd: + image: oai-gnb:latest + privileged: true + container_name: sa-du-b200-gnb + environment: + USE_B2XX: 'yes' + USE_ADDITIONAL_OPTIONS: --sa --RUs.[0].sdr_addrs serial=30C51D4 --continuous-tx -E --log_config.global_log_options level,nocolor,time,line_num,function --gNBs.[0].min_rxtxtime 2 --gNBs.[0].do_CSIRS 1 --gNBs.[0].do_SRS 1 --RUs.[0].att_rx 14 --RUs.[0].att_tx 14 + volumes: + - ../../conf_files/gnb-du.sa.band78.106prb.usrpb200.conf:/opt/oai-gnb/etc/gnb.conf + - /dev:/dev + networks: + public_net: + ipv4_address: 192.168.68.195 + #entrypoint: /bin/bash -c "sleep infinity" + healthcheck: + # pgrep does NOT work + test: /bin/bash -c "ps aux | grep -v grep | grep -c softmodem" + interval: 10s + timeout: 5s + retries: 5 + +networks: + public_net: + name: sa-b200-gnb-net + ipam: + config: + - subnet: 192.168.68.192/26 + driver_opts: + com.docker.network.bridge.name: "sa-gnb-net" diff --git a/ci-scripts/yaml_files/sa_f1_b200_gnb/docker-compose.yml b/ci-scripts/yaml_files/sa_f1_b200_gnb/docker-compose.yml index d5396e4933..e40dc686d7 100644 --- a/ci-scripts/yaml_files/sa_f1_b200_gnb/docker-compose.yml +++ b/ci-scripts/yaml_files/sa_f1_b200_gnb/docker-compose.yml @@ -6,11 +6,9 @@ services: privileged: true container_name: sa-cu-gnb environment: - USE_B2XX: 'yes' USE_ADDITIONAL_OPTIONS: --sa --log_config.global_log_options level,nocolor,time,line_num,function volumes: - ../../conf_files/gnb-cu.sa.band78.106prb.usrpb200.conf:/opt/oai-gnb/etc/gnb.conf - - /dev:/dev networks: public_net: ipv4_address: 192.168.68.194 diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index cb66d4f862..a9241bf3b3 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -120,6 +120,8 @@ Options: Builds Coverity-Scan objects for upload --disable-deadline Disables deadline scheduler of Linux kernel (>=3.14.x). +--trace-asn1c-enc-dec + Output asn1c logging traces via OAI logging system. --enable-deadline Enable deadline scheduler of Linux kernel (>=3.14.x). --disable-cpu-affinity @@ -416,6 +418,10 @@ function main() { sleep 2 CMAKE_CMD="$CMAKE_CMD -DSANITIZE_MEMORY=ON -DSANITIZE_ADDRESS=OFF -DSANITIZE_UNDEFINED=OFF" shift;; + --trace-asn1c-enc-dec) + CMAKE_CMD="$CMAKE_CMD -DTRACE_ASN1C_ENC_DEC=ON" + echo_info "Enabling asn1c internal traces via OAI logging system" + shift 1;; -h | --help) print_help exit 1;; diff --git a/common/utils/LOG/log.c b/common/utils/LOG/log.c index f936ed5ae2..eed04ecbae 100644 --- a/common/utils/LOG/log.c +++ b/common/utils/LOG/log.c @@ -45,6 +45,7 @@ #include "common/config/config_userapi.h" #include #include +#include #include "common/utils/LOG/log_extern.h" // main log variables @@ -282,7 +283,7 @@ void log_getconfig(log_t *g_log) int ret = config_get( logparams_defaults,sizeof(logparams_defaults)/sizeof(paramdef_t),CONFIG_STRING_LOG_PREFIX); if (ret <0) { - fprintf(stderr,"[LOG] init aborted, configuration couldn't be performed"); + fprintf(stderr,"[LOG] init aborted, configuration couldn't be performed\n"); return; } @@ -810,7 +811,7 @@ void logClean (void) } } -extern int oai_exit; +static atomic_bool stop_flush_mem_to_file = false; void flush_mem_to_file(void) { int fp; @@ -821,7 +822,7 @@ void flush_mem_to_file(void) pthread_setname_np( pthread_self(), "flush_mem_to_file"); - while (!oai_exit) { + while (!atomic_load(&stop_flush_mem_to_file)) { pthread_mutex_lock(&log_mem_lock); log_mem_write_flag=0; pthread_cond_wait(&log_mem_notify, &log_mem_lock); @@ -981,6 +982,7 @@ void close_log_mem(void){ char f_name[1024]; if(log_mem_flag==1){ + atomic_store(&stop_flush_mem_to_file, false); log_mem_d[0].enable_flag=0; log_mem_d[1].enable_flag=0; usleep(10); // wait for log writing diff --git a/common/utils/T/T_messages.txt b/common/utils/T/T_messages.txt index c535f36f5e..71cd8a5486 100644 --- a/common/utils/T/T_messages.txt +++ b/common/utils/T/T_messages.txt @@ -969,25 +969,25 @@ ID = LEGACY_OSA_TRACE GROUP = ALL:LEGACY_OSA:LEGACY_GROUP_TRACE:LEGACY FORMAT = string,log -ID = LEGACY_ASN_INFO - DESC = ASN legacy logs - info level - GROUP = ALL:LEGACY_ASN:LEGACY_GROUP_INFO:LEGACY +ID = LEGACY_ASN1_INFO + DESC = ASN1 legacy logs - info level + GROUP = ALL:LEGACY_ASN1:LEGACY_GROUP_INFO:LEGACY FORMAT = string,log -ID = LEGACY_ASN_ERROR - DESC = ASN legacy logs - error level - GROUP = ALL:LEGACY_ASN:LEGACY_GROUP_ERROR:LEGACY +ID = LEGACY_ASN1_ERROR + DESC = ASN1 legacy logs - error level + GROUP = ALL:LEGACY_ASN1:LEGACY_GROUP_ERROR:LEGACY FORMAT = string,log -ID = LEGACY_ASN_WARNING - DESC = ASN legacy logs - warning level - GROUP = ALL:LEGACY_ASN:LEGACY_GROUP_WARNING:LEGACY +ID = LEGACY_ASN1_WARNING + DESC = ASN1 legacy logs - warning level + GROUP = ALL:LEGACY_ASN1:LEGACY_GROUP_WARNING:LEGACY FORMAT = string,log -ID = LEGACY_ASN_DEBUG - DESC = ASN legacy logs - debug level - GROUP = ALL:LEGACY_ASN:LEGACY_GROUP_DEBUG:LEGACY +ID = LEGACY_ASN1_DEBUG + DESC = ASN1 legacy logs - debug level + GROUP = ALL:LEGACY_ASN1:LEGACY_GROUP_DEBUG:LEGACY FORMAT = string,log -ID = LEGACY_ASN_TRACE - DESC = ASN legacy logs - trace level - GROUP = ALL:LEGACY_ASN:LEGACY_GROUP_TRACE:LEGACY +ID = LEGACY_ASN1_TRACE + DESC = ASN1 legacy logs - trace level + GROUP = ALL:LEGACY_ASN1:LEGACY_GROUP_TRACE:LEGACY FORMAT = string,log ID = LEGACY_SIM_INFO diff --git a/common/utils/T/tracer/CMakeLists.txt b/common/utils/T/tracer/CMakeLists.txt index b60649d2d4..a587b00243 100644 --- a/common/utils/T/tracer/CMakeLists.txt +++ b/common/utils/T/tracer/CMakeLists.txt @@ -1,4 +1,4 @@ -add_library(tracer_utils OBJECT config.c database.c event.c handler.c utils.c) +add_library(tracer_utils OBJECT configuration.c database.c event.c handler.c utils.c) target_link_libraries(tracer_utils PUBLIC m pthread) add_library(tracer_events OBJECT event_selector.c) diff --git a/common/utils/T/tracer/Makefile b/common/utils/T/tracer/Makefile index 0713d9a3df..6ddf05e65b 100644 --- a/common/utils/T/tracer/Makefile +++ b/common/utils/T/tracer/Makefile @@ -10,7 +10,7 @@ all: record replay extract_config textlog enb ue vcd macpdu2wireshark \ extract_input_subframe extract_output_subframe to_vcd extract multi \ gnb -record: utils.o record.o database.o config.o +record: utils.o record.o database.o configuration.o $(CC) $(CFLAGS) -o record $^ $(LIBS) replay: utils.o replay.o @@ -20,48 +20,48 @@ extract_config: extract_config.o $(CC) $(CFLAGS) -o extract_config $^ $(LIBS) extract_input_subframe: extract_input_subframe.o database.o event.o utils.o \ - config.o + configuration.o $(CC) $(CFLAGS) -o $@ $^ $(LIBS) extract_output_subframe: extract_output_subframe.o database.o event.o utils.o \ - config.o + configuration.o $(CC) $(CFLAGS) -o $@ $^ $(LIBS) -extract: extract.o database.o event.o utils.o config.o +extract: extract.o database.o event.o utils.o configuration.o $(CC) $(CFLAGS) -o $@ $^ $(LIBS) -textlog: utils.o textlog.o database.o event.o handler.o config.o \ +textlog: utils.o textlog.o database.o event.o handler.o configuration.o \ event_selector.o view/view.a gui/gui.a logger/logger.a \ filter/filter.a $(CC) $(CFLAGS) -o textlog $^ $(LIBS) $(XLIBS) -enb: utils.o enb.o database.o event.o handler.o config.o \ +enb: utils.o enb.o database.o event.o handler.o configuration.o \ event_selector.o view/view.a gui/gui.a logger/logger.a \ filter/filter.a $(CC) $(CFLAGS) -o enb $^ $(LIBS) $(XLIBS) -ue: utils.o ue.o database.o event.o handler.o config.o \ +ue: utils.o ue.o database.o event.o handler.o configuration.o \ event_selector.o view/view.a gui/gui.a logger/logger.a \ filter/filter.a $(CC) $(CFLAGS) -o ue $^ $(LIBS) $(XLIBS) -vcd: utils.o vcd.o database.o event.o handler.o config.o \ +vcd: utils.o vcd.o database.o event.o handler.o configuration.o \ event_selector.o view/view.a gui/gui.a logger/logger.a \ filter/filter.a $(CC) $(CFLAGS) -o vcd $^ $(LIBS) $(XLIBS) -to_vcd: to_vcd.o database.o event.o handler.o utils.o config.o \ +to_vcd: to_vcd.o database.o event.o handler.o utils.o configuration.o \ logger/logger.a filter/filter.a $(CC) $(CFLAGS) -o to_vcd $^ $(LIBS) macpdu2wireshark: macpdu2wireshark.o database.o utils.o handler.o event.o \ - config.o + configuration.o $(CC) $(CFLAGS) -o $@ $^ $(LIBS) -multi: multi.o utils.o database.o config.o +multi: multi.o utils.o database.o configuration.o $(CC) $(CFLAGS) -o multi $^ $(LIBS) -gnb: utils.o gnb.o database.o event.o handler.o config.o \ +gnb: utils.o gnb.o database.o event.o handler.o configuration.o \ view/view.a gui/gui.a logger/logger.a \ filter/filter.a $(CC) $(CFLAGS) -o gnb $^ $(LIBS) $(XLIBS) diff --git a/common/utils/T/tracer/config.c b/common/utils/T/tracer/configuration.c similarity index 97% rename from common/utils/T/tracer/config.c rename to common/utils/T/tracer/configuration.c index 723902ec9c..701043c05e 100644 --- a/common/utils/T/tracer/config.c +++ b/common/utils/T/tracer/configuration.c @@ -1,4 +1,4 @@ -#include "config.h" +#include "configuration.h" #include #include #include diff --git a/common/utils/T/tracer/config.h b/common/utils/T/tracer/configuration.h similarity index 100% rename from common/utils/T/tracer/config.h rename to common/utils/T/tracer/configuration.h diff --git a/common/utils/T/tracer/enb.c b/common/utils/T/tracer/enb.c index ea499a68f8..9a4751b67e 100644 --- a/common/utils/T/tracer/enb.c +++ b/common/utils/T/tracer/enb.c @@ -14,7 +14,7 @@ #include "utils.h" #include "event_selector.h" #include "openair_logo.h" -#include "config.h" +#include "configuration.h" /****************************************************************************/ /* conversion from rnti to "ue_id" (which does not really exists) */ diff --git a/common/utils/T/tracer/event.c b/common/utils/T/tracer/event.c index f5d12e472c..41da5c0823 100644 --- a/common/utils/T/tracer/event.c +++ b/common/utils/T/tracer/event.c @@ -1,7 +1,7 @@ #include "event.h" #include "database.h" #include "utils.h" -#include "config.h" +#include "configuration.h" #include #include #include diff --git a/common/utils/T/tracer/extract.c b/common/utils/T/tracer/extract.c index bd1649a31a..fe3177b74a 100644 --- a/common/utils/T/tracer/extract.c +++ b/common/utils/T/tracer/extract.c @@ -4,7 +4,7 @@ #include #include "database.h" #include "event.h" -#include "config.h" +#include "configuration.h" void usage(void) { diff --git a/common/utils/T/tracer/extract_input_subframe.c b/common/utils/T/tracer/extract_input_subframe.c index 48e3ec07f9..78bc288df1 100644 --- a/common/utils/T/tracer/extract_input_subframe.c +++ b/common/utils/T/tracer/extract_input_subframe.c @@ -4,7 +4,7 @@ #include #include "database.h" #include "event.h" -#include "config.h" +#include "configuration.h" void usage(void) { diff --git a/common/utils/T/tracer/extract_output_subframe.c b/common/utils/T/tracer/extract_output_subframe.c index d7f9ff95ed..5c5abb768e 100644 --- a/common/utils/T/tracer/extract_output_subframe.c +++ b/common/utils/T/tracer/extract_output_subframe.c @@ -4,7 +4,7 @@ #include #include "database.h" #include "event.h" -#include "config.h" +#include "configuration.h" void usage(void) { diff --git a/common/utils/T/tracer/gnb.c b/common/utils/T/tracer/gnb.c index 6629a1efd6..a2953cb00d 100644 --- a/common/utils/T/tracer/gnb.c +++ b/common/utils/T/tracer/gnb.c @@ -6,7 +6,7 @@ #include "database.h" #include "event.h" #include "handler.h" -#include "config.h" +#include "configuration.h" #include "logger/logger.h" #include "gui/gui.h" #include "utils.h" diff --git a/common/utils/T/tracer/hacks/Makefile b/common/utils/T/tracer/hacks/Makefile index af2663e48f..f345bb4499 100644 --- a/common/utils/T/tracer/hacks/Makefile +++ b/common/utils/T/tracer/hacks/Makefile @@ -5,18 +5,18 @@ LIBS=-lX11 -lm -lpng -lXft all: dump_nack_signal time_meas timeplot multi-rru-clean -dump_nack_signal: ../utils.o ../database.o ../config.o ../event.o \ +dump_nack_signal: ../utils.o ../database.o ../configuration.o ../event.o \ dump_nack_signal.o $(CC) $(CFLAGS) -o dump_nack_signal $^ $(LIBS) -time_meas: ../utils.o ../database.o ../config.o ../event.o \ +time_meas: ../utils.o ../database.o ../configuration.o ../event.o \ time_meas.o $(CC) $(CFLAGS) -o time_meas $^ $(LIBS) timplot: timeplot.o $(CC) $(CFLAGS) -o timeplot $^ $(LIBS) -multi-rru-clean: ../utils.o ../database.o ../event.o ../config.o multi-rru-clean.o +multi-rru-clean: ../utils.o ../database.o ../event.o ../configuration.o multi-rru-clean.o $(CC) $(CFLAGS) -o $@ $^ $(LIBS) .PHONY: all diff --git a/common/utils/T/tracer/macpdu2wireshark.c b/common/utils/T/tracer/macpdu2wireshark.c index 195bf33335..02720e01f3 100644 --- a/common/utils/T/tracer/macpdu2wireshark.c +++ b/common/utils/T/tracer/macpdu2wireshark.c @@ -7,7 +7,7 @@ #include "database.h" #include "event.h" #include "handler.h" -#include "config.h" +#include "configuration.h" #include "utils.h" #include "packet-mac-lte.h" diff --git a/common/utils/T/tracer/multi.c b/common/utils/T/tracer/multi.c index 6a9de838c6..73fadc37d3 100644 --- a/common/utils/T/tracer/multi.c +++ b/common/utils/T/tracer/multi.c @@ -8,7 +8,7 @@ #include "database.h" #include "utils.h" #include "../T.h" -#include "config.h" +#include "configuration.h" #define DEFAULT_LOCAL_PORT 2022 diff --git a/common/utils/T/tracer/record.c b/common/utils/T/tracer/record.c index a565884e52..e4c059a5ca 100644 --- a/common/utils/T/tracer/record.c +++ b/common/utils/T/tracer/record.c @@ -6,7 +6,7 @@ #include "database.h" #include "utils.h" #include "../T_defs.h" -#include "config.h" +#include "configuration.h" void usage(void) { diff --git a/common/utils/T/tracer/textlog.c b/common/utils/T/tracer/textlog.c index 99cddaf43a..71a928ce80 100644 --- a/common/utils/T/tracer/textlog.c +++ b/common/utils/T/tracer/textlog.c @@ -11,7 +11,7 @@ #include "gui/gui.h" #include "utils.h" #include "event_selector.h" -#include "config.h" +#include "configuration.h" typedef struct { int socket; diff --git a/common/utils/T/tracer/to_vcd.c b/common/utils/T/tracer/to_vcd.c index a3c13aebf9..be3c839115 100644 --- a/common/utils/T/tracer/to_vcd.c +++ b/common/utils/T/tracer/to_vcd.c @@ -8,7 +8,7 @@ #include "database.h" #include "utils.h" #include "handler.h" -#include "config.h" +#include "configuration.h" #include "logger/logger.h" #include "view/view.h" diff --git a/common/utils/T/tracer/ue.c b/common/utils/T/tracer/ue.c index bafa0384f2..31584e0215 100644 --- a/common/utils/T/tracer/ue.c +++ b/common/utils/T/tracer/ue.c @@ -14,7 +14,7 @@ #include "utils.h" #include "event_selector.h" #include "openair_logo.h" -#include "config.h" +#include "configuration.h" typedef struct { view *phyview; diff --git a/common/utils/T/tracer/vcd.c b/common/utils/T/tracer/vcd.c index d4faa5fd84..c57798c4c4 100644 --- a/common/utils/T/tracer/vcd.c +++ b/common/utils/T/tracer/vcd.c @@ -11,7 +11,7 @@ #include "gui/gui.h" #include "utils.h" #include "event_selector.h" -#include "config.h" +#include "configuration.h" typedef struct { int socket; diff --git a/common/utils/config.h b/common/utils/config.h index 6d15a309c9..91aabe1347 100644 --- a/common/utils/config.h +++ b/common/utils/config.h @@ -22,12 +22,15 @@ #ifndef UTILS_CONFIG_H_ASN1 #define UTILS_CONFIG_H_ASN1 -// This is hard coded file name "config.h" and HAVE_CONFIG_H_ in asn1c skeletons +// This is hard coded file name "config.h" in asn1c skeletons /* * This file "config.h" will be used by asn1c if HAVE_CONFIG_H_ is defined and - * included. This logs asn1c encoder and decoder traces at execution time using - * the regular OAI logging system, i.e., LOG_I(ASN1...); + * included (this is the case for OAI). + * This allows to trace the asn1c encoder and decoder at execution time using + * the regular OAI logging system, i.e., LOG_I(ASN1, ...); + * + * to enable it, at compilation time, see ./build_oai --enable-asn1c-debug * * As it is very verbose, note that you can change the log level per module in * source or in gdb, e.g., to only activate it for a short time. @@ -47,7 +50,7 @@ */ #include "common/utils/LOG/log.h" -#if DEBUG_ASN1C +#if TRACE_ASN1C_ENC_DEC #define ASN_DEBUG(x...) do{ LOG_I(ASN1,x);LOG_I(ASN1,"\n"); } while(false) #else #define ASN_DEBUG(x...) diff --git a/common/utils/nr/nr_common.c b/common/utils/nr/nr_common.c index 4ffbe71ded..4b0722a79c 100644 --- a/common/utils/nr/nr_common.c +++ b/common/utils/nr/nr_common.c @@ -240,11 +240,16 @@ int NRRIV2PRBOFFSET(int locationAndBandwidth,int N_RB) { } /* TS 38.214 ch. 6.1.2.2.2 - Resource allocation type 1 for DL and UL */ -int PRBalloc_to_locationandbandwidth0(int NPRB,int RBstart,int BWPsize) { - AssertFatal(NPRB>0 && (NPRB + RBstart <= BWPsize),"Illegal NPRB/RBstart Configuration (%d,%d) for BWPsize %d\n",NPRB,RBstart,BWPsize); +int PRBalloc_to_locationandbandwidth0(int NPRB, int RBstart, int BWPsize) +{ + AssertFatal(NPRB>0 && (NPRB + RBstart <= BWPsize), + "Illegal NPRB/RBstart Configuration (%d,%d) for BWPsize %d\n", + NPRB, RBstart, BWPsize); - if (NPRB <= 1+(BWPsize>>1)) return(BWPsize*(NPRB-1)+RBstart); - else return(BWPsize*(BWPsize+1-NPRB) + (BWPsize-1-RBstart)); + if (NPRB <= 1 + (BWPsize >> 1)) + return (BWPsize * (NPRB - 1) + RBstart); + else + return (BWPsize * (BWPsize + 1 - NPRB) + (BWPsize - 1 - RBstart)); } int PRBalloc_to_locationandbandwidth(int NPRB,int RBstart) { diff --git a/doc/FEATURE_SET.md b/doc/FEATURE_SET.md index f8d9c460d4..55596ea556 100644 --- a/doc/FEATURE_SET.md +++ b/doc/FEATURE_SET.md @@ -18,6 +18,351 @@ ![Block Diagram](./oai_enb_block_diagram.png) +# OpenAirInterface 5G-NR Feature Set # + +## General Parameters + +The following features are valid for the gNB and the 5G-NR UE. + +* Static TDD, FDD +* Normal CP +* Subcarrier spacings: 15 and 30kHz (FR1), 120kHz (FR2) +* Bandwidths: 10, 20, 40, 60, 80, 100MHz +* Intermediate downlink and uplink frequencies to interface with IF equipment +* Procedures for 2-layer DL and UL MIMO +* Slot format: 14 OFDM symbols in UL or DL +* Highly efficient 3GPP compliant LDPC encoder and decoder (BG1 and BG2 supported) +* Highly efficient 3GPP compliant polar encoder and decoder +* Encoder and decoder for short blocks +* Support for UL transform precoding (SC-FDMA) + +Furthermore, the gNB and UE support + +* "noS1" mode (DL and UL): + - Creates TUN interface to PDCP to inject and receive user-place traffic + - No connection to the core network +* Standalone (SA) mode: + - UE can register with the 5G Core Network through the gNB, establish a PDU Session and exchange user-plane traffic + + +## gNB PHY + +* 15kHz and 30kHz SCS for FR1 and 120kHz SCS for FR2 +* Generation of NR-PSS/NR-SSS +* NR-PBCH supports multiple SSBs and flexible periodicity +* Generation of NR-PDCCH (including generation of DCI, polar encoding, scrambling, modulation, RB mapping, etc) + - common search space + - user-specific search space + - DCI formats: 00, 10, 01 and 11 +* Generation of NR-PDSCH (including Segmentation, LDPC encoding, rate matching, scrambling, modulation, RB mapping, etc). + - PDSCH mapping type A and B + - DMRS configuration type 1 and 2 + - Single and multiple DMRS symbols + - PTRS support + - Support for 1, 2 and 4 TX antennas + - Support for up to 2 layers (currently limited to DMRS configuration type 2) + - Support for 256 QAM +* NR-CSIRS Generation of sequence at PHY +* NR-PUSCH (including Segmentation, LDPC encoding, rate matching, scrambling, modulation, RB mapping, etc). + - PUSCH mapping type A and B + - DMRS configuration type 1 and 2 + - Single and multiple DMRS symbols + - PTRS support + - Support for up to 2 RX antenna + - Support for up to 2 layers + - Support for 256 QAM +* NR-PUCCH + - Format 0 (2 bits, for ACK/NACK and SR) + - Format 2 (mainly for CSI feedback) +* NR-SRS + - SRS signal reception + - Channel estimation (with T tracer real time monitoring) + - Power noise estimation +* NR-PRS + - Rel16 Positioning reference signal(PRS) generation and modulation + - Multiple PRS resources, one per beam is supported in FR2 TDD mode + - FR1 and FR2 support with config file +* NR-PRACH + - Formats 0,1,2,3, A1-A3, B1-B3 +* Highly efficient 3GPP compliant LDPC encoder and decoder (BG1 and BG2 are supported) +* Highly efficient 3GPP compliant polar encoder and decoder +* Encoder and decoder for short block + +## gNB MAC + +- MAC -> PHY configuration using NR FAPI P5 interface +- MAC <-> PHY data interface using FAPI P7 interface for BCH PDU, DCI PDU, PDSCH PDU +- Scheduler procedures for SIB1 +- Scheduler procedures for RA + - Contention Free RA procedure + - Contention Based RA procedure + - Msg3 can transfer uplink CCCH, DTCH or DCCH messages + - CBRA can be performed using MAC CE or C-RNTI +- Scheduler procedures for CSI-RS +- MAC downlink scheduler + - phy-test scheduler (fixed allocation and usable also without UE) + - regular scheduler with dynamic proportionally-fair allocation + - MCS adaptation from HARQ BLER +- MAC header generation (including timing advance) +- ACK / NACK handling and HARQ procedures for downlink +- MAC uplink scheduler + - phy-test scheduler (fixed allocation) + - regular scheduler with dynamic proportionally-fair allocation + - HARQ procedures for uplink +- Scheduler procedures for SRS reception + - Periodic SRS reception + - Channel rank computation up to 2x2 scenario + - TPMI computation based on SRS up 4 antenna ports and 2 layers +- MAC procedures to handle CSI measurement report + - evalution of RSRP report + - evaluation of CQI report +- MAC scheduling of SR reception +- Bandwidth part (BWP) operation + - Handle multiple dedicated BWPs, supports one UE + - BWP switching through RRCReconfiguration method + +## gNB RLC + +- Send/Receive operations according to 38.322 Rel.16 + - Segmentation and reassembly procedures + - RLC Acknowledged mode supporting PDU retransmissions + - RLC Unacknowledged mode + - DRBs and SRBs establishment/handling and association with RLC entities + - Timers implementation + - Interfaces with PDCP, MAC + - Interfaces with gtp-u (data Tx/Rx over F1-U at the DU) + +## gNB PDCP + +- Send/Receive operations according to 38.323 Rel.16 + - Integrity protection and ciphering procedures + - Sequence number management, SDU dicard and in-order delivery + - Radio bearer establishment/handling and association with PDCP entities + - Interfaces with RRC, RLC + - Interfaces with gtp-u (data Tx/Rx over N3 and F1-U interfaces) + +## gNB SDAP + +- Send/Receive operations according to 37.324 Rel.15 + - Establishment/Handling of SDAP entities. + - Transfer of User Plane Data + - Mapping between a QoS flow and a DRB for both DL and UL + - Marking QoS flow ID in both DL and UL packets + - Reflective QoS flow to DRB mapping for UL SDAP data PDUs + +## gNB RRC + +- NR RRC (38.331) Rel 17 messages using new [asn1c](https://github.com/mouse07410/asn1c) +- LTE RRC (36.331) also updated to Rel 15 +- Generation of CellGroupConfig (for eNB) and MIB +- Generation of system information block 1 (SIB1) +- Generation of system information block 2 (SIB2) +- Application to read configuration file and program gNB RRC +- RRC can configure PDCP, RLC, MAC +- Interface with GTP-U (tunnel creation/handling for S1-U (NSA), N3 (SA) interfaces) +- Integration of RRC messages and procedures supporting UE 5G SA connection + - RRCSetupRequest/RRCSetup/RRCSetupComplete + - RRC Uplink/Downlink Information transfer carrying NAS messages transparently + - RRC Reconfiguration/Reconfiguration complete + - RRC Reestablishment/Reestablishment complete + - Support for master cell group configuration + - Interface with NGAP for the interactions with the AMF + - Interface with F1AP for CU/DU split deployment option + - Periodic RRC measurements of serving cell (no A/B events) + +## gNB X2AP + +- Integration of X2AP messages and procedures for the exchanges with the eNB over X2 interface supporting the NSA setup according to 36.423 Rel. 15 + - X2 setup with eNB + - Handling of SgNB Addition Request/Addition Request Acknowledge/Reconfiguration Complete + +## gNB NGAP + +- Integration of NGAP messages and procedures for the exchanges with the AMF over N2 interface according to 38.413 Rel. 15 + - NGAP Setup request/response + - NGAP Initial UE message + - NGAP Initial context setup request/response + - NGAP Downlink/Uplink NAS transfer + - NGAP UE context release request/complete + - NGAP UE radio capability info indication + - NGAP PDU session resource setup request/response +- Interface with RRC + +## gNB F1AP + +- Integration of F1AP messages and procedures for the control plane exchanges between the CU and DU entities according to 38.473 Rel. 16 + - F1 Setup request/response + - F1 DL/UL RRC message transfer + - F1 Initial UL RRC message transfer + - F1 UE Context setup request/response + - F1 UE Context modification request/response + - F1 UE Context release + - F1 gNB CU configuration update +- Interface with RRC +- Interface with gtp-u (tunnel creation/handling for F1-U interface) + +## gNB E1AP + +- Integration of E1AP messages and procedures for exchange between CU-CP and CU-UP according to 38.463 Rel. 16 + - gNB-CU-UP E1 Setup Setup request/response + - E1 Bearer Context Setup + - Bearer Context Modification (gNB-CU-CP initiated) +- Interface with RRC and PDCP + +## gNB GTP-U + +- New GTP-U implementation supporting both N3 and F1-U interfaces according to 29.281 Rel.15 + - Interfaces with RRC, F1AP for tunnel creation + - Interfaces with PDCP and RLC for data send/receive at the CU and DU respectively (F1-U interface) + - Interface with SDAP for data send/receive, capture of GTP-U Optional Header, GTP-U Extension Header and PDU Session Container. + +# OpenAirInterface 5G-NR UE Feature Set # + +## NR UE PHY Layer ## + +* Initial synchronization + - the UE needs to know the position in frequency of the SSBs (via command line parameter in SA) +* Time tracking based on PBCH DMRS +* Frequency offset estimation based on PSS and SSS +* 15kHz and 30kHz SCS for FR1 and 120 kHz SCS for FR2 +* Reception of NR-PSS/NR-SSS +* NR-PBCH supports multiple SSBs and flexible periodicity + - RSRP measurement for the strongest SSB +* Reception of NR-PDCCH (including reception of DCI, polar decoding, de-scrambling, de-modulation, RB de-mapping, etc) + - common search space configured by MIB + - user-specific search space configured by RRC + - DCI formats: 00, 10, 01 and 11 +* Reception of NR-PDSCH (including Segmentation, LDPC decoding, rate de-matching, de-scrambling, de-modulation, RB de-mapping, etc). + - PDSCH mapping type A and B + - DMRS configuration type 1 and 2 + - Single and multiple DMRS symbols + - PTRS support + - Support for 256 QAM + - Support for 1, 2 and 4 RX antennas + - Support for up to 2 layers (currently limited to DMRS configuration type 2) +* Measurements based on NR-CSIRS + - RSRP measurements + - RI, PMI and CQI computation + - Support for up to 4 RX antennas + - Support for up to 2 layers +* NR-PUSCH (including Segmentation, LDPC encoding, rate matching, scrambling, modulation, RB mapping, etc). + - PUSCH mapping type A and B + - DMRS configuration type 1 and 2 + - Single and multiple DMRS symbols + - PTRS support + - Support for 256 QAM + - Support for up to 2 TX antenna + - Support for up to 2 layers +* NR-PUCCH + - Format 0 (2 bits for ACK/NACK and SR) + - Format 2 (mainly for CSI feedback) + - Format 1 (limited testing) + - Format 3 and 4 present but old code never tested (need restructuring before verification) +* NR-SRS + - Generation of sequence at PHY + - SRS signal transmission +* NR-PRS + - PRS based Channel estimation with T tracer dumps + - Time of arrival(ToA) estimation based on channel impulse response(CIR) + - Finer ToA estimation by 16x oversampled IDFT for CIR + - Support for multiple gNB reception with gNBs synced via GPSDO +* NR-PRACH + - Formats 0,1,2,3, A1-A3, B1-B3 +* Highly efficient 3GPP compliant LDPC encoder and decoder (BG1 and BG2 are supported) +* Highly efficient 3GPP compliant polar encoder and decoder +* Encoder and decoder for short block + +## NR UE FAPI ## + +* MAC -> PHY configuration via UE FAPI P5 interface +* Basic MAC to control PHY via UE FAPI P7 interface +* PHY -> MAC indication (needs some improvement) + +## NR UE Higher Layers ## + +## UE MAC + +* Minimum system information (MSI) + - MIB processing + - Scheduling of system information block 1 (SIB1) reception +* Random access procedure (needs improvement, there is still not a clear separation between MAC and PHY) + - Mapping SSBs to multiple ROs + - Scheduling of PRACH + - Processing of RAR + - Transmission and re-transmission of Msg3 + - Msg4 and contention resolution +* DCI processing + - format 10 (RA-RNTI, C-RNTI, SI-RNTI, TC-RNTI) + - format 00 (C-RNTI, TC-RNTI) + - format 11 (C-RNTI) + - format 01 (C-RNTI) +* UCI processing + - ACK/NACK processing + - Triggering periodic SR + - CSI measurement reporting +* DLSCH scheduler + - Configuration of fapi PDU according to DCI + - HARQ procedures +* ULSCH scheduler + - Configuration of fapi PDU according to DCI +* NR-CSIRS scheduler + - Scheduling of NR-CSIRS reception + - Fill UCI for CSI measurement reporting +* Scheduler procedures for SRS transmission + - Periodic SRS transmission +* Bandwidth part (BWP) operation + - Operation in configured dedicated BWP through RRCSetup or RRCReconfiguration + + +## UE RLC + +* Tx/Rx operations according to 38.322 Rel.16 + - Segmentation and reassembly procedures + - RLC Acknowledged mode supporting PDU retransmissions + - RLC Unacknowledged mode + - DRBs and SRBs establishment and handling + - Timers implementation + - Interfaces with PDCP, MAC + +## UE PDCP + +* Tx/Rx operations according to 38.323 Rel.16 + - Integrity protection and ciphering procedures + - Sequence number management, SDU dicard and in-order delivery + - Radio bearer establishment/handling and association with PDCP entities + - Interfaces with RRC, RLC + +## UE SDAP + +* Tx/Rx operations operations according to 37.324 Rel.15 + - Establishment/Handling of SDAP entities. + - Transfer of User Plane Data + - Reflective Mapping + - RRC Signaling Mapping + +## UE RRC + +* Integration of RRC messages and procedures supporting UE 5G SA connection according to 38.331 Rel.16 + - RRCSetupRequest/RRCSetup/RRCSetupComplete + - RRC Uplink/Downlink Information transfer carrying NAS messages transparently + - RRC Reconfiguration/Reconfiguration complete + - Support for master cell group configuration + - Reception of UECapabilityEnquiry, encoding and transmission of UECapability +* Interface with PDCP: configuration, DCCH and CCCH message handling +* Interface with RLC and MAC for configuration + +## UE NAS + +* Transfer of NAS messages between the AMF and the UE supporting the UE registration with the core network and the PDU session establishment according to 24.501 Rel.16 + - Identity Request/Response + - Authentication Request/Response + - Security Mode Command/Complete + - Registration Request/Accept/Complete + - PDU Session Establishment Request/Accept + - NAS configuration and basic interfacing with RRC + + + # OpenAirInterface 4G LTE eNB Feature Set # ## eNB PHY Layer ## @@ -45,15 +390,15 @@ The Physical layer implements **3GPP 36.211**, **36.212**, **36.213** and provid FDD DL: 5 MHz, 25 PRBS/ MCS 28 | 16 - 17 Mbit/s | TM1: 17.0 Mbits/s | COTS-UE Cat 4 (150/50 Mbps) FDD DL: 10 MHz, 50 PRBS/ MCS 28 | 34 - 35 Mbit/s | TM1: 34.0 Mbits/s | COTS-UE Cat 4 (150/50 Mbps) FDD DL: 20 MHz, 100 PRBS/ MCS 28 | 70 Mbit/s | TM1: 69.9 Mbits/s | COTS-UE Cat 4 (150/50 Mbps) - | | | + | | | FDD UL: 5 MHz, 25 PRBS/ MCS 20 | 9 Mbit/s | TM1: 8.28 Mbits/s | COTS-UE Cat 4 (150/50 Mbps) FDD UL: 10 MHz, 50 PRBS/ MCS 20 | 17 Mbit/s | TM1: 18.3 Mbits/s | COTS-UE Cat 4 (150/50 Mbps) FDD UL: 20 MHz, 100 PRBS/ MCS 20 | 35 Mbit/s | TM1: 18.6 Mbits/s | COTS-UE Cat 4 (150/50 Mbps) - | | + | | TDD DL: 5 MHz, 25 PRBS/ MCS **XX** | 6.5 Mbit/s | TM1: 6.71 Mbits/s | COTS-UE Cat 4 (150/50 Mbps) TDD DL: 10 MHz, 50 PRBS/ MCS **XX** | 13.5 Mbit/s | TM1: 13.6 Mbits/s | COTS-UE Cat 4 (150/50 Mbps) TDD DL: 20 MHz, 100 PRBS/ MCS **XX** | 28.0 Mbit/s | TM1: 27.2 Mbits/s | COTS-UE Cat 4 (150/50 Mbps) - | | | + | | | TDD UL: 5 MHz, 25 PRBS/ MCS **XX** | 2.0 Mbit/s | TM1: 3.31 Mbits/s | COTS-UE Cat 4 (150/50 Mbps) TDD UL: 10 MHz, 50 PRBS/ MCS **XX** | 2.0 Mbit/s | TM1: 7.25 Mbits/s | COTS-UE Cat 4 (150/50 Mbps) TDD UL: 20 MHz, 100 PRBS/ MCS **XX** | 3.0 Mbit/s | TM1: 4.21 Mbits/s | COTS-UE Cat 4 (150/50 Mbps) @@ -66,7 +411,7 @@ TDD UL: 20 MHz, 100 PRBS/ MCS **XX** | 3.0 Mbit/s | TM1: 4.21 Mbits/s ## eNB MAC Layer ## -The MAC layer implements a subset of the **3GPP 36.321** release v8.6 in support of BCH, DLSCH, RACH, and ULSCH channels. +The MAC layer implements a subset of the **3GPP 36.321** release v8.6 in support of BCH, DLSCH, RACH, and ULSCH channels. - RRC interface for CCCH, DCCH, and DTCH - Proportional fair scheduler (round robin scheduler soon), with the following improvements: @@ -86,16 +431,16 @@ The MAC layer implements a subset of the **3GPP 36.321** release v8.6 in support The RLC layer implements a full specification of the 3GPP 36.322 release v9.3. -- RLC TM (mainly used for BCCH and CCCH) +- RLC TM (mainly used for BCCH and CCCH) * Neither segment nor concatenate RLC SDUs * Do not include a RLC header in the RLC PDU * Delivery of received RLC PDUs to upper layers -- RLC UM (mainly used for DTCH) +- RLC UM (mainly used for DTCH) * Segment or concatenate RLC SDUs according to the TB size selected by MAC * Include a RLC header in the RLC PDU * Duplication detection * PDU reordering and reassembly -- RLC AM, compatible with 9.3 +- RLC AM, compatible with 9.3 * Segmentation, re-segmentation, concatenation, and reassembly * Padding * Data transfer to the user @@ -133,9 +478,9 @@ The RRC layer is based on **3GPP 36.331** v15.6 and implements the following fun The X2AP layer is based on **3GPP 36.423** v14.6.0 and implements the following functions: - X2 Setup Request - - X2 Setup Response + - X2 Setup Response - X2 Setup Failure - - Handover Request + - Handover Request - Handover Request Acknowledge - UE Context Release - X2 timers (t_reloc_prep, tx2_reloc_overall) @@ -144,16 +489,16 @@ The X2AP layer is based on **3GPP 36.423** v14.6.0 and implements the following - EN-DC is implemented - X2AP : Handling of SgNB Addition Request / Addition Request Acknowledge / Reconfiguration Complete - RRC : Handling of RRC Connection Reconfiguration with 5G cell info, configuration of 5G-NR measurements - - S1AP : Handling of E-RAB Modification Indication / Confirmation + - S1AP : Handling of E-RAB Modification Indication / Confirmation ## eNB/MCE M2AP ## The M2AP layer is based on **3GPP 36.443** v14.0.1: - M2 Setup Request - - M2 Setup Response + - M2 Setup Response - M2 Setup Failure - M2 Scheduling Information - - M2 Scheduling Information Response + - M2 Scheduling Information Response - M2 Session Start Request - M2 Session Start Response @@ -161,7 +506,7 @@ The M2AP layer is based on **3GPP 36.443** v14.0.1: The M3AP layer is based on **3GPP 36.444** v14.0.1: - M3 Setup Request - - M3 Setup Response + - M3 Setup Response - M3 Setup Failure - M3 Session Start Request - M3 Session Start Response @@ -184,11 +529,11 @@ The Physical layer implements **3GPP 36.211**, **36.212**, **36.213** and provid - All uplink (UL) channels are supported: PRACH, PUSCH, PUCCH (format 1/1a/1b), SRS, DRS - LTE MBMS-dedicated cell (feMBMS) procedures subset for LTE release 14 (experimental) - LTE non-MBSFN subframe (feMBMS) Carrier Adquistion Subframe-CAS procedures (PSS/SSS/PBCH/PDSH) (experimental) -- LTE MBSFN MBSFN subframe channel (feMBMS): PMCH (CS@1.25KHz) (channel estimation for 25MHz bandwidth) (experimental) +- LTE MBSFN MBSFN subframe channel (feMBMS): PMCH (CS@1.25KHz) (channel estimation for 25MHz bandwidth) (experimental) ## LTE UE MAC Layer ## -The MAC layer implements a subset of the **3GPP 36.321** release v8.6 in support of BCH, DLSCH, RACH, and ULSCH channels. +The MAC layer implements a subset of the **3GPP 36.321** release v8.6 in support of BCH, DLSCH, RACH, and ULSCH channels. - RRC interface for CCCH, DCCH, and DTCH - HARQ Support @@ -196,7 +541,7 @@ The MAC layer implements a subset of the **3GPP 36.321** release v8.6 in support - RLC interface (AM, UM) - UL power control - Link adaptation -- MBMS-dedicated cell (feMBMS) RRC interface for BCCH +- MBMS-dedicated cell (feMBMS) RRC interface for BCCH - eMBMS and MBMS-dedicated cell (feMBMS) RRC interface for MCCH, MTCH ## LTE UE RLC Layer ## @@ -223,328 +568,6 @@ The NAS layer is based on **3GPP 24.301** and implements the following functions - ESM default/dedicated bearer, PDN connectivity, and more -# OpenAirInterface 5G-NR Feature Set # - -## General Parameters ## - -The following features are valid for the gNB and the 5G-NR UE. - -* Static TDD, -* FDD -* Normal CP -* Subcarrier spacings: 15 and 30kHz (FR1), 120kHz (FR2) -* Bandwidths: 10, 20, 40, 80, 100MHz (273 Physical Resource Blocks) -* Intermediate downlink and uplink frequencies to interface with IF equipment -* Procedures for 2-layer DL MIMO -* Slot format: 14 OFDM symbols in UL or DL -* Highly efficient 3GPP compliant LDPC encoder and decoder (BG1 and BG2 supported) -* Highly efficient 3GPP compliant polar encoder and decoder -* Encoder and decoder for short blocks -* Support for UL transform precoding (SC-FDMA) - - -## gNB PHY Layer ## - -* 15kHz and 30kHz SCS for FR1 and 120kHz SCS for FR2 -* Generation of NR-PSS/NR-SSS -* NR-PBCH supports multiple SSBs and flexible periodicity -* Generation of NR-PDCCH (including generation of DCI, polar encoding, scrambling, modulation, RB mapping, etc) - - common search space - - user-specific search space - - DCI formats: 00, 10, 01 and 11 -* Generation of NR-PDSCH (including Segmentation, LDPC encoding, rate matching, scrambling, modulation, RB mapping, etc). - - PDSCH mapping type A and B - - DMRS configuration type 1 and 2 - - Single and multiple DMRS symbols - - PTRS support - - Support for 1, 2 and 4 TX antennas - - Support for up to 2 layers (currently limited to DMRS configuration type 2) - - Support for 256 QAM -* NR-CSIRS Generation of sequence at PHY -* NR-PUSCH (including Segmentation, LDPC encoding, rate matching, scrambling, modulation, RB mapping, etc). - - PUSCH mapping type A and B - - DMRS configuration type 1 and 2 - - Single and multiple DMRS symbols - - PTRS support - - Support for up to 2 RX antenna - - Support for up to 2 layers - - Support for 256 QAM -* NR-PUCCH - - Format 0 (2 bits, for ACK/NACK and SR) - - Format 2 (mainly for CSI feedback) -* NR-SRS - - SRS signal reception - - Channel estimation (with T tracer real time monitoring) - - Power noise estimation -* NR-PRS - - Rel16 Positioning reference signal(PRS) generation and modulation - - Multiple PRS resources, one per beam is supported in FR2 TDD mode - - FR1 and FR2 support with config file -* NR-PRACH - - Formats 0,1,2,3, A1-A3, B1-B3 -* Highly efficient 3GPP compliant LDPC encoder and decoder (BG1 and BG2 are supported) -* Highly efficient 3GPP compliant polar encoder and decoder -* Encoder and decoder for short block - -## gNB Higher Layers ## - -**gNB MAC** -- MAC -> PHY configuration using NR FAPI P5 interface -- MAC <-> PHY data interface using FAPI P7 interface for BCH PDU, DCI PDU, PDSCH PDU -- Scheduler procedures for SIB1 -- Scheduler procedures for RA - - Contention Free RA procedure - - Contention Based RA procedure - - Msg3 can transfer uplink CCCH, DTCH or DCCH messages - - CBRA can be performed using MAC CE or C-RNTI -- Scheduler procedures for CSI-RS -- MAC downlink scheduler - - phy-test scheduler (fixed allocation and usable also without UE) - - regular scheduler with dynamic allocation - - MCS adaptation from HARQ BLER -- MAC header generation (including timing advance) -- ACK / NACK handling and HARQ procedures for downlink -- MAC uplink scheduler - - phy-test scheduler (fixed allocation) - - regular scheduler with dynamic allocation - - HARQ procedures for uplink -- Scheduler procedures for SRS reception - - Periodic SRS reception - - Channel rank computation up to 2x2 scenario - - TPMI computation based on SRS up 4 antenna ports and 2 layers -- MAC procedures to handle CSI measurement report - - evalution of RSRP report - - evaluation of CQI report -- MAC scheduling of SR reception -- Bandwidth part (BWP) operation - - Handle multiple dedicated BWPs - - BWP switching through RRCReconfiguration method - -**gNB RLC** -- Send/Receive operations according to 38.322 Rel.16 - - Segmentation and reassembly procedures - - RLC Acknowledged mode supporting PDU retransmissions - - RLC Unacknowledged mode - - DRBs and SRBs establishment/handling and association with RLC entities - - Timers implementation - - Interfaces with PDCP, MAC - - Interfaces with gtp-u (data Tx/Rx over F1-U at the DU) - -**gNB PDCP** -- Send/Receive operations according to 38.323 Rel.16 - - Integrity protection and ciphering procedures - - Sequence number management, SDU dicard and in-order delivery - - Radio bearer establishment/handling and association with PDCP entities - - Interfaces with RRC, RLC - - Interfaces with gtp-u (data Tx/Rx over N3 and F1-U interfaces) - -**gNB SDAP** -- Send/Receive operations according to 37.324 Rel.15 - - Establishment/Handling of SDAP entities. - - Transfer of User Plane Data - - Mapping between a QoS flow and a DRB for both DL and UL - - Marking QoS flow ID in both DL and UL packets - - Reflective QoS flow to DRB mapping for UL SDAP data PDUs - -**gNB RRC** -- NR RRC (38.331) Rel 16 messages using new asn1c -- LTE RRC (36.331) also updated to Rel 15 -- Generation of CellGroupConfig (for eNB) and MIB -- Generation of system information block 1 (SIB1) -- Generation of system information block 2 (SIB2) -- Application to read configuration file and program gNB RRC -- RRC can configure PDCP, RLC, MAC -- Interface with gtp-u (tunnel creation/handling for S1-U (NSA), N3 (SA) interfaces) -- Integration of RRC messages and procedures supporting UE 5G SA connection - - RRCSetupRequest/RRCSetup/RRCSetupComplete - - RRC Uplink/Downlink Information transfer carrying NAS messages transparently - - RRC Reconfiguration/Reconfiguration complete - - RRC Reestablishment/Reestablishment complete - - Paging - - Support for master cell group configuration - - Interface with NGAP for the interactions with the AMF - - Interface with F1AP for CU/DU split deployment option - - Periodic RRC measurements of serving cell (no A/B events) - -**gNB X2AP** -- Integration of X2AP messages and procedures for the exchanges with the eNB over X2 interface supporting the NSA setup according to 36.423 Rel. 15 - - X2 setup with eNB - - Handling of SgNB Addition Request / Addition Request Acknowledge / Reconfiguration Complete - -**gNB NGAP** - -- Integration of NGAP messages and procedures for the exchanges with the AMF over N2 interface according to 38.413 Rel. 15 - - NGAP Setup request/response - - NGAP Initial UE message - - NGAP Initial context setup request/response - - NGAP Downlink/Uplink NAS transfer - - NGAP UE context release request/complete - - NGAP UE radio capability info indication - - NGAP PDU session resource setup request/response -- Interface with RRC - -**gNB F1AP** - -- Integration of F1AP messages and procedures for the control plane exchanges between the CU and DU entities according to 38.473 Rel. 16 - - F1 Setup request/response - - F1 DL/UL RRC message transfer - - F1 Initial UL RRC message transfer - - F1 UE Context setup request/response - - F1 gNB CU configuration update -- Interface with RRC -- Interface with gtp-u (tunnel creation/handling for F1-U interface) - -**gNB GTP-U** -- New gtp-u implementation supporting both N3 and F1-U interfaces according to 29.281 Rel.15 - - Interfaces with RRC, F1AP for tunnel creation - - Interfaces with PDCP and RLC for data send/receive at the CU and DU respectively (F1-U interface) - - Interface with SDAP for data send/receive, capture of GTP-U Optional Header, GTP-U Extension Header and PDU Session Container. - -# OpenAirInterface 5G-NR UE Feature Set # - -* Supporting "noS1" mode (DL and UL): - - Creates TUN interface to PDCP to inject and receive user-place traffic - - No connection to the core network -* Supporting Standalone (SA) mode: - - UE can register with the 5G Core Network, establish a PDU Session and exchange user-plane traffic - -## NR UE PHY Layer ## - -* Initial synchronization - - the UE needs to know the position in frequency of the SSBs (via command line parameter in SA) -* Time tracking based on PBCH DMRS -* Frequency offset estimation based on PSS and SSS -* 15kHz and 30kHz SCS for FR1 and 120 kHz SCS for FR2 -* Reception of NR-PSS/NR-SSS -* NR-PBCH supports multiple SSBs and flexible periodicity - - RSRP measurement for the strongest SSB -* Reception of NR-PDCCH (including reception of DCI, polar decoding, de-scrambling, de-modulation, RB de-mapping, etc) - - common search space configured by MIB - - user-specific search space configured by RRC - - DCI formats: 00, 10, 01 and 11 -* Reception of NR-PDSCH (including Segmentation, LDPC decoding, rate de-matching, de-scrambling, de-modulation, RB de-mapping, etc). - - PDSCH mapping type A and B - - DMRS configuration type 1 and 2 - - Single and multiple DMRS symbols - - PTRS support - - Support for 1, 2 and 4 RX antennas - - Support for up to 2 layers (currently limited to DMRS configuration type 2) -* Measurements based on NR-CSIRS - - RSRP measurements - - RI, PMI and CQI computation - - Support for up to 4 RX antennas - - Support for up to 2 layers -* NR-PUSCH (including Segmentation, LDPC encoding, rate matching, scrambling, modulation, RB mapping, etc). - - PUSCH mapping type A and B - - DMRS configuration type 1 and 2 - - Single and multiple DMRS symbols - - PTRS support - - Support for up to 2 TX antenna - - Support for up to 2 layers -* NR-PUCCH - - Format 0 (2 bits for ACK/NACK and SR) - - Format 2 (mainly for CSI feedback) - - Format 1 (limited testing) - - Format 3 and 4 present but old code never tested (need restructuring before verification) -* NR-SRS - - Generation of sequence at PHY - - SRS signal transmission -* NR-PRS - - PRS based Channel estimation with T tracer dumps - - Time of arrival(ToA) estimation based on channel impulse response(CIR) - - Finer ToA estimation by 16x oversampled IDFT for CIR - - Support for multiple gNB reception with gNBs synced via GPSDO -* NR-PRACH - - Formats 0,1,2,3, A1-A3, B1-B3 -* Highly efficient 3GPP compliant LDPC encoder and decoder (BG1 and BG2 are supported) -* Highly efficient 3GPP compliant polar encoder and decoder -* Encoder and decoder for short block - -## NR UE FAPI ## - -* MAC -> PHY configuration via UE FAPI P5 interface -* Basic MAC to control PHY via UE FAPI P7 interface -* PHY -> MAC indication (needs some improvement) - -## NR UE Higher Layers ## - -**UE MAC** -* Minimum system information (MSI) - - MIB processing - - Scheduling of system information block 1 (SIB1) reception -* Random access procedure (needs improvement, there is still not a clear separation between MAC and PHY) - - Mapping SSBs to multiple ROs - - Scheduling of PRACH - - Processing of RAR - - Transmission and re-transmission of Msg3 - - Msg4 and contention resolution -* DCI processing - - format 10 (RA-RNTI, C-RNTI, SI-RNTI, TC-RNTI) - - format 00 (C-RNTI, TC-RNTI) - - format 11 (C-RNTI) - - format 01 (C-RNTI) -* UCI processing - - ACK/NACK processing - - Triggering periodic SR - - CSI measurement reporting -* DLSCH scheduler - - Configuration of fapi PDU according to DCI - - HARQ procedures -* ULSCH scheduler - - Configuration of fapi PDU according to DCI -* NR-CSIRS scheduler - - Scheduling of NR-CSIRS reception - - Fill UCI for CSI measurement reporting -* Scheduler procedures for SRS transmission - - Periodic SRS transmission -* Bandwidth part (BWP) operation - - Operation in configured dedicated BWP through RRCSetup or RRCReconfiguration - - -**UE RLC** -* Tx/Rx operations according to 38.322 Rel.16 - - Segmentation and reassembly procedures - - RLC Acknowledged mode supporting PDU retransmissions - - RLC Unacknowledged mode - - DRBs and SRBs establishment and handling - - Timers implementation - - Interfaces with PDCP, MAC - -**UE PDCP** -* Tx/Rx operations according to 38.323 Rel.16 - - Integrity protection and ciphering procedures - - Sequence number management, SDU dicard and in-order delivery - - Radio bearer establishment/handling and association with PDCP entities - - Interfaces with RRC, RLC - -**UE SDAP** -* Tx/Rx operations operations according to 37.324 Rel.15 - - Establishment/Handling of SDAP entities. - - Transfer of User Plane Data - - Reflective Mapping - - RRC Signaling Mapping - -**UE RRC** -* Integration of RRC messages and procedures supporting UE 5G SA connection according to 38.331 Rel.16 - - RRCSetupRequest/RRCSetup/RRCSetupComplete - - RRC Uplink/Downlink Information transfer carrying NAS messages transparently - - RRC Reconfiguration/Reconfiguration complete - - Support for master cell group configuration - - Reception of UECapabilityEnquiry, encoding and transmission of UECapability -* Interface with PDCP: configuration, DCCH and CCCH message handling -* Interface with RLC and MAC for configuration - -**UE NAS** -* Transfer of NAS messages between the AMF and the UE supporting the UE registration with the core network and the PDU session establishment according to 24.501 Rel.16 - - Identity Request/Response - - Authentication Request/Response - - Security Mode Command/Complete - - Registration Request/Accept/Complete - - PDU Session Establishment Request/Accept - - NAS configuration and basic interfacing with RRC - - - [OAI wiki home](https://gitlab.eurecom.fr/oai/openairinterface5g/wikis/home) [OAI softmodem build procedure](BUILD.md) diff --git a/doc/README.md b/doc/README.md index 776b217248..d42bad0a72 100644 --- a/doc/README.md +++ b/doc/README.md @@ -99,6 +99,7 @@ The other SDRs (AW2S, LimeSDR, ...) have no READMEs. - OAI comes with an integrated [telnet server](../common/utils/telnetsrv/DOC/telnethelp.md) to monitor and control - OAI comes with an integrated [web server](../common/utils/websrv/DOC/websrv.md) -# CI +# Testing +- [UnitTests.md](./UnitTests.md) explains the unit testing setup - [TESTBenches.md](./TESTBenches.md) lists the CI setup and links to pipelines diff --git a/doc/TESTBenches.md b/doc/TESTBenches.md index 35aebfe1aa..555511e153 100644 --- a/doc/TESTBenches.md +++ b/doc/TESTBenches.md @@ -101,10 +101,13 @@ Webhook - L2simulator: skips physical layer and uses proxy between gNB and UE, currently only ping - [RAN-LTE-FDD-LTEBOX-Container](https://jenkins-oai.eurecom.fr/job/RAN-LTE-FDD-LTEBOX-Container/) - hutch + B210, nano w/ ltebox + 2x UE - - tests RRC inactivity timers, different bandwidths + - tests RRC inactivity timers, different bandwidths, IF4p5 fronthaul +- [RAN-LTE-FDD-OAIUE-OAICN4G-Container](https://jenkins-oai.eurecom.fr/job/RAN-LTE-FDD-OAIUE-OAICN4G-Container/) + - hutch + B210 (eNB), carabe + B210 (4G UE), nano w/ OAI 4GC + - tests OAI 4G for 10 MHz/TM1; known to be unstable - [RAN-LTE-TDD-2x2-Container](https://jenkins-oai.eurecom.fr/view/RAN/job/RAN-LTE-TDD-2x2-Container/) - obelix + N310, porcepix, nrmodule2 + Quectel - - TM1 and TM2 test + - TM1 and TM2 test, IF4p5 fronthaul - [RAN-LTE-TDD-LTEBOX-Container](https://jenkins-oai.eurecom.fr/job/RAN-LTE-TDD-LTEBOX-Container/) - starsky + B210, nano w/ ltebox + 2x UE - TM1 over bandwidths 5, 10, 20 MHz in Band 40, default scheduler for 20 MHz @@ -148,23 +151,3 @@ Webhook - [RAN-SA-AmariS-CN5G](https://jenkins-oai.eurecom.fr/view/RAN/job/RAN-SA-AmariS-CN5G/) - asterix + N310, amariue (1x UE), porcepix w/ OAI 5GC - Amarisoft UE simulator: expected to be increased to more UEs - -### RAN-CI-develop - -***DEFUNCT***: automatically triggered tests, mostly 4G, to be phased out and -integrated into RAN-Container-Parent - -The following defunct pipelines remain to be integrated into RAN-Container-Parent: -- eNB-CI-IF4p5-FDD-Band7-B210 - - hutch + B210, nano w/ ltebox + 2x UE - - tests IF4.5 split over bandwidths 5, 10, 20 MHz in Band 7 -- eNB-CI-IF4p5-TDD-Band40-B210 - - starsky + B210, nano w/ ltebox + 2x UE - - tests IF4.5 split over bandwidths 5, 10, 20 MHz in Band 40 -- eNB-UE-CI-MONO-FDD-Band7-B200 - - hutch + B210 (eNB), carabe + B210 (4G UE), nano w/ ltebox - - tests OAI 4G for 5 MHz/TM1 with both CN and in noS1 model, MBMS; known to - be unstable -- UE-CI-FDD-Band20-B200 - - starsky + B210 (sniffer) - - Sniff MIB + SIB1 of Orange, SFR diff --git a/doc/UnitTests.md b/doc/UnitTests.md new file mode 100644 index 0000000000..6ea18e2280 --- /dev/null +++ b/doc/UnitTests.md @@ -0,0 +1,108 @@ +# Unit Testing in OAI + +OpenAirInterface uses +[ctest](https://cmake.org/cmake/help/latest/manual/ctest.1.html) for unit +testing. The cmake documentation has a +[tutorial](https://cmake.org/cmake/help/book/mastering-cmake/chapter/Testing%20With%20CMake%20and%20CTest.html) +explaining how to test with cmake and ctest; it is a suggested read, and the +following just lists the main points of how to compile the tests and how to add +new ones. + +At the time of writing, only the NR RLC tests have been integrated. The author +hopes that more tests follow suit. + +# How to compile tests + +To compile only the tests, a special target `tests` is available. It has to be +enabled with the special cmake variable `ENABLE_TESTS`: + +```bash +cd openairinterface5g +mkdir build && cd build # you can also do that in cmake_targets/ran_build/build +cmake .. -GNinja -DENABLE_TESTS=ON +ninja tests +``` + +Then, you can run `ctest` to run all tests: +``` +$ ctest +Test project /home/richie/w/ctest/build + Start 1: nr_rlc_tests +1/1 Test #1: nr_rlc_tests ..................... Passed 0.06 sec + +100% tests passed, 0 tests failed out of 1 + +Total Test time (real) = 0.06 sec +``` + +A couple of interesting variables are `--verbose`, `--output-on-failure`. + +# How to add a new test + +As of now, there is no dedicated testing directory. Rather, tests are together +with the sources of the corresponding (sub)system. The generic four-step +process is + +1. Guard all the following steps with `if(ENABLE_TESTS)`. In a world where OAI + is tested completely, there would be many executables that would be of + tangential interest to the average user only. A "normal" build without tests + would result in less executables, due to this guard. +2. Add an executable that you want to execute. In a `CMakeLists.txt`, do for + instance `add_executable(my_test mytest.c)` where `mytest.c` contains + `main()`. You can then build this executable with `ninja/make my_test`, + given you ran `cmake -DENABLE_TESTS=ON ...` before. +3. Create a dependency to `tests` so that triggering the `tests` (`ninja/make + tests`) target will build your test: `add_dependencies(tests my_test)`. +4. Use `add_test(NAME my_new_test COMMAND my_test )` to declare a new + test that will be run by `ctest` under name `my_new_test`. + +In the simplest case, in an existing `CMakeLists.txt`, you might add the +following: +``` +if(ENABLE_TESTS) + add_executable(my_test mytest.c) + add_dependencies(tests my_test) + add_test(NAME my_new_test COMMAND my_test) # no options required +endif() +``` + +Note that this might get more complicated, e.g., typically you will have to +link some library into the executable with `target_link_libraries()`, or pass +some option to the test program. + +`ctest` decides if a test passed via the return code of the program. So a test +executable that always passes is `int main() { return 0; }` and one that always +fails `int main() { return 1; }`. It is left as an exercise to the reader to +include these examples into `ctest`. Other programming languages other than C +or shell scripts are possible but discouraged. Obviously, though, a test in +a mainstream non-C programming language/shell script (C++, Rust, Python, Perl) +is preferable over no test. + +Let's look at a more concrete, elaborate example, the NR RLC tests. +They are located in `openair2/LAYER2/nr_rlc/tests/`. Note that due to +historical reasons, a test script `run_tests.sh` allows to run all tests from +that directory directly, which you might also use to compare to the +`cmake`/`ctest` implementation. + +1. Since the tests are in a sub-directory `tests/`, the inclusion of the entire + directory is guarded in `openair2/LAYER2/nr_rlc/CMakeLists.txt` (in fact, it + might in general be a good idea to create a separate sub-directory + `tests/`!). +2. The NR RLC tests in fact consist of one "test driver program" (`test.c`) + which is compiled with different "test stimuli" into the program. In total, + there are 17 stimuli (`test1.h` to `test17.h`) with corresponding known + "good" outputs after running (in `test1.txt.gz` to `test17.txt.gz`). To + implement this, the `tests/CMakeLists.txt` creates multiple executables + `nr_rlc_test_X` via the loop over `TESTNUM`, links necessary libraries into + the test driver and a compile definition for the test stimuli. +3. For each executable, create a dependency to `tests`. +4. Finally, there is a single(!) `ctest` test that runs all the 17 test + executables at once(!). If you look at the shell script + `exec_nr_rlc_test.sh`, you see that it runs the program, filters for `TEST`, + and compares with a predefined output from each test in `testX.txt.gz`, + which is `gunzip`ed on the fly... Anyway, the actual `add_test()` definition + just tells `ctest` to run this script (in the source directory), and passes + an option where to find the executables (in the build directory). This + slight complication is due to using shell scripts. An easier way is to + directly declare the executable in `add_test()`, and `ctest` will locate and + run the executable properly. diff --git a/docker/Dockerfile.lteUE.ubuntu20 b/docker/Dockerfile.lteUE.ubuntu20 index 7b09b45b3e..dc7376e644 100644 --- a/docker/Dockerfile.lteUE.ubuntu20 +++ b/docker/Dockerfile.lteUE.ubuntu20 @@ -51,6 +51,7 @@ RUN apt-get update && \ python3 \ python3-six \ python3-requests \ + libpython3.8 \ libusb-1.0-0 \ iputils-ping \ iproute2 \ diff --git a/executables/nr-ue.c b/executables/nr-ue.c index 40a3d16753..8b1f6b969f 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -306,10 +306,6 @@ static void *NRUE_phy_stub_standalone_pnf_task(void *arg) process_queued_nr_nfapi_msgs(mac, sfn_slot); } - bool only_dl = false; - if (mac->scc == NULL && mac->scc_SIB == NULL) - only_dl = true; - int CC_id = 0; uint8_t gNB_id = 0; nr_uplink_indication_t ul_info; @@ -332,10 +328,7 @@ static void *NRUE_phy_stub_standalone_pnf_task(void *arg) free_and_zero(ch_info); } - if (only_dl || - is_nr_DL_slot(get_softmodem_params()->nsa ? - mac->scc->tdd_UL_DL_ConfigurationCommon : - mac->scc_SIB->tdd_UL_DL_ConfigurationCommon, + if (is_nr_DL_slot(mac->tdd_UL_DL_ConfigurationCommon, ul_info.slot_rx)) { memset(&mac->dl_info, 0, sizeof(mac->dl_info)); mac->dl_info.cc_id = CC_id; @@ -350,10 +343,7 @@ static void *NRUE_phy_stub_standalone_pnf_task(void *arg) if (pthread_mutex_unlock(&mac->mutex_dl_info)) abort(); - if (!only_dl && - is_nr_UL_slot(get_softmodem_params()->nsa ? - mac->scc->tdd_UL_DL_ConfigurationCommon : - mac->scc_SIB->tdd_UL_DL_ConfigurationCommon, + if (is_nr_UL_slot(mac->tdd_UL_DL_ConfigurationCommon, ul_info.slot_tx, mac->frame_type)) { LOG_D(NR_MAC, "Slot %d. calling nr_ue_ul_ind()\n", ul_info.slot_tx); nr_ue_ul_scheduler(&ul_info); @@ -517,16 +507,8 @@ static void RU_write(nr_rxtx_thread_data_t *rxtxD) { !get_softmodem_params()->continuous_tx) { uint8_t tdd_period = mac->phy_config.config_req.tdd_table.tdd_period_in_slots; - int nrofUplinkSlots, nrofUplinkSymbols; - if (mac->scc) { - nrofUplinkSlots = mac->scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots; - nrofUplinkSymbols = mac->scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols; - } - else { - nrofUplinkSlots = mac->scc_SIB->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots; - nrofUplinkSymbols = mac->scc_SIB->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols; - } - + int nrofUplinkSlots = mac->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots; + int nrofUplinkSymbols = mac->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols; int slot_tx_usrp = proc->nr_slot_tx; uint8_t num_UL_slots = nrofUplinkSlots + (nrofUplinkSymbols != 0); uint8_t first_tx_slot = tdd_period - num_UL_slots; @@ -928,7 +910,8 @@ void *UE_thread(void *arg) timing_advance = UE->timing_advance; } - nr_ue_rrc_timer_trigger(UE->Mod_id, curMsg.proc.frame_tx, curMsg.proc.nr_slot_tx, curMsg.proc.gNB_id); + if (curMsg.proc.nr_slot_tx == 0) + nr_ue_rrc_timer_trigger(UE->Mod_id, curMsg.proc.frame_tx, curMsg.proc.gNB_id); // Start TX slot processing here. It runs in parallel with RX slot processing notifiedFIFO_elt_t *newElt = newNotifiedFIFO_elt(sizeof(nr_rxtx_thread_data_t), curMsg.proc.nr_slot_tx, &txFifo, processSlotTX); diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c index 29afb86a6f..1c147047c1 100644 --- a/executables/nr-uesoftmodem.c +++ b/executables/nr-uesoftmodem.c @@ -528,8 +528,7 @@ int main( int argc, char **argv ) { mac->phy_config_request_sent = true; fapi_nr_config_request_t *nrUE_config = &UE[CC_id]->nrUE_config; - nr_init_frame_parms_ue(&UE[CC_id]->frame_parms, nrUE_config, - *mac->scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]); + nr_init_frame_parms_ue(&UE[CC_id]->frame_parms, nrUE_config, mac->nr_band); } init_nr_ue_vars(UE[CC_id], 0, abstraction_flag); diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c index b06b690c0b..bf5b619528 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c @@ -8,6 +8,7 @@ #include "PHY/NR_ESTIMATION/nr_ul_estimation.h" #include "PHY/defs_nr_common.h" #include "common/utils/nr/nr_common.h" +#include //#define DEBUG_CH_COMP //#define DEBUG_RB_EXT @@ -2015,6 +2016,7 @@ void nr_rx_pusch(PHY_VARS_gNB *gNB, ad_shift = -3; // For 2-layers, we are already doing a bit shift in the nr_ulsch_mmse_2layers() function, so we can use more bits } + int num_re_total = 0; for(uint8_t symbol = rel15_ul->start_symbol_index; symbol < (rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols); symbol++) { uint8_t dmrs_symbol_flag = (rel15_ul->ul_dmrs_symb_pos >> symbol) & 0x01; if (dmrs_symbol_flag == 1) { @@ -2037,6 +2039,7 @@ void nr_rx_pusch(PHY_VARS_gNB *gNB, nb_re_pusch = rel15_ul->rb_size * NR_NB_SC_PER_RB; } + num_re_total += nb_re_pusch; pusch_vars->ul_valid_re_per_slot[symbol] = nb_re_pusch; LOG_D(PHY, "symbol %d: nb_re_pusch %d, DMRS symbl used for Chest :%d \n", symbol, nb_re_pusch, pusch_vars->dmrs_symbol); @@ -2214,4 +2217,9 @@ void nr_rx_pusch(PHY_VARS_gNB *gNB, rxdataF_ext_offset += pusch_vars->ul_valid_re_per_slot[symbol]; } } // symbol loop + if (!(frame % 128)) { + int num_llr = num_re_total*rel15_ul->qam_mod_order; + GnbScopeUpdate(gNB, puschLLRe, num_llr); + GnbScopeUpdate(gNB, puschIQe, num_re_total); + } } diff --git a/openair1/PHY/NR_UE_ESTIMATION/filt16a_32.h b/openair1/PHY/NR_UE_ESTIMATION/filt16a_32.h index 2ab6b7e63b..3f0f70526e 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/filt16a_32.h +++ b/openair1/PHY/NR_UE_ESTIMATION/filt16a_32.h @@ -252,12 +252,7 @@ static const short filt8_rep4[8] = {16384, 16384, 16384, 16384, 0, 0, 0, 0}; // DL // DMRS_Type1 -static const short filt16_dl_first[16] = {12228, 12228, 12228, 12228, 8192, 8192, 8192, 8192, 4096, 4096, 4096, 4096, 0, 0, 0, 0}; - -static const short filt16_dl_middle[16] = - {2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048}; - -static const short filt16_dl_last[16] = {4096, 4096, 4096, 4096, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +// using UL filter // DMRS_Type2 static const short filt16_dl_first_type2[16] = {16384, 16384, 16384, 8192, 8192, 8192, 8192, 8192, 8192, 0, 0, 0, 0, 0, 0}; diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c index 1dc97cc674..60d2368a48 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c @@ -1300,13 +1300,15 @@ void NFAPI_NR_DMRS_TYPE1_linear_interp(NR_DL_FRAME_PARMS *frame_parms, #endif if (pilot_cnt == 0) { // Treat first pilot - c16multaddVectRealComplex(filt16_dl_first, &ch, dl_ch, 16); + c16multaddVectRealComplex(filt16_ul_p0, &ch, dl_ch, 16); + } else if (pilot_cnt == 1 || pilot_cnt == 2) { + c16multaddVectRealComplex(filt16_ul_p1p2, &ch, dl_ch, 16); } else if (pilot_cnt == 6 * nb_rb_pdsch - 1) { // Treat last pilot - c16multaddVectRealComplex(filt16_dl_last, &ch, dl_ch, 16); + c16multaddVectRealComplex(filt16_ul_last, &ch, dl_ch, 16); } else { // Treat middle pilots - c16multaddVectRealComplex(filt16_dl_middle, &ch, dl_ch, 16); + c16multaddVectRealComplex(filt16_ul_middle, &ch, dl_ch, 16); if (pilot_cnt % 2 == 0) { - dl_ch += 4; + dl_ch += 4; } } } diff --git a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c index de672b8cc5..00762afc34 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c @@ -800,7 +800,8 @@ void nr_pdcch_unscrambling(int16_t *e_rx, uint16_t scrambling_RNTI, uint32_t length, uint16_t pdcch_DMRS_scrambling_id, - int16_t *z2) { + int16_t *z2) +{ int i; uint8_t reset; uint32_t x1 = 0, x2 = 0, s = 0; @@ -809,7 +810,7 @@ void nr_pdcch_unscrambling(int16_t *e_rx, reset = 1; // x1 is set in first call to lte_gold_generic n_id = pdcch_DMRS_scrambling_id; - x2 = ((rnti<<16) + n_id); //mod 2^31 is implicit //this is c_init in 38.211 v15.1.0 Section 7.3.2.3 + x2 = ((rnti << 16) + n_id) % (1U << 31); // this is c_init in 38.211 v15.1.0 Section 7.3.2.3 LOG_D(PHY,"PDCCH Unscrambling x2 %x : scrambling_RNTI %x\n", x2, rnti); diff --git a/openair1/PHY/TOOLS/nr_phy_qt_scope.cpp b/openair1/PHY/TOOLS/nr_phy_qt_scope.cpp index 4f73978448..4151a7e4cd 100644 --- a/openair1/PHY/TOOLS/nr_phy_qt_scope.cpp +++ b/openair1/PHY/TOOLS/nr_phy_qt_scope.cpp @@ -70,6 +70,22 @@ float Limits_KPI_ue[2][2] = { {0.2, 10} // Throughput in Mbs }; +// Plot updater +PlotUpdater puschLlrUpdater; +PlotUpdater puschIqUpdater; + +void scopeUpdaterGnb(enum PlotTypeGnbIf plotType, int numElt) +{ + switch (plotType) { + case puschLLRe: + puschLlrUpdater.updatePlot(numElt); + break; + case puschIQe: + puschIqUpdater.updatePlot(numElt); + break; + } +} + /* This class creates the window when choosing the option 'Configs' to configure the threshold values. */ ConfigBoxFloat::ConfigBoxFloat(float *valuePtr, QWidget *parent) : QLineEdit(parent), valuePtr(valuePtr) { @@ -178,7 +194,8 @@ KPIListSelectUE::KPIListSelectUE(QWidget *parent) : QComboBox(parent) this->addItem("Configs", static_cast(PlotTypeUE::config)); } -WaterFall::WaterFall(complex16 *values, NR_DL_FRAME_PARMS *frame_parms, QWidget *parent) : QWidget(parent), values(values), frame_parms(frame_parms) +WaterFall::WaterFall(complex16 *values, NR_DL_FRAME_PARMS *frame_parms, QWidget *parent) + : QWidget(parent), values(values), frame_parms(frame_parms) { this->iteration = 0; this->image = nullptr; @@ -187,8 +204,8 @@ WaterFall::WaterFall(complex16 *values, NR_DL_FRAME_PARMS *frame_parms, QWidget startTimer(100); } -/* this function to plot the waterfall graph for the RX signal in time domain for one frame. x-axis shows the frame divided into slots - and the y-axis is a color map depending on the SquaredNorm of the received signal at the correspoinding slot. */ +/* this function to plot the waterfall graph for the RX signal in time domain for one frame. x-axis shows the frame divided into + slots and the y-axis is a color map depending on the SquaredNorm of the received signal at the correspoinding slot. */ void WaterFall::timerEvent(QTimerEvent *event) { if (!this->isVisible()) @@ -340,17 +357,19 @@ void CIRPlotUE::timerEvent(QTimerEvent *event) maxY = std::max(maxY, value); } + this->axisX->setRange(-this->len / 2, this->len / 2); this->axisY->setMax(maxY); this->series->replace(points); } } -LLRPlot::LLRPlot(int16_t *data, int len) : data(data), len(len) +LLRPlot::LLRPlot(int16_t *data, int len, int interval, PlotUpdater *plotUpdater) : data(data), len(len), plotUpdater(plotUpdater) { this->legend()->hide(); // add new series to the chart this->series = new QScatterSeries(); + this->series->setUseOpenGL(); this->series->setMarkerSize(3); this->series->setMarkerShape(QScatterSeries::MarkerShapeRectangle); this->series->setColor(Qt::blue); @@ -360,7 +379,6 @@ LLRPlot::LLRPlot(int16_t *data, int len) : data(data), len(len) // add new X axis this->axisX = new QValueAxis(); this->axisX->setLabelFormat("%d"); - this->axisX->setRange(0, len); this->addAxis(this->axisX, Qt::AlignBottom); this->series->attachAxis(this->axisX); @@ -369,26 +387,44 @@ LLRPlot::LLRPlot(int16_t *data, int len) : data(data), len(len) this->addAxis(this->axisY, Qt::AlignLeft); this->series->attachAxis(this->axisY); - startTimer(1000); + if (interval) + startTimer(interval); + + if (plotUpdater) + connect(plotUpdater, &PlotUpdater::updatePlot, this, &LLRPlot::updatePlot, Qt::QueuedConnection); } -void LLRPlot::timerEvent(QTimerEvent *event) +LLRPlot::~LLRPlot() { + if (this->plotUpdater) + disconnect(this->plotUpdater, &PlotUpdater::updatePlot, this, &LLRPlot::updatePlot); +} + +void LLRPlot::updatePlot(int len) +{ + this->len = len; + if (!this->isVisible()) return; - QVector points(this->len); + QVector points(len); int maxY = this->axisY->max(); - for (int i = 0; i < this->len; i++) { + for (int i = 0; i < len; i++) { points[i] = QPointF(i, this->data[i]); maxY = std::max(maxY, abs(this->data[i])); } + this->axisX->setRange(0, len); this->axisY->setRange(-maxY, maxY); this->series->replace(points); } +void LLRPlot::timerEvent(QTimerEvent *event) +{ + this->updatePlot(this->len); +} + void LLRPlotUE::timerEvent(QTimerEvent *event) { if (!this->isVisible()) @@ -406,17 +442,19 @@ void LLRPlotUE::timerEvent(QTimerEvent *event) maxY = std::max(maxY, abs(this->data[i])); } + this->axisX->setRange(0, this->len); this->axisY->setRange(-maxY, maxY); this->series->replace(points); } } -IQPlot::IQPlot(complex16 *data, int len) : data(data), len(len) +IQPlot::IQPlot(complex16 *data, int len, int interval, PlotUpdater *plotUpdater) : data(data), len(len), plotUpdater(plotUpdater) { this->legend()->hide(); // add new series to the chart this->series = new QScatterSeries(); + this->series->setUseOpenGL(); this->series->setMarkerSize(3); this->series->setMarkerShape(QScatterSeries::MarkerShapeRectangle); this->series->setColor(Qt::blue); @@ -433,19 +471,31 @@ IQPlot::IQPlot(complex16 *data, int len) : data(data), len(len) this->addAxis(this->axisY, Qt::AlignLeft); this->series->attachAxis(this->axisY); - startTimer(1000); + if (interval) + startTimer(interval); + + if (plotUpdater) + connect(plotUpdater, &PlotUpdater::updatePlot, this, &IQPlot::updatePlot, Qt::QueuedConnection); } -void IQPlot::timerEvent(QTimerEvent *event) +IQPlot::~IQPlot() { + if (this->plotUpdater) + disconnect(this->plotUpdater, &PlotUpdater::updatePlot, this, &IQPlot::updatePlot); +} + +void IQPlot::updatePlot(int len) +{ + this->len = len; + if (!this->isVisible()) return; - QVector points(this->len); + QVector points(len); int maxX = this->axisX->max(); int maxY = this->axisY->max(); - for (int i = 0; i < this->len; i++) { + for (int i = 0; i < len; i++) { points[i] = QPointF(this->data[i].r, this->data[i].i); maxX = std::max(maxX, abs(this->data[i].r)); @@ -457,6 +507,11 @@ void IQPlot::timerEvent(QTimerEvent *event) this->series->replace(points); } +void IQPlot::timerEvent(QTimerEvent *event) +{ + this->updatePlot(this->len); +} + void IQPlotUE::timerEvent(QTimerEvent *event) { if (!this->isVisible()) @@ -667,7 +722,10 @@ PainterWidgetGnb::PainterWidgetGnb(QWidget *config, QComboBox *comboBox, scopeDa this->plotType = PlotTypeGnb::empty; makeConnections(this->comboBox->currentIndex()); - connect(this->comboBox, static_cast(&QComboBox::currentIndexChanged), this, &PainterWidgetGnb::makeConnections); + connect(this->comboBox, + static_cast(&QComboBox::currentIndexChanged), + this, + &PainterWidgetGnb::makeConnections); } float PainterWidgetGnb::getValue() @@ -778,15 +836,13 @@ void PainterWidgetGnb::makeConnections(int type) } case PlotTypeGnb::puschLLR: { - int num_re = frame_parms->N_RB_UL * 12 * frame_parms->symbols_per_slot; - int Qm = 2; - int coded_bits_per_codeword = num_re * Qm; - newChart = new LLRPlot((int16_t *)p->gNB->pusch_vars[0].llr, coded_bits_per_codeword); + int init_coded_bits_per_codeword = 100; + newChart = new LLRPlot((int16_t *)p->gNB->pusch_vars[0].llr, init_coded_bits_per_codeword, 0, &puschLlrUpdater); break; } case PlotTypeGnb::puschIQ: { - int num_re = frame_parms->N_RB_UL * 12 * frame_parms->symbols_per_slot; - newChart = new IQPlot((complex16 *)p->gNB->pusch_vars[0].rxdataF_comp[0], num_re); + int init_num_re = 100; + newChart = new IQPlot((complex16 *)p->gNB->pusch_vars[0].rxdataF_comp[0], init_num_re, 0, &puschIqUpdater); break; } case PlotTypeGnb::puschSNR: { @@ -846,7 +902,8 @@ void PainterWidgetGnb::makeConnections(int type) /* @UE: This is the main function of the UE sub-widgets, i.e., for each KPI. This function will be called only once when the the sub-widget is created, and it mainly initializes the widget variables and structures. */ -PainterWidgetUE::PainterWidgetUE(QWidget *config, QComboBox *comboBox, PHY_VARS_NR_UE *ue) : config(config), comboBox(comboBox), ue(ue) +PainterWidgetUE::PainterWidgetUE(QWidget *config, QComboBox *comboBox, PHY_VARS_NR_UE *ue) + : config(config), comboBox(comboBox), ue(ue) { this->chartView = new QChartView(this); this->chartView->hide(); @@ -854,7 +911,10 @@ PainterWidgetUE::PainterWidgetUE(QWidget *config, QComboBox *comboBox, PHY_VARS_ this->plotType = PlotTypeUE::empty; makeConnections(this->comboBox->currentIndex()); - connect(this->comboBox, static_cast(&QComboBox::currentIndexChanged), this, &PainterWidgetUE::makeConnections); + connect(this->comboBox, + static_cast(&QComboBox::currentIndexChanged), + this, + &PainterWidgetUE::makeConnections); } float PainterWidgetUE::getValue() @@ -891,7 +951,6 @@ float PainterWidgetUE::getValue() case PlotTypeUE::timingAdvance: return (float)this->ue->timing_advance; - default: return 0; } @@ -1240,6 +1299,7 @@ void nrgNBinitQtScope(scopeParms_t *p) scope->argc = p->argc; scope->argv = p->argv; scope->ru = p->ru; + scope->scopeUpdater = scopeUpdaterGnb; scope->copyData = copyData; copyDataMutexInit(scope); diff --git a/openair1/PHY/TOOLS/nr_phy_qt_scope.h b/openair1/PHY/TOOLS/nr_phy_qt_scope.h index 8a00d5fa96..08296e03d7 100644 --- a/openair1/PHY/TOOLS/nr_phy_qt_scope.h +++ b/openair1/PHY/TOOLS/nr_phy_qt_scope.h @@ -94,11 +94,20 @@ class ValueProvider { class ValueProviderUE : public ValueProvider { public: /// This pure virtual function is meant to provide the graph values to be plotted - virtual scopeGraphData_t *getPlotValue() { + virtual scopeGraphData_t *getPlotValue() + { return nullptr; } }; +/// Class for emitting a queued signal to update plots +class PlotUpdater : public QObject { + Q_OBJECT + + signals: + void updatePlot(int numElt); +}; + /// An editable GUI field for a dialog box to set certain KPI configurations class ConfigBoxFloat : public QLineEdit { Q_OBJECT @@ -234,7 +243,9 @@ class CIRPlotUE : public CIRPlot { Q_OBJECT public: - CIRPlotUE(complex16 *data, int len, ValueProviderUE *valueProvider) : CIRPlot(data, len), valueProvider(valueProvider) {} + CIRPlotUE(complex16 *data, int len, ValueProviderUE *valueProvider) : CIRPlot(data, len), valueProvider(valueProvider) + { + } protected: /// This function is triggered when the own timer expires. It updates the plotted CIR @@ -253,10 +264,19 @@ class LLRPlot : public QChart { /// Constructor /// \param data Pointer to the LLR data /// \param len Length of the LLR data - LLRPlot(int16_t *data, int len); + /// \param interval update interval in ms (0 means no timer-triggered updates) + /// \param plotUpdater pointer to a PlotUpdater for update notifications + LLRPlot(int16_t *data, int len, int interval = 1000, PlotUpdater *plotUpdater = nullptr); + + /// Destructor + ~LLRPlot(); + + public slots: + /// This function updates the plotted LLR + void updatePlot(int len); protected: - /// This function is triggered when the own timer expires. It updates the plotted LLR + /// This function is triggered when the own timer expires. It calls updatePlot() to update the plotted LLR /// \param event Pointer to the timer event virtual void timerEvent(QTimerEvent *event) override; @@ -266,6 +286,9 @@ class LLRPlot : public QChart { /// Length of the LLR data int len; + /// Pointer to a PlotUpdater for update notifications + PlotUpdater *plotUpdater; + /// Scatter series used to plot the LLR in the chart QScatterSeries *series; @@ -280,7 +303,9 @@ class LLRPlotUE : public LLRPlot { Q_OBJECT public: - LLRPlotUE(int16_t *data, int len, ValueProviderUE *valueProvider) : LLRPlot(data, len), valueProvider(valueProvider) {} + LLRPlotUE(int16_t *data, int len, ValueProviderUE *valueProvider) : LLRPlot(data, len), valueProvider(valueProvider) + { + } protected: /// This function is triggered when the own timer expires. It updates the plotted I/Q constellation diagram @@ -299,10 +324,19 @@ class IQPlot : public QChart { /// Constructor /// \param data Pointer to the complex I/Q data /// \param len Length of the I/Q data - IQPlot(complex16 *data, int len); + /// \param interval update interval in ms (0 means no timer-triggered updates) + /// \param plotUpdater pointer to a PlotUpdater for update notifications + IQPlot(complex16 *data, int len, int interval = 1000, PlotUpdater *plotUpdater = nullptr); + + /// Destructor + ~IQPlot(); + + public slots: + /// This function updates the plotted I/Q constellation diagram + void updatePlot(int len); protected: - /// This function is triggered when the own timer expires. It updates the plotted I/Q constellation diagram + /// This function is triggered when the own timer expires. It calls updatePlot() to update the plotted I/Q constellation diagram /// \param event Pointer to the timer event virtual void timerEvent(QTimerEvent *event) override; @@ -312,6 +346,9 @@ class IQPlot : public QChart { /// Length of the I/Q data int len; + /// Pointer to a PlotUpdater for update notifications + PlotUpdater *plotUpdater; + /// Scatter series used to plot the I/Q constellation diagram QScatterSeries *series; @@ -326,7 +363,9 @@ class IQPlotUE : public IQPlot { Q_OBJECT public: - IQPlotUE(complex16 *data, int len, ValueProviderUE *valueProvider) : IQPlot(data, len), valueProvider(valueProvider) {} + IQPlotUE(complex16 *data, int len, ValueProviderUE *valueProvider) : IQPlot(data, len), valueProvider(valueProvider) + { + } protected: /// This function is triggered when the own timer expires. It updates the plotted I/Q constellation diagram diff --git a/openair1/PHY/TOOLS/nr_phy_scope.c b/openair1/PHY/TOOLS/nr_phy_scope.c index 9b0d152c6d..d07bf07076 100644 --- a/openair1/PHY/TOOLS/nr_phy_scope.c +++ b/openair1/PHY/TOOLS/nr_phy_scope.c @@ -738,6 +738,18 @@ static void *scope_thread_gNB(void *arg) { } #endif +static void scopeUpdaterGnb(enum PlotTypeGnbIf plotType, int numElt) +{ + switch (plotType) { + case puschLLRe: + /* update PUSCH LLR plot */ + break; + case puschIQe: + /* update PUSCH IQ plot */ + break; + } +} + STATICFORXSCOPE void gNBinitScope(scopeParms_t *p) { AssertFatal(p->gNB->scopeData = calloc(sizeof(scopeData_t), 1), ""); @@ -746,6 +758,7 @@ STATICFORXSCOPE void gNBinitScope(scopeParms_t *p) scope->argv=p->argv; scope->ru=p->ru; scope->gNB=p->gNB; + scope->scopeUpdater = scopeUpdaterGnb; scope->copyData = copyData; #ifndef WEBSRVSCOPE pthread_t forms_thread; diff --git a/openair1/PHY/TOOLS/phy_scope_interface.h b/openair1/PHY/TOOLS/phy_scope_interface.h index 3c520513cf..ca0f14e019 100644 --- a/openair1/PHY/TOOLS/phy_scope_interface.h +++ b/openair1/PHY/TOOLS/phy_scope_interface.h @@ -70,6 +70,11 @@ enum scopeDataType { MAX_SCOPE_TYPES }; +enum PlotTypeGnbIf { + puschLLRe, + puschIQe, +}; + #define COPIES_MEM 4 typedef struct { @@ -89,6 +94,7 @@ typedef struct scopeData_s { pthread_mutex_t copyDataMutex; scopeGraphData_t *copyDataBufs[MAX_SCOPE_TYPES][COPIES_MEM]; int copyDataBufsIdx[MAX_SCOPE_TYPES]; + void (*scopeUpdater)(enum PlotTypeGnbIf plotType, int numElements); } scopeData_t; int load_softscope(char *exectype, void *initarg); @@ -102,6 +108,9 @@ void copyData(void *, enum scopeDataType type, void *dataIn, int elementSz, int #define gNBscopeCopy(gnb, type, ...) \ if (gnb->scopeData) \ ((scopeData_t *)gnb->scopeData)->copyData((scopeData_t *)gNB->scopeData, type, ##__VA_ARGS__); +#define GnbScopeUpdate(gnb, type, numElt) \ + if (gnb->scopeData) \ + ((scopeData_t *)gnb->scopeData)->scopeUpdater(type, numElt); extended_kpi_ue* getKPIUE(); diff --git a/openair2/CMakeLists.txt b/openair2/CMakeLists.txt index c6e28a6b36..762d3670fb 100644 --- a/openair2/CMakeLists.txt +++ b/openair2/CMakeLists.txt @@ -3,6 +3,7 @@ if(E2_AGENT) add_subdirectory(E2AP) endif() add_subdirectory(F1AP) +add_subdirectory(LAYER2) add_subdirectory(M2AP) add_subdirectory(X2AP) add_subdirectory(RRC) diff --git a/openair2/COMMON/rrc_messages_def.h b/openair2/COMMON/rrc_messages_def.h index 12e6269da0..19a339db7c 100644 --- a/openair2/COMMON/rrc_messages_def.h +++ b/openair2/COMMON/rrc_messages_def.h @@ -79,7 +79,7 @@ MESSAGE_DEF(NAS_DOWNLINK_DATA_IND, MESSAGE_PRIORITY_MED, NasDlDataInd // eNB: realtime -> RRC messages MESSAGE_DEF(RRC_SUBFRAME_PROCESS, MESSAGE_PRIORITY_MED, RrcSubframeProcess, rrc_subframe_process) -MESSAGE_DEF(NRRRC_SLOT_PROCESS, MESSAGE_PRIORITY_MED, NRRrcSlotProcess, nr_rrc_slot_process) +MESSAGE_DEF(NRRRC_FRAME_PROCESS, MESSAGE_PRIORITY_MED, NRRrcFrameProcess, nr_rrc_frame_process) // eNB: RLC -> RRC messages MESSAGE_DEF(RLC_SDU_INDICATION, MESSAGE_PRIORITY_MED, RlcSduIndication, rlc_sdu_indication) diff --git a/openair2/COMMON/rrc_messages_types.h b/openair2/COMMON/rrc_messages_types.h index 4914dd9068..6a29ee1ae7 100644 --- a/openair2/COMMON/rrc_messages_types.h +++ b/openair2/COMMON/rrc_messages_types.h @@ -88,7 +88,7 @@ #define NAS_DOWNLINK_DATA_IND(mSGpTR) (mSGpTR)->ittiMsg.nas_dl_data_ind #define RRC_SUBFRAME_PROCESS(mSGpTR) (mSGpTR)->ittiMsg.rrc_subframe_process -#define NRRRC_SLOT_PROCESS(mSGpTR) (mSGpTR)->ittiMsg.nr_rrc_slot_process +#define NRRRC_FRAME_PROCESS(mSGpTR) (mSGpTR)->ittiMsg.nr_rrc_frame_process #define RLC_SDU_INDICATION(mSGpTR) (mSGpTR)->ittiMsg.rlc_sdu_indication #define NRDuDlReq(mSGpTR) (mSGpTR)->ittiMsg.nr_du_dl_req @@ -464,11 +464,10 @@ typedef struct rrc_subframe_process_s { int CC_id; } RrcSubframeProcess; -typedef struct nrrrc_slot_process_s { +typedef struct nrrrc_frame_process_s { int frame; - int slot; int gnb_id; -} NRRrcSlotProcess; +} NRRrcFrameProcess; // eNB: RLC -> RRC messages typedef struct rlc_sdu_indication_s { diff --git a/openair2/LAYER2/CMakeLists.txt b/openair2/LAYER2/CMakeLists.txt new file mode 100644 index 0000000000..b8bc21e78c --- /dev/null +++ b/openair2/LAYER2/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(nr_rlc) diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index 8ed2b0d0ba..e7b6259284 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -3635,12 +3635,12 @@ int ul_ant_bits(NR_DMRS_UplinkConfig_t *NR_DMRS_UplinkConfig, long transformPrec int tdd_period_to_num[8] = {500,625,1000,1250,2000,2500,5000,10000}; -int is_nr_DL_slot(NR_TDD_UL_DL_ConfigCommon_t *tdd_UL_DL_ConfigurationCommon,slot_t slot) { - - int period,period1,period2=0; - - if (tdd_UL_DL_ConfigurationCommon==NULL) return(1); +bool is_nr_DL_slot(NR_TDD_UL_DL_ConfigCommon_t *tdd_UL_DL_ConfigurationCommon,slot_t slot) +{ + if (tdd_UL_DL_ConfigurationCommon == NULL) + return true; + int period1, period2 = 0; if (tdd_UL_DL_ConfigurationCommon->pattern1.ext1 && tdd_UL_DL_ConfigurationCommon->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530) period1 = 3000+*tdd_UL_DL_ConfigurationCommon->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530; @@ -3650,49 +3650,54 @@ int is_nr_DL_slot(NR_TDD_UL_DL_ConfigCommon_t *tdd_UL_DL_ConfigurationCommon,slo if (tdd_UL_DL_ConfigurationCommon->pattern2) { if (tdd_UL_DL_ConfigurationCommon->pattern2->ext1 && tdd_UL_DL_ConfigurationCommon->pattern2->ext1->dl_UL_TransmissionPeriodicity_v1530) - period2 = 3000+*tdd_UL_DL_ConfigurationCommon->pattern2->ext1->dl_UL_TransmissionPeriodicity_v1530; + period2 = 3000 + *tdd_UL_DL_ConfigurationCommon->pattern2->ext1->dl_UL_TransmissionPeriodicity_v1530; else period2 = tdd_period_to_num[tdd_UL_DL_ConfigurationCommon->pattern2->dl_UL_TransmissionPeriodicity]; } - period = period1+period2; - int scs=tdd_UL_DL_ConfigurationCommon->referenceSubcarrierSpacing; - int slots=period*(1<referenceSubcarrierSpacing; + int slots = period * (1 << scs) / 1000; + int slots1 = period1 * (1 << scs) / 1000; int slot_in_period = slot % slots; - if (slot_in_period < slots1) return(slot_in_period <= tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSlots ? 1 : 0); - else return(slot_in_period <= slots1+tdd_UL_DL_ConfigurationCommon->pattern2->nrofDownlinkSlots ? 1 : 0); + if (slot_in_period < slots1) + return slot_in_period <= tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSlots; + else + return slot_in_period <= slots1 + tdd_UL_DL_ConfigurationCommon->pattern2->nrofDownlinkSlots; } -int is_nr_UL_slot(NR_TDD_UL_DL_ConfigCommon_t *tdd_UL_DL_ConfigurationCommon, slot_t slot, frame_type_t frame_type) { - - int period,period1,period2=0; - +bool is_nr_UL_slot(NR_TDD_UL_DL_ConfigCommon_t *tdd_UL_DL_ConfigurationCommon, slot_t slot, frame_type_t frame_type) +{ // Note: condition on frame_type // goal: the UL scheduler assumes mode is TDD therefore this hack is needed to make FDD work - if (tdd_UL_DL_ConfigurationCommon == NULL || frame_type == FDD) { - return(1); - } + if (frame_type == FDD) + return true; + if (tdd_UL_DL_ConfigurationCommon == NULL) + // before receiving TDD information all slots should be considered to be DL + return false; + int period1, period2 = 0; if (tdd_UL_DL_ConfigurationCommon->pattern1.ext1 && tdd_UL_DL_ConfigurationCommon->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530) - period1 = 3000+*tdd_UL_DL_ConfigurationCommon->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530; + period1 = 3000 + *tdd_UL_DL_ConfigurationCommon->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530; else period1 = tdd_period_to_num[tdd_UL_DL_ConfigurationCommon->pattern1.dl_UL_TransmissionPeriodicity]; if (tdd_UL_DL_ConfigurationCommon->pattern2) { if (tdd_UL_DL_ConfigurationCommon->pattern2->ext1 && tdd_UL_DL_ConfigurationCommon->pattern2->ext1->dl_UL_TransmissionPeriodicity_v1530) - period2 = 3000+*tdd_UL_DL_ConfigurationCommon->pattern2->ext1->dl_UL_TransmissionPeriodicity_v1530; + period2 = 3000 + *tdd_UL_DL_ConfigurationCommon->pattern2->ext1->dl_UL_TransmissionPeriodicity_v1530; else period2 = tdd_period_to_num[tdd_UL_DL_ConfigurationCommon->pattern2->dl_UL_TransmissionPeriodicity]; } - period = period1+period2; - int scs=tdd_UL_DL_ConfigurationCommon->referenceSubcarrierSpacing; - int slots=period*(1<referenceSubcarrierSpacing; + int slots = period * (1 << scs) / 1000; + int slots1 = period1 * (1 << scs) / 1000; int slot_in_period = slot % slots; - if (slot_in_period < slots1) return(slot_in_period >= tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSlots ? 1 : 0); - else return(slot_in_period >= slots1+tdd_UL_DL_ConfigurationCommon->pattern2->nrofDownlinkSlots ? 1 : 0); + if (slot_in_period < slots1) + return slot_in_period >= tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSlots; + else + return slot_in_period >= slots1+tdd_UL_DL_ConfigurationCommon->pattern2->nrofDownlinkSlots; } int16_t fill_dmrs_mask(const NR_PDSCH_Config_t *pdsch_Config, diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h index e2e97e0964..07daa61725 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h @@ -67,9 +67,9 @@ int16_t fill_dmrs_mask(const NR_PDSCH_Config_t *pdsch_Config, mappingType_t mappingtype, int length); -int is_nr_DL_slot(NR_TDD_UL_DL_ConfigCommon_t *tdd_UL_DL_ConfigurationCommon,slot_t slotP); +bool is_nr_DL_slot(NR_TDD_UL_DL_ConfigCommon_t *tdd_UL_DL_ConfigurationCommon, slot_t slotP); -int is_nr_UL_slot(NR_TDD_UL_DL_ConfigCommon_t *tdd_UL_DL_ConfigurationCommon, slot_t slotP, frame_type_t frame_type); +bool is_nr_UL_slot(NR_TDD_UL_DL_ConfigCommon_t *tdd_UL_DL_ConfigurationCommon, slot_t slotP, frame_type_t frame_type); uint8_t compute_srs_resource_indicator(NR_PUSCH_ServingCellConfig_t *pusch_servingcellconfig, NR_PUSCH_Config_t *pusch_Config, diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index a04606b7e2..8798213b4c 100644 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -118,12 +118,11 @@ void set_tdd_config_nr_ue(fapi_nr_config_request_t *cfg, } void config_common_ue_sa(NR_UE_MAC_INST_t *mac, + NR_ServingCellConfigCommonSIB_t *scc, module_id_t module_id, - int cc_idP) { - + int cc_idP) +{ fapi_nr_config_request_t *cfg = &mac->phy_config.config_req; - NR_ServingCellConfigCommonSIB_t *scc = mac->scc_SIB; - mac->phy_config.Mod_id = module_id; mac->phy_config.CC_id = cc_idP; @@ -140,7 +139,7 @@ void config_common_ue_sa(NR_UE_MAC_INST_t *mac, (15 << frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing); cfg->carrier_config.dl_frequency = (downlink_frequency[cc_idP][0]/1000) - (dl_bw_khz>>1); - for (int i=0; i<5; i++) { + for (int i = 0; i < 5; i++) { if (i == frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing) { cfg->carrier_config.dl_grid_size[i] = frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth; cfg->carrier_config.dl_k0[i] = frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->offsetToCarrier; @@ -207,7 +206,7 @@ void config_common_ue_sa(NR_UE_MAC_INST_t *mac, if (cfg->cell_config.frame_duplex_type == TDD){ set_tdd_config_nr_ue(cfg, frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing, - scc->tdd_UL_DL_ConfigurationCommon); + mac->tdd_UL_DL_ConfigurationCommon); } // PRACH configuration @@ -264,11 +263,11 @@ void config_common_ue_sa(NR_UE_MAC_INST_t *mac, } void config_common_ue(NR_UE_MAC_INST_t *mac, + NR_ServingCellConfigCommon_t *scc, module_id_t module_id, int cc_idP) { - fapi_nr_config_request_t *cfg = &mac->phy_config.config_req; - NR_ServingCellConfigCommon_t *scc = mac->scc; + fapi_nr_config_request_t *cfg = &mac->phy_config.config_req; mac->phy_config.Mod_id = module_id; mac->phy_config.CC_id = cc_idP; @@ -378,7 +377,7 @@ void config_common_ue(NR_UE_MAC_INST_t *mac, if (cfg->cell_config.frame_duplex_type == TDD){ set_tdd_config_nr_ue(cfg, frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing, - scc->tdd_UL_DL_ConfigurationCommon); + mac->tdd_UL_DL_ConfigurationCommon); } // PRACH configuration @@ -537,35 +536,33 @@ void configure_current_BWP(NR_UE_MAC_INST_t *mac, NR_UE_UL_BWP_t *UL_BWP = &mac->current_UL_BWP; NR_BWP_t dl_genericParameters = {0}; NR_BWP_t ul_genericParameters = {0}; - NR_BWP_DownlinkCommon_t *bwp_dlcommon = NULL; - NR_BWP_UplinkCommon_t *bwp_ulcommon = NULL; DL_BWP->n_dl_bwp = 0; UL_BWP->n_ul_bwp = 0; if(scc) { DL_BWP->bwp_id = 0; UL_BWP->bwp_id = 0; - bwp_dlcommon = &scc->downlinkConfigCommon.initialDownlinkBWP; - bwp_ulcommon = &scc->uplinkConfigCommon->initialUplinkBWP; - dl_genericParameters = bwp_dlcommon->genericParameters; + mac->bwp_dlcommon = &scc->downlinkConfigCommon.initialDownlinkBWP; + mac->bwp_ulcommon = &scc->uplinkConfigCommon->initialUplinkBWP; + dl_genericParameters = mac->bwp_dlcommon->genericParameters; if(scc->uplinkConfigCommon) ul_genericParameters = scc->uplinkConfigCommon->initialUplinkBWP.genericParameters; else - ul_genericParameters = bwp_dlcommon->genericParameters; + ul_genericParameters = mac->bwp_dlcommon->genericParameters; DL_BWP->pdsch_Config = NULL; - if (bwp_dlcommon->pdsch_ConfigCommon) - DL_BWP->tdaList_Common = bwp_dlcommon->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList; - if (bwp_ulcommon->pusch_ConfigCommon) { - UL_BWP->tdaList_Common = bwp_ulcommon->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList; - UL_BWP->msg3_DeltaPreamble = bwp_ulcommon->pusch_ConfigCommon->choice.setup->msg3_DeltaPreamble; + if (mac->bwp_dlcommon->pdsch_ConfigCommon) + DL_BWP->tdaList_Common = mac->bwp_dlcommon->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList; + if (mac->bwp_ulcommon->pusch_ConfigCommon) { + UL_BWP->tdaList_Common = mac->bwp_ulcommon->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList; + UL_BWP->msg3_DeltaPreamble = mac->bwp_ulcommon->pusch_ConfigCommon->choice.setup->msg3_DeltaPreamble; } - if (bwp_ulcommon->pucch_ConfigCommon) - UL_BWP->pucch_ConfigCommon = bwp_ulcommon->pucch_ConfigCommon->choice.setup; - if (bwp_ulcommon->rach_ConfigCommon) - UL_BWP->rach_ConfigCommon = bwp_ulcommon->rach_ConfigCommon->choice.setup; - if (bwp_dlcommon->pdcch_ConfigCommon) - configure_ss_coreset(mac, bwp_dlcommon->pdcch_ConfigCommon->choice.setup, NULL); + if (mac->bwp_ulcommon->pucch_ConfigCommon) + UL_BWP->pucch_ConfigCommon = mac->bwp_ulcommon->pucch_ConfigCommon->choice.setup; + if (mac->bwp_ulcommon->rach_ConfigCommon) + UL_BWP->rach_ConfigCommon = mac->bwp_ulcommon->rach_ConfigCommon->choice.setup; + if (mac->bwp_dlcommon->pdcch_ConfigCommon) + configure_ss_coreset(mac, mac->bwp_dlcommon->pdcch_ConfigCommon->choice.setup, NULL); } if(cell_group_config) { @@ -586,17 +583,6 @@ void configure_current_BWP(NR_UE_MAC_INST_t *mac, if (spCellConfigDedicated->uplinkConfig->firstActiveUplinkBWP_Id) UL_BWP->bwp_id = *spCellConfigDedicated->uplinkConfig->firstActiveUplinkBWP_Id; - if (mac->scc) { - bwp_dlcommon = mac->scc->downlinkConfigCommon->initialDownlinkBWP; - bwp_ulcommon = mac->scc->uplinkConfigCommon->initialUplinkBWP; - } - else if (mac->scc_SIB) { - bwp_dlcommon = &mac->scc_SIB->downlinkConfigCommon.initialDownlinkBWP; - bwp_ulcommon = &mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP; - } - else - AssertFatal(false, "Either SCC or SCC SIB should be non-NULL\n"); - NR_BWP_Downlink_t *bwp_downlink = NULL; const struct NR_ServingCellConfig__downlinkBWP_ToAddModList *bwpList = spCellConfigDedicated->downlinkBWP_ToAddModList; if (bwpList) @@ -617,16 +603,16 @@ void configure_current_BWP(NR_UE_MAC_INST_t *mac, } else { - dl_genericParameters = bwp_dlcommon->genericParameters; + dl_genericParameters = mac->bwp_dlcommon->genericParameters; DL_BWP->pdsch_Config = spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup; - DL_BWP->tdaList_Common = bwp_dlcommon->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList; + DL_BWP->tdaList_Common = mac->bwp_dlcommon->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList; configure_ss_coreset(mac, - bwp_dlcommon->pdcch_ConfigCommon ? bwp_dlcommon->pdcch_ConfigCommon->choice.setup : NULL, + mac->bwp_dlcommon->pdcch_ConfigCommon ? mac->bwp_dlcommon->pdcch_ConfigCommon->choice.setup : NULL, spCellConfigDedicated->initialDownlinkBWP->pdcch_Config ? spCellConfigDedicated->initialDownlinkBWP->pdcch_Config->choice.setup : NULL); } - UL_BWP->msg3_DeltaPreamble = bwp_ulcommon->pusch_ConfigCommon->choice.setup->msg3_DeltaPreamble; + UL_BWP->msg3_DeltaPreamble = mac->bwp_ulcommon->pusch_ConfigCommon->choice.setup->msg3_DeltaPreamble; NR_BWP_Uplink_t *bwp_uplink = NULL; const struct NR_UplinkConfig__uplinkBWP_ToAddModList *ubwpList = spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList; @@ -651,17 +637,17 @@ void configure_current_BWP(NR_UE_MAC_INST_t *mac, UL_BWP->rach_ConfigCommon = bwp_uplink->bwp_Common->rach_ConfigCommon->choice.setup; } else { - UL_BWP->tdaList_Common = bwp_ulcommon->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList; + UL_BWP->tdaList_Common = mac->bwp_ulcommon->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList; UL_BWP->pusch_Config = spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pusch_Config->choice.setup; UL_BWP->pucch_Config = spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup; UL_BWP->srs_Config = spCellConfigDedicated->uplinkConfig->initialUplinkBWP->srs_Config->choice.setup; UL_BWP->configuredGrantConfig = spCellConfigDedicated->uplinkConfig->initialUplinkBWP->configuredGrantConfig ? spCellConfigDedicated->uplinkConfig->initialUplinkBWP->configuredGrantConfig->choice.setup : NULL; - ul_genericParameters = bwp_ulcommon->genericParameters; - if (bwp_ulcommon->pucch_ConfigCommon) - UL_BWP->pucch_ConfigCommon = bwp_ulcommon->pucch_ConfigCommon->choice.setup; - if (bwp_ulcommon->rach_ConfigCommon) - UL_BWP->rach_ConfigCommon = bwp_ulcommon->rach_ConfigCommon->choice.setup; + ul_genericParameters = mac->bwp_ulcommon->genericParameters; + if (mac->bwp_ulcommon->pucch_ConfigCommon) + UL_BWP->pucch_ConfigCommon = mac->bwp_ulcommon->pucch_ConfigCommon->choice.setup; + if (mac->bwp_ulcommon->rach_ConfigCommon) + UL_BWP->rach_ConfigCommon = mac->bwp_ulcommon->rach_ConfigCommon->choice.setup; } } else @@ -677,14 +663,10 @@ void configure_current_BWP(NR_UE_MAC_INST_t *mac, UL_BWP->BWPSize = NRRIV2BW(ul_genericParameters.locationAndBandwidth, MAX_BWP_SIZE); UL_BWP->BWPStart = NRRIV2PRBOFFSET(ul_genericParameters.locationAndBandwidth, MAX_BWP_SIZE); - DL_BWP->initial_BWPSize = mac->scc ? NRRIV2BW(mac->scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE) : - NRRIV2BW(mac->scc_SIB->downlinkConfigCommon.initialDownlinkBWP.genericParameters.locationAndBandwidth, MAX_BWP_SIZE); - UL_BWP->initial_BWPSize = mac->scc ? NRRIV2BW(mac->scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE) : - NRRIV2BW(mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP.genericParameters.locationAndBandwidth, MAX_BWP_SIZE); - DL_BWP->initial_BWPStart = mac->scc ? NRRIV2PRBOFFSET(mac->scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE) : - NRRIV2PRBOFFSET(mac->scc_SIB->downlinkConfigCommon.initialDownlinkBWP.genericParameters.locationAndBandwidth, MAX_BWP_SIZE); - UL_BWP->initial_BWPStart = mac->scc ? NRRIV2PRBOFFSET(mac->scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE) : - NRRIV2PRBOFFSET(mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP.genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + DL_BWP->initial_BWPSize = NRRIV2BW(mac->bwp_dlcommon->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + UL_BWP->initial_BWPSize = NRRIV2BW(mac->bwp_ulcommon->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + DL_BWP->initial_BWPStart = NRRIV2PRBOFFSET(mac->bwp_dlcommon->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + UL_BWP->initial_BWPStart = NRRIV2PRBOFFSET(mac->bwp_ulcommon->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); } @@ -724,10 +706,11 @@ void nr_rrc_mac_config_req_sib1(module_id_t module_id, { NR_UE_MAC_INST_t *mac = get_mac_inst(module_id); AssertFatal(scc, "SIB1 SCC should not be NULL\n"); - mac->scc_SIB = scc; + mac->tdd_UL_DL_ConfigurationCommon = scc->tdd_UL_DL_ConfigurationCommon; + mac->p_Max = scc->uplinkConfigCommon->frequencyInfoUL.p_Max; mac->si_SchedulingInfo = si_SchedulingInfo; mac->nr_band = *scc->downlinkConfigCommon.frequencyInfoDL.frequencyBandList.list.array[0]->freqBandIndicatorNR; - config_common_ue_sa(mac, module_id, cc_idP); + config_common_ue_sa(mac, scc, module_id, cc_idP); configure_current_BWP(mac, scc, NULL); // Setup the SSB to Rach Occasionsif (cell_group_config->spCellConfig) { mapping according to the config @@ -737,6 +720,28 @@ void nr_rrc_mac_config_req_sib1(module_id_t module_id, mac->phy_config_request_sent = true; } +void handle_reconfiguration_with_sync(NR_UE_MAC_INST_t *mac, + module_id_t module_id, + int cc_idP, + struct NR_ReconfigurationWithSync *reconfigurationWithSync) +{ + RA_config_t *ra = &mac->ra; + if (reconfigurationWithSync->rach_ConfigDedicated) { + ra->rach_ConfigDedicated = reconfigurationWithSync->rach_ConfigDedicated->choice.uplink; + } + NR_ServingCellConfigCommon_t *scc = reconfigurationWithSync->spCellConfigCommon; + mac->bwp_dlcommon = scc->downlinkConfigCommon->initialDownlinkBWP; + mac->bwp_ulcommon = scc->uplinkConfigCommon->initialUplinkBWP; + mac->dmrs_TypeA_Position = scc->dmrs_TypeA_Position; + mac->tdd_UL_DL_ConfigurationCommon = scc->tdd_UL_DL_ConfigurationCommon; + mac->p_Max = scc->uplinkConfigCommon->frequencyInfoUL->p_Max; + mac->nr_band = *scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]; + mac->physCellId = *scc->physCellId; + mac->crnti = reconfigurationWithSync->newUE_Identity; + LOG_I(NR_MAC, "Configuring CRNTI %x\n", mac->crnti); + config_common_ue(mac, scc, module_id, cc_idP); +} + void nr_rrc_mac_config_req_mcg(module_id_t module_id, int cc_idP, NR_CellGroupConfig_t *cell_group_config) @@ -758,69 +763,40 @@ void nr_rrc_mac_config_req_mcg(module_id_t module_id, mac->scheduling_info.periodicBSR_SF, mac->scheduling_info.retxBSR_SF); - RA_config_t *ra = &mac->ra; if (cell_group_config->spCellConfig && cell_group_config->spCellConfig->reconfigurationWithSync) { LOG_A(NR_MAC, "Received the reconfigurationWithSync in %s\n", __FUNCTION__); - if (cell_group_config->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated) { - ra->rach_ConfigDedicated = cell_group_config->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink; - } - mac->scc = cell_group_config->spCellConfig->reconfigurationWithSync->spCellConfigCommon; - mac->nr_band = *mac->scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]; - if (mac->scc_SIB) { - ASN_STRUCT_FREE(asn_DEF_NR_ServingCellConfigCommonSIB, mac->scc_SIB); - mac->scc_SIB = NULL; - } + + handle_reconfiguration_with_sync(mac, module_id, cc_idP, cell_group_config->spCellConfig->reconfigurationWithSync); + mac->state = UE_NOT_SYNC; mac->ra.ra_state = RA_UE_IDLE; - mac->physCellId = *mac->scc->physCellId; + nr_ue_mac_default_configs(mac); + if (!get_softmodem_params()->emulate_l1) { mac->synch_request.Mod_id = module_id; mac->synch_request.CC_id = cc_idP; mac->synch_request.synch_req.target_Nid_cell = mac->physCellId; mac->if_module->synch_request(&mac->synch_request); - } - mac->crnti = cell_group_config->spCellConfig->reconfigurationWithSync->newUE_Identity; - LOG_I(NR_MAC, "Configuring CRNTI %x\n", mac->crnti); - - configure_current_BWP(mac, NULL, cell_group_config); - config_common_ue(mac, module_id, cc_idP); - nr_ue_mac_default_configs(mac); - - if (!get_softmodem_params()->emulate_l1) { mac->if_module->phy_config_request(&mac->phy_config); mac->phy_config_request_sent = true; } - // Setup the SSB to Rach Occasions mapping according to the config build_ssb_to_ro_map(mac); - } else { - configure_current_BWP(mac, NULL, cell_group_config); } + configure_current_BWP(mac, NULL, cell_group_config); } void nr_rrc_mac_config_req_scg(module_id_t module_id, int cc_idP, NR_CellGroupConfig_t *scell_group_config) { - NR_UE_MAC_INST_t *mac = get_mac_inst(module_id); - RA_config_t *ra = &mac->ra; - AssertFatal(scell_group_config, "scell_group_config cannot be NULL\n"); mac->cg = scell_group_config; mac->servCellIndex = *scell_group_config->spCellConfig->servCellIndex; - if (scell_group_config->spCellConfig->reconfigurationWithSync) { - if (scell_group_config->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated) { - ra->rach_ConfigDedicated = scell_group_config->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink; - } - mac->scc = scell_group_config->spCellConfig->reconfigurationWithSync->spCellConfigCommon; - mac->nr_band = *mac->scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]; - mac->physCellId = *mac->scc->physCellId; - config_common_ue(mac,module_id,cc_idP); - mac->crnti = scell_group_config->spCellConfig->reconfigurationWithSync->newUE_Identity; - LOG_I(MAC,"Configuring CRNTI %x\n",mac->crnti); - } + if (scell_group_config->spCellConfig->reconfigurationWithSync) + handle_reconfiguration_with_sync(mac, module_id, cc_idP, scell_group_config->spCellConfig->reconfigurationWithSync); configure_current_BWP(mac, NULL, scell_group_config); // Setup the SSB to Rach Occasions mapping according to the config build_ssb_to_ro_map(mac); diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index 596354223f..7c6419a22b 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -422,8 +422,6 @@ typedef struct ssb_list_info { /*!\brief Top level UE MAC structure */ typedef struct { NR_UE_L2_STATE_t state; - NR_ServingCellConfigCommon_t *scc; - NR_ServingCellConfigCommonSIB_t *scc_SIB; NR_CellGroupConfig_t *cg; int servCellIndex; NR_CSI_ReportConfig_t *csirc; @@ -445,6 +443,9 @@ typedef struct { NR_UE_DL_BWP_t current_DL_BWP; NR_UE_UL_BWP_t current_UL_BWP; + NR_BWP_DownlinkCommon_t *bwp_dlcommon; + NR_BWP_UplinkCommon_t *bwp_ulcommon; + NR_UL_TIME_ALIGNMENT_t ul_time_alignment; NR_SearchSpace_t *otherSI_SS; @@ -455,6 +456,8 @@ typedef struct { NR_SearchSpace_t *BWP_searchspaces[FAPI_NR_MAX_SS]; NR_SearchSpace_t *search_space_zero; + NR_TDD_UL_DL_ConfigCommon_t *tdd_UL_DL_ConfigurationCommon; + bool phy_config_request_sent; frame_type_t frame_type; @@ -508,6 +511,9 @@ typedef struct { /// PHR uint8_t PHR_reporting_active; + int dmrs_TypeA_Position; + NR_P_Max_t *p_Max; + NR_Type0_PDCCH_CSS_config_t type0_PDCCH_CSS_config; frequency_range_t frequency_range; uint16_t nr_band; diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index 383880bcb2..5534e586b1 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -238,8 +238,6 @@ void config_dci_pdu(NR_UE_MAC_INST_t *mac, void ue_dci_configuration(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_request_t *dl_config, const frame_t frame, const int slot); -NR_BWP_DownlinkCommon_t *get_bwp_downlink_common(NR_UE_MAC_INST_t *mac, NR_BWP_Id_t dl_bwp_id); - uint8_t nr_ue_get_sdu(module_id_t module_idP, int cc_id, frame_t frameP, diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index 9820e60107..54d91e9971 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -72,14 +72,14 @@ void init_RA(module_id_t mod_id, ra->starting_preamble_nb = 0; ra->RA_backoff_cnt = 0; + fapi_nr_config_request_t *cfg = &mac->phy_config.config_req; + prach_resources->RA_PREAMBLE_BACKOFF = 0; NR_SubcarrierSpacing_t prach_scs = *nr_rach_ConfigCommon->msg1_SubcarrierSpacing; int n_prbs = get_N_RA_RB (prach_scs, mac->current_UL_BWP.scs); int start_prb = rach_ConfigGeneric->msg1_FrequencyStart + mac->current_UL_BWP.BWPStart; - int carrier_bandwidth = mac->scc_SIB ? mac->scc_SIB->uplinkConfigCommon->frequencyInfoUL.scs_SpecificCarrierList.list.array[0]->carrierBandwidth : - mac->scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth; // PRACH shall be as specified for QPSK modulated DFT-s-OFDM of equivalent RB allocation (38.101-1) - prach_resources->RA_PCMAX = nr_get_Pcmax(mac, 2, false, prach_scs, carrier_bandwidth, true, n_prbs, start_prb); + prach_resources->RA_PCMAX = nr_get_Pcmax(mac, 2, false, prach_scs, cfg->carrier_config.dl_grid_size[prach_scs], true, n_prbs, start_prb); prach_resources->RA_PREAMBLE_TRANSMISSION_COUNTER = 1; prach_resources->RA_PREAMBLE_POWER_RAMPING_COUNTER = 1; prach_resources->POWER_OFFSET_2STEP_RA = 0; @@ -810,25 +810,17 @@ uint8_t nr_ue_get_rach(module_id_t mod_id, return ra->ra_state; } -void nr_get_RA_window(NR_UE_MAC_INST_t *mac){ - - uint8_t mu, ra_ResponseWindow; +void nr_get_RA_window(NR_UE_MAC_INST_t *mac) +{ RA_config_t *ra = &mac->ra; NR_RACH_ConfigCommon_t *setup = mac->current_UL_BWP.rach_ConfigCommon; AssertFatal(&setup->rach_ConfigGeneric != NULL, "In %s: FATAL! rach_ConfigGeneric is NULL...\n", __FUNCTION__); NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &setup->rach_ConfigGeneric; - long scs = (mac->scc) ? - mac->scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing : - mac->scc_SIB->downlinkConfigCommon.frequencyInfoDL.scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; - ra_ResponseWindow = rach_ConfigGeneric->ra_ResponseWindow; + int ra_ResponseWindow = rach_ConfigGeneric->ra_ResponseWindow; + int mu = mac->current_DL_BWP.scs; - if (setup->msg1_SubcarrierSpacing) - mu = *setup->msg1_SubcarrierSpacing; - else - mu = scs; - - ra->RA_window_cnt = ra->RA_offset*nr_slots_per_frame[mu]; // taking into account the 2 frames gap introduced by OAI gNB + ra->RA_window_cnt = ra->RA_offset * nr_slots_per_frame[mu]; // taking into account the 2 frames gap introduced by OAI gNB switch (ra_ResponseWindow) { case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl1: diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_power_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_power_procedures.c index 21c726336e..02c4881898 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_power_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_power_procedures.c @@ -57,12 +57,11 @@ int nr_get_Pcmax(NR_UE_MAC_INST_t *mac, int Qm, bool powerBoostPi2BPSK, int scs, if(mac->frequency_range == FR1) { //TODO configure P-MAX from the upper layers according to 38.331 - long *p_emax = (mac->scc!=NULL) ? mac->scc->uplinkConfigCommon->frequencyInfoUL->p_Max : mac->scc_SIB->uplinkConfigCommon->frequencyInfoUL.p_Max; int p_powerclass = 23; // dBm assuming poweclass 3 UE - + int p_emax = mac->p_Max ? *mac->p_Max : 0; int delta_P_powerclass = 0; // for powerclass 2 needs to be changed - if(p_emax && Qm == 1 && powerBoostPi2BPSK && (nr_band == 40 || nr_band == 41 || nr_band == 77 || nr_band == 78 || nr_band == 79)) { - *p_emax += 3; + if(mac->p_Max && Qm == 1 && powerBoostPi2BPSK && (nr_band == 40 || nr_band == 41 || nr_band == 77 || nr_band == 78 || nr_band == 79)) { + p_emax += 3; delta_P_powerclass -= 3; } @@ -137,10 +136,10 @@ int nr_get_Pcmax(NR_UE_MAC_INST_t *mac, int Qm, bool powerBoostPi2BPSK, int scs, if (P_MPR > total_reduction) total_reduction = P_MPR; int pcmax_high, pcmax_low; - if(p_emax) { - pcmax_high = *p_emax < (p_powerclass - delta_P_powerclass) ? *p_emax : (p_powerclass - delta_P_powerclass); - pcmax_low = (*p_emax - delta_TC) < (p_powerclass - delta_P_powerclass - total_reduction) ? - (*p_emax - delta_TC) : (p_powerclass - delta_P_powerclass - total_reduction); + if(mac->p_Max) { + pcmax_high = p_emax < (p_powerclass - delta_P_powerclass) ? p_emax : (p_powerclass - delta_P_powerclass); + pcmax_low = (p_emax - delta_TC) < (p_powerclass - delta_P_powerclass - total_reduction) ? + (p_emax - delta_TC) : (p_powerclass - delta_P_powerclass - total_reduction); } else { pcmax_high = p_powerclass - delta_P_powerclass; diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 0bc0546fe4..b1706f7fbf 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -207,18 +207,6 @@ void nr_ue_mac_default_configs(NR_UE_MAC_INST_t *mac) memset(&mac->ul_time_alignment, 0, sizeof(mac->ul_time_alignment)); } -NR_BWP_DownlinkCommon_t *get_bwp_downlink_common(NR_UE_MAC_INST_t *mac, NR_BWP_Id_t dl_bwp_id) { - NR_BWP_DownlinkCommon_t *bwp_Common = NULL; - if (dl_bwp_id > 0 && mac->cg->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList) { - bwp_Common = mac->cg->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[dl_bwp_id-1]->bwp_Common; - } else if (mac->scc) { - bwp_Common = mac->scc->downlinkConfigCommon->initialDownlinkBWP; - } else if (mac->scc_SIB) { - bwp_Common = &mac->scc_SIB->downlinkConfigCommon.initialDownlinkBWP; - } - return bwp_Common; -} - int get_rnti_type(NR_UE_MAC_INST_t *mac, uint16_t rnti) { @@ -288,6 +276,7 @@ int8_t nr_ue_decode_mib(module_id_t module_id, #endif mac->ssb_subcarrier_offset = ssb_subcarrier_offset; + mac->dmrs_TypeA_Position = mac->mib->dmrs_TypeA_Position; if (mac->first_sync_frame == -1) mac->first_sync_frame = frame; @@ -647,7 +636,7 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr dlsch_config_pdu_1_0->rb_offset -= dlsch_config_pdu_1_0->BWPStart; /* TIME_DOM_RESOURCE_ASSIGNMENT */ - int dmrs_typeA_pos = (mac->scc != NULL) ? mac->scc->dmrs_TypeA_Position : mac->mib->dmrs_TypeA_Position; + int dmrs_typeA_pos = mac->dmrs_TypeA_Position; NR_tda_info_t tda_info = get_dl_tda_info(current_DL_BWP, dci_ind->ss_type, dci->time_domain_assignment.val, dmrs_typeA_pos, mux_pattern, get_rnti_type(mac, rnti), coreset_type, mac->get_sib1); @@ -669,7 +658,7 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr /* dmrs symbol positions*/ dlsch_config_pdu_1_0->dlDmrsSymbPos = fill_dmrs_mask(pdsch_config, NR_DL_DCI_FORMAT_1_0, - mac->scc ? mac->scc->dmrs_TypeA_Position : mac->mib->dmrs_TypeA_Position, + mac->dmrs_TypeA_Position, dlsch_config_pdu_1_0->number_symbols, dlsch_config_pdu_1_0->start_symbol, tda_info.mapping_type, @@ -868,7 +857,7 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr } dlsch_config_pdu_1_1->rb_offset = dlsch_config_pdu_1_1->start_rb + dlsch_config_pdu_1_1->BWPStart; /* TIME_DOM_RESOURCE_ASSIGNMENT */ - int dmrs_typeA_pos = (mac->scc != NULL) ? mac->scc->dmrs_TypeA_Position : mac->mib->dmrs_TypeA_Position; + int dmrs_typeA_pos = mac->dmrs_TypeA_Position; NR_tda_info_t tda_info = get_dl_tda_info(current_DL_BWP, dci_ind->ss_type, dci->time_domain_assignment.val, dmrs_typeA_pos, mux_pattern, get_rnti_type(mac, rnti), coreset_type, false); @@ -1059,7 +1048,7 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr /* dmrs symbol positions*/ dlsch_config_pdu_1_1->dlDmrsSymbPos = fill_dmrs_mask(pdsch_Config, NR_DL_DCI_FORMAT_1_1, - mac->scc? mac->scc->dmrs_TypeA_Position:mac->mib->dmrs_TypeA_Position, + mac->dmrs_TypeA_Position, dlsch_config_pdu_1_1->number_symbols, dlsch_config_pdu_1_1->start_symbol, tda_info.mapping_type, @@ -1276,6 +1265,7 @@ void nr_ue_configure_pucch(NR_UE_MAC_INST_t *mac, // Only HARQ transmitted in default PUCCH pucch_pdu->mcs = get_pucch0_mcs(pucch->n_harq, 0, pucch->ack_payload, 0); pucch_pdu->payload = pucch->ack_payload; + pucch_pdu->n_bit = 1; } else if (pucch->pucch_resource != NULL) { @@ -1315,9 +1305,6 @@ void nr_ue_configure_pucch(NR_UE_MAC_INST_t *mac, LOG_E(MAC,"PUCCH number of UCI bits exceeds payload size\n"); return; } - if (pucchres->format.present != NR_PUCCH_Resource__format_PR_format0) - pucch_pdu->payload = - (pucch->csi_part1_payload << (pucch->n_harq + pucch->n_sr)) | (pucch->sr_payload << pucch->n_harq) | pucch->ack_payload; switch(pucchres->format.present) { case NR_PUCCH_Resource__format_PR_format0 : @@ -1333,6 +1320,18 @@ void nr_ue_configure_pucch(NR_UE_MAC_INST_t *mac, pucch_pdu->nr_of_symbols = pucchres->format.choice.format1->nrofSymbols; pucch_pdu->start_symbol_index = pucchres->format.choice.format1->startingSymbolIndex; pucch_pdu->time_domain_occ_idx = pucchres->format.choice.format1->timeDomainOCC; + if (pucch->n_harq > 0) { + // only HARQ bits are transmitted, resource selection depends on SR + // resource selection handled in function multiplex_pucch_resource + pucch_pdu->n_bit = pucch->n_harq; + pucch_pdu->payload = pucch->ack_payload; + } + else { + // For a positive SR transmission using PUCCH format 1, + // the UE transmits the PUCCH as described in 38.211 by setting b(0) = 0 + pucch_pdu->n_bit = pucch->n_sr; + pucch_pdu->payload = 0; + } break; case NR_PUCCH_Resource__format_PR_format2 : pucch_pdu->format_type = 2; @@ -1348,6 +1347,7 @@ void nr_ue_configure_pucch(NR_UE_MAC_INST_t *mac, 2, pucchres->format.choice.format2->nrofSymbols, 8); + pucch_pdu->payload = (pucch->csi_part1_payload << (pucch->n_harq + pucch->n_sr)) | (pucch->sr_payload << pucch->n_harq) | pucch->ack_payload; break; case NR_PUCCH_Resource__format_PR_format3 : pucch_pdu->format_type = 3; @@ -1380,6 +1380,7 @@ void nr_ue_configure_pucch(NR_UE_MAC_INST_t *mac, 2 - pucch_pdu->pi_2bpsk, pucchres->format.choice.format3->nrofSymbols - f3_dmrs_symbols, 12); + pucch_pdu->payload = (pucch->csi_part1_payload << (pucch->n_harq + pucch->n_sr)) | (pucch->sr_payload << pucch->n_harq) | pucch->ack_payload; break; case NR_PUCCH_Resource__format_PR_format4 : pucch_pdu->format_type = 4; @@ -1397,6 +1398,7 @@ void nr_ue_configure_pucch(NR_UE_MAC_INST_t *mac, pucch_pdu->pi_2bpsk = pucchfmt->pi2BPSK!= NULL ? 1 : 0; pucch_pdu->add_dmrs_flag = pucchfmt->additionalDMRS!= NULL ? 1 : 0; } + pucch_pdu->payload = (pucch->csi_part1_payload << (pucch->n_harq + pucch->n_sr)) | (pucch->sr_payload << pucch->n_harq) | pucch->ack_payload; break; default : AssertFatal(1==0,"Undefined PUCCH format \n"); @@ -4138,17 +4140,13 @@ int nr_ue_process_rar(nr_downlink_indication_t *dl_info, int pdu_id) // - referenceSignalPower: dBm/RE (average EPRE of the resources elements that carry secondary synchronization signals in dBm) int16_t compute_nr_SSB_PL(NR_UE_MAC_INST_t *mac, short ssb_rsrp_dBm) { - - long referenceSignalPower; + fapi_nr_config_request_t *cfg = &mac->phy_config.config_req; + int referenceSignalPower = cfg->ssb_config.ss_pbch_power; //TODO improve PL measurements. Probably not correct as it is. - if (mac->scc) - referenceSignalPower = mac->scc->ss_PBCH_BlockPower; - else - referenceSignalPower = mac->scc_SIB->ss_PBCH_BlockPower; int16_t pathloss = (int16_t)(referenceSignalPower - ssb_rsrp_dBm); - LOG_D(NR_MAC, "pathloss %d dB, referenceSignalPower %ld dBm/RE (%f mW), RSRP %d dBm (%f mW)\n", + LOG_D(NR_MAC, "pathloss %d dB, referenceSignalPower %d dBm/RE (%f mW), RSRP %d dBm (%f mW)\n", pathloss, referenceSignalPower, pow(10, referenceSignalPower/10), diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index defaf6c37d..94aff89a56 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -111,7 +111,7 @@ void fill_scheduled_response(nr_scheduled_response_t *scheduled_response, fapi_nr_ul_config_request_t *get_ul_config_request(NR_UE_MAC_INST_t *mac, int slot, int fb_time) { - NR_TDD_UL_DL_ConfigCommon_t *tdd_config = mac->scc==NULL ? mac->scc_SIB->tdd_UL_DL_ConfigurationCommon : mac->scc->tdd_UL_DL_ConfigurationCommon; + NR_TDD_UL_DL_ConfigCommon_t *tdd_config = mac->tdd_UL_DL_ConfigurationCommon; //Check if requested on the right slot AssertFatal(is_nr_UL_slot(tdd_config, slot, mac->frame_type) != 0, "UL config_request called at wrong slot %d\n", slot); @@ -483,8 +483,12 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, pusch_config_pdu->start_symbol_index = tda_info->startSymbolIndex; pusch_config_pdu->nr_of_symbols = tda_info->nrOfSymbols; - l_prime_mask = - get_l_prime(tda_info->nrOfSymbols, tda_info->mapping_type, add_pos, dmrslength, tda_info->startSymbolIndex, mac->scc ? mac->scc->dmrs_TypeA_Position : mac->mib->dmrs_TypeA_Position); + l_prime_mask = get_l_prime(tda_info->nrOfSymbols, + tda_info->mapping_type, + add_pos, + dmrslength, + tda_info->startSymbolIndex, + mac->dmrs_TypeA_Position); LOG_D(NR_MAC, "MSG3 start_sym:%d NR Symb:%d mappingtype:%d, DMRS_MASK:%x\n", pusch_config_pdu->start_symbol_index, pusch_config_pdu->nr_of_symbols, tda_info->mapping_type, l_prime_mask); #ifdef DEBUG_MSG3 @@ -655,7 +659,7 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, l_prime_mask = get_l_prime(pusch_config_pdu->nr_of_symbols, mappingtype, add_pos, dmrslength, pusch_config_pdu->start_symbol_index, - mac->scc ? mac->scc->dmrs_TypeA_Position : mac->mib->dmrs_TypeA_Position); + mac->dmrs_TypeA_Position); // Num PRB Overhead from PUSCH-ServingCellConfig if (current_UL_BWP->pusch_servingcellconfig && current_UL_BWP->pusch_servingcellconfig->xOverhead) @@ -859,7 +863,7 @@ void nr_ue_aperiodic_srs_scheduling(NR_UE_MAC_INST_t *mac, long resource_trigger slot_offset, DURATION_RX_TO_TX); int n_slots_frame = nr_slots_per_frame[current_UL_BWP->scs]; int sched_slot = (slot + slot_offset) % n_slots_frame; - NR_TDD_UL_DL_ConfigCommon_t *tdd_config = mac->scc==NULL ? mac->scc_SIB->tdd_UL_DL_ConfigurationCommon : mac->scc->tdd_UL_DL_ConfigurationCommon; + NR_TDD_UL_DL_ConfigCommon_t *tdd_config = mac->tdd_UL_DL_ConfigurationCommon; if (!is_nr_UL_slot(tdd_config, sched_slot, mac->frame_type)) { LOG_E(NR_MAC, "Slot for scheduling aperiodic SRS %d is not an UL slot\n", sched_slot); return; @@ -1655,84 +1659,20 @@ static void build_ssb_list(NR_UE_MAC_INST_t *mac) { // Create the list of transmitted SSBs // =================================== - BIT_STRING_t *ssb_bitmap; - uint64_t ssb_positionsInBurst; - uint8_t ssb_idx = 0; ssb_list_info_t *ssb_list = &mac->ssb_list; + fapi_nr_config_request_t *cfg = &mac->phy_config.config_req; + ssb_list->nb_tx_ssb = 0; - if (mac->scc) { - NR_ServingCellConfigCommon_t *scc = mac->scc; - switch (scc->ssb_PositionsInBurst->present) { - case NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_shortBitmap: - ssb_bitmap = &scc->ssb_PositionsInBurst->choice.shortBitmap; - - ssb_positionsInBurst = BIT_STRING_to_uint8(ssb_bitmap); - LOG_D(NR_MAC,"SSB config: SSB_positions_in_burst 0x%lx\n", ssb_positionsInBurst); - - for (uint8_t bit_nb=3; bit_nb<=3; bit_nb--) { - // If SSB is transmitted - if ((ssb_positionsInBurst>>bit_nb) & 0x01) { - ssb_list->nb_tx_ssb++; - ssb_list->tx_ssb[ssb_idx].transmitted = true; - LOG_D(NR_MAC,"SSB idx %d transmitted\n", ssb_idx); - } - ssb_idx++; - } - break; - case NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_mediumBitmap: - ssb_bitmap = &scc->ssb_PositionsInBurst->choice.mediumBitmap; - - ssb_positionsInBurst = BIT_STRING_to_uint8(ssb_bitmap); - LOG_D(NR_MAC,"SSB config: SSB_positions_in_burst 0x%lx\n", ssb_positionsInBurst); - - for (uint8_t bit_nb=7; bit_nb<=7; bit_nb--) { - // If SSB is transmitted - if ((ssb_positionsInBurst>>bit_nb) & 0x01) { - ssb_list->nb_tx_ssb++; - ssb_list->tx_ssb[ssb_idx].transmitted = true; - LOG_D(NR_MAC,"SSB idx %d transmitted\n", ssb_idx); - } - ssb_idx++; - } - break; - case NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_longBitmap: - ssb_bitmap = &scc->ssb_PositionsInBurst->choice.longBitmap; - - ssb_positionsInBurst = BIT_STRING_to_uint64(ssb_bitmap); - LOG_D(NR_MAC,"SSB config: SSB_positions_in_burst 0x%lx\n", ssb_positionsInBurst); - - for (uint8_t bit_nb=63; bit_nb<=63; bit_nb--) { - // If SSB is transmitted - if ((ssb_positionsInBurst>>bit_nb) & 0x01) { - ssb_list->nb_tx_ssb++; - ssb_list->tx_ssb[ssb_idx].transmitted = true; - LOG_D(NR_MAC,"SSB idx %d transmitted\n", ssb_idx); - } - ssb_idx++; - } - break; - default: - AssertFatal(false,"ssb_PositionsInBurst not present\n"); - break; - } - } else { // This is configuration from SIB1 - - AssertFatal(mac->scc_SIB->ssb_PositionsInBurst.groupPresence == NULL, "Handle case for >8 SSBs\n"); - ssb_bitmap = &mac->scc_SIB->ssb_PositionsInBurst.inOneGroup; - - ssb_positionsInBurst = BIT_STRING_to_uint8(ssb_bitmap); - - LOG_D(NR_MAC,"SSB config: SSB_positions_in_burst 0x%lx\n", ssb_positionsInBurst); - - for (uint8_t bit_nb=7; bit_nb<=7; bit_nb--) { - // If SSB is transmitted - if ((ssb_positionsInBurst>>bit_nb) & 0x01) { - ssb_list->nb_tx_ssb++; - ssb_list->tx_ssb[ssb_idx].transmitted = true; - LOG_D(NR_MAC,"SSB idx %d transmitted\n", ssb_idx); - } - ssb_idx++; + for(int ssb_index = 0; ssb_index < 64; ssb_index++) { + uint32_t curr_mask = cfg->ssb_table.ssb_mask_list[ssb_index / 32].ssb_mask; + // check if if current SSB is transmitted + if ((curr_mask >> (31 - (ssb_index % 32))) & 0x01) { + ssb_list->nb_tx_ssb++; + ssb_list->tx_ssb[ssb_index].transmitted = true; + LOG_D(NR_MAC,"SSB idx %d transmitted\n", ssb_index); } + else + ssb_list->tx_ssb[ssb_index].transmitted = false; } } @@ -2512,12 +2452,10 @@ static void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_fr fapi_nr_prach_config_t *prach_config = &cfg->prach_config; nr_scheduled_response_t scheduled_response; - NR_ServingCellConfigCommon_t *scc = mac->scc; - NR_ServingCellConfigCommonSIB_t *scc_SIB = mac->scc_SIB; NR_RACH_ConfigCommon_t *setup = mac->current_UL_BWP.rach_ConfigCommon; NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &setup->rach_ConfigGeneric; - NR_TDD_UL_DL_ConfigCommon_t *tdd_config = scc==NULL ? scc_SIB->tdd_UL_DL_ConfigurationCommon : scc->tdd_UL_DL_ConfigurationCommon; + NR_TDD_UL_DL_ConfigCommon_t *tdd_config = mac->tdd_UL_DL_ConfigurationCommon; if (is_nr_UL_slot(tdd_config, slotP, mac->frame_type)) { diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index 0d213c6826..01a0a1ef6b 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -379,6 +379,33 @@ void abort_nr_dl_harq(NR_UE_info_t* UE, int8_t harq_pid) } +static void get_start_stop_allocation(gNB_MAC_INST *mac, + NR_UE_info_t *UE, + int *rbStart, + int *rbStop) +{ + NR_UE_DL_BWP_t *dl_bwp = &UE->current_DL_BWP; + NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; + // UE is scheduled in a set of contiguously allocated resource blocks within the active bandwidth part of size N_BWP PRBs + // except for the case when DCI format 1_0 is decoded in any common search space + // in which case the size of CORESET 0 shall be used if CORESET 0 is configured for the cell + // and the size of initial DL bandwidth part shall be used if CORESET 0 is not configured for the cell. + // TS 38.214 Section 5.1.2.2.2 + *rbStop = dl_bwp->BWPSize; + *rbStart = 0; // start wrt BWPstart + if (sched_ctrl->search_space->searchSpaceType->present == NR_SearchSpace__searchSpaceType_PR_common && + dl_bwp->dci_format == NR_DL_DCI_FORMAT_1_0) { + if (mac->cset0_bwp_size != 0) { + *rbStart = mac->cset0_bwp_start; + *rbStop = *rbStart + mac->cset0_bwp_size; + } + else { + *rbStart = dl_bwp->initial_BWPStart; + *rbStop = *rbStart + dl_bwp->initial_BWPSize; + } + } +} + static bool allocate_dl_retransmission(module_id_t module_id, frame_t frame, sub_frame_t slot, @@ -404,9 +431,11 @@ static bool allocate_dl_retransmission(module_id_t module_id, int pm_index = (curInfo->nrOfLayers < retInfo->nrOfLayers) ? curInfo->pm_index : retInfo->pm_index; const int coresetid = sched_ctrl->coreset->controlResourceSetId; - const uint16_t bwpSize = coresetid == 0 ? nr_mac->cset0_bwp_size : dl_bwp->BWPSize; - int rbStart = 0; // start wrt BWPstart + int rbStop = 0; + int rbStart = 0; + get_start_stop_allocation(nr_mac, UE, &rbStart, &rbStop); + int rbSize = 0; const int tda = get_dl_tda(nr_mac, scc, slot); AssertFatal(tda>=0,"Unable to find PDSCH time domain allocation in list\n"); @@ -429,10 +458,10 @@ static bool allocate_dl_retransmission(module_id_t module_id, rbSize = 0; const uint16_t slbitmap = SL_to_bitmap(retInfo->tda_info.startSymbolIndex, retInfo->tda_info.nrOfSymbols); - while (rbStart < bwpSize && (rballoc_mask[rbStart] & slbitmap) != slbitmap) + while (rbStart < rbStop && (rballoc_mask[rbStart] & slbitmap) != slbitmap) rbStart++; - if (rbStart >= bwpSize) { + if (rbStart >= rbStop) { LOG_D(NR_MAC, "[UE %04x][%4d.%2d] could not allocate DL retransmission: no resources\n", UE->rnti, frame, @@ -440,7 +469,7 @@ static bool allocate_dl_retransmission(module_id_t module_id, return false; } - while (rbStart + rbSize < bwpSize && + while (rbStart + rbSize < rbStop && (rballoc_mask[rbStart + rbSize] & slbitmap) == slbitmap && rbSize < retInfo->rbSize) rbSize++; @@ -454,10 +483,10 @@ static bool allocate_dl_retransmission(module_id_t module_id, layers); const uint16_t slbitmap = SL_to_bitmap(temp_tda.startSymbolIndex, temp_tda.nrOfSymbols); - while (rbStart < bwpSize && (rballoc_mask[rbStart] & slbitmap) != slbitmap) + while (rbStart < rbStop && (rballoc_mask[rbStart] & slbitmap) != slbitmap) rbStart++; - while (rbStart + rbSize < bwpSize && (rballoc_mask[rbStart + rbSize] & slbitmap) == slbitmap) + while (rbStart + rbSize < rbStop && (rballoc_mask[rbStart + rbSize] & slbitmap) == slbitmap) rbSize++; uint32_t new_tbs; @@ -673,12 +702,6 @@ static void pf_dl(module_id_t module_id, NR_UE_DL_BWP_t *dl_bwp = &iterator->UE->current_DL_BWP; NR_UE_UL_BWP_t *ul_bwp = &iterator->UE->current_UL_BWP; - const int coresetid = sched_ctrl->coreset->controlResourceSetId; - const uint16_t bwpSize = coresetid == 0 ? - mac->cset0_bwp_size : - dl_bwp->BWPSize; - int rbStart = 0; // start wrt BWPstart - if (sched_ctrl->available_dl_harq.head < 0) { LOG_D(NR_MAC, "[UE %04x][%4d.%2d] UE has no free DL HARQ process, skipping\n", iterator->UE->rnti, @@ -731,6 +754,7 @@ static void pf_dl(module_id_t module_id, sched_pdsch->time_domain_allocation = get_dl_tda(mac, scc, slot); AssertFatal(sched_pdsch->time_domain_allocation>=0,"Unable to find PDSCH time domain allocation in list\n"); + const int coresetid = sched_ctrl->coreset->controlResourceSetId; sched_pdsch->tda_info = get_dl_tda_info(dl_bwp, sched_ctrl->search_space->searchSpaceType->present, sched_pdsch->time_domain_allocation, scc->dmrs_TypeA_Position, 1, NR_RNTI_C, coresetid, false); @@ -738,13 +762,16 @@ static void pf_dl(module_id_t module_id, const uint16_t slbitmap = SL_to_bitmap(tda_info->startSymbolIndex, tda_info->nrOfSymbols); + int rbStop = 0; + int rbStart = 0; + get_start_stop_allocation(mac, iterator->UE, &rbStart, &rbStop); // Freq-demain allocation - while (rbStart < bwpSize && (rballoc_mask[rbStart] & slbitmap) != slbitmap) + while (rbStart < rbStop && (rballoc_mask[rbStart] & slbitmap) != slbitmap) rbStart++; uint16_t max_rbSize = 1; - while (rbStart + max_rbSize < bwpSize && (rballoc_mask[rbStart + max_rbSize] & slbitmap) == slbitmap) + while (rbStart + max_rbSize < rbStop && (rballoc_mask[rbStart + max_rbSize] & slbitmap) == slbitmap) max_rbSize++; sched_pdsch->dmrs_parms = get_dl_dmrs_params(scc, @@ -809,8 +836,8 @@ static void nr_fr1_dlsch_preprocessor(module_id_t module_id, frame_t frame, sub_ const int startSymbolAndLength = tdaList->list.array[tda]->startSymbolAndLength; SLIV2SL(startSymbolAndLength, &startSymbolIndex, &nrOfSymbols); - const uint16_t bwpSize = coresetid == 0 ? RC.nrmac[module_id]->cset0_bwp_size : current_BWP->BWPSize; - const uint16_t BWPStart = coresetid == 0 ? RC.nrmac[module_id]->cset0_bwp_start : current_BWP->BWPStart; + const uint16_t bwpSize = current_BWP->BWPSize; + const uint16_t BWPStart = current_BWP->BWPStart; const uint16_t slbitmap = SL_to_bitmap(startSymbolIndex, nrOfSymbols); uint16_t *vrb_map = RC.nrmac[module_id]->common_channels[CC_id].vrb_map; @@ -1013,13 +1040,8 @@ void nr_schedule_ue_spec(module_id_t module_id, const int pduindex = gNB_mac->pdu_index[CC_id]++; pdsch_pdu->pduIndex = pduindex; - if (coresetid == 0) { - pdsch_pdu->BWPSize = gNB_mac->cset0_bwp_size; - pdsch_pdu->BWPStart = gNB_mac->cset0_bwp_start; - } else { - pdsch_pdu->BWPSize = current_BWP->BWPSize; - pdsch_pdu->BWPStart = current_BWP->BWPStart; - } + pdsch_pdu->BWPSize = current_BWP->BWPSize; + pdsch_pdu->BWPStart = current_BWP->BWPStart; pdsch_pdu->SubcarrierSpacing = current_BWP->scs; pdsch_pdu->CyclicPrefix = current_BWP->cyclicprefix ? *current_BWP->cyclicprefix : 0; @@ -1123,9 +1145,17 @@ void nr_schedule_ue_spec(module_id_t module_id, AssertFatal(pdsch_Config == NULL || pdsch_Config->resourceAllocation == NR_PDSCH_Config__resourceAllocation_resourceAllocationType1, "Only frequency resource allocation type 1 is currently supported\n"); + + // For a PDSCH scheduled with a DCI format 1_0 in any type of PDCCH common search space, regardless of which + // bandwidth part is the active bandwidth part, RB numbering starts from the lowest RB of the CORESET in which the + // DCI was received; otherwise RB numbering starts from the lowest RB in the determined downlink bandwidth part. + // TS 38.214 Section 5.1.2.2.2 + int rbStop = 0; + int rbStart = 0; + get_start_stop_allocation(gNB_mac, UE, &rbStart, &rbStop); dci_payload.frequency_domain_assignment.val = PRBalloc_to_locationandbandwidth0(pdsch_pdu->rbSize, - pdsch_pdu->rbStart, - pdsch_pdu->BWPSize); + pdsch_pdu->rbStart - rbStart, + rbStop - rbStart); dci_payload.format_indicator = 1; dci_payload.time_domain_assignment.val = sched_pdsch->time_domain_allocation; dci_payload.mcs = sched_pdsch->mcs; diff --git a/openair2/LAYER2/NR_MAC_gNB/main.c b/openair2/LAYER2/NR_MAC_gNB/main.c index c64c975f0e..cdba0b676b 100644 --- a/openair2/LAYER2/NR_MAC_gNB/main.c +++ b/openair2/LAYER2/NR_MAC_gNB/main.c @@ -240,6 +240,9 @@ void mac_top_init_gNB(ngran_node_t node_type) RC.nrmac[i]->first_MIB = true; + RC.nrmac[i]->cset0_bwp_start = 0; + RC.nrmac[i]->cset0_bwp_size = 0; + pthread_mutex_init(&RC.nrmac[i]->sched_lock, NULL); pthread_mutex_init(&RC.nrmac[i]->UE_info.mutex, NULL); diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp.c b/openair2/LAYER2/PDCP_v10.1.0/pdcp.c index b52f3fb9b4..2dcc3e429d 100644 --- a/openair2/LAYER2/PDCP_v10.1.0/pdcp.c +++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp.c @@ -135,6 +135,36 @@ pdcp_enb_t pdcp_enb[MAX_NUM_CCs]; extern int oai_exit; pthread_t pdcp_stats_thread_desc; +/*! \fn bool pdcp_config_req_asn1 (const protocol_ctxt_t* const ctxt_pP, srb_flag_t srb_flagP, uint32_t action, rb_id_t rb_id, + * uint8_t rb_sn, uint8_t rb_report, uint16_t header_compression_profile, uint8_t security_mode) \brief Function for RRC to + * configure a Radio Bearer. \param[in] ctxt_pP Running context. \param[in] pdcp_pP Pointer on PDCP + * structure. \param[in] enb_mod_idP Virtualized enb module identifier, Not used if eNB_flagP = 0. \param[in] ue_mod_idP + * Virtualized ue module identifier. \param[in] frame Frame index. \param[in] eNB_flag Flag to indicate eNB + * (1) or UE (0) \param[in] srb_flagP Flag to indicate SRB (1) or DRB (0) \param[in] action add, remove, + * modify a RB \param[in] rb_id radio bearer id \param[in] rb_sn sequence number for this radio bearer + * \param[in] drb_report set a pdcp report for this drb + * \param[in] header_compression set the rohc profile + * \param[in] security_mode set the integrity and ciphering algs + * \param[in] kRRCenc RRC encryption key + * \param[in] kRRCint RRC integrity key + * \param[in] kUPenc User-Plane encryption key + * \return A status about the processing, OK or error code. + */ +static bool pdcp_config_req_asn1(const protocol_ctxt_t *const ctxt_pP, + pdcp_t *const pdcp_pP, + const srb_flag_t srb_flagP, + const rlc_mode_t rlc_modeP, + const config_action_t actionP, + const uint16_t lc_idP, + const uint16_t mch_idP, + const rb_id_t rb_idP, + const uint8_t rb_snP, + const uint8_t rb_reportP, + const uint16_t header_compression_profileP, + const uint8_t security_modeP, + uint8_t *const kRRCenc_pP, + uint8_t *const kRRCint_pP, + uint8_t *const kUPenc_pP); void *pdcp_stats_thread(void *param) { @@ -1880,24 +1910,21 @@ rrc_pdcp_config_asn1_req(const protocol_ctxt_t *const ctxt_pP, return 0; } - -//----------------------------------------------------------------------------- -bool -pdcp_config_req_asn1(const protocol_ctxt_t *const ctxt_pP, - pdcp_t *const pdcp_pP, - const srb_flag_t srb_flagP, - const rlc_mode_t rlc_modeP, - const config_action_t actionP, - const uint16_t lc_idP, - const uint16_t mch_idP, - const rb_id_t rb_idP, - const uint8_t rb_snP, - const uint8_t rb_reportP, - const uint16_t header_compression_profileP, - const uint8_t security_modeP, - uint8_t *const kRRCenc_pP, - uint8_t *const kRRCint_pP, - uint8_t *const kUPenc_pP) +static bool pdcp_config_req_asn1(const protocol_ctxt_t *const ctxt_pP, + pdcp_t *const pdcp_pP, + const srb_flag_t srb_flagP, + const rlc_mode_t rlc_modeP, + const config_action_t actionP, + const uint16_t lc_idP, + const uint16_t mch_idP, + const rb_id_t rb_idP, + const uint8_t rb_snP, + const uint8_t rb_reportP, + const uint16_t header_compression_profileP, + const uint8_t security_modeP, + uint8_t *const kRRCenc_pP, + uint8_t *const kRRCint_pP, + uint8_t *const kUPenc_pP) //----------------------------------------------------------------------------- { diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp.h b/openair2/LAYER2/PDCP_v10.1.0/pdcp.h index 9f4cdefb3b..1f1a9ae740 100644 --- a/openair2/LAYER2/PDCP_v10.1.0/pdcp.h +++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp.h @@ -322,42 +322,6 @@ bool rrc_pdcp_config_asn1_req(const protocol_ctxt_t *const ctxt_pP, LTE_PMCH_InfoList_r9_t *pmch_InfoList_r9, rb_id_t *const defaultDRB); -/*! \fn bool pdcp_config_req_asn1 (const protocol_ctxt_t* const ctxt_pP, srb_flag_t srb_flagP, uint32_t action, rb_id_t rb_id, uint8_t rb_sn, uint8_t rb_report, uint16_t header_compression_profile, uint8_t security_mode) -* \brief Function for RRC to configure a Radio Bearer. -* \param[in] ctxt_pP Running context. -* \param[in] pdcp_pP Pointer on PDCP structure. -* \param[in] enb_mod_idP Virtualized enb module identifier, Not used if eNB_flagP = 0. -* \param[in] ue_mod_idP Virtualized ue module identifier. -* \param[in] frame Frame index. -* \param[in] eNB_flag Flag to indicate eNB (1) or UE (0) -* \param[in] srb_flagP Flag to indicate SRB (1) or DRB (0) -* \param[in] action add, remove, modify a RB -* \param[in] rb_id radio bearer id -* \param[in] rb_sn sequence number for this radio bearer -* \param[in] drb_report set a pdcp report for this drb -* \param[in] header_compression set the rohc profile -* \param[in] security_mode set the integrity and ciphering algs -* \param[in] kRRCenc RRC encryption key -* \param[in] kRRCint RRC integrity key -* \param[in] kUPenc User-Plane encryption key -* \return A status about the processing, OK or error code. -*/ -bool pdcp_config_req_asn1(const protocol_ctxt_t *const ctxt_pP, - pdcp_t *const pdcp_pP, - const srb_flag_t srb_flagP, - const rlc_mode_t rlc_mode, - const uint32_t action, - const uint16_t lc_id, - const uint16_t mch_id, - const rb_id_t rb_id, - const uint8_t rb_sn, - const uint8_t rb_report, - const uint16_t header_compression_profile, - const uint8_t security_mode, - uint8_t *const kRRCenc, - uint8_t *const kRRCint, - uint8_t *const kUPenc); - /*! \fn void pdcp_add_UE(const protocol_ctxt_t* const ctxt_pP) * \brief Function (for RRC) to add a new UE in PDCP module * \param[in] ctxt_pP Running context. diff --git a/openair2/LAYER2/nr_rlc/CMakeLists.txt b/openair2/LAYER2/nr_rlc/CMakeLists.txt new file mode 100644 index 0000000000..d72ac37d09 --- /dev/null +++ b/openair2/LAYER2/nr_rlc/CMakeLists.txt @@ -0,0 +1,22 @@ +add_library(nr_rlc_core OBJECT + nr_rlc_entity.c + nr_rlc_entity_am.c + nr_rlc_entity_tm.c + nr_rlc_entity_um.c + nr_rlc_pdu.c + nr_rlc_sdu.c) +target_include_directories(nr_rlc_core PRIVATE ../../..) +target_link_libraries(nr_rlc_core PRIVATE ${T_LIB}) +add_library(nr_rlc STATIC + asn1_utils.c + nr_rlc_oai_api.c + nr_rlc_ue_manager.c +) +# L2_NR: for PDCP +target_link_libraries(nr_rlc PUBLIC pthread f1ap nr_rlc_core UTIL ${T_LIB}) +target_include_directories(nr_rlc PRIVATE ../../..) +target_link_libraries(nr_rlc PRIVATE asn1_lte_rrc asn1_nr_rrc) + +if(ENABLE_TESTS) + add_subdirectory(tests) +endif() diff --git a/openair2/LAYER2/nr_rlc/tests/CMakeLists.txt b/openair2/LAYER2/nr_rlc/tests/CMakeLists.txt new file mode 100644 index 0000000000..1f616e7927 --- /dev/null +++ b/openair2/LAYER2/nr_rlc/tests/CMakeLists.txt @@ -0,0 +1,14 @@ + +foreach(TESTNUM RANGE 1 17) + add_executable(nr_rlc_test_${TESTNUM} test.c) + target_link_libraries(nr_rlc_test_${TESTNUM} PRIVATE nr_rlc_core pthread UTIL ${T_LIB} minimal_lib) + target_compile_definitions(nr_rlc_test_${TESTNUM} PRIVATE TEST="test${TESTNUM}.h") + #target_include_directories(nr_rlc_test_${TESTNUM} PRIVATE LOG) + #target_compile_options(nr_rlc_test_${TESTNUM} PRIVATE -g --coverage -Wall) + add_dependencies(tests nr_rlc_test_${TESTNUM}) +endforeach() + +add_test(NAME nr_rlc_tests + COMMAND exec_nr_rlc_test.sh ${CMAKE_CURRENT_BINARY_DIR} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) + diff --git a/openair2/LAYER2/nr_rlc/tests/Makefile b/openair2/LAYER2/nr_rlc/tests/Makefile index c23726444d..1e9cd432bf 100644 --- a/openair2/LAYER2/nr_rlc/tests/Makefile +++ b/openair2/LAYER2/nr_rlc/tests/Makefile @@ -1,5 +1,5 @@ CC=gcc -CFLAGS=-Wall -g --coverage -I. -I../../../.. +CFLAGS=-Wall -g --coverage -I. -I../../../.. -D_STANDALONE_TESTING_ LIB=nr_rlc_entity.o nr_rlc_entity_am.o nr_rlc_entity_um.o nr_rlc_entity_tm.o \ nr_rlc_pdu.o nr_rlc_sdu.o time_stat.o diff --git a/openair2/LAYER2/nr_rlc/tests/exec_nr_rlc_test.sh b/openair2/LAYER2/nr_rlc/tests/exec_nr_rlc_test.sh new file mode 100755 index 0000000000..8f2052075b --- /dev/null +++ b/openair2/LAYER2/nr_rlc/tests/exec_nr_rlc_test.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +# this script is to be executed in the current folder. It takes one argument, +# which is the directory in which the executables are. + +if [ $# -ne 1 ]; then + echo "usage: $0 " + exit 1 +fi + +EXEC_DIR=$1 + +for i in {1..17}; do + diff \ + <($EXEC_DIR/nr_rlc_test_$i | \grep ^TEST) \ + <(gunzip -c test$i.txt.gz) \ + || exit 1 +done diff --git a/openair2/LAYER2/nr_rlc/tests/test.c b/openair2/LAYER2/nr_rlc/tests/test.c index bfde8b9fad..716a6aef11 100644 --- a/openair2/LAYER2/nr_rlc/tests/test.c +++ b/openair2/LAYER2/nr_rlc/tests/test.c @@ -10,6 +10,10 @@ #include #include +#ifndef _STANDALONE_TESTING_ +#include "common/utils/LOG/log.h" +#endif + /* * GNB_AM * @@ -223,6 +227,10 @@ int test_main(void) int gnb_pdu_size = 1000; int ue_pdu_size = 1000; +#ifndef _STANDALONE_TESTING_ + logInit(); +#endif + printf("TEST: start\n"); sdu = malloc(16001); diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c index 8f269a5cd0..942ec698c3 100644 --- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c @@ -346,7 +346,7 @@ static bool is_my_dci(NR_UE_MAC_INST_t *mac, nfapi_nr_dl_dci_pdu_t *received_pdu if (get_softmodem_params()->sa) { if (mac->state == UE_NOT_SYNC) return false; - if (received_pdu->RNTI == 0xFFFF && mac->scc_SIB) + if (received_pdu->RNTI == 0xFFFF && mac->phy_config_request_sent) return false; if (received_pdu->RNTI != mac->crnti && mac->ra.ra_state == RA_SUCCEEDED) return false; @@ -742,19 +742,17 @@ void check_and_process_dci(nfapi_nr_dl_tti_request_t *dl_tti_request, int slots_per_frame = 20; //30 kHZ subcarrier spacing int slot_ahead = 2; // TODO: Make this dynamic - if (mac->scc || mac->scc_SIB) { - if (is_nr_UL_slot(mac->scc ? mac->scc->tdd_UL_DL_ConfigurationCommon : mac->scc_SIB->tdd_UL_DL_ConfigurationCommon, - (slot + slot_ahead) % slots_per_frame, - mac->frame_type) - && mac->ra.ra_state != RA_SUCCEEDED) { - // If we filled dl_info AFTER we got the slot indication, we want to check if we should fill tx_req: - nr_uplink_indication_t ul_info = { + if (is_nr_UL_slot(mac->tdd_UL_DL_ConfigurationCommon, + (slot + slot_ahead) % slots_per_frame, + mac->frame_type) + && mac->ra.ra_state != RA_SUCCEEDED) { + // If we filled dl_info AFTER we got the slot indication, we want to check if we should fill tx_req: + nr_uplink_indication_t ul_info = { .frame_rx = frame, .slot_rx = slot, .slot_tx = (slot + slot_ahead) % slots_per_frame, .frame_tx = (ul_info.slot_rx + slot_ahead >= slots_per_frame) ? ul_info.frame_rx + 1 : ul_info.frame_rx}; - nr_ue_ul_scheduler(&ul_info); - } + nr_ue_ul_scheduler(&ul_info); } } @@ -1133,10 +1131,7 @@ int nr_ue_ul_indication(nr_uplink_indication_t *ul_info) LOG_T(NR_MAC, "In %s():%d not calling scheduler mac->ra.ra_state = %d\n", __FUNCTION__, __LINE__, mac->ra.ra_state); - NR_TDD_UL_DL_ConfigCommon_t *tdd_UL_DL_ConfigurationCommon = - mac->scc != NULL ? mac->scc->tdd_UL_DL_ConfigurationCommon - : (mac->scc_SIB ? mac->scc_SIB->tdd_UL_DL_ConfigurationCommon : NULL); - if (mac->phy_config_request_sent && is_nr_UL_slot(tdd_UL_DL_ConfigurationCommon, ul_info->slot_tx, mac->frame_type)) + if (mac->phy_config_request_sent && is_nr_UL_slot(mac->tdd_UL_DL_ConfigurationCommon, ul_info->slot_tx, mac->frame_type)) nr_ue_ul_scheduler(ul_info); pthread_mutex_unlock(&mac_IF_mutex); @@ -1251,8 +1246,8 @@ int nr_ue_dl_indication(nr_downlink_indication_t *dl_info) return ret_mask; } -nr_ue_if_module_t *nr_ue_if_module_init(uint32_t module_id){ - +nr_ue_if_module_t *nr_ue_if_module_init(uint32_t module_id) +{ if (nr_ue_if_module_inst[module_id] == NULL) { nr_ue_if_module_inst[module_id] = (nr_ue_if_module_t *)malloc(sizeof(nr_ue_if_module_t)); memset((void*)nr_ue_if_module_inst[module_id],0,sizeof(nr_ue_if_module_t)); diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index 892c48a734..bf9861ecfb 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -120,55 +120,6 @@ nr_rrc_ue_generate_rrcReestablishmentComplete( mui_t nr_rrc_mui=0; -static Rrc_State_NR_t nr_rrc_get_state (module_id_t ue_mod_idP) { - return NR_UE_rrc_inst[ue_mod_idP].nrRrcState; -} - - -static Rrc_Sub_State_NR_t nr_rrc_get_sub_state (module_id_t ue_mod_idP) { - return NR_UE_rrc_inst[ue_mod_idP].nrRrcSubState; -} - -static int nr_rrc_set_state (module_id_t ue_mod_idP, Rrc_State_NR_t state) { - AssertFatal ((RRC_STATE_FIRST_NR <= state) && (state <= RRC_STATE_LAST_NR), - "Invalid state %d!\n", state); - - if (NR_UE_rrc_inst[ue_mod_idP].nrRrcState != state) { - NR_UE_rrc_inst[ue_mod_idP].nrRrcState = state; - return (1); - } - - return (0); -} - -static int nr_rrc_set_sub_state( module_id_t ue_mod_idP, Rrc_Sub_State_NR_t subState ) { - if (get_softmodem_params()->sa) { - switch (NR_UE_rrc_inst[ue_mod_idP].nrRrcState) { - case RRC_STATE_INACTIVE_NR: - AssertFatal ((RRC_SUB_STATE_INACTIVE_FIRST_NR <= subState) && (subState <= RRC_SUB_STATE_INACTIVE_LAST_NR), - "Invalid nr sub state %d for state %d!\n", subState, NR_UE_rrc_inst[ue_mod_idP].nrRrcState); - break; - - case RRC_STATE_IDLE_NR: - AssertFatal ((RRC_SUB_STATE_IDLE_FIRST_NR <= subState) && (subState <= RRC_SUB_STATE_IDLE_LAST_NR), - "Invalid nr sub state %d for state %d!\n", subState, NR_UE_rrc_inst[ue_mod_idP].nrRrcState); - break; - - case RRC_STATE_CONNECTED_NR: - AssertFatal ((RRC_SUB_STATE_CONNECTED_FIRST_NR <= subState) && (subState <= RRC_SUB_STATE_CONNECTED_LAST_NR), - "Invalid nr sub state %d for state %d!\n", subState, NR_UE_rrc_inst[ue_mod_idP].nrRrcState); - break; - } - } - - if (NR_UE_rrc_inst[ue_mod_idP].nrRrcSubState != subState) { - NR_UE_rrc_inst[ue_mod_idP].nrRrcSubState = subState; - return (1); - } - - return (0); -} - static void nr_rrc_addmod_srbs(int rnti, const NR_SRB_ToAddModList_t *srb_list, const struct NR_CellGroupConfig__rlc_BearerToAddModList *bearer_list) @@ -727,7 +678,6 @@ int nr_decode_SI(const module_id_t module_id, const uint8_t gNB_index, NR_System default: break; } - nr_rrc_set_sub_state(module_id, RRC_SUB_STATE_IDLE_SIB_COMPLETE_NR); } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_UE_DECODE_SI, VCD_FUNCTION_OUT); return 0; @@ -800,11 +750,10 @@ static int8_t nr_rrc_ue_decode_NR_BCCH_DL_SCH_Message(module_id_t module_id, const uint8_t rsrp) { NR_BCCH_DL_SCH_Message_t *bcch_message = NULL; - NR_UE_RRC_SI_INFO *SI_info = &NR_UE_rrc_inst[module_id].SInfo[gNB_index]; + NR_UE_RRC_INST_t *rrc = &NR_UE_rrc_inst[module_id]; + NR_UE_RRC_SI_INFO *SI_info = &rrc->SInfo[gNB_index]; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_BCCH, VCD_FUNCTION_IN); - nr_rrc_set_sub_state(module_id, RRC_SUB_STATE_IDLE_RECEIVING_SIB_NR); - asn_dec_rval_t dec_rval = uper_decode_complete(NULL, &asn_DEF_NR_BCCH_DL_SCH_Message, (void **)&bcch_message, @@ -838,17 +787,16 @@ static int8_t nr_rrc_ue_decode_NR_BCCH_DL_SCH_Message(module_id_t module_id, LOG_A(NR_RRC, "SIB1 decoded\n"); SI_info->sib1_timer = 0; // FIXME: improve condition for the RA trigger - if(nr_rrc_get_state(module_id) <= RRC_STATE_IDLE_NR) { - NR_UE_rrc_inst[module_id].ra_trigger = INITIAL_ACCESS_FROM_RRC_IDLE; + if(rrc->nrRrcState == RRC_STATE_IDLE_NR) { + rrc->ra_trigger = INITIAL_ACCESS_FROM_RRC_IDLE; LOG_D(PHY,"Setting state to RRC_STATE_IDLE_NR\n"); - nr_rrc_set_state(module_id, RRC_STATE_IDLE_NR); } // configure default SI nr_rrc_configure_default_SI(SI_info, sib1); // configure timers and constant - nr_rrc_set_sib1_timers_and_constants(&NR_UE_rrc_inst[module_id].timers_and_constants, sib1); + nr_rrc_set_sib1_timers_and_constants(&rrc->timers_and_constants, sib1); // take ServingCellConfigCommon and configure L1/L2 - NR_UE_rrc_inst[module_id].servingCellConfigCommonSIB = sib1->servingCellConfigCommon; + rrc->servingCellConfigCommonSIB = sib1->servingCellConfigCommon; nr_rrc_mac_config_req_sib1(module_id, 0, sib1->si_SchedulingInfo, sib1->servingCellConfigCommon); nr_rrc_ue_generate_ra_msg(module_id, gNB_index); break; @@ -863,14 +811,6 @@ static int8_t nr_rrc_ue_decode_NR_BCCH_DL_SCH_Message(module_id_t module_id, break; } } - - if (nr_rrc_get_sub_state(module_id) == RRC_SUB_STATE_IDLE_SIB_COMPLETE_NR) { - //if ( (NR_UE_rrc_inst[ctxt_pP->module_id].initialNasMsg.data != NULL) || (!get_softmodem_params()->sa)) { - nr_rrc_ue_generate_RRCSetupRequest(module_id, 0); - nr_rrc_set_sub_state(module_id, RRC_SUB_STATE_IDLE_CONNECTING_NR); - //} - } - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_BCCH, VCD_FUNCTION_OUT ); return 0; } @@ -1063,14 +1003,15 @@ static void rrc_ue_generate_RRCSetupComplete( nr_pdcp_data_req_srb(ctxt_pP->rntiMaybeUEid, DCCH, nr_rrc_mui++, size, buffer, deliver_pdu_srb_rlc, NULL); } -int8_t nr_rrc_ue_decode_ccch( const protocol_ctxt_t *const ctxt_pP, const NR_SRB_INFO *const Srb_info, const uint8_t gNB_index ){ - +int8_t nr_rrc_ue_decode_ccch( const protocol_ctxt_t *const ctxt_pP, const NR_SRB_INFO *const Srb_info, const uint8_t gNB_index ) +{ + NR_UE_RRC_INST_t *rrc = &NR_UE_rrc_inst[ctxt_pP->module_id]; NR_DL_CCCH_Message_t *dl_ccch_msg=NULL; asn_dec_rval_t dec_rval; int rval=0; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_CCCH, VCD_FUNCTION_IN); LOG_D(RRC,"[NR UE%d] Decoding DL-CCCH message (%d bytes), State %d\n",ctxt_pP->module_id,Srb_info->Rx_buffer.payload_size, - NR_UE_rrc_inst[ctxt_pP->module_id].nrRrcState); + rrc->nrRrcState); dec_rval = uper_decode(NULL, &asn_DEF_NR_DL_CCCH_Message, (void **)&dl_ccch_msg, @@ -1109,14 +1050,13 @@ int8_t nr_rrc_ue_decode_ccch( const protocol_ctxt_t *const ctxt_pP, const NR_SRB // Get configuration // Release T300 timer - NR_UE_rrc_inst[ctxt_pP->module_id].timers_and_constants.T300_active = 0; + rrc->timers_and_constants.T300_active = 0; nr_rrc_ue_process_masterCellGroup(ctxt_pP, gNB_index, &dl_ccch_msg->message.choice.c1->choice.rrcSetup->criticalExtensions.choice.rrcSetup->masterCellGroup, NULL); nr_rrc_ue_process_RadioBearerConfig(ctxt_pP, gNB_index, &dl_ccch_msg->message.choice.c1->choice.rrcSetup->criticalExtensions.choice.rrcSetup->radioBearerConfig); - nr_rrc_set_state(ctxt_pP->module_id, RRC_STATE_CONNECTED_NR); - nr_rrc_set_sub_state(ctxt_pP->module_id, RRC_SUB_STATE_CONNECTED_NR); - NR_UE_rrc_inst[ctxt_pP->module_id].rnti = ctxt_pP->rntiMaybeUEid; - rrc_ue_generate_RRCSetupComplete(ctxt_pP, gNB_index, dl_ccch_msg->message.choice.c1->choice.rrcSetup->rrc_TransactionIdentifier, NR_UE_rrc_inst[ctxt_pP->module_id].selected_plmn_identity); + rrc->nrRrcState = RRC_STATE_CONNECTED_NR; + rrc->rnti = ctxt_pP->rntiMaybeUEid; + rrc_ue_generate_RRCSetupComplete(ctxt_pP, gNB_index, dl_ccch_msg->message.choice.c1->choice.rrcSetup->rrc_TransactionIdentifier, rrc->selected_plmn_identity); rval = 0; break; @@ -2029,12 +1969,13 @@ void *rrc_nrue_task(void *args_p) handle_rlf_sync(tac, sync_msg); break; - case NRRRC_SLOT_PROCESS: - LOG_D(NR_RRC, "[UE %d] Received %s: frame %d slot %d\n", - ue_mod_id, ITTI_MSG_NAME (msg_p), NRRRC_SLOT_PROCESS (msg_p).frame, NRRRC_SLOT_PROCESS (msg_p).slot); + case NRRRC_FRAME_PROCESS: + LOG_D(NR_RRC, "[UE %d] Received %s: frame %d\n", + ue_mod_id, ITTI_MSG_NAME (msg_p), NRRRC_FRAME_PROCESS (msg_p).frame); + // increase the timers every 10ms (every new frame) NR_UE_Timers_Constants_t *timers = &NR_UE_rrc_inst[ue_mod_id].timers_and_constants; nr_rrc_handle_timers(timers); - NR_UE_RRC_SI_INFO *SInfo = &NR_UE_rrc_inst[ue_mod_id].SInfo[NRRRC_SLOT_PROCESS (msg_p).gnb_id]; + NR_UE_RRC_SI_INFO *SInfo = &NR_UE_rrc_inst[ue_mod_id].SInfo[NRRRC_FRAME_PROCESS (msg_p).gnb_id]; nr_rrc_SI_timers(SInfo); break; @@ -2152,7 +2093,7 @@ void *rrc_nrue_task(void *args_p) LOG_E(NR_RRC, "[UE %d] Received unexpected message %s\n", ue_mod_id, ITTI_MSG_NAME (msg_p)); break; } - LOG_D(NR_RRC, "[UE %d] RRC Status %d\n", ue_mod_id, nr_rrc_get_state(ue_mod_id)); + LOG_D(NR_RRC, "[UE %d] RRC Status %d\n", ue_mod_id, NR_UE_rrc_inst[ue_mod_id].nrRrcState); result = itti_free(ITTI_MSG_ORIGIN_ID(msg_p), msg_p); AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result); msg_p = NULL; @@ -2528,13 +2469,12 @@ void process_lte_nsa_msg(nsa_msg_t *msg, int msg_len) } } -void nr_ue_rrc_timer_trigger(int module_id, int frame, int slot, int gnb_id) +void nr_ue_rrc_timer_trigger(int module_id, int frame, int gnb_id) { MessageDef *message_p; - message_p = itti_alloc_new_message(TASK_RRC_NRUE, 0, NRRRC_SLOT_PROCESS); - NRRRC_SLOT_PROCESS(message_p).frame = frame; - NRRRC_SLOT_PROCESS(message_p).slot = slot; - NRRRC_SLOT_PROCESS(message_p).gnb_id = gnb_id; - LOG_D(NR_RRC, "RRC timer trigger: frame %d slot %d \n", frame, slot); + message_p = itti_alloc_new_message(TASK_RRC_NRUE, 0, NRRRC_FRAME_PROCESS); + NRRRC_FRAME_PROCESS(message_p).frame = frame; + NRRRC_FRAME_PROCESS(message_p).gnb_id = gnb_id; + LOG_D(NR_RRC, "RRC timer trigger: frame %d\n", frame); itti_send_msg_to_task(TASK_RRC_NRUE, GNB_MODULE_ID_TO_INSTANCE(module_id), message_p); } diff --git a/openair2/RRC/NR_UE/rrc_defs.h b/openair2/RRC/NR_UE/rrc_defs.h index 53eaf69c4b..89dac531a5 100644 --- a/openair2/RRC/NR_UE/rrc_defs.h +++ b/openair2/RRC/NR_UE/rrc_defs.h @@ -80,7 +80,7 @@ typedef struct OAI_NR_UECapability_s { } OAI_NR_UECapability_t; typedef enum Rrc_State_NR_e { - RRC_STATE_IDLE_NR=0, + RRC_STATE_IDLE_NR = 0, RRC_STATE_INACTIVE_NR, RRC_STATE_CONNECTED_NR, @@ -88,27 +88,6 @@ typedef enum Rrc_State_NR_e { RRC_STATE_LAST_NR = RRC_STATE_CONNECTED_NR, } Rrc_State_NR_t; -typedef enum Rrc_Sub_State_NR_e { - RRC_SUB_STATE_INACTIVE_NR=0, - - RRC_SUB_STATE_IDLE_SEARCHING_NR, - RRC_SUB_STATE_IDLE_RECEIVING_SIB_NR, - RRC_SUB_STATE_IDLE_SIB_COMPLETE_NR, - RRC_SUB_STATE_IDLE_CONNECTING_NR, - RRC_SUB_STATE_IDLE_NR, - - RRC_SUB_STATE_CONNECTED_NR, - - RRC_SUB_STATE_INACTIVE_FIRST_NR = RRC_SUB_STATE_INACTIVE_NR, - RRC_SUB_STATE_INACTIVE_LAST_NR = RRC_SUB_STATE_INACTIVE_NR, - - RRC_SUB_STATE_IDLE_FIRST_NR = RRC_SUB_STATE_IDLE_SEARCHING_NR, - RRC_SUB_STATE_IDLE_LAST_NR = RRC_SUB_STATE_IDLE_NR, - - RRC_SUB_STATE_CONNECTED_FIRST_NR = RRC_SUB_STATE_CONNECTED_NR, - RRC_SUB_STATE_CONNECTED_LAST_NR = RRC_SUB_STATE_CONNECTED_NR, -} Rrc_Sub_State_NR_t; - typedef enum requested_SI_List_e { SIB2 = 1, SIB3 = 2, @@ -252,7 +231,6 @@ typedef struct NR_UE_RRC_INST_s { long selected_plmn_identity; Rrc_State_NR_t nrRrcState; - Rrc_Sub_State_NR_t nrRrcSubState; as_nas_info_t initialNasMsg; } NR_UE_RRC_INST_t; diff --git a/openair2/RRC/NR_UE/rrc_proto.h b/openair2/RRC/NR_UE/rrc_proto.h index d4bfe0e52d..55e025e0f1 100644 --- a/openair2/RRC/NR_UE/rrc_proto.h +++ b/openair2/RRC/NR_UE/rrc_proto.h @@ -161,7 +161,7 @@ int get_from_lte_ue_fd(); void nr_rrc_SI_timers(NR_UE_RRC_SI_INFO *SInfo); -void nr_ue_rrc_timer_trigger(int module_id, int frame, int slot, int gnb_id); +void nr_ue_rrc_timer_trigger(int module_id, int frame, int gnb_id); void configure_spcell(NR_UE_RRC_INST_t *rrc, NR_SpCellConfig_t *spcell_config); void reset_rlf_timers_and_constants(NR_UE_Timers_Constants_t *tac);