diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6e8758cea3..5d9ca49a4a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -709,14 +709,15 @@ target_link_libraries(SCHED_LIB PRIVATE asn1_lte_rrc_hdrs)
set(SCHED_NR_SRC
${OPENAIR1_DIR}/SCHED_NR/phy_procedures_nr_gNB.c
${OPENAIR1_DIR}/SCHED_NR/nr_prach_procedures.c
+ ${OPENAIR1_DIR}/SCHED_NR/nr_ru_procedures.c
${OPENAIR1_DIR}/SCHED_NR/phy_frame_config_nr.c
)
add_library(SCHED_NR_LIB ${SCHED_NR_SRC})
target_link_libraries(SCHED_NR_LIB PRIVATE asn1_nr_rrc_hdrs UTIL)
+target_link_libraries(SCHED_NR_LIB PRIVATE NFAPI_LIB) # some FAPI messages pack "subPDUs"
set(SCHED_SRC_RU
${OPENAIR1_DIR}/SCHED/ru_procedures.c
- ${OPENAIR1_DIR}/SCHED_NR/nr_ru_procedures.c
${OPENAIR1_DIR}/SCHED/prach_procedures.c
)
add_library(SCHED_RU_LIB ${SCHED_SRC_RU})
@@ -752,6 +753,7 @@ set(NFAPI_SRC
add_library(NFAPI_LIB ${NFAPI_SRC})
target_link_libraries(NFAPI_LIB PUBLIC nfapi_common)
target_link_libraries(NFAPI_LIB PUBLIC nr_fapi_p5 nr_fapi_p7)
+target_link_libraries(NFAPI_LIB PRIVATE z)
if(OAI_WLS)
target_compile_definitions(NFAPI_LIB PRIVATE ENABLE_WLS)
@@ -877,6 +879,10 @@ set(PHY_SRC
${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/pilots_mbsfn.c
${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/dlsch_coding.c
${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/dlsch_modulation.c
+ ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/ulsch_demodulation.c
+ ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c
+ ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/freq_equalization.c
+ ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/lte_adjust_sync_eNB.c
${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/dci_tools.c
${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/pbch.c
${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/dci.c
@@ -893,22 +899,22 @@ set(PHY_SRC
)
set(PHY_SRC_RU
- ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/if4_tools.c
+ ${OPENAIR1_DIR}/PHY/if4_tools.c
${OPENAIR1_DIR}/PHY/LTE_UE_TRANSPORT/drs_modulation.c
- ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/ulsch_demodulation.c
- ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c
- ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/lte_adjust_sync_eNB.c
- ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/freq_equalization.c
${OPENAIR1_DIR}/PHY/MODULATION/slot_fep_ul.c
- ${OPENAIR1_DIR}/PHY/MODULATION/slot_fep_nr.c
${OPENAIR1_DIR}/PHY/MODULATION/ul_7_5_kHz.c
${OPENAIR1_DIR}/PHY/MODULATION/gen_75KHz.cpp
${OPENAIR1_DIR}/PHY/MODULATION/beamforming.c
${OPENAIR1_DIR}/PHY/MODULATION/compute_bf_weights.c
${OPENAIR1_DIR}/PHY/INIT/lte_init_ru.c
- ${OPENAIR1_DIR}/PHY/INIT/nr_init_ru.c
${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/prach.c
+ )
+set(NR_PHY_SRC_RU
+ ${OPENAIR1_DIR}/PHY/MODULATION/nr_beamforming.c
+ ${OPENAIR1_DIR}/PHY/MODULATION/slot_fep_nr.c
+ ${OPENAIR1_DIR}/PHY/INIT/nr_init_ru.c
+ ${OPENAIR1_DIR}/PHY/if4_tools.c
)
set(PHY_SRC_UE
@@ -1068,7 +1074,7 @@ add_library(PHY_NR_COMMON ${PHY_NR_SRC_COMMON})
target_link_libraries(PHY_NR_COMMON PUBLIC UTIL)
add_library(PHY_NR ${PHY_NR_SRC})
-target_link_libraries(PHY_NR nr_phy_common nr_common nr_fapi_p5 polar smallblock)
+target_link_libraries(PHY_NR nr_phy_common nr_common nr_fapi_p5 polar smallblock ds)
add_library(PHY_NR_NO_AVX_256 ${PHY_NR_SRC})
target_link_libraries(PHY_NR_NO_AVX_256 nr_phy_common nr_common)
@@ -1080,6 +1086,8 @@ target_link_libraries(PHY_NR_UE PRIVATE asn1_nr_rrc_hdrs nr_phy_common nr_common
add_library(PHY_RU ${PHY_SRC_RU})
target_link_libraries(PHY_RU PRIVATE asn1_lte_rrc_hdrs UTIL)
+add_library(NR_PHY_RU ${NR_PHY_SRC_RU})
+
#Layer 2 library
#####################
set(MAC_DIR ${OPENAIR2_DIR}/LAYER2/MAC)
@@ -1742,7 +1750,7 @@ target_link_libraries(lte-softmodem PRIVATE
lte_rrc nr_rrc s1ap m2ap x2ap m3ap GTPV1U SECURITY UTIL SCTP_CLIENT MME_APP SCHED_LIB SCHED_RU_LIB
PHY_COMMON PHY PHY_RU L2 L2_LTE NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB MISC_NFAPI_LTE_LIB
${NAS_UE_LIB} ITTI SIMU radio_common softmodem_common
- -Wl,--end-group z dl)
+ -Wl,--end-group dl)
target_link_libraries(lte-softmodem PRIVATE pthread m CONFIG_LIB rt)
target_link_libraries(lte-softmodem PRIVATE ${T_LIB})
@@ -1757,13 +1765,17 @@ add_executable(oairu
${OPENAIR_DIR}/executables/lte-ru.c
${OPENAIR_DIR}/executables/ru_control.c
${OPENAIR_DIR}/openair1/SCHED/phy_procedures_lte_common.c
+ ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c
+ ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/freq_equalization.c
+ ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/ulsch_demodulation.c
+ ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/lte_adjust_sync_eNB.c
${OPENAIR_DIR}/executables/main_ru.c
${OPENAIR_DIR}/common/utils/lte/prach_utils.c
)
target_link_libraries(oairu PRIVATE
-Wl,--start-group
SCHED_RU_LIB PHY_COMMON PHY_RU UTIL radio_common softmodem_common
- -Wl,--end-group z dl)
+ -Wl,--end-group dl)
target_link_libraries(oairu PRIVATE pthread m CONFIG_LIB rt ${T_LIB})
target_link_libraries(oairu PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
@@ -1792,7 +1804,7 @@ target_link_libraries(lte-uesoftmodem PRIVATE
SECURITY UTIL SCTP_CLIENT MME_APP SCHED_RU_LIB SCHED_UE_LIB PHY_COMMON
PHY_UE PHY_RU L2_UE L2_LTE SIMU NFAPI_LIB NFAPI_PNF_LIB NFAPI_USER_LIB MISC_NFAPI_LTE_LIB
${NAS_UE_LIB} ITTI radio_common softmodem_common
- -Wl,--end-group z dl)
+ -Wl,--end-group dl)
target_link_libraries(lte-uesoftmodem PRIVATE pthread m CONFIG_LIB rt)
target_link_libraries(lte-uesoftmodem PRIVATE ${T_LIB})
@@ -1808,11 +1820,12 @@ add_executable(nr-oru
${OPENAIR_DIR}/openair1/PHY/INIT/nr_parms.c
${OPENAIR_DIR}/openair1/SCHED_NR/phy_frame_config_nr.c
${OPENAIR_DIR}/openair1/SCHED_NR/nr_prach_procedures.c
+ ${OPENAIR_DIR}/openair1/SCHED_NR/nr_ru_procedures.c
${OPENAIR_DIR}/openair1/SCHED/phy_procedures_lte_common.c
${OPENAIR_DIR}/executables/main_nr_ru.c
)
target_link_libraries(nr-oru PRIVATE
- UTIL SCHED_RU_LIB PHY_COMMON PHY_RU PHY_NR shlib_loader z dl
+ UTIL NR_PHY_RU PHY_NR shlib_loader dl
radio_common softmodem_common)
target_link_libraries(nr-oru PRIVATE pthread m CONFIG_LIB rt ${T_LIB} utils
barrier actor)
@@ -1836,12 +1849,12 @@ add_executable(nr-softmodem
target_link_libraries(nr-softmodem PRIVATE
-Wl,--start-group
- UTIL SCTP_CLIENT SCHED_LIB SCHED_RU_LIB SCHED_NR_LIB PHY_NR PHY PHY_COMMON PHY_NR_COMMON PHY_RU GTPV1U SECURITY
- ITTI ${NAS_UE_LIB} lte_rrc nr_rrc
+ UTIL SCTP_CLIENT SCHED_LIB SCHED_NR_LIB PHY_NR PHY PHY_NR_COMMON NR_PHY_RU GTPV1U SECURITY
+ ITTI ${NAS_UE_LIB} nr_rrc
ngap s1ap L2_LTE_NR L2_NR MAC_NR_COMMON NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB SIMU
x2ap f1ap m2ap m3ap e1ap radio_common
time_management softmodem_common
- -Wl,--end-group z dl)
+ -Wl,--end-group dl)
target_link_libraries(nr-softmodem PRIVATE pthread m CONFIG_LIB rt)
target_link_libraries(nr-softmodem PRIVATE ${T_LIB})
@@ -1881,7 +1894,7 @@ target_link_libraries(nr-cuup PRIVATE
GTPV1U e1ap f1ap
time_management softmodem_common
alg
- z dl pthread ${T_LIB})
+ dl pthread ${T_LIB})
target_link_libraries(nr-cuup PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs)
if(E2_AGENT)
target_link_libraries(nr-cuup PRIVATE e2_agent e2_agent_arg e2_ran_func_cuup)
@@ -1905,11 +1918,11 @@ add_executable(nr-uesoftmodem
target_link_libraries(nr-uesoftmodem PRIVATE
-Wl,--start-group
- nr_rrc SECURITY UTIL SCHED_RU_LIB SCHED_NR_UE_LIB
- PHY_COMMON PHY_NR_COMMON PHY_NR_UE NR_L2_UE MAC_NR_COMMON NFAPI_LIB
+ nr_rrc SECURITY UTIL SCHED_NR_UE_LIB
+ PHY_NR_COMMON PHY_NR_UE NR_L2_UE MAC_NR_COMMON NFAPI_LIB
ITTI SIMU radio_common
time_management softmodem_common
- -Wl,--end-group z dl)
+ -Wl,--end-group dl)
target_link_libraries(nr-uesoftmodem PRIVATE pthread m CONFIG_LIB rt nr_ue_phy_meas)
target_link_libraries(nr-uesoftmodem PRIVATE ${T_LIB})
@@ -1983,14 +1996,14 @@ target_link_libraries(physim_common PRIVATE UTIL)
add_executable(nr_dlschsim ${OPENAIR1_DIR}/SIMULATION/NR_PHY/dlschsim.c)
target_link_libraries(nr_dlschsim PRIVATE
- -Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB CONFIG_LIB MAC_NR_COMMON -Wl,--end-group
+ -Wl,--start-group UTIL SIMU PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB CONFIG_LIB MAC_NR_COMMON -Wl,--end-group
m pthread ${T_LIB} ITTI dl physim_common
)
target_link_libraries(nr_dlschsim PRIVATE asn1_nr_rrc_hdrs)
add_executable(nr_pbchsim ${OPENAIR1_DIR}/SIMULATION/NR_PHY/pbchsim.c)
target_link_libraries(nr_pbchsim PRIVATE
- -Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB CONFIG_LIB MAC_NR_COMMON -Wl,--end-group
+ -Wl,--start-group UTIL SIMU PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB CONFIG_LIB MAC_NR_COMMON -Wl,--end-group
m pthread ${T_LIB} ITTI dl physim_common
)
target_link_libraries(nr_pbchsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
@@ -2000,14 +2013,14 @@ add_executable(nr_psbchsim
${NFAPI_USER_DIR}/nfapi.c
)
target_link_libraries(nr_psbchsim PRIVATE
- -Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_UE_NR MAC_NR_COMMON CONFIG_LIB -Wl,--end-group
+ -Wl,--start-group UTIL SIMU PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_UE_NR MAC_NR_COMMON CONFIG_LIB -Wl,--end-group
m pthread ${T_LIB} ITTI dl physim_common softmodem_common
)
target_link_libraries(nr_psbchsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
add_executable(nr_pucchsim ${OPENAIR1_DIR}/SIMULATION/NR_PHY/pucchsim.c)
target_link_libraries(nr_pucchsim PRIVATE
- -Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB CONFIG_LIB MAC_NR_COMMON -Wl,--end-group
+ -Wl,--start-group UTIL SIMU PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB CONFIG_LIB MAC_NR_COMMON -Wl,--end-group
m pthread ${T_LIB} ITTI dl physim_common
)
target_link_libraries(nr_pucchsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
@@ -2019,15 +2032,15 @@ add_executable(nr_dlsim
${PHY_INTERFACE_DIR}/queue_t.c
)
target_link_libraries(nr_dlsim PRIVATE
- -Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_UE_NR MAC_NR_COMMON CONFIG_LIB L2_NR -Wl,--end-group
- m pthread ${T_LIB} ITTI dl nr_ue_phy_meas physim_common
+ -Wl,--start-group UTIL SIMU PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_UE_NR MAC_NR_COMMON CONFIG_LIB L2_NR -Wl,--end-group
+ m pthread ${T_LIB} ITTI dl nr_ue_phy_meas physim_common NR_L2_UE
softmodem_common
)
target_link_libraries(nr_dlsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
add_executable(nr_prachsim ${OPENAIR1_DIR}/SIMULATION/NR_PHY/prachsim.c)
target_link_libraries(nr_prachsim PRIVATE
- -Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_RU PHY_NR_UE MAC_NR_COMMON SCHED_NR_LIB CONFIG_LIB -Wl,--end-group
+ -Wl,--start-group UTIL SIMU PHY_NR_COMMON PHY_NR NR_PHY_RU PHY_NR_UE MAC_NR_COMMON SCHED_NR_LIB CONFIG_LIB -Wl,--end-group
m pthread ${T_LIB} ITTI dl physim_common)
target_link_libraries(nr_prachsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
@@ -2035,7 +2048,7 @@ add_executable(nr_ulschsim
${OPENAIR1_DIR}/SIMULATION/NR_PHY/ulschsim.c
)
target_link_libraries(nr_ulschsim PRIVATE
- -Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB CONFIG_LIB MAC_NR_COMMON -Wl,--end-group
+ -Wl,--start-group UTIL SIMU PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB CONFIG_LIB MAC_NR_COMMON -Wl,--end-group
m pthread ${T_LIB} ITTI dl physim_common
)
target_link_libraries(nr_ulschsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
@@ -2048,8 +2061,8 @@ add_executable(nr_ulsim
)
target_link_libraries(nr_ulsim PRIVATE
- -Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_UE_NR MAC_NR_COMMON CONFIG_LIB L2_NR -Wl,--end-group
- m pthread ${T_LIB} ITTI dl nr_ue_phy_meas physim_common softmodem_common
+ -Wl,--start-group UTIL SIMU PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_UE_NR MAC_NR_COMMON CONFIG_LIB L2_NR -Wl,--end-group
+ m pthread ${T_LIB} ITTI dl nr_ue_phy_meas physim_common softmodem_common NR_L2_UE
)
target_link_libraries(nr_ulsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
@@ -2059,7 +2072,7 @@ add_executable(nr_srssim
)
target_link_libraries(nr_srssim PRIVATE
- -Wl,--start-group UTIL SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_UE_NR MAC_NR_COMMON -Wl,--end-group
+ -Wl,--start-group UTIL SIMU PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_UE_NR MAC_NR_COMMON -Wl,--end-group
m pthread ITTI dl nr_ue_phy_meas physim_common softmodem_common
)
@@ -2128,7 +2141,7 @@ if (${T_TRACER})
SECURITY SCHED_LIB SCHED_NR_LIB SCHED_RU_LIB SCHED_UE_LIB SCHED_NR_UE_LIB
NFAPI_LIB NFAPI_PNF_LIB NFAPI_VNF_LIB NFAPI_USER_LIB
MISC_NFAPI_LTE_LIB
- PHY_COMMON PHY PHY_UE PHY_NR PHY_NR_COMMON PHY_NR_UE PHY_RU
+ PHY_COMMON PHY PHY_UE PHY_NR PHY_NR_COMMON PHY_NR_UE PHY_RU NR_PHY_RU
L2 L2_LTE L2_NR L2_LTE_NR L2_UE NR_L2_UE MAC_NR_COMMON MAC_UE_NR ngap
GTPV1U SCTP_CLIENT MME_APP LIB_NAS_UE SIMU
dfts config_internals nr_common crc_byte)
diff --git a/ci-scripts/Jenkinsfile-GitLab-Container b/ci-scripts/Jenkinsfile-GitLab-Container
index d75b1888d4..721c89b77f 100644
--- a/ci-scripts/Jenkinsfile-GitLab-Container
+++ b/ci-scripts/Jenkinsfile-GitLab-Container
@@ -219,28 +219,6 @@ pipeline {
}
}
}
- stage ("cppcheck") {
- steps {
- script {
- triggerSlaveJob ('RAN-cppcheck', 'cppcheck')
- }
- }
- post {
- always {
- script {
- // Using a unique variable name for each test stage to avoid overwriting on a global variable
- // due to parallel-time concurrency
- cppcheckStatus = finalizeSlaveJob('RAN-cppcheck')
- }
- }
- failure {
- script {
- currentBuild.result = 'FAILURE'
- failingStages += cppcheckStatus
- }
- }
- }
- }
stage ("ARM-Cross-Compile") {
steps {
script {
diff --git a/ci-scripts/args_parse.py b/ci-scripts/args_parse.py
index 6206c67d69..16e23113ab 100644
--- a/ci-scripts/args_parse.py
+++ b/ci-scripts/args_parse.py
@@ -22,7 +22,7 @@ import constants as CONST
#-----------------------------------------------------------
-def ArgsParse(argvs,CiTestObj,RAN,HTML,CONTAINERS,HELP,SCA,CLUSTER):
+def ArgsParse(argvs,CiTestObj,RAN,HTML,CONTAINERS,HELP,CLUSTER):
force_local = False
date_fmt = None
@@ -53,7 +53,6 @@ def ArgsParse(argvs,CiTestObj,RAN,HTML,CONTAINERS,HELP,SCA,CLUSTER):
RAN.ranRepository=matchReg.group(1)
HTML.ranRepository=matchReg.group(1)
CONTAINERS.ranRepository=matchReg.group(1)
- SCA.ranRepository=matchReg.group(1)
CLUSTER.ranRepository=matchReg.group(1)
elif re.match(r'^\-\-eNB_AllowMerge=(.+)$|^\-\-ranAllowMerge=(.+)$', myArgv, re.IGNORECASE):
if re.match(r'^\-\-eNB_AllowMerge=(.+)$', myArgv, re.IGNORECASE):
@@ -66,7 +65,6 @@ def ArgsParse(argvs,CiTestObj,RAN,HTML,CONTAINERS,HELP,SCA,CLUSTER):
RAN.ranAllowMerge=True
HTML.ranAllowMerge=True
CONTAINERS.ranAllowMerge=True
- SCA.ranAllowMerge=True
CLUSTER.ranAllowMerge=True
elif re.match(r'^\-\-eNBBranch=(.+)$|^\-\-ranBranch=(.+)$', myArgv, re.IGNORECASE):
if re.match(r'^\-\-eNBBranch=(.+)$', myArgv, re.IGNORECASE):
@@ -77,7 +75,6 @@ def ArgsParse(argvs,CiTestObj,RAN,HTML,CONTAINERS,HELP,SCA,CLUSTER):
RAN.ranBranch=matchReg.group(1)
HTML.ranBranch=matchReg.group(1)
CONTAINERS.ranBranch=matchReg.group(1)
- SCA.ranBranch=matchReg.group(1)
CLUSTER.ranBranch=matchReg.group(1)
elif re.match(r'^\-\-eNBCommitID=(.*)$|^\-\-ranCommitID=(.*)$', myArgv, re.IGNORECASE):
if re.match(r'^\-\-eNBCommitID=(.*)$', myArgv, re.IGNORECASE):
@@ -88,7 +85,6 @@ def ArgsParse(argvs,CiTestObj,RAN,HTML,CONTAINERS,HELP,SCA,CLUSTER):
RAN.ranCommitID=matchReg.group(1)
HTML.ranCommitID=matchReg.group(1)
CONTAINERS.ranCommitID=matchReg.group(1)
- SCA.ranCommitID=matchReg.group(1)
CLUSTER.ranCommitID=matchReg.group(1)
elif re.match(r'^\-\-eNBTargetBranch=(.*)$|^\-\-ranTargetBranch=(.*)$', myArgv, re.IGNORECASE):
if re.match(r'^\-\-eNBTargetBranch=(.*)$', myArgv, re.IGNORECASE):
@@ -99,7 +95,6 @@ def ArgsParse(argvs,CiTestObj,RAN,HTML,CONTAINERS,HELP,SCA,CLUSTER):
RAN.ranTargetBranch=matchReg.group(1)
HTML.ranTargetBranch=matchReg.group(1)
CONTAINERS.ranTargetBranch=matchReg.group(1)
- SCA.ranTargetBranch=matchReg.group(1)
CLUSTER.ranTargetBranch=matchReg.group(1)
elif re.match(r'^\-\-eNBIPAddress=(.+)$|^\-\-eNB[1-2]IPAddress=(.+)$', myArgv, re.IGNORECASE):
print("parameters --eNB*IPAddress ignored")
@@ -112,7 +107,6 @@ def ArgsParse(argvs,CiTestObj,RAN,HTML,CONTAINERS,HELP,SCA,CLUSTER):
matchReg = re.match(r'^\-\-eNBSourceCodePath=(.+)$', myArgv, re.IGNORECASE)
RAN.eNBSourceCodePath=matchReg.group(1)
CONTAINERS.eNBSourceCodePath=matchReg.group(1)
- SCA.eNBSourceCodePath=matchReg.group(1)
CLUSTER.eNBSourceCodePath=matchReg.group(1)
elif re.match(r'^\-\-eNB1SourceCodePath=(.+)$', myArgv, re.IGNORECASE):
print("parameter --eNB1SourceCodePath ignored")
diff --git a/ci-scripts/cls_containerize.py b/ci-scripts/cls_containerize.py
index c7831136e2..461c64d133 100644
--- a/ci-scripts/cls_containerize.py
+++ b/ci-scripts/cls_containerize.py
@@ -184,11 +184,6 @@ class Containerize():
self.services = ''
self.deploymentTag = ''
- self.cli = ''
- self.cliBuildOptions = ''
- self.dockerfileprefix = ''
- self.host = ''
-
self.num_attempts = 1
self.flexricTag = ''
@@ -203,18 +198,7 @@ class Containerize():
cmd = cls_cmd.getConnection(node)
log_files = []
- # Checking the hostname to get adapted on cli and dockerfileprefixes
- cmd.run('hostnamectl')
- result = re.search('Ubuntu|Red Hat', cmd.getBefore())
- self.host = result.group(0)
- if self.host == 'Ubuntu':
- self.cli = 'docker'
- self.dockerfileprefix = '.ubuntu'
- self.cliBuildOptions = ''
- elif self.host == 'Red Hat':
- self.cli = 'sudo podman'
- self.dockerfileprefix = '.rhel9'
- self.cliBuildOptions = '--disable-compression'
+ dockerfileprefix = '.ubuntu'
# we always build the ran-build image with all targets
# Creating a tupple with the imageName, the DockerFile prefix pattern, targetName and sanitized option
@@ -232,23 +216,20 @@ class Containerize():
imageNames.append(('oai-nr-cuup', 'nr-cuup', 'oai-nr-cuup', ''))
imageNames.append(('oai-lte-ue', 'lteUE', 'oai-lte-ue', ''))
imageNames.append(('oai-nr-ue', 'nrUE', 'oai-nr-ue', ''))
- if self.host == 'Red Hat':
- imageNames.append(('oai-physim', 'phySim', 'oai-physim', ''))
- if self.host == 'Ubuntu':
- imageNames.append(('oai-lte-ru', 'lteRU', 'oai-lte-ru', ''))
- # Building again the 5G images with Address Sanitizer
- imageNames.append(('ran-build', 'build', 'ran-build-asan', '--build-arg "BUILD_OPTION=--sanitize"'))
- imageNames.append(('oai-enb', 'eNB', 'oai-enb-asan', '--build-arg "BUILD_OPTION=--sanitize"'))
- imageNames.append(('oai-gnb', 'gNB', 'oai-gnb-asan', '--build-arg "BUILD_OPTION=--sanitize"'))
- imageNames.append(('oai-lte-ue', 'lteUE', 'oai-lte-ue-asan', '--build-arg "BUILD_OPTION=--sanitize"'))
- imageNames.append(('oai-nr-ue', 'nrUE', 'oai-nr-ue-asan', '--build-arg "BUILD_OPTION=--sanitize"'))
- imageNames.append(('oai-nr-cuup', 'nr-cuup', 'oai-nr-cuup-asan', '--build-arg "BUILD_OPTION=--sanitize"'))
- imageNames.append(('ran-build-fhi72', 'build.fhi72', 'ran-build-fhi72', ''))
- imageNames.append(('oai-gnb', 'gNB.fhi72', 'oai-gnb-fhi72', ''))
- imageNames.append(('oai-nr-oru', 'nrORU.fhi72', 'oai-nr-oru', ''))
+ imageNames.append(('oai-lte-ru', 'lteRU', 'oai-lte-ru', ''))
+ # Building again the 5G images with Address Sanitizer
+ imageNames.append(('ran-build', 'build', 'ran-build-asan', '--build-arg "BUILD_OPTION=--sanitize"'))
+ imageNames.append(('oai-enb', 'eNB', 'oai-enb-asan', '--build-arg "BUILD_OPTION=--sanitize"'))
+ imageNames.append(('oai-gnb', 'gNB', 'oai-gnb-asan', '--build-arg "BUILD_OPTION=--sanitize"'))
+ imageNames.append(('oai-lte-ue', 'lteUE', 'oai-lte-ue-asan', '--build-arg "BUILD_OPTION=--sanitize"'))
+ imageNames.append(('oai-nr-ue', 'nrUE', 'oai-nr-ue-asan', '--build-arg "BUILD_OPTION=--sanitize"'))
+ imageNames.append(('oai-nr-cuup', 'nr-cuup', 'oai-nr-cuup-asan', '--build-arg "BUILD_OPTION=--sanitize"'))
+ imageNames.append(('ran-build-fhi72', 'build.fhi72', 'ran-build-fhi72', ''))
+ imageNames.append(('oai-gnb', 'gNB.fhi72', 'oai-gnb-fhi72', ''))
+ imageNames.append(('oai-nr-oru', 'nrORU.fhi72', 'oai-nr-oru', ''))
result = re.search('build_cross_arm64', self.imageKind)
if result is not None:
- self.dockerfileprefix = '.ubuntu.cross-arm64'
+ dockerfileprefix = '.ubuntu.cross-arm64'
result = re.search('native_armv9', self.imageKind)
if result is not None:
imageNames.append(('oai-gnb', 'gNB', 'oai-gnb', ''))
@@ -263,10 +244,6 @@ class Containerize():
imageNames.append(('oai-nr-ue', 'nrUE', 'oai-nr-ue', ''))
cmd.cd(lSourcePath)
- # if asterix, copy the entitlement and subscription manager configurations
- if self.host == 'Red Hat':
- cmd.run('mkdir -p ./etc-pki-entitlement')
- cmd.run('cp /etc/pki/entitlement/*.pem ./etc-pki-entitlement/')
baseImage = 'ran-base'
baseTag = 'develop'
@@ -275,7 +252,7 @@ class Containerize():
if (self.ranAllowMerge):
imageTag = 'ci-temp'
if self.ranTargetBranch == 'develop':
- cmd.run(f'git diff HEAD..origin/develop -- cmake_targets/build_oai cmake_targets/tools/build_helper docker/Dockerfile.base{self.dockerfileprefix} | grep --colour=never -i INDEX')
+ cmd.run(f'git diff HEAD..origin/develop -- cmake_targets/build_oai cmake_targets/tools/build_helper docker/Dockerfile.base{dockerfileprefix} | grep --colour=never -i INDEX')
result = re.search('index', cmd.getBefore())
if result is not None:
forceBaseImageBuild = True
@@ -289,31 +266,30 @@ class Containerize():
forceBaseImageBuild = True
# Let's remove any previous run artifacts if still there
- cmd.run(f"{self.cli} image prune --force")
+ cmd.run(f"docker image prune --force")
for image,pattern,name,option in imageNames:
- cmd.run(f"{self.cli} image rm {name}:{imageTag}", reportNonZero=False)
+ cmd.run(f"docker image rm {name}:{imageTag}", reportNonZero=False)
cmd.run(f'docker login -u oaicicd -p oaicicd {DEFAULT_REGISTRY}')
ubuntuImage = "ubuntu:noble"
# Build the base image only on Push Events (not on Merge Requests)
# On when the base image docker file is being modified.
if forceBaseImageBuild:
- cmd.run(f"{self.cli} image rm {baseImage}:{baseTag}")
+ cmd.run(f"docker image rm {baseImage}:{baseTag}")
logfile = f'{lSourcePath}/cmake_targets/log/ran-base.docker.log'
- if self.host == 'Ubuntu':
- option = f" --build-arg UBUNTU_IMAGE={DEFAULT_REGISTRY}/{ubuntuImage}"
- cmd.run(f"{self.cli} build {self.cliBuildOptions} --target {baseImage} --tag {baseImage}:{baseTag} --file docker/Dockerfile.base{self.dockerfileprefix} {option} . &> {logfile}", timeout=1600)
+ option = f" --build-arg UBUNTU_IMAGE={DEFAULT_REGISTRY}/{ubuntuImage}"
+ cmd.run(f"docker build --target {baseImage} --tag {baseImage}:{baseTag} --file docker/Dockerfile.base{dockerfileprefix} {option} . &> {logfile}", timeout=1600)
t = ("ran-base", archiveArtifact(cmd, ctx, logfile))
log_files.append(t)
# First verify if the base image was properly created.
- ret = cmd.run(f"{self.cli} image inspect --format=\'Size = {{{{.Size}}}} bytes\' {baseImage}:{baseTag}")
+ ret = cmd.run(f"docker image inspect --format=\'Size = {{{{.Size}}}} bytes\' {baseImage}:{baseTag}")
allImagesSize = {}
if ret.returncode != 0:
logging.error('\u001B[1m Could not build properly ran-base\u001B[0m')
# Recover the name of the failed container?
- cmd.run(f"{self.cli} ps --quiet --filter \"status=exited\" -n1 | xargs --no-run-if-empty {self.cli} rm -f")
- cmd.run(f"{self.cli} image prune --force")
+ cmd.run(f"docker ps --quiet --filter \"status=exited\" -n1 | xargs --no-run-if-empty docker rm -f")
+ cmd.run(f"docker image prune --force")
cmd.close()
logging.error('\u001B[1m Building OAI Images Failed\u001B[0m')
HTML.CreateHtmlTestRow(self.imageKind, 'KO', CONST.ALL_PROCESSES_OK)
@@ -333,32 +309,31 @@ class Containerize():
for image,pattern,name,option in imageNames:
# the archived Dockerfiles have "ran-base:latest" as base image
# we need to update them with proper tag
- cmd.run(f'git checkout -- docker/Dockerfile.{pattern}{self.dockerfileprefix}')
- cmd.run(f'sed -i -e "s#{baseImage}:latest#{baseImage}:{baseTag}#" docker/Dockerfile.{pattern}{self.dockerfileprefix}')
+ cmd.run(f'git checkout -- docker/Dockerfile.{pattern}{dockerfileprefix}')
+ cmd.run(f'sed -i -e "s#{baseImage}:latest#{baseImage}:{baseTag}#" docker/Dockerfile.{pattern}{dockerfileprefix}')
# target images should use the proper ran-build image
if image != 'ran-build' and "-asan" in name:
- cmd.run(f'sed -i -e "s#ran-build:latest#ran-build-asan:{imageTag}#" docker/Dockerfile.{pattern}{self.dockerfileprefix}')
+ cmd.run(f'sed -i -e "s#ran-build:latest#ran-build-asan:{imageTag}#" docker/Dockerfile.{pattern}{dockerfileprefix}')
elif "fhi72" in name or name == "oai-nr-oru":
- cmd.run(f'sed -i -e "s#ran-build-fhi72:latest#ran-build-fhi72:{imageTag}#" docker/Dockerfile.{pattern}{self.dockerfileprefix}')
+ cmd.run(f'sed -i -e "s#ran-build-fhi72:latest#ran-build-fhi72:{imageTag}#" docker/Dockerfile.{pattern}{dockerfileprefix}')
elif image != 'ran-build':
- cmd.run(f'sed -i -e "s#ran-build:latest#ran-build:{imageTag}#" docker/Dockerfile.{pattern}{self.dockerfileprefix}')
+ cmd.run(f'sed -i -e "s#ran-build:latest#ran-build:{imageTag}#" docker/Dockerfile.{pattern}{dockerfileprefix}')
if image == 'oai-gnb-aerial':
cmd.run('cp -f /opt/nvidia-ipc/nvipc_src.2026.01.07.tar.gz .')
logfile = f'{lSourcePath}/cmake_targets/log/{name}.docker.log'
- if self.host == 'Ubuntu':
- option = option + f" --build-arg UBUNTU_IMAGE={DEFAULT_REGISTRY}/{ubuntuImage}"
- ret = cmd.run(f'{self.cli} build {self.cliBuildOptions} --target {image} --tag {name}:{imageTag} --file docker/Dockerfile.{pattern}{self.dockerfileprefix} {option} . > {logfile} 2>&1', timeout=1200)
+ option = option + f" --build-arg UBUNTU_IMAGE={DEFAULT_REGISTRY}/{ubuntuImage}"
+ ret = cmd.run(f'docker build --target {image} --tag {name}:{imageTag} --file docker/Dockerfile.{pattern}{dockerfileprefix} {option} . > {logfile} 2>&1', timeout=1200)
t = (name, archiveArtifact(cmd, ctx, logfile))
log_files.append(t)
if image == 'oai-gnb-aerial':
cmd.run('rm -f nvipc_src.2026.01.07.tar.gz')
# check the status of the build
- ret = cmd.run(f"{self.cli} image inspect --format=\'Size = {{{{.Size}}}} bytes\' {name}:{imageTag}")
+ ret = cmd.run(f"docker image inspect --format=\'Size = {{{{.Size}}}} bytes\' {name}:{imageTag}")
if ret.returncode != 0:
logging.error('\u001B[1m Could not build properly ' + name + '\u001B[0m')
status = False
# Here we should check if the last container corresponds to a failed command and destroy it
- cmd.run(f"{self.cli} ps --quiet --filter \"status=exited\" -n1 | xargs --no-run-if-empty {self.cli} rm -f")
+ cmd.run(f"docker ps --quiet --filter \"status=exited\" -n1 | xargs --no-run-if-empty docker rm -f")
allImagesSize[name] = 'N/A -- Build Failed'
break
else:
@@ -372,16 +347,16 @@ class Containerize():
logging.debug(f'{name} size is unknown')
allImagesSize[name] = 'unknown'
# Now pruning dangling images in between target builds
- cmd.run(f"{self.cli} image prune --force")
+ cmd.run(f"docker image prune --force")
cmd.run(f'docker logout {DEFAULT_REGISTRY}')
# Remove all intermediate build images and clean up
- cmd.run(f"{self.cli} image rm ran-build:{imageTag} ran-build-asan:{imageTag} ran-build-fhi72:{imageTag} || true")
- cmd.run(f"{self.cli} volume prune --force")
+ cmd.run(f"docker image rm ran-build:{imageTag} ran-build-asan:{imageTag} ran-build-fhi72:{imageTag} || true")
+ cmd.run(f"docker volume prune --force")
# Remove some cached artifacts to prevent out of diskspace problem
logging.debug(cmd.run("df -h").stdout)
logging.debug(cmd.run("docker system df").stdout)
- cmd.run(f"{self.cli} buildx prune --filter until=1h --force")
+ cmd.run(f"docker buildx prune --filter until=1h --force")
logging.debug(cmd.run("df -h").stdout)
logging.debug(cmd.run("docker system df").stdout)
@@ -489,20 +464,12 @@ class Containerize():
cmd = cls_cmd.getConnection(node)
cmd.cd(lSourcePath)
- ret = cmd.run('hostnamectl')
- result = re.search('Ubuntu', ret.stdout)
- host = result.group(0)
- if host != 'Ubuntu':
- cmd.close()
- raise Exception("Can build unit tests only on Ubuntu server")
- logging.debug('running on Ubuntu as expected')
-
# check that ran-base image exists as we expect it
baseImage = 'ran-base'
baseTag = 'develop'
if self.ranAllowMerge:
if self.ranTargetBranch == 'develop':
- cmd.run(f'git diff HEAD..origin/develop -- cmake_targets/build_oai cmake_targets/tools/build_helper docker/Dockerfile.base{self.dockerfileprefix} | grep --colour=never -i INDEX')
+ cmd.run(f'git diff HEAD..origin/develop -- cmake_targets/build_oai cmake_targets/tools/build_helper docker/Dockerfile.base.ubuntu | grep --colour=never -i INDEX')
result = re.search('index', cmd.getBefore())
if result is not None:
baseTag = 'ci-temp'
diff --git a/ci-scripts/cls_oai_html.py b/ci-scripts/cls_oai_html.py
index 2f59ae1852..66d4b804ae 100644
--- a/ci-scripts/cls_oai_html.py
+++ b/ci-scripts/cls_oai_html.py
@@ -379,90 +379,6 @@ class HTMLManagement():
self.htmlFile.write(' \n')
self.htmlFile.close()
- def CreateHtmlTestRowCppCheckResults(self, CCR):
- if (self.htmlFooterCreated or (not self.htmlHeaderCreated)):
- return
- self.htmlFile = open('test_results.html', 'a')
- vId = 0
- for version in CCR.versions:
- self.htmlFile.write('
\n')
- self.htmlFile.write(' | Results for cppcheck v ' + version + ' | \n')
- self.htmlFile.write('
\n')
- self.htmlFile.write(' \n')
- self.htmlFile.write(' | \n')
- self.htmlFile.write(' NB ERRORS | \n')
- if CCR.nbErrors[vId] == 0:
- myColor = 'lightgreen'
- elif CCR.nbErrors[vId] < 20:
- myColor = 'orange'
- else:
- myColor = 'lightcoral'
- self.htmlFile.write(' ' + str(CCR.nbErrors[vId]) + ' | \n')
- self.htmlFile.write('
\n')
- self.htmlFile.write(' \n')
- self.htmlFile.write(' | \n')
- self.htmlFile.write(' NB WARNINGS | \n')
- if CCR.nbWarnings[vId] == 0:
- myColor = 'lightgreen'
- elif CCR.nbWarnings[vId] < 20:
- myColor = 'orange'
- else:
- myColor = 'lightcoral'
- self.htmlFile.write(' ' + str(CCR.nbWarnings[vId]) + ' | \n')
- self.htmlFile.write('
\n')
- self.htmlFile.write(' \n')
- self.htmlFile.write(' | ----------------- | \n')
- self.htmlFile.write('
\n')
- self.htmlFile.write(' \n')
- self.htmlFile.write(' | \n')
- self.htmlFile.write(' Memory leak | \n')
- self.htmlFile.write(' ' + str(CCR.nbMemLeaks[vId]) + ' | \n')
- self.htmlFile.write('
\n')
- self.htmlFile.write(' \n')
- self.htmlFile.write(' | \n')
- self.htmlFile.write(' Possible null pointer deference | \n')
- self.htmlFile.write(' ' + str(CCR.nbNullPtrs[vId]) + ' | \n')
- self.htmlFile.write('
\n')
- self.htmlFile.write(' \n')
- self.htmlFile.write(' | \n')
- self.htmlFile.write(' Uninitialized variable | \n')
- self.htmlFile.write(' ' + str(CCR.nbUninitVars[vId]) + ' | \n')
- self.htmlFile.write('
\n')
- self.htmlFile.write(' \n')
- self.htmlFile.write(' | \n')
- self.htmlFile.write(' Undefined behaviour shifting | \n')
- self.htmlFile.write(' ' + str(CCR.nbTooManyBitsShift[vId]) + ' | \n')
- self.htmlFile.write('
\n')
- self.htmlFile.write(' \n')
- self.htmlFile.write(' | \n')
- self.htmlFile.write(' Signed integer overflow | \n')
- self.htmlFile.write(' ' + str(CCR.nbIntegerOverflow[vId]) + ' | \n')
- self.htmlFile.write('
\n')
- self.htmlFile.write(' \n')
- self.htmlFile.write(' | | \n')
- self.htmlFile.write('
\n')
- self.htmlFile.write(' \n')
- self.htmlFile.write(' | \n')
- self.htmlFile.write(' Printf formatting issues | \n')
- self.htmlFile.write(' ' + str(CCR.nbInvalidPrintf[vId]) + ' | \n')
- self.htmlFile.write('
\n')
- self.htmlFile.write(' \n')
- self.htmlFile.write(' | \n')
- self.htmlFile.write(' Modulo result is predetermined | \n')
- self.htmlFile.write(' ' + str(CCR.nbModuloAlways[vId]) + ' | \n')
- self.htmlFile.write('
\n')
- self.htmlFile.write(' \n')
- self.htmlFile.write(' | \n')
- self.htmlFile.write(' Opposite Condition -> dead code | \n')
- self.htmlFile.write(' ' + str(CCR.nbOppoInnerCondition[vId]) + ' | \n')
- self.htmlFile.write('
\n')
- self.htmlFile.write(' \n')
- self.htmlFile.write(' | \n')
- self.htmlFile.write(' Wrong Scanf Nb Args | \n')
- self.htmlFile.write(' ' + str(CCR.nbWrongScanfArg[vId]) + ' | \n')
- self.htmlFile.write('
\n')
- vId += 1
-
def CreateHtmlTestRowPhySimTestResult(self, testSummary, testResult):
if (self.htmlFooterCreated or (not self.htmlHeaderCreated)):
return
diff --git a/ci-scripts/cls_static_code_analysis.py b/ci-scripts/cls_static_code_analysis.py
index 603df581e3..3b4ee10f9b 100644
--- a/ci-scripts/cls_static_code_analysis.py
+++ b/ci-scripts/cls_static_code_analysis.py
@@ -27,160 +27,30 @@ import constants as CONST
import cls_cmd
from cls_ci_helper import archiveArtifact
-#-----------------------------------------------------------
-# Class Declaration
-#-----------------------------------------------------------
-class CppCheckResults():
-
- def __init__(self):
-
- self.variants = ['bionic', 'focal']
- self.versions = ['','']
- self.nbErrors = [0,0]
- self.nbWarnings = [0,0]
- self.nbNullPtrs = [0,0]
- self.nbMemLeaks = [0,0]
- self.nbUninitVars = [0,0]
- self.nbInvalidPrintf = [0,0]
- self.nbModuloAlways = [0,0]
- self.nbTooManyBitsShift = [0,0]
- self.nbIntegerOverflow = [0,0]
- self.nbWrongScanfArg = [0,0]
- self.nbPtrAddNotNull = [0,0]
- self.nbOppoInnerCondition = [0,0]
-
class StaticCodeAnalysis():
- def __init__(self):
-
- self.ranRepository = ''
- self.ranBranch = ''
- self.ranAllowMerge = False
- self.ranCommitID = ''
- self.ranTargetBranch = ''
- self.eNBSourceCodePath = ''
-
- def CppCheckAnalysis(self, ctx, node, HTML):
- if self.ranRepository == '' or self.ranBranch == '' or self.ranCommitID == '':
- HELP.GenericHelp(CONST.Version)
- sys.exit('Insufficient Parameter')
- lSourcePath = self.eNBSourceCodePath
-
- if not lSourcePath or not node:
- raise ValueError(f"{lSourcePath=} {node=}")
- logging.debug('Building on server: ' + node)
- cmd = cls_cmd.getConnection(node)
- # on RedHat/CentOS .git extension is mandatory
- result = re.search(r'([a-zA-Z0-9\:\-\.\/])+\.git', self.ranRepository)
- if result is not None:
- full_ran_repo_name = self.ranRepository.replace('git/', 'git')
- else:
- full_ran_repo_name = self.ranRepository + '.git'
-
- cmd.cd(lSourcePath)
- logDir = f'{lSourcePath}/cmake_targets/log'
- cmd.run(f'mkdir -p {logDir}')
- cmd.run('docker image rm oai-cppcheck:bionic oai-cppcheck:focal')
- cmd.run(f'sed -e "s@xenial@bionic@" {lSourcePath}/ci-scripts/docker/Dockerfile.cppcheck.xenial > {lSourcePath}/ci-scripts/docker/Dockerfile.cppcheck.bionic')
- cmd.run(f'docker build --tag oai-cppcheck:bionic --file {lSourcePath}/ci-scripts/docker/Dockerfile.cppcheck.bionic . > {logDir}/cppcheck-bionic.txt 2>&1')
- cmd.run(f'sed -e "s@xenial@focal@" {lSourcePath}/ci-scripts/docker/Dockerfile.cppcheck.xenial > {lSourcePath}/ci-scripts/docker/Dockerfile.cppcheck.focal')
- cmd.run(f'docker build --tag oai-cppcheck:focal --file {lSourcePath}/ci-scripts/docker/Dockerfile.cppcheck.focal . > {logDir}/cppcheck-focal.txt 2>&1')
- cmd.run('docker image rm oai-cppcheck:bionic oai-cppcheck:focal')
-
- bionic = archiveArtifact(cmd, ctx, f'{logDir}/cppcheck-bionic.txt')
- focal = archiveArtifact(cmd, ctx, f'{logDir}/cppcheck-focal.txt')
- cmd.close()
-
- CCR = CppCheckResults()
- CCR_ref = CppCheckResults()
- vId = 0
- for variant in CCR.variants:
- filename = ctx.baseFilename() + '-cppcheck-'+ variant + '.txt'
- logging.info(f"will check file '{filename}'")
- if not os.path.isfile(filename):
- raise FileNotFoundError(f"{filename} is not a file")
- else:
- xmlStart = False
- with open(filename, 'r') as logfile:
- for line in logfile:
- ret = re.search(r'cppcheck version="(?P[0-9\.]+)"', str(line))
- if ret is not None:
- CCR.versions[vId] = ret.group('version')
- if re.search('RUN cat cmake_targets/log/cppcheck.xml', str(line)) is not None:
- xmlStart = True
- if xmlStart:
- if re.search('severity="error"', str(line)) is not None:
- CCR.nbErrors[vId] += 1
- if re.search('severity="warning"', str(line)) is not None:
- CCR.nbWarnings[vId] += 1
- if re.search('id="memleak"', str(line)) is not None:
- CCR.nbMemLeaks[vId] += 1
- if re.search('id="nullPointer"', str(line)) is not None:
- CCR.nbNullPtrs[vId] += 1
- if re.search('id="uninitvar"', str(line)) is not None:
- CCR.nbUninitVars[vId] += 1
- if re.search('id="invalidPrintfArgType_sint"|id="invalidPrintfArgType_uint"', str(line)) is not None:
- CCR.nbInvalidPrintf[vId] += 1
- if re.search('id="moduloAlwaysTrueFalse"', str(line)) is not None:
- CCR.nbModuloAlways[vId] += 1
- if re.search('id="shiftTooManyBitsSigned"', str(line)) is not None:
- CCR.nbTooManyBitsShift[vId] += 1
- if re.search('id="integerOverflow"', str(line)) is not None:
- CCR.nbIntegerOverflow[vId] += 1
- if re.search('id="wrongPrintfScanfArgNum"|id="invalidScanfArgType_int"', str(line)) is not None:
- CCR.nbWrongScanfArg[vId] += 1
- if re.search('id="pointerAdditionResultNotNull"', str(line)) is not None:
- CCR.nbPtrAddNotNull[vId] += 1
- if re.search('id="oppositeInnerCondition"', str(line)) is not None:
- CCR.nbOppoInnerCondition[vId] += 1
- vMsg = ''
- vMsg += '======== Variant ' + variant + ' - ' + CCR.versions[vId] + ' ========\n'
- vMsg += ' ' + str(CCR.nbErrors[vId]) + ' errors\n'
- vMsg += ' ' + str(CCR.nbWarnings[vId]) + ' warnings\n'
- vMsg += ' -- Details --\n'
- vMsg += ' Memory leak: ' + str(CCR.nbMemLeaks[vId]) + '\n'
- vMsg += ' Possible null pointer deference: ' + str(CCR.nbNullPtrs[vId]) + '\n'
- vMsg += ' Uninitialized variable: ' + str(CCR.nbUninitVars[vId]) + '\n'
- vMsg += ' Undefined behaviour shifting: ' + str(CCR.nbTooManyBitsShift[vId]) + '\n'
- vMsg += ' Signed integer overflow: ' + str(CCR.nbIntegerOverflow[vId]) + '\n'
- vMsg += '\n'
- vMsg += ' Printf formatting issue: ' + str(CCR.nbInvalidPrintf[vId]) + '\n'
- vMsg += ' Modulo result is predetermined: ' + str(CCR.nbModuloAlways[vId]) + '\n'
- vMsg += ' Opposite Condition -> dead code: ' + str(CCR.nbOppoInnerCondition[vId]) + '\n'
- vMsg += ' Wrong Scanf Nb Args: ' + str(CCR.nbWrongScanfArg[vId]) + '\n'
- for vLine in vMsg.split('\n'):
- logging.debug(vLine)
- vId += 1
-
- HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK)
- HTML.CreateHtmlTestRowCppCheckResults(CCR)
- logging.info('\u001B[1m Static Code Analysis Pass\u001B[0m')
-
- return True
-
- def LicenceAndFormattingCheck(self, ctx, node, HTML):
+ def LicenceAndFormattingCheck(ctx, node, HTML, d, branch, allowMerge, targetBranch):
# Workspace is no longer recreated from scratch.
# It implies that this method shall be called last within a build pipeline
# where workspace is already created
- lSourcePath = self.eNBSourceCodePath
- if not node or not lSourcePath:
- raise ValueError(f"{lSourcePath=} {node=}")
+ if not node or not d:
+ raise ValueError(f"{d=} {node=}")
logging.debug('Building on server: ' + node)
cmd = cls_cmd.getConnection(node)
check_options = ''
- if self.ranAllowMerge:
- check_options = f'--build-arg MERGE_REQUEST=true --build-arg SRC_BRANCH={self.ranBranch}'
- if self.ranTargetBranch == '':
- if self.ranBranch != 'develop' and self.ranBranch != 'origin/develop':
+ if allowMerge:
+ check_options = f'--build-arg MERGE_REQUEST=true --build-arg SRC_BRANCH={branch}'
+ if targetBranch == '':
+ if branch != 'develop' and branch != 'origin/develop':
check_options += ' --build-arg TARGET_BRANCH=develop'
else:
- check_options += f' --build-arg TARGET_BRANCH={self.ranTargetBranch}'
+ check_options += f' --build-arg TARGET_BRANCH={targetBranch}'
- logDir = f'{lSourcePath}/cmake_targets/log/'
+ logDir = f'{d}/cmake_targets/log/'
cmd.run(f'mkdir -p {logDir}')
cmd.run('docker image rm oai-formatting-check:latest')
- cmd.run(f'docker build --target oai-formatting-check --tag oai-formatting-check:latest {check_options} --file {lSourcePath}/ci-scripts/docker/Dockerfile.formatting.ubuntu {lSourcePath} > {logDir}/oai-formatting-check.txt 2>&1')
+ cmd.run(f'docker build --target oai-formatting-check --tag oai-formatting-check:latest {check_options} --file {d}/ci-scripts/docker/Dockerfile.formatting.ubuntu {d} > {logDir}/oai-formatting-check.txt 2>&1')
cmd.run('docker image rm oai-formatting-check:latest')
cmd.run('docker image prune --force')
diff --git a/ci-scripts/conf_files/gnb-cu.sa.band78.106prb.conf b/ci-scripts/conf_files/gnb-cu.sa.band78.106prb.conf
index 015d77cacc..8460983d2b 100644
--- a/ci-scripts/conf_files/gnb-cu.sa.band78.106prb.conf
+++ b/ci-scripts/conf_files/gnb-cu.sa.band78.106prb.conf
@@ -17,6 +17,7 @@ gNBs =
// Tracking area code, 0x0000 and 0xfffe are reserved values
tracking_area_code = 1;
plmn_list = ({ mcc = 208; mnc = 99; mnc_length = 2; snssaiList = ({ sst = 1, sd = 0xffffff }) });
+ cu_sibs = ( 2, 3, 4 );
@include "neighbour-config.conf"
nr_cellid = 12345678L;
diff --git a/ci-scripts/conf_files/neighbour-config.conf b/ci-scripts/conf_files/neighbour-config.conf
index fe91ff2f08..57aa55f772 100644
--- a/ci-scripts/conf_files/neighbour-config.conf
+++ b/ci-scripts/conf_files/neighbour-config.conf
@@ -5,6 +5,57 @@
# for the 2-cell rfsim setup (gNB_ID 0xe00 & 0xb00) #
############################################################
+############################################################
+# SIB2 #
+############################################################
+
+sib2_config : {
+ q_Hyst = 0;
+ cellReselectionPriority = 0;
+ threshServingLowP = 0;
+ threshServingLowQ = 0;
+ s_NonIntraSearchP = -1;
+ s_NonIntraSearchQ = -1;
+ q_RxLevMin = -56;
+ q_QualMin = -1;
+ s_IntraSearchP = 22;
+ s_IntraSearchQ = -1;
+ t_ReselectionNR = 1;
+ deriveSSB_IndexFromCell = 1;
+
+ speed_t_Evaluation = 0;
+ speed_t_HystNormal = 0;
+ speed_n_CellChangeMedium = 1;
+ speed_n_CellChangeHigh = 2;
+ speed_sf_Medium = 1;
+ speed_sf_High = 0;
+};
+
+############################################################
+# Per-frequency SIB4 inter-frequency configuration #
+############################################################
+
+frequency_list = (
+ {
+ absoluteFrequencySSB = 621312;
+ subcarrierSpacing = 1; # 30 kHz
+ band = 78;
+
+ frequency_config = (
+ {
+ cellReselectionPriority = 5;
+ threshX_HighP = 10;
+ threshX_LowP = 6;
+ threshX_HighQ = -1;
+ threshX_LowQ = -1;
+ q_OffsetFreq = 0;
+ q_RxLevMin = -56;
+ t_ReselectionNR = 1;
+ }
+ );
+ }
+);
+
neighbour_list = (
##########################################################
# Entry USED BY gNB_ID = 0xe00 (nr_cellid = 1) #
@@ -21,6 +72,9 @@ neighbour_list = (
band = 78;
plmn = { mcc = 208; mnc = 99; mnc_length = 2 };
tracking_area_code = 1;
+ q_OffsetCell = 2;
+ q_RxLevMinOffsetCell= 2;
+ q_QualMinOffsetCell = 1;
}
);
},
@@ -40,6 +94,9 @@ neighbour_list = (
band = 78;
plmn = { mcc = 208; mnc = 99; mnc_length = 2 };
tracking_area_code = 1;
+ q_OffsetCell = 2;
+ q_RxLevMinOffsetCell= 2;
+ q_QualMinOffsetCell = 1;
}
);
}
diff --git a/ci-scripts/docker/Dockerfile.cppcheck.xenial b/ci-scripts/docker/Dockerfile.cppcheck.xenial
deleted file mode 100644
index fcb7f814ae..0000000000
--- a/ci-scripts/docker/Dockerfile.cppcheck.xenial
+++ /dev/null
@@ -1,41 +0,0 @@
-# SPDX-License-Identifier: LicenseRef-CSSL-1.0
-
-#---------------------------------------------------------------------
-#
-# Dockerfile for the Open-Air-Interface BUILD service
-# Valid for Ubuntu 22.04
-#
-#---------------------------------------------------------------------
-FROM ubuntu:xenial AS oai-cppcheck
-
-
-ENV DEBIAN_FRONTEND=noninteractive
-
-RUN apt-get update && \
- apt-get upgrade --yes && \
- apt-get install --yes \
- build-essential \
- vim \
- cppcheck
-
-WORKDIR /oai-ran
-COPY . .
-
-WORKDIR /oai-ran/common/utils/T
-RUN make
-
-WORKDIR /oai-ran
-RUN mkdir -p cmake_targets/log && \
- cppcheck --enable=warning --force --xml --xml-version=2 \
- --inline-suppr \
- -i openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c \
- --suppressions-list=ci-scripts/cppcheck_suppressions.list \
- -I common/utils \
- -I openair3/NAS/COMMON/UTIL \
- -j`nproc` . 2> cmake_targets/log/cppcheck.xml 1> cmake_targets/log/cppcheck_build.txt
-
-RUN grep -E -c 'severity="error' cmake_targets/log/cppcheck.xml
-
-RUN grep -E -c 'severity="warning' cmake_targets/log/cppcheck.xml
-
-RUN cat cmake_targets/log/cppcheck.xml
diff --git a/ci-scripts/main.py b/ci-scripts/main.py
index 27cf36bcf8..66e8b2091b 100644
--- a/ci-scripts/main.py
+++ b/ci-scripts/main.py
@@ -22,7 +22,7 @@ import constants as CONST
import cls_oaicitest #main class for OAI CI test framework
import cls_containerize #class Containerize for all container-based operations on RAN/UE objects
-import cls_static_code_analysis #class for static code analysis
+import cls_static_code_analysis as SCA
import cls_cluster # class for building/deploying on cluster
import cls_native # class for all native/source-based operations
from cls_ci_helper import TestCaseCtx
@@ -64,7 +64,6 @@ def ExecuteActionWithParam(action, ctx, node):
global RAN
global HTML
global CONTAINERS
- global SCA
global CLUSTER
if action == 'Build_eNB' or action == 'Build_Image' or action == 'Build_Proxy' or action == "Build_Cluster_Image" or action == "Build_Run_Tests":
RAN.Build_eNB_args=test.findtext('Build_eNB_args')
@@ -196,10 +195,7 @@ def ExecuteActionWithParam(action, ctx, node):
success = CONTAINERS.Create_Workspace(node, HTML)
elif action == 'LicenceAndFormattingCheck':
- success = SCA.LicenceAndFormattingCheck(ctx, node, HTML)
-
- elif action == 'Cppcheck_Analysis':
- success = SCA.CppCheckAnalysis(ctx, node, HTML)
+ success = SCA.StaticCodeAnalysis.LicenceAndFormattingCheck(ctx, node, HTML, RAN.eNBSourceCodePath, RAN.ranBranch, RAN.ranAllowMerge, RAN.ranTargetBranch)
elif action == 'Push_Local_Registry':
tag_prefix = test.findtext('tag_prefix') or ""
@@ -297,7 +293,6 @@ CiTestObj = cls_oaicitest.OaiCiTest()
RAN = ran.RANManagement()
HTML = cls_oai_html.HTMLManagement()
CONTAINERS = cls_containerize.Containerize()
-SCA = cls_static_code_analysis.StaticCodeAnalysis()
CLUSTER = cls_cluster.Cluster()
#-----------------------------------------------------------
@@ -307,7 +302,7 @@ CLUSTER = cls_cluster.Cluster()
import args_parse
# Force local execution, move all execution targets to localhost
force_local = False
-mode, force_local, date_fmt = args_parse.ArgsParse(sys.argv,CiTestObj,RAN,HTML,CONTAINERS,HELP,SCA,CLUSTER)
+mode, force_local, date_fmt = args_parse.ArgsParse(sys.argv,CiTestObj,RAN,HTML,CONTAINERS,HELP,CLUSTER)
fmt = "%(levelname)8s: %(message)s"
if date_fmt:
fmt = "[%(asctime)s] %(levelname)s %(message)s"
diff --git a/ci-scripts/xml_class_list.yml b/ci-scripts/xml_class_list.yml
index 52b44e0e96..d762c4b316 100755
--- a/ci-scripts/xml_class_list.yml
+++ b/ci-scripts/xml_class_list.yml
@@ -23,7 +23,6 @@
- Deploy_Object
- Stop_Object
- Undeploy_Object
- - Cppcheck_Analysis
- Deploy_Run_OC_PhySim
- Build_Deploy_PhySim
- LicenceAndFormattingCheck
diff --git a/ci-scripts/xml_files/cppcheck.xml b/ci-scripts/xml_files/cppcheck.xml
deleted file mode 100644
index 061c39b5b8..0000000000
--- a/ci-scripts/xml_files/cppcheck.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-
- build-tab
- CPPCHECK Analysis
- wrench
-
-
- Create_Workspace
- Create new Workspace
- carabe
-
-
-
- Cppcheck_Analysis
- Static Code Analysis with cppcheck
- carabe
-
-
-
diff --git a/ci-scripts/yaml_files/4g_l2sim_fdd/docker-compose.yml b/ci-scripts/yaml_files/4g_l2sim_fdd/docker-compose.yml
index 7bc7a4d8cc..6813e13b10 100644
--- a/ci-scripts/yaml_files/4g_l2sim_fdd/docker-compose.yml
+++ b/ci-scripts/yaml_files/4g_l2sim_fdd/docker-compose.yml
@@ -166,7 +166,7 @@ services:
retries: 5
trf_gen:
- image: oaisoftwarealliance/trf-gen-cn5g:focal
+ image: oaisoftwarealliance/trf-gen-cn5g:latest
privileged: true
container_name: l2sim4g-trf-gen
networks:
diff --git a/ci-scripts/yaml_files/4g_rfsimulator_fdd_05MHz/docker-compose.yml b/ci-scripts/yaml_files/4g_rfsimulator_fdd_05MHz/docker-compose.yml
index a88f36fbc0..53793a924b 100644
--- a/ci-scripts/yaml_files/4g_rfsimulator_fdd_05MHz/docker-compose.yml
+++ b/ci-scripts/yaml_files/4g_rfsimulator_fdd_05MHz/docker-compose.yml
@@ -166,7 +166,7 @@ services:
retries: 5
trf_gen:
- image: oaisoftwarealliance/trf-gen-cn5g:focal
+ image: oaisoftwarealliance/trf-gen-cn5g:latest
privileged: true
container_name: rfsim4g-trf-gen
networks:
diff --git a/ci-scripts/yaml_files/4g_rfsimulator_fdd_10MHz/docker-compose.yml b/ci-scripts/yaml_files/4g_rfsimulator_fdd_10MHz/docker-compose.yml
index 2b19d5bbb7..f61c077b70 100644
--- a/ci-scripts/yaml_files/4g_rfsimulator_fdd_10MHz/docker-compose.yml
+++ b/ci-scripts/yaml_files/4g_rfsimulator_fdd_10MHz/docker-compose.yml
@@ -166,7 +166,7 @@ services:
retries: 5
trf_gen:
- image: oaisoftwarealliance/trf-gen-cn5g:focal
+ image: oaisoftwarealliance/trf-gen-cn5g:latest
privileged: true
container_name: rfsim4g-trf-gen
networks:
diff --git a/ci-scripts/yaml_files/4g_rfsimulator_fdd_20MHz/docker-compose.yml b/ci-scripts/yaml_files/4g_rfsimulator_fdd_20MHz/docker-compose.yml
index 0e6caffb13..81362b26d1 100644
--- a/ci-scripts/yaml_files/4g_rfsimulator_fdd_20MHz/docker-compose.yml
+++ b/ci-scripts/yaml_files/4g_rfsimulator_fdd_20MHz/docker-compose.yml
@@ -166,7 +166,7 @@ services:
retries: 5
trf_gen:
- image: oaisoftwarealliance/trf-gen-cn5g:focal
+ image: oaisoftwarealliance/trf-gen-cn5g:latest
privileged: true
container_name: rfsim4g-trf-gen
networks:
diff --git a/ci-scripts/yaml_files/4g_rfsimulator_tdd_05MHz/docker-compose.yml b/ci-scripts/yaml_files/4g_rfsimulator_tdd_05MHz/docker-compose.yml
index b795350642..35672381cc 100644
--- a/ci-scripts/yaml_files/4g_rfsimulator_tdd_05MHz/docker-compose.yml
+++ b/ci-scripts/yaml_files/4g_rfsimulator_tdd_05MHz/docker-compose.yml
@@ -166,7 +166,7 @@ services:
retries: 5
trf_gen:
- image: oaisoftwarealliance/trf-gen-cn5g:focal
+ image: oaisoftwarealliance/trf-gen-cn5g:latest
privileged: true
container_name: rfsim4g-trf-gen
networks:
diff --git a/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml b/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml
index 58b5748668..a606c50ccc 100644
--- a/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml
+++ b/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml
@@ -3,7 +3,7 @@
services:
mysql:
container_name: "rfsim5g-mysql"
- image: mysql:8.0
+ image: mysql:9.6
init: true
volumes:
- ../5g_rfsimulator/oai_db.sql:/docker-entrypoint-initdb.d/oai_db.sql
@@ -26,7 +26,7 @@ services:
ipv4_address: 192.168.71.131
oai-amf:
container_name: "rfsim5g-oai-amf"
- image: oaisoftwarealliance/oai-amf:v2.1.10
+ image: oaisoftwarealliance/oai-amf:v2.2.1
environment:
- TZ=Europe/paris
volumes:
@@ -38,7 +38,7 @@ services:
ipv4_address: 192.168.71.132
oai-smf:
container_name: "rfsim5g-oai-smf"
- image: oaisoftwarealliance/oai-smf:v2.1.10
+ image: oaisoftwarealliance/oai-smf:v2.2.1
environment:
- TZ=Europe/Paris
volumes:
@@ -50,7 +50,7 @@ services:
ipv4_address: 192.168.71.133
oai-upf:
container_name: "rfsim5g-oai-upf"
- image: oaisoftwarealliance/oai-upf:v2.1.10
+ image: oaisoftwarealliance/oai-upf:v2.2.1
init: true
environment:
- TZ=Europe/Paris
@@ -75,7 +75,7 @@ services:
oai-ext-dn:
privileged: true
container_name: rfsim5g-oai-ext-dn
- image: oaisoftwarealliance/trf-gen-cn5g:focal
+ image: oaisoftwarealliance/trf-gen-cn5g:latest
init: true
entrypoint: /bin/bash -c \
"iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE;"\
diff --git a/ci-scripts/yaml_files/5g_fdd_rfsimulator/docker-compose.yaml b/ci-scripts/yaml_files/5g_fdd_rfsimulator/docker-compose.yaml
index f43c8aaa03..9d1a35a249 100644
--- a/ci-scripts/yaml_files/5g_fdd_rfsimulator/docker-compose.yaml
+++ b/ci-scripts/yaml_files/5g_fdd_rfsimulator/docker-compose.yaml
@@ -3,7 +3,7 @@
services:
mysql:
container_name: "rfsim5g-mysql"
- image: mysql:8.0
+ image: mysql:9.6
init: true
volumes:
- ../5g_rfsimulator/oai_db.sql:/docker-entrypoint-initdb.d/oai_db.sql
@@ -26,7 +26,7 @@ services:
ipv4_address: 192.168.71.131
oai-amf:
container_name: "rfsim5g-oai-amf"
- image: oaisoftwarealliance/oai-amf:v2.1.10
+ image: oaisoftwarealliance/oai-amf:v2.2.1
environment:
- TZ=Europe/paris
volumes:
@@ -38,7 +38,7 @@ services:
ipv4_address: 192.168.71.132
oai-smf:
container_name: "rfsim5g-oai-smf"
- image: oaisoftwarealliance/oai-smf:v2.1.10
+ image: oaisoftwarealliance/oai-smf:v2.2.1
environment:
- TZ=Europe/Paris
volumes:
@@ -50,7 +50,7 @@ services:
ipv4_address: 192.168.71.133
oai-upf:
container_name: "rfsim5g-oai-upf"
- image: oaisoftwarealliance/oai-upf:v2.1.10
+ image: oaisoftwarealliance/oai-upf:v2.2.1
init: true
environment:
- TZ=Europe/Paris
@@ -74,7 +74,7 @@ services:
oai-ext-dn:
privileged: true
container_name: rfsim5g-oai-ext-dn
- image: oaisoftwarealliance/trf-gen-cn5g:focal
+ image: oaisoftwarealliance/trf-gen-cn5g:latest
init: true
entrypoint: /bin/bash -c \
"iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE;"\
diff --git a/ci-scripts/yaml_files/5g_rfsimulator/README.md b/ci-scripts/yaml_files/5g_rfsimulator/README.md
index d2ef888771..6090b4b918 100644
--- a/ci-scripts/yaml_files/5g_rfsimulator/README.md
+++ b/ci-scripts/yaml_files/5g_rfsimulator/README.md
@@ -38,11 +38,11 @@ Password:
Now pull images.
```bash
-$ docker pull mysql:8.0
-$ docker pull oaisoftwarealliance/oai-amf:v2.1.10
-$ docker pull oaisoftwarealliance/oai-smf:v2.1.10
-$ docker pull oaisoftwarealliance/oai-upf:v2.1.10
-$ docker pull oaisoftwarealliance/trf-gen-cn5g:focal
+$ docker pull mysql:9.6
+$ docker pull oaisoftwarealliance/oai-amf:v2.2.1
+$ docker pull oaisoftwarealliance/oai-smf:v2.2.1
+$ docker pull oaisoftwarealliance/oai-upf:v2.2.1
+$ docker pull oaisoftwarealliance/trf-gen-cn5g:latest
$ docker pull oaisoftwarealliance/oai-gnb:develop
$ docker pull oaisoftwarealliance/oai-nr-ue:develop
@@ -570,7 +570,7 @@ runs the gnb service with modified gNB executable.
```bash
docker compose -f docker-compose.yaml -f local-override.yaml up -d oai-gnb
```
-This command rebuilds both the gNB & nrUE and runs the oai-nr-ue container with
+This command rebuilds both the gNB & nrUE and runs the oai-nr-ue container with
modified nrUE executable.
```bash
docker compose -f docker-compose.yaml -f local-override.yaml up -d oai-nr-ue
diff --git a/ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml
index cf7d5b5f85..a668adc840 100644
--- a/ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml
+++ b/ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml
@@ -3,7 +3,7 @@
services:
mysql:
container_name: "rfsim5g-mysql"
- image: mysql:8.0
+ image: mysql:9.6
init: true
volumes:
- ./oai_db.sql:/docker-entrypoint-initdb.d/oai_db.sql
@@ -26,7 +26,7 @@ services:
ipv4_address: 192.168.71.131
oai-amf:
container_name: "rfsim5g-oai-amf"
- image: oaisoftwarealliance/oai-amf:v2.1.10
+ image: oaisoftwarealliance/oai-amf:v2.2.1
environment:
- TZ=Europe/paris
volumes:
@@ -38,7 +38,7 @@ services:
ipv4_address: 192.168.71.132
oai-smf:
container_name: "rfsim5g-oai-smf"
- image: oaisoftwarealliance/oai-smf:v2.1.10
+ image: oaisoftwarealliance/oai-smf:v2.2.1
environment:
- TZ=Europe/Paris
volumes:
@@ -50,7 +50,7 @@ services:
ipv4_address: 192.168.71.133
oai-upf:
container_name: "rfsim5g-oai-upf"
- image: oaisoftwarealliance/oai-upf:v2.1.10
+ image: oaisoftwarealliance/oai-upf:v2.2.1
init: true
environment:
- TZ=Europe/Paris
@@ -74,7 +74,7 @@ services:
oai-ext-dn:
privileged: true
container_name: rfsim5g-oai-ext-dn
- image: oaisoftwarealliance/trf-gen-cn5g:focal
+ image: oaisoftwarealliance/trf-gen-cn5g:latest
init: true
entrypoint: /bin/bash -c \
"iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE;"\
diff --git a/ci-scripts/yaml_files/5g_rfsimulator_24prb/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_24prb/docker-compose.yaml
index 299ebbc543..0ae419fb4c 100644
--- a/ci-scripts/yaml_files/5g_rfsimulator_24prb/docker-compose.yaml
+++ b/ci-scripts/yaml_files/5g_rfsimulator_24prb/docker-compose.yaml
@@ -3,7 +3,7 @@
services:
mysql:
container_name: "rfsim5g-mysql"
- image: mysql:8.0
+ image: mysql:9.6
init: true
volumes:
- ../5g_rfsimulator/oai_db.sql:/docker-entrypoint-initdb.d/oai_db.sql
@@ -26,7 +26,7 @@ services:
ipv4_address: 192.168.71.131
oai-amf:
container_name: "rfsim5g-oai-amf"
- image: oaisoftwarealliance/oai-amf:v2.1.10
+ image: oaisoftwarealliance/oai-amf:v2.2.1
environment:
- TZ=Europe/paris
volumes:
@@ -38,7 +38,7 @@ services:
ipv4_address: 192.168.71.132
oai-smf:
container_name: "rfsim5g-oai-smf"
- image: oaisoftwarealliance/oai-smf:v2.1.10
+ image: oaisoftwarealliance/oai-smf:v2.2.1
environment:
- TZ=Europe/Paris
volumes:
@@ -50,7 +50,7 @@ services:
ipv4_address: 192.168.71.133
oai-upf:
container_name: "rfsim5g-oai-upf"
- image: oaisoftwarealliance/oai-upf:v2.1.10
+ image: oaisoftwarealliance/oai-upf:v2.2.1
init: true
environment:
- TZ=Europe/Paris
@@ -74,7 +74,7 @@ services:
oai-ext-dn:
privileged: true
container_name: rfsim5g-oai-ext-dn
- image: oaisoftwarealliance/trf-gen-cn5g:focal
+ image: oaisoftwarealliance/trf-gen-cn5g:latest
init: true
entrypoint: /bin/bash -c \
"iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE;"\
diff --git a/ci-scripts/yaml_files/5g_rfsimulator_2x2/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_2x2/docker-compose.yaml
index 8b4c02da2e..d22850b214 100644
--- a/ci-scripts/yaml_files/5g_rfsimulator_2x2/docker-compose.yaml
+++ b/ci-scripts/yaml_files/5g_rfsimulator_2x2/docker-compose.yaml
@@ -3,7 +3,7 @@
services:
mysql:
container_name: "rfsim5g-mysql"
- image: mysql:8.0
+ image: mysql:9.6
init: true
volumes:
- ../5g_rfsimulator/oai_db.sql:/docker-entrypoint-initdb.d/oai_db.sql
@@ -26,7 +26,7 @@ services:
ipv4_address: 192.168.71.131
oai-amf:
container_name: "rfsim5g-oai-amf"
- image: oaisoftwarealliance/oai-amf:v2.1.10
+ image: oaisoftwarealliance/oai-amf:v2.2.1
environment:
- TZ=Europe/paris
volumes:
@@ -38,7 +38,7 @@ services:
ipv4_address: 192.168.71.132
oai-smf:
container_name: "rfsim5g-oai-smf"
- image: oaisoftwarealliance/oai-smf:v2.1.10
+ image: oaisoftwarealliance/oai-smf:v2.2.1
environment:
- TZ=Europe/Paris
volumes:
@@ -50,7 +50,7 @@ services:
ipv4_address: 192.168.71.133
oai-upf:
container_name: "rfsim5g-oai-upf"
- image: oaisoftwarealliance/oai-upf:v2.1.10
+ image: oaisoftwarealliance/oai-upf:v2.2.1
init: true
environment:
- TZ=Europe/Paris
@@ -74,7 +74,7 @@ services:
oai-ext-dn:
privileged: true
container_name: rfsim5g-oai-ext-dn
- image: oaisoftwarealliance/trf-gen-cn5g:focal
+ image: oaisoftwarealliance/trf-gen-cn5g:latest
init: true
entrypoint: /bin/bash -c \
"iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE;"\
diff --git a/ci-scripts/yaml_files/5g_rfsimulator_e1/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_e1/docker-compose.yaml
index 0f03a33c82..a78f2ef897 100644
--- a/ci-scripts/yaml_files/5g_rfsimulator_e1/docker-compose.yaml
+++ b/ci-scripts/yaml_files/5g_rfsimulator_e1/docker-compose.yaml
@@ -3,7 +3,7 @@
services:
mysql:
container_name: "rfsim5g-mysql"
- image: mysql:8.0
+ image: mysql:9.6
init: true
volumes:
- ../5g_rfsimulator/oai_db.sql:/docker-entrypoint-initdb.d/oai_db.sql
@@ -26,7 +26,7 @@ services:
ipv4_address: 192.168.71.131
oai-amf:
container_name: "rfsim5g-oai-amf"
- image: oaisoftwarealliance/oai-amf:v2.1.10
+ image: oaisoftwarealliance/oai-amf:v2.2.1
environment:
- TZ=Europe/paris
volumes:
@@ -38,7 +38,7 @@ services:
ipv4_address: 192.168.71.132
oai-smf:
container_name: "rfsim5g-oai-smf"
- image: oaisoftwarealliance/oai-smf:v2.1.10
+ image: oaisoftwarealliance/oai-smf:v2.2.1
environment:
- TZ=Europe/Paris
volumes:
@@ -50,7 +50,7 @@ services:
ipv4_address: 192.168.71.133
oai-upf:
container_name: "rfsim5g-oai-upf"
- image: oaisoftwarealliance/oai-upf:v2.1.10
+ image: oaisoftwarealliance/oai-upf:v2.2.1
init: true
environment:
- TZ=Europe/Paris
diff --git a/ci-scripts/yaml_files/5g_rfsimulator_fr2_66prb/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_fr2_66prb/docker-compose.yaml
index 9ed90c8b2d..b27cd57a06 100644
--- a/ci-scripts/yaml_files/5g_rfsimulator_fr2_66prb/docker-compose.yaml
+++ b/ci-scripts/yaml_files/5g_rfsimulator_fr2_66prb/docker-compose.yaml
@@ -3,7 +3,7 @@
services:
mysql:
container_name: "rfsim5g-mysql"
- image: mysql:8.0
+ image: mysql:9.6
init: true
volumes:
- ../5g_rfsimulator/oai_db.sql:/docker-entrypoint-initdb.d/oai_db.sql
@@ -26,7 +26,7 @@ services:
ipv4_address: 192.168.71.131
oai-amf:
container_name: "rfsim5g-oai-amf"
- image: oaisoftwarealliance/oai-amf:v2.1.10
+ image: oaisoftwarealliance/oai-amf:v2.2.1
environment:
- TZ=Europe/paris
volumes:
@@ -38,7 +38,7 @@ services:
ipv4_address: 192.168.71.132
oai-smf:
container_name: "rfsim5g-oai-smf"
- image: oaisoftwarealliance/oai-smf:v2.1.10
+ image: oaisoftwarealliance/oai-smf:v2.2.1
environment:
- TZ=Europe/Paris
volumes:
@@ -50,7 +50,7 @@ services:
ipv4_address: 192.168.71.133
oai-upf:
container_name: "rfsim5g-oai-upf"
- image: oaisoftwarealliance/oai-upf:v2.1.10
+ image: oaisoftwarealliance/oai-upf:v2.2.1
init: true
environment:
- TZ=Europe/Paris
@@ -74,7 +74,7 @@ services:
oai-ext-dn:
privileged: true
container_name: rfsim5g-oai-ext-dn
- image: oaisoftwarealliance/trf-gen-cn5g:focal
+ image: oaisoftwarealliance/trf-gen-cn5g:latest
init: true
entrypoint: /bin/bash -c \
"iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE;"\
diff --git a/ci-scripts/yaml_files/5g_rfsimulator_multiue/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_multiue/docker-compose.yaml
index 5e376f650e..313d36bbfb 100644
--- a/ci-scripts/yaml_files/5g_rfsimulator_multiue/docker-compose.yaml
+++ b/ci-scripts/yaml_files/5g_rfsimulator_multiue/docker-compose.yaml
@@ -3,7 +3,7 @@
services:
mysql:
container_name: "rfsim5g-mysql"
- image: mysql:8.0
+ image: mysql:9.6
volumes:
- ../5g_rfsimulator/oai_db.sql:/docker-entrypoint-initdb.d/oai_db.sql
- ../5g_rfsimulator/mysql-healthcheck.sh:/tmp/mysql-healthcheck.sh
@@ -23,7 +23,7 @@ services:
ipv4_address: 192.168.71.131
oai-amf:
container_name: "rfsim5g-oai-amf"
- image: oaisoftwarealliance/oai-amf:v2.1.10
+ image: oaisoftwarealliance/oai-amf:v2.2.1
environment:
- TZ=Europe/paris
volumes:
@@ -35,7 +35,7 @@ services:
ipv4_address: 192.168.71.132
oai-smf:
container_name: "rfsim5g-oai-smf"
- image: oaisoftwarealliance/oai-smf:v2.1.10
+ image: oaisoftwarealliance/oai-smf:v2.2.1
environment:
- TZ=Europe/Paris
volumes:
@@ -47,7 +47,7 @@ services:
ipv4_address: 192.168.71.133
oai-upf:
container_name: "rfsim5g-oai-upf"
- image: oaisoftwarealliance/oai-upf:v2.1.10
+ image: oaisoftwarealliance/oai-upf:v2.2.1
environment:
- TZ=Europe/Paris
volumes:
@@ -70,7 +70,7 @@ services:
oai-ext-dn:
privileged: true
container_name: rfsim5g-oai-ext-dn
- image: oaisoftwarealliance/trf-gen-cn5g:focal
+ image: oaisoftwarealliance/trf-gen-cn5g:latest
entrypoint: /bin/bash -c \
"iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE;"\
"ip route add 12.1.1.0/24 via 192.168.72.134 dev eth0; sleep infinity"
diff --git a/ci-scripts/yaml_files/5g_rfsimulator_n2_ho/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_n2_ho/docker-compose.yaml
index 9fe4bdc25f..5e11c8cb3c 100644
--- a/ci-scripts/yaml_files/5g_rfsimulator_n2_ho/docker-compose.yaml
+++ b/ci-scripts/yaml_files/5g_rfsimulator_n2_ho/docker-compose.yaml
@@ -3,7 +3,7 @@
services:
mysql:
container_name: "rfsim5g-mysql"
- image: mysql:8.0
+ image: mysql:9.6
volumes:
- ../5g_rfsimulator/oai_db.sql:/docker-entrypoint-initdb.d/oai_db.sql
- ../5g_rfsimulator/mysql-healthcheck.sh:/tmp/mysql-healthcheck.sh
@@ -23,7 +23,7 @@ services:
ipv4_address: 192.168.71.131
oai-amf:
container_name: "rfsim5g-oai-amf"
- image: oaisoftwarealliance/oai-amf:ci-tmp-pr-372-26c14bcd
+ image: oaisoftwarealliance/oai-amf:v2.2.1
environment:
- TZ=Europe/paris
volumes:
@@ -35,7 +35,7 @@ services:
ipv4_address: 192.168.71.132
oai-smf:
container_name: "rfsim5g-oai-smf"
- image: oaisoftwarealliance/oai-smf:v2.1.9
+ image: oaisoftwarealliance/oai-smf:v2.2.1
environment:
- TZ=Europe/Paris
volumes:
@@ -47,7 +47,7 @@ services:
ipv4_address: 192.168.71.133
oai-upf:
container_name: "rfsim5g-oai-upf"
- image: oaisoftwarealliance/oai-upf:v2.1.9
+ image: oaisoftwarealliance/oai-upf:v2.2.1
environment:
- TZ=Europe/Paris
volumes:
@@ -70,7 +70,7 @@ services:
oai-ext-dn:
privileged: true
container_name: rfsim5g-oai-ext-dn
- image: oaisoftwarealliance/trf-gen-cn5g:focal
+ image: oaisoftwarealliance/trf-gen-cn5g:latest
entrypoint: /bin/bash -c \
"iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE;"\
"ip route add 12.1.1.0/24 via 192.168.72.134 dev eth0; sleep infinity"
diff --git a/ci-scripts/yaml_files/5g_rfsimulator_ntn_geo/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_ntn_geo/docker-compose.yaml
index 785402c3f7..42899ae248 100644
--- a/ci-scripts/yaml_files/5g_rfsimulator_ntn_geo/docker-compose.yaml
+++ b/ci-scripts/yaml_files/5g_rfsimulator_ntn_geo/docker-compose.yaml
@@ -3,7 +3,7 @@
services:
mysql:
container_name: "rfsim5g-mysql"
- image: mysql:8.0
+ image: mysql:9.6
init: true
volumes:
- ../5g_rfsimulator/oai_db.sql:/docker-entrypoint-initdb.d/oai_db.sql
@@ -26,7 +26,7 @@ services:
ipv4_address: 192.168.71.131
oai-amf:
container_name: "rfsim5g-oai-amf"
- image: oaisoftwarealliance/oai-amf:v2.1.10
+ image: oaisoftwarealliance/oai-amf:v2.2.1
environment:
- TZ=Europe/paris
volumes:
@@ -38,7 +38,7 @@ services:
ipv4_address: 192.168.71.132
oai-smf:
container_name: "rfsim5g-oai-smf"
- image: oaisoftwarealliance/oai-smf:v2.1.10
+ image: oaisoftwarealliance/oai-smf:v2.2.1
environment:
- TZ=Europe/Paris
volumes:
@@ -50,7 +50,7 @@ services:
ipv4_address: 192.168.71.133
oai-upf:
container_name: "rfsim5g-oai-upf"
- image: oaisoftwarealliance/oai-upf:v2.1.10
+ image: oaisoftwarealliance/oai-upf:v2.2.1
init: true
environment:
- TZ=Europe/Paris
@@ -74,7 +74,7 @@ services:
oai-ext-dn:
privileged: true
container_name: rfsim5g-oai-ext-dn
- image: oaisoftwarealliance/trf-gen-cn5g:focal
+ image: oaisoftwarealliance/trf-gen-cn5g:latest
init: true
entrypoint: /bin/bash -c \
"iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE;"\
diff --git a/ci-scripts/yaml_files/5g_rfsimulator_ntn_leo/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_ntn_leo/docker-compose.yaml
index fd57881969..c7343e9a25 100644
--- a/ci-scripts/yaml_files/5g_rfsimulator_ntn_leo/docker-compose.yaml
+++ b/ci-scripts/yaml_files/5g_rfsimulator_ntn_leo/docker-compose.yaml
@@ -3,7 +3,7 @@
services:
mysql:
container_name: "rfsim5g-mysql"
- image: mysql:8.0
+ image: mysql:9.6
volumes:
- ../5g_rfsimulator/oai_db.sql:/docker-entrypoint-initdb.d/oai_db.sql
- ../5g_rfsimulator/mysql-healthcheck.sh:/tmp/mysql-healthcheck.sh
@@ -25,7 +25,7 @@ services:
ipv4_address: 192.168.71.131
oai-amf:
container_name: "rfsim5g-oai-amf"
- image: oaisoftwarealliance/oai-amf:v2.1.10
+ image: oaisoftwarealliance/oai-amf:v2.2.1
environment:
- TZ=Europe/paris
volumes:
@@ -37,7 +37,7 @@ services:
ipv4_address: 192.168.71.132
oai-smf:
container_name: "rfsim5g-oai-smf"
- image: oaisoftwarealliance/oai-smf:v2.1.10
+ image: oaisoftwarealliance/oai-smf:v2.2.1
environment:
- TZ=Europe/Paris
volumes:
@@ -49,7 +49,7 @@ services:
ipv4_address: 192.168.71.133
oai-upf:
container_name: "rfsim5g-oai-upf"
- image: oaisoftwarealliance/oai-upf:v2.1.10
+ image: oaisoftwarealliance/oai-upf:v2.2.1
environment:
- TZ=Europe/Paris
volumes:
@@ -72,7 +72,7 @@ services:
oai-ext-dn:
privileged: true
container_name: rfsim5g-oai-ext-dn
- image: oaisoftwarealliance/trf-gen-cn5g:focal
+ image: oaisoftwarealliance/trf-gen-cn5g:latest
entrypoint: /bin/bash -c \
"iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE;"\
"ip route add 12.1.1.0/24 via 192.168.72.134 dev eth0; sleep infinity"
diff --git a/ci-scripts/yaml_files/5g_rfsimulator_u0_25prb/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_u0_25prb/docker-compose.yaml
index 581c2362fe..60ca044f94 100644
--- a/ci-scripts/yaml_files/5g_rfsimulator_u0_25prb/docker-compose.yaml
+++ b/ci-scripts/yaml_files/5g_rfsimulator_u0_25prb/docker-compose.yaml
@@ -3,7 +3,7 @@
services:
mysql:
container_name: "rfsim5g-mysql"
- image: mysql:8.0
+ image: mysql:9.6
init: true
volumes:
- ../5g_rfsimulator/oai_db.sql:/docker-entrypoint-initdb.d/oai_db.sql
@@ -26,7 +26,7 @@ services:
ipv4_address: 192.168.71.131
oai-amf:
container_name: "rfsim5g-oai-amf"
- image: oaisoftwarealliance/oai-amf:v2.1.10
+ image: oaisoftwarealliance/oai-amf:v2.2.1
environment:
- TZ=Europe/paris
volumes:
@@ -38,7 +38,7 @@ services:
ipv4_address: 192.168.71.132
oai-smf:
container_name: "rfsim5g-oai-smf"
- image: oaisoftwarealliance/oai-smf:v2.1.10
+ image: oaisoftwarealliance/oai-smf:v2.2.1
environment:
- TZ=Europe/Paris
volumes:
@@ -50,7 +50,7 @@ services:
ipv4_address: 192.168.71.133
oai-upf:
container_name: "rfsim5g-oai-upf"
- image: oaisoftwarealliance/oai-upf:v2.1.10
+ image: oaisoftwarealliance/oai-upf:v2.2.1
init: true
environment:
- TZ=Europe/Paris
@@ -74,7 +74,7 @@ services:
oai-ext-dn:
privileged: true
container_name: rfsim5g-oai-ext-dn
- image: oaisoftwarealliance/trf-gen-cn5g:focal
+ image: oaisoftwarealliance/trf-gen-cn5g:latest
init: true
entrypoint: /bin/bash -c \
"iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE;"\
diff --git a/ci-scripts/yaml_files/5g_vrtsim_chanmod/docker-compose.yaml b/ci-scripts/yaml_files/5g_vrtsim_chanmod/docker-compose.yaml
index 357444be73..85303fe749 100644
--- a/ci-scripts/yaml_files/5g_vrtsim_chanmod/docker-compose.yaml
+++ b/ci-scripts/yaml_files/5g_vrtsim_chanmod/docker-compose.yaml
@@ -3,7 +3,7 @@
services:
mysql:
container_name: "rfsim5g-mysql"
- image: mysql:8.0
+ image: mysql:9.6
init: true
volumes:
- ../5g_rfsimulator/oai_db.sql:/docker-entrypoint-initdb.d/oai_db.sql
@@ -26,7 +26,7 @@ services:
ipv4_address: 192.168.71.131
oai-amf:
container_name: "rfsim5g-oai-amf"
- image: oaisoftwarealliance/oai-amf:v2.1.10
+ image: oaisoftwarealliance/oai-amf:v2.2.1
environment:
- TZ=Europe/paris
volumes:
@@ -38,7 +38,7 @@ services:
ipv4_address: 192.168.71.132
oai-smf:
container_name: "rfsim5g-oai-smf"
- image: oaisoftwarealliance/oai-smf:v2.1.10
+ image: oaisoftwarealliance/oai-smf:v2.2.1
environment:
- TZ=Europe/Paris
volumes:
@@ -50,7 +50,7 @@ services:
ipv4_address: 192.168.71.133
oai-upf:
container_name: "rfsim5g-oai-upf"
- image: oaisoftwarealliance/oai-upf:v2.1.10
+ image: oaisoftwarealliance/oai-upf:v2.2.1
init: true
environment:
- TZ=Europe/Paris
diff --git a/ci-scripts/yaml_files/5g_vrtsim_cirdb/docker-compose.yaml b/ci-scripts/yaml_files/5g_vrtsim_cirdb/docker-compose.yaml
index 183c244018..7ab1020d01 100644
--- a/ci-scripts/yaml_files/5g_vrtsim_cirdb/docker-compose.yaml
+++ b/ci-scripts/yaml_files/5g_vrtsim_cirdb/docker-compose.yaml
@@ -12,7 +12,7 @@ services:
mysql:
container_name: "rfsim5g-mysql"
- image: mysql:8.0
+ image: mysql:9.6
init: true
volumes:
- ../5g_rfsimulator/oai_db.sql:/docker-entrypoint-initdb.d/oai_db.sql
@@ -36,7 +36,7 @@ services:
oai-amf:
container_name: "rfsim5g-oai-amf"
- image: oaisoftwarealliance/oai-amf:v2.1.10
+ image: oaisoftwarealliance/oai-amf:v2.2.1
environment:
- TZ=Europe/paris
volumes:
@@ -49,7 +49,7 @@ services:
oai-smf:
container_name: "rfsim5g-oai-smf"
- image: oaisoftwarealliance/oai-smf:v2.1.10
+ image: oaisoftwarealliance/oai-smf:v2.2.1
environment:
- TZ=Europe/Paris
volumes:
@@ -62,7 +62,7 @@ services:
oai-upf:
container_name: "rfsim5g-oai-upf"
- image: oaisoftwarealliance/oai-upf:v2.1.10
+ image: oaisoftwarealliance/oai-upf:v2.2.1
init: true
environment:
- TZ=Europe/Paris
diff --git a/ci-scripts/yaml_files/5g_vrtsim_multiue/docker-compose.yaml b/ci-scripts/yaml_files/5g_vrtsim_multiue/docker-compose.yaml
index 49f2e9a4cc..349c61ff24 100644
--- a/ci-scripts/yaml_files/5g_vrtsim_multiue/docker-compose.yaml
+++ b/ci-scripts/yaml_files/5g_vrtsim_multiue/docker-compose.yaml
@@ -12,7 +12,7 @@ services:
mysql:
container_name: "rfsim5g-mysql"
- image: mysql:8.0
+ image: mysql:9.6
init: true
volumes:
- ../5g_rfsimulator/oai_db.sql:/docker-entrypoint-initdb.d/oai_db.sql
@@ -36,7 +36,7 @@ services:
oai-amf:
container_name: "rfsim5g-oai-amf"
- image: oaisoftwarealliance/oai-amf:v2.1.10
+ image: oaisoftwarealliance/oai-amf:v2.2.1
environment:
- TZ=Europe/paris
volumes:
@@ -49,7 +49,7 @@ services:
oai-smf:
container_name: "rfsim5g-oai-smf"
- image: oaisoftwarealliance/oai-smf:v2.1.10
+ image: oaisoftwarealliance/oai-smf:v2.2.1
environment:
- TZ=Europe/Paris
volumes:
@@ -62,7 +62,7 @@ services:
oai-upf:
container_name: "rfsim5g-oai-upf"
- image: oaisoftwarealliance/oai-upf:v2.1.10
+ image: oaisoftwarealliance/oai-upf:v2.2.1
init: true
environment:
- TZ=Europe/Paris
diff --git a/ci-scripts/yaml_files/fr1_epc_20897/docker-compose.yml b/ci-scripts/yaml_files/fr1_epc_20897/docker-compose.yml
index ee1f5c2110..3ab53378d9 100644
--- a/ci-scripts/yaml_files/fr1_epc_20897/docker-compose.yml
+++ b/ci-scripts/yaml_files/fr1_epc_20897/docker-compose.yml
@@ -184,7 +184,7 @@ services:
retries: 5
trf_gen:
- image: oaisoftwarealliance/trf-gen-cn5g:focal
+ image: oaisoftwarealliance/trf-gen-cn5g:latest
privileged: true
container_name: prod-trf-gen
networks:
diff --git a/ci-scripts/yaml_files/magma_lte_20892/docker-compose.yml b/ci-scripts/yaml_files/magma_lte_20892/docker-compose.yml
index d025588de7..535561be8c 100644
--- a/ci-scripts/yaml_files/magma_lte_20892/docker-compose.yml
+++ b/ci-scripts/yaml_files/magma_lte_20892/docker-compose.yml
@@ -168,7 +168,7 @@ services:
retries: 5
trf_gen:
- image: oaisoftwarealliance/trf-gen-cn5g:focal
+ image: oaisoftwarealliance/trf-gen-cn5g:latest
privileged: true
container_name: prod-trf-gen
networks:
diff --git a/ci-scripts/yaml_files/magma_nsa_20897/docker-compose.yml b/ci-scripts/yaml_files/magma_nsa_20897/docker-compose.yml
index 636f416bfb..5005a53de3 100644
--- a/ci-scripts/yaml_files/magma_nsa_20897/docker-compose.yml
+++ b/ci-scripts/yaml_files/magma_nsa_20897/docker-compose.yml
@@ -168,7 +168,7 @@ services:
retries: 5
trf_gen:
- image: oaisoftwarealliance/trf-gen-cn5g:focal
+ image: oaisoftwarealliance/trf-gen-cn5g:latest
privileged: true
container_name: prod-trf-gen
networks:
diff --git a/common/config/config_paramdesc.h b/common/config/config_paramdesc.h
index 51c8626116..efb5c956d2 100644
--- a/common/config/config_paramdesc.h
+++ b/common/config/config_paramdesc.h
@@ -48,8 +48,8 @@ typedef union checkedparam {
int num_okintval; /* number of valid values in the checkingval array */
} s1a;
struct {
- int (*f2)(configmodule_interface_t *cfg,
- paramdef_t *param); /* check an integer against an authorized range, defined by its min and max value */
+ int (*f2)(const configmodule_interface_t *cfg,
+ const paramdef_t *param); /* check an integer against an authorized range, defined by its min and max value */
int okintrange[CONFIG_MAX_NUMCHECKVAL]; /* integer array, store min and max values */
} s2;
diff --git a/common/config/config_userapi.c b/common/config/config_userapi.c
index 76f9722d0a..c009187800 100644
--- a/common/config/config_userapi.c
+++ b/common/config/config_userapi.c
@@ -183,14 +183,35 @@ int config_check_intval(configmodule_interface_t *cfg, paramdef_t *param)
return -1;
}
- for ( int i=0; ichkPptr->s1.num_okintval ; i++) {
- if( *(param->uptr) == param->chkPptr->s1.okintval[i] ) {
- return 0;
+ if (param->type == TYPE_INT32 || param->type == TYPE_INT) {
+ if (param->iptr == NULL) {
+ fprintf(stderr, "[CONFIG] config_check_intval: %s: NULL iptr\n", param->optname);
+ return -1;
}
+ const int v = *param->iptr;
+ for (int i = 0; i < param->chkPptr->s1.num_okintval; i++) {
+ if (v == param->chkPptr->s1.okintval[i])
+ return 0;
+ }
+ fprintf(stderr, "[CONFIG] config_check_intval: %s: %i invalid value, authorized values:\n ", param->optname, v);
+ for (int i = 0; i < param->chkPptr->s1.num_okintval; i++) {
+ fprintf(stderr, " %i", param->chkPptr->s1.okintval[i]);
+ }
+ fprintf(stderr, " \n");
+ return -1;
+ } else {
+ if (param->uptr == NULL) {
+ fprintf(stderr, "[CONFIG] config_check_intval: %s: NULL uptr\n", param->optname);
+ return -1;
+ }
+ for (int i = 0; i < param->chkPptr->s1.num_okintval; i++) {
+ if (*(param->uptr) == (uint32_t)param->chkPptr->s1.okintval[i]) {
+ return 0;
+ }
+ }
+ print_intvalueerror(param, "config_check_intval", param->chkPptr->s1.okintval, param->chkPptr->s1.num_okintval);
+ return -1;
}
-
- print_intvalueerror(param,"config_check_intval", param->chkPptr->s1.okintval,param->chkPptr->s1.num_okintval);
- return -1;
}
int config_check_modify_integer(configmodule_interface_t *cfg, paramdef_t *param)
@@ -211,15 +232,38 @@ int config_check_modify_integer(configmodule_interface_t *cfg, paramdef_t *param
return -1;
}
-int config_check_intrange(configmodule_interface_t *cfg, paramdef_t *param)
+int config_check_intrange(const configmodule_interface_t *cfg, const paramdef_t *param)
{
UNUSED(cfg);
if( *(param->iptr) >= param->chkPptr->s2.okintrange[0] && *(param->iptr) <= param->chkPptr->s2.okintrange[1] ) {
return 0;
}
- fprintf(stderr,"[CONFIG] config_check_intrange: %s: %i invalid value, authorized range: %i %i\n",
- param->optname, (int)*(param->uptr), param->chkPptr->s2.okintrange[0], param->chkPptr->s2.okintrange[1]);
+ fprintf(stderr,
+ "[CONFIG] config_check_intrange: %s: %i invalid value, authorized range: %i %i\n",
+ param->optname,
+ (int)*(param->iptr),
+ param->chkPptr->s2.okintrange[0],
+ param->chkPptr->s2.okintrange[1]);
+ return -1;
+}
+
+int config_check_uintrange(const configmodule_interface_t *cfg, const paramdef_t *param)
+{
+ (void)cfg;
+ const uint32_t *v = param->uptr;
+ const int *range = param->chkPptr->s2.okintrange;
+
+ if (*v >= (uint32_t)range[0] && *v <= (uint32_t)range[1]) {
+ return 0;
+ }
+
+ fprintf(stderr,
+ "[CONFIG] config_check_uintrange: %s: %u invalid, authorized range: %i %i\n",
+ param->optname,
+ *v,
+ range[0],
+ range[1]);
return -1;
}
diff --git a/common/config/config_userapi.h b/common/config/config_userapi.h
index fafbd81019..b959cb57fe 100644
--- a/common/config/config_userapi.h
+++ b/common/config/config_userapi.h
@@ -51,7 +51,8 @@ int config_get_processedint(configmodule_interface_t *cfg, paramdef_t *cfgoption
/* functions to be used in parameters definition, to check parameters values */
int config_check_intval(configmodule_interface_t *cfg, paramdef_t *param);
int config_check_modify_integer(configmodule_interface_t *cfg, paramdef_t *param);
-int config_check_intrange(configmodule_interface_t *cfg, paramdef_t *param);
+int config_check_intrange(const configmodule_interface_t *cfg, const paramdef_t *param);
+int config_check_uintrange(const configmodule_interface_t *cfg, const paramdef_t *param);
int config_check_strval(configmodule_interface_t *cfg, paramdef_t *param);
int config_checkstr_assign_integer(configmodule_interface_t *cfg, paramdef_t *param);
const paramdef_t *config_get_paramdef_from_name(const paramdef_t *pd, int num, const char *name);
diff --git a/common/platform_constants.h b/common/platform_constants.h
index d7cf6f9ed6..26894fd82b 100644
--- a/common/platform_constants.h
+++ b/common/platform_constants.h
@@ -66,7 +66,6 @@
#define RETURNok (0)
#define RETURNerror (-1)
#define DEFAULT_NAS_PATH "PWD"
-#define UNUSED_VARIABLE(vARIABLE) (void)(vARIABLE)
#define NUM_PRACH_RX_FOR_NOISE_ESTIMATE 100
// SDAP
diff --git a/common/utils/CMakeLists.txt b/common/utils/CMakeLists.txt
index 3196b39868..fc113ffa46 100644
--- a/common/utils/CMakeLists.txt
+++ b/common/utils/CMakeLists.txt
@@ -16,7 +16,7 @@ add_subdirectory(nr)
add_subdirectory(LOG)
add_subdirectory(threadPool)
add_subdirectory(time_manager)
-add_library(utils utils.c system.c time_meas.c time_stat.c tuntap_if.c reverse_bits.c)
+add_library(utils utils.c system.c time_meas.c time_stat.c tuntap_if.c reverse_bits.c fsn.c)
target_include_directories(utils PUBLIC .)
target_link_libraries(utils PRIVATE ${T_LIB})
add_subdirectory(barrier)
diff --git a/common/utils/T/DOC/T/basic.md b/common/utils/T/DOC/T/basic.md
index 0103c30de7..ff54c7efc6 100644
--- a/common/utils/T/DOC/T/basic.md
+++ b/common/utils/T/DOC/T/basic.md
@@ -67,18 +67,26 @@ the T tracer and only output on the terminal). The default is
## Run a tracer
-Go into the directory `common/utils/T/tracer` (or
-`cmake_targets/ran_build/build/common/utils/T/tracer`) and run for example the
+Go into the directory `common/utils/T/tracer` and run for example the
`enb` tracer:
```shell
+#in common/utils/T/tracer directory
./enb -d ../T_messages.txt
```
+You can also run it from `cmake_targets/ran_build/build/` directory:
+
+```shell
+# in cmake_targets/ran_build/build directory
+./common/utils/T/tracer/enb -d ../../../common/utils/T/T_messages.txt
+```
+
To trace a remote program, use the `-ip` option. For example,
if you want to trace a program running on `192.168.12.148` do:
```shell
+# in common/utils/T/tracer directory
./enb -d ../T_messages.txt -ip 192.168.12.148
```
diff --git a/common/utils/T/DOC/T/record_db.md b/common/utils/T/DOC/T/record_db.md
index 2c3825252f..27444fa87c 100644
--- a/common/utils/T/DOC/T/record_db.md
+++ b/common/utils/T/DOC/T/record_db.md
@@ -44,6 +44,7 @@ Or, from an existing build directory using cmake:
```shell
cd cmake_targets/ran_build/build
cmake -DT_RECORD_DB=ON .
+# use make or ninja
make T_tools
```
@@ -53,6 +54,9 @@ The binary is then available in:
cmake_targets/ran_build/build/common/utils/T/tracer/record_db
```
+**NOTE*: Unlike other docs on T Tracer for `record_db` we are building in cmake
+directory rather than in the directory of T.
+
## Prerequisites
- a running ClickHouse server reachable from `record_db`
@@ -84,8 +88,8 @@ To enable all events except the most verbose groups and write them to
ClickHouse:
```shell
-cd cmake_targets/ran_build/build/common/utils/T/tracer
-./record_db -d ../T_messages.txt \
+cd cmake_targets/ran_build/build/
+./common/utils/T/tracer/record_db -d ../../../common/utils/T/T_messages.txt \
-ON \
-off VCD \
-off HEAVY \
@@ -108,7 +112,7 @@ The event selection rules are the same as for [`record`](./record.md):
These options are processed in order. For example:
```shell
-./record_db -d ../T_messages.txt -OFF -on GNB_PHY_UL_FD_PUSCH_IQ -on GNB_PHY_UL_PAYLOAD_RX_BITS
+./common/utils/T/tracer/record_db -d ../../../common/utils/T/T_messages.txt -OFF -on GNB_PHY_UL_FD_PUSCH_IQ -on GNB_PHY_UL_PAYLOAD_RX_BITS
```
This starts from everything disabled and enables only the two listed
diff --git a/common/utils/actor/actor.h b/common/utils/actor/actor.h
index 3d7760356c..d49bd88c65 100644
--- a/common/utils/actor/actor.h
+++ b/common/utils/actor/actor.h
@@ -4,7 +4,7 @@
#ifndef ACTOR_H
#define ACTOR_H
-#include "notified_fifo.h"
+#include "common/utils/threadPool/notified_fifo.h"
#define INIT_ACTOR(ptr, name, core_affinity) init_actor((Actor_t *)ptr, name, core_affinity);
diff --git a/common/utils/ds/CMakeLists.txt b/common/utils/ds/CMakeLists.txt
index 7007d77fac..6f7053a1be 100644
--- a/common/utils/ds/CMakeLists.txt
+++ b/common/utils/ds/CMakeLists.txt
@@ -6,6 +6,7 @@ add_library(ds OBJECT
seq_arr.c
hashtable.c
obj_hashtable.c
+ spsc_q.c
)
target_include_directories(ds PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
diff --git a/common/utils/ds/hashtable.c b/common/utils/ds/hashtable.c
index c84d332973..78a62f570c 100644
--- a/common/utils/ds/hashtable.c
+++ b/common/utils/ds/hashtable.c
@@ -10,36 +10,6 @@
#include "assertions.h"
-//-------------------------------------------------------------------------------------------------------------------------------
-char *hashtable_rc_code2string(hashtable_rc_t rcP)
-//-------------------------------------------------------------------------------------------------------------------------------
-{
- switch (rcP) {
- case HASH_TABLE_OK:
- return "HASH_TABLE_OK";
- break;
-
- case HASH_TABLE_INSERT_OVERWRITTEN_DATA:
- return "HASH_TABLE_INSERT_OVERWRITTEN_DATA";
- break;
-
- case HASH_TABLE_KEY_NOT_EXISTS:
- return "HASH_TABLE_KEY_NOT_EXISTS";
- break;
-
- case HASH_TABLE_KEY_ALREADY_EXISTS:
- return "HASH_TABLE_KEY_ALREADY_EXISTS";
- break;
-
- case HASH_TABLE_BAD_PARAMETER_HASHTABLE:
- return "HASH_TABLE_BAD_PARAMETER_HASHTABLE";
- break;
-
- default:
- return "UNKNOWN hashtable_rc_t";
- }
-}
-//-------------------------------------------------------------------------------------------------------------------------------
/*
* free int function
* hash_free_int_func() is used when this hashtable is used to store int values as data (pointer = value).
@@ -147,41 +117,6 @@ hashtable_rc_t hashtable_is_key_exists (const hash_table_t *const hashtblP, cons
return HASH_TABLE_KEY_NOT_EXISTS;
}
-//-------------------------------------------------------------------------------------------------------------------------------
-hashtable_rc_t hashtable_dump_content (const hash_table_t *const hashtblP, char *const buffer_pP, int *const remaining_bytes_in_buffer_pP )
-//-------------------------------------------------------------------------------------------------------------------------------
-{
- hash_node_t *node = NULL;
- unsigned int i = 0;
-
- if (hashtblP == NULL) {
- *remaining_bytes_in_buffer_pP = snprintf(
- buffer_pP,
- *remaining_bytes_in_buffer_pP,
- "HASH_TABLE_BAD_PARAMETER_HASHTABLE");
- return HASH_TABLE_BAD_PARAMETER_HASHTABLE;
- }
-
- while ((i < hashtblP->size) && (*remaining_bytes_in_buffer_pP > 0)) {
- if (hashtblP->nodes[i] != NULL) {
- node=hashtblP->nodes[i];
-
- while(node) {
- *remaining_bytes_in_buffer_pP = snprintf(
- buffer_pP,
- *remaining_bytes_in_buffer_pP,
- "Key 0x%"PRIx64" Element %p\n",
- node->key,
- node->data);
- node=node->next;
- }
- }
-
- i += 1;
- }
-
- return HASH_TABLE_OK;
-}
//-------------------------------------------------------------------------------------------------------------------------------
/*
diff --git a/common/utils/ds/hashtable.h b/common/utils/ds/hashtable.h
index ba43b0230f..fd8fe013c3 100644
--- a/common/utils/ds/hashtable.h
+++ b/common/utils/ds/hashtable.h
@@ -44,12 +44,10 @@ typedef struct hash_table_iterator_s {
const hash_table_t* const hashtbl;
} hash_table_iterator_s;
-char *hashtable_rc_code2string(hashtable_rc_t rcP);
void hash_free_int_func(void *memoryP);
hash_table_t *hashtable_create (const hash_size_t size, hash_size_t (*hashfunc)(const hash_key_t ), void (*freefunc)(void *));
hashtable_rc_t hashtable_destroy(hash_table_t **hashtbl);
hashtable_rc_t hashtable_is_key_exists (const hash_table_t *const hashtbl, const uint64_t key);
-hashtable_rc_t hashtable_dump_content (const hash_table_t *const hashtblP, char *const buffer_pP, int *const remaining_bytes_in_buffer_pP );
hashtable_rc_t hashtable_insert (hash_table_t *const hashtbl, const hash_key_t key, void *data);
hashtable_rc_t hashtable_remove (hash_table_t *const hashtbl, const hash_key_t key);
hashtable_rc_t hashtable_get (const hash_table_t *const hashtbl, const hash_key_t key, void **dataP);
diff --git a/common/utils/ds/spsc_q.c b/common/utils/ds/spsc_q.c
new file mode 100644
index 0000000000..6f05a19865
--- /dev/null
+++ b/common/utils/ds/spsc_q.c
@@ -0,0 +1,90 @@
+/*
+ * SPDX-License-Identifier: LicenseRef-CSSL-1.0
+ */
+
+#include
+#include
+#include
+
+#include "spsc_q.h"
+
+spsc_q_t spsc_q_alloc(size_t cnt, size_t elsiz)
+{
+ /* internally, use one element more: the ringbuffer is full if
+ * (write_idx + 1) % cnt == read_idx, so it's full if one element is still
+ * free (because otherwise write_idx == read_idx, but this is the empty
+ * condition) */
+ cnt += 1;
+ spsc_q_t rb = {.cnt = cnt, .elsiz = elsiz};
+ rb.buf = calloc(cnt, elsiz);
+ return rb;
+}
+
+void spsc_q_free(spsc_q_t *rb)
+{
+ free(rb->buf);
+ memset(rb, 0, sizeof(*rb));
+}
+
+bool spsc_q_put(spsc_q_t *rb, const void *src, size_t elsiz)
+{
+ assert(elsiz == rb->elsiz);
+ size_t w = atomic_load_explicit(&rb->write_idx, memory_order_relaxed);
+ size_t r = atomic_load_explicit(&rb->read_idx, memory_order_acquire);
+ if ((w + 1) % rb->cnt == r) {
+ return false;
+ }
+
+ uint8_t *bufpos = &rb->buf[w * rb->elsiz];
+ memcpy(bufpos, src, elsiz);
+ atomic_store_explicit(&rb->write_idx, (w + 1) % rb->cnt, memory_order_release);
+ return true;
+}
+
+bool spsc_q_get_if(spsc_q_t *rb, pred p, void *user, void *dest, size_t elsiz)
+{
+ assert(elsiz == rb->elsiz);
+ size_t w = atomic_load_explicit(&rb->write_idx, memory_order_acquire);
+ size_t r = atomic_load_explicit(&rb->read_idx, memory_order_relaxed);
+ if (w == r) {
+ return false;
+ }
+
+ uint8_t *bufpos = &rb->buf[rb->read_idx * rb->elsiz];
+ if (!p(bufpos, user)) {
+ return false;
+ }
+
+ if (dest)
+ memcpy(dest, bufpos, elsiz);
+ atomic_store_explicit(&rb->read_idx, (r + 1) % rb->cnt, memory_order_release);
+ return true;
+}
+
+static bool always(const void *data, void *user)
+{
+ (void) data;
+ (void) user;
+ return true;
+}
+bool spsc_q_get(spsc_q_t *rb, void *dest, size_t elsiz)
+{
+ return spsc_q_get_if(rb, always, NULL, dest, elsiz);
+}
+
+int spsc_q_get_while(spsc_q_t *rb, pred p, void *user, void *dest, size_t elsiz, size_t max_len)
+{
+ assert(elsiz == rb->elsiz);
+ size_t count = 0;
+ while (count < max_len && spsc_q_get_if(rb, p, user, dest + elsiz * count, elsiz))
+ count++;
+ return count;
+}
+
+int spsc_q_drop_while(spsc_q_t *rb, pred p, void *user)
+{
+ size_t dropped = 0;
+ while (spsc_q_get_if(rb, p, user, NULL, rb->elsiz))
+ dropped++;
+ return dropped;
+}
diff --git a/common/utils/ds/spsc_q.h b/common/utils/ds/spsc_q.h
new file mode 100644
index 0000000000..7fd968b2f0
--- /dev/null
+++ b/common/utils/ds/spsc_q.h
@@ -0,0 +1,37 @@
+/*
+ * SPDX-License-Identifier: LicenseRef-CSSL-1.0
+ */
+
+#ifndef SPSC_Q_H_
+#define SPSC_Q_H_
+
+#include
+#include
+#include
+
+#if defined(__cplusplus)
+// use atomic_size_t to help interworking with C++
+using std::atomic_size_t;
+#endif
+
+typedef struct spsc_q {
+ uint8_t *buf;
+ size_t elsiz;
+ size_t cnt;
+
+ atomic_size_t write_idx;
+ atomic_size_t read_idx;
+} spsc_q_t;
+
+spsc_q_t spsc_q_alloc(size_t cnt, size_t elsiz);
+void spsc_q_free(spsc_q_t *rb);
+
+bool spsc_q_put(spsc_q_t *rb, const void *src, size_t elsiz);
+bool spsc_q_get(spsc_q_t *rb, void *dest, size_t elsiz);
+
+typedef bool (*pred)(const void *data, void *user);
+bool spsc_q_get_if(spsc_q_t *rb, pred p, void *user, void *dest, size_t elsiz);
+int spsc_q_drop_while(spsc_q_t *rb, pred p, void *user);
+int spsc_q_get_while(spsc_q_t *rb, pred p, void *user, void *dest, size_t elsiz, size_t max_len);
+
+#endif /* SPSC_Q_H_ */
diff --git a/common/utils/ds/tests/CMakeLists.txt b/common/utils/ds/tests/CMakeLists.txt
index a38cf159cb..1a2e5277a1 100644
--- a/common/utils/ds/tests/CMakeLists.txt
+++ b/common/utils/ds/tests/CMakeLists.txt
@@ -8,5 +8,11 @@ add_test(NAME test_seq_arr COMMAND test_seq_arr) # no options required
add_executable(test_hashtable test_hashtable.cpp)
add_dependencies(tests test_hashtable)
target_link_libraries(test_hashtable PRIVATE ds GTest::gtest)
-add_test(NAME test_hashtable
- COMMAND ./test_hashtable)
+add_test(NAME test_hashtable COMMAND ./test_hashtable)
+
+add_executable(test_spsc_q test_spsc_q.cpp)
+target_link_libraries(test_spsc_q ds GTest::gtest)
+add_dependencies(tests test_spsc_q)
+add_test(NAME test_spsc_q COMMAND test_spsc_q)
+add_executable(test_spsc_q_perf test_spsc_q_perf.cpp)
+target_link_libraries(test_spsc_q_perf PRIVATE ds benchmark::benchmark)
diff --git a/common/utils/ds/tests/test_spsc_q.cpp b/common/utils/ds/tests/test_spsc_q.cpp
new file mode 100644
index 0000000000..0c1638d490
--- /dev/null
+++ b/common/utils/ds/tests/test_spsc_q.cpp
@@ -0,0 +1,135 @@
+/*
+ * SPDX-License-Identifier: LicenseRef-CSSL-1.0
+ */
+
+#include "gtest/gtest.h"
+extern "C" {
+#include "spsc_q.h"
+}
+
+TEST(spsc_q, basic_test) {
+ spsc_q_t rb = spsc_q_alloc(2, sizeof(int));
+
+ int a = 1;
+ EXPECT_TRUE(spsc_q_put(&rb, &a, sizeof(a)));
+ EXPECT_TRUE(spsc_q_put(&rb, &a, sizeof(a)));
+ EXPECT_FALSE(spsc_q_put(&rb, &a, sizeof(a)));
+
+ int b;
+ EXPECT_TRUE(spsc_q_get(&rb, &b, sizeof(b)));
+ EXPECT_EQ(a, b);
+ EXPECT_TRUE(spsc_q_get(&rb, &b, sizeof(b)));
+ EXPECT_EQ(a, b);
+ EXPECT_FALSE(spsc_q_get(&rb, &b, sizeof(b)));
+
+ spsc_q_free(&rb);
+}
+
+TEST(spsc_q, cont_write) {
+ spsc_q_t rb = spsc_q_alloc(10, sizeof(int));
+
+ int a = 1;
+ for (int i = 0; i < 1111; ++i) {
+ EXPECT_TRUE(spsc_q_put(&rb, &a, sizeof(a)));
+ a++;
+ EXPECT_TRUE(spsc_q_put(&rb, &a, sizeof(a)));
+ a++;
+ EXPECT_TRUE(spsc_q_put(&rb, &a, sizeof(a)));
+ a++;
+
+ int b;
+ EXPECT_TRUE(spsc_q_get(&rb, &b, sizeof(b)));
+ EXPECT_EQ(b, a - 3);
+ EXPECT_TRUE(spsc_q_get(&rb, &b, sizeof(b)));
+ EXPECT_EQ(b, a - 2);
+ EXPECT_TRUE(spsc_q_get(&rb, &b, sizeof(b)));
+ EXPECT_EQ(b, a - 1);
+ }
+
+ spsc_q_free(&rb);
+}
+
+bool count(const void *data, void *user)
+{
+ EXPECT_TRUE(data != NULL);
+ int *c = (int *)user;
+ (*c)++;
+ return true; /* count all */
+}
+TEST(spsc_q, iterator) {
+ spsc_q_t rb = spsc_q_alloc(10, sizeof(int));
+ int n = 8;
+ for (int i = 0; i < n; ++i)
+ EXPECT_TRUE(spsc_q_put(&rb, &i, sizeof(i)));
+
+ int c = 0;
+ int results[n];
+ int ret = spsc_q_get_while(&rb, count, &c, results, sizeof(*results), n);
+ EXPECT_EQ(c, n);
+ EXPECT_EQ(ret, n);
+ for (int i = 0; i < n; ++i)
+ EXPECT_EQ(results[i], i);
+
+ int b;
+ EXPECT_FALSE(spsc_q_get(&rb, &b, sizeof(b))); /* empty! */
+
+ spsc_q_free(&rb);
+}
+
+bool drop(const void *data, void *user)
+{
+ const int *e = (const int *)data;
+ int *c = (int *)user;
+ EXPECT_EQ(*e, *c);
+ (*c)++;
+ return true; /* drop all */
+}
+TEST(spsc_q, drop) {
+ spsc_q_t rb = spsc_q_alloc(10, sizeof(int));
+ int n = 8;
+ for (int i = 0; i < n; ++i)
+ EXPECT_TRUE(spsc_q_put(&rb, &i, sizeof(i)));
+
+ int c = 0;
+ int ret = spsc_q_drop_while(&rb, drop, &c);
+ EXPECT_EQ(c, n);
+ EXPECT_EQ(ret, n);
+
+ int b;
+ EXPECT_FALSE(spsc_q_get(&rb, &b, sizeof(b))); /* empty! */
+
+ spsc_q_free(&rb);
+}
+
+
+TEST(spsc_q, full) {
+ int n = 3;
+ spsc_q_t rb = spsc_q_alloc(n, sizeof(int));
+ int a = 1;
+ EXPECT_TRUE(spsc_q_put(&rb, &a, sizeof(a)));
+ a++;
+ EXPECT_TRUE(spsc_q_put(&rb, &a, sizeof(a)));
+ a++;
+ EXPECT_TRUE(spsc_q_put(&rb, &a, sizeof(a)));
+ a++;
+ EXPECT_FALSE(spsc_q_put(&rb, &a, sizeof(a))); /* full! */
+
+ int b;
+ EXPECT_TRUE(spsc_q_get(&rb, &b, sizeof(b)));
+ EXPECT_EQ(b, a - n);
+
+ EXPECT_TRUE(spsc_q_put(&rb, &a, sizeof(a)));
+ a++;
+ EXPECT_FALSE(spsc_q_put(&rb, &a, sizeof(a))); /* full! */
+
+ EXPECT_TRUE(spsc_q_get(&rb, &b, sizeof(b)));
+ EXPECT_EQ(b, a - n);
+
+ spsc_q_free(&rb);
+}
+
+int main(int argc, char** argv)
+{
+ testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
diff --git a/common/utils/ds/tests/test_spsc_q_perf.cpp b/common/utils/ds/tests/test_spsc_q_perf.cpp
new file mode 100644
index 0000000000..6487e9e6c3
--- /dev/null
+++ b/common/utils/ds/tests/test_spsc_q_perf.cpp
@@ -0,0 +1,75 @@
+#include "benchmark/benchmark.h"
+#include "stdio.h"
+#include "assert.h"
+#include "pthread.h"
+
+extern "C" {
+#include "spsc_q.h"
+}
+
+typedef struct q_args {
+ spsc_q_t q;
+ int range;
+} q_args_t;
+
+static void *producer(void *arg)
+{
+ q_args_t *a = (q_args_t *) arg;
+ int i = 0;
+ while (i <= a->range) {
+ if (spsc_q_put(&a->q, &i, sizeof(i)))
+ i++;
+ }
+ return NULL;
+}
+
+static void *consumer(void *arg)
+{
+ q_args_t *a = (q_args_t *) arg;
+ int i = 0;
+ while (i != a->range) {
+ int r;
+ if (spsc_q_get(&a->q, &r, sizeof(r))) {
+ assert(r == i);
+ i++;
+ }
+ }
+ return NULL;
+}
+
+static void run_test(int range, int q_size)
+{
+ q_args_t args = {
+ .q = spsc_q_alloc(q_size, sizeof(int)),
+ .range = range,
+ };
+
+ pthread_t p, c;
+ int ret;
+ // start
+ ret = pthread_create(&p, NULL, producer, &args);
+ assert(ret == 0);
+ ret = pthread_create(&c, NULL, consumer, &args);
+ assert(ret == 0);
+
+ ret = pthread_join(p, NULL);
+ assert(ret == 0);
+ ret = pthread_join(c, NULL);
+ assert(ret == 0);
+ // stop
+ // data/time => throughput
+
+ spsc_q_free(&args.q);
+}
+
+static void BM_spsc_q(benchmark::State &state)
+{
+ int range = 500000;
+ int q_size = state.range(0);
+ for (auto _ : state)
+ run_test(range, q_size);
+}
+
+BENCHMARK(BM_spsc_q)->RangeMultiplier(2)->Range(10, 160);
+
+BENCHMARK_MAIN();
diff --git a/common/utils/fsn.c b/common/utils/fsn.c
new file mode 100644
index 0000000000..e8566a2da9
--- /dev/null
+++ b/common/utils/fsn.c
@@ -0,0 +1,55 @@
+/*
+ * SPDX-License-Identifier: LicenseRef-CSSL-1.0
+ */
+
+#include "fsn.h"
+
+#include
+
+static int num_slots[5] = {10, 20, 40, 80, 160};
+
+fsn_t fsn_add_delta(fsn_t fsn, uint32_t delta)
+{
+ const int slots_frame = num_slots[fsn.mu];
+ int next_f = fsn.f + delta / slots_frame;
+ int next_s = fsn.s + delta % slots_frame;
+ fsn_t res = {
+ .f = (next_f + next_s / slots_frame) % 1024,
+ .s = next_s % slots_frame,
+ .mu = fsn.mu,
+ };
+ return res;
+}
+
+int fsn_get_diff(fsn_t a, fsn_t b)
+{
+ assert(a.mu == b.mu);
+ const int slots_frame = num_slots[a.mu];
+ int diff = (a.f * slots_frame + a.s) - (b.f * slots_frame + b.s);
+ if (diff < -512 * slots_frame)
+ diff += 1024 * slots_frame;
+ else if (diff > 512 * slots_frame)
+ diff -= 1024 * slots_frame;
+ return diff;
+}
+
+fsn_t fsn_get_max(fsn_t a, fsn_t b)
+{
+ if (fsn_get_diff(a, b) <= 0) {
+ return b;
+ } else {
+ return a;
+ }
+}
+
+bool fsn_equal(fsn_t a, fsn_t b)
+{
+ assert(a.mu == b.mu);
+ return a.f == b.f && a.s == b.s && a.mu == b.mu;
+}
+
+bool fsn_in_the_past(fsn_t old, fsn_t new)
+{
+ int diff = fsn_get_diff(old, new);
+ return diff < 0;
+}
diff --git a/common/utils/fsn.h b/common/utils/fsn.h
new file mode 100644
index 0000000000..dfa126bc85
--- /dev/null
+++ b/common/utils/fsn.h
@@ -0,0 +1,36 @@
+/*
+ * SPDX-License-Identifier: LicenseRef-CSSL-1.0
+ */
+
+#ifndef FSN_H_
+#define FSN_H_
+
+#include
+#include
+
+/// helper type to encapsulate a frame/slot combination in a single type.
+typedef struct fsn {
+ uint16_t f; /// frame
+ uint16_t s; /// slot
+ uint8_t mu; /// numerology
+} fsn_t;
+
+/* \brief Add delta slots to fsn. Note that this depends also on the stored
+ * numerology inside fsn. */
+fsn_t fsn_add_delta(fsn_t fsn, uint32_t delta);
+
+/* \brief Get difference of slots for a and b.
+ * \note asserts if numerology not the same. */
+int fsn_get_diff(fsn_t a, fsn_t b);
+
+/* \brief Gets the larger of two fsns */
+fsn_t fsn_get_max(fsn_t a, fsn_t b);
+
+/* \brief Compare if both fsn_t's are equal */
+bool fsn_equal(fsn_t a, fsn_t b);
+
+/* \brief Determine if told is in the past of tnew. The threshold is 512
+ * frames. */
+bool fsn_in_the_past(fsn_t told, fsn_t tnew);
+
+#endif /* FSN_H_ */
diff --git a/common/utils/nr/nr_common.h b/common/utils/nr/nr_common.h
index 8580a0491b..228e51feb2 100644
--- a/common/utils/nr/nr_common.h
+++ b/common/utils/nr/nr_common.h
@@ -13,6 +13,7 @@
#include
#include "assertions.h"
#include "common/utils/utils.h"
+#include "common/utils/ds/byte_array.h"
#define MAX_SI_GROUPS 3
#define NR_MAX_PDSCH_TBS 3824
@@ -79,10 +80,32 @@ static inline const char *rnti_types(nr_rnti_type_t rr)
// the total shift is 2 * 15, in dB scale thats 10log10(2^(15*2))
#define SQ15_SQUARED_NORM_FACTOR_DB 90.3089986992
+typedef enum {
+ NR_SIB_1 = 1,
+ NR_SIB_2,
+ NR_SIB_3,
+ NR_SIB_4,
+ NR_SIB_5,
+ NR_SIB_6,
+ NR_SIB_7,
+ NR_SIB_8,
+ NR_SIB_9,
+ NR_SIB_10,
+ NR_SIB_11,
+ NR_SIB_12,
+ NR_SIB_13,
+ NR_SIB_14,
+ NR_SIB_15,
+ NR_SIB_16,
+ NR_SIB_17,
+ NR_SIB_18,
+ NR_SIB_19,
+ NR_SIB_20,
+ NR_SIB_21,
+} nr_sib_type_t;
+
typedef struct {
- uint8_t *SIB_buffer;
- int SIB_size;
- int SIB_type;
+ nr_sib_type_t SIB_type;
} nr_SIBs_t;
typedef struct nr_bandentry_s {
diff --git a/common/utils/tests/CMakeLists.txt b/common/utils/tests/CMakeLists.txt
index e3c310fed9..14d2f83d7a 100644
--- a/common/utils/tests/CMakeLists.txt
+++ b/common/utils/tests/CMakeLists.txt
@@ -2,3 +2,10 @@
add_executable(test_tpool_vs_actors test_tpool_vs_actors.c)
target_link_libraries(test_tpool_vs_actors PRIVATE thread-pool pthread LOG minimal_lib actor)
+add_test(NAME test_tpool_vs_actors COMMAND ./test_tpool_vs_actors)
+add_dependencies(tests test_tpool_vs_actors)
+
+add_executable(test_fsn test_fsn.cpp)
+add_dependencies(tests test_fsn)
+target_link_libraries(test_fsn PRIVATE utils GTest::gtest)
+add_test(NAME test_fsn COMMAND ./test_fsn)
diff --git a/common/utils/tests/test_fsn.cpp b/common/utils/tests/test_fsn.cpp
new file mode 100644
index 0000000000..3cbe34dfb2
--- /dev/null
+++ b/common/utils/tests/test_fsn.cpp
@@ -0,0 +1,84 @@
+/*
+ * SPDX-License-Identifier: LicenseRef-CSSL-1.0
+ */
+
+#include
+extern "C" {
+#include "fsn.h"
+}
+
+TEST(fsn, test_mu0_fsn_add) {
+ fsn_t current = {123, 5, 0};
+ fsn_t next = current;
+
+ next = fsn_add_delta(next, 12);
+ EXPECT_EQ(next.f, 124);
+ EXPECT_EQ(next.s, 7);
+ EXPECT_EQ(next.mu, 0);
+
+ next = fsn_add_delta(next, 10);
+ EXPECT_EQ(next.f, 125);
+ EXPECT_EQ(next.s, 7);
+ EXPECT_EQ(next.mu, 0);
+
+ next = fsn_add_delta(next, 10 * 1024);
+ EXPECT_EQ(next.f, 125);
+ EXPECT_EQ(next.s, 7);
+ EXPECT_EQ(next.mu, 0);
+}
+
+TEST(fsn, test_mu0_get_diff) {
+ fsn_t current = {123, 5, 0};
+ fsn_t next = fsn_add_delta(current, 12);
+ int diff;
+
+ diff = fsn_get_diff(current, next);
+ EXPECT_EQ(diff, -12);
+
+ diff = fsn_get_diff(next, current);
+ EXPECT_EQ(diff, 12);
+}
+
+TEST(fsn, test_mu0_get_max) {
+ fsn_t current = {123, 5, 0};
+ fsn_t next = {125, 7, 0};
+
+ fsn_t max = fsn_get_max(current, next);
+ EXPECT_EQ(max.f, next.f);
+ EXPECT_EQ(max.s, next.s);
+ EXPECT_EQ(max.mu, next.mu);
+}
+
+TEST(fsn, test_mu0_equal) {
+ fsn_t a = {123, 5, 0};
+ fsn_t b = a;
+ fsn_t c = {123, 6, 0};
+
+ EXPECT_TRUE(fsn_equal(a, b));
+ EXPECT_FALSE(fsn_equal(a, c));
+}
+
+TEST(fsn, test_mu0_in_the_past) {
+ fsn_t a = {0, 0, 0};
+ fsn_t n = {100, 9, 0};
+ fsn_t b_bef = {511, 9, 0};
+ fsn_t b_ex = {512, 0, 0};
+ fsn_t b_aft = {512, 1, 0};
+
+ // a is in the past of n
+ EXPECT_TRUE(fsn_in_the_past(a, n));
+ // similarly, a is in the past of b_bef
+ EXPECT_TRUE(fsn_in_the_past(a, b_bef));
+ // difference "to both sides" is 512 frames, so we consider a still in the
+ // past of b_ex
+ EXPECT_TRUE(fsn_in_the_past(a, b_ex));
+ // (b_aft - a) < (a - b_aft) => b_aft is in the past of a because of
+ // wrap-around
+ EXPECT_TRUE(fsn_in_the_past(b_aft, a));
+}
+
+int main(int argc, char** argv)
+{
+ testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
diff --git a/doc/Doxyfile b/doc/Doxyfile
index fad5807544..7c09e6272e 100644
--- a/doc/Doxyfile
+++ b/doc/Doxyfile
@@ -1967,7 +1967,7 @@ INPUT = \
@CMAKE_CURRENT_SOURCE_DIR@/../openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c \
@CMAKE_CURRENT_SOURCE_DIR@/../openair1/PHY/LTE_TRANSPORT/dci_NB_IoT.h \
@CMAKE_CURRENT_SOURCE_DIR@/../openair1/PHY/LTE_TRANSPORT/group_hopping.c \
-@CMAKE_CURRENT_SOURCE_DIR@/../openair1/PHY/LTE_TRANSPORT/if4_tools.h \
+@CMAKE_CURRENT_SOURCE_DIR@/../openair1/PHY/if4_tools.h \
@CMAKE_CURRENT_SOURCE_DIR@/../openair1/PHY/LTE_TRANSPORT/uci_tools.c \
@CMAKE_CURRENT_SOURCE_DIR@/../openair1/PHY/LTE_TRANSPORT/prach.c \
@CMAKE_CURRENT_SOURCE_DIR@/../openair1/PHY/LTE_TRANSPORT/edci.c \
diff --git a/doc/FEATURE_SET.md b/doc/FEATURE_SET.md
index 95aa32166f..bc6ba6b4a3 100644
--- a/doc/FEATURE_SET.md
+++ b/doc/FEATURE_SET.md
@@ -154,7 +154,7 @@ These modes of operation are supported:
- RedCap SIB1 v17 IEs supported
- Coexistence of RedCap and Normal UEs
- Handling of RedCap capability for small PDCP/RLC SN size
-- Scheduling of other SIBs (2, 19)
+- Scheduling of other SIBs (2, 3, 4, 19)
- NTN
- Support downlinkHARQ-FeedbackDisabled-r17
- Support for 32 PDSCH and PUSCH HARQ processes per UE
@@ -194,7 +194,7 @@ These modes of operation are supported:
- 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 system information (SIB2)
+- Generation of system information (SIB2, SIB3, SIB4)
- RRC can configure PDCP and SDAP (through E1), and RLC and MAC (through F1)
- Interface with GTP-U (tunnel creation/handling for S1-U (NSA), N3 (SA), F1 interfaces)
- Integration of RRC messages and procedures supporting UE 5G SA connection
@@ -380,7 +380,7 @@ These modes of operation are supported:
- MIB processing
- Scheduling of system information block 1 (SIB1) reception
* Other system information
- - Scheduling of other system information blocks reception
+ - Scheduling of other system information blocks reception (SIB2, SIB3, SIB4)
* Random access procedure (needs improvement, there is still not a clear separation between MAC and PHY)
- Mapping SSBs to multiple ROs
- Scheduling of PRACH
diff --git a/doc/README.md b/doc/README.md
index 37fe2a980d..d1dfc2dc4d 100644
--- a/doc/README.md
+++ b/doc/README.md
@@ -135,6 +135,7 @@ The other SDRs (AW2S, LimeSDR, ...) have no READMEs.
- [clang-format.md](./clang-format.md): how to format the code. See also the
next entry for an error detection tool.
- [formatting](../tools/formatting/README.md) is a clang-format error detection tool
+- [cppcheck](../tools/cppcheck/README.md) for static code analysis
- [sanitizers.md](./dev_tools/sanitizers.md): how to run with ASan/UBSan/MemSAN/TSan
- [iwyu](../tools/iwyu/README.md) is a tool to detect `#include` errors
- [docker-dev-env](../tools/docker-dev-env/README.md) is a ubuntu24 docker development environment
diff --git a/doc/RRC/rrc-dev.md b/doc/RRC/rrc-dev.md
index eee1b861fa..a218997d3a 100644
--- a/doc/RRC/rrc-dev.md
+++ b/doc/RRC/rrc-dev.md
@@ -633,6 +633,98 @@ sequenceDiagram
Note over TargetCU: Then: encode Handover Command, send NGAP HANDOVER REQUEST ACKNOWLEDGE
```
+### Neighbour cells
+
+#### SIB3/SIB4 and measurement-gap implementation
+
+The following section documents the implementation-level control flow
+for SIB3/SIB4 and measurement-gap handling in current OAI, using the configured
+neighbor cell list as a shared input model.
+
+Briefly, the three procedures are:
+- SIB3: CU derives and provides intra-frequency neighbour SI, which DU broadcasts
+ and UE uses for autonomous idle/inactive intra-frequency reselection.
+- SIB4: CU derives and provides inter-frequency carrier/neighbour SI, which DU
+ broadcasts and UE uses for autonomous idle/inactive inter-frequency reselection.
+- MeasGap: CU/DU coordinate dedicated `MeasGapConfig` in UE `MeasConfig`, DU
+ scheduler interrupts transmission (`nr_measgap_scheduling()`) for the UE to
+ apply the MeasGap configuration in connected mode for gap-based measurements that
+ are sent as `MeasurementReport` and processed at CU-CP (`rrc_gNB_process_MeasurementReport()`).
+ Event-driven reports (for example A3) are used by CU-side mobility logic and can
+ trigger handover procedures.
+
+### MeasGap
+
+```mermaid
+sequenceDiagram
+ participant DM as Data model (neighbour_cell_configuration)
+ participant CU as CU-CP (RRC)
+ participant DU as DU (MAC/RRC)
+ participant UE as UE
+
+ CU-->>DM: Read serving + neighbour frequency/PCI/band data
+ DM-->>CU: Provide neighbour/frequency inputs for MeasConfig
+ CU->>CU: nr_rrc_get_measconfig
+ Note over CU: Build UE MeasConfig
+ CU->>CU: get_meas_timing_config (cell.mtc, ue.measConfig)
+ Note over CU: Check distinct ssbFrequency
+ alt one frequency only
+ Note over CU: returns NULL, no meas_timing_config sent to DU
+ else multiple frequencies
+ CU->>DU: F1AP UE Context Setup Request
+ Note over CU,DU: Includes cu_to_du_rrc_info.meas_timing_config
+ DU->>DU: create_measgap_config
+ DU->>DU: encode_measgap_config
+ DU-->>CU: F1AP UE Context Setup Response
+ Note over DU,CU: Includes du_to_cu_rrc_info.meas_gap_config
+ CU->>CU: get_meas_gap_config
+ Note over CU: Decode/store gap in UE MeasConfig (UE.measConfig.measGapConfig)
+ CU->>UE: RRCReconfiguration
+ Note over CU,UE: Includes MeasConfig.measGapConfig
+ rect rgba(210, 235, 255, 0.35)
+ Note over DU,UE: Measurement-gap window
+ DU->>DU: nr_measgap_scheduling
+ Note over DU: Interrupt transmission for meas gap
+ UE->>UE: nr_rrc_handle_meas_indication
+ Note over UE: Perform gap-based neighbour/inter-frequency measurements
+ UE-->>CU: MeasurementReport
+ end
+ Note over UE,CU: UL-DCCH MeasurementReport for configured events (e.g. A3)
+ CU->>CU: rrc_gNB_process_MeasurementReport
+ Note over CU: Run mobility decision logic (may trigger handover)
+ end
+```
+
+### SIB3/SIB4
+
+```mermaid
+sequenceDiagram
+ participant DM as Data model (neighbour_cell_configuration)
+ participant CU as CU-CP (RRC)
+ participant DU as DU
+ participant UE as UE
+
+ CU->>CU: cp_f1_served_cell_info_to_cell
+ CU->>DM: get_cell_neighbour_list
+ DM-->>CU: neighbour_cell_configuration for serving cell
+ CU->>CU: get_ssb_arfcn
+ Note over CU: Derive serving_ssb_arfcn from cell MTC
+ loop for each configured neighbour
+ Note over CU: Compare neighbour.absoluteFrequencySSB vs serving_ssb_arfcn
+ alt equal
+ CU->>CU: get_sib3_intra_freq_neighbors
+ else different
+ CU->>CU: get_sib4_inter_freq_neighbors
+ end
+ end
+ CU-->>DU: F1AP F1 Setup Response
+ DU-->>UE: BCCH-DL-SCH-Message
+ Note over DU,UE: Broadcast SystemInformation including configured SIB3/SIB4
+ UE->>UE: nr_rrc_ue_decode_NR_BCCH_DL_SCH_Message
+ Note over UE: Evaluate idle/inactive reselection criteria and timers
+ Note over UE,DU: After reselection, access/registration continues on selected cell DU as needed
+```
+
## UE Context
UE context information is stored in `gNB_RRC_UE_t`, which includes:
diff --git a/doc/RRC/rrc-usage.md b/doc/RRC/rrc-usage.md
index 46ff9f061c..e828001d1b 100644
--- a/doc/RRC/rrc-usage.md
+++ b/doc/RRC/rrc-usage.md
@@ -94,7 +94,81 @@ the [MAC configuration](../MAC/mac-usage.md) as well for SIB configuration.
deactivated, a transparent SDAP header is prepended to packets, but no
further processing is being done.
- `cu_sibs` (default: `[]`) list of SIBs to give to the DU for transmission.
- Currently, SIB2 is supported.
+ Currently supported:
+ - SIB2: serving-cell reselection parameters (configured in `sib2_config`)
+ - SIB3: intra-frequency neighbour cell list (neighbours on the same SSB ARFCN as the serving cell)
+ - SIB4: inter-frequency carriers + neighbour lists, grouped per `(absoluteFrequencySSB, subcarrierSpacing)`. Per-frequency fields (e.g. `cellReselectionPriority`, `threshX_HighP`, `threshX_LowP`, `q_OffsetFreq`) come from `frequency_list`
+
+Example activation:
+```
+cu_sibs = ( 2, 3, 4 );
+```
+SIB2 is configured per-gNB in `sib2_config` (see below). SIB3/SIB4 are derived from the neighbour configuration:
+- `neighbour_list` / `neighbour_cell_configuration`: neighbour identity + per-neighbour offsets (`q_OffsetCell`, etc.)
+- `frequency_list`: per-frequency SIB4 reselection parameters (priority/thresholds/`q_OffsetFreq`)
+
+Example `gNBs.[0].sib2_config`:
+```
+cu_sibs = ( 2 );
+
+sib2_config : {
+ q_Hyst = 0;
+ cellReselectionPriority = 0;
+ threshServingLowP = 0;
+ threshServingLowQ = 4;
+ s_NonIntraSearchP = 10;
+ s_NonIntraSearchQ = 8;
+ q_RxLevMin = -56;
+ q_QualMin = -18;
+ s_IntraSearchP = 22;
+ s_IntraSearchQ = 20;
+ t_ReselectionNR = 1;
+ deriveSSB_IndexFromCell = 1;
+
+ speed_t_Evaluation = 0;
+ speed_t_HystNormal = 0;
+ speed_n_CellChangeMedium = 1;
+ speed_n_CellChangeHigh = 2;
+ speed_sf_Medium = 1;
+ speed_sf_High = 0;
+};
+```
+
+#### SIB3/SIB4 and measurement gaps
+
+This section summarizes how SIB3/SIB4 and measurement gaps relate in NR and how OAI currently implements them.
+
+From 3GPP TS 38.331:
+
+- `SIB3` carries intra-frequency reselection information (`intraFreqNeighCellList`).
+- `SIB4` carries inter-frequency reselection information (`interFreqCarrierFreqList`
+ and per-carrier neighbour lists).
+- `MeasGapConfig` is part of dedicated `MeasConfig` (typically sent in
+ `RRCReconfiguration`) and controls measurement gaps in connected mode.
+
+In other words:
+
+- SIB3/SIB4 are broadcast SI for idle/inactive (`RRC_IDLE` / `RRC_INACTIVE`)
+ reselection behavior: UE performs autonomous cell reselection using broadcast
+ SI (SIB3 for intra-frequency, SIB4 for inter-frequency).
+- `MeasGapConfig` is a dedicated UE measurement behavior and applies to
+ connected mode (`RRC_CONNECTED`): the network configures what the UE
+ measures and reports (periodic and event-based, e.g., A3), and those reports
+ are used by CU-CP mobility logic (including handover decisions).
+
+MeasGap does not depend on SIB3/SIB4, however they share the same underlying
+neighbour/frequency data model, which is the common source of serving +
+neighbour frequency information (see also [Neighbor-gNB configuration](#neighbour-gnb-configuration)):
+
+- SIB3/SIB4 generation is done on the CU-CP side (inside `rrc_gNB_du.c`) from
+ neighbour/frequency configuration and serving-cell MTC-derived ARFCN.
+- Measurement-gap configuration also starts from the same neighbour/frequency
+ model: CU uses neighbour fields (frequency/PCI/band) to build UE
+ `MeasConfig` measurement objects, then DU derives/encodes gap parameters
+ from CU-provided timing (`meas_timing_config`) and returns `meas_gap_config`
+ for CU forwarding in dedicated `RRCReconfiguration`.
+
+Detailed implementation flow and sequence diagrams are documented in [`rrc-dev.md`](./rrc-dev.md).
#### UE-specific configuration
@@ -105,12 +179,64 @@ the [MAC configuration](../MAC/mac-usage.md) as well for SIB configuration.
Refer to the [handover tutorial](../handover-tutorial.md) for detailed information about gNB neighbors and handover procedures.
+##### Configuration structure and key semantics
+
+The neighbour configuration is a 2-level structure:
+
+- Outer list: `neighbour_list`
+ - Key: `nr_cellid` of the serving cell
+ - One entry per serving cell
+- Inner list: `neighbour_cell_configuration`
+ - Actual neighbour cells for that serving cell
+ - Contains neighbour fields such as `gNB_ID`, neighbour `nr_cellid`, `physical_cellId`, frequency, PLMN, etc.
+
+This same core configuration model is reused by multiple RRC procedures.
+
+- SIB3/SIB4 generation: uses neighbour identity/frequency/offset fields to derive
+ intra/inter-frequency SI.
+- Connected-mode measurement config: uses neighbour frequency/PCI/band fields to build
+ UE `MeasConfig` measurement objects.
+- Handover-related procedures: reuse neighbour identity fields (e.g., cell ID/PCI/PLMN
+ TAC, gNB ID) for target selection and for populating target-cell information carried
+ in NGAP handover messages.
+
+Conceptually, for each serving cell the RRC keeps:
+
+- A per-frequency table (`inter_freqs`): one entry per `(absoluteFrequencySSB,
+ subcarrierSpacing)` used for SIB4, containing the SIB4 per-frequency fields
+ (priority, thresholds, `q_OffsetFreq`, `q_RxLevMin`, `t_ReselectionNR`).
+- A per-neighbour list (`neighbour_cells`): one entry per neighbour, with
+ identity (cell ID, PCI, PLMN, TAC), frequency (`absoluteFrequencySSB`,
+ `subcarrierSpacing`, `band`), and SIB3/SIB4 per-neighbour offsets
+ (`q_OffsetCell`, `q_RxLevMinOffsetCell`, `q_QualMinOffsetCell`).
+- A link from neighbours to frequencies: each neighbour implicitly points to
+ the matching `inter_freqs` entry via its `(absoluteFrequencySSB,
+ subcarrierSpacing)`; if no such frequency exists, it is treated as having no
+ SIB4 per-frequency configuration.
+
+Notes:
+
+- In `neighbour_list`, only `nr_cellid` is used as the key for lookup.
+- `physical_cellId` belongs to neighbour-cell entries in `neighbour_cell_configuration` (inner list).
+- `nr_cellid` entries in `neighbour_list` should be unique to avoid ambiguous lookup.
+- Intra-frequency neighbours (SIB3) are derived only from the per-cell
+ `neighbour_cell_configuration` on the serving carrier.
+
+At configuration time (`gnb_config.c`), neighbours are parsed into `neighbour_cells`,
+per-neighbour SIB3/SIB4 offsets are validated, and a per-frequency array `inter_freqs`
+is built by grouping neighbours by `(absoluteFrequencySSB, subcarrierSpacing)` and
+in-range SIB4 per-frequency fields (`cellReselectionPriority`, `threshX_HighP/L`,
+`q_OffsetFreq`) across neighbours on the same ARFCN. At SIB4 build time, the RRC uses
+`inter_freqs` to create one `InterFreqCarrierFreqInfo` per ARFCN for inter-frequency
+carriers (ARFCN different from the serving SSB ARFCN) and attaches all neighbours whose
+`inter_freq_idx` points to that frequency entry.
+
##### Required configuration parameters
-To define a neighbor cell in the configuration file, the following parameters are required:
+To define a neighbour cell in the configuration file, the following parameters are required:
-- `gNB_ID` - identifier of the neighbor gNB (e.g., `0xe01`)
-- `nr_cellid` - cell identifier of the neighbor cell (e.g., `11111111`)
+- `gNB_ID` - identifier of the neighbour gNB (e.g., `0xe01`)
+- `nr_cellid` - cell identifier of the neighbour cell (e.g., `11111111`)
- `physical_cellId` - physical cell ID for radio identification (e.g., `1`)
- `absoluteFrequencySSB` - SSB frequency in ARFCN notation (e.g., `643296`)
- `subcarrierSpacing` - numerology index: 0=15kHz, 1=30kHz, 2=60kHz, 3=120kHz
@@ -123,19 +249,45 @@ To define a neighbor cell in the configuration file, the following parameters ar
Example configuration structure:
```
+# Per-frequency SIB4 configuration (one entry per ARFCN), shared by all cells
+frequency_list = (
+ {
+ absoluteFrequencySSB = 643296;
+ subcarrierSpacing = 1; # 30 kHz
+ band = 78;
+
+ frequency_config = (
+ {
+ cellReselectionPriority = 5;
+ threshX_HighP = 10;
+ threshX_LowP = 6;
+ q_OffsetFreq = 0;
+ # Optional: threshX_HighQ, threshX_LowQ, etc.
+ }
+ );
+ }
+);
+
+# Per-cell neighbour configuration; neighbours reference frequency_list via ARFCN/SCS
neighbour_list = (
{
nr_cellid = 12345678;
+
neighbour_cell_configuration = (
{
gNB_ID = 0xe01;
nr_cellid = 11111111;
physical_cellId = 1;
- absoluteFrequencySSB = 643296;
- subcarrierSpacing = 1; # 30 kHz
+ absoluteFrequencySSB = 643296; # ARFCN used to look up matching entry in frequency_list
+ subcarrierSpacing = 1; # 30 kHz
band = 78;
plmn = { mcc = 001; mnc = 01; mnc_length = 2 };
tracking_area_code = 1;
+
+ # Example per-neighbour offsets (SIB3/SIB4)
+ q_OffsetCell = 0;
+ q_RxLevMinOffsetCell = -1;
+ q_QualMinOffsetCell = -1;
}
);
}
diff --git a/doc/TESTBenches.md b/doc/TESTBenches.md
index d348ffe355..361d774215 100644
--- a/doc/TESTBenches.md
+++ b/doc/TESTBenches.md
@@ -96,10 +96,6 @@ information on how the images are built.
- orion: Cross-compilation from Intel to ARM
- base image from `Dockerfile.base.ubuntu.cross-arm64`
- build image from `Dockerfile.build.ubuntu.cross-arm64` (no target images)
-- [RAN-cppcheck](https://jenkins-oai.eurecom.fr/job/RAN-cppcheck/)
- ~BUILD-ONLY ~4G-LTE ~5G-NR ~nrUE
- - bellatrix
- - performs static code analysis, currently not actively enforced
- [RAN-RHEL8-Cluster-Image-Builder](https://jenkins-oai.eurecom.fr/job/RAN-RHEL8-Cluster-Image-Builder/)
~BUILD-ONLY ~4G-LTE ~5G-NR ~nrUE
- cluster (`Asterix-OC-oaicicd-session` resource): RHEL image build using the OpenShift Cluster (using gcc/clang)
diff --git a/doc/handover-tutorial.md b/doc/handover-tutorial.md
index 68e685c83d..02736da931 100644
--- a/doc/handover-tutorial.md
+++ b/doc/handover-tutorial.md
@@ -512,8 +512,16 @@ configuration, e.g. [neighbour-config-rfsim.conf](../../ci-scripts/conf_files/ne
This configuration can also be present in a different file and included in the
gNB configuration file with `@include "neighbour-config-rfsim.conf"`.
-For each gNB there is a `neighbour_cell_configuration` linked to its serving
-cell ID.
+The neighbor configuration is nested:
+
+- `neighbour_list` outer entries are keyed by serving `nr_cellid`
+- each outer entry contains `neighbour_cell_configuration`, i.e., the list of neighbor cells for that serving cell
+
+In this model:
+
+- outer `nr_cellid` entries should be unique
+- neighbor `physical_cellId` values are defined in inner neighbor entries
+- the same serving-cell keyed neighbor mapping is used for both F1 and N2 handover logic
See the example above for `neighbour-config-ho.conf`. The same configuration
is for both F1 and N2 handover.
diff --git a/doc/tutorial_resources/oai-cn5g/docker-compose-positioning.yaml b/doc/tutorial_resources/oai-cn5g/docker-compose-positioning.yaml
index 6b75c22b6b..c3b9d937c1 100644
--- a/doc/tutorial_resources/oai-cn5g/docker-compose-positioning.yaml
+++ b/doc/tutorial_resources/oai-cn5g/docker-compose-positioning.yaml
@@ -1,7 +1,7 @@
services:
mysql:
container_name: "mysql"
- image: mysql:8.0
+ image: mysql:9.6
volumes:
- ./database/oai_db.sql:/docker-entrypoint-initdb.d/oai_db.sql
- ./healthscripts/mysql-healthcheck.sh:/tmp/mysql-healthcheck.sh
@@ -172,7 +172,7 @@ services:
privileged: true
init: true
container_name: oai-ext-dn
- image: oaisoftwarealliance/trf-gen-cn5g:jammy
+ image: oaisoftwarealliance/trf-gen-cn5g:latest
entrypoint: /bin/bash -c \
"ip route add 10.0.0.0/16 via 192.168.70.134 dev eth0; ip route; sleep infinity"
command: ["/bin/bash", "-c", "trap : SIGTERM SIGINT; sleep infinity & wait"]
diff --git a/doc/tutorial_resources/oai-cn5g/docker-compose.yaml b/doc/tutorial_resources/oai-cn5g/docker-compose.yaml
index 0baf032fbb..d99eadb844 100644
--- a/doc/tutorial_resources/oai-cn5g/docker-compose.yaml
+++ b/doc/tutorial_resources/oai-cn5g/docker-compose.yaml
@@ -1,7 +1,7 @@
services:
mysql:
container_name: "mysql"
- image: mysql:8.0
+ image: mysql:9.6
volumes:
- ./database/oai_db.sql:/docker-entrypoint-initdb.d/oai_db.sql
- ./healthscripts/mysql-healthcheck.sh:/tmp/mysql-healthcheck.sh
@@ -154,9 +154,9 @@ services:
privileged: true
init: true
container_name: oai-ext-dn
- image: oaisoftwarealliance/trf-gen-cn5g:jammy
+ image: oaisoftwarealliance/trf-gen-cn5g:latest
entrypoint: /bin/bash -c \
- "ip route add 10.0.0.0/16 via 192.168.70.134 dev eth0; ip route; sleep infinity"
+ "ip route add 10.0.0.0/16 via 192.168.70.134 dev eth0; ip route; iperf3 -s -D; sleep infinity"
command: ["/bin/bash", "-c", "trap : SIGTERM SIGINT; sleep infinity & wait"]
healthcheck:
test: /bin/bash -c "ip r | grep 10.0.0"
diff --git a/docker/Dockerfile.clang.rhel9 b/docker/Dockerfile.clang.rhel9
index 81fd8ccc83..4fae70955f 100644
--- a/docker/Dockerfile.clang.rhel9
+++ b/docker/Dockerfile.clang.rhel9
@@ -25,4 +25,4 @@ RUN /bin/sh oaienv && \
CFLAGS="-Werror" CXXFLAGS="-Werror -Wno-vla-cxx-extension" \
./build_oai --phy_simulators --gNB --eNB --nrUE --UE \
--ninja --build-tool-opt -k10 \
- --noavx512 --disable-T-Tracer -c
+ --noavx512 -c
diff --git a/docker/Dockerfile.phySim.rhel9 b/docker/Dockerfile.phySim.rhel9
index ac1c8680ca..31ca26adef 100644
--- a/docker/Dockerfile.phySim.rhel9
+++ b/docker/Dockerfile.phySim.rhel9
@@ -24,6 +24,7 @@ RUN /bin/sh oaienv && \
-DAVX512=OFF -DCMAKE_C_FLAGS=-Werror -DCMAKE_CXX_FLAGS=-Werror \
-DENABLE_PHYSIM_TESTS=ON \
-DSANITIZE_ADDRESS=ON -DSANITIZE_UNDEFINED=ON \
+ -DT_TRACER=OFF \
-DCMAKE_RUNTIME_OUTPUT_DIRECTORY=/opt/oai-physim/bin && \
ninja -k10 -j36
diff --git a/executables/lte-enb.c b/executables/lte-enb.c
index b62815b70a..c735934c1a 100644
--- a/executables/lte-enb.c
+++ b/executables/lte-enb.c
@@ -20,7 +20,7 @@
#include "nfapi/oai_integration/vendor_ext.h"
#include "radio/COMMON/common_lib.h"
-#include "PHY/LTE_TRANSPORT/if4_tools.h"
+#include "PHY/if4_tools.h"
#include "PHY/LTE_ESTIMATION/lte_estimation.h"
#include "PHY/phy_extern.h"
diff --git a/executables/lte-ru.c b/executables/lte-ru.c
index 91470d8f63..a0a82deabd 100644
--- a/executables/lte-ru.c
+++ b/executables/lte-ru.c
@@ -28,7 +28,7 @@
#include "PHY/phy_extern.h"
#include "PHY/LTE_ESTIMATION/lte_estimation.h"
#include "PHY/LTE_REFSIG/lte_refsig.h"
-#include "PHY/LTE_TRANSPORT/if4_tools.h"
+#include "PHY/if4_tools.h"
#include "PHY/LTE_TRANSPORT/transport_proto.h"
#include "SCHED/sched_common.h"
#include "common/utils/LOG/log.h"
diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c
index abbfa05df1..1b27b2e4e6 100644
--- a/executables/nr-gnb.c
+++ b/executables/nr-gnb.c
@@ -161,7 +161,12 @@ static void rx_func(processingData_L1_t *info)
NR_UL_IND_t UL_INFO = {.frame = frame_rx, .slot = slot_rx, .module_id = gNB->Mod_id, .CC_id = gNB->CC_id};
// Do PRACH RU processing
UL_INFO.rach_ind.pdu_list = UL_INFO.prach_pdu_indication_list;
- L1_nr_prach_procedures(gNB, frame_rx, slot_rx, &UL_INFO.rach_ind);
+ UL_INFO.rach_ind.number_of_pdus = 0;
+ // even if processing is late, we might collect all PRACH
+ // the last PRACH's frame/slot is when all UE's appear to have accessed
+ prach_item_t p;
+ while (spsc_q_get(&gNB->prach_l1rx_queue, &p, sizeof(p)))
+ L1_nr_prach_procedures(gNB, &p, &UL_INFO.rach_ind);
//WA: comment rotation in tx/rx
if (gNB->phase_comp) {
diff --git a/executables/nr-ru.c b/executables/nr-ru.c
index 7554c8a9a6..b66d4976c9 100644
--- a/executables/nr-ru.c
+++ b/executables/nr-ru.c
@@ -15,12 +15,13 @@
#include "common/utils/nr/nr_common.h"
#include "common/utils/assertions.h"
#include "common/utils/system.h"
+#include "common/utils/fsn.h"
#include "common/ran_context.h"
#include "radio/COMMON/common_lib.h"
#include "radio/ETHERNET/ethernet_lib.h"
-#include "PHY/LTE_TRANSPORT/if4_tools.h"
+#include "PHY/if4_tools.h"
#include "PHY/defs_nr_common.h"
#include "PHY/phy_extern.h"
@@ -980,11 +981,16 @@ void *ru_thread(void *param)
proc->tti_rx * gNB->frame_parms.samples_per_slot_wCP);
// Do PRACH RU processing
- prach_item_t *p =
- find_nr_prach(&gNB->prach_list, proc->frame_rx, proc->tti_rx, gNB->frame_parms.nb_antennas_rx, NR_SEARCH_EXIST);
- if (p) {
+ fsn_t now = {.f = proc->frame_rx, .s = proc->tti_rx, .mu = fp->numerology_index};
+ prach_item_t p;
+ while (get_next_nr_prach(&gNB->prach_ru_queue, &now, &p)) {
// need to extract RACH data for later processing by rx_nr_prach()
- rx_nr_prach_ru(p, ru->common.rxdata, ru->nr_frame_parms, ru->N_TA_offset);
+ rx_nr_prach_ru(&p, ru->common.rxdata, ru->nr_frame_parms, ru->N_TA_offset);
+ bool success = spsc_q_put(&gNB->prach_l1rx_queue, &p, sizeof(p));
+ // assume prach_l1rx_queue never full: prach_ru_queue filled at
+ // constant pace, but prach_l1rx_queue emptied as fast as possible,
+ // see rx_func()
+ DevAssert(success);
} // end if (prach_id >= 0)
} // end if (ru->feprx)
} // end if (slot_type == NR_UPLINK_SLOT || slot_type == NR_MIXED_SLOT) {
diff --git a/executables/ru_control.c b/executables/ru_control.c
index 11a3ef0f14..1852a67afb 100644
--- a/executables/ru_control.c
+++ b/executables/ru_control.c
@@ -27,7 +27,7 @@
#include "radio/COMMON/common_lib.h"
#include "radio/ETHERNET/ethernet_lib.h"
-#include "PHY/LTE_TRANSPORT/if4_tools.h"
+#include "PHY/if4_tools.h"
#include "PHY/LTE_TRANSPORT/transport_proto.h"
#include "SCHED/sched_eNB.h"
diff --git a/nfapi/oai_integration/wls_integration/wls_pnf.c b/nfapi/oai_integration/wls_integration/wls_pnf.c
index 42c09b4845..738f15a1a1 100644
--- a/nfapi/oai_integration/wls_integration/wls_pnf.c
+++ b/nfapi/oai_integration/wls_integration/wls_pnf.c
@@ -183,7 +183,7 @@ bool wls_pnf_nr_send_p5_message(pnf_t *pnf, nfapi_nr_p4_p5_message_header_t *msg
bool wls_pnf_nr_send_p7_message(pnf_p7_t *pnf_p7, nfapi_nr_p7_message_header_t *msg, uint32_t msg_len)
{
- UNUSED_VARIABLE(msg_len);
+ UNUSED(msg_len);
if (pnf_p7->terminate) {
// don't send any further P7 messages after terminating
return false;
diff --git a/nfapi/oai_integration/wls_integration/wls_vnf.c b/nfapi/oai_integration/wls_integration/wls_vnf.c
index a250188c78..7249bae551 100644
--- a/nfapi/oai_integration/wls_integration/wls_vnf.c
+++ b/nfapi/oai_integration/wls_integration/wls_vnf.c
@@ -410,7 +410,7 @@ int wls_fapi_nr_vnf_start(nfapi_vnf_config_t *cfg)
bool wls_vnf_nr_send_p5_message(vnf_t *vnf, uint16_t p5_idx, nfapi_nr_p4_p5_message_header_t *msg, uint32_t msg_len)
{
- UNUSED_VARIABLE(p5_idx);
+ UNUSED(p5_idx);
int packed_len =
vnf->_public.pack_func(msg, msg_len, vnf->tx_message_buffer, sizeof(vnf->tx_message_buffer), &vnf->_public.codec_config);
diff --git a/openair1/PHY/INIT/nr_init.c b/openair1/PHY/INIT/nr_init.c
index 59bdd7012d..35b27468f6 100644
--- a/openair1/PHY/INIT/nr_init.c
+++ b/openair1/PHY/INIT/nr_init.c
@@ -50,6 +50,8 @@ int l1_north_init_gNB()
NR_gNB_PHY_STATS_t *get_phy_stats(PHY_VARS_gNB *gNB, uint16_t rnti)
{
+ // TODO reimplement with hashtable? also called from both UL/DL => not
+ // thread-safe
NR_gNB_PHY_STATS_t *stats;
int first_free = -1;
for (int i = 0; i < MAX_MOBILES_PER_GNB; i++) {
@@ -141,16 +143,6 @@ void phy_init_nr_gNB(PHY_VARS_gNB *gNB)
init_DLSCH_struct(gNB);
- gNB->nr_srs_info = (nr_srs_info_t **)malloc16_clear(gNB->max_nb_srs * sizeof(nr_srs_info_t*));
- for (int id = 0; id < gNB->max_nb_srs; id++) {
- gNB->nr_srs_info[id] = (nr_srs_info_t *)malloc16_clear(sizeof(nr_srs_info_t));
- gNB->nr_srs_info[id]->srs_generated_signal = malloc16_clear(MAX_NUM_NR_SRS_AP * sizeof(c16_t *));
- for(int ap=0; apnr_srs_info[id]->srs_generated_signal[ap] =
- malloc16_clear(fp->ofdm_symbol_size * MAX_NUM_NR_SRS_SYMBOLS * sizeof(c16_t));
- }
- }
-
/* Do NOT allocate per-antenna rxdataF: the gNB gets a pointer to the
* RU to copy/recover freq-domain memory from there */
common_vars->rxdataF = (c16_t ***)malloc16(common_vars->num_beams_period * sizeof(c16_t**));
@@ -174,7 +166,7 @@ void phy_init_nr_gNB(PHY_VARS_gNB *gNB)
common_vars->debugBuff_sample_offset = 0;
// PRACH
- init_prach_list(&gNB->prach_list);
+ init_nr_prach(gNB);
int N_RB_UL = cfg->carrier_config.ul_grid_size[cfg->ssb_config.scs_common.value].value;
int n_buf = Prx*max_ul_mimo_layers;
@@ -212,19 +204,11 @@ void phy_free_nr_gNB(PHY_VARS_gNB *gNB)
PHY_MEASUREMENTS_gNB *meas = &gNB->measurements;
free_and_zero(meas->n0_subband_power);
- for (int id = 0; id < gNB->max_nb_srs; id++) {
- for(int i=0; inr_srs_info[id]->srs_generated_signal[i]);
- }
- free_and_zero(gNB->nr_srs_info[id]->srs_generated_signal);
- free_and_zero(gNB->nr_srs_info[id]);
- }
- free_and_zero(gNB->nr_srs_info);
-
free_ul_reference_signal_sequences();
free_gnb_lowpapr_sequences();
reset_nr_transport(gNB);
+ reset_nr_prach(gNB);
destroy_DLSCH_struct(gNB);
@@ -437,18 +421,14 @@ void init_nr_transport(PHY_VARS_gNB *gNB)
else
buffer_ul_slots = (nb_ul_slots_period < slot_ahead) ? nb_ul_slots_period : slot_ahead;
- gNB->max_nb_pucch = buffer_ul_slots ? MAX_MOBILES_PER_GNB * buffer_ul_slots : 1;
gNB->max_nb_pusch = buffer_ul_slots ? MAX_MOBILES_PER_GNB * buffer_ul_slots : 1;
- gNB->max_nb_srs = buffer_ul_slots ? buffer_ul_slots << 1 : 1; // assuming at most 2 SRS per slot
- gNB->pucch = (NR_gNB_PUCCH_t *)malloc16(gNB->max_nb_pucch * sizeof(NR_gNB_PUCCH_t));
- for (int i = 0; i < gNB->max_nb_pucch; i++) {
- memset(&gNB->pucch[i], 0, sizeof(gNB->pucch[i]));
- }
+ int max_nb_pucch = buffer_ul_slots ? MAX_MOBILES_PER_GNB * buffer_ul_slots : 1;
+ gNB->pucch_queue = spsc_q_alloc(max_nb_pucch, sizeof(NR_gNB_PUCCH_job_t));
+ gNB->pusch_queue = spsc_q_alloc(gNB->max_nb_pusch, sizeof(NR_gNB_PUSCH_job_t));
- gNB->srs = (NR_gNB_SRS_t *)malloc16(gNB->max_nb_srs * sizeof(NR_gNB_SRS_t));
- for (int i = 0; i < gNB->max_nb_srs; i++)
- gNB->srs[i].active = 0;
+ int max_nb_srs = buffer_ul_slots ? buffer_ul_slots << 1 : 1; // assuming at most 2 SRS per slot
+ gNB->srs_queue = spsc_q_alloc(max_nb_srs, sizeof(NR_gNB_SRS_job_t));
gNB->ulsch = (NR_gNB_ULSCH_t *)malloc16(gNB->max_nb_pusch * sizeof(NR_gNB_ULSCH_t));
for (int i = 0; i < gNB->max_nb_pusch; i++) {
@@ -465,8 +445,9 @@ void reset_nr_transport(PHY_VARS_gNB *gNB)
{
const NR_DL_FRAME_PARMS *fp = &gNB->frame_parms;
- free(gNB->pucch);
- free(gNB->srs);
+ spsc_q_free(&gNB->pucch_queue);
+ spsc_q_free(&gNB->pusch_queue);
+ spsc_q_free(&gNB->srs_queue);
for (int i = 0; i < gNB->max_nb_pusch; i++)
free_gNB_ulsch(&gNB->ulsch[i], fp->N_RB_UL);
diff --git a/openair1/PHY/INIT/nr_init_ru.c b/openair1/PHY/INIT/nr_init_ru.c
index 0cbb679f82..71ad18ab62 100644
--- a/openair1/PHY/INIT/nr_init_ru.c
+++ b/openair1/PHY/INIT/nr_init_ru.c
@@ -3,7 +3,6 @@
*/
#include "PHY/phy_extern.h"
-#include "SCHED/sched_common.h"
#include "assertions.h"
#include
#include "openair1/PHY/defs_RU.h"
diff --git a/openair1/PHY/INIT/nr_init_ue.c b/openair1/PHY/INIT/nr_init_ue.c
index d7d73e1c01..cccf4cf3a8 100644
--- a/openair1/PHY/INIT/nr_init_ue.c
+++ b/openair1/PHY/INIT/nr_init_ue.c
@@ -251,8 +251,6 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB)
ue->nr_csi_info->csi_rs_generated_signal[i] =
malloc16_clear(fp->samples_per_slot_wCP * sizeof(**ue->nr_csi_info->csi_rs_generated_signal));
}
-
- ue->nr_srs_info = malloc16_clear(sizeof(nr_srs_info_t));
}
ue->init_averaging = 1;
@@ -301,8 +299,6 @@ void term_nr_ue_signal(PHY_VARS_NR_UE *ue)
free_and_zero(ue->nr_csi_info->csi_rs_generated_signal);
free_and_zero(ue->nr_csi_info);
- free_and_zero(ue->nr_srs_info);
-
free_and_zero(ue->prach_vars[gNB_id]);
}
diff --git a/openair1/PHY/LTE_TRANSPORT/prach.c b/openair1/PHY/LTE_TRANSPORT/prach.c
index b821aa758e..6751f68da0 100644
--- a/openair1/PHY/LTE_TRANSPORT/prach.c
+++ b/openair1/PHY/LTE_TRANSPORT/prach.c
@@ -7,9 +7,7 @@
*/
#include "PHY/sse_intrin.h"
#include "PHY/defs_eNB.h"
-//#include "PHY/phy_extern.h"
-//#include "prach.h"
-#include "PHY/LTE_TRANSPORT/if4_tools.h"
+#include "PHY/if4_tools.h"
#include "SCHED/sched_eNB.h"
#include "common/utils/LOG/vcd_signal_dumper.h"
diff --git a/openair1/PHY/LTE_UE_TRANSPORT/dci_tools_ue.c b/openair1/PHY/LTE_UE_TRANSPORT/dci_tools_ue.c
index 2f04a0eeaf..b85b05277d 100644
--- a/openair1/PHY/LTE_UE_TRANSPORT/dci_tools_ue.c
+++ b/openair1/PHY/LTE_UE_TRANSPORT/dci_tools_ue.c
@@ -4255,7 +4255,7 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu,
LOG_D(PHY,"Format 0 DCI :ulsch (ue): cshift %d\n",ulsch->harq_processes[harq_pid]->n_DMRS2);
LOG_D(PHY,"Format 0 DCI :ulsch (ue): phich status %d\n",ulsch->harq_processes[harq_pid]->status);
#else
- UNUSED_VARIABLE(dai);
+ UNUSED(dai);
#endif
return(0);
} else {
@@ -4889,7 +4889,7 @@ int generate_eNB_ulsch_params_from_dci(PHY_VARS_eNB *eNB,
printf("ulsch (eNB): Nsymb_pusch %d\n",ulsch->harq_processes[harq_pid]->Nsymb_pusch);
printf("ulsch (eNB): cshift %d\n",ulsch->harq_processes[harq_pid]->n_DMRS2);
#else
- UNUSED_VARIABLE(dai);
+ UNUSED(dai);
#endif
return(0);
} else {
diff --git a/openair1/PHY/LTE_UE_TRANSPORT/prach_ue.c b/openair1/PHY/LTE_UE_TRANSPORT/prach_ue.c
index 62268ef930..b5abfdea92 100644
--- a/openair1/PHY/LTE_UE_TRANSPORT/prach_ue.c
+++ b/openair1/PHY/LTE_UE_TRANSPORT/prach_ue.c
@@ -10,7 +10,7 @@
#include "executables/lte-softmodem.h"
#include "PHY/phy_extern_ue.h"
//#include "prach.h"
-#include "PHY/LTE_TRANSPORT/if4_tools.h"
+#include "PHY/if4_tools.h"
#include "SCHED_UE/sched_UE.h"
#include "SCHED/sched_common_extern.h"
diff --git a/openair1/PHY/MODULATION/beamforming.c b/openair1/PHY/MODULATION/beamforming.c
index 56def37b41..f65a1bac48 100644
--- a/openair1/PHY/MODULATION/beamforming.c
+++ b/openair1/PHY/MODULATION/beamforming.c
@@ -9,7 +9,6 @@
#include "PHY/CODING/lte_interleaver_inline.h"
#include "PHY/LTE_TRANSPORT/transport_eNB.h"
#include "modulation_eNB.h"
-#include "nr_modulation.h"
#include "common/utils/LOG/vcd_signal_dumper.h"
int beam_precoding(int32_t **txdataF,
@@ -80,25 +79,3 @@ int beam_precoding_one_eNB(int32_t **txdataF,
}
return 0;
}
-
-
-void nr_beam_precoding(c16_t **txdataF,
- c16_t **txdataF_BF,
- NR_DL_FRAME_PARMS *frame_parms,
- int32_t ***beam_weights,
- int symbol,
- int aa,
- int nb_antenna_ports,
- int offset)
-{
- // clear txdata_BF[aa][re] for each call of ue_spec_beamforming
- memset(&txdataF_BF[aa][symbol*frame_parms->ofdm_symbol_size], 0, sizeof(c16_t) *(frame_parms->ofdm_symbol_size));
-
- for (int p = 0; p < nb_antenna_ports; p++) {
- multadd_cpx_vector((c16_t *)&txdataF[p][(symbol * frame_parms->ofdm_symbol_size) + offset],
- (c16_t *)beam_weights[p][aa],
- (c16_t *)&txdataF_BF[aa][symbol * frame_parms->ofdm_symbol_size],
- frame_parms->ofdm_symbol_size,
- 15);
- }
-}
diff --git a/openair1/PHY/MODULATION/nr_beamforming.c b/openair1/PHY/MODULATION/nr_beamforming.c
new file mode 100644
index 0000000000..a10b95d6d2
--- /dev/null
+++ b/openair1/PHY/MODULATION/nr_beamforming.c
@@ -0,0 +1,27 @@
+/*
+ * SPDX-License-Identifier: LicenseRef-CSSL-1.0
+ */
+
+#include "nr_modulation.h"
+#include "openair1/PHY/TOOLS/tools_defs.h"
+
+void nr_beam_precoding(c16_t **txdataF,
+ c16_t **txdataF_BF,
+ NR_DL_FRAME_PARMS *frame_parms,
+ int32_t ***beam_weights,
+ int symbol,
+ int aa,
+ int nb_antenna_ports,
+ int offset)
+{
+ // clear txdata_BF[aa][re] for each call of ue_spec_beamforming
+ memset(&txdataF_BF[aa][symbol*frame_parms->ofdm_symbol_size], 0, sizeof(c16_t) *(frame_parms->ofdm_symbol_size));
+
+ for (int p = 0; p < nb_antenna_ports; p++) {
+ multadd_cpx_vector((c16_t *)&txdataF[p][(symbol * frame_parms->ofdm_symbol_size) + offset],
+ (c16_t *)beam_weights[p][aa],
+ (c16_t *)&txdataF_BF[aa][symbol * frame_parms->ofdm_symbol_size],
+ frame_parms->ofdm_symbol_size,
+ 15);
+ }
+}
diff --git a/openair1/PHY/MODULATION/nr_modulation.c b/openair1/PHY/MODULATION/nr_modulation.c
index e3afd9b93f..8a1349b648 100644
--- a/openair1/PHY/MODULATION/nr_modulation.c
+++ b/openair1/PHY/MODULATION/nr_modulation.c
@@ -3,6 +3,7 @@
*/
#include "nr_modulation.h"
+#include "openair1/PHY/TOOLS/tools_defs.h"
#include "PHY/NR_REFSIG/nr_mod_table.h"
#include "executables/softmodem-common.h"
#include
@@ -688,12 +689,12 @@ c16_t nr_layer_precoder_cm(int n_layers,
int symSz,
c16_t datatx_F_precoding[n_layers][symSz],
int ap,
- nfapi_nr_pm_pdu_t *pmi_pdu,
+ c16_t weights[NR_MAX_NB_LAYERS][NR_MAX_CSI_PORTS],
int offset)
{
c16_t precodatatx_F = {0};
for (int al = 0; al < n_layers; al++) {
- c16_t prec_weight = pmi_pdu->weights[al][ap];
+ c16_t prec_weight = weights[al][ap];
precodatatx_F = c16maddShift(datatx_F_precoding[al][offset], prec_weight, precodatatx_F, 15);
}
return precodatatx_F;
@@ -803,15 +804,15 @@ static inline __attribute__((always_inline)) __m128i cmac_prec128(__m128i y, __m
#endif
#define load_consts(Type, Instruct, Rank) \
- const Type w_c##Rank = Instruct(c16toI32(c16conj(pmi_pdu->weights[Rank][ant]))); \
- const Type w_s##Rank = Instruct(c16toI32(c16swap(pmi_pdu->weights[Rank][ant]))); \
+ const Type w_c##Rank = Instruct(c16toI32(c16conj(weights[Rank][ant]))); \
+ const Type w_s##Rank = Instruct(c16toI32(c16swap(weights[Rank][ant]))); \
const Type *in##Rank = (Type *)(txdataF_res_mapped[Rank] + sc_offset + (out-beginning));
void nr_layer_precoder_simd(const int n_layers,
const int symSz,
const c16_t txdataF_res_mapped[n_layers][symSz],
const int ant,
- const nfapi_nr_pm_pdu_t *pmi_pdu,
+ c16_t weights[NR_MAX_NB_LAYERS][NR_MAX_CSI_PORTS],
const int sc_offset,
const int re_cnt,
c16_t *txdataF_precoded)
diff --git a/openair1/PHY/MODULATION/nr_modulation.h b/openair1/PHY/MODULATION/nr_modulation.h
index ef834db509..769bf43da1 100644
--- a/openair1/PHY/MODULATION/nr_modulation.h
+++ b/openair1/PHY/MODULATION/nr_modulation.h
@@ -7,7 +7,6 @@
#include
#include "PHY/defs_nr_common.h"
-#include "PHY/defs_gNB.h"
#define DMRS_MOD_ORDER 2
/*Precoding matices: W[pmi][antenna_port][layer]*/
@@ -127,7 +126,7 @@ c16_t nr_layer_precoder_cm(int n_layers,
int symSz,
c16_t datatx_F_precoding[n_layers][symSz],
int ap,
- nfapi_nr_pm_pdu_t *pmi_pdu,
+ c16_t weights[NR_MAX_NB_LAYERS][NR_MAX_CSI_PORTS],
int offset);
/*! \brief Precoding with SIMDe, txdataF_precoded[] = prec_matrix[] * txdataF_res_mapped[]
@@ -140,7 +139,7 @@ void nr_layer_precoder_simd(const int n_layers,
const int symSz,
const c16_t txdataF_res_mapped[n_layers][symSz],
const int ant,
- const nfapi_nr_pm_pdu_t *pmi_pdu,
+ c16_t weights[NR_MAX_NB_LAYERS][NR_MAX_CSI_PORTS],
const int sc_offset,
const int re_cnt,
c16_t *txdataF_precoded);
diff --git a/openair1/PHY/MODULATION/tests/test_nr_modulation.cpp b/openair1/PHY/MODULATION/tests/test_nr_modulation.cpp
index d232c442bf..7a66696384 100644
--- a/openair1/PHY/MODULATION/tests/test_nr_modulation.cpp
+++ b/openair1/PHY/MODULATION/tests/test_nr_modulation.cpp
@@ -15,7 +15,6 @@ extern "C" {
#endif
#include "openair1/PHY/TOOLS/tools_defs.h" // c16_t
-#include "nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h" // nfapi_nr_pm_pdu_t
#include "nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h" // fapi_nr_dl_config_dci_dl_pdu_rel15_t
//#include "openair1/PHY/MODULATION/nr_modulation.h" // nr_layer_precoder_simd_[cm, simd]
@@ -25,7 +24,7 @@ c16_t nr_layer_precoder_cm(int n_layers,
int symbol_size,
c16_t (*dataF_in)[/*symbol_size*/], // c16_t dataF_in[n_layers][symbol_size]
int ant,
- nfapi_nr_pm_pdu_t *pmi_pdu,
+ c16_t weights[NR_MAX_NB_LAYERS][NR_MAX_CSI_PORTS],
int offset);
// Forward declare the function but hide the Variable-Length Array (VLA) feature from C not available in C++
@@ -33,7 +32,7 @@ void nr_layer_precoder_simd(int n_layers,
int symbol_size,
const c16_t (*dataF_in)[/*symbol_size*/], // c16_t dataF_in[n_layers][symbol_size]
int ant,
- const nfapi_nr_pm_pdu_t *pmi_pdu,
+ c16_t weights[NR_MAX_NB_LAYERS][NR_MAX_CSI_PORTS],
int offset,
int re_cnt,
c16_t *dataF_out);
@@ -65,15 +64,15 @@ TEST(NrLayerPrecoderTest, Basic)
c16_t(*dataF_in)[symbol_size] = reinterpret_cast(buffer_in.data());
c16_t(*dataF_out)[symbol_size] = reinterpret_cast(buffer_out.data());
- // Create and populate the pmi_pdu structure
- nfapi_nr_pm_pdu_t pmi_pdu = {0};
+ // Create and populate the weights
+ c16_t weights[NR_MAX_NB_LAYERS][NR_MAX_CSI_PORTS];
for (int layer = 0; layer < n_layers; ++layer) {
- pmi_pdu.weights[layer][ant] = (c16_t){-SHRT_MAX, 0};
+ weights[layer][ant] = (c16_t){-SHRT_MAX, 0};
}
// Call the C function
for (int symbol = 0; symbol < re_cnt; symbol++)
- dataF_out[ant][symbol] = nr_layer_precoder_cm(n_layers, symbol_size, dataF_in, ant, &pmi_pdu, symbol);
+ dataF_out[ant][symbol] = nr_layer_precoder_cm(n_layers, symbol_size, dataF_in, ant, weights, symbol);
// You can calculate the expected value manually or test rough correctness
for (int symbol = 0; symbol < re_cnt; symbol++) {
@@ -110,14 +109,14 @@ TEST(NrLayerPrecoderTest, SIMD)
c16_t(*dataF_in)[symbol_size] = reinterpret_cast(buffer_in.data());
c16_t(*dataF_out)[symbol_size] = reinterpret_cast(buffer_out.data());
- // Create and populate the pmi_pdu structure
- nfapi_nr_pm_pdu_t pmi_pdu = {0};
+ // Create and populate the weights
+ c16_t weights[NR_MAX_NB_LAYERS][NR_MAX_CSI_PORTS];
for (int layer = 0; layer < n_layers; ++layer) {
- pmi_pdu.weights[layer][ant] = (c16_t){-SHRT_MAX, 0};
+ weights[layer][ant] = (c16_t){-SHRT_MAX, 0};
}
// Call the C function
- nr_layer_precoder_simd(n_layers, symbol_size, dataF_in, ant, &pmi_pdu, 0, re_cnt, dataF_out[ant]);
+ nr_layer_precoder_simd(n_layers, symbol_size, dataF_in, ant, weights, 0, re_cnt, dataF_out[ant]);
// You can calculate the expected value manually or test rough correctness
for (int symbol = 0; symbol < re_cnt; symbol++) {
@@ -156,15 +155,14 @@ TEST(NrLayerPrecoderTest, Compare_CM_SIMD)
c16_t(*dataF_out_cm)[symbol_size] = reinterpret_cast(buffer_out_cm.data());
c16_t(*dataF_out_simd)[symbol_size] = reinterpret_cast(buffer_out_simd.data());
- // Create and populate the pmi_pdu structure
- nfapi_nr_pm_pdu_t pmi_pdu = {0};
- pmi_pdu.pm_idx = 4;
+ // Create and populate the weights
+ c16_t weights[NR_MAX_NB_LAYERS][NR_MAX_CSI_PORTS];
for (int layer = 0; layer < n_layers; ++layer) {
// Could not use convert_precoder_weight() as complex.h could not be used in googletest
// Use the logic in convert_precoder_weight()
// precoder [−1,−j]
- pmi_pdu.weights[layer][0] = (c16_t){-SHRT_MAX, 0};
- pmi_pdu.weights[layer][1] = (c16_t){0, -SHRT_MAX};
+ weights[layer][0] = (c16_t){-SHRT_MAX, 0};
+ weights[layer][1] = (c16_t){0, -SHRT_MAX};
}
// Get the results for all the antenna
@@ -172,10 +170,10 @@ TEST(NrLayerPrecoderTest, Compare_CM_SIMD)
// Call the C function
for (int symbol = 0; symbol < re_cnt; symbol++)
- dataF_out_cm[ant][symbol] = nr_layer_precoder_cm(n_layers, symbol_size, dataF_in, ant, &pmi_pdu, symbol);
+ dataF_out_cm[ant][symbol] = nr_layer_precoder_cm(n_layers, symbol_size, dataF_in, ant, weights, symbol);
// Call the C function
- nr_layer_precoder_simd(n_layers, symbol_size, dataF_in, ant, &pmi_pdu, 0, re_cnt, dataF_out_simd[ant]);
+ nr_layer_precoder_simd(n_layers, symbol_size, dataF_in, ant, weights, 0, re_cnt, dataF_out_simd[ant]);
// Compare the result from both C function
for (int symbol = 0; symbol < re_cnt; symbol++) {
diff --git a/openair1/PHY/NR_ESTIMATION/nr_freq_equalization.c b/openair1/PHY/NR_ESTIMATION/nr_freq_equalization.c
index fd7530b0d9..75589c75f8 100644
--- a/openair1/PHY/NR_ESTIMATION/nr_freq_equalization.c
+++ b/openair1/PHY/NR_ESTIMATION/nr_freq_equalization.c
@@ -2,7 +2,6 @@
* SPDX-License-Identifier: LicenseRef-CSSL-1.0
*/
-#include "PHY/defs_eNB.h"
#include "PHY/sse_intrin.h"
#include "PHY/NR_ESTIMATION/nr_ul_estimation.h"
diff --git a/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c b/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c
index a901f8dba1..1f8be0fa38 100644
--- a/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c
+++ b/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c
@@ -123,12 +123,12 @@ void dump_nr_I0_stats(FILE *fd, PHY_VARS_gNB *gNB)
fprintf(fd, "\nPRACH I0 = %d.%d dB\n", gNB->measurements.prach_I0 / 10, gNB->measurements.prach_I0 % 10);
}
-void gNB_I0_measurements(PHY_VARS_gNB *gNB, int slot, int first_symb, int num_symb, uint32_t rb_mask_ul[14][9])
+void gNB_I0_measurements(PHY_VARS_gNB *gNB, int slot, int first_symb, int num_symb, uint32_t rb_mask_ul[14][MAX_BWP_SIZE])
{
NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms;
NR_gNB_COMMON *common_vars = &gNB->common_vars;
PHY_MEASUREMENTS_gNB *measurements = &gNB->measurements;
- int nb_symb[275]={0};
+ int nb_symb[MAX_BWP_SIZE] = {0};
unsigned int tmp_n0_subband[frame_parms->nb_antennas_rx][frame_parms->N_RB_UL];
memset(tmp_n0_subband, 0, sizeof(tmp_n0_subband));
@@ -137,7 +137,7 @@ void gNB_I0_measurements(PHY_VARS_gNB *gNB, int slot, int first_symb, int num_sy
for (int s = first_symb; s < first_symb + num_symb; s++) {
int offset0 = ((slot % RU_RX_SLOT_DEPTH) * frame_parms->symbols_per_slot + s) * frame_parms->ofdm_symbol_size;
for (int rb = 0; rb < frame_parms->N_RB_UL; rb++) {
- if ((rb_mask_ul[s][rb >> 5] & (1U << (rb & 31))) == 0 && // check that rb was not used in this subframe
+ if (rb_mask_ul[s][rb] == 0 && // check that rb was not used in this subframe
!(I0_SKIP_DC && rb == frame_parms->N_RB_UL >> 1)) { // skip middle PRB because of artificial noise possibly created by FFT
int offset = offset0 + (frame_parms->first_carrier_offset + (rb*12))%frame_parms->ofdm_symbol_size;
nb_symb[rb]++;
@@ -162,6 +162,7 @@ void gNB_I0_measurements(PHY_VARS_gNB *gNB, int slot, int first_symb, int num_sy
int32_t n0_subband_tot_perANT[frame_parms->nb_antennas_rx];
memset(n0_subband_tot_perANT, 0, sizeof(n0_subband_tot_perANT));
+ bool init_meas = measurements->n0_subband_power == NULL;
allocCast2D(n0_subband_power,
unsigned int,
measurements->n0_subband_power,
@@ -174,6 +175,9 @@ void gNB_I0_measurements(PHY_VARS_gNB *gNB, int slot, int first_symb, int num_sy
if (nb_symb[rb] > 0) {
for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) {
tmp_n0_subband[aarx][rb] /= nb_symb[rb];
+ // Initialize n0_subband_power from the first measurement before EMA
+ if (init_meas)
+ n0_subband_power[aarx][rb] = tmp_n0_subband[aarx][rb];
// apply exponential moving average to smooth noise measurements
n0_subband_power[aarx][rb] = 0.9 * n0_subband_power[aarx][rb] + 0.1 * tmp_n0_subband[aarx][rb];
n0_subband_tot_perPRB += n0_subband_power[aarx][rb];
diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c
index 4d70db6f02..a5190997fa 100644
--- a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c
+++ b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c
@@ -34,7 +34,7 @@ typedef struct puschAntennaProc_s {
int aarx;
int beam_nb;
int numAntennas;
- nfapi_nr_pusch_pdu_t *pusch_pdu;
+ const nfapi_nr_pusch_pdu_t *pusch_pdu;
int *max_ch;
c16_t *pilot;
int *nest_count;
@@ -82,7 +82,7 @@ static void nr_pusch_antenna_processing(void *arg)
int aarx = rdata->aarx;
int numAntennas = rdata->numAntennas;
unsigned short bwp_start_subcarrier = rdata->bwp_start_subcarrier;
- nfapi_nr_pusch_pdu_t *pusch_pdu = rdata->pusch_pdu;
+ const nfapi_nr_pusch_pdu_t *pusch_pdu = rdata->pusch_pdu;
int *max_ch = rdata->max_ch;
c16_t *pilot = rdata->pilot;
uint64_t noise_amp2 = *(rdata->noise_amp2);
@@ -452,10 +452,10 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
int nl,
unsigned short p,
unsigned char symbol,
- int ul_id,
+ NR_gNB_PUSCH *pusch_vars,
int beam_nb,
unsigned short bwp_start_subcarrier,
- nfapi_nr_pusch_pdu_t *pusch_pdu,
+ const nfapi_nr_pusch_pdu_t *pusch_pdu,
int *max_ch,
uint32_t *nvar,
c16_t *pusch_dmrs_slot_mem,
@@ -534,7 +534,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
int nest_count = 0;
uint64_t noise_amp2 = 0;
- delay_t *delay = &gNB->ulsch[ul_id].delay;
+ delay_t *delay = &pusch_vars->delay;
memset(delay, 0, sizeof(*delay));
int nb_antennas_rx = fp->nb_antennas_rx;
@@ -579,7 +579,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
rdata->delay = &delay_arr[rdata->aarx];
rdata->beam_nb = beam_nb;
rdata->frame_parms = fp;
- rdata->pusch_vars = &gNB->pusch_vars[ul_id];
+ rdata->pusch_vars = pusch_vars;
rdata->chest_freq = gNB->chest_freq;
rdata->rxdataF = gNB->common_vars.rxdataF;
rdata->scope = gNB->scopeData;
@@ -628,7 +628,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
*
* PARAMETERS : gNB : gNB data structure
* rel15_ul : UL parameters
- * UE_id : UE ID
+ * pusch_vars : PUSCH data
* nr_tti_rx : slot rx TTI
* dmrs_symbol_flag: DMRS Symbol Flag
* symbol : OFDM Symbol
@@ -646,25 +646,22 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
// #define DEBUG_UL_PTRS
void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB,
NR_DL_FRAME_PARMS *frame_parms,
- nfapi_nr_pusch_pdu_t *rel15_ul,
- uint8_t ulsch_id,
+ const nfapi_nr_pusch_pdu_t *rel15_ul,
+ NR_gNB_PUSCH *pusch_vars,
uint8_t nr_tti_rx,
unsigned char symbol,
uint32_t nb_re_pusch)
{
- NR_gNB_PUSCH *pusch_vars = &gNB->pusch_vars[ulsch_id];
int32_t *ptrs_re_symbol = NULL;
int8_t ret = 0;
uint8_t symbInSlot = rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols;
- uint8_t *startSymbIndex = &rel15_ul->start_symbol_index;
- uint8_t *nbSymb = &rel15_ul->nr_of_symbols;
- uint8_t *L_ptrs = &rel15_ul->pusch_ptrs.ptrs_time_density;
- uint8_t *K_ptrs = &rel15_ul->pusch_ptrs.ptrs_freq_density;
- uint16_t *dmrsSymbPos = &rel15_ul->ul_dmrs_symb_pos;
- uint16_t *ptrsSymbPos = &pusch_vars->ptrs_symbols;
- uint8_t *ptrsSymbIdx = &pusch_vars->ptrs_symbol_index;
- uint16_t *nb_rb = &rel15_ul->rb_size;
- uint8_t *ptrsReOffset = &rel15_ul->pusch_ptrs.ptrs_ports_list[0].ptrs_re_offset;
+ uint8_t startSymbIndex = rel15_ul->start_symbol_index;
+ uint8_t nbSymb = rel15_ul->nr_of_symbols;
+ uint8_t L_ptrs = rel15_ul->pusch_ptrs.ptrs_time_density;
+ uint8_t K_ptrs = rel15_ul->pusch_ptrs.ptrs_freq_density;
+ uint16_t dmrsSymbPos = rel15_ul->ul_dmrs_symb_pos;
+ uint16_t nb_rb = rel15_ul->rb_size;
+ uint8_t ptrsReOffset = rel15_ul->pusch_ptrs.ptrs_ports_list[0].ptrs_re_offset;
/* loop over antennas */
for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) {
@@ -673,7 +670,7 @@ void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB,
*ptrs_re_symbol = 0;
phase_per_symbol[symbol].i = 0;
/* set DMRS estimates to 0 angle with magnitude 1 */
- if (is_dmrs_symbol(symbol, *dmrsSymbPos)) {
+ if (is_dmrs_symbol(symbol, dmrsSymbPos)) {
/* set DMRS real estimation to 32767 */
phase_per_symbol[symbol].r = INT16_MAX; // 32767
#ifdef DEBUG_UL_PTRS
@@ -683,17 +680,13 @@ void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB,
phase_per_symbol[symbol].r = 0;
}
- if (symbol == *startSymbIndex) {
- *ptrsSymbPos = 0;
- set_ptrs_symb_idx(ptrsSymbPos, *nbSymb, *startSymbIndex, 1 << *L_ptrs, *dmrsSymbPos);
+ if (symbol == startSymbIndex) {
+ pusch_vars->ptrs_symbols = 0;
+ set_ptrs_symb_idx(&pusch_vars->ptrs_symbols, nbSymb, startSymbIndex, 1 << L_ptrs, dmrsSymbPos);
}
- /* if not PTRS symbol set current ptrs symbol index to zero*/
- *ptrsSymbIdx = 0;
-
/* Check if current symbol contains PTRS */
- if (is_ptrs_symbol(symbol, *ptrsSymbPos)) {
- *ptrsSymbIdx = symbol;
+ if (is_ptrs_symbol(symbol, pusch_vars->ptrs_symbols)) {
/*------------------------------------------------------------------------------------------------------- */
/* 1) Estimate common phase error per PTRS symbol */
/*------------------------------------------------------------------------------------------------------- */
@@ -703,9 +696,9 @@ void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB,
rel15_ul->scid,
nr_tti_rx,
symbol);
- nr_ptrs_cpe_estimation(*K_ptrs,
- *ptrsReOffset,
- *nb_rb,
+ nr_ptrs_cpe_estimation(K_ptrs,
+ ptrsReOffset,
+ nb_rb,
rel15_ul->rnti,
frame_parms->ofdm_symbol_size,
&pusch_vars->rxdataF_comp[aarx][(symbol * nb_re_pusch)],
@@ -720,8 +713,8 @@ void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB,
/* 2) Interpolate PTRS estimated value in TD */
/*------------------------------------------------------------------------------------------------------- */
/* If L-PTRS is > 0 then we need interpolation */
- if (*L_ptrs > 0) {
- ret = nr_ptrs_process_slot(*dmrsSymbPos, *ptrsSymbPos, (int16_t *)phase_per_symbol, *startSymbIndex, *nbSymb);
+ if (L_ptrs > 0) {
+ ret = nr_ptrs_process_slot(dmrsSymbPos, pusch_vars->ptrs_symbols, (int16_t *)phase_per_symbol, startSymbIndex, nbSymb);
if (ret != 0) {
LOG_W(PHY, "[PTRS] Compensation is skipped due to error in PTRS slot processing !!\n");
}
@@ -730,17 +723,17 @@ void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB,
/*------------------------------------------------------------------------------------------------------- */
/* 3) Compensated DMRS based estimated signal with PTRS estimation */
/*--------------------------------------------------------------------------------------------------------*/
- for (uint8_t i = *startSymbIndex; i < symbInSlot; i++) {
+ for (uint8_t i = startSymbIndex; i < symbInSlot; i++) {
/* DMRS Symbol has 0 phase so no need to rotate the respective symbol */
/* Skip rotation if the slot processing is wrong */
- if ((!is_dmrs_symbol(i, *dmrsSymbPos)) && (ret == 0)) {
+ if ((!is_dmrs_symbol(i, dmrsSymbPos)) && (ret == 0)) {
#ifdef DEBUG_UL_PTRS
printf("[PHY][UL][PTRS]: Rotate Symbol %2d with %d + j* %d\n", i, phase_per_symbol[i].r, phase_per_symbol[i].i);
#endif
rotate_cpx_vector(&pusch_vars->rxdataF_comp[aarx][i * nb_re_pusch],
&phase_per_symbol[i],
&pusch_vars->rxdataF_comp[aarx][i * nb_re_pusch],
- ((*nb_rb) * NR_NB_SC_PER_RB),
+ (nb_rb * NR_NB_SC_PER_RB),
15);
} // if not DMRS Symbol
} // symbol loop
diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h b/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h
index 540a04ec52..34bf64cc51 100644
--- a/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h
+++ b/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h
@@ -17,7 +17,7 @@
\param Ns slot number (0..19)
\param p
\param symbol symbol within slot
-\param ul_id
+\param pusch_vars lower-phy PUSCH info
\param bwp_start_subcarrier first allocated subcarrier
\param pusch_pdu
\param max_ch maximum value of estimated channel
@@ -29,10 +29,10 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
int nl,
unsigned short p,
unsigned char symbol,
- int ul_id,
+ NR_gNB_PUSCH *pusch_vars,
int beam_nb,
unsigned short bwp_start_subcarrier,
- nfapi_nr_pusch_pdu_t *pusch_pdu,
+ const nfapi_nr_pusch_pdu_t *pusch_pdu,
int *max_ch,
uint32_t *nvar,
c16_t *pusch_dmrs_slot_mem,
@@ -40,7 +40,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
void dump_nr_I0_stats(FILE *fd,PHY_VARS_gNB *gNB);
-void gNB_I0_measurements(PHY_VARS_gNB *gNB, int slot, int first_symb, int num_symb, uint32_t rb_mask_ul[14][9]);
+void gNB_I0_measurements(PHY_VARS_gNB *gNB, int slot, int first_symb, int num_symb, uint32_t rb_mask_ul[14][MAX_BWP_SIZE]);
void nr_est_srs_timing_advance_offset(uint16_t ofdm_symbol_size,
const c16_t srs_estimated_channel_time[][NR_SRS_IDFT_OVERSAMP_FACTOR * ofdm_symbol_size],
@@ -52,8 +52,8 @@ void nr_est_srs_timing_advance_offset(uint16_t ofdm_symbol_size,
void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB,
NR_DL_FRAME_PARMS *frame_parms,
- nfapi_nr_pusch_pdu_t *rel15_ul,
- uint8_t ulsch_id,
+ const nfapi_nr_pusch_pdu_t *rel15_ul,
+ NR_gNB_PUSCH *pusch_vars,
uint8_t nr_tti_rx,
unsigned char symbol,
uint32_t nb_re_pusch);
diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c
index d227148353..8f1bb827be 100644
--- a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c
+++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c
@@ -438,7 +438,7 @@ static inline void do_txdataF(c16_t **txdataF,
symbol_sz,
txdataF_precoding,
ant,
- pmi_pdu,
+ pmi_pdu->weights,
subCarrier,
re_cnt,
&txdataF[ant][txdataF_offset_per_symbol]);
diff --git a/openair1/PHY/NR_TRANSPORT/nr_prach.c b/openair1/PHY/NR_TRANSPORT/nr_prach.c
index c54c9ccc29..dc3cb1950d 100644
--- a/openair1/PHY/NR_TRANSPORT/nr_prach.c
+++ b/openair1/PHY/NR_TRANSPORT/nr_prach.c
@@ -12,72 +12,73 @@
#include "PHY/NR_TRANSPORT/nr_transport_common_proto.h"
#include "openair1/PHY/NR_TRANSPORT/nr_prach.h"
-void init_prach_list(prach_list_t *l)
+void init_nr_prach(PHY_VARS_gNB *gNB)
{
- pthread_mutex_init(&l->prach_list_mutex, NULL);
- memset(l->list, 0, sizeof(l->list));
+ int num_prach = 8;
+ gNB->prach_ru_queue = spsc_q_alloc(num_prach, sizeof(prach_item_t));
+ gNB->prach_l1rx_queue = spsc_q_alloc(num_prach, sizeof(prach_item_t));
}
-void free_nr_prach_entry(prach_list_t *l, prach_item_t *p)
+void reset_nr_prach(PHY_VARS_gNB *gNB)
{
- pthread_mutex_lock(&l->prach_list_mutex);
- if (p->frame == -1)
- LOG_E(NR_PHY_RACH, "Freeing a not allocated prach entry\n");
- *p = (prach_item_t){.frame = -1, .slot = -1, .num_slots = -1, .nb_rx = p->nb_rx, .prach_buf = (void *)(p + 1)};
- pthread_mutex_unlock(&l->prach_list_mutex);
+ spsc_q_free(&gNB->prach_ru_queue);
+ spsc_q_free(&gNB->prach_l1rx_queue);
}
-prach_item_t *find_nr_prach(prach_list_t *l, int frame, int slot, int nb_rx, nr_find_type_t type)
+void free_nr_prach_entry(prach_item_t *p)
{
- pthread_mutex_lock(&l->prach_list_mutex);
- AssertFatal(nb_rx, "Error! Number of antennas set to 0.\n");
- prach_item_t **p = l->list;
- prach_item_t **end = p + NUMBER_OF_NR_PRACH_MAX;
- for (; p < end; p++)
- if ((*p) && (*p)->frame == frame && ((*p)->slot + (*p)->num_slots - 1) == slot)
- break;
- if (p == end) {
- if (type == NR_SEARCH_EXIST) {
- pthread_mutex_unlock(&l->prach_list_mutex);
- return NULL;
- }
- for (p = l->list; p < end; p++)
- if (!(*p) || ((*p)->frame == -1 && (*p)->slot == -1))
- break;
- }
- if (p == end) {
- pthread_mutex_unlock(&l->prach_list_mutex);
- return NULL;
- }
- // mark it used, it will be filled later
- if (*p && (*p)->nb_rx != nb_rx) {
- LOG_W(PHY, "rach procedure nb_rx ant changed from %d to %d\n", (*p)->nb_rx, nb_rx);
- free(*p);
- *p = NULL;
- }
- if (!(*p)) {
- *p = calloc(1, sizeof(prach_item_t) + sizeof(c16_t) * nb_rx * NUMBER_OF_NR_RU_PRACH_OCCASIONS_MAX * NR_PRACH_SEQ_LEN_L);
- (*p)->prach_buf = (void *)((*p) + 1);
- }
- (*p)->nb_rx = nb_rx;
- (*p)->frame = frame;
- pthread_mutex_unlock(&l->prach_list_mutex);
- return (*p);
+ free(p->prach_buf);
}
-prach_item_t *nr_schedule_rx_prach(PHY_VARS_gNB *gNB, int SFN, int Slot, nfapi_nr_prach_pdu_t *prach_pdu)
+static bool drop_old_prach(const void *data, void *user)
+{
+ const prach_item_t *p = data;
+ const fsn_t *now = user;
+ const fsn_t t = {p->frame, p->slot, now->mu};
+ bool drop = fsn_in_the_past(t, *now);
+ if (drop)
+ LOG_E(NR_PHY, "%4d.%2d PRACH job is in the past (%4d.%2d)\n", now->f, now->s, t.f, t.s);
+ return drop;
+}
+
+static bool get_current_prach(const void *data, void *user)
+{
+ const prach_item_t *p = data;
+ const fsn_t *now = user;
+ const fsn_t t = {p->frame, p->slot, now->mu};
+ return fsn_equal(t, *now);
+}
+
+bool get_next_nr_prach(spsc_q_t *q, const fsn_t *now, prach_item_t *p)
+{
+ spsc_q_drop_while(q, drop_old_prach, (void *)now);
+ return spsc_q_get_if(q, get_current_prach, (void *)now, p, sizeof(*p));
+}
+
+void nr_schedule_rx_prach(PHY_VARS_gNB *gNB, int SFN, int Slot, nfapi_nr_prach_pdu_t *prach_pdu)
{
- prach_item_t *prach = find_nr_prach(&gNB->prach_list, SFN, Slot, gNB->frame_parms.nb_antennas_rx, NR_SEARCH_EXIST_OR_FREE);
- if (!prach) {
- LOG_W(PHY, "no free space for a new detected rach, discarding\n");
- return NULL;
- }
const int fmt = prach_pdu->prach_format;
- NR_DL_FRAME_PARMS *fp = &gNB->frame_parms;
- // we set only elements as the whole structure has been cleaned when we release it
- prach->frame = SFN;
- prach->slot = Slot;
- prach->num_slots = fmt < 4 ? get_long_prach_dur(fmt, fp->numerology_index) : 1;
+ const NR_DL_FRAME_PARMS *fp = &gNB->frame_parms;
+ const nfapi_nr_prach_config_t *cfg = &gNB->gNB_config.prach_config;
+ const nfapi_nr_num_prach_fd_occasions_t *occ = &cfg->num_prach_fd_occasions_list[prach_pdu->num_ra];
+ prach_item_t prach = {
+ .frame = SFN,
+ .slot = Slot,
+ .num_slots = fmt < 4 ? get_long_prach_dur(fmt, fp->numerology_index) : 1,
+ .pdu = *prach_pdu,
+ .rootSequenceIndex = occ->prach_root_sequence_index.value,
+ .numrootSequenceIndex = occ->num_root_sequences.value,
+ .msg1_frequencystart = occ->k1.value,
+ .mu = cfg->prach_sub_c_spacing.value,
+ .prach_sequence_length = cfg->prach_sequence_length.value,
+ .restricted_set = cfg->restricted_set_config.value,
+ .numerology_index = fp->numerology_index,
+ .nb_rx = gNB->gNB_config.carrier_config.num_rx_ant.value,
+ .Xu = gNB->X_u,
+ .rx_prach = &gNB->rx_prach,
+ // TODO can be made permanently allocated?
+ .prach_buf = calloc_or_fail(1, sizeof(c16_t) * prach.nb_rx * NUMBER_OF_NR_RU_PRACH_OCCASIONS_MAX * NR_PRACH_SEQ_LEN_L),
+ };
if (gNB->common_vars.beam_id) {
int n_symb = get_nr_prach_duration(prach_pdu->prach_format);
AssertFatal(prach_pdu->beamforming.dig_bf_interface < NFAPI_MAX_NUM_BG_IF,
@@ -87,7 +88,7 @@ prach_item_t *nr_schedule_rx_prach(PHY_VARS_gNB *gNB, int SFN, int Slot, nfapi_n
int fapi_beam_idx = prach_pdu->beamforming.prgs_list[0].dig_bf_interface_list[i].beam_idx;
int start_symb = prach_pdu->prach_start_symbol + i * n_symb;
int bitmap = SL_to_bitmap(start_symb, n_symb);
- prach->beams[i] = beam_index_allocation(gNB->enable_analog_das,
+ prach.beams[i] = beam_index_allocation(gNB->enable_analog_das,
fapi_beam_idx,
&gNB->common_vars,
Slot,
@@ -95,20 +96,9 @@ prach_item_t *nr_schedule_rx_prach(PHY_VARS_gNB *gNB, int SFN, int Slot, nfapi_n
bitmap);
}
}
- prach->pdu = *prach_pdu;
- nfapi_nr_prach_config_t *cfg = &gNB->gNB_config.prach_config;
- nfapi_nr_num_prach_fd_occasions_t *occ = &cfg->num_prach_fd_occasions_list[prach_pdu->num_ra];
- prach->rootSequenceIndex = occ->prach_root_sequence_index.value;
- prach->numrootSequenceIndex = occ->num_root_sequences.value;
- prach->msg1_frequencystart = occ->k1.value;
- prach->mu = cfg->prach_sub_c_spacing.value;
- prach->prach_sequence_length = cfg->prach_sequence_length.value;
- prach->restricted_set = cfg->restricted_set_config.value;
- prach->numerology_index = fp->numerology_index;
- prach->nb_rx = gNB->gNB_config.carrier_config.num_rx_ant.value;
- prach->Xu = gNB->X_u;
- prach->rx_prach = &gNB->rx_prach;
- return prach;
+ bool found = spsc_q_put(&gNB->prach_ru_queue, &prach, sizeof(prach));
+ if (!found)
+ LOG_W(NR_PHY, "%4d.%2d PRACH occ queue is full: dropping PRACH request\n", SFN, Slot);
}
static void rx_nr_prach_ru_internal(prach_item_t *p,
diff --git a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h
index f7497a148a..863903c242 100644
--- a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h
+++ b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h
@@ -11,6 +11,7 @@
#include "PHY/defs_nr_common.h"
#include "PHY/defs_gNB.h"
+#include "common/utils/fsn.h"
#define NR_PBCH_PDU_BITS 24
@@ -85,11 +86,19 @@ void free_gNB_dlsch(NR_gNB_DLSCH_t *dlsch, uint16_t N_RB, const NR_DL_FRAME_PARM
- LLR computation
This function supports TM1, 2, 3, 5, and 6.
@param ue Pointer to PHY variables
- @param UE_id id of current UE
+ @param pusch_vars ULSCH PUSCH data
+ @param rel15_ul FAPI message to process
+ @param unav_res unav_res result
@param frame Frame number
@param slot Slot number
*/
-int nr_rx_pusch_tp(PHY_VARS_gNB *gNB, uint8_t ulsch_id, uint32_t frame, uint8_t slot, int beam_nb);
+int nr_rx_pusch_tp(PHY_VARS_gNB *gNB,
+ NR_gNB_PUSCH *pusch_vars,
+ const nfapi_nr_pusch_pdu_t *rel15_ul,
+ uint32_t *ret_unav_res,
+ uint32_t frame,
+ uint8_t slot,
+ int beam_nb);
/*!
\brief This function implements the idft transform precoding in PUSCH
@@ -159,7 +168,7 @@ void nr_fill_ulsch(PHY_VARS_gNB *gNB,
int slot,
nfapi_nr_pusch_pdu_t *ulsch_pdu);
-prach_item_t *nr_schedule_rx_prach(PHY_VARS_gNB *gNB, int SFN, int Slot, nfapi_nr_prach_pdu_t *prach_pdu);
+void nr_schedule_rx_prach(PHY_VARS_gNB *gNB, int SFN, int Slot, nfapi_nr_prach_pdu_t *prach_pdu);
typedef struct rx_prach_out {
uint16_t max_preamble;
@@ -170,12 +179,6 @@ rx_prach_out_t rx_nr_prach(const prach_item_t *, int occasion);
void rx_nr_prach_ru(prach_item_t *, int32_t **, NR_DL_FRAME_PARMS *frame_parms, int N_TA_offset);
-typedef enum {
- NR_SEARCH_EXIST = 0,
- NR_SEARCH_EXIST_OR_FREE
-} nr_find_type_t;
-
-prach_item_t *find_nr_prach(prach_list_t *, int frame, int slot, int nb_rx, nr_find_type_t type);
void nr_fill_pucch(PHY_VARS_gNB *gNB,
int frame,
int slot,
@@ -189,30 +192,32 @@ void nr_fill_srs(PHY_VARS_gNB *gNB,
int nr_get_srs_signal(PHY_VARS_gNB *gNB,
c16_t **rxdataF,
slot_t slot,
- nfapi_nr_srs_pdu_t *srs_pdu,
+ const nfapi_nr_srs_pdu_t *srs_pdu,
nr_srs_info_t *nr_srs_info,
c16_t srs_received_signal[][gNB->frame_parms.ofdm_symbol_size * (1 << srs_pdu->num_symbols)],
c16_t srs_received_noise[][gNB->frame_parms.ofdm_symbol_size * (1 << srs_pdu->num_symbols)]);
-void nr_srs_rx_procedures(PHY_VARS_gNB *gNB,
+nr_srs_info_t nr_srs_rx_procedures(PHY_VARS_gNB *gNB,
int frame_rx,
int slot_rx,
uint8_t nb_antennas_rx,
uint8_t N_ap,
uint8_t N_symb_SRS,
uint16_t ofdm_symbol_size,
- NR_gNB_SRS_t *srs,
- nr_srs_info_t *nr_srs_info,
+ const NR_gNB_SRS_job_t *srs,
int *srs_est,
+ int8_t *snr,
c16_t srs_estimated_channel_freq[][N_ap][ofdm_symbol_size * N_symb_SRS],
- c16_t srs_estimated_channel_time[][N_ap][NR_SRS_IDFT_OVERSAMP_FACTOR * ofdm_symbol_size],
int16_t *snr_per_rb,
uint16_t *timing_advance_offset,
int16_t *timing_advance_offset_nsec);
int get_nr_prach_duration(uint8_t prach_format);
-void free_nr_prach_entry(prach_list_t *, prach_item_t *);
+void init_nr_prach(PHY_VARS_gNB *gNB);
+void reset_nr_prach(PHY_VARS_gNB *gNB);
+void free_nr_prach_entry(prach_item_t *);
+bool get_next_nr_prach(spsc_q_t *q, const fsn_t *now, prach_item_t *p);
void nr_decode_pucch1(PHY_VARS_gNB *gNB,
c16_t **rxdataF,
@@ -227,14 +232,14 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
int frame,
int slot,
nfapi_nr_uci_pucch_pdu_format_2_3_4_t* uci_pdu,
- nfapi_nr_pucch_pdu_t* pucch_pdu);
+ const nfapi_nr_pucch_pdu_t* pucch_pdu);
void nr_decode_pucch0(PHY_VARS_gNB *gNB,
c16_t **rxdataF,
int frame,
int slot,
nfapi_nr_uci_pucch_pdu_format_0_1_t* uci_pdu,
- nfapi_nr_pucch_pdu_t* pucch_pdu);
+ const nfapi_nr_pucch_pdu_t* pucch_pdu);
#endif /*__NR_TRANSPORT__H__*/
diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch.c
index 2d7727b55a..51d885cc1e 100644
--- a/openair1/PHY/NR_TRANSPORT/nr_ulsch.c
+++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch.c
@@ -11,30 +11,6 @@
#include "PHY/NR_TRANSPORT/nr_ulsch.h"
#include "SCHED_NR/sched_nr.h"
-static NR_gNB_ULSCH_t *find_nr_ulsch(PHY_VARS_gNB *gNB, uint16_t rnti, int pid)
-{
- int16_t first_free_index = -1;
- AssertFatal(gNB != NULL, "gNB is null\n");
- NR_gNB_ULSCH_t *ulsch = NULL;
-
- for (int i = 0; i < gNB->max_nb_pusch; i++) {
- ulsch = &gNB->ulsch[i];
- AssertFatal(ulsch, "gNB->ulsch[%d] is null\n", i);
- if (!ulsch->active) {
- if (first_free_index == -1)
- first_free_index = i;
- } else {
- // if there is already an active ULSCH for this RNTI and HARQ_PID
- if ((ulsch->harq_pid == pid) && (ulsch->rnti == rnti))
- return ulsch;
- }
- }
- if (first_free_index != -1)
- ulsch = &gNB->ulsch[first_free_index];
-
- return ulsch;
-}
-
static void dump_pusch_pdu(int instance, int frame, int slot, nfapi_nr_pusch_pdu_t *pusch_pdu)
{
LOG_D(PHY,
@@ -117,49 +93,28 @@ static void dump_pusch_pdu(int instance, int frame, int slot, nfapi_nr_pusch_pdu
void nr_fill_ulsch(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_pusch_pdu_t *ulsch_pdu)
{
dump_pusch_pdu(gNB->Mod_id, frame, slot, ulsch_pdu);
- int harq_pid = ulsch_pdu->pusch_data.harq_process_id;
- NR_gNB_ULSCH_t *ulsch = find_nr_ulsch(gNB, ulsch_pdu->rnti, harq_pid);
- if (ulsch == NULL) {
- LOG_E(NR_PHY, "No ulsch_id found for rnti %04x\n", ulsch_pdu->rnti);
- return;
- }
+ LOG_D(NR_PHY,
+ "%4d.%2d Programming ULSCH RNTI %04x HARQ PID %d new data indicator %d\n",
+ frame,
+ slot,
+ ulsch_pdu->rnti,
+ ulsch_pdu->pusch_data.harq_process_id,
+ ulsch_pdu->pusch_data.new_data_indicator);
- ulsch->rnti = ulsch_pdu->rnti;
- ulsch->harq_pid = harq_pid;
- ulsch->handled = 0;
- ulsch->active = true;
- ulsch->beam_nb = 0;
+ NR_gNB_PUSCH_job_t pusch = {.frame = frame, .slot = slot, .pusch_pdu = *ulsch_pdu};
if (gNB->common_vars.beam_id) {
int fapi_beam_idx = ulsch_pdu->beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx;
int bitmap = SL_to_bitmap(ulsch_pdu->start_symbol_index, ulsch_pdu->nr_of_symbols);
- ulsch->beam_nb = beam_index_allocation(gNB->enable_analog_das,
+ pusch.beam_nb = beam_index_allocation(gNB->enable_analog_das,
fapi_beam_idx,
&gNB->common_vars,
slot,
gNB->frame_parms.symbols_per_slot,
bitmap);
}
- ulsch->frame = frame;
- ulsch->slot = slot;
-
- NR_UL_gNB_HARQ_t *harq = ulsch->harq_process;
- if (ulsch_pdu->pusch_data.new_data_indicator)
- harq->harq_to_be_cleared = true;
- LOG_D(NR_PHY,
- "NEW ULSCH %d.%d RNTI %x HARQ PID %d new data indicator %d\n",
- frame,
- slot,
- ulsch_pdu->rnti,
- harq_pid,
- ulsch_pdu->pusch_data.new_data_indicator);
-
- if (ulsch_pdu->pusch_data.new_data_indicator)
- harq->round = 0;
- else
- harq->round++;
-
- memcpy(&ulsch->harq_process->ulsch_pdu, ulsch_pdu, sizeof(ulsch->harq_process->ulsch_pdu));
- LOG_D(PHY, "Initializing nFAPI for ULSCH, harq_pid %d, layers %d\n", harq_pid, ulsch_pdu->nrOfLayers);
+ bool done = spsc_q_put(&gNB->pusch_queue, &pusch, sizeof(pusch));
+ if (!done)
+ LOG_W(NR_PHY, "PUSCH queue is full: dropping PUSCH UE %04x\n", ulsch_pdu->rnti);
}
void reset_active_ulsch(PHY_VARS_gNB *gNB, int frame)
diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch.h b/openair1/PHY/NR_TRANSPORT/nr_ulsch.h
index b1e932f60d..816ce9a16a 100644
--- a/openair1/PHY/NR_TRANSPORT/nr_ulsch.h
+++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch.h
@@ -23,7 +23,6 @@ NR_gNB_ULSCH_t new_gNB_ulsch(uint8_t max_ldpc_iterations, uint16_t N_RB_UL);
@param frame_parms, Pointer to frame descriptor structure
@param frame, current received frame
@param nr_tti_rx, current received TTI
- @param G
@param ULSCH_ids, array of ULSCH ids
@param nb_pusch, number of uplink shared channels
*/
@@ -32,8 +31,7 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
NR_DL_FRAME_PARMS *frame_parms,
uint32_t frame,
uint8_t nr_tti_rx,
- uint32_t *G,
- uint8_t *ULSCH_ids,
+ int *ULSCH_ids,
int nb_pusch);
/*! \brief Perform PUSCH unscrambling. TS 38.211 V15.4.0 subclause 6.3.1.1
diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c
index 29a53ec5a0..9cb6e22c03 100644
--- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c
+++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c
@@ -93,8 +93,7 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
NR_DL_FRAME_PARMS *frame_parms,
uint32_t frame,
uint8_t nr_tti_rx,
- uint32_t *G,
- uint8_t *ULSCH_ids,
+ int *ULSCH_ids,
int nb_pusch)
{
nrLDPC_TB_decoding_parameters_t TBs[nb_pusch];
@@ -112,17 +111,29 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
NR_gNB_ULSCH_t *ulsch = &phy_vars_gNB->ulsch[ULSCH_id];
NR_gNB_PUSCH *pusch = &phy_vars_gNB->pusch_vars[ULSCH_id];
NR_UL_gNB_HARQ_t *harq_process = ulsch->harq_process;
- nfapi_nr_pusch_pdu_t *pusch_pdu = &harq_process->ulsch_pdu;
+ const nfapi_nr_pusch_pdu_t *pusch_pdu = &harq_process->ulsch_pdu;
nrLDPC_TB_decoding_parameters_t *TB_parameters = &TBs[pusch_id];
- TB_parameters->G = G[pusch_id];
-
if (!harq_process) {
LOG_E(PHY, "ulsch_decoding.c: NULL harq_process pointer\n");
return -1;
}
+ uint8_t number_dmrs_symbols = count_bits64_with_mask(pusch_pdu->ul_dmrs_symb_pos, pusch_pdu->start_symbol_index, pusch_pdu->nr_of_symbols);
+ int factor = pusch_pdu->dmrs_config_type == pusch_dmrs_type1 ? 6 : 4;
+ int nb_re_dmrs = factor * pusch_pdu->num_dmrs_cdm_grps_no_data;
+ uint32_t G = nr_get_G(pusch_pdu->rb_size,
+ pusch_pdu->nr_of_symbols,
+ nb_re_dmrs,
+ number_dmrs_symbols, // number of dmrs symbols irrespective of single or double symbol dmrs
+ ulsch->unav_res,
+ pusch_pdu->qam_mod_order,
+ pusch_pdu->nrOfLayers);
+ DevAssert(G > 0);
+ TB_parameters->G = G;
+
+
// The harq_pid is not unique among the active HARQ processes in the instance so we use ULSCH_id instead
TB_parameters->harq_unique_pid = ULSCH_id;
@@ -134,10 +145,9 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
// ------------------------------------------------------------------
TB_parameters->processedSegments = &harq_process->processedSegments;
- harq_process->TBS = pusch_pdu->pusch_data.tb_size;
TB_parameters->BG = pusch_pdu->maintenance_parms_v3.ldpcBaseGraph;
- TB_parameters->A = (harq_process->TBS) << 3;
+ TB_parameters->A = pusch_pdu->pusch_data.tb_size << 3;
NR_gNB_PHY_STATS_t *stats = get_phy_stats(phy_vars_gNB, ulsch->rnti);
if (stats) {
stats->frame = frame;
@@ -149,7 +159,7 @@ int nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
if (!harq_process->harq_to_be_cleared) {
stats->ulsch_stats.current_Qm = TB_parameters->Qm;
stats->ulsch_stats.current_RI = TB_parameters->nb_layers;
- stats->ulsch_stats.total_bytes_tx += harq_process->TBS;
+ stats->ulsch_stats.total_bytes_tx += pusch_pdu->pusch_data.tb_size;
}
}
diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c
index 82d6b0d99d..684e65699e 100644
--- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c
+++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c
@@ -80,7 +80,7 @@ static void nr_ulsch_extract_rbs(c16_t* const rxdataF,
int rxoffset,
int choffset,
int is_dmrs_symbol,
- nfapi_nr_pusch_pdu_t *pusch_pdu,
+ const nfapi_nr_pusch_pdu_t *pusch_pdu,
NR_DL_FRAME_PARMS *frame_parms)
{
uint8_t delta = 0;
@@ -160,7 +160,7 @@ static void nr_ulsch_extract_rbs(c16_t* const rxdataF,
}
}
-static int get_nb_re_pusch (NR_DL_FRAME_PARMS *frame_parms, nfapi_nr_pusch_pdu_t *rel15_ul,int symbol)
+static int get_nb_re_pusch (NR_DL_FRAME_PARMS *frame_parms, const nfapi_nr_pusch_pdu_t *rel15_ul, int symbol)
{
uint8_t dmrs_symbol_flag = (rel15_ul->ul_dmrs_symb_pos >> symbol) & 0x01;
if (dmrs_symbol_flag == 1) {
@@ -186,7 +186,7 @@ static void nr_ulsch_channel_compensation(uint32_t buffer_length,
c16_t **rxComp,
int nb_layers,
c16_t rho[][nb_layers][buffer_length],
- nfapi_nr_pusch_pdu_t *rel15_ul,
+ const nfapi_nr_pusch_pdu_t *rel15_ul,
uint32_t symbol,
uint32_t output_shift)
{
@@ -857,11 +857,10 @@ static uint8_t nr_ulsch_mmse_2layers(c16_t **rxdataF_comp,
}
static void inner_rx(PHY_VARS_gNB *gNB,
- int ulsch_id,
int slot,
NR_DL_FRAME_PARMS *frame_parms,
NR_gNB_PUSCH *pusch_vars,
- nfapi_nr_pusch_pdu_t *rel15_ul,
+ const nfapi_nr_pusch_pdu_t *rel15_ul,
c16_t **rxF,
int16_t **llr,
int soffset,
@@ -952,7 +951,7 @@ static void inner_rx(PHY_VARS_gNB *gNB,
nr_pusch_ptrs_processing(gNB,
frame_parms,
rel15_ul,
- ulsch_id,
+ pusch_vars,
slot,
symbol,
buffer_length);
@@ -1003,8 +1002,8 @@ static void inner_rx(PHY_VARS_gNB *gNB,
typedef struct puschSymbolProc_s {
PHY_VARS_gNB *gNB;
NR_DL_FRAME_PARMS *frame_parms;
- nfapi_nr_pusch_pdu_t *rel15_ul;
- int ulsch_id;
+ const nfapi_nr_pusch_pdu_t *rel15_ul;
+ NR_gNB_PUSCH *pusch_vars;
int slot;
int startSymbol;
int numSymbols;
@@ -1023,12 +1022,11 @@ static void nr_pusch_symbol_processing(void *arg)
PHY_VARS_gNB *gNB = rdata->gNB;
NR_DL_FRAME_PARMS *frame_parms = rdata->frame_parms;
- nfapi_nr_pusch_pdu_t *rel15_ul = rdata->rel15_ul;
- int ulsch_id = rdata->ulsch_id;
+ const nfapi_nr_pusch_pdu_t *rel15_ul = rdata->rel15_ul;
int slot = rdata->slot;
- NR_gNB_PUSCH *pusch_vars = &gNB->pusch_vars[ulsch_id];
+ NR_gNB_PUSCH *pusch_vars = rdata->pusch_vars;
for (int symbol = rdata->startSymbol; symbol < rdata->startSymbol + rdata->numSymbols; symbol++) {
- if (gNB->pusch_vars[ulsch_id].ul_valid_re_per_slot[symbol] == 0)
+ if (pusch_vars->ul_valid_re_per_slot[symbol] == 0)
continue;
int soffset = (slot % RU_RX_SLOT_DEPTH) * frame_parms->symbols_per_slot * frame_parms->ofdm_symbol_size;
int buffer_length = ceil_mod(pusch_vars->ul_valid_re_per_slot[symbol] * NR_NB_SC_PER_RB, 16);
@@ -1038,7 +1036,6 @@ static void nr_pusch_symbol_processing(void *arg)
llrss[l] = llrs[l];
inner_rx(gNB,
- ulsch_id,
slot,
frame_parms,
pusch_vars,
@@ -1047,12 +1044,12 @@ static void nr_pusch_symbol_processing(void *arg)
llrss,
soffset,
symbol,
- gNB->pusch_vars[ulsch_id].log2_maxh,
+ pusch_vars->log2_maxh,
rdata->nvar,
rdata->rxFext_slot_mem,
rdata->pusch_ch_est_dmrs_interpl_slot_mem);
- int nb_re_pusch = gNB->pusch_vars[ulsch_id].ul_valid_re_per_slot[symbol];
+ int nb_re_pusch = pusch_vars->ul_valid_re_per_slot[symbol];
// layer de-mapping
int16_t *llr_ptr = llrs[0];
if (rel15_ul->nrOfLayers != 1) {
@@ -1098,12 +1095,16 @@ static uint32_t average_u32(const uint32_t *x, uint16_t size)
return (uint32_t)(sum_x / size);
}
-int nr_rx_pusch_tp(PHY_VARS_gNB *gNB, uint8_t ulsch_id, uint32_t frame, uint8_t slot, int beam_nb)
+int nr_rx_pusch_tp(PHY_VARS_gNB *gNB,
+ NR_gNB_PUSCH *pusch_vars,
+ const nfapi_nr_pusch_pdu_t *rel15_ul,
+ uint32_t *ret_unav_res,
+ uint32_t frame,
+ uint8_t slot,
+ int beam_nb)
{
NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms;
- nfapi_nr_pusch_pdu_t *rel15_ul = &gNB->ulsch[ulsch_id].harq_process->ulsch_pdu;
- NR_gNB_PUSCH *pusch_vars = &gNB->pusch_vars[ulsch_id];
uint32_t bwp_start_subcarrier = ((rel15_ul->rb_start + rel15_ul->bwp_start) * NR_NB_SC_PER_RB + frame_parms->first_carrier_offset) % frame_parms->ofdm_symbol_size;
LOG_D(PHY,"pusch %d.%d : bwp_start_subcarrier %d, rb_start %d, first_carrier_offset %d\n", frame,slot,bwp_start_subcarrier, rel15_ul->rb_start, frame_parms->first_carrier_offset);
LOG_D(PHY,"pusch %d.%d : ul_dmrs_symb_pos %x\n",frame,slot,rel15_ul->ul_dmrs_symb_pos);
@@ -1159,7 +1160,7 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB, uint8_t ulsch_id, uint32_t frame, uint8_t
nl,
get_dmrs_port(nl, rel15_ul->dmrs_ports),
symbol,
- ulsch_id,
+ pusch_vars,
beam_nb,
bwp_start_subcarrier,
rel15_ul,
@@ -1261,7 +1262,7 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB, uint8_t ulsch_id, uint32_t frame, uint8_t
unav_res,
rel15_ul->qam_mod_order,
rel15_ul->nrOfLayers);
- gNB->ulsch[ulsch_id].unav_res = unav_res;
+ *ret_unav_res = unav_res;
// initialize scrambling sequence //
int16_t scramblingSequence[G + 96] __attribute__((aligned(32)));
@@ -1378,7 +1379,7 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB, uint8_t ulsch_id, uint32_t frame, uint8_t
rdata->startSymbol = symbol;
// Last task processes remainder symbols
rdata->numSymbols = task_index == loop_iter - 1 ? rel15_ul->nr_of_symbols - (loop_iter - 1) * numSymbols : numSymbols;
- rdata->ulsch_id = ulsch_id;
+ rdata->pusch_vars = pusch_vars;
rdata->llr = pusch_vars->llr;
rdata->scramblingSequence = scramblingSequence;
rdata->nvar = nvar;
diff --git a/openair1/PHY/NR_TRANSPORT/pucch_rx.c b/openair1/PHY/NR_TRANSPORT/pucch_rx.c
index 8017fb0bc9..fd6bd8ea42 100644
--- a/openair1/PHY/NR_TRANSPORT/pucch_rx.c
+++ b/openair1/PHY/NR_TRANSPORT/pucch_rx.c
@@ -33,40 +33,32 @@
//#define DEBUG_NR_PUCCH_RX 1
void nr_fill_pucch(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_pucch_pdu_t *pucch_pdu)
{
- for (int i = 0; i < gNB->max_nb_pucch; i++) {
- NR_gNB_PUCCH_t *pucch = &gNB->pucch[i];
- if (pucch->active == false) {
- pucch->frame = frame;
- pucch->slot = slot;
- pucch->active = true;
- pucch->beam_nb = 0;
- if (gNB->common_vars.beam_id) {
- int fapi_beam_idx = pucch_pdu->beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx;
- int bitmap = SL_to_bitmap(pucch_pdu->start_symbol_index, pucch_pdu->nr_of_symbols);
- pucch->beam_nb = beam_index_allocation(gNB->enable_analog_das,
- fapi_beam_idx,
- &gNB->common_vars,
- slot,
- gNB->frame_parms.symbols_per_slot,
- bitmap);
- }
- memcpy((void *)&pucch->pucch_pdu, (void *)pucch_pdu, sizeof(nfapi_nr_pucch_pdu_t));
- LOG_D(PHY,
- "Programming PUCCH[%d] for %d.%d, format %d, nb_harq %d, nb_sr %d, nb_csi %d\n",
- i,
- pucch->frame,
- pucch->slot,
- pucch->pucch_pdu.format_type,
- pucch->pucch_pdu.bit_len_harq,
- pucch->pucch_pdu.sr_flag,
- pucch->pucch_pdu.bit_len_csi_part1);
- return;
- }
+ LOG_D(PHY,
+ "%4d.%2d UE %04x Programming PUCCH format %d, nb_harq %d, nb_sr %d, nb_csi %d\n",
+ frame,
+ slot,
+ pucch_pdu->rnti,
+ pucch_pdu->format_type,
+ pucch_pdu->bit_len_harq,
+ pucch_pdu->sr_flag,
+ pucch_pdu->bit_len_csi_part1);
+ NR_gNB_PUCCH_job_t pucch = {.frame = frame, .slot = slot, .pucch_pdu = *pucch_pdu};
+ if (gNB->common_vars.beam_id) {
+ int fapi_beam_idx = pucch_pdu->beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx;
+ int bitmap = SL_to_bitmap(pucch_pdu->start_symbol_index, pucch_pdu->nr_of_symbols);
+ pucch.beam_nb = beam_index_allocation(gNB->enable_analog_das,
+ fapi_beam_idx,
+ &gNB->common_vars,
+ slot,
+ gNB->frame_parms.symbols_per_slot,
+ bitmap);
}
- LOG_W(PHY, "PUCCH list is full\n");
+ bool found = spsc_q_put(&gNB->pucch_queue, &pucch, sizeof(pucch));
+ if (!found)
+ LOG_W(NR_PHY, "PUCCH list is full: dropping PUCCH UE %04x\n", pucch_pdu->rnti);
}
-int get_pucch0_cs_lut_index(PHY_VARS_gNB *gNB, nfapi_nr_pucch_pdu_t *pucch_pdu)
+int get_pucch0_cs_lut_index(PHY_VARS_gNB *gNB, const nfapi_nr_pucch_pdu_t *pucch_pdu)
{
int i = 0;
@@ -129,7 +121,7 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB,
int frame,
int slot,
nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_pdu,
- nfapi_nr_pucch_pdu_t *pucch_pdu)
+ const nfapi_nr_pucch_pdu_t *pucch_pdu)
{
NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms;
int soffset = (slot % RU_RX_SLOT_DEPTH) * frame_parms->symbols_per_slot * frame_parms->ofdm_symbol_size;
@@ -1132,7 +1124,7 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
int frame,
int slot,
nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu,
- nfapi_nr_pucch_pdu_t *pucch_pdu)
+ const nfapi_nr_pucch_pdu_t *pucch_pdu)
{
NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms;
// pucch_GroupHopping_t pucch_GroupHopping = pucch_pdu->group_hop_flag + (pucch_pdu->sequence_hop_flag<<1);
diff --git a/openair1/PHY/NR_TRANSPORT/srs_rx.c b/openair1/PHY/NR_TRANSPORT/srs_rx.c
index fb6f5f648e..b0436cb2d7 100644
--- a/openair1/PHY/NR_TRANSPORT/srs_rx.c
+++ b/openair1/PHY/NR_TRANSPORT/srs_rx.c
@@ -29,37 +29,27 @@
void nr_fill_srs(PHY_VARS_gNB *gNB, frame_t frame, slot_t slot, nfapi_nr_srs_pdu_t *srs_pdu)
{
- bool found = false;
- for (int i = 0; i < gNB->max_nb_srs; i++) {
- NR_gNB_SRS_t *srs = &gNB->srs[i];
- if (srs->active == false) {
- found = true;
- srs->frame = frame;
- srs->slot = slot;
- srs->active = true;
- srs->beam_nb = 0;
- if (gNB->common_vars.beam_id) {
- const uint8_t l0 = gNB->frame_parms.symbols_per_slot - 1 - srs_pdu->time_start_position;
- int bitmap = SL_to_bitmap(l0, 1 << srs_pdu->num_symbols);
- int fapi_beam_idx = srs_pdu->beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx;
- srs->beam_nb = beam_index_allocation(gNB->enable_analog_das,
- fapi_beam_idx,
- &gNB->common_vars,
- slot,
- gNB->frame_parms.symbols_per_slot,
- bitmap);
- }
- memcpy((void *)&srs->srs_pdu, (void *)srs_pdu, sizeof(nfapi_nr_srs_pdu_t));
- break;
- }
+ NR_gNB_SRS_job_t srs = {.frame = frame, .slot = slot, .srs_pdu = *srs_pdu};
+ if (gNB->common_vars.beam_id) {
+ const uint8_t l0 = gNB->frame_parms.symbols_per_slot - 1 - srs_pdu->time_start_position;
+ int bitmap = SL_to_bitmap(l0, 1 << srs_pdu->num_symbols);
+ int fapi_beam_idx = srs_pdu->beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx;
+ srs.beam_nb = beam_index_allocation(gNB->enable_analog_das,
+ fapi_beam_idx,
+ &gNB->common_vars,
+ slot,
+ gNB->frame_parms.symbols_per_slot,
+ bitmap);
}
- AssertFatal(found, "SRS list is full\n");
+ bool found = spsc_q_put(&gNB->srs_queue, &srs, sizeof(srs));
+ if (!found)
+ LOG_W(NR_PHY, "SRS list is full: dropping SRS UE %04x\n", srs_pdu->rnti);
}
int nr_get_srs_signal(PHY_VARS_gNB *gNB,
c16_t **rxdataF,
slot_t slot,
- nfapi_nr_srs_pdu_t *srs_pdu,
+ const nfapi_nr_srs_pdu_t *srs_pdu,
nr_srs_info_t *nr_srs_info,
c16_t srs_received_signal[][gNB->frame_parms.ofdm_symbol_size * (1 << srs_pdu->num_symbols)],
c16_t srs_received_noise[][gNB->frame_parms.ofdm_symbol_size * (1 << srs_pdu->num_symbols)])
diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h
index 32d03c1010..7de87cc2ee 100644
--- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h
+++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h
@@ -148,11 +148,11 @@ void nr_tx_rotation_and_ofdm_mod(const uint8_t slot,
bool was_symbol_used[NR_SYMBOLS_PER_SLOT],
bool no_phase_pre_comp);
-bool ue_srs_procedures_nr(PHY_VARS_NR_UE *ue,
- const UE_nr_rxtx_proc_t *proc,
- c16_t **txdataF,
- nr_phy_data_tx_t *phy_data,
- bool was_symbol_used[NR_SYMBOLS_PER_SLOT]);
+void ue_srs_procedures_nr(PHY_VARS_NR_UE *ue,
+ const UE_nr_rxtx_proc_t *proc,
+ c16_t **txdataF,
+ const fapi_nr_ul_config_srs_pdu *srs_config_pdu,
+ bool was_symbol_used[NR_SYMBOLS_PER_SLOT]);
void clean_UE_harq(PHY_VARS_NR_UE *UE);
diff --git a/openair1/PHY/defs_gNB.h b/openair1/PHY/defs_gNB.h
index a6fb9d8890..3e627c38cd 100644
--- a/openair1/PHY/defs_gNB.h
+++ b/openair1/PHY/defs_gNB.h
@@ -19,6 +19,7 @@
#include "nfapi_nr_interface_scf.h"
#include "common/utils/threadPool/task_ans.h"
#include "openair1/PHY/defs_RU.h"
+#include "common/utils/ds/spsc_q.h"
#define MAX_NUM_RU_PER_gNB 8
#define MAX_PUCCH0_NID 8
@@ -45,14 +46,6 @@ typedef struct {
c16_t (*prach_buf)[NUMBER_OF_NR_RU_PRACH_OCCASIONS_MAX][NR_PRACH_SEQ_LEN_L];
} prach_item_t;
-typedef struct {
- /// prach commands
- prach_item_t *list[NUMBER_OF_NR_PRACH_MAX];
- /// mutex for prach_list access
- pthread_mutex_t prach_list_mutex;
-} prach_list_t;
-void init_prach_list(prach_list_t *);
-
typedef struct {
int nb_id;
int Nid[MAX_PUCCH0_NID];
@@ -127,7 +120,7 @@ typedef struct {
typedef struct {
/// Nfapi ULSCH PDU
- nfapi_nr_pusch_pdu_t ulsch_pdu;
+ nfapi_nr_pusch_pdu_t ulsch_pdu; // !!
/// Index of current HARQ round for this DLSCH
uint8_t round;
bool new_rx;
@@ -135,8 +128,6 @@ typedef struct {
/// flag used to clear d properly (together with d_to_be_cleared below)
/// set to true in nr_fill_ulsch() when new_data_indicator is received
bool harq_to_be_cleared;
- /// Transport block size (This is A from 38.212 V15.4.0 section 5.1)
- uint32_t TBS;
/// Pointer to the payload (38.212 V15.4.0 section 5.1)
uint8_t *b;
/// Pointers to code blocks after code block segmentation and CRC attachment (38.212 V15.4.0 section 5.2.2)
@@ -184,13 +175,20 @@ typedef struct {
int8_t last_iteration_cnt;
/// Status Flag indicating for this ULSCH
bool active;
- /// Flag to indicate that the UL configuration has been handled. Used to remove a stale ULSCH when frame wraps around
- uint8_t handled;
- delay_t delay;
} NR_gNB_ULSCH_t;
typedef struct {
- bool active;
+ // identifier for concurrent beams
+ int beam_nb;
+ /// Frame where current PUSCH pdu was sent
+ uint32_t frame;
+ /// Slot where current PUSCH pdu was sent
+ uint32_t slot;
+ /// ULSCH PDU
+ nfapi_nr_pusch_pdu_t pusch_pdu;
+} NR_gNB_PUSCH_job_t;
+
+typedef struct {
// identifier for concurrent beams
int beam_nb;
/// Frame where current PUCCH pdu was sent
@@ -199,21 +197,18 @@ typedef struct {
uint32_t slot;
/// ULSCH PDU
nfapi_nr_pucch_pdu_t pucch_pdu;
-} NR_gNB_PUCCH_t;
+} NR_gNB_PUCCH_job_t;
typedef struct {
- bool active;
// identifier for concurrent beams
int beam_nb;
/// Frame where current SRS pdu was received
uint32_t frame;
/// Slot where current SRS pdu was received
uint32_t slot;
- /// Measured SNR
- int8_t snr;
/// ULSCH PDU
nfapi_nr_srs_pdu_t srs_pdu;
-} NR_gNB_SRS_t;
+} NR_gNB_SRS_job_t;
typedef struct {
/// \brief Pointers (dynamic) to the received data in the frequency domain.
@@ -275,6 +270,8 @@ typedef struct {
int llr_offset[14];
/// flag to indicate DTX on reception
int DTX;
+ /// delay estimation
+ delay_t delay;
} NR_gNB_PUSCH;
/// Context data structure for RX/TX portion of slot processing
@@ -369,26 +366,23 @@ typedef struct PHY_VARS_gNB_s {
nfapi_nr_ul_tti_request_t UL_tti_req;
- int max_nb_pucch;
- int max_nb_srs;
int max_nb_pdsch;
int max_nb_pusch;
NR_gNB_COMMON common_vars;
- prach_list_t prach_list;
+ spsc_q_t prach_ru_queue;
+ spsc_q_t prach_l1rx_queue;
// TODO: can we remove c from NR_gNB_DLSCH_t and put it on the stack?
NR_gNB_DLSCH_t *dlsch;
NR_gNB_PRS prs_vars;
NR_gNB_PUSCH *pusch_vars;
- NR_gNB_PUCCH_t *pucch;
- NR_gNB_SRS_t *srs;
+ spsc_q_t pucch_queue;
+ spsc_q_t pusch_queue;
+ spsc_q_t srs_queue;
NR_gNB_ULSCH_t *ulsch;
NR_gNB_PHY_STATS_t phy_stats[MAX_MOBILES_PER_GNB];
t_nrPolar_params **polarParams;
- /// SRS variables
- nr_srs_info_t **nr_srs_info;
-
// reference amplitude for TX
int16_t TX_AMP;
diff --git a/openair1/PHY/defs_nr_UE.h b/openair1/PHY/defs_nr_UE.h
index 63771f7125..3f4c29bdaf 100644
--- a/openair1/PHY/defs_nr_UE.h
+++ b/openair1/PHY/defs_nr_UE.h
@@ -28,8 +28,8 @@
#include "common_lib.h"
#include "fapi_nr_ue_interface.h"
#include "assertions.h"
-#include "barrier.h"
-#include "actor.h"
+#include "common/utils/barrier/barrier.h"
+#include "common/utils/actor/actor.h"
//#include "openair1/SCHED_NR_UE/defs.h"
#define msg(aRGS...) LOG_D(PHY, ##aRGS)
@@ -402,9 +402,6 @@ typedef struct PHY_VARS_NR_UE_s {
nrLDPC_coding_interface_t nrLDPC_coding_interface;
uint8_t max_ldpc_iterations;
- /// SRS variables
- nr_srs_info_t *nr_srs_info;
-
/// CSI variables
nr_csi_info_t *nr_csi_info;
diff --git a/openair1/PHY/defs_nr_common.h b/openair1/PHY/defs_nr_common.h
index 7cd439bcee..8b50f36290 100644
--- a/openair1/PHY/defs_nr_common.h
+++ b/openair1/PHY/defs_nr_common.h
@@ -77,8 +77,6 @@ typedef enum{
typedef struct {
uint8_t k_0_p[MAX_NUM_NR_SRS_AP][MAX_NUM_NR_SRS_SYMBOLS];
uint8_t srs_generated_signal_bits;
- c16_t **srs_generated_signal;
- bool is_signal_generated;
int B_SRS;
int C_SRS;
int b_hop;
diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.c b/openair1/PHY/if4_tools.c
similarity index 99%
rename from openair1/PHY/LTE_TRANSPORT/if4_tools.c
rename to openair1/PHY/if4_tools.c
index 66097fc87f..5c5428db90 100644
--- a/openair1/PHY/LTE_TRANSPORT/if4_tools.c
+++ b/openair1/PHY/if4_tools.c
@@ -3,7 +3,6 @@
*/
#include
-//#include "PHY/defs_eNB.h"
#include "PHY/defs_RU.h"
#include "PHY/TOOLS/alaw_lut.h"
//#include "PHY/phy_extern.h"
diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.h b/openair1/PHY/if4_tools.h
similarity index 96%
rename from openair1/PHY/LTE_TRANSPORT/if4_tools.h
rename to openair1/PHY/if4_tools.h
index 3cc30f7710..367ccfa859 100644
--- a/openair1/PHY/LTE_TRANSPORT/if4_tools.h
+++ b/openair1/PHY/if4_tools.h
@@ -4,7 +4,7 @@
#ifndef __IF4_TOOLS_H__
#define __IF4_TOOLS_H__
-#include "PHY/defs_eNB.h"
+#include "openair1/PHY/defs_RU.h"
/// Macro for IF4 packet type
#define IF4p5_PACKET_TYPE 0x080A
diff --git a/openair1/PHY/nr_phy_common/src/nr_phy_common_srs.c b/openair1/PHY/nr_phy_common/src/nr_phy_common_srs.c
index 76ad47a4e2..3bd4746c92 100644
--- a/openair1/PHY/nr_phy_common/src/nr_phy_common_srs.c
+++ b/openair1/PHY/nr_phy_common/src/nr_phy_common_srs.c
@@ -203,7 +203,7 @@ bool generate_srs_nr(const NR_DL_FRAME_PARMS *frame_parms,
nr_srs_info->srs_generated_signal_bits = log2_approx(amp);
}
uint64_t subcarrier_offset = frame_parms->first_carrier_offset + bwp_start * NR_NB_SC_PER_RB;
- double sqrt_N_ap = sqrt(N_ap);
+ float amp_sqrt_N_ap = amp / sqrt(N_ap);
int n_b[nr_srs_info->B_SRS + 1];
// Find index of table which is for this SRS length
@@ -298,14 +298,16 @@ bool generate_srs_nr(const NR_DL_FRAME_PARMS *frame_parms,
uint16_t l_line_offset = l_line * frame_parms->ofdm_symbol_size;
// For each port, and for each OFDM symbol, here it is computed and mapped an SRS sequence with M_sc_b_SRS symbols
for (int k = 0; k < M_sc_b_SRS; k++) {
- cd_t shift = {cos(alpha_i * k), sin(alpha_i * k)};
- const c16_t tmp = rv_ul_ref_sig[u][v][M_sc_b_SRS_index][k];
- cd_t r_overbar = {tmp.r, tmp.i};
+ cf_t shift = {cosf(alpha_i * k), sinf(alpha_i * k)};
+ const c16_t r_overbar = rv_ul_ref_sig[u][v][M_sc_b_SRS_index][k];
// cos(x+y) = cos(x)cos(y) - sin(x)sin(y)
- cd_t r = cdMul(shift, r_overbar);
- c16_t r_amp = {(((int32_t)round((double)amp * r.r / sqrt_N_ap)) >> 15),
- (((int32_t)round((double)amp * r.i / sqrt_N_ap)) >> 15)};
+ cf_t r = (cf_t) {
+ .r = shift.r * r_overbar.r - shift.i * r_overbar.i,
+ .i = shift.r * r_overbar.i + shift.i * r_overbar.r,
+ };
+ c16_t r_amp = {(((int32_t)(amp_sqrt_N_ap * r.r)) >> 15),
+ (((int32_t)(amp_sqrt_N_ap * r.i)) >> 15)};
#ifdef SRS_DEBUG
int subcarrier_log = subcarrier-subcarrier_offset;
diff --git a/openair1/SCHED/nfapi_lte_dummy.c b/openair1/SCHED/nfapi_lte_dummy.c
index 1c22057064..55c339d7c8 100644
--- a/openair1/SCHED/nfapi_lte_dummy.c
+++ b/openair1/SCHED/nfapi_lte_dummy.c
@@ -16,18 +16,6 @@ int slot_ahead = 6;
//uint8_t nfapi_mode=0;
NR_IF_Module_t *NR_IF_Module_init(int Mod_id) {return NULL;}
-void nr_fill_ulsch(PHY_VARS_gNB *gNB,
- int frame,
- int slot,
- nfapi_nr_pusch_pdu_t *ulsch_pdu){}
-void nr_fill_pucch(PHY_VARS_gNB *gNB,
- int frame,
- int slot,
- nfapi_nr_pucch_pdu_t *pucch_pdu){}
-void nr_schedule_rx_prach(PHY_VARS_gNB *gNB, int SFN, int Slot, nfapi_nr_prach_pdu_t *prach_pdu)
-{
-}
-
void nr_phy_config_request(NR_PHY_Config_t *gNB){}
void nr_dump_frame_parms(NR_DL_FRAME_PARMS *fp){}
@@ -70,59 +58,6 @@ void *pnf_nr_p7_thread_start(void *ptr)
{
return 0;
}
-
-bool wls_vnf_nr_send_p7_message(vnf_p7_t *vnf_p7, nfapi_nr_p7_message_header_t *msg)
-{
- return false;
-}
-
-
-bool wls_vnf_nr_send_p5_message(vnf_t *vnf,uint16_t p5_idx, nfapi_nr_p4_p5_message_header_t* msg, uint32_t msg_len)
-{
- return false;
-}
-
-void *wls_fapi_vnf_nr_start_thread(void *ptr)
-{
- return NULL;
-}
-
-bool wls_pnf_nr_send_p7_message(pnf_p7_t* pnf_p7,nfapi_nr_p7_message_header_t *msg, uint32_t msg_len)
-{
- return false;
-}
-
-bool wls_pnf_nr_send_p5_message(pnf_t *pnf, nfapi_nr_p4_p5_message_header_t *msg, uint32_t msg_len)
-{
- return false;
-}
-
-void *wls_fapi_pnf_nr_start_thread(void *ptr)
-{
- return NULL;
-}
-
-void wls_pnf_set_p7_config(void *p7_config)
-{
-
-}
-
-void wls_fapi_nr_pnf_stop()
-{
-}
-
-void wls_pnf_close(pthread_t p5_thread)
-{
-}
-
-void wls_vnf_send_stop_request()
-{
-}
-
-void wls_vnf_stop()
-{
-}
-
void socket_nfapi_nr_pnf_stop()
{
}
diff --git a/openair1/SCHED/ru_procedures.c b/openair1/SCHED/ru_procedures.c
index 065c66d14c..8162d11699 100644
--- a/openair1/SCHED/ru_procedures.c
+++ b/openair1/SCHED/ru_procedures.c
@@ -10,7 +10,7 @@
#include "PHY/defs_eNB.h"
#include "SCHED/sched_eNB.h"
#include "PHY/MODULATION/modulation_eNB.h"
-#include "PHY/LTE_TRANSPORT/if4_tools.h"
+#include "PHY/if4_tools.h"
#include "PHY/LTE_TRANSPORT/transport_common_proto.h"
#include "PHY/LTE_TRANSPORT/transport_proto.h"
#include "PHY/LTE_UE_TRANSPORT/transport_proto_ue.h"
diff --git a/openair1/SCHED_NR/nr_prach_procedures.c b/openair1/SCHED_NR/nr_prach_procedures.c
index fcaf2f1c1b..929bf476f3 100644
--- a/openair1/SCHED_NR/nr_prach_procedures.c
+++ b/openair1/SCHED_NR/nr_prach_procedures.c
@@ -21,20 +21,14 @@ int get_nr_prach_duration(uint8_t prach_format)
return val[prach_format];
}
-void L1_nr_prach_procedures(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_rach_indication_t *rach_ind)
+void L1_nr_prach_procedures(PHY_VARS_gNB *gNB, prach_item_t *prach_id, nfapi_nr_rach_indication_t *rach_ind)
{
+ const frame_t frame = prach_id->frame;
+ const slot_t slot = prach_id->slot;
rach_ind->sfn = frame;
rach_ind->slot = slot;
- rach_ind->number_of_pdus = 0;
-
- prach_item_t *prach_id = find_nr_prach(&gNB->prach_list, frame, slot, gNB->frame_parms.nb_antennas_rx, NR_SEARCH_EXIST);
- if (!prach_id) {
- return;
- }
-
nfapi_nr_prach_pdu_t *prach_pdu = &prach_id->pdu;
LOG_D(NR_PHY_RACH, "%d.%d, prachstart slot %d prach entry occas %d\n", frame, slot, prach_id->slot, prach_pdu->num_prach_ocas);
- const int prach_start_slot = prach_id->slot;
int N_dur = get_nr_prach_duration(prach_pdu->prach_format);
for (int prach_oc = 0; prach_oc < prach_pdu->num_prach_ocas; prach_oc++) {
@@ -63,7 +57,7 @@ void L1_nr_prach_procedures(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_rac
"[RAPROC] %d.%d Initiating RA procedure with preamble %d, energy %d.%d dB (I0 %d, thres %d), delay %d start symbol "
"%u freq index %u\n",
frame,
- prach_start_slot,
+ slot,
res.max_preamble,
res.max_preamble_energy / 10,
res.max_preamble_energy % 10,
@@ -100,7 +94,6 @@ void L1_nr_prach_procedures(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_rac
if (gNB->prach_energy_counter < NUM_PRACH_RX_FOR_NOISE_ESTIMATE)
gNB->prach_energy_counter++;
} // if prach_id>0
- rach_ind->slot = prach_start_slot;
LOG_D(NR_PHY_RACH, "Freeing PRACH entry\n");
- free_nr_prach_entry(&gNB->prach_list, prach_id);
+ free_nr_prach_entry(prach_id);
}
diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c
index 7a5af5b070..58d9ad398a 100644
--- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c
+++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c
@@ -2,6 +2,7 @@
* SPDX-License-Identifier: LicenseRef-CSSL-1.0
*/
+#include "common/utils/fsn.h"
#include "PHY/defs_gNB.h"
#include "sched_nr.h"
#include "PHY/NR_TRANSPORT/nr_transport_proto.h"
@@ -26,22 +27,14 @@
//#define DEBUG_RXDATA
//#define SRS_IND_DEBUG
-static void nr_fill_indication(PHY_VARS_gNB *gNB,
- int frame,
- int slot_rx,
- int UE_id,
- uint8_t harq_pid,
- uint8_t crc_flag,
- int dtx_flag,
- nfapi_nr_crc_t *crc,
- nfapi_nr_rx_data_pdu_t *pdu);
-static void nr_fill_indication(PHY_VARS_gNB *gNB,
+static void nr_fill_indication(const PHY_VARS_gNB *gNB,
int frame,
int slot_rx,
- int ULSCH_id,
- uint8_t harq_pid,
- uint8_t crc_flag,
+ const NR_gNB_PUSCH *pusch,
+ const nfapi_nr_pusch_pdu_t *pusch_pdu,
+ NR_gNB_PHY_STATS_t *stats,
+ uint8_t *payload,
int dtx_flag,
nfapi_nr_crc_t *crc,
nfapi_nr_rx_data_pdu_t *pdu);
@@ -322,91 +315,33 @@ void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB,
stop_meas(&gNB->phase_comp_stats);
}
-static int nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, bool *ulsch_to_decode, NR_UL_IND_t *UL_INFO)
+static int nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int *ulsch_to_decode, int nb_pusch, NR_UL_IND_t *UL_INFO)
{
+ DevAssert(nb_pusch > 0);
NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms;
-
- int nb_pusch = 0;
- for (int ULSCH_id = 0; ULSCH_id < gNB->max_nb_pusch; ULSCH_id++) {
- if (ulsch_to_decode[ULSCH_id]) {
- nb_pusch++;
- }
- }
-
- if (nb_pusch == 0) {
- return 0;
- }
-
- uint8_t ULSCH_ids[nb_pusch];
- uint32_t G[nb_pusch];
- int pusch_id = 0;
- for (int ULSCH_id = 0; ULSCH_id < gNB->max_nb_pusch; ULSCH_id++) {
-
- if (ulsch_to_decode[ULSCH_id]) {
-
- ULSCH_ids[pusch_id] = ULSCH_id;
-
- nfapi_nr_pusch_pdu_t *pusch_pdu = &gNB->ulsch[ULSCH_id].harq_process->ulsch_pdu;
-
- uint16_t nb_re_dmrs;
- uint16_t start_symbol = pusch_pdu->start_symbol_index;
- uint16_t number_symbols = pusch_pdu->nr_of_symbols;
-
- uint8_t number_dmrs_symbols = 0;
- for (int l = start_symbol; l < start_symbol + number_symbols; l++)
- number_dmrs_symbols += ((pusch_pdu->ul_dmrs_symb_pos)>>l)&0x01;
-
- if (pusch_pdu->dmrs_config_type==pusch_dmrs_type1)
- nb_re_dmrs = 6*pusch_pdu->num_dmrs_cdm_grps_no_data;
- else
- nb_re_dmrs = 4*pusch_pdu->num_dmrs_cdm_grps_no_data;
-
- G[pusch_id] = nr_get_G(pusch_pdu->rb_size,
- number_symbols,
- nb_re_dmrs,
- number_dmrs_symbols, // number of dmrs symbols irrespective of single or double symbol dmrs
- gNB->ulsch[ULSCH_id].unav_res,
- pusch_pdu->qam_mod_order,
- pusch_pdu->nrOfLayers);
- AssertFatal(G[pusch_id]>0,"G is 0 : rb_size %u, number_symbols %d, nb_re_dmrs %d, number_dmrs_symbols %d, qam_mod_order %u, nrOfLayer %u\n",
- pusch_pdu->rb_size,
- number_symbols,
- nb_re_dmrs,
- number_dmrs_symbols, // number of dmrs symbols irrespective of single or double symbol dmrs
- pusch_pdu->qam_mod_order,
- pusch_pdu->nrOfLayers);
- LOG_D(PHY,"rb_size %d, number_symbols %d, nb_re_dmrs %d, dmrs symbol positions %d, number_dmrs_symbols %d, qam_mod_order %d, nrOfLayer %d\n",
- pusch_pdu->rb_size,
- number_symbols,
- nb_re_dmrs,
- pusch_pdu->ul_dmrs_symb_pos,
- number_dmrs_symbols, // number of dmrs symbols irrespective of single or double symbol dmrs
- pusch_pdu->qam_mod_order,
- pusch_pdu->nrOfLayers);
- pusch_id++;
- }
- }
//----------------------------------------------------------
//--------------------- ULSCH decoding ---------------------
//----------------------------------------------------------
- int ret_nr_ulsch_decoding = nr_ulsch_decoding(gNB, frame_parms, frame_rx, slot_rx, G, ULSCH_ids, nb_pusch);
+ int ret_nr_ulsch_decoding = nr_ulsch_decoding(gNB, frame_parms, frame_rx, slot_rx, ulsch_to_decode, nb_pusch);
// CRC check per uplink shared channel
- for (pusch_id = 0; pusch_id < nb_pusch; pusch_id++) {
- uint8_t ULSCH_id = ULSCH_ids[pusch_id];
+ for (int pusch_id = 0; pusch_id < nb_pusch; pusch_id++) {
+ uint8_t ULSCH_id = ulsch_to_decode[pusch_id];
NR_gNB_ULSCH_t *ulsch = &gNB->ulsch[ULSCH_id];
NR_gNB_PUSCH *pusch = &gNB->pusch_vars[ULSCH_id];
NR_UL_gNB_HARQ_t *ulsch_harq = ulsch->harq_process;
- nfapi_nr_pusch_pdu_t *pusch_pdu = &ulsch_harq->ulsch_pdu;
+ NR_gNB_PHY_STATS_t *stats = get_phy_stats(gNB, ulsch->rnti);
+ const nfapi_nr_pusch_pdu_t *pusch_pdu = &ulsch_harq->ulsch_pdu;
bool crc_valid = false;
// if all segments are done
if (ulsch_harq->processedSegments == ulsch_harq->C) {
if (ulsch_harq->C > 1) {
- crc_valid = check_crc(ulsch_harq->b, lenWithCrc(1, (ulsch_harq->TBS) << 3), crcType(1, (ulsch_harq->TBS) << 3));
+ int tbs = pusch_pdu->pusch_data.tb_size;
+ crc_valid = check_crc(ulsch_harq->b, lenWithCrc(1, tbs << 3), crcType(1, tbs << 3));
} else {
// When the number of code blocks is 1 (C = 1) and ulsch_harq->processedSegments = 1, we can assume a good TB because of the
// CRC check made by the LDPC for early termination, so, no need to perform CRC check twice for a single code block
@@ -471,8 +406,8 @@ static int nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, boo
T_INT((int)dmrs_port), // dmrs_antenna_port
T_INT((int)pusch_pdu->scid), // dmrs_nscid
T_INT((int)frame_parms->nb_antennas_rx), // rx antenna
- T_INT(((ulsch_harq->TBS) << 3)), // number_of_bits
- T_BUFFER((uint8_t *)((ulsch_harq->b)), ((ulsch_harq->TBS) << 3) / 8)); // data
+ T_INT((pusch_pdu->pusch_data.tb_size << 3)), // number_of_bits
+ T_BUFFER((uint8_t *)((ulsch_harq->b)), pusch_pdu->pusch_data.tb_size)); // data
}
#endif
@@ -491,9 +426,9 @@ static int nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, boo
pusch_pdu->pusch_data.new_data_indicator,
ulsch->active,
ulsch_harq->round,
- ulsch_harq->TBS,
+ pusch_pdu->pusch_data.tb_size,
ulsch->max_ldpc_iterations);
- nr_fill_indication(gNB, ulsch->frame, ulsch->slot, ULSCH_id, ulsch->harq_pid, 0, 0, crc, pdu);
+ nr_fill_indication(gNB, ulsch->frame, ulsch->slot, pusch, pusch_pdu, stats, ulsch->harq_process->b, 0, crc, pdu);
LOG_D(PHY, "ULSCH received ok \n");
ulsch->active = false;
ulsch_harq->round = 0;
@@ -512,10 +447,9 @@ static int nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, boo
ulsch_harq->ulsch_pdu.pusch_data.rv_index,
ulsch_harq->ulsch_pdu.rb_start,
ulsch_harq->ulsch_pdu.rb_size,
- ulsch_harq->TBS);
- nr_fill_indication(gNB, ulsch->frame, ulsch->slot, ULSCH_id, ulsch->harq_pid, 1, 0, crc, pdu);
+ pusch_pdu->pusch_data.tb_size);
+ nr_fill_indication(gNB, ulsch->frame, ulsch->slot, pusch, pusch_pdu, stats, NULL, 0, crc, pdu);
gNBdumpScopeData(gNB, ulsch->slot, ulsch->frame, "ULSCH_NACK");
- ulsch->handled = 1;
LOG_D(PHY, "ULSCH %d in error\n",ULSCH_id);
ulsch->last_iteration_cnt = ulsch->max_ldpc_iterations; // Setting to max_ldpc_iterations is sufficient given that this variable is only used for checking for failure
}
@@ -524,24 +458,19 @@ static int nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, boo
return ret_nr_ulsch_decoding;
}
-static void nr_fill_indication(PHY_VARS_gNB *gNB,
+static void nr_fill_indication(const PHY_VARS_gNB *gNB,
int frame,
int slot_rx,
- int ULSCH_id,
- uint8_t harq_pid,
- uint8_t crc_flag,
+ const NR_gNB_PUSCH *pusch,
+ const nfapi_nr_pusch_pdu_t *pusch_pdu,
+ NR_gNB_PHY_STATS_t *stats,
+ uint8_t *payload,
int dtx_flag,
nfapi_nr_crc_t *crc,
nfapi_nr_rx_data_pdu_t *pdu)
{
- NR_UL_gNB_HARQ_t *harq_process = gNB->ulsch[ULSCH_id].harq_process;
- NR_gNB_PHY_STATS_t *stats = get_phy_stats(gNB, gNB->ulsch[ULSCH_id].rnti);
- NR_gNB_PUSCH *pusch = &gNB->pusch_vars[ULSCH_id];
-
- nfapi_nr_pusch_pdu_t *pusch_pdu = &harq_process->ulsch_pdu;
-
// Get estimated timing advance for MAC
- const int sync_pos = gNB->ulsch[ULSCH_id].delay.est_delay;
+ const int sync_pos = pusch->delay.est_delay;
// scale the 16 factor in N_TA calculation in 38.213 section 4.2 according to the used FFT size
uint16_t bw_scaling = 16 * gNB->frame_parms.ofdm_symbol_size / 2048;
@@ -562,14 +491,6 @@ static void nr_fill_indication(PHY_VARS_gNB *gNB,
timing_advance_update = max(timing_advance_update, 0);
timing_advance_update = min(timing_advance_update, 63);
- if (crc_flag == 0)
- LOG_D(PHY,
- "%d.%d : Received PUSCH : Estimated timing advance PUSCH is = %d, timing_advance_update is %d \n",
- frame,
- slot_rx,
- sync_pos,
- timing_advance_update);
-
// estimate UL_CQI for MAC
int SNRtimes10 = dB_fixed_x10(pusch->ulsch_power_tot) - dB_fixed_x10(pusch->ulsch_noise_power_tot);
@@ -589,8 +510,8 @@ static void nr_fill_indication(PHY_VARS_gNB *gNB,
crc->handle = pusch_pdu->handle;
crc->rnti = pusch_pdu->rnti;
- crc->harq_id = harq_pid;
- crc->tb_crc_status = crc_flag;
+ crc->harq_id = pusch_pdu->pusch_data.harq_process_id;
+ crc->tb_crc_status = payload == NULL; // 222.10.02/04: pass 0, fail 1
crc->num_cb = pusch_pdu->pusch_data.num_cb;
crc->ul_cqi = cqi;
crc->timing_advance = timing_advance_update;
@@ -599,92 +520,62 @@ static void nr_fill_indication(PHY_VARS_gNB *gNB,
pdu->handle = pusch_pdu->handle;
pdu->rnti = pusch_pdu->rnti;
- pdu->harq_id = harq_pid;
+ pdu->harq_id = pusch_pdu->pusch_data.harq_process_id;
pdu->ul_cqi = cqi;
pdu->timing_advance = timing_advance_update;
pdu->rssi = crc->rssi;
- if (crc_flag)
- pdu->pdu_length = 0;
- else {
- pdu->pdu_length = harq_process->TBS;
- pdu->pdu = harq_process->b;
- }
+ pdu->pdu_length = payload != NULL ? pusch_pdu->pusch_data.tb_size : 0;
+ pdu->pdu = payload;
}
// Function to fill UL RB mask to be used for N0 measurements
static void fill_ul_rb_mask(PHY_VARS_gNB *gNB,
- int frame_rx,
- int slot_rx,
- uint32_t rb_mask_ul[14][9],
- nfapi_nr_max_num_of_symbol_per_slot_t *slot_conf)
+ fsn_t now,
+ uint32_t rb_mask_ul[14][MAX_BWP_SIZE],
+ const NR_gNB_PUCCH_job_t *pucch,
+ int n_pucch,
+ const NR_gNB_PUSCH_job_t *pusch,
+ int n_pusch,
+ const NR_gNB_SRS_job_t *srs,
+ int n_srs)
{
for (int symbol = 0; symbol < 14; symbol++) {
- for (int m = 0; m < 9; m++) {
- rb_mask_ul[symbol][m] = 0;
- for (int i = 0; i < 32; i++) {
- int prbpos = (m * 32) + i;
- if (prbpos > gNB->frame_parms.N_RB_UL)
- break;
- rb_mask_ul[symbol][m] |= (gNB->ulprbbl[prbpos] > 0 ? 1U : 0) << i;
- }
+ for (int prb = 0; prb < MAX_BWP_SIZE; prb++) {
+ rb_mask_ul[symbol][prb] = gNB->ulprbbl[prb] > 0;
}
}
- for (int i = 0; i < gNB->max_nb_pucch; i++){
- const NR_gNB_PUCCH_t *pucch = gNB->pucch + i;
- if (!(pucch && pucch->active && pucch->frame == frame_rx && pucch->slot == slot_rx))
- continue;
- const nfapi_nr_pucch_pdu_t *pucch_pdu = &pucch->pucch_pdu;
+ for (int i = 0; i < n_pucch; ++i) {
+ const nfapi_nr_pucch_pdu_t *pucch_pdu = &pucch[i].pucch_pdu;
const int start = pucch_pdu->start_symbol_index;
- LOG_D(PHY,
- "%d.%d pucch %d : start_symbol %d, nb_symbols %d, prb_size %d\n",
- frame_rx,
- slot_rx,
- i,
- start,
- pucch_pdu->nr_of_symbols,
- pucch_pdu->prb_size);
- for (int symbol = start; symbol < (start + pucch_pdu->nr_of_symbols); symbol++) {
- if (gNB->frame_parms.frame_type == FDD || (gNB->frame_parms.frame_type == TDD && slot_conf[symbol].slot_config.value == 1)) {
- for (int rb = 0; rb < pucch_pdu->prb_size; rb++) {
- int rb2 =
- rb + pucch_pdu->bwp_start
- + ((symbol < start + (pucch_pdu->nr_of_symbols >> 1)) || (pucch_pdu->freq_hop_flag == 0) ? pucch_pdu->prb_start
- : pucch_pdu->second_hop_prb);
- rb_mask_ul[symbol][rb2 >> 5] |= 1U << (rb2 & 31);
- }
+ for (int symbol = start; symbol < start + pucch_pdu->nr_of_symbols; symbol++) {
+ bool first_hop = symbol < start + (pucch_pdu->nr_of_symbols >> 1);
+ int prb_first_second = first_hop || pucch_pdu->freq_hop_flag == 0 ? pucch_pdu->prb_start : pucch_pdu->second_hop_prb;
+ for (int rb = 0; rb < pucch_pdu->prb_size; rb++) {
+ int prb = rb + pucch_pdu->bwp_start + prb_first_second;
+ rb_mask_ul[symbol][prb] = 1;
}
}
}
- for (int ULSCH_id = 0; ULSCH_id < gNB->max_nb_pusch; ULSCH_id++) {
- NR_gNB_ULSCH_t *ulsch = &gNB->ulsch[ULSCH_id];
- NR_UL_gNB_HARQ_t *ulsch_harq = ulsch->harq_process;
- AssertFatal(ulsch_harq != NULL, "harq_pid %d is not allocated\n", ulsch->harq_pid);
- if (!(ulsch->active && ulsch->frame == frame_rx && ulsch->slot == slot_rx && !ulsch->handled))
- continue;
- uint8_t symbol_start = ulsch_harq->ulsch_pdu.start_symbol_index;
- uint8_t symbol_end = symbol_start + ulsch_harq->ulsch_pdu.nr_of_symbols;
+ for (int i = 0; i < n_pusch; i++) {
+ const nfapi_nr_pusch_pdu_t *pusch_pdu = &pusch[i].pusch_pdu;
+ uint8_t symbol_start = pusch_pdu->start_symbol_index;
+ uint8_t symbol_end = symbol_start + pusch_pdu->nr_of_symbols;
for (int symbol = symbol_start; symbol < symbol_end; symbol++) {
- if (gNB->frame_parms.frame_type == FDD || (gNB->frame_parms.frame_type == TDD && slot_conf[symbol].slot_config.value == 1)) {
- LOG_D(PHY, "symbol %d Filling rb_mask_ul rb_size %d\n", symbol, ulsch_harq->ulsch_pdu.rb_size);
- for (int rb = 0; rb < ulsch_harq->ulsch_pdu.rb_size; rb++) {
- int rb2 = rb + ulsch_harq->ulsch_pdu.rb_start + ulsch_harq->ulsch_pdu.bwp_start;
- rb_mask_ul[symbol][rb2 >> 5] |= 1U << (rb2 & 31);
- }
+ for (int rb = 0; rb < pusch_pdu->rb_size; rb++) {
+ int prb = rb + pusch_pdu->rb_start + pusch_pdu->bwp_start;
+ rb_mask_ul[symbol][prb] = 1;
}
}
}
- for (int i = 0; i < gNB->max_nb_srs; i++) {
- NR_gNB_SRS_t *srs = &gNB->srs[i];
- if (!(srs && srs->active && srs->frame == frame_rx && srs->slot == slot_rx))
- continue;
- nfapi_nr_srs_pdu_t *srs_pdu = &srs->srs_pdu;
+ for (int i = 0; i < n_srs; i++) {
+ const nfapi_nr_srs_pdu_t *srs_pdu = &srs[i].srs_pdu;
const uint8_t l0 = gNB->frame_parms.symbols_per_slot - 1 - srs_pdu->time_start_position;
for (int symbol = 0; symbol < (1 << srs_pdu->num_symbols); symbol++) {
for (int rb = srs_pdu->bwp_start; rb < (srs_pdu->bwp_start + srs_pdu->bwp_size); rb++) {
- rb_mask_ul[l0 + symbol][rb >> 5] |= 1U << (rb & 31);
+ rb_mask_ul[l0 + symbol][rb] = 1;
}
}
}
@@ -712,56 +603,50 @@ static int fill_srs_reported_symbol(nfapi_nr_srs_reported_symbol_t *reported_sym
return 0;
}
-static int fill_srs_channel_matrix(
- nfapi_nr_srs_normalized_channel_iq_matrix_t *nr_srs_channel_iq_matrix,
- const nfapi_nr_srs_pdu_t *srs_pdu,
- const nr_srs_info_t *nr_srs_info,
- const uint8_t normalized_iq_representation,
- const uint16_t num_gnb_antenna_elements,
- const uint16_t num_ue_srs_ports,
- const uint16_t prg_size,
- const uint16_t num_prgs,
- const NR_DL_FRAME_PARMS *frame_parms,
- const c16_t srs_estimated_channel_freq[][1 << srs_pdu->num_ant_ports]
- [frame_parms->ofdm_symbol_size * (1 << srs_pdu->num_symbols)])
+static int fill_srs_channel_matrix(nfapi_nr_srs_normalized_channel_iq_matrix_t *nr_srs_channel_iq_matrix,
+ const nfapi_nr_srs_pdu_t *srs_pdu,
+ const nr_srs_info_t *nr_srs_info,
+ const NR_DL_FRAME_PARMS *frame_parms,
+ const c16_t srs_estimated_channel_freq[][1 << srs_pdu->num_ant_ports][frame_parms->ofdm_symbol_size * (1 << srs_pdu->num_symbols)])
{
+ const uint16_t num_gnb_antenna_elements = frame_parms->nb_antennas_rx;
+ const uint16_t num_ue_srs_ports = srs_pdu->srs_parameters_v4.num_total_ue_antennas;
+ const uint8_t normalized_iq_representation = srs_pdu->srs_parameters_v4.iq_representation;
+ const uint16_t prg_size = srs_pdu->srs_parameters_v4.prg_size;
+ const uint16_t num_prgs = srs_pdu->srs_parameters_v4.srs_bandwidth_size / srs_pdu->srs_parameters_v4.prg_size;
+ const uint64_t first_subcarrier =
+ (frame_parms->first_carrier_offset - (frame_parms->ofdm_symbol_size >> 1)) + srs_pdu->bwp_start * NR_NB_SC_PER_RB;
+ const uint16_t step = prg_size * NR_NB_SC_PER_RB;
+
nr_srs_channel_iq_matrix->normalized_iq_representation = normalized_iq_representation;
nr_srs_channel_iq_matrix->num_gnb_antenna_elements = num_gnb_antenna_elements;
nr_srs_channel_iq_matrix->num_ue_srs_ports = num_ue_srs_ports;
nr_srs_channel_iq_matrix->prg_size = prg_size;
nr_srs_channel_iq_matrix->num_prgs = num_prgs;
+
uint8_t *channel_matrix = nr_srs_channel_iq_matrix->channel_matrix;
- const uint64_t subcarrier_offset = frame_parms->first_carrier_offset + srs_pdu->bwp_start*NR_NB_SC_PER_RB;
- const uint16_t step = prg_size*NR_NB_SC_PER_RB;
+ c16_t *channel_matrix16 = (c16_t *)channel_matrix;
+ c8_t *channel_matrix8 = (c8_t *)channel_matrix;
- c16_t *channel_matrix16 = (c16_t*)channel_matrix;
- c8_t *channel_matrix8 = (c8_t*)channel_matrix;
+ for (int uI = 0; uI < num_ue_srs_ports; uI++) {
+ for (int gI = 0; gI < num_gnb_antenna_elements; gI++) {
- for(int uI = 0; uI < num_ue_srs_ports; uI++) {
- for(int gI = 0; gI < num_gnb_antenna_elements; gI++) {
+ // channel_matrix8 or channel_matrix16 will only be populated for the symbol 0
+ uint16_t subcarrier_abs = first_subcarrier + nr_srs_info->k_0_p[uI][0];
- uint16_t subcarrier = subcarrier_offset + nr_srs_info->k_0_p[uI][0];
- if (subcarrier >= frame_parms->ofdm_symbol_size) {
- subcarrier -= frame_parms->ofdm_symbol_size;
- }
-
- for(int pI = 0; pI < num_prgs; pI++) {
- const c16_t *srs_estimated_channel16 = srs_estimated_channel_freq[gI][uI] + subcarrier;
- uint16_t index = uI*num_gnb_antenna_elements*num_prgs + gI*num_prgs + pI;
+ for (int pI = 0; pI < num_prgs; pI++) {
+ const c16_t *srs_estimated_channel16 = srs_estimated_channel_freq[gI][uI] + subcarrier_abs;
+ uint16_t index = uI * num_gnb_antenna_elements * num_prgs + gI * num_prgs + pI;
if (normalized_iq_representation == 0) {
- channel_matrix8[index].r = (int8_t)(srs_estimated_channel16->r>>8);
- channel_matrix8[index].i = (int8_t)(srs_estimated_channel16->i>>8);
+ channel_matrix8[index].r = (int8_t)(srs_estimated_channel16->r >> 8);
+ channel_matrix8[index].i = (int8_t)(srs_estimated_channel16->i >> 8);
} else {
channel_matrix16[index].r = srs_estimated_channel16->r;
channel_matrix16[index].i = srs_estimated_channel16->i;
}
-
// Subcarrier increment
- subcarrier += step;
- if (subcarrier >= frame_parms->ofdm_symbol_size) {
- subcarrier -= frame_parms->ofdm_symbol_size;
- }
+ subcarrier_abs += step;
}
}
}
@@ -791,66 +676,46 @@ static void copy_srs_info(const nfapi_nr_srs_pdu_t *srs_config_pdu, nr_srs_info_
nr_srs_info->resource_type = srs_config_pdu->resource_type;
}
-static bool srs_has_changed(const nfapi_nr_srs_pdu_t *srs_config_pdu, nr_srs_info_t *nr_srs_info)
-{
- return nr_srs_info->B_SRS != srs_config_pdu->bandwidth_index
- || nr_srs_info->C_SRS != srs_config_pdu->config_index
- || nr_srs_info->b_hop != srs_config_pdu->frequency_hopping
- || nr_srs_info->comb_size != srs_config_pdu->comb_size
- || nr_srs_info->K_TC_overbar != srs_config_pdu->comb_offset
- || nr_srs_info->n_SRS_cs != srs_config_pdu->cyclic_shift
- || nr_srs_info->n_ID_SRS != srs_config_pdu->sequence_id
- || nr_srs_info->n_shift != srs_config_pdu->frequency_position
- || nr_srs_info->n_RRC != srs_config_pdu->frequency_shift
- || nr_srs_info->groupOrSequenceHopping != srs_config_pdu->group_or_sequence_hopping
- || nr_srs_info->l_offset != srs_config_pdu->time_start_position
- || nr_srs_info->T_SRS != srs_config_pdu->t_srs
- || nr_srs_info->T_offset != srs_config_pdu->t_offset
- || nr_srs_info->R != 1 << srs_config_pdu->num_repetitions
- || nr_srs_info->N_symb_SRS != 1 << srs_config_pdu->num_symbols
- || nr_srs_info->n_srs_ports != 1 << srs_config_pdu->num_ant_ports
- || nr_srs_info->resource_type != srs_config_pdu->resource_type;
-}
-
-static bool check_and_configure_srs_info(nfapi_nr_srs_pdu_t *srs_config_pdu, nr_srs_info_t *nr_srs_info)
-{
- if (srs_has_changed(srs_config_pdu, nr_srs_info)) {
- copy_srs_info(srs_config_pdu, nr_srs_info);
- return true;
- }
- return false;
-}
-
-void nr_srs_rx_procedures(PHY_VARS_gNB *gNB,
+nr_srs_info_t nr_srs_rx_procedures(PHY_VARS_gNB *gNB,
int frame_rx,
int slot_rx,
uint8_t nb_antennas_rx,
uint8_t N_ap,
uint8_t N_symb_SRS,
uint16_t ofdm_symbol_size,
- NR_gNB_SRS_t *srs,
- nr_srs_info_t *nr_srs_info,
+ const NR_gNB_SRS_job_t *srs,
int *srs_est,
+ int8_t *snr,
c16_t srs_estimated_channel_freq[][N_ap][ofdm_symbol_size * N_symb_SRS],
- c16_t srs_estimated_channel_time[][N_ap][NR_SRS_IDFT_OVERSAMP_FACTOR * ofdm_symbol_size],
int16_t *snr_per_rb,
uint16_t *timing_advance_offset,
int16_t *timing_advance_offset_nsec)
{
NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms;
- nfapi_nr_srs_pdu_t *srs_pdu = &srs->srs_pdu;
+ const nfapi_nr_srs_pdu_t *srs_pdu = &srs->srs_pdu;
+
+ c16_t srs_estimated_channel_time[nb_antennas_rx][N_ap][NR_SRS_IDFT_OVERSAMP_FACTOR * ofdm_symbol_size]
+ __attribute__((aligned(32)));
c16_t srs_received_signal[nb_antennas_rx][ofdm_symbol_size * N_symb_SRS];
c16_t srs_received_noise[nb_antennas_rx][ofdm_symbol_size * N_symb_SRS];
c16_t srs_estimated_channel_time_shifted[nb_antennas_rx][N_ap][NR_SRS_IDFT_OVERSAMP_FACTOR * ofdm_symbol_size];
start_meas(&gNB->generate_srs_stats);
- if (check_and_configure_srs_info(srs_pdu, nr_srs_info)) {
+ nr_srs_info_t nr_srs_info = {0};
+ copy_srs_info(srs_pdu, &nr_srs_info);
+
+ // TODO permanently allocate?
+ c16_t srs_generated_signal_tmp[N_ap][ofdm_symbol_size * MAX_NUM_NR_SRS_SYMBOLS];
+ c16_t *srs_generated_signal[N_ap];
+ for (int i = 0; i < N_ap; ++i)
+ srs_generated_signal[i] = srs_generated_signal_tmp[i];
+ if (true) {
generate_srs_nr(frame_parms,
- nr_srs_info->srs_generated_signal,
+ srs_generated_signal,
0,
srs_pdu->bwp_start,
- nr_srs_info,
+ &nr_srs_info,
AMP,
frame_rx,
slot_rx,
@@ -860,7 +725,7 @@ void nr_srs_rx_procedures(PHY_VARS_gNB *gNB,
stop_meas(&gNB->generate_srs_stats);
c16_t **rxdataF = gNB->common_vars.rxdataF[srs->beam_nb];
start_meas(&gNB->get_srs_signal_stats);
- *srs_est = nr_get_srs_signal(gNB, rxdataF, slot_rx, srs_pdu, nr_srs_info, srs_received_signal, srs_received_noise);
+ *srs_est = nr_get_srs_signal(gNB, rxdataF, slot_rx, srs_pdu, &nr_srs_info, srs_received_signal, srs_received_noise);
stop_meas(&gNB->get_srs_signal_stats);
uint32_t signal_power_avg = 0;
@@ -879,8 +744,8 @@ void nr_srs_rx_procedures(PHY_VARS_gNB *gNB,
frame_parms->first_carrier_offset,
N_symb_SRS,
srs_pdu,
- nr_srs_info,
- nr_srs_info->srs_generated_signal[p_ind],
+ &nr_srs_info,
+ srs_generated_signal[p_ind],
srs_received_signal[ant_rx_ind],
srs_ls_estimated_channel[ant_rx_ind][p_ind],
&delay_aux);
@@ -898,7 +763,7 @@ void nr_srs_rx_procedures(PHY_VARS_gNB *gNB,
frame_parms->first_carrier_offset,
N_symb_SRS,
srs_pdu,
- nr_srs_info,
+ &nr_srs_info,
srs_ls_estimated_channel[ant_rx_ind][p_ind],
delay.est_delay,
srs_received_noise[ant_rx_ind],
@@ -943,7 +808,7 @@ void nr_srs_rx_procedures(PHY_VARS_gNB *gNB,
frame_parms->first_carrier_offset,
N_symb_SRS,
srs_pdu,
- nr_srs_info,
+ &nr_srs_info,
signal_power_avg,
srs_received_noise[ant_rx_ind],
&noise_power_per_ant,
@@ -952,7 +817,7 @@ void nr_srs_rx_procedures(PHY_VARS_gNB *gNB,
}
noise_power_avg /= nb_antennas_rx;
- gNB->srs->snr = dB_fixed(signal_power_avg) - dB_fixed(max(noise_power_avg, 1));
+ *snr = dB_fixed(signal_power_avg) - dB_fixed(max(noise_power_avg, 1));
const uint16_t m_SRS_b = get_m_srs(srs_pdu->config_index, srs_pdu->bandwidth_index);
for (int rb = 0; rb < m_SRS_b; rb++) {
@@ -987,29 +852,362 @@ void nr_srs_rx_procedures(PHY_VARS_gNB *gNB,
T_INT(slot_rx),
T_BUFFER(timing_advance_offset_nsec, nb_antennas_rx * sizeof(int16_t)));
}
+ return nr_srs_info;
+}
+
+static void handle_srs(fsn_t now, PHY_VARS_gNB *gNB, const NR_gNB_SRS_job_t *srs, nfapi_nr_srs_indication_pdu_t *srs_indication)
+{
+ const NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms;
+ const uint8_t nb_antennas_rx = frame_parms->nb_antennas_rx;
+ const uint16_t ofdm_symbol_size = frame_parms->ofdm_symbol_size;
+ const nfapi_nr_srs_pdu_t *srs_pdu = &srs->srs_pdu;
+
+ uint8_t N_symb_SRS = 1 << srs_pdu->num_symbols;
+ uint8_t N_ap = 1 << srs_pdu->num_ant_ports;
+ int16_t snr_per_rb[srs_pdu->bwp_size];
+ uint16_t timing_advance_offset;
+ int16_t timing_advance_offset_nsec[nb_antennas_rx];
+ int srs_est;
+
+ c16_t srs_estimated_channel_freq[nb_antennas_rx][N_ap][ofdm_symbol_size * N_symb_SRS] __attribute__((aligned(32)));
+
+ int8_t snr;
+ nr_srs_info_t srs_info = nr_srs_rx_procedures(gNB,
+ now.f,
+ now.s,
+ nb_antennas_rx,
+ N_ap,
+ N_symb_SRS,
+ ofdm_symbol_size,
+ srs,
+ &srs_est,
+ &snr,
+ srs_estimated_channel_freq,
+ snr_per_rb,
+ &timing_advance_offset,
+ timing_advance_offset_nsec);
+
+ if ((snr * 10) < gNB->srs_thres) {
+ srs_est = -1;
+ }
+
+ srs_indication->handle = srs_pdu->handle;
+ srs_indication->rnti = srs_pdu->rnti;
+ srs_indication->timing_advance_offset = srs_est >= 0 ? timing_advance_offset : 0xFFFF;
+ // TODO: currently we fill timing_advance_offset_nsec for antenna 0. Need to extend it for other antennas
+ srs_indication->timing_advance_offset_nsec = srs_est >= 0 ? timing_advance_offset_nsec[0] : 0x8000;
+ switch (srs_pdu->srs_parameters_v4.usage) {
+ case 0:
+ LOG_W(NR_PHY, "SRS report was not requested by MAC\n");
+ return;
+ case 1 << NFAPI_NR_SRS_BEAMMANAGEMENT:
+ srs_indication->srs_usage = NFAPI_NR_SRS_BEAMMANAGEMENT;
+ break;
+ case 1 << NFAPI_NR_SRS_CODEBOOK:
+ srs_indication->srs_usage = NFAPI_NR_SRS_CODEBOOK;
+ break;
+ case 1 << NFAPI_NR_SRS_NONCODEBOOK:
+ srs_indication->srs_usage = NFAPI_NR_SRS_NONCODEBOOK;
+ break;
+ case 1 << NFAPI_NR_SRS_ANTENNASWITCH:
+ srs_indication->srs_usage = NFAPI_NR_SRS_ANTENNASWITCH;
+ break;
+ default:
+ LOG_E(NR_PHY, "Invalid srs_pdu->srs_parameters_v4.usage %i\n", srs_pdu->srs_parameters_v4.usage);
+ }
+ srs_indication->report_type = srs_pdu->srs_parameters_v4.report_type[0];
+
+ nfapi_srs_report_tlv_t *report_tlv = &srs_indication->report_tlv;
+ report_tlv->tag = 0;
+ report_tlv->length = 0;
+
+ start_meas(&gNB->srs_report_tlv_stats);
+ switch (srs_indication->srs_usage) {
+ case NFAPI_NR_SRS_BEAMMANAGEMENT: {
+ start_meas(&gNB->srs_beam_report_stats);
+ nfapi_nr_srs_beamforming_report_t nr_srs_bf_report;
+ nr_srs_bf_report.prg_size = srs_pdu->beamforming.prg_size;
+ nr_srs_bf_report.num_symbols = N_symb_SRS;
+ nr_srs_bf_report.wide_band_snr = srs_est >= 0 ? (snr + 64) << 1 : 0xFF; // 0xFF will be set if this field is invalid
+ nr_srs_bf_report.num_reported_symbols = N_symb_SRS;
+ AssertFatal(nr_srs_bf_report.num_reported_symbols == 1,
+ "nr_srs_bf_report.num_reported_symbols %i not handled yet!\n",
+ nr_srs_bf_report.num_reported_symbols);
+ fill_srs_reported_symbol(&nr_srs_bf_report.reported_symbol_list[0], srs_pdu, snr_per_rb, srs_est);
+
+ report_tlv->length = pack_nr_srs_beamforming_report(&nr_srs_bf_report, report_tlv->value, sizeof(report_tlv->value));
+ stop_meas(&gNB->srs_beam_report_stats);
+ break;
+ }
+
+ case NFAPI_NR_SRS_CODEBOOK: {
+ start_meas(&gNB->srs_iq_matrix_stats);
+ nfapi_nr_srs_normalized_channel_iq_matrix_t nr_srs_channel_iq_matrix;
+ fill_srs_channel_matrix(&nr_srs_channel_iq_matrix,
+ srs_pdu,
+ &srs_info,
+ frame_parms,
+ srs_estimated_channel_freq);
+
+ report_tlv->length =
+ pack_nr_srs_normalized_channel_iq_matrix(&nr_srs_channel_iq_matrix, report_tlv->value, sizeof(report_tlv->value));
+ stop_meas(&gNB->srs_iq_matrix_stats);
+ break;
+ }
+
+ case NFAPI_NR_SRS_NONCODEBOOK:
+ case NFAPI_NR_SRS_ANTENNASWITCH:
+ LOG_W(NR_PHY, "PHY procedures for this SRS usage are not implemented yet!\n");
+ break;
+
+ default:
+ AssertFatal(1 == 0, "Invalid SRS usage\n");
+ }
+ stop_meas(&gNB->srs_report_tlv_stats);
+}
+
+static void handle_pucch(PHY_VARS_gNB *gNB, c16_t **rxdataF, const NR_gNB_PUCCH_job_t *pucch, nfapi_nr_uci_t *uci)
+{
+ const nfapi_nr_pucch_pdu_t *pucch_pdu = &pucch->pucch_pdu;
+
+ switch (pucch_pdu->format_type) {
+ case 0:
+ uci->pdu_type = NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE;
+ uci->pdu_size = sizeof(nfapi_nr_uci_pucch_pdu_format_0_1_t);
+ nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_pdu_format0 = &uci->pucch_pdu_format_0_1;
+ nr_decode_pucch0(gNB, rxdataF, pucch->frame, pucch->slot, uci_pdu_format0, pucch_pdu);
+ break;
+ case 2:
+ uci->pdu_type = NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE;
+ uci->pdu_size = sizeof(nfapi_nr_uci_pucch_pdu_format_2_3_4_t);
+ nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu_format2 = &uci->pucch_pdu_format_2_3_4;
+ nr_decode_pucch2(gNB, rxdataF, pucch->frame, pucch->slot, uci_pdu_format2, pucch_pdu);
+ break;
+ default:
+ AssertFatal(1 == 0, "Only PUCCH formats 0 and 2 are currently supported\n");
+ }
+}
+
+static bool handle_pusch_decode_trigger(PHY_VARS_gNB *gNB, NR_gNB_PUSCH *pusch_vars, NR_gNB_ULSCH_t *ulsch, NR_UL_IND_t *UL_INFO, int *pusch_DTX)
+{
+ NR_UL_gNB_HARQ_t *ulsch_harq = ulsch->harq_process;
+ AssertFatal(ulsch_harq != NULL, "harq_pid %d is not allocated\n", ulsch->harq_pid);
+ const nfapi_nr_pusch_pdu_t *pdu = &ulsch_harq->ulsch_pdu;
+
+#ifdef DEBUG_RXDATA
+ RU_t *ru = gNB->RU_list[0];
+ int slot_offset = frame_parms->get_samples_slot_timestamp(ulsch->slot, frame_parms, 0);
+ slot_offset -= ru->N_TA_offset;
+ int32_t sample_offset = gNB->common_vars.debugBuff_sample_offset;
+ int16_t buf = (int16_t *)&gNB->common_vars.debugBuff[offset];
+ buf[0] = (int16_t)ulsch->rnti;
+ buf[1] = (int16_t)pdu->rb_size;
+ buf[2] = (int16_t)pdu->rb_start;
+ buf[3] = (int16_t)pdu->nr_of_symbols;
+ buf[4] = (int16_t)pdu->start_symbol_index;
+ buf[5] = (int16_t)pdu->mcs_index;
+ buf[6] = (int16_t)pdu->pusch_data.rv_index;
+ buf[7] = (int16_t)ulsch->harq_pid;
+ memcpy(&gNB->common_vars.debugBuff[gNB->common_vars.debugBuff_sample_offset + 4],
+ &ru->common.rxdata[0][slot_offset],
+ frame_parms->get_samples_per_slot(ulsch->slot, frame_parms) * sizeof(int32_t));
+ gNB->common_vars.debugBuff_sample_offset += (frame_parms->get_samples_per_slot(ulsch->slot, frame_parms) + 1000 + 4);
+ if (gNB->common_vars.debugBuff_sample_offset > ((frame_parms->get_samples_per_slot(ulsch->slot, frame_parms) + 1000 + 2) * 20)) {
+ FILE *f;
+ f = fopen("rxdata_buff.raw", "w");
+ if (f == NULL)
+ exit(1);
+ fwrite((int16_t *)gNB->common_vars.debugBuff,
+ 2,
+ (frame_parms->get_samples_per_slot(ulsch->slot, frame_parms) + 1000 + 4) * 20 * 2,
+ f);
+ fclose(f);
+ exit(-1);
+ }
+#endif
+
+ start_meas(&gNB->rx_pusch_stats);
+ nr_rx_pusch_tp(gNB, pusch_vars, pdu, &ulsch->unav_res, ulsch->frame, ulsch->slot, ulsch->beam_nb);
+ pusch_vars->ulsch_power_tot = 0;
+ pusch_vars->ulsch_noise_power_tot = 0;
+ for (int aarx = 0; aarx < gNB->frame_parms.nb_antennas_rx; aarx++) {
+ pusch_vars->ulsch_power_tot += pusch_vars->ulsch_power[aarx];
+ pusch_vars->ulsch_noise_power_tot += pusch_vars->ulsch_noise_power[aarx];
+ }
+ if (dB_fixed_x10(pusch_vars->ulsch_power_tot) < dB_fixed_x10(pusch_vars->ulsch_noise_power_tot) + gNB->pusch_thres) {
+ NR_gNB_PHY_STATS_t *stats = get_phy_stats(gNB, ulsch->rnti);
+
+ LOG_D(PHY,
+ "PUSCH not detected in %d.%d (%d,%d,%d)\n",
+ ulsch->frame,
+ ulsch->slot,
+ dB_fixed_x10(pusch_vars->ulsch_power_tot),
+ dB_fixed_x10(pusch_vars->ulsch_noise_power_tot),
+ gNB->pusch_thres);
+ pusch_vars->ulsch_power_tot = pusch_vars->ulsch_noise_power_tot;
+ pusch_vars->DTX = 1;
+ if (stats)
+ stats->ulsch_stats.DTX++;
+ if (!get_softmodem_params()->phy_test) {
+ /* in case of phy_test mode, we still want to decode to measure execution time.
+ Therefore, we don't yet call nr_fill_indication, it will be called later */
+ nfapi_nr_crc_t *crc = &UL_INFO->crc_ind.crc_list[UL_INFO->crc_ind.number_crcs++];
+ nfapi_nr_rx_data_pdu_t *rx = &UL_INFO->rx_ind.pdu_list[UL_INFO->rx_ind.number_of_pdus++];
+ nr_fill_indication(gNB, ulsch->frame, ulsch->slot, pusch_vars, pdu, stats, NULL, 1, crc, rx);
+ (*pusch_DTX)++;
+ gNBdumpScopeData(gNB, ulsch->slot, ulsch->frame, "ULSCH_DTX");
+ return false;
+ }
+ } else {
+ LOG_D(PHY,
+ "PUSCH detected in %d.%d (%d,%d,%d)\n",
+ ulsch->frame,
+ ulsch->slot,
+ dB_fixed_x10(pusch_vars->ulsch_power_tot),
+ dB_fixed_x10(pusch_vars->ulsch_noise_power_tot),
+ gNB->pusch_thres);
+
+ pusch_vars->DTX = 0;
+ }
+ stop_meas(&gNB->rx_pusch_stats);
+
+ return true;
+}
+
+static bool drop_old_pucch(const void *data, void *user)
+{
+ const NR_gNB_PUCCH_job_t *pucch = data;
+ const fsn_t *now = user;
+ const fsn_t t = {pucch->frame, pucch->slot, now->mu};
+ bool drop = fsn_in_the_past(t, *now);
+ if (drop)
+ LOG_E(NR_PHY, "%4d.%2d PUCCH job for UE %04x is in the past (%4d.%2d)\n", now->f, now->s, pucch->pucch_pdu.rnti, t.f, t.s);
+ return drop;
+}
+
+static bool get_current_pucch(const void *data, void *user)
+{
+ const NR_gNB_PUCCH_job_t *pucch = data;
+ const fsn_t *now = user;
+ const fsn_t t = {pucch->frame, pucch->slot, now->mu};
+ return fsn_equal(t, *now);
+}
+
+static bool drop_old_pusch(const void *data, void *user)
+{
+ const NR_gNB_PUSCH_job_t *pusch = data;
+ const fsn_t *now = user;
+ const fsn_t t = {pusch->frame, pusch->slot, now->mu};
+ bool drop = fsn_in_the_past(t, *now);
+ if (drop)
+ LOG_E(NR_PHY, "%4d.%2d PUSCH job for UE %04x is in the past (%4d.%2d)\n", now->f, now->s, pusch->pusch_pdu.rnti, t.f, t.s);
+ return drop;
+}
+
+static bool get_current_pusch(const void *data, void *user)
+{
+ const NR_gNB_PUSCH_job_t *pusch = data;
+ const fsn_t *now = user;
+ const fsn_t t = {pusch->frame, pusch->slot, now->mu};
+ return fsn_equal(t, *now);
+}
+
+static bool drop_old_srs(const void *data, void *user)
+{
+ const NR_gNB_SRS_job_t *srs = data;
+ const fsn_t *now = user;
+ const fsn_t t = {srs->frame, srs->slot, now->mu};
+ bool drop = fsn_in_the_past(t, *now);
+ if (drop)
+ LOG_E(NR_PHY, "%4d.%2d SRS job for UE %04x is in the past (%4d.%2d)\n", now->f, now->s, srs->srs_pdu.rnti, t.f, t.s);
+ return drop;
+}
+
+static bool get_current_srs(const void *data, void *user)
+{
+ const NR_gNB_SRS_job_t *srs = data;
+ const fsn_t *now = user;
+ const fsn_t t = {srs->frame, srs->slot, now->mu};
+ return fsn_equal(t, *now);
+}
+
+static int find_nr_ulsch_idx(PHY_VARS_gNB *gNB, uint16_t rnti, int pid)
+{
+ AssertFatal(gNB != NULL, "gNB is null\n");
+
+ int16_t first_free_index = -1;
+ for (int i = 0; i < gNB->max_nb_pusch; i++) {
+ const NR_gNB_ULSCH_t *ulsch = &gNB->ulsch[i];
+ AssertFatal(ulsch, "gNB->ulsch[%d] is null\n", i);
+ if (!ulsch->active) {
+ if (first_free_index == -1)
+ first_free_index = i;
+ } else {
+ // if there is already an active ULSCH for this RNTI and HARQ_PID
+ if ((ulsch->harq_pid == pid) && (ulsch->rnti == rnti))
+ return i;
+ }
+ }
+ return first_free_index;
+}
+static int handle_pusch_job_trigger(PHY_VARS_gNB *gNB, const NR_gNB_PUSCH_job_t *job)
+{
+ const nfapi_nr_pusch_pdu_t *pdu = &job->pusch_pdu;
+ int pid = pdu->pusch_data.harq_process_id;
+ int ULSCH_id = find_nr_ulsch_idx(gNB, pdu->rnti, pid);
+ if (ULSCH_id < 0) {
+ LOG_E(NR_PHY, "%4d.%2d cannot handle PUSCH job of RNTI %04x: no space\n", job->frame, job->slot, pdu->rnti);
+ return -1;
+ }
+ /* (re-)initialize this PUSCH context from job data */
+ NR_gNB_ULSCH_t *ulsch = &gNB->ulsch[ULSCH_id];
+ ulsch->active = true;
+ ulsch->frame = job->frame;
+ ulsch->slot = job->slot;
+ ulsch->rnti = pdu->rnti;
+ ulsch->harq_pid = pid;
+ ulsch->beam_nb = job->beam_nb;
+ ulsch->harq_process->ulsch_pdu = job->pusch_pdu;
+ if (pdu->pusch_data.new_data_indicator) {
+ ulsch->harq_process->harq_to_be_cleared = true;
+ ulsch->harq_process->round = 0;
+ } else {
+ ulsch->harq_process->round++;
+ }
+ return ULSCH_id;
}
int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, NR_UL_IND_t *UL_INFO)
{
/* those variables to log T_GNB_PHY_PUCCH_PUSCH_IQ only when we try to decode */
- int pucch_decode_done = 0;
- int pusch_decode_done = 0;
int pusch_DTX = 0;
const NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms;
const uint16_t ofdm_symbol_size = frame_parms->ofdm_symbol_size;
- const uint8_t nb_antennas_rx = frame_parms->nb_antennas_rx;
+
+ fsn_t now = {frame_rx, slot_rx, frame_parms->numerology_index};
+
+ spsc_q_drop_while(&gNB->pucch_queue, drop_old_pucch, &now);
+ NR_gNB_PUCCH_job_t pucch[MAX_NUM_NR_UCI_PDUS];
+ int n_pucch = spsc_q_get_while(&gNB->pucch_queue, get_current_pucch, &now, pucch, sizeof(*pucch), MAX_NUM_NR_UCI_PDUS);
+
+ spsc_q_drop_while(&gNB->pusch_queue, drop_old_pusch, &now);
+ NR_gNB_PUSCH_job_t pusch[MAX_UL_PDUS_PER_SLOT];
+ int n_pusch_jobs = spsc_q_get_while(&gNB->pusch_queue, get_current_pusch, &now, pusch, sizeof(*pusch), MAX_UL_PDUS_PER_SLOT);
+
+ spsc_q_drop_while(&gNB->srs_queue, drop_old_srs, &now);
+ NR_gNB_SRS_job_t srs[MAX_NUM_NR_SRS_PDUS];
+ int n_srs = spsc_q_get_while(&gNB->srs_queue, get_current_srs, &now, srs, sizeof(*srs), MAX_NUM_NR_SRS_PDUS);
+
LOG_D(PHY,"phy_procedures_gNB_uespec_RX frame %d, slot %d\n",frame_rx,slot_rx);
{
// Mask of occupied RBs, per symbol and PRB
- uint32_t rb_mask_ul[14][9];
- nfapi_nr_max_num_of_symbol_per_slot_t *slot_conf = NULL;
- if (frame_parms->frame_type == TDD)
- slot_conf = gNB->gNB_config.tdd_table.max_tdd_periodicity_list[slot_rx].max_num_of_symbol_per_slot_list;
- fill_ul_rb_mask(gNB, frame_rx, slot_rx, rb_mask_ul, slot_conf);
+ uint32_t rb_mask_ul[14][MAX_BWP_SIZE] = {0};
+ fill_ul_rb_mask(gNB, now, rb_mask_ul, pucch, n_pucch, pusch, n_pusch_jobs, srs, n_srs);
int first_symb = 0, num_symb = 0;
- if (frame_parms->frame_type == TDD)
+ if (frame_parms->frame_type == TDD) {
+ const nfapi_nr_max_num_of_symbol_per_slot_t *slot_conf = gNB->gNB_config.tdd_table.max_tdd_periodicity_list[slot_rx].max_num_of_symbol_per_slot_list;
for (int symbol_count = 0; symbol_count < frame_parms->symbols_per_slot; symbol_count++) {
if (slot_conf[symbol_count].slot_config.value == 1) {
if (num_symb == 0)
@@ -1017,51 +1215,21 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, N
num_symb++;
}
}
- else
+ } else {
num_symb = frame_parms->symbols_per_slot;
+ }
gNB_I0_measurements(gNB, slot_rx, first_symb, num_symb, rb_mask_ul);
}
- const int soffset = (slot_rx & 3) * frame_parms->symbols_per_slot * ofdm_symbol_size;
start_meas(&gNB->phy_proc_rx);
-
- for (int i = 0; i < gNB->max_nb_pucch; i++) {
- NR_gNB_PUCCH_t *pucch = &gNB->pucch[i];
- if (!(pucch && pucch->active && pucch->frame == frame_rx && pucch->slot == slot_rx))
- continue;
+ UL_INFO->uci_ind.uci_list = UL_INFO->uci_pdu_list;
+ UL_INFO->uci_ind.sfn = frame_rx;
+ UL_INFO->uci_ind.slot = slot_rx;
+ UL_INFO->uci_ind.num_ucis = n_pucch;
+ nfapi_nr_uci_t *uci = UL_INFO->uci_ind.uci_list;
+ for (int i = 0; i < n_pucch; ++i) {
c16_t **rxdataF = gNB->common_vars.rxdataF[pucch->beam_nb];
- pucch_decode_done = 1;
- nfapi_nr_pucch_pdu_t *pucch_pdu = &pucch->pucch_pdu;
- UL_INFO->uci_ind.uci_list = UL_INFO->uci_pdu_list;
- nfapi_nr_uci_t *uci = UL_INFO->uci_ind.uci_list + UL_INFO->uci_ind.num_ucis;
- UL_INFO->uci_ind.sfn = frame_rx;
- UL_INFO->uci_ind.slot = slot_rx;
- switch (pucch_pdu->format_type) {
- case 0:
- uci->pdu_type = NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE;
- uci->pdu_size = sizeof(nfapi_nr_uci_pucch_pdu_format_0_1_t);
- nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_pdu_format0 = &uci->pucch_pdu_format_0_1;
- int offset =
- pucch_pdu->start_symbol_index * ofdm_symbol_size + (frame_parms->first_carrier_offset + pucch_pdu->prb_start * 12);
- LOG_D(NR_PHY,
- "frame %d, slot %d: PUCCH signal energy %d\n",
- frame_rx,
- slot_rx,
- signal_energy_nodc(&rxdataF[0][soffset + offset], 12));
- nr_decode_pucch0(gNB, rxdataF, frame_rx, slot_rx, uci_pdu_format0, pucch_pdu);
- break;
- case 2:
- uci->pdu_type = NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE;
- uci->pdu_size = sizeof(nfapi_nr_uci_pucch_pdu_format_2_3_4_t);
- nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu_format2 = &uci->pucch_pdu_format_2_3_4;
- LOG_D(PHY, "%d.%d Calling nr_decode_pucch2\n", frame_rx, slot_rx);
- nr_decode_pucch2(gNB, rxdataF, frame_rx, slot_rx, uci_pdu_format2, pucch_pdu);
- break;
- default:
- AssertFatal(1 == 0, "Only PUCCH formats 0 and 2 are currently supported\n");
- }
- UL_INFO->uci_ind.num_ucis += 1;
- pucch->active = false;
+ handle_pucch(gNB, rxdataF, &pucch[i], uci++);
}
UL_INFO->crc_ind.sfn = frame_rx;
@@ -1070,95 +1238,16 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, N
UL_INFO->rx_ind.sfn = frame_rx;
UL_INFO->rx_ind.slot = slot_rx;
UL_INFO->rx_ind.pdu_list = UL_INFO->rx_pdu_list;
- bool ulsch_to_decode[gNB->max_nb_pusch];
- bzero(ulsch_to_decode, sizeof(ulsch_to_decode));
- for (int ULSCH_id = 0; ULSCH_id < gNB->max_nb_pusch; ULSCH_id++) {
- NR_gNB_ULSCH_t *ulsch = &gNB->ulsch[ULSCH_id];
- NR_UL_gNB_HARQ_t *ulsch_harq = ulsch->harq_process;
- AssertFatal(ulsch_harq != NULL, "harq_pid %d is not allocated\n", ulsch->harq_pid);
- if (!(ulsch->active && ulsch->frame == frame_rx && ulsch->slot == slot_rx && !ulsch->handled))
+ int ulsch_idx_to_decode[MAX_UL_PDUS_PER_SLOT];
+ int num_pusch = 0;
+ for (int i = 0; i < n_pusch_jobs; ++i) {
+ int ULSCH_id = handle_pusch_job_trigger(gNB, &pusch[i]);
+ if (ULSCH_id < 0)
continue;
- LOG_D(PHY, "PUSCH ID %d with RNTI %x detection started in frame %d slot %d\n", ULSCH_id, ulsch->rnti, frame_rx, slot_rx);
-
-#ifdef DEBUG_RXDATA
- RU_t *ru = gNB->RU_list[0];
- int slot_offset = frame_parms->get_samples_slot_timestamp(slot_rx, frame_parms, 0);
- slot_offset -= ru->N_TA_offset;
- int32_t sample_offset = gNB->common_vars.debugBuff_sample_offset;
- int16_t buf = (int16_t *)&gNB->common_vars.debugBuff[offset];
- buf[0] = (int16_t)ulsch->rnti;
- buf[1] = (int16_t)pdu->rb_size;
- buf[2] = (int16_t)pdu->rb_start;
- buf[3] = (int16_t)pdu->nr_of_symbols;
- buf[4] = (int16_t)pdu->start_symbol_index;
- buf[5] = (int16_t)pdu->mcs_index;
- buf[6] = (int16_t)pdu->pusch_data.rv_index;
- buf[7] = (int16_t)ulsch->harq_pid;
- memcpy(&gNB->common_vars.debugBuff[gNB->common_vars.debugBuff_sample_offset + 4],
- &ru->common.rxdata[0][slot_offset],
- get_samples_per_slot(slot_rx, frame_parms) * sizeof(int32_t));
- gNB->common_vars.debugBuff_sample_offset += (get_samples_per_slot(slot_rx, frame_parms) + 1000 + 4);
- if (gNB->common_vars.debugBuff_sample_offset > ((get_samples_per_slot(slot_rx, frame_parms) + 1000 + 2) * 20)) {
- FILE *f;
- f = fopen("rxdata_buff.raw", "w");
- if (f == NULL)
- exit(1);
- fwrite((int16_t *)gNB->common_vars.debugBuff, 2, (get_samples_per_slot(slot_rx, frame_parms) + 1000 + 4) * 20 * 2, f);
- fclose(f);
- exit(-1);
- }
-#endif
-
- pusch_decode_done = 1;
-
- start_meas(&gNB->rx_pusch_stats);
- nr_rx_pusch_tp(gNB, ULSCH_id, frame_rx, slot_rx, ulsch->beam_nb);
NR_gNB_PUSCH *pusch_vars = &gNB->pusch_vars[ULSCH_id];
- pusch_vars->ulsch_power_tot = 0;
- pusch_vars->ulsch_noise_power_tot = 0;
- for (int aarx = 0; aarx < nb_antennas_rx; aarx++) {
- pusch_vars->ulsch_power_tot += pusch_vars->ulsch_power[aarx];
- pusch_vars->ulsch_noise_power_tot += pusch_vars->ulsch_noise_power[aarx];
- }
- if (dB_fixed_x10(pusch_vars->ulsch_power_tot) < dB_fixed_x10(pusch_vars->ulsch_noise_power_tot) + gNB->pusch_thres) {
- NR_gNB_PHY_STATS_t *stats = get_phy_stats(gNB, ulsch->rnti);
-
- LOG_D(PHY,
- "PUSCH not detected in %d.%d (%d,%d,%d)\n",
- frame_rx,
- slot_rx,
- dB_fixed_x10(pusch_vars->ulsch_power_tot),
- dB_fixed_x10(pusch_vars->ulsch_noise_power_tot),
- gNB->pusch_thres);
- pusch_vars->ulsch_power_tot = pusch_vars->ulsch_noise_power_tot;
- pusch_vars->DTX = 1;
- if (stats)
- stats->ulsch_stats.DTX++;
- if (!get_softmodem_params()->phy_test) {
- /* in case of phy_test mode, we still want to decode to measure execution time.
- Therefore, we don't yet call nr_fill_indication, it will be called later */
- nfapi_nr_crc_t *crc = &UL_INFO->crc_ind.crc_list[UL_INFO->crc_ind.number_crcs++];
- nfapi_nr_rx_data_pdu_t *pdu = &UL_INFO->rx_ind.pdu_list[UL_INFO->rx_ind.number_of_pdus++];
- nr_fill_indication(gNB, frame_rx, slot_rx, ULSCH_id, ulsch->harq_pid, 1, 1, crc, pdu);
- pusch_DTX++;
- gNBdumpScopeData(gNB, ulsch->slot, ulsch->frame, "ULSCH_DTX");
- continue;
- }
- } else {
- LOG_D(PHY,
- "PUSCH detected in %d.%d (%d,%d,%d)\n",
- frame_rx,
- slot_rx,
- dB_fixed_x10(pusch_vars->ulsch_power_tot),
- dB_fixed_x10(pusch_vars->ulsch_noise_power_tot),
- gNB->pusch_thres);
-
- pusch_vars->DTX = 0;
- }
- ulsch_to_decode[ULSCH_id] = true;
- stop_meas(&gNB->rx_pusch_stats);
- // LOG_M("rxdataF_comp.m","rxF_comp",gNB->pusch_vars[0]->rxdataF_comp[0],6900,1,1);
- // LOG_M("rxdataF_ext.m","rxF_ext",gNB->pusch_vars[0]->rxdataF_ext[0],6900,1,1);
+ NR_gNB_ULSCH_t *ulsch = &gNB->ulsch[ULSCH_id];
+ if (handle_pusch_decode_trigger(gNB, pusch_vars, ulsch, UL_INFO, &pusch_DTX))
+ ulsch_idx_to_decode[num_pusch++] = ULSCH_id;
}
/* Do ULSCH decoding time measurement only when number of PUSCH is limited to 1
@@ -1168,9 +1257,10 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, N
if (gNB->max_nb_pusch == 1)
start_meas(&gNB->ulsch_decoding_stats);
- int const ret_nr_ulsch_procedures = nr_ulsch_procedures(gNB, frame_rx, slot_rx, ulsch_to_decode, UL_INFO);
- if (ret_nr_ulsch_procedures != 0) {
- LOG_E(PHY,"Error in nr_ulsch_procedures, returned %d\n",ret_nr_ulsch_procedures);
+ if (num_pusch > 0) {
+ int ret_nr_ulsch_procedures = nr_ulsch_procedures(gNB, frame_rx, slot_rx, ulsch_idx_to_decode, num_pusch, UL_INFO);
+ if (ret_nr_ulsch_procedures != 0)
+ LOG_E(PHY,"Error in nr_ulsch_procedures, returned %d\n",ret_nr_ulsch_procedures);
}
/* Do ULSCH decoding time measurement only when number of PUSCH is limited to 1
@@ -1180,208 +1270,20 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, N
if (gNB->max_nb_pusch == 1)
stop_meas(&gNB->ulsch_decoding_stats);
- for (int i = 0; i < gNB->max_nb_srs; i++) {
- NR_gNB_SRS_t *srs = &gNB->srs[i];
- if (!(srs && srs->active && srs->frame == frame_rx && srs->slot == slot_rx))
- continue;
- LOG_D(NR_PHY, "(%d.%d) gNB is waiting for SRS, id = %i\n", frame_rx, slot_rx, i);
-
+ UL_INFO->srs_ind.sfn = frame_rx;
+ UL_INFO->srs_ind.slot = slot_rx;
+ UL_INFO->srs_ind.pdu_list = UL_INFO->srs_pdu_list;
+ UL_INFO->srs_ind.number_of_pdus = n_srs;
+ for (int i = 0; i < n_srs; ++i) {
start_meas(&gNB->rx_srs_stats);
-
- uint8_t N_symb_SRS = 1 << srs->srs_pdu.num_symbols;
- uint8_t N_ap = 1 << srs->srs_pdu.num_ant_ports;
- int16_t snr_per_rb[srs->srs_pdu.bwp_size];
- nfapi_nr_srs_pdu_t *srs_pdu = &srs->srs_pdu;
- uint16_t timing_advance_offset;
- int16_t timing_advance_offset_nsec[nb_antennas_rx];
- int srs_est;
-
- c16_t srs_estimated_channel_freq[nb_antennas_rx][N_ap][ofdm_symbol_size * N_symb_SRS] __attribute__((aligned(32)));
- c16_t srs_estimated_channel_time[nb_antennas_rx][N_ap][NR_SRS_IDFT_OVERSAMP_FACTOR * ofdm_symbol_size]
- __attribute__((aligned(32)));
-
- nr_srs_rx_procedures(gNB,
- frame_rx,
- slot_rx,
- nb_antennas_rx,
- N_ap,
- N_symb_SRS,
- ofdm_symbol_size,
- srs,
- gNB->nr_srs_info[i],
- &srs_est,
- srs_estimated_channel_freq,
- srs_estimated_channel_time,
- snr_per_rb,
- &timing_advance_offset,
- timing_advance_offset_nsec);
-
- if ((gNB->srs->snr * 10) < gNB->srs_thres) {
- srs_est = -1;
- }
-
- UL_INFO->srs_ind.sfn = frame_rx;
- UL_INFO->srs_ind.slot = slot_rx;
-
- // data model difficult to understand, nfapi do malloc for this pointer
- UL_INFO->srs_ind.pdu_list = UL_INFO->srs_pdu_list;
- nfapi_nr_srs_indication_pdu_t *srs_indication = UL_INFO->srs_pdu_list + UL_INFO->srs_ind.number_of_pdus++;
- srs_indication->handle = srs_pdu->handle;
- srs_indication->rnti = srs_pdu->rnti;
- srs_indication->timing_advance_offset = srs_est >= 0 ? timing_advance_offset : 0xFFFF;
- // TODO: currently we fill timing_advance_offset_nsec for antenna 0. Need to extend it for other antennas
- srs_indication->timing_advance_offset_nsec = srs_est >= 0 ? timing_advance_offset_nsec[0] : 0x8000;
- switch (srs_pdu->srs_parameters_v4.usage) {
- case 0:
- LOG_W(NR_PHY, "SRS report was not requested by MAC\n");
- return 0;
- case 1 << NFAPI_NR_SRS_BEAMMANAGEMENT:
- srs_indication->srs_usage = NFAPI_NR_SRS_BEAMMANAGEMENT;
- break;
- case 1 << NFAPI_NR_SRS_CODEBOOK:
- srs_indication->srs_usage = NFAPI_NR_SRS_CODEBOOK;
- break;
- case 1 << NFAPI_NR_SRS_NONCODEBOOK:
- srs_indication->srs_usage = NFAPI_NR_SRS_NONCODEBOOK;
- break;
- case 1 << NFAPI_NR_SRS_ANTENNASWITCH:
- srs_indication->srs_usage = NFAPI_NR_SRS_ANTENNASWITCH;
- break;
- default:
- LOG_E(NR_PHY, "Invalid srs_pdu->srs_parameters_v4.usage %i\n", srs_pdu->srs_parameters_v4.usage);
- }
- srs_indication->report_type = srs_pdu->srs_parameters_v4.report_type[0];
-
-#ifdef SRS_IND_DEBUG
- LOG_I(NR_PHY, "UL_INFO->srs_ind.sfn = %i\n", UL_INFO->srs_ind.sfn);
- LOG_I(NR_PHY, "UL_INFO->srs_ind.slot = %i\n", UL_INFO->srs_ind.slot);
- LOG_I(NR_PHY, "srs_indication->rnti = %04x\n", srs_indication->rnti);
- LOG_I(NR_PHY, "srs_indication->timing_advance = %i\n", srs_indication->timing_advance_offset);
- LOG_I(NR_PHY, "srs_indication->timing_advance_offset_nsec = %i\n", srs_indication->timing_advance_offset_nsec);
- LOG_I(NR_PHY, "srs_indication->srs_usage = %i\n", srs_indication->srs_usage);
- LOG_I(NR_PHY, "srs_indication->report_type = %i\n", srs_indication->report_type);
-#endif
-
- nfapi_srs_report_tlv_t *report_tlv = &srs_indication->report_tlv;
- report_tlv->tag = 0;
- report_tlv->length = 0;
-
- start_meas(&gNB->srs_report_tlv_stats);
- switch (srs_indication->srs_usage) {
- case NFAPI_NR_SRS_BEAMMANAGEMENT: {
- start_meas(&gNB->srs_beam_report_stats);
- nfapi_nr_srs_beamforming_report_t nr_srs_bf_report;
- nr_srs_bf_report.prg_size = srs_pdu->beamforming.prg_size;
- nr_srs_bf_report.num_symbols = N_symb_SRS;
- nr_srs_bf_report.wide_band_snr =
- srs_est >= 0 ? (gNB->srs->snr + 64) << 1 : 0xFF; // 0xFF will be set if this field is invalid
- nr_srs_bf_report.num_reported_symbols = N_symb_SRS;
- AssertFatal(nr_srs_bf_report.num_reported_symbols == 1,
- "nr_srs_bf_report.num_reported_symbols %i not handled yet!\n",
- nr_srs_bf_report.num_reported_symbols);
- fill_srs_reported_symbol(&nr_srs_bf_report.reported_symbol_list[0], srs_pdu, snr_per_rb, srs_est);
-
-#ifdef SRS_IND_DEBUG
- LOG_I(NR_PHY, "nr_srs_bf_report.prg_size = %i\n", nr_srs_bf_report.prg_size);
- LOG_I(NR_PHY, "nr_srs_bf_report.num_symbols = %i\n", nr_srs_bf_report.num_symbols);
- LOG_I(NR_PHY,
- "nr_srs_bf_report.wide_band_snr = %i (%i dB)\n",
- nr_srs_bf_report.wide_band_snr,
- (nr_srs_bf_report.wide_band_snr >> 1) - 64);
- LOG_I(NR_PHY, "nr_srs_bf_report.num_reported_symbols = %i\n", nr_srs_bf_report.num_reported_symbols);
- LOG_I(NR_PHY,
- "nr_srs_bf_report.reported_symbol_list[0].num_prgs = %i\n",
- nr_srs_bf_report.reported_symbol_list[0].num_prgs);
- for (int prg_idx = 0; prg_idx < nr_srs_bf_report.reported_symbol_list[0].num_prgs; prg_idx++) {
- LOG_I(NR_PHY,
- "nr_srs_beamforming_report.reported_symbol_list[0].prg_list[%3i].rb_snr = %i (%i dB)\n",
- prg_idx,
- nr_srs_bf_report.reported_symbol_list[0].prg_list[prg_idx].rb_snr,
- (nr_srs_bf_report.reported_symbol_list[0].prg_list[prg_idx].rb_snr >> 1) - 64);
- }
-#endif
-
- report_tlv->length = pack_nr_srs_beamforming_report(&nr_srs_bf_report, report_tlv->value, sizeof(report_tlv->value));
- stop_meas(&gNB->srs_beam_report_stats);
- break;
- }
-
- case NFAPI_NR_SRS_CODEBOOK: {
- start_meas(&gNB->srs_iq_matrix_stats);
- nfapi_nr_srs_normalized_channel_iq_matrix_t nr_srs_channel_iq_matrix;
- fill_srs_channel_matrix(&nr_srs_channel_iq_matrix,
- srs_pdu,
- gNB->nr_srs_info[i],
- srs_pdu->srs_parameters_v4.iq_representation,
- nb_antennas_rx,
- srs_pdu->srs_parameters_v4.num_total_ue_antennas,
- srs_pdu->srs_parameters_v4.prg_size,
- srs_pdu->srs_parameters_v4.srs_bandwidth_size / srs_pdu->srs_parameters_v4.prg_size,
- frame_parms,
- srs_estimated_channel_freq);
-
-#ifdef SRS_IND_DEBUG
- LOG_I(NR_PHY,
- "nr_srs_channel_iq_matrix.normalized_iq_representation = %i\n",
- nr_srs_channel_iq_matrix.normalized_iq_representation);
- LOG_I(NR_PHY,
- "nr_srs_channel_iq_matrix.num_gnb_antenna_elements = %i\n",
- nr_srs_channel_iq_matrix.num_gnb_antenna_elements);
- LOG_I(NR_PHY, "nr_srs_channel_iq_matrix.num_ue_srs_ports = %i\n", nr_srs_channel_iq_matrix.num_ue_srs_ports);
- LOG_I(NR_PHY, "nr_srs_channel_iq_matrix.prg_size = %i\n", nr_srs_channel_iq_matrix.prg_size);
- LOG_I(NR_PHY, "nr_srs_channel_iq_matrix.num_prgs = %i\n", nr_srs_channel_iq_matrix.num_prgs);
- c16_t *channel_matrix16 = (c16_t *)nr_srs_channel_iq_matrix.channel_matrix;
- c8_t *channel_matrix8 = (c8_t *)nr_srs_channel_iq_matrix.channel_matrix;
- for (int uI = 0; uI < nr_srs_channel_iq_matrix.num_ue_srs_ports; uI++) {
- for (int gI = 0; gI < nr_srs_channel_iq_matrix.num_gnb_antenna_elements; gI++) {
- for (int pI = 0; pI < nr_srs_channel_iq_matrix.num_prgs; pI++) {
- uint16_t index = uI * nr_srs_channel_iq_matrix.num_gnb_antenna_elements * nr_srs_channel_iq_matrix.num_prgs
- + gI * nr_srs_channel_iq_matrix.num_prgs + pI;
- LOG_I(
- NR_PHY,
- "(uI %i, gI %i, pI %i) channel_matrix --> real %i, imag %i\n",
- uI,
- gI,
- pI,
- nr_srs_channel_iq_matrix.normalized_iq_representation == 0 ? channel_matrix8[index].r : channel_matrix16[index].r,
- nr_srs_channel_iq_matrix.normalized_iq_representation == 0 ? channel_matrix8[index].i
- : channel_matrix16[index].i);
- }
- }
- }
-#endif
-
- report_tlv->length =
- pack_nr_srs_normalized_channel_iq_matrix(&nr_srs_channel_iq_matrix, report_tlv->value, sizeof(report_tlv->value));
- stop_meas(&gNB->srs_iq_matrix_stats);
- break;
- }
-
- case NFAPI_NR_SRS_NONCODEBOOK:
- case NFAPI_NR_SRS_ANTENNASWITCH:
- LOG_W(NR_PHY, "PHY procedures for this SRS usage are not implemented yet!\n");
- break;
-
- default:
- AssertFatal(1 == 0, "Invalid SRS usage\n");
- }
- stop_meas(&gNB->srs_report_tlv_stats);
-
-#ifdef SRS_IND_DEBUG
- LOG_I(NR_PHY, "report_tlv->tag = %i\n", report_tlv->tag);
- LOG_I(NR_PHY, "report_tlv->length = %i\n", report_tlv->length);
- char *value = (char *)report_tlv->value;
- for (int b = 0; b < report_tlv->length; b++) {
- LOG_I(NR_PHY, "value[%i] = 0x%02x\n", b, value[b] & 0xFF);
- }
-#endif
- srs->active = false;
+ handle_srs(now, gNB, &srs[i], &UL_INFO->srs_ind.pdu_list[i]);
stop_meas(&gNB->rx_srs_stats);
}
stop_meas(&gNB->phy_proc_rx);
- if (pucch_decode_done || pusch_decode_done) {
+ if (n_pucch > 0 || num_pusch > 0) {
+ UNUSED(ofdm_symbol_size); // only used if T activated
T(T_GNB_PHY_PUCCH_PUSCH_IQ,
T_INT(frame_rx),
T_INT(slot_rx),
@@ -1417,9 +1319,7 @@ void nr_save_ul_tti_req(PHY_VARS_gNB *gNB, nfapi_nr_ul_tti_request_t *UL_tti_req
break;
case NFAPI_NR_UL_CONFIG_PRACH_PDU_TYPE: {
nfapi_nr_prach_pdu_t *prach_pdu = &UL_tti_req->pdus_list[i].prach_pdu;
- prach_item_t *prach = nr_schedule_rx_prach(gNB, UL_tti_req->SFN, UL_tti_req->Slot, prach_pdu);
- if (!prach)
- LOG_W(NR_PHY_RACH, "Error in scheduling rach\n");
+ nr_schedule_rx_prach(gNB, UL_tti_req->SFN, UL_tti_req->Slot, prach_pdu);
} break;
case NFAPI_NR_UL_CONFIG_SRS_PDU_TYPE:
nr_fill_srs(gNB, UL_tti_req->SFN, UL_tti_req->Slot, &UL_tti_req->pdus_list[i].srs_pdu);
diff --git a/openair1/SCHED_NR/sched_nr.h b/openair1/SCHED_NR/sched_nr.h
index 7ff044b46c..ba1d00457b 100644
--- a/openair1/SCHED_NR/sched_nr.h
+++ b/openair1/SCHED_NR/sched_nr.h
@@ -18,7 +18,7 @@ void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB,
int slot);
void nr_save_ul_tti_req(PHY_VARS_gNB *gNB, nfapi_nr_ul_tti_request_t *UL_tti_req);
int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, NR_UL_IND_t *UL_INFO);
-void L1_nr_prach_procedures(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_rach_indication_t *rach_ind);
+void L1_nr_prach_procedures(PHY_VARS_gNB *gNB, prach_item_t *prach_id, nfapi_nr_rach_indication_t *rach_ind);
void nr_common_signal_procedures (PHY_VARS_gNB *gNB,int frame,int slot, const nfapi_nr_dl_tti_ssb_pdu *ssb_pdu);
void nr_feptx_ofdm(RU_t *ru,int frame_tx,int tti_tx);
void nr_feptx0(RU_t *ru,int tti_tx,int first_symbol, int num_symbols, int aa);
diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c
index 225634937b..f9c8f38b56 100644
--- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c
+++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c
@@ -243,7 +243,7 @@ void ue_ta_procedures(PHY_VARS_NR_UE *ue, int slot_tx, int frame_tx)
}
}
-static void configure_srs_info(fapi_nr_ul_config_srs_pdu *srs_config_pdu, nr_srs_info_t *nr_srs_info)
+static void configure_srs_info(const fapi_nr_ul_config_srs_pdu *srs_config_pdu, nr_srs_info_t *nr_srs_info)
{
nr_srs_info->B_SRS = srs_config_pdu->bandwidth_index;
nr_srs_info->C_SRS = srs_config_pdu->config_index;
@@ -272,25 +272,17 @@ static void configure_srs_info(fapi_nr_ul_config_srs_pdu *srs_config_pdu, nr_srs
* PARAMETERS : pointer to ue context
* pointer to rxtx context*
*
-* RETURN : 0 if it is a valid slot for transmitting srs
-* -1 if srs should not be transmitted
-*
* DESCRIPTION : ue srs procedure
* send srs according to current configuration
*
*********************************************************************/
-bool ue_srs_procedures_nr(PHY_VARS_NR_UE *ue,
+void ue_srs_procedures_nr(PHY_VARS_NR_UE *ue,
const UE_nr_rxtx_proc_t *proc,
c16_t **txdataF,
- nr_phy_data_tx_t *phy_data,
+ const fapi_nr_ul_config_srs_pdu *srs_config_pdu,
bool was_symbol_used[NR_SYMBOLS_PER_SLOT])
{
- if(phy_data->srs_vars.active == false) {
- return false;
- }
-
NR_DL_FRAME_PARMS *frame_parms = &(ue->frame_parms);
- fapi_nr_ul_config_srs_pdu *srs_config_pdu = &phy_data->srs_vars.srs_config_pdu;
const uint8_t l0 = frame_parms->symbols_per_slot - 1 - srs_config_pdu->time_start_position;
// Num consecutive SRS symbols according to 38.211 6.4.1.4.1
int num_srs_symbols[] = {1, 2, 4, 8, 12};
@@ -326,18 +318,20 @@ bool ue_srs_procedures_nr(PHY_VARS_NR_UE *ue,
LOG_I(NR_PHY,"srs_config_pdu->t_offset = %u\n", srs_config_pdu->t_offset);
#endif
- configure_srs_info(srs_config_pdu, ue->nr_srs_info);
+ nr_srs_info_t nr_srs_info = {0};
+ configure_srs_info(srs_config_pdu, &nr_srs_info);
uint16_t symbol_offset = l0 * frame_parms->ofdm_symbol_size;
bool generated = generate_srs_nr(frame_parms,
txdataF,
symbol_offset,
srs_config_pdu->bwp_start,
- ue->nr_srs_info,
+ &nr_srs_info,
AMP,
proc->frame_tx,
proc->nr_slot_tx,
frame_parms->nb_antennas_tx);
- return generated;
+ DevAssert(generated); // if we can't generate despite the SRS config, there
+ // is a problem
}
void phy_procedures_nrUE_TX(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_data_tx_t *phy_data, c16_t **txp)
@@ -365,7 +359,8 @@ void phy_procedures_nrUE_TX(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, n
nr_ue_ulsch_procedures(ue, frame_tx, slot_tx, phy_data, (c16_t **)&txdataF, was_symbol_used);
- ue_srs_procedures_nr(ue, proc, (c16_t **)&txdataF, phy_data, was_symbol_used);
+ if (phy_data->srs_vars.active)
+ ue_srs_procedures_nr(ue, proc, (c16_t **)&txdataF, &phy_data->srs_vars.srs_config_pdu, was_symbol_used);
pucch_procedures_ue_nr(ue, proc, phy_data, (c16_t **)&txdataF, was_symbol_used);
diff --git a/openair1/SIMULATION/NR_PHY/nr_unitary_common.c b/openair1/SIMULATION/NR_PHY/nr_unitary_common.c
index 9a595a9295..4f76749c8d 100644
--- a/openair1/SIMULATION/NR_PHY/nr_unitary_common.c
+++ b/openair1/SIMULATION/NR_PHY/nr_unitary_common.c
@@ -56,40 +56,6 @@ void handle_nr_slot_ind(uint16_t sfn, uint16_t slot)
UNUSED(slot);
}
-int pack_nr_srs_beamforming_report(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen)
-{
- UNUSED(pMessageBuf);
- UNUSED(pPackedBuf);
- UNUSED(packedBufLen);
- return 0;
-}
-int unpack_nr_srs_beamforming_report(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen)
-{
- UNUSED(pMessageBuf);
- UNUSED(messageBufLen);
- UNUSED(pUnpackedBuf);
- UNUSED(unpackedBufLen);
- return 0;
-}
-int pack_nr_srs_normalized_channel_iq_matrix(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen)
-{
- UNUSED(pMessageBuf);
- UNUSED(pPackedBuf);
- UNUSED(packedBufLen);
- return 0;
-}
-int unpack_nr_srs_normalized_channel_iq_matrix(void *pMessageBuf,
- uint32_t messageBufLen,
- void *pUnpackedBuf,
- uint32_t unpackedBufLen)
-{
- UNUSED(pMessageBuf);
- UNUSED(messageBufLen);
- UNUSED(pUnpackedBuf);
- UNUSED(unpackedBufLen);
- return 0;
-}
-
void configure_nr_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_addr, int pnf_p7_port, int vnf_p7_port)
{
UNUSED(vnf_ip_addr);
@@ -102,117 +68,3 @@ void configure_nr_nfapi_vnf(eth_params_t params)
{
UNUSED(params);
}
-int nfapi_nr_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen, nfapi_p7_codec_config_t *config)
-{
- UNUSED(pMessageBuf);
- UNUSED(pPackedBuf);
- UNUSED(packedBufLen);
- UNUSED(config);
- return 0;
-}
-bool nfapi_nr_p7_message_unpack(void *pMessageBuf,
- uint32_t messageBufLen,
- void *pUnpackedBuf,
- uint32_t unpackedBufLen,
- nfapi_p7_codec_config_t *config)
-{
- UNUSED(pMessageBuf);
- UNUSED(messageBufLen);
- UNUSED(pUnpackedBuf);
- UNUSED(unpackedBufLen);
- UNUSED(config);
- return false;
-}
-int nfapi_p7_message_header_unpack(void *pMessageBuf,
- uint32_t messageBufLen,
- void *pUnpackedBuf,
- uint32_t unpackedBufLen,
- nfapi_p7_codec_config_t *config)
-{
- UNUSED(pMessageBuf);
- UNUSED(messageBufLen);
- UNUSED(pUnpackedBuf);
- UNUSED(unpackedBufLen);
- UNUSED(config);
- return 0;
-}
-
-void nr_mac_rrc_sync_ind(const module_id_t module_id, const frame_t frame, const bool in_sync)
-{
- UNUSED(module_id);
- UNUSED(frame);
- UNUSED(in_sync);
-}
-
-void nr_mac_rrc_msg3_ind(const module_id_t mod_id, int rnti, int gnb_id)
-{
- UNUSED(mod_id);
- UNUSED(gnb_id);
- UNUSED(rnti);
-}
-
-void nr_mac_rrc_ra_ind(const module_id_t mod_id, bool success)
-{
- UNUSED(mod_id);
- UNUSED(success);
-}
-
-void nr_mac_rrc_inactivity_timer_ind(const module_id_t mod_id)
-{
- UNUSED(mod_id);
-}
-
-void rrc_data_ind(const protocol_ctxt_t *const ctxt_pP,
- const rb_id_t Srb_id,
- const sdu_size_t sdu_sizeP,
- const uint8_t *const buffer_pP)
-{
- UNUSED(ctxt_pP);
- UNUSED(Srb_id);
- UNUSED(sdu_sizeP);
- UNUSED(buffer_pP);
-}
-
-typedef uint32_t channel_t;
-int8_t nr_mac_rrc_data_ind_ue(const module_id_t module_id,
- const int CC_id,
- const uint8_t gNB_index,
- const int hfn,
- const frame_t frame,
- const int slot,
- const rnti_t rnti,
- const uint32_t cellid,
- const long arfcn,
- const channel_t channel,
- const uint8_t *pduP,
- const sdu_size_t pdu_len)
-{
- UNUSED(module_id);
- UNUSED(CC_id);
- UNUSED(gNB_index);
- UNUSED(hfn);
- UNUSED(frame);
- UNUSED(slot);
- UNUSED(rnti);
- UNUSED(arfcn);
- UNUSED(channel);
- UNUSED(pduP);
- UNUSED(pdu_len);
- UNUSED(cellid);
- return 0;
-}
-
-void nr_mac_rrc_meas_ind_ue(module_id_t module_id,
- uint32_t gNB_index,
- uint16_t Nid_cell,
- bool csi_meas,
- bool is_neighboring_cell,
- int rsrp_dBm)
-{
- UNUSED(module_id);
- UNUSED(Nid_cell);
- UNUSED(gNB_index);
- UNUSED(csi_meas);
- UNUSED(is_neighboring_cell);
- UNUSED(rsrp_dBm);
-}
diff --git a/openair1/SIMULATION/NR_PHY/prachsim.c b/openair1/SIMULATION/NR_PHY/prachsim.c
index 6e29abd9a5..b47b35b470 100644
--- a/openair1/SIMULATION/NR_PHY/prachsim.c
+++ b/openair1/SIMULATION/NR_PHY/prachsim.c
@@ -547,12 +547,10 @@ int main(int argc, char **argv){
phy_init_nr_gNB(gNB);
nr_phy_init_RU(ru);
- prach_item_t *prach_data = calloc(1,sizeof(prach_item_t));
- gNB->prach_list.list[0] = prach_data;
- nfapi_nr_prach_pdu_t *prach_pdu = &prach_data->pdu;
- prach_pdu->num_cs = get_NCS(NCS_config, format0, restrictedSetConfig);
- prach_config->num_prach_fd_occasions_list[fd_occasion].num_root_sequences.value = 1+(64/(N_ZC/prach_pdu->num_cs));
- prach_pdu->prach_format = prach_format;
+ nfapi_nr_prach_pdu_t prach_pdu = {0};
+ prach_pdu.num_cs = get_NCS(NCS_config, format0, restrictedSetConfig);
+ prach_config->num_prach_fd_occasions_list[fd_occasion].num_root_sequences.value = 1+(64/(N_ZC/prach_pdu.num_cs));
+ prach_pdu.prach_format = prach_format;
// Configure UE
UE = malloc(sizeof(PHY_VARS_NR_UE));
@@ -749,14 +747,14 @@ int main(int argc, char **argv){
}
nfapi_nr_prach_config_t *cfg = &gNB->gNB_config.prach_config;
- nfapi_nr_num_prach_fd_occasions_t *occ = &cfg->num_prach_fd_occasions_list[prach_pdu->num_ra];
- prach_pdu->num_prach_ocas=1;
+ nfapi_nr_num_prach_fd_occasions_t *occ = &cfg->num_prach_fd_occasions_list[prach_pdu.num_ra];
+ prach_pdu.num_prach_ocas=1;
prach_item_t *in = malloc(sizeof(prach_item_t)
+ sizeof(c16_t) * gNB->gNB_config.carrier_config.num_rx_ant.value
* NUMBER_OF_NR_RU_PRACH_OCCASIONS_MAX * NR_PRACH_SEQ_LEN_L);
*in = (prach_item_t){.frame = frame,
.slot = slot,
- .pdu = *prach_pdu,
+ .pdu = prach_pdu,
.rootSequenceIndex = occ->prach_root_sequence_index.value,
.numrootSequenceIndex = occ->num_root_sequences.value,
.msg1_frequencystart = occ->k1.value,
@@ -772,7 +770,7 @@ int main(int argc, char **argv){
if (n_frames == 1)
LOG_I(PHY,
"ncs %d,num_seq %d\n",
- prach_pdu->num_cs,
+ prach_pdu.num_cs,
prach_config->num_prach_fd_occasions_list[fd_occasion].num_root_sequences.value);
rx_prach_out_t out = rx_nr_prach(in, prachOccasion);
@@ -823,7 +821,6 @@ int main(int argc, char **argv){
nr_phy_free_RU(ru);
free(RC.ru[0]);
free(RC.ru);
- free(prach_data);
phy_free_nr_gNB(gNB);
// allocated in set_tdd_config_nr()
int nb_slots_to_set = (1<ofdm_symbol_size], 12);
// set UL mask for pucch allocation
- uint32_t rb_mask_ul[14][9] = {0};
+ uint32_t rb_mask_ul[14][MAX_BWP_SIZE] = {0};
if (format == 1) {
for (int s = 0; s < frame_parms->symbols_per_slot; s++) {
if (s >= startingSymbolIndex && s < (startingSymbolIndex + nrofSymbols / 2))
for (int rb = 0; rb < N_RB; rb++) {
- int rb2 = rb + startingPRB;
- rb_mask_ul[s][rb2 >> 5] |= (1 << (rb2 & 31));
+ rb_mask_ul[s][rb + startingPRB] = 1;
}
else if (s >= (startingSymbolIndex + nrofSymbols / 2) && s < startingSymbolIndex + nrofSymbols)
for (int rb = 0; rb < N_RB; rb++) {
- int rb2 = rb + startingPRB_intraSlotHopping;
- rb_mask_ul[s][rb2 >> 5] |= (1 << (rb2 & 31));
+ rb_mask_ul[s][rb + startingPRB_intraSlotHopping] = 1;
}
}
} else {
for (int s = 0; s < frame_parms->symbols_per_slot; s++) {
if (s >= startingSymbolIndex && s < (startingSymbolIndex + nrofSymbols))
for (int rb = 0; rb < N_RB; rb++) {
- int rb2 = rb + startingPRB;
- rb_mask_ul[s][rb2 >> 5] |= (1 << (rb2 & 31));
+ rb_mask_ul[s][rb + startingPRB] = 1;
}
}
}
diff --git a/openair1/SIMULATION/NR_PHY/srssim.c b/openair1/SIMULATION/NR_PHY/srssim.c
index afb4da5a80..0ab34dac47 100644
--- a/openair1/SIMULATION/NR_PHY/srssim.c
+++ b/openair1/SIMULATION/NR_PHY/srssim.c
@@ -435,11 +435,7 @@ int main(int argc, char *argv[])
.beamforming.num_prgs = m_SRS[srs_pdu.config_index],
.beamforming.prg_size = 1};
- gNB->srs->srs_pdu = srs_pdu;
- gNB->srs->active = true;
- gNB->srs->beam_nb = 0;
- gNB->srs->frame = frame;
- gNB->srs->slot = slot;
+ NR_gNB_SRS_job_t srs_job = {.frame = frame, .slot = slot, .srs_pdu = srs_pdu};
// Configure SRS parameters at UE
fapi_nr_ul_config_srs_pdu srs_config_pdu = {.rnti = srs_pdu.rnti,
@@ -467,11 +463,6 @@ int main(int argc, char *argv[])
.beamforming.num_prgs = srs_pdu.beamforming.num_prgs,
.beamforming.prg_size = srs_pdu.beamforming.prg_size};
- nr_phy_data_tx_t phy_data = {0};
- phy_data.srs_vars.active = true;
- phy_data.srs_vars.srs_config_pdu = srs_config_pdu;
- UE->nr_srs_info = malloc16_clear(sizeof(nr_srs_info_t));
-
//----------- UE TX SRS procedures ---------------------
UE_nr_rxtx_proc_t proc;
@@ -492,7 +483,7 @@ int main(int argc, char *argv[])
for (i = 0; i < n_tx; i++)
txd[i] = txdata[i] + slot_offset;
- ue_srs_procedures_nr(UE, &proc, (c16_t **)txF, &phy_data, was_symbol_used);
+ ue_srs_procedures_nr(UE, &proc, (c16_t **)txF, &srs_config_pdu, was_symbol_used);
//------------ TX rotation and OFDM Modulation --------------------------
nr_tx_rotation_and_ofdm_mod(slot, fp, n_tx, txF, txd, link_type_ul, was_symbol_used, false);
@@ -564,16 +555,15 @@ int main(int argc, char *argv[])
//----------- UE RX SRS procedures ---------------------
start_meas(&gNB->rx_srs_stats);
- NR_gNB_SRS_t *srs = &gNB->srs[0];
- uint8_t N_symb_SRS = 1 << srs->srs_pdu.num_symbols;
- uint8_t N_ap = 1 << srs->srs_pdu.num_ant_ports;
- int16_t snr_per_rb[srs->srs_pdu.bwp_size];
+ uint8_t N_symb_SRS = 1 << srs_pdu.num_symbols;
+ uint8_t N_ap = 1 << srs_pdu.num_ant_ports;
+ int16_t snr_per_rb[srs_pdu.bwp_size];
uint16_t timing_advance_offset;
int16_t timing_advance_offset_nsec[n_rx];
int srs_est;
c16_t srs_estimated_channel_freq[n_rx][N_ap][ofdm_symbol_size * N_symb_SRS] __attribute__((aligned(32)));
- c16_t srs_estimated_channel_time[n_rx][N_ap][NR_SRS_IDFT_OVERSAMP_FACTOR * ofdm_symbol_size] __attribute__((aligned(32)));
+ int8_t snr;
nr_srs_rx_procedures(gNB,
frame,
slot,
@@ -581,16 +571,15 @@ int main(int argc, char *argv[])
N_ap,
N_symb_SRS,
ofdm_symbol_size,
- srs,
- gNB->nr_srs_info[0],
+ &srs_job,
&srs_est,
+ &snr,
srs_estimated_channel_freq,
- srs_estimated_channel_time,
snr_per_rb,
&timing_advance_offset,
timing_advance_offset_nsec);
- sum_srs_snr += pow(10, (double)gNB->srs->snr / 10.0);
+ sum_srs_snr += pow(10, (double)snr / 10.0);
int16_t delay_ns = delay * 1e9 / (fp->samples_per_frame * 100);
for (int ant_idx = 0; ant_idx < n_rx; ant_idx++) {
@@ -666,7 +655,6 @@ int main(int argc, char *argv[])
phy_free_nr_gNB(gNB);
free_channel_desc_scm(UE2gNB);
- free_and_zero(UE->nr_srs_info);
free(gNB->RU_list[0]);
free(UE);
diff --git a/openair1/SIMULATION/NR_PHY/ulschsim.c b/openair1/SIMULATION/NR_PHY/ulschsim.c
index f07ad92ca9..c5b8723908 100644
--- a/openair1/SIMULATION/NR_PHY/ulschsim.c
+++ b/openair1/SIMULATION/NR_PHY/ulschsim.c
@@ -414,12 +414,12 @@ int main(int argc, char **argv)
unsigned int TBS = 8424;
unsigned int available_bits;
uint8_t nb_re_dmrs = 6;
- uint8_t length_dmrs = 1;
+ uint8_t length_dmrs = 2;
uint8_t N_PRB_oh;
uint16_t N_RE_prime,code_rate;
unsigned char mod_order;
uint8_t rvidx = 0;
- uint8_t UE_id = 0;
+ int UE_id = 0;
NR_gNB_ULSCH_t *ulsch_gNB = &gNB->ulsch[UE_id];
NR_UL_gNB_HARQ_t *harq_process_gNB = ulsch_gNB->harq_process;
@@ -429,9 +429,6 @@ int main(int argc, char **argv)
nr_phy_data_tx_t phy_data = {0};
NR_UE_ULSCH_t *ulsch_ue = &phy_data.ulsch;
- if ((Nl==4)||(Nl==3))
- nb_re_dmrs = nb_re_dmrs*2;
-
mod_order = nr_get_Qm_ul(Imcs, mcs_table);
code_rate = nr_get_code_rate_ul(Imcs, mcs_table);
available_bits = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, 0, mod_order, Nl);
@@ -445,10 +442,15 @@ int main(int argc, char **argv)
rel15_ul->qam_mod_order = mod_order;
rel15_ul->mcs_index = Imcs;
rel15_ul->pusch_data.rv_index = rvidx;
+ rel15_ul->ul_dmrs_symb_pos = nb_re_dmrs;
+ rel15_ul->dmrs_config_type = pusch_dmrs_type1;
+ rel15_ul->num_dmrs_cdm_grps_no_data = 1;
rel15_ul->nrOfLayers = Nl;
rel15_ul->target_code_rate = code_rate;
rel15_ul->pusch_data.tb_size = TBS>>3;
rel15_ul->maintenance_parms_v3.ldpcBaseGraph = get_BG(TBS, code_rate);
+ int bits = count_bits64_with_mask(rel15_ul->ul_dmrs_symb_pos, rel15_ul->start_symbol_index, rel15_ul->nr_of_symbols);
+ AssertFatal(length_dmrs == bits, "length_dmrs %d bits %d\n", length_dmrs, bits);
///////////////////////////////////////////////////
double modulated_input[16 * 68 * 384]; // [hna] 16 segments, 68*Zc
@@ -558,9 +560,9 @@ int main(int argc, char **argv)
printf("\n");
exit(-1);
#endif
- nr_ulsch_decoding(gNB, frame_parms, frame, subframe, &G, &UE_id, 1);
+ nr_ulsch_decoding(gNB, frame_parms, frame, subframe, &UE_id, 1);
if (harq_process_gNB->processedSegments == harq_process_gNB->C) {
- bool crc_valid = check_crc(harq_process_gNB->b, lenWithCrc(1, (harq_process_gNB->TBS) << 3), crcType(1, (harq_process_gNB->TBS) << 3));
+ bool crc_valid = check_crc(harq_process_gNB->b, lenWithCrc(1, TBS << 3), crcType(1, TBS << 3));
if (!crc_valid) {
n_false_positive++;
}
diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c
index 0d432bfdd0..7e74f26f56 100644
--- a/openair1/SIMULATION/NR_PHY/ulsim.c
+++ b/openair1/SIMULATION/NR_PHY/ulsim.c
@@ -1208,6 +1208,7 @@ int main(int argc, char *argv[])
uint8_t round = 0;
crc_status = 1;
errors_decoding = 0;
+ NR_gNB_PUSCH *pusch_vars = &gNB->pusch_vars[UE_id];
while (round < max_rounds && crc_status && !stop) {
@@ -1307,7 +1308,7 @@ int main(int argc, char *argv[])
srs_pdu->resource_type = NR_SRS_Resource__resourceType_PR_periodic;
srs_pdu->t_srs = 1;
srs_pdu->srs_parameters_v4.srs_bandwidth_size = m_SRS[srs_pdu->config_index];
- srs_pdu->srs_parameters_v4.usage = 1 << NR_SRS_ResourceSet__usage_codebook;
+ srs_pdu->srs_parameters_v4.usage = 1 << NFAPI_NR_SRS_BEAMMANAGEMENT; // to get SNR
srs_pdu->srs_parameters_v4.report_type[0] = 1;
srs_pdu->srs_parameters_v4.iq_representation = 1;
srs_pdu->srs_parameters_v4.prg_size = 1;
@@ -1594,7 +1595,6 @@ int main(int argc, char *argv[])
}
}
- NR_gNB_PUSCH *pusch_vars = &gNB->pusch_vars[UE_id];
if (n_trials == 1 && round == 0) {
__attribute__((unused)) int off = ((nb_rb & 1) == 1) ? 4 : 0;
@@ -1742,13 +1742,20 @@ int main(int argc, char *argv[])
if (!crc_status)
effRate += ((double)TBS) / (double)round;
- sum_pusch_delay += ulsch_gNB->delay.est_delay;
- min_pusch_delay = min(ulsch_gNB->delay.est_delay, min_pusch_delay);
- max_pusch_delay = max(ulsch_gNB->delay.est_delay, max_pusch_delay);
+ sum_pusch_delay += pusch_vars->delay.est_delay;
+ min_pusch_delay = min(pusch_vars->delay.est_delay, min_pusch_delay);
+ max_pusch_delay = max(pusch_vars->delay.est_delay, max_pusch_delay);
delay_pusch_est_count++;
if (do_SRS == 1) {
- sum_srs_snr += gNB->srs->snr;
+ DevAssert(UL_INFO.srs_ind.number_of_pdus == 1); // there must be SRS indication
+ const nfapi_nr_srs_indication_pdu_t *srs_ind = &UL_INFO.srs_ind.pdu_list[0];
+ DevAssert(srs_ind->srs_usage == NFAPI_NR_SRS_BEAMMANAGEMENT);
+ nfapi_nr_srs_beamforming_report_t bf_rep;
+ unpack_nr_srs_beamforming_report((void *)srs_ind->report_tlv.value, srs_ind->report_tlv.length, &bf_rep, sizeof(bf_rep));
+ DevAssert(bf_rep.wide_band_snr != 0xff);
+ int8_t snr = (bf_rep.wide_band_snr >> 1) - 64;
+ sum_srs_snr += snr;
srs_snr_count++;
}
} // trial loop
diff --git a/openair1/SIMULATION/TOOLS/channel_sim.c b/openair1/SIMULATION/TOOLS/channel_sim.c
index 80f933db69..0e6e7404d0 100644
--- a/openair1/SIMULATION/TOOLS/channel_sim.c
+++ b/openair1/SIMULATION/TOOLS/channel_sim.c
@@ -256,9 +256,9 @@ void do_DL_sig(sim_t *sim,
LOG_D(OCM,"[SIM][DL] UE %d : rx_pwr (ADC out) %f dB/RE (%d) for subframe %d, writing to %p, length %d\n",UE_id, 10*log10((double)rx_pwr2),rx_pwr2,subframe,rxdata,lengthN_RB_DL) ,subframe);
#else
- UNUSED_VARIABLE(rx_pwr2);
- UNUSED_VARIABLE(tx_pwr);
- UNUSED_VARIABLE(rx_pwr);
+ UNUSED(rx_pwr2);
+ UNUSED(tx_pwr);
+ UNUSED(rx_pwr);
#endif
} // RU_output_mask
@@ -434,8 +434,8 @@ void do_UL_sig(sim_t *sim, uint16_t subframe, uint8_t abstraction_flag, LTE_DL_F
rx_pwr2 = signal_energy(rxdata[0]+sf_offset_tdd,frame_parms->samples_per_tti)*(double)frame_parms->ofdm_symbol_size/(12.0*frame_parms->N_RB_DL);
LOG_D(OCM,"[SIM][UL] RU %d rx_pwr (ADC out) %f dB (%d) for subframe %d (offset %d) = %p\n",ru_id,10*log10((double)rx_pwr2),rx_pwr2,subframe,sf_offset,rxdata[0]+sf_offset_tdd);
#else
- UNUSED_VARIABLE(tx_pwr);
- UNUSED_VARIABLE(rx_pwr);
- UNUSED_VARIABLE(rx_pwr2);
+ UNUSED(tx_pwr);
+ UNUSED(rx_pwr);
+ UNUSED(rx_pwr2);
#endif
}
diff --git a/openair2/COMMON/f1ap_messages_types.h b/openair2/COMMON/f1ap_messages_types.h
index 37c4a7ee83..2df2c783bf 100644
--- a/openair2/COMMON/f1ap_messages_types.h
+++ b/openair2/COMMON/f1ap_messages_types.h
@@ -161,8 +161,7 @@ typedef struct f1ap_du_register_req_s {
typedef struct f1ap_sib_msg_s {
/// RRC container with system information owned by gNB-CU
- uint8_t *SI_container;
- int SI_container_length;
+ byte_array_t SI_container;
/// SIB block type, e.g. 2 for sibType2
int SI_type;
} f1ap_sib_msg_t;
diff --git a/openair2/COMMON/mac_messages_def.h b/openair2/COMMON/mac_messages_def.h
index cca53d38e6..bed2ad4243 100644
--- a/openair2/COMMON/mac_messages_def.h
+++ b/openair2/COMMON/mac_messages_def.h
@@ -31,6 +31,7 @@ MESSAGE_DEF(RRC_MAC_PCCH_DATA_REQ, MESSAGE_PRIORITY_MED_PLUS, RrcMacPcchDat
MESSAGE_DEF(NR_RRC_MAC_RA_IND, MESSAGE_PRIORITY_MED_PLUS, NRRrcMacRaInd, nr_rrc_mac_ra_ind)
MESSAGE_DEF(NR_RRC_MAC_MSG3_IND, MESSAGE_PRIORITY_MED_PLUS, NRRrcMacMsg3Ind, nr_rrc_mac_msg3_ind)
MESSAGE_DEF(NR_RRC_MAC_INAC_IND, MESSAGE_PRIORITY_MED_PLUS, NRRrcMacInacInd, nr_rrc_mac_inac_ind)
+MESSAGE_DEF(NR_RRC_MAC_VERIFY, MESSAGE_PRIORITY_MED_PLUS, NRRrcMacVerify, nr_rrc_mac_verify)
/* RRC configures DRX context (MAC timers) of a UE */
MESSAGE_DEF(RRC_MAC_DRX_CONFIG_REQ, MESSAGE_PRIORITY_MED, rrc_mac_drx_config_req_t, rrc_mac_drx_config_req)
diff --git a/openair2/COMMON/mac_messages_types.h b/openair2/COMMON/mac_messages_types.h
index c447379640..dc6770948f 100644
--- a/openair2/COMMON/mac_messages_types.h
+++ b/openair2/COMMON/mac_messages_types.h
@@ -41,6 +41,7 @@
#define NR_RRC_MAC_RA_IND(mSGpTR) (mSGpTR)->ittiMsg.nr_rrc_mac_ra_ind
#define NR_RRC_MAC_MSG3_IND(mSGpTR) (mSGpTR)->ittiMsg.nr_rrc_mac_msg3_ind
#define NR_RRC_MAC_INAC_IND(mSGpTR) (mSGpTR)->ittiMsg.nr_rrc_mac_inac_ind
+#define NR_RRC_MAC_VERIFY(mSGpTR) (mSGpTR)->ittiMsg.nr_rrc_mac_verify
#define RRC_MAC_DRX_CONFIG_REQ(mSGpTR) (mSGpTR)->ittiMsg.rrc_mac_drx_config_req
@@ -67,6 +68,10 @@ typedef struct NRRrcMacMsg3Ind_s {
bool prepare_payload;
} NRRrcMacMsg3Ind;
+typedef struct NRRrcMacVerify_s {
+ bool L2_RRC_verification_failed; // not to leave the struct empty
+} NRRrcMacVerify;
+
typedef struct NRRrcMacInacInd_s {
bool inactivity_timer_expired; // not to leave the struct empty
} NRRrcMacInacInd;
diff --git a/openair2/F1AP/lib/f1ap_interface_management.c b/openair2/F1AP/lib/f1ap_interface_management.c
index bb2015b33e..815a9f1b82 100644
--- a/openair2/F1AP/lib/f1ap_interface_management.c
+++ b/openair2/F1AP/lib/f1ap_interface_management.c
@@ -627,10 +627,10 @@ static void encode_cells_to_activate(const served_cells_to_activate_t *cell, F1A
F1AP_GNB_CUSystemInformation_t *gNB_CUSystemInformation =
&cells_to_be_activated_itemExtIEs->extensionValue.choice.GNB_CUSystemInformation;
const f1ap_sib_msg_t *SI_msg = &cell->SI_msg[n];
- if (SI_msg->SI_container != NULL) {
+ if (SI_msg->SI_container.buf != NULL) {
asn1cSequenceAdd(gNB_CUSystemInformation->sibtypetobeupdatedlist.list, F1AP_SibtypetobeupdatedListItem_t, sib_item);
sib_item->sIBtype = SI_msg->SI_type;
- OCTET_STRING_fromBuf(&sib_item->sIBmessage, (const char *)SI_msg->SI_container, SI_msg->SI_container_length);
+ OCTET_STRING_fromBuf(&sib_item->sIBmessage, (const char *)SI_msg->SI_container.buf, SI_msg->SI_container.len);
}
}
}
@@ -670,7 +670,7 @@ static bool decode_cells_to_activate(served_cells_to_activate_t *out, const F1AP
F1AP_SibtypetobeupdatedListItem_t *sib_item = gNB_CUSystemInformation->sibtypetobeupdatedlist.list.array[s];
/* SI container */
f1ap_sib_msg_t *SI_msg = &out->SI_msg[s];
- SI_msg->SI_container = cp_octet_string(&sib_item->sIBmessage, &SI_msg->SI_container_length);
+ SI_msg->SI_container.buf = cp_octet_string(&sib_item->sIBmessage, (int *)&SI_msg->SI_container.len);
/* SIB type */
SI_msg->SI_type = sib_item->sIBtype;
}
@@ -1163,8 +1163,8 @@ bool eq_f1ap_setup_response(const f1ap_setup_resp_t *a, const f1ap_setup_resp_t
for (int j = 0; j < b->cells_to_activate[i].num_SI; j++) {
const f1ap_sib_msg_t *a_SI_msg = &a->cells_to_activate[i].SI_msg[j];
const f1ap_sib_msg_t *b_SI_msg = &b->cells_to_activate[i].SI_msg[j];
- _EQ_CHECK_INT(*a_SI_msg->SI_container, *b_SI_msg->SI_container);
- _EQ_CHECK_INT(a_SI_msg->SI_container_length, b_SI_msg->SI_container_length);
+ if (!eq_byte_array(&a_SI_msg->SI_container, &b_SI_msg->SI_container))
+ return false;
_EQ_CHECK_INT(a_SI_msg->SI_type, b_SI_msg->SI_type);
}
}
@@ -1201,9 +1201,7 @@ f1ap_setup_resp_t cp_f1ap_setup_response(const f1ap_setup_resp_t *msg)
for (int j = 0; j < cp_cell->num_SI; j++) {
f1ap_sib_msg_t *cp_SI_msg = &cp_cell->SI_msg[j];
const f1ap_sib_msg_t *b_SI_msg = &msg_cell->SI_msg[j];
- cp_SI_msg->SI_container_length = b_SI_msg->SI_container_length;
- cp_SI_msg->SI_container = malloc_or_fail(cp_SI_msg->SI_container_length);
- memcpy(cp_SI_msg->SI_container, b_SI_msg->SI_container, b_SI_msg->SI_container_length);
+ cp_SI_msg->SI_container = copy_byte_array(b_SI_msg->SI_container);
cp_SI_msg->SI_type = b_SI_msg->SI_type;
}
}
@@ -1221,8 +1219,7 @@ void free_f1ap_setup_response(const f1ap_setup_resp_t *msg)
free(msg->gNB_CU_name);
for (int i = 0; i < msg->num_cells_to_activate; i++)
for (int j = 0; j < msg->cells_to_activate[i].num_SI; j++)
- if (msg->cells_to_activate[i].SI_msg[j].SI_container_length > 0)
- free(msg->cells_to_activate[i].SI_msg[j].SI_container);
+ free_byte_array(msg->cells_to_activate[i].SI_msg[j].SI_container);
free(msg->cells_to_activate);
}
@@ -1798,7 +1795,7 @@ void free_f1ap_cu_configuration_update(const f1ap_gnb_cu_configuration_update_t
{
for (int i = 0; i < msg->num_cells_to_activate; i++)
for (int j = 0; j < msg->cells_to_activate[i].num_SI; j++)
- free(msg->cells_to_activate[i].SI_msg[j].SI_container);
+ free_byte_array(msg->cells_to_activate[i].SI_msg[j].SI_container);
free(msg->cells_to_activate);
}
@@ -1819,8 +1816,8 @@ bool eq_f1ap_cu_configuration_update(const f1ap_gnb_cu_configuration_update_t *a
for (int s = 0; s < a->cells_to_activate[i].num_SI; s++) {
f1ap_sib_msg_t *a_sib_msg = &a->cells_to_activate[i].SI_msg[s];
f1ap_sib_msg_t *b_sib_msg = &b->cells_to_activate[i].SI_msg[s];
- _EQ_CHECK_INT(*a_sib_msg->SI_container, *b_sib_msg->SI_container);
- _EQ_CHECK_INT(a_sib_msg->SI_container_length, b_sib_msg->SI_container_length);
+ if (!eq_byte_array(&a_sib_msg->SI_container, &b_sib_msg->SI_container))
+ return false;
_EQ_CHECK_INT(a_sib_msg->SI_type, b_sib_msg->SI_type);
}
}
@@ -1842,9 +1839,7 @@ f1ap_gnb_cu_configuration_update_t cp_f1ap_cu_configuration_update(const f1ap_gn
for (int s = 0; s < cp.cells_to_activate[i].num_SI; s++) {
cp.cells_to_activate[i].SI_msg[s] = msg->cells_to_activate[i].SI_msg[s];
f1ap_sib_msg_t *SI_msg = &cp.cells_to_activate[i].SI_msg[s];
- SI_msg->SI_container = calloc_or_fail(SI_msg->SI_container_length, sizeof(*SI_msg->SI_container));
- for (int j = 0; j < SI_msg->SI_container_length; j++)
- SI_msg->SI_container[j] = msg->cells_to_activate[i].SI_msg[s].SI_container[j];
+ SI_msg->SI_container = copy_byte_array(msg->cells_to_activate[i].SI_msg[s].SI_container);
}
}
return cp;
@@ -2153,8 +2148,8 @@ bool eq_f1ap_du_configuration_update_acknowledge(const f1ap_gnb_du_configuration
return false;
_EQ_CHECK_INT(a->cells_to_activate[i].num_SI, b->cells_to_activate[i].num_SI);
for (int s = 0; s < a->cells_to_activate[i].num_SI; s++) {
- _EQ_CHECK_INT(*a->cells_to_activate[i].SI_msg[s].SI_container, *b->cells_to_activate[i].SI_msg[s].SI_container);
- _EQ_CHECK_INT(a->cells_to_activate[i].SI_msg[s].SI_container_length, b->cells_to_activate[i].SI_msg[s].SI_container_length);
+ if (!eq_byte_array(&a->cells_to_activate[i].SI_msg[s].SI_container, &b->cells_to_activate[i].SI_msg[s].SI_container))
+ return false;
_EQ_CHECK_INT(a->cells_to_activate[i].SI_msg[s].SI_type, b->cells_to_activate[i].SI_msg[s].SI_type);
}
}
@@ -2180,9 +2175,7 @@ f1ap_gnb_du_configuration_update_acknowledge_t cp_f1ap_du_configuration_update_a
f1ap_sib_msg_t *cp_sib = &cp.cells_to_activate[i].SI_msg[s];
const f1ap_sib_msg_t *msg_sib = &msg->cells_to_activate[i].SI_msg[s];
cp_sib->SI_type = msg_sib->SI_type;
- cp_sib->SI_container_length = msg_sib->SI_container_length;
- cp_sib->SI_container = calloc_or_fail(cp_sib->SI_container_length, sizeof(*cp_sib->SI_container));
- memcpy(cp_sib->SI_container, msg_sib->SI_container, cp_sib->SI_container_length);
+ cp_sib->SI_container = copy_byte_array(msg_sib->SI_container);
}
}
return cp;
@@ -2196,9 +2189,7 @@ void free_f1ap_du_configuration_update_acknowledge(const f1ap_gnb_du_configurati
// SI_container
for (int i = 0; i < msg->num_cells_to_activate; i++) {
for (int j = 0; j < msg->cells_to_activate[i].num_SI; j++) {
- if (msg->cells_to_activate[i].SI_msg[j].SI_container) {
- free(msg->cells_to_activate[i].SI_msg[j].SI_container);
- }
+ free_byte_array(msg->cells_to_activate[i].SI_msg[j].SI_container);
}
}
free(msg->cells_to_activate);
diff --git a/openair2/F1AP/tests/f1ap_lib_test.c b/openair2/F1AP/tests/f1ap_lib_test.c
index 8f315ff8ae..1140e3c39b 100644
--- a/openair2/F1AP/tests/f1ap_lib_test.c
+++ b/openair2/F1AP/tests/f1ap_lib_test.c
@@ -313,9 +313,9 @@ static void test_f1ap_setup_response(void)
int SI_container_length = strlen(s) + 1;
orig.cells_to_activate[0].num_SI = 1;
f1ap_sib_msg_t *SI_msg = &orig.cells_to_activate[0].SI_msg[0];
- SI_msg->SI_container = malloc_or_fail(SI_container_length);
- memcpy(SI_msg->SI_container, (uint8_t *)s, SI_container_length);
- SI_msg->SI_container_length = SI_container_length;
+ SI_msg->SI_container.buf = malloc_or_fail(SI_container_length);
+ memcpy(SI_msg->SI_container.buf, s, SI_container_length);
+ SI_msg->SI_container.len = SI_container_length;
SI_msg->SI_type = 7;
}
F1AP_F1AP_PDU_t *f1enc = encode_f1ap_setup_response(&orig);
@@ -609,10 +609,10 @@ static void test_f1ap_du_configuration_update_acknowledge(void)
orig.cells_to_activate[0].plmn.mnc_digit_length = 2;
orig.cells_to_activate[0].num_SI = 1;
orig.cells_to_activate[0].SI_msg[0].SI_type = 7;
- orig.cells_to_activate[0].SI_msg[0].SI_container_length = 10;
- orig.cells_to_activate[0].SI_msg[0].SI_container = malloc(sizeof(uint8_t) * 10);
- for (int i = 0; i < orig.cells_to_activate[0].SI_msg[0].SI_container_length; i++) {
- orig.cells_to_activate[0].SI_msg[0].SI_container[i] = i;
+ orig.cells_to_activate[0].SI_msg[0].SI_container.len = 10;
+ orig.cells_to_activate[0].SI_msg[0].SI_container.buf = malloc(sizeof(uint8_t) * 10);
+ for (int i = 0; i < (int)orig.cells_to_activate[0].SI_msg[0].SI_container.len; i++) {
+ orig.cells_to_activate[0].SI_msg[0].SI_container.buf[i] = i;
}
// ASN.1 enc/dec
F1AP_F1AP_PDU_t *f1enc = encode_f1ap_du_configuration_update_acknowledge(&orig);
@@ -655,8 +655,8 @@ static void test_f1ap_cu_configuration_update(void)
orig.cells_to_activate[0].plmn.mnc_digit_length = 2;
orig.cells_to_activate[0].num_SI = 1;
orig.cells_to_activate[0].SI_msg[0].SI_type = 7;
- orig.cells_to_activate[0].SI_msg[0].SI_container_length = 10;
- orig.cells_to_activate[0].SI_msg[0].SI_container = malloc(sizeof(uint8_t) * 10);
+ orig.cells_to_activate[0].SI_msg[0].SI_container.len = 10;
+ orig.cells_to_activate[0].SI_msg[0].SI_container.buf = malloc(sizeof(uint8_t) * 10);
F1AP_F1AP_PDU_t *f1enc = encode_f1ap_cu_configuration_update(&orig);
F1AP_F1AP_PDU_t *f1dec = f1ap_encode_decode(f1enc);
f1ap_msg_free(f1enc);
diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c
index a73a77b0ee..856078e6f7 100644
--- a/openair2/GNB_APP/gnb_config.c
+++ b/openair2/GNB_APP/gnb_config.c
@@ -1083,7 +1083,7 @@ f1ap_gnb_du_system_info_t *get_sys_info(NR_BCCH_BCH_Message_t *mib, const NR_BCC
nr_SIBs_t *si = (nr_SIBs_t *)seq_arr_at(du_SIBs, i);
// other SIB in gNB-DU System Information not implemented yet
// only DU SIB not included in this message is SIB19
- AssertFatal(si->SIB_type == 19, "Cannot handle SIB%d in gNB-DU System Information\n", si->SIB_type);
+ AssertFatal(si->SIB_type == NR_SIB_19, "Cannot handle SIB%d in gNB-DU System Information\n", (int)si->SIB_type);
}
}
return sys_info;
@@ -1243,7 +1243,7 @@ static seq_arr_t *fill_du_sibs(paramdef_t *GNBparamarray)
int sib_value = GNBparamarray[GNB_DU_SIBS_IDX].iptr[i];
// SIB10, SIB12, SIB13, SIB14, SIB15, SIB17, SIB18, SIB19 and SIB20 are generated by the DU
// all the rest in the DU
- AssertFatal((sib_value > 9 && sib_value < 21) && sib_value != 11 && sib_value != 16,
+ AssertFatal((sib_value > NR_SIB_9 && sib_value < NR_SIB_21) && sib_value != NR_SIB_11 && sib_value != NR_SIB_16,
"SIB%d is not a DU SIB, to be configured in DU section\n",
sib_value);
nr_SIBs_t *du_sib = calloc_or_fail(1, sizeof(nr_SIBs_t));
@@ -2012,94 +2012,209 @@ static nr_neighbour_cell_t *get_neighbour_by_pci(seq_arr_t *neighbour_cells, int
return NULL;
}
-static void fill_neighbour_cell_configuration(uint8_t gnb_idx, gNB_RRC_INST *rrc)
+/** @brief Parse gNB-level inter-frequency list (frequency_list) into a shared array.
+ * This parses gNBs.[gnb_idx].frequency_list once and validates per-frequency SIB4
+ * parameters. The resulting list can then be reused for all serving cells.
+ * @param[out] inter_freqs Sequence array of nr_inter_freq_cfg_t to populate
+ * @param[in] gnb_idx gNB index */
+static bool eq_inter_freq_arfcn_scs(const void *vval, const void *vit)
{
- char gnbpath[MAX_OPTNAME_SIZE + 8];
- snprintf(gnbpath, sizeof(gnbpath), "%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, gnb_idx);
+ const nr_inter_freq_cfg_t *key = (const nr_inter_freq_cfg_t *)vval;
+ const nr_inter_freq_cfg_t *cur = (const nr_inter_freq_cfg_t *)vit;
+ return key->arfcn == cur->arfcn && key->scs == cur->scs;
+}
- GET_PARAMS_LIST(neighbour_list_param_list,
- neighbour_list_params,
- GNB_NEIGHBOUR_LIST_PARAM_LIST,
- GNB_CONFIG_STRING_NEIGHBOUR_LIST,
- gnbpath);
-
- if (neighbour_list_param_list.numelt < 1)
- return;
-
- rrc->neighbour_cell_configuration = malloc(sizeof(seq_arr_t));
- seq_arr_init(rrc->neighbour_cell_configuration, sizeof(neighbour_cell_configuration_t));
-
- for (int elm = 0; elm < neighbour_list_param_list.numelt; ++elm) {
- neighbour_cell_configuration_t cell = {0};
- cell.nr_cell_id = (uint64_t)*neighbour_list_param_list.paramarray[elm][0].u64ptr;
-
- char neighbourpath[MAX_OPTNAME_SIZE + 8];
- snprintf(neighbourpath, sizeof(neighbourpath), "%s.[%i].%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, gnb_idx, GNB_CONFIG_STRING_NEIGHBOUR_LIST, elm);
- GET_PARAMS_LIST(NeighbourCellParamList,
- NeighbourCellParams,
- GNBNEIGHBOURCELLPARAMS_DESC,
- GNB_CONFIG_STRING_NEIGHBOUR_CELL_LIST,
- neighbourpath);
- LOG_I(GNB_APP, "Cell %ld has %d neighbours\n", cell.nr_cell_id, NeighbourCellParamList.numelt);
- if (NeighbourCellParamList.numelt < 1)
- continue;
-
- cell.neighbour_cells = malloc_or_fail(sizeof(seq_arr_t));
- seq_arr_init(cell.neighbour_cells, sizeof(nr_neighbour_cell_t));
- for (int l = 0; l < NeighbourCellParamList.numelt; ++l) {
- nr_neighbour_cell_t n = {0};
- n.gNB_ID = *(NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_GNB_ID_IDX].uptr);
- n.nrcell_id = (uint64_t) * (NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_NR_CELLID_IDX].u64ptr);
- n.physicalCellId = *NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_PHYSICAL_ID_IDX].uptr;
- n.subcarrierSpacing = *NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_SCS_IDX].uptr;
- n.band = *NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_BAND_IDX].uptr;
- n.absoluteFrequencySSB = *NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_ABS_FREQ_SSB_IDX].i64ptr;
- n.tac = *NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_TAC_IDX].uptr;
-
- char neighbour_plmn_path[CONFIG_MAXOPTLENGTH];
- snprintf(neighbour_plmn_path,
- sizeof(neighbour_plmn_path),
- "%s.%s.[%i].%s",
- neighbourpath,
- GNB_CONFIG_STRING_NEIGHBOUR_CELL_LIST,
- l,
- GNB_CONFIG_STRING_NEIGHBOUR_PLMN);
- GET_PARAMS(NeighbourPlmn, GNBPLMNPARAMS_DESC, neighbour_plmn_path);
-
- n.plmn.mcc = *NeighbourPlmn[GNB_MOBILE_COUNTRY_CODE_IDX].uptr;
- n.plmn.mnc = *NeighbourPlmn[GNB_MOBILE_NETWORK_CODE_IDX].uptr;
- n.plmn.mnc_digit_length = *NeighbourPlmn[GNB_MNC_DIGIT_LENGTH].uptr;
- if (get_neighbour_by_pci(cell.neighbour_cells, n.physicalCellId) != NULL) {
- LOG_E(GNB_APP,
- "Cell %ld: duplicate PCI %d in neighbour list (nrcell_id %ld)\n",
- cell.nr_cell_id,
- n.physicalCellId,
- n.nrcell_id);
- AssertFatal(false, "PCI must be unique within a cell's neighbour list\n");
- }
- seq_arr_push_back(cell.neighbour_cells, &n, sizeof(n));
- LOG_I(GNB_APP,
- " [%d] neighbor ID %d cellId %ld PCI %d SCS %d SSB ARFCN %u TAC %u PLMN %03u.%0*u\n",
- l,
- n.gNB_ID,
- n.nrcell_id,
- n.physicalCellId,
- n.subcarrierSpacing,
- n.absoluteFrequencySSB,
- n.tac,
- n.plmn.mcc,
- n.plmn.mnc_digit_length,
- n.plmn.mnc);
- }
- seq_arr_push_back(rrc->neighbour_cell_configuration, &cell, sizeof(cell));
+/** @brief Insert an inter-frequency config if (ARFCN,SCS) is unique in the list.
+ * Fails fast if a duplicate is found.
+ * @param[in,out] inter_freqs Existing inter-frequency list
+ * @param[in] f Candidate entry to insert (by value)
+ * @param[in] gnb_idx gNB index for logging
+ */
+static void add_inter_freq(seq_arr_t *inter_freqs, const nr_inter_freq_cfg_t *f, uint8_t gnb_idx)
+{
+ const nr_inter_freq_cfg_t key = {.arfcn = f->arfcn, .scs = f->scs};
+ elm_arr_t dup = find_if(inter_freqs, (void *)&key, eq_inter_freq_arfcn_scs);
+ if (dup.found) {
+ AssertFatal(false, "gNB %d: duplicate inter-freq carrier ARFCN %d, SCS %d in frequency_list\n", gnb_idx, f->arfcn, f->scs);
}
+
+ seq_arr_push_back(inter_freqs, (void *)f, sizeof(*f));
+}
+
+static void parse_inter_freq_list(seq_arr_t *inter_freqs, const uint8_t gnb_idx)
+{
+ seq_arr_init(inter_freqs, sizeof(nr_inter_freq_cfg_t));
+
+ char freq_path[MAX_OPTNAME_SIZE + 8];
+ snprintf(freq_path, sizeof(freq_path), "%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, gnb_idx);
+ GET_PARAMS_LIST(freq_list, freq_params, GNBFREQUENCYPARAMS_DESC, GNB_CONFIG_STRING_FREQUENCY_LIST, freq_path);
+
+ for (int i = 0; i < freq_list.numelt; ++i) {
+ const paramdef_t *freq_item = freq_list.paramarray[i];
+ nr_inter_freq_cfg_t f = {0};
+ f.arfcn = *gpd(freq_item, sizeofArray(freq_params), GNB_CONFIG_STRING_FREQUENCY_ABS_FREQ_SSB)->i64ptr;
+ f.scs = *gpd(freq_item, sizeofArray(freq_params), GNB_CONFIG_STRING_FREQUENCY_SCS)->uptr;
+
+ char cfg_path[MAX_OPTNAME_SIZE + 16];
+ snprintf(cfg_path,
+ sizeof(cfg_path),
+ "%s.[%i].%s.[%i]",
+ GNB_CONFIG_STRING_GNB_LIST,
+ gnb_idx,
+ GNB_CONFIG_STRING_FREQUENCY_LIST,
+ i);
+ GET_PARAMS(freq_cfg, GNBFREQUENCYCONFIGPARAMS_DESC, cfg_path);
+
+ nr_neighbour_cell_sib4_freq_t *p = &f.freq_cfg;
+
+ p->cellReselectionPriority = *freq_cfg[GNB_CONFIG_FREQUENCY_CELL_RESEL_PRIO_IDX].iptr;
+ p->threshX_HighP = *freq_cfg[GNB_CONFIG_FREQUENCY_THRESH_X_HIGH_P_IDX].iptr;
+ p->threshX_LowP = *freq_cfg[GNB_CONFIG_FREQUENCY_THRESH_X_LOW_P_IDX].iptr;
+ p->threshX_HighQ = *freq_cfg[GNB_CONFIG_FREQUENCY_THRESH_X_HIGH_Q_IDX].iptr;
+ p->threshX_LowQ = *freq_cfg[GNB_CONFIG_FREQUENCY_THRESH_X_LOW_Q_IDX].iptr;
+ p->q_OffsetFreq = *freq_cfg[GNB_CONFIG_FREQUENCY_Q_OFFSET_FREQ_IDX].iptr;
+ f.q_RxLevMin = *freq_cfg[GNB_CONFIG_FREQUENCY_Q_RXLEVMIN_IDX].iptr;
+ f.t_ReselectionNR = *freq_cfg[GNB_CONFIG_FREQUENCY_T_RESEL_NR_IDX].uptr;
+
+ /* Add inter-frequency configuration to the list. */
+ add_inter_freq(inter_freqs, &f, gnb_idx);
+
+ LOG_I(GNB_APP,
+ "gNB %d: SIB4 inter-freq ARFCN %d, SCS %d, prio=%d, ThreshX_HighP=%d, ThreshX_LowP=%d, ThreshX_HighQ=%d, "
+ "ThreshX_LowQ=%d, q_OffsetFreq=%d\n",
+ gnb_idx,
+ f.arfcn,
+ f.scs,
+ f.freq_cfg.cellReselectionPriority,
+ f.freq_cfg.threshX_HighP,
+ f.freq_cfg.threshX_LowP,
+ f.freq_cfg.threshX_HighQ,
+ f.freq_cfg.threshX_LowQ,
+ f.freq_cfg.q_OffsetFreq);
+ }
+}
+
+static void set_sib3_offsets(nr_neighbour_cell_t *n, const paramdef_t *cell_params, int n_cell_params)
+{
+ nr_neighbour_cell_neighbor_offset_t *sib3_off = &n->sib3.offset;
+
+ /* SIB3 per-neighbour offsets */
+ sib3_off->q_OffsetCell = *gpd(cell_params, n_cell_params, GNB_CONFIG_STRING_NEIGHBOUR_CELL_Q_OFFSET_CELL)->iptr;
+ sib3_off->q_RxLevMinOffsetCell = *gpd(cell_params, n_cell_params, GNB_CONFIG_STRING_NEIGHBOUR_CELL_Q_RXLEVMIN_OFFSET_CELL)->iptr;
+ sib3_off->q_QualMinOffsetCell = *gpd(cell_params, n_cell_params, GNB_CONFIG_STRING_NEIGHBOUR_CELL_Q_QUALMIN_OFFSET_CELL)->iptr;
+}
+
+static void set_sib4_offsets(nr_neighbour_cell_t *n, const paramdef_t *cell_params, int n_cell_params)
+{
+ nr_neighbour_cell_neighbor_offset_t *sib4_off = &n->sib4.offset;
+
+ /* SIB4 per-neighbour offsets */
+ sib4_off->q_OffsetCell = *gpd(cell_params, n_cell_params, GNB_CONFIG_STRING_NEIGHBOUR_CELL_Q_OFFSET_CELL)->iptr;
+ sib4_off->q_RxLevMinOffsetCell = *gpd(cell_params, n_cell_params, GNB_CONFIG_STRING_NEIGHBOUR_CELL_Q_RXLEVMIN_OFFSET_CELL)->iptr;
+ sib4_off->q_QualMinOffsetCell = *gpd(cell_params, n_cell_params, GNB_CONFIG_STRING_NEIGHBOUR_CELL_Q_QUALMIN_OFFSET_CELL)->iptr;
+}
+
+/** @brief Parse and add neighbour cells for a given cell configuration
+ * @param[in,out] cell Neighbour cell configuration to populate
+ * @param[in] list Parameter list describing neighbour cells
+ * @param[in] n_path Base path for neighbour configuration in the config tree
+ * @param[in] n_cell_params Number of neighbour-cell parameters */
+static void parse_neighbour_cells_list(neighbour_cell_configuration_t *cell,
+ const paramlist_def_t *list,
+ const char *n_path,
+ int n_cell_params)
+{
+ seq_arr_init(&cell->neighbour_cells, sizeof(nr_neighbour_cell_t));
+
+ /* Parse each neighbour cell in the list */
+ for (int l = 0; l < list->numelt; ++l) {
+ const paramdef_t *cell_params = list->paramarray[l];
+ nr_neighbour_cell_t n = {
+ .gNB_ID = *gpd(cell_params, n_cell_params, GNB_CONFIG_STRING_GNB_ID)->uptr,
+ .nrcell_id = *gpd(cell_params, n_cell_params, GNB_CONFIG_STRING_NRCELLID)->u64ptr,
+ .physicalCellId = *gpd(cell_params, n_cell_params, GNB_CONFIG_STRING_NEIGHBOUR_CELL_PHYSICAL_ID)->uptr,
+ .subcarrierSpacing = *gpd(cell_params, n_cell_params, GNB_CONFIG_STRING_NEIGHBOUR_CELL_SCS)->uptr,
+ .band = *gpd(cell_params, n_cell_params, GNB_CONFIG_STRING_NEIGHBOUR_CELL_BAND)->uptr,
+ .absoluteFrequencySSB = *gpd(cell_params, n_cell_params, GNB_CONFIG_STRING_NEIGHBOUR_CELL_ABS_FREQ_SSB)->i64ptr,
+ .tac = *gpd(cell_params, n_cell_params, GNB_CONFIG_STRING_NEIGHBOUR_TRACKING_ARE_CODE)->uptr};
+
+ set_sib3_offsets(&n, cell_params, n_cell_params);
+ set_sib4_offsets(&n, cell_params, n_cell_params);
+ /* SIB4 per-frequency reselection parameters (q_OffsetFreq, thresholds, priority)
+ * are populated in parse_inter_freq_list() per-frequency, not per neighbour here. */
+
+ char p[CONFIG_MAXOPTLENGTH]; // plmn path
+ snprintf(p, sizeof(p), "%s.%s.[%i].%s", n_path, GNB_CONFIG_STRING_NEIGHBOUR_CELL_LIST, l, GNB_CONFIG_STRING_NEIGHBOUR_PLMN);
+ GET_PARAMS(NeighbourPlmn, GNBPLMNPARAMS_DESC, p);
+ n.plmn = extract_plmn_from_params(NeighbourPlmn, sizeofArray(NeighbourPlmn));
+
+ LOG_I(GNB_APP,
+ "Neighbour[%d]: cellId %ld, PLMN %03u.%0*u, gNB %d, PCI %d, SCS %d, SSB ARFCN %u, TAC %u\n",
+ l,
+ n.nrcell_id,
+ n.plmn.mcc,
+ n.plmn.mnc_digit_length,
+ n.plmn.mnc,
+ n.gNB_ID,
+ n.physicalCellId,
+ n.subcarrierSpacing,
+ n.absoluteFrequencySSB,
+ n.tac);
+
+ /* Check for duplicate PCI in the neighbour list */
+ if (get_neighbour_by_pci(&cell->neighbour_cells, n.physicalCellId) != NULL) {
+ LOG_E(GNB_APP, "Cell %ld: duplicate PCI %d in neighbour list (NCI=%ld)\n", cell->nr_cell_id, n.physicalCellId, n.nrcell_id);
+ AssertFatal(false, "PCI must be unique within a cell's neighbour list\n");
+ }
+
+ seq_arr_push_back(&cell->neighbour_cells, &n, sizeof(n));
+ }
+}
+
+/** @brief Sort neighbour cell configuration by cell ID
+ * @param[in] rrc Pointer to RRC instance */
+static void sort_neighbour_configuration(gNB_RRC_INST *rrc)
+{
void *base = seq_arr_front(rrc->neighbour_cell_configuration);
size_t nmemb = seq_arr_size(rrc->neighbour_cell_configuration);
size_t element_size = sizeof(neighbour_cell_configuration_t);
-
qsort(base, nmemb, element_size, sort_neighbour_cell_config_by_cell_id);
}
+/** @brief Fill neighbour cell configuration from config file
+ * @param[in] gnb_idx gNB index
+ * @param[in,out] rrc Pointer to RRC instance */
+static void fill_neighbour_cell_configuration(const uint8_t gnb_idx, gNB_RRC_INST *rrc)
+{
+ char path[MAX_OPTNAME_SIZE + 8];
+ snprintf(path, sizeof(path), "%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, gnb_idx);
+ GET_PARAMS_LIST(nlist, nparams, GNB_NEIGHBOUR_LIST_PARAM_LIST, GNB_CONFIG_STRING_NEIGHBOUR_LIST, path);
+
+ LOG_I(GNB_APP, "gNB %d: neighbour_list has %d serving cell(s)\n", gnb_idx, nlist.numelt);
+ if (nlist.numelt < 1)
+ return;
+
+ /* Parse gNB-level inter-frequency configuration once and reuse it for all cells. */
+ parse_inter_freq_list(&rrc->inter_freqs, gnb_idx);
+
+ rrc->neighbour_cell_configuration = malloc_or_fail(sizeof(seq_arr_t));
+ seq_arr_init(rrc->neighbour_cell_configuration, sizeof(neighbour_cell_configuration_t));
+
+ for (int elm = 0; elm < nlist.numelt; ++elm) {
+ neighbour_cell_configuration_t cell = {0};
+ cell.nr_cell_id = *gpd(nlist.paramarray[elm], sizeofArray(nparams), GNB_CONFIG_STRING_NRCELLID)->u64ptr;
+ snprintf(path, sizeof(path), "%s.[%i].%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, gnb_idx, GNB_CONFIG_STRING_NEIGHBOUR_LIST, elm);
+ GET_PARAMS_LIST(ncell_list, ncell_params, GNBNEIGHBOURCELLPARAMS_DESC, GNB_CONFIG_STRING_NEIGHBOUR_CELL_LIST, path);
+ LOG_I(GNB_APP, "Cell %ld has %d neighbours configured\n", cell.nr_cell_id, ncell_list.numelt);
+ if (ncell_list.numelt < 1)
+ continue;
+ parse_neighbour_cells_list(&cell, &ncell_list, path, sizeofArray(ncell_params));
+ seq_arr_push_back(rrc->neighbour_cell_configuration, &cell, sizeof(cell));
+ }
+
+ sort_neighbour_configuration(rrc);
+}
+
static void fill_measurement_configuration(uint8_t gnb_idx, gNB_RRC_INST *rrc)
{
char measurement_path[MAX_OPTNAME_SIZE + 8];
@@ -2166,6 +2281,64 @@ static void fill_measurement_configuration(uint8_t gnb_idx, gNB_RRC_INST *rrc)
}
}
+/** @brief Parse and populate SIB2 configuration from config file
+ * @param[in] gnb_idx gNB index
+ * @return populated SIB2 configuration */
+static sib2_config_t fill_sib2_configuration(uint8_t gnb_idx)
+{
+ sib2_config_t sib2 = {0};
+
+ char sib2_path[MAX_OPTNAME_SIZE * 2 + 8];
+ snprintf(sib2_path, sizeof(sib2_path), "%s.[%i].%s", GNB_CONFIG_STRING_GNB_LIST, gnb_idx, GNB_CONFIG_STRING_SIB2_CONFIG);
+
+ GET_PARAMS(SIB2Params, GNBSIB2PARAMS_DESC, sib2_path);
+ const int n_sib2_params = sizeofArray(SIB2Params);
+
+ cell_reselection_info_common_t *common = &sib2.cell_reselection_info_common;
+ common->q_Hyst = *gpd(SIB2Params, n_sib2_params, GNB_CONFIG_STRING_SIB2_Q_HYST)->iptr;
+ /* speedStateReselectionPars */
+ common->speedStateReselectionPars = calloc_or_fail(1, sizeof(*common->speedStateReselectionPars));
+ sib2_speed_state_reselection_pars_t *speed = common->speedStateReselectionPars;
+
+ /* Cell reselection serving frequency information */
+ cell_reselection_serving_freq_info_t *serv = &sib2.cell_reselection_serving_freq_info;
+ serv->cellReselectionPriority = *gpd(SIB2Params, n_sib2_params, GNB_CONFIG_STRING_SIB2_CELLRESEL_PRIORITY)->iptr;
+ serv->threshServingLowP = *gpd(SIB2Params, n_sib2_params, GNB_CONFIG_STRING_SIB2_THRESH_SERVING_LOW_P)->iptr;
+ serv->threshServingLowQ = *gpd(SIB2Params, n_sib2_params, GNB_CONFIG_STRING_SIB2_THRESH_SERVING_LOW_Q)->iptr;
+ serv->s_NonIntraSearchP = *gpd(SIB2Params, n_sib2_params, GNB_CONFIG_STRING_SIB2_S_NONINTRASEARCH_P)->iptr;
+ serv->s_NonIntraSearchQ = *gpd(SIB2Params, n_sib2_params, GNB_CONFIG_STRING_SIB2_S_NONINTRASEARCH_Q)->iptr;
+
+ /* Intra-frequency cell reselection parameters */
+ intra_freq_cell_reselection_info_t *intra = &sib2.intra_freq_cell_reselection_info;
+ intra->q_RxLevMin = *gpd(SIB2Params, n_sib2_params, GNB_CONFIG_STRING_SIB2_Q_RXLEVMIN)->iptr;
+ intra->q_QualMin = *gpd(SIB2Params, n_sib2_params, GNB_CONFIG_STRING_SIB2_Q_QUALMIN)->iptr;
+ intra->s_IntraSearchP = *gpd(SIB2Params, n_sib2_params, GNB_CONFIG_STRING_SIB2_S_INTRASEARCH_P)->iptr;
+ intra->s_IntraSearchQ = *gpd(SIB2Params, n_sib2_params, GNB_CONFIG_STRING_SIB2_S_INTRASEARCH_Q)->iptr;
+ intra->t_ReselectionNR = *gpd(SIB2Params, n_sib2_params, GNB_CONFIG_STRING_SIB2_T_RESEL_NR)->iptr;
+
+ /* deriveSSB_IndexFromCell (0/1) */
+ int derive_ssb = *gpd(SIB2Params, n_sib2_params, GNB_CONFIG_STRING_SIB2_DERIVE_SSB_IDX)->iptr;
+ sib2.deriveSSB_IndexFromCell = (derive_ssb != 0);
+
+ /* Speed-state pars: optional parameters are omitted from the config file (default applied), not set to -1. */
+ speed->t_Evaluation = *gpd(SIB2Params, n_sib2_params, GNB_CONFIG_STRING_SIB2_SPEED_T_EVAL)->iptr;
+ speed->t_HystNormal = *gpd(SIB2Params, n_sib2_params, GNB_CONFIG_STRING_SIB2_SPEED_T_HYST_NORMAL)->iptr;
+ speed->n_CellChangeMedium = *gpd(SIB2Params, n_sib2_params, GNB_CONFIG_STRING_SIB2_SPEED_N_CELL_CHG_MED)->iptr;
+ speed->n_CellChangeHigh = *gpd(SIB2Params, n_sib2_params, GNB_CONFIG_STRING_SIB2_SPEED_N_CELL_CHG_HIGH)->iptr;
+ speed->sf_Medium = *gpd(SIB2Params, n_sib2_params, GNB_CONFIG_STRING_SIB2_SPEED_SF_MEDIUM)->iptr;
+ speed->sf_High = *gpd(SIB2Params, n_sib2_params, GNB_CONFIG_STRING_SIB2_SPEED_SF_HIGH)->iptr;
+
+ LOG_I(GNB_APP,
+ "gNB %d SIB2 config: q_Hyst=%d dB, cellReselPrio=%d, q_RxLevMin=%d dBm, t_ReselectionNR=%d s\n",
+ gnb_idx,
+ common->q_Hyst,
+ serv->cellReselectionPriority,
+ intra->q_RxLevMin,
+ intra->t_ReselectionNR);
+
+ return sib2;
+}
+
/**
* @brief Allocates and initializes RRC instances
* Currently assuming 1 instance
@@ -2265,6 +2438,9 @@ gNB_RRC_INST *RCconfig_NRRRC()
}//
}//End for (k=0; k sib2_config = fill_sib2_configuration(i);
}//End if (num_gnbs>0)
if (!NODE_IS_DU(rrc->node_type))
diff --git a/openair2/GNB_APP/gnb_config_common.c b/openair2/GNB_APP/gnb_config_common.c
index 395af98750..aca2457d08 100644
--- a/openair2/GNB_APP/gnb_config_common.c
+++ b/openair2/GNB_APP/gnb_config_common.c
@@ -31,19 +31,28 @@ uint16_t set_snssai_config(nssai_t *nssai, const int max_num_ssi, uint8_t k, uin
return num_ssi;
}
+/** @brief Extract PLMN from parameter array
+ * @param[in] params Parameter array containing PLMN fields
+ * @return plmn_id_t structure filled from parameters */
+plmn_id_t extract_plmn_from_params(const paramdef_t *params, int n_params)
+{
+ plmn_id_t plmn = {.mcc = *gpd(params, n_params, GNB_CONFIG_STRING_MOBILE_COUNTRY_CODE)->uptr,
+ .mnc = *gpd(params, n_params, GNB_CONFIG_STRING_MOBILE_NETWORK_CODE)->uptr,
+ .mnc_digit_length = *gpd(params, n_params, GNB_CONFIG_STRING_MNC_DIGIT_LENGTH)->uptr};
+ AssertFatal((plmn.mnc_digit_length == 2) || (plmn.mnc_digit_length == 3), "BAD MNC DIGIT LENGTH %d", plmn.mnc_digit_length);
+ return plmn;
+}
+
uint8_t set_plmn_config(plmn_id_t *p, uint8_t idx)
{
char gnbpath[MAX_OPTNAME_SIZE * 2 + 8];
snprintf(gnbpath, sizeof(gnbpath), "%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, idx);
GET_PARAMS_LIST(PLMNParamList, PLMNParams, GNBPLMNPARAMS_DESC, GNB_CONFIG_STRING_PLMN_LIST, gnbpath, PLMNPARAMS_CHECK);
uint8_t num_plmn = PLMNParamList.numelt;
+ const int n_plmn_params = sizeofArray(PLMNParams);
AssertFatal(num_plmn >= 1 && num_plmn <= 6, "The number of PLMN IDs must be in [1,6], but is %d\n", num_plmn);
for (int l = 0; l < num_plmn; ++l) {
- plmn_id_t *plmn = &p[l];
- plmn->mcc = *PLMNParamList.paramarray[l][GNB_MOBILE_COUNTRY_CODE_IDX].uptr;
- plmn->mnc = *PLMNParamList.paramarray[l][GNB_MOBILE_NETWORK_CODE_IDX].uptr;
- plmn->mnc_digit_length = *PLMNParamList.paramarray[l][GNB_MNC_DIGIT_LENGTH].u8ptr;
- AssertFatal((plmn->mnc_digit_length == 2) || (plmn->mnc_digit_length == 3), "BAD MNC DIGIT LENGTH %d", plmn->mnc_digit_length);
+ p[l] = extract_plmn_from_params(PLMNParamList.paramarray[l], n_plmn_params);
}
return num_plmn;
}
diff --git a/openair2/GNB_APP/gnb_config_common.h b/openair2/GNB_APP/gnb_config_common.h
index ae2ae4e799..bfa875c13d 100644
--- a/openair2/GNB_APP/gnb_config_common.h
+++ b/openair2/GNB_APP/gnb_config_common.h
@@ -4,6 +4,8 @@
#include
#include "common/5g_platform_types.h"
+#include "common/config/config_paramdesc.h"
uint16_t set_snssai_config(nssai_t *nssai, const int max_num_ssi, uint8_t k, uint8_t l);
uint8_t set_plmn_config(plmn_id_t *p, uint8_t idx);
+plmn_id_t extract_plmn_from_params(const paramdef_t *params, int n_params);
diff --git a/openair2/GNB_APP/gnb_paramdef.h b/openair2/GNB_APP/gnb_paramdef.h
index 8265303969..35a1c096d1 100644
--- a/openair2/GNB_APP/gnb_paramdef.h
+++ b/openair2/GNB_APP/gnb_paramdef.h
@@ -10,6 +10,7 @@
#define __GNB_APP_GNB_PARAMDEF__H__
#include "common/config/config_paramdesc.h"
+#include "common/config/config_userapi.h"
#include "common/ngran_types.h"
#include "RRC_nr_paramsvalues.h"
@@ -289,7 +290,6 @@ typedef enum {
#define GNB_NEIGHBOUR_LIST_PARAM_LIST { \
/* optname helpstr paramflags XXXptr def val type numelt */ \
{GNB_CONFIG_STRING_NRCELLID, "cell nrCell Id which has neighbours", PARAMFLAG_MANDATORY, .u64ptr=NULL, .defint64val=0, TYPE_UINT64, 0}, \
- {GNB_CONFIG_STRING_NEIGHBOUR_CELL_PHYSICAL_ID, "neighbour cell physical id", PARAMFLAG_MANDATORY, .uptr=NULL, .defuintval=0, TYPE_UINT, 0}, \
}
// clang-format on
#define GNB_CONFIG_STRING_NEIGHBOUR_CELL_LIST "neighbour_cell_configuration"
@@ -300,27 +300,111 @@ typedef enum {
#define GNB_CONFIG_STRING_NEIGHBOUR_CELL_BAND "band"
#define GNB_CONFIG_STRING_NEIGHBOUR_TRACKING_ARE_CODE "tracking_area_code"
#define GNB_CONFIG_STRING_NEIGHBOUR_PLMN "plmn"
+/* SIB3 fields (intra-frequency) - per-neighbor */
+#define GNB_CONFIG_STRING_NEIGHBOUR_CELL_Q_OFFSET_CELL "q_OffsetCell"
+#define GNB_CONFIG_STRING_NEIGHBOUR_CELL_Q_RXLEVMIN_OFFSET_CELL "q_RxLevMinOffsetCell"
+#define GNB_CONFIG_STRING_NEIGHBOUR_CELL_Q_QUALMIN_OFFSET_CELL "q_QualMinOffsetCell"
+/* SIB4 per-frequency fields are configured in frequency_list.frequency_config */
-#define GNB_CONFIG_N_CELL_GNB_ID_IDX 0
-#define GNB_CONFIG_N_CELL_NR_CELLID_IDX 1
-#define GNB_CONFIG_N_CELL_PHYSICAL_ID_IDX 2
-#define GNB_CONFIG_N_CELL_ABS_FREQ_SSB_IDX 3
-#define GNB_CONFIG_N_CELL_SCS_IDX 4
-#define GNB_CONFIG_N_CELL_BAND_IDX 5
-#define GNB_CONFIG_N_CELL_TAC_IDX 6
// clang-format off
-#define GNBNEIGHBOURCELLPARAMS_DESC { \
-/* optname helpstr paramflags XXXptr def val type numelt */ \
- {GNB_CONFIG_STRING_GNB_ID, "neighbour cell's gNB ID", PARAMFLAG_MANDATORY, .uptr=NULL, .defintval=0, TYPE_UINT, 0}, \
- {GNB_CONFIG_STRING_NRCELLID, "neighbour cell nrCell Id", PARAMFLAG_MANDATORY, .u64ptr=NULL, .defint64val=0, TYPE_UINT64, 0}, \
- {GNB_CONFIG_STRING_NEIGHBOUR_CELL_PHYSICAL_ID, "neighbour cell physical id", PARAMFLAG_MANDATORY, .uptr=NULL, .defuintval=0, TYPE_UINT, 0}, \
- {GNB_CONFIG_STRING_NEIGHBOUR_CELL_ABS_FREQ_SSB, "neighbour cell abs freq ssb", PARAMFLAG_MANDATORY, .i64ptr=NULL, .defint64val=0, TYPE_INT64, 0}, \
- {GNB_CONFIG_STRING_NEIGHBOUR_CELL_SCS, "neighbour cell scs", PARAMFLAG_MANDATORY, .uptr=NULL, .defuintval=0, TYPE_UINT, 0}, \
- {GNB_CONFIG_STRING_NEIGHBOUR_CELL_BAND, "neighbour cell band", PARAMFLAG_MANDATORY, .uptr=NULL, .defuintval=78, TYPE_UINT, 0}, \
- {GNB_CONFIG_STRING_NEIGHBOUR_TRACKING_ARE_CODE, "neighbour cell tracking area", PARAMFLAG_MANDATORY, .uptr=NULL, .defuintval=0, TYPE_UINT, 0}, \
+#define GNBNEIGHBOURCELLPARAMS_DESC { /* optname helpstr paramflags XXXptr def val type numelt */ \
+ {GNB_CONFIG_STRING_GNB_ID, \
+ "neighbour cell's gNB ID", PARAMFLAG_MANDATORY, .uptr=NULL, .defintval=0, TYPE_UINT, 0, \
+ .chkPptr=NULL}, \
+ {GNB_CONFIG_STRING_NRCELLID, \
+ "neighbour cell nrCell Id", PARAMFLAG_MANDATORY, .u64ptr=NULL, .defint64val=0, TYPE_UINT64, 0, \
+ .chkPptr=NULL}, \
+ {GNB_CONFIG_STRING_NEIGHBOUR_CELL_PHYSICAL_ID, \
+ "neighbour cell physical id", PARAMFLAG_MANDATORY, .uptr=NULL, .defuintval=0, TYPE_UINT, 0, \
+ .chkPptr = &(checkedparam_t){.s2 = {config_check_uintrange, {0, 1007}}}}, \
+ {GNB_CONFIG_STRING_NEIGHBOUR_CELL_ABS_FREQ_SSB, \
+ "neighbour cell absolute frequency SSB (0..3279165)", PARAMFLAG_MANDATORY, .i64ptr=NULL, .defint64val=0, TYPE_INT64, 0, \
+ .chkPptr = &(checkedparam_t){.s2 = {config_check_intrange, {0, 3279165}}}}, \
+ {GNB_CONFIG_STRING_NEIGHBOUR_CELL_SCS, \
+ "neighbour cell scs (15/30/60/120 kHz)", PARAMFLAG_MANDATORY, .uptr=NULL, .defuintval=0, TYPE_UINT, 0, \
+ .chkPptr = &(checkedparam_t){.s1 = {config_check_intval, {0, 1, 2, 3}, 4}}}, \
+ {GNB_CONFIG_STRING_NEIGHBOUR_CELL_BAND, \
+ "neighbour cell band (1..1024)", PARAMFLAG_MANDATORY, .uptr=NULL, .defuintval=78, TYPE_UINT, 0, \
+ .chkPptr = &(checkedparam_t){.s2 = {config_check_uintrange, {1, 1024}}}}, \
+ {GNB_CONFIG_STRING_NEIGHBOUR_TRACKING_ARE_CODE, \
+ "neighbour cell tracking area (0..16777215)", PARAMFLAG_MANDATORY, .uptr=NULL, .defuintval=0, TYPE_UINT, 0, \
+ .chkPptr = &(checkedparam_t){.s2 = {config_check_uintrange, {0, 16777215}}}}, \
+ {GNB_CONFIG_STRING_NEIGHBOUR_CELL_Q_OFFSET_CELL, \
+ "Q-OffsetCell for SIB3/SIB4 (Q-OffsetRange, default 0)", 0, .iptr=NULL, .defintval=0, TYPE_INT, 0, \
+ .chkPptr = &(checkedparam_t){.s1 = {config_check_intval, \
+ {-24, -22, -20, -18, -16, -14, -12, -10, -8, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24}, 31}}}, \
+ {GNB_CONFIG_STRING_NEIGHBOUR_CELL_Q_RXLEVMIN_OFFSET_CELL, \
+ "Q-RxLevMinOffsetCell for SIB3/SIB4 (1..8 or -1=disabled)", 0, .iptr=NULL, .defintval=-1, TYPE_INT, 0, \
+ .chkPptr = &(checkedparam_t){.s1 = {config_check_intval, {-1, 1, 2, 3, 4, 5, 6, 7, 8}, 9}}}, \
+ {GNB_CONFIG_STRING_NEIGHBOUR_CELL_Q_QUALMIN_OFFSET_CELL, \
+ "Q-QualMinOffsetCell for SIB3/SIB4 (1..8 or -1=disabled)", 0, .iptr=NULL, .defintval=-1, TYPE_INT, 0, \
+ .chkPptr = &(checkedparam_t){.s1 = {config_check_intval, {-1, 1, 2, 3, 4, 5, 6, 7, 8}, 9}}}, \
}
// clang-format on
+/* Per-frequency neighbour configuration (frequency_list) */
+#define GNB_CONFIG_STRING_FREQUENCY_LIST "frequency_list"
+#define GNB_CONFIG_STRING_FREQUENCY_ABS_FREQ_SSB "absoluteFrequencySSB"
+#define GNB_CONFIG_STRING_FREQUENCY_SCS "subcarrierSpacing"
+#define GNB_CONFIG_STRING_FREQUENCY_BAND "band"
+#define GNB_CONFIG_STRING_FREQUENCY_CONFIG "frequency_config"
+
+#define GNB_CONFIG_STRING_FREQUENCY_CELL_RESEL_PRIO "cellReselectionPriority"
+#define GNB_CONFIG_STRING_FREQUENCY_THRESH_X_HIGH_P "threshX_HighP"
+#define GNB_CONFIG_STRING_FREQUENCY_THRESH_X_LOW_P "threshX_LowP"
+#define GNB_CONFIG_STRING_FREQUENCY_THRESH_X_HIGH_Q "threshX_HighQ"
+#define GNB_CONFIG_STRING_FREQUENCY_THRESH_X_LOW_Q "threshX_LowQ"
+#define GNB_CONFIG_STRING_FREQUENCY_Q_OFFSET_FREQ "q_OffsetFreq"
+#define GNB_CONFIG_STRING_FREQUENCY_Q_RXLEVMIN "q_RxLevMin"
+#define GNB_CONFIG_STRING_FREQUENCY_T_RESEL_NR "t_ReselectionNR"
+
+// clang-format off
+#define GNBFREQUENCYPARAMS_DESC { \
+/* optname helpstr paramflags XXXptr def val type numelt */ \
+ {GNB_CONFIG_STRING_FREQUENCY_ABS_FREQ_SSB, "inter-frequency abs freq ssb", PARAMFLAG_MANDATORY, .i64ptr=NULL, .defint64val=0, TYPE_INT64, 0}, \
+ {GNB_CONFIG_STRING_FREQUENCY_SCS, "inter-frequency scs", PARAMFLAG_MANDATORY, .uptr=NULL, .defuintval=0, TYPE_UINT, 0}, \
+ {GNB_CONFIG_STRING_FREQUENCY_BAND, "inter-frequency band", PARAMFLAG_MANDATORY, .uptr=NULL, .defuintval=78, TYPE_UINT, 0}, \
+}
+
+#define GNBFREQUENCYCONFIGPARAMS_DESC { \
+ {GNB_CONFIG_STRING_FREQUENCY_CELL_RESEL_PRIO, \
+ "SIB4 cellReselectionPriority (0..7, -1=disabled)", 0, .iptr=NULL, .defintval=-1, TYPE_INT, 0, \
+ .chkPptr = &(checkedparam_t){.s2 = {config_check_intrange, {-1, 7}}}}, \
+ {GNB_CONFIG_STRING_FREQUENCY_THRESH_X_HIGH_P, \
+ "SIB4 threshX-HighP (0..31)", 0, .iptr=NULL, .defintval=0, TYPE_INT, 0, \
+ .chkPptr = &(checkedparam_t){.s2 = {config_check_intrange, {0, 31}}}}, \
+ {GNB_CONFIG_STRING_FREQUENCY_THRESH_X_LOW_P, \
+ "SIB4 threshX-LowP (0..31)", 0, .iptr=NULL, .defintval=0, TYPE_INT, 0, \
+ .chkPptr = &(checkedparam_t){.s2 = {config_check_intrange, {0, 31}}}}, \
+ {GNB_CONFIG_STRING_FREQUENCY_THRESH_X_HIGH_Q, \
+ "SIB4 threshX-HighQ (0..31, -1=disabled)", 0, .iptr=NULL, .defintval=-1, TYPE_INT, 0, \
+ .chkPptr = &(checkedparam_t){.s2 = {config_check_intrange, {-1, 31}}}}, \
+ {GNB_CONFIG_STRING_FREQUENCY_THRESH_X_LOW_Q, \
+ "SIB4 threshX-LowQ (0..31, -1=disabled)", 0, .iptr=NULL, .defintval=-1, TYPE_INT, 0, \
+ .chkPptr = &(checkedparam_t){.s2 = {config_check_intrange, {-1, 31}}}}, \
+ {GNB_CONFIG_STRING_FREQUENCY_Q_OFFSET_FREQ, \
+ "SIB4 q-OffsetFreq (Q-OffsetRange values, default 0)", 0, .iptr=NULL, .defintval=0, TYPE_INT, 0, \
+ .chkPptr = &(checkedparam_t){.s1 = {config_check_intval, {-24, -22, -20, -18, -16, -14, -12, -10, \
+ -8, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24}, 31}}}, \
+ {GNB_CONFIG_STRING_FREQUENCY_Q_RXLEVMIN, \
+ "SIB4 per-carrier Q-RxLevMin (-70..-22, default -22)", 0, .iptr=NULL, .defintval=-22, TYPE_INT, 0, \
+ .chkPptr = &(checkedparam_t){.s2 = {config_check_intrange, {-70, -22}}}}, \
+ {GNB_CONFIG_STRING_FREQUENCY_T_RESEL_NR, \
+ "SIB4 per-carrier t-ReselectionNR (0..7, default 0)", 0, .uptr=NULL, .defuintval=0, TYPE_UINT, 0, \
+ .chkPptr = &(checkedparam_t){.s2 = {config_check_uintrange, {0, 7}}}}, \
+}
+// clang-format on
+
+/* Indexes into GNBFREQUENCYCONFIGPARAMS_DESC */
+#define GNB_CONFIG_FREQUENCY_CELL_RESEL_PRIO_IDX 0
+#define GNB_CONFIG_FREQUENCY_THRESH_X_HIGH_P_IDX 1
+#define GNB_CONFIG_FREQUENCY_THRESH_X_LOW_P_IDX 2
+#define GNB_CONFIG_FREQUENCY_THRESH_X_HIGH_Q_IDX 3
+#define GNB_CONFIG_FREQUENCY_THRESH_X_LOW_Q_IDX 4
+#define GNB_CONFIG_FREQUENCY_Q_OFFSET_FREQ_IDX 5
+#define GNB_CONFIG_FREQUENCY_Q_RXLEVMIN_IDX 6
+#define GNB_CONFIG_FREQUENCY_T_RESEL_NR_IDX 7
+
/* New Measurement Configurations*/
#define GNB_CONFIG_STRING_MEASUREMENT_CONFIGURATION "nr_measurement_configuration"
@@ -369,6 +453,95 @@ typedef enum {
#define MEASUREMENT_EVENTS_INCLUDE_BEAM_MEAS_IDX 1
#define MEASUREMENT_EVENTS_MAX_RS_INDEX_TO_REPORT 2
+/*-------------------------------------------------------------------------------------------------------------------------------------*/
+/* SIB2 cell reselection configuration parameters */
+/*-------------------------------------------------------------------------------------------------------------------------------------*/
+
+#define GNB_CONFIG_STRING_SIB2_CONFIG "sib2_config"
+
+/* clang-format off */
+
+/* SIB2 top-level parameters (per cell) */
+#define GNB_CONFIG_STRING_SIB2_Q_HYST "q_Hyst"
+#define GNB_CONFIG_STRING_SIB2_CELLRESEL_PRIORITY "cellReselectionPriority"
+#define GNB_CONFIG_STRING_SIB2_THRESH_SERVING_LOW_P "threshServingLowP"
+#define GNB_CONFIG_STRING_SIB2_THRESH_SERVING_LOW_Q "threshServingLowQ"
+#define GNB_CONFIG_STRING_SIB2_S_NONINTRASEARCH_P "s_NonIntraSearchP"
+#define GNB_CONFIG_STRING_SIB2_S_NONINTRASEARCH_Q "s_NonIntraSearchQ"
+#define GNB_CONFIG_STRING_SIB2_Q_RXLEVMIN "q_RxLevMin"
+#define GNB_CONFIG_STRING_SIB2_Q_QUALMIN "q_QualMin"
+#define GNB_CONFIG_STRING_SIB2_S_INTRASEARCH_P "s_IntraSearchP"
+#define GNB_CONFIG_STRING_SIB2_S_INTRASEARCH_Q "s_IntraSearchQ"
+#define GNB_CONFIG_STRING_SIB2_T_RESEL_NR "t_ReselectionNR"
+#define GNB_CONFIG_STRING_SIB2_DERIVE_SSB_IDX "deriveSSB_IndexFromCell"
+
+/* SIB2 speedStateReselectionPars parameters */
+#define GNB_CONFIG_STRING_SIB2_SPEED_T_EVAL "speed_t_Evaluation"
+#define GNB_CONFIG_STRING_SIB2_SPEED_T_HYST_NORMAL "speed_t_HystNormal"
+#define GNB_CONFIG_STRING_SIB2_SPEED_N_CELL_CHG_MED "speed_n_CellChangeMedium"
+#define GNB_CONFIG_STRING_SIB2_SPEED_N_CELL_CHG_HIGH "speed_n_CellChangeHigh"
+#define GNB_CONFIG_STRING_SIB2_SPEED_SF_MEDIUM "speed_sf_Medium"
+#define GNB_CONFIG_STRING_SIB2_SPEED_SF_HIGH "speed_sf_High"
+
+#define GNBSIB2PARAMS_DESC { /* optname helpstr paramflags XXXptr def val type numelt */ \
+ {GNB_CONFIG_STRING_SIB2_Q_HYST, \
+ "SIB2 q-Hyst (0,1,2,3,4,5,6,8,10..24 dB)", 0, .iptr=NULL, .defintval=0, TYPE_INT, 0, \
+ .chkPptr = &(checkedparam_t){.s1 = {config_check_intval, {0, 1, 2, 3, 4, 5, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24}, 16}}}, \
+ {GNB_CONFIG_STRING_SIB2_CELLRESEL_PRIORITY, \
+ "SIB2 cellReselectionPriority (0..7)", 0, .iptr=NULL, .defintval=0, TYPE_INT, 0, \
+ .chkPptr = &(checkedparam_t){.s2 = {config_check_intrange, {0, 7}}}}, \
+ {GNB_CONFIG_STRING_SIB2_THRESH_SERVING_LOW_P, \
+ "SIB2 threshServingLowP (0..31)", 0, .iptr=NULL, .defintval=0, TYPE_INT, 0, \
+ .chkPptr = &(checkedparam_t){.s2 = {config_check_intrange, {0, 31}}}}, \
+ {GNB_CONFIG_STRING_SIB2_THRESH_SERVING_LOW_Q, \
+ "SIB2 threshServingLowQ (0..31, -1=disabled)", 0, .iptr=NULL, .defintval=0, TYPE_INT, 0, \
+ .chkPptr = &(checkedparam_t){.s2 = {config_check_intrange, {-1, 31}}}}, \
+ {GNB_CONFIG_STRING_SIB2_S_NONINTRASEARCH_P, \
+ "SIB2 s-NonIntraSearchP (0..31, -1=disabled)", 0, .iptr=NULL, .defintval=-1, TYPE_INT, 0, \
+ .chkPptr = &(checkedparam_t){.s2 = {config_check_intrange, {-1, 31}}}}, \
+ {GNB_CONFIG_STRING_SIB2_S_NONINTRASEARCH_Q, \
+ "SIB2 s-NonIntraSearchQ (0..31, -1=disabled)", 0, .iptr=NULL, .defintval=-1, TYPE_INT, 0, \
+ .chkPptr = &(checkedparam_t){.s2 = {config_check_intrange, {-1, 31}}}}, \
+ {GNB_CONFIG_STRING_SIB2_Q_RXLEVMIN, \
+ "SIB2 q-RxLevMin (-70..-22)", 0, .iptr=NULL, .defintval=-56, TYPE_INT, 0, \
+ .chkPptr = &(checkedparam_t){.s2 = {config_check_intrange, {-70, -22}}}}, \
+ {GNB_CONFIG_STRING_SIB2_Q_QUALMIN, \
+ "SIB2 q-QualMin (-43..-12 or -1=disabled)", 0, .iptr=NULL, .defintval=-1, TYPE_INT, 0, \
+ .chkPptr = &(checkedparam_t){.s1 = {config_check_intval, \
+ {-1, -43, -42, -41, -40, -39, -38, -37, -36, -35, -34, -33, -32, -31, -30, -29, -28, \
+ -27, -26, -25, -24, -23, -22, -21, -20, -19, -18, -17, -16, -15, -14, -13, -12}, 33}}}, \
+ {GNB_CONFIG_STRING_SIB2_S_INTRASEARCH_P, \
+ "SIB2 s-IntraSearchP (0..31)", 0, .iptr=NULL, .defintval=22, TYPE_INT, 0, \
+ .chkPptr = &(checkedparam_t){.s2 = {config_check_intrange, {0, 31}}}}, \
+ {GNB_CONFIG_STRING_SIB2_S_INTRASEARCH_Q, \
+ "SIB2 s-IntraSearchQ (0..31, -1=disabled)", 0, .iptr=NULL, .defintval=-1, TYPE_INT, 0, \
+ .chkPptr = &(checkedparam_t){.s2 = {config_check_intrange, {-1, 31}}}}, \
+ {GNB_CONFIG_STRING_SIB2_T_RESEL_NR, \
+ "SIB2 t-ReselectionNR (0..7)", 0, .iptr=NULL, .defintval=1, TYPE_INT, 0, \
+ .chkPptr = &(checkedparam_t){.s2 = {config_check_intrange, {0, 7}}}}, \
+ {GNB_CONFIG_STRING_SIB2_DERIVE_SSB_IDX, \
+ "SIB2 deriveSSB-IndexFromCell (0/1)", PARAMFLAG_BOOL, .iptr=NULL, .defintval=1, TYPE_INT, 0}, \
+ {GNB_CONFIG_STRING_SIB2_SPEED_T_EVAL, \
+ "SIB2 speed t-Evaluation (0=s30,1=s60,2=s120,3=s180,4=s240)", 0, .iptr=NULL, .defintval=0, TYPE_INT, 0, \
+ .chkPptr = &(checkedparam_t){.s2 = {config_check_intrange, {0, 4}}}}, \
+ {GNB_CONFIG_STRING_SIB2_SPEED_T_HYST_NORMAL, \
+ "SIB2 speed t-HystNormal (0=s30,1=s60,2=s120,3=s180,4=s240)", 0, .iptr=NULL, .defintval=0, TYPE_INT, 0, \
+ .chkPptr = &(checkedparam_t){.s2 = {config_check_intrange, {0, 4}}}}, \
+ {GNB_CONFIG_STRING_SIB2_SPEED_N_CELL_CHG_MED, \
+ "SIB2 speed n-CellChangeMedium (1..16)", 0, .iptr=NULL, .defintval=1, TYPE_INT, 0, \
+ .chkPptr = &(checkedparam_t){.s2 = {config_check_intrange, {1, 16}}}}, \
+ {GNB_CONFIG_STRING_SIB2_SPEED_N_CELL_CHG_HIGH, \
+ "SIB2 speed n-CellChangeHigh (1..16)", 0, .iptr=NULL, .defintval=2, TYPE_INT, 0, \
+ .chkPptr = &(checkedparam_t){.s2 = {config_check_intrange, {1, 16}}}}, \
+ {GNB_CONFIG_STRING_SIB2_SPEED_SF_MEDIUM, \
+ "SIB2 speed sf-Medium (0=dB-6,1=dB-4,2=dB-2,3=dB0)", 0, .iptr=NULL, .defintval=1, TYPE_INT, 0, \
+ .chkPptr = &(checkedparam_t){.s2 = {config_check_intrange, {0, 3}}}}, \
+ {GNB_CONFIG_STRING_SIB2_SPEED_SF_HIGH, \
+ "SIB2 speed sf-High (0=dB-6,1=dB-4,2=dB-2,3=dB0)", 0, .iptr=NULL, .defintval=0, TYPE_INT, 0, \
+ .chkPptr = &(checkedparam_t){.s2 = {config_check_intrange, {0, 3}}}}, \
+}
+/* clang-format on */
+
/* PLMN ID configuration */
#define GNB_CONFIG_STRING_PLMN_LIST "plmn_list"
diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c
index 6ecba2e923..d56b921b48 100644
--- a/openair2/LAYER2/NR_MAC_UE/config_ue.c
+++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c
@@ -15,6 +15,8 @@
#include "common/utils/nr/nr_common.h"
#include "executables/softmodem-common.h"
#include "SCHED_NR/phy_frame_config_nr.h"
+#include "RRC/NR_UE/verify_RRC.h"
+#include "RRC/NR_UE/L2_interface_ue.h"
#include "oai_asn1.h"
#define ASIGN_P_VAL(dst, src) \
@@ -2552,7 +2554,9 @@ static void modify_csi_measconfig(NR_CSI_MeasConfig_t *source, NR_CSI_MeasConfig
}
}
-static void configure_csiconfig(NR_UE_ServingCell_Info_t *sc_info, struct NR_SetupRelease_CSI_MeasConfig *csi_MeasConfig_sr)
+static void configure_csiconfig(NR_UE_ServingCell_Info_t *sc_info,
+ struct NR_SetupRelease_CSI_MeasConfig *csi_MeasConfig_sr,
+ module_id_t ue_id)
{
switch (csi_MeasConfig_sr->present) {
case NR_SetupRelease_CSI_MeasConfig_PR_NOTHING:
@@ -2574,6 +2578,8 @@ static void configure_csiconfig(NR_UE_ServingCell_Info_t *sc_info, struct NR_Set
} else { // modification
modify_csi_measconfig(csi_MeasConfig_sr->choice.setup, sc_info->csi_MeasConfig);
}
+ if (!check_csi_report_consistency(sc_info->csi_MeasConfig))
+ nr_mac_rrc_verification_failed(ue_id);
break;
}
default:
@@ -2585,7 +2591,7 @@ static void configure_servingcell_info(NR_UE_MAC_INST_t *mac, NR_ServingCellConf
{
NR_UE_ServingCell_Info_t *sc_info = &mac->sc_info;
if (scd->csi_MeasConfig) {
- configure_csiconfig(sc_info, scd->csi_MeasConfig);
+ configure_csiconfig(sc_info, scd->csi_MeasConfig, mac->ue_id);
compute_csi_bitlen(sc_info->csi_MeasConfig, mac->csi_report_template);
}
diff --git a/openair2/LAYER2/NR_MAC_UE/tests/test_nr_ue_ra_procedures.cpp b/openair2/LAYER2/NR_MAC_UE/tests/test_nr_ue_ra_procedures.cpp
index ae79c87aee..0fb34a9a37 100644
--- a/openair2/LAYER2/NR_MAC_UE/tests/test_nr_ue_ra_procedures.cpp
+++ b/openair2/LAYER2/NR_MAC_UE/tests/test_nr_ue_ra_procedures.cpp
@@ -42,7 +42,9 @@ void nr_mac_rlc_data_ind(const module_id_t module_idP,
int num_data)
{
}
-
+void nr_mac_rrc_verification_failed(const module_id_t mod_id)
+{
+}
bool nr_rlc_activate_srb0(int ue_id,
void *data,
void (*send_initial_ul_rrc_message)(int ue_id, const uint8_t *sdu, sdu_size_t sdu_len, void *data))
@@ -77,6 +79,10 @@ int8_t nr_mac_rrc_data_ind_ue(const module_id_t module_id,
{
return 0;
}
+bool check_csi_report_consistency(const NR_CSI_MeasConfig_t *meas)
+{
+ return true;
+}
void nr_mac_rrc_meas_ind_ue(module_id_t module_id,
uint32_t gNB_index,
uint16_t Nid_cell,
diff --git a/openair2/LAYER2/NR_MAC_gNB/config.c b/openair2/LAYER2/NR_MAC_gNB/config.c
index 202590f9fc..1d217b7c72 100644
--- a/openair2/LAYER2/NR_MAC_gNB/config.c
+++ b/openair2/LAYER2/NR_MAC_gNB/config.c
@@ -988,27 +988,56 @@ bool nr_mac_configure_other_sib(gNB_MAC_INST *nrmac, int num_cu_sib, const f1ap_
NR_SystemInformation_IEs_t *sysInfov17 = calloc(1, sizeof(*sysInfov17)); // for othersibs
for (int i = 0; i < num_cu_sib; i++) {
config_sibs[i] = cu_sib[i].SI_type;
+ const byte_array_t *container = &cu_sib[i].SI_container;
+ if (!container->buf || container->len == 0) {
+ LOG_W(NR_MAC, "SIB%d container is invalid (ptr=%p len=%zu), skipping\n", config_sibs[i], container->buf, container->len);
+ continue;
+ }
switch (config_sibs[i]) {
- case 2: {
+ case NR_SIB_2: {
struct NR_SystemInformation_IEs__sib_TypeAndInfo__Member *type = calloc(1, sizeof(*type));
type->present = NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib2;
// SIB2 coming from CU need to decode it
NR_SIB2_t *sib2 = NULL;
- asn_dec_rval_t dec_rval = uper_decode(NULL,
- &asn_DEF_NR_SIB2,
- (void **)&sib2,
- cu_sib[i].SI_container,
- cu_sib[i].SI_container_length,
- 0,
- 0);
+ asn_dec_rval_t dec_rval = uper_decode(NULL, &asn_DEF_NR_SIB2, (void **)&sib2, container->buf, container->len, 0, 0);
if (dec_rval.code != RC_OK) {
LOG_E(NR_MAC, "cannot decode SIB%d from CU\n", config_sibs[i]);
- ASN_STRUCT_FREE(asn_DEF_NR_SIB2, cu_sib[i].SI_container);
+ ASN_STRUCT_FREE(asn_DEF_NR_SIB2, sib2);
}
type->choice.sib2 = sib2;
add_sib_to_systeminformation(sysInfo, type);
break;
}
+ case NR_SIB_3: {
+ struct NR_SystemInformation_IEs__sib_TypeAndInfo__Member *type = calloc_or_fail(1, sizeof(*type));
+ type->present = NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib3;
+ NR_SIB3_t *sib3 = NULL;
+ asn_dec_rval_t dec_rval = uper_decode(NULL, &asn_DEF_NR_SIB3, (void **)&sib3, container->buf, container->len, 0, 0);
+ if (dec_rval.code != RC_OK) {
+ LOG_E(NR_MAC, "cannot decode SIB%d from CU\n", config_sibs[i]);
+ ASN_STRUCT_FREE(asn_DEF_NR_SIB3, sib3);
+ free(type);
+ break;
+ }
+ type->choice.sib3 = sib3;
+ add_sib_to_systeminformation(sysInfo, type);
+ break;
+ }
+ case NR_SIB_4: {
+ struct NR_SystemInformation_IEs__sib_TypeAndInfo__Member *type = calloc_or_fail(1, sizeof(*type));
+ type->present = NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib4;
+ NR_SIB4_t *sib4 = NULL;
+ asn_dec_rval_t dec_rval = uper_decode(NULL, &asn_DEF_NR_SIB4, (void **)&sib4, container->buf, container->len, 0, 0);
+ if (dec_rval.code != RC_OK) {
+ LOG_E(NR_MAC, "cannot decode SIB%d from CU\n", config_sibs[i]);
+ ASN_STRUCT_FREE(asn_DEF_NR_SIB4, sib4);
+ free(type);
+ break;
+ }
+ type->choice.sib4 = sib4;
+ add_sib_to_systeminformation(sysInfo, type);
+ break;
+ }
default :
AssertFatal(false, "Invalid or not supported SIB%d\n", config_sibs[i]);
}
@@ -1019,7 +1048,7 @@ bool nr_mac_configure_other_sib(gNB_MAC_INST *nrmac, int num_cu_sib, const f1ap_
int sib_idx = i + num_cu_sib;
config_sibs[sib_idx] = si->SIB_type;
switch (config_sibs[sib_idx]) {
- case 19: {
+ case NR_SIB_19: {
struct NR_SystemInformation_IEs__sib_TypeAndInfo__Member *type_du = calloc(1, sizeof(*type_du));
type_du->present = NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib19_v1700;
NR_SIB19_r17_t *sib19 = get_SIB19_NR(cc->ServingCellConfigCommon);
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c
index 6b2c9e23ac..3341455e45 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c
@@ -7,7 +7,6 @@
*/
#include "common/platform_types.h"
-#include "uper_decoder.h"
/* MAC */
#include "nr_mac_gNB.h"
@@ -24,8 +23,6 @@
#include
-static void nr_fill_rar(NR_UE_info_t *UE, uint8_t *dlsch_buffer, nfapi_nr_pusch_pdu_t *pusch_pdu);
-
static const float ssb_per_rach_occasion[8] = {0.125, 0.25, 0.5, 1, 2, 4, 8};
static int16_t ssb_index_from_prach(module_id_t module_idP,
@@ -1027,6 +1024,126 @@ static bool get_feasible_msg3_tda(const NR_ServingCellConfigCommon_t *scc,
return false;
}
+/////////////////////////////////////
+// Random Access Response PDU //
+// TS 38.213 ch 8.2 //
+// TS 38.321 ch 6.2.3 //
+/////////////////////////////////////
+//| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |// bit-wise
+//| E | T | R A P I D |//
+//| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |//
+//| R | T A |//
+//| T A | UL grant |//
+//| UL grant |//
+//| UL grant |//
+//| UL grant |//
+//| T C - R N T I |//
+//| T C - R N T I |//
+/////////////////////////////////////
+// UL grant (27 bits) //
+/////////////////////////////////////
+//| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |// bit-wise
+//|-------------------|FHF|F_alloc|//
+//| Freq allocation |//
+//| F_alloc |Time allocation|//
+//| MCS | TPC |CSI|//
+/////////////////////////////////////
+// WIP
+// todo:
+// - handle MAC RAR BI subheader
+// - sending only 1 RAR subPDU
+// - UL Grant: hardcoded CSI, TPC, time alloc
+// - padding
+static void nr_fill_rar(NR_UE_info_t *UE, uint8_t *dlsch_buffer, nfapi_nr_pusch_pdu_t *pusch_pdu)
+{
+ NR_RA_t *ra = UE->ra;
+ LOG_D(NR_MAC,
+ "[gNB] Generate RAR MAC PDU frame %d slot %d preamble index %u TA command %d \n",
+ ra->Msg2_frame,
+ ra->Msg2_slot,
+ ra->preamble_index,
+ ra->timing_offset);
+ NR_RA_HEADER_BI *rarbi = (NR_RA_HEADER_BI *) dlsch_buffer;
+ NR_RA_HEADER_RAPID *rarh = (NR_RA_HEADER_RAPID *) (dlsch_buffer + 1);
+ NR_MAC_RAR *rar = (NR_MAC_RAR *) (dlsch_buffer + 2);
+ unsigned char csi_req = 0;
+
+ /// E/T/R/R/BI subheader ///
+ // E = 1, MAC PDU includes another MAC sub-PDU (RAPID)
+ // T = 0, Back-off indicator subheader
+ // R = 2, Reserved
+ // BI = 0, 5ms
+ rarbi->E = 1;
+ rarbi->T = 0;
+ rarbi->R = 0;
+ rarbi->BI = 0;
+
+ /// E/T/RAPID subheader ///
+ // E = 0, one only RAR, first and last
+ // T = 1, RAPID
+ rarh->E = 0;
+ rarh->T = 1;
+ rarh->RAPID = ra->preamble_index;
+
+ /// RAR MAC payload ///
+ rar->R = 0;
+
+ // TA command
+ rar->TA1 = (uint8_t) (ra->timing_offset >> 5); // 7 MSBs of timing advance
+ rar->TA2 = (uint8_t) (ra->timing_offset & 0x1f); // 5 LSBs of timing advance
+
+ // TC-RNTI
+ rar->TCRNTI_1 = (uint8_t) (UE->rnti >> 8); // 8 MSBs of rnti
+ rar->TCRNTI_2 = (uint8_t) (UE->rnti & 0xff); // 8 LSBs of rnti
+
+ // UL grant
+
+ if (pusch_pdu->frequency_hopping)
+ AssertFatal(1==0,"PUSCH with frequency hopping currently not supported");
+
+ int bwp_size = pusch_pdu->bwp_size;
+ int prb_alloc = PRBalloc_to_locationandbandwidth0(ra->msg3_nb_rb, ra->msg3_first_rb, bwp_size);
+ int valid_bits = 14;
+ int f_alloc = prb_alloc & ((1 << valid_bits) - 1);
+
+ uint32_t ul_grant = csi_req | (ra->msg3_TPC << 1) | (pusch_pdu->mcs_index << 4) | (ra->Msg3_tda_id << 8) | (f_alloc << 12) | (pusch_pdu->frequency_hopping << 26);
+
+ rar->UL_GRANT_1 = (uint8_t) (ul_grant >> 24) & 0x07;
+ rar->UL_GRANT_2 = (uint8_t) (ul_grant >> 16) & 0xff;
+ rar->UL_GRANT_3 = (uint8_t) (ul_grant >> 8) & 0xff;
+ rar->UL_GRANT_4 = (uint8_t) ul_grant & 0xff;
+
+#ifdef DEBUG_RAR
+ LOG_I(NR_MAC, "rarh->E = 0x%x\n", rarh->E);
+ LOG_I(NR_MAC, "rarh->T = 0x%x\n", rarh->T);
+ LOG_I(NR_MAC, "rarh->RAPID = 0x%x (%i)\n", rarh->RAPID, rarh->RAPID);
+ LOG_I(NR_MAC, "rar->R = 0x%x\n", rar->R);
+ LOG_I(NR_MAC, "rar->TA1 = 0x%x\n", rar->TA1);
+ LOG_I(NR_MAC, "rar->TA2 = 0x%x\n", rar->TA2);
+ LOG_I(NR_MAC, "rar->UL_GRANT_1 = 0x%x\n", rar->UL_GRANT_1);
+ LOG_I(NR_MAC, "rar->UL_GRANT_2 = 0x%x\n", rar->UL_GRANT_2);
+ LOG_I(NR_MAC, "rar->UL_GRANT_3 = 0x%x\n", rar->UL_GRANT_3);
+ LOG_I(NR_MAC, "rar->UL_GRANT_4 = 0x%x\n", rar->UL_GRANT_4);
+ LOG_I(NR_MAC, "rar->TCRNTI_1 = 0x%x\n", rar->TCRNTI_1);
+ LOG_I(NR_MAC, "rar->TCRNTI_2 = 0x%x\n", rar->TCRNTI_2);
+#endif
+ LOG_D(NR_MAC,
+ "In %s: Transmitted RAR with t_alloc %d f_alloc %d ta_command %d mcs %d freq_hopping %d tpc_command %d csi_req %d t_crnti "
+ "%x \n",
+ __FUNCTION__,
+ rar->UL_GRANT_3 & 0x0f,
+ (rar->UL_GRANT_3 >> 4) | (rar->UL_GRANT_2 << 4) | ((rar->UL_GRANT_1 & 0x03) << 12),
+ rar->TA2 + (rar->TA1 << 5),
+ rar->UL_GRANT_4 >> 4,
+ rar->UL_GRANT_1 >> 2,
+ ra->msg3_TPC,
+ csi_req,
+ rar->TCRNTI_2 + (rar->TCRNTI_1 << 8));
+
+ // resetting msg3 TPC to 0dB for possible retransmissions
+ ra->msg3_TPC = 1;
+}
+
static bool nr_get_Msg3alloc(gNB_MAC_INST *mac, int CC_id, int current_slot, frame_t current_frame, NR_UE_info_t *UE)
{
NR_RA_t *ra = UE->ra;
@@ -1964,126 +2081,6 @@ bool nr_check_Msg4_MsgB_Ack(module_id_t module_id, frame_t frame, slot_t slot, N
return false;
}
-/////////////////////////////////////
-// Random Access Response PDU //
-// TS 38.213 ch 8.2 //
-// TS 38.321 ch 6.2.3 //
-/////////////////////////////////////
-//| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |// bit-wise
-//| E | T | R A P I D |//
-//| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |//
-//| R | T A |//
-//| T A | UL grant |//
-//| UL grant |//
-//| UL grant |//
-//| UL grant |//
-//| T C - R N T I |//
-//| T C - R N T I |//
-/////////////////////////////////////
-// UL grant (27 bits) //
-/////////////////////////////////////
-//| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |// bit-wise
-//|-------------------|FHF|F_alloc|//
-//| Freq allocation |//
-//| F_alloc |Time allocation|//
-//| MCS | TPC |CSI|//
-/////////////////////////////////////
-// WIP
-// todo:
-// - handle MAC RAR BI subheader
-// - sending only 1 RAR subPDU
-// - UL Grant: hardcoded CSI, TPC, time alloc
-// - padding
-static void nr_fill_rar(NR_UE_info_t *UE, uint8_t *dlsch_buffer, nfapi_nr_pusch_pdu_t *pusch_pdu)
-{
- NR_RA_t *ra = UE->ra;
- LOG_D(NR_MAC,
- "[gNB] Generate RAR MAC PDU frame %d slot %d preamble index %u TA command %d \n",
- ra->Msg2_frame,
- ra->Msg2_slot,
- ra->preamble_index,
- ra->timing_offset);
- NR_RA_HEADER_BI *rarbi = (NR_RA_HEADER_BI *) dlsch_buffer;
- NR_RA_HEADER_RAPID *rarh = (NR_RA_HEADER_RAPID *) (dlsch_buffer + 1);
- NR_MAC_RAR *rar = (NR_MAC_RAR *) (dlsch_buffer + 2);
- unsigned char csi_req = 0;
-
- /// E/T/R/R/BI subheader ///
- // E = 1, MAC PDU includes another MAC sub-PDU (RAPID)
- // T = 0, Back-off indicator subheader
- // R = 2, Reserved
- // BI = 0, 5ms
- rarbi->E = 1;
- rarbi->T = 0;
- rarbi->R = 0;
- rarbi->BI = 0;
-
- /// E/T/RAPID subheader ///
- // E = 0, one only RAR, first and last
- // T = 1, RAPID
- rarh->E = 0;
- rarh->T = 1;
- rarh->RAPID = ra->preamble_index;
-
- /// RAR MAC payload ///
- rar->R = 0;
-
- // TA command
- rar->TA1 = (uint8_t) (ra->timing_offset >> 5); // 7 MSBs of timing advance
- rar->TA2 = (uint8_t) (ra->timing_offset & 0x1f); // 5 LSBs of timing advance
-
- // TC-RNTI
- rar->TCRNTI_1 = (uint8_t) (UE->rnti >> 8); // 8 MSBs of rnti
- rar->TCRNTI_2 = (uint8_t) (UE->rnti & 0xff); // 8 LSBs of rnti
-
- // UL grant
-
- if (pusch_pdu->frequency_hopping)
- AssertFatal(1==0,"PUSCH with frequency hopping currently not supported");
-
- int bwp_size = pusch_pdu->bwp_size;
- int prb_alloc = PRBalloc_to_locationandbandwidth0(ra->msg3_nb_rb, ra->msg3_first_rb, bwp_size);
- int valid_bits = 14;
- int f_alloc = prb_alloc & ((1 << valid_bits) - 1);
-
- uint32_t ul_grant = csi_req | (ra->msg3_TPC << 1) | (pusch_pdu->mcs_index << 4) | (ra->Msg3_tda_id << 8) | (f_alloc << 12) | (pusch_pdu->frequency_hopping << 26);
-
- rar->UL_GRANT_1 = (uint8_t) (ul_grant >> 24) & 0x07;
- rar->UL_GRANT_2 = (uint8_t) (ul_grant >> 16) & 0xff;
- rar->UL_GRANT_3 = (uint8_t) (ul_grant >> 8) & 0xff;
- rar->UL_GRANT_4 = (uint8_t) ul_grant & 0xff;
-
-#ifdef DEBUG_RAR
- LOG_I(NR_MAC, "rarh->E = 0x%x\n", rarh->E);
- LOG_I(NR_MAC, "rarh->T = 0x%x\n", rarh->T);
- LOG_I(NR_MAC, "rarh->RAPID = 0x%x (%i)\n", rarh->RAPID, rarh->RAPID);
- LOG_I(NR_MAC, "rar->R = 0x%x\n", rar->R);
- LOG_I(NR_MAC, "rar->TA1 = 0x%x\n", rar->TA1);
- LOG_I(NR_MAC, "rar->TA2 = 0x%x\n", rar->TA2);
- LOG_I(NR_MAC, "rar->UL_GRANT_1 = 0x%x\n", rar->UL_GRANT_1);
- LOG_I(NR_MAC, "rar->UL_GRANT_2 = 0x%x\n", rar->UL_GRANT_2);
- LOG_I(NR_MAC, "rar->UL_GRANT_3 = 0x%x\n", rar->UL_GRANT_3);
- LOG_I(NR_MAC, "rar->UL_GRANT_4 = 0x%x\n", rar->UL_GRANT_4);
- LOG_I(NR_MAC, "rar->TCRNTI_1 = 0x%x\n", rar->TCRNTI_1);
- LOG_I(NR_MAC, "rar->TCRNTI_2 = 0x%x\n", rar->TCRNTI_2);
-#endif
- LOG_D(NR_MAC,
- "In %s: Transmitted RAR with t_alloc %d f_alloc %d ta_command %d mcs %d freq_hopping %d tpc_command %d csi_req %d t_crnti "
- "%x \n",
- __FUNCTION__,
- rar->UL_GRANT_3 & 0x0f,
- (rar->UL_GRANT_3 >> 4) | (rar->UL_GRANT_2 << 4) | ((rar->UL_GRANT_1 & 0x03) << 12),
- rar->TA2 + (rar->TA1 << 5),
- rar->UL_GRANT_4 >> 4,
- rar->UL_GRANT_1 >> 2,
- ra->msg3_TPC,
- csi_req,
- rar->TCRNTI_2 + (rar->TCRNTI_1 << 8));
-
- // resetting msg3 TPC to 0dB for possible retransmissions
- ra->msg3_TPC = 1;
-}
-
/** @brief remove the UE with RNTI rnti from list of UEs doing RA.
*
* The corresponding function to add is add_new_UE_RA(). */
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c
index 81e1ab1819..6e2e4970a0 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c
@@ -16,16 +16,12 @@
#include "UTIL/OPT/opt.h"
#include "openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h"
-#include "F1AP_CauseRadioNetwork.h"
-
#include "intertask_interface.h"
#include "openair2/F1AP/f1ap_ids.h"
#include "F1AP_CauseRadioNetwork.h"
#include "T.h"
-
#include "uper_encoder.h"
-#include "uper_decoder.h"
#include "SIMULATION/TOOLS/sim.h" // for taus
@@ -96,11 +92,6 @@ static const uint16_t cqi_table3[16][2] = {{0, 0},
{6, 6660},
{6, 7720}};
-static void determine_aggregation_level_search_order(int agg_level_search_order[NUM_PDCCH_AGG_LEVELS],
- float pdcch_cl_adjust);
-
-static int nr_mac_interrupt_ue_transmission(gNB_MAC_INST *mac, NR_UE_info_t *UE, int slots, int slots_per_frame);
-
int get_ssbidx_from_beam(gNB_MAC_INST *mac, int beam_idx)
{
for (int i = 0; i < MAX_NUM_OF_SSB; i++)
@@ -570,6 +561,21 @@ int find_pdcch_candidate(const gNB_MAC_INST *mac,
return -1;
}
+/// @brief Orders PDCCH aggregation levels so that we first check desired aggregation level according to
+/// pdcch_cl_adjust
+/// @param agg_level_search_order in/out 5-element array of aggregation levels from 0 to 4
+/// @param pdcch_cl_adjust value from 0 to 1 indication channel impariments (0 - good channel, 1 - bad channel)
+static void determine_aggregation_level_search_order(int agg_level_search_order[NUM_PDCCH_AGG_LEVELS], float pdcch_cl_adjust)
+{
+ int desired_agg_level_index = round(4 * pdcch_cl_adjust);
+ int agg_level_search_index = 0;
+ for (int i = desired_agg_level_index; i < NUM_PDCCH_AGG_LEVELS; i++) {
+ agg_level_search_order[agg_level_search_index++] = i;
+ }
+ for (int i = desired_agg_level_index - 1; i >= 0; i--) {
+ agg_level_search_order[agg_level_search_index++] = i;
+ }
+}
int get_cce_index(const gNB_MAC_INST *nrmac,
const int CC_id,
@@ -3448,6 +3454,25 @@ void nr_csirs_scheduling(int Mod_idP, frame_t frame, slot_t slot, nfapi_nr_dl_tt
}
}
+static void nr_mac_interrupt_ue_transmission(gNB_MAC_INST *mac, NR_UE_info_t *UE, int slots, int slots_per_frame)
+{
+ DevAssert(mac != NULL);
+ DevAssert(UE != NULL);
+ NR_SCHED_ENSURE_LOCKED(&mac->sched_lock);
+
+ nr_timer_setup(&UE->UE_sched_ctrl.transm_interrupt, slots, 1);
+ nr_timer_start(&UE->UE_sched_ctrl.transm_interrupt);
+
+ // it might happen that timing advance command should be sent during the UE inactivity time.
+ // To prevent this, delay next TA command just after the UE inactivity time.
+ const int inactive_frames = slots / slots_per_frame + 1;
+ if ((UE->UE_sched_ctrl.ta_frame - mac->frame + MAX_FRAME_NUMBER) % MAX_FRAME_NUMBER < inactive_frames)
+ UE->UE_sched_ctrl.ta_frame = (mac->frame + inactive_frames) % MAX_FRAME_NUMBER;
+
+ LOG_D(NR_MAC, "UE %04x: Interrupt UE transmission (%d slots)\n", UE->rnti, slots);
+}
+
+
void nr_measgap_scheduling(gNB_MAC_INST *nr_mac, frame_t frame, sub_frame_t slot)
{
NR_SCHED_ENSURE_LOCKED(&nr_mac->sched_lock);
@@ -3517,25 +3542,6 @@ int nr_mac_get_reconfig_delay_slots(NR_SubcarrierSpacing_t scs)
return (delay_ms << scs) + sl_ahead;
}
-static int nr_mac_interrupt_ue_transmission(gNB_MAC_INST *mac, NR_UE_info_t *UE, int slots, int slots_per_frame)
-{
- DevAssert(mac != NULL);
- DevAssert(UE != NULL);
- NR_SCHED_ENSURE_LOCKED(&mac->sched_lock);
-
- nr_timer_setup(&UE->UE_sched_ctrl.transm_interrupt, slots, 1);
- nr_timer_start(&UE->UE_sched_ctrl.transm_interrupt);
-
- // it might happen that timing advance command should be sent during the UE inactivity time.
- // To prevent this, delay next TA command just after the UE inactivity time.
- const int inactive_frames = slots / slots_per_frame + 1;
- if ((UE->UE_sched_ctrl.ta_frame - mac->frame + MAX_FRAME_NUMBER) % MAX_FRAME_NUMBER < inactive_frames)
- UE->UE_sched_ctrl.ta_frame = (mac->frame + inactive_frames) % MAX_FRAME_NUMBER;
-
- LOG_D(NR_MAC, "UE %04x: Interrupt UE transmission (%d slots)\n", UE->rnti, slots);
- return 0;
-}
-
static void nr_mac_ue_transmission_timeout(gNB_MAC_INST *mac, NR_UE_info_t *UE, int slots)
{
DevAssert(mac != NULL);
@@ -4120,22 +4126,6 @@ bool nr_mac_get_new_rnti(NR_UEs_t *UEs, rnti_t *rnti)
return loop < 100; // nothing found: loop count 100
}
-/// @brief Orders PDCCH aggregation levels so that we first check desired aggregation level according to
-/// pdcch_cl_adjust
-/// @param agg_level_search_order in/out 5-element array of aggregation levels from 0 to 4
-/// @param pdcch_cl_adjust value from 0 to 1 indication channel impariments (0 - good channel, 1 - bad channel)
-static void determine_aggregation_level_search_order(int agg_level_search_order[NUM_PDCCH_AGG_LEVELS], float pdcch_cl_adjust)
-{
- int desired_agg_level_index = round(4 * pdcch_cl_adjust);
- int agg_level_search_index = 0;
- for (int i = desired_agg_level_index; i < NUM_PDCCH_AGG_LEVELS; i++) {
- agg_level_search_order[agg_level_search_index++] = i;
- }
- for (int i = desired_agg_level_index - 1; i >= 0; i--) {
- agg_level_search_order[agg_level_search_index++] = i;
- }
-}
-
/// @brief Update PDCCH closed loop adjust for UE depending on detection of feedback.
/// @param sched_ctrl UE scheduling control info
/// @param feedback_not_detected Whether feedback (PUSCH or HARQ) was detected
@@ -4200,6 +4190,21 @@ void nr_mac_pc_snr(nr_power_control_t *pc, int snrx10, int rssi)
pc->tpc_in_flight = PC_AVG_CNST * pc->tpc_in_flight; // + (1 - PC_AVG_CNST) * 0.0f
}
+/**
+ * @brief Enter new SNR and RSSI value for the latest UL transmission as new
+ * fixed averages. Reset "TPC in flight" to zero.
+ *
+ * @param pc the power control loop
+ * @param snrx10 the current SNR measurement multiplied by 10
+ * @param rssi the current RSSI measurement
+ */
+void nr_mac_pc_reset_snr(nr_power_control_t *pc, int snrx10, int rssi)
+{
+ pc->avg_snr = 0.1f * snrx10;
+ pc->avg_rssi = rssi;
+ pc->tpc_in_flight = 0.0f;
+}
+
/**
* @brief Set a new target SNR for this power control loop, which can be
* updated on a continuous basis, and will be reflected immediately upon
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c
index a6f66d738a..d0ab235276 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c
@@ -910,6 +910,9 @@ void handle_nr_uci_pucch_0_1(module_id_t mod_id, frame_t frame, slot_t slot, con
NR_SCHED_UNLOCK(&nrmac->sched_lock);
return;
}
+ // Msg4 Ack: reset average with first measurement
+ if (uci_01->ul_cqi != 0xff)
+ nr_mac_pc_reset_snr(&UE->UE_sched_ctrl.pucch_pc, uci_01->ul_cqi * 5 - 640, uci_01->rssi);
}
if (harq_confidence == 1) {
UE->mac_stats.pucch0_DTX++;
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c
index be869d9de9..f1fbbe2dfc 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c
@@ -762,11 +762,9 @@ static void nr_rx_ra_sdu(const module_id_t mod_id,
}
if (ul_cqi != 0xff) {
- NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
- // Msg3: reset average. If this fails (e.g., ul_cqi == 0xff)
+ // Msg3: reset average with first measurement. If this fails (e.g., ul_cqi == 0xff)
// everything starts from predetermined value
- sched_ctrl->pusch_pc.avg_snr = 0.1 * (ul_cqi * 5 - 640);
- sched_ctrl->pusch_pc.avg_rssi = rssi;
+ nr_mac_pc_reset_snr(&UE->UE_sched_ctrl.pusch_pc, ul_cqi * 5 - 640, rssi);
}
if (!sdu) { // NACK
@@ -2528,34 +2526,6 @@ void post_process_ulsch(gNB_MAC_INST *nr_mac, post_process_pusch_t *pusch, NR_UE
nr_mac->cset0_bwp_size);
}
-fsn_t fs_add_delta(const frame_structure_t *fs, uint32_t delta, fsn_t fsn)
-{
- const int slots_frame = fs->numb_slots_frame;
- fsn_t res = {
- .f = (fsn.f + (fsn.s + delta) / slots_frame) % MAX_FRAME_NUMBER,
- .s = (fsn.s + delta) % slots_frame,
- };
- return res;
-}
-int fs_get_diff(const frame_structure_t *fs, fsn_t a, fsn_t b)
-{
- const int slots_frame = fs->numb_slots_frame;
- int diff = (a.f * slots_frame + a.s) - (b.f * slots_frame + b.s);
- if (diff < -512 * slots_frame)
- diff += 1024 * slots_frame;
- else if (diff > 512 * slots_frame)
- diff -= 1024 * slots_frame;
- return diff;
-}
-fsn_t fs_get_max(const frame_structure_t *fs, fsn_t a, fsn_t b)
-{
- if (fs_get_diff(fs, a, b) <= 0) {
- return b;
- } else {
- return a;
- }
-}
-
static void nr_ulsch_preprocessor(gNB_MAC_INST *nr_mac, post_process_pusch_t *pp_pusch)
{
int frame = pp_pusch->frame;
@@ -2579,8 +2549,8 @@ static void nr_ulsch_preprocessor(gNB_MAC_INST *nr_mac, post_process_pusch_t *pp
// FAPI cannot handle more than MAX_DCI_CORESET DCIs
max_dci = min(max_dci, MAX_DCI_CORESET);
- fsn_t current = {frame, slot};
- fsn_t min_next = fs_add_delta(fs, min_rxtx, current);
+ fsn_t current = {frame, slot, *scc->ssbSubcarrierSpacing};
+ fsn_t min_next = fsn_add_delta(current, min_rxtx);
/* if it's the last DL slot, we should try all TDAs to make sure that the
* scheduler can reach e.g. the next mixed slot. Otherwise, if we don't, we
* might starve HARQ processes that need a retransmission in a specific slot
@@ -2589,16 +2559,16 @@ static void nr_ulsch_preprocessor(gNB_MAC_INST *nr_mac, post_process_pusch_t *pp
fsn_t *next = &nr_mac->ul_next;
while (max_dci > 0) {
/* go to the next UL slot, skipping DL if necessary */
- *next = fs_get_max(fs, *next, min_next);
+ *next = fsn_get_max(*next, min_next);
while (!is_ul_slot(next->s, fs))
- *next = fs_add_delta(fs, 1, *next);
+ *next = fsn_add_delta(*next, 1);
if (!is_dl_slot(current.s, fs)) // if current slot is not DL, nothing to do
break;
/* get a TDA so that next UL scheduling slot can be reached from current,
* and exit if there is no such TDA. Remove koffset, as it is
* "cell-specific", i.e., the UE will add it on the computation. */
- int k2 = fs_get_diff(fs, *next, current) - koffset;
+ int k2 = fsn_get_diff(*next, current) - koffset;
DevAssert(k2 > 0);
// we assume that all beams have the same symbol utilization in all RBs for
// simplification (but this might not be true). Otherwise, we would need to
@@ -2631,7 +2601,7 @@ static void nr_ulsch_preprocessor(gNB_MAC_INST *nr_mac, post_process_pusch_t *pp
break;
max_dci -= sched;
- *next = fs_add_delta(fs, 1, *next);
+ *next = fsn_add_delta(*next, 1);
}
}
diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h
index fb2f12e6d2..5aeace199c 100644
--- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h
+++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h
@@ -500,6 +500,7 @@ void post_process_ulsch(gNB_MAC_INST *nr_mac, post_process_pusch_t *pusch, NR_UE
float nr_mac_get_snr(const nr_power_control_t *pc);
void nr_mac_pc_snr(nr_power_control_t *pc, int snrx10, int rssi);
+void nr_mac_pc_reset_snr(nr_power_control_t *pc, int snrx10, int rssi);
void nr_mac_set_target_snrx10(nr_power_control_t *pc, int target_snrx10);
void nr_mac_set_rssi_threshold(nr_power_control_t *pc, int rssi_threshold);
void nr_mac_signal_dtx(nr_power_control_t *pc);
diff --git a/openair2/LAYER2/NR_MAC_gNB/main.c b/openair2/LAYER2/NR_MAC_gNB/main.c
index ca12c48c48..1f619308c2 100644
--- a/openair2/LAYER2/NR_MAC_gNB/main.c
+++ b/openair2/LAYER2/NR_MAC_gNB/main.c
@@ -293,6 +293,7 @@ void mac_top_init_gNB(ngran_node_t node_type,
RC.nrmac[i]->cset0_bwp_start = 0;
RC.nrmac[i]->cset0_bwp_size = 0;
+ RC.nrmac[i]->ul_next = (fsn_t) {.mu = *scc->ssbSubcarrierSpacing};
RC.nrmac[i]->print_ue_stats = true;
pthread_mutex_init(&RC.nrmac[i]->sched_lock, NULL);
diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h
index f7ea466a94..391bfeabe8 100644
--- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h
+++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h
@@ -16,6 +16,7 @@
#include
#include
#include
+#include "fsn.h"
#include "common/utils/ds/seq_arr.h"
#include "common/utils/nr/nr_common.h"
#include "common/utils/ds/byte_array.h"
@@ -878,14 +879,6 @@ typedef struct {
NR_ControlResourceSet_t coreset;
} NR_sched_ctrl_sib1_t;
-/// helper type to encapsulate a frame/slot combination in a single type.
-/// Currently only used in the UL preprocessor. Note: if you use this type
-/// further, please refactor it into a common type first.
-typedef struct fsn {
- frame_t f;
- slot_t s;
-} fsn_t;
-
typedef struct NR_du_stats {
/// cell-wide wide-band CQI distribution, see 28.552 5.1.1.11.1;
/// 0-15 CQI, 1-8 RI, 1-3 CQI table
diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.c b/openair2/RRC/NR/MESSAGES/asn1_msg.c
index 8d5d00c975..d818229054 100644
--- a/openair2/RRC/NR/MESSAGES/asn1_msg.c
+++ b/openair2/RRC/NR/MESSAGES/asn1_msg.c
@@ -223,39 +223,67 @@ NR_UE_NR_Capability_t *decode_nr_ue_capability(int rnti, const NR_UE_CapabilityR
return NULL;
}
-//------------------------------------------------------------------------------
-
-int do_SIB2_NR(uint8_t **msg_SIB2, NR_SSB_MTC_t *ssbmtc)
+byte_array_t do_SIB2_NR(const NR_SIB2_t *sib2)
{
- NR_SIB2_t *sib2 = calloc(1, sizeof(*sib2));
- sib2->cellReselectionInfoCommon.q_Hyst = NR_SIB2__cellReselectionInfoCommon__q_Hyst_dB0;
- struct NR_SIB2__cellReselectionInfoCommon__speedStateReselectionPars *speed = calloc(1, sizeof(*speed));
- NR_MobilityStateParameters_t mobilityStateParameters = {0};
- mobilityStateParameters.t_Evaluation = NR_MobilityStateParameters__t_Evaluation_s30;
- mobilityStateParameters.t_HystNormal = NR_MobilityStateParameters__t_HystNormal_s30;
- mobilityStateParameters.n_CellChangeMedium = 1;
- mobilityStateParameters.n_CellChangeHigh = 2;
- speed->mobilityStateParameters = mobilityStateParameters;
- struct NR_SIB2__cellReselectionInfoCommon__speedStateReselectionPars__q_HystSF qhyst = {0};
- qhyst.sf_Medium = NR_SIB2__cellReselectionInfoCommon__speedStateReselectionPars__q_HystSF__sf_Medium_dB_4;
- qhyst.sf_High = NR_SIB2__cellReselectionInfoCommon__speedStateReselectionPars__q_HystSF__sf_High_dB_6;
- speed->q_HystSF = qhyst;
- sib2->cellReselectionInfoCommon.speedStateReselectionPars = speed;
- sib2->cellReselectionServingFreqInfo.cellReselectionPriority = 0; // INTEGER (0..7)
- sib2->cellReselectionServingFreqInfo.threshServingLowP = 0;
- NR_ReselectionThresholdQ_t *threshServingLowQ = calloc(1, sizeof(*threshServingLowQ));
- *threshServingLowQ = 0;
- sib2->cellReselectionServingFreqInfo.threshServingLowQ = threshServingLowQ;
- sib2->intraFreqCellReselectionInfo.q_RxLevMin = -56; // INTEGER (-70..-22)
- sib2->intraFreqCellReselectionInfo.s_IntraSearchP = 22; // INTEGER (0..31)
- sib2->intraFreqCellReselectionInfo.t_ReselectionNR = 1; // INTEGER (0..7)
- sib2->intraFreqCellReselectionInfo.deriveSSB_IndexFromCell = true;
- sib2->intraFreqCellReselectionInfo.smtc = ssbmtc;
+ byte_array_t msg = {.buf = NULL, .len = 0};
+ char errbuf[256] = {0};
+ size_t errlen = sizeof(errbuf);
+ int ret = asn_check_constraints(&asn_DEF_NR_SIB2, sib2, errbuf, &errlen);
+ if (ret != 0) {
+ LOG_E(NR_RRC, "SIB2 constraint check failed: %s\n", errbuf);
+ return msg;
+ }
- ssize_t size = uper_encode_to_new_buffer(&asn_DEF_NR_SIB2, NULL, (void *)sib2, (void **)msg_SIB2);
- AssertFatal (size > 0, "ASN1 message encoding failed (encoded %lu bytes)!\n", size);
- ASN_STRUCT_FREE(asn_DEF_NR_SIB2, sib2);
- return size;
+ int val = uper_encode_to_new_buffer(&asn_DEF_NR_SIB2, NULL, (void *)sib2, (void **)&msg.buf);
+ if (val <= 0) {
+ LOG_E(NR_RRC, "Failed to encode SIB2\n");
+ return msg;
+ }
+
+ msg.len = val;
+ return msg;
+}
+
+byte_array_t do_SIB3_NR(const NR_SIB3_t *sib3)
+{
+ byte_array_t msg = {.buf = NULL, .len = 0};
+ char errbuf[256] = {0};
+ size_t errlen = sizeof(errbuf);
+ int ret = asn_check_constraints(&asn_DEF_NR_SIB3, sib3, errbuf, &errlen);
+ if (ret != 0) {
+ LOG_E(NR_RRC, "SIB3 constraint check failed: %s\n", errbuf);
+ return msg;
+ }
+
+ int val = uper_encode_to_new_buffer(&asn_DEF_NR_SIB3, NULL, (void *)sib3, (void **)&msg.buf);
+ if (val <= 0) {
+ LOG_E(NR_RRC, "Failed to encode SIB3\n");
+ return msg;
+ }
+
+ msg.len = val;
+ return msg;
+}
+
+byte_array_t do_SIB4_NR(NR_SIB4_t *sib4)
+{
+ byte_array_t msg = {.buf = NULL, .len = 0};
+ char errbuf[256] = {0};
+ size_t errlen = sizeof(errbuf);
+ int ret = asn_check_constraints(&asn_DEF_NR_SIB4, sib4, errbuf, &errlen);
+ if (ret != 0) {
+ LOG_E(NR_RRC, "SIB4 constraint check failed: %s\n", errbuf);
+ return msg;
+ }
+
+ int val = uper_encode_to_new_buffer(&asn_DEF_NR_SIB4, NULL, (void *)sib4, (void **)&msg.buf);
+ if (val <= 0) {
+ LOG_E(NR_RRC, "Failed to encode SIB4\n");
+ return msg;
+ }
+
+ msg.len = val;
+ return msg;
}
int do_RRCReject(uint8_t *const buffer)
diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.h b/openair2/RRC/NR/MESSAGES/asn1_msg.h
index 7aeb2b4ed0..384096ee16 100644
--- a/openair2/RRC/NR/MESSAGES/asn1_msg.h
+++ b/openair2/RRC/NR/MESSAGES/asn1_msg.h
@@ -33,6 +33,9 @@
#include "NR_MeasurementTimingConfiguration.h"
#include "NR_UE-NR-Capability.h"
#include "NR_UE-CapabilityRAT-ContainerList.h"
+#include "NR_SIB2.h"
+#include "NR_SIB3.h"
+#include "NR_SIB4.h"
#include "ds/seq_arr.h"
#include "ds/byte_array.h"
#include "openair2/LAYER2/nr_pdcp/nr_pdcp_configuration.h"
@@ -65,7 +68,9 @@ typedef struct {
*/
int xer_sprint_NR(char *string, size_t string_size, struct asn_TYPE_descriptor_s *td, void *sptr);
-int do_SIB2_NR(uint8_t **msg_SIB2, NR_SSB_MTC_t *ssbmtc);
+byte_array_t do_SIB2_NR(const NR_SIB2_t *sib2);
+byte_array_t do_SIB3_NR(const NR_SIB3_t *sib3);
+byte_array_t do_SIB4_NR(NR_SIB4_t *sib4);
int do_RRCReject(uint8_t *const buffer);
diff --git a/openair2/RRC/NR/MESSAGES/tests/test_asn1_msg.cpp b/openair2/RRC/NR/MESSAGES/tests/test_asn1_msg.cpp
index 4867d7f8ab..c14e9bdba0 100644
--- a/openair2/RRC/NR/MESSAGES/tests/test_asn1_msg.cpp
+++ b/openair2/RRC/NR/MESSAGES/tests/test_asn1_msg.cpp
@@ -14,12 +14,61 @@ extern "C" {
#include "NR_DRB-ToAddMod.h"
#include "NR_DRB-ToAddModList.h"
#include "NR_SRB-ToAddModList.h"
+#include "NR_InterFreqCarrierFreqInfo.h"
#include "ds/byte_array.h"
+#include "NR_SIB2.h"
+#include "NR_SIB3.h"
+#include "NR_SIB4.h"
+#include "NR_IntraFreqNeighCellInfo.h"
+#include "NR_IntraFreqNeighCellList.h"
+#include "NR_InterFreqCarrierFreqInfo.h"
+#include "NR_InterFreqNeighCellInfo.h"
+#include "NR_InterFreqNeighCellList.h"
+#include "asn_application.h"
RAN_CONTEXT_t RC;
#ifdef __cplusplus
}
#endif
+static NR_SIB2_t *encode_and_decode_sib2(const NR_SIB2_t *sib2, byte_array_t *ba_out)
+{
+ *ba_out = do_SIB2_NR(sib2);
+ EXPECT_GT(ba_out->len, 0);
+ EXPECT_NE(ba_out->buf, nullptr);
+
+ NR_SIB2_t *decoded = nullptr;
+ asn_dec_rval_t dec = uper_decode(nullptr, &asn_DEF_NR_SIB2, (void **)&decoded, ba_out->buf, ba_out->len, 0, 0);
+ EXPECT_EQ(dec.code, RC_OK);
+ EXPECT_NE(decoded, nullptr);
+ return decoded;
+}
+
+static NR_SIB3_t *encode_and_decode_sib3(const NR_SIB3_t *sib3, byte_array_t *ba_out)
+{
+ *ba_out = do_SIB3_NR(sib3);
+ EXPECT_GT(ba_out->len, 0);
+ EXPECT_NE(ba_out->buf, nullptr);
+
+ NR_SIB3_t *decoded = nullptr;
+ asn_dec_rval_t dec = uper_decode(nullptr, &asn_DEF_NR_SIB3, (void **)&decoded, ba_out->buf, ba_out->len, 0, 0);
+ EXPECT_EQ(dec.code, RC_OK);
+ EXPECT_NE(decoded, nullptr);
+ return decoded;
+}
+
+static NR_SIB4_t *encode_and_decode_sib4(NR_SIB4_t *sib4, byte_array_t *ba_out)
+{
+ *ba_out = do_SIB4_NR(sib4);
+ EXPECT_GT(ba_out->len, 0);
+ EXPECT_NE(ba_out->buf, nullptr);
+
+ NR_SIB4_t *decoded = nullptr;
+ asn_dec_rval_t dec = uper_decode(nullptr, &asn_DEF_NR_SIB4, (void **)&decoded, ba_out->buf, ba_out->len, 0, 0);
+ EXPECT_EQ(dec.code, RC_OK);
+ EXPECT_NE(decoded, nullptr);
+ return decoded;
+}
+
TEST(nr_asn1, rrc_reject)
{
unsigned char buf[1000];
@@ -138,6 +187,167 @@ TEST(nr_asn1, rrc_reconfiguration)
free_RRCReconfiguration_params(params);
}
+TEST(nr_asn1, sib2_basic_encode_decode)
+{
+ NR_SIB2_t *sib2 = (NR_SIB2_t *)calloc_or_fail(1, sizeof(*sib2));
+ sib2->cellReselectionInfoCommon.q_Hyst = NR_SIB2__cellReselectionInfoCommon__q_Hyst_dB0;
+ sib2->cellReselectionServingFreqInfo.cellReselectionPriority = 3;
+ sib2->cellReselectionServingFreqInfo.threshServingLowP = 10;
+ sib2->intraFreqCellReselectionInfo.q_RxLevMin = -56;
+ sib2->intraFreqCellReselectionInfo.s_IntraSearchP = 22;
+ sib2->intraFreqCellReselectionInfo.t_ReselectionNR = 1;
+ sib2->intraFreqCellReselectionInfo.deriveSSB_IndexFromCell = true;
+
+ byte_array_t ba = {};
+ NR_SIB2_t *decoded = encode_and_decode_sib2(sib2, &ba);
+
+ EXPECT_EQ(decoded->cellReselectionServingFreqInfo.cellReselectionPriority,
+ sib2->cellReselectionServingFreqInfo.cellReselectionPriority);
+ EXPECT_EQ(decoded->cellReselectionServingFreqInfo.threshServingLowP, sib2->cellReselectionServingFreqInfo.threshServingLowP);
+
+ ASN_STRUCT_FREE(asn_DEF_NR_SIB2, sib2);
+ ASN_STRUCT_FREE(asn_DEF_NR_SIB2, decoded);
+ free_byte_array(ba);
+}
+
+TEST(nr_asn1, sib3_basic_encode_decode)
+{
+ NR_SIB3_t *sib3 = (NR_SIB3_t *)calloc_or_fail(1, sizeof(*sib3));
+ sib3->intraFreqNeighCellList = (struct NR_IntraFreqNeighCellList *)calloc_or_fail(1, sizeof(*sib3->intraFreqNeighCellList));
+
+ NR_IntraFreqNeighCellInfo_t *cell = (NR_IntraFreqNeighCellInfo_t *)calloc_or_fail(1, sizeof(*cell));
+ cell->physCellId = 100;
+ cell->q_OffsetCell = NR_Q_OffsetRange_dB0;
+ ASN_SEQUENCE_ADD(&sib3->intraFreqNeighCellList->list, cell);
+
+ byte_array_t ba = {};
+ NR_SIB3_t *decoded = encode_and_decode_sib3(sib3, &ba);
+
+ ASSERT_NE(decoded->intraFreqNeighCellList, nullptr);
+ EXPECT_EQ(decoded->intraFreqNeighCellList->list.count, 1);
+ EXPECT_EQ(decoded->intraFreqNeighCellList->list.array[0]->physCellId, cell->physCellId);
+
+ ASN_STRUCT_FREE(asn_DEF_NR_SIB3, sib3);
+ ASN_STRUCT_FREE(asn_DEF_NR_SIB3, decoded);
+ free_byte_array(ba);
+}
+
+TEST(nr_asn1, sib4_basic_encode_decode)
+{
+ NR_SIB4_t *sib4 = (NR_SIB4_t *)calloc_or_fail(1, sizeof(*sib4));
+
+ NR_InterFreqCarrierFreqInfo_t *carrier = (NR_InterFreqCarrierFreqInfo_t *)calloc_or_fail(1, sizeof(*carrier));
+ carrier->dl_CarrierFreq = 2000;
+ carrier->ssbSubcarrierSpacing = NR_SubcarrierSpacing_kHz15;
+ carrier->deriveSSB_IndexFromCell = true;
+ carrier->q_RxLevMin = -56;
+ carrier->t_ReselectionNR = 1;
+ carrier->threshX_HighP = 5;
+ carrier->threshX_LowP = 3;
+ carrier->interFreqNeighCellList = (struct NR_InterFreqNeighCellList *)calloc_or_fail(1, sizeof(*carrier->interFreqNeighCellList));
+
+ NR_InterFreqNeighCellInfo_t *ncell = (NR_InterFreqNeighCellInfo_t *)calloc_or_fail(1, sizeof(*ncell));
+ ncell->physCellId = 200;
+ ncell->q_OffsetCell = NR_Q_OffsetRange_dB0;
+ ASN_SEQUENCE_ADD(&carrier->interFreqNeighCellList->list, ncell);
+ ASN_SEQUENCE_ADD(&sib4->interFreqCarrierFreqList.list, carrier);
+
+ byte_array_t ba = {};
+ NR_SIB4_t *decoded = encode_and_decode_sib4(sib4, &ba);
+
+ ASSERT_GT(decoded->interFreqCarrierFreqList.list.count, 0);
+ EXPECT_EQ(decoded->interFreqCarrierFreqList.list.array[0]->dl_CarrierFreq, carrier->dl_CarrierFreq);
+
+ ASN_STRUCT_FREE(asn_DEF_NR_SIB4, sib4);
+ ASN_STRUCT_FREE(asn_DEF_NR_SIB4, decoded);
+ free_byte_array(ba);
+}
+
+TEST(nr_asn1, inter_freq_carrier_freq_info_ranges)
+{
+ NR_SIB4_t *sib4 = (NR_SIB4_t *)calloc_or_fail(1, sizeof(*sib4));
+ ASN_SEQUENCE_ADD(&sib4->interFreqCarrierFreqList.list,
+ (NR_InterFreqCarrierFreqInfo_t *)calloc_or_fail(1, sizeof(NR_InterFreqCarrierFreqInfo_t)));
+
+ NR_InterFreqCarrierFreqInfo_t *carrier = sib4->interFreqCarrierFreqList.list.array[0];
+ carrier->dl_CarrierFreq = 640000;
+ carrier->ssbSubcarrierSpacing = NR_SubcarrierSpacing_kHz30;
+ carrier->deriveSSB_IndexFromCell = 1;
+ carrier->threshX_HighP = 0;
+ carrier->threshX_LowP = 0;
+
+ NR_Q_OffsetRange_t *qoff = (NR_Q_OffsetRange_t *)calloc_or_fail(1, sizeof(*qoff));
+ *qoff = 15; // arbitrary valid Q-OffsetRange enum
+ carrier->q_OffsetFreq = qoff;
+
+ // Optional threshX_Q struct
+ carrier->threshX_Q = (decltype(carrier->threshX_Q))calloc_or_fail(1, sizeof(*carrier->threshX_Q));
+ carrier->threshX_Q->threshX_HighQ = 0;
+ carrier->threshX_Q->threshX_LowQ = 0;
+
+ auto try_encode = [](NR_SIB4_t *s, bool expect_success) {
+ byte_array_t ba = do_SIB4_NR(s);
+ int len = (int)ba.len;
+ if (expect_success) {
+ EXPECT_GT(len, 0);
+ EXPECT_NE(ba.buf, nullptr);
+ } else {
+ EXPECT_LE(len, 0);
+ }
+ free_byte_array(ba);
+ };
+
+ // Valid lower bounds for all constrained scalars
+ carrier->q_RxLevMin = -70;
+ carrier->t_ReselectionNR = 0;
+ carrier->threshX_HighP = 0;
+ carrier->threshX_LowP = 0;
+ carrier->threshX_Q->threshX_HighQ = 0;
+ carrier->threshX_Q->threshX_LowQ = 0;
+ *qoff = 15;
+ try_encode(sib4, true);
+
+ // Invalid q_RxLevMin (below ASN.1 range)
+ carrier->q_RxLevMin = -80;
+ carrier->t_ReselectionNR = 0;
+ try_encode(sib4, false);
+
+ // Invalid t_ReselectionNR (above ASN.1 range)
+ carrier->q_RxLevMin = -70;
+ carrier->t_ReselectionNR = 8;
+ try_encode(sib4, false);
+
+ // Restore valid q_RxLevMin / t_ReselectionNR
+ carrier->q_RxLevMin = -70;
+ carrier->t_ReselectionNR = 0;
+
+ // Invalid threshX_HighP (below 0)
+ carrier->threshX_HighP = -1;
+ try_encode(sib4, false);
+ carrier->threshX_HighP = 0;
+
+ // Invalid threshX_LowP (below 0)
+ carrier->threshX_LowP = -1;
+ try_encode(sib4, false);
+ carrier->threshX_LowP = 0;
+
+ // Invalid threshX_HighQ (below 0)
+ carrier->threshX_Q->threshX_HighQ = -1;
+ try_encode(sib4, false);
+ carrier->threshX_Q->threshX_HighQ = 0;
+
+ // Invalid threshX_LowQ (below 0)
+ carrier->threshX_Q->threshX_LowQ = -1;
+ try_encode(sib4, false);
+ carrier->threshX_Q->threshX_LowQ = 0;
+
+ // Invalid q_OffsetFreq (outside [-24,24] enum range)
+ *qoff = 99;
+ try_encode(sib4, false);
+
+ ASN_STRUCT_FREE(asn_DEF_NR_SIB4, sib4);
+}
+
int main(int argc, char **argv)
{
logInit();
diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h
index 606eb86327..5a4063c3f2 100644
--- a/openair2/RRC/NR/nr_rrc_defs.h
+++ b/openair2/RRC/NR/nr_rrc_defs.h
@@ -312,21 +312,107 @@ typedef struct {
bool is_default_a3_configuration_exists;
} nr_measurement_configuration_t;
+/** @brief Per-neighbor cell-specific offsets (TS 38.331), shared by SIB3 and SIB4
+ * Maps to ASN.1 IntraFreqNeighCellInfo and InterFreqNeighCellInfo
+ * (SIB3.IntraFreqNeighCellList, SIB4.InterFreqCarrierFreqInfo.neighCellList) */
typedef struct {
+ // q-OffsetCell: (Q-OffsetRange values -24,-22,-20,-18,-16,-14,-12,-10,-8,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,8,10,12,14,16,18,20,22,24 dB)
+ // per-neighbor cell ranking
+ int q_OffsetCell;
+ // q-RxLevMinOffsetCell: Q-OffsetCellSmall (1..8): Per-neighbor RSRP minimum offset
+ int q_RxLevMinOffsetCell;
+ // q-QualMinOffsetCell: Q-OffsetCellSmall (1..8): Per-neighbor RSRQ minimum offset
+ int q_QualMinOffsetCell;
+} nr_neighbour_cell_neighbor_offset_t;
+
+/** @brief SIB3 (intra-frequency) neighbor list parameters (TS 38.331)
+ * Per-neighbor fields for SIB3.IntraFreqNeighCellList.IntraFreqNeighCellInfo.
+ * SIB3 carries intra-freq neighbor offsets for ranking. */
+typedef struct {
+ nr_neighbour_cell_neighbor_offset_t offset;
+} nr_neighbour_cell_sib3_t;
+
+/** @brief SIB4 inter-frequency carrier parameters (TS 38.331)
+ * Per-frequency fields for SIB4.InterFreqCarrierFreqList.InterFreqCarrierFreqInfo.
+ * Stored once per ARFCN; all neighbors on that frequency share this config. */
+typedef struct {
+ // cellReselectionPriority (0..7): Absolute priority of this inter-freq carrier
+ int cellReselectionPriority;
+ // threshX-HighP (0..31): RSRP threshold for reselection to a higher-priority inter-freq
+ int threshX_HighP;
+ // threshX-LowP (0..31): RSRP threshold for reselection to a lower-priority inter-freq
+ int threshX_LowP;
+ // threshX-HighQ (0..31): RSRQ threshold for higher-priority inter-freq reselection
+ int threshX_HighQ;
+ // threshX-LowQ (0..31): RSRQ threshold for lower-priority inter-freq reselection
+ int threshX_LowQ;
+ // q-OffsetFreq (Q-OffsetRange values: -24,-22,-20,-18,-16,-14,-12,-10,-8,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,8,10,12,14,16,18,20,22,24 dB):
+ // Frequency-specific offset in inter-freq cell ranking formula
+ int q_OffsetFreq;
+} nr_neighbour_cell_sib4_freq_t;
+
+/** @brief SIB4 (inter-frequency) parameters per neighbor (TS 38.331)
+ * Combines per-frequency carrier info (InterFreqCarrierFreqInfo) and per-neighbor
+ * offsets (InterFreqNeighCellInfo). */
+typedef struct {
+ // Per-frequency carrier (InterFreqCarrierFreqInfo)
+ nr_neighbour_cell_sib4_freq_t sib4_freq;
+ // Per-neighbor offsets (InterFreqNeighCellInfo)
+ nr_neighbour_cell_neighbor_offset_t offset;
+} nr_neighbour_cell_sib4_t;
+
+/** @brief Per-frequency SIB4 configuration (TS 38.331), keyed by ARFCN
+ * One entry per inter-freq carrier (absoluteFrequencySSB + subcarrierSpacing).
+ * freq_cfg holds InterFreqCarrierFreqInfo parameters. Analogous to one “carrier” slice of SIB4
+ * interFreqCarrierFreqList. */
+typedef struct {
+ // absoluteFrequencySSB (ARFCN)
+ int arfcn;
+ // ssbSubcarrierSpacing
+ int scs;
+ // q-RxLevMin (-70..-22 dBm)
+ int q_RxLevMin;
+ // t-ReselectionNR (0..7)
+ int t_ReselectionNR;
+ // Inter-frequency carrier parameters (InterFreqCarrierFreqInfo)
+ nr_neighbour_cell_sib4_freq_t freq_cfg;
+} nr_inter_freq_cfg_t;
+
+/** @brief Neighbor cell configuration structure
+ * Single source of truth for neighbor cell information, used across multiple protocols/scopes:
+ * - Handover (NGAP/XnAP): for target gNB (ID, plmn, tac, nrcell_id, physicalCellId)
+ * - Measurement (MeasConfig): physicalCellId, absoluteFrequencySSB, band
+ * - DU validation: all fields validated against actual cell information
+ * - SIB3/SIB4 generation: physicalCellId, absoluteFrequencySSB, subcarrierSpacing, band
+ * References:
+ * - 3GPP TS 38.331 (RRC) for SIB3/SIB4 and MeasConfig
+ * - 3GPP TS 38.413 (NGAP) / TS 38.423 (XnAP) for target cell identification */
+typedef struct {
+ // gNB identifier (for target node in NGAP/XnAP handover)
uint32_t gNB_ID;
+ // NR Cell Global Identifier (for NGAP/XnAP handover, DU validation)
uint64_t nrcell_id;
+ // Physical Cell ID (PCI) (used in HandoverPreparationInformation and MeasObjectNR)
int physicalCellId;
+ // SSB absolute frequency (ARFCN) (for MeasObjectNR, intra/inter-frequency determination)
int absoluteFrequencySSB;
+ // SSB subcarrier spacing (for MeasObjectNR/SIB4)
int subcarrierSpacing;
+ // Frequency band indicator (for MeasObjectNR/SIB4)
int band;
+ // PLMN identity (for target node in NGAP/XnAP handover)
plmn_id_t plmn;
+ // Tracking Area Code (for target node in NGAP/XnAP handover)
uint32_t tac;
- bool isIntraFrequencyNeighbour;
+ // SIB3 (intra-frequency neighbor cell-specific offsets)
+ nr_neighbour_cell_sib3_t sib3;
+ // SIB4 (inter-frequency neighbor cell-specific parameters)
+ nr_neighbour_cell_sib4_t sib4;
} nr_neighbour_cell_t;
typedef struct neighbour_cell_configuration_s {
uint64_t nr_cell_id;
- seq_arr_t *neighbour_cells;
+ seq_arr_t neighbour_cells;
} neighbour_cell_configuration_t;
typedef struct nr_mac_rrc_dl_if_s {
@@ -418,6 +504,101 @@ typedef struct nr_rrc_cuup_container_t {
sctp_assoc_t assoc_id;
} nr_rrc_cuup_container_t;
+/**Timers for SIB2 MobilityStateParameters (TS 38.331)
+ * Value set shared by T-Evaluation and T-HystNormal: (s30, s60, s120, s180, s240). */
+typedef enum sib2_mobility_state_timer_e {
+ SIB2_MOBILITY_STATE_TIMER_S30,
+ SIB2_MOBILITY_STATE_TIMER_S60,
+ SIB2_MOBILITY_STATE_TIMER_S120,
+ SIB2_MOBILITY_STATE_TIMER_S180,
+ SIB2_MOBILITY_STATE_TIMER_S240,
+} sib2_mobility_state_timer_t;
+
+/** Q-HystSF scaling factors for Q_hyst (TS 38.331)
+ * Speed-dependent offsets (-6, -4, -2, 0 dB) applied to the base Q_hyst
+ * when the UE is in medium or high mobility state. */
+typedef enum sib2_q_hystsf_e {
+ SIB2_Q_HYSTSF_DB_6,
+ SIB2_Q_HYSTSF_DB_4,
+ SIB2_Q_HYSTSF_DB_2,
+ SIB2_Q_HYSTSF_DB0,
+} sib2_q_hystsf_t;
+
+/** SIB2 speedStateReselectionPars configuration
+ * Mirrors TS 38.331 MobilityStateParameters and Q-hystSF. */
+typedef struct sib2_speed_state_reselection_pars_s {
+ /* t-Evaluation: duration for evaluating allowed reselections
+ * to enter mobility states (s30, s60, s120, s180, s240) */
+ sib2_mobility_state_timer_t t_Evaluation;
+ /* t-HystNormal: additional time period to evaluate reselection criteria
+ * before returning to normal mobility (s30, s60, s120, s180, s240) */
+ sib2_mobility_state_timer_t t_HystNormal;
+ /* n-CellChangeMedium: max number of cell reselections to enter medium mobility state (1..16) */
+ int n_CellChangeMedium;
+ /* n-CellChangeHigh: max number of cell reselections to enter high mobility state (1..16) */
+ int n_CellChangeHigh;
+ /* sf-Medium: speed-dependent scaling factor for Qhyst in medium state (-6, -4, -2, 0 dB) */
+ sib2_q_hystsf_t sf_Medium;
+ /* sf-High: speed-dependent scaling factor for Qhyst in high state (-6, -4, -2, 0 dB) */
+ sib2_q_hystsf_t sf_High;
+} sib2_speed_state_reselection_pars_t;
+
+/** SIB2 cellReselectionServingFreqInfo (TS 38.331) */
+typedef struct {
+ /* s-NonIntraSearchP: Srxlev threshold to trigger NR inter-freq / inter-RAT measurements (0..31)*2 dB.
+ * Set to -1 to omit (optional ASN.1 field). */
+ int s_NonIntraSearchP;
+ /* s-NonIntraSearchQ: Squal threshold to trigger NR inter-freq / inter-RAT measurements (0..31)*2 dB */
+ int s_NonIntraSearchQ;
+ /* threshServingLowP: Srxlev threshold (dB) used by the UE on the serving cell
+ * when reselecting towards a lower-priority RAT/frequency (0..31)*2 dB */
+ int threshServingLowP;
+ /* threshServingLowQ: Squal threshold (dB) used by the UE on the serving cell
+ * when reselecting towards a lower-priority RAT/frequency (0..31)*2 dB.
+ * Set to -1 to omit (optional ASN.1 field). */
+ int threshServingLowQ;
+ /* cellReselectionPriority: absolute priority of serving NR frequency (0..7) */
+ int cellReselectionPriority;
+} cell_reselection_serving_freq_info_t;
+
+/** SIB2 cellReselectionInfoCommon (TS 38.331) */
+typedef struct {
+ /* q-Hyst: hysteresis added to serving-cell ranking R_s (0..24 dB) */
+ int q_Hyst;
+ /* speedStateReselectionPars: MobilityStateParameters + q-HystSF */
+ sib2_speed_state_reselection_pars_t *speedStateReselectionPars;
+} cell_reselection_info_common_t;
+
+/** SIB2 intraFreqCellReselectionInfo (TS 38.331) */
+typedef struct {
+ /* q-RxLevMin: minimum required RX level in the cell (dBm) */
+ int q_RxLevMin;
+ /* q-QualMin: minimum required quality level in the cell (dB); */
+ int q_QualMin;
+ /* s-IntraSearchP: Srxlev threshold for intra-freq meas (0..31) */
+ int s_IntraSearchP;
+ /* s-IntraSearchQ: Squal threshold for intra-freq meas (0..31) */
+ int s_IntraSearchQ;
+ /* t-ReselectionNR: NR cell reselection timer (0..7) */
+ int t_ReselectionNR;
+} intra_freq_cell_reselection_info_t;
+
+/** SIB2 configuration for idle/inactive cell reselection
+ * (maps to SIB2 reselection parameters in TS 38.304/38.331, per cell).
+ * @note Squal = Cell selection quality value (dB)
+ * Srxlev = Cell selection RX level value (dB) */
+typedef struct sib2_config_s {
+ // cellReselectionInfoCommon
+ cell_reselection_info_common_t cell_reselection_info_common;
+ // cellReselectionServingFreqInfo
+ cell_reselection_serving_freq_info_t cell_reselection_serving_freq_info;
+ // intraFreqCellReselectionInfo
+ intra_freq_cell_reselection_info_t intra_freq_cell_reselection_info;
+ /* deriveSSB_IndexFromCell: SIB2 deriveSSB-IndexFromCell - whether UE may
+ * assume SFN/SSB alignment across cells on serving freq (per TS 38.304/38.133) */
+ bool deriveSSB_IndexFromCell;
+} sib2_config_t;
+
//---NR---(completely change)---------------------
typedef struct gNB_RRC_INST_s {
@@ -432,6 +613,8 @@ typedef struct gNB_RRC_INST_s {
// RRC configuration
nr_rrc_config_t configuration;
seq_arr_t *SIBs;
+ // SIB2 configuration for cell reselection parameters
+ sib2_config_t sib2_config;
// gNB N3 GTPU instance
instance_t e1_inst;
@@ -443,6 +626,9 @@ typedef struct gNB_RRC_INST_s {
nr_mac_rrc_dl_if_t mac_rrc;
cucp_cuup_if_t cucp_cuup;
+ // Per-frequency SIB4 configurations, indexed by ARFCN
+ seq_arr_t inter_freqs; /* array of nr_inter_freq_cfg_t */
+ // Per-cell neighbour configurations, indexed by cell_id
seq_arr_t *neighbour_cell_configuration;
nr_measurement_configuration_t measurementConfiguration;
diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c
index 096dc98eea..4c47e6a23b 100644
--- a/openair2/RRC/NR/rrc_gNB.c
+++ b/openair2/RRC/NR/rrc_gNB.c
@@ -263,10 +263,8 @@ static bool eq_pci(const void *vval, const void *vit)
const nr_neighbour_cell_t *get_neighbour_cell_by_pci(const neighbour_cell_configuration_t *cell, int pci)
{
- seq_arr_t *head = cell->neighbour_cells;
- DevAssert(head != NULL);
- LOG_D(NR_RRC, "Number of neighbour cells: %ld\n", head->size);
- elm_arr_t e = find_if(head, &pci, eq_pci);
+ DevAssert(cell);
+ elm_arr_t e = find_if((seq_arr_t *)&cell->neighbour_cells, &pci, eq_pci);
if (e.found) {
const nr_neighbour_cell_t *neighbour = (const nr_neighbour_cell_t *)e.it;
LOG_D(NR_RRC, "Found matching neighbour cell with PCI %d and Cell ID %ld\n", neighbour->physicalCellId, neighbour->nrcell_id);
@@ -772,23 +770,23 @@ NR_MeasConfig_t *nr_rrc_get_measconfig(const gNB_RRC_INST *rrc, uint64_t nr_cell
const NR_MeasTimingList_t *mtlist = cell->mtc->criticalExtensions.choice.c1->choice.measTimingConf->measTiming;
const NR_MeasTiming_t *mt = mtlist->list.array[0];
const neighbour_cell_configuration_t *neighbour_config = get_neighbour_cell_config(rrc, cell->info.cell_id);
- seq_arr_t *neighbour_cells = NULL;
- if (neighbour_config)
- neighbour_cells = neighbour_config->neighbour_cells;
+ const seq_arr_t *neighbour_cells = neighbour_config ? &neighbour_config->neighbour_cells : NULL;
int *neigh_a3_id = NULL;
if (neighbour_cells && neighbour_cells->size)
neigh_a3_id = calloc_or_fail(neighbour_cells->size, sizeof(int));
- if (neighbour_cells && rrc->measurementConfiguration.a3_event_list && rrc->measurementConfiguration.a3_event_list->size > 0) {
+ const nr_measurement_configuration_t *meas_cfg = &rrc->measurementConfiguration;
+ const seq_arr_t *a3_event_list = meas_cfg->a3_event_list;
+ if (neighbour_cells && a3_event_list && a3_event_list->size > 0) {
/* Loop through neighbours and find related A3 configuration
If no related A3 but there is default add the default one.
If default one added once as a report, no need to add it again && duplication.
*/
LOG_D(NR_RRC, "Preparing A3 Event Measurement Configuration!\n");
bool default_a3_added = false; // To ensure that the default configuration is only added once
- for (int i = 0; i < neighbour_cells->size; i++) {
- nr_neighbour_cell_t *neighbourCell = (nr_neighbour_cell_t *)seq_arr_at(neighbour_cells, i);
+ int i = 0;
+ FOR_EACH_SEQ_ARR(nr_neighbour_cell_t *, neighbourCell, neighbour_cells) {
seq_arr_push_back(&neigh_seq, neighbourCell, sizeof(nr_neighbour_cell_t));
const nr_a3_event_t *a3Event = get_a3_configuration((gNB_RRC_INST *)rrc, neighbourCell->physicalCellId);
if (!a3Event) {
@@ -814,12 +812,13 @@ NR_MeasConfig_t *nr_rrc_get_measconfig(const gNB_RRC_INST *rrc, uint64_t nr_cell
}
NR_ReportConfigId_t reportConfigId = neigh_a3_id[i];
seq_arr_push_back(&rc_A3_seq, prepare_a3_event_report(a3Event, reportConfigId), sizeof(NR_ReportConfigToAddMod_t));
+ i++;
}
}
- if (rrc->measurementConfiguration.per_event)
- rc_PER = prepare_periodic_event_report(rrc->measurementConfiguration.per_event);
- if (rrc->measurementConfiguration.a2_event)
- rc_A2 = prepare_a2_event_report(rrc->measurementConfiguration.a2_event);
+ if (meas_cfg->per_event)
+ rc_PER = prepare_periodic_event_report(meas_cfg->per_event);
+ if (meas_cfg->a2_event)
+ rc_A2 = prepare_a2_event_report(meas_cfg->a2_event);
NR_MeasConfig_t *result = get_MeasConfig(mt, band, cell->info.pci, rc_PER, rc_A2, &rc_A3_seq, &neigh_seq, neigh_a3_id);
diff --git a/openair2/RRC/NR/rrc_gNB_du.c b/openair2/RRC/NR/rrc_gNB_du.c
index ec139e684d..6b60e5b6b9 100644
--- a/openair2/RRC/NR/rrc_gNB_du.c
+++ b/openair2/RRC/NR/rrc_gNB_du.c
@@ -23,6 +23,11 @@
#include "f1ap_messages_types.h"
#include "ngap_messages_types.h"
#include "nr_rrc_defs.h"
+#include "NR_SIB2.h"
+#include "NR_SIB3.h"
+#include "NR_SIB4.h"
+#include "NR_Q-OffsetRange.h"
+#include "openair2/RRC/NR/MESSAGES/asn1_msg.h"
#include "rrc_gNB_mobility.h"
#include "openair2/F1AP/f1ap_common.h"
#include "openair2/F1AP/f1ap_ids.h"
@@ -33,6 +38,7 @@
#include "s1ap_messages_types.h"
#include "tree.h"
#include "uper_decoder.h"
+#include "common/utils/oai_asn1.h"
#include "utils.h"
#include "xer_encoder.h"
@@ -55,6 +61,375 @@ static NR_SSB_MTC_t *get_ssb_mtc(const NR_MeasurementTimingConfiguration_t *mtc)
return ssb_mtc;
}
+/** @brief Map config q_Hyst (dB: 0,1,2,3,4,5,6,8,10..24) to ASN.1 q-Hyst enum index (0..15).
+ * ASN.1 NR_SIB2 cellReselectionInfoCommon.q-Hyst is encoded with 16 values. */
+static long get_q_hyst_asn1(int q_hyst_db)
+{
+ switch (q_hyst_db) {
+ case 0:
+ return NR_SIB2__cellReselectionInfoCommon__q_Hyst_dB0;
+ case 1:
+ return NR_SIB2__cellReselectionInfoCommon__q_Hyst_dB1;
+ case 2:
+ return NR_SIB2__cellReselectionInfoCommon__q_Hyst_dB2;
+ case 3:
+ return NR_SIB2__cellReselectionInfoCommon__q_Hyst_dB3;
+ case 4:
+ return NR_SIB2__cellReselectionInfoCommon__q_Hyst_dB4;
+ case 5:
+ return NR_SIB2__cellReselectionInfoCommon__q_Hyst_dB5;
+ case 6:
+ return NR_SIB2__cellReselectionInfoCommon__q_Hyst_dB6;
+ case 8:
+ return NR_SIB2__cellReselectionInfoCommon__q_Hyst_dB8;
+ case 10:
+ return NR_SIB2__cellReselectionInfoCommon__q_Hyst_dB10;
+ case 12:
+ return NR_SIB2__cellReselectionInfoCommon__q_Hyst_dB12;
+ case 14:
+ return NR_SIB2__cellReselectionInfoCommon__q_Hyst_dB14;
+ case 16:
+ return NR_SIB2__cellReselectionInfoCommon__q_Hyst_dB16;
+ case 18:
+ return NR_SIB2__cellReselectionInfoCommon__q_Hyst_dB18;
+ case 20:
+ return NR_SIB2__cellReselectionInfoCommon__q_Hyst_dB20;
+ case 22:
+ return NR_SIB2__cellReselectionInfoCommon__q_Hyst_dB22;
+ case 24:
+ return NR_SIB2__cellReselectionInfoCommon__q_Hyst_dB24;
+ default:
+ AssertFatal(false, "unexpected q-Hyst value %d (configuration should have been validated)\n", q_hyst_db);
+ }
+}
+
+/** @brief Build NR_SIB2 from validated SIB2 configuration.
+ * @param cfg Validated SIB2 configuration from config file
+ * @param ssbmtc SSB-MTC instance to attach to intraFreqCellReselectionInfo.smtc. */
+static NR_SIB2_t *get_sib2_from_cfg(const sib2_config_t *cfg, NR_SSB_MTC_t *ssbmtc)
+{
+ NR_SIB2_t *sib2 = calloc_or_fail(1, sizeof(*sib2));
+ typeof(sib2->cellReselectionInfoCommon) *common = &sib2->cellReselectionInfoCommon;
+ const cell_reselection_info_common_t *cfg_common = &cfg->cell_reselection_info_common;
+
+ /* q-Hyst: ASN.1 enum (0..15) converted from config dB (0,1,2,3,4,5,6,8,10..24). */
+ common->q_Hyst = get_q_hyst_asn1(cfg_common->q_Hyst);
+
+ /* speedStateReselectionPars */
+ if (cfg_common->speedStateReselectionPars != NULL) {
+ struct NR_SIB2__cellReselectionInfoCommon__speedStateReselectionPars *speed = calloc_or_fail(1, sizeof(*speed));
+ NR_MobilityStateParameters_t mobilityStateParameters = {0};
+ const sib2_speed_state_reselection_pars_t *pars = cfg_common->speedStateReselectionPars;
+ /* t-Evaluation / t-HystNormal: (0..7) */
+ mobilityStateParameters.t_Evaluation = pars->t_Evaluation;
+ mobilityStateParameters.t_HystNormal = pars->t_HystNormal;
+ /* n-CellChangeMedium / n-CellChangeHigh: (1..16) */
+ mobilityStateParameters.n_CellChangeMedium = pars->n_CellChangeMedium;
+ mobilityStateParameters.n_CellChangeHigh = pars->n_CellChangeHigh;
+ speed->mobilityStateParameters = mobilityStateParameters;
+
+ /* q-HystSF: sf-Medium/sf-High (0..3) */
+ struct NR_SIB2__cellReselectionInfoCommon__speedStateReselectionPars__q_HystSF qhyst = {0};
+ qhyst.sf_Medium = pars->sf_Medium;
+ qhyst.sf_High = pars->sf_High;
+ speed->q_HystSF = qhyst;
+
+ common->speedStateReselectionPars = speed;
+ }
+
+ /* cellReselectionServingFreqInfo */
+ typeof(sib2->cellReselectionServingFreqInfo) *serv = &sib2->cellReselectionServingFreqInfo;
+ const cell_reselection_serving_freq_info_t *cfg_serv = &cfg->cell_reselection_serving_freq_info;
+ /* cellReselectionPriority: CellReselectionPriority (0..7) */
+ serv->cellReselectionPriority = cfg_serv->cellReselectionPriority;
+ /* threshServingLowP: ReselectionThreshold (0..31) */
+ serv->threshServingLowP = cfg_serv->threshServingLowP;
+ /* threshServingLowQ: ReselectionThresholdQ (0..31) */
+ if (cfg_serv->threshServingLowQ != -1)
+ asn1cCallocOne(serv->threshServingLowQ, cfg_serv->threshServingLowQ);
+ /* s-NonIntraSearchP/Q: ReselectionThreshold/ReselectionThresholdQ (0..31) */
+ if (cfg_serv->s_NonIntraSearchP != -1)
+ asn1cCallocOne(serv->s_NonIntraSearchP, cfg_serv->s_NonIntraSearchP);
+ if (cfg_serv->s_NonIntraSearchQ != -1)
+ asn1cCallocOne(serv->s_NonIntraSearchQ, cfg_serv->s_NonIntraSearchQ);
+
+ /* intraFreqCellReselectionInfo */
+ typeof(sib2->intraFreqCellReselectionInfo) *intra = &sib2->intraFreqCellReselectionInfo;
+ const intra_freq_cell_reselection_info_t *cfg_intra = &cfg->intra_freq_cell_reselection_info;
+ /* q-RxLevMin: Q-RxLevMin (-70..-22) */
+ intra->q_RxLevMin = cfg_intra->q_RxLevMin;
+ /* q-QualMin: Q-QualMin (-43..-12) */
+ if (cfg_intra->q_QualMin != -1)
+ asn1cCallocOne(intra->q_QualMin, cfg_intra->q_QualMin);
+ /* s-IntraSearchP: ReselectionThreshold (0..31) */
+ intra->s_IntraSearchP = cfg_intra->s_IntraSearchP;
+ /* s-IntraSearchQ: ReselectionThresholdQ (0..31) */
+ if (cfg_intra->s_IntraSearchQ != -1)
+ asn1cCallocOne(intra->s_IntraSearchQ, cfg_intra->s_IntraSearchQ);
+ /* t-ReselectionNR: (0..7) */
+ intra->t_ReselectionNR = cfg_intra->t_ReselectionNR;
+ /* deriveSSB-IndexFromCell (bool) */
+ intra->deriveSSB_IndexFromCell = cfg->deriveSSB_IndexFromCell;
+ /* smtc */
+ intra->smtc = ssbmtc;
+
+ return sib2;
+}
+
+/** @brief Map internal int enum to ASN.1 Q-OffsetRange value. */
+static long get_q_offset_asn1(int q_offset_db)
+{
+ switch (q_offset_db) {
+ case -24:
+ return NR_Q_OffsetRange_dB_24;
+ case -22:
+ return NR_Q_OffsetRange_dB_22;
+ case -20:
+ return NR_Q_OffsetRange_dB_20;
+ case -18:
+ return NR_Q_OffsetRange_dB_18;
+ case -16:
+ return NR_Q_OffsetRange_dB_16;
+ case -14:
+ return NR_Q_OffsetRange_dB_14;
+ case -12:
+ return NR_Q_OffsetRange_dB_12;
+ case -10:
+ return NR_Q_OffsetRange_dB_10;
+ case -8:
+ return NR_Q_OffsetRange_dB_8;
+ case -6:
+ return NR_Q_OffsetRange_dB_6;
+ case -5:
+ return NR_Q_OffsetRange_dB_5;
+ case -4:
+ return NR_Q_OffsetRange_dB_4;
+ case -3:
+ return NR_Q_OffsetRange_dB_3;
+ case -2:
+ return NR_Q_OffsetRange_dB_2;
+ case -1:
+ return NR_Q_OffsetRange_dB_1;
+ case 0:
+ return NR_Q_OffsetRange_dB0;
+ case 1:
+ return NR_Q_OffsetRange_dB1;
+ case 2:
+ return NR_Q_OffsetRange_dB2;
+ case 3:
+ return NR_Q_OffsetRange_dB3;
+ case 4:
+ return NR_Q_OffsetRange_dB4;
+ case 5:
+ return NR_Q_OffsetRange_dB5;
+ case 6:
+ return NR_Q_OffsetRange_dB6;
+ case 8:
+ return NR_Q_OffsetRange_dB8;
+ case 10:
+ return NR_Q_OffsetRange_dB10;
+ case 12:
+ return NR_Q_OffsetRange_dB12;
+ case 14:
+ return NR_Q_OffsetRange_dB14;
+ case 16:
+ return NR_Q_OffsetRange_dB16;
+ case 18:
+ return NR_Q_OffsetRange_dB18;
+ case 20:
+ return NR_Q_OffsetRange_dB20;
+ case 22:
+ return NR_Q_OffsetRange_dB22;
+ case 24:
+ return NR_Q_OffsetRange_dB24;
+ default:
+ AssertFatal(false, "Invalid q_offset_db value %d\n", q_offset_db);
+ }
+}
+
+/** @brief Build a SIB3 (intra-frequency neighbour cell list) from the configured neighbour cells.
+ * Only neighbours whose SSB ARFCN matches @param serving_ssb_arfcn are included.
+ * @param neighbours list of configured neighbour cells
+ * @param serving_ssb_arfcn SSB ARFCN of the serving cell, used to filter intra-frequency neighbours
+ * @returns allocated NR_SIB3_t on success, NULL if no matching neighbours were found */
+static NR_SIB3_t *get_sib3_intra_freq_neighbors(const seq_arr_t *neighbours, uint32_t serving_ssb_arfcn)
+{
+ DevAssert(neighbours);
+
+ NR_SIB3_t *sib3 = calloc_or_fail(1, sizeof(*sib3));
+ sib3->intraFreqNeighCellList = calloc_or_fail(1, sizeof(*sib3->intraFreqNeighCellList));
+
+ int intra_count = 0;
+ FOR_EACH_SEQ_ARR (const nr_neighbour_cell_t *, neigh, neighbours) {
+ if (neigh->absoluteFrequencySSB != serving_ssb_arfcn)
+ continue;
+
+ LOG_D(NR_RRC,
+ "SIB3: intra-frequency neighbour candidate: cell ID %lu, PCI %d (SSB ARFCN %d)\n",
+ neigh->nrcell_id,
+ neigh->physicalCellId,
+ neigh->absoluteFrequencySSB);
+
+ NR_IntraFreqNeighCellInfo_t *cell = calloc_or_fail(1, sizeof(*cell));
+ cell->physCellId = neigh->physicalCellId;
+
+ const nr_neighbour_cell_neighbor_offset_t *off = &neigh->sib3.offset;
+ /* q-OffsetCell: NR_Q-OffsetRange (-24..24 dB), 0 dB default */
+ cell->q_OffsetCell = get_q_offset_asn1(off->q_OffsetCell);
+
+ /* q-RxLevMinOffsetCell / q-QualMinOffsetCell: (1..8) */
+ if (off->q_RxLevMinOffsetCell != -1)
+ asn1cCallocOne(cell->q_RxLevMinOffsetCell, off->q_RxLevMinOffsetCell);
+ if (off->q_QualMinOffsetCell != -1)
+ asn1cCallocOne(cell->q_QualMinOffsetCell, off->q_QualMinOffsetCell);
+
+ /* Add to SIB3 intra-frequency neighbour list */
+ if (sib3->intraFreqNeighCellList->list.count >= NR_maxCellIntra) {
+ LOG_W(NR_RRC, "SIB3: too many intra-frequency neighbors (max %d), skipping cell %ld\n", NR_maxCellIntra, neigh->nrcell_id);
+ asn1cFreeStruc(asn_DEF_NR_IntraFreqNeighCellInfo, cell);
+ break;
+ }
+ asn1cSeqAdd(&sib3->intraFreqNeighCellList->list, cell);
+ ++intra_count;
+ }
+
+ if (intra_count == 0) {
+ LOG_W(NR_RRC,
+ "SIB3: no intra-frequency neighbours found for serving SSB ARFCN %u "
+ "(configured neighbours %u), not building SIB3\n",
+ serving_ssb_arfcn,
+ (unsigned)seq_arr_size(neighbours));
+ asn1cFreeStruc(asn_DEF_NR_SIB3, sib3);
+ return NULL;
+ }
+
+ return sib3;
+}
+
+/** @brief Build an NR_InterFreqCarrierFreqInfo structure from a nr_inter_freq_cfg_t configuration.
+ * @param cfg Configuration to build the carrier from
+ * @return Allocated NR_InterFreqCarrierFreqInfo_t on success, NULL if the configuration is invalid */
+static NR_InterFreqCarrierFreqInfo_t *build_inter_freq_carrier_from_cfg(const nr_inter_freq_cfg_t *cfg)
+{
+ DevAssert(cfg);
+
+ const nr_neighbour_cell_sib4_freq_t *f = &cfg->freq_cfg;
+
+ NR_InterFreqCarrierFreqInfo_t *carrier = calloc_or_fail(1, sizeof(*carrier));
+ /* dl_CarrierFreq (ARFCN) */
+ carrier->dl_CarrierFreq = cfg->arfcn;
+ /* ssbSubcarrierSpacing: (15/30/60/120 kHz) */
+ carrier->ssbSubcarrierSpacing = cfg->scs;
+ carrier->deriveSSB_IndexFromCell = true;
+ /* Q-RxLevMin (-70..-22 dBm) */
+ carrier->q_RxLevMin = cfg->q_RxLevMin;
+ /* T-Reselection (0..7) */
+ carrier->t_ReselectionNR = cfg->t_ReselectionNR;
+ /* threshX_HighP/LowP: Reselection threshold (0..31) */
+ carrier->threshX_HighP = f->threshX_HighP;
+ carrier->threshX_LowP = f->threshX_LowP;
+ /* threshX-Q: Optional RSRQ thresholds; emit only when both are provided. */
+ if (f->threshX_HighQ != -1 && f->threshX_LowQ != -1) {
+ carrier->threshX_Q = calloc_or_fail(1, sizeof(*carrier->threshX_Q));
+ carrier->threshX_Q->threshX_HighQ = f->threshX_HighQ;
+ carrier->threshX_Q->threshX_LowQ = f->threshX_LowQ;
+ } else if (f->threshX_HighQ != -1 || f->threshX_LowQ != -1) {
+ LOG_W(NR_RRC,
+ "SIB4: partial threshX-Q for ARFCN %d (HighQ=%d LowQ=%d), omitting threshX-Q\n",
+ cfg->arfcn,
+ f->threshX_HighQ,
+ f->threshX_LowQ);
+ }
+ /* CellReselectionPriority (0..7) */
+ if (f->cellReselectionPriority != -1)
+ asn1cCallocOne(carrier->cellReselectionPriority, f->cellReselectionPriority);
+ /* q-OffsetFreq (-24..24 dB), 0 dB default */
+ asn1cCallocOne(carrier->q_OffsetFreq, get_q_offset_asn1(f->q_OffsetFreq));
+ /* InterFreqNeighCellList */
+ carrier->interFreqNeighCellList = calloc_or_fail(1, sizeof(*carrier->interFreqNeighCellList));
+ return carrier;
+}
+
+/**
+ * @brief Build an NR_SIB4 structure populated with inter-frequency neighbour cell entries.
+ *
+ * Iterates over all configured inter-frequency carriers (excluding the serving cell ARFCN)
+ * and, for each carrier, adds the matching neighbour cells from @p neighbour_config.
+ * Carriers with no matching neighbours are discarded. If no valid carrier is found,
+ * the function returns NULL.
+ *
+ * @param neighbour_config Neighbour cell configuration (cells only).
+ * @param inter_freqs gNB-level inter-frequency configuration.
+ * @param serving_ssb_arfcn SSB ARFCN of the serving cell, used to skip the serving carrier.
+ * @return Allocated NR_SIB4_t on success, NULL if no inter-frequency neighbours are available.
+ */
+static NR_SIB4_t *get_sib4_inter_freq_neighbors(const neighbour_cell_configuration_t *neighbour_config,
+ const seq_arr_t *inter_freqs,
+ uint32_t serving_ssb_arfcn)
+{
+ DevAssert(neighbour_config);
+
+ NR_SIB4_t *sib4 = calloc_or_fail(1, sizeof(*sib4));
+
+ const seq_arr_t *neigh = &neighbour_config->neighbour_cells;
+
+ FOR_EACH_SEQ_ARR (nr_inter_freq_cfg_t *, cfg, inter_freqs) {
+ if (cfg->arfcn == serving_ssb_arfcn)
+ continue;
+
+ NR_InterFreqCarrierFreqInfo_t *carrier = build_inter_freq_carrier_from_cfg(cfg);
+ if (!carrier)
+ continue;
+
+ NR_InterFreqNeighCellList_t *neigh_list = carrier->interFreqNeighCellList;
+
+ FOR_EACH_SEQ_ARR (nr_neighbour_cell_t *, nc, neigh) {
+ if (nc->absoluteFrequencySSB != cfg->arfcn || nc->subcarrierSpacing != cfg->scs)
+ continue;
+
+ if (neigh_list->list.count >= NR_maxCellInter) {
+ LOG_W(NR_RRC,
+ "SIB4: too many inter-frequency neighbors for ARFCN %ld (max %d), skipping neighbour\n",
+ carrier->dl_CarrierFreq,
+ NR_maxCellInter);
+ continue;
+ }
+
+ const nr_neighbour_cell_neighbor_offset_t *offset = &nc->sib4.offset;
+ LOG_I(NR_RRC,
+ "SIB4: added inter-frequency neighbour cell: cellId %ld (PCI %d), ARFCN %d, SCS %d\n",
+ nc->nrcell_id,
+ nc->physicalCellId,
+ cfg->arfcn,
+ cfg->scs);
+ asn1cSequenceAdd(neigh_list->list, NR_InterFreqNeighCellInfo_t, cell);
+ cell->physCellId = nc->physicalCellId;
+
+ /* q_OffsetCell: 0 dB is default */
+ cell->q_OffsetCell = get_q_offset_asn1(offset->q_OffsetCell);
+
+ /* q_RxLevMinOffsetCell / q_QualMinOffsetCell: range 1..8 */
+ if (offset->q_RxLevMinOffsetCell != -1)
+ asn1cCallocOne(cell->q_RxLevMinOffsetCell, offset->q_RxLevMinOffsetCell);
+ if (offset->q_QualMinOffsetCell != -1)
+ asn1cCallocOne(cell->q_QualMinOffsetCell, offset->q_QualMinOffsetCell);
+ }
+
+ if (neigh_list->list.count > 0) {
+ asn1cSeqAdd(&sib4->interFreqCarrierFreqList.list, carrier);
+ } else {
+ ASN_STRUCT_FREE(asn_DEF_NR_InterFreqCarrierFreqInfo, carrier);
+ }
+ }
+
+ if (sib4->interFreqCarrierFreqList.list.count == 0) {
+ ASN_STRUCT_FREE(asn_DEF_NR_SIB4, sib4);
+ return NULL;
+ }
+
+ return sib4;
+}
+
/** @brief Return the frequency of the SS block of the cell for which this message is included,
* or of other SS blocks within the same carrier. MeasurementTimingConfiguration message is
* used to convey assistance information for measurement timing between nodes (e.g F1 setup) */
@@ -152,7 +527,7 @@ static int nr_cell_id_match(const void *key, const void *element)
return 1;
}
-static neighbour_cell_configuration_t *get_cell_neighbour_list(const gNB_RRC_INST *rrc, const nr_rrc_cell_container_t *cell)
+static const neighbour_cell_configuration_t *get_cell_neighbour_list(const gNB_RRC_INST *rrc, const nr_rrc_cell_container_t *cell)
{
void *base = seq_arr_front(rrc->neighbour_cell_configuration);
size_t nmemb = seq_arr_size(rrc->neighbour_cell_configuration);
@@ -160,42 +535,7 @@ static neighbour_cell_configuration_t *get_cell_neighbour_list(const gNB_RRC_INS
void *it = bsearch((void *)&cell->info.cell_id, base, nmemb, size, nr_cell_id_match);
- return (neighbour_cell_configuration_t *)it;
-}
-
-static void is_intra_frequency_neighbour(void *ssb_arfcn, void *neighbour_cell)
-{
- uint32_t *ssb_arfcn_ptr = (uint32_t *)ssb_arfcn;
- nr_neighbour_cell_t *neighbour_cell_ptr = (nr_neighbour_cell_t *)neighbour_cell;
-
- if (*ssb_arfcn_ptr == neighbour_cell_ptr->absoluteFrequencySSB) {
- LOG_D(NR_RRC, "HO LOG: found intra frequency neighbour %lu!\n", neighbour_cell_ptr->nrcell_id);
- neighbour_cell_ptr->isIntraFrequencyNeighbour = true;
- }
-}
-/**
- * @brief Labels neighbour cells if they are intra frequency to prepare meas config only for intra frequency ho
- * @param[in] rrc Pointer to RRC instance
- * @param[in] cell Pointer to cell container
- */
-static void label_intra_frequency_neighbours(gNB_RRC_INST *rrc, const nr_rrc_cell_container_t *cell)
-{
- if (!rrc->neighbour_cell_configuration)
- return;
-
- neighbour_cell_configuration_t *neighbour_cell_config = get_cell_neighbour_list(rrc, cell);
- if (!neighbour_cell_config)
- return;
-
- uint32_t ssb_arfcn = get_ssb_arfcn(cell);
- LOG_D(NR_RRC,
- "Cell %lu (PCI %d, SSB ARFCN %u) has neighbour cell configuration, labeling intra-frequency neighbours\n",
- cell->info.cell_id,
- cell->info.pci,
- ssb_arfcn);
-
- seq_arr_t *cell_neighbour_list = neighbour_cell_config->neighbour_cells;
- for_each(cell_neighbour_list, (void *)&ssb_arfcn, is_intra_frequency_neighbour);
+ return (const neighbour_cell_configuration_t *)it;
}
static bool valid_du_in_neighbour_configs(const seq_arr_t *neighbour_cell_configuration, const f1ap_served_cell_info_t *cell)
@@ -206,10 +546,8 @@ static bool valid_du_in_neighbour_configs(const seq_arr_t *neighbour_cell_config
int ssb_arfcn = ssb_arfcn_mtc(mtc);
ASN_STRUCT_FREE(asn_DEF_NR_MeasurementTimingConfiguration, mtc);
- for (int c = 0; c < neighbour_cell_configuration->size; c++) {
- const neighbour_cell_configuration_t *neighbour_config = seq_arr_at(neighbour_cell_configuration, c);
- for (int ni = 0; ni < neighbour_config->neighbour_cells->size; ni++) {
- const nr_neighbour_cell_t *nc = seq_arr_at(neighbour_config->neighbour_cells, ni);
+ FOR_EACH_SEQ_ARR(const neighbour_cell_configuration_t *, neighbour_config, neighbour_cell_configuration) {
+ FOR_EACH_SEQ_ARR(const nr_neighbour_cell_t *, nc, &neighbour_config->neighbour_cells) {
if (nc->nrcell_id != cell->nr_cellid)
continue;
// current cell is in the nc config, check that config matches
@@ -299,6 +637,17 @@ static void cp_f1_served_cell_info_to_cell(nr_rrc_cell_container_t *dst, const f
}
}
+static void add_si_msg(served_cells_to_activate_t *cell, int sib_type, const byte_array_t *enc)
+{
+ AssertFatal(cell->num_SI < F1AP_MAX_NO_SIB_TYPES,
+ "Too many SI messages (%u), max supported is %u\n",
+ cell->num_SI,
+ F1AP_MAX_NO_SIB_TYPES);
+ cell->SI_msg[cell->num_SI].SI_container = copy_byte_array(*enc);
+ cell->SI_msg[cell->num_SI].SI_type = sib_type;
+ cell->num_SI++;
+}
+
void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id)
{
AssertFatal(assoc_id != 0, "illegal assoc_id == 0: should be -1 (monolithic) or >0 (split)\n");
@@ -427,16 +776,68 @@ void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id)
// Encode CU SIBs and configure setup response with sysinfo
seq_arr_t *sibs = rrc->SIBs;
if (sibs) {
- for (int i = 0; i < sibs->size; i++) {
- nr_SIBs_t *sib = (nr_SIBs_t *)seq_arr_at(sibs, i);
+ FOR_EACH_SEQ_ARR (nr_SIBs_t *, sib, sibs) {
switch (sib->SIB_type) {
- case 2: {
+ case NR_SIB_2: {
NR_SSB_MTC_t *ssbmtc = get_ssb_mtc(new->mtc);
- sib->SIB_size = do_SIB2_NR(&sib->SIB_buffer, ssbmtc);
- cell.SI_msg[cell.num_SI].SI_container = sib->SIB_buffer;
- cell.SI_msg[cell.num_SI].SI_container_length = sib->SIB_size;
- cell.SI_msg[cell.num_SI].SI_type = sib->SIB_type;
- cell.num_SI++;
+ NR_SIB2_t *sib2 = get_sib2_from_cfg(&rrc->sib2_config, ssbmtc);
+ byte_array_t enc = do_SIB2_NR(sib2);
+ ASN_STRUCT_FREE(asn_DEF_NR_SIB2, sib2);
+ if (!enc.buf || enc.len == 0) {
+ free_byte_array(enc);
+ LOG_E(NR_RRC, "SIB2 encoding failed\n");
+ break;
+ }
+ add_si_msg(&cell, sib->SIB_type, &enc);
+ free_byte_array(enc);
+ LOG_I(NR_RRC, "DU %ld: added SIB2 to F1 Setup Response (cell %ld)\n", du->gNB_DU_id, new->info.cell_id);
+ } break;
+ case NR_SIB_3: {
+ if (!rrc->neighbour_cell_configuration)
+ break;
+ const neighbour_cell_configuration_t *neighbour_config = get_cell_neighbour_list(rrc, new);
+ if (!neighbour_config)
+ break;
+ const seq_arr_t *neigh_cells = &neighbour_config->neighbour_cells;
+
+ NR_SIB3_t *sib3 = get_sib3_intra_freq_neighbors(neigh_cells, get_ssb_arfcn(new));
+ if (!sib3)
+ break;
+
+ byte_array_t enc = do_SIB3_NR(sib3);
+ ASN_STRUCT_FREE(asn_DEF_NR_SIB3, sib3);
+ if (!enc.buf || enc.len == 0) {
+ free_byte_array(enc);
+ LOG_E(NR_RRC, "SIB3 encoding failed\n");
+ break;
+ }
+ add_si_msg(&cell, sib->SIB_type, &enc);
+ free_byte_array(enc);
+ LOG_I(NR_RRC, "DU %ld: added SIB3 to F1 Setup Response (cell %ld)\n", du->gNB_DU_id, new->info.cell_id);
+ } break;
+ case NR_SIB_4: {
+ if (!rrc->neighbour_cell_configuration)
+ break;
+ const neighbour_cell_configuration_t *neighbour_cfg = get_cell_neighbour_list(rrc, new);
+ if (!neighbour_cfg)
+ break;
+
+ NR_SIB4_t *sib4 = get_sib4_inter_freq_neighbors(neighbour_cfg, &rrc->inter_freqs, get_ssb_arfcn(new));
+ if (!sib4) {
+ LOG_W(NR_RRC, "SIB4: could not build from neighbours, skipping\n");
+ break;
+ }
+
+ byte_array_t enc = do_SIB4_NR(sib4);
+ ASN_STRUCT_FREE(asn_DEF_NR_SIB4, sib4);
+ if (!enc.buf || enc.len == 0) {
+ free_byte_array(enc);
+ LOG_E(NR_RRC, "SIB4 encoding failed\n");
+ break;
+ }
+ add_si_msg(&cell, sib->SIB_type, &enc);
+ free_byte_array(enc);
+ LOG_I(NR_RRC, "DU %ld: added SIB4 to F1 Setup Response (cell %ld)\n", du->gNB_DU_id, new->info.cell_id);
} break;
default:
AssertFatal(false, "SIB%d not handled yet\n", sib->SIB_type);
@@ -444,9 +845,6 @@ void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id)
}
}
- if (new->mib != NULL &&new->sib1 != NULL)
- label_intra_frequency_neighbours(rrc, new);
-
resp.cells_to_activate[i] = cell;
}
@@ -662,10 +1060,6 @@ void rrc_gNB_process_f1_du_configuration_update(f1ap_gnb_du_configuration_update
LOG_I(NR_RRC, "update system information of DU %ld\n", du->gNB_DU_id);
}
}
-
- if (cell && cell->mib != NULL && cell->sib1 != NULL && cell->assoc_id == du->assoc_id) {
- label_intra_frequency_neighbours(rrc, cell);
- }
}
if (conf_up->num_cells_to_delete > 0) {
diff --git a/openair2/RRC/NR/rrc_gNB_mobility.c b/openair2/RRC/NR/rrc_gNB_mobility.c
index e36e6ee684..fdbc2d66af 100644
--- a/openair2/RRC/NR/rrc_gNB_mobility.c
+++ b/openair2/RRC/NR/rrc_gNB_mobility.c
@@ -607,7 +607,6 @@ void nr_HO_N2_trigger_telnet(gNB_RRC_INST *rrc, uint32_t neighbour_pci, uint32_t
if (neighbour_pci == scell_pci) {
LOG_I(NR_RRC, "UE %d: trigger handover on the same cell PCI=%d\n", rrc_ue_id, neighbour_pci);
nr_neighbour_cell_t neighbourConfig = {
- .isIntraFrequencyNeighbour = true,
.gNB_ID = du->gNB_DU_id,
.nrcell_id = pcell->info.cell_id,
.physicalCellId = pcell->info.pci,
diff --git a/openair2/RRC/NR_UE/L2_interface_ue.c b/openair2/RRC/NR_UE/L2_interface_ue.c
index b0b3b501cd..0133f81e03 100644
--- a/openair2/RRC/NR_UE/L2_interface_ue.c
+++ b/openair2/RRC/NR_UE/L2_interface_ue.c
@@ -155,6 +155,13 @@ void process_msg_rcc_to_mac(nr_mac_rrc_message_t *msg, int instance_id)
}
}
+void nr_mac_rrc_verification_failed(const module_id_t mod_id)
+{
+ MessageDef *message_p = itti_alloc_new_message(TASK_MAC_UE, 0, NR_RRC_MAC_VERIFY);
+ NR_RRC_MAC_VERIFY (message_p).L2_RRC_verification_failed = true;
+ itti_send_msg_to_task(TASK_RRC_NRUE, GNB_MODULE_ID_TO_INSTANCE(mod_id), message_p);
+}
+
void nr_mac_rrc_inactivity_timer_ind(const module_id_t mod_id)
{
MessageDef *message_p = itti_alloc_new_message(TASK_MAC_UE, 0, NR_RRC_MAC_INAC_IND);
diff --git a/openair2/RRC/NR_UE/L2_interface_ue.h b/openair2/RRC/NR_UE/L2_interface_ue.h
index 09c7b7daae..5121f0859e 100644
--- a/openair2/RRC/NR_UE/L2_interface_ue.h
+++ b/openair2/RRC/NR_UE/L2_interface_ue.h
@@ -30,5 +30,6 @@ void nr_mac_rrc_msg3_ind(const module_id_t mod_id, const int rnti, bool prepare_
void nr_ue_rrc_timer_trigger(int instance, int hfn, int frame, int gnb_id);
void nr_mac_rrc_ra_ind(const module_id_t mod_id, bool success);
void process_msg_rcc_to_mac(nr_mac_rrc_message_t *msg, int instance_id);
+void nr_mac_rrc_verification_failed(const module_id_t mod_id);
#endif
diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c
index 37bca1d45a..5f0fefdcff 100644
--- a/openair2/RRC/NR_UE/rrc_UE.c
+++ b/openair2/RRC/NR_UE/rrc_UE.c
@@ -24,6 +24,7 @@
#include "rrc_defs.h"
#include "rrc_proto.h"
+#include "verify_RRC.h"
#include "L2_interface_ue.h"
#include "LAYER2/NR_MAC_UE/mac_proto.h"
@@ -3115,6 +3116,11 @@ void *rrc_nrue(void *notUsed)
}
break;
+ case NR_RRC_MAC_VERIFY:
+ LOG_W(NR_RRC, "L2 verification of RRC consistency failed\n");
+ handle_rlf_detection(rrc);
+ break;
+
case NR_RRC_MAC_INAC_IND:
LOG_D(NR_RRC, "Received data inactivity indication from lower layers\n");
NR_Release_Cause_t release_cause = RRC_CONNECTION_FAILURE;
diff --git a/openair2/RRC/NR_UE/rrc_proto.h b/openair2/RRC/NR_UE/rrc_proto.h
index 5efd15306a..f4bf1b4e1e 100644
--- a/openair2/RRC/NR_UE/rrc_proto.h
+++ b/openair2/RRC/NR_UE/rrc_proto.h
@@ -72,7 +72,6 @@ void nr_rrc_ue_decode_NR_SBCCH_SL_BCH_Message(NR_UE_RRC_INST_t *rrc,
const uint16_t rx_slss_id);
void nr_rrc_set_mac_queue(instance_t instance, notifiedFIFO_t *mac_input_nf);
-bool check_cellgroup_config(const NR_CellGroupConfig_t *cgConfig);
/** @}*/
#endif
diff --git a/openair2/RRC/NR_UE/verify_RRC.c b/openair2/RRC/NR_UE/verify_RRC.c
index 9d5cd5d726..42d3204d27 100644
--- a/openair2/RRC/NR_UE/verify_RRC.c
+++ b/openair2/RRC/NR_UE/verify_RRC.c
@@ -188,7 +188,7 @@ static bool check_csi_resourceMapping_consistency(NR_CSI_RS_ResourceMapping_t re
return true;
}
-static bool check_csi_report_consistency(const NR_CSI_MeasConfig_t *meas)
+bool check_csi_report_consistency(const NR_CSI_MeasConfig_t *meas)
{
if (!meas || !meas->csi_ReportConfigToAddModList)
return true;
@@ -223,8 +223,6 @@ static bool check_csi_resource_consistency(const NR_CSI_MeasConfig_t *meas)
static bool check_csi_MeasConfig(struct NR_SetupRelease_CSI_MeasConfig *csi_MeasConfig)
{
const NR_CSI_MeasConfig_t *meas = csi_MeasConfig->choice.setup;
- if (!check_csi_report_consistency(meas))
- return false;
if (!check_csi_resource_consistency(meas))
return false;
return true;
diff --git a/openair2/RRC/NR_UE/verify_RRC.h b/openair2/RRC/NR_UE/verify_RRC.h
new file mode 100644
index 0000000000..e4de684402
--- /dev/null
+++ b/openair2/RRC/NR_UE/verify_RRC.h
@@ -0,0 +1,16 @@
+/*
+ * SPDX-License-Identifier: LicenseRef-CSSL-1.0
+ */
+
+/*
+ * \brief RRC functions prototypes for eNB and UE
+ */
+
+#ifndef _VERIFY_RRC_H_
+#define _VERIFY_RRC_H_
+
+#include "NR_MeasConfig.h"
+
+bool check_csi_report_consistency(const NR_CSI_MeasConfig_t *meas);
+bool check_cellgroup_config(const NR_CellGroupConfig_t *cgConfig);
+#endif
diff --git a/openair3/NGAP/ngap_gNB_handlers.c b/openair3/NGAP/ngap_gNB_handlers.c
index 754a2e2f86..78bc0b3de4 100644
--- a/openair3/NGAP/ngap_gNB_handlers.c
+++ b/openair3/NGAP/ngap_gNB_handlers.c
@@ -68,9 +68,17 @@ void ngap_handle_ng_setup_message(ngap_gNB_amf_data_t *amf_desc_p, int sctp_shut
}
}
} else {
+ if (amf_desc_p->t_reconnect != -1 && amf_desc_p->ngap_gNB_instance->ngap_amf_associated_nb > 0) {
+ timer_remove(amf_desc_p->t_reconnect);
+ amf_desc_p->t_reconnect = -1;
+ NGAP_INFO("reconnected to AMF\n");
+ }
+
/* Check that at least one setup message is pending */
- DevCheck(amf_desc_p->ngap_gNB_instance->ngap_amf_pending_nb > 0, amf_desc_p->ngap_gNB_instance->instance,
- amf_desc_p->ngap_gNB_instance->ngap_amf_pending_nb, 0);
+ DevCheck(amf_desc_p->ngap_gNB_instance->ngap_amf_pending_nb > 0,
+ amf_desc_p->ngap_gNB_instance->instance,
+ amf_desc_p->ngap_gNB_instance->ngap_amf_pending_nb,
+ 0);
if (amf_desc_p->ngap_gNB_instance->ngap_amf_pending_nb > 0) {
/* Decrease pending messages number */
diff --git a/openair3/NGAP/ngap_gNB_ue_context.c b/openair3/NGAP/ngap_gNB_ue_context.c
index 7555685afb..57856a890f 100644
--- a/openair3/NGAP/ngap_gNB_ue_context.c
+++ b/openair3/NGAP/ngap_gNB_ue_context.c
@@ -94,7 +94,7 @@ void ngap_release_ues_for_amf(ngap_gNB_amf_data_t *amf_desc_p)
0,
TASK_NGAP,
amf_desc_p->ngap_gNB_instance->instance,
- TIMER_ONE_SHOT,
+ TIMER_PERIODIC,
amf_desc_p,
&tid);
if (rc == 0) {
diff --git a/radio/ETHERNET/if_defs.h b/radio/ETHERNET/if_defs.h
index e357858137..9e5ec6818e 100644
--- a/radio/ETHERNET/if_defs.h
+++ b/radio/ETHERNET/if_defs.h
@@ -9,7 +9,7 @@
#include
#ifndef LITE_COMPILATION
-#include "PHY/LTE_TRANSPORT/if4_tools.h"
+#include "PHY/if4_tools.h"
#endif
// ETH transport preference modes
diff --git a/radio/fhi_72/oran_isolate.c b/radio/fhi_72/oran_isolate.c
index ed330ed30e..3a670f5f7f 100644
--- a/radio/fhi_72/oran_isolate.c
+++ b/radio/fhi_72/oran_isolate.c
@@ -12,6 +12,7 @@
#include "xran_sync_api.h"
#include "common/utils/LOG/log.h"
+#include "common/utils/fsn.h"
#include "openair1/PHY/defs_gNB.h"
#include "openair1/PHY/NR_TRANSPORT/nr_transport_proto.h"
#include "oaioran.h"
@@ -205,19 +206,21 @@ void oran_fh_if4p5_south_in(RU_t *ru, int *frame, int *slot)
.prach_buf = NULL,
};
- prach_item_t *prach_id = find_nr_prach(&ru->gNB_list[0]->prach_list, *frame, *slot, ru->nr_frame_parms->nb_antennas_rx, SEARCH_EXIST);
- if (prach_id) {
+ prach_item_t p;
+ PHY_VARS_gNB *gNB = ru->gNB_list[0];
+ fsn_t now = {.f = *frame, .s = *slot, .mu = gNB->frame_parms.numerology_index};
+ if (get_next_nr_prach(&gNB->prach_ru_queue, &now, &p)) {
struct xran_fh_config *fh_cfg = get_xran_fh_config(0);
int slots_per_subframe = 1 << fh_cfg->frame_conf.nNumerology;
uint32_t subframe = *slot / slots_per_subframe; // `slot` = slot in which PRACH is received
// PRACH occasion in a frame if and only if SFN % x == y, TS 38.211 Table 6.3.3.2-2/3/4
nr_prach_info_t prach_info = get_prach_info(0);
bool is_prach_frame = (*frame % prach_info.x == prach_info.y);
- bool is_prach_slot = is_prach_frame && xran_is_prach_slot(0, subframe, (prach_id->slot % slots_per_subframe)); // `prach_id->slot` = slot in which PRACH is scheduled
+ bool is_prach_slot = is_prach_frame && xran_is_prach_slot(0, subframe, (p.slot % slots_per_subframe)); // `p.slot` = slot in which PRACH is scheduled
if (is_prach_slot) {
- ru_info.prach_buf = prach_id->prach_buf;
+ ru_info.prach_buf = p.prach_buf;
} else {
- LOG_W(HW, "[%d.%d] Expected PRACH reception of scheduled slot %d\n", *frame, *slot, prach_id->slot);
+ LOG_W(HW, "[%d.%d] Expected PRACH reception of scheduled slot %d\n", *frame, *slot, p.slot);
}
}
@@ -232,6 +235,15 @@ void oran_fh_if4p5_south_in(RU_t *ru, int *frame, int *slot)
printf("ORAN: %d.%d ORAN_fh_if4p5_south_in ERROR in RX function \n", f, sl);
}
+ if (ru_info.prach_buf) {
+ // xran_fh_rx_read_slot() should have read PRACH, write back to queue
+ bool success = spsc_q_put(&gNB->prach_l1rx_queue, &p, sizeof(p));
+ // assume prach_l1rx_queue never full: prach_ru_queue filled at
+ // constant pace, but prach_l1rx_queue emptied as fast as possible,
+ // see rx_func()
+ DevAssert(success);
+ }
+
int slots_per_frame = 10 << (ru->openair0_cfg.nr_scs_for_raster);
proc->tti_rx = sl;
proc->frame_rx = f;
diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.redcap.yaml b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.redcap.yaml
index b5b5708811..735c15ca1c 100644
--- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.redcap.yaml
+++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.redcap.yaml
@@ -21,7 +21,7 @@ gNBs:
# Physical parameters:
do_CSIRS: 1
do_SRS: 1
- first_active_bwp: 1;
+ first_active_bwp: 1
bwp_list:
-
scs: 1
diff --git a/tools/cppcheck/README.md b/tools/cppcheck/README.md
new file mode 100644
index 0000000000..414f35a68a
--- /dev/null
+++ b/tools/cppcheck/README.md
@@ -0,0 +1,28 @@
+
+
+# Static code analysis
+
+How to run static code analysis tool(s).
+
+[[_TOC_]]
+
+## cppcheck Overview
+
+This can run a (dockerized) cppcheck static code analysis. The docker-compose
+file represents the status as run as in the CI until it's removal (because it
+was not enforced). It is now here so that people could use it to find bugs (and
+use the tool more easily).
+
+## cppcheck Usage
+
+From the openairinterface5g root, simply run
+
+ ./tools/cppcheck/run-cppcheck.sh
+
+This will run cppcheck with options listed in this file, assuming you have it
+installed. Alternatively, you can run the CI version as of Ubuntu 20 with
+
+ cd tools/cppcheck && docker compose up --no-log-prefix
+
+You can upgrade to a newer version by modifying the `FROM` line in the
+docker-compose file.
diff --git a/tools/cppcheck/docker-compose.yaml b/tools/cppcheck/docker-compose.yaml
new file mode 100644
index 0000000000..8b8c5878d0
--- /dev/null
+++ b/tools/cppcheck/docker-compose.yaml
@@ -0,0 +1,14 @@
+# SPDX-License-Identifier: MIT
+
+services:
+ cppcheck:
+ image: cppcheck
+ build:
+ dockerfile_inline: |
+ FROM ubuntu:focal
+ RUN DEBIAN_FRONTEND=noninteractive apt update && apt install -y cppcheck
+ volumes:
+ - ../../:/code/
+ command:
+ bash -c "cd /code/ && ./tools/cppcheck/run-cppcheck.sh"
+
diff --git a/tools/cppcheck/run-cppcheck.sh b/tools/cppcheck/run-cppcheck.sh
new file mode 100755
index 0000000000..5a5df0c752
--- /dev/null
+++ b/tools/cppcheck/run-cppcheck.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+# SPDX-License-Identifier: MIT
+
+cppcheck --enable=warning --force \
+ --inline-suppr \
+ --quiet \
+ -i openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c \
+ --suppressions-list=tools/cppcheck/suppressions.list \
+ -I common/utils \
+ -I openair3/NAS/COMMON/UTIL \
+ -j`nproc` .
diff --git a/ci-scripts/cppcheck_suppressions.list b/tools/cppcheck/suppressions.list
similarity index 100%
rename from ci-scripts/cppcheck_suppressions.list
rename to tools/cppcheck/suppressions.list