diff --git a/.vscode/launch.json b/.vscode/launch.json index 6757ed47f6..4b563febde 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -25,4 +25,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/ci-scripts/Jenkinsfile-gitlab b/ci-scripts/Jenkinsfile-gitlab index 9a6f363954..ff661543c0 100644 --- a/ci-scripts/Jenkinsfile-gitlab +++ b/ci-scripts/Jenkinsfile-gitlab @@ -38,6 +38,10 @@ def nodeExecutor = params.nodeExecutor // VM Lockable resources def vmResource = params.vmLockableResource +// Tags to shorten pipeline duration +def doMandatoryTests = false +def doFullTestsuite = false + pipeline { agent { label nodeExecutor @@ -46,31 +50,6 @@ pipeline { disableConcurrentBuilds() timestamps() gitLabConnection('OAI GitLab') - gitlabBuilds(builds: [ - "Build gNB-USRP", - "Build nr-UE-USRP", - "Build eNB-USRP", - "Build basic-sim", - "Build phy-sim", - "Build eNB-ethernet", - "Build UE-ethernet", - "Analysis with cppcheck", - "Test phy-sim", - "Test basic-sim", - "Test L1-sim", - "Test RF-sim", - "Test L2-sim", - "Test-Mono-FDD-Band7", - "Test-Mono-TDD-Band40", - "Test-IF4p5-FDD-Band7", - "Test-IF4p5-TDD-Band40", - "Test-Mono-FDD-Band13-LTE-M", - "Test-IF4p5-TDD-Band38-Multi-RRU", - "Test-eNB-OAI-UE-FDD-Band7", - "Test-Mono-FDD-Band13-X2-HO", - "Test-TDD-Band78-gNB-NR-UE", - "Test-OCP-FDD-Band7" - ]) ansiColor('xterm') } @@ -93,6 +72,33 @@ pipeline { if (fileExists("flexran")) { sh "rm -Rf flexran > /dev/null 2>&1" } + + echo '\u2705 \u001B[32mVerify Labels\u001B[0m' + if ("MERGE".equals(env.gitlabActionType)) { + LABEL_CHECK = sh returnStdout: true, script: 'ci-scripts/checkGitLabMergeRequestLabels.sh --mr-id ' + env.gitlabMergeRequestIid + LABEL_CHECK = LABEL_CHECK.trim() + if (LABEL_CHECK == 'NONE') { + def message = "OAI " + JOB_NAME + " build (" + BUILD_ID + "): Your merge request has none of the mandatory labels:\n\n" + message += " - BUILD-ONLY\n" + message += " - 4G-LTE\n" + message += " - 5G-NR\n" + message += " - CI\n\n" + message += "Not performing CI due to lack of labels" + addGitLabMRComment comment: message + error('Not performing CI due to lack of labels') + } else if (LABEL_CHECK == 'FULL') { + doMandatoryTests = true + doFullTestsuite = true + } else if (LABEL_CHECK == 'SHORTEN-5G') { + doMandatoryTests = true + } else { + def message = "OAI " + JOB_NAME + " build (" + BUILD_ID + "): We will perform only build stages on your Merge Request" + addGitLabMRComment comment: message + } + } else { + doMandatoryTests = true + doFullTestsuite = true + } } } } @@ -135,7 +141,7 @@ pipeline { // For the moment, there is no fail criteria. Just a notification of number of files that do not follow sh "./ci-scripts/checkCodingFormattingRules.sh" } - if (doFlexranCtrlTest) { + if (doFlexranCtrlTest && doMandatoryTests) { sh "mkdir flexran" dir ('flexran') { withCredentials([ @@ -375,6 +381,9 @@ pipeline { stage ("VM-based tests") { stages { stage ("Test physical simulators") { + when { + expression {doMandatoryTests} + } steps { lock (vmResource) { script { @@ -393,7 +402,7 @@ pipeline { } stage ("Build Flexran Controller") { when { - expression {doFlexranCtrlTest} + expression {doFlexranCtrlTest && doMandatoryTests} } steps { lock (vmResource) { @@ -410,6 +419,9 @@ pipeline { } } stage ("Test basic simulator") { + when { + expression {doMandatoryTests} + } steps { lock (vmResource) { script { @@ -427,6 +439,9 @@ pipeline { } } stage ("Test L1 simulator") { + when { + expression {doMandatoryTests} + } steps { lock (vmResource) { script { @@ -444,6 +459,9 @@ pipeline { } } stage ("Test RF simulator") { + when { + expression {doMandatoryTests} + } steps { lock (vmResource) { script { @@ -461,6 +479,9 @@ pipeline { } } stage ("Test L2 simulator") { + when { + expression {doFullTestsuite} + } steps { lock (vmResource) { script { @@ -478,6 +499,9 @@ pipeline { } } stage ("Destroy all Virtual Machines") { + when { + expression {doMandatoryTests} + } steps { lock (vmResource) { sh "./ci-scripts/oai-ci-vm-tool destroy --job-name ${JOB_NAME} --build-id ${BUILD_ID}" @@ -487,6 +511,9 @@ pipeline { } } stage ("Test MONOLITHIC - FDD - Band 7 - B210") { + when { + expression {doFullTestsuite} + } steps { script { triggerSlaveJob ('eNB-CI-FDD-Band7-B210', 'Test-Mono-FDD-Band7') @@ -506,6 +533,9 @@ pipeline { } } stage ("Test MONOLITHIC - TDD - Band 40 - B210") { + when { + expression {doFullTestsuite} + } steps { script { triggerSlaveJob ('eNB-CI-TDD-Band40-B210', 'Test-Mono-TDD-Band40') @@ -525,6 +555,9 @@ pipeline { } } stage ("Test IF4p5 - FDD - Band 7 - B210") { + when { + expression {doFullTestsuite} + } steps { script { sh "sleep 60" @@ -545,6 +578,9 @@ pipeline { } } stage ("Test IF4p5 - TDD - Band 40 - B210") { + when { + expression {doFullTestsuite} + } steps { script { sh "sleep 60" @@ -565,6 +601,9 @@ pipeline { } } stage ("Test MONOLITHIC - FDD - Band 13 - B210") { + when { + expression {doFullTestsuite} + } steps { script { sh "sleep 60" @@ -585,6 +624,9 @@ pipeline { } } stage ("Test X2 Handover - FDD - Band 13 - B210") { + when { + expression {doFullTestsuite} + } steps { script { sh "sleep 60" @@ -605,6 +647,9 @@ pipeline { } } stage ("Test IF4p5 - TDD - Band 38 - B210 - MultiRRU") { + when { + expression {doFullTestsuite} + } steps { script { triggerSlaveJob ('eNB-CI-IF4p5-TDD-Band38-MultiRRU-B210', 'Test-IF4p5-TDD-Band38-Multi-RRU') @@ -624,6 +669,9 @@ pipeline { } } stage ("Test OAI UE - FDD - Band 20 - B200") { + when { + expression {doFullTestsuite} + } steps { script { triggerSlaveJobNoGitLab ('UE-CI-FDD-Band20-B200') @@ -643,6 +691,9 @@ pipeline { } } stage ("Test OAI UE - OAI eNB - FDD - Band 7 - B200") { + when { + expression {doFullTestsuite} + } steps { script { // Delayed trigger on slave job, so it is always the last one to run @@ -664,6 +715,9 @@ pipeline { } } stage ("Test OAI NR UE - OAI gNB - TDD - Band 78 - N300") { + when { + expression {doMandatoryTests} + } steps { script { triggerSlaveJob ('gNB-nrUE-MONO-TDD-Band78-N300', 'Test-TDD-Band78-gNB-NR-UE') @@ -683,6 +737,9 @@ pipeline { } } stage ("Test OAI OCP-eNB - FDD - Band 7 - B210") { + when { + expression {doFullTestsuite} + } steps { script { triggerSlaveJob ('OCPeNB-FDD-Band7-B210', 'Test-OCP-FDD-Band7') @@ -705,6 +762,7 @@ pipeline { post { always { script { + if (doMandatoryTests) { dir ('archives') { sh "if [ -d basic_sim/test ] || [ -d phy_sim/test ] || [ -d l2_sim/test ]; then zip -r -qq vm_tests_logs.zip */test ; fi" } @@ -720,6 +778,7 @@ pipeline { archiveArtifacts artifacts: 'test_simulator_results.html' } } + } } } } diff --git a/ci-scripts/checkGitLabMergeRequestLabels.sh b/ci-scripts/checkGitLabMergeRequestLabels.sh new file mode 100755 index 0000000000..7e4ea1c7de --- /dev/null +++ b/ci-scripts/checkGitLabMergeRequestLabels.sh @@ -0,0 +1,108 @@ +#!/bin/bash +#/* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (the "License"); you may not use this file +# * except in compliance with the License. +# * You may obtain a copy of the License at +# * +# * http://www.openairinterface.org/?page_id=698 +# * +# * Unless required by applicable law or agreed to in writing, software +# * distributed under the License is distributed on an "AS IS" BASIS, +# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# * See the License for the specific language governing permissions and +# * limitations under the License. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ + +function usage { + echo "OAI GitLab merge request applying script" + echo " Original Author: Raphael Defosseux" + echo "" + echo "Usage:" + echo "------" + echo "" + echo " checkGitLabMergeRequestLabels.sh [OPTIONS]" + echo "" + echo "Options:" + echo "------------------" + echo "" + echo " --mr-id ####" + echo " Specify the ID of the merge request." + echo "" + echo " --help OR -h" + echo " Print this help message." + echo "" +} + +if [ $# -ne 2 ] && [ $# -ne 1 ] +then + echo "Syntax Error: not the correct number of arguments" + echo "" + usage + exit 1 +fi + +while [[ $# -gt 0 ]] +do +key="$1" + +case $key in + -h|--help) + shift + usage + exit 0 + ;; + --mr-id) + MERGE_REQUEST_ID="$2" + shift + shift + ;; + *) + echo "Syntax Error: unknown option: $key" + echo "" + usage + exit 1 +esac +done + +LABELS=`curl --silent "https://gitlab.eurecom.fr/api/v4/projects/oai%2Fopenairinterface5g/merge_requests/$MERGE_REQUEST_ID" | jq '.labels' || true` + +IS_MR_BUILD_ONLY=`echo $LABELS | grep -c BUILD-ONLY || true` +IS_MR_CI=`echo $LABELS | grep -c CI || true` +IS_MR_4G=`echo $LABELS | grep -c 4G-LTE || true` +IS_MR_5G=`echo $LABELS | grep -c 5G-NR || true` + +# First case: none is present! No CI +if [ $IS_MR_BUILD_ONLY -eq 0 ] && [ $IS_MR_CI -eq 0 ] && [ $IS_MR_4G -eq 0 ] && [ $IS_MR_5G -eq 0 ] +then + echo "NONE" + exit 0 +fi + +# Second case: Build-Only +if [ $IS_MR_BUILD_ONLY -eq 1 ] +then + echo "BUILD-ONLY" + exit 0 +fi + +# Third case: CI or 4G label --> Full CI run +if [ $IS_MR_4G -eq 1 ] || [ $IS_MR_CI -eq 1 ] +then + echo "FULL" + exit 0 +fi + +# Fourth case: 5G label +if [ $IS_MR_BUILD_ONLY -eq 0 ] && [ $IS_MR_CI -eq 0 ] && [ $IS_MR_4G -eq 0 ] && [ $IS_MR_5G -eq 1 ] +then + echo "SHORTEN-5G" + exit 0 +fi + diff --git a/ci-scripts/conf_files/gnb.band78.tm1.fr1.106PRB.usrpb210.conf b/ci-scripts/conf_files/gnb.band78.tm1.fr1.106PRB.usrpb210.conf index 259a2466ad..258618e7f0 100644 --- a/ci-scripts/conf_files/gnb.band78.tm1.fr1.106PRB.usrpb210.conf +++ b/ci-scripts/conf_files/gnb.band78.tm1.fr1.106PRB.usrpb210.conf @@ -1,7 +1,6 @@ Active_gNBs = ( "gNB-Eurecom-5GNRBox"); # Asn1_verbosity, choice in: none, info, annoying Asn1_verbosity = "none"; -Num_Threads_PUSCH = 8 gNBs = @@ -251,6 +250,7 @@ L1s = ( { num_cc = 1; tr_n_preference = "local_mac"; + pusch_proc_threads = 8; } ); diff --git a/ci-scripts/xml_files/gnb_nr_ue_usrp_run.xml b/ci-scripts/xml_files/gnb_nr_ue_usrp_run.xml index ed134f478c..b1e9697be2 100644 --- a/ci-scripts/xml_files/gnb_nr_ue_usrp_run.xml +++ b/ci-scripts/xml_files/gnb_nr_ue_usrp_run.xml @@ -52,7 +52,7 @@ Initialize_OAI_UE Initialize NR UE USRP - --phy-test --usrp-args "addr=192.168.30.2,second_addr=192.168.50.2,clock_source=external,time_source=external" --ue-rxgain 75 --rrc_config_path . --dlsch-parallel 4 + --phy-test --usrp-args "addr=192.168.30.2,second_addr=192.168.50.2,clock_source=external,time_source=external" --ue-rxgain 50 --rrc_config_path . --dlsch-parallel 4 NR diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index edd3e3fa52..49330ddc92 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -485,7 +485,6 @@ add_custom_target ( add_library(NR_RRC_LIB ${nr_rrc_h} ${nr_rrc_source} ${OPENAIR2_DIR}/RRC/NR/MESSAGES/asn1_msg.c - ${OPENAIR2_DIR}/RRC/NR/nr_ngap_gNB.c ) add_dependencies(NR_RRC_LIB nr_rrc_flag) include_directories ("${NR_RRC_FULL_DIR}") @@ -1969,6 +1968,7 @@ set(NR_PDCP_SRC ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_ue_manager.c ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_entity.c ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_entity_drb_am.c + ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_security_nea2.c ${OPENAIR2_DIR}/LAYER2/nr_pdcp/asn1_utils.c ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_entity_srb.c ) @@ -2112,10 +2112,10 @@ set (MAC_NR_SRC_UE ${NR_UE_MAC_DIR}/mac_vars.c ${NR_UE_MAC_DIR}/main_ue_nr.c ${NR_UE_MAC_DIR}/nr_ue_procedures.c + ${NR_UE_MAC_DIR}/nr_ue_scheduler.c ${NR_UE_MAC_DIR}/nr_ue_dci_configuration.c ${NR_UE_MAC_DIR}/nr_l1_helpers.c ${NR_UE_MAC_DIR}/nr_ra_procedures.c - ${NR_UE_MAC_DIR}/rar_tools_nrUE.c ) set (ENB_APP_SRC @@ -2135,7 +2135,23 @@ set (MCE_APP_SRC ${OPENAIR2_DIR}/MCE_APP/mce_app.c ${OPENAIR2_DIR}/MCE_APP/mce_config.c ) +set (MISC_NFAPI_LTE + ${OPENAIR1_DIR}/SCHED/nfapi_lte_dummy.c + ) + +add_library(MISC_NFAPI_LTE_LIB + ${MISC_NFAPI_LTE} + ) + +set (MISC_NFAPI_NR + ${OPENAIR1_DIR}/SCHED/nfapi_nr_dummy.c + ) + + +add_library(MISC_NFAPI_NR_LIB + ${MISC_NFAPI_NR} + ) add_library(L2 ${L2_SRC} ${MAC_SRC} @@ -2888,7 +2904,7 @@ add_dependencies(lte-softmodem rrc_flag s1ap_flag x2_flag oai_iqplayer) target_link_libraries (lte-softmodem -Wl,--start-group RRC_LIB NR_RRC_LIB S1AP_LIB S1AP_ENB F1AP_LIB F1AP M2AP_LIB M2AP_ENB X2AP_LIB X2AP_ENB M3AP_LIB M3AP_ENB GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT MME_APP UDP SCHED_LIB SCHED_RU_LIB - PHY_COMMON PHY PHY_RU LFDS L2 L2_LTE NFAPI_COMMON_LIB NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB LFDS7 + PHY_COMMON PHY PHY_RU LFDS L2 L2_LTE NFAPI_COMMON_LIB NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB MISC_NFAPI_LTE_LIB LFDS7 ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${FLEXRAN_AGENT_LIB} ${FSPT_MSG_LIB} ${PROTO_AGENT_LIB} -Wl,--end-group z dl) @@ -2929,7 +2945,7 @@ add_dependencies(ocp-enb rrc_flag s1ap_flag x2_flag oai_iqplayer coding params_l target_link_libraries (ocp-enb -Wl,--start-group RRC_LIB NR_RRC_LIB S1AP_LIB S1AP_ENB F1AP_LIB F1AP M2AP_LIB M2AP_ENB X2AP_LIB X2AP_ENB M3AP_LIB M3AP_ENB GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT MME_APP UDP SCHED_LIB SCHED_RU_LIB - PHY_COMMON PHY PHY_RU LFDS L2 L2_LTE NFAPI_COMMON_LIB NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB LFDS7 SIMU_COMMON + PHY_COMMON PHY PHY_RU LFDS L2 L2_LTE NFAPI_COMMON_LIB NFAPI_LIB MISC_NFAPI_LTE_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB LFDS7 SIMU_COMMON ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${FLEXRAN_AGENT_LIB} ${FSPT_MSG_LIB} ${PROTO_AGENT_LIB} -Wl,--end-group z dl) target_link_libraries (ocp-enb ${LIBXML2_LIBRARIES} pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} sctp ${PROTOBUF_LIB} ${CMAKE_DL_LIBS} ${LIBYAML_LIBRARIES} ${LIB_LMS_LIBRARIES} ${T_LIB}) @@ -2999,7 +3015,7 @@ target_link_libraries (lte-uesoftmodem -Wl,--start-group RRC_LIB NR_RRC_LIB S1AP_LIB S1AP_ENB X2AP_LIB X2AP_ENB M2AP_LIB M2AP_ENB M3AP_LIB M3AP_ENB F1AP F1AP_LIB GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT MME_APP UDP SCHED_RU_LIB SCHED_UE_LIB PHY_COMMON - PHY_UE PHY_RU LFDS L2_UE L2_LTE LFDS7 SIMU_COMMON SIMU NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB NFAPI_USER_LIB + PHY_UE PHY_RU LFDS L2_UE L2_LTE LFDS7 SIMU_COMMON SIMU NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB NFAPI_USER_LIB MISC_NFAPI_LTE_LIB ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${ATLAS_LIBRARIES} -Wl,--end-group z dl) @@ -3126,7 +3142,13 @@ target_link_libraries (nr-uesoftmodem -Wl,--start-group RRC_LIB NR_RRC_LIB NGAP_LIB NGAP_GNB SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT UDP SCHED_RU_LIB SCHED_UE_LIB SCHED_NR_UE_LIB PHY_COMMON PHY_NR_COMMON PHY_UE PHY_NR_UE PHY_RU LFDS NR_L2_UE L2_UE_LTE_NR MAC_NR_COMMON NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB +<<<<<<< HEAD NFAPI_USER_LIB S1AP_LIB S1AP_ENB ${PROTO_AGENT_LIB} ${FSPT_MSG_LIB} +======= + NFAPI_USER_LIB MISC_NFAPI_NR_LIB S1AP_LIB S1AP_ENB + ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} LFDS7 ${ATLAS_LIBRARIES} + NFAPI_USER_LIB S1AP_LIB S1AP_ENB +>>>>>>> origin/develop ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} LFDS7 ${ATLAS_LIBRARIES} LIB_5GNAS_GNB -Wl,--end-group z dl) diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml index 6d3424b420..089d0503fd 100644 --- a/cmake_targets/autotests/test_case_list.xml +++ b/cmake_targets/autotests/test_case_list.xml @@ -1292,7 +1292,9 @@ (Test8: DMRS Type B, 3 DMRS, 2 PTRS, 3 Interpolated Symbols), (Test9: SC-FDMA, 50 PRBs), (Test10: SC-FDMA, 75 PRBs), - (Test11: SC-FDMA, 3 DMRS) + (Test11: SC-FDMA, 216 PRBs), + (Test12: SC-FDMA, 273 PRBs), + (Test13: SC-FDMA, 3 DMRS) $OPENAIR_DIR/cmake_targets/build_oai --phy_simulators -c @@ -1307,10 +1309,13 @@ -n100 -s5 -T 2 1 2 -U 2 0 2 -n100 -s5 -T 2 2 2 -U 2 1 2 -n100 -s5 -a4 -b8 -T 2 1 2 -U 2 1 3 - -n100 -s20 -Z - -n100 -s20 -Z -r75 - -n100 -s20 -Z -U 2 0 2 - nr_ulsim.test1 nr_ulsim.test2 nr_ulsim.test3 nr_ulsim.test4 nr_ulsim.test5 nr_ulsim.test6 nr_ulsim.test7 nr_ulsim.test8 nr_ulsim.test9 nr_ulsim.test10 nr_ulsim.test11 + -n100 -s2 -Z + -n100 -s2 -Z -r75 + -n100 -s2 -Z -r216 -R217 + -n100 -s2 -Z -r270 -R273 + -n100 -s2 -Z -U 2 0 2 + + nr_ulsim.test1 nr_ulsim.test2 nr_ulsim.test3 nr_ulsim.test4 nr_ulsim.test5 nr_ulsim.test6 nr_ulsim.test7 nr_ulsim.test8 nr_ulsim.test9 nr_ulsim.test10 nr_ulsim.test11 nr_ulsim.test12 nr_ulsim.test13 PUSCH test OK segmentation fault|assertion|exiting|fatal 3 diff --git a/common/config/config_load_configmodule.c b/common/config/config_load_configmodule.c index 61a3984347..740c6e240b 100644 --- a/common/config/config_load_configmodule.c +++ b/common/config/config_load_configmodule.c @@ -43,7 +43,7 @@ #include "config_userapi.h" #include "../utils/LOG/log.h" #define CONFIG_SHAREDLIBFORMAT "libparams_%s.so" - +#include "nfapi/oai_integration/vendor_ext.h" int load_config_sharedlib(configmodule_interface_t *cfgptr) { void *lib_handle; @@ -331,9 +331,10 @@ void end_configmodule(void) { printf ("[CONFIG] free %u config value pointers\n",cfgptr->numptrs); for(int i=0; inumptrs ; i++) { - if (cfgptr->ptrs[i] != NULL) { + if (cfgptr->ptrs[i] != NULL && cfgptr->ptrsAllocated[i] == true) { free(cfgptr->ptrs[i]); cfgptr->ptrs[i]=NULL; + cfgptr->ptrsAllocated[i] = false; } } diff --git a/common/config/config_load_configmodule.h b/common/config/config_load_configmodule.h index d0309c62c3..8baaa99bb8 100644 --- a/common/config/config_load_configmodule.h +++ b/common/config/config_load_configmodule.h @@ -36,6 +36,8 @@ #include #include +#include +#include #include "common/config/config_paramdesc.h" #include "common/utils/T/T.h" #define CONFIG_MAX_OOPT_PARAMS 10 // maximum number of parameters in the -O option (-O :P1:P2... @@ -74,6 +76,7 @@ typedef struct configmodule_interface { uint32_t numptrs; uint32_t rtflags; char *ptrs[CONFIG_MAX_ALLOCATEDPTRS]; + bool ptrsAllocated[CONFIG_MAX_ALLOCATEDPTRS]; } configmodule_interface_t; #ifdef CONFIG_LOADCONFIG_MAIN diff --git a/common/config/config_userapi.c b/common/config/config_userapi.c index 33d6408828..af70cae71e 100644 --- a/common/config/config_userapi.c +++ b/common/config/config_userapi.c @@ -62,6 +62,7 @@ char *config_check_valptr(paramdef_t *cfgoptions, char **ptr, int length) { if ( (cfgoptions->paramflags & PARAMFLAG_NOFREE) == 0) { config_get_if()->ptrs[config_get_if()->numptrs] = (char *)ptr; + config_get_if()->ptrsAllocated[config_get_if()->numptrs] = true; config_get_if()->numptrs++; } } else { @@ -82,7 +83,9 @@ char *config_check_valptr(paramdef_t *cfgoptions, char **ptr, int length) { } if (*ptr == NULL) { - *ptr = malloc(length>40?length:40); // LTS: dummy fix, waiting Francois full fix in 4G branch + *ptr = malloc(length>40?length:40); + // LTS: dummy fix, waiting Francois full fix in 4G branch + // the issue is we don't know at this point the size we will get if ( *ptr != NULL) { memset(*ptr,0,length); diff --git a/common/config/libconfig/config_libconfig.c b/common/config/libconfig/config_libconfig.c index 2e9fd614c5..eb08a70183 100644 --- a/common/config/libconfig/config_libconfig.c +++ b/common/config/libconfig/config_libconfig.c @@ -346,6 +346,7 @@ int config_libconfig_init(char *cfgP[], int numP) { libconfig_privdata.configfile = strdup((char *)cfgP[0]); config_get_if()->numptrs=0; memset(config_get_if()->ptrs,0,sizeof(void *) * CONFIG_MAX_ALLOCATEDPTRS); + memset(config_get_if()->ptrsAllocated, 0, sizeof(config_get_if()->ptrsAllocated)); /* Read the file. If there is an error, report it and exit. */ if(! config_read_file(&(libconfig_privdata.cfg), libconfig_privdata.configfile)) { diff --git a/common/utils/LOG/log.c b/common/utils/LOG/log.c index 2340c78bf1..9fd67a6dbb 100644 --- a/common/utils/LOG/log.c +++ b/common/utils/LOG/log.c @@ -88,16 +88,19 @@ int write_file_matlab(const char *fname, void *data, int length, int dec, - char format) + unsigned int format) { FILE *fp=NULL; int i; + AssertFatal((format&~MATLAB_RAW) <16,""); + if (data == NULL) return -1; //printf("Writing %d elements of type %d to %s\n",length,format,fname); + if (format == 10 || format ==11 || format == 12 || format == 13 || format == 14) { fp = fopen(fname,"a+"); } else if (format != 10 && format !=11 && format != 12 && format != 13 && format != 14) { @@ -109,6 +112,32 @@ int write_file_matlab(const char *fname, return(-1); } + if ( (format&MATLAB_RAW) == MATLAB_RAW ) { + int sz[16]={sizeof(short), 2*sizeof(short), + sizeof(int), 2*sizeof(int), + sizeof(char), 2*sizeof(char), + sizeof(long long), + sizeof(double), 2*sizeof(double), + sizeof(unsigned char), + sizeof(short), + sizeof(short), + sizeof(short), + sizeof(short), + sizeof(short), + sizeof(short) + }; + int eltSz= sz[format&~MATLAB_RAW]; + if (dec==1) + fwrite(data, eltSz, length, fp); + else + for (i=0; i + + + + + + + + + Running L3 ITTI simulator + + + + +This page is valid on the following branches: + +- `develop` starting from tag `2020.w48` + +# 1. Building the ITTI simulator. + +The ITTI simulator is available directly from the standard build. + +```bash +$ source oaienv +$ cd cmake_targets +$ sudo ./build_oai -x -w None -c -ittiSIM +``` + +# 2. Running the ITTI simulator. + +The ITTI simulator establishes ITTI-threaded communication between the gNB RRC task and the UE RRC task. + +This allows to test the sequence of NGAP/RRC/NAS messages. + +The main limitations are: + +- NAS is a simple stub that just sends and receives messages +- only initial Attach sequence + +## 2.1. Starting the ITTI simulator + +The ITTI simulator is able to run with a connected 5GC or without any. +The develop branch tag `2020.w48` only works RRC without 5GC connection. + +```bash +$ sudo -E ./ran_build/build/nr-ittisim -O gnb.conf +``` + diff --git a/doc/SW_archi.md b/doc/SW_archi.md index 412dad402d..d92f802148 100644 --- a/doc/SW_archi.md +++ b/doc/SW_archi.md @@ -186,7 +186,7 @@ development], for FR2 does not exist yet. 3) allocate a CCE for the UE (and return if it is not possible) 4) Calculate DMRS stuff (nr_save_pusch_fields()) and the TBS. 5) Mark used resources in vrb_map_UL. -* loop through all users: get a free HARQ PID using select_ul_harq_pid() and +* loop through all users: get a free HARQ PID and update statistics. Fill nFAPI structures directly for PUSCH, and call config_uldci() and fill_dci_pdu_rel15() for DCI filling and PDCCH messages. diff --git a/executables/main-ocp.c b/executables/main-ocp.c index 39e7b558ac..ae1db7195b 100644 --- a/executables/main-ocp.c +++ b/executables/main-ocp.c @@ -74,6 +74,7 @@ int config_sync_var=-1; volatile int oai_exit = 0; double cpuf; uint16_t sf_ahead=4; +//uint16_t slot_ahead=6; int otg_enabled; uint64_t downlink_frequency[MAX_NUM_CCs][4]; int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c index be9261a117..cd1bfd14b6 100644 --- a/executables/nr-gnb.c +++ b/executables/nr-gnb.c @@ -84,7 +84,7 @@ #include "T.h" - +#include "nfapi/oai_integration/vendor_ext.h" //#define DEBUG_THREADS 1 //#define USRP_DEBUG 1 @@ -137,6 +137,7 @@ void wakeup_prach_gNB(PHY_VARS_gNB *gNB, RU_t *ru, int frame, int subframe); extern uint8_t nfapi_mode; extern void oai_subframe_ind(uint16_t sfn, uint16_t sf); +extern void oai_slot_ind(uint16_t sfn, uint16_t slot); extern void add_subframe(uint16_t *frameP, uint16_t *subframeP, int offset); //#define TICK_TO_US(ts) (ts.diff) @@ -151,13 +152,14 @@ static inline int rxtx(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int frame_t // ******************************************************************* // NFAPI not yet supported for NR - this code has to be revised - if (nfapi_mode == 1) { + if (NFAPI_MODE == NFAPI_MODE_PNF) { // I am a PNF and I need to let nFAPI know that we have a (sub)frame tick //add_subframe(&frame, &subframe, 4); //oai_subframe_ind(proc->frame_tx, proc->subframe_tx); //LOG_D(PHY, "oai_subframe_ind(frame:%u, subframe:%d) - NOT CALLED ********\n", frame, subframe); start_meas(&nfapi_meas); - oai_subframe_ind(frame_rx, slot_rx); + // oai_subframe_ind(frame_rx, slot_rx); + oai_slot_ind(frame_rx, slot_rx); stop_meas(&nfapi_meas); /*if (gNB->UL_INFO.rx_ind.rx_indication_body.number_of_pdus|| @@ -873,10 +875,7 @@ void init_gNB_proc(int inst) { gNB->threadPool = (tpool_t*)malloc(sizeof(tpool_t)); gNB->respDecode = (notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t)); int numCPU = sysconf(_SC_NPROCESSORS_ONLN); - uint32_t num_threads_pusch; - paramdef_t PUSCHThreads[] = NUM_THREADS_DESC; - config_get( PUSCHThreads,sizeof(PUSCHThreads)/sizeof(paramdef_t),NULL); - int threadCnt = min(numCPU, num_threads_pusch); + int threadCnt = min(numCPU, gNB->pusch_proc_threads); char ul_pool[80]; sprintf(ul_pool,"-1"); int s_offset = 0; diff --git a/executables/nr-ru.c b/executables/nr-ru.c index feff0c29c2..73421d8ed7 100644 --- a/executables/nr-ru.c +++ b/executables/nr-ru.c @@ -114,6 +114,7 @@ int attach_rru(RU_t *ru); int connect_rau(RU_t *ru); uint16_t sf_ahead; +uint16_t slot_ahead; uint16_t sl_ahead; extern int emulate_rf; diff --git a/executables/nr-softmodem-common.h b/executables/nr-softmodem-common.h index c968fee7b6..500819e684 100644 --- a/executables/nr-softmodem-common.h +++ b/executables/nr-softmodem-common.h @@ -77,6 +77,7 @@ #define CONFIG_HLP_UE "Set the lte softmodem as a UE\n" #define CONFIG_HLP_L2MONW "Enable L2 wireshark messages on localhost \n" #define CONFIG_HLP_L2MONP "Enable L2 pcap messages on localhost \n" +#define CONFIG_HLP_MAC "Disable the MAC procedures at UE side (default is enabled)\n" #define CONFIG_HLP_VCD "Enable VCD (generated file will is named openair_dump_eNB.vcd, read it with target/RT/USER/eNB.gtkw\n" #define CONFIG_HLP_TQFS "Apply three-quarter of sampling frequency, 23.04 Msps to reduce the data rate on USB/PCIe transfers (only valid for 20 MHz)\n" #define CONFIG_HLP_TPORT "tracer port\n" diff --git a/executables/nr-softmodem.c b/executables/nr-softmodem.c index 463c102d06..19491b4dfa 100644 --- a/executables/nr-softmodem.c +++ b/executables/nr-softmodem.c @@ -87,13 +87,13 @@ unsigned short config_frames[4] = {2,9,11,13}; #include "gnb_paramdef.h" #include "f1ap_cu_task.h" #include "f1ap_du_task.h" - +#include "nfapi/oai_integration/vendor_ext.h" pthread_cond_t nfapi_sync_cond; pthread_mutex_t nfapi_sync_mutex; int nfapi_sync_var=-1; //!< protected by mutex \ref nfapi_sync_mutex -uint8_t nfapi_mode = 0; // Default to monolithic mode +extern uint8_t nfapi_mode; // Default to monolithic mode pthread_cond_t sync_cond; pthread_mutex_t sync_mutex; @@ -836,7 +836,7 @@ if(!IS_SOFTMODEM_NOS1) nr_read_config_and_init(); } else { printf("No ITTI, Initializing L1\n"); - RCconfig_L1(); + RCconfig_NR_L1(); } if (RC.nb_nr_inst > 0) { @@ -874,7 +874,7 @@ if(!IS_SOFTMODEM_NOS1) usleep(1000); - if (nfapi_mode) { + if (NFAPI_MODE) { printf("NFAPI*** - mutex and cond created - will block shortly for completion of PNF connection\n"); pthread_cond_init(&sync_cond,NULL); pthread_mutex_init(&sync_mutex, NULL); @@ -882,7 +882,7 @@ if(!IS_SOFTMODEM_NOS1) const char *nfapi_mode_str = ""; - switch(nfapi_mode) { + switch(NFAPI_MODE) { case 0: nfapi_mode_str = "MONOLITHIC"; break; @@ -902,7 +902,7 @@ if(!IS_SOFTMODEM_NOS1) printf("NFAPI MODE:%s\n", nfapi_mode_str); - if (nfapi_mode==2) // VNF + if (NFAPI_MODE==NFAPI_MODE_VNF) wait_nfapi_init("main?"); printf("START MAIN THREADS\n"); @@ -931,10 +931,11 @@ if(!IS_SOFTMODEM_NOS1) config_sync_var=0; - if (nfapi_mode==1) { // PNF + if (NFAPI_MODE==NFAPI_MODE_PNF) { wait_nfapi_init("main?"); } + if (NODE_IS_DU(node_type) || (node_type == ngran_gNB)) { printf("wait RUs\n"); wait_RUs(); @@ -951,6 +952,13 @@ if(!IS_SOFTMODEM_NOS1) p.ru=RC.ru[0]; load_softscope("nr",&p); } + + if (NFAPI_MODE != NFAPI_MODE_PNF && NFAPI_MODE != NFAPI_MODE_VNF) { + printf("Not NFAPI mode - call init_eNB_afterRU()\n"); + init_eNB_afterRU(); + } else { + printf("NFAPI mode - DO NOT call init_gNB_afterRU()\n"); + } if (nfapi_mode != 1 && nfapi_mode != 2) { printf("Not NFAPI mode - call init_eNB_afterRU()\n"); diff --git a/executables/nr-ue.c b/executables/nr-ue.c index d744b6e780..6be23582b1 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -18,49 +18,16 @@ * For more information about the OpenAirInterface (OAI) Software Alliance: * contact@openairinterface.org */ -#include "executables/thread-common.h" + #include "executables/nr-uesoftmodem.h" - -#include "NR_MAC_UE/mac.h" -//#include "RRC/LTE/rrc_extern.h" -#include "PHY_INTERFACE/phy_interface_extern.h" - -#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all -//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all - -#include "fapi_nr_ue_l1.h" #include "PHY/phy_extern_nr_ue.h" #include "PHY/INIT/phy_init.h" -#include "PHY/MODULATION/modulation_UE.h" #include "NR_MAC_UE/mac_proto.h" #include "RRC/NR_UE/rrc_proto.h" - #include "SCHED_NR_UE/phy_frame_config_nr.h" #include "SCHED_NR_UE/defs.h" - #include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h" -#include "common/utils/LOG/log.h" -#include "common/utils/system.h" -#include "common/utils/LOG/vcd_signal_dumper.h" -#include "executables/nr-softmodem.h" - -#include "T.h" - -#ifdef XFORMS - #include "PHY/TOOLS/nr_phy_scope.h" - - extern char do_forms; -#endif - -// Missing stuff? -int next_ra_frame = 0; -module_id_t next_Mod_id = 0; - -extern double cpuf; -//static nfapi_nr_config_request_t config_t; -//static nfapi_nr_config_request_t* config =&config_t; - /* * NR SLOT PROCESSING SEQUENCE * @@ -124,16 +91,12 @@ extern double cpuf; #define DURATION_RX_TO_TX (6) /* For LTE, this duration is fixed to 4 and it is linked to LTE standard for both modes FDD/TDD */ #endif -#define FRAME_PERIOD 100000000ULL -#define DAQ_PERIOD 66667ULL - typedef enum { - pss=0, - pbch=1, - si=2 + pss = 0, + pbch = 1, + si = 2 } sync_mode_t; - void init_nr_ue_vars(PHY_VARS_NR_UE *ue, uint8_t UE_id, uint8_t abstraction_flag) @@ -258,7 +221,7 @@ static void UE_synch(void *arg) { double rx_gain_off = 0; nr_get_carrier_frequencies(&UE->frame_parms, &dl_carrier, &ul_carrier); - if (nr_initial_sync( &syncD->proc, UE, UE->mode,2) == 0) { + if (nr_initial_sync(&syncD->proc, UE, 2) == 0) { freq_offset = UE->common_vars.freq_offset; // frequency offset computed with pss in initial sync hw_slot_offset = ((UE->rx_offset<<1) / UE->frame_parms.samples_per_subframe * UE->frame_parms.slots_per_subframe) + round((float)((UE->rx_offset<<1) % UE->frame_parms.samples_per_subframe)/UE->frame_parms.samples_per_slot0); @@ -394,26 +357,17 @@ void processSlotRX( PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc) { if(UE->if_inst != NULL && UE->if_inst->dl_indication != NULL) { nr_downlink_indication_t dl_indication; - memset((void*)&dl_indication, 0, sizeof(dl_indication)); - - dl_indication.module_id = UE->Mod_id; - dl_indication.gNB_index = gNB_id; - dl_indication.cc_id = UE->CC_id; - dl_indication.frame = proc->frame_rx; - dl_indication.slot = proc->nr_slot_rx; - dl_indication.thread_id = proc->thread_id; - + nr_fill_dl_indication(&dl_indication, NULL, NULL, proc, UE, gNB_id); UE->if_inst->dl_indication(&dl_indication, NULL); } // Process Rx data for one sub-frame #ifdef UE_SLOT_PARALLELISATION - phy_procedures_slot_parallelization_nrUE_RX( UE, proc, 0, 0, 1, UE->mode, no_relay, NULL ); + phy_procedures_slot_parallelization_nrUE_RX( UE, proc, 0, 0, 1, no_relay, NULL ); #else uint64_t a=rdtsc(); - phy_procedures_nrUE_RX( UE, proc, 0, UE->mode,get_nrUE_params()->nr_dlsch_parallel); - LOG_D(PHY,"phy_procedures_nrUE_RX: slot:%d, time %lu\n", proc->nr_slot_rx, (rdtsc()-a)/3500); - //printf(">>> nr_ue_pdcch_procedures ended\n"); + phy_procedures_nrUE_RX(UE, proc, gNB_id, get_nrUE_params()->nr_dlsch_parallel); + LOG_D(PHY, "In %s: slot %d, time %lu\n", __FUNCTION__, proc->nr_slot_rx, (rdtsc()-a)/3500); #endif if(IS_SOFTMODEM_NOS1){ @@ -424,23 +378,6 @@ void processSlotRX( PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc) { } } - // no UL for now - /* - if (UE->mac_enabled==1) { - // trigger L2 to run ue_scheduler thru IF module - // [TODO] mapping right after NR initial sync - if(UE->if_inst != NULL && UE->if_inst->ul_indication != NULL) { - UE->ul_indication.module_id = 0; - UE->ul_indication.gNB_index = 0; - UE->ul_indication.cc_id = 0; - UE->ul_indication.frame = proc->frame_rx; - UE->ul_indication.slot = proc->nr_slot_rx; - UE->ul_indication.thread_id = proc->thread_id; - UE->if_inst->ul_indication(&UE->ul_indication); - } - } - */ - } /*! @@ -705,8 +642,7 @@ void *UE_thread(void *arg) { UE->rx_offset_diff = computeSamplesShift(UE); readBlockSize=get_readBlockSize(slot_nr, &UE->frame_parms) - UE->rx_offset_diff; - writeBlockSize=UE->frame_parms.get_samples_per_slot((slot_nr + DURATION_RX_TO_TX - RX_NB_TH) % nb_slot_frame, &UE->frame_parms)- - UE->rx_offset_diff; + writeBlockSize=UE->frame_parms.get_samples_per_slot((slot_nr + DURATION_RX_TO_TX - RX_NB_TH) % nb_slot_frame, &UE->frame_parms)- UE->rx_offset_diff; } AssertFatal(readBlockSize == @@ -765,14 +701,28 @@ void *UE_thread(void *arg) { timing_advance = UE->timing_advance; } - AssertFatal( writeBlockSize == - UE->rfdevice.trx_write_func(&UE->rfdevice, - writeTimestamp, - txp, - writeBlockSize, - UE->frame_parms.nb_antennas_tx, - 1),""); + int flags = 0; + int slot_tx_usrp = slot_nr + DURATION_RX_TO_TX - RX_NB_TH; + uint8_t tdd_period = mac->phy_config.config_req.tdd_table.tdd_period_in_slots; + uint8_t num_UL_slots = mac->scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots + + (mac->scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols!=0); + uint8_t first_tx_slot = tdd_period - num_UL_slots; + if (slot_tx_usrp%tdd_period==first_tx_slot) + flags=2; + else if (slot_tx_usrp%tdd_period==first_tx_slot+num_UL_slots-1) + flags = 3; + else if (slot_tx_usrp%tdd_period>first_tx_slot) + flags = 1; + if (flags || IS_SOFTMODEM_RFSIM) + AssertFatal( writeBlockSize == + UE->rfdevice.trx_write_func(&UE->rfdevice, + writeTimestamp, + txp, + writeBlockSize, + UE->frame_parms.nb_antennas_tx, + flags),""); + for (int i=0; iframe_parms.nb_antennas_tx; i++) memset(txp[i], 0, writeBlockSize); @@ -780,7 +730,7 @@ void *UE_thread(void *arg) { msgToPush->key=slot_nr; pushTpool(&(get_nrUE_params()->Tpool), msgToPush); - if ( IS_SOFTMODEM_RFSIM || IS_SOFTMODEM_NOS1) { //getenv("RFSIMULATOR") + if (IS_SOFTMODEM_RFSIM) { //getenv("RFSIMULATOR") // FixMe: Wait previous thread is done, because race conditions seems too bad // in case of actual RF board, the overlap between threads mitigate the issue // We must receive one message, that proves the slot processing is done diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c index 275f199900..814bb39e84 100644 --- a/executables/nr-uesoftmodem.c +++ b/executables/nr-uesoftmodem.c @@ -298,7 +298,6 @@ void set_options(int CC_id, PHY_VARS_NR_UE *UE){ tx_gain[0][CC_id] = tx_gain[0][0]; // Set UE variables - UE->rx_total_gain_dB = (int)rx_gain[CC_id][0] + rx_gain_off; UE->tx_total_gain_dB = (int)tx_gain[CC_id][0]; UE->tx_power_max_dBm = tx_max_power[CC_id]; @@ -576,22 +575,15 @@ int main( int argc, char **argv ) { init_NR_UE_threads(1); - config_check_unknown_cmdlineopt(CONFIG_CHECKALLSECTIONS); printf("UE threads created by %ld\n", gettid()); // wait for end of program printf("TYPE TO TERMINATE\n"); - protocol_ctxt_t ctxt_pP = {0}; - ctxt_pP.enb_flag = ENB_FLAG_NO; - ctxt_pP.rnti = 0x1234; - RC.nrrrc = (gNB_RRC_INST **)malloc(1*sizeof(gNB_RRC_INST *)); - RC.nrrrc[0] = (gNB_RRC_INST*)malloc(sizeof(gNB_RRC_INST)); - RC.nrrrc[0]->node_type = ngran_gNB; - rrc_ue_generate_RRCSetupRequest(&ctxt_pP, 0); - if (create_tasks_nrue(1) < 0) { - printf("cannot create ITTI tasks\n"); - exit(-1); // need a softer mode - } + // Sleep a while before checking all parameters have been used + // Some are used directly in external threads, asynchronously + sleep(20); + config_check_unknown_cmdlineopt(CONFIG_CHECKALLSECTIONS); + while(true) sleep(3600); diff --git a/executables/nr-uesoftmodem.h b/executables/nr-uesoftmodem.h index de5aa377fc..5902c8cca8 100644 --- a/executables/nr-uesoftmodem.h +++ b/executables/nr-uesoftmodem.h @@ -50,15 +50,15 @@ {"ue-rxgain", CONFIG_HLP_UERXG, 0, dblptr:&(rx_gain[0][0]), defdblval:0, TYPE_DOUBLE, 0}, \ {"ue-rxgain-off", CONFIG_HLP_UERXGOFF, 0, dblptr:&rx_gain_off, defdblval:0, TYPE_DOUBLE, 0}, \ {"ue-txgain", CONFIG_HLP_UETXG, 0, dblptr:&(tx_gain[0][0]), defdblval:0, TYPE_DOUBLE, 0}, \ - {"ue-nb-ant-rx", CONFIG_HLP_UENANTR, 0, u8ptr:&(fp->nb_antennas_rx), defuintval:1, TYPE_UINT8, 0}, \ - {"ue-nb-ant-tx", CONFIG_HLP_UENANTT, 0, u8ptr:&(fp->nb_antennas_tx), defuintval:1, TYPE_UINT8, 0}, \ + {"ue-nb-ant-rx", CONFIG_HLP_UENANTR, 0, u8ptr:&(fp->nb_antennas_rx), defuintval:1, TYPE_UINT8, 0}, \ + {"ue-nb-ant-tx", CONFIG_HLP_UENANTT, 0, u8ptr:&(fp->nb_antennas_tx), defuintval:1, TYPE_UINT8, 0}, \ {"ue-scan-carrier", CONFIG_HLP_UESCAN, PARAMFLAG_BOOL, iptr:&(UE->UE_scan_carrier), defintval:0, TYPE_INT, 0}, \ {"ue-fo-compensation", CONFIG_HLP_UEFO, PARAMFLAG_BOOL, iptr:&(UE->UE_fo_compensation), defintval:0, TYPE_INT, 0}, \ {"ue-max-power", NULL, 0, iptr:&(tx_max_power[0]), defintval:90, TYPE_INT, 0}, \ {"r" , CONFIG_HLP_PRB, 0, iptr:&(fp->N_RB_DL), defintval:25, TYPE_UINT, 0}, \ - {"A" , CONFIG_HLP_TADV, 0, iptr:&(UE->timing_advance), defintval:0, TYPE_INT, 0}, \ + {"A" , CONFIG_HLP_TADV, 0, iptr:&(UE->timing_advance), defintval:0, TYPE_INT, 0}, \ {"E" , CONFIG_HLP_TQFS, PARAMFLAG_BOOL, u8ptr:&(fp->threequarter_fs), defintval:0, TYPE_UINT8, 0}, \ - {"T" , CONFIG_HLP_TDD, PARAMFLAG_BOOL, iptr:&tddflag, defintval:0, TYPE_INT, 0}, \ + {"T" , CONFIG_HLP_TDD, PARAMFLAG_BOOL, iptr:&tddflag, defintval:0, TYPE_INT, 0}, \ {"ue-timing-correction-disable", CONFIG_HLP_DISABLETIMECORR, PARAMFLAG_BOOL, iptr:&(UE->no_timing_correction), defintval:0, TYPE_INT, 0}, \ } diff --git a/executables/softmodem-common.c b/executables/softmodem-common.c index 04a58413b5..1077c0e1ac 100644 --- a/executables/softmodem-common.c +++ b/executables/softmodem-common.c @@ -39,11 +39,14 @@ #include "executables/thread-common.h" #include "common/utils/LOG/log.h" #include "softmodem-common.h" +#include "nfapi/oai_integration/vendor_ext.h" + static softmodem_params_t softmodem_params; char *parallel_config=NULL; char *worker_config=NULL; +uint8_t nfapi_mode=0; static mapping softmodem_funcs[] = MAPPING_SOFTMODEM_FUNCTIONS; static struct timespec start; @@ -143,6 +146,7 @@ void get_common_options(uint32_t execmask) { if(parallel_config != NULL) set_parallel_conf(parallel_config); if(worker_config != NULL) set_worker_conf(worker_config); + nfapi_setmode(nfapi_mode); } void softmodem_printresources(int sig, telnet_printfunc_t pf) { struct rusage usage; diff --git a/executables/softmodem-common.h b/executables/softmodem-common.h index a6035122c0..60a761c732 100644 --- a/executables/softmodem-common.h +++ b/executables/softmodem-common.h @@ -91,6 +91,7 @@ extern "C" #define CONFIG_HLP_RFSIM "Run in rf simulator mode (also known as basic simulator)\n" #define CONFIG_HLP_NOKRNMOD "(noS1 only): Use tun instead of namesh module \n" #define CONFIG_HLP_DISABLNBIOT "disable nb-iot, even if defined in config\n" +#define CONFIG_HLP_NFAPI "Change the nFAPI mode for NR\n" /*-----------------------------------------------------------------------------------------------------------------------------------------------------*/ /* command line parameters common to eNodeB and UE */ @@ -112,6 +113,7 @@ extern "C" #define SEND_DMRSSYNC softmodem_params.send_dmrs_sync #define USIM_TEST softmodem_params.usim_test #define USE_256QAM_TABLE softmodem_params.use_256qam_table +#define NFAPI softmodem_params.nfapi #define DEFAULT_RFCONFIG_FILE "/usr/local/etc/syriq/ue.band7.tm1.PRB100.NR40.dat"; @@ -142,6 +144,7 @@ extern "C" {"nokrnmod", CONFIG_HLP_NOKRNMOD, PARAMFLAG_BOOL, uptr:&nokrnmod, defintval:0, TYPE_INT, 0}, \ {"nbiot-disable", CONFIG_HLP_DISABLNBIOT, PARAMFLAG_BOOL, uptr:&nonbiot, defuintval:0, TYPE_INT, 0}, \ {"use-256qam-table", CONFIG_HLP_256QAM, PARAMFLAG_BOOL, iptr:&USE_256QAM_TABLE, defintval:0, TYPE_INT, 0}, \ + {"nfapi", CONFIG_HLP_NFAPI, 0, u8ptr:&nfapi_mode, defintval:0, TYPE_UINT8, 0}, \ } @@ -229,6 +232,7 @@ typedef struct { int hw_timing_advance; uint32_t send_dmrs_sync; int use_256qam_table; + uint8_t nfapi; } softmodem_params_t; extern uint64_t get_softmodem_optmask(void); @@ -240,6 +244,7 @@ extern char *get_softmodem_function(uint64_t *sofmodemfunc_mask_ptr); extern void set_softmodem_sighandler(void); extern uint64_t downlink_frequency[MAX_NUM_CCs][4]; extern int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; +extern uint8_t nfapi_mode; #ifdef __cplusplus } #endif diff --git a/nfapi/CHANGES.md b/nfapi/CHANGES.md new file mode 100644 index 0000000000..4dc68c6ff8 --- /dev/null +++ b/nfapi/CHANGES.md @@ -0,0 +1,2 @@ +# Changelog + diff --git a/nfapi/nrNFAPI.md b/nfapi/nrNFAPI.md new file mode 100644 index 0000000000..299a43fd93 --- /dev/null +++ b/nfapi/nrNFAPI.md @@ -0,0 +1,35 @@ +# Procedure to run nFAPI in 5G NR + +## Conributed by 5G Testbed IISC +### Developers: Sudhakar B,Mahesh K,Gokul S,Aniq U.R + +## Procedure to Build gNB and UE + +The regular commands to build gNB and UE can be used +``` +sudo ./build_oai --gNB --UE + +``` +## Procedure to run NR nFAPI using RF-Simulator + +### VNF command +``` +sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band78.tm1.106PRB.nfapi.conf --nfapi 2 --noS1 --phy-test + +``` +### PNF command +``` +sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/oaiL1.nfapi.usrpx300.conf --nfapi 1 --rfsim --phy-test --rfsimulator.serveraddr server + +``` +### UE command +``` +sudo RFSIMULATOR=127.0.0.1 ./nr-uesoftmodem --rfsim --phy-test --rrc_config_path . -d + +``` +## Procedure to run NR nFAPI using Hardware +Will be updated as we have not yet currently tested on hardware + +## Notes +* In order to acheive the synchronization between VNF and PNF and receive the P7 messages within the timing window the order in which we should run the modules on different terminals is UE->VNF->PNF +* Currently only downlink is functional and working as we are still working on uplink functionality diff --git a/nfapi/oai_integration/nfapi_pnf.c b/nfapi/oai_integration/nfapi_pnf.c index 3dfbc2811d..4ca02ed929 100644 --- a/nfapi/oai_integration/nfapi_pnf.c +++ b/nfapi/oai_integration/nfapi_pnf.c @@ -30,6 +30,9 @@ #include "debug.h" #include "nfapi/oai_integration/vendor_ext.h" #include "nfapi_pnf_interface.h" +#include "nfapi_nr_interface.h" +#include "nfapi_nr_interface_scf.h" + #include "nfapi.h" #include "nfapi_pnf.h" #include "common/ran_context.h" @@ -52,6 +55,11 @@ extern RAN_CONTEXT_t RC; #include "PHY/INIT/phy_init.h" #include "PHY/LTE_TRANSPORT/transport_proto.h" +#include "openair2/LAYER2/NR_MAC_gNB/mac_proto.h" +#include "openair1/SCHED_NR/fapi_nr_l1.h" +#include "openair1/PHY/NR_TRANSPORT/nr_dlsch.h" +#include "openair1/PHY/defs_gNB.h" + #define NUM_P5_PHY 2 @@ -75,17 +83,46 @@ extern void handle_nfapi_dlsch_pdu(PHY_VARS_eNB *eNB,int frame, int subframe, L1 extern void handle_nfapi_hi_dci0_dci_pdu(PHY_VARS_eNB *eNB,int frame, int subframe, L1_rxtx_proc_t *proc, nfapi_hi_dci0_request_pdu_t *hi_dci0_config_pdu); extern void handle_nfapi_hi_dci0_hi_pdu(PHY_VARS_eNB *eNB,int frame, int subframe, L1_rxtx_proc_t *proc, nfapi_hi_dci0_request_pdu_t *hi_dci0_config_pdu); extern void handle_nfapi_bch_pdu(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc, nfapi_dl_config_request_pdu_t *dl_config_pdu, uint8_t *sdu); +extern void handle_nfapi_nr_ul_dci_pdu(PHY_VARS_gNB *gNB, + int frame, int slot, + nfapi_nr_ul_dci_request_pdus_t *ul_dci_request_pdu); +extern void handle_nfapi_nr_pdcch_pdu(PHY_VARS_gNB *gNB, + int frame, int slot, + nfapi_nr_dl_tti_pdcch_pdu *pdcch_pdu); +extern void handle_nr_nfapi_pdsch_pdu(PHY_VARS_gNB *gNB,int frame,int slot, + nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu, + uint8_t *sdu); +extern void handle_nr_nfapi_ssb_pdu(PHY_VARS_gNB *gNB,int frame,int slot, + nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdu); +extern void nr_fill_ulsch(PHY_VARS_gNB *gNB, + int frame, + int slot, + nfapi_nr_pusch_pdu_t *ulsch_pdu); +extern void nr_fill_pucch(PHY_VARS_gNB *gNB, + int frame, + int slot, + nfapi_nr_pucch_pdu_t *pucch_pdu); +extern void nr_fill_prach(PHY_VARS_gNB *gNB, + int SFN, + int Slot, + nfapi_nr_prach_pdu_t *prach_pdu); +extern void nr_fill_prach_ru(RU_t *ru, + int SFN, + int Slot, + nfapi_nr_prach_pdu_t *prach_pdu); + nfapi_tx_request_pdu_t *tx_request_pdu[1023][10][10]; // [frame][subframe][max_num_pdus] - +uint8_t nr_tx_pdus[32][16][4096]; +nfapi_nr_pdu_t *tx_data_request[1023][20][10]; //[frame][slot][max_num_pdus] uint8_t tx_pdus[32][8][4096]; nfapi_ue_release_request_body_t release_rntis; uint16_t phy_antenna_capability_values[] = { 1, 2, 4, 8, 16 }; -nfapi_pnf_param_response_t g_pnf_param_resp; +nfapi_nr_pnf_param_response_t g_pnf_param_resp; nfapi_pnf_p7_config_t *p7_config_g = NULL; @@ -248,6 +285,63 @@ void *pnf_p7_thread_start(void *ptr) { return 0; } +void *pnf_nr_p7_thread_start(void *ptr) { + NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] P7 THREAD %s\n", __FUNCTION__); + pnf_set_thread_priority(79); + nfapi_pnf_p7_config_t *config = (nfapi_pnf_p7_config_t *)ptr; + nfapi_nr_pnf_p7_start(config); + return 0; +} + +int pnf_nr_param_request(nfapi_pnf_config_t *config, nfapi_nr_pnf_param_request_t *req) { + printf("[PNF] pnf param request\n"); + nfapi_nr_pnf_param_response_t resp; + memset(&resp, 0, sizeof(resp)); + resp.header.message_id = NFAPI_PNF_PARAM_RESPONSE; + resp.error_code = NFAPI_MSG_OK; + pnf_info *pnf = (pnf_info *)(config->user_data); + resp.pnf_param_general.tl.tag = NFAPI_PNF_PARAM_GENERAL_TAG; + resp.pnf_param_general.nfapi_sync_mode = pnf->sync_mode; + resp.pnf_param_general.location_mode = pnf->location_mode; + resp.pnf_param_general.dl_config_timing = pnf->dl_config_timing; + resp.pnf_param_general.tx_timing = pnf->tx_timing; + resp.pnf_param_general.ul_config_timing = pnf->ul_config_timing; + resp.pnf_param_general.hi_dci0_timing = pnf->hi_dci0_timing; + resp.pnf_param_general.maximum_number_phys = pnf->max_phys; + resp.pnf_param_general.maximum_total_bandwidth = pnf->max_total_bw; + resp.pnf_param_general.maximum_total_number_dl_layers = pnf->max_total_dl_layers; + resp.pnf_param_general.maximum_total_number_ul_layers = pnf->max_total_ul_layers; + resp.pnf_param_general.shared_bands = pnf->shared_bands; + resp.pnf_param_general.shared_pa = pnf->shared_pa; + resp.pnf_param_general.maximum_total_power = pnf->max_total_power; + resp.pnf_phy.tl.tag = NFAPI_PNF_PHY_TAG; + resp.pnf_phy.number_of_phys = 1; + + for(int i = 0; i < 1; ++i) { + resp.pnf_phy.phy[i].phy_config_index = pnf->phys[i].index; + resp.pnf_phy.phy[i].downlink_channel_bandwidth_supported = pnf->phys[i].dl_channel_bw_support; + resp.pnf_phy.phy[i].uplink_channel_bandwidth_supported = pnf->phys[i].ul_channel_bw_support; + resp.pnf_phy.phy[i].number_of_dl_layers_supported = pnf->phys[i].num_dl_layers_supported; + resp.pnf_phy.phy[i].number_of_ul_layers_supported = pnf->phys[i].num_ul_layers_supported; + resp.pnf_phy.phy[i].maximum_3gpp_release_supported = pnf->phys[i].release_supported; + resp.pnf_phy.phy[i].nmm_modes_supported = pnf->phys[i].nmm_modes_supported; + resp.pnf_phy.phy[i].number_of_rfs = 2; + + for(int j = 0; j < 1; ++j) { + resp.pnf_phy.phy[i].rf_config[j].rf_config_index = pnf->phys[i].rfs[j]; + } + + resp.pnf_phy.phy[i].number_of_rf_exclusions = 0; + + for(int j = 0; j < 0; ++j) { + resp.pnf_phy.phy[i].excluded_rf_config[j].rf_config_index = pnf->phys[i].excluded_rfs[j]; + } + } + nfapi_nr_pnf_pnf_param_resp(config, &resp); + return 0; +} + + int pnf_param_request(nfapi_pnf_config_t *config, nfapi_pnf_param_request_t *req) { printf("[PNF] pnf param request\n"); nfapi_pnf_param_response_t resp; @@ -413,6 +507,21 @@ int pnf_config_request(nfapi_pnf_config_t *config, nfapi_pnf_config_request_t *r return 0; } +int pnf_nr_config_request(nfapi_pnf_config_t *config, nfapi_nr_pnf_config_request_t *req) { + printf("[PNF] pnf config request\n"); + pnf_info *pnf = (pnf_info *)(config->user_data); + phy_info *phy = pnf->phys; + phy->id = req->pnf_phy_rf_config.phy_rf_config[0].phy_id; + printf("[PNF] pnf config request assigned phy_id %d to phy_config_index %d\n", phy->id, req->pnf_phy_rf_config.phy_rf_config[0].phy_config_index); + nfapi_nr_pnf_config_response_t resp; + memset(&resp, 0, sizeof(resp)); + resp.header.message_id = NFAPI_NR_PHY_MSG_TYPE_PNF_CONFIG_RESPONSE; + resp.error_code = NFAPI_MSG_OK; + nfapi_nr_pnf_pnf_config_resp(config, &resp); + printf("[PNF] Sent pnf_config_resp\n"); + return 0; +} + void nfapi_send_pnf_start_resp(nfapi_pnf_config_t *config, uint16_t phy_id) { printf("Sending NFAPI_START_RESPONSE config:%p phy_id:%d\n", config, phy_id); nfapi_start_response_t start_resp; @@ -423,6 +532,16 @@ void nfapi_send_pnf_start_resp(nfapi_pnf_config_t *config, uint16_t phy_id) { nfapi_pnf_start_resp(config, &start_resp); } +void nfapi_nr_send_pnf_start_resp(nfapi_pnf_config_t *config, uint16_t phy_id) { + printf("Sending NFAPI_START_RESPONSE config:%p phy_id:%d\n", config, phy_id); + nfapi_nr_start_response_scf_t start_resp; + memset(&start_resp, 0, sizeof(start_resp)); + start_resp.header.message_id = NFAPI_NR_PHY_MSG_TYPE_START_RESPONSE; + start_resp.header.phy_id = phy_id; + start_resp.error_code = NFAPI_MSG_OK; + nfapi_nr_pnf_start_resp(config, &start_resp); +} + int pnf_start_request(nfapi_pnf_config_t *config, nfapi_pnf_start_request_t *req) { printf("Received NFAPI_PNF_START_REQUEST\n"); pnf_info *pnf = (pnf_info *)(config->user_data); @@ -441,6 +560,24 @@ int pnf_start_request(nfapi_pnf_config_t *config, nfapi_pnf_start_request_t *req return 0; } +int pnf_nr_start_request(nfapi_pnf_config_t *config, nfapi_nr_pnf_start_request_t *req) { + printf("Received NFAPI_PNF_START_REQUEST\n"); + pnf_info *pnf = (pnf_info *)(config->user_data); + // start all phys that have been configured + phy_info *phy = pnf->phys; + + if(phy->id != 0) { + nfapi_nr_pnf_start_response_t resp; + memset(&resp, 0, sizeof(resp)); + resp.header.message_id = NFAPI_NR_PHY_MSG_TYPE_PNF_START_RESPONSE; + resp.error_code = NFAPI_MSG_OK; + nfapi_nr_pnf_pnf_start_resp(config, &resp); + printf("[PNF] Sent NFAPI_PNF_START_RESP\n"); + } + + return 0; +} + int pnf_stop_request(nfapi_pnf_config_t *config, nfapi_pnf_stop_request_t *req) { printf("[PNF] Received NFAPI_PNF_STOP_REQ\n"); nfapi_pnf_stop_response_t resp; @@ -476,7 +613,228 @@ int param_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, nfapi return 0; } -int config_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, nfapi_config_request_t *req) { +int nr_param_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, nfapi_nr_param_request_scf_t *req) { + printf("[PNF] Received NFAPI_PARAM_REQUEST phy_id:%d\n", req->header.phy_id); + //pnf_info* pnf = (pnf_info*)(config->user_data); + nfapi_nr_param_response_scf_t nfapi_resp; + pnf_info *pnf = (pnf_info *)(config->user_data); + memset(&nfapi_resp, 0, sizeof(nfapi_resp)); + nfapi_resp.header.message_id = NFAPI_NR_PHY_MSG_TYPE_PARAM_RESPONSE; + nfapi_resp.header.phy_id = req->header.phy_id; + nfapi_resp.error_code = 0; // DJP - what value??? + struct sockaddr_in pnf_p7_sockaddr; + + // ASSIGN TAGS + { + nfapi_resp.cell_param.release_capability.tl.tag = NFAPI_NR_PARAM_TLV_RELEASE_CAPABILITY_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.cell_param.phy_state.tl.tag = NFAPI_NR_PARAM_TLV_PHY_STATE_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.cell_param.skip_blank_dl_config.tl.tag = NFAPI_NR_PARAM_TLV_SKIP_BLANK_DL_CONFIG_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.cell_param.skip_blank_ul_config.tl.tag = NFAPI_NR_PARAM_TLV_SKIP_BLANK_UL_CONFIG_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.cell_param.num_config_tlvs_to_report .tl.tag = NFAPI_NR_PARAM_TLV_NUM_CONFIG_TLVS_TO_REPORT_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.carrier_param.cyclic_prefix.tl.tag = NFAPI_NR_PARAM_TLV_CYCLIC_PREFIX_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.carrier_param.supported_subcarrier_spacings_dl.tl.tag = NFAPI_NR_PARAM_TLV_SUPPORTED_SUBCARRIER_SPACINGS_DL_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.carrier_param.supported_bandwidth_dl.tl.tag = NFAPI_NR_PARAM_TLV_SUPPORTED_BANDWIDTH_DL_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.carrier_param.supported_subcarrier_spacings_ul.tl.tag = NFAPI_NR_PARAM_TLV_SUPPORTED_SUBCARRIER_SPACINGS_UL_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.carrier_param.supported_bandwidth_ul.tl.tag = NFAPI_NR_PARAM_TLV_SUPPORTED_BANDWIDTH_UL_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pdcch_param.cce_mapping_type.tl.tag = NFAPI_NR_PARAM_TLV_CCE_MAPPING_TYPE_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pdcch_param.coreset_outside_first_3_of_ofdm_syms_of_slot.tl.tag = NFAPI_NR_PARAM_TLV_CORESET_OUTSIDE_FIRST_3_OFDM_SYMS_OF_SLOT_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pdcch_param.coreset_precoder_granularity_coreset.tl.tag = NFAPI_NR_PARAM_TLV_PRECODER_GRANULARITY_CORESET_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pdcch_param.pdcch_mu_mimo.tl.tag = NFAPI_NR_PARAM_TLV_PDCCH_MU_MIMO_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pdcch_param.pdcch_precoder_cycling.tl.tag = NFAPI_NR_PARAM_TLV_PDCCH_PRECODER_CYCLING_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pdcch_param.max_pdcch_per_slot.tl.tag = NFAPI_NR_PARAM_TLV_MAX_PDCCHS_PER_SLOT_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pucch_param.pucch_formats.tl.tag = NFAPI_NR_PARAM_TLV_PUCCH_FORMATS_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pucch_param.max_pucchs_per_slot.tl.tag = NFAPI_NR_PARAM_TLV_MAX_PUCCHS_PER_SLOT_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pdsch_param.pdsch_mapping_type.tl.tag = NFAPI_NR_PARAM_TLV_PDSCH_MAPPING_TYPE_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pdsch_param.pdsch_dmrs_additional_pos.tl.tag = NFAPI_NR_PARAM_TLV_PDSCH_DMRS_ADDITIONAL_POS_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pdsch_param.pdsch_allocation_types.tl.tag = NFAPI_NR_PARAM_TLV_PDSCH_ALLOCATION_TYPES_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pdsch_param.pdsch_vrb_to_prb_mapping.tl.tag = NFAPI_NR_PARAM_TLV_PDSCH_VRB_TO_PRB_MAPPING_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pdsch_param.pdsch_cbg.tl.tag = NFAPI_NR_PARAM_TLV_PDSCH_CBG_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pdsch_param.pdsch_dmrs_config_types.tl.tag = NFAPI_NR_PARAM_TLV_PDSCH_DMRS_CONFIG_TYPES_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pdsch_param.max_number_mimo_layers_pdsch.tl.tag = NFAPI_NR_PARAM_TLV_MAX_NUMBER_MIMO_LAYERS_PDSCH_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pdsch_param.max_mu_mimo_users_dl.tl.tag = NFAPI_NR_PARAM_TLV_MAX_MU_MIMO_USERS_DL_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pdsch_param.pdsch_data_in_dmrs_symbols.tl.tag = NFAPI_NR_PARAM_TLV_PDSCH_DATA_IN_DMRS_SYMBOLS_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pdsch_param.premption_support.tl.tag = NFAPI_NR_PARAM_TLV_PREMPTION_SUPPORT_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pdsch_param.pdsch_non_slot_support.tl.tag = NFAPI_NR_PARAM_TLV_PDSCH_NON_SLOT_SUPPORT_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pusch_param.uci_mux_ulsch_in_pusch.tl.tag = NFAPI_NR_PARAM_TLV_UCI_MUX_ULSCH_IN_PUSCH_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pusch_param.uci_only_pusch.tl.tag = NFAPI_NR_PARAM_TLV_UCI_ONLY_PUSCH_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pusch_param.pusch_frequency_hopping.tl.tag = NFAPI_NR_PARAM_TLV_PUSCH_FREQUENCY_HOPPING_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pusch_param.pusch_dmrs_config_types.tl.tag = NFAPI_NR_PARAM_TLV_PUSCH_DMRS_CONFIG_TYPES_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pusch_param.pusch_dmrs_max_len.tl.tag = NFAPI_NR_PARAM_TLV_PUSCH_DMRS_MAX_LEN_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pusch_param.pusch_dmrs_additional_pos.tl.tag = NFAPI_NR_PARAM_TLV_PUSCH_DMRS_ADDITIONAL_POS_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pusch_param.pusch_cbg.tl.tag = NFAPI_NR_PARAM_TLV_PUSCH_CBG_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pusch_param.pusch_mapping_type.tl.tag = NFAPI_NR_PARAM_TLV_PUSCH_MAPPING_TYPE_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pusch_param.pusch_allocation_types.tl.tag = NFAPI_NR_PARAM_TLV_PUSCH_ALLOCATION_TYPES_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pusch_param.pusch_vrb_to_prb_mapping.tl.tag = NFAPI_NR_PARAM_TLV_PUSCH_VRB_TO_PRB_MAPPING_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pusch_param.pusch_max_ptrs_ports.tl.tag = NFAPI_NR_PARAM_TLV_PUSCH_MAX_PTRS_PORTS_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pusch_param.max_pduschs_tbs_per_slot.tl.tag = NFAPI_NR_PARAM_TLV_MAX_PDUSCHS_TBS_PER_SLOT_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pusch_param.max_number_mimo_layers_non_cb_pusch.tl.tag = NFAPI_NR_PARAM_TLV_MAX_NUMBER_MIMO_LAYERS_NON_CB_PUSCH_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pusch_param.supported_modulation_order_ul.tl.tag = NFAPI_NR_PARAM_TLV_SUPPORTED_MODULATION_ORDER_UL_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pusch_param.max_mu_mimo_users_ul.tl.tag = NFAPI_NR_PARAM_TLV_MAX_MU_MIMO_USERS_UL_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pusch_param.dfts_ofdm_support.tl.tag = NFAPI_NR_PARAM_TLV_DFTS_OFDM_SUPPORT_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.pusch_param.pusch_aggregation_factor.tl.tag = NFAPI_NR_PARAM_TLV_PUSCH_AGGREGATION_FACTOR_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.prach_param.prach_long_formats.tl.tag = NFAPI_NR_PARAM_TLV_PRACH_LONG_FORMATS_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.prach_param.prach_short_formats.tl.tag = NFAPI_NR_PARAM_TLV_PRACH_SHORT_FORMATS_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.prach_param.prach_restricted_sets.tl.tag = NFAPI_NR_PARAM_TLV_PRACH_RESTRICTED_SETS_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.prach_param.max_prach_fd_occasions_in_a_slot.tl.tag = NFAPI_NR_PARAM_TLV_MAX_PRACH_FD_OCCASIONS_IN_A_SLOT_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.measurement_param.rssi_measurement_support.tl.tag = NFAPI_NR_PARAM_TLV_RSSI_MEASUREMENT_SUPPORT_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.nfapi_config.p7_vnf_address_ipv4.tl.tag = NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV4_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.nfapi_config.p7_vnf_address_ipv6.tl.tag = NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV6_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.nfapi_config.p7_vnf_port.tl.tag = NFAPI_NR_NFAPI_P7_VNF_PORT_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.nfapi_config.p7_pnf_address_ipv4.tl.tag = NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV4_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.nfapi_config.p7_pnf_address_ipv6.tl.tag = NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV6_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.nfapi_config.p7_pnf_port.tl.tag = NFAPI_NR_NFAPI_P7_PNF_PORT_TAG; + nfapi_resp.num_tlv++; +/* + nfapi_resp.nfapi_config.dl_ue_per_sf.tl.tag = NFAPI_NR_NFAPI_DOWNLINK_UES_PER_SUBFRAME_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.nfapi_config.ul_ue_per_sf.tl.tag = NFAPI_NR_NFAPI_UPLINK_UES_PER_SUBFRAME_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.nfapi_config.rf_bands.tl.tag = NFAPI_NR_NFAPI_RF_BANDS_TAG; + nfapi_resp.num_tlv++; + nfapi_resp.nfapi_config.max_transmit_power.tl.tag = NFAPI_NR_NFAPI_MAXIMUM_TRANSMIT_POWER_TAG; + nfapi_resp.num_tlv++; +*/ + nfapi_resp.nfapi_config.timing_window.tl.tag = NFAPI_NR_NFAPI_TIMING_WINDOW_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.nfapi_config.timing_info_mode.tl.tag = NFAPI_NR_NFAPI_TIMING_INFO_MODE_TAG; + nfapi_resp.num_tlv++; + + nfapi_resp.nfapi_config.timing_info_period.tl.tag = NFAPI_NR_NFAPI_TIMING_INFO_PERIOD_TAG; + nfapi_resp.num_tlv++; + } + + nfapi_resp.nfapi_config.p7_pnf_port.value = 32123; //pnf->phys[0].local_port; DJP - hard code alert!!!! FIXME TODO + nfapi_resp.num_tlv++; + pnf_p7_sockaddr.sin_addr.s_addr = inet_addr(pnf->phys[0].local_addr); + + memcpy(nfapi_resp.nfapi_config.p7_pnf_address_ipv4.address, &pnf_p7_sockaddr.sin_addr.s_addr, 4); + nfapi_resp.num_tlv++; + // P7 PNF Port + printf("TAG value :%d",nfapi_resp.cell_param.phy_state.tl.tag); + nfapi_nr_pnf_param_resp(config, &nfapi_resp); + + printf("[PNF] Sent NFAPI_PNF_PARAM_RESPONSE phy_id:%d number_of_tlvs:%u\n", req->header.phy_id, nfapi_resp.num_tlv); + printf("[PNF] param request .. exit\n"); + return 0; +} + +int config_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, nfapi_config_request_t *req) +{ printf("[PNF] Received NFAPI_CONFIG_REQ phy_id:%d\n", req->header.phy_id); pnf_info *pnf = (pnf_info *)(config->user_data); uint8_t num_tlv = 0; @@ -657,8 +1015,7 @@ int config_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, nfap phy_config_request(&phy_config); dump_frame_parms(fp); } - - phy_info->remote_port = req->nfapi_config.p7_vnf_port.value; + phy_info->remote_port = req->nfapi_config.p7_vnf_port.value; struct sockaddr_in vnf_p7_sockaddr; memcpy(&vnf_p7_sockaddr.sin_addr.s_addr, &(req->nfapi_config.p7_vnf_address_ipv4.address[0]), 4); phy_info->remote_addr = inet_ntoa(vnf_p7_sockaddr.sin_addr); @@ -678,6 +1035,100 @@ int config_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, nfap return 0; } +int nr_config_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, nfapi_nr_config_request_scf_t *req) +{ + printf("[PNF] Received NFAPI_CONFIG_REQ phy_id:%d\n", req->header.phy_id); + pnf_info *pnf = (pnf_info *)(config->user_data); + uint8_t num_tlv = 0; + //struct PHY_VARS_eNB_s *eNB = RC.eNB[0][0]; + // In the case of nfapi_mode = 3 (UE = PNF) we should not have dependency on any eNB var. So we aim + // to keep only the necessary just to keep the nfapi FSM rolling by sending a dummy response. + NR_DL_FRAME_PARMS *fp; + + if (NFAPI_MODE!=NFAPI_UE_STUB_PNF) { + struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; + fp = &gNB->frame_parms; + } else { + fp = (NR_DL_FRAME_PARMS *) malloc(sizeof(NR_DL_FRAME_PARMS)); + } + + phy_info *phy_info = pnf->phys; + + printf("\nTiming window tag: %d\n",NFAPI_NR_NFAPI_TIMING_WINDOW_TAG); + if(req->nfapi_config.timing_window.tl.tag == NFAPI_NR_NFAPI_TIMING_WINDOW_TAG) { + phy_info->timing_window = req->nfapi_config.timing_window.value; + printf("Phy_info:Timing window:%u NFAPI_CONFIG:timing_window:%u\n", phy_info->timing_window, req->nfapi_config.timing_window.value); + num_tlv++; + } + + if(req->nfapi_config.timing_info_mode.tl.tag == NFAPI_NR_NFAPI_TIMING_INFO_MODE_TAG) { + printf("timing info mode:%d\n", req->nfapi_config.timing_info_mode.value); + phy_info->timing_info_mode = req->nfapi_config.timing_info_mode.value; + num_tlv++; + } else { + phy_info->timing_info_mode = 0; + printf("NO timing info mode provided\n"); + } + //TODO: Read the P7 message offset values + if(req->nfapi_config.timing_info_period.tl.tag == NFAPI_NR_NFAPI_TIMING_INFO_PERIOD_TAG) { + printf("timing info period provided value:%d\n", req->nfapi_config.timing_info_period.value); + phy_info->timing_info_period = req->nfapi_config.timing_info_period.value; + num_tlv++; + } else { + phy_info->timing_info_period = 0; + } + + if(req->carrier_config.dl_bandwidth.tl.tag == NFAPI_NR_CONFIG_DL_BANDWIDTH_TAG) { + phy_info->dl_channel_bw_support = req->carrier_config.dl_bandwidth.value; //rf_config.dl_channel_bandwidth.value; + fp->N_RB_DL = req->carrier_config.dl_bandwidth.value; //rf_config.dl_channel_bandwidth.value; + num_tlv++; + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() NFAPI_NR_CONFIG_DL_BANDWIDTH_TAG N_RB_DL:%u\n", __FUNCTION__, fp->N_RB_DL); + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() Missing NFAPI_NR_CONFIG_DL_BANDWIDTH_TAG\n", __FUNCTION__); + } + + if(req->carrier_config.uplink_bandwidth.tl.tag == NFAPI_NR_CONFIG_UPLINK_BANDWIDTH_TAG) { + phy_info->ul_channel_bw_support = req->carrier_config.uplink_bandwidth.value; //req->rf_config.ul_channel_bandwidth.value; + fp->N_RB_UL = req->carrier_config.uplink_bandwidth.value; //req->rf_config.ul_channel_bandwidth.value; + num_tlv++; + } + + if (req->cell_config.phy_cell_id.tl.tag == NFAPI_NR_CONFIG_PHY_CELL_ID_TAG) { + fp->Nid_cell = req->cell_config.phy_cell_id.value; //sch_config.physical_cell_id.value; + fp->nushift = fp->Nid_cell%6; + num_tlv++; + } + + if(NFAPI_MODE!=NFAPI_UE_STUB_PNF) { + printf("[PNF] CONFIG_REQUEST[num_tlv:%d] TLVs processed:%d\n", req->num_tlv, num_tlv); + printf("[PNF] Simulating PHY CONFIG - DJP\n"); + NR_PHY_Config_t nr_phy_config; + nr_phy_config.Mod_id = 0; + nr_phy_config.CC_id=0; + nr_phy_config.cfg = req; + nr_phy_config_request(&nr_phy_config); + nr_dump_frame_parms(fp); + } + phy_info->remote_port = req->nfapi_config.p7_vnf_port.value; + struct sockaddr_in vnf_p7_sockaddr; + memcpy(&vnf_p7_sockaddr.sin_addr.s_addr, &(req->nfapi_config.p7_vnf_address_ipv4.address[0]), 4); + phy_info->remote_addr = inet_ntoa(vnf_p7_sockaddr.sin_addr); + printf("[PNF] %d vnf p7 %s:%d timing %d %d %d\n", phy_info->id, phy_info->remote_addr, phy_info->remote_port, + phy_info->timing_window, phy_info->timing_info_mode, phy_info->timing_info_period); + nfapi_nr_config_response_scf_t nfapi_resp; + memset(&nfapi_resp, 0, sizeof(nfapi_resp)); + nfapi_resp.header.message_id = NFAPI_NR_PHY_MSG_TYPE_CONFIG_RESPONSE; + nfapi_resp.header.phy_id = phy_info->id; + nfapi_resp.error_code = 0; // DJP - some value resp->error_code; + nfapi_nr_pnf_config_resp(config, &nfapi_resp); + printf("[PNF] Sent NFAPI_PNF_CONFIG_RESPONSE phy_id:%d\n", phy_info->id); + + if(NFAPI_MODE==NFAPI_UE_STUB_PNF) + free(fp); + + return 0; +} + nfapi_p7_message_header_t *pnf_phy_allocate_p7_vendor_ext(uint16_t message_id, uint16_t *msg_size) { if(message_id == P7_VENDOR_EXT_REQ) { (*msg_size) = sizeof(vendor_ext_p7_req); @@ -691,6 +1142,33 @@ void pnf_phy_deallocate_p7_vendor_ext(nfapi_p7_message_header_t *header) { free(header); } + +int pnf_phy_ul_dci_req(gNB_L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, nfapi_nr_ul_dci_request_t *req) { + + // LOG_D(PHY,"[PNF] HI_DCI0_REQUEST SFN/SF:%05d dci:%d hi:%d\n", NFAPI_SFNSF2DEC(req->sfn_sf), req->hi_dci0_request_body.number_of_dci, req->hi_dci0_request_body.number_of_hi); + + //phy_info* phy = (phy_info*)(pnf_p7->user_data); + struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; + if (proc ==NULL) + proc = &gNB->proc.L1_proc; + + for (int i=0; inumPdus; i++) { + //LOG_D(PHY,"[PNF] HI_DCI0_REQ sfn_sf:%d PDU[%d]\n", NFAPI_SFNSF2DEC(req->sfn_sf), i); + if (req->ul_dci_pdu_list[i].PDUType == 0) { + //LOG_D(PHY,"[PNF] HI_DCI0_REQ sfn_sf:%d PDU[%d] - NFAPI_HI_DCI0_DCI_PDU_TYPE\n", NFAPI_SFNSF2DEC(req->sfn_sf), i); + nfapi_nr_ul_dci_request_pdus_t *ul_dci_req_pdu = &req->ul_dci_pdu_list[i]; + int SFN=req->SFN+2; + handle_nfapi_nr_ul_dci_pdu(gNB, SFN, req->Slot, ul_dci_req_pdu); + } + else { + LOG_E(PHY,"[PNF] UL_DCI_REQ sfn_slot:%d PDU[%d] - unknown pdu type:%d\n", NFAPI_SFNSLOT2DEC(req->SFN, req->Slot), i, req->ul_dci_pdu_list[i].PDUType); + } + } + + return 0; +} + + int pnf_phy_hi_dci0_req(L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, nfapi_hi_dci0_request_t *req) { if (req->hi_dci0_request_body.number_of_dci == 0 && req->hi_dci0_request_body.number_of_hi == 0) LOG_D(PHY,"[PNF] HI_DCI0_REQUEST SFN/SF:%05d dci:%d hi:%d\n", NFAPI_SFNSF2DEC(req->sfn_sf), req->hi_dci0_request_body.number_of_dci, req->hi_dci0_request_body.number_of_hi); @@ -719,6 +1197,97 @@ int pnf_phy_hi_dci0_req(L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, nfa return 0; } + +int pnf_phy_dl_tti_req(gNB_L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, nfapi_nr_dl_tti_request_t *req) { + if (RC.ru == 0) { + return -1; + } + + if (RC.gNB == 0) { + return -2; + } + + if (RC.gNB[0] == 0) { + return -3; + } + + if (sync_var != 0) { + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() Main system not up - is this a dummy subframe?\n", __FUNCTION__); + return -4; + } + + int sfn = req->SFN; + int slot = req->Slot; + + struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; + if (proc==NULL) + proc = &gNB->proc.L1_proc; + nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdu_list = req->dl_tti_request_body.dl_tti_pdu_list; + + if (req->dl_tti_request_body.nPDUs) + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() TX:%d/%d RX:%d/%d; sfn:%d, slot:%d, nGroup:%u, nPDUs: %u, nUE: %u, PduIdx: %u,\n", + __FUNCTION__, proc->frame_tx, proc->slot_tx, proc->frame_rx, proc->slot_rx, // TODO: change subframes to slot + req->SFN, + req->Slot, + req->dl_tti_request_body.nGroup, + req->dl_tti_request_body.nPDUs, + req->dl_tti_request_body.nUe, + req->dl_tti_request_body.PduIdx); + + for (int i=0; idl_tti_request_body.nPDUs; i++) { + // TODO: enable after adding gNB PDCCH: + // NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() sfn/sf:%d PDU[%d] size:%d pdcch_vars->num_dci:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(req->sfn_sf), i, dl_config_pdu_list[i].pdu_size,pdcch_vars->num_dci); + + if (dl_tti_pdu_list[i].PDUType == NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE) { + nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdu=&dl_tti_pdu_list[i]; + memcpy(dl_tti_pdu,&dl_tti_pdu_list[i],sizeof(nfapi_nr_dl_tti_request_pdu_t)); + int SFN=sfn+2; + handle_nfapi_nr_pdcch_pdu(gNB, SFN, slot, &dl_tti_pdu->pdcch_pdu); + //dl_tti_pdu_list[i].pdcch_pdu.pdcch_pdu_rel15.numDlDci++; // ? + // NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() pdcch_vars->num_dci:%d\n", __FUNCTION__, pdcch_vars->num_dci); + } else if (dl_tti_pdu_list[i].PDUType == NFAPI_NR_DL_TTI_SSB_PDU_TYPE) { + //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() PDU:%d BCH: pdu_index:%u pdu_length:%d sdu_length:%d BCH_SDU:%x,%x,%x\n", __FUNCTION__, i, pdu_index, bch_pdu->bch_pdu_rel8.length, tx_request_pdu[sfn][sf][pdu_index]->segments[0].segment_length, sdu[0], sdu[1], sdu[2]); + handle_nr_nfapi_ssb_pdu(gNB, sfn, slot, &dl_tti_pdu_list[i]); + gNB->pbch_configured=1; + //} else { + // NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() BCH NULL TX PDU SFN/SF:%d PDU_INDEX:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(req->sfn_sf), pdu_index); + //} + } else if (dl_tti_pdu_list[i].PDUType == NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE) { + nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu = &dl_tti_pdu_list[i].pdsch_pdu; + nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15_pdu = &pdsch_pdu->pdsch_pdu_rel15; + //nfapi_nr_tx_data_request_t *tx_data = tx_data_request[sfn][slot][rel15_pdu->pduIndex]; + nfapi_nr_pdu_t *tx_data = tx_data_request[sfn][slot][0]; + + if (tx_data != NULL) { + int UE_id = find_nr_dlsch(rel15_pdu->rnti,gNB,SEARCH_EXIST_OR_FREE); + AssertFatal(UE_id!=-1,"no free or exiting dlsch_context\n"); + AssertFatal(UE_id= %d(NUMBER_OF_UE_MAX)\n",UE_id,NUMBER_OF_UE_MAX); + NR_gNB_DLSCH_t *dlsch0 = gNB->dlsch[UE_id][0]; + int harq_pid = dlsch0->harq_ids[sfn%2][slot]; + + if(harq_pid >= dlsch0->Mdlharq) { + LOG_E(PHY,"pnf_phy_dl_config_req illegal harq_pid %d\n", harq_pid); + return(-1); + } + //uint8_t *dlsch_sdu = (uint8_t *)tx_data->TLVs[0].value.direct; + uint8_t *dlsch_sdu = nr_tx_pdus[UE_id][harq_pid]; + memcpy(dlsch_sdu, tx_data->TLVs[0].value.direct,tx_data->PDU_length);//TODO: Check if required + //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() DLSCH:pdu_index:%d handle_nfapi_dlsch_pdu(eNB, proc_rxtx, dlsch_pdu, transport_blocks:%d sdu:%p) eNB->pdcch_vars[proc->subframe_tx & 1].num_pdcch_symbols:%d\n", __FUNCTION__, rel8_pdu->pdu_index, rel8_pdu->transport_blocks, dlsch_sdu, eNB->pdcch_vars[proc->subframe_tx & 1].num_pdcch_symbols); + handle_nr_nfapi_pdsch_pdu(gNB, sfn, slot,pdsch_pdu, dlsch_sdu); + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() DLSCH NULL TX PDU SFN/SF:%d PDU_INDEX:%d\n", __FUNCTION__, NFAPI_SFNSLOT2DEC(sfn,slot), rel15_pdu->pduIndex); } + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() UNKNOWN:%d\n", __FUNCTION__, dl_tti_pdu_list[i].PDUType); + } + } + + if(req->vendor_extension) + free(req->vendor_extension); + + return 0; +} + + int pnf_phy_dl_config_req(L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, nfapi_dl_config_request_t *req) { if (RC.eNB == 0) { @@ -810,6 +1379,35 @@ int pnf_phy_dl_config_req(L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, n return 0; } + + +int pnf_phy_tx_data_req(nfapi_pnf_p7_config_t *pnf_p7, nfapi_nr_tx_data_request_t *req) { + uint16_t sfn = req->SFN; + uint16_t slot = req->Slot; + + if (req->Number_of_PDUs == 0) + LOG_D(PHY,"%s() SFN/SLOT:%d%d PDUs:%d\n", __FUNCTION__, sfn, slot, req->Number_of_PDUs); + + //if (req->pdu_list[0].TLVs->tag == NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST) { + for (int i=0; iNumber_of_PDUs; i++) { + // LOG_D(PHY,"%s() SFN/SF:%d%d number_of_pdus:%d [PDU:%d] pdu_length:%d pdu_index:%d num_segments:%d\n", + // __FUNCTION__, + // sfn, sf, + // req->tx_request_body.number_of_pdus, + // i, + // req->tx_request_body.tx_pdu_list[i].pdu_length, + // req->tx_request_body.tx_pdu_list[i].pdu_index, + // req->tx_request_body.tx_pdu_list[i].num_segments + // ); + // tx_request_pdu[sfn][sf][i] = &req->tx_request_body.tx_pdu_list[i]; + tx_data_request[sfn][slot][i] = &req->pdu_list[i]; + } + //} + + return 0; +} + + int pnf_phy_tx_req(nfapi_pnf_p7_config_t *pnf_p7, nfapi_tx_request_t *req) { uint16_t sfn = NFAPI_SFNSF2SFN(req->sfn_sf); uint16_t sf = NFAPI_SFNSF2SF(req->sfn_sf); @@ -835,6 +1433,82 @@ int pnf_phy_tx_req(nfapi_pnf_p7_config_t *pnf_p7, nfapi_tx_request_t *req) { return 0; } + + +int pnf_phy_ul_tti_req(gNB_L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, nfapi_nr_ul_tti_request_t *req) { + // if (0)LOG_D(PHY,"[PNF] UL_CONFIG_REQ %s() sfn_sf:%d pdu:%d rach_prach_frequency_resources:%d srs_present:%u\n", + // __FUNCTION__, + // NFAPI_SFNSF2DEC(req->sfn_sf), + // req->ul_config_request_body.number_of_pdus, + // req->ul_config_request_body.rach_prach_frequency_resources, + // req->ul_config_request_body.srs_present + // ); + + if (RC.ru == 0) { + return -1; + } + + if (RC.gNB == 0) { + return -2; + } + + if (RC.gNB[0] == 0) { + return -3; + } + + if (sync_var != 0) { + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() Main system not up - is this a dummy slot?\n", __FUNCTION__); + return -4; + } + uint16_t curr_sfn = req->SFN; + uint16_t curr_slot = req->Slot; + struct PHY_VARS_gNB_s *gNB = RC.gNB[0]; + + if (proc==NULL) + proc = &gNB->proc.L1_proc; + + nfapi_nr_ul_tti_request_number_of_pdus_t *ul_tti_pdu_list = req->pdus_list; + + for (int i=0; i< req->n_pdus; i++) { + switch (ul_tti_pdu_list[i].pdu_type) { + case NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE: + //LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_UL_TTI_PUSCH_PDU_TYPE for %d.%d\n", frame, slot, UL_tti_req->SFN, UL_tti_req->Slot); + nr_fill_ulsch(gNB,curr_sfn, curr_slot, &ul_tti_pdu_list[i].pusch_pdu); + break; + case NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE: + //LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_UL_TTI_PUCCH_PDU_TYPE for %d.%d\n", frame, slot, UL_tti_req->SFN, UL_tti_req->Slot); + nr_fill_pucch(gNB,curr_sfn, curr_slot, &ul_tti_pdu_list[i].pucch_pdu); + break; + case NFAPI_NR_UL_CONFIG_PRACH_PDU_TYPE: + //LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_UL_TTI_PRACH_PDU_TYPE for %d.%d\n", frame, slot, UL_tti_req->SFN, UL_tti_req->Slot); + nr_fill_prach(gNB, curr_sfn, curr_slot, &ul_tti_pdu_list[i].prach_pdu); + if (gNB->RU_list[0]->if_south == LOCAL_RF) nr_fill_prach_ru(gNB->RU_list[0], curr_sfn, curr_slot, &ul_tti_pdu_list[i].prach_pdu); + break; + default: + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() PDU:%i UNKNOWN type :%d\n", __FUNCTION__, i, ul_tti_pdu_list[i].pdu_type); + break; + + } + // //LOG_D(PHY, "%s() sfn/sf:%d PDU[%d] size:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(req->sfn_sf), i, ul_config_pdu_list[i].pdu_size); + // if ( + // ul_tti_pdu_list[i].pdu_type == NFAPI_NR_UL_CONFIG_PRACH_PDU_TYPE || + // ul_tti_pdu_list[i].pdu_type == NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE || + // ul_tti_pdu_list[i].pdu_type == NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE || + // ul_tti_pdu_list[i].pdu_type == NFAPI_NR_UL_CONFIG_SRS_PDU_TYPE + // ) { + // //LOG_D(PHY, "%s() handle_nfapi_ul_pdu() for PDU:%d\n", __FUNCTION__, i); + // // handle_nfapi_ul_pdu(eNB,proc,&ul_config_pdu_list[i],curr_sfn,curr_sf,req->ul_config_request_body.srs_present); + + // // TODO: dont have an NR function for this, also srs_present flag not there + + // } else { + // NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() PDU:%i UNKNOWN type :%d\n", __FUNCTION__, i, ul_tti_pdu_list[i].pdu_type); + // } + } + + return 0; +} + int pnf_phy_ul_config_req(L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, nfapi_ul_config_request_t *req) { if (0)LOG_D(PHY,"[PNF] UL_CONFIG_REQ %s() sfn_sf:%d pdu:%d rach_prach_frequency_resources:%d srs_present:%u\n", __FUNCTION__, @@ -983,6 +1657,7 @@ int pnf_sim_pack_vendor_extention_tlv(void *ve, uint8_t **ppWritePackedMsg, uint //printf("%s\n", __FUNCTION__); (void)ve; (void)ppWritePackedMsg; + return -1; } @@ -1000,7 +1675,7 @@ int start_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, nfapi p7_config->phy_id = phy->phy_id; p7_config->remote_p7_port = phy_info->remote_port; p7_config->remote_p7_addr = phy_info->remote_addr; - p7_config->local_p7_port = 32123; // DJP - good grief cannot seem to get the right answer phy_info->local_port; + p7_config->local_p7_port = 32123;//phy_info->local_port;//50010; // DJP - good grief cannot seem to get the right answer phy_info->local_port; //DJP p7_config->local_p7_addr = (char*)phy_info->local_addr.c_str(); p7_config->local_p7_addr = phy_info->local_addr; printf("[PNF] P7 remote:%s:%d local:%s:%d\n", p7_config->remote_p7_addr, p7_config->remote_p7_port, p7_config->local_p7_addr, p7_config->local_p7_port); @@ -1111,6 +1786,142 @@ int start_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, nfapi return 0; } +int nr_start_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, nfapi_nr_start_request_scf_t *req) { + printf("[PNF] Received NFAPI_START_REQ phy_id:%d\n", req->header.phy_id); + nfapi_set_trace_level(NFAPI_TRACE_INFO); + pnf_info *pnf = (pnf_info *)(config->user_data); + phy_info *phy_info = pnf->phys; + nfapi_pnf_p7_config_t *p7_config = nfapi_pnf_p7_config_create(); + p7_config->phy_id = phy->phy_id; + p7_config->remote_p7_port = phy_info->remote_port; + p7_config->remote_p7_addr = phy_info->remote_addr; + // TODO: remove this hardcoded port + p7_config->local_p7_port = 32123; // DJP - good grief cannot seem to get the right answer phy_info->local_port; + //DJP p7_config->local_p7_addr = (char*)phy_info->local_addr.c_str(); + p7_config->local_p7_addr = phy_info->local_addr; + printf("[PNF] P7 remote:%s:%d local:%s:%d\n", p7_config->remote_p7_addr, p7_config->remote_p7_port, p7_config->local_p7_addr, p7_config->local_p7_port); + p7_config->user_data = phy_info; + p7_config->malloc = &pnf_allocate; + p7_config->free = &pnf_deallocate; + p7_config->codec_config.allocate = &pnf_allocate; + p7_config->codec_config.deallocate = &pnf_deallocate; + p7_config->trace = &pnf_nfapi_trace; + phy->user_data = p7_config; + p7_config->subframe_buffer_size = phy_info->timing_window; + p7_config->slot_buffer_size = phy_info->timing_window; // TODO: check if correct for NR + printf("subframe_buffer_size configured using phy_info->timing_window:%d\n", phy_info->timing_window); + + if(phy_info->timing_info_mode & 0x1) { + p7_config->timing_info_mode_periodic = 1; + p7_config->timing_info_period = phy_info->timing_info_period; + } + + if(phy_info->timing_info_mode & 0x2) { + p7_config->timing_info_mode_aperiodic = 1; + } + + // NR + p7_config->dl_tti_req_fn = &pnf_phy_dl_tti_req; + p7_config->ul_tti_req_fn = &pnf_phy_ul_tti_req; + p7_config->ul_dci_req_fn = &pnf_phy_ul_dci_req; + p7_config->tx_data_req_fn = &pnf_phy_tx_data_req; + + // LTE + p7_config->dl_config_req = &pnf_phy_dl_config_req; + p7_config->ul_config_req = &pnf_phy_ul_config_req; + p7_config->hi_dci0_req = &pnf_phy_hi_dci0_req; + p7_config->tx_req = &pnf_phy_tx_req; + p7_config->lbt_dl_config_req = &pnf_phy_lbt_dl_config_req; + p7_config->ue_release_req = &pnf_phy_ue_release_req; + if (NFAPI_MODE==NFAPI_UE_STUB_PNF) { + p7_config->dl_config_req = &memcpy_dl_config_req; + p7_config->ul_config_req = &memcpy_ul_config_req; + p7_config->hi_dci0_req = &memcpy_hi_dci0_req; + p7_config->tx_req = &memcpy_tx_req; + } else { + p7_config->dl_config_req = &pnf_phy_dl_config_req; + p7_config->ul_config_req = &pnf_phy_ul_config_req; + p7_config->hi_dci0_req = &pnf_phy_hi_dci0_req; + p7_config->tx_req = &pnf_phy_tx_req; + } + + p7_config->lbt_dl_config_req = &pnf_phy_lbt_dl_config_req; + memset(&dummy_dl_config_req, 0, sizeof(dummy_dl_config_req)); + dummy_dl_config_req.dl_config_request_body.tl.tag=NFAPI_DL_CONFIG_REQUEST_BODY_TAG; + dummy_dl_config_req.dl_config_request_body.number_pdcch_ofdm_symbols=1; + dummy_dl_config_req.dl_config_request_body.number_dci=0; + dummy_dl_config_req.dl_config_request_body.number_pdu=0; + dummy_dl_config_req.dl_config_request_body.number_pdsch_rnti=0; + dummy_dl_config_req.dl_config_request_body.transmission_power_pcfich=6000; + dummy_dl_config_req.dl_config_request_body.dl_config_pdu_list=0; + memset(&dummy_tx_req, 0, sizeof(dummy_tx_req)); + dummy_tx_req.tx_request_body.number_of_pdus=0; + dummy_tx_req.tx_request_body.tl.tag=NFAPI_TX_REQUEST_BODY_TAG; + dummy_subframe.dl_config_req = &dummy_dl_config_req; + dummy_subframe.tx_req = 0;//&dummy_tx_req; + dummy_subframe.ul_config_req=0; + dummy_subframe.hi_dci0_req=0; + dummy_subframe.lbt_dl_config_req=0; + p7_config->dummy_subframe = dummy_subframe; + p7_config->vendor_ext = &pnf_phy_vendor_ext; + p7_config->allocate_p7_vendor_ext = &pnf_phy_allocate_p7_vendor_ext; + p7_config->deallocate_p7_vendor_ext = &pnf_phy_deallocate_p7_vendor_ext; + p7_config->codec_config.unpack_p7_vendor_extension = &pnf_phy_unpack_p7_vendor_extension; + p7_config->codec_config.pack_p7_vendor_extension = &pnf_phy_pack_p7_vendor_extension; + p7_config->codec_config.unpack_vendor_extension_tlv = &pnf_phy_unpack_vendor_extension_tlv; + p7_config->codec_config.pack_vendor_extension_tlv = &pnf_phy_pack_vendor_extention_tlv; + NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] Creating P7 thread %s\n", __FUNCTION__); + pthread_t p7_thread; + pthread_create(&p7_thread, NULL, &pnf_nr_p7_thread_start, p7_config); + //((pnf_phy_user_data_t*)(phy_info->fapi->user_data))->p7_config = p7_config; + NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] Calling l1_north_init_eNB() %s\n", __FUNCTION__); + l1_north_init_gNB(); + NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] DJP - HACK - Set p7_config global ready for subframe ind%s\n", __FUNCTION__); + p7_config_g = p7_config; + + // Need to wait for main thread to create RU structures + while(config_sync_var<0) { + usleep(5000000); + printf("[PNF] waiting for OAI to be configured (eNB/RU)\n"); + } + + printf("[PNF] OAI eNB/RU configured\n"); + //printf("[PNF] About to call phy_init_RU() for RC.ru[0]:%p\n", RC.ru[0]); + //phy_init_RU(RC.ru[0]); + printf("[PNF] About to call init_eNB_afterRU()\n"); + + if (NFAPI_MODE!=NFAPI_UE_STUB_PNF) { + init_eNB_afterRU(); + } + + // Signal to main thread that it can carry on - otherwise RU will startup too quickly and it is not initialised + { + pthread_mutex_lock(&nfapi_sync_mutex); + nfapi_sync_var=0; + pthread_cond_broadcast(&nfapi_sync_cond); + pthread_mutex_unlock(&nfapi_sync_mutex); + } + + while(sync_var<0) { + usleep(5000000); + printf("[PNF] waiting for OAI to be started\n"); + } + + printf("[PNF] Sending PNF_START_RESP\n"); + nfapi_nr_send_pnf_start_resp(config, p7_config->phy_id); + printf("[PNF] Sending first P7 slot indication\n"); +#if 1 + nfapi_pnf_p7_slot_ind(p7_config, p7_config->phy_id, 0, 0); + printf("[PNF] Sent first P7 slot ind\n"); +#else + nfapi_pnf_p7_subframe_ind(p7_config, p7_config->phy_id, 0); // DJP - SFN_SF set to zero - correct??? + printf("[PNF] Sent first P7 subframe ind\n"); +#endif + + + return 0; +} + int measurement_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, nfapi_measurement_request_t *req) { nfapi_measurement_response_t resp; memset(&resp, 0, sizeof(resp)); @@ -1356,7 +2167,6 @@ int pnf_sim_unpack_p4_p5_vendor_extension(nfapi_p4_p5_message_header_t *header, } /*------------------------------------------------------------------------------*/ - void *pnf_start_thread(void *ptr) { NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] IN PNF NFAPI start thread %s\n", __FUNCTION__); nfapi_pnf_config_t *config = (nfapi_pnf_config_t *)ptr; @@ -1367,18 +2177,76 @@ void *pnf_start_thread(void *ptr) { return (void *)0; } +void *pnf_nr_start_thread(void *ptr) { + NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] IN PNF NFAPI start thread %s\n", __FUNCTION__); + nfapi_pnf_config_t *config = (nfapi_pnf_config_t *)ptr; + struct sched_param sp; + sp.sched_priority = 20; + pthread_setschedparam(pthread_self(),SCHED_FIFO,&sp); + nfapi_nr_pnf_start(config); + return (void *)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) { + printf("%s() PNF\n\n\n\n\n\n", __FUNCTION__); + nfapi_setmode(NFAPI_MODE_PNF); // PNF! + + nfapi_pnf_config_t *config = nfapi_pnf_config_create(); + config->vnf_ip_addr = vnf_ip_addr; + config->vnf_p5_port = vnf_p5_port; + pnf.phys[0].udp.enabled = 1; + pnf.phys[0].udp.rx_port = 32123;//pnf_p7_port; + pnf.phys[0].udp.tx_port = vnf_p7_port; + strcpy(pnf.phys[0].udp.tx_addr, vnf_ip_addr); + strcpy(pnf.phys[0].local_addr, pnf_ip_addr); + printf("%s() VNF:%s:%d PNF_PHY[addr:%s UDP:tx_addr:%s:%d rx:%d]\n", + __FUNCTION__,config->vnf_ip_addr, config->vnf_p5_port, + pnf.phys[0].local_addr, + pnf.phys[0].udp.tx_addr, pnf.phys[0].udp.tx_port, + pnf.phys[0].udp.rx_port); + config->cell_search_req = &cell_search_request; + + + //config->pnf_nr_param_req = &pnf_nr_param_request; + config->pnf_nr_param_req = &pnf_nr_param_request; + config->pnf_nr_config_req = &pnf_nr_config_request; + config->pnf_nr_start_req = &pnf_nr_start_request; + config->pnf_stop_req = &pnf_stop_request; + config->nr_param_req = &nr_param_request; + config->nr_config_req = &nr_config_request; + config->nr_start_req = &nr_start_request; + config->measurement_req = &measurement_request; + config->rssi_req = &rssi_request; + config->broadcast_detect_req = &broadcast_detect_request; + config->system_information_schedule_req = &system_information_schedule_request; + config->system_information_req = &system_information_request; + config->nmm_stop_req = &nmm_stop_request; + config->vendor_ext = &vendor_ext; + config->trace = &pnf_nfapi_trace; + config->user_data = &pnf; + // To allow custom vendor extentions to be added to nfapi + config->codec_config.unpack_vendor_extension_tlv = &pnf_sim_unpack_vendor_extension_tlv; + config->codec_config.pack_vendor_extension_tlv = &pnf_sim_pack_vendor_extention_tlv; + config->allocate_p4_p5_vendor_ext = &pnf_sim_allocate_p4_p5_vendor_ext; + config->deallocate_p4_p5_vendor_ext = &pnf_sim_deallocate_p4_p5_vendor_ext; + config->codec_config.unpack_p4_p5_vendor_extension = &pnf_sim_unpack_p4_p5_vendor_extension; + config->codec_config.pack_p4_p5_vendor_extension = &pnf_sim_pack_p4_p5_vendor_extension; + NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] Creating PNF NFAPI start thread %s\n", __FUNCTION__); + pthread_create(&pnf_start_pthread, NULL, &pnf_nr_start_thread, config); + pthread_setname_np(pnf_start_pthread, "NFAPI_PNF"); +} + void configure_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_addr, int pnf_p7_port, int vnf_p7_port) { printf("%s() PNF\n\n\n\n\n\n", __FUNCTION__); if(NFAPI_MODE!=NFAPI_UE_STUB_PNF) { nfapi_setmode(NFAPI_MODE_PNF); // PNF! } - nfapi_pnf_config_t *config = nfapi_pnf_config_create(); config->vnf_ip_addr = vnf_ip_addr; config->vnf_p5_port = vnf_p5_port; pnf.phys[0].udp.enabled = 1; - pnf.phys[0].udp.rx_port = pnf_p7_port; + pnf.phys[0].udp.rx_port = 32123;//pnf_p7_port; pnf.phys[0].udp.tx_port = vnf_p7_port; strcpy(pnf.phys[0].udp.tx_addr, vnf_ip_addr); strcpy(pnf.phys[0].local_addr, pnf_ip_addr); @@ -1422,7 +2290,7 @@ void oai_subframe_ind(uint16_t sfn, uint16_t sf) { //TODO FIXME - HACK - DJP - using a global to bodge it in if (p7_config_g != NULL && sync_var==0) { - uint16_t sfn_sf_tx = sfn<<4 | sf; + uint16_t sfn_sf_tx = sfn<<4 | sf; if ((sfn % 100 == 0) && sf==0) { struct timespec ts; @@ -1441,6 +2309,52 @@ void oai_subframe_ind(uint16_t sfn, uint16_t sf) { } } + +long shift_ns,prev_ts_nsec,shift_us; +void oai_slot_ind(uint16_t sfn, uint16_t slot) { + + //slow down PNF + + LOG_D(PHY,"%s(sfn:%d, slot:%d)\n", __FUNCTION__, sfn, slot); + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + + // if (!(sfn == 0 && slot == 0) && ts.tv_nsec > prev_ts_nsec){ + // shift_ns = ts.tv_nsec - prev_ts_nsec; + // shift_us = shift_ns/1000; + // printf("previous: %d, current: %d, shift: %d", prev_ts_nsec, ts.tv_nsec, shift_us); + // if(500-shift_us > 0) + // usleep(500-shift_us); + // // usleep(50); + // } + prev_ts_nsec = ts.tv_nsec; + + +//NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] %s %d.%d (sfn:%u slot:%u) SFN/SLOT(TX):%u\n", __FUNCTION__, ts.tv_sec, ts.tv_nsec, sfn, slot, NFAPI_SFNSLOT2DEC(sfn, slot)); + //TODO FIXME - HACK - DJP - using a global to bodge it in + if (p7_config_g != NULL && sync_var==0) { + // DONE: changed for NR x x x x x x x x x x x x x x - - - - - - : x (Frame), - (Slot) (max_numer =2) + uint16_t sfn_slot_tx = sfn<<6 | slot; + // if ((sfn % 100 == 0) && slot==0) { // DOUBT: Why 100? + // struct timespec ts; + // clock_gettime(CLOCK_MONOTONIC, &ts); + // NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] %s %d.%d (sfn:%u slot:%u) SFN/SLOT(TX):%u\n", __FUNCTION__, ts.tv_sec, ts.tv_nsec, sfn, slot, NFAPI_SFNSLOT2DEC(sfn, slot)); + // } + + //TODO: send p7_config instead of p7_config_g + int slot_ret = nfapi_pnf_p7_slot_ind(p7_config_g, p7_config_g->phy_id, sfn, slot); + + // if (subframe_ret) { + if (slot_ret) { + NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] %s(frame:%u slot:%u) SFN/SLOT(TX):%u - PROBLEM with pnf_p7_slot_ind()\n", __FUNCTION__, sfn, slot, sfn_slot_tx, NFAPI_SFNSLOT2DEC(sfn, slot)); + // printing anything causes error: probably because there isn't enough time to accomodate a print statement + } else { + //NFAPI_TRACE(NFAPI_TRACE_INFO, "***NFAPI subframe handler finished *** \n"); + } + } else { + } +} + int oai_nfapi_rach_ind(nfapi_rach_indication_t *rach_ind) { rach_ind->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! LOG_D(PHY, "%s() sfn_sf:%d preambles:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(rach_ind->sfn_sf), rach_ind->rach_indication_body.number_of_preambles); diff --git a/nfapi/oai_integration/nfapi_pnf.h b/nfapi/oai_integration/nfapi_pnf.h index 2c8201737c..b3ab7cbdbc 100644 --- a/nfapi/oai_integration/nfapi_pnf.h +++ b/nfapi/oai_integration/nfapi_pnf.h @@ -23,5 +23,8 @@ #define NFAPI_PNF_H__ int oai_nfapi_rach_ind(nfapi_rach_indication_t *rach_ind); void configure_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_addr, int pnf_p7_port, int vnf_p7_port); +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); + void oai_subframe_ind(uint16_t sfn, uint16_t sf); +void oai_slot_ind(uint16_t sfn, uint16_t slot); #endif diff --git a/nfapi/oai_integration/nfapi_vnf.c b/nfapi/oai_integration/nfapi_vnf.c index f76cad87f7..485f17922f 100644 --- a/nfapi/oai_integration/nfapi_vnf.c +++ b/nfapi/oai_integration/nfapi_vnf.c @@ -39,8 +39,12 @@ #include "nfapi_vnf.h" #include "PHY/defs_eNB.h" #include "PHY/LTE_TRANSPORT/transport_proto.h" +#include "openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h" #include "common/ran_context.h" + +#define TEST + extern RAN_CONTEXT_t RC; extern UL_RCC_IND_t UL_RCC_INFO; @@ -189,11 +193,12 @@ int vnf_pack_vendor_extension_tlv(void *ve, uint8_t **ppWritePackedMsg, uint8_t int vnf_unpack_vendor_extension_tlv(nfapi_tl_t *tl, uint8_t **ppReadPackedMessage, uint8_t *end, void **ve, nfapi_p4_p5_codec_config_t *codec) { return -1; } - +void install_nr_schedule_handlers(NR_IF_Module_t *if_inst); void install_schedule_handlers(IF_Module_t *if_inst); extern int single_thread_flag; extern void init_eNB_afterRU(void); extern uint16_t sf_ahead; +extern uint16_t slot_ahead; void oai_create_enb(void) { int bodge_counter=0; @@ -231,6 +236,39 @@ void oai_enb_init(void) { init_eNB_afterRU(); } + +void oai_create_gnb(void) { + int bodge_counter=0; + PHY_VARS_gNB *gNB = RC.gNB[0]; + RC.nb_nr_CC = (int *)malloc(sizeof(int)); // TODO: find a better function to place this in + + gNB->Mod_id = bodge_counter; + gNB->CC_id = bodge_counter; + gNB->abstraction_flag = 0; + gNB->single_thread_flag = 0;//single_thread_flag; + RC.nb_nr_CC[bodge_counter] = 1; + + if (gNB->if_inst==0) { + gNB->if_inst = NR_IF_Module_init(bodge_counter); + } + + + // This will cause phy_config_request to be installed. That will result in RRC configuring the PHY + // that will result in gNB->configured being set to TRUE. + // See we need to wait for that to happen otherwise the NFAPI message exchanges won't contain the right parameter values + if (RC.gNB[0]->if_inst==0 || RC.gNB[0]->if_inst->NR_PHY_config_req==0 || RC.gNB[0]->if_inst->NR_Schedule_response==0) { + printf("RC.gNB[0][0]->if_inst->NR_PHY_config_req is not installed - install it\n"); + install_nr_schedule_handlers(RC.gNB[0]->if_inst); + } + + do { + printf("%s() Waiting for gNB to become configured (by RRC/PHY) - need to wait otherwise NFAPI messages won't contain correct values\n", __FUNCTION__); + usleep(50000); + } while(gNB->configured != 1); + + printf("%s() gNB is now configured\n", __FUNCTION__); +} + int pnf_connection_indication_cb(nfapi_vnf_config_t *config, int p5_idx) { printf("[VNF] pnf connection indication idx:%d\n", p5_idx); oai_create_enb(); @@ -241,6 +279,16 @@ int pnf_connection_indication_cb(nfapi_vnf_config_t *config, int p5_idx) { return 0; } +int pnf_nr_connection_indication_cb(nfapi_vnf_config_t *config, int p5_idx) { + printf("[VNF] pnf connection indication idx:%d\n", p5_idx); + oai_create_gnb(); + nfapi_nr_pnf_param_request_t req; + memset(&req, 0, sizeof(req)); + req.header.message_id = NFAPI_NR_PHY_MSG_TYPE_PNF_PARAM_REQUEST; + nfapi_nr_vnf_pnf_param_req(config, p5_idx, &req); + return 0; +} + int pnf_disconnection_indication_cb(nfapi_vnf_config_t *config, int p5_idx) { printf("[VNF] pnf disconnection indication idx:%d\n", p5_idx); vnf_info *vnf = (vnf_info *)(config->user_data); @@ -251,6 +299,42 @@ int pnf_disconnection_indication_cb(nfapi_vnf_config_t *config, int p5_idx) { return 0; } +int pnf_nr_param_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_nr_pnf_param_response_t *resp) { + printf("[VNF] pnf param response idx:%d error:%d\n", p5_idx, resp->error_code); + vnf_info *vnf = (vnf_info *)(config->user_data); + pnf_info *pnf = vnf->pnfs; + + for(int i = 0; i < resp->pnf_phy.number_of_phys; ++i) { + phy_info phy; + memset(&phy,0,sizeof(phy)); + phy.index = resp->pnf_phy.phy[i].phy_config_index; + printf("[VNF] (PHY:%d) phy_config_idx:%d\n", i, resp->pnf_phy.phy[i].phy_config_index); + nfapi_vnf_allocate_phy(config, p5_idx, &(phy.id)); + + for(int j = 0; j < resp->pnf_phy.phy[i].number_of_rfs; ++j) { + printf("[VNF] (PHY:%d) (RF%d) %d\n", i, j, resp->pnf_phy.phy[i].rf_config[j].rf_config_index); + phy.rfs[0] = resp->pnf_phy.phy[i].rf_config[j].rf_config_index; + } + + pnf->phys[0] = phy; + } + nfapi_nr_pnf_config_request_t req; + memset(&req, 0, sizeof(req)); + req.header.message_id = NFAPI_PNF_CONFIG_REQUEST; + req.pnf_phy_rf_config.tl.tag = NFAPI_PNF_PHY_RF_TAG; + req.pnf_phy_rf_config.number_phy_rf_config_info = 2; // DJP pnf.phys.size(); + printf("DJP:Hard coded num phy rf to 2\n"); + + for(unsigned i = 0; i < 2; ++i) { + req.pnf_phy_rf_config.phy_rf_config[i].phy_id = pnf->phys[i].id; + req.pnf_phy_rf_config.phy_rf_config[i].phy_config_index = pnf->phys[i].index; + req.pnf_phy_rf_config.phy_rf_config[i].rf_config_index = pnf->phys[i].rfs[0]; + } + + nfapi_nr_vnf_pnf_config_req(config, p5_idx, &req); + return 0; +} + int pnf_param_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_pnf_param_response_t *resp) { printf("[VNF] pnf param response idx:%d error:%d\n", p5_idx, resp->error_code); vnf_info *vnf = (vnf_info *)(config->user_data); @@ -270,7 +354,6 @@ int pnf_param_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_pnf_param_re pnf->phys[0] = phy; } - for(int i = 0; i < resp->pnf_rf.number_of_rfs; ++i) { rf_info rf; memset(&rf,0,sizeof(rf)); @@ -278,7 +361,6 @@ int pnf_param_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_pnf_param_re printf("[VNF] (RF:%d) rf_config_idx:%d\n", i, resp->pnf_rf.rf[i].rf_config_index); pnf->rfs[0] = rf; } - nfapi_pnf_config_request_t req; memset(&req, 0, sizeof(req)); req.header.message_id = NFAPI_PNF_CONFIG_REQUEST; @@ -296,6 +378,31 @@ int pnf_param_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_pnf_param_re return 0; } +int pnf_nr_config_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_nr_pnf_config_response_t *resp) { + printf("[VNF] pnf config response idx:%d resp[header[phy_id:%u message_id:%02x message_length:%u]]\n", p5_idx, resp->header.phy_id, resp->header.message_id, resp->header.message_length); + + if(1) { + nfapi_nr_pnf_start_request_t req; + memset(&req, 0, sizeof(req)); + req.header.phy_id = resp->header.phy_id; + req.header.message_id = NFAPI_PNF_START_REQUEST; + nfapi_nr_vnf_pnf_start_req(config, p5_idx, &req); + } else { + // Rather than send the pnf_start_request we will demonstrate + // sending a vendor extention message. The start request will be + // send when the vendor extension response is received + //vnf_info* vnf = (vnf_info*)(config->user_data); + vendor_ext_p5_req req; + memset(&req, 0, sizeof(req)); + req.header.message_id = P5_VENDOR_EXT_REQ; + req.dummy1 = 45; + req.dummy2 = 1977; + nfapi_vnf_vendor_extension(config, p5_idx, &req.header); + } + + return 0; +} + int pnf_config_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_pnf_config_response_t *resp) { printf("[VNF] pnf config response idx:%d resp[header[phy_id:%u message_id:%02x message_length:%u]]\n", p5_idx, resp->header.phy_id, resp->header.message_id, resp->header.message_length); @@ -321,6 +428,70 @@ int pnf_config_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_pnf_config_ return 0; } +int wake_gNB_rxtx(PHY_VARS_gNB *gNB, uint16_t sfn, uint16_t slot) { + struct timespec curr_t; + clock_gettime(CLOCK_MONOTONIC,&curr_t); + //printf("\n wake_gNB_rxtx before assignment sfn:%d slot:%d TIME %d.%d",sfn,slot,curr_t.tv_sec,curr_t.tv_nsec); + gNB_L1_proc_t *proc=&gNB->proc; + gNB_L1_rxtx_proc_t *L1_proc= (slot&1)? &proc->L1_proc : &proc->L1_proc_tx; + + NR_DL_FRAME_PARMS *fp = &gNB->frame_parms; + //printf("%s(eNB:%p, sfn:%d, sf:%d)\n", __FUNCTION__, eNB, sfn, sf); + //int i; + struct timespec wait; + clock_gettime(CLOCK_REALTIME, &wait); + wait.tv_sec = 0; + wait.tv_nsec +=5000L; + //wait.tv_nsec = 0; + // wake up TX for subframe n+sf_ahead + // lock the TX mutex and make sure the thread is ready + if (pthread_mutex_timedlock(&L1_proc->mutex,&wait) != 0) { + LOG_E( PHY, "[gNB] ERROR pthread_mutex_lock for gNB RXTX thread %d (IC %d)\n", L1_proc->slot_rx&1,L1_proc->instance_cnt ); + exit_fun( "error locking mutex_rxtx" ); + return(-1); + } + + { + static uint16_t old_slot = 0; + static uint16_t old_sfn = 0; + proc->slot_rx = old_slot; + proc->frame_rx = old_sfn; + // Try to be 1 frame back + old_slot = slot; + old_sfn = sfn; + //printf("\n wake_gNB_rxtx after assignment sfn:%d slot:%d",proc->frame_rx,proc->slot_rx); + if (old_slot == 0 && old_sfn % 100 == 0) LOG_W( PHY,"[gNB] sfn/slot:%d%d old_sfn/slot:%d%d proc[rx:%d%d]\n", sfn, slot, old_sfn, old_slot, proc->frame_rx, proc->slot_rx); + } + + ++L1_proc->instance_cnt; + //LOG_D( PHY,"[VNF-subframe_ind] sfn/sf:%d:%d proc[frame_rx:%d subframe_rx:%d] L1_proc->instance_cnt_rxtx:%d \n", sfn, sf, proc->frame_rx, proc->subframe_rx, L1_proc->instance_cnt_rxtx); + // We have just received and processed the common part of a subframe, say n. + // TS_rx is the last received timestamp (start of 1st slot), TS_tx is the desired + // transmitted timestamp of the next TX slot (first). + // The last (TS_rx mod samples_per_frame) was n*samples_per_tti, + // we want to generate subframe (n+N), so TS_tx = TX_rx+N*samples_per_tti, + // and proc->subframe_tx = proc->subframe_rx+sf_ahead + L1_proc->timestamp_tx = proc->timestamp_rx + (slot_ahead *fp->samples_per_subframe); + L1_proc->frame_rx = proc->frame_rx; + L1_proc->slot_rx = proc->slot_rx; + L1_proc->frame_tx = (L1_proc->slot_rx > (19-slot_ahead)) ? (L1_proc->frame_rx+1)&1023 : L1_proc->frame_rx; + L1_proc->slot_tx = (L1_proc->slot_rx + slot_ahead)%20; + + //LOG_I(PHY, "sfn/sf:%d%d proc[rx:%d%d] rx:%d%d] About to wake rxtx thread\n\n", sfn, slot, proc->frame_rx, proc->slot_rx, L1_proc->frame_rx, L1_proc->slot_rx); + //printf("\nEntering wake_gNB_rxtx sfn %d slot %d\n",L1_proc->frame_rx,L1_proc->slot_rx); + // the thread can now be woken up + if (pthread_cond_signal(&L1_proc->cond) != 0) { + LOG_E( PHY, "[gNB] ERROR pthread_cond_signal for gNB RXn-TXnp4 thread\n"); + exit_fun( "ERROR pthread_clond_signal" ); + return(-1); + } + + //LOG_D(PHY,"%s() About to attempt pthread_mutex_unlock\n", __FUNCTION__); + pthread_mutex_unlock( &L1_proc->mutex ); + //LOG_D(PHY,"%s() UNLOCKED pthread_mutex_unlock\n", __FUNCTION__); + return(0); +} + int wake_eNB_rxtx(PHY_VARS_eNB *eNB, uint16_t sfn, uint16_t sf) { L1_proc_t *proc=&eNB->proc; L1_rxtx_proc_t *L1_proc= (sf&1)? &proc->L1_proc : &proc->L1_proc_tx; @@ -416,6 +587,7 @@ int phy_sync_indication(struct nfapi_vnf_p7_config *config, uint8_t sync) { printf("[VNF] SYNC %s\n", sync==1 ? "ACHIEVED" : "LOST"); if (sync==1 && nfapi_sync_var!=0) { + printf("[VNF] Signal to OAI main code that it can go\n"); pthread_mutex_lock(&nfapi_sync_mutex); nfapi_sync_var=0; @@ -426,6 +598,29 @@ int phy_sync_indication(struct nfapi_vnf_p7_config *config, uint8_t sync) { return(0); } + +int phy_slot_indication(struct nfapi_vnf_p7_config *config, uint16_t phy_id, uint16_t sfn, uint16_t slot) { + static uint8_t first_time = 1; + + if (first_time) { + printf("[VNF] slot indication %d\n", NFAPI_SFNSLOT2DEC(sfn, slot)); + first_time = 0; + } + + if (RC.gNB && RC.gNB[0]->configured) { + // uint16_t sfn = NFAPI_SFNSF2SFN(sfn_sf); + // uint16_t sf = NFAPI_SFNSF2SF(sfn_sf); + LOG_D(PHY,"[VNF] slot indication sfn:%d sf:%d\n", sfn, slot); + wake_gNB_rxtx(RC.gNB[0], sfn, slot); // DONE: find NR equivalent + } else { + printf("[VNF] %s() RC.gNB:%p\n", __FUNCTION__, RC.gNB); + + if (RC.gNB) printf("RC.gNB[0]->configured:%d\n", RC.gNB[0]->configured); + } + + return 0; +} + int phy_subframe_indication(struct nfapi_vnf_p7_config *config, uint16_t phy_id, uint16_t sfn_sf) { static uint8_t first_time = 1; @@ -937,6 +1132,14 @@ int vnf_pack_p4_p5_vendor_extension(nfapi_p4_p5_message_header_t *header, uint8_ static pthread_t vnf_start_pthread; static pthread_t vnf_p7_start_pthread; +void *vnf_nr_p7_start_thread(void *ptr) { + printf("%s()\n", __FUNCTION__); + pthread_setname_np(pthread_self(), "VNF_P7"); + nfapi_vnf_p7_config_t *config = (nfapi_vnf_p7_config_t *)ptr; + nfapi_nr_vnf_p7_start(config); + return config; +} + void *vnf_p7_start_thread(void *ptr) { printf("%s()\n", __FUNCTION__); pthread_setname_np(pthread_self(), "VNF_P7"); @@ -947,12 +1150,13 @@ void *vnf_p7_start_thread(void *ptr) { void set_thread_priority(int priority); -void *vnf_p7_thread_start(void *ptr) { +void *vnf_nr_p7_thread_start(void *ptr) { set_thread_priority(79); vnf_p7_info *p7_vnf = (vnf_p7_info *)ptr; p7_vnf->config->port = p7_vnf->local_port; p7_vnf->config->sync_indication = &phy_sync_indication; - p7_vnf->config->subframe_indication = &phy_subframe_indication; + p7_vnf->config->slot_indication = &phy_slot_indication; + p7_vnf->config->harq_indication = &phy_harq_indication; p7_vnf->config->crc_indication = &phy_crc_indication; p7_vnf->config->rx_indication = &phy_rx_indication; @@ -977,11 +1181,72 @@ void *vnf_p7_thread_start(void *ptr) { p7_vnf->config->codec_config.deallocate = &vnf_deallocate; p7_vnf->config->allocate_p7_vendor_ext = &phy_allocate_p7_vendor_ext; p7_vnf->config->deallocate_p7_vendor_ext = &phy_deallocate_p7_vendor_ext; - NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Creating VNF NFAPI start thread %s\n", __FUNCTION__); + NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Creating VNF NFAPI P7 start thread %s\n", __FUNCTION__); + pthread_create(&vnf_p7_start_pthread, NULL, &vnf_nr_p7_start_thread, p7_vnf->config); + return 0; +} + +void *vnf_p7_thread_start(void *ptr) { + set_thread_priority(79); + vnf_p7_info *p7_vnf = (vnf_p7_info *)ptr; + p7_vnf->config->port = p7_vnf->local_port; + p7_vnf->config->sync_indication = &phy_sync_indication; + p7_vnf->config->subframe_indication = &phy_subframe_indication; + p7_vnf->config->slot_indication = &phy_slot_indication; + + p7_vnf->config->harq_indication = &phy_harq_indication; + p7_vnf->config->crc_indication = &phy_crc_indication; + p7_vnf->config->rx_indication = &phy_rx_indication; + p7_vnf->config->rach_indication = &phy_rach_indication; + p7_vnf->config->srs_indication = &phy_srs_indication; + p7_vnf->config->sr_indication = &phy_sr_indication; + p7_vnf->config->cqi_indication = &phy_cqi_indication; + p7_vnf->config->lbt_dl_indication = &phy_lbt_dl_indication; + p7_vnf->config->nb_harq_indication = &phy_nb_harq_indication; + p7_vnf->config->nrach_indication = &phy_nrach_indication; + p7_vnf->config->malloc = &vnf_allocate; + p7_vnf->config->free = &vnf_deallocate; + p7_vnf->config->trace = &vnf_trace; + p7_vnf->config->vendor_ext = &phy_vendor_ext; + p7_vnf->config->user_data = p7_vnf; + p7_vnf->mac->user_data = p7_vnf; + p7_vnf->config->codec_config.unpack_p7_vendor_extension = &phy_unpack_p7_vendor_extension; + p7_vnf->config->codec_config.pack_p7_vendor_extension = &phy_pack_p7_vendor_extension; + p7_vnf->config->codec_config.unpack_vendor_extension_tlv = &phy_unpack_vendor_extension_tlv; + p7_vnf->config->codec_config.pack_vendor_extension_tlv = &phy_pack_vendor_extension_tlv; + p7_vnf->config->codec_config.allocate = &vnf_allocate; + p7_vnf->config->codec_config.deallocate = &vnf_deallocate; + p7_vnf->config->allocate_p7_vendor_ext = &phy_allocate_p7_vendor_ext; + p7_vnf->config->deallocate_p7_vendor_ext = &phy_deallocate_p7_vendor_ext; + NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Creating VNF NFAPI P7 start thread %s\n", __FUNCTION__); pthread_create(&vnf_p7_start_pthread, NULL, &vnf_p7_start_thread, p7_vnf->config); return 0; } +int pnf_nr_start_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_nr_pnf_start_response_t *resp) { + vnf_info *vnf = (vnf_info *)(config->user_data); + vnf_p7_info *p7_vnf = vnf->p7_vnfs; + pnf_info *pnf = vnf->pnfs; + nfapi_nr_param_request_scf_t req; + printf("[VNF] pnf start response idx:%d config:%p user_data:%p p7_vnf[config:%p thread_started:%d]\n", p5_idx, config, config->user_data, vnf->p7_vnfs[0].config, vnf->p7_vnfs[0].thread_started); + + if(p7_vnf->thread_started == 0) { + pthread_t vnf_p7_thread; + pthread_create(&vnf_p7_thread, NULL, &vnf_nr_p7_thread_start, p7_vnf); + p7_vnf->thread_started = 1; + } else { + // P7 thread already running. + } + + // start all the phys in the pnf. + printf("[VNF] Sending NFAPI_VNF_PARAM_REQUEST phy_id:%d\n", pnf->phys[0].id); + memset(&req, 0, sizeof(req)); + req.header.message_id = NFAPI_NR_PHY_MSG_TYPE_PARAM_REQUEST; + req.header.phy_id = pnf->phys[0].id; + nfapi_nr_vnf_param_req(config, p5_idx, &req); + return 0; +} + int pnf_start_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_pnf_start_response_t *resp) { vnf_info *vnf = (vnf_info *)(config->user_data); vnf_p7_info *p7_vnf = vnf->p7_vnfs; @@ -998,7 +1263,7 @@ int pnf_start_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_pnf_start_re } // start all the phys in the pnf. - printf("[VNF] Sending NFAPI_PARAM_REQUEST phy_id:%d\n", pnf->phys[0].id); + printf("[VNF] Sending NFAPI_VNF_PARAM_REQUEST phy_id:%d\n", pnf->phys[0].id); memset(&req, 0, sizeof(req)); req.header.message_id = NFAPI_PARAM_REQUEST; req.header.phy_id = pnf->phys[0].id; @@ -1008,6 +1273,69 @@ int pnf_start_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_pnf_start_re extern uint32_t to_earfcn(int eutra_bandP,uint32_t dl_CarrierFreq,uint32_t bw); +int nr_param_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_nr_param_response_scf_t *resp) { + + printf("[VNF] Received NFAPI_PARAM_RESP idx:%d phy_id:%d\n", p5_idx, resp->header.phy_id); + vnf_info *vnf = (vnf_info *)(config->user_data); + vnf_p7_info *p7_vnf = vnf->p7_vnfs; + pnf_info *pnf = vnf->pnfs; + phy_info *phy = pnf->phys; + struct sockaddr_in pnf_p7_sockaddr; + nfapi_nr_config_request_scf_t *req = &RC.nrmac[0]->config[0]; // check + phy->remote_port = 32123;//resp->nfapi_config.p7_pnf_port.value; + memcpy(&pnf_p7_sockaddr.sin_addr.s_addr, &(resp->nfapi_config.p7_pnf_address_ipv4.address[0]), 4); + phy->remote_addr = inet_ntoa(pnf_p7_sockaddr.sin_addr); + // for now just 1 + printf("[VNF] %d.%d pnf p7 %s:%d timing %u %u %u %u\n", p5_idx, phy->id, phy->remote_addr, phy->remote_port, p7_vnf->timing_window, p7_vnf->periodic_timing_period, p7_vnf->aperiodic_timing_enabled, + p7_vnf->periodic_timing_period); + req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_CONFIG_REQUEST; + req->header.phy_id = phy->id; + printf("[VNF] Send NFAPI_CONFIG_REQUEST\n"); + //printf("\n NR bandP =%d\n",req->nfapi_config.rf_bands.rf_band[0]); + + req->nfapi_config.p7_vnf_port.tl.tag = NFAPI_NR_NFAPI_P7_VNF_PORT_TAG; + req->nfapi_config.p7_vnf_port.value = p7_vnf->local_port; + req->num_tlv++; + printf("[VNF] DJP local_port:%d\n", p7_vnf->local_port); + req->nfapi_config.p7_vnf_address_ipv4.tl.tag = NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV4_TAG; + struct sockaddr_in vnf_p7_sockaddr; + vnf_p7_sockaddr.sin_addr.s_addr = inet_addr(p7_vnf->local_addr); + memcpy(&(req->nfapi_config.p7_vnf_address_ipv4.address[0]), &vnf_p7_sockaddr.sin_addr.s_addr, 4); + req->num_tlv++; + printf("[VNF] DJP local_addr:%s\n", p7_vnf->local_addr); + req->nfapi_config.timing_window.tl.tag = NFAPI_NR_NFAPI_TIMING_WINDOW_TAG; + req->nfapi_config.timing_window.value = p7_vnf->timing_window; + printf("\n[VNF]Timing window tag : %d Timing window:%u\n",NFAPI_NR_NFAPI_TIMING_WINDOW_TAG, p7_vnf->timing_window); + req->num_tlv++; + + if(p7_vnf->periodic_timing_enabled || p7_vnf->aperiodic_timing_enabled) { + req->nfapi_config.timing_info_mode.tl.tag = NFAPI_NR_NFAPI_TIMING_INFO_MODE_TAG; + req->nfapi_config.timing_info_mode.value = (p7_vnf->aperiodic_timing_enabled << 1) | (p7_vnf->periodic_timing_enabled); + req->num_tlv++; + + if(p7_vnf->periodic_timing_enabled) { + req->nfapi_config.timing_info_period.tl.tag = NFAPI_NR_NFAPI_TIMING_INFO_PERIOD_TAG; + req->nfapi_config.timing_info_period.value = p7_vnf->periodic_timing_period; + req->num_tlv++; + } + } +//TODO: Assign tag and value for P7 message offsets +req->nfapi_config.dl_tti_timing_offset.tl.tag = NFAPI_NR_NFAPI_DL_TTI_TIMING_OFFSET; +req->nfapi_config.ul_tti_timing_offset.tl.tag = NFAPI_NR_NFAPI_UL_TTI_TIMING_OFFSET; +req->nfapi_config.ul_dci_timing_offset.tl.tag = NFAPI_NR_NFAPI_UL_DCI_TIMING_OFFSET; +req->nfapi_config.tx_data_timing_offset.tl.tag = NFAPI_NR_NFAPI_TX_DATA_TIMING_OFFSET; + + vendor_ext_tlv_2 ve2; + memset(&ve2, 0, sizeof(ve2)); + ve2.tl.tag = VENDOR_EXT_TLV_2_TAG; + ve2.dummy = 2016; + req->vendor_extension = &ve2.tl; + nfapi_nr_vnf_config_req(config, p5_idx, req); + printf("[VNF] Sent NFAPI_VNF_CONFIG_REQ num_tlv:%u\n",req->num_tlv); + return 0; +} + + int param_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_param_response_t *resp) { printf("[VNF] Received NFAPI_PARAM_RESP idx:%d phy_id:%d\n", p5_idx, resp->header.phy_id); vnf_info *vnf = (vnf_info *)(config->user_data); @@ -1016,7 +1344,7 @@ int param_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_param_response_t phy_info *phy = pnf->phys; struct sockaddr_in pnf_p7_sockaddr; nfapi_config_request_t *req = &RC.mac[0]->config[0]; - phy->remote_port = resp->nfapi_config.p7_pnf_port.value; + phy->remote_port = 32123;//resp->nfapi_config.p7_pnf_port.value; memcpy(&pnf_p7_sockaddr.sin_addr.s_addr, &(resp->nfapi_config.p7_pnf_address_ipv4.address[0]), 4); phy->remote_addr = inet_ntoa(pnf_p7_sockaddr.sin_addr); // for now just 1 @@ -1062,6 +1390,19 @@ int param_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_param_response_t return 0; } +int nr_config_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_nr_config_response_scf_t *resp) { + nfapi_nr_start_request_scf_t req; + printf("[VNF] Received NFAPI_CONFIG_RESP idx:%d phy_id:%d\n", p5_idx, resp->header.phy_id); + printf("[VNF] Calling oai_enb_init()\n"); + oai_enb_init(); // TODO: change to gnb + memset(&req, 0, sizeof(req)); + req.header.message_id = NFAPI_NR_PHY_MSG_TYPE_START_REQUEST; + req.header.phy_id = resp->header.phy_id; + nfapi_nr_vnf_start_req(config, p5_idx, &req); + printf("[VNF] Send NFAPI_VNF_START_REQUEST idx:%d phy_id:%d\n", p5_idx, resp->header.phy_id); + return 0; +} + int config_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_config_response_t *resp) { nfapi_start_request_t req; printf("[VNF] Received NFAPI_CONFIG_RESP idx:%d phy_id:%d\n", p5_idx, resp->header.phy_id); @@ -1085,6 +1426,17 @@ int start_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_start_response_t return 0; } +int nr_start_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_nr_start_response_scf_t *resp) { + printf("[VNF] Received NFAPI_START_RESP idx:%d phy_id:%d\n", p5_idx, resp->header.phy_id); + vnf_info *vnf = (vnf_info *)(config->user_data); + pnf_info *pnf = vnf->pnfs; + phy_info *phy = pnf->phys; + vnf_p7_info *p7_vnf = vnf->p7_vnfs; + + nfapi_vnf_p7_add_pnf((p7_vnf->config), phy->remote_addr, phy->remote_port, phy->id); + return 0; +} + int vendor_ext_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_p4_p5_message_header_t *msg) { printf("[VNF] %s\n", __FUNCTION__); @@ -1129,6 +1481,13 @@ void vnf_deallocate_p4_p5_vendor_ext(nfapi_p4_p5_message_header_t *header) { nfapi_vnf_config_t *config = 0; +void vnf_nr_start_thread(void *ptr) { + NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] VNF NFAPI thread - nfapi_vnf_start()%s\n", __FUNCTION__); + pthread_setname_np(pthread_self(), "VNF"); + config = (nfapi_vnf_config_t *)ptr; + nfapi_nr_vnf_start(config); +} + void vnf_start_thread(void *ptr) { NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] VNF NFAPI thread - nfapi_vnf_start()%s\n", __FUNCTION__); pthread_setname_np(pthread_self(), "VNF"); @@ -1138,7 +1497,57 @@ void vnf_start_thread(void *ptr) { static vnf_info vnf; -/*------------------------------------------------------------------------------*/ +void configure_nr_nfapi_vnf(char *vnf_addr, int vnf_p5_port) { + nfapi_setmode(NFAPI_MODE_VNF); + memset(&vnf, 0, sizeof(vnf)); + memset(vnf.p7_vnfs, 0, sizeof(vnf.p7_vnfs)); + vnf.p7_vnfs[0].timing_window = 32; + vnf.p7_vnfs[0].periodic_timing_enabled = 1; + vnf.p7_vnfs[0].aperiodic_timing_enabled = 0; + vnf.p7_vnfs[0].periodic_timing_period = 10; + vnf.p7_vnfs[0].config = nfapi_vnf_p7_config_create(); + NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] %s() vnf.p7_vnfs[0].config:%p VNF ADDRESS:%s:%d\n", __FUNCTION__, vnf.p7_vnfs[0].config, vnf_addr, vnf_p5_port); + strcpy(vnf.p7_vnfs[0].local_addr, vnf_addr); + //vnf.p7_vnfs[0].local_port = vnf.p7_vnfs[0].local_port; // 50001; // TODO: remove hardcode + vnf.p7_vnfs[0].local_port = 50011; + vnf.p7_vnfs[0].mac = (mac_t *)malloc(sizeof(mac_t)); + nfapi_vnf_config_t *config = nfapi_vnf_config_create(); + config->malloc = malloc; + config->free = free; + config->trace = &vnf_trace; + config->vnf_p5_port = vnf_p5_port; + config->vnf_ipv4 = 1; + config->vnf_ipv6 = 0; + config->pnf_list = 0; + config->phy_list = 0; + + config->pnf_nr_connection_indication = &pnf_nr_connection_indication_cb; + config->pnf_disconnect_indication = &pnf_disconnection_indication_cb; + + config->pnf_nr_param_resp = &pnf_nr_param_resp_cb; + config->pnf_nr_config_resp = &pnf_nr_config_resp_cb; + config->pnf_nr_start_resp = &pnf_nr_start_resp_cb; + config->nr_param_resp = &nr_param_resp_cb; + config->nr_config_resp = &nr_config_resp_cb; + config->nr_start_resp = &nr_start_resp_cb; + config->vendor_ext = &vendor_ext_cb; + config->user_data = &vnf; + // To allow custom vendor extentions to be added to nfapi + config->codec_config.unpack_vendor_extension_tlv = &vnf_unpack_vendor_extension_tlv; + config->codec_config.pack_vendor_extension_tlv = &vnf_pack_vendor_extension_tlv; + config->codec_config.unpack_p4_p5_vendor_extension = &vnf_unpack_p4_p5_vendor_extension; + config->codec_config.pack_p4_p5_vendor_extension = &vnf_pack_p4_p5_vendor_extension; + config->allocate_p4_p5_vendor_ext = &vnf_allocate_p4_p5_vendor_ext; + config->deallocate_p4_p5_vendor_ext = &vnf_deallocate_p4_p5_vendor_ext; + config->codec_config.allocate = &vnf_allocate; + config->codec_config.deallocate = &vnf_deallocate; + memset(&UL_RCC_INFO,0,sizeof(UL_RCC_IND_t)); + NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Creating VNF NFAPI start thread %s\n", __FUNCTION__); + pthread_create(&vnf_start_pthread, NULL, (void *)&vnf_nr_start_thread, config); + NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Created VNF NFAPI start thread %s\n", __FUNCTION__); +} + + void configure_nfapi_vnf(char *vnf_addr, int vnf_p5_port) { nfapi_setmode(NFAPI_MODE_VNF); memset(&vnf, 0, sizeof(vnf)); @@ -1150,7 +1559,8 @@ void configure_nfapi_vnf(char *vnf_addr, int vnf_p5_port) { vnf.p7_vnfs[0].config = nfapi_vnf_p7_config_create(); NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] %s() vnf.p7_vnfs[0].config:%p VNF ADDRESS:%s:%d\n", __FUNCTION__, vnf.p7_vnfs[0].config, vnf_addr, vnf_p5_port); strcpy(vnf.p7_vnfs[0].local_addr, vnf_addr); - vnf.p7_vnfs[0].local_port = 50001; + //vnf.p7_vnfs[0].local_port = vnf.p7_vnfs[0].local_port; // 50001; // TODO: remove hardcode + vnf.p7_vnfs[0].local_port = 50011; vnf.p7_vnfs[0].mac = (mac_t *)malloc(sizeof(mac_t)); nfapi_vnf_config_t *config = nfapi_vnf_config_create(); config->malloc = malloc; @@ -1161,8 +1571,10 @@ void configure_nfapi_vnf(char *vnf_addr, int vnf_p5_port) { config->vnf_ipv6 = 0; config->pnf_list = 0; config->phy_list = 0; + config->pnf_connection_indication = &pnf_connection_indication_cb; config->pnf_disconnect_indication = &pnf_disconnection_indication_cb; + config->pnf_param_resp = &pnf_param_resp_cb; config->pnf_config_resp = &pnf_config_resp_cb; config->pnf_start_resp = &pnf_start_resp_cb; @@ -1203,15 +1615,17 @@ int oai_nfapi_dl_config_req(nfapi_dl_config_request_t *dl_config_req) { return retval; } -int oai_nfapi_nr_dl_config_req(nfapi_nr_dl_tti_request_t *dl_config_req) +int oai_nfapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req) { + //LOG_I(PHY, "sfn:%d,slot:%d\n",dl_config_req->SFN,dl_config_req->Slot); + //printf("\nEntering oai_nfapi_nr_dl_config_req sfn:%d,slot:%d\n",dl_config_req->SFN,dl_config_req->Slot); nfapi_vnf_p7_config_t *p7_config = vnf.p7_vnfs[0].config; - + dl_config_req->header.message_id= NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST; dl_config_req->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! int retval = nfapi_vnf_p7_nr_dl_config_req(p7_config, dl_config_req); - dl_config_req->dl_tti_request_body.nPDUs = 0; + dl_config_req->dl_tti_request_body.nPDUs = 0; dl_config_req->dl_tti_request_body.nGroup = 0; @@ -1221,6 +1635,23 @@ int oai_nfapi_nr_dl_config_req(nfapi_nr_dl_tti_request_t *dl_config_req) return retval; } +int oai_nfapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req) +{ + nfapi_vnf_p7_config_t *p7_config = vnf.p7_vnfs[0].config; + tx_data_req->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! + tx_data_req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST; + //LOG_D(PHY, "[VNF] %s() TX_REQ sfn_sf:%d number_of_pdus:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(tx_req->sfn_sf), tx_req->tx_request_body.number_of_pdus); + int retval = nfapi_vnf_p7_tx_data_req(p7_config, tx_data_req); + + if (retval!=0) { + LOG_E(PHY, "%s() Problem sending retval:%d\n", __FUNCTION__, retval); + } else { + tx_data_req->Number_of_PDUs = 0; + } + + return retval; +} + int oai_nfapi_tx_req(nfapi_tx_request_t *tx_req) { nfapi_vnf_p7_config_t *p7_config = vnf.p7_vnfs[0].config; @@ -1238,6 +1669,22 @@ int oai_nfapi_tx_req(nfapi_tx_request_t *tx_req) return retval; } +int oai_nfapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req) { + nfapi_vnf_p7_config_t *p7_config = vnf.p7_vnfs[0].config; + ul_dci_req->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! + ul_dci_req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST; + //LOG_D(PHY, "[VNF] %s() HI_DCI0_REQ sfn_sf:%d dci:%d hi:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(hi_dci0_req->sfn_sf), hi_dci0_req->hi_dci0_request_body.number_of_dci, hi_dci0_req->hi_dci0_request_body.number_of_hi); + int retval = nfapi_vnf_p7_ul_dci_req(p7_config, ul_dci_req); + + if (retval!=0) { + LOG_E(PHY, "%s() Problem sending retval:%d\n", __FUNCTION__, retval); + } else { + ul_dci_req->numPdus = 0; + } + + return retval; +} + int oai_nfapi_hi_dci0_req(nfapi_hi_dci0_request_t *hi_dci0_req) { nfapi_vnf_p7_config_t *p7_config = vnf.p7_vnfs[0].config; hi_dci0_req->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! @@ -1255,6 +1702,26 @@ int oai_nfapi_hi_dci0_req(nfapi_hi_dci0_request_t *hi_dci0_req) { return retval; } +int oai_nfapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req) { + nfapi_vnf_p7_config_t *p7_config = vnf.p7_vnfs[0].config; + + ul_tti_req->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! + ul_tti_req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST; + + int retval = nfapi_vnf_p7_ul_tti_req(p7_config, ul_tti_req); + + if (retval!=0) { + LOG_E(PHY, "%s() Problem sending retval:%d\n", __FUNCTION__, retval); + } else { + // Reset number of PDUs so that it is not resent + ul_tti_req->n_pdus = 0; + ul_tti_req->n_group = 0; + ul_tti_req->n_ulcch = 0; + ul_tti_req->n_ulsch = 0; + } + return retval; +} + int oai_nfapi_ul_config_req(nfapi_ul_config_request_t *ul_config_req) { nfapi_vnf_p7_config_t *p7_config = vnf.p7_vnfs[0].config; ul_config_req->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! diff --git a/nfapi/oai_integration/nfapi_vnf.h b/nfapi/oai_integration/nfapi_vnf.h index 4ea26eda12..f4fd6a2bf9 100644 --- a/nfapi/oai_integration/nfapi_vnf.h +++ b/nfapi/oai_integration/nfapi_vnf.h @@ -23,5 +23,5 @@ #define NFAPI_VNF_H__ void configure_nfapi_vnf(char *vnf_addr, int vnf_p5_port); - +void configure_nr_nfapi_vnf(char *vnf_addr, int vnf_p5_port); #endif diff --git a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h index da84901602..9df9be4cbd 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h @@ -1019,6 +1019,7 @@ typedef struct typedef struct { uint8_t tdd_period;//DL UL Transmission Periodicity. Value:0: ms0p5 1: ms0p625 2: ms1 3: ms1p25 4: ms2 5: ms2p5 6: ms5 7: ms10 8: ms3 9: ms4 + uint8_t tdd_period_in_slots; fapi_nr_max_tdd_periodicity_t* max_tdd_periodicity_list; } fapi_nr_tdd_table_t; diff --git a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_interface.h b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_interface.h index 32a31a99f6..0eb77a9d26 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_interface.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_interface.h @@ -120,6 +120,17 @@ typedef struct { } nfapi_tl_t; #define NFAPI_TAG_LENGTH_PACKED_LEN 4 +// Convenience methods to convert between SFN/SLOT formats +#define NFAPI_SFNSLOT2DEC(_sfn,_slot) ( _sfn*20 + _slot ) // total count of slots +#define NFAPI_SFNSLOTDEC2SFNSLOT(_sfnslot_dec) ((((_sfnslot_dec) / 20) << 4) | (((_sfnslot_dec) - (((_sfnslot_dec) / 20) * 10)) & 0x3F)) + +#define NFAPI_SFNSLOT2SFN(_sfnslot) ((_sfnslot) >> 6) +#define NFAPI_SFNSLOT2SLOT(_sfnslot) ((_sfnslot) & 0x3F) +#define NFAPI_SFNSLOTDEC2SFN(_sfnslot_dec) ((_sfnslot_dec) / 20) +#define NFAPI_SFNSLOTDEC2SLOT(_sfnslot_dec) ((_sfnslot_dec) % 20) + +#define NFAPI_MAX_SFNSLOTDEC 1024*20 // 20 is for numerology 1 + // Convenience methods to convert between SFN/SFN formats #define NFAPI_SFNSF2DEC(_sfnsf) ((((_sfnsf) >> 4) * 10) + ((_sfnsf) & 0xF)) #define NFAPI_SFNSFDEC2SFNSF(_sfnsf_dec) ((((_sfnsf_dec) / 10) << 4) | (((_sfnsf_dec) - (((_sfnsf_dec) / 10) * 10)) & 0xF)) @@ -176,7 +187,6 @@ typedef enum { NFAPI_DL_NODE_SYNC, NFAPI_TIMING_INFO, - NFAPI_RSSI_REQUEST = 0x0200, NFAPI_RSSI_RESPONSE, NFAPI_RSSI_INDICATION, @@ -587,6 +597,26 @@ typedef struct { #define NFAPI_PNF_PHY_RF_TAG 0x1003 // Generic strucutre for single tlv value. +typedef struct { + nfapi_tl_t tl; + int32_t value; +} nfapi_int32_tlv_t; + +typedef struct { + nfapi_tl_t tl; + uint32_t value; +} nfapi_uint32_tlv_t; + +typedef struct { + nfapi_tl_t tl; + int64_t value; +} nfapi_int64_tlv_t; + +typedef struct { + nfapi_tl_t tl; + uint64_t value; +} nfapi_uint64_tlv_t; + typedef struct { nfapi_tl_t tl; uint16_t value; @@ -1106,6 +1136,7 @@ typedef struct { typedef struct { nfapi_p4_p5_message_header_t header; + uint8_t num_tlvs; nfapi_pnf_phy_rf_config_t pnf_phy_rf_config; nfapi_vendor_extension_tlv_t vendor_extension; } nfapi_pnf_config_request_t; @@ -2466,7 +2497,7 @@ typedef struct { typedef struct { nfapi_p7_message_header_t header; uint32_t t1; - int32_t delta_sfn_sf; + int32_t delta_sfn_sf; nfapi_vendor_extension_tlv_t vendor_extension; } nfapi_dl_node_sync_t; @@ -2481,22 +2512,50 @@ typedef struct { typedef struct { nfapi_p7_message_header_t header; uint32_t last_sfn_sf; + uint32_t time_since_last_timing_info; uint32_t dl_config_jitter; uint32_t tx_request_jitter; uint32_t ul_config_jitter; uint32_t hi_dci0_jitter; + int32_t dl_config_latest_delay; int32_t tx_request_latest_delay; int32_t ul_config_latest_delay; int32_t hi_dci0_latest_delay; + int32_t dl_config_earliest_arrival; int32_t tx_request_earliest_arrival; int32_t ul_config_earliest_arrival; int32_t hi_dci0_earliest_arrival; + nfapi_vendor_extension_tlv_t vendor_extension; } nfapi_timing_info_t; +typedef struct { + nfapi_p7_message_header_t header; + + uint32_t last_sfn; + uint32_t last_slot; + uint32_t time_since_last_timing_info; + + uint32_t dl_tti_jitter; + uint32_t tx_data_request_jitter; + uint32_t ul_tti_jitter; + uint32_t ul_dci_jitter; + + int32_t dl_tti_latest_delay; + int32_t tx_data_request_latest_delay; + int32_t ul_tti_latest_delay; + int32_t ul_dci_latest_delay; + + int32_t dl_tti_earliest_arrival; + int32_t tx_data_request_earliest_arrival; + int32_t ul_tti_earliest_arrival; + int32_t ul_dci_earliest_arrival; + nfapi_vendor_extension_tlv_t vendor_extension; +} nfapi_nr_timing_info_t; + typedef struct { nfapi_tl_t tl; uint32_t handle; @@ -3653,6 +3712,50 @@ typedef struct { nfapi_vendor_extension_tlv_t vendor_extension; } nfapi_nmm_stop_response_t; +typedef struct +{ + // TODO: see if this needs to be uncommented + + // These TLVs are used to setup the transport connection between VNF and PNF + nfapi_ipv4_address_t p7_vnf_address_ipv4; + nfapi_ipv6_address_t p7_vnf_address_ipv6; + nfapi_uint16_tlv_t p7_vnf_port; + + nfapi_ipv4_address_t p7_pnf_address_ipv4; + nfapi_ipv6_address_t p7_pnf_address_ipv6; + nfapi_uint16_tlv_t p7_pnf_port; + + nfapi_uint8_tlv_t timing_window; //Value: 0 → 30,000 microseconds + nfapi_uint8_tlv_t timing_info_mode; + nfapi_uint8_tlv_t timing_info_period; + + nfapi_uint32_tlv_t dl_tti_timing_offset; + nfapi_uint32_tlv_t ul_tti_timing_offset; + nfapi_uint32_tlv_t ul_dci_timing_offset; + nfapi_uint32_tlv_t tx_data_timing_offset; + + // These TLVs are used to setup the transport connection between VNF and PNF + /* + nfapi_uint8_tlv_t dl_ue_per_sf; + nfapi_uint8_tlv_t ul_ue_per_sf; + + // These TLVs are used by PNF to report its RF capabilities to the VNF software + nfapi_rf_bands_t rf_bands; +*/ + // These TLVs are used by the VNF to configure the synchronization with the PNF. + + + // These TLVs are used by the VNF to configure the RF in the PNF + //nfapi_uint16_tlv_t max_transmit_power; + //nfapi_uint32_tlv_t nrarfcn; + + // nfapi_nmm_frequency_bands_t nmm_gsm_frequency_bands; + // nfapi_nmm_frequency_bands_t nmm_umts_frequency_bands; + // nfapi_nmm_frequency_bands_t nmm_lte_frequency_bands; + // nfapi_uint8_tlv_t nmm_uplink_rssi_supported; + +} nfapi_nr_nfapi_t; + // // Configuration options for the encode decode functions // @@ -3864,6 +3967,7 @@ int nfapi_p4_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUn * */ int nfapi_p5_message_pack(void *pMessageBuf, uint32_t messageBufLen, void *pPackedBuf, uint32_t packedBufLen, nfapi_p4_p5_codec_config_t* config); +int nfapi_nr_p5_message_pack(void *pMessageBuf, uint32_t messageBufLen, void *pPackedBuf, uint32_t packedBufLen, nfapi_p4_p5_codec_config_t* config); /*! \brief Decodes an NFAPI P5 message header * \param pMessageBuf A pointer to an encoded P5 message header @@ -3887,6 +3991,7 @@ int nfapi_p5_message_header_unpack(void *pMessageBuf, uint32_t messageBufLen, vo * * The function will decode a byte stream pointed to by pMessageBuf into a nfapi p5 message structure pointer to by pUnpackedBuf */ +int nfapi_nr_p5_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p4_p5_codec_config_t* config); int nfapi_p5_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p4_p5_codec_config_t* config); /*! \brief Encodes an NFAPI P7 message to a buffer @@ -3900,6 +4005,7 @@ int nfapi_p5_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUn * */ int nfapi_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen, nfapi_p7_codec_config_t* config); +int nfapi_nr_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen, nfapi_p7_codec_config_t* config); /*! \brief Decodes an NFAPI P7 message header * \param pMessageBuf A pointer to an encoded P7 message header @@ -3925,6 +4031,7 @@ int nfapi_p7_message_header_unpack(void *pMessageBuf, uint32_t messageBufLen, vo * The function will decode a byte stream pointed to by pMessageBuf into a nfapi p7 message structure pointer to by pUnpackedBuf */ int nfapi_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p7_codec_config_t* config); +int nfapi_nr_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p7_codec_config_t* config); /*! \brief Calculates the checksum of a message * diff --git a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h index 650bda4f78..fbe7a0e170 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h @@ -10,7 +10,7 @@ #define _NFAPI_NR_INTERFACE_H_ #include "nfapi_interface.h" -#include +#include "nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h" #define NFAPI_NR_MAX_NB_CCE_AGGREGATION_LEVELS 5 #define NFAPI_NR_MAX_NB_TCI_STATES_PDCCH 64 @@ -22,62 +22,32 @@ // nFAPI enums - //These TLVs are used exclusively by nFAPI -typedef struct -{ - // These TLVs are used to setup the transport connection between VNF and PNF - // nfapi_ipv4_address_t p7_vnf_address_ipv4; - // nfapi_ipv6_address_t p7_vnf_address_ipv6; - // nfapi_uint16_tlv_t p7_vnf_port; - - // nfapi_ipv4_address_t p7_pnf_address_ipv4; - // nfapi_ipv6_address_t p7_pnf_address_ipv6; - // nfapi_uint16_tlv_t p7_pnf_port; - - // // These TLVs are used to setup the transport connection between VNF and PNF - // nfapi_uint8_tlv_t dl_ue_per_sf; - // nfapi_uint8_tlv_t ul_ue_per_sf; - - // These TLVs are used by PNF to report its RF capabilities to the VNF software - nfapi_rf_bands_t rf_bands; - - // These TLVs are used by the VNF to configure the synchronization with the PNF. - // nfapi_uint8_tlv_t timing_window; - // nfapi_uint8_tlv_t timing_info_mode; - // nfapi_uint8_tlv_t timing_info_period; - - // These TLVs are used by the VNF to configure the RF in the PNF - // nfapi_uint16_tlv_t max_transmit_power; - nfapi_uint32_tlv_t nrarfcn; - - // nfapi_nmm_frequency_bands_t nmm_gsm_frequency_bands; - // nfapi_nmm_frequency_bands_t nmm_umts_frequency_bands; - // nfapi_nmm_frequency_bands_t nmm_lte_frequency_bands; - // nfapi_uint8_tlv_t nmm_uplink_rssi_supported; - -} nfapi_nr_nfapi_t; - -#define NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV4_TAG 0x5100 -#define NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV6_TAG 0x5101 -#define NFAPI_NR_NFAPI_P7_VNF_PORT_TAG 0x5102 -#define NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV4_TAG 0x5103 -#define NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV6_TAG 0x5104 -#define NFAPI_NR_NFAPI_P7_PNF_PORT_TAG 0x5105 +#define NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV4_TAG 0x0100 +#define NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV6_TAG 0x0101 +#define NFAPI_NR_NFAPI_P7_VNF_PORT_TAG 0x0102 +#define NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV4_TAG 0x0103 +#define NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV6_TAG 0x0104 +#define NFAPI_NR_NFAPI_P7_PNF_PORT_TAG 0x0105 +#define NFAPI_NR_NFAPI_DL_TTI_TIMING_OFFSET 0x0106 +#define NFAPI_NR_NFAPI_UL_TTI_TIMING_OFFSET 0x0107 +#define NFAPI_NR_NFAPI_UL_DCI_TIMING_OFFSET 0x0108 +#define NFAPI_NR_NFAPI_TX_DATA_TIMING_OFFSET 0x0109 +#define NFAPI_NR_NFAPI_TIMING_WINDOW_TAG 0x011E +#define NFAPI_NR_NFAPI_TIMING_INFO_MODE_TAG 0x011F +#define NFAPI_NR_NFAPI_TIMING_INFO_PERIOD_TAG 0x0120 +/* #define NFAPI_NR_NFAPI_DOWNLINK_UES_PER_SUBFRAME_TAG 0x510A #define NFAPI_NR_NFAPI_UPLINK_UES_PER_SUBFRAME_TAG 0x510B #define NFAPI_NR_NFAPI_RF_BANDS_TAG 0x5114 -#define NFAPI_NR_NFAPI_TIMING_WINDOW_TAG 0x511E -#define NFAPI_NR_NFAPI_TIMING_INFO_MODE_TAG 0x511F -#define NFAPI_NR_NFAPI_TIMING_INFO_PERIOD_TAG 0x5120 #define NFAPI_NR_NFAPI_MAXIMUM_TRANSMIT_POWER_TAG 0x5128 #define NFAPI_NR_NFAPI_NRARFCN_TAG 0x5129 #define NFAPI_NR_NFAPI_NMM_GSM_FREQUENCY_BANDS_TAG 0x5130 #define NFAPI_NR_NFAPI_NMM_UMTS_FREQUENCY_BANDS_TAG 0x5131 #define NFAPI_NR_NFAPI_NMM_LTE_FREQUENCY_BANDS_TAG 0x5132 #define NFAPI_NR_NFAPI_NMM_UPLINK_RSSI_SUPPORTED_TAG 0x5133 - +*/ // P5 Message Structures typedef struct { @@ -323,7 +293,7 @@ typedef enum { typedef enum { NFAPI_NR_CCE_REG_MAPPING_INTERLEAVED=0, - NFAPI_NR_CCE_REG_MAPPING_NON_INTERLEAVED + NFAPI_NR_CCE_REG_MAPPING_NON_INTERLEAVED=1 } nfapi_nr_cce_reg_mapping_type_e; typedef enum { diff --git a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf new file mode 100644 index 0000000000..6ee4ec8404 Binary files /dev/null and b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf differ diff --git a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h index c254e1a028..bc5e7af45f 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h @@ -11,6 +11,7 @@ #include "stddef.h" #include "nfapi_interface.h" +#include "nfapi_nr_interface.h" #define NFAPI_NR_MAX_NB_CCE_AGGREGATION_LEVELS 5 #define NFAPI_NR_MAX_NB_TCI_STATES_PDCCH 64 @@ -24,25 +25,7 @@ #define NFAPI_MAX_NUM_CB 8 // Extension to the generic structures for single tlv values -typedef struct { - nfapi_tl_t tl; - int32_t value; -} nfapi_int32_tlv_t; -typedef struct { - nfapi_tl_t tl; - uint32_t value; -} nfapi_uint32_tlv_t; - -typedef struct { - nfapi_tl_t tl; - int64_t value; -} nfapi_int64_tlv_t; - -typedef struct { - nfapi_tl_t tl; - uint64_t value; -} nfapi_uint64_tlv_t; typedef enum { NFAPI_NR_DMRS_TYPE1=0, @@ -76,35 +59,42 @@ typedef enum { NFAPI_NR_PHY_MSG_TYPE_STOP_REQUEST= 0X05, NFAPI_NR_PHY_MSG_TYPE_STOP_INDICATION=0X06, NFAPI_NR_PHY_MSG_TYPE_ERROR_INDICATION=0X07, + NFAPI_NR_PHY_MSG_TYPE_START_RESPONSE=0X010D, + NFAPI_NR_PHY_MSG_TYPE_STOP_RESPONSE=0X010F, //RESERVED 0X08 ~ 0X7F NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST= 0X80, NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST= 0X81, NFAPI_NR_PHY_MSG_TYPE_SLOT_INDICATION=0X82, NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST= 0X83, - NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST=0X54, + NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST=0X84, // CHANGED TO 0X84 NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION=0X85, NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION= 0X86, NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION= 0X87, NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION= 0X88, - NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION= 0X89 + NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION= 0X89, //RESERVED 0X8a ~ 0xff + NFAPI_NR_PHY_MSG_TYPE_PNF_PARAM_REQUEST = 0x0100, + NFAPI_NR_PHY_MSG_TYPE_PNF_PARAM_RESPONSE = 0x0101, + NFAPI_NR_PHY_MSG_TYPE_PNF_CONFIG_REQUEST= 0x0102, + NFAPI_NR_PHY_MSG_TYPE_PNF_CONFIG_RESPONSE= 0x0103, + NFAPI_NR_PHY_MSG_TYPE_PNF_START_REQUEST= 0x0104, + NFAPI_NR_PHY_MSG_TYPE_PNF_START_RESPONSE= 0x0105, + NFAPI_NR_PHY_MSG_TYPE_PNF_STOP_REQUEST= 0x0106, + NFAPI_NR_PHY_MSG_TYPE_PNF_STOP_RESPONSE= 0x0107, + + NFAPI_NR_PHY_MSG_TYPE_UL_NODE_SYNC = 0x0180, + NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC, + NFAPI_NR_PHY_MSG_TYPE_TIMING_INFO } nfapi_nr_phy_msg_type_e; // SCF222_5G-FAPI_PHY_SPI_Specificayion.pdf Section 3.3 //3.3.1 PARAM + + //same with nfapi_param_request_t -typedef struct { - nfapi_p4_p5_message_header_t header; - nfapi_vendor_extension_tlv_t vendor_extension; -} nfapi_nr_param_request_t; -typedef enum { - NFAPI_NR_PARAM_MSG_OK = 0, - NFAPI_NR_PARAM_MSG_INVALID_STATE - -} nfapi_nr_param_errors_e; /*typedef struct { nfapi_nr_param_errors_e error_code; @@ -278,12 +268,6 @@ typedef struct //-------------------------------------------// //3.3.2 CONFIG - -typedef enum { - NFAPI_NR_CONFIG_MSG_OK = 0, - NFAPI_NR_CONFIG_MSG_INVALID_CONFIG //The configuration provided has missing mandatory TLVs, or TLVs that are invalid or unsupported in this state. -} nfapi_nr_config_errors_e; - /*typedef struct { nfapi_nr_config_errors_e error_code; uint8_t number_of_invalid_tlvs_that_can_only_be_configured_in_idle; @@ -465,9 +449,108 @@ typedef struct } nfapi_nr_measurement_config_t; +// ERROR enums +typedef enum { // Table 2-22 + NFAPI_NR_PARAM_MSG_OK = 0, + NFAPI_NR_PARAM_MSG_INVALID_STATE +} nfapi_nr_param_errors_e; + +typedef enum { // Table 2-25 + NFAPI_NR_CONFIG_MSG_OK = 0, + NFAPI_NR_CONFIG_MSG_INVALID_STATE, //The CONFIG.request was received when the PHY was not in the IDLE state or the CONFIGURED state. + NFAPI_NR_CONFIG_MSG_INVALID_CONFIG //The configuration provided has missing mandatory TLVs, or TLVs that are invalid or unsupported in this state. +} nfapi_nr_config_errors_e; + +typedef enum { // Table 2-27 + NFAPI_NR_START_MSG_OK = 0, + NFAPI_NR_START_MSG_INVALID_STATE +} nfapi_nr_start_errors_e; + +//PNF P5 NR +typedef struct { + nfapi_p4_p5_message_header_t header; + nfapi_vendor_extension_tlv_t vendor_extension; +} nfapi_nr_pnf_param_request_t; typedef struct { - uint8_t num_tlv; + nfapi_p4_p5_message_header_t header; + uint32_t error_code; + nfapi_pnf_param_general_t pnf_param_general; + nfapi_pnf_phy_t pnf_phy; + nfapi_vendor_extension_tlv_t vendor_extension; +} nfapi_nr_pnf_param_response_t; + +typedef struct { + nfapi_p4_p5_message_header_t header; + uint8_t num_tlvs; + nfapi_pnf_phy_rf_config_t pnf_phy_rf_config; + nfapi_vendor_extension_tlv_t vendor_extension; +} nfapi_nr_pnf_config_request_t; + +typedef struct { + nfapi_p4_p5_message_header_t header; + uint32_t error_code; + nfapi_vendor_extension_tlv_t vendor_extension; +} nfapi_nr_pnf_config_response_t; + +typedef struct { + nfapi_p4_p5_message_header_t header; + nfapi_vendor_extension_tlv_t vendor_extension; +} nfapi_nr_pnf_start_request_t; + +typedef struct { + nfapi_p4_p5_message_header_t header; + uint32_t error_code; + nfapi_vendor_extension_tlv_t vendor_extension; +} nfapi_nr_pnf_start_response_t; + +typedef struct { + nfapi_p4_p5_message_header_t header; + nfapi_vendor_extension_tlv_t vendor_extension; +} nfapi_nr_pnf_stop_request_t; + +typedef struct { + nfapi_p4_p5_message_header_t header; + uint32_t error_code; + nfapi_vendor_extension_tlv_t vendor_extension; +} nfapi_nr_pnf_stop_response_t; + + +/* PARAM.REQUEST */ +typedef struct { + nfapi_p4_p5_message_header_t header; + nfapi_vendor_extension_tlv_t vendor_extension; +} nfapi_nr_param_request_scf_t; + +/* PARAM.RESPONSE */ +typedef struct { + nfapi_p4_p5_message_header_t header; + uint8_t error_code; + + uint8_t num_tlv; + nfapi_vendor_extension_tlv_t vendor_extension; + + nfapi_nr_cell_param_t cell_param; + nfapi_nr_carrier_param_t carrier_param; + nfapi_nr_pdcch_param_t pdcch_param; + nfapi_nr_pucch_param_t pucch_param; + nfapi_nr_pdsch_param_t pdsch_param; + nfapi_nr_pusch_param_t pusch_param; + nfapi_nr_prach_param_t prach_param; + nfapi_nr_measurement_param_t measurement_param; + nfapi_nr_nfapi_t nfapi_config; +} nfapi_nr_param_response_scf_t; + +//------------------------------// +//3.3.2 CONFIG + +/* CONFIG.REQUEST */ +typedef struct { + nfapi_p4_p5_message_header_t header; + + uint8_t num_tlv; + nfapi_vendor_extension_tlv_t vendor_extension; + nfapi_nr_carrier_config_t carrier_config; nfapi_nr_cell_config_t cell_config; nfapi_nr_ssb_config_t ssb_config; @@ -475,20 +558,32 @@ typedef struct { nfapi_nr_ssb_table_t ssb_table; nfapi_nr_tdd_table_t tdd_table; nfapi_nr_measurement_config_t measurement_config; + nfapi_nr_nfapi_t nfapi_config; } nfapi_nr_config_request_scf_t; +/* CONFIG.RESPONSE */ +typedef struct { + nfapi_p4_p5_message_header_t header; + uint8_t error_code; + //uint8_t num_invalid_tlvs; + // TODO: add list of invalid/unsupported TLVs (see Table 3.18) + nfapi_vendor_extension_tlv_t vendor_extension; +} nfapi_nr_config_response_scf_t; + //------------------------------// //3.3.3 START typedef struct { nfapi_p4_p5_message_header_t header; nfapi_vendor_extension_tlv_t vendor_extension; -} nfapi_nr_start_request_t; +} nfapi_nr_start_request_scf_t; -typedef enum { - NFAPI_NR_START_MSG_INVALID_STATE -} nfapi_nr_start_errors_e; +typedef struct { + nfapi_p4_p5_message_header_t header; + nfapi_nr_start_errors_e error_code; + nfapi_vendor_extension_tlv_t vendor_extension; +} nfapi_nr_start_response_scf_t; //3.3.4 STOP @@ -497,6 +592,7 @@ typedef struct { nfapi_vendor_extension_tlv_t vendor_extension; } nfapi_nr_stop_request_t; + typedef struct { nfapi_p4_p5_message_header_t header; nfapi_vendor_extension_tlv_t vendor_extension; @@ -580,7 +676,7 @@ typedef struct { uint16_t sfn; //0->1023 uint16_t slot;//0->319 -} nfapi_nr_slot_indication_t; +} nfapi_nr_slot_indication_scf_t; // 3.4.2 @@ -619,8 +715,10 @@ typedef struct { uint16_t prgSize; /// Number of STD ant ports (parallel streams) feeding into the digBF Value: 0->255 uint8_t digBFInterfaces; + // Depends on numPRGs uint16_t PMIdx[275]; - uint16_t *beamIdx[275]; + // Depends on digBFInterfaces + uint16_t beamIdx[256]; } nfapi_nr_tx_precoding_and_beamforming_t; //table 3-37 @@ -630,30 +728,30 @@ typedef struct { typedef struct { // The RNTI used for identifying the UE when receiving the PDU Value: 1 -> 65535. - uint16_t RNTI[MAX_DCI_CORESET]; + uint16_t RNTI; // For a UE-specific search space it equals the higher-layer parameter PDCCH-DMRSScrambling-ID if configured, // otherwise it should be set to the phy cell ID. [TS38.211, sec 7.3.2.3] Value: 0->65535 - uint16_t ScramblingId[MAX_DCI_CORESET]; + uint16_t ScramblingId; // For a UE-specific search space where PDCCH-DMRSScrambling- ID is configured This param equals the CRNTI. // Otherwise, it should be set to 0. [TS38.211, sec 7.3.2.3] Value: 0 -> 65535 - uint16_t ScramblingRNTI[MAX_DCI_CORESET]; + uint16_t ScramblingRNTI; // CCE start Index used to send the DCI Value: 0->135 - uint8_t CceIndex[MAX_DCI_CORESET]; + uint8_t CceIndex; // Aggregation level used [TS38.211, sec 7.3.2.1] Value: 1,2,4,8,16 - uint8_t AggregationLevel[MAX_DCI_CORESET]; + uint8_t AggregationLevel; // Precoding and Beamforming structure See Table 3-43 - nfapi_nr_tx_precoding_and_beamforming_t precodingAndBeamforming[MAX_DCI_CORESET]; + nfapi_nr_tx_precoding_and_beamforming_t precodingAndBeamforming; // PDCCH power value used for PDCCH Format 1_0 with CRC scrambled by SI-RNTI, PI-RNTI or RA-RNTI. // This is ratio of SSB/PBCH EPRE to PDCCH and PDCCH DMRS EPRE [TS38.213, sec 4.1] // Value :0->17 Report title: 5G FAPI: PHY API Specification Issue date: 29 June 2019 Version: 222.10.17 68 Field Type Description representing -8 to 8 dB in 1dB steps - uint8_t beta_PDCCH_1_0[MAX_DCI_CORESET]; + uint8_t beta_PDCCH_1_0; // PDCCH power value used for all other PDCCH Formats. // This is ratio of SSB/PBCH block EPRE to PDCCH and PDCCH DMRS EPRE [TS38.214, sec 4.1] Values: 0: -3dB,1: 0dB,2: 3dB,3: 6dB - uint8_t powerControlOffsetSS[MAX_DCI_CORESET]; + uint8_t powerControlOffsetSS; // The total DCI length (in bits) including padding bits [TS38.212 sec 7.3.1] Range 0->DCI_PAYLOAD_BYTE_LEN*8 - uint16_t PayloadSizeBits[MAX_DCI_CORESET]; + uint16_t PayloadSizeBits; // DCI payload, where the actual size is defined by PayloadSizeBits. The bit order is as following bit0-bit7 are mapped to first byte of MSB - LSB - uint8_t Payload[MAX_DCI_CORESET][DCI_PAYLOAD_BYTE_LEN]; + uint8_t Payload[DCI_PAYLOAD_BYTE_LEN]; } nfapi_nr_dl_dci_pdu_t; @@ -698,7 +796,7 @@ typedef struct { ///Number of DCIs in this CORESET.Value: 0->MaxDciPerSlot uint16_t numDlDci; ///DL DCI PDU - nfapi_nr_dl_dci_pdu_t dci_pdu; + nfapi_nr_dl_dci_pdu_t dci_pdu[MAX_DCI_CORESET]; } nfapi_nr_dl_tti_pdcch_pdu_rel15_t; typedef struct { @@ -941,6 +1039,7 @@ typedef struct { } nfapi_nr_dl_tti_request_pdu_t; #define NFAPI_NR_MAX_DL_TTI_PDUS 32 + typedef struct { /// Number of PDUs that are included in this message. All PDUs in the message are numbered in order. Value 0 -> 255 uint8_t nPDUs; @@ -954,11 +1053,28 @@ typedef struct { uint8_t PduIdx[256][12]; } nfapi_nr_dl_tti_request_body_t; + +typedef struct { + nfapi_p7_message_header_t header; + uint32_t t1; + int32_t delta_sfn_slot; + nfapi_vendor_extension_tlv_t vendor_extension; +} nfapi_nr_dl_node_sync_t; + +typedef struct { + nfapi_p7_message_header_t header; + uint32_t t1; + uint32_t t2; + uint32_t t3; + nfapi_vendor_extension_tlv_t vendor_extension; +} nfapi_nr_ul_node_sync_t; + + typedef struct { nfapi_p7_message_header_t header; /// System Frame Number (0-1023) uint16_t SFN; - /// Slot number (0-319) + /// Slot number (0-19) uint16_t Slot; nfapi_nr_dl_tti_request_body_t dl_tti_request_body; nfapi_vendor_extension_tlv_t vendor_extension; @@ -973,7 +1089,7 @@ typedef struct nfapi_nr_dl_tti_ssb_pdu_t* ssb_pdu; } nfapi_nr_dl_pdu_configuration_t; */ - /* + /* typedef struct { uint16_t pdu_type;//0: PDCCH PDU 1: PDSCH PDU 2: CSI-RS PDU 3: SSB PDU, @@ -1272,6 +1388,7 @@ typedef struct } nfapi_nr_ul_tti_request_number_of_groups_t; typedef struct { + nfapi_p7_message_header_t header; uint16_t SFN; //0->1023 uint16_t Slot;//0->319 uint8_t n_pdus;//Number of PDUs that are included in this message. All PDUs in the message are numbered in order. Value 0 -> 255 @@ -1318,6 +1435,7 @@ typedef struct { } nfapi_nr_ul_dci_request_pdus_t; typedef struct { + nfapi_p7_message_header_t header; uint16_t SFN; uint16_t Slot; uint8_t numPdus; @@ -1363,6 +1481,7 @@ typedef struct #define NFAPI_NR_MAX_TX_REQUEST_PDUS 16 typedef struct { + nfapi_p7_message_header_t header; uint16_t SFN; uint16_t Slot; uint16_t Number_of_PDUs; diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi.c b/nfapi/open-nFAPI/nfapi/src/nfapi.c index 61c6875bc6..ba800c3634 100644 --- a/nfapi/open-nFAPI/nfapi/src/nfapi.c +++ b/nfapi/open-nFAPI/nfapi/src/nfapi.c @@ -712,7 +712,7 @@ int unpack_tlv_list(unpack_tlv_t unpack_fns[], uint16_t size, uint8_t **ppReadPa for(idx = 0; idx < size; ++idx) { - if(unpack_fns[idx].tag == generic_tl.tag) + if(unpack_fns[idx].tag == generic_tl.tag) // match the extracted tag value with all the tags in unpack_fn list { tagMatch = 1; nfapi_tl_t* tl = (nfapi_tl_t*)(unpack_fns[idx].tlv); diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi_p5.c b/nfapi/open-nFAPI/nfapi/src/nfapi_p5.c index a8ac0f0a65..8aea9f590c 100644 --- a/nfapi/open-nFAPI/nfapi/src/nfapi_p5.c +++ b/nfapi/open-nFAPI/nfapi/src/nfapi_p5.c @@ -33,10 +33,18 @@ #include #include +#include "nfapi_nr_interface.h" +#include "nfapi_nr_interface_scf.h" #include // Pack routines +//TODO: Add pacl/unpack fns for uint32 and uint64 +static uint8_t pack_nr_pnf_param_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t* end, nfapi_p4_p5_codec_config_t* config) +{ + nfapi_nr_pnf_param_request_t* request = (nfapi_nr_pnf_param_request_t*)msg; + return pack_vendor_extension_tlv(request->vendor_extension, ppWritePackedMsg, end, config); +} static uint8_t pack_pnf_param_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t* end, nfapi_p4_p5_codec_config_t* config) { @@ -233,6 +241,26 @@ static uint8_t pack_pnf_phy_rel13_nb_iot_value(void* tlv, uint8_t **ppWritePacke return (push16(value->number_of_phys, ppWritePackedMsg, end) && packarray(value->phy, sizeof(nfapi_pnf_phy_rel13_nb_iot_info_t), NFAPI_MAX_PNF_PHY, value->number_of_phys, ppWritePackedMsg, end, &pack_pnf_phy_rel13_nb_iot_info)); } +/* +static uint8_t pack_nr_pnf_param_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) +{ + nfapi_nr_pnf_param_response_t *pNfapiMsg = (nfapi_nr_pnf_param_response_t*)msg; + + return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && + pack_tlv(NFAPI_PNF_PARAM_GENERAL_TAG, &pNfapiMsg->pnf_param_general, ppWritePackedMsg, end, &pack_pnf_param_general_value) && + pack_tlv(NFAPI_PNF_PHY_TAG, &pNfapiMsg->pnf_phy, ppWritePackedMsg, end, &pack_pnf_phy_value) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} +*/ +static uint8_t pack_nr_pnf_param_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) +{ + nfapi_nr_pnf_param_response_t *pNfapiMsg = (nfapi_nr_pnf_param_response_t*)msg; + + return (push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && + pack_tlv(NFAPI_PNF_PARAM_GENERAL_TAG, &pNfapiMsg->pnf_param_general, ppWritePackedMsg, end, &pack_pnf_param_general_value) && + pack_tlv(NFAPI_PNF_PHY_TAG, &pNfapiMsg->pnf_phy, ppWritePackedMsg, end, &pack_pnf_phy_value) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} static uint8_t pack_pnf_param_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) @@ -251,6 +279,7 @@ static uint8_t pack_pnf_param_response(void *msg, uint8_t **ppWritePackedMsg, ui pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); } + static uint8_t pack_phy_rf_config_info(void* elem, uint8_t **ppWritePackedMsg, uint8_t *end) { nfapi_phy_rf_config_info_t* rf = (nfapi_phy_rf_config_info_t*)elem; @@ -270,11 +299,29 @@ static uint8_t pack_pnf_phy_rf_config_value(void *tlv, uint8_t **ppWritePackedMs } +static uint8_t pack_nr_pnf_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) +{ + nfapi_nr_pnf_config_request_t *pNfapiMsg = (nfapi_nr_pnf_config_request_t*)msg; + return (pack_tlv(NFAPI_PNF_PHY_RF_TAG, &pNfapiMsg->pnf_phy_rf_config, ppWritePackedMsg, end, &pack_pnf_phy_rf_config_value) && + //push8(pNfapiMsg->num_tlvs,ppWritePackedMsg,end) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end , config)); +} + static uint8_t pack_pnf_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) { nfapi_pnf_config_request_t *pNfapiMsg = (nfapi_pnf_config_request_t*)msg; - return ( pack_tlv(NFAPI_PNF_PHY_RF_TAG, &pNfapiMsg->pnf_phy_rf_config, ppWritePackedMsg, end, &pack_pnf_phy_rf_config_value) && - pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end , config)); + return (pack_tlv(NFAPI_PNF_PHY_RF_TAG, &pNfapiMsg->pnf_phy_rf_config, ppWritePackedMsg, end, &pack_pnf_phy_rf_config_value) && + push8(pNfapiMsg->num_tlvs,ppWritePackedMsg,end) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end , config)); +} + + +static uint8_t pack_nr_pnf_config_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t* end, nfapi_p4_p5_codec_config_t* config) +{ + nfapi_nr_pnf_config_response_t *pNfapiMsg = (nfapi_nr_pnf_config_response_t*)msg; + + return ( push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); } @@ -286,12 +333,28 @@ static uint8_t pack_pnf_config_response(void *msg, uint8_t **ppWritePackedMsg, u pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); } +static uint8_t pack_nr_pnf_start_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t* end, nfapi_p4_p5_codec_config_t* config) +{ + nfapi_nr_pnf_start_request_t *pNfapiMsg = (nfapi_nr_pnf_start_request_t*)msg; + return ( pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + static uint8_t pack_pnf_start_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t* end, nfapi_p4_p5_codec_config_t* config) { nfapi_pnf_start_request_t *pNfapiMsg = (nfapi_pnf_start_request_t*)msg; return ( pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); } + +static uint8_t pack_nr_pnf_start_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t* end, nfapi_p4_p5_codec_config_t* config) +{ + nfapi_nr_pnf_start_response_t *pNfapiMsg = (nfapi_nr_pnf_start_response_t*)msg; + + return( push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + + static uint8_t pack_pnf_start_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t* end, nfapi_p4_p5_codec_config_t* config) { nfapi_pnf_start_response_t *pNfapiMsg = (nfapi_pnf_start_response_t*)msg; @@ -300,12 +363,31 @@ static uint8_t pack_pnf_start_response(void *msg, uint8_t **ppWritePackedMsg, ui pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); } + +static uint8_t pack_nr_pnf_stop_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t* end, nfapi_p4_p5_codec_config_t* config) +{ + nfapi_nr_pnf_stop_request_t *pNfapiMsg = (nfapi_nr_pnf_stop_request_t*)msg; + return ( pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config) ); +} + + + static uint8_t pack_pnf_stop_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t* end, nfapi_p4_p5_codec_config_t* config) { nfapi_pnf_stop_request_t *pNfapiMsg = (nfapi_pnf_stop_request_t*)msg; return ( pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config) ); } + +static uint8_t pack_nr_pnf_stop_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t* end, nfapi_p4_p5_codec_config_t* config) +{ + nfapi_nr_pnf_stop_response_t *pNfapiMsg = (nfapi_nr_pnf_stop_response_t*)msg; + + return ( push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + + static uint8_t pack_pnf_stop_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t* end, nfapi_p4_p5_codec_config_t* config) { nfapi_pnf_stop_response_t *pNfapiMsg = (nfapi_pnf_stop_response_t*)msg; @@ -314,12 +396,31 @@ static uint8_t pack_pnf_stop_response(void *msg, uint8_t **ppWritePackedMsg, uin pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); } +static uint8_t pack_nr_param_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t* end, nfapi_p4_p5_codec_config_t* config) +{ + nfapi_nr_param_request_scf_t *pNfapiMsg = (nfapi_nr_param_request_scf_t*)msg; + return (pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + static uint8_t pack_param_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t* end, nfapi_p4_p5_codec_config_t* config) -{ +{ nfapi_param_request_t *pNfapiMsg = (nfapi_param_request_t*)msg; return (pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); } +static uint8_t pack_uint32_tlv_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_uint32_tlv_t* value = (nfapi_uint32_tlv_t*)tlv; + return push32(value->value, ppWritePackedMsg, end); +} + +static uint8_t unpack_uint32_tlv_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_uint32_tlv_t* value = (nfapi_uint32_tlv_t*)tlv; + return pull32(ppReadPackedMsg, &value->value, end); +} + + static uint8_t pack_uint16_tlv_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { nfapi_uint16_tlv_t* value = (nfapi_uint16_tlv_t*)tlv; @@ -331,6 +432,7 @@ static uint8_t unpack_uint16_tlv_value(void* tlv, uint8_t **ppReadPackedMsg, uin nfapi_uint16_tlv_t* value = (nfapi_uint16_tlv_t*)tlv; return pull16(ppReadPackedMsg, &value->value, end); } + static uint8_t pack_int16_tlv_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { nfapi_int16_tlv_t* value = (nfapi_int16_tlv_t*)tlv; @@ -414,18 +516,19 @@ static uint8_t pack_embms_mbsfn_config_value(void* tlv, uint8_t **ppWritePackedM pusharray8(value->fourframes_flag, 8,value->num_mbsfn_config,ppWritePackedMsg, end) && pusharrays32(value->mbsfn_subframeconfig, 8, value->num_mbsfn_config, ppWritePackedMsg, end)); } -//static uint8_t unpack_embms_mbsfn_config_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t* end) -//{ +// static uint8_t unpack_embms_mbsfn_config_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t* end) +// { // nfapi_embms_mbsfn_config_t* value = (nfapi_embms_mbsfn_config_t*)tlv; -// + // return ( pull16(ppReadPackedMsg, &value->num_mbsfn_config, end) && // pull16(ppReadPackedMsg, &value->radioframe_allocation_period, end) && // pull16(ppReadPackedMsg, &value->radioframe_allocation_offset, end) && // pull8(ppReadPackedMsg, &value->fourframes_flag, end) && // pullarrays32(ppReadPackedMsg, value->mbsfn_subframeconfig, 8, value->num_mbsfn_config, end)); -//} -static uint8_t pack_param_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) -{ +// } + +static uint8_t pack_param_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t* end, nfapi_p4_p5_codec_config_t* config) +{ nfapi_param_response_t *pNfapiMsg = (nfapi_param_response_t*)msg; return( push8(pNfapiMsg->error_code, ppWritePackedMsg, end) && @@ -536,6 +639,92 @@ static uint8_t pack_param_response(void *msg, uint8_t **ppWritePackedMsg, uint8_ } +static uint8_t pack_nr_param_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) +{ + printf("\nRUNNING pack_param_response\n"); + nfapi_nr_param_response_scf_t *pNfapiMsg = (nfapi_nr_param_response_scf_t*)msg; + + return (push8(pNfapiMsg->error_code, ppWritePackedMsg, end) && + push8(pNfapiMsg->num_tlv, ppWritePackedMsg, end) && + pack_tlv(NFAPI_NR_PARAM_TLV_RELEASE_CAPABILITY_TAG, &(pNfapiMsg->cell_param.release_capability), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PHY_STATE_TAG, &(pNfapiMsg->cell_param.phy_state), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_SKIP_BLANK_DL_CONFIG_TAG, &(pNfapiMsg->cell_param.skip_blank_dl_config), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_SKIP_BLANK_UL_CONFIG_TAG, &(pNfapiMsg->cell_param.skip_blank_ul_config), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_NUM_CONFIG_TLVS_TO_REPORT_TAG, &(pNfapiMsg->cell_param.num_config_tlvs_to_report ), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + + pack_tlv(NFAPI_NR_PARAM_TLV_CYCLIC_PREFIX_TAG, &(pNfapiMsg->carrier_param.cyclic_prefix), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_SUPPORTED_SUBCARRIER_SPACINGS_DL_TAG, &(pNfapiMsg->carrier_param.supported_subcarrier_spacings_dl), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_SUPPORTED_BANDWIDTH_DL_TAG, &(pNfapiMsg->carrier_param.supported_bandwidth_dl), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_SUPPORTED_SUBCARRIER_SPACINGS_UL_TAG, &(pNfapiMsg->carrier_param.supported_subcarrier_spacings_ul), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_SUPPORTED_BANDWIDTH_UL_TAG, &(pNfapiMsg->carrier_param.supported_bandwidth_ul), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + + pack_tlv(NFAPI_NR_PARAM_TLV_CCE_MAPPING_TYPE_TAG, &(pNfapiMsg->pdcch_param.cce_mapping_type), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_CORESET_OUTSIDE_FIRST_3_OFDM_SYMS_OF_SLOT_TAG, &(pNfapiMsg->pdcch_param.coreset_outside_first_3_of_ofdm_syms_of_slot), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PRECODER_GRANULARITY_CORESET_TAG, &(pNfapiMsg->pdcch_param.coreset_precoder_granularity_coreset), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PDCCH_MU_MIMO_TAG, &(pNfapiMsg->pdcch_param.pdcch_mu_mimo), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PDCCH_PRECODER_CYCLING_TAG, &(pNfapiMsg->pdcch_param.pdcch_precoder_cycling), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_MAX_PDCCHS_PER_SLOT_TAG, &(pNfapiMsg->pdcch_param.max_pdcch_per_slot), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + + pack_tlv(NFAPI_NR_PARAM_TLV_PUCCH_FORMATS_TAG, &(pNfapiMsg->pucch_param.pucch_formats), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_MAX_PUCCHS_PER_SLOT_TAG, &(pNfapiMsg->pucch_param.max_pucchs_per_slot), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + + pack_tlv(NFAPI_NR_PARAM_TLV_PDSCH_MAPPING_TYPE_TAG, &(pNfapiMsg->pdsch_param.pdsch_mapping_type), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PDSCH_ALLOCATION_TYPES_TAG, &(pNfapiMsg->pdsch_param.pdsch_allocation_types), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PDSCH_VRB_TO_PRB_MAPPING_TAG, &(pNfapiMsg->pdsch_param.pdsch_vrb_to_prb_mapping), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PDSCH_CBG_TAG, &(pNfapiMsg->pdsch_param.pdsch_cbg), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PDSCH_DMRS_CONFIG_TYPES_TAG, &(pNfapiMsg->pdsch_param.pdsch_dmrs_config_types), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PDSCH_DMRS_MAX_LENGTH_TAG, &(pNfapiMsg->pdsch_param.pdsch_dmrs_max_length), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PDSCH_DMRS_ADDITIONAL_POS_TAG, &(pNfapiMsg->pdsch_param.pdsch_dmrs_additional_pos), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_MAX_PDSCH_S_YBS_PER_SLOT_TAG, &(pNfapiMsg->pdsch_param.max_pdsch_tbs_per_slot), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_MAX_NUMBER_MIMO_LAYERS_PDSCH_TAG, &(pNfapiMsg->pdsch_param.max_number_mimo_layers_pdsch), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_MAX_MU_MIMO_USERS_DL_TAG, &(pNfapiMsg->pdsch_param.max_mu_mimo_users_dl), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PDSCH_DATA_IN_DMRS_SYMBOLS_TAG, &(pNfapiMsg->pdsch_param.pdsch_data_in_dmrs_symbols), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PREMPTION_SUPPORT_TAG, &(pNfapiMsg->pdsch_param.premption_support), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PDSCH_NON_SLOT_SUPPORT_TAG, &(pNfapiMsg->pdsch_param.pdsch_non_slot_support), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + + pack_tlv(NFAPI_NR_PARAM_TLV_UCI_MUX_ULSCH_IN_PUSCH_TAG, &(pNfapiMsg->pusch_param.uci_mux_ulsch_in_pusch), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_UCI_ONLY_PUSCH_TAG, &(pNfapiMsg->pusch_param.uci_only_pusch), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PUSCH_FREQUENCY_HOPPING_TAG, &(pNfapiMsg->pusch_param.pusch_frequency_hopping), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PUSCH_DMRS_CONFIG_TYPES_TAG, &(pNfapiMsg->pusch_param.pusch_dmrs_config_types), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PUSCH_DMRS_MAX_LEN_TAG, &(pNfapiMsg->pusch_param.pusch_dmrs_max_len), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PUSCH_DMRS_ADDITIONAL_POS_TAG, &(pNfapiMsg->pusch_param.pusch_dmrs_additional_pos), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PUSCH_CBG_TAG, &(pNfapiMsg->pusch_param.pusch_cbg), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PUSCH_MAPPING_TYPE_TAG, &(pNfapiMsg->pusch_param.pusch_mapping_type), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PUSCH_ALLOCATION_TYPES_TAG, &(pNfapiMsg->pusch_param.pusch_allocation_types), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PUSCH_VRB_TO_PRB_MAPPING_TAG, &(pNfapiMsg->pusch_param.pusch_vrb_to_prb_mapping), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PUSCH_MAX_PTRS_PORTS_TAG, &(pNfapiMsg->pusch_param.pusch_max_ptrs_ports), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_MAX_PDUSCHS_TBS_PER_SLOT_TAG, &(pNfapiMsg->pusch_param.max_pduschs_tbs_per_slot), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_MAX_NUMBER_MIMO_LAYERS_NON_CB_PUSCH_TAG, &(pNfapiMsg->pusch_param.max_number_mimo_layers_non_cb_pusch), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_SUPPORTED_MODULATION_ORDER_UL_TAG, &(pNfapiMsg->pusch_param.supported_modulation_order_ul), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_MAX_MU_MIMO_USERS_UL_TAG, &(pNfapiMsg->pusch_param.max_mu_mimo_users_ul), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_DFTS_OFDM_SUPPORT_TAG, &(pNfapiMsg->pusch_param.dfts_ofdm_support), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PUSCH_AGGREGATION_FACTOR_TAG, &(pNfapiMsg->pusch_param.pusch_aggregation_factor), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + + pack_tlv(NFAPI_NR_PARAM_TLV_PRACH_LONG_FORMATS_TAG, &(pNfapiMsg->prach_param.prach_long_formats), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PRACH_SHORT_FORMATS_TAG, &(pNfapiMsg->prach_param.prach_short_formats), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_PRACH_RESTRICTED_SETS_TAG, &(pNfapiMsg->prach_param.prach_restricted_sets), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_PARAM_TLV_MAX_PRACH_FD_OCCASIONS_IN_A_SLOT_TAG, &(pNfapiMsg->prach_param.max_prach_fd_occasions_in_a_slot), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + + pack_tlv(NFAPI_NR_PARAM_TLV_RSSI_MEASUREMENT_SUPPORT_TAG, &(pNfapiMsg->measurement_param.rssi_measurement_support), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + + // config: + + pack_tlv(NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV4_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv4), ppWritePackedMsg, end, &pack_ipv4_address_value) && + pack_tlv(NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV6_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv6), ppWritePackedMsg, end, &pack_ipv6_address_value) && + + pack_tlv(NFAPI_NR_NFAPI_P7_VNF_PORT_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_port), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + + pack_tlv(NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV4_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_address_ipv4), ppWritePackedMsg, end, &pack_ipv4_address_value) && + pack_tlv(NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV6_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_address_ipv6), ppWritePackedMsg, end, &pack_ipv6_address_value) && + + pack_tlv(NFAPI_NR_NFAPI_P7_PNF_PORT_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_port), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NR_NFAPI_TIMING_WINDOW_TAG, &(pNfapiMsg->nfapi_config.timing_window), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_NFAPI_TIMING_INFO_MODE_TAG, &(pNfapiMsg->nfapi_config.timing_info_mode), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_NFAPI_TIMING_INFO_PERIOD_TAG, &(pNfapiMsg->nfapi_config.timing_info_period), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); + +} + static uint8_t pack_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) { nfapi_config_request_t *pNfapiMsg = (nfapi_config_request_t*)msg; @@ -668,20 +857,108 @@ static uint8_t pack_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_ pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config) ); } + +static uint8_t pack_nr_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) +{ + printf("\n\nEntering pack_config_request\n"); + nfapi_nr_config_request_scf_t *pNfapiMsg = (nfapi_nr_config_request_scf_t*)msg; + + + return (push8(pNfapiMsg->num_tlv, ppWritePackedMsg, end) && + pack_tlv(NFAPI_NR_CONFIG_DL_BANDWIDTH_TAG, &(pNfapiMsg->carrier_config.dl_bandwidth), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_DL_FREQUENCY_TAG, &(pNfapiMsg->carrier_config.dl_frequency), ppWritePackedMsg, end, &pack_uint32_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_DL_GRID_SIZE_TAG, &(pNfapiMsg->carrier_config.dl_grid_size[1]), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_DL_K0_TAG, &(pNfapiMsg->carrier_config.dl_k0[1]), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_NUM_RX_ANT_TAG, &(pNfapiMsg->carrier_config.num_rx_ant), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_NUM_TX_ANT_TAG, &(pNfapiMsg->carrier_config.num_tx_ant), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_UL_GRID_SIZE_TAG, &(pNfapiMsg->carrier_config.ul_grid_size[1]), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_UL_K0_TAG, &(pNfapiMsg->carrier_config.ul_k0[1]), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_UPLINK_BANDWIDTH_TAG, &(pNfapiMsg->carrier_config.uplink_bandwidth), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_UPLINK_FREQUENCY_TAG, &(pNfapiMsg->carrier_config.uplink_frequency), ppWritePackedMsg, end, &pack_uint32_tlv_value) && + + pack_tlv(NFAPI_NR_CONFIG_FRAME_DUPLEX_TYPE_TAG, &(pNfapiMsg->cell_config.frame_duplex_type), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_PHY_CELL_ID_TAG, &(pNfapiMsg->cell_config.phy_cell_id), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + + pack_tlv(NFAPI_NR_CONFIG_NUM_PRACH_FD_OCCASIONS_TAG, &(pNfapiMsg->prach_config.num_prach_fd_occasions), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_PRACH_SEQUENCE_LENGTH_TAG, &(pNfapiMsg->prach_config.prach_sequence_length), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_RESTRICTED_SET_CONFIG_TAG, &(pNfapiMsg->prach_config.restricted_set_config), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_SSB_PER_RACH_TAG, &(pNfapiMsg->prach_config.ssb_per_rach), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_PRACH_SUB_C_SPACING_TAG, &(pNfapiMsg->prach_config.prach_sub_c_spacing), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_PRACH_ROOT_SEQUENCE_INDEX_TAG, &(pNfapiMsg->prach_config.num_prach_fd_occasions_list[0].prach_root_sequence_index), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_K1_TAG, &(pNfapiMsg->prach_config.num_prach_fd_occasions_list[0].k1), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_PRACH_ZERO_CORR_CONF_TAG, &(pNfapiMsg->prach_config.num_prach_fd_occasions_list[0].prach_zero_corr_conf), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_NUM_ROOT_SEQUENCES_TAG, &(pNfapiMsg->prach_config.num_prach_fd_occasions_list[0].num_root_sequences), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + + + pack_tlv(NFAPI_NR_CONFIG_SCS_COMMON_TAG, &(pNfapiMsg->ssb_config.scs_common), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_SS_PBCH_POWER_TAG, &(pNfapiMsg->ssb_config.ss_pbch_power), ppWritePackedMsg, end, &pack_uint32_tlv_value) && + + pack_tlv(NFAPI_NR_CONFIG_BETA_PSS_TAG, &(pNfapiMsg->ssb_table.beta_pss), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_MIB_TAG, &(pNfapiMsg->ssb_table.MIB), ppWritePackedMsg, end, &pack_uint32_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_SSB_MASK_TAG, &(pNfapiMsg->ssb_table.ssb_mask_list[0].ssb_mask), ppWritePackedMsg, end, &pack_uint32_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_SSB_MASK_TAG, &(pNfapiMsg->ssb_table.ssb_mask_list[1].ssb_mask), ppWritePackedMsg, end, &pack_uint32_tlv_value) && + + pack_tlv(NFAPI_NR_CONFIG_SSB_OFFSET_POINT_A_TAG, &(pNfapiMsg->ssb_table.ssb_offset_point_a), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_SSB_PERIOD_TAG, &(pNfapiMsg->ssb_table.ssb_period), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_SSB_SUBCARRIER_OFFSET_TAG, &(pNfapiMsg->ssb_table.ssb_subcarrier_offset), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + + pack_tlv(NFAPI_NR_CONFIG_TDD_PERIOD_TAG, &(pNfapiMsg->tdd_table.tdd_period), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_CONFIG_SLOT_CONFIG_TAG, &(pNfapiMsg->tdd_table.max_tdd_periodicity_list[0].max_num_of_symbol_per_slot_list[0].slot_config), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + + //pack_tlv(NFAPI_NR_NFAPI_DOWNLINK_UES_PER_SUBFRAME_TAG, &(pNfapiMsg->nfapi_config.dl_ue_per_sf), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + //pack_tlv(NFAPI_NR_NFAPI_MAXIMUM_TRANSMIT_POWER_TAG, &(pNfapiMsg->nfapi_config.max_transmit_power), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + //pack_tlv(NFAPI_NR_NFAPI_NRARFCN_TAG, &(pNfapiMsg->nfapi_config.nrarfcn), ppWritePackedMsg, end, &pack_uint32_tlv_value) && + pack_tlv(NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV4_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_address_ipv4), ppWritePackedMsg, end, &pack_ipv4_address_value) && + pack_tlv(NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV6_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_address_ipv6), ppWritePackedMsg, end, &pack_ipv6_address_value) && + pack_tlv(NFAPI_NR_NFAPI_P7_PNF_PORT_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_port), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + pack_tlv(NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV4_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv4), ppWritePackedMsg, end, &pack_ipv4_address_value) && + pack_tlv(NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV6_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv6), ppWritePackedMsg, end, &pack_ipv6_address_value) && + pack_tlv(NFAPI_NR_NFAPI_P7_VNF_PORT_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_port), ppWritePackedMsg, end, &pack_uint16_tlv_value) && + //pack_tlv(NFAPI_NR_NFAPI_RF_BANDS_TAG, &(pNfapiMsg->nfapi_config.rf_bands), ppWritePackedMsg, end, &pack_rf_bands_value) && + pack_tlv(NFAPI_NR_NFAPI_TIMING_INFO_MODE_TAG, &(pNfapiMsg->nfapi_config.timing_info_mode), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_NFAPI_TIMING_INFO_PERIOD_TAG, &(pNfapiMsg->nfapi_config.timing_info_period), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + pack_tlv(NFAPI_NR_NFAPI_TIMING_WINDOW_TAG, &(pNfapiMsg->nfapi_config.timing_window), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + //pack_tlv(NFAPI_NR_NFAPI_UPLINK_UES_PER_SUBFRAME_TAG, &(pNfapiMsg->nfapi_config.ul_ue_per_sf), ppWritePackedMsg, end, &pack_uint8_tlv_value) && + + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config) ); +} + +static uint8_t pack_nr_config_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) +{ + nfapi_nr_config_response_scf_t *pNfapiMsg = (nfapi_nr_config_response_scf_t*)msg; + + return ( push8(pNfapiMsg->error_code, ppWritePackedMsg, end) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config) ); +} + static uint8_t pack_config_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) { nfapi_config_response_t *pNfapiMsg = (nfapi_config_response_t*)msg; - return ( push32(pNfapiMsg->error_code, ppWritePackedMsg, end) && + return ( push8(pNfapiMsg->error_code, ppWritePackedMsg, end) && pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config) ); } +static uint8_t pack_nr_start_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) +{ + nfapi_nr_start_request_scf_t *pNfapiMsg = (nfapi_nr_start_request_scf_t*)msg; + return pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config); +} + static uint8_t pack_start_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) { nfapi_start_request_t *pNfapiMsg = (nfapi_start_request_t*)msg; return pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config); } +static uint8_t pack_nr_start_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) +{ + nfapi_nr_start_response_scf_t *pNfapiMsg = (nfapi_nr_start_response_scf_t*)msg; + + return ( push32(pNfapiMsg->error_code, ppWritePackedMsg, end ) && + pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config) ); +} + static uint8_t pack_start_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) { nfapi_start_response_t *pNfapiMsg = (nfapi_start_response_t*)msg; @@ -690,6 +967,7 @@ static uint8_t pack_start_response(void *msg, uint8_t **ppWritePackedMsg, uint8_ pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config) ); } + static uint8_t pack_stop_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) { nfapi_stop_request_t *pNfapiMsg = (nfapi_stop_request_t*)msg; @@ -733,6 +1011,101 @@ static uint8_t pack_measurement_response(void *msg, uint8_t **ppWritePackedMsg, pack_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); } +static uint8_t pack_nr_p5_message_body(nfapi_p4_p5_message_header_t *header, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) +{ + uint8_t result = 0; + // look for the specific message + switch (header->message_id) + { + case NFAPI_NR_PHY_MSG_TYPE_PNF_PARAM_REQUEST: + result = pack_nr_pnf_param_request(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_PNF_PARAM_RESPONSE: + result = pack_nr_pnf_param_response(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PNF_CONFIG_REQUEST: + result = pack_nr_pnf_config_request(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PNF_CONFIG_RESPONSE: + result = pack_nr_pnf_config_response(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PNF_START_REQUEST: + result = pack_nr_pnf_start_request(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PNF_START_RESPONSE: + result = pack_nr_pnf_start_response(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PNF_STOP_REQUEST: + result = pack_nr_pnf_stop_request(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_PNF_STOP_RESPONSE: + result = pack_nr_pnf_stop_response(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PARAM_REQUEST: + result = pack_nr_param_request(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PARAM_RESPONSE: + result = pack_nr_param_response(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_CONFIG_REQUEST: + result = pack_nr_config_request(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_CONFIG_RESPONSE: + result = pack_nr_config_response(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_START_REQUEST: + result = pack_nr_start_request(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_START_RESPONSE: + result = pack_nr_start_response(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_STOP_REQUEST: + result = pack_stop_request(header, ppWritePackedMsg, end, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_STOP_RESPONSE: + result = pack_stop_response(header, ppWritePackedMsg, end, config); + break; + default: + { + if(header->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && + header->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) + { + if(config && config->pack_p4_p5_vendor_extension) + { + result = (config->pack_p4_p5_vendor_extension)(header, ppWritePackedMsg, end, config); + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve ecoder provided\n", __FUNCTION__, header->message_id); + } + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown message ID %d\n", __FUNCTION__, header->message_id); + } + } + break; + } + + return result; +} + + static uint8_t pack_p5_message_body(nfapi_p4_p5_message_header_t *header, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config) { uint8_t result = 0; @@ -852,6 +1225,55 @@ static uint32_t get_packed_msg_len(uintptr_t msgHead, uintptr_t msgEnd) } // Main pack function - public +int nfapi_nr_p5_message_pack(void *pMessageBuf, uint32_t messageBufLen, void *pPackedBuf, uint32_t packedBufLen, nfapi_p4_p5_codec_config_t* config) +{ + nfapi_p4_p5_message_header_t *pMessageHeader = pMessageBuf; + uint8_t *pWritePackedMessage = pPackedBuf; + uint8_t *pPackMessageEnd = pPackedBuf + packedBufLen; + uint8_t *pPackedLengthField = &pWritePackedMessage[4]; + uint32_t packedMsgLen; + uint16_t packedMsgLen16; + + if (pMessageBuf == NULL || pPackedBuf == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P5 Pack supplied pointers are null\n"); + return -1; + } + + // pack the message + if(push16(pMessageHeader->phy_id, &pWritePackedMessage, pPackMessageEnd) && + push16(pMessageHeader->message_id, &pWritePackedMessage, pPackMessageEnd) && + push16(0, &pWritePackedMessage, pPackMessageEnd) && + push16(pMessageHeader->spare, &pWritePackedMessage, pPackMessageEnd) && + pack_nr_p5_message_body(pMessageHeader, &pWritePackedMessage, pPackMessageEnd, config)) + { + // check for a valid message length + packedMsgLen = get_packed_msg_len((uintptr_t)pPackedBuf, (uintptr_t)pWritePackedMessage); + if (packedMsgLen > 0xFFFF || packedMsgLen > packedBufLen) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Packed message length error %d, buffer supplied %d\n", packedMsgLen, packedBufLen); + return -1; + } + else + { + packedMsgLen16 = (uint16_t)packedMsgLen; + } + + // Update the message length in the header + if(!push16(packedMsgLen16, &pPackedLengthField, pPackMessageEnd)) + return -1; + + // return the packed length + return (packedMsgLen); + } + else + { + // Failed to pack the meassage + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P5 Failed to pack message\n"); + return -1; + } + +} int nfapi_p5_message_pack(void *pMessageBuf, uint32_t messageBufLen, void *pPackedBuf, uint32_t packedBufLen, nfapi_p4_p5_codec_config_t* config) { @@ -906,6 +1328,20 @@ int nfapi_p5_message_pack(void *pMessageBuf, uint32_t messageBufLen, void *pPack // Unpack routines + + +static uint8_t unpack_nr_pnf_param_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) +{ + nfapi_nr_pnf_param_request_t *pNfapiMsg = (nfapi_nr_pnf_param_request_t*)msg; + + unpack_tlv_t unpack_fns[] = + { + }; + + return unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension)); +} + + static uint8_t unpack_pnf_param_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) { nfapi_pnf_param_request_t *pNfapiMsg = (nfapi_pnf_param_request_t*)msg; @@ -1108,6 +1544,20 @@ static uint8_t unpack_pnf_phy_rel13_nb_iot_value(void* tlv, uint8_t **ppReadPack unpackarray(ppReadPackedMsg, value->phy, sizeof(nfapi_pnf_phy_rel13_nb_iot_info_t), NFAPI_MAX_PNF_PHY, value->number_of_phys, end, &unpack_pnf_phy_rel13_nb_info_info)); } +static uint8_t unpack_nr_pnf_param_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) +{ + nfapi_nr_pnf_param_response_t *pNfapiMsg = (nfapi_nr_pnf_param_response_t*)msg; + + unpack_tlv_t unpack_fns[] = + { + { NFAPI_PNF_PARAM_GENERAL_TAG, &pNfapiMsg->pnf_param_general, &unpack_pnf_param_general_value}, + { NFAPI_PNF_PHY_TAG, &pNfapiMsg->pnf_phy, &unpack_pnf_phy_value}, + }; + + return ( pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + static uint8_t unpack_pnf_param_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) @@ -1124,12 +1574,14 @@ static uint8_t unpack_pnf_param_response(uint8_t **ppReadPackedMsg, uint8_t *end { NFAPI_PNF_PHY_REL12_TAG, &pNfapiMsg->pnf_phy_rel12, &unpack_pnf_phy_rel12_value}, { NFAPI_PNF_PHY_REL13_TAG, &pNfapiMsg->pnf_phy_rel13, &unpack_pnf_phy_rel13_value}, { NFAPI_PNF_PHY_REL13_NB_IOT_TAG, &pNfapiMsg->pnf_phy_rel13_nb_iot, &unpack_pnf_phy_rel13_nb_iot_value}, + }; return ( pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); } + static uint8_t unpack_phy_rf_config_info(void* elem, uint8_t **ppReadPackedMsg, uint8_t *end) { nfapi_phy_rf_config_info_t* rf = (nfapi_phy_rf_config_info_t*)elem; @@ -1148,6 +1600,20 @@ static uint8_t unpack_pnf_phy_rf_config_value(void* tlv, uint8_t **ppReadPackedM unpackarray(ppReadPackedMsg, value->phy_rf_config, sizeof(nfapi_phy_rf_config_info_t), NFAPI_MAX_PHY_RF_INSTANCES, value->number_phy_rf_config_info, end, &unpack_phy_rf_config_info)); } +static uint8_t unpack_nr_pnf_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) +{ + nfapi_nr_pnf_config_request_t *pNfapiMsg = (nfapi_nr_pnf_config_request_t*)msg; + + unpack_tlv_t unpack_fns[] = + { + { NFAPI_PNF_PHY_RF_TAG, &pNfapiMsg->pnf_phy_rf_config, &unpack_pnf_phy_rf_config_value}, + }; + + return unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension); +} + + + static uint8_t unpack_pnf_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) { nfapi_pnf_config_request_t *pNfapiMsg = (nfapi_pnf_config_request_t*)msg; @@ -1160,6 +1626,20 @@ static uint8_t unpack_pnf_config_request(uint8_t **ppReadPackedMsg, uint8_t *end return unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension); } + +static uint8_t unpack_nr_pnf_config_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) +{ + nfapi_nr_pnf_config_response_t *pNfapiMsg = (nfapi_nr_pnf_config_response_t*)msg; + + unpack_tlv_t unpack_fns[] = + { + }; + + return ( pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension))); + +} + static uint8_t unpack_pnf_config_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) { nfapi_pnf_config_response_t *pNfapiMsg = (nfapi_pnf_config_response_t*)msg; @@ -1173,6 +1653,18 @@ static uint8_t unpack_pnf_config_response(uint8_t **ppReadPackedMsg, uint8_t *en } +static uint8_t unpack_nr_pnf_start_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) +{ + nfapi_nr_pnf_start_request_t *pNfapiMsg = (nfapi_nr_pnf_start_request_t*)msg; + + unpack_tlv_t unpack_fns[] = + { + }; + + return unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension)); +} + + static uint8_t unpack_pnf_start_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) { nfapi_pnf_start_request_t *pNfapiMsg = (nfapi_pnf_start_request_t*)msg; @@ -1184,6 +1676,7 @@ static uint8_t unpack_pnf_start_request(uint8_t **ppReadPackedMsg, uint8_t *end, return unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension)); } + static uint8_t unpack_pnf_start_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) { nfapi_pnf_start_response_t *pNfapiMsg = (nfapi_pnf_start_response_t*)msg; @@ -1196,6 +1689,19 @@ static uint8_t unpack_pnf_start_response(uint8_t **ppReadPackedMsg, uint8_t *end unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension))); } +static uint8_t unpack_nr_pnf_start_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) +{ + nfapi_nr_pnf_start_response_t *pNfapiMsg = (nfapi_nr_pnf_start_response_t*)msg; + + unpack_tlv_t unpack_fns[] = + { + }; + + return ( pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end ) && + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension))); +} + + static uint8_t unpack_pnf_stop_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) { nfapi_pnf_stop_request_t *pNfapiMsg = (nfapi_pnf_stop_request_t*)msg; @@ -1231,6 +1737,17 @@ static uint8_t unpack_param_request(uint8_t **ppReadPackedMsg, uint8_t *end, voi return unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension)); } +static uint8_t unpack_nr_param_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) +{ + nfapi_nr_param_request_scf_t *pNfapiMsg = (nfapi_nr_param_request_scf_t*)msg; + + unpack_tlv_t unpack_fns[] = + { + }; + + return unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension)); +} + static uint8_t unpack_param_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) { nfapi_param_response_t *pNfapiMsg = (nfapi_param_response_t*)msg; @@ -1329,6 +1846,100 @@ static uint8_t unpack_param_response(uint8_t **ppReadPackedMsg, uint8_t *end, vo } +static uint8_t unpack_nr_param_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) +{ + nfapi_nr_param_response_scf_t *pNfapiMsg = (nfapi_nr_param_response_scf_t*)msg; + + unpack_tlv_t unpack_fns[] = + { + { NFAPI_NR_PARAM_TLV_RELEASE_CAPABILITY_TAG, &(pNfapiMsg->cell_param.release_capability), &unpack_uint16_tlv_value}, + { NFAPI_NR_PARAM_TLV_PHY_STATE_TAG, &(pNfapiMsg->cell_param.phy_state),&unpack_uint16_tlv_value}, + { NFAPI_NR_PARAM_TLV_SKIP_BLANK_DL_CONFIG_TAG, &(pNfapiMsg->cell_param.skip_blank_dl_config), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_SKIP_BLANK_UL_CONFIG_TAG, &(pNfapiMsg->cell_param.skip_blank_ul_config), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_NUM_CONFIG_TLVS_TO_REPORT_TAG, &(pNfapiMsg->cell_param.num_config_tlvs_to_report ), &unpack_uint16_tlv_value}, + + { NFAPI_NR_PARAM_TLV_CYCLIC_PREFIX_TAG, &(pNfapiMsg->carrier_param.cyclic_prefix), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_SUPPORTED_SUBCARRIER_SPACINGS_DL_TAG, &(pNfapiMsg->carrier_param.supported_subcarrier_spacings_dl), &unpack_uint16_tlv_value}, + { NFAPI_NR_PARAM_TLV_SUPPORTED_BANDWIDTH_DL_TAG, &(pNfapiMsg->carrier_param.supported_bandwidth_dl), &unpack_uint16_tlv_value}, + { NFAPI_NR_PARAM_TLV_SUPPORTED_SUBCARRIER_SPACINGS_UL_TAG, &(pNfapiMsg->carrier_param.supported_subcarrier_spacings_ul), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_SUPPORTED_BANDWIDTH_UL_TAG, &(pNfapiMsg->carrier_param.supported_bandwidth_ul), &unpack_uint16_tlv_value}, + + + { NFAPI_NR_PARAM_TLV_CCE_MAPPING_TYPE_TAG, &(pNfapiMsg->pdcch_param.cce_mapping_type), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_CORESET_OUTSIDE_FIRST_3_OFDM_SYMS_OF_SLOT_TAG, &(pNfapiMsg->pdcch_param.coreset_outside_first_3_of_ofdm_syms_of_slot), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PRECODER_GRANULARITY_CORESET_TAG, &(pNfapiMsg->pdcch_param.coreset_precoder_granularity_coreset), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PDCCH_MU_MIMO_TAG, &(pNfapiMsg->pdcch_param.pdcch_mu_mimo), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PDCCH_PRECODER_CYCLING_TAG, &(pNfapiMsg->pdcch_param.pdcch_precoder_cycling), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_MAX_PDCCHS_PER_SLOT_TAG, &(pNfapiMsg->pdcch_param.max_pdcch_per_slot), &unpack_uint8_tlv_value}, + + { NFAPI_NR_PARAM_TLV_PUCCH_FORMATS_TAG, &(pNfapiMsg->pucch_param.pucch_formats), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_MAX_PUCCHS_PER_SLOT_TAG, &(pNfapiMsg->pucch_param.max_pucchs_per_slot), &unpack_uint8_tlv_value}, + + { NFAPI_NR_PARAM_TLV_PDSCH_MAPPING_TYPE_TAG, &(pNfapiMsg->pdsch_param.pdsch_mapping_type), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PDSCH_ALLOCATION_TYPES_TAG, &(pNfapiMsg->pdsch_param.pdsch_allocation_types), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PDSCH_VRB_TO_PRB_MAPPING_TAG, &(pNfapiMsg->pdsch_param.pdsch_vrb_to_prb_mapping), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PDSCH_CBG_TAG, &(pNfapiMsg->pdsch_param.pdsch_cbg), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PDSCH_DMRS_CONFIG_TYPES_TAG, &(pNfapiMsg->pdsch_param.pdsch_dmrs_config_types), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PDSCH_DMRS_MAX_LENGTH_TAG, &(pNfapiMsg->pdsch_param.pdsch_dmrs_max_length), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PDSCH_DMRS_ADDITIONAL_POS_TAG, &(pNfapiMsg->pdsch_param.pdsch_dmrs_additional_pos), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_MAX_PDSCH_S_YBS_PER_SLOT_TAG, &(pNfapiMsg->pdsch_param.max_pdsch_tbs_per_slot), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_MAX_NUMBER_MIMO_LAYERS_PDSCH_TAG, &(pNfapiMsg->pdsch_param.max_number_mimo_layers_pdsch), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_MAX_MU_MIMO_USERS_DL_TAG, &(pNfapiMsg->pdsch_param.max_mu_mimo_users_dl), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PDSCH_DATA_IN_DMRS_SYMBOLS_TAG, &(pNfapiMsg->pdsch_param.pdsch_data_in_dmrs_symbols), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PREMPTION_SUPPORT_TAG, &(pNfapiMsg->pdsch_param.premption_support), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PDSCH_NON_SLOT_SUPPORT_TAG, &(pNfapiMsg->pdsch_param.pdsch_non_slot_support), &unpack_uint8_tlv_value}, + + { NFAPI_NR_PARAM_TLV_UCI_MUX_ULSCH_IN_PUSCH_TAG, &(pNfapiMsg->pusch_param.uci_mux_ulsch_in_pusch), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_UCI_ONLY_PUSCH_TAG, &(pNfapiMsg->pusch_param.uci_only_pusch), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PUSCH_FREQUENCY_HOPPING_TAG, &(pNfapiMsg->pusch_param.pusch_frequency_hopping), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PUSCH_DMRS_CONFIG_TYPES_TAG, &(pNfapiMsg->pusch_param.pusch_dmrs_config_types), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PUSCH_DMRS_MAX_LEN_TAG, &(pNfapiMsg->pusch_param.pusch_dmrs_max_len), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PUSCH_DMRS_ADDITIONAL_POS_TAG, &(pNfapiMsg->pusch_param.pusch_dmrs_additional_pos), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PUSCH_CBG_TAG, &(pNfapiMsg->pusch_param.pusch_cbg), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PUSCH_MAPPING_TYPE_TAG, &(pNfapiMsg->pusch_param.pusch_mapping_type), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PUSCH_ALLOCATION_TYPES_TAG, &(pNfapiMsg->pusch_param.pusch_allocation_types), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PUSCH_VRB_TO_PRB_MAPPING_TAG, &(pNfapiMsg->pusch_param.pusch_vrb_to_prb_mapping), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PUSCH_MAX_PTRS_PORTS_TAG, &(pNfapiMsg->pusch_param.pusch_max_ptrs_ports), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_MAX_PDUSCHS_TBS_PER_SLOT_TAG, &(pNfapiMsg->pusch_param.max_pduschs_tbs_per_slot), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_MAX_NUMBER_MIMO_LAYERS_NON_CB_PUSCH_TAG, &(pNfapiMsg->pusch_param.max_number_mimo_layers_non_cb_pusch), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_SUPPORTED_MODULATION_ORDER_UL_TAG, &(pNfapiMsg->pusch_param.supported_modulation_order_ul), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_MAX_MU_MIMO_USERS_UL_TAG, &(pNfapiMsg->pusch_param.max_mu_mimo_users_ul), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_DFTS_OFDM_SUPPORT_TAG, &(pNfapiMsg->pusch_param.dfts_ofdm_support), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PUSCH_AGGREGATION_FACTOR_TAG, &(pNfapiMsg->pusch_param.pusch_aggregation_factor), &unpack_uint8_tlv_value}, + + { NFAPI_NR_PARAM_TLV_PRACH_LONG_FORMATS_TAG, &(pNfapiMsg->prach_param.prach_long_formats), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PRACH_SHORT_FORMATS_TAG, &(pNfapiMsg->prach_param.prach_short_formats), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_PRACH_RESTRICTED_SETS_TAG, &(pNfapiMsg->prach_param.prach_restricted_sets), &unpack_uint8_tlv_value}, + { NFAPI_NR_PARAM_TLV_MAX_PRACH_FD_OCCASIONS_IN_A_SLOT_TAG, &(pNfapiMsg->prach_param.max_prach_fd_occasions_in_a_slot), &unpack_uint8_tlv_value}, + + { NFAPI_NR_PARAM_TLV_RSSI_MEASUREMENT_SUPPORT_TAG, &(pNfapiMsg->measurement_param.rssi_measurement_support), &unpack_uint8_tlv_value}, + //config + { NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV4_TAG, &pNfapiMsg->nfapi_config.p7_vnf_address_ipv4, &unpack_ipv4_address_value}, + { NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV6_TAG, &pNfapiMsg->nfapi_config.p7_vnf_address_ipv6, &unpack_ipv6_address_value}, + { NFAPI_NR_NFAPI_P7_VNF_PORT_TAG, &pNfapiMsg->nfapi_config.p7_vnf_port, &unpack_uint16_tlv_value}, + { NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV4_TAG, &pNfapiMsg->nfapi_config.p7_pnf_address_ipv4, &unpack_ipv4_address_value}, + { NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV6_TAG, &pNfapiMsg->nfapi_config.p7_pnf_address_ipv6, &unpack_ipv6_address_value}, + { NFAPI_NR_NFAPI_P7_PNF_PORT_TAG, &pNfapiMsg->nfapi_config.p7_pnf_port, &unpack_uint16_tlv_value}, + { NFAPI_NR_NFAPI_TIMING_WINDOW_TAG, &pNfapiMsg->nfapi_config.timing_window, &unpack_uint8_tlv_value}, + { NFAPI_NR_NFAPI_TIMING_INFO_MODE_TAG, &pNfapiMsg->nfapi_config.timing_info_mode, &unpack_uint8_tlv_value}, + { NFAPI_NR_NFAPI_TIMING_INFO_PERIOD_TAG, &pNfapiMsg->nfapi_config.timing_info_period, &unpack_uint8_tlv_value}, + }; + // print ppReadPackedMsg + uint8_t *ptr = *ppReadPackedMsg; + printf("\n Read message unpack_param_response: "); + while(ptr < end){ + printf(" %d ", *ptr); + ptr++; + } + printf("\n"); + + + return ( pull8(ppReadPackedMsg, &pNfapiMsg->error_code, end) && + pull8(ppReadPackedMsg, &pNfapiMsg->num_tlv, end) && + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); + +} + static uint8_t unpack_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) { nfapi_config_request_t *pNfapiMsg = (nfapi_config_request_t*)msg; @@ -1454,6 +2065,66 @@ static uint8_t unpack_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, vo return ( pull8(ppReadPackedMsg, &pNfapiMsg->num_tlv, end) && unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} +static uint8_t unpack_nr_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) +{ + nfapi_nr_config_request_scf_t *pNfapiMsg = (nfapi_nr_config_request_scf_t*)msg; + + pNfapiMsg->tdd_table.max_tdd_periodicity_list = (nfapi_nr_max_tdd_periodicity_t*) malloc(20*sizeof(nfapi_nr_max_tdd_periodicity_t)); + for(int i=0;i<40;i++) + pNfapiMsg->tdd_table.max_tdd_periodicity_list[i].max_num_of_symbol_per_slot_list = (nfapi_nr_max_num_of_symbol_per_slot_t*) malloc(14*sizeof(nfapi_nr_max_num_of_symbol_per_slot_t)); + + pNfapiMsg->prach_config.num_prach_fd_occasions_list=(nfapi_nr_num_prach_fd_occasions_t *) malloc(sizeof(nfapi_nr_num_prach_fd_occasions_t)); + + unpack_tlv_t unpack_fns[] = + { + { NFAPI_NR_CONFIG_DL_BANDWIDTH_TAG, &(pNfapiMsg->carrier_config.dl_bandwidth), &unpack_uint16_tlv_value}, + { NFAPI_NR_CONFIG_DL_FREQUENCY_TAG, &(pNfapiMsg->carrier_config.dl_frequency), &unpack_uint32_tlv_value}, + { NFAPI_NR_CONFIG_DL_GRID_SIZE_TAG, &(pNfapiMsg->carrier_config.dl_grid_size[1]), &unpack_uint16_tlv_value}, + { NFAPI_NR_CONFIG_DL_K0_TAG, &(pNfapiMsg->carrier_config.dl_k0[1]), &unpack_uint16_tlv_value}, + { NFAPI_NR_CONFIG_NUM_RX_ANT_TAG, &(pNfapiMsg->carrier_config.num_rx_ant), &unpack_uint16_tlv_value}, + { NFAPI_NR_CONFIG_NUM_TX_ANT_TAG, &(pNfapiMsg->carrier_config.num_tx_ant), &unpack_uint16_tlv_value}, + { NFAPI_NR_CONFIG_UL_GRID_SIZE_TAG, &(pNfapiMsg->carrier_config.ul_grid_size[1]), &unpack_uint16_tlv_value}, + { NFAPI_NR_CONFIG_UL_K0_TAG, &(pNfapiMsg->carrier_config.ul_k0[1]), &unpack_uint16_tlv_value}, + { NFAPI_NR_CONFIG_UPLINK_BANDWIDTH_TAG, &(pNfapiMsg->carrier_config.uplink_bandwidth), &unpack_uint16_tlv_value}, + { NFAPI_NR_CONFIG_UPLINK_FREQUENCY_TAG, &(pNfapiMsg->carrier_config.uplink_frequency), &unpack_uint32_tlv_value}, + { NFAPI_NR_CONFIG_FRAME_DUPLEX_TYPE_TAG, &(pNfapiMsg->cell_config.frame_duplex_type), &unpack_uint8_tlv_value}, + { NFAPI_NR_CONFIG_PHY_CELL_ID_TAG, &(pNfapiMsg->cell_config.phy_cell_id), &unpack_uint8_tlv_value}, + { NFAPI_NR_CONFIG_NUM_PRACH_FD_OCCASIONS_TAG, &(pNfapiMsg->prach_config.num_prach_fd_occasions), &unpack_uint8_tlv_value}, + { NFAPI_NR_CONFIG_PRACH_SEQUENCE_LENGTH_TAG, &(pNfapiMsg->prach_config.prach_sequence_length), &unpack_uint8_tlv_value}, + { NFAPI_NR_CONFIG_RESTRICTED_SET_CONFIG_TAG, &(pNfapiMsg->prach_config.restricted_set_config), &unpack_uint8_tlv_value}, + { NFAPI_NR_CONFIG_SSB_PER_RACH_TAG, &(pNfapiMsg->prach_config.ssb_per_rach), &unpack_uint8_tlv_value}, + { NFAPI_NR_CONFIG_PRACH_SUB_C_SPACING_TAG, &(pNfapiMsg->prach_config.prach_sub_c_spacing), &unpack_uint8_tlv_value}, + { NFAPI_NR_CONFIG_PRACH_ROOT_SEQUENCE_INDEX_TAG, &(pNfapiMsg->prach_config.num_prach_fd_occasions_list[0].prach_root_sequence_index), &unpack_uint16_tlv_value}, + { NFAPI_NR_CONFIG_K1_TAG, &(pNfapiMsg->prach_config.num_prach_fd_occasions_list[0].k1), &unpack_uint16_tlv_value}, + { NFAPI_NR_CONFIG_PRACH_ZERO_CORR_CONF_TAG, &(pNfapiMsg->prach_config.num_prach_fd_occasions_list[0].prach_zero_corr_conf), &unpack_uint8_tlv_value}, + { NFAPI_NR_CONFIG_NUM_ROOT_SEQUENCES_TAG, &(pNfapiMsg->prach_config.num_prach_fd_occasions_list[0].num_root_sequences), &unpack_uint8_tlv_value}, + + { NFAPI_NR_CONFIG_SCS_COMMON_TAG, &(pNfapiMsg->ssb_config.scs_common), &unpack_uint8_tlv_value}, + { NFAPI_NR_CONFIG_SS_PBCH_POWER_TAG, &(pNfapiMsg->ssb_config.ss_pbch_power), &unpack_uint32_tlv_value}, + { NFAPI_NR_CONFIG_BETA_PSS_TAG, &(pNfapiMsg->ssb_table.beta_pss), &unpack_uint8_tlv_value}, + { NFAPI_NR_CONFIG_MIB_TAG, &(pNfapiMsg->ssb_table.MIB), &unpack_uint32_tlv_value}, + { NFAPI_NR_CONFIG_SSB_MASK_TAG, &(pNfapiMsg->ssb_table.ssb_mask_list[0].ssb_mask), &unpack_uint32_tlv_value}, + { NFAPI_NR_CONFIG_SSB_MASK_TAG, &(pNfapiMsg->ssb_table.ssb_mask_list[1].ssb_mask), &unpack_uint32_tlv_value}, + + { NFAPI_NR_CONFIG_SSB_OFFSET_POINT_A_TAG, &(pNfapiMsg->ssb_table.ssb_offset_point_a), &unpack_uint16_tlv_value}, + { NFAPI_NR_CONFIG_SSB_PERIOD_TAG, &(pNfapiMsg->ssb_table.ssb_period), &unpack_uint8_tlv_value}, + { NFAPI_NR_CONFIG_SSB_SUBCARRIER_OFFSET_TAG, &(pNfapiMsg->ssb_table.ssb_subcarrier_offset), &unpack_uint8_tlv_value}, + { NFAPI_NR_CONFIG_TDD_PERIOD_TAG, &(pNfapiMsg->tdd_table.tdd_period), &unpack_uint8_tlv_value}, + { NFAPI_NR_CONFIG_SLOT_CONFIG_TAG, &(pNfapiMsg->tdd_table.max_tdd_periodicity_list[0].max_num_of_symbol_per_slot_list[0].slot_config), &unpack_uint8_tlv_value}, + { NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV4_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_address_ipv4), &unpack_ipv4_address_value}, + { NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV6_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_address_ipv6), &unpack_ipv6_address_value}, + { NFAPI_NR_NFAPI_P7_PNF_PORT_TAG, &(pNfapiMsg->nfapi_config.p7_pnf_port), &unpack_uint16_tlv_value}, + { NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV4_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv4), &unpack_ipv4_address_value}, + { NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV6_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv6), &unpack_ipv6_address_value}, + { NFAPI_NR_NFAPI_P7_VNF_PORT_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_port), &unpack_uint16_tlv_value}, + { NFAPI_NR_NFAPI_TIMING_INFO_MODE_TAG, &(pNfapiMsg->nfapi_config.timing_info_mode), &unpack_uint8_tlv_value}, + { NFAPI_NR_NFAPI_TIMING_INFO_PERIOD_TAG, &(pNfapiMsg->nfapi_config.timing_info_period), &unpack_uint8_tlv_value}, + { NFAPI_NR_NFAPI_TIMING_WINDOW_TAG, &(pNfapiMsg->nfapi_config.timing_window), &unpack_uint8_tlv_value}, + }; + return ( pull8(ppReadPackedMsg, &pNfapiMsg->num_tlv, end) && + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); + } static uint8_t unpack_config_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) @@ -1468,9 +2139,32 @@ static uint8_t unpack_config_response(uint8_t **ppReadPackedMsg, uint8_t *end, v unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension))); } +static uint8_t unpack_nr_config_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) +{ + nfapi_nr_config_response_scf_t *pNfapiMsg = (nfapi_nr_config_response_scf_t*)msg; + + unpack_tlv_t unpack_fns[] = + { + }; + + return ( pull8(ppReadPackedMsg, &pNfapiMsg->error_code, end) && + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension))); +} + +static uint8_t unpack_nr_start_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) +{ + nfapi_nr_start_request_scf_t *pNfapiMsg = ( nfapi_nr_start_request_scf_t*)msg; + + unpack_tlv_t unpack_fns[] = + { + }; + + return unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension)); +} + static uint8_t unpack_start_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) { - nfapi_start_request_t *pNfapiMsg = (nfapi_start_request_t*)msg; + nfapi_start_request_t *pNfapiMsg = ( nfapi_start_request_t*)msg; unpack_tlv_t unpack_fns[] = { @@ -1492,6 +2186,19 @@ static uint8_t unpack_start_response(uint8_t **ppReadPackedMsg, uint8_t *end, vo } +static uint8_t unpack_nr_start_response(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) +{ + nfapi_nr_start_response_scf_t *pNfapiMsg = (nfapi_nr_start_response_scf_t*)msg; + + unpack_tlv_t unpack_fns[] = + { + }; + + return ( pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) && + unpack_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &(pNfapiMsg->vendor_extension))); + +} + static uint8_t unpack_stop_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t* config) { nfapi_stop_request_t *pNfapiMsg = (nfapi_stop_request_t*)msg; @@ -1557,6 +2264,100 @@ static uint8_t unpack_measurement_response(uint8_t **ppReadPackedMsg, uint8_t *e // unpack length check +static int check_nr_unpack_length(nfapi_nr_phy_msg_type_e msgId, uint32_t unpackedBufLen) +{ + int retLen = 0; + + switch (msgId) + { + case NFAPI_NR_PHY_MSG_TYPE_PNF_PARAM_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_pnf_param_request_t)) + retLen = sizeof(nfapi_pnf_param_request_t); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PNF_PARAM_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_nr_pnf_param_response_t)) + retLen = sizeof(nfapi_nr_pnf_param_response_t); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PNF_CONFIG_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_nr_pnf_config_request_t)) + retLen = sizeof(nfapi_nr_pnf_config_request_t); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PNF_CONFIG_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_nr_pnf_config_response_t)) + retLen = sizeof(nfapi_nr_pnf_config_response_t); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PNF_START_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_nr_pnf_start_request_t)) + retLen = sizeof(nfapi_nr_pnf_start_request_t); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PNF_START_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_nr_pnf_start_response_t)) + retLen = sizeof(nfapi_nr_pnf_start_response_t); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PNF_STOP_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_nr_pnf_stop_request_t)) + retLen = sizeof(nfapi_nr_pnf_stop_request_t); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PNF_STOP_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_nr_pnf_stop_response_t)) + retLen = sizeof(nfapi_nr_pnf_stop_response_t); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PARAM_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_nr_param_request_scf_t)) + retLen = sizeof(nfapi_nr_param_request_scf_t); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PARAM_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_nr_param_response_scf_t)) + retLen = sizeof(nfapi_nr_param_response_scf_t); + break; + + case NFAPI_NR_PHY_MSG_TYPE_CONFIG_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_nr_config_request_scf_t)) + retLen = sizeof(nfapi_nr_config_request_scf_t); + break; + + case NFAPI_NR_PHY_MSG_TYPE_CONFIG_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_nr_config_response_scf_t)) + retLen = sizeof(nfapi_nr_config_response_scf_t); + break; + + case NFAPI_NR_PHY_MSG_TYPE_START_REQUEST: + if (unpackedBufLen >= sizeof( nfapi_nr_start_request_scf_t)) + retLen = sizeof( nfapi_nr_start_request_scf_t); + break; + + case NFAPI_NR_PHY_MSG_TYPE_START_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_nr_start_response_scf_t)) + retLen = sizeof(nfapi_nr_start_response_scf_t); + break; + + case NFAPI_NR_PHY_MSG_TYPE_STOP_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_stop_request_t)) + retLen = sizeof(nfapi_stop_request_t); + break; + + case NFAPI_NR_PHY_MSG_TYPE_STOP_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_stop_response_t)) + retLen = sizeof(nfapi_stop_response_t); + break; + default: + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s Unknown message ID %d\n", __FUNCTION__, msgId); + break; + } + + return retLen; +} + + static int check_unpack_length(nfapi_message_id_e msgId, uint32_t unpackedBufLen) { int retLen = 0; @@ -1624,8 +2425,8 @@ static int check_unpack_length(nfapi_message_id_e msgId, uint32_t unpackedBufLen break; case NFAPI_START_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_start_request_t)) - retLen = sizeof(nfapi_start_request_t); + if (unpackedBufLen >= sizeof( nfapi_start_request_t)) + retLen = sizeof( nfapi_start_request_t); break; case NFAPI_START_RESPONSE: @@ -1690,6 +2491,152 @@ int nfapi_p5_message_header_unpack(void *pMessageBuf, uint32_t messageBufLen, vo } +int nfapi_nr_p5_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p4_p5_codec_config_t* config) +{ + nfapi_p4_p5_message_header_t *pMessageHeader = pUnpackedBuf; + uint8_t *pReadPackedMessage = pMessageBuf; + uint8_t *end = pMessageBuf + messageBufLen; + + if (pMessageBuf == NULL || pUnpackedBuf == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P5 unpack supplied pointers are null\n"); + return -1; + } + + if (messageBufLen < NFAPI_HEADER_LENGTH || unpackedBufLen < sizeof(nfapi_p4_p5_message_header_t)) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P5 unpack supplied message buffer is too small %d, %d\n", messageBufLen, unpackedBufLen); + return -1; + } + + uint8_t *ptr = pReadPackedMessage; + printf("\n Read message unpack: "); + while(ptr < end){ + printf(" %d ", *ptr); + ptr++; + } + printf("\n"); + + // clean the supplied buffer for - tag value blanking + (void)memset(pUnpackedBuf, 0, unpackedBufLen); + + // process the header + if( !(pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end ) && + pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) && + pull16(&pReadPackedMessage, &pMessageHeader->message_length, end) && + pull16(&pReadPackedMessage, &pMessageHeader->spare, end))) + { + // failed to read the header + return -1; + } + + int result = -1; + + + if(check_nr_unpack_length(pMessageHeader->message_id, unpackedBufLen) == 0) + { + // the unpack buffer is not big enough for the struct + return -1; + } + + // look for the specific message + switch (pMessageHeader->message_id) + { + case NFAPI_NR_PHY_MSG_TYPE_PNF_PARAM_REQUEST: + result = unpack_nr_pnf_param_request(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PNF_PARAM_RESPONSE: + result = unpack_nr_pnf_param_response(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PNF_CONFIG_REQUEST: + result = unpack_nr_pnf_config_request(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PNF_CONFIG_RESPONSE: + result = unpack_nr_pnf_config_response(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PNF_START_REQUEST: + result = unpack_nr_pnf_start_request(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PNF_START_RESPONSE: + result = unpack_nr_pnf_start_response(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PNF_STOP_REQUEST: + result = unpack_pnf_stop_request(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PNF_STOP_RESPONSE: + result = unpack_pnf_stop_response(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PARAM_REQUEST: + result = unpack_nr_param_request(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PARAM_RESPONSE: + result = unpack_nr_param_response(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_CONFIG_REQUEST: + result = unpack_nr_config_request(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_CONFIG_RESPONSE: + result = unpack_nr_config_response(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_START_REQUEST: + result = unpack_nr_start_request(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_START_RESPONSE: + result = unpack_nr_start_response(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_STOP_REQUEST: + result = unpack_stop_request(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_STOP_RESPONSE: + result = unpack_stop_response(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_MEASUREMENT_REQUEST: + result = unpack_measurement_request(&pReadPackedMessage, end, pMessageHeader, config); + break; + + case NFAPI_MEASUREMENT_RESPONSE: + result = unpack_measurement_response(&pReadPackedMessage, end, pMessageHeader, config); + break; + + default: + if(pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && + pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) + { + if(config && config->unpack_p4_p5_vendor_extension) + { + result = (config->unpack_p4_p5_vendor_extension)(pMessageHeader, &pReadPackedMessage, end, config); + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve decoder provided\n", __FUNCTION__, pMessageHeader->message_id); + } + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown P5 message ID %d\n", __FUNCTION__, pMessageHeader->message_id); + } + break; + } + + return result; +} + int nfapi_p5_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p4_p5_codec_config_t* config) { nfapi_p4_p5_message_header_t *pMessageHeader = pUnpackedBuf; @@ -1708,6 +2655,14 @@ int nfapi_p5_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUn return -1; } + uint8_t *ptr = pReadPackedMessage; + printf("\n Read message unpack: "); + while(ptr < end){ + printf(" %d ", *ptr); + ptr++; + } + printf("\n"); + // clean the supplied buffer for - tag value blanking (void)memset(pUnpackedBuf, 0, unpackedBufLen); diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c index be9205d035..837f33fe6f 100755 --- a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c +++ b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c @@ -36,6 +36,7 @@ #include #include #include +#include "nfapi_nr_interface_scf.h" extern int nfapi_unpack_p7_vendor_extension(nfapi_p7_message_header_t* header, uint8_t **ppReadPackedMsg, void* user_data); extern int nfapi_pack_p7_vendor_extension(nfapi_p7_message_header_t* header, uint8_t **ppWritePackedMsg, void* user_data); @@ -81,19 +82,19 @@ void* nfapi_p7_allocate(size_t size, nfapi_p7_codec_config_t* config) if(size == 0) return 0; - void* buffer_p = NULL; + void* buffer_p = NULL; if(config && config->allocate) { - buffer_p = (config->allocate)(size); - if(buffer_p != NULL){ - memset(buffer_p,0,size); - } - return buffer_p; + buffer_p = (config->allocate)(size); + if(buffer_p != NULL){ + memset(buffer_p,0,size); + } + return buffer_p; } else { - buffer_p = calloc(1, size); - return buffer_p; + buffer_p = calloc(1, size); + return buffer_p; } } @@ -226,6 +227,155 @@ static uint8_t pack_tpm_value(nfapi_dl_config_dci_dl_tpm_t* value, uint8_t **ppW } + +static uint8_t pack_dl_tti_csi_rs_pdu_rel15_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_dl_tti_csi_rs_pdu_rel15_t* value = (nfapi_nr_dl_tti_csi_rs_pdu_rel15_t*)tlv; + + return( + push16(value->bwp_size, ppWritePackedMsg, end) && + push16(value->bwp_start, ppWritePackedMsg, end) && + + push8(value->subcarrier_spacing, ppWritePackedMsg, end) && + push8(value->cyclic_prefix, ppWritePackedMsg, end) && + + push16(value->start_rb, ppWritePackedMsg, end) && + push16(value->nr_of_rbs, ppWritePackedMsg, end) && + + push8(value->csi_type, ppWritePackedMsg, end) && + push8(value->row, ppWritePackedMsg, end) && + + push16(value->freq_domain, ppWritePackedMsg, end) && + push8(value->symb_l0, ppWritePackedMsg, end) && + + push8(value->symb_l1, ppWritePackedMsg, end) && + push8(value->cdm_type, ppWritePackedMsg, end) && + + push8(value->freq_density, ppWritePackedMsg, end) && + push16(value->scramb_id, ppWritePackedMsg, end) && + + push8(value->power_control_offset, ppWritePackedMsg, end) && + push8(value->power_control_offset_ss, ppWritePackedMsg, end) + ); + +} + + +static uint8_t pack_dl_tti_pdcch_pdu_rel15_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_dl_tti_pdcch_pdu_rel15_t* value = (nfapi_nr_dl_tti_pdcch_pdu_rel15_t*)tlv; + + for(uint8_t i = 0; i < MAX_DCI_CORESET; ++i) + { + if(!push16(value->dci_pdu[i].RNTI, ppWritePackedMsg, end) && + push16(value->dci_pdu[i].ScramblingId, ppWritePackedMsg, end) && + + push16(value->dci_pdu[i].ScramblingRNTI, ppWritePackedMsg, end) && + push8(value->dci_pdu[i].CceIndex, ppWritePackedMsg, end) && + push8(value->dci_pdu[i].AggregationLevel, ppWritePackedMsg, end) && + push8(value->dci_pdu[i].beta_PDCCH_1_0, ppWritePackedMsg, end) && + + push8(value->dci_pdu[i].powerControlOffsetSS, ppWritePackedMsg, end) && + push16(value->dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end) && + pusharray8(value->dci_pdu[i].Payload, DCI_PAYLOAD_BYTE_LEN, value->dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end)); + + return 0; + } + + // TODO: resolve the packaging of array (currently sending a single element) + return( + push16(value->BWPSize, ppWritePackedMsg, end) && + push16(value->BWPStart, ppWritePackedMsg, end) && + push8(value->SubcarrierSpacing, ppWritePackedMsg, end) && + push8(value->CyclicPrefix, ppWritePackedMsg, end) && + + push8(value->StartSymbolIndex, ppWritePackedMsg, end) && + push8(value->DurationSymbols, ppWritePackedMsg, end) && + pusharray8(value->FreqDomainResource, 6, 6, ppWritePackedMsg, end) && + push8(value->CceRegMappingType, ppWritePackedMsg, end) && + + push8(value->RegBundleSize, ppWritePackedMsg, end) && + push8(value->InterleaverSize, ppWritePackedMsg, end) && + push8(value->CoreSetType, ppWritePackedMsg, end) && + push16(value->ShiftIndex, ppWritePackedMsg, end) && + + push8(value->precoderGranularity, ppWritePackedMsg, end) && + push16(value->numDlDci, ppWritePackedMsg, end)); + +} + + +static uint8_t pack_dl_tti_pdsch_pdu_rel15_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_dl_tti_pdsch_pdu_rel15_t* value = (nfapi_nr_dl_tti_pdsch_pdu_rel15_t*)tlv; + + // TODO: resolve the packaging of array (currently sending a single element) + return( + push16(value->pduBitmap, ppWritePackedMsg, end) && + push16(value->rnti, ppWritePackedMsg, end) && + push16(value->pduIndex, ppWritePackedMsg, end) && + push16(value->BWPSize, ppWritePackedMsg, end) && + + push16(value->BWPStart, ppWritePackedMsg, end) && + push8(value->SubcarrierSpacing, ppWritePackedMsg, end) && + push8(value->CyclicPrefix, ppWritePackedMsg, end) && + push8(value->NrOfCodewords, ppWritePackedMsg, end) && + + pusharray16(value->targetCodeRate, 2, 1, ppWritePackedMsg, end) && + pusharray8(value->qamModOrder, 2, 1, ppWritePackedMsg, end) && + pusharray8(value->mcsIndex, 2, 1, ppWritePackedMsg, end) && + pusharray8(value->mcsTable, 2, 1, ppWritePackedMsg, end) && + + pusharray8(value->rvIndex, 2, 1, ppWritePackedMsg, end) && + pusharray32(value->TBSize, 2, 1, ppWritePackedMsg, end) && + push16(value->dataScramblingId, ppWritePackedMsg, end) && + push8(value->nrOfLayers, ppWritePackedMsg, end) && + + push8(value->transmissionScheme, ppWritePackedMsg, end) && + push8(value->refPoint, ppWritePackedMsg, end) && + push16(value->dlDmrsSymbPos, ppWritePackedMsg, end) && + push8(value->dmrsConfigType, ppWritePackedMsg, end) && + + push16(value->dlDmrsScramblingId, ppWritePackedMsg, end) && + push8(value->SCID, ppWritePackedMsg, end) && + push8(value->numDmrsCdmGrpsNoData, ppWritePackedMsg, end) && + push16(value->dmrsPorts, ppWritePackedMsg, end) && + + push8(value->resourceAlloc, ppWritePackedMsg, end) && + push16(value->rbStart, ppWritePackedMsg, end) && + push16(value->rbSize, ppWritePackedMsg, end) && + + push8(value->VRBtoPRBMapping, ppWritePackedMsg, end) && + push8(value->StartSymbolIndex, ppWritePackedMsg, end) && + push8(value->NrOfSymbols, ppWritePackedMsg, end) && + push8(value->PTRSPortIndex, ppWritePackedMsg, end) && + + push8(value->PTRSTimeDensity, ppWritePackedMsg, end) && + push8(value->PTRSFreqDensity, ppWritePackedMsg, end) && + push8(value->PTRSReOffset, ppWritePackedMsg, end) + ); + +} + + +static uint8_t pack_dl_tti_ssb_pdu_rel15_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_dl_tti_ssb_pdu_rel15_t* value = (nfapi_nr_dl_tti_ssb_pdu_rel15_t*)tlv; + + return( + push16(value->PhysCellId, ppWritePackedMsg, end) && + push8(value->BetaPss, ppWritePackedMsg, end) && + push8(value->SsbBlockIndex, ppWritePackedMsg, end) && + push8(value->SsbSubcarrierOffset, ppWritePackedMsg, end) && + push16(value->ssbOffsetPointA, ppWritePackedMsg, end) && + push8(value->bchPayloadFlag, ppWritePackedMsg, end) && + push32(value->bchPayload, ppWritePackedMsg, end) + // TODO: pack precoding_and_beamforming too + ); + +} + + static uint8_t pack_dl_config_dci_dl_pdu_rel13_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { nfapi_dl_config_dci_dl_pdu_rel13_t* value = (nfapi_dl_config_dci_dl_pdu_rel13_t*)tlv; @@ -552,6 +702,55 @@ static uint8_t pack_dl_config_ndlsch_pdu_rel13_value(void* tlv, uint8_t **ppWrit push8(value->nrs_antenna_ports_assumed_by_the_ue, ppWritePackedMsg, end)); } + +static uint8_t pack_dl_tti_request_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_dl_tti_request_pdu_t* value = (nfapi_nr_dl_tti_request_pdu_t*)tlv; + + if(!(push16(value->PDUSize, ppWritePackedMsg, end) && + push16(value->PDUType, ppWritePackedMsg, end) )) + return 0; + + + // first match the pdu type, then call the respective function + switch(value->PDUType) + { + case NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE: + { + if(!(pack_dl_tti_csi_rs_pdu_rel15_value(&value->csi_rs_pdu.csi_rs_pdu_rel15,ppWritePackedMsg,end))) + return 0; + } + break; + + case NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE: + { + if(!(pack_dl_tti_pdcch_pdu_rel15_value(&value->pdcch_pdu.pdcch_pdu_rel15,ppWritePackedMsg,end))) + return 0; + } + break; + case NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE: + { + if(!(pack_dl_tti_pdsch_pdu_rel15_value(&value->pdsch_pdu.pdsch_pdu_rel15,ppWritePackedMsg,end))) + return 0; + } + break; + case NFAPI_NR_DL_TTI_SSB_PDU_TYPE: + { + if(!(pack_dl_tti_ssb_pdu_rel15_value(&value->ssb_pdu.ssb_pdu_rel15,ppWritePackedMsg,end))) + return 0; + } + break; + + default: + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid DL_TTI pdu type %d \n", value->PDUType ); + } + break; + } + + return 1; +} + static uint8_t pack_dl_config_request_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { nfapi_dl_config_request_body_t* value = (nfapi_dl_config_request_body_t*)tlv; @@ -697,6 +896,41 @@ static uint8_t pack_dl_config_request_body_value(void* tlv, uint8_t **ppWritePac return 1; } + +static uint8_t pack_dl_tti_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_dl_tti_request_t *pNfapiMsg = (nfapi_nr_dl_tti_request_t*)msg; + + if (!(push16(pNfapiMsg->SFN , ppWritePackedMsg, end) && + push16(pNfapiMsg->Slot , ppWritePackedMsg, end) && + push8(pNfapiMsg->dl_tti_request_body.nGroup , ppWritePackedMsg, end) && + push8(pNfapiMsg->dl_tti_request_body.nPDUs , ppWritePackedMsg, end) && + pusharray8(pNfapiMsg->dl_tti_request_body.nUe ,256,pNfapiMsg->dl_tti_request_body.nGroup, ppWritePackedMsg, end) + //pusharray8(pNfapiMsg->PduIdx[0] ,256,256, ppWritePackedMsg, end) + )) + return 0; + + int arr[12]; + for(int i=0;idl_tti_request_body.nGroup;i++) + { + for(int j=0;jdl_tti_request_body.nUe[i];j++) + { + arr[j] = pNfapiMsg->dl_tti_request_body.PduIdx[i][j]; + } + if(!(pusharrays32(arr,12,pNfapiMsg->dl_tti_request_body.nUe[i],ppWritePackedMsg, end))) + return 0; + } + + for(int i=0;idl_tti_request_body.nPDUs;i++) + { + if(!pack_dl_tti_request_body_value(&pNfapiMsg->dl_tti_request_body.dl_tti_pdu_list[i],ppWritePackedMsg,end)) + return 0; + } + +return 1; +} + + static uint8_t pack_dl_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) { nfapi_dl_config_request_t *pNfapiMsg = (nfapi_dl_config_request_t*)msg; @@ -718,6 +952,9 @@ static uint8_t pack_dl_config_request(void *msg, uint8_t **ppWritePackedMsg, uin } } + + + static uint8_t pack_ul_config_request_ulsch_rel8_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t * end) { nfapi_ul_config_ulsch_pdu_rel8_t* ulsch_pdu_rel8 = (nfapi_ul_config_ulsch_pdu_rel8_t*)tlv; @@ -772,6 +1009,196 @@ static uint8_t pack_ul_config_request_ulsch_rel13_value(void *tlv, uint8_t **ppW push8(ulsch_pdu_rel13->empty_symbols_due_to_re_tunning, ppWritePackedMsg, end)); } +//Pack fns for ul_tti PDUS + + +static uint8_t pack_ul_tti_request_prach_pdu(nfapi_nr_prach_pdu_t* prach_pdu, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + return( + push16(prach_pdu->phys_cell_id, ppWritePackedMsg, end) && + push8(prach_pdu->num_prach_ocas, ppWritePackedMsg, end) && + push8(prach_pdu->prach_format, ppWritePackedMsg, end) && + push8(prach_pdu->num_ra, ppWritePackedMsg, end) && + push8(prach_pdu->prach_start_symbol, ppWritePackedMsg, end) && + push16(prach_pdu->num_cs, ppWritePackedMsg, end) + // TODO: ignoring beamforming tlv for now + ); + +} + +static uint8_t pack_ul_tti_request_pucch_pdu(nfapi_nr_pucch_pdu_t* pucch_pdu, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + return( + push16(pucch_pdu->rnti, ppWritePackedMsg, end) && + push32(pucch_pdu->handle, ppWritePackedMsg, end) && + push16(pucch_pdu->bwp_size, ppWritePackedMsg, end) && + push16(pucch_pdu->bwp_start, ppWritePackedMsg, end) && + push8(pucch_pdu->subcarrier_spacing, ppWritePackedMsg, end) && + push8(pucch_pdu->cyclic_prefix, ppWritePackedMsg, end) && + push8(pucch_pdu->format_type, ppWritePackedMsg, end) && + push8(pucch_pdu->multi_slot_tx_indicator, ppWritePackedMsg, end) && + push16(pucch_pdu->prb_start, ppWritePackedMsg, end) && + push16(pucch_pdu->prb_size, ppWritePackedMsg, end) && + push8(pucch_pdu->start_symbol_index, ppWritePackedMsg, end) && + push8(pucch_pdu->nr_of_symbols, ppWritePackedMsg, end) && + push8(pucch_pdu->freq_hop_flag, ppWritePackedMsg, end) && + push16(pucch_pdu->second_hop_prb, ppWritePackedMsg, end) && + push8(pucch_pdu->group_hop_flag, ppWritePackedMsg, end) && + push8(pucch_pdu->sequence_hop_flag, ppWritePackedMsg, end) && + push16(pucch_pdu->hopping_id, ppWritePackedMsg, end) && + push16(pucch_pdu->initial_cyclic_shift, ppWritePackedMsg, end) && + push16(pucch_pdu->data_scrambling_id, ppWritePackedMsg, end) && + push8(pucch_pdu->time_domain_occ_idx, ppWritePackedMsg, end) && + push8(pucch_pdu->pre_dft_occ_idx, ppWritePackedMsg, end) && + push8(pucch_pdu->pre_dft_occ_len, ppWritePackedMsg, end) && + push8(pucch_pdu->add_dmrs_flag, ppWritePackedMsg, end) && + push16(pucch_pdu->dmrs_scrambling_id, ppWritePackedMsg, end) && + push8(pucch_pdu->dmrs_cyclic_shift, ppWritePackedMsg, end) && + push8(pucch_pdu->sr_flag, ppWritePackedMsg, end) && + push8(pucch_pdu->bit_len_harq, ppWritePackedMsg, end) && + push16(pucch_pdu->bit_len_csi_part1, ppWritePackedMsg, end) && + push16(pucch_pdu->bit_len_csi_part2, ppWritePackedMsg, end) + // TODO: ignoring beamforming tlv for now + ); + +} + + +static uint8_t pack_ul_tti_request_pusch_pdu(nfapi_nr_pusch_pdu_t* pusch_pdu, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + + if (!( + push16(pusch_pdu->pdu_bit_map, ppWritePackedMsg, end) && + push16(pusch_pdu->rnti, ppWritePackedMsg, end) && + push32(pusch_pdu->handle, ppWritePackedMsg, end) && + push16(pusch_pdu->bwp_size, ppWritePackedMsg, end) && + push16(pusch_pdu->bwp_start, ppWritePackedMsg, end) && + push8(pusch_pdu->subcarrier_spacing, ppWritePackedMsg, end) && + push8(pusch_pdu->cyclic_prefix, ppWritePackedMsg, end) && + push16(pusch_pdu->target_code_rate, ppWritePackedMsg, end) && + push8(pusch_pdu->qam_mod_order, ppWritePackedMsg, end) && + push8(pusch_pdu->mcs_index, ppWritePackedMsg, end) && + push8(pusch_pdu->mcs_table, ppWritePackedMsg, end) && + push8(pusch_pdu->transform_precoding, ppWritePackedMsg, end) && + push16(pusch_pdu->data_scrambling_id, ppWritePackedMsg, end) && + push8(pusch_pdu->nrOfLayers, ppWritePackedMsg, end) && + push16(pusch_pdu->ul_dmrs_symb_pos, ppWritePackedMsg, end) && + push8(pusch_pdu->dmrs_config_type, ppWritePackedMsg, end) && + push16(pusch_pdu->ul_dmrs_scrambling_id, ppWritePackedMsg, end) && + push8(pusch_pdu->scid, ppWritePackedMsg, end) && + push8(pusch_pdu->num_dmrs_cdm_grps_no_data, ppWritePackedMsg, end) && + push16(pusch_pdu->dmrs_ports, ppWritePackedMsg, end) && + push8(pusch_pdu->resource_alloc, ppWritePackedMsg, end) && + push8(pusch_pdu->resource_alloc,ppWritePackedMsg, end) && + push16(pusch_pdu->dmrs_ports, ppWritePackedMsg, end) && + push16(pusch_pdu->rb_start, ppWritePackedMsg, end) && + push16(pusch_pdu->rb_size, ppWritePackedMsg, end) && + push8(pusch_pdu->vrb_to_prb_mapping, ppWritePackedMsg, end) && + push8(pusch_pdu->frequency_hopping, ppWritePackedMsg, end) && + push16(pusch_pdu->tx_direct_current_location, ppWritePackedMsg, end) && + push8(pusch_pdu->uplink_frequency_shift_7p5khz, ppWritePackedMsg, end) && + push8(pusch_pdu->start_symbol_index, ppWritePackedMsg, end) && + push8(pusch_pdu->nr_of_symbols, ppWritePackedMsg, end) + // TODO: ignoring beamforming tlv for now + )) + return 0; + + + //Pack Optional Data only included if indicated in pduBitmap + switch(pusch_pdu->pdu_bit_map){ + case PUSCH_PDU_BITMAP_PUSCH_DATA: + { + // pack optional TLVs + return( + push8(pusch_pdu->pusch_data.rv_index, ppWritePackedMsg, end) && + push8(pusch_pdu->pusch_data.harq_process_id, ppWritePackedMsg, end) && + push32(pusch_pdu->pusch_data.tb_size, ppWritePackedMsg, end) && + push16(pusch_pdu->pusch_data.num_cb, ppWritePackedMsg, end) && + pusharray8(pusch_pdu->pusch_data.cb_present_and_position,1,1,ppWritePackedMsg, end) + ); + } + break; + + case PUSCH_PDU_BITMAP_PUSCH_UCI: + { + return( + push16(pusch_pdu->pusch_uci.harq_ack_bit_length, ppWritePackedMsg, end) && + push16(pusch_pdu->pusch_uci.csi_part1_bit_length, ppWritePackedMsg, end) && + push16(pusch_pdu->pusch_uci.csi_part2_bit_length, ppWritePackedMsg, end) && + push8(pusch_pdu->pusch_uci.alpha_scaling, ppWritePackedMsg, end) && + push8(pusch_pdu->pusch_uci.beta_offset_harq_ack, ppWritePackedMsg, end) && + push8(pusch_pdu->pusch_uci.beta_offset_csi1, ppWritePackedMsg, end) && + push8(pusch_pdu->pusch_uci.beta_offset_csi2, ppWritePackedMsg, end) + ); + } + break; + + case PUSCH_PDU_BITMAP_PUSCH_PTRS: + { + return( + push8(pusch_pdu->pusch_ptrs.num_ptrs_ports, ppWritePackedMsg, end) && + push8(pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_dmrs_port, ppWritePackedMsg, end) && + push16(pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_port_index, ppWritePackedMsg, end) && + push8(pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_re_offset, ppWritePackedMsg, end) && + push8(pusch_pdu->pusch_ptrs.ptrs_time_density, ppWritePackedMsg, end) && + push8(pusch_pdu->pusch_ptrs.ptrs_freq_density, ppWritePackedMsg, end) && + push8(pusch_pdu->pusch_ptrs.ul_ptrs_power, ppWritePackedMsg, end) + ); + } + break; + + case PUSCH_PDU_BITMAP_DFTS_OFDM: + { + return( + push8(pusch_pdu->dfts_ofdm.low_papr_group_number, ppWritePackedMsg, end) && + push16(pusch_pdu->dfts_ofdm.low_papr_sequence_number, ppWritePackedMsg, end) && + push8(pusch_pdu->dfts_ofdm.ul_ptrs_sample_density, ppWritePackedMsg, end) && + push8(pusch_pdu->dfts_ofdm.ul_ptrs_time_density_transform_precoding, ppWritePackedMsg, end) + ); + } + break; + + default: + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "Invalid pdu bitmap %d \n", pusch_pdu->pdu_bit_map ); + } + } + + return 1; +} + +static uint8_t pack_ul_tti_request_srs_pdu(nfapi_nr_srs_pdu_t* srs_pdu, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + return( + push16(srs_pdu->rnti, ppWritePackedMsg, end) && + push32(srs_pdu->handle, ppWritePackedMsg, end) && + push16(srs_pdu->bwp_size, ppWritePackedMsg, end) && + push16(srs_pdu->bwp_start, ppWritePackedMsg, end) && + push8(srs_pdu->subcarrier_spacing, ppWritePackedMsg, end) && + push8(srs_pdu->cyclic_prefix, ppWritePackedMsg, end) && + push8(srs_pdu->num_ant_ports, ppWritePackedMsg, end) && + push8(srs_pdu->num_symbols, ppWritePackedMsg, end) && + push8(srs_pdu->num_repetitions, ppWritePackedMsg, end) && + push8(srs_pdu->time_start_position, ppWritePackedMsg, end) && + push8(srs_pdu->config_index, ppWritePackedMsg, end) && + push16(srs_pdu->sequence_id, ppWritePackedMsg, end) && + push8(srs_pdu->bandwidth_index, ppWritePackedMsg, end) && + push8(srs_pdu->comb_size, ppWritePackedMsg, end) && + push8(srs_pdu->comb_offset, ppWritePackedMsg, end) && + push8(srs_pdu->cyclic_shift, ppWritePackedMsg, end) && + push8(srs_pdu->frequency_position, ppWritePackedMsg, end) && + push8(srs_pdu->frequency_shift, ppWritePackedMsg, end) && + push8(srs_pdu->frequency_hopping, ppWritePackedMsg, end) && + push8(srs_pdu->group_or_sequence_hopping, ppWritePackedMsg, end) && + push8(srs_pdu->resource_type, ppWritePackedMsg, end) && + push16(srs_pdu->t_srs, ppWritePackedMsg, end) && + push16(srs_pdu->t_offset, ppWritePackedMsg, end) + + // TODO: ignoring beamforming tlv for now + ); + +} + static uint8_t pack_ul_config_request_ulsch_pdu(nfapi_ul_config_ulsch_pdu* ulsch_pdu, uint8_t **ppWritePackedMsg, uint8_t *end) { return ( pack_tlv(NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL8_TAG, &ulsch_pdu->ulsch_pdu_rel8, ppWritePackedMsg, end, &pack_ul_config_request_ulsch_rel8_value) && @@ -1124,6 +1551,70 @@ static uint8_t pack_ul_config_request_nrach_pdu_rel13_value(void *tlv, uint8_t * } + + +static uint8_t pack_ul_tti_pdu_list_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_ul_tti_request_number_of_pdus_t* value = (nfapi_nr_ul_tti_request_number_of_pdus_t*)tlv; + + if(!(push16(value->pdu_size, ppWritePackedMsg, end) && + push16(value->pdu_type, ppWritePackedMsg, end) )) + return 0; + + + // first match the pdu type, then call the respective function + switch(value->pdu_type) + { + case NFAPI_NR_UL_CONFIG_PRACH_PDU_TYPE: + { + if(!pack_ul_tti_request_prach_pdu(&value->prach_pdu, ppWritePackedMsg, end)) + return 0; + } + break; + + case NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE: + { + if(!pack_ul_tti_request_pucch_pdu(&value->pucch_pdu, ppWritePackedMsg, end)) + return 0; + } + break; + case NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE: + { + if(!pack_ul_tti_request_pusch_pdu(&value->pusch_pdu, ppWritePackedMsg, end)) + return 0; + } + break; + case NFAPI_NR_UL_CONFIG_SRS_PDU_TYPE: + { + if(!pack_ul_tti_request_srs_pdu(&value->srs_pdu, ppWritePackedMsg, end)) + return 0; + } + break; + + default: + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid UL_TTI pdu type %d \n", value->pdu_type ); + } + break; + } + + return 1; +} + +static uint8_t pack_ul_tti_groups_list_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_ul_tti_request_number_of_groups_t* value = (nfapi_nr_ul_tti_request_number_of_groups_t*)tlv; + + if(!push8(value->n_ue, ppWritePackedMsg, end)) + return 0; + for(int i=0; in_ue;i++) + { + if(!push8(value->ue_list[i].pdu_idx, ppWritePackedMsg, end)) + return 0; + } + return 1; +} + static uint8_t pack_ul_config_request_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { nfapi_ul_config_request_body_t* value = (nfapi_ul_config_request_body_t*)tlv; @@ -1298,6 +1789,37 @@ static uint8_t pack_ul_config_request_body_value(void* tlv, uint8_t **ppWritePac return 1; } + +static uint8_t pack_ul_tti_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_ul_tti_request_t *pNfapiMsg = (nfapi_nr_ul_tti_request_t*)msg; + + if (!(push16(pNfapiMsg->SFN , ppWritePackedMsg, end) && + push16(pNfapiMsg->Slot , ppWritePackedMsg, end) && + push8(pNfapiMsg->n_pdus , ppWritePackedMsg, end) && + push8(pNfapiMsg->rach_present, ppWritePackedMsg, end) && + push8(pNfapiMsg->n_ulsch, ppWritePackedMsg, end) && + push8(pNfapiMsg->n_ulcch, ppWritePackedMsg, end) && + push8(pNfapiMsg->n_group, ppWritePackedMsg, end) )) + return 0; + + for(int i=0; in_pdus; i++) + { + if(!pack_ul_tti_pdu_list_value(&pNfapiMsg->pdus_list[i], ppWritePackedMsg, end)) + return 0; + } + + for(int i=0; in_group; i++) + { + if(!pack_ul_tti_groups_list_value(&pNfapiMsg->groups_list[i], ppWritePackedMsg, end)) + return 0; + + } + + return 1; +} + + static uint8_t pack_ul_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) { nfapi_ul_config_request_t *pNfapiMsg = (nfapi_ul_config_request_t*)msg; @@ -1517,6 +2039,69 @@ static uint8_t pack_hi_dci0_request_body_value(void *tlv, uint8_t **ppWritePacke return 1; } +static uint8_t pack_ul_dci_pdu_list_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_ul_dci_request_pdus_t* value = (nfapi_nr_ul_dci_request_pdus_t*)tlv; + + for(uint8_t i = 0; i < MAX_DCI_CORESET; ++i) + { + if(!push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].RNTI, ppWritePackedMsg, end) && + push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].ScramblingId, ppWritePackedMsg, end) && + + push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].ScramblingRNTI, ppWritePackedMsg, end) && + push8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].CceIndex, ppWritePackedMsg, end) && + push8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].AggregationLevel, ppWritePackedMsg, end) && + push8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].beta_PDCCH_1_0, ppWritePackedMsg, end) && + + push8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].powerControlOffsetSS, ppWritePackedMsg, end) && + push16(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end) && + + pusharray8(value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].Payload, DCI_PAYLOAD_BYTE_LEN, value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, ppWritePackedMsg, end)); + + return 0; + } + + return (push16(value->PDUType, ppWritePackedMsg, end) && + push16(value->PDUSize, ppWritePackedMsg, end) && + push16(value->pdcch_pdu.pdcch_pdu_rel15.BWPSize, ppWritePackedMsg, end) && + push16(value->pdcch_pdu.pdcch_pdu_rel15.BWPStart, ppWritePackedMsg, end) && + push8(value->pdcch_pdu.pdcch_pdu_rel15.SubcarrierSpacing, ppWritePackedMsg, end) && + push8(value->pdcch_pdu.pdcch_pdu_rel15.CyclicPrefix, ppWritePackedMsg, end) && + + push8(value->pdcch_pdu.pdcch_pdu_rel15.StartSymbolIndex, ppWritePackedMsg, end) && + push8(value->pdcch_pdu.pdcch_pdu_rel15.DurationSymbols, ppWritePackedMsg, end) && + pusharray8(value->pdcch_pdu.pdcch_pdu_rel15.FreqDomainResource, 6, 6, ppWritePackedMsg, end) && + push8(value->pdcch_pdu.pdcch_pdu_rel15.CceRegMappingType, ppWritePackedMsg, end) && + + push8(value->pdcch_pdu.pdcch_pdu_rel15.RegBundleSize, ppWritePackedMsg, end) && + push8(value->pdcch_pdu.pdcch_pdu_rel15.InterleaverSize, ppWritePackedMsg, end) && + push8(value->pdcch_pdu.pdcch_pdu_rel15.CoreSetType, ppWritePackedMsg, end) && + push16(value->pdcch_pdu.pdcch_pdu_rel15.ShiftIndex, ppWritePackedMsg, end)); + +} + +static uint8_t pack_ul_dci_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_ul_dci_request_t *pNfapiMsg = (nfapi_nr_ul_dci_request_t*)msg; + + if (!(push16(pNfapiMsg->SFN, ppWritePackedMsg, end) && + push16(pNfapiMsg->Slot, ppWritePackedMsg, end) && + push8(pNfapiMsg->numPdus, ppWritePackedMsg, end) + )) + return 0; + + for(int i=0; inumPdus; i++) + { + if(!pack_ul_dci_pdu_list_value(&pNfapiMsg->ul_dci_pdu_list[i], ppWritePackedMsg, end)) + return 0; + } + return 1; + + +} + + + static uint8_t pack_hi_dci0_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) { nfapi_hi_dci0_request_t *pNfapiMsg = (nfapi_hi_dci0_request_t*)msg; @@ -1526,6 +2111,55 @@ static uint8_t pack_hi_dci0_request(void *msg, uint8_t **ppWritePackedMsg, uint8 pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); } +//pack_tx_data_pdu_list_value +static uint8_t pack_tx_data_pdu_list_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_pdu_t* value = (nfapi_nr_pdu_t*)tlv; + + if(!(push32(value->num_TLV, ppWritePackedMsg, end) && + push16(value->PDU_index, ppWritePackedMsg, end) && + push16(value->PDU_length, ppWritePackedMsg, end) + )) + return 0; + + uint16_t i = 0; + uint16_t total_number_of_tlvs = value->num_TLV; + for(; i < total_number_of_tlvs; ++i) + { + + if (!(push16(value->TLVs[i].length, ppWritePackedMsg, end) && + push16(value->TLVs[i].tag, ppWritePackedMsg, end))) + return 0; + + switch(value->TLVs[i].tag) + { + case 0: + { + if(!pusharray32(value->TLVs[i].value.direct, 16384, value->TLVs[i].length, ppWritePackedMsg, end)) + return 0; + break; + + } + + case 1: + { + if(!pusharray32(value->TLVs[i].value.ptr, value->TLVs[i].length , value->TLVs[i].length, ppWritePackedMsg, end)) + return 0; + break; + + } + + default: + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid tag value %d \n", value->TLVs[i].tag ); + break; + } + + } + } + return 1; +} + static uint8_t pack_tx_request_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { nfapi_tx_request_body_t* value = (nfapi_tx_request_body_t*)tlv; @@ -1551,7 +2185,7 @@ static uint8_t pack_tx_request_body_value(void* tlv, uint8_t **ppWritePackedMsg, // DJP - if(pusharray8(pdu->segments[j].segment_data, (uint32_t)(-1), pdu->segments[j].segment_length, ppWritePackedMsg, end) == 0) int push_ret = pusharray8(pdu->segments[j].segment_data, 65535, pdu->segments[j].segment_length, ppWritePackedMsg, end); - if (pdu->segments[j].segment_length == 3) + if (pdu->segments[j].segment_length == 3) { NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() BCH? segment_data:%x %x %x\n", __FUNCTION__, pdu->segments[j].segment_data[0], @@ -1571,6 +2205,26 @@ static uint8_t pack_tx_request_body_value(void* tlv, uint8_t **ppWritePackedMsg, return 1; } +static uint8_t pack_tx_data_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_tx_data_request_t *pNfapiMsg = (nfapi_nr_tx_data_request_t*)msg; + + if (!( + push16(pNfapiMsg->SFN, ppWritePackedMsg, end) && + push16(pNfapiMsg->Slot, ppWritePackedMsg, end) && + push16(pNfapiMsg->Number_of_PDUs, ppWritePackedMsg, end) + )) + return 0; + + for(int i=0; iNumber_of_PDUs; i++) + { + if(!pack_tx_data_pdu_list_value(&pNfapiMsg->pdu_list[i], ppWritePackedMsg, end)) + return 0; + } + + return 1; +} + static uint8_t pack_tx_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) { nfapi_tx_request_t *pNfapiMsg = (nfapi_tx_request_t*)msg; @@ -1583,43 +2237,43 @@ static uint8_t pack_tx_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *e return x && y && z; } - -static uint8_t pack_release_request_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) -{ - nfapi_ue_release_request_body_t* value = (nfapi_ue_release_request_body_t*)tlv; - if(push16(value->number_of_TLVs, ppWritePackedMsg, end) == 0){ - return 0; - } - - uint8_t j; - uint16_t num = value->number_of_TLVs; - for(j = 0; j < num; ++j){ - if(push16(value->ue_release_request_TLVs_list[j].rnti, ppWritePackedMsg, end) == 0){ - return 0; - } - } - return 1; -} - -static uint8_t pack_ue_release_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - nfapi_ue_release_request_t *pNfapiMsg = (nfapi_ue_release_request_t*)msg; - int x = push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end); - int y = pack_tlv(NFAPI_UE_RELEASE_BODY_TAG, &pNfapiMsg->ue_release_request_body, ppWritePackedMsg, end, &pack_release_request_body_value); - int z = pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config); - return x && y && z; -} - -static uint8_t pack_ue_release_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) -{ - - nfapi_ue_release_response_t *pNfapiMsg = (nfapi_ue_release_response_t*)msg; - - int x = push32(pNfapiMsg->error_code, ppWritePackedMsg, end); - int z = pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config); - return x && z; -} - + +static uint8_t pack_release_request_body_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_ue_release_request_body_t* value = (nfapi_ue_release_request_body_t*)tlv; + if(push16(value->number_of_TLVs, ppWritePackedMsg, end) == 0){ + return 0; + } + + uint8_t j; + uint16_t num = value->number_of_TLVs; + for(j = 0; j < num; ++j){ + if(push16(value->ue_release_request_TLVs_list[j].rnti, ppWritePackedMsg, end) == 0){ + return 0; + } + } + return 1; +} + +static uint8_t pack_ue_release_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_ue_release_request_t *pNfapiMsg = (nfapi_ue_release_request_t*)msg; + int x = push16(pNfapiMsg->sfn_sf, ppWritePackedMsg, end); + int y = pack_tlv(NFAPI_UE_RELEASE_BODY_TAG, &pNfapiMsg->ue_release_request_body, ppWritePackedMsg, end, &pack_release_request_body_value); + int z = pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config); + return x && y && z; +} + +static uint8_t pack_ue_release_response(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + + nfapi_ue_release_response_t *pNfapiMsg = (nfapi_ue_release_response_t*)msg; + + int x = push32(pNfapiMsg->error_code, ppWritePackedMsg, end); + int z = pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config); + return x && z; +} + static uint8_t pack_rx_ue_information_value(void* tlv, uint8_t **ppWritePackedMsg, uint8_t *end) { nfapi_rx_ue_information* value = (nfapi_rx_ue_information*)tlv; @@ -2614,6 +3268,15 @@ static uint8_t pack_nrach_indication(void *msg, uint8_t **ppWritePackedMsg, uint pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); } +static uint8_t pack_nr_dl_node_sync(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_dl_node_sync_t *pNfapiMsg = (nfapi_nr_dl_node_sync_t*)msg; + + return ( push32(pNfapiMsg->t1, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->delta_sfn_slot, ppWritePackedMsg, end) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + static uint8_t pack_dl_node_sync(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) { nfapi_dl_node_sync_t *pNfapiMsg = (nfapi_dl_node_sync_t*)msg; @@ -2623,6 +3286,16 @@ static uint8_t pack_dl_node_sync(void *msg, uint8_t **ppWritePackedMsg, uint8_t pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); } +static uint8_t pack_nr_ul_node_sync(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_ul_node_sync_t *pNfapiMsg = (nfapi_nr_ul_node_sync_t*)msg; + + return (push32(pNfapiMsg->t1, ppWritePackedMsg, end) && + push32(pNfapiMsg->t2, ppWritePackedMsg, end) && + push32(pNfapiMsg->t3, ppWritePackedMsg, end) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + static uint8_t pack_ul_node_sync(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) { nfapi_ul_node_sync_t *pNfapiMsg = (nfapi_ul_node_sync_t*)msg; @@ -2636,7 +3309,7 @@ static uint8_t pack_ul_node_sync(void *msg, uint8_t **ppWritePackedMsg, uint8_t static uint8_t pack_timing_info(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) { nfapi_timing_info_t *pNfapiMsg = (nfapi_timing_info_t*)msg; - + return (push32(pNfapiMsg->last_sfn_sf, ppWritePackedMsg, end) && push32(pNfapiMsg->time_since_last_timing_info, ppWritePackedMsg, end) && push32(pNfapiMsg->dl_config_jitter, ppWritePackedMsg, end) && @@ -2654,9 +3327,211 @@ static uint8_t pack_timing_info(void *msg, uint8_t **ppWritePackedMsg, uint8_t * pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); } +static uint8_t pack_nr_timing_info(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_timing_info_t *pNfapiMsg = (nfapi_nr_timing_info_t*)msg; + + return (push32(pNfapiMsg->last_sfn, ppWritePackedMsg, end) && + push32(pNfapiMsg->last_slot, ppWritePackedMsg, end) && + push32(pNfapiMsg->time_since_last_timing_info, ppWritePackedMsg, end) && + push32(pNfapiMsg->dl_tti_jitter, ppWritePackedMsg, end) && + push32(pNfapiMsg->tx_data_request_jitter, ppWritePackedMsg, end) && + push32(pNfapiMsg->ul_tti_jitter, ppWritePackedMsg, end) && + push32(pNfapiMsg->ul_dci_jitter, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->dl_tti_latest_delay, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->tx_data_request_latest_delay, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->ul_tti_latest_delay, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->ul_dci_latest_delay, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->dl_tti_earliest_arrival, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->tx_data_request_earliest_arrival, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->ul_tti_earliest_arrival, ppWritePackedMsg, end) && + pushs32(pNfapiMsg->ul_dci_earliest_arrival, ppWritePackedMsg, end) && + pack_p7_vendor_extension_tlv(pNfapiMsg->vendor_extension, ppWritePackedMsg, end, config)); +} + + // Main pack function - public +int nfapi_nr_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen, nfapi_p7_codec_config_t* config) +{ + nfapi_p7_message_header_t *pMessageHeader = pMessageBuf; + uint8_t *pWritePackedMessage = pPackedBuf; + uint8_t *pPackedLengthField = &pWritePackedMessage[4]; + uint8_t *end = pPackedBuf + packedBufLen; + + if (pMessageBuf == NULL || pPackedBuf == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack supplied pointers are null\n"); + return -1; + } + /* + printf("\n P7 MESSAGE SENT: \n"); + for(int i=0; i< packedBufLen; i++){ + printf("%d", *(uint8_t *)(pMessageBuf + i)); + } + printf("\n"); + */ + // process the header + if(!(push16(pMessageHeader->phy_id, &pWritePackedMessage, end) && + push16(pMessageHeader->message_id, &pWritePackedMessage, end) && + push16(0/*pMessageHeader->message_length*/, &pWritePackedMessage, end) && + push16(pMessageHeader->m_segment_sequence, &pWritePackedMessage, end) && + push32(0/*pMessageHeader->checksum*/, &pWritePackedMessage, end) && + push32(pMessageHeader->transmit_timestamp, &pWritePackedMessage, end))) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack header failed\n"); + return -1; + } + + if (pMessageHeader->message_id != NFAPI_TIMING_INFO) + { + //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() message_id:0x%04x phy_id:%u m_segment_sequence:%u timestamp:%u\n", __FUNCTION__, pMessageHeader->message_id, pMessageHeader->phy_id, pMessageHeader->m_segment_sequence, pMessageHeader->transmit_timestamp); + } + // look for the specific message + uint8_t result = 0; + switch (pMessageHeader->message_id) + { + case NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST: + result = pack_dl_tti_request(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST: + result = pack_ul_tti_request(pMessageHeader, &pWritePackedMessage, end, config); + break; + case NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST: + result = pack_tx_data_request(pMessageHeader, &pWritePackedMessage, end, config); + break; + case NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST: + result = pack_ul_dci_request(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_UE_RELEASE_REQUEST: + result =pack_ue_release_request(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_UE_RELEASE_RESPONSE: + result =pack_ue_release_response(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_HARQ_INDICATION: + result = pack_harq_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_CRC_INDICATION: + result = pack_crc_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_RX_ULSCH_INDICATION: + //printf("RX ULSCH\n"); + result = pack_rx_ulsch_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_RACH_INDICATION: + result = pack_rach_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_SRS_INDICATION: + result = pack_srs_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_RX_SR_INDICATION: + result = pack_sr_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_RX_CQI_INDICATION: + result = pack_cqi_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_LBT_DL_CONFIG_REQUEST: + result = pack_lbt_dl_config_request(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_LBT_DL_INDICATION: + result = pack_lbt_dl_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_NB_HARQ_INDICATION: + result = pack_nb_harq_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_NRACH_INDICATION: + result = pack_nrach_indication(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC: + result = pack_nr_dl_node_sync(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_NR_PHY_MSG_TYPE_UL_NODE_SYNC: + result = pack_nr_ul_node_sync(pMessageHeader, &pWritePackedMessage, end, config); + break; + + case NFAPI_TIMING_INFO: + result = pack_nr_timing_info(pMessageHeader, &pWritePackedMessage, end, config); + break; + + default: + { + if(pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && + pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) + { + if(config && config->pack_p7_vendor_extension) + { + result = (config->pack_p7_vendor_extension)(pMessageHeader, &pWritePackedMessage, end, config); + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve ecoder provided\n", __FUNCTION__, pMessageHeader->message_id); + } + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown message ID %d\n", __FUNCTION__, pMessageHeader->message_id); + } + } + break; + } + + if(result == 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack failed to pack message\n"); + return -1; + } + + // check for a valid message length + uintptr_t msgHead = (uintptr_t)pPackedBuf; + uintptr_t msgEnd = (uintptr_t)pWritePackedMessage; + uint32_t packedMsgLen = msgEnd - msgHead; + uint16_t packedMsgLen16; + if (packedMsgLen > 0xFFFF || packedMsgLen > packedBufLen) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Packed message length error %d, buffer supplied %d\n", packedMsgLen, packedBufLen); + return -1; + } + else + { + packedMsgLen16 = (uint16_t)packedMsgLen; + } + + // Update the message length in the header + pMessageHeader->message_length = packedMsgLen16; + + if(!push16(packedMsgLen16, &pPackedLengthField, end)) + return -1; + + if(1) + { + //quick test + if(pMessageHeader->message_length != packedMsgLen) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "nfapi packedMsgLen(%d) != message_length(%d) id %d\n", packedMsgLen, pMessageHeader->message_length, pMessageHeader->message_id); + } + } + + return (packedMsgLen); +} + int nfapi_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen, nfapi_p7_codec_config_t* config) { nfapi_p7_message_header_t *pMessageHeader = pMessageBuf; @@ -2669,7 +3544,13 @@ int nfapi_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBu NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack supplied pointers are null\n"); return -1; } - + /* + printf("\n P7 MESSAGE SENT: \n"); + for(int i=0; i< packedBufLen; i++){ + printf("%d", *(uint8_t *)(pMessageBuf + i)); + } + printf("\n"); + */ // process the header if(!(push16(pMessageHeader->phy_id, &pWritePackedMessage, end) && push16(pMessageHeader->message_id, &pWritePackedMessage, end) && @@ -2698,24 +3579,22 @@ int nfapi_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBu case NFAPI_UL_CONFIG_REQUEST: result = pack_ul_config_request(pMessageHeader, &pWritePackedMessage, end, config); break; - + case NFAPI_TX_REQUEST: + //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() NFAPI_TX_REQUEST\n", __FUNCTION__); + result = pack_tx_request(pMessageHeader, &pWritePackedMessage, end, config); + break; case NFAPI_HI_DCI0_REQUEST: result = pack_hi_dci0_request(pMessageHeader, &pWritePackedMessage, end, config); break; - - case NFAPI_TX_REQUEST: - //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() NFAPI_TX_REQUEST\n", __FUNCTION__); - result = pack_tx_request(pMessageHeader, &pWritePackedMessage, end, config); + + case NFAPI_UE_RELEASE_REQUEST: + result =pack_ue_release_request(pMessageHeader, &pWritePackedMessage, end, config); break; - - case NFAPI_UE_RELEASE_REQUEST: - result =pack_ue_release_request(pMessageHeader, &pWritePackedMessage, end, config); - break; - - case NFAPI_UE_RELEASE_RESPONSE: - result =pack_ue_release_response(pMessageHeader, &pWritePackedMessage, end, config); - break; - + + case NFAPI_UE_RELEASE_RESPONSE: + result =pack_ue_release_response(pMessageHeader, &pWritePackedMessage, end, config); + break; + case NFAPI_HARQ_INDICATION: result = pack_harq_indication(pMessageHeader, &pWritePackedMessage, end, config); break; @@ -2834,10 +3713,158 @@ int nfapi_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBu return (packedMsgLen); } - - // Unpack routines +// NR: +static uint8_t unpack_dl_tti_csi_rs_pdu_rel15_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_nr_dl_tti_csi_rs_pdu_rel15_t* value = (nfapi_nr_dl_tti_csi_rs_pdu_rel15_t*)tlv; + return( + pull16(ppReadPackedMsg, &value->bwp_size, end) && + pull16(ppReadPackedMsg, &value->bwp_start, end) && + + pull8(ppReadPackedMsg, &value->subcarrier_spacing, end) && + pull8(ppReadPackedMsg, &value->cyclic_prefix, end) && + + pull16(ppReadPackedMsg, &value->start_rb, end) && + pull16(ppReadPackedMsg, &value->nr_of_rbs, end) && + + pull8(ppReadPackedMsg, &value->csi_type, end) && + pull8(ppReadPackedMsg, &value->row, end) && + + pull16(ppReadPackedMsg, &value->freq_domain, end) && + pull8(ppReadPackedMsg, &value->symb_l0, end) && + + pull8(ppReadPackedMsg, &value->symb_l1, end) && + pull8(ppReadPackedMsg, &value->cdm_type, end) && + + pull8(ppReadPackedMsg, &value->freq_density, end) && + pull16(ppReadPackedMsg, &value->scramb_id, end) && + + pull8(ppReadPackedMsg, &value->power_control_offset, end) && + pull8(ppReadPackedMsg, &value->power_control_offset_ss, end) + ); + +} + + +static uint8_t unpack_dl_tti_pdcch_pdu_rel15_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_nr_dl_tti_pdcch_pdu_rel15_t* value = (nfapi_nr_dl_tti_pdcch_pdu_rel15_t*)tlv; + + for(uint8_t i = 0; i < MAX_DCI_CORESET; ++i) + { + if(!pull16(ppReadPackedMsg, &value->dci_pdu[i].RNTI, end) && + pull16(ppReadPackedMsg, &value->dci_pdu[i].ScramblingId, end) && + + pull16(ppReadPackedMsg, &value->dci_pdu[i].ScramblingRNTI, end) && + pull8(ppReadPackedMsg, &value->dci_pdu[i].CceIndex, end) && + pull8(ppReadPackedMsg, &value->dci_pdu[i].AggregationLevel, end) && + pull8(ppReadPackedMsg, &value->dci_pdu[i].beta_PDCCH_1_0, end) && + + pull8(ppReadPackedMsg, &value->dci_pdu[i].powerControlOffsetSS, end) && + pull16(ppReadPackedMsg, &value->dci_pdu[i].PayloadSizeBits, end) && + + pullarray8(ppReadPackedMsg, value->dci_pdu[i].Payload, DCI_PAYLOAD_BYTE_LEN, value->dci_pdu[i].PayloadSizeBits, end)); + + return 0; + } + + // TODO: resolve the packaging of array (currently sending a single element) + return( + pull16(ppReadPackedMsg, &value->BWPSize, end) && + pull16(ppReadPackedMsg, &value->BWPStart, end) && + pull8(ppReadPackedMsg, &value->SubcarrierSpacing, end) && + pull8(ppReadPackedMsg, &value->CyclicPrefix, end) && + + pull8(ppReadPackedMsg, &value->StartSymbolIndex, end) && + pull8(ppReadPackedMsg, &value->DurationSymbols, end) && + pullarray8(ppReadPackedMsg, value->FreqDomainResource, 6, 6, end) && + pull8(ppReadPackedMsg, &value->CceRegMappingType, end) && + + pull8(ppReadPackedMsg, &value->RegBundleSize, end) && + pull8(ppReadPackedMsg, &value->InterleaverSize, end) && + pull8(ppReadPackedMsg, &value->CoreSetType, end) && + pull16(ppReadPackedMsg, &value->ShiftIndex, end) && + + pull8(ppReadPackedMsg, &value->precoderGranularity, end) && + pull16(ppReadPackedMsg, &value->numDlDci, end)); + +} + + +static uint8_t unpack_dl_tti_pdsch_pdu_rel15_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_nr_dl_tti_pdsch_pdu_rel15_t* value = (nfapi_nr_dl_tti_pdsch_pdu_rel15_t*)tlv; + + // TODO: resolve the packaging of array (currently sending a single element) + return( + pull16(ppReadPackedMsg, &value->pduBitmap, end) && + pull16(ppReadPackedMsg, &value->rnti, end) && + pull16(ppReadPackedMsg, &value->pduIndex, end) && + pull16(ppReadPackedMsg, &value->BWPSize, end) && + + pull16(ppReadPackedMsg, &value->BWPStart, end) && + pull8(ppReadPackedMsg, &value->SubcarrierSpacing, end) && + pull8(ppReadPackedMsg, &value->CyclicPrefix, end) && + pull8(ppReadPackedMsg, &value->NrOfCodewords, end) && + + pullarray16(ppReadPackedMsg, value->targetCodeRate, 2, 1, end) && + pullarray8(ppReadPackedMsg, value->qamModOrder, 2, 1, end) && + pullarray8(ppReadPackedMsg, value->mcsIndex, 2, 1, end) && + pullarray8(ppReadPackedMsg, value->mcsTable, 2, 1, end) && + + pullarray8(ppReadPackedMsg, value->rvIndex, 2, 1, end) && + pullarray32(ppReadPackedMsg, value->TBSize, 2, 1, end) && + pull16(ppReadPackedMsg, &value->dataScramblingId, end) && + pull8(ppReadPackedMsg, &value->nrOfLayers, end) && + + pull8(ppReadPackedMsg, &value->transmissionScheme, end) && + pull8(ppReadPackedMsg, &value->refPoint, end) && + pull16(ppReadPackedMsg, &value->dlDmrsSymbPos, end) && + pull8(ppReadPackedMsg, &value->dmrsConfigType, end) && + + pull16(ppReadPackedMsg, &value->dlDmrsScramblingId, end) && + pull8(ppReadPackedMsg, &value->SCID, end) && + pull8(ppReadPackedMsg, &value->numDmrsCdmGrpsNoData, end) && + pull16(ppReadPackedMsg, &value->dmrsPorts, end) && + + pull8(ppReadPackedMsg, &value->resourceAlloc, end) && + pull16(ppReadPackedMsg, &value->rbStart, end) && + pull16(ppReadPackedMsg, &value->rbSize, end) && + + pull8(ppReadPackedMsg, &value->VRBtoPRBMapping, end) && + pull8(ppReadPackedMsg, &value->StartSymbolIndex, end) && + pull8(ppReadPackedMsg, &value->NrOfSymbols, end) && + pull8(ppReadPackedMsg, &value->PTRSPortIndex, end) && + + pull8(ppReadPackedMsg, &value->PTRSTimeDensity, end) && + pull8(ppReadPackedMsg, &value->PTRSFreqDensity, end) && + pull8(ppReadPackedMsg, &value->PTRSReOffset, end) + ); + +} + + +static uint8_t unpack_dl_tti_ssb_pdu_rel15_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_nr_dl_tti_ssb_pdu_rel15_t* value = (nfapi_nr_dl_tti_ssb_pdu_rel15_t*)tlv; + + return( + pull16(ppReadPackedMsg, &value->PhysCellId, end) && + pull8(ppReadPackedMsg, &value->BetaPss, end) && + pull8(ppReadPackedMsg, &value->SsbBlockIndex, end) && + pull8(ppReadPackedMsg, &value->SsbSubcarrierOffset, end) && + pull16(ppReadPackedMsg, &value->ssbOffsetPointA, end) && + pull8(ppReadPackedMsg, &value->bchPayloadFlag, end) && + pull32(ppReadPackedMsg, &value->bchPayload, end) + // TODO: pack precoding_and_beamforming too + ); + +} + + +// LTE: static uint8_t unpack_dl_config_dci_dl_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { nfapi_dl_config_dci_dl_pdu_rel8_t* dci_dl_pdu_rel8 = (nfapi_dl_config_dci_dl_pdu_rel8_t*)tlv; @@ -3279,7 +4306,58 @@ static uint8_t unpack_dl_config_ndlsch_pdu_rel13_value(void *tlv, uint8_t **ppRe pull8(ppReadPackedMsg, &ndlsch_params_rel13->scrambling_sequence_initialization_cinit, end) && pull16(ppReadPackedMsg, &ndlsch_params_rel13->sf_idx, end) && pull8(ppReadPackedMsg, &ndlsch_params_rel13->nrs_antenna_ports_assumed_by_the_ue, end)); -} +} + + +static uint8_t unpack_dl_tti_request_body_value(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg) +{ + nfapi_nr_dl_tti_request_pdu_t* value = (nfapi_nr_dl_tti_request_pdu_t*)msg; + + if(!(pull16(ppReadPackedMsg, &value->PDUSize, end) && + pull16(ppReadPackedMsg, &value->PDUType, end) )) + return 0; + + + // first match the pdu type, then call the respective function + switch(value->PDUType) + { + case NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE: + { + if(!(unpack_dl_tti_csi_rs_pdu_rel15_value(&value->csi_rs_pdu.csi_rs_pdu_rel15,ppReadPackedMsg,end))) + return 0; + } + break; + + case NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE: + { + if(!(unpack_dl_tti_pdcch_pdu_rel15_value(&value->pdcch_pdu.pdcch_pdu_rel15,ppReadPackedMsg,end))) + return 0; + } + break; + case NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE: + { + if(!(unpack_dl_tti_pdsch_pdu_rel15_value(&value->pdsch_pdu.pdsch_pdu_rel15,ppReadPackedMsg,end))) + return 0; + } + break; + case NFAPI_NR_DL_TTI_SSB_PDU_TYPE: + { + if(!(unpack_dl_tti_ssb_pdu_rel15_value(&value->ssb_pdu.ssb_pdu_rel15,ppReadPackedMsg,end))) + return 0; + } + break; + + default: + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid DL_TTI pdu type %d \n", value->PDUType ); + } + break; + } + + return 1; +} + + static uint8_t unpack_dl_config_request_body_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) @@ -3483,6 +4561,334 @@ static uint8_t unpack_dl_config_request_body_value(void *tlv, uint8_t **ppReadPa return 1; } + +static uint8_t unpack_dl_tti_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_dl_tti_request_t *pNfapiMsg = (nfapi_nr_dl_tti_request_t*)msg; + + if (!(pull16(ppReadPackedMsg,&pNfapiMsg->SFN, end) && + pull16(ppReadPackedMsg, &pNfapiMsg->Slot, end) && + pull8(ppReadPackedMsg, &pNfapiMsg->dl_tti_request_body.nGroup, end) && + pull8(ppReadPackedMsg, &pNfapiMsg->dl_tti_request_body.nPDUs, end) && + pullarray8(ppReadPackedMsg,pNfapiMsg->dl_tti_request_body.nUe ,256,pNfapiMsg->dl_tti_request_body.nGroup, end) + //pusharray8(pNfapiMsg->PduIdx[0] ,256,256, ppWritePackedMsg, end) + )) + return 0; + + int arr[12]; + for(int i=0;idl_tti_request_body.nGroup;i++) + { + for(int j=0;jdl_tti_request_body.nUe[i];j++) + { + arr[j] = pNfapiMsg->dl_tti_request_body.PduIdx[i][j]; + } + if(!(pullarrays32(ppReadPackedMsg,arr,12,pNfapiMsg->dl_tti_request_body.nUe[i], end))) + return 0; + } + + for(int i=0;idl_tti_request_body.nPDUs;i++) + { + if(!unpack_dl_tti_request_body_value(ppReadPackedMsg, end, &pNfapiMsg->dl_tti_request_body.dl_tti_pdu_list[i])) + return 0; + } + +return 1; +} + + +static uint8_t unpack_ul_tti_request_prach_pdu(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_nr_prach_pdu_t* prach_pdu = (nfapi_nr_prach_pdu_t*)tlv; + + return( + pull16(ppReadPackedMsg, &prach_pdu->phys_cell_id, end) && + pull8(ppReadPackedMsg, &prach_pdu->num_prach_ocas, end) && + pull8(ppReadPackedMsg, &prach_pdu->prach_format, end) && + pull8(ppReadPackedMsg, &prach_pdu->num_ra, end) && + pull8(ppReadPackedMsg, &prach_pdu->prach_start_symbol, end) && + pull16(ppReadPackedMsg, &prach_pdu->num_cs, end) + // TODO: ignoring beamforming tlv for now + ); +} + + +static uint8_t unpack_ul_tti_request_pucch_pdu(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_nr_pucch_pdu_t* pucch_pdu = (nfapi_nr_pucch_pdu_t*)tlv; + + return( + pull16(ppReadPackedMsg, &pucch_pdu->rnti, end) && + pull32(ppReadPackedMsg, &pucch_pdu->handle, end) && + pull16(ppReadPackedMsg, &pucch_pdu->bwp_size, end) && + pull16(ppReadPackedMsg, &pucch_pdu->bwp_start, end) && + pull8(ppReadPackedMsg, &pucch_pdu->subcarrier_spacing, end) && + pull8(ppReadPackedMsg, &pucch_pdu->cyclic_prefix, end) && + pull8(ppReadPackedMsg, &pucch_pdu->format_type, end) && + pull8(ppReadPackedMsg, &pucch_pdu->multi_slot_tx_indicator, end) && + pull16(ppReadPackedMsg, &pucch_pdu->prb_start, end) && + pull16(ppReadPackedMsg, &pucch_pdu->prb_size, end) && + pull8(ppReadPackedMsg, &pucch_pdu->start_symbol_index, end) && + pull8(ppReadPackedMsg, &pucch_pdu->nr_of_symbols, end) && + pull8(ppReadPackedMsg, &pucch_pdu->freq_hop_flag, end) && + pull16(ppReadPackedMsg, &pucch_pdu->second_hop_prb, end) && + pull8(ppReadPackedMsg, &pucch_pdu->group_hop_flag, end) && + pull8(ppReadPackedMsg, &pucch_pdu->sequence_hop_flag, end) && + pull16(ppReadPackedMsg, &pucch_pdu->hopping_id, end) && + pull16(ppReadPackedMsg, &pucch_pdu->initial_cyclic_shift, end) && + pull16(ppReadPackedMsg, &pucch_pdu->data_scrambling_id, end) && + pull8(ppReadPackedMsg, &pucch_pdu->time_domain_occ_idx, end) && + pull8(ppReadPackedMsg, &pucch_pdu->pre_dft_occ_idx, end) && + pull8(ppReadPackedMsg, &pucch_pdu->pre_dft_occ_len, end) && + pull8(ppReadPackedMsg, &pucch_pdu->add_dmrs_flag, end) && + pull16(ppReadPackedMsg, &pucch_pdu->dmrs_scrambling_id, end) && + pull8(ppReadPackedMsg, &pucch_pdu->dmrs_cyclic_shift, end) && + pull8(ppReadPackedMsg, &pucch_pdu->sr_flag, end) && + pull8(ppReadPackedMsg, &pucch_pdu->bit_len_harq, end) && + pull16(ppReadPackedMsg, &pucch_pdu->bit_len_csi_part1, end) && + pull16(ppReadPackedMsg, &pucch_pdu->bit_len_csi_part2, end) + // TODO: ignoring beamforming tlv for now + ); +} + + +static uint8_t unpack_ul_tti_request_pusch_pdu(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_nr_pusch_pdu_t* pusch_pdu = (nfapi_nr_pusch_pdu_t*)tlv; + + if (!( + pull16(ppReadPackedMsg, &pusch_pdu->pdu_bit_map, end) && + pull16(ppReadPackedMsg, &pusch_pdu->rnti, end) && + pull32(ppReadPackedMsg, &pusch_pdu->handle, end) && + pull16(ppReadPackedMsg, &pusch_pdu->bwp_size, end) && + pull16(ppReadPackedMsg, &pusch_pdu->bwp_start, end) && + pull8(ppReadPackedMsg, &pusch_pdu->subcarrier_spacing, end) && + pull8(ppReadPackedMsg, &pusch_pdu->cyclic_prefix, end) && + pull16(ppReadPackedMsg, &pusch_pdu->target_code_rate, end) && + pull8(ppReadPackedMsg, &pusch_pdu->qam_mod_order, end) && + pull8(ppReadPackedMsg, &pusch_pdu->mcs_index, end) && + pull8(ppReadPackedMsg, &pusch_pdu->mcs_table, end) && + pull8(ppReadPackedMsg, &pusch_pdu->transform_precoding, end) && + pull16(ppReadPackedMsg, &pusch_pdu->data_scrambling_id, end) && + pull8(ppReadPackedMsg, &pusch_pdu->nrOfLayers, end) && + pull16(ppReadPackedMsg, &pusch_pdu->ul_dmrs_symb_pos, end) && + pull8(ppReadPackedMsg, &pusch_pdu->dmrs_config_type, end) && + pull16(ppReadPackedMsg, &pusch_pdu->ul_dmrs_scrambling_id, end) && + pull8(ppReadPackedMsg, &pusch_pdu->scid, end) && + pull8(ppReadPackedMsg, &pusch_pdu->num_dmrs_cdm_grps_no_data, end) && + pull16(ppReadPackedMsg, &pusch_pdu->dmrs_ports, end) && + pull8(ppReadPackedMsg, &pusch_pdu->resource_alloc, end) && + pull8(ppReadPackedMsg, &pusch_pdu->resource_alloc,end) && + pull16(ppReadPackedMsg, &pusch_pdu->dmrs_ports, end) && + pull16(ppReadPackedMsg, &pusch_pdu->rb_start, end) && + pull16(ppReadPackedMsg, &pusch_pdu->rb_size, end) && + pull8(ppReadPackedMsg, &pusch_pdu->vrb_to_prb_mapping, end) && + pull8(ppReadPackedMsg, &pusch_pdu->frequency_hopping, end) && + pull16(ppReadPackedMsg, &pusch_pdu->tx_direct_current_location, end) && + pull8(ppReadPackedMsg, &pusch_pdu->uplink_frequency_shift_7p5khz, end) && + pull8(ppReadPackedMsg, &pusch_pdu->start_symbol_index, end) && + pull8(ppReadPackedMsg, &pusch_pdu->nr_of_symbols, end) + // TODO: ignoring beamforming tlv for now + )) + return 0; + + + //Pack Optional Data only included if indicated in pduBitmap + switch(pusch_pdu->pdu_bit_map){ + case PUSCH_PDU_BITMAP_PUSCH_DATA: + { + // pack optional TLVs + return( + pull8(ppReadPackedMsg, &pusch_pdu->pusch_data.rv_index, end) && + pull8(ppReadPackedMsg, &pusch_pdu->pusch_data.harq_process_id, end) && + pull32(ppReadPackedMsg, &pusch_pdu->pusch_data.tb_size, end) && + pull16(ppReadPackedMsg, &pusch_pdu->pusch_data.num_cb, end) && + pullarray8(ppReadPackedMsg, pusch_pdu->pusch_data.cb_present_and_position,1,1,end) + ); + } + break; + + case PUSCH_PDU_BITMAP_PUSCH_UCI: + { + return( + pull16(ppReadPackedMsg, &pusch_pdu->pusch_uci.harq_ack_bit_length, end) && + pull16(ppReadPackedMsg, &pusch_pdu->pusch_uci.csi_part1_bit_length, end) && + pull16(ppReadPackedMsg, &pusch_pdu->pusch_uci.csi_part2_bit_length, end) && + pull8(ppReadPackedMsg, &pusch_pdu->pusch_uci.alpha_scaling, end) && + pull8(ppReadPackedMsg, &pusch_pdu->pusch_uci.beta_offset_harq_ack, end) && + pull8(ppReadPackedMsg, &pusch_pdu->pusch_uci.beta_offset_csi1, end) && + pull8(ppReadPackedMsg, &pusch_pdu->pusch_uci.beta_offset_csi2, end) + ); + } + break; + + case PUSCH_PDU_BITMAP_PUSCH_PTRS: + { + return( + pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.num_ptrs_ports, end) && + pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_dmrs_port, end) && ++ pull16(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_port_index, end) && ++ pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_ports_list->ptrs_re_offset, end) && + pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_time_density, end) && + pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ptrs_freq_density, end) && + pull8(ppReadPackedMsg, &pusch_pdu->pusch_ptrs.ul_ptrs_power, end) + ); + } + break; + + case PUSCH_PDU_BITMAP_DFTS_OFDM: + { + return( + pull8(ppReadPackedMsg, &pusch_pdu->dfts_ofdm.low_papr_group_number, end) && + pull16(ppReadPackedMsg, &pusch_pdu->dfts_ofdm.low_papr_sequence_number, end) && + pull8(ppReadPackedMsg, &pusch_pdu->dfts_ofdm.ul_ptrs_sample_density, end) && + pull8(ppReadPackedMsg, &pusch_pdu->dfts_ofdm.ul_ptrs_time_density_transform_precoding, end) + ); + } + break; + + default: + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "Invalid pdu bitmap %d \n", pusch_pdu->pdu_bit_map ); + } + } + + return 1; +} + + +static uint8_t unpack_ul_tti_request_srs_pdu(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_nr_srs_pdu_t* srs_pdu = (nfapi_nr_srs_pdu_t*)tlv; + + return( + pull16(ppReadPackedMsg, &srs_pdu->rnti, end) && + pull32(ppReadPackedMsg, &srs_pdu->handle, end) && + pull16(ppReadPackedMsg, &srs_pdu->bwp_size, end) && + pull16(ppReadPackedMsg, &srs_pdu->bwp_start, end) && + pull8(ppReadPackedMsg, &srs_pdu->subcarrier_spacing, end) && + pull8(ppReadPackedMsg, &srs_pdu->cyclic_prefix, end) && + pull8(ppReadPackedMsg, &srs_pdu->num_ant_ports, end) && + pull8(ppReadPackedMsg, &srs_pdu->num_symbols, end) && + pull8(ppReadPackedMsg, &srs_pdu->num_repetitions, end) && + pull8(ppReadPackedMsg, &srs_pdu->time_start_position, end) && + pull8(ppReadPackedMsg, &srs_pdu->config_index, end) && + pull16(ppReadPackedMsg, &srs_pdu->sequence_id, end) && + pull8(ppReadPackedMsg, &srs_pdu->bandwidth_index, end) && + pull8(ppReadPackedMsg, &srs_pdu->comb_size, end) && + pull8(ppReadPackedMsg, &srs_pdu->comb_offset, end) && + pull8(ppReadPackedMsg, &srs_pdu->cyclic_shift, end) && + pull8(ppReadPackedMsg, &srs_pdu->frequency_position, end) && + pull8(ppReadPackedMsg, &srs_pdu->frequency_shift, end) && + pull8(ppReadPackedMsg, &srs_pdu->frequency_hopping, end) && + pull8(ppReadPackedMsg, &srs_pdu->group_or_sequence_hopping, end) && + pull8(ppReadPackedMsg, &srs_pdu->resource_type, end) && + pull16(ppReadPackedMsg, &srs_pdu->t_srs, end) && + pull16(ppReadPackedMsg, &srs_pdu->t_offset, end) + // TODO: ignoring beamforming tlv for now + ); +} + + +static uint8_t unpack_ul_tti_pdu_list_value(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg) +{ + nfapi_nr_ul_tti_request_number_of_pdus_t* pNfapiMsg = (nfapi_nr_ul_tti_request_number_of_pdus_t*)msg; + + if(!(pull16(ppReadPackedMsg, &pNfapiMsg->pdu_size, end) && + pull16(ppReadPackedMsg, &pNfapiMsg->pdu_type, end) )) + return 0; + + + // first natch the pdu type, then call the respective function + switch(pNfapiMsg->pdu_type) + { + + case NFAPI_NR_UL_CONFIG_PRACH_PDU_TYPE: + { + if(!unpack_ul_tti_request_prach_pdu(&pNfapiMsg->prach_pdu, ppReadPackedMsg, end)) + return 0; + } + break; + + case NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE: + { + if(!unpack_ul_tti_request_pucch_pdu(&pNfapiMsg->pucch_pdu, ppReadPackedMsg, end)) + return 0; + } + break; + + case NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE: + { + if(!unpack_ul_tti_request_pusch_pdu(&pNfapiMsg->pusch_pdu, ppReadPackedMsg, end)) + return 0; + } + break; + + case NFAPI_NR_UL_CONFIG_SRS_PDU_TYPE: + { + if(!unpack_ul_tti_request_srs_pdu(&pNfapiMsg->srs_pdu, ppReadPackedMsg, end)) + return 0; + } + break; + + default: + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid UL_TTI pdu type %d \n", pNfapiMsg->pdu_type ); + } + break; + + + } + + return 1; +} + + +static uint8_t unpack_ul_tti_groups_list_value(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg) +{ + nfapi_nr_ul_tti_request_number_of_groups_t* pNfapiMsg = (nfapi_nr_ul_tti_request_number_of_groups_t*)msg; + + if(!pull8(ppReadPackedMsg, &pNfapiMsg->n_ue, end)) + return 0; + for (int i = 0; i < pNfapiMsg->n_ue; i++) + { + if(!pull8(ppReadPackedMsg, &pNfapiMsg->ue_list[i].pdu_idx ,end) ) + return 0; + } + return 1; +} + + +static uint8_t unpack_ul_tti_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_ul_tti_request_t *pNfapiMsg = (nfapi_nr_ul_tti_request_t*)msg; + + if (!( + pull16(ppReadPackedMsg, &pNfapiMsg->SFN, end) && + pull16(ppReadPackedMsg, &pNfapiMsg->Slot, end) && + pull8(ppReadPackedMsg, &pNfapiMsg->n_pdus, end) && + pull8(ppReadPackedMsg, &pNfapiMsg->n_group, end) && + pull8(ppReadPackedMsg, &pNfapiMsg->rach_present, end) && + pull8(ppReadPackedMsg, &pNfapiMsg->n_ulcch, end) && + pull8(ppReadPackedMsg, &pNfapiMsg->n_ulsch, end) )) + return 0; + + for(int i=0; i< pNfapiMsg->n_pdus; i++) + { + if (!unpack_ul_tti_pdu_list_value(ppReadPackedMsg, end, &pNfapiMsg->pdus_list[i])) + return 0; + } + + for(int i=0; i< pNfapiMsg->n_group; i++) + { + if (!unpack_ul_tti_groups_list_value(ppReadPackedMsg, end, &pNfapiMsg->groups_list[i])) + return 0; + } + + return 1; +} + + + static uint8_t unpack_dl_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) { nfapi_dl_config_request_t *pNfapiMsg = (nfapi_dl_config_request_t*)msg; @@ -3498,6 +4904,9 @@ static uint8_t unpack_dl_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, static uint8_t unpack_ul_config_ulsch_pdu_rel8_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { + + + nfapi_ul_config_ulsch_pdu_rel8_t* ulsch_pdu_rel8 = (nfapi_ul_config_ulsch_pdu_rel8_t*)tlv; return (pull32(ppReadPackedMsg, &ulsch_pdu_rel8->handle, end) && @@ -3516,6 +4925,7 @@ static uint8_t unpack_ul_config_ulsch_pdu_rel8_value(void *tlv, uint8_t **ppRead pull8(ppReadPackedMsg, &ulsch_pdu_rel8->current_tx_nb, end) && pull8(ppReadPackedMsg, &ulsch_pdu_rel8->n_srs, end )); } + static uint8_t unpack_ul_config_ulsch_pdu_rel10_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { nfapi_ul_config_ulsch_pdu_rel10_t* ulsch_pdu_rel10 = (nfapi_ul_config_ulsch_pdu_rel10_t*)tlv; @@ -4415,6 +5825,70 @@ static uint8_t unpack_hi_dci0_request_body_value(void *tlv, uint8_t **ppReadPack return 1; } +//unpack_ul_dci_pdu_list_value + +static uint8_t unpack_ul_dci_pdu_list_value(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg) +{ + nfapi_nr_ul_dci_request_pdus_t* value = (nfapi_nr_ul_dci_request_pdus_t*)msg; + + for(uint8_t i = 0; i < MAX_DCI_CORESET; ++i) + { + if(!pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].RNTI, end) && + pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].ScramblingId, end) && + + pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].ScramblingRNTI, end) && + pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].CceIndex, end) && + pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].AggregationLevel, end) && + pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].beta_PDCCH_1_0, end) && + + pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].powerControlOffsetSS, end) && + pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, end) && + + pullarray8(ppReadPackedMsg, value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].Payload, DCI_PAYLOAD_BYTE_LEN, value->pdcch_pdu.pdcch_pdu_rel15.dci_pdu[i].PayloadSizeBits, end)); + + return 0; + } + + return (pull16(ppReadPackedMsg, &value->PDUType, end) && + pull16(ppReadPackedMsg, &value->PDUSize, end) && + pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.BWPSize, end) && + pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.BWPStart, end) && + pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.SubcarrierSpacing, end) && + pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.CyclicPrefix, end) && + + pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.StartSymbolIndex, end) && + pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.DurationSymbols, end) && + pullarray8(ppReadPackedMsg, value->pdcch_pdu.pdcch_pdu_rel15.FreqDomainResource, 6, 6, end) && + pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.CceRegMappingType, end) && + + pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.RegBundleSize, end) && + pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.InterleaverSize, end) && + pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.CoreSetType, end) && + pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.ShiftIndex, end) && + + pull8(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.precoderGranularity, end) && + pull16(ppReadPackedMsg, &value->pdcch_pdu.pdcch_pdu_rel15.numDlDci, end)); + +} + +static uint8_t unpack_ul_dci_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ +nfapi_nr_ul_dci_request_t *pNfapiMsg = (nfapi_nr_ul_dci_request_t*)msg; + + if (!(pull16(ppReadPackedMsg, &pNfapiMsg->SFN, end) && + pull16(ppReadPackedMsg, &pNfapiMsg->Slot, end) && + pull8(ppReadPackedMsg, &pNfapiMsg->numPdus, end) + )) + return 0; + for(int i=0; i< pNfapiMsg->numPdus; i++) + { + if (!unpack_ul_dci_pdu_list_value(ppReadPackedMsg, end, &pNfapiMsg->ul_dci_pdu_list[i])) + return 0; + } + + return 1; + +} static uint8_t unpack_hi_dci0_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) { @@ -4429,6 +5903,72 @@ static uint8_t unpack_hi_dci0_request(uint8_t **ppReadPackedMsg, uint8_t *end, v unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); } +static uint8_t unpack_tx_data_pdu_list_value(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg) +{ + nfapi_nr_pdu_t* pNfapiMsg = (nfapi_nr_pdu_t*)msg; + + if(!(pull32(ppReadPackedMsg, &pNfapiMsg->num_TLV, end) && + pull16(ppReadPackedMsg, &pNfapiMsg->PDU_index, end) && + pull16(ppReadPackedMsg, &pNfapiMsg->PDU_length, end) + )) + return 0; + + uint16_t i = 0; + uint16_t total_number_of_tlvs = pNfapiMsg->num_TLV; + for(; i < total_number_of_tlvs; ++i) + { + + if (!(pull16(ppReadPackedMsg, &pNfapiMsg->TLVs[i].length, end) && + pull16(ppReadPackedMsg, &pNfapiMsg->TLVs[i].tag, end))) + return 0; + + switch(pNfapiMsg->TLVs[i].tag){ + case 0: + { + if(!pullarray32(ppReadPackedMsg, pNfapiMsg->TLVs[i].value.direct, 16384, pNfapiMsg->TLVs[i].length, end)) + return 0; + break; + + } + + case 1: + { + if(!pullarray32(ppReadPackedMsg, pNfapiMsg->TLVs[i].value.ptr, pNfapiMsg->TLVs[i].length , pNfapiMsg->TLVs[i].length, end)) + return 0; + break; + + } + + default: + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "FIXME : Invalid tag value %d \n", pNfapiMsg->TLVs[i].tag ); + break; + } + + } + } + + + return 1; +} + +static uint8_t unpack_tx_data_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_tx_data_request_t *pNfapiMsg = (nfapi_nr_tx_data_request_t*)msg; + + if(!(pull16(ppReadPackedMsg, &pNfapiMsg->SFN, end) && + pull16(ppReadPackedMsg, &pNfapiMsg->Slot, end) && + pull16(ppReadPackedMsg, &pNfapiMsg->Number_of_PDUs, end))) + return 0; + + for(int i=0; i< pNfapiMsg->Number_of_PDUs; i++) + { + if (!unpack_tx_data_pdu_list_value(ppReadPackedMsg, end, &pNfapiMsg->pdu_list[i])) + return 0; + } + + return 1; +} static uint8_t unpack_tx_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) { @@ -4479,43 +6019,43 @@ static uint8_t unpack_tx_request(uint8_t **ppReadPackedMsg, uint8_t *end, void * for(i = 0; i < totalNumPdus; ++i) { nfapi_tx_request_pdu_t* pdu = &(pNfapiMsg->tx_request_body.tx_pdu_list[i]); - if (pdu) { - uint16_t length = 0; - uint16_t index = 0; + if (pdu) { + uint16_t length = 0; + uint16_t index = 0; - if(!(pull16(ppReadPackedMsg, &length, end) && + if(!(pull16(ppReadPackedMsg, &length, end) && pull16(ppReadPackedMsg, &index, end))) - return 0; + return 0; - pdu->pdu_length = length; - pdu->pdu_index = index; + pdu->pdu_length = length; + pdu->pdu_index = index; // TODO : May need to rethink this bit - pdu->num_segments = 1; - pdu->segments[0].segment_length = pdu->pdu_length; - pdu->segments[0].segment_data = nfapi_p7_allocate(pdu->pdu_length, config); + pdu->num_segments = 1; + pdu->segments[0].segment_length = pdu->pdu_length; + pdu->segments[0].segment_data = nfapi_p7_allocate(pdu->pdu_length, config); - if(pdu->segments[0].segment_data) - { - if(!pullarray8(ppReadPackedMsg, pdu->segments[0].segment_data, pdu->segments[0].segment_length, pdu->segments[0].segment_length, end)) + if(pdu->segments[0].segment_data) + { + if(!pullarray8(ppReadPackedMsg, pdu->segments[0].segment_data, pdu->segments[0].segment_length, pdu->segments[0].segment_length, end)) return 0; - if (pdu->segments[0].segment_length == 3) - { + if (pdu->segments[0].segment_length == 3) + { NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() BCH? segment_data:%x %x %x\n", __FUNCTION__, pdu->segments[0].segment_data[0], pdu->segments[0].segment_data[1], pdu->segments[0].segment_data[2] ); - } - } - else - { + } + } + else + { NFAPI_TRACE(NFAPI_TRACE_ERROR, "unpack_tx_request: Failed to allocate pdu (len:%d) %d/%d %d\n", pdu->pdu_length, totalNumPdus, i, pdu->pdu_index); - } - } else { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "NULL pdu\n"); - } + } + } else { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "NULL pdu\n"); + } } } break; @@ -4529,55 +6069,55 @@ static uint8_t unpack_tx_request(uint8_t **ppReadPackedMsg, uint8_t *end, void * return 1; } - -static uint8_t unpack_ue_release_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - uint8_t proceed = 1; - nfapi_ue_release_request_t *pNfapiMsg = (nfapi_ue_release_request_t*)msg; - - if(pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) == 0) - return 0; - - while (((uint8_t*)(*ppReadPackedMsg) < end) && proceed) - { - nfapi_tl_t generic_tl; - if(unpack_tl(ppReadPackedMsg, &generic_tl, end) == 0) - return 0; - - switch(generic_tl.tag) - { - case NFAPI_UE_RELEASE_BODY_TAG: - { - pNfapiMsg->ue_release_request_body.tl = generic_tl; - if( pull16(ppReadPackedMsg, &pNfapiMsg->ue_release_request_body.number_of_TLVs, end) == 0) - return 0; - - if(pNfapiMsg->ue_release_request_body.number_of_TLVs > NFAPI_RELEASE_MAX_RNTI) - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of relese rnti's exceed maxium (count:%d max:%d)\n", __FUNCTION__, pNfapiMsg->ue_release_request_body.number_of_TLVs, NFAPI_RELEASE_MAX_RNTI); - return 0; - } else { - uint8_t j; - uint16_t num = pNfapiMsg->ue_release_request_body.number_of_TLVs; - for(j = 0; j < num; ++j){ - if(pull16(ppReadPackedMsg, &pNfapiMsg->ue_release_request_body.ue_release_request_TLVs_list[j].rnti, end) == 0){ - return 0; - } - } - } - } - break; - default: - { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "unpack_ue_release_request FIXME : Invalid type %d \n", generic_tl.tag ); - } - break; - }; - } - - return 1; -} - + +static uint8_t unpack_ue_release_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + uint8_t proceed = 1; + nfapi_ue_release_request_t *pNfapiMsg = (nfapi_ue_release_request_t*)msg; + + if(pull16(ppReadPackedMsg, &pNfapiMsg->sfn_sf, end) == 0) + return 0; + + while (((uint8_t*)(*ppReadPackedMsg) < end) && proceed) + { + nfapi_tl_t generic_tl; + if(unpack_tl(ppReadPackedMsg, &generic_tl, end) == 0) + return 0; + + switch(generic_tl.tag) + { + case NFAPI_UE_RELEASE_BODY_TAG: + { + pNfapiMsg->ue_release_request_body.tl = generic_tl; + if( pull16(ppReadPackedMsg, &pNfapiMsg->ue_release_request_body.number_of_TLVs, end) == 0) + return 0; + + if(pNfapiMsg->ue_release_request_body.number_of_TLVs > NFAPI_RELEASE_MAX_RNTI) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s number of relese rnti's exceed maxium (count:%d max:%d)\n", __FUNCTION__, pNfapiMsg->ue_release_request_body.number_of_TLVs, NFAPI_RELEASE_MAX_RNTI); + return 0; + } else { + uint8_t j; + uint16_t num = pNfapiMsg->ue_release_request_body.number_of_TLVs; + for(j = 0; j < num; ++j){ + if(pull16(ppReadPackedMsg, &pNfapiMsg->ue_release_request_body.ue_release_request_TLVs_list[j].rnti, end) == 0){ + return 0; + } + } + } + } + break; + default: + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "unpack_ue_release_request FIXME : Invalid type %d \n", generic_tl.tag ); + } + break; + }; + } + + return 1; +} + static uint8_t unpack_harq_indication_tdd_harq_data_bundling(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end) { nfapi_harq_indication_tdd_harq_data_bundling_t* value = (nfapi_harq_indication_tdd_harq_data_bundling_t*)tlv; @@ -5825,18 +7365,18 @@ static uint8_t unpack_nrach_indication_rel13_value(void *tlv, uint8_t **ppReadPa pull8(ppReadPackedMsg, &value->nrach_ce_level, end)); } -static uint8_t unpack_ue_release_resp(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) -{ - nfapi_ue_release_response_t *pNfapiMsg = (nfapi_ue_release_response_t*)msg; - if(pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) == 0){ - return 0; - } - else{ - NFAPI_TRACE(NFAPI_TRACE_INFO, "ue_release_response:error_code = %d\n", pNfapiMsg->error_code); - } - return 1; -} - +static uint8_t unpack_ue_release_resp(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_ue_release_response_t *pNfapiMsg = (nfapi_ue_release_response_t*)msg; + if(pull32(ppReadPackedMsg, &pNfapiMsg->error_code, end) == 0){ + return 0; + } + else{ + NFAPI_TRACE(NFAPI_TRACE_INFO, "ue_release_response:error_code = %d\n", pNfapiMsg->error_code); + } + return 1; +} + static uint8_t unpack_nrach_indication_body_value(void* tlv, uint8_t **ppReadPackedMsg, uint8_t *end, nfapi_p7_codec_config_t* config) { nfapi_nrach_indication_body_t* value = (nfapi_nrach_indication_body_t*)tlv; @@ -5894,6 +7434,19 @@ static uint8_t unpack_nrach_indication(uint8_t **ppReadPackedMsg, uint8_t *end, unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); } +static uint8_t unpack_nr_dl_node_sync(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_dl_node_sync_t *pNfapiMsg = (nfapi_nr_dl_node_sync_t*)msg; + + unpack_p7_tlv_t unpack_fns[] = + { + }; + + return (pull32(ppReadPackedMsg, &pNfapiMsg->t1, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->delta_sfn_slot, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + static uint8_t unpack_dl_node_sync(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) { nfapi_dl_node_sync_t *pNfapiMsg = (nfapi_dl_node_sync_t*)msg; @@ -5907,6 +7460,22 @@ static uint8_t unpack_dl_node_sync(uint8_t **ppReadPackedMsg, uint8_t *end, void unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); } + +static uint8_t unpack_nr_ul_node_sync(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_ul_node_sync_t *pNfapiMsg = (nfapi_nr_ul_node_sync_t*)msg; + + unpack_p7_tlv_t unpack_fns[] = + { + }; + + return (pull32(ppReadPackedMsg, &pNfapiMsg->t1, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->t2, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->t3, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + + static uint8_t unpack_ul_node_sync(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) { nfapi_ul_node_sync_t *pNfapiMsg = (nfapi_ul_node_sync_t*)msg; @@ -5928,7 +7497,7 @@ static uint8_t unpack_timing_info(uint8_t **ppReadPackedMsg, uint8_t *end, void unpack_p7_tlv_t unpack_fns[] = { }; - + return (pull32(ppReadPackedMsg, &pNfapiMsg->last_sfn_sf, end) && pull32(ppReadPackedMsg, &pNfapiMsg->time_since_last_timing_info, end) && pull32(ppReadPackedMsg, &pNfapiMsg->dl_config_jitter, end) && @@ -5947,6 +7516,34 @@ static uint8_t unpack_timing_info(uint8_t **ppReadPackedMsg, uint8_t *end, void } +static uint8_t unpack_nr_timing_info(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p7_codec_config_t* config) +{ + nfapi_nr_timing_info_t *pNfapiMsg = (nfapi_nr_timing_info_t*)msg; + + unpack_p7_tlv_t unpack_fns[] = + { + }; + + return (pull32(ppReadPackedMsg, &pNfapiMsg->last_sfn, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->last_slot, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->time_since_last_timing_info, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->dl_tti_jitter, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->tx_data_request_jitter, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->ul_tti_jitter, end) && + pull32(ppReadPackedMsg, &pNfapiMsg->ul_dci_jitter, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->dl_tti_latest_delay, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->tx_data_request_latest_delay, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->ul_tti_latest_delay, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->ul_dci_latest_delay, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->dl_tti_earliest_arrival, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->tx_data_request_earliest_arrival, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->ul_tti_earliest_arrival, end) && + pulls32(ppReadPackedMsg, &pNfapiMsg->ul_dci_earliest_arrival, end) && + unpack_p7_tlv_list(unpack_fns, sizeof(unpack_fns)/sizeof(unpack_tlv_t), ppReadPackedMsg, end, config, &pNfapiMsg->vendor_extension)); +} + + + // unpack length check static int check_unpack_length(nfapi_message_id_e msgId, uint32_t unpackedBufLen) @@ -6049,17 +7646,17 @@ static int check_unpack_length(nfapi_message_id_e msgId, uint32_t unpackedBufLen if (unpackedBufLen >= sizeof(nfapi_timing_info_t)) retLen = sizeof(nfapi_timing_info_t); break; - - case NFAPI_UE_RELEASE_REQUEST: - if (unpackedBufLen >= sizeof(nfapi_ue_release_request_t)) - retLen = sizeof(nfapi_ue_release_request_t); - break; - - case NFAPI_UE_RELEASE_RESPONSE: - if (unpackedBufLen >= sizeof(nfapi_ue_release_response_t)) - retLen = sizeof(nfapi_ue_release_response_t); - break; - + + case NFAPI_UE_RELEASE_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_ue_release_request_t)) + retLen = sizeof(nfapi_ue_release_request_t); + break; + + case NFAPI_UE_RELEASE_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_ue_release_response_t)) + retLen = sizeof(nfapi_ue_release_response_t); + break; + default: NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unknown message ID %d\n", msgId); break; @@ -6068,6 +7665,126 @@ static int check_unpack_length(nfapi_message_id_e msgId, uint32_t unpackedBufLen return retLen; } +static int check_nr_unpack_length(nfapi_message_id_e msgId, uint32_t unpackedBufLen) +{ + int retLen = 0; + + switch (msgId) + { + case NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_nr_dl_tti_request_t)) + retLen = sizeof(nfapi_nr_dl_tti_request_t); + break; + + case NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_nr_ul_tti_request_t)) + retLen = sizeof(nfapi_nr_ul_tti_request_t); + break; + + case NFAPI_SUBFRAME_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_subframe_indication_t)) + retLen = sizeof(nfapi_subframe_indication_t); + break; + + case NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_nr_ul_dci_request_t)) + retLen = sizeof(nfapi_nr_ul_dci_request_t); + break; + + case NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_nr_tx_data_request_t)) + retLen = sizeof(nfapi_nr_tx_data_request_t); + break; + + case NFAPI_HARQ_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_harq_indication_t)) + retLen = sizeof(nfapi_harq_indication_t); + break; + + case NFAPI_CRC_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_crc_indication_t)) + retLen = sizeof(nfapi_crc_indication_t); + break; + + case NFAPI_RX_ULSCH_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_rx_indication_t)) + retLen = sizeof(nfapi_rx_indication_t); + break; + + case NFAPI_RACH_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_rach_indication_t)) + retLen = sizeof(nfapi_rach_indication_t); + break; + + case NFAPI_SRS_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_srs_indication_t)) + retLen = sizeof(nfapi_srs_indication_t); + break; + + case NFAPI_RX_SR_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_sr_indication_t)) + retLen = sizeof(nfapi_sr_indication_t); + break; + + case NFAPI_RX_CQI_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_cqi_indication_t)) + retLen = sizeof(nfapi_cqi_indication_t); + break; + + case NFAPI_LBT_DL_CONFIG_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_lbt_dl_config_request_t)) + retLen = sizeof(nfapi_lbt_dl_config_request_t); + break; + + case NFAPI_LBT_DL_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_lbt_dl_indication_t)) + retLen = sizeof(nfapi_lbt_dl_indication_t); + break; + + case NFAPI_NB_HARQ_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_nb_harq_indication_t)) + retLen = sizeof(nfapi_nb_harq_indication_t); + break; + + case NFAPI_NRACH_INDICATION: + if (unpackedBufLen >= sizeof(nfapi_nrach_indication_t)) + retLen = sizeof(nfapi_nrach_indication_t); + break; + + case NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC: + if (unpackedBufLen >= sizeof(nfapi_nr_dl_node_sync_t)) + retLen = sizeof(nfapi_nr_dl_node_sync_t); + break; + + case NFAPI_NR_PHY_MSG_TYPE_UL_NODE_SYNC: + if (unpackedBufLen >= sizeof(nfapi_nr_ul_node_sync_t)) + retLen = sizeof(nfapi_nr_ul_node_sync_t); + break; + + case NFAPI_TIMING_INFO: + if (unpackedBufLen >= sizeof(nfapi_timing_info_t)) + retLen = sizeof(nfapi_timing_info_t); + break; + + case NFAPI_UE_RELEASE_REQUEST: + if (unpackedBufLen >= sizeof(nfapi_ue_release_request_t)) + retLen = sizeof(nfapi_ue_release_request_t); + break; + + case NFAPI_UE_RELEASE_RESPONSE: + if (unpackedBufLen >= sizeof(nfapi_ue_release_response_t)) + retLen = sizeof(nfapi_ue_release_response_t); + break; + + default: + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unknown message ID %d\n", msgId); + break; + } + + return retLen; +} + + // Main unpack functions - public @@ -6119,7 +7836,15 @@ int nfapi_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUn NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack supplied message buffer is too small %d, %d\n", messageBufLen, unpackedBufLen); return -1; } - + /* + uint8_t *ptr = pMessageBuf; + printf("\n Read P7 message unpack: "); + while(ptr < end){ + printf(" %d ", *ptr); + ptr++; + } + printf("\n"); +*/ // clean the supplied buffer for - tag value blanking (void)memset(pUnpackedBuf, 0, unpackedBufLen); @@ -6151,7 +7876,7 @@ int nfapi_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUn // look for the specific message switch (pMessageHeader->message_id) - { + { case NFAPI_DL_CONFIG_REQUEST: if (check_unpack_length(NFAPI_DL_CONFIG_REQUEST, unpackedBufLen)) result = unpack_dl_config_request(&pReadPackedMessage, end, pMessageHeader, config); @@ -6165,28 +7890,26 @@ int nfapi_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUn else return -1; break; - - case NFAPI_HI_DCI0_REQUEST: - if (check_unpack_length(NFAPI_HI_DCI0_REQUEST, unpackedBufLen)) - result = unpack_hi_dci0_request(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - case NFAPI_TX_REQUEST: if (check_unpack_length(NFAPI_TX_REQUEST, unpackedBufLen)) result = unpack_tx_request(&pReadPackedMessage, end, pMessageHeader, config); else return -1; break; - - case NFAPI_UE_RELEASE_REQUEST: - if (check_unpack_length(NFAPI_UE_RELEASE_REQUEST, unpackedBufLen)) - result = unpack_ue_release_request(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - + case NFAPI_HI_DCI0_REQUEST: + if (check_unpack_length(NFAPI_HI_DCI0_REQUEST, unpackedBufLen)) + result = unpack_hi_dci0_request(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_UE_RELEASE_REQUEST: + if (check_unpack_length(NFAPI_UE_RELEASE_REQUEST, unpackedBufLen)) + result = unpack_ue_release_request(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + case NFAPI_HARQ_INDICATION: if (check_unpack_length(NFAPI_HARQ_INDICATION, unpackedBufLen)) result = unpack_harq_indication(&pReadPackedMessage, end, pMessageHeader, config); @@ -6284,14 +8007,14 @@ int nfapi_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUn else return -1; break; - - case NFAPI_UE_RELEASE_RESPONSE: - if (check_unpack_length(NFAPI_UE_RELEASE_RESPONSE, unpackedBufLen)) - result = unpack_ue_release_resp(&pReadPackedMessage, end, pMessageHeader, config); - else - return -1; - break; - + + case NFAPI_UE_RELEASE_RESPONSE: + if (check_unpack_length(NFAPI_UE_RELEASE_RESPONSE, unpackedBufLen)) + result = unpack_ue_release_resp(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + default: if(pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && @@ -6319,3 +8042,228 @@ int nfapi_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUn return 0; } +int nfapi_nr_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p7_codec_config_t* config) +{ + int result = 0; + nfapi_p7_message_header_t *pMessageHeader = (nfapi_p7_message_header_t*)pUnpackedBuf; + uint8_t *pReadPackedMessage = pMessageBuf; + uint8_t *end = pMessageBuf + messageBufLen; + + if (pMessageBuf == NULL || pUnpackedBuf == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack supplied pointers are null\n"); + return -1; + } + + if (messageBufLen < NFAPI_P7_HEADER_LENGTH || unpackedBufLen < sizeof(nfapi_p7_message_header_t)) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack supplied message buffer is too small %d, %d\n", messageBufLen, unpackedBufLen); + return -1; + } + /* + uint8_t *ptr = pMessageBuf; + printf("\n Read P7 message unpack: "); + while(ptr < end){ + printf(" %d ", *ptr); + ptr++; + } + printf("\n"); +*/ + // clean the supplied buffer for - tag value blanking + (void)memset(pUnpackedBuf, 0, unpackedBufLen); + + // process the header + if(!(pull16(&pReadPackedMessage, &pMessageHeader->phy_id, end) && + pull16(&pReadPackedMessage, &pMessageHeader->message_id, end) && + pull16(&pReadPackedMessage, &pMessageHeader->message_length, end) && + pull16(&pReadPackedMessage, &pMessageHeader->m_segment_sequence, end) && + pull32(&pReadPackedMessage, &pMessageHeader->checksum, end) && + pull32(&pReadPackedMessage, &pMessageHeader->transmit_timestamp, end))) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack header failed\n"); + return -1; + } + + if((uint8_t*)(pMessageBuf + pMessageHeader->message_length) > end) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack message length is greater than the message buffer \n"); + return -1; + } + + /* + if(check_unpack_length(pMessageHeader->message_id, unpackedBufLen) == 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 unpack unpack buffer is not large enough \n"); + return -1; + } + */ + + // look for the specific message + switch (pMessageHeader->message_id) + { + case NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST: + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST, unpackedBufLen)) + result = unpack_dl_tti_request(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST: + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST, unpackedBufLen)) + result = unpack_ul_tti_request(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + case NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST: + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST, unpackedBufLen)) + result = unpack_tx_data_request(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + case NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST: + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST, unpackedBufLen)) + result = unpack_ul_dci_request(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_UE_RELEASE_REQUEST: + if (check_nr_unpack_length(NFAPI_UE_RELEASE_REQUEST, unpackedBufLen)) + result = unpack_ue_release_request(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_HARQ_INDICATION: + if (check_nr_unpack_length(NFAPI_HARQ_INDICATION, unpackedBufLen)) + result = unpack_harq_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_CRC_INDICATION: + if (check_nr_unpack_length(NFAPI_CRC_INDICATION, unpackedBufLen)) + result = unpack_crc_indication(&pReadPackedMessage,end , pMessageHeader, config); + else + return -1; + break; + + case NFAPI_RX_ULSCH_INDICATION: + if (check_nr_unpack_length(NFAPI_RX_ULSCH_INDICATION, unpackedBufLen)) + result = unpack_rx_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_RACH_INDICATION: + if (check_nr_unpack_length(NFAPI_RACH_INDICATION, unpackedBufLen)) + result = unpack_rach_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_SRS_INDICATION: + if (check_nr_unpack_length(NFAPI_SRS_INDICATION, unpackedBufLen)) + result = unpack_srs_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_RX_SR_INDICATION: + if (check_nr_unpack_length(NFAPI_RX_SR_INDICATION, unpackedBufLen)) + result = unpack_sr_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_RX_CQI_INDICATION: + if (check_nr_unpack_length(NFAPI_RX_CQI_INDICATION, unpackedBufLen)) + result = unpack_cqi_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_LBT_DL_CONFIG_REQUEST: + if (check_nr_unpack_length(NFAPI_LBT_DL_CONFIG_REQUEST, unpackedBufLen)) + result = unpack_lbt_dl_config_request(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_LBT_DL_INDICATION: + if (check_nr_unpack_length(NFAPI_LBT_DL_INDICATION, unpackedBufLen)) + result = unpack_lbt_dl_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_NB_HARQ_INDICATION: + if (check_nr_unpack_length(NFAPI_NB_HARQ_INDICATION, unpackedBufLen)) + result = unpack_nb_harq_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_NRACH_INDICATION: + if (check_nr_unpack_length(NFAPI_NRACH_INDICATION, unpackedBufLen)) + result = unpack_nrach_indication(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC: + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC, unpackedBufLen)) + result = unpack_nr_dl_node_sync(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_NR_PHY_MSG_TYPE_UL_NODE_SYNC: + if (check_nr_unpack_length(NFAPI_NR_PHY_MSG_TYPE_UL_NODE_SYNC, unpackedBufLen)) + result = unpack_nr_ul_node_sync(&pReadPackedMessage, end , pMessageHeader, config); + else + return -1; + break; + + case NFAPI_TIMING_INFO: + if (check_nr_unpack_length(NFAPI_TIMING_INFO, unpackedBufLen)) + result = unpack_nr_timing_info(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + case NFAPI_UE_RELEASE_RESPONSE: + if (check_nr_unpack_length(NFAPI_UE_RELEASE_RESPONSE, unpackedBufLen)) + result = unpack_ue_release_resp(&pReadPackedMessage, end, pMessageHeader, config); + else + return -1; + break; + + default: + + if(pMessageHeader->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && + pMessageHeader->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) + { + if(config && config->unpack_p7_vendor_extension) + { + result = (config->unpack_p7_vendor_extension)(pMessageHeader, &pReadPackedMessage, end, config); + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve decoder provided\n", __FUNCTION__, pMessageHeader->message_id); + } + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown message ID %d\n", __FUNCTION__, pMessageHeader->message_id); + } + break; + } + + if(result == 0) + return -1; + else + return 0; +} + + diff --git a/nfapi/open-nFAPI/pnf/inc/pnf.h b/nfapi/open-nFAPI/pnf/inc/pnf.h index ab38c66e09..8c4e5cf9ab 100644 --- a/nfapi/open-nFAPI/pnf/inc/pnf.h +++ b/nfapi/open-nFAPI/pnf/inc/pnf.h @@ -38,7 +38,9 @@ typedef struct { int pnf_connect(pnf_t *pnf); int pnf_message_pump(pnf_t *pnf); +int pnf_nr_message_pump(pnf_t *pnf); +int pnf_nr_pack_and_send_p5_message(pnf_t* pnf, nfapi_p4_p5_message_header_t* msg, uint32_t msg_len); int pnf_pack_and_send_p5_message(pnf_t* pnf, nfapi_p4_p5_message_header_t* msg, uint32_t msg_len); int pnf_pack_and_send_p4_message(pnf_t* pnf, nfapi_p4_p5_message_header_t* msg, uint32_t msg_len); int pnf_send_message(pnf_t* pnf, uint8_t* msg, uint32_t msg_len, uint16_t stream_id); diff --git a/nfapi/open-nFAPI/pnf/inc/pnf_p7.h b/nfapi/open-nFAPI/pnf/inc/pnf_p7.h index 3f08d85e6b..1e2e2fa21d 100644 --- a/nfapi/open-nFAPI/pnf/inc/pnf_p7.h +++ b/nfapi/open-nFAPI/pnf/inc/pnf_p7.h @@ -29,15 +29,37 @@ typedef struct { uint16_t dl_conf_ontime; + uint16_t dl_tti_ontime; uint16_t dl_conf_late; + uint16_t dl_tti_late; uint16_t ul_conf_ontime; + uint16_t ul_tti_ontime; uint16_t ul_conf_late; + uint16_t ul_tti_late; uint16_t hi_dci0_ontime; uint16_t hi_dci0_late; + uint16_t ul_dci_ontime; + uint16_t ul_dci_late; uint16_t tx_ontime; uint16_t tx_late; + uint16_t tx_data_ontime; + uint16_t tx_data_late; } pnf_p7_stats_t; + +typedef struct { // TODO: replace with the stats + uint16_t dl_tti_ontime; + uint16_t dl_tti_late; + uint16_t ul_tti_ontime; + uint16_t ul_tti_late; + uint16_t ul_dci_ontime; + uint16_t ul_dci_late; + uint16_t tx_data_ontime; + uint16_t tx_data_late; +} pnf_p7_nr_stats_t; + + + typedef struct { uint8_t* buffer; uint16_t length; @@ -82,7 +104,7 @@ typedef struct { pthread_mutex_t pack_mutex; // should we allow the client to specifiy nfapi_pnf_p7_subframe_buffer_t subframe_buffer[30/*NFAPI_MAX_TIMING_WINDOW_SIZE*/]; - + nfapi_pnf_p7_slot_buffer_t slot_buffer[30/*NFAPI_MAX_TIMING_WINDOW_SIZE*/]; uint32_t sequence_number; uint16_t max_num_segments; @@ -94,6 +116,12 @@ typedef struct { uint16_t sfn_sf; uint32_t sf_start_time_hr; int32_t sfn_sf_shift; + + uint16_t sfn; + uint16_t slot; + uint16_t sfn_slot; + uint32_t slot_start_time_hr; + int32_t slot_shift; uint8_t timing_info_period_counter; uint8_t timing_info_aperiodic_send; // 0:false 1:true @@ -104,18 +132,26 @@ typedef struct { uint32_t ul_config_jitter; uint32_t hi_dci0_jitter; uint32_t tx_jitter; + + //P7 NR + uint32_t dl_tti_jitter; + uint32_t ul_tti_jitter; + uint32_t ul_dci_jitter; + uint32_t tx_data_jitter; uint32_t tick; pnf_p7_stats_t stats; + pnf_p7_nr_stats_t nr_stats; } pnf_p7_t; int pnf_p7_message_pump(pnf_p7_t* pnf_p7); - +int pnf_nr_p7_message_pump(pnf_p7_t* pnf_p7); int pnf_p7_pack_and_send_p7_message(pnf_p7_t* pnf_p7, nfapi_p7_message_header_t* msg, uint32_t msg_len); int pnf_p7_send_message(pnf_p7_t* pnf_p7, uint8_t* msg, uint32_t msg_len); +int pnf_p7_slot_ind(pnf_p7_t* config, uint16_t phy_id, uint16_t sfn, uint16_t slot); int pnf_p7_subframe_ind(pnf_p7_t* config, uint16_t phy_id, uint16_t sfn_sf); pnf_p7_rx_message_t* pnf_p7_rx_reassembly_queue_add_segment(pnf_p7_t* pnf_p7, pnf_p7_rx_reassembly_queue_t* queue, uint32_t rx_hr_time, uint16_t sequence_number, uint16_t segment_number, uint8_t m, uint8_t* data, uint16_t data_len); diff --git a/nfapi/open-nFAPI/pnf/public_inc/nfapi_pnf_interface.h b/nfapi/open-nFAPI/pnf/public_inc/nfapi_pnf_interface.h index d169177d6b..fc9cd66077 100644 --- a/nfapi/open-nFAPI/pnf/public_inc/nfapi_pnf_interface.h +++ b/nfapi/open-nFAPI/pnf/public_inc/nfapi_pnf_interface.h @@ -25,8 +25,14 @@ extern "C" { #include "nfapi_interface.h" #include "debug.h" #include +#include "nfapi_nr_interface.h" +#include "nfapi_nr_interface_scf.h" #include +#include "openair1/PHY/defs_gNB.h" + + + /*! This enum is used to describe the states of the pnf */ @@ -121,6 +127,7 @@ typedef struct nfapi_pnf_config * The client is expected to send the PNF_PARAM.response after receiving the * PNF_PARAM.request. This can be done in the call back. */ + int (*pnf_nr_param_req)(nfapi_pnf_config_t* config, nfapi_nr_pnf_param_request_t* req); int (*pnf_param_req)(nfapi_pnf_config_t* config, nfapi_pnf_param_request_t* req); /*! A callback for the PNF_CONFIG.request @@ -133,7 +140,8 @@ typedef struct nfapi_pnf_config * PNF_CONFIG.request. This can be done in the call back. */ int (*pnf_config_req)(nfapi_pnf_config_t* config, nfapi_pnf_config_request_t* req); - + int (*pnf_nr_config_req)(nfapi_pnf_config_t* config, nfapi_nr_pnf_config_request_t* req); + /*! A callback for the PNF_START.request * \param config A pointer to the pnf configuration * \param req A data structure for the decoded PNF_CONFIG.request. This will have @@ -144,7 +152,8 @@ typedef struct nfapi_pnf_config * PNF_START.request. This can be done in the call back. */ int (*pnf_start_req)(nfapi_pnf_config_t* config, nfapi_pnf_start_request_t* req); - + int (*pnf_nr_start_req)(nfapi_pnf_config_t* config, nfapi_nr_pnf_start_request_t* req); + /*! A callback for the PNF_STOP.request * \param config A pointer to the pnf configuration * \param req A data structure for the decoded PNF_STOP.request. This will have @@ -167,7 +176,8 @@ typedef struct nfapi_pnf_config * PARAM.request. This can be done in the call back. */ int (*param_req)(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi_param_request_t* req); - + int (*nr_param_req)(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi_nr_param_request_scf_t* req); + /*! A callback for the CONFIG.request * \param config A pointer to the pnf configuration * \param phy A pointer to the pnf phy configuration @@ -179,6 +189,7 @@ typedef struct nfapi_pnf_config * CONFIG.request. This can be done in the call back. */ int (*config_req)(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi_config_request_t* req); + int (*nr_config_req)(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi_nr_config_request_scf_t* req); /*! A callback for the START.request * \param config A pointer to the pnf configuration @@ -190,8 +201,8 @@ typedef struct nfapi_pnf_config * The client is expected to send the START.response after the client has received the * first subframe indication from FAPI. */ - int (*start_req)(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi_start_request_t* req); - + int (*start_req)(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi_start_request_t* req); + int (*nr_start_req)(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi_nr_start_request_scf_t* req); /*! A callback for the STOP.request * \param config A pointer to the pnf configuration * \param phy A pointer to the pnf phy configuration @@ -203,7 +214,8 @@ typedef struct nfapi_pnf_config * STOP.request. This can be done in the call back. */ int (*stop_req)(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi_stop_request_t* req); - + int (*nr_stop_req)(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi_nr_stop_request_t* req); + /*! A callback for the MEASUREMENT.request * \param config A pointer to the pnf configuration * \param phy A pointer to the pnf phy configuration @@ -355,6 +367,7 @@ int nfapi_pnf_config_destroy(nfapi_pnf_config_t* config); * \endcode */ int nfapi_pnf_start(nfapi_pnf_config_t* config); +int nfapi_nr_pnf_start(nfapi_pnf_config_t* config); /*! Stop the PNF library. * \param config A pointer to the pnf configuration @@ -371,6 +384,8 @@ int nfapi_pnf_stop(nfapi_pnf_config_t* config); * */ int nfapi_pnf_pnf_param_resp(nfapi_pnf_config_t* config, nfapi_pnf_param_response_t* resp); +int nfapi_nr_pnf_pnf_param_resp(nfapi_pnf_config_t* config, nfapi_nr_pnf_param_response_t* resp); + /*! Send the PNF_CONFIG.response * \param config A pointer to a pnf configuraiton @@ -379,6 +394,7 @@ int nfapi_pnf_pnf_param_resp(nfapi_pnf_config_t* config, nfapi_pnf_param_respons * */ int nfapi_pnf_pnf_config_resp(nfapi_pnf_config_t* config, nfapi_pnf_config_response_t* resp); +int nfapi_nr_pnf_pnf_config_resp(nfapi_pnf_config_t* config, nfapi_nr_pnf_config_response_t* resp); /*! Send the PNF_START.response * \param config A pointer to a pnf configuraiton @@ -387,7 +403,7 @@ int nfapi_pnf_pnf_config_resp(nfapi_pnf_config_t* config, nfapi_pnf_config_respo * */ int nfapi_pnf_pnf_start_resp(nfapi_pnf_config_t* config, nfapi_pnf_start_response_t* resp); - +int nfapi_nr_pnf_pnf_start_resp(nfapi_pnf_config_t* config, nfapi_nr_pnf_start_response_t* resp); /*! Send the PNF_STOP.response * \param config A pointer to a pnf configuraiton * \param resp A pointer to the message structure @@ -403,6 +419,7 @@ int nfapi_pnf_pnf_stop_resp(nfapi_pnf_config_t* config, nfapi_pnf_stop_response_ * */ int nfapi_pnf_param_resp(nfapi_pnf_config_t* config, nfapi_param_response_t* resp); +int nfapi_nr_pnf_param_resp(nfapi_pnf_config_t* config, nfapi_nr_param_response_scf_t* resp); /*! Send the CONFIG.response * \param config A pointer to a pnf configuraiton @@ -411,7 +428,7 @@ int nfapi_pnf_param_resp(nfapi_pnf_config_t* config, nfapi_param_response_t* res * */ int nfapi_pnf_config_resp(nfapi_pnf_config_t* config, nfapi_config_response_t* resp); - +int nfapi_nr_pnf_config_resp(nfapi_pnf_config_t* config, nfapi_nr_config_response_scf_t* resp); /*! Send the START.response * \param config A pointer to a pnf configuraiton * \param resp A pointer to the message structure @@ -419,6 +436,7 @@ int nfapi_pnf_config_resp(nfapi_pnf_config_t* config, nfapi_config_response_t* r * */ int nfapi_pnf_start_resp(nfapi_pnf_config_t* config, nfapi_start_response_t* resp); +int nfapi_nr_pnf_start_resp(nfapi_pnf_config_t* config, nfapi_nr_start_response_scf_t* resp); /*! Send the STOP.response * \param config A pointer to a pnf configuraiton @@ -550,6 +568,22 @@ typedef struct nfapi_ue_release_request_t* ue_release_req; } nfapi_pnf_p7_subframe_buffer_t; +typedef struct +{ + //uint16_t sfn_slot + int16_t sfn; + int16_t slot; + //TODO: Change P7 structs to NR + nfapi_nr_dl_tti_request_t* dl_tti_req;//nfapi_dl_config_request_t* dl_config_req; + nfapi_nr_ul_tti_request_t* ul_tti_req;//nfapi_ul_config_request_t* ul_config_req; + nfapi_nr_ul_dci_request_t* ul_dci_req;//nfapi_hi_dci0_request_t* hi_dci0_req; + nfapi_nr_tx_data_request_t* tx_data_req;//nfapi_tx_request_t* tx_req; + + //TODO: check these two later + //nfapi_lbt_dl_config_request_t* lbt_dl_config_req; + //nfapi_ue_release_request_t* ue_release_req; +} nfapi_pnf_p7_slot_buffer_t; + typedef struct nfapi_pnf_p7_config nfapi_pnf_p7_config_t; /*! The nfapi PNF PHY P7 configuration information created using the nfapi_pnf_p7_create function @@ -602,6 +636,8 @@ typedef struct nfapi_pnf_p7_config /*! The dummy subframe buffer structure that should be used in case there * are no 'valid' subframe messages */ nfapi_pnf_p7_subframe_buffer_t dummy_subframe; + + nfapi_pnf_p7_slot_buffer_t dummy_slot; // defining a slot equivalent for now /*! Configuration options for the p7 pack unpack functions*/ nfapi_p7_codec_config_t codec_config; @@ -611,6 +647,7 @@ typedef struct nfapi_pnf_p7_config // tdb : if these should be public uint16_t subframe_buffer_size; + uint16_t slot_buffer_size; uint8_t timing_info_mode_periodic; // 0:false 1:true uint8_t timing_info_mode_aperiodic; // 0:false 1:true uint8_t timing_info_period; // 1..225 in subframes @@ -620,6 +657,7 @@ typedef struct nfapi_pnf_p7_config * \param req A pointer to the dl config request message structure * \return not currently used */ + int (*dl_tti_req_fn)(gNB_L1_rxtx_proc_t *proc,nfapi_pnf_p7_config_t* config, nfapi_nr_dl_tti_request_t* req); int (*dl_config_req)(L1_rxtx_proc_t *proc,nfapi_pnf_p7_config_t* config, nfapi_dl_config_request_t* req); /*! A callback for the UL_CONFIG.request @@ -627,6 +665,7 @@ typedef struct nfapi_pnf_p7_config * \param req A pointer to the ul config request message structure * \return not currently used */ + int (*ul_tti_req_fn)(gNB_L1_rxtx_proc_t *proc,nfapi_pnf_p7_config_t* config, nfapi_nr_ul_tti_request_t* req); int (*ul_config_req)(L1_rxtx_proc_t *proc,nfapi_pnf_p7_config_t* config, nfapi_ul_config_request_t* req); /*! A callback for the HI_DCI0.request @@ -634,8 +673,9 @@ typedef struct nfapi_pnf_p7_config * \param req A pointer to the hi dci0 request message structure * \return not currently used */ + int (*ul_dci_req_fn)(gNB_L1_rxtx_proc_t *proc,nfapi_pnf_p7_config_t* config, nfapi_nr_ul_dci_request_t* req); int (*hi_dci0_req)(L1_rxtx_proc_t *proc,nfapi_pnf_p7_config_t* config, nfapi_hi_dci0_request_t* req); - + /*! A callback for the TX_REQ.request * \param config A poiner to the PNF P7 config * \param req A pointer to the tx request message structure @@ -645,6 +685,7 @@ typedef struct nfapi_pnf_p7_config * will 'keep' the pointers until they are transmitted the callee should set the pointers in the req to 0 * and then use the p7 codec config free function to release the pdu's when appropriate. */ + int (*tx_data_req_fn)(nfapi_pnf_p7_config_t* config, nfapi_nr_tx_data_request_t* req); int (*tx_req)(nfapi_pnf_p7_config_t* config, nfapi_tx_request_t* req); /*! A callback for the LBT_DL_CONFIG.request @@ -708,6 +749,7 @@ int nfapi_pnf_p7_config_destroy(nfapi_pnf_p7_config_t* config); * This function will not return until nfapi_pnf_p7_stop is called. */ int nfapi_pnf_p7_start(nfapi_pnf_p7_config_t* config); +int nfapi_nr_pnf_p7_start(nfapi_pnf_p7_config_t* config); /*! Stop the PNF P7 library. * \param config A pointer to a PNF P7 config @@ -717,6 +759,21 @@ int nfapi_pnf_p7_start(nfapi_pnf_p7_config_t* config); */ int nfapi_pnf_p7_stop(nfapi_pnf_p7_config_t* config); +/*! NR Slot indication + * message copied from nfapi_pnf_p7_subframe_ind + * \param config A pointer to a PNF P7 config + * \param phy_id The phy_id for the phy instance + * \param sfn_sf The SFN and SF in the format of FAPI + * \return 0 means success, -1 means failure + * + * The client should call the subframe indication every 1ms. The PNF will + * respond by invoking the pnf p7 subframe callbacks with the messages from the subframe buffer + * + * If messages are not in the subframe buffer, they dummy subframe messages will be sent + */ +int nfapi_pnf_p7_slot_ind(nfapi_pnf_p7_config_t* config, uint16_t phy_id, uint16_t sfn, uint16_t slot); + + /*! Subframe indication * \param config A pointer to a PNF P7 config * \param phy_id The phy_id for the phy instance diff --git a/nfapi/open-nFAPI/pnf/src/pnf.c b/nfapi/open-nFAPI/pnf/src/pnf.c index eec9ff80c3..fdafd93279 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf.c +++ b/nfapi/open-nFAPI/pnf/src/pnf.c @@ -26,9 +26,29 @@ #include #include #include - +#include "nfapi_nr_interface.h" +#include "nfapi_nr_interface_scf.h" #include "pnf.h" +# if 1 // for hard-code (remove later) +#include "COMMON/platform_types.h" +#include "COMMON/platform_constants.h" +#include "common/ran_context.h" + +#include "common/utils/LOG/log.h" +#include "common/utils/LOG/vcd_signal_dumper.h" + +#include "NR_BCCH-BCH-Message.h" +#include "NR_ServingCellConfigCommon.h" + +#include "LAYER2/NR_MAC_gNB/mac_proto.h" +#include "SCHED_NR/phy_frame_config_nr.h" + +#include "NR_MIB.h" +#include "openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h" + +#endif + #define MAX_SCTP_STREAMS 16 void nfapi_pnf_phy_config_delete_all(nfapi_pnf_config_t* config) @@ -63,6 +83,50 @@ nfapi_pnf_phy_config_t* nfapi_pnf_phy_config_find(nfapi_pnf_config_t* config, ui return 0; } +void pnf_nr_handle_pnf_param_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen) +{ + // ensure it's valid + if (pRecvMsg == NULL || pnf == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + } + else + { + nfapi_nr_pnf_param_request_t req; + + NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF_PARAM.request received\n"); + + // unpack the message + if (nfapi_nr_p5_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(nfapi_nr_pnf_param_request_t), &pnf->_public.codec_config) >= 0) + { + if(pnf->_public.state == NFAPI_PNF_IDLE) + { + if(pnf->_public.pnf_nr_param_req) + { + (pnf->_public.pnf_nr_param_req)(&pnf->_public, &req); + } + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: PNF not in IDLE state\n", __FUNCTION__); + + nfapi_nr_pnf_param_response_t resp; + memset(&resp, 0, sizeof(resp)); + resp.header.message_id = NFAPI_NR_PHY_MSG_TYPE_PNF_PARAM_RESPONSE; + resp.error_code = NFAPI_MSG_INVALID_STATE; + nfapi_nr_pnf_pnf_param_resp(&pnf->_public, &resp); + } + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__); + } + + if(req.vendor_extension) + pnf->_public.codec_config.deallocate(req.vendor_extension); + } +} + void pnf_handle_pnf_param_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen) { // ensure it's valid @@ -173,6 +237,72 @@ void pnf_handle_pnf_config_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen) } } +void pnf_nr_handle_pnf_config_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen) +{ + + + // ensure it's valid + if (pRecvMsg == NULL || pnf == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + } + else + { + nfapi_nr_pnf_config_request_t req; + + NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF_CONFIG.request received\n"); + + // unpack the message + if (nfapi_nr_p5_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(req), &pnf->_public.codec_config) >= 0) + { + // ensure correct state + if(pnf->_public.state != NFAPI_PNF_RUNNING) + { + // delete the phy records + nfapi_pnf_phy_config_delete_all(&pnf->_public); + + // create the phy records + if (req.pnf_phy_rf_config.tl.tag == NFAPI_PNF_PHY_RF_TAG) + { + int i = 0; + for(i = 0; i < req.pnf_phy_rf_config.number_phy_rf_config_info; ++i) + { + nfapi_pnf_phy_config_t* phy = (nfapi_pnf_phy_config_t*)malloc(sizeof(nfapi_pnf_phy_config_t)); + memset(phy, 0, sizeof(nfapi_pnf_phy_config_t)); + + phy->state = NFAPI_PNF_PHY_IDLE; + phy->phy_id = req.pnf_phy_rf_config.phy_rf_config[i].phy_id; + + nfapi_pnf_phy_config_add(&(pnf->_public), phy); + } + } + + if(pnf->_public.pnf_nr_config_req) + { + (pnf->_public.pnf_nr_config_req)(&(pnf->_public), &req); + } + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: PNF not in correct state: %d\n", __FUNCTION__, pnf->_public.state); + + nfapi_nr_pnf_config_response_t resp; + memset(&resp, 0, sizeof(resp)); + resp.header.message_id = NFAPI_PNF_CONFIG_RESPONSE; + resp.error_code = NFAPI_MSG_INVALID_STATE; + nfapi_nr_pnf_pnf_config_resp(&(pnf->_public), &resp); + } + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__); + } + + if(req.vendor_extension) + pnf->_public.codec_config.deallocate(req.vendor_extension); + } +} + void pnf_handle_pnf_start_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen) { // ensure it's valid @@ -215,6 +345,48 @@ void pnf_handle_pnf_start_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen) } } +void pnf_nr_handle_pnf_start_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen) +{ + // ensure it's valid + if (pRecvMsg == NULL || pnf == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + } + else + { + nfapi_nr_pnf_start_request_t req; + + NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF_START.request Received\n"); + + // unpack the message + if (nfapi_nr_p5_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(req), &pnf->_public.codec_config) >= 0) + { + if(pnf->_public.state == NFAPI_PNF_CONFIGURED) + { + if(pnf->_public.pnf_nr_start_req) + { + (pnf->_public.pnf_nr_start_req)(&(pnf->_public), &req); + } + } + else + { + nfapi_nr_pnf_start_response_t resp; + memset(&resp, 0, sizeof(resp)); + resp.header.message_id = NFAPI_PNF_START_RESPONSE; + resp.error_code = NFAPI_MSG_INVALID_STATE; + nfapi_nr_pnf_pnf_start_resp(&(pnf->_public), &resp); + } + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__); + } + + if(req.vendor_extension) + pnf->_public.codec_config.deallocate(req.vendor_extension); + } +} + void pnf_handle_pnf_stop_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen) { // ensure it's valid @@ -330,6 +502,78 @@ void pnf_handle_param_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen) } } +void pnf_nr_handle_param_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen) +{ + // ensure it's valid + if (pRecvMsg == NULL || pnf == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + } + else + { + nfapi_nr_param_request_scf_t req; + + nfapi_pnf_config_t* config = &(pnf->_public); + + NFAPI_TRACE(NFAPI_TRACE_INFO, "PARAM.request received\n"); + + // unpack the message + if (nfapi_nr_p5_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(req), &config->codec_config) >= 0) + { + if(config->state == NFAPI_PNF_RUNNING) + { + nfapi_pnf_phy_config_t* phy = nfapi_pnf_phy_config_find(config, req.header.phy_id); + if(phy) + { + if(phy->state == NFAPI_PNF_PHY_IDLE) + { + if(config->nr_param_req) + { + (config->nr_param_req)(config, phy, &req); + } + } + else + { + nfapi_nr_param_response_scf_t resp; + memset(&resp, 0, sizeof(resp)); + resp.header.message_id = NFAPI_NR_PHY_MSG_TYPE_PARAM_RESPONSE; + resp.header.phy_id = req.header.phy_id; + resp.error_code = NFAPI_MSG_INVALID_STATE; + nfapi_nr_pnf_param_resp(config, &resp); + } + } + else + { + nfapi_nr_param_response_scf_t resp; + memset(&resp, 0, sizeof(resp)); + resp.header.message_id = NFAPI_NR_PHY_MSG_TYPE_PARAM_RESPONSE; + resp.header.phy_id = req.header.phy_id; + resp.error_code = NFAPI_MSG_INVALID_CONFIG; + nfapi_nr_pnf_param_resp(config, &resp); + } + + } + else + { + nfapi_nr_param_response_scf_t resp; + memset(&resp, 0, sizeof(resp)); + resp.header.message_id = NFAPI_NR_PHY_MSG_TYPE_PARAM_RESPONSE; + resp.header.phy_id = req.header.phy_id; + resp.error_code = NFAPI_MSG_INVALID_STATE; + nfapi_nr_pnf_param_resp(config, &resp); + } + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__); + } + + if(req.vendor_extension) + pnf->_public.codec_config.deallocate(req.vendor_extension); + + } +} + void pnf_handle_config_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen) { @@ -401,6 +645,85 @@ void pnf_handle_config_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen) } } + +void pnf_nr_handle_config_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen) +{ + + // ensure it's valid + if (pRecvMsg == NULL || pnf == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + } + else + { + nfapi_nr_config_request_scf_t req; + + NFAPI_TRACE(NFAPI_TRACE_INFO, "CONFIG.request received\n"); + + nfapi_pnf_config_t* config = &(pnf->_public); + + // unpack the message + if (nfapi_nr_p5_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(req), &config->codec_config) >= 0) + { + if(config->state == NFAPI_PNF_RUNNING) + { + nfapi_pnf_phy_config_t* phy = nfapi_pnf_phy_config_find(config, req.header.phy_id); + +#if 0 // emulate set_config TLV reception (hard-code) + int tdd_return = set_tdd_config_nr(&req, 1, 7, 6, 2, 4); +#endif + + if(phy) + { + if(phy->state != NFAPI_PNF_PHY_RUNNING) + { + if(config->nr_config_req) + { + (config->nr_config_req)(config, phy, &req); + + + } + } + else + { + nfapi_nr_config_response_scf_t resp; + memset(&resp, 0, sizeof(resp)); + resp.header.message_id = NFAPI_CONFIG_RESPONSE; + resp.header.phy_id = req.header.phy_id; + resp.error_code = NFAPI_MSG_INVALID_STATE; + nfapi_nr_pnf_config_resp(config, &resp); + } + } + else + { + nfapi_nr_config_response_scf_t resp; + memset(&resp, 0, sizeof(resp)); + resp.header.message_id = NFAPI_CONFIG_RESPONSE; + resp.header.phy_id = req.header.phy_id; + resp.error_code = NFAPI_MSG_INVALID_CONFIG; + nfapi_nr_pnf_config_resp(config, &resp); + } + } + else + { + nfapi_nr_config_response_scf_t resp; + memset(&resp, 0, sizeof(resp)); + resp.header.message_id = NFAPI_CONFIG_RESPONSE; + resp.header.phy_id = req.header.phy_id; + resp.error_code = NFAPI_MSG_INVALID_STATE; + nfapi_nr_pnf_config_resp(config, &resp); + } + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__); + } + + if(req.vendor_extension) + pnf->_public.codec_config.deallocate(req.vendor_extension); + } +} + void pnf_handle_start_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen) { // ensure it's valid @@ -472,6 +795,77 @@ void pnf_handle_start_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen) } } +void pnf_nr_handle_start_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen) +{ + // ensure it's valid + if (pRecvMsg == NULL || pnf == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + } + else + { + nfapi_nr_start_request_scf_t req; + + nfapi_pnf_config_t* config = &(pnf->_public); + + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() START.request received state:%d\n", __FUNCTION__, config->state); + + // unpack the message + if (nfapi_nr_p5_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(req), &config->codec_config) >= 0) + { + if(config->state == NFAPI_PNF_RUNNING) + { + nfapi_pnf_phy_config_t* phy = nfapi_pnf_phy_config_find(config, req.header.phy_id); + if(phy) + { + if(phy->state != NFAPI_PNF_PHY_RUNNING) + { + if(config->nr_start_req) + { + (config->nr_start_req)(config, phy, &req); + } + } + else + { + nfapi_nr_start_response_scf_t resp; + memset(&resp, 0, sizeof(resp)); + resp.header.message_id = NFAPI_NR_PHY_MSG_TYPE_START_RESPONSE; + resp.header.phy_id = req.header.phy_id; + resp.error_code = NFAPI_MSG_INVALID_STATE; + nfapi_nr_pnf_start_resp(config, &resp); + } + } + else + { + nfapi_nr_start_response_scf_t resp; + memset(&resp, 0, sizeof(resp)); + resp.header.message_id = NFAPI_NR_PHY_MSG_TYPE_START_RESPONSE; + resp.header.phy_id = req.header.phy_id; + resp.error_code = NFAPI_MSG_INVALID_CONFIG; + nfapi_nr_pnf_start_resp(config, &resp); + } + } + else + { + nfapi_nr_start_response_scf_t resp; + memset(&resp, 0, sizeof(resp)); + resp.header.message_id = NFAPI_NR_PHY_MSG_TYPE_START_RESPONSE; + resp.header.phy_id = req.header.phy_id; + resp.error_code = NFAPI_MSG_INVALID_STATE; + nfapi_nr_pnf_start_resp(config, &resp); + } + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__); + } + + if(req.vendor_extension) + pnf->_public.codec_config.deallocate(req.vendor_extension); + + } +} + void pnf_handle_stop_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen) { // ensure it's valid @@ -543,6 +937,77 @@ void pnf_handle_stop_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen) } } +void pnf_nr_handle_stop_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen) +{ + // ensure it's valid + if (pRecvMsg == NULL || pnf == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + } + else + { + nfapi_nr_stop_request_t req; + + NFAPI_TRACE(NFAPI_TRACE_INFO, "STOP.request received\n"); + + nfapi_pnf_config_t* config = &(pnf->_public); + + // unpack the message + if (nfapi_nr_p5_message_unpack(pRecvMsg, recvMsgLen, &req, sizeof(req), &config->codec_config) >= 0) + { + if(config->state == NFAPI_PNF_RUNNING) + { + nfapi_pnf_phy_config_t* phy = nfapi_pnf_phy_config_find(config, req.header.phy_id); + if(phy) + { + if(phy->state != NFAPI_PNF_PHY_RUNNING) + { + if(config->nr_stop_req) + { + (config->nr_stop_req)(config, phy, &req); + } + } + else + { + nfapi_stop_response_t resp; + memset(&resp, 0, sizeof(resp)); + resp.header.message_id = NFAPI_NR_PHY_MSG_TYPE_STOP_RESPONSE; + resp.header.phy_id = req.header.phy_id; + resp.error_code = NFAPI_MSG_INVALID_STATE; + nfapi_pnf_stop_resp(config, &resp); + } + } + else + { + nfapi_stop_response_t resp; + memset(&resp, 0, sizeof(resp)); + resp.header.message_id = NFAPI_NR_PHY_MSG_TYPE_STOP_RESPONSE; + resp.header.phy_id = req.header.phy_id; + resp.error_code = NFAPI_MSG_INVALID_CONFIG; + nfapi_pnf_stop_resp(config, &resp); + } + } + else + { + nfapi_stop_response_t resp; + memset(&resp, 0, sizeof(resp)); + resp.header.message_id = NFAPI_NR_PHY_MSG_TYPE_STOP_RESPONSE; + resp.header.phy_id = req.header.phy_id; + resp.error_code = NFAPI_MSG_INVALID_STATE; + nfapi_pnf_stop_resp(config, &resp); + } + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__); + } + + if(req.vendor_extension) + pnf->_public.codec_config.deallocate(req.vendor_extension); + + } +} + void pnf_handle_measurement_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen) { // ensure it's valid @@ -1071,7 +1536,101 @@ void pnf_handle_vendor_extension(void* pRecvMsg, int recvMsgLen, pnf_t* pnf, uin } } +void pnf_nr_handle_p5_message(pnf_t* pnf, void *pRecvMsg, int recvMsgLen) +{ + nfapi_p4_p5_message_header_t messageHeader; + // validate the input params + if(pRecvMsg == NULL || recvMsgLen < NFAPI_HEADER_LENGTH) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__); + return; + } + + // unpack the message header + if (nfapi_p5_message_header_unpack(pRecvMsg, recvMsgLen, &messageHeader, sizeof(nfapi_p4_p5_message_header_t), &pnf->_public.codec_config) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unpack message header failed, ignoring\n"); + return; + } + + switch (messageHeader.message_id) + { + case NFAPI_NR_PHY_MSG_TYPE_PNF_PARAM_REQUEST: + pnf_nr_handle_pnf_param_request(pnf, pRecvMsg, recvMsgLen); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PNF_CONFIG_REQUEST: + pnf_nr_handle_pnf_config_request(pnf, pRecvMsg, recvMsgLen); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PNF_START_REQUEST: + pnf_nr_handle_pnf_start_request(pnf, pRecvMsg, recvMsgLen); + break; + + case NFAPI_PNF_STOP_REQUEST: + pnf_handle_pnf_stop_request(pnf, pRecvMsg, recvMsgLen); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PARAM_REQUEST: + pnf_nr_handle_param_request(pnf, pRecvMsg, recvMsgLen); + break; + + case NFAPI_NR_PHY_MSG_TYPE_CONFIG_REQUEST: + pnf_nr_handle_config_request(pnf, pRecvMsg, recvMsgLen); + break; + + case NFAPI_NR_PHY_MSG_TYPE_START_REQUEST: + pnf_nr_handle_start_request(pnf, pRecvMsg, recvMsgLen); + break; + + case NFAPI_NR_PHY_MSG_TYPE_STOP_REQUEST: + pnf_nr_handle_stop_request(pnf, pRecvMsg, recvMsgLen); + break; + + case NFAPI_MEASUREMENT_REQUEST: + pnf_handle_measurement_request(pnf, pRecvMsg, recvMsgLen); + break; + + case NFAPI_RSSI_REQUEST: + pnf_handle_rssi_request(pnf, pRecvMsg, recvMsgLen); + break; + + case NFAPI_CELL_SEARCH_REQUEST: + pnf_handle_cell_search_request(pnf, pRecvMsg, recvMsgLen); + break; + + case NFAPI_BROADCAST_DETECT_REQUEST: + pnf_handle_broadcast_detect_request(pnf, pRecvMsg, recvMsgLen); + break; + + case NFAPI_SYSTEM_INFORMATION_SCHEDULE_REQUEST: + pnf_handle_system_information_schedule_request(pnf, pRecvMsg, recvMsgLen); + break; + + case NFAPI_SYSTEM_INFORMATION_REQUEST: + pnf_handle_system_information_request(pnf, pRecvMsg, recvMsgLen); + break; + + case NFAPI_NMM_STOP_REQUEST: + pnf_handle_nmm_stop_request(pnf, pRecvMsg, recvMsgLen); + break; + + default: + { + if(messageHeader.message_id >= NFAPI_VENDOR_EXT_MSG_MIN && + messageHeader.message_id <= NFAPI_VENDOR_EXT_MSG_MAX) + { + pnf_handle_vendor_extension(pRecvMsg, recvMsgLen, pnf, messageHeader.message_id); + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s P5 Unknown message ID %d\n", __FUNCTION__, messageHeader.message_id); + } + } + break; + } +} void pnf_handle_p5_message(pnf_t* pnf, void *pRecvMsg, int recvMsgLen) { @@ -1169,6 +1728,24 @@ void pnf_handle_p5_message(pnf_t* pnf, void *pRecvMsg, int recvMsgLen) } } + +int pnf_nr_pack_and_send_p5_message(pnf_t* pnf, nfapi_p4_p5_message_header_t* msg, uint32_t msg_len) +{ + int packed_len = nfapi_nr_p5_message_pack(msg, msg_len, + pnf->tx_message_buffer, + sizeof(pnf->tx_message_buffer), + &pnf->_public.codec_config); + + if (packed_len < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "nfapi_p5_message_pack failed (%d)\n", packed_len); + return -1; + } + + return pnf_send_message(pnf, pnf->tx_message_buffer, packed_len, 0/*msg->stream_id*/); +} + + int pnf_pack_and_send_p5_message(pnf_t* pnf, nfapi_p4_p5_message_header_t* msg, uint32_t msg_len) { int packed_len = nfapi_p5_message_pack(msg, msg_len, @@ -1393,8 +1970,15 @@ int pnf_connect(pnf_t* pnf) int pnf_send_message(pnf_t* pnf, uint8_t *msg, uint32_t len, uint16_t stream) { + if (pnf->sctp) { + printf("\nPNF SENDS: \n"); + for(int i=0; ip5_sock, msg, len, NULL, 0, 42/*config->sctp_stream_number*/, 0, stream/*P5_STREAM_ID*/, 0, 0) < 0) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "sctp_sendmsg failed errno: %d\n", errno); @@ -1412,7 +1996,6 @@ int pnf_send_message(pnf_t* pnf, uint8_t *msg, uint32_t len, uint16_t stream) return 0; } - int pnf_read_dispatch_message(pnf_t* pnf) { int socket_connected = 1; @@ -1486,6 +2069,13 @@ int pnf_read_dispatch_message(pnf_t* pnf) } else { + // print the received message + printf("\n MESSAGE RECEIVED: \n"); + for(int i=0; ip5_sock, header_buffer, header_buffer_size, /*(struct sockaddr*)&addr, &addr_len*/ 0, 0, &sndrcvinfo, &flags); + + if(message_size == -1) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF Failed to peek sctp message size errno:%d\n", errno); + return 0; + } + + nfapi_p4_p5_message_header_t header; + int unpack_result = nfapi_p5_message_header_unpack(header_buffer, header_buffer_size, &header, sizeof(header), 0); + if(unpack_result < 0) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF Failed to unpack p5 message header\n"); + return 0; + } + message_size = header.message_length; + + // now have the size of the mesage + } + + if(message_size > stack_buffer_size) + { + dynamic_buffer = (uint8_t*)malloc(message_size); + + if(dynamic_buffer == NULL) + { + // todo : add error mesage + NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF Failed to allocate dynamic buffer for sctp_recvmsg size:%d\n", message_size); + return -1; + } + + read_buffer = dynamic_buffer; + } + + { + int flags = 0; + (void)memset(&sndrcvinfo, 0, sizeof(struct sctp_sndrcvinfo)); + + int recvmsg_result = sctp_recvmsg(pnf->p5_sock, read_buffer, message_size, (struct sockaddr*)&addr, &addr_len, &sndrcvinfo, &flags); + if(recvmsg_result == -1) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "Failed to read sctp message size errno:%d\n", errno); + } + else + { + // print the received message + printf("\n MESSAGE RECEIVED: \n"); + for(int i=0; ip5_sock, + inet_ntoa(addr.sin_addr), + ntohs(addr.sin_port), + sndrcvinfo.sinfo_assoc_id, + sndrcvinfo.sinfo_stream, + ntohl(sndrcvinfo.sinfo_ppid), + message_size, + flags); + */ + + // handle now if complete message in one or more segments + if ((flags & 0x80) == 0x80) + { + pnf_nr_handle_p5_message(pnf, read_buffer, message_size); + } + else + { + NFAPI_TRACE(NFAPI_TRACE_WARN, "sctp_recvmsg: unhandled mode with flags 0x%x\n", flags); + + // assume socket disconnected + NFAPI_TRACE(NFAPI_TRACE_WARN, "Disconnected socket\n"); + socket_connected = 0; + } + + + } + } + } + + if(dynamic_buffer) + { + free(dynamic_buffer); + } + + return socket_connected; + + } @@ -1597,3 +2316,64 @@ int pnf_message_pump(pnf_t* pnf) } +int pnf_nr_message_pump(pnf_t* pnf) +{ + uint8_t socketConnected = 1; + + while(socketConnected && pnf->terminate == 0) + { + fd_set rfds; + int selectRetval = 0; + + // select on a timeout and then get the message + FD_ZERO(&rfds); + FD_SET(pnf->p5_sock, &rfds); + + struct timeval timeout; + timeout.tv_sec = 1; + timeout.tv_usec = 0; + + selectRetval = select(pnf->p5_sock+1, &rfds, NULL, NULL, &timeout); + + if(selectRetval == 0) + { + // timeout + continue; + } + else if (selectRetval == -1 && (errno == EINTR)) + { + // interrupted by signal + NFAPI_TRACE(NFAPI_TRACE_WARN, "P5 Signal Interrupt %d\n", errno); + continue; + } + else if (selectRetval == -1) + { + NFAPI_TRACE(NFAPI_TRACE_WARN, "P5 select() failed\n"); + sleep(1); + continue; + } + + if(FD_ISSET(pnf->p5_sock, &rfds)) + { + socketConnected = pnf_nr_read_dispatch_message(pnf); + } + else + { + NFAPI_TRACE(NFAPI_TRACE_WARN, "Why are we here\n"); + } + } + + // Drop back to idle if we have lost connection + pnf->_public.state = NFAPI_PNF_PHY_IDLE; + + + // close the connection and socket + if (close(pnf->p5_sock) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "close(sctpSock) failed errno: %d\n", errno); + } + + return 0; + +} + diff --git a/nfapi/open-nFAPI/pnf/src/pnf_interface.c b/nfapi/open-nFAPI/pnf/src/pnf_interface.c index dda0d0fdc6..8c9722c13e 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf_interface.c +++ b/nfapi/open-nFAPI/pnf/src/pnf_interface.c @@ -19,6 +19,8 @@ #include #include #include +#include "nfapi_nr_interface.h" +#include "nfapi_nr_interface_scf.h" nfapi_pnf_config_t* nfapi_pnf_config_create() { @@ -81,6 +83,40 @@ int nfapi_pnf_start(nfapi_pnf_config_t* config) return 0; } +int nfapi_nr_pnf_start(nfapi_pnf_config_t* config) +{ + // Verify that config is not null + if(config == 0) + return -1; + + // Make sure to set the defined trace function before using NFAPI_TRACE + if(config->trace) + nfapi_trace_g = config->trace; + + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__); + + pnf_t* _this = (pnf_t*)(config); + + while (_this->terminate == 0) + { + int connect_result = pnf_connect(_this); + + if(connect_result > 0) + { + pnf_nr_message_pump(_this); + } + else if(connect_result < 0) + { + return connect_result; + } + + sleep(1); + } + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() terminate=1 - EXITTING............\n", __FUNCTION__); + + return 0; +} + int nfapi_pnf_stop(nfapi_pnf_config_t* config) { // Verify that config is not null @@ -96,6 +132,21 @@ int nfapi_pnf_stop(nfapi_pnf_config_t* config) return 0; } + +int nfapi_nr_pnf_pnf_param_resp(nfapi_pnf_config_t* config, nfapi_nr_pnf_param_response_t* resp) +{ + // ensure it's valid + if (config == NULL || resp == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + return -1; + } + + pnf_t* _this = (pnf_t*)(config); + + return pnf_nr_pack_and_send_p5_message(_this, &(resp->header), sizeof(nfapi_nr_pnf_param_response_t)); +} + int nfapi_pnf_pnf_param_resp(nfapi_pnf_config_t* config, nfapi_pnf_param_response_t* resp) { // ensure it's valid @@ -129,6 +180,27 @@ int nfapi_pnf_pnf_config_resp(nfapi_pnf_config_t* config, nfapi_pnf_config_respo return pnf_pack_and_send_p5_message(_this, &(resp->header), sizeof(nfapi_pnf_config_response_t)); } + +int nfapi_nr_pnf_pnf_config_resp(nfapi_pnf_config_t* config, nfapi_nr_pnf_config_response_t* resp) +{ + // ensure it's valid + if (config == NULL || resp == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + return -1; + } + + if(resp->error_code == NFAPI_MSG_OK) + { + config->state = NFAPI_PNF_CONFIGURED; + } + + pnf_t* _this = (pnf_t*)(config); + + return pnf_nr_pack_and_send_p5_message(_this, &(resp->header), sizeof(nfapi_nr_pnf_config_response_t)); +} + + int nfapi_pnf_pnf_start_resp(nfapi_pnf_config_t* config, nfapi_pnf_start_response_t* resp) { // ensure it's valid @@ -148,6 +220,26 @@ int nfapi_pnf_pnf_start_resp(nfapi_pnf_config_t* config, nfapi_pnf_start_respons return pnf_pack_and_send_p5_message(_this, &(resp->header), sizeof(nfapi_pnf_start_response_t)); } +int nfapi_nr_pnf_pnf_start_resp(nfapi_pnf_config_t* config, nfapi_nr_pnf_start_response_t* resp) +{ + // ensure it's valid + if (config == NULL || resp == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + return -1; + } + + if(resp->error_code == NFAPI_MSG_OK) + { + config->state = NFAPI_PNF_RUNNING; + } + + pnf_t* _this = (pnf_t*)(config); + + return pnf_nr_pack_and_send_p5_message(_this, &(resp->header), sizeof(nfapi_nr_pnf_start_response_t)); +} + + int nfapi_pnf_pnf_stop_resp(nfapi_pnf_config_t* config, nfapi_pnf_stop_response_t* resp) { // ensure it's valid @@ -166,7 +258,6 @@ int nfapi_pnf_pnf_stop_resp(nfapi_pnf_config_t* config, nfapi_pnf_stop_response_ return pnf_pack_and_send_p5_message(_this, &(resp->header), sizeof(nfapi_pnf_stop_response_t)); } - int nfapi_pnf_param_resp(nfapi_pnf_config_t* config, nfapi_param_response_t* resp) { if (config == NULL || resp == NULL) @@ -180,6 +271,20 @@ int nfapi_pnf_param_resp(nfapi_pnf_config_t* config, nfapi_param_response_t* res return pnf_pack_and_send_p5_message(_this, &(resp->header), sizeof(nfapi_param_response_t)); } + +int nfapi_nr_pnf_param_resp(nfapi_pnf_config_t* config, nfapi_nr_param_response_scf_t* resp) +{ + if (config == NULL || resp == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + return -1; + } + + pnf_t* _this = (pnf_t*)(config); + + return pnf_nr_pack_and_send_p5_message(_this, &(resp->header), sizeof(nfapi_nr_param_response_scf_t)); +} + int nfapi_pnf_config_resp(nfapi_pnf_config_t* config, nfapi_config_response_t* resp) { if (config == NULL || resp == NULL) @@ -208,6 +313,35 @@ int nfapi_pnf_config_resp(nfapi_pnf_config_t* config, nfapi_config_response_t* r return pnf_pack_and_send_p5_message(_this, &(resp->header), sizeof(nfapi_config_response_t)); } +int nfapi_nr_pnf_config_resp(nfapi_pnf_config_t* config, nfapi_nr_config_response_scf_t* resp) +{ + if (config == NULL || resp == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + return -1; + } + + pnf_t* _this = (pnf_t*)(config); + + nfapi_pnf_phy_config_t* phy = nfapi_pnf_phy_config_find(config, resp->header.phy_id); + + if(phy) + { + if(resp->error_code == NFAPI_NR_CONFIG_MSG_OK) + { + phy->state = NFAPI_PNF_PHY_CONFIGURED; + } + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: unknow phy id %d\n", __FUNCTION__, resp->header.phy_id); + return -1; + } + + return pnf_nr_pack_and_send_p5_message(_this, &(resp->header), sizeof(nfapi_nr_config_response_scf_t)); +} + + int nfapi_pnf_start_resp(nfapi_pnf_config_t* config, nfapi_start_response_t* resp) { if (config == NULL || resp == NULL) @@ -235,6 +369,34 @@ int nfapi_pnf_start_resp(nfapi_pnf_config_t* config, nfapi_start_response_t* res return pnf_pack_and_send_p5_message(_this, &(resp->header), sizeof(nfapi_start_response_t)); } +int nfapi_nr_pnf_start_resp(nfapi_pnf_config_t* config, nfapi_nr_start_response_scf_t* resp) +{ + if (config == NULL || resp == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + return -1; + } + + pnf_t* _this = (pnf_t*)(config); + + nfapi_pnf_phy_config_t* phy = nfapi_pnf_phy_config_find(config, resp->header.phy_id); + if(phy) + { + if(resp->error_code == NFAPI_NR_START_MSG_OK) + { + phy->state = NFAPI_PNF_PHY_RUNNING; + } + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: unknown phy id %d\n", __FUNCTION__, resp->header.phy_id); + return -1; + } + + return pnf_nr_pack_and_send_p5_message(_this, &(resp->header), sizeof(nfapi_nr_start_response_scf_t)); +} + + int nfapi_pnf_stop_resp(nfapi_pnf_config_t* config, nfapi_stop_response_t* resp) { if (config == NULL || resp == NULL) diff --git a/nfapi/open-nFAPI/pnf/src/pnf_p7.c b/nfapi/open-nFAPI/pnf/src/pnf_p7.c index 5ba912e059..18891cdee9 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf_p7.c +++ b/nfapi/open-nFAPI/pnf/src/pnf_p7.c @@ -32,8 +32,19 @@ #define FAPI2_IP_DSCP 0 extern uint16_t sf_ahead; +extern uint16_t slot_ahead; + //uint16_t sf_ahead=4; +void add_slot(uint16_t *frameP, uint16_t *slotP, int offset) +{ + uint16_t num_slots = 20; // set based on numerlogy (fixing for 1) + + *frameP = (*frameP + ((*slotP + offset) / num_slots))%1024; + + *slotP = ((*slotP + offset) % num_slots); +} + void add_sf(uint16_t *frameP, uint16_t *subframeP, int offset) { *frameP = (*frameP + ((*subframeP + offset) / 10))%1024; @@ -50,6 +61,22 @@ void subtract_sf(uint16_t *frameP, uint16_t *subframeP, int offset) *subframeP = (*subframeP+10-offset)%10; } +uint32_t sfnslot_add_slot(uint16_t sfn, uint16_t slot, int offset) +{ + uint32_t new_sfnslot; +// uint16_t sfn = NFAPI_SFNSLOT2SFN(sfnslot); +// uint16_t slot = NFAPI_SFNSLOT2SLOT(sfnslot); + + //printf("%s() sfn:%u sf:%u\n", __FUNCTION__, sfn, sf); + add_slot(&sfn, &slot, offset); + + new_sfnslot = sfn<<6|slot; + + //printf("%s() sfn:%u sf:%u offset:%d sfnsf:%d(DEC:%d) new:%d(DEC:%d)\n", __FUNCTION__, sfn, sf, offset, sfnsf, NFAPI_SFNSF2DEC(sfnsf), new_sfnsf, NFAPI_SFNSF2DEC(new_sfnsf)); + + return new_sfnslot; +} + uint16_t sfnsf_add_sf(uint16_t sfnsf, int offset) { uint16_t new_sfnsf; @@ -114,12 +141,34 @@ void pnf_p7_free(pnf_p7_t* pnf_p7, void* ptr) } // todo : for now these just malloc/free need to move to a memory cache +nfapi_nr_dl_tti_request_t* allocate_nfapi_dl_tti_request(pnf_p7_t* pnf_p7) +{ + void *ptr= pnf_p7_malloc(pnf_p7, sizeof(nfapi_nr_dl_tti_request_t)); + //printf("%s() ptr:%p\n", __FUNCTION__, ptr); + return ptr; +} nfapi_dl_config_request_t* allocate_nfapi_dl_config_request(pnf_p7_t* pnf_p7) { void *ptr= pnf_p7_malloc(pnf_p7, sizeof(nfapi_dl_config_request_t)); //printf("%s() ptr:%p\n", __FUNCTION__, ptr); return ptr; } +void deallocate_nfapi_dl_tti_request(nfapi_nr_dl_tti_request_t* req, pnf_p7_t* pnf_p7) +{ + //printf("%s() SFN/SF:%d %s req:%p pdu_list:%p\n", __FUNCTION__, NFAPI_SFNSF2DEC(req->sfn_sf), pnf_p7->_public.codec_config.deallocate ? "DEALLOCATE" : "FREE", req, req->dl_config_request_body.dl_config_pdu_list); + /* + if(pnf_p7->_public.codec_config.deallocate) + { + //nfapi_nr_dl_tti_request_pdu_t *temp = &req->dl_tti_pdu_list; + (pnf_p7->_public.codec_config.deallocate)(req); + } + else + { + free(req); + } +*/ + pnf_p7_free(pnf_p7, req); +} void deallocate_nfapi_dl_config_request(nfapi_dl_config_request_t* req, pnf_p7_t* pnf_p7) { @@ -137,6 +186,13 @@ void deallocate_nfapi_dl_config_request(nfapi_dl_config_request_t* req, pnf_p7_t pnf_p7_free(pnf_p7, req); } +nfapi_nr_ul_tti_request_t* allocate_nfapi_ul_tti_request(pnf_p7_t* pnf_p7) +{ + void *ptr= pnf_p7_malloc(pnf_p7, sizeof(nfapi_nr_ul_tti_request_t)); + //printf("%s() ptr:%p\n", __FUNCTION__, ptr); + return ptr; +} + nfapi_ul_config_request_t* allocate_nfapi_ul_config_request(pnf_p7_t* pnf_p7) { void *ptr= pnf_p7_malloc(pnf_p7, sizeof(nfapi_ul_config_request_t)); @@ -144,6 +200,23 @@ nfapi_ul_config_request_t* allocate_nfapi_ul_config_request(pnf_p7_t* pnf_p7) return ptr; } +void deallocate_nfapi_ul_tti_request(nfapi_nr_ul_tti_request_t* req, pnf_p7_t* pnf_p7) +{ + //printf("%s() SFN/SF:%d %s req:%p pdu_list:%p\n", __FUNCTION__, NFAPI_SFNSF2DEC(req->sfn_sf), pnf_p7->_public.codec_config.deallocate ? "DEALLOCATE" : "FREE", req, req->ul_config_request_body.ul_config_pdu_list); + /*if(pnf_p7->_public.codec_config.deallocate) + { + (pnf_p7->_public.codec_config.deallocate)(req->pdus_list); + (pnf_p7->_public.codec_config.deallocate)(req->groups_list); + } + else + { + free(req->pdus_list); + free(req->groups_list); + } + */ + pnf_p7_free(pnf_p7, req); +} + void deallocate_nfapi_ul_config_request(nfapi_ul_config_request_t* req, pnf_p7_t* pnf_p7) { //printf("%s() SFN/SF:%d %s req:%p pdu_list:%p\n", __FUNCTION__, NFAPI_SFNSF2DEC(req->sfn_sf), pnf_p7->_public.codec_config.deallocate ? "DEALLOCATE" : "FREE", req, req->ul_config_request_body.ul_config_pdu_list); @@ -160,11 +233,31 @@ void deallocate_nfapi_ul_config_request(nfapi_ul_config_request_t* req, pnf_p7_t pnf_p7_free(pnf_p7, req); } +nfapi_nr_ul_dci_request_t* allocate_nfapi_ul_dci_request(pnf_p7_t* pnf_p7) +{ + return pnf_p7_malloc(pnf_p7, sizeof(nfapi_nr_ul_dci_request_t)); +} + nfapi_hi_dci0_request_t* allocate_nfapi_hi_dci0_request(pnf_p7_t* pnf_p7) { return pnf_p7_malloc(pnf_p7, sizeof(nfapi_hi_dci0_request_t)); } +void deallocate_nfapi_ul_dci_request(nfapi_nr_ul_dci_request_t* req, pnf_p7_t* pnf_p7) +{ + //printf("%s() SFN/SF:%d %s req:%p pdu_list:%p\n", __FUNCTION__, NFAPI_SFNSF2DEC(req->sfn_sf), pnf_p7->_public.codec_config.deallocate ? "DEALLOCATE" : "FREE", req, req->hi_dci0_request_body.hi_dci0_pdu_list); + // if(pnf_p7->_public.codec_config.deallocate) + // { + // (pnf_p7->_public.codec_config.deallocate)(req->ul_dci_pdu_list); + // } + // else + // { + // free(req->ul_dci_pdu_list); + // } + + pnf_p7_free(pnf_p7, req); +} + void deallocate_nfapi_hi_dci0_request(nfapi_hi_dci0_request_t* req, pnf_p7_t* pnf_p7) { //printf("%s() SFN/SF:%d %s req:%p pdu_list:%p\n", __FUNCTION__, NFAPI_SFNSF2DEC(req->sfn_sf), pnf_p7->_public.codec_config.deallocate ? "DEALLOCATE" : "FREE", req, req->hi_dci0_request_body.hi_dci0_pdu_list); @@ -181,11 +274,32 @@ void deallocate_nfapi_hi_dci0_request(nfapi_hi_dci0_request_t* req, pnf_p7_t* pn pnf_p7_free(pnf_p7, req); } +nfapi_nr_tx_data_request_t* allocate_nfapi_tx_data_request(pnf_p7_t* pnf_p7) +{ + return pnf_p7_malloc(pnf_p7, sizeof(nfapi_nr_tx_data_request_t)); +} + nfapi_tx_request_t* allocate_nfapi_tx_request(pnf_p7_t* pnf_p7) { return pnf_p7_malloc(pnf_p7, sizeof(nfapi_tx_request_t)); } +//TODO: Check if deallocate_nfapi_tx_data_request defn is proper +void deallocate_nfapi_tx_data_request(nfapi_nr_tx_data_request_t* req, pnf_p7_t* pnf_p7) +{ +/* + if(pnf_p7->_public.codec_config.deallocate) + { + (pnf_p7->_public.codec_config.deallocate)(req->pdu_list); + } + else + { + free(req->pdu_list); + } +*/ + pnf_p7_free(pnf_p7, req); +} + void deallocate_nfapi_tx_request(nfapi_tx_request_t* req, pnf_p7_t* pnf_p7) { int i = 0; @@ -385,11 +499,33 @@ void pnf_p7_rx_reassembly_queue_remove_old_msgs(pnf_p7_t* pnf_p7, pnf_p7_rx_reas } +static uint32_t get_slot_time(uint32_t now_hr, uint32_t slot_start_hr) +{ + if(now_hr < slot_start_hr) + { + //NFAPI_TRACE(NFAPI_TRACE_INFO, "now is earlier than start of subframe now_hr:%u sf_start_hr:%u\n", now_hr, sf_start_hr); + return 0; + } + else + { + uint32_t now_us = TIMEHR_USEC(now_hr); + uint32_t slot_start_us = TIMEHR_USEC(slot_start_hr); + + // if the us have wrapped adjust for it + if(now_hr < slot_start_us) + { + now_us += 500000; + } + + return now_us - slot_start_us; + } +} + static uint32_t get_sf_time(uint32_t now_hr, uint32_t sf_start_hr) { if(now_hr < sf_start_hr) { - //NFAPI_TRACE(NFAPI_TRACE_INFO, "now is earlier than start of subframe now_hr:%u sf_start_hr:%u\n", now_hr, sf_start_hr); + NFAPI_TRACE(NFAPI_TRACE_INFO, "now is earlier than start of subframe\n"); return 0; } else @@ -407,6 +543,8 @@ static uint32_t get_sf_time(uint32_t now_hr, uint32_t sf_start_hr) } } + + int pnf_p7_send_message(pnf_p7_t* pnf_p7, uint8_t* msg, uint32_t len) { // todo : consider how to do this only once @@ -414,7 +552,8 @@ int pnf_p7_send_message(pnf_p7_t* pnf_p7, uint8_t* msg, uint32_t len) memset((char*)&remote_addr, 0, sizeof(struct sockaddr_in)); remote_addr.sin_family = AF_INET; remote_addr.sin_port = htons(pnf_p7->_public.remote_p7_port); - //remote_addr.sin_addr.s_addr = inet_addr(pnf_p7->_public.remote_p7_addr); + + if(inet_aton(pnf_p7->_public.remote_p7_addr, &remote_addr.sin_addr) == -1) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "inet_aton failed %d\n", errno); @@ -424,7 +563,9 @@ int pnf_p7_send_message(pnf_p7_t* pnf_p7, uint8_t* msg, uint32_t len) socklen_t remote_addr_len = sizeof(struct sockaddr_in); int sendto_result; + if ((sendto_result = sendto((int)pnf_p7->p7_sock, (const char*)msg, len, 0, (const struct sockaddr*)&remote_addr, remote_addr_len)) < 0) +//if ((sendto_result = sendto((int)pnf_p7->p7_sock,"hello", 6, 0, (const struct sockaddr*)&remote_addr, remote_addr_len)) < 0) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s %s:%d sendto(%d, %p, %d) %d failed errno: %d\n", __FUNCTION__, pnf_p7->_public.remote_p7_addr, pnf_p7->_public.remote_p7_port, (int)pnf_p7->p7_sock, (const char*)msg, len, remote_addr_len, errno); return -1; @@ -527,6 +668,97 @@ int pnf_p7_pack_and_send_p7_message(pnf_p7_t* pnf_p7, nfapi_p7_message_header_t* return 0; } + +int pnf_nr_p7_pack_and_send_p7_message(pnf_p7_t* pnf_p7, nfapi_p7_message_header_t* header, uint32_t msg_len) +{ + header->m_segment_sequence = NFAPI_P7_SET_MSS(0, 0, pnf_p7->sequence_number); + + // Need to guard against different threads calling the encode function at the same time + if(pthread_mutex_lock(&(pnf_p7->pack_mutex)) != 0) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to lock mutex\n"); + return -1; + } + + int len = nfapi_nr_p7_message_pack(header, pnf_p7->tx_message_buffer, sizeof(pnf_p7->tx_message_buffer), &pnf_p7->_public.codec_config); + + if (len < 0) + { + if(pthread_mutex_unlock(&(pnf_p7->pack_mutex)) != 0) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to unlock mutex\n"); + return -1; + } + + NFAPI_TRACE(NFAPI_TRACE_ERROR, "nfapi_p7_message_pack failed with return %d\n", len ); + return -1; + } + + if(len > pnf_p7->_public.segment_size) + { + int msg_body_len = len - NFAPI_P7_HEADER_LENGTH ; + int seg_body_len = pnf_p7->_public.segment_size - NFAPI_P7_HEADER_LENGTH ; + int segment_count = (msg_body_len / (seg_body_len)) + ((msg_body_len % seg_body_len) ? 1 : 0); + + int segment = 0; + int offset = NFAPI_P7_HEADER_LENGTH; + uint8_t buffer[pnf_p7->_public.segment_size]; + for(segment = 0; segment < segment_count; ++segment) + { + uint8_t last = 0; + uint16_t size = pnf_p7->_public.segment_size - NFAPI_P7_HEADER_LENGTH; + if(segment + 1 == segment_count) + { + last = 1; + size = (msg_body_len) - (seg_body_len * segment); + } + + uint16_t segment_size = size + NFAPI_P7_HEADER_LENGTH; + + // Update the header with the m and segement + memcpy(&buffer[0], pnf_p7->tx_message_buffer, NFAPI_P7_HEADER_LENGTH); + + // set the segment length + buffer[4] = (segment_size & 0xFF00) >> 8; + buffer[5] = (segment_size & 0xFF); + + // set the m & segment number + buffer[6] = ((!last) << 7) + segment; + + memcpy(&buffer[NFAPI_P7_HEADER_LENGTH], pnf_p7->tx_message_buffer + offset, size); + offset += size; + + if(pnf_p7->_public.checksum_enabled) + { + nfapi_p7_update_checksum(buffer, segment_size); + } + + + pnf_p7_send_message(pnf_p7, &buffer[0], segment_size); + } + } + else + { + if(pnf_p7->_public.checksum_enabled) + { + nfapi_p7_update_checksum(pnf_p7->tx_message_buffer, len); + } + + // simple case that the message fits in a single segment + pnf_p7_send_message(pnf_p7, pnf_p7->tx_message_buffer, len); + } + + pnf_p7->sequence_number++; + + if(pthread_mutex_unlock(&(pnf_p7->pack_mutex)) != 0) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to unlock mutex\n"); + return -1; + } + + return 0; +} + void pnf_pack_and_send_timing_info(pnf_p7_t* pnf_p7) { nfapi_timing_info_t timing_info; @@ -558,6 +790,88 @@ void pnf_pack_and_send_timing_info(pnf_p7_t* pnf_p7) pnf_p7->timing_info_ms_counter = 0; } + +void pnf_nr_pack_and_send_timing_info(pnf_p7_t* pnf_p7) +{ + nfapi_nr_timing_info_t timing_info; + memset(&timing_info, 0, sizeof(timing_info)); + timing_info.header.message_id = NFAPI_TIMING_INFO; + timing_info.header.phy_id = pnf_p7->_public.phy_id; + + timing_info.last_sfn = pnf_p7->sfn; + timing_info.last_slot = pnf_p7->slot; + timing_info.time_since_last_timing_info = pnf_p7->timing_info_ms_counter; + + timing_info.dl_tti_jitter = pnf_p7->dl_tti_jitter; + timing_info.tx_data_request_jitter = pnf_p7->tx_data_jitter; + timing_info.ul_tti_jitter = pnf_p7->ul_tti_jitter; + timing_info.ul_dci_jitter = pnf_p7->ul_dci_jitter; + + timing_info.dl_tti_latest_delay = 0; + timing_info.tx_data_request_latest_delay = 0; + timing_info.ul_tti_latest_delay = 0; + timing_info.ul_dci_latest_delay = 0; + + timing_info.dl_tti_earliest_arrival = 0; + timing_info.tx_data_request_earliest_arrival = 0; + timing_info.ul_tti_earliest_arrival = 0; + timing_info.ul_dci_earliest_arrival = 0; + + + pnf_nr_p7_pack_and_send_p7_message(pnf_p7, &(timing_info.header), sizeof(timing_info)); + + pnf_p7->timing_info_ms_counter = 0; +} + + +void send_dummy_slot(pnf_p7_t* pnf_p7, uint16_t sfn, uint16_t slot) +{ + struct timespec t; + clock_gettime( CLOCK_MONOTONIC, &t); + + //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s(sfn_sf:%d) t:%ld.%09ld\n", __FUNCTION__, NFAPI_SFNSF2DEC(sfn_sf), t.tv_sec, t.tv_nsec); + + if(pnf_p7->_public.tx_data_req_fn && pnf_p7->_public.dummy_slot.tx_data_req) + { + pnf_p7->_public.dummy_slot.tx_data_req->SFN = sfn; + pnf_p7->_public.dummy_slot.tx_data_req->Slot = slot; + //NFAPI_TRACE(NFAPI_TRACE_INFO, "Dummy tx_req - enter\n"); + (pnf_p7->_public.tx_data_req_fn)(&pnf_p7->_public, pnf_p7->_public.dummy_slot.tx_data_req); + //NFAPI_TRACE(NFAPI_TRACE_INFO, "Dummy tx_req - exit\n"); + } + if(pnf_p7->_public.dl_tti_req_fn && pnf_p7->_public.dummy_slot.dl_tti_req) + { + pnf_p7->_public.dummy_slot.dl_tti_req->SFN = sfn; + pnf_p7->_public.dummy_slot.dl_tti_req->Slot = slot; + //NFAPI_TRACE(NFAPI_TRACE_INFO, "Dummy dl_config_req - enter\n"); + (pnf_p7->_public.dl_tti_req_fn)(NULL, &(pnf_p7->_public), pnf_p7->_public.dummy_slot.dl_tti_req); + //NFAPI_TRACE(NFAPI_TRACE_INFO, "Dummy dl_config_req - exit\n"); + } + if(pnf_p7->_public.ul_tti_req_fn && pnf_p7->_public.dummy_slot.ul_tti_req) + { + pnf_p7->_public.dummy_slot.ul_tti_req->SFN = sfn; + pnf_p7->_public.dummy_slot.ul_tti_req->Slot = slot; + NFAPI_TRACE(NFAPI_TRACE_INFO, "Dummy ul_config_req - enter\n"); + (pnf_p7->_public.ul_tti_req_fn)(NULL, &pnf_p7->_public, pnf_p7->_public.dummy_slot.ul_tti_req); + } + if(pnf_p7->_public.ul_dci_req_fn && pnf_p7->_public.dummy_slot.ul_dci_req) + { + pnf_p7->_public.dummy_slot.ul_dci_req->SFN = sfn; + pnf_p7->_public.dummy_slot.ul_dci_req->Slot = slot; + NFAPI_TRACE(NFAPI_TRACE_INFO, "Dummy hi_dci0 - enter\n"); + (pnf_p7->_public.ul_dci_req_fn)(NULL, &pnf_p7->_public, pnf_p7->_public.dummy_slot.ul_dci_req); + } + #if 0 + if(pnf_p7->_public.lbt_dl_config_req && pnf_p7->_public.dummy_subframe.lbt_dl_config_req) // TODO: Change later + { + pnf_p7->_public.dummy_slot.lbt_dl_config_req->sfn_sf = sfn; + NFAPI_TRACE(NFAPI_TRACE_INFO, "Dummy lbt - enter\n"); + (pnf_p7->_public.lbt_dl_config_req)(&pnf_p7->_public, pnf_p7->_public.dummy_slot.lbt_dl_config_req); + } + #endif +} + + void send_dummy_subframe(pnf_p7_t* pnf_p7, uint16_t sfn_sf) { struct timespec t; @@ -599,6 +913,292 @@ void send_dummy_subframe(pnf_p7_t* pnf_p7, uint16_t sfn_sf) } } + +int pnf_p7_slot_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn, uint16_t slot) +{ + // We could either send an event to the p7 thread have have it run the + // subframe or we could handle it here and lock access to the subframe + // buffers. If we do it on the p7 thread then we run the risk of blocking + // on the udp send. + // + // todo : start a timer to give us more of the 1 ms tick before send back + // the frame + + // todo : consider a more efficent lock mechasium + //uint16_t NUM_SLOTS = 20;//10* 2^mu + + if(pthread_mutex_lock(&(pnf_p7->mutex)) != 0) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to lock mutex\n"); + return -1; + } + + // save the curren time, sfn and slot + pnf_p7->slot_start_time_hr = pnf_get_current_time_hr(); + pnf_p7->sfn = sfn; + + pnf_p7->slot = slot; + + + + uint32_t sfn_slot_tx = sfnslot_add_slot(sfn, slot, slot_ahead); + uint16_t sfn_tx = sfn_slot_tx>>6; + uint16_t slot_tx = sfn_slot_tx & 0X3F; + + // uint32_t tx_sfn_slot_dec = NFAPI_SFNSLOT2DEC(sfn,slot); + uint32_t tx_slot_dec = NFAPI_SFNSLOT2DEC(sfn,slot); + + + //uint32_t tx_sfn_slot_dec = NFAPI_SFNSLOT2DEC(sfn_slot_tx); + + // If the subframe_buffer has been configured + if(pnf_p7->_public.slot_buffer_size!= 0) // for now value is same as sf_buffer_size + { + + // apply the shift to the incoming sfn_sf + if(pnf_p7->slot_shift != 0) // see in vnf_build_send_dl_node_sync + { + uint16_t shifted_slot = slot + pnf_p7->slot_shift; + + // adjust for wrap-around + if(shifted_slot < 0) + shifted_slot += NFAPI_MAX_SFNSLOTDEC; + else if(shifted_slot > NFAPI_MAX_SFNSLOTDEC) + shifted_slot -= NFAPI_MAX_SFNSLOTDEC; + + // NFAPI_TRACE(NFAPI_TRACE_INFO, "Applying shift %d to sfn/slot (%d -> %d)\n", pnf_p7->sfn_slot_shift, NFAPI_SFNSF2DEC(sfn_slot), shifted_sfn_slot); + slot = shifted_slot; + + // + // DJP - why does the shift not apply to pnf_p7->sfn_sf??? + // + + pnf_p7->slot_shift = 0; + } + + uint32_t slot_dec = NFAPI_SFNSLOT2DEC(sfn, slot); + uint8_t buffer_index = slot_dec % pnf_p7->_public.slot_buffer_size; + + nfapi_pnf_p7_slot_buffer_t* slot_buffer = &(pnf_p7->slot_buffer[buffer_index]); + // see where the PNF_P7 slot buffer its getting filled + + uint8_t tx_buffer_index = tx_slot_dec % pnf_p7->_public.slot_buffer_size; + nfapi_pnf_p7_slot_buffer_t* tx_slot_buffer = &(pnf_p7->slot_buffer[tx_buffer_index]); + + if (0) NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() shift:%d slot_buffer->sfn_sf:%d tx_slot_buffer->sfn_slot:%d sfn_sf:%d subframe_buffer[buffer_index:%u dl_config_req:%p tx_req:%p] " + "TX:sfn_sf:%d:tx_buffer_index:%d[dl_config_req:%p tx_req:%p]\n", + __FUNCTION__, + pnf_p7->slot_shift, + NFAPI_SFNSLOT2DEC(slot_buffer->sfn, slot_buffer->slot), + NFAPI_SFNSLOT2DEC(tx_slot_buffer->sfn, tx_slot_buffer->slot), + slot_dec, buffer_index, slot_buffer->dl_tti_req, slot_buffer->tx_data_req, + tx_slot_dec, tx_buffer_index, tx_slot_buffer->dl_tti_req, tx_slot_buffer->tx_data_req); + //TODO: Change later if required + + + // if the subframe buffer sfn sf is set then we have atlease 1 message + // from the vnf. + // todo : how to handle the messages we don't have, send dummies for + // now + + //printf("tx_subframe_buffer->sfn_sf:%d sfn_sf_tx:%d\n", tx_subframe_buffer->sfn_sf, sfn_sf_tx); + //printf("subframe_buffer->sfn_sf:%d sfn_sf:%d\n", subframe_buffer->sfn_sf, sfn_sf); + //printf("tx_slot_buff_sfn - %d, tx_slot_buf_slot - %d, sfn_tx = %d, sllot_tx - %d \n",tx_slot_buffer->sfn,tx_slot_buffer->slot,sfn_tx,slot_tx); + // if(tx_slot_buffer->slot == slot_tx && tx_slot_buffer->sfn == sfn_tx) + // { + + if(tx_slot_buffer->tx_data_req != 0) + { + + if(pnf_p7->_public.tx_data_req_fn) + { + (pnf_p7->_public.tx_data_req_fn)(&(pnf_p7->_public), tx_slot_buffer->tx_data_req); + } + } + else + { + // send dummy + if(pnf_p7->_public.tx_data_req_fn && pnf_p7->_public.dummy_slot.tx_data_req) + { + pnf_p7->_public.dummy_slot.tx_data_req->SFN = sfn_tx; + pnf_p7->_public.dummy_slot.tx_data_req->Slot = slot_tx; + + (pnf_p7->_public.tx_data_req_fn)(&(pnf_p7->_public), pnf_p7->_public.dummy_slot.tx_data_req); + } + } + //} + + if( tx_slot_buffer->dl_tti_req != 0) // ADDED & TO BYPASS ERROR + { + if(pnf_p7->_public.dl_tti_req_fn) + { + (pnf_p7->_public.dl_tti_req_fn)(NULL, &(pnf_p7->_public), tx_slot_buffer->dl_tti_req); + } + } + + + else + { + // send dummy + if(pnf_p7->_public.dl_tti_req_fn && pnf_p7->_public.dummy_slot.dl_tti_req) + { + pnf_p7->_public.dummy_slot.dl_tti_req->SFN = sfn_tx; + pnf_p7->_public.dummy_slot.dl_tti_req->Slot = slot_tx; + (pnf_p7->_public.dl_tti_req_fn)(NULL, &(pnf_p7->_public), pnf_p7->_public.dummy_slot.dl_tti_req); + } + } + + if(tx_slot_buffer->ul_dci_req!= 0) + { + if(pnf_p7->_public.ul_dci_req_fn) + { + (pnf_p7->_public.ul_dci_req_fn)(NULL, &(pnf_p7->_public), tx_slot_buffer->ul_dci_req); + } + } + else + { + //send dummy + if(pnf_p7->_public.ul_dci_req_fn && pnf_p7->_public.dummy_slot.ul_dci_req) + { + pnf_p7->_public.dummy_slot.ul_dci_req->SFN = sfn_tx; + pnf_p7->_public.dummy_slot.ul_dci_req->Slot = slot_tx; + (pnf_p7->_public.ul_dci_req_fn)(NULL, &(pnf_p7->_public), pnf_p7->_public.dummy_slot.ul_dci_req); + } + } + if(tx_slot_buffer->dl_tti_req != 0) + { + deallocate_nfapi_dl_tti_request(tx_slot_buffer->dl_tti_req, pnf_p7); + tx_slot_buffer->dl_tti_req = 0; + } + + if(tx_slot_buffer->tx_data_req != 0) + { + deallocate_nfapi_tx_data_request(tx_slot_buffer->tx_data_req, pnf_p7); + tx_slot_buffer->tx_data_req = 0; + } + + if(tx_slot_buffer->ul_dci_req != 0) + { + deallocate_nfapi_ul_dci_request(tx_slot_buffer->ul_dci_req, pnf_p7); + tx_slot_buffer->ul_dci_req = 0; + } + else + { + // If we ever need to "send" a dummy ul_config this won't work!!! + // send_dummy_subframe(pnf_p7, sfn_sf_tx); + + // send_dummy_slot(pnf_p7, sfn_tx, slot_tx); + } + + + + if(slot_buffer->sfn == sfn && slot_buffer->slot == slot ) + { + + if(slot_buffer->ul_tti_req != 0) + { + if(pnf_p7->_public.ul_tti_req_fn) + { + (pnf_p7->_public.ul_tti_req_fn)(NULL, &(pnf_p7->_public), slot_buffer->ul_tti_req); + } + //deallocate_nfapi_ul_config_request(subframe_buffer->ul_config_req, pnf_p7); + } + else + { + // send dummy + if(pnf_p7->_public.ul_tti_req_fn && pnf_p7->_public.dummy_slot.ul_tti_req) + { + pnf_p7->_public.dummy_slot.ul_tti_req->SFN = sfn; + pnf_p7->_public.dummy_slot.ul_tti_req->Slot = slot; + (pnf_p7->_public.ul_tti_req_fn)(NULL, &(pnf_p7->_public), pnf_p7->_public.dummy_slot.ul_tti_req); + } + } + //if(subframe_buffer->dl_config_req != 0) + //deallocate_nfapi_dl_config_request(subframe_buffer->dl_config_req, pnf_p7); + //if(subframe_buffer->tx_req != 0) + //deallocate_nfapi_tx_request(subframe_buffer->tx_req, pnf_p7); + if(slot_buffer->ul_tti_req != 0) + { + deallocate_nfapi_ul_tti_request(slot_buffer->ul_tti_req, pnf_p7); + slot_buffer->ul_tti_req = 0; + + } + #if 0 + if(slot_buffer->lbt_dl_config_req != 0) + { + deallocate_nfapi_lbt_dl_config_request(slot_buffer->lbt_dl_config_req, pnf_p7); + slot_buffer->lbt_dl_config_req = 0; + } + #endif + } // sfn_slot match + + + if ( slot_buffer->dl_tti_req == 0 && + slot_buffer->tx_data_req == 0 && + slot_buffer->ul_tti_req == 0) + //slot_buffer->lbt_dl_config_req == 0 && + //slot_buffer->ue_release_req == 0) + { + memset(&(pnf_p7->slot_buffer[buffer_index]), 0, sizeof(nfapi_pnf_p7_slot_buffer_t)); + pnf_p7->slot_buffer[buffer_index].sfn = -1; + pnf_p7->slot_buffer[buffer_index].slot = -1; + } + + //printf("pnf_p7->_public.timing_info_mode_periodic:%d pnf_p7->timing_info_period_counter:%d pnf_p7->_public.timing_info_period:%d\n", pnf_p7->_public.timing_info_mode_periodic, pnf_p7->timing_info_period_counter, pnf_p7->_public.timing_info_period); + //printf("pnf_p7->_public.timing_info_mode_aperiodic:%d pnf_p7->timing_info_aperiodic_send:%d\n", pnf_p7->_public.timing_info_mode_aperiodic, pnf_p7->timing_info_aperiodic_send); + //printf("pnf_p7->timing_info_ms_counter:%d\n", pnf_p7->timing_info_ms_counter); + + // send the periodic timing info if configured + if(pnf_p7->_public.timing_info_mode_periodic && (pnf_p7->timing_info_period_counter++) == pnf_p7->_public.timing_info_period) + { + pnf_nr_pack_and_send_timing_info(pnf_p7); + + pnf_p7->timing_info_period_counter = 0; + } + else if(pnf_p7->_public.timing_info_mode_aperiodic && pnf_p7->timing_info_aperiodic_send) + { + pnf_nr_pack_and_send_timing_info(pnf_p7); + + pnf_p7->timing_info_aperiodic_send = 0; + } + else + { + pnf_p7->timing_info_ms_counter++; + } + + } + else + { + //send_dummy_subframe(pnf_p7, sfn_sf_tx); + } + + + //printf("pnf_p7->tick:%d\n", pnf_p7->tick); + // if(pnf_p7->tick == 1000) // why? + // { + // // TODO: change stats to nr_stats + // NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF P7:%d] (ONTIME/LATE) DL:(%d/%d) UL:(%d/%d) HI:(%d/%d) TX:(%d/%d)\n", pnf_p7->_public.phy_id, + // pnf_p7->stats.dl_conf_ontime, pnf_p7->stats.dl_conf_late, + // pnf_p7->stats.ul_conf_ontime, pnf_p7->stats.ul_conf_late, + // pnf_p7->stats.hi_dci0_ontime, pnf_p7->stats.hi_dci0_late, + // pnf_p7->stats.tx_ontime, pnf_p7->stats.tx_late); + // pnf_p7->tick = 0; + // memset(&pnf_p7->stats, 0, sizeof(pnf_p7->stats)); + // } + // pnf_p7->tick++; + + + if(pthread_mutex_unlock(&(pnf_p7->mutex)) != 0) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to unlock mutex\n"); + return -1; + } + + return 0; +} + + + int pnf_p7_subframe_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn_sf) { // We could either send an event to the p7 thread have have it run the @@ -621,8 +1221,8 @@ int pnf_p7_subframe_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn_sf) pnf_p7->sf_start_time_hr = pnf_get_current_time_hr(); pnf_p7->sfn_sf = sfn_sf; - uint32_t sfn_sf_tx = sfnsf_add_sf(sfn_sf, sf_ahead); - uint32_t tx_sfn_sf_dec = NFAPI_SFNSF2DEC(sfn_sf_tx); + uint32_t sfn_sf_tx = sfnsf_add_sf(sfn_sf, sf_ahead); + uint32_t tx_sfn_sf_dec = NFAPI_SFNSF2DEC(sfn_sf_tx); // If the subframe_buffer has been configured if(pnf_p7->_public.subframe_buffer_size != 0) @@ -890,6 +1490,82 @@ int pnf_p7_subframe_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn_sf) // return 1 if in window // return 0 if out of window + +uint8_t is_nr_p7_request_in_window(uint16_t sfn,uint16_t slot, const char* name, pnf_p7_t* phy) +{ + uint32_t recv_sfn_slot_dec = NFAPI_SFNSLOT2DEC(sfn,slot); + uint32_t current_sfn_slot_dec = NFAPI_SFNSLOT2DEC(phy->sfn,phy->slot); + printf("p7_msg_sfn: %d, p7_msg_slot: %d, phy_sfn:%d , phy_slot:%d \n",sfn,slot,phy->sfn,phy->slot); + uint8_t in_window = 0; + uint8_t timing_window = phy->_public.slot_buffer_size; + + // if(recv_sfn_slot_dec <= current_sfn_slot_dec) + // { + // // Need to check for wrap in window + // if(((recv_sfn_slot_dec + timing_window) % NFAPI_MAX_SFNSLOTDEC) < recv_sfn_slot_dec) + // { + // if(current_sfn_slot_dec > ((recv_sfn_slot_dec + timing_window) % NFAPI_MAX_SFNSLOTDEC)) + // { + // // out of window + // NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] %s is late %d (with wrap)\n", current_sfn_slot_dec, name, recv_sfn_slot_dec); + // } + // else + // { + // // ok + // //NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] %s is in window %d (with wrap)\n", current_sfn_sf_dec, name, recv_sfn_sf_dec); + // in_window = 1; + // } + // } + // else + // { + // if((current_sfn_slot_dec - recv_sfn_slot_dec) <= timing_window) + // { + // // in window + // //NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] %s is in window %d\n", current_sfn_slot_dec, name, recv_sfn_slot_dec); + // in_window = 1; + // } + // //NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] %s is in late %d (delta:%d)\n", current_sfn_slot_dec, name, recv_sfn_slot_dec, (current_sfn_slot_dec - recv_sfn_slot_dec)); + // } + + // } + // else + // { + // // Need to check it is in window + // if((recv_sfn_slot_dec - current_sfn_slot_dec) <= timing_window) + // { + // // in window + // //NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] %s is in window %d\n", current_sfn_sf_dec, name, recv_sfn_sf_dec); + // in_window = 1; + // } + // else + // { + // // too far in the future + // NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] %s is out of window %d (delta:%d) [max:%d]\n", current_sfn_slot_dec, name, recv_sfn_slot_dec, (recv_sfn_slot_dec - current_sfn_slot_dec), timing_window); + // } + + // } + if(current_sfn_slot_dec <= recv_sfn_slot_dec + timing_window){ + in_window = 1; + NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] %s is in window %d\n", current_sfn_slot_dec, name, recv_sfn_slot_dec); + } + else if(current_sfn_slot_dec + NFAPI_MAX_SFNSLOTDEC <= recv_sfn_slot_dec + timing_window){ //checking for wrap + in_window = 1; + NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] %s is in window %d\n", current_sfn_slot_dec, name, recv_sfn_slot_dec); + } + + else + { + + NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] %s is out of window %d (delta:%d) [max:%d]\n", current_sfn_slot_dec, name, recv_sfn_slot_dec, (current_sfn_slot_dec - recv_sfn_slot_dec), timing_window); + + }//Need to add more cases + + + return in_window; +} + + + uint8_t is_p7_request_in_window(uint16_t sfnsf, const char* name, pnf_p7_t* phy) { uint32_t recv_sfn_sf_dec = NFAPI_SFNSF2DEC(sfnsf); @@ -943,8 +1619,97 @@ uint8_t is_p7_request_in_window(uint16_t sfnsf, const char* name, pnf_p7_t* phy) } -// P7 messages -// +// P7 messages +void pnf_handle_dl_tti_request(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7) +{ + //NFAPI_TRACE(NFAPI_TRACE_INFO, "DL_CONFIG.req Received\n"); + nfapi_nr_dl_tti_request_t* req = allocate_nfapi_dl_tti_request(pnf_p7); + + if(req == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s failed to alloced nfapi_dl_tti_request structure\n"); + return; + } + + int unpack_result = nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, req, sizeof(nfapi_nr_dl_tti_request_t), &(pnf_p7->_public.codec_config)); + + if(unpack_result == 0) + { + if(pthread_mutex_lock(&(pnf_p7->mutex)) != 0) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to lock mutex\n"); + return; + } +#if 0 + if ( + 0 && + (NFAPI_SFNSF2DEC(req->sfn_sf) % 100 ==0 || + NFAPI_SFNSF2DEC(req->sfn_sf) % 105 ==0 + ) + ) + NFAPI_TRACE(NFAPI_TRACE_INFO, "DL_CONFIG.req sfn_sf:%d pdcch:%u dci:%u pdu:%u pdsch_rnti:%u pcfich:%u\n", + NFAPI_SFNSF2DEC(req->sfn_sf), + req->dl_config_request_body.number_pdcch_ofdm_symbols, + req->dl_config_request_body.number_dci, + req->dl_config_request_body.number_pdu, + req->dl_config_request_body.number_pdsch_rnti, + req->dl_config_request_body.transmission_power_pcfich + ); +#endif + + if(is_nr_p7_request_in_window(req->SFN,req->Slot, "dl_tti_request", pnf_p7)) + { + uint32_t sfn_slot_dec = NFAPI_SFNSLOT2DEC(req->SFN,req->Slot); + uint8_t buffer_index = sfn_slot_dec % pnf_p7->_public.slot_buffer_size; + + struct timespec t; + clock_gettime(CLOCK_MONOTONIC, &t); + + //NFAPI_TRACE(NFAPI_TRACE_INFO,"%s() %ld.%09ld POPULATE DL_TTI_REQ sfn_slot:%d buffer_index:%d\n", __FUNCTION__, t.tv_sec, t.tv_nsec, sfn_slot_dec, buffer_index); + + // if there is already an dl_config_req make sure we free it. + if(pnf_p7->slot_buffer[buffer_index].dl_tti_req != 0) + { + NFAPI_TRACE(NFAPI_TRACE_NOTE, "%s() is_nr_p7_request_in_window()=TRUE buffer_index occupied - free it first sfn_slot:%d buffer_index:%d\n", __FUNCTION__, NFAPI_SFNSLOT2DEC(req->SFN,req->Slot), buffer_index); + //NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] Freeing dl_config_req at index %d (%d/%d)", + // pMyPhyInfo->sfnSf, bufferIdx, + // SFNSF2SFN(dreq->sfn_sf), SFNSF2SF(dreq->sfn_sf)); + deallocate_nfapi_dl_tti_request(pnf_p7->slot_buffer[buffer_index].dl_tti_req, pnf_p7); + } + + // saving dl_config_request in subframe buffer + pnf_p7->slot_buffer[buffer_index].sfn = req->SFN; + pnf_p7->slot_buffer[buffer_index].slot = req->Slot; + pnf_p7->slot_buffer[buffer_index].dl_tti_req = req; + + pnf_p7->stats.dl_tti_ontime++; + } + else + { + //NFAPI_TRACE(NFAPI_TRACE_NOTE, "NOT storing dl_config_req SFN/SF %d\n", req->sfn_sf); + deallocate_nfapi_dl_tti_request(req, pnf_p7); + + if(pnf_p7->_public.timing_info_mode_aperiodic) + { + pnf_p7->timing_info_aperiodic_send = 1; + } + + pnf_p7->stats.dl_tti_late++; + } + if(pthread_mutex_unlock(&(pnf_p7->mutex)) != 0) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to unlock mutex\n"); + return; + } + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Failed to unpack dl_tti_req"); + deallocate_nfapi_dl_tti_request(req, pnf_p7); + } +} + + void pnf_handle_dl_config_request(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7) { //NFAPI_TRACE(NFAPI_TRACE_INFO, "DL_CONFIG.req Received\n"); @@ -1035,6 +1800,80 @@ void pnf_handle_dl_config_request(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_ } } + +void pnf_handle_ul_tti_request(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7) +{ + //NFAPI_TRACE(NFAPI_TRACE_INFO, "UL_CONFIG.req Received\n"); + + nfapi_nr_ul_tti_request_t* req = allocate_nfapi_ul_tti_request(pnf_p7); + + if(req == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s failed to alloced nfapi_ul_tti_request structure\n"); + return; + } + + int unpack_result = nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, req, sizeof(nfapi_nr_ul_tti_request_t), &(pnf_p7->_public.codec_config)); + + if(unpack_result == 0) + { + if(pthread_mutex_lock(&(pnf_p7->mutex)) != 0) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to lock mutex\n"); + return; + } + + if(is_nr_p7_request_in_window(req->SFN,req->Slot, "ul_tti_request", pnf_p7)) + { + uint32_t sfn_slot_dec = NFAPI_SFNSLOT2DEC(req->SFN,req->Slot); + uint8_t buffer_index = sfn_slot_dec % pnf_p7->_public.slot_buffer_size; + + struct timespec t; + clock_gettime(CLOCK_MONOTONIC, &t); + + NFAPI_TRACE(NFAPI_TRACE_INFO,"%s() %ld.%09ld POPULATE UL_TTI_REQ sfn_slot:%d buffer_index:%d\n", __FUNCTION__, t.tv_sec, t.tv_nsec, sfn_slot_dec, buffer_index); + + if(pnf_p7->slot_buffer[buffer_index].ul_tti_req != 0) + { + //NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] Freeing ul_config_req at index %d (%d/%d)", + // pMyPhyInfo->sfnSf, bufferIdx, + // SFNSF2SFN(dreq->sfn_sf), SFNSF2SF(dreq->sfn_sf)); + + deallocate_nfapi_ul_tti_request(pnf_p7->slot_buffer[buffer_index].ul_tti_req, pnf_p7); + } + + pnf_p7->slot_buffer[buffer_index].sfn = req->SFN; + pnf_p7->slot_buffer[buffer_index].slot = req->Slot; + pnf_p7->slot_buffer[buffer_index].ul_tti_req = req; + + pnf_p7->stats.ul_tti_ontime++; + } + else + { + NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] NOT storing ul_tti_req OUTSIDE OF TRANSMIT BUFFER WINDOW SFN/SLOT %d\n", NFAPI_SFNSLOT2DEC(pnf_p7->sfn,pnf_p7->slot), NFAPI_SFNSLOT2DEC(req->SFN,req->Slot)); + deallocate_nfapi_ul_tti_request(req, pnf_p7); + + if(pnf_p7->_public.timing_info_mode_aperiodic) + { + pnf_p7->timing_info_aperiodic_send = 1; + } + + pnf_p7->stats.ul_tti_late++; + } + + if(pthread_mutex_unlock(&(pnf_p7->mutex)) != 0) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to unlock mutex\n"); + return; + } + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Failed to unpack ul_tti_req\n"); + deallocate_nfapi_ul_tti_request(req, pnf_p7); + } +} + void pnf_handle_ul_config_request(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7) { //NFAPI_TRACE(NFAPI_TRACE_INFO, "UL_CONFIG.req Received\n"); @@ -1107,7 +1946,79 @@ void pnf_handle_ul_config_request(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_ } } + +void pnf_handle_ul_dci_request(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7) +{ + //NFAPI_TRACE(NFAPI_TRACE_INFO, "HI_DCI0.req Received\n"); + + nfapi_nr_ul_dci_request_t* req = allocate_nfapi_ul_dci_request(pnf_p7); + + if(req == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s failed to allocate nfapi_ul_dci_request structure\n"); + return; + } + + int unpack_result = nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, req, sizeof(nfapi_nr_ul_dci_request_t), &pnf_p7->_public.codec_config); + + if(unpack_result == 0) + { + if(pthread_mutex_lock(&(pnf_p7->mutex)) != 0) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to lock mutex\n"); + return; + } + + if(is_nr_p7_request_in_window(req->SFN,req->Slot,"ul_dci_request", pnf_p7)) + { + uint32_t sfn_slot_dec = NFAPI_SFNSLOT2DEC(req->SFN,req->Slot); + uint8_t buffer_index = sfn_slot_dec % pnf_p7->_public.slot_buffer_size; + + if(pnf_p7->slot_buffer[buffer_index].ul_dci_req!= 0) + { + //NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] Freeing hi_dci0_req at index %d (%d/%d)", + // pMyPhyInfo->sfnSf, bufferIdx, + // SFNSF2SFN(dreq->sfn_sf), SFNSF2SF(dreq->sfn_sf)); + + deallocate_nfapi_ul_dci_request(pnf_p7->slot_buffer[buffer_index].ul_dci_req, pnf_p7); + } + + pnf_p7->slot_buffer[buffer_index].sfn = req->SFN; + pnf_p7->slot_buffer[buffer_index].ul_dci_req = req; + + pnf_p7->stats.ul_dci_ontime++; + + } + else + { + //NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] NOT storing hi_dci0_req SFN/SF %d/%d\n", pMyPhyInfo->sfnSf, SFNSF2SFN(req->sfn_sf), SFNSF2SF(req->sfn_sf)); + deallocate_nfapi_ul_dci_request(req, pnf_p7); + + if(pnf_p7->_public.timing_info_mode_aperiodic) + { + pnf_p7->timing_info_aperiodic_send = 1; + } + + pnf_p7->stats.ul_dci_late++; + } + + if(pthread_mutex_unlock(&(pnf_p7->mutex)) != 0) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to unlock mutex\n"); + return; + } + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Failed to unpack hi_dci0_req\n"); + deallocate_nfapi_ul_dci_request(req, pnf_p7); + } +} + + + void pnf_handle_hi_dci0_request(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7) + { //NFAPI_TRACE(NFAPI_TRACE_INFO, "HI_DCI0.req Received\n"); @@ -1175,6 +2086,87 @@ void pnf_handle_hi_dci0_request(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7 } } + +void pnf_handle_tx_data_request(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7) +{ + //NFAPI_TRACE(NFAPI_TRACE_INFO, "TX.req Received\n"); + + nfapi_nr_tx_data_request_t* req = allocate_nfapi_tx_data_request(pnf_p7); + + if(req == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s failed to alloced nfapi_tx_request structure\n"); + return; + } + + int unpack_result = nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, req, sizeof(nfapi_nr_tx_data_request_t), &pnf_p7->_public.codec_config); + if(unpack_result == 0) + { + if(pthread_mutex_lock(&(pnf_p7->mutex)) != 0) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to lock mutex\n"); + return; + } + + if(is_nr_p7_request_in_window(req->SFN, req->Slot,"tx_request", pnf_p7)) + { + uint32_t sfn_slot_dec = NFAPI_SFNSLOT2DEC(req->SFN,req->Slot); + uint8_t buffer_index = sfn_slot_dec % pnf_p7->_public.slot_buffer_size; + + struct timespec t; + clock_gettime(CLOCK_MONOTONIC, &t); + + NFAPI_TRACE(NFAPI_TRACE_INFO,"%s() %ld.%09ld POPULATE TX_DATA_REQ sfn_sf:%d buffer_index:%d\n", __FUNCTION__, t.tv_sec, t.tv_nsec, sfn_slot_dec, buffer_index); +#if 0 + if (0 && NFAPI_SFNSF2DEC(req->sfn_sf)%100==0) NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() TX_REQ.req sfn_sf:%d pdus:%d - TX_REQ is within window\n", + __FUNCTION__, + NFAPI_SFNSF2DEC(req->sfn_sf), + req->tx_request_body.number_of_pdus); +#endif + + if(pnf_p7->slot_buffer[buffer_index].tx_data_req != 0) + { + //NFAPI_TRACE(NFAPI_TRACE_NOTE, "[%d] Freeing tx_req at index %d (%d/%d)", + // pMyPhyInfo->sfnSf, bufferIdx, + // SFNSF2SFN(dreq->sfn_sf), SFNSF2SF(dreq->sfn_sf)); + + deallocate_nfapi_tx_data_request(pnf_p7->slot_buffer[buffer_index].tx_data_req, pnf_p7); + } + + pnf_p7->slot_buffer[buffer_index].sfn = req->SFN; + pnf_p7->slot_buffer[buffer_index].slot = req->Slot; + pnf_p7->slot_buffer[buffer_index].tx_data_req = req; + + pnf_p7->stats.tx_data_ontime++; + } + else + { + NFAPI_TRACE(NFAPI_TRACE_INFO,"%s() TX_DATA_REQUEST Request is outside of window REQ:SFN_SLOT:%d CURR:SFN_SLOT:%d\n", __FUNCTION__, NFAPI_SFNSLOT2DEC(req->SFN,req->Slot), NFAPI_SFNSLOT2DEC(pnf_p7->sfn,pnf_p7->slot)); + + deallocate_nfapi_tx_data_request(req, pnf_p7); + + if(pnf_p7->_public.timing_info_mode_aperiodic) + { + pnf_p7->timing_info_aperiodic_send = 1; + } + + pnf_p7->stats.tx_data_late++; + } + + if(pthread_mutex_unlock(&(pnf_p7->mutex)) != 0) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to unlock mutex\n"); + return; + } + } + else + { + deallocate_nfapi_tx_data_request(req, pnf_p7); + } +} + + + void pnf_handle_tx_request(void* pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7) { //NFAPI_TRACE(NFAPI_TRACE_INFO, "TX.req Received\n"); @@ -1437,6 +2429,29 @@ uint32_t calculate_t2(uint32_t now_time_hr, uint16_t sfn_sf, uint32_t sf_start_t return t2; } +uint32_t calculate_nr_t2(uint32_t now_time_hr, uint16_t sfn,uint16_t slot, uint32_t slot_start_time_hr) +{ + uint32_t slot_time_us = get_slot_time(now_time_hr, slot_start_time_hr); + uint32_t t2 = (NFAPI_SFNSLOT2DEC(sfn, slot) * 500) + slot_time_us; + + if (0) + { + static uint32_t prev_t2 = 0; + + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s(now_time_hr:%u sfn:%d slot:%d slot_start_time_Hr:%u) slot_time_us:%u t2:%u prev_t2:%u diff:%u\n", + __FUNCTION__, + now_time_hr, NFAPI_SFNSLOT2DEC(sfn, slot), slot_start_time_hr, + slot_time_us, + t2, + prev_t2, + t2-prev_t2); + + prev_t2 = t2; + } + + return t2; +} + uint32_t calculate_t3(uint16_t sfn_sf, uint32_t sf_start_time_hr) { uint32_t now_time_hr = pnf_get_current_time_hr(); @@ -1448,6 +2463,17 @@ uint32_t calculate_t3(uint16_t sfn_sf, uint32_t sf_start_time_hr) return t3; } +uint32_t calculate_nr_t3(uint16_t sfn, uint16_t slot, uint32_t slot_start_time_hr) +{ + uint32_t now_time_hr = pnf_get_current_time_hr(); + + uint32_t slot_time_us = get_slot_time(now_time_hr, slot_start_time_hr); + + uint32_t t3 = (NFAPI_SFNSLOT2DEC(sfn, slot) * 500) + slot_time_us; + + return t3; +} + void pnf_handle_dl_node_sync(void *pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7, uint32_t rx_hr_time) { nfapi_dl_node_sync_t dl_node_sync; @@ -1498,6 +2524,60 @@ void pnf_handle_dl_node_sync(void *pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7, u pnf_p7_pack_and_send_p7_message(pnf_p7, &(ul_node_sync.header), sizeof(ul_node_sync)); } + +void pnf_nr_handle_dl_node_sync(void *pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7, uint32_t rx_hr_time) +{ + //printf("Received DL node sync"); + + nfapi_nr_dl_node_sync_t dl_node_sync; + + //NFAPI_TRACE(NFAPI_TRACE_INFO, "DL_NODE_SYNC Received\n"); + + if (pRecvMsg == NULL || pnf_p7 == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + return; + } + + // unpack the message + if (nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, &dl_node_sync, sizeof(dl_node_sync), &pnf_p7->_public.codec_config) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__); + return; + } + + if(pthread_mutex_lock(&(pnf_p7->mutex)) != 0) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to lock mutex\n"); + return; + } + + + if (dl_node_sync.delta_sfn_slot != 0) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "Will shift Slot timing by %d on next slot\n", dl_node_sync.delta_sfn_slot); + + pnf_p7->slot_shift = dl_node_sync.delta_sfn_slot; + } + + nfapi_nr_ul_node_sync_t ul_node_sync; + memset(&ul_node_sync, 0, sizeof(ul_node_sync)); + ul_node_sync.header.message_id = NFAPI_NR_PHY_MSG_TYPE_UL_NODE_SYNC; + ul_node_sync.header.phy_id = dl_node_sync.header.phy_id; + ul_node_sync.t1 = dl_node_sync.t1; + ul_node_sync.t2 = calculate_nr_t2(rx_hr_time, pnf_p7->sfn,pnf_p7->slot, pnf_p7->slot_start_time_hr); + ul_node_sync.t3 = calculate_nr_t3(pnf_p7->sfn,pnf_p7->slot, pnf_p7->slot_start_time_hr); + + if(pthread_mutex_unlock(&(pnf_p7->mutex)) != 0) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to unlock mutex\n"); + return; + } + + pnf_nr_p7_pack_and_send_p7_message(pnf_p7, &(ul_node_sync.header), sizeof(ul_node_sync)); + //printf("\nSSent UL Node Sync sfn:%d,slot:%d\n",pnf_p7->sfn,pnf_p7->slot); +} + void pnf_dispatch_p7_message(void *pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7, uint32_t rx_hr_time) { nfapi_p7_message_header_t header; @@ -1528,7 +2608,6 @@ void pnf_dispatch_p7_message(void *pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7, case NFAPI_DL_NODE_SYNC: pnf_handle_dl_node_sync(pRecvMsg, recvMsgLen, pnf_p7, rx_hr_time); break; - case NFAPI_DL_CONFIG_REQUEST: pnf_handle_dl_config_request(pRecvMsg, recvMsgLen, pnf_p7); break; @@ -1544,7 +2623,7 @@ void pnf_dispatch_p7_message(void *pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7, case NFAPI_TX_REQUEST: pnf_handle_tx_request(pRecvMsg, recvMsgLen, pnf_p7); break; - + case NFAPI_LBT_DL_CONFIG_REQUEST: pnf_handle_lbt_dl_config_request(pRecvMsg, recvMsgLen, pnf_p7); break; @@ -1569,6 +2648,66 @@ void pnf_dispatch_p7_message(void *pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7, } } +void pnf_nr_dispatch_p7_message(void *pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7, uint32_t rx_hr_time) +{ + nfapi_p7_message_header_t header; + + // validate the input params + if(pRecvMsg == NULL || recvMsgLen < 4 || pnf_p7 == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__); + return; + } + + // unpack the message header + if (nfapi_p7_message_header_unpack(pRecvMsg, recvMsgLen, &header, sizeof(header), &pnf_p7->_public.codec_config) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unpack message header failed, ignoring\n"); + return; + } + + // ensure the message is sensible + if (recvMsgLen < 8 || pRecvMsg == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_WARN, "Invalid message size: %d, ignoring\n", recvMsgLen); + return; + } + + switch (header.message_id) + { + case NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC: + pnf_nr_handle_dl_node_sync(pRecvMsg, recvMsgLen, pnf_p7, rx_hr_time); + break; + + case NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST: + //printf("\nEntering pnf_handle_dl_tti_request sfn=%d,slot=%d \n",pnf_p7->sfn,pnf_p7->slot); + pnf_handle_dl_tti_request(pRecvMsg, recvMsgLen, pnf_p7); + break; + case NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST: + pnf_handle_ul_tti_request(pRecvMsg, recvMsgLen, pnf_p7); + break; + case NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST: + pnf_handle_ul_dci_request(pRecvMsg, recvMsgLen, pnf_p7); + break; + case NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST: + pnf_handle_tx_data_request(pRecvMsg, recvMsgLen, pnf_p7); + break; + default: + { + if(header.message_id >= NFAPI_VENDOR_EXT_MSG_MIN && + header.message_id <= NFAPI_VENDOR_EXT_MSG_MAX) + { + pnf_handle_p7_vendor_extension(pRecvMsg, recvMsgLen, pnf_p7, header.message_id); + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s P7 Unknown message ID %d\n", __FUNCTION__, header.message_id); + } + } + break; + } +} + void pnf_handle_p7_message(void *pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7, uint32_t rx_hr_time) { nfapi_p7_message_header_t messageHeader; @@ -1674,6 +2813,114 @@ void pnf_handle_p7_message(void *pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7, ui pnf_p7_rx_reassembly_queue_remove_old_msgs(pnf_p7, &(pnf_p7->reassembly_queue), rx_hr_time, 1000); } + +void pnf_nr_handle_p7_message(void *pRecvMsg, int recvMsgLen, pnf_p7_t* pnf_p7, uint32_t rx_hr_time) +{ + nfapi_p7_message_header_t messageHeader; + + // validate the input params + if(pRecvMsg == NULL || recvMsgLen < 4 || pnf_p7 == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "pnf_handle_p7_message: invalid input params (%d %d %d)\n", pRecvMsg, recvMsgLen, pnf_p7); + return; + } + + // unpack the message header + if (nfapi_p7_message_header_unpack(pRecvMsg, recvMsgLen, &messageHeader, sizeof(nfapi_p7_message_header_t), &pnf_p7->_public.codec_config) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unpack message header failed, ignoring\n"); + return; + } + + uint8_t m = NFAPI_P7_GET_MORE(messageHeader.m_segment_sequence); + uint8_t sequence_num = NFAPI_P7_GET_SEQUENCE(messageHeader.m_segment_sequence); + uint8_t segment_num = NFAPI_P7_GET_SEGMENT(messageHeader.m_segment_sequence); + + if(pnf_p7->_public.checksum_enabled) + { + uint32_t checksum = nfapi_p7_calculate_checksum(pRecvMsg, recvMsgLen); + if(checksum != messageHeader.checksum) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Checksum verification failed %d %d\n", checksum, messageHeader.checksum); + return; + } + } + + if(m == 0 && segment_num == 0) + { + // we have a complete message + // ensure the message is sensible + if (recvMsgLen < 8 || pRecvMsg == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_WARN, "Invalid message size: %d, ignoring\n", recvMsgLen); + return; + } + + pnf_nr_dispatch_p7_message(pRecvMsg, recvMsgLen, pnf_p7, rx_hr_time); + } + else + { + pnf_p7_rx_message_t* rx_msg = pnf_p7_rx_reassembly_queue_add_segment(pnf_p7, &(pnf_p7->reassembly_queue), rx_hr_time, sequence_num, segment_num, m, pRecvMsg, recvMsgLen); + + if(rx_msg->num_segments_received == rx_msg->num_segments_expected) + { + // send the buffer on + uint16_t i = 0; + uint16_t length = 0; + for(i = 0; i < rx_msg->num_segments_expected; ++i) + { + length += rx_msg->segments[i].length - (i > 0 ? NFAPI_P7_HEADER_LENGTH : 0); + } + + if(pnf_p7->reassemby_buffer_size < length) + { + pnf_p7_free(pnf_p7, pnf_p7->reassemby_buffer); + pnf_p7->reassemby_buffer = 0; + } + + if(pnf_p7->reassemby_buffer == 0) + { + NFAPI_TRACE(NFAPI_TRACE_NOTE, "Resizing PNF_P7 Reassembly buffer %d->%d\n", pnf_p7->reassemby_buffer_size, length); + pnf_p7->reassemby_buffer = (uint8_t*)pnf_p7_malloc(pnf_p7, length); + + if(pnf_p7->reassemby_buffer == 0) + { + NFAPI_TRACE(NFAPI_TRACE_NOTE, "Failed to allocate PNF_P7 reassemby buffer len:%d\n", length); + return; + } + memset(pnf_p7->reassemby_buffer, 0, length); + pnf_p7->reassemby_buffer_size = length; + } + + uint16_t offset = 0; + for(i = 0; i < rx_msg->num_segments_expected; ++i) + { + if(i == 0) + { + memcpy(pnf_p7->reassemby_buffer, rx_msg->segments[i].buffer, rx_msg->segments[i].length); + offset += rx_msg->segments[i].length; + } + else + { + memcpy(pnf_p7->reassemby_buffer + offset, rx_msg->segments[i].buffer + NFAPI_P7_HEADER_LENGTH, rx_msg->segments[i].length - NFAPI_P7_HEADER_LENGTH); + offset += rx_msg->segments[i].length - NFAPI_P7_HEADER_LENGTH; + } + } + + + pnf_nr_dispatch_p7_message(pnf_p7->reassemby_buffer, length, pnf_p7, rx_msg->rx_hr_time); + + + // delete the structure + pnf_p7_rx_reassembly_queue_remove_msg(pnf_p7, &(pnf_p7->reassembly_queue), rx_msg); + } + } + + pnf_p7_rx_reassembly_queue_remove_old_msgs(pnf_p7, &(pnf_p7->reassembly_queue), rx_hr_time, 1000); + +} + + void pnf_nfapi_p7_read_dispatch_message(pnf_p7_t* pnf_p7, uint32_t now_hr_time) { int recvfrom_result = 0; @@ -1708,6 +2955,7 @@ void pnf_nfapi_p7_read_dispatch_message(pnf_p7_t* pnf_p7, uint32_t now_hr_time) if(recvfrom_result > 0) { pnf_handle_p7_message(pnf_p7->rx_message_buffer, recvfrom_result, pnf_p7, now_hr_time); + //printf("\npnf_handle_p7_message sfn=%d,slot=%d\n",pnf_p7->sfn,pnf_p7->slot); } } else if(recvfrom_result == 0) @@ -1735,6 +2983,70 @@ void pnf_nfapi_p7_read_dispatch_message(pnf_p7_t* pnf_p7, uint32_t now_hr_time) while(recvfrom_result > 0); } +void pnf_nr_nfapi_p7_read_dispatch_message(pnf_p7_t* pnf_p7, uint32_t now_hr_time) +{ + int recvfrom_result = 0; + struct sockaddr_in remote_addr; + socklen_t remote_addr_size = sizeof(remote_addr); + remote_addr.sin_family = 2; //hardcoded + + do + { + // peek the header + uint8_t header_buffer[NFAPI_P7_HEADER_LENGTH]; + recvfrom_result = recvfrom(pnf_p7->p7_sock, header_buffer, NFAPI_P7_HEADER_LENGTH, MSG_DONTWAIT | MSG_PEEK, (struct sockaddr*)&remote_addr, &remote_addr_size); + + if(recvfrom_result > 0) + { + // get the segment size + nfapi_p7_message_header_t header; + nfapi_p7_message_header_unpack(header_buffer, NFAPI_P7_HEADER_LENGTH, &header, 34, 0); + + // resize the buffer if we have a large segment + if(header.message_length > pnf_p7->rx_message_buffer_size) + { + NFAPI_TRACE(NFAPI_TRACE_NOTE, "reallocing rx buffer %d\n", header.message_length); + pnf_p7->rx_message_buffer = realloc(pnf_p7->rx_message_buffer, header.message_length); + pnf_p7->rx_message_buffer_size = header.message_length; + } + + // read the segment + recvfrom_result = recvfrom(pnf_p7->p7_sock, pnf_p7->rx_message_buffer, header.message_length, MSG_DONTWAIT, (struct sockaddr*)&remote_addr, &remote_addr_size); + + now_hr_time = pnf_get_current_time_hr(); //DJP - moved to here - get closer timestamp??? + + if(recvfrom_result > 0) + { + pnf_nr_handle_p7_message(pnf_p7->rx_message_buffer, recvfrom_result, pnf_p7, now_hr_time); + //printf("\npnf_handle_p7_message sfn=%d,slot=%d\n",pnf_p7->sfn,pnf_p7->slot); + } + } + else if(recvfrom_result == 0) + { + // recv zero length message + recvfrom_result = recvfrom(pnf_p7->p7_sock, header_buffer, 0, MSG_DONTWAIT, (struct sockaddr*)&remote_addr, &remote_addr_size); + } + + if(recvfrom_result == -1) + { + if(errno == EAGAIN || errno == EWOULDBLOCK) + { + // return to the select + //NFAPI_TRACE(NFAPI_TRACE_WARN, "%s recvfrom would block :%d\n", __FUNCTION__, errno); + } + else + { + NFAPI_TRACE(NFAPI_TRACE_WARN, "%s recvfrom failed errno:%d\n", __FUNCTION__, errno); + } + } + + // need to update the time as we would only use the value from the + // select + } + while(recvfrom_result > 0); +} + + int pnf_p7_message_pump(pnf_p7_t* pnf_p7) { @@ -1786,7 +3098,7 @@ int pnf_p7_message_pump(pnf_p7_t* pnf_p7) struct sockaddr_in addr; memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; - addr.sin_port = htons(pnf_p7->_public.local_p7_port); + addr.sin_port = pnf_p7->_public.local_p7_port; if(pnf_p7->_public.local_p7_addr == 0) { @@ -1827,6 +3139,9 @@ int pnf_p7_message_pump(pnf_p7_t* pnf_p7) uint32_t now_hr_time = pnf_get_current_time_hr(); + + + if(selectRetval == 0) { // timeout @@ -1845,7 +3160,8 @@ int pnf_p7_message_pump(pnf_p7_t* pnf_p7) continue; } - if(FD_ISSET(pnf_p7->p7_sock, &rfds)) + if(FD_ISSET(pnf_p7->p7_sock, &rfds)) + { pnf_nfapi_p7_read_dispatch_message(pnf_p7, now_hr_time); } @@ -1870,3 +3186,143 @@ int pnf_p7_message_pump(pnf_p7_t* pnf_p7) return 0; } + +int pnf_nr_p7_message_pump(pnf_p7_t* pnf_p7) +{ + + // initialize the mutex lock + if(pthread_mutex_init(&(pnf_p7->mutex), NULL) != 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After P7 mutex init: %d\n", errno); + return -1; + } + + if(pthread_mutex_init(&(pnf_p7->pack_mutex), NULL) != 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After P7 mutex init: %d\n", errno); + return -1; + } + + // create the pnf p7 socket + if ((pnf_p7->p7_sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After P7 socket errno: %d\n", errno); + return -1; + } + NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF P7 socket created (%d)...\n", pnf_p7->p7_sock); + + // configure the UDP socket options + int reuseaddr_enable = 1; + if (setsockopt(pnf_p7->p7_sock, SOL_SOCKET, SO_REUSEADDR, &reuseaddr_enable, sizeof(int)) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "PNF P7 setsockopt (SOL_SOCKET, SO_REUSEADDR) failed errno: %d\n", errno); + return -1; + } + +/* + int reuseport_enable = 1; + if (setsockopt(pnf_p7->p7_sock, SOL_SOCKET, SO_REUSEPORT, &reuseport_enable, sizeof(int)) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "PNF P7 setsockopt (SOL_SOCKET, SO_REUSEPORT) failed errno: %d\n", errno); + return -1; + } +*/ + + int iptos_value = FAPI2_IP_DSCP << 2; + if (setsockopt(pnf_p7->p7_sock, IPPROTO_IP, IP_TOS, &iptos_value, sizeof(iptos_value)) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "PNF P7 setsockopt (IPPROTO_IP, IP_TOS) failed errno: %d\n", errno); + return -1; + } + + struct sockaddr_in addr; + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = pnf_p7->_public.local_p7_port; + + if(pnf_p7->_public.local_p7_addr == 0) + { + addr.sin_addr.s_addr = INADDR_ANY; + } + else + { + //addr.sin_addr.s_addr = inet_addr(pnf_p7->_public.local_p7_addr); + if(inet_aton(pnf_p7->_public.local_p7_addr, &addr.sin_addr) == -1) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "inet_aton failed\n"); + } + } + + + NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF P7 binding %d too %s:%d\n", pnf_p7->p7_sock, inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); + if (bind(pnf_p7->p7_sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "PNF_P7 bind error fd:%d errno: %d\n", pnf_p7->p7_sock, errno); + return -1; + } + NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF P7 bind succeeded...\n"); + + while(pnf_p7->terminate == 0) + { + fd_set rfds; + int selectRetval = 0; + + // select on a timeout and then get the message + FD_ZERO(&rfds); + FD_SET(pnf_p7->p7_sock, &rfds); + + struct timeval timeout; + timeout.tv_sec = 1; + timeout.tv_usec = 0; + + selectRetval = select(pnf_p7->p7_sock+1, &rfds, NULL, NULL, &timeout); + + uint32_t now_hr_time = pnf_get_current_time_hr(); + + + + + if(selectRetval == 0) + { + // timeout + continue; + } + else if (selectRetval == -1 && (errno == EINTR)) + { + // interrupted by signal + NFAPI_TRACE(NFAPI_TRACE_WARN, "PNF P7 Signal Interrupt %d\n", errno); + continue; + } + else if (selectRetval == -1) + { + NFAPI_TRACE(NFAPI_TRACE_WARN, "PNF P7 select() failed\n"); + sleep(1); + continue; + } + + if(FD_ISSET(pnf_p7->p7_sock, &rfds)) + + { + pnf_nr_nfapi_p7_read_dispatch_message(pnf_p7, now_hr_time); + } + } + NFAPI_TRACE(NFAPI_TRACE_ERROR, "PNF_P7 Terminating..\n"); + + // close the connection and socket + if (close(pnf_p7->p7_sock) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "close failed errno: %d\n", errno); + } + + if(pthread_mutex_destroy(&(pnf_p7->pack_mutex)) != 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "mutex destroy failed errno: %d\n", errno); + } + + if(pthread_mutex_destroy(&(pnf_p7->mutex)) != 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "mutex destroy failed errno: %d\n", errno); + } + + return 0; +} diff --git a/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c b/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c index 24e73ae9b3..efcb60ce96 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c +++ b/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c @@ -31,7 +31,7 @@ nfapi_pnf_p7_config_t* nfapi_pnf_p7_config_create() _this->_public.segment_size = 1400; _this->max_num_segments = 8; - _this->_public.subframe_buffer_size = 8; + _this->_public.subframe_buffer_size = 8;// TODO: Initialize the slot_buffer size _this->_public.timing_info_mode_periodic = 1; _this->_public.timing_info_period = 32; _this->_public.timing_info_mode_aperiodic = 1; @@ -76,6 +76,26 @@ int nfapi_pnf_p7_start(nfapi_pnf_p7_config_t* config) return 0; } +int nfapi_nr_pnf_p7_start(nfapi_pnf_p7_config_t* config) +{ + // Verify that config is not null + if(config == 0) + return -1; + + // Make sure to set the defined trace function before using NFAPI_TRACE + if(config->trace) + nfapi_trace_g = config->trace; + + pnf_p7_t* _this = (pnf_p7_t*)(config); + + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__); + + pnf_nr_p7_message_pump(_this); + + return 0; +} + + int nfapi_pnf_p7_stop(nfapi_pnf_p7_config_t* config) { // Verify that config is not null @@ -88,6 +108,16 @@ int nfapi_pnf_p7_stop(nfapi_pnf_p7_config_t* config) return 0; } +int nfapi_pnf_p7_slot_ind(nfapi_pnf_p7_config_t* config, uint16_t phy_id, uint16_t sfn, uint16_t slot) +{ + // Verify that config is not null + if(config == 0) + return -1; + + pnf_p7_t* _this = (pnf_p7_t*)(config); + + return pnf_p7_slot_ind(_this, phy_id, sfn, slot); +} int nfapi_pnf_p7_subframe_ind(nfapi_pnf_p7_config_t* config, uint16_t phy_id, uint16_t sfn_sf) { diff --git a/nfapi/open-nFAPI/pnf/tests/pnf_cunit_main.c b/nfapi/open-nFAPI/pnf/tests/pnf_cunit_main.c index d2ab031ad4..bd6bedbea5 100644 --- a/nfapi/open-nFAPI/pnf/tests/pnf_cunit_main.c +++ b/nfapi/open-nFAPI/pnf/tests/pnf_cunit_main.c @@ -48,6 +48,9 @@ typedef struct phy_info uint8_t enabled; uint16_t phy_id; uint16_t sfn_sf; + uint16_t sfn; + uint16_t slot; + pthread_t thread; @@ -1207,6 +1210,12 @@ void send_dl_subframe_msgs_interleaved(int p7Sock, int phy_id, struct sockaddr_i //free(req.tx_request_body.tx_pdu_list); } +void send_slot_indication(phy_info_t* phy_info) +{ + // DONE: add sfn and slot as members in the phy_info + nfapi_pnf_p7_slot_ind(phy_info->config, phy_info->phy_id, phy_info->sfn, phy_info->slot); +} + void send_subframe_indication(phy_info_t* phy_info) { nfapi_pnf_p7_subframe_ind(phy_info->config, phy_info->phy_id, phy_info->sfn_sf); diff --git a/nfapi/open-nFAPI/vnf/inc/vnf.h b/nfapi/open-nFAPI/vnf/inc/vnf.h index 4fd8d2b91d..b16b842606 100644 --- a/nfapi/open-nFAPI/vnf/inc/vnf.h +++ b/nfapi/open-nFAPI/vnf/inc/vnf.h @@ -35,9 +35,13 @@ typedef struct int vnf_pack_and_send_p5_message(vnf_t* vnf, uint16_t p5_idx, nfapi_p4_p5_message_header_t* msg, uint16_t msg_len); +int vnf_nr_pack_and_send_p5_message(vnf_t* vnf, uint16_t p5_idx, nfapi_p4_p5_message_header_t* msg, uint16_t msg_len); + int vnf_pack_and_send_p4_message(vnf_t* vnf, uint16_t p5_idx, nfapi_p4_p5_message_header_t* msg, uint16_t msg_len); int vnf_read_dispatch_message(nfapi_vnf_config_t* config, nfapi_vnf_pnf_info_t* pnf); +int vnf_nr_read_dispatch_message(nfapi_vnf_config_t* config, nfapi_vnf_pnf_info_t* pnf); + void nfapi_vnf_phy_info_list_add(nfapi_vnf_config_t* config, nfapi_vnf_phy_info_t* info); nfapi_vnf_phy_info_t* nfapi_vnf_phy_info_list_find(nfapi_vnf_config_t* config, uint16_t phy_id); diff --git a/nfapi/open-nFAPI/vnf/inc/vnf_p7.h b/nfapi/open-nFAPI/vnf/inc/vnf_p7.h index fc2ab4e6b5..ad1c5e7944 100644 --- a/nfapi/open-nFAPI/vnf/inc/vnf_p7.h +++ b/nfapi/open-nFAPI/vnf/inc/vnf_p7.h @@ -77,6 +77,9 @@ typedef struct nfapi_vnf_p7_connection_info { int32_t sf_offset_filtered; int32_t sf_offset_trend; int32_t sf_offset; + int32_t slot_offset; + int32_t slot_offset_trend; + int32_t slot_offset_filtered; uint16_t zero_count; int32_t adjustment; int32_t insync_minor_adjustment; @@ -85,8 +88,10 @@ typedef struct nfapi_vnf_p7_connection_info { uint32_t previous_t1; uint32_t previous_t2; int32_t previous_sf_offset_filtered; - + int32_t previous_slot_offset_filtered; int sfn_sf; + int sfn; + int slot; int socket; struct sockaddr_in local_addr; @@ -111,6 +116,7 @@ typedef struct { nfapi_vnf_p7_connection_info_t* p7_connections; int socket; uint32_t sf_start_time_hr; + uint32_t slot_start_time_hr; uint8_t* rx_message_buffer; // would this be better put in the p7 conenction info? uint16_t rx_message_buffer_size; @@ -120,14 +126,19 @@ uint32_t vnf_get_current_time_hr(void); uint16_t increment_sfn_sf(uint16_t sfn_sf); int vnf_sync(vnf_p7_t* vnf_p7, nfapi_vnf_p7_connection_info_t* p7_info); +int vnf_nr_sync(vnf_p7_t* vnf_p7, nfapi_vnf_p7_connection_info_t* p7_info); + int send_mac_subframe_indications(vnf_p7_t* config); +int send_mac_slot_indications(vnf_p7_t* config); int vnf_p7_read_dispatch_message(vnf_p7_t* vnf_p7 ); +int vnf_nr_p7_read_dispatch_message(vnf_p7_t* vnf_p7 ); void vnf_p7_connection_info_list_add(vnf_p7_t* vnf_p7, nfapi_vnf_p7_connection_info_t* node); nfapi_vnf_p7_connection_info_t* vnf_p7_connection_info_list_find(vnf_p7_t* vnf_p7, uint16_t phy_id); nfapi_vnf_p7_connection_info_t* vnf_p7_connection_info_list_delete(vnf_p7_t* vnf_p7, uint16_t phy_id); int vnf_p7_pack_and_send_p7_msg(vnf_p7_t* vnf_p7, nfapi_p7_message_header_t* header); +int vnf_nr_p7_pack_and_send_p7_msg(vnf_p7_t* vnf_p7, nfapi_p7_message_header_t* header); void vnf_p7_release_msg(vnf_p7_t* vnf_p7, nfapi_p7_message_header_t* header); void vnf_p7_release_pdu(vnf_p7_t* vnf_p7, void* pdu); diff --git a/nfapi/open-nFAPI/vnf/public_inc/nfapi_vnf_interface.h b/nfapi/open-nFAPI/vnf/public_inc/nfapi_vnf_interface.h index 5abf6b75c3..518b01864e 100644 --- a/nfapi/open-nFAPI/vnf/public_inc/nfapi_vnf_interface.h +++ b/nfapi/open-nFAPI/vnf/public_inc/nfapi_vnf_interface.h @@ -19,6 +19,7 @@ #include "nfapi_interface.h" #include "nfapi_nr_interface_scf.h" +#include "nfapi_nr_interface.h" #include "debug.h" @@ -120,6 +121,7 @@ typedef struct nfapi_vnf_config * * \todo Do we need to send the address information of the PNF? */ + int (*pnf_nr_connection_indication)(nfapi_vnf_config_t* config, int p5_idx); int (*pnf_connection_indication)(nfapi_vnf_config_t* config, int p5_idx); /*! \brief Callback indicating that a pnf has lost connection @@ -160,6 +162,7 @@ typedef struct nfapi_vnf_config * then the substructure pointers should be set to 0 and then the client should * use the codec_config.deallocate function to release it at a future point */ + int (*pnf_nr_param_resp)(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_pnf_param_response_t* resp); int (*pnf_param_resp)(nfapi_vnf_config_t* config, int p5_idx, nfapi_pnf_param_response_t* resp); /*! A callback for the PNF_CONFIG.resp @@ -182,7 +185,8 @@ typedef struct nfapi_vnf_config * use the codec_config.deallocate function to release it at a future point */ int (*pnf_config_resp)(nfapi_vnf_config_t* config, int p5_idx, nfapi_pnf_config_response_t* resp); - + int (*pnf_nr_config_resp)(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_pnf_config_response_t* resp); + /*! A callback for the PNF_START.resp * \param config A pointer to the vnf configuration * \param p5_idx The p5 index used to indicate a particular pnf p5 connection @@ -203,7 +207,8 @@ typedef struct nfapi_vnf_config * use the codec_config.deallocate function to release it at a future point */ int (*pnf_start_resp)(nfapi_vnf_config_t* config, int p5_idx, nfapi_pnf_start_response_t* resp); - + int (*pnf_nr_start_resp)(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_pnf_start_response_t* resp); + /*! A callback for the PNF_STOP.resp * \param config A pointer to the vnf configuration * \param p5_idx The p5 index used to indicate a particular pnf p5 connection @@ -249,6 +254,7 @@ typedef struct nfapi_vnf_config * use the codec_config.deallocate function to release it at a future point */ int (*param_resp)(nfapi_vnf_config_t* config, int p5_idx, nfapi_param_response_t* resp); + int (*nr_param_resp)(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_param_response_scf_t* resp); /*! A callback for the CONFIG.response * \param config A pointer to the vnf configuration @@ -266,8 +272,9 @@ typedef struct nfapi_vnf_config * then the substructure pointers should be set to 0 and then the client should * use the codec_config.deallocate function to release it at a future point */ + int (*nr_config_resp)(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_config_response_scf_t* resp); int (*config_resp)(nfapi_vnf_config_t* config, int p5_idx, nfapi_config_response_t* resp); - + /*! A callback for the START.resp * \param config A pointer to the vnf configuration * \param p5_idx The p5 index used to indicate a particular pnf p5 connection @@ -285,6 +292,7 @@ typedef struct nfapi_vnf_config * use the codec_config.deallocate function to release it at a future point */ int (*start_resp)(nfapi_vnf_config_t* config, int p5_idx, nfapi_start_response_t* resp); + int (*nr_start_resp)(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_start_response_scf_t* resp); /*! A callback for the STOP.resp * \param config A pointer to the vnf configuration @@ -469,6 +477,8 @@ void nfapi_vnf_config_destory(nfapi_vnf_config_t* config); * * This function will not return untill nfapi_vnf_stop is called */ +int nfapi_nr_vnf_start(nfapi_vnf_config_t* config); + int nfapi_vnf_start(nfapi_vnf_config_t* config); /*! Stop the VNF library. @@ -500,6 +510,7 @@ int nfapi_vnf_allocate_phy(nfapi_vnf_config_t* config, int p5_idx, uint16_t* phy * \return 0 means success, -1 failure */ int nfapi_vnf_pnf_param_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_pnf_param_request_t* req); +int nfapi_nr_vnf_pnf_param_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_pnf_param_request_t* req); /*! Send the PNF_CONFIG.request * \param config A pointer to a vnf config @@ -508,6 +519,7 @@ int nfapi_vnf_pnf_param_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_pnf_pa * \return 0 means success, -1 failure */ int nfapi_vnf_pnf_config_req(nfapi_vnf_config_t* config,int p5_idx, nfapi_pnf_config_request_t* req); +int nfapi_nr_vnf_pnf_config_req(nfapi_vnf_config_t* config,int p5_idx, nfapi_nr_pnf_config_request_t* req); /*! Send the PNF_START.request * \param config A pointer to a vnf config @@ -516,6 +528,7 @@ int nfapi_vnf_pnf_config_req(nfapi_vnf_config_t* config,int p5_idx, nfapi_pnf_co * \return 0 means success, -1 failure */ int nfapi_vnf_pnf_start_req(nfapi_vnf_config_t* config,int p5_idx, nfapi_pnf_start_request_t* req); +int nfapi_nr_vnf_pnf_start_req(nfapi_vnf_config_t* config,int p5_idx, nfapi_nr_pnf_start_request_t* req); /*! Send the PNF_STOP.request * \param config A pointer to a vnf config @@ -532,6 +545,7 @@ int nfapi_vnf_pnf_stop_req(nfapi_vnf_config_t* config,int p5_idx, nfapi_pnf_stop * \return 0 means success, -1 failure */ int nfapi_vnf_param_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_param_request_t* req); +int nfapi_nr_vnf_param_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_param_request_scf_t* req); /*! Send the CONFIG.request * \param config A pointer to a vnf config @@ -539,6 +553,7 @@ int nfapi_vnf_param_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_param_requ * \param req A pointer to a CONFIG.request message structure * \return 0 means success, -1 failure */ +int nfapi_nr_vnf_config_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_config_request_scf_t* req); int nfapi_vnf_config_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_config_request_t* req); /*! Send the START.request @@ -548,6 +563,7 @@ int nfapi_vnf_config_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_config_re * \return 0 means success, -1 failure */ int nfapi_vnf_start_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_start_request_t* req); +int nfapi_nr_vnf_start_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_start_request_scf_t* req); /*! Send the STOP.request * \param config A pointer to a vnf config @@ -692,6 +708,7 @@ typedef struct nfapi_vnf_p7_config */ int (*subframe_indication)(struct nfapi_vnf_p7_config* config, uint16_t phy_id, uint16_t sfn_sf); + int (*slot_indication)(struct nfapi_vnf_p7_config* config, uint16_t phy_id, uint16_t sfn, uint16_t slot); /*! A callback for the HARQ.indication * \param config A pointer to the vnf p7 configuration @@ -885,6 +902,8 @@ void nfapi_vnf_p7_config_destory(nfapi_vnf_p7_config_t* config); */ int nfapi_vnf_p7_start(nfapi_vnf_p7_config_t* config); +int nfapi_nr_vnf_p7_start(nfapi_vnf_p7_config_t* config); + /*! Stop the VNF P7 library. * \param config A pointer to an vnf p7 configuration structure @@ -950,7 +969,7 @@ int nfapi_vnf_p7_nr_dl_config_req(nfapi_vnf_p7_config_t* config, nfapi_nr_dl_tti * may be released after this function call has returned or at a later pointer */ int nfapi_vnf_p7_ul_config_req(nfapi_vnf_p7_config_t* config, nfapi_ul_config_request_t* req); - +int nfapi_vnf_p7_ul_tti_req(nfapi_vnf_p7_config_t* config, nfapi_nr_ul_tti_request_t* req); /*! Send the HI_DCI0.request * \param config A pointer to the vnf p7 configuration * \param req A data structure for the decoded HI_DCI0.request. @@ -960,7 +979,7 @@ int nfapi_vnf_p7_ul_config_req(nfapi_vnf_p7_config_t* config, nfapi_ul_config_re * may be released after this function call has returned or at a later pointer */ int nfapi_vnf_p7_hi_dci0_req(nfapi_vnf_p7_config_t* config, nfapi_hi_dci0_request_t* req); - +int nfapi_vnf_p7_ul_dci_req(nfapi_vnf_p7_config_t* config, nfapi_nr_ul_dci_request_t* req); /*! Send the TX.req * \param config A pointer to the vnf p7 configuration * \param req A data structure for the decoded HI_DCI0.request. @@ -970,7 +989,7 @@ int nfapi_vnf_p7_hi_dci0_req(nfapi_vnf_p7_config_t* config, nfapi_hi_dci0_reques * may be released after this function call has returned or at a later pointer */ int nfapi_vnf_p7_tx_req(nfapi_vnf_p7_config_t* config, nfapi_tx_request_t* req); - +int nfapi_vnf_p7_tx_data_req(nfapi_vnf_p7_config_t* config, nfapi_nr_tx_data_request_t* req); /*! Send the LBT_DL_CONFIG.requst * \param config A pointer to the vnf p7 configuration * \param req A data structure for the decoded LBT_DL_CONFIG.request. diff --git a/nfapi/open-nFAPI/vnf/src/vnf.c b/nfapi/open-nFAPI/vnf/src/vnf.c index 6800ee21d2..7fee47d6d5 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf.c +++ b/nfapi/open-nFAPI/vnf/src/vnf.c @@ -21,9 +21,12 @@ #include #include #include +#include #include #include "vnf.h" +#include "nfapi_nr_interface.h" +#include "nfapi_nr_interface_scf.h" void* vnf_malloc(nfapi_vnf_config_t* config, size_t size) @@ -101,6 +104,39 @@ nfapi_vnf_pnf_info_t* nfapi_vnf_pnf_list_find(nfapi_vnf_config_t* config, int p5 return 0; } +void vnf_nr_handle_pnf_param_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx) +{ + // ensure it's valid + if (pRecvMsg == NULL || config == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s : NULL parameters\n", __FUNCTION__); + } + else + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "Received PNF_PARAM.reponse\n"); + + nfapi_nr_pnf_param_response_t msg; + + // unpack the message + if (nfapi_nr_p5_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >= 0) + { + // Invoke the call back + if(config->pnf_nr_param_resp) + { + (config->pnf_nr_param_resp)(config, p5_idx, &msg); + } + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__); + } + + // make sure to release any dyanmic part of the message + if(msg.vendor_extension) + config->codec_config.deallocate(msg.vendor_extension); + } +} + void vnf_handle_pnf_param_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx) { // ensure it's valid @@ -134,6 +170,40 @@ void vnf_handle_pnf_param_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_con } } + +void vnf_nr_handle_pnf_config_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx) +{ + // ensure it's valid + if (pRecvMsg == NULL || config == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + } + else + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "Received PNF_CONFIG_RESPONSE\n"); + + nfapi_nr_pnf_config_response_t msg; + + // unpack the message + if (nfapi_nr_p5_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >= 0) + { + // Invoke the call back + if(config->pnf_nr_config_resp) + { + (config->pnf_nr_config_resp)(config, p5_idx, &msg); + } + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__); + } + + // make sure to release any dyanmic part of the message + if(msg.vendor_extension) + config->codec_config.deallocate(msg.vendor_extension); + } +} + void vnf_handle_pnf_config_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx) { // ensure it's valid @@ -167,6 +237,38 @@ void vnf_handle_pnf_config_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_co } } +void vnf_nr_handle_pnf_start_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx) +{ + // ensure it's valid + if (pRecvMsg == NULL || config == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + } + else + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "Received PNF_START_RESPONSE\n"); + + nfapi_nr_pnf_start_response_t msg; + + // unpack the message + if (nfapi_nr_p5_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >= 0) + { + if(config->pnf_nr_start_resp) + { + (config->pnf_nr_start_resp)(config, p5_idx, &msg); + } + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__); + } + + // make sure to release any dyanmic part of the message + if(msg.vendor_extension) + config->codec_config.deallocate(msg.vendor_extension); + } +} + void vnf_handle_pnf_start_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx) { // ensure it's valid @@ -298,8 +400,113 @@ void vnf_handle_param_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_ } } +void vnf_nr_handle_param_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx) +{ + + // ensure it's valid + if (pRecvMsg == NULL || config == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + } + else + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "Received PARAM_RESPONSE\n"); + + nfapi_nr_param_response_scf_t msg; + + // unpack the message + if (nfapi_nr_p5_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >= 0) + { + + if (msg.error_code == NFAPI_NR_PARAM_MSG_OK) + { + nfapi_vnf_phy_info_t* phy_info = nfapi_vnf_phy_info_list_find(config, msg.header.phy_id); + + if(msg.nfapi_config.p7_pnf_address_ipv4.tl.tag) + { + struct sockaddr_in sockAddr; + + (void)memcpy(&sockAddr.sin_addr.s_addr, msg.nfapi_config.p7_pnf_address_ipv4.address, NFAPI_IPV4_ADDRESS_LENGTH); + NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF P7 IPv4 address: %s\n", inet_ntoa(sockAddr.sin_addr)); + + // store address + phy_info->p7_pnf_address.sin_addr = sockAddr.sin_addr; + } + + if(msg.nfapi_config.p7_pnf_address_ipv6.tl.tag) + { + struct sockaddr_in6 sockAddr6; + char addr6[64]; + (void)memcpy(&sockAddr6.sin6_addr, msg.nfapi_config.p7_pnf_address_ipv6.address, NFAPI_IPV6_ADDRESS_LENGTH); + NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF P7 IPv6 address: %s\n", inet_ntop(AF_INET6, &sockAddr6.sin6_addr, addr6, sizeof(addr6))); + } + + if (msg.nfapi_config.p7_pnf_port.tl.tag) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF P7 Port: %d\n", msg.nfapi_config.p7_pnf_port.value); + + // store port + phy_info->p7_pnf_address.sin_port = htons(msg.nfapi_config.p7_pnf_port.value); + } + } + + if(config->nr_param_resp) + { + (config->nr_param_resp)(config, p5_idx, &msg); + } + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__); + } + + // make sure to release any dyanmic part of the message + if(msg.vendor_extension) + config->codec_config.deallocate(msg.vendor_extension); + } +} + + +void vnf_nr_handle_config_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx) +{ + + // ensure it's valid + if (pRecvMsg == NULL || config == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + } + else + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "Received CONFIG_RESPONSE\n"); + + nfapi_nr_config_response_scf_t msg; + + // unpack the message + if (nfapi_nr_p5_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >=0 ) + { + // check the error code: + + if (msg.error_code == NFAPI_NR_CONFIG_MSG_OK){ + if(config->nr_config_resp) + { + (config->nr_config_resp)(config, p5_idx, &msg); + } + } + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__); + } + + // make sure to release any dyanmic part of the message + if(msg.vendor_extension) + config->codec_config.deallocate(msg.vendor_extension); + } +} + void vnf_handle_config_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx) { + // ensure it's valid if (pRecvMsg == NULL || config == NULL) { @@ -314,9 +521,13 @@ void vnf_handle_config_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config // unpack the message if (nfapi_p5_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >=0 ) { - if(config->config_resp) - { - (config->config_resp)(config, p5_idx, &msg); + // check the error code: + + if (msg.error_code == NFAPI_MSG_OK){ + if(config->config_resp) + { + (config->config_resp)(config, p5_idx, &msg); + } } } else @@ -362,6 +573,40 @@ void vnf_handle_start_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_ } } +void vnf_nr_handle_start_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx) +{ + // ensure it's valid + if (pRecvMsg == NULL || config == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: NULL parameters\n", __FUNCTION__); + } + else + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "Received START_RESPONSE\n"); + + nfapi_nr_start_response_scf_t msg; + + // unpack the message + if (nfapi_nr_p5_message_unpack(pRecvMsg, recvMsgLen, &msg, sizeof(msg), &config->codec_config) >= 0) + { // check the error code + if (msg.error_code == NFAPI_NR_START_MSG_OK){ + if(config->nr_start_resp) + { + (config->nr_start_resp)(config, p5_idx, &msg); + } + } + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: Unpack message failed, ignoring\n", __FUNCTION__); + } + + // make sure to release any dyanmic part of the message + if(msg.vendor_extension) + config->codec_config.deallocate(msg.vendor_extension); + } +} + void vnf_handle_stop_response(void *pRecvMsg, int recvMsgLen, nfapi_vnf_config_t* config, int p5_idx) { @@ -811,6 +1056,74 @@ void vnf_handle_vendor_extension(void* pRecvMsg, int recvMsgLen, nfapi_vnf_confi } } +void vnf_nr_handle_p4_p5_message(void *pRecvMsg, int recvMsgLen, int p5_idx, nfapi_vnf_config_t* config) +{ + nfapi_p4_p5_message_header_t messageHeader; + + // validate the input params + if(pRecvMsg == NULL || recvMsgLen < NFAPI_HEADER_LENGTH || config == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "vnf_handle_p4_p5_message: invalid input params\n"); + return; + } + + // unpack the message header + if (nfapi_p5_message_header_unpack(pRecvMsg, recvMsgLen, &messageHeader, sizeof(nfapi_p4_p5_message_header_t), &config->codec_config) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unpack message header failed, ignoring\n"); + return; + } + + switch (messageHeader.message_id) + { + case NFAPI_NR_PHY_MSG_TYPE_PNF_PARAM_RESPONSE: + vnf_nr_handle_pnf_param_response(pRecvMsg, recvMsgLen, config, p5_idx); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PNF_CONFIG_RESPONSE: + vnf_nr_handle_pnf_config_response(pRecvMsg, recvMsgLen, config, p5_idx); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PNF_START_RESPONSE: + vnf_nr_handle_pnf_start_response(pRecvMsg, recvMsgLen, config, p5_idx); + break; + + case NFAPI_PNF_STOP_RESPONSE: + vnf_handle_pnf_stop_response(pRecvMsg, recvMsgLen, config, p5_idx); + break; + + case NFAPI_NR_PHY_MSG_TYPE_PARAM_RESPONSE: + vnf_nr_handle_param_response(pRecvMsg, recvMsgLen, config, p5_idx); + break; + + case NFAPI_NR_PHY_MSG_TYPE_CONFIG_RESPONSE: + vnf_nr_handle_config_response(pRecvMsg, recvMsgLen, config, p5_idx); + break; + + case NFAPI_NR_PHY_MSG_TYPE_START_RESPONSE: + vnf_nr_handle_start_response(pRecvMsg, recvMsgLen, config, p5_idx); + break; + + case NFAPI_NR_PHY_MSG_TYPE_STOP_RESPONSE: + vnf_handle_stop_response(pRecvMsg, recvMsgLen, config, p5_idx); + break; + + default: + { + if(messageHeader.message_id >= NFAPI_VENDOR_EXT_MSG_MIN && + messageHeader.message_id <= NFAPI_VENDOR_EXT_MSG_MAX) + { + vnf_handle_vendor_extension(pRecvMsg, recvMsgLen, config, p5_idx, messageHeader.message_id); + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s P5 Unknown message ID %d\n", __FUNCTION__, messageHeader.message_id); + } + } + break; + } +} + void vnf_handle_p4_p5_message(void *pRecvMsg, int recvMsgLen, int p5_idx, nfapi_vnf_config_t* config) { nfapi_p4_p5_message_header_t messageHeader; @@ -926,6 +1239,137 @@ void vnf_handle_p4_p5_message(void *pRecvMsg, int recvMsgLen, int p5_idx, nfapi_ break; } } + + +int vnf_nr_read_dispatch_message(nfapi_vnf_config_t* config, nfapi_vnf_pnf_info_t* pnf) +{ + if(1) + { + int socket_connected = 1; + + // 1. Peek the message header + // 2. If the message is larger than the stack buffer then create a dynamic buffer + // 3. Read the buffer + // 4. Handle the p5 message + + uint32_t header_buffer_size = NFAPI_HEADER_LENGTH; + uint8_t header_buffer[header_buffer_size]; + + uint32_t stack_buffer_size = 32; //should it be the size of then sctp_notificatoin structure + uint8_t stack_buffer[stack_buffer_size]; + + uint8_t* dynamic_buffer = 0; + + uint8_t* read_buffer = &stack_buffer[0]; + uint32_t message_size = 0; + + struct sockaddr_in addr; + socklen_t addr_len = sizeof(addr); + + struct sctp_sndrcvinfo sndrcvinfo; + (void)memset(&sndrcvinfo, 0, sizeof(struct sctp_sndrcvinfo)); + + { + int flags = MSG_PEEK; + message_size = sctp_recvmsg(pnf->p5_sock, header_buffer, header_buffer_size, (struct sockaddr*)&addr, &addr_len, &sndrcvinfo, &flags); + + if(message_size == -1) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF Failed to peek sctp message size errno:%d\n", errno); + return 0; + } + + nfapi_p4_p5_message_header_t header; + int unpack_result = nfapi_p5_message_header_unpack(header_buffer, header_buffer_size, &header, sizeof(header), 0); + if(unpack_result < 0) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF Failed to decode message header %d\n", unpack_result); + return 0; + } + message_size = header.message_length; + + // now have the size of the mesage + } + + if(message_size > stack_buffer_size) + { + dynamic_buffer = (uint8_t*)malloc(message_size); + + if(dynamic_buffer == NULL) + { + // todo : add error mesage + NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF Failed to allocate dynamic buffer for sctp_recvmsg size:%d\n", message_size); + return -1; + } + + read_buffer = dynamic_buffer; + } + + { + int flags = 0; + (void)memset(&sndrcvinfo, 0, sizeof(struct sctp_sndrcvinfo)); + + int recvmsg_result = sctp_recvmsg(pnf->p5_sock, read_buffer, message_size, (struct sockaddr*)&addr, &addr_len, &sndrcvinfo, &flags); + if(recvmsg_result == -1) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "Failed to read sctp message size errno:%d\n", errno); + } + else + { + if (flags & MSG_NOTIFICATION) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "Notification received from %s:%u\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); + + // todo - handle the events + } + else + { + /* + NFAPI_TRACE(NFAPI_TRACE_INFO, "Received message fd:%d from %s:%u assoc:%d on stream %d, PPID %d, length %d, flags 0x%x\n", + pnf->p5_sock, + inet_ntoa(addr.sin_addr), + ntohs(addr.sin_port), + sndrcvinfo.sinfo_assoc_id, + sndrcvinfo.sinfo_stream, + ntohl(sndrcvinfo.sinfo_ppid), + message_size, + flags); + */ + + // handle now if complete message in one or more segments + if ((flags & 0x80) == 0x80) + { + // printf("\nVNF RECEIVES:\n"); + // for(int i=0; ip5_idx, config); + } + else + { + NFAPI_TRACE(NFAPI_TRACE_WARN, "sctp_recvmsg: unhandled mode with flags 0x%x\n", flags); + + // assume socket disconnected + NFAPI_TRACE(NFAPI_TRACE_WARN, "Disconnected socket\n"); + socket_connected = 0; + } + + + } + } + } + + if(dynamic_buffer) + { + free(dynamic_buffer); + } + + return socket_connected; + } +} + int vnf_read_dispatch_message(nfapi_vnf_config_t* config, nfapi_vnf_pnf_info_t* pnf) { if(1) @@ -1024,6 +1468,12 @@ int vnf_read_dispatch_message(nfapi_vnf_config_t* config, nfapi_vnf_pnf_info_t* // handle now if complete message in one or more segments if ((flags & 0x80) == 0x80) { + // printf("\nVNF RECEIVES:\n"); + // for(int i=0; ip5_idx, config); } else @@ -1051,6 +1501,12 @@ int vnf_read_dispatch_message(nfapi_vnf_config_t* config, nfapi_vnf_pnf_info_t* static int vnf_send_p5_msg(nfapi_vnf_pnf_info_t* pnf, const void *msg, int len, uint8_t stream) { + // printf("\n MESSAGE SENT: \n"); + // for(int i=0; ip5_sock, msg, len, (struct sockaddr*)&pnf->p5_pnf_sockaddr, sizeof(pnf->p5_pnf_sockaddr),1, 0, stream, 0, 4); @@ -1071,6 +1527,29 @@ static int vnf_send_p5_msg(nfapi_vnf_pnf_info_t* pnf, const void *msg, int len, return 0; } +int vnf_nr_pack_and_send_p5_message(vnf_t* vnf, uint16_t p5_idx, nfapi_p4_p5_message_header_t* msg, uint16_t msg_len) +{ + nfapi_vnf_pnf_info_t* pnf = nfapi_vnf_pnf_list_find(&(vnf->_public), p5_idx); + + if(pnf) + { + // pack the message for transmission + int packedMessageLength = nfapi_nr_p5_message_pack(msg, msg_len, vnf->tx_message_buffer, sizeof(vnf->tx_message_buffer), &vnf->_public.codec_config); + + if (packedMessageLength < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "nfapi_p5_message_pack failed with return %d\n", packedMessageLength); + return -1; + } + return vnf_send_p5_msg(pnf, vnf->tx_message_buffer, packedMessageLength, 0); + } + else + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() cannot find pnf info for p5_idx:%d\n", __FUNCTION__, p5_idx); + return -1; + } +} + int vnf_pack_and_send_p5_message(vnf_t* vnf, uint16_t p5_idx, nfapi_p4_p5_message_header_t* msg, uint16_t msg_len) { diff --git a/nfapi/open-nFAPI/vnf/src/vnf_interface.c b/nfapi/open-nFAPI/vnf/src/vnf_interface.c index 59d7f3eb4f..084c4fa485 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_interface.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_interface.c @@ -63,6 +63,418 @@ void nfapi_vnf_config_destory(nfapi_vnf_config_t* config) free(config); } +int nfapi_nr_vnf_start(nfapi_vnf_config_t* config) +{ + // Verify that config is not null + if(config == 0) + return -1; + + // Make sure to set the defined trace function before using NFAPI_TRACE + if(config->trace) + nfapi_trace_g = (nfapi_trace_fn_t)config->trace; + + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s()\n", __FUNCTION__); + + int p5ListenSock, p5Sock; + + struct sockaddr_in addr; + socklen_t addrSize; + + struct sockaddr_in6 addr6; + + struct sctp_event_subscribe events; + struct sctp_initmsg initMsg; + int noDelay; + + (void)memset(&addr, 0, sizeof(struct sockaddr_in)); + (void)memset(&addr6, 0, sizeof(struct sockaddr_in6)); + (void)memset(&events, 0, sizeof(struct sctp_event_subscribe)); + (void)memset(&initMsg, 0, sizeof(struct sctp_initmsg)); + + vnf_t* vnf = (vnf_t*)(config); + + NFAPI_TRACE(NFAPI_TRACE_INFO, "Starting P5 VNF connection on port %u\n", config->vnf_p5_port); + + /* + char * host = 0; + char * port = "4242"; + struct addrinfo hints; + bzero(&hints, sizeof(struct addrinfo)); + //hints.ai_flags=AI_PASSIVE; + //hints.ai_flags=AI_DEFAULT; + hints.ai_family=AF_UNSPEC; + //hints.ai_family=AF_INET6; + hints.ai_socktype=SOCK_STREAM; + //hints.ai_protocol=IPPROTO_SCTP + + struct addrinfo *aiHead = 0; + + + + int result = getaddrinfo(host, port, &hints, &aiHead); + NFAPI_TRACE(NFAPI_TRACE_INFO, "getaddrinfo return %d %d\n", result, errno); + + while(aiHead->ai_next != NULL) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "addr info %d (IP %d UDP %d SCTP %d)\n %d (%d)\n", + aiHead->ai_protocol, IPPROTO_IP, IPPROTO_UDP, IPPROTO_SCTP, + aiHead->ai_flags, AI_PASSIVE); + + char hostBfr[ NI_MAXHOST ]; + char servBfr[ NI_MAXSERV ]; + + getnameinfo(aiHead->ai_addr, + aiHead->ai_addrlen, + hostBfr, + sizeof( hostBfr ), + servBfr, + sizeof( servBfr ), + NI_NUMERICHOST | NI_NUMERICSERV ); + + switch(aiHead->ai_family) + { + case PF_INET: + { + struct sockaddr_in *pSadrIn = (struct sockaddr_in*) aiHead->ai_addr; + printf( + " ai_addr = sin_family: %d (AF_INET = %d, " + "AF_INET6 = %d)\n" + " sin_addr: %s\n" + " sin_port: %s\n", + pSadrIn->sin_family, + AF_INET, + AF_INET6, + hostBfr, + servBfr ); + } + break; + case PF_INET6: + { + struct sockaddr_in6 *pSadrIn6 = (struct sockaddr_in6*) aiHead->ai_addr; + fprintf( stderr, + " ai_addr = sin6_family: %d (AF_INET = %d, " + "AF_INET6 = %d) \n" + " sin6_addr: %s\n" + " sin6_port: %s\n" + " sin6_flowinfo: %d\n" + " sin6_scope_id: %d\n", + pSadrIn6->sin6_family, + AF_INET, + AF_INET6, + hostBfr, + servBfr, + pSadrIn6->sin6_flowinfo, + pSadrIn6->sin6_scope_id); + } + break; + default: + NFAPI_TRACE(NFAPI_TRACE_INFO, "Not ment to be here\n"); + break; + } + + aiHead = aiHead->ai_next; + } + */ + + { + int protocol; + int domain; + + if (vnf->sctp) + protocol = IPPROTO_SCTP; + else + protocol = IPPROTO_IP; + + if(config->vnf_ipv6) + { + domain = PF_INET6; + } + else + { + domain = AF_INET; + } + + // open the SCTP socket + if ((p5ListenSock = socket(domain, SOCK_STREAM, protocol)) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After P5 socket errno: %d\n", errno); + return 0; + } + NFAPI_TRACE(NFAPI_TRACE_INFO, "P5 socket created... %d\n", p5ListenSock); + } + + if (vnf->sctp) + { + // configure for MSG_NOTIFICATION + if (setsockopt(p5ListenSock, IPPROTO_SCTP, SCTP_EVENTS, &events, sizeof(struct sctp_event_subscribe)) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After setsockopt (SCTP_EVENTS) errno: %d\n", errno); + close(p5ListenSock); + return 0; + } + NFAPI_TRACE(NFAPI_TRACE_NOTE, "VNF Setting the SCTP_INITMSG\n"); + // configure the SCTP socket options + initMsg.sinit_num_ostreams = 5; //MAX_SCTP_STREAMS; // number of output streams can be greater + initMsg.sinit_max_instreams = 5; //MAX_SCTP_STREAMS; // number of output streams can be greater + if (setsockopt(p5ListenSock, IPPROTO_SCTP, SCTP_INITMSG, &initMsg, sizeof(initMsg)) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After setsockopt (SCTP_INITMSG) errno: %d\n", errno) + close(p5ListenSock); + return 0; + } + noDelay = 1; + if (setsockopt(p5ListenSock, IPPROTO_SCTP, SCTP_NODELAY, &noDelay, sizeof(noDelay)) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After setsockopt (STCP_NODELAY) errno: %d\n", errno); + close(p5ListenSock); + return 0; + } + struct sctp_event_subscribe events; + memset( (void *)&events, 0, sizeof(events) ); + events.sctp_data_io_event = 1; + + if(setsockopt(p5ListenSock, SOL_SCTP, SCTP_EVENTS, (const void *)&events, sizeof(events)) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After setsockopt errno: %d\n", errno); + close(p5ListenSock); + return -1; + } + + } + + + if(config->vnf_ipv6) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "IPV6 binding to port %d %d\n", config->vnf_p5_port, p5ListenSock); + addr6.sin6_family = AF_INET6; + addr6.sin6_port = htons(config->vnf_p5_port); + addr6.sin6_addr = in6addr_any; + + // bind to the configured address and port + if (bind(p5ListenSock, (struct sockaddr *)&addr6, sizeof(struct sockaddr_in6)) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After bind errno: %d\n", errno); + close(p5ListenSock); + return 0; + } + } + else if(config->vnf_ipv4) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "IPV4 binding to port %d\n", config->vnf_p5_port); + addr.sin_family = AF_INET; + addr.sin_port = htons(config->vnf_p5_port); + addr.sin_addr.s_addr = INADDR_ANY; + + // bind to the configured address and port + if (bind(p5ListenSock, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) + //if (sctp_bindx(p5ListenSock, (struct sockaddr *)&addr, sizeof(struct sockaddr_in), SCTP_BINDX_ADD_ADDR) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After bind errno: %d\n", errno); + close(p5ListenSock); + return 0; + } + } + + NFAPI_TRACE(NFAPI_TRACE_INFO, "bind succeeded..%d.\n", p5ListenSock); + + // put the socket into listen mode + if (listen(p5ListenSock, 2) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After listen errno: %d\n", errno); + close(p5ListenSock); + return 0; + } + + NFAPI_TRACE(NFAPI_TRACE_INFO, "listen succeeded...\n"); + + struct timeval tv; + fd_set read_fd_set; + + + int p5_idx = 0; + while(vnf->terminate == 0) + { + FD_ZERO(&read_fd_set); + + FD_SET(p5ListenSock, &read_fd_set); + int max_fd = p5ListenSock; + + tv.tv_sec = 5; + tv.tv_usec = 0; + + nfapi_vnf_pnf_info_t* pnf = config->pnf_list; + while(pnf != 0) + { + if(pnf->connected) + { + FD_SET(pnf->p5_sock, &read_fd_set); + if (pnf->p5_sock > max_fd) + { + max_fd = pnf->p5_sock; + } + } + + pnf = pnf->next; + } + + int select_result = select(max_fd + 1, &read_fd_set, 0, 0, &tv); + + if(select_result == -1) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "select result %d errno %d\n", select_result, errno); + close(p5ListenSock); + return 0; + } + else if(select_result) + { + if(FD_ISSET(p5ListenSock, &read_fd_set)) + { + addrSize = sizeof(struct sockaddr_in); + NFAPI_TRACE(NFAPI_TRACE_INFO, "Accepting connection from PNF...\n"); + + p5Sock = accept(p5ListenSock, (struct sockaddr *)&addr, &addrSize); + + if (p5Sock < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Failed to accept PNF connection reason:%d\n", errno); + } + else + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "PNF connection (fd:%d) accepted from %s:%d \n", p5Sock, inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); + nfapi_vnf_pnf_info_t* pnf = (nfapi_vnf_pnf_info_t*)malloc(sizeof(nfapi_vnf_pnf_info_t)); + NFAPI_TRACE(NFAPI_TRACE_INFO, "MALLOC nfapi_vnf_pnf_info_t for pnf_list pnf:%p\n", pnf); + memset(pnf, 0, sizeof(nfapi_vnf_pnf_info_t)); + pnf->p5_sock = p5Sock; + pnf->p5_idx = p5_idx++; + pnf->p5_pnf_sockaddr = addr; + pnf->connected = 1; + + nfapi_vnf_pnf_list_add(config, pnf); + + // Inform mac that a pnf connection has been established + // todo : allow mac to 'accept' the connection. i.e. to + // reject it. + if(config->pnf_nr_connection_indication != 0) + { + (config->pnf_nr_connection_indication)(config, pnf->p5_idx); + } + + + // check the connection status + { + struct sctp_status status; + (void)memset(&status, 0, sizeof(struct sctp_status)); + socklen_t optLen = (socklen_t) sizeof(struct sctp_status); + if (getsockopt(p5Sock, IPPROTO_SCTP, SCTP_STATUS, &status, &optLen) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After getsockopt errno: %d\n", errno); + return -1; + } + else + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF Association ID = %d\n", status.sstat_assoc_id); + NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF Receiver window size = %d\n", status.sstat_rwnd); + NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF In Streams = %d\n", status.sstat_instrms); + NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF Out Streams = %d\n", status.sstat_outstrms); + + } + } + } + } + else + { + uint8_t delete_pnfs = 0; + + nfapi_vnf_pnf_info_t* pnf = config->pnf_list; + while(pnf != 0) + { + if(FD_ISSET(pnf->p5_sock, &read_fd_set)) + { + if(vnf_nr_read_dispatch_message(config, pnf) == 0) + { + if(config->pnf_disconnect_indication != 0) + { + (config->pnf_disconnect_indication)(config, pnf->p5_idx); + } + + close(pnf->p5_sock); + + pnf->to_delete = 1; + delete_pnfs = 1; + } + } + + pnf = pnf->next; + } + + if(delete_pnfs) + { + nfapi_vnf_pnf_info_t* pnf = config->pnf_list; + nfapi_vnf_pnf_info_t* prev = 0; + while(pnf != 0) + { + nfapi_vnf_pnf_info_t* curr = pnf; + + if(pnf->to_delete == 1) + { + if(prev == 0) + { + config->pnf_list = pnf->next; + } + else + { + prev->next = pnf->next; + } + + pnf = pnf->next; + + free(curr); + } + else + { + prev = pnf; + pnf = pnf->next; + } + + } + + } + } + + continue; + } + else + { + // timeout + + // Should we test for socket closure here every second? + + continue; + } + } + + NFAPI_TRACE(NFAPI_TRACE_INFO, "Closing p5Sock socket's\n"); + { + nfapi_vnf_pnf_info_t* curr = config->pnf_list; + while(curr != NULL) + { + if(config->pnf_disconnect_indication) + { + (config->pnf_disconnect_indication)(config, curr->p5_idx); + } + + close(curr->p5_sock); + curr = curr->next; + } + } + + NFAPI_TRACE(NFAPI_TRACE_INFO, "Closing p5Listen socket\n"); + close(p5ListenSock); + + return 0; + +} + int nfapi_vnf_start(nfapi_vnf_config_t* config) { // Verify that config is not null @@ -486,6 +898,16 @@ int nfapi_vnf_stop(nfapi_vnf_config_t* config) return 0; } +int nfapi_nr_vnf_pnf_param_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_pnf_param_request_t* req) +{ + if(config == 0 || req == 0) + return -1; + + vnf_t* _this = (vnf_t*)(config); + + return vnf_nr_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_nr_pnf_param_request_t)); +} + int nfapi_vnf_pnf_param_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_pnf_param_request_t* req) { if(config == 0 || req == 0) @@ -496,6 +918,17 @@ int nfapi_vnf_pnf_param_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_pnf_pa return vnf_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_pnf_param_request_t)); } +int nfapi_nr_vnf_pnf_config_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_pnf_config_request_t* req) +{ + if(config == 0 || req == 0) + return -1; + + vnf_t* _this = (vnf_t*)(config); + + return vnf_nr_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_nr_pnf_config_request_t)); +} + + int nfapi_vnf_pnf_config_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_pnf_config_request_t* req) { if(config == 0 || req == 0) @@ -516,6 +949,16 @@ int nfapi_vnf_pnf_start_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_pnf_st return vnf_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_pnf_start_request_t)); } +int nfapi_nr_vnf_pnf_start_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_pnf_start_request_t* req) +{ + if(config == 0 || req == 0) + return -1; + + vnf_t* _this = (vnf_t*)(config); + + return vnf_nr_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_nr_pnf_start_request_t)); +} + int nfapi_vnf_pnf_stop_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_pnf_stop_request_t* req) { if(config == 0 || req == 0) @@ -526,6 +969,16 @@ int nfapi_vnf_pnf_stop_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_pnf_sto return vnf_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_pnf_stop_request_t)); } +int nfapi_nr_vnf_param_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_param_request_scf_t* req) +{ + if(config == 0 || req == 0) + return -1; + + vnf_t* _this = (vnf_t*)(config); + + return vnf_nr_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_nr_param_request_scf_t)); +} + int nfapi_vnf_param_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_param_request_t* req) { if(config == 0 || req == 0) @@ -535,6 +988,38 @@ int nfapi_vnf_param_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_param_requ return vnf_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_param_request_t)); } + +int nfapi_nr_vnf_config_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_config_request_scf_t* req) +{ + if(config == 0 || req == 0) + return -1; + + vnf_t* _this = (vnf_t*)(config); + + nfapi_vnf_phy_info_t* phy = nfapi_vnf_phy_info_list_find(config, req->header.phy_id); + + if(phy == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_WARN, "%s failed to find phy information phy_id:%d\n", __FUNCTION__, req->header.phy_id); + return -1; + } + + // set the timing parameters + req->nfapi_config.timing_window.tl.tag = NFAPI_NR_NFAPI_TIMING_WINDOW_TAG; + req->nfapi_config.timing_window.value = phy->timing_window; + req->num_tlv++; + + req->nfapi_config.timing_info_mode.tl.tag = NFAPI_NR_NFAPI_TIMING_INFO_MODE_TAG; + req->nfapi_config.timing_info_mode.value = phy->timing_info_mode; + req->num_tlv++; + + req->nfapi_config.timing_info_period.tl.tag = NFAPI_NR_NFAPI_TIMING_INFO_PERIOD_TAG; + req->nfapi_config.timing_info_period.value = phy->timing_info_period; + req->num_tlv++; + + return vnf_nr_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_nr_config_request_scf_t)); +} + int nfapi_vnf_config_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_config_request_t* req) { if(config == 0 || req == 0) @@ -565,7 +1050,8 @@ int nfapi_vnf_config_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_config_re return vnf_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_config_request_t)); } -int nfapi_vnf_start_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_start_request_t* req) + +int nfapi_vnf_start_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_start_request_t * req) { if(config == 0 || req == 0) return -1; @@ -574,6 +1060,18 @@ int nfapi_vnf_start_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_start_requ return vnf_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_start_request_t)); } + +int nfapi_nr_vnf_start_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_nr_start_request_scf_t * req) +{ + if(config == 0 || req == 0) + return -1; + + vnf_t* _this = (vnf_t*)(config); + + return vnf_nr_pack_and_send_p5_message(_this, p5_idx, &req->header, sizeof(nfapi_nr_start_request_scf_t)); +} + + int nfapi_vnf_stop_req(nfapi_vnf_config_t* config, int p5_idx, nfapi_stop_request_t* req) { if(config == 0 || req == 0) @@ -664,7 +1162,7 @@ int nfapi_vnf_allocate_phy(nfapi_vnf_config_t* config, int p5_idx, uint16_t* phy info->p5_idx = p5_idx; info->phy_id = vnf->next_phy_id++; - info->timing_window = 30; // This seems to override what gets set by the user - why??? + info->timing_window = 30; // This seems to override what gets set by the user - why??? //TODO: Change in NR in terms of microsecends,what should be the value? info->timing_info_mode = 0x03; info->timing_info_period = 128; diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7.c b/nfapi/open-nFAPI/vnf/src/vnf_p7.c index cff24500b6..ffbc5819bc 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_p7.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_p7.c @@ -303,7 +303,7 @@ static uint32_t get_sf_time(uint32_t now_hr, uint32_t sf_start_hr) { if(now_hr < sf_start_hr) { - NFAPI_TRACE(NFAPI_TRACE_INFO, "now is earlier that start of subframe\n"); + NFAPI_TRACE(NFAPI_TRACE_INFO, "now is earlier than start of subframe\n"); return 0; } else @@ -321,6 +321,28 @@ static uint32_t get_sf_time(uint32_t now_hr, uint32_t sf_start_hr) } } +static uint32_t get_slot_time(uint32_t now_hr, uint32_t slot_start_hr) +{ + if(now_hr < slot_start_hr) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "now is earlier than start of slot\n"); + return 0; + } + else + { + uint32_t now_us = TIMEHR_USEC(now_hr); + uint32_t slot_start_us = TIMEHR_USEC(slot_start_hr); + + // if the us have wrapped adjust for it + if(now_hr < slot_start_us) + { + now_us += 1000000; + } + + return now_us - slot_start_us; + } +} + uint32_t calculate_t1(uint16_t sfn_sf, uint32_t sf_start_time_hr) { uint32_t now_time_hr = vnf_get_current_time_hr(); @@ -332,6 +354,17 @@ uint32_t calculate_t1(uint16_t sfn_sf, uint32_t sf_start_time_hr) return t1; } +uint32_t calculate_nr_t1(uint16_t sfn, uint16_t slot, uint32_t slot_start_time_hr) +{ + uint32_t now_time_hr = vnf_get_current_time_hr(); + + uint32_t slot_time_us = get_slot_time(now_time_hr, slot_start_time_hr); + + uint32_t t1 = (NFAPI_SFNSLOT2DEC(sfn,slot) * 500) + slot_time_us; + + return t1; +} + uint32_t calculate_t4(uint32_t now_time_hr, uint16_t sfn_sf, uint32_t sf_start_time_hr) { @@ -343,15 +376,25 @@ uint32_t calculate_t4(uint32_t now_time_hr, uint16_t sfn_sf, uint32_t sf_start_t } +uint32_t calculate_nr_t4(uint32_t now_time_hr, uint16_t sfn, uint16_t slot, uint32_t slot_start_time_hr) +{ + uint32_t slot_time_us = get_slot_time(now_time_hr, slot_start_time_hr); -uint32_t calculate_transmit_timestamp(uint16_t sfn_sf, uint32_t sf_start_time_hr) + uint32_t t4 = (NFAPI_SFNSLOT2DEC(sfn,slot) * 500) + slot_time_us; + + return t4; + +} + + +uint32_t calculate_transmit_timestamp(uint16_t sfn, uint16_t slot, uint32_t slot_start_time_hr) { uint32_t now_time_hr = vnf_get_current_time_hr(); - uint32_t sf_time_us = get_sf_time(now_time_hr, sf_start_time_hr); - - uint32_t tt = (NFAPI_SFNSF2DEC(sfn_sf) * 1000) + sf_time_us; + uint32_t slot_time_us = get_slot_time(now_time_hr, slot_start_time_hr); + uint32_t tt = (NFAPI_SFNSLOT2DEC(sfn, slot) * 500) + slot_time_us; + return tt; } @@ -367,6 +410,27 @@ uint16_t increment_sfn_sf_by(uint16_t sfn_sf, uint8_t increment) return sfn_sf; } +int send_mac_slot_indications(vnf_p7_t* vnf_p7) +{ + nfapi_vnf_p7_connection_info_t* curr = vnf_p7->p7_connections; + while(curr != 0) + { + if(curr->in_sync == 1) + { + // ask for subframes in the future + //uint16_t sfn_sf_adv = increment_sfn_sf_by(curr->sfn_sf, 2); + + //vnf_p7->_public.subframe_indication(&(vnf_p7->_public), curr->phy_id, sfn_sf_adv); + // suggestion fix by Haruki NAOI + //printf("\nsfn:%d, slot:%d\n",curr->sfn,curr->slot); + vnf_p7->_public.slot_indication(&(vnf_p7->_public), curr->phy_id, curr->sfn,curr->slot); + } + + curr = curr->next; + } + + return 0; +} int send_mac_subframe_indications(vnf_p7_t* vnf_p7) { @@ -392,7 +456,7 @@ int send_mac_subframe_indications(vnf_p7_t* vnf_p7) int vnf_send_p7_msg(vnf_p7_t* vnf_p7, nfapi_vnf_p7_connection_info_t* p7_info, uint8_t* msg, const uint32_t len) { int sendto_result = sendto(vnf_p7->socket, msg, len, 0, (struct sockaddr*)&(p7_info->remote_addr), sizeof(p7_info->remote_addr)); - + //printf("\nSending p7 message sfn=%d,slot=%d\n",vnf_p7->p7_connections->sfn,vnf_p7->p7_connections->slot); if(sendto_result != len) { NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() sendto_result %d %d\n", __FUNCTION__, sendto_result, errno); @@ -401,6 +465,100 @@ int vnf_send_p7_msg(vnf_p7_t* vnf_p7, nfapi_vnf_p7_connection_info_t* p7_info, u return 0; } +int vnf_nr_p7_pack_and_send_p7_msg(vnf_p7_t* vnf_p7, nfapi_p7_message_header_t* header) +{ + + nfapi_vnf_p7_connection_info_t* p7_connection = vnf_p7_connection_info_list_find(vnf_p7, header->phy_id); + if(p7_connection) + { + int send_result = 0; + uint8_t buffer[1024 * 32]; + + header->m_segment_sequence = NFAPI_P7_SET_MSS(0, 0, p7_connection->sequence_number); + + int len = nfapi_nr_p7_message_pack(header, buffer, sizeof(buffer), &vnf_p7->_public.codec_config); + + //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() phy_id:%d nfapi_p7_message_pack()=len=%d vnf_p7->_public.segment_size:%u\n", __FUNCTION__, header->phy_id, len, vnf_p7->_public.segment_size); + + if(len < 0) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() failed to pack p7 message phy_id:%d\n", __FUNCTION__, header->phy_id); + return -1; + } + + if(len > vnf_p7->_public.segment_size) + { + // todo : consider replacing with the sendmmsg call + // todo : worry about blocking writes? + + // segmenting the transmit + int msg_body_len = len - NFAPI_P7_HEADER_LENGTH ; + int seg_body_len = vnf_p7->_public.segment_size - NFAPI_P7_HEADER_LENGTH ; + int segment_count = (msg_body_len / (seg_body_len)) + ((msg_body_len % seg_body_len) ? 1 : 0); + + int segment = 0; + int offset = NFAPI_P7_HEADER_LENGTH; + uint8_t tx_buffer[vnf_p7->_public.segment_size]; + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() MORE THAN ONE SEGMENT phy_id:%d nfapi_p7_message_pack()=len=%d vnf_p7->_public.segment_size:%u\n", __FUNCTION__, header->phy_id, len, vnf_p7->_public.segment_size); + for(segment = 0; segment < segment_count; ++segment) + { + uint8_t last = 0; + uint16_t size = vnf_p7->_public.segment_size - NFAPI_P7_HEADER_LENGTH; + if(segment + 1 == segment_count) + { + last = 1; + size = (msg_body_len) - (seg_body_len * segment); + } + + uint16_t segment_size = size + NFAPI_P7_HEADER_LENGTH; + + // Update the header with the m and segement + memcpy(&tx_buffer[0], buffer, NFAPI_P7_HEADER_LENGTH); + + // set the segment length + tx_buffer[4] = (segment_size & 0xFF00) >> 8; + tx_buffer[5] = (segment_size & 0xFF); + + // set the m & segment number + tx_buffer[6] = ((!last) << 7) + segment; + + memcpy(&tx_buffer[NFAPI_P7_HEADER_LENGTH], &buffer[0] + offset, size); + offset += size; + + if(vnf_p7->_public.checksum_enabled) + { + nfapi_p7_update_checksum(tx_buffer, segment_size); + } + + nfapi_p7_update_transmit_timestamp(buffer, calculate_transmit_timestamp(p7_connection->sfn, p7_connection->slot, vnf_p7->slot_start_time_hr)); + + send_result = vnf_send_p7_msg(vnf_p7, p7_connection, &tx_buffer[0], segment_size); + } + } + else + { + if(vnf_p7->_public.checksum_enabled) + { + nfapi_p7_update_checksum(buffer, len); + } + + nfapi_p7_update_transmit_timestamp(buffer, calculate_transmit_timestamp(p7_connection->sfn, p7_connection->slot, vnf_p7->slot_start_time_hr)); + + // simple case that the message fits in a single segement + send_result = vnf_send_p7_msg(vnf_p7, p7_connection, &buffer[0], len); + } + + p7_connection->sequence_number++; + + return send_result; + } + else + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() cannot find p7 connection info for phy_id:%d\n", __FUNCTION__, header->phy_id); + return -1; + } +} + int vnf_p7_pack_and_send_p7_msg(vnf_p7_t* vnf_p7, nfapi_p7_message_header_t* header) { @@ -466,7 +624,7 @@ int vnf_p7_pack_and_send_p7_msg(vnf_p7_t* vnf_p7, nfapi_p7_message_header_t* hea nfapi_p7_update_checksum(tx_buffer, segment_size); } - nfapi_p7_update_transmit_timestamp(buffer, calculate_transmit_timestamp(p7_connection->sfn_sf, vnf_p7->sf_start_time_hr)); + nfapi_p7_update_transmit_timestamp(buffer, calculate_transmit_timestamp(p7_connection->sfn, p7_connection->slot, vnf_p7->slot_start_time_hr)); send_result = vnf_send_p7_msg(vnf_p7, p7_connection, &tx_buffer[0], segment_size); } @@ -478,7 +636,7 @@ int vnf_p7_pack_and_send_p7_msg(vnf_p7_t* vnf_p7, nfapi_p7_message_header_t* hea nfapi_p7_update_checksum(buffer, len); } - nfapi_p7_update_transmit_timestamp(buffer, calculate_transmit_timestamp(p7_connection->sfn_sf, vnf_p7->sf_start_time_hr)); + nfapi_p7_update_transmit_timestamp(buffer, calculate_transmit_timestamp(p7_connection->sfn, p7_connection->slot, vnf_p7->slot_start_time_hr)); // simple case that the message fits in a single segement send_result = vnf_send_p7_msg(vnf_p7, p7_connection, &buffer[0], len); @@ -494,7 +652,6 @@ int vnf_p7_pack_and_send_p7_msg(vnf_p7_t* vnf_p7, nfapi_p7_message_header_t* hea return -1; } } - int vnf_build_send_dl_node_sync(vnf_p7_t* vnf_p7, nfapi_vnf_p7_connection_info_t* p7_info) { nfapi_dl_node_sync_t dl_node_sync; @@ -508,6 +665,52 @@ int vnf_build_send_dl_node_sync(vnf_p7_t* vnf_p7, nfapi_vnf_p7_connection_info_t return vnf_p7_pack_and_send_p7_msg(vnf_p7, &dl_node_sync.header); } +int vnf_nr_build_send_dl_node_sync(vnf_p7_t* vnf_p7, nfapi_vnf_p7_connection_info_t* p7_info) +{ + + nfapi_nr_dl_node_sync_t dl_node_sync; + memset(&dl_node_sync, 0, sizeof(dl_node_sync)); + + dl_node_sync.header.phy_id = p7_info->phy_id; + dl_node_sync.header.message_id = NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC; + //dl_node_sync.t1 = calculate_t1(p7_info->sfn_sf, vnf_p7->sf_start_time_hr); + dl_node_sync.t1 = calculate_nr_t1(p7_info->sfn,p7_info->slot, vnf_p7->slot_start_time_hr); + dl_node_sync.delta_sfn_slot = 0; + + return vnf_nr_p7_pack_and_send_p7_msg(vnf_p7, &dl_node_sync.header); +} + +int vnf_nr_sync(vnf_p7_t* vnf_p7, nfapi_vnf_p7_connection_info_t* p7_info) +{ + + if(p7_info->in_sync == 1) + { + uint16_t dl_sync_period_mask = p7_info->dl_in_sync_period-1; + // uint16_t sfn_sf_dec = NFAPI_SFNSF2DEC(p7_info->sfn_sf); + uint16_t sfn_slot_dec = NFAPI_SFNSLOT2DEC(p7_info->sfn,p7_info->slot); + + //if ((((sfn_sf_dec + p7_info->dl_in_sync_offset) % NFAPI_MAX_SFNSFDEC) & dl_sync_period_mask) == 0) + if ((((sfn_slot_dec + p7_info->dl_in_sync_offset) % NFAPI_MAX_SFNSLOTDEC) & dl_sync_period_mask) == 0) + { + vnf_nr_build_send_dl_node_sync(vnf_p7, p7_info); + } + } + else + { + uint16_t dl_sync_period_mask = p7_info->dl_out_sync_period-1; + //uint16_t sfn_sf_dec = NFAPI_SFNSF2DEC(p7_info->sfn_sf); + uint16_t sfn_slot_dec = NFAPI_SFNSLOT2DEC(p7_info->sfn, p7_info->slot); + + //if ((((sfn_sf_dec + p7_info->dl_out_sync_offset) % NFAPI_MAX_SFNSFDEC) & dl_sync_period_mask) == 0) + if ((((sfn_slot_dec + p7_info->dl_out_sync_offset) % NFAPI_MAX_SFNSLOTDEC) & dl_sync_period_mask) == 0) + { + vnf_nr_build_send_dl_node_sync(vnf_p7, p7_info); + } + } + return 0; +} + + int vnf_sync(vnf_p7_t* vnf_p7, nfapi_vnf_p7_connection_info_t* p7_info) { @@ -1251,6 +1454,389 @@ void vnf_handle_ul_node_sync(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) } } +void vnf_nr_handle_ul_node_sync(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) +{ + //printf("received UL Node sync"); + + uint32_t now_time_hr = vnf_get_current_time_hr(); + + if (pRecvMsg == NULL || vnf_p7 == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "vnf_handle_ul_node_sync: NULL parameters\n"); + return; + } + + nfapi_nr_ul_node_sync_t ind; + if(nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(nfapi_nr_ul_node_sync_t), &vnf_p7->_public.codec_config) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Failed to unpack ul_node_sync\n"); + return; + } + + //NFAPI_TRACE(NFAPI_TRACE_INFO, "Received UL_NODE_SYNC phy_id:%d t1:%d t2:%d t3:%d\n", ind.header.phy_id, ind.t1, ind.t2, ind.t3); + + nfapi_vnf_p7_connection_info_t* phy = vnf_p7_connection_info_list_find(vnf_p7, ind.header.phy_id); + uint32_t t4 = calculate_nr_t4(now_time_hr, phy->sfn, phy->slot, vnf_p7->slot_start_time_hr); + + uint32_t tx_2_rx = t4>ind.t1 ? t4 - ind.t1 : t4 + NFAPI_MAX_SFNSLOTDEC - ind.t1 ; //time taken to receive ul node sync - time taken to send dl node sync + uint32_t pnf_proc_time = ind.t3 - ind.t2; + + // divide by 2 using shift operator + uint32_t latency = (tx_2_rx - pnf_proc_time) >> 1; + + if(!(phy->filtered_adjust)) + { + phy->latency[phy->min_sync_cycle_count] = latency; + + //NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%4d/%d) PNF to VNF !sync phy_id:%d (t1/2/3/4:%8u, %8u, %8u, %8u) txrx:%4u procT:%3u latency(us):%4d\n", + // phy->sfn, phy->slot, ind.header.phy_id, ind.t1, ind.t2, ind.t3, t4, + // tx_2_rx, pnf_proc_time, latency); + } + else + { + phy->latency[phy->min_sync_cycle_count] = latency; + + //if(phy->min_sync_cycle_count != SYNC_CYCLE_COUNT) + { + if (ind.t2 < phy->previous_t2 && ind.t1 > phy->previous_t1) + { + // Only t2 wrap has occurred!!! + phy->slot_offset = (NFAPI_MAX_SFNSLOTDEC + ind.t2) - ind.t1 - latency; + } + else if (ind.t2 > phy->previous_t2 && ind.t1 < phy->previous_t1) + { + // Only t1 wrap has occurred + phy->slot_offset = ind.t2 - ( ind.t1 + NFAPI_MAX_SFNSLOTDEC) - latency; + } + else + { + // Either no wrap or both have wrapped + phy->slot_offset = ind.t2 - ind.t1 - latency; + } + + if (phy->slot_offset_filtered == 0) + { + phy->slot_offset_filtered = phy->slot_offset; + } + else + { + int32_t oldFilteredValueShifted = phy->slot_offset_filtered << 5; + int32_t newOffsetShifted = phy->slot_offset << 5; + + // 1/8 of new and 7/8 of old + phy->slot_offset_filtered = ((newOffsetShifted >> 3) + ((oldFilteredValueShifted * 7) >> 3)) >> 5; + } + } + + if(1) + { + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + + //NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%4d/%1d) %d.%d PNF to VNF phy_id:%2d (t1/2/3/4:%8u, %8u, %8u, %8u) txrx:%4u procT:%3u latency(us):%4d(avg:%4d) offset(us):%8d filtered(us):%8d wrap[t1:%u t2:%u]\n", + // phy->sfn, phy->slot, ts.tv_sec, ts.tv_nsec, ind.header.phy_id, + // ind.t1, ind.t2, ind.t3, t4, + // tx_2_rx, pnf_proc_time, latency, phy->average_latency, phy->slot_offset, phy->slot_offset_filtered, + // (ind.t1previous_t1), (ind.t2previous_t2)); + } + + } + + if (phy->filtered_adjust && (phy->slot_offset_filtered > 1e6 || phy->slot_offset_filtered < -1e6)) + { + phy->filtered_adjust = 0; + phy->zero_count=0; + phy->min_sync_cycle_count = 2; + phy->in_sync = 0; + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s - ADJUST TOO BAD - go out of filtered phy->slot_offset_filtered:%d\n", __FUNCTION__, phy->slot_offset_filtered); + } + + if(phy->min_sync_cycle_count) + phy->min_sync_cycle_count--; + + if(phy->min_sync_cycle_count == 0) + { + uint32_t curr_sfn = phy->sfn; + uint32_t curr_slot = phy->slot; + int32_t sfn_slot_dec = NFAPI_SFNSLOT2DEC(phy->sfn,phy->slot); + + if(!phy->filtered_adjust) + { + int i = 0; + //phy->average_latency = 0; + for(i = 0; i < SYNC_CYCLE_COUNT; ++i) + { + phy->average_latency += phy->latency[i]; + + } + phy->average_latency /= SYNC_CYCLE_COUNT; + + phy->slot_offset = ind.t2 - (ind.t1 - phy->average_latency); + + sfn_slot_dec += (phy->slot_offset / 500); + + NFAPI_TRACE(NFAPI_TRACE_NOTE, "PNF to VNF slot offset:%d sfn :%d slot:%d \n",phy->slot_offset,NFAPI_SFNSLOTDEC2SFN(sfn_slot_dec),NFAPI_SFNSLOTDEC2SLOT(sfn_slot_dec) ); + + + } + else + { + sfn_slot_dec += ((phy->slot_offset_filtered + 250) / 500); //Round up to go from microsecond to slot + + } + + if(sfn_slot_dec < 0) + { + sfn_slot_dec += NFAPI_MAX_SFNSLOTDEC; + } + else if( sfn_slot_dec >= NFAPI_MAX_SFNSLOTDEC) + { + sfn_slot_dec -= NFAPI_MAX_SFNSLOTDEC; + } + + + uint16_t new_sfn = NFAPI_SFNSLOTDEC2SFN(sfn_slot_dec); + uint16_t new_slot = NFAPI_SFNSLOTDEC2SLOT(sfn_slot_dec); + + { + phy->adjustment = NFAPI_SFNSLOT2DEC(new_sfn, new_slot) - NFAPI_SFNSLOT2DEC(curr_sfn, curr_slot); + + //NFAPI_TRACE(NFAPI_TRACE_NOTE, "PNF to VNF phy_id:%d adjustment%d phy->previous_slot_offset_filtered:%d phy->previous_slot_offset_filtered:%d phy->slot_offset_trend:%d\n", ind.header.phy_id, phy->adjustment, phy->previous_slot_offset_filtered, phy->previous_slot_offset_filtered, phy->slot_offset_trend); + + phy->previous_t1 = 0; + phy->previous_t2 = 0; + + if(phy->previous_slot_offset_filtered > 0) + { + if( phy->slot_offset_filtered > phy->previous_slot_offset_filtered) + { + // pnf is getting futher ahead of vnf + //phy->sf_offset_trend = phy->sf_offset_filtered - phy->previous_sf_offset_filtered; + phy->slot_offset_trend = (phy->slot_offset_filtered + phy->previous_slot_offset_filtered)/2; + } + else + { + // pnf is getting back in sync + } + } + else if(phy->previous_slot_offset_filtered < 0) + { + if(phy->slot_offset_filtered < phy->previous_slot_offset_filtered) + { + // vnf is getting future ahead of pnf + //phy->sf_offset_trend = -(phy->sf_offset_filtered - phy->previous_sf_offset_filtered); + phy->slot_offset_trend = (-(phy->slot_offset_filtered + phy->previous_slot_offset_filtered)) /2; + } + else + { + // vnf is getting back in sync + } + } + + + int insync_minor_adjustment_1 = phy->slot_offset_trend / 6; + int insync_minor_adjustment_2 = phy->slot_offset_trend / 2; + + + if(insync_minor_adjustment_1 == 0) + insync_minor_adjustment_1 = 2; + + if(insync_minor_adjustment_2 == 0) + insync_minor_adjustment_2 = 10; + + if(!phy->filtered_adjust) + { + if(phy->adjustment < 10) + { + phy->zero_count++; + + if(phy->zero_count >= 10) + { + phy->filtered_adjust = 1; + phy->zero_count = 0; + + NFAPI_TRACE(NFAPI_TRACE_NOTE, "***** Adjusting VNF SFN/SF switching to filtered mode\n"); + } + } + else + { + phy->zero_count = 0; + } + } + else + { + // Fine level of adjustment + if (phy->adjustment == 0) + { + if (phy->zero_count >= 10) + { + if(phy->in_sync == 0) + { + NFAPI_TRACE(NFAPI_TRACE_NOTE, "VNF P7 In Sync with phy (phy_id:%d)\n", phy->phy_id); + + if(vnf_p7->_public.sync_indication) + (vnf_p7->_public.sync_indication)(&(vnf_p7->_public), 1); + } + + phy->in_sync = 1; + } + else + { + phy->zero_count++; + } + + if(phy->in_sync) + { + // in sync + if(phy->slot_offset_filtered > 250) + { + // VNF is slow + phy->insync_minor_adjustment = insync_minor_adjustment_1; //25; + phy->insync_minor_adjustment_duration = ((phy->slot_offset_filtered) / insync_minor_adjustment_1); + } + else if(phy->slot_offset_filtered < -250) + { + // VNF is fast + phy->insync_minor_adjustment = -(insync_minor_adjustment_1); //25; + phy->insync_minor_adjustment_duration = (((phy->slot_offset_filtered) / -(insync_minor_adjustment_1))); + } + else + { + phy->insync_minor_adjustment = 0; + } + + if(phy->insync_minor_adjustment != 0) + { + // NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%4d/%d) VNF phy_id:%d Apply minor insync adjustment %dus for %d slots (slot_offset_filtered:%d) %d %d %d NEW:%d CURR:%d adjustment:%d\n", + // phy->sfn, phy->slot, ind.header.phy_id, + // phy->insync_minor_adjustment, phy->insync_minor_adjustment_duration, + // phy->slot_offset_filtered, + // insync_minor_adjustment_1, insync_minor_adjustment_2, phy->slot_offset_trend, + // NFAPI_SFNSLOT2DEC(new_sfn, new_slot), + // NFAPI_SFNSLOT2DEC(curr_sfn, curr_slot), + // phy->adjustment); + } + } + } + else + { + if (phy->in_sync) + { + if(phy->adjustment == 0) + { + } + else if(phy->adjustment > 0) + { + // VNF is slow + //if(phy->adjustment == 1) + { + // + if(phy->slot_offset_filtered > 250) + { + // VNF is slow + phy->insync_minor_adjustment = insync_minor_adjustment_2; + phy->insync_minor_adjustment_duration = 2 * ((phy->slot_offset_filtered - 250) / insync_minor_adjustment_2); + } + else if(phy->slot_offset_filtered < -250) + { + // VNF is fast + phy->insync_minor_adjustment = -(insync_minor_adjustment_2); + phy->insync_minor_adjustment_duration = 2 * ((phy->slot_offset_filtered + 250) / -(insync_minor_adjustment_2)); + } + + } + //else + { + // out of sync? + } + + // NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%4d/%d) VNF phy_id:%d Apply minor insync adjustment %dus for %d slots (adjustment:%d slot_offset_filtered:%d) %d %d %d NEW:%d CURR:%d adj:%d\n", + // phy->sfn, phy->slot, ind.header.phy_id, + // phy->insync_minor_adjustment, phy->insync_minor_adjustment_duration, phy->adjustment, phy->slot_offset_filtered, + // insync_minor_adjustment_1, insync_minor_adjustment_2, phy->slot_offset_trend, + // NFAPI_SFNSLOT2DEC(new_sfn, new_slot), + // NFAPI_SFNSLOT2DEC(curr_sfn, curr_slot), + // phy->adjustment); + + } + else if(phy->adjustment < 0) + { + // VNF is fast + //if(phy->adjustment == -1) + { + // + if(phy->slot_offset_filtered > 250) + { + // VNF is slow + phy->insync_minor_adjustment = insync_minor_adjustment_2; + phy->insync_minor_adjustment_duration = 2 * ((phy->slot_offset_filtered - 250) / insync_minor_adjustment_2); + } + else if(phy->slot_offset_filtered < -250) + { + // VNF is fast + phy->insync_minor_adjustment = -(insync_minor_adjustment_2); + phy->insync_minor_adjustment_duration = 2 * ((phy->slot_offset_filtered + 250) / -(insync_minor_adjustment_2)); + } + } + //else + { + // out of sync? + } + + // NFAPI_TRACE(NFAPI_TRACE_NOTE, "(%d/%d) VNF phy_id:%d Apply minor insync adjustment %dus for %d slots (adjustment:%d slot_offset_filtered:%d) %d %d %d\n", + // phy->sfn, phy->slot, ind.header.phy_id, + // phy->insync_minor_adjustment, phy->insync_minor_adjustment_duration, phy->adjustment, phy->slot_offset_filtered, + // insync_minor_adjustment_1, insync_minor_adjustment_2, phy->slot_offset_trend); + } + + /* + if (phy->adjustment > 10 || phy->adjustment < -10) + { + phy->zero_count++; // Add one to the getting out of sync counter + } + else + { + phy->zero_count = 0; // Small error - zero the out of sync counter + } + + if (phy->zero_count >= 10) // If we have had 10 consecutive large errors - drop out of sync + { + NFAPI_TRACE(NFAPI_TRACE_NOTE, "we have fallen out of sync...\n"); + //pP7SockInfo->syncAchieved = 0; + } + */ + } + } + } + + + if(phy->in_sync == 0) + { + /*NFAPI_TRACE(NFAPI_TRACE_NOTE, "***** Adjusting VNF phy_id:%d SFN/SF (%s) from %d to %d (%d) mode:%s zeroCount:%u sync:%s\n", + ind.header.phy_id, (phy->in_sync ? "via sfn" : "now"), + NFAPI_SFNSF2DEC(curr_sfn_sf), NFAPI_SFNSF2DEC(new_sfn_sf), phy->adjustment, + phy->filtered_adjust ? "FILTERED" : "ABSOLUTE", + phy->zero_count, + phy->in_sync ? "IN_SYNC" : "OUT_OF_SYNC");*/ + + phy->sfn = new_sfn; + phy->slot = new_slot; + } + } + + // reset for next cycle + phy->previous_slot_offset_filtered = phy->slot_offset_filtered; + phy->min_sync_cycle_count = 2; + phy->slot_offset_filtered = 0; + phy->slot_offset = 0; + } + else + { + phy->previous_t1 = ind.t1; + phy->previous_t2 = ind.t2; + } +} + void vnf_handle_timing_info(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) { if (pRecvMsg == NULL || vnf_p7 == NULL) @@ -1283,6 +1869,41 @@ void vnf_handle_timing_info(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) } } + +void vnf_nr_handle_timing_info(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) +{ + if (pRecvMsg == NULL || vnf_p7 == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "vnf_handle_timing_info: NULL parameters\n"); + return; + } + + nfapi_nr_timing_info_t ind; + if(nfapi_nr_p7_message_unpack(pRecvMsg, recvMsgLen, &ind, sizeof(nfapi_timing_info_t), &vnf_p7->_public.codec_config) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Failed to unpack timing_info\n"); + return; + } + + if (vnf_p7 && vnf_p7->p7_connections) + { + //int16_t vnf_pnf_sfnsf_delta = NFAPI_SFNSF2DEC(vnf_p7->p7_connections[0].sfn_sf) - NFAPI_SFNSF2DEC(ind.last_sfn_sf); + int16_t vnf_pnf_sfnslot_delta = NFAPI_SFNSLOT2DEC(vnf_p7->p7_connections[0].sfn,vnf_p7->p7_connections[0].slot) - NFAPI_SFNSLOT2DEC(ind.last_sfn,ind.last_slot); + //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() PNF:SFN/SF:%d VNF:SFN/SF:%d deltaSFNSF:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(ind.last_sfn_sf), NFAPI_SFNSF2DEC(vnf_p7->p7_connections[0].sfn_sf), vnf_pnf_sfnsf_delta); + + // Panos: Careful here!!! Modification of the original nfapi-code + //if (vnf_pnf_sfnsf_delta>1 || vnf_pnf_sfnsf_delta < -1) + //printf("VNF-PNF delta - %d", vnf_pnf_sfnslot_delta); + if (vnf_pnf_sfnslot_delta>0 || vnf_pnf_sfnslot_delta < 0) + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() LARGE SFN/SF DELTA between PNF and VNF delta:%d VNF:%d PNF:%d\n\n\n\n\n\n\n\n\n", __FUNCTION__, vnf_pnf_sfnslot_delta,NFAPI_SFNSLOT2DEC(vnf_p7->p7_connections[0].sfn,vnf_p7->p7_connections[0].slot),NFAPI_SFNSLOT2DEC(ind.last_sfn,ind.last_slot)) ; + // Panos: Careful here!!! Modification of the original nfapi-code + // vnf_p7->p7_connections[0].sfn = ind.last_sfn; + // vnf_p7->p7_connections[0].slot = ind.last_slot; + } + } +} + void vnf_dispatch_p7_message(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) { nfapi_p7_message_header_t header; @@ -1378,6 +1999,101 @@ void vnf_dispatch_p7_message(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) } } +void vnf_nr_dispatch_p7_message(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) +{ + nfapi_p7_message_header_t header; + + // validate the input params + if(pRecvMsg == NULL || recvMsgLen < 4 || vnf_p7 == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s: invalid input params\n", __FUNCTION__); + return; + } + + // unpack the message header + if (nfapi_p7_message_header_unpack(pRecvMsg, recvMsgLen, &header, sizeof(header), &vnf_p7->_public.codec_config) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unpack message header failed, ignoring\n"); + return; + } + + // ensure the message is sensible + if (recvMsgLen < 8 || pRecvMsg == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_WARN, "Invalid message size: %d, ignoring\n", recvMsgLen); + return; + } + + switch (header.message_id) + { + case NFAPI_NR_PHY_MSG_TYPE_UL_NODE_SYNC: + vnf_nr_handle_ul_node_sync(pRecvMsg, recvMsgLen, vnf_p7); + break; + + case NFAPI_TIMING_INFO: + vnf_nr_handle_timing_info(pRecvMsg, recvMsgLen, vnf_p7); + break; + + case NFAPI_HARQ_INDICATION: + vnf_handle_harq_indication(pRecvMsg, recvMsgLen, vnf_p7); + break; + + case NFAPI_CRC_INDICATION: + vnf_handle_crc_indication(pRecvMsg, recvMsgLen, vnf_p7); + break; + + case NFAPI_RX_ULSCH_INDICATION: + vnf_handle_rx_ulsch_indication(pRecvMsg, recvMsgLen, vnf_p7); + break; + + case NFAPI_RACH_INDICATION: + vnf_handle_rach_indication(pRecvMsg, recvMsgLen, vnf_p7); + break; + + case NFAPI_SRS_INDICATION: + vnf_handle_srs_indication(pRecvMsg, recvMsgLen, vnf_p7); + break; + + case NFAPI_RX_SR_INDICATION: + vnf_handle_rx_sr_indication(pRecvMsg, recvMsgLen, vnf_p7); + break; + + case NFAPI_RX_CQI_INDICATION: + vnf_handle_rx_cqi_indication(pRecvMsg, recvMsgLen, vnf_p7); + break; + + case NFAPI_LBT_DL_INDICATION: + vnf_handle_lbt_dl_indication(pRecvMsg, recvMsgLen, vnf_p7); + break; + + case NFAPI_NB_HARQ_INDICATION: + vnf_handle_nb_harq_indication(pRecvMsg, recvMsgLen, vnf_p7); + break; + + case NFAPI_NRACH_INDICATION: + vnf_handle_nrach_indication(pRecvMsg, recvMsgLen, vnf_p7); + break; + + case NFAPI_UE_RELEASE_RESPONSE: + vnf_handle_ue_release_resp(pRecvMsg, recvMsgLen, vnf_p7); + break; + + default: + { + if(header.message_id >= NFAPI_VENDOR_EXT_MSG_MIN && + header.message_id <= NFAPI_VENDOR_EXT_MSG_MAX) + { + vnf_handle_p7_vendor_extension(pRecvMsg, recvMsgLen, vnf_p7, header.message_id); + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Unknown message ID %d\n", header.message_id); + } + } + break; + } +} + void vnf_handle_p7_message(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) { nfapi_p7_message_header_t messageHeader; @@ -1496,6 +2212,200 @@ void vnf_handle_p7_message(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) } } +void vnf_nr_handle_p7_message(void *pRecvMsg, int recvMsgLen, vnf_p7_t* vnf_p7) +{ + nfapi_p7_message_header_t messageHeader; + + // validate the input params + if(pRecvMsg == NULL || recvMsgLen < 4 || vnf_p7 == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "vnf_handle_p7_message: invalid input params (%d %d %d)\n", pRecvMsg, recvMsgLen, vnf_p7); + return; + } + + // unpack the message header + if (nfapi_p7_message_header_unpack(pRecvMsg, recvMsgLen, &messageHeader, sizeof(nfapi_p7_message_header_t), &vnf_p7->_public.codec_config) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unpack message header failed, ignoring\n"); + return; + } + + if(vnf_p7->_public.checksum_enabled) + { + uint32_t checksum = nfapi_p7_calculate_checksum(pRecvMsg, recvMsgLen); + if(checksum != messageHeader.checksum) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Checksum verification failed %d %d msg:%d len:%d\n", checksum, messageHeader.checksum, messageHeader.message_id, recvMsgLen); + return; + } + } + + uint8_t m = NFAPI_P7_GET_MORE(messageHeader.m_segment_sequence); + uint8_t segment_num = NFAPI_P7_GET_SEGMENT(messageHeader.m_segment_sequence); + uint8_t sequence_num = NFAPI_P7_GET_SEQUENCE(messageHeader.m_segment_sequence); + + + if(m == 0 && segment_num == 0) + { + // we have a complete message + // ensure the message is sensible + if (recvMsgLen < 8 || pRecvMsg == NULL) + { + NFAPI_TRACE(NFAPI_TRACE_WARN, "Invalid message size: %d, ignoring\n", recvMsgLen); + return; + } + + //vnf_dispatch_p7_message(&messageHeader, pRecvMsg, recvMsgLen, vnf_p7); + vnf_nr_dispatch_p7_message(pRecvMsg, recvMsgLen, vnf_p7); + } + else + { + nfapi_vnf_p7_connection_info_t* phy = vnf_p7_connection_info_list_find(vnf_p7, messageHeader.phy_id); + + if(phy) + { + vnf_p7_rx_message_t* rx_msg = vnf_p7_rx_reassembly_queue_add_segment(vnf_p7, &(phy->reassembly_queue), sequence_num, segment_num, m, pRecvMsg, recvMsgLen); + + if(rx_msg->num_segments_received == rx_msg->num_segments_expected) + { + // send the buffer on + uint16_t i = 0; + uint16_t length = 0; + for(i = 0; i < rx_msg->num_segments_expected; ++i) + { + length += rx_msg->segments[i].length - (i > 0 ? NFAPI_P7_HEADER_LENGTH : 0); + } + + if(phy->reassembly_buffer_size < length) + { + vnf_p7_free(vnf_p7, phy->reassembly_buffer); + phy->reassembly_buffer = 0; + } + + if(phy->reassembly_buffer == 0) + { + NFAPI_TRACE(NFAPI_TRACE_NOTE, "Resizing VNF_P7 Reassembly buffer %d->%d\n", phy->reassembly_buffer_size, length); + phy->reassembly_buffer = (uint8_t*)vnf_p7_malloc(vnf_p7, length); + + if(phy->reassembly_buffer == 0) + { + NFAPI_TRACE(NFAPI_TRACE_NOTE, "Failed to allocate VNF_P7 reassemby buffer len:%d\n", length); + return; + } + memset(phy->reassembly_buffer, 0, length); + phy->reassembly_buffer_size = length; + } + + uint16_t offset = 0; + for(i = 0; i < rx_msg->num_segments_expected; ++i) + { + if(i == 0) + { + memcpy(phy->reassembly_buffer, rx_msg->segments[i].buffer, rx_msg->segments[i].length); + offset += rx_msg->segments[i].length; + } + else + { + memcpy(phy->reassembly_buffer + offset, rx_msg->segments[i].buffer + NFAPI_P7_HEADER_LENGTH, rx_msg->segments[i].length - NFAPI_P7_HEADER_LENGTH); + offset += rx_msg->segments[i].length - NFAPI_P7_HEADER_LENGTH; + } + } + + + //pnf_dispatch_p7_message(pnf_p7->reassemby_buffer, length, pnf_p7, rx_msg->rx_hr_time); + vnf_nr_dispatch_p7_message(phy->reassembly_buffer, length , vnf_p7); + + + // delete the structure + vnf_p7_rx_reassembly_queue_remove_msg(vnf_p7, &(phy->reassembly_queue), rx_msg); + } + + vnf_p7_rx_reassembly_queue_remove_old_msgs(vnf_p7, &(phy->reassembly_queue), 1000); + } + else + { + + NFAPI_TRACE(NFAPI_TRACE_INFO, "Unknown phy id %d\n", messageHeader.phy_id); + } + } +} + +int vnf_nr_p7_read_dispatch_message(vnf_p7_t* vnf_p7) +{ + int recvfrom_result = 0; + struct sockaddr_in remote_addr; + socklen_t remote_addr_size = sizeof(remote_addr); + + do + { + // peek the header + uint8_t header_buffer[NFAPI_P7_HEADER_LENGTH]; + recvfrom_result = recvfrom(vnf_p7->socket, header_buffer, NFAPI_P7_HEADER_LENGTH, MSG_DONTWAIT | MSG_PEEK, (struct sockaddr*)&remote_addr, &remote_addr_size); + + if(recvfrom_result > 0) + { + // get the segment size + nfapi_p7_message_header_t header; + if(nfapi_p7_message_header_unpack(header_buffer, NFAPI_P7_HEADER_LENGTH, &header, sizeof(header), 0) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "Unpack message header failed, ignoring\n"); + return -1; + } + + // resize the buffer if we have a large segment + if(header.message_length > vnf_p7->rx_message_buffer_size) + { + NFAPI_TRACE(NFAPI_TRACE_NOTE, "reallocing rx buffer %d\n", header.message_length); + vnf_p7->rx_message_buffer = realloc(vnf_p7->rx_message_buffer, header.message_length); + vnf_p7->rx_message_buffer_size = header.message_length; + } + + // read the segment + recvfrom_result = recvfrom(vnf_p7->socket, vnf_p7->rx_message_buffer, header.message_length, MSG_WAITALL, (struct sockaddr*)&remote_addr, &remote_addr_size); + + // todo : how to handle incomplete readfroms, need some sort of buffer/select + + if(recvfrom_result == 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "recvfrom returned 0\n"); + } + else if(recvfrom_result != header.message_length) + { + NFAPI_TRACE(NFAPI_TRACE_NOTE, "did not receive the entire message %d %d\n", recvfrom_result, header.message_length); + + recvfrom_result += recvfrom(vnf_p7->socket, &vnf_p7->rx_message_buffer[recvfrom_result], header.message_length - recvfrom_result, MSG_WAITALL, (struct sockaddr*)&remote_addr, &remote_addr_size); + + } + + + if(recvfrom_result > 0) + { + vnf_nr_handle_p7_message(vnf_p7->rx_message_buffer, recvfrom_result, vnf_p7); + } + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "recvfrom failed %d %d\n", recvfrom_result, errno); + } + } + + if(recvfrom_result == -1) + { + if(errno == EAGAIN || errno == EWOULDBLOCK) + { + // return to the select + //NFAPI_TRACE(NFAPI_TRACE_WARN, "%s recvfrom would block :%d\n", __FUNCTION__, errno); + } + else + { + NFAPI_TRACE(NFAPI_TRACE_WARN, "%s recvfrom failed errno:%d\n", __FUNCTION__, errno); + } + } + } + while(recvfrom_result > 0); + + return 0; +} + int vnf_p7_read_dispatch_message(vnf_p7_t* vnf_p7) { int recvfrom_result = 0; diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c b/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c index a0efeeb5f4..3fa1f035fd 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c @@ -28,6 +28,7 @@ #define FAPI2_IP_DSCP 0 + nfapi_vnf_p7_config_t* nfapi_vnf_p7_config_create() { vnf_p7_t* _this = (vnf_p7_t*)calloc(1, sizeof(vnf_p7_t)); @@ -90,6 +91,368 @@ struct timespec timespec_sub(struct timespec lhs, struct timespec rhs) // monitor the p7 endpoints and the timing loop and // send indications to mac +int nfapi_nr_vnf_p7_start(nfapi_vnf_p7_config_t* config) +{ + if(config == 0) + return -1; + + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s()\n", __FUNCTION__); + + vnf_p7_t* vnf_p7 = (vnf_p7_t*)config; + + // Create p7 receive udp port + // todo : this needs updating for Ipv6 + + NFAPI_TRACE(NFAPI_TRACE_INFO, "Initialising VNF P7 port:%u\n", config->port); + + // open the UDP socket + if ((vnf_p7->socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After P7 socket errno: %d\n", errno); + return -1; + } + + NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF P7 socket created...\n"); + + // configure the UDP socket options + int iptos_value = FAPI2_IP_DSCP << 2; + if (setsockopt(vnf_p7->socket, IPPROTO_IP, IP_TOS, &iptos_value, sizeof(iptos_value)) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After setsockopt (IP_TOS) errno: %d\n", errno); + return -1; + } + + NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF P7 setsockopt succeeded...\n"); + + // Create the address structure + struct sockaddr_in addr; + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(config->port); + addr.sin_addr.s_addr = INADDR_ANY; + + // bind to the configured port + NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF P7 binding too %s:%d\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); + if (bind(vnf_p7->socket, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) + //if (sctp_bindx(config->socket, (struct sockaddr *)&addr, sizeof(struct sockaddr_in), 0) < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "After bind errno: %d\n", errno); + return -1; + } + + NFAPI_TRACE(NFAPI_TRACE_INFO, "VNF P7 bind succeeded...\n"); + + + //struct timespec original_pselect_timeout; + struct timespec pselect_timeout; + pselect_timeout.tv_sec = 0; + pselect_timeout.tv_nsec = 500000; // ns in a 0.5 ms + //pselect_timeout.tv_nsec = 500000; + + struct timespec pselect_start; + struct timespec pselect_stop; + + //struct timespec sf_end; + + long last_millisecond = -1; + + +// struct timespec sf_duration; //Change to slot_duration? +// sf_duration.tv_sec = 0; +// sf_duration.tv_nsec = 0.5e6; // We want 1ms pause //We want 0.5 ms pause for NR + struct timespec slot_duration; + slot_duration.tv_sec = 0; + //slot_duration.tv_nsec = 0.5e6; + slot_duration.tv_nsec = 0.5e6; + + +// struct timespec sf_start; //Change to slot_start? + struct timespec slot_start; +// clock_gettime(CLOCK_MONOTONIC, &sf_start); + clock_gettime(CLOCK_MONOTONIC, &slot_start); + long millisecond = slot_start.tv_nsec / 1e6; //Check if we have to change + //long millisecond = slot_start.tv_nsec / 0.5e6; +// sf_start = timespec_add(sf_start, sf_duration); + slot_start = timespec_add(slot_start, slot_duration); + + NFAPI_TRACE(NFAPI_TRACE_INFO, "next slot will start at %d.%d\n", slot_start.tv_sec, slot_start.tv_nsec); + + while(vnf_p7->terminate == 0) + { + fd_set rfds; + int maxSock = 0; + FD_ZERO(&rfds); + int selectRetval = 0; + + // Add the p7 socket + FD_SET(vnf_p7->socket, &rfds); + maxSock = vnf_p7->socket; + + clock_gettime(CLOCK_MONOTONIC, &pselect_start); + //long millisecond = pselect_start.tv_nsec / 1e6; + + if((last_millisecond == -1) || (millisecond == last_millisecond) || (millisecond == (last_millisecond + 1) % 1000) ) + { + //NFAPI_TRACE(NFAPI_TRACE_INFO, "pselect_start:%d.%d sf_start:%d.%d\n", pselect_start.tv_sec, pselect_start.tv_nsec, sf_start.tv_sec, sf_start.tv_nsec); + + + //if((pselect_start.tv_sec > sf_start.tv_sec) || + // ((pselect_start.tv_sec == sf_start.tv_sec) && (pselect_start.tv_nsec > sf_start.tv_nsec))) + if((pselect_start.tv_sec > slot_start.tv_sec) || ((pselect_start.tv_sec == slot_start.tv_sec) && (pselect_start.tv_nsec > slot_start.tv_nsec))) + { + // overran the end of the subframe we do not want to wait + pselect_timeout.tv_sec = 0; + pselect_timeout.tv_nsec = 0; + + //struct timespec overrun = timespec_sub(pselect_start, sf_start); + //NFAPI_TRACE(NFAPI_TRACE_INFO, "Subframe overrun detected of %d.%d running to catchup\n", overrun.tv_sec, overrun.tv_nsec); + } + else + { + // still time before the end of the subframe wait + //pselect_timeout = timespec_sub(sf_start, pselect_start); + pselect_timeout = timespec_sub(slot_start, pselect_start); + } + +//original_pselect_timeout = pselect_timeout; + + // detemine how long to sleep in ns before the start of the next 1ms + //pselect_timeout.tv_nsec = 1e6 - (pselect_start.tv_nsec % 1000000); + + //uint8_t underrun_possible =0; + + // if we are not sleeping until the next milisecond due to the + // insycn minor adjment flag it so we don't consider it an error + //uint8_t underrun_possible =0; + /* + { + nfapi_vnf_p7_connection_info_t* phy = vnf_p7->p7_connections; + if(phy && phy->in_sync && phy->insync_minor_adjustment != 0 && phy->insync_minor_adjustment_duration > 0 && pselect_start.tv_nsec != 0) + { + NFAPI_TRACE(NFAPI_TRACE_NOTE, "[VNF] Subframe minor adjustment %d (%d->%d)\n", phy->insync_minor_adjustment, + pselect_timeout.tv_nsec, pselect_timeout.tv_nsec - (phy->insync_minor_adjustment * 1000)) + if(phy->insync_minor_adjustment > 0) + { + // todo check we don't go below 0 + if((phy->insync_minor_adjustment * 1000) > pselect_timeout.tv_nsec) + pselect_timeout.tv_nsec = 0; + else + pselect_timeout.tv_nsec = pselect_timeout.tv_nsec - (phy->insync_minor_adjustment * 1000); + + + //underrun_possible = 1; + } + else if(phy->insync_minor_adjustment < 0) + { + // todo check we don't go below 0 + pselect_timeout.tv_nsec = pselect_timeout.tv_nsec - (phy->insync_minor_adjustment * 1000); + + + //phy->insync_minor_adjustment = 0; + phy->insync_minor_adjustment_duration--; + } + } + */ + + +//long wraps = pselect_timeout.tv_nsec % 1e9; + + + selectRetval = pselect(maxSock+1, &rfds, NULL, NULL, &pselect_timeout, NULL); + // selectRetval = pselect(120, &rfds, NULL, NULL, &pselect_timeout, NULL); + + clock_gettime(CLOCK_MONOTONIC, &pselect_stop); + + nfapi_vnf_p7_connection_info_t* phy = vnf_p7->p7_connections; + +if (selectRetval==-1 && errno == 22) +{ +// NFAPI_TRACE(NFAPI_TRACE_ERROR, "INVAL: pselect_timeout:%d.%ld adj[dur:%d adj:%d], sf_dur:%d.%ld\n", +// pselect_timeout.tv_sec, pselect_timeout.tv_nsec, +// phy->insync_minor_adjustment_duration, phy->insync_minor_adjustment, +// sf_duration.tv_sec, sf_duration.tv_nsec); + +NFAPI_TRACE(NFAPI_TRACE_ERROR, "INVAL: pselect_timeout:%d.%ld adj[dur:%d adj:%d], sf_dur:%d.%ld\n", + pselect_timeout.tv_sec, pselect_timeout.tv_nsec, + phy->insync_minor_adjustment_duration, phy->insync_minor_adjustment, + slot_duration.tv_sec, slot_duration.tv_nsec); + +} + if(selectRetval == 0) + { + // calculate the start of the next slot + //sf_start = timespec_add(sf_start, sf_duration); + slot_start = timespec_add(slot_start, slot_duration); + //NFAPI_TRACE(NFAPI_TRACE_INFO, "next subframe will start at %d.%d\n", sf_start.tv_sec, sf_start.tv_nsec); + + if(phy && phy->in_sync && phy->insync_minor_adjustment != 0 && phy->insync_minor_adjustment_duration > 0) + { + long insync_minor_adjustment_ns = (phy->insync_minor_adjustment * 1000); + + //sf_start.tv_nsec -= insync_minor_adjustment_ns; + slot_start.tv_nsec -= insync_minor_adjustment_ns; + +#if 1 +/* if (sf_start.tv_nsec > 1e9) //Change to 0.5e6? + { + sf_start.tv_sec++; + sf_start.tv_nsec-=1e9; + } + else if (sf_start.tv_nsec < 0) + { + sf_start.tv_sec--; + sf_start.tv_nsec+=1e9; + }*/ + if (slot_start.tv_nsec > 1e9) + { + slot_start.tv_sec++; + slot_start.tv_nsec-=1e9; + } + else if (slot_start.tv_nsec < 0) + { + slot_start.tv_sec--; + slot_start.tv_nsec+=1e9; + } +#else + //NFAPI_TRACE(NFAPI_TRACE_NOTE, "[VNF] BEFORE adjustment - Subframe minor adjustment %dus sf_start.tv_nsec:%d\n", phy->insync_minor_adjustment, sf_start.tv_nsec); + if(phy->insync_minor_adjustment > 0) + { + // decrease the subframe duration a little + if (sf_start.tv_nsec > insync_minor_adjustment_ns) + sf_start.tv_nsec -= insync_minor_adjustment_ns; + else + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "[VNF] Adjustment would make it negative sf:%d.%ld adjust:%ld\n\n\n", sf_start.tv_sec, sf_start.tv_nsec, insync_minor_adjustment_ns); + sf_start.tv_sec--; + sf_start.tv_nsec += 1e9 - insync_minor_adjustment_ns; + } + } + else if(phy->insync_minor_adjustment < 0) + { + // todo check we don't go below 0 + // increase the subframe duration a little + sf_start.tv_nsec += insync_minor_adjustment_ns; + + if (sf_start.tv_nsec < 0) + { + NFAPI_TRACE(NFAPI_TRACE_ERROR, "[VNF] OVERFLOW %d.%ld\n\n\n\n", sf_start.tv_sec, sf_start.tv_nsec); + sf_start.tv_sec++; + sf_start.tv_nsec += 1e9; + } + } +#endif + + //phy->insync_minor_adjustment = 0; + phy->insync_minor_adjustment_duration--; + +// NFAPI_TRACE(NFAPI_TRACE_NOTE, "[VNF] AFTER adjustment - Subframe minor adjustment %dus sf_start.tv_nsec:%d duration:%u\n", +// phy->insync_minor_adjustment, sf_start.tv_nsec, phy->insync_minor_adjustment_duration); + // NFAPI_TRACE(NFAPI_TRACE_NOTE, "[VNF] AFTER adjustment - Slot minor adjustment %dus slot_start.tv_nsec:%d duration:%u\n", + // phy->insync_minor_adjustment, slot_start.tv_nsec, phy->insync_minor_adjustment_duration); + + if (phy->insync_minor_adjustment_duration==0) + { + phy->insync_minor_adjustment = 0; + } + } + /* + long pselect_stop_millisecond = pselect_stop.tv_nsec / 1e6; + if(millisecond == pselect_stop_millisecond) + { + // we have woke up in the same subframe + if(underrun_possible == 0) + NFAPI_TRACE(NFAPI_TRACE_WARN, "subframe pselect underrun %ld (%d.%d)\n", millisecond, pselect_stop.tv_sec, pselect_stop.tv_nsec); + } + else if(((millisecond + 1) % 1000) != pselect_stop_millisecond) + { + // we have overrun the subframe + NFAPI_TRACE(NFAPI_TRACE_WARN, "subframe pselect overrun %ld %ld\n", millisecond, pselect_stop_millisecond); + NFAPI_TRACE(NFAPI_TRACE_WARN, "subframe underrun %ld\n", millisecond); + } + last_millisecond = millisecond; + */ + + //millisecond ++; + millisecond = millisecond + 1; + + } + } + else + { + // we have overrun the subframe advance to go and collect $200 + + if((millisecond - last_millisecond) > 3) + NFAPI_TRACE(NFAPI_TRACE_WARN, "subframe overrun %ld %ld (%ld)\n", millisecond, last_millisecond, millisecond - last_millisecond + 1); + + last_millisecond = ( last_millisecond + 1 ) % 1000; + selectRetval = 0; + } + + if(selectRetval == 0) + { + //vnf_p7->sf_start_time_hr = vnf_get_current_time_hr(); + vnf_p7->slot_start_time_hr = vnf_get_current_time_hr(); +struct timespec current_time; + clock_gettime(CLOCK_MONOTONIC, ¤t_time); + // pselect timed out + nfapi_vnf_p7_connection_info_t* curr = vnf_p7->p7_connections; + while(curr != 0) + { + if (curr->slot == 19) + { //curr->slot = 0; + if(curr->sfn == 1023) + curr->sfn=0; + else + curr->sfn++; + curr->slot=0; + } + else + { + curr->slot++; + } + vnf_nr_sync(vnf_p7, curr); + curr = curr->next; + } + send_mac_slot_indications(vnf_p7); + } + else if(selectRetval > 0) + { + // have a p7 message + if(FD_ISSET(vnf_p7->socket, &rfds)) + { + vnf_nr_p7_read_dispatch_message(vnf_p7); + } + } + else + { + // pselect error + if(selectRetval == -1 && errno == EINTR) + { + // a sigal was received. + } + else + { + NFAPI_TRACE(NFAPI_TRACE_INFO, "P7 select failed result %d errno %d timeout:%d.%d orginal:%d.%d last_ms:%ld ms:%ld\n", selectRetval, errno, pselect_timeout.tv_sec, pselect_timeout.tv_nsec, pselect_timeout.tv_sec, pselect_timeout.tv_nsec, last_millisecond, millisecond); + // should we exit now? + if (selectRetval == -1 && errno == 22) // invalid argument??? not sure about timeout duration + { + usleep(100000); + } + } + } + + } + + + NFAPI_TRACE(NFAPI_TRACE_INFO, "Closing p7 socket\n"); + close(vnf_p7->socket); + + NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() returning\n", __FUNCTION__); + + return 0; +} + + int nfapi_vnf_p7_start(nfapi_vnf_p7_config_t* config) { if(config == 0) @@ -408,6 +771,7 @@ if (selectRetval==-1 && errno == 22) return 0; } + int nfapi_vnf_p7_stop(nfapi_vnf_p7_config_t* config) { if(config == 0) @@ -434,17 +798,18 @@ int nfapi_vnf_p7_add_pnf(nfapi_vnf_p7_config_t* config, const char* pnf_p7_addr, memset(node, 0, sizeof(nfapi_vnf_p7_connection_info_t)); node->phy_id = phy_id; node->in_sync = 0; - node->dl_out_sync_offset = 30; + node->dl_out_sync_offset = 30;//TODO: Values need to be changed for NR,How to set the values node->dl_out_sync_period = 10; node->dl_in_sync_offset = 30; node->dl_in_sync_period = 512; - node->sfn_sf = 0; - + //node->sfn_sf = 0; + node->sfn = 0; + node->slot = 0; node->min_sync_cycle_count = 8; // save the remote endpoint information node->remote_addr.sin_family = AF_INET; - node->remote_addr.sin_port = htons(pnf_p7_port); + node->remote_addr.sin_port = pnf_p7_port;//htons(pnf_p7_port); node->remote_addr.sin_addr.s_addr = inet_addr(pnf_p7_addr); vnf_p7_connection_info_list_add(vnf_p7, node); @@ -490,7 +855,16 @@ int nfapi_vnf_p7_nr_dl_config_req(nfapi_vnf_p7_config_t* config, nfapi_nr_dl_tti return -1; vnf_p7_t* vnf_p7 = (vnf_p7_t*)config; - return vnf_p7_pack_and_send_p7_msg(vnf_p7, &req->header); + return vnf_nr_p7_pack_and_send_p7_msg(vnf_p7, &req->header); +} + +int nfapi_vnf_p7_ul_tti_req(nfapi_vnf_p7_config_t* config, nfapi_nr_ul_tti_request_t* req) +{ + if(config == 0 || req == 0) + return -1; + + vnf_p7_t* vnf_p7 = (vnf_p7_t*)config; + return vnf_nr_p7_pack_and_send_p7_msg(vnf_p7, &req->header); } int nfapi_vnf_p7_ul_config_req(nfapi_vnf_p7_config_t* config, nfapi_ul_config_request_t* req) @@ -501,6 +875,14 @@ int nfapi_vnf_p7_ul_config_req(nfapi_vnf_p7_config_t* config, nfapi_ul_config_re vnf_p7_t* vnf_p7 = (vnf_p7_t*)config; return vnf_p7_pack_and_send_p7_msg(vnf_p7, &req->header); } +int nfapi_vnf_p7_ul_dci_req(nfapi_vnf_p7_config_t* config, nfapi_nr_ul_dci_request_t* req) +{ + if(config == 0 || req == 0) + return -1; + + vnf_p7_t* vnf_p7 = (vnf_p7_t*)config; + return vnf_nr_p7_pack_and_send_p7_msg(vnf_p7, &req->header); +} int nfapi_vnf_p7_hi_dci0_req(nfapi_vnf_p7_config_t* config, nfapi_hi_dci0_request_t* req) { if(config == 0 || req == 0) @@ -509,6 +891,14 @@ int nfapi_vnf_p7_hi_dci0_req(nfapi_vnf_p7_config_t* config, nfapi_hi_dci0_reques vnf_p7_t* vnf_p7 = (vnf_p7_t*)config; return vnf_p7_pack_and_send_p7_msg(vnf_p7, &req->header); } +int nfapi_vnf_p7_tx_data_req(nfapi_vnf_p7_config_t* config, nfapi_nr_tx_data_request_t* req) +{ + if(config == 0 || req == 0) + return -1; + + vnf_p7_t* vnf_p7 = (vnf_p7_t*)config; + return vnf_nr_p7_pack_and_send_p7_msg(vnf_p7, &req->header); +} int nfapi_vnf_p7_tx_req(nfapi_vnf_p7_config_t* config, nfapi_tx_request_t* req) { if(config == 0 || req == 0) diff --git a/openair1/PHY/INIT/nr_init.c b/openair1/PHY/INIT/nr_init.c index 9897a4d399..d00bc90315 100644 --- a/openair1/PHY/INIT/nr_init.c +++ b/openair1/PHY/INIT/nr_init.c @@ -84,8 +84,6 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB, NR_gNB_COMMON *const common_vars = &gNB->common_vars; NR_gNB_PRACH *const prach_vars = &gNB->prach_vars; NR_gNB_PUSCH **const pusch_vars = gNB->pusch_vars; - /*LTE_eNB_SRS *const srs_vars = gNB->srs_vars; - LTE_eNB_PRACH *const prach_vars = &gNB->prach_vars;*/ int i; int Ptx=cfg->carrier_config.num_tx_ant.value; @@ -98,19 +96,7 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB, while(gNB->configured == 0) usleep(10000); load_dftslib(); - /* - LOG_I(PHY,"[gNB %"PRIu8"] Initializing DL_FRAME_PARMS : N_RB_DL %"PRIu8", PHICH Resource %d, PHICH Duration %d nb_antennas_tx:%u nb_antennas_rx:%u PRACH[rootSequenceIndex:%u prach_Config_enabled:%u configIndex:%u highSpeed:%u zeroCorrelationZoneConfig:%u freqOffset:%u]\n", - gNB->Mod_id, - fp->N_RB_DL,fp->phich_config_common.phich_resource, - fp->phich_config_common.phich_duration, - fp->nb_antennas_tx, fp->nb_antennas_rx, - fp->prach_config_common.rootSequenceIndex, - fp->prach_config_common.prach_Config_enabled, - fp->prach_config_common.prach_ConfigInfo.prach_ConfigIndex, - fp->prach_config_common.prach_ConfigInfo.highSpeedFlag, - fp->prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig, - fp->prach_config_common.prach_ConfigInfo.prach_FreqOffset - );*/ + LOG_D(PHY,"[MSC_NEW][FRAME 00000][PHY_gNB][MOD %02"PRIu8"][]\n", gNB->Mod_id); crcTableInit(); init_scrambling_luts(); @@ -264,9 +250,7 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB, int N_RB_UL = cfg->carrier_config.ul_grid_size[cfg->ssb_config.scs_common.value].value; - printf("Before ULSCH init : %p\n",gNB->dlsch[0][0]->harq_processes[0]); for (int ULSCH_id=0; ULSCH_iddlsch[0][0]->harq_processes[0]); pusch_vars[ULSCH_id] = (NR_gNB_PUSCH *)malloc16_clear( sizeof(NR_gNB_PUSCH) ); pusch_vars[ULSCH_id]->rxdataF_ext = (int32_t **)malloc16(Prx*sizeof(int32_t *) ); pusch_vars[ULSCH_id]->rxdataF_ext2 = (int32_t **)malloc16(Prx*sizeof(int32_t *) ); @@ -283,7 +267,6 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB, pusch_vars[ULSCH_id]->ul_ch_magb = (int32_t **)malloc16(Prx*sizeof(int32_t *) ); pusch_vars[ULSCH_id]->rho = (int32_t **)malloc16_clear(Prx*sizeof(int32_t*) ); - printf("ULSCH_id %d (before rx antenna alloc) : %p\n",ULSCH_id,gNB->dlsch[0][0]->harq_processes[0]); for (i=0; irxdataF_ext[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*N_RB_UL*12*fp->symbols_per_slot ); pusch_vars[ULSCH_id]->rxdataF_ext2[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*N_RB_UL*12*fp->symbols_per_slot ); @@ -300,16 +283,13 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB, pusch_vars[ULSCH_id]->ul_ch_magb[i] = (int32_t *)malloc16_clear( fp->symbols_per_slot*sizeof(int32_t)*N_RB_UL*12 ); pusch_vars[ULSCH_id]->rho[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*(fp->N_RB_UL*12*7*2) ); } - printf("ULSCH_id %d (before llr alloc) : %p\n",ULSCH_id,gNB->dlsch[0][0]->harq_processes[0]); pusch_vars[ULSCH_id]->llr = (int16_t *)malloc16_clear( (8*((3*8*6144)+12))*sizeof(int16_t) ); // [hna] 6144 is LTE and (8*((3*8*6144)+12)) is not clear - printf("ULSCH_id %d (after llr alloc) : %p\n",ULSCH_id,gNB->dlsch[0][0]->harq_processes[0]); pusch_vars[ULSCH_id]->ul_valid_re_per_slot = (int16_t *)malloc16_clear( sizeof(int16_t)*fp->symbols_per_slot); } //ulsch_id /* for (ulsch_id=0; ulsch_idUE_stats_ptr[ulsch_id] = &gNB->UE_stats[ulsch_id]; */ - printf("After ULSCH init : %p\n",gNB->dlsch[0][0]->harq_processes[0]); return (0); } @@ -401,6 +381,13 @@ void phy_free_nr_gNB(PHY_VARS_gNB *gNB) } + +//Adding nr_schedule_handler +void install_nr_schedule_handlers(NR_IF_Module_t *if_inst) +{ + if_inst->NR_PHY_config_req = nr_phy_config_request; + if_inst->NR_Schedule_response = nr_schedule_response; +} /* void install_schedule_handlers(IF_Module_t *if_inst) { @@ -479,7 +466,10 @@ void nr_phy_config_request(NR_PHY_Config_t *phy_config) { uint64_t ul_bw_khz = (12*gNB_config->carrier_config.ul_grid_size[gNB_config->ssb_config.scs_common.value].value)*(15<ssb_config.scs_common.value); fp->ul_CarrierFreq = ((ul_bw_khz>>1) + gNB_config->carrier_config.uplink_frequency.value)*1000 ; - fp->nr_band = *RC.nrmac[Mod_id]->common_channels[0].ServingCellConfigCommon->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]; + //fp->nr_band = *RC.nrmac[Mod_id]->common_channels[0].ServingCellConfigCommon->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]; + lte_frame_type_t frame_type = 0; // FDD + + get_band(fp->dl_CarrierFreq,&fp->nr_band,&dlul_offset,&frame_type); //RC.nrmac[Mod_id] cannot be accessed in NFAPI get_delta_duplex(fp->nr_band, gNB_config->ssb_config.scs_common.value, &dlul_offset); dlul_offset *= 1000; @@ -519,6 +509,7 @@ void nr_phy_config_request(NR_PHY_Config_t *phy_config) { LOG_I(PHY,"gNB %d configured\n",Mod_id); } + void init_nr_transport(PHY_VARS_gNB *gNB) { int i; int j; diff --git a/openair1/PHY/INIT/nr_init_ue.c b/openair1/PHY/INIT/nr_init_ue.c index ff1b00e65e..8bcc58160f 100644 --- a/openair1/PHY/INIT/nr_init_ue.c +++ b/openair1/PHY/INIT/nr_init_ue.c @@ -41,327 +41,17 @@ #include "PHY/NR_REFSIG/refsig_defs_ue.h" #include "PHY/NR_REFSIG/nr_refsig.h" -//uint8_t dmrs1_tab_ue[8] = {0,2,3,4,6,8,9,10}; - -/*void phy_config_sib1_ue(uint8_t Mod_id,int CC_id, - uint8_t eNB_id, - TDD_Config_t *tdd_Config, - uint8_t SIwindowsize, - uint16_t SIperiod) -{ - - NR_DL_FRAME_PARMS *fp = &PHY_vars_UE_g[Mod_id][CC_id]->frame_parms; - - if (tdd_Config) { - fp->tdd_config = tdd_Config->subframeAssignment; - fp->tdd_config_S = tdd_Config->specialSubframePatterns; - } - - fp->SIwindowsize = SIwindowsize; - fp->SIPeriod = SIperiod; -} - -void phy_config_sib2_ue(uint8_t Mod_id,int CC_id, - uint8_t eNB_id, - RadioResourceConfigCommonSIB_t *radioResourceConfigCommon, - ARFCN_ValueEUTRA_t *ul_CarrierFreq, - long *ul_Bandwidth, - AdditionalSpectrumEmission_t *additionalSpectrumEmission, - struct MBSFN_SubframeConfigList *mbsfn_SubframeConfigList) -{ - - PHY_VARS_UE *ue = PHY_vars_UE_g[Mod_id][CC_id]; - NR_DL_FRAME_PARMS *fp = &ue->frame_parms; - int i; - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_UE_CONFIG_SIB2, VCD_FUNCTION_IN); - - LOG_I(PHY,"[UE%d] Applying radioResourceConfigCommon from eNB%d\n",Mod_id,eNB_id); - - ue->prach_vars[eNB_id]->prach_pdu.root_seq_id =radioResourceConfigCommon->prach_Config.rootSequenceIndex; - - ue->prach_vars[eNB_id]->prach_Config_enabled=1; - //ue->prach_vars[eNB_id]->prach_pdu.prach_ConfigIndex =radioResourceConfigCommon->prach_Config.prach_ConfigInfo.prach_ConfigIndex; - ue->prach_vars[eNB_id]->prach_pdu.restricted_set =radioResourceConfigCommon->prach_Config.prach_ConfigInfo.highSpeedFlag; - ue->prach_vars[eNB_id]->prach_pdu.num_cs =radioResourceConfigCommon->prach_Config.prach_ConfigInfo.zeroCorrelationZoneConfig; - //ue->prach_vars[eNB_id]->prach_pdu.prach_FreqOffset =radioResourceConfigCommon->prach_Config.prach_ConfigInfo.prach_FreqOffset; - - //compute_prach_seq(fp->prach_config_common.rootSequenceIndex, - // fp->prach_config_common.prach_ConfigInfo.prach_ConfigIndex, - // fp->prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig, - // fp->prach_config_common.prach_ConfigInfo.highSpeedFlag, - // fp->frame_type,ue->X_u); - - - - fp->pucch_config_common.deltaPUCCH_Shift = 1+radioResourceConfigCommon->pucch_ConfigCommon.deltaPUCCH_Shift; - fp->pucch_config_common.nRB_CQI = radioResourceConfigCommon->pucch_ConfigCommon.nRB_CQI; - fp->pucch_config_common.nCS_AN = radioResourceConfigCommon->pucch_ConfigCommon.nCS_AN; - fp->pucch_config_common.n1PUCCH_AN = radioResourceConfigCommon->pucch_ConfigCommon.n1PUCCH_AN; - - - - fp->pdsch_config_common.referenceSignalPower = radioResourceConfigCommon->pdsch_ConfigCommon.referenceSignalPower; - fp->pdsch_config_common.p_b = radioResourceConfigCommon->pdsch_ConfigCommon.p_b; - - - fp->pusch_config_common.n_SB = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.n_SB; - fp->pusch_config_common.hoppingMode = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.hoppingMode; - fp->pusch_config_common.pusch_HoppingOffset = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.pusch_HoppingOffset; - fp->pusch_config_common.enable64QAM = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.enable64QAM; - fp->pusch_config_common.ul_ReferenceSignalsPUSCH.groupHoppingEnabled = radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.groupHoppingEnabled; - fp->pusch_config_common.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH = radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH; - fp->pusch_config_common.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled = radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled; - fp->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift = dmrs1_tab_ue[radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.cyclicShift]; - - - init_ul_hopping(fp); - fp->soundingrs_ul_config_common.enabled_flag = 0; - - if (radioResourceConfigCommon->soundingRS_UL_ConfigCommon.present==SoundingRS_UL_ConfigCommon_PR_setup) { - fp->soundingrs_ul_config_common.enabled_flag = 1; - fp->soundingrs_ul_config_common.srs_BandwidthConfig = radioResourceConfigCommon->soundingRS_UL_ConfigCommon.choice.setup.srs_BandwidthConfig; - fp->soundingrs_ul_config_common.srs_SubframeConfig = radioResourceConfigCommon->soundingRS_UL_ConfigCommon.choice.setup.srs_SubframeConfig; - fp->soundingrs_ul_config_common.ackNackSRS_SimultaneousTransmission = radioResourceConfigCommon->soundingRS_UL_ConfigCommon.choice.setup.ackNackSRS_SimultaneousTransmission; - - if (radioResourceConfigCommon->soundingRS_UL_ConfigCommon.choice.setup.srs_MaxUpPts) - fp->soundingrs_ul_config_common.srs_MaxUpPts = 1; - else - fp->soundingrs_ul_config_common.srs_MaxUpPts = 0; - } - - - - fp->ul_power_control_config_common.p0_NominalPUSCH = radioResourceConfigCommon->uplinkPowerControlCommon.p0_NominalPUSCH; - fp->ul_power_control_config_common.alpha = radioResourceConfigCommon->uplinkPowerControlCommon.alpha; - fp->ul_power_control_config_common.p0_NominalPUCCH = radioResourceConfigCommon->uplinkPowerControlCommon.p0_NominalPUCCH; - fp->ul_power_control_config_common.deltaPreambleMsg3 = radioResourceConfigCommon->uplinkPowerControlCommon.deltaPreambleMsg3; - fp->ul_power_control_config_common.deltaF_PUCCH_Format1 = radioResourceConfigCommon->uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format1; - fp->ul_power_control_config_common.deltaF_PUCCH_Format1b = radioResourceConfigCommon->uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format1b; - fp->ul_power_control_config_common.deltaF_PUCCH_Format2 = radioResourceConfigCommon->uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format2; - fp->ul_power_control_config_common.deltaF_PUCCH_Format2a = radioResourceConfigCommon->uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format2a; - fp->ul_power_control_config_common.deltaF_PUCCH_Format2b = radioResourceConfigCommon->uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format2b; - - fp->maxHARQ_Msg3Tx = radioResourceConfigCommon->rach_ConfigCommon.maxHARQ_Msg3Tx; - - // Now configure some of the Physical Channels - - // PUCCH - init_ncs_cell(fp,ue->ncs_cell); - - init_ul_hopping(fp); - - // PCH - init_ue_paging_info(ue,radioResourceConfigCommon->pcch_Config.defaultPagingCycle,radioResourceConfigCommon->pcch_Config.nB); - - // MBSFN - - if (mbsfn_SubframeConfigList != NULL) { - fp->num_MBSFN_config = mbsfn_SubframeConfigList->list.count; - - for (i=0; ilist.count; i++) { - fp->MBSFN_config[i].radioframeAllocationPeriod = mbsfn_SubframeConfigList->list.array[i]->radioframeAllocationPeriod; - fp->MBSFN_config[i].radioframeAllocationOffset = mbsfn_SubframeConfigList->list.array[i]->radioframeAllocationOffset; - - if (mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.present == MBSFN_SubframeConfig__subframeAllocation_PR_oneFrame) { - fp->MBSFN_config[i].fourFrames_flag = 0; - fp->MBSFN_config[i].mbsfn_SubframeConfig = mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.choice.oneFrame.buf[0]; // 6-bit subframe configuration - LOG_I(PHY, "[CONFIG] MBSFN_SubframeConfig[%d] pattern is %d\n", i, - fp->MBSFN_config[i].mbsfn_SubframeConfig); - } else if (mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.present == MBSFN_SubframeConfig__subframeAllocation_PR_fourFrames) { // 24-bit subframe configuration - fp->MBSFN_config[i].fourFrames_flag = 1; - fp->MBSFN_config[i].mbsfn_SubframeConfig = - mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.choice.oneFrame.buf[0]| - (mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.choice.oneFrame.buf[1]<<8)| - (mbsfn_SubframeConfigList->list.array[i]->subframeAllocation.choice.oneFrame.buf[2]<<16); - - LOG_I(PHY, "[CONFIG] MBSFN_SubframeConfig[%d] pattern is %d\n", i, - fp->MBSFN_config[i].mbsfn_SubframeConfig); - } - } - } - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_UE_CONFIG_SIB2, VCD_FUNCTION_OUT); - -} - -void phy_config_sib13_ue(uint8_t Mod_id,int CC_id,uint8_t eNB_id,int mbsfn_Area_idx, - long mbsfn_AreaId_r9) -{ - - NR_DL_FRAME_PARMS *fp = &PHY_vars_UE_g[Mod_id][CC_id]->frame_parms; - - - LOG_I(PHY,"[UE%d] Applying MBSFN_Area_id %ld for index %d\n",Mod_id,mbsfn_AreaId_r9,mbsfn_Area_idx); - - if (mbsfn_Area_idx == 0) { - fp->Nid_cell_mbsfn = (uint16_t)mbsfn_AreaId_r9; - LOG_N(PHY,"Fix me: only called when mbsfn_Area_idx == 0)\n"); - } - - lte_gold_mbsfn(fp,PHY_vars_UE_g[Mod_id][CC_id]->lte_gold_mbsfn_table,fp->Nid_cell_mbsfn); - -}*/ - - -/* - * Configures UE MAC and PHY with radioResourceCommon received in mobilityControlInfo IE during Handover - */ -/*void phy_config_afterHO_ue(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_id, MobilityControlInfo_t *mobilityControlInfo, uint8_t ho_failed) -{ - - if(mobilityControlInfo!=NULL) { - RadioResourceConfigCommon_t *radioResourceConfigCommon = &mobilityControlInfo->radioResourceConfigCommon; - LOG_I(PHY,"radioResourceConfigCommon %p\n", radioResourceConfigCommon); - memcpy((void *)&PHY_vars_UE_g[Mod_id][CC_id]->frame_parms_before_ho, - (void *)&PHY_vars_UE_g[Mod_id][CC_id]->frame_parms, - sizeof(NR_DL_FRAME_PARMS)); - PHY_vars_UE_g[Mod_id][CC_id]->ho_triggered = 1; - //PHY_vars_UE_g[UE_id]->UE_mode[0] = PRACH; - - NR_DL_FRAME_PARMS *fp = &PHY_vars_UE_g[Mod_id][CC_id]->frame_parms; - // int N_ZC; - // uint8_t prach_fmt; - // int u; - - LOG_I(PHY,"[UE%d] Handover triggered: Applying radioResourceConfigCommon from eNB %d\n", - Mod_id,eNB_id); - - ue->prach_vars[eNB_id]->prach_pdu.root_seq_id =radioResourceConfigCommon->prach_Config.rootSequenceIndex; - ue->prach_vars[eNB_id]->prach_Config_enabled=1; - //ue->prach_vars[eNB_id]->prach_pdu.prach_ConfigIndex =radioResourceConfigCommon->prach_Config.prach_ConfigInfo->prach_ConfigIndex; - ue->prach_vars[eNB_id]->prach_pdu.restricted_set =radioResourceConfigCommon->prach_Config.prach_ConfigInfo->highSpeedFlag; - ue->prach_vars[eNB_id]->prach_pdu.num_cs =radioResourceConfigCommon->prach_Config.prach_ConfigInfo->zeroCorrelationZoneConfig; - //ue->prach_vars[eNB_id]->prach_pdu.prach_FreqOffset =radioResourceConfigCommon->prach_Config.prach_ConfigInfo->prach_FreqOffset; - - // prach_fmt = get_prach_fmt(radioResourceConfigCommon->prach_Config.prach_ConfigInfo->prach_ConfigIndex,fp->frame_type); - // N_ZC = (prach_fmt <4)?839:139; - // u = (prach_fmt < 4) ? prach_root_sequence_map0_3[fp->prach_config_common.rootSequenceIndex] : - // prach_root_sequence_map4[fp->prach_config_common.rootSequenceIndex]; - - //compute_prach_seq(u,N_ZC, PHY_vars_UE_g[Mod_id]->X_u); - //compute_prach_seq(PHY_vars_UE_g[Mod_id][CC_id]->frame_parms.prach_config_common.rootSequenceIndex, - // PHY_vars_UE_g[Mod_id][CC_id]->frame_parms.prach_config_common.prach_ConfigInfo.prach_ConfigIndex, - // PHY_vars_UE_g[Mod_id][CC_id]->frame_parms.prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig, - // PHY_vars_UE_g[Mod_id][CC_id]->frame_parms.prach_config_common.prach_ConfigInfo.highSpeedFlag, - // fp->frame_type, - // PHY_vars_UE_g[Mod_id][CC_id]->X_u); - - - fp->pucch_config_common.deltaPUCCH_Shift = 1+radioResourceConfigCommon->pucch_ConfigCommon->deltaPUCCH_Shift; - fp->pucch_config_common.nRB_CQI = radioResourceConfigCommon->pucch_ConfigCommon->nRB_CQI; - fp->pucch_config_common.nCS_AN = radioResourceConfigCommon->pucch_ConfigCommon->nCS_AN; - fp->pucch_config_common.n1PUCCH_AN = radioResourceConfigCommon->pucch_ConfigCommon->n1PUCCH_AN; - fp->pdsch_config_common.referenceSignalPower = radioResourceConfigCommon->pdsch_ConfigCommon->referenceSignalPower; - fp->pdsch_config_common.p_b = radioResourceConfigCommon->pdsch_ConfigCommon->p_b; - - - fp->pusch_config_common.n_SB = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.n_SB; - fp->pusch_config_common.hoppingMode = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.hoppingMode; - fp->pusch_config_common.pusch_HoppingOffset = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.pusch_HoppingOffset; - fp->pusch_config_common.enable64QAM = radioResourceConfigCommon->pusch_ConfigCommon.pusch_ConfigBasic.enable64QAM; - fp->pusch_config_common.ul_ReferenceSignalsPUSCH.groupHoppingEnabled = radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.groupHoppingEnabled; - fp->pusch_config_common.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH = radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH; - fp->pusch_config_common.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled = radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled; - fp->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift = radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.cyclicShift; - - init_ul_hopping(fp); - fp->soundingrs_ul_config_common.enabled_flag = 0; - - if (radioResourceConfigCommon->soundingRS_UL_ConfigCommon->present==SoundingRS_UL_ConfigCommon_PR_setup) { - fp->soundingrs_ul_config_common.enabled_flag = 1; - fp->soundingrs_ul_config_common.srs_BandwidthConfig = radioResourceConfigCommon->soundingRS_UL_ConfigCommon->choice.setup.srs_BandwidthConfig; - fp->soundingrs_ul_config_common.srs_SubframeConfig = radioResourceConfigCommon->soundingRS_UL_ConfigCommon->choice.setup.srs_SubframeConfig; - fp->soundingrs_ul_config_common.ackNackSRS_SimultaneousTransmission = radioResourceConfigCommon->soundingRS_UL_ConfigCommon->choice.setup.ackNackSRS_SimultaneousTransmission; - - if (radioResourceConfigCommon->soundingRS_UL_ConfigCommon->choice.setup.srs_MaxUpPts) - fp->soundingrs_ul_config_common.srs_MaxUpPts = 1; - else - fp->soundingrs_ul_config_common.srs_MaxUpPts = 0; - } - - fp->ul_power_control_config_common.p0_NominalPUSCH = radioResourceConfigCommon->uplinkPowerControlCommon->p0_NominalPUSCH; - fp->ul_power_control_config_common.alpha = radioResourceConfigCommon->uplinkPowerControlCommon->alpha; - fp->ul_power_control_config_common.p0_NominalPUCCH = radioResourceConfigCommon->uplinkPowerControlCommon->p0_NominalPUCCH; - fp->ul_power_control_config_common.deltaPreambleMsg3 = radioResourceConfigCommon->uplinkPowerControlCommon->deltaPreambleMsg3; - fp->ul_power_control_config_common.deltaF_PUCCH_Format1 = radioResourceConfigCommon->uplinkPowerControlCommon->deltaFList_PUCCH.deltaF_PUCCH_Format1; - fp->ul_power_control_config_common.deltaF_PUCCH_Format1b = radioResourceConfigCommon->uplinkPowerControlCommon->deltaFList_PUCCH.deltaF_PUCCH_Format1b; - fp->ul_power_control_config_common.deltaF_PUCCH_Format2 = radioResourceConfigCommon->uplinkPowerControlCommon->deltaFList_PUCCH.deltaF_PUCCH_Format2; - fp->ul_power_control_config_common.deltaF_PUCCH_Format2a = radioResourceConfigCommon->uplinkPowerControlCommon->deltaFList_PUCCH.deltaF_PUCCH_Format2a; - fp->ul_power_control_config_common.deltaF_PUCCH_Format2b = radioResourceConfigCommon->uplinkPowerControlCommon->deltaFList_PUCCH.deltaF_PUCCH_Format2b; - - fp->maxHARQ_Msg3Tx = radioResourceConfigCommon->rach_ConfigCommon->maxHARQ_Msg3Tx; - - // Now configure some of the Physical Channels - if (radioResourceConfigCommon->antennaInfoCommon) - fp->nb_antennas_tx = (1<antennaInfoCommon->antennaPortsCount); - else - fp->nb_antennas_tx = 1; - - //PHICH - if (radioResourceConfigCommon->antennaInfoCommon) { - fp->phich_config_common.phich_resource = radioResourceConfigCommon->phich_Config->phich_Resource; - fp->phich_config_common.phich_duration = radioResourceConfigCommon->phich_Config->phich_Duration; - } - - //Target CellId - fp->Nid_cell = mobilityControlInfo->targetPhysCellId; - fp->nushift = fp->Nid_cell%6; - - // PUCCH - init_ncs_cell(fp,PHY_vars_UE_g[Mod_id][CC_id]->ncs_cell); - - init_ul_hopping(fp); - - // RNTI - - - PHY_vars_UE_g[Mod_id][CC_id]->pdcch_vars[0][eNB_id]->crnti = mobilityControlInfo->newUE_Identity.buf[0]|(mobilityControlInfo->newUE_Identity.buf[1]<<8); - PHY_vars_UE_g[Mod_id][CC_id]->pdcch_vars[1][eNB_id]->crnti = mobilityControlInfo->newUE_Identity.buf[0]|(mobilityControlInfo->newUE_Identity.buf[1]<<8); - - LOG_I(PHY,"SET C-RNTI %x %x\n",PHY_vars_UE_g[Mod_id][CC_id]->pdcch_vars[0][eNB_id]->crnti, - PHY_vars_UE_g[Mod_id][CC_id]->pdcch_vars[1][eNB_id]->crnti); - } - - if(ho_failed) { - LOG_D(PHY,"[UE%d] Handover failed, triggering RACH procedure\n",Mod_id); - memcpy((void *)&PHY_vars_UE_g[Mod_id][CC_id]->frame_parms,(void *)&PHY_vars_UE_g[Mod_id][CC_id]->frame_parms_before_ho, sizeof(NR_DL_FRAME_PARMS)); - PHY_vars_UE_g[Mod_id][CC_id]->UE_mode[eNB_id] = PRACH; - } -} - - -void phy_config_meas_ue(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index,uint8_t n_adj_cells,unsigned int *adj_cell_id) -{ - - PHY_NR_MEASUREMENTS *phy_meas = &PHY_vars_UE_g[Mod_id][CC_id]->measurements; - int i; - - LOG_I(PHY,"Configuring inter-cell measurements for %d cells, ids: \n",n_adj_cells); - - for (i=0; iframe_parms,PHY_vars_UE_g[Mod_id][CC_id]->lte_gold_table[i+1],adj_cell_id[i]); - } - - phy_meas->n_adj_cells = n_adj_cells; - memcpy((void*)phy_meas->adj_cell_id,(void *)adj_cell_id,n_adj_cells*sizeof(unsigned int)); - -} -*/ - - #if 0 void phy_config_harq_ue(module_id_t Mod_id, int CC_id, - uint8_t eNB_id, + uint8_t gNB_id, uint16_t max_harq_tx) { int num_of_threads,num_of_code_words; PHY_VARS_NR_UE *phy_vars_ue = PHY_vars_UE_g[Mod_id][CC_id]; for (num_of_threads=0; num_of_threadsulsch[num_of_threads][eNB_id][num_of_code_words]->Mlimit = max_harq_tx; + phy_vars_ue->ulsch[num_of_threads][gNB_id][num_of_code_words]->Mlimit = max_harq_tx; } #endif @@ -435,7 +125,7 @@ void phy_init_nr_ue_PUSCH(NR_UE_PUSCH *const pusch, } int init_nr_ue_signal(PHY_VARS_NR_UE *ue, - int nb_connected_eNB, + int nb_connected_gNB, uint8_t abstraction_flag) { // create shortcuts NR_DL_FRAME_PARMS *const fp = &ue->frame_parms; @@ -443,7 +133,7 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, NR_UE_PBCH **const pbch_vars = ue->pbch_vars; NR_UE_PRACH **const prach_vars = ue->prach_vars; int i,j,k,l,slot,symb,q; - int eNB_id; + int gNB_id; int th_id; uint32_t ****pusch_dmrs; uint16_t N_n_scid[2] = {0,1}; // [HOTFIX] This is a temporary implementation of scramblingID0 and scramblingID1 which are given by DMRS-UplinkConfig @@ -457,8 +147,8 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, //LOG_D(PHY,"[MSC_NEW][FRAME 00000][PHY_UE][MOD %02u][]\n", ue->Mod_id+NB_eNB_INST); phy_init_nr_top(ue); // many memory allocation sizes are hard coded - AssertFatal( fp->nb_antennas_rx <= 2, "hard coded allocation for ue_common_vars->dl_ch_estimates[eNB_id]" ); - AssertFatal( nb_connected_eNB <= NUMBER_OF_CONNECTED_eNB_MAX, "n_connected_eNB is too large" ); + AssertFatal( fp->nb_antennas_rx <= 2, "hard coded allocation for ue_common_vars->dl_ch_estimates[gNB_id]" ); + AssertFatal(nb_connected_gNB <= NUMBER_OF_CONNECTED_gNB_MAX, "n_connected_gNB is too large" ); // init phy_vars_ue for (i=0; i<4; i++) { @@ -467,17 +157,17 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, ue->rx_gain_byp[i] = 120; } - ue->n_connected_eNB = nb_connected_eNB; + ue->n_connected_gNB = nb_connected_gNB; - for(eNB_id = 0; eNB_id < ue->n_connected_eNB; eNB_id++) { - ue->total_TBS[eNB_id] = 0; - ue->total_TBS_last[eNB_id] = 0; - ue->bitrate[eNB_id] = 0; - ue->total_received_bits[eNB_id] = 0; + for(gNB_id = 0; gNB_id < ue->n_connected_gNB; gNB_id++) { + ue->total_TBS[gNB_id] = 0; + ue->total_TBS_last[gNB_id] = 0; + ue->bitrate[gNB_id] = 0; + ue->total_received_bits[gNB_id] = 0; - ue->ul_time_alignment[eNB_id].apply_ta = 0; - ue->ul_time_alignment[eNB_id].ta_frame = -1; - ue->ul_time_alignment[eNB_id].ta_slot = -1; + ue->ul_time_alignment[gNB_id].apply_ta = 0; + ue->ul_time_alignment[gNB_id].ta_frame = -1; + ue->ul_time_alignment[gNB_id].ta_slot = -1; } // init NR modulation lookup tables nr_generate_modulation_table(); @@ -485,9 +175,9 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, /////////////////////////PUSCH init///////////////////////// /////////// for (th_id = 0; th_id < RX_NB_TH_MAX; th_id++) { - for (eNB_id = 0; eNB_id < ue->n_connected_eNB; eNB_id++) { - ue->pusch_vars[th_id][eNB_id] = (NR_UE_PUSCH *)malloc16(sizeof(NR_UE_PUSCH)); - phy_init_nr_ue_PUSCH( ue->pusch_vars[th_id][eNB_id], fp ); + for (gNB_id = 0; gNB_id < ue->n_connected_gNB; gNB_id++) { + ue->pusch_vars[th_id][gNB_id] = (NR_UE_PUSCH *)malloc16(sizeof(NR_UE_PUSCH)); + phy_init_nr_ue_PUSCH( ue->pusch_vars[th_id][gNB_id], fp ); } } @@ -621,40 +311,40 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, } // DLSCH - for (eNB_id=0; eNB_idn_connected_eNB; eNB_id++) { + for (gNB_id = 0; gNB_id < ue->n_connected_gNB; gNB_id++) { for (th_id=0; th_idpdsch_vars[th_id][eNB_id] = (NR_UE_PDSCH *)malloc16_clear(sizeof(NR_UE_PDSCH)); + ue->pdsch_vars[th_id][gNB_id] = (NR_UE_PDSCH *)malloc16_clear(sizeof(NR_UE_PDSCH)); } for (th_id=0; th_idpdcch_vars[th_id][eNB_id] = (NR_UE_PDCCH *)malloc16_clear(sizeof(NR_UE_PDCCH)); + ue->pdcch_vars[th_id][gNB_id] = (NR_UE_PDCCH *)malloc16_clear(sizeof(NR_UE_PDCCH)); } - prach_vars[eNB_id] = (NR_UE_PRACH *)malloc16_clear(sizeof(NR_UE_PRACH)); - pbch_vars[eNB_id] = (NR_UE_PBCH *)malloc16_clear(sizeof(NR_UE_PBCH)); + prach_vars[gNB_id] = (NR_UE_PRACH *)malloc16_clear(sizeof(NR_UE_PRACH)); + pbch_vars[gNB_id] = (NR_UE_PBCH *)malloc16_clear(sizeof(NR_UE_PBCH)); if (abstraction_flag == 0) { for (th_id=0; th_idpdsch_vars[th_id][eNB_id], fp ); + phy_init_nr_ue__PDSCH( ue->pdsch_vars[th_id][gNB_id], fp ); } for (th_id=0; th_idpdsch_vars[th_id][eNB_id]->llr_shifts = (uint8_t *)malloc16_clear(7*2*fp->N_RB_DL*12); - ue->pdsch_vars[th_id][eNB_id]->llr_shifts_p = ue->pdsch_vars[0][eNB_id]->llr_shifts; - ue->pdsch_vars[th_id][eNB_id]->llr[1] = (int16_t *)malloc16_clear( (8*(3*8*8448))*sizeof(int16_t) ); - ue->pdsch_vars[th_id][eNB_id]->layer_llr[1] = (int16_t *)malloc16_clear( (8*(3*8*8448))*sizeof(int16_t) ); - ue->pdsch_vars[th_id][eNB_id]->llr128_2ndstream = (int16_t **)malloc16_clear( sizeof(int16_t *) ); - ue->pdsch_vars[th_id][eNB_id]->rho = (int32_t **)malloc16_clear( fp->nb_antennas_rx*sizeof(int32_t *) ); + ue->pdsch_vars[th_id][gNB_id]->llr_shifts = (uint8_t *)malloc16_clear(7*2*fp->N_RB_DL*12); + ue->pdsch_vars[th_id][gNB_id]->llr_shifts_p = ue->pdsch_vars[0][gNB_id]->llr_shifts; + ue->pdsch_vars[th_id][gNB_id]->llr[1] = (int16_t *)malloc16_clear((8*(3*8*8448))*sizeof(int16_t)); + ue->pdsch_vars[th_id][gNB_id]->layer_llr[1] = (int16_t *)malloc16_clear((8*(3*8*8448))*sizeof(int16_t)); + ue->pdsch_vars[th_id][gNB_id]->llr128_2ndstream = (int16_t **)malloc16_clear(sizeof(int16_t *)); + ue->pdsch_vars[th_id][gNB_id]->rho = (int32_t **)malloc16_clear(fp->nb_antennas_rx*sizeof(int32_t *)); } for (int i=0; inb_antennas_rx; i++) { for (th_id=0; th_idpdsch_vars[th_id][eNB_id]->rho[i] = (int32_t *)malloc16_clear( 7*2*sizeof(int32_t)*(fp->N_RB_DL*12) ); + ue->pdsch_vars[th_id][gNB_id]->rho[i] = (int32_t *)malloc16_clear(7*2*sizeof(int32_t)*(fp->N_RB_DL*12)); } } for (th_id=0; th_idpdsch_vars[th_id][eNB_id]->dl_ch_rho2_ext = (int32_t **)malloc16_clear( 8*sizeof(int32_t *) ); + ue->pdsch_vars[th_id][gNB_id]->dl_ch_rho2_ext = (int32_t **)malloc16_clear(8*sizeof(int32_t *)); } for (i=0; inb_antennas_rx; i++) @@ -663,7 +353,7 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, const size_t num = 7*2*fp->N_RB_DL*12+4; for (th_id=0; th_idpdsch_vars[th_id][eNB_id]->dl_ch_rho2_ext[idx] = (int32_t *)malloc16_clear( sizeof(int32_t) * num ); + ue->pdsch_vars[th_id][gNB_id]->dl_ch_rho2_ext[idx] = (int32_t *)malloc16_clear(sizeof(int32_t) * num); } } @@ -671,10 +361,10 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, for (k=0; k<8; k++) { //harq_pid for (l=0; l<8; l++) { //round for (th_id=0; th_idpdsch_vars[th_id][eNB_id]->rxdataF_comp1[k][l] = (int32_t **)malloc16_clear( 8*sizeof(int32_t *) ); - ue->pdsch_vars[th_id][eNB_id]->dl_ch_rho_ext[k][l] = (int32_t **)malloc16_clear( 8*sizeof(int32_t *) ); - ue->pdsch_vars[th_id][eNB_id]->dl_ch_mag1[k][l] = (int32_t **)malloc16_clear( 8*sizeof(int32_t *) ); - ue->pdsch_vars[th_id][eNB_id]->dl_ch_magb1[k][l] = (int32_t **)malloc16_clear( 8*sizeof(int32_t *) ); + ue->pdsch_vars[th_id][gNB_id]->rxdataF_comp1[k][l] = (int32_t **)malloc16_clear(8*sizeof(int32_t *)); + ue->pdsch_vars[th_id][gNB_id]->dl_ch_rho_ext[k][l] = (int32_t **)malloc16_clear(8*sizeof(int32_t *)); + ue->pdsch_vars[th_id][gNB_id]->dl_ch_mag1[k][l] = (int32_t **)malloc16_clear(8*sizeof(int32_t *)); + ue->pdsch_vars[th_id][gNB_id]->dl_ch_magb1[k][l] = (int32_t **)malloc16_clear(8*sizeof(int32_t *)); } for (int i=0; inb_antennas_rx; i++) @@ -682,10 +372,10 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, const int idx = (j<<1)+i; for (th_id=0; th_idpdsch_vars[th_id][eNB_id]->dl_ch_rho_ext[k][l][idx] = (int32_t *)malloc16_clear( 7*2*sizeof(int32_t)*(fp->N_RB_DL*12) ); - ue->pdsch_vars[th_id][eNB_id]->rxdataF_comp1[k][l][idx] = (int32_t *)malloc16_clear( 7*2*sizeof(int32_t)*(fp->N_RB_DL*12) ); - ue->pdsch_vars[th_id][eNB_id]->dl_ch_mag1[k][l][idx] = (int32_t *)malloc16_clear( 7*2*sizeof(int32_t)*(fp->N_RB_DL*12) ); - ue->pdsch_vars[th_id][eNB_id]->dl_ch_magb1[k][l][idx] = (int32_t *)malloc16_clear( 7*2*sizeof(int32_t)*(fp->N_RB_DL*12) ); + ue->pdsch_vars[th_id][gNB_id]->dl_ch_rho_ext[k][l][idx] = (int32_t *)malloc16_clear(7*2*sizeof(int32_t)*(fp->N_RB_DL*12)); + ue->pdsch_vars[th_id][gNB_id]->rxdataF_comp1[k][l][idx] = (int32_t *)malloc16_clear(7*2*sizeof(int32_t)*(fp->N_RB_DL*12)); + ue->pdsch_vars[th_id][gNB_id]->dl_ch_mag1[k][l][idx] = (int32_t *)malloc16_clear(7*2*sizeof(int32_t)*(fp->N_RB_DL*12)); + ue->pdsch_vars[th_id][gNB_id]->dl_ch_magb1[k][l][idx] = (int32_t *)malloc16_clear(7*2*sizeof(int32_t)*(fp->N_RB_DL*12)); } } } @@ -693,72 +383,72 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, // 100 PRBs * 12 REs/PRB * 4 PDCCH SYMBOLS * 2 LLRs/RE for (th_id=0; th_idpdcch_vars[th_id][eNB_id]->llr = (int16_t *)malloc16_clear( 2*4*100*12*sizeof(uint16_t) ); - ue->pdcch_vars[th_id][eNB_id]->llr16 = (int16_t *)malloc16_clear( 2*4*100*12*sizeof(uint16_t) ); - ue->pdcch_vars[th_id][eNB_id]->wbar = (int16_t *)malloc16_clear( 2*4*100*12*sizeof(uint16_t) ); - ue->pdcch_vars[th_id][eNB_id]->e_rx = (int16_t *)malloc16_clear( 4*2*100*12 ); - ue->pdcch_vars[th_id][eNB_id]->rxdataF_comp = (int32_t **)malloc16_clear( 8*sizeof(int32_t *) ); - ue->pdcch_vars[th_id][eNB_id]->dl_ch_rho_ext = (int32_t **)malloc16_clear( 8*sizeof(int32_t *) ); - ue->pdcch_vars[th_id][eNB_id]->rho = (int32_t **)malloc16( fp->nb_antennas_rx*sizeof(int32_t *) ); - ue->pdcch_vars[th_id][eNB_id]->rxdataF_ext = (int32_t **)malloc16_clear( 8*sizeof(int32_t *) ); - ue->pdcch_vars[th_id][eNB_id]->dl_ch_estimates_ext = (int32_t **)malloc16_clear( 8*sizeof(int32_t *) ); + ue->pdcch_vars[th_id][gNB_id]->llr = (int16_t *)malloc16_clear(2*4*100*12*sizeof(uint16_t)); + ue->pdcch_vars[th_id][gNB_id]->llr16 = (int16_t *)malloc16_clear(2*4*100*12*sizeof(uint16_t)); + ue->pdcch_vars[th_id][gNB_id]->wbar = (int16_t *)malloc16_clear(2*4*100*12*sizeof(uint16_t)); + ue->pdcch_vars[th_id][gNB_id]->e_rx = (int16_t *)malloc16_clear(4*2*100*12 ); + ue->pdcch_vars[th_id][gNB_id]->rxdataF_comp = (int32_t **)malloc16_clear(8*sizeof(int32_t *)); + ue->pdcch_vars[th_id][gNB_id]->dl_ch_rho_ext = (int32_t **)malloc16_clear(8*sizeof(int32_t *)); + ue->pdcch_vars[th_id][gNB_id]->rho = (int32_t **)malloc16(fp->nb_antennas_rx*sizeof(int32_t *)); + ue->pdcch_vars[th_id][gNB_id]->rxdataF_ext = (int32_t **)malloc16_clear(8*sizeof(int32_t *)); + ue->pdcch_vars[th_id][gNB_id]->dl_ch_estimates_ext = (int32_t **)malloc16_clear(8*sizeof(int32_t *)); // Channel estimates - ue->pdcch_vars[th_id][eNB_id]->dl_ch_estimates = (int32_t **)malloc16_clear(8*sizeof(int32_t *)); - ue->pdcch_vars[th_id][eNB_id]->dl_ch_estimates_time = (int32_t **)malloc16_clear(8*sizeof(int32_t *)); + ue->pdcch_vars[th_id][gNB_id]->dl_ch_estimates = (int32_t **)malloc16_clear(8*sizeof(int32_t *)); + ue->pdcch_vars[th_id][gNB_id]->dl_ch_estimates_time = (int32_t **)malloc16_clear(8*sizeof(int32_t *)); for (i=0; inb_antennas_rx; i++) { - ue->pdcch_vars[th_id][eNB_id]->rho[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*(100*12*4) ); + ue->pdcch_vars[th_id][gNB_id]->rho[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*(100*12*4)); for (j=0; j<4; j++) { int idx = (j<<1) + i; - ue->pdcch_vars[th_id][eNB_id]->dl_ch_estimates[idx] = (int32_t *)malloc16_clear( sizeof(int32_t)*fp->symbols_per_slot*(fp->ofdm_symbol_size+LTE_CE_FILTER_LENGTH) ); - ue->pdcch_vars[th_id][eNB_id]->dl_ch_estimates_time[idx] = (int32_t *)malloc16_clear( sizeof(int32_t)*fp->ofdm_symbol_size*2 ); + ue->pdcch_vars[th_id][gNB_id]->dl_ch_estimates[idx] = (int32_t *)malloc16_clear(sizeof(int32_t)*fp->symbols_per_slot*(fp->ofdm_symbol_size+LTE_CE_FILTER_LENGTH)); + ue->pdcch_vars[th_id][gNB_id]->dl_ch_estimates_time[idx] = (int32_t *)malloc16_clear(sizeof(int32_t)*fp->ofdm_symbol_size*2); // size_t num = 7*2*fp->N_RB_DL*12; size_t num = 4*273*12; // 4 symbols, 100 PRBs, 12 REs per PRB - ue->pdcch_vars[th_id][eNB_id]->rxdataF_comp[idx] = (int32_t *)malloc16_clear( sizeof(int32_t) * num ); - ue->pdcch_vars[th_id][eNB_id]->dl_ch_rho_ext[idx] = (int32_t *)malloc16_clear( sizeof(int32_t) * num ); - ue->pdcch_vars[th_id][eNB_id]->rxdataF_ext[idx] = (int32_t *)malloc16_clear( sizeof(int32_t) * num ); - ue->pdcch_vars[th_id][eNB_id]->dl_ch_estimates_ext[idx] = (int32_t *)malloc16_clear( sizeof(int32_t) * num ); + ue->pdcch_vars[th_id][gNB_id]->rxdataF_comp[idx] = (int32_t *)malloc16_clear(sizeof(int32_t) * num); + ue->pdcch_vars[th_id][gNB_id]->dl_ch_rho_ext[idx] = (int32_t *)malloc16_clear(sizeof(int32_t) * num); + ue->pdcch_vars[th_id][gNB_id]->rxdataF_ext[idx] = (int32_t *)malloc16_clear(sizeof(int32_t) * num); + ue->pdcch_vars[th_id][gNB_id]->dl_ch_estimates_ext[idx] = (int32_t *)malloc16_clear(sizeof(int32_t) * num); } } } // PBCH - pbch_vars[eNB_id]->rxdataF_ext = (int32_t **)malloc16( fp->nb_antennas_rx*sizeof(int32_t *) ); - pbch_vars[eNB_id]->rxdataF_comp = (int32_t **)malloc16_clear( 8*sizeof(int32_t *) ); - pbch_vars[eNB_id]->dl_ch_estimates = (int32_t **)malloc16_clear( 8*sizeof(int32_t *) ); - pbch_vars[eNB_id]->dl_ch_estimates_ext = (int32_t **)malloc16_clear( 8*sizeof(int32_t *) ); - pbch_vars[eNB_id]->dl_ch_estimates_time = (int32_t **)malloc16_clear( 8*sizeof(int32_t *) ); - pbch_vars[eNB_id]->llr = (int16_t *)malloc16_clear( 1920 ); // - prach_vars[eNB_id]->prachF = (int16_t *)malloc16_clear( sizeof(int)*(7*2*sizeof(int)*(fp->ofdm_symbol_size*12)) ); - prach_vars[eNB_id]->prach = (int16_t *)malloc16_clear( sizeof(int)*(7*2*sizeof(int)*(fp->ofdm_symbol_size*12)) ); + pbch_vars[gNB_id]->rxdataF_ext = (int32_t **)malloc16(fp->nb_antennas_rx*sizeof(int32_t *)); + pbch_vars[gNB_id]->rxdataF_comp = (int32_t **)malloc16_clear(8*sizeof(int32_t *)); + pbch_vars[gNB_id]->dl_ch_estimates = (int32_t **)malloc16_clear(8*sizeof(int32_t *)); + pbch_vars[gNB_id]->dl_ch_estimates_ext = (int32_t **)malloc16_clear(8*sizeof(int32_t *)); + pbch_vars[gNB_id]->dl_ch_estimates_time = (int32_t **)malloc16_clear(8*sizeof(int32_t *)); + pbch_vars[gNB_id]->llr = (int16_t *)malloc16_clear(1920); // + prach_vars[gNB_id]->prachF = (int16_t *)malloc16_clear(sizeof(int)*(7*2*sizeof(int)*(fp->ofdm_symbol_size*12))); + prach_vars[gNB_id]->prach = (int16_t *)malloc16_clear(sizeof(int)*(7*2*sizeof(int)*(fp->ofdm_symbol_size*12))); for (i=0; inb_antennas_rx; i++) { - pbch_vars[eNB_id]->rxdataF_ext[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*20*12*4 ); + pbch_vars[gNB_id]->rxdataF_ext[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*20*12*4 ); for (j=0; j<4; j++) {//fp->nb_antennas_tx;j++) { int idx = (j<<1)+i; - pbch_vars[eNB_id]->rxdataF_comp[idx] = (int32_t *)malloc16_clear( sizeof(int32_t)*20*12*4 ); - pbch_vars[eNB_id]->dl_ch_estimates[idx] = (int32_t *)malloc16_clear( sizeof(int32_t)*7*2*sizeof(int)*(fp->ofdm_symbol_size) ); - pbch_vars[eNB_id]->dl_ch_estimates_time[idx]= (int32_t *)malloc16_clear( sizeof(int32_t)*7*2*sizeof(int)*(fp->ofdm_symbol_size) ); - pbch_vars[eNB_id]->dl_ch_estimates_ext[idx] = (int32_t *)malloc16_clear( sizeof(int32_t)*20*12*4 ); + pbch_vars[gNB_id]->rxdataF_comp[idx] = (int32_t *)malloc16_clear(sizeof(int32_t)*20*12*4); + pbch_vars[gNB_id]->dl_ch_estimates[idx] = (int32_t *)malloc16_clear(sizeof(int32_t)*7*2*sizeof(int)*(fp->ofdm_symbol_size)); + pbch_vars[gNB_id]->dl_ch_estimates_time[idx] = (int32_t *)malloc16_clear(sizeof(int32_t)*7*2*sizeof(int)*(fp->ofdm_symbol_size)); + pbch_vars[gNB_id]->dl_ch_estimates_ext[idx] = (int32_t *)malloc16_clear(sizeof(int32_t)*20*12*4); } } } - pbch_vars[eNB_id]->decoded_output = (uint8_t *)malloc16_clear( 64 ); + pbch_vars[gNB_id]->decoded_output = (uint8_t *)malloc16_clear(64); } // initialization for the last instance of pdsch_vars (used for MU-MIMO) for (th_id=0; th_idpdsch_vars[th_id][eNB_id] = (NR_UE_PDSCH *)malloc16_clear( sizeof(NR_UE_PDSCH) ); + ue->pdsch_vars[th_id][gNB_id] = (NR_UE_PDSCH *)malloc16_clear(sizeof(NR_UE_PDSCH)); } if (abstraction_flag == 0) { for (th_id=0; th_idpdsch_vars[th_id][eNB_id], fp ); - ue->pdsch_vars[th_id][eNB_id]->llr[1] = (int16_t *)malloc16_clear( (8*(3*8*8448))*sizeof(int16_t) ); - ue->pdsch_vars[th_id][eNB_id]->layer_llr[1] = (int16_t *)malloc16_clear( (8*(3*8*8448))*sizeof(int16_t) ); + //phy_init_lte_ue__PDSCH( ue->pdsch_vars[th_id][gNB_id], fp ); + ue->pdsch_vars[th_id][gNB_id]->llr[1] = (int16_t *)malloc16_clear((8*(3*8*8448))*sizeof(int16_t)); + ue->pdsch_vars[th_id][gNB_id]->layer_llr[1] = (int16_t *)malloc16_clear((8*(3*8*8448))*sizeof(int16_t)); } } else { //abstraction == 1 ue->sinr_dB = (double *) malloc16_clear( fp->N_RB_DL*12*sizeof(double) ); @@ -787,7 +477,7 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, void init_nr_ue_transport(PHY_VARS_NR_UE *ue, int abstraction_flag) { - for (int i=0; idlsch[k][i][j] = new_nr_ue_dlsch(1,NR_MAX_DLSCH_HARQ_PROCESSES,NSOFT,MAX_LDPC_ITERATIONS,ue->frame_parms.N_RB_DL, abstraction_flag))!=NULL,"Can't get ue dlsch structures\n"); diff --git a/openair1/PHY/MODULATION/nr_modulation.c b/openair1/PHY/MODULATION/nr_modulation.c index 0a7088ba39..ed9a859fb6 100644 --- a/openair1/PHY/MODULATION/nr_modulation.c +++ b/openair1/PHY/MODULATION/nr_modulation.c @@ -325,10 +325,10 @@ void nr_ue_layer_mapping(NR_UE_ULSCH_t **ulsch_ue, void nr_dft(int32_t *z, int32_t *d, uint32_t Msc_PUSCH) { -#if defined(__x86_64__) || defined(__i386__) - __m128i dft_in128[1][1200], dft_out128[1][1200]; +#if defined(__x86_64__) || +defined(__i386__) + __m128i dft_in128[1][3240], dft_out128[1][3240]; #elif defined(__arm__) - int16x8_t dft_in128[1][1200], dft_out128[1][1200]; + int16x8_t dft_in128[1][3240], dft_out128[1][3240]; #endif uint32_t *dft_in0 = (uint32_t*)dft_in128[0], *dft_out0 = (uint32_t*)dft_out128[0]; @@ -340,8 +340,10 @@ void nr_dft(int32_t *z, int32_t *d, uint32_t Msc_PUSCH) int16x8_t norm128; #endif - for (i = 0, ip = 0; i < Msc_PUSCH; i++, ip+=4) { - dft_in0[ip] = d[i]; + if ((Msc_PUSCH % 1536) > 0) { + for (i = 0, ip = 0; i < Msc_PUSCH; i++, ip+=4) { + dft_in0[ip] = d[i]; + } } switch (Msc_PUSCH) { @@ -480,7 +482,7 @@ void nr_dft(int32_t *z, int32_t *d, uint32_t Msc_PUSCH) break; case 972: - dft(DFT_960,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); + dft(DFT_972,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); break; case 1080: @@ -494,11 +496,98 @@ void nr_dft(int32_t *z, int32_t *d, uint32_t Msc_PUSCH) case 1200: dft(DFT_1200,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); break; + + case 1296: + dft(DFT_1296,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + + case 1440: + dft(DFT_1440,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + + case 1500: + dft(DFT_1500,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + + case 1536: + //dft(DFT_1536,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); + dft(DFT_1536,(int16_t*)d, (int16_t*)z, 1); + break; + + case 1620: + dft(DFT_1620,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + + case 1728: + dft(DFT_1728,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + + case 1800: + dft(DFT_1800,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + + case 1920: + dft(DFT_1920,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + + case 1944: + dft(DFT_1944,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + + case 2160: + dft(DFT_2160,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + + case 2304: + dft(DFT_2304,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + + case 2400: + dft(DFT_2400,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + + case 2592: + dft(DFT_2592,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + + case 2700: + dft(DFT_2700,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + + case 2880: + dft(DFT_2880,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + + case 2916: + dft(DFT_2916,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + + case 3000: + dft(DFT_3000,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + + case 3072: + //dft(DFT_3072,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); + dft(DFT_3072,(int16_t*)d, (int16_t*)z, 1); + break; + + case 3240: + dft(DFT_3240,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); + break; + + default: + // should not be reached + LOG_E( PHY, "Unsupported Msc_PUSCH value of %"PRIu16"\n", Msc_PUSCH ); + return; + } - for (i = 0, ip = 0; i < Msc_PUSCH; i++, ip+=4) { - z[i] = dft_out0[ip]; + + if ((Msc_PUSCH % 1536) > 0) { + for (i = 0, ip = 0; i < Msc_PUSCH; i++, ip+=4) + z[i] = dft_out0[ip]; } + } diff --git a/openair1/PHY/NR_REFSIG/scrambling_luts.c b/openair1/PHY/NR_REFSIG/scrambling_luts.c index 3509291e42..2a37a12539 100644 --- a/openair1/PHY/NR_REFSIG/scrambling_luts.c +++ b/openair1/PHY/NR_REFSIG/scrambling_luts.c @@ -51,7 +51,7 @@ void init_byte2m64(void) { ((int16_t*)&byte2m64_re[s])[0],((int16_t*)&byte2m64_im[s])[0], ((int16_t*)&byte2m64_re[s])[1],((int16_t*)&byte2m64_im[s])[1], ((int16_t*)&byte2m64_re[s])[2],((int16_t*)&byte2m64_im[s])[2], - ((int16_t*)&byte2m64_re[s])[3],((int16_t*)&byte2m64_im[s])[3]); + ((int16_t*)&byte2m64_re[s])[3],((int16_t*)&byte2m64_im[s])[3]); } } diff --git a/openair1/PHY/NR_TRANSPORT/nr_dci.c b/openair1/PHY/NR_TRANSPORT/nr_dci.c index a4acaf9476..469415908f 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dci.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dci.c @@ -95,6 +95,7 @@ void nr_generate_dci(PHY_VARS_gNB *gNB, * in frequency: the first subcarrier is obtained by adding the first CRB overlapping the SSB and the rb_offset for coreset 0 * or the rb_offset for other coresets * in time: by its first slot and its first symbol*/ + const nfapi_nr_dl_dci_pdu_t *dci_pdu = &pdcch_pdu_rel15->dci_pdu[d]; cset_start_symb = pdcch_pdu_rel15->StartSymbolIndex; cset_nsymb = pdcch_pdu_rel15->DurationSymbols; @@ -102,9 +103,8 @@ void nr_generate_dci(PHY_VARS_gNB *gNB, LOG_D(PHY, "Coreset rb_offset %d, nb_rb %d\n",rb_offset,n_rb); LOG_D(PHY, "Coreset starting subcarrier %d on symbol %d (%d symbols)\n", cset_start_sc, cset_start_symb, cset_nsymb); // DMRS length is per OFDM symbol - uint32_t dmrs_length = (pdcch_pdu_rel15->CceRegMappingType == NFAPI_NR_CCE_REG_MAPPING_NON_INTERLEAVED)? - (n_rb*6) : (pdcch_pdu_rel15->dci_pdu.AggregationLevel[d]*36/cset_nsymb); //2(QPSK)*3(per RB)*6(REG per CCE) - uint32_t encoded_length = pdcch_pdu_rel15->dci_pdu.AggregationLevel[d]*108; //2(QPSK)*9(per RB)*6(REG per CCE) + uint32_t dmrs_length = n_rb*6; //2(QPSK)*3(per RB)*6(REG per CCE) + uint32_t encoded_length = dci_pdu->AggregationLevel*108; //2(QPSK)*9(per RB)*6(REG per CCE) LOG_D(PHY, "DMRS length per symbol %d\t DCI encoded length %d (precoder_granularity %d,reg_mapping %d)\n", dmrs_length, encoded_length,pdcch_pdu_rel15->precoderGranularity,pdcch_pdu_rel15->CceRegMappingType); dmrs_length += rb_offset*6; // To accommodate more DMRS symbols in case of rb offset @@ -126,19 +126,19 @@ void nr_generate_dci(PHY_VARS_gNB *gNB, // CRC attachment + Scrambling + Channel coding + Rate matching uint32_t encoder_output[NR_MAX_DCI_SIZE_DWORD]; - uint16_t n_RNTI = pdcch_pdu_rel15->dci_pdu.RNTI[d]; - uint16_t Nid = pdcch_pdu_rel15->dci_pdu.ScramblingId[d]; - uint16_t scrambling_RNTI = pdcch_pdu_rel15->dci_pdu.ScramblingRNTI[d]; + uint16_t n_RNTI = dci_pdu->RNTI; + uint16_t Nid = dci_pdu->ScramblingId; + uint16_t scrambling_RNTI = dci_pdu->ScramblingRNTI; t_nrPolar_params *currentPtr = nr_polar_params(NR_POLAR_DCI_MESSAGE_TYPE, - pdcch_pdu_rel15->dci_pdu.PayloadSizeBits[d], - pdcch_pdu_rel15->dci_pdu.AggregationLevel[d], + dci_pdu->PayloadSizeBits, + dci_pdu->AggregationLevel, 0,NULL); - polar_encoder_fast((uint64_t*)pdcch_pdu_rel15->dci_pdu.Payload[d], (void*)encoder_output, n_RNTI,1,currentPtr); + polar_encoder_fast((uint64_t*)dci_pdu->Payload, (void*)encoder_output, n_RNTI,1,currentPtr); #ifdef DEBUG_CHANNEL_CODING - printf("polar rnti %x,length %d, L %d\n",n_RNTI, pdcch_pdu_rel15->dci_pdu.PayloadSizeBits[d],pdcch_pdu_rel15->dci_pdu.AggregationLevel[d]); + printf("polar rnti %x,length %d, L %d\n",n_RNTI, dci_pdu->PayloadSizeBits,pdcch_pdu_rel15->dci_pdu.AggregationLevel[d]); printf("DCI PDU: [0]->0x%lx \t [1]->0x%lx\n", - ((uint64_t*)pdcch_pdu_rel15->dci_pdu.Payload[d])[0], ((uint64_t*)pdcch_pdu_rel15->dci_pdu.Payload[d])[1]); + ((uint64_t*)dci_pdu->Payload)[0], ((uint64_t*)dci_pdu->Payload)[1]); printf("Encoded Payload (length:%d dwords):\n", encoded_length>>5); for (int i=0; i>5; i++) @@ -164,66 +164,86 @@ void nr_generate_dci(PHY_VARS_gNB *gNB, printf("i %d mod_dci %d %d\n", i, mod_dci[i<<1], mod_dci[(i<<1)+1] ); #endif - + /// Resource mapping - + if (cset_start_sc >= frame_parms.ofdm_symbol_size) cset_start_sc -= frame_parms.ofdm_symbol_size; - - /*Reorder REG list for a freq first mapping*/ - uint8_t reg_idx0 = pdcch_pdu_rel15->dci_pdu.CceIndex[d]*NR_NB_REG_PER_CCE; - uint8_t nb_regs = pdcch_pdu_rel15->dci_pdu.AggregationLevel[d]*NR_NB_REG_PER_CCE; + + // Get cce_list indices by reg_idx in ascending order + int reg_list_index = 0; + int reg_list_order[NR_MAX_PDCCH_AGG_LEVEL] = {}; + for (int p = 0; p < NR_MAX_PDCCH_AGG_LEVEL; p++) { + for(int p2 = 0; p2 < dci_pdu->AggregationLevel; p2++) { + if(gNB->cce_list[d][p2].reg_list[0].reg_idx == p * NR_NB_REG_PER_CCE) { + reg_list_order[reg_list_index] = p2; + reg_list_index++; + break; + } + } + } /*Mapping the encoded DCI along with the DMRS */ - for (int reg_idx=reg_idx0; reg_idx<(nb_regs+reg_idx0); reg_idx++) { - k = cset_start_sc + (12*reg_idx/cset_nsymb); - - if (k >= frame_parms.ofdm_symbol_size) - k -= frame_parms.ofdm_symbol_size; - - l = cset_start_symb + ((reg_idx/cset_nsymb)%cset_nsymb); - - // dmrs index depends on reference point for k according to 38.211 7.4.1.3.2 - if (pdcch_pdu_rel15->CoreSetType == NFAPI_NR_CSET_CONFIG_PDCCH_CONFIG) - dmrs_idx = (reg_idx/cset_nsymb)*3; - else - dmrs_idx = ((reg_idx/cset_nsymb)+rb_offset)*3; - - k_prime = 0; - - for (int m=0; mCceRegMappingType == NFAPI_NR_CCE_REG_MAPPING_NON_INTERLEAVED) { - ((int16_t *)txdataF)[(l*frame_parms.ofdm_symbol_size + k)<<1] = (amp * mod_dmrs[l][dmrs_idx<<1]) >> 15; - ((int16_t *)txdataF)[((l*frame_parms.ofdm_symbol_size + k)<<1) + 1] = (amp * mod_dmrs[l][(dmrs_idx<<1) + 1]) >> 15; + for (int cce_count = 0; cce_count < dci_pdu->AggregationLevel; cce_count ++) { + + int8_t cce_idx = reg_list_order[cce_count]; + + for (int reg_in_cce_idx = 0; reg_in_cce_idx < NR_NB_REG_PER_CCE; reg_in_cce_idx++) { + + k = cset_start_sc + gNB->cce_list[d][cce_idx].reg_list[reg_in_cce_idx].start_sc_idx; + + if (k >= frame_parms.ofdm_symbol_size) + k -= frame_parms.ofdm_symbol_size; + + l = cset_start_symb + gNB->cce_list[d][cce_idx].reg_list[reg_in_cce_idx].symb_idx; + + // dmrs index depends on reference point for k according to 38.211 7.4.1.3.2 + if (pdcch_pdu_rel15->CoreSetType == NFAPI_NR_CSET_CONFIG_PDCCH_CONFIG) + dmrs_idx =gNB->cce_list[d][cce_idx].reg_list[reg_in_cce_idx].reg_idx * 3; + else + dmrs_idx = (gNB->cce_list[d][cce_idx].reg_list[reg_in_cce_idx].reg_idx + rb_offset) * 3; + + k_prime = 0; + + for (int m = 0; m < NR_NB_SC_PER_RB; m++) { + if (m == (k_prime << 2) + 1) { // DMRS if not already mapped + ((int16_t *) txdataF)[(l * frame_parms.ofdm_symbol_size + k) << 1] = + (amp * mod_dmrs[l][dmrs_idx << 1]) >> 15; + ((int16_t *) txdataF)[((l * frame_parms.ofdm_symbol_size + k) << 1) + 1] = + (amp * mod_dmrs[l][(dmrs_idx << 1) + 1]) >> 15; + #ifdef DEBUG_PDCCH_DMRS printf("PDCCH DMRS: l %d position %d => (%d,%d)\n",l,k,((int16_t *)txdataF)[(l*frame_parms.ofdm_symbol_size + k)<<1], ((int16_t *)txdataF)[((l*frame_parms.ofdm_symbol_size + k)<<1)+1]); #endif - dmrs_idx++; - //} - - k_prime++; - } else { // DCI payload - ((int16_t *)txdataF)[(l*frame_parms.ofdm_symbol_size + k)<<1] = (amp * mod_dci[dci_idx<<1]) >> 15; - ((int16_t *)txdataF)[((l*frame_parms.ofdm_symbol_size + k)<<1) + 1] = (amp * mod_dci[(dci_idx<<1) + 1]) >> 15; + + dmrs_idx++; + k_prime++; + + } else { // DCI payload + ((int16_t *) txdataF)[(l * frame_parms.ofdm_symbol_size + k) << 1] = (amp * mod_dci[dci_idx << 1]) >> 15; + ((int16_t *) txdataF)[((l * frame_parms.ofdm_symbol_size + k) << 1) + 1] = + (amp * mod_dci[(dci_idx << 1) + 1]) >> 15; #ifdef DEBUG_DCI printf("PDCCH: l %d position %d => (%d,%d)\n",l,k,((int16_t *)txdataF)[(l*frame_parms.ofdm_symbol_size + k)<<1], ((int16_t *)txdataF)[((l*frame_parms.ofdm_symbol_size + k)<<1)+1]); #endif - dci_idx++; - } - - k++; - - if (k >= frame_parms.ofdm_symbol_size) - k -= frame_parms.ofdm_symbol_size; - } // m - } // reg_idx + dci_idx++; + } - LOG_I(PHY, "DCI: payloadSize = %d | payload = %llx\n", - *pdcch_pdu_rel15->dci_pdu.PayloadSizeBits,*(unsigned long long*)pdcch_pdu_rel15->dci_pdu.Payload); + k++; + if (k >= frame_parms.ofdm_symbol_size) + k -= frame_parms.ofdm_symbol_size; + + } // m + } // reg_in_cce_idx + } // cce_count + + LOG_D(PHY, + "DCI: payloadSize = %d | payload = %llx\n", + dci_pdu->PayloadSizeBits, + *(unsigned long long *)dci_pdu->Payload); } // for (int d=0;dnumDlDci;d++) } diff --git a/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c b/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c index 2b64a3062c..3814c78295 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c @@ -142,7 +142,7 @@ void nr_fill_cce_list(PHY_VARS_gNB *gNB, uint8_t m, nfapi_nr_dl_tti_pdcch_pdu_r AssertFatal(N_reg > 0,"N_reg cannot be 0\n"); for (int d=0;dnumDlDci;d++) { - int L = pdcch_pdu_rel15->dci_pdu.AggregationLevel[d]; + int L = pdcch_pdu_rel15->dci_pdu[d].AggregationLevel; if (pdcch_pdu_rel15->CoreSetType == NFAPI_NR_CSET_CONFIG_MIB_SIB1) AssertFatal(L>=4, "Invalid aggregation level for SIB1 configured PDCCH %d\n", L); @@ -153,10 +153,10 @@ void nr_fill_cce_list(PHY_VARS_gNB *gNB, uint8_t m, nfapi_nr_dl_tti_pdcch_pdu_r C = N_reg/(bsize*R); } - LOG_D(PHY, "CCE list generation for candidate %d: bundle size %d ilv size %d CceIndex %d\n", m, bsize, R, pdcch_pdu_rel15->dci_pdu.CceIndex[d]); + LOG_D(PHY, "CCE list generation for candidate %d: bundle size %d ilv size %d CceIndex %d\n", m, bsize, R, pdcch_pdu_rel15->dci_pdu[d].CceIndex); for (uint8_t cce_idx=0; cce_idxcce_list[d][cce_idx]; - cce->cce_idx = pdcch_pdu_rel15->dci_pdu.CceIndex[d] + cce_idx; + cce->cce_idx = pdcch_pdu_rel15->dci_pdu[d].CceIndex + cce_idx; LOG_D(PHY, "cce_idx %d\n", cce->cce_idx); if (pdcch_pdu_rel15->CceRegMappingType == NFAPI_NR_CCE_REG_MAPPING_INTERLEAVED) { @@ -236,25 +236,24 @@ void nr_fill_dci(PHY_VARS_gNB *gNB, for (int i=0;inumDlDci;i++) { - //uint64_t *dci_pdu = (uint64_t*)pdcch_pdu_rel15->dci_pdu.Payload[i]; + //uint64_t *dci_pdu = (uint64_t*)pdcch_pdu_rel15->dci_pdu[i].Payload; - int dlsch_id = find_nr_dlsch(pdcch_pdu_rel15->dci_pdu.RNTI[i],gNB,SEARCH_EXIST_OR_FREE); + int dlsch_id = find_nr_dlsch(pdcch_pdu_rel15->dci_pdu[i].RNTI,gNB,SEARCH_EXIST_OR_FREE); if( (dlsch_id<0) || (dlsch_id>=NUMBER_OF_NR_DLSCH_MAX) ){ - LOG_E(PHY,"illegal dlsch_id found!!! rnti %04x dlsch_id %d\n",(unsigned int)pdcch_pdu_rel15->dci_pdu.RNTI[i],dlsch_id); + LOG_E(PHY,"illegal dlsch_id found!!! rnti %04x dlsch_id %d\n",(unsigned int)pdcch_pdu_rel15->dci_pdu[i].RNTI,dlsch_id); return; } dlsch = gNB->dlsch[dlsch_id][0]; - int num_slots_tdd = (gNB->frame_parms.slots_per_frame)>>(7-gNB->gNB_config.tdd_table.tdd_period.value); - int harq_pid = slot % num_slots_tdd; + int harq_pid = 0; dlsch->slot_tx[slot] = 1; - dlsch->harq_ids[frame%2][slot] = harq_pid; + dlsch->harq_ids[frame % 2][slot] = 0; AssertFatal(harq_pid < 8 && harq_pid >= 0, "illegal harq_pid %d\n",harq_pid); dlsch->harq_mask |= (1<rnti = pdcch_pdu_rel15->dci_pdu.RNTI[i]; + dlsch->rnti = pdcch_pdu_rel15->dci_pdu[i].RNTI; // nr_fill_cce_list(gNB,0); /* @@ -300,7 +299,7 @@ void nr_fill_ul_dci(PHY_VARS_gNB *gNB, for (int i=0;inumDlDci;i++) { - //uint64_t *dci_pdu = (uint64_t*)pdcch_pdu_rel15->dci_pdu.Payload[i]; + //uint64_t *dci_pdu = (uint64_t*)pdcch_pdu_rel15->dci_pdu[i].Payload; // if there's no DL DCI then generate CCE list // nr_fill_cce_list(gNB,0); diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c index e3627b9344..1cce5e1174 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c @@ -136,8 +136,7 @@ uint8_t nr_generate_pdsch(PHY_VARS_gNB *gNB, dlsch = gNB->dlsch[dlsch_id][0]; if (dlsch->slot_tx[slot] == 0) continue; - int harq_pid = dlsch->harq_ids[frame%2][slot]; - NR_DL_gNB_HARQ_t *harq = dlsch->harq_processes[harq_pid]; + NR_DL_gNB_HARQ_t *harq = &dlsch->harq_process; nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &harq->pdsch_pdu.pdsch_pdu_rel15; uint32_t scrambled_output[NR_MAX_NB_CODEWORDS][NR_MAX_PDSCH_ENCODED_LENGTH>>5]; int16_t **mod_symbs = (int16_t**)dlsch->mod_symbs; @@ -421,15 +420,8 @@ void dump_pdsch_stats(PHY_VARS_gNB *gNB) { for (int i=0;idlsch_stats[i].rnti > 0) - LOG_I(PHY,"DLSCH RNTI %x: round_trials %d(%1.1e):%d(%1.1e):%d(%1.1e):%d, current_Qm %d, current_RI %d, total_bytes TX %d\n", + LOG_D(PHY,"DLSCH RNTI %x: current_Qm %d, current_RI %d, total_bytes TX %d\n", gNB->dlsch_stats[i].rnti, - gNB->dlsch_stats[i].round_trials[0], - (double)gNB->dlsch_stats[i].round_trials[1]/gNB->dlsch_stats[i].round_trials[0], - gNB->dlsch_stats[i].round_trials[1], - (double)gNB->dlsch_stats[i].round_trials[2]/gNB->dlsch_stats[i].round_trials[0], - gNB->dlsch_stats[i].round_trials[2], - (double)gNB->dlsch_stats[i].round_trials[3]/gNB->dlsch_stats[i].round_trials[0], - gNB->dlsch_stats[i].round_trials[3], gNB->dlsch_stats[i].current_Qm, gNB->dlsch_stats[i].current_RI, gNB->dlsch_stats[i].total_bytes_tx); diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c index 021ce1d1a9..e6544bbe0c 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c @@ -51,7 +51,6 @@ void free_gNB_dlsch(NR_gNB_DLSCH_t **dlschptr, uint16_t N_RB) { - int i; int r; NR_gNB_DLSCH_t *dlsch = *dlschptr; @@ -63,76 +62,61 @@ void free_gNB_dlsch(NR_gNB_DLSCH_t **dlschptr, uint16_t N_RB) a_segments = a_segments*N_RB; a_segments = a_segments/273 +1; } - - - + + + #ifdef DEBUG_DLSCH_FREE LOG_D(PHY,"Freeing dlsch %p\n",dlsch); #endif - - for (i=0; iMdlharq; i++) { + NR_DL_gNB_HARQ_t *harq = &dlsch->harq_process; + if (harq->b) { + free16(harq->b, a_segments * 1056); + harq->b = NULL; #ifdef DEBUG_DLSCH_FREE - LOG_D(PHY,"Freeing dlsch process %d\n",i); + LOG_D(PHY, "Freeing harq->b (%p)\n", harq->b); #endif - if (dlsch->harq_processes[i]) { + if (harq->e) { + free16(harq->e, 14 * N_RB * 12 * 8); + harq->e = NULL; #ifdef DEBUG_DLSCH_FREE - LOG_D(PHY,"Freeing dlsch process %d (%p)\n",i,dlsch->harq_processes[i]); + printf("Freeing dlsch process %d e (%p)\n", i, harq->e); #endif - - if (dlsch->harq_processes[i]->b) { - free16(dlsch->harq_processes[i]->b,a_segments*1056); - dlsch->harq_processes[i]->b = NULL; -#ifdef DEBUG_DLSCH_FREE - LOG_D(PHY,"Freeing dlsch process %d b (%p)\n",i,dlsch->harq_processes[i]->b); -#endif - } - - if (dlsch->harq_processes[i]->e) { - free16(dlsch->harq_processes[i]->e,14*N_RB*12*8); - dlsch->harq_processes[i]->e = NULL; -#ifdef DEBUG_DLSCH_FREE - printf("Freeing dlsch process %d e (%p)\n",i,dlsch->harq_processes[i]->e); -#endif - } - - if (dlsch->harq_processes[i]->f) { - free16(dlsch->harq_processes[i]->f,14*N_RB*12*8); - dlsch->harq_processes[i]->f = NULL; -#ifdef DEBUG_DLSCH_FREE - printf("Freeing dlsch process %d f (%p)\n",i,dlsch->harq_processes[i]->f); -#endif - } - -#ifdef DEBUG_DLSCH_FREE - LOG_D(PHY,"Freeing dlsch process %d c (%p)\n",i,dlsch->harq_processes[i]->c); -#endif - - for (r=0; rharq_processes[i]->c[r]); -#endif - - if (dlsch->harq_processes[i]->c[r]) { - free16(dlsch->harq_processes[i]->c[r],1056); - dlsch->harq_processes[i]->c[r] = NULL; - } - if (dlsch->harq_processes[i]->d[r]) { - free16(dlsch->harq_processes[i]->d[r],3*8448); - dlsch->harq_processes[i]->d[r] = NULL; - } - - } - free16(dlsch->harq_processes[i],sizeof(NR_DL_gNB_HARQ_t)); - dlsch->harq_processes[i] = NULL; } - } - free16(dlsch,sizeof(NR_gNB_DLSCH_t)); - *dlschptr = NULL; + if (harq->f) { + free16(harq->f, 14 * N_RB * 12 * 8); + harq->f = NULL; +#ifdef DEBUG_DLSCH_FREE + printf("Freeing dlsch process %d f (%p)\n", i, harq->f); +#endif + } + +#ifdef DEBUG_DLSCH_FREE + LOG_D(PHY, "Freeing dlsch process %d c (%p)\n", i, harq->c); +#endif + + for (r = 0; r < a_segments; r++) { +#ifdef DEBUG_DLSCH_FREE + LOG_D(PHY, "Freeing dlsch process %d c[%d] (%p)\n", i, r, harq->c[r]); +#endif + + if (harq->c[r]) { + free16(harq->c[r], 1056); + harq->c[r] = NULL; + } + if (harq->d[r]) { + free16(harq->d[r], 3 * 8448); + harq->d[r] = NULL; + } + } + free16(harq, sizeof(NR_DL_gNB_HARQ_t)); + harq = NULL; + } } + free16(dlsch, sizeof(NR_gNB_DLSCH_t)); + *dlschptr = NULL; } NR_gNB_DLSCH_t *new_gNB_dlsch(NR_DL_FRAME_PARMS *frame_parms, @@ -142,9 +126,7 @@ NR_gNB_DLSCH_t *new_gNB_dlsch(NR_DL_FRAME_PARMS *frame_parms, uint8_t abstraction_flag, uint16_t N_RB) { - - NR_gNB_DLSCH_t *dlsch; - unsigned char exit_flag = 0,i,r,aa,layer; + unsigned char i,r,aa,layer; int re; uint16_t a_segments = MAX_NUM_NR_DLSCH_SEGMENTS; //number of segments to be allocated @@ -155,127 +137,74 @@ NR_gNB_DLSCH_t *new_gNB_dlsch(NR_DL_FRAME_PARMS *frame_parms, uint16_t dlsch_bytes = a_segments*1056; // allocated bytes per segment + NR_gNB_DLSCH_t *dlsch = malloc16(sizeof(NR_gNB_DLSCH_t)); + AssertFatal(dlsch, "cannot allocate dlsch\n"); + + bzero(dlsch,sizeof(NR_gNB_DLSCH_t)); + dlsch->Kmimo = Kmimo; + dlsch->Mdlharq = Mdlharq; + dlsch->Mlimit = 4; + dlsch->Nsoft = Nsoft; - dlsch = (NR_gNB_DLSCH_t *)malloc16(sizeof(NR_gNB_DLSCH_t)); + for (layer=0; layerue_spec_bf_weights[layer] = (int32_t **)malloc16(64 * sizeof(int32_t *)); - if (dlsch) { - bzero(dlsch,sizeof(NR_gNB_DLSCH_t)); - dlsch->Kmimo = Kmimo; - dlsch->Mdlharq = Mdlharq; - dlsch->Mlimit = 4; - dlsch->Nsoft = Nsoft; - - for (layer=0; layerue_spec_bf_weights[layer] = (int32_t**)malloc16(64*sizeof(int32_t*)); - - for (aa=0; aa<64; aa++) { - dlsch->ue_spec_bf_weights[layer][aa] = (int32_t *)malloc16(OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES*sizeof(int32_t)); - for (re=0;reue_spec_bf_weights[layer][aa][re] = 0x00007fff; - } - } - - dlsch->txdataF[layer] = (int32_t *)malloc16((NR_MAX_PDSCH_ENCODED_LENGTH/NR_MAX_NB_LAYERS)*sizeof(int32_t)); // NR_MAX_NB_LAYERS is already included in NR_MAX_PDSCH_ENCODED_LENGTH - } - - for (int q=0; qmod_symbs[q] = (int32_t *)malloc16(NR_MAX_PDSCH_ENCODED_LENGTH*sizeof(int32_t)); - - dlsch->calib_dl_ch_estimates = (int32_t**)malloc16(64*sizeof(int32_t*)); - for (aa=0; aa<64; aa++) { - dlsch->calib_dl_ch_estimates[aa] = (int32_t *)malloc16(OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES*sizeof(int32_t)); - - } - - for (i=0; i<20; i++) { - dlsch->harq_ids[0][i] = 0; - dlsch->harq_ids[1][i] = 0; - } - - for (i=0; iharq_processes[i] = (NR_DL_gNB_HARQ_t *)malloc16(sizeof(NR_DL_gNB_HARQ_t)); - LOG_T(PHY, "Required mem size %d dlsch->harq_processes[%d] %p\n", - dlsch_bytes, i,dlsch->harq_processes[i]); - - if (dlsch->harq_processes[i]) { - bzero(dlsch->harq_processes[i],sizeof(NR_DL_gNB_HARQ_t)); - // dlsch->harq_processes[i]->first_tx=1; - dlsch->harq_processes[i]->b = (unsigned char*)malloc16(dlsch_bytes); - dlsch->harq_processes[i]->pdu = (uint8_t*)malloc16(dlsch_bytes); - if (dlsch->harq_processes[i]->pdu) { - bzero(dlsch->harq_processes[i]->pdu,dlsch_bytes); - nr_emulate_dlsch_payload(dlsch->harq_processes[i]->pdu, (dlsch_bytes)>>3); - } else { - LOG_D(PHY,"Can't allocate PDU\n"); - exit_flag=1; - } - - if (dlsch->harq_processes[i]->b) { - bzero(dlsch->harq_processes[i]->b,dlsch_bytes); - } else { - LOG_D(PHY,"Can't get b\n"); - exit_flag=1; - } - - if (abstraction_flag==0) { - for (r=0; rharq_processes[i]->c[r] = (uint8_t*)malloc16(8448); - dlsch->harq_processes[i]->d[r] = (uint8_t*)malloc16(68*384); //max size for coded output - if (dlsch->harq_processes[i]->c[r]) { - bzero(dlsch->harq_processes[i]->c[r],8448); - } else { - LOG_D(PHY,"Can't get c\n"); - exit_flag=2; - } - if (dlsch->harq_processes[i]->d[r]) { - bzero(dlsch->harq_processes[i]->d[r],(3*8448)); - } else { - LOG_D(PHY,"Can't get d\n"); - exit_flag=2; - } - } - dlsch->harq_processes[i]->e = (uint8_t*)malloc16(14*N_RB*12*8); - if (dlsch->harq_processes[i]->e) { - bzero(dlsch->harq_processes[i]->e,14*N_RB*12*8); - } else { - printf("Can't get e\n"); - exit_flag=1; - } - dlsch->harq_processes[i]->f = (uint8_t*)malloc16(14*N_RB*12*8); - if (dlsch->harq_processes[i]->f) { - bzero(dlsch->harq_processes[i]->f,14*N_RB*12*8); - } else { - printf("Can't get f\n"); - exit_flag=1; - } - } - } else { - LOG_D(PHY,"Can't get harq_p %d\n",i); - exit_flag=3; + for (aa = 0; aa < 64; aa++) { + dlsch->ue_spec_bf_weights[layer][aa] = (int32_t *)malloc16(OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES * sizeof(int32_t)); + for (re = 0; re < OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES; re++) { + dlsch->ue_spec_bf_weights[layer][aa][re] = 0x00007fff; } } - if (exit_flag==0) { - for (i=0; iharq_processes[i]->round=0; - } - - return(dlsch); - } + dlsch->txdataF[layer] = + (int32_t *)malloc16((NR_MAX_PDSCH_ENCODED_LENGTH / NR_MAX_NB_LAYERS) + * sizeof(int32_t)); // NR_MAX_NB_LAYERS is already included in NR_MAX_PDSCH_ENCODED_LENGTH } - LOG_D(PHY,"new_gNB_dlsch exit flag %d, size of %ld\n", - exit_flag, sizeof(NR_gNB_DLSCH_t)); + for (int q = 0; q < NR_MAX_NB_CODEWORDS; q++) + dlsch->mod_symbs[q] = (int32_t *)malloc16(NR_MAX_PDSCH_ENCODED_LENGTH * sizeof(int32_t)); - free_gNB_dlsch(&dlsch,N_RB); + dlsch->calib_dl_ch_estimates = (int32_t **)malloc16(64 * sizeof(int32_t *)); + for (aa = 0; aa < 64; aa++) { + dlsch->calib_dl_ch_estimates[aa] = (int32_t *)malloc16(OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES * sizeof(int32_t)); + } - return(NULL); + for (i = 0; i < 20; i++) { + dlsch->harq_ids[0][i] = 0; + dlsch->harq_ids[1][i] = 0; + } + NR_DL_gNB_HARQ_t *harq = &dlsch->harq_process; + bzero(harq, sizeof(NR_DL_gNB_HARQ_t)); + harq->b = malloc16(dlsch_bytes); + AssertFatal(harq->b, "cannot allocate memory for harq->b\n"); + harq->pdu = malloc16(dlsch_bytes); + AssertFatal(harq->pdu, "cannot allocate memory for harq->pdu\n"); + bzero(harq->pdu, dlsch_bytes); + nr_emulate_dlsch_payload(harq->pdu, (dlsch_bytes) >> 3); + bzero(harq->b, dlsch_bytes); + + for (r = 0; r < a_segments; r++) { + // account for filler in first segment and CRCs for multiple segment case + // [hna] 8448 is the maximum CB size in NR + // 68*348 = 68*(maximum size of Zc) + // In section 5.3.2 in 38.212, the for loop is up to N + 2*Zc (maximum size of N is 66*Zc, therefore 68*Zc) + harq->c[r] = malloc16(8448); + AssertFatal(harq->c[r], "cannot allocate harq->c[%d]\n", r); + harq->d[r] = malloc16(68 * 384); + AssertFatal(harq->d[r], "cannot allocate harq->d[%d]\n", r); // max size for coded output + bzero(harq->c[r], 8448); + bzero(harq->d[r], (3 * 8448)); + harq->e = malloc16(14 * N_RB * 12 * 8); + AssertFatal(harq->e, "cannot allocate harq->e\n"); + bzero(harq->e, 14 * N_RB * 12 * 8); + harq->f = malloc16(14 * N_RB * 12 * 8); + AssertFatal(harq->f, "cannot allocate harq->f\n"); + bzero(harq->f, 14 * N_RB * 12 * 8); + } + + return(dlsch); } void clean_gNB_dlsch(NR_gNB_DLSCH_t *dlsch) @@ -284,28 +213,21 @@ void clean_gNB_dlsch(NR_gNB_DLSCH_t *dlsch) unsigned char Mdlharq; unsigned char i,j,r; - if (dlsch) { - Mdlharq = dlsch->Mdlharq; - dlsch->rnti = 0; - dlsch->active = 0; + AssertFatal(dlsch!=NULL,"dlsch is null\n"); + Mdlharq = dlsch->Mdlharq; + dlsch->rnti = 0; + dlsch->active = 0; + NR_DL_gNB_HARQ_t *harq=&dlsch->harq_process; - for (i=0; i<10; i++) { - dlsch->harq_ids[0][i] = Mdlharq; - dlsch->harq_ids[1][i] = Mdlharq; - } - for (i=0; iharq_processes[i]) { - // dlsch->harq_processes[i]->Ndi = 0; - //dlsch->harq_processes[i]->status = 0; - dlsch->harq_processes[i]->round = 0; - - for (j=0; j<96; j++) - for (r=0; rharq_processes[i]->d[r]) - dlsch->harq_processes[i]->d[r][j] = NR_NULL; - - } - } + for (i=0; i<10; i++) { + dlsch->harq_ids[0][i] = Mdlharq; + dlsch->harq_ids[1][i] = Mdlharq; + } + for (i=0; id[r]) + harq->d[r][j] = NR_NULL; } } @@ -322,13 +244,12 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB, unsigned int G; unsigned int crc=1; - uint8_t harq_pid = dlsch->harq_ids[frame%2][slot]; - AssertFatal(harq_pid<8 && harq_pid>=0,"illegal harq_pid %d\b",harq_pid); - nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &dlsch->harq_processes[harq_pid]->pdsch_pdu.pdsch_pdu_rel15; + NR_DL_gNB_HARQ_t *harq = &dlsch->harq_process; + nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &harq->pdsch_pdu.pdsch_pdu_rel15; uint16_t nb_rb = rel15->rbSize; uint8_t nb_symb_sch = rel15->NrOfSymbols; uint32_t A, Kb, F=0; - uint32_t *Zc = &dlsch->harq_processes[harq_pid]->Z; + uint32_t *Zc = &dlsch->harq_process.Z; uint8_t mod_order = rel15->qamModOrder[0]; uint16_t Kr=0,r; uint32_t r_offset=0; @@ -347,8 +268,7 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB, float Coderate = 0.0; uint8_t Nl = 4; - dlsch->harq_processes[harq_pid]->round = nr_rv_round_map[rel15->rvIndex[0]]; - + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_DLSCH_ENCODING, VCD_FUNCTION_IN); A = rel15->TBSize[0]<<3; @@ -367,175 +287,157 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB, } if (stats) { - stats->round_trials[dlsch->harq_processes[harq_pid]->round]++; stats->rnti = dlsch->rnti; - if (dlsch->harq_processes[harq_pid]->round == 0){ - stats->total_bytes_tx += rel15->TBSize[0]; - stats->current_RI = rel15->nrOfLayers; - stats->current_Qm = rel15->qamModOrder[0]; - } + stats->total_bytes_tx += rel15->TBSize[0]; + stats->current_RI = rel15->nrOfLayers; + stats->current_Qm = rel15->qamModOrder[0]; } G = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs,mod_order,rel15->nrOfLayers); LOG_D(PHY,"dlsch coding A %d G %d mod_order %d\n", A,G, mod_order); - // if (dlsch->harq_processes[harq_pid]->Ndi == 1) { // this is a new packet - if (dlsch->harq_processes[harq_pid]->round == 0) { // this is a new packet -#ifdef DEBUG_DLSCH_CODING - LOG_D(PHY,"encoding thinks this is a new packet \n"); -#endif - /* - int i; - LOG_D(PHY,"dlsch (tx): \n"); - for (i=0;i<(A>>3);i++) - LOG_D(PHY,"%02x\n",a[i]); - LOG_D(PHY,"\n"); - */ - log_dump(PHY, a, 16, LOG_DUMP_CHAR,"gNB pdsch tx frame %d %d: ", frame, slot); + if (A > 3824) { + // Add 24-bit crc (polynomial A) to payload + crc = crc24a(a,A)>>8; + a[A>>3] = ((uint8_t*)&crc)[2]; + a[1+(A>>3)] = ((uint8_t*)&crc)[1]; + a[2+(A>>3)] = ((uint8_t*)&crc)[0]; + //printf("CRC %x (A %d)\n",crc,A); + //printf("a0 %d a1 %d a2 %d\n", a[A>>3], a[1+(A>>3)], a[2+(A>>3)]); + + harq->B = A+24; + // harq->b = a; - if (A > 3824) { - // Add 24-bit crc (polynomial A) to payload - crc = crc24a(a,A)>>8; - a[A>>3] = ((uint8_t*)&crc)[2]; - a[1+(A>>3)] = ((uint8_t*)&crc)[1]; - a[2+(A>>3)] = ((uint8_t*)&crc)[0]; - //printf("CRC %x (A %d)\n",crc,A); - //printf("a0 %d a1 %d a2 %d\n", a[A>>3], a[1+(A>>3)], a[2+(A>>3)]); - - dlsch->harq_processes[harq_pid]->B = A+24; - // dlsch->harq_processes[harq_pid]->b = a; - - AssertFatal((A/8)+4 <= MAX_NR_DLSCH_PAYLOAD_BYTES,"A %d is too big (A/8+4 = %d > %d)\n",A,(A/8)+4,MAX_NR_DLSCH_PAYLOAD_BYTES); - - memcpy(dlsch->harq_processes[harq_pid]->b,a,(A/8)+4); // why is this +4 if the CRC is only 3 bytes? - } - else { - // Add 16-bit crc (polynomial A) to payload - crc = crc16(a,A)>>16; - a[A>>3] = ((uint8_t*)&crc)[1]; - a[1+(A>>3)] = ((uint8_t*)&crc)[0]; - //printf("CRC %x (A %d)\n",crc,A); - //printf("a0 %d a1 %d \n", a[A>>3], a[1+(A>>3)]); - - dlsch->harq_processes[harq_pid]->B = A+16; - // dlsch->harq_processes[harq_pid]->b = a; - - AssertFatal((A/8)+3 <= MAX_NR_DLSCH_PAYLOAD_BYTES,"A %d is too big (A/8+3 = %d > %d)\n",A,(A/8)+3,MAX_NR_DLSCH_PAYLOAD_BYTES); - - memcpy(dlsch->harq_processes[harq_pid]->b,a,(A/8)+3); // using 3 bytes to mimic the case of 24 bit crc - } - if (R<1000) - Coderate = (float) R /(float) 1024; - else // to scale for mcs 20 and 26 in table 5.1.3.1-2 which are decimal and input 2* in nr_tbs_tools - Coderate = (float) R /(float) 2048; - - if ((A <=292) || ((A<=3824) && (Coderate <= 0.6667)) || Coderate <= 0.25) - dlsch->harq_processes[harq_pid]->BG = 2; - else - dlsch->harq_processes[harq_pid]->BG = 1; - - start_meas(dlsch_segmentation_stats); - Kb = nr_segmentation(dlsch->harq_processes[harq_pid]->b, - dlsch->harq_processes[harq_pid]->c, - dlsch->harq_processes[harq_pid]->B, - &dlsch->harq_processes[harq_pid]->C, - &dlsch->harq_processes[harq_pid]->K, - Zc, - &dlsch->harq_processes[harq_pid]->F, - dlsch->harq_processes[harq_pid]->BG); - stop_meas(dlsch_segmentation_stats); - F = dlsch->harq_processes[harq_pid]->F; - - Kr = dlsch->harq_processes[harq_pid]->K; -#ifdef DEBUG_DLSCH_CODING - uint16_t Kr_bytes; - Kr_bytes = Kr>>3; -#endif - - //printf("segment Z %d k %d Kr %d BG %d C %d\n", *Zc,dlsch->harq_processes[harq_pid]->K,Kr,BG,dlsch->harq_processes[harq_pid]->C); - - for (r=0; rharq_processes[harq_pid]->C; r++) { - //d_tmp[r] = &dlsch->harq_processes[harq_pid]->d[r][0]; - //channel_input[r] = &dlsch->harq_processes[harq_pid]->d[r][0]; -#ifdef DEBUG_DLSCH_CODING - LOG_D(PHY,"Encoder: B %d F %d \n",dlsch->harq_processes[harq_pid]->B, dlsch->harq_processes[harq_pid]->F); - LOG_D(PHY,"start ldpc encoder segment %d/%d\n",r,dlsch->harq_processes[harq_pid]->C); - LOG_D(PHY,"input %d %d %d %d %d \n", dlsch->harq_processes[harq_pid]->c[r][0], dlsch->harq_processes[harq_pid]->c[r][1], dlsch->harq_processes[harq_pid]->c[r][2],dlsch->harq_processes[harq_pid]->c[r][3], dlsch->harq_processes[harq_pid]->c[r][4]); - for (int cnt =0 ; cnt < 22*(*Zc)/8; cnt ++){ - LOG_D(PHY,"%d ", dlsch->harq_processes[harq_pid]->c[r][cnt]); - } - LOG_D(PHY,"\n"); - -#endif - //ldpc_encoder_orig((unsigned char*)dlsch->harq_processes[harq_pid]->c[r],dlsch->harq_processes[harq_pid]->d[r],*Zc,Kb,Kr,BG,0); - //ldpc_encoder_optim((unsigned char*)dlsch->harq_processes[harq_pid]->c[r],(unsigned char*)&dlsch->harq_processes[harq_pid]->d[r][0],*Zc,Kb,Kr,BG,NULL,NULL,NULL,NULL); - } - encoder_implemparams_t impp; - impp.n_segments=dlsch->harq_processes[harq_pid]->C; - impp.tprep = tprep; - impp.tinput = tinput; - impp.tparity = tparity; - impp.toutput = toutput; - - for(int j=0;j<(dlsch->harq_processes[harq_pid]->C/8+1);j++) { - impp.macro_num=j; - nrLDPC_encoder(dlsch->harq_processes[harq_pid]->c,dlsch->harq_processes[harq_pid]->d,*Zc,Kb,Kr,dlsch->harq_processes[harq_pid]->BG,&impp); - } - - -#ifdef DEBUG_DLSCH_CODING - write_output("enc_input0.m","enc_in0",&dlsch->harq_processes[harq_pid]->c[0][0],Kr_bytes,1,4); - write_output("enc_output0.m","enc0",&dlsch->harq_processes[harq_pid]->d[0][0],(3*8*Kr_bytes)+12,1,4); -#endif + AssertFatal((A / 8) + 4 <= MAX_NR_DLSCH_PAYLOAD_BYTES, + "A %d is too big (A/8+4 = %d > %d)\n", + A, + (A / 8) + 4, + MAX_NR_DLSCH_PAYLOAD_BYTES); + memcpy(harq->b, a, (A / 8) + 4); // why is this +4 if the CRC is only 3 bytes? } + else { + // Add 16-bit crc (polynomial A) to payload + crc = crc16(a,A)>>16; + a[A>>3] = ((uint8_t*)&crc)[1]; + a[1+(A>>3)] = ((uint8_t*)&crc)[0]; + //printf("CRC %x (A %d)\n",crc,A); + //printf("a0 %d a1 %d \n", a[A>>3], a[1+(A>>3)]); + + harq->B = A+16; + // harq->b = a; - F = dlsch->harq_processes[harq_pid]->F; + AssertFatal((A / 8) + 3 <= MAX_NR_DLSCH_PAYLOAD_BYTES, + "A %d is too big (A/8+3 = %d > %d)\n", + A, + (A / 8) + 3, + MAX_NR_DLSCH_PAYLOAD_BYTES); - Kr = dlsch->harq_processes[harq_pid]->K; - for (r=0; rharq_processes[harq_pid]->C; r++) { + memcpy(harq->b, a, (A / 8) + 3); // using 3 bytes to mimic the case of 24 bit crc + } + if (R<1000) + Coderate = (float) R /(float) 1024; + else // to scale for mcs 20 and 26 in table 5.1.3.1-2 which are decimal and input 2* in nr_tbs_tools + Coderate = (float) R /(float) 2048; + + if ((A <=292) || ((A<=3824) && (Coderate <= 0.6667)) || Coderate <= 0.25) + harq->BG = 2; + else + harq->BG = 1; + + start_meas(dlsch_segmentation_stats); + Kb = nr_segmentation(harq->b, harq->c, harq->B, &harq->C, &harq->K, Zc, &harq->F, harq->BG); + stop_meas(dlsch_segmentation_stats); + F = harq->F; + + Kr = harq->K; +#ifdef DEBUG_DLSCH_CODING + uint16_t Kr_bytes; + Kr_bytes = Kr>>3; +#endif + //printf("segment Z %d k %d Kr %d BG %d C %d\n", *Zc,harq->K,Kr,BG,harq->C); + + for (r=0; rC; r++) { + //d_tmp[r] = &harq->d[r][0]; + //channel_input[r] = &harq->d[r][0]; +#ifdef DEBUG_DLSCH_CODING + LOG_D(PHY,"Encoder: B %d F %d \n",harq->B, harq->F); + LOG_D(PHY,"start ldpc encoder segment %d/%d\n",r,harq->C); + LOG_D(PHY,"input %d %d %d %d %d \n", harq->c[r][0], harq->c[r][1], harq->c[r][2],harq->c[r][3], harq->c[r][4]); + for (int cnt =0 ; cnt < 22*(*Zc)/8; cnt ++){ + LOG_D(PHY,"%d ", harq->c[r][cnt]); + } + LOG_D(PHY,"\n"); + +#endif + //ldpc_encoder_orig((unsigned char*)harq->c[r],harq->d[r],*Zc,Kb,Kr,BG,0); + //ldpc_encoder_optim((unsigned char*)harq->c[r],(unsigned char*)&harq->d[r][0],*Zc,Kb,Kr,BG,NULL,NULL,NULL,NULL); + } + encoder_implemparams_t impp; + impp.n_segments=harq->C; + impp.tprep = tprep; + impp.tinput = tinput; + impp.tparity = tparity; + impp.toutput = toutput; + + for(int j=0;j<(harq->C/8+1);j++) { + impp.macro_num=j; + nrLDPC_encoder(harq->c,harq->d,*Zc,Kb,Kr,harq->BG,&impp); + } + + +#ifdef DEBUG_DLSCH_CODING + write_output("enc_input0.m","enc_in0",&harq->c[0][0],Kr_bytes,1,4); + write_output("enc_output0.m","enc0",&harq->d[0][0],(3*8*Kr_bytes)+12,1,4); +#endif + + F = harq->F; + + Kr = harq->K; + for (r=0; rC; r++) { + if (F>0) { for (int k=(Kr-F-2*(*Zc)); kharq_processes[harq_pid]->d[r][k] = NR_NULL; + harq->d[r][k] = NR_NULL; //if (k<(Kr-F+8)) - //printf("r %d filler bits [%d] = %d \n", r,k, dlsch->harq_processes[harq_pid]->d[r][k]); + //printf("r %d filler bits [%d] = %d \n", r,k, harq->d[r][k]); } } - - - + + + #ifdef DEBUG_DLSCH_CODING - LOG_D(PHY,"rvidx in encoding = %d\n", rel15->rvIndex[0]); + LOG_D(PHY,"rvidx in encoding = %d\n", rel15->rvIndex[0]); #endif - - E = nr_get_E(G, dlsch->harq_processes[harq_pid]->C, mod_order, rel15->nrOfLayers, r); - + + E = nr_get_E(G, harq->C, mod_order, rel15->nrOfLayers, r); + //#ifdef DEBUG_DLSCH_CODING LOG_D(PHY,"Rate Matching, Code segment %d/%d (coded bits (G) %u, E %d, Filler bits %d, Filler offset %d mod_order %d, nb_rb %d)...\n", r, - dlsch->harq_processes[harq_pid]->C, + harq->C, G, E, F, Kr-F-2*(*Zc), mod_order,nb_rb); - + // for tbslbrm calculation according to 5.4.2.1 of 38.212 if (rel15->nrOfLayers < Nl) Nl = rel15->nrOfLayers; - + Tbslbrm = nr_compute_tbslbrm(rel15->mcsTable[0],nb_rb,Nl); - + start_meas(dlsch_rate_matching_stats); nr_rate_matching_ldpc(Ilbrm, Tbslbrm, - dlsch->harq_processes[harq_pid]->BG, + harq->BG, *Zc, - dlsch->harq_processes[harq_pid]->d[r], - dlsch->harq_processes[harq_pid]->e+r_offset, - dlsch->harq_processes[harq_pid]->C, + harq->d[r], + harq->e+r_offset, + harq->C, F, Kr-F-2*(*Zc), rel15->rvIndex[0], @@ -543,22 +445,22 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB, stop_meas(dlsch_rate_matching_stats); #ifdef DEBUG_DLSCH_CODING for (int i =0; i<16; i++) - printf("output ratematching e[%d]= %d r_offset %u\n", i,dlsch->harq_processes[harq_pid]->e[i+r_offset], r_offset); + printf("output ratematching e[%d]= %d r_offset %u\n", i,harq->e[i+r_offset], r_offset); #endif start_meas(dlsch_interleaving_stats); nr_interleaving_ldpc(E, mod_order, - dlsch->harq_processes[harq_pid]->e+r_offset, - dlsch->harq_processes[harq_pid]->f+r_offset); + harq->e+r_offset, + harq->f+r_offset); stop_meas(dlsch_interleaving_stats); #ifdef DEBUG_DLSCH_CODING for (int i =0; i<16; i++) - printf("output interleaving f[%d]= %d r_offset %u\n", i,dlsch->harq_processes[harq_pid]->f[i+r_offset], r_offset); + printf("output interleaving f[%d]= %d r_offset %u\n", i,harq->f[i+r_offset], r_offset); - if (r==dlsch->harq_processes[harq_pid]->C-1) - write_output("enc_output.m","enc",dlsch->harq_processes[harq_pid]->f,G,1,4); + if (r==harq->C-1) + write_output("enc_output.m","enc",harq->f,G,1,4); #endif r_offset += E; diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch_tools.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch_tools.c index 5ce2c45a7d..05d6c4c112 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch_tools.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch_tools.c @@ -289,12 +289,12 @@ void nr_fill_dlsch(PHY_VARS_gNB *gNB, AssertFatal( (dlsch_id>=0) && (dlsch_idrnti,dlsch_id); NR_gNB_DLSCH_t *dlsch = gNB->dlsch[dlsch_id][0]; - NR_DL_gNB_HARQ_t **harq = dlsch->harq_processes; + NR_DL_gNB_HARQ_t *harq = &dlsch->harq_process; /// DLSCH struct - memcpy((void*)&harq[dlsch->harq_ids[frame%2][slot]]->pdsch_pdu, (void*)pdsch_pdu, sizeof(nfapi_nr_dl_tti_pdsch_pdu)); + memcpy((void*)&harq->pdsch_pdu, (void*)pdsch_pdu, sizeof(nfapi_nr_dl_tti_pdsch_pdu)); gNB->num_pdsch_rnti[slot]++; AssertFatal(sdu!=NULL,"sdu is null\n"); - harq[dlsch->harq_ids[frame%2][slot]]->pdu = sdu; + harq->pdu = sdu; } diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c index 7e6becb4a8..42d6cfad7a 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c @@ -16,10 +16,10 @@ void nr_idft(int32_t *z, uint32_t Msc_PUSCH) { #if defined(__x86_64__) || defined(__i386__) - __m128i idft_in128[1][1200], idft_out128[1][1200]; + __m128i idft_in128[1][3240], idft_out128[1][3240]; __m128i norm128; #elif defined(__arm__) - int16x8_t idft_in128[1][1200], idft_out128[1][1200]; + int16x8_t idft_in128[1][3240], idft_out128[1][3240]; int16x8_t norm128; #endif int16_t *idft_in0 = (int16_t*)idft_in128[0], *idft_out0 = (int16_t*)idft_out128[0]; @@ -28,20 +28,19 @@ void nr_idft(int32_t *z, uint32_t Msc_PUSCH) LOG_T(PHY,"Doing lte_idft for Msc_PUSCH %d\n",Msc_PUSCH); - // conjugate input - for (i = 0; i < (Msc_PUSCH>>2); i++) { + if ((Msc_PUSCH % 1536) > 0) { + // conjugate input + for (i = 0; i < (Msc_PUSCH>>2); i++) { #if defined(__x86_64__)||defined(__i386__) - *&(((__m128i*)z)[i]) = _mm_sign_epi16(*&(((__m128i*)z)[i]), *(__m128i*)&conjugate2[0]); + *&(((__m128i*)z)[i]) = _mm_sign_epi16(*&(((__m128i*)z)[i]), *(__m128i*)&conjugate2[0]); #elif defined(__arm__) - *&(((int16x8_t*)z)[i]) = vmulq_s16(*&(((int16x8_t*)z)[i]), *(int16x8_t*)&conjugate2[0]); + *&(((int16x8_t*)z)[i]) = vmulq_s16(*&(((int16x8_t*)z)[i]), *(int16x8_t*)&conjugate2[0]); #endif + } + for (i = 0, ip = 0; i < Msc_PUSCH; i++, ip+=4) + ((uint32_t*)idft_in0)[ip+0] = z[i]; } - for (i=0,ip=0; i 0) { + for (i = 0, ip = 0; i < Msc_PUSCH; i++, ip+=4) + z[i] = ((uint32_t*)idft_out0)[ip]; - - for (i = 0, ip = 0; i < Msc_PUSCH; i++, ip+=4) { - z[i] = ((int32_t*)idft_out0)[ip]; - } - - // conjugate output - for (i = 0; i < (Msc_PUSCH>>2); i++) { + // conjugate output + for (i = 0; i < (Msc_PUSCH>>2); i++) { #if defined(__x86_64__) || defined(__i386__) - ((__m128i*)z)[i] = _mm_sign_epi16(((__m128i*)z)[i], *(__m128i*)&conjugate2[0]); + ((__m128i*)z)[i] = _mm_sign_epi16(((__m128i*)z)[i], *(__m128i*)&conjugate2[0]); #elif defined(__arm__) - *&(((int16x8_t*)z)[i]) = vmulq_s16(*&(((int16x8_t*)z)[i]), *(int16x8_t*)&conjugate2[0]); + *&(((int16x8_t*)z)[i]) = vmulq_s16(*&(((int16x8_t*)z)[i]), *(int16x8_t*)&conjugate2[0]); #endif + } } #if defined(__x86_64__) || defined(__i386__) @@ -222,6 +298,7 @@ void nr_idft(int32_t *z, uint32_t Msc_PUSCH) } + void nr_ulsch_extract_rbs_single(int32_t **rxdataF, NR_gNB_PUSCH *pusch_vars, unsigned char symbol, diff --git a/openair1/PHY/NR_TRANSPORT/pucch_rx.c b/openair1/PHY/NR_TRANSPORT/pucch_rx.c index 83a66b55fb..2d1fdff4be 100644 --- a/openair1/PHY/NR_TRANSPORT/pucch_rx.c +++ b/openair1/PHY/NR_TRANSPORT/pucch_rx.c @@ -393,6 +393,7 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB, // first bit of bitmap for sr presence and second bit for acknack presence uci_pdu->pduBitmap = pucch_pdu->sr_flag | ((pucch_pdu->bit_len_harq>0)<<1); uci_pdu->pucch_format = 0; // format 0 + uci_pdu->rnti = pucch_pdu->rnti; uci_pdu->ul_cqi = cqi; uci_pdu->timing_advance = 0xffff; // currently not valid uci_pdu->rssi = 1280 - (10*dB_fixed(32767*32767)-dB_fixed_times10(signal_energy_nodc(&rxdataF[0][pucch_pdu->start_symbol_index*frame_parms->ofdm_symbol_size+re_offset],12))); diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c b/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c index 4b36180b58..0318ed6478 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c @@ -24,6 +24,7 @@ #include "PHY/NR_UE_ESTIMATION/nr_estimation.h" #include "PHY/impl_defs_top.h" +#include "executables/softmodem-common.h" #include "common/utils/LOG/vcd_signal_dumper.h" #define DEBUG_PHY @@ -104,15 +105,14 @@ void nr_adjust_synch_ue(NR_DL_FRAME_PARMS *frame_parms, { first_time = 0; ue->time_sync_cell = 1; - if (ue->mac_enabled==1) { + if (get_softmodem_params()->do_ra) { LOG_I(PHY,"[UE%d] Sending synch status to higher layers\n",ue->Mod_id); //mac_resynch(); //dl_phy_sync_success(ue->Mod_id,frame,0,1);//ue->common_vars.eNb_id); ue->UE_mode[0] = PRACH; ue->prach_resources[gNB_id]->sync_frame = frame; ue->prach_resources[gNB_id]->init_msg1 = 0; - } - else { + } else { ue->UE_mode[0] = PUSCH; } } diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h b/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h index dd0a7ae2da..6c461ef448 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h @@ -90,6 +90,7 @@ void nr_ue_measurements(PHY_VARS_NR_UE *ue, uint8_t slot); void nr_ue_rsrp_measurements(PHY_VARS_NR_UE *ue, + uint8_t gNB_index, UE_nr_rxtx_proc_t *proc, uint8_t slot, uint8_t abstraction_flag); diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c b/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c index eebce03d83..61fc40ad3f 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c @@ -30,7 +30,7 @@ * \warning */ -#include "nr-softmodem-common.h" +#include "executables/softmodem-common.h" #include "PHY/defs_nr_UE.h" #include "PHY/phy_extern_nr_ue.h" #include "common/utils/LOG/log.h" @@ -45,25 +45,41 @@ //#define DEBUG_MEAS_UE //#define DEBUG_RANK_EST +// Returns the pathloss in dBm for the active UL BWP on the selected carrier based on the DL RS associated with the PRACH transmission +// computation according to clause 7.4 (Physical random access channel) of 3GPP TS 38.213 version 16.3.0 Release 16 +// Assumptions: +// - PRACH transmission from a UE is not in response to a detection of a PDCCH order by the UE +// Measurement units: +// - referenceSignalPower: dBm/RE (average EPRE of the resources elements that carry secondary synchronization signals in dBm) int16_t get_nr_PL(uint8_t Mod_id, uint8_t CC_id, uint8_t gNB_index){ PHY_VARS_NR_UE *ue = PHY_vars_UE_g[Mod_id][CC_id]; + int16_t pathloss; - /* - if (ue->frame_parms.mode1_flag == 1) - RSoffset = 6; - else - RSoffset = 3; - */ + if (get_softmodem_params()->do_ra){ - /* LOG_D(PHY,"get_nr_PL : rsrp %f dBm/RE (%f), eNB power %d dBm/RE\n", - (1.0*dB_fixed_times10(ue->measurements.rsrp[eNB_index])-(10.0*ue->rx_total_gain_dB))/10.0, - 10*log10((double)ue->measurements.rsrp[eNB_index]), - ue->frame_parms.pdsch_config_common.referenceSignalPower);*/ + long referenceSignalPower = ue->nrUE_config.ssb_config.ss_pbch_power; + double rsrp_dBm = 10*log10(ue->measurements.rsrp[gNB_index]) + 30 - ue->rx_total_gain_dB; + + pathloss = (int16_t)(10*log10(pow(10, (double)(referenceSignalPower)/10) - pow(10, (double)(rsrp_dBm)/10))); + + LOG_D(MAC, "In %s: pathloss %d dBm, UE RX total gain %d dB, referenceSignalPower %ld dBm (%f mW), RSRP %f dBm (%f mW)\n", + __FUNCTION__, + pathloss, + ue->rx_total_gain_dB, + referenceSignalPower, + pow(10, referenceSignalPower/10), + rsrp_dBm, + pow(10, rsrp_dBm/10)); + + } else { + + pathloss = ((int16_t)(((10*ue->rx_total_gain_dB) - dB_fixed_times10(ue->measurements.rsrp[gNB_index]))/10)); + + } + + return pathloss; - return((int16_t)(((10*ue->rx_total_gain_dB) - dB_fixed_times10(ue->measurements.rsrp[gNB_index]))/10)); - // dB_fixed_times10(RSoffset*12*ue_g[Mod_id][CC_id]->frame_parms.N_RB_DL) + - //(ue->frame_parms.pdsch_config_common.referenceSignalPower*10))/10)); } uint32_t get_nr_rx_total_gain_dB (module_id_t Mod_id,uint8_t CC_id) @@ -108,7 +124,7 @@ void nr_ue_measurements(PHY_VARS_NR_UE *ue, ue->measurements.nb_antennas_rx = frame_parms->nb_antennas_rx; // signal measurements - for (gNB_id = 0; gNB_id < ue->n_connected_eNB; gNB_id++){ + for (gNB_id = 0; gNB_id < ue->n_connected_gNB; gNB_id++){ ue->measurements.rx_power_tot[gNB_id] = 0; @@ -140,7 +156,7 @@ void nr_ue_measurements(PHY_VARS_NR_UE *ue, // filter to remove jitter if (ue->init_averaging == 0) { - for (gNB_id = 0; gNB_id < ue->n_connected_eNB; gNB_id++) + for (gNB_id = 0; gNB_id < ue->n_connected_gNB; gNB_id++) ue->measurements.rx_power_avg[gNB_id] = (int)(((k1*((long long int)(ue->measurements.rx_power_avg[gNB_id]))) + (k2*((long long int)(ue->measurements.rx_power_tot[gNB_id])))) >> 10); ue->measurements.n0_power_avg = (int)(((k1*((long long int) (ue->measurements.n0_power_avg))) + (k2*((long long int) (ue->measurements.n0_power_tot))))>>10); @@ -149,7 +165,7 @@ void nr_ue_measurements(PHY_VARS_NR_UE *ue, } else { - for (gNB_id = 0; gNB_id < ue->n_connected_eNB; gNB_id++) + for (gNB_id = 0; gNB_id < ue->n_connected_gNB; gNB_id++) ue->measurements.rx_power_avg[gNB_id] = ue->measurements.rx_power_tot[gNB_id]; ue->measurements.n0_power_avg = ue->measurements.n0_power_tot; @@ -157,7 +173,7 @@ void nr_ue_measurements(PHY_VARS_NR_UE *ue, } - for (gNB_id = 0; gNB_id < ue->n_connected_eNB; gNB_id++) { + for (gNB_id = 0; gNB_id < ue->n_connected_gNB; gNB_id++) { ue->measurements.rx_power_avg_dB[gNB_id] = dB_fixed( ue->measurements.rx_power_avg[gNB_id]); ue->measurements.wideband_cqi_tot[gNB_id] = dB_fixed2(ue->measurements.rx_power_tot[gNB_id], ue->measurements.n0_power_tot); @@ -180,74 +196,74 @@ void nr_ue_measurements(PHY_VARS_NR_UE *ue, #endif } +// This function implements: +// - SS reference signal received power (SS-RSRP) as per clause 5.1.1 of 3GPP TS 38.215 version 16.3.0 Release 16 +// - no Layer 3 filtering implemented (no filterCoefficient provided from RRC) +// Todo: +// - Layer 3 filtering according to clause 5.5.3.2 of 3GPP TS 38.331 version 16.2.0 Release 16 +// Measurement units: +// - RSRP: W (dBW) +// - RX Gain dB void nr_ue_rsrp_measurements(PHY_VARS_NR_UE *ue, - UE_nr_rxtx_proc_t *proc, - uint8_t slot, - uint8_t abstraction_flag) + uint8_t gNB_id, + UE_nr_rxtx_proc_t *proc, + uint8_t slot, + uint8_t abstraction_flag) { - int aarx,rb, symbol_offset; - int16_t *rxF; + int aarx; + int nb_re; + int k_start = 55; + int k_end = 183; + unsigned int ssb_offset = ue->frame_parms.first_carrier_offset + ue->frame_parms.ssb_start_subcarrier; + uint8_t l_sss = ue->symbol_offset + 2; - uint16_t Nid_cell = ue->frame_parms.Nid_cell; - uint8_t eNB_offset=0,l,nushift; - uint16_t off,nb_rb; -// NR_UE_MAC_INST_t *mac = get_mac_inst(0); - int **rxdataF=ue->common_vars.common_vars_rx_data_per_thread[proc->thread_id].rxdataF; + if (ssb_offset>= ue->frame_parms.ofdm_symbol_size){ - nushift = ue->frame_parms.Nid_cell%4; - ue->frame_parms.nushift = nushift; - unsigned int ssb_offset = ue->frame_parms.first_carrier_offset + ue->frame_parms.ssb_start_subcarrier; - if (ssb_offset>= ue->frame_parms.ofdm_symbol_size) ssb_offset-=ue->frame_parms.ofdm_symbol_size; - - symbol_offset = ue->frame_parms.ofdm_symbol_size*((ue->symbol_offset+1)%(ue->frame_parms.symbols_per_slot)); + ssb_offset -= ue->frame_parms.ofdm_symbol_size; - ue->measurements.rsrp[eNB_offset] = 0; + } - //if (mac->csirc->reportQuantity.choice.ssb_Index_RSRP){ - nb_rb = 20; - //} else{ - // LOG_E(PHY,"report quantity not supported \n"); - //} + ue->measurements.rsrp[gNB_id] = 0; - if (abstraction_flag == 0) { + if (abstraction_flag == 0) { - for (l=0; l<1; l++) { + LOG_D(PHY, "In %s: [UE %d] slot %d l_sss %d ssb_offset %d\n", __FUNCTION__, ue->Mod_id, slot, l_sss, ssb_offset); - LOG_D(PHY,"[UE %d] slot %d Doing ue_rrc_measurements rsrp/rssi (Nid_cell %d, nushift %d, eNB_offset %d, l %d)\n",ue->Mod_id,slot,Nid_cell,nushift, - eNB_offset,l); + nb_re = 0; - for (aarx=0; aarxframe_parms.nb_antennas_rx; aarx++) { - rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+ssb_offset+nushift)]; - off = 0; + for (aarx = 0; aarx < ue->frame_parms.nb_antennas_rx; aarx++) { - if (l==0) { - for (rb=0; rbcommon_vars.common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aarx][(l_sss*ue->frame_parms.ofdm_symbol_size) + ssb_offset]; - ue->measurements.rsrp[eNB_offset] += (((int32_t)(rxF[off])*rxF[off])+((int32_t)(rxF[off+1])*rxF[off+1])); - //printf("rb %d, off %d : %d\n",rb,off,((((int32_t)rxF[off])*rxF[off])+((int32_t)(rxF[off+1])*rxF[off+1]))); + for(int k = k_start; k < k_end; k++){ + + #ifdef DEBUG_MEAS_UE + LOG_I(PHY, "In %s rxF_sss %d %d\n", __FUNCTION__, rxF_sss[k*2], rxF_sss[k*2 + 1]); + #endif + + ue->measurements.rsrp[gNB_id] += (((int32_t)rxF_sss[k*2]*rxF_sss[k*2]) + ((int32_t)rxF_sss[k*2 + 1]*rxF_sss[k*2 + 1])); + + nb_re++; - off = (off+4) % ue->frame_parms.ofdm_symbol_size; - } - } - } } - - ue->measurements.rsrp[eNB_offset]/=nb_rb; - - } else { - - ue->measurements.rsrp[eNB_offset] = -93 ; } + ue->measurements.rsrp[gNB_id] /= nb_re; - if (eNB_offset == 0) + } else { - LOG_D(PHY,"[UE %d] slot %d RSRP Measurements (idx %d, Cell id %d) => rsrp: %3.1f dBm/RE (%d)\n", - ue->Mod_id, - slot,eNB_offset, - (eNB_offset>0) ? ue->measurements.adj_cell_id[eNB_offset-1] : ue->frame_parms.Nid_cell, - 10*log10(ue->measurements.rsrp[eNB_offset])-ue->rx_total_gain_dB, - ue->measurements.rsrp[eNB_offset]); + ue->measurements.rsrp[gNB_id] = -93; + + } + + ue->measurements.rsrp_filtered[gNB_id] = ue->measurements.rsrp[gNB_id]; + + LOG_D(PHY, "In %s: [UE %d] slot %d SS-RSRP: %3.1f dBm/RE (%d W)\n", + __FUNCTION__, + ue->Mod_id, + slot, + 10*log10(ue->measurements.rsrp[gNB_id]) + 30 - ue->rx_total_gain_dB, + ue->measurements.rsrp[gNB_id]); } diff --git a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c index a63d8d60e7..bfec64820b 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c @@ -81,12 +81,14 @@ void nr_pdcch_demapping_deinterleaving(uint32_t *llr, uint32_t *z, - NR_DL_FRAME_PARMS *frame_parms, uint8_t coreset_time_dur, uint32_t coreset_nbr_rb, uint8_t reg_bundle_size_L, uint8_t coreset_interleaver_size_R, - uint8_t n_shift) { + uint8_t n_shift, + uint8_t number_of_candidates, + uint16_t *CCE, + uint8_t *L) { /* * This function will do demapping and deinterleaving from llr containing demodulated symbols * Demapping will regroup in REG and bundles @@ -122,35 +124,61 @@ void nr_pdcch_demapping_deinterleaving(uint32_t *llr, | REG 0 (bundle 0) bundle 0 bundle 0 */ - int c=0,r=0; - uint16_t bundle_j=0, f_bundle_j=0,f_reg=0; - uint32_t coreset_C=0; + int c = 0, r = 0; + uint16_t bundle_j = 0, f_bundle_j = 0, f_reg = 0; + uint32_t coreset_C = 0; uint16_t index_z, index_llr; int coreset_interleaved = 0; - if (reg_bundle_size_L!=0) { // interleaving will be done only if reg_bundle_size_L != 0 - coreset_interleaved=1; - coreset_C = (uint32_t)((coreset_nbr_rb * coreset_time_dur)/ (coreset_interleaver_size_R*reg_bundle_size_L)); + if (reg_bundle_size_L != 0) { // interleaving will be done only if reg_bundle_size_L != 0 + coreset_interleaved = 1; + coreset_C = (uint32_t) ((coreset_nbr_rb * coreset_time_dur) / (coreset_interleaver_size_R * reg_bundle_size_L)); } else { - reg_bundle_size_L=6; + reg_bundle_size_L = 6; } - for(int reg=0; reg<((coreset_nbr_rb*coreset_time_dur)); reg++) { - if ((reg%reg_bundle_size_L) == 0) { + + int f_bundle_j_list[NR_MAX_PDCCH_AGG_LEVEL] = {}; + + for (int reg = 0; reg < ((coreset_nbr_rb * coreset_time_dur)); reg++) { + if ((reg % reg_bundle_size_L) == 0) { if (r == coreset_interleaver_size_R) { - r=0; + r = 0; c++; } - bundle_j = (c*coreset_interleaver_size_R)+r; - f_bundle_j = ((r*coreset_C)+c+n_shift)%((coreset_nbr_rb*coreset_time_dur)/reg_bundle_size_L); + bundle_j = (c * coreset_interleaver_size_R) + r; + f_bundle_j = ((r * coreset_C) + c + n_shift) % ((coreset_nbr_rb * coreset_time_dur) / reg_bundle_size_L); - if (coreset_interleaved==0) f_bundle_j=bundle_j; + if (coreset_interleaved == 0) f_bundle_j = bundle_j; + + f_bundle_j_list[reg / 6] = f_bundle_j; - LOG_DNL("[r=%d,c=%d] bundle_j(%d) interleaved at f_bundle_j(%d)\n",r,c,bundle_j,f_bundle_j); } + if ((reg % reg_bundle_size_L) == 0) r++; + } - f_reg = (f_bundle_j*reg_bundle_size_L)+(reg%reg_bundle_size_L); + + // Get cce_list indices by reg_idx in ascending order + int f_bundle_j_list_id = 0; + int f_bundle_j_list_ord[NR_MAX_PDCCH_AGG_LEVEL] = {}; + for (int c_id = 0; c_id < number_of_candidates; c_id++ ) { + f_bundle_j_list_id = CCE[c_id]; + for (int p = 0; p < NR_MAX_PDCCH_AGG_LEVEL; p++) { + for (int p2 = CCE[c_id]; p2 < CCE[c_id] + L[c_id]; p2++) { + if (f_bundle_j_list[p2] == p) { + f_bundle_j_list_ord[f_bundle_j_list_id] = p; + f_bundle_j_list_id++; + break; + } + } + } + } + + + for(int reg=0; reg<((coreset_nbr_rb*coreset_time_dur)); reg++) { + + f_reg = (f_bundle_j_list_ord[reg/6]*reg_bundle_size_L)+(reg%reg_bundle_size_L); index_z = 9*reg; index_llr = 9*((uint16_t)floor(f_reg/coreset_time_dur)+((f_reg%coreset_time_dur)*(coreset_nbr_rb))); @@ -386,14 +414,14 @@ void nr_pdcch_extract_rbs_single(int32_t **rxdataF, rxF=NULL; // first we set initial conditions for pointer to rxdataF depending on the situation of the first RB within the CORESET (c_rb = n_BWP_start) - if ((c_rb < (frame_parms->N_RB_DL >> 1)) && ((frame_parms->N_RB_DL & 1) == 0)) { + if (((c_rb + n_BWP_start) < (frame_parms->N_RB_DL >> 1)) && ((frame_parms->N_RB_DL & 1) == 0)) { //if RB to be treated is lower than middle system bandwidth then rxdataF pointed at (offset + c_br + symbol * ofdm_symbol_size): even case rxF = &rxdataF[aarx][(frame_parms->first_carrier_offset + 12 * c_rb + (symbol * (frame_parms->ofdm_symbol_size)))+n_BWP_start*12]; LOG_DDD("in even case c_rb (%d) is lower than half N_RB_DL -> rxF = &rxdataF[aarx = (%d)][(frame_parms->first_carrier_offset + 12 * c_rb + (symbol * (frame_parms->ofdm_symbol_size))) = (%d)]\n", c_rb,aarx,(frame_parms->first_carrier_offset + 12 * c_rb + (symbol * (frame_parms->ofdm_symbol_size)))); } - if ((c_rb >= (frame_parms->N_RB_DL >> 1)) && ((frame_parms->N_RB_DL & 1) == 0)) { + if (((c_rb + n_BWP_start) >= (frame_parms->N_RB_DL >> 1)) && ((frame_parms->N_RB_DL & 1) == 0)) { // number of RBs is even and c_rb is higher than half system bandwidth (we don't skip DC) // if these conditions are true the pointer has to be situated at the 1st part of the rxdataF rxF = &rxdataF[aarx][(12*(c_rb - (frame_parms->N_RB_DL>>1)) + (symbol * (frame_parms->ofdm_symbol_size)))+n_BWP_start*12]; // we point at the 1st part of the rxdataF in symbol @@ -406,7 +434,7 @@ void nr_pdcch_extract_rbs_single(int32_t **rxdataF, //#endif } - if ((c_rb < (frame_parms->N_RB_DL >> 1)) && ((frame_parms->N_RB_DL & 1) != 0)) { + if (((c_rb + n_BWP_start) < (frame_parms->N_RB_DL >> 1)) && ((frame_parms->N_RB_DL & 1) != 0)) { //if RB to be treated is lower than middle system bandwidth then rxdataF pointed at (offset + c_br + symbol * ofdm_symbol_size): odd case rxF = &rxdataF[aarx][(frame_parms->first_carrier_offset + 12 * c_rb + (symbol * (frame_parms->ofdm_symbol_size)))+n_BWP_start*12]; #ifdef NR_PDCCH_DCI_DEBUG @@ -415,7 +443,7 @@ void nr_pdcch_extract_rbs_single(int32_t **rxdataF, #endif } - if ((c_rb > (frame_parms->N_RB_DL >> 1)) && ((frame_parms->N_RB_DL & 1) != 0)) { + if (((c_rb + n_BWP_start) > (frame_parms->N_RB_DL >> 1)) && ((frame_parms->N_RB_DL & 1) != 0)) { // number of RBs is odd and c_rb is higher than half system bandwidth + 1 // if these conditions are true the pointer has to be situated at the 1st part of the rxdataF just after the first IQ symbols of the RB containing DC rxF = &rxdataF[aarx][(12*(c_rb - (frame_parms->N_RB_DL>>1)) - 6 + (symbol * (frame_parms->ofdm_symbol_size)))+n_BWP_start*12]; // we point at the 1st part of the rxdataF in symbol @@ -425,7 +453,7 @@ void nr_pdcch_extract_rbs_single(int32_t **rxdataF, #endif } - if ((c_rb == (frame_parms->N_RB_DL >> 1)) && ((frame_parms->N_RB_DL & 1) != 0)) { // treatment of RB containing the DC + if (((c_rb + n_BWP_start) == (frame_parms->N_RB_DL >> 1)) && ((frame_parms->N_RB_DL & 1) != 0)) { // treatment of RB containing the DC // if odd number RBs in system bandwidth and first RB to be treated is higher than middle system bandwidth (around DC) // we have to treat the RB in two parts: first part from i=0 to 5, the data is at the end of rxdataF (pointing at the end of the table) rxF = &rxdataF[aarx][(frame_parms->first_carrier_offset + 12 * c_rb + (symbol * (frame_parms->ofdm_symbol_size)))+n_BWP_start*12]; @@ -760,12 +788,14 @@ int32_t nr_rx_pdcch(PHY_VARS_NR_UE *ue, LOG_D(PHY,"we enter nr_pdcch_demapping_deinterleaving()\n"); nr_pdcch_demapping_deinterleaving((uint32_t *) pdcch_vars->llr, (uint32_t *) pdcch_vars->e_rx, - frame_parms, rel15->coreset.duration, n_rb, rel15->coreset.RegBundleSize, rel15->coreset.InterleaverSize, - rel15->coreset.ShiftIndex); + rel15->coreset.ShiftIndex, + rel15->number_of_candidates, + rel15->CCE, + rel15->L); /* nr_pdcch_unscrambling(rel15->rnti, frame_parms, @@ -889,7 +919,7 @@ uint8_t nr_dci_decoding_procedure(PHY_VARS_NR_UE *ue, n_rnti = rel15->rnti; if (crc == n_rnti) { - LOG_I(PHY, "(%i.%i) Received dci indication (rnti %x,dci format %d,n_CCE %d,payloadSize %d,payload %llx)\n", + LOG_D(PHY, "(%i.%i) Received dci indication (rnti %x,dci format %d,n_CCE %d,payloadSize %d,payload %llx)\n", proc->frame_rx, proc->nr_slot_rx,n_rnti,rel15->dci_format_options[k],CCEind,dci_length,*(unsigned long long*)dci_estimation); dci_ind->SFN = proc->frame_rx; dci_ind->slot = proc->nr_slot_rx; diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c index 2cb4f97910..19259f5724 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c @@ -203,7 +203,7 @@ NR_UE_DLSCH_t *new_nr_ue_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint32_t Nsoft,uint return(dlsch); } - LOG_I(PHY,"new_ue_dlsch with size %zu: exit_flag = %u\n",sizeof(NR_DL_UE_HARQ_t), exit_flag); + LOG_D(PHY,"new_ue_dlsch with size %zu: exit_flag = %u\n",sizeof(NR_DL_UE_HARQ_t), exit_flag); free_nr_ue_dlsch(&dlsch,N_RB_DL); return(NULL); @@ -361,7 +361,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, else Coderate = (float) (harq_process->R) /(float) 2048; - if ((A <=292) || ((A<=3824) && (Coderate <= 0.6667)) || Coderate <= 0.25) + if ((A <=292) || ((A <= NR_MAX_PDSCH_TBS) && (Coderate <= 0.6667)) || Coderate <= 0.25) { p_decParams->BG = 2; kc = 52; @@ -391,8 +391,8 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, if (harq_process->round == 0) { - // This is a new packet, so compute quantities regarding segmentation - if (A > 3824) + // This is a new packet, so compute quantities regarding segmentation + if (A > NR_MAX_PDSCH_TBS) harq_process->B = A+24; else harq_process->B = A+16; @@ -531,7 +531,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, if (harq_process->C == 1){ - if (A > 3824) + if (A > NR_MAX_PDSCH_TBS) crc_type = CRC24_A; else crc_type = CRC16; @@ -577,7 +577,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, // Fixme: correct type is unsigned, but nrLDPC_decoder and all called behind use signed int if (check_crc((uint8_t*)llrProcBuf,length_dec,harq_process->F,crc_type)) { - LOG_I(PHY,"Segment %u CRC OK\n\033[0m",r); + LOG_D(PHY,"Segment %u CRC OK\n\033[0m",r); if (r==0) { for (int i=0;i<10;i++) LOG_D(PHY,"byte %d : %x\n",i,((uint8_t*)llrProcBuf)[i]); } @@ -617,13 +617,13 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, if ((err_flag == 0) && (ret>=(1+dlsch->max_ldpc_iterations))) {// a Code segment is in error so break; - LOG_I(PHY,"AbsSubframe %d.%d CRC failed, segment %d/%d \n",frame%1024,nr_slot_rx,r,harq_process->C-1); + LOG_D(PHY,"AbsSubframe %d.%d CRC failed, segment %d/%d \n",frame%1024,nr_slot_rx,r,harq_process->C-1); err_flag = 1; } } if (err_flag == 1) { - LOG_I(PHY,"[UE %d] DLSCH: Setting NAK for SFN/SF %d/%d (pid %d, status %d, round %d, TBS %d, mcs %d) Kr %d r %d harq_process->round %d\n", + LOG_D(PHY,"[UE %d] DLSCH: Setting NAK for SFN/SF %d/%d (pid %d, status %d, round %d, TBS %d, mcs %d) Kr %d r %d harq_process->round %d\n", phy_vars_ue->Mod_id, frame, nr_slot_rx, harq_pid,harq_process->status, harq_process->round,harq_process->TBS,harq_process->mcs,Kr,r,harq_process->round); harq_process->harq_ack.ack = 0; @@ -639,7 +639,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, if(is_crnti) { - LOG_I(PHY,"[UE %d] DLSCH: Setting NACK for nr_slot_rx %d (pid %d, pid status %d, round %d/Max %d, TBS %d)\n", + LOG_D(PHY,"[UE %d] DLSCH: Setting NACK for nr_slot_rx %d (pid %d, pid status %d, round %d/Max %d, TBS %d)\n", phy_vars_ue->Mod_id,nr_slot_rx,harq_pid,harq_process->status,harq_process->round,dlsch->Mdlharq,harq_process->TBS); } @@ -814,6 +814,9 @@ uint32_t nr_dlsch_decoding_mthread(PHY_VARS_NR_UE *phy_vars_ue, nb_rb = harq_process->nb_rb; harq_process->trials[harq_process->round]++; + // HARQ stats + phy_vars_ue->dl_stats[harq_process->round]++; + uint16_t nb_rb_oh = 0; // it was not computed at UE side even before and set to 0 in nr_compute_tbs harq_process->TBS = nr_compute_tbs(harq_process->Qm,harq_process->R,nb_rb,nb_symb_sch,nb_re_dmrs*length_dmrs, nb_rb_oh, 0, harq_process->Nl); @@ -827,7 +830,7 @@ uint32_t nr_dlsch_decoding_mthread(PHY_VARS_NR_UE *phy_vars_ue, G = harq_process->G; - LOG_I(PHY,"DLSCH Decoding main, harq_pid %d TBS %d G %d, nb_re_dmrs %d, length_dmrs %d mcs %d Nl %d nb_symb_sch %d nb_rb %d\n",harq_pid,A,G, nb_re_dmrs, length_dmrs, harq_process->mcs, harq_process->Nl, nb_symb_sch,nb_rb); + LOG_D(PHY,"DLSCH Decoding main, harq_pid %d TBS %d G %d, nb_re_dmrs %d, length_dmrs %d mcs %d Nl %d nb_symb_sch %d nb_rb %d\n",harq_pid,A,G, nb_re_dmrs, length_dmrs, harq_process->mcs, harq_process->Nl, nb_symb_sch,nb_rb); proc->decoder_main_available = 1; proc->decoder_thread_available = 0; @@ -839,7 +842,7 @@ uint32_t nr_dlsch_decoding_mthread(PHY_VARS_NR_UE *phy_vars_ue, else Coderate = (float) (harq_process->R) /(float) 2048; - if ((A <=292) || ((A<=3824) && (Coderate <= 0.6667)) || Coderate <= 0.25) + if ((A <= 292) || ((A <= NR_MAX_PDSCH_TBS) && (Coderate <= 0.6667)) || Coderate <= 0.25) { p_decParams->BG = 2; kc = 52; @@ -869,7 +872,7 @@ uint32_t nr_dlsch_decoding_mthread(PHY_VARS_NR_UE *phy_vars_ue, if (harq_process->round == 0) { // This is a new packet, so compute quantities regarding segmentation - if (A > 3824) + if (A > NR_MAX_PDSCH_TBS) harq_process->B = A+24; else harq_process->B = A+16; @@ -906,7 +909,7 @@ uint32_t nr_dlsch_decoding_mthread(PHY_VARS_NR_UE *phy_vars_ue, return((1+dlsch->max_ldpc_iterations)); } if (LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD)) - LOG_I(PHY,"Segmentation: C %d, K %d\n",harq_process->C,harq_process->K); + LOG_D(PHY,"Segmentation: C %d, K %d\n",harq_process->C,harq_process->K); notifiedFIFO_elt_t *res_dl; @@ -1056,7 +1059,7 @@ uint32_t nr_dlsch_decoding_mthread(PHY_VARS_NR_UE *phy_vars_ue, memset(harq_process->c[r],0,Kr_bytes); if (harq_process->C == 1){ - if (A > 3824) + if (A > NR_MAX_PDSCH_TBS) crc_type = CRC24_A; else crc_type = CRC16; @@ -1080,7 +1083,7 @@ uint32_t nr_dlsch_decoding_mthread(PHY_VARS_NR_UE *phy_vars_ue, #if UE_TIMING_TRACE start_meas(dlsch_turbo_decoding_stats); #endif - LOG_I(PHY,"mthread AbsSubframe %d.%d Start LDPC segment %d/%d \n",frame%1024,nr_slot_rx,r,harq_process->C-1); + LOG_D(PHY,"mthread AbsSubframe %d.%d Start LDPC segment %d/%d \n",frame%1024,nr_slot_rx,r,harq_process->C-1); /*for (int cnt =0; cnt < (kc-2)*p_decParams->Z; cnt++){ inv_d[cnt] = (1)*harq_process->d[r][cnt]; @@ -1120,7 +1123,7 @@ uint32_t nr_dlsch_decoding_mthread(PHY_VARS_NR_UE *phy_vars_ue, ret = 2; } else { - LOG_I(PHY,"CRC NOK\n"); + LOG_D(PHY,"CRC NOK\n"); ret = 1+dlsch->max_ldpc_iterations; } @@ -1161,7 +1164,7 @@ uint32_t nr_dlsch_decoding_mthread(PHY_VARS_NR_UE *phy_vars_ue, if ((err_flag == 0) && (ret>=(1+dlsch->max_ldpc_iterations))) {// a Code segment is in error so break; - LOG_I(PHY,"AbsSubframe %d.%d CRC failed, segment %d/%d \n",frame%1024,nr_slot_rx,r,harq_process->C-1); + LOG_D(PHY,"AbsSubframe %d.%d CRC failed, segment %d/%d \n",frame%1024,nr_slot_rx,r,harq_process->C-1); err_flag = 1; } //} //loop r @@ -1182,7 +1185,7 @@ uint32_t nr_dlsch_decoding_mthread(PHY_VARS_NR_UE *phy_vars_ue, } if(is_crnti) { - LOG_I(PHY,"[UE %d] DLSCH: Setting NACK for nr_slot_rx %d (pid %d, pid status %d, round %d/Max %d, TBS %d)\n", + LOG_D(PHY,"[UE %d] DLSCH: Setting NACK for nr_slot_rx %d (pid %d, pid status %d, round %d/Max %d, TBS %d)\n", phy_vars_ue->Mod_id,nr_slot_rx,harq_pid,harq_process->status,harq_process->round,dlsch->Mlimit,harq_process->TBS); } @@ -1333,7 +1336,7 @@ void nr_dlsch_decoding_process(void *arg) p_nrLDPC_procBuf = harq_process->p_nrLDPC_procBuf[r]; nb_symb_sch = harq_process->nb_symbols; - LOG_I(PHY,"dlsch decoding process frame %d slot %d segment %d r %u nb symb %d \n", frame, proc->nr_slot_rx, proc->num_seg, r, harq_process->nb_symbols); + LOG_D(PHY,"dlsch decoding process frame %d slot %d segment %d r %u nb symb %d \n", frame, proc->nr_slot_rx, proc->num_seg, r, harq_process->nb_symbols); nb_rb = harq_process->nb_rb; @@ -1352,14 +1355,14 @@ void nr_dlsch_decoding_process(void *arg) harq_process->G = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, harq_process->Qm,harq_process->Nl); G = harq_process->G; - LOG_I(PHY,"DLSCH Decoding process, harq_pid %d TBS %d G %d mcs %d Nl %d nb_symb_sch %d nb_rb %d\n",harq_pid,A,G, harq_process->mcs, harq_process->Nl, nb_symb_sch,nb_rb); + LOG_D(PHY,"DLSCH Decoding process, harq_pid %d TBS %d G %d mcs %d Nl %d nb_symb_sch %d nb_rb %d\n",harq_pid,A,G, harq_process->mcs, harq_process->Nl, nb_symb_sch,nb_rb); if ((harq_process->R)<1024) Coderate = (float) (harq_process->R) /(float) 1024; else Coderate = (float) (harq_process->R) /(float) 2048; - if ((A <=292) || ((A<=3824) && (Coderate <= 0.6667)) || Coderate <= 0.25) + if ((A <= 292) || ((A <= NR_MAX_PDSCH_TBS) && (Coderate <= 0.6667)) || Coderate <= 0.25) { p_decParams->BG = 2; kc = 52; @@ -1390,7 +1393,7 @@ void nr_dlsch_decoding_process(void *arg) harq_process->round =0; // if (harq_process->round == 0) { // This is a new packet, so compute quantities regarding segmentation - if (A > 3824) + if (A > NR_MAX_PDSCH_TBS) harq_process->B = A+24; else harq_process->B = A+16; @@ -1514,7 +1517,7 @@ void nr_dlsch_decoding_process(void *arg) memset(harq_process->c[r],0,Kr_bytes); if (harq_process->C == 1){ - if (A > 3824) + if (A > NR_MAX_PDSCH_TBS) crc_type = CRC24_A; else crc_type = CRC16; @@ -1572,12 +1575,12 @@ void nr_dlsch_decoding_process(void *arg) ret = 2; } else { - LOG_I(PHY,"Segment %u CRC NOK\n",r); + LOG_D(PHY,"Segment %u CRC NOK\n",r); ret = 1+dlsch->max_ldpc_iterations; } if (no_iteration_ldpc > 10) - LOG_I(PHY,"Error number of iteration LPDC %d\n", no_iteration_ldpc); + LOG_D(PHY,"Error number of iteration LPDC %d\n", no_iteration_ldpc); for (int m=0; m < Kr>>3; m ++) diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c index 316eb53029..9a31257244 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c @@ -112,7 +112,7 @@ static int nr_dlsch_llr(NR_UE_PDSCH **pdsch_vars, NR_DL_UE_HARQ_t *dlsch1_harq, RX_type_t rx_type, unsigned char harq_pid, - unsigned char eNB_id, + unsigned char gNB_id, unsigned char eNB_id_i, unsigned char first_symbol_flag, unsigned char symbol, @@ -128,8 +128,8 @@ static int nr_dlsch_llr(NR_UE_PDSCH **pdsch_vars, int nr_rx_pdsch(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, PDSCH_t type, - unsigned char eNB_id, - unsigned char eNB_id_i, //if this == ue->n_connected_eNB, we assume MU interference + unsigned char gNB_id, + unsigned char eNB_id_i, //if this == ue->n_connected_gNB, we assume MU interference uint32_t frame, uint8_t nr_slot_rx, unsigned char symbol, @@ -184,24 +184,24 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, switch (type) { case SI_PDSCH: pdsch_vars = ue->pdsch_vars[proc->thread_id]; - dlsch = &ue->dlsch_SI[eNB_id]; + dlsch = &ue->dlsch_SI[gNB_id]; dlsch0_harq = dlsch[0]->harq_processes[harq_pid]; break; case RA_PDSCH: pdsch_vars = ue->pdsch_vars[proc->thread_id]; - dlsch = &ue->dlsch_ra[eNB_id]; + dlsch = &ue->dlsch_ra[gNB_id]; dlsch0_harq = dlsch[0]->harq_processes[harq_pid]; break; case PDSCH: pdsch_vars = ue->pdsch_vars[proc->thread_id]; - dlsch = ue->dlsch[proc->thread_id][eNB_id]; + dlsch = ue->dlsch[proc->thread_id][gNB_id]; dlsch0_harq = dlsch[0]->harq_processes[harq_pid]; dlsch1_harq = dlsch[1]->harq_processes[harq_pid]; - beamforming_mode = ue->transmission_mode[eNB_id] < 7 ? 0 :ue->transmission_mode[eNB_id]; + beamforming_mode = ue->transmission_mode[gNB_id] < 7 ? 0 :ue->transmission_mode[gNB_id]; break; default: @@ -285,8 +285,8 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, round = dlsch0_harq->round; //printf("round = %d\n", round); - if (eNB_id > 2) { - LOG_W(PHY,"dlsch_demodulation.c: Illegal eNB_id %d\n",eNB_id); + if (gNB_id > 2) { + LOG_W(PHY, "In %s: Illegal gNB_id %d\n", __FUNCTION__, gNB_id); return(-1); } @@ -341,11 +341,11 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, start_meas(&ue->generic_stat_bis[proc->thread_id][slot]); #endif nb_rb = nr_dlsch_extract_rbs_dual(common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF, - pdsch_vars[eNB_id]->dl_ch_estimates, - pdsch_vars[eNB_id]->rxdataF_ext, - pdsch_vars[eNB_id]->dl_ch_estimates_ext, + pdsch_vars[gNB_id]->dl_ch_estimates, + pdsch_vars[gNB_id]->rxdataF_ext, + pdsch_vars[gNB_id]->dl_ch_estimates_ext, dlsch0_harq->pmi_alloc, - pdsch_vars[eNB_id]->pmi_ext, + pdsch_vars[gNB_id]->pmi_ext, symbol, pilots, start_rb, @@ -357,14 +357,14 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, #ifdef DEBUG_DLSCH_MOD printf("dlsch: using pmi %lx, pmi_ext ",pmi2hex_2Ar1(dlsch0_harq->pmi_alloc)); for (rb=0;rbpmi_ext[rb]); + printf("%d",pdsch_vars[gNB_id]->pmi_ext[rb]); printf("\n"); #endif if (rx_type >= rx_IC_single_stream) { - if (eNB_id_in_connected_eNB) // we are in TM5 + if (eNB_id_i < ue->n_connected_gNB) // we are in TM5 nb_rb = nr_dlsch_extract_rbs_dual(common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF, - pdsch_vars[eNB_id]->dl_ch_estimates, + pdsch_vars[gNB_id]->dl_ch_estimates, pdsch_vars[eNB_id_i]->rxdataF_ext, pdsch_vars[eNB_id_i]->dl_ch_estimates_ext, dlsch0_harq->pmi_alloc, @@ -379,7 +379,7 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, dlsch0_harq->mimo_mode); else nb_rb = nr_dlsch_extract_rbs_dual(common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF, - pdsch_vars[eNB_id]->dl_ch_estimates, + pdsch_vars[gNB_id]->dl_ch_estimates, pdsch_vars[eNB_id_i]->rxdataF_ext, pdsch_vars[eNB_id_i]->dl_ch_estimates_ext, dlsch0_harq->pmi_alloc, @@ -396,11 +396,11 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, } else if (beamforming_mode==0) { //else if nb_antennas_ports_gNB==1 && beamforming_mode == 0 //printf("start nr dlsch extract nr_slot_rx %d thread id %d \n", nr_slot_rx, proc->thread_id); nb_rb = nr_dlsch_extract_rbs_single(common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF, - pdsch_vars[eNB_id]->dl_ch_estimates, - pdsch_vars[eNB_id]->rxdataF_ext, - pdsch_vars[eNB_id]->dl_ch_estimates_ext, + pdsch_vars[gNB_id]->dl_ch_estimates, + pdsch_vars[gNB_id]->rxdataF_ext, + pdsch_vars[gNB_id]->dl_ch_estimates_ext, dlsch0_harq->pmi_alloc, - pdsch_vars[eNB_id]->pmi_ext, + pdsch_vars[gNB_id]->pmi_ext, symbol, pilots, config_type, @@ -415,7 +415,7 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, LOG_W(PHY,"dlsch_demodulation: beamforming mode not supported yet.\n"); }*/ - //printf("nb_rb = %d, eNB_id %d\n",nb_rb,eNB_id); + //printf("nb_rb = %d, gNB_id %d\n",nb_rb,gNB_id); if (nb_rb==0) { LOG_D(PHY,"dlsch_demodulation.c: nb_rb=0\n"); return(-1); @@ -440,7 +440,7 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, n_tx = frame_parms->nb_antenna_ports_gNB; n_rx = frame_parms->nb_antennas_rx; - nr_dlsch_scale_channel(pdsch_vars[eNB_id]->dl_ch_estimates_ext, + nr_dlsch_scale_channel(pdsch_vars[gNB_id]->dl_ch_estimates_ext, frame_parms, dlsch, symbol, @@ -463,7 +463,7 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, if (first_symbol_flag==1) { if (beamforming_mode==0){ if (dlsch0_harq->mimo_modedl_ch_estimates_ext, + nr_dlsch_channel_level(pdsch_vars[gNB_id]->dl_ch_estimates_ext, frame_parms, avg, symbol, @@ -474,11 +474,11 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, for (aarx=0;aarxnb_antennas_rx;aarx++) avgs = cmax(avgs,avg[(aatx<<1)+aarx]); - pdsch_vars[eNB_id]->log2_maxh = (log2_approx(avgs)/2)+3; + pdsch_vars[gNB_id]->log2_maxh = (log2_approx(avgs)/2)+3; } else if (dlsch0_harq->mimo_mode == NR_DUALSTREAM) { - nr_dlsch_channel_level_median(pdsch_vars[eNB_id]->dl_ch_estimates_ext, + nr_dlsch_channel_level_median(pdsch_vars[gNB_id]->dl_ch_estimates_ext, median, n_tx, n_rx, @@ -493,16 +493,19 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, } } - pdsch_vars[eNB_id]->log2_maxh = (log2_approx(avgs)/2) + 1; // this might need to be tuned + pdsch_vars[gNB_id]->log2_maxh = (log2_approx(avgs)/2) + 1; // this might need to be tuned } } //#ifdef UE_DEBUG_TRACE LOG_D(PHY,"[DLSCH] AbsSubframe %d.%d log2_maxh = %d [log2_maxh0 %d log2_maxh1 %d] (%d,%d)\n", - frame%1024,nr_slot_rx, pdsch_vars[eNB_id]->log2_maxh, - pdsch_vars[eNB_id]->log2_maxh0, - pdsch_vars[eNB_id]->log2_maxh1, - avg[0],avgs); + frame%1024, + nr_slot_rx, + pdsch_vars[gNB_id]->log2_maxh, + pdsch_vars[gNB_id]->log2_maxh0, + pdsch_vars[gNB_id]->log2_maxh1, + avg[0], + avgs); //LOG_D(PHY,"[DLSCH] mimo_mode = %d\n", dlsch0_harq->mimo_mode); //#endif @@ -522,7 +525,7 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, #if T_TRACER if (type == PDSCH) { - T(T_UE_PHY_PDSCH_ENERGY, T_INT(eNB_id), T_INT(0), T_INT(frame%1024), T_INT(nr_slot_rx), + T(T_UE_PHY_PDSCH_ENERGY, T_INT(gNB_id), T_INT(0), T_INT(frame%1024), T_INT(nr_slot_rx), T_INT(avg[0]), T_INT(avg[1]), T_INT(avg[2]), T_INT(avg[3])); } #endif @@ -542,27 +545,27 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, #endif // Now channel compensation if (dlsch0_harq->mimo_moderxdataF_ext, - pdsch_vars[eNB_id]->dl_ch_estimates_ext, - pdsch_vars[eNB_id]->dl_ch_mag0, - pdsch_vars[eNB_id]->dl_ch_magb0, - pdsch_vars[eNB_id]->dl_ch_magr0, - pdsch_vars[eNB_id]->rxdataF_comp0, - (aatx>1) ? pdsch_vars[eNB_id]->rho : NULL, + nr_dlsch_channel_compensation(pdsch_vars[gNB_id]->rxdataF_ext, + pdsch_vars[gNB_id]->dl_ch_estimates_ext, + pdsch_vars[gNB_id]->dl_ch_mag0, + pdsch_vars[gNB_id]->dl_ch_magb0, + pdsch_vars[gNB_id]->dl_ch_magr0, + pdsch_vars[gNB_id]->rxdataF_comp0, + (aatx>1) ? pdsch_vars[gNB_id]->rho : NULL, frame_parms, symbol, pilots, first_symbol_flag, dlsch0_harq->Qm, nb_rb, - pdsch_vars[eNB_id]->log2_maxh, + pdsch_vars[gNB_id]->log2_maxh, measurements); // log2_maxh+I0_shift /*if (symbol == 5) { - write_output("rxF_comp_d.m","rxF_c_d",&pdsch_vars[eNB_id]->rxdataF_comp0[0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1); + write_output("rxF_comp_d.m","rxF_c_d",&pdsch_vars[gNB_id]->rxdataF_comp0[0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1); } */ /*if ((rx_type==rx_IC_single_stream) && - (eNB_id_in_connected_eNB)) { + (eNB_id_in_connected_gNB)) { nr_dlsch_channel_compensation(pdsch_vars[eNB_id_i]->rxdataF_ext, pdsch_vars[eNB_id_i]->dl_ch_estimates_ext, pdsch_vars[eNB_id_i]->dl_ch_mag0, @@ -574,11 +577,11 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, first_symbol_flag, i_mod, nb_rb, - pdsch_vars[eNB_id]->log2_maxh, + pdsch_vars[gNB_id]->log2_maxh, measurements); // log2_maxh+I0_shift #ifdef DEBUG_PHY if (symbol == 5) { - write_output("rxF_comp_d.m","rxF_c_d",&pdsch_vars[eNB_id]->rxdataF_comp0[0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1); + write_output("rxF_comp_d.m","rxF_c_d",&pdsch_vars[gNB_id]->rxdataF_comp0[0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1); write_output("rxF_comp_i.m","rxF_c_i",&pdsch_vars[eNB_id_i]->rxdataF_comp0[0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1); } #endif @@ -586,57 +589,57 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, dlsch_dual_stream_correlation(frame_parms, symbol, nb_rb, - pdsch_vars[eNB_id]->dl_ch_estimates_ext, + pdsch_vars[gNB_id]->dl_ch_estimates_ext, pdsch_vars[eNB_id_i]->dl_ch_estimates_ext, - pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], - pdsch_vars[eNB_id]->log2_maxh); + pdsch_vars[gNB_id]->dl_ch_rho_ext[harq_pid][round], + pdsch_vars[gNB_id]->log2_maxh); }*/ } else if (dlsch0_harq->mimo_mode == NR_DUALSTREAM){ - nr_dlsch_channel_compensation_core(pdsch_vars[eNB_id]->rxdataF_ext, - pdsch_vars[eNB_id]->dl_ch_estimates_ext, - pdsch_vars[eNB_id]->dl_ch_mag0, - pdsch_vars[eNB_id]->dl_ch_magb0, - pdsch_vars[eNB_id]->rxdataF_comp0, //rxdataF_comp - NULL, - n_tx, - n_rx, - dlsch0_harq->Qm, - pdsch_vars[eNB_id]->log2_maxh, - 2*len, // subcarriers Re Im - 0); // we start from the beginning of the vector + nr_dlsch_channel_compensation_core(pdsch_vars[gNB_id]->rxdataF_ext, + pdsch_vars[gNB_id]->dl_ch_estimates_ext, + pdsch_vars[gNB_id]->dl_ch_mag0, + pdsch_vars[gNB_id]->dl_ch_magb0, + pdsch_vars[gNB_id]->rxdataF_comp0, //rxdataF_comp + NULL, + n_tx, + n_rx, + dlsch0_harq->Qm, + pdsch_vars[gNB_id]->log2_maxh, + 2*len, // subcarriers Re Im + 0); // we start from the beginning of the vector /* if (symbol == 5) { - write_output("rxF_comp_d00.m","rxF_c_d00",&pdsch_vars[eNB_id]->rxdataF_comp0[0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1);// should be QAM - write_output("rxF_comp_d01.m","rxF_c_d01",&pdsch_vars[eNB_id]->rxdataF_comp0[1][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1);//should be almost 0 - write_output("rxF_comp_d10.m","rxF_c_d10",&pdsch_vars[eNB_id]->rxdataF_comp1[harq_pid][round][0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1);//should be almost 0 - write_output("rxF_comp_d11.m","rxF_c_d11",&pdsch_vars[eNB_id]->rxdataF_comp1[harq_pid][round][1][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1);//should be QAM + write_output("rxF_comp_d00.m","rxF_c_d00",&pdsch_vars[gNB_id]->rxdataF_comp0[0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1);// should be QAM + write_output("rxF_comp_d01.m","rxF_c_d01",&pdsch_vars[gNB_id]->rxdataF_comp0[1][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1);//should be almost 0 + write_output("rxF_comp_d10.m","rxF_c_d10",&pdsch_vars[gNB_id]->rxdataF_comp1[harq_pid][round][0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1);//should be almost 0 + write_output("rxF_comp_d11.m","rxF_c_d11",&pdsch_vars[gNB_id]->rxdataF_comp1[harq_pid][round][1][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1);//should be QAM } */ // compute correlation between signal and interference channels (rho12 and rho21) - nr_dlsch_dual_stream_correlation_core(pdsch_vars[eNB_id]->dl_ch_estimates_ext, - &(pdsch_vars[eNB_id]->dl_ch_estimates_ext[2]), - pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], - n_tx, - n_rx, - pdsch_vars[eNB_id]->log2_maxh, - 2*len, - 0); - //printf("rho stream1 =%d\n", &pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round] ); - nr_dlsch_dual_stream_correlation_core(&(pdsch_vars[eNB_id]->dl_ch_estimates_ext[2]), - pdsch_vars[eNB_id]->dl_ch_estimates_ext, - pdsch_vars[eNB_id]->dl_ch_rho2_ext, - n_tx, - n_rx, - pdsch_vars[eNB_id]->log2_maxh, - 2*len, - 0); - // printf("rho stream2 =%d\n",&pdsch_vars[eNB_id]->dl_ch_rho2_ext ); - //printf("TM3 log2_maxh : %d\n",pdsch_vars[eNB_id]->log2_maxh); + nr_dlsch_dual_stream_correlation_core(pdsch_vars[gNB_id]->dl_ch_estimates_ext, + &(pdsch_vars[gNB_id]->dl_ch_estimates_ext[2]), + pdsch_vars[gNB_id]->dl_ch_rho_ext[harq_pid][round], + n_tx, + n_rx, + pdsch_vars[gNB_id]->log2_maxh, + 2*len, + 0); + //printf("rho stream1 =%d\n", &pdsch_vars[gNB_id]->dl_ch_rho_ext[harq_pid][round] ); + nr_dlsch_dual_stream_correlation_core(&(pdsch_vars[gNB_id]->dl_ch_estimates_ext[2]), + pdsch_vars[gNB_id]->dl_ch_estimates_ext, + pdsch_vars[gNB_id]->dl_ch_rho2_ext, + n_tx, + n_rx, + pdsch_vars[gNB_id]->log2_maxh, + 2*len, + 0); + // printf("rho stream2 =%d\n",&pdsch_vars[gNB_id]->dl_ch_rho2_ext ); + //printf("TM3 log2_maxh : %d\n",pdsch_vars[gNB_id]->log2_maxh); /* if (symbol == 5) { - write_output("rho0_0.m","rho0_0",&pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round][0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1);// should be QAM - write_output("rho2_0.m","rho2_0",&pdsch_vars[eNB_id]->dl_ch_rho2_ext[0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1);//should be almost 0 - write_output("rho0_1.m.m","rho0_1",&pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round][1][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1);//should be almost 0 - write_output("rho2_1.m","rho2_1",&pdsch_vars[eNB_id]->dl_ch_rho2_ext[1][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1);//should be QAM + write_output("rho0_0.m","rho0_0",&pdsch_vars[gNB_id]->dl_ch_rho_ext[harq_pid][round][0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1);// should be QAM + write_output("rho2_0.m","rho2_0",&pdsch_vars[gNB_id]->dl_ch_rho2_ext[0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1);//should be almost 0 + write_output("rho0_1.m.m","rho0_1",&pdsch_vars[gNB_id]->dl_ch_rho_ext[harq_pid][round][1][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1);//should be almost 0 + write_output("rho2_1.m","rho2_1",&pdsch_vars[gNB_id]->dl_ch_rho2_ext[1][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1);//should be QAM } */ } @@ -644,9 +647,9 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, #if UE_TIMING_TRACE stop_meas(&ue->generic_stat_bis[proc->thread_id][slot]); #if DISABLE_LOG_X - printf("[AbsSFN %u.%d] Slot%d Symbol %d log2_maxh %d channel_level %d: Channel Comp %5.2f \n",frame,nr_slot_rx,slot,symbol,pdsch_vars[eNB_id]->log2_maxh,proc->channel_level,ue->generic_stat_bis[proc->thread_id][slot].p_time/(cpuf*1000.0)); + printf("[AbsSFN %u.%d] Slot%d Symbol %d log2_maxh %d channel_level %d: Channel Comp %5.2f \n", frame, nr_slot_rx, slot, symbol, pdsch_vars[gNB_id]->log2_maxh, proc->channel_level, ue->generic_stat_bis[proc->thread_id][slot].p_time/(cpuf*1000.0)); #else - LOG_I(PHY, "[AbsSFN %u.%d] Slot%d Symbol %d log2_maxh %d channel_level %d: Channel Comp %5.2f \n",frame,nr_slot_rx,slot,symbol,pdsch_vars[eNB_id]->log2_maxh,proc->channel_level,ue->generic_stat_bis[proc->thread_id][slot].p_time/(cpuf*1000.0)); + LOG_I(PHY, "[AbsSFN %u.%d] Slot%d Symbol %d log2_maxh %d channel_level %d: Channel Comp %5.2f \n", frame, nr_slot_rx, slot, symbol, pdsch_vars[gNB_id]->log2_maxh, proc->channel_level, ue->generic_stat_bis[proc->thread_id][slot].p_time/(cpuf*1000.0)); #endif #endif // MRC @@ -656,29 +659,29 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, if (frame_parms->nb_antennas_rx > 1) { if (dlsch0_harq->mimo_mode == NR_DUALSTREAM){ - nr_dlsch_detection_mrc_core(pdsch_vars[eNB_id]->rxdataF_comp0, - NULL, - pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], - pdsch_vars[eNB_id]->dl_ch_rho2_ext, - pdsch_vars[eNB_id]->dl_ch_mag0, - pdsch_vars[eNB_id]->dl_ch_magb0, - NULL, - NULL, - n_tx, - n_rx, - 2*len, - 0); + nr_dlsch_detection_mrc_core(pdsch_vars[gNB_id]->rxdataF_comp0, + NULL, + pdsch_vars[gNB_id]->dl_ch_rho_ext[harq_pid][round], + pdsch_vars[gNB_id]->dl_ch_rho2_ext, + pdsch_vars[gNB_id]->dl_ch_mag0, + pdsch_vars[gNB_id]->dl_ch_magb0, + NULL, + NULL, + n_tx, + n_rx, + 2*len, + 0); /* if (symbol == 5) { - write_output("rho0_mrc.m","rho0_0",&pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round][0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1);// should be QAM - write_output("rho2_mrc.m","rho2_0",&pdsch_vars[eNB_id]->dl_ch_rho2_ext[0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1);//should be almost 0 + write_output("rho0_mrc.m","rho0_0",&pdsch_vars[gNB_id]->dl_ch_rho_ext[harq_pid][round][0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1);// should be QAM + write_output("rho2_mrc.m","rho2_0",&pdsch_vars[gNB_id]->dl_ch_rho2_ext[0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1);//should be almost 0 } */ } } //printf("start compute LLR\n"); if (dlsch0_harq->mimo_mode == NR_DUALSTREAM) { - rxdataF_comp_ptr = pdsch_vars[eNB_id]->rxdataF_comp1[harq_pid][round]; - dl_ch_mag_ptr = pdsch_vars[eNB_id]->dl_ch_mag1[harq_pid][round]; + rxdataF_comp_ptr = pdsch_vars[gNB_id]->rxdataF_comp1[harq_pid][round]; + dl_ch_mag_ptr = pdsch_vars[gNB_id]->dl_ch_mag1[harq_pid][round]; } else { rxdataF_comp_ptr = pdsch_vars[eNB_id_i]->rxdataF_comp0; @@ -700,7 +703,7 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, start_meas(&ue->generic_stat_bis[proc->thread_id][slot]); #endif /* Store the valid DL RE's */ - pdsch_vars[eNB_id]->dl_valid_re[symbol-1] = len; + pdsch_vars[gNB_id]->dl_valid_re[symbol-1] = len; if(dlsch0_harq->status == ACTIVE) { startSymbIdx = dlsch0_harq->start_symbol; @@ -718,12 +721,15 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, nr_pdsch_ptrs_processing(ue, pdsch_vars, frame_parms, - dlsch0_harq, dlsch1_harq, - eNB_id, nr_slot_rx, - symbol, (nb_rb*12), + dlsch0_harq, + dlsch1_harq, + gNB_id, + nr_slot_rx, + symbol, + (nb_rb*12), harq_pid, dlsch[0]->rnti,rx_type); - pdsch_vars[eNB_id]->dl_valid_re[symbol-1] -= pdsch_vars[eNB_id]->ptrs_re_per_slot[0][symbol]; + pdsch_vars[gNB_id]->dl_valid_re[symbol-1] -= pdsch_vars[gNB_id]->ptrs_re_per_slot[0][symbol]; } /* at last symbol in a slot calculate LLR's for whole slot */ @@ -741,11 +747,11 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, rxdataF_comp_ptr, dl_ch_mag_ptr, dlsch0_harq, dlsch1_harq, rx_type, harq_pid, - eNB_id, eNB_id_i, + gNB_id, eNB_id_i, first_symbol_flag, i, nb_rb, round, codeword_TB0, codeword_TB1, - pdsch_vars[eNB_id]->dl_valid_re[i-1], + pdsch_vars[gNB_id]->dl_valid_re[i-1], nr_slot_rx, beamforming_mode); } } @@ -753,11 +759,11 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, //nr_dlsch_deinterleaving(symbol,bundle_L,(int16_t*)pllr_symbol_cw0,(int16_t*)pllr_symbol_cw0_deint, nb_rb_pdsch); if (rx_type==rx_IC_dual_stream) { - nr_dlsch_layer_demapping(pdsch_vars[eNB_id]->llr, + nr_dlsch_layer_demapping(pdsch_vars[gNB_id]->llr, dlsch[0]->harq_processes[harq_pid]->Nl, dlsch[0]->harq_processes[harq_pid]->Qm, dlsch[0]->harq_processes[harq_pid]->G, - pdsch_vars[eNB_id]->layer_llr); + pdsch_vars[gNB_id]->layer_llr); } #if UE_TIMING_TRACE @@ -778,29 +784,28 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, write_output(filename, "rxdataF0", &common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[0][0], NR_SYMBOLS_PER_SLOT*frame_parms->ofdm_symbol_size, 1, 1); snprintf(filename, 40, "dl_ch_estimates0%d_symb_%d_nr_slot_rx_%d.m", aa, symbol, nr_slot_rx); - write_output(filename, "dl_ch_estimates", &pdsch_vars[eNB_id]->dl_ch_estimates[aa][0], NR_SYMBOLS_PER_SLOT*frame_parms->ofdm_symbol_size, 1, 1); + write_output(filename, "dl_ch_estimates", &pdsch_vars[gNB_id]->dl_ch_estimates[aa][0], NR_SYMBOLS_PER_SLOT*frame_parms->ofdm_symbol_size, 1, 1); snprintf(filename, 40, "rxdataF_ext0%d_symb_%d_nr_slot_rx_%d.m", aa, symbol, nr_slot_rx); - write_output(filename, "rxdataF_ext", &pdsch_vars[eNB_id]->rxdataF_ext[aa][0], NR_SYMBOLS_PER_SLOT*frame_parms->N_RB_DL*NR_NB_SC_PER_RB, 1, 1); + write_output(filename, "rxdataF_ext", &pdsch_vars[gNB_id]->rxdataF_ext[aa][0], NR_SYMBOLS_PER_SLOT*frame_parms->N_RB_DL*NR_NB_SC_PER_RB, 1, 1); snprintf(filename, 40, "dl_ch_estimates_ext0%d_symb_%d_nr_slot_rx_%d.m", aa, symbol, nr_slot_rx); - write_output(filename, "dl_ch_estimates_ext00", &pdsch_vars[eNB_id]->dl_ch_estimates_ext[aa][0], NR_SYMBOLS_PER_SLOT*frame_parms->N_RB_DL*NR_NB_SC_PER_RB, 1, 1); + write_output(filename, "dl_ch_estimates_ext00", &pdsch_vars[gNB_id]->dl_ch_estimates_ext[aa][0], NR_SYMBOLS_PER_SLOT*frame_parms->N_RB_DL*NR_NB_SC_PER_RB, 1, 1); snprintf(filename, 40, "rxdataF_comp0%d_symb_%d_nr_slot_rx_%d.m", aa, symbol, nr_slot_rx); - write_output(filename, "rxdataF_comp00", &pdsch_vars[eNB_id]->rxdataF_comp0[aa][0], NR_SYMBOLS_PER_SLOT*frame_parms->N_RB_DL*NR_NB_SC_PER_RB, 1, 1); + write_output(filename, "rxdataF_comp00", &pdsch_vars[gNB_id]->rxdataF_comp0[aa][0], NR_SYMBOLS_PER_SLOT*frame_parms->N_RB_DL*NR_NB_SC_PER_RB, 1, 1); for (int i=0; i < 2; i++){ snprintf(filename, 40, "llr%d_symb_%d_nr_slot_rx_%d.m", i, symbol, nr_slot_rx); - write_output(filename,"llr", &pdsch_vars[eNB_id]->llr[i][0], (NR_SYMBOLS_PER_SLOT*nb_rb*NR_NB_SC_PER_RB*dlsch1_harq->Qm) - 4*(nb_rb*4*dlsch1_harq->Qm), 1, 0); + write_output(filename,"llr", &pdsch_vars[gNB_id]->llr[i][0], (NR_SYMBOLS_PER_SLOT*nb_rb*NR_NB_SC_PER_RB*dlsch1_harq->Qm) - 4*(nb_rb*4*dlsch1_harq->Qm), 1, 0); } #endif #if T_TRACER - T(T_UE_PHY_PDSCH_IQ, T_INT(eNB_id), T_INT(ue->Mod_id), T_INT(frame%1024), + T(T_UE_PHY_PDSCH_IQ, T_INT(gNB_id), T_INT(ue->Mod_id), T_INT(frame%1024), T_INT(nr_slot_rx), T_INT(nb_rb), T_INT(frame_parms->N_RB_UL), T_INT(frame_parms->symbols_per_slot), - T_BUFFER(&pdsch_vars[eNB_id]->rxdataF_comp0[eNB_id][0], - 2 * /* ulsch[UE_id]->harq_processes[harq_pid]->nb_rb */ frame_parms->N_RB_UL *12*frame_parms->symbols_per_slot*2)); + T_BUFFER(&pdsch_vars[gNB_id]->rxdataF_comp0[gNB_id][0], 2 * /* ulsch[UE_id]->harq_processes[harq_pid]->nb_rb */ frame_parms->N_RB_UL *12*frame_parms->symbols_per_slot*2)); #endif return(0); @@ -2321,7 +2326,7 @@ static int nr_dlsch_llr(NR_UE_PDSCH **pdsch_vars, NR_DL_UE_HARQ_t *dlsch1_harq, RX_type_t rx_type, unsigned char harq_pid, - unsigned char eNB_id, + unsigned char gNB_id, unsigned char eNB_id_i, unsigned char first_symbol_flag, unsigned char symbol, @@ -2340,42 +2345,42 @@ static int nr_dlsch_llr(NR_UE_PDSCH **pdsch_vars, int16_t *pllr_symbol_layer1; uint32_t llr_offset_symbol; - if (first_symbol_flag==1) pdsch_vars[eNB_id]->llr_offset[symbol-1] = 0; - llr_offset_symbol = pdsch_vars[eNB_id]->llr_offset[symbol-1]; - //pllr_symbol_cw0_deint = (int8_t*)pdsch_vars[eNB_id]->llr[0]; - //pllr_symbol_cw1_deint = (int8_t*)pdsch_vars[eNB_id]->llr[1]; - pllr_symbol_layer0 = pdsch_vars[eNB_id]->layer_llr[0]; - pllr_symbol_layer1 = pdsch_vars[eNB_id]->layer_llr[1]; + if (first_symbol_flag==1) pdsch_vars[gNB_id]->llr_offset[symbol-1] = 0; + llr_offset_symbol = pdsch_vars[gNB_id]->llr_offset[symbol-1]; + //pllr_symbol_cw0_deint = (int8_t*)pdsch_vars[gNB_id]->llr[0]; + //pllr_symbol_cw1_deint = (int8_t*)pdsch_vars[gNB_id]->llr[1]; + pllr_symbol_layer0 = pdsch_vars[gNB_id]->layer_llr[0]; + pllr_symbol_layer1 = pdsch_vars[gNB_id]->layer_llr[1]; pllr_symbol_layer0 += llr_offset_symbol; pllr_symbol_layer1 += llr_offset_symbol; - pllr_symbol_cw0 = pdsch_vars[eNB_id]->llr[0]; - pllr_symbol_cw1 = pdsch_vars[eNB_id]->llr[1]; + pllr_symbol_cw0 = pdsch_vars[gNB_id]->llr[0]; + pllr_symbol_cw1 = pdsch_vars[gNB_id]->llr[1]; pllr_symbol_cw0 += llr_offset_symbol; pllr_symbol_cw1 += llr_offset_symbol; - pdsch_vars[eNB_id]->llr_offset[symbol] = len*dlsch0_harq->Qm + llr_offset_symbol; + pdsch_vars[gNB_id]->llr_offset[symbol] = len*dlsch0_harq->Qm + llr_offset_symbol; /*LOG_I(PHY,"compute LLRs [symbol %d] NbRB %d Qm %d LLRs-Length %d LLR-Offset %d @LLR Buff %x @LLR Buff(symb) %x\n", symbol, nb_rb,dlsch0_harq->Qm, - pdsch_vars[eNB_id]->llr_length[symbol], - pdsch_vars[eNB_id]->llr_offset[symbol], - (int16_t*)pdsch_vars[eNB_id]->llr[0], + pdsch_vars[gNB_id]->llr_length[symbol], + pdsch_vars[gNB_id]->llr_offset[symbol], + (int16_t*)pdsch_vars[gNB_id]->llr[0], pllr_symbol_cw0);*/ /*printf("compute LLRs [symbol %d] NbRB %d Qm %d LLRs-Length %d LLR-Offset %d @LLR Buff %p @LLR Buff(symb) %p\n", symbol, nb_rb,dlsch0_harq->Qm, - pdsch_vars[eNB_id]->llr_length[symbol], - pdsch_vars[eNB_id]->llr_offset[symbol], - pdsch_vars[eNB_id]->llr[0], + pdsch_vars[gNB_id]->llr_length[symbol], + pdsch_vars[gNB_id]->llr_offset[symbol], + pdsch_vars[gNB_id]->llr[0], pllr_symbol_cw0);*/ switch (dlsch0_harq->Qm) { case 2 : if ((rx_type==rx_standard) || (codeword_TB1 == -1)) { nr_dlsch_qpsk_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, + pdsch_vars[gNB_id]->rxdataF_comp0, pllr_symbol_cw0, symbol, len, @@ -2386,7 +2391,7 @@ static int nr_dlsch_llr(NR_UE_PDSCH **pdsch_vars, } else if (codeword_TB0 == -1){ nr_dlsch_qpsk_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, + pdsch_vars[gNB_id]->rxdataF_comp0, pllr_symbol_cw1, symbol, len, @@ -2397,66 +2402,66 @@ static int nr_dlsch_llr(NR_UE_PDSCH **pdsch_vars, else if (rx_type >= rx_IC_single_stream) { if (dlsch1_harq->Qm == 2) { nr_dlsch_qpsk_qpsk_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, + pdsch_vars[gNB_id]->rxdataF_comp0, rxdataF_comp_ptr, - pdsch_vars[eNB_id]->dl_ch_rho2_ext, - pdsch_vars[eNB_id]->layer_llr[0], + pdsch_vars[gNB_id]->dl_ch_rho2_ext, + pdsch_vars[gNB_id]->layer_llr[0], symbol,len,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,nr_slot_rx,symbol), - pdsch_vars[eNB_id]->llr128); + pdsch_vars[gNB_id]->llr128); if (rx_type==rx_IC_dual_stream) { nr_dlsch_qpsk_qpsk_llr(frame_parms, rxdataF_comp_ptr, - pdsch_vars[eNB_id]->rxdataF_comp0, - pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], - pdsch_vars[eNB_id]->layer_llr[1], + pdsch_vars[gNB_id]->rxdataF_comp0, + pdsch_vars[gNB_id]->dl_ch_rho_ext[harq_pid][round], + pdsch_vars[gNB_id]->layer_llr[1], symbol,len,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,2,nr_slot_rx,symbol), - pdsch_vars[eNB_id]->llr128_2ndstream); + pdsch_vars[gNB_id]->llr128_2ndstream); } } else if (dlsch1_harq->Qm == 4) { nr_dlsch_qpsk_16qam_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, + pdsch_vars[gNB_id]->rxdataF_comp0, rxdataF_comp_ptr,//i dl_ch_mag_ptr,//i - pdsch_vars[eNB_id]->dl_ch_rho2_ext, - pdsch_vars[eNB_id]->layer_llr[0], + pdsch_vars[gNB_id]->dl_ch_rho2_ext, + pdsch_vars[gNB_id]->layer_llr[0], symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,nr_slot_rx,symbol), - pdsch_vars[eNB_id]->llr128); + pdsch_vars[gNB_id]->llr128); if (rx_type==rx_IC_dual_stream) { nr_dlsch_16qam_qpsk_llr(frame_parms, rxdataF_comp_ptr, - pdsch_vars[eNB_id]->rxdataF_comp0,//i + pdsch_vars[gNB_id]->rxdataF_comp0,//i dl_ch_mag_ptr, - pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], - pdsch_vars[eNB_id]->layer_llr[1], + pdsch_vars[gNB_id]->dl_ch_rho_ext[harq_pid][round], + pdsch_vars[gNB_id]->layer_llr[1], symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,4,nr_slot_rx,symbol), - pdsch_vars[eNB_id]->llr128_2ndstream); + pdsch_vars[gNB_id]->llr128_2ndstream); } } else { nr_dlsch_qpsk_64qam_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, + pdsch_vars[gNB_id]->rxdataF_comp0, rxdataF_comp_ptr,//i dl_ch_mag_ptr,//i - pdsch_vars[eNB_id]->dl_ch_rho2_ext, - pdsch_vars[eNB_id]->layer_llr[0], + pdsch_vars[gNB_id]->dl_ch_rho2_ext, + pdsch_vars[gNB_id]->layer_llr[0], symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,nr_slot_rx,symbol), - pdsch_vars[eNB_id]->llr128); + pdsch_vars[gNB_id]->llr128); if (rx_type==rx_IC_dual_stream) { nr_dlsch_64qam_qpsk_llr(frame_parms, rxdataF_comp_ptr, - pdsch_vars[eNB_id]->rxdataF_comp0,//i + pdsch_vars[gNB_id]->rxdataF_comp0,//i dl_ch_mag_ptr, - pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], - pdsch_vars[eNB_id]->layer_llr[1], + pdsch_vars[gNB_id]->dl_ch_rho_ext[harq_pid][round], + pdsch_vars[gNB_id]->layer_llr[1], symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,6,nr_slot_rx,symbol), - pdsch_vars[eNB_id]->llr128_2ndstream); + pdsch_vars[gNB_id]->llr128_2ndstream); } } } @@ -2464,90 +2469,90 @@ static int nr_dlsch_llr(NR_UE_PDSCH **pdsch_vars, case 4 : if ((rx_type==rx_standard ) || (codeword_TB1 == -1)) { nr_dlsch_16qam_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, - pdsch_vars[eNB_id]->llr[0], - pdsch_vars[eNB_id]->dl_ch_mag0, + pdsch_vars[gNB_id]->rxdataF_comp0, + pdsch_vars[gNB_id]->llr[0], + pdsch_vars[gNB_id]->dl_ch_mag0, symbol,len,first_symbol_flag,nb_rb, - pdsch_vars[eNB_id]->llr128, + pdsch_vars[gNB_id]->llr128, beamforming_mode); } else if (codeword_TB0 == -1){ nr_dlsch_16qam_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, - pdsch_vars[eNB_id]->llr[1], - pdsch_vars[eNB_id]->dl_ch_mag0, + pdsch_vars[gNB_id]->rxdataF_comp0, + pdsch_vars[gNB_id]->llr[1], + pdsch_vars[gNB_id]->dl_ch_mag0, symbol,len,first_symbol_flag,nb_rb, - pdsch_vars[eNB_id]->llr128_2ndstream, + pdsch_vars[gNB_id]->llr128_2ndstream, beamforming_mode); } else if (rx_type >= rx_IC_single_stream) { if (dlsch1_harq->Qm == 2) { nr_dlsch_16qam_qpsk_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, + pdsch_vars[gNB_id]->rxdataF_comp0, rxdataF_comp_ptr,//i - pdsch_vars[eNB_id]->dl_ch_mag0, - pdsch_vars[eNB_id]->dl_ch_rho2_ext, - pdsch_vars[eNB_id]->layer_llr[0], + pdsch_vars[gNB_id]->dl_ch_mag0, + pdsch_vars[gNB_id]->dl_ch_rho2_ext, + pdsch_vars[gNB_id]->layer_llr[0], symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,4,nr_slot_rx,symbol), - pdsch_vars[eNB_id]->llr128); + pdsch_vars[gNB_id]->llr128); if (rx_type==rx_IC_dual_stream) { nr_dlsch_qpsk_16qam_llr(frame_parms, rxdataF_comp_ptr, - pdsch_vars[eNB_id]->rxdataF_comp0,//i - pdsch_vars[eNB_id]->dl_ch_mag0,//i - pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], - pdsch_vars[eNB_id]->layer_llr[1], + pdsch_vars[gNB_id]->rxdataF_comp0,//i + pdsch_vars[gNB_id]->dl_ch_mag0,//i + pdsch_vars[gNB_id]->dl_ch_rho_ext[harq_pid][round], + pdsch_vars[gNB_id]->layer_llr[1], symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,2,nr_slot_rx,symbol), - pdsch_vars[eNB_id]->llr128_2ndstream); + pdsch_vars[gNB_id]->llr128_2ndstream); } } else if (dlsch1_harq->Qm == 4) { nr_dlsch_16qam_16qam_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, + pdsch_vars[gNB_id]->rxdataF_comp0, rxdataF_comp_ptr,//i - pdsch_vars[eNB_id]->dl_ch_mag0, + pdsch_vars[gNB_id]->dl_ch_mag0, dl_ch_mag_ptr,//i - pdsch_vars[eNB_id]->dl_ch_rho2_ext, - pdsch_vars[eNB_id]->layer_llr[0], + pdsch_vars[gNB_id]->dl_ch_rho2_ext, + pdsch_vars[gNB_id]->layer_llr[0], symbol,len,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,4,nr_slot_rx,symbol), - pdsch_vars[eNB_id]->llr128); + pdsch_vars[gNB_id]->llr128); if (rx_type==rx_IC_dual_stream) { nr_dlsch_16qam_16qam_llr(frame_parms, rxdataF_comp_ptr, - pdsch_vars[eNB_id]->rxdataF_comp0,//i + pdsch_vars[gNB_id]->rxdataF_comp0,//i dl_ch_mag_ptr, - pdsch_vars[eNB_id]->dl_ch_mag0,//i - pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], - pdsch_vars[eNB_id]->layer_llr[1], + pdsch_vars[gNB_id]->dl_ch_mag0,//i + pdsch_vars[gNB_id]->dl_ch_rho_ext[harq_pid][round], + pdsch_vars[gNB_id]->layer_llr[1], symbol,len,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,4,nr_slot_rx,symbol), - pdsch_vars[eNB_id]->llr128_2ndstream); + pdsch_vars[gNB_id]->llr128_2ndstream); } } else { nr_dlsch_16qam_64qam_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, + pdsch_vars[gNB_id]->rxdataF_comp0, rxdataF_comp_ptr,//i - pdsch_vars[eNB_id]->dl_ch_mag0, + pdsch_vars[gNB_id]->dl_ch_mag0, dl_ch_mag_ptr,//i - pdsch_vars[eNB_id]->dl_ch_rho2_ext, - pdsch_vars[eNB_id]->layer_llr[0], + pdsch_vars[gNB_id]->dl_ch_rho2_ext, + pdsch_vars[gNB_id]->layer_llr[0], symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,4,nr_slot_rx,symbol), - pdsch_vars[eNB_id]->llr128); + pdsch_vars[gNB_id]->llr128); if (rx_type==rx_IC_dual_stream) { nr_dlsch_64qam_16qam_llr(frame_parms, rxdataF_comp_ptr, - pdsch_vars[eNB_id]->rxdataF_comp0, + pdsch_vars[gNB_id]->rxdataF_comp0, dl_ch_mag_ptr, - pdsch_vars[eNB_id]->dl_ch_mag0, - pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], - pdsch_vars[eNB_id]->layer_llr[1], + pdsch_vars[gNB_id]->dl_ch_mag0, + pdsch_vars[gNB_id]->dl_ch_rho_ext[harq_pid][round], + pdsch_vars[gNB_id]->layer_llr[1], symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,6,nr_slot_rx,symbol), - pdsch_vars[eNB_id]->llr128_2ndstream); + pdsch_vars[gNB_id]->llr128_2ndstream); } } } @@ -2555,92 +2560,92 @@ static int nr_dlsch_llr(NR_UE_PDSCH **pdsch_vars, case 6 : if ((rx_type==rx_standard) || (codeword_TB1 == -1)) { nr_dlsch_64qam_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, + pdsch_vars[gNB_id]->rxdataF_comp0, (int16_t*)pllr_symbol_cw0, - pdsch_vars[eNB_id]->dl_ch_mag0, - pdsch_vars[eNB_id]->dl_ch_magb0, + pdsch_vars[gNB_id]->dl_ch_mag0, + pdsch_vars[gNB_id]->dl_ch_magb0, symbol,len,first_symbol_flag,nb_rb, - pdsch_vars[eNB_id]->llr_offset[symbol], + pdsch_vars[gNB_id]->llr_offset[symbol], beamforming_mode); } else if (codeword_TB0 == -1){ nr_dlsch_64qam_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, + pdsch_vars[gNB_id]->rxdataF_comp0, pllr_symbol_cw1, - pdsch_vars[eNB_id]->dl_ch_mag0, - pdsch_vars[eNB_id]->dl_ch_magb0, + pdsch_vars[gNB_id]->dl_ch_mag0, + pdsch_vars[gNB_id]->dl_ch_magb0, symbol,len,first_symbol_flag,nb_rb, - pdsch_vars[eNB_id]->llr_offset[symbol], + pdsch_vars[gNB_id]->llr_offset[symbol], beamforming_mode); } else if (rx_type >= rx_IC_single_stream) { if (dlsch1_harq->Qm == 2) { nr_dlsch_64qam_qpsk_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, + pdsch_vars[gNB_id]->rxdataF_comp0, rxdataF_comp_ptr,//i - pdsch_vars[eNB_id]->dl_ch_mag0, - pdsch_vars[eNB_id]->dl_ch_rho2_ext, - pdsch_vars[eNB_id]->layer_llr[0], + pdsch_vars[gNB_id]->dl_ch_mag0, + pdsch_vars[gNB_id]->dl_ch_rho2_ext, + pdsch_vars[gNB_id]->layer_llr[0], symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,6,nr_slot_rx,symbol), - pdsch_vars[eNB_id]->llr128); + pdsch_vars[gNB_id]->llr128); if (rx_type==rx_IC_dual_stream) { nr_dlsch_qpsk_64qam_llr(frame_parms, rxdataF_comp_ptr, - pdsch_vars[eNB_id]->rxdataF_comp0,//i - pdsch_vars[eNB_id]->dl_ch_mag0, - pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], - pdsch_vars[eNB_id]->layer_llr[1], + pdsch_vars[gNB_id]->rxdataF_comp0,//i + pdsch_vars[gNB_id]->dl_ch_mag0, + pdsch_vars[gNB_id]->dl_ch_rho_ext[harq_pid][round], + pdsch_vars[gNB_id]->layer_llr[1], symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,2,nr_slot_rx,symbol), - pdsch_vars[eNB_id]->llr128_2ndstream); + pdsch_vars[gNB_id]->llr128_2ndstream); } } else if (dlsch1_harq->Qm == 4) { nr_dlsch_64qam_16qam_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, + pdsch_vars[gNB_id]->rxdataF_comp0, rxdataF_comp_ptr,//i - pdsch_vars[eNB_id]->dl_ch_mag0, + pdsch_vars[gNB_id]->dl_ch_mag0, dl_ch_mag_ptr,//i - pdsch_vars[eNB_id]->dl_ch_rho2_ext, - pdsch_vars[eNB_id]->layer_llr[0], + pdsch_vars[gNB_id]->dl_ch_rho2_ext, + pdsch_vars[gNB_id]->layer_llr[0], symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,6,nr_slot_rx,symbol), - pdsch_vars[eNB_id]->llr128); + pdsch_vars[gNB_id]->llr128); if (rx_type==rx_IC_dual_stream) { nr_dlsch_16qam_64qam_llr(frame_parms, rxdataF_comp_ptr, - pdsch_vars[eNB_id]->rxdataF_comp0,//i + pdsch_vars[gNB_id]->rxdataF_comp0,//i dl_ch_mag_ptr, - pdsch_vars[eNB_id]->dl_ch_mag0,//i - pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], - pdsch_vars[eNB_id]->layer_llr[1], + pdsch_vars[gNB_id]->dl_ch_mag0,//i + pdsch_vars[gNB_id]->dl_ch_rho_ext[harq_pid][round], + pdsch_vars[gNB_id]->layer_llr[1], symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,4,nr_slot_rx,symbol), - pdsch_vars[eNB_id]->llr128_2ndstream); + pdsch_vars[gNB_id]->llr128_2ndstream); } } else { nr_dlsch_64qam_64qam_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, + pdsch_vars[gNB_id]->rxdataF_comp0, rxdataF_comp_ptr,//i - pdsch_vars[eNB_id]->dl_ch_mag0, + pdsch_vars[gNB_id]->dl_ch_mag0, dl_ch_mag_ptr,//i - pdsch_vars[eNB_id]->dl_ch_rho2_ext, + pdsch_vars[gNB_id]->dl_ch_rho2_ext, (int16_t*)pllr_symbol_layer0, symbol,len,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,6,nr_slot_rx,symbol), - pdsch_vars[eNB_id]->llr_offset[symbol]); + pdsch_vars[gNB_id]->llr_offset[symbol]); if (rx_type==rx_IC_dual_stream) { nr_dlsch_64qam_64qam_llr(frame_parms, rxdataF_comp_ptr, - pdsch_vars[eNB_id]->rxdataF_comp0,//i + pdsch_vars[gNB_id]->rxdataF_comp0,//i dl_ch_mag_ptr, - pdsch_vars[eNB_id]->dl_ch_mag0,//i - pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], + pdsch_vars[gNB_id]->dl_ch_mag0,//i + pdsch_vars[gNB_id]->dl_ch_rho_ext[harq_pid][round], pllr_symbol_layer1, symbol,len,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,6,nr_slot_rx,symbol), - pdsch_vars[eNB_id]->llr_offset[symbol]); + pdsch_vars[gNB_id]->llr_offset[symbol]); } } } @@ -2648,23 +2653,23 @@ static int nr_dlsch_llr(NR_UE_PDSCH **pdsch_vars, case 8: if ((rx_type==rx_standard) || (codeword_TB1 == -1)) { nr_dlsch_256qam_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, + pdsch_vars[gNB_id]->rxdataF_comp0, (int16_t*)pllr_symbol_cw0, - pdsch_vars[eNB_id]->dl_ch_mag0, - pdsch_vars[eNB_id]->dl_ch_magb0, - pdsch_vars[eNB_id]->dl_ch_magr0, + pdsch_vars[gNB_id]->dl_ch_mag0, + pdsch_vars[gNB_id]->dl_ch_magb0, + pdsch_vars[gNB_id]->dl_ch_magr0, symbol,len,first_symbol_flag,nb_rb, - pdsch_vars[eNB_id]->llr_offset[symbol], + pdsch_vars[gNB_id]->llr_offset[symbol], beamforming_mode); } else if (codeword_TB0 == -1){ nr_dlsch_256qam_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, + pdsch_vars[gNB_id]->rxdataF_comp0, pllr_symbol_cw1, - pdsch_vars[eNB_id]->dl_ch_mag0, - pdsch_vars[eNB_id]->dl_ch_magb0, - pdsch_vars[eNB_id]->dl_ch_magr0, + pdsch_vars[gNB_id]->dl_ch_mag0, + pdsch_vars[gNB_id]->dl_ch_magb0, + pdsch_vars[gNB_id]->dl_ch_magr0, symbol,len,first_symbol_flag,nb_rb, - pdsch_vars[eNB_id]->llr_offset[symbol], + pdsch_vars[gNB_id]->llr_offset[symbol], beamforming_mode); } break; @@ -2679,7 +2684,7 @@ static int nr_dlsch_llr(NR_UE_PDSCH **pdsch_vars, case 2 : if (rx_type==rx_standard) { nr_dlsch_qpsk_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, + pdsch_vars[gNB_id]->rxdataF_comp0, pllr_symbol_cw0, symbol,len,first_symbol_flag,nb_rb, beamforming_mode); @@ -2688,36 +2693,36 @@ static int nr_dlsch_llr(NR_UE_PDSCH **pdsch_vars, case 4: if (rx_type==rx_standard) { nr_dlsch_16qam_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, - pdsch_vars[eNB_id]->llr[0], - pdsch_vars[eNB_id]->dl_ch_mag0, + pdsch_vars[gNB_id]->rxdataF_comp0, + pdsch_vars[gNB_id]->llr[0], + pdsch_vars[gNB_id]->dl_ch_mag0, symbol,len,first_symbol_flag,nb_rb, - pdsch_vars[eNB_id]->llr128, + pdsch_vars[gNB_id]->llr128, beamforming_mode); } break; case 6 : if (rx_type==rx_standard) { nr_dlsch_64qam_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, + pdsch_vars[gNB_id]->rxdataF_comp0, pllr_symbol_cw0, - pdsch_vars[eNB_id]->dl_ch_mag0, - pdsch_vars[eNB_id]->dl_ch_magb0, + pdsch_vars[gNB_id]->dl_ch_mag0, + pdsch_vars[gNB_id]->dl_ch_magb0, symbol,len,first_symbol_flag,nb_rb, - pdsch_vars[eNB_id]->llr_offset[symbol], + pdsch_vars[gNB_id]->llr_offset[symbol], beamforming_mode); } break; case 8 : if (rx_type==rx_standard) { nr_dlsch_256qam_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, + pdsch_vars[gNB_id]->rxdataF_comp0, pllr_symbol_cw0, - pdsch_vars[eNB_id]->dl_ch_mag0, - pdsch_vars[eNB_id]->dl_ch_magb0, - pdsch_vars[eNB_id]->dl_ch_magr0, + pdsch_vars[gNB_id]->dl_ch_mag0, + pdsch_vars[gNB_id]->dl_ch_magb0, + pdsch_vars[gNB_id]->dl_ch_magr0, symbol,len,first_symbol_flag,nb_rb, - pdsch_vars[eNB_id]->llr_offset[symbol], + pdsch_vars[gNB_id]->llr_offset[symbol], beamforming_mode); } break; @@ -2734,94 +2739,94 @@ static int nr_dlsch_llr(NR_UE_PDSCH **pdsch_vars, #ifdef USER_MODE -void dump_dlsch2(PHY_VARS_UE *ue,uint8_t eNB_id,uint8_t nr_slot_rx,unsigned int *coded_bits_per_codeword,int round, unsigned char harq_pid) +void dump_dlsch2(PHY_VARS_UE *ue,uint8_t gNB_id,uint8_t nr_slot_rx,unsigned int *coded_bits_per_codeword,int round, unsigned char harq_pid) { unsigned int nsymb = (ue->frame_parms.Ncp == 0) ? 14 : 12; char fname[32],vname[32]; int N_RB_DL=ue->frame_parms.N_RB_DL; - snprintf(fname, 32, "dlsch%d_rxF_r%d_ext0.m",eNB_id,round); - snprintf(vname, 32, "dl%d_rxF_r%d_ext0",eNB_id,round); - write_output(fname,vname,ue->pdsch_vars[proc->thread_id][eNB_id]->rxdataF_ext[0],12*N_RB_DL*nsymb,1,1); + snprintf(fname, 32, "dlsch%d_rxF_r%d_ext0.m", gNB_id, round); + snprintf(vname, 32, "dl%d_rxF_r%d_ext0", gNB_id, round); + write_output(fname,vname,ue->pdsch_vars[proc->thread_id][gNB_id]->rxdataF_ext[0],12*N_RB_DL*nsymb,1,1); if (ue->frame_parms.nb_antennas_rx >1) { - snprintf(fname, 32, "dlsch%d_rxF_r%d_ext1.m",eNB_id,round); - snprintf(vname, 32, "dl%d_rxF_r%d_ext1",eNB_id,round); - write_output(fname,vname,ue->pdsch_vars[proc->thread_id][eNB_id]->rxdataF_ext[1],12*N_RB_DL*nsymb,1,1); + snprintf(fname, 32, "dlsch%d_rxF_r%d_ext1.m", gNB_id, round); + snprintf(vname, 32, "dl%d_rxF_r%d_ext1", gNB_id, round); + write_output(fname,vname,ue->pdsch_vars[proc->thread_id][gNB_id]->rxdataF_ext[1],12*N_RB_DL*nsymb,1,1); } - snprintf(fname, 32, "dlsch%d_ch_r%d_ext00.m",eNB_id,round); - snprintf(vname, 32, "dl%d_ch_r%d_ext00",eNB_id,round); - write_output(fname,vname,ue->pdsch_vars[proc->thread_id][eNB_id]->dl_ch_estimates_ext[0],12*N_RB_DL*nsymb,1,1); + snprintf(fname, 32, "dlsch%d_ch_r%d_ext00.m", gNB_id, round); + snprintf(vname, 32, "dl%d_ch_r%d_ext00", gNB_id, round); + write_output(fname,vname,ue->pdsch_vars[proc->thread_id][gNB_id]->dl_ch_estimates_ext[0],12*N_RB_DL*nsymb,1,1); - if (ue->transmission_mode[eNB_id]==7){ - snprintf(fname, 32, "dlsch%d_bf_ch_r%d.m",eNB_id,round); - snprintf(vname, 32, "dl%d_bf_ch_r%d",eNB_id,round); - write_output(fname,vname,ue->pdsch_vars[proc->thread_id][eNB_id]->dl_bf_ch_estimates[0],512*nsymb,1,1); - //write_output(fname,vname,phy_vars_ue->lte_ue_pdsch_vars[eNB_id]->dl_bf_ch_estimates[0],512,1,1); + if (ue->transmission_mode[gNB_id]==7){ + snprintf(fname, 32, "dlsch%d_bf_ch_r%d.m", gNB_id, round); + snprintf(vname, 32, "dl%d_bf_ch_r%d", gNB_id, round); + write_output(fname,vname,ue->pdsch_vars[proc->thread_id][gNB_id]->dl_bf_ch_estimates[0],512*nsymb,1,1); + //write_output(fname,vname,phy_vars_ue->lte_ue_pdsch_vars[gNB_id]->dl_bf_ch_estimates[0],512,1,1); - snprintf(fname, 32, "dlsch%d_bf_ch_r%d_ext00.m",eNB_id,round); - snprintf(vname, 32, "dl%d_bf_ch_r%d_ext00",eNB_id,round); - write_output(fname,vname,ue->pdsch_vars[proc->thread_id][eNB_id]->dl_bf_ch_estimates_ext[0],12*N_RB_DL*nsymb,1,1); + snprintf(fname, 32, "dlsch%d_bf_ch_r%d_ext00.m", gNB_id, round); + snprintf(vname, 32, "dl%d_bf_ch_r%d_ext00", gNB_id, round); + write_output(fname,vname,ue->pdsch_vars[proc->thread_id][gNB_id]->dl_bf_ch_estimates_ext[0],12*N_RB_DL*nsymb,1,1); } if (ue->frame_parms.nb_antennas_rx == 2) { - snprintf(fname, 32, "dlsch%d_ch_r%d_ext01.m",eNB_id,round); - snprintf(vname, 32, "dl%d_ch_r%d_ext01",eNB_id,round); - write_output(fname,vname,ue->pdsch_vars[proc->thread_id][eNB_id]->dl_ch_estimates_ext[1],12*N_RB_DL*nsymb,1,1); + snprintf(fname, 32, "dlsch%d_ch_r%d_ext01.m", gNB_id, round); + snprintf(vname, 32, "dl%d_ch_r%d_ext01", gNB_id, round); + write_output(fname,vname,ue->pdsch_vars[proc->thread_id][gNB_id]->dl_ch_estimates_ext[1],12*N_RB_DL*nsymb,1,1); } if (ue->frame_parms.nb_antenna_ports_gNB == 2) { - snprintf(fname, 32, "dlsch%d_ch_r%d_ext10.m",eNB_id,round); - snprintf(vname, 32, "dl%d_ch_r%d_ext10",eNB_id,round); - write_output(fname,vname,ue->pdsch_vars[proc->thread_id][eNB_id]->dl_ch_estimates_ext[2],12*N_RB_DL*nsymb,1,1); + snprintf(fname, 32, "dlsch%d_ch_r%d_ext10.m", gNB_id, round); + snprintf(vname, 32, "dl%d_ch_r%d_ext10", gNB_id, round); + write_output(fname,vname,ue->pdsch_vars[proc->thread_id][gNB_id]->dl_ch_estimates_ext[2],12*N_RB_DL*nsymb,1,1); if (ue->frame_parms.nb_antennas_rx == 2) { - snprintf(fname, 32, "dlsch%d_ch_r%d_ext11.m",eNB_id,round); - snprintf(vname, 32, "dl%d_ch_r%d_ext11",eNB_id,round); - write_output(fname,vname,ue->pdsch_vars[proc->thread_id][eNB_id]->dl_ch_estimates_ext[3],12*N_RB_DL*nsymb,1,1); + snprintf(fname, 32, "dlsch%d_ch_r%d_ext11.m",gNB_id,round); + snprintf(vname, 32, "dl%d_ch_r%d_ext11",gNB_id,round); + write_output(fname,vname,ue->pdsch_vars[proc->thread_id][gNB_id]->dl_ch_estimates_ext[3],12*N_RB_DL*nsymb,1,1); } } - snprintf(fname, 32, "dlsch%d_rxF_r%d_uespec0.m",eNB_id,round); - snprintf(vname, 32, "dl%d_rxF_r%d_uespec0",eNB_id,round); - write_output(fname,vname,ue->pdsch_vars[proc->thread_id][eNB_id]->rxdataF_uespec_pilots[0],12*N_RB_DL,1,1); + snprintf(fname, 32, "dlsch%d_rxF_r%d_uespec0.m", gNB_id, round); + snprintf(vname, 32, "dl%d_rxF_r%d_uespec0", gNB_id, round); + write_output(fname,vname,ue->pdsch_vars[proc->thread_id][gNB_id]->rxdataF_uespec_pilots[0],12*N_RB_DL,1,1); /* - write_output("dlsch%d_ch_ext01.m","dl01_ch0_ext",pdsch_vars[eNB_id]->dl_ch_estimates_ext[1],12*N_RB_DL*nsymb,1,1); - write_output("dlsch%d_ch_ext10.m","dl10_ch0_ext",pdsch_vars[eNB_id]->dl_ch_estimates_ext[2],12*N_RB_DL*nsymb,1,1); - write_output("dlsch%d_ch_ext11.m","dl11_ch0_ext",pdsch_vars[eNB_id]->dl_ch_estimates_ext[3],12*N_RB_DL*nsymb,1,1); + write_output("dlsch%d_ch_ext01.m","dl01_ch0_ext",pdsch_vars[gNB_id]->dl_ch_estimates_ext[1],12*N_RB_DL*nsymb,1,1); + write_output("dlsch%d_ch_ext10.m","dl10_ch0_ext",pdsch_vars[gNB_id]->dl_ch_estimates_ext[2],12*N_RB_DL*nsymb,1,1); + write_output("dlsch%d_ch_ext11.m","dl11_ch0_ext",pdsch_vars[gNB_id]->dl_ch_estimates_ext[3],12*N_RB_DL*nsymb,1,1); */ - snprintf(fname, 32, "dlsch%d_r%d_rho.m",eNB_id,round); - snprintf(vname, 32, "dl_rho_r%d_%d",eNB_id,round); + snprintf(fname, 32, "dlsch%d_r%d_rho.m", gNB_id, round); + snprintf(vname, 32, "dl_rho_r%d_%d", gNB_id, round); - write_output(fname,vname,ue->pdsch_vars[proc->thread_id][eNB_id]->dl_ch_rho_ext[harq_pid][round][0],12*N_RB_DL*nsymb,1,1); + write_output(fname,vname,ue->pdsch_vars[proc->thread_id][gNB_id]->dl_ch_rho_ext[harq_pid][round][0],12*N_RB_DL*nsymb,1,1); - snprintf(fname, 32, "dlsch%d_r%d_rho2.m",eNB_id,round); - snprintf(vname, 32, "dl_rho2_r%d_%d",eNB_id,round); + snprintf(fname, 32, "dlsch%d_r%d_rho2.m", gNB_id, round); + snprintf(vname, 32, "dl_rho2_r%d_%d", gNB_id, round); - write_output(fname,vname,ue->pdsch_vars[proc->thread_id][eNB_id]->dl_ch_rho2_ext[0],12*N_RB_DL*nsymb,1,1); + write_output(fname,vname,ue->pdsch_vars[proc->thread_id][gNB_id]->dl_ch_rho2_ext[0],12*N_RB_DL*nsymb,1,1); - snprintf(fname, 32, "dlsch%d_rxF_r%d_comp0.m",eNB_id,round); - snprintf(vname, 32, "dl%d_rxF_r%d_comp0",eNB_id,round); - write_output(fname,vname,ue->pdsch_vars[proc->thread_id][eNB_id]->rxdataF_comp0[0],12*N_RB_DL*nsymb,1,1); + snprintf(fname, 32, "dlsch%d_rxF_r%d_comp0.m", gNB_id, round); + snprintf(vname, 32, "dl%d_rxF_r%d_comp0", gNB_id, round); + write_output(fname,vname,ue->pdsch_vars[proc->thread_id][gNB_id]->rxdataF_comp0[0],12*N_RB_DL*nsymb,1,1); if (ue->frame_parms.nb_antenna_ports_gNB == 2) { - snprintf(fname, 32, "dlsch%d_rxF_r%d_comp1.m",eNB_id,round); - snprintf(vname, 32, "dl%d_rxF_r%d_comp1",eNB_id,round); - write_output(fname,vname,ue->pdsch_vars[proc->thread_id][eNB_id]->rxdataF_comp1[harq_pid][round][0],12*N_RB_DL*nsymb,1,1); + snprintf(fname, 32, "dlsch%d_rxF_r%d_comp1.m", gNB_id, round); + snprintf(vname, 32, "dl%d_rxF_r%d_comp1", gNB_id, round); + write_output(fname,vname,ue->pdsch_vars[proc->thread_id][gNB_id]->rxdataF_comp1[harq_pid][round][0],12*N_RB_DL*nsymb,1,1); } - snprintf(fname, 32, "dlsch%d_rxF_r%d_llr.m",eNB_id,round); - snprintf(vname, 32, "dl%d_r%d_llr",eNB_id,round); - write_output(fname,vname, ue->pdsch_vars[proc->thread_id][eNB_id]->llr[0],coded_bits_per_codeword[0],1,0); - snprintf(fname, 32, "dlsch%d_r%d_mag1.m",eNB_id,round); - snprintf(vname, 32, "dl%d_r%d_mag1",eNB_id,round); - write_output(fname,vname,ue->pdsch_vars[proc->thread_id][eNB_id]->dl_ch_mag0[0],12*N_RB_DL*nsymb,1,1); - snprintf(fname, 32, "dlsch%d_r%d_mag2.m",eNB_id,round); - snprintf(vname, 32, "dl%d_r%d_mag2",eNB_id,round); - write_output(fname,vname,ue->pdsch_vars[proc->thread_id][eNB_id]->dl_ch_magb0[0],12*N_RB_DL*nsymb,1,1); + snprintf(fname, 32, "dlsch%d_rxF_r%d_llr.m", gNB_id, round); + snprintf(vname, 32, "dl%d_r%d_llr", gNB_id, round); + write_output(fname, vname, ue->pdsch_vars[proc->thread_id][gNB_id]->llr[0], coded_bits_per_codeword[0], 1, 0); + snprintf(fname, 32, "dlsch%d_r%d_mag1.m", gNB_id, round); + snprintf(vname, 32, "dl%d_r%d_mag1", gNB_id, round); + write_output(fname, vname, ue->pdsch_vars[proc->thread_id][gNB_id]->dl_ch_mag0[0], 12*N_RB_DL*nsymb, 1, 1); + snprintf(fname, 32, "dlsch%d_r%d_mag2.m", gNB_id, round); + snprintf(vname, 32, "dl%d_r%d_mag2", gNB_id, round); + write_output(fname, vname, ue->pdsch_vars[proc->thread_id][gNB_id]->dl_ch_magb0[0], 12*N_RB_DL*nsymb, 1, 1); - // printf("log2_maxh = %d\n",ue->pdsch_vars[eNB_id]->log2_maxh); + // printf("log2_maxh = %d\n",ue->pdsch_vars[gNB_id]->log2_maxh); } #endif diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c index b5ab563c26..13270c5c4b 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c @@ -103,7 +103,7 @@ void free_list(NR_UE_SSB *node) { } -int nr_pbch_detection(UE_nr_rxtx_proc_t * proc, PHY_VARS_NR_UE *ue, int pbch_initial_symbol, runmode_t mode) +int nr_pbch_detection(UE_nr_rxtx_proc_t * proc, PHY_VARS_NR_UE *ue, int pbch_initial_symbol) { NR_DL_FRAME_PARMS *frame_parms=&ue->frame_parms; int ret =-1; @@ -202,7 +202,7 @@ int nr_pbch_detection(UE_nr_rxtx_proc_t * proc, PHY_VARS_NR_UE *ue, int pbch_ini char duplex_string[2][4] = {"FDD","TDD"}; char prefix_string[2][9] = {"NORMAL","EXTENDED"}; -int nr_initial_sync(UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *ue, runmode_t mode, int n_frames) +int nr_initial_sync(UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *ue, int n_frames) { int32_t sync_pos, sync_pos_frame; // k_ssb, N_ssb_crb, sync_pos2, @@ -299,7 +299,7 @@ int nr_initial_sync(UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *ue, runmode_t mode, rx_sss_nr(ue, proc, &metric_tdd_ncp, &phase_tdd_ncp); nr_gold_pbch(ue); - ret = nr_pbch_detection(proc, ue,1,mode); // start pbch detection at first symbol after pss + ret = nr_pbch_detection(proc, ue, 1); // start pbch detection at first symbol after pss if (ret == 0) { // sync at symbol ue->symbol_offset diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c b/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c index 4d21fe782b..e33693ce0e 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c @@ -35,6 +35,7 @@ #include "PHY/sse_intrin.h" #include "PHY/LTE_REFSIG/lte_refsig.h" #include "PHY/INIT/phy_init.h" +#include "openair1/SCHED_NR_UE/defs.h" //#define DEBUG_PBCH //#define DEBUG_PBCH_ENCODING @@ -608,23 +609,10 @@ int nr_rx_pbch( PHY_VARS_NR_UE *ue, nr_downlink_indication_t dl_indication; fapi_nr_rx_indication_t rx_ind; - - dl_indication.module_id = ue->Mod_id; - dl_indication.gNB_index = gNB_id; - dl_indication.cc_id = proc->CC_id; - dl_indication.frame = proc->frame_rx; - dl_indication.slot = proc->nr_slot_rx; - dl_indication.thread_id = proc->thread_id; - dl_indication.rx_ind = &rx_ind; // hang on rx_ind instance - dl_indication.dci_ind = NULL; + uint16_t number_pdus = 1; - rx_ind.rx_indication_body[0].pdu_type = FAPI_NR_RX_PDU_TYPE_MIB; - rx_ind.rx_indication_body[0].mib_pdu.pdu = &decoded_output[0]; //not good as it is pointing to a memory that can change - rx_ind.rx_indication_body[0].mib_pdu.additional_bits = nr_ue_pbch_vars->xtra_byte; - rx_ind.rx_indication_body[0].mib_pdu.ssb_index = i_ssb; // confirm with TCL - rx_ind.rx_indication_body[0].mib_pdu.ssb_length = Lmax; // confirm with TCL - rx_ind.rx_indication_body[0].mib_pdu.cell_id = frame_parms->Nid_cell; // confirm with TCL - rx_ind.number_pdus = 1; //rx_ind.number_pdus++; + nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, gNB_id); + nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_MIB, gNB_id, ue, NULL, number_pdus); if (ue->if_inst && ue->if_inst->dl_indication) ue->if_inst->dl_indication(&dl_indication, NULL); 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 6648197153..91274b908a 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h @@ -1172,8 +1172,7 @@ int nr_rx_pbch( PHY_VARS_NR_UE *ue, int nr_pbch_detection(UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *ue, - int pbch_initial_symbol, - runmode_t mode); + int pbch_initial_symbol); uint16_t rx_pbch_emul(PHY_VARS_NR_UE *phy_vars_ue, uint8_t eNB_id, @@ -1453,7 +1452,6 @@ void generate_RIV_tables(void); */ int nr_initial_sync(UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *phy_vars_ue, - runmode_t mode, int n_frames); /*! diff --git a/openair1/PHY/TOOLS/nr_phy_scope.c b/openair1/PHY/TOOLS/nr_phy_scope.c index f6cb93ed03..cb61523852 100644 --- a/openair1/PHY/TOOLS/nr_phy_scope.c +++ b/openair1/PHY/TOOLS/nr_phy_scope.c @@ -225,6 +225,8 @@ static void oai_xygraph(OAIgraph_t *graph, float *x, float *y, int len, int laye } static void genericWaterFall (OAIgraph_t *graph, scopeSample_t *values, const int datasize, const int divisions, const char *label) { + if ( values == NULL ) + return; fl_winset(FL_ObjWin(graph->graph)); const int samplesPerPixel=datasize/graph->w; int displayPart=graph->waterFallh-ScaleZone; diff --git a/openair1/PHY/TOOLS/oai_dfts.c b/openair1/PHY/TOOLS/oai_dfts.c index e4e85f7ba9..6569f7eab5 100644 --- a/openair1/PHY/TOOLS/oai_dfts.c +++ b/openair1/PHY/TOOLS/oai_dfts.c @@ -5952,8 +5952,6 @@ void idft32768(int16_t *x,int16_t *y,unsigned char scale) #endif - - int16_t twa1536[1024],twb1536[1024]; // 512 x 3 @@ -9471,6 +9469,919 @@ void dft1200(int16_t *x,int16_t *y,unsigned char scale_flag) } + +static int16_t twa1296[431*2*4]; +static int16_t twb1296[431*2*4]; + +void dft1296(int16_t *x,int16_t *y,unsigned char scale_flag) //432 * 3 +{ + + int i,j; + simd_q15_t *x128=(simd_q15_t *)x; + simd_q15_t *y128=(simd_q15_t *)y; + simd_q15_t *twa128=(simd_q15_t *)&twa1296[0]; + simd_q15_t *twb128=(simd_q15_t *)&twb1296[0]; + simd_q15_t x2128[1296];// = (simd_q15_t *)&x2128array[0]; + simd_q15_t ytmp128[1296];//=&ytmp128array3[0]; + + + + for (i=0,j=0; i<432; i++,j+=3) { + x2128[i] = x128[j]; + x2128[i+432] = x128[j+1]; + x2128[i+864] = x128[j+2]; + } + + dft432((int16_t *)x2128,(int16_t *)ytmp128,1); + dft432((int16_t *)(x2128+432),(int16_t *)(ytmp128+432),1); + dft432((int16_t *)(x2128+864),(int16_t *)(ytmp128+864),1); + + bfly3_tw1(ytmp128,ytmp128+432,ytmp128+864,y128,y128+432,y128+864); + + for (i=1,j=0; i<432; i++,j++) { + bfly3(ytmp128+i, + ytmp128+432+i, + ytmp128+864+i, + y128+i, + y128+432+i, + y128+864+i, + twa128+j, + twb128+j); + } + + if (scale_flag==1) { + norm128 = set1_int16(dft_norm_table[14]); + + for (i=0; i<1296; i++) { + y128[i] = mulhi_int16(y128[i],norm128); + } + } + + _mm_empty(); + _m_empty(); + +}; + + +static int16_t twa1440[479*2*4]; +static int16_t twb1440[479*2*4]; + +void dft1440(int16_t *x,int16_t *y,unsigned char scale_flag) // 480 x 3 +{ + int i,j; + simd_q15_t *x128=(simd_q15_t *)x; + simd_q15_t *y128=(simd_q15_t *)y; + simd_q15_t *twa128=(simd_q15_t *)&twa1440[0]; + simd_q15_t *twb128=(simd_q15_t *)&twb1440[0]; + simd_q15_t x2128[1440];// = (simd_q15_t *)&x2128array[0]; + simd_q15_t ytmp128[1440];//=&ytmp128array3[0]; + + + + for (i=0,j=0; i<480; i++,j+=3) { + x2128[i] = x128[j]; + x2128[i+480] = x128[j+1]; + x2128[i+960] = x128[j+2]; + } + + dft480((int16_t *)x2128,(int16_t *)ytmp128,1); + dft480((int16_t *)(x2128+480),(int16_t *)(ytmp128+480),1); + dft480((int16_t *)(x2128+960),(int16_t *)(ytmp128+960),1); + + bfly3_tw1(ytmp128,ytmp128+480,ytmp128+960,y128,y128+480,y128+960); + + for (i=1,j=0; i<480; i++,j++) { + bfly3(ytmp128+i, + ytmp128+480+i, + ytmp128+960+i, + y128+i, + y128+480+i, + y128+960+i, + twa128+j, + twb128+j); + } + + if (scale_flag==1) { + norm128 = set1_int16(dft_norm_table[14]); + + for (i=0; i<1440; i++) { + y128[i] = mulhi_int16(y128[i],norm128); + } + } + + _mm_empty(); + _m_empty(); + +}; + +static int16_t twa1500[2392]__attribute__((aligned(32))); +static int16_t twb1500[2392]__attribute__((aligned(32))); +static int16_t twc1500[2392]__attribute__((aligned(32))); +static int16_t twd1500[2392]__attribute__((aligned(32))); + +void dft1500(int16_t *x,int16_t *y,unsigned char scale_flag) +{ + + int i,j; + simd_q15_t *x128=(simd_q15_t *)x; + simd_q15_t *y128=(simd_q15_t *)y; + simd_q15_t *twa128=(simd_q15_t *)&twa1500[0]; + simd_q15_t *twb128=(simd_q15_t *)&twb1500[0]; + simd_q15_t *twc128=(simd_q15_t *)&twc1500[0]; + simd_q15_t *twd128=(simd_q15_t *)&twd1500[0]; + simd_q15_t x2128[1500];// = (simd_q15_t *)&x2128array[0]; + simd_q15_t ytmp128[1500];//=&ytmp128array2[0]; + + + + for (i=0,j=0; i<300; i++,j+=5) { + x2128[i] = x128[j]; + x2128[i+300] = x128[j+1]; + x2128[i+600] = x128[j+2]; + x2128[i+900] = x128[j+3]; + x2128[i+1200] = x128[j+4]; + } + + dft300((int16_t *)x2128,(int16_t *)ytmp128,1); + dft300((int16_t *)(x2128+300),(int16_t *)(ytmp128+300),1); + dft300((int16_t *)(x2128+600),(int16_t *)(ytmp128+600),1); + dft300((int16_t *)(x2128+900),(int16_t *)(ytmp128+900),1); + dft300((int16_t *)(x2128+1200),(int16_t *)(ytmp128+1200),1); + + bfly5_tw1(ytmp128,ytmp128+300,ytmp128+600,ytmp128+900,ytmp128+1200,y128,y128+300,y128+600,y128+900,y128+1200); + + for (i=1,j=0; i<300; i++,j++) { + bfly5(ytmp128+i, + ytmp128+300+i, + ytmp128+600+i, + ytmp128+900+i, + ytmp128+1200+i, + y128+i, + y128+300+i, + y128+600+i, + y128+900+i, + y128+1200+i, + twa128+j, + twb128+j, + twc128+j, + twd128+j); + } + + if (scale_flag==1) { + norm128 = set1_int16(dft_norm_table[15]); + + for (i=0; i<1500; i++) { + y128[i] = mulhi_int16(y128[i],norm128); + } + } + + _mm_empty(); + _m_empty(); + +} + +static int16_t twa1620[539*2*4]; +static int16_t twb1620[539*2*4]; + +void dft1620(int16_t *x,int16_t *y,unsigned char scale_flag) // 540 x 3 +{ + int i,j; + simd_q15_t *x128=(simd_q15_t *)x; + simd_q15_t *y128=(simd_q15_t *)y; + simd_q15_t *twa128=(simd_q15_t *)&twa1620[0]; + simd_q15_t *twb128=(simd_q15_t *)&twb1620[0]; + simd_q15_t x2128[1620];// = (simd_q15_t *)&x2128array[0]; + simd_q15_t ytmp128[1620];//=&ytmp128array3[0]; + + + + for (i=0,j=0; i<540; i++,j+=3) { + x2128[i] = x128[j]; + x2128[i+540] = x128[j+1]; + x2128[i+1080] = x128[j+2]; + } + + dft540((int16_t *)x2128,(int16_t *)ytmp128,1); + dft540((int16_t *)(x2128+540),(int16_t *)(ytmp128+540),1); + dft540((int16_t *)(x2128+1080),(int16_t *)(ytmp128+1080),1); + + bfly3_tw1(ytmp128,ytmp128+540,ytmp128+1080,y128,y128+540,y128+1080); + + for (i=1,j=0; i<540; i++,j++) { + bfly3(ytmp128+i, + ytmp128+540+i, + ytmp128+1080+i, + y128+i, + y128+540+i, + y128+1080+i, + twa128+j, + twb128+j); + } + + if (scale_flag==1) { + norm128 = set1_int16(dft_norm_table[14]); + + for (i=0; i<1620; i++) { + y128[i] = mulhi_int16(y128[i],norm128); + } + } + + _mm_empty(); + _m_empty(); + +}; + +static int16_t twa1728[575*2*4]; +static int16_t twb1728[575*2*4]; + +void dft1728(int16_t *x,int16_t *y,unsigned char scale_flag) // 576 x 3 +{ + int i,j; + simd_q15_t *x128=(simd_q15_t *)x; + simd_q15_t *y128=(simd_q15_t *)y; + simd_q15_t *twa128=(simd_q15_t *)&twa1728[0]; + simd_q15_t *twb128=(simd_q15_t *)&twb1728[0]; + simd_q15_t x2128[1728];// = (simd_q15_t *)&x2128array[0]; + simd_q15_t ytmp128[1728];//=&ytmp128array3[0]; + + + + for (i=0,j=0; i<576; i++,j+=3) { + x2128[i] = x128[j]; + x2128[i+576] = x128[j+1]; + x2128[i+1152] = x128[j+2]; + } + + dft576((int16_t *)x2128,(int16_t *)ytmp128,1); + dft576((int16_t *)(x2128+576),(int16_t *)(ytmp128+576),1); + dft576((int16_t *)(x2128+1152),(int16_t *)(ytmp128+1152),1); + + bfly3_tw1(ytmp128,ytmp128+576,ytmp128+1152,y128,y128+576,y128+1152); + + for (i=1,j=0; i<576; i++,j++) { + bfly3(ytmp128+i, + ytmp128+576+i, + ytmp128+1152+i, + y128+i, + y128+576+i, + y128+1152+i, + twa128+j, + twb128+j); + } + + if (scale_flag==1) { + norm128 = set1_int16(dft_norm_table[14]); + + for (i=0; i<1728; i++) { + y128[i] = mulhi_int16(y128[i],norm128); + } + } + + _mm_empty(); + _m_empty(); + +}; + +static int16_t twa1800[599*2*4]; +static int16_t twb1800[599*2*4]; + +void dft1800(int16_t *x,int16_t *y,unsigned char scale_flag) // 600 x 3 +{ + int i,j; + simd_q15_t *x128=(simd_q15_t *)x; + simd_q15_t *y128=(simd_q15_t *)y; + simd_q15_t *twa128=(simd_q15_t *)&twa1800[0]; + simd_q15_t *twb128=(simd_q15_t *)&twb1800[0]; + simd_q15_t x2128[1800];// = (simd_q15_t *)&x2128array[0]; + simd_q15_t ytmp128[1800];//=&ytmp128array3[0]; + + + + for (i=0,j=0; i<600; i++,j+=3) { + x2128[i] = x128[j]; + x2128[i+600] = x128[j+1]; + x2128[i+1200] = x128[j+2]; + } + + dft600((int16_t *)x2128,(int16_t *)ytmp128,1); + dft600((int16_t *)(x2128+600),(int16_t *)(ytmp128+600),1); + dft600((int16_t *)(x2128+1200),(int16_t *)(ytmp128+1200),1); + + bfly3_tw1(ytmp128,ytmp128+600,ytmp128+1200,y128,y128+600,y128+1200); + + for (i=1,j=0; i<600; i++,j++) { + bfly3(ytmp128+i, + ytmp128+600+i, + ytmp128+1200+i, + y128+i, + y128+600+i, + y128+1200+i, + twa128+j, + twb128+j); + } + + if (scale_flag==1) { + norm128 = set1_int16(dft_norm_table[14]); + + for (i=0; i<1800; i++) { + y128[i] = mulhi_int16(y128[i],norm128); + } + } + + _mm_empty(); + _m_empty(); + +}; + +static int16_t twa1920[479*2*4]; +static int16_t twb1920[479*2*4]; +static int16_t twc1920[479*2*4]; + +void dft1920(int16_t *x,int16_t *y,unsigned char scale_flag) // 480 x 4 +{ + int i,j; + simd_q15_t *x128=(simd_q15_t *)x; + simd_q15_t *y128=(simd_q15_t *)y; + simd_q15_t *twa128=(simd_q15_t *)&twa1920[0]; + simd_q15_t *twb128=(simd_q15_t *)&twb1920[0]; + simd_q15_t *twc128=(simd_q15_t *)&twc1920[0]; + simd_q15_t x2128[1920];// = (simd_q15_t *)&x2128array[0]; + simd_q15_t ytmp128[1920];//=&ytmp128array2[0]; + + + + for (i=0,j=0; i<480; i++,j+=4) { + x2128[i] = x128[j]; + x2128[i+480] = x128[j+1]; + x2128[i+960] = x128[j+2]; + x2128[i+1440] = x128[j+3]; + } + + dft480((int16_t *)x2128,(int16_t *)ytmp128,1); + dft480((int16_t *)(x2128+480),(int16_t *)(ytmp128+480),1); + dft480((int16_t *)(x2128+960),(int16_t *)(ytmp128+960),1); + dft480((int16_t *)(x2128+1440),(int16_t *)(ytmp128+1440),1); + + bfly4_tw1(ytmp128,ytmp128+480,ytmp128+960,ytmp128+1440,y128,y128+480,y128+960,y128+1440); + + for (i=1,j=0; i<480; i++,j++) { + bfly4(ytmp128+i, + ytmp128+480+i, + ytmp128+960+i, + ytmp128+1440+i, + y128+i, + y128+480+i, + y128+960+i, + y128+1440+i, + twa128+j, + twb128+j, + twc128+j); + } + + if (scale_flag==1) { + norm128 = set1_int16(dft_norm_table[13]); + for (i=0; i<1920; i++) { + y128[i] = mulhi_int16(y128[i],norm128); + } + } + + _mm_empty(); + _m_empty(); + +}; + +static int16_t twa1944[647*2*4]; +static int16_t twb1944[647*2*4]; + +void dft1944(int16_t *x,int16_t *y,unsigned char scale_flag) // 648 x 3 +{ + int i,j; + simd_q15_t *x128=(simd_q15_t *)x; + simd_q15_t *y128=(simd_q15_t *)y; + simd_q15_t *twa128=(simd_q15_t *)&twa1944[0]; + simd_q15_t *twb128=(simd_q15_t *)&twb1944[0]; + simd_q15_t x2128[1944];// = (simd_q15_t *)&x2128array[0]; + simd_q15_t ytmp128[1944];//=&ytmp128array3[0]; + + + + for (i=0,j=0; i<648; i++,j+=3) { + x2128[i] = x128[j]; + x2128[i+648] = x128[j+1]; + x2128[i+1296] = x128[j+2]; + } + + dft648((int16_t *)x2128,(int16_t *)ytmp128,1); + dft648((int16_t *)(x2128+648),(int16_t *)(ytmp128+648),1); + dft648((int16_t *)(x2128+1296),(int16_t *)(ytmp128+1296),1); + + bfly3_tw1(ytmp128,ytmp128+648,ytmp128+1296,y128,y128+648,y128+1296); + + for (i=1,j=0; i<648; i++,j++) { + bfly3(ytmp128+i, + ytmp128+648+i, + ytmp128+1296+i, + y128+i, + y128+648+i, + y128+1296+i, + twa128+j, + twb128+j); + } + + if (scale_flag==1) { + norm128 = set1_int16(dft_norm_table[14]); + + for (i=0; i<1944; i++) { + y128[i] = mulhi_int16(y128[i],norm128); + } + } + + _mm_empty(); + _m_empty(); + +}; + +static int16_t twa2160[719*2*4]; +static int16_t twb2160[719*2*4]; + +void dft2160(int16_t *x,int16_t *y,unsigned char scale_flag) // 720 x 3 +{ + int i,j; + simd_q15_t *x128=(simd_q15_t *)x; + simd_q15_t *y128=(simd_q15_t *)y; + simd_q15_t *twa128=(simd_q15_t *)&twa2160[0]; + simd_q15_t *twb128=(simd_q15_t *)&twb2160[0]; + simd_q15_t x2128[2160];// = (simd_q15_t *)&x2128array[0]; + simd_q15_t ytmp128[2160];//=&ytmp128array3[0]; + + + + for (i=0,j=0; i<720; i++,j+=3) { + x2128[i] = x128[j]; + x2128[i+720] = x128[j+1]; + x2128[i+1440] = x128[j+2]; + } + + dft720((int16_t *)x2128,(int16_t *)ytmp128,1); + dft720((int16_t *)(x2128+720),(int16_t *)(ytmp128+720),1); + dft720((int16_t *)(x2128+1440),(int16_t *)(ytmp128+1440),1); + + bfly3_tw1(ytmp128,ytmp128+720,ytmp128+1440,y128,y128+720,y128+1440); + + for (i=1,j=0; i<720; i++,j++) { + bfly3(ytmp128+i, + ytmp128+720+i, + ytmp128+1440+i, + y128+i, + y128+720+i, + y128+1440+i, + twa128+j, + twb128+j); + } + + if (scale_flag==1) { + norm128 = set1_int16(dft_norm_table[14]); + + for (i=0; i<2160; i++) { + y128[i] = mulhi_int16(y128[i],norm128); + } + } + + _mm_empty(); + _m_empty(); + +}; + +static int16_t twa2304[767*2*4]; +static int16_t twb2304[767*2*4]; + +void dft2304(int16_t *x,int16_t *y,unsigned char scale_flag) // 768 x 3 +{ + int i,j; + simd_q15_t *x128=(simd_q15_t *)x; + simd_q15_t *y128=(simd_q15_t *)y; + simd_q15_t *twa128=(simd_q15_t *)&twa2304[0]; + simd_q15_t *twb128=(simd_q15_t *)&twb2304[0]; + simd_q15_t x2128[2304];// = (simd_q15_t *)&x2128array[0]; + simd_q15_t ytmp128[2304];//=&ytmp128array3[0]; + + + + for (i=0,j=0; i<768; i++,j+=3) { + x2128[i] = x128[j]; + x2128[i+768] = x128[j+1]; + x2128[i+1536] = x128[j+2]; + } + + dft768((int16_t *)x2128,(int16_t *)ytmp128,1); + dft768((int16_t *)(x2128+768),(int16_t *)(ytmp128+768),1); + dft768((int16_t *)(x2128+1536),(int16_t *)(ytmp128+1536),1); + + bfly3_tw1(ytmp128,ytmp128+768,ytmp128+1536,y128,y128+768,y128+1536); + + for (i=1,j=0; i<768; i++,j++) { + bfly3(ytmp128+i, + ytmp128+768+i, + ytmp128+1536+i, + y128+i, + y128+768+i, + y128+1536+i, + twa128+j, + twb128+j); + } + + if (scale_flag==1) { + norm128 = set1_int16(dft_norm_table[14]); + + for (i=0; i<2304; i++) { + y128[i] = mulhi_int16(y128[i],norm128); + } + } + + _mm_empty(); + _m_empty(); + +}; + +static int16_t twa2400[599*2*4]; +static int16_t twb2400[599*2*4]; +static int16_t twc2400[599*2*4]; + +void dft2400(int16_t *x,int16_t *y,unsigned char scale_flag) // 600 x 4 +{ + + int i,j; + simd_q15_t *x128=(simd_q15_t *)x; + simd_q15_t *y128=(simd_q15_t *)y; + simd_q15_t *twa128=(simd_q15_t *)&twa2400[0]; + simd_q15_t *twb128=(simd_q15_t *)&twb2400[0]; + simd_q15_t *twc128=(simd_q15_t *)&twc2400[0]; + simd_q15_t x2128[2400];// = (simd_q15_t *)&x2128array[0]; + simd_q15_t ytmp128[2400];//=&ytmp128array2[0]; + + + + for (i=0,j=0; i<600; i++,j+=4) { + x2128[i] = x128[j]; + x2128[i+600] = x128[j+1]; + x2128[i+1200] = x128[j+2]; + x2128[i+1800] = x128[j+3]; + } + + dft600((int16_t *)x2128,(int16_t *)ytmp128,1); + dft600((int16_t *)(x2128+600),(int16_t *)(ytmp128+600),1); + dft600((int16_t *)(x2128+1200),(int16_t *)(ytmp128+1200),1); + dft600((int16_t *)(x2128+1800),(int16_t *)(ytmp128+1800),1); + + bfly4_tw1(ytmp128,ytmp128+600,ytmp128+1200,ytmp128+1800,y128,y128+600,y128+1200,y128+1800); + + for (i=1,j=0; i<600; i++,j++) { + bfly4(ytmp128+i, + ytmp128+600+i, + ytmp128+1200+i, + ytmp128+1800+i, + y128+i, + y128+600+i, + y128+1200+i, + y128+1800+i, + twa128+j, + twb128+j, + twc128+j); + } + + if (scale_flag==1) { + norm128 = set1_int16(dft_norm_table[13]); + for (i=0; i<2400; i++) { + y128[i] = mulhi_int16(y128[i],norm128); + } + } + + _mm_empty(); + _m_empty(); + +}; + +static int16_t twa2592[863*2*4]; +static int16_t twb2592[863*2*4]; + +void dft2592(int16_t *x,int16_t *y,unsigned char scale_flag) // 864 x 3 +{ + int i,j; + simd_q15_t *x128=(simd_q15_t *)x; + simd_q15_t *y128=(simd_q15_t *)y; + simd_q15_t *twa128=(simd_q15_t *)&twa2592[0]; + simd_q15_t *twb128=(simd_q15_t *)&twb2592[0]; + simd_q15_t x2128[2592];// = (simd_q15_t *)&x2128array[0]; + simd_q15_t ytmp128[2592];//=&ytmp128array3[0]; + + + + for (i=0,j=0; i<864; i++,j+=3) { + x2128[i] = x128[j]; + x2128[i+864] = x128[j+1]; + x2128[i+1728] = x128[j+2]; + } + + dft864((int16_t *)x2128,(int16_t *)ytmp128,1); + dft864((int16_t *)(x2128+864),(int16_t *)(ytmp128+864),1); + dft864((int16_t *)(x2128+1728),(int16_t *)(ytmp128+1728),1); + + bfly3_tw1(ytmp128,ytmp128+864,ytmp128+1728,y128,y128+864,y128+1728); + + for (i=1,j=0; i<864; i++,j++) { + bfly3(ytmp128+i, + ytmp128+864+i, + ytmp128+1728+i, + y128+i, + y128+864+i, + y128+1728+i, + twa128+j, + twb128+j); + } + + if (scale_flag==1) { + norm128 = set1_int16(dft_norm_table[14]); + + for (i=0; i<2592; i++) { + y128[i] = mulhi_int16(y128[i],norm128); + } + } + + _mm_empty(); + _m_empty(); + +}; + +static int16_t twa2700[899*2*4]; +static int16_t twb2700[899*2*4]; + +void dft2700(int16_t *x,int16_t *y,unsigned char scale_flag) // 900 x 3 +{ + int i,j; + simd_q15_t *x128=(simd_q15_t *)x; + simd_q15_t *y128=(simd_q15_t *)y; + simd_q15_t *twa128=(simd_q15_t *)&twa2700[0]; + simd_q15_t *twb128=(simd_q15_t *)&twb2700[0]; + simd_q15_t x2128[2700];// = (simd_q15_t *)&x2128array[0]; + simd_q15_t ytmp128[2700];//=&ytmp128array3[0]; + + + + for (i=0,j=0; i<900; i++,j+=3) { + x2128[i] = x128[j]; + x2128[i+900] = x128[j+1]; + x2128[i+1800] = x128[j+2]; + } + + dft900((int16_t *)x2128,(int16_t *)ytmp128,1); + dft900((int16_t *)(x2128+900),(int16_t *)(ytmp128+900),1); + dft900((int16_t *)(x2128+1800),(int16_t *)(ytmp128+1800),1); + + bfly3_tw1(ytmp128,ytmp128+900,ytmp128+1800,y128,y128+900,y128+1800); + + for (i=1,j=0; i<900; i++,j++) { + bfly3(ytmp128+i, + ytmp128+900+i, + ytmp128+1800+i, + y128+i, + y128+900+i, + y128+1800+i, + twa128+j, + twb128+j); + } + + if (scale_flag==1) { + norm128 = set1_int16(dft_norm_table[14]); + + for (i=0; i<2700; i++) { + y128[i] = mulhi_int16(y128[i],norm128); + } + } + + _mm_empty(); + _m_empty(); + +}; + +static int16_t twa2880[959*2*4]; +static int16_t twb2880[959*2*4]; + +void dft2880(int16_t *x,int16_t *y,unsigned char scale_flag) // 960 x 3 +{ + int i,j; + simd_q15_t *x128=(simd_q15_t *)x; + simd_q15_t *y128=(simd_q15_t *)y; + simd_q15_t *twa128=(simd_q15_t *)&twa2880[0]; + simd_q15_t *twb128=(simd_q15_t *)&twb2880[0]; + simd_q15_t x2128[2880];// = (simd_q15_t *)&x2128array[0]; + simd_q15_t ytmp128[2880];//=&ytmp128array3[0]; + + + + for (i=0,j=0; i<960; i++,j+=3) { + x2128[i] = x128[j]; + x2128[i+960] = x128[j+1]; + x2128[i+1920] = x128[j+2]; + } + + dft960((int16_t *)x2128,(int16_t *)ytmp128,1); + dft960((int16_t *)(x2128+960),(int16_t *)(ytmp128+960),1); + dft960((int16_t *)(x2128+1920),(int16_t *)(ytmp128+1920),1); + + bfly3_tw1(ytmp128,ytmp128+960,ytmp128+1920,y128,y128+960,y128+1920); + + for (i=1,j=0; i<960; i++,j++) { + bfly3(ytmp128+i, + ytmp128+960+i, + ytmp128+1920+i, + y128+i, + y128+960+i, + y128+1920+i, + twa128+j, + twb128+j); + } + + if (scale_flag==1) { + norm128 = set1_int16(dft_norm_table[14]); + + for (i=0; i<2880; i++) { + y128[i] = mulhi_int16(y128[i],norm128); + } + } + + _mm_empty(); + _m_empty(); + +}; + +static int16_t twa2916[971*2*4]; +static int16_t twb2916[971*2*4]; + +void dft2916(int16_t *x,int16_t *y,unsigned char scale_flag) // 972 x 3 +{ + int i,j; + simd_q15_t *x128=(simd_q15_t *)x; + simd_q15_t *y128=(simd_q15_t *)y; + simd_q15_t *twa128=(simd_q15_t *)&twa2916[0]; + simd_q15_t *twb128=(simd_q15_t *)&twb2916[0]; + simd_q15_t x2128[2916];// = (simd_q15_t *)&x2128array[0]; + simd_q15_t ytmp128[2916];//=&ytmp128array3[0]; + + + + for (i=0,j=0; i<972; i++,j+=3) { + x2128[i] = x128[j]; + x2128[i+972] = x128[j+1]; + x2128[i+1944] = x128[j+2]; + } + + dft972((int16_t *)x2128,(int16_t *)ytmp128,1); + dft972((int16_t *)(x2128+972),(int16_t *)(ytmp128+972),1); + dft972((int16_t *)(x2128+1944),(int16_t *)(ytmp128+1944),1); + + bfly3_tw1(ytmp128,ytmp128+972,ytmp128+1944,y128,y128+972,y128+1944); + + for (i=1,j=0; i<972; i++,j++) { + bfly3(ytmp128+i, + ytmp128+972+i, + ytmp128+1944+i, + y128+i, + y128+972+i, + y128+1944+i, + twa128+j, + twb128+j); + } + + if (scale_flag==1) { + norm128 = set1_int16(dft_norm_table[14]); + + for (i=0; i<2916; i++) { + y128[i] = mulhi_int16(y128[i],norm128); + } + } + + _mm_empty(); + _m_empty(); + +}; + +static int16_t twa3000[599*8]__attribute__((aligned(32))); +static int16_t twb3000[599*8]__attribute__((aligned(32))); +static int16_t twc3000[599*8]__attribute__((aligned(32))); +static int16_t twd3000[599*8]__attribute__((aligned(32))); + +void dft3000(int16_t *x,int16_t *y,unsigned char scale_flag) // 600 * 5 +{ + + int i,j; + simd_q15_t *x128=(simd_q15_t *)x; + simd_q15_t *y128=(simd_q15_t *)y; + simd_q15_t *twa128=(simd_q15_t *)&twa3000[0]; + simd_q15_t *twb128=(simd_q15_t *)&twb3000[0]; + simd_q15_t *twc128=(simd_q15_t *)&twc3000[0]; + simd_q15_t *twd128=(simd_q15_t *)&twd3000[0]; + simd_q15_t x2128[3000];// = (simd_q15_t *)&x2128array[0]; + simd_q15_t ytmp128[3000];//=&ytmp128array2[0]; + + + + for (i=0,j=0; i<600; i++,j+=5) { + x2128[i] = x128[j]; + x2128[i+600] = x128[j+1]; + x2128[i+1200] = x128[j+2]; + x2128[i+1800] = x128[j+3]; + x2128[i+2400] = x128[j+4]; + } + + dft600((int16_t *)x2128,(int16_t *)ytmp128,1); + dft600((int16_t *)(x2128+600),(int16_t *)(ytmp128+600),1); + dft600((int16_t *)(x2128+1200),(int16_t *)(ytmp128+1200),1); + dft600((int16_t *)(x2128+1800),(int16_t *)(ytmp128+1800),1); + dft600((int16_t *)(x2128+2400),(int16_t *)(ytmp128+2400),1); + + bfly5_tw1(ytmp128,ytmp128+600,ytmp128+1200,ytmp128+1800,ytmp128+2400,y128,y128+600,y128+1200,y128+1800,y128+2400); + + for (i=1,j=0; i<600; i++,j++) { + bfly5(ytmp128+i, + ytmp128+600+i, + ytmp128+1200+i, + ytmp128+1800+i, + ytmp128+2400+i, + y128+i, + y128+600+i, + y128+1200+i, + y128+1800+i, + y128+2400+i, + twa128+j, + twb128+j, + twc128+j, + twd128+j); + } + + if (scale_flag==1) { + norm128 = set1_int16(dft_norm_table[15]); + + for (i=0; i<3000; i++) { + y128[i] = mulhi_int16(y128[i],norm128); + } + } + + _mm_empty(); + _m_empty(); + +} + +static int16_t twa3240[1079*2*4]; +static int16_t twb3240[1079*2*4]; + +void dft3240(int16_t *x,int16_t *y,unsigned char scale_flag) // 1080 x 3 +{ + int i,j; + simd_q15_t *x128=(simd_q15_t *)x; + simd_q15_t *y128=(simd_q15_t *)y; + simd_q15_t *twa128=(simd_q15_t *)&twa3240[0]; + simd_q15_t *twb128=(simd_q15_t *)&twb3240[0]; + simd_q15_t x2128[3240];// = (simd_q15_t *)&x2128array[0]; + simd_q15_t ytmp128[3240];//=&ytmp128array3[0]; + + + + for (i=0,j=0; i<1080; i++,j+=3) { + x2128[i] = x128[j]; + x2128[i+1080] = x128[j+1]; + x2128[i+2160] = x128[j+2]; + } + + dft1080((int16_t *)x2128,(int16_t *)ytmp128,1); + dft1080((int16_t *)(x2128+1080),(int16_t *)(ytmp128+1080),1); + dft1080((int16_t *)(x2128+2160),(int16_t *)(ytmp128+2160),1); + + bfly3_tw1(ytmp128,ytmp128+1080,ytmp128+2160,y128,y128+1080,y128+2160); + + for (i=1,j=0; i<1080; i++,j++) { + bfly3(ytmp128+i, + ytmp128+1080+i, + ytmp128+2160+i, + y128+i, + y128+1080+i, + y128+2160+i, + twa128+j, + twb128+j); + } + + if (scale_flag==1) { + norm128 = set1_int16(dft_norm_table[14]); + + for (i=0; i<3240; i++) { + y128[i] = mulhi_int16(y128[i],norm128); + } + } + + _mm_empty(); + _m_empty(); + +}; + void init_rad4(int N,int16_t *tw) { int16_t *twa = tw; @@ -9492,7 +10403,7 @@ void init_rad4_rep(int N,int16_t *twa,int16_t *twb,int16_t *twc) { int i,j; for (i=1;i<(N/4);i++) { - twa[0] = (int16_t)round(32767.0*cos(2*M_PI*i/N)); + twa[0] = (int16_t)round(32767.0*cos(2*M_PI*i/N)); twa[1] = -(int16_t)round(32767.0*sin(2*M_PI*i/N)); twb[0] = (int16_t)round(32767.0*cos(2*M_PI*2*i/N)); twb[1] = -(int16_t)round(32767.0*sin(2*M_PI*2*i/N)); @@ -9525,7 +10436,7 @@ void init_rad2_rep(int N,int16_t *twa) { int i,j; for (i=1;i<(N/2);i++) { - twa[0] = (int16_t)round(32767.0*cos(2*M_PI*i/N)); + twa[0] = (int16_t)round(32767.0*cos(2*M_PI*i/N)); twa[1] = -(int16_t)round(32767.0*sin(2*M_PI*i/N)); for (j=1;j<4;j++) { ((int32_t*)twa)[j]=((int32_t*)twa)[0]; @@ -9551,7 +10462,7 @@ void init_rad3_rep(int N,int16_t *twa,int16_t *twb) { int i,j; for (i=1;i<(N/3);i++) { - twa[0] = (int16_t)round(32767.0*cos(2*M_PI*i/N)); + twa[0] = (int16_t)round(32767.0*cos(2*M_PI*i/N)); twa[1] = -(int16_t)round(32767.0*sin(2*M_PI*i/N)); twb[0] = (int16_t)round(32767.0*cos(2*M_PI*2*i/N)); twb[1] = -(int16_t)round(32767.0*sin(2*M_PI*2*i/N)); @@ -9569,7 +10480,7 @@ void init_rad5_rep(int N,int16_t *twa,int16_t *twb,int16_t *twc,int16_t *twd) { int i,j; for (i=1;i<(N/5);i++) { - twa[0] = (int16_t)round(32767.0*cos(2*M_PI*i/N)); + twa[0] = (int16_t)round(32767.0*cos(2*M_PI*i/N)); twa[1] = -(int16_t)round(32767.0*sin(2*M_PI*i/N)); twb[0] = (int16_t)round(32767.0*cos(2*M_PI*2*i/N)); twb[1] = -(int16_t)round(32767.0*sin(2*M_PI*2*i/N)); @@ -9586,7 +10497,7 @@ void init_rad5_rep(int N,int16_t *twa,int16_t *twb,int16_t *twc,int16_t *twd) { twa+=8; twb+=8; twc+=8; - twd+=8; + twd+=8; } } /*----------------------------------------------------------------*/ @@ -9600,7 +10511,7 @@ int dfts_autoinit(void) init_rad2(8192,tw8192); init_rad4(16384,tw16384); init_rad2(32768,tw32768); - + init_rad3(1536,twa1536,twb1536); init_rad3(3072,twa3072,twb3072); init_rad3(6144,twa6144,twb6144); @@ -9645,6 +10556,24 @@ int dfts_autoinit(void) init_rad3_rep(1080,twa1080,twb1080); init_rad4_rep(1152,twa1152,twb1152,twc1152); init_rad4_rep(1200,twa1200,twb1200,twc1200); + init_rad3_rep(1296,twa1296,twb1296); + init_rad3_rep(1440,twa1440,twb1440); + init_rad5_rep(1500,twa1500,twb1500,twc1500,twd1500); + init_rad3_rep(1620,twa1620,twb1620); + init_rad3_rep(1728,twa1728,twb1728); + init_rad3_rep(1800,twa1800,twb1800); + init_rad4_rep(1920,twa1920,twb1920, twc1920); + init_rad3_rep(1944,twa1944,twb1944); + init_rad3_rep(2160,twa2160,twb2160); + init_rad3_rep(2304,twa2304,twb2304); + init_rad4_rep(2400,twa2400,twb2400,twc2400); + init_rad3_rep(2592,twa2592,twb2592); + init_rad3_rep(2700,twa2700,twb2700); + init_rad3_rep(2880,twa2880,twb2880); + init_rad3_rep(2916,twa2916,twb2916); + init_rad5_rep(3000,twa3000,twb3000,twc3000,twd3000); + init_rad3_rep(3240,twa3240,twb3240); + return 0; } diff --git a/openair1/PHY/TOOLS/tools_defs.h b/openair1/PHY/TOOLS/tools_defs.h index 12467e1fdc..db7ac3d813 100644 --- a/openair1/PHY/TOOLS/tools_defs.h +++ b/openair1/PHY/TOOLS/tools_defs.h @@ -226,9 +226,26 @@ void dft1024(int16_t *x,int16_t *y,uint8_t scale_flag); void dft1080(int16_t *x,int16_t *y,uint8_t scale_flag); void dft1152(int16_t *x,int16_t *y,uint8_t scale_flag); void dft1200(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft1296(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft1440(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft1500(int16_t *x,int16_t *y,uint8_t scale_flag); void dft1536(int16_t *sigF,int16_t *sig,uint8_t scale_flag); +void dft1620(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft1728(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft1800(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft1920(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft1944(int16_t *x,int16_t *y,uint8_t scale_flag); void dft2048(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft2160(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft2304(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft2400(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft2592(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft2700(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft2880(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft2916(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft3000(int16_t *x,int16_t *y,uint8_t scale_flag); void dft3072(int16_t *sigF,int16_t *sig,uint8_t scale_flag); +void dft3240(int16_t *x,int16_t *y,uint8_t scale_flag); void dft4096(int16_t *x,int16_t *y,uint8_t scale_flag); void dft6144(int16_t *sigF,int16_t *sig,uint8_t scale_flag); void dft8192(int16_t *x,int16_t *y,uint8_t scale_flag); @@ -283,21 +300,25 @@ typedef enum DFT_size_idx { DFT_108, DFT_120, DFT_128, DFT_144, DFT_180, DFT_192, DFT_216, DFT_240, DFT_256, DFT_288, DFT_300, DFT_324, DFT_360, DFT_384, DFT_432, DFT_480, DFT_512, DFT_540, DFT_576, DFT_600, DFT_648, DFT_720, DFT_768, DFT_864, - DFT_900, DFT_960, DFT_972, DFT_1024, DFT_1080, DFT_1152, DFT_1200, DFT_1536, - DFT_2048, DFT_3072, DFT_4096, DFT_6144, DFT_8192, DFT_9216, DFT_12288, DFT_18432, - DFT_24576, DFT_36864, DFT_49152, DFT_73728, DFT_98304, + DFT_900, DFT_960, DFT_972, DFT_1024, DFT_1080, DFT_1152, DFT_1200, DFT_1296, + DFT_1440, DFT_1500, DFT_1536, DFT_1620, DFT_1728, DFT_1800, DFT_1920, DFT_1944, + DFT_2048, DFT_2160, DFT_2304, DFT_2400, DFT_2592, DFT_2700, DFT_2880, DFT_2916, + DFT_3000, DFT_3072, DFT_3240, DFT_4096, DFT_6144, DFT_8192, DFT_9216, DFT_12288, + DFT_18432, DFT_24576, DFT_36864, DFT_49152, DFT_73728, DFT_98304, DFT_SIZE_IDXTABLESIZE } dft_size_idx_t; #ifdef OAIDFTS_MAIN adftfunc_t dft_ftab[]={ dft12, dft24, dft36, dft48, dft60, dft72, dft96, - dft108, dft120, dft128, dft144, dft180, dft192, dft216, dft240, + dft108, dft120, dft128, dft144, dft180, dft192, dft216, dft240, dft256, dft288, dft300, dft324, dft360, dft384, dft432, dft480, dft512, dft540, dft576, dft600, dft648, dft720, dft768, dft864, - dft900, dft960, dft972, dft1024, dft1080, dft1152, dft1200, dft1536, - dft2048, dft3072, dft4096, dft6144, dft8192, dft9216, dft12288, dft18432, - dft24576, dft36864, dft49152, dft73728, dft98304 + dft900, dft960, dft972, dft1024, dft1080, dft1152, dft1200, dft1296, + dft1440, dft1500, dft1536, dft1620, dft1728, dft1800, dft1920, dft1944, + dft2048, dft2160, dft2304, dft2400, dft2592, dft2700, dft2880, dft2916, + dft3000, dft3072, dft3240, dft4096, dft6144, dft8192, dft9216, dft12288, + dft18432, dft24576, dft36864, dft49152, dft73728, dft98304 }; #endif @@ -309,9 +330,9 @@ typedef enum idft_size_idx { } idft_size_idx_t; #ifdef OAIDFTS_MAIN aidftfunc_t idft_ftab[]={ - idft128, idft256, idft512, idft1024, idft1536, idft2048, idft3072, idft4096, - idft6144, idft8192, idft9216, idft12288, idft18432, idft24576, idft36864, idft49152, - idft73728, idft98304 + idft128, idft256, idft512, idft1024, idft1536, idft2048, idft3072, idft4096, + idft6144, idft8192, idft9216, idft12288, idft18432, idft24576, idft36864, idft49152, + idft73728, idft98304 }; #endif diff --git a/openair1/PHY/defs_gNB.h b/openair1/PHY/defs_gNB.h index 7b33b2040f..b7923adb0b 100644 --- a/openair1/PHY/defs_gNB.h +++ b/openair1/PHY/defs_gNB.h @@ -94,8 +94,6 @@ typedef struct { uint32_t frame; /// Subframe where current HARQ round was sent uint32_t subframe; - /// Index of current HARQ round for this DLSCH - uint8_t round; /// MIMO mode for this DLSCH MIMO_mode_t mimo_mode; /// Concatenated sequences @@ -138,8 +136,8 @@ typedef struct { } NR_gNB_SCH_STATS_t; typedef struct { - /// Pointers to 16 HARQ processes for the DLSCH - NR_DL_gNB_HARQ_t *harq_processes[NR_MAX_NB_HARQ_PROCESSES]; + /// Pointers to variables related to DLSCH harq process + NR_DL_gNB_HARQ_t harq_process; /// TX buffers for UE-spec transmission (antenna ports 5 or 7..14, prior to precoding) int32_t *txdataF[NR_MAX_NB_LAYERS]; /// Modulated symbols buffer @@ -834,6 +832,7 @@ typedef struct PHY_VARS_gNB_s { notifiedFIFO_t *respDecode; tpool_t *threadPool; int nbDecode; + uint8_t pusch_proc_threads; } PHY_VARS_gNB; diff --git a/openair1/PHY/defs_nr_UE.h b/openair1/PHY/defs_nr_UE.h index 5cf6115b32..390574a66b 100644 --- a/openair1/PHY/defs_nr_UE.h +++ b/openair1/PHY/defs_nr_UE.h @@ -20,7 +20,7 @@ */ /*! \file PHY/defs_nr_UE.h - \brief Top-level defines and structure definitions for nr ue + \brief Top-level constants and data structures definitions for NR UE \author Guy De Souza, H. WANG, A. Mico Pereperez \date 2018 \version 0.1 @@ -46,9 +46,8 @@ #include "common_lib.h" #include "msc.h" #include "fapi_nr_ue_interface.h" - -//#include #include "assertions.h" + #ifdef MEX #define msg mexPrintf #else @@ -79,9 +78,6 @@ #define openair_free(y,x) free((y)) #define PAGE_SIZE 4096 -//#define RX_NB_TH_MAX 3 -//#define RX_NB_TH 3 - #ifdef NR_UNIT_TEST #define FILE_NAME " " #define LINE_FILE (0) @@ -92,53 +88,19 @@ #define NR_TST_PHY_PRINTF(...) #endif -//#ifdef SHRLIBDEV -//extern int rxrescale; -//#define RX_IQRESCALELEN rxrescale -//#else -//#define RX_IQRESCALELEN 15 -//#endif - -//! \brief Allocate \c size bytes of memory on the heap with alignment 16 and zero it afterwards. -//! If no more memory is available, this function will terminate the program with an assertion error. -/*static inline void* malloc16_clear( size_t size ) -{ -#ifdef __AVX2__ - void* ptr = memalign(32, size); -#else - void* ptr = memalign(16, size); -#endif - DevAssert(ptr); - memset( ptr, 0, size ); - return ptr; -}*/ - - - #define PAGE_MASK 0xfffff000 #define virt_to_phys(x) (x) - #define openair_sched_exit() exit(-1) - -//#define max(a,b) ((a)>(b) ? (a) : (b)) -//#define min(a,b) ((a)<(b) ? (a) : (b)) - - #define bzero(s,n) (memset((s),0,(n))) - #define cmax(a,b) ((a>b) ? (a) : (b)) #define cmin(a,b) ((ac) ? (cmax(a,b)) : (c)) - /// suppress compiler warning for unused arguments #define UNUSED(x) (void)x; - #include "impl_defs_top.h" #include "impl_defs_nr.h" - #include "PHY/TOOLS/time_meas.h" #include "PHY/CODING/coding_defs.h" #include "PHY/TOOLS/tools_defs.h" @@ -146,20 +108,14 @@ #include "NR_UE_TRANSPORT/nr_transport_ue.h" #if defined(UPGRADE_RAT_NR) - #include "PHY/NR_REFSIG/ss_pbch_nr.h" - #endif #include "PHY/NR_UE_TRANSPORT/dci_nr.h" -//#include "PHY/LTE_TRANSPORT/defs.h" -//#include "PHY/NR_UE_TRANSPORT/defs_nr.h" #include - #include "targets/ARCH/COMMON/common_lib.h" - -/// Context data structure for eNB subframe processing +/// Context data structure for gNB subframe processing typedef struct { /// Component Carrier index uint8_t CC_id; @@ -177,9 +133,6 @@ typedef enum { #define debug_msg if (((mac_xface->frame%100) == 0) || (mac_xface->frame < 50)) msg typedef struct { - //unsigned int rx_power[NUMBER_OF_CONNECTED_eNB_MAX][NB_ANTENNAS_RX]; //! estimated received signal power (linear) - //unsigned short rx_power_dB[NUMBER_OF_CONNECTED_eNB_MAX][NB_ANTENNAS_RX]; //! estimated received signal power (dB) - //unsigned short rx_avg_power_dB[NUMBER_OF_CONNECTED_eNB_MAX]; //! estimated avg received signal power (dB) // RRC measurements uint32_t rssi; @@ -207,59 +160,59 @@ typedef struct { // UE measurements //! estimated received spatial signal power (linear) - int rx_spatial_power[NUMBER_OF_CONNECTED_eNB_MAX][2][2]; + int rx_spatial_power[NUMBER_OF_CONNECTED_gNB_MAX][2][2]; //! estimated received spatial signal power (dB) - unsigned short rx_spatial_power_dB[NUMBER_OF_CONNECTED_eNB_MAX][2][2]; + unsigned short rx_spatial_power_dB[NUMBER_OF_CONNECTED_gNB_MAX][2][2]; /// estimated received signal power (sum over all TX antennas) - int rx_power[NUMBER_OF_CONNECTED_eNB_MAX][NB_ANTENNAS_RX]; + int rx_power[NUMBER_OF_CONNECTED_gNB_MAX][NB_ANTENNAS_RX]; /// estimated received signal power (sum over all TX antennas) - unsigned short rx_power_dB[NUMBER_OF_CONNECTED_eNB_MAX][NB_ANTENNAS_RX]; + unsigned short rx_power_dB[NUMBER_OF_CONNECTED_gNB_MAX][NB_ANTENNAS_RX]; /// estimated received signal power (sum over all TX/RX antennas) - int rx_power_tot[NUMBER_OF_CONNECTED_eNB_MAX]; //NEW + int rx_power_tot[NUMBER_OF_CONNECTED_gNB_MAX]; //NEW /// estimated received signal power (sum over all TX/RX antennas) - unsigned short rx_power_tot_dB[NUMBER_OF_CONNECTED_eNB_MAX]; //NEW + unsigned short rx_power_tot_dB[NUMBER_OF_CONNECTED_gNB_MAX]; //NEW //! estimated received signal power (sum of all TX/RX antennas, time average) - int rx_power_avg[NUMBER_OF_CONNECTED_eNB_MAX]; + int rx_power_avg[NUMBER_OF_CONNECTED_gNB_MAX]; //! estimated received signal power (sum of all TX/RX antennas, time average, in dB) - unsigned short rx_power_avg_dB[NUMBER_OF_CONNECTED_eNB_MAX]; + unsigned short rx_power_avg_dB[NUMBER_OF_CONNECTED_gNB_MAX]; /// SINR (sum of all TX/RX antennas, in dB) - int wideband_cqi_tot[NUMBER_OF_CONNECTED_eNB_MAX]; + int wideband_cqi_tot[NUMBER_OF_CONNECTED_gNB_MAX]; /// SINR (sum of all TX/RX antennas, time average, in dB) - int wideband_cqi_avg[NUMBER_OF_CONNECTED_eNB_MAX]; + int wideband_cqi_avg[NUMBER_OF_CONNECTED_gNB_MAX]; //! estimated rssi (dBm) - short rx_rssi_dBm[NUMBER_OF_CONNECTED_eNB_MAX]; + short rx_rssi_dBm[NUMBER_OF_CONNECTED_gNB_MAX]; //! estimated correlation (wideband linear) between spatial channels (computed in dlsch_demodulation) - int rx_correlation[NUMBER_OF_CONNECTED_eNB_MAX][2]; + int rx_correlation[NUMBER_OF_CONNECTED_gNB_MAX][2]; //! estimated correlation (wideband dB) between spatial channels (computed in dlsch_demodulation) - int rx_correlation_dB[NUMBER_OF_CONNECTED_eNB_MAX][2]; + int rx_correlation_dB[NUMBER_OF_CONNECTED_gNB_MAX][2]; /// Wideband CQI (sum of all RX antennas, in dB, for precoded transmission modes (3,4,5,6), up to 4 spatial streams) - int precoded_cqi_dB[NUMBER_OF_CONNECTED_eNB_MAX+1][4]; + int precoded_cqi_dB[NUMBER_OF_CONNECTED_gNB_MAX+1][4]; /// Subband CQI per RX antenna (= SINR) - int subband_cqi[NUMBER_OF_CONNECTED_eNB_MAX][NB_ANTENNAS_RX][NUMBER_OF_SUBBANDS_MAX]; + int subband_cqi[NUMBER_OF_CONNECTED_gNB_MAX][NB_ANTENNAS_RX][NUMBER_OF_SUBBANDS_MAX]; /// Total Subband CQI (= SINR) - int subband_cqi_tot[NUMBER_OF_CONNECTED_eNB_MAX][NUMBER_OF_SUBBANDS_MAX]; + int subband_cqi_tot[NUMBER_OF_CONNECTED_gNB_MAX][NUMBER_OF_SUBBANDS_MAX]; /// Subband CQI in dB (= SINR dB) - int subband_cqi_dB[NUMBER_OF_CONNECTED_eNB_MAX][NB_ANTENNAS_RX][NUMBER_OF_SUBBANDS_MAX]; + int subband_cqi_dB[NUMBER_OF_CONNECTED_gNB_MAX][NB_ANTENNAS_RX][NUMBER_OF_SUBBANDS_MAX]; /// Total Subband CQI - int subband_cqi_tot_dB[NUMBER_OF_CONNECTED_eNB_MAX][NUMBER_OF_SUBBANDS_MAX]; + int subband_cqi_tot_dB[NUMBER_OF_CONNECTED_gNB_MAX][NUMBER_OF_SUBBANDS_MAX]; /// Wideband PMI for each RX antenna - int wideband_pmi_re[NUMBER_OF_CONNECTED_eNB_MAX][NB_ANTENNAS_RX]; + int wideband_pmi_re[NUMBER_OF_CONNECTED_gNB_MAX][NB_ANTENNAS_RX]; /// Wideband PMI for each RX antenna - int wideband_pmi_im[NUMBER_OF_CONNECTED_eNB_MAX][NB_ANTENNAS_RX]; + int wideband_pmi_im[NUMBER_OF_CONNECTED_gNB_MAX][NB_ANTENNAS_RX]; ///Subband PMI for each RX antenna - int subband_pmi_re[NUMBER_OF_CONNECTED_eNB_MAX][NUMBER_OF_SUBBANDS_MAX][NB_ANTENNAS_RX]; + int subband_pmi_re[NUMBER_OF_CONNECTED_gNB_MAX][NUMBER_OF_SUBBANDS_MAX][NB_ANTENNAS_RX]; ///Subband PMI for each RX antenna - int subband_pmi_im[NUMBER_OF_CONNECTED_eNB_MAX][NUMBER_OF_SUBBANDS_MAX][NB_ANTENNAS_RX]; + int subband_pmi_im[NUMBER_OF_CONNECTED_gNB_MAX][NUMBER_OF_SUBBANDS_MAX][NB_ANTENNAS_RX]; /// chosen RX antennas (1=Rx antenna 1, 2=Rx antenna 2, 3=both Rx antennas) - unsigned char selected_rx_antennas[NUMBER_OF_CONNECTED_eNB_MAX][NUMBER_OF_SUBBANDS_MAX]; + unsigned char selected_rx_antennas[NUMBER_OF_CONNECTED_gNB_MAX][NUMBER_OF_SUBBANDS_MAX]; /// Wideband Rank indication - unsigned char rank[NUMBER_OF_CONNECTED_eNB_MAX]; + unsigned char rank[NUMBER_OF_CONNECTED_gNB_MAX]; /// Number of RX Antennas unsigned char nb_antennas_rx; /// DLSCH error counter @@ -379,7 +332,7 @@ typedef struct { int32_t **dl_ch_magb1[8][8]; /// \brief Magnitude of Downlink Channel, first layer (256QAM level). int32_t **dl_ch_magr0; - /// \brief Cross-correlation of two eNB signals. + /// \brief Cross-correlation of two gNB signals. /// - first index: rx antenna [0..nb_antennas_rx[ /// - second index: symbol [0..] int32_t **rho; @@ -647,11 +600,11 @@ typedef struct { /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx /// - second index: ? [0..168*N_RB_DL[ int32_t **dl_ch_estimates_ext; - /// \brief Pointers to channel cross-correlation vectors for multi-eNB detection. + /// \brief Pointers to channel cross-correlation vectors for multi-gNB detection. /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx /// - second index: ? [0..168*N_RB_DL[ int32_t **dl_ch_rho_ext; - /// \brief Pointers to channel cross-correlation vectors for multi-eNB detection. + /// \brief Pointers to channel cross-correlation vectors for multi-gNB detection. /// - first index: rx antenna [0..nb_antennas_rx[ /// - second index: ? [0..] int32_t **rho; @@ -748,7 +701,6 @@ typedef struct { int16_t *prachF; int16_t *prach; fapi_nr_ul_config_prach_pdu prach_pdu; - uint8_t prach_Config_enabled; } NR_UE_PRACH; // structure used for multiple SSB detection @@ -785,7 +737,7 @@ typedef struct NR_UL_TIME_ALIGNMENT { int16_t ta_frame; char ta_slot; /// TA command and TAGID received from the gNB - uint8_t ta_command; + uint16_t ta_command; uint8_t tag_id; } NR_UL_TIME_ALIGNMENT_t; @@ -832,8 +784,8 @@ typedef struct { int tx_total_RE[NR_MAX_SLOTS_PER_FRAME]; /// \brief Maximum transmit power int8_t tx_power_max_dBm; - /// \brief Number of eNB seen by UE - uint8_t n_connected_eNB; + /// \brief Number of gNB seen by UE + uint8_t n_connected_gNB; /// \brief indicator that Handover procedure has been initiated uint8_t ho_initiated; /// \brief indicator that Handover procedure has been triggered @@ -849,33 +801,18 @@ typedef struct { fapi_nr_config_request_t nrUE_config; - // the following structures are not part of PHY_vars_UE anymore as it is not thread safe. They are now on the stack of the functions that actually need them - - //nr_downlink_indication_t dl_indication; - //nr_uplink_indication_t ul_indication; - /// UE FAPI DCI request - //nr_dcireq_t dcireq; - - // pointers to the next 2 strcutres are also included in dl_indictation - /// UE FAPI indication for DLSCH reception - //fapi_nr_rx_indication_t rx_ind; - /// UE FAPI indication for DCI reception - //fapi_nr_dci_indication_t dci_ind; - t_nrPolar_params *polarList; - NR_UE_PDSCH *pdsch_vars[RX_NB_TH_MAX][NUMBER_OF_CONNECTED_eNB_MAX+1]; // two RxTx Threads - NR_UE_PBCH *pbch_vars[NUMBER_OF_CONNECTED_eNB_MAX]; - NR_UE_PDCCH *pdcch_vars[RX_NB_TH_MAX][NUMBER_OF_CONNECTED_eNB_MAX]; - NR_UE_PRACH *prach_vars[NUMBER_OF_CONNECTED_eNB_MAX]; - NR_UE_PUSCH *pusch_vars[RX_NB_TH_MAX][NUMBER_OF_CONNECTED_eNB_MAX]; - NR_UE_DLSCH_t *dlsch[RX_NB_TH_MAX][NUMBER_OF_CONNECTED_eNB_MAX][NR_MAX_NB_CODEWORDS]; // two RxTx Threads - NR_UE_ULSCH_t *ulsch[RX_NB_TH_MAX][NUMBER_OF_CONNECTED_eNB_MAX][NR_MAX_NB_CODEWORDS]; // two code words - NR_UE_DLSCH_t *dlsch_SI[NUMBER_OF_CONNECTED_eNB_MAX]; - NR_UE_DLSCH_t *dlsch_ra[NUMBER_OF_CONNECTED_eNB_MAX]; - NR_UE_DLSCH_t *dlsch_p[NUMBER_OF_CONNECTED_eNB_MAX]; - NR_UE_DLSCH_t *dlsch_MCH[NUMBER_OF_CONNECTED_eNB_MAX]; - // This is for SIC in the UE, to store the reencoded data - LTE_eNB_DLSCH_t *dlsch_eNB[NUMBER_OF_CONNECTED_eNB_MAX]; + NR_UE_PDSCH *pdsch_vars[RX_NB_TH_MAX][NUMBER_OF_CONNECTED_gNB_MAX+1]; // two RxTx Threads + NR_UE_PBCH *pbch_vars[NUMBER_OF_CONNECTED_gNB_MAX]; + NR_UE_PDCCH *pdcch_vars[RX_NB_TH_MAX][NUMBER_OF_CONNECTED_gNB_MAX]; + NR_UE_PRACH *prach_vars[NUMBER_OF_CONNECTED_gNB_MAX]; + NR_UE_PUSCH *pusch_vars[RX_NB_TH_MAX][NUMBER_OF_CONNECTED_gNB_MAX]; + NR_UE_DLSCH_t *dlsch[RX_NB_TH_MAX][NUMBER_OF_CONNECTED_gNB_MAX][NR_MAX_NB_CODEWORDS]; // two RxTx Threads + NR_UE_ULSCH_t *ulsch[RX_NB_TH_MAX][NUMBER_OF_CONNECTED_gNB_MAX][NR_MAX_NB_CODEWORDS]; // two code words + NR_UE_DLSCH_t *dlsch_SI[NUMBER_OF_CONNECTED_gNB_MAX]; + NR_UE_DLSCH_t *dlsch_ra[NUMBER_OF_CONNECTED_gNB_MAX]; + NR_UE_DLSCH_t *dlsch_p[NUMBER_OF_CONNECTED_gNB_MAX]; + NR_UE_DLSCH_t *dlsch_MCH[NUMBER_OF_CONNECTED_gNB_MAX]; //Paging parameters uint32_t IMSImod1024; @@ -916,52 +853,47 @@ typedef struct { uint32_t high_speed_flag; uint32_t perfect_ce; int16_t ch_est_alpha; - int generate_ul_signal[NUMBER_OF_CONNECTED_eNB_MAX]; + int generate_ul_signal[NUMBER_OF_CONNECTED_gNB_MAX]; UE_NR_SCAN_INFO_t scan_info[NB_BANDS_MAX]; - char ulsch_no_allocation_counter[NUMBER_OF_CONNECTED_eNB_MAX]; - - unsigned char ulsch_Msg3_active[NUMBER_OF_CONNECTED_gNB_MAX]; + char ulsch_no_allocation_counter[NUMBER_OF_CONNECTED_gNB_MAX]; NR_PRACH_RESOURCES_t *prach_resources[NUMBER_OF_CONNECTED_gNB_MAX]; int turbo_iterations, turbo_cntl_iterations; /// \brief ?. - /// - first index: eNB [0..NUMBER_OF_CONNECTED_eNB_MAX[ (hard coded) - uint32_t total_TBS[NUMBER_OF_CONNECTED_eNB_MAX]; + /// - first index: gNB [0..NUMBER_OF_CONNECTED_gNB_MAX[ (hard coded) + uint32_t total_TBS[NUMBER_OF_CONNECTED_gNB_MAX]; /// \brief ?. - /// - first index: eNB [0..NUMBER_OF_CONNECTED_eNB_MAX[ (hard coded) - uint32_t total_TBS_last[NUMBER_OF_CONNECTED_eNB_MAX]; + /// - first index: gNB [0..NUMBER_OF_CONNECTED_gNB_MAX[ (hard coded) + uint32_t total_TBS_last[NUMBER_OF_CONNECTED_gNB_MAX]; /// \brief ?. - /// - first index: eNB [0..NUMBER_OF_CONNECTED_eNB_MAX[ (hard coded) - uint32_t bitrate[NUMBER_OF_CONNECTED_eNB_MAX]; + /// - first index: gNB [0..NUMBER_OF_CONNECTED_gNB_MAX[ (hard coded) + uint32_t bitrate[NUMBER_OF_CONNECTED_gNB_MAX]; /// \brief ?. - /// - first index: eNB [0..NUMBER_OF_CONNECTED_eNB_MAX[ (hard coded) - uint32_t total_received_bits[NUMBER_OF_CONNECTED_eNB_MAX]; - int dlsch_errors[NUMBER_OF_CONNECTED_eNB_MAX]; - int dlsch_errors_last[NUMBER_OF_CONNECTED_eNB_MAX]; - int dlsch_received[NUMBER_OF_CONNECTED_eNB_MAX]; - int dlsch_received_last[NUMBER_OF_CONNECTED_eNB_MAX]; - int dlsch_fer[NUMBER_OF_CONNECTED_eNB_MAX]; - int dlsch_SI_received[NUMBER_OF_CONNECTED_eNB_MAX]; - int dlsch_SI_errors[NUMBER_OF_CONNECTED_eNB_MAX]; - int dlsch_ra_received[NUMBER_OF_CONNECTED_eNB_MAX]; - int dlsch_ra_errors[NUMBER_OF_CONNECTED_eNB_MAX]; - int dlsch_p_received[NUMBER_OF_CONNECTED_eNB_MAX]; - int dlsch_p_errors[NUMBER_OF_CONNECTED_eNB_MAX]; - int dlsch_mch_received_sf[MAX_MBSFN_AREA][NUMBER_OF_CONNECTED_eNB_MAX]; - int dlsch_mch_received[NUMBER_OF_CONNECTED_eNB_MAX]; - int dlsch_mcch_received[MAX_MBSFN_AREA][NUMBER_OF_CONNECTED_eNB_MAX]; - int dlsch_mtch_received[MAX_MBSFN_AREA][NUMBER_OF_CONNECTED_eNB_MAX]; - int dlsch_mcch_errors[MAX_MBSFN_AREA][NUMBER_OF_CONNECTED_eNB_MAX]; - int dlsch_mtch_errors[MAX_MBSFN_AREA][NUMBER_OF_CONNECTED_eNB_MAX]; - int dlsch_mcch_trials[MAX_MBSFN_AREA][NUMBER_OF_CONNECTED_eNB_MAX]; - int dlsch_mtch_trials[MAX_MBSFN_AREA][NUMBER_OF_CONNECTED_eNB_MAX]; - int current_dlsch_cqi[NUMBER_OF_CONNECTED_eNB_MAX]; - unsigned char first_run_timing_advance[NUMBER_OF_CONNECTED_eNB_MAX]; - uint8_t prach_cnt; - uint8_t prach_PreambleIndex; - // uint8_t prach_timer; + /// - first index: gNB [0..NUMBER_OF_CONNECTED_gNB_MAX[ (hard coded) + uint32_t total_received_bits[NUMBER_OF_CONNECTED_gNB_MAX]; + int dlsch_errors[NUMBER_OF_CONNECTED_gNB_MAX]; + int dlsch_errors_last[NUMBER_OF_CONNECTED_gNB_MAX]; + int dlsch_received[NUMBER_OF_CONNECTED_gNB_MAX]; + int dlsch_received_last[NUMBER_OF_CONNECTED_gNB_MAX]; + int dlsch_fer[NUMBER_OF_CONNECTED_gNB_MAX]; + int dlsch_SI_received[NUMBER_OF_CONNECTED_gNB_MAX]; + int dlsch_SI_errors[NUMBER_OF_CONNECTED_gNB_MAX]; + int dlsch_ra_received[NUMBER_OF_CONNECTED_gNB_MAX]; + int dlsch_ra_errors[NUMBER_OF_CONNECTED_gNB_MAX]; + int dlsch_p_received[NUMBER_OF_CONNECTED_gNB_MAX]; + int dlsch_p_errors[NUMBER_OF_CONNECTED_gNB_MAX]; + int dlsch_mch_received_sf[MAX_MBSFN_AREA][NUMBER_OF_CONNECTED_gNB_MAX]; + int dlsch_mch_received[NUMBER_OF_CONNECTED_gNB_MAX]; + int dlsch_mcch_received[MAX_MBSFN_AREA][NUMBER_OF_CONNECTED_gNB_MAX]; + int dlsch_mtch_received[MAX_MBSFN_AREA][NUMBER_OF_CONNECTED_gNB_MAX]; + int dlsch_mcch_errors[MAX_MBSFN_AREA][NUMBER_OF_CONNECTED_gNB_MAX]; + int dlsch_mtch_errors[MAX_MBSFN_AREA][NUMBER_OF_CONNECTED_gNB_MAX]; + int dlsch_mcch_trials[MAX_MBSFN_AREA][NUMBER_OF_CONNECTED_gNB_MAX]; + int dlsch_mtch_trials[MAX_MBSFN_AREA][NUMBER_OF_CONNECTED_gNB_MAX]; + int current_dlsch_cqi[NUMBER_OF_CONNECTED_gNB_MAX]; + unsigned char first_run_timing_advance[NUMBER_OF_CONNECTED_gNB_MAX]; uint8_t decode_SIB; uint8_t decode_MIB; uint8_t init_sync_frame; @@ -980,9 +912,9 @@ typedef struct { /// Flag to tell if UE is secondary user (cognitive mode) unsigned char is_secondary_ue; - /// Flag to tell if secondary eNB has channel estimates to create NULL-beams from. + /// Flag to tell if secondary gNB has channel estimates to create NULL-beams from. unsigned char has_valid_precoder; - /// hold the precoder for NULL beam to the primary eNB + /// hold the precoder for NULL beam to the primary gNB int **ul_precoder_S_UE; /// holds the maximum channel/precoder coefficient char log2_maxp; @@ -1008,17 +940,17 @@ typedef struct { double N0; /// PDSCH Varaibles - PDSCH_CONFIG_DEDICATED pdsch_config_dedicated[NUMBER_OF_CONNECTED_eNB_MAX]; + PDSCH_CONFIG_DEDICATED pdsch_config_dedicated[NUMBER_OF_CONNECTED_gNB_MAX]; /// PUSCH Varaibles - PUSCH_CONFIG_DEDICATED pusch_config_dedicated[NUMBER_OF_CONNECTED_eNB_MAX]; + PUSCH_CONFIG_DEDICATED pusch_config_dedicated[NUMBER_OF_CONNECTED_gNB_MAX]; /// PUSCH contention-based access vars PUSCH_CA_CONFIG_DEDICATED pusch_ca_config_dedicated[NUMBER_OF_eNB_MAX]; // lola /// PUCCH variables - PUCCH_CONFIG_DEDICATED pucch_config_dedicated[NUMBER_OF_CONNECTED_eNB_MAX]; + PUCCH_CONFIG_DEDICATED pucch_config_dedicated[NUMBER_OF_CONNECTED_gNB_MAX]; //#if defined(UPGRADE_RAT_NR) #if 1 @@ -1029,8 +961,8 @@ typedef struct { PDSCH_ServingCellConfig_t PDSCH_ServingCellConfig; PDSCH_Config_t PDSCH_Config; - PUCCH_ConfigCommon_nr_t pucch_config_common_nr[NUMBER_OF_CONNECTED_eNB_MAX]; - PUCCH_Config_t pucch_config_dedicated_nr[NUMBER_OF_CONNECTED_eNB_MAX]; + PUCCH_ConfigCommon_nr_t pucch_config_common_nr[NUMBER_OF_CONNECTED_gNB_MAX]; + PUCCH_Config_t pucch_config_dedicated_nr[NUMBER_OF_CONNECTED_gNB_MAX]; PUSCH_Config_t pusch_config; SRS_NR srs; @@ -1046,29 +978,29 @@ typedef struct { uint8_t ncs_cell[20][7]; /// UL-POWER-Control - UL_POWER_CONTROL_DEDICATED ul_power_control_dedicated[NUMBER_OF_CONNECTED_eNB_MAX]; + UL_POWER_CONTROL_DEDICATED ul_power_control_dedicated[NUMBER_OF_CONNECTED_gNB_MAX]; /// TPC - TPC_PDCCH_CONFIG tpc_pdcch_config_pucch[NUMBER_OF_CONNECTED_eNB_MAX]; - TPC_PDCCH_CONFIG tpc_pdcch_config_pusch[NUMBER_OF_CONNECTED_eNB_MAX]; + TPC_PDCCH_CONFIG tpc_pdcch_config_pucch[NUMBER_OF_CONNECTED_gNB_MAX]; + TPC_PDCCH_CONFIG tpc_pdcch_config_pusch[NUMBER_OF_CONNECTED_gNB_MAX]; /// CQI reporting - CQI_REPORT_CONFIG cqi_report_config[NUMBER_OF_CONNECTED_eNB_MAX]; + CQI_REPORT_CONFIG cqi_report_config[NUMBER_OF_CONNECTED_gNB_MAX]; /// SRS Variables - SOUNDINGRS_UL_CONFIG_DEDICATED soundingrs_ul_config_dedicated[NUMBER_OF_CONNECTED_eNB_MAX]; + SOUNDINGRS_UL_CONFIG_DEDICATED soundingrs_ul_config_dedicated[NUMBER_OF_CONNECTED_gNB_MAX]; /// Scheduling Request Config - SCHEDULING_REQUEST_CONFIG scheduling_request_config[NUMBER_OF_CONNECTED_eNB_MAX]; + SCHEDULING_REQUEST_CONFIG scheduling_request_config[NUMBER_OF_CONNECTED_gNB_MAX]; //#if defined(UPGRADE_RAT_NR) #if 1 - scheduling_request_config_t scheduling_request_config_nr[NUMBER_OF_CONNECTED_eNB_MAX]; + scheduling_request_config_t scheduling_request_config_nr[NUMBER_OF_CONNECTED_gNB_MAX]; #endif - /// Transmission mode per eNB - uint8_t transmission_mode[NUMBER_OF_CONNECTED_eNB_MAX]; + /// Transmission mode per gNB + uint8_t transmission_mode[NUMBER_OF_CONNECTED_gNB_MAX]; time_stats_t phy_proc[RX_NB_TH]; time_stats_t phy_proc_tx; @@ -1137,7 +1069,6 @@ typedef struct { } PHY_VARS_NR_UE; - /* this structure is used to pass both UE phy vars and * proc to the function UE_thread_rxn_txnp4 */ @@ -1146,76 +1077,5 @@ typedef struct nr_rxtx_thread_data_s { PHY_VARS_NR_UE *UE; } nr_rxtx_thread_data_t; -/*static inline int wait_on_condition(pthread_mutex_t *mutex,pthread_cond_t *cond,int *instance_cnt,char *name) { - - if (pthread_mutex_lock(mutex) != 0) { - LOG_E( PHY, "[SCHED][eNB] error locking mutex for %s\n",name); - exit_fun("nothing to add"); - return(-1); - } - - while (*instance_cnt < 0) { - // most of the time the thread is waiting here - // proc->instance_cnt_rxtx is -1 - pthread_cond_wait(cond,mutex); // this unlocks mutex_rxtx while waiting and then locks it again - } - - if (pthread_mutex_unlock(mutex) != 0) { - LOG_E(PHY,"[SCHED][eNB] error unlocking mutex for %s\n",name); - exit_fun("nothing to add"); - return(-1); - } - return(0); -} - -static inline int wait_on_busy_condition(pthread_mutex_t *mutex,pthread_cond_t *cond,int *instance_cnt,char *name) { - - if (pthread_mutex_lock(mutex) != 0) { - LOG_E( PHY, "[SCHED][eNB] error locking mutex for %s\n",name); - exit_fun("nothing to add"); - return(-1); - } - - while (*instance_cnt == 0) { - // most of the time the thread will skip this - // waits only if proc->instance_cnt_rxtx is 0 - pthread_cond_wait(cond,mutex); // this unlocks mutex_rxtx while waiting and then locks it again - } - - if (pthread_mutex_unlock(mutex) != 0) { - LOG_E(PHY,"[SCHED][eNB] error unlocking mutex for %s\n",name); - exit_fun("nothing to add"); - return(-1); - } - return(0); -} - -static inline int release_thread(pthread_mutex_t *mutex,int *instance_cnt,char *name) { - - if (pthread_mutex_lock(mutex) != 0) { - LOG_E( PHY, "[SCHED][eNB] error locking mutex for %s\n",name); - exit_fun("nothing to add"); - return(-1); - } - - *instance_cnt=*instance_cnt-1; - - if (pthread_mutex_unlock(mutex) != 0) { - LOG_E( PHY, "[SCHED][eNB] error unlocking mutex for %s\n",name); - exit_fun("nothing to add"); - return(-1); - } - return(0); -} -*/ - - -/* -#include "PHY/INIT/defs.h" -#include "PHY/LTE_REFSIG/defs.h" -#include "PHY/MODULATION/defs.h" -#include "PHY/LTE_TRANSPORT/proto.h" -#include "PHY/LTE_ESTIMATION/defs.h" -*/ #include "SIMULATION/ETH_TRANSPORT/defs.h" #endif diff --git a/openair1/PHY/defs_nr_common.h b/openair1/PHY/defs_nr_common.h index d1d47e0391..18c7dd413b 100644 --- a/openair1/PHY/defs_nr_common.h +++ b/openair1/PHY/defs_nr_common.h @@ -89,7 +89,7 @@ #define NR_MAX_NUM_BWP 4 -#define NR_MAX_PDCCH_AGG_LEVEL 16 +#define NR_MAX_PDCCH_AGG_LEVEL 16 // 3GPP TS 38.211 V15.8 Section 7.3.2 Table 7.3.2.1-1: Supported PDCCH aggregation levels #define NR_MAX_CSET_DURATION 3 #define NR_MAX_NB_RBG 18 @@ -150,6 +150,11 @@ typedef enum { MOD_QAM256 }nr_mod_t; +typedef enum { + RA_2STEP = 0, + RA_4STEP +} nr_ra_type_e; + typedef struct { /// Size of first RBG uint8_t start_size; @@ -205,8 +210,12 @@ typedef struct { uint16_t prach_format; /// Preamble index for PRACH (0-63) uint8_t ra_PreambleIndex; - /// RACH MaskIndex - uint8_t ra_RACH_MaskIndex; + /// Preamble Tx Counter + uint8_t RA_PREAMBLE_TRANSMISSION_COUNTER; + /// Preamble Power Ramping Counter + uint8_t RA_PREAMBLE_POWER_RAMPING_COUNTER; + /// 2-step RA power offset + int POWER_OFFSET_2STEP_RA; /// Target received power at gNB. Baseline is range -202..-60 dBm. Depends on delta preamble, power ramping counter and step. int ra_PREAMBLE_RECEIVED_TARGET_POWER; /// PRACH index for TDD (0 ... 6) depending on TDD configuration and prachConfigIndex @@ -217,8 +226,10 @@ typedef struct { uint8_t RA_PREAMBLE_BACKOFF; /// uint8_t RA_SCALING_FACTOR_BI; - /// - uint8_t RA_PCMAX; + /// Indicating whether it is 2-step or 4-step RA + nr_ra_type_e RA_TYPE; + /// UE configured maximum output power + int RA_PCMAX; /// Corresponding RA-RNTI for UL-grant uint16_t ra_RNTI; /// Pointer to Msg3 payload for UL-grant diff --git a/openair1/PHY/phy_extern_nr_ue.h b/openair1/PHY/phy_extern_nr_ue.h index e06b0c913a..700419c61c 100644 --- a/openair1/PHY/phy_extern_nr_ue.h +++ b/openair1/PHY/phy_extern_nr_ue.h @@ -25,6 +25,11 @@ #include "PHY/defs_nr_UE.h" //#include "common/ran_context.h" +#ifdef XFORMS + #include "PHY/TOOLS/nr_phy_scope.h" + extern char do_forms; +#endif + extern char* namepointer_chMag ; extern char* namepointer_log2; extern char fmageren_name2[512]; @@ -109,5 +114,8 @@ extern unsigned short Nb_81_110[8][4]; extern uint16_t hundred_times_log10_NPRB[100]; extern uint8_t alpha_lut[8]; extern uint8_t max_turbo_iterations; + +extern double cpuf; + #endif /*__PHY_EXTERN_H__ */ diff --git a/openair1/SCHED/fapi_l1.h b/openair1/SCHED/fapi_l1.h index 4da1fa63ec..6b9121e17f 100644 --- a/openair1/SCHED/fapi_l1.h +++ b/openair1/SCHED/fapi_l1.h @@ -31,6 +31,7 @@ */ #include "PHY/defs_eNB.h" +#include "PHY/defs_gNB.h" #include "PHY/phy_extern.h" #include "PHY/LTE_TRANSPORT/transport_proto.h" #include "SCHED/sched_eNB.h" diff --git a/openair1/SCHED/nfapi_lte_dummy.c b/openair1/SCHED/nfapi_lte_dummy.c new file mode 100644 index 0000000000..9562e2de30 --- /dev/null +++ b/openair1/SCHED/nfapi_lte_dummy.c @@ -0,0 +1,50 @@ +//Dummy NR defs to avoid linking errors + +#include "PHY/defs_gNB.h" +#include "nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h" +#include "openair2/NR_PHY_INTERFACE/NR_IF_Module.h" +#include "openair1/PHY/LTE_TRANSPORT/transport_common.h" + +void handle_nfapi_nr_pdcch_pdu(PHY_VARS_gNB *gNB, + int frame, int slot, + nfapi_nr_dl_tti_pdcch_pdu *pdcch_pdu){} + +void handle_nr_nfapi_ssb_pdu(PHY_VARS_gNB *gNB,int frame,int slot, + nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdu){} + +int16_t find_nr_dlsch(uint16_t rnti, PHY_VARS_gNB *gNB,find_type_t type){return 0;} +void handle_nr_nfapi_pdsch_pdu(PHY_VARS_gNB *gNB,int frame,int slot, + nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu, + uint8_t *sdu){ + } +int l1_north_init_gNB(void){return 0;} + +uint8_t slot_ahead=6; +//uint8_t nfapi_mode=0; +NR_IF_Module_t *NR_IF_Module_init(int Mod_id) {return NULL;} + +void handle_nfapi_nr_ul_dci_pdu(PHY_VARS_gNB *gNB, + int frame, int slot, + nfapi_nr_ul_dci_request_pdus_t *ul_dci_request_pdu){} +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_fill_prach(PHY_VARS_gNB *gNB, + int SFN, + int Slot, + nfapi_nr_prach_pdu_t *prach_pdu){} +void nr_fill_prach_ru(RU_t *ru, + int SFN, + int Slot, + nfapi_nr_prach_pdu_t *prach_pdu){} + +void nr_phy_config_request(NR_PHY_Config_t *gNB){} + +void install_nr_schedule_handlers(NR_IF_Module_t *if_inst){} + +void nr_dump_frame_parms(NR_DL_FRAME_PARMS *fp){} \ No newline at end of file diff --git a/openair1/SCHED/nfapi_nr_dummy.c b/openair1/SCHED/nfapi_nr_dummy.c new file mode 100644 index 0000000000..db20017fb8 --- /dev/null +++ b/openair1/SCHED/nfapi_nr_dummy.c @@ -0,0 +1,52 @@ +//Dummy NR defs to avoid linking errors + +#include "PHY/defs_gNB.h" +#include "nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h" +#include "openair2/NR_PHY_INTERFACE/NR_IF_Module.h" +#include "openair1/PHY/LTE_TRANSPORT/transport_common.h" + +void handle_nfapi_nr_pdcch_pdu(PHY_VARS_gNB *gNB, + int frame, int slot, + nfapi_nr_dl_tti_pdcch_pdu *pdcch_pdu){} + +void handle_nr_nfapi_ssb_pdu(PHY_VARS_gNB *gNB,int frame,int slot, + nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdu){} + +int16_t find_nr_dlsch(uint16_t rnti, PHY_VARS_gNB *gNB,find_type_t type){return 0;} +void handle_nr_nfapi_pdsch_pdu(PHY_VARS_gNB *gNB,int frame,int slot, + nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu, + uint8_t *sdu){ + } +int l1_north_init_gNB(void){return 0;} + +uint8_t slot_ahead=6; +//uint8_t nfapi_mode=0; +NR_IF_Module_t *NR_IF_Module_init(int Mod_id) {return NULL;} + +void handle_nfapi_nr_ul_dci_pdu(PHY_VARS_gNB *gNB, + int frame, int slot, + nfapi_nr_ul_dci_request_pdus_t *ul_dci_request_pdu){} +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_fill_prach(PHY_VARS_gNB *gNB, + int SFN, + int Slot, + nfapi_nr_prach_pdu_t *prach_pdu){} +void nr_fill_prach_ru(RU_t *ru, + int SFN, + int Slot, + nfapi_nr_prach_pdu_t *prach_pdu){} + +void nr_phy_config_request(NR_PHY_Config_t *gNB){} + +void install_nr_schedule_handlers(NR_IF_Module_t *if_inst){} + +//void nr_dump_frame_parms(NR_DL_FRAME_PARMS *fp){} + + \ No newline at end of file diff --git a/openair1/SCHED_NR/fapi_nr_l1.c b/openair1/SCHED_NR/fapi_nr_l1.c index 84490bfad4..d65d3b54bb 100644 --- a/openair1/SCHED_NR/fapi_nr_l1.c +++ b/openair1/SCHED_NR/fapi_nr_l1.c @@ -33,6 +33,12 @@ #include "PHY/NR_TRANSPORT/nr_transport_proto.h" #include "PHY/NR_TRANSPORT/nr_dlsch.h" #include "PHY/NR_TRANSPORT/nr_dci.h" +#include "nfapi/oai_integration/vendor_ext.h" + +extern int oai_nfapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req); +extern int oai_nfapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req); +extern int oai_nfapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req); +extern int oai_nfapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req); extern uint8_t nfapi_mode; @@ -126,7 +132,7 @@ void handle_nr_nfapi_pdsch_pdu(PHY_VARS_gNB *gNB,int frame,int slot, } void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO){ - + PHY_VARS_gNB *gNB; // copy data from L2 interface into L1 structures module_id_t Mod_id = Sched_INFO->module_id; @@ -169,6 +175,7 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO){ case NFAPI_NR_DL_TTI_SSB_PDU_TYPE: gNB->pbch_configured=1; + if(NFAPI_MODE != NFAPI_MODE_VNF) handle_nr_nfapi_ssb_pdu(gNB,frame,slot, dl_tti_pdu); @@ -176,7 +183,7 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO){ case NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE: AssertFatal(pdcch_received == 0, "pdcch_received is not 0, we can only handle one PDCCH PDU per slot\n"); - LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE for %d.%d\n",frame,slot,DL_req->SFN,DL_req->Slot); + if(NFAPI_MODE != NFAPI_MODE_VNF) handle_nfapi_nr_pdcch_pdu(gNB, frame, slot, &dl_tti_pdu->pdcch_pdu); @@ -193,33 +200,61 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO){ AssertFatal(TX_req->pdu_list[pduIndex].num_TLV == 1, "TX_req->pdu_list[%d].num_TLV %d != 1\n", pduIndex,TX_req->pdu_list[pduIndex].num_TLV); uint8_t *sdu = (uint8_t *)TX_req->pdu_list[pduIndex].TLVs[0].value.direct; + if(NFAPI_MODE != NFAPI_MODE_VNF) handle_nr_nfapi_pdsch_pdu(gNB,frame,slot,&dl_tti_pdu->pdsch_pdu, sdu); } } } // if (UL_tti_req!=NULL) memcpy(&gNB->UL_tti_req,UL_tti_req,sizeof(nfapi_nr_ul_tti_request_t)); + if(NFAPI_MODE != NFAPI_MODE_VNF) + for (int i=0;iul_dci_pdu_list[i]); + } + + if(NFAPI_MODE != NFAPI_MODE_VNF) + for (int i = 0; i < number_ul_tti_pdu; i++) { + switch (UL_tti_req->pdus_list[i].pdu_type) { + case NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE: + LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_UL_TTI_PUSCH_PDU_TYPE for %d.%d\n", frame, slot, UL_tti_req->SFN, UL_tti_req->Slot); + nr_fill_ulsch(gNB,UL_tti_req->SFN, UL_tti_req->Slot, &UL_tti_req->pdus_list[i].pusch_pdu); + break; + case NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE: + LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_UL_TTI_PUCCH_PDU_TYPE for %d.%d\n", frame, slot, UL_tti_req->SFN, UL_tti_req->Slot); + nr_fill_pucch(gNB,UL_tti_req->SFN, UL_tti_req->Slot, &UL_tti_req->pdus_list[i].pucch_pdu); + break; + case NFAPI_NR_UL_CONFIG_PRACH_PDU_TYPE: + LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_UL_TTI_PRACH_PDU_TYPE for %d.%d\n", frame, slot, UL_tti_req->SFN, UL_tti_req->Slot); + nfapi_nr_prach_pdu_t *prach_pdu = &UL_tti_req->pdus_list[i].prach_pdu; + nr_fill_prach(gNB, UL_tti_req->SFN, UL_tti_req->Slot, prach_pdu); + if (gNB->RU_list[0]->if_south == LOCAL_RF) nr_fill_prach_ru(gNB->RU_list[0], UL_tti_req->SFN, UL_tti_req->Slot, prach_pdu); + break; + } + } + + if(NFAPI_MODE != NFAPI_MONOLITHIC && number_ul_tti_pdu>0) + { + oai_nfapi_ul_tti_req(UL_tti_req); + } - for (int i=0;iul_dci_pdu_list[i]); + if (NFAPI_MODE != NFAPI_MONOLITHIC && Sched_INFO->UL_dci_req->numPdus!=0) + { + oai_nfapi_ul_dci_req(Sched_INFO->UL_dci_req); + } + + if (NFAPI_MODE != NFAPI_MONOLITHIC) + { + if(Sched_INFO->DL_req->dl_tti_request_body.nPDUs>0) + { + Sched_INFO->DL_req->SFN = frame; + Sched_INFO->DL_req->Slot = slot; + oai_nfapi_dl_tti_req(Sched_INFO->DL_req); + } + if (Sched_INFO->TX_req->Number_of_PDUs > 0) + { + oai_nfapi_tx_data_req(Sched_INFO->TX_req); + } + } - for (int i = 0; i < number_ul_tti_pdu; i++) { - switch (UL_tti_req->pdus_list[i].pdu_type) { - case NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE: - LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_UL_TTI_PUSCH_PDU_TYPE for %d.%d\n", frame, slot, UL_tti_req->SFN, UL_tti_req->Slot); - nr_fill_ulsch(gNB,UL_tti_req->SFN, UL_tti_req->Slot, &UL_tti_req->pdus_list[i].pusch_pdu); - break; - case NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE: - LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_UL_TTI_PUCCH_PDU_TYPE for %d.%d\n", frame, slot, UL_tti_req->SFN, UL_tti_req->Slot); - nr_fill_pucch(gNB,UL_tti_req->SFN, UL_tti_req->Slot, &UL_tti_req->pdus_list[i].pucch_pdu); - break; - case NFAPI_NR_UL_CONFIG_PRACH_PDU_TYPE: - LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_UL_TTI_PRACH_PDU_TYPE for %d.%d\n", frame, slot, UL_tti_req->SFN, UL_tti_req->Slot); - nfapi_nr_prach_pdu_t *prach_pdu = &UL_tti_req->pdus_list[i].prach_pdu; - nr_fill_prach(gNB, UL_tti_req->SFN, UL_tti_req->Slot, prach_pdu); - if (gNB->RU_list[0]->if_south == LOCAL_RF) nr_fill_prach_ru(gNB->RU_list[0], UL_tti_req->SFN, UL_tti_req->Slot, prach_pdu); - break; - } - } -} +} \ No newline at end of file diff --git a/openair1/SCHED_NR/fapi_nr_l1.h b/openair1/SCHED_NR/fapi_nr_l1.h index d66d6e7b24..ed90b9870b 100644 --- a/openair1/SCHED_NR/fapi_nr_l1.h +++ b/openair1/SCHED_NR/fapi_nr_l1.h @@ -36,6 +36,11 @@ #include "nfapi_nr_interface.h" #include "nfapi_nr_interface_scf.h" +// added +void handle_nr_nfapi_ssb_pdu(PHY_VARS_gNB *gNB, + int frame,int slot, + nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdu); + void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO); void handle_nfapi_nr_pdcch_pdu(PHY_VARS_gNB *gNB, @@ -48,3 +53,8 @@ void handle_nr_nfapi_pdsch_pdu(PHY_VARS_gNB *gNB,int frame,int slot, void nr_fill_indication(PHY_VARS_gNB *gNB, int frame, int slot_rx, int UE_id, uint8_t harq_pid, uint8_t crc_flag); +//added + +void handle_nfapi_nr_ul_dci_pdu(PHY_VARS_gNB *gNB, + int frame, int slot, + nfapi_nr_ul_dci_request_pdus_t *ul_dci_request_pdu); diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index e3cb2d9ad6..a66965d277 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -161,7 +161,7 @@ void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB, } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_COMMON_TX,1); - if (nfapi_mode == 0 || nfapi_mode == 1) { + if (NFAPI_MODE == NFAPI_MONOLITHIC || NFAPI_MODE == NFAPI_MODE_PNF) { if ((!(frame%ssb_frame_periodicity))) // generate SSB only for given frames according to SSB periodicity nr_common_signal_procedures(gNB,frame, slot); } @@ -201,10 +201,10 @@ void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB, VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_DLSCH,1); LOG_D(PHY, "PDSCH generation started (%d) in frame %d.%d\n", gNB->num_pdsch_rnti[slot],frame,slot); nr_generate_pdsch(gNB,frame, slot); - if ((frame&127) == 0) dump_pdsch_stats(gNB); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_DLSCH,0); } + if ((frame&127) == 0) dump_pdsch_stats(gNB); //apply the OFDM symbol rotation here apply_nr_rotation(fp,(int16_t*) &gNB->common_vars.txdataF[0][txdataF_offset],slot,0,fp->Ncp==EXTENDED?12:14,fp->ofdm_symbol_size); diff --git a/openair1/SCHED_NR_UE/defs.h b/openair1/SCHED_NR_UE/defs.h index 4888e88797..f7f44a520d 100644 --- a/openair1/SCHED_NR_UE/defs.h +++ b/openair1/SCHED_NR_UE/defs.h @@ -20,6 +20,7 @@ */ /* + \brief NR UE PHY functions prototypes \author R. Knopp, F. Kaltenberger \company EURECOM \email knopp@eurecom.fr @@ -113,16 +114,14 @@ void phy_procedures_nrUE_TX(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t @param ue Pointer to UE variables on which to act @param proc Pointer to proc information @param gNB_id Local id of eNB on which to act - @param mode calibration/debug mode @param dlsch_parallel use multithreaded dlsch processing */ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t gNB_id, - runmode_t mode, uint8_t dlsch_parallel); -int phy_procedures_slot_parallelization_nrUE_RX(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t abstraction_flag,uint8_t do_pdcch_flag,runmode_t mode,relaying_type_t r_type); +int phy_procedures_slot_parallelization_nrUE_RX(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t eNB_id, uint8_t abstraction_flag, uint8_t do_pdcch_flag, relaying_type_t r_type); #ifdef UE_SLOT_PARALLELISATION @@ -223,7 +222,7 @@ void ra_succeeded(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index); @param @param */ -void nr_ue_prach_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t gNB_id, runmode_t mode); +void nr_ue_prach_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t gNB_id); int is_nr_prach_subframe(NR_DL_FRAME_PARMS *frame_parms, uint32_t frame, uint8_t subframe); @@ -305,15 +304,6 @@ int8_t nr_find_ue(uint16_t rnti, PHY_VARS_eNB *phy_vars_eNB); */ void ue_ta_procedures(PHY_VARS_NR_UE *ue, int slot_tx, int frame_tx); -/*! \brief Compute the timing adjustment at UE side from the old TA offset and the new received TA command - @param Mod_id Local UE index on which to act - @param CC_id Component Carrier Index - @param ta_command TA command received from the network - @param mu numerology index (0,1,2..) -*/ -void nr_process_timing_advance(module_id_t Mod_id,uint8_t CC_id,uint8_t ta_command, uint8_t mu, uint16_t bwp_ul_NB_RB); -void nr_process_timing_advance_rar(PHY_VARS_NR_UE *ue, int frame_rx, int nr_slot_rx, uint16_t ta_command); - unsigned int nr_get_tx_amp(int power_dBm, int power_max_dBm, int N_RB_UL, int nb_rb); void phy_reset_ue(module_id_t Mod_id,uint8_t CC_id,uint8_t eNB_index); @@ -347,6 +337,8 @@ uint16_t nr_get_n1_pucch(PHY_VARS_NR_UE *phy_vars_ue, */ UE_MODE_t get_nrUE_mode(uint8_t Mod_id,uint8_t CC_id,uint8_t gNB_index); +uint8_t get_ra_PreambleIndex(uint8_t Mod_id, uint8_t CC_id, uint8_t gNB_id); + /*! \brief This function implements the power control mechanism for PUCCH from 36.213. @param phy_vars_ue PHY variables @param proc Pointer to proc descriptor @@ -396,8 +388,34 @@ int get_tx_harq_id(NR_UE_ULSCH_t *ulsch, int slot_tx); int is_pbch_in_slot(fapi_nr_config_request_t *config, int frame, int slot, NR_DL_FRAME_PARMS *fp); int is_ssb_in_slot(fapi_nr_config_request_t *config, int frame, int slot, NR_DL_FRAME_PARMS *fp); +/*! \brief This function prepares the dl indication to pass to the MAC + @param + @param + @param + @param + */ +void nr_fill_dl_indication(nr_downlink_indication_t *dl_ind, + fapi_nr_dci_indication_t *dci_ind, + fapi_nr_rx_indication_t *rx_ind, + UE_nr_rxtx_proc_t *proc, + PHY_VARS_NR_UE *ue, + uint8_t gNB_id); + /*@}*/ +/*! \brief This function prepares the dl rx indication + @param + @param + @param + @param + */ +void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind, + uint8_t pdu_type, + uint8_t gNB_id, + PHY_VARS_NR_UE *ue, + NR_UE_DLSCH_t *dlsch0, + uint16_t n_pdus); + #endif diff --git a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c index 6577a3b150..e70c353589 100644 --- a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c +++ b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c @@ -42,6 +42,9 @@ extern PHY_VARS_NR_UE ***PHY_vars_UE_g; +const char *dl_pdu_type[]={"DCI", "DLSCH", "RA_DLSCH"}; +const char *ul_pdu_type[]={"PRACH", "PUCCH", "PUSCH", "SRS"}; + int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){ if(scheduled_response != NULL){ @@ -61,14 +64,14 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){ if(scheduled_response->dl_config != NULL){ fapi_nr_dl_config_request_t *dl_config = scheduled_response->dl_config; - LOG_D(PHY,"Received %d DL pdus:\n",dl_config->number_pdus); pdcch_vars->nb_search_space = 0; for (i = 0; i < dl_config->number_pdus; ++i){ + LOG_D(PHY, "In %s: received 1 DL %s PDU of %d total DL PDUs:\n", __FUNCTION__, dl_pdu_type[dl_config->dl_config_list[i].pdu_type - 1], dl_config->number_pdus); + if (dl_config->dl_config_list[i].pdu_type == FAPI_NR_DL_CONFIG_TYPE_DCI) { - LOG_D(PHY,"FAPI_NR_DL_CONFIG_TYPE_DCI\n"); fapi_nr_dl_config_dci_dl_pdu_rel15_t *pdcch_config = &dl_config->dl_config_list[i].dci_config_pdu.dci_config_rel15; memcpy((void*)&pdcch_vars->pdcch_config[pdcch_vars->nb_search_space],(void*)pdcch_config,sizeof(*pdcch_config)); pdcch_vars->nb_search_space = pdcch_vars->nb_search_space + 1; @@ -77,11 +80,9 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){ } else { if (dl_config->dl_config_list[i].pdu_type == FAPI_NR_DL_CONFIG_TYPE_DLSCH){ - LOG_D(PHY,"FAPI_NR_DL_CONFIG_TYPE_DLSCH\n"); dlsch0 = PHY_vars_UE_g[module_id][cc_id]->dlsch[thread_id][0][0]; } else if (dl_config->dl_config_list[i].pdu_type == FAPI_NR_DL_CONFIG_TYPE_RA_DLSCH){ - LOG_D(PHY,"FAPI_NR_DL_CONFIG_TYPE_RA_DLSCH\n"); dlsch0 = PHY_vars_UE_g[module_id][cc_id]->dlsch_ra[0]; } else if (dl_config->dl_config_list[i].pdu_type == FAPI_NR_DL_CONFIG_TYPE_SI_DLSCH){ @@ -146,6 +147,8 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){ for (i = 0; i < ul_config->number_pdus; ++i){ + LOG_D(PHY, "In %s: processing %s PDU of %d total UL PDUs (ul_config %p) \n", __FUNCTION__, ul_pdu_type[ul_config->ul_config_list[i].pdu_type - 1], ul_config->number_pdus, ul_config); + uint8_t pdu_type = ul_config->ul_config_list[i].pdu_type, pucch_resource_id, current_harq_pid, format, gNB_id = 0; /* PRACH */ //NR_PRACH_RESOURCES_t *prach_resources; @@ -241,14 +244,15 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){ // prach config pdu prach_config_pdu = &ul_config->ul_config_list[i].prach_config_pdu; memcpy((void*)&(PHY_vars_UE_g[module_id][cc_id]->prach_vars[gNB_id]->prach_pdu), (void*)prach_config_pdu, sizeof(fapi_nr_ul_config_prach_pdu)); - PHY_vars_UE_g[module_id][cc_id]->prach_vars[gNB_id]->prach_Config_enabled = 1; break; default: break; } } - ul_config->number_pdus = 0; + + memset(ul_config, 0, sizeof(fapi_nr_ul_config_request_t)); + } } return 0; diff --git a/openair1/SCHED_NR_UE/harq_nr.c b/openair1/SCHED_NR_UE/harq_nr.c index f3e5f91285..85f6d90bbe 100644 --- a/openair1/SCHED_NR_UE/harq_nr.c +++ b/openair1/SCHED_NR_UE/harq_nr.c @@ -295,7 +295,7 @@ harq_result_t uplink_harq_process(NR_UE_ULSCH_t *ulsch, int harq_pid, int ndi, u /* 38.321 5.4.2.1 2> if the uplink grant was received on PDCCH for the C-RNTI and the HARQ buffer of the identified process is empty */ if ((ulsch->harq_processes[harq_pid]->first_tx == 1) && (rnti_type == _C_RNTI_)) { /* no transmission yet on this process so consider its harq buffer as empty */ - ulsch->harq_processes[harq_pid]->first_tx = 0; + ulsch->harq_processes[harq_pid]->first_tx = 0; ulsch->harq_processes[harq_pid]->pusch_pdu.pusch_data.new_data_indicator = ndi; /* store first value of ndi */ ulsch->harq_processes[harq_pid]->round = 0; ulsch->harq_processes[harq_pid]->subframe_scheduling_flag = 1; diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index 8629d07410..f516ad8639 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -77,23 +77,83 @@ fifo_dump_emos_UE emos_dump_UE; #include "intertask_interface.h" #include "T.h" -#define DLSCH_RB_ALLOC 0x1fbf // skip DC RB (total 23/25 RBs) -#define DLSCH_RB_ALLOC_12 0x0aaa // skip DC RB (total 23/25 RBs) - -#define NS_PER_SLOT 500000 - char nr_mode_string[4][20] = {"NOT SYNCHED","PRACH","RAR","PUSCH"}; const uint8_t nr_rv_round_map_ue[4] = {0, 2, 1, 3}; -extern double cpuf; - #if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) || defined(OAI_ADRV9371_ZC706) extern uint64_t downlink_frequency[MAX_NUM_CCs][4]; #endif unsigned int gain_table[31] = {100,112,126,141,158,178,200,224,251,282,316,359,398,447,501,562,631,708,794,891,1000,1122,1258,1412,1585,1778,1995,2239,2512,2818,3162}; +void nr_fill_dl_indication(nr_downlink_indication_t *dl_ind, + fapi_nr_dci_indication_t *dci_ind, + fapi_nr_rx_indication_t *rx_ind, + UE_nr_rxtx_proc_t *proc, + PHY_VARS_NR_UE *ue, + uint8_t gNB_id){ + + memset((void*)dl_ind, 0, sizeof(nr_downlink_indication_t)); + + dl_ind->gNB_index = gNB_id; + dl_ind->module_id = ue->Mod_id; + dl_ind->cc_id = ue->CC_id; + dl_ind->frame = proc->frame_rx; + dl_ind->slot = proc->nr_slot_rx; + dl_ind->thread_id = proc->thread_id; + + if (dci_ind) { + + dl_ind->rx_ind = NULL; //no data, only dci for now + dl_ind->dci_ind = dci_ind; + + } else if (rx_ind) { + + dl_ind->rx_ind = rx_ind; // hang on rx_ind instance + dl_ind->dci_ind = NULL; + + } + +} + +void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind, + uint8_t pdu_type, + uint8_t gNB_id, + PHY_VARS_NR_UE *ue, + NR_UE_DLSCH_t *dlsch0, + uint16_t n_pdus){ + + int harq_pid; + NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; + + if (n_pdus > 1){ + LOG_E(PHY, "In %s: multiple number of DL PDUs not supported yet...\n", __FUNCTION__); + } + + switch (pdu_type){ + case FAPI_NR_RX_PDU_TYPE_DLSCH: + case FAPI_NR_RX_PDU_TYPE_RAR: + harq_pid = dlsch0->current_harq_pid; + rx_ind->rx_indication_body[n_pdus - 1].pdsch_pdu.pdu = dlsch0->harq_processes[harq_pid]->b; + rx_ind->rx_indication_body[n_pdus - 1].pdsch_pdu.pdu_length = dlsch0->harq_processes[harq_pid]->TBS / 8; + break; + case FAPI_NR_RX_PDU_TYPE_MIB: + rx_ind->rx_indication_body[n_pdus - 1].mib_pdu.pdu = ue->pbch_vars[gNB_id]->decoded_output; + rx_ind->rx_indication_body[n_pdus - 1].mib_pdu.additional_bits = ue->pbch_vars[gNB_id]->xtra_byte; + rx_ind->rx_indication_body[n_pdus - 1].mib_pdu.ssb_index = frame_parms->ssb_index; + rx_ind->rx_indication_body[n_pdus - 1].mib_pdu.ssb_length = frame_parms->Lmax; + rx_ind->rx_indication_body[n_pdus - 1].mib_pdu.cell_id = frame_parms->Nid_cell; + break; + default: + break; + } + + rx_ind->rx_indication_body[n_pdus -1].pdu_type = pdu_type; + rx_ind->number_pdus = n_pdus; + +} + int get_tx_amp_prach(int power_dBm, int power_max_dBm, int N_RB_UL){ int gain_dB = power_dBm - power_max_dBm, amp_x_100 = -1; @@ -136,6 +196,13 @@ UE_MODE_t get_nrUE_mode(uint8_t Mod_id,uint8_t CC_id,uint8_t gNB_id){ return(PHY_vars_UE_g[Mod_id][CC_id]->UE_mode[gNB_id]); } +uint8_t get_ra_PreambleIndex(uint8_t Mod_id, uint8_t CC_id, uint8_t gNB_id){ + + return PHY_vars_UE_g[Mod_id][CC_id]->prach_resources[gNB_id]->ra_PreambleIndex; + +} + + // scale the 16 factor in N_TA calculation in 38.213 section 4.2 according to the used FFT size uint16_t get_bw_scaling(uint16_t nb_rb){ uint16_t bw_scaling; @@ -151,9 +218,12 @@ uint16_t get_bw_scaling(uint16_t nb_rb){ return bw_scaling; } -/* UL time alignment -// If the current tx frame and slot match the TA configuration in ul_time_alignment -// then timing advance is processed and set to be applied in the next UL transmission */ +// UL time alignment procedures: +// - If the current tx frame and slot match the TA configuration in ul_time_alignment +// then timing advance is processed and set to be applied in the next UL transmission +// - Application of timing adjustment according to TS 38.213 p4.2 +// todo: +// - handle RAR TA application as per ch 4.2 TS 38.213 void ue_ta_procedures(PHY_VARS_NR_UE *ue, int slot_tx, int frame_tx){ if (ue->mac_enabled == 1) { @@ -165,10 +235,36 @@ void ue_ta_procedures(PHY_VARS_NR_UE *ue, int slot_tx, int frame_tx){ uint8_t numerology = ue->frame_parms.numerology_index; uint16_t bwp_ul_NB_RB = ue->frame_parms.N_RB_UL; + int factor_mu = 1 << numerology; + uint16_t bw_scaling = get_bw_scaling(bwp_ul_NB_RB); - LOG_D(PHY, "In %s: applying timing advance -- frame %d -- slot %d\n", __FUNCTION__, frame_tx, slot_tx); + LOG_D(PHY, "In %s: applying timing advance -- frame %d -- slot %d -- UE_mode %d\n", __FUNCTION__, frame_tx, slot_tx, ue->UE_mode[gNB_id]); - nr_process_timing_advance(ue->Mod_id, ue->CC_id, ul_time_alignment->ta_command, numerology, bwp_ul_NB_RB); + if (ue->UE_mode[gNB_id] == RA_RESPONSE){ + + ue->timing_advance = ul_time_alignment->ta_command * bw_scaling / factor_mu; + + LOG_D(PHY, "In %s: [UE %d] [%d.%d] Received (RAR) timing advance command %d new value is %u \n", + __FUNCTION__, + ue->Mod_id, + frame_tx, + slot_tx, + ul_time_alignment->ta_command, + ue->timing_advance); + + } else if (ue->UE_mode[gNB_id] == PUSCH){ + + ue->timing_advance += (ul_time_alignment->ta_command - 31) * bw_scaling / factor_mu; + + LOG_D(PHY, "In %s: [UE %d] [%d.%d] Got timing advance command %u from MAC, new value is %d\n", + __FUNCTION__, + ue->Mod_id, + frame_tx, + slot_tx, + ul_time_alignment->ta_command, + ue->timing_advance); + + } ul_time_alignment->ta_frame = -1; ul_time_alignment->ta_slot = -1; @@ -177,38 +273,14 @@ void ue_ta_procedures(PHY_VARS_NR_UE *ue, int slot_tx, int frame_tx){ } } -void nr_process_timing_advance(module_id_t Mod_id, uint8_t CC_id, uint8_t ta_command, uint8_t mu, uint16_t bwp_ul_NB_RB){ - - // 3GPP TS 38.213 p4.2 - // scale by the scs numerology - int factor_mu = 1 << mu; - uint16_t bw_scaling = get_bw_scaling(bwp_ul_NB_RB); - - PHY_vars_UE_g[Mod_id][CC_id]->timing_advance += (ta_command - 31) * bw_scaling / factor_mu; - - LOG_D(PHY, "[UE %d] Got timing advance command %u from MAC, new value is %d\n", Mod_id, ta_command, PHY_vars_UE_g[Mod_id][CC_id]->timing_advance); -} - -// WIP -// - todo: handle TA application as per ch 4.2 TS 38.213 -void nr_process_timing_advance_rar(PHY_VARS_NR_UE *ue, int frame_rx, int nr_slot_rx, uint16_t ta_command) { - - int factor_mu = 1 << ue->frame_parms.numerology_index; - uint16_t bwp_ul_NB_RB = ue->frame_parms.N_RB_UL; - uint16_t bw_scaling = get_bw_scaling(bwp_ul_NB_RB); - - // Transmission timing adjustment (TS 38.213 p4.2) - ue->timing_advance = bw_scaling / factor_mu; - - LOG_D(PHY, "[UE %d] Frame %d Slot %d, Received (RAR) timing advance command %d new value is %u \n", ue->Mod_id, frame_rx, nr_slot_rx, ta_command, ue->timing_advance); -} - void phy_procedures_nrUE_TX(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t gNB_id) { + int slot_tx = proc->nr_slot_tx; int frame_tx = proc->frame_tx; - runmode_t mode = normal_txrx; + + AssertFatal(ue->CC_id == 0, "Transmission on secondary CCs is not supported yet\n"); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX,VCD_FUNCTION_IN); @@ -239,15 +311,11 @@ void phy_procedures_nrUE_TX(PHY_VARS_NR_UE *ue, nr_ue_pusch_common_procedures(ue, slot_tx, &ue->frame_parms,1); - //ue->ulsch[proc->thread_id][gNB_id][0]->harq_processes[harq_pid]->pusch_pdu.nrOfLayers); - } - //LOG_M("txdata.m","txs",ue->common_vars.txdata[0],1228800,1,1); - /* RACH */ - if (get_softmodem_params()->do_ra==1) { - if ((ue->UE_mode[gNB_id] > NOT_SYNCHED && ue->UE_mode[gNB_id] < PUSCH) && (ue->prach_vars[gNB_id]->prach_Config_enabled == 1)) { - nr_ue_prach_procedures(ue, proc, gNB_id, mode); - } + } + + if (ue->UE_mode[gNB_id] > NOT_SYNCHED && ue->UE_mode[gNB_id] < PUSCH) { + nr_ue_prach_procedures(ue, proc, gNB_id); } LOG_D(PHY,"****** end TX-Chain for AbsSubframe %d.%d ******\n", frame_tx, slot_tx); @@ -262,8 +330,7 @@ void nr_ue_measurement_procedures(uint16_t l, PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t eNB_id, - uint16_t slot, - runmode_t mode){ + uint16_t slot){ NR_DL_FRAME_PARMS *frame_parms=&ue->frame_parms; int frame_rx = proc->frame_rx; @@ -316,11 +383,7 @@ void nr_ue_pbch_procedures(uint8_t gNB_id, UE_nr_rxtx_proc_t *proc, uint8_t abstraction_flag) { - // int i; - //int pbch_tx_ant=0; int ret = 0; - //static uint8_t first_run = 1; - //uint8_t pbch_trials = 0; DevAssert(ue); @@ -345,9 +408,13 @@ void nr_ue_pbch_procedures(uint8_t gNB_id, // Switch to PRACH state if it is first PBCH after initial synch and no timing correction is performed if (ue->UE_mode[gNB_id] == NOT_SYNCHED && ue->no_timing_correction == 1){ - ue->UE_mode[gNB_id] = PRACH; - ue->prach_resources[gNB_id]->sync_frame = frame_rx; - ue->prach_resources[gNB_id]->init_msg1 = 0; + if (get_softmodem_params()->do_ra) { + ue->UE_mode[gNB_id] = PRACH; + ue->prach_resources[gNB_id]->sync_frame = frame_rx; + ue->prach_resources[gNB_id]->init_msg1 = 0; + } else { + ue->UE_mode[gNB_id] = PUSCH; + } } #ifdef DEBUG_PHY_PROC @@ -439,6 +506,8 @@ int nr_ue_pdcch_procedures(uint8_t gNB_id, int frame_rx = proc->frame_rx; int nr_slot_rx = proc->nr_slot_rx; unsigned int dci_cnt=0; + fapi_nr_dci_indication_t dci_ind = {0}; + nr_downlink_indication_t dl_indication; /* // unsigned int dci_cnt=0, i; //removed for nr_ue_pdcch_procedures and added in the loop for nb_coreset_active @@ -635,8 +704,6 @@ int nr_ue_pdcch_procedures(uint8_t gNB_id, pdcch_vars->nb_search_space); #endif - fapi_nr_dci_indication_t dci_ind={0}; - nr_downlink_indication_t dl_indication={0}; dci_cnt = nr_dci_decoding_procedure(ue, proc, &dci_ind); #ifdef NR_PDCCH_SCHED_DEBUG @@ -694,15 +761,7 @@ int nr_ue_pdcch_procedures(uint8_t gNB_id, */ // fill dl_indication message - dl_indication.module_id = ue->Mod_id; - dl_indication.cc_id = ue->CC_id; - dl_indication.gNB_index = gNB_id; - dl_indication.frame = frame_rx; - dl_indication.slot = nr_slot_rx; - dl_indication.thread_id = proc->thread_id; - dl_indication.rx_ind = NULL; //no data, only dci for now - dl_indication.dci_ind = &dci_ind; - + nr_fill_dl_indication(&dl_indication, &dci_ind, NULL, proc, ue, gNB_id); // send to mac ue->if_inst->dl_indication(&dl_indication, NULL); @@ -851,85 +910,6 @@ int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, int eNB_ return 0; } -// WIP fix: -// - time domain indication hardcoded to 0 for k2 offset -// - extend TS 38.213 ch 8.3 Msg3 PUSCH -// - b buffer -// - ulsch power offset -// - UE_mode == PUSCH case (should be handled by TA updates) -// - harq -// - optimize: mu_pusch, j and table_6_1_2_1_1_2_time_dom_res_alloc_A are already defined in nr_ue_procedures -void nr_process_rar(nr_downlink_indication_t *dl_info) { - - module_id_t module_id = dl_info->module_id; - int cc_id = dl_info->cc_id, frame_rx = dl_info->frame, nr_slot_rx = dl_info->slot, ta_command; - uint8_t gNB_index = dl_info->gNB_index; // *rar; - PHY_VARS_NR_UE *ue = PHY_vars_UE_g[module_id][cc_id]; - NR_UE_DLSCH_t *dlsch0 = ue->dlsch_ra[gNB_index]; - UE_MODE_t UE_mode = ue->UE_mode[gNB_index]; - NR_PRACH_RESOURCES_t *prach_resources = ue->prach_resources[gNB_index]; - - LOG_D(PHY,"[UE %d][RAPROC] Frame %d slot %d Received RAR mode %d\n", module_id, frame_rx, nr_slot_rx, UE_mode); - - if (ue->mac_enabled == 1) { - if ((UE_mode != PUSCH) && (prach_resources->Msg3 != NULL)) { - - LOG_D(PHY,"[UE %d][RAPROC] Frame %d slot %d Invoking MAC for RAR (current preamble %d)\n", module_id, frame_rx, nr_slot_rx, prach_resources->ra_PreambleIndex); - - ta_command = nr_ue_process_rar(ue->Mod_id, - cc_id, - frame_rx, - nr_slot_rx, - dlsch0->harq_processes[0]->b, - &ue->pdcch_vars[dl_info->thread_id][gNB_index]->pdcch_config[0].rnti, - prach_resources->ra_PreambleIndex, - dlsch0->harq_processes[0]->b); // alter the 'b' buffer so it contains only the selected RAR header and RAR payload - - if (ta_command != 0xffff) { - LOG_D(PHY,"[UE %d][RAPROC] Frame %d slot %d Got Temporary C-RNTI %x and timing advance %d from RAR\n", - ue->Mod_id, - frame_rx, - nr_slot_rx, - ue->pdcch_vars[dl_info->thread_id][gNB_index]->pdcch_config[0].rnti, - ta_command); - - nr_process_timing_advance_rar(ue, frame_rx, nr_slot_rx, ta_command); - - if (ue->mode != debug_prach) - ue->UE_mode[gNB_index] = RA_RESPONSE; - - } else { - LOG_W(PHY,"[UE %d][RAPROC] Received RAR preamble (%d) doesn't match !!!\n", ue->Mod_id, prach_resources->ra_PreambleIndex); - } - } - } else { - // rar = dlsch0->harq_processes[0]->b+1; - // ta_command = ((((uint16_t)(rar[0]&0x7f))<<4) + (rar[1]>>4)); - // nr_process_timing_advance_rar(ue, frame_rx, nr_slot_rx, ta_command); - } -} - -// if contention resolution fails, go back to UE mode PRACH -void nr_ra_failed(uint8_t Mod_id, uint8_t CC_id, uint8_t gNB_index) { - - PHY_VARS_NR_UE *ue = PHY_vars_UE_g[Mod_id][CC_id]; - ue->UE_mode[gNB_index] = PRACH; - - for (int i=0; i pdcch_vars[i][gNB_index]->pdcch_config[0].rnti = 0; - } - LOG_E(PHY,"[UE %d] [RAPROC] Random-access procedure fails, going back to PRACH\n", Mod_id); -} - -void nr_ra_succeeded(uint8_t Mod_id, - uint8_t CC_id, - uint8_t gNB_index){ - LOG_I(PHY,"[UE %d][RAPROC] RA procedure succeeded. UE set to PUSCH mode\n", Mod_id); - PHY_VARS_NR_UE *ue = PHY_vars_UE_g[Mod_id][CC_id]; - ue->ulsch_Msg3_active[gNB_index] = 0; - ue->UE_mode[gNB_index] = PUSCH; -} - void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, int eNB_id, @@ -937,7 +917,6 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, NR_UE_DLSCH_t *dlsch0, NR_UE_DLSCH_t *dlsch1, int *dlsch_errors, - runmode_t mode, uint8_t dlsch_parallel) { if (dlsch0==NULL) @@ -955,6 +934,7 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, uint16_t nb_symb_sch = 9; nr_downlink_indication_t dl_indication; fapi_nr_rx_indication_t rx_ind; + uint16_t number_pdus = 1; // params for UL time alignment procedure NR_UL_TIME_ALIGNMENT_t *ul_time_alignment = &ue->ul_time_alignment[eNB_id]; uint16_t slots_per_frame = ue->frame_parms.slots_per_frame; @@ -1213,42 +1193,33 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, LOG_D(PHY," ------ end ldpc decoder for AbsSubframe %d.%d ------ \n", frame_rx, nr_slot_rx); LOG_D(PHY, "harq_pid: %d, TBS expected dlsch0: %d \n",harq_pid, dlsch0->harq_processes[harq_pid]->TBS); - + if(retmax_ldpc_iterations+1){ - // fill dl_indication message - dl_indication.module_id = ue->Mod_id; - dl_indication.cc_id = ue->CC_id; - dl_indication.gNB_index = eNB_id; - dl_indication.frame = frame_rx; - dl_indication.slot = nr_slot_rx; - dl_indication.thread_id = proc->thread_id; - dl_indication.rx_ind = &rx_ind; // hang on rx_ind instance - dl_indication.dci_ind = NULL; - - //dl_indication.rx_ind->number_pdus switch (pdsch) { case RA_PDSCH: - rx_ind.rx_indication_body[0].pdu_type = FAPI_NR_RX_PDU_TYPE_RAR; - break; + nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, eNB_id); + nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_RAR, eNB_id, ue, dlsch0, number_pdus); + + ue->UE_mode[eNB_id] = RA_RESPONSE; + break; case PDSCH: - rx_ind.rx_indication_body[0].pdu_type = FAPI_NR_RX_PDU_TYPE_DLSCH; - break; + nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, eNB_id); + nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_DLSCH, eNB_id, ue, dlsch0, number_pdus); + break; case SI_PDSCH: rx_ind.rx_indication_body[0].pdu_type = FAPI_NR_RX_PDU_TYPE_SIB; break; default: - break; + break; } - rx_ind.rx_indication_body[0].pdsch_pdu.pdu = dlsch0->harq_processes[harq_pid]->b; - rx_ind.rx_indication_body[0].pdsch_pdu.pdu_length = dlsch0->harq_processes[harq_pid]->TBS>>3; - LOG_D(PHY, "PDU length in bits: %d, in bytes: %d \n", dlsch0->harq_processes[harq_pid]->TBS, rx_ind.rx_indication_body[0].pdsch_pdu.pdu_length); - rx_ind.number_pdus = 1; + LOG_D(PHY, "In %s DL PDU length in bits: %d, in bytes: %d \n", __FUNCTION__, dlsch0->harq_processes[harq_pid]->TBS, dlsch0->harq_processes[harq_pid]->TBS / 8); // send to mac - if (ue->if_inst && ue->if_inst->dl_indication) - ue->if_inst->dl_indication(&dl_indication, ul_time_alignment); + if (ue->if_inst && ue->if_inst->dl_indication) { + ue->if_inst->dl_indication(&dl_indication, ul_time_alignment); + } } // TODO CRC check for CW0 @@ -1607,7 +1578,7 @@ void *UE_thread_slot1_dl_processing(void *arg) { abstraction_flag); } // do procedures for RA-RNTI - if ((ue->dlsch_ra[eNB_id]) && (ue->dlsch_ra[eNB_id]->active == 1)) { + if ((ue->dlsch_ra[eNB_id]) && (ue->dlsch_ra[eNB_id]->active == 1) && (UE_mode != PUSCH)) { ue_pdsch_procedures(ue, proc, eNB_id, @@ -1725,7 +1696,6 @@ int is_pbch_in_slot(fapi_nr_config_request_t *config, int frame, int slot, NR_DL int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t gNB_id, - runmode_t mode, uint8_t dlsch_parallel ) { @@ -1779,9 +1749,7 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue, #endif } - //if (mac->csirc->reportQuantity.choice.ssb_Index_RSRP){ - nr_ue_rsrp_measurements(ue,proc,nr_slot_rx,0); - //} + nr_ue_rsrp_measurements(ue, gNB_id, proc, nr_slot_rx, 0); if ((ue->decode_MIB == 1) && slot_pbch) { @@ -1909,7 +1877,7 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue, ue->dlsch[proc->thread_id][gNB_id][0], NULL); - nr_ue_measurement_procedures(2, ue, proc, gNB_id, nr_slot_rx, mode); + nr_ue_measurement_procedures(2, ue, proc, gNB_id, nr_slot_rx); } // do procedures for SI-RNTI @@ -1929,7 +1897,6 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue, ue->dlsch_SI[gNB_id], NULL, &ue->dlsch_SI_errors[gNB_id], - mode, dlsch_parallel); // deactivate dlsch once dlsch proc is done @@ -1955,7 +1922,6 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue, ue->dlsch_p[gNB_id], NULL, &ue->dlsch_p_errors[gNB_id], - mode, dlsch_parallel); // deactivate dlsch once dlsch proc is done @@ -1965,7 +1931,7 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue, } // do procedures for RA-RNTI - if ((ue->dlsch_ra[gNB_id]) && (ue->dlsch_ra[gNB_id]->active == 1)) { + if ((ue->dlsch_ra[gNB_id]) && (ue->dlsch_ra[gNB_id]->active == 1) && (ue->UE_mode[gNB_id] != PUSCH)) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_RA, VCD_FUNCTION_IN); nr_ue_pdsch_procedures(ue, proc, @@ -1981,7 +1947,6 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue, ue->dlsch_ra[gNB_id], NULL, &ue->dlsch_ra_errors[gNB_id], - mode, dlsch_parallel); // deactivate dlsch once dlsch proc is done @@ -2008,7 +1973,6 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue, ue->dlsch[proc->thread_id][gNB_id][0], ue->dlsch[proc->thread_id][gNB_id][1], &ue->dlsch_errors[gNB_id], - mode, dlsch_parallel); @@ -2169,66 +2133,51 @@ uint8_t nr_is_ri_TXOp(PHY_VARS_NR_UE *ue, return(0); } -// WIP // todo: -// - set tx_total_RE // - power control as per 38.213 ch 7.4 -void nr_ue_prach_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t gNB_id, runmode_t runmode) { +void nr_ue_prach_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t gNB_id) { int frame_tx = proc->frame_tx, nr_slot_tx = proc->nr_slot_tx, prach_power; // tx_amp - uint16_t /*preamble_tx = 50,*/ pathloss; uint8_t mod_id = ue->Mod_id; - UE_MODE_t UE_mode = get_nrUE_mode(mod_id, ue->CC_id, gNB_id); NR_PRACH_RESOURCES_t * prach_resources = ue->prach_resources[gNB_id]; + AssertFatal(prach_resources != NULL, "ue->prach_resources[%u] == NULL\n", gNB_id); uint8_t nr_prach = 0; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_PRACH, VCD_FUNCTION_IN); - if (!prach_resources->init_msg1 && ((MAX_FRAME_NUMBER+frame_tx-ue->prach_resources[gNB_id]->sync_frame)% MAX_FRAME_NUMBER)>150){ - ue->prach_cnt = 0; - prach_resources->init_msg1 = 1; - } - if (ue->mac_enabled == 0){ - // prach_resources->ra_PreambleIndex = preamble_tx; + prach_resources->ra_TDD_map_index = 0; prach_resources->ra_PREAMBLE_RECEIVED_TARGET_POWER = 10; prach_resources->ra_RNTI = 0x1234; nr_prach = 1; + prach_resources->init_msg1 = 1; + } else { - // ask L2 for RACH transport - if ((runmode != rx_calib_ue) && (runmode != rx_calib_ue_med) && (runmode != rx_calib_ue_byp) && (runmode != no_L2_connect) ) { - LOG_D(PHY, "Getting PRACH resources. Frame %d Slot %d \n", frame_tx, nr_slot_tx); - // flush Msg3 Buffer - if (prach_resources->Msg3 == NULL){ - for(int i = 0; iulsch_Msg3_active[i] = 0; - } - } - nr_prach = nr_ue_get_rach(ue->prach_resources[gNB_id], &ue->prach_vars[0]->prach_pdu, mod_id, ue->CC_id, UE_mode, frame_tx, gNB_id, nr_slot_tx); - } + + LOG_D(PHY, "In %s:[%d.%d] getting PRACH resources\n", __FUNCTION__, frame_tx, nr_slot_tx); + nr_prach = nr_ue_get_rach(prach_resources, &ue->prach_vars[0]->prach_pdu, mod_id, ue->CC_id, frame_tx, gNB_id, nr_slot_tx); + } - if (ue->prach_resources[gNB_id] != NULL && nr_prach == 1 && prach_resources->init_msg1) { + if (nr_prach == 1) { - pathloss = get_nr_PL(mod_id, ue->CC_id, gNB_id); - LOG_D(PHY,"runmode %d\n",runmode); + if (ue->mac_enabled == 1) { + int16_t pathloss = get_nr_PL(mod_id, ue->CC_id, gNB_id); + int16_t ra_preamble_rx_power = (int16_t)(10*log10(pow(10, (double)(prach_resources->ra_PREAMBLE_RECEIVED_TARGET_POWER)/10) + pow(10, (double)(pathloss)/10))); + ue->tx_power_dBm[nr_slot_tx] = min(nr_get_Pcmax(mod_id), ra_preamble_rx_power); - if ((ue->mac_enabled == 1) && (runmode != calib_prach_tx)) { - ue->tx_power_dBm[nr_slot_tx] = prach_resources->ra_PREAMBLE_RECEIVED_TARGET_POWER + pathloss; + LOG_I(PHY,"[UE %d][RAPROC][%d.%d]: Generating PRACH Msg1 (preamble %d, PL %d, P0_PRACH %d, TARGET_RECEIVED_POWER %d dBm, RA-RNTI %x)\n", + mod_id, + frame_tx, + nr_slot_tx, + prach_resources->ra_PreambleIndex, + pathloss, + ue->tx_power_dBm[nr_slot_tx], + prach_resources->ra_PREAMBLE_RECEIVED_TARGET_POWER, + prach_resources->ra_RNTI); } - LOG_I(PHY,"[UE %d][RAPROC] Frame %d, nr_slot_tx %d : Generating PRACH, preamble %d, PL %d, P0_PRACH %d, TARGET_RECEIVED_POWER %d dBm, RA-RNTI %x\n", - ue->Mod_id, - frame_tx, - nr_slot_tx, - prach_resources->ra_PreambleIndex, - pathloss, - ue->tx_power_dBm[nr_slot_tx], - prach_resources->ra_PREAMBLE_RECEIVED_TARGET_POWER, - prach_resources->ra_RNTI); - - //ue->tx_total_RE[nr_slot_tx] = 96; // todo ue->prach_vars[gNB_id]->amp = AMP; /* #if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) || defined(OAI_ADRV9371_ZC706) @@ -2239,51 +2188,38 @@ void nr_ue_prach_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t ue->prach_vars[gNB_id]->amp = AMP; #endif */ - if ((runmode == calib_prach_tx) && (((proc->frame_tx&0xfffe)%100)==0)) - LOG_D(PHY,"[UE %d][RAPROC] Frame %d, nr_slot_tx %d : PRACH TX power %d dBm, amp %d\n", ue->Mod_id, - proc->frame_rx, - proc->nr_slot_tx, - ue->tx_power_dBm[nr_slot_tx], - ue->prach_vars[gNB_id]->amp); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GENERATE_PRACH, VCD_FUNCTION_IN); prach_power = generate_nr_prach(ue, gNB_id, nr_slot_tx); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GENERATE_PRACH, VCD_FUNCTION_OUT); - LOG_D(PHY,"[UE %d][RAPROC] PRACH PL %d dB, power %d dBm, digital power %d dB (amp %d)\n", - ue->Mod_id, - pathloss, + LOG_D(PHY, "In %s: [UE %d][RAPROC][%d.%d]: Generated PRACH Msg1 (TX power PRACH %d dBm, digital power %d dBW (amp %d)\n", + __FUNCTION__, + mod_id, + frame_tx, + nr_slot_tx, ue->tx_power_dBm[nr_slot_tx], dB_fixed(prach_power), ue->prach_vars[gNB_id]->amp); if (ue->mac_enabled == 1) - nr_Msg1_transmitted(ue->Mod_id, ue->CC_id, frame_tx, gNB_id); + nr_Msg1_transmitted(mod_id, ue->CC_id, frame_tx, gNB_id); - LOG_I(PHY,"[UE %d][RAPROC] Frame %d, nr_slot_tx %d: Generated PRACH Msg1 (gNB %d) preamble index %d for UL, TX power %d dBm (PL %d dB) \n", - ue->Mod_id, - frame_tx, - nr_slot_tx, - gNB_id, - prach_resources->ra_PreambleIndex, - ue->tx_power_dBm[nr_slot_tx], - pathloss); - - LOG_D(PHY,"[UE %d] frame %d nr_slot_tx %d : prach_cnt %d\n", ue->Mod_id, frame_tx, nr_slot_tx, ue->prach_cnt); - - ue->prach_cnt++; - - if (ue->prach_cnt == 3) - ue->prach_cnt = 0; } else if (nr_prach == 2) { - nr_ra_succeeded(mod_id, ue->CC_id, gNB_id); + + LOG_D(PHY, "In %s: [UE %d] RA completed, setting UE mode to PUSCH\n", __FUNCTION__, mod_id); + + ue->UE_mode[gNB_id] = PUSCH; + + } else if(nr_prach == 3){ + + LOG_D(PHY, "In %s: [UE %d] RA failed, setting UE mode to PRACH\n", __FUNCTION__, mod_id); + + ue->UE_mode[gNB_id] = PRACH; + } - // if we're calibrating the PRACH kill the pointer to its resources so that the RA protocol doesn't continue - if (runmode == calib_prach_tx) - ue->prach_resources[gNB_id] = NULL; - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_PRACH, VCD_FUNCTION_OUT); + } diff --git a/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c b/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c index 354d044ff9..edb070f873 100644 --- a/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c +++ b/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c @@ -202,8 +202,6 @@ void nr_generate_pucch3_4(int32_t **txdataF, * *********************************************************************/ -static int bwp_id = 1; - bool pucch_procedures_ue_nr(PHY_VARS_NR_UE *ue, uint8_t gNB_id, UE_nr_rxtx_proc_t *proc, bool reset_harq) { uint8_t sr_payload = 0; @@ -234,6 +232,7 @@ bool pucch_procedures_ue_nr(PHY_VARS_NR_UE *ue, uint8_t gNB_id, UE_nr_rxtx_proc_ NR_UE_MAC_INST_t *mac = get_mac_inst(0); NR_PUCCH_Resource_t *pucch_resource; uint16_t crnti = mac->crnti; + NR_BWP_Id_t bwp_id = mac->UL_BWP_Id; /* update current context */ @@ -762,7 +761,7 @@ uint8_t get_downlink_ack(PHY_VARS_NR_UE *ue, uint8_t gNB_id, UE_nr_rxtx_proc_t number_of_code_word = 1; } - if (ue->n_connected_eNB > 1) { + if (ue->n_connected_gNB > 1) { LOG_E(PHY,"PUCCH ACK feedback is not implemented for mutiple gNB cells : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); return (0); } @@ -781,19 +780,15 @@ uint8_t get_downlink_ack(PHY_VARS_NR_UE *ue, uint8_t gNB_id, UE_nr_rxtx_proc_t if (harq_status->ack == DL_ACKNACK_NO_SET) { LOG_E(PHY,"PUCCH Downlink acknowledgment has not been set : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); - return (0); } else if (harq_status->vDAI_DL == DL_DAI_NO_SET) { LOG_E(PHY,"PUCCH Downlink DAI has not been set : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); - return (0); } else if (harq_status->vDAI_DL > NR_DL_MAX_DAI) { LOG_E(PHY,"PUCCH Downlink DAI has an invalid value : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); - return (0); } else if (harq_status->send_harq_status == 0) { - LOG_E(PHY,"PUCCH Downlink ack can not be transmitted : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); - return(0); + LOG_D(PHY,"PUCCH Downlink ack can not be transmitted : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); } else { @@ -809,6 +804,8 @@ uint8_t get_downlink_ack(PHY_VARS_NR_UE *ue, uint8_t gNB_id, UE_nr_rxtx_proc_t number_harq_feedback++; ack_data[code_word][dai_current - 1] = harq_status->ack; dai[code_word][dai_current - 1] = dai_current; + harq_status->slot_for_feedback_ack = NR_MAX_SLOTS_PER_FRAME; + harq_status->send_harq_status = 0; } if (do_reset == TRUE) { init_downlink_harq_status(ue->dlsch[thread_idx][gNB_id][code_word]->harq_processes[dl_harq_pid]); @@ -939,6 +936,7 @@ boolean_t select_pucch_resource(PHY_VARS_NR_UE *ue, NR_UE_MAC_INST_t *mac, uint8 pucch_format_nr_t format_pucch; int ready_pucch_resource_id = FALSE; /* in the case that it is already given */ NR_PUCCH_Resource_t *pucch_resource; + NR_BWP_Id_t bwp_id = mac->UL_BWP_Id; /* ini values to unset */ *initial_pucch_id = NB_INITIAL_PUCCH_RESOURCE; @@ -1111,6 +1109,8 @@ boolean_t select_pucch_resource(PHY_VARS_NR_UE *ue, NR_UE_MAC_INST_t *mac, uint8 int find_pucch_resource_set(NR_UE_MAC_INST_t *mac, uint8_t gNB_id, int uci_size) { int pucch_resource_set_id = 0; + NR_BWP_Id_t bwp_id = mac->DL_BWP_Id; + //long *pucch_max_pl_bits = NULL; /* from TS 38.331 field maxPayloadMinus1 diff --git a/openair1/SIMULATION/NR_PHY/dlschsim.c b/openair1/SIMULATION/NR_PHY/dlschsim.c index c60bc8dd9f..00983553d8 100644 --- a/openair1/SIMULATION/NR_PHY/dlschsim.c +++ b/openair1/SIMULATION/NR_PHY/dlschsim.c @@ -56,7 +56,7 @@ UE_nr_rxtx_proc_t proc; int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; double cpuf; -uint8_t nfapi_mode = 0; +//uint8_t nfapi_mode = 0; uint16_t NB_UE_INST = 1; uint8_t const nr_rv_round_map[4] = {0, 2, 1, 3}; @@ -427,7 +427,7 @@ int main(int argc, char **argv) UE->dlsch_ra[0] = new_nr_ue_dlsch(1, 1, Nsoft, 5, N_RB_DL, 0); unsigned char harq_pid = 0; //dlsch->harq_ids[subframe]; NR_gNB_DLSCH_t *dlsch = gNB->dlsch[0][0]; - nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &dlsch->harq_processes[harq_pid]->pdsch_pdu.pdsch_pdu_rel15; + nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &dlsch->harq_process.pdsch_pdu.pdsch_pdu_rel15; //time_stats_t *rm_stats, *te_stats, *i_stats; uint8_t is_crnti = 0, llr8_flag = 0; unsigned int TBS = 8424; @@ -519,7 +519,7 @@ int main(int argc, char **argv) //if (i<16) // printf("encoder output f[%d] = %d\n",i,dlsch->harq_processes[0]->f[i]); - if (dlsch->harq_processes[0]->f[i] == 0) + if (dlsch->harq_process.f[i] == 0) modulated_input[i] = 1.0; ///sqrt(2); //QPSK else modulated_input[i] = -1.0; ///sqrt(2); @@ -547,7 +547,7 @@ int main(int argc, char **argv) else channel_output_uncoded[i] = 0; - if (channel_output_uncoded[i] != dlsch->harq_processes[harq_pid]->f[i]) + if (channel_output_uncoded[i] != dlsch->harq_process.f[i]) errors_bit_uncoded = errors_bit_uncoded + 1; } diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index 7d8605453c..6784535391 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -81,7 +81,7 @@ double cpuf; int sf_ahead=4 ; int sl_ahead=0; -uint8_t nfapi_mode = 0; +//uint8_t nfapi_mode = 0; uint64_t downlink_frequency[MAX_NUM_CCs][4]; // dummy functions @@ -151,6 +151,12 @@ nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP( return 0; } +int nr_derive_key(int alg_type, uint8_t alg_id, + const uint8_t key[32], uint8_t **out) +{ + return 0; +} + void config_common(int Mod_idP, int pdsch_AntennaPorts, NR_ServingCellConfigCommon_t *scc @@ -172,6 +178,13 @@ int is_x2ap_enabled(void) return 0; } +//nFAPI P7 dummy functions + +int oai_nfapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req) { return(0); } +int oai_nfapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req){ return(0); } +int oai_nfapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req){ return(0); } +int oai_nfapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req){ return(0); } + int8_t nr_rrc_ue_decode_NR_SIB1_Message(module_id_t module_id, uint8_t gNB_index, uint8_t *const bufferP, const uint8_t buffer_len) { return 0; } @@ -186,8 +199,7 @@ void update_dmrs_config(NR_CellGroupConfig_t *scg,PHY_VARS_NR_UE *ue, int8_t* dm int g_mcsIndex = -1, g_mcsTableIdx = 0, g_rbStart = -1, g_rbSize = -1; void nr_dlsim_preprocessor(module_id_t module_id, frame_t frame, - sub_frame_t slot, - int num_slots_per_tdd) { + sub_frame_t slot) { NR_UE_info_t *UE_info = &RC.nrmac[module_id]->UE_info; AssertFatal(UE_info->num_UEs == 1, "can have only a single UE\n"); NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[0]; @@ -203,15 +215,25 @@ void nr_dlsim_preprocessor(module_id_t module_id, sched_ctrl->active_bwp, sched_ctrl->search_space, 1 /* dedicated */); sched_ctrl->cce_index = 0; - /* set "any" value for PUCCH (simulator evaluates PDSCH only) */ - sched_ctrl->pucch_sched_idx = 0; - sched_ctrl->pucch_occ_idx = 0; - sched_ctrl->rbStart = g_rbStart; sched_ctrl->rbSize = g_rbSize; sched_ctrl->mcs = g_mcsIndex; sched_ctrl->time_domain_allocation = 2; sched_ctrl->mcsTableIdx = g_mcsTableIdx; + /* the simulator assumes the HARQ PID is equal to the slot number */ + sched_ctrl->dl_harq_pid = slot; + /* The scheduler uses lists to track whether a HARQ process is + * free/busy/awaiting retransmission, and updates the HARQ process states. + * However, in the simulation, we never get ack or nack for any HARQ process, + * thus the list and HARQ states don't match what the scheduler expects. + * Therefore, below lines just "repair" everything so that the scheduler + * won't remark that there is no HARQ feedback */ + sched_ctrl->feedback_dl_harq.head = -1; // always overwrite feedback HARQ process + if (sched_ctrl->harq_processes[slot].round == 0) // depending on round set in simulation ... + add_front_nr_list(&sched_ctrl->available_dl_harq, slot); // ... make PID available + else + add_front_nr_list(&sched_ctrl->retrans_dl_harq, slot); // ... make PID retransmission + sched_ctrl->harq_processes[slot].is_waiting = false; AssertFatal(sched_ctrl->rbStart >= 0, "invalid rbStart %d\n", sched_ctrl->rbStart); AssertFatal(sched_ctrl->rbSize > 0, "invalid rbSize %d\n", sched_ctrl->rbSize); AssertFatal(sched_ctrl->mcs >= 0, "invalid sched_ctrl->mcs %d\n", sched_ctrl->mcs); @@ -671,6 +693,9 @@ int main(int argc, char **argv) rrc_mac_config_req_gNB(0,0,1,pusch_tgt_snrx10,pucch_tgt_snrx10,NULL,1,secondaryCellGroup->spCellConfig->reconfigurationWithSync->newUE_Identity,secondaryCellGroup); phy_init_nr_gNB(gNB,0,0); N_RB_DL = gNB->frame_parms.N_RB_DL; + NR_UE_info_t *UE_info = &RC.nrmac[0]->UE_info; + UE_info->num_UEs=1; + // stub to configure frame_parms // nr_phy_config_request_sim(gNB,N_RB_DL,N_RB_DL,mu,Nid_cell,SSB_positions); // call MAC to configure common parameters @@ -836,10 +861,10 @@ int main(int argc, char **argv) scheduled_response.thread_id = UE_proc.thread_id; nr_ue_phy_config_request(&UE_mac->phy_config); - NR_UE_info_t *UE_info = &RC.nrmac[0]->UE_info; //NR_COMMON_channels_t *cc = RC.nrmac[0]->common_channels; snrRun = 0; + for (SNR = snr0; SNR < snr1; SNR += .2) { varArray_t *table_tx=initVarArray(1000,sizeof(double)); @@ -885,7 +910,7 @@ int main(int argc, char **argv) NR_DL_UE_HARQ_t *UE_harq_process = dlsch0->harq_processes[harq_pid]; NR_gNB_DLSCH_t *gNB_dlsch = gNB->dlsch[0][0]; - nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &gNB_dlsch->harq_processes[slot]->pdsch_pdu.pdsch_pdu_rel15; + nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &gNB_dlsch->harq_process.pdsch_pdu.pdsch_pdu_rel15; UE_harq_process->harq_ack.ack = 0; round = 0; @@ -901,15 +926,11 @@ int main(int argc, char **argv) UE_info->UE_sched_ctrl[0].harq_processes[harq_pid].round = round; - gNB->dlsch[0][0]->harq_processes[harq_pid]->round = round; for (int i=0; iUE_info.num_pdcch_cand[0][i] = 0; if (css_flag == 0) { - const uint8_t slots_per_frame[5] = {10, 20, 40, 80, 160}; - const NR_TDD_UL_DL_Pattern_t *tdd_pattern = &scc->tdd_UL_DL_ConfigurationCommon->pattern1; - const int num_slots_per_tdd = slots_per_frame[*scc->ssbSubcarrierSpacing] >> (7 - tdd_pattern->dl_UL_TransmissionPeriodicity); - nr_schedule_ue_spec(0, frame, slot, num_slots_per_tdd); + nr_schedule_ue_spec(0, frame, slot); } else { nr_schedule_css_dlsch_phytest(0,frame,slot); } @@ -1021,7 +1042,6 @@ int main(int argc, char **argv) phy_procedures_nrUE_RX(UE, &UE_proc, 0, - normal_txrx, dlsch_threads); //printf("dlsim round %d ends\n",round); @@ -1054,8 +1074,8 @@ int main(int argc, char **argv) for (i = 0; i < available_bits; i++) { - if(((gNB_dlsch->harq_processes[harq_pid]->f[i] == 0) && (UE_llr[i] <= 0)) || - ((gNB_dlsch->harq_processes[harq_pid]->f[i] == 1) && (UE_llr[i] >= 0))) + if(((gNB_dlsch->harq_process.f[i] == 0) && (UE_llr[i] <= 0)) || + ((gNB_dlsch->harq_process.f[i] == 1) && (UE_llr[i] >= 0))) { if(errors_scrambling == 0) { LOG_D(PHY,"\n"); @@ -1068,7 +1088,7 @@ int main(int argc, char **argv) for (i = 0; i < TBS; i++) { estimated_output_bit[i] = (UE_harq_process->b[i/8] & (1 << (i & 7))) >> (i & 7); - test_input_bit[i] = (gNB_dlsch->harq_processes[harq_pid]->b[i / 8] & (1 << (i & 7))) >> (i & 7); // Further correct for multiple segments + test_input_bit[i] = (gNB_dlsch->harq_process.b[i / 8] & (1 << (i & 7))) >> (i & 7); // Further correct for multiple segments if (estimated_output_bit[i] != test_input_bit[i]) { if(errors_bit == 0) @@ -1108,9 +1128,9 @@ int main(int argc, char **argv) if (print_perf==1) { printf("\ngNB TX function statistics (per %d us slot, NPRB %d, mcs %d, TBS %d, Kr %d (Zc %d))\n", 1000>>*scc->ssbSubcarrierSpacing, g_rbSize, g_mcsIndex, - gNB->dlsch[0][0]->harq_processes[0]->pdsch_pdu.pdsch_pdu_rel15.TBSize[0]<<3, - gNB->dlsch[0][0]->harq_processes[0]->K, - gNB->dlsch[0][0]->harq_processes[0]->K/((gNB->dlsch[0][0]->harq_processes[0]->pdsch_pdu.pdsch_pdu_rel15.TBSize[0]<<3)>3824?22:10)); + gNB->dlsch[0][0]->harq_process.pdsch_pdu.pdsch_pdu_rel15.TBSize[0]<<3, + gNB->dlsch[0][0]->harq_process.K, + gNB->dlsch[0][0]->harq_process.K/((gNB->dlsch[0][0]->harq_process.pdsch_pdu.pdsch_pdu_rel15.TBSize[0]<<3)>3824?22:10)); printDistribution(&gNB->phy_proc_tx,table_tx,"PHY proc tx"); printStatIndent2(&gNB->dlsch_encoding_stats,"DLSCH encoding time"); printStatIndent3(&gNB->dlsch_segmentation_stats,"DLSCH segmentation time"); diff --git a/openair1/SIMULATION/NR_PHY/nr_dummy_functions.c b/openair1/SIMULATION/NR_PHY/nr_dummy_functions.c index c7ee863c35..32b6b10412 100644 --- a/openair1/SIMULATION/NR_PHY/nr_dummy_functions.c +++ b/openair1/SIMULATION/NR_PHY/nr_dummy_functions.c @@ -2,8 +2,27 @@ int oai_nfapi_hi_dci0_req(nfapi_hi_dci0_request_t *hi_dci0_req) { re int oai_nfapi_tx_req(nfapi_tx_request_t *tx_req) { return(0); } int oai_nfapi_dl_config_req(nfapi_dl_config_request_t *dl_config_req) { return(0); } //int oai_nfapi_ul_config_req(nfapi_ul_config_request_t *ul_config_req) { return(0); } -//int oai_nfapi_nr_dl_config_req(nfapi_nr_dl_config_request_t *dl_config_req) { return(0); } +int oai_nfapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req) { return(0); } +int oai_nfapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req){ return(0); } +int oai_nfapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req){ return(0); } +int oai_nfapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req){ return(0); } int32_t get_uldl_offset(int nr_bandP) { return(0); } NR_IF_Module_t *NR_IF_Module_init(int Mod_id) {return(NULL);} +nfapi_mode_t nfapi_mod; +nfapi_mode_t nfapi_getmode(void) { + return nfapi_mod; +} int dummy_nr_ue_dl_indication(nr_downlink_indication_t *dl_info) { return(0); } int dummy_nr_ue_ul_indication(nr_uplink_indication_t *ul_info) { return(0); } +void nr_fill_dl_indication(nr_downlink_indication_t *dl_ind, + fapi_nr_dci_indication_t *dci_ind, + fapi_nr_rx_indication_t *rx_ind, + UE_nr_rxtx_proc_t *proc, + PHY_VARS_NR_UE *ue, + uint8_t gNB_id) {} +void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind, + uint8_t pdu_type, + uint8_t gNB_id, + PHY_VARS_NR_UE *ue, + NR_UE_DLSCH_t *dlsch0, + uint16_t n_pdus) {} diff --git a/openair1/SIMULATION/NR_PHY/nr_dummy_functions_prach.c b/openair1/SIMULATION/NR_PHY/nr_dummy_functions_prach.c index bfb9150868..a930c96a75 100644 --- a/openair1/SIMULATION/NR_PHY/nr_dummy_functions_prach.c +++ b/openair1/SIMULATION/NR_PHY/nr_dummy_functions_prach.c @@ -2,7 +2,10 @@ int oai_nfapi_hi_dci0_req(nfapi_hi_dci0_request_t *hi_dci0_req) { re int oai_nfapi_tx_req(nfapi_tx_request_t *tx_req) { return(0); } int oai_nfapi_dl_config_req(nfapi_dl_config_request_t *dl_config_req) { return(0); } int oai_nfapi_ul_config_req(nfapi_ul_config_request_t *ul_config_req) { return(0); } -//int oai_nfapi_nr_dl_config_req(nfapi_nr_dl_config_request_t *dl_config_req) { return(0); } +int oai_nfapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req) { return(0); } + int oai_nfapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req){ return(0); } + int oai_nfapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req){ return(0); } + int oai_nfapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req){ return(0); } int32_t get_uldl_offset(int nr_bandP) { return(0); } NR_IF_Module_t *NR_IF_Module_init(int Mod_id) {return(NULL);} int dummy_nr_ue_dl_indication(nr_downlink_indication_t *dl_info) { return(0); } @@ -83,7 +86,6 @@ void nr_get_prach_resources(module_id_t mod_id, int CC_id, uint8_t gNB_id, uint8_t t_id, - uint8_t first_Msg3, NR_PRACH_RESOURCES_t *prach_resources, NR_RACH_ConfigDedicated_t * rach_ConfigDedicated){ @@ -206,9 +208,6 @@ void nr_get_prach_resources(module_id_t mod_id, AssertFatal(1 == 0,"Unknown messagePowerOffsetGroupB %lu\n", nr_rach_ConfigCommon->groupBconfigured->messagePowerOffsetGroupB); } - // todo Msg3-DeltaPreamble should be provided from higher layers, otherwise is 0 - mac->deltaPreamble_Msg3 = 0; - deltaPreamble_Msg3 = mac->deltaPreamble_Msg3; } PLThreshold = prach_resources->RA_PCMAX - nr_rach_ConfigCommon->rach_ConfigGeneric.preambleReceivedTargetPower - deltaPreamble_Msg3 - messagePowerOffsetGroupB; diff --git a/openair1/SIMULATION/NR_PHY/nr_unitary_defs.h b/openair1/SIMULATION/NR_PHY/nr_unitary_defs.h index a7150fb2f9..8004fbb6b5 100644 --- a/openair1/SIMULATION/NR_PHY/nr_unitary_defs.h +++ b/openair1/SIMULATION/NR_PHY/nr_unitary_defs.h @@ -239,6 +239,7 @@ ngap_gNB_config_t ngap_config; uint32_t ngap_generate_gNB_id(void) {return 0;} void configure_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_addr, int pnf_p7_port, int vnf_p7_port) { return;} void configure_nfapi_vnf(char *vnf_addr, int vnf_p5_port) { return;} - +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) { return;} +void configure_nr_nfapi_vnf(char *vnf_addr, int vnf_p5_port) { return;} #endif diff --git a/openair1/SIMULATION/NR_PHY/pbchsim.c b/openair1/SIMULATION/NR_PHY/pbchsim.c index 2a7c51a582..2512988371 100644 --- a/openair1/SIMULATION/NR_PHY/pbchsim.c +++ b/openair1/SIMULATION/NR_PHY/pbchsim.c @@ -56,7 +56,7 @@ RAN_CONTEXT_t RC; int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; double cpuf; -uint8_t nfapi_mode = 0; +//uint8_t nfapi_mode = 0; uint16_t NB_UE_INST = 1; // needed for some functions @@ -675,7 +675,7 @@ int main(int argc, char **argv) } if (UE->is_synchronized == 0) { UE_nr_rxtx_proc_t proc={0}; - ret = nr_initial_sync(&proc, UE, normal_txrx,1); + ret = nr_initial_sync(&proc, UE, 1); printf("nr_initial_sync1 returns %d\n",ret); if (ret<0) n_errors++; } diff --git a/openair1/SIMULATION/NR_PHY/prachsim.c b/openair1/SIMULATION/NR_PHY/prachsim.c index 509fdb2e94..c90bcf1395 100644 --- a/openair1/SIMULATION/NR_PHY/prachsim.c +++ b/openair1/SIMULATION/NR_PHY/prachsim.c @@ -47,6 +47,7 @@ #include "OCG_vars.h" #include #include +//#include "openair1/SIMULATION/NR_PHY/nr_dummy_functions.c" #define NR_PRACH_DEBUG 1 @@ -62,7 +63,7 @@ RU_t *ru; double cpuf; extern uint16_t prach_root_sequence_map0_3[838]; openair0_config_t openair0_cfg[MAX_CARDS]; -uint8_t nfapi_mode=0; +//uint8_t nfapi_mode=0; int sl_ahead = 0; //void dump_nr_prach_config(NR_DL_FRAME_PARMS *frame_parms,uint8_t subframe); @@ -70,6 +71,10 @@ int sl_ahead = 0; /* temporary dummy implem of get_softmodem_optmask, till basic simulators implemented as device */ uint64_t get_softmodem_optmask(void) {return 0;} softmodem_params_t *get_softmodem_params(void) {return 0;} +int oai_nfapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req) { return(0); } +int oai_nfapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req){ return(0); } +int oai_nfapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req){ return(0); } +int oai_nfapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req){ return(0); } void rrc_data_ind( @@ -137,6 +142,12 @@ int8_t nr_rrc_ue_decode_NR_SIB1_Message(module_id_t module_id, uint8_t gNB_index return 0; } +int nr_derive_key(int alg_type, uint8_t alg_id, + const uint8_t key[32], uint8_t **out) +{ + return 0; +} + int main(int argc, char **argv){ char c; @@ -671,7 +682,7 @@ int main(int argc, char **argv){ UE_nr_rxtx_proc_t proc={0}; proc.frame_tx = frame; proc.nr_slot_tx = slot; - nr_ue_prach_procedures(UE,&proc,0,0); + nr_ue_prach_procedures(UE, &proc, 0); /* tx_lev_dB not used later, no need to set */ //tx_lev_dB = (unsigned int) dB_fixed(tx_lev); diff --git a/openair1/SIMULATION/NR_PHY/pucchsim.c b/openair1/SIMULATION/NR_PHY/pucchsim.c index a96a62f656..8d79633a6f 100644 --- a/openair1/SIMULATION/NR_PHY/pucchsim.c +++ b/openair1/SIMULATION/NR_PHY/pucchsim.c @@ -53,7 +53,7 @@ openair0_config_t openair0_cfg[MAX_CARDS]; int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; double cpuf; -uint8_t nfapi_mode = 0; +//uint8_t nfapi_mode = 0; uint16_t NB_UE_INST = 1; uint8_t const nr_rv_round_map[4] = {0, 2, 1, 3}; uint8_t const nr_rv_round_map_ue[4] = {0, 2, 1, 3}; diff --git a/openair1/SIMULATION/NR_PHY/ulschsim.c b/openair1/SIMULATION/NR_PHY/ulschsim.c index afebe4ed97..6f2af73a1d 100644 --- a/openair1/SIMULATION/NR_PHY/ulschsim.c +++ b/openair1/SIMULATION/NR_PHY/ulschsim.c @@ -60,7 +60,7 @@ uint8_t const nr_rv_round_map[4] = {0, 2, 1, 3}; uint8_t const nr_rv_round_map_ue[4] = {0, 2, 1, 3}; double cpuf; -uint8_t nfapi_mode = 0; +//uint8_t nfapi_mode = 0; uint16_t NB_UE_INST = 1; // needed for some functions diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index fd2e1dc0b7..443ee6e1c0 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -76,9 +76,10 @@ RAN_CONTEXT_t RC; int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; int sf_ahead=4 ; +int slot_ahead=6 ; int sl_ahead=0; double cpuf; -uint8_t nfapi_mode = 0; +//uint8_t nfapi_mode = 0; uint64_t downlink_frequency[MAX_NUM_CCs][4]; @@ -154,10 +155,22 @@ int is_x2ap_enabled(void) return 0; } +//nFAPI P7 dummy functions + +int oai_nfapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req) { return(0); } +int oai_nfapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req){ return(0); } +int oai_nfapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req){ return(0); } +int oai_nfapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req){ return(0); } int8_t nr_rrc_ue_decode_NR_SIB1_Message(module_id_t module_id, uint8_t gNB_index, uint8_t *const bufferP, const uint8_t buffer_len) { return 0; } +int nr_derive_key(int alg_type, uint8_t alg_id, + const uint8_t key[32], uint8_t **out) +{ + return 0; +} + // needed for some functions uint16_t n_rnti = 0x1234; openair0_config_t openair0_cfg[MAX_CARDS]; diff --git a/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/dummy_functions.c b/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/dummy_functions.c index cc8c62a36d..4d17fe723c 100644 --- a/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/dummy_functions.c +++ b/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/dummy_functions.c @@ -142,6 +142,10 @@ void thread_top_init(char *thread_name, int oai_nfapi_hi_dci0_req(nfapi_hi_dci0_request_t *hi_dci0_req) { return(0);} int oai_nfapi_tx_req(nfapi_tx_request_t *tx_req) { return(0); } +int oai_nfapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req) { return(0); } +int oai_nfapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req){ return(0); } +int oai_nfapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req){ return(0); } +int oai_nfapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req){ return(0); } int oai_nfapi_dl_config_req(nfapi_dl_config_request_t *dl_config_req) { return(0); } diff --git a/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/pucch_uci_test.c b/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/pucch_uci_test.c index bdb860a150..f731edc20a 100644 --- a/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/pucch_uci_test.c +++ b/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/pucch_uci_test.c @@ -232,7 +232,7 @@ int test_pucch_basic_error(PHY_VARS_NR_UE *ue, int gNB_id, UE_nr_rxtx_proc_t *pr v_return = -1; } - ue->n_connected_eNB = 2; + ue->n_connected_gNB = 2; printf("\n => Test : Error due to PUCCH format with multiple cells not already implemented \n"); @@ -240,7 +240,7 @@ int test_pucch_basic_error(PHY_VARS_NR_UE *ue, int gNB_id, UE_nr_rxtx_proc_t *pr v_return = -1; } - ue->n_connected_eNB = 1; + ue->n_connected_gNB = 1; return (v_return); } diff --git a/openair2/COMMON/s1ap_messages_types.h b/openair2/COMMON/s1ap_messages_types.h index f6b4f3c4e2..bd0788d2d0 100644 --- a/openair2/COMMON/s1ap_messages_types.h +++ b/openair2/COMMON/s1ap_messages_types.h @@ -155,6 +155,11 @@ typedef struct security_capabilities_s { uint16_t integrity_algorithms; } security_capabilities_t; +typedef struct nr_security_capabilities_s { + uint16_t encryption_algorithms; + uint16_t integrity_algorithms; +} nr_security_capabilities_t; + /* Provides the establishment cause for the RRC connection request as provided * by the upper layers. W.r.t. the cause value names: highPriorityAccess * concerns AC11..AC15, ‘mt’ stands for ‘Mobile Terminating’ and ‘mo’ for @@ -538,6 +543,9 @@ typedef struct s1ap_initial_context_setup_req_s { uint8_t nb_of_e_rabs; /* list of e_rab to be setup by RRC layers */ e_rab_t e_rab_param[S1AP_MAX_E_RAB]; + + /* NR Security algorithms (if any, set to 0 if not present) */ + nr_security_capabilities_t nr_security_capabilities; } s1ap_initial_context_setup_req_t; typedef struct tai_plmn_identity_s { diff --git a/openair2/COMMON/x2ap_messages_types.h b/openair2/COMMON/x2ap_messages_types.h index 0c55764d6e..f4911c47dc 100644 --- a/openair2/COMMON/x2ap_messages_types.h +++ b/openair2/COMMON/x2ap_messages_types.h @@ -338,7 +338,7 @@ typedef struct x2ap_ENDC_sgnb_addition_req_s { /* used for RRC->X2AP in source eNB */ int rnti; - security_capabilities_t security_capabilities; + nr_security_capabilities_t security_capabilities; /* SgNB Security Key */ uint8_t kgnb[32]; diff --git a/openair2/GNB_APP/L1_nr_paramdef.h b/openair2/GNB_APP/L1_nr_paramdef.h index a5a808c281..67be560778 100644 --- a/openair2/GNB_APP/L1_nr_paramdef.h +++ b/openair2/GNB_APP/L1_nr_paramdef.h @@ -46,6 +46,7 @@ #define CONFIG_STRING_L1_LOCAL_N_PORTD "local_n_portd" #define CONFIG_STRING_L1_REMOTE_N_PORTD "remote_n_portd" #define CONFIG_STRING_L1_TRANSPORT_N_PREFERENCE "tr_n_preference" +#define CONFIG_STRING_L1_PUSCH_PROC_THREADS "pusch_proc_threads" /*----------------------------------------------------------------------------------------------------------------------------------------------------*/ /* L1 configuration parameters */ @@ -61,6 +62,7 @@ {CONFIG_STRING_L1_REMOTE_N_PORTC, NULL, 0, uptr:NULL, defintval:50030, TYPE_UINT, 0}, \ {CONFIG_STRING_L1_LOCAL_N_PORTD, NULL, 0, uptr:NULL, defintval:50031, TYPE_UINT, 0}, \ {CONFIG_STRING_L1_REMOTE_N_PORTD, NULL, 0, uptr:NULL, defintval:50031, TYPE_UINT, 0}, \ +{CONFIG_STRING_L1_PUSCH_PROC_THREADS, NULL, 0, uptr:NULL, defintval:1, TYPE_UINT, 0} \ } #define L1_CC_IDX 0 #define L1_TRANSPORT_N_PREFERENCE_IDX 1 @@ -71,6 +73,7 @@ #define L1_REMOTE_N_PORTC_IDX 6 #define L1_LOCAL_N_PORTD_IDX 7 #define L1_REMOTE_N_PORTD_IDX 8 +#define L1_PUSCH_PROC_THREADS 9 /*----------------------------------------------------------------------------------------------------------------------------------------------------*/ #endif diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 1bdd6c0937..72b4e8b3b8 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -51,7 +51,8 @@ #include "nfapi_vnf.h" #include "nfapi_pnf.h" -#include "L1_paramdef.h" +//#include "L1_paramdef.h" +#include "L1_nr_paramdef.h" #include "MACRLC_paramdef.h" #include "common/config/config_userapi.h" //#include "RRC_config_tools.h" @@ -166,6 +167,8 @@ void prepare_scc(NR_ServingCellConfigCommon_t *scc) { // scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rsrp_ThresholdSSB_SUL = CALLOC(1,sizeof(NR_RSRP_Range_t)); scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing = CALLOC(1,sizeof(NR_SubcarrierSpacing_t)); scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg3_transformPrecoder = CALLOC(1,sizeof(long)); + // 0 - ENABLE, 1 - DISABLE, hence explicitly setting to DISABLED. + *scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg3_transformPrecoder = NR_PUSCH_Config__transformPrecoder_disabled; scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon = CALLOC(1,sizeof(NR_SetupRelease_PUSCH_ConfigCommon_t)); scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->present = NR_SetupRelease_PUSCH_ConfigCommon_PR_setup; scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup = CALLOC(1,sizeof(struct NR_PUSCH_ConfigCommon)); @@ -403,6 +406,8 @@ void RCconfig_NR_L1(void) { RC.gNB[j]->Mod_id = j; } + RC.gNB[j]->pusch_proc_threads = *(L1_ParamList.paramarray[j][L1_PUSCH_PROC_THREADS].uptr); + if(strcmp(*(L1_ParamList.paramarray[j][L1_TRANSPORT_N_PREFERENCE_IDX].strptr), "local_mac") == 0) { //sf_ahead = 2; // Need 4 subframe gap between RX and TX }else if (strcmp(*(L1_ParamList.paramarray[j][L1_TRANSPORT_N_PREFERENCE_IDX].strptr), "nfapi") == 0) { @@ -431,7 +436,7 @@ void RCconfig_NR_L1(void) { mac_top_init_gNB(); - configure_nfapi_pnf(RC.gNB[j]->eth_params_n.remote_addr, RC.gNB[j]->eth_params_n.remote_portc, RC.gNB[j]->eth_params_n.my_addr, RC.gNB[j]->eth_params_n.my_portd, RC.gNB[j]->eth_params_n .remote_portd); + configure_nr_nfapi_pnf(RC.gNB[j]->eth_params_n.remote_addr, RC.gNB[j]->eth_params_n.remote_portc, RC.gNB[j]->eth_params_n.my_addr, RC.gNB[j]->eth_params_n.my_portd, RC.gNB[j]->eth_params_n .remote_portd); }else { // other midhaul } }// for (j = 0; j < RC.nb_nr_L1_inst; j++) @@ -512,8 +517,8 @@ void RCconfig_nr_macrlc() { //sf_ahead = 2; // Cannot cope with 4 subframes between RX and TX - set it to 2 - printf("**************** vnf_port:%d\n", RC.mac[j]->eth_params_s.my_portc); - configure_nfapi_vnf(RC.nrmac[j]->eth_params_s.my_addr, RC.nrmac[j]->eth_params_s.my_portc); + printf("**************** vnf_port:%d\n", RC.nrmac[j]->eth_params_s.my_portc); + configure_nr_nfapi_vnf(RC.nrmac[j]->eth_params_s.my_addr, RC.nrmac[j]->eth_params_s.my_portc); printf("**************** RETURNED FROM configure_nfapi_vnf() vnf_port:%d\n", RC.nrmac[j]->eth_params_s.my_portc); }else { // other midhaul AssertFatal(1==0,"MACRLC %d: %s unknown southbound midhaul\n",j,*(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_S_PREFERENCE_IDX].strptr)); @@ -526,6 +531,101 @@ void RCconfig_nr_macrlc() { } +void config_security(gNB_RRC_INST *rrc) +{ + paramdef_t logparams_defaults[] = SECURITY_GLOBALPARAMS_DESC; + int ret = config_get(logparams_defaults, + sizeof(logparams_defaults) / sizeof(paramdef_t), + CONFIG_STRING_SECURITY); + int i; + + if (ret < 0) { + LOG_W(RRC, "configuration file does not contain a \"security\" section, applying default parameters (no security)\n"); + rrc->security.ciphering_algorithms[0] = 0; /* nea0 = no ciphering */ + rrc->security.ciphering_algorithms_count = 1; + rrc->security.integrity_algorithms[0] = 0; /* nia0 = no integrity */ + rrc->security.integrity_algorithms_count = 1; + return; + } + + if (logparams_defaults[SECURITY_CONFIG_CIPHERING_IDX].numelt > 4) { + LOG_E(RRC, "too much ciphering algorithms in section \"security\" of the configuration file, maximum is 4\n"); + exit(1); + } + if (logparams_defaults[SECURITY_CONFIG_INTEGRITY_IDX].numelt > 4) { + LOG_E(RRC, "too much integrity algorithms in section \"security\" of the configuration file, maximum is 4\n"); + exit(1); + } + + /* get ciphering algorithms */ + rrc->security.ciphering_algorithms_count = 0; + for (i = 0; i < logparams_defaults[SECURITY_CONFIG_CIPHERING_IDX].numelt; i++) { + if (!strcmp(logparams_defaults[SECURITY_CONFIG_CIPHERING_IDX].strlistptr[i], "nea0")) { + rrc->security.ciphering_algorithms[rrc->security.ciphering_algorithms_count] = 0; + rrc->security.ciphering_algorithms_count++; + continue; + } + if (!strcmp(logparams_defaults[SECURITY_CONFIG_CIPHERING_IDX].strlistptr[i], "nea1")) { + rrc->security.ciphering_algorithms[rrc->security.ciphering_algorithms_count] = 1; + rrc->security.ciphering_algorithms_count++; + continue; + } + if (!strcmp(logparams_defaults[SECURITY_CONFIG_CIPHERING_IDX].strlistptr[i], "nea2")) { + rrc->security.ciphering_algorithms[rrc->security.ciphering_algorithms_count] = 2; + rrc->security.ciphering_algorithms_count++; + continue; + } + if (!strcmp(logparams_defaults[SECURITY_CONFIG_CIPHERING_IDX].strlistptr[i], "nea3")) { + rrc->security.ciphering_algorithms[rrc->security.ciphering_algorithms_count] = 3; + rrc->security.ciphering_algorithms_count++; + continue; + } + LOG_E(RRC, "unknown ciphering algorithm \"%s\" in section \"security\" of the configuration file\n", + logparams_defaults[SECURITY_CONFIG_CIPHERING_IDX].strlistptr[i]); + exit(1); + } + + /* get integrity algorithms */ + rrc->security.integrity_algorithms_count = 0; + for (i = 0; i < logparams_defaults[SECURITY_CONFIG_INTEGRITY_IDX].numelt; i++) { + if (!strcmp(logparams_defaults[SECURITY_CONFIG_INTEGRITY_IDX].strlistptr[i], "nia0")) { + rrc->security.integrity_algorithms[rrc->security.integrity_algorithms_count] = 0; + rrc->security.integrity_algorithms_count++; + continue; + } + if (!strcmp(logparams_defaults[SECURITY_CONFIG_INTEGRITY_IDX].strlistptr[i], "nia1")) { + rrc->security.integrity_algorithms[rrc->security.integrity_algorithms_count] = 1; + rrc->security.integrity_algorithms_count++; + continue; + } + if (!strcmp(logparams_defaults[SECURITY_CONFIG_INTEGRITY_IDX].strlistptr[i], "nia2")) { + rrc->security.integrity_algorithms[rrc->security.integrity_algorithms_count] = 2; + rrc->security.integrity_algorithms_count++; + continue; + } + if (!strcmp(logparams_defaults[SECURITY_CONFIG_INTEGRITY_IDX].strlistptr[i], "nia3")) { + rrc->security.integrity_algorithms[rrc->security.integrity_algorithms_count] = 3; + rrc->security.integrity_algorithms_count++; + continue; + } + LOG_E(RRC, "unknown integrity algorithm \"%s\" in section \"security\" of the configuration file\n", + logparams_defaults[SECURITY_CONFIG_INTEGRITY_IDX].strlistptr[i]); + exit(1); + } + + if (rrc->security.ciphering_algorithms_count == 0) { + LOG_W(RRC, "no preferred ciphering algorithm set in configuration file, applying default parameters (no security)\n"); + rrc->security.ciphering_algorithms[0] = 0; /* nea0 = no ciphering */ + rrc->security.ciphering_algorithms_count = 1; + } + + if (rrc->security.integrity_algorithms_count == 0) { + LOG_W(RRC, "no preferred integrity algorithm set in configuration file, applying default parameters (no security)\n"); + rrc->security.integrity_algorithms[0] = 0; /* nia0 = no integrity */ + rrc->security.integrity_algorithms_count = 1; + } +} + void RCconfig_NRRRC(MessageDef *msg_p, uint32_t i, gNB_RRC_INST *rrc) { int num_gnbs = 0; @@ -728,7 +828,7 @@ void RCconfig_NRRRC(MessageDef *msg_p, uint32_t i, gNB_RRC_INST *rrc) { memcpy(&rrc->configuration, &NRRRC_CONFIGURATION_REQ(msg_p), sizeof(NRRRC_CONFIGURATION_REQ(msg_p))); }//End if (num_gnbs>0) - + config_security(rrc); }//End RCconfig_NRRRC function int RCconfig_nr_gtpu(void ) { diff --git a/openair2/GNB_APP/gnb_paramdef.h b/openair2/GNB_APP/gnb_paramdef.h index 1f6999d82e..fc545c8d51 100644 --- a/openair2/GNB_APP/gnb_paramdef.h +++ b/openair2/GNB_APP/gnb_paramdef.h @@ -82,7 +82,6 @@ typedef enum { /* global parameters, not under a specific section */ #define GNB_CONFIG_STRING_ASN1_VERBOSITY "Asn1_verbosity" #define GNB_CONFIG_STRING_ACTIVE_GNBS "Active_gNBs" -#define GNB_CONFIG_PUSCH_THREADS "Num_Threads_PUSCH" /*--------------------------------------------------------------------------------------------------------------------------------------------------------------*/ /* global configuration parameters */ /* optname helpstr paramflags XXXptr defXXXval type numelt */ @@ -92,10 +91,6 @@ typedef enum { {GNB_CONFIG_STRING_ACTIVE_GNBS, NULL, 0, uptr:NULL, defstrval:NULL, TYPE_STRINGLIST, 0} \ } -#define NUM_THREADS_DESC { \ -{GNB_CONFIG_PUSCH_THREADS, NULL, 0, uptr:&num_threads_pusch, defuintval:1, TYPE_UINT, 0} \ -} - #define GNB_ASN1_VERBOSITY_IDX 0 #define GNB_ACTIVE_GNBS_IDX 1 @@ -460,4 +455,27 @@ typedef enum { #define CONFIG_HLP_WORKER "coding and FEP worker thread WORKER_DISABLE or WORKER_ENABLE\n" #define CONFIG_HLP_PARALLEL "PARALLEL_SINGLE_THREAD, PARALLEL_RU_L1_SPLIT, or PARALLEL_RU_L1_TRX_SPLIT(RU_L1_TRX_SPLIT by defult)\n" /*-------------------------------------------------------------------------------------------------------------------------------------------------------------*/ + + +/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ +/* security configuration */ +/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ +#define CONFIG_STRING_SECURITY "security" + +#define SECURITY_CONFIG_CIPHERING "ciphering_algorithms" +#define SECURITY_CONFIG_INTEGRITY "integrity_algorithms" + +/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ +/* security configuration */ +/* optname help paramflags XXXptr defXXXval type numelt */ +/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ +#define SECURITY_GLOBALPARAMS_DESC { \ + {SECURITY_CONFIG_CIPHERING, "preferred ciphering algorithms\n", 0, strlistptr:NULL, defstrlistval:NULL, TYPE_STRINGLIST, 0}, \ + {SECURITY_CONFIG_INTEGRITY, "preferred integrity algorithms\n", 0, strlistptr:NULL, defstrlistval:NULL, TYPE_STRINGLIST, 0}, \ +} + +#define SECURITY_CONFIG_CIPHERING_IDX 0 +#define SECURITY_CONFIG_INTEGRITY_IDX 1 +/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ + #endif diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c index e720c1dfec..bf8202f622 100644 --- a/openair2/LAYER2/MAC/pre_processor.c +++ b/openair2/LAYER2/MAC/pre_processor.c @@ -734,7 +734,7 @@ void calculate_max_mcs_min_rb(module_id_t mod_id, /* find maximum MCS */ while ((phr - *tx_power < 0 || tbs > bytes) && *mcs > 3) { - mcs--; + (*mcs)--; tbs = get_TBS_UL(*mcs, rb_table[*rb_index]); *tx_power = estimate_ue_tx_power(tbs * 8, rb_table[*rb_index], 0, Ncp, 0); } diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_compute_tbs_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_compute_tbs_common.c index 30dccea2a9..452ed45b3a 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_compute_tbs_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_compute_tbs_common.c @@ -82,8 +82,11 @@ uint32_t nr_compute_tbs(uint16_t Qm, } } } - //printf("Ninfo %d nbp_re %d nb_re %d Qm %d, R %d, tbs %d\n", Ninfo, nbp_re, nb_re, Qm, R, nr_tbs); + + LOG_D(PHY, "In %s: Ninfo %d nbp_re %d nb_re %d Qm %d, R %d, tbs %d\n", __FUNCTION__, Ninfo, nbp_re, nb_re, Qm, R, nr_tbs); + return nr_tbs; + } diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h index d8583167dd..381dce11b2 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h @@ -20,7 +20,7 @@ */ /* \file nr_mac.h - * \brief common MAC data structures, constant, and function prototype + * \brief common MAC data structures and constants * \author R. Knopp, K.H. HSU, G. Casati * \date 2019 * \version 0.1 @@ -37,13 +37,30 @@ #include #include +#define TABLE_38213_13_1_NUM_INDEXES 15 +#define TABLE_38213_13_2_NUM_INDEXES 14 +#define TABLE_38213_13_3_NUM_INDEXES 9 +#define TABLE_38213_13_4_NUM_INDEXES 16 +#define TABLE_38213_13_5_NUM_INDEXES 9 +#define TABLE_38213_13_6_NUM_INDEXES 10 +#define TABLE_38213_13_7_NUM_INDEXES 12 +#define TABLE_38213_13_8_NUM_INDEXES 8 +#define TABLE_38213_13_9_NUM_INDEXES 4 +#define TABLE_38213_13_10_NUM_INDEXES 8 +#define TABLE_38213_13_11_NUM_INDEXES 16 +#define TABLE_38213_13_12_NUM_INDEXES 14 + +// Definitions for MAC control and data #define NR_BCCH_DL_SCH 3 // SI - #define NR_BCCH_BCH 5 // MIB - #define CCCH_PAYLOAD_SIZE_MAX 128 - #define RAR_PAYLOAD_SIZE_MAX 128 +#define MAX_BWP_SIZE 275 + +typedef enum frequency_range_e { + FR1 = 0, + FR2 +} frequency_range_t; // For both DL/UL-SCH // Except: @@ -102,22 +119,22 @@ typedef NR_BSR_SHORT NR_BSR_SHORT_TRUNCATED; // Long BSR for all logical channel group ID typedef struct { - uint8_t Buffer_size7: 8; - uint8_t Buffer_size6: 8; - uint8_t Buffer_size5: 8; - uint8_t Buffer_size4: 8; - uint8_t Buffer_size3: 8; - uint8_t Buffer_size2: 8; - uint8_t Buffer_size1: 8; - uint8_t Buffer_size0: 8; - uint8_t LcgID0: 1; - uint8_t LcgID1: 1; - uint8_t LcgID2: 1; - uint8_t LcgID3: 1; - uint8_t LcgID4: 1; - uint8_t LcgID5: 1; - uint8_t LcgID6: 1; - uint8_t LcgID7: 1; + uint8_t LcgID0: 1; // octet 1 [0] + uint8_t LcgID1: 1; // octet 1 [1] + uint8_t LcgID2: 1; // octet 1 [2] + uint8_t LcgID3: 1; // octet 1 [3] + uint8_t LcgID4: 1; // octet 1 [4] + uint8_t LcgID5: 1; // octet 1 [5] + uint8_t LcgID6: 1; // octet 1 [6] + uint8_t LcgID7: 1; // octet 1 [7] + uint8_t Buffer_size0: 8; // octet 2 [7:0] + uint8_t Buffer_size1: 8; // octet 3 [7:0] + uint8_t Buffer_size2: 8; // octet 4 [7:0] + uint8_t Buffer_size3: 8; // octet 5 [7:0] + uint8_t Buffer_size4: 8; // octet 6 [7:0] + uint8_t Buffer_size5: 8; // octet 7 [7:0] + uint8_t Buffer_size6: 8; // octet 8 [7:0] + uint8_t Buffer_size7: 8; // octet 9 [7:0] } __attribute__ ((__packed__)) NR_BSR_LONG; typedef NR_BSR_LONG NR_BSR_LONG_TRUNCATED; @@ -339,6 +356,113 @@ typedef struct { #define NR_MAX_NUM_LCGID 8 #define MAX_RLC_SDU_SUBHEADER_SIZE 3 +//=========== +// PRACH defs +//=========== + +// =============================================== +// SSB to RO mapping public defines and structures +// =============================================== +#define MAX_SSB_PER_RO (16) // Maximum number of SSBs that can be mapped to a single RO +#define MAX_TDM (7) // Maximum nb of PRACH occasions TDMed in a slot +#define MAX_FDM (8) // Maximum nb of PRACH occasions FDMed in a slot + +// PRACH occasion details +typedef struct prach_occasion_info { + uint8_t start_symbol; // 0 - 13 (14 symbols in a slot) + uint8_t fdm; // 0-7 (possible values of msg1-FDM: 1, 2, 4 or 8) + uint8_t slot; // 0 - 159 (maximum number of slots in a 10ms frame - @ 240kHz) + uint8_t frame; // 0 - 15 (maximum number of frames in a 160ms association pattern) + uint8_t mapped_ssb_idx[MAX_SSB_PER_RO]; // List of mapped SSBs + uint8_t nb_mapped_ssb; + uint16_t format; // RO preamble format +} prach_occasion_info_t; + +// PRACH occasion slot details +// A PRACH occasion slot is a series of PRACH occasions in time (symbols) and frequency +typedef struct prach_occasion_slot { + prach_occasion_info_t prach_occasion[MAX_TDM][MAX_FDM]; // Starting symbol of each PRACH occasions in a slot + uint8_t nb_of_prach_occasion_in_time; + uint8_t nb_of_prach_occasion_in_freq; +} prach_occasion_slot_t; + +//========= +// DCI defs +//========= + +typedef enum { + NR_DL_DCI_FORMAT_1_0 = 0, + NR_DL_DCI_FORMAT_1_1, + NR_DL_DCI_FORMAT_2_0, + NR_DL_DCI_FORMAT_2_1, + NR_DL_DCI_FORMAT_2_2, + NR_DL_DCI_FORMAT_2_3, + NR_UL_DCI_FORMAT_0_0, + NR_UL_DCI_FORMAT_0_1 +} nr_dci_format_t; + +typedef enum { + NR_RNTI_new = 0, + NR_RNTI_C, + NR_RNTI_RA, + NR_RNTI_P, + NR_RNTI_CS, + NR_RNTI_TC, + NR_RNTI_SP_CSI, + NR_RNTI_SI, + NR_RNTI_SFI, + NR_RNTI_INT, + NR_RNTI_TPC_PUSCH, + NR_RNTI_TPC_PUCCH, + NR_RNTI_TPC_SRS, + NR_RNTI_MCS_C, +} nr_rnti_type_t; + +typedef enum subcarrier_spacing_e { + scs_15kHz = 0x1, + scs_30kHz = 0x2, + scs_60kHz = 0x4, + scs_120kHz = 0x8, + scs_240kHz = 0x16 +} subcarrier_spacing_t; + +typedef enum channel_bandwidth_e { + bw_5MHz = 0x1, + bw_10MHz = 0x2, + bw_20MHz = 0x4, + bw_40MHz = 0x8, + bw_80MHz = 0x16, + bw_100MHz = 0x32 +} channel_bandwidth_t; + +typedef enum nr_ssb_and_cset_mux_pattern_type_e { + NR_SSB_AND_CSET_MUX_PATTERN_TYPE1=1, + NR_SSB_AND_CSET_MUX_PATTERN_TYPE2, + NR_SSB_AND_CSET_MUX_PATTERN_TYPE3 +} nr_ssb_and_cset_mux_pattern_type_t; + +typedef enum { + SFN_C_MOD_2_EQ_0, + SFN_C_MOD_2_EQ_1, + SFN_C_IMPOSSIBLE +} SFN_C_TYPE; + +typedef struct Type0_PDCCH_CSS_config_s { + int32_t num_rbs; + int32_t num_symbols; + int32_t rb_offset; // Offset from SSB RB0 + uint32_t type0_pdcch_ss_mux_pattern; + uint16_t frame; + SFN_C_TYPE sfn_c; + uint32_t n_c; + uint32_t n_0; + uint32_t number_of_search_space_per_slot; + uint32_t first_symbol_index; + uint32_t search_space_duration; + uint32_t ssb_length; + uint32_t ssb_index; + uint32_t cset_start_rb; +} NR_Type0_PDCCH_CSS_config_t; #endif /*__LAYER2_MAC_H__ */ diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index d056b06450..5d1b08bcf6 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -2380,8 +2380,44 @@ uint8_t get_K_ptrs(uint16_t nrb0, uint16_t nrb1, uint16_t N_RB) { return 4; } -uint16_t nr_dci_size(NR_ServingCellConfigCommon_t *scc, - NR_CellGroupConfig_t *secondaryCellGroup, +// Set the transform precoding status according to 6.1.3 of 3GPP TS 38.214 version 16.3.0 Release 16: +// - "UE procedure for applying transform precoding on PUSCH" +uint8_t get_transformPrecoding(const NR_ServingCellConfigCommon_t *scc, + const NR_PUSCH_Config_t *pusch_config, + const NR_BWP_Uplink_t *ubwp, + uint8_t *dci_format, + int rnti_type, + uint8_t configuredGrant){ + + if (configuredGrant) { + if (ubwp->bwp_Dedicated->configuredGrantConfig) { + if (ubwp->bwp_Dedicated->configuredGrantConfig->choice.setup->transformPrecoder) { + return *ubwp->bwp_Dedicated->configuredGrantConfig->choice.setup->transformPrecoder; + } + } + } + + if (rnti_type != NR_RNTI_RA) { + if (*dci_format != NR_UL_DCI_FORMAT_0_0) { + if (pusch_config->transformPrecoder != NULL) { + return *pusch_config->transformPrecoder; + } + } + } + + if (scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg3_transformPrecoder == NULL) { + return 1; // Transformprecoding disabled + } else { + LOG_D(PHY, "MAC_COMMON: Transform Precodig enabled through msg3_transformPrecoder\n"); + return 0; // Enabled + } + + LOG_E(MAC, "In %s: could not fetch transform precoder status...\n", __FUNCTION__); + return -1; +} + +uint16_t nr_dci_size(const NR_ServingCellConfigCommon_t *scc, + const NR_CellGroupConfig_t *secondaryCellGroup, dci_pdu_rel15_t *dci_pdu, nr_dci_format_t format, nr_rnti_type_t rnti_type, @@ -2442,8 +2478,8 @@ uint16_t nr_dci_size(NR_ServingCellConfigCommon_t *scc, rbg_size_config = 1; else rbg_size_config = 0; - numRBG = getNRBG(NRRIV2BW(ubwp->bwp_Common->genericParameters.locationAndBandwidth,275), - NRRIV2PRBOFFSET(ubwp->bwp_Common->genericParameters.locationAndBandwidth,275), + numRBG = getNRBG(NRRIV2BW(ubwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE), + NRRIV2PRBOFFSET(ubwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE), rbg_size_config); if (pusch_Config->resourceAllocation == 0) dci_pdu->frequency_domain_assignment.nbits = numRBG; @@ -2517,16 +2553,8 @@ uint16_t nr_dci_size(NR_ServingCellConfigCommon_t *scc, } } // Precoding info and number of layers - long transformPrecoder; - if (pusch_Config->transformPrecoder == NULL){ - // if transform precoder is null, apply the values from msg3 - if(scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg3_transformPrecoder == NULL) - transformPrecoder = 1; - else - transformPrecoder = 0; - } - else - transformPrecoder = *pusch_Config->transformPrecoder; + long transformPrecoder = get_transformPrecoding(scc, pusch_Config, ubwp, (uint8_t*)&format, rnti_type, 0); + if (pusch_Config->txConfig != NULL){ if (*pusch_Config->txConfig == NR_PUSCH_Config__txConfig_codebook){ if (pusch_antenna_ports > 1) { @@ -2637,8 +2665,8 @@ uint16_t nr_dci_size(NR_ServingCellConfigCommon_t *scc, size += dci_pdu->bwp_indicator.nbits; // Freq domain assignment rbg_size_config = secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->rbg_Size; - numRBG = getNRBG(NRRIV2BW(bwp->bwp_Common->genericParameters.locationAndBandwidth,275), - NRRIV2PRBOFFSET(bwp->bwp_Common->genericParameters.locationAndBandwidth,275), + numRBG = getNRBG(NRRIV2BW(bwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE), + NRRIV2PRBOFFSET(bwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE), rbg_size_config); if (pdsch_config->resourceAllocation == 0) dci_pdu->frequency_domain_assignment.nbits = numRBG; @@ -3039,6 +3067,49 @@ bool set_dl_ptrs_values(NR_PTRS_DownlinkConfig_t *ptrs_config, //printf("[MAC] PTRS is set K= %u L= %u\n", *K_ptrs,1<<*L_ptrs); return valid; } +void get_band(uint64_t downlink_frequency, + uint16_t *current_band, + int32_t *current_offset, + lte_frame_type_t *current_type) +{ + int ind; + uint64_t center_frequency_khz; + uint64_t center_freq_diff_khz; + uint64_t dl_freq_khz = downlink_frequency/1000; + + center_freq_diff_khz = 999999999999999999; // 2^64 + *current_band = 0; + + for ( ind=0; + ind < sizeof(nr_bandtable) / sizeof(nr_bandtable[0]); + ind++) { + + LOG_I(PHY, "Scanning band %d, dl_min %"PRIu64", ul_min %"PRIu64"\n", nr_bandtable[ind].band, nr_bandtable[ind].dl_min,nr_bandtable[ind].ul_min); + + if ( nr_bandtable[ind].dl_min <= dl_freq_khz && nr_bandtable[ind].dl_max >= dl_freq_khz ) { + + center_frequency_khz = (nr_bandtable[ind].dl_max + nr_bandtable[ind].dl_min)/2; + if (abs(dl_freq_khz - center_frequency_khz) < center_freq_diff_khz){ + *current_band = nr_bandtable[ind].band; + *current_offset = (nr_bandtable[ind].ul_min - nr_bandtable[ind].dl_min)*1000; + center_freq_diff_khz = abs(dl_freq_khz - center_frequency_khz); + + if (*current_offset == 0) + *current_type = TDD; + else + *current_type = FDD; + } + } + } + + LOG_I( PHY, "DL frequency %"PRIu64": band %d, frame_type %d, UL frequency %"PRIu64"\n", + downlink_frequency, *current_band, *current_type, downlink_frequency+*current_offset); + + AssertFatal(*current_band != 0, + "Can't find EUTRA band for frequency %lu\n", downlink_frequency); +} + + uint32_t get_ssb_slot(uint32_t ssb_index){ // this function now only support f <= 3GHz return ssb_index & 0x3 ; diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h index e41ca67229..087d316567 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h @@ -20,13 +20,12 @@ */ /*! \file mac.h -* \brief MAC data structures, constant, and function prototype +* \brief common MAC function prototypes * \author Navid Nikaein and Raymond Knopp, WIE-TAI CHEN * \date Dec. 2019 * \version 0.1 * \company Eurecom * \email raymond.knopp@eurecom.fr - */ #ifndef __LAYER2_NR_MAC_COMMON_H__ @@ -38,128 +37,6 @@ #include "nr_mac.h" #include "openair1/PHY/impl_defs_nr.h" -#define TABLE_38213_13_1_NUM_INDEXES 15 -#define TABLE_38213_13_2_NUM_INDEXES 14 -#define TABLE_38213_13_3_NUM_INDEXES 9 -#define TABLE_38213_13_4_NUM_INDEXES 16 -#define TABLE_38213_13_5_NUM_INDEXES 9 -#define TABLE_38213_13_6_NUM_INDEXES 10 -#define TABLE_38213_13_7_NUM_INDEXES 12 -#define TABLE_38213_13_8_NUM_INDEXES 8 -#define TABLE_38213_13_9_NUM_INDEXES 4 -#define TABLE_38213_13_10_NUM_INDEXES 8 -#define TABLE_38213_13_11_NUM_INDEXES 16 -#define TABLE_38213_13_12_NUM_INDEXES 14 - - -// =============================================== -// SSB to RO mapping public defines and structures -// =============================================== -#define MAX_SSB_PER_RO (16) // Maximum number of SSBs that can be mapped to a single RO -#define MAX_TDM (7) // Maximum nb of PRACH occasions TDMed in a slot -#define MAX_FDM (8) // Maximum nb of PRACH occasions FDMed in a slot - -typedef enum frequency_range_e { - FR1 = 0, - FR2 -} frequency_range_t; - -// PRACH occasion details -typedef struct prach_occasion_info { - uint8_t start_symbol; // 0 - 13 (14 symbols in a slot) - uint8_t fdm; // 0-7 (possible values of msg1-FDM: 1, 2, 4 or 8) - uint8_t slot; // 0 - 159 (maximum number of slots in a 10ms frame - @ 240kHz) - uint8_t frame; // 0 - 15 (maximum number of frames in a 160ms association pattern) - uint8_t mapped_ssb_idx[MAX_SSB_PER_RO]; // List of mapped SSBs - uint8_t nb_mapped_ssb; - uint16_t format; // RO preamble format -} prach_occasion_info_t; - -// PRACH occasion slot details -// A PRACH occasion slot is a series of PRACH occasions in time (symbols) and frequency -typedef struct prach_occasion_slot { - prach_occasion_info_t prach_occasion[MAX_TDM][MAX_FDM]; // Starting symbol of each PRACH occasions in a slot - uint8_t nb_of_prach_occasion_in_time; - uint8_t nb_of_prach_occasion_in_freq; -} prach_occasion_slot_t; - -// ======================================== - - -typedef enum { - NR_DL_DCI_FORMAT_1_0 = 0, - NR_DL_DCI_FORMAT_1_1, - NR_DL_DCI_FORMAT_2_0, - NR_DL_DCI_FORMAT_2_1, - NR_DL_DCI_FORMAT_2_2, - NR_DL_DCI_FORMAT_2_3, - NR_UL_DCI_FORMAT_0_0, - NR_UL_DCI_FORMAT_0_1 -} nr_dci_format_t; - -typedef enum { - NR_RNTI_new = 0, - NR_RNTI_C, - NR_RNTI_RA, - NR_RNTI_P, - NR_RNTI_CS, - NR_RNTI_TC, - NR_RNTI_SP_CSI, - NR_RNTI_SI, - NR_RNTI_SFI, - NR_RNTI_INT, - NR_RNTI_TPC_PUSCH, - NR_RNTI_TPC_PUCCH, - NR_RNTI_TPC_SRS, - NR_RNTI_MCS_C, -} nr_rnti_type_t; - -typedef enum subcarrier_spacing_e { - scs_15kHz = 0x1, - scs_30kHz = 0x2, - scs_60kHz = 0x4, - scs_120kHz = 0x8, - scs_240kHz = 0x16 -} subcarrier_spacing_t; - -typedef enum channel_bandwidth_e { - bw_5MHz = 0x1, - bw_10MHz = 0x2, - bw_20MHz = 0x4, - bw_40MHz = 0x8, - bw_80MHz = 0x16, - bw_100MHz = 0x32 -} channel_bandwidth_t; - -typedef enum nr_ssb_and_cset_mux_pattern_type_e { - NR_SSB_AND_CSET_MUX_PATTERN_TYPE1=1, - NR_SSB_AND_CSET_MUX_PATTERN_TYPE2, - NR_SSB_AND_CSET_MUX_PATTERN_TYPE3 -} nr_ssb_and_cset_mux_pattern_type_t; - -typedef enum { - SFN_C_MOD_2_EQ_0, - SFN_C_MOD_2_EQ_1, - SFN_C_IMPOSSIBLE -} SFN_C_TYPE; - -typedef struct Type0_PDCCH_CSS_config_s { - int32_t num_rbs; - int32_t num_symbols; - int32_t rb_offset; // Offset from SSB RB0 - uint32_t type0_pdcch_ss_mux_pattern; - uint16_t frame; - SFN_C_TYPE sfn_c; - uint32_t n_c; - uint32_t n_0; - uint32_t number_of_search_space_per_slot; - uint32_t first_symbol_index; - uint32_t search_space_duration; - uint32_t ssb_length; - uint32_t ssb_index; - uint32_t cset_start_rb; -} NR_Type0_PDCCH_CSS_config_t; - uint16_t config_bandwidth(int mu, int nb_rb, int nr_band); void get_frame_type(uint16_t nr_bandP, uint8_t scs_index, lte_frame_type_t *current_type); @@ -176,8 +53,8 @@ int is_nr_DL_slot(NR_ServingCellConfigCommon_t *scc,slot_t slotP); int is_nr_UL_slot(NR_ServingCellConfigCommon_t *scc,slot_t slotP); -uint16_t nr_dci_size(NR_ServingCellConfigCommon_t *scc, - NR_CellGroupConfig_t *secondaryCellGroup, +uint16_t nr_dci_size(const NR_ServingCellConfigCommon_t *scc, + const NR_CellGroupConfig_t *secondaryCellGroup, dci_pdu_rel15_t *dci_pdu, nr_dci_format_t format, nr_rnti_type_t rnti_type, @@ -263,7 +140,22 @@ bool set_dl_ptrs_values(NR_PTRS_DownlinkConfig_t *ptrs_config, uint8_t *K_ptrs, uint8_t *L_ptrs,uint8_t *portIndex, uint8_t *nERatio,uint8_t *reOffset, uint8_t NrOfSymbols); +void get_band(uint64_t downlink_frequency, uint16_t *current_band, int32_t *current_offset, lte_frame_type_t *current_type); uint8_t get_num_dmrs_symbols(NR_PDSCH_Config_t *pdsch_Config,int dmrs_TypeA_Position,int NrOfSymbols); +/* \brief Set the transform precoding according to 6.1.3 of 3GPP TS 38.214 version 16.3.0 Release 16 +@param *pusch_config, pointer to pusch config +@param *ubwp pointer to uplink bwp +@param *dci_format pointer to dci format +@param rnti_type rnti type +@param configuredGrant indicates whether a configured grant was received or not +@returns transformPrecoding value */ +uint8_t get_transformPrecoding(const NR_ServingCellConfigCommon_t *scc, + const NR_PUSCH_Config_t *pusch_config, + const NR_BWP_Uplink_t *ubwp, + uint8_t *dci_format, + int rnti_type, + uint8_t configuredGrant); + #endif diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index 20fe84d819..f6bd5436bc 100755 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -82,6 +82,7 @@ int set_tdd_config_nr_ue(fapi_nr_config_request_t *cfg, } int nb_slots_per_period = ((1<tdd_table.tdd_period_in_slots = nb_slots_per_period; if ( (nrofDownlinkSymbols + nrofUplinkSymbols) == 0 ) AssertFatal(nb_slots_per_period == (nrofDownlinkSlots + nrofUplinkSlots), @@ -152,8 +153,7 @@ void config_common_ue(NR_UE_MAC_INST_t *mac, mac->phy_config.CC_id = cc_idP; // carrier config - - LOG_I(MAC, "Entering UE Config Common\n"); + LOG_D(MAC, "Entering UE Config Common\n"); cfg->carrier_config.dl_bandwidth = config_bandwidth(scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing, scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth, @@ -321,6 +321,47 @@ void config_common_ue(NR_UE_MAC_INST_t *mac, } +/** \brief This function performs some configuration routines according to clause 12 "Bandwidth part operation" 3GPP TS 38.213 version 16.3.0 Release 16 + @param NR_UE_MAC_INST_t mac: pointer to local MAC instance + @returns void + */ +void config_bwp_ue(NR_UE_MAC_INST_t *mac, uint16_t *bwp_ind, uint8_t *dci_format){ + + NR_ServingCellConfig_t *scd = mac->scg->spCellConfig->spCellConfigDedicated; + + if (bwp_ind && dci_format){ + + switch(*dci_format){ + case NR_UL_DCI_FORMAT_0_1: + mac->UL_BWP_Id = *bwp_ind; + break; + case NR_DL_DCI_FORMAT_1_1: + mac->DL_BWP_Id = *bwp_ind; + break; + default: + LOG_E(MAC, "In %s: failed to configure BWP Id from DCI with format %d \n", __FUNCTION__, *dci_format); + } + + } else { + + if (scd->firstActiveDownlinkBWP_Id) + mac->DL_BWP_Id = *scd->firstActiveDownlinkBWP_Id; + else if (scd->defaultDownlinkBWP_Id) + mac->DL_BWP_Id = *scd->defaultDownlinkBWP_Id; + else + mac->DL_BWP_Id = 1; + + if (scd->uplinkConfig && scd->uplinkConfig->firstActiveUplinkBWP_Id) + mac->UL_BWP_Id = *scd->uplinkConfig->firstActiveUplinkBWP_Id; + else + mac->UL_BWP_Id = 1; + + } + + LOG_D(MAC, "In %s setting DL_BWP_Id %ld UL_BWP_Id %ld \n", __FUNCTION__, mac->DL_BWP_Id, mac->UL_BWP_Id); + +} + /** \brief This function is relavant for the UE procedures for control. It loads the search spaces, the BWPs and the CORESETs into the MAC instance and \brief performs assert checks on the relevant RRC configuration. @param NR_UE_MAC_INST_t mac: pointer to local MAC instance @@ -328,15 +369,20 @@ void config_common_ue(NR_UE_MAC_INST_t *mac, */ void config_control_ue(NR_UE_MAC_INST_t *mac){ - uint8_t bwp_id = 1, coreset_id = 1, ss_id; + uint8_t coreset_id = 1, ss_id; + NR_ServingCellConfig_t *scd = mac->scg->spCellConfig->spCellConfigDedicated; AssertFatal(scd->downlinkBWP_ToAddModList != NULL, "downlinkBWP_ToAddModList is null\n"); AssertFatal(scd->downlinkBWP_ToAddModList->list.count == 1, "downlinkBWP_ToAddModList->list->count is %d\n", scd->downlinkBWP_ToAddModList->list.count); - NR_BWP_DownlinkCommon_t *bwp_Common = scd->downlinkBWP_ToAddModList->list.array[bwp_id - 1]->bwp_Common; + config_bwp_ue(mac, NULL, NULL); + NR_BWP_Id_t dl_bwp_id = mac->DL_BWP_Id; + AssertFatal(dl_bwp_id != 0, "DL_BWP_Id is 0!"); + + NR_BWP_DownlinkCommon_t *bwp_Common = scd->downlinkBWP_ToAddModList->list.array[dl_bwp_id - 1]->bwp_Common; AssertFatal(bwp_Common != NULL, "bwp_Common is null\n"); - NR_BWP_DownlinkDedicated_t *dl_bwp_Dedicated = scd->downlinkBWP_ToAddModList->list.array[bwp_id - 1]->bwp_Dedicated; + NR_BWP_DownlinkDedicated_t *dl_bwp_Dedicated = scd->downlinkBWP_ToAddModList->list.array[dl_bwp_id - 1]->bwp_Dedicated; AssertFatal(dl_bwp_Dedicated != NULL, "dl_bwp_Dedicated is null\n"); NR_SetupRelease_PDCCH_Config_t *pdcch_Config = dl_bwp_Dedicated->pdcch_Config; @@ -365,8 +411,8 @@ void config_control_ue(NR_UE_MAC_INST_t *mac){ AssertFatal(uplinkBWP_ToAddModList->list.count == 1, "uplinkBWP_ToAddModList->list->count is %d\n", uplinkBWP_ToAddModList->list.count); // check pdcch_Config, pdcch_ConfigCommon and DL BWP - mac->DLbwp[0] = scd->downlinkBWP_ToAddModList->list.array[bwp_id - 1]; - mac->coreset[bwp_id - 1][coreset_id - 1] = controlResourceSetToAddModList->list.array[0]; + mac->DLbwp[0] = scd->downlinkBWP_ToAddModList->list.array[dl_bwp_id - 1]; + mac->coreset[dl_bwp_id - 1][coreset_id - 1] = controlResourceSetToAddModList->list.array[0]; // Check dedicated UL BWP and pass to MAC mac->ULbwp[0] = uplinkBWP_ToAddModList->list.array[0]; @@ -378,7 +424,7 @@ void config_control_ue(NR_UE_MAC_INST_t *mac){ NR_SearchSpace_t *ss = searchSpacesToAddModList->list.array[ss_id]; AssertFatal(ss->controlResourceSetId != NULL, "ss->controlResourceSetId is null\n"); AssertFatal(ss->searchSpaceType != NULL, "ss->searchSpaceType is null\n"); - AssertFatal(*ss->controlResourceSetId == mac->coreset[bwp_id - 1][coreset_id - 1]->controlResourceSetId, "ss->controlResourceSetId is unknown\n"); + AssertFatal(*ss->controlResourceSetId == mac->coreset[dl_bwp_id - 1][coreset_id - 1]->controlResourceSetId, "ss->controlResourceSetId is unknown\n"); AssertFatal(ss->monitoringSymbolsWithinSlot != NULL, "NR_SearchSpace->monitoringSymbolsWithinSlot is null\n"); AssertFatal(ss->monitoringSymbolsWithinSlot->buf != NULL, "NR_SearchSpace->monitoringSymbolsWithinSlot->buf is null\n"); mac->SSpace[0][0][ss_id] = ss; @@ -389,7 +435,7 @@ void config_control_ue(NR_UE_MAC_INST_t *mac){ for (int css_id = 0; css_id < commonSearchSpaceList->list.count; css_id++) { NR_SearchSpace_t *css = commonSearchSpaceList->list.array[css_id]; AssertFatal(css->controlResourceSetId != NULL, "ss->controlResourceSetId is null\n"); - AssertFatal(*css->controlResourceSetId == mac->coreset[bwp_id - 1][coreset_id - 1]->controlResourceSetId, "ss->controlResourceSetId is unknown\n"); + AssertFatal(*css->controlResourceSetId == mac->coreset[dl_bwp_id - 1][coreset_id - 1]->controlResourceSetId, "ss->controlResourceSetId is unknown\n"); AssertFatal(css->searchSpaceType != NULL, "css->searchSpaceType is null\n"); AssertFatal(css->monitoringSymbolsWithinSlot != NULL, "css->monitoringSymbolsWithinSlot is null\n"); AssertFatal(css->monitoringSymbolsWithinSlot->buf != NULL, "css->monitoringSymbolsWithinSlot->buf is null\n"); @@ -414,15 +460,15 @@ void config_control_ue(NR_UE_MAC_INST_t *mac){ mac->search_space_zero->duration=NULL; // should be '1100 0000 0000 00'B (LSB first!), first two symbols in slot, adjust if needed mac->search_space_zero->monitoringSymbolsWithinSlot->buf[1] = 0; - mac->search_space_zero->monitoringSymbolsWithinSlot->buf[0] = (1<<7) | (1<<6); + mac->search_space_zero->monitoringSymbolsWithinSlot->buf[0] = (1<<7); mac->search_space_zero->monitoringSymbolsWithinSlot->size = 2; mac->search_space_zero->monitoringSymbolsWithinSlot->bits_unused = 2; // FIXME: update values from TS38.213 Section 10.1 Table 10.1-1: CCE aggregation levels and maximum number of PDCCH candidates per CCE aggregation level for CSS sets configured by searchSpaceSIB1 mac->search_space_zero->nrofCandidates->aggregationLevel1 = NR_SearchSpace__nrofCandidates__aggregationLevel1_n0; mac->search_space_zero->nrofCandidates->aggregationLevel2 = NR_SearchSpace__nrofCandidates__aggregationLevel2_n0; - mac->search_space_zero->nrofCandidates->aggregationLevel4 = NR_SearchSpace__nrofCandidates__aggregationLevel4_n0; - mac->search_space_zero->nrofCandidates->aggregationLevel8 = NR_SearchSpace__nrofCandidates__aggregationLevel8_n1; + mac->search_space_zero->nrofCandidates->aggregationLevel4 = NR_SearchSpace__nrofCandidates__aggregationLevel4_n2; + mac->search_space_zero->nrofCandidates->aggregationLevel8 = NR_SearchSpace__nrofCandidates__aggregationLevel8_n0; mac->search_space_zero->nrofCandidates->aggregationLevel16 = NR_SearchSpace__nrofCandidates__aggregationLevel16_n0; mac->search_space_zero->searchSpaceType->present = NR_SearchSpace__searchSpaceType_PR_common; @@ -440,7 +486,9 @@ void config_control_ue(NR_UE_MAC_INST_t *mac){ mac->coreset0->frequencyDomainResources.size = 6; mac->coreset0->frequencyDomainResources.bits_unused = 3; mac->coreset0->duration = 1; + mac->coreset0->cce_REG_MappingType.present=NR_ControlResourceSet__cce_REG_MappingType_PR_interleaved; mac->coreset0->cce_REG_MappingType.choice.interleaved=calloc(1,sizeof(*mac->coreset0->cce_REG_MappingType.choice.interleaved)); + mac->coreset0->cce_REG_MappingType.choice.interleaved->reg_BundleSize = NR_ControlResourceSet__cce_REG_MappingType__interleaved__reg_BundleSize_n6; mac->coreset0->cce_REG_MappingType.choice.interleaved->interleaverSize = NR_ControlResourceSet__cce_REG_MappingType__interleaved__interleaverSize_n2; mac->coreset0->cce_REG_MappingType.choice.interleaved->shiftIndex = NULL; mac->coreset0->precoderGranularity = NR_ControlResourceSet__precoderGranularity_sameAsREG_bundle; @@ -468,6 +516,7 @@ int nr_rrc_mac_config_req_ue( NR_CellGroupConfig_t *cell_group_config ){ NR_UE_MAC_INST_t *mac = get_mac_inst(module_id); + RA_config_t *ra = &mac->ra; // TODO do something FAPI-like P5 L1/L2 config interface in config_si, config_mib, etc. @@ -479,10 +528,8 @@ int nr_rrc_mac_config_req_ue( mac->scg = cell_group_config; mac->servCellIndex = *cell_group_config->spCellConfig->servCellIndex; config_control_ue(mac); - mac->msg3_frame = -1; // initialize to an invalid value - mac->msg3_slot = -1; if (cell_group_config->spCellConfig->reconfigurationWithSync) { - mac->rach_ConfigDedicated = cell_group_config->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink; + ra->rach_ConfigDedicated = cell_group_config->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink; mac->scc = cell_group_config->spCellConfig->reconfigurationWithSync->spCellConfigCommon; config_common_ue(mac,module_id,cc_idP); mac->crnti = cell_group_config->spCellConfig->reconfigurationWithSync->newUE_Identity; diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index 6bbbc00c00..dd0aa15c52 100755 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -20,7 +20,7 @@ */ /* \file mac_defs.h - * \brief MAC data structures, constant, and function prototype + * \brief MAC data structures and constants * \author R. Knopp, K.H. HSU * \date 2018 * \version 0.1 @@ -69,13 +69,107 @@ #include "PHY/defs_nr_common.h" #include "openair2/LAYER2/NR_MAC_COMMON/nr_mac.h" -#define NB_NR_UE_MAC_INST 1 -/*!\brief Maximum number of logical channl group IDs */ +// ========== +// NR UE defs +// ========== +#define NB_NR_UE_MAC_INST 1 +#define MAX_NUM_BWP 2 +#define NUM_SLOT_FRAME 10 /*!\brief value for indicating BSR Timer is not running */ #define NR_MAC_UE_BSR_TIMER_NOT_RUNNING (0xFFFF) +// ================================================ +// SSB to RO mapping private defines and structures +// ================================================ + +#define MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PERIOD (16) // Maximum association period is 16 +#define MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD (16) // Max association pattern period is 160ms and minimum PRACH configuration period is 10ms +#define MAX_NB_ASSOCIATION_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD (16) // Max nb of association periods in an association pattern period of 160ms +#define MAX_NB_FRAME_IN_PRACH_CONF_PERIOD (16) // Max PRACH configuration period is 160ms and frame is 10ms +#define MAX_NB_SLOT_IN_FRAME (160) // Max number of slots in a frame (@ SCS 240kHz = 160) +#define MAX_NB_FRAME_IN_ASSOCIATION_PATTERN_PERIOD (16) // Maximum number of frames in the maximum association pattern period +#define MAX_NB_SSB (64) // Maximum number of possible SSB indexes +#define MAX_RO_PER_SSB (8) // Maximum number of consecutive ROs that can be mapped to an SSB according to the ssb_per_RACH config + +// Maximum number of ROs that can be mapped to an SSB in an association pattern +// This is to reserve enough elements in the SSBs list for each mapped ROs for a single SSB +// An arbitrary maximum number is chosen to be safe: maximum number of slots in an association pattern * maximum number of ROs in a slot +#define MAX_NB_RO_PER_SSB_IN_ASSOCIATION_PATTERN (MAX_TDM*MAX_FDM*MAX_NB_SLOT_IN_FRAME*MAX_NB_FRAME_IN_ASSOCIATION_PATTERN_PERIOD) + +// =============== +// DCI fields defs +// =============== + +#define NBR_NR_FORMATS 8 // The number of formats is 8 (0_0, 0_1, 1_0, 1_1, 2_0, 2_1, 2_2, 2_3) +#define NBR_NR_DCI_FIELDS 56 // The number of different dci fields defined in TS 38.212 subclause 7.3.1 + +#define IDENTIFIER_DCI_FORMATS 0 +#define CARRIER_IND 1 +#define SUL_IND_0_1 2 +#define SLOT_FORMAT_IND 3 +#define PRE_EMPTION_IND 4 +#define BLOCK_NUMBER 5 +#define CLOSE_LOOP_IND 6 +#define BANDWIDTH_PART_IND 7 +#define SHORT_MESSAGE_IND 8 +#define SHORT_MESSAGES 9 +#define FREQ_DOM_RESOURCE_ASSIGNMENT_UL 10 +#define FREQ_DOM_RESOURCE_ASSIGNMENT_DL 11 +#define TIME_DOM_RESOURCE_ASSIGNMENT 12 +#define VRB_TO_PRB_MAPPING 13 +#define PRB_BUNDLING_SIZE_IND 14 +#define RATE_MATCHING_IND 15 +#define ZP_CSI_RS_TRIGGER 16 +#define FREQ_HOPPING_FLAG 17 +#define TB1_MCS 18 +#define TB1_NDI 19 +#define TB1_RV 20 +#define TB2_MCS 21 +#define TB2_NDI 22 +#define TB2_RV 23 +#define MCS 24 +#define NDI 25 +#define RV 26 +#define HARQ_PROCESS_NUMBER 27 +#define DAI_ 28 +#define FIRST_DAI 29 +#define SECOND_DAI 30 +#define TB_SCALING 31 +#define TPC_PUSCH 32 +#define TPC_PUCCH 33 +#define PUCCH_RESOURCE_IND 34 +#define PDSCH_TO_HARQ_FEEDBACK_TIME_IND 35 +#define SRS_RESOURCE_IND 36 +#define PRECOD_NBR_LAYERS 37 +#define ANTENNA_PORTS 38 +#define TCI 39 +#define SRS_REQUEST 40 +#define TPC_CMD 41 +#define CSI_REQUEST 42 +#define CBGTI 43 +#define CBGFI 44 +#define PTRS_DMRS 45 +#define BETA_OFFSET_IND 46 +#define DMRS_SEQ_INI 47 +#define UL_SCH_IND 48 +#define PADDING_NR_DCI 49 +#define SUL_IND_0_0 50 +#define RA_PREAMBLE_INDEX 51 +#define SUL_IND_1_0 52 +#define SS_PBCH_INDEX 53 +#define PRACH_MASK_INDEX 54 +#define RESERVED_NR_DCI 55 + +/*!\brief UE layer 2 status */ +typedef enum { + UE_CONNECTION_OK = 0, + UE_CONNECTION_LOST, + UE_PHY_RESYNCH, + UE_PHY_HO_PRACH +} NR_UE_L2_STATE_t; + // LTE structure, might need to be adapted for NR typedef struct { /// buffer status for each lcgid @@ -138,9 +232,6 @@ typedef struct { int16_t bucket_size[NR_MAX_NUM_LCID]; } NR_UE_SCHEDULING_INFO; - -#define MAX_NUM_BWP 2 - typedef enum { RA_UE_IDLE = 0, WAIT_RAR = 1, @@ -148,12 +239,76 @@ typedef enum { RA_SUCCEEDED = 3 } RA_state_t; +typedef struct { + + // pointer to RACH config dedicated + NR_RACH_ConfigDedicated_t *rach_ConfigDedicated; + /// state of RA procedure + RA_state_t ra_state; + /// RA contention type + uint8_t cfra; + /// RA rx frame offset: compensate RA rx offset introduced by OAI gNB. + uint8_t RA_offset; + /// RA-rnti + uint16_t ra_rnti; + /// Temporary CRNTI + uint16_t t_crnti; + /// number of attempt for rach + uint8_t RA_attempt_number; + /// Random-access procedure flag + uint8_t RA_active; + /// Flag for the Msg1 generation: enabled at every occurrence of nr prach slot + uint8_t generate_nr_prach; + + /// Random-access window counter + int16_t RA_window_cnt; + /// Flag to monitor if matching RAPID was received in RAR + uint8_t RA_RAPID_found; + /// Flag to monitor if BI was received in RAR + uint8_t RA_BI_found; + /// Random-access backoff counter + int16_t RA_backoff_indicator; + /// Flag to indicate whether preambles Group A was used + uint8_t RA_usedGroupA; + /// RA backoff counter + int16_t RA_backoff_cnt; + /// RA max number of preamble transmissions + int preambleTransMax; + /// Nb of preambles per SSB + long cb_preambles_per_ssb; + int starting_preamble_nb; + + /// Received TPC command (in dB) from RAR + int8_t Msg3_TPC; + /// Flag to indicate whether it is the first Msg3 to be transmitted + uint8_t first_Msg3; + /// RA Msg3 size in bytes + uint8_t Msg3_size; + + /// Random-access Contention Resolution Timer active flag + uint8_t RA_contention_resolution_timer_active; + /// Random-access Contention Resolution Timer count value + uint8_t RA_contention_resolution_cnt; + + /// BeamfailurerecoveryConfig + NR_BeamFailureRecoveryConfig_t RA_BeamFailureRecoveryConfig; + +} RA_config_t; + +typedef struct { + + uint8_t freq_hopping; + uint8_t mcs; + uint8_t Msg3_t_alloc; + uint16_t Msg3_f_alloc; + +} RAR_grant_t; + /*!\brief Top level UE MAC structure */ typedef struct { NR_ServingCellConfigCommon_t *scc; NR_CellGroupConfig_t *scg; - NR_RACH_ConfigDedicated_t *rach_ConfigDedicated; int servCellIndex; NR_CSI_ReportConfig_t *csirc; //// MAC config @@ -170,6 +325,12 @@ typedef struct { NR_ControlResourceSet_t *coreset[MAX_NUM_BWP][FAPI_NR_MAX_CORESET_PER_BWP]; NR_SearchSpace_t *SSpace[MAX_NUM_BWP][FAPI_NR_MAX_CORESET_PER_BWP][FAPI_NR_MAX_SS_PER_CORESET]; + /*BWP*/ + // dedicated active DL BWP + NR_BWP_Id_t DL_BWP_Id; + // dedicated active UL BWP + NR_BWP_Id_t UL_BWP_Id; + /// Type0-PDCCH seach space fapi_nr_dl_config_dci_dl_pdu_rel15_t type0_pdcch_dci_config; uint32_t type0_pdcch_ss_mux_pattern; @@ -182,69 +343,15 @@ typedef struct { CCCH_PDU CCCH_pdu; ULSCH_PDU ulsch_pdu; - /* Random Access parameters */ - /// state of RA procedure - RA_state_t ra_state; - /// RA rx frame offset: compensate RA rx offset introduced by OAI gNB. - uint8_t RA_offset; - /// RA-rnti - uint16_t ra_rnti; - /// Temporary CRNTI - uint16_t t_crnti; + /* Random Access */ /// CRNTI uint16_t crnti; - /// number of attempt for rach - uint8_t RA_attempt_number; - /// Random-access procedure flag - uint8_t RA_active; - /// Random-access window counter - int16_t RA_window_cnt; - /// Random-access Msg3 size in bytes - uint8_t RA_Msg3_size; - /// Random-access prachMaskIndex - uint8_t RA_prachMaskIndex; - /// Flag indicating Preamble set (A,B) used for first Msg3 transmission - uint8_t RA_usedGroupA; - /// BeamfailurerecoveryConfig - NR_BeamFailureRecoveryConfig_t RA_BeamFailureRecoveryConfig; - /// Preamble Tx Counter - uint8_t RA_PREAMBLE_TRANSMISSION_COUNTER; - /// Preamble Power Ramping Counter - uint8_t RA_PREAMBLE_POWER_RAMPING_COUNTER; - /// Random-access backoff counter - int16_t RA_backoff_indicator; - /// Random-access backoff counter - int16_t RA_backoff_cnt; - /// Random-access variable for window calculation (frame of last change in window counter) - uint32_t RA_tx_frame; - /// Random-access variable for window calculation (subframe of last change in window counter) - uint8_t RA_tx_subframe; - /// Scheduled TX frame for RA Msg3 - int16_t msg3_frame; - /// Scheduled TX slot for RA Msg3 - int16_t msg3_slot; - /// Random-access variable for backoff (frame of last change in backoff counter) - uint32_t RA_backoff_frame; - /// Random-access variable for backoff (subframe of last change in backoff counter) - uint8_t RA_backoff_subframe; - /// Random-access Group B maximum path-loss - uint16_t RA_maxPL; - /// Random-access Contention Resolution Timer active flag - uint8_t RA_contention_resolution_timer_active; - /// Random-access Contention Resolution Timer count value - uint8_t RA_contention_resolution_cnt; - /// Msg3 Delta Preamble - int8_t deltaPreamble_Msg3; - /// Received TPC command (in dB) from RAR - int8_t Msg3_TPC; - /// Flag to monitor if matching RAPID was received in RAR - uint8_t RA_RAPID_found; - /// Flag to monitor if BI was received in RAR - uint8_t RA_BI_found; - /// Flag for the Msg1 generation: enabled at every occurrence of nr prach slot - uint8_t generate_nr_prach; + /// RA configuration + RA_config_t ra; /// SSB index from MIB decoding uint8_t mib_ssb; + /// Last NDI of UL HARQ processes + uint8_t UL_ndi[NR_MAX_HARQ_PROCESSES]; //// FAPI-like interface message fapi_nr_ul_config_request_t *ul_config_request; @@ -347,67 +454,42 @@ typedef struct { uint8_t reserved_nr_dci ; // 55 RESERVED_NR_DCI } nr_dci_pdu_rel15_t; -#define NUM_SLOT_FRAME 10 +// The PRACH Config period is a series of selected slots in one or multiple frames +typedef struct prach_conf_period { + prach_occasion_slot_t prach_occasion_slot_map[MAX_NB_FRAME_IN_PRACH_CONF_PERIOD][MAX_NB_SLOT_IN_FRAME]; + uint16_t nb_of_prach_occasion; // Total number of PRACH occasions in the PRACH Config period + uint8_t nb_of_frame; // Size of the PRACH Config period in number of 10ms frames + uint8_t nb_of_slot; // Nb of slots in each frame +} prach_conf_period_t; -#define NBR_NR_FORMATS 8 // The number of formats is 8 (0_0, 0_1, 1_0, 1_1, 2_0, 2_1, 2_2, 2_3) -#define NBR_NR_DCI_FIELDS 56 // The number of different dci fields defined in TS 38.212 subclause 7.3.1 +// The association period is a series of PRACH Config periods +typedef struct prach_association_period { + prach_conf_period_t *prach_conf_period_list[MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PERIOD]; + uint8_t nb_of_prach_conf_period; // Nb of PRACH configuration periods within the association period + uint8_t nb_of_frame; // Total number of frames included in the association period +} prach_association_period_t; -#define IDENTIFIER_DCI_FORMATS 0 -#define CARRIER_IND 1 -#define SUL_IND_0_1 2 -#define SLOT_FORMAT_IND 3 -#define PRE_EMPTION_IND 4 -#define BLOCK_NUMBER 5 -#define CLOSE_LOOP_IND 6 -#define BANDWIDTH_PART_IND 7 -#define SHORT_MESSAGE_IND 8 -#define SHORT_MESSAGES 9 -#define FREQ_DOM_RESOURCE_ASSIGNMENT_UL 10 -#define FREQ_DOM_RESOURCE_ASSIGNMENT_DL 11 -#define TIME_DOM_RESOURCE_ASSIGNMENT 12 -#define VRB_TO_PRB_MAPPING 13 -#define PRB_BUNDLING_SIZE_IND 14 -#define RATE_MATCHING_IND 15 -#define ZP_CSI_RS_TRIGGER 16 -#define FREQ_HOPPING_FLAG 17 -#define TB1_MCS 18 -#define TB1_NDI 19 -#define TB1_RV 20 -#define TB2_MCS 21 -#define TB2_NDI 22 -#define TB2_RV 23 -#define MCS 24 -#define NDI 25 -#define RV 26 -#define HARQ_PROCESS_NUMBER 27 -#define DAI_ 28 -#define FIRST_DAI 29 -#define SECOND_DAI 30 -#define TB_SCALING 31 -#define TPC_PUSCH 32 -#define TPC_PUCCH 33 -#define PUCCH_RESOURCE_IND 34 -#define PDSCH_TO_HARQ_FEEDBACK_TIME_IND 35 -#define SRS_RESOURCE_IND 36 -#define PRECOD_NBR_LAYERS 37 -#define ANTENNA_PORTS 38 -#define TCI 39 -#define SRS_REQUEST 40 -#define TPC_CMD 41 -#define CSI_REQUEST 42 -#define CBGTI 43 -#define CBGFI 44 -#define PTRS_DMRS 45 -#define BETA_OFFSET_IND 46 -#define DMRS_SEQ_INI 47 -#define UL_SCH_IND 48 -#define PADDING_NR_DCI 49 -#define SUL_IND_0_0 50 -#define RA_PREAMBLE_INDEX 51 -#define SUL_IND_1_0 52 -#define SS_PBCH_INDEX 53 -#define PRACH_MASK_INDEX 54 -#define RESERVED_NR_DCI 55 +// The association pattern is a series of Association periods +typedef struct prach_association_pattern { + prach_association_period_t prach_association_period_list[MAX_NB_ASSOCIATION_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD]; + prach_conf_period_t prach_conf_period_list[MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD]; + uint8_t nb_of_assoc_period; // Nb of association periods within the association pattern + uint8_t nb_of_prach_conf_period_in_max_period; // Nb of PRACH configuration periods within the maximum association pattern period (according to the size of the configured PRACH + uint8_t nb_of_frame; // Total number of frames included in the association pattern period (after mapping the SSBs and determining the real association pattern length) +} prach_association_pattern_t; + +// SSB details +typedef struct ssb_info { + boolean_t transmitted; // True if the SSB index is transmitted according to the SSB positions map configuration + prach_occasion_info_t *mapped_ro[MAX_NB_RO_PER_SSB_IN_ASSOCIATION_PATTERN]; // List of mapped RACH Occasions to this SSB index + uint16_t nb_mapped_ro; // Total number of mapped ROs to this SSB index +} ssb_info_t; + +// List of all the possible SSBs and their details +typedef struct ssb_list_info { + ssb_info_t tx_ssb[MAX_NB_SSB]; + uint8_t nb_tx_ssb; +} ssb_list_info_t; /*@}*/ #endif /*__LAYER2_MAC_DEFS_H__ */ diff --git a/openair2/LAYER2/NR_MAC_UE/mac_extern.h b/openair2/LAYER2/NR_MAC_UE/mac_extern.h index 79d671b8fb..e551790f7a 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_extern.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_extern.h @@ -40,4 +40,47 @@ extern uint8_t table_6_1_2_1_1_2_time_dom_res_alloc_A[16][3]; // for PDSCH from TS 38.214 subclause 5.1.2.1.1 extern uint8_t table_5_1_2_1_1_2_time_dom_res_alloc_A[16][3]; +extern int64_t table_6_3_3_2_3_prachConfig_Index [256][9]; + +// DCI +extern const uint8_t table_7_3_1_1_2_2_3_4_5[64][20]; +extern const uint8_t table_7_3_1_1_2_12[14][3]; +extern const uint8_t table_7_3_1_1_2_13[10][4]; +extern const uint8_t table_7_3_1_1_2_14[3][5]; +extern const uint8_t table_7_3_1_1_2_15[4][6]; +extern const uint8_t table_7_3_1_1_2_16[12][2]; +extern const uint8_t table_7_3_1_1_2_17[7][3]; +extern const uint8_t table_7_3_1_1_2_18[3][4]; +extern const uint8_t table_7_3_1_1_2_19[2][5]; +extern const uint8_t table_7_3_1_1_2_20[28][3]; +extern const uint8_t table_7_3_1_1_2_21[19][4]; +extern const uint8_t table_7_3_1_1_2_22[6][5]; +extern const uint8_t table_7_3_1_1_2_23[5][6]; +extern const uint8_t table_7_3_2_3_3_1[12][5]; +extern const uint8_t table_7_3_2_3_3_2_oneCodeword[31][6]; +extern const uint8_t table_7_3_2_3_3_2_twoCodeword[4][10]; +extern const uint8_t table_7_3_2_3_3_3_oneCodeword[24][5]; +extern const uint8_t table_7_3_2_3_3_3_twoCodeword[2][7]; +extern const uint8_t table_7_3_2_3_3_4_oneCodeword[58][6]; +extern const uint8_t table_7_3_2_3_3_4_twoCodeword[6][10]; + +extern const uint16_t table_7_2_1[16]; + extern dci_pdu_rel15_t *def_dci_pdu_rel15; + +extern dci_pdu_rel15_t *def_dci_pdu_rel15; + +extern void mac_rlc_data_ind(const module_id_t module_idP, + const rnti_t rntiP, + const eNB_index_t eNB_index, + const frame_t frameP, + const eNB_flag_t enb_flagP, + const MBMS_flag_t MBMS_flagP, + const logical_chan_id_t channel_idP, + char *buffer_pP, + const tb_size_t tb_sizeP, + num_tb_t num_tbP, + crc_t *crcs_pP); + +extern const char *rnti_types[]; +extern const char *dci_formats[]; diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index 59ce130c24..c4909c1384 100755 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -34,11 +34,9 @@ #define __LAYER2_MAC_UE_PROTO_H__ #include "mac_defs.h" -#include "mac.h" #include "PHY/defs_nr_UE.h" #include "RRC/NR_UE/rrc_defs.h" - /**\brief decode mib pdu in NR_UE, from if_module ul_ind with P7 tx_ind message \param module_id module id \param cc_id component carrier id @@ -134,7 +132,7 @@ uint32_t ue_get_SR(module_id_t module_idP, int CC_id, frame_t frameP, int8_t nr_ue_get_SR(module_id_t module_idP, int CC_id, frame_t frameP, uint8_t eNB_id, uint16_t rnti, sub_frame_t subframe); -int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, frame_t frame, int slot, dci_pdu_rel15_t *dci, uint16_t rnti, uint32_t dci_format); +int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, frame_t frame, int slot, dci_pdu_rel15_t *dci, uint16_t rnti, uint8_t dci_format); int nr_ue_process_dci_indication_pdu(module_id_t module_id, int cc_id, int gNB_index, frame_t frame, int slot, fapi_nr_dci_indication_pdu_t *dci); uint32_t get_ssb_frame(uint32_t test); @@ -142,33 +140,18 @@ uint32_t get_ssb_frame(uint32_t test); uint32_t mr_ue_get_SR(module_id_t module_idP, int CC_id, frame_t frameP, uint8_t eNB_id, uint16_t rnti, sub_frame_t subframe); /* \brief Get payload (MAC PDU) from UE PHY -@param module_idP Instance id of UE in machine -@param CC_id Component Carrier index -@param frameP Current Rx frame -@param slotP Current Rx slot -@param pdu Pointer to the MAC PDU -@param pdu_len Length of the MAC PDU -@param gNB_id Index of gNB that UE is attached to -@param ul_time_alignment of struct handling the timing advance parameters +@param dl_info pointer to dl indication +@param ul_time_alignment pointer to timing advance parameters +@param pdu_id index of DL PDU @returns void */ -void nr_ue_send_sdu(module_id_t module_idP, - uint8_t CC_id, - frame_t frameP, - int slotP, - uint8_t * pdu, - uint16_t pdu_len, - uint8_t gNB_index, - NR_UL_TIME_ALIGNMENT_t *ul_time_alignment); - -void nr_ue_process_mac_pdu(module_id_t module_idP, - uint8_t CC_id, - frame_t frameP, - uint8_t *pduP, - uint16_t mac_pdu_len, - uint8_t gNB_index, - NR_UL_TIME_ALIGNMENT_t *ul_time_alignment); +void nr_ue_send_sdu(nr_downlink_indication_t *dl_info, + NR_UL_TIME_ALIGNMENT_t *ul_time_alignment, + int pdu_id); +void nr_ue_process_mac_pdu(nr_downlink_indication_t *dl_info, + NR_UL_TIME_ALIGNMENT_t *ul_time_alignment, + int pdu_id); uint16_t nr_generate_ulsch_pdu(uint8_t *sdus_payload, uint8_t *pdu, @@ -183,17 +166,19 @@ uint16_t nr_generate_ulsch_pdu(uint8_t *sdus_payload, unsigned short post_padding, uint16_t buflen); -int8_t nr_ue_process_dlsch(module_id_t module_id, int cc_id, uint8_t gNB_index, fapi_nr_dci_indication_t *dci_ind, void *pduP, uint32_t pdu_len); - void ue_dci_configuration(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_request_t *dl_config, frame_t frame, int slot); -int nr_extract_dci_info(NR_UE_MAC_INST_t *mac, - int dci_format, - uint8_t dci_length, - uint16_t rnti, - uint64_t *dci_pdu, - dci_pdu_rel15_t *nr_pdci_info_extracted); +uint8_t nr_extract_dci_info(NR_UE_MAC_INST_t *mac, + uint8_t dci_format, + uint8_t dci_length, + uint16_t rnti, + uint64_t *dci_pdu, + dci_pdu_rel15_t *nr_pdci_info_extracted); +int8_t nr_ue_process_dci_time_dom_resource_assignment(NR_UE_MAC_INST_t *mac, + nfapi_nr_ue_pusch_pdu_t *pusch_config_pdu, + fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config_pdu, + uint8_t time_domain_ind); uint8_t nr_ue_get_sdu(module_id_t module_idP, int CC_id, frame_t frameP, @@ -217,6 +202,11 @@ int nr_get_Po_NOMINAL_PUSCH(NR_PRACH_RESOURCES_t *prach_resources, module_id_t m */ int8_t nr_get_DELTA_PREAMBLE(module_id_t mod_id, int CC_id, uint16_t prach_format); +/** \brief Function to compute configured maximum output power according to clause 6.2.4 of 3GPP TS 38.101-1 version 16.5.0 Release 16 + @param Mod_id Module id of UE +*/ +long nr_get_Pcmax(module_id_t mod_id); + /* Random Access */ /* \brief This function schedules the PRACH according to prach_ConfigurationIndex and TS 38.211 tables 6.3.3.2.x @@ -252,22 +242,15 @@ random-access procedure @param selected_rar_buffer the output buffer for storing the selected RAR header and RAR payload @returns timing advance or 0xffff if preamble doesn't match */ -uint16_t nr_ue_process_rar(module_id_t mod_id, - int CC_id, - frame_t frameP, - sub_frame_t slotP, - uint8_t * dlsch_buffer, - rnti_t * t_crnti, - uint8_t preamble_index, - uint8_t * selected_rar_buffer); +int nr_ue_process_rar(nr_downlink_indication_t *dl_info, NR_UL_TIME_ALIGNMENT_t *ul_time_alignment, int pdu_id); void nr_process_rar(nr_downlink_indication_t *dl_info); -void ue_contention_resolution(module_id_t module_id, uint8_t gNB_index, int cc_id, frame_t tx_frame); +void nr_ue_contention_resolution(module_id_t module_id, int cc_id, frame_t frame, int slot, NR_PRACH_RESOURCES_t *prach_resources); -void nr_ra_failed(uint8_t Mod_id, uint8_t CC_id, uint8_t gNB_index); +void nr_ra_failed(uint8_t mod_id, uint8_t CC_id, NR_PRACH_RESOURCES_t *prach_resources, frame_t frame, int slot); -void nr_ra_succeeded(uint8_t Mod_id, uint8_t CC_id, uint8_t gNB_index); +void nr_ra_succeeded(module_id_t mod_id, frame_t frame, int slot); /* \brief Function called by PHY to retrieve information to be transmitted using the RA procedure. If the UE is not in PUSCH mode for a particular eNB index, this is assumed to be an Msg3 and MAC @@ -284,7 +267,6 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources, fapi_nr_ul_config_prach_pdu *prach_pdu, module_id_t mod_id, int CC_id, - UE_MODE_t UE_mode, frame_t frame, uint8_t gNB_id, int nr_slot_tx); @@ -298,7 +280,6 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources, void nr_get_prach_resources(module_id_t mod_id, int CC_id, uint8_t gNB_id, - uint8_t first_Msg3, NR_PRACH_RESOURCES_t *prach_resources, fapi_nr_ul_config_prach_pdu *prach_pdu, NR_RACH_ConfigDedicated_t * rach_ConfigDedicated); @@ -321,6 +302,35 @@ void get_num_re_dmrs(nfapi_nr_ue_pusch_pdu_t *pusch_pdu, void build_ssb_to_ro_map(NR_ServingCellConfigCommon_t *scc, uint8_t unpaired); +void config_bwp_ue(NR_UE_MAC_INST_t *mac, uint16_t *bwp_ind, uint8_t *dci_format); +fapi_nr_ul_config_request_t *get_ul_config_request(NR_UE_MAC_INST_t *mac, int slot); + +void fill_ul_config(fapi_nr_ul_config_request_t *ul_config, frame_t frame_tx, int slot_tx, uint8_t pdu_type); + +// PUSCH scheduler: +// - Calculate the slot in which ULSCH should be scheduled. This is current slot + K2, +// - where K2 is the offset between the slot in which UL DCI is received and the slot +// - in which ULSCH should be scheduled. K2 is configured in RRC configuration. +// PUSCH Msg3 scheduler: +// - scheduled by RAR UL grant according to 8.3 of TS 38.213 +int nr_ue_pusch_scheduler(NR_UE_MAC_INST_t *mac, uint8_t is_Msg3, frame_t current_frame, int current_slot, frame_t *frame_tx, int *slot_tx, uint8_t tda_id); + +int get_rnti_type(NR_UE_MAC_INST_t *mac, uint16_t rnti); + +// Configuration of Msg3 PDU according to clauses: +// - 8.3 of 3GPP TS 38.213 version 16.3.0 Release 16 +// - 6.1.2.2 of TS 38.214 +// - 6.1.3 of TS 38.214 +// - 6.2.2 of TS 38.214 +// - 6.1.4.2 of TS 38.214 +// - 6.4.1.1.1 of TS 38.211 +// - 6.3.1.7 of 38.211 +int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, + nfapi_nr_ue_pusch_pdu_t *pusch_config_pdu, + dci_pdu_rel15_t *dci, + RAR_grant_t *rar_grant, + uint16_t rnti, + uint8_t *dci_format); #endif /** @}*/ diff --git a/openair2/LAYER2/NR_MAC_UE/mac_vars.c b/openair2/LAYER2/NR_MAC_UE/mac_vars.c index 4986ab5883..ecabdb870c 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_vars.c +++ b/openair2/LAYER2/NR_MAC_UE/mac_vars.c @@ -30,48 +30,404 @@ * \warning */ -#include "mac_defs.h" +#include -/* - #define mu_pusch 1 -// definition table j Table 6.1.2.1.1-4 - #define j ((mu_pusch==3)?3:(mu_pusch==2)?2:1) - uint8_t table_6_1_2_1_1_2_time_dom_res_alloc_A[16][3]={ // for PUSCH from TS 38.214 subclause 6.1.2.1.1 - {j, 0,14}, // row index 1 - {j, 0,12}, // row index 2 - {j, 0,10}, // row index 3 - {j, 2,10}, // row index 4 - {j, 4,10}, // row index 5 - {j, 4,8}, // row index 6 - {j, 4,6}, // row index 7 - {j+1,0,14}, // row index 8 - {j+1,0,12}, // row index 9 - {j+1,0,10}, // row index 10 - {j+2,0,14}, // row index 11 - {j+2,0,12}, // row index 12 - {j+2,0,10}, // row index 13 - {j, 8,6}, // row index 14 - {j+3,0,14}, // row index 15 - {j+3,0,10} // row index 16 - }; +const char *rnti_types[]={"RNTI_new", "RNTI_C", "RNTI_RA", "NR_RNTI_P", "NR_RNTI_CS", "NR_RNTI_TC"}; +const char *dci_formats[]={"1_0", "1_1", "2_0", "2_1", "2_2", "2_3", "0_0", "0_1"}; - #define dmrs_typeA_pos 2 - uint8_t table_5_1_2_1_1_2_time_dom_res_alloc_A[16][3]={ // for PDSCH from TS 38.214 subclause 5.1.2.1.1 - {0,(dmrs_typeA_pos == 2)?2:3, (dmrs_typeA_pos == 2)?12:11}, // row index 1 - {0,(dmrs_typeA_pos == 2)?2:3, (dmrs_typeA_pos == 2)?10:9}, // row index 2 - {0,(dmrs_typeA_pos == 2)?2:3, (dmrs_typeA_pos == 2)?9:8}, // row index 3 - {0,(dmrs_typeA_pos == 2)?2:3, (dmrs_typeA_pos == 2)?7:6}, // row index 4 - {0,(dmrs_typeA_pos == 2)?2:3, (dmrs_typeA_pos == 2)?5:4}, // row index 5 - {0,(dmrs_typeA_pos == 2)?9:10,(dmrs_typeA_pos == 2)?4:4}, // row index 6 - {0,(dmrs_typeA_pos == 2)?4:6, (dmrs_typeA_pos == 2)?4:4}, // row index 7 - {0,5,7}, // row index 8 - {0,5,2}, // row index 9 - {0,9,2}, // row index 10 - {0,12,2}, // row index 11 - {0,1,13}, // row index 12 - {0,1,6}, // row index 13 - {0,2,4}, // row index 14 - {0,4,7}, // row index 15 - {0,8,4} // row index 16 - }; -*/ +// table_7_3_1_1_2_2_3_4_5 contains values for number of layers and precoding information for tables 7.3.1.1.2-2/3/4/5 from TS 38.212 subclause 7.3.1.1.2 +// the first 6 columns contain table 7.3.1.1.2-2: Precoding information and number of layers, for 4 antenna ports, if transformPrecoder=disabled and maxRank = 2 or 3 or 4 +// next six columns contain table 7.3.1.1.2-3: Precoding information and number of layers for 4 antenna ports, if transformPrecoder= enabled, or if transformPrecoder=disabled and maxRank = 1 +// next four columns contain table 7.3.1.1.2-4: Precoding information and number of layers, for 2 antenna ports, if transformPrecoder=disabled and maxRank = 2 +// next four columns contain table 7.3.1.1.2-5: Precoding information and number of layers, for 2 antenna ports, if transformPrecoder= enabled, or if transformPrecoder= disabled and maxRank = 1 +const uint8_t table_7_3_1_1_2_2_3_4_5[64][20] = { + {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}, + {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, + {1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 0, 2, 0, 1, 2, 0, 0}, + {1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 2, 0, 0, 1, 3, 0, 0}, + {2, 0, 2, 0, 2, 0, 1, 4, 1, 4, 0, 0, 1, 3, 0, 0, 1, 4, 0, 0}, + {2, 1, 2, 1, 2, 1, 1, 5, 1, 5, 0, 0, 1, 4, 0, 0, 1, 5, 0, 0}, + {2, 2, 2, 2, 2, 2, 1, 6, 1, 6, 0, 0, 1, 5, 0, 0, 0, 0, 0, 0}, + {2, 3, 2, 3, 2, 3, 1, 7, 1, 7, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0}, + {2, 4, 2, 4, 2, 4, 1, 8, 1, 8, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0}, + {2, 5, 2, 5, 2, 5, 1, 9, 1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {3, 0, 3, 0, 3, 0, 1, 10, 1, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {4, 0, 4, 0, 4, 0, 1, 11, 1, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 4, 1, 4, 0, 0, 1, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 5, 1, 5, 0, 0, 1, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 6, 1, 6, 0, 0, 1, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 7, 1, 7, 0, 0, 1, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 8, 1, 8, 0, 0, 1, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 9, 1, 9, 0, 0, 1, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 10, 1, 10, 0, 0, 1, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 11, 1, 11, 0, 0, 1, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {2, 6, 2, 6, 0, 0, 1, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {2, 7, 2, 7, 0, 0, 1, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {2, 8, 2, 8, 0, 0, 1, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {2, 9, 2, 9, 0, 0, 1, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {2, 10, 2, 10, 0, 0, 1, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {2, 11, 2, 11, 0, 0, 1, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {2, 12, 2, 12, 0, 0, 1, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {2, 13, 2, 13, 0, 0, 1, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {3, 1, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {3, 2, 3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {4, 1, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {4, 2, 4, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {2, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {2, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {2, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {2, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {2, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {2, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {2, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {2, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {3, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {3, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {4, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +}; + +const uint8_t table_7_3_1_1_2_12[14][3] = { + {1,0,1}, + {1,1,1}, + {2,0,1}, + {2,1,1}, + {2,2,1}, + {2,3,1}, + {2,0,2}, + {2,1,2}, + {2,2,2}, + {2,3,2}, + {2,4,2}, + {2,5,2}, + {2,6,2}, + {2,7,2} +}; + +const uint8_t table_7_3_1_1_2_13[10][4] = { + {1,0,1,1}, + {2,0,1,1}, + {2,2,3,1}, + {2,0,2,1}, + {2,0,1,2}, + {2,2,3,2}, + {2,4,5,2}, + {2,6,7,2}, + {2,0,4,2}, + {2,2,6,2} +}; + +const uint8_t table_7_3_1_1_2_14[3][5] = { + {2,0,1,2,1}, + {2,0,1,4,2}, + {2,2,3,6,2} +}; + +const uint8_t table_7_3_1_1_2_15[4][6] = { + {2,0,1,2,3,1}, + {2,0,1,4,5,2}, + {2,2,3,6,7,2}, + {2,0,2,4,6,2} +}; + +const uint8_t table_7_3_1_1_2_16[12][2] = { + {1,0}, + {1,1}, + {2,0}, + {2,1}, + {2,2}, + {2,3}, + {3,0}, + {3,1}, + {3,2}, + {3,3}, + {3,4}, + {3,5} +}; + +const uint8_t table_7_3_1_1_2_17[7][3] = { + {1,0,1}, + {2,0,1}, + {2,2,3}, + {3,0,1}, + {3,2,3}, + {3,4,5}, + {2,0,2} +}; + +const uint8_t table_7_3_1_1_2_18[3][4] = { + {2,0,1,2}, + {3,0,1,2}, + {3,3,4,5} +}; + +const uint8_t table_7_3_1_1_2_19[2][5] = { + {2,0,1,2,3}, + {3,0,1,2,3} +}; + +const uint8_t table_7_3_1_1_2_20[28][3] = { + {1,0,1}, + {1,1,1}, + {2,0,1}, + {2,1,1}, + {2,2,1}, + {2,3,1}, + {3,0,1}, + {3,1,1}, + {3,2,1}, + {3,3,1}, + {3,4,1}, + {3,5,1}, + {3,0,2}, + {3,1,2}, + {3,2,2}, + {3,3,2}, + {3,4,2}, + {3,5,2}, + {3,6,2}, + {3,7,2}, + {3,8,2}, + {3,9,2}, + {3,10,2}, + {3,11,2}, + {1,0,2}, + {1,1,2}, + {1,6,2}, + {1,7,2} +}; + +const uint8_t table_7_3_1_1_2_21[19][4] = { + {1,0,1,1}, + {2,0,1,1}, + {2,2,3,1}, + {3,0,1,1}, + {3,2,3,1}, + {3,4,5,1}, + {2,0,2,1}, + {3,0,1,2}, + {3,2,3,2}, + {3,4,5,2}, + {3,6,7,2}, + {3,8,9,2}, + {3,10,11,2}, + {1,0,1,2}, + {1,6,7,2}, + {2,0,1,2}, + {2,2,3,2}, + {2,6,7,2}, + {2,8,9,2} +}; + +const uint8_t table_7_3_1_1_2_22[6][5] = { + {2,0,1,2,1}, + {3,0,1,2,1}, + {3,3,4,5,1}, + {3,0,1,6,2}, + {3,2,3,8,2}, + {3,4,5,10,2} +}; + +const uint8_t table_7_3_1_1_2_23[5][6] = { + {2,0,1,2,3,1}, + {3,0,1,2,3,1}, + {3,0,1,6,7,2}, + {3,2,3,8,9,2}, + {3,4,5,10,11,2} +}; + +const uint8_t table_7_3_2_3_3_1[12][5] = { + {1,0,0,0,0}, + {1,1,0,0,0}, + {1,0,1,0,0}, + {2,0,0,0,0}, + {2,1,0,0,0}, + {2,2,0,0,0}, + {2,3,0,0,0}, + {2,0,1,0,0}, + {2,2,3,0,0}, + {2,0,1,2,0}, + {2,0,1,2,3}, + {2,0,2,0,0} +}; + +const uint8_t table_7_3_2_3_3_2_oneCodeword[31][6] = { + {1,0,0,0,0,1}, + {1,1,0,0,0,1}, + {1,0,1,0,0,1}, + {2,0,0,0,0,1}, + {2,1,0,0,0,1}, + {2,2,0,0,0,1}, + {2,3,0,0,0,1}, + {2,0,1,0,0,1}, + {2,2,3,0,0,1}, + {2,0,1,2,0,1}, + {2,0,1,2,3,1}, + {2,0,2,0,0,1}, + {2,0,0,0,0,2}, + {2,1,0,0,0,2}, + {2,2,0,0,0,2}, + {2,3,0,0,0,2}, + {2,4,0,0,0,2}, + {2,5,0,0,0,2}, + {2,6,0,0,0,2}, + {2,7,0,0,0,2}, + {2,0,1,0,0,2}, + {2,2,3,0,0,2}, + {2,4,5,0,0,2}, + {2,6,7,0,0,2}, + {2,0,4,0,0,2}, + {2,2,6,0,0,2}, + {2,0,1,4,0,2}, + {2,2,3,6,0,2}, + {2,0,1,4,5,2}, + {2,2,3,6,7,2}, + {2,0,2,4,6,2} +}; + +const uint8_t table_7_3_2_3_3_2_twoCodeword[4][10] = { + {2,0,1,2,3,4,0,0,0,2}, + {2,0,1,2,3,4,6,0,0,2}, + {2,0,1,2,3,4,5,6,0,2}, + {2,0,1,2,3,4,5,6,7,2} +}; + +const uint8_t table_7_3_2_3_3_3_oneCodeword[24][5] = { + {1,0,0,0,0}, + {1,1,0,0,0}, + {1,0,1,0,0}, + {2,0,0,0,0}, + {2,1,0,0,0}, + {2,2,0,0,0}, + {2,3,0,0,0}, + {2,0,1,0,0}, + {2,2,3,0,0}, + {2,0,1,2,0}, + {2,0,1,2,3}, + {3,0,0,0,0}, + {3,1,0,0,0}, + {3,2,0,0,0}, + {3,3,0,0,0}, + {3,4,0,0,0}, + {3,5,0,0,0}, + {3,0,1,0,0}, + {3,2,3,0,0}, + {3,4,5,0,0}, + {3,0,1,2,0}, + {3,3,4,5,0}, + {3,0,1,2,3}, + {2,0,2,0,0} +}; + +const uint8_t table_7_3_2_3_3_3_twoCodeword[2][7] = { + {3,0,1,2,3,4,0}, + {3,0,1,2,3,4,5} +}; + +const uint8_t table_7_3_2_3_3_4_oneCodeword[58][6] = { + {1,0,0,0,0,1}, + {1,1,0,0,0,1}, + {1,0,1,0,0,1}, + {2,0,0,0,0,1}, + {2,1,0,0,0,1}, + {2,2,0,0,0,1}, + {2,3,0,0,0,1}, + {2,0,1,0,0,1}, + {2,2,3,0,0,1}, + {2,0,1,2,0,1}, + {2,0,1,2,3,1}, + {3,0,0,0,0,1}, + {3,1,0,0,0,1}, + {3,2,0,0,0,1}, + {3,3,0,0,0,1}, + {3,4,0,0,0,1}, + {3,5,0,0,0,1}, + {3,0,1,0,0,1}, + {3,2,3,0,0,1}, + {3,4,5,0,0,1}, + {3,0,1,2,0,1}, + {3,3,4,5,0,1}, + {3,0,1,2,3,1}, + {2,0,2,0,0,1}, + {3,0,0,0,0,2}, + {3,1,0,0,0,2}, + {3,2,0,0,0,2}, + {3,3,0,0,0,2}, + {3,4,0,0,0,2}, + {3,5,0,0,0,2}, + {3,6,0,0,0,2}, + {3,7,0,0,0,2}, + {3,8,0,0,0,2}, + {3,9,0,0,0,2}, + {3,10,0,0,0,2}, + {3,11,0,0,0,2}, + {3,0,1,0,0,2}, + {3,2,3,0,0,2}, + {3,4,5,0,0,2}, + {3,6,7,0,0,2}, + {3,8,9,0,0,2}, + {3,10,11,0,0,2}, + {3,0,1,6,0,2}, + {3,2,3,8,0,2}, + {3,4,5,10,0,2}, + {3,0,1,6,7,2}, + {3,2,3,8,9,2}, + {3,4,5,10,11,2}, + {1,0,0,0,0,2}, + {1,1,0,0,0,2}, + {1,6,0,0,0,2}, + {1,7,0,0,0,2}, + {1,0,1,0,0,2}, + {1,6,7,0,0,2}, + {2,0,1,0,0,2}, + {2,2,3,0,0,2}, + {2,6,7,0,0,2}, + {2,8,9,0,0,2} +}; + +const uint8_t table_7_3_2_3_3_4_twoCodeword[6][10] = { + {3,0,1,2,3,4,0,0,0,1}, + {3,0,1,2,3,4,5,0,0,1}, + {2,0,1,2,3,6,0,0,0,2}, + {2,0,1,2,3,6,8,0,0,2}, + {2,0,1,2,3,6,7,8,0,2}, + {2,0,1,2,3,6,7,8,9,2} +}; + +// table 7.2-1 TS 38.321 +const uint16_t table_7_2_1[16] = { + 5, // row index 0 + 10, // row index 1 + 20, // row index 2 + 30, // row index 3 + 40, // row index 4 + 60, // row index 5 + 80, // row index 6 + 120, // row index 7 + 160, // row index 8 + 240, // row index 9 + 320, // row index 10 + 480, // row index 11 + 960, // row index 12 + 1920, // row index 13 +}; diff --git a/openair2/LAYER2/NR_MAC_UE/nr_l1_helpers.c b/openair2/LAYER2/NR_MAC_UE/nr_l1_helpers.c index 30e4acaf49..27623fe5be 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_l1_helpers.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_l1_helpers.c @@ -30,10 +30,12 @@ */ #include "PHY/defs_nr_common.h" +//#include "PHY/impl_defs_top.h" #include "mac_defs.h" #include "LAYER2/NR_MAC_COMMON/nr_mac_extern.h" #include "LAYER2/NR_MAC_UE/mac_proto.h" +#include "NR_P-Max.h" /* TS 38.321 subclause 7.3 - return DELTA_PREAMBLE values in dB */ int8_t nr_get_DELTA_PREAMBLE(module_id_t mod_id, int CC_id, uint16_t prach_format){ @@ -133,21 +135,33 @@ int8_t nr_get_DELTA_PREAMBLE(module_id_t mod_id, int CC_id, uint16_t prach_forma return 0; } -/* TS 38.321 subclause 5.1.3 - RA preamble transmission - ra_PREAMBLE_RECEIVED_TARGET_POWER configuration */ +// TS 38.321 subclause 5.1.3 - RA preamble transmission - ra_PREAMBLE_RECEIVED_TARGET_POWER configuration +// Measurement units: +// - preambleReceivedTargetPower dBm (-202..-60, 2 dBm granularity) +// - delta_preamble dB +// - RA_PREAMBLE_POWER_RAMPING_STEP dB +// - POWER_OFFSET_2STEP_RA dB +// returns receivedTargerPower in dBm int nr_get_Po_NOMINAL_PUSCH(NR_PRACH_RESOURCES_t *prach_resources, module_id_t mod_id, uint8_t CC_id){ NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id); NR_ServingCellConfigCommon_t *scc = mac->scc; - NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup; int8_t receivedTargerPower, delta_preamble; - long preambleReceivedTargetPower; + long preambleReceivedTargetPower = 0; - AssertFatal(nr_rach_ConfigCommon != NULL, "[UE %d] CCid %d FATAL nr_rach_ConfigCommon is NULL !!!\n", mod_id, CC_id); + if (prach_resources->RA_TYPE == RA_4STEP){ + NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup; + preambleReceivedTargetPower = nr_rach_ConfigCommon->rach_ConfigGeneric.preambleReceivedTargetPower; + } else if (prach_resources->RA_TYPE == RA_2STEP){ + // msgA-PreambleReceivedTargetPower + LOG_E(MAC, "In %s:%d: missing implementation for 2-step RA...\n", __FUNCTION__, __LINE__); + } - preambleReceivedTargetPower = nr_rach_ConfigCommon->rach_ConfigGeneric.preambleReceivedTargetPower; delta_preamble = nr_get_DELTA_PREAMBLE(mod_id, CC_id, prach_resources->prach_format); - receivedTargerPower = preambleReceivedTargetPower + delta_preamble + (mac->RA_PREAMBLE_POWER_RAMPING_COUNTER - 1) * prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP; + receivedTargerPower = preambleReceivedTargetPower + delta_preamble + (prach_resources->RA_PREAMBLE_POWER_RAMPING_COUNTER - 1) * prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP + prach_resources->POWER_OFFSET_2STEP_RA; + + LOG_D(MAC, "In %s: receivedTargerPower is %d dBm \n", __FUNCTION__, receivedTargerPower); return receivedTargerPower; } @@ -171,3 +185,81 @@ void get_num_re_dmrs(nfapi_nr_ue_pusch_pdu_t *pusch_pdu, *nb_dmrs_re_per_rb = ((dmrs_type == pusch_dmrs_type1) ? 6:4)*cdm_grps_no_data; } + +// Implementation of 6.2.4 Configured ransmitted power +// 3GPP TS 38.101-1 version 16.5.0 Release 16 +// - +// The UE is allowed to set its configured maximum output power PCMAX,f,c for carrier f of serving cell c in each slot. +// The configured maximum output power PCMAX,f,c is set within the following bounds: PCMAX_L,f,c <= PCMAX,f,c <= PCMAX_H,f,c +// - +// Measurement units: +// - p_max: dBm +// - delta_TC_c: dB +// - P_powerclass: dBm +// - delta_P_powerclass: dB +// - MPR_c: dB +// - delta_MPR_c: dB +// - delta_T_IB_c dB +// - delta_rx_SRS dB +// note: +// - Assuming: +// -- Powerclass 3 capable UE (which is default power class unless otherwise stated) +// -- Maximum power reduction (MPR_c) for power class 3, QPSK, inner RB allocations +// -- no additional MPR (A_MPR_c) +// todo: +// - in current implementation delta_P_powerclass is not handling power classes different from 3 +long nr_get_Pcmax(module_id_t mod_id){ + + NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id); + uint32_t band = *mac->scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]; + NR_P_Max_t p_max = 0; + uint8_t P_powerclass = 23; + uint8_t delta_P_powerclass = 0; + uint8_t MPR_c = 1.5; + uint8_t delta_MPR_c = 0; + uint8_t A_MPR_c = 0; + uint8_t delta_T_IB_c = 0; + uint8_t delta_TC_c = 0; + uint8_t delta_rx_SRS = 0; + uint8_t P_MPR_c = 0; + long P_cmax_l = 0; + long P_cmax_h = 0; + long P_cmax = 0; + + if (band == 28 && mac->phy_config.config_req.carrier_config.uplink_bandwidth == 30){ + delta_MPR_c = 0.5; + } + + if (mac->scg->spCellConfig->spCellConfigDedicated->uplinkConfig->ext1){ + if (*mac->scg->spCellConfig->spCellConfigDedicated->uplinkConfig->ext1->powerBoostPi2BPSK == 1){ + // TbD: assuming power class 3 capable UE operating in TDD bands n40, n41, n77, n78, and n79 with Pi/2 BPSK modulation + delta_P_powerclass = -3; + p_max += 3; + } + } + + if (mac->scc->uplinkConfigCommon->frequencyInfoUL->p_Max){ + + p_max += *mac->scc->uplinkConfigCommon->frequencyInfoUL->p_Max; + + LOG_D(MAC, "In %s maximum UL transmission power p_max is %ld dBm \n", __FUNCTION__, p_max); + + P_cmax_l = min(p_max - delta_TC_c, (P_powerclass - delta_P_powerclass) - max(max(MPR_c + delta_MPR_c, A_MPR_c) + delta_T_IB_c + delta_TC_c + delta_rx_SRS, P_MPR_c)); + + P_cmax_h = min(p_max, P_powerclass - delta_P_powerclass); + + } else { + + P_cmax_l = (P_powerclass - delta_P_powerclass) - max(max(MPR_c + delta_MPR_c, A_MPR_c) + delta_T_IB_c + delta_TC_c + delta_rx_SRS, P_MPR_c); + + P_cmax_h = P_powerclass - delta_P_powerclass; + + } + + P_cmax = (P_cmax_h + P_cmax_l) / 2; + + LOG_D(MAC, "In %s configured maximum output power: %ld dBm <= PCMAX %ld dBm <= %ld dBm \n", __FUNCTION__, P_cmax_l, P_cmax, P_cmax_h); + + return P_cmax; + +} \ No newline at end of file diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index c8b7074b9b..177156cabb 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -30,21 +30,6 @@ * \warning */ -#include "mac.h" - -/* -#include "common/utils/LOG/vcd_signal_dumper.h" -#include "PHY_INTERFACE/phy_interface_extern.h" -#include "SCHED_UE/sched_UE.h" -#include "COMMON/mac_rrc_primitives.h" -#include "RRC/LTE/rrc_extern.h" -#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h" -#include "common/utils/LOG/log.h" -#include "UTIL/OPT/opt.h" -#include "OCG.h" -#include "OCG_extern.h" -#include "PHY/LTE_ESTIMATION/lte_estimation.h"*/ - /* Tools */ #include "SIMULATION/TOOLS/sim.h" // for taus @@ -62,133 +47,179 @@ #include "NR_MAC_COMMON/nr_mac.h" #include "LAYER2/NR_MAC_UE/mac_proto.h" -extern int64_t table_6_3_3_2_3_prachConfig_Index [256][9]; - -//extern uint8_t nfapi_mode; - void nr_get_RA_window(NR_UE_MAC_INST_t *mac); -// WIP -// This routine implements Section 5.1.2 (UE Random Access Resource Selection) -// and Section 5.1.3 (Random Access Preamble Transmission) from 3GPP TS 38.321 -void nr_get_prach_resources(module_id_t mod_id, - int CC_id, - uint8_t gNB_id, - uint8_t first_Msg3, - NR_PRACH_RESOURCES_t *prach_resources, - fapi_nr_ul_config_prach_pdu *prach_pdu, - NR_RACH_ConfigDedicated_t * rach_ConfigDedicated){ +// Random Access procedure initialization as per 5.1.1 and initialization of variables specific +// to Random Access type as specified in clause 5.1.1a (3GPP TS 38.321 version 16.2.1 Release 16) +// todo: +// - check if carrier to use is explicitly signalled then do (1) RA CARRIER SELECTION (SUL, NUL) (2) set PCMAX (currently hardcoded to 0) +void init_RA(module_id_t mod_id, + NR_PRACH_RESOURCES_t *prach_resources, + NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon, + NR_RACH_ConfigGeneric_t *rach_ConfigGeneric, + NR_RACH_ConfigDedicated_t *rach_ConfigDedicated) { NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id); - NR_ServingCellConfigCommon_t *scc = mac->scc; - NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon; - NR_RACH_ConfigGeneric_t *rach_ConfigGeneric; - // NR_BeamFailureRecoveryConfig_t *beam_failure_recovery_config = &mac->RA_BeamFailureRecoveryConfig; // todo + RA_config_t *ra = &mac->ra; + ra->RA_active = 1; + ra->RA_RAPID_found = 0; + ra->preambleTransMax = 0; + ra->first_Msg3 = 1; + ra->starting_preamble_nb = 0; + ra->RA_backoff_cnt = 0; - int messagePowerOffsetGroupB = 0, messageSizeGroupA, PLThreshold, sizeOfRA_PreamblesGroupA = 0, numberOfRA_Preambles, deltaPreamble_Msg3 = 0; - uint8_t noGroupB = 0, s_id, t_id, f_id, ul_carrier_id, Msg3_size; - - AssertFatal(scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup != NULL, "[UE %d] FATAL nr_rach_ConfigCommon is NULL !!!\n", mod_id); - nr_rach_ConfigCommon = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup; - rach_ConfigGeneric = &nr_rach_ConfigCommon->rach_ConfigGeneric; - - // NR_RSRP_Range_t rsrp_ThresholdSSB; // todo - - /////////////////////////////////////////////////////////// - //////////* UE Random Access Resource Selection *////////// - /////////////////////////////////////////////////////////// - - - // todo: - // - switch initialisation cases - // -- RA initiated by beam failure recovery operation (subclause 5.17 TS 38.321) - // --- SSB selection, set prach_resources->ra_PreambleIndex - // -- RA initiated by PDCCH: ra_preamble_index provided by PDCCH && ra_PreambleIndex != 0b000000 - // --- set PREAMBLE_INDEX to ra_preamble_index - // --- select the SSB signalled by PDCCH - // -- RA initiated for SI request: - // --- SSB selection, set prach_resources->ra_PreambleIndex + prach_resources->RA_PREAMBLE_BACKOFF = 0; + prach_resources->RA_PCMAX = nr_get_Pcmax(mod_id); + prach_resources->RA_PREAMBLE_TRANSMISSION_COUNTER = 1; + prach_resources->RA_PREAMBLE_POWER_RAMPING_COUNTER = 1; + prach_resources->POWER_OFFSET_2STEP_RA = 0; + prach_resources->RA_SCALING_FACTOR_BI = 1; if (rach_ConfigDedicated) { - //////////* Contention free RA *////////// - // - the PRACH preamble for the UE to transmit is set through RRC configuration - // - this is the default mode in current implementation! - // Operation for contention-free RA resources when: - // - available SSB with SS-RSRP above rsrp-ThresholdSSB: SSB selection - // - available CSI-RS with CSI-RSRP above rsrp-ThresholdCSI-RS: CSI-RS selection - // - network controlled Mobility - uint8_t cfra_ssb_resource_idx = 0; - prach_resources->ra_PreambleIndex = rach_ConfigDedicated->cfra->resources.choice.ssb->ssb_ResourceList.list.array[cfra_ssb_resource_idx]->ra_PreambleIndex; - LOG_D(MAC, "[RAPROC] - Selected RA preamble index %d for contention-free random access procedure... \n", prach_resources->ra_PreambleIndex); + if (rach_ConfigDedicated->cfra){ + LOG_I(MAC, "Initialization of 4-step contention-free random access procedure\n"); + prach_resources->RA_TYPE = RA_4STEP; + ra->cfra = 1; + } else if (rach_ConfigDedicated->ext1){ + if (rach_ConfigDedicated->ext1->cfra_TwoStep_r16){ + LOG_I(MAC, "In %s: setting RA type to 2-step...\n", __FUNCTION__); + prach_resources->RA_TYPE = RA_2STEP; + ra->cfra = 1; + } else { + LOG_E(MAC, "In %s: config not handled\n", __FUNCTION__); + } + } else { + LOG_E(MAC, "In %s: config not handled\n", __FUNCTION__); + } } else { - //////////* Contention-based RA preamble selection *////////// - // todo: - // - selection of SSB with SS-RSRP above rsrp-ThresholdSSB else select any SSB - // - todo determine next available PRACH occasion + LOG_E(MAC, "In %s: config not handled\n", __FUNCTION__); + } - // rsrp_ThresholdSSB = *nr_rach_ConfigCommon->rsrp_ThresholdSSB; + if (prach_resources->RA_TYPE == RA_2STEP){ + LOG_E(MAC, "Missing implementation of initialization of 2-step RA specific variables...\n"); + } else if (prach_resources->RA_TYPE == RA_4STEP){ + LOG_D(MAC, "Initialization of 4-step RA specific variables...\n"); + switch (rach_ConfigGeneric->powerRampingStep){ // in dB + case 0: + prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP = 0; + break; + case 1: + prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP = 2; + break; + case 2: + prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP = 4; + break; + case 3: + prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP = 6; + break; + } - // Determine the SSB to RACH mapping ratio - // ======================================= + switch (rach_ConfigGeneric->preambleTransMax) { + case 0: + ra->preambleTransMax = 3; + break; + case 1: + ra->preambleTransMax = 4; + break; + case 2: + ra->preambleTransMax = 5; + break; + case 3: + ra->preambleTransMax = 6; + break; + case 4: + ra->preambleTransMax = 7; + break; + case 5: + ra->preambleTransMax = 8; + break; + case 6: + ra->preambleTransMax = 10; + break; + case 7: + ra->preambleTransMax = 20; + break; + case 8: + ra->preambleTransMax = 50; + break; + case 9: + ra->preambleTransMax = 100; + break; + case 10: + ra->preambleTransMax = 200; + break; + } + if (nr_rach_ConfigCommon->ext1) { + if (nr_rach_ConfigCommon->ext1->ra_PrioritizationForAccessIdentity){ + LOG_D(MAC, "In %s:%d: Missing implementation for Access Identity initialization procedures\n", __FUNCTION__, __LINE__); + } + } + } + + return; + +} + +void ssb_rach_config(RA_config_t *ra, NR_PRACH_RESOURCES_t *prach_resources, NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon, fapi_nr_ul_config_prach_pdu *prach_pdu){ + + // Determine the SSB to RACH mapping ratio + // ======================================= + if (prach_resources->RA_TYPE == RA_4STEP){ NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR ssb_perRACH_config = nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present; boolean_t multiple_ssb_per_ro; // true if more than one or exactly one SSB per RACH occasion, false if more than one RO per SSB uint8_t ssb_rach_ratio; // Nb of SSBs per RACH or RACHs per SSB - long cb_preambles_per_ssb; // Nb of preambles per SSB int total_preambles_per_ssb; - int starting_preamble_nb = 0; uint8_t ssb_nb_in_ro; + int numberOfRA_Preambles = 64; switch (ssb_perRACH_config){ case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneEighth: multiple_ssb_per_ro = false; ssb_rach_ratio = 8; - cb_preambles_per_ssb = 4 * (nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.oneEighth + 1); + ra->cb_preambles_per_ssb = 4 * (nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.oneEighth + 1); break; case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneFourth: multiple_ssb_per_ro = false; ssb_rach_ratio = 4; - cb_preambles_per_ssb = 4 * (nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.oneFourth + 1); + ra->cb_preambles_per_ssb = 4 * (nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.oneFourth + 1); break; case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneHalf: multiple_ssb_per_ro = false; ssb_rach_ratio = 2; - cb_preambles_per_ssb = 4 * (nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.oneHalf + 1); + ra->cb_preambles_per_ssb = 4 * (nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.oneHalf + 1); break; case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_one: multiple_ssb_per_ro = true; ssb_rach_ratio = 1; - cb_preambles_per_ssb = 4 * (nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.one + 1); + ra->cb_preambles_per_ssb = 4 * (nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.one + 1); break; case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_two: multiple_ssb_per_ro = true; ssb_rach_ratio = 2; - cb_preambles_per_ssb = 4 * (nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.two + 1); + ra->cb_preambles_per_ssb = 4 * (nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.two + 1); break; case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_four: multiple_ssb_per_ro = true; ssb_rach_ratio = 4; - cb_preambles_per_ssb = nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.four; + ra->cb_preambles_per_ssb = nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.four; break; case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_eight: multiple_ssb_per_ro = true; ssb_rach_ratio = 8; - cb_preambles_per_ssb = nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.eight; + ra->cb_preambles_per_ssb = nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.eight; break; case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_sixteen: multiple_ssb_per_ro = true; ssb_rach_ratio = 16; - cb_preambles_per_ssb = nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.sixteen; + ra->cb_preambles_per_ssb = nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.sixteen; break; default: AssertFatal(1 == 0, "Unsupported ssb_perRACH_config %d\n", ssb_perRACH_config); break; } - Msg3_size = mac->RA_Msg3_size; - - numberOfRA_Preambles = 64; - if(nr_rach_ConfigCommon->totalNumberOfRA_Preambles != NULL) + if (nr_rach_ConfigCommon->totalNumberOfRA_Preambles) numberOfRA_Preambles = *(nr_rach_ConfigCommon->totalNumberOfRA_Preambles); // Compute the proper Preamble selection params according to the selected SSB and the ssb_perRACH_OccasionAndCB_PreamblesPerSSB configuration @@ -197,18 +228,47 @@ void nr_get_prach_resources(module_id_t mod_id, total_preambles_per_ssb = numberOfRA_Preambles / ssb_rach_ratio; ssb_nb_in_ro = prach_pdu->ssb_nb_in_ro; - starting_preamble_nb = total_preambles_per_ssb * ssb_nb_in_ro; + ra->starting_preamble_nb = total_preambles_per_ssb * ssb_nb_in_ro; } else { total_preambles_per_ssb = numberOfRA_Preambles; - starting_preamble_nb = 0; + ra->starting_preamble_nb = 0; + } + } else { + LOG_E(MAC, "In %s:%d: missing implementation for 2-step RA...\n", __FUNCTION__, __LINE__); + } +} + +// This routine implements RA premable configuration according to +// section 5.1 (Random Access procedure) of 3GPP TS 38.321 version 16.2.1 Release 16 +void ra_preambles_config(NR_PRACH_RESOURCES_t *prach_resources, NR_UE_MAC_INST_t *mac, int16_t dl_pathloss){ + + int messageSizeGroupA = 0; + int sizeOfRA_PreamblesGroupA = 0; + int messagePowerOffsetGroupB = 0; + int PLThreshold; + long deltaPreamble_Msg3 = 0; + uint8_t noGroupB = 0; + RA_config_t *ra = &mac->ra; + NR_ServingCellConfigCommon_t *scc = mac->scc; + NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup; + NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &nr_rach_ConfigCommon->rach_ConfigGeneric; + + if (prach_resources->RA_TYPE == RA_4STEP){ + + if (scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->msg3_DeltaPreamble){ + deltaPreamble_Msg3 = (*scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->msg3_DeltaPreamble) * 2; // dB + LOG_D(MAC, "In %s: deltaPreamble_Msg3 set to %ld\n", __FUNCTION__, deltaPreamble_Msg3); } if (!nr_rach_ConfigCommon->groupBconfigured) { noGroupB = 1; + LOG_D(MAC, "In %s:%d: preambles group B is not configured...\n", __FUNCTION__, __LINE__); } else { // RA preambles group B is configured - // - Defining the number of RA preambles in RA Preamble Group A for each SSB */ + // - Random Access Preambles group B is configured for 4-step RA type + // - Defining the number of RA preambles in RA Preamble Group A for each SSB + LOG_D(MAC, "In %s:%d: preambles group B is configured...\n", __FUNCTION__, __LINE__); sizeOfRA_PreamblesGroupA = nr_rach_ConfigCommon->groupBconfigured->numberOfRA_PreamblesGroupA; switch (nr_rach_ConfigCommon->groupBconfigured->ra_Msg3SizeGroupA){ /* - Threshold to determine the groups of RA preambles */ @@ -243,7 +303,7 @@ void nr_get_prach_resources(module_id_t mod_id, messageSizeGroupA = 72; break; default: - AssertFatal(1 == 0,"Unknown ra_Msg3SizeGroupA %lu\n", nr_rach_ConfigCommon->groupBconfigured->ra_Msg3SizeGroupA); + AssertFatal(1 == 0, "Unknown ra_Msg3SizeGroupA %lu\n", nr_rach_ConfigCommon->groupBconfigured->ra_Msg3SizeGroupA); /* todo cases 10 -15*/ } @@ -278,187 +338,201 @@ void nr_get_prach_resources(module_id_t mod_id, AssertFatal(1 == 0,"Unknown messagePowerOffsetGroupB %lu\n", nr_rach_ConfigCommon->groupBconfigured->messagePowerOffsetGroupB); } - // todo Msg3-DeltaPreamble should be provided from higher layers, otherwise is 0 - mac->deltaPreamble_Msg3 = 0; - deltaPreamble_Msg3 = mac->deltaPreamble_Msg3; + PLThreshold = prach_resources->RA_PCMAX - rach_ConfigGeneric->preambleReceivedTargetPower - deltaPreamble_Msg3 - messagePowerOffsetGroupB; + } - - PLThreshold = prach_resources->RA_PCMAX - rach_ConfigGeneric->preambleReceivedTargetPower - deltaPreamble_Msg3 - messagePowerOffsetGroupB; - - /* Msg3 has not been transmitted yet */ - if (first_Msg3 == 1) { - if (noGroupB == 1) { - // use Group A preamble - prach_resources->ra_PreambleIndex = starting_preamble_nb + ((taus()) % cb_preambles_per_ssb); - mac->RA_usedGroupA = 1; - } else if ((Msg3_size < messageSizeGroupA) && (get_nr_PL(mod_id, CC_id, gNB_id) > PLThreshold)) { - // Group B is configured and RA preamble Group A is used - // - todo add condition on CCCH_sdu_size for initiation by CCCH - prach_resources->ra_PreambleIndex = starting_preamble_nb + ((taus()) % sizeOfRA_PreamblesGroupA); - mac->RA_usedGroupA = 1; - } else { - // Group B preamble is configured and used - // the first sizeOfRA_PreamblesGroupA RA preambles belong to RA Preambles Group A - // the remaining belong to RA Preambles Group B - prach_resources->ra_PreambleIndex = starting_preamble_nb + sizeOfRA_PreamblesGroupA + ((taus()) % (cb_preambles_per_ssb - sizeOfRA_PreamblesGroupA)); - mac->RA_usedGroupA = 0; - } - } else { // Msg3 is being retransmitted - if (mac->RA_usedGroupA == 1 && noGroupB == 1) { - prach_resources->ra_PreambleIndex = starting_preamble_nb + ((taus()) % cb_preambles_per_ssb); - } else if (mac->RA_usedGroupA == 1 && noGroupB == 0){ - prach_resources->ra_PreambleIndex = starting_preamble_nb + ((taus()) % sizeOfRA_PreamblesGroupA); - } else { - prach_resources->ra_PreambleIndex = starting_preamble_nb + sizeOfRA_PreamblesGroupA + ((taus()) % (cb_preambles_per_ssb - sizeOfRA_PreamblesGroupA)); - } + } else { + // todo: + // - groupB-ConfiguredTwoStepRA + // - msgA-DeltaPreamble + LOG_E(MAC, "In %s:%d: missing implementation for 2-step RA...\n", __FUNCTION__, __LINE__); + } + /* Msg3 has not been transmitted yet */ + if (ra->first_Msg3) { + if (noGroupB) { + // use Group A preamble + prach_resources->ra_PreambleIndex = ra->starting_preamble_nb + ((taus()) % ra->cb_preambles_per_ssb); + ra->RA_usedGroupA = 1; + } else if ((ra->Msg3_size < messageSizeGroupA) && (dl_pathloss > PLThreshold)) { + // Group B is configured and RA preamble Group A is used + // - todo add condition on CCCH_sdu_size for initiation by CCCH + prach_resources->ra_PreambleIndex = ra->starting_preamble_nb + ((taus()) % sizeOfRA_PreamblesGroupA); + ra->RA_usedGroupA = 1; + } else { + // Group B preamble is configured and used + // the first sizeOfRA_PreamblesGroupA RA preambles belong to RA Preambles Group A + // the remaining belong to RA Preambles Group B + prach_resources->ra_PreambleIndex = ra->starting_preamble_nb + sizeOfRA_PreamblesGroupA + ((taus()) % (ra->cb_preambles_per_ssb - sizeOfRA_PreamblesGroupA)); + ra->RA_usedGroupA = 0; } + } else { // Msg3 is being retransmitted + if (ra->RA_usedGroupA && noGroupB) { + prach_resources->ra_PreambleIndex = ra->starting_preamble_nb + ((taus()) % ra->cb_preambles_per_ssb); + } else if (ra->RA_usedGroupA && !noGroupB){ + prach_resources->ra_PreambleIndex = ra->starting_preamble_nb + ((taus()) % sizeOfRA_PreamblesGroupA); + } else { + prach_resources->ra_PreambleIndex = ra->starting_preamble_nb + sizeOfRA_PreamblesGroupA + ((taus()) % (ra->cb_preambles_per_ssb - sizeOfRA_PreamblesGroupA)); + } + } +} +// RA-RNTI computation (associated to PRACH occasion in which the RA Preamble is transmitted) +// - this does not apply to contention-free RA Preamble for beam failure recovery request +// - getting star_symb, SFN_nbr from table 6.3.3.2-3 (TDD and FR1 scenario) +// - ul_carrier_id: UL carrier used for RA preamble transmission, hardcoded for NUL carrier +// - f_id: index of the PRACH occasion in the frequency domain +// - s_id is starting symbol of the PRACH occasion [0...14] +// - t_id is the first slot of the PRACH occasion in a system frame [0...80] +uint16_t set_ra_rnti(NR_UE_MAC_INST_t *mac, fapi_nr_ul_config_prach_pdu *prach_pdu){ + + RA_config_t *ra = &mac->ra; + uint8_t ul_carrier_id = 0; // NUL + uint8_t f_id = prach_pdu->num_ra; + uint8_t t_id = prach_pdu->prach_slot; + uint8_t s_id = prach_pdu->prach_start_symbol; + + ra->ra_rnti = 1 + s_id + 14 * t_id + 1120 * f_id + 8960 * ul_carrier_id; + + LOG_D(MAC, "Computed ra_RNTI is %x \n", ra->ra_rnti); + + return ra->ra_rnti; + +} + +// This routine implements Section 5.1.2 (UE Random Access Resource Selection) +// and Section 5.1.3 (Random Access Preamble Transmission) from 3GPP TS 38.321 +// - currently the PRACH preamble is set through RRC configuration for 4-step CFRA mode +// todo: +// - determine next available PRACH occasion +// -- if RA initiated for SI request and ra_AssociationPeriodIndex and si-RequestPeriod are configured +// -- else if SSB is selected above +// -- else if CSI-RS is selected above +// - switch initialisation cases +// -- RA initiated by beam failure recovery operation (subclause 5.17 TS 38.321) +// --- SSB selection, set prach_resources->ra_PreambleIndex +// -- RA initiated by PDCCH: ra_preamble_index provided by PDCCH && ra_PreambleIndex != 0b000000 +// --- set PREAMBLE_INDEX to ra_preamble_index +// --- select the SSB signalled by PDCCH +// -- RA initiated for SI request: +// --- SSB selection, set prach_resources->ra_PreambleIndex +// - condition on notification of suspending power ramping counter from lower layer (5.1.3 TS 38.321) +// - check if SSB or CSI-RS have not changed since the selection in the last RA Preamble tranmission +// - Contention-based RA preamble selection: +// -- selection of SSB with SS-RSRP above rsrp-ThresholdSSB else select any SSB +void nr_get_prach_resources(module_id_t mod_id, + int CC_id, + uint8_t gNB_id, + NR_PRACH_RESOURCES_t *prach_resources, + fapi_nr_ul_config_prach_pdu *prach_pdu, + NR_RACH_ConfigDedicated_t * rach_ConfigDedicated){ + + NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id); + RA_config_t *ra = &mac->ra; + NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon = mac->scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup; + + LOG_D(PHY, "In %s: getting PRACH resources frame (first_Msg3 %d)\n", __FUNCTION__, ra->first_Msg3); + + if (rach_ConfigDedicated) { + if (rach_ConfigDedicated->cfra){ + uint8_t cfra_ssb_resource_idx = 0; + prach_resources->ra_PreambleIndex = rach_ConfigDedicated->cfra->resources.choice.ssb->ssb_ResourceList.list.array[cfra_ssb_resource_idx]->ra_PreambleIndex; + LOG_D(MAC, "In %s: selected RA preamble index %d for contention-free random access procedure for SSB with Id %d\n", __FUNCTION__, prach_resources->ra_PreambleIndex, cfra_ssb_resource_idx); + } + } else { + int16_t dl_pathloss = get_nr_PL(mod_id, CC_id, gNB_id); + ssb_rach_config(ra, prach_resources, nr_rach_ConfigCommon, prach_pdu); + ra_preambles_config(prach_resources, mac, dl_pathloss); LOG_D(MAC, "[RAPROC] - Selected RA preamble index %d for contention-based random access procedure... \n", prach_resources->ra_PreambleIndex); } - // todo determine next available PRACH occasion - // - if RA initiated for SI request and ra_AssociationPeriodIndex and si-RequestPeriod are configured - // - else if SSB is selected above - // - else if CSI-RS is selected above - - ///////////////////////////////////////////////////////////////////////////// - //////////* Random Access Preamble Transmission (5.1.3 TS 38.321) *////////// - ///////////////////////////////////////////////////////////////////////////// - // todo: - // - condition on notification of suspending power ramping counter from lower layer (5.1.3 TS 38.321) - // - check if SSB or CSI-RS have not changed since the selection in the last RA Preamble tranmission - // - Extend RA_rnti computation (e.g. f_id selection, ul_carrier_id are hardcoded) - - if (mac->RA_PREAMBLE_TRANSMISSION_COUNTER > 1) - mac->RA_PREAMBLE_POWER_RAMPING_COUNTER++; - + if (prach_resources->RA_PREAMBLE_TRANSMISSION_COUNTER > 1) + prach_resources->RA_PREAMBLE_POWER_RAMPING_COUNTER++; prach_resources->ra_PREAMBLE_RECEIVED_TARGET_POWER = nr_get_Po_NOMINAL_PUSCH(prach_resources, mod_id, CC_id); + prach_resources->ra_RNTI = set_ra_rnti(mac, prach_pdu); - // RA-RNTI computation (associated to PRACH occasion in which the RA Preamble is transmitted) - // 1) this does not apply to contention-free RA Preamble for beam failure recovery request - // 2) getting star_symb, SFN_nbr from table 6.3.3.2-3 (TDD and FR1 scenario) - - // ra_RNTI computation - // - ul_carrier_id: UL carrier used for RA preamble transmission, hardcoded for NUL carrier - // - f_id: index of the PRACH occasion in the frequency domain - // - s_id is starting symbol of the PRACH occasion [0...14] - // - t_id is the first slot of the PRACH occasion in a system frame [0...80] - ul_carrier_id = 0; // NUL - f_id = prach_pdu->num_ra; - t_id = prach_pdu->prach_slot; - s_id = prach_pdu->prach_start_symbol; - - prach_resources->ra_RNTI = 1 + s_id + 14 * t_id + 1120 * f_id + 8960 * ul_carrier_id; - mac->ra_rnti = prach_resources->ra_RNTI; - - LOG_D(MAC, "Computed ra_RNTI is %x \n", prach_resources->ra_RNTI); } // TbD: RA_attempt_number not used void nr_Msg1_transmitted(module_id_t mod_id, uint8_t CC_id, frame_t frameP, uint8_t gNB_id){ - AssertFatal(CC_id == 0, "Transmission on secondary CCs is not supported yet\n"); NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id); - mac->ra_state = WAIT_RAR; - // Start contention resolution timer - mac->RA_attempt_number++; + RA_config_t *ra = &mac->ra; + ra->ra_state = WAIT_RAR; + ra->RA_attempt_number++; } void nr_Msg3_transmitted(module_id_t mod_id, uint8_t CC_id, frame_t frameP, uint8_t gNB_id){ - AssertFatal(CC_id == 0, "Transmission on secondary CCs is not supported yet\n"); - LOG_D(MAC,"[UE %d][RAPROC] Frame %d : Msg3_tx: Starting contention resolution timer\n", mod_id, frameP); + NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id); + NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon = mac->scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup; + RA_config_t *ra = &mac->ra; + + LOG_D(MAC,"In %s: [UE %d] Frame %d, CB-RA: starting contention resolution timer\n", __FUNCTION__, mod_id, frameP); + // start contention resolution timer - mac->RA_contention_resolution_cnt = 0; - mac->RA_contention_resolution_timer_active = 1; + ra->RA_contention_resolution_cnt = (nr_rach_ConfigCommon->ra_ContentionResolutionTimer + 1) * 8; + ra->RA_contention_resolution_timer_active = 1; + } ///////////////////////////////////////////////////////////////////////// -///////* Random Access Preamble Initialization (5.1.1 TS 38.321) */////// +// This function handles: +// - Random Access Preamble Initialization (5.1.1 TS 38.321) +// - Random Access Response reception (5.1.4 TS 38.321) +/// In the current implementation, RA is 4-step contention free only ///////////////////////////////////////////////////////////////////////// -/// Handling inizialization by PDCCH order, MAC entity or RRC (TS 38.300) -/// Only one RA procedure is ongoing at any point in time in a MAC entity -/// the RA procedure on a SCell shall only be initiated by PDCCH order -/// in the current implementation, RA is contention free only - -// WIP // todo TS 38.321: -// - check if carrier to use is explicitly signalled then do (1) RA CARRIER SELECTION (SUL, NUL) (2) set PCMAX // - BWP operation (subclause 5.15 TS 38.321) -// - handle initialization by beam failure recovery +// - beam failure recovery // - handle initialization by handover -// - handle transmission on DCCH using PRACH (during handover, or sending SR for example) +// - handle DL assignment on PDCCH for RA-RNTI +// - transmission on DCCH using PRACH (during handover, or sending SR for example) // - take into account MAC CEs in size_sdu (currently hardcoded size to 1 MAC subPDU and 1 padding subheader) // - fix rrc data req logic // - retrieve TBS // - add mac_rrc_nr_data_req_ue, etc ... -// - add the backoff condition here if we have it from a previous RA reponse which failed (i.e. backoff indicator) - +// - Msg3 Retransmissions to be scheduled by DCI 0_0 uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources, fapi_nr_ul_config_prach_pdu *prach_pdu, module_id_t mod_id, int CC_id, - UE_MODE_t UE_mode, frame_t frame, uint8_t gNB_id, int nr_slot_tx){ NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id); + RA_config_t *ra = &mac->ra; uint8_t mac_sdus[MAX_NR_ULSCH_PAYLOAD_BYTES]; uint8_t lcid = UL_SCH_LCID_CCCH_MSG3, *payload; - //uint8_t ra_ResponseWindow; uint16_t size_sdu = 0; unsigned short post_padding; - //fapi_nr_config_request_t *cfg = &mac->phy_config.config_req; NR_ServingCellConfigCommon_t *scc = mac->scc; + AssertFatal(scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup != NULL, "In %s: FATAL! nr_rach_ConfigCommon is NULL...\n", __FUNCTION__); NR_RACH_ConfigCommon_t *setup = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup; + AssertFatal(&setup->rach_ConfigGeneric != NULL, "In %s: FATAL! rach_ConfigGeneric is NULL...\n", __FUNCTION__); NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &setup->rach_ConfigGeneric; - //NR_FrequencyInfoDL_t *frequencyInfoDL = scc->downlinkConfigCommon->frequencyInfoDL; - NR_RACH_ConfigDedicated_t *rach_ConfigDedicated = mac->rach_ConfigDedicated; - - int prach_genarate = 0; - // int32_t frame_diff = 0; + NR_RACH_ConfigDedicated_t *rach_ConfigDedicated = ra->rach_ConfigDedicated; uint8_t sdu_lcids[NB_RB_MAX] = {0}; uint16_t sdu_lengths[NB_RB_MAX] = {0}; - int TBS_bytes = 848, header_length_total=0, num_sdus, offset, preambleTransMax, mac_ce_len; + int TBS_bytes = 848, header_length_total=0, num_sdus, offset, mac_ce_len; - AssertFatal(CC_id == 0,"Transmission on secondary CCs is not supported yet\n"); + // Delay init RA procedure to allow the convergence of the IIR filter on PRACH noise measurements at gNB side + if (!prach_resources->init_msg1) { + if (((MAX_FRAME_NUMBER + frame - prach_resources->sync_frame) % MAX_FRAME_NUMBER) > 150){ + prach_resources->init_msg1 = 1; + } else { + return 0; + } + } if (prach_resources->init_msg1) { - LOG_D(MAC, "nr_ue_get_rach, RA_active value: %d", mac->RA_active); - - AssertFatal(setup != NULL, "[UE %d] FATAL nr_rach_ConfigCommon is NULL !!!\n", mod_id); - - if (mac->RA_active == 0) { + if (ra->RA_active == 0) { /* RA not active - checking if RRC is ready to initiate the RA procedure */ - LOG_I(MAC, "RA not active. Starting RA preamble initialization.\n"); - - mac->RA_RAPID_found = 0; - - /* Set RA_PREAMBLE_POWER_RAMPING_STEP */ - switch (rach_ConfigGeneric->powerRampingStep){ // in dB - case 0: - prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP = 0; - break; - case 1: - prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP = 2; - break; - case 2: - prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP = 4; - break; - case 3: - prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP = 6; - break; - } - - prach_resources->RA_PREAMBLE_BACKOFF = 0; - prach_resources->RA_SCALING_FACTOR_BI = 1; - prach_resources->RA_PCMAX = 0; // currently hardcoded to 0 + LOG_D(MAC, "RA not active. Checking for data to transmit from upper layers...\n"); payload = (uint8_t*) &mac->CCCH_pdu.payload; - mac_ce_len = 0; num_sdus = 1; post_padding = 1; @@ -488,32 +562,20 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources, size_sdu += sdu_lengths[0]; } - //mac->RA_tx_frame = frame; - //mac->RA_tx_slot = nr_slot_tx; - //mac->RA_backoff_frame = frame; - //mac->RA_backoff_slot = nr_slot_tx; - if (size_sdu > 0) { - LOG_I(MAC, "[UE %d] Frame %d: Initialisation Random Access Procedure\n", mod_id, frame); + LOG_D(MAC, "[UE %d][%d.%d]: starting initialisation Random Access Procedure...\n", mod_id, frame, nr_slot_tx); - mac->RA_PREAMBLE_TRANSMISSION_COUNTER = 1; - mac->RA_PREAMBLE_POWER_RAMPING_COUNTER = 1; - mac->RA_Msg3_size = size_sdu + sizeof(NR_MAC_SUBHEADER_SHORT) + sizeof(NR_MAC_SUBHEADER_SHORT); - mac->RA_prachMaskIndex = 0; - // todo: add the backoff condition here - mac->RA_backoff_cnt = 0; - mac->RA_active = 1; + ra->Msg3_size = size_sdu + sizeof(NR_MAC_SUBHEADER_SHORT) + sizeof(NR_MAC_SUBHEADER_SHORT); + + init_RA(mod_id, prach_resources, setup, rach_ConfigGeneric, rach_ConfigDedicated); prach_resources->Msg3 = payload; - nr_get_RA_window(mac); // Fill in preamble and PRACH resources - if (mac->generate_nr_prach == 1) - { - nr_get_prach_resources(mod_id, CC_id, gNB_id, nr_slot_tx, prach_resources, prach_pdu, rach_ConfigDedicated); - prach_genarate = 1; - } + if (ra->generate_nr_prach == 1) + nr_get_prach_resources(mod_id, CC_id, gNB_id, prach_resources, prach_pdu, rach_ConfigDedicated); + offset = nr_generate_ulsch_pdu((uint8_t *) mac_sdus, // sdus buffer (uint8_t *) payload, // UL MAC pdu pointer num_sdus, // num sdus @@ -533,146 +595,60 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources, payload[offset + j] = 0; // mac_pdu[offset + j] = 0; } } - } else if (mac->RA_window_cnt != -1) { // RACH is active + } else if (ra->RA_window_cnt != -1) { // RACH is active - //////////////////////////////////////////////////////////////// - /////* Random Access Response reception (5.1.4 TS 38.321) *///// - //////////////////////////////////////////////////////////////// - // Handling ra_responseWindow, RA_PREAMBLE_TRANSMISSION_COUNTER - // and RA_backoff_cnt - // todo: - // - handle beam failure recovery request - // - handle DL assignment on PDCCH for RA-RNTI - // - handle backoff and raResponseWindow params + LOG_D(MAC, "In %s [%d.%d] RA is active: RA window count %d, RA backoff count %d\n", __FUNCTION__, frame, nr_slot_tx, ra->RA_window_cnt, ra->RA_backoff_cnt); - // LOG_D(MAC, "[MAC][UE %d][RAPROC] frame %d, subframe %d: RA Active, window cnt %d (RA_tx_frame %d, RA_tx_subframe %d)\n", - // mod_id, frame, nr_slot_tx, mac->RA_window_cnt, mac->RA_tx_frame, mac->RA_tx_subframe); - - if (mac->RA_BI_found){ - prach_resources->RA_PREAMBLE_BACKOFF = prach_resources->RA_SCALING_FACTOR_BI * mac->RA_backoff_indicator; + if (ra->RA_BI_found){ + prach_resources->RA_PREAMBLE_BACKOFF = prach_resources->RA_SCALING_FACTOR_BI * ra->RA_backoff_indicator; } else { prach_resources->RA_PREAMBLE_BACKOFF = 0; } - if (mac->RA_window_cnt >= 0 && mac->RA_RAPID_found == 1) { - + if (ra->RA_window_cnt >= 0 && ra->RA_RAPID_found == 1) { // Reset RA_active flag: it disables Msg3 retransmission (8.3 of TS 38.213) - // TbD Msg3 Retransmissions to be scheduled by DCI 0_0 - //mac->RA_active = 0; - mac->RA_window_cnt = -1; - mac->ra_state = RA_SUCCEEDED; - mac->generate_nr_prach = 2; - LOG_I(MAC, "[MAC][UE %d][RAPROC]: frame %d slot %d RAR successfully received\n", mod_id, frame, nr_slot_tx); + nr_ra_succeeded(mod_id, frame, nr_slot_tx); - } else if (mac->RA_window_cnt == 0 && !mac->RA_RAPID_found) { + } else if (ra->RA_window_cnt == 0 && !ra->RA_RAPID_found) { - LOG_I(MAC, "[MAC][UE %d][RAPROC] Frame %d: nr_slot_tx %d: RAR reception failed \n", mod_id, frame, nr_slot_tx); + LOG_I(MAC, "[UE %d][%d:%d] RAR reception failed \n", mod_id, frame, nr_slot_tx); - mac->ra_state = RA_UE_IDLE; - mac->RA_PREAMBLE_TRANSMISSION_COUNTER++; + nr_ra_failed(mod_id, CC_id, prach_resources, frame, nr_slot_tx); - preambleTransMax = -1; - switch (rach_ConfigGeneric->preambleTransMax) { - case 0: - preambleTransMax = 3; - break; - case 1: - preambleTransMax = 4; - break; - case 2: - preambleTransMax = 5; - break; - case 3: - preambleTransMax = 6; - break; - case 4: - preambleTransMax = 7; - break; - case 5: - preambleTransMax = 8; - break; - case 6: - preambleTransMax = 10; - break; - case 7: - preambleTransMax = 20; - break; - case 8: - preambleTransMax = 50; - break; - case 9: - preambleTransMax = 100; - break; - case 10: - preambleTransMax = 200; - break; - } + } else if (ra->RA_window_cnt > 0) { - // Resetting RA window - nr_get_RA_window(mac); - - if (mac->RA_PREAMBLE_TRANSMISSION_COUNTER == preambleTransMax + 1){ - LOG_D(MAC, "[UE %d] Frame %d: Maximum number of RACH attempts (%d)\n", mod_id, frame, preambleTransMax); - mac->RA_backoff_cnt = rand() % (prach_resources->RA_PREAMBLE_BACKOFF + 1); - mac->RA_PREAMBLE_TRANSMISSION_COUNTER = 1; - prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP += prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP << 1; // 2 dB increment - prach_resources->ra_PREAMBLE_RECEIVED_TARGET_POWER = nr_get_Po_NOMINAL_PUSCH(prach_resources, mod_id, CC_id); - } - - // compute backoff parameters - // if (mac->RA_backoff_cnt > 0){ - // frame_diff = (sframe_t) frame - mac->RA_backoff_frame; - // if (frame_diff < 0) frame_diff = -frame_diff; - // mac->RA_backoff_frame = frame; - // mac->RA_backoff_slot = nr_slot_tx; - // } - // compute RA window parameters - // if (mac->RA_window_cnt > 0){ - // frame_diff = (frame_t) frame - mac->RA_tx_frame; - // if (frame_diff < 0) frame_diff = -frame_diff; - // mac->RA_window_cnt -= ((10 * frame_diff) + (nr_slot_tx - mac->RA_tx_subframe)); - // LOG_D(MAC, "[MAC][UE %d][RAPROC] Frame %d, subframe %d: RA Active, adjusted window cnt %d\n", mod_id, frame, nr_slot_tx, mac->RA_window_cnt); - // } - - // mac->RA_tx_frame = frame; - // mac->RA_tx_slot = nr_slot_tx; + LOG_D(MAC, "[UE %d][%d.%d]: RAR not received yet (RA window count %d) \n", mod_id, frame, nr_slot_tx, ra->RA_window_cnt); // Fill in preamble and PRACH resources - if (mac->generate_nr_prach == 1) - { - nr_get_prach_resources(mod_id, CC_id, gNB_id, nr_slot_tx, prach_resources, prach_pdu, rach_ConfigDedicated); - prach_genarate = 1; - } - } else { + ra->RA_window_cnt--; + nr_get_prach_resources(mod_id, CC_id, gNB_id, prach_resources, prach_pdu, rach_ConfigDedicated); - mac->RA_window_cnt--; + } else if (ra->RA_backoff_cnt > 0) { - LOG_D(MAC, "[MAC][UE %d][RAPROC][%d.%d]: RAR not received yet (RA window count %d) \n", - mod_id, - frame, - nr_slot_tx, - mac->RA_window_cnt); + LOG_D(MAC, "[UE %d][%d.%d]: RAR not received yet (RA backoff count %d) \n", mod_id, frame, nr_slot_tx, ra->RA_backoff_cnt); - // Fill in preamble and PRACH resources - if (mac->generate_nr_prach == 1) - { - nr_get_prach_resources(mod_id, CC_id, gNB_id, nr_slot_tx, prach_resources, prach_pdu, rach_ConfigDedicated); - prach_genarate = 1; + ra->RA_backoff_cnt--; + + if ((ra->RA_backoff_cnt > 0 && ra->generate_nr_prach == 1) || ra->RA_backoff_cnt == 0){ + nr_get_prach_resources(mod_id, CC_id, gNB_id, prach_resources, prach_pdu, rach_ConfigDedicated); } } } - } else if (UE_mode == PUSCH) { - LOG_D(MAC, "[UE %d] FATAL: Should not have checked for RACH in PUSCH yet ...", mod_id); - AssertFatal(1 == 0, ""); } - //return mac->generate_nr_prach; - return prach_genarate; + + if (ra->RA_contention_resolution_timer_active){ + nr_ue_contention_resolution(mod_id, CC_id, frame, nr_slot_tx, prach_resources); + } + + return ra->generate_nr_prach; + } void nr_get_RA_window(NR_UE_MAC_INST_t *mac){ uint8_t mu, ra_ResponseWindow; + RA_config_t *ra = &mac->ra; NR_ServingCellConfigCommon_t *scc = mac->scc; NR_RACH_ConfigCommon_t *setup = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup; NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &setup->rach_ConfigGeneric; @@ -685,32 +661,139 @@ void nr_get_RA_window(NR_UE_MAC_INST_t *mac){ else mu = frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; - mac->RA_window_cnt = mac->RA_offset*nr_slots_per_frame[mu]; // taking into account the 2 frames gap introduced by OAI gNB + ra->RA_window_cnt = ra->RA_offset*nr_slots_per_frame[mu]; // taking into account the 2 frames gap introduced by OAI gNB switch (ra_ResponseWindow) { case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl1: - mac->RA_window_cnt += 1; + ra->RA_window_cnt += 1; break; case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl2: - mac->RA_window_cnt += 2; + ra->RA_window_cnt += 2; break; case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl4: - mac->RA_window_cnt += 4; + ra->RA_window_cnt += 4; break; case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl8: - mac->RA_window_cnt += 8; + ra->RA_window_cnt += 8; break; case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl10: - mac->RA_window_cnt += 10; + ra->RA_window_cnt += 10; break; case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl20: - mac->RA_window_cnt += 20; + ra->RA_window_cnt += 20; break; case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl40: - mac->RA_window_cnt += 40; + ra->RA_window_cnt += 40; break; case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl80: - mac->RA_window_cnt += 80; + ra->RA_window_cnt += 80; break; } } + +//////////////////////////////////////////////////////////////////////////// +/////////* Random Access Contention Resolution (5.1.35 TS 38.321) *///////// +//////////////////////////////////////////////////////////////////////////// +// Handling contention resolution timer +// WIP todo: +// - beam failure recovery +// - RA completed +void nr_ue_contention_resolution(module_id_t module_id, int cc_id, frame_t frame, int slot, NR_PRACH_RESOURCES_t *prach_resources){ + + NR_UE_MAC_INST_t *mac = get_mac_inst(module_id); + RA_config_t *ra = &mac->ra; + + if (ra->RA_contention_resolution_timer_active == 1) { + + ra->RA_contention_resolution_cnt--; + + LOG_D(MAC, "In %s: [%d.%d] RA contention resolution timer %d\n", __FUNCTION__, frame, slot, ra->RA_contention_resolution_cnt); + + if (ra->RA_contention_resolution_cnt == 0) { + ra->t_crnti = 0; + ra->RA_active = 0; + ra->RA_contention_resolution_timer_active = 0; + // Signal PHY to quit RA procedure + LOG_E(MAC, "[UE %d] CB-RA: Contention resolution timer has expired, RA procedure has failed...\n", module_id); + nr_ra_failed(module_id, cc_id, prach_resources, frame, slot); + } + + } +} + +// Handlig successful RA completion @ MAC layer +// according to section 5 of 3GPP TS 38.321 version 16.2.1 Release 16 +// todo: +// - complete handling of received contention-based RA preamble +void nr_ra_succeeded(module_id_t mod_id, frame_t frame, int slot){ + + NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id); + RA_config_t *ra = &mac->ra; + + if (ra->cfra) { + + LOG_I(MAC, "[UE %d][%d.%d][RAPROC] RA procedure succeeded. CF-RA: RAR successfully received.\n", mod_id, frame, slot); + + ra->RA_window_cnt = -1; + + } else { + + LOG_I(MAC, "[UE %d][%d.%d][RAPROC] RA procedure succeeded. CB-RA: Contention Resolution is successful.\n", mod_id, frame, slot); + + ra->RA_contention_resolution_cnt = -1; + ra->RA_contention_resolution_timer_active = 0; + ra->t_crnti = 0; + + LOG_D(MAC, "In %s: [UE %d][%d.%d] CB-RA: cleared contention resolution timer...\n", __FUNCTION__, mod_id, frame, slot); + + } + + LOG_D(MAC, "In %s: [UE %d] clearing RA_active flag...\n", __FUNCTION__, mod_id); + ra->RA_active = 0; + ra->generate_nr_prach = 2; + ra->ra_state = RA_SUCCEEDED; + +} + +// Handlig failure of RA procedure @ MAC layer +// according to section 5 of 3GPP TS 38.321 version 16.2.1 Release 16 +// todo: +// - complete handling of received contention-based RA preamble +// - 2-step RA implementation +void nr_ra_failed(uint8_t mod_id, uint8_t CC_id, NR_PRACH_RESOURCES_t *prach_resources, frame_t frame, int slot) { + + NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id); + RA_config_t *ra = &mac->ra; + + ra->first_Msg3 = 0; + ra->generate_nr_prach = 3; + ra->ra_state = RA_UE_IDLE; + + prach_resources->RA_PREAMBLE_TRANSMISSION_COUNTER++; + + if(prach_resources->RA_TYPE == RA_4STEP){ + + if (prach_resources->RA_PREAMBLE_TRANSMISSION_COUNTER == ra->preambleTransMax + 1){ + + LOG_D(MAC, "In %s: [UE %d][%d.%d] Maximum number of RACH attempts (%d) reached, selecting backoff time...\n", __FUNCTION__, mod_id, frame, slot, ra->preambleTransMax); + + ra->RA_backoff_cnt = rand() % (prach_resources->RA_PREAMBLE_BACKOFF + 1); + + prach_resources->RA_PREAMBLE_TRANSMISSION_COUNTER = 1; + prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP += 2; // 2 dB increment + prach_resources->ra_PREAMBLE_RECEIVED_TARGET_POWER = nr_get_Po_NOMINAL_PUSCH(prach_resources, mod_id, CC_id); + + } else { + + // Resetting RA window + nr_get_RA_window(mac); + + } + + } else if (prach_resources->RA_TYPE == RA_2STEP){ + + LOG_E(MAC, "Missing implementation of RA failure handling for 2-step RA...\n"); + + } + +} diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c index 6195fff47b..11edc6c20d 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c @@ -55,23 +55,6 @@ void fill_dci_search_candidates(NR_SearchSpace_t *ss,fapi_nr_dl_config_dci_dl_pd LOG_D(MAC,"Filling search candidates for DCI\n"); - if(ss->searchSpaceId == 0) { - // TODO: Update the maximum number of PDCCH candidates accordingly with Aggregation Level - rel15->number_of_candidates=1; - rel15->CCE[0]=0; - rel15->L[0]=6; - } else { - rel15->number_of_candidates=4; - rel15->CCE[0]=0; - rel15->L[0]=4; - rel15->CCE[1]=4; - rel15->L[1]=4; - rel15->CCE[2]=8; - rel15->L[2]=4; - rel15->CCE[3]=12; - rel15->L[3]=4; - } - uint8_t aggregation; find_aggregation_candidates(&aggregation, &rel15->number_of_candidates, @@ -85,11 +68,13 @@ void fill_dci_search_candidates(NR_SearchSpace_t *ss,fapi_nr_dl_config_dci_dl_pd void config_dci_pdu(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15, fapi_nr_dl_config_request_t *dl_config, int rnti_type, int ss_id){ + RA_config_t *ra = &mac->ra; uint16_t monitoringSymbolsWithinSlot = 0; - uint8_t bwp_id = 1, coreset_id = 1; + uint8_t coreset_id = 1; int sps = 0; def_dci_pdu_rel15 = calloc(1,2*sizeof(dci_pdu_rel15_t)); AssertFatal(mac->scc != NULL, "scc is null\n"); + NR_BWP_Id_t bwp_id = mac->DL_BWP_Id; NR_ServingCellConfigCommon_t *scc = mac->scc; NR_BWP_DownlinkCommon_t *bwp_Common = mac->DLbwp[bwp_id - 1]->bwp_Common; NR_BWP_DownlinkCommon_t *initialDownlinkBWP = scc->downlinkConfigCommon->initialDownlinkBWP; @@ -128,7 +113,7 @@ void config_dci_pdu(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_dci_dl_pdu_rel15_t // Scrambling RNTI if (coreset->pdcch_DMRS_ScramblingID) { rel15->coreset.pdcch_dmrs_scrambling_id = *coreset->pdcch_DMRS_ScramblingID; - rel15->coreset.scrambling_rnti = mac->t_crnti; + rel15->coreset.scrambling_rnti = mac->crnti; } else { rel15->coreset.pdcch_dmrs_scrambling_id = *scc->physCellId; rel15->coreset.scrambling_rnti = 0; @@ -146,8 +131,8 @@ void config_dci_pdu(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_dci_dl_pdu_rel15_t // for SPS=14 8 MSBs in positions 13 down to 6 monitoringSymbolsWithinSlot = (ss->monitoringSymbolsWithinSlot->buf[0]<<(sps-8)) | (ss->monitoringSymbolsWithinSlot->buf[1]>>(16-sps)); rel15->rnti = mac->crnti; - rel15->BWPSize = NRRIV2BW(bwp_Common->genericParameters.locationAndBandwidth, 275); - rel15->BWPStart = NRRIV2PRBOFFSET(bwp_Common->genericParameters.locationAndBandwidth, 275); + rel15->BWPSize = NRRIV2BW(bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + rel15->BWPStart = NRRIV2PRBOFFSET(bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); rel15->SubcarrierSpacing = bwp_Common->genericParameters.subcarrierSpacing; for (int i = 0; i < rel15->num_dci_options; i++) { rel15->dci_length_options[i] = nr_dci_size(scc, mac->scg, def_dci_pdu_rel15+i, rel15->dci_format_options[i], NR_RNTI_C, rel15->BWPSize, bwp_id); @@ -157,9 +142,9 @@ void config_dci_pdu(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_dci_dl_pdu_rel15_t // we use the initial DL BWP sps = initialDownlinkBWP->genericParameters.cyclicPrefix == NULL ? 14 : 12; monitoringSymbolsWithinSlot = (ss->monitoringSymbolsWithinSlot->buf[0]<<(sps-8)) | (ss->monitoringSymbolsWithinSlot->buf[1]>>(16-sps)); - rel15->rnti = mac->ra_rnti; - rel15->BWPSize = NRRIV2BW(initialDownlinkBWP->genericParameters.locationAndBandwidth, 275); - rel15->BWPStart = NRRIV2PRBOFFSET(bwp_Common->genericParameters.locationAndBandwidth, 275); //NRRIV2PRBOFFSET(initialDownlinkBWP->genericParameters.locationAndBandwidth, 275); + rel15->rnti = ra->ra_rnti; + rel15->BWPSize = NRRIV2BW(initialDownlinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + rel15->BWPStart = NRRIV2PRBOFFSET(bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); //NRRIV2PRBOFFSET(initialDownlinkBWP->genericParameters.locationAndBandwidth, 275); rel15->SubcarrierSpacing = initialDownlinkBWP->genericParameters.subcarrierSpacing; rel15->dci_length_options[0] = nr_dci_size(scc, mac->scg, def_dci_pdu_rel15, rel15->dci_format_options[0], NR_RNTI_RA, rel15->BWPSize, bwp_id); break; @@ -224,13 +209,14 @@ void config_dci_pdu(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_dci_dl_pdu_rel15_t void ue_dci_configuration(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_request_t *dl_config, frame_t frame, int slot) { + RA_config_t *ra = &mac->ra; int ss_id; uint8_t bwp_id = 1, coreset_id = 1; //NR_ServingCellConfig_t *scd = mac->scg->spCellConfig->spCellConfigDedicated; NR_BWP_Downlink_t *bwp = mac->DLbwp[bwp_id - 1]; #ifdef DEBUG_DCI - LOG_D(MAC, "[DCI_CONFIG] ra_rnti %p (%x) crnti %p (%x) t_crnti %p (%x)\n", &mac->ra_rnti, mac->ra_rnti, &mac->crnti, mac->crnti, &mac->t_crnti, mac->t_crnti); + LOG_D(MAC, "[DCI_CONFIG] ra_rnti %p (%x) crnti %p (%x) t_crnti %p (%x)\n", &ra->ra_rnti, ra->ra_rnti, &mac->crnti, mac->crnti, &ra->t_crnti, ra->t_crnti); #endif // loop over all available SS for BWP ID 1, CORESET ID 1 @@ -257,7 +243,7 @@ void ue_dci_configuration(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_request_t *dl // check available SS IDs if (pdcch_ConfigCommon->choice.setup->ra_SearchSpace){ if (ss->searchSpaceId == *pdcch_ConfigCommon->choice.setup->ra_SearchSpace){ - switch(mac->ra_state){ + switch(ra->ra_state){ case WAIT_RAR: LOG_D(MAC, "[DCI_CONFIG] Configure monitoring of PDCCH candidates in Type1-PDCCH common random access search space\n"); rel15->num_dci_options = 1; @@ -266,7 +252,7 @@ void ue_dci_configuration(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_request_t *dl fill_dci_search_candidates(ss, rel15); break; case WAIT_CONTENTION_RESOLUTION: - rel15->rnti = mac->t_crnti; + LOG_E(MAC, "In %s: CB-RA not implemented yet. Should not have fallen in this case.\n", __FUNCTION__); break; default: break; @@ -331,8 +317,7 @@ void ue_dci_configuration(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_request_t *dl if (ss->searchSpaceType->choice.ue_Specific){ if(ss->searchSpaceType->choice.ue_Specific->dci_Formats == NR_SearchSpace__searchSpaceType__ue_Specific__dci_Formats_formats0_1_And_1_1){ // Monitors DCI 01 and 11 scrambled with C-RNTI, or CS-RNTI(s), or SP-CSI-RNTI - //if (get_softmodem_params()->phy_test == 1 && mac->crnti > 0) { - if (((mac->ra_state == RA_SUCCEEDED) || (get_softmodem_params()->phy_test == 1)) && mac->crnti > 0){ + if ((ra->ra_state == RA_SUCCEEDED || get_softmodem_params()->phy_test) && mac->crnti > 0) { LOG_D(MAC, "[DCI_CONFIG] Configure monitoring of PDCCH candidates in the user specific search space\n"); rel15->num_dci_options = 2; rel15->dci_format_options[0] = NR_DL_DCI_FORMAT_1_1; diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 50f922071d..89416266d5 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -45,7 +45,6 @@ #include "NR_PDCCH-ConfigCommon.h" /* MAC */ -#include "mac_defs.h" #include "NR_MAC_COMMON/nr_mac.h" #include "NR_MAC_UE/mac_proto.h" #include "NR_MAC_UE/mac_extern.h" @@ -53,895 +52,45 @@ #include "common/utils/nr/nr_common.h" /* PHY */ -#include "SCHED_NR_UE/defs.h" -#include "PHY/defs_nr_UE.h" #include "PHY/NR_TRANSPORT/nr_dci.h" - -/*Openair Packet Tracer */ -#include "UTIL/OPT/opt.h" -#include "OCG.h" #include "executables/softmodem-common.h" +#include "SCHED_NR_UE/defs.h" /* utils */ #include "assertions.h" - -/* Tools */ #include "asn1_conversions.h" -#include "SIMULATION/TOOLS/sim.h" // for taus - #include "common/utils/LOG/log.h" -#include "SIMULATION/TOOLS/sim.h" // for taus -#include "openair2/LAYER2/NR_MAC_COMMON/nr_mac.h" #include "common/utils/LOG/vcd_signal_dumper.h" -#include -#include - -// ================================================ -// SSB to RO mapping private defines and structures -// ================================================ - -#define MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PERIOD (16) // Maximum association period is 16 -#define MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD (16) // Max association pattern period is 160ms and minimum PRACH configuration period is 10ms -#define MAX_NB_ASSOCIATION_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD (16) // Max nb of association periods in an association pattern period of 160ms -#define MAX_NB_FRAME_IN_PRACH_CONF_PERIOD (16) // Max PRACH configuration period is 160ms and frame is 10ms -#define MAX_NB_SLOT_IN_FRAME (160) // Max number of slots in a frame (@ SCS 240kHz = 160) -#define MAX_NB_FRAME_IN_ASSOCIATION_PATTERN_PERIOD (16) // Maximum number of frames in the maximum association pattern period -#define MAX_NB_SSB (64) // Maximum number of possible SSB indexes -#define MAX_RO_PER_SSB (8) // Maximum number of consecutive ROs that can be mapped to an SSB according to the ssb_per_RACH config - -// Maximum number of ROs that can be mapped to an SSB in an association pattern -// This is to reserve enough elements in the SSBs list for each mapped ROs for a single SSB -// An arbitrary maximum number is chosen to be safe: maximum number of slots in an association pattern * maximum number of ROs in a slot -#define MAX_NB_RO_PER_SSB_IN_ASSOCIATION_PATTERN (MAX_TDM*MAX_FDM*MAX_NB_SLOT_IN_FRAME*MAX_NB_FRAME_IN_ASSOCIATION_PATTERN_PERIOD) - -// The PRACH Config period is a series of selected slots in one or multiple frames -typedef struct prach_conf_period { - prach_occasion_slot_t prach_occasion_slot_map[MAX_NB_FRAME_IN_PRACH_CONF_PERIOD][MAX_NB_SLOT_IN_FRAME]; - uint16_t nb_of_prach_occasion; // Total number of PRACH occasions in the PRACH Config period - uint8_t nb_of_frame; // Size of the PRACH Config period in number of 10ms frames - uint8_t nb_of_slot; // Nb of slots in each frame -} prach_conf_period_t; - -// The association period is a series of PRACH Config periods -typedef struct prach_association_period { - prach_conf_period_t *prach_conf_period_list[MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PERIOD]; - uint8_t nb_of_prach_conf_period; // Nb of PRACH configuration periods within the association period - uint8_t nb_of_frame; // Total number of frames included in the association period -} prach_association_period_t; - -// The association pattern is a series of Association periods -typedef struct prach_association_pattern { - prach_association_period_t prach_association_period_list[MAX_NB_ASSOCIATION_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD]; - prach_conf_period_t prach_conf_period_list[MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD]; - uint8_t nb_of_assoc_period; // Nb of association periods within the association pattern - uint8_t nb_of_prach_conf_period_in_max_period; // Nb of PRACH configuration periods within the maximum association pattern period (according to the size of the configured PRACH - uint8_t nb_of_frame; // Total number of frames included in the association pattern period (after mapping the SSBs and determining the real association pattern length) -} prach_association_pattern_t; - -// SSB details -typedef struct ssb_info { - boolean_t transmitted; // True if the SSB index is transmitted according to the SSB positions map configuration - prach_occasion_info_t *mapped_ro[MAX_NB_RO_PER_SSB_IN_ASSOCIATION_PATTERN]; // List of mapped RACH Occasions to this SSB index - uint16_t nb_mapped_ro; // Total number of mapped ROs to this SSB index -} ssb_info_t; - -// List of all the possible SSBs and their details -typedef struct ssb_list_info { - ssb_info_t tx_ssb[MAX_NB_SSB]; - uint8_t nb_tx_ssb; -} ssb_list_info_t; - -static prach_association_pattern_t prach_assoc_pattern; -static ssb_list_info_t ssb_list; - -// =============================================== -// =============================================== - //#define ENABLE_MAC_PAYLOAD_DEBUG 1 -#define DEBUG_EXTRACT_DCI 1 - -extern int bwp_id; -extern dci_pdu_rel15_t *def_dci_pdu_rel15; - -extern void mac_rlc_data_ind ( - const module_id_t module_idP, - const rnti_t rntiP, - const eNB_index_t eNB_index, - const frame_t frameP, - const eNB_flag_t enb_flagP, - const MBMS_flag_t MBMS_flagP, - const logical_chan_id_t channel_idP, - char *buffer_pP, - const tb_size_t tb_sizeP, - num_tb_t num_tbP, - crc_t *crcs_pP); - -// Build the list of all the valid RACH occasions in the maximum association pattern period according to the PRACH config -static void build_ro_list(NR_ServingCellConfigCommon_t *scc, uint8_t unpaired) { - - int x,y; // PRACH Configuration Index table variables used to compute the valid frame numbers - int y2; // PRACH Configuration Index table additional variable used to compute the valid frame numbers - uint8_t slot_shift_for_map; - uint8_t map_shift; - boolean_t even_slot_invalid; - int64_t s_map; - uint8_t prach_conf_start_symbol; // Starting symbol of the PRACH occasions in the PRACH slot - uint8_t N_t_slot; // Number of PRACH occasions in a 14-symbols PRACH slot - uint8_t N_dur; // Duration of a PRACH occasion (nb of symbols) - uint8_t frame; // Maximum is NB_FRAMES_IN_MAX_ASSOCIATION_PATTERN_PERIOD - uint8_t slot; // Maximum is the number of slots in a frame @ SCS 240kHz - uint16_t format = 0xffff; - uint8_t format2 = 0xff; - int nb_fdm; - - uint8_t config_index, mu; - uint32_t pointa; - int msg1_FDM; - - uint8_t prach_conf_period_idx; - uint8_t nb_of_frames_per_prach_conf_period; - uint8_t prach_conf_period_frame_idx; - int64_t *prach_config_info_p; - - NR_RACH_ConfigCommon_t *setup = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup; - NR_FrequencyInfoDL_t *frequencyInfoDL = scc->downlinkConfigCommon->frequencyInfoDL; - NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &setup->rach_ConfigGeneric; - - config_index = rach_ConfigGeneric->prach_ConfigurationIndex; - - if (setup->msg1_SubcarrierSpacing) - mu = *setup->msg1_SubcarrierSpacing; - else - mu = frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; - - pointa = frequencyInfoDL->absoluteFrequencyPointA; - msg1_FDM = rach_ConfigGeneric->msg1_FDM; - - switch (msg1_FDM){ - case 0: - case 1: - case 2: - case 3: - nb_fdm = 1 << msg1_FDM; - break; - default: - AssertFatal(1 == 0, "Unknown msg1_FDM from rach_ConfigGeneric %d\n", msg1_FDM); - } - - // Create the PRACH occasions map - // ============================== - // WIP: For now assume no rejected PRACH occasions because of conflict with SSB or TDD_UL_DL_ConfigurationCommon schedule - - // Identify the proper PRACH Configuration Index table according to the operating frequency - LOG_D(MAC,"Pointa %u, mu = %u, PRACH config index = %u, unpaired = %u\n", pointa, mu, config_index, unpaired); - - prach_config_info_p = get_prach_config_info(pointa, config_index, unpaired); - - if (pointa > 2016666) { //FR2 - - x = prach_config_info_p[2]; - y = prach_config_info_p[3]; - y2 = prach_config_info_p[4]; - - s_map = prach_config_info_p[5]; - - prach_conf_start_symbol = prach_config_info_p[6]; - N_t_slot = prach_config_info_p[8]; - N_dur = prach_config_info_p[9]; - if (prach_config_info_p[1] != -1) - format2 = (uint8_t) prach_config_info_p[1]; - format = ((uint8_t) prach_config_info_p[0]) | (format2<<8); - - slot_shift_for_map = mu-2; - if ( (mu == 3) && (prach_config_info_p[7] == 1) ) - even_slot_invalid = true; - else - even_slot_invalid = false; - } - else { // FR1 - x = prach_config_info_p[2]; - y = prach_config_info_p[3]; - y2 = y; - - s_map = prach_config_info_p[4]; - - prach_conf_start_symbol = prach_config_info_p[5]; - N_t_slot = prach_config_info_p[7]; - N_dur = prach_config_info_p[8]; - if (prach_config_info_p[1] != -1) - format2 = (uint8_t) prach_config_info_p[1]; - format = ((uint8_t) prach_config_info_p[0]) | (format2<<8); - - slot_shift_for_map = mu; - if ( (mu == 1) && (prach_config_info_p[6] <= 1) ) - // no prach in even slots @ 30kHz for 1 prach per subframe - even_slot_invalid = true; - else - even_slot_invalid = false; - } // FR2 / FR1 - - prach_assoc_pattern.nb_of_prach_conf_period_in_max_period = MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD / x; - nb_of_frames_per_prach_conf_period = x; - - LOG_D(MAC,"nb_of_prach_conf_period_in_max_period %d\n", prach_assoc_pattern.nb_of_prach_conf_period_in_max_period); - - // Fill in the PRACH occasions table for every slot in every frame in every PRACH configuration periods in the maximum association pattern period - // ---------------------------------------------------------------------------------------------------------------------------------------------- - // ---------------------------------------------------------------------------------------------------------------------------------------------- - // For every PRACH configuration periods - // ------------------------------------- - for (prach_conf_period_idx=0; prach_conf_period_idx> slot_shift_for_map; // in PRACH configuration index table slots are numbered wrt 60kHz - if ( (s_map>>map_shift)&0x01 ) { - // Valid slot - - // Additionally, for 30kHz/120kHz, we must check for the n_RA_Slot param also - if ( even_slot_invalid && (slot%2 == 0) ) - continue; // no prach in even slots @ 30kHz/120kHz for 1 prach per 60khz slot/subframe - - // We're good: valid frame and valid slot - // Compute all the PRACH occasions in the slot - - uint8_t n_prach_occ_in_time; - uint8_t n_prach_occ_in_freq; - - prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].prach_occasion_slot_map[prach_conf_period_frame_idx][slot].nb_of_prach_occasion_in_time = N_t_slot; - prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].prach_occasion_slot_map[prach_conf_period_frame_idx][slot].nb_of_prach_occasion_in_freq = nb_fdm; - - for (n_prach_occ_in_time=0; n_prach_occ_in_timestart_symbol = start_symbol; - prach_occasion_p->fdm = n_prach_occ_in_freq; - prach_occasion_p->frame = frame; - prach_occasion_p->slot = slot; - prach_occasion_p->format = format; - prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].nb_of_prach_occasion++; - - LOG_D(MAC,"Adding a PRACH occasion: frame %u, slot-symbol %d-%d, occ_in_time-occ_in-freq %d-%d, nb ROs in conf period %d, for this slot: RO# in time %d, RO# in freq %d\n", - frame, slot, start_symbol, n_prach_occ_in_time, n_prach_occ_in_freq, prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].nb_of_prach_occasion, - prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].prach_occasion_slot_map[prach_conf_period_frame_idx][slot].nb_of_prach_occasion_in_time, - prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].prach_occasion_slot_map[prach_conf_period_frame_idx][slot].nb_of_prach_occasion_in_freq); - } // For every freq in the slot - } // For every time occasions in the slot - } // Valid slot? - } // For every slots in a frame - } // Valid frame? - } // For every frames in a prach configuration period - } // For every prach configuration periods in the maximum association pattern period (160ms) -} - -// Build the list of all the valid/transmitted SSBs according to the config -static void build_ssb_list(NR_ServingCellConfigCommon_t *scc) { - - // Create the list of transmitted SSBs - // =================================== - BIT_STRING_t *ssb_bitmap; - uint64_t ssb_positionsInBurst; - uint8_t ssb_idx = 0; - - switch (scc->ssb_PositionsInBurst->present) { - case NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_shortBitmap: - ssb_bitmap = &scc->ssb_PositionsInBurst->choice.shortBitmap; - - ssb_positionsInBurst = BIT_STRING_to_uint8(ssb_bitmap); - LOG_D(MAC,"SSB config: SSB_positions_in_burst 0x%lx\n", ssb_positionsInBurst); - - for (uint8_t bit_nb=3; bit_nb<=3; bit_nb--) { - // If SSB is transmitted - if ((ssb_positionsInBurst>>bit_nb) & 0x01) { - ssb_list.nb_tx_ssb++; - ssb_list.tx_ssb[ssb_idx].transmitted = true; - LOG_D(MAC,"SSB idx %d transmitted\n", ssb_idx); - } - ssb_idx++; - } - break; - case NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_mediumBitmap: - ssb_bitmap = &scc->ssb_PositionsInBurst->choice.mediumBitmap; - - ssb_positionsInBurst = BIT_STRING_to_uint8(ssb_bitmap); - LOG_D(MAC,"SSB config: SSB_positions_in_burst 0x%lx\n", ssb_positionsInBurst); - - for (uint8_t bit_nb=7; bit_nb<=7; bit_nb--) { - // If SSB is transmitted - if ((ssb_positionsInBurst>>bit_nb) & 0x01) { - ssb_list.nb_tx_ssb++; - ssb_list.tx_ssb[ssb_idx].transmitted = true; - LOG_D(MAC,"SSB idx %d transmitted\n", ssb_idx); - } - ssb_idx++; - } - break; - case NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_longBitmap: - ssb_bitmap = &scc->ssb_PositionsInBurst->choice.longBitmap; - - ssb_positionsInBurst = BIT_STRING_to_uint64(ssb_bitmap); - LOG_D(MAC,"SSB config: SSB_positions_in_burst 0x%lx\n", ssb_positionsInBurst); - - for (uint8_t bit_nb=63; bit_nb<=63; bit_nb--) { - // If SSB is transmitted - if ((ssb_positionsInBurst>>bit_nb) & 0x01) { - ssb_list.nb_tx_ssb++; - ssb_list.tx_ssb[ssb_idx].transmitted = true; - LOG_D(MAC,"SSB idx %d transmitted\n", ssb_idx); - } - ssb_idx++; - } - break; - default: - AssertFatal(false,"ssb_PositionsInBurst not present\n"); - break; - } -} - -// Map the transmitted SSBs to the ROs and create the association pattern according to the config -static void map_ssb_to_ro(NR_ServingCellConfigCommon_t *scc) { - - // Map SSBs to PRACH occasions - // =========================== - // WIP: Assumption: No PRACH occasion is rejected because of a conflict with SSBs or TDD_UL_DL_ConfigurationCommon schedule - NR_RACH_ConfigCommon_t *setup = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup; - NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR ssb_perRACH_config = setup->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present; - - boolean_t multiple_ssb_per_ro; // true if more than one or exactly one SSB per RACH occasion, false if more than one RO per SSB - uint8_t ssb_rach_ratio; // Nb of SSBs per RACH or RACHs per SSB - uint16_t required_nb_of_prach_occasion; // Nb of RACH occasions required to map all the SSBs - uint8_t required_nb_of_prach_conf_period; // Nb of PRACH configuration periods required to map all the SSBs - - // Determine the SSB to RACH mapping ratio - // ======================================= - switch (ssb_perRACH_config){ - case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneEighth: - multiple_ssb_per_ro = false; - ssb_rach_ratio = 8; - break; - case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneFourth: - multiple_ssb_per_ro = false; - ssb_rach_ratio = 4; - break; - case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneHalf: - multiple_ssb_per_ro = false; - ssb_rach_ratio = 2; - break; - case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_one: - multiple_ssb_per_ro = true; - ssb_rach_ratio = 1; - break; - case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_two: - multiple_ssb_per_ro = true; - ssb_rach_ratio = 2; - break; - case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_four: - multiple_ssb_per_ro = true; - ssb_rach_ratio = 4; - break; - case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_eight: - multiple_ssb_per_ro = true; - ssb_rach_ratio = 8; - break; - case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_sixteen: - multiple_ssb_per_ro = true; - ssb_rach_ratio = 16; - break; - default: - AssertFatal(1 == 0, "Unsupported ssb_perRACH_config %d\n", ssb_perRACH_config); - break; - } - LOG_D(MAC,"SSB rach ratio %d, Multiple SSB per RO %d\n", ssb_rach_ratio, multiple_ssb_per_ro); - - // Evaluate the number of PRACH configuration periods required to map all the SSBs and set the association period - // ============================================================================================================== - // WIP: Assumption for now is that all the PRACH configuration periods within a maximum association pattern period have the same number of PRACH occasions - // (No PRACH occasions are conflicting with SSBs nor TDD_UL_DL_ConfigurationCommon schedule) - // There is only one possible association period which can contain up to 16 PRACH configuration periods - LOG_D(MAC,"Evaluate the number of PRACH configuration periods required to map all the SSBs and set the association period\n"); - if (true == multiple_ssb_per_ro) { - required_nb_of_prach_occasion = ((ssb_list.nb_tx_ssb-1) + ssb_rach_ratio) / ssb_rach_ratio; - } - else { - required_nb_of_prach_occasion = ssb_list.nb_tx_ssb * ssb_rach_ratio; - } - - required_nb_of_prach_conf_period = ((required_nb_of_prach_occasion-1) + prach_assoc_pattern.prach_conf_period_list[0].nb_of_prach_occasion) / prach_assoc_pattern.prach_conf_period_list[0].nb_of_prach_occasion; - - if (required_nb_of_prach_conf_period == 1) { - prach_assoc_pattern.prach_association_period_list[0].nb_of_prach_conf_period = 1; - } - else if (required_nb_of_prach_conf_period == 2) { - prach_assoc_pattern.prach_association_period_list[0].nb_of_prach_conf_period = 2; - } - else if (required_nb_of_prach_conf_period <= 4) { - prach_assoc_pattern.prach_association_period_list[0].nb_of_prach_conf_period = 4; - } - else if (required_nb_of_prach_conf_period <= 8) { - prach_assoc_pattern.prach_association_period_list[0].nb_of_prach_conf_period = 8; - } - else if (required_nb_of_prach_conf_period <= 16) { - prach_assoc_pattern.prach_association_period_list[0].nb_of_prach_conf_period = 16; - } - else { - AssertFatal(1 == 0, "Invalid number of PRACH config periods within an association period %d\n", required_nb_of_prach_conf_period); - } - - prach_assoc_pattern.nb_of_assoc_period = 1; // WIP: only one possible association period - prach_assoc_pattern.prach_association_period_list[0].nb_of_frame = prach_assoc_pattern.prach_association_period_list[0].nb_of_prach_conf_period * prach_assoc_pattern.prach_conf_period_list[0].nb_of_frame; - prach_assoc_pattern.nb_of_frame = prach_assoc_pattern.prach_association_period_list[0].nb_of_frame; - - LOG_D(MAC,"Assoc period %d, Nb of frames in assoc period %d\n", - prach_assoc_pattern.prach_association_period_list[0].nb_of_prach_conf_period, - prach_assoc_pattern.prach_association_period_list[0].nb_of_frame); - - // Proceed to the SSB to RO mapping - // ================================ - uint8_t association_period_idx; // Association period index within the association pattern - uint8_t ssb_idx = 0; - uint8_t prach_configuration_period_idx; // PRACH Configuration period index within the association pattern - prach_conf_period_t *prach_conf_period_p; - - // Map all the association periods within the association pattern period - LOG_D(MAC,"Proceed to the SSB to RO mapping\n"); - for (association_period_idx=0; association_period_idxnb_of_frame; frame++) { - for (slot=0; slotnb_of_slot; slot++) { - for (ro_in_time=0; ro_in_timeprach_occasion_slot_map[frame][slot].nb_of_prach_occasion_in_time; ro_in_time++) { - for (ro_in_freq=0; ro_in_freqprach_occasion_slot_map[frame][slot].nb_of_prach_occasion_in_freq; ro_in_freq++) { - prach_occasion_info_t *ro_p = &prach_conf_period_p->prach_occasion_slot_map[frame][slot].prach_occasion[ro_in_time][ro_in_freq]; - - // Go through the list of transmitted SSBs and map the required amount of SSBs to this RO - // WIP: For the moment, only map each SSB idx once per association period if configuration is multiple SSBs per RO - // this is true if no PRACH occasions are conflicting with SSBs nor TDD_UL_DL_ConfigurationCommon schedule - for (; ssb_idxmapped_ssb_idx[ro_p->nb_mapped_ssb] = ssb_idx; - ro_p->nb_mapped_ssb++; - ssb_list.tx_ssb[ssb_idx].mapped_ro[ssb_list.tx_ssb[ssb_idx].nb_mapped_ro] = ro_p; - ssb_list.tx_ssb[ssb_idx].nb_mapped_ro++; - AssertFatal(MAX_NB_RO_PER_SSB_IN_ASSOCIATION_PATTERN > ssb_list.tx_ssb[ssb_idx].nb_mapped_ro,"Too many mapped ROs (%d) to a single SSB\n", ssb_list.tx_ssb[ssb_idx].nb_mapped_ro); - - LOG_D(MAC,"Mapped ssb_idx %u to RO slot-symbol %u-%u, %u-%u-%u/%u\n", ssb_idx, ro_p->slot, ro_p->start_symbol, slot, ro_in_time, ro_in_freq, prach_conf_period_p->prach_occasion_slot_map[frame][slot].nb_of_prach_occasion_in_freq); - LOG_D(MAC,"Nb mapped ROs for this ssb idx: in the association period only %u\n", ssb_list.tx_ssb[ssb_idx].nb_mapped_ro); - - // If all the required SSBs are mapped to this RO, exit the loop of SSBs - if (ro_p->nb_mapped_ssb == ssb_rach_ratio) { - ssb_idx++; - break; - } - } // if ssb_idx is transmitted - } // for ssb_idx - - // Exit the loop of ROs if there is no more SSB to map - if (MAX_NB_SSB == ssb_idx) break; - } // for ro_in_freq - - // Exit the loop of ROs if there is no more SSB to map - if (MAX_NB_SSB == ssb_idx) break; - } // for ro_in_time - - // Exit the loop of slots if there is no more SSB to map - if (MAX_NB_SSB == ssb_idx) break; - } // for slot - - // Exit the loop frames if there is no more SSB to map - if (MAX_NB_SSB == ssb_idx) break; - } // for frame - - // Exit the loop of PRACH configurations if there is no more SSB to map - if (MAX_NB_SSB == ssb_idx) break; - } // for n_prach_conf - - // WIP: note that there is no re-mapping of the SSBs within the association period since there is no invalid ROs in the PRACH config periods that would create this situation - - } // if multiple_ssbs_per_ro - - else { - // -------------------- - // -------------------- - // Multiple ROs per SSB - // -------------------- - // -------------------- - - n_prach_conf = 0; - - // Go through the list of transmitted SSBs - for (ssb_idx=0; ssb_idxnb_of_frame; frame++) { - for (; slotnb_of_slot; slot++) { - for (; ro_in_timeprach_occasion_slot_map[frame][slot].nb_of_prach_occasion_in_time; ro_in_time++) { - for (; ro_in_freqprach_occasion_slot_map[frame][slot].nb_of_prach_occasion_in_freq; ro_in_freq++) { - prach_occasion_info_t *ro_p = &prach_conf_period_p->prach_occasion_slot_map[frame][slot].prach_occasion[ro_in_time][ro_in_freq]; - - ro_p->mapped_ssb_idx[0] = ssb_idx; - ro_p->nb_mapped_ssb = 1; - ssb_list.tx_ssb[ssb_idx].mapped_ro[ssb_list.tx_ssb[ssb_idx].nb_mapped_ro] = ro_p; - ssb_list.tx_ssb[ssb_idx].nb_mapped_ro++; - AssertFatal(MAX_NB_RO_PER_SSB_IN_ASSOCIATION_PATTERN > ssb_list.tx_ssb[ssb_idx].nb_mapped_ro,"Too many mapped ROs (%d) to a single SSB\n", ssb_list.tx_ssb[ssb_idx].nb_mapped_ro); - nb_mapped_ro_in_association_period++; - - LOG_D(MAC,"Mapped ssb_idx %u to RO slot-symbol %u-%u, %u-%u-%u/%u\n", ssb_idx, ro_p->slot, ro_p->start_symbol, slot, ro_in_time, ro_in_freq, prach_conf_period_p->prach_occasion_slot_map[frame][slot].nb_of_prach_occasion_in_freq); - LOG_D(MAC,"Nb mapped ROs for this ssb idx: in the association period only %u / total %u\n", ssb_list.tx_ssb[ssb_idx].nb_mapped_ro, nb_mapped_ro_in_association_period); - - // Exit the loop if this SSB has been mapped to all the required ROs - // WIP: Assuming that ssb_rach_ratio equals the maximum nb of times a given ssb_idx is mapped within an association period: - // this is true if no PRACH occasions are conflicting with SSBs nor TDD_UL_DL_ConfigurationCommon schedule - if (nb_mapped_ro_in_association_period == ssb_rach_ratio) { - ro_in_freq++; - break; - } - } // for ro_in_freq - - // Exit the loop if this SSB has been mapped to all the required ROs - if (nb_mapped_ro_in_association_period == ssb_rach_ratio) { - break; - } - else ro_in_freq = 0; // else go to the next time symbol in that slot and reset the freq index - } // for ro_in_time - - // Exit the loop if this SSB has been mapped to all the required ROs - if (nb_mapped_ro_in_association_period == ssb_rach_ratio) { - break; - } - else ro_in_time = 0; // else go to the next slot in that PRACH config period and reset the symbol index - } // for slot - - // Exit the loop if this SSB has been mapped to all the required ROs - if (nb_mapped_ro_in_association_period == ssb_rach_ratio) { - break; - } - else slot = 0; // else go to the next frame in that PRACH config period and reset the slot index - } // for frame - - // Exit the loop if this SSB has been mapped to all the required ROs - if (nb_mapped_ro_in_association_period == ssb_rach_ratio) { - break; - } - else frame = 0; // else go to the next PRACH config period in that association period and reset the frame index - } // for n_prach_conf - - } // if ssb_idx is transmitted - } // for ssb_idx - } // else if multiple_ssbs_per_ro - - } // for association_period_index -} - -// Returns a RACH occasion if any matches the SSB idx, the frame and the slot -static int get_nr_prach_info_from_ssb_index(uint8_t ssb_idx, - int frame, - int slot, - prach_occasion_info_t **prach_occasion_info_pp) { - - ssb_info_t *ssb_info_p; - prach_occasion_slot_t *prach_occasion_slot_p = NULL; - - *prach_occasion_info_pp = NULL; - - // Search for a matching RO slot in the SSB_to_RO map - // A valid RO slot will match: - // - ssb_idx mapped to one of the ROs in that RO slot - // - exact slot number - // - frame offset - ssb_info_p = &ssb_list.tx_ssb[ssb_idx]; - for (uint8_t n_mapped_ro=0; n_mapped_ronb_mapped_ro; n_mapped_ro++) { - if ((slot == ssb_info_p->mapped_ro[n_mapped_ro]->slot) && - (ssb_info_p->mapped_ro[n_mapped_ro]->frame == (frame % prach_assoc_pattern.nb_of_frame))) { - - uint8_t prach_config_period_nb = ssb_info_p->mapped_ro[n_mapped_ro]->frame / prach_assoc_pattern.prach_conf_period_list[0].nb_of_frame; - uint8_t frame_nb_in_prach_config_period = ssb_info_p->mapped_ro[n_mapped_ro]->frame % prach_assoc_pattern.prach_conf_period_list[0].nb_of_frame; - prach_occasion_slot_p = &prach_assoc_pattern.prach_conf_period_list[prach_config_period_nb].prach_occasion_slot_map[frame_nb_in_prach_config_period][slot]; - } - } - - // If there is a matching RO slot in the SSB_to_RO map - if (NULL != prach_occasion_slot_p) - { - // A random RO mapped to the SSB index should be selected in the slot - - // First count the number of times the SSB index is found in that RO - uint8_t nb_mapped_ssb = 0; - - for (int ro_in_time=0; ro_in_time < prach_occasion_slot_p->nb_of_prach_occasion_in_time; ro_in_time++) { - for (int ro_in_freq=0; ro_in_freq < prach_occasion_slot_p->nb_of_prach_occasion_in_freq; ro_in_freq++) { - prach_occasion_info_t *prach_occasion_info_p = &prach_occasion_slot_p->prach_occasion[ro_in_time][ro_in_freq]; - - for (uint8_t ssb_nb=0; ssb_nbnb_mapped_ssb; ssb_nb++) { - if (prach_occasion_info_p->mapped_ssb_idx[ssb_nb] == ssb_idx) { - nb_mapped_ssb++; - } - } - } +//#define DEBUG_EXTRACT_DCI +//#define DEBUG_RAR + +int get_rnti_type(NR_UE_MAC_INST_t *mac, uint16_t rnti){ + + RA_config_t *ra = &mac->ra; + int rnti_type; + + if (rnti == ra->ra_rnti) { + rnti_type = NR_RNTI_RA; + } else if (rnti == mac->crnti) { + rnti_type = NR_RNTI_C; + } else if (rnti == ra->t_crnti) { + rnti_type = NR_RNTI_TC; + } else if (rnti == 0xFFFE) { + rnti_type = NR_RNTI_P; + } else if (rnti == 0xFFFF) { + rnti_type = NR_RNTI_SI; + } else { + AssertFatal(1 == 0, "In %s: Not identified/handled rnti %d \n", __FUNCTION__, rnti); } - // Choose a random SSB nb - uint8_t random_ssb_nb = 0; + LOG_D(MAC, "In %s: returning rnti_type %s \n", __FUNCTION__, rnti_types[rnti_type]); - random_ssb_nb = ((taus()) % nb_mapped_ssb); + return rnti_type; - // Select the RO according to the chosen random SSB nb - nb_mapped_ssb=0; - for (int ro_in_time=0; ro_in_time < prach_occasion_slot_p->nb_of_prach_occasion_in_time; ro_in_time++) { - for (int ro_in_freq=0; ro_in_freq < prach_occasion_slot_p->nb_of_prach_occasion_in_freq; ro_in_freq++) { - prach_occasion_info_t *prach_occasion_info_p = &prach_occasion_slot_p->prach_occasion[ro_in_time][ro_in_freq]; - - for (uint8_t ssb_nb=0; ssb_nbnb_mapped_ssb; ssb_nb++) { - if (prach_occasion_info_p->mapped_ssb_idx[ssb_nb] == ssb_idx) { - if (nb_mapped_ssb == random_ssb_nb) { - *prach_occasion_info_pp = prach_occasion_info_p; - return 1; - } - else { - nb_mapped_ssb++; - } - } - } - } - } - } - - return 0; } -// Build the SSB to RO mapping upon RRC configuration update -void build_ssb_to_ro_map(NR_ServingCellConfigCommon_t *scc, uint8_t unpaired){ - - // Clear all the lists and maps - memset(&prach_assoc_pattern, 0, sizeof(prach_association_pattern_t)); - memset(&ssb_list, 0, sizeof(ssb_list_info_t)); - - // Build the list of all the valid RACH occasions in the maximum association pattern period according to the PRACH config - LOG_D(MAC,"Build RO list\n"); - build_ro_list(scc, unpaired); - - // Build the list of all the valid/transmitted SSBs according to the config - LOG_D(MAC,"Build SSB list\n"); - build_ssb_list(scc); - - // Map the transmitted SSBs to the ROs and create the association pattern according to the config - LOG_D(MAC,"Map SSB to RO\n"); - map_ssb_to_ro(scc); - LOG_D(MAC,"Map SSB to RO done\n"); -} - -void fill_scheduled_response(nr_scheduled_response_t *scheduled_response, - fapi_nr_dl_config_request_t *dl_config, - fapi_nr_ul_config_request_t *ul_config, - fapi_nr_tx_request_t *tx_request, - module_id_t mod_id, - int cc_id, - frame_t frame, - int slot, - int thread_id){ - - scheduled_response->dl_config = dl_config; - scheduled_response->ul_config = ul_config; - scheduled_response->tx_request = tx_request; - scheduled_response->module_id = mod_id; - scheduled_response->CC_id = cc_id; - scheduled_response->frame = frame; - scheduled_response->slot = slot; - scheduled_response->thread_id = thread_id; -} - -uint8_t table_9_2_2_1[16][8]={ - {0,12,2, 0, 0,3,0,0}, - {0,12,2, 0, 0,4,8,0}, - {0,12,2, 3, 0,4,8,0}, - {1,10,4, 0, 0,6,0,0}, - {1,10,4, 0, 0,3,6,9}, - {1,10,4, 2, 0,3,6,9}, - {1,10,4, 4, 0,3,6,9}, - {1,4, 10,0, 0,6,0,0}, - {1,4, 10,0, 0,3,6,9}, - {1,4, 10,2, 0,3,6,9}, - {1,4, 10,4, 0,3,6,9}, - {1,0, 14,0, 0,6,0,0}, - {1,0, 14,0, 0,3,6,9}, - {1,0, 14,2, 0,3,6,9}, - {1,0, 14,4, 0,3,6,9}, - {1,0, 14,26,0,3,0,0} -}; - -#if 0 // Not in use. In case of use, please adapt the schedule_response (no longer in MAC) -int8_t nr_ue_process_dlsch(module_id_t module_id, - int cc_id, - uint8_t gNB_index, - fapi_nr_dci_indication_t *dci_ind, - void *pduP, - uint32_t pdu_len) -{ - NR_UE_MAC_INST_t *mac = get_mac_inst(module_id); - fapi_nr_ul_config_request_t *ul_config = &mac->ul_config_request; - //fapi_nr_dl_config_request_t *dl_config = &mac->dl_config_request; - nr_phy_config_t *phy_config = &mac->phy_config; - - //ul_config->ul_config_list[ul_config->number_pdus].pusch_config_pdu.rnti = rnti; - // First we need to verify if DCI ind contains a ul-sch to be perfomred. If it does, we will handle a PUSCH in the UL_CONFIG_REQ. - ul_config->ul_config_list[ul_config->number_pdus].pdu_type = FAPI_NR_UL_CONFIG_TYPE_PUCCH; - for (int i=0; i<10; i++) { - if(dci_ind!=NULL){ - if (dci_ind->dci_list[i].dci_format < 2) ul_config->ul_config_list[ul_config->number_pdus].pdu_type = FAPI_NR_UL_CONFIG_TYPE_PUSCH; - } - } - if (ul_config->ul_config_list[ul_config->number_pdus].pdu_type == FAPI_NR_UL_CONFIG_TYPE_PUSCH) { - // fill in the elements in config request inside P5 message - //ul_config->ul_config_list[ul_config->number_pdus].pusch_config_pdu.bandwidth_part_ind = 0; //FIXME - ul_config->ul_config_list[ul_config->number_pdus].pusch_config_pdu.rb_size = 0; - ul_config->ul_config_list[ul_config->number_pdus].pusch_config_pdu.rb_start = 0; - ul_config->ul_config_list[ul_config->number_pdus].pusch_config_pdu.nr_of_symbols = 0; - ul_config->ul_config_list[ul_config->number_pdus].pusch_config_pdu.start_symbol_index = 0; - ul_config->ul_config_list[ul_config->number_pdus].pusch_config_pdu.frequency_hopping = 0; - ul_config->ul_config_list[ul_config->number_pdus].pusch_config_pdu.mcs_index = 0; - ul_config->ul_config_list[ul_config->number_pdus].pusch_config_pdu.pusch_data.new_data_indicator = 0; - ul_config->ul_config_list[ul_config->number_pdus].pusch_config_pdu.pusch_data.rv_index = 0; - ul_config->ul_config_list[ul_config->number_pdus].pusch_config_pdu.pusch_data.harq_process_id = 0; - ul_config->ul_config_list[ul_config->number_pdus].pusch_config_pdu.absolute_delta_PUSCH = 0; - ul_config->ul_config_list[ul_config->number_pdus].pusch_config_pdu.nrOfLayers = 0; - ul_config->ul_config_list[ul_config->number_pdus].pusch_config_pdu.transform_precoding = 0; - ul_config->ul_config_list[ul_config->number_pdus].pusch_config_pdu.num_dmrs_cdm_grps_no_data = 0; - ul_config->ul_config_list[ul_config->number_pdus].pusch_config_pdu.dmrs_ports = 0; - ul_config->ul_config_list[ul_config->number_pdus].pusch_config_pdu.dmrs_config_type = 0; - //ul_config->ul_config_list[ul_config->number_pdus].pusch_config_pdu.n_front_load_symb = 0; //FIXME - //ul_config->ul_config_list[ul_config->number_pdus].pusch_config_pdu.srs_config = 0; //FIXME - //ul_config->ul_config_list[ul_config->number_pdus].pusch_config_pdu.csi_reportTriggerSize = 0; //FIXME - //ul_config->ul_config_list[ul_config->number_pdus].pusch_config_pdu.maxCodeBlockGroupsPerTransportBlock = 0; //FIXME - //ul_config->ul_config_list[ul_config->number_pdus].pusch_config_pdu.ptrs_dmrs_association_port = 0; FIXME - //ul_config->ul_config_list[ul_config->number_pdus].pusch_config_pdu.beta_offset_ind = 0; //FIXME - } else { // If DCI ind is not format 0_0 or 0_1, we will handle a PUCCH in the UL_CONFIG_REQ - ul_config->ul_config_list[ul_config->number_pdus].pdu_type = FAPI_NR_UL_CONFIG_TYPE_PUCCH; - // If we handle PUCCH common - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.format = table_9_2_2_1[phy_config->config_req.ul_bwp_common.pucch_config_common.pucch_resource_common][0]; /* format 0 1 2 3 4 */ - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.initialCyclicShift = table_9_2_2_1[phy_config->config_req.ul_bwp_common.pucch_config_common.pucch_resource_common][4]; /* x x */ - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.nrofSymbols = table_9_2_2_1[phy_config->config_req.ul_bwp_common.pucch_config_common.pucch_resource_common][2]; /* x x x x x */ - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.startingSymbolIndex = table_9_2_2_1[phy_config->config_req.ul_bwp_common.pucch_config_common.pucch_resource_common][1]; /* x x x x x */ - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.timeDomainOCC = 0; /* x */ - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.nrofPRBs = 0; /* x x */ - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.startingPRB = table_9_2_2_1[phy_config->config_req.ul_bwp_common.pucch_config_common.pucch_resource_common][3]; /* maxNrofPhysicalResourceBlocks = 275 */ - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.occ_length = 0; /* x */ - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.occ_Index = 0; /* x */ - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.intraSlotFrequencyHopping = 0; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.secondHopPRB = 0; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.interslotFrequencyHopping = 0; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.additionalDMRS = 0; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.maxCodeRate = 0; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.nrofSlots = 0; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.pi2PBSK = 0; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.simultaneousHARQ_ACK_CSI = 0; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.pucch_GroupHopping = phy_config->config_req.ul_bwp_common.pucch_config_common.pucch_group_hopping; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.hoppingId = phy_config->config_req.ul_bwp_common.pucch_config_common.hopping_id; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.p0_nominal = phy_config->config_req.ul_bwp_common.pucch_config_common.p0_nominal; - for (int i=0;iul_config_list[ul_config->number_pdus].pucch_config_pdu.deltaF_PUCCH_f[i] = 0; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.p0_PUCCH_Id = 0; /* INTEGER (1..8) */ - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.p0_PUCCH_Value = 0; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.twoPUCCH_PC_AdjustmentStates = 0; - // If we handle PUCCH dedicated - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.format = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.multi_csi_pucch_resources[0].format; /* format 0 1 2 3 4 */ - switch (ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.format){ - case pucch_format1_nr: - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.interslotFrequencyHopping = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.format1.inter_slot_frequency_hopping; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.additionalDMRS = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.format1.additional_dmrs; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.maxCodeRate = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.format1.max_code_rate; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.nrofSlots = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.format1.number_of_slots; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.pi2PBSK = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.format1.pi2bpsk; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.simultaneousHARQ_ACK_CSI = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.format1.simultaneous_harq_ack_csi; - break; - case pucch_format2_nr: - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.interslotFrequencyHopping = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.format2.inter_slot_frequency_hopping; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.additionalDMRS = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.format2.additional_dmrs; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.maxCodeRate = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.format2.max_code_rate; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.nrofSlots = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.format2.number_of_slots; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.pi2PBSK = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.format2.pi2bpsk; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.simultaneousHARQ_ACK_CSI = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.format2.simultaneous_harq_ack_csi; - break; - case pucch_format3_nr: - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.interslotFrequencyHopping = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.format3.inter_slot_frequency_hopping; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.additionalDMRS = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.format3.additional_dmrs; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.maxCodeRate = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.format3.max_code_rate; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.nrofSlots = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.format3.number_of_slots; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.pi2PBSK = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.format3.pi2bpsk; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.simultaneousHARQ_ACK_CSI = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.format3.simultaneous_harq_ack_csi; - break; - case pucch_format4_nr: - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.interslotFrequencyHopping = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.format4.inter_slot_frequency_hopping; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.additionalDMRS = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.format4.additional_dmrs; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.maxCodeRate = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.format4.max_code_rate; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.nrofSlots = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.format4.number_of_slots; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.pi2PBSK = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.format4.pi2bpsk; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.simultaneousHARQ_ACK_CSI = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.format4.simultaneous_harq_ack_csi; - break; - default: - break; - } - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.initialCyclicShift = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.multi_csi_pucch_resources[0].initial_cyclic_shift; /* x x */ - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.nrofSymbols = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.multi_csi_pucch_resources[0].number_of_symbols; /* x x x x x */ - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.startingSymbolIndex = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.multi_csi_pucch_resources[0].starting_symbol_index; /* x x x x x */ - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.timeDomainOCC = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.multi_csi_pucch_resources[0].time_domain_occ; /* x */ - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.nrofPRBs = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.multi_csi_pucch_resources[0].number_of_prbs; /* x x */ - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.startingPRB = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.multi_csi_pucch_resources[0].starting_prb; /* maxNrofPhysicalResourceBlocks = 275 */ - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.occ_length = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.multi_csi_pucch_resources[0].occ_length; /* x */ - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.occ_Index = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.multi_csi_pucch_resources[0].occ_index; /* x */ - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.intraSlotFrequencyHopping = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.multi_csi_pucch_resources[0].intra_slot_frequency_hopping; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.secondHopPRB = phy_config->config_req.ul_bwp_dedicated.pucch_config_dedicated.multi_csi_pucch_resources[0].second_hop_prb; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.pucch_GroupHopping = phy_config->config_req.ul_bwp_common.pucch_config_common.pucch_group_hopping; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.hoppingId = phy_config->config_req.ul_bwp_common.pucch_config_common.hopping_id; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.p0_nominal = phy_config->config_req.ul_bwp_common.pucch_config_common.p0_nominal; - for (int i=0;iul_config_list[ul_config->number_pdus].pucch_config_pdu.deltaF_PUCCH_f[i] = 0; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.p0_PUCCH_Id = 0; /* INTEGER (1..8) */ - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.p0_PUCCH_Value = 0; - ul_config->ul_config_list[ul_config->number_pdus].pucch_config_pdu.twoPUCCH_PC_AdjustmentStates = 0; - - } - if(mac->if_module != NULL && mac->if_module->scheduled_response != NULL){ - mac->if_module->scheduled_response(&mac->scheduled_response); - } - return 0; -} -#endif int8_t nr_ue_decode_mib(module_id_t module_id, int cc_id, @@ -987,7 +136,7 @@ int8_t nr_ue_decode_mib(module_id_t module_id, LOG_D(MAC,"cell barred (0=barred,1=notBarred): %d\n", (int)mac->mib->cellBarred); LOG_D(MAC,"intra frequency reselection (0=allowed,1=notAllowed): %d\n", (int)mac->mib->intraFreqReselection); LOG_D(MAC,"half frame bit(extra bits): %d\n", (int)half_frame_bit); - LOG_I(MAC,"ssb index(extra bits): %d\n", (int)ssb_index); + LOG_D(MAC,"ssb index(extra bits): %d\n", (int)ssb_index); //storing ssb index in the mac structure mac->mib_ssb = ssb_index; @@ -1021,1587 +170,10 @@ uint32_t get_ssb_frame(uint32_t test){ return test; } -/* - * This function returns the slot offset K2 corresponding to a given time domain - * indication value from RRC configuration. - */ -long get_k2(NR_UE_MAC_INST_t *mac, uint8_t time_domain_ind) { - long k2 = -1; - // Get K2 from RRC configuration - NR_PUSCH_Config_t *pusch_config=mac->ULbwp[0]->bwp_Dedicated->pusch_Config->choice.setup; - NR_PUSCH_TimeDomainResourceAllocationList_t *pusch_TimeDomainAllocationList = NULL; - if (pusch_config->pusch_TimeDomainAllocationList) { - pusch_TimeDomainAllocationList = pusch_config->pusch_TimeDomainAllocationList->choice.setup; - } - else if (mac->ULbwp[0]->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList) { - pusch_TimeDomainAllocationList = mac->ULbwp[0]->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList; - } - if (pusch_TimeDomainAllocationList) { - if (time_domain_ind >= pusch_TimeDomainAllocationList->list.count) { - LOG_E(MAC, "time_domain_ind %d >= pusch->TimeDomainAllocationList->list.count %d\n", - time_domain_ind, pusch_TimeDomainAllocationList->list.count); - return -1; - } - k2 = *pusch_TimeDomainAllocationList->list.array[time_domain_ind]->k2; - } - - LOG_D(MAC, "get_k2(): k2 is %ld\n", k2); - return k2; -} - -/* - * This function returns the UL config corresponding to a given UL slot - * from MAC instance . - */ -fapi_nr_ul_config_request_t *get_ul_config_request(NR_UE_MAC_INST_t *mac, int slot) { - //Check if request to access ul_config is for a UL slot - if (is_nr_UL_slot(mac->scc, slot) == 0) { - LOG_W(MAC, "Slot %d is not a UL slot. get_ul_config_request() called for wrong slot!!!\n", slot); - return NULL; - } - - // Calculate the index of the UL slot in mac->ul_config_request list. This is - // based on the TDD pattern (slot configuration period) and number of UL+mixed - // slots in the period. TS 38.213 Sec 11.1 - int mu = mac->ULbwp[0]->bwp_Common->genericParameters.subcarrierSpacing; - NR_TDD_UL_DL_Pattern_t *tdd_pattern = &mac->scc->tdd_UL_DL_ConfigurationCommon->pattern1; - const int num_slots_per_tdd = nr_slots_per_frame[mu] >> (7 - tdd_pattern->dl_UL_TransmissionPeriodicity); - const int num_slots_ul = tdd_pattern->nrofUplinkSlots + (tdd_pattern->nrofUplinkSymbols!=0); - int index = (slot + num_slots_ul - num_slots_per_tdd) % num_slots_per_tdd; - LOG_D(MAC, "nr_ue_procedures: get_ul_config_request() slots per tdd %d, num_slots_ul %d, index %d\n", - num_slots_per_tdd, - num_slots_ul, - index); - - return &mac->ul_config_request[index]; -} - -// Performs : -// 1. TODO: Call RRC for link status return to PHY -// 2. TODO: Perform SR/BSR procedures for scheduling feedback -// 3. TODO: Perform PHR procedures -NR_UE_L2_STATE_t nr_ue_scheduler(nr_downlink_indication_t *dl_info, nr_uplink_indication_t *ul_info){ - - uint32_t search_space_mask = 0; - - if (dl_info){ - - module_id_t mod_id = dl_info->module_id; - uint32_t gNB_index = dl_info->gNB_index; - int cc_id = dl_info->cc_id; - frame_t rx_frame = dl_info->frame; - slot_t rx_slot = dl_info->slot; - NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id); - - fapi_nr_dl_config_request_t *dl_config = &mac->dl_config_request; - nr_scheduled_response_t scheduled_response; - nr_dcireq_t dcireq; - - // check type0 from 38.213 13 if we have no CellGroupConfig - // TODO: implementation to be completed - if (mac->scg == NULL) { - - if(dl_info->ssb_index != -1){ - - if(mac->type0_pdcch_ss_mux_pattern == 1){ - // 38.213 chapter 13 - if((mac->type0_pdcch_ss_sfn_c == SFN_C_MOD_2_EQ_0) && !(rx_frame & 0x1) && (rx_slot == mac->type0_pdcch_ss_n_c)){ - search_space_mask = search_space_mask | type0_pdcch; - mac->type0_pdcch_consecutive_slots = mac->type0_pdcch_dci_config.coreset.duration; - } - if((mac->type0_pdcch_ss_sfn_c == SFN_C_MOD_2_EQ_1) && (rx_frame & 0x1) && (rx_slot == mac->type0_pdcch_ss_n_c)){ - search_space_mask = search_space_mask | type0_pdcch; - mac->type0_pdcch_consecutive_slots = mac->type0_pdcch_dci_config.coreset.duration; - } - } - if(mac->type0_pdcch_ss_mux_pattern == 2){ - // 38.213 Table 13-13, 13-14 - if((rx_frame == get_ssb_frame(rx_frame)) && (rx_slot == mac->type0_pdcch_ss_n_c)){ - search_space_mask = search_space_mask | type0_pdcch; - mac->type0_pdcch_consecutive_slots = mac->type0_pdcch_dci_config.coreset.duration; - } - } - if(mac->type0_pdcch_ss_mux_pattern == 3){ - // 38.213 Table 13-15 - if((rx_frame == get_ssb_frame(rx_frame)) && (rx_slot == mac->type0_pdcch_ss_n_c)){ - search_space_mask = search_space_mask | type0_pdcch; - mac->type0_pdcch_consecutive_slots = mac->type0_pdcch_dci_config.coreset.duration; - } - } - } // ssb_index != -1 - - // Type0 PDCCH search space - if((search_space_mask & type0_pdcch) || ( mac->type0_pdcch_consecutive_slots != 0 )){ - mac->type0_pdcch_consecutive_slots = mac->type0_pdcch_consecutive_slots - 1; - - dl_config->dl_config_list[dl_config->number_pdus].dci_config_pdu.dci_config_rel15 = mac->type0_pdcch_dci_config; - dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_DL_CONFIG_TYPE_DCI; - - /* - dl_config->dl_config_list[dl_config->number_pdus].dci_config_pdu.dci_config_rel15.rnti = 0xaaaa; // to be set - dl_config->dl_config_list[dl_config->number_pdus].dci_config_pdu.dci_config_rel15.N_RB_BWP = 106; // to be set - - LOG_I(MAC,"nr_ue_scheduler Type0 PDCCH with rnti %x, BWP %d\n", - dl_config->dl_config_list[dl_config->number_pdus].dci_config_pdu.dci_config_rel15.rnti, - dl_config->dl_config_list[dl_config->number_pdus].dci_config_pdu.dci_config_rel15.N_RB_BWP); - */ - dl_config->number_pdus = dl_config->number_pdus + 1; - - fill_scheduled_response(&scheduled_response, dl_config, NULL, NULL, mod_id, cc_id, rx_frame, rx_slot, dl_info->thread_id); - if(mac->if_module != NULL && mac->if_module->scheduled_response != NULL) - mac->if_module->scheduled_response(&scheduled_response); - } - } else { // we have an scg - - dcireq.module_id = mod_id; - dcireq.gNB_index = gNB_index; - dcireq.cc_id = cc_id; - dcireq.frame = rx_frame; - dcireq.slot = rx_slot; - dcireq.dl_config_req.number_pdus = 0; - nr_ue_dcireq(&dcireq); //to be replaced with function pointer later - - fill_scheduled_response(&scheduled_response, &dcireq.dl_config_req, NULL, NULL, mod_id, cc_id, rx_frame, rx_slot, dl_info->thread_id); - if(mac->if_module != NULL && mac->if_module->scheduled_response != NULL){ - mac->if_module->scheduled_response(&scheduled_response); - } - - /* - if(search_space_mask & type0a_pdcch){ - } - - if(search_space_mask & type1_pdcch){ - } - - if(search_space_mask & type2_pdcch){ - } - - if(search_space_mask & type3_pdcch){ - } - */ - } - } else if (ul_info) { - - module_id_t mod_id = ul_info->module_id; - NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id); - - if (((get_softmodem_params()->phy_test) || ((mac->ra_state == RA_SUCCEEDED)) ) && ul_info->slot_tx == 8) { // ULSCH is handled only in phy-test mode (consistently with OAI gNB) - static int skip_the_first = 0; - if (skip_the_first == 0) - { - skip_the_first = 1; - return UE_CONNECTION_OK; - } - - uint8_t nb_dmrs_re_per_rb; - uint8_t ulsch_input_buffer[MAX_ULSCH_PAYLOAD_BYTES]; - uint8_t data_existing = 0; - uint16_t TBS_bytes; - uint32_t TBS; - int i, N_PRB_oh; - - uint32_t gNB_index = ul_info->gNB_index; - int cc_id = ul_info->cc_id; - frame_t rx_frame = ul_info->frame_rx; - slot_t rx_slot = ul_info->slot_rx; - frame_t frame_tx = ul_info->frame_tx; - slot_t slot_tx = ul_info->slot_tx; - uint8_t access_mode = SCHEDULED_ACCESS; - - fapi_nr_ul_config_request_t *ul_config_req = get_ul_config_request(mac, slot_tx); - - // Schedule ULSCH only if the current frame and slot match those in ul_config_req - // AND if a UL DCI has been received (as indicated by num_pdus). - if ((frame_tx == ul_config_req->sfn && slot_tx == ul_config_req->slot) && - ul_config_req->number_pdus > 0) { - - // program PUSCH with UL DCI parameters - nr_scheduled_response_t scheduled_response; - fapi_nr_tx_request_t tx_req; - nfapi_nr_ue_ptrs_ports_t ptrs_ports_list; - - for (int j = 0; j < ul_config_req->number_pdus; j++) { - fapi_nr_ul_config_request_pdu_t *ulcfg_pdu = &ul_config_req->ul_config_list[j]; - - if (ulcfg_pdu->pdu_type == FAPI_NR_UL_CONFIG_TYPE_PUSCH) { - uint32_t rb_size = ulcfg_pdu->pusch_config_pdu.rb_size; - uint32_t rb_start = ulcfg_pdu->pusch_config_pdu.rb_start; - uint8_t nr_of_symbols = ulcfg_pdu->pusch_config_pdu.nr_of_symbols; - uint8_t start_symbol_index = ulcfg_pdu->pusch_config_pdu.start_symbol_index; - uint8_t mcs_index = ulcfg_pdu->pusch_config_pdu.mcs_index; - - rb_size = 106; - rb_start = 0; - nr_of_symbols = 11; - start_symbol_index = 0; - mcs_index = 9; - - // These should come from RRC config!!! - uint8_t ptrs_mcs1 = 2; - uint8_t ptrs_mcs2 = 4; - uint8_t ptrs_mcs3 = 10; - uint16_t n_rb0 = 25; - uint16_t n_rb1 = 75; - uint8_t ptrs_time_density = get_L_ptrs(ptrs_mcs1, ptrs_mcs2, ptrs_mcs3, mcs_index, ulcfg_pdu->pusch_config_pdu.mcs_table); - uint8_t ptrs_freq_density = get_K_ptrs(n_rb0, n_rb1, rb_size); - uint16_t l_prime_mask = get_l_prime(nr_of_symbols, typeB, pusch_dmrs_pos0, pusch_len1); - uint16_t ul_dmrs_symb_pos = l_prime_mask << start_symbol_index; - - uint8_t dmrs_config_type = 0; - uint16_t number_dmrs_symbols = 0; - - // PTRS ports configuration - // TbD: ptrs_dmrs_port and ptrs_port_index are not initialised! - ptrs_ports_list.ptrs_re_offset = 0; - - // Num PRB Overhead from PUSCH-ServingCellConfig - if (mac->scg->spCellConfig->spCellConfigDedicated->uplinkConfig->pusch_ServingCellConfig->choice.setup->xOverhead == NULL) - N_PRB_oh = 0; - else - N_PRB_oh = *mac->scg->spCellConfig->spCellConfigDedicated->uplinkConfig->pusch_ServingCellConfig->choice.setup->xOverhead; - - ulcfg_pdu->pusch_config_pdu.ul_dmrs_symb_pos = ul_dmrs_symb_pos; - ulcfg_pdu->pusch_config_pdu.dmrs_config_type = dmrs_config_type; - ulcfg_pdu->pusch_config_pdu.num_dmrs_cdm_grps_no_data = 1; - ulcfg_pdu->pusch_config_pdu.nrOfLayers = 1; - ulcfg_pdu->pusch_config_pdu.pusch_data.new_data_indicator = 0; - ulcfg_pdu->pusch_config_pdu.pdu_bit_map = PUSCH_PDU_BITMAP_PUSCH_DATA; - ulcfg_pdu->pusch_config_pdu.pusch_ptrs.ptrs_time_density = ptrs_time_density; - ulcfg_pdu->pusch_config_pdu.pusch_ptrs.ptrs_freq_density = ptrs_freq_density; - ulcfg_pdu->pusch_config_pdu.pusch_ptrs.ptrs_ports_list = &ptrs_ports_list; - //ulcfg_pdu->pusch_config_pdu.target_code_rate = nr_get_code_rate_ul(ulcfg_pdu->pusch_config_pdu.mcs_index, ulcfg_pdu->pusch_config_pdu.mcs_table); - //ulcfg_pdu->pusch_config_pdu.qam_mod_order = nr_get_Qm_ul(ulcfg_pdu->pusch_config_pdu.mcs_index, ulcfg_pdu->pusch_config_pdu.mcs_table); - - if (1 << ulcfg_pdu->pusch_config_pdu.pusch_ptrs.ptrs_time_density >= nr_of_symbols) { - ulcfg_pdu->pusch_config_pdu.pdu_bit_map &= ~PUSCH_PDU_BITMAP_PUSCH_PTRS; // disable PUSCH PTRS - } - - /* TRANSFORM PRECODING ------------------------------------------------------------------------------------------*/ - - if (ulcfg_pdu->pusch_config_pdu.transform_precoding == transform_precoder_enabled) { - - uint32_t n_RS_Id = 0; - - NR_PUSCH_Config_t *pusch_config=mac->ULbwp[0]->bwp_Dedicated->pusch_Config->choice.setup; - NR_DMRS_UplinkConfig_t *NR_DMRS_ulconfig = NULL; - - ulcfg_pdu->pusch_config_pdu.num_dmrs_cdm_grps_no_data = 2; - - if(pusch_config->dmrs_UplinkForPUSCH_MappingTypeA != NULL) - NR_DMRS_ulconfig = pusch_config->dmrs_UplinkForPUSCH_MappingTypeA->choice.setup; - else - NR_DMRS_ulconfig = pusch_config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup; - - - if (NR_DMRS_ulconfig->transformPrecodingEnabled->nPUSCH_Identity != NULL) - n_RS_Id = *NR_DMRS_ulconfig->transformPrecodingEnabled->nPUSCH_Identity; - else - n_RS_Id = *mac->scc->physCellId; - - // U as specified in section 6.4.1.1.1.2 in 38.211, if sequence hopping and group hopping are disabled - ulcfg_pdu->pusch_config_pdu.dfts_ofdm.low_papr_group_number = n_RS_Id % 30; - - // V as specified in section 6.4.1.1.1.2 in 38.211 V = 0 if sequence hopping and group hopping are disabled - if ((NR_DMRS_ulconfig->transformPrecodingEnabled->sequenceGroupHopping == NULL) && - (NR_DMRS_ulconfig->transformPrecodingEnabled->sequenceHopping == NULL)) - ulcfg_pdu->pusch_config_pdu.dfts_ofdm.low_papr_sequence_number = 0; - else - AssertFatal(1==0,"SequenceGroupHopping or sequenceHopping are NOT Supported\n"); - - LOG_D(MAC,"TRANSFORM PRECODING IS ENABLED. CDM groups: %d, U: %d \n", ulcfg_pdu->pusch_config_pdu.num_dmrs_cdm_grps_no_data, - ulcfg_pdu->pusch_config_pdu.dfts_ofdm.low_papr_group_number); - } - - /* TRANSFORM PRECODING --------------------------------------------------------------------------------------------------------*/ - - get_num_re_dmrs(&ulcfg_pdu->pusch_config_pdu, - &nb_dmrs_re_per_rb, - &number_dmrs_symbols); - - TBS = nr_compute_tbs(ulcfg_pdu->pusch_config_pdu.qam_mod_order, - ulcfg_pdu->pusch_config_pdu.target_code_rate, - rb_size, - nr_of_symbols, - nb_dmrs_re_per_rb*number_dmrs_symbols, - N_PRB_oh, - 0, - ulcfg_pdu->pusch_config_pdu.nrOfLayers); - TBS_bytes = TBS/8; - ulcfg_pdu->pusch_config_pdu.pusch_data.tb_size = TBS_bytes; - - if (IS_SOFTMODEM_NOS1){ - // Getting IP traffic to be transmitted - data_existing = nr_ue_get_sdu(mod_id, - cc_id, - frame_tx, - slot_tx, - 0, - ulsch_input_buffer, - TBS_bytes, - &access_mode); - } - - //Random traffic to be transmitted if there is no IP traffic available for this Tx opportunity - if (!IS_SOFTMODEM_NOS1 || !data_existing) { - //Use zeros for the header bytes in noS1 mode, in order to make sure that the LCID is not valid - //and block this traffic from being forwarded to the upper layers at the gNB - LOG_D(PHY, "Random data to be tranmsitted: \n"); - - //Give the first byte a dummy value (a value not corresponding to any valid LCID based on 38.321, Table 6.2.1-2) - //in order to distinguish the PHY random packets at the MAC layer of the gNB receiver from the normal packets that should - //have a valid LCID (nr_process_mac_pdu function) - ulsch_input_buffer[0] = 0x31; - - for (i = 1; i < TBS_bytes; i++) { - ulsch_input_buffer[i] = (unsigned char) rand(); - //printf(" input encoder a[%d]=0x%02x\n",i,harq_process_ul_ue->a[i]); - } - } - - #ifdef DEBUG_MAC_PDU - - LOG_D(PHY, "Is data existing ?: %d \n", data_existing); - LOG_I(PHY, "Printing MAC PDU to be encoded, TBS is: %d \n", TBS_bytes); - for (i = 0; i < TBS_bytes; i++) { - printf("%02x", ulsch_input_buffer[i]); - } - printf("\n"); - - #endif - - // Config UL TX PDU - tx_req.slot = slot_tx; - tx_req.sfn = frame_tx; - // tx_req->tx_config // TbD - tx_req.number_of_pdus++; - tx_req.tx_request_body[j].pdu_length = TBS_bytes; - tx_req.tx_request_body[j].pdu_index = j; - tx_req.tx_request_body[j].pdu = ulsch_input_buffer; - } - } - - fill_scheduled_response(&scheduled_response, NULL, ul_config_req, &tx_req, mod_id, cc_id, rx_frame, rx_slot, ul_info->thread_id); - if(mac->if_module != NULL && mac->if_module->scheduled_response != NULL){ - mac->if_module->scheduled_response(&scheduled_response); - } - - // TODO: expand - // Note: Contention resolution is currently not active - if (mac->RA_contention_resolution_timer_active == 1) - ue_contention_resolution(mod_id, gNB_index, cc_id, ul_info->frame_tx); - - } - - } else if (get_softmodem_params()->do_ra){ - - NR_UE_MAC_INST_t *mac = get_mac_inst(ul_info->module_id); - - if (ul_info->slot_tx == mac->msg3_slot && ul_info->frame_tx == mac->msg3_frame){ - - uint8_t ulsch_input_buffer[MAX_ULSCH_PAYLOAD_BYTES]; - nr_scheduled_response_t scheduled_response; - fapi_nr_tx_request_t tx_req; - //fapi_nr_ul_config_request_t *ul_config = get_ul_config_request(mac, ul_info->slot_tx); - fapi_nr_ul_config_request_t *ul_config = &mac->ul_config_request[0]; - fapi_nr_ul_config_request_pdu_t *ul_config_list = &ul_config->ul_config_list[ul_config->number_pdus]; - uint16_t TBS_bytes = ul_config_list->pusch_config_pdu.pusch_data.tb_size; - - //if (IS_SOFTMODEM_NOS1){ - // // Getting IP traffic to be transmitted - // data_existing = nr_ue_get_sdu(mod_id, - // cc_id, - // frame_tx, - // slot_tx, - // 0, - // ulsch_input_buffer, - // TBS_bytes, - // &access_mode); - //} - - //Random traffic to be transmitted if there is no IP traffic available for this Tx opportunity - //if (!IS_SOFTMODEM_NOS1 || !data_existing) { - //Use zeros for the header bytes in noS1 mode, in order to make sure that the LCID is not valid - //and block this traffic from being forwarded to the upper layers at the gNB - LOG_D(MAC, "Random data to be tranmsitted (TBS_bytes %d): \n", TBS_bytes); - //Give the first byte a dummy value (a value not corresponding to any valid LCID based on 38.321, Table 6.2.1-2) - //in order to distinguish the PHY random packets at the MAC layer of the gNB receiver from the normal packets that should - //have a valid LCID (nr_process_mac_pdu function) - ulsch_input_buffer[0] = 0x31; - for (int i = 1; i < TBS_bytes; i++) { - ulsch_input_buffer[i] = (unsigned char) rand(); - //printf(" input encoder a[%d]=0x%02x\n",i,harq_process_ul_ue->a[i]); - } - //} - - LOG_I(MAC, "[UE %d] Frame %d, Subframe %d Adding Msg3 UL Config Request for rnti: %x\n", - ul_info->module_id, - ul_info->frame_tx, - ul_info->slot_tx, - mac->t_crnti); - - // Config UL TX PDU - tx_req.slot = ul_info->slot_tx; - tx_req.sfn = ul_info->frame_tx; - tx_req.number_of_pdus = 1; - tx_req.tx_request_body[0].pdu_length = TBS_bytes; - tx_req.tx_request_body[0].pdu_index = 0; - tx_req.tx_request_body[0].pdu = ulsch_input_buffer; - ul_config_list->pdu_type = FAPI_NR_UL_CONFIG_TYPE_PUSCH; - ul_config->number_pdus++; - // scheduled_response - fill_scheduled_response(&scheduled_response, NULL, ul_config, &tx_req, ul_info->module_id, ul_info->cc_id, ul_info->frame_rx, ul_info->slot_rx, ul_info->thread_id); - if(mac->if_module != NULL && mac->if_module->scheduled_response != NULL){ - mac->if_module->scheduled_response(&scheduled_response); - } - mac->msg3_frame = -1; // re-initialize to an invalid value after scheduling - mac->msg3_slot = -1; - } - } - } - return UE_CONNECTION_OK; -} - -// PUSCH Msg3 scheduled by RAR UL grant according to 8.3 of TS 38.213 -// Note: Msg3 tx in the uplink symbols of mixed slot -void nr_ue_msg3_scheduler(NR_UE_MAC_INST_t *mac, - frame_t current_frame, - sub_frame_t current_slot, - uint8_t Msg3_tda_id){ - - int delta = 0; - NR_BWP_Uplink_t *ubwp = mac->ULbwp[0]; - int mu = ubwp->bwp_Common->genericParameters.subcarrierSpacing; - struct NR_PUSCH_TimeDomainResourceAllocationList *pusch_TimeDomainAllocationList = ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList; - // k2 as per 3GPP TS 38.214 version 15.9.0 Release 15 ch 6.1.2.1.1 - // PUSCH time domain resource allocation is higher layer configured from uschTimeDomainAllocationList in either pusch-ConfigCommon - uint8_t k2 = *pusch_TimeDomainAllocationList->list.array[Msg3_tda_id]->k2; - - switch (mu) { - case 0: - delta = 2; - break; - case 1: - delta = 3; - break; - case 2: - delta = 4; - break; - case 3: - delta = 6; - break; - } - - mac->msg3_slot = (current_slot + k2 + delta) % nr_slots_per_frame[mu]; - if (current_slot + k2 + delta > nr_slots_per_frame[mu]) - mac->msg3_frame = (current_frame + 1) % 1024; - else - mac->msg3_frame = current_frame; - - LOG_D(MAC, "[DEBUG_MSG3] current_slot %d k2 %d delta %d temp_slot %d mac->msg3_frame %d mac->msg3_slot %d \n", current_slot, k2, delta, current_slot + k2 + delta, mac->msg3_frame, mac->msg3_slot); -} - -// This function schedules the PRACH according to prach_ConfigurationIndex and TS 38.211, tables 6.3.3.2.x -// PRACH formats 9, 10, 11 are corresponding to dual PRACH format configurations A1/B1, A2/B2, A3/B3. -// - todo: -// - Partial configuration is actually already stored in (fapi_nr_prach_config_t) &mac->phy_config.config_req->prach_config -void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t slotP, int thread_id) { - - uint16_t format, format0, format1, ncs; - int is_nr_prach_slot; - prach_occasion_info_t *prach_occasion_info_p; - - NR_UE_MAC_INST_t *mac = get_mac_inst(module_idP); - - //fapi_nr_ul_config_request_t *ul_config = get_ul_config_request(mac, slotP); - fapi_nr_ul_config_request_t *ul_config = &mac->ul_config_request[0]; - fapi_nr_ul_config_prach_pdu *prach_config_pdu; - fapi_nr_config_request_t *cfg = &mac->phy_config.config_req; - fapi_nr_prach_config_t *prach_config = &cfg->prach_config; - nr_scheduled_response_t scheduled_response; - - NR_ServingCellConfigCommon_t *scc = mac->scc; - NR_RACH_ConfigCommon_t *setup = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup; - NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &setup->rach_ConfigGeneric; - - mac->RA_offset = 2; // to compensate the rx frame offset at the gNB - mac->generate_nr_prach = 0; // Reset flag for PRACH generation - - if (is_nr_UL_slot(scc, slotP)) { - - uint8_t selected_gnb_ssb_idx = mac->mib_ssb; - - // Get any valid PRACH occasion in the current slot for the selected SSB index - is_nr_prach_slot = get_nr_prach_info_from_ssb_index(selected_gnb_ssb_idx, - (int)frameP, - (int)slotP, - &prach_occasion_info_p); - - if (is_nr_prach_slot && mac->ra_state == RA_UE_IDLE) { - AssertFatal(NULL != prach_occasion_info_p,"PRACH Occasion Info not returned in a valid NR Prach Slot\n"); - - mac->generate_nr_prach = 1; - - format = prach_occasion_info_p->format; - format0 = format & 0xff; // single PRACH format - format1 = (format >> 8) & 0xff; // dual PRACH format - - ul_config->sfn = frameP; - ul_config->slot = slotP; - - ul_config->ul_config_list[ul_config->number_pdus].pdu_type = FAPI_NR_UL_CONFIG_TYPE_PRACH; - prach_config_pdu = &ul_config->ul_config_list[ul_config->number_pdus].prach_config_pdu; - memset(prach_config_pdu, 0, sizeof(fapi_nr_ul_config_prach_pdu)); - ul_config->number_pdus += 1; - - ncs = get_NCS(rach_ConfigGeneric->zeroCorrelationZoneConfig, format0, setup->restrictedSetConfig); - - prach_config_pdu->phys_cell_id = *scc->physCellId; - prach_config_pdu->num_prach_ocas = 1; - prach_config_pdu->prach_slot = prach_occasion_info_p->slot; - prach_config_pdu->prach_start_symbol = prach_occasion_info_p->start_symbol; - prach_config_pdu->num_ra = prach_occasion_info_p->fdm; - - prach_config_pdu->num_cs = ncs; - prach_config_pdu->root_seq_id = prach_config->num_prach_fd_occasions_list[prach_occasion_info_p->fdm].prach_root_sequence_index; - prach_config_pdu->restricted_set = prach_config->restricted_set_config; - prach_config_pdu->freq_msg1 = prach_config->num_prach_fd_occasions_list[prach_occasion_info_p->fdm].k1; - - LOG_D(MAC,"Selected RO Frame %u, Slot %u, Symbol %u, Fdm %u\n", frameP, prach_config_pdu->prach_slot, prach_config_pdu->prach_start_symbol, prach_config_pdu->num_ra); - - // Search which SSB is mapped in the RO (among all the SSBs mapped to this RO) - for (prach_config_pdu->ssb_nb_in_ro=0; prach_config_pdu->ssb_nb_in_ronb_mapped_ssb; prach_config_pdu->ssb_nb_in_ro++) { - if (prach_occasion_info_p->mapped_ssb_idx[prach_config_pdu->ssb_nb_in_ro] == selected_gnb_ssb_idx) - break; - } - AssertFatal(prach_config_pdu->ssb_nb_in_ronb_mapped_ssb, "%u not found in the mapped SSBs to the PRACH occasion", selected_gnb_ssb_idx); - - if (format1 != 0xff) { - switch(format0) { // dual PRACH format - case 0xa1: - prach_config_pdu->prach_format = 11; - break; - case 0xa2: - prach_config_pdu->prach_format = 12; - break; - case 0xa3: - prach_config_pdu->prach_format = 13; - break; - default: - AssertFatal(1 == 0, "Only formats A1/B1 A2/B2 A3/B3 are valid for dual format"); - } - } else { - switch(format0) { // single PRACH format - case 0: - prach_config_pdu->prach_format = 0; - break; - case 1: - prach_config_pdu->prach_format = 1; - break; - case 2: - prach_config_pdu->prach_format = 2; - break; - case 3: - prach_config_pdu->prach_format = 3; - break; - case 0xa1: - prach_config_pdu->prach_format = 4; - break; - case 0xa2: - prach_config_pdu->prach_format = 5; - break; - case 0xa3: - prach_config_pdu->prach_format = 6; - break; - case 0xb1: - prach_config_pdu->prach_format = 7; - break; - case 0xb4: - prach_config_pdu->prach_format = 8; - break; - case 0xc0: - prach_config_pdu->prach_format = 9; - break; - case 0xc2: - prach_config_pdu->prach_format = 10; - break; - default: - AssertFatal(1 == 0, "Invalid PRACH format"); - } - } // if format1 - } // is_nr_prach_slot - - fill_scheduled_response(&scheduled_response, NULL, ul_config, NULL, module_idP, 0 /*TBR fix*/, frameP, slotP, thread_id); - if(mac->if_module != NULL && mac->if_module->scheduled_response != NULL) - mac->if_module->scheduled_response(&scheduled_response); - } // if is_nr_UL_slot -} - -//////////////////////////////////////////////////////////////////////////// -/////////* Random Access Contention Resolution (5.1.35 TS 38.321) *///////// -//////////////////////////////////////////////////////////////////////////// -// Handling contention resolution timer -// WIP todo: -// - beam failure recovery -// - RA completed - -void ue_contention_resolution(module_id_t module_id, uint8_t gNB_index, int cc_id, frame_t tx_frame){ - - NR_UE_MAC_INST_t *mac = get_mac_inst(module_id); - NR_ServingCellConfigCommon_t *scc = mac->scc; - NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup; - - if (mac->RA_contention_resolution_timer_active == 1) { - if (nr_rach_ConfigCommon){ - LOG_I(MAC, "Frame %d: Contention resolution timer %d/%ld\n", - tx_frame, - mac->RA_contention_resolution_cnt, - ((1 + nr_rach_ConfigCommon->ra_ContentionResolutionTimer) << 3)); - mac->RA_contention_resolution_cnt++; - - if (mac->RA_contention_resolution_cnt == ((1 + nr_rach_ConfigCommon->ra_ContentionResolutionTimer) << 3)) { - mac->t_crnti = 0; - mac->RA_active = 0; - mac->RA_contention_resolution_timer_active = 0; - // Signal PHY to quit RA procedure - LOG_E(MAC, "[UE %u] [RAPROC] Contention resolution timer expired, RA failed, discarded TC-RNTI\n", module_id); - nr_ra_failed(module_id, cc_id, gNB_index); - } - } - } -} - -#if 0 -uint16_t nr_dci_format_size (PHY_VARS_NR_UE *ue, - uint8_t slot, - int p, - crc_scrambled_t crc_scrambled, - uint8_t dci_fields_sizes[NBR_NR_DCI_FIELDS][NBR_NR_FORMATS], - uint8_t format) { - LOG_DDD("crc_scrambled=%d, n_RB_ULBWP=%d, n_RB_DLBWP=%d\n",crc_scrambled,n_RB_ULBWP,n_RB_DLBWP); - /* - * function nr_dci_format_size calculates and returns the size in bits of a determined format - * it also returns an bi-dimensional array 'dci_fields_sizes' with x rows and y columns, where: - * x is the number of fields defined in TS 38.212 subclause 7.3.1 (Each field is mapped in the order in which it appears in the description in the specification) - * y is the number of formats - * e.g.: dci_fields_sizes[10][0] contains the size in bits of the field FREQ_DOM_RESOURCE_ASSIGNMENT_UL for format 0_0 - */ - // pdsch_config contains the PDSCH-Config IE is used to configure the UE specific PDSCH parameters (TS 38.331) - PDSCH_Config_t pdsch_config = ue->PDSCH_Config; - // pusch_config contains the PUSCH-Config IE is used to configure the UE specific PUSCH parameters (TS 38.331) - PUSCH_Config_t pusch_config = ue->pusch_config; - PUCCH_Config_t pucch_config_dedicated = ue->pucch_config_dedicated_nr[eNB_id]; - crossCarrierSchedulingConfig_t crossCarrierSchedulingConfig = ue->crossCarrierSchedulingConfig; - dmrs_UplinkConfig_t dmrs_UplinkConfig = ue->dmrs_UplinkConfig; - dmrs_DownlinkConfig_t dmrs_DownlinkConfig = ue->dmrs_DownlinkConfig; - csi_MeasConfig_t csi_MeasConfig = ue->csi_MeasConfig; - PUSCH_ServingCellConfig_t PUSCH_ServingCellConfig= ue->PUSCH_ServingCellConfig; - PDSCH_ServingCellConfig_t PDSCH_ServingCellConfig= ue->PDSCH_ServingCellConfig; - NR_UE_PDCCH *pdcch_vars2 = ue->pdcch_vars[proc->thread_id][eNB_id]; - // 1 CARRIER_IN - // crossCarrierSchedulingConfig from higher layers, variable crossCarrierSchedulingConfig indicates if 'cross carrier scheduling' is enabled or not: - // if No cross carrier scheduling: number of bits for CARRIER_IND is 0 - // if Cross carrier scheduling: number of bits for CARRIER_IND is 3 - // The IE CrossCarrierSchedulingConfig is used to specify the configuration when the cross-carrier scheduling is used in a cell - uint8_t crossCarrierSchedulingConfig_ind = 0; - - if (crossCarrierSchedulingConfig.schedulingCellInfo.other.cif_InSchedulingCell !=0 ) crossCarrierSchedulingConfig_ind=1; - - // 2 SUL_IND_0_1, // 40 SRS_REQUEST, // 50 SUL_IND_0_0 - // UL/SUL indicator (TS 38.331, supplementary uplink is indicated in higher layer parameter ServCellAdd-SUL from IE ServingCellConfig and ServingCellConfigCommon): - // 0 bit for UEs not configured with SUL in the cell or UEs configured with SUL in the cell but only PUCCH carrier in the cell is configured for PUSCH transmission - // 1 bit for UEs configured with SUL in the cell as defined in Table 7.3.1.1.1-1 - // sul_ind indicates whether SUL is configured in cell or not - uint8_t sul_ind=ue->supplementaryUplink.supplementaryUplink; // this value will be 0 or 1 depending on higher layer parameter ServCellAdd-SUL. FIXME!!! - // 7 BANDWIDTH_PART_IND - // number of UL BWPs configured by higher layers - uint8_t n_UL_BWP_RRC=1; // initialized to 1 but it has to be initialized by higher layers FIXME!!! - n_UL_BWP_RRC = ((n_UL_BWP_RRC > 3)?n_UL_BWP_RRC:(n_UL_BWP_RRC+1)); - // number of DL BWPs configured by higher layers - uint8_t n_DL_BWP_RRC=1; // initialized to 1 but it has to be initialized by higher layers FIXME!!! - n_DL_BWP_RRC = ((n_DL_BWP_RRC > 3)?n_DL_BWP_RRC:(n_DL_BWP_RRC+1)); - // 10 FREQ_DOM_RESOURCE_ASSIGNMENT_UL - // if format0_0, only resource allocation type 1 is allowed - // if format0_1, then resource allocation type 0 can be configured and N_RBG is defined in TS 38.214 subclause 6.1.2.2.1 - // for PUSCH hopping with resource allocation type 1 - // n_UL_hopping = 1 if the higher layer parameter frequencyHoppingOffsetLists contains two offset values - // n_UL_hopping = 2 if the higher layer parameter frequencyHoppingOffsetLists contains four offset values - uint8_t n_UL_hopping=pusch_config.n_frequencyHoppingOffsetLists; - - if (n_UL_hopping == 2) { - n_UL_hopping = 1; - } else if (n_UL_hopping == 4) { - n_UL_hopping = 2; - } else { - n_UL_hopping = 0; - } - - ul_resourceAllocation_t ul_resource_allocation_type = pusch_config.ul_resourceAllocation; - uint8_t ul_res_alloc_type_0 = 0; - uint8_t ul_res_alloc_type_1 = 0; - - if (ul_resource_allocation_type == ul_resourceAllocationType0) ul_res_alloc_type_0 = 1; - - if (ul_resource_allocation_type == ul_resourceAllocationType1) ul_res_alloc_type_1 = 1; - - if (ul_resource_allocation_type == ul_dynamicSwitch) { - ul_res_alloc_type_0 = 1; - ul_res_alloc_type_1 = 1; - } - - uint8_t n_bits_freq_dom_res_assign_ul=0,n_ul_RGB_tmp; - - if (ul_res_alloc_type_0 == 1) { // implementation of Table 6.1.2.2.1-1 TC 38.214 subclause 6.1.2.2.1 - // config1: PUSCH-Config IE contains rbg-Size ENUMERATED {config1 config2} - ul_rgb_Size_t config = pusch_config.ul_rgbSize; - uint8_t nominal_RBG_P = (config==ul_rgb_config1?2:4); - - if (n_RB_ULBWP > 36) nominal_RBG_P = (config==ul_rgb_config1?4:8); - - if (n_RB_ULBWP > 72) nominal_RBG_P = (config==ul_rgb_config1?8:16); - - if (n_RB_ULBWP > 144) nominal_RBG_P = 16; - - n_bits_freq_dom_res_assign_ul = (uint8_t)ceil((n_RB_ULBWP+(0%nominal_RBG_P))/nominal_RBG_P); //FIXME!!! what is 0??? - n_ul_RGB_tmp = n_bits_freq_dom_res_assign_ul; - } - - if (ul_res_alloc_type_1 == 1) n_bits_freq_dom_res_assign_ul = (uint8_t)(ceil(log2(n_RB_ULBWP*(n_RB_ULBWP+1)/2)))-n_UL_hopping; - - if ((ul_res_alloc_type_0 == 1) && (ul_res_alloc_type_1 == 1)) - n_bits_freq_dom_res_assign_ul = ((n_bits_freq_dom_res_assign_ul>n_ul_RGB_tmp)?(n_bits_freq_dom_res_assign_ul+1):(n_ul_RGB_tmp+1)); - - // 11 FREQ_DOM_RESOURCE_ASSIGNMENT_DL - // if format1_0, only resource allocation type 1 is allowed - // if format1_1, then resource allocation type 0 can be configured and N_RBG is defined in TS 38.214 subclause 5.1.2.2.1 - dl_resourceAllocation_t dl_resource_allocation_type = pdsch_config.dl_resourceAllocation; - uint8_t dl_res_alloc_type_0 = 0; - uint8_t dl_res_alloc_type_1 = 0; - - if (dl_resource_allocation_type == dl_resourceAllocationType0) dl_res_alloc_type_0 = 1; - - if (dl_resource_allocation_type == dl_resourceAllocationType1) dl_res_alloc_type_1 = 1; - - if (dl_resource_allocation_type == dl_dynamicSwitch) { - dl_res_alloc_type_0 = 1; - dl_res_alloc_type_1 = 1; - } - - uint8_t n_bits_freq_dom_res_assign_dl=0,n_dl_RGB_tmp; - - if (dl_res_alloc_type_0 == 1) { // implementation of Table 5.1.2.2.1-1 TC 38.214 subclause 6.1.2.2.1 - // config1: PDSCH-Config IE contains rbg-Size ENUMERATED {config1, config2} - dl_rgb_Size_t config = pdsch_config.dl_rgbSize; - uint8_t nominal_RBG_P = (config==dl_rgb_config1?2:4); - - if (n_RB_DLBWP > 36) nominal_RBG_P = (config==dl_rgb_config1?4:8); - - if (n_RB_DLBWP > 72) nominal_RBG_P = (config==dl_rgb_config1?8:16); - - if (n_RB_DLBWP > 144) nominal_RBG_P = 16; - - n_bits_freq_dom_res_assign_dl = (uint8_t)ceil((n_RB_DLBWP+(0%nominal_RBG_P))/nominal_RBG_P); //FIXME!!! what is 0??? - n_dl_RGB_tmp = n_bits_freq_dom_res_assign_dl; - } - - if (dl_res_alloc_type_1 == 1) n_bits_freq_dom_res_assign_dl = (uint8_t)(ceil(log2(n_RB_DLBWP*(n_RB_DLBWP+1)/2))); - - if ((dl_res_alloc_type_0 == 1) && (dl_res_alloc_type_1 == 1)) - n_bits_freq_dom_res_assign_dl = ((n_bits_freq_dom_res_assign_dl>n_dl_RGB_tmp)?(n_bits_freq_dom_res_assign_dl+1):(n_dl_RGB_tmp+1)); - - // 12 TIME_DOM_RESOURCE_ASSIGNMENT - uint8_t pusch_alloc_list = pusch_config.n_push_alloc_list; - uint8_t pdsch_alloc_list = pdsch_config.n_pdsh_alloc_list; - // 14 PRB_BUNDLING_SIZE_IND:0 bit if the higher layer parameter PRB_bundling is not configured or is set to 'static', or 1 bit if the higher layer parameter PRB_bundling is set to 'dynamic' according to Subclause 5.1.2.3 of [6, TS 38.214] - static_bundleSize_t static_prb_BundlingType = pdsch_config.prbBundleType.staticBundling; - bundleSizeSet1_t dynamic_prb_BundlingType1 = pdsch_config.prbBundleType.dynamicBundlig.bundleSizeSet1; - bundleSizeSet2_t dynamic_prb_BundlingType2 = pdsch_config.prbBundleType.dynamicBundlig.bundleSizeSet2; - uint8_t prb_BundlingType_size=0; - - if ((static_prb_BundlingType==st_n4)||(static_prb_BundlingType==st_wideband)) prb_BundlingType_size=0; - - if ((dynamic_prb_BundlingType1==dy_1_n4)||(dynamic_prb_BundlingType1==dy_1_wideband)||(dynamic_prb_BundlingType1==dy_1_n2_wideband)||(dynamic_prb_BundlingType1==dy_1_n4_wideband)|| - (dynamic_prb_BundlingType2==dy_2_n4)||(dynamic_prb_BundlingType2==dy_2_wideband)) prb_BundlingType_size=1; - - // 15 RATE_MATCHING_IND FIXME!!! - // according to TS 38.212: Rate matching indicator  E0, 1, or 2 bits according to higher layer parameter rateMatchPattern - uint8_t rateMatching_bits = pdsch_config.n_rateMatchPatterns; - // 16 ZP_CSI_RS_TRIGGER FIXME!!! - // 0, 1, or 2 bits as defined in Subclause 5.1.4.2 of [6, TS 38.214]. - // is the number of ZP CSI-RS resource sets in the higher layer parameter zp-CSI-RS-Resource - uint8_t n_zp_bits = pdsch_config.n_zp_CSI_RS_ResourceId; - // 17 FREQ_HOPPING_FLAG - // freqHopping is defined by higher layer parameter frequencyHopping from IE PUSCH-Config. Values are ENUMERATED{mode1, mode2} - frequencyHopping_t f_hopping = pusch_config.frequencyHopping; - uint8_t freqHopping = 0; - - if ((f_hopping==f_hop_mode1)||(f_hopping==f_hop_mode2)) freqHopping = 1; - - // 28 DAI - pdsch_HARQ_ACK_Codebook_t pdsch_HARQ_ACK_Codebook = pdsch_config.pdsch_HARQ_ACK_Codebook; - uint8_t n_dai = 0; - uint8_t n_serving_cell_dl = 1; // this is hardcoded to 1 as we need to get this value from RRC higher layers parameters. FIXME!!! - - if ((pdsch_HARQ_ACK_Codebook == dynamic) && (n_serving_cell_dl == 1)) n_dai = 2; - - if ((pdsch_HARQ_ACK_Codebook == dynamic) && (n_serving_cell_dl > 1)) n_dai = 4; - - // 29 FIRST_DAI - uint8_t codebook_HARQ_ACK = 0; // We need to get this value to calculate number of bits of fields 1st DAI and 2nd DAI. - - if (pdsch_HARQ_ACK_Codebook == semiStatic) codebook_HARQ_ACK = 1; - - if (pdsch_HARQ_ACK_Codebook == dynamic) codebook_HARQ_ACK = 2; - - // 30 SECOND_DAI - uint8_t n_HARQ_ACK_sub_codebooks = 0; // We need to get this value to calculate number of bits of fields 1st DAI and 2nd DAI. FIXME!!! - // 35 PDSCH_TO_HARQ_FEEDBACK_TIME_IND - uint8_t pdsch_harq_t_ind = (uint8_t)ceil(log2(pucch_config_dedicated.dl_DataToUL_ACK[0])); - // 36 SRS_RESOURCE_IND - // n_SRS is the number of configured SRS resources in the SRS resource set associated with the higher layer parameter usage of value 'codeBook' or 'nonCodeBook' - // from SRS_ResourceSet_t type we should get the information of the usage parameter (with possible values beamManagement, codebook, nonCodebook, antennaSwitching) - // at frame_parms->srs_nr->p_SRS_ResourceSetList[]->usage - uint8_t n_SRS = ue->srs.number_srs_Resource_Set; - // 37 PRECOD_NBR_LAYERS - // 38 ANTENNA_PORTS - txConfig_t txConfig = pusch_config.txConfig; - transformPrecoder_t transformPrecoder = pusch_config.transformPrecoder; - codebookSubset_t codebookSubset = pusch_config.codebookSubset; - uint8_t maxRank = pusch_config.maxRank; - uint8_t num_antenna_ports = 1; // this is hardcoded. We need to get the real value FIXME!!! - uint8_t precond_nbr_layers_bits = 0; - uint8_t antenna_ports_bits_ul = 0; - - // searching number of bits at tables 7.3.1.1.2-2/3/4/5 from TS 38.212 subclause 7.3.1.1.2 - if (txConfig == txConfig_codebook) { - if (num_antenna_ports == 4) { - if ((transformPrecoder == transformPrecoder_disabled) && ((maxRank == 2)||(maxRank == 3)||(maxRank == 4))) { // Table 7.3.1.1.2-2 - if (codebookSubset == codebookSubset_fullyAndPartialAndNonCoherent) precond_nbr_layers_bits=6; - - if (codebookSubset == codebookSubset_partialAndNonCoherent) precond_nbr_layers_bits=5; - - if (codebookSubset == codebookSubset_nonCoherent) precond_nbr_layers_bits=4; - } - - if (((transformPrecoder == transformPrecoder_enabled)||(transformPrecoder == transformPrecoder_disabled)) && (maxRank == 1)) { // Table 7.3.1.1.2-3 - if (codebookSubset == codebookSubset_fullyAndPartialAndNonCoherent) precond_nbr_layers_bits=5; - - if (codebookSubset == codebookSubset_partialAndNonCoherent) precond_nbr_layers_bits=4; - - if (codebookSubset == codebookSubset_nonCoherent) precond_nbr_layers_bits=2; - } - } - - if (num_antenna_ports == 2) { - if ((transformPrecoder == transformPrecoder_disabled) && (maxRank == 2)) { // Table 7.3.1.1.2-4 - if (codebookSubset == codebookSubset_fullyAndPartialAndNonCoherent) precond_nbr_layers_bits=4; - - if (codebookSubset == codebookSubset_nonCoherent) precond_nbr_layers_bits=2; - } - - if (((transformPrecoder == transformPrecoder_enabled)||(transformPrecoder == transformPrecoder_disabled)) && (maxRank == 1)) { // Table 7.3.1.1.2-5 - if (codebookSubset == codebookSubset_fullyAndPartialAndNonCoherent) precond_nbr_layers_bits=3; - - if (codebookSubset == codebookSubset_nonCoherent) precond_nbr_layers_bits=1; - } - } - } - - if (txConfig == txConfig_nonCodebook) { - } - - // searching number of bits at tables 7.3.1.1.2-6/7/8/9/10/11/12/13/14/15/16/17/18/19 - if((dmrs_UplinkConfig.pusch_dmrs_type == pusch_dmrs_type1)) { - if ((transformPrecoder == transformPrecoder_enabled) && (dmrs_UplinkConfig.pusch_maxLength == pusch_len1)) antenna_ports_bits_ul = 2; - - if ((transformPrecoder == transformPrecoder_enabled) && (dmrs_UplinkConfig.pusch_maxLength == pusch_len2)) antenna_ports_bits_ul = 4; - - if ((transformPrecoder == transformPrecoder_disabled) && (dmrs_UplinkConfig.pusch_maxLength == pusch_len1)) antenna_ports_bits_ul = 3; - - if ((transformPrecoder == transformPrecoder_disabled) && (dmrs_UplinkConfig.pusch_maxLength == pusch_len2)) antenna_ports_bits_ul = 4; - } - - if((dmrs_UplinkConfig.pusch_dmrs_type == pusch_dmrs_type2)) { - if ((transformPrecoder == transformPrecoder_disabled) && (dmrs_UplinkConfig.pusch_maxLength == pusch_len1)) antenna_ports_bits_ul = 4; - - if ((transformPrecoder == transformPrecoder_disabled) && (dmrs_UplinkConfig.pusch_maxLength == pusch_len2)) antenna_ports_bits_ul = 5; - } - - // for format 1_1 number of bits as defined by Tables 7.3.1.2.2-1/2/3/4 - uint8_t antenna_ports_bits_dl = 0; - - if((dmrs_DownlinkConfig.pdsch_dmrs_type == pdsch_dmrs_type1) && (dmrs_DownlinkConfig.pdsch_maxLength == pdsch_len1)) antenna_ports_bits_dl = 4; // Table 7.3.1.2.2-1 - - if((dmrs_DownlinkConfig.pdsch_dmrs_type == pdsch_dmrs_type1) && (dmrs_DownlinkConfig.pdsch_maxLength == pdsch_len2)) antenna_ports_bits_dl = 5; // Table 7.3.1.2.2-2 - - if((dmrs_DownlinkConfig.pdsch_dmrs_type == pdsch_dmrs_type2) && (dmrs_DownlinkConfig.pdsch_maxLength == pdsch_len1)) antenna_ports_bits_dl = 5; // Table 7.3.1.2.2-3 - - if((dmrs_DownlinkConfig.pdsch_dmrs_type == pdsch_dmrs_type2) && (dmrs_DownlinkConfig.pdsch_maxLength == pdsch_len2)) antenna_ports_bits_dl = 6; // Table 7.3.1.2.2-4 - - // 39 TCI - uint8_t tci_bits=0; - - if (pdcch_vars2->coreset[p].tciPresentInDCI == tciPresentInDCI_enabled) tci_bits=3; - - // 42 CSI_REQUEST - // reportTriggerSize is defined in the CSI-MeasConfig IE (TS 38.331). - // Size of CSI request field in DCI (bits). Corresponds to L1 parameter 'ReportTriggerSize' (see 38.214, section 5.2) - uint8_t reportTriggerSize = csi_MeasConfig.reportTriggerSize; // value from 0..6 - // 43 CBGTI - // for format 0_1 - uint8_t maxCodeBlockGroupsPerTransportBlock = 0; - - if (PUSCH_ServingCellConfig.maxCodeBlockGroupsPerTransportBlock != 0) - maxCodeBlockGroupsPerTransportBlock = (uint8_t)PUSCH_ServingCellConfig.maxCodeBlockGroupsPerTransportBlock; - - // for format 1_1, as defined in Subclause 5.1.7 of [6, TS38.214] - uint8_t maxCodeBlockGroupsPerTransportBlock_dl = 0; - - if (PDSCH_ServingCellConfig.maxCodeBlockGroupsPerTransportBlock_dl != 0) - maxCodeBlockGroupsPerTransportBlock_dl = pdsch_config.maxNrofCodeWordsScheduledByDCI; // FIXME!!! - - // 44 CBGFI - uint8_t cbgfi_bit = PDSCH_ServingCellConfig.codeBlockGroupFlushIndicator; - // 45 PTRS_DMRS - // 0 bit if PTRS-UplinkConfig is not configured and transformPrecoder=disabled, or if transformPrecoder=enabled, or if maxRank=1 - // 2 bits otherwise - uint8_t ptrs_dmrs_bits=0; //FIXME!!! - // 46 BETA_OFFSET_IND - // at IE PUSCH-Config, beta_offset indicator  E0 if the higher layer parameter betaOffsets = semiStatic; otherwise 2 bits - // uci-OnPUSCH - // Selection between and configuration of dynamic and semi-static beta-offset. If the field is absent or released, the UE applies the value 'semiStatic' and the BetaOffsets - uint8_t betaOffsets = 0; - - if (pusch_config.uci_onPusch.betaOffset_type == betaOffset_semiStatic); - - if (pusch_config.uci_onPusch.betaOffset_type == betaOffset_dynamic) betaOffsets = 2; - - // 47 DMRS_SEQ_INI - uint8_t dmrs_seq_ini_bits_ul = 0; - uint8_t dmrs_seq_ini_bits_dl = 0; - - //1 bit if both scramblingID0 and scramblingID1 are configured in DMRS-UplinkConfig - if ((transformPrecoder == transformPrecoder_disabled) && (dmrs_UplinkConfig.scramblingID0 != 0) && (dmrs_UplinkConfig.scramblingID1 != 0)) dmrs_seq_ini_bits_ul = 1; - - //1 bit if both scramblingID0 and scramblingID1 are configured in DMRS-DownlinkConfig - if ((dmrs_DownlinkConfig.scramblingID0 != 0) && (dmrs_DownlinkConfig.scramblingID0 != 0)) dmrs_seq_ini_bits_dl = 1; - - /* - * For format 2_2 - * - * This format supports power control commands for semi-persistent scheduling. - * As we can already support power control commands dynamically with formats 0_0/0_1 (TPC PUSCH) and 1_0/1_1 (TPC PUCCH) - * - * This format will be implemented in the future FIXME!!! - * - */ - // 5 BLOCK_NUMBER: The parameter tpc-PUSCH or tpc-PUCCH provided by higher layers determines the index to the block number for an UL of a cell - // The following fields are defined for each block: Closed loop indicator and TPC command - // 6 CLOSE_LOOP_IND - // 41 TPC_CMD - uint8_t tpc_cmd_bit_2_2 = 2; - /* - * For format 2_3 - * - * This format is used for power control of uplink sounding reference signals for devices which have not coupled SRS power control to the PUSCH power control - * either because independent control is desirable or because the device is configured without PUCCH and PUSCH - * - * This format will be implemented in the future FIXME!!! - * - */ - // 40 SRS_REQUEST - // 41 TPC_CMD - uint8_t tpc_cmd_bit_2_3 = 0; - uint8_t dci_field_size_table [NBR_NR_DCI_FIELDS][NBR_NR_FORMATS] = { // This table contains the number of bits for each field (row) contained in each dci format (column). - // The values of the variables indicate field sizes in number of bits - //Format0_0 Format0_1 Format1_0 Format1_1 Formats2_0/1/2/3 - { - 1, 1, (((crc_scrambled == _p_rnti) || (crc_scrambled == _si_rnti) || (crc_scrambled == _ra_rnti)) ? 0:1), - 1, 0,0,0,0 - }, // 0 IDENTIFIER_DCI_FORMATS: - { - 0, ((crossCarrierSchedulingConfig_ind == 0) ? 0:3), - 0, ((crossCarrierSchedulingConfig_ind == 0) ? 0:3), - 0,0,0,0 - }, // 1 CARRIER_IND: 0 or 3 bits, as defined in Subclause x.x of [5, TS38.213] - {0, (sul_ind == 0)?0:1, 0, 0, 0,0,0,0}, // 2 SUL_IND_0_1: - {0, 0, 0, 0, 1,0,0,0}, // 3 SLOT_FORMAT_IND: size of DCI format 2_0 is configurable by higher layers up to 128 bits, according to Subclause 11.1.1 of [5, TS 38.213] - {0, 0, 0, 0, 0,1,0,0}, // 4 PRE_EMPTION_IND: size of DCI format 2_1 is configurable by higher layers up to 126 bits, according to Subclause 11.2 of [5, TS 38.213]. Each pre-emption indication is 14 bits - {0, 0, 0, 0, 0,0,0,0}, // 5 BLOCK_NUMBER: starting position of a block is determined by the parameter startingBitOfFormat2_3 - {0, 0, 0, 0, 0,0,1,0}, // 6 CLOSE_LOOP_IND - { - 0, (uint8_t)ceil(log2(n_UL_BWP_RRC)), - 0, (uint8_t)ceil(log2(n_DL_BWP_RRC)), - 0,0,0,0 - }, // 7 BANDWIDTH_PART_IND: - { - 0, 0, ((crc_scrambled == _p_rnti) ? 2:0), - 0, 0,0,0,0 - }, // 8 SHORT_MESSAGE_IND 2 bits if crc scrambled with P-RNTI - { - 0, 0, ((crc_scrambled == _p_rnti) ? 8:0), - 0, 0,0,0,0 - }, // 9 SHORT_MESSAGES 8 bit8 if crc scrambled with P-RNTI - { - (uint8_t)(ceil(log2(n_RB_ULBWP*(n_RB_ULBWP+1)/2)))-n_UL_hopping, - n_bits_freq_dom_res_assign_ul, - 0, 0, 0,0,0,0 - }, // 10 FREQ_DOM_RESOURCE_ASSIGNMENT_UL: PUSCH hopping with resource allocation type 1 not considered - // (NOTE 1) If DCI format 0_0 is monitored in common search space - // and if the number of information bits in the DCI format 0_0 prior to padding - // is larger than the payload size of the DCI format 1_0 monitored in common search space - // the bitwidth of the frequency domain resource allocation field in the DCI format 0_0 - // is reduced such that the size of DCI format 0_0 equals to the size of the DCI format 1_0 - { - 0, 0, (uint8_t)ceil(log2(n_RB_DLBWP*(n_RB_DLBWP+1)/2)), - n_bits_freq_dom_res_assign_dl, - 0,0,0,0 - }, // 11 FREQ_DOM_RESOURCE_ASSIGNMENT_DL: - { - 4, (uint8_t)log2(pusch_alloc_list), - 4, (uint8_t)log2(pdsch_alloc_list), - 0,0,0,0 - }, // 12 TIME_DOM_RESOURCE_ASSIGNMENT: 0, 1, 2, 3, or 4 bits as defined in Subclause 6.1.2.1 of [6, TS 38.214]. The bitwidth for this field is determined as log2(I) bits, - // where I the number of entries in the higher layer parameter pusch-AllocationList - { - 0, 0, 1, (((dl_res_alloc_type_0==1) &&(dl_res_alloc_type_1==0))?0:1), - 0,0,0,0 - }, // 13 VRB_TO_PRB_MAPPING: 0 bit if only resource allocation type 0 - {0, 0, 0, prb_BundlingType_size, 0,0,0,0}, // 14 PRB_BUNDLING_SIZE_IND:0 bit if the higher layer parameter PRB_bundling is not configured or is set to 'static', or 1 bit if the higher layer parameter PRB_bundling is set to 'dynamic' according to Subclause 5.1.2.3 of [6, TS 38.214] - {0, 0, 0, rateMatching_bits, 0,0,0,0}, // 15 RATE_MATCHING_IND: 0, 1, or 2 bits according to higher layer parameter rate-match-PDSCH-resource-set - {0, 0, 0, n_zp_bits, 0,0,0,0}, // 16 ZP_CSI_RS_TRIGGER: - { - 1, (((ul_res_alloc_type_0==1) &&(ul_res_alloc_type_1==0))||(freqHopping == 0))?0:1, - 0, 0, 0,0,0,0 - }, // 17 FREQ_HOPPING_FLAG: 0 bit if only resource allocation type 0 - {0, 0, 0, 5, 0,0,0,0}, // 18 TB1_MCS: - {0, 0, 0, 1, 0,0,0,0}, // 19 TB1_NDI: - {0, 0, 0, 2, 0,0,0,0}, // 20 TB1_RV: - {0, 0, 0, 5, 0,0,0,0}, // 21 TB2_MCS: - {0, 0, 0, 1, 0,0,0,0}, // 22 TB2_NDI: - {0, 0, 0, 2, 0,0,0,0}, // 23 TB2_RV: - {5, 5, 5, 0, 0,0,0,0}, // 24 MCS: - {1, 1, (crc_scrambled == _c_rnti)?1:0,0, 0,0,0,0}, // 25 NDI: - { - 2, 2, (((crc_scrambled == _c_rnti) || (crc_scrambled == _si_rnti)) ? 2:0), - 0, 0,0,0,0 - }, // 26 RV: - {4, 4, (crc_scrambled == _c_rnti)?4:0,4, 0,0,0,0}, // 27 HARQ_PROCESS_NUMBER: - {0, 0, (crc_scrambled == _c_rnti)?2:0,n_dai, 0,0,0,0}, // 28 DAI: For format1_1: 4 if more than one serving cell are configured in the DL and the higher layer parameter HARQ-ACK-codebook=dynamic, where the 2 MSB bits are the counter DAI and the 2 LSB bits are the total DAI - // 2 if one serving cell is configured in the DL and the higher layer parameter HARQ-ACK-codebook=dynamic, where the 2 bits are the counter DAI - // 0 otherwise - {0, codebook_HARQ_ACK, 0, 0, 0,0,0,0}, // 29 FIRST_DAI: (1 or 2 bits) 1 bit for semi-static HARQ-ACK // 2 bits for dynamic HARQ-ACK codebook with single HARQ-ACK codebook - { - 0, (((codebook_HARQ_ACK == 2) &&(n_HARQ_ACK_sub_codebooks==2))?2:0), - 0, 0, 0,0,0,0 - }, // 30 SECOND_DAI: (0 or 2 bits) 2 bits for dynamic HARQ-ACK codebook with two HARQ-ACK sub-codebooks // 0 bits otherwise - { - 0, 0, (((crc_scrambled == _p_rnti) || (crc_scrambled == _ra_rnti)) ? 2:0), - 0, 0,0,0,0 - }, // 31 TB_SCALING - {2, 2, 0, 0, 0,0,0,0}, // 32 TPC_PUSCH: - {0, 0, (crc_scrambled == _c_rnti)?2:0,2, 0,0,0,0}, // 33 TPC_PUCCH: - {0, 0, (crc_scrambled == _c_rnti)?3:0,3, 0,0,0,0}, // 34 PUCCH_RESOURCE_IND: - {0, 0, (crc_scrambled == _c_rnti)?3:0,pdsch_harq_t_ind, 0,0,0,0}, // 35 PDSCH_TO_HARQ_FEEDBACK_TIME_IND: - {0, (uint8_t)log2(n_SRS), 0, 0, 0,0,0,0}, // 36 SRS_RESOURCE_IND: - {0, precond_nbr_layers_bits, 0, 0, 0,0,0,0}, // 37 PRECOD_NBR_LAYERS: - {0, antenna_ports_bits_ul, 0, antenna_ports_bits_dl, 0,0,0,0}, // 38 ANTENNA_PORTS: - {0, 0, 0, tci_bits, 0,0,0,0}, // 39 TCI: 0 bit if higher layer parameter tci-PresentInDCI is not enabled; otherwise 3 bits - {0, (sul_ind == 0)?2:3, 0, (sul_ind == 0)?2:3, 0,0,0,2}, // 40 SRS_REQUEST: - { - 0, 0, 0, 0, 0,0,tpc_cmd_bit_2_2, - tpc_cmd_bit_2_3 - }, - // 41 TPC_CMD: - {0, reportTriggerSize, 0, 0, 0,0,0,0}, // 42 CSI_REQUEST: - { - 0, maxCodeBlockGroupsPerTransportBlock, - 0, maxCodeBlockGroupsPerTransportBlock_dl, - 0,0,0,0 - }, // 43 CBGTI: 0, 2, 4, 6, or 8 bits determined by higher layer parameter maxCodeBlockGroupsPerTransportBlock for the PDSCH - {0, 0, 0, cbgfi_bit, 0,0,0,0}, // 44 CBGFI: 0 or 1 bit determined by higher layer parameter codeBlockGroupFlushIndicator - {0, ptrs_dmrs_bits, 0, 0, 0,0,0,0}, // 45 PTRS_DMRS: - {0, betaOffsets, 0, 0, 0,0,0,0}, // 46 BETA_OFFSET_IND: - {0, dmrs_seq_ini_bits_ul, 0, dmrs_seq_ini_bits_dl, 0,0,0,0}, // 47 DMRS_SEQ_INI: 1 bit if the cell has two ULs and the number of bits for DCI format 1_0 before padding - // is larger than the number of bits for DCI format 0_0 before padding; 0 bit otherwise - {0, 1, 0, 0, 0,0,0,0}, // 48 UL_SCH_IND: value of "1" indicates UL-SCH shall be transmitted on the PUSCH and a value of "0" indicates UL-SCH shall not be transmitted on the PUSCH - {0, 0, 0, 0, 0,0,0,0}, // 49 PADDING_NR_DCI: - // (NOTE 2) If DCI format 0_0 is monitored in common search space - // and if the number of information bits in the DCI format 0_0 prior to padding - // is less than the payload size of the DCI format 1_0 monitored in common search space - // zeros shall be appended to the DCI format 0_0 - // until the payload size equals that of the DCI format 1_0 - {(sul_ind == 0)?0:1, 0, 0, 0, 0,0,0,0}, // 50 SUL_IND_0_0: - {0, 0, 0, 0, 0,0,0,0}, // 51 RA_PREAMBLE_INDEX (random access procedure initiated by a PDCCH order not implemented, FIXME!!!) - {0, 0, 0, 0, 0,0,0,0}, // 52 SUL_IND_1_0 (random access procedure initiated by a PDCCH order not implemented, FIXME!!!) - {0, 0, 0, 0, 0,0,0,0}, // 53 SS_PBCH_INDEX (random access procedure initiated by a PDCCH order not implemented, FIXME!!!) - {0, 0, 0, 0, 0,0,0,0}, // 54 PRACH_MASK_INDEX (random access procedure initiated by a PDCCH order not implemented, FIXME!!!) - { - 0, 0, ((crc_scrambled == _p_rnti)?6:(((crc_scrambled == _si_rnti) || (crc_scrambled == _ra_rnti))?16:0)), - 0, 0,0,0,0 - } // 55 RESERVED_NR_DCI - }; - // NOTE 1: adjustments in freq_dom_resource_assignment_UL to be done if necessary - // NOTE 2: adjustments in padding to be done if necessary - uint8_t dci_size [8] = {0,0,0,0,0,0,0,0}; // will contain size for each format - - for (int i=0 ; i position in table is 2) - dci_fields_sizes[j][i] = dci_field_size_table[j][i]; // dci_fields_sizes[j] contains the sizes of each field (j) for a determined format i - //} - } - - LOG_DDD("(nr_dci_format_size) dci_size[%d]=%d for n_RB_ULBWP=%d\n", - i,dci_size[i],n_RB_ULBWP); - } - - LOG_DDD("(nr_dci_format_size) dci_fields_sizes[][] = { \n"); - -#ifdef NR_PDCCH_DCI_DEBUG - for (int j=0; j dci_size[2])) { - dci_field_size_table[SUL_IND_0_0][0] = 0; - dci_size[0]=dci_size[0]-1; - } - - // if ((format == format0_0) || (format == format1_0)) { - // According to Section 7.3.1.1.1 in TS 38.212 - // If DCI format 0_0 is monitored in common search space and if the number of information bits in the DCI format 0_0 prior to padding - // is less than the payload size of the DCI format 1_0 monitored in common search space for scheduling the same serving cell, - // zeros shall be appended to the DCI format 0_0 until the payload size equals that of the DCI format 1_0. - if (dci_size[0] < dci_size[2]) { // '0' corresponding to index for format0_0 and '2' corresponding to index of format1_0 - //if (format == format0_0) { - dci_fields_sizes[PADDING_NR_DCI][0] = dci_size[2] - dci_size[0]; - dci_size[0] = dci_size[2]; - LOG_DDD("(nr_dci_format_size) new dci_size[format0_0]=%d\n",dci_size[0]); - //} - } - - // If DCI format 0_0 is monitored in common search space and if the number of information bits in the DCI format 0_0 prior to padding - // is larger than the payload size of the DCI format 1_0 monitored in common search space for scheduling the same serving cell, - // the bitwidth of the frequency domain resource allocation field in the DCI format 0_0 is reduced - // such that the size of DCI format 0_0 equals to the size of the DCI format 1_0.. - if (dci_size[0] > dci_size[2]) { - //if (format == format0_0) { - dci_fields_sizes[FREQ_DOM_RESOURCE_ASSIGNMENT_UL][0] -= (dci_size[0] - dci_size[2]); - dci_size[0] = dci_size[2]; - LOG_DDD("(nr_dci_format_size) new dci_size[format0_0]=%d\n",dci_size[0]); - //} - } - - /* - * TS 38.212 subclause 7.3.1.1.2 - * For a UE configured with SUL in a cell: - * if PUSCH is configured to be transmitted on both the SUL and the non-SUL of the cell and - * if the number of information bits in format 0_1 for the SUL - * is not equal to the number of information bits in format 0_1 for the non-SUL, - * zeros shall be appended to smaller format 0_1 until the payload size equals that of the larger format 0_1 - * - * Not implemented. FIXME!!! - * - */ - // } - LOG_DDD("(nr_dci_format_size) dci_fields_sizes[][] = { \n"); - -#ifdef NR_PDCCH_DCI_DEBUG - for (int j=0; jrnti,dci->dci_format,dci->n_CCE,dci->payloadSize,*(unsigned long long*)dci->payloadBits); - int dci_format = nr_extract_dci_info(mac,dci->dci_format,dci->payloadSize,dci->rnti,(uint64_t *)dci->payloadBits,def_dci_pdu_rel15); + uint32_t dci_format = nr_extract_dci_info(mac, dci->dci_format, dci->payloadSize, dci->rnti, (uint64_t *)dci->payloadBits, def_dci_pdu_rel15); return (nr_ue_process_dci(module_id, cc_id, gNB_index, frame, slot, def_dci_pdu_rel15, dci->rnti, dci_format)); } -int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, frame_t frame, int slot, dci_pdu_rel15_t *dci, uint16_t rnti, uint32_t dci_format){ +int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, frame_t frame, int slot, dci_pdu_rel15_t *dci, uint16_t rnti, uint8_t dci_format){ - int bwp_id = 1; - int mu = 0; - long k2 = 0; + int ret = 0; int pucch_res_set_cnt = 0, valid = 0; - uint16_t frame_tx = 0, slot_tx = 0; + frame_t frame_tx = 0; + int slot_tx = 0; bool valid_ptrs_setup = 0; NR_UE_MAC_INST_t *mac = get_mac_inst(module_id); + RA_config_t *ra = &mac->ra; fapi_nr_dl_config_request_t *dl_config = &mac->dl_config_request; - fapi_nr_ul_config_request_t *ul_config = NULL; - + uint8_t is_Msg3 = 0; + //const uint16_t n_RB_DLBWP = dl_config->dl_config_list[dl_config->number_pdus].dci_config_pdu.dci_config_rel15.N_RB_BWP; //make sure this has been set AssertFatal(mac->DLbwp[0]!=NULL,"DLbwp[0] should not be zero here!\n"); AssertFatal(mac->ULbwp[0]!=NULL,"DLbwp[0] should not be zero here!\n"); - const uint16_t n_RB_DLBWP = (mac->ra_state == WAIT_RAR) ? NRRIV2BW(mac->scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, 275) : NRRIV2BW(mac->DLbwp[0]->bwp_Common->genericParameters.locationAndBandwidth,275); - const uint16_t n_RB_ULBWP = NRRIV2BW(mac->ULbwp[0]->bwp_Common->genericParameters.locationAndBandwidth,275); + const uint16_t n_RB_DLBWP = (ra->ra_state == WAIT_RAR) ? NRRIV2BW(mac->scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE) : NRRIV2BW(mac->DLbwp[0]->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); - LOG_D(MAC,"nr_ue_process_dci at MAC layer with dci_format=%d (DL BWP %d, UL BWP %d)\n",dci_format,n_RB_DLBWP,n_RB_ULBWP); - - NR_PDSCH_Config_t *pdsch_config=mac->DLbwp[0]->bwp_Dedicated->pdsch_Config->choice.setup; - NR_PUSCH_Config_t *pusch_config=mac->ULbwp[0]->bwp_Dedicated->pusch_Config->choice.setup; + LOG_D(MAC, "In %s: Processing received DCI format %s (DL BWP %d)\n", __FUNCTION__, dci_formats[dci_format], n_RB_DLBWP); switch(dci_format){ - case NR_UL_DCI_FORMAT_0_0: + case NR_UL_DCI_FORMAT_0_0: { /* * with CRC scrambled by C-RNTI or CS-RNTI or new-RNTI or TC-RNTI * 0 IDENTIFIER_DCI_FORMATS: @@ -2924,92 +492,39 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr // Calculate the slot in which ULSCH should be scheduled. This is current slot + K2, // where K2 is the offset between the slot in which UL DCI is received and the slot // in which ULSCH should be scheduled. K2 is configured in RRC configuration. + // todo: + // - SUL_IND_0_0 + + // Schedule PUSCH + ret = nr_ue_pusch_scheduler(mac, is_Msg3, frame, slot, &frame_tx, &slot_tx, dci->time_domain_assignment.val); + + if (ret != -1){ + + // Get UL config request corresponding slot_tx + fapi_nr_ul_config_request_t *ul_config = get_ul_config_request(mac, slot_tx); + + if (!ul_config) { + LOG_W(MAC, "In %s: ul_config request is NULL. Probably due to unexpected UL DCI in frame.slot %d.%d. Ignoring DCI!\n", __FUNCTION__, frame, slot); + return -1; + } + + nfapi_nr_ue_pusch_pdu_t *pusch_config_pdu = &ul_config->ul_config_list[ul_config->number_pdus].pusch_config_pdu; + + fill_ul_config(ul_config, frame_tx, slot_tx, FAPI_NR_UL_CONFIG_TYPE_PUSCH); + + // Config PUSCH PDU + ret = nr_config_pusch_pdu(mac, pusch_config_pdu, dci, NULL, rnti, &dci_format); + + if (ret != -1 && ra->RA_active && mac->crnti){ + nr_ra_succeeded(module_id, frame, slot); + } + + } - // Get the numerology to calculate the Tx frame and slot - mu = mac->ULbwp[0]->bwp_Common->genericParameters.subcarrierSpacing; - // Get slot offset K2 which will be used to calculate TX slot - k2 = get_k2(mac, dci->time_domain_assignment.val); - if (k2 < 0) // This can happen when a false DCI is received - return -1; - // Calculate TX slot and frame - slot_tx = (slot + k2) % nr_slots_per_frame[mu]; - frame_tx = ((slot + k2) > nr_slots_per_frame[mu]) ? (frame + 1) % 1024 : frame; - - // Get UL config request corresponding slot_tx - ul_config = get_ul_config_request(mac, slot_tx); - //AssertFatal(ul_config != NULL, "nr_ue_process_dci(): ul_config is NULL\n"); - if (!ul_config) { - LOG_W(MAC, "nr_ue_process_dci(): ul_config request is NULL. Probably due to unexpected UL DCI in frame.slot %d.%d. Ignoring DCI!\n",frame,slot); - return -1; - } - - ul_config->ul_config_list[ul_config->number_pdus].pdu_type = FAPI_NR_UL_CONFIG_TYPE_PUSCH; - ul_config->ul_config_list[ul_config->number_pdus].pusch_config_pdu.rnti = rnti; - nfapi_nr_ue_pusch_pdu_t *pusch_config_pdu_0_0 = &ul_config->ul_config_list[ul_config->number_pdus].pusch_config_pdu; - /* IDENTIFIER_DCI_FORMATS */ - /* FREQ_DOM_RESOURCE_ASSIGNMENT_UL */ - if (nr_ue_process_dci_freq_dom_resource_assignment(pusch_config_pdu_0_0,NULL,n_RB_ULBWP,0,dci->frequency_domain_assignment.val) < 0) - return -1; - /* TIME_DOM_RESOURCE_ASSIGNMENT */ - if (nr_ue_process_dci_time_dom_resource_assignment(mac,pusch_config_pdu_0_0,NULL,dci->time_domain_assignment.val) < 0) - return -1; - /* FREQ_HOPPING_FLAG */ - if ((mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.resource_allocation != 0) && - (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.frequency_hopping !=0)) - pusch_config_pdu_0_0->frequency_hopping = dci->frequency_hopping_flag.val; - - /* MCS */ - pusch_config_pdu_0_0->mcs_index = dci->mcs; - - /* MCS TABLE */ - if (mac->scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg3_transformPrecoder == NULL) - pusch_config_pdu_0_0->transform_precoding = transform_precoder_disabled; - else - pusch_config_pdu_0_0->transform_precoding = transform_precoder_enabled; - - if (pusch_config_pdu_0_0->transform_precoding == transform_precoder_disabled) - pusch_config_pdu_0_0->mcs_table = get_pusch_mcs_table(pusch_config->mcs_Table, 0, - dci_format, NR_RNTI_TC, NR_SearchSpace__searchSpaceType_PR_common, false); - else - pusch_config_pdu_0_0->mcs_table = get_pusch_mcs_table(pusch_config->mcs_TableTransformPrecoder, 1, - dci_format, NR_RNTI_TC, NR_SearchSpace__searchSpaceType_PR_common, false); - - pusch_config_pdu_0_0->target_code_rate = nr_get_code_rate_ul(pusch_config_pdu_0_0->mcs_index, pusch_config_pdu_0_0->mcs_table); - pusch_config_pdu_0_0->qam_mod_order = nr_get_Qm_ul(pusch_config_pdu_0_0->mcs_index, pusch_config_pdu_0_0->mcs_table); - if (pusch_config_pdu_0_0->target_code_rate == 0 || pusch_config_pdu_0_0->qam_mod_order == 0) { - LOG_W(MAC, "Invalid code rate or Mod order, likely due to unexpected UL DCI. Ignoring DCI! \n"); - return -1; - } - - /* NDI */ - pusch_config_pdu_0_0->pusch_data.new_data_indicator = dci->ndi; - /* RV */ - pusch_config_pdu_0_0->pusch_data.rv_index = dci->rv; - /* HARQ_PROCESS_NUMBER */ - pusch_config_pdu_0_0->pusch_data.harq_process_id = dci->harq_pid; - /* TPC_PUSCH */ - // according to TS 38.213 Table Table 7.1.1-1 - if (dci->tpc == 0) { - pusch_config_pdu_0_0->absolute_delta_PUSCH = -4; - } - if (dci->tpc == 1) { - pusch_config_pdu_0_0->absolute_delta_PUSCH = -1; - } - if (dci->tpc == 2) { - pusch_config_pdu_0_0->absolute_delta_PUSCH = 1; - } - if (dci->tpc == 3) { - pusch_config_pdu_0_0->absolute_delta_PUSCH = 4; - } - /* SUL_IND_0_0 */ // To be implemented, FIXME!!! - - ul_config->slot = slot_tx; - ul_config->sfn = frame_tx; - ul_config->number_pdus = ul_config->number_pdus + 1; - LOG_D(MAC, "nr_ue_process_dci(): Calculated frame and slot for pusch Tx: %d.%d, number of pdus %d\n", ul_config->sfn, ul_config->slot, ul_config->number_pdus); break; + } - case NR_UL_DCI_FORMAT_0_1: + case NR_UL_DCI_FORMAT_0_1: { /* * with CRC scrambled by C-RNTI or CS-RNTI or SP-CSI-RNTI or new-RNTI * 0 IDENTIFIER_DCI_FORMATS: @@ -3038,381 +553,41 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr * 48 UL_SCH_IND * 49 PADDING_NR_DCI: (Note 2) If DCI format 0_0 is monitored in common search space */ - // Calculate the slot in which ULSCH should be scheduled. This is current slot + K2, - // where K2 is the offset between the slot in which UL DCI is received and the slot - // in which ULSCH should be scheduled. K2 is configured in RRC configuration. - - // Get the numerology to calculate the Tx frame and slot - mu = mac->ULbwp[0]->bwp_Common->genericParameters.subcarrierSpacing; - // Get slot offset K2 which will be used to calculate TX slot - k2 = get_k2(mac, dci->time_domain_assignment.val); - if (k2 < 0) // This can happen when a false DCI is received - return -1; - // Calculate TX slot and frame - slot_tx = (slot + k2) % nr_slots_per_frame[mu]; - frame_tx = ((slot + k2) > nr_slots_per_frame[mu]) ? (frame + 1) % 1024 : frame; - - // Get UL config request corresponding slot_tx - ul_config = get_ul_config_request(mac, slot_tx); - //AssertFatal(ul_config != NULL, "nr_ue_process_dci(): ul_config is NULL\n"); - if (!ul_config) { - LOG_W(MAC, "nr_ue_process_dci(): ul_config request is NULL. Probably due to unexpected UL DCI in frame.slot %d.%d. Ignoring DCI!\n",frame,slot); - return -1; + // TODO: + // - FIRST_DAI + // - SECOND_DAI + // - SRS_RESOURCE_IND + + // Schedule PUSCH + ret = nr_ue_pusch_scheduler(mac, is_Msg3, frame, slot, &frame_tx, &slot_tx, dci->time_domain_assignment.val); + + if (ret != -1){ + + // Get UL config request corresponding slot_tx + fapi_nr_ul_config_request_t *ul_config = get_ul_config_request(mac, slot_tx); + + if (!ul_config) { + LOG_W(MAC, "In %s: ul_config request is NULL. Probably due to unexpected UL DCI in frame.slot %d.%d. Ignoring DCI!\n", __FUNCTION__, frame, slot); + return -1; + } + + nfapi_nr_ue_pusch_pdu_t *pusch_config_pdu = &ul_config->ul_config_list[ul_config->number_pdus].pusch_config_pdu; + + fill_ul_config(ul_config, frame_tx, slot_tx, FAPI_NR_UL_CONFIG_TYPE_PUSCH); + + // Config PUSCH PDU + ret = nr_config_pusch_pdu(mac, pusch_config_pdu, dci, NULL, rnti, &dci_format); + + if (ret != -1 && ra->RA_active && mac->crnti){ + nr_ra_succeeded(module_id, frame, slot); + } + } - ul_config->ul_config_list[ul_config->number_pdus].pdu_type = FAPI_NR_UL_CONFIG_TYPE_PUSCH; - ul_config->ul_config_list[ul_config->number_pdus].pusch_config_pdu.rnti = rnti; - nfapi_nr_ue_pusch_pdu_t *pusch_config_pdu_0_1 = &ul_config->ul_config_list[ul_config->number_pdus].pusch_config_pdu; - /* IDENTIFIER_DCI_FORMATS */ - /* CARRIER_IND */ - /* SUL_IND_0_1 */ - /* BANDWIDTH_PART_IND */ - //pusch_config_pdu_0_1->bandwidth_part_ind = dci->bwp_indicator.val; - /* FREQ_DOM_RESOURCE_ASSIGNMENT_UL */ - if (nr_ue_process_dci_freq_dom_resource_assignment(pusch_config_pdu_0_1,NULL,n_RB_ULBWP,0,dci->frequency_domain_assignment.val) < 0) - return -1; - /* TIME_DOM_RESOURCE_ASSIGNMENT */ - if (nr_ue_process_dci_time_dom_resource_assignment(mac,pusch_config_pdu_0_1,NULL,dci->time_domain_assignment.val) < 0) - return -1; - /* FREQ_HOPPING_FLAG */ - if ((mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.resource_allocation != 0) && - (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.frequency_hopping !=0)) - pusch_config_pdu_0_1->frequency_hopping = dci->frequency_hopping_flag.val; - /* MCS */ - pusch_config_pdu_0_1->mcs_index = dci->mcs; - /* MCS TABLE */ - if (pusch_config->transformPrecoder == NULL) { - if (mac->scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg3_transformPrecoder == NULL) - pusch_config_pdu_0_1->transform_precoding = transform_precoder_disabled; - else - pusch_config_pdu_0_1->transform_precoding = transform_precoder_enabled; - } - else - pusch_config_pdu_0_1->transform_precoding = *pusch_config->transformPrecoder; - - if (pusch_config_pdu_0_1->transform_precoding == transform_precoder_disabled) - pusch_config_pdu_0_1->mcs_table = get_pusch_mcs_table(pusch_config->mcs_Table, 0, - dci_format, NR_RNTI_C, NR_SearchSpace__searchSpaceType_PR_ue_Specific, false); - else - pusch_config_pdu_0_1->mcs_table = get_pusch_mcs_table(pusch_config->mcs_TableTransformPrecoder, 1, - dci_format, NR_RNTI_C, NR_SearchSpace__searchSpaceType_PR_ue_Specific, false); - - pusch_config_pdu_0_1->target_code_rate = nr_get_code_rate_ul(pusch_config_pdu_0_1->mcs_index, pusch_config_pdu_0_1->mcs_table); - pusch_config_pdu_0_1->qam_mod_order = nr_get_Qm_ul(pusch_config_pdu_0_1->mcs_index, pusch_config_pdu_0_1->mcs_table); - if (pusch_config_pdu_0_1->target_code_rate == 0 || pusch_config_pdu_0_1->qam_mod_order == 0) { - LOG_W(MAC, "Invalid code rate or Mod order, likely due to unexpected UL DCI. Ignoring DCI! \n"); - return -1; - } - - /* NDI */ - pusch_config_pdu_0_1->pusch_data.new_data_indicator = dci->ndi; - /* RV */ - pusch_config_pdu_0_1->pusch_data.rv_index = dci->rv; - /* HARQ_PROCESS_NUMBER */ - pusch_config_pdu_0_1->pusch_data.harq_process_id = dci->harq_pid; - /* FIRST_DAI */ //To be implemented, FIXME!!! - /* SECOND_DAI */ //To be implemented, FIXME!!! - /* TPC_PUSCH */ - // according to TS 38.213 Table Table 7.1.1-1 - if (dci->tpc == 0) { - pusch_config_pdu_0_1->absolute_delta_PUSCH = -4; - } - if (dci->tpc == 1) { - pusch_config_pdu_0_1->absolute_delta_PUSCH = -1; - } - if (dci->tpc == 2) { - pusch_config_pdu_0_1->absolute_delta_PUSCH = 1; - } - if (dci->tpc == 3) { - pusch_config_pdu_0_1->absolute_delta_PUSCH = 4; - } - /* SRS_RESOURCE_IND */ - //FIXME!! - /* PRECOD_NBR_LAYERS */ - if ((mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.tx_config == tx_config_nonCodebook)); - // 0 bits if the higher layer parameter txConfig = nonCodeBook - if ((mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.tx_config == tx_config_codebook)){ - uint8_t n_antenna_port = 0; //FIXME!!! - if (n_antenna_port == 1); // 1 antenna port and the higher layer parameter txConfig = codebook 0 bits - if (n_antenna_port == 4){ // 4 antenna port and the higher layer parameter txConfig = codebook - // Table 7.3.1.1.2-2: transformPrecoder=disabled and maxRank = 2 or 3 or 4 - if ((mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.transform_precoder == transform_precoder_disabled) - && ((mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.max_rank == 2) || - (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.max_rank == 3) || - (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.max_rank == 4))){ - if (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.codebook_subset == codebook_subset_fullyAndPartialAndNonCoherent) { - pusch_config_pdu_0_1->nrOfLayers = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][0]; - pusch_config_pdu_0_1->transform_precoding = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][1]; - } - if (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.codebook_subset == codebook_subset_partialAndNonCoherent){ - pusch_config_pdu_0_1->nrOfLayers = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][2]; - pusch_config_pdu_0_1->transform_precoding = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][3]; - } - if (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.codebook_subset == codebook_subset_nonCoherent){ - pusch_config_pdu_0_1->nrOfLayers = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][4]; - pusch_config_pdu_0_1->transform_precoding = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][5]; - } - } - // Table 7.3.1.1.2-3: transformPrecoder= enabled, or transformPrecoder=disabled and maxRank = 1 - if (((mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.transform_precoder == transform_precoder_enabled) - || (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.transform_precoder == transform_precoder_disabled)) - && (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.max_rank == 1)){ - if (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.codebook_subset == codebook_subset_fullyAndPartialAndNonCoherent) { - pusch_config_pdu_0_1->nrOfLayers = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][6]; - pusch_config_pdu_0_1->transform_precoding = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][7]; - } - if (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.codebook_subset == codebook_subset_partialAndNonCoherent){ - pusch_config_pdu_0_1->nrOfLayers = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][8]; - pusch_config_pdu_0_1->transform_precoding = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][9]; - } - if (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.codebook_subset == codebook_subset_nonCoherent){ - pusch_config_pdu_0_1->nrOfLayers = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][10]; - pusch_config_pdu_0_1->transform_precoding = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][11]; - } - } - } - if (n_antenna_port == 4){ // 2 antenna port and the higher layer parameter txConfig = codebook - // Table 7.3.1.1.2-4: transformPrecoder=disabled and maxRank = 2 - if ((mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.transform_precoder == transform_precoder_disabled) - && (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.max_rank == 2)){ - if (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.codebook_subset == codebook_subset_fullyAndPartialAndNonCoherent) { - pusch_config_pdu_0_1->nrOfLayers = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][12]; - pusch_config_pdu_0_1->transform_precoding = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][13]; - } - if (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.codebook_subset == codebook_subset_nonCoherent){ - pusch_config_pdu_0_1->nrOfLayers = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][14]; - pusch_config_pdu_0_1->transform_precoding = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][15]; - } - } - // Table 7.3.1.1.2-5: transformPrecoder= enabled, or transformPrecoder= disabled and maxRank = 1 - if (((mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.transform_precoder == transform_precoder_enabled) - || (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.transform_precoder == transform_precoder_disabled)) - && (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.max_rank == 1)){ - if (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.codebook_subset == codebook_subset_fullyAndPartialAndNonCoherent) { - pusch_config_pdu_0_1->nrOfLayers = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][16]; - pusch_config_pdu_0_1->transform_precoding = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][17]; - } - if (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.codebook_subset == codebook_subset_nonCoherent){ - pusch_config_pdu_0_1->nrOfLayers = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][18]; - pusch_config_pdu_0_1->transform_precoding = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][19]; - } - } - } - } - -/*-------------------- Changed to enable Transform precoding in RF SIM------------------------------------------------*/ - - NR_DMRS_UplinkConfig_t *NR_DMRS_ulconfig = NULL; - - if (pusch_config_pdu_0_1->transform_precoding == transform_precoder_enabled) { - - mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.transform_precoder = transform_precoder_enabled; - - if(pusch_config->dmrs_UplinkForPUSCH_MappingTypeA != NULL) { - - NR_DMRS_ulconfig = pusch_config->dmrs_UplinkForPUSCH_MappingTypeA->choice.setup; - - if (NR_DMRS_ulconfig->dmrs_Type == NULL) - mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.dmrs_ul_for_pusch_mapping_type_a.dmrs_type = 1; - if (NR_DMRS_ulconfig->maxLength == NULL) - mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.dmrs_ul_for_pusch_mapping_type_a.max_length = 1; - - } else if(pusch_config->dmrs_UplinkForPUSCH_MappingTypeB != NULL) { - - NR_DMRS_ulconfig = pusch_config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup; - - if (NR_DMRS_ulconfig->dmrs_Type == NULL) - mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.dmrs_ul_for_pusch_mapping_type_b.dmrs_type = 1; - if (NR_DMRS_ulconfig->maxLength == NULL) - mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.dmrs_ul_for_pusch_mapping_type_b.max_length = 1; - - } - } else - mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.transform_precoder = transform_precoder_disabled; - - // mapping type b configured from RRC. TBD: Mapping type b is not handled in this function. - if ((mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.transform_precoder == transform_precoder_enabled) && - (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.dmrs_ul_for_pusch_mapping_type_b.dmrs_type == 1) && - (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.dmrs_ul_for_pusch_mapping_type_b.max_length == 1)) { // tables 7.3.1.1.2-6 - pusch_config_pdu_0_1->num_dmrs_cdm_grps_no_data = 2; - pusch_config_pdu_0_1->dmrs_ports = dci->antenna_ports.val; - } - - /*-------------------- ---------------------------------------------------------------------------------------------------------------*/ - - - /* ANTENNA_PORTS */ - uint8_t rank=0; // We need to initialize rank FIXME!!! - - if ((mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.transform_precoder == transform_precoder_enabled) && - (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.dmrs_ul_for_pusch_mapping_type_a.dmrs_type == 1) && - (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.dmrs_ul_for_pusch_mapping_type_a.max_length == 1)) { // tables 7.3.1.1.2-6 - pusch_config_pdu_0_1->num_dmrs_cdm_grps_no_data = 2; //TBC - pusch_config_pdu_0_1->dmrs_ports = dci->antenna_ports.val; //TBC - } - - if ((mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.transform_precoder == transform_precoder_enabled) && - (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.dmrs_ul_for_pusch_mapping_type_a.dmrs_type == 1) && - (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.dmrs_ul_for_pusch_mapping_type_a.max_length == 2)) { // tables 7.3.1.1.2-7 - pusch_config_pdu_0_1->num_dmrs_cdm_grps_no_data = 2; //TBC - pusch_config_pdu_0_1->dmrs_ports = (dci->antenna_ports.val > 3)?(dci->antenna_ports.val-4):(dci->antenna_ports.val); //TBC - //pusch_config_pdu_0_1->n_front_load_symb = (dci->antenna_ports > 3)?2:1; //FIXME - } - if ((mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.transform_precoder == transform_precoder_disabled) && - (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.dmrs_ul_for_pusch_mapping_type_a.dmrs_type == 1) && - (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.dmrs_ul_for_pusch_mapping_type_a.max_length == 1)) { // tables 7.3.1.1.2-8/9/10/11 - if (rank == 1){ - pusch_config_pdu_0_1->num_dmrs_cdm_grps_no_data = (dci->antenna_ports.val > 1)?2:1; //TBC - pusch_config_pdu_0_1->dmrs_ports = (dci->antenna_ports.val > 1)?(dci->antenna_ports.val-2):(dci->antenna_ports.val); //TBC - } - if (rank == 2){ - pusch_config_pdu_0_1->num_dmrs_cdm_grps_no_data = (dci->antenna_ports.val > 0)?2:1; //TBC - pusch_config_pdu_0_1->dmrs_ports = 0; //FIXME - //pusch_config_pdu_0_1->dmrs_ports[0] = (dci->antenna_ports > 1)?(dci->antenna_ports > 2 ?0:2):0; - //pusch_config_pdu_0_1->dmrs_ports[1] = (dci->antenna_ports > 1)?(dci->antenna_ports > 2 ?2:3):1; - } - if (rank == 3){ - pusch_config_pdu_0_1->num_dmrs_cdm_grps_no_data = 2; //TBC - pusch_config_pdu_0_1->dmrs_ports = 0; //FIXME - //pusch_config_pdu_0_1->dmrs_ports[0] = 0; - //pusch_config_pdu_0_1->dmrs_ports[1] = 1; - //pusch_config_pdu_0_1->dmrs_ports[2] = 2; - } - if (rank == 4){ - pusch_config_pdu_0_1->num_dmrs_cdm_grps_no_data = 2; //TBC - pusch_config_pdu_0_1->dmrs_ports = 0; //FIXME - //pusch_config_pdu_0_1->dmrs_ports[0] = 0; - //pusch_config_pdu_0_1->dmrs_ports[1] = 1; - //pusch_config_pdu_0_1->dmrs_ports[2] = 2; - //pusch_config_pdu_0_1->dmrs_ports[3] = 3; - } - } - if ((mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.transform_precoder == transform_precoder_disabled) && - (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.dmrs_ul_for_pusch_mapping_type_a.dmrs_type == 1) && - (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.dmrs_ul_for_pusch_mapping_type_a.max_length == 2)) { // tables 7.3.1.1.2-12/13/14/15 - if (rank == 1){ - pusch_config_pdu_0_1->num_dmrs_cdm_grps_no_data = (dci->antenna_ports.val > 1)?2:1; //TBC - pusch_config_pdu_0_1->dmrs_ports = (dci->antenna_ports.val > 1)?(dci->antenna_ports.val > 5 ?(dci->antenna_ports.val-6):(dci->antenna_ports.val-2)):dci->antenna_ports.val; //TBC - //pusch_config_pdu_0_1->n_front_load_symb = (dci->antenna_ports.val > 6)?2:1; //FIXME - } - if (rank == 2){ - pusch_config_pdu_0_1->num_dmrs_cdm_grps_no_data = (dci->antenna_ports.val > 0)?2:1; //TBC - pusch_config_pdu_0_1->dmrs_ports = 0; //FIXME - //pusch_config_pdu_0_1->dmrs_ports[0] = table_7_3_1_1_2_13[dci->antenna_ports.val][1]; - //pusch_config_pdu_0_1->dmrs_ports[1] = table_7_3_1_1_2_13[dci->antenna_ports.val][2]; - //pusch_config_pdu_0_1->n_front_load_symb = (dci->antenna_ports.val > 3)?2:1; // FIXME - } - if (rank == 3){ - pusch_config_pdu_0_1->num_dmrs_cdm_grps_no_data = 2; //TBC - pusch_config_pdu_0_1->dmrs_ports = 0; //FIXME - //pusch_config_pdu_0_1->dmrs_ports[0] = table_7_3_1_1_2_14[dci->antenna_ports.val][1]; - //pusch_config_pdu_0_1->dmrs_ports[1] = table_7_3_1_1_2_14[dci->antenna_ports.val][2]; - //pusch_config_pdu_0_1->dmrs_ports[2] = table_7_3_1_1_2_14[dci->antenna_ports.val][3]; - //pusch_config_pdu_0_1->n_front_load_symb = (dci->antenna_ports.val > 1)?2:1; //FIXME - } - if (rank == 4){ - pusch_config_pdu_0_1->num_dmrs_cdm_grps_no_data = 2; //TBC - pusch_config_pdu_0_1->dmrs_ports = 0; //FIXME - //pusch_config_pdu_0_1->dmrs_ports[0] = table_7_3_1_1_2_15[dci->antenna_ports.val][1]; - //pusch_config_pdu_0_1->dmrs_ports[1] = table_7_3_1_1_2_15[dci->antenna_ports.val][2]; - //pusch_config_pdu_0_1->dmrs_ports[2] = table_7_3_1_1_2_15[dci->antenna_ports.val][3]; - //pusch_config_pdu_0_1->dmrs_ports[3] = table_7_3_1_1_2_15[dci->antenna_ports.val][4]; - //pusch_config_pdu_0_1->n_front_load_symb = (dci->antenna_ports.val > 1)?2:1; //FIXME - } - } - if ((mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.transform_precoder == transform_precoder_disabled) && - (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.dmrs_ul_for_pusch_mapping_type_a.dmrs_type == 2) && - (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.dmrs_ul_for_pusch_mapping_type_a.max_length == 1)) { // tables 7.3.1.1.2-16/17/18/19 - if (rank == 1){ - pusch_config_pdu_0_1->num_dmrs_cdm_grps_no_data = (dci->antenna_ports.val > 1)?((dci->antenna_ports.val > 5)?3:2):1; //TBC - pusch_config_pdu_0_1->dmrs_ports = (dci->antenna_ports.val > 1)?(dci->antenna_ports.val > 5 ?(dci->antenna_ports.val-6):(dci->antenna_ports.val-2)):dci->antenna_ports.val; //TBC - } - if (rank == 2){ - pusch_config_pdu_0_1->num_dmrs_cdm_grps_no_data = (dci->antenna_ports.val > 0)?((dci->antenna_ports.val > 2)?3:2):1; //TBC - pusch_config_pdu_0_1->dmrs_ports = 0; //FIXME - //pusch_config_pdu_0_1->dmrs_ports[0] = table_7_3_1_1_2_17[dci->antenna_ports.val][1]; - //pusch_config_pdu_0_1->dmrs_ports[1] = table_7_3_1_1_2_17[dci->antenna_ports.val][2]; - } - if (rank == 3){ - pusch_config_pdu_0_1->num_dmrs_cdm_grps_no_data = (dci->antenna_ports.val > 0)?3:2; //TBC - pusch_config_pdu_0_1->dmrs_ports = 0; //FIXME - //pusch_config_pdu_0_1->dmrs_ports[0] = table_7_3_1_1_2_18[dci->antenna_ports.val][1]; - //pusch_config_pdu_0_1->dmrs_ports[1] = table_7_3_1_1_2_18[dci->antenna_ports.val][2]; - //pusch_config_pdu_0_1->dmrs_ports[2] = table_7_3_1_1_2_18[dci->antenna_ports.val][3]; - } - if (rank == 4){ - pusch_config_pdu_0_1->num_dmrs_cdm_grps_no_data = dci->antenna_ports.val + 2; //TBC - pusch_config_pdu_0_1->dmrs_ports = 0; //FIXME - //pusch_config_pdu_0_1->dmrs_ports[0] = 0; - //pusch_config_pdu_0_1->dmrs_ports[1] = 1; - //pusch_config_pdu_0_1->dmrs_ports[2] = 2; - //pusch_config_pdu_0_1->dmrs_ports[3] = 3; - } - } - if ((mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.transform_precoder == transform_precoder_disabled) && - (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.dmrs_ul_for_pusch_mapping_type_a.dmrs_type == 2) && - (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.dmrs_ul_for_pusch_mapping_type_a.max_length == 2)) { // tables 7.3.1.1.2-20/21/22/23 - if (rank == 1){ - pusch_config_pdu_0_1->num_dmrs_cdm_grps_no_data = table_7_3_1_1_2_20[dci->antenna_ports.val][0]; //TBC - pusch_config_pdu_0_1->dmrs_ports = table_7_3_1_1_2_20[dci->antenna_ports.val][1]; //TBC - //pusch_config_pdu_0_1->n_front_load_symb = table_7_3_1_1_2_20[dci->antenna_ports.val][2]; //FIXME - } - if (rank == 2){ - pusch_config_pdu_0_1->num_dmrs_cdm_grps_no_data = table_7_3_1_1_2_21[dci->antenna_ports.val][0]; //TBC - pusch_config_pdu_0_1->dmrs_ports = 0; //FIXME - //pusch_config_pdu_0_1->dmrs_ports[0] = table_7_3_1_1_2_21[dci->antenna_ports.val][1]; - //pusch_config_pdu_0_1->dmrs_ports[1] = table_7_3_1_1_2_21[dci->antenna_ports.val][2]; - //pusch_config_pdu_0_1->n_front_load_symb = table_7_3_1_1_2_21[dci->antenna_ports.val][3]; //FIXME - } - if (rank == 3){ - pusch_config_pdu_0_1->num_dmrs_cdm_grps_no_data = table_7_3_1_1_2_22[dci->antenna_ports.val][0]; //TBC - pusch_config_pdu_0_1->dmrs_ports = 0; //FIXME - //pusch_config_pdu_0_1->dmrs_ports[0] = table_7_3_1_1_2_22[dci->antenna_ports.val][1]; - //pusch_config_pdu_0_1->dmrs_ports[1] = table_7_3_1_1_2_22[dci->antenna_ports.val][2]; - //pusch_config_pdu_0_1->dmrs_ports[2] = table_7_3_1_1_2_22[dci->antenna_ports.val][3]; - //pusch_config_pdu_0_1->n_front_load_symb = table_7_3_1_1_2_22[dci->antenna_ports.val][4]; //FIXME - } - if (rank == 4){ - pusch_config_pdu_0_1->num_dmrs_cdm_grps_no_data = table_7_3_1_1_2_23[dci->antenna_ports.val][0]; //TBC - pusch_config_pdu_0_1->dmrs_ports = 0; //FIXME - //pusch_config_pdu_0_1->dmrs_ports[0] = table_7_3_1_1_2_23[dci->antenna_ports.val][1]; - //pusch_config_pdu_0_1->dmrs_ports[1] = table_7_3_1_1_2_23[dci->antenna_ports.val][2]; - //pusch_config_pdu_0_1->dmrs_ports[2] = table_7_3_1_1_2_23[dci->antenna_ports.val][3]; - //pusch_config_pdu_0_1->dmrs_ports[3] = table_7_3_1_1_2_23[dci->antenna_ports.val][4]; - //pusch_config_pdu_0_1->n_front_load_symb = table_7_3_1_1_2_23[dci->antenna_ports.val][5]; //FIXME - } - } - /* SRS_REQUEST */ - // if SUL is supported in the cell, there is an additional bit in thsi field and the value of this bit represents table 7.1.1.1-1 TS 38.212 FIXME!!! - //pusch_config_pdu_0_1->srs_config.aperiodicSRS_ResourceTrigger = (dci->srs_request.val & 0x11); // as per Table 7.3.1.1.2-24 TS 38.212 //FIXME - /* CSI_REQUEST */ - //pusch_config_pdu_0_1->csi_reportTriggerSize = dci->csi_request.val; //FIXME - /* CBGTI */ - //pusch_config_pdu_0_1->maxCodeBlockGroupsPerTransportBlock = dci->cbgti.val; //FIXME - /* PTRS_DMRS */ - if (((mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.transform_precoder == transform_precoder_disabled) && - (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.dmrs_ul_for_pusch_mapping_type_a.ptrs_uplink_config == 0)) || - ((mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.transform_precoder == transform_precoder_enabled) && - (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.max_rank == 1))){ - } else { - //pusch_config_pdu_0_1->ptrs_dmrs_association_port = dci->ptrs_dmrs_association.val; //FIXME - } - /* BETA_OFFSET_IND */ - // Table 9.3-3 in [5, TS 38.213] - //pusch_config_pdu_0_1->beta_offset_ind = dci->beta_offset_indicator.val; //FIXME - /* DMRS_SEQ_INI */ - // FIXME!! - /* UL_SCH_IND */ - // A value of "1" indicates UL-SCH shall be transmitted on the PUSCH and - // a value of "0" indicates UL-SCH shall not be transmitted on the PUSCH - - ul_config->slot = slot_tx; - ul_config->sfn = frame_tx; - ul_config->number_pdus = ul_config->number_pdus + 1; - LOG_D(MAC, "nr_ue_process_dci(): Calculated frame and slot for pusch Tx: %d.%d, number of pdus %d\n", ul_config->sfn, ul_config->slot, ul_config->number_pdus); break; + } - case NR_DL_DCI_FORMAT_1_0: + case NR_DL_DCI_FORMAT_1_0: { /* * with CRC scrambled by C-RNTI or CS-RNTI or new-RNTI * 0 IDENTIFIER_DCI_FORMATS: @@ -3466,6 +641,7 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr dl_config->dl_config_list[dl_config->number_pdus].dlsch_config_pdu.rnti = rnti; fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config_pdu_1_0 = &dl_config->dl_config_list[dl_config->number_pdus].dlsch_config_pdu.dlsch_config_rel15; + NR_PDSCH_Config_t *pdsch_config=mac->DLbwp[0]->bwp_Dedicated->pdsch_Config->choice.setup; uint16_t BWPSize = 0; if(rnti == SI_RNTI) { @@ -3476,24 +652,28 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr pdsch_config->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_AdditionalPosition = NULL; // For PDSCH with mapping type A, the UE shall assume dmrs-AdditionalPosition='pos2' BWPSize = dlsch_config_pdu_1_0->BWPSize; } else { - if (mac->RA_window_cnt >= 0 && rnti == mac->ra_rnti){ + if (ra->RA_window_cnt >= 0 && rnti == ra->ra_rnti){ dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_DL_CONFIG_TYPE_RA_DLSCH; } else { dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_DL_CONFIG_TYPE_DLSCH; } - dlsch_config_pdu_1_0->BWPSize = NRRIV2BW(mac->DLbwp[0]->bwp_Common->genericParameters.locationAndBandwidth,275); - dlsch_config_pdu_1_0->BWPStart = NRRIV2PRBOFFSET(mac->DLbwp[0]->bwp_Common->genericParameters.locationAndBandwidth,275); + dlsch_config_pdu_1_0->BWPSize = NRRIV2BW(mac->DLbwp[0]->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + dlsch_config_pdu_1_0->BWPStart = NRRIV2PRBOFFSET(mac->DLbwp[0]->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); dlsch_config_pdu_1_0->SubcarrierSpacing = mac->DLbwp[0]->bwp_Common->genericParameters.subcarrierSpacing; BWPSize = n_RB_DLBWP; } /* IDENTIFIER_DCI_FORMATS */ /* FREQ_DOM_RESOURCE_ASSIGNMENT_DL */ - if (nr_ue_process_dci_freq_dom_resource_assignment(NULL,dlsch_config_pdu_1_0,0,BWPSize,dci->frequency_domain_assignment.val) < 0) + if (nr_ue_process_dci_freq_dom_resource_assignment(NULL,dlsch_config_pdu_1_0,0,BWPSize,dci->frequency_domain_assignment.val) < 0) { + LOG_W(MAC, "[%d.%d] Invalid frequency_domain_assignment. Possibly due to false DCI. Ignoring DCI!\n", frame, slot); return -1; + } /* TIME_DOM_RESOURCE_ASSIGNMENT */ - if (nr_ue_process_dci_time_dom_resource_assignment(mac,NULL,dlsch_config_pdu_1_0,dci->time_domain_assignment.val) < 0) + if (nr_ue_process_dci_time_dom_resource_assignment(mac,NULL,dlsch_config_pdu_1_0,dci->time_domain_assignment.val) < 0) { + LOG_W(MAC, "[%d.%d] Invalid time_domain_assignment. Possibly due to false DCI. Ignoring DCI!\n", frame, slot); return -1; + } /* dmrs symbol positions*/ dlsch_config_pdu_1_0->dlDmrsSymbPos = fill_dmrs_mask(pdsch_config, mac->scc->dmrs_TypeA_Position, @@ -3512,7 +692,7 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr dlsch_config_pdu_1_0->mcs = dci->mcs; // Basic sanity check for MCS value to check for a false or erroneous DCI if (dlsch_config_pdu_1_0->mcs > 28) { - LOG_W(MAC, "MCS value % d out of bounds! Possibly due to false DCI. Ignoring DCI!!\n", dlsch_config_pdu_1_0->mcs); + LOG_W(MAC, "[%d.%d] MCS value %d out of bounds! Possibly due to false DCI. Ignoring DCI!\n", frame, slot, dlsch_config_pdu_1_0->mcs); return -1; } /* NDI (only if CRC scrambled by C-RNTI or CS-RNTI or new-RNTI or TC-RNTI)*/ @@ -3555,7 +735,7 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr } } if (!valid) { - LOG_W(MAC, "pucch_resource_indicator value %d is out of bounds. Possibly due to false DCI. Ignoring DCI!\n", dlsch_config_pdu_1_0->pucch_resource_id); + LOG_W(MAC, "[%d.%d] pucch_resource_indicator value %d is out of bounds. Possibly due to false DCI. Ignoring DCI!\n", frame, slot, dlsch_config_pdu_1_0->pucch_resource_id); return -1; } @@ -3591,8 +771,9 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr dl_config->number_pdus = dl_config->number_pdus + 1; break; + } - case NR_DL_DCI_FORMAT_1_1: + case NR_DL_DCI_FORMAT_1_1: { /* * with CRC scrambled by C-RNTI or CS-RNTI or new-RNTI * 0 IDENTIFIER_DCI_FORMATS: @@ -3622,6 +803,15 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr * 44 CBGFI: * 47 DMRS_SEQ_INI: */ + + if (dci->bwp_indicator.val != 1) { + LOG_W(MAC, "[%d.%d] bwp_indicator != 1! Possibly due to false DCI. Ignoring DCI!\n", frame, slot); + return -1; + } + config_bwp_ue(mac, &dci->bwp_indicator.val, &dci_format); + NR_BWP_Id_t dl_bwp_id = mac->DL_BWP_Id; + NR_PDSCH_Config_t *pdsch_config=mac->DLbwp[dl_bwp_id-1]->bwp_Dedicated->pdsch_Config->choice.setup; + dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_DL_CONFIG_TYPE_DLSCH; dl_config->dl_config_list[dl_config->number_pdus].dlsch_config_pdu.rnti = rnti; fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config_pdu_1_1 = &dl_config->dl_config_list[dl_config->number_pdus].dlsch_config_pdu.dlsch_config_rel15; @@ -3630,16 +820,20 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr /* BANDWIDTH_PART_IND */ // dlsch_config_pdu_1_1->bandwidth_part_ind = dci->bandwidth_part_ind; /* FREQ_DOM_RESOURCE_ASSIGNMENT_DL */ - if (nr_ue_process_dci_freq_dom_resource_assignment(NULL,dlsch_config_pdu_1_1,0,n_RB_DLBWP,dci->frequency_domain_assignment.val) < 0) + if (nr_ue_process_dci_freq_dom_resource_assignment(NULL,dlsch_config_pdu_1_1,0,n_RB_DLBWP,dci->frequency_domain_assignment.val) < 0) { + LOG_W(MAC, "[%d.%d] Invalid frequency_domain_assignment. Possibly due to false DCI. Ignoring DCI!\n", frame, slot); return -1; + } /* TIME_DOM_RESOURCE_ASSIGNMENT */ - if (nr_ue_process_dci_time_dom_resource_assignment(mac,NULL,dlsch_config_pdu_1_1,dci->time_domain_assignment.val) < 0) + if (nr_ue_process_dci_time_dom_resource_assignment(mac,NULL,dlsch_config_pdu_1_1,dci->time_domain_assignment.val) < 0) { + LOG_W(MAC, "[%d.%d] Invalid time_domain_assignment. Possibly due to false DCI. Ignoring DCI!\n", frame, slot); return -1; + } /* dmrs symbol positions*/ dlsch_config_pdu_1_1->dlDmrsSymbPos = fill_dmrs_mask(pdsch_config, mac->scc->dmrs_TypeA_Position, dlsch_config_pdu_1_1->number_symbols); - dlsch_config_pdu_1_1->dmrsConfigType = mac->DLbwp[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_Type == NULL ? 0 : 1; + dlsch_config_pdu_1_1->dmrsConfigType = mac->DLbwp[dl_bwp_id-1]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_Type == NULL ? 0 : 1; /* TODO: fix number of DM-RS CDM groups without data according to subclause 5.1.6.2 of 3GPP TS 38.214, using tables 7.3.1.2.2-1, 7.3.1.2.2-2, 7.3.1.2.2-3, 7.3.1.2.2-4 of 3GPP TS 38.212 */ dlsch_config_pdu_1_1->n_dmrs_cdm_groups = 1; @@ -3656,7 +850,7 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr dlsch_config_pdu_1_1->mcs = dci->mcs; // Basic sanity check for MCS value to check for a false or erroneous DCI if (dlsch_config_pdu_1_1->mcs > 28) { - LOG_W(MAC, "MCS value % d out of bounds! Possibly due to false DCI. Ignoring DCI!!\n", dlsch_config_pdu_1_1->mcs); + LOG_W(MAC, "[%d.%d] MCS value %d out of bounds! Possibly due to false DCI. Ignoring DCI!\n", frame, slot, dlsch_config_pdu_1_1->mcs); return -1; } /* NDI (for transport block 1)*/ @@ -3667,7 +861,7 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr dlsch_config_pdu_1_1->tb2_mcs = dci->mcs2.val; // Basic sanity check for MCS value to check for a false or erroneous DCI if (dlsch_config_pdu_1_1->tb2_mcs > 28) { - LOG_W(MAC, "MCS value % d out of bounds! Possibly due to false DCI. Ignoring DCI!!\n", dlsch_config_pdu_1_1->tb2_mcs); + LOG_W(MAC, "[%d.%d] MCS value %d out of bounds! Possibly due to false DCI. Ignoring DCI!\n", frame, slot, dlsch_config_pdu_1_1->tb2_mcs); return -1; } /* NDI (for transport block 2)*/ @@ -3696,13 +890,14 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr } } if (!valid) { - LOG_W(MAC, "pucch_resource_indicator value %d is out of bounds. Possibly due to false DCI. Ignoring DCI!\n", dlsch_config_pdu_1_1->pucch_resource_id); + LOG_W(MAC, "[%d.%d] pucch_resource_indicator value %d is out of bounds. Possibly due to false DCI. Ignoring DCI!\n", frame, slot, dlsch_config_pdu_1_1->pucch_resource_id); return -1; } /* PDSCH_TO_HARQ_FEEDBACK_TIME_IND */ // according to TS 38.213 Table 9.2.3-1 - dlsch_config_pdu_1_1->pdsch_to_harq_feedback_time_ind = mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->dl_DataToUL_ACK->list.array[dci->pdsch_to_harq_feedback_timing_indicator.val][0]; + NR_BWP_Id_t ul_bwp_id = mac->UL_BWP_Id; + dlsch_config_pdu_1_1->pdsch_to_harq_feedback_time_ind = mac->ULbwp[ul_bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->dl_DataToUL_ACK->list.array[dci->pdsch_to_harq_feedback_timing_indicator.val][0]; /* ANTENNA_PORTS */ uint8_t n_codewords = 1; // FIXME!!! if ((mac->phy_config.config_req.dl_bwp_dedicated.pdsch_config_dedicated.dmrs_dl_for_pdsch_mapping_type_a.dmrs_type == 1) && @@ -3807,8 +1002,8 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr /* TODO same calculation for MCS table as done in UL */ dlsch_config_pdu_1_1->mcs_table = (pdsch_config->mcs_Table) ? (*pdsch_config->mcs_Table + 1) : 0; /*PTRS configuration */ - if(mac->DLbwp[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS != NULL) { - valid_ptrs_setup = set_dl_ptrs_values(mac->DLbwp[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup, + if(mac->DLbwp[dl_bwp_id-1]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS != NULL) { + valid_ptrs_setup = set_dl_ptrs_values(mac->DLbwp[dl_bwp_id-1]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup, dlsch_config_pdu_1_1->number_rbs, dlsch_config_pdu_1_1->mcs, dlsch_config_pdu_1_1->mcs_table, &dlsch_config_pdu_1_1->PTRSFreqDensity,&dlsch_config_pdu_1_1->PTRSTimeDensity, &dlsch_config_pdu_1_1->PTRSPortIndex,&dlsch_config_pdu_1_1->nEpreRatioOfPDSCHToPTRS, @@ -3819,6 +1014,7 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr } break; + } case NR_DL_DCI_FORMAT_2_0: break; @@ -3852,7 +1048,9 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr /// else normal DL-SCH grant } - return 0; + + return ret; + } int8_t nr_ue_get_SR(module_id_t module_idP, int CC_id, frame_t frameP, uint8_t eNB_id, uint16_t rnti, sub_frame_t subframe){ @@ -3860,28 +1058,10 @@ int8_t nr_ue_get_SR(module_id_t module_idP, int CC_id, frame_t frameP, uint8_t e return 0; } -void nr_ue_send_sdu(module_id_t module_idP, - uint8_t CC_id, - frame_t frameP, - int slotP, - uint8_t * pdu, uint16_t pdu_len, uint8_t gNB_index, - NR_UL_TIME_ALIGNMENT_t *ul_time_alignment){ - - LOG_D(MAC, "Handling PDU frame %d slot %d\n", frameP, slotP); - - uint8_t * pduP = pdu; +void nr_ue_send_sdu(nr_downlink_indication_t *dl_info, NR_UL_TIME_ALIGNMENT_t *ul_time_alignment, int pdu_id){ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_SDU, VCD_FUNCTION_IN); - //LOG_D(MAC,"sdu: %x.%x.%x\n",sdu[0],sdu[1],sdu[2]); - - /* - #ifdef DEBUG_HEADER_PARSING - LOG_D(MAC, "[UE %d] ue_send_sdu : Frame %d gNB_index %d : num_ce %d num_sdu %d\n", - module_idP, frameP, gNB_index, num_ce, num_sdu); - #endif - */ - #if defined(ENABLE_MAC_PAYLOAD_DEBUG) LOG_T(MAC, "[UE %d] First 32 bytes of DLSCH : \n", module_idP); for (i = 0; i < 32; i++) { @@ -3890,10 +1070,20 @@ void nr_ue_send_sdu(module_id_t module_idP, LOG_T(MAC, "\n"); #endif + LOG_D(MAC, "In %s [%d.%d] Handling DLSCH PDU...\n", __FUNCTION__, dl_info->frame, dl_info->slot); + // Processing MAC PDU // it parses MAC CEs subheaders, MAC CEs, SDU subheaderds and SDUs - if (pduP != NULL) - nr_ue_process_mac_pdu(module_idP, CC_id, frameP, pduP, pdu_len, gNB_index, ul_time_alignment); + switch (dl_info->rx_ind->rx_indication_body[pdu_id].pdu_type){ + case FAPI_NR_RX_PDU_TYPE_DLSCH: + nr_ue_process_mac_pdu(dl_info, ul_time_alignment, pdu_id); + break; + case FAPI_NR_RX_PDU_TYPE_RAR: + nr_ue_process_rar(dl_info, ul_time_alignment, pdu_id); + break; + default: + break; + } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_SDU, VCD_FUNCTION_OUT); @@ -3906,48 +1096,43 @@ int get_n_rb(NR_UE_MAC_INST_t *mac, int rnti_type){ switch(rnti_type) { case NR_RNTI_RA: case NR_RNTI_TC: - case NR_RNTI_P: - if (mac->DLbwp[0]->bwp_Common->pdcch_ConfigCommon->choice.setup->controlResourceSetZero) { - uint8_t bwp_id = 1; + case NR_RNTI_P: { + NR_BWP_Id_t dl_bwp_id = mac->DL_BWP_Id; + if (mac->DLbwp[dl_bwp_id-1]->bwp_Common->pdcch_ConfigCommon->choice.setup->controlResourceSetZero) { uint8_t coreset_id = 0; // assuming controlResourceSetId is 0 for controlResourceSetZero - NR_ControlResourceSet_t *coreset = mac->coreset[bwp_id - 1][coreset_id]; + NR_ControlResourceSet_t *coreset = mac->coreset[dl_bwp_id-1][coreset_id]; get_coreset_rballoc(coreset->frequencyDomainResources.buf,&N_RB,&start_RB); } else { - N_RB = NRRIV2BW(mac->scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, 275); + N_RB = NRRIV2BW(mac->scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); } break; + } case NR_RNTI_SI: N_RB = mac->type0_PDCCH_CSS_config.num_rbs; break; case NR_RNTI_C: - N_RB = NRRIV2BW(mac->DLbwp[0]->bwp_Common->genericParameters.locationAndBandwidth, 275); - break; + N_RB = NRRIV2BW(mac->DLbwp[0]->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + break; } return N_RB; } -int nr_extract_dci_info(NR_UE_MAC_INST_t *mac, - int dci_format, +uint8_t nr_extract_dci_info(NR_UE_MAC_INST_t *mac, + uint8_t dci_format, uint8_t dci_size, uint16_t rnti, uint64_t *dci_pdu, dci_pdu_rel15_t *dci_pdu_rel15) { - int rnti_type=-1; - if (rnti == mac->ra_rnti) rnti_type = NR_RNTI_RA; - else if (rnti == mac->crnti) rnti_type = NR_RNTI_C; - else if (rnti == mac->t_crnti) rnti_type = NR_RNTI_TC; - else if (rnti == 0xFFFE) rnti_type = NR_RNTI_P; - else if (rnti == 0xFFFF) rnti_type = NR_RNTI_SI; + int rnti_type = get_rnti_type(mac, rnti); - AssertFatal(rnti_type!=-1,"no identified/handled rnti\n"); AssertFatal(mac->DLbwp[0] != NULL, "DLbwp[0] shouldn't be null here!\n"); AssertFatal(mac->ULbwp[0] != NULL, "ULbwp[0] shouldn't be null here!\n"); int N_RB = get_n_rb(mac, rnti_type); int N_RB_UL = (mac->scg != NULL) ? - NRRIV2BW(mac->ULbwp[0]->bwp_Common->genericParameters.locationAndBandwidth,275) : - NRRIV2BW(mac->scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth,275); + NRRIV2BW(mac->ULbwp[0]->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE) : + NRRIV2BW(mac->scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); int pos=0; int fsize=0; @@ -4409,7 +1594,7 @@ int nr_extract_dci_info(NR_UE_MAC_INST_t *mac, // BWP Indicator pos+=dci_pdu_rel15->bwp_indicator.nbits; dci_pdu_rel15->bwp_indicator.val = (*dci_pdu>>(dci_size-pos))&((1<bwp_indicator.nbits)-1); - + // Freq domain assignment max 16 bit fsize = (int)ceil( log2( (N_RB_UL*(N_RB_UL+1))>>1 ) ); //pos+=dci_pdu_rel15->frequency_domain_assignment.nbits; @@ -4509,58 +1694,68 @@ int nr_extract_dci_info(NR_UE_MAC_INST_t *mac, return dci_format; } +/////////////////////////////////// +// brief: nr_ue_process_mac_pdu +// function: parsing DL PDU header +/////////////////////////////////// +// Header for DLSCH: +// Except: +// - DL-SCH: fixed-size MAC CE(known by LCID) +// - DL-SCH: padding +// +// |0|1|2|3|4|5|6|7| bit-wise +// |R|F| LCID | +// | L | +// |0|1|2|3|4|5|6|7| bit-wise +// |R|F| LCID | +// | L | +// | L | +//////////////////////////////// +// Header for DLSCH: +// - DLSCH: fixed-size MAC CE(known by LCID) +// - DLSCH: padding, for single/multiple 1-oct padding CE(s) +// +// |0|1|2|3|4|5|6|7| bit-wise +// |R|R| LCID | +// LCID: The Logical Channel ID field identifies the logical channel instance of the corresponding MAC SDU or the type of the corresponding MAC CE or padding as described +// in Tables 6.2.1-1 and 6.2.1-2 for the DL-SCH and UL-SCH respectively. There is one LCID field per MAC subheader. The LCID field size is 6 bits; +// L: The Length field indicates the length of the corresponding MAC SDU or variable-sized MAC CE in bytes. There is one L field per MAC subheader except for subheaders +// corresponding to fixed-sized MAC CEs and padding. The size of the L field is indicated by the F field; +// F: lenght of L is 0:8 or 1:16 bits wide +// R: Reserved bit, set to zero. +//////////////////////////////// +void nr_ue_process_mac_pdu(nr_downlink_indication_t *dl_info, + NR_UL_TIME_ALIGNMENT_t *ul_time_alignment, + int pdu_id){ -void nr_ue_process_mac_pdu(module_id_t module_idP, - uint8_t CC_id, - frame_t frameP, - uint8_t *pduP, - uint16_t mac_pdu_len, - uint8_t gNB_index, - NR_UL_TIME_ALIGNMENT_t *ul_time_alignment){ + uint8_t rx_lcid; + uint16_t mac_ce_len; + uint16_t mac_subheader_len; + uint16_t mac_sdu_len; + module_id_t module_idP = dl_info->module_id; + frame_t frameP = dl_info->frame; + int slot = dl_info->slot; + uint8_t *pduP = (dl_info->rx_ind->rx_indication_body + pdu_id)->pdsch_pdu.pdu; + uint16_t pdu_len = (dl_info->rx_ind->rx_indication_body + pdu_id)->pdsch_pdu.pdu_length; + uint8_t gNB_index = dl_info->gNB_index; + uint8_t CC_id = dl_info->cc_id; + uint8_t done = 0; + NR_UE_MAC_INST_t *mac = get_mac_inst(module_idP); + RA_config_t *ra = &mac->ra; - // This function is adapting code from the old - // parse_header(...) and ue_send_sdu(...) functions of OAI LTE + if (!pduP){ + return; + } - uint8_t *pdu_ptr = pduP, rx_lcid, done = 0; - int pdu_len = mac_pdu_len; - uint16_t mac_ce_len, mac_subheader_len, mac_sdu_len; - NR_UE_MAC_INST_t *mac = get_mac_inst(module_idP); + LOG_D(MAC, "In %s [%d.%d]: processing PDU %d of %d total number of PDUs...\n", __FUNCTION__, frameP, slot, pdu_id, dl_info->rx_ind->number_pdus); - //NR_UE_MAC_INST_t *UE_mac_inst = get_mac_inst(module_idP); - //uint8_t scs = UE_mac_inst->mib->subCarrierSpacingCommon; - //uint16_t bwp_ul_NB_RB = UE_mac_inst->initial_bwp_ul.N_RB; - - // For both DL/UL-SCH - // Except: - // - UL/DL-SCH: fixed-size MAC CE(known by LCID) - // - UL/DL-SCH: padding - // - UL-SCH: MSG3 48-bits - // |0|1|2|3|4|5|6|7| bit-wise - // |R|F| LCID | - // | L | - // |0|1|2|3|4|5|6|7| bit-wise - // |R|F| LCID | - // | L | - // | L | - - // For both DL/UL-SCH - // For: - // - UL/DL-SCH: fixed-size MAC CE(known by LCID) - // - UL/DL-SCH: padding, for single/multiple 1-oct padding CE(s) - // - UL-SCH: MSG3 48-bits - // |0|1|2|3|4|5|6|7| bit-wise - // |R|R| LCID | - // LCID: The Logical Channel ID field identifies the logical channel instance of the corresponding MAC SDU or the type of the corresponding MAC CE or padding as described in Tables 6.2.1-1 and 6.2.1-2 for the DL-SCH and UL-SCH respectively. There is one LCID field per MAC subheader. The LCID field size is 6 bits; - // L: The Length field indicates the length of the corresponding MAC SDU or variable-sized MAC CE in bytes. There is one L field per MAC subheader except for subheaders corresponding to fixed-sized MAC CEs and padding. The size of the L field is indicated by the F field; - // F: lenght of L is 0:8 or 1:16 bits wide - // R: Reserved bit, set to zero. while (!done && pdu_len > 0){ mac_ce_len = 0x0000; mac_subheader_len = 0x0001; // default to fixed-length subheader = 1-oct mac_sdu_len = 0x0000; - rx_lcid = ((NR_MAC_SUBHEADER_FIXED *)pdu_ptr)->LCID; + rx_lcid = ((NR_MAC_SUBHEADER_FIXED *)pduP)->LCID; //#ifdef DEBUG_HEADER_PARSING - LOG_D(MAC, "[UE] LCID %d, PDU length %d\n", ((NR_MAC_SUBHEADER_FIXED *)pdu_ptr)->LCID, pdu_len); + LOG_D(MAC, "[UE] LCID %d, PDU length %d\n", ((NR_MAC_SUBHEADER_FIXED *)pduP)->LCID, pdu_len); //#endif LOG_D(MAC, "[UE] LCID %d, PDU length %d\n", rx_lcid, pdu_len); @@ -4570,10 +1765,10 @@ void nr_ue_process_mac_pdu(module_id_t module_idP, case DL_SCH_LCID_CCCH: // MSG4 RRC Connection Setup 38.331 // varialbe length - mac_ce_len |= (uint16_t)((NR_MAC_SUBHEADER_SHORT *)pdu_ptr)->L; + mac_ce_len |= (uint16_t)((NR_MAC_SUBHEADER_SHORT *)pduP)->L; mac_subheader_len = 2; - if(((NR_MAC_SUBHEADER_SHORT *)pdu_ptr)->F){ - mac_ce_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pdu_ptr)->L2)<<8; + if(((NR_MAC_SUBHEADER_SHORT *)pduP)->F){ + mac_ce_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pduP)->L2)<<8; mac_subheader_len = 3; } @@ -4583,40 +1778,40 @@ void nr_ue_process_mac_pdu(module_id_t module_idP, // 38.321 Ch6.1.3.14 // varialbe length - mac_ce_len |= (uint16_t)((NR_MAC_SUBHEADER_SHORT *)pdu_ptr)->L; + mac_ce_len |= (uint16_t)((NR_MAC_SUBHEADER_SHORT *)pduP)->L; mac_subheader_len = 2; - if(((NR_MAC_SUBHEADER_SHORT *)pdu_ptr)->F){ - mac_ce_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pdu_ptr)->L2)<<8; + if(((NR_MAC_SUBHEADER_SHORT *)pduP)->F){ + mac_ce_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pduP)->L2)<<8; mac_subheader_len = 3; } break; case DL_SCH_LCID_APERIODIC_CSI_TRI_STATE_SUBSEL: // 38.321 Ch6.1.3.13 // varialbe length - mac_ce_len |= (uint16_t)((NR_MAC_SUBHEADER_SHORT *)pdu_ptr)->L; + mac_ce_len |= (uint16_t)((NR_MAC_SUBHEADER_SHORT *)pduP)->L; mac_subheader_len = 2; - if(((NR_MAC_SUBHEADER_SHORT *)pdu_ptr)->F){ - mac_ce_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pdu_ptr)->L2)<<8; + if(((NR_MAC_SUBHEADER_SHORT *)pduP)->F){ + mac_ce_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pduP)->L2)<<8; mac_subheader_len = 3; } break; case DL_SCH_LCID_SP_CSI_RS_CSI_IM_RES_SET_ACT: // 38.321 Ch6.1.3.12 // varialbe length - mac_ce_len |= (uint16_t)((NR_MAC_SUBHEADER_SHORT *)pdu_ptr)->L; + mac_ce_len |= (uint16_t)((NR_MAC_SUBHEADER_SHORT *)pduP)->L; mac_subheader_len = 2; - if(((NR_MAC_SUBHEADER_SHORT *)pdu_ptr)->F){ - mac_ce_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pdu_ptr)->L2)<<8; + if(((NR_MAC_SUBHEADER_SHORT *)pduP)->F){ + mac_ce_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pduP)->L2)<<8; mac_subheader_len = 3; } break; case DL_SCH_LCID_SP_SRS_ACTIVATION: // 38.321 Ch6.1.3.17 // varialbe length - mac_ce_len |= (uint16_t)((NR_MAC_SUBHEADER_SHORT *)pdu_ptr)->L; + mac_ce_len |= (uint16_t)((NR_MAC_SUBHEADER_SHORT *)pduP)->L; mac_subheader_len = 2; - if(((NR_MAC_SUBHEADER_SHORT *)pdu_ptr)->F){ - mac_ce_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pdu_ptr)->L2)<<8; + if(((NR_MAC_SUBHEADER_SHORT *)pduP)->F){ + mac_ce_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pduP)->L2)<<8; mac_subheader_len = 3; } break; @@ -4667,52 +1862,33 @@ void nr_ue_process_mac_pdu(module_id_t module_idP, // 38.321 Ch6.1.3.4 mac_ce_len = 1; - /*uint8_t ta_command = ((NR_MAC_CE_TA *)pdu_ptr)[1].TA_COMMAND; - uint8_t tag_id = ((NR_MAC_CE_TA *)pdu_ptr)[1].TAGID;*/ + /*uint8_t ta_command = ((NR_MAC_CE_TA *)pduP)[1].TA_COMMAND; + uint8_t tag_id = ((NR_MAC_CE_TA *)pduP)[1].TAGID;*/ ul_time_alignment->apply_ta = 1; - ul_time_alignment->ta_command = ((NR_MAC_CE_TA *)pdu_ptr)[1].TA_COMMAND; - ul_time_alignment->tag_id = ((NR_MAC_CE_TA *)pdu_ptr)[1].TAGID; + ul_time_alignment->ta_command = ((NR_MAC_CE_TA *)pduP)[1].TA_COMMAND; + ul_time_alignment->tag_id = ((NR_MAC_CE_TA *)pduP)[1].TAGID; /* #ifdef DEBUG_HEADER_PARSING - LOG_D(MAC, "[UE] CE %d : UE Timing Advance : %d\n", i, pdu_ptr[1]); + LOG_D(MAC, "[UE] CE %d : UE Timing Advance : %d\n", i, pduP[1]); #endif */ - LOG_D(MAC, "Received TA_COMMAND %u TAGID %u CC_id %d\n", ul_time_alignment->ta_command, ul_time_alignment->tag_id, CC_id); + LOG_I(MAC, "[%d.%d] Received TA_COMMAND %u TAGID %u CC_id %d\n", frameP, slot, ul_time_alignment->ta_command, ul_time_alignment->tag_id, CC_id); break; case DL_SCH_LCID_CON_RES_ID: - // 38.321 Ch6.1.3.3 + // Clause 5.1.5 and 6.1.3.3 of 3GPP TS 38.321 version 16.2.1 Release 16 // WIP todo: handle CCCH_pdu mac_ce_len = 6; - LOG_I(MAC, "[UE %d][RAPROC] Frame %d : received contention resolution msg: %x.%x.%x.%x.%x.%x, Terminating RA procedure\n", module_idP, frameP, pdu_ptr[0], pdu_ptr[1], pdu_ptr[2], pdu_ptr[3], pdu_ptr[4], pdu_ptr[5]); + LOG_I(MAC, "[UE %d][RAPROC] Frame %d : received contention resolution msg: %x.%x.%x.%x.%x.%x, Terminating RA procedure\n", module_idP, frameP, pduP[0], pduP[1], pduP[2], pduP[3], pduP[4], pduP[5]); - if (mac->RA_active == 1) { - LOG_I(MAC, "[UE %d][RAPROC] Frame %d : Clearing RA_active flag\n", module_idP, frameP); - mac->RA_active = 0; - // // check if RA procedure has finished completely (no contention) - // tx_sdu = &mac->CCCH_pdu.payload[3]; - // //Note: 3 assumes sizeof(SCH_SUBHEADER_SHORT) + PADDING CE, which is when UL-Grant has TBS >= 9 (64 bits) - // // (other possibility is 1 for TBS=7 (SCH_SUBHEADER_FIXED), or 2 for TBS=8 (SCH_SUBHEADER_FIXED+PADDING or // SCH_SUBHEADER_SHORT) - // for (i = 0; i < 6; i++) - // if (tx_sdu[i] != payload_ptr[i]) { - // LOG_E(MAC, "[UE %d][RAPROC] Contention detected, RA failed\n", module_idP); - // nr_ra_failed(module_idP, CC_id, eNB_index); - // mac->RA_contention_resolution_timer_active = 0; - // return; - // } - LOG_I(MAC, "[UE %d][RAPROC] Frame %d : Cleared contention resolution timer. Set C-RNTI to TC-RNTI\n", - module_idP, - frameP); - mac->RA_contention_resolution_timer_active = 0; - nr_ra_succeeded(module_idP, CC_id, gNB_index); - mac->crnti = mac->t_crnti; - mac->t_crnti = 0; - mac->ra_state = RA_SUCCEEDED; + if (ra->RA_active == 1) { + nr_ra_succeeded(module_idP, frameP, slot); } + break; case DL_SCH_LCID_PADDING: done = 1; @@ -4729,14 +1905,14 @@ void nr_ue_process_mac_pdu(module_id_t module_idP, default: // check if LCID is valid at current time. - if(((NR_MAC_SUBHEADER_SHORT *)pdu_ptr)->F){ - //mac_sdu_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pdu_ptr)->L2)<<8; + if(((NR_MAC_SUBHEADER_SHORT *)pduP)->F){ + //mac_sdu_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pduP)->L2)<<8; mac_subheader_len = 3; - mac_sdu_len = ((uint16_t)(((NR_MAC_SUBHEADER_LONG *) pdu_ptr)->L1 & 0x7f) << 8) - | ((uint16_t)((NR_MAC_SUBHEADER_LONG *) pdu_ptr)->L2 & 0xff); + mac_sdu_len = ((uint16_t)(((NR_MAC_SUBHEADER_LONG *) pduP)->L1 & 0x7f) << 8) + | ((uint16_t)((NR_MAC_SUBHEADER_LONG *) pduP)->L2 & 0xff); } else { - mac_sdu_len = (uint16_t)((NR_MAC_SUBHEADER_SHORT *)pdu_ptr)->L; + mac_sdu_len = (uint16_t)((NR_MAC_SUBHEADER_SHORT *)pduP)->L; mac_subheader_len = 2; } @@ -4746,7 +1922,7 @@ void nr_ue_process_mac_pdu(module_id_t module_idP, LOG_T(MAC, "[UE %d] First 32 bytes of DLSCH : \n", module_idP); for (i = 0; i < 32; i++) - LOG_T(MAC, "%x.", (pdu_ptr + mac_subheader_len)[i]); + LOG_T(MAC, "%x.", (pduP + mac_subheader_len)[i]); LOG_T(MAC, "\n"); #endif @@ -4761,7 +1937,7 @@ void nr_ue_process_mac_pdu(module_id_t module_idP, ENB_FLAG_NO, MBMS_FLAG_NO, rx_lcid, - (char *) (pdu_ptr + mac_subheader_len), + (char *) (pduP + mac_subheader_len), mac_sdu_len, 1, NULL); @@ -4772,7 +1948,7 @@ void nr_ue_process_mac_pdu(module_id_t module_idP, break; } - pdu_ptr += ( mac_subheader_len + mac_ce_len + mac_sdu_len ); + pduP += ( mac_subheader_len + mac_ce_len + mac_sdu_len ); pdu_len -= ( mac_subheader_len + mac_ce_len + mac_sdu_len ); if (pdu_len < 0) LOG_E(MAC, "[MAC] nr_ue_process_mac_pdu, residual mac pdu length %d < 0!\n", pdu_len); @@ -4870,7 +2046,7 @@ uint16_t nr_generate_ulsch_pdu(uint8_t *sdus_payload, if (crnti) { // MAC CE fixed subheader mac_pdu_ptr->R = 0; - mac_pdu_ptr->LCID = CRNTI; + mac_pdu_ptr->LCID = UL_SCH_LCID_C_RNTI; mac_pdu_ptr++; // C-RNTI MAC CE (2 octets) @@ -4954,125 +2130,200 @@ uint16_t nr_generate_ulsch_pdu(uint8_t *sdus_payload, return offset; } -uint8_t -nr_ue_get_sdu(module_id_t module_idP, int CC_id, frame_t frameP, - sub_frame_t subframe, uint8_t eNB_index, - uint8_t *ulsch_buffer, uint16_t buflen, uint8_t *access_mode) { - uint8_t total_rlc_pdu_header_len = 0; - int16_t buflen_remain = 0; - uint8_t lcid = 0; - uint16_t sdu_lengths[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; - uint8_t sdu_lcids[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; - uint16_t payload_offset = 0, num_sdus = 0; - uint8_t ulsch_sdus[MAX_ULSCH_PAYLOAD_BYTES]; - uint16_t sdu_length_total = 0; - //unsigned short post_padding = 0; - NR_UE_MAC_INST_t *mac = get_mac_inst(module_idP); +///////////////////////////////////// +// 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|// +///////////////////////////////////// +// TbD WIP Msg3 development ongoing +// - apply UL grant freq alloc & time alloc as per 8.2 TS 38.213 +// - apply tpc command +// WIP fix: +// - time domain indication hardcoded to 0 for k2 offset +// - extend TS 38.213 ch 8.3 Msg3 PUSCH +// - b buffer +// - ulsch power offset +// - optimize: mu_pusch, j and table_6_1_2_1_1_2_time_dom_res_alloc_A are already defined in nr_ue_procedures +int nr_ue_process_rar(nr_downlink_indication_t *dl_info, NR_UL_TIME_ALIGNMENT_t *ul_time_alignment, int pdu_id){ - rlc_buffer_occupancy_t lcid_buffer_occupancy_old = - 0, lcid_buffer_occupancy_new = 0; - LOG_D(MAC, - "[UE %d] MAC PROCESS UL TRANSPORT BLOCK at frame%d subframe %d TBS=%d\n", - module_idP, frameP, subframe, buflen); - AssertFatal(CC_id == 0, - "Transmission on secondary CCs is not supported yet\n"); + module_id_t mod_id = dl_info->module_id; + frame_t frame = dl_info->frame; + int slot = dl_info->slot; + int cc_id = dl_info->cc_id; + uint8_t gNB_id = dl_info->gNB_index; + NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id); + RA_config_t *ra = &mac->ra; + uint8_t n_subPDUs = 0; // number of RAR payloads + uint8_t n_subheaders = 0; // number of MAC RAR subheaders + uint8_t *dlsch_buffer = dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu.pdu; + uint8_t is_Msg3 = 1; + frame_t frame_tx = 0; + int slot_tx = 0; + uint16_t rnti = 0; + int ret = 0; + NR_RA_HEADER_RAPID *rarh = (NR_RA_HEADER_RAPID *) dlsch_buffer; // RAR subheader pointer + NR_MAC_RAR *rar = (NR_MAC_RAR *) (dlsch_buffer + 1); // RAR subPDU pointer + uint8_t preamble_index = get_ra_PreambleIndex(mod_id, cc_id, gNB_id); //prach_resources->ra_PreambleIndex; - // Check for DCCH first - // TO DO: Multiplex in the order defined by the logical channel prioritization - for (lcid = UL_SCH_LCID_SRB1; - lcid < NR_MAX_NUM_LCID; lcid++) { + LOG_D(MAC, "In %s:[%d.%d]: [UE %d][RAPROC] invoking MAC for received RAR (current preamble %d)\n", __FUNCTION__, frame, slot, mod_id, preamble_index); - lcid_buffer_occupancy_old = mac_rlc_get_buffer_occupancy_ind(module_idP, mac->crnti, eNB_index, frameP, subframe, ENB_FLAG_NO, lcid); - lcid_buffer_occupancy_new = lcid_buffer_occupancy_old; - - if(lcid_buffer_occupancy_new){ - - buflen_remain = - buflen - (total_rlc_pdu_header_len + sdu_length_total + MAX_RLC_SDU_SUBHEADER_SIZE); - LOG_D(MAC, - "[UE %d] Frame %d : UL-DXCH -> ULSCH, RLC %d has %d bytes to " - "send (Transport Block size %d SDU Length Total %d , mac header len %d, buflen_remain %d )\n", //BSR byte before Tx=%d - module_idP, frameP, lcid, lcid_buffer_occupancy_new, - buflen, sdu_length_total, - total_rlc_pdu_header_len, buflen_remain); // ,nr_ue_mac_inst->scheduling_info.BSR_bytes[nr_ue_mac_inst->scheduling_info.LCGID[lcid]] - - while(buflen_remain > 0 && lcid_buffer_occupancy_new){ - - sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP, - mac->crnti, - eNB_index, - frameP, - ENB_FLAG_NO, - MBMS_FLAG_NO, - lcid, - buflen_remain, - (char *)&ulsch_sdus[sdu_length_total],0, - 0); - - AssertFatal(buflen_remain >= sdu_lengths[num_sdus], - "LCID=%d RLC has segmented %d bytes but MAC has max=%d\n", - lcid, sdu_lengths[num_sdus], buflen_remain); - - if (sdu_lengths[num_sdus]) { - sdu_length_total += sdu_lengths[num_sdus]; - sdu_lcids[num_sdus] = lcid; - - total_rlc_pdu_header_len += MAX_RLC_SDU_SUBHEADER_SIZE; //rlc_pdu_header_len_last; - - //Update number of SDU - num_sdus++; - } - - /* Get updated BO after multiplexing this PDU */ - lcid_buffer_occupancy_new = mac_rlc_get_buffer_occupancy_ind(module_idP, - mac->crnti, - eNB_index, - frameP, - subframe, - ENB_FLAG_NO, - lcid); - buflen_remain = - buflen - (total_rlc_pdu_header_len + sdu_length_total + MAX_RLC_SDU_SUBHEADER_SIZE); - } + while (1) { + n_subheaders++; + if (rarh->T == 1) { + n_subPDUs++; + LOG_D(MAC, "[UE %d][RAPROC] Got RAPID RAR subPDU\n", mod_id); + } else { + n_subPDUs++; + ra->RA_backoff_indicator = table_7_2_1[((NR_RA_HEADER_BI *)rarh)->BI]; + ra->RA_BI_found = 1; + LOG_D(MAC, "[UE %d][RAPROC] Got BI RAR subPDU %d\n", mod_id, ra->RA_backoff_indicator); + } + if (rarh->RAPID == preamble_index) { + LOG_I(MAC, "[UE %d][RAPROC][%d.%d] Found RAR with the intended RAPID %d\n", mod_id, frame, slot, rarh->RAPID); + rar = (NR_MAC_RAR *) (dlsch_buffer + n_subheaders + (n_subPDUs - 1) * sizeof(NR_MAC_RAR)); + ra->RA_RAPID_found = 1; + break; + } + if (rarh->E == 0) { + LOG_W(PHY,"[UE %d][RAPROC] Received RAR preamble (%d) doesn't match the intended RAPID...\n", mod_id, preamble_index); + break; + } else { + rarh += sizeof(NR_MAC_RAR) + 1; + } } -} + #ifdef DEBUG_RAR + LOG_D(MAC, "[DEBUG_RAR] (%d,%d) number of RAR subheader %d; number of RAR pyloads %d\n", frame, slot, n_subheaders, n_subPDUs); + LOG_D(MAC, "[DEBUG_RAR] Received RAR (%02x|%02x.%02x.%02x.%02x.%02x.%02x) for preamble %d/%d\n", *(uint8_t *) rarh, rar[0], rar[1], rar[2], rar[3], rar[4], rar[5], rarh->RAPID, preamble_index); + #endif - // Generate ULSCH PDU - if (num_sdus>0) { - payload_offset = nr_generate_ulsch_pdu(ulsch_sdus, - ulsch_buffer, // mac header - num_sdus, // num sdus - sdu_lengths, // sdu length - sdu_lcids, // sdu lcid - 0, // power_headroom - mac->crnti, // crnti - 0, // truncated_bsr - 0, // short_bsr - 0, // long_bsr - 0, // post_padding - buflen); // TBS in bytes - } - else - return 0; + if (ra->RA_RAPID_found) { - // Padding: fill remainder of ULSCH with 0 - if (buflen - payload_offset > 0){ - for (int j = payload_offset; j < buflen; j++) - ulsch_buffer[j] = 0; - } + RAR_grant_t rar_grant; -// log_dump(MAC, ulsch_buffer, 16, LOG_DUMP_CHAR, "UE ULSCH payload : "); - -#if defined(ENABLE_MAC_PAYLOAD_DEBUG) - LOG_I(MAC, "Printing UL MAC payload UE side, payload_offset: %d \n", payload_offset); - for (int i = 0; i < buflen ; i++) { - //harq_process_ul_ue->a[i] = (unsigned char) rand(); - //printf("a[%d]=0x%02x\n",i,harq_process_ul_ue->a[i]); - printf("%02x ",(unsigned char)ulsch_buffer[i]); - } - printf("\n"); + unsigned char tpc_command; +#ifdef DEBUG_RAR + unsigned char csi_req; #endif - return 1; + // TC-RNTI + ra->t_crnti = rar->TCRNTI_2 + (rar->TCRNTI_1 << 8); + + // TA command + ul_time_alignment->apply_ta = 1; + ul_time_alignment->ta_command = rar->TA2 + (rar->TA1 << 5); + +#ifdef DEBUG_RAR + // CSI + csi_req = (unsigned char) (rar->UL_GRANT_4 & 0x01); +#endif + + // TPC + tpc_command = (unsigned char) ((rar->UL_GRANT_4 >> 1) & 0x07); + switch (tpc_command){ + case 0: + ra->Msg3_TPC = -6; + break; + case 1: + ra->Msg3_TPC = -4; + break; + case 2: + ra->Msg3_TPC = -2; + break; + case 3: + ra->Msg3_TPC = 0; + break; + case 4: + ra->Msg3_TPC = 2; + break; + case 5: + ra->Msg3_TPC = 4; + break; + case 6: + ra->Msg3_TPC = 6; + break; + case 7: + ra->Msg3_TPC = 8; + break; + } + // MCS + rar_grant.mcs = (unsigned char) (rar->UL_GRANT_4 >> 4); + // time alloc + rar_grant.Msg3_t_alloc = (unsigned char) (rar->UL_GRANT_3 & 0x07); + // frequency alloc + rar_grant.Msg3_f_alloc = (uint16_t) ((rar->UL_GRANT_3 >> 4) | (rar->UL_GRANT_2 << 4) | ((rar->UL_GRANT_1 & 0x03) << 12)); + // frequency hopping + rar_grant.freq_hopping = (unsigned char) (rar->UL_GRANT_1 >> 2); + // TC-RNTI + if (ra->t_crnti) { + rnti = ra->t_crnti; + } else { + rnti = mac->crnti; + } + + #ifdef DEBUG_RAR + LOG_D(MAC, "In %s:[%d.%d]: [UE %d] Received 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__, + frame, + slot, + mod_id, + rar_grant.Msg3_t_alloc, + rar_grant.Msg3_f_alloc, + ul_time_alignment->ta_command, + rar_grant.mcs, + rar_grant.freq_hopping, + tpc_command, + csi_req, + ra->t_crnti); + #endif + + // Schedule Msg3 + ret = nr_ue_pusch_scheduler(mac, is_Msg3, frame, slot, &frame_tx, &slot_tx, rar_grant.Msg3_t_alloc); + + if (ret != -1){ + + fapi_nr_ul_config_request_t *ul_config = get_ul_config_request(mac, slot_tx); + + if (!ul_config) { + LOG_W(MAC, "In %s: ul_config request is NULL. Probably due to unexpected UL DCI in frame.slot %d.%d. Ignoring DCI!\n", __FUNCTION__, frame, slot); + return -1; + } + + nfapi_nr_ue_pusch_pdu_t *pusch_config_pdu = &ul_config->ul_config_list[ul_config->number_pdus].pusch_config_pdu; + + fill_ul_config(ul_config, frame_tx, slot_tx, FAPI_NR_UL_CONFIG_TYPE_PUSCH); + + // Config Msg3 PDU + nr_config_pusch_pdu(mac, pusch_config_pdu, NULL, &rar_grant, rnti, NULL); + + } + + } else { + + ra->t_crnti = 0; + ul_time_alignment->ta_command = (0xffff); + + } + + return ret; + } diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c new file mode 100644 index 0000000000..d6e1cba6df --- /dev/null +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -0,0 +1,1897 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/* \file nr_ue_scheduler.c + * \brief Routines for UE scheduling + * \author Guido Casati + * \date Jan 2021 + * \version 0.1 + * \company Fraunhofer IIS + * \email guido.casati@iis.fraunhofer.de + */ + +#include +#include + +/* exe */ +#include + +/* RRC*/ +#include "RRC/NR_UE/rrc_proto.h" +#include "NR_RACH-ConfigCommon.h" +#include "NR_RACH-ConfigGeneric.h" +#include "NR_FrequencyInfoDL.h" +#include "NR_PDCCH-ConfigCommon.h" + +/* MAC */ +#include "NR_MAC_COMMON/nr_mac.h" +#include "NR_MAC_UE/mac_proto.h" +#include "NR_MAC_UE/mac_extern.h" + +/* utils */ +#include "assertions.h" +#include "asn1_conversions.h" +#include "SIMULATION/TOOLS/sim.h" // for taus + +static prach_association_pattern_t prach_assoc_pattern; +static ssb_list_info_t ssb_list; + +void fill_ul_config(fapi_nr_ul_config_request_t *ul_config, frame_t frame_tx, int slot_tx, uint8_t pdu_type){ + + ul_config->ul_config_list[ul_config->number_pdus].pdu_type = pdu_type; + ul_config->slot = slot_tx; + ul_config->sfn = frame_tx; + ul_config->number_pdus++; + + LOG_D(MAC, "In %s: Set config request for UL transmission in [%d.%d], number of UL PDUs: %d\n", __FUNCTION__, ul_config->sfn, ul_config->slot, ul_config->number_pdus); + +} + +void fill_scheduled_response(nr_scheduled_response_t *scheduled_response, + fapi_nr_dl_config_request_t *dl_config, + fapi_nr_ul_config_request_t *ul_config, + fapi_nr_tx_request_t *tx_request, + module_id_t mod_id, + int cc_id, + frame_t frame, + int slot, + int thread_id){ + + scheduled_response->dl_config = dl_config; + scheduled_response->ul_config = ul_config; + scheduled_response->tx_request = tx_request; + scheduled_response->module_id = mod_id; + scheduled_response->CC_id = cc_id; + scheduled_response->frame = frame; + scheduled_response->slot = slot; + scheduled_response->thread_id = thread_id; + +} + +/* + * This function returns the slot offset K2 corresponding to a given time domain + * indication value from RRC configuration. + */ +long get_k2(NR_UE_MAC_INST_t *mac, uint8_t time_domain_ind) { + long k2 = -1; + // Get K2 from RRC configuration + NR_PUSCH_Config_t *pusch_config=mac->ULbwp[0]->bwp_Dedicated->pusch_Config->choice.setup; + NR_PUSCH_TimeDomainResourceAllocationList_t *pusch_TimeDomainAllocationList = NULL; + if (pusch_config->pusch_TimeDomainAllocationList) { + pusch_TimeDomainAllocationList = pusch_config->pusch_TimeDomainAllocationList->choice.setup; + } + else if (mac->ULbwp[0]->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList) { + pusch_TimeDomainAllocationList = mac->ULbwp[0]->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList; + } + if (pusch_TimeDomainAllocationList) { + if (time_domain_ind >= pusch_TimeDomainAllocationList->list.count) { + LOG_E(MAC, "time_domain_ind %d >= pusch->TimeDomainAllocationList->list.count %d\n", + time_domain_ind, pusch_TimeDomainAllocationList->list.count); + return -1; + } + k2 = *pusch_TimeDomainAllocationList->list.array[time_domain_ind]->k2; + } + + LOG_D(MAC, "get_k2(): k2 is %ld\n", k2); + return k2; +} + +/* + * This function returns the UL config corresponding to a given UL slot + * from MAC instance . + */ +fapi_nr_ul_config_request_t *get_ul_config_request(NR_UE_MAC_INST_t *mac, int slot) { + //Check if request to access ul_config is for a UL slot + if (is_nr_UL_slot(mac->scc, slot) == 0) { + LOG_W(MAC, "Slot %d is not a UL slot. %s called for wrong slot!!!\n", slot, __FUNCTION__); + return NULL; + } + + // Calculate the index of the UL slot in mac->ul_config_request list. This is + // based on the TDD pattern (slot configuration period) and number of UL+mixed + // slots in the period. TS 38.213 Sec 11.1 + int mu = mac->ULbwp[0]->bwp_Common->genericParameters.subcarrierSpacing; + NR_TDD_UL_DL_Pattern_t *tdd_pattern = &mac->scc->tdd_UL_DL_ConfigurationCommon->pattern1; + const int num_slots_per_tdd = nr_slots_per_frame[mu] >> (7 - tdd_pattern->dl_UL_TransmissionPeriodicity); + const int num_slots_ul = tdd_pattern->nrofUplinkSlots + (tdd_pattern->nrofUplinkSymbols!=0); + int index = (slot + num_slots_ul - num_slots_per_tdd) % num_slots_per_tdd; + + LOG_D(MAC, "In %s slots per tdd %d, num_slots_ul %d, index %d\n", __FUNCTION__, + num_slots_per_tdd, + num_slots_ul, + index); + + return &mac->ul_config_request[index]; +} + +void ul_layers_config(NR_UE_MAC_INST_t * mac, nfapi_nr_ue_pusch_pdu_t *pusch_config_pdu, dci_pdu_rel15_t *dci) { + + fapi_nr_pusch_config_dedicated_t *pusch_config_dedicated = &mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated; + NR_PUSCH_Config_t *pusch_Config = mac->ULbwp[0]->bwp_Dedicated->pusch_Config->choice.setup; + + /* PRECOD_NBR_LAYERS */ + if ((pusch_config_dedicated->tx_config == tx_config_nonCodebook)); + // 0 bits if the higher layer parameter txConfig = nonCodeBook + + if ((pusch_config_dedicated->tx_config == tx_config_codebook)){ + + uint8_t n_antenna_port = 0; //FIXME!!! + + if (n_antenna_port == 1); // 1 antenna port and the higher layer parameter txConfig = codebook 0 bits + + if (n_antenna_port == 4){ // 4 antenna port and the higher layer parameter txConfig = codebook + + // Table 7.3.1.1.2-2: transformPrecoder=disabled and maxRank = 2 or 3 or 4 + if ((pusch_config_dedicated->transform_precoder == transform_precoder_disabled) + && ((pusch_config_dedicated->max_rank == 2) || + (pusch_config_dedicated->max_rank == 3) || + (pusch_config_dedicated->max_rank == 4))){ + + if (pusch_config_dedicated->codebook_subset == codebook_subset_fullyAndPartialAndNonCoherent) { + pusch_config_pdu->nrOfLayers = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][0]; + pusch_config_pdu->transform_precoding = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][1]; + } + + if (pusch_config_dedicated->codebook_subset == codebook_subset_partialAndNonCoherent){ + pusch_config_pdu->nrOfLayers = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][2]; + pusch_config_pdu->transform_precoding = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][3]; + } + + if (pusch_config_dedicated->codebook_subset == codebook_subset_nonCoherent){ + pusch_config_pdu->nrOfLayers = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][4]; + pusch_config_pdu->transform_precoding = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][5]; + } + } + + // Table 7.3.1.1.2-3: transformPrecoder= enabled, or transformPrecoder=disabled and maxRank = 1 + if (((pusch_config_dedicated->transform_precoder == transform_precoder_enabled) + || (pusch_config_dedicated->transform_precoder == transform_precoder_disabled)) + && (pusch_config_dedicated->max_rank == 1)){ + + if (pusch_config_dedicated->codebook_subset == codebook_subset_fullyAndPartialAndNonCoherent) { + pusch_config_pdu->nrOfLayers = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][6]; + pusch_config_pdu->transform_precoding = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][7]; + } + + if (pusch_config_dedicated->codebook_subset == codebook_subset_partialAndNonCoherent){ + pusch_config_pdu->nrOfLayers = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][8]; + pusch_config_pdu->transform_precoding = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][9]; + } + + if (pusch_config_dedicated->codebook_subset == codebook_subset_nonCoherent){ + pusch_config_pdu->nrOfLayers = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][10]; + pusch_config_pdu->transform_precoding = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][11]; + } + } + } + + if (n_antenna_port == 4){ // 2 antenna port and the higher layer parameter txConfig = codebook + // Table 7.3.1.1.2-4: transformPrecoder=disabled and maxRank = 2 + if ((pusch_config_dedicated->transform_precoder == transform_precoder_disabled) && (pusch_config_dedicated->max_rank == 2)){ + + if (pusch_config_dedicated->codebook_subset == codebook_subset_fullyAndPartialAndNonCoherent) { + pusch_config_pdu->nrOfLayers = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][12]; + pusch_config_pdu->transform_precoding = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][13]; + } + + if (pusch_config_dedicated->codebook_subset == codebook_subset_nonCoherent){ + pusch_config_pdu->nrOfLayers = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][14]; + pusch_config_pdu->transform_precoding = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][15]; + } + + } + + // Table 7.3.1.1.2-5: transformPrecoder= enabled, or transformPrecoder= disabled and maxRank = 1 + if (((pusch_config_dedicated->transform_precoder == transform_precoder_enabled) + || (pusch_config_dedicated->transform_precoder == transform_precoder_disabled)) + && (pusch_config_dedicated->max_rank == 1)){ + + if (pusch_config_dedicated->codebook_subset == codebook_subset_fullyAndPartialAndNonCoherent) { + pusch_config_pdu->nrOfLayers = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][16]; + pusch_config_pdu->transform_precoding = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][17]; + } + + if (pusch_config_dedicated->codebook_subset == codebook_subset_nonCoherent){ + pusch_config_pdu->nrOfLayers = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][18]; + pusch_config_pdu->transform_precoding = table_7_3_1_1_2_2_3_4_5[dci->precoding_information.val][19]; + } + + } + } + } + + /*-------------------- Changed to enable Transform precoding in RF SIM------------------------------------------------*/ + + if (pusch_config_pdu->transform_precoding == transform_precoder_enabled) { + + pusch_config_dedicated->transform_precoder = transform_precoder_enabled; + + if(pusch_Config->dmrs_UplinkForPUSCH_MappingTypeA != NULL) { + + NR_DMRS_UplinkConfig_t *NR_DMRS_ulconfig = pusch_Config->dmrs_UplinkForPUSCH_MappingTypeA->choice.setup; + + if (NR_DMRS_ulconfig->dmrs_Type == NULL) + pusch_config_dedicated->dmrs_ul_for_pusch_mapping_type_a.dmrs_type = 1; + if (NR_DMRS_ulconfig->maxLength == NULL) + pusch_config_dedicated->dmrs_ul_for_pusch_mapping_type_a.max_length = 1; + + } else if(pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB != NULL) { + + NR_DMRS_UplinkConfig_t *NR_DMRS_ulconfig = pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup; + + if (NR_DMRS_ulconfig->dmrs_Type == NULL) + pusch_config_dedicated->dmrs_ul_for_pusch_mapping_type_b.dmrs_type = 1; + if (NR_DMRS_ulconfig->maxLength == NULL) + pusch_config_dedicated->dmrs_ul_for_pusch_mapping_type_b.max_length = 1; + + } + } else + pusch_config_dedicated->transform_precoder = transform_precoder_disabled; + + // mapping type b configured from RRC. TBD: Mapping type b is not handled in this function. + if ((pusch_config_dedicated->transform_precoder == transform_precoder_enabled) && + (pusch_config_dedicated->dmrs_ul_for_pusch_mapping_type_b.dmrs_type == 1) && + (pusch_config_dedicated->dmrs_ul_for_pusch_mapping_type_b.max_length == 1)) { // tables 7.3.1.1.2-6 + pusch_config_pdu->num_dmrs_cdm_grps_no_data = 2; + pusch_config_pdu->dmrs_ports = dci->antenna_ports.val; + } +} + +// todo: this function shall be reviewed completely because of the many comments left by the author +void ul_ports_config(NR_UE_MAC_INST_t * mac, nfapi_nr_ue_pusch_pdu_t *pusch_config_pdu, dci_pdu_rel15_t *dci) { + + /* ANTENNA_PORTS */ + uint8_t rank = 0; // We need to initialize rank FIXME!!! + fapi_nr_pusch_config_dedicated_t *pusch_config_dedicated = &mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated; + + if ((pusch_config_dedicated->transform_precoder == transform_precoder_enabled) && + (pusch_config_dedicated->dmrs_ul_for_pusch_mapping_type_a.dmrs_type == 1) && + (pusch_config_dedicated->dmrs_ul_for_pusch_mapping_type_a.max_length == 1)) { // tables 7.3.1.1.2-6 + pusch_config_pdu->num_dmrs_cdm_grps_no_data = 2; //TBC + pusch_config_pdu->dmrs_ports = dci->antenna_ports.val; //TBC + } + + if ((pusch_config_dedicated->transform_precoder == transform_precoder_enabled) && + (pusch_config_dedicated->dmrs_ul_for_pusch_mapping_type_a.dmrs_type == 1) && + (pusch_config_dedicated->dmrs_ul_for_pusch_mapping_type_a.max_length == 2)) { // tables 7.3.1.1.2-7 + + pusch_config_pdu->num_dmrs_cdm_grps_no_data = 2; //TBC + pusch_config_pdu->dmrs_ports = (dci->antenna_ports.val > 3)?(dci->antenna_ports.val-4):(dci->antenna_ports.val); //TBC + //pusch_config_pdu->n_front_load_symb = (dci->antenna_ports > 3)?2:1; //FIXME + } + + if ((pusch_config_dedicated->transform_precoder == transform_precoder_disabled) && + (pusch_config_dedicated->dmrs_ul_for_pusch_mapping_type_a.dmrs_type == 1) && + (pusch_config_dedicated->dmrs_ul_for_pusch_mapping_type_a.max_length == 1)) { // tables 7.3.1.1.2-8/9/10/11 + + if (rank == 1) { + pusch_config_pdu->num_dmrs_cdm_grps_no_data = (dci->antenna_ports.val > 1)?2:1; //TBC + pusch_config_pdu->dmrs_ports = (dci->antenna_ports.val > 1)?(dci->antenna_ports.val-2):(dci->antenna_ports.val); //TBC + } + + if (rank == 2){ + pusch_config_pdu->num_dmrs_cdm_grps_no_data = (dci->antenna_ports.val > 0)?2:1; //TBC + pusch_config_pdu->dmrs_ports = 0; //FIXME + //pusch_config_pdu->dmrs_ports[0] = (dci->antenna_ports > 1)?(dci->antenna_ports > 2 ?0:2):0; + //pusch_config_pdu->dmrs_ports[1] = (dci->antenna_ports > 1)?(dci->antenna_ports > 2 ?2:3):1; + } + + if (rank == 3){ + pusch_config_pdu->num_dmrs_cdm_grps_no_data = 2; //TBC + pusch_config_pdu->dmrs_ports = 0; //FIXME + //pusch_config_pdu->dmrs_ports[0] = 0; + //pusch_config_pdu->dmrs_ports[1] = 1; + //pusch_config_pdu->dmrs_ports[2] = 2; + } + + if (rank == 4){ + pusch_config_pdu->num_dmrs_cdm_grps_no_data = 2; //TBC + pusch_config_pdu->dmrs_ports = 0; //FIXME + //pusch_config_pdu->dmrs_ports[0] = 0; + //pusch_config_pdu->dmrs_ports[1] = 1; + //pusch_config_pdu->dmrs_ports[2] = 2; + //pusch_config_pdu->dmrs_ports[3] = 3; + } + } + + if ((pusch_config_dedicated->transform_precoder == transform_precoder_disabled) && + (pusch_config_dedicated->dmrs_ul_for_pusch_mapping_type_a.dmrs_type == 1) && + (pusch_config_dedicated->dmrs_ul_for_pusch_mapping_type_a.max_length == 2)) { // tables 7.3.1.1.2-12/13/14/15 + + if (rank == 1){ + pusch_config_pdu->num_dmrs_cdm_grps_no_data = (dci->antenna_ports.val > 1)?2:1; //TBC + pusch_config_pdu->dmrs_ports = (dci->antenna_ports.val > 1)?(dci->antenna_ports.val > 5 ?(dci->antenna_ports.val-6):(dci->antenna_ports.val-2)):dci->antenna_ports.val; //TBC + //pusch_config_pdu->n_front_load_symb = (dci->antenna_ports.val > 6)?2:1; //FIXME + } + + if (rank == 2){ + pusch_config_pdu->num_dmrs_cdm_grps_no_data = (dci->antenna_ports.val > 0)?2:1; //TBC + pusch_config_pdu->dmrs_ports = 0; //FIXME + //pusch_config_pdu->dmrs_ports[0] = table_7_3_1_1_2_13[dci->antenna_ports.val][1]; + //pusch_config_pdu->dmrs_ports[1] = table_7_3_1_1_2_13[dci->antenna_ports.val][2]; + //pusch_config_pdu->n_front_load_symb = (dci->antenna_ports.val > 3)?2:1; // FIXME + } + + if (rank == 3){ + pusch_config_pdu->num_dmrs_cdm_grps_no_data = 2; //TBC + pusch_config_pdu->dmrs_ports = 0; //FIXME + //pusch_config_pdu->dmrs_ports[0] = table_7_3_1_1_2_14[dci->antenna_ports.val][1]; + //pusch_config_pdu->dmrs_ports[1] = table_7_3_1_1_2_14[dci->antenna_ports.val][2]; + //pusch_config_pdu->dmrs_ports[2] = table_7_3_1_1_2_14[dci->antenna_ports.val][3]; + //pusch_config_pdu->n_front_load_symb = (dci->antenna_ports.val > 1)?2:1; //FIXME + } + + if (rank == 4){ + pusch_config_pdu->num_dmrs_cdm_grps_no_data = 2; //TBC + pusch_config_pdu->dmrs_ports = 0; //FIXME + //pusch_config_pdu->dmrs_ports[0] = table_7_3_1_1_2_15[dci->antenna_ports.val][1]; + //pusch_config_pdu->dmrs_ports[1] = table_7_3_1_1_2_15[dci->antenna_ports.val][2]; + //pusch_config_pdu->dmrs_ports[2] = table_7_3_1_1_2_15[dci->antenna_ports.val][3]; + //pusch_config_pdu->dmrs_ports[3] = table_7_3_1_1_2_15[dci->antenna_ports.val][4]; + //pusch_config_pdu->n_front_load_symb = (dci->antenna_ports.val > 1)?2:1; //FIXME + } + } + + if ((pusch_config_dedicated->transform_precoder == transform_precoder_disabled) && + (pusch_config_dedicated->dmrs_ul_for_pusch_mapping_type_a.dmrs_type == 2) && + (pusch_config_dedicated->dmrs_ul_for_pusch_mapping_type_a.max_length == 1)) { // tables 7.3.1.1.2-16/17/18/19 + + if (rank == 1){ + pusch_config_pdu->num_dmrs_cdm_grps_no_data = (dci->antenna_ports.val > 1)?((dci->antenna_ports.val > 5)?3:2):1; //TBC + pusch_config_pdu->dmrs_ports = (dci->antenna_ports.val > 1)?(dci->antenna_ports.val > 5 ?(dci->antenna_ports.val-6):(dci->antenna_ports.val-2)):dci->antenna_ports.val; //TBC + } + + if (rank == 2){ + pusch_config_pdu->num_dmrs_cdm_grps_no_data = (dci->antenna_ports.val > 0)?((dci->antenna_ports.val > 2)?3:2):1; //TBC + pusch_config_pdu->dmrs_ports = 0; //FIXME + //pusch_config_pdu->dmrs_ports[0] = table_7_3_1_1_2_17[dci->antenna_ports.val][1]; + //pusch_config_pdu->dmrs_ports[1] = table_7_3_1_1_2_17[dci->antenna_ports.val][2]; + } + + if (rank == 3){ + pusch_config_pdu->num_dmrs_cdm_grps_no_data = (dci->antenna_ports.val > 0)?3:2; //TBC + pusch_config_pdu->dmrs_ports = 0; //FIXME + //pusch_config_pdu->dmrs_ports[0] = table_7_3_1_1_2_18[dci->antenna_ports.val][1]; + //pusch_config_pdu->dmrs_ports[1] = table_7_3_1_1_2_18[dci->antenna_ports.val][2]; + //pusch_config_pdu->dmrs_ports[2] = table_7_3_1_1_2_18[dci->antenna_ports.val][3]; + } + + if (rank == 4){ + pusch_config_pdu->num_dmrs_cdm_grps_no_data = dci->antenna_ports.val + 2; //TBC + pusch_config_pdu->dmrs_ports = 0; //FIXME + //pusch_config_pdu->dmrs_ports[0] = 0; + //pusch_config_pdu->dmrs_ports[1] = 1; + //pusch_config_pdu->dmrs_ports[2] = 2; + //pusch_config_pdu->dmrs_ports[3] = 3; + } + } + + if ((pusch_config_dedicated->transform_precoder == transform_precoder_disabled) && + (pusch_config_dedicated->dmrs_ul_for_pusch_mapping_type_a.dmrs_type == 2) && + (pusch_config_dedicated->dmrs_ul_for_pusch_mapping_type_a.max_length == 2)) { // tables 7.3.1.1.2-20/21/22/23 + + if (rank == 1){ + pusch_config_pdu->num_dmrs_cdm_grps_no_data = table_7_3_1_1_2_20[dci->antenna_ports.val][0]; //TBC + pusch_config_pdu->dmrs_ports = table_7_3_1_1_2_20[dci->antenna_ports.val][1]; //TBC + //pusch_config_pdu->n_front_load_symb = table_7_3_1_1_2_20[dci->antenna_ports.val][2]; //FIXME + } + + if (rank == 2){ + pusch_config_pdu->num_dmrs_cdm_grps_no_data = table_7_3_1_1_2_21[dci->antenna_ports.val][0]; //TBC + pusch_config_pdu->dmrs_ports = 0; //FIXME + //pusch_config_pdu->dmrs_ports[0] = table_7_3_1_1_2_21[dci->antenna_ports.val][1]; + //pusch_config_pdu->dmrs_ports[1] = table_7_3_1_1_2_21[dci->antenna_ports.val][2]; + //pusch_config_pdu->n_front_load_symb = table_7_3_1_1_2_21[dci->antenna_ports.val][3]; //FIXME + } + + if (rank == 3){ + pusch_config_pdu->num_dmrs_cdm_grps_no_data = table_7_3_1_1_2_22[dci->antenna_ports.val][0]; //TBC + pusch_config_pdu->dmrs_ports = 0; //FIXME + //pusch_config_pdu->dmrs_ports[0] = table_7_3_1_1_2_22[dci->antenna_ports.val][1]; + //pusch_config_pdu->dmrs_ports[1] = table_7_3_1_1_2_22[dci->antenna_ports.val][2]; + //pusch_config_pdu->dmrs_ports[2] = table_7_3_1_1_2_22[dci->antenna_ports.val][3]; + //pusch_config_pdu->n_front_load_symb = table_7_3_1_1_2_22[dci->antenna_ports.val][4]; //FIXME + } + + if (rank == 4){ + pusch_config_pdu->num_dmrs_cdm_grps_no_data = table_7_3_1_1_2_23[dci->antenna_ports.val][0]; //TBC + pusch_config_pdu->dmrs_ports = 0; //FIXME + //pusch_config_pdu->dmrs_ports[0] = table_7_3_1_1_2_23[dci->antenna_ports.val][1]; + //pusch_config_pdu->dmrs_ports[1] = table_7_3_1_1_2_23[dci->antenna_ports.val][2]; + //pusch_config_pdu->dmrs_ports[2] = table_7_3_1_1_2_23[dci->antenna_ports.val][3]; + //pusch_config_pdu->dmrs_ports[3] = table_7_3_1_1_2_23[dci->antenna_ports.val][4]; + //pusch_config_pdu->n_front_load_symb = table_7_3_1_1_2_23[dci->antenna_ports.val][5]; //FIXME + } + } +} + +// Configuration of Msg3 PDU according to clauses: +// - 8.3 of 3GPP TS 38.213 version 16.3.0 Release 16 +// - 6.1.2.2 of TS 38.214 +// - 6.1.3 of TS 38.214 +// - 6.2.2 of TS 38.214 +// - 6.1.4.2 of TS 38.214 +// - 6.4.1.1.1 of TS 38.211 +// - 6.3.1.7 of 38.211 +int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, + nfapi_nr_ue_pusch_pdu_t *pusch_config_pdu, + dci_pdu_rel15_t *dci, + RAR_grant_t *rar_grant, + uint16_t rnti, + uint8_t *dci_format){ + + int f_alloc; + int mask; + int StartSymbolIndex; + int NrOfSymbols; + uint8_t nb_dmrs_re_per_rb; + + uint16_t l_prime_mask = 1; + uint16_t number_dmrs_symbols = 0; + int N_PRB_oh = 0; + + NR_ServingCellConfigCommon_t *scc = mac->scc; + int rnti_type = get_rnti_type(mac, rnti); + + // Common configuration + pusch_config_pdu->dmrs_config_type = pusch_dmrs_type1; + pusch_config_pdu->pdu_bit_map = PUSCH_PDU_BITMAP_PUSCH_DATA; + pusch_config_pdu->nrOfLayers = 1; + pusch_config_pdu->rnti = rnti; + + if (rar_grant) { + + // Note: for Msg3 or MsgA PUSCH transmission the N_PRB_oh is always set to 0 + + NR_BWP_Uplink_t *ubwp = mac->ULbwp[0]; + NR_BWP_UplinkDedicated_t *ibwp = mac->scg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP; + NR_PUSCH_Config_t *pusch_Config = ibwp->pusch_Config->choice.setup; + int startSymbolAndLength = ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[rar_grant->Msg3_t_alloc]->startSymbolAndLength; + + // active BWP start + int abwp_start = NRRIV2PRBOFFSET(ubwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + int abwp_size = NRRIV2BW(ubwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + + // initial BWP start + int ibwp_start = NRRIV2PRBOFFSET(scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + int ibwp_size = NRRIV2BW(scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + + // BWP start selection according to 8.3 of TS 38.213 + pusch_config_pdu->bwp_size = ibwp_size; + if ((ibwp_start < abwp_start) || (ibwp_size > abwp_size)) + pusch_config_pdu->bwp_start = abwp_start; + else + pusch_config_pdu->bwp_start = ibwp_start; + + //// Resource assignment from RAR + // Frequency domain allocation according to 8.3 of TS 38.213 + if (ibwp_size < 180) + mask = (1 << ((int) ceil(log2((ibwp_size*(ibwp_size+1))>>1)))) - 1; + else + mask = (1 << (28 - (int)(ceil(log2((ibwp_size*(ibwp_size+1))>>1))))) - 1; + + f_alloc = rar_grant->Msg3_f_alloc & mask; + if (nr_ue_process_dci_freq_dom_resource_assignment(pusch_config_pdu, NULL, ibwp_size, 0, f_alloc) < 0) + return -1; + + // virtual resource block to physical resource mapping for Msg3 PUSCH (6.3.1.7 in 38.211) + pusch_config_pdu->rb_start += ibwp_start - abwp_start; + + // Time domain allocation + SLIV2SL(startSymbolAndLength, &StartSymbolIndex, &NrOfSymbols); + pusch_config_pdu->start_symbol_index = StartSymbolIndex; + pusch_config_pdu->nr_of_symbols = NrOfSymbols; + + #ifdef DEBUG_MSG3 + LOG_D(MAC, "In %s BWP assignment (BWP (start %d, size %d) \n", __FUNCTION__, pusch_config_pdu->bwp_start, pusch_config_pdu->bwp_size); + #endif + + // MCS + pusch_config_pdu->mcs_index = rar_grant->mcs; + // Frequency hopping + pusch_config_pdu->frequency_hopping = rar_grant->freq_hopping; + + // DM-RS configuration according to 6.2.2 UE DM-RS transmission procedure in 38.214 + pusch_config_pdu->num_dmrs_cdm_grps_no_data = 2; + pusch_config_pdu->dmrs_ports = 1; + + // DMRS sequence initialization [TS 38.211, sec 6.4.1.1.1]. + // Should match what is sent in DCI 0_1, otherwise set to 0. + pusch_config_pdu->scid = 0; + + // Transform precoding according to 6.1.3 UE procedure for applying transform precoding on PUSCH in 38.214 + pusch_config_pdu->transform_precoding = get_transformPrecoding(scc, pusch_Config, NULL, NULL, NR_RNTI_RA, 0); // TBR fix rnti and take out + + // Resource allocation in frequency domain according to 6.1.2.2 in TS 38.214 + pusch_config_pdu->resource_alloc = pusch_Config->resourceAllocation; + + //// Completing PUSCH PDU + pusch_config_pdu->mcs_table = 0; + pusch_config_pdu->cyclic_prefix = 0; + pusch_config_pdu->data_scrambling_id = *scc->physCellId; + pusch_config_pdu->ul_dmrs_scrambling_id = *scc->physCellId; + pusch_config_pdu->subcarrier_spacing = ubwp->bwp_Common->genericParameters.subcarrierSpacing; + pusch_config_pdu->vrb_to_prb_mapping = 0; + pusch_config_pdu->uplink_frequency_shift_7p5khz = 0; + //Optional Data only included if indicated in pduBitmap + pusch_config_pdu->pusch_data.rv_index = 0; // 8.3 in 38.213 + pusch_config_pdu->pusch_data.harq_process_id = 0; + pusch_config_pdu->pusch_data.new_data_indicator = 1; // new data + pusch_config_pdu->pusch_data.num_cb = 0; + + } else if (dci) { + + int target_ss; + uint8_t ptrs_time_density; + uint8_t ptrs_freq_density; + nfapi_nr_ue_ptrs_ports_t ptrs_ports_list; + uint16_t n_RB_ULBWP = NRRIV2BW(mac->ULbwp[0]->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + fapi_nr_pusch_config_dedicated_t *pusch_config_dedicated = &mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated; + NR_PUSCH_Config_t *pusch_Config = mac->ULbwp[0]->bwp_Dedicated->pusch_Config->choice.setup; + + // These should come from RRC config!!! + uint8_t ptrs_mcs1 = 2; + uint8_t ptrs_mcs2 = 4; + uint8_t ptrs_mcs3 = 10; + uint16_t n_rb0 = 25; + uint16_t n_rb1 = 75; + + // Basic sanity check for MCS value to check for a false or erroneous DCI + if (dci->mcs > 28) { + LOG_W(MAC, "MCS value %d out of bounds! Possibly due to false DCI. Ignoring DCI!\n", dci->mcs); + return -1; + } + + /* Transform precoding */ + if (rnti_type != NR_RNTI_CS || (rnti_type == NR_RNTI_CS && dci->ndi == 1)) { + pusch_config_pdu->transform_precoding = get_transformPrecoding(scc, pusch_Config, NULL, dci_format, rnti_type, 0); + } + + /*DCI format-related configuration*/ + if (*dci_format == NR_UL_DCI_FORMAT_0_0) { + + target_ss = NR_SearchSpace__searchSpaceType_PR_common; + + } else if (*dci_format == NR_UL_DCI_FORMAT_0_1) { + + /* BANDWIDTH_PART_IND */ + if (dci->bwp_indicator.val != 1) { + LOG_W(MAC, "bwp_indicator != 1! Possibly due to false DCI. Ignoring DCI!\n"); + return -1; + } + config_bwp_ue(mac, &dci->bwp_indicator.val, dci_format); + target_ss = NR_SearchSpace__searchSpaceType_PR_ue_Specific; + ul_layers_config(mac, pusch_config_pdu, dci); + ul_ports_config(mac, pusch_config_pdu, dci); + + } else { + + LOG_E(MAC, "In %s: UL grant from DCI format %d is not handled...\n", __FUNCTION__, *dci_format); + return -1; + + } + + /* TRANSFORM PRECODING ------------------------------------------------------------------------------------------*/ + + if (pusch_config_pdu->transform_precoding == transform_precoder_enabled) { + + pusch_config_pdu->num_dmrs_cdm_grps_no_data = 2; + + NR_DMRS_UplinkConfig_t *NR_DMRS_ulconfig = NULL; + if(pusch_Config->dmrs_UplinkForPUSCH_MappingTypeA != NULL) + NR_DMRS_ulconfig = pusch_Config->dmrs_UplinkForPUSCH_MappingTypeA->choice.setup; + else + NR_DMRS_ulconfig = pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup; + + uint32_t n_RS_Id = 0; + if (NR_DMRS_ulconfig->transformPrecodingEnabled->nPUSCH_Identity != NULL) + n_RS_Id = *NR_DMRS_ulconfig->transformPrecodingEnabled->nPUSCH_Identity; + else + n_RS_Id = *mac->scc->physCellId; + + // U as specified in section 6.4.1.1.1.2 in 38.211, if sequence hopping and group hopping are disabled + pusch_config_pdu->dfts_ofdm.low_papr_group_number = n_RS_Id % 30; + + // V as specified in section 6.4.1.1.1.2 in 38.211 V = 0 if sequence hopping and group hopping are disabled + if ((NR_DMRS_ulconfig->transformPrecodingEnabled->sequenceGroupHopping == NULL) && + (NR_DMRS_ulconfig->transformPrecodingEnabled->sequenceHopping == NULL)) + pusch_config_pdu->dfts_ofdm.low_papr_sequence_number = 0; + else + AssertFatal(1==0,"SequenceGroupHopping or sequenceHopping are NOT Supported\n"); + + LOG_D(MAC,"TRANSFORM PRECODING IS ENABLED. CDM groups: %d, U: %d \n", pusch_config_pdu->num_dmrs_cdm_grps_no_data, + pusch_config_pdu->dfts_ofdm.low_papr_group_number); + } + + /* TRANSFORM PRECODING --------------------------------------------------------------------------------------------------------*/ + + /* IDENTIFIER_DCI_FORMATS */ + /* FREQ_DOM_RESOURCE_ASSIGNMENT_UL */ + if (nr_ue_process_dci_freq_dom_resource_assignment(pusch_config_pdu, NULL, n_RB_ULBWP, 0, dci->frequency_domain_assignment.val) < 0){ + return -1; + } + /* TIME_DOM_RESOURCE_ASSIGNMENT */ + if (nr_ue_process_dci_time_dom_resource_assignment(mac, pusch_config_pdu, NULL, dci->time_domain_assignment.val) < 0) { + return -1; + } + + /* FREQ_HOPPING_FLAG */ + if ((pusch_config_dedicated->resource_allocation != 0) && (pusch_config_dedicated->frequency_hopping !=0)){ + pusch_config_pdu->frequency_hopping = dci->frequency_hopping_flag.val; + } + + /* MCS */ + pusch_config_pdu->mcs_index = dci->mcs; + + /* MCS TABLE */ + if (pusch_config_pdu->transform_precoding == transform_precoder_disabled) { + pusch_config_pdu->mcs_table = get_pusch_mcs_table(pusch_Config->mcs_Table, 0, *dci_format, rnti_type, target_ss, false); + } else { + pusch_config_pdu->mcs_table = get_pusch_mcs_table(pusch_Config->mcs_TableTransformPrecoder, 1, *dci_format, rnti_type, target_ss, false); + } + + /* NDI */ + pusch_config_pdu->pusch_data.new_data_indicator = dci->ndi; + /* RV */ + pusch_config_pdu->pusch_data.rv_index = dci->rv; + /* HARQ_PROCESS_NUMBER */ + pusch_config_pdu->pusch_data.harq_process_id = dci->harq_pid; + /* TPC_PUSCH */ + // according to TS 38.213 Table Table 7.1.1-1 + if (dci->tpc == 0) { + pusch_config_pdu->absolute_delta_PUSCH = -4; + } + if (dci->tpc == 1) { + pusch_config_pdu->absolute_delta_PUSCH = -1; + } + if (dci->tpc == 2) { + pusch_config_pdu->absolute_delta_PUSCH = 1; + } + if (dci->tpc == 3) { + pusch_config_pdu->absolute_delta_PUSCH = 4; + } + + ptrs_time_density = get_L_ptrs(ptrs_mcs1, ptrs_mcs2, ptrs_mcs3, pusch_config_pdu->mcs_index, pusch_config_pdu->mcs_table); + ptrs_freq_density = get_K_ptrs(n_rb0, n_rb1, pusch_config_pdu->rb_size); + // PTRS ports configuration + // TbD: ptrs_dmrs_port and ptrs_port_index are not initialised! + ptrs_ports_list.ptrs_re_offset = 0; + + /* DMRS */ + l_prime_mask = get_l_prime(pusch_config_pdu->nr_of_symbols, typeB, pusch_dmrs_pos0, pusch_len1); + if (pusch_config_pdu->transform_precoding == transform_precoder_disabled) + pusch_config_pdu->num_dmrs_cdm_grps_no_data = 1; + + // Num PRB Overhead from PUSCH-ServingCellConfig + if (mac->scg->spCellConfig->spCellConfigDedicated->uplinkConfig->pusch_ServingCellConfig->choice.setup->xOverhead == NULL) { + N_PRB_oh = 0; + } else { + N_PRB_oh = *mac->scg->spCellConfig->spCellConfigDedicated->uplinkConfig->pusch_ServingCellConfig->choice.setup->xOverhead; + } + + /* PTRS */ + pusch_config_pdu->pusch_ptrs.ptrs_time_density = ptrs_time_density; + pusch_config_pdu->pusch_ptrs.ptrs_freq_density = ptrs_freq_density; + pusch_config_pdu->pusch_ptrs.ptrs_ports_list = &ptrs_ports_list; + + if (1 << pusch_config_pdu->pusch_ptrs.ptrs_time_density >= pusch_config_pdu->nr_of_symbols) { + pusch_config_pdu->pdu_bit_map &= ~PUSCH_PDU_BITMAP_PUSCH_PTRS; // disable PUSCH PTRS + } + + } + + LOG_D(MAC, "In %s: received UL grant (rb_start %d, rb_size %d, start_symbol_index %d, nr_of_symbols %d) for RNTI type %s \n", + __FUNCTION__, + pusch_config_pdu->rb_start, + pusch_config_pdu->rb_size, + pusch_config_pdu->start_symbol_index, + pusch_config_pdu->nr_of_symbols, + rnti_types[rnti_type]); + + pusch_config_pdu->ul_dmrs_symb_pos = l_prime_mask << pusch_config_pdu->start_symbol_index;; + pusch_config_pdu->target_code_rate = nr_get_code_rate_ul(pusch_config_pdu->mcs_index, pusch_config_pdu->mcs_table); + pusch_config_pdu->qam_mod_order = nr_get_Qm_ul(pusch_config_pdu->mcs_index, pusch_config_pdu->mcs_table); + + if (pusch_config_pdu->target_code_rate == 0 || pusch_config_pdu->qam_mod_order == 0) { + LOG_W(MAC, "In %s: Invalid code rate or Mod order, likely due to unexpected UL DCI. Ignoring DCI! \n", __FUNCTION__); + return -1; + } + + get_num_re_dmrs(pusch_config_pdu, &nb_dmrs_re_per_rb, &number_dmrs_symbols); + + // Compute TBS + pusch_config_pdu->pusch_data.tb_size = nr_compute_tbs(pusch_config_pdu->qam_mod_order, + pusch_config_pdu->target_code_rate, + pusch_config_pdu->rb_size, + pusch_config_pdu->nr_of_symbols, + nb_dmrs_re_per_rb*number_dmrs_symbols, + N_PRB_oh, + 0, // TBR to verify tb scaling + pusch_config_pdu->nrOfLayers)/8; + + return 0; + +} + +// Performs : +// 1. TODO: Call RRC for link status return to PHY +// 2. TODO: Perform SR/BSR procedures for scheduling feedback +// 3. TODO: Perform PHR procedures +NR_UE_L2_STATE_t nr_ue_scheduler(nr_downlink_indication_t *dl_info, nr_uplink_indication_t *ul_info){ + + uint32_t search_space_mask = 0; + + if (dl_info){ + + module_id_t mod_id = dl_info->module_id; + uint32_t gNB_index = dl_info->gNB_index; + int cc_id = dl_info->cc_id; + frame_t rx_frame = dl_info->frame; + slot_t rx_slot = dl_info->slot; + NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id); + + fapi_nr_dl_config_request_t *dl_config = &mac->dl_config_request; + nr_scheduled_response_t scheduled_response; + nr_dcireq_t dcireq; + + // check type0 from 38.213 13 if we have no CellGroupConfig + // TODO: implementation to be completed + if (mac->scg == NULL) { + + if(dl_info->ssb_index != -1){ + + if(mac->type0_pdcch_ss_mux_pattern == 1){ + // 38.213 chapter 13 + if((mac->type0_pdcch_ss_sfn_c == SFN_C_MOD_2_EQ_0) && !(rx_frame & 0x1) && (rx_slot == mac->type0_pdcch_ss_n_c)){ + search_space_mask = search_space_mask | type0_pdcch; + mac->type0_pdcch_consecutive_slots = mac->type0_pdcch_dci_config.coreset.duration; + } + if((mac->type0_pdcch_ss_sfn_c == SFN_C_MOD_2_EQ_1) && (rx_frame & 0x1) && (rx_slot == mac->type0_pdcch_ss_n_c)){ + search_space_mask = search_space_mask | type0_pdcch; + mac->type0_pdcch_consecutive_slots = mac->type0_pdcch_dci_config.coreset.duration; + } + } + if(mac->type0_pdcch_ss_mux_pattern == 2){ + // 38.213 Table 13-13, 13-14 + if((rx_frame == get_ssb_frame(rx_frame)) && (rx_slot == mac->type0_pdcch_ss_n_c)){ + search_space_mask = search_space_mask | type0_pdcch; + mac->type0_pdcch_consecutive_slots = mac->type0_pdcch_dci_config.coreset.duration; + } + } + if(mac->type0_pdcch_ss_mux_pattern == 3){ + // 38.213 Table 13-15 + if((rx_frame == get_ssb_frame(rx_frame)) && (rx_slot == mac->type0_pdcch_ss_n_c)){ + search_space_mask = search_space_mask | type0_pdcch; + mac->type0_pdcch_consecutive_slots = mac->type0_pdcch_dci_config.coreset.duration; + } + } + } // ssb_index != -1 + + // Type0 PDCCH search space + if((search_space_mask & type0_pdcch) || ( mac->type0_pdcch_consecutive_slots != 0 )){ + mac->type0_pdcch_consecutive_slots = mac->type0_pdcch_consecutive_slots - 1; + + dl_config->dl_config_list[dl_config->number_pdus].dci_config_pdu.dci_config_rel15 = mac->type0_pdcch_dci_config; + dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_DL_CONFIG_TYPE_DCI; + + /* + dl_config->dl_config_list[dl_config->number_pdus].dci_config_pdu.dci_config_rel15.rnti = 0xaaaa; // to be set + dl_config->dl_config_list[dl_config->number_pdus].dci_config_pdu.dci_config_rel15.N_RB_BWP = 106; // to be set + + LOG_I(MAC,"nr_ue_scheduler Type0 PDCCH with rnti %x, BWP %d\n", + dl_config->dl_config_list[dl_config->number_pdus].dci_config_pdu.dci_config_rel15.rnti, + dl_config->dl_config_list[dl_config->number_pdus].dci_config_pdu.dci_config_rel15.N_RB_BWP); + */ + dl_config->number_pdus = dl_config->number_pdus + 1; + + fill_scheduled_response(&scheduled_response, dl_config, NULL, NULL, mod_id, cc_id, rx_frame, rx_slot, dl_info->thread_id); + if(mac->if_module != NULL && mac->if_module->scheduled_response != NULL) + mac->if_module->scheduled_response(&scheduled_response); + } + } else { // we have an scg + + dcireq.module_id = mod_id; + dcireq.gNB_index = gNB_index; + dcireq.cc_id = cc_id; + dcireq.frame = rx_frame; + dcireq.slot = rx_slot; + dcireq.dl_config_req.number_pdus = 0; + nr_ue_dcireq(&dcireq); //to be replaced with function pointer later + + fill_scheduled_response(&scheduled_response, &dcireq.dl_config_req, NULL, NULL, mod_id, cc_id, rx_frame, rx_slot, dl_info->thread_id); + if(mac->if_module != NULL && mac->if_module->scheduled_response != NULL){ + mac->if_module->scheduled_response(&scheduled_response); + } + + /* + if(search_space_mask & type0a_pdcch){ + } + + if(search_space_mask & type1_pdcch){ + } + + if(search_space_mask & type2_pdcch){ + } + + if(search_space_mask & type3_pdcch){ + } + */ + } + } else if (ul_info) { + + int cc_id = ul_info->cc_id; + frame_t rx_frame = ul_info->frame_rx; + slot_t rx_slot = ul_info->slot_rx; + frame_t frame_tx = ul_info->frame_tx; + slot_t slot_tx = ul_info->slot_tx; + module_id_t mod_id = ul_info->module_id; + uint8_t access_mode = SCHEDULED_ACCESS; + + NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id); + RA_config_t *ra = &mac->ra; + + fapi_nr_ul_config_request_t *ul_config = get_ul_config_request(mac, slot_tx); + + // Schedule ULSCH only if the current frame and slot match those in ul_config_req + // AND if a UL grant (UL DCI or Msg3) has been received (as indicated by num_pdus) + if ((ul_info->slot_tx == ul_config->slot && ul_info->frame_tx == ul_config->sfn) && ul_config->number_pdus > 0){ + + LOG_D(MAC, "In %s:[%d.%d]: number of UL PDUs: %d with UL transmission in [%d.%d]\n", __FUNCTION__, frame_tx, slot_tx, ul_config->number_pdus, ul_config->sfn, ul_config->slot); + + uint8_t ulsch_input_buffer[MAX_ULSCH_PAYLOAD_BYTES]; + uint8_t data_existing = 0; + nr_scheduled_response_t scheduled_response; + fapi_nr_tx_request_t tx_req; + + for (int j = 0; j < ul_config->number_pdus; j++) { + + fapi_nr_ul_config_request_pdu_t *ulcfg_pdu = &ul_config->ul_config_list[j]; + + if (ulcfg_pdu->pdu_type == FAPI_NR_UL_CONFIG_TYPE_PUSCH) { + + uint16_t TBS_bytes = ulcfg_pdu->pusch_config_pdu.pusch_data.tb_size; + + // Push data from MAC to PHY only when NDI toggles + if (IS_SOFTMODEM_NOS1 && (mac->UL_ndi[ulcfg_pdu->pusch_config_pdu.pusch_data.harq_process_id] != ulcfg_pdu->pusch_config_pdu.pusch_data.new_data_indicator)){ + // Getting IP traffic to be transmitted + data_existing = nr_ue_get_sdu(mod_id, + cc_id, + frame_tx, + slot_tx, + 0, + ulsch_input_buffer, + TBS_bytes, + &access_mode); + } + + mac->UL_ndi[ulcfg_pdu->pusch_config_pdu.pusch_data.harq_process_id] = ulcfg_pdu->pusch_config_pdu.pusch_data.new_data_indicator; + //Random traffic to be transmitted if there is no IP traffic available for this Tx opportunity + if (!IS_SOFTMODEM_NOS1 || !data_existing) { + //Use zeros for the header bytes in noS1 mode, in order to make sure that the LCID is not valid + //and block this traffic from being forwarded to the upper layers at the gNB + LOG_D(PHY, "In %s: Random data to be transmitted: TBS_bytes %d \n", __FUNCTION__, TBS_bytes); + + //Give the first byte a dummy value (a value not corresponding to any valid LCID based on 38.321, Table 6.2.1-2) + //in order to distinguish the PHY random packets at the MAC layer of the gNB receiver from the normal packets that should + //have a valid LCID (nr_process_mac_pdu function) + ulsch_input_buffer[0] = 0x31; + + for (int i = 1; i < TBS_bytes; i++) { + ulsch_input_buffer[i] = (unsigned char) rand(); + //printf(" input encoder a[%d]=0x%02x\n",i,harq_process_ul_ue->a[i]); + } + } + + #ifdef DEBUG_MAC_PDU + LOG_D(PHY, "Is data existing ?: %d \n", data_existing); + LOG_I(PHY, "Printing MAC PDU to be encoded, TBS is: %d \n", TBS_bytes); + for (i = 0; i < TBS_bytes; i++) { + printf("%02x", ulsch_input_buffer[i]); + } + printf("\n"); + #endif + + // Config UL TX PDU + tx_req.slot = slot_tx; + tx_req.sfn = frame_tx; + tx_req.number_of_pdus++; + tx_req.tx_request_body[0].pdu_length = TBS_bytes; + tx_req.tx_request_body[0].pdu_index = j; + tx_req.tx_request_body[0].pdu = ulsch_input_buffer; + + if (ra->ra_state != RA_SUCCEEDED && !ra->cfra){ + nr_Msg3_transmitted(ul_info->module_id, ul_info->cc_id, ul_info->frame_tx, ul_info->gNB_index); + } + + } + } + + fill_scheduled_response(&scheduled_response, NULL, ul_config, &tx_req, mod_id, cc_id, rx_frame, rx_slot, ul_info->thread_id); + if(mac->if_module != NULL && mac->if_module->scheduled_response != NULL){ + mac->if_module->scheduled_response(&scheduled_response); + } + } + } + + return UE_CONNECTION_OK; + +} + +// PUSCH scheduler: +// - Calculate the slot in which ULSCH should be scheduled. This is current slot + K2, +// - where K2 is the offset between the slot in which UL DCI is received and the slot +// - in which ULSCH should be scheduled. K2 is configured in RRC configuration. +// PUSCH Msg3 scheduler: +// - scheduled by RAR UL grant according to 8.3 of TS 38.213 +// Note: Msg3 tx in the uplink symbols of mixed slot +int nr_ue_pusch_scheduler(NR_UE_MAC_INST_t *mac, + uint8_t is_Msg3, + frame_t current_frame, + int current_slot, + frame_t *frame_tx, + int *slot_tx, + uint8_t tda_id){ + + int delta = 0; + NR_BWP_Uplink_t *ubwp = mac->ULbwp[0]; + // Get the numerology to calculate the Tx frame and slot + int mu = ubwp->bwp_Common->genericParameters.subcarrierSpacing; + struct NR_PUSCH_TimeDomainResourceAllocationList *pusch_TimeDomainAllocationList = ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList; + // k2 as per 3GPP TS 38.214 version 15.9.0 Release 15 ch 6.1.2.1.1 + // PUSCH time domain resource allocation is higher layer configured from uschTimeDomainAllocationList in either pusch-ConfigCommon + uint8_t k2; + + if (is_Msg3) { + k2 = *pusch_TimeDomainAllocationList->list.array[tda_id]->k2; + + switch (mu) { + case 0: + delta = 2; + break; + case 1: + delta = 3; + break; + case 2: + delta = 4; + break; + case 3: + delta = 6; + break; + } + + *slot_tx = (current_slot + k2 + delta) % nr_slots_per_frame[mu]; + if (current_slot + k2 + delta > nr_slots_per_frame[mu]){ + *frame_tx = (current_frame + 1) % 1024; + } else { + *frame_tx = current_frame; + } + + } else { + + // Get slot offset K2 which will be used to calculate TX slot + k2 = get_k2(mac, tda_id); + if (k2 < 0) { // This can happen when a false DCI is received + return -1; + } + + // Calculate TX slot and frame + *slot_tx = (current_slot + k2) % nr_slots_per_frame[mu]; + *frame_tx = ((current_slot + k2) > nr_slots_per_frame[mu]) ? (current_frame + 1) % 1024 : current_frame; + + } + + LOG_D(MAC, "In %s: currently at [%d.%d] UL transmission in [%d.%d] (k2 %d delta %d)\n", __FUNCTION__, current_frame, current_slot, *frame_tx, *slot_tx, k2, delta); + + return 0; + +} + +// Build the list of all the valid RACH occasions in the maximum association pattern period according to the PRACH config +static void build_ro_list(NR_ServingCellConfigCommon_t *scc, uint8_t unpaired) { + + int x,y; // PRACH Configuration Index table variables used to compute the valid frame numbers + int y2; // PRACH Configuration Index table additional variable used to compute the valid frame numbers + uint8_t slot_shift_for_map; + uint8_t map_shift; + boolean_t even_slot_invalid; + int64_t s_map; + uint8_t prach_conf_start_symbol; // Starting symbol of the PRACH occasions in the PRACH slot + uint8_t N_t_slot; // Number of PRACH occasions in a 14-symbols PRACH slot + uint8_t N_dur; // Duration of a PRACH occasion (nb of symbols) + uint8_t frame; // Maximum is NB_FRAMES_IN_MAX_ASSOCIATION_PATTERN_PERIOD + uint8_t slot; // Maximum is the number of slots in a frame @ SCS 240kHz + uint16_t format = 0xffff; + uint8_t format2 = 0xff; + int nb_fdm; + + uint8_t config_index, mu; + uint32_t pointa; + int msg1_FDM; + + uint8_t prach_conf_period_idx; + uint8_t nb_of_frames_per_prach_conf_period; + uint8_t prach_conf_period_frame_idx; + int64_t *prach_config_info_p; + + NR_RACH_ConfigCommon_t *setup = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup; + NR_FrequencyInfoDL_t *frequencyInfoDL = scc->downlinkConfigCommon->frequencyInfoDL; + NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &setup->rach_ConfigGeneric; + + config_index = rach_ConfigGeneric->prach_ConfigurationIndex; + + if (setup->msg1_SubcarrierSpacing) + mu = *setup->msg1_SubcarrierSpacing; + else + mu = frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; + + pointa = frequencyInfoDL->absoluteFrequencyPointA; + msg1_FDM = rach_ConfigGeneric->msg1_FDM; + + switch (msg1_FDM){ + case 0: + case 1: + case 2: + case 3: + nb_fdm = 1 << msg1_FDM; + break; + default: + AssertFatal(1 == 0, "Unknown msg1_FDM from rach_ConfigGeneric %d\n", msg1_FDM); + } + + // Create the PRACH occasions map + // ============================== + // WIP: For now assume no rejected PRACH occasions because of conflict with SSB or TDD_UL_DL_ConfigurationCommon schedule + + // Identify the proper PRACH Configuration Index table according to the operating frequency + LOG_D(MAC,"Pointa %u, mu = %u, PRACH config index = %u, unpaired = %u\n", pointa, mu, config_index, unpaired); + + prach_config_info_p = get_prach_config_info(pointa, config_index, unpaired); + + if (pointa > 2016666) { //FR2 + + x = prach_config_info_p[2]; + y = prach_config_info_p[3]; + y2 = prach_config_info_p[4]; + + s_map = prach_config_info_p[5]; + + prach_conf_start_symbol = prach_config_info_p[6]; + N_t_slot = prach_config_info_p[8]; + N_dur = prach_config_info_p[9]; + if (prach_config_info_p[1] != -1) + format2 = (uint8_t) prach_config_info_p[1]; + format = ((uint8_t) prach_config_info_p[0]) | (format2<<8); + + slot_shift_for_map = mu-2; + if ( (mu == 3) && (prach_config_info_p[7] == 1) ) + even_slot_invalid = true; + else + even_slot_invalid = false; + } + else { // FR1 + x = prach_config_info_p[2]; + y = prach_config_info_p[3]; + y2 = y; + + s_map = prach_config_info_p[4]; + + prach_conf_start_symbol = prach_config_info_p[5]; + N_t_slot = prach_config_info_p[7]; + N_dur = prach_config_info_p[8]; + if (prach_config_info_p[1] != -1) + format2 = (uint8_t) prach_config_info_p[1]; + format = ((uint8_t) prach_config_info_p[0]) | (format2<<8); + + slot_shift_for_map = mu; + if ( (mu == 1) && (prach_config_info_p[6] <= 1) ) + // no prach in even slots @ 30kHz for 1 prach per subframe + even_slot_invalid = true; + else + even_slot_invalid = false; + } // FR2 / FR1 + + prach_assoc_pattern.nb_of_prach_conf_period_in_max_period = MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD / x; + nb_of_frames_per_prach_conf_period = x; + + LOG_D(MAC,"nb_of_prach_conf_period_in_max_period %d\n", prach_assoc_pattern.nb_of_prach_conf_period_in_max_period); + + // Fill in the PRACH occasions table for every slot in every frame in every PRACH configuration periods in the maximum association pattern period + // ---------------------------------------------------------------------------------------------------------------------------------------------- + // ---------------------------------------------------------------------------------------------------------------------------------------------- + // For every PRACH configuration periods + // ------------------------------------- + for (prach_conf_period_idx=0; prach_conf_period_idx> slot_shift_for_map; // in PRACH configuration index table slots are numbered wrt 60kHz + if ( (s_map>>map_shift)&0x01 ) { + // Valid slot + + // Additionally, for 30kHz/120kHz, we must check for the n_RA_Slot param also + if ( even_slot_invalid && (slot%2 == 0) ) + continue; // no prach in even slots @ 30kHz/120kHz for 1 prach per 60khz slot/subframe + + // We're good: valid frame and valid slot + // Compute all the PRACH occasions in the slot + + uint8_t n_prach_occ_in_time; + uint8_t n_prach_occ_in_freq; + + prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].prach_occasion_slot_map[prach_conf_period_frame_idx][slot].nb_of_prach_occasion_in_time = N_t_slot; + prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].prach_occasion_slot_map[prach_conf_period_frame_idx][slot].nb_of_prach_occasion_in_freq = nb_fdm; + + for (n_prach_occ_in_time=0; n_prach_occ_in_timestart_symbol = start_symbol; + prach_occasion_p->fdm = n_prach_occ_in_freq; + prach_occasion_p->frame = frame; + prach_occasion_p->slot = slot; + prach_occasion_p->format = format; + prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].nb_of_prach_occasion++; + + LOG_D(MAC,"Adding a PRACH occasion: frame %u, slot-symbol %d-%d, occ_in_time-occ_in-freq %d-%d, nb ROs in conf period %d, for this slot: RO# in time %d, RO# in freq %d\n", + frame, slot, start_symbol, n_prach_occ_in_time, n_prach_occ_in_freq, prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].nb_of_prach_occasion, + prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].prach_occasion_slot_map[prach_conf_period_frame_idx][slot].nb_of_prach_occasion_in_time, + prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].prach_occasion_slot_map[prach_conf_period_frame_idx][slot].nb_of_prach_occasion_in_freq); + } // For every freq in the slot + } // For every time occasions in the slot + } // Valid slot? + } // For every slots in a frame + } // Valid frame? + } // For every frames in a prach configuration period + } // For every prach configuration periods in the maximum association pattern period (160ms) +} + +// Build the list of all the valid/transmitted SSBs according to the config +static void build_ssb_list(NR_ServingCellConfigCommon_t *scc) { + + // Create the list of transmitted SSBs + // =================================== + BIT_STRING_t *ssb_bitmap; + uint64_t ssb_positionsInBurst; + uint8_t ssb_idx = 0; + + switch (scc->ssb_PositionsInBurst->present) { + case NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_shortBitmap: + ssb_bitmap = &scc->ssb_PositionsInBurst->choice.shortBitmap; + + ssb_positionsInBurst = BIT_STRING_to_uint8(ssb_bitmap); + LOG_D(MAC,"SSB config: SSB_positions_in_burst 0x%lx\n", ssb_positionsInBurst); + + for (uint8_t bit_nb=3; bit_nb<=3; bit_nb--) { + // If SSB is transmitted + if ((ssb_positionsInBurst>>bit_nb) & 0x01) { + ssb_list.nb_tx_ssb++; + ssb_list.tx_ssb[ssb_idx].transmitted = true; + LOG_D(MAC,"SSB idx %d transmitted\n", ssb_idx); + } + ssb_idx++; + } + break; + case NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_mediumBitmap: + ssb_bitmap = &scc->ssb_PositionsInBurst->choice.mediumBitmap; + + ssb_positionsInBurst = BIT_STRING_to_uint8(ssb_bitmap); + LOG_D(MAC,"SSB config: SSB_positions_in_burst 0x%lx\n", ssb_positionsInBurst); + + for (uint8_t bit_nb=7; bit_nb<=7; bit_nb--) { + // If SSB is transmitted + if ((ssb_positionsInBurst>>bit_nb) & 0x01) { + ssb_list.nb_tx_ssb++; + ssb_list.tx_ssb[ssb_idx].transmitted = true; + LOG_D(MAC,"SSB idx %d transmitted\n", ssb_idx); + } + ssb_idx++; + } + break; + case NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_longBitmap: + ssb_bitmap = &scc->ssb_PositionsInBurst->choice.longBitmap; + + ssb_positionsInBurst = BIT_STRING_to_uint64(ssb_bitmap); + LOG_D(MAC,"SSB config: SSB_positions_in_burst 0x%lx\n", ssb_positionsInBurst); + + for (uint8_t bit_nb=63; bit_nb<=63; bit_nb--) { + // If SSB is transmitted + if ((ssb_positionsInBurst>>bit_nb) & 0x01) { + ssb_list.nb_tx_ssb++; + ssb_list.tx_ssb[ssb_idx].transmitted = true; + LOG_D(MAC,"SSB idx %d transmitted\n", ssb_idx); + } + ssb_idx++; + } + break; + default: + AssertFatal(false,"ssb_PositionsInBurst not present\n"); + break; + } +} + +// Map the transmitted SSBs to the ROs and create the association pattern according to the config +static void map_ssb_to_ro(NR_ServingCellConfigCommon_t *scc) { + + // Map SSBs to PRACH occasions + // =========================== + // WIP: Assumption: No PRACH occasion is rejected because of a conflict with SSBs or TDD_UL_DL_ConfigurationCommon schedule + NR_RACH_ConfigCommon_t *setup = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup; + NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR ssb_perRACH_config = setup->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present; + + boolean_t multiple_ssb_per_ro; // true if more than one or exactly one SSB per RACH occasion, false if more than one RO per SSB + uint8_t ssb_rach_ratio; // Nb of SSBs per RACH or RACHs per SSB + uint16_t required_nb_of_prach_occasion; // Nb of RACH occasions required to map all the SSBs + uint8_t required_nb_of_prach_conf_period; // Nb of PRACH configuration periods required to map all the SSBs + + // Determine the SSB to RACH mapping ratio + // ======================================= + switch (ssb_perRACH_config){ + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneEighth: + multiple_ssb_per_ro = false; + ssb_rach_ratio = 8; + break; + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneFourth: + multiple_ssb_per_ro = false; + ssb_rach_ratio = 4; + break; + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneHalf: + multiple_ssb_per_ro = false; + ssb_rach_ratio = 2; + break; + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_one: + multiple_ssb_per_ro = true; + ssb_rach_ratio = 1; + break; + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_two: + multiple_ssb_per_ro = true; + ssb_rach_ratio = 2; + break; + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_four: + multiple_ssb_per_ro = true; + ssb_rach_ratio = 4; + break; + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_eight: + multiple_ssb_per_ro = true; + ssb_rach_ratio = 8; + break; + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_sixteen: + multiple_ssb_per_ro = true; + ssb_rach_ratio = 16; + break; + default: + AssertFatal(1 == 0, "Unsupported ssb_perRACH_config %d\n", ssb_perRACH_config); + break; + } + LOG_D(MAC,"SSB rach ratio %d, Multiple SSB per RO %d\n", ssb_rach_ratio, multiple_ssb_per_ro); + + // Evaluate the number of PRACH configuration periods required to map all the SSBs and set the association period + // ============================================================================================================== + // WIP: Assumption for now is that all the PRACH configuration periods within a maximum association pattern period have the same number of PRACH occasions + // (No PRACH occasions are conflicting with SSBs nor TDD_UL_DL_ConfigurationCommon schedule) + // There is only one possible association period which can contain up to 16 PRACH configuration periods + LOG_D(MAC,"Evaluate the number of PRACH configuration periods required to map all the SSBs and set the association period\n"); + if (true == multiple_ssb_per_ro) { + required_nb_of_prach_occasion = ((ssb_list.nb_tx_ssb-1) + ssb_rach_ratio) / ssb_rach_ratio; + } + else { + required_nb_of_prach_occasion = ssb_list.nb_tx_ssb * ssb_rach_ratio; + } + + required_nb_of_prach_conf_period = ((required_nb_of_prach_occasion-1) + prach_assoc_pattern.prach_conf_period_list[0].nb_of_prach_occasion) / prach_assoc_pattern.prach_conf_period_list[0].nb_of_prach_occasion; + + if (required_nb_of_prach_conf_period == 1) { + prach_assoc_pattern.prach_association_period_list[0].nb_of_prach_conf_period = 1; + } + else if (required_nb_of_prach_conf_period == 2) { + prach_assoc_pattern.prach_association_period_list[0].nb_of_prach_conf_period = 2; + } + else if (required_nb_of_prach_conf_period <= 4) { + prach_assoc_pattern.prach_association_period_list[0].nb_of_prach_conf_period = 4; + } + else if (required_nb_of_prach_conf_period <= 8) { + prach_assoc_pattern.prach_association_period_list[0].nb_of_prach_conf_period = 8; + } + else if (required_nb_of_prach_conf_period <= 16) { + prach_assoc_pattern.prach_association_period_list[0].nb_of_prach_conf_period = 16; + } + else { + AssertFatal(1 == 0, "Invalid number of PRACH config periods within an association period %d\n", required_nb_of_prach_conf_period); + } + + prach_assoc_pattern.nb_of_assoc_period = 1; // WIP: only one possible association period + prach_assoc_pattern.prach_association_period_list[0].nb_of_frame = prach_assoc_pattern.prach_association_period_list[0].nb_of_prach_conf_period * prach_assoc_pattern.prach_conf_period_list[0].nb_of_frame; + prach_assoc_pattern.nb_of_frame = prach_assoc_pattern.prach_association_period_list[0].nb_of_frame; + + LOG_D(MAC,"Assoc period %d, Nb of frames in assoc period %d\n", + prach_assoc_pattern.prach_association_period_list[0].nb_of_prach_conf_period, + prach_assoc_pattern.prach_association_period_list[0].nb_of_frame); + + // Proceed to the SSB to RO mapping + // ================================ + uint8_t association_period_idx; // Association period index within the association pattern + uint8_t ssb_idx = 0; + uint8_t prach_configuration_period_idx; // PRACH Configuration period index within the association pattern + prach_conf_period_t *prach_conf_period_p; + + // Map all the association periods within the association pattern period + LOG_D(MAC,"Proceed to the SSB to RO mapping\n"); + for (association_period_idx=0; association_period_idxnb_of_frame; frame++) { + for (slot=0; slotnb_of_slot; slot++) { + for (ro_in_time=0; ro_in_timeprach_occasion_slot_map[frame][slot].nb_of_prach_occasion_in_time; ro_in_time++) { + for (ro_in_freq=0; ro_in_freqprach_occasion_slot_map[frame][slot].nb_of_prach_occasion_in_freq; ro_in_freq++) { + prach_occasion_info_t *ro_p = &prach_conf_period_p->prach_occasion_slot_map[frame][slot].prach_occasion[ro_in_time][ro_in_freq]; + + // Go through the list of transmitted SSBs and map the required amount of SSBs to this RO + // WIP: For the moment, only map each SSB idx once per association period if configuration is multiple SSBs per RO + // this is true if no PRACH occasions are conflicting with SSBs nor TDD_UL_DL_ConfigurationCommon schedule + for (; ssb_idxmapped_ssb_idx[ro_p->nb_mapped_ssb] = ssb_idx; + ro_p->nb_mapped_ssb++; + ssb_list.tx_ssb[ssb_idx].mapped_ro[ssb_list.tx_ssb[ssb_idx].nb_mapped_ro] = ro_p; + ssb_list.tx_ssb[ssb_idx].nb_mapped_ro++; + AssertFatal(MAX_NB_RO_PER_SSB_IN_ASSOCIATION_PATTERN > ssb_list.tx_ssb[ssb_idx].nb_mapped_ro,"Too many mapped ROs (%d) to a single SSB\n", ssb_list.tx_ssb[ssb_idx].nb_mapped_ro); + + LOG_D(MAC,"Mapped ssb_idx %u to RO slot-symbol %u-%u, %u-%u-%u/%u\n", ssb_idx, ro_p->slot, ro_p->start_symbol, slot, ro_in_time, ro_in_freq, prach_conf_period_p->prach_occasion_slot_map[frame][slot].nb_of_prach_occasion_in_freq); + LOG_D(MAC,"Nb mapped ROs for this ssb idx: in the association period only %u\n", ssb_list.tx_ssb[ssb_idx].nb_mapped_ro); + + // If all the required SSBs are mapped to this RO, exit the loop of SSBs + if (ro_p->nb_mapped_ssb == ssb_rach_ratio) { + ssb_idx++; + break; + } + } // if ssb_idx is transmitted + } // for ssb_idx + + // Exit the loop of ROs if there is no more SSB to map + if (MAX_NB_SSB == ssb_idx) break; + } // for ro_in_freq + + // Exit the loop of ROs if there is no more SSB to map + if (MAX_NB_SSB == ssb_idx) break; + } // for ro_in_time + + // Exit the loop of slots if there is no more SSB to map + if (MAX_NB_SSB == ssb_idx) break; + } // for slot + + // Exit the loop frames if there is no more SSB to map + if (MAX_NB_SSB == ssb_idx) break; + } // for frame + + // Exit the loop of PRACH configurations if there is no more SSB to map + if (MAX_NB_SSB == ssb_idx) break; + } // for n_prach_conf + + // WIP: note that there is no re-mapping of the SSBs within the association period since there is no invalid ROs in the PRACH config periods that would create this situation + + } // if multiple_ssbs_per_ro + + else { + // -------------------- + // -------------------- + // Multiple ROs per SSB + // -------------------- + // -------------------- + + n_prach_conf = 0; + + // Go through the list of transmitted SSBs + for (ssb_idx=0; ssb_idxnb_of_frame; frame++) { + for (; slotnb_of_slot; slot++) { + for (; ro_in_timeprach_occasion_slot_map[frame][slot].nb_of_prach_occasion_in_time; ro_in_time++) { + for (; ro_in_freqprach_occasion_slot_map[frame][slot].nb_of_prach_occasion_in_freq; ro_in_freq++) { + prach_occasion_info_t *ro_p = &prach_conf_period_p->prach_occasion_slot_map[frame][slot].prach_occasion[ro_in_time][ro_in_freq]; + + ro_p->mapped_ssb_idx[0] = ssb_idx; + ro_p->nb_mapped_ssb = 1; + ssb_list.tx_ssb[ssb_idx].mapped_ro[ssb_list.tx_ssb[ssb_idx].nb_mapped_ro] = ro_p; + ssb_list.tx_ssb[ssb_idx].nb_mapped_ro++; + AssertFatal(MAX_NB_RO_PER_SSB_IN_ASSOCIATION_PATTERN > ssb_list.tx_ssb[ssb_idx].nb_mapped_ro,"Too many mapped ROs (%d) to a single SSB\n", ssb_list.tx_ssb[ssb_idx].nb_mapped_ro); + nb_mapped_ro_in_association_period++; + + LOG_D(MAC,"Mapped ssb_idx %u to RO slot-symbol %u-%u, %u-%u-%u/%u\n", ssb_idx, ro_p->slot, ro_p->start_symbol, slot, ro_in_time, ro_in_freq, prach_conf_period_p->prach_occasion_slot_map[frame][slot].nb_of_prach_occasion_in_freq); + LOG_D(MAC,"Nb mapped ROs for this ssb idx: in the association period only %u / total %u\n", ssb_list.tx_ssb[ssb_idx].nb_mapped_ro, nb_mapped_ro_in_association_period); + + // Exit the loop if this SSB has been mapped to all the required ROs + // WIP: Assuming that ssb_rach_ratio equals the maximum nb of times a given ssb_idx is mapped within an association period: + // this is true if no PRACH occasions are conflicting with SSBs nor TDD_UL_DL_ConfigurationCommon schedule + if (nb_mapped_ro_in_association_period == ssb_rach_ratio) { + ro_in_freq++; + break; + } + } // for ro_in_freq + + // Exit the loop if this SSB has been mapped to all the required ROs + if (nb_mapped_ro_in_association_period == ssb_rach_ratio) { + break; + } + else ro_in_freq = 0; // else go to the next time symbol in that slot and reset the freq index + } // for ro_in_time + + // Exit the loop if this SSB has been mapped to all the required ROs + if (nb_mapped_ro_in_association_period == ssb_rach_ratio) { + break; + } + else ro_in_time = 0; // else go to the next slot in that PRACH config period and reset the symbol index + } // for slot + + // Exit the loop if this SSB has been mapped to all the required ROs + if (nb_mapped_ro_in_association_period == ssb_rach_ratio) { + break; + } + else slot = 0; // else go to the next frame in that PRACH config period and reset the slot index + } // for frame + + // Exit the loop if this SSB has been mapped to all the required ROs + if (nb_mapped_ro_in_association_period == ssb_rach_ratio) { + break; + } + else frame = 0; // else go to the next PRACH config period in that association period and reset the frame index + } // for n_prach_conf + + } // if ssb_idx is transmitted + } // for ssb_idx + } // else if multiple_ssbs_per_ro + + } // for association_period_index +} + +// Returns a RACH occasion if any matches the SSB idx, the frame and the slot +static int get_nr_prach_info_from_ssb_index(uint8_t ssb_idx, + int frame, + int slot, + prach_occasion_info_t **prach_occasion_info_pp) { + + ssb_info_t *ssb_info_p; + prach_occasion_slot_t *prach_occasion_slot_p = NULL; + + *prach_occasion_info_pp = NULL; + + // Search for a matching RO slot in the SSB_to_RO map + // A valid RO slot will match: + // - ssb_idx mapped to one of the ROs in that RO slot + // - exact slot number + // - frame offset + ssb_info_p = &ssb_list.tx_ssb[ssb_idx]; + for (uint8_t n_mapped_ro=0; n_mapped_ronb_mapped_ro; n_mapped_ro++) { + if ((slot == ssb_info_p->mapped_ro[n_mapped_ro]->slot) && + (ssb_info_p->mapped_ro[n_mapped_ro]->frame == (frame % prach_assoc_pattern.nb_of_frame))) { + + uint8_t prach_config_period_nb = ssb_info_p->mapped_ro[n_mapped_ro]->frame / prach_assoc_pattern.prach_conf_period_list[0].nb_of_frame; + uint8_t frame_nb_in_prach_config_period = ssb_info_p->mapped_ro[n_mapped_ro]->frame % prach_assoc_pattern.prach_conf_period_list[0].nb_of_frame; + prach_occasion_slot_p = &prach_assoc_pattern.prach_conf_period_list[prach_config_period_nb].prach_occasion_slot_map[frame_nb_in_prach_config_period][slot]; + } + } + + // If there is a matching RO slot in the SSB_to_RO map + if (NULL != prach_occasion_slot_p) + { + // A random RO mapped to the SSB index should be selected in the slot + + // First count the number of times the SSB index is found in that RO + uint8_t nb_mapped_ssb = 0; + + for (int ro_in_time=0; ro_in_time < prach_occasion_slot_p->nb_of_prach_occasion_in_time; ro_in_time++) { + for (int ro_in_freq=0; ro_in_freq < prach_occasion_slot_p->nb_of_prach_occasion_in_freq; ro_in_freq++) { + prach_occasion_info_t *prach_occasion_info_p = &prach_occasion_slot_p->prach_occasion[ro_in_time][ro_in_freq]; + + for (uint8_t ssb_nb=0; ssb_nbnb_mapped_ssb; ssb_nb++) { + if (prach_occasion_info_p->mapped_ssb_idx[ssb_nb] == ssb_idx) { + nb_mapped_ssb++; + } + } + } + } + + // Choose a random SSB nb + uint8_t random_ssb_nb = 0; + + random_ssb_nb = ((taus()) % nb_mapped_ssb); + + // Select the RO according to the chosen random SSB nb + nb_mapped_ssb=0; + for (int ro_in_time=0; ro_in_time < prach_occasion_slot_p->nb_of_prach_occasion_in_time; ro_in_time++) { + for (int ro_in_freq=0; ro_in_freq < prach_occasion_slot_p->nb_of_prach_occasion_in_freq; ro_in_freq++) { + prach_occasion_info_t *prach_occasion_info_p = &prach_occasion_slot_p->prach_occasion[ro_in_time][ro_in_freq]; + + for (uint8_t ssb_nb=0; ssb_nbnb_mapped_ssb; ssb_nb++) { + if (prach_occasion_info_p->mapped_ssb_idx[ssb_nb] == ssb_idx) { + if (nb_mapped_ssb == random_ssb_nb) { + *prach_occasion_info_pp = prach_occasion_info_p; + return 1; + } + else { + nb_mapped_ssb++; + } + } + } + } + } + } + + return 0; +} + +// Build the SSB to RO mapping upon RRC configuration update +void build_ssb_to_ro_map(NR_ServingCellConfigCommon_t *scc, uint8_t unpaired){ + + // Clear all the lists and maps + memset(&prach_assoc_pattern, 0, sizeof(prach_association_pattern_t)); + memset(&ssb_list, 0, sizeof(ssb_list_info_t)); + + // Build the list of all the valid RACH occasions in the maximum association pattern period according to the PRACH config + LOG_D(MAC,"Build RO list\n"); + build_ro_list(scc, unpaired); + + // Build the list of all the valid/transmitted SSBs according to the config + LOG_D(MAC,"Build SSB list\n"); + build_ssb_list(scc); + + // Map the transmitted SSBs to the ROs and create the association pattern according to the config + LOG_D(MAC,"Map SSB to RO\n"); + map_ssb_to_ro(scc); + LOG_D(MAC,"Map SSB to RO done\n"); +} + +// This function schedules the PRACH according to prach_ConfigurationIndex and TS 38.211, tables 6.3.3.2.x +// PRACH formats 9, 10, 11 are corresponding to dual PRACH format configurations A1/B1, A2/B2, A3/B3. +// - todo: +// - Partial configuration is actually already stored in (fapi_nr_prach_config_t) &mac->phy_config.config_req->prach_config +void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t slotP, int thread_id) { + + uint16_t format, format0, format1, ncs; + int is_nr_prach_slot; + prach_occasion_info_t *prach_occasion_info_p; + + NR_UE_MAC_INST_t *mac = get_mac_inst(module_idP); + RA_config_t *ra = &mac->ra; + + //fapi_nr_ul_config_request_t *ul_config = get_ul_config_request(mac, slotP); + fapi_nr_ul_config_request_t *ul_config = &mac->ul_config_request[0]; + fapi_nr_ul_config_prach_pdu *prach_config_pdu; + fapi_nr_config_request_t *cfg = &mac->phy_config.config_req; + fapi_nr_prach_config_t *prach_config = &cfg->prach_config; + nr_scheduled_response_t scheduled_response; + + NR_ServingCellConfigCommon_t *scc = mac->scc; + NR_RACH_ConfigCommon_t *setup = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup; + NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &setup->rach_ConfigGeneric; + + ra->RA_offset = 2; // to compensate the rx frame offset at the gNB + ra->generate_nr_prach = 0; // Reset flag for PRACH generation + + if (is_nr_UL_slot(scc, slotP)) { + + // WIP Need to get the proper selected ssb_idx + // Initial beam selection functionality is not available yet + uint8_t selected_gnb_ssb_idx = mac->mib_ssb; + + // Get any valid PRACH occasion in the current slot for the selected SSB index + is_nr_prach_slot = get_nr_prach_info_from_ssb_index(selected_gnb_ssb_idx, + (int)frameP, + (int)slotP, + &prach_occasion_info_p); + + if (is_nr_prach_slot && ra->ra_state == RA_UE_IDLE) { + AssertFatal(NULL != prach_occasion_info_p,"PRACH Occasion Info not returned in a valid NR Prach Slot\n"); + + ra->generate_nr_prach = 1; + + format = prach_occasion_info_p->format; + format0 = format & 0xff; // single PRACH format + format1 = (format >> 8) & 0xff; // dual PRACH format + + ul_config->sfn = frameP; + ul_config->slot = slotP; + + ul_config->ul_config_list[ul_config->number_pdus].pdu_type = FAPI_NR_UL_CONFIG_TYPE_PRACH; + prach_config_pdu = &ul_config->ul_config_list[ul_config->number_pdus].prach_config_pdu; + memset(prach_config_pdu, 0, sizeof(fapi_nr_ul_config_prach_pdu)); + ul_config->number_pdus += 1; + LOG_D(PHY, "In %s: (%p) %d UL PDUs:\n", __FUNCTION__, ul_config, ul_config->number_pdus); + + ncs = get_NCS(rach_ConfigGeneric->zeroCorrelationZoneConfig, format0, setup->restrictedSetConfig); + + prach_config_pdu->phys_cell_id = *scc->physCellId; + prach_config_pdu->num_prach_ocas = 1; + prach_config_pdu->prach_slot = prach_occasion_info_p->slot; + prach_config_pdu->prach_start_symbol = prach_occasion_info_p->start_symbol; + prach_config_pdu->num_ra = prach_occasion_info_p->fdm; + + prach_config_pdu->num_cs = ncs; + prach_config_pdu->root_seq_id = prach_config->num_prach_fd_occasions_list[prach_occasion_info_p->fdm].prach_root_sequence_index; + prach_config_pdu->restricted_set = prach_config->restricted_set_config; + prach_config_pdu->freq_msg1 = prach_config->num_prach_fd_occasions_list[prach_occasion_info_p->fdm].k1; + + LOG_D(MAC,"Selected RO Frame %u, Slot %u, Symbol %u, Fdm %u\n", frameP, prach_config_pdu->prach_slot, prach_config_pdu->prach_start_symbol, prach_config_pdu->num_ra); + + // Search which SSB is mapped in the RO (among all the SSBs mapped to this RO) + for (prach_config_pdu->ssb_nb_in_ro=0; prach_config_pdu->ssb_nb_in_ronb_mapped_ssb; prach_config_pdu->ssb_nb_in_ro++) { + if (prach_occasion_info_p->mapped_ssb_idx[prach_config_pdu->ssb_nb_in_ro] == selected_gnb_ssb_idx) + break; + } + AssertFatal(prach_config_pdu->ssb_nb_in_ronb_mapped_ssb, "%u not found in the mapped SSBs to the PRACH occasion", selected_gnb_ssb_idx); + + if (format1 != 0xff) { + switch(format0) { // dual PRACH format + case 0xa1: + prach_config_pdu->prach_format = 11; + break; + case 0xa2: + prach_config_pdu->prach_format = 12; + break; + case 0xa3: + prach_config_pdu->prach_format = 13; + break; + default: + AssertFatal(1 == 0, "Only formats A1/B1 A2/B2 A3/B3 are valid for dual format"); + } + } else { + switch(format0) { // single PRACH format + case 0: + prach_config_pdu->prach_format = 0; + break; + case 1: + prach_config_pdu->prach_format = 1; + break; + case 2: + prach_config_pdu->prach_format = 2; + break; + case 3: + prach_config_pdu->prach_format = 3; + break; + case 0xa1: + prach_config_pdu->prach_format = 4; + break; + case 0xa2: + prach_config_pdu->prach_format = 5; + break; + case 0xa3: + prach_config_pdu->prach_format = 6; + break; + case 0xb1: + prach_config_pdu->prach_format = 7; + break; + case 0xb4: + prach_config_pdu->prach_format = 8; + break; + case 0xc0: + prach_config_pdu->prach_format = 9; + break; + case 0xc2: + prach_config_pdu->prach_format = 10; + break; + default: + AssertFatal(1 == 0, "Invalid PRACH format"); + } + } // if format1 + } // is_nr_prach_slot + + fill_scheduled_response(&scheduled_response, NULL, ul_config, NULL, module_idP, 0 /*TBR fix*/, frameP, slotP, thread_id); + if(mac->if_module != NULL && mac->if_module->scheduled_response != NULL) + mac->if_module->scheduled_response(&scheduled_response); + } // if is_nr_UL_slot +} + +uint8_t +nr_ue_get_sdu(module_id_t module_idP, int CC_id, frame_t frameP, + sub_frame_t subframe, uint8_t eNB_index, + uint8_t *ulsch_buffer, uint16_t buflen, uint8_t *access_mode) { + uint8_t total_rlc_pdu_header_len = 0; + int16_t buflen_remain = 0; + uint8_t lcid = 0; + uint16_t sdu_lengths[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + uint8_t sdu_lcids[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + uint16_t payload_offset = 0, num_sdus = 0; + uint8_t ulsch_sdus[MAX_ULSCH_PAYLOAD_BYTES]; + uint16_t sdu_length_total = 0; + //unsigned short post_padding = 0; + NR_UE_MAC_INST_t *mac = get_mac_inst(module_idP); + + rlc_buffer_occupancy_t lcid_buffer_occupancy_old = + 0, lcid_buffer_occupancy_new = 0; + LOG_D(MAC, + "[UE %d] MAC PROCESS UL TRANSPORT BLOCK at frame%d subframe %d TBS=%d\n", + module_idP, frameP, subframe, buflen); + AssertFatal(CC_id == 0, + "Transmission on secondary CCs is not supported yet\n"); + + // Check for DCCH first + // TO DO: Multiplex in the order defined by the logical channel prioritization + for (lcid = UL_SCH_LCID_SRB1; + lcid < NR_MAX_NUM_LCID; lcid++) { + + lcid_buffer_occupancy_old = mac_rlc_get_buffer_occupancy_ind(module_idP, mac->crnti, eNB_index, frameP, subframe, ENB_FLAG_NO, lcid); + lcid_buffer_occupancy_new = lcid_buffer_occupancy_old; + + if(lcid_buffer_occupancy_new){ + + buflen_remain = + buflen - (total_rlc_pdu_header_len + sdu_length_total + MAX_RLC_SDU_SUBHEADER_SIZE); + LOG_D(MAC, + "[UE %d] Frame %d : UL-DXCH -> ULSCH, RLC %d has %d bytes to " + "send (Transport Block size %d SDU Length Total %d , mac header len %d, buflen_remain %d )\n", //BSR byte before Tx=%d + module_idP, frameP, lcid, lcid_buffer_occupancy_new, + buflen, sdu_length_total, + total_rlc_pdu_header_len, buflen_remain); // ,nr_ue_mac_inst->scheduling_info.BSR_bytes[nr_ue_mac_inst->scheduling_info.LCGID[lcid]] + + while(buflen_remain > 0 && lcid_buffer_occupancy_new){ + + sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP, + mac->crnti, + eNB_index, + frameP, + ENB_FLAG_NO, + MBMS_FLAG_NO, + lcid, + buflen_remain, + (char *)&ulsch_sdus[sdu_length_total],0, + 0); + + AssertFatal(buflen_remain >= sdu_lengths[num_sdus], + "LCID=%d RLC has segmented %d bytes but MAC has max=%d\n", + lcid, sdu_lengths[num_sdus], buflen_remain); + + if (sdu_lengths[num_sdus]) { + sdu_length_total += sdu_lengths[num_sdus]; + sdu_lcids[num_sdus] = lcid; + + total_rlc_pdu_header_len += MAX_RLC_SDU_SUBHEADER_SIZE; //rlc_pdu_header_len_last; + + //Update number of SDU + num_sdus++; + } + + /* Get updated BO after multiplexing this PDU */ + lcid_buffer_occupancy_new = mac_rlc_get_buffer_occupancy_ind(module_idP, + mac->crnti, + eNB_index, + frameP, + subframe, + ENB_FLAG_NO, + lcid); + buflen_remain = + buflen - (total_rlc_pdu_header_len + sdu_length_total + MAX_RLC_SDU_SUBHEADER_SIZE); + } + } + +} + + // Generate ULSCH PDU + if (num_sdus>0) { + payload_offset = nr_generate_ulsch_pdu(ulsch_sdus, + ulsch_buffer, // mac header + num_sdus, // num sdus + sdu_lengths, // sdu length + sdu_lcids, // sdu lcid + 0, // power_headroom + mac->crnti, // crnti + 0, // truncated_bsr + 0, // short_bsr + 0, // long_bsr + 0, // post_padding + buflen); // TBS in bytes + } + else + return 0; + + // Padding: fill remainder of ULSCH with 0 + if (buflen - payload_offset > 0){ + for (int j = payload_offset; j < buflen; j++) + ulsch_buffer[j] = 0; + } + +#if defined(ENABLE_MAC_PAYLOAD_DEBUG) + LOG_I(MAC, "Printing UL MAC payload UE side, payload_offset: %d \n", payload_offset); + for (int i = 0; i < buflen ; i++) { + //harq_process_ul_ue->a[i] = (unsigned char) rand(); + //printf("a[%d]=0x%02x\n",i,harq_process_ul_ue->a[i]); + printf("%02x ",(unsigned char)ulsch_buffer[i]); + } + printf("\n"); +#endif + + return 1; +} diff --git a/openair2/LAYER2/NR_MAC_UE/rar_tools_nrUE.c b/openair2/LAYER2/NR_MAC_UE/rar_tools_nrUE.c deleted file mode 100644 index 8273c9caff..0000000000 --- a/openair2/LAYER2/NR_MAC_UE/rar_tools_nrUE.c +++ /dev/null @@ -1,359 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.openairinterface.org/?page_id=698 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -/*! \file rar_tools_nrUE.c - * \brief RA tools for NR UE - * \author Guido Casati - * \date 2019 - * \version 1.0 - * @ingroup _mac - - */ - -/* Sim */ -#include "SIMULATION/TOOLS/sim.h" - -/* Utils */ -#include "common/utils/LOG/log.h" -#include "OCG.h" -#include "OCG_extern.h" -#include "UTIL/OPT/opt.h" - -/* Common */ -#include "common/ran_context.h" - -/* MAC */ -#include "NR_MAC_UE/mac.h" -#include "NR_MAC_UE/mac_proto.h" -#include "NR_MAC_COMMON/nr_mac_extern.h" -#include - -// #define DEBUG_RAR -// #define DEBUG_MSG3 - -// table 7.2-1 TS 38.321 -uint16_t table_7_2_1[16] = { - 5, // row index 0 - 10, // row index 1 - 20, // row index 2 - 30, // row index 3 - 40, // row index 4 - 60, // row index 5 - 80, // row index 6 - 120, // row index 7 - 160, // row index 8 - 240, // row index 9 - 320, // row index 10 - 480, // row index 11 - 960, // row index 12 - 1920, // row index 13 -}; - -void nr_config_Msg3_pdu(NR_UE_MAC_INST_t *mac, - int Msg3_f_alloc, - uint8_t Msg3_t_alloc, - uint8_t mcs, - uint8_t freq_hopping){ - - int f_alloc, mask, StartSymbolIndex, NrOfSymbols; - uint8_t nb_dmrs_re_per_rb; - uint16_t number_dmrs_symbols = 0; - int N_PRB_oh; - fapi_nr_ul_config_request_t *ul_config = &mac->ul_config_request[0]; - nfapi_nr_ue_pusch_pdu_t *pusch_config_pdu = &ul_config->ul_config_list[ul_config->number_pdus].pusch_config_pdu; - NR_ServingCellConfigCommon_t *scc = mac->scc; - NR_BWP_Uplink_t *ubwp = mac->ULbwp[0]; - NR_BWP_UplinkDedicated_t *ibwp = mac->scg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP; - NR_PUSCH_Config_t *pusch_Config = ibwp->pusch_Config->choice.setup; - int startSymbolAndLength = ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[Msg3_t_alloc]->startSymbolAndLength; - - #ifdef DEBUG_MSG3 - printf("[DEBUG_MSG3] Configuring 1 Msg3 PDU of %d UL pdus \n", ul_config->number_pdus); - #endif - - // Num PRB Overhead from PUSCH-ServingCellConfig - if (mac->scg->spCellConfig->spCellConfigDedicated->uplinkConfig->pusch_ServingCellConfig->choice.setup->xOverhead == NULL) - N_PRB_oh = 0; - else - N_PRB_oh = *mac->scg->spCellConfig->spCellConfigDedicated->uplinkConfig->pusch_ServingCellConfig->choice.setup->xOverhead; - - // active BWP start - int abwp_start = NRRIV2PRBOFFSET(ubwp->bwp_Common->genericParameters.locationAndBandwidth, 275); - int abwp_size = NRRIV2BW(ubwp->bwp_Common->genericParameters.locationAndBandwidth, 275); - - // initial BWP start - int ibwp_start = NRRIV2PRBOFFSET(scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth, 275); - int ibwp_size = NRRIV2BW(scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth, 275); - - // BWP start selection according to 8.3 of TS 38.213 - pusch_config_pdu->bwp_size = ibwp_size; - if ((ibwp_start < abwp_start) || (ibwp_size > abwp_size)) - pusch_config_pdu->bwp_start = abwp_start; - else - pusch_config_pdu->bwp_start = ibwp_start; - - //// Resource assignment from RAR - // Frequency domain allocation according to 8.3 of TS 38.213 - if (ibwp_size < 180) - mask = (1 << ((int) ceil(log2((ibwp_size*(ibwp_size+1))>>1)))) - 1; - else - mask = (1 << (28 - (int)(ceil(log2((ibwp_size*(ibwp_size+1))>>1))))) - 1; - - f_alloc = Msg3_f_alloc & mask; - nr_ue_process_dci_freq_dom_resource_assignment(pusch_config_pdu, NULL, ibwp_size, 0, f_alloc); - - // virtual resource block to physical resource mapping for Msg3 PUSCH (6.3.1.7 in 38.211) - pusch_config_pdu->rb_start += ibwp_start - abwp_start; - - // Time domain allocation - SLIV2SL(startSymbolAndLength, &StartSymbolIndex, &NrOfSymbols); - pusch_config_pdu->ul_dmrs_symb_pos = 1<start_symbol_index = StartSymbolIndex; - pusch_config_pdu->nr_of_symbols = NrOfSymbols; - - #ifdef DEBUG_MSG3 - printf("[DEBUG_MSG3] Freq assignment (RB start %d size %d) BWP (start %d, size %d), Time assignment (sliv_S %d sliv_L %d) \n", - pusch_config_pdu->rb_start, - pusch_config_pdu->rb_size, - pusch_config_pdu->bwp_start, - pusch_config_pdu->bwp_size, - StartSymbolIndex, - NrOfSymbols); - #endif - - // MCS - pusch_config_pdu->mcs_index = mcs; - // Frequency hopping - pusch_config_pdu->frequency_hopping = freq_hopping; - // TC-RNTI - pusch_config_pdu->rnti = mac->t_crnti; - - // DM-RS configuration according to 6.2.2 UE DM-RS transmission procedure in 38.214 - pusch_config_pdu->dmrs_config_type = pusch_dmrs_type1; - pusch_config_pdu->num_dmrs_cdm_grps_no_data = 2; - pusch_config_pdu->dmrs_ports = 1; - get_num_re_dmrs(pusch_config_pdu, - &nb_dmrs_re_per_rb, - &number_dmrs_symbols); - - // DMRS sequence initialization [TS 38.211, sec 6.4.1.1.1]. - // Should match what is sent in DCI 0_1, otherwise set to 0. - pusch_config_pdu->scid = 0; - - // Transform precoding according to 6.1.3 UE procedure for applying transform precoding on PUSCH in 38.214 - if (scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg3_transformPrecoder == NULL) - pusch_config_pdu->transform_precoding = 1; - else - pusch_config_pdu->transform_precoding = 0; - - // Resource allocation in frequency domain according to 6.1.2.2 in TS 38.214 - pusch_config_pdu->resource_alloc = pusch_Config->resourceAllocation; - - //// Completing PUSCH PDU - pusch_config_pdu->pdu_bit_map = PUSCH_PDU_BITMAP_PUSCH_DATA; - pusch_config_pdu->mcs_table = 0; - pusch_config_pdu->nrOfLayers = 1; - pusch_config_pdu->cyclic_prefix = 0; - pusch_config_pdu->target_code_rate = nr_get_code_rate_ul(pusch_config_pdu->mcs_index, pusch_config_pdu->mcs_table); - pusch_config_pdu->qam_mod_order = nr_get_Qm_ul(pusch_config_pdu->mcs_index, pusch_config_pdu->mcs_table); - pusch_config_pdu->data_scrambling_id = *scc->physCellId; - pusch_config_pdu->ul_dmrs_scrambling_id = *scc->physCellId; - pusch_config_pdu->subcarrier_spacing = ubwp->bwp_Common->genericParameters.subcarrierSpacing; - pusch_config_pdu->vrb_to_prb_mapping = 0; - pusch_config_pdu->uplink_frequency_shift_7p5khz = 0; - //Optional Data only included if indicated in pduBitmap - pusch_config_pdu->pusch_data.rv_index = 0; // 8.3 in 38.213 - pusch_config_pdu->pusch_data.harq_process_id = 0; - pusch_config_pdu->pusch_data.new_data_indicator = 1; // new data - pusch_config_pdu->pusch_data.num_cb = 0; - - // Compute TBS - pusch_config_pdu->pusch_data.tb_size = nr_compute_tbs(pusch_config_pdu->qam_mod_order, - pusch_config_pdu->target_code_rate, - pusch_config_pdu->rb_size, - pusch_config_pdu->nr_of_symbols, - nb_dmrs_re_per_rb*number_dmrs_symbols, - N_PRB_oh, - 0, // TBR to verify tb scaling - pusch_config_pdu->nrOfLayers)/8; - -} - -///////////////////////////////////// -// 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|// -///////////////////////////////////// -// TbD WIP Msg3 development ongoing -// - apply UL grant freq alloc & time alloc as per 8.2 TS 38.213 -// - apply tpc command -uint16_t nr_ue_process_rar(module_id_t mod_id, - int CC_id, - frame_t frame, - sub_frame_t slot, - uint8_t * dlsch_buffer, - rnti_t * t_crnti, - uint8_t preamble_index, - uint8_t * selected_rar_buffer){ - - NR_UE_MAC_INST_t *ue_mac = get_mac_inst(mod_id); - NR_RA_HEADER_RAPID *rarh = (NR_RA_HEADER_RAPID *) dlsch_buffer; // RAR subheader pointer - NR_MAC_RAR *rar = (NR_MAC_RAR *) (dlsch_buffer + 1); // RAR subPDU pointer - uint8_t n_subPDUs = 0; // number of RAR payloads - uint8_t n_subheaders = 0; // number of MAC RAR subheaders - uint16_t ta_command = 0; - - AssertFatal(CC_id == 0, "RAR reception on secondary CCs is not supported yet\n"); - - while (1) { - n_subheaders++; - if (rarh->T == 1) { - n_subPDUs++; - LOG_D(MAC, "[UE %d][RAPROC] Got RAPID RAR subPDU\n", mod_id); - } else { - n_subPDUs++; - ue_mac->RA_backoff_indicator = table_7_2_1[((NR_RA_HEADER_BI *)rarh)->BI]; - ue_mac->RA_BI_found = 1; - LOG_D(MAC, "[UE %d][RAPROC] Got BI RAR subPDU %d\n", mod_id, ue_mac->RA_backoff_indicator); - } - if (rarh->RAPID == preamble_index) { - LOG_I(PHY, "[UE %d][RAPROC][%d.%d] Found RAR with the intended RAPID %d\n", mod_id, frame, slot, rarh->RAPID); - rar = (NR_MAC_RAR *) (dlsch_buffer + n_subheaders + (n_subPDUs - 1) * sizeof(NR_MAC_RAR)); - ue_mac->RA_RAPID_found = 1; - break; - } - if (rarh->E == 0) { - LOG_I(PHY, "No RAR found with the intended RAPID. \n"); - break; - } else { - rarh += sizeof(NR_MAC_RAR) + 1; - } - }; - - #ifdef DEBUG_RAR - LOG_D(MAC, "[DEBUG_RAR] (%d,%d) number of RAR subheader %d; number of RAR pyloads %d\n", frame, slot, n_subheaders, n_subPDUs); - LOG_D(MAC, "[DEBUG_RAR] Received RAR (%02x|%02x.%02x.%02x.%02x.%02x.%02x) for preamble %d/%d\n", *(uint8_t *) rarh, rar[0], rar[1], rar[2], rar[3], rar[4], rar[5], rarh->RAPID, preamble_index); - #endif - - if (ue_mac->RA_RAPID_found) { - - uint8_t freq_hopping, mcs, Msg3_t_alloc; - uint16_t Msg3_f_alloc; - unsigned char tpc_command; -#ifdef DEBUG_RAR - unsigned char csi_req; -#endif - - // TC-RNTI - *t_crnti = rar->TCRNTI_2 + (rar->TCRNTI_1 << 8); - ue_mac->t_crnti = *t_crnti; - // TA command - ta_command = rar->TA2 + (rar->TA1 << 5); - -#ifdef DEBUG_RAR - // CSI - csi_req = (unsigned char) (rar->UL_GRANT_4 & 0x01); -#endif - - // TPC - tpc_command = (unsigned char) ((rar->UL_GRANT_4 >> 1) & 0x07); - switch (tpc_command){ - case 0: - ue_mac->Msg3_TPC = -6; - break; - case 1: - ue_mac->Msg3_TPC = -4; - break; - case 2: - ue_mac->Msg3_TPC = -2; - break; - case 3: - ue_mac->Msg3_TPC = 0; - break; - case 4: - ue_mac->Msg3_TPC = 2; - break; - case 5: - ue_mac->Msg3_TPC = 4; - break; - case 6: - ue_mac->Msg3_TPC = 6; - break; - case 7: - ue_mac->Msg3_TPC = 8; - break; - } - // MCS - mcs = (unsigned char) (rar->UL_GRANT_4 >> 4); - // time alloc - Msg3_t_alloc = (unsigned char) (rar->UL_GRANT_3 & 0x07); - // frequency alloc - Msg3_f_alloc = (uint16_t) ((rar->UL_GRANT_3 >> 4) | (rar->UL_GRANT_2 << 4) | ((rar->UL_GRANT_1 & 0x03) << 12)); - // frequency hopping - freq_hopping = (unsigned char) (rar->UL_GRANT_1 >> 2); - - #ifdef DEBUG_RAR - LOG_D(MAC, "[DEBUG_RAR] Received 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", - Msg3_t_alloc, - Msg3_f_alloc, - ta_command, - mcs, - freq_hopping, - tpc_command, - csi_req, - ue_mac->t_crnti); - #endif - - // Config Msg3 PDU - nr_config_Msg3_pdu(ue_mac, Msg3_f_alloc, Msg3_t_alloc, mcs, freq_hopping); - // Schedule Msg3 - nr_ue_msg3_scheduler(ue_mac, frame, slot, Msg3_t_alloc); - - } else { - ue_mac->t_crnti = 0; - ta_command = (0xffff); - } - - // move the selected RAR to the front of the RA_PDSCH buffer - memcpy((void *) (selected_rar_buffer + 0), (void *) rarh, 1); - memcpy((void *) (selected_rar_buffer + 1), (void *) rar, sizeof(NR_MAC_RAR)); - - return ta_command; -} diff --git a/openair2/LAYER2/NR_MAC_gNB/config.c b/openair2/LAYER2/NR_MAC_gNB/config.c index bd6a8f3384..bce0719556 100644 --- a/openair2/LAYER2/NR_MAC_gNB/config.c +++ b/openair2/LAYER2/NR_MAC_gNB/config.c @@ -45,7 +45,7 @@ #include "NR_MIB.h" #include "LAYER2/NR_MAC_COMMON/nr_mac_common.h" - +#include "../../../../nfapi/oai_integration/vendor_ext.h" /* Softmodem params */ #include "executables/softmodem-common.h" @@ -264,6 +264,7 @@ void config_common(int Mod_idP, int pdsch_AntennaPorts, NR_ServingCellConfigComm } cfg->ssb_table.ssb_mask_list[0].ssb_mask.tl.tag = NFAPI_NR_CONFIG_SSB_MASK_TAG; + cfg->ssb_table.ssb_mask_list[1].ssb_mask.tl.tag = NFAPI_NR_CONFIG_SSB_MASK_TAG; cfg->num_tlv++; cfg->carrier_config.num_tx_ant.value = pdsch_AntennaPorts; @@ -305,7 +306,7 @@ void config_common(int Mod_idP, int pdsch_AntennaPorts, NR_ServingCellConfigComm if (return_tdd != 0) LOG_E(MAC,"TDD configuration can not be done\n"); else - LOG_I(MAC,"TDD has been properly configurated\n"); + LOG_I(MAC,"TDD has been properly configurated\n"); } } @@ -346,10 +347,18 @@ int rrc_mac_config_req_gNB(module_id_t Mod_idP, } RC.nrmac[Mod_idP]->common_channels[0].vrb_map_UL = - calloc(n * 275, sizeof(uint16_t)); + calloc(n * MAX_BWP_SIZE, sizeof(uint16_t)); AssertFatal(RC.nrmac[Mod_idP]->common_channels[0].vrb_map_UL, "could not allocate memory for RC.nrmac[]->common_channels[0].vrb_map_UL\n"); + for (int i = 0; i < MAX_NUM_BWP; ++i) { + RC.nrmac[Mod_idP]->pucch_index_used[i] = + calloc(n, sizeof(*RC.nrmac[Mod_idP]->pucch_index_used)); + AssertFatal(RC.nrmac[Mod_idP]->pucch_index_used[i], + "could not allocate memory for RC.nrmac[]->pucch_index_used[%d]\n", + i); + } + LOG_I(MAC,"Configuring common parameters from NR ServingCellConfig\n"); config_common(Mod_idP, @@ -358,11 +367,11 @@ int rrc_mac_config_req_gNB(module_id_t Mod_idP, LOG_E(MAC, "%s() %s:%d RC.nrmac[Mod_idP]->if_inst->NR_PHY_config_req:%p\n", __FUNCTION__, __FILE__, __LINE__, RC.nrmac[Mod_idP]->if_inst->NR_PHY_config_req); // if in nFAPI mode - if ( (nfapi_mode == 1 || nfapi_mode == 2) && (RC.nrmac[Mod_idP]->if_inst->NR_PHY_config_req == NULL) ){ + if ( (NFAPI_MODE == NFAPI_MODE_PNF || NFAPI_MODE == NFAPI_MODE_VNF) && (RC.nrmac[Mod_idP]->if_inst->NR_PHY_config_req == NULL) ){ while(RC.nrmac[Mod_idP]->if_inst->NR_PHY_config_req == NULL) { - // DJP AssertFatal(RC.nrmac[Mod_idP]->if_inst->PHY_config_req != NULL,"if_inst->phy_config_request is null\n"); - usleep(100 * 1000); - printf("Waiting for PHY_config_req\n"); + // DJP AssertFatal(RC.nrmac[Mod_idP]->if_inst->PHY_config_req != NULL,"if_inst->phy_config_request is null\n"); + usleep(100 * 1000); + printf("Waiting for PHY_config_req\n"); } } @@ -389,39 +398,40 @@ int rrc_mac_config_req_gNB(module_id_t Mod_idP, NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info; if (add_ue == 1 && get_softmodem_params()->phy_test) { - const int UE_id = add_new_nr_ue(Mod_idP,rnti); - UE_info->secondaryCellGroup[UE_id] = secondaryCellGroup; - compute_csi_bitlen (secondaryCellGroup, UE_info, UE_id); - struct NR_ServingCellConfig__downlinkBWP_ToAddModList *bwpList = - secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList; - AssertFatal(bwpList->list.count == 1, - "downlinkBWP_ToAddModList has %d BWP!\n", - bwpList->list.count); - const int bwp_id = 1; - UE_info->UE_sched_ctrl[UE_id].active_bwp = bwpList->list.array[bwp_id - 1]; - struct NR_UplinkConfig__uplinkBWP_ToAddModList *ubwpList = - secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList; - AssertFatal(ubwpList->list.count == 1, - "uplinkBWP_ToAddModList has %d BWP!\n", - ubwpList->list.count); - UE_info->UE_sched_ctrl[UE_id].active_ubwp = ubwpList->list.array[bwp_id - 1]; + const int UE_id = add_new_nr_ue(Mod_idP, rnti, secondaryCellGroup); LOG_I(PHY,"Added new UE_id %d/%x with initial secondaryCellGroup\n",UE_id,rnti); } else if (add_ue == 1 && !get_softmodem_params()->phy_test) { - /* TODO: should check for free RA process */ const int CC_id = 0; - NR_RA_t *ra = &RC.nrmac[Mod_idP]->common_channels[CC_id].ra[0]; - ra->state = RA_IDLE; + NR_COMMON_channels_t *cc = &RC.nrmac[Mod_idP]->common_channels[CC_id]; + uint8_t ra_index = 0; + /* checking for free RA process */ + for(; ra_index < NR_NB_RA_PROC_MAX; ra_index++) { + if((cc->ra[ra_index].state == RA_IDLE) && (!cc->ra[ra_index].cfra)) break; + } + if (ra_index == NR_NB_RA_PROC_MAX) { + LOG_E(MAC, "%s() %s:%d RA processes are not available for CFRA RNTI :%x\n", __FUNCTION__, __FILE__, __LINE__, rnti); + return -1; + } + NR_RA_t *ra = &cc->ra[ra_index]; ra->secondaryCellGroup = secondaryCellGroup; if (secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated!=NULL) { if (secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra != NULL) { ra->cfra = true; ra->rnti = rnti; - struct NR_CFRA cfra = *secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra; - uint8_t num_preamble = cfra.resources.choice.ssb->ssb_ResourceList.list.count; + struct NR_CFRA *cfra = secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra; + uint8_t num_preamble = cfra->resources.choice.ssb->ssb_ResourceList.list.count; ra->preambles.num_preambles = num_preamble; ra->preambles.preamble_list = (uint8_t *) malloc(num_preamble*sizeof(uint8_t)); - for (int i = 0; i < num_preamble; i++) - ra->preambles.preamble_list[i] = cfra.resources.choice.ssb->ssb_ResourceList.list.array[i]->ra_PreambleIndex; + for(int i=0; inum_active_ssb; i++) { + for(int j=0; jssb_index[i] == cfra->resources.choice.ssb->ssb_ResourceList.list.array[j]->ssb) { + // one dedicated preamble for each beam + ra->preambles.preamble_list[i] = + cfra->resources.choice.ssb->ssb_ResourceList.list.array[j]->ra_PreambleIndex; + break; + } + } + } } } LOG_I(PHY,"Added new RA process for UE RNTI %04x with initial secondaryCellGroup\n", rnti); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c index dfb7ce0466..589a2ee7fd 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c @@ -52,6 +52,7 @@ #include "intertask_interface.h" #include "executables/softmodem-common.h" +#include "nfapi/oai_integration/vendor_ext.h" uint16_t nr_pdcch_order_table[6] = { 31, 31, 511, 2047, 2047, 8191 }; @@ -59,24 +60,31 @@ void clear_mac_stats(gNB_MAC_INST *gNB) { memset((void*)gNB->UE_info.mac_stats,0,MAX_MOBILES_PER_GNB*sizeof(NR_mac_stats_t)); } -void dump_mac_stats(gNB_MAC_INST *gNB) { - +void dump_mac_stats(gNB_MAC_INST *gNB) +{ NR_UE_info_t *UE_info = &gNB->UE_info; - NR_mac_stats_t *stats; - int lc_id; - - for (int UE_id=0;UE_idactive[UE_id]) { - LOG_I(MAC, "UE %x\n", UE_info->rnti[UE_id]); - stats = &UE_info->mac_stats[UE_id]; - LOG_I(MAC,"dlsch_rounds %d/%d/%d/%d, dlsch_errors %d\n",stats->dlsch_rounds[0],stats->dlsch_rounds[1],stats->dlsch_rounds[2],stats->dlsch_rounds[3],stats->dlsch_errors); - LOG_I(MAC,"dlsch_total_bytes %d\n",stats->dlsch_total_bytes); - LOG_I(MAC,"ulsch_rounds %d/%d/%d/%d, ulsch_errors %d\n",stats->ulsch_rounds[0],stats->ulsch_rounds[1],stats->ulsch_rounds[2],stats->ulsch_rounds[3],stats->ulsch_errors); - LOG_I(MAC,"ulsch_total_bytes_scheduled %d, ulsch_total_bytes_received %d\n",stats->ulsch_total_bytes_scheduled,stats->ulsch_total_bytes_rx); - for (lc_id=0;lc_id<63;lc_id++) { - if (stats->lc_bytes_tx[lc_id]>0) LOG_I(MAC,"LCID %d : %d bytes TX\n",lc_id,stats->lc_bytes_tx[lc_id]); - if (stats->lc_bytes_rx[lc_id]>0) LOG_I(MAC,"LCID %d : %d bytes RX\n",lc_id,stats->lc_bytes_rx[lc_id]); - } + int num = 1; + for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { + LOG_I(MAC, "UE ID %d RNTI %04x (%d/%d)\n", UE_id, UE_info->rnti[UE_id], num++, UE_info->num_UEs); + const NR_mac_stats_t *stats = &UE_info->mac_stats[UE_id]; + LOG_I(MAC, "UE %d: dlsch_rounds %d/%d/%d/%d, dlsch_errors %d\n", + UE_id, + stats->dlsch_rounds[0], stats->dlsch_rounds[1], + stats->dlsch_rounds[2], stats->dlsch_rounds[3], stats->dlsch_errors); + LOG_I(MAC, "UE %d: dlsch_total_bytes %d\n", UE_id, stats->dlsch_total_bytes); + LOG_I(MAC, "UE %d: ulsch_rounds %d/%d/%d/%d, ulsch_errors %d\n", + UE_id, + stats->ulsch_rounds[0], stats->ulsch_rounds[1], + stats->ulsch_rounds[2], stats->ulsch_rounds[3], stats->ulsch_errors); + LOG_I(MAC, + "UE %d: ulsch_total_bytes_scheduled %d, ulsch_total_bytes_received %d\n", + UE_id, + stats->ulsch_total_bytes_scheduled, stats->ulsch_total_bytes_rx); + for (int lc_id = 0; lc_id < 63; lc_id++) { + if (stats->lc_bytes_tx[lc_id] > 0) + LOG_I(MAC, "UE %d: LCID %d: %d bytes TX\n", UE_id, lc_id, stats->lc_bytes_tx[lc_id]); + if (stats->lc_bytes_rx[lc_id] > 0) + LOG_I(MAC, "UE %d: LCID %d: %d bytes RX\n", UE_id, lc_id, stats->lc_bytes_rx[lc_id]); } } } @@ -89,6 +97,7 @@ void clear_nr_nfapi_information(gNB_MAC_INST * gNB, const int num_slots = nr_slots_per_frame[*scc->ssbSubcarrierSpacing]; nfapi_nr_dl_tti_request_t *DL_req = &gNB->DL_req[0]; + nfapi_nr_dl_tti_pdcch_pdu_rel15_t ***pdcch = (nfapi_nr_dl_tti_pdcch_pdu_rel15_t ***)gNB->pdcch_pdu_idx[CC_idP]; nfapi_nr_ul_tti_request_t *future_ul_tti_req = &gNB->UL_tti_req_ahead[CC_idP][(slotP + num_slots - 1) % num_slots]; nfapi_nr_ul_dci_request_t *UL_dci_req = &gNB->UL_dci_req[0]; @@ -96,13 +105,14 @@ void clear_nr_nfapi_information(gNB_MAC_INST * gNB, gNB->pdu_index[CC_idP] = 0; - if (nfapi_mode==0 || nfapi_mode == 1) { // monolithic or PNF + if (NFAPI_MODE == NFAPI_MONOLITHIC || NFAPI_MODE == NFAPI_MODE_PNF) { // monolithic or PNF DL_req[CC_idP].SFN = frameP; DL_req[CC_idP].Slot = slotP; DL_req[CC_idP].dl_tti_request_body.nPDUs = 0; DL_req[CC_idP].dl_tti_request_body.nGroup = 0; //DL_req[CC_idP].dl_tti_request_body.transmission_power_pcfich = 6000; + memset(pdcch, 0, sizeof(**pdcch) * MAX_NUM_BWP * MAX_NUM_CORESET); UL_dci_req[CC_idP].SFN = frameP; UL_dci_req[CC_idP].Slot = slotP; @@ -299,11 +309,9 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, int nb_periods_per_frame; - const int UE_id = 0; const int bwp_id = 1; gNB_MAC_INST *gNB = RC.nrmac[module_idP]; - NR_UE_info_t *UE_info = &gNB->UE_info; NR_COMMON_channels_t *cc = gNB->common_channels; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; NR_TDD_UL_DL_Pattern_t *tdd_pattern = &scc->tdd_UL_DL_ConfigurationCommon->pattern1; @@ -360,23 +368,27 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, // nr_rrc_trigger(&ctxt, 0 /*CC_id*/, frame, slot >> *scc->ssbSubcarrierSpacing); } - const uint64_t dlsch_in_slot_bitmap = (1 << 1) | (1 << 3); - const uint64_t ulsch_in_slot_bitmap = (1 << 8); +#define BIT(x) (1 << (x)) + const uint64_t dlsch_in_slot_bitmap = BIT( 1) | BIT( 2) | BIT( 3) | BIT( 4) | BIT( 5) | BIT( 6) + | BIT(11) | BIT(12) | BIT(13) | BIT(14) | BIT(15) | BIT(16); + const uint64_t ulsch_in_slot_bitmap = BIT( 8) | BIT(18); memset(RC.nrmac[module_idP]->cce_list[bwp_id][0],0,MAX_NUM_CCE*sizeof(int)); // coreset0 memset(RC.nrmac[module_idP]->cce_list[bwp_id][1],0,MAX_NUM_CCE*sizeof(int)); // coresetid 1 - for (int i=0; iUE_info.num_pdcch_cand[UE_id][i] = 0; + NR_UE_info_t *UE_info = &RC.nrmac[module_idP]->UE_info; + for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) + for (int i=0; inum_pdcch_cand[UE_id][i] = 0; for (int CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { //mbsfn_status[CC_id] = 0; // clear vrb_maps - memset(cc[CC_id].vrb_map, 0, sizeof(uint16_t) * 275); + memset(cc[CC_id].vrb_map, 0, sizeof(uint16_t) * MAX_BWP_SIZE); // clear last scheduled slot's content (only)! const int num_slots = nr_slots_per_frame[*scc->ssbSubcarrierSpacing]; const int last_slot = (slot + num_slots - 1) % num_slots; uint16_t *vrb_map_UL = cc[CC_id].vrb_map_UL; - memset(&vrb_map_UL[last_slot * 275], 0, sizeof(uint16_t) * 275); + memset(&vrb_map_UL[last_slot * MAX_BWP_SIZE], 0, sizeof(uint16_t) * MAX_BWP_SIZE); clear_nr_nfapi_information(RC.nrmac[module_idP], CC_id, frame, slot); } @@ -410,9 +422,9 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, // This schedule SR // TODO - // This schedule CSI measurement reporting - if (UE_info->active[UE_id]) - nr_csi_meas_reporting(module_idP, UE_id, frame, slot, num_slots_per_tdd, nr_ulmix_slots, nr_slots_per_frame[*scc->ssbSubcarrierSpacing]); + // Schedule CSI measurement reporting: check in slot 0 for the whole frame + if (slot == 0) + nr_csi_meas_reporting(module_idP, frame, slot); // This schedule RA procedure if not in phy_test mode // Otherwise already consider 5G already connected @@ -421,19 +433,16 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, } // This schedules the DCI for Uplink and subsequently PUSCH - if (slot < 10) { + { nr_schedule_ulsch(module_idP, frame, slot, num_slots_per_tdd, nr_ulmix_slots, ulsch_in_slot_bitmap); } // This schedules the DCI for Downlink and PDSCH - if (is_xlsch_in_slot(dlsch_in_slot_bitmap, slot % num_slots_per_tdd) - && slot < 10) { - nr_schedule_ue_spec(module_idP, frame, slot, num_slots_per_tdd); - } + if (is_xlsch_in_slot(dlsch_in_slot_bitmap, slot)) + nr_schedule_ue_spec(module_idP, frame, slot); - if (UE_info->active[UE_id]) - nr_schedule_pucch(module_idP, UE_id, nr_ulmix_slots, frame, slot); + nr_schedule_pucch(module_idP, frame, slot); stop_meas(&RC.nrmac[module_idP]->eNB_scheduler); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index e15963f355..ac3a4e77d2 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -151,6 +151,38 @@ void find_SSB_and_RO_available(module_id_t module_idP) { uint8_t num_active_ssb = 0; uint8_t max_association_period = 1; + struct NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB *ssb_perRACH_OccasionAndCB_PreamblesPerSSB = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->ssb_perRACH_OccasionAndCB_PreamblesPerSSB; + + switch (ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present){ + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneEighth: + cc->cb_preambles_per_ssb = 4 * (ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.oneEighth + 1); + break; + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneFourth: + cc->cb_preambles_per_ssb = 4 * (ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.oneFourth + 1); + break; + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneHalf: + cc->cb_preambles_per_ssb = 4 * (ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.oneHalf + 1); + break; + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_one: + cc->cb_preambles_per_ssb = 4 * (ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.one + 1); + break; + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_two: + cc->cb_preambles_per_ssb = 4 * (ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.two + 1); + break; + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_four: + cc->cb_preambles_per_ssb = ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.four; + break; + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_eight: + cc->cb_preambles_per_ssb = ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.eight; + break; + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_sixteen: + cc->cb_preambles_per_ssb = ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.sixteen; + break; + default: + AssertFatal(1 == 0, "Unsupported ssb_perRACH_config %d\n", ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present); + break; + } + if (scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing) mu = *scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing; else @@ -181,25 +213,28 @@ void find_SSB_and_RO_available(module_id_t module_idP) { } } - for(int i = 1; (1 << (i-1)) <= max_association_period;i++) { + cc->total_prach_occasions_per_config_period = total_RA_occasions; + for(int i=1; (1 << (i-1)) < max_association_period; i++) { + cc->max_association_period = (1 <<(i-1)); + total_RA_occasions = total_RA_occasions * cc->max_association_period; if(total_RA_occasions >= (int) (num_active_ssb/num_ssb_per_RO)) { repetition = (uint16_t)((total_RA_occasions * num_ssb_per_RO )/num_active_ssb); break; } - else { - total_RA_occasions = total_RA_occasions * i; - cc->max_association_period = i; - } } - if(cc->max_association_period == 0) - cc->max_association_period = 1; unused_RA_occasion = total_RA_occasions - (int)((num_active_ssb * repetition)/num_ssb_per_RO); cc->total_prach_occasions = total_RA_occasions - unused_RA_occasion; cc->num_active_ssb = num_active_ssb; - LOG_I(MAC, "Total available RO %d, num of active SSB %d: unused RO = %d max_association_period %u N_RA_sfn %u \n", - cc->total_prach_occasions, cc->num_active_ssb, unused_RA_occasion, max_association_period, N_RA_sfn); + LOG_I(MAC, + "Total available RO %d, num of active SSB %d: unused RO = %d association_period %u N_RA_sfn %u total_prach_occasions_per_config_period %u\n", + cc->total_prach_occasions, + cc->num_active_ssb, + unused_RA_occasion, + cc->max_association_period, + N_RA_sfn, + cc->total_prach_occasions_per_config_period); } void schedule_nr_prach(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) @@ -439,139 +474,167 @@ void nr_initiate_ra_proc(module_id_t module_idP, gNB_MAC_INST *nr_mac = RC.nrmac[module_idP]; NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id]; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; - NR_RA_t *ra = &cc->ra[0]; - uint16_t ra_rnti; + uint8_t total_RApreambles = 64; + uint8_t num_ssb_per_RO = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present; + int pr_found; - // ra_rnti from 5.1.3 in 38.321 - // FK: in case of long PRACH the phone seems to expect the subframe number instead of the slot number here. - if (scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->prach_RootSequenceIndex.present==NR_RACH_ConfigCommon__prach_RootSequenceIndex_PR_l839) - ra_rnti=1+symbol+(9/*slotP*/*14)+(freq_index*14*80)+(ul_carrier_id*14*80*8); - else - ra_rnti=1+symbol+(slotP*14)+(freq_index*14*80)+(ul_carrier_id*14*80*8); - - - // if the preamble received correspond to one of the listed - // the UE sent a RACH either for starting RA procedure or RA procedure failed and UE retries - int pr_found=0; - for (int i = 0; i < ra->preambles.num_preambles; i++) { - if (preamble_index == ra->preambles.preamble_list[i]) { - pr_found=1; - break; - } + if( scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->totalNumberOfRA_Preambles != NULL) + total_RApreambles = *scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->totalNumberOfRA_Preambles; + + if(num_ssb_per_RO > 3) { /*num of ssb per RO >= 1*/ + num_ssb_per_RO -= 3; + total_RApreambles = total_RApreambles/num_ssb_per_RO ; } - if (!pr_found) { - LOG_E(MAC, "[gNB %d][RAPROC] FAILURE: preamble %d does not correspond to any of the ones in rach_ConfigDedicated\n", - module_idP, preamble_index); - - return; // if the PRACH preamble does not correspond to any of the ones sent through RRC abort RA proc - } - // This should be handled differently when we use the initialBWP for RA - ra->bwp_id=1; - NR_BWP_Downlink_t *bwp=ra->secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[ra->bwp_id-1]; - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_INITIATE_RA_PROC, 1); - - LOG_I(MAC, "[gNB %d][RAPROC] CC_id %d Frame %d, Slot %d Initiating RA procedure for preamble index %d\n", module_idP, CC_id, frameP, slotP, preamble_index); - - if (ra->state == RA_IDLE) { - - uint8_t beam_index = ssb_index_from_prach(module_idP, - frameP, - slotP, - preamble_index, - freq_index, - symbol); - int loop = 0; - LOG_D(MAC, "Frame %d, Slot %d: Activating RA process \n", frameP, slotP); - ra->state = Msg2; - ra->timing_offset = timing_offset; - ra->preamble_slot = slotP; - - struct NR_PDCCH_ConfigCommon__commonSearchSpaceList *commonSearchSpaceList = bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->commonSearchSpaceList; - AssertFatal(commonSearchSpaceList->list.count>0, - "common SearchSpace list has 0 elements\n"); - // Common searchspace list - for (int i=0;ilist.count;i++) { - ss=commonSearchSpaceList->list.array[i]; - if(ss->searchSpaceId == *bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->ra_SearchSpace) - ra->ra_ss=ss; - } - - // retrieving ra pdcch monitoring period and offset - find_monitoring_periodicity_offset_common(ra->ra_ss, - &monitoring_slot_period, - &monitoring_offset); - - nr_schedule_msg2(frameP, slotP, &msg2_frame, &msg2_slot, scc, monitoring_slot_period, monitoring_offset,beam_index,cc->num_active_ssb); - - ra->Msg2_frame = msg2_frame; - ra->Msg2_slot = msg2_slot; - - LOG_I(MAC, "%s() Msg2[%04d%d] SFN/SF:%04d%d\n", __FUNCTION__, ra->Msg2_frame, ra->Msg2_slot, frameP, slotP); - if (!ra->cfra) { - do { - ra->rnti = (taus() % 65518) + 1; - loop++; + for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) { + NR_RA_t *ra = &cc->ra[i]; + pr_found = 0; + if (ra->state == RA_IDLE) { + for(int j = 0; j < ra->preambles.num_preambles; j++) { + //check if the preamble received correspond to one of the listed or configured preambles + if (preamble_index == ra->preambles.preamble_list[j]) { + pr_found=1; + break; + } } - while (loop != 100 && !((find_nr_UE_id(module_idP, ra->rnti) == -1) && (find_nr_RA_id(module_idP, CC_id, ra->rnti) == -1) && ra->rnti >= 1 && ra->rnti <= 65519)); - if (loop == 100) { - LOG_E(MAC,"%s:%d:%s: [RAPROC] initialisation random access aborted\n", __FILE__, __LINE__, __FUNCTION__); - abort(); + + if (pr_found == 0) { + continue; } + + uint16_t ra_rnti; + + // ra_rnti from 5.1.3 in 38.321 + // FK: in case of long PRACH the phone seems to expect the subframe number instead of the slot number here. + if (scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->prach_RootSequenceIndex.present + == NR_RACH_ConfigCommon__prach_RootSequenceIndex_PR_l839) + ra_rnti = 1 + symbol + (9 /*slotP*/ * 14) + (freq_index * 14 * 80) + (ul_carrier_id * 14 * 80 * 8); + else + ra_rnti = 1 + symbol + (slotP * 14) + (freq_index * 14 * 80) + (ul_carrier_id * 14 * 80 * 8); + + // This should be handled differently when we use the initialBWP for RA + ra->bwp_id = 1; + NR_BWP_Downlink_t *bwp = ra->secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList + ->list.array[ra->bwp_id - 1]; + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_INITIATE_RA_PROC, 1); + + LOG_I(MAC, + "[gNB %d][RAPROC] CC_id %d Frame %d, Slot %d Initiating RA procedure for preamble index %d\n", + module_idP, + CC_id, + frameP, + slotP, + preamble_index); + + uint8_t beam_index = ssb_index_from_prach(module_idP, frameP, slotP, preamble_index, freq_index, symbol); + + // the UE sent a RACH either for starting RA procedure or RA procedure failed and UE retries + if (ra->cfra) { + // if the preamble received correspond to one of the listed + if (!(preamble_index == ra->preambles.preamble_list[beam_index])) { + LOG_E( + MAC, + "[gNB %d][RAPROC] FAILURE: preamble %d does not correspond to any of the ones in rach_ConfigDedicated\n", + module_idP, + preamble_index); + continue; // if the PRACH preamble does not correspond to any of the ones sent through RRC abort RA proc + } + } + int loop = 0; + LOG_D(MAC, "Frame %d, Slot %d: Activating RA process \n", frameP, slotP); + ra->state = Msg2; + ra->timing_offset = timing_offset; + ra->preamble_slot = slotP; + + struct NR_PDCCH_ConfigCommon__commonSearchSpaceList *commonSearchSpaceList = + bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->commonSearchSpaceList; + AssertFatal(commonSearchSpaceList->list.count > 0, "common SearchSpace list has 0 elements\n"); + // Common searchspace list + for (int i = 0; i < commonSearchSpaceList->list.count; i++) { + ss = commonSearchSpaceList->list.array[i]; + if (ss->searchSpaceId == *bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->ra_SearchSpace) + ra->ra_ss = ss; + } + + // retrieving ra pdcch monitoring period and offset + find_monitoring_periodicity_offset_common(ra->ra_ss, &monitoring_slot_period, &monitoring_offset); + + nr_schedule_msg2(frameP, + slotP, + &msg2_frame, + &msg2_slot, + scc, + monitoring_slot_period, + monitoring_offset, + beam_index, + cc->num_active_ssb); + + ra->Msg2_frame = msg2_frame; + ra->Msg2_slot = msg2_slot; + + LOG_I(MAC, "%s() Msg2[%04d%d] SFN/SF:%04d%d\n", __FUNCTION__, ra->Msg2_frame, ra->Msg2_slot, frameP, slotP); + if (!ra->cfra) { + do { + ra->rnti = (taus() % 65518) + 1; + loop++; + } while (loop != 100 + && !((find_nr_UE_id(module_idP, ra->rnti) == -1) && (find_nr_RA_id(module_idP, CC_id, ra->rnti) == -1) + && ra->rnti >= 1 && ra->rnti <= 65519)); + if (loop == 100) { + LOG_E(MAC, "%s:%d:%s: [RAPROC] initialisation random access aborted\n", __FILE__, __LINE__, __FUNCTION__); + abort(); + } + } + ra->RA_rnti = ra_rnti; + ra->preamble_index = preamble_index; + ra->beam_id = beam_index; + + LOG_I(MAC, + "[gNB %d][RAPROC] CC_id %d Frame %d Activating Msg2 generation in frame %d, slot %d using RA rnti %x SSB " + "index %u\n", + module_idP, + CC_id, + frameP, + ra->Msg2_frame, + ra->Msg2_slot, + ra->RA_rnti, + cc->ssb_index[beam_index]); + + return; } - ra->RA_rnti = ra_rnti; - ra->preamble_index = preamble_index; - ra->beam_id = beam_index; - - LOG_I(MAC,"[gNB %d][RAPROC] CC_id %d Frame %d Activating Msg2 generation in frame %d, slot %d using RA rnti %x SSB index %u\n", - module_idP, - CC_id, - frameP, - ra->Msg2_frame, - ra->Msg2_slot, - ra->RA_rnti, - cc->ssb_index[beam_index]); - - return; } LOG_E(MAC, "[gNB %d][RAPROC] FAILURE: CC_id %d Frame %d initiating RA procedure for preamble index %d\n", module_idP, CC_id, frameP, preamble_index); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_INITIATE_RA_PROC, 0); } -void nr_schedule_RA(module_id_t module_idP, frame_t frameP, sub_frame_t slotP){ - - //uint8_t i = 0; - int CC_id = 0; +void nr_schedule_RA(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) +{ gNB_MAC_INST *mac = RC.nrmac[module_idP]; - NR_COMMON_channels_t *cc = &mac->common_channels[CC_id]; start_meas(&mac->schedule_ra); - -// for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { -// for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) { - -// NR_RA_t *ra = &cc->ra[i]; - NR_RA_t *ra = &cc->ra[0]; - - LOG_D(MAC,"RA[state:%d]\n",ra->state); - switch (ra->state){ - case Msg2: - nr_generate_Msg2(module_idP, CC_id, frameP, slotP); - break; - case Msg4: - //generate_Msg4(module_idP, CC_id, frameP, slotP); - break; - case WAIT_Msg4_ACK: - //check_Msg4_retransmission(module_idP, CC_id, frameP, slotP); - break; - default: - break; + for (int CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { + NR_COMMON_channels_t *cc = &mac->common_channels[CC_id]; + for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) { + NR_RA_t *ra = &cc->ra[i]; + LOG_D(MAC, "RA[state:%d]\n", ra->state); + switch (ra->state) { + case Msg2: + nr_generate_Msg2(module_idP, CC_id, frameP, slotP, ra); + break; + case Msg4: + // generate_Msg4(module_idP, CC_id, frameP, slotP); + break; + case WAIT_Msg4_ACK: + // check_Msg4_retransmission(module_idP, CC_id, frameP, slotP); + break; + default: + break; + } + } } -// } -// } stop_meas(&mac->schedule_ra); } @@ -612,8 +675,8 @@ void nr_get_Msg3alloc(module_id_t module_id, LOG_I(MAC, "[RAPROC] Msg3 slot %d: current slot %u Msg3 frame %u k2 %u Msg3_tda_id %u start symbol index %u\n", ra->Msg3_slot, current_slot, ra->Msg3_frame, k2,ra->Msg3_tda_id, StartSymbolIndex); uint16_t *vrb_map_UL = - &RC.nrmac[module_id]->common_channels[CC_id].vrb_map_UL[ra->Msg3_slot * 275]; - const uint16_t bwpSize = NRRIV2BW(ubwp->bwp_Common->genericParameters.locationAndBandwidth, 275); + &RC.nrmac[module_id]->common_channels[CC_id].vrb_map_UL[ra->Msg3_slot * MAX_BWP_SIZE]; + const uint16_t bwpSize = NRRIV2BW(ubwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); /* search 18 free RBs */ int rbSize = 0; int rbStart = 0; @@ -632,12 +695,11 @@ void nr_get_Msg3alloc(module_id_t module_id, ra->msg3_first_rb = rbStart; } -void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t slotP){ - +void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t slotP, NR_RA_t *ra, uint8_t *RAR_pdu) +{ gNB_MAC_INST *mac = RC.nrmac[module_idP]; NR_COMMON_channels_t *cc = &mac->common_channels[CC_id]; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; - NR_RA_t *ra = &cc->ra[0]; if (ra->state == RA_IDLE) { LOG_W(MAC,"RA is not active for RA %X. skipping msg3 scheduling\n", ra->rnti); @@ -645,7 +707,7 @@ void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t } uint16_t *vrb_map_UL = - &RC.nrmac[module_idP]->common_channels[CC_id].vrb_map_UL[ra->Msg3_slot * 275]; + &RC.nrmac[module_idP]->common_channels[CC_id].vrb_map_UL[ra->Msg3_slot * MAX_BWP_SIZE]; for (int i = 0; i < ra->msg3_nb_rb; ++i) { AssertFatal(!vrb_map_UL[i + ra->msg3_first_rb], "RB %d in %4d.%2d is already taken, cannot allocate Msg3!\n", @@ -694,10 +756,10 @@ void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t pusch_pdu->pdu_bit_map = PUSCH_PDU_BITMAP_PUSCH_DATA; pusch_pdu->rnti = ra->rnti; pusch_pdu->handle = 0; - int abwp_size = NRRIV2BW(ubwp->bwp_Common->genericParameters.locationAndBandwidth,275); - int abwp_start = NRRIV2PRBOFFSET(ubwp->bwp_Common->genericParameters.locationAndBandwidth,275); - int ibwp_size = NRRIV2BW(scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth,275); - int ibwp_start = NRRIV2PRBOFFSET(scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth,275); + int abwp_size = NRRIV2BW(ubwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + int abwp_start = NRRIV2PRBOFFSET(ubwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + int ibwp_size = NRRIV2BW(scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + int ibwp_start = NRRIV2PRBOFFSET(scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); if ((ibwp_start < abwp_start) || (ibwp_size > abwp_size)) pusch_pdu->bwp_start = abwp_start; else @@ -752,27 +814,25 @@ void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t pusch_pdu->nrOfLayers = 1)>>3; // calling function to fill rar message - nr_fill_rar(module_idP, ra, cc->RAR_pdu.payload, pusch_pdu); - + nr_fill_rar(module_idP, ra, RAR_pdu, pusch_pdu); } -// WIP -// todo: -// - fix me -// - get msg3 alloc (see nr_process_rar) -void nr_generate_Msg2(module_id_t module_idP, - int CC_id, - frame_t frameP, - sub_frame_t slotP) +void nr_generate_Msg2(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t slotP, NR_RA_t *ra) { - - int dci_formats[2], rnti_types[2], mcsIndex; + int mcsIndex; int startSymbolAndLength = 0, StartSymbolIndex = -1, NrOfSymbols = 14, StartSymbolIndex_tmp, NrOfSymbols_tmp, x_Overhead, time_domain_assignment = 0; gNB_MAC_INST *nr_mac = RC.nrmac[module_idP]; NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id]; - NR_RA_t *ra = &cc->ra[CC_id]; NR_SearchSpace_t *ss = ra->ra_ss; + // This code from this point on will not work on initialBWP or CORESET0 + AssertFatal(ra->bwp_id > 0, "cannot work on initialBWP for now\n"); + + AssertFatal(ra->secondaryCellGroup, "no secondaryCellGroup for RNTI %04x\n", ra->crnti); + AssertFatal(ra->secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count == 1, + "downlinkBWP_ToAddModList has %d BWP!\n", + ra->secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count); + uint16_t RA_rnti = ra->RA_rnti; long locationAndBandwidth; @@ -780,51 +840,84 @@ void nr_generate_Msg2(module_id_t module_idP, // get the BW of the PDCCH for PDCCH size and RAR PDSCH size NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; - int dci10_bw; + int dci10_bw = 0; if (ra->coreset0_configured == 1) { AssertFatal(1==0,"This is a standalone condition\n"); } else { // on configured BWP or initial LDBWP, bandwidth parameters in DCI correspond size of initialBWP locationAndBandwidth = scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth; - dci10_bw = NRRIV2BW(locationAndBandwidth,275); + dci10_bw = NRRIV2BW(locationAndBandwidth, MAX_BWP_SIZE); } if ((ra->Msg2_frame == frameP) && (ra->Msg2_slot == slotP)) { + uint16_t *vrb_map = cc[CC_id].vrb_map; + int rbStart = 0, rbSize = 6; + for (int i = 0; (i < rbSize) && (rbStart <= (dci10_bw - rbSize)); i++) { + if (vrb_map[rbStart + i]) { + rbStart += i; + i = 0; + } + } + if (rbStart > (dci10_bw - rbSize)) { + LOG_E(MAC, "%s(): cannot find free vrb_map for RA RNTI %04x!\n", __func__, ra->RA_rnti); + return; + } + nfapi_nr_dl_tti_request_body_t *dl_req = &nr_mac->DL_req[CC_id].dl_tti_request_body; - nfapi_nr_pdu_t *tx_req = &nr_mac->TX_req[CC_id].pdu_list[nr_mac->TX_req[CC_id].Number_of_PDUs]; - - nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdcch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs]; - memset((void*)dl_tti_pdcch_pdu,0,sizeof(nfapi_nr_dl_tti_request_pdu_t)); - dl_tti_pdcch_pdu->PDUType = NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE; - dl_tti_pdcch_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdcch_pdu)); - - nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdsch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs+1]; - memset((void *)dl_tti_pdsch_pdu,0,sizeof(nfapi_nr_dl_tti_request_pdu_t)); - dl_tti_pdsch_pdu->PDUType = NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE; - dl_tti_pdsch_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdsch_pdu)); - - nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = &dl_tti_pdcch_pdu->pdcch_pdu.pdcch_pdu_rel15; - nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu_rel15 = &dl_tti_pdsch_pdu->pdsch_pdu.pdsch_pdu_rel15; - - // Checking if the DCI allocation is feasible in current subframe - if (dl_req->nPDUs == NFAPI_NR_MAX_DL_TTI_PDUS) { + // Checking if the DCI allocation is feasible in current subframe: we might + // need to need up to two (PDCCH + PDSCH) messages, so check that we can + // always allocate both (this might be an overestimation, since the PDCCH + // message might already exist) + if (dl_req->nPDUs > NFAPI_NR_MAX_DL_TTI_PDUS - 2) { LOG_I(MAC, "[RAPROC] Subframe %d: FAPI DL structure is full, skip scheduling UE %d\n", slotP, RA_rnti); return; } + uint8_t nr_of_candidates, aggregation_level; + find_aggregation_candidates(&aggregation_level, &nr_of_candidates, ss); + NR_BWP_Downlink_t *bwp = ra->secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[ra->bwp_id - 1]; + NR_ControlResourceSet_t *coreset = get_coreset(bwp, ss, 0 /* common */); + int CCEIndex = allocate_nr_CCEs(nr_mac, + bwp, + coreset, + aggregation_level, + 0, // Y + 0, // m + nr_of_candidates); + + if (CCEIndex < 0) { + LOG_E(MAC, "%s(): cannot find free CCE for RA RNTI %04x!\n", __func__, ra->rnti); + return; + } + + /* look up the PDCCH PDU for this CC, BWP, and CORESET. If it does not + * exist, create it. This is especially important if we have multiple RAs, + * and the DLSCH has to reuse them, so we need to mark them */ + const int bwpid = bwp->bwp_Id; + const int coresetid = coreset->controlResourceSetId; + nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = nr_mac->pdcch_pdu_idx[CC_id][bwpid][coresetid]; + if (!pdcch_pdu_rel15) { + nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdcch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs]; + memset(dl_tti_pdcch_pdu, 0, sizeof(nfapi_nr_dl_tti_request_pdu_t)); + dl_tti_pdcch_pdu->PDUType = NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE; + dl_tti_pdcch_pdu->PDUSize = (uint8_t)(2 + sizeof(nfapi_nr_dl_tti_pdcch_pdu)); + dl_req->nPDUs += 1; + pdcch_pdu_rel15 = &dl_tti_pdcch_pdu->pdcch_pdu.pdcch_pdu_rel15; + nr_configure_pdcch(pdcch_pdu_rel15, ss, coreset, scc, bwp); + nr_mac->pdcch_pdu_idx[CC_id][bwpid][coresetid] = pdcch_pdu_rel15; + } + + nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdsch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs]; + memset((void *)dl_tti_pdsch_pdu,0,sizeof(nfapi_nr_dl_tti_request_pdu_t)); + dl_tti_pdsch_pdu->PDUType = NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE; + dl_tti_pdsch_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdsch_pdu)); + dl_req->nPDUs+=1; + nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu_rel15 = &dl_tti_pdsch_pdu->pdsch_pdu.pdsch_pdu_rel15; + LOG_I(MAC,"[gNB %d] [RAPROC] CC_id %d Frame %d, slotP %d: Generating RAR DCI, state %d\n", module_idP, CC_id, frameP, slotP, ra->state); - // This code from this point on will not work on initialBWP or CORESET0 - AssertFatal(ra->bwp_id>0,"cannot work on initialBWP for now\n"); - - AssertFatal(ra->secondaryCellGroup, - "no secondaryCellGroup for RNTI %04x\n", - ra->crnti); - AssertFatal(ra->secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count == 1, - "downlinkBWP_ToAddModList has %d BWP!\n", ra->secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count); - NR_BWP_Downlink_t *bwp = ra->secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[ra->bwp_id - 1]; NR_BWP_Uplink_t *ubwp=ra->secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[ra->bwp_id-1]; LOG_I(MAC, "[RAPROC] Scheduling common search space DCI type 1 dlBWP BW %d\n", dci10_bw); @@ -837,11 +930,15 @@ void nr_generate_Msg2(module_id_t module_idP, pdsch_pdu_rel15->pduBitmap = 0; pdsch_pdu_rel15->rnti = RA_rnti; - pdsch_pdu_rel15->pduIndex = 0; + /* SCF222: PDU index incremented for each PDSCH PDU sent in TX control + * message. This is used to associate control information to data and is + * reset every slot. */ + const int pduindex = nr_mac->pdu_index[CC_id]++; + pdsch_pdu_rel15->pduIndex = pduindex; - pdsch_pdu_rel15->BWPSize = NRRIV2BW(bwp->bwp_Common->genericParameters.locationAndBandwidth,275); - pdsch_pdu_rel15->BWPStart = NRRIV2PRBOFFSET(bwp->bwp_Common->genericParameters.locationAndBandwidth,275); + pdsch_pdu_rel15->BWPSize = NRRIV2BW(bwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + pdsch_pdu_rel15->BWPStart = NRRIV2PRBOFFSET(bwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); pdsch_pdu_rel15->SubcarrierSpacing = bwp->bwp_Common->genericParameters.subcarrierSpacing; pdsch_pdu_rel15->CyclicPrefix = 0; pdsch_pdu_rel15->NrOfCodewords = 1; @@ -867,8 +964,8 @@ void nr_generate_Msg2(module_id_t module_idP, pdsch_pdu_rel15->numDmrsCdmGrpsNoData = 2; pdsch_pdu_rel15->dmrsPorts = 1; pdsch_pdu_rel15->resourceAlloc = 1; - pdsch_pdu_rel15->rbStart = 0; - pdsch_pdu_rel15->rbSize = 6; + pdsch_pdu_rel15->rbStart = rbStart; + pdsch_pdu_rel15->rbSize = rbSize; pdsch_pdu_rel15->VRBtoPRBMapping = 0; // non interleaved for (int i=0; ibwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.count; i++) { @@ -887,94 +984,89 @@ void nr_generate_Msg2(module_id_t module_idP, pdsch_pdu_rel15->NrOfSymbols = NrOfSymbols; pdsch_pdu_rel15->dlDmrsSymbPos = fill_dmrs_mask(NULL, scc->dmrs_TypeA_Position, NrOfSymbols); - dci_pdu_rel15_t dci_pdu_rel15[MAX_DCI_CORESET]; - dci_pdu_rel15[0].frequency_domain_assignment.val = PRBalloc_to_locationandbandwidth0(pdsch_pdu_rel15->rbSize, + /* Fill PDCCH DL DCI PDU */ + nfapi_nr_dl_dci_pdu_t *dci_pdu = &pdcch_pdu_rel15->dci_pdu[pdcch_pdu_rel15->numDlDci]; + pdcch_pdu_rel15->numDlDci++; + dci_pdu->RNTI = RA_rnti; + /* TODO: remove next line */ + AssertFatal(ss->searchSpaceType->present != NR_SearchSpace__searchSpaceType_PR_ue_Specific, + "shouldn't the RA SS be common?\n"); + dci_pdu->ScramblingId = *scc->physCellId; + dci_pdu->ScramblingRNTI = 0; + dci_pdu->AggregationLevel = aggregation_level; + dci_pdu->CceIndex = CCEIndex; + dci_pdu->beta_PDCCH_1_0 = 0; + dci_pdu->powerControlOffsetSS = 1; + + dci_pdu_rel15_t dci_payload; + dci_payload.frequency_domain_assignment.val = PRBalloc_to_locationandbandwidth0(pdsch_pdu_rel15->rbSize, pdsch_pdu_rel15->rbStart,dci10_bw); - dci_pdu_rel15[0].time_domain_assignment.val = time_domain_assignment; - dci_pdu_rel15[0].vrb_to_prb_mapping.val = 0; - dci_pdu_rel15[0].mcs = pdsch_pdu_rel15->mcsIndex[0]; - dci_pdu_rel15[0].tb_scaling = 0; + dci_payload.time_domain_assignment.val = time_domain_assignment; + dci_payload.vrb_to_prb_mapping.val = 0; + dci_payload.mcs = pdsch_pdu_rel15->mcsIndex[0]; + dci_payload.tb_scaling = 0; - LOG_I(MAC, "[RAPROC] DCI type 1 payload: freq_alloc %d (%d,%d,%d), time_alloc %d, vrb to prb %d, mcs %d tb_scaling %d \n", - dci_pdu_rel15[0].frequency_domain_assignment.val, - pdsch_pdu_rel15->rbStart, - pdsch_pdu_rel15->rbSize, - dci10_bw, - dci_pdu_rel15[0].time_domain_assignment.val, - dci_pdu_rel15[0].vrb_to_prb_mapping.val, - dci_pdu_rel15[0].mcs, - dci_pdu_rel15[0].tb_scaling); - - uint8_t nr_of_candidates, aggregation_level; - find_aggregation_candidates(&aggregation_level, &nr_of_candidates, ss); - NR_ControlResourceSet_t *coreset = get_coreset(bwp, ss, 0 /* common */); - int CCEIndex = allocate_nr_CCEs(nr_mac, - bwp, - coreset, - aggregation_level, - 0, // Y - 0, // m - nr_of_candidates); - - if (CCEIndex < 0) { - LOG_E(MAC, "%s(): cannot find free CCE for RA RNTI %04x!\n", __func__, ra->rnti); - return; - } - nr_configure_pdcch(nr_mac, - pdcch_pdu_rel15, - RA_rnti, - ss, - coreset, - scc, - bwp, - aggregation_level, - CCEIndex); + LOG_I(MAC, + "[RAPROC] DCI type 1 payload: freq_alloc %d (%d,%d,%d), time_alloc %d, vrb to prb %d, mcs %d tb_scaling %d \n", + dci_payload.frequency_domain_assignment.val, + pdsch_pdu_rel15->rbStart, + pdsch_pdu_rel15->rbSize, + dci10_bw, + dci_payload.time_domain_assignment.val, + dci_payload.vrb_to_prb_mapping.val, + dci_payload.mcs, + dci_payload.tb_scaling); LOG_I(MAC, "Frame %d: Subframe %d : Adding common DL DCI for RA_RNTI %x\n", frameP, slotP, RA_rnti); - dci_formats[0] = NR_DL_DCI_FORMAT_1_0; - rnti_types[0] = NR_RNTI_RA; + const int dci_format = NR_DL_DCI_FORMAT_1_0; + const int rnti_type = NR_RNTI_RA; - LOG_I(MAC, "[RAPROC] DCI params: rnti %d, rnti_type %d, dci_format %d coreset params: FreqDomainResource %llx, start_symbol %d n_symb %d\n", - pdcch_pdu_rel15->dci_pdu.RNTI[0], - rnti_types[0], - dci_formats[0], - (unsigned long long)pdcch_pdu_rel15->FreqDomainResource, - pdcch_pdu_rel15->StartSymbolIndex, - pdcch_pdu_rel15->DurationSymbols); + LOG_I(MAC, + "[RAPROC] DCI params: rnti %d, rnti_type %d, dci_format %d coreset params: FreqDomainResource %llx, start_symbol %d n_symb %d\n", + pdcch_pdu_rel15->dci_pdu[0].RNTI, + rnti_type, + dci_format, + (unsigned long long)pdcch_pdu_rel15->FreqDomainResource, + pdcch_pdu_rel15->StartSymbolIndex, + pdcch_pdu_rel15->DurationSymbols); - fill_dci_pdu_rel15(scc,ra->secondaryCellGroup,pdcch_pdu_rel15, &dci_pdu_rel15[0], dci_formats, rnti_types,dci10_bw,ra->bwp_id); - - dl_req->nPDUs+=2; - - // Program UL processing for Msg3 - nr_get_Msg3alloc(module_idP, CC_id, scc, ubwp, slotP, frameP, ra); - LOG_I(MAC, "Frame %d, Subframe %d: Setting Msg3 reception for Frame %d Subframe %d\n", frameP, slotP, ra->Msg3_frame, ra->Msg3_slot); - nr_add_msg3(module_idP, CC_id, frameP, slotP); - ra->state = WAIT_Msg3; - LOG_I(MAC,"[gNB %d][RAPROC] Frame %d, Subframe %d: RA state %d\n", module_idP, frameP, slotP, ra->state); - - x_Overhead = 0; - nr_get_tbs_dl(&dl_tti_pdsch_pdu->pdsch_pdu, x_Overhead, pdsch_pdu_rel15->numDmrsCdmGrpsNoData, dci_pdu_rel15[0].tb_scaling); + fill_dci_pdu_rel15(scc, + ra->secondaryCellGroup, + dci_pdu, + &dci_payload, + dci_format, + rnti_type, + dci10_bw, + ra->bwp_id); // DL TX request + nfapi_nr_pdu_t *tx_req = &nr_mac->TX_req[CC_id].pdu_list[nr_mac->TX_req[CC_id].Number_of_PDUs]; tx_req->PDU_length = pdsch_pdu_rel15->TBSize[0]; - tx_req->PDU_index = nr_mac->pdu_index[CC_id]++; + tx_req->PDU_index = pduindex; tx_req->num_TLV = 1; tx_req->TLVs[0].length = 8; nr_mac->TX_req[CC_id].SFN = frameP; nr_mac->TX_req[CC_id].Number_of_PDUs++; nr_mac->TX_req[CC_id].Slot = slotP; - memcpy((void*)&tx_req->TLVs[0].value.direct[0], (void*)&cc[CC_id].RAR_pdu.payload[0], tx_req->TLVs[0].length); + + // Program UL processing for Msg3 + nr_get_Msg3alloc(module_idP, CC_id, scc, ubwp, slotP, frameP, ra); + LOG_I(MAC, "Frame %d, Subframe %d: Setting Msg3 reception for Frame %d Subframe %d\n", frameP, slotP, ra->Msg3_frame, ra->Msg3_slot); + nr_add_msg3(module_idP, CC_id, frameP, slotP, ra, (uint8_t *) &tx_req->TLVs[0].value.direct[0]); + ra->state = WAIT_Msg3; + LOG_I(MAC,"[gNB %d][RAPROC] Frame %d, Subframe %d: RA state %d\n", module_idP, frameP, slotP, ra->state); + + x_Overhead = 0; + nr_get_tbs_dl(&dl_tti_pdsch_pdu->pdsch_pdu, x_Overhead, pdsch_pdu_rel15->numDmrsCdmGrpsNoData, dci_payload.tb_scaling); T(T_GNB_MAC_DL_RAR_PDU_WITH_DATA, T_INT(module_idP), T_INT(CC_id), T_INT(RA_rnti), T_INT(frameP), T_INT(slotP), T_INT(0) /* harq pid, meaningful? */, - T_BUFFER(&cc[CC_id].RAR_pdu.payload[0], tx_req->TLVs[0].length)); + T_BUFFER(&tx_req->TLVs[0].value.direct[0], tx_req->TLVs[0].length)); /* mark the corresponding RBs as used */ - uint16_t *vrb_map = cc[CC_id].vrb_map; - for (int rb = 0; rb < pdsch_pdu_rel15->rbSize; rb++) - vrb_map[rb + pdsch_pdu_rel15->rbStart] = 1; + for (int rb = 0; rb < rbSize; rb++) + vrb_map[rb + rbStart] = 1; } } @@ -1025,7 +1117,7 @@ void nr_fill_rar(uint8_t Mod_idP, uint8_t * dlsch_buffer, nfapi_nr_pusch_pdu_t *pusch_pdu){ - LOG_I(MAC, "[gNB] Generate RAR MAC PDU frame %d slot %d preamble index %u\n", ra->Msg2_frame, ra-> Msg2_slot, ra->preamble_index); + LOG_I(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_RAPID *rarh = (NR_RA_HEADER_RAPID *) dlsch_buffer; NR_MAC_RAR *rar = (NR_MAC_RAR *) (dlsch_buffer + 1); unsigned char csi_req = 0, tpc_command; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c index 66766535e8..1de46aaea4 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c @@ -126,7 +126,12 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP, mib_sdu_length); if ((frameP & 1023) < 80){ - LOG_I(MAC,"[gNB %d] Frame %d : MIB->BCH CC_id %d, Received %d bytes\n",module_idP, frameP, CC_id, mib_sdu_length); + LOG_D(MAC, + "[gNB %d] Frame %d : MIB->BCH CC_id %d, Received %d bytes\n", + module_idP, + frameP, + CC_id, + mib_sdu_length); } dl_config_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs]; @@ -331,13 +336,19 @@ void nr_fill_nfapi_dl_sib1_pdu(int Mod_idP, memset((void*)dl_tti_pdcch_pdu,0,sizeof(nfapi_nr_dl_tti_request_pdu_t)); dl_tti_pdcch_pdu->PDUType = NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE; dl_tti_pdcch_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdcch_pdu)); + dl_req->nPDUs += 1; + nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = &dl_tti_pdcch_pdu->pdcch_pdu.pdcch_pdu_rel15; + nr_configure_pdcch(pdcch_pdu_rel15, + gNB_mac->sched_ctrlCommon->search_space, + gNB_mac->sched_ctrlCommon->coreset, + scc, + bwp); - nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdsch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs+1]; + nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdsch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs]; memset((void*)dl_tti_pdsch_pdu,0,sizeof(nfapi_nr_dl_tti_request_pdu_t)); dl_tti_pdsch_pdu->PDUType = NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE; dl_tti_pdsch_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdsch_pdu)); - - nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = &dl_tti_pdcch_pdu->pdcch_pdu.pdcch_pdu_rel15; + dl_req->nPDUs += 1; nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu_rel15 = &dl_tti_pdsch_pdu->pdsch_pdu.pdsch_pdu_rel15; pdcch_pdu_rel15->CoreSetType = NFAPI_NR_CSET_CONFIG_MIB_SIB1; @@ -385,48 +396,50 @@ void nr_fill_nfapi_dl_sib1_pdu(int Mod_idP, LOG_D(MAC,"dlDmrsSymbPos = 0x%x\n", pdsch_pdu_rel15->dlDmrsSymbPos); - dci_pdu_rel15_t dci_pdu_rel15[MAX_DCI_CORESET]; - memset(dci_pdu_rel15, 0, sizeof(dci_pdu_rel15_t) * MAX_DCI_CORESET); + /* Fill PDCCH DL DCI PDU */ + nfapi_nr_dl_dci_pdu_t *dci_pdu = &pdcch_pdu_rel15->dci_pdu[pdcch_pdu_rel15->numDlDci]; + pdcch_pdu_rel15->numDlDci++; + dci_pdu->RNTI = SI_RNTI; + dci_pdu->ScramblingId = *scc->physCellId; + dci_pdu->ScramblingRNTI = 0; + dci_pdu->AggregationLevel = gNB_mac->sched_ctrlCommon->aggregation_level; + dci_pdu->CceIndex = gNB_mac->sched_ctrlCommon->cce_index; + dci_pdu->beta_PDCCH_1_0 = 0; + dci_pdu->powerControlOffsetSS = 1; - dci_pdu_rel15[0].bwp_indicator.val = gNB_mac->sched_ctrlCommon->active_bwp->bwp_Id; + /* DCI payload */ + dci_pdu_rel15_t dci_payload; + memset(&dci_payload, 0, sizeof(dci_pdu_rel15_t)); + + dci_payload.bwp_indicator.val = gNB_mac->sched_ctrlCommon->active_bwp->bwp_Id; // frequency domain assignment - dci_pdu_rel15[0].frequency_domain_assignment.val = - PRBalloc_to_locationandbandwidth0(pdsch_pdu_rel15->rbSize, - pdsch_pdu_rel15->rbStart, - gNB_mac->type0_PDCCH_CSS_config.num_rbs); + dci_payload.frequency_domain_assignment.val = PRBalloc_to_locationandbandwidth0( + pdsch_pdu_rel15->rbSize, pdsch_pdu_rel15->rbStart, gNB_mac->type0_PDCCH_CSS_config.num_rbs); - dci_pdu_rel15[0].time_domain_assignment.val = gNB_mac->sched_ctrlCommon->time_domain_allocation; - dci_pdu_rel15[0].mcs = gNB_mac->sched_ctrlCommon->mcs; - dci_pdu_rel15[0].rv = pdsch_pdu_rel15->rvIndex[0]; - dci_pdu_rel15[0].harq_pid = 0; - dci_pdu_rel15[0].ndi = 0; - dci_pdu_rel15[0].dai[0].val = 0; - dci_pdu_rel15[0].tpc = 0; // table 7.2.1-1 in 38.213 - dci_pdu_rel15[0].pucch_resource_indicator = 0; - dci_pdu_rel15[0].pdsch_to_harq_feedback_timing_indicator.val = 0; - dci_pdu_rel15[0].antenna_ports.val = 0; - dci_pdu_rel15[0].dmrs_sequence_initialization.val = pdsch_pdu_rel15->SCID; + dci_payload.time_domain_assignment.val = gNB_mac->sched_ctrlCommon->time_domain_allocation; + dci_payload.mcs = gNB_mac->sched_ctrlCommon->mcs; + dci_payload.rv = pdsch_pdu_rel15->rvIndex[0]; + dci_payload.harq_pid = 0; + dci_payload.ndi = 0; + dci_payload.dai[0].val = 0; + dci_payload.tpc = 0; // table 7.2.1-1 in 38.213 + dci_payload.pucch_resource_indicator = 0; + dci_payload.pdsch_to_harq_feedback_timing_indicator.val = 0; + dci_payload.antenna_ports.val = 0; + dci_payload.dmrs_sequence_initialization.val = pdsch_pdu_rel15->SCID; - nr_configure_pdcch(gNB_mac, - pdcch_pdu_rel15, - SI_RNTI, - gNB_mac->sched_ctrlCommon->search_space, - gNB_mac->sched_ctrlCommon->coreset, - scc, - bwp, - gNB_mac->sched_ctrlCommon->aggregation_level, - gNB_mac->sched_ctrlCommon->cce_index); + int dci_format = NR_DL_DCI_FORMAT_1_0; + int rnti_type = NR_RNTI_SI; - int dci_formats[2]; - int rnti_types[2]; - - dci_formats[0] = NR_DL_DCI_FORMAT_1_0; - rnti_types[0] = NR_RNTI_SI; - - fill_dci_pdu_rel15(scc,secondaryCellGroup,pdcch_pdu_rel15,dci_pdu_rel15,dci_formats,rnti_types,pdsch_pdu_rel15->BWPSize,gNB_mac->sched_ctrlCommon->active_bwp->bwp_Id); - - dl_req->nPDUs += 2; + fill_dci_pdu_rel15(scc, + secondaryCellGroup, + &pdcch_pdu_rel15->dci_pdu[pdcch_pdu_rel15->numDlDci - 1], + &dci_payload, + dci_format, + rnti_type, + pdsch_pdu_rel15->BWPSize, + gNB_mac->sched_ctrlCommon->active_bwp->bwp_Id); LOG_D(MAC,"BWPSize: %i\n", pdcch_pdu_rel15->BWPSize); LOG_D(MAC,"BWPStart: %i\n", pdcch_pdu_rel15->BWPStart); @@ -504,4 +517,4 @@ void schedule_nr_sib1(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) gNB_mac->TX_req[CC_id].SFN = frameP; gNB_mac->TX_req[CC_id].Slot = slotP; } -} \ No newline at end of file +} diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index 8cb1003706..8733f080ec 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -55,28 +55,22 @@ #define HALFWORD 16 #define WORD 32 //#define SIZE_OF_POINTER sizeof (void *) -static boolean_t loop_dcch_dtch = TRUE; -int nr_generate_dlsch_pdu(module_id_t module_idP, - NR_UE_sched_ctrl_t *ue_sched_ctl, - unsigned char *sdus_payload, +// Compute and write all MAC CEs and subheaders, and return number of written +// bytes +int nr_write_ce_dlsch_pdu(module_id_t module_idP, + const NR_UE_sched_ctrl_t *ue_sched_ctl, unsigned char *mac_pdu, - unsigned char num_sdus, - unsigned short *sdu_lengths, - unsigned char *sdu_lcids, unsigned char drx_cmd, - unsigned char *ue_cont_res_id, - unsigned short post_padding) { + unsigned char *ue_cont_res_id) +{ gNB_MAC_INST *gNB = RC.nrmac[module_idP]; NR_MAC_SUBHEADER_FIXED *mac_pdu_ptr = (NR_MAC_SUBHEADER_FIXED *) mac_pdu; - unsigned char *dlsch_buffer_ptr = sdus_payload; uint8_t last_size = 0; int offset = 0, mac_ce_size, i, timing_advance_cmd, tag_id = 0; // MAC CEs uint8_t mac_header_control_elements[16], *ce_ptr; ce_ptr = &mac_header_control_elements[0]; - // 1) Compute MAC CE and related subheaders - // DRX command subheader (MAC CE size 0) if (drx_cmd != 255) { mac_pdu_ptr->R = 0; @@ -301,42 +295,6 @@ int nr_generate_dlsch_pdu(module_id_t module_idP, } } - // 2) Generation of DLSCH MAC subPDUs including subheaders and MAC SDUs - for (i = 0; i < num_sdus; i++) { - - if (sdu_lengths[i] < 256) { - ((NR_MAC_SUBHEADER_SHORT *) mac_pdu_ptr)->R = 0; - ((NR_MAC_SUBHEADER_SHORT *) mac_pdu_ptr)->F = 0; - ((NR_MAC_SUBHEADER_SHORT *) mac_pdu_ptr)->LCID = sdu_lcids[i]; - ((NR_MAC_SUBHEADER_SHORT *) mac_pdu_ptr)->L = (unsigned char) sdu_lengths[i]; - last_size = 2; - } else { - ((NR_MAC_SUBHEADER_LONG *) mac_pdu_ptr)->R = 0; - ((NR_MAC_SUBHEADER_LONG *) mac_pdu_ptr)->F = 1; - ((NR_MAC_SUBHEADER_LONG *) mac_pdu_ptr)->LCID = sdu_lcids[i]; - ((NR_MAC_SUBHEADER_LONG *) mac_pdu_ptr)->L1 = ((unsigned short) sdu_lengths[i] >> 8) & 0xff; - ((NR_MAC_SUBHEADER_LONG *) mac_pdu_ptr)->L2 = (unsigned short) sdu_lengths[i] & 0xff; - last_size = 3; - } - - mac_pdu_ptr += last_size; - // 3) cycle through SDUs, compute each relevant and place dlsch_buffer in - memcpy((void *) mac_pdu_ptr, (void *) dlsch_buffer_ptr, sdu_lengths[i]); - dlsch_buffer_ptr += sdu_lengths[i]; - mac_pdu_ptr += sdu_lengths[i]; - LOG_D(MAC, "Generate DLSCH header num sdu %d len header %d len sdu %d -> offset %ld\n", num_sdus, last_size, sdu_lengths[i], (unsigned char *)mac_pdu_ptr - mac_pdu); - } - - // 4) Compute final offset for padding - if (post_padding > 0) { - ((NR_MAC_SUBHEADER_FIXED *) mac_pdu_ptr)->R = 0; - ((NR_MAC_SUBHEADER_FIXED *) mac_pdu_ptr)->LCID = DL_SCH_LCID_PADDING; - mac_pdu_ptr++; - LOG_D(MAC, "Generate Padding -> offset %ld\n", (unsigned char *)mac_pdu_ptr - mac_pdu); - } else { - // no MAC subPDU with padding - } - // compute final offset offset = ((unsigned char *) mac_pdu_ptr - mac_pdu); //printf("Offset %d \n", ((unsigned char *) mac_pdu_ptr - mac_pdu)); @@ -372,131 +330,236 @@ uint8_t getN_PRB_DMRS(NR_BWP_Downlink_t *bwp, int numDmrsCdmGrpsNoData) { } } -void nr_simple_dlsch_preprocessor(module_id_t module_id, - frame_t frame, - sub_frame_t slot, - int num_slots_per_tdd) { +void nr_store_dlsch_buffer(module_id_t module_id, + frame_t frame, + sub_frame_t slot) { + NR_UE_info_t *UE_info = &RC.nrmac[module_id]->UE_info; - AssertFatal(UE_info->num_UEs <= 1, - "%s() cannot handle more than one UE, but found %d\n", - __func__, - UE_info->num_UEs); - if (UE_info->num_UEs == 0) - return; + for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { + NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; - const int UE_id = 0; - const int CC_id = 0; - - NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; - - /* Retrieve amount of data to send for this UE */ - sched_ctrl->num_total_bytes = 0; - loop_dcch_dtch = BOOL_NOT(loop_dcch_dtch); - const int lcid = loop_dcch_dtch?DL_SCH_LCID_DTCH:DL_SCH_LCID_DCCH; - const uint16_t rnti = UE_info->rnti[UE_id]; - sched_ctrl->rlc_status[lcid] = mac_rlc_status_ind(module_id, - rnti, - module_id, - frame, - slot, - ENB_FLAG_YES, - MBMS_FLAG_NO, - lcid, - 0, - 0); - sched_ctrl->num_total_bytes += sched_ctrl->rlc_status[lcid].bytes_in_buffer; - LOG_I(MAC, - "%d.%d, LCID%d:->DLSCH, RLC status %d bytes. \n", - frame, - slot, - lcid, - sched_ctrl->num_total_bytes); - - if (sched_ctrl->num_total_bytes == 0 - && !sched_ctrl->ta_apply) /* If TA should be applied, give at least one RB */ - return; - - LOG_D(MAC, "[%s][%d.%d], DTCH%d->DLSCH, RLC status %d bytes TA %d\n", - __FUNCTION__, - frame, - slot, - lcid, - sched_ctrl->rlc_status[lcid].bytes_in_buffer, - sched_ctrl->ta_apply); - - /* Find a free CCE */ - const int target_ss = NR_SearchSpace__searchSpaceType_PR_ue_Specific; - sched_ctrl->search_space = get_searchspace(sched_ctrl->active_bwp, target_ss); - uint8_t nr_of_candidates; - find_aggregation_candidates(&sched_ctrl->aggregation_level, - &nr_of_candidates, - sched_ctrl->search_space); - sched_ctrl->coreset = get_coreset(sched_ctrl->active_bwp, sched_ctrl->search_space, 1 /*dedicated*/); - int cid = sched_ctrl->coreset->controlResourceSetId; - const uint16_t Y = UE_info->Y[UE_id][cid][slot]; - const int m = UE_info->num_pdcch_cand[UE_id][cid]; - sched_ctrl->cce_index = allocate_nr_CCEs(RC.nrmac[module_id], - sched_ctrl->active_bwp, - sched_ctrl->coreset, - sched_ctrl->aggregation_level, - Y, - m, - nr_of_candidates); - if (sched_ctrl->cce_index < 0) { - LOG_E(MAC, "%s(): could not find CCE for UE %d\n", __func__, UE_id); - return; + sched_ctrl->num_total_bytes = 0; + const int lcid = DL_SCH_LCID_DTCH; + const uint16_t rnti = UE_info->rnti[UE_id]; + sched_ctrl->rlc_status[lcid] = mac_rlc_status_ind(module_id, + rnti, + module_id, + frame, + slot, + ENB_FLAG_YES, + MBMS_FLAG_NO, + lcid, + 0, + 0); + sched_ctrl->num_total_bytes += sched_ctrl->rlc_status[lcid].bytes_in_buffer; + LOG_D(MAC, + "[%s][%d.%d], DTCH%d->DLSCH, RLC status %d bytes TA %d\n", + __func__, + frame, + slot, + lcid, + sched_ctrl->rlc_status[lcid].bytes_in_buffer, + sched_ctrl->ta_apply); } - UE_info->num_pdcch_cand[UE_id][cid]++; +} - /* Find PUCCH occasion */ - nr_acknack_scheduling(module_id, - UE_id, - frame, - slot, - num_slots_per_tdd, - &sched_ctrl->pucch_sched_idx, - &sched_ctrl->pucch_occ_idx); - - AssertFatal(sched_ctrl->pucch_sched_idx >= 0, "no uplink slot for PUCCH found!\n"); - - uint16_t *vrb_map = RC.nrmac[module_id]->common_channels[CC_id].vrb_map; - // for now HARQ PID is fixed and should be the same as in post-processor - const int current_harq_pid = slot % num_slots_per_tdd; - NR_UE_harq_t *harq = &sched_ctrl->harq_processes[current_harq_pid]; +bool allocate_retransmission(module_id_t module_id, + uint8_t *rballoc_mask, + int *n_rb_sched, + int UE_id, + int current_harq_pid){ + NR_UE_sched_ctrl_t *sched_ctrl = &RC.nrmac[module_id]->UE_info.UE_sched_ctrl[UE_id]; NR_UE_ret_info_t *retInfo = &sched_ctrl->retInfo[current_harq_pid]; - const uint16_t bwpSize = NRRIV2BW(sched_ctrl->active_bwp->bwp_Common->genericParameters.locationAndBandwidth, 275); - int rbStart = NRRIV2PRBOFFSET(sched_ctrl->active_bwp->bwp_Common->genericParameters.locationAndBandwidth, 275); + const uint16_t bwpSize = NRRIV2BW(sched_ctrl->active_bwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + int rbStart = NRRIV2PRBOFFSET(sched_ctrl->active_bwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); - if (harq->round != 0) { /* retransmission */ - sched_ctrl->time_domain_allocation = retInfo->time_domain_allocation; + sched_ctrl->time_domain_allocation = retInfo->time_domain_allocation; - /* ensure that there is a free place for RB allocation */ - int rbSize = 0; - while (rbSize < retInfo->rbSize) { - rbStart += rbSize; /* last iteration rbSize was not enough, skip it */ - rbSize = 0; - while (rbStart < bwpSize && vrb_map[rbStart]) rbStart++; - if (rbStart >= bwpSize) { - LOG_E(MAC, - "cannot allocate retransmission for UE %d/RNTI %04x: no resources\n", + /* ensure that there is a free place for RB allocation */ + int rbSize = 0; + while (rbSize < retInfo->rbSize) { + rbStart += rbSize; /* last iteration rbSize was not enough, skip it */ + rbSize = 0; + while (rbStart < bwpSize && !rballoc_mask[rbStart]) rbStart++; + if (rbStart >= bwpSize) { + LOG_D(MAC, + "cannot allocate retransmission for UE %d/RNTI %04x: no resources\n", + UE_id, + RC.nrmac[module_id]->UE_info.rnti[UE_id]); + return false; + } + while (rbStart + rbSize < bwpSize + && rballoc_mask[rbStart + rbSize] + && rbSize < retInfo->rbSize) + rbSize++; + } + sched_ctrl->rbSize = retInfo->rbSize; + sched_ctrl->rbStart = rbStart; + + /* MCS etc: just reuse from previous scheduling opportunity */ + sched_ctrl->mcsTableIdx = retInfo->mcsTableIdx; + sched_ctrl->mcs = retInfo->mcs; + sched_ctrl->numDmrsCdmGrpsNoData = retInfo->numDmrsCdmGrpsNoData; + + /* retransmissions: directly allocate */ + *n_rb_sched -= sched_ctrl->rbSize; + for (int rb = 0; rb < sched_ctrl->rbSize; rb++) + rballoc_mask[rb+sched_ctrl->rbStart] = 0; + return true; +} + +float thr_ue[MAX_MOBILES_PER_GNB]; + +void pf_dl(module_id_t module_id, + frame_t frame, + sub_frame_t slot, + NR_list_t *UE_list, + int n_rb_sched, + uint8_t *rballoc_mask, + int max_num_ue) { + + NR_UE_info_t *UE_info = &RC.nrmac[module_id]->UE_info; + float coeff_ue[MAX_MOBILES_PER_GNB]; + // UEs that could be scheduled + int ue_array[MAX_MOBILES_PER_GNB]; + NR_list_t UE_sched = { .head = -1, .next = ue_array, .tail = -1, .len = MAX_MOBILES_PER_GNB }; + + /* Loop UE_info->list to check retransmission */ + for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { + NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + sched_ctrl->search_space = get_searchspace(sched_ctrl->active_bwp, NR_SearchSpace__searchSpaceType_PR_ue_Specific); + sched_ctrl->coreset = get_coreset(sched_ctrl->active_bwp, sched_ctrl->search_space, 1 /* dedicated */); + /* get the PID of a HARQ process awaiting retrnasmission, or -1 otherwise */ + sched_ctrl->dl_harq_pid = sched_ctrl->retrans_dl_harq.head; + const rnti_t rnti = UE_info->rnti[UE_id]; + + /* Calculate Throughput */ + const float a = 0.0005f; // corresponds to 200ms window + const uint32_t b = UE_info->mac_stats[UE_id].dlsch_current_bytes; + thr_ue[UE_id] = (1 - a) * thr_ue[UE_id] + a * b; + + /* retransmission */ + if (sched_ctrl->dl_harq_pid >= 0) { + /* Find a free CCE */ + bool freeCCE = find_free_CCE(module_id, slot, UE_id); + if (!freeCCE){ + LOG_D(MAC, "%4d.%2d could not find CCE for DL DCI retransmission UE %d/RNTI %04x\n", frame, slot, UE_id, rnti); + continue; + } + /* Find PUCCH occasion: if it fails, undo CCE allocation (undoing PUCCH + * allocation after CCE alloc fail would be more complex) */ + const bool alloc = nr_acknack_scheduling(module_id, UE_id, frame, slot); + if (!alloc) { + LOG_W(MAC, + "%s(): could not find PUCCH for UE %d/%04x@%d.%d\n", + __func__, UE_id, - rnti); + rnti, + frame, + slot); + int cid = sched_ctrl->coreset->controlResourceSetId; + UE_info->num_pdcch_cand[UE_id][cid]--; + int *cce_list = RC.nrmac[module_id]->cce_list[sched_ctrl->active_bwp->bwp_Id][cid]; + for (int i = 0; i < sched_ctrl->aggregation_level; i++) + cce_list[sched_ctrl->cce_index + i] = 0; return; } - while (rbStart + rbSize < bwpSize - && !vrb_map[rbStart + rbSize] - && rbSize < retInfo->rbSize) - rbSize++; - } - sched_ctrl->rbSize = retInfo->rbSize; - sched_ctrl->rbStart = rbStart; + /* Allocate retransmission */ + bool r = allocate_retransmission(module_id, rballoc_mask, &n_rb_sched, UE_id, sched_ctrl->dl_harq_pid); + if (!r) { + LOG_D(MAC, "%4d.%2d retransmission can NOT be allocated\n", frame, slot); + continue; + } + /* reduce max_num_ue once we are sure UE can be allocated, i.e., has CCE */ + max_num_ue--; + if (max_num_ue < 0) return; + } else { + /* Check DL buffer and skip this UE if no bytes and no TA necessary */ + if (sched_ctrl->num_total_bytes == 0 && frame != (sched_ctrl->ta_frame + 10) % 1024) + continue; - /* MCS etc: just reuse from previous scheduling opportunity */ - sched_ctrl->mcsTableIdx = retInfo->mcsTableIdx; - sched_ctrl->mcs = retInfo->mcs; - sched_ctrl->numDmrsCdmGrpsNoData = retInfo->numDmrsCdmGrpsNoData; - } else { + /* Calculate coeff */ + sched_ctrl->time_domain_allocation = 2; + sched_ctrl->mcsTableIdx = 0; + sched_ctrl->mcs = 9; + sched_ctrl->numDmrsCdmGrpsNoData = 1; + uint8_t N_PRB_DMRS = + getN_PRB_DMRS(sched_ctrl->active_bwp, sched_ctrl->numDmrsCdmGrpsNoData); + int nrOfSymbols = getNrOfSymbols(sched_ctrl->active_bwp, + sched_ctrl->time_domain_allocation); + uint32_t tbs = nr_compute_tbs(nr_get_Qm_dl(sched_ctrl->mcs, sched_ctrl->mcsTableIdx), + nr_get_code_rate_dl(sched_ctrl->mcs, sched_ctrl->mcsTableIdx), + 1, // rbSize + nrOfSymbols, + N_PRB_DMRS, // FIXME // This should be multiplied by the + // number of dmrs symbols + 0 /* N_PRB_oh, 0 for initialBWP */, 0 /* tb_scaling */, + 1 /* nrOfLayers */) + >> 3; + coeff_ue[UE_id] = (float) tbs / thr_ue[UE_id]; + LOG_D(MAC,"b %d, thr_ue[%d] %f, tbs %d, coeff_ue[%d] %f\n", + b, UE_id, thr_ue[UE_id], tbs, UE_id, coeff_ue[UE_id]); + /* Create UE_sched list for UEs eligible for new transmission*/ + add_tail_nr_list(&UE_sched, UE_id); + } + } + + /* Loop UE_sched to find max coeff and allocate transmission */ + while (max_num_ue > 0 && n_rb_sched > 0 && UE_sched.head >= 0) { + + /* Find max coeff from UE_sched*/ + int *max = &UE_sched.head; /* assume head is max */ + int *p = &UE_sched.next[*max]; + while (*p >= 0) { + /* if the current one has larger coeff, save for later */ + if (coeff_ue[*p] > coeff_ue[*max]) + max = p; + p = &UE_sched.next[*p]; + } + /* remove the max one: do not use remove_nr_list() it goes through the + * whole list every time. Note that UE_sched.tail might not be set + * correctly anymore */ + const int UE_id = *max; + p = &UE_sched.next[*max]; + *max = UE_sched.next[*max]; + *p = -1; + + NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + const uint16_t rnti = UE_info->rnti[UE_id]; + const uint16_t bwpSize = NRRIV2BW(sched_ctrl->active_bwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + int rbStart = NRRIV2PRBOFFSET(sched_ctrl->active_bwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + + /* Find a free CCE */ + bool freeCCE = find_free_CCE(module_id, slot, UE_id); + if (!freeCCE) { + LOG_D(MAC, "%4d.%2d could not find CCE for DL DCI UE %d/RNTI %04x\n", frame, slot, UE_id, rnti); + continue; + } + /* reduce max_num_ue once we are sure UE can be allocated, i.e., has CCE */ + max_num_ue--; + if (max_num_ue < 0) return; + + /* Find PUCCH occasion: if it fails, undo CCE allocation (undoing PUCCH + * allocation after CCE alloc fail would be more complex) */ + const bool alloc = nr_acknack_scheduling(module_id, UE_id, frame, slot); + if (!alloc) { + LOG_W(MAC, + "%s(): could not find PUCCH for UE %d/%04x@%d.%d\n", + __func__, + UE_id, + rnti, + frame, + slot); + int cid = sched_ctrl->coreset->controlResourceSetId; + UE_info->num_pdcch_cand[UE_id][cid]--; + int *cce_list = RC.nrmac[module_id]->cce_list[sched_ctrl->active_bwp->bwp_Id][cid]; + for (int i = 0; i < sched_ctrl->aggregation_level; i++) + cce_list[sched_ctrl->cce_index + i] = 0; + return; + } + + /* Allocate transmission */ // Time-domain allocation sched_ctrl->time_domain_allocation = 2; @@ -506,20 +569,22 @@ void nr_simple_dlsch_preprocessor(module_id_t module_id, sched_ctrl->numDmrsCdmGrpsNoData = 1; // Freq-demain allocation - while (rbStart < bwpSize && vrb_map[rbStart]) rbStart++; + while (rbStart < bwpSize && !rballoc_mask[rbStart]) rbStart++; - uint8_t N_PRB_DMRS = + const uint8_t N_PRB_DMRS = getN_PRB_DMRS(sched_ctrl->active_bwp, sched_ctrl->numDmrsCdmGrpsNoData); - int nrOfSymbols = getNrOfSymbols(sched_ctrl->active_bwp, - sched_ctrl->time_domain_allocation); - uint8_t N_DMRS_SLOT = get_num_dmrs_symbols(sched_ctrl->active_bwp->bwp_Dedicated->pdsch_Config->choice.setup, - RC.nrmac[module_id]->common_channels->ServingCellConfigCommon->dmrs_TypeA_Position , - nrOfSymbols); + const int nrOfSymbols = getNrOfSymbols(sched_ctrl->active_bwp, + sched_ctrl->time_domain_allocation); + const NR_ServingCellConfigCommon_t *scc = RC.nrmac[module_id]->common_channels->ServingCellConfigCommon; + const uint8_t N_DMRS_SLOT = get_num_dmrs_symbols( + sched_ctrl->active_bwp->bwp_Dedicated->pdsch_Config->choice.setup, + scc->dmrs_TypeA_Position, + nrOfSymbols); int rbSize = 0; + uint32_t TBS = 0; const int oh = 2 + (sched_ctrl->num_total_bytes >= 256) + 2 * (frame == (sched_ctrl->ta_frame + 10) % 1024); - uint32_t TBS = 0; do { rbSize++; TBS = nr_compute_tbs(nr_get_Qm_dl(sched_ctrl->mcs, sched_ctrl->mcsTableIdx), @@ -531,31 +596,74 @@ void nr_simple_dlsch_preprocessor(module_id_t module_id, 0 /* tb_scaling */, 1 /* nrOfLayers */) >> 3; - } while (rbStart + rbSize < bwpSize && !vrb_map[rbStart + rbSize] && TBS < sched_ctrl->num_total_bytes + oh); + } while (rbStart + rbSize < bwpSize && rballoc_mask[rbStart + rbSize] && TBS < sched_ctrl->num_total_bytes + oh); sched_ctrl->rbSize = rbSize; sched_ctrl->rbStart = rbStart; + + /* transmissions: directly allocate */ + n_rb_sched -= sched_ctrl->rbSize; + for (int rb = 0; rb < sched_ctrl->rbSize; rb++) + rballoc_mask[rb+sched_ctrl->rbStart] = 0; + } +} + +void nr_simple_dlsch_preprocessor(module_id_t module_id, + frame_t frame, + sub_frame_t slot) { + NR_UE_info_t *UE_info = &RC.nrmac[module_id]->UE_info; + + if (UE_info->num_UEs == 0) + return; + + const int CC_id = 0; + + + /* Get bwpSize from the first UE */ + int UE_id = UE_info->list.head; + NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + const uint16_t bwpSize = NRRIV2BW(sched_ctrl->active_bwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + + uint16_t *vrb_map = RC.nrmac[module_id]->common_channels[CC_id].vrb_map; + uint8_t rballoc_mask[bwpSize]; + int n_rb_sched = 0; + for (int i = 0; i < bwpSize; i++) { + // calculate mask: init with "NOT" vrb_map: + // if any RB in vrb_map is blocked (1), the current RBG will be 0 + rballoc_mask[i] = !vrb_map[i]; + n_rb_sched += rballoc_mask[i]; } - /* mark the corresponding RBs as used */ - for (int rb = 0; rb < sched_ctrl->rbSize; rb++) - vrb_map[rb + sched_ctrl->rbStart] = 1; + /* Retrieve amount of data to send for this UE */ + nr_store_dlsch_buffer(module_id, frame, slot); + + /* proportional fair scheduling algorithm */ + pf_dl(module_id, + frame, + slot, + &UE_info->list, + n_rb_sched, + rballoc_mask, + 2); } void nr_schedule_ue_spec(module_id_t module_id, frame_t frame, - sub_frame_t slot, - int num_slots_per_tdd) { + sub_frame_t slot) { gNB_MAC_INST *gNB_mac = RC.nrmac[module_id]; /* PREPROCESSOR */ - gNB_mac->pre_processor_dl(module_id, frame, slot, num_slots_per_tdd); - - NR_UE_info_t *UE_info = &gNB_mac->UE_info; + gNB_mac->pre_processor_dl(module_id, frame, slot); const int CC_id = 0; - NR_UE_list_t *UE_list = &UE_info->list; + NR_ServingCellConfigCommon_t *scc = gNB_mac->common_channels[CC_id].ServingCellConfigCommon; + NR_UE_info_t *UE_info = &gNB_mac->UE_info; + + nfapi_nr_dl_tti_request_body_t *dl_req = &gNB_mac->DL_req[CC_id].dl_tti_request_body; + + NR_list_t *UE_list = &UE_info->list; for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + UE_info->mac_stats[UE_id].dlsch_current_bytes = 0; /* update TA and set ta_apply every 10 frames. * Possible improvement: take the periodicity from input file. @@ -586,10 +694,13 @@ void nr_schedule_ue_spec(module_id_t module_id, uint8_t N_PRB_DMRS = getN_PRB_DMRS(sched_ctrl->active_bwp, sched_ctrl->numDmrsCdmGrpsNoData); - uint8_t N_DMRS_SLOT = get_num_dmrs_symbols(sched_ctrl->active_bwp->bwp_Dedicated->pdsch_Config->choice.setup, RC.nrmac[module_id]->common_channels->ServingCellConfigCommon->dmrs_TypeA_Position , nrOfSymbols); + const nfapi_nr_dmrs_type_e dmrsConfigType = getDmrsConfigType(sched_ctrl->active_bwp); + const int nrOfLayers = 1; + const uint16_t R = nr_get_code_rate_dl(sched_ctrl->mcs, sched_ctrl->mcsTableIdx); + const uint8_t Qm = nr_get_Qm_dl(sched_ctrl->mcs, sched_ctrl->mcsTableIdx); const uint32_t TBS = nr_compute_tbs(nr_get_Qm_dl(sched_ctrl->mcs, sched_ctrl->mcsTableIdx), nr_get_code_rate_dl(sched_ctrl->mcs, sched_ctrl->mcsTableIdx), @@ -598,36 +709,228 @@ void nr_schedule_ue_spec(module_id_t module_id, N_PRB_DMRS * N_DMRS_SLOT, 0 /* N_PRB_oh, 0 for initialBWP */, 0 /* tb_scaling */, - 1 /* nrOfLayers */) + nrOfLayers) >> 3; - const int current_harq_pid = slot % num_slots_per_tdd; + int8_t current_harq_pid = sched_ctrl->dl_harq_pid; + if (current_harq_pid < 0) { + /* PP has not selected a specific HARQ Process, get a new one */ + current_harq_pid = sched_ctrl->available_dl_harq.head; + AssertFatal(current_harq_pid >= 0, + "no free HARQ process available for UE %d\n", + UE_id); + remove_front_nr_list(&sched_ctrl->available_dl_harq); + sched_ctrl->dl_harq_pid = current_harq_pid; + } else { + /* PP selected a specific HARQ process. Check whether it will be a new + * transmission or a retransmission, and remove from the corresponding + * list */ + if (sched_ctrl->harq_processes[current_harq_pid].round == 0) + remove_nr_list(&sched_ctrl->available_dl_harq, current_harq_pid); + else + remove_nr_list(&sched_ctrl->retrans_dl_harq, current_harq_pid); + } NR_UE_harq_t *harq = &sched_ctrl->harq_processes[current_harq_pid]; - NR_sched_pucch *pucch = &sched_ctrl->sched_pucch[sched_ctrl->pucch_sched_idx][sched_ctrl->pucch_occ_idx]; + DevAssert(!harq->is_waiting); + add_tail_nr_list(&sched_ctrl->feedback_dl_harq, current_harq_pid); + NR_sched_pucch_t *pucch = &sched_ctrl->sched_pucch[0]; harq->feedback_slot = pucch->ul_slot; - harq->is_waiting = 1; + harq->is_waiting = true; UE_info->mac_stats[UE_id].dlsch_rounds[harq->round]++; - LOG_D(MAC, "%4d.%2d RNTI %04x start %d RBS %d MCS %d TBS %d HARQ PID %d round %d NDI %d\n", - frame, slot, rnti, sched_ctrl->rbStart, sched_ctrl->rbSize, sched_ctrl->mcs, - TBS, current_harq_pid, harq->round, harq->ndi); + LOG_D(MAC, + "%4d.%2d RNTI %04x start %d RBs %d startSymbol %d nb_symbsol %d MCS %d TBS %d HARQ PID %d round %d NDI %d\n", + frame, + slot, + rnti, + sched_ctrl->rbStart, + sched_ctrl->rbSize, + startSymbolIndex, + nrOfSymbols, + sched_ctrl->mcs, + TBS, + current_harq_pid, + harq->round, + harq->ndi); - nfapi_nr_dl_tti_request_body_t *dl_req = &gNB_mac->DL_req[CC_id].dl_tti_request_body; - nr_fill_nfapi_dl_pdu(module_id, - dl_req, - rnti, - UE_info->secondaryCellGroup[UE_id], - sched_ctrl, - pucch, - getDmrsConfigType(sched_ctrl->active_bwp), - nr_get_code_rate_dl(sched_ctrl->mcs, sched_ctrl->mcsTableIdx), - nr_get_Qm_dl(sched_ctrl->mcs, sched_ctrl->mcsTableIdx), - TBS, - startSymbolIndex, - nrOfSymbols, - current_harq_pid, - harq->ndi, - harq->round); + NR_BWP_Downlink_t *bwp = sched_ctrl->active_bwp; + AssertFatal(bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList, + "searchSpacesToAddModList is null\n"); + AssertFatal(bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList->list.count > 0, + "searchSPacesToAddModList is empty\n"); + + /* look up the PDCCH PDU for this CC, BWP, and CORESET. If it does not + * exist, create it */ + const int bwpid = sched_ctrl->active_bwp->bwp_Id; + const int coresetid = sched_ctrl->coreset->controlResourceSetId; + nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu = gNB_mac->pdcch_pdu_idx[CC_id][bwpid][coresetid]; + if (!pdcch_pdu) { + nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdcch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs]; + memset(dl_tti_pdcch_pdu, 0, sizeof(nfapi_nr_dl_tti_request_pdu_t)); + dl_tti_pdcch_pdu->PDUType = NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE; + dl_tti_pdcch_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdcch_pdu)); + dl_req->nPDUs += 1; + pdcch_pdu = &dl_tti_pdcch_pdu->pdcch_pdu.pdcch_pdu_rel15; + nr_configure_pdcch(pdcch_pdu, sched_ctrl->search_space, sched_ctrl->coreset, scc, bwp); + gNB_mac->pdcch_pdu_idx[CC_id][bwpid][coresetid] = pdcch_pdu; + } + + nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdsch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs]; + memset(dl_tti_pdsch_pdu, 0, sizeof(nfapi_nr_dl_tti_request_pdu_t)); + dl_tti_pdsch_pdu->PDUType = NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE; + dl_tti_pdsch_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdsch_pdu)); + dl_req->nPDUs += 1; + nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu = &dl_tti_pdsch_pdu->pdsch_pdu.pdsch_pdu_rel15; + + pdsch_pdu->pduBitmap = 0; + pdsch_pdu->rnti = rnti; + /* SCF222: PDU index incremented for each PDSCH PDU sent in TX control + * message. This is used to associate control information to data and is + * reset every slot. */ + const int pduindex = gNB_mac->pdu_index[CC_id]++; + pdsch_pdu->pduIndex = pduindex; + + // BWP + pdsch_pdu->BWPSize = NRRIV2BW(bwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + pdsch_pdu->BWPStart = NRRIV2PRBOFFSET(bwp->bwp_Common->genericParameters.locationAndBandwidth,MAX_BWP_SIZE); + pdsch_pdu->SubcarrierSpacing = bwp->bwp_Common->genericParameters.subcarrierSpacing; + if (bwp->bwp_Common->genericParameters.cyclicPrefix) + pdsch_pdu->CyclicPrefix = *bwp->bwp_Common->genericParameters.cyclicPrefix; + else + pdsch_pdu->CyclicPrefix = 0; + + // Codeword information + pdsch_pdu->NrOfCodewords = 1; + pdsch_pdu->targetCodeRate[0] = R; + pdsch_pdu->qamModOrder[0] = Qm; + pdsch_pdu->mcsIndex[0] = sched_ctrl->mcs; + pdsch_pdu->mcsTable[0] = sched_ctrl->mcsTableIdx; + pdsch_pdu->rvIndex[0] = nr_rv_round_map[harq->round]; + pdsch_pdu->TBSize[0] = TBS; + + pdsch_pdu->dataScramblingId = *scc->physCellId; + pdsch_pdu->nrOfLayers = nrOfLayers; + pdsch_pdu->transmissionScheme = 0; + pdsch_pdu->refPoint = 0; // Point A + + // DMRS + pdsch_pdu->dlDmrsSymbPos = + fill_dmrs_mask(bwp->bwp_Dedicated->pdsch_Config->choice.setup, + scc->dmrs_TypeA_Position, + nrOfSymbols); + pdsch_pdu->dmrsConfigType = dmrsConfigType; + pdsch_pdu->dlDmrsScramblingId = *scc->physCellId; + pdsch_pdu->SCID = 0; + pdsch_pdu->numDmrsCdmGrpsNoData = sched_ctrl->numDmrsCdmGrpsNoData; + pdsch_pdu->dmrsPorts = 1; + + // Pdsch Allocation in frequency domain + pdsch_pdu->resourceAlloc = 1; + pdsch_pdu->rbStart = sched_ctrl->rbStart; + pdsch_pdu->rbSize = sched_ctrl->rbSize; + pdsch_pdu->VRBtoPRBMapping = 1; // non-interleaved, check if this is ok for initialBWP + + // Resource Allocation in time domain + pdsch_pdu->StartSymbolIndex = startSymbolIndex; + pdsch_pdu->NrOfSymbols = nrOfSymbols; + + /* Check and validate PTRS values */ + struct NR_SetupRelease_PTRS_DownlinkConfig *phaseTrackingRS = + bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS; + if (phaseTrackingRS) { + bool valid_ptrs_setup = set_dl_ptrs_values(phaseTrackingRS->choice.setup, + pdsch_pdu->rbSize, + pdsch_pdu->mcsIndex[0], + pdsch_pdu->mcsTable[0], + &pdsch_pdu->PTRSFreqDensity, + &pdsch_pdu->PTRSTimeDensity, + &pdsch_pdu->PTRSPortIndex, + &pdsch_pdu->nEpreRatioOfPDSCHToPTRS, + &pdsch_pdu->PTRSReOffset, + pdsch_pdu->NrOfSymbols); + if (valid_ptrs_setup) + pdsch_pdu->pduBitmap |= 0x1; // Bit 0: pdschPtrs - Indicates PTRS included (FR2) + } + + /* Fill PDCCH DL DCI PDU */ + nfapi_nr_dl_dci_pdu_t *dci_pdu = &pdcch_pdu->dci_pdu[pdcch_pdu->numDlDci]; + pdcch_pdu->numDlDci++; + dci_pdu->RNTI = rnti; + if (sched_ctrl->coreset->pdcch_DMRS_ScramblingID && + sched_ctrl->search_space->searchSpaceType->present == NR_SearchSpace__searchSpaceType_PR_ue_Specific) { + dci_pdu->ScramblingId = *sched_ctrl->coreset->pdcch_DMRS_ScramblingID; + dci_pdu->ScramblingRNTI = rnti; + } else { + dci_pdu->ScramblingId = *scc->physCellId; + dci_pdu->ScramblingRNTI = 0; + } + dci_pdu->AggregationLevel = sched_ctrl->aggregation_level; + dci_pdu->CceIndex = sched_ctrl->cce_index; + dci_pdu->beta_PDCCH_1_0 = 0; + dci_pdu->powerControlOffsetSS = 1; + + /* DCI payload */ + dci_pdu_rel15_t dci_payload; + memset(&dci_payload, 0, sizeof(dci_pdu_rel15_t)); + // bwp indicator + const int n_dl_bwp = UE_info->secondaryCellGroup[UE_id]->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count; + AssertFatal(n_dl_bwp == 1, + "downlinkBWP_ToAddModList has %d BWP!\n", + n_dl_bwp); + // as per table 7.3.1.1.2-1 in 38.212 + dci_payload.bwp_indicator.val = n_dl_bwp < 4 ? bwp->bwp_Id : bwp->bwp_Id - 1; + AssertFatal(bwp->bwp_Dedicated->pdsch_Config->choice.setup->resourceAllocation == NR_PDSCH_Config__resourceAllocation_resourceAllocationType1, + "Only frequency resource allocation type 1 is currently supported\n"); + dci_payload.frequency_domain_assignment.val = + PRBalloc_to_locationandbandwidth0( + pdsch_pdu->rbSize, + pdsch_pdu->rbStart, + pdsch_pdu->BWPSize); + dci_payload.time_domain_assignment.val = sched_ctrl->time_domain_allocation; + dci_payload.mcs = sched_ctrl->mcs; + dci_payload.rv = pdsch_pdu->rvIndex[0]; + dci_payload.harq_pid = current_harq_pid; + dci_payload.ndi = harq->ndi; + dci_payload.dai[0].val = (pucch->dai_c-1)&3; + dci_payload.tpc = sched_ctrl->tpc1; // TPC for PUCCH: table 7.2.1-1 in 38.213 + dci_payload.pucch_resource_indicator = pucch->resource_indicator; + dci_payload.pdsch_to_harq_feedback_timing_indicator.val = pucch->timing_indicator; // PDSCH to HARQ TI + dci_payload.antenna_ports.val = 0; // nb of cdm groups w/o data 1 and dmrs port 0 + dci_payload.dmrs_sequence_initialization.val = pdsch_pdu->SCID; + LOG_D(MAC, + "%4d.%2d DCI type 1 payload: freq_alloc %d (%d,%d,%d), " + "time_alloc %d, vrb to prb %d, mcs %d tb_scaling %d ndi %d rv %d\n", + frame, + slot, + dci_payload.frequency_domain_assignment.val, + pdsch_pdu->rbStart, + pdsch_pdu->rbSize, + pdsch_pdu->BWPSize, + dci_payload.time_domain_assignment.val, + dci_payload.vrb_to_prb_mapping.val, + dci_payload.mcs, + dci_payload.tb_scaling, + dci_payload.ndi, + dci_payload.rv); + + const long f = sched_ctrl->search_space->searchSpaceType->choice.ue_Specific->dci_Formats; + const int dci_format = f ? NR_DL_DCI_FORMAT_1_1 : NR_DL_DCI_FORMAT_1_0; + const int rnti_type = NR_RNTI_C; + + fill_dci_pdu_rel15(scc, + UE_info->secondaryCellGroup[UE_id], + dci_pdu, + &dci_payload, + dci_format, + rnti_type, + pdsch_pdu->BWPSize, + bwp->bwp_Id); + + LOG_D(MAC, + "coreset params: FreqDomainResource %llx, start_symbol %d n_symb %d\n", + (unsigned long long)pdcch_pdu->FreqDomainResource, + pdcch_pdu->StartSymbolIndex, + pdcch_pdu->DurationSymbols); NR_UE_ret_info_t *retInfo = &sched_ctrl->retInfo[current_harq_pid]; if (harq->round != 0) { /* retransmission */ @@ -653,8 +956,9 @@ void nr_schedule_ue_spec(module_id_t module_id, retInfo->mcs, retInfo->numDmrsCdmGrpsNoData); /* we do not have to do anything, since we do not require to get data - * from RLC, encode MAC CEs, or copy data to FAPI structures */ - LOG_W(MAC, + * from RLC or encode MAC CEs. The TX_req structure is filled below + * or copy data to FAPI structures */ + LOG_D(MAC, "%d.%2d DL retransmission UE %d/RNTI %04x HARQ PID %d round %d NDI %d\n", frame, slot, @@ -663,123 +967,120 @@ void nr_schedule_ue_spec(module_id_t module_id, current_harq_pid, harq->round, harq->ndi); + AssertFatal(harq->tb_size == TBS, + "UE %d mismatch between scheduled TBS and buffered TB for HARQ PID %d\n", + UE_id, + current_harq_pid); } else { /* initial transmission */ LOG_D(MAC, "[%s] Initial HARQ transmission in %d.%d\n", __FUNCTION__, frame, slot); - /* reserve space for timing advance of UE if necessary, - * nr_generate_dlsch_pdu() checks for ta_apply and add TA CE if necessary */ - const int ta_len = (sched_ctrl->ta_apply) ? 2 : 0; + harq->tb_size = TBS; + uint8_t *buf = (uint8_t *) harq->tb; - /* Get RLC data */ - int header_length_total = 0; - int header_length_last = 0; - int sdu_length_total = 0; - int num_sdus = 0; - uint16_t sdu_lengths[NB_RB_MAX] = {0}; - uint8_t mac_sdus[MAX_NR_DLSCH_PAYLOAD_BYTES]; - unsigned char sdu_lcids[NB_RB_MAX] = {0}; - const int lcid = loop_dcch_dtch?DL_SCH_LCID_DTCH:DL_SCH_LCID_DCCH; + /* first, write all CEs that might be there */ + int written = nr_write_ce_dlsch_pdu(module_id, + sched_ctrl, + (unsigned char *)buf, + 255, // no drx + NULL); // contention res id + buf += written; + int size = TBS - written; + DevAssert(size >= 0); + + /* next, get RLC data */ + + const int lcid = DL_SCH_LCID_DTCH; + int dlsch_total_bytes = 0; if (sched_ctrl->num_total_bytes > 0) { - /* this is the data from the RLC we would like to request (e.g., only - * some bytes for first LC and some more from a second one */ - const rlc_buffer_occupancy_t ndata = sched_ctrl->rlc_status[lcid].bytes_in_buffer; - /* this is the maximum data we can transport based on TBS minus headers */ - const int mindata = min(ndata, TBS - ta_len - header_length_total - sdu_length_total - 2 - (ndata >= 256)); -#if 1 - LOG_D(MAC, - "[gNB %d][USER-PLANE DEFAULT DRB] Frame %d : DTCH->DLSCH, Requesting " - "%d bytes from RLC (lcid %d total hdr len %d), TBS: %d \n \n", - module_id, - frame, - mindata, - lcid, - header_length_total, - TBS); + tbs_size_t len = 0; + while (size > 3) { + // we do not know how much data we will get from RLC, i.e., whether it + // will be longer than 256B or not. Therefore, reserve space for long header, then + // fetch data, then fill real length + NR_MAC_SUBHEADER_LONG *header = (NR_MAC_SUBHEADER_LONG *) buf; + buf += 3; + size -= 3; - sdu_lengths[num_sdus] = mac_rlc_data_req(module_id, - 0x1234, - module_id, - frame, - ENB_FLAG_YES, - MBMS_FLAG_NO, - lcid, - mindata, - (char *)&mac_sdus[sdu_length_total], - 0, - 0); + /* limit requested number of bytes to what preprocessor specified, or + * such that TBS is full */ + const rlc_buffer_occupancy_t ndata = min(sched_ctrl->rlc_status[lcid].bytes_in_buffer, size); + len = mac_rlc_data_req(module_id, + rnti, + module_id, + frame, + ENB_FLAG_YES, + MBMS_FLAG_NO, + lcid, + ndata, + (char *)buf, + 0, + 0); - LOG_D(MAC, - "[gNB %d][USER-PLANE DEFAULT DRB] Got %d bytes for DTCH %d \n", - module_id, - sdu_lengths[num_sdus], - lcid); + LOG_D(MAC, + "%4d.%2d RNTI %04x: %d bytes from DTCH %d (ndata %d, remaining size %d)\n", + frame, + slot, + rnti, + len, + lcid, + ndata, + size); + if (len == 0) + break; - sdu_lcids[num_sdus] = lcid; - sdu_length_total += sdu_lengths[num_sdus]; - header_length_last = 1 + 1 + (sdu_lengths[num_sdus] >= 128); - header_length_total += header_length_last; - num_sdus++; -#else - LOG_D(MAC, "Configuring DL_TX in %d.%d: random data\n", frame, slot); - for (int i = 0; i < TBS; i++) - mac_sdus[i] = (unsigned char) (lrand48()&0xff); - sdu_lcids[0] = 0x3f; // DRB - sdu_lengths[0] = TBS - ta_len - 3; - header_length_total += 2 + (sdu_lengths[0] >= 128); - sdu_length_total += sdu_lengths[0]; - num_sdus +=1; - -#endif + header->R = 0; + header->F = 1; + header->LCID = lcid; + header->L1 = (len >> 8) & 0xff; + header->L2 = len & 0xff; + size -= len; + buf += len; + dlsch_total_bytes += len; + } + if (len == 0) { + /* RLC did not have data anymore, mark buffer as unused */ + buf -= 3; + size += 3; + } } else if (get_softmodem_params()->phy_test || get_softmodem_params()->do_ra) { - LOG_D(MAC, "Configuring DL_TX in %d.%d: random data\n", frame, slot); + /* we will need the large header, phy-test typically allocates all + * resources and fills to the last byte below */ + NR_MAC_SUBHEADER_LONG *header = (NR_MAC_SUBHEADER_LONG *) buf; + buf += 3; + size -= 3; + DevAssert(size > 0); + LOG_D(MAC, "Configuring DL_TX in %d.%d: TBS %d with %d B of random data\n", frame, slot, TBS, size); // fill dlsch_buffer with random data - for (int i = 0; i < TBS; i++) - mac_sdus[i] = (unsigned char) (lrand48()&0xff); - sdu_lcids[0] = 0x3f; // DRB - sdu_lengths[0] = TBS - ta_len - 3; - header_length_total += 2 + (sdu_lengths[0] >= 256); - sdu_length_total += sdu_lengths[0]; - num_sdus +=1; + for (int i = 0; i < size; i++) + buf[i] = lrand48() & 0xff; + header->R = 0; + header->F = 1; + header->LCID = DL_SCH_LCID_PADDING; + header->L1 = (size >> 8) & 0xff; + header->L2 = size & 0xff; + size -= size; + buf += size; + dlsch_total_bytes += size; + } + + // Add padding header and zero rest out if there is space left + if (size > 0) { + NR_MAC_SUBHEADER_FIXED *padding = (NR_MAC_SUBHEADER_FIXED *) buf; + padding->R = 0; + padding->LCID = DL_SCH_LCID_PADDING; + size -= 1; + buf += 1; + while (size > 0) { + *buf = 0; + buf += 1; + size -= 1; + } } UE_info->mac_stats[UE_id].dlsch_total_bytes += TBS; - UE_info->mac_stats[UE_id].lc_bytes_tx[lcid] += sdu_length_total; - - const int post_padding = TBS > header_length_total + sdu_length_total + ta_len; - - const int ntx_req = gNB_mac->TX_req[CC_id].Number_of_PDUs; - nfapi_nr_pdu_t *tx_req = &gNB_mac->TX_req[CC_id].pdu_list[ntx_req]; - /* pointer to directly generate the PDU into the nFAPI structure */ - uint32_t *buf = tx_req->TLVs[0].value.direct; - - const int offset = nr_generate_dlsch_pdu( - module_id, - sched_ctrl, - (unsigned char *)mac_sdus, - (unsigned char *)buf, - num_sdus, // num_sdus - sdu_lengths, - sdu_lcids, - 255, // no drx - NULL, // contention res id - post_padding); - - // Padding: fill remainder of DLSCH with 0 - if (post_padding > 0) { - for (int j = 0; j < TBS - offset; j++) - buf[offset + j] = 0; - } - - /* the buffer has been filled by nr_generate_dlsch_pdu(), below we simply - * fill the remaining information */ - tx_req->PDU_length = TBS; - tx_req->PDU_index = gNB_mac->pdu_index[0]++; - tx_req->num_TLV = 1; - tx_req->TLVs[0].length = TBS + 2; - gNB_mac->TX_req[CC_id].Number_of_PDUs++; - gNB_mac->TX_req[CC_id].SFN = frame; - gNB_mac->TX_req[CC_id].Slot = slot; + UE_info->mac_stats[UE_id].dlsch_current_bytes = TBS; + UE_info->mac_stats[UE_id].lc_bytes_tx[lcid] += dlsch_total_bytes; retInfo->rbSize = sched_ctrl->rbSize; retInfo->time_domain_allocation = sched_ctrl->time_domain_allocation; @@ -799,21 +1100,20 @@ void nr_schedule_ue_spec(module_id_t module_id, } T(T_GNB_MAC_DL_PDU_WITH_DATA, T_INT(module_id), T_INT(CC_id), T_INT(rnti), - T_INT(frame), T_INT(slot), T_INT(current_harq_pid), T_BUFFER(buf, TBS)); - -#if defined(ENABLE_MAC_PAYLOAD_DEBUG) - if (frame%100 == 0) { - LOG_I(MAC, - "%d.%d, first 10 payload bytes, TBS size: %d \n", - frame, - slot, - TBS); - for(int i = 0; i < 10; i++) - LOG_I(MAC, "byte %d: %x\n", i, ((uint8_t *) buf)[i]); - } -#endif + T_INT(frame), T_INT(slot), T_INT(current_harq_pid), T_BUFFER(harq->tb, TBS)); } + const int ntx_req = gNB_mac->TX_req[CC_id].Number_of_PDUs; + nfapi_nr_pdu_t *tx_req = &gNB_mac->TX_req[CC_id].pdu_list[ntx_req]; + tx_req->PDU_length = TBS; + tx_req->PDU_index = pduindex; + tx_req->num_TLV = 1; + tx_req->TLVs[0].length = TBS + 2; + memcpy(tx_req->TLVs[0].value.direct, harq->tb, TBS); + gNB_mac->TX_req[CC_id].Number_of_PDUs++; + gNB_mac->TX_req[CC_id].SFN = frame; + gNB_mac->TX_req[CC_id].Slot = slot; + /* mark UE as scheduled */ sched_ctrl->rbSize = 0; } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c index f0f809fb39..6487f391b9 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c @@ -80,7 +80,7 @@ void nr_schedule_css_dlsch_phytest(module_id_t module_idP, NR_ServingCellConfigCommon_t *scc=cc->ServingCellConfigCommon; - int dlBWP_carrier_bandwidth = NRRIV2BW(scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth,275); + int dlBWP_carrier_bandwidth = NRRIV2BW(scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); /* @@ -94,7 +94,7 @@ void nr_schedule_css_dlsch_phytest(module_id_t module_idP, for (CC_id=0; CC_iddownlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth,275)); + NRRIV2PRBOFFSET(scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE)); dl_req = &nr_mac->DL_req[CC_id].dl_tti_request_body; @@ -103,7 +103,7 @@ void nr_schedule_css_dlsch_phytest(module_id_t module_idP, dl_tti_pdcch_pdu->PDUType = NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE; dl_tti_pdcch_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdcch_pdu)); - dl_tti_pdsch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs+1]; + dl_tti_pdsch_pdu = &nr_mac->DL_req[CC_id].dl_tti_request_body.dl_tti_pdu_list[nr_mac->DL_req[CC_id].dl_tti_request_body.nPDUs+1]; memset((void *)dl_tti_pdsch_pdu,0,sizeof(nfapi_nr_dl_tti_request_pdu_t)); dl_tti_pdsch_pdu->PDUType = NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE; dl_tti_pdsch_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdsch_pdu)); @@ -117,8 +117,8 @@ void nr_schedule_css_dlsch_phytest(module_id_t module_idP, pdsch_pdu_rel15->pduIndex = 0; // BWP - pdsch_pdu_rel15->BWPSize = NRRIV2BW(scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth,275); - pdsch_pdu_rel15->BWPStart = NRRIV2PRBOFFSET(scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth,275); + pdsch_pdu_rel15->BWPSize = NRRIV2BW(scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + pdsch_pdu_rel15->BWPStart = NRRIV2PRBOFFSET(scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); pdsch_pdu_rel15->SubcarrierSpacing = scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.subcarrierSpacing; pdsch_pdu_rel15->CyclicPrefix = 0; pdsch_pdu_rel15->NrOfCodewords = 1; @@ -238,14 +238,16 @@ void nr_schedule_css_dlsch_phytest(module_id_t module_idP, pdsch_pdu_rel15->mcsIndex[0]); */ - dl_req->nPDUs+=2; + nr_mac->DL_req[CC_id].dl_tti_request_body.nPDUs+=2; TX_req = &nr_mac->TX_req[CC_id].pdu_list[nr_mac->TX_req[CC_id].Number_of_PDUs]; TX_req->PDU_length = 6; TX_req->PDU_index = nr_mac->pdu_index[CC_id]++; TX_req->num_TLV = 1; TX_req->TLVs[0].length = 8; - memcpy((void*)&TX_req->TLVs[0].value.direct[0],(void*)&cc[CC_id].RAR_pdu.payload[0],TX_req->TLVs[0].length); + // why do we copy from RAR_pdu here? Shouldn't we fill some more or less + // meaningful data, e.g., padding + random data? + //memcpy((void *)&TX_req->TLVs[0].value.direct[0], (void *)&cc[CC_id].RAR_pdu[0].payload[0], TX_req->TLVs[0].length); nr_mac->TX_req[CC_id].Number_of_PDUs++; nr_mac->TX_req[CC_id].SFN=frameP; nr_mac->TX_req[CC_id].Slot=slotP; @@ -255,9 +257,10 @@ void nr_schedule_css_dlsch_phytest(module_id_t module_idP, /* schedules whole bandwidth for first user, all the time */ void nr_preprocessor_phytest(module_id_t module_id, frame_t frame, - sub_frame_t slot, - int num_slots_per_tdd) + sub_frame_t slot) { + if (slot != 1) + return; NR_UE_info_t *UE_info = &RC.nrmac[module_id]->UE_info; const int UE_id = 0; const int CC_id = 0; @@ -267,7 +270,7 @@ void nr_preprocessor_phytest(module_id_t module_id, UE_id); NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; /* find largest unallocated chunk */ - const int bwpSize = NRRIV2BW(sched_ctrl->active_bwp->bwp_Common->genericParameters.locationAndBandwidth, 275); + const int bwpSize = NRRIV2BW(sched_ctrl->active_bwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); int rbStart = 0; int tStart = 0; int rbSize = 0; @@ -328,14 +331,25 @@ void nr_preprocessor_phytest(module_id_t module_id, __func__, UE_id); - nr_acknack_scheduling(module_id, - UE_id, - frame, - slot, - num_slots_per_tdd, - &sched_ctrl->pucch_sched_idx, - &sched_ctrl->pucch_occ_idx); - AssertFatal(sched_ctrl->pucch_sched_idx >= 0, "no uplink slot for PUCCH found!\n"); + const bool alloc = nr_acknack_scheduling(module_id, UE_id, frame, slot); + if (!alloc) { + LOG_D(MAC, + "%s(): could not find PUCCH for UE %d/%04x@%d.%d\n", + __func__, + UE_id, + rnti, + frame, + slot); + UE_info->num_pdcch_cand[UE_id][cid]--; + int *cce_list = RC.nrmac[module_id]->cce_list[sched_ctrl->active_bwp->bwp_Id][cid]; + for (int i = 0; i < sched_ctrl->aggregation_level; i++) + cce_list[sched_ctrl->cce_index + i] = 0; + return; + } + + AssertFatal(alloc, + "could not find uplink slot for PUCCH (RNTI %04x@%d.%d)!\n", + rnti, frame, slot); sched_ctrl->rbStart = rbStart; sched_ctrl->rbSize = rbSize; @@ -350,13 +364,15 @@ void nr_preprocessor_phytest(module_id_t module_id, } sched_ctrl->mcs = 9; sched_ctrl->numDmrsCdmGrpsNoData = 1; + /* get the PID of a HARQ process awaiting retransmission, or -1 otherwise */ + sched_ctrl->dl_harq_pid = sched_ctrl->retrans_dl_harq.head; /* mark the corresponding RBs as used */ for (int rb = 0; rb < sched_ctrl->rbSize; rb++) vrb_map[rb + sched_ctrl->rbStart] = 1; } -void nr_ul_preprocessor_phytest(module_id_t module_id, +bool nr_ul_preprocessor_phytest(module_id_t module_id, frame_t frame, sub_frame_t slot, int num_slots_per_tdd, @@ -372,7 +388,7 @@ void nr_ul_preprocessor_phytest(module_id_t module_id, __func__, UE_info->num_UEs); if (UE_info->num_UEs == 0) - return; + return false; const int UE_id = 0; const int CC_id = 0; @@ -387,22 +403,22 @@ void nr_ul_preprocessor_phytest(module_id_t module_id, tda, tdaList->list.count); int K2 = get_K2(sched_ctrl->active_ubwp, tda, mu); - const int sched_frame = frame + (slot + K2 >= num_slots_per_tdd); - const int sched_slot = (slot + K2) % num_slots_per_tdd; + const int sched_frame = frame + (slot + K2 >= nr_slots_per_frame[mu]); + const int sched_slot = (slot + K2) % nr_slots_per_frame[mu]; /* check if slot is UL, and that slot is 8 (assuming K2=6 because of UE * limitations). Note that if K2 or the TDD configuration is changed, below * conditions might exclude each other and never be true */ if (!(is_xlsch_in_slot(ulsch_in_slot_bitmap, sched_slot) && sched_slot == 8)) - return; + return false; - const int bw = NRRIV2BW(sched_ctrl->active_ubwp->bwp_Common->genericParameters.locationAndBandwidth, 275); + const int bw = NRRIV2BW(sched_ctrl->active_ubwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); uint16_t rbStart = 0; uint16_t rbSize = 50; /* due to OAI UE limitations */ if (rbSize>bw) rbSize = bw; uint16_t *vrb_map_UL = - &RC.nrmac[module_id]->common_channels[CC_id].vrb_map_UL[sched_slot * 275]; + &RC.nrmac[module_id]->common_channels[CC_id].vrb_map_UL[sched_slot * MAX_BWP_SIZE]; for (int i = rbStart; i < rbStart + rbSize; ++i) { if (vrb_map_UL[i]) { LOG_E(MAC, @@ -411,7 +427,7 @@ void nr_ul_preprocessor_phytest(module_id_t module_id, frame, slot, i); - return; + return false; } } @@ -438,7 +454,7 @@ void nr_ul_preprocessor_phytest(module_id_t module_id, nr_of_candidates); if (sched_ctrl->cce_index < 0) { LOG_E(MAC, "%s(): CCE list not empty, couldn't schedule PUSCH\n", __func__); - return; + return false; } UE_info->num_pdcch_cand[UE_id][cid]++; @@ -465,6 +481,8 @@ void nr_ul_preprocessor_phytest(module_id_t module_id, sched_pusch->mcs = mcs; sched_pusch->rbStart = rbStart; sched_pusch->rbSize = rbSize; + /* get the PID of a HARQ process awaiting retransmission, or -1 for "any new" */ + sched_pusch->ul_harq_pid = sched_ctrl->retrans_ul_harq.head; /* Calculate TBS from MCS */ sched_pusch->R = nr_get_code_rate_ul(mcs, ps->mcs_table); @@ -487,4 +505,5 @@ void nr_ul_preprocessor_phytest(module_id_t module_id, /* mark the corresponding RBs as used */ for (int rb = rbStart; rb < rbStart + rbSize; rb++) vrb_map_UL[rb] = 1; + return true; } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index ebe8e4cb87..20da8fa30a 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -502,259 +502,34 @@ void nr_configure_css_dci_initial(nfapi_nr_dl_tti_pdcch_pdu_rel15_t* pdcch_pdu, } -void nr_fill_nfapi_dl_pdu(int Mod_idP, - nfapi_nr_dl_tti_request_body_t *dl_req, - rnti_t rnti, - NR_CellGroupConfig_t *secondaryCellGroup, - NR_UE_sched_ctrl_t *sched_ctrl, - NR_sched_pucch *pucch_sched, - nfapi_nr_dmrs_type_e dmrsConfigType, - uint16_t R, - uint8_t Qm, - uint32_t TBS, - int StartSymbolIndex, - int NrOfSymbols, - int harq_pid, - int ndi, - int round) { - gNB_MAC_INST *nr_mac = RC.nrmac[Mod_idP]; - NR_COMMON_channels_t *cc = nr_mac->common_channels; - NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; - - const int bwp_id = sched_ctrl->active_bwp->bwp_Id; - const int nrOfLayers = 1; - const int mcs = sched_ctrl->mcs; - const int mcs_table_index = sched_ctrl->mcsTableIdx; - bool valid_ptrs_setup = false; - - AssertFatal(secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count == 1, - "downlinkBWP_ToAddModList has %d BWP!\n", - secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count); - NR_BWP_Downlink_t *bwp=secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[bwp_id-1]; - - AssertFatal(bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList!=NULL,"searchPsacesToAddModList is null\n"); - AssertFatal(bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList->list.count>0, - "searchPsacesToAddModList is empty\n"); - - nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdcch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs]; - memset((void*)dl_tti_pdcch_pdu,0,sizeof(nfapi_nr_dl_tti_request_pdu_t)); - dl_tti_pdcch_pdu->PDUType = NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE; - dl_tti_pdcch_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdcch_pdu)); - - nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdsch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs+1]; - memset((void*)dl_tti_pdsch_pdu,0,sizeof(nfapi_nr_dl_tti_request_pdu_t)); - dl_tti_pdsch_pdu->PDUType = NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE; - dl_tti_pdsch_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdsch_pdu)); - - nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = &dl_tti_pdcch_pdu->pdcch_pdu.pdcch_pdu_rel15; - nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu_rel15 = &dl_tti_pdsch_pdu->pdsch_pdu.pdsch_pdu_rel15; - - - pdsch_pdu_rel15->pduBitmap = 0; - pdsch_pdu_rel15->rnti = rnti; - pdsch_pdu_rel15->pduIndex = nr_mac->pdu_index[0]++; - - // BWP - pdsch_pdu_rel15->BWPSize = NRRIV2BW(bwp->bwp_Common->genericParameters.locationAndBandwidth,275); - pdsch_pdu_rel15->BWPStart = NRRIV2PRBOFFSET(bwp->bwp_Common->genericParameters.locationAndBandwidth,275); - pdsch_pdu_rel15->SubcarrierSpacing = bwp->bwp_Common->genericParameters.subcarrierSpacing; - if (bwp->bwp_Common->genericParameters.cyclicPrefix) - pdsch_pdu_rel15->CyclicPrefix = *bwp->bwp_Common->genericParameters.cyclicPrefix; - else - pdsch_pdu_rel15->CyclicPrefix = 0; - - pdsch_pdu_rel15->NrOfCodewords = 1; - pdsch_pdu_rel15->targetCodeRate[0] = nr_get_code_rate_dl(mcs, mcs_table_index); - pdsch_pdu_rel15->qamModOrder[0] = 2; - pdsch_pdu_rel15->mcsIndex[0] = mcs; - pdsch_pdu_rel15->mcsTable[0] = mcs_table_index; - pdsch_pdu_rel15->rvIndex[0] = nr_rv_round_map[round]; - pdsch_pdu_rel15->dataScramblingId = *scc->physCellId; - pdsch_pdu_rel15->nrOfLayers = nrOfLayers; - pdsch_pdu_rel15->transmissionScheme = 0; - pdsch_pdu_rel15->refPoint = 0; // Point A - pdsch_pdu_rel15->dmrsConfigType = dmrsConfigType; - pdsch_pdu_rel15->dlDmrsScramblingId = *scc->physCellId; - pdsch_pdu_rel15->SCID = 0; - pdsch_pdu_rel15->numDmrsCdmGrpsNoData = sched_ctrl->numDmrsCdmGrpsNoData; - pdsch_pdu_rel15->dmrsPorts = 1; - pdsch_pdu_rel15->resourceAlloc = 1; - pdsch_pdu_rel15->rbStart = sched_ctrl->rbStart; - pdsch_pdu_rel15->rbSize = sched_ctrl->rbSize; - pdsch_pdu_rel15->VRBtoPRBMapping = 1; // non-interleaved, check if this is ok for initialBWP - pdsch_pdu_rel15->targetCodeRate[0] = R; - pdsch_pdu_rel15->qamModOrder[0] = Qm; - pdsch_pdu_rel15->TBSize[0] = TBS; - pdsch_pdu_rel15->mcsTable[0] = sched_ctrl->mcsTableIdx; - pdsch_pdu_rel15->StartSymbolIndex = StartSymbolIndex; - pdsch_pdu_rel15->NrOfSymbols = NrOfSymbols; - - pdsch_pdu_rel15->dlDmrsSymbPos = - fill_dmrs_mask(bwp->bwp_Dedicated->pdsch_Config->choice.setup, - scc->dmrs_TypeA_Position, - pdsch_pdu_rel15->NrOfSymbols); - - /* Check and validate PTRS values */ - if(bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS != NULL) { - valid_ptrs_setup = set_dl_ptrs_values(bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup, - pdsch_pdu_rel15->rbSize, pdsch_pdu_rel15->mcsIndex[0], - pdsch_pdu_rel15->mcsTable[0], - &pdsch_pdu_rel15->PTRSFreqDensity,&pdsch_pdu_rel15->PTRSTimeDensity, - &pdsch_pdu_rel15->PTRSPortIndex,&pdsch_pdu_rel15->nEpreRatioOfPDSCHToPTRS, - &pdsch_pdu_rel15->PTRSReOffset, pdsch_pdu_rel15->NrOfSymbols); - if(valid_ptrs_setup==true) { - pdsch_pdu_rel15->pduBitmap |=0x1; - } - } - - dci_pdu_rel15_t dci_pdu_rel15[MAX_DCI_CORESET]; - memset(dci_pdu_rel15, 0, sizeof(dci_pdu_rel15_t) * MAX_DCI_CORESET); - - // bwp indicator - int n_dl_bwp = secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count; - if (n_dl_bwp < 4) - dci_pdu_rel15[0].bwp_indicator.val = bwp_id; - else - dci_pdu_rel15[0].bwp_indicator.val = bwp_id - 1; // as per table 7.3.1.1.2-1 in 38.212 - // frequency domain assignment - if (bwp->bwp_Dedicated->pdsch_Config->choice.setup->resourceAllocation==NR_PDSCH_Config__resourceAllocation_resourceAllocationType1) - dci_pdu_rel15[0].frequency_domain_assignment.val = - PRBalloc_to_locationandbandwidth0( - pdsch_pdu_rel15->rbSize, - pdsch_pdu_rel15->rbStart, - NRRIV2BW(bwp->bwp_Common->genericParameters.locationAndBandwidth, - 275)); - else - AssertFatal(1==0,"Only frequency resource allocation type 1 is currently supported\n"); - // time domain assignment: row index used instead of SLIV - dci_pdu_rel15[0].time_domain_assignment.val = sched_ctrl->time_domain_allocation; - // mcs and rv - dci_pdu_rel15[0].mcs = mcs; - dci_pdu_rel15[0].rv = pdsch_pdu_rel15->rvIndex[0]; - // harq pid and ndi - dci_pdu_rel15[0].harq_pid = harq_pid; - dci_pdu_rel15[0].ndi = ndi; - // DAI - dci_pdu_rel15[0].dai[0].val = (pucch_sched->dai_c-1)&3; - - // TPC for PUCCH - dci_pdu_rel15[0].tpc = sched_ctrl->tpc1; // table 7.2.1-1 in 38.213 - // PUCCH resource indicator - dci_pdu_rel15[0].pucch_resource_indicator = pucch_sched->resource_indicator; - // PDSCH to HARQ TI - dci_pdu_rel15[0].pdsch_to_harq_feedback_timing_indicator.val = pucch_sched->timing_indicator; - // antenna ports - dci_pdu_rel15[0].antenna_ports.val = 0; // nb of cdm groups w/o data 1 and dmrs port 0 - // dmrs sequence initialization - dci_pdu_rel15[0].dmrs_sequence_initialization.val = pdsch_pdu_rel15->SCID; - LOG_D(MAC, - "[gNB scheduler phytest] DCI type 1 payload: freq_alloc %d (%d,%d,%d), " - "time_alloc %d, vrb to prb %d, mcs %d tb_scaling %d ndi %d rv %d\n", - dci_pdu_rel15[0].frequency_domain_assignment.val, - pdsch_pdu_rel15->rbStart, - pdsch_pdu_rel15->rbSize, - NRRIV2BW(bwp->bwp_Common->genericParameters.locationAndBandwidth, 275), - dci_pdu_rel15[0].time_domain_assignment.val, - dci_pdu_rel15[0].vrb_to_prb_mapping.val, - dci_pdu_rel15[0].mcs, - dci_pdu_rel15[0].tb_scaling, - dci_pdu_rel15[0].ndi, - dci_pdu_rel15[0].rv); - - nr_configure_pdcch(nr_mac, - pdcch_pdu_rel15, - rnti, - sched_ctrl->search_space, - sched_ctrl->coreset, - scc, - bwp, - sched_ctrl->aggregation_level, - sched_ctrl->cce_index); - - int dci_formats[2]; - int rnti_types[2]; - - if (sched_ctrl->search_space->searchSpaceType->choice.ue_Specific->dci_Formats) - dci_formats[0] = NR_DL_DCI_FORMAT_1_1; - else - dci_formats[0] = NR_DL_DCI_FORMAT_1_0; - - rnti_types[0] = NR_RNTI_C; - - fill_dci_pdu_rel15(scc,secondaryCellGroup,pdcch_pdu_rel15,dci_pdu_rel15,dci_formats,rnti_types,pdsch_pdu_rel15->BWPSize,bwp_id); - - LOG_D(MAC, - "DCI params: rnti %x, rnti_type %d, dci_format %d\n", - pdcch_pdu_rel15->dci_pdu.RNTI[0], - rnti_types[0], - dci_formats[0]); - LOG_D(MAC, - "coreset params: FreqDomainResource %llx, start_symbol %d n_symb %d\n", - (unsigned long long)pdcch_pdu_rel15->FreqDomainResource, - pdcch_pdu_rel15->StartSymbolIndex, - pdcch_pdu_rel15->DurationSymbols); - - LOG_D(MAC, - "DLSCH PDU: start PRB %d n_PRB %d start symbol %d nb_symbols %d " - "nb_layers %d nb_codewords %d mcs %d TBS: %d\n", - pdsch_pdu_rel15->rbStart, - pdsch_pdu_rel15->rbSize, - pdsch_pdu_rel15->StartSymbolIndex, - pdsch_pdu_rel15->NrOfSymbols, - pdsch_pdu_rel15->nrOfLayers, - pdsch_pdu_rel15->NrOfCodewords, - pdsch_pdu_rel15->mcsIndex[0], - TBS); - - dl_req->nPDUs += 2; -} - -void config_uldci(NR_BWP_Uplink_t *ubwp, - nfapi_nr_pusch_pdu_t *pusch_pdu, - nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15, +void config_uldci(const NR_BWP_Uplink_t *ubwp, + const nfapi_nr_pusch_pdu_t *pusch_pdu, dci_pdu_rel15_t *dci_pdu_rel15, - int *dci_formats, - int time_domain_assignment, uint8_t tpc, - int n_ubwp, int bwp_id) { - const int bw = NRRIV2BW(ubwp->bwp_Common->genericParameters.locationAndBandwidth, 275); - switch (dci_formats[(pdcch_pdu_rel15->numDlDci) - 1]) { + int dci_format, + int time_domain_assignment, + uint8_t tpc, + int n_ubwp, + int bwp_id) { + const int bw = NRRIV2BW(ubwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + dci_pdu_rel15->frequency_domain_assignment.val = + PRBalloc_to_locationandbandwidth0(pusch_pdu->rb_size, pusch_pdu->rb_start, bw); + dci_pdu_rel15->time_domain_assignment.val = time_domain_assignment; + dci_pdu_rel15->frequency_hopping_flag.val = pusch_pdu->frequency_hopping; + dci_pdu_rel15->mcs = pusch_pdu->mcs_index; + dci_pdu_rel15->ndi = pusch_pdu->pusch_data.new_data_indicator; + dci_pdu_rel15->rv = pusch_pdu->pusch_data.rv_index; + dci_pdu_rel15->harq_pid = pusch_pdu->pusch_data.harq_process_id; + dci_pdu_rel15->tpc = tpc; + AssertFatal(ubwp->bwp_Dedicated->pusch_Config->choice.setup->resourceAllocation == NR_PUSCH_Config__resourceAllocation_resourceAllocationType1, + "Only frequency resource allocation type 1 is currently supported\n"); + switch (dci_format) { case NR_UL_DCI_FORMAT_0_0: - dci_pdu_rel15->frequency_domain_assignment.val = - PRBalloc_to_locationandbandwidth0(pusch_pdu->rb_size, pusch_pdu->rb_start, bw); - - dci_pdu_rel15->time_domain_assignment.val = time_domain_assignment; - dci_pdu_rel15->frequency_hopping_flag.val = pusch_pdu->frequency_hopping; - dci_pdu_rel15->mcs = pusch_pdu->mcs_index; - dci_pdu_rel15->format_indicator = 0; - dci_pdu_rel15->ndi = pusch_pdu->pusch_data.new_data_indicator; - dci_pdu_rel15->rv = pusch_pdu->pusch_data.rv_index; - dci_pdu_rel15->harq_pid = pusch_pdu->pusch_data.harq_process_id; - dci_pdu_rel15->tpc = tpc; break; case NR_UL_DCI_FORMAT_0_1: - dci_pdu_rel15->ndi = pusch_pdu->pusch_data.new_data_indicator; - dci_pdu_rel15->rv = pusch_pdu->pusch_data.rv_index; - dci_pdu_rel15->harq_pid = pusch_pdu->pusch_data.harq_process_id; - dci_pdu_rel15->frequency_hopping_flag.val = pusch_pdu->frequency_hopping; dci_pdu_rel15->dai[0].val = 0; //TODO - // bwp indicator - if (n_ubwp < 4) - dci_pdu_rel15->bwp_indicator.val = bwp_id; - else - dci_pdu_rel15->bwp_indicator.val = bwp_id - 1; // as per table 7.3.1.1.2-1 in 38.212 - // frequency domain assignment - AssertFatal(ubwp->bwp_Dedicated->pusch_Config->choice.setup->resourceAllocation - == NR_PUSCH_Config__resourceAllocation_resourceAllocationType1, - "Only frequency resource allocation type 1 is currently supported\n"); - dci_pdu_rel15->frequency_domain_assignment.val = - PRBalloc_to_locationandbandwidth0(pusch_pdu->rb_size, pusch_pdu->rb_start, bw); - // time domain assignment - dci_pdu_rel15->time_domain_assignment.val = time_domain_assignment; - // mcs - dci_pdu_rel15->mcs = pusch_pdu->mcs_index; - // tpc command for pusch - dci_pdu_rel15->tpc = tpc; + // bwp indicator as per table 7.3.1.1.2-1 in 38.212 + dci_pdu_rel15->bwp_indicator.val = n_ubwp < 4 ? bwp_id : bwp_id - 1; // SRS resource indicator if (ubwp->bwp_Dedicated->pusch_Config->choice.setup->txConfig != NULL) { AssertFatal(*ubwp->bwp_Dedicated->pusch_Config->choice.setup->txConfig == NR_PUSCH_Config__txConfig_codebook, @@ -771,10 +546,8 @@ void config_uldci(NR_BWP_Uplink_t *ubwp, } LOG_D(MAC, - "%s() ULDCI type 0 payload: PDCCH CCEIndex %d, freq_alloc %d, " - "time_alloc %d, freq_hop_flag %d, mcs %d tpc %d ndi %d rv %d\n", + "%s() ULDCI type 0 payload: freq_alloc %d, time_alloc %d, freq_hop_flag %d, mcs %d tpc %d ndi %d rv %d\n", __func__, - pdcch_pdu_rel15->dci_pdu.CceIndex[pdcch_pdu_rel15->numDlDci], dci_pdu_rel15->frequency_domain_assignment.val, dci_pdu_rel15->time_domain_assignment.val, dci_pdu_rel15->frequency_hopping_flag.val, @@ -784,18 +557,15 @@ void config_uldci(NR_BWP_Uplink_t *ubwp, dci_pdu_rel15->rv); } -void nr_configure_pdcch(gNB_MAC_INST *nr_mac, - nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu, - uint16_t rnti, +void nr_configure_pdcch(nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu, NR_SearchSpace_t *ss, NR_ControlResourceSet_t *coreset, NR_ServingCellConfigCommon_t *scc, - NR_BWP_Downlink_t *bwp, - uint8_t aggregation_level, - int CCEIndex) { + NR_BWP_Downlink_t *bwp) +{ if (bwp) { // This is not the InitialBWP - pdcch_pdu->BWPSize = NRRIV2BW(bwp->bwp_Common->genericParameters.locationAndBandwidth,275); - pdcch_pdu->BWPStart = NRRIV2PRBOFFSET(bwp->bwp_Common->genericParameters.locationAndBandwidth,275); + pdcch_pdu->BWPSize = NRRIV2BW(bwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + pdcch_pdu->BWPStart = NRRIV2PRBOFFSET(bwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); pdcch_pdu->SubcarrierSpacing = bwp->bwp_Common->genericParameters.subcarrierSpacing; pdcch_pdu->CyclicPrefix = (bwp->bwp_Common->genericParameters.cyclicPrefix==NULL) ? 0 : *bwp->bwp_Common->genericParameters.cyclicPrefix; @@ -847,27 +617,6 @@ void nr_configure_pdcch(gNB_MAC_INST *nr_mac, //precoderGranularity pdcch_pdu->precoderGranularity = coreset->precoderGranularity; - - pdcch_pdu->dci_pdu.RNTI[pdcch_pdu->numDlDci]=rnti; - - if (coreset->pdcch_DMRS_ScramblingID != NULL && - ss->searchSpaceType->present == NR_SearchSpace__searchSpaceType_PR_ue_Specific) { - pdcch_pdu->dci_pdu.ScramblingId[pdcch_pdu->numDlDci] = *coreset->pdcch_DMRS_ScramblingID; - pdcch_pdu->dci_pdu.ScramblingRNTI[pdcch_pdu->numDlDci]=rnti; - } - else { - pdcch_pdu->dci_pdu.ScramblingId[pdcch_pdu->numDlDci] = *scc->physCellId; - pdcch_pdu->dci_pdu.ScramblingRNTI[pdcch_pdu->numDlDci]=0; - } - - pdcch_pdu->dci_pdu.AggregationLevel[pdcch_pdu->numDlDci] = aggregation_level; - pdcch_pdu->dci_pdu.CceIndex[pdcch_pdu->numDlDci] = CCEIndex; - - if (ss->searchSpaceType->choice.ue_Specific->dci_Formats==NR_SearchSpace__searchSpaceType__ue_Specific__dci_Formats_formats0_0_And_1_0) - pdcch_pdu->dci_pdu.beta_PDCCH_1_0[pdcch_pdu->numDlDci]=0; - - pdcch_pdu->dci_pdu.powerControlOffsetSS[pdcch_pdu->numDlDci]=1; - pdcch_pdu->numDlDci++; } else { // this is for InitialBWP AssertFatal(1==0,"Fill in InitialBWP PDCCH configuration\n"); @@ -936,8 +685,8 @@ void nr_configure_pucch(nfapi_nr_pucch_pdu_t* pucch_pdu, else pucch_pdu->hopping_id = *scc->physCellId; - pucch_pdu->bwp_size = NRRIV2BW(bwp->bwp_Common->genericParameters.locationAndBandwidth,275); - pucch_pdu->bwp_start = NRRIV2PRBOFFSET(bwp->bwp_Common->genericParameters.locationAndBandwidth,275); + pucch_pdu->bwp_size = NRRIV2BW(bwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + pucch_pdu->bwp_start = NRRIV2PRBOFFSET(bwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); pucch_pdu->subcarrier_spacing = bwp->bwp_Common->genericParameters.subcarrierSpacing; pucch_pdu->cyclic_prefix = (bwp->bwp_Common->genericParameters.cyclicPrefix==NULL) ? 0 : *bwp->bwp_Common->genericParameters.cyclicPrefix; @@ -1084,7 +833,7 @@ void nr_configure_pucch(nfapi_nr_pucch_pdu_t* pucch_pdu, } -void prepare_dci(NR_CellGroupConfig_t *secondaryCellGroup, +void prepare_dci(const NR_CellGroupConfig_t *secondaryCellGroup, dci_pdu_rel15_t *dci_pdu_rel15, nr_dci_format_t format, int bwp_id) { @@ -1160,592 +909,506 @@ void prepare_dci(NR_CellGroupConfig_t *secondaryCellGroup, } -void fill_dci_pdu_rel15(NR_ServingCellConfigCommon_t *scc, - NR_CellGroupConfig_t *secondaryCellGroup, - nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15, +void fill_dci_pdu_rel15(const NR_ServingCellConfigCommon_t *scc, + const NR_CellGroupConfig_t *secondaryCellGroup, + nfapi_nr_dl_dci_pdu_t *pdcch_dci_pdu, dci_pdu_rel15_t *dci_pdu_rel15, - int *dci_formats, - int *rnti_types, + int dci_format, + int rnti_type, int N_RB, int bwp_id) { + uint8_t fsize = 0, pos = 0; - uint8_t fsize=0, pos=0; + uint64_t *dci_pdu = (uint64_t *)pdcch_dci_pdu->Payload; + int dci_size = nr_dci_size(scc, secondaryCellGroup, dci_pdu_rel15, dci_format, rnti_type, N_RB, bwp_id); + pdcch_dci_pdu->PayloadSizeBits = dci_size; + AssertFatal(dci_size <= 64, "DCI sizes above 64 bits not yet supported"); - for (int d=0;dnumDlDci;d++) { + if (dci_format == NR_DL_DCI_FORMAT_1_1 || dci_format == NR_UL_DCI_FORMAT_0_1) + prepare_dci(secondaryCellGroup, dci_pdu_rel15, dci_format, bwp_id); - uint64_t *dci_pdu = (uint64_t *)pdcch_pdu_rel15->dci_pdu.Payload[d]; - int dci_size = nr_dci_size(scc,secondaryCellGroup,&dci_pdu_rel15[d],dci_formats[d],rnti_types[d],N_RB,bwp_id); - pdcch_pdu_rel15->dci_pdu.PayloadSizeBits[d] = dci_size; - AssertFatal(pdcch_pdu_rel15->dci_pdu.PayloadSizeBits[d]<=64, "DCI sizes above 64 bits not yet supported"); - - if(dci_formats[d]==NR_DL_DCI_FORMAT_1_1 || dci_formats[d]==NR_UL_DCI_FORMAT_0_1) - prepare_dci(secondaryCellGroup,&dci_pdu_rel15[d],dci_formats[d],bwp_id); - - /// Payload generation - switch(dci_formats[d]) { - case NR_DL_DCI_FORMAT_1_0: - switch(rnti_types[d]) { - case NR_RNTI_RA: - // Freq domain assignment - fsize = (int)ceil( log2( (N_RB*(N_RB+1))>>1 ) ); - pos=fsize; - *dci_pdu |= (((uint64_t)dci_pdu_rel15->frequency_domain_assignment.val&((1< %d (0x%lx)\n",dci_pdu_rel15->frequency_domain_assignment.val,fsize,N_RB,dci_size-pos,*dci_pdu); - // Time domain assignment - pos+=4; - *dci_pdu |= (((uint64_t)dci_pdu_rel15->time_domain_assignment.val&0xf) << (dci_size-pos)); - LOG_D(MAC,"time-domain assignment %d (3 bits)=> %d (0x%lx)\n",dci_pdu_rel15->time_domain_assignment.val,dci_size-pos,*dci_pdu); - // VRB to PRB mapping - - pos++; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->vrb_to_prb_mapping.val&0x1)<<(dci_size-pos); - LOG_D(MAC,"vrb to prb mapping %d (1 bits)=> %d (0x%lx)\n",dci_pdu_rel15->vrb_to_prb_mapping.val,dci_size-pos,*dci_pdu); - // MCS - pos+=5; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->mcs&0x1f)<<(dci_size-pos); + /// Payload generation + switch (dci_format) { + case NR_DL_DCI_FORMAT_1_0: + switch (rnti_type) { + case NR_RNTI_RA: + // Freq domain assignment + fsize = (int)ceil(log2((N_RB * (N_RB + 1)) >> 1)); + pos = fsize; + *dci_pdu |= (((uint64_t)dci_pdu_rel15->frequency_domain_assignment.val & ((1 << fsize) - 1)) << (dci_size - pos)); + LOG_D(MAC, + "frequency-domain assignment %d (%d bits) N_RB_BWP %d=> %d (0x%lx)\n", + dci_pdu_rel15->frequency_domain_assignment.val, + fsize, + N_RB, + dci_size - pos, + *dci_pdu); + // Time domain assignment + pos += 4; + *dci_pdu |= (((uint64_t)dci_pdu_rel15->time_domain_assignment.val & 0xf) << (dci_size - pos)); + LOG_D(MAC, + "time-domain assignment %d (3 bits)=> %d (0x%lx)\n", + dci_pdu_rel15->time_domain_assignment.val, + dci_size - pos, + *dci_pdu); + // VRB to PRB mapping + pos++; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->vrb_to_prb_mapping.val & 0x1) << (dci_size - pos); + LOG_D(MAC, + "vrb to prb mapping %d (1 bits)=> %d (0x%lx)\n", + dci_pdu_rel15->vrb_to_prb_mapping.val, + dci_size - pos, + *dci_pdu); + // MCS + pos += 5; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->mcs & 0x1f) << (dci_size - pos); #ifdef DEBUG_FILL_DCI - LOG_I(MAC,"mcs %d (5 bits)=> %d (0x%lx)\n",dci_pdu_rel15->mcs,dci_size-pos,*dci_pdu); + LOG_I(MAC, "mcs %d (5 bits)=> %d (0x%lx)\n", dci_pdu_rel15->mcs, dci_size - pos, *dci_pdu); #endif - // TB scaling - pos+=2; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->tb_scaling&0x3)<<(dci_size-pos); + // TB scaling + pos += 2; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->tb_scaling & 0x3) << (dci_size - pos); #ifdef DEBUG_FILL_DCI - LOG_I(MAC,"tb_scaling %d (2 bits)=> %d (0x%lx)\n",dci_pdu_rel15->tb_scaling,dci_size-pos,*dci_pdu); + LOG_I(MAC, "tb_scaling %d (2 bits)=> %d (0x%lx)\n", dci_pdu_rel15->tb_scaling, dci_size - pos, *dci_pdu); #endif - break; - - case NR_RNTI_C: - - // indicating a DL DCI format 1bit - pos++; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->format_indicator&1)<<(dci_size-pos); - LOG_D(MAC,"Format indicator %d (%d bits) N_RB_BWP %d => %d (0x%lx)\n",dci_pdu_rel15->format_indicator,1,N_RB,dci_size-pos,*dci_pdu); - - // Freq domain assignment (275rb >> fsize = 16) - fsize = (int)ceil( log2( (N_RB*(N_RB+1))>>1 ) ); - pos+=fsize; - *dci_pdu |= (((uint64_t)dci_pdu_rel15->frequency_domain_assignment.val&((1< %d (0x%lx)\n",dci_pdu_rel15->frequency_domain_assignment.val,fsize,dci_size-pos,*dci_pdu); - - uint16_t is_ra = 1; - for (int i=0; ifrequency_domain_assignment.val>>i)&1)) { - is_ra = 0; - break; - } - if (is_ra) //fsize are all 1 38.212 p86 - { - // ra_preamble_index 6 bits - pos+=6; - *dci_pdu |= ((dci_pdu_rel15->ra_preamble_index&0x3f)<<(dci_size-pos)); - - // UL/SUL indicator 1 bit - pos++; - *dci_pdu |= (dci_pdu_rel15->ul_sul_indicator.val&1)<<(dci_size-pos); - - // SS/PBCH index 6 bits - pos+=6; - *dci_pdu |= ((dci_pdu_rel15->ss_pbch_index&0x3f)<<(dci_size-pos)); - - // prach_mask_index 4 bits - pos+=4; - *dci_pdu |= ((dci_pdu_rel15->prach_mask_index&0xf)<<(dci_size-pos)); - - } //end if - - else { - - // Time domain assignment 4bit - - pos+=4; - *dci_pdu |= ((dci_pdu_rel15->time_domain_assignment.val&0xf) << (dci_size-pos)); - LOG_D(MAC,"Time domain assignment %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->time_domain_assignment.val,4,dci_size-pos,*dci_pdu); - - // VRB to PRB mapping 1bit - pos++; - *dci_pdu |= (dci_pdu_rel15->vrb_to_prb_mapping.val&1)<<(dci_size-pos); - LOG_D(MAC,"VRB to PRB %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->vrb_to_prb_mapping.val,1,dci_size-pos,*dci_pdu); - - // MCS 5bit //bit over 32, so dci_pdu ++ - pos+=5; - *dci_pdu |= (dci_pdu_rel15->mcs&0x1f)<<(dci_size-pos); - LOG_D(MAC,"MCS %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->mcs,5,dci_size-pos,*dci_pdu); - - // New data indicator 1bit - pos++; - *dci_pdu |= (dci_pdu_rel15->ndi&1)<<(dci_size-pos); - LOG_D(MAC,"NDI %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->ndi,1,dci_size-pos,*dci_pdu); - - // Redundancy version 2bit - pos+=2; - *dci_pdu |= (dci_pdu_rel15->rv&0x3)<<(dci_size-pos); - LOG_D(MAC,"RV %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->rv,2,dci_size-pos,*dci_pdu); - - // HARQ process number 4bit - pos+=4; - *dci_pdu |= ((dci_pdu_rel15->harq_pid&0xf)<<(dci_size-pos)); - LOG_D(MAC,"HARQ_PID %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->harq_pid,4,dci_size-pos,*dci_pdu); - - // Downlink assignment index 2bit - pos+=2; - *dci_pdu |= ((dci_pdu_rel15->dai[0].val&3)<<(dci_size-pos)); - LOG_D(MAC,"DAI %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->dai[0].val,2,dci_size-pos,*dci_pdu); - - // TPC command for scheduled PUCCH 2bit - pos+=2; - *dci_pdu |= ((dci_pdu_rel15->tpc&3)<<(dci_size-pos)); - LOG_D(MAC,"TPC %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->tpc,2,dci_size-pos,*dci_pdu); - - // PUCCH resource indicator 3bit - pos+=3; - *dci_pdu |= ((dci_pdu_rel15->pucch_resource_indicator&0x7)<<(dci_size-pos)); - LOG_D(MAC,"PUCCH RI %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->pucch_resource_indicator,3,dci_size-pos,*dci_pdu); - - // PDSCH-to-HARQ_feedback timing indicator 3bit - pos+=3; - *dci_pdu |= ((dci_pdu_rel15->pdsch_to_harq_feedback_timing_indicator.val&0x7)<<(dci_size-pos)); - LOG_D(MAC,"PDSCH to HARQ TI %d (%d bits)=> %d (0x%lx)\n",dci_pdu_rel15->pdsch_to_harq_feedback_timing_indicator.val,3,dci_size-pos,*dci_pdu); - - } //end else - break; - - case NR_RNTI_P: - - // Short Messages Indicator – 2 bits - for (int i=0; i<2; i++) - *dci_pdu |= (((uint64_t)dci_pdu_rel15->short_messages_indicator>>(1-i))&1)<<(dci_size-pos++); - // Short Messages – 8 bits - for (int i=0; i<8; i++) - *dci_pdu |= (((uint64_t)dci_pdu_rel15->short_messages>>(7-i))&1)<<(dci_size-pos++); - // Freq domain assignment 0-16 bit - fsize = (int)ceil( log2( (N_RB*(N_RB+1))>>1 ) ); - for (int i=0; ifrequency_domain_assignment.val>>(fsize-i-1))&1)<<(dci_size-pos++); - // Time domain assignment 4 bit - for (int i=0; i<4; i++) - *dci_pdu |= (((uint64_t)dci_pdu_rel15->time_domain_assignment.val>>(3-i))&1)<<(dci_size-pos++); - // VRB to PRB mapping 1 bit - *dci_pdu |= ((uint64_t)dci_pdu_rel15->vrb_to_prb_mapping.val&1)<<(dci_size-pos++); - // MCS 5 bit - for (int i=0; i<5; i++) - *dci_pdu |= (((uint64_t)dci_pdu_rel15->mcs>>(4-i))&1)<<(dci_size-pos++); - - // TB scaling 2 bit - for (int i=0; i<2; i++) - *dci_pdu |= (((uint64_t)dci_pdu_rel15->tb_scaling>>(1-i))&1)<<(dci_size-pos++); - - - break; - - case NR_RNTI_SI: - pos=1; + break; - // Freq domain assignment 0-16 bit - fsize = (int)ceil( log2( (N_RB*(N_RB+1))>>1 ) ); - for (int i=0; ifrequency_domain_assignment.val>>(fsize-1-i))&1)<<(dci_size-pos++); - - // Time domain assignment 4 bit - for (int i=0; i<4; i++) - *dci_pdu |= (((uint64_t)dci_pdu_rel15->time_domain_assignment.val>>(3-i))&1)<<(dci_size-pos++); - - // VRB to PRB mapping 1 bit - *dci_pdu |= ((uint64_t)dci_pdu_rel15->vrb_to_prb_mapping.val&1)<<(dci_size-pos++); - - // MCS 5bit //bit over 32, so dci_pdu ++ - for (int i=0; i<5; i++) - *dci_pdu |= (((uint64_t)dci_pdu_rel15->mcs>>(4-i))&1)<<(dci_size-pos++); - - // Redundancy version 2 bit - for (int i=0; i<2; i++) - *dci_pdu |= (((uint64_t)dci_pdu_rel15->rv>>(1-i))&1)<<(dci_size-pos++); - - // System information indicator 1bit - *dci_pdu |= ((uint64_t)dci_pdu_rel15->system_info_indicator&1)<<(dci_size-pos++); - - // reserved 15 bits - - LOG_D(PHY,"dci_size = %i\n", dci_size); - LOG_D(PHY,"fsize = %i\n", fsize); - LOG_D(PHY,"dci_pdu_rel15->frequency_domain_assignment.val = %i\n", dci_pdu_rel15->frequency_domain_assignment.val); - LOG_D(PHY,"dci_pdu_rel15->time_domain_assignment.val = %i\n", dci_pdu_rel15->time_domain_assignment.val); - LOG_D(PHY,"dci_pdu_rel15->vrb_to_prb_mapping.val = %i\n", dci_pdu_rel15->vrb_to_prb_mapping.val); - LOG_D(PHY,"dci_pdu_rel15->mcs = %i\n", dci_pdu_rel15->mcs); - LOG_D(PHY,"dci_pdu_rel15->rv = %i\n", dci_pdu_rel15->rv); - LOG_D(PHY,"dci_pdu_rel15->system_info_indicator = %i\n", dci_pdu_rel15->system_info_indicator); - - break; - - case NR_RNTI_TC: - // indicating a DL DCI format 1bit - *dci_pdu |= ((uint64_t)dci_pdu_rel15->format_indicator&1)<<(dci_size-pos++); - // Freq domain assignment 0-16 bit - fsize = (int)ceil( log2( (N_RB*(N_RB+1))>>1 ) ); - for (int i=0; ifrequency_domain_assignment.val>>(fsize-i-1))&1)<<(dci_size-pos++); - // Time domain assignment 4 bit - for (int i=0; i<4; i++) - *dci_pdu |= (((uint64_t)dci_pdu_rel15->time_domain_assignment.val>>(3-i))&1)<<(dci_size-pos++); - // VRB to PRB mapping 1 bit - *dci_pdu |= ((uint64_t)dci_pdu_rel15->vrb_to_prb_mapping.val&1)<<(dci_size-pos++); - // MCS 5bit //bit over 32, so dci_pdu ++ - for (int i=0; i<5; i++) - *dci_pdu |= (((uint64_t)dci_pdu_rel15->mcs>>(4-i))&1)<<(dci_size-pos++); - // New data indicator 1bit - *dci_pdu |= ((uint64_t)dci_pdu_rel15->ndi&1)<<(dci_size-pos++); - // Redundancy version 2bit - for (int i=0; i<2; i++) - *dci_pdu |= (((uint64_t)dci_pdu_rel15->rv>>(1-i))&1)<<(dci_size-pos++); - // HARQ process number 4bit - for (int i=0; i<4; i++) - *dci_pdu |= (((uint64_t)dci_pdu_rel15->harq_pid>>(3-i))&1)<<(dci_size-pos++); - - // Downlink assignment index – 2 bits - for (int i=0; i<2; i++) - *dci_pdu |= (((uint64_t)dci_pdu_rel15->dai[0].val>>(1-i))&1)<<(dci_size-pos++); - - // TPC command for scheduled PUCCH – 2 bits - for (int i=0; i<2; i++) - *dci_pdu |= (((uint64_t)dci_pdu_rel15->tpc>>(1-i))&1)<<(dci_size-pos++); - - - // LOG_D(MAC, "DCI PDU: [0]->0x%08llx \t [1]->0x%08llx \t [2]->0x%08llx \t [3]->0x%08llx\n", - // dci_pdu[0], dci_pdu[1], dci_pdu[2], dci_pdu[3]); - - - // PDSCH-to-HARQ_feedback timing indicator – 3 bits - for (int i=0; i<3; i++) - *dci_pdu |= (((uint64_t)dci_pdu_rel15->pdsch_to_harq_feedback_timing_indicator.val>>(2-i))&1)<<(dci_size-pos++); - - break; + case NR_RNTI_C: + // indicating a DL DCI format 1bit + pos++; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->format_indicator & 1) << (dci_size - pos); + LOG_D(MAC, + "Format indicator %d (%d bits) N_RB_BWP %d => %d (0x%lx)\n", + dci_pdu_rel15->format_indicator, + 1, + N_RB, + dci_size - pos, + *dci_pdu); + // Freq domain assignment (275rb >> fsize = 16) + fsize = (int)ceil(log2((N_RB * (N_RB + 1)) >> 1)); + pos += fsize; + *dci_pdu |= (((uint64_t)dci_pdu_rel15->frequency_domain_assignment.val & ((1 << fsize) - 1)) << (dci_size - pos)); + LOG_D(MAC, + "Freq domain assignment %d (%d bits)=> %d (0x%lx)\n", + dci_pdu_rel15->frequency_domain_assignment.val, + fsize, + dci_size - pos, + *dci_pdu); + uint16_t is_ra = 1; + for (int i = 0; i < fsize; i++) { + if (!((dci_pdu_rel15->frequency_domain_assignment.val >> i) & 1)) { + is_ra = 0; + break; + } } - break; - - case NR_UL_DCI_FORMAT_0_0: - switch(rnti_types[d]) - { - case NR_RNTI_C: - // indicating a DL DCI format 1bit - *dci_pdu |= ((uint64_t)dci_pdu_rel15->format_indicator&1)<<(dci_size-pos++); - // Freq domain assignment max 16 bit - fsize = (int)ceil( log2( (N_RB*(N_RB+1))>>1 ) ); - for (int i=0; ifrequency_domain_assignment.val>>(fsize-i-1))&1)<<(dci_size-pos++); - // Time domain assignment 4bit - for (int i=0; i<4; i++) - *dci_pdu |= (((uint64_t)dci_pdu_rel15->time_domain_assignment.val>>(3-i))&1)<<(dci_size-pos++); - // Frequency hopping flag – 1 bit - *dci_pdu |= ((uint64_t)dci_pdu_rel15->frequency_hopping_flag.val&1)<<(dci_size-pos++); - // MCS 5 bit - for (int i=0; i<5; i++) - *dci_pdu |= (((uint64_t)dci_pdu_rel15->mcs>>(4-i))&1)<<(dci_size-pos++); - // New data indicator 1bit - *dci_pdu |= ((uint64_t)dci_pdu_rel15->ndi&1)<<(dci_size-pos++); - // Redundancy version 2bit - for (int i=0; i<2; i++) - *dci_pdu |= (((uint64_t)dci_pdu_rel15->rv>>(1-i))&1)<<(dci_size-pos++); - // HARQ process number 4bit - for (int i=0; i<4; i++) - *dci_pdu |= (((uint64_t)dci_pdu_rel15->harq_pid>>(3-i))&1)<<(dci_size-pos++); - - // TPC command for scheduled PUSCH – 2 bits - for (int i=0; i<2; i++) - *dci_pdu |= (((uint64_t)dci_pdu_rel15->tpc>>(1-i))&1)<<(dci_size-pos++); - - // Padding bits - for(int a = pos;a<32;a++) - *dci_pdu |= ((uint64_t)dci_pdu_rel15->padding&1)<<(dci_size-pos++); - - // UL/SUL indicator – 1 bit - /* commented for now (RK): need to get this from BWP descriptor - if (cfg->pucch_config.pucch_GroupHopping.value) - *dci_pdu |= ((uint64_t)dci_pdu_rel15->ul_sul_indicator.val&1)<<(dci_size-pos++); - */ - break; - - case NFAPI_NR_RNTI_TC: - - // indicating a DL DCI format 1bit - *dci_pdu |= (dci_pdu_rel15->format_indicator&1)<<(dci_size-pos++); - // Freq domain assignment max 16 bit - fsize = (int)ceil( log2( (N_RB*(N_RB+1))>>1 ) ); - for (int i=0; ifrequency_domain_assignment.val>>(fsize-i-1))&1)<<(dci_size-pos++); - // Time domain assignment 4bit - for (int i=0; i<4; i++) - *dci_pdu |= (((uint64_t)dci_pdu_rel15->time_domain_assignment.val>>(3-i))&1)<<(dci_size-pos++); - // Frequency hopping flag – 1 bit - *dci_pdu |= ((uint64_t)dci_pdu_rel15->frequency_hopping_flag.val&1)<<(dci_size-pos++); - // MCS 5 bit - for (int i=0; i<5; i++) - *dci_pdu |= (((uint64_t)dci_pdu_rel15->mcs>>(4-i))&1)<<(dci_size-pos++); - // New data indicator 1bit - *dci_pdu |= ((uint64_t)dci_pdu_rel15->ndi&1)<<(dci_size-pos++); - // Redundancy version 2bit - for (int i=0; i<2; i++) - *dci_pdu |= (((uint64_t)dci_pdu_rel15->rv>>(1-i))&1)<<(dci_size-pos++); - // HARQ process number 4bit - for (int i=0; i<4; i++) - *dci_pdu |= (((uint64_t)dci_pdu_rel15->harq_pid>>(3-i))&1)<<(dci_size-pos++); - - // TPC command for scheduled PUSCH – 2 bits - for (int i=0; i<2; i++) - *dci_pdu |= (((uint64_t)dci_pdu_rel15->tpc>>(1-i))&1)<<(dci_size-pos++); - - // Padding bits - for(int a = pos;a<32;a++) - *dci_pdu |= ((uint64_t)dci_pdu_rel15->padding&1)<<(dci_size-pos++); - - // UL/SUL indicator – 1 bit - /* - commented for now (RK): need to get this information from BWP descriptor - if (cfg->pucch_config.pucch_GroupHopping.value) - *dci_pdu |= ((uint64_t)dci_pdu_rel15->ul_sul_indicator.val&1)<<(dci_size-pos++); - */ - break; - - } + if (is_ra) { // fsize are all 1 38.212 p86 + // ra_preamble_index 6 bits + pos += 6; + *dci_pdu |= ((dci_pdu_rel15->ra_preamble_index & 0x3f) << (dci_size - pos)); + // UL/SUL indicator 1 bit + pos++; + *dci_pdu |= (dci_pdu_rel15->ul_sul_indicator.val & 1) << (dci_size - pos); + // SS/PBCH index 6 bits + pos += 6; + *dci_pdu |= ((dci_pdu_rel15->ss_pbch_index & 0x3f) << (dci_size - pos)); + // prach_mask_index 4 bits + pos += 4; + *dci_pdu |= ((dci_pdu_rel15->prach_mask_index & 0xf) << (dci_size - pos)); + } else { + // Time domain assignment 4bit + pos += 4; + *dci_pdu |= ((dci_pdu_rel15->time_domain_assignment.val & 0xf) << (dci_size - pos)); + LOG_D(MAC, + "Time domain assignment %d (%d bits)=> %d (0x%lx)\n", + dci_pdu_rel15->time_domain_assignment.val, + 4, + dci_size - pos, + *dci_pdu); + // VRB to PRB mapping 1bit + pos++; + *dci_pdu |= (dci_pdu_rel15->vrb_to_prb_mapping.val & 1) << (dci_size - pos); + LOG_D(MAC, + "VRB to PRB %d (%d bits)=> %d (0x%lx)\n", + dci_pdu_rel15->vrb_to_prb_mapping.val, + 1, + dci_size - pos, + *dci_pdu); + // MCS 5bit //bit over 32, so dci_pdu ++ + pos += 5; + *dci_pdu |= (dci_pdu_rel15->mcs & 0x1f) << (dci_size - pos); + LOG_D(MAC, "MCS %d (%d bits)=> %d (0x%lx)\n", dci_pdu_rel15->mcs, 5, dci_size - pos, *dci_pdu); + // New data indicator 1bit + pos++; + *dci_pdu |= (dci_pdu_rel15->ndi & 1) << (dci_size - pos); + LOG_D(MAC, "NDI %d (%d bits)=> %d (0x%lx)\n", dci_pdu_rel15->ndi, 1, dci_size - pos, *dci_pdu); + // Redundancy version 2bit + pos += 2; + *dci_pdu |= (dci_pdu_rel15->rv & 0x3) << (dci_size - pos); + LOG_D(MAC, "RV %d (%d bits)=> %d (0x%lx)\n", dci_pdu_rel15->rv, 2, dci_size - pos, *dci_pdu); + // HARQ process number 4bit + pos += 4; + *dci_pdu |= ((dci_pdu_rel15->harq_pid & 0xf) << (dci_size - pos)); + LOG_D(MAC, "HARQ_PID %d (%d bits)=> %d (0x%lx)\n", dci_pdu_rel15->harq_pid, 4, dci_size - pos, *dci_pdu); + // Downlink assignment index 2bit + pos += 2; + *dci_pdu |= ((dci_pdu_rel15->dai[0].val & 3) << (dci_size - pos)); + LOG_D(MAC, "DAI %d (%d bits)=> %d (0x%lx)\n", dci_pdu_rel15->dai[0].val, 2, dci_size - pos, *dci_pdu); + // TPC command for scheduled PUCCH 2bit + pos += 2; + *dci_pdu |= ((dci_pdu_rel15->tpc & 3) << (dci_size - pos)); + LOG_D(MAC, "TPC %d (%d bits)=> %d (0x%lx)\n", dci_pdu_rel15->tpc, 2, dci_size - pos, *dci_pdu); + // PUCCH resource indicator 3bit + pos += 3; + *dci_pdu |= ((dci_pdu_rel15->pucch_resource_indicator & 0x7) << (dci_size - pos)); + LOG_D(MAC, + "PUCCH RI %d (%d bits)=> %d (0x%lx)\n", + dci_pdu_rel15->pucch_resource_indicator, + 3, + dci_size - pos, + *dci_pdu); + // PDSCH-to-HARQ_feedback timing indicator 3bit + pos += 3; + *dci_pdu |= ((dci_pdu_rel15->pdsch_to_harq_feedback_timing_indicator.val & 0x7) << (dci_size - pos)); + LOG_D(MAC, + "PDSCH to HARQ TI %d (%d bits)=> %d (0x%lx)\n", + dci_pdu_rel15->pdsch_to_harq_feedback_timing_indicator.val, + 3, + dci_size - pos, + *dci_pdu); + } // end else break; - case NR_UL_DCI_FORMAT_0_1: - switch(rnti_types[d]) - { - case NR_RNTI_C: - // Indicating a DL DCI format 1bit - pos=1; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->format_indicator&0x1)<<(dci_size-pos); - - // Carrier indicator - pos+=dci_pdu_rel15->carrier_indicator.nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->carrier_indicator.val&((1<carrier_indicator.nbits)-1))<<(dci_size-pos); - - // UL/SUL Indicator - pos+=dci_pdu_rel15->ul_sul_indicator.nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->ul_sul_indicator.val&((1<ul_sul_indicator.nbits)-1))<<(dci_size-pos); - - // BWP indicator - pos+=dci_pdu_rel15->bwp_indicator.nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->bwp_indicator.val&((1<bwp_indicator.nbits)-1))<<(dci_size-pos); - - // Frequency domain resource assignment - pos+=dci_pdu_rel15->frequency_domain_assignment.nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->frequency_domain_assignment.val&((1<frequency_domain_assignment.nbits)-1)) << (dci_size-pos); - - // Time domain resource assignment - pos+=dci_pdu_rel15->time_domain_assignment.nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->time_domain_assignment.val&((1<time_domain_assignment.nbits)-1)) << (dci_size-pos); - - // Frequency hopping - pos+=dci_pdu_rel15->frequency_hopping_flag.nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->frequency_hopping_flag.val&((1<frequency_hopping_flag.nbits)-1)) << (dci_size-pos); - - // MCS 5bit - pos+=5; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->mcs&0x1f)<<(dci_size-pos); - - // New data indicator 1bit - pos+=1; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->ndi&0x1)<<(dci_size-pos); - - // Redundancy version 2bit - pos+=2; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->rv&0x3)<<(dci_size-pos); - - // HARQ process number 4bit - pos+=4; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->harq_pid&0xf)<<(dci_size-pos); - - // 1st Downlink assignment index - pos+=dci_pdu_rel15->dai[0].nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->dai[0].val&((1<dai[0].nbits)-1))<<(dci_size-pos); - - // 2nd Downlink assignment index - pos+=dci_pdu_rel15->dai[1].nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->dai[1].val&((1<dai[1].nbits)-1))<<(dci_size-pos); - - // TPC command for scheduled PUSCH 2bit - pos+=2; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->tpc&0x3)<<(dci_size-pos); - - // SRS resource indicator - pos+=dci_pdu_rel15->srs_resource_indicator.nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->srs_resource_indicator.val&((1<srs_resource_indicator.nbits)-1))<<(dci_size-pos); - - // Precoding info and n. of layers - pos+=dci_pdu_rel15->precoding_information.nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->precoding_information.val&((1<precoding_information.nbits)-1))<<(dci_size-pos); - - // Antenna ports - pos+=dci_pdu_rel15->antenna_ports.nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->antenna_ports.val&((1<antenna_ports.nbits)-1))<<(dci_size-pos); - - // SRS request - pos+=dci_pdu_rel15->srs_request.nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->srs_request.val&((1<srs_request.nbits)-1))<<(dci_size-pos); - - // CSI request - pos+=dci_pdu_rel15->csi_request.nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->csi_request.val&((1<csi_request.nbits)-1))<<(dci_size-pos); - - // CBG transmission information - pos+=dci_pdu_rel15->cbgti.nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->cbgti.val&((1<cbgti.nbits)-1))<<(dci_size-pos); - - // PTRS DMRS association - pos+=dci_pdu_rel15->ptrs_dmrs_association.nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->ptrs_dmrs_association.val&((1<ptrs_dmrs_association.nbits)-1))<<(dci_size-pos); - - // Beta offset indicator - pos+=dci_pdu_rel15->beta_offset_indicator.nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->beta_offset_indicator.val&((1<beta_offset_indicator.nbits)-1))<<(dci_size-pos); - - // DMRS sequence initialization - pos+=dci_pdu_rel15->dmrs_sequence_initialization.nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->dmrs_sequence_initialization.val&((1<dmrs_sequence_initialization.nbits)-1))<<(dci_size-pos); - - // UL-SCH indicator - pos+=1; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->ulsch_indicator&0x1)<<(dci_size-pos); - - break; - } + case NR_RNTI_P: + // Short Messages Indicator – 2 bits + for (int i = 0; i < 2; i++) + *dci_pdu |= (((uint64_t)dci_pdu_rel15->short_messages_indicator >> (1 - i)) & 1) << (dci_size - pos++); + // Short Messages – 8 bits + for (int i = 0; i < 8; i++) + *dci_pdu |= (((uint64_t)dci_pdu_rel15->short_messages >> (7 - i)) & 1) << (dci_size - pos++); + // Freq domain assignment 0-16 bit + fsize = (int)ceil(log2((N_RB * (N_RB + 1)) >> 1)); + for (int i = 0; i < fsize; i++) + *dci_pdu |= (((uint64_t)dci_pdu_rel15->frequency_domain_assignment.val >> (fsize - i - 1)) & 1) << (dci_size - pos++); + // Time domain assignment 4 bit + for (int i = 0; i < 4; i++) + *dci_pdu |= (((uint64_t)dci_pdu_rel15->time_domain_assignment.val >> (3 - i)) & 1) << (dci_size - pos++); + // VRB to PRB mapping 1 bit + *dci_pdu |= ((uint64_t)dci_pdu_rel15->vrb_to_prb_mapping.val & 1) << (dci_size - pos++); + // MCS 5 bit + for (int i = 0; i < 5; i++) + *dci_pdu |= (((uint64_t)dci_pdu_rel15->mcs >> (4 - i)) & 1) << (dci_size - pos++); + // TB scaling 2 bit + for (int i = 0; i < 2; i++) + *dci_pdu |= (((uint64_t)dci_pdu_rel15->tb_scaling >> (1 - i)) & 1) << (dci_size - pos++); break; - case NR_DL_DCI_FORMAT_1_1: - // Indicating a DL DCI format 1bit - pos=1; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->format_indicator&0x1)<<(dci_size-pos); - - // Carrier indicator - pos+=dci_pdu_rel15->carrier_indicator.nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->carrier_indicator.val&((1<carrier_indicator.nbits)-1))<<(dci_size-pos); - - // BWP indicator - pos+=dci_pdu_rel15->bwp_indicator.nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->bwp_indicator.val&((1<bwp_indicator.nbits)-1))<<(dci_size-pos); - - // Frequency domain resource assignment - pos+=dci_pdu_rel15->frequency_domain_assignment.nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->frequency_domain_assignment.val&((1<frequency_domain_assignment.nbits)-1)) << (dci_size-pos); - - // Time domain resource assignment - pos+=dci_pdu_rel15->time_domain_assignment.nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->time_domain_assignment.val&((1<time_domain_assignment.nbits)-1)) << (dci_size-pos); - - // VRB-to-PRB mapping - pos+=dci_pdu_rel15->vrb_to_prb_mapping.nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->vrb_to_prb_mapping.val&((1<vrb_to_prb_mapping.nbits)-1))<<(dci_size-pos); - - // PRB bundling size indicator - pos+=dci_pdu_rel15->prb_bundling_size_indicator.nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->prb_bundling_size_indicator.val&((1<prb_bundling_size_indicator.nbits)-1))<<(dci_size-pos); - - // Rate matching indicator - pos+=dci_pdu_rel15->rate_matching_indicator.nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->rate_matching_indicator.val&((1<rate_matching_indicator.nbits)-1))<<(dci_size-pos); - - // ZP CSI-RS trigger - pos+=dci_pdu_rel15->zp_csi_rs_trigger.nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->zp_csi_rs_trigger.val&((1<zp_csi_rs_trigger.nbits)-1)) << (dci_size-pos); - - //TB1 - // MCS 5bit - pos+=5; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->mcs&0x1f)<<(dci_size-pos); - - // New data indicator 1bit - pos+=1; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->ndi&0x1)<<(dci_size-pos); - + case NR_RNTI_SI: + pos = 1; + // Freq domain assignment 0-16 bit + fsize = (int)ceil(log2((N_RB * (N_RB + 1)) >> 1)); + LOG_D(PHY, "fsize = %i\n", fsize); + for (int i = 0; i < fsize; i++) + *dci_pdu |= (((uint64_t)dci_pdu_rel15->frequency_domain_assignment.val >> (fsize - i - 1)) & 1) << (dci_size - pos++); + LOG_D(PHY, "dci_pdu_rel15->frequency_domain_assignment.val = %i\n", dci_pdu_rel15->frequency_domain_assignment.val); + // Time domain assignment 4 bit + for (int i = 0; i < 4; i++) + *dci_pdu |= (((uint64_t)dci_pdu_rel15->time_domain_assignment.val >> (3 - i)) & 1) << (dci_size - pos++); + LOG_D(PHY, "dci_pdu_rel15->time_domain_assignment.val = %i\n", dci_pdu_rel15->time_domain_assignment.val); + // VRB to PRB mapping 1 bit + *dci_pdu |= ((uint64_t)dci_pdu_rel15->vrb_to_prb_mapping.val & 1) << (dci_size - pos++); + LOG_D(PHY, "dci_pdu_rel15->vrb_to_prb_mapping.val = %i\n", dci_pdu_rel15->vrb_to_prb_mapping.val); + // MCS 5bit //bit over 32, so dci_pdu ++ + for (int i = 0; i < 5; i++) + *dci_pdu |= (((uint64_t)dci_pdu_rel15->mcs >> (4 - i)) & 1) << (dci_size - pos++); + LOG_D(PHY, "dci_pdu_rel15->mcs = %i\n", dci_pdu_rel15->mcs); // Redundancy version 2bit - pos+=2; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->rv&0x3)<<(dci_size-pos); + for (int i = 0; i < 2; i++) + *dci_pdu |= (((uint64_t)dci_pdu_rel15->rv >> (1 - i)) & 1) << (dci_size - pos++); + LOG_D(PHY, "dci_pdu_rel15->rv = %i\n", dci_pdu_rel15->rv); + // System information indicator 1bit + *dci_pdu |= ((uint64_t)dci_pdu_rel15->system_info_indicator&1)<<(dci_size-pos++); + LOG_D(PHY, "dci_pdu_rel15->system_info_indicator = %i\n", dci_pdu_rel15->system_info_indicator); + break; - //TB2 - // MCS 5bit - pos+=dci_pdu_rel15->mcs2.nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->mcs2.val&((1<mcs2.nbits)-1))<<(dci_size-pos); - + case NR_RNTI_TC: + // indicating a DL DCI format 1bit + *dci_pdu |= ((uint64_t)dci_pdu_rel15->format_indicator & 1) << (dci_size - pos++); + // Freq domain assignment 0-16 bit + fsize = (int)ceil(log2((N_RB * (N_RB + 1)) >> 1)); + for (int i = 0; i < fsize; i++) + *dci_pdu |= (((uint64_t)dci_pdu_rel15->frequency_domain_assignment.val >> (fsize - i - 1)) & 1) << (dci_size - pos++); + // Time domain assignment 4 bit + for (int i = 0; i < 4; i++) + *dci_pdu |= (((uint64_t)dci_pdu_rel15->time_domain_assignment.val >> (3 - i)) & 1) << (dci_size - pos++); + // VRB to PRB mapping 1 bit + *dci_pdu |= ((uint64_t)dci_pdu_rel15->vrb_to_prb_mapping.val & 1) << (dci_size - pos++); + // MCS 5bit //bit over 32, so dci_pdu ++ + for (int i = 0; i < 5; i++) + *dci_pdu |= (((uint64_t)dci_pdu_rel15->mcs >> (4 - i)) & 1) << (dci_size - pos++); // New data indicator 1bit - pos+=dci_pdu_rel15->ndi2.nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->ndi2.val&((1<ndi2.nbits)-1))<<(dci_size-pos); - + *dci_pdu |= ((uint64_t)dci_pdu_rel15->ndi & 1) << (dci_size - pos++); // Redundancy version 2bit - pos+=dci_pdu_rel15->rv2.nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->rv2.val&((1<rv2.nbits)-1))<<(dci_size-pos); - + for (int i = 0; i < 2; i++) + *dci_pdu |= (((uint64_t)dci_pdu_rel15->rv >> (1 - i)) & 1) << (dci_size - pos++); // HARQ process number 4bit - pos+=4; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->harq_pid&0xf)<<(dci_size-pos); - - // Downlink assignment index - pos+=dci_pdu_rel15->dai[0].nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->dai[0].val&((1<dai[0].nbits)-1))<<(dci_size-pos); - - // TPC command for scheduled PUCCH 2bit - pos+=2; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->tpc&0x3)<<(dci_size-pos); - - // PUCCH resource indicator 3bit - pos+=3; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->pucch_resource_indicator&0x7)<<(dci_size-pos); - - // PDSCH-to-HARQ_feedback timing indicator - pos+=dci_pdu_rel15->pdsch_to_harq_feedback_timing_indicator.nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->pdsch_to_harq_feedback_timing_indicator.val&((1<pdsch_to_harq_feedback_timing_indicator.nbits)-1))<<(dci_size-pos); - - // Antenna ports - pos+=dci_pdu_rel15->antenna_ports.nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->antenna_ports.val&((1<antenna_ports.nbits)-1))<<(dci_size-pos); - - // TCI - pos+=dci_pdu_rel15->transmission_configuration_indication.nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->transmission_configuration_indication.val&((1<transmission_configuration_indication.nbits)-1))<<(dci_size-pos); - - // SRS request - pos+=dci_pdu_rel15->srs_request.nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->srs_request.val&((1<srs_request.nbits)-1))<<(dci_size-pos); - - // CBG transmission information - pos+=dci_pdu_rel15->cbgti.nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->cbgti.val&((1<cbgti.nbits)-1))<<(dci_size-pos); - - // CBG flushing out information - pos+=dci_pdu_rel15->cbgfi.nbits; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->cbgfi.val&((1<cbgfi.nbits)-1))<<(dci_size-pos); - - // DMRS sequence init - pos+=1; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->dmrs_sequence_initialization.val&0x1)<<(dci_size-pos); + for (int i = 0; i < 4; i++) + *dci_pdu |= (((uint64_t)dci_pdu_rel15->harq_pid >> (3 - i)) & 1) << (dci_size - pos++); + // Downlink assignment index – 2 bits + for (int i = 0; i < 2; i++) + *dci_pdu |= (((uint64_t)dci_pdu_rel15->dai[0].val >> (1 - i)) & 1) << (dci_size - pos++); + // TPC command for scheduled PUCCH – 2 bits + for (int i = 0; i < 2; i++) + *dci_pdu |= (((uint64_t)dci_pdu_rel15->tpc >> (1 - i)) & 1) << (dci_size - pos++); + // PDSCH-to-HARQ_feedback timing indicator – 3 bits + for (int i = 0; i < 3; i++) + *dci_pdu |= (((uint64_t)dci_pdu_rel15->pdsch_to_harq_feedback_timing_indicator.val >> (2 - i)) & 1) << (dci_size - pos++); + break; } - LOG_D(MAC, "DCI index %d has %d bits and the payload is %lx\n", d, dci_size, *dci_pdu); + break; + + case NR_UL_DCI_FORMAT_0_0: + switch (rnti_type) { + case NR_RNTI_C: + // indicating a DL DCI format 1bit + *dci_pdu |= ((uint64_t)dci_pdu_rel15->format_indicator & 1) << (dci_size - pos++); + // Freq domain assignment max 16 bit + fsize = (int)ceil(log2((N_RB * (N_RB + 1)) >> 1)); + for (int i = 0; i < fsize; i++) + *dci_pdu |= ((dci_pdu_rel15->frequency_domain_assignment.val >> (fsize - i - 1)) & 1) << (dci_size - pos++); + // Time domain assignment 4bit + for (int i = 0; i < 4; i++) + *dci_pdu |= (((uint64_t)dci_pdu_rel15->time_domain_assignment.val >> (3 - i)) & 1) << (dci_size - pos++); + // Frequency hopping flag – 1 bit + *dci_pdu |= ((uint64_t)dci_pdu_rel15->frequency_hopping_flag.val & 1) << (dci_size - pos++); + // MCS 5 bit + for (int i = 0; i < 5; i++) + *dci_pdu |= (((uint64_t)dci_pdu_rel15->mcs >> (4 - i)) & 1) << (dci_size - pos++); + // New data indicator 1bit + *dci_pdu |= ((uint64_t)dci_pdu_rel15->ndi & 1) << (dci_size - pos++); + // Redundancy version 2bit + for (int i = 0; i < 2; i++) + *dci_pdu |= (((uint64_t)dci_pdu_rel15->rv >> (1 - i)) & 1) << (dci_size - pos++); + // HARQ process number 4bit + for (int i = 0; i < 4; i++) + *dci_pdu |= (((uint64_t)dci_pdu_rel15->harq_pid >> (3 - i)) & 1) << (dci_size - pos++); + // TPC command for scheduled PUSCH – 2 bits + for (int i = 0; i < 2; i++) + *dci_pdu |= (((uint64_t)dci_pdu_rel15->tpc >> (1 - i)) & 1) << (dci_size - pos++); + // Padding bits + for (int a = pos; a < 32; a++) + *dci_pdu |= ((uint64_t)dci_pdu_rel15->padding & 1) << (dci_size - pos++); + // UL/SUL indicator – 1 bit + /* commented for now (RK): need to get this from BWP descriptor + if (cfg->pucch_config.pucch_GroupHopping.value) + *dci_pdu |= + ((uint64_t)dci_pdu_rel15->ul_sul_indicator.val&1)<<(dci_size-pos++); + */ + break; + + case NFAPI_NR_RNTI_TC: + // indicating a DL DCI format 1bit + *dci_pdu |= (dci_pdu_rel15->format_indicator & 1) << (dci_size - pos++); + // Freq domain assignment max 16 bit + fsize = (int)ceil(log2((N_RB * (N_RB + 1)) >> 1)); + for (int i = 0; i < fsize; i++) + *dci_pdu |= ((dci_pdu_rel15->frequency_domain_assignment.val >> (fsize - i - 1)) & 1) << (dci_size - pos++); + // Time domain assignment 4bit + for (int i = 0; i < 4; i++) + *dci_pdu |= (((uint64_t)dci_pdu_rel15->time_domain_assignment.val >> (3 - i)) & 1) << (dci_size - pos++); + // Frequency hopping flag – 1 bit + *dci_pdu |= ((uint64_t)dci_pdu_rel15->frequency_hopping_flag.val & 1) << (dci_size - pos++); + // MCS 5 bit + for (int i = 0; i < 5; i++) + *dci_pdu |= (((uint64_t)dci_pdu_rel15->mcs >> (4 - i)) & 1) << (dci_size - pos++); + // New data indicator 1bit + *dci_pdu |= ((uint64_t)dci_pdu_rel15->ndi & 1) << (dci_size - pos++); + // Redundancy version 2bit + for (int i = 0; i < 2; i++) + *dci_pdu |= (((uint64_t)dci_pdu_rel15->rv >> (1 - i)) & 1) << (dci_size - pos++); + // HARQ process number 4bit + for (int i = 0; i < 4; i++) + *dci_pdu |= (((uint64_t)dci_pdu_rel15->harq_pid >> (3 - i)) & 1) << (dci_size - pos++); + // TPC command for scheduled PUSCH – 2 bits + for (int i = 0; i < 2; i++) + *dci_pdu |= (((uint64_t)dci_pdu_rel15->tpc >> (1 - i)) & 1) << (dci_size - pos++); + // Padding bits + for (int a = pos; a < 32; a++) + *dci_pdu |= ((uint64_t)dci_pdu_rel15->padding & 1) << (dci_size - pos++); + // UL/SUL indicator – 1 bit + /* + commented for now (RK): need to get this information from BWP descriptor + if (cfg->pucch_config.pucch_GroupHopping.value) + *dci_pdu |= + ((uint64_t)dci_pdu_rel15->ul_sul_indicator.val&1)<<(dci_size-pos++); + */ + break; + } + break; + + case NR_UL_DCI_FORMAT_0_1: + switch (rnti_type) { + case NR_RNTI_C: + // Indicating a DL DCI format 1bit + pos = 1; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->format_indicator & 0x1) << (dci_size - pos); + // Carrier indicator + pos += dci_pdu_rel15->carrier_indicator.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->carrier_indicator.val & ((1 << dci_pdu_rel15->carrier_indicator.nbits) - 1)) << (dci_size - pos); + // UL/SUL Indicator + pos += dci_pdu_rel15->ul_sul_indicator.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->ul_sul_indicator.val & ((1 << dci_pdu_rel15->ul_sul_indicator.nbits) - 1)) << (dci_size - pos); + // BWP indicator + pos += dci_pdu_rel15->bwp_indicator.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->bwp_indicator.val & ((1 << dci_pdu_rel15->bwp_indicator.nbits) - 1)) << (dci_size - pos); + // Frequency domain resource assignment + pos += dci_pdu_rel15->frequency_domain_assignment.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->frequency_domain_assignment.val & ((1 << dci_pdu_rel15->frequency_domain_assignment.nbits) - 1)) << (dci_size - pos); + // Time domain resource assignment + pos += dci_pdu_rel15->time_domain_assignment.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->time_domain_assignment.val & ((1 << dci_pdu_rel15->time_domain_assignment.nbits) - 1)) << (dci_size - pos); + // Frequency hopping + pos += dci_pdu_rel15->frequency_hopping_flag.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->frequency_hopping_flag.val & ((1 << dci_pdu_rel15->frequency_hopping_flag.nbits) - 1)) << (dci_size - pos); + // MCS 5bit + pos += 5; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->mcs & 0x1f) << (dci_size - pos); + // New data indicator 1bit + pos += 1; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->ndi & 0x1) << (dci_size - pos); + // Redundancy version 2bit + pos += 2; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->rv & 0x3) << (dci_size - pos); + // HARQ process number 4bit + pos += 4; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->harq_pid & 0xf) << (dci_size - pos); + // 1st Downlink assignment index + pos += dci_pdu_rel15->dai[0].nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->dai[0].val & ((1 << dci_pdu_rel15->dai[0].nbits) - 1)) << (dci_size - pos); + // 2nd Downlink assignment index + pos += dci_pdu_rel15->dai[1].nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->dai[1].val & ((1 << dci_pdu_rel15->dai[1].nbits) - 1)) << (dci_size - pos); + // TPC command for scheduled PUSCH 2bit + pos += 2; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->tpc & 0x3) << (dci_size - pos); + // SRS resource indicator + pos += dci_pdu_rel15->srs_resource_indicator.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->srs_resource_indicator.val & ((1 << dci_pdu_rel15->srs_resource_indicator.nbits) - 1)) << (dci_size - pos); + // Precoding info and n. of layers + pos += dci_pdu_rel15->precoding_information.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->precoding_information.val & ((1 << dci_pdu_rel15->precoding_information.nbits) - 1)) << (dci_size - pos); + // Antenna ports + pos += dci_pdu_rel15->antenna_ports.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->antenna_ports.val & ((1 << dci_pdu_rel15->antenna_ports.nbits) - 1)) << (dci_size - pos); + // SRS request + pos += dci_pdu_rel15->srs_request.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->srs_request.val & ((1 << dci_pdu_rel15->srs_request.nbits) - 1)) << (dci_size - pos); + // CSI request + pos += dci_pdu_rel15->csi_request.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->csi_request.val & ((1 << dci_pdu_rel15->csi_request.nbits) - 1)) << (dci_size - pos); + // CBG transmission information + pos += dci_pdu_rel15->cbgti.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->cbgti.val & ((1 << dci_pdu_rel15->cbgti.nbits) - 1)) << (dci_size - pos); + // PTRS DMRS association + pos += dci_pdu_rel15->ptrs_dmrs_association.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->ptrs_dmrs_association.val & ((1 << dci_pdu_rel15->ptrs_dmrs_association.nbits) - 1)) << (dci_size - pos); + // Beta offset indicator + pos += dci_pdu_rel15->beta_offset_indicator.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->beta_offset_indicator.val & ((1 << dci_pdu_rel15->beta_offset_indicator.nbits) - 1)) << (dci_size - pos); + // DMRS sequence initialization + pos += dci_pdu_rel15->dmrs_sequence_initialization.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->dmrs_sequence_initialization.val & ((1 << dci_pdu_rel15->dmrs_sequence_initialization.nbits) - 1)) << (dci_size - pos); + // UL-SCH indicator + pos += 1; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->ulsch_indicator & 0x1) << (dci_size - pos); + break; + } + break; + + case NR_DL_DCI_FORMAT_1_1: + // Indicating a DL DCI format 1bit + pos = 1; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->format_indicator & 0x1) << (dci_size - pos); + // Carrier indicator + pos += dci_pdu_rel15->carrier_indicator.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->carrier_indicator.val & ((1 << dci_pdu_rel15->carrier_indicator.nbits) - 1)) << (dci_size - pos); + // BWP indicator + pos += dci_pdu_rel15->bwp_indicator.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->bwp_indicator.val & ((1 << dci_pdu_rel15->bwp_indicator.nbits) - 1)) << (dci_size - pos); + // Frequency domain resource assignment + pos += dci_pdu_rel15->frequency_domain_assignment.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->frequency_domain_assignment.val & ((1 << dci_pdu_rel15->frequency_domain_assignment.nbits) - 1)) << (dci_size - pos); + // Time domain resource assignment + pos += dci_pdu_rel15->time_domain_assignment.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->time_domain_assignment.val & ((1 << dci_pdu_rel15->time_domain_assignment.nbits) - 1)) << (dci_size - pos); + // VRB-to-PRB mapping + pos += dci_pdu_rel15->vrb_to_prb_mapping.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->vrb_to_prb_mapping.val & ((1 << dci_pdu_rel15->vrb_to_prb_mapping.nbits) - 1)) << (dci_size - pos); + // PRB bundling size indicator + pos += dci_pdu_rel15->prb_bundling_size_indicator.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->prb_bundling_size_indicator.val & ((1 << dci_pdu_rel15->prb_bundling_size_indicator.nbits) - 1)) << (dci_size - pos); + // Rate matching indicator + pos += dci_pdu_rel15->rate_matching_indicator.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->rate_matching_indicator.val & ((1 << dci_pdu_rel15->rate_matching_indicator.nbits) - 1)) << (dci_size - pos); + // ZP CSI-RS trigger + pos += dci_pdu_rel15->zp_csi_rs_trigger.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->zp_csi_rs_trigger.val & ((1 << dci_pdu_rel15->zp_csi_rs_trigger.nbits) - 1)) << (dci_size - pos); + // TB1 + // MCS 5bit + pos += 5; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->mcs & 0x1f) << (dci_size - pos); + // New data indicator 1bit + pos += 1; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->ndi & 0x1) << (dci_size - pos); + // Redundancy version 2bit + pos += 2; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->rv & 0x3) << (dci_size - pos); + // TB2 + // MCS 5bit + pos += dci_pdu_rel15->mcs2.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->mcs2.val & ((1 << dci_pdu_rel15->mcs2.nbits) - 1)) << (dci_size - pos); + // New data indicator 1bit + pos += dci_pdu_rel15->ndi2.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->ndi2.val & ((1 << dci_pdu_rel15->ndi2.nbits) - 1)) << (dci_size - pos); + // Redundancy version 2bit + pos += dci_pdu_rel15->rv2.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->rv2.val & ((1 << dci_pdu_rel15->rv2.nbits) - 1)) << (dci_size - pos); + // HARQ process number 4bit + pos += 4; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->harq_pid & 0xf) << (dci_size - pos); + // Downlink assignment index + pos += dci_pdu_rel15->dai[0].nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->dai[0].val & ((1 << dci_pdu_rel15->dai[0].nbits) - 1)) << (dci_size - pos); + // TPC command for scheduled PUCCH 2bit + pos += 2; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->tpc & 0x3) << (dci_size - pos); + // PUCCH resource indicator 3bit + pos += 3; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->pucch_resource_indicator & 0x7) << (dci_size - pos); + // PDSCH-to-HARQ_feedback timing indicator + pos += dci_pdu_rel15->pdsch_to_harq_feedback_timing_indicator.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->pdsch_to_harq_feedback_timing_indicator.val & ((1 << dci_pdu_rel15->pdsch_to_harq_feedback_timing_indicator.nbits) - 1)) << (dci_size - pos); + // Antenna ports + pos += dci_pdu_rel15->antenna_ports.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->antenna_ports.val & ((1 << dci_pdu_rel15->antenna_ports.nbits) - 1)) << (dci_size - pos); + // TCI + pos += dci_pdu_rel15->transmission_configuration_indication.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->transmission_configuration_indication.val & ((1 << dci_pdu_rel15->transmission_configuration_indication.nbits) - 1)) << (dci_size - pos); + // SRS request + pos += dci_pdu_rel15->srs_request.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->srs_request.val & ((1 << dci_pdu_rel15->srs_request.nbits) - 1)) << (dci_size - pos); + // CBG transmission information + pos += dci_pdu_rel15->cbgti.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->cbgti.val & ((1 << dci_pdu_rel15->cbgti.nbits) - 1)) << (dci_size - pos); + // CBG flushing out information + pos += dci_pdu_rel15->cbgfi.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->cbgfi.val & ((1 << dci_pdu_rel15->cbgfi.nbits) - 1)) << (dci_size - pos); + // DMRS sequence init + pos += 1; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->dmrs_sequence_initialization.val & 0x1) << (dci_size - pos); } + LOG_D(MAC, "DCI has %d bits and the payload is %lx\n", dci_size, *dci_pdu); } - - /* - int nr_is_dci_opportunity(nfapi_nr_search_space_t search_space, - nfapi_nr_coreset_t coreset, - uint16_t frame, - uint16_t slot, - nfapi_nr_config_request_scf_t cfg) { - - AssertFatal(search_space.coreset_id==coreset.coreset_id, "Invalid association of coreset(%d) and search space(%d)\n", - search_space.search_space_id, coreset.coreset_id); - - uint8_t is_dci_opportunity=0; - uint16_t Ks=search_space.slot_monitoring_periodicity; - uint16_t Os=search_space.slot_monitoring_offset; - uint8_t Ts=search_space.duration; - - if (((frame*get_spf(&cfg) + slot - Os)%Ks)ssb_config.scs_common.value; @@ -1779,35 +1442,105 @@ int extract_length(int startSymbolAndLength) { /* * Dump the UL or DL UE_info into LOG_T(MAC) */ -void dump_nr_ue_list(NR_UE_list_t *listP) { +void dump_nr_list(NR_list_t *listP) +{ for (int j = listP->head; j >= 0; j = listP->next[j]) - LOG_T(MAC, "DL list node %d => %d\n", j, listP->next[j]); + LOG_T(MAC, "NR list node %d => %d\n", j, listP->next[j]); } /* - * Add a UE to NR_UE_list listP + * Create a new NR_list */ -inline void add_nr_ue_list(NR_UE_list_t *listP, int UE_id) { +void create_nr_list(NR_list_t *list, int len) +{ + list->head = -1; + list->next = calloc(len, sizeof(*list->next)); + AssertFatal(list, "cannot calloc() memory for NR_list_t->next\n"); + for (int i = 0; i < len; ++i) + list->next[i] = -1; + list->tail = -1; + list->len = len; +} + +/* + * Destroy an NR_list + */ +void destroy_nr_list(NR_list_t *list) +{ + free(list->next); +} + +/* + * Add an ID to an NR_list at the end, traversing the whole list. Note: + * add_tail_nr_list() is a faster alternative, but this implementation ensures + * we do not add an existing ID. + */ +void add_nr_list(NR_list_t *listP, int id) +{ int *cur = &listP->head; while (*cur >= 0) { - AssertFatal(*cur != UE_id, "UE_id %d already in NR_UE_list!\n", UE_id); + AssertFatal(*cur != id, "id %d already in NR_UE_list!\n", id); cur = &listP->next[*cur]; } - *cur = UE_id; + *cur = id; + if (listP->next[id] < 0) + listP->tail = id; } /* - * Remove a UE from NR_UE_list listP + * Remove an ID from an NR_list */ -static inline void remove_nr_ue_list(NR_UE_list_t *listP, int UE_id) { +void remove_nr_list(NR_list_t *listP, int id) +{ int *cur = &listP->head; - while (*cur != -1 && *cur != UE_id) + int *prev = &listP->head; + while (*cur != -1 && *cur != id) { + prev = cur; cur = &listP->next[*cur]; - AssertFatal(*cur != -1, "UE %d not found in UE_list\n", UE_id); + } + AssertFatal(*cur != -1, "ID %d not found in UE_list\n", id); int *next = &listP->next[*cur]; *cur = listP->next[*cur]; *next = -1; - return; + listP->tail = *prev >= 0 && listP->next[*prev] >= 0 ? listP->tail : *prev; +} + +/* + * Add an ID to the tail of the NR_list in O(1). Note that there is + * corresponding remove_tail_nr_list(), as we cannot set the tail backwards and + * therefore need to go through the whole list (use remove_nr_list()) + */ +void add_tail_nr_list(NR_list_t *listP, int id) +{ + int *last = listP->tail < 0 ? &listP->head : &listP->next[listP->tail]; + *last = id; + listP->next[id] = -1; + listP->tail = id; +} + +/* + * Add an ID to the front of the NR_list in O(1) + */ +void add_front_nr_list(NR_list_t *listP, int id) +{ + const int ohead = listP->head; + listP->head = id; + listP->next[id] = ohead; + if (listP->tail < 0) + listP->tail = id; +} + +/* + * Remove an ID from the front of the NR_list in O(1) + */ +void remove_front_nr_list(NR_list_t *listP) +{ + AssertFatal(listP->head >= 0, "Nothing to remove\n"); + const int ohead = listP->head; + listP->head = listP->next[ohead]; + listP->next[ohead] = -1; + if (listP->head < 0) + listP->tail = -1; } int find_nr_UE_id(module_id_t mod_idP, rnti_t rntiP) @@ -1860,20 +1593,35 @@ int find_nr_RA_id(module_id_t mod_idP, int CC_idP, rnti_t rntiP) { return -1; } -//------------------------------------------------------------------------------ -int add_new_nr_ue(module_id_t mod_idP, rnti_t rntiP){ +int get_nrofHARQ_ProcessesForPDSCH(e_NR_PDSCH_ServingCellConfig__nrofHARQ_ProcessesForPDSCH n) +{ + switch (n) { + case NR_PDSCH_ServingCellConfig__nrofHARQ_ProcessesForPDSCH_n2: + return 2; + case NR_PDSCH_ServingCellConfig__nrofHARQ_ProcessesForPDSCH_n4: + return 4; + case NR_PDSCH_ServingCellConfig__nrofHARQ_ProcessesForPDSCH_n6: + return 6; + case NR_PDSCH_ServingCellConfig__nrofHARQ_ProcessesForPDSCH_n10: + return 10; + case NR_PDSCH_ServingCellConfig__nrofHARQ_ProcessesForPDSCH_n12: + return 12; + case NR_PDSCH_ServingCellConfig__nrofHARQ_ProcessesForPDSCH_n16: + return 16; + default: + return 8; + } +} +//------------------------------------------------------------------------------ +int add_new_nr_ue(module_id_t mod_idP, rnti_t rntiP, NR_CellGroupConfig_t *secondaryCellGroup) +{ NR_UE_info_t *UE_info = &RC.nrmac[mod_idP]->UE_info; - NR_COMMON_channels_t *cc = RC.nrmac[mod_idP]->common_channels; - NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; - int num_slots_ul = scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots; - if (scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols>0) - num_slots_ul++; - LOG_W(MAC, "[gNB %d] Adding UE with rnti %x (num_UEs %d)\n", + LOG_I(MAC, "[gNB %d] Adding UE with rnti %x (num_UEs %d)\n", mod_idP, rntiP, UE_info->num_UEs); - dump_nr_ue_list(&UE_info->list); + dump_nr_list(&UE_info->list); for (int i = 0; i < MAX_MOBILES_PER_GNB; i++) { if (UE_info->active[i]) @@ -1883,38 +1631,65 @@ int add_new_nr_ue(module_id_t mod_idP, rnti_t rntiP){ UE_info->num_UEs++; UE_info->active[UE_id] = true; UE_info->rnti[UE_id] = rntiP; - add_nr_ue_list(&UE_info->list, UE_id); + UE_info->secondaryCellGroup[UE_id] = secondaryCellGroup; + add_nr_list(&UE_info->list, UE_id); + memset(&UE_info->mac_stats[UE_id], 0, sizeof(NR_mac_stats_t)); set_Y(UE_info->Y[UE_id], rntiP); - memset((void *) &UE_info->UE_sched_ctrl[UE_id], - 0, - sizeof(NR_UE_sched_ctrl_t)); - UE_info->UE_sched_ctrl[UE_id].ta_frame = 0; - UE_info->UE_sched_ctrl[UE_id].ta_update = 31; - UE_info->UE_sched_ctrl[UE_id].ta_apply = false; - UE_info->UE_sched_ctrl[UE_id].ul_rssi = 0; + compute_csi_bitlen(secondaryCellGroup, UE_info, UE_id); + NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + memset(sched_ctrl, 0, sizeof(*sched_ctrl)); + sched_ctrl->ta_frame = 0; + sched_ctrl->ta_update = 31; + sched_ctrl->ta_apply = false; + sched_ctrl->ul_rssi = 0; /* set illegal time domain allocation to force recomputation of all fields */ - UE_info->UE_sched_ctrl[UE_id].pusch_save.time_domain_allocation = -1; - UE_info->UE_sched_ctrl[UE_id].sched_pucch = (NR_sched_pucch **)malloc(num_slots_ul*sizeof(NR_sched_pucch *)); - for (int s=0; sUE_sched_ctrl[UE_id].sched_pucch[s] = (NR_sched_pucch *)malloc(2*sizeof(NR_sched_pucch)); + sched_ctrl->pusch_save.time_domain_allocation = -1; + const NR_ServingCellConfig_t *servingCellConfig = secondaryCellGroup->spCellConfig->spCellConfigDedicated; - for (int k=0; kUE_sched_ctrl[UE_id].sched_pucch[k][l], - 0, - sizeof(NR_sched_pucch)); - } + /* Set default BWPs */ + const struct NR_ServingCellConfig__downlinkBWP_ToAddModList *bwpList = servingCellConfig->downlinkBWP_ToAddModList; + AssertFatal(bwpList->list.count == 1, + "downlinkBWP_ToAddModList has %d BWP!\n", + bwpList->list.count); + const int bwp_id = 1; + sched_ctrl->active_bwp = bwpList->list.array[bwp_id - 1]; + const struct NR_UplinkConfig__uplinkBWP_ToAddModList *ubwpList = servingCellConfig->uplinkConfig->uplinkBWP_ToAddModList; + AssertFatal(ubwpList->list.count == 1, + "uplinkBWP_ToAddModList has %d BWP!\n", + ubwpList->list.count); + sched_ctrl->active_ubwp = ubwpList->list.array[bwp_id - 1]; + + /* get Number of HARQ processes for this UE */ + AssertFatal(servingCellConfig->pdsch_ServingCellConfig->present == NR_SetupRelease_PDSCH_ServingCellConfig_PR_setup, + "no pdsch-ServingCellConfig found for UE %d\n", + UE_id); + const NR_PDSCH_ServingCellConfig_t *pdsch = servingCellConfig->pdsch_ServingCellConfig->choice.setup; + const int nrofHARQ = pdsch->nrofHARQ_ProcessesForPDSCH ? + get_nrofHARQ_ProcessesForPDSCH(*pdsch->nrofHARQ_ProcessesForPDSCH) : 8; + // add all available DL HARQ processes for this UE + create_nr_list(&sched_ctrl->available_dl_harq, nrofHARQ); + for (int harq = 0; harq < nrofHARQ; harq++) + add_tail_nr_list(&sched_ctrl->available_dl_harq, harq); + create_nr_list(&sched_ctrl->feedback_dl_harq, nrofHARQ); + create_nr_list(&sched_ctrl->retrans_dl_harq, nrofHARQ); + + // add all available UL HARQ processes for this UE + create_nr_list(&sched_ctrl->available_ul_harq, 16); + for (int harq = 0; harq < 16; harq++) + add_tail_nr_list(&sched_ctrl->available_ul_harq, harq); + create_nr_list(&sched_ctrl->feedback_ul_harq, 16); + create_nr_list(&sched_ctrl->retrans_ul_harq, 16); LOG_I(MAC, "gNB %d] Add NR UE_id %d : rnti %x\n", mod_idP, UE_id, rntiP); - dump_nr_ue_list(&UE_info->list); + dump_nr_list(&UE_info->list); return (UE_id); } // printf("MAC: cannot add new UE for rnti %x\n", rntiP); LOG_E(MAC, "error in add_new_ue(), could not find space in UE_info, Dumping UE list\n"); - dump_nr_ue_list(&UE_info->list); + dump_nr_list(&UE_info->list); return -1; } @@ -1942,11 +1717,14 @@ void mac_remove_nr_ue(module_id_t mod_id, rnti_t rnti) UE_info->num_UEs--; UE_info->active[UE_id] = FALSE; UE_info->rnti[UE_id] = 0; - remove_nr_ue_list(&UE_info->list, UE_id); - free(UE_info->UE_sched_ctrl[UE_id].sched_pucch); - memset((void *) &UE_info->UE_sched_ctrl[UE_id], - 0, - sizeof(NR_UE_sched_ctrl_t)); + remove_nr_list(&UE_info->list, UE_id); + NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + destroy_nr_list(&sched_ctrl->available_dl_harq); + destroy_nr_list(&sched_ctrl->feedback_dl_harq); + destroy_nr_list(&sched_ctrl->retrans_dl_harq); + destroy_nr_list(&sched_ctrl->available_ul_harq); + destroy_nr_list(&sched_ctrl->feedback_ul_harq); + destroy_nr_list(&sched_ctrl->retrans_ul_harq); LOG_I(MAC, "[gNB %d] Remove NR UE_id %d : rnti %x\n", mod_id, UE_id, @@ -2024,6 +1802,30 @@ void get_pdsch_to_harq_feedback(int Mod_idP, } +bool find_free_CCE(module_id_t module_id, + sub_frame_t slot, + int UE_id){ + NR_UE_sched_ctrl_t *sched_ctrl = &RC.nrmac[module_id]->UE_info.UE_sched_ctrl[UE_id]; + uint8_t nr_of_candidates; + find_aggregation_candidates(&sched_ctrl->aggregation_level, + &nr_of_candidates, + sched_ctrl->search_space); + const int cid = sched_ctrl->coreset->controlResourceSetId; + const uint16_t Y = RC.nrmac[module_id]->UE_info.Y[UE_id][cid][slot]; + const int m = RC.nrmac[module_id]->UE_info.num_pdcch_cand[UE_id][cid]; + sched_ctrl->cce_index = allocate_nr_CCEs(RC.nrmac[module_id], + sched_ctrl->active_bwp, + sched_ctrl->coreset, + sched_ctrl->aggregation_level, + Y, + m, + nr_of_candidates); + if (sched_ctrl->cce_index < 0) + return false; + + RC.nrmac[module_id]->UE_info.num_pdcch_cand[UE_id][cid]++; + return true; +} /*void fill_nfapi_coresets_and_searchspaces(NR_CellGroupConfig_t *cg, nfapi_nr_coreset_t *coreset, diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index ec5195ec5b..629b4dc7b0 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -31,67 +31,76 @@ #include "NR_MAC_COMMON/nr_mac_extern.h" #include "NR_MAC_gNB/mac_proto.h" #include "common/ran_context.h" +#include "nfapi/oai_integration/vendor_ext.h" extern RAN_CONTEXT_t RC; +void nr_fill_nfapi_pucch(module_id_t mod_id, + frame_t frame, + sub_frame_t slot, + const NR_sched_pucch_t *pucch, + int UE_id) +{ + NR_UE_info_t *UE_info = &RC.nrmac[mod_id]->UE_info; + + nfapi_nr_ul_tti_request_t *future_ul_tti_req = + &RC.nrmac[mod_id]->UL_tti_req_ahead[0][pucch->ul_slot]; + AssertFatal(future_ul_tti_req->SFN == pucch->frame + && future_ul_tti_req->Slot == pucch->ul_slot, + "future UL_tti_req's frame.slot %d.%d does not match PUCCH %d.%d\n", + future_ul_tti_req->SFN, + future_ul_tti_req->Slot, + pucch->frame, + pucch->ul_slot); + future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pdu_type = NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE; + future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pdu_size = sizeof(nfapi_nr_pucch_pdu_t); + nfapi_nr_pucch_pdu_t *pucch_pdu = &future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pucch_pdu; + memset(pucch_pdu, 0, sizeof(nfapi_nr_pucch_pdu_t)); + future_ul_tti_req->n_pdus += 1; + + LOG_D(MAC, + "%4d.%2d Scheduling pucch reception in %4d.%2d: bits SR %d, ACK %d, CSI %d on res %d\n", + frame, + slot, + pucch->frame, + pucch->ul_slot, + pucch->sr_flag, + pucch->dai_c, + pucch->csi_bits, + pucch->resource_indicator); + + NR_ServingCellConfigCommon_t *scc = RC.nrmac[mod_id]->common_channels->ServingCellConfigCommon; + nr_configure_pucch(pucch_pdu, + scc, + UE_info->UE_sched_ctrl[UE_id].active_ubwp, + UE_info->rnti[UE_id], + pucch->resource_indicator, + pucch->csi_bits, + pucch->dai_c, + pucch->sr_flag); +} + void nr_schedule_pucch(int Mod_idP, - int UE_id, - int nr_ulmix_slots, frame_t frameP, sub_frame_t slotP) { NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info; - AssertFatal(UE_info->active[UE_id],"Cannot find UE_id %d is not active\n",UE_id); + const NR_list_t *UE_list = &UE_info->list; - for (int k=0; kUE_sched_ctrl[UE_id].sched_pucch[k][l]; + for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { + NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + const int n = sizeof(sched_ctrl->sched_pucch) / sizeof(*sched_ctrl->sched_pucch); + for (int i = 0; i < n; i++) { + NR_sched_pucch_t *curr_pucch = &UE_info->UE_sched_ctrl[UE_id].sched_pucch[i]; const uint16_t O_ack = curr_pucch->dai_c; const uint16_t O_csi = curr_pucch->csi_bits; - const uint8_t O_sr = 0; // no SR in PUCCH implemented for now + const uint8_t O_sr = curr_pucch->sr_flag; if (O_ack + O_csi + O_sr == 0 || frameP != curr_pucch->frame || slotP != curr_pucch->ul_slot) continue; - nfapi_nr_ul_tti_request_t *future_ul_tti_req = - &RC.nrmac[Mod_idP]->UL_tti_req_ahead[0][curr_pucch->ul_slot]; - AssertFatal(future_ul_tti_req->SFN == curr_pucch->frame - && future_ul_tti_req->Slot == curr_pucch->ul_slot, - "future UL_tti_req's frame.slot %d.%d does not match PUCCH %d.%d\n", - future_ul_tti_req->SFN, - future_ul_tti_req->Slot, - curr_pucch->frame, - curr_pucch->ul_slot); - future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pdu_type = NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE; - future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pdu_size = sizeof(nfapi_nr_pucch_pdu_t); - nfapi_nr_pucch_pdu_t *pucch_pdu = &future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pucch_pdu; - memset(pucch_pdu, 0, sizeof(nfapi_nr_pucch_pdu_t)); - future_ul_tti_req->n_pdus += 1; - - LOG_D(MAC, - "%4d.%2d Scheduling pucch reception in %4d.%2d: bits SR %d, ACK %d, CSI %d, k %d l %d\n", - frameP, - slotP, - curr_pucch->frame, - curr_pucch->ul_slot, - O_sr, - O_ack, - O_csi, - k, l); - - NR_ServingCellConfigCommon_t *scc = RC.nrmac[Mod_idP]->common_channels->ServingCellConfigCommon; - nr_configure_pucch(pucch_pdu, - scc, - UE_info->UE_sched_ctrl[UE_id].active_ubwp, - UE_info->rnti[UE_id], - curr_pucch->resource_indicator, - O_csi, - O_ack, - O_sr); - - memset(&UE_info->UE_sched_ctrl[UE_id].sched_pucch[k][l], - 0, - sizeof(NR_sched_pucch)); + nr_fill_nfapi_pucch(Mod_idP, frameP, slotP, curr_pucch, UE_id); + memset(curr_pucch, 0, sizeof(*curr_pucch)); } } } @@ -172,107 +181,136 @@ void compute_csi_bitlen (NR_CellGroupConfig_t *secondaryCellGroup, NR_UE_info_t } -uint16_t nr_get_csi_bitlen(int Mod_idP, - int UE_id, - uint8_t csi_report_id) { - - uint16_t csi_bitlen =0; - NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info; - CRI_SSBRI_RSRP_bitlen_t * CSI_report_bitlen = NULL; - - CSI_report_bitlen = &(UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0]); - csi_bitlen = ((CSI_report_bitlen->cri_ssbri_bitlen * CSI_report_bitlen->nb_ssbri_cri) + - CSI_report_bitlen->rsrp_bitlen +(CSI_report_bitlen->diff_rsrp_bitlen * - (CSI_report_bitlen->nb_ssbri_cri -1 )) *UE_info->csi_report_template[UE_id][csi_report_id].nb_of_csi_ssb_report); - - return csi_bitlen; +uint16_t nr_get_csi_bitlen(const nr_csi_report_t *csi_report) +{ + const CRI_SSBRI_RSRP_bitlen_t *bitlen = &csi_report->CSI_report_bitlen[0]; + return bitlen->cri_ssbri_bitlen * bitlen->nb_ssbri_cri + + bitlen->rsrp_bitlen + + bitlen->diff_rsrp_bitlen * (bitlen->nb_ssbri_cri - 1) * csi_report->nb_of_csi_ssb_report; } void nr_csi_meas_reporting(int Mod_idP, - int UE_id, frame_t frame, - sub_frame_t slot, - int slots_per_tdd, - int ul_slots, - int n_slots_frame) { + sub_frame_t slot) +{ + NR_ServingCellConfigCommon_t *scc = + RC.nrmac[Mod_idP]->common_channels->ServingCellConfigCommon; + const int n_slots_frame = nr_slots_per_frame[*scc->ssbSubcarrierSpacing]; NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info; - NR_sched_pucch *curr_pucch; - NR_PUCCH_ResourceSet_t *pucchresset; - NR_CSI_ReportConfig_t *csirep; - NR_CellGroupConfig_t *secondaryCellGroup = UE_info->secondaryCellGroup[UE_id]; - NR_CSI_MeasConfig_t *csi_measconfig = secondaryCellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig->choice.setup; - NR_BWP_Uplink_t *ubwp=secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]; - NR_PUCCH_Config_t *pucch_Config = ubwp->bwp_Dedicated->pucch_Config->choice.setup; + NR_list_t *UE_list = &UE_info->list; + for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { + const NR_CellGroupConfig_t *secondaryCellGroup = UE_info->secondaryCellGroup[UE_id]; + NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + const NR_CSI_MeasConfig_t *csi_measconfig = secondaryCellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig->choice.setup; + AssertFatal(csi_measconfig->csi_ReportConfigToAddModList->list.count > 0, + "NO CSI report configuration available"); + NR_PUCCH_Config_t *pucch_Config = sched_ctrl->active_ubwp->bwp_Dedicated->pucch_Config->choice.setup; - AssertFatal(csi_measconfig->csi_ReportConfigToAddModList->list.count>0,"NO CSI report configuration available"); + for (int csi_report_id = 0; csi_report_id < csi_measconfig->csi_ReportConfigToAddModList->list.count; csi_report_id++){ + const NR_CSI_ReportConfig_t *csirep = csi_measconfig->csi_ReportConfigToAddModList->list.array[csi_report_id]; - for (int csi_report_id = 0; csi_report_id < csi_measconfig->csi_ReportConfigToAddModList->list.count; csi_report_id++){ + AssertFatal(csirep->reportConfigType.choice.periodic, + "Only periodic CSI reporting is implemented currently\n"); + int period, offset; + csi_period_offset(csirep, &period, &offset); + const int sched_slot = (period + offset) % n_slots_frame; + // prepare to schedule csi measurement reception according to 5.2.1.4 in 38.214 + // preparation is done in first slot of tdd period + if (frame % (period / n_slots_frame) != offset / n_slots_frame) + continue; + LOG_D(MAC, "CSI in frame %d slot %d\n", frame, sched_slot); - csirep = csi_measconfig->csi_ReportConfigToAddModList->list.array[csi_report_id]; + const NR_PUCCH_CSI_Resource_t *pucchcsires = csirep->reportConfigType.choice.periodic->pucch_CSI_ResourceList.list.array[0]; + const NR_PUCCH_ResourceSet_t *pucchresset = pucch_Config->resourceSetToAddModList->list.array[1]; // set with formats >1 + const int n = pucchresset->resourceList.list.count; + int res_index = 0; + for (; res_index < n; res_index++) + if (*pucchresset->resourceList.list.array[res_index] == pucchcsires->pucch_Resource) + break; + AssertFatal(res_index < n, + "CSI resource not found among PUCCH resources\n"); - AssertFatal(csirep->reportConfigType.choice.periodic!=NULL,"Only periodic CSI reporting is implemented currently"); - int period, offset, sched_slot; - csi_period_offset(csirep,&period,&offset); - sched_slot = (period+offset)%n_slots_frame; - // prepare to schedule csi measurement reception according to 5.2.1.4 in 38.214 - // preparation is done in first slot of tdd period - if ( (frame%(period/n_slots_frame)==(offset/n_slots_frame)) && (slot==((sched_slot/slots_per_tdd)*slots_per_tdd))) { - - // we are scheduling pucch for csi in the first pucch occasion (this comes before ack/nack) - curr_pucch = &UE_info->UE_sched_ctrl[UE_id].sched_pucch[(sched_slot%slots_per_tdd)-slots_per_tdd+ul_slots][0]; - - NR_PUCCH_CSI_Resource_t *pucchcsires = csirep->reportConfigType.choice.periodic->pucch_CSI_ResourceList.list.array[0]; - - int found = -1; - pucchresset = pucch_Config->resourceSetToAddModList->list.array[1]; // set with formats >1 - int n_list = pucchresset->resourceList.list.count; - for (int i=0; iresourceList.list.array[i] == pucchcsires->pucch_Resource) - found = i; - } - AssertFatal(found>-1,"CSI resource not found among PUCCH resources"); - - curr_pucch->resource_indicator = found; - - n_list = pucch_Config->resourceToAddModList->list.count; - - // going through the list of PUCCH resources to find the one indexed by resource_id - for (int i=0; iresourceToAddModList->list.array[i]; - if (pucchres->pucch_ResourceId == *pucchresset->resourceList.list.array[found]) { - switch(pucchres->format.present){ - case NR_PUCCH_Resource__format_PR_format2: - if (pucch_Config->format2->choice.setup->simultaneousHARQ_ACK_CSI == NULL) - curr_pucch->simultaneous_harqcsi = false; - else - curr_pucch->simultaneous_harqcsi = true; - break; - case NR_PUCCH_Resource__format_PR_format3: - if (pucch_Config->format3->choice.setup->simultaneousHARQ_ACK_CSI == NULL) - curr_pucch->simultaneous_harqcsi = false; - else - curr_pucch->simultaneous_harqcsi = true; - break; - case NR_PUCCH_Resource__format_PR_format4: - if (pucch_Config->format4->choice.setup->simultaneousHARQ_ACK_CSI == NULL) - curr_pucch->simultaneous_harqcsi = false; - else - curr_pucch->simultaneous_harqcsi = true; - break; - default: - AssertFatal(1==0,"Invalid PUCCH format type"); - } - } - } - curr_pucch->csi_bits += nr_get_csi_bitlen(Mod_idP,UE_id,csi_report_id); // TODO function to compute CSI meas report bit size + // find free PUCCH that is in order with possibly existing PUCCH + // schedulings (other CSI, SR) + NR_sched_pucch_t *curr_pucch = &sched_ctrl->sched_pucch[2]; + AssertFatal(curr_pucch->csi_bits == 0 + && !curr_pucch->sr_flag + && curr_pucch->dai_c == 0, + "PUCCH not free at index 2 for UE %04x\n", + UE_info->rnti[UE_id]); curr_pucch->frame = frame; curr_pucch->ul_slot = sched_slot; + curr_pucch->resource_indicator = res_index; + curr_pucch->csi_bits += + nr_get_csi_bitlen(&UE_info->csi_report_template[UE_id][csi_report_id]); + + // going through the list of PUCCH resources to find the one indexed by resource_id + uint16_t *vrb_map_UL = &RC.nrmac[Mod_idP]->common_channels[0].vrb_map_UL[sched_slot * MAX_BWP_SIZE]; + const int m = pucch_Config->resourceToAddModList->list.count; + for (int j = 0; j < m; j++) { + NR_PUCCH_Resource_t *pucchres = pucch_Config->resourceToAddModList->list.array[j]; + if (pucchres->pucch_ResourceId != *pucchresset->resourceList.list.array[res_index]) + continue; + int start = pucchres->startingPRB; + int len = 1; + uint64_t mask = 0; + switch(pucchres->format.present){ + case NR_PUCCH_Resource__format_PR_format2: + len = pucchres->format.choice.format2->nrofPRBs; + mask = ((1 << pucchres->format.choice.format2->nrofSymbols) - 1) << pucchres->format.choice.format2->startingSymbolIndex; + curr_pucch->simultaneous_harqcsi = pucch_Config->format2->choice.setup->simultaneousHARQ_ACK_CSI; + break; + case NR_PUCCH_Resource__format_PR_format3: + len = pucchres->format.choice.format3->nrofPRBs; + mask = ((1 << pucchres->format.choice.format3->nrofSymbols) - 1) << pucchres->format.choice.format3->startingSymbolIndex; + curr_pucch->simultaneous_harqcsi = pucch_Config->format3->choice.setup->simultaneousHARQ_ACK_CSI; + break; + case NR_PUCCH_Resource__format_PR_format4: + mask = ((1 << pucchres->format.choice.format4->nrofSymbols) - 1) << pucchres->format.choice.format4->startingSymbolIndex; + curr_pucch->simultaneous_harqcsi = pucch_Config->format4->choice.setup->simultaneousHARQ_ACK_CSI; + break; + default: + AssertFatal(0, "Invalid PUCCH format type\n"); + } + // verify resources are free + for (int i = start; i < start + len; ++i) { + vrb_map_UL[i] |= mask; + } + AssertFatal(!curr_pucch->simultaneous_harqcsi, + "UE %04x has simultaneous HARQ/CSI configured, but we don't support that\n", + UE_info->rnti[UE_id]); + } } } } +static void handle_dl_harq(module_id_t mod_id, + int UE_id, + int8_t harq_pid, + bool success) +{ + NR_UE_info_t *UE_info = &RC.nrmac[mod_id]->UE_info; + NR_UE_harq_t *harq = &UE_info->UE_sched_ctrl[UE_id].harq_processes[harq_pid]; + harq->feedback_slot = -1; + harq->is_waiting = false; + if (success) { + add_tail_nr_list(&UE_info->UE_sched_ctrl[UE_id].available_dl_harq, harq_pid); + harq->round = 0; + harq->ndi ^= 1; + } else if (harq->round == MAX_HARQ_ROUNDS) { + add_tail_nr_list(&UE_info->UE_sched_ctrl[UE_id].available_dl_harq, harq_pid); + harq->round = 0; + harq->ndi ^= 1; + NR_mac_stats_t *stats = &UE_info->mac_stats[UE_id]; + stats->dlsch_errors++; + LOG_D(MAC, "retransmission error for UE %d (total %d)\n", UE_id, stats->dlsch_errors); + } else { + add_tail_nr_list(&UE_info->UE_sched_ctrl[UE_id].retrans_dl_harq, harq_pid); + harq->round++; + } +} void handle_nr_uci_pucch_0_1(module_id_t mod_id, frame_t frame, @@ -292,50 +330,36 @@ void handle_nr_uci_pucch_0_1(module_id_t mod_id, uci_01->ul_cqi, 30); - // TODO - int max_harq_rounds = 4; // TODO define macro + NR_ServingCellConfigCommon_t *scc = RC.nrmac[mod_id]->common_channels->ServingCellConfigCommon; + const int num_slots = nr_slots_per_frame[*scc->ssbSubcarrierSpacing]; if (((uci_01->pduBitmap >> 1) & 0x01)) { - // handle harq - int harq_idx_s = 0; - // iterate over received harq bits for (int harq_bit = 0; harq_bit < uci_01->harq->num_harq; harq_bit++) { - // search for the right harq process - for (int harq_idx = harq_idx_s; harq_idx < NR_MAX_NB_HARQ_PROCESSES; harq_idx++) { - // if the gNB received ack with a good confidence - if ((slot - 1) == sched_ctrl->harq_processes[harq_idx].feedback_slot) { - sched_ctrl->harq_processes[harq_idx].feedback_slot = -1; - if ((uci_01->harq->harq_list[harq_bit].harq_value == 1) && - (uci_01->harq->harq_confidence_level == 0)) { - // toggle NDI and reset round - sched_ctrl->harq_processes[harq_idx].ndi ^= 1; - sched_ctrl->harq_processes[harq_idx].round = 0; - } - else - sched_ctrl->harq_processes[harq_idx].round++; - sched_ctrl->harq_processes[harq_idx].is_waiting = 0; - harq_idx_s = harq_idx + 1; - // if the max harq rounds was reached - if (sched_ctrl->harq_processes[harq_idx].round == max_harq_rounds) { - sched_ctrl->harq_processes[harq_idx].ndi ^= 1; - sched_ctrl->harq_processes[harq_idx].round = 0; - UE_info->mac_stats[UE_id].dlsch_errors++; - } - break; - } - // if feedback slot processing is aborted - else if (sched_ctrl->harq_processes[harq_idx].feedback_slot != -1 - && (slot - 1) > sched_ctrl->harq_processes[harq_idx].feedback_slot - && sched_ctrl->harq_processes[harq_idx].is_waiting) { - sched_ctrl->harq_processes[harq_idx].feedback_slot = -1; - sched_ctrl->harq_processes[harq_idx].round++; - if (sched_ctrl->harq_processes[harq_idx].round == max_harq_rounds) { - sched_ctrl->harq_processes[harq_idx].ndi ^= 1; - sched_ctrl->harq_processes[harq_idx].round = 0; - } - sched_ctrl->harq_processes[harq_idx].is_waiting = 0; - } + const uint8_t harq_value = uci_01->harq->harq_list[harq_bit].harq_value; + const uint8_t harq_confidence = uci_01->harq->harq_confidence_level; + const int feedback_slot = (slot - 1 + num_slots) % num_slots; + /* In case of realtime problems: we can only identify a HARQ process by + * timing. If the HARQ process's feedback_slot is not the one we + * expected, we assume that processing has been aborted and we need to + * skip this HARQ process, which is what happens in the loop below. If + * you don't experience real-time problems, you might simply revert the + * commit that introduced these changes. */ + int8_t pid = sched_ctrl->feedback_dl_harq.head; + DevAssert(pid >= 0); + while (sched_ctrl->harq_processes[pid].feedback_slot != feedback_slot) { + LOG_W(MAC, + "expected feedback slot %d, but found %d instead\n", + sched_ctrl->harq_processes[pid].feedback_slot, + feedback_slot); + remove_front_nr_list(&sched_ctrl->feedback_dl_harq); + handle_dl_harq(mod_id, UE_id, pid, 0); + pid = sched_ctrl->feedback_dl_harq.head; + DevAssert(pid >= 0); } + remove_front_nr_list(&sched_ctrl->feedback_dl_harq); + NR_UE_harq_t *harq = &sched_ctrl->harq_processes[pid]; + DevAssert(harq->is_waiting); + handle_dl_harq(mod_id, UE_id, pid, harq_value == 1 && harq_confidence == 0); } } } @@ -358,130 +382,243 @@ void handle_nr_uci_pucch_2_3_4(module_id_t mod_id, uci_234->ul_cqi, 30); - // TODO - int max_harq_rounds = 4; // TODO define macro + NR_ServingCellConfigCommon_t *scc = RC.nrmac[mod_id]->common_channels->ServingCellConfigCommon; + const int num_slots = nr_slots_per_frame[*scc->ssbSubcarrierSpacing]; if ((uci_234->pduBitmap >> 1) & 0x01) { - int harq_idx_s = 0; - int acknack; - // iterate over received harq bits for (int harq_bit = 0; harq_bit < uci_234->harq.harq_bit_len; harq_bit++) { - acknack = ((uci_234->harq.harq_payload[harq_bit>>3])>>harq_bit)&0x01; - for (int harq_idx = harq_idx_s; harq_idx < NR_MAX_NB_HARQ_PROCESSES-1; harq_idx++) { - // if the gNB received ack with a good confidence or if the max harq rounds was reached - if ((slot - 1) == sched_ctrl->harq_processes[harq_idx].feedback_slot) { - // TODO add some confidence level for when there is no CRC - sched_ctrl->harq_processes[harq_idx].feedback_slot = -1; - if ((uci_234->harq.harq_crc != 1) && acknack) { - // toggle NDI and reset round - sched_ctrl->harq_processes[harq_idx].ndi ^= 1; - sched_ctrl->harq_processes[harq_idx].round = 0; - } - else - sched_ctrl->harq_processes[harq_idx].round++; - sched_ctrl->harq_processes[harq_idx].is_waiting = 0; - harq_idx_s = harq_idx + 1; - // if the max harq rounds was reached - if (sched_ctrl->harq_processes[harq_idx].round == max_harq_rounds) { - sched_ctrl->harq_processes[harq_idx].ndi ^= 1; - sched_ctrl->harq_processes[harq_idx].round = 0; - UE_info->mac_stats[UE_id].dlsch_errors++; - } - break; - } - // if feedback slot processing is aborted - else if (sched_ctrl->harq_processes[harq_idx].feedback_slot != -1 - && (slot - 1) > sched_ctrl->harq_processes[harq_idx].feedback_slot - && sched_ctrl->harq_processes[harq_idx].is_waiting) { - sched_ctrl->harq_processes[harq_idx].feedback_slot = -1; - sched_ctrl->harq_processes[harq_idx].round++; - if (sched_ctrl->harq_processes[harq_idx].round == max_harq_rounds) { - sched_ctrl->harq_processes[harq_idx].ndi ^= 1; - sched_ctrl->harq_processes[harq_idx].round = 0; - } - sched_ctrl->harq_processes[harq_idx].is_waiting = 0; - } + const int acknack = ((uci_234->harq.harq_payload[harq_bit >> 3]) >> harq_bit) & 0x01; + const int feedback_slot = (slot - 1 + num_slots) % num_slots; + /* In case of realtime problems: we can only identify a HARQ process by + * timing. If the HARQ process's feedback_slot is not the one we + * expected, we assume that processing has been aborted and we need to + * skip this HARQ process, which is what happens in the loop below. If + * you don't experience real-time problems, you might simply revert the + * commit that introduced these changes. */ + int8_t pid = sched_ctrl->feedback_dl_harq.head; + DevAssert(pid >= 0); + while (sched_ctrl->harq_processes[pid].feedback_slot != feedback_slot) { + LOG_W(MAC, + "expected feedback slot %d, but found %d instead\n", + sched_ctrl->harq_processes[pid].feedback_slot, + feedback_slot); + remove_front_nr_list(&sched_ctrl->feedback_dl_harq); + handle_dl_harq(mod_id, UE_id, pid, 0); + pid = sched_ctrl->feedback_dl_harq.head; + DevAssert(pid >= 0); } + remove_front_nr_list(&sched_ctrl->feedback_dl_harq); + NR_UE_harq_t *harq = &sched_ctrl->harq_processes[pid]; + DevAssert(harq->is_waiting); + handle_dl_harq(mod_id, UE_id, pid, uci_234->harq.harq_crc != 1 && acknack); } } } // function to update pucch scheduling parameters in UE list when a USS DL is scheduled -void nr_acknack_scheduling(int Mod_idP, +bool nr_acknack_scheduling(int mod_id, int UE_id, - frame_t frameP, - sub_frame_t slotP, - int slots_per_tdd, - int *pucch_id, - int *pucch_occ) { + frame_t frame, + sub_frame_t slot) +{ + const NR_ServingCellConfigCommon_t *scc = RC.nrmac[mod_id]->common_channels->ServingCellConfigCommon; + const int n_slots_frame = nr_slots_per_frame[*scc->ssbSubcarrierSpacing]; + const NR_TDD_UL_DL_Pattern_t *tdd = &scc->tdd_UL_DL_ConfigurationCommon->pattern1; + const int nr_ulmix_slots = tdd->nrofUplinkSlots + (tdd->nrofUplinkSymbols != 0); + const int nr_mix_slots = tdd->nrofDownlinkSymbols != 0 || tdd->nrofUplinkSymbols != 0; + const int nr_slots_period = tdd->nrofDownlinkSlots + tdd->nrofUplinkSlots + nr_mix_slots; + const int first_ul_slot_tdd = tdd->nrofDownlinkSlots + nr_slots_period * (slot / nr_slots_period); + const int CC_id = 0; - NR_ServingCellConfigCommon_t *scc = RC.nrmac[Mod_idP]->common_channels->ServingCellConfigCommon; - NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info; - NR_sched_pucch *curr_pucch; - int max_acknacks,pucch_res,first_ul_slot_tdd,k,i,l; - uint8_t pdsch_to_harq_feedback[8]; - int found = 0; - int nr_ulmix_slots = scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots; - if (scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols!=0) - nr_ulmix_slots++; + AssertFatal(slot < first_ul_slot_tdd + (tdd->nrofUplinkSymbols != 0), + "cannot handle multiple TDD periods (yet): slot %d first_ul_slot_tdd %d nrofUplinkSlots %ld\n", + slot, + first_ul_slot_tdd, + tdd->nrofUplinkSlots); - bool csi_pres=false; - for (k=0; kUE_sched_ctrl[UE_id].sched_pucch[k][0].csi_bits>0) - csi_pres=true; + /* for the moment, we consider: + * * only pucch_sched[0] holds HARQ (and SR) + * * we do not multiplex with CSI, which is always in pucch_sched[2] + * * SR uses format 0 and is allocated in the first UL (mixed) slot (and not + * later) + * * that the PUCCH resource set 0 (for up to 2 bits) points to the first N + * PUCCH resources, where N is the number of resources in the PUCCH + * resource set. This is used in pucch_index_used, which counts the used + * resources by index, and not by their ID! */ + NR_UE_sched_ctrl_t *sched_ctrl = &RC.nrmac[mod_id]->UE_info.UE_sched_ctrl[UE_id]; + NR_sched_pucch_t *pucch = &sched_ctrl->sched_pucch[0]; + AssertFatal(pucch->csi_bits == 0, + "%s(): csi_bits %d in sched_pucch[0]\n", + __func__, + pucch->csi_bits); + + const int max_acknacks = 2; + AssertFatal(pucch->dai_c + pucch->sr_flag <= max_acknacks, + "illegal number of bits in PUCCH of UE %d\n", + UE_id); + /* if the currently allocated PUCCH of this UE is full, allocate it */ + if (pucch->sr_flag + pucch->dai_c == max_acknacks) { + /* advance the UL slot information in PUCCH by one so we won't schedule in + * the same slot again */ + const int f = pucch->frame; + const int s = pucch->ul_slot; + nr_fill_nfapi_pucch(mod_id, frame, slot, pucch, UE_id); + memset(pucch, 0, sizeof(*pucch)); + pucch->frame = s == n_slots_frame - 1 ? (f + 1) % 1024 : f; + pucch->ul_slot = (s + 1) % n_slots_frame; + // we assume that only two indices over the array sched_pucch exist + const NR_sched_pucch_t *csi_pucch = &sched_ctrl->sched_pucch[2]; + // skip the CSI PUCCH if it is present and if in the next frame/slot + if (csi_pucch->csi_bits > 0 + && csi_pucch->frame == pucch->frame + && csi_pucch->ul_slot == pucch->ul_slot) { + AssertFatal(!csi_pucch->simultaneous_harqcsi, + "%s(): %d.%d cannot handle simultaneous_harqcsi, but found for UE %d\n", + __func__, + pucch->frame, + pucch->ul_slot, + UE_id); + nr_fill_nfapi_pucch(mod_id, frame, slot, csi_pucch, UE_id); + pucch->frame = s >= n_slots_frame - 2 ? (f + 1) % 1024 : f; + pucch->ul_slot = (s + 2) % n_slots_frame; + } } - // As a preference always schedule ack nacks in PUCCH0 (max 2 per slots) - // Unless there is CSI meas reporting scheduled in the period to avoid conflicts in the same slot - if (csi_pres) - max_acknacks=10; - else - max_acknacks=2; + /* if the UE's next PUCCH occasion is after the possible UL slots (within the + * same frame) or wrapped around to the next frame, then we assume there is + * no possible PUCCH allocation anymore */ + if ((pucch->frame == frame + && (pucch->ul_slot >= first_ul_slot_tdd + nr_ulmix_slots)) + || (pucch->frame == frame + 1)) + return false; // this is hardcoded for now as ue specific NR_SearchSpace__searchSpaceType_PR ss_type = NR_SearchSpace__searchSpaceType_PR_ue_Specific; - get_pdsch_to_harq_feedback(Mod_idP,UE_id,ss_type,pdsch_to_harq_feedback); + uint8_t pdsch_to_harq_feedback[8]; + get_pdsch_to_harq_feedback(mod_id, UE_id, ss_type, pdsch_to_harq_feedback); - // for each possible ul or mixed slot - for (k=0; kUE_sched_ctrl[UE_id].sched_pucch[k][l]; - //if it is possible to schedule acknack in current pucch (no exclusive csi pucch) - if ((curr_pucch->csi_bits == 0) || (curr_pucch->simultaneous_harqcsi==true)) { - // if there is free room in current pucch structure - if (curr_pucch->dai_c-1){ - curr_pucch->resource_indicator = pucch_res; - curr_pucch->frame = frameP; - // first pucch occasion in first UL or MIXED slot - first_ul_slot_tdd = scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSlots; - i = 0; - while (i<8 && found == 0) { // look if timing indicator is among allowed values - if (pdsch_to_harq_feedback[i]==(first_ul_slot_tdd+k)-(slotP % slots_per_tdd)) - found = 1; - if (found == 0) i++; - } - if (found == 1) { - // computing slot in which pucch is scheduled - curr_pucch->dai_c++; - curr_pucch->ul_slot = first_ul_slot_tdd + k + (slotP - (slotP % slots_per_tdd)); - curr_pucch->timing_indicator = i; // index in the list of timing indicators - *pucch_id = k; - *pucch_occ = l; - return; - } - } - } - } + /* there is a scheduled SR or HARQ. Check whether we can use it for this + * ACKNACK */ + if (pucch->sr_flag + pucch->dai_c > 0) { + /* this UE already has a PUCCH occasion */ + DevAssert(pucch->frame == frame); + + // Find the right timing_indicator value. + int i = 0; + while (i < 8) { + if (pdsch_to_harq_feedback[i] == pucch->ul_slot - slot) + break; + ++i; + } + if (i >= 8) { + // we cannot reach this timing anymore, allocate and try again + const int f = pucch->frame; + const int s = pucch->ul_slot; + const int n_slots_frame = nr_slots_per_frame[*scc->ssbSubcarrierSpacing]; + nr_fill_nfapi_pucch(mod_id, frame, slot, pucch, UE_id); + memset(pucch, 0, sizeof(*pucch)); + pucch->frame = s == n_slots_frame - 1 ? (f + 1) % 1024 : f; + pucch->ul_slot = (s + 1) % n_slots_frame; + return nr_acknack_scheduling(mod_id, UE_id, frame, slot); + } + + pucch->timing_indicator = i; + pucch->dai_c++; + // retain old resource indicator, and we are good + return true; + } + + /* we need to find a new PUCCH occasion */ + + NR_PUCCH_Config_t *pucch_Config = sched_ctrl->active_ubwp->bwp_Dedicated->pucch_Config->choice.setup; + DevAssert(pucch_Config->resourceToAddModList->list.count > 0); + DevAssert(pucch_Config->resourceSetToAddModList->list.count > 0); + const int n_res = pucch_Config->resourceSetToAddModList->list.array[0]->resourceList.list.count; + int *pucch_index_used = RC.nrmac[mod_id]->pucch_index_used[sched_ctrl->active_ubwp->bwp_Id]; + + /* if time information is outdated (e.g., last PUCCH occasion in last frame), + * set to first possible UL occasion in this frame. Note that if such UE is + * scheduled a lot and used all AckNacks, pucch->frame might have been + * wrapped around to next frame */ + if (frame != pucch->frame || pucch->ul_slot < first_ul_slot_tdd) { + DevAssert(pucch->sr_flag + pucch->dai_c == 0); + AssertFatal(frame + 1 != pucch->frame, + "frame wrap around not handled in %s() yet\n", + __func__); + pucch->frame = frame; + pucch->ul_slot = first_ul_slot_tdd; + } + + // increase to first slot in which PUCCH resources are available + while (pucch_index_used[pucch->ul_slot] >= n_res) { + pucch->ul_slot++; + /* if there is no free resource anymore, abort search */ + if ((pucch->frame == frame + && pucch->ul_slot >= first_ul_slot_tdd + nr_ulmix_slots) + || (pucch->frame == frame + 1)) { + LOG_E(MAC, + "%4d.%2d no free PUCCH resources anymore while searching for UE %d\n", + frame, + slot, + UE_id); + return false; } } - AssertFatal(1==0,"No Uplink slot available in accordance to allowed timing indicator\n"); + + // advance ul_slot if it is not reachable by UE + pucch->ul_slot = max(pucch->ul_slot, slot + pdsch_to_harq_feedback[0]); + + // Find the right timing_indicator value. + int i = 0; + while (i < 8) { + if (pdsch_to_harq_feedback[i] == pucch->ul_slot - slot) + break; + ++i; + } + if (i >= 8) { + LOG_W(MAC, + "%4d.%2d could not find pdsch_to_harq_feedback for UE %d: earliest " + "ack slot %d\n", + frame, + slot, + UE_id, + pucch->ul_slot); + return false; + } + pucch->timing_indicator = i; // index in the list of timing indicators + + pucch->dai_c++; + const int pucch_res = pucch_index_used[pucch->ul_slot]; + pucch->resource_indicator = pucch_res; + pucch_index_used[pucch->ul_slot] += 1; + AssertFatal(pucch_index_used[pucch->ul_slot] <= n_res, + "UE %d in %4d.%2d: pucch_index_used is %d (%d available)\n", + UE_id, + pucch->frame, + pucch->ul_slot, + pucch_index_used[pucch->ul_slot], + n_res); + + /* verify that at that slot and symbol, resources are free. We only do this + * for initialCyclicShift 0 (we assume it always has that one), so other + * initialCyclicShifts can overlap with ICS 0!*/ + const NR_PUCCH_Resource_t *resource = + pucch_Config->resourceToAddModList->list.array[pucch_res]; + DevAssert(resource->format.present == NR_PUCCH_Resource__format_PR_format0); + if (resource->format.choice.format0->initialCyclicShift == 0) { + uint16_t *vrb_map_UL = &RC.nrmac[mod_id]->common_channels[CC_id].vrb_map_UL[pucch->ul_slot * MAX_BWP_SIZE]; + const uint16_t symb = 1 << resource->format.choice.format0->startingSymbolIndex; + AssertFatal((vrb_map_UL[resource->startingPRB] & symb) == 0, + "symbol %x is not free for PUCCH alloc in vrb_map_UL at RB %ld and slot %d\n", + symb, resource->startingPRB, pucch->ul_slot); + vrb_map_UL[resource->startingPRB] |= symb; + } + return true; } -void csi_period_offset(NR_CSI_ReportConfig_t *csirep, +void csi_period_offset(const NR_CSI_ReportConfig_t *csirep, int *period, int *offset) { NR_CSI_ReportPeriodicityAndOffset_PR p_and_o = csirep->reportConfigType.choice.periodic->reportSlotConfig.present; @@ -532,24 +669,6 @@ void csi_period_offset(NR_CSI_ReportConfig_t *csirep, } } - -int get_pucch_resource(NR_UE_info_t *UE_info,int UE_id,int k,int l) { - - // to be updated later, for now simple implementation - // use the second allocation just in case there is csi in the first - // in that case use second resource (for a different symbol) see 9.2 in 38.213 - if (l==1) { - if (UE_info->UE_sched_ctrl[UE_id].sched_pucch[k][0].csi_bits==0) - return -1; - else - return 1; - } - else - return 0; - -} - - uint16_t compute_pucch_prb_size(uint8_t format, uint8_t nr_prbs, uint16_t O_tot, diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 46969b9f61..3720731304 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -33,6 +33,33 @@ #include "executables/softmodem-common.h" #include "common/utils/nr/nr_common.h" +//38.321 Table 6.1.3.1-1 +const uint32_t NR_SHORT_BSR_TABLE[32] = { + 0, 10, 14, 20, 28, 38, 53, 74, + 102, 142, 198, 276, 384, 535, 745, 1038, + 1446, 2014, 2806, 3909, 5446, 7587, 10570, 14726, +20516, 28581, 39818, 55474, 77284, 107669, 150000, 300000 +}; + +//38.321 Table 6.1.3.1-2 +const uint32_t NR_LONG_BSR_TABLE[256] ={ + 0, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 22, 23, 25, 26, + 28, 30, 32, 34, 36, 38, 40, 43, 46, 49, 52, 55, 59, 62, 66, 71, + 75, 80, 85, 91, 97, 103, 110, 117, 124, 132, 141, 150, 160, 170, 181, 193, + 205, 218, 233, 248, 264, 281, 299, 318, 339, 361, 384, 409, 436, 464, 494, 526, + 560, 597, 635, 677, 720, 767, 817, 870, 926, 987, 1051, 1119, 1191, 1269, 1351, 1439, + 1532, 1631, 1737, 1850, 1970, 2098, 2234, 2379, 2533, 2698, 2873, 3059, 3258, 3469, 3694, 3934, + 4189, 4461, 4751, 5059, 5387, 5737, 6109, 6506, 6928, 7378, 7857, 8367, 8910, 9488, 10104, 10760, + 11458, 12202, 12994, 13838, 14736, 15692, 16711, 17795, 18951, 20181, 21491, 22885, 24371, 25953, 27638, 29431, + 31342, 33376, 35543, 37850, 40307, 42923, 45709, 48676, 51836, 55200, 58784, 62599, 66663, 70990, 75598, 80505, + 85730, 91295, 97221, 103532, 110252, 117409, 125030, 133146, 141789, 150992, 160793, 171231, 182345, 194182, 206786, 220209, + 234503, 249725, 265935, 283197, 301579, 321155, 342002, 364202, 387842, 413018, 439827, 468377, 498780, 531156, 565634, 602350, + 641449, 683087, 727427, 774645, 824928, 878475, 935498, 996222, 1060888, 1129752, 1203085, 1281179, 1364342, 1452903, 1547213, 1647644, + 1754595, 1868488, 1989774, 2118933, 2256475, 2402946, 2558924, 2725027, 2901912, 3090279, 3290873, 3504487, 3731968, 3974215, 4232186, 4506902, + 4799451, 5110989, 5442750, 5796046, 6172275, 6572925, 6999582, 7453933, 7937777, 8453028, 9001725, 9586039, 10208280, 10870913, 11576557, 12328006, +13128233, 13980403, 14887889, 15854280, 16883401, 17979324, 19146385, 20389201, 21712690, 23122088, 24622972, 26221280, 27923336, 29735875, 31666069, 33721553, +35910462, 38241455, 40723756, 43367187, 46182206, 49179951, 52372284, 55771835, 59392055, 63247269, 67352729, 71724679, 76380419, 81338368, 162676736, 4294967295 +}; void nr_process_mac_pdu( module_id_t module_idP, @@ -50,7 +77,13 @@ void nr_process_mac_pdu( int pdu_len = mac_pdu_len; uint16_t mac_ce_len, mac_subheader_len, mac_sdu_len; - // log_dump(MAC, pduP, 16, LOG_DUMP_CHAR, "gNB ULSCH payload: "); + NR_UE_info_t *UE_info = &RC.nrmac[module_idP]->UE_info; + int UE_id = find_nr_UE_id(module_idP, rnti); + if (UE_id == -1) { + LOG_E(MAC, "%s() UE_id == -1\n",__func__); + return; + } + NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; // For both DL/UL-SCH // Except: // - UL/DL-SCH: fixed-size MAC CE(known by LCID) @@ -84,6 +117,9 @@ void nr_process_mac_pdu( LOG_D(MAC, "LCID received at gNB side: %d \n", rx_lcid); + unsigned char *ce_ptr; + int n_Lcg = 0; + switch(rx_lcid){ // MAC CE @@ -97,32 +133,25 @@ void nr_process_mac_pdu( case UL_SCH_LCID_CONFIGURED_GRANT_CONFIRMATION: // 38.321 Ch6.1.3.7 break; - case UL_SCH_LCID_S_BSR: - //38.321 section 6.1.3.1 - //fixed length - mac_ce_len =1; - /* Extract short BSR value */ - break; + case UL_SCH_LCID_S_BSR: case UL_SCH_LCID_S_TRUNCATED_BSR: //38.321 section 6.1.3.1 //fixed length mac_ce_len =1; - /* Extract short truncated BSR value */ + /* Extract short BSR value */ + ce_ptr = &pdu_ptr[mac_subheader_len]; + NR_BSR_SHORT *bsr_s = (NR_BSR_SHORT *) ce_ptr; + sched_ctrl->estimated_ul_buffer = 0; + sched_ctrl->estimated_ul_buffer = NR_SHORT_BSR_TABLE[bsr_s->Buffer_size]; + LOG_D(MAC, "SHORT BSR, LCG ID %d, BS Index %d, BS value < %d, est buf %d\n", + bsr_s->LcgID, + bsr_s->Buffer_size, + NR_SHORT_BSR_TABLE[bsr_s->Buffer_size], + sched_ctrl->estimated_ul_buffer); break; case UL_SCH_LCID_L_BSR: - //38.321 section 6.1.3.1 - //variable length - mac_ce_len |= (uint16_t)((NR_MAC_SUBHEADER_SHORT *)pdu_ptr)->L; - mac_subheader_len = 2; - if(((NR_MAC_SUBHEADER_SHORT *)pdu_ptr)->F){ - mac_ce_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pdu_ptr)->L2)<<8; - mac_subheader_len = 3; - } - /* Extract long BSR value */ - break; - case UL_SCH_LCID_L_TRUNCATED_BSR: //38.321 section 6.1.3.1 //variable length @@ -132,9 +161,27 @@ void nr_process_mac_pdu( mac_ce_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pdu_ptr)->L2)<<8; mac_subheader_len = 3; } - /* Extract long truncated BSR value */ - break; + /* Extract long BSR value */ + ce_ptr = &pdu_ptr[mac_subheader_len]; + NR_BSR_LONG *bsr_l = (NR_BSR_LONG *) ce_ptr; + sched_ctrl->estimated_ul_buffer = 0; + n_Lcg = bsr_l->LcgID7 + bsr_l->LcgID6 + bsr_l->LcgID5 + bsr_l->LcgID4 + + bsr_l->LcgID3 + bsr_l->LcgID2 + bsr_l->LcgID1 + bsr_l->LcgID0; + + LOG_D(MAC, "LONG BSR, LCG ID(7-0) %d/%d/%d/%d/%d/%d/%d/%d\n", + bsr_l->LcgID7, bsr_l->LcgID6, bsr_l->LcgID5, bsr_l->LcgID4, + bsr_l->LcgID3, bsr_l->LcgID2, bsr_l->LcgID1, bsr_l->LcgID0); + + for (int n = 0; n < n_Lcg; n++){ + LOG_D(MAC, "LONG BSR, %d/%d (n/n_Lcg), BS Index %d, BS value < %d", + n, n_Lcg, pdu_ptr[mac_subheader_len + 1 + n], + NR_LONG_BSR_TABLE[pdu_ptr[mac_subheader_len + 1 + n]]); + sched_ctrl->estimated_ul_buffer += + NR_LONG_BSR_TABLE[pdu_ptr[mac_subheader_len + 1 + n]]; + } + + break; case UL_SCH_LCID_C_RNTI: //38.321 section 6.1.3.2 @@ -254,17 +301,28 @@ void nr_process_mac_pdu( 1, NULL); + /* Updated estimated buffer when receiving data */ + if (sched_ctrl->estimated_ul_buffer >= mac_sdu_len) + sched_ctrl->estimated_ul_buffer -= mac_sdu_len; + else + sched_ctrl->estimated_ul_buffer = 0; + break; default: - return; - break; + LOG_D(MAC, "Received unknown MAC header (LCID = 0x%02x)\n", rx_lcid); + return; + break; } pdu_ptr += ( mac_subheader_len + mac_ce_len + mac_sdu_len ); pdu_len -= ( mac_subheader_len + mac_ce_len + mac_sdu_len ); if (pdu_len < 0) { LOG_E(MAC, "%s() residual mac pdu length < 0!, pdu_len: %d\n", __func__, pdu_len); + LOG_E(MAC, "MAC PDU "); + for (int i = 0; i < 20; i++) // Only printf 1st - 20nd bytes + printf("%02x ", pdu_ptr[i]); + printf("\n"); return; } } @@ -283,45 +341,51 @@ void handle_nr_ul_harq(module_id_t mod_id, NR_UE_info_t *UE_info = &RC.nrmac[mod_id]->UE_info; NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; - int max_harq_rounds = 4; // TODO define macro - uint8_t hrq_id = crc_pdu->harq_id; - NR_UE_ul_harq_t *cur_harq = &sched_ctrl->ul_harq_processes[hrq_id]; - if (cur_harq->state==ACTIVE_SCHED) { - if (!crc_pdu->tb_crc_status) { - cur_harq->ndi ^= 1; - cur_harq->round = 0; - cur_harq->state = INACTIVE; // passed -> make inactive. can be used by scheduder for next grant - LOG_D(MAC, - "Ulharq id %d crc passed for RNTI %04x\n", - hrq_id, - crc_pdu->rnti); - } else { - cur_harq->round++; - cur_harq->state = ACTIVE_NOT_SCHED; - LOG_D(MAC, - "Ulharq id %d crc failed for RNTI %04x\n", - hrq_id, - crc_pdu->rnti); - } - - if (!(cur_harq->roundndi ^= 1; - cur_harq->state = INACTIVE; // failed after 4 rounds -> make inactive - cur_harq->round = 0; - LOG_D(MAC, - "RNTI %04x: Ulharq id %d crc failed in all rounds\n", - crc_pdu->rnti, - hrq_id); - UE_info->mac_stats[UE_id].ulsch_errors++; - } - return; - } else + int8_t harq_pid = sched_ctrl->feedback_ul_harq.head; + while (crc_pdu->harq_id != harq_pid || harq_pid < 0) { LOG_W(MAC, - "Incorrect ULSCH HARQ PID %d or invalid state %d for RNTI %04x " - "(ignore this warning for RA)\n", - hrq_id, - cur_harq->state, + "Unexpected ULSCH HARQ PID %d (have %d) for RNTI %04x (ignore this warning for RA)\n", + crc_pdu->harq_id, + harq_pid, crc_pdu->rnti); + if (harq_pid < 0) + return; + + remove_front_nr_list(&sched_ctrl->feedback_ul_harq); + sched_ctrl->ul_harq_processes[harq_pid].round++; + add_tail_nr_list(&sched_ctrl->retrans_ul_harq, harq_pid); + harq_pid = sched_ctrl->feedback_ul_harq.head; + } + remove_front_nr_list(&sched_ctrl->feedback_ul_harq); + NR_UE_ul_harq_t *harq = &sched_ctrl->ul_harq_processes[harq_pid]; + DevAssert(harq->is_waiting); + harq->feedback_slot = -1; + harq->is_waiting = false; + if (!crc_pdu->tb_crc_status) { + harq->ndi ^= 1; + harq->round = 0; + LOG_D(MAC, + "Ulharq id %d crc passed for RNTI %04x\n", + harq_pid, + crc_pdu->rnti); + add_tail_nr_list(&sched_ctrl->available_ul_harq, harq_pid); + } else if (harq->round == MAX_HARQ_ROUNDS) { + harq->ndi ^= 1; + harq->round = 0; + LOG_D(MAC, + "RNTI %04x: Ulharq id %d crc failed in all rounds\n", + crc_pdu->rnti, + harq_pid); + UE_info->mac_stats[UE_id].ulsch_errors++; + add_tail_nr_list(&sched_ctrl->available_ul_harq, harq_pid); + } else { + harq->round++; + LOG_D(MAC, + "Ulharq id %d crc failed for RNTI %04x\n", + harq_pid, + crc_pdu->rnti); + add_tail_nr_list(&sched_ctrl->retrans_ul_harq, harq_pid); + } } /* @@ -337,25 +401,21 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP, const uint16_t timing_advance, const uint8_t ul_cqi, const uint16_t rssi){ - int current_rnti = 0, UE_id = -1, harq_pid = 0; - gNB_MAC_INST *gNB_mac = NULL; - NR_UE_info_t *UE_info = NULL; - NR_UE_sched_ctrl_t *UE_scheduling_control = NULL; + gNB_MAC_INST *gNB_mac = RC.nrmac[gnb_mod_idP]; + NR_UE_info_t *UE_info = &gNB_mac->UE_info; - current_rnti = rntiP; - UE_id = find_nr_UE_id(gnb_mod_idP, current_rnti); - gNB_mac = RC.nrmac[gnb_mod_idP]; - UE_info = &gNB_mac->UE_info; - int target_snrx10 = gNB_mac->pusch_target_snrx10; - - if (sduP != NULL) { - T(T_GNB_MAC_UL_PDU_WITH_DATA, T_INT(gnb_mod_idP), T_INT(CC_idP), - T_INT(rntiP), T_INT(frameP), T_INT(slotP), T_INT(-1) /* harq_pid */, - T_BUFFER(sduP, sdu_lenP)); - } + const int current_rnti = rntiP; + const int UE_id = find_nr_UE_id(gnb_mod_idP, current_rnti); + const int target_snrx10 = gNB_mac->pusch_target_snrx10; if (UE_id != -1) { - UE_scheduling_control = &(UE_info->UE_sched_ctrl[UE_id]); + NR_UE_sched_ctrl_t *UE_scheduling_control = &UE_info->UE_sched_ctrl[UE_id]; + const int8_t harq_pid = UE_scheduling_control->feedback_ul_harq.head; + + if (sduP) + T(T_GNB_MAC_UL_PDU_WITH_DATA, T_INT(gnb_mod_idP), T_INT(CC_idP), + T_INT(rntiP), T_INT(frameP), T_INT(slotP), T_INT(harq_pid), + T_BUFFER(sduP, sdu_lenP)); UE_info->mac_stats[UE_id].ulsch_total_bytes_rx += sdu_lenP; LOG_D(MAC, "[gNB %d][PUSCH %d] CC_id %d %d.%d Received ULSCH sdu from PHY (rnti %x, UE_id %d) ul_cqi %d\n", @@ -394,15 +454,32 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP, if (sduP != NULL){ LOG_D(MAC, "Received PDU at MAC gNB \n"); + + const uint32_t tb_size = UE_scheduling_control->ul_harq_processes[harq_pid].sched_pusch.tb_size; + UE_scheduling_control->sched_ul_bytes -= tb_size; + if (UE_scheduling_control->sched_ul_bytes < 0) + UE_scheduling_control->sched_ul_bytes = 0; + nr_process_mac_pdu(gnb_mod_idP, current_rnti, CC_idP, frameP, sduP, sdu_lenP); } else { - + NR_UE_ul_harq_t *cur_harq = &UE_scheduling_control->ul_harq_processes[harq_pid]; + /* reduce sched_ul_bytes when cur_harq->round == 3 */ + if (cur_harq->round == 3){ + const uint32_t tb_size = UE_scheduling_control->ul_harq_processes[harq_pid].sched_pusch.tb_size; + UE_scheduling_control->sched_ul_bytes -= tb_size; + if (UE_scheduling_control->sched_ul_bytes < 0) + UE_scheduling_control->sched_ul_bytes = 0; + } } } else { if (!sduP) // check that CRC passed return; + T(T_GNB_MAC_UL_PDU_WITH_DATA, T_INT(gnb_mod_idP), T_INT(CC_idP), + T_INT(rntiP), T_INT(frameP), T_INT(slotP), T_INT(-1) /* harq_pid */, + T_BUFFER(sduP, sdu_lenP)); + /* we don't know this UE (yet). Check whether there is a ongoing RA (Msg 3) * and check the corresponding UE's RNTI match, in which case we activate * it. */ @@ -419,21 +496,8 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP, current_rnti); continue; } - const int UE_id = add_new_nr_ue(gnb_mod_idP, ra->rnti); - UE_info->secondaryCellGroup[UE_id] = ra->secondaryCellGroup; - compute_csi_bitlen(ra->secondaryCellGroup, UE_info, UE_id); + const int UE_id = add_new_nr_ue(gnb_mod_idP, ra->rnti, ra->secondaryCellGroup); UE_info->UE_beam_index[UE_id] = ra->beam_id; - struct NR_ServingCellConfig__downlinkBWP_ToAddModList *bwpList = ra->secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList; - AssertFatal(bwpList->list.count == 1, - "downlinkBWP_ToAddModList has %d BWP!\n", - bwpList->list.count); - const int bwp_id = 1; - UE_info->UE_sched_ctrl[UE_id].active_bwp = bwpList->list.array[bwp_id - 1]; - struct NR_UplinkConfig__uplinkBWP_ToAddModList *ubwpList = ra->secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList; - AssertFatal(ubwpList->list.count == 1, - "uplinkBWP_ToAddModList has %d BWP!\n", - ubwpList->list.count); - UE_info->UE_sched_ctrl[UE_id].active_ubwp = ubwpList->list.array[bwp_id - 1]; LOG_I(MAC, "[gNB %d][RAPROC] PUSCH with TC_RNTI %x received correctly, " "adding UE MAC Context UE_id %d/RNTI %04x\n", @@ -469,30 +533,256 @@ long get_K2(NR_BWP_Uplink_t *ubwp, int time_domain_assignment, int mu) { return 3; } -int8_t select_ul_harq_pid(NR_UE_sched_ctrl_t *sched_ctrl) { - const uint8_t max_ul_harq_pids = 3; // temp: for testing - // schedule active harq processes - for (uint8_t hrq_id = 0; hrq_id < max_ul_harq_pids; hrq_id++) { - NR_UE_ul_harq_t *cur_harq = &sched_ctrl->ul_harq_processes[hrq_id]; - if (cur_harq->state == ACTIVE_NOT_SCHED) { - LOG_D(MAC, "Found ulharq id %d, scheduling it for retransmission\n", hrq_id); - return hrq_id; - } - } - - // schedule new harq processes - for (uint8_t hrq_id=0; hrq_id < max_ul_harq_pids; hrq_id++) { - NR_UE_ul_harq_t *cur_harq = &sched_ctrl->ul_harq_processes[hrq_id]; - if (cur_harq->state == INACTIVE) { - LOG_D(MAC, "Found new ulharq id %d, scheduling it\n", hrq_id); - return hrq_id; - } - } - LOG_E(MAC, "All UL HARQ processes are busy. Cannot schedule ULSCH\n"); - return -1; +int next_list_entry_looped(NR_list_t *list, int UE_id) +{ + if (UE_id < 0) + return list->head; + return list->next[UE_id] < 0 ? list->head : list->next[UE_id]; } -void nr_simple_ulsch_preprocessor(module_id_t module_id, +float ul_thr_ue[MAX_MOBILES_PER_GNB]; +int bsr0ue = -1; +void pf_ul(module_id_t module_id, + frame_t frame, + sub_frame_t slot, + int num_slots_per_tdd, + NR_list_t *UE_list, + int n_rb_sched, + uint8_t *rballoc_mask, + int max_num_ue) { + + const int CC_id = 0; + const int tda = 1; + NR_ServingCellConfigCommon_t *scc = RC.nrmac[module_id]->common_channels[CC_id].ServingCellConfigCommon; + NR_UE_info_t *UE_info = &RC.nrmac[module_id]->UE_info; + const int min_rb = 5; + float coeff_ue[MAX_MOBILES_PER_GNB]; + // UEs that could be scheduled + int ue_array[MAX_MOBILES_PER_GNB]; + NR_list_t UE_sched = { .head = -1, .next = ue_array, .tail = -1, .len = MAX_MOBILES_PER_GNB }; + + /* Hack: currently, we do not have SR, and need to schedule UEs continuously. + * To keep the wasted resources low, we switch UEs to be scheduled in a + * round-robin fashion below, and only schedule a UE with BSR=0 if it is the + * selected one */ + bsr0ue = next_list_entry_looped(UE_list, bsr0ue); + + /* Loop UE_list to calculate throughput and coeff */ + for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { + NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + int rbStart = NRRIV2PRBOFFSET(sched_ctrl->active_bwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + const uint16_t bwpSize = NRRIV2BW(sched_ctrl->active_ubwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + + /* Calculate throughput */ + const float a = 0.0005f; // corresponds to 200ms window + const uint32_t b = UE_info->mac_stats[UE_id].ulsch_current_bytes; + ul_thr_ue[UE_id] = (1 - a) * ul_thr_ue[UE_id] + a * b; + + /* Save PUSCH field */ + /* we want to avoid a lengthy deduction of DMRS and other parameters in + * every TTI if we can save it, so check whether dci_format, TDA, or + * num_dmrs_cdm_grps_no_data has changed and only then recompute */ + sched_ctrl->sched_pusch.time_domain_allocation = tda; + sched_ctrl->search_space = get_searchspace(sched_ctrl->active_bwp, NR_SearchSpace__searchSpaceType_PR_ue_Specific); + sched_ctrl->coreset = get_coreset(sched_ctrl->active_bwp, sched_ctrl->search_space, 1 /* dedicated */); + const long f = sched_ctrl->search_space->searchSpaceType->choice.ue_Specific->dci_Formats; + const int dci_format = f ? NR_UL_DCI_FORMAT_0_1 : NR_UL_DCI_FORMAT_0_0; + const uint8_t num_dmrs_cdm_grps_no_data = 1; + NR_sched_pusch_save_t *ps = &sched_ctrl->pusch_save; + if (ps->time_domain_allocation != tda + || ps->dci_format != dci_format + || ps->num_dmrs_cdm_grps_no_data != num_dmrs_cdm_grps_no_data) + nr_save_pusch_fields(scc, sched_ctrl->active_ubwp, dci_format, tda, num_dmrs_cdm_grps_no_data, ps); + + /* Check if retransmission is necessary */ + sched_ctrl->sched_pusch.ul_harq_pid = sched_ctrl->retrans_ul_harq.head; + if (sched_ctrl->sched_pusch.ul_harq_pid >= 0) { + /* RETRANSMISSION: Allocate retransmission*/ + /* Find free CCE */ + bool freeCCE = find_free_CCE(module_id, slot, UE_id); + if (!freeCCE) { + LOG_D(MAC, "%4d.%2d no free CCE for retransmission UL DCI UE %04x\n", frame, slot, UE_info->rnti[UE_id]); + continue; + } + /* reduce max_num_ue once we are sure UE can be allocated, i.e., has CCE */ + max_num_ue--; + if (max_num_ue < 0) + return; + + /* Save shced_frame and sched_slot before overwrite by previous PUSCH filed */ + NR_UE_ul_harq_t *cur_harq = &sched_ctrl->ul_harq_processes[sched_ctrl->sched_pusch.ul_harq_pid]; + cur_harq->sched_pusch.frame = sched_ctrl->sched_pusch.frame; + cur_harq->sched_pusch.slot = sched_ctrl->sched_pusch.slot; + /* Get previous PSUCH filed info */ + sched_ctrl->sched_pusch = cur_harq->sched_pusch; + NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch; + LOG_D(MAC, "%4d.%2d Allocate UL retransmission UE %d/RNTI %04x sched %4d.%2d (%d RBs)\n", + frame, slot, UE_id, UE_info->rnti[UE_id], + sched_pusch->frame, sched_pusch->slot, + sched_pusch->rbSize); + + while (rbStart < bwpSize && !rballoc_mask[rbStart]) rbStart++; + if (rbStart + sched_pusch->rbSize >= bwpSize) { + LOG_W(MAC, "cannot allocate UL data for UE %d/RNTI %04x: no resources\n", + UE_id, UE_info->rnti[UE_id]); + return; + } + sched_pusch->rbStart = rbStart; + /* no need to recompute the TBS, it will be the same */ + + /* Mark the corresponding RBs as used */ + n_rb_sched -= sched_pusch->rbSize; + for (int rb = 0; rb < sched_ctrl->sched_pusch.rbSize; rb++) + rballoc_mask[rb + sched_ctrl->sched_pusch.rbStart] = 0; + + continue; + } + + /* Calculate TBS from MCS */ + NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch; + const int mcs = 9; + sched_pusch->mcs = mcs; + sched_pusch->R = nr_get_code_rate_ul(mcs, ps->mcs_table); + sched_pusch->Qm = nr_get_Qm_ul(mcs, ps->mcs_table); + if (ps->pusch_Config->tp_pi2BPSK + && ((ps->mcs_table == 3 && mcs < 2) || (ps->mcs_table == 4 && mcs < 6))) { + sched_pusch->R >>= 1; + sched_pusch->Qm <<= 1; + } + + /* Check BSR and schedule UE if it is zero to avoid starvation, since we do + * not have SR (yet) */ + if (sched_ctrl->estimated_ul_buffer - sched_ctrl->sched_ul_bytes <= 0) { + if (UE_id != bsr0ue) + continue; + /* if no data, pre-allocate 5RB */ + bool freeCCE = find_free_CCE(module_id, slot, UE_id); + if (!freeCCE) { + LOG_D(MAC, "%4d.%2d no free CCE for UL DCI UE %04x (BSR 0)\n", frame, slot, UE_info->rnti[UE_id]); + continue; + } + /* reduce max_num_ue once we are sure UE can be allocated, i.e., has CCE */ + max_num_ue--; + if (max_num_ue < 0) + return; + + while (rbStart < bwpSize && !rballoc_mask[rbStart]) rbStart++; + if (rbStart + min_rb >= bwpSize) { + LOG_W(MAC, "cannot allocate UL data for UE %d/RNTI %04x: no resources\n", + UE_id, UE_info->rnti[UE_id]); + return; + } + sched_pusch->rbStart = rbStart; + sched_pusch->rbSize = min_rb; + sched_pusch->tb_size = nr_compute_tbs(sched_pusch->Qm, + sched_pusch->R, + sched_pusch->rbSize, + ps->nrOfSymbols, + ps->N_PRB_DMRS * ps->num_dmrs_symb, + 0, // nb_rb_oh + 0, + 1 /* NrOfLayers */) + >> 3; + + /* Mark the corresponding RBs as used */ + n_rb_sched -= sched_pusch->rbSize; + for (int rb = 0; rb < sched_ctrl->sched_pusch.rbSize; rb++) + rballoc_mask[rb + sched_ctrl->sched_pusch.rbStart] = 0; + + continue; + } + + /* Create UE_sched for UEs eligibale for new data transmission*/ + add_tail_nr_list(&UE_sched, UE_id); + + /* Calculate coefficient*/ + const uint32_t tbs = nr_compute_tbs(sched_pusch->Qm, + sched_pusch->R, + 1, // rbSize + ps->nrOfSymbols, + ps->N_PRB_DMRS * ps->num_dmrs_symb, + 0, // nb_rb_oh + 0, + 1 /* NrOfLayers */) + >> 3; + coeff_ue[UE_id] = (float) tbs / ul_thr_ue[UE_id]; + LOG_D(MAC,"b %d, ul_thr_ue[%d] %f, tbs %d, coeff_ue[%d] %f\n", + b, UE_id, ul_thr_ue[UE_id], tbs, UE_id, coeff_ue[UE_id]); + } + + + /* Loop UE_sched to find max coeff and allocate transmission */ + while (UE_sched.head >= 0 && max_num_ue> 0 && n_rb_sched > 0) { + /* Find max coeff */ + int *max = &UE_sched.head; /* Find max coeff: assume head is max */ + int *p = &UE_sched.next[*max]; + while (*p >= 0) { + /* Find max coeff: if the current one has larger coeff, save for later */ + if (coeff_ue[*p] > coeff_ue[*max]) + max = p; + p = &UE_sched.next[*p]; + } + /* Find max coeff: remove the max one: do not use remove_nr_list() since it + * goes through the whole list every time. Note that UE_sched.tail might + * not be set correctly anymore */ + const int UE_id = *max; + p = &UE_sched.next[*max]; + *max = UE_sched.next[*max]; + *p = -1; + + bool freeCCE = find_free_CCE(module_id, slot, UE_id); + if (!freeCCE) { + LOG_D(MAC, "%4d.%2d no free CCE for UL DCI UE %04x\n", frame, slot, UE_info->rnti[UE_id]); + continue; + } + + /* reduce max_num_ue once we are sure UE can be allocated, i.e., has CCE */ + max_num_ue--; + if (max_num_ue < 0) + return; + + NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + int rbStart = NRRIV2PRBOFFSET(sched_ctrl->active_bwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + const uint16_t bwpSize = NRRIV2BW(sched_ctrl->active_ubwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch; + + + while (rbStart < bwpSize && !rballoc_mask[rbStart]) rbStart++; + sched_pusch->rbStart = rbStart; + if (rbStart + min_rb >= bwpSize) { + LOG_W(MAC, "cannot allocate UL data for UE %d/RNTI %04x: no resources\n", + UE_id, UE_info->rnti[UE_id]); + return; + } + + /* Calculate the current scheduling bytes */ + const int B = cmax(sched_ctrl->estimated_ul_buffer - sched_ctrl->sched_ul_bytes, 0); + uint16_t rbSize = min_rb - 1; + do { + rbSize++; + sched_pusch->rbSize = rbSize; + sched_pusch->tb_size = nr_compute_tbs(sched_pusch->Qm, + sched_pusch->R, + sched_pusch->rbSize, + sched_ctrl->pusch_save.nrOfSymbols, + sched_ctrl->pusch_save.N_PRB_DMRS * sched_ctrl->pusch_save.num_dmrs_symb, + 0, // nb_rb_oh + 0, + 1 /* NrOfLayers */) + >> 3; + } while (rbStart + rbSize < bwpSize && rballoc_mask[rbStart+rbSize] && + sched_pusch->tb_size < B); + LOG_D(MAC,"rbSize %d, TBS %d, est buf %d, sched_ul %d, B %d\n", + rbSize, sched_pusch->tb_size, sched_ctrl->estimated_ul_buffer, sched_ctrl->sched_ul_bytes, B); + + /* Mark the corresponding RBs as used */ + n_rb_sched -= sched_pusch->rbSize; + for (int rb = 0; rb < sched_ctrl->sched_pusch.rbSize; rb++) + rballoc_mask[rb + sched_ctrl->sched_pusch.rbStart] = 0; + } +} + +bool nr_simple_ulsch_preprocessor(module_id_t module_id, frame_t frame, sub_frame_t slot, int num_slots_per_tdd, @@ -503,17 +793,14 @@ void nr_simple_ulsch_preprocessor(module_id_t module_id, const int mu = scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.subcarrierSpacing; NR_UE_info_t *UE_info = &nr_mac->UE_info; - AssertFatal(UE_info->num_UEs <= 1, - "%s() cannot handle more than one UE, but found %d\n", - __func__, - UE_info->num_UEs); if (UE_info->num_UEs == 0) - return; + return false; - const int UE_id = 0; const int CC_id = 0; - NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + /* NOT support different K2 in here, Get the K2 for first UE */ + int UE_id = UE_info->list.head; + NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; const int tda = 1; const struct NR_PUSCH_TimeDomainResourceAllocationList *tdaList = sched_ctrl->active_ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList; @@ -521,94 +808,59 @@ void nr_simple_ulsch_preprocessor(module_id_t module_id, "time domain assignment %d >= %d\n", tda, tdaList->list.count); - int K2 = get_K2(sched_ctrl->active_ubwp, tda, mu); - const int sched_frame = frame + (slot + K2 >= num_slots_per_tdd); - const int sched_slot = (slot + K2) % num_slots_per_tdd; - if (!is_xlsch_in_slot(ulsch_in_slot_bitmap, sched_slot)) - return; - /* get first, largest unallocated region */ - uint16_t *vrb_map_UL = - &RC.nrmac[module_id]->common_channels[CC_id].vrb_map_UL[sched_slot * 275]; - uint16_t rbStart = 0; - while (vrb_map_UL[rbStart]) rbStart++; - const uint16_t bwpSize = NRRIV2BW(sched_ctrl->active_ubwp->bwp_Common->genericParameters.locationAndBandwidth,275); - uint16_t rbSize = 1; - while (rbStart + rbSize < bwpSize && !vrb_map_UL[rbStart+rbSize]) - rbSize++; + int K2 = get_K2(sched_ctrl->active_ubwp, tda, mu); + const int sched_frame = frame + (slot + K2 >= nr_slots_per_frame[mu]); + const int sched_slot = (slot + K2) % nr_slots_per_frame[mu]; + if (!is_xlsch_in_slot(ulsch_in_slot_bitmap, sched_slot)) + return false; sched_ctrl->sched_pusch.slot = sched_slot; sched_ctrl->sched_pusch.frame = sched_frame; - const int target_ss = NR_SearchSpace__searchSpaceType_PR_ue_Specific; - sched_ctrl->search_space = get_searchspace(sched_ctrl->active_bwp, target_ss); - uint8_t nr_of_candidates; - find_aggregation_candidates(&sched_ctrl->aggregation_level, - &nr_of_candidates, - sched_ctrl->search_space); - sched_ctrl->coreset = get_coreset( - sched_ctrl->active_bwp, sched_ctrl->search_space, 1 /* dedicated */); - const int cid = sched_ctrl->coreset->controlResourceSetId; - const uint16_t Y = UE_info->Y[UE_id][cid][slot]; - const int m = UE_info->num_pdcch_cand[UE_id][cid]; - sched_ctrl->cce_index = allocate_nr_CCEs(RC.nrmac[module_id], - sched_ctrl->active_bwp, - sched_ctrl->coreset, - sched_ctrl->aggregation_level, - Y, - m, - nr_of_candidates); - if (sched_ctrl->cce_index < 0) { - LOG_E(MAC, "%s(): CCE list not empty, couldn't schedule PUSCH\n", __func__); - return; + /* Confirm all the UE have same K2 as the first UE */ + for (UE_id = UE_info->list.next[UE_id]; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { + NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + AssertFatal(K2 == get_K2(sched_ctrl->active_ubwp, tda, mu), + "Different K2, %d(UE%d) != %ld(UE%d)\n", K2, 0, get_K2(sched_ctrl->active_ubwp, tda, mu), UE_id); + sched_ctrl->sched_pusch.slot = sched_slot; + sched_ctrl->sched_pusch.frame = sched_frame; } - UE_info->num_pdcch_cand[UE_id][cid]++; - sched_ctrl->sched_pusch.time_domain_allocation = tda; - const long f = sched_ctrl->search_space->searchSpaceType->choice.ue_Specific->dci_Formats; - const int dci_format = f ? NR_UL_DCI_FORMAT_0_1 : NR_UL_DCI_FORMAT_0_0; - const uint8_t num_dmrs_cdm_grps_no_data = 1; - /* we want to avoid a lengthy deduction of DMRS and other parameters in - * every TTI if we can save it, so check whether dci_format, TDA, or - * num_dmrs_cdm_grps_no_data has changed and only then recompute */ - NR_sched_pusch_save_t *ps = &sched_ctrl->pusch_save; - if (ps->time_domain_allocation != tda - || ps->dci_format != dci_format - || ps->num_dmrs_cdm_grps_no_data != num_dmrs_cdm_grps_no_data) - nr_save_pusch_fields(scc, - sched_ctrl->active_ubwp, - dci_format, - tda, - num_dmrs_cdm_grps_no_data, - ps); - - const int mcs = 9; - NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch; - sched_pusch->mcs = mcs; - sched_pusch->rbStart = rbStart; - sched_pusch->rbSize = rbSize; - - /* Calculate TBS from MCS */ - sched_pusch->R = nr_get_code_rate_ul(mcs, ps->mcs_table); - sched_pusch->Qm = nr_get_Qm_ul(mcs, ps->mcs_table); - if (ps->pusch_Config->tp_pi2BPSK - && ((ps->mcs_table == 3 && mcs < 2) || (ps->mcs_table == 4 && mcs < 6))) { - sched_pusch->R >>= 1; - sched_pusch->Qm <<= 1; + /* Change vrb_map_UL to rballoc_mask */ + uint16_t *vrb_map_UL = + &RC.nrmac[module_id]->common_channels[CC_id].vrb_map_UL[sched_slot * MAX_BWP_SIZE]; + const uint16_t bwpSize = NRRIV2BW(sched_ctrl->active_ubwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + int st = 0, e = 0, len = 0; + for (int i = 0; i < bwpSize; i++) { + while (vrb_map_UL[i] == 1) + i++; + st = i; + while (vrb_map_UL[i] == 0) + i++; + if (i - st > len) { + len = i - st; + e = i - 1; + } } - sched_pusch->tb_size = nr_compute_tbs(sched_pusch->Qm, - sched_pusch->R, - sched_pusch->rbSize, - ps->nrOfSymbols, - ps->N_PRB_DMRS * ps->num_dmrs_symb, - 0, // nb_rb_oh - 0, - 1 /* NrOfLayers */) - >> 3; + st = e - len + 1; - /* mark the corresponding RBs as used */ - for (int rb = 0; rb < sched_ctrl->sched_pusch.rbSize; rb++) - vrb_map_UL[rb + sched_ctrl->sched_pusch.rbStart] = 1; + uint8_t rballoc_mask[bwpSize]; + + /* Calculate mask: if any RB in vrb_map_UL is blocked (1), the current RB will be 0 */ + for (int i = 0; i < bwpSize; i++) + rballoc_mask[i] = i >= st && i <= e; + + /* proportional fair scheduling algorithm */ + pf_ul(module_id, + frame, + slot, + num_slots_per_tdd, + &UE_info->list, + len, + rballoc_mask, + 2); + return true; } void nr_schedule_ulsch(module_id_t module_id, @@ -617,14 +869,32 @@ void nr_schedule_ulsch(module_id_t module_id, int num_slots_per_tdd, int ul_slots, uint64_t ulsch_in_slot_bitmap) { - RC.nrmac[module_id]->pre_processor_ul( + /* Uplink data ONLY can be scheduled when the current slot is downlink slot, + * because we have to schedule the DCI0 first before schedule uplink data */ + if (is_xlsch_in_slot(ulsch_in_slot_bitmap, slot)) { + LOG_D(MAC, "Current slot %d is NOT DL slot, cannot schedule DCI0 for UL data\n", slot); + return; + } + bool do_sched = RC.nrmac[module_id]->pre_processor_ul( module_id, frame, slot, num_slots_per_tdd, ulsch_in_slot_bitmap); + if (!do_sched) + return; + + const int CC_id = 0; + nfapi_nr_ul_dci_request_t *ul_dci_req = &RC.nrmac[module_id]->UL_dci_req[CC_id]; + ul_dci_req->SFN = frame; + ul_dci_req->Slot = slot; + /* a PDCCH PDU groups DCIs per BWP and CORESET. Save a pointer to each + * allocated PDCCH so we can easily allocate UE's DCIs independent of any + * CORESET order */ + nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_bwp_coreset[MAX_NUM_BWP][MAX_NUM_CORESET] = {{0}}; NR_ServingCellConfigCommon_t *scc = RC.nrmac[module_id]->common_channels[0].ServingCellConfigCommon; NR_UE_info_t *UE_info = &RC.nrmac[module_id]->UE_info; - const NR_UE_list_t *UE_list = &UE_info->list; + const NR_list_t *UE_list = &UE_info->list; for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + UE_info->mac_stats[UE_id].ulsch_current_bytes = 0; /* dynamic PUSCH values (RB alloc, MCS, hence R, Qm, TBS) that change in * every TTI are pre-populated by the preprocessor and used below */ NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch; @@ -633,11 +903,29 @@ void nr_schedule_ulsch(module_id_t module_id, uint16_t rnti = UE_info->rnti[UE_id]; - int8_t harq_id = select_ul_harq_pid(sched_ctrl); - if (harq_id < 0) return; + int8_t harq_id = sched_pusch->ul_harq_pid; + if (harq_id < 0) { + /* PP has not selected a specific HARQ Process, get a new one */ + harq_id = sched_ctrl->available_ul_harq.head; + AssertFatal(harq_id >= 0, + "no free HARQ process available for UE %d\n", + UE_id); + remove_front_nr_list(&sched_ctrl->available_ul_harq); + sched_pusch->ul_harq_pid = harq_id; + } else { + /* PP selected a specific HARQ process. Check whether it will be a new + * transmission or a retransmission, and remove from the corresponding + * list */ + if (sched_ctrl->ul_harq_processes[harq_id].round == 0) + remove_nr_list(&sched_ctrl->available_ul_harq, harq_id); + else + remove_nr_list(&sched_ctrl->retrans_ul_harq, harq_id); + } NR_UE_ul_harq_t *cur_harq = &sched_ctrl->ul_harq_processes[harq_id]; - cur_harq->state = ACTIVE_SCHED; - cur_harq->last_tx_slot = sched_pusch->slot; + DevAssert(!cur_harq->is_waiting); + add_tail_nr_list(&sched_ctrl->feedback_ul_harq, harq_id); + cur_harq->feedback_slot = sched_pusch->slot; + cur_harq->is_waiting = true; int rnti_types[2] = { NR_RNTI_C, 0 }; @@ -650,8 +938,12 @@ void nr_schedule_ulsch(module_id_t module_id, UE_info->mac_stats[UE_id].ulsch_rounds[cur_harq->round]++; if (cur_harq->round == 0) { UE_info->mac_stats[UE_id].ulsch_total_bytes_scheduled += sched_pusch->tb_size; + /* Save information on MCS, TBS etc for the current initial transmission + * so we have access to it when retransmitting */ + cur_harq->sched_pusch = *sched_pusch; + sched_ctrl->sched_ul_bytes += sched_pusch->tb_size; } else { - LOG_W(MAC, + LOG_D(MAC, "%d.%2d UL retransmission RNTI %04x sched %d.%2d HARQ PID %d round %d NDI %d\n", frame, slot, @@ -662,6 +954,7 @@ void nr_schedule_ulsch(module_id_t module_id, cur_harq->round, cur_harq->ndi); } + UE_info->mac_stats[UE_id].ulsch_current_bytes = sched_pusch->tb_size; LOG_D(MAC, "%4d.%2d RNTI %04x UL sched %4d.%2d start %d RBS %d MCS %d TBS %d HARQ PID %d round %d NDI %d\n", @@ -701,8 +994,8 @@ void nr_schedule_ulsch(module_id_t module_id, pusch_pdu->handle = 0; //not yet used /* FAPI: BWP */ - pusch_pdu->bwp_size = NRRIV2BW(sched_ctrl->active_ubwp->bwp_Common->genericParameters.locationAndBandwidth,275); - pusch_pdu->bwp_start = NRRIV2PRBOFFSET(sched_ctrl->active_ubwp->bwp_Common->genericParameters.locationAndBandwidth,275); + pusch_pdu->bwp_size = NRRIV2BW(sched_ctrl->active_ubwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + pusch_pdu->bwp_start = NRRIV2PRBOFFSET(sched_ctrl->active_ubwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); pusch_pdu->subcarrier_spacing = sched_ctrl->active_ubwp->bwp_Common->genericParameters.subcarrierSpacing; pusch_pdu->cyclic_prefix = 0; @@ -804,51 +1097,59 @@ void nr_schedule_ulsch(module_id_t module_id, pusch_pdu->pdu_bit_map &= ~PUSCH_PDU_BITMAP_PUSCH_PTRS; // disable PUSCH PTRS } - nfapi_nr_ul_dci_request_t *ul_dci_req = &RC.nrmac[module_id]->UL_dci_req[0]; - ul_dci_req->SFN = frame; - ul_dci_req->Slot = slot; - nfapi_nr_ul_dci_request_pdus_t *ul_dci_request_pdu = &ul_dci_req->ul_dci_pdu_list[ul_dci_req->numPdus]; - memset(ul_dci_request_pdu, 0, sizeof(nfapi_nr_ul_dci_request_pdus_t)); - ul_dci_request_pdu->PDUType = NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE; - ul_dci_request_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdcch_pdu)); - nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = &ul_dci_request_pdu->pdcch_pdu.pdcch_pdu_rel15; - ul_dci_req->numPdus += 1; + /* look up the PDCCH PDU for this BWP and CORESET. If it does not exist, + * create it */ + const int bwpid = sched_ctrl->active_bwp->bwp_Id; + const int coresetid = sched_ctrl->coreset->controlResourceSetId; + nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu = pdcch_pdu_bwp_coreset[bwpid][coresetid]; + if (!pdcch_pdu) { + nfapi_nr_ul_dci_request_pdus_t *ul_dci_request_pdu = &ul_dci_req->ul_dci_pdu_list[ul_dci_req->numPdus]; + memset(ul_dci_request_pdu, 0, sizeof(nfapi_nr_ul_dci_request_pdus_t)); + ul_dci_request_pdu->PDUType = NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE; + ul_dci_request_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdcch_pdu)); + pdcch_pdu = &ul_dci_request_pdu->pdcch_pdu.pdcch_pdu_rel15; + ul_dci_req->numPdus += 1; + nr_configure_pdcch(pdcch_pdu, sched_ctrl->search_space, sched_ctrl->coreset, scc, sched_ctrl->active_bwp); + pdcch_pdu_bwp_coreset[bwpid][coresetid] = pdcch_pdu; + } LOG_D(MAC,"Configuring ULDCI/PDCCH in %d.%d\n", frame,slot); - nr_configure_pdcch(RC.nrmac[0], - pdcch_pdu_rel15, - rnti, - sched_ctrl->search_space, - sched_ctrl->coreset, - scc, - sched_ctrl->active_bwp, - sched_ctrl->aggregation_level, - sched_ctrl->cce_index); + /* Fill PDCCH DL DCI PDU */ + nfapi_nr_dl_dci_pdu_t *dci_pdu = &pdcch_pdu->dci_pdu[pdcch_pdu->numDlDci]; + pdcch_pdu->numDlDci++; + dci_pdu->RNTI = rnti; + if (sched_ctrl->coreset->pdcch_DMRS_ScramblingID && + sched_ctrl->search_space->searchSpaceType->present == NR_SearchSpace__searchSpaceType_PR_ue_Specific) { + dci_pdu->ScramblingId = *sched_ctrl->coreset->pdcch_DMRS_ScramblingID; + dci_pdu->ScramblingRNTI = rnti; + } else { + dci_pdu->ScramblingId = *scc->physCellId; + dci_pdu->ScramblingRNTI = 0; + } + dci_pdu->AggregationLevel = sched_ctrl->aggregation_level; + dci_pdu->CceIndex = sched_ctrl->cce_index; + dci_pdu->beta_PDCCH_1_0 = 0; + dci_pdu->powerControlOffsetSS = 1; - dci_pdu_rel15_t dci_pdu_rel15[MAX_DCI_CORESET]; - memset(dci_pdu_rel15, 0, sizeof(dci_pdu_rel15)); + dci_pdu_rel15_t uldci_payload; + memset(&uldci_payload, 0, sizeof(uldci_payload)); NR_CellGroupConfig_t *secondaryCellGroup = UE_info->secondaryCellGroup[UE_id]; const int n_ubwp = secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.count; - // NOTE: below functions assume that dci_formats is an array corresponding - // to all UL DCIs in the PDCCH, but for us it is a simple int. So before - // having multiple UEs, the below need to be changed (IMO the functions - // should fill for one DCI only and not handle all of them). config_uldci(sched_ctrl->active_ubwp, pusch_pdu, - pdcch_pdu_rel15, - &dci_pdu_rel15[0], - &ps->dci_format, + &uldci_payload, + ps->dci_format, ps->time_domain_allocation, UE_info->UE_sched_ctrl[UE_id].tpc0, n_ubwp, sched_ctrl->active_bwp->bwp_Id); fill_dci_pdu_rel15(scc, secondaryCellGroup, - pdcch_pdu_rel15, - dci_pdu_rel15, - &ps->dci_format, - rnti_types, + dci_pdu, + &uldci_payload, + ps->dci_format, + rnti_types[0], pusch_pdu->bwp_size, sched_ctrl->active_bwp->bwp_Id); diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index a8dbec98f5..3502a11580 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -64,21 +64,9 @@ void clear_nr_nfapi_information(gNB_MAC_INST * gNB, void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frame_rxP, sub_frame_t slot_rxP); -int nr_generate_dlsch_pdu(module_id_t Mod_idP, - NR_UE_sched_ctrl_t *ue_sched_ctl, - unsigned char *sdus_payload, - unsigned char *mac_pdu, - unsigned char num_sdus, - unsigned short *sdu_lengths, - unsigned char *sdu_lcids, - unsigned char drx_cmd, - unsigned char *ue_cont_res_id, - unsigned short post_padding); - void nr_schedule_ue_spec(module_id_t module_id, frame_t frame, - sub_frame_t slot, - int num_slots_per_tdd); + sub_frame_t slot); void schedule_control_sib1(module_id_t module_id, int CC_id, @@ -92,8 +80,7 @@ void schedule_nr_sib1(module_id_t module_idP, frame_t frameP, sub_frame_t subfra /* \brief default preprocessor */ void nr_simple_dlsch_preprocessor(module_id_t module_id, frame_t frame, - sub_frame_t slot, - int num_slots_per_tdd); + sub_frame_t slot); void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP, uint8_t slots_per_frame); @@ -105,7 +92,7 @@ void nr_schedule_ulsch(module_id_t module_id, int ul_slots, uint64_t ulsch_in_slot_bitmap); -void nr_simple_ulsch_preprocessor(module_id_t module_id, +bool nr_simple_ulsch_preprocessor(module_id_t module_id, frame_t frame, sub_frame_t slot, int num_slots_per_tdd, @@ -159,11 +146,10 @@ uint16_t nr_mac_compute_RIV(uint16_t N_RB_DL, uint16_t RBstart, uint16_t Lcrbs); * freq resources */ void nr_preprocessor_phytest(module_id_t module_id, frame_t frame, - sub_frame_t slot, - int num_slots_per_tdd); + sub_frame_t slot); /* \brief UL preprocessor for phytest: schedules UE_id 0 with fixed MCS on a * fixed set of resources */ -void nr_ul_preprocessor_phytest(module_id_t module_id, +bool nr_ul_preprocessor_phytest(module_id_t module_id, frame_t frame, sub_frame_t slot, int num_slots_per_tdd, @@ -173,22 +159,6 @@ void nr_schedule_css_dlsch_phytest(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP); -void nr_fill_nfapi_dl_pdu(int Mod_id, - nfapi_nr_dl_tti_request_body_t *dl_req, - rnti_t rnti, - NR_CellGroupConfig_t *secondaryCellGroup, - NR_UE_sched_ctrl_t *sched_ctrl, - NR_sched_pucch *pucch_sched, - nfapi_nr_dmrs_type_e dmrsConfigType, - uint16_t R, - uint8_t Qm, - uint32_t tbs, - int StartSymbolIndex, - int NrOfSymbols, - int harq_pid, - int ndi, - int round); - void handle_nr_uci_pucch_0_1(module_id_t mod_id, frame_t frame, sub_frame_t slot, @@ -199,40 +169,30 @@ void handle_nr_uci_pucch_2_3_4(module_id_t mod_id, const nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_234); -void config_uldci(NR_BWP_Uplink_t *ubwp, - nfapi_nr_pusch_pdu_t *pusch_pdu, - nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15, +void config_uldci(const NR_BWP_Uplink_t *ubwp, + const nfapi_nr_pusch_pdu_t *pusch_pdu, dci_pdu_rel15_t *dci_pdu_rel15, - int *dci_formats, - int time_domain_assignment, uint8_t tpc, - int n_ubwp, int bwp_id); + int dci_format, + int time_domain_assignment, + uint8_t tpc, + int n_ubwp, + int bwp_id); void nr_schedule_pucch(int Mod_idP, - int UE_id, - int nr_ulmix_slots, frame_t frameP, sub_frame_t slotP); -void csi_period_offset(NR_CSI_ReportConfig_t *csirep, +void csi_period_offset(const NR_CSI_ReportConfig_t *csirep, int *period, int *offset); void nr_csi_meas_reporting(int Mod_idP, + frame_t frameP, + sub_frame_t slotP); + +bool nr_acknack_scheduling(int Mod_idP, int UE_id, frame_t frameP, - sub_frame_t slotP, - int slots_per_tdd, - int ul_slots, - int n_slots_frame); - -void nr_acknack_scheduling(int Mod_idP, - int UE_id, - frame_t frameP, - sub_frame_t slotP, - int slots_per_tdd, - int *pucch_id, - int *pucch_occ); - -int get_pucch_resource(NR_UE_info_t *UE_info,int UE_id,int k,int l); + sub_frame_t slotP); void get_pdsch_to_harq_feedback(int Mod_idP, int UE_id, @@ -271,26 +231,22 @@ void find_search_space(int ss_type, NR_BWP_Downlink_t *bwp, NR_SearchSpace_t *ss); -void nr_configure_pdcch(gNB_MAC_INST *nr_mac, - nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu, - uint16_t rnti, +void nr_configure_pdcch(nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu, NR_SearchSpace_t *ss, NR_ControlResourceSet_t *coreset, NR_ServingCellConfigCommon_t *scc, - NR_BWP_Downlink_t *bwp, - uint8_t aggregation_level, - int CCEIndex); + NR_BWP_Downlink_t *bwp); -void fill_dci_pdu_rel15(NR_ServingCellConfigCommon_t *scc, - NR_CellGroupConfig_t *secondaryCellGroup, - nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15, +void fill_dci_pdu_rel15(const NR_ServingCellConfigCommon_t *scc, + const NR_CellGroupConfig_t *secondaryCellGroup, + nfapi_nr_dl_dci_pdu_t *pdcch_dci_pdu, dci_pdu_rel15_t *dci_pdu_rel15, - int *dci_formats, - int *rnti_types, + int dci_formats, + int rnti_types, int N_RB, int bwp_id); -void prepare_dci(NR_CellGroupConfig_t *secondaryCellGroup, +void prepare_dci(const NR_CellGroupConfig_t *secondaryCellGroup, dci_pdu_rel15_t *dci_pdu_rel15, nr_dci_format_t format, int bwp_id); @@ -337,14 +293,21 @@ int NRRIV2BW(int locationAndBandwidth,int N_RB); int NRRIV2PRBOFFSET(int locationAndBandwidth,int N_RB); -void dump_nr_ue_list(NR_UE_list_t *listP); -void add_nr_ue_list(NR_UE_list_t *listP, int UE_id); +/* Functions to manage an NR_list_t */ +void dump_nr_list(NR_list_t *listP); +void create_nr_list(NR_list_t *listP, int len); +void destroy_nr_list(NR_list_t *list); +void add_nr_list(NR_list_t *listP, int id); +void remove_nr_list(NR_list_t *listP, int id); +void add_tail_nr_list(NR_list_t *listP, int id); +void add_front_nr_list(NR_list_t *listP, int id); +void remove_front_nr_list(NR_list_t *listP); int find_nr_UE_id(module_id_t mod_idP, rnti_t rntiP); int find_nr_RA_id(module_id_t mod_idP, int CC_idP, rnti_t rntiP); -int add_new_nr_ue(module_id_t mod_idP, rnti_t rntiP); +int add_new_nr_ue(module_id_t mod_idP, rnti_t rntiP, NR_CellGroupConfig_t *secondaryCellGroup); void mac_remove_nr_ue(module_id_t mod_id, rnti_t rnti); @@ -383,11 +346,7 @@ void config_nr_mib(int Mod_idP, int cellBarred, int intraFreqReselection); - -void nr_generate_Msg2(module_id_t module_idP, - int CC_id, - frame_t frameP, - sub_frame_t slotP); +void nr_generate_Msg2(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t slotP, NR_RA_t *ra); void nr_process_mac_pdu( module_id_t module_idP, @@ -438,4 +397,5 @@ int16_t ssb_index_from_prach(module_id_t module_idP, void find_SSB_and_RO_available(module_id_t module_idP); +bool find_free_CCE(module_id_t module_id, sub_frame_t slot, int UE_id); #endif /*__LAYER2_NR_MAC_PROTO_H__*/ diff --git a/openair2/LAYER2/NR_MAC_gNB/main.c b/openair2/LAYER2/NR_MAC_gNB/main.c index f3ce94d9c6..2c156bb571 100644 --- a/openair2/LAYER2/NR_MAC_gNB/main.c +++ b/openair2/LAYER2/NR_MAC_gNB/main.c @@ -113,18 +113,9 @@ void mac_top_init_gNB(void) UE_info = &nrmac->UE_info; UE_info->num_UEs = 0; - UE_info->list.head = -1; + create_nr_list(&UE_info->list, MAX_MOBILES_PER_GNB); for (list_el = 0; list_el < MAX_MOBILES_PER_GNB; list_el++) { - UE_info->list.next[list_el] = -1; UE_info->active[list_el] = false; - for (int list_harq = 0; list_harq < NR_MAX_NB_HARQ_PROCESSES; list_harq++) { - UE_info->UE_sched_ctrl[list_el].harq_processes[list_harq].round = 0; - UE_info->UE_sched_ctrl[list_el].harq_processes[list_harq].ndi = 0; - UE_info->UE_sched_ctrl[list_el].harq_processes[list_harq].is_waiting = 0; - UE_info->UE_sched_ctrl[list_el].ul_harq_processes[list_harq].round = 0; - UE_info->UE_sched_ctrl[list_el].ul_harq_processes[list_harq].ndi = 0; - UE_info->UE_sched_ctrl[list_el].ul_harq_processes[list_harq].state = 0; - } } } diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index 5f14a9db78..63587d58a4 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -75,10 +75,20 @@ #define MAX_NUM_BWP 2 #define MAX_NUM_CORESET 2 #define MAX_NUM_CCE 90 +#define MAX_HARQ_ROUNDS 4 /*!\brief Maximum number of random access process */ #define NR_NB_RA_PROC_MAX 4 #define MAX_NUM_OF_SSB 64 +/*! \brief NR_list_t is a "list" (of users, HARQ processes, slices, ...). + * Especially useful in the scheduler and to keep "classes" of users. */ +typedef struct { + int head; + int *next; + int tail; + int len; +} NR_list_t; + typedef enum { RA_IDLE = 0, Msg2 = 1, @@ -184,8 +194,6 @@ typedef struct { uint32_t PCCH_alloc_pdu; /// Outgoing PCCH pdu for PHY PCCH_PDU PCCH_pdu; - /// Outgoing RAR pdu for PHY - RAR_PDU RAR_pdu; /// Template for RA computations NR_RA_t ra[NR_NB_RA_PROC_MAX]; /// VRB map for common channels @@ -205,6 +213,8 @@ typedef struct { uint8_t max_association_period; //SSB index uint8_t ssb_index[MAX_NUM_OF_SSB]; + //CB preambles for each SSB + uint8_t cb_preambles_per_ssb; } NR_COMMON_channels_t; @@ -282,7 +292,7 @@ typedef struct NR_sched_pucch { uint8_t dai_c; uint8_t timing_indicator; uint8_t resource_indicator; -} NR_sched_pucch; +} NR_sched_pucch_t; /* this struct is a helper: as long as the TDA and DCI format remain the same * over the same uBWP and search space, there is no need to recalculate all @@ -326,13 +336,20 @@ typedef struct NR_sched_pusch { uint16_t R; uint8_t Qm; uint32_t tb_size; + + /// UL HARQ PID to use for this UE, or -1 for "any new" + int8_t ul_harq_pid; } NR_sched_pusch_t; typedef struct NR_UE_harq { - uint8_t is_waiting; + bool is_waiting; uint8_t ndi; uint8_t round; uint16_t feedback_slot; + + /* Transport block to be sent using this HARQ process */ + uint32_t tb[16384]; + uint32_t tb_size; } NR_UE_harq_t; typedef struct NR_UE_old_sched { @@ -350,10 +367,13 @@ typedef enum { } NR_UL_harq_states_t; typedef struct NR_UE_ul_harq { + bool is_waiting; uint8_t ndi; uint8_t round; - uint16_t last_tx_slot; - NR_UL_harq_states_t state; + uint16_t feedback_slot; + + /// sched_pusch keeps information on MCS etc used for the initial transmission + NR_sched_pusch_t sched_pusch; } NR_UE_ul_harq_t; @@ -387,10 +407,12 @@ typedef struct { /// the currently active BWP in UL NR_BWP_Uplink_t *active_ubwp; - NR_sched_pucch **sched_pucch; - /// selected PUCCH index, if scheduled - int pucch_sched_idx; - int pucch_occ_idx; + /// PUCCH scheduling information. Array of three, we assume for the moment: + /// HARQ in the first field, SR in second, CSI in third (as fixed by RRC + /// conf., i.e. if actually present). The order is important for + /// nr_acknack_scheduling()! + NR_sched_pucch_t sched_pucch[3]; + NR_sched_pusch_save_t pusch_save; NR_sched_pusch_t sched_pusch; @@ -404,6 +426,11 @@ typedef struct { uint16_t rbSize; uint16_t rbStart; + /// uplink bytes that are currently scheduled + int sched_ul_bytes; + /// estimation of the UL buffer size + int estimated_ul_buffer; + // time-domain allocation for scheduled RBs int time_domain_allocation; @@ -414,6 +441,8 @@ typedef struct { /// Retransmission-related information NR_UE_ret_info_t retInfo[NR_MAX_NB_HARQ_PROCESSES]; + /// DL HARQ PID to use for this UE, or -1 for "any new" + int8_t dl_harq_pid; uint16_t ta_frame; int16_t ta_update; @@ -421,8 +450,22 @@ typedef struct { uint8_t tpc0; uint8_t tpc1; uint16_t ul_rssi; + /// information about every HARQ process NR_UE_harq_t harq_processes[NR_MAX_NB_HARQ_PROCESSES]; + /// HARQ processes that are free + NR_list_t available_dl_harq; + /// HARQ processes that await feedback + NR_list_t feedback_dl_harq; + /// HARQ processes that await retransmission + NR_list_t retrans_dl_harq; + /// information about every UL HARQ process NR_UE_ul_harq_t ul_harq_processes[NR_MAX_NB_HARQ_PROCESSES]; + /// UL HARQ processes that are free + NR_list_t available_ul_harq; + /// UL HARQ processes that await feedback + NR_list_t feedback_ul_harq; + /// UL HARQ processes that await retransmission + NR_list_t retrans_ul_harq; int dummy; NR_UE_mac_ce_ctrl_t UE_mac_ce_ctrl;// MAC CE related information } NR_UE_sched_ctrl_t; @@ -438,22 +481,15 @@ typedef struct { int dlsch_rounds[8]; int dlsch_errors; int dlsch_total_bytes; + int dlsch_current_bytes; int ulsch_rounds[8]; int ulsch_errors; int ulsch_total_bytes_scheduled; int ulsch_total_bytes_rx; + int ulsch_current_bytes; } NR_mac_stats_t; - -/*! \brief UNR_E_list_t is a "list" of users within UE_info_t. Especial useful in - * the scheduler and to keep "classes" of users. */ -typedef struct { - int head; - int next[MAX_MOBILES_PER_GNB]; -} NR_UE_list_t; - - /*! \brief UE list used by gNB to order UEs/CC for scheduling*/ #define MAX_CSI_REPORTCONFIG 48 typedef struct { @@ -461,7 +497,7 @@ typedef struct { nr_csi_report_t csi_report_template[MAX_MOBILES_PER_GNB][MAX_CSI_REPORTCONFIG]; NR_UE_sched_ctrl_t UE_sched_ctrl[MAX_MOBILES_PER_GNB]; NR_mac_stats_t mac_stats[MAX_MOBILES_PER_GNB]; - NR_UE_list_t list; + NR_list_t list; int num_UEs; bool active[MAX_MOBILES_PER_GNB]; @@ -477,9 +513,8 @@ typedef struct { typedef void (*nr_pp_impl_dl)(module_id_t mod_id, frame_t frame, - sub_frame_t slot, - int num_slots_per_tdd); -typedef void (*nr_pp_impl_ul)(module_id_t mod_id, + sub_frame_t slot); +typedef bool (*nr_pp_impl_ul)(module_id_t mod_id, frame_t frame, sub_frame_t slot, int num_slots_per_tdd, @@ -510,6 +545,10 @@ typedef struct gNB_MAC_INST_s { nfapi_nr_config_request_scf_t config[NFAPI_CC_MAX]; /// NFAPI DL Config Request Structure nfapi_nr_dl_tti_request_t DL_req[NFAPI_CC_MAX]; + /// a PDCCH PDU groups DCIs per BWP and CORESET. The following structure + /// keeps pointers to PDCCH PDUs within DL_req so that we can easily track + /// PDCCH PDUs per CC/BWP/CORESET + nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_idx[NFAPI_CC_MAX][MAX_NUM_BWP][MAX_NUM_CORESET]; /// NFAPI UL TTI Request Structure, simple pointer into structure /// UL_tti_req_ahead for current frame/slot nfapi_nr_ul_tti_request_t *UL_tti_req[NFAPI_CC_MAX]; @@ -550,6 +589,10 @@ typedef struct gNB_MAC_INST_s { time_stats_t schedule_pch; /// CCE lists int cce_list[MAX_NUM_BWP][MAX_NUM_CORESET][MAX_NUM_CCE]; + /// PUCCH: keep track of the resources has already been used by saving the + /// highest index not yet been used in a given slot. Dynamically allocated + /// so we can have it for every slot as a function of the numerology + int *pucch_index_used[MAX_NUM_BWP]; /// DL preprocessor for differentiated scheduling nr_pp_impl_dl pre_processor_dl; diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp.c b/openair2/LAYER2/PDCP_v10.1.0/pdcp.c index 8196d2b1fc..ee2711c6ef 100644 --- a/openair2/LAYER2/PDCP_v10.1.0/pdcp.c +++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp.c @@ -2098,8 +2098,7 @@ pdcp_config_set_security( } //----------------------------------------------------------------------------- -void -rrc_pdcp_config_req ( +void rrc_pdcp_config_req ( const protocol_ctxt_t *const ctxt_pP, const srb_flag_t srb_flagP, const uint32_t actionP, diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c index 8098d3fde8..514f10a94b 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c @@ -22,12 +22,12 @@ #include "nr_pdcp_entity.h" #include "nr_pdcp_entity_drb_am.h" -#include "nr_pdcp_entity_srb.h" +#include "nr_pdcp_security_nea2.h" #include "LOG/log.h" nr_pdcp_entity_t *new_nr_pdcp_entity_srb( - int rb_id, + int is_gnb, int rb_id, void (*deliver_sdu)(void *deliver_sdu_data, struct nr_pdcp_entity_t *entity, char *buf, int size), void *deliver_sdu_data, @@ -64,7 +64,7 @@ nr_pdcp_entity_t *new_nr_pdcp_entity_srb( } nr_pdcp_entity_t *new_nr_pdcp_entity_drb_am( - int rb_id, + int is_gnb, int rb_id, void (*deliver_sdu)(void *deliver_sdu_data, struct nr_pdcp_entity_t *entity, char *buf, int size), void *deliver_sdu_data, @@ -73,7 +73,11 @@ nr_pdcp_entity_t *new_nr_pdcp_entity_drb_am( void *deliver_pdu_data, int sn_size, int t_reordering, - int discard_timer) + int discard_timer, + int ciphering_algorithm, + int integrity_algorithm, + unsigned char *ciphering_key, + unsigned char *integrity_key) { nr_pdcp_entity_drb_am_t *ret; @@ -102,5 +106,25 @@ nr_pdcp_entity_t *new_nr_pdcp_entity_drb_am( ret->common.maximum_nr_pdcp_sn = (1 << sn_size) - 1; + if (ciphering_key != NULL && ciphering_algorithm != 0) { + if (ciphering_algorithm != 2) { + LOG_E(PDCP, "FATAL: only nea2 supported for the moment\n"); + exit(1); + } + ret->common.has_ciphering = 1; + ret->common.ciphering_algorithm = ciphering_algorithm; + memcpy(ret->common.ciphering_key, ciphering_key, 16); + + ret->common.security_context = nr_pdcp_security_nea2_init(ciphering_key); + ret->common.cipher = nr_pdcp_security_nea2_cipher; + ret->common.free_security = nr_pdcp_security_nea2_free_security; + } + ret->common.is_gnb = is_gnb; + + if (integrity_key != NULL) { + printf("%s:%d:%s: TODO\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + return (nr_pdcp_entity_t *)ret; } diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h index 0e5b645dd1..6e5f231c0a 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h @@ -43,10 +43,28 @@ typedef struct nr_pdcp_entity_t { int tx_hfn; int next_nr_pdcp_tx_sn; int maximum_nr_pdcp_sn; + + /* security */ + int has_ciphering; + int has_integrity; + int ciphering_algorithm; + int integrity_algorithm; + unsigned char ciphering_key[16]; + unsigned char integrity_key[16]; + void *security_context; + void (*cipher)(void *security_context, + unsigned char *buffer, int length, + int bearer, int count, int direction); + void (*free_security)(void *security_context); + /* security algorithms need to know uplink/downlink information + * which is reverse for gnb and ue, so we need to know if this + * pdcp entity is for a gnb or an ue + */ + int is_gnb; } nr_pdcp_entity_t; nr_pdcp_entity_t *new_nr_pdcp_entity_srb( - int rb_id, + int is_gnb, int rb_id, void (*deliver_sdu)(void *deliver_sdu_data, struct nr_pdcp_entity_t *entity, char *buf, int size), void *deliver_sdu_data, @@ -55,7 +73,7 @@ nr_pdcp_entity_t *new_nr_pdcp_entity_srb( void *deliver_pdu_data); nr_pdcp_entity_t *new_nr_pdcp_entity_drb_am( - int rb_id, + int is_gnb, int rb_id, void (*deliver_sdu)(void *deliver_sdu_data, struct nr_pdcp_entity_t *entity, char *buf, int size), void *deliver_sdu_data, @@ -64,7 +82,11 @@ nr_pdcp_entity_t *new_nr_pdcp_entity_drb_am( void *deliver_pdu_data, int sn_size, int t_reordering, - int discard_timer); + int discard_timer, + int ciphering_algorithm, + int integrity_algorithm, + unsigned char *ciphering_key, + unsigned char *integrity_key); void nr_DRB_preconfiguration(uint16_t crnti); diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity_drb_am.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity_drb_am.c index 328f5b4b7d..3472b36396 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity_drb_am.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity_drb_am.c @@ -29,10 +29,27 @@ void nr_pdcp_entity_drb_am_recv_pdu( protocol_ctxt_t *ctxt_pP , nr_pdcp_entity_t *_entity, char *buffer, int size) { nr_pdcp_entity_drb_am_t *entity = (nr_pdcp_entity_drb_am_t *)_entity; + int sn; if (size < 3) abort(); +<<<<<<< HEAD if (!(buffer[0] & 0x80)) { printf("%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); exit(1); } entity->common.deliver_sdu(ctxt_pP, entity->common.deliver_sdu_data, +======= + + if (!(buffer[0] & 0x80)) + LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + + sn = (((unsigned char)buffer[0] & 0x3) << 16) | + ((unsigned char)buffer[1] << 8) | + (unsigned char)buffer[2]; + + if (entity->common.has_ciphering) + entity->common.cipher(entity->common.security_context, (unsigned char *)buffer+3, size-3, + entity->rb_id, sn, entity->common.is_gnb ? 0 : 1); + + entity->common.deliver_sdu(entity->common.deliver_sdu_data, +>>>>>>> origin/develop (nr_pdcp_entity_t *)entity, buffer+3, size-3); } @@ -56,6 +73,10 @@ void nr_pdcp_entity_drb_am_recv_sdu(nr_pdcp_entity_t *_entity, char *buffer, int buf[2] = sn & 0xff; memcpy(buf+3, buffer, size); + if (entity->common.has_ciphering) + entity->common.cipher(entity->common.security_context, (unsigned char *)buf+3, size, + entity->rb_id, sn, entity->common.is_gnb ? 1 : 0); + entity->common.deliver_pdu(entity->common.deliver_pdu_data, (nr_pdcp_entity_t *)entity, buf, size+3, sdu_id); } @@ -68,5 +89,7 @@ void nr_pdcp_entity_drb_am_set_integrity_key(nr_pdcp_entity_t *_entity, char *ke void nr_pdcp_entity_drb_am_delete(nr_pdcp_entity_t *_entity) { nr_pdcp_entity_drb_am_t *entity = (nr_pdcp_entity_drb_am_t *)_entity; + if (entity->common.free_security != NULL) + entity->common.free_security(entity->common.security_context); free(entity); } diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c index 37c498ffc2..b2b75729de 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c @@ -306,7 +306,7 @@ static void *enb_tun_read_thread(void *_) exit(1); } -printf("\n\n\n########## nas_sock_fd read returns len %d\n", len); + LOG_D(PDCP, "%s(): nas_sock_fd read returns len %d\n", __func__, len); nr_pdcp_manager_lock(nr_pdcp_ue_manager); rnti = nr_pdcp_get_first_rnti(nr_pdcp_ue_manager); @@ -356,7 +356,7 @@ static void *ue_tun_read_thread(void *_) exit(1); } -printf("\n\n\n########## nas_sock_fd read returns len %d\n", len); + LOG_D(PDCP, "%s(): nas_sock_fd read returns len %d\n", __func__, len); nr_pdcp_manager_lock(nr_pdcp_ue_manager); rnti = nr_pdcp_get_first_rnti(nr_pdcp_ue_manager); @@ -876,7 +876,11 @@ static void add_srb(int rnti, struct NR_SRB_ToAddMod *s) nr_pdcp_manager_unlock(nr_pdcp_ue_manager); } -static void add_drb_am(int rnti, struct NR_DRB_ToAddMod *s) +static void add_drb_am(int is_gnb, int rnti, struct NR_DRB_ToAddMod *s, + int ciphering_algorithm, + int integrity_algorithm, + unsigned char *ciphering_key, + unsigned char *integrity_key) { nr_pdcp_entity_t *pdcp_drb; nr_pdcp_ue_t *ue; @@ -906,8 +910,11 @@ static void add_drb_am(int rnti, struct NR_DRB_ToAddMod *s) LOG_D(PDCP, "%s:%d:%s: warning DRB %d already exist for ue %d, do nothing\n", __FILE__, __LINE__, __FUNCTION__, drb_id, rnti); } else { - pdcp_drb = new_nr_pdcp_entity_drb_am(drb_id, deliver_sdu_drb, ue, deliver_pdu_drb, ue, - sn_size_dl, t_reordering, discard_timer); + pdcp_drb = new_nr_pdcp_entity_drb_am(is_gnb, drb_id, + deliver_sdu_drb, ue, deliver_pdu_drb, ue, + sn_size_dl, t_reordering, discard_timer, + ciphering_algorithm, integrity_algorithm, + ciphering_key, integrity_key); nr_pdcp_ue_add_drb_pdcp_entity(ue, drb_id, pdcp_drb); LOG_D(PDCP, "%s:%d:%s: added drb %d to ue rnti %x\n", __FILE__, __LINE__, __FUNCTION__, drb_id, rnti); @@ -915,16 +922,23 @@ static void add_drb_am(int rnti, struct NR_DRB_ToAddMod *s) nr_pdcp_manager_unlock(nr_pdcp_ue_manager); } -static void add_drb(int rnti, struct NR_DRB_ToAddMod *s, NR_RLC_Config_t *rlc_Config) +static void add_drb(int is_gnb, int rnti, struct NR_DRB_ToAddMod *s, + NR_RLC_Config_t *rlc_Config, + int ciphering_algorithm, + int integrity_algorithm, + unsigned char *ciphering_key, + unsigned char *integrity_key) { switch (rlc_Config->present) { case NR_RLC_Config_PR_am: - add_drb_am(rnti, s); + add_drb_am(is_gnb, rnti, s, ciphering_algorithm, integrity_algorithm, + ciphering_key, integrity_key); break; case NR_RLC_Config_PR_um_Bi_Directional: //add_drb_um(rnti, s); /* hack */ - add_drb_am(rnti, s); + add_drb_am(is_gnb, rnti, s, ciphering_algorithm, integrity_algorithm, + ciphering_key, integrity_key); break; default: LOG_E(PDCP, "%s:%d:%s: fatal: unhandled DRB type\n", @@ -942,7 +956,8 @@ boolean_t nr_rrc_pdcp_config_asn1_req( const uint8_t security_modeP, uint8_t *const kRRCenc, uint8_t *const kRRCint, - uint8_t *const kUPenc + uint8_t *const kUPenc, + uint8_t *const kUPint #if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0)) ,LTE_PMCH_InfoList_r9_t *pmch_InfoList_r9 #endif @@ -961,7 +976,7 @@ boolean_t nr_rrc_pdcp_config_asn1_req( //srb2add_list == NULL || //drb2add_list != NULL || drb2release_list != NULL || - security_modeP != 255 || + //security_modeP != 255 || //kRRCenc != NULL || //kRRCint != NULL || //kUPenc != NULL || @@ -978,7 +993,10 @@ boolean_t nr_rrc_pdcp_config_asn1_req( if ((drb2add_list != NULL) && (rlc_bearer2add_list != NULL)) { for (i = 0; i < drb2add_list->list.count; i++) { - add_drb(rnti, drb2add_list->list.array[i], rlc_bearer2add_list->list.array[i]->rlc_Config); + add_drb(ctxt_pP->enb_flag, rnti, drb2add_list->list.array[i], + rlc_bearer2add_list->list.array[i]->rlc_Config, + security_modeP & 0x0f, (security_modeP >> 4) & 0x0f, + kUPenc, kUPint); } } @@ -990,6 +1008,7 @@ boolean_t nr_rrc_pdcp_config_asn1_req( free(kRRCenc); free(kRRCint); free(kUPenc); + free(kUPint); return 0; } @@ -1102,6 +1121,7 @@ void nr_DRB_preconfiguration(uint16_t crnti) NULL, NULL, NULL, + NULL, Rlc_Bearer_ToAdd_list); } diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_security_nea2.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_security_nea2.c new file mode 100644 index 0000000000..fc07f661dd --- /dev/null +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_security_nea2.c @@ -0,0 +1,65 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include "nr_pdcp_security_nea2.h" + +#include +#include +#include +#include +#include + +void *nr_pdcp_security_nea2_init(unsigned char *ciphering_key) +{ + void *ctx = calloc(1, nettle_aes128.context_size); + if (ctx == NULL) exit(1); + +#if NETTLE_VERSION_MAJOR < 3 + nettle_aes128.set_encrypt_key(ctx, 16, ciphering_key); +#else + nettle_aes128.set_encrypt_key(ctx, ciphering_key); +#endif + + return ctx; +} + +void nr_pdcp_security_nea2_cipher(void *security_context, + unsigned char *buffer, int length, + int bearer, int count, int direction) +{ + unsigned char t[16]; + + t[0] = (count >> 24) & 255; + t[1] = (count >> 16) & 255; + t[2] = (count >> 8) & 255; + t[3] = (count ) & 255; + t[4] = ((bearer-1) << 3) | (direction << 2); + memset(&t[5], 0, 16-5); + + nettle_ctr_crypt(security_context, nettle_aes128.encrypt, + nettle_aes128.block_size, t, + length, buffer, buffer); +} + +void nr_pdcp_security_nea2_free_security(void *security_context) +{ + free(security_context); +} diff --git a/openair2/LAYER2/NR_MAC_UE/mac.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_security_nea2.h similarity index 64% rename from openair2/LAYER2/NR_MAC_UE/mac.h rename to openair2/LAYER2/nr_pdcp/nr_pdcp_security_nea2.h index 9418511adf..c3667c93d4 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac.h +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_security_nea2.h @@ -19,30 +19,15 @@ * contact@openairinterface.org */ -/* \file mac.h - * \brief MAC data structures, constant, and function prototype - * \author R. Knopp, K.H. HSU - * \date 2018 - * \version 0.1 - * \company Eurecom / NTUST - * \email: knopp@eurecom.fr, kai-hsiang.hsu@eurecom.fr - * \note - * \warning - */ +#ifndef _NR_PDCP_SECURITY_NEA2_H_ +#define _NR_PDCP_SECURITY_NEA2_H_ -#ifndef __LAYER2_NR_UE_MAC_DEFS_H__ -#define __LAYER2_NR_UE_MAC_DEFS_H__ +void *nr_pdcp_security_nea2_init(unsigned char *ciphering_key); -#include -#include -#include +void nr_pdcp_security_nea2_cipher(void *security_context, + unsigned char *buffer, int length, + int bearer, int count, int direction); -/*!\brief UE layer 2 status */ -typedef enum { - UE_CONNECTION_OK = 0, - UE_CONNECTION_LOST, - UE_PHY_RESYNCH, - UE_PHY_HO_PRACH -} NR_UE_L2_STATE_t; +void nr_pdcp_security_nea2_free_security(void *security_context); -#endif /*__LAYER2_NR_UE_MAC_DEFS_H__ */ +#endif /* _NR_PDCP_SECURITY_NEA2_H_ */ diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c b/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c index 804f1e8a74..1d4efc1e26 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c @@ -1581,7 +1581,7 @@ void nr_rlc_entity_am_recv_sdu(nr_rlc_entity_t *_entity, } if (entity->tx_size + size > entity->tx_maxsize) { - LOG_D(RLC, "%s:%d:%s: warning: SDU rejected, SDU buffer full\n", + LOG_E(RLC, "%s:%d:%s: warning: SDU rejected, SDU buffer full\n", __FILE__, __LINE__, __FUNCTION__); return; } diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c index d597eda7a0..ab8dd8585e 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c @@ -716,8 +716,8 @@ static void add_srb(int rnti, struct LTE_SRB_ToAddMod *s) poll_byte = -1; max_retx_threshold = 8; sn_field_length = 12; - nr_rlc_am = new_nr_rlc_entity_am(100000, - 100000, + nr_rlc_am = new_nr_rlc_entity_am(10000000, + 10000000, deliver_sdu, ue, successful_delivery, ue, max_retx_reached, ue, @@ -799,8 +799,8 @@ static void add_drb_am(int rnti, struct NR_DRB_ToAddMod *s, NR_RLC_BearerConfig_ if (ue->drb[drb_id-1] != NULL) { LOG_W(RLC, "%s:%d:%s: DRB %d already exists for UE with RNTI %d, do nothing\n", __FILE__, __LINE__, __FUNCTION__, drb_id, rnti); } else { - nr_rlc_am = new_nr_rlc_entity_am(100000, - 100000, + nr_rlc_am = new_nr_rlc_entity_am(10000000, + 10000000, deliver_sdu, ue, successful_delivery, ue, max_retx_reached, ue, @@ -943,8 +943,8 @@ static void add_drb_um(int rnti, struct NR_DRB_ToAddMod *s, NR_RLC_BearerConfig_ if (ue->drb[drb_id-1] != NULL) { LOG_W(RLC, "DEBUG add_drb_um %s:%d:%s: warning DRB %d already exist for ue %d, do nothing\n", __FILE__, __LINE__, __FUNCTION__, drb_id, rnti); } else { - nr_rlc_um = new_nr_rlc_entity_um(1000000, - 1000000, + nr_rlc_um = new_nr_rlc_entity_um(100000000, + 100000000, deliver_sdu, ue, t_reassembly, sn_field_length); diff --git a/openair2/NETWORK_DRIVER/LITE/device.c b/openair2/NETWORK_DRIVER/LITE/device.c index 854c3bcc99..59340784c1 100644 --- a/openair2/NETWORK_DRIVER/LITE/device.c +++ b/openair2/NETWORK_DRIVER/LITE/device.c @@ -316,7 +316,11 @@ void oai_nw_drv_change_rx_flags(struct net_device *dev, int flags) } //--------------------------------------------------------------------------- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,6,0) +void oai_nw_drv_tx_timeout(struct net_device *dev, unsigned int txqueue) +#else void oai_nw_drv_tx_timeout(struct net_device *dev) +#endif { //--------------------------------------------------------------------------- // Transmitter timeout, serious problems. diff --git a/openair2/NETWORK_DRIVER/MESH/device.c b/openair2/NETWORK_DRIVER/MESH/device.c index 181899cd6e..47c68466bd 100644 --- a/openair2/NETWORK_DRIVER/MESH/device.c +++ b/openair2/NETWORK_DRIVER/MESH/device.c @@ -297,10 +297,10 @@ int nas_change_mtu(struct net_device *dev, int mtu) } //--------------------------------------------------------------------------- -#if LINUX_VERSION_CODE < KERNEL_VERSION(5,7,0) -void nas_tx_timeout(struct net_device *dev) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,6,0) +void nas_tx_timeout(struct net_device *dev, unsigned int txqueue) #else -void nas_tx_timeout(struct net_device *dev, unsigned int x) +void nas_tx_timeout(struct net_device *dev) #endif { //--------------------------------------------------------------------------- diff --git a/openair2/NETWORK_DRIVER/UE_IP/device.c b/openair2/NETWORK_DRIVER/UE_IP/device.c index 32f9442747..0ff9a73925 100644 --- a/openair2/NETWORK_DRIVER/UE_IP/device.c +++ b/openair2/NETWORK_DRIVER/UE_IP/device.c @@ -302,7 +302,13 @@ void ue_ip_change_rx_flags(struct net_device *dev_pP, int flagsP) { } //--------------------------------------------------------------------------- -void ue_ip_tx_timeout(struct net_device *dev_pP) { + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,6,0) +void ue_ip_tx_timeout(struct net_device *dev_pP, unsigned int txqueue) +#else +void ue_ip_tx_timeout(struct net_device *dev_pP) +#endif +{ //--------------------------------------------------------------------------- // Transmitter timeout, serious problems. ue_ip_priv_t *priv_p = netdev_priv(dev_pP); diff --git a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c index 7f98dd6a3e..b183b32aab 100644 --- a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c @@ -36,6 +36,7 @@ #include "LAYER2/NR_MAC_gNB/mac_proto.h" #include "common/ran_context.h" #include "executables/softmodem-common.h" +#include "nfapi/oai_integration/vendor_ext.h" #define MAX_IF_MODULES 100 //#define UL_HARQ_PRINT @@ -104,6 +105,10 @@ void handle_nr_uci(NR_UL_IND_t *UL_info) } UL_info->uci_ind.num_ucis = 0; + + // mark corresponding PUCCH resources as free + // NOTE: we just assume it is BWP ID 1, to be revised for multiple BWPs + RC.nrmac[mod_id]->pucch_index_used[1][slot] = 0; } @@ -181,7 +186,7 @@ void NR_UL_indication(NR_UL_IND_t *UL_info) { module_id,CC_id, UL_info->rach_ind.number_of_pdus, UL_info->rx_ind.number_of_pdus, UL_info->crc_ind.number_crcs); - if (nfapi_mode != 1) { + if (NFAPI_MODE != NFAPI_MODE_PNF) { if (ifi->CC_mask==0) { ifi->current_frame = UL_info->frame; ifi->current_slot = UL_info->slot; @@ -200,7 +205,7 @@ void NR_UL_indication(NR_UL_IND_t *UL_info) { mac->UL_dci_req[CC_id].numPdus = 0; handle_nr_ulsch(UL_info); - if (nfapi_mode != 1) { + if (NFAPI_MODE != NFAPI_MODE_PNF) { if (ifi->CC_mask == ((1<rx_ind != NULL){ - LOG_D(MAC,"[L2][IF MODULE][DL INDICATION][RX_IND], Number of PDUs: %d \n", dl_info->rx_ind->number_pdus); - for(i=0; irx_ind->number_pdus; ++i){ + LOG_D(MAC, "In %s sending DL indication to MAC. 1 PDU type %s of %d total number of PDUs \n", + __FUNCTION__, + dl_indication_type[dl_info->rx_ind->rx_indication_body[i].pdu_type - 1], + dl_info->rx_ind->number_pdus); + switch(dl_info->rx_ind->rx_indication_body[i].pdu_type){ case FAPI_NR_RX_PDU_TYPE_MIB: + ret_mask |= (handle_bcch_bch(dl_info->module_id, dl_info->cc_id, dl_info->gNB_index, (dl_info->rx_ind->rx_indication_body+i)->mib_pdu.pdu, (dl_info->rx_ind->rx_indication_body+i)->mib_pdu.additional_bits, @@ -179,8 +164,6 @@ int nr_ue_dl_indication(nr_downlink_indication_t *dl_info, NR_UL_TIME_ALIGNMENT_ (dl_info->rx_ind->rx_indication_body+i)->mib_pdu.ssb_length, (dl_info->rx_ind->rx_indication_body+i)->mib_pdu.cell_id)) << FAPI_NR_RX_PDU_TYPE_MIB; - LOG_D(MAC,"[L2][IF MODULE][DL INDICATION][RX_IND], MIB case Number of PDUs: %d \n", dl_info->rx_ind->number_pdus); - break; case FAPI_NR_RX_PDU_TYPE_SIB: @@ -195,26 +178,18 @@ int nr_ue_dl_indication(nr_downlink_indication_t *dl_info, NR_UL_TIME_ALIGNMENT_ case FAPI_NR_RX_PDU_TYPE_DLSCH: - ret_mask |= (handle_dlsch(dl_info->module_id, dl_info->cc_id, dl_info->gNB_index, - dl_info->dci_ind, - (dl_info->rx_ind->rx_indication_body+i)->pdsch_pdu.pdu, - (dl_info->rx_ind->rx_indication_body+i)->pdsch_pdu.pdu_length, - dl_info->frame, - dl_info->slot, - ul_time_alignment)) << FAPI_NR_RX_PDU_TYPE_DLSCH; - - LOG_D(MAC,"[L2][IF MODULE][DL INDICATION][RX_IND], DLSCH case Number of PDUs: %d \n", dl_info->rx_ind->number_pdus); + ret_mask |= (handle_dlsch(dl_info, ul_time_alignment, i)) << FAPI_NR_RX_PDU_TYPE_DLSCH; break; case FAPI_NR_RX_PDU_TYPE_RAR: - ret_mask |= (handle_rar(dl_info)) << FAPI_NR_RX_PDU_TYPE_RAR; + ret_mask |= (handle_dlsch(dl_info, ul_time_alignment, i)) << FAPI_NR_RX_PDU_TYPE_RAR; break; default: - break; + break; } } } diff --git a/openair2/PHY_INTERFACE/phy_stub_UE.c b/openair2/PHY_INTERFACE/phy_stub_UE.c index b4a7f8c6e7..21740016b1 100644 --- a/openair2/PHY_INTERFACE/phy_stub_UE.c +++ b/openair2/PHY_INTERFACE/phy_stub_UE.c @@ -30,6 +30,10 @@ #include "targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h" #include "common/config/config_load_configmodule.h" #include "common/config/config_userapi.h" +#include "openair2/NR_PHY_INTERFACE/NR_IF_Module.h" +#include "openair1/PHY/defs_gNB.h" +#include "nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h" +#include "openair1/PHY/LTE_TRANSPORT/transport_common.h" extern int oai_nfapi_rach_ind(nfapi_rach_indication_t *rach_ind); void configure_nfapi_pnf(char *vnf_ip_addr, diff --git a/openair2/RRC/LTE/rrc_defs.h b/openair2/RRC/LTE/rrc_defs.h index 7602e9ca64..4f55f94121 100644 --- a/openair2/RRC/LTE/rrc_defs.h +++ b/openair2/RRC/LTE/rrc_defs.h @@ -546,6 +546,13 @@ typedef struct rrc_gummei_s { uint16_t mme_group_id; } rrc_gummei_t; +typedef struct { + uint16_t ciphering_algorithms; + uint16_t integrity_algorithms; + uint16_t sk_counter; + uint8_t kgNB[32]; +} lte_rrc_nr_security_t; + typedef struct eNB_RRC_UE_s { uint8_t primaryCC_id; LTE_SCellToAddMod_r10_t sCell_config[2]; @@ -615,6 +622,9 @@ typedef struct eNB_RRC_UE_s { security_capabilities_t security_capabilities; + /* security capabilities and settings for an UE in ENDC mode */ + lte_rrc_nr_security_t nr_security; + int next_hop_chain_count; uint8_t next_security_key[SECURITY_KEY_LENGTH]; diff --git a/openair2/RRC/LTE/rrc_eNB.c b/openair2/RRC/LTE/rrc_eNB.c index f15fb6cf31..526ce129b1 100644 --- a/openair2/RRC/LTE/rrc_eNB.c +++ b/openair2/RRC/LTE/rrc_eNB.c @@ -4426,69 +4426,11 @@ static int encode_CG_ConfigInfo( struct NR_RadioBearerConfig *rb_config = NULL; asn_enc_rval_t enc_rval; int RRC_OK = 1; - int index = 0; char temp_buff[ASN_MAX_ENCODE_SIZE]; - LTE_UE_CapabilityRAT_ContainerList_t *ue_cap_rat_container_list = NULL; - LTE_UE_CapabilityRAT_Container_t ue_cap_rat_container_MRDC; - LTE_UE_CapabilityRAT_Container_t ue_cap_rat_container_nr; + NR_UE_CapabilityRAT_ContainerList_t *ue_cap_rat_container_list = NULL; + NR_UE_CapabilityRAT_Container_t *ue_cap_rat_container_MRDC = NULL; + NR_UE_CapabilityRAT_Container_t *ue_cap_rat_container_nr = NULL; int RAT_Container_count = 0; - rb_config = calloc(1,sizeof(struct NR_RadioBearerConfig)); - AssertFatal(rb_config != NULL,"failed to allocate memory for rb_config"); - - if(ue_context_pP->ue_context.DRB_configList->list.count != 0) { - rb_config->drb_ToAddModList = calloc(1,sizeof(struct NR_DRB_ToAddModList )); - AssertFatal(rb_config->drb_ToAddModList != NULL,"failed to allocated memory for drbtoaddmodlist"); - rb_config->drb_ToAddModList->list.count = NUMBEROF_DRBS_TOBE_ADDED; - rb_config->drb_ToAddModList->list.array - = calloc(NUMBEROF_DRBS_TOBE_ADDED, sizeof(struct NR_DRB_ToAddMod *)); - AssertFatal( rb_config->drb_ToAddModList->list.array != NULL, - "falied to allocate memory for list.array"); - - for(index = 0; index < NUMBEROF_DRBS_TOBE_ADDED; index++) { - rb_config->drb_ToAddModList->list.array[index] - = calloc(1,sizeof(struct NR_DRB_ToAddMod)); - AssertFatal(rb_config->drb_ToAddModList->list.array[index] != NULL, - "failed to allocate memory for drb_toaddmod"); - rb_config->drb_ToAddModList->list.array[index]->drb_Identity - = ue_context_pP->ue_context.DRB_configList->list.array[index]->drb_Identity; - - if(ue_context_pP->ue_context.DRB_configList->list.array[index]->eps_BearerIdentity) { - rb_config->drb_ToAddModList->list.array[index]->cnAssociation - = calloc(1,sizeof(struct NR_DRB_ToAddMod__cnAssociation)); - AssertFatal(rb_config->drb_ToAddModList->list.array[index]->cnAssociation != NULL, - "failed to allocate memory cnAssociation"); - rb_config->drb_ToAddModList->list.array[index]->cnAssociation->present - = NR_DRB_ToAddMod__cnAssociation_PR_eps_BearerIdentity; - rb_config->drb_ToAddModList->list.array[index]->cnAssociation->choice.eps_BearerIdentity - = *(ue_context_pP->ue_context.DRB_configList->list.array[index]->eps_BearerIdentity); - } - - rb_config->drb_ToAddModList->list.array[index]->pdcp_Config = calloc(1,sizeof(struct NR_PDCP_Config)); - rb_config->drb_ToAddModList->list.array[index]->pdcp_Config->drb = calloc(1,sizeof(struct NR_PDCP_Config__drb)); - rb_config->drb_ToAddModList->list.array[index]->pdcp_Config->drb->discardTimer = calloc(1,sizeof(long)); - *rb_config->drb_ToAddModList->list.array[index]->pdcp_Config->drb->discardTimer - = *(ue_context_pP->ue_context.DRB_configList->list.array[index]->pdcp_Config->discardTimer); - rb_config->drb_ToAddModList->list.array[index]->pdcp_Config->drb->pdcp_SN_SizeUL = calloc(1,sizeof(long)); - *rb_config->drb_ToAddModList->list.array[index]->pdcp_Config->drb->pdcp_SN_SizeUL - = NR_PDCP_Config__drb__pdcp_SN_SizeUL_len18bits; - rb_config->drb_ToAddModList->list.array[index]->pdcp_Config->drb->pdcp_SN_SizeDL = calloc(1,sizeof(long)); - *rb_config->drb_ToAddModList->list.array[index]->pdcp_Config->drb->pdcp_SN_SizeDL - = NR_PDCP_Config__drb__pdcp_SN_SizeDL_len18bits; - rb_config->drb_ToAddModList->list.array[index]->pdcp_Config->drb->headerCompression.present - = NR_PDCP_Config__drb__headerCompression_PR_notUsed; - rb_config->drb_ToAddModList->list.array[index]->pdcp_Config->drb->headerCompression.choice.notUsed = 0; - rb_config->drb_ToAddModList->list.array[index]->pdcp_Config->t_Reordering = calloc(1,sizeof(long)); - *rb_config->drb_ToAddModList->list.array[index]->pdcp_Config->t_Reordering - = NR_PDCP_Config__t_Reordering_ms0; - } - - rb_config->securityConfig = calloc(1,sizeof(struct NR_SecurityConfig )); - rb_config->securityConfig->securityAlgorithmConfig = calloc(1,sizeof(struct NR_SecurityAlgorithmConfig)); - rb_config->securityConfig->securityAlgorithmConfig->cipheringAlgorithm = NR_CipheringAlgorithm_nea0; - rb_config->securityConfig->securityAlgorithmConfig->integrityProtAlgorithm = NULL; - rb_config->securityConfig->keyToUse = calloc(1,sizeof(long)); - *rb_config->securityConfig->keyToUse = NR_SecurityConfig__keyToUse_master; - } cg_configinfo = calloc(1,sizeof(struct NR_CG_ConfigInfo)); AssertFatal(cg_configinfo != NULL,"failed to allocate memory for cg_configinfo"); @@ -4503,10 +4445,6 @@ static int encode_CG_ConfigInfo( = calloc(1,sizeof(struct NR_CG_ConfigInfo_IEs)); AssertFatal(cg_configinfo->criticalExtensions.choice.c1->choice.cg_ConfigInfo != NULL, "failed to allocate memory for cg_configinfo_IEs"); - cg_configinfo->criticalExtensions.choice.c1->choice.cg_ConfigInfo->ue_CapabilityInfo - = calloc(1,sizeof( OCTET_STRING_t)); - AssertFatal(cg_configinfo->criticalExtensions.choice.c1->choice.cg_ConfigInfo-> - ue_CapabilityInfo != NULL, "failed to allocate memory for ue_capabilityinfo"); if(ue_context_pP->ue_context.UE_Capability_MRDC) { RAT_Container_count++; @@ -4514,8 +4452,10 @@ static int encode_CG_ConfigInfo( (void *)ue_context_pP->ue_context.UE_Capability_MRDC,temp_buff,ASN_MAX_ENCODE_SIZE); AssertFatal(enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %jd)!\n", enc_rval.failed_type->name, enc_rval.encoded); - ue_cap_rat_container_MRDC.rat_Type = LTE_RAT_Type_eutra_nr; - OCTET_STRING_fromBuf(&ue_cap_rat_container_MRDC.ueCapabilityRAT_Container, + ue_cap_rat_container_MRDC = calloc(1, sizeof(*ue_cap_rat_container_MRDC)); + AssertFatal(ue_cap_rat_container_MRDC != NULL,"failed to allocate memory for ue_cap_rat_container_MRDC"); + ue_cap_rat_container_MRDC->rat_Type = NR_RAT_Type_eutra_nr; + OCTET_STRING_fromBuf(&ue_cap_rat_container_MRDC->ue_CapabilityRAT_Container, (const char *)temp_buff,(enc_rval.encoded+7)>>3); memset((void *)temp_buff,0,sizeof(temp_buff)); } @@ -4526,44 +4466,30 @@ static int encode_CG_ConfigInfo( (void *)ue_context_pP->ue_context.UE_Capability_nr,temp_buff,ASN_MAX_ENCODE_SIZE); AssertFatal(enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %jd)!\n", enc_rval.failed_type->name, enc_rval.encoded); - ue_cap_rat_container_nr.rat_Type = LTE_RAT_Type_nr; - OCTET_STRING_fromBuf(&ue_cap_rat_container_nr.ueCapabilityRAT_Container, + ue_cap_rat_container_nr = calloc(1, sizeof(*ue_cap_rat_container_nr)); + AssertFatal(ue_cap_rat_container_nr != NULL,"failed to allocate memory for ue_cap_rat_container_nr"); + ue_cap_rat_container_nr->rat_Type = NR_RAT_Type_nr; + OCTET_STRING_fromBuf(&ue_cap_rat_container_nr->ue_CapabilityRAT_Container, (const char *)temp_buff,(enc_rval.encoded+7)>>3); memset((void *)temp_buff,0,sizeof(temp_buff)); } - ue_cap_rat_container_list = calloc(1,sizeof(LTE_UE_CapabilityRAT_ContainerList_t)); - ue_cap_rat_container_list->list.count = RAT_Container_count; - ue_cap_rat_container_list->list.size = RAT_Container_count * sizeof(LTE_UE_CapabilityRAT_Container_t); - ue_cap_rat_container_list->list.array = calloc(RAT_Container_count,sizeof(LTE_UE_CapabilityRAT_Container_t *)); - - if(ue_context_pP->ue_context.UE_Capability_MRDC) { - ue_cap_rat_container_list->list.array[0] = calloc(1,sizeof(LTE_UE_CapabilityRAT_Container_t)); - memcpy(ue_cap_rat_container_list->list.array[0],&ue_cap_rat_container_MRDC,sizeof(LTE_UE_CapabilityRAT_Container_t)); + if (RAT_Container_count) { + cg_configinfo->criticalExtensions.choice.c1->choice.cg_ConfigInfo->ue_CapabilityInfo = calloc(1,sizeof( OCTET_STRING_t)); + AssertFatal(cg_configinfo->criticalExtensions.choice.c1->choice.cg_ConfigInfo-> ue_CapabilityInfo != NULL, "failed to allocate memory for ue_capabilityinfo"); + ue_cap_rat_container_list = calloc(1,sizeof(NR_UE_CapabilityRAT_ContainerList_t)); + if (ue_cap_rat_container_MRDC != NULL) + ASN_SEQUENCE_ADD(&ue_cap_rat_container_list->list, ue_cap_rat_container_MRDC); + if (ue_cap_rat_container_nr != NULL) + ASN_SEQUENCE_ADD(&ue_cap_rat_container_list->list, ue_cap_rat_container_nr); + enc_rval = uper_encode_to_buffer(&asn_DEF_NR_UE_CapabilityRAT_ContainerList,NULL, + (void *)ue_cap_rat_container_list,temp_buff,ASN_MAX_ENCODE_SIZE); + AssertFatal(enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %jd)!\n", + enc_rval.failed_type->name, enc_rval.encoded); + OCTET_STRING_fromBuf(cg_configinfo->criticalExtensions.choice.c1->choice.cg_ConfigInfo->ue_CapabilityInfo, + (const char *)temp_buff, (enc_rval.encoded+7)>>3); } - if(ue_context_pP->ue_context.UE_Capability_nr) { - ue_cap_rat_container_list->list.array[1] = calloc(1,sizeof(LTE_UE_CapabilityRAT_Container_t)); - memcpy(ue_cap_rat_container_list->list.array[1],&ue_cap_rat_container_nr,sizeof(LTE_UE_CapabilityRAT_Container_t)); - } - - //this xer_fprint logs can be enabled for additional debugging logs - //xer_fprint(stdout,&asn_DEF_LTE_UE_CapabilityRAT_ContainerList,ue_cap_rat_container_list); - enc_rval = uper_encode_to_buffer(&asn_DEF_LTE_UE_CapabilityRAT_ContainerList,NULL, - (void *)ue_cap_rat_container_list,temp_buff,ASN_MAX_ENCODE_SIZE); - AssertFatal(enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %jd)!\n", - enc_rval.failed_type->name, enc_rval.encoded); - OCTET_STRING_fromBuf(cg_configinfo->criticalExtensions.choice.c1->choice.cg_ConfigInfo->ue_CapabilityInfo, - (const char *)temp_buff, (enc_rval.encoded+7)>>3); - cg_configinfo->criticalExtensions.choice.c1->choice.cg_ConfigInfo->mcg_RB_Config - = calloc(1,sizeof(OCTET_STRING_t)); - AssertFatal(cg_configinfo->criticalExtensions.choice.c1->choice.cg_ConfigInfo-> - mcg_RB_Config != NULL, "failed to allocate memory for mcg_rb_config"); - enc_rval = uper_encode_to_buffer(&asn_DEF_NR_RadioBearerConfig,NULL,(void *)rb_config,temp_buff,ASN_MAX_ENCODE_SIZE); - AssertFatal(enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %jd)!\n", - enc_rval.failed_type->name, enc_rval.encoded); - OCTET_STRING_fromBuf(cg_configinfo->criticalExtensions.choice.c1->choice.cg_ConfigInfo->mcg_RB_Config, - (const char *)temp_buff, (enc_rval.encoded+7)>>3); // this xer_fprint can be enabled for additional debugging messages // xer_fprint(stdout,&asn_DEF_NR_CG_ConfigInfo,(void *)cg_configinfo); enc_rval = uper_encode_to_buffer(&asn_DEF_NR_CG_ConfigInfo,NULL,(void *)cg_configinfo, @@ -4573,7 +4499,7 @@ static int encode_CG_ConfigInfo( *enc_size = (enc_rval.encoded+7)/8; ASN_STRUCT_FREE(asn_DEF_NR_RadioBearerConfig,rb_config); ASN_STRUCT_FREE(asn_DEF_NR_CG_ConfigInfo,cg_configinfo); - ASN_STRUCT_FREE(asn_DEF_LTE_UE_CapabilityRAT_ContainerList,ue_cap_rat_container_list); + ASN_STRUCT_FREE(asn_DEF_NR_UE_CapabilityRAT_ContainerList,ue_cap_rat_container_list); return RRC_OK; } //----------------------------------------------------------------------------- @@ -4672,11 +4598,20 @@ rrc_eNB_process_MeasurementReport( msg = itti_alloc_new_message(TASK_RRC_ENB, 0, X2AP_ENDC_SGNB_ADDITION_REQ); memset(&(X2AP_ENDC_SGNB_ADDITION_REQ(msg)), 0, sizeof(x2ap_ENDC_sgnb_addition_req_t)); + X2AP_ENDC_SGNB_ADDITION_REQ(msg).rnti = ctxt_pP->rnti; + + X2AP_ENDC_SGNB_ADDITION_REQ(msg).security_capabilities.encryption_algorithms = ue_context_pP->ue_context.nr_security.ciphering_algorithms; + X2AP_ENDC_SGNB_ADDITION_REQ(msg).security_capabilities.integrity_algorithms = ue_context_pP->ue_context.nr_security.integrity_algorithms; + + memcpy(X2AP_ENDC_SGNB_ADDITION_REQ(msg).kgnb, ue_context_pP->ue_context.nr_security.kgNB, 32); + memcpy(X2AP_ENDC_SGNB_ADDITION_REQ(msg).rrc_buffer,enc_buf,enc_size); X2AP_ENDC_SGNB_ADDITION_REQ(msg).rrc_buffer_size = enc_size; + X2AP_ENDC_SGNB_ADDITION_REQ(msg).target_physCellId = measResults2->measResultNeighCells->choice.measResultListEUTRA.list.array[0]->physCellId; + //For the moment we have a single E-RAB which will be the one to be added to the gNB //Not sure how to select bearers to be added if there are multiple. X2AP_ENDC_SGNB_ADDITION_REQ(msg).nb_e_rabs_tobeadded = 1; diff --git a/openair2/RRC/LTE/rrc_eNB_S1AP.c b/openair2/RRC/LTE/rrc_eNB_S1AP.c index 320004a361..d34b4164a2 100644 --- a/openair2/RRC/LTE/rrc_eNB_S1AP.c +++ b/openair2/RRC/LTE/rrc_eNB_S1AP.c @@ -1045,6 +1045,15 @@ int rrc_eNB_process_S1AP_INITIAL_CONTEXT_SETUP_REQ(MessageDef *msg_p, const char } } + ue_context_p->ue_context.nr_security.ciphering_algorithms = S1AP_INITIAL_CONTEXT_SETUP_REQ(msg_p).nr_security_capabilities.encryption_algorithms; + ue_context_p->ue_context.nr_security.integrity_algorithms = S1AP_INITIAL_CONTEXT_SETUP_REQ(msg_p).nr_security_capabilities.integrity_algorithms; + /* let's initialize sk_counter to 0 */ + ue_context_p->ue_context.nr_security.sk_counter = 0; + /* let's compute kgNB */ + derive_skgNB(ue_context_p->ue_context.kenb, + ue_context_p->ue_context.nr_security.sk_counter, + ue_context_p->ue_context.nr_security.kgNB); + // in case, send the S1SP initial context response if it is not sent with the attach complete message if (ue_context_p->ue_context.Status == RRC_RECONFIGURED) { LOG_I(RRC, "Sending rrc_eNB_send_S1AP_INITIAL_CONTEXT_SETUP_RESP, cause %ld\n", ue_context_p->ue_context.reestablishment_cause); diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.c b/openair2/RRC/NR/MESSAGES/asn1_msg.c index 4c0d624198..68b490d997 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.c +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.c @@ -359,7 +359,7 @@ uint8_t do_SIB1_NR(rrc_gNB_carrier_data_t *carrier, nr_plmn_info->cellIdentity.buf[4]= (configuration->cell_identity << 4) & 0xff; nr_plmn_info->cellIdentity.size= 5; nr_plmn_info->cellIdentity.bits_unused= 4; - nr_plmn_info->cellReservedForOperatorUse = NR_PLMN_IdentityInfo__cellReservedForOperatorUse_reserved; + nr_plmn_info->cellReservedForOperatorUse = NR_PLMN_IdentityInfo__cellReservedForOperatorUse_notReserved; nr_plmn_info->trackingAreaCode = CALLOC(1,sizeof(NR_TrackingAreaCode_t)); nr_plmn_info->trackingAreaCode->buf = CALLOC(1,3); @@ -377,14 +377,32 @@ uint8_t do_SIB1_NR(rrc_gNB_carrier_data_t *carrier, //si-SchedulingInfo /*sib1->si_SchedulingInfo = CALLOC(1,sizeof(struct NR_SI_SchedulingInfo)); asn_set_empty(&sib1->si_SchedulingInfo->schedulingInfoList.list); - sib1->si_SchedulingInfo->si_WindowLength = NR_SI_SchedulingInfo__si_WindowLength_s20; + sib1->si_SchedulingInfo->si_WindowLength = NR_SI_SchedulingInfo__si_WindowLength_s40; struct NR_SchedulingInfo *schedulingInfo = CALLOC(1,sizeof(struct NR_SchedulingInfo)); schedulingInfo->si_BroadcastStatus = NR_SchedulingInfo__si_BroadcastStatus_broadcasting; schedulingInfo->si_Periodicity = NR_SchedulingInfo__si_Periodicity_rf8; asn_set_empty(&schedulingInfo->sib_MappingInfo.list); - e_NR_SIB_TypeInfo__type *sib_type = CALLOC(1,sizeof(e_NR_SIB_TypeInfo__type)); - *sib_type = NR_SIB_TypeInfo__type_sibType3; - ASN_SEQUENCE_ADD(&schedulingInfo->sib_MappingInfo.list,sib_type); + + NR_SIB_TypeInfo_t *sib_type3 = CALLOC(1,sizeof(e_NR_SIB_TypeInfo__type)); + sib_type3->type = NR_SIB_TypeInfo__type_sibType3; + sib_type3->valueTag = CALLOC(1,sizeof(sib_type3->valueTag)); + ASN_SEQUENCE_ADD(&schedulingInfo->sib_MappingInfo.list,sib_type3); + + NR_SIB_TypeInfo_t *sib_type5 = CALLOC(1,sizeof(e_NR_SIB_TypeInfo__type)); + sib_type5->type = NR_SIB_TypeInfo__type_sibType5; + sib_type5->valueTag = CALLOC(1,sizeof(sib_type5->valueTag)); + ASN_SEQUENCE_ADD(&schedulingInfo->sib_MappingInfo.list,sib_type5); + + NR_SIB_TypeInfo_t *sib_type4 = CALLOC(1,sizeof(e_NR_SIB_TypeInfo__type)); + sib_type4->type = NR_SIB_TypeInfo__type_sibType4; + sib_type4->valueTag = CALLOC(1,sizeof(sib_type4->valueTag)); + ASN_SEQUENCE_ADD(&schedulingInfo->sib_MappingInfo.list,sib_type4); + + NR_SIB_TypeInfo_t *sib_type2 = CALLOC(1,sizeof(e_NR_SIB_TypeInfo__type)); + sib_type2->type = NR_SIB_TypeInfo__type_sibType2; + sib_type2->valueTag = CALLOC(1,sizeof(sib_type2->valueTag)); + ASN_SEQUENCE_ADD(&schedulingInfo->sib_MappingInfo.list,sib_type2); + ASN_SEQUENCE_ADD(&sib1->si_SchedulingInfo->schedulingInfoList.list,schedulingInfo);*/ // servingCellConfigCommon @@ -404,25 +422,180 @@ uint8_t do_SIB1_NR(rrc_gNB_carrier_data_t *carrier, for(int i = 0; i< configuration->scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.count; i++) { ASN_SEQUENCE_ADD(&sib1->servingCellConfigCommon->downlinkConfigCommon.frequencyInfoDL.scs_SpecificCarrierList.list,configuration->scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[i]); } + sib1->servingCellConfigCommon->downlinkConfigCommon.initialDownlinkBWP.pdcch_ConfigCommon = configuration->scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon; + sib1->servingCellConfigCommon->downlinkConfigCommon.initialDownlinkBWP.pdcch_ConfigCommon->choice.setup->commonSearchSpaceList = CALLOC(1,sizeof(struct NR_PDCCH_ConfigCommon__commonSearchSpaceList)); + asn_set_empty(&sib1->servingCellConfigCommon->downlinkConfigCommon.initialDownlinkBWP.pdcch_ConfigCommon->choice.setup->commonSearchSpaceList->list); + + NR_SearchSpace_t *ss1 = calloc(1,sizeof(*ss1)); + ss1->searchSpaceId = 1; + ss1->controlResourceSetId=calloc(1,sizeof(*ss1->controlResourceSetId)); + *ss1->controlResourceSetId=0; + ss1->monitoringSlotPeriodicityAndOffset = calloc(1,sizeof(*ss1->monitoringSlotPeriodicityAndOffset)); + ss1->monitoringSlotPeriodicityAndOffset->present = NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl1; + ss1->monitoringSymbolsWithinSlot = calloc(1,sizeof(*ss1->monitoringSymbolsWithinSlot)); + ss1->monitoringSymbolsWithinSlot->buf = calloc(1,2); + // should be '1100 0000 0000 00'B (LSB first!), first two symols in slot, adjust if needed + ss1->monitoringSymbolsWithinSlot->buf[1] = 0; + ss1->monitoringSymbolsWithinSlot->buf[0] = (1<<7); + ss1->monitoringSymbolsWithinSlot->size = 2; + ss1->monitoringSymbolsWithinSlot->bits_unused = 2; + ss1->nrofCandidates = calloc(1,sizeof(*ss1->nrofCandidates)); + ss1->nrofCandidates->aggregationLevel1 = NR_SearchSpace__nrofCandidates__aggregationLevel1_n0; + ss1->nrofCandidates->aggregationLevel2 = NR_SearchSpace__nrofCandidates__aggregationLevel2_n0; + ss1->nrofCandidates->aggregationLevel4 = NR_SearchSpace__nrofCandidates__aggregationLevel4_n1; + ss1->nrofCandidates->aggregationLevel8 = NR_SearchSpace__nrofCandidates__aggregationLevel8_n0; + ss1->nrofCandidates->aggregationLevel16 = NR_SearchSpace__nrofCandidates__aggregationLevel16_n0; + ss1->searchSpaceType = calloc(1,sizeof(*ss1->searchSpaceType)); + ss1->searchSpaceType->present = NR_SearchSpace__searchSpaceType_PR_common; + ss1->searchSpaceType->choice.common=calloc(1,sizeof(*ss1->searchSpaceType->choice.common)); + ss1->searchSpaceType->choice.common->dci_Format0_0_AndFormat1_0 = calloc(1,sizeof(*ss1->searchSpaceType->choice.common->dci_Format0_0_AndFormat1_0)); + ASN_SEQUENCE_ADD(&sib1->servingCellConfigCommon->downlinkConfigCommon.initialDownlinkBWP.pdcch_ConfigCommon->choice.setup->commonSearchSpaceList->list,ss1); + + NR_SearchSpace_t *ss5 = calloc(1,sizeof(*ss5)); + ss5->searchSpaceId = 5; + ss5->controlResourceSetId=calloc(1,sizeof(*ss5->controlResourceSetId)); + *ss5->controlResourceSetId=0; + ss5->monitoringSlotPeriodicityAndOffset = calloc(1,sizeof(*ss5->monitoringSlotPeriodicityAndOffset)); + ss5->monitoringSlotPeriodicityAndOffset->present = NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl5; + ss5->monitoringSlotPeriodicityAndOffset->choice.sl5 = 0; + ss5->duration = calloc(1,sizeof(*ss5->duration)); + *ss5->duration = 2; + ss5->monitoringSymbolsWithinSlot = calloc(1,sizeof(*ss5->monitoringSymbolsWithinSlot)); + ss5->monitoringSymbolsWithinSlot->buf = calloc(1,2); + // should be '1100 0000 0000 00'B (LSB first!), first two symols in slot, adjust if needed + ss5->monitoringSymbolsWithinSlot->buf[1] = 0; + ss5->monitoringSymbolsWithinSlot->buf[0] = (1<<7); + ss5->monitoringSymbolsWithinSlot->size = 2; + ss5->monitoringSymbolsWithinSlot->bits_unused = 2; + ss5->nrofCandidates = calloc(1,sizeof(*ss5->nrofCandidates)); + ss5->nrofCandidates->aggregationLevel1 = NR_SearchSpace__nrofCandidates__aggregationLevel1_n0; + ss5->nrofCandidates->aggregationLevel2 = NR_SearchSpace__nrofCandidates__aggregationLevel2_n0; + ss5->nrofCandidates->aggregationLevel4 = NR_SearchSpace__nrofCandidates__aggregationLevel4_n4; + ss5->nrofCandidates->aggregationLevel8 = NR_SearchSpace__nrofCandidates__aggregationLevel8_n2; + ss5->nrofCandidates->aggregationLevel16 = NR_SearchSpace__nrofCandidates__aggregationLevel16_n1; + ss5->searchSpaceType = calloc(1,sizeof(*ss5->searchSpaceType)); + ss5->searchSpaceType->present = NR_SearchSpace__searchSpaceType_PR_common; + ss5->searchSpaceType->choice.common=calloc(1,sizeof(*ss5->searchSpaceType->choice.common)); + ss5->searchSpaceType->choice.common->dci_Format0_0_AndFormat1_0 = calloc(1,sizeof(*ss5->searchSpaceType->choice.common->dci_Format0_0_AndFormat1_0)); + ASN_SEQUENCE_ADD(&sib1->servingCellConfigCommon->downlinkConfigCommon.initialDownlinkBWP.pdcch_ConfigCommon->choice.setup->commonSearchSpaceList->list,ss5); + + NR_SearchSpace_t *ss7 = calloc(1,sizeof(*ss7)); + ss7->searchSpaceId = 7; + ss7->controlResourceSetId=calloc(1,sizeof(*ss7->controlResourceSetId)); + *ss7->controlResourceSetId=0; + ss7->monitoringSlotPeriodicityAndOffset = calloc(1,sizeof(*ss7->monitoringSlotPeriodicityAndOffset)); + ss7->monitoringSlotPeriodicityAndOffset->present = NR_SearchSpace__monitoringSlotPeriodicityAndOffset_PR_sl1; + ss7->monitoringSymbolsWithinSlot = calloc(1,sizeof(*ss7->monitoringSymbolsWithinSlot)); + ss7->monitoringSymbolsWithinSlot->buf = calloc(1,2); + // should be '1100 0000 0000 00'B (LSB first!), first two symols in slot, adjust if needed + ss7->monitoringSymbolsWithinSlot->buf[1] = 0; + ss7->monitoringSymbolsWithinSlot->buf[0] = (1<<7); + ss7->monitoringSymbolsWithinSlot->size = 2; + ss7->monitoringSymbolsWithinSlot->bits_unused = 2; + ss7->nrofCandidates = calloc(1,sizeof(*ss7->nrofCandidates)); + ss7->nrofCandidates->aggregationLevel1 = NR_SearchSpace__nrofCandidates__aggregationLevel1_n0; + ss7->nrofCandidates->aggregationLevel2 = NR_SearchSpace__nrofCandidates__aggregationLevel2_n0; + ss7->nrofCandidates->aggregationLevel4 = NR_SearchSpace__nrofCandidates__aggregationLevel4_n4; + ss7->nrofCandidates->aggregationLevel8 = NR_SearchSpace__nrofCandidates__aggregationLevel8_n2; + ss7->nrofCandidates->aggregationLevel16 = NR_SearchSpace__nrofCandidates__aggregationLevel16_n1; + ss7->searchSpaceType = calloc(1,sizeof(*ss7->searchSpaceType)); + ss7->searchSpaceType->present = NR_SearchSpace__searchSpaceType_PR_common; + ss7->searchSpaceType->choice.common=calloc(1,sizeof(*ss7->searchSpaceType->choice.common)); + ss7->searchSpaceType->choice.common->dci_Format0_0_AndFormat1_0 = calloc(1,sizeof(*ss7->searchSpaceType->choice.common->dci_Format0_0_AndFormat1_0)); + ASN_SEQUENCE_ADD(&sib1->servingCellConfigCommon->downlinkConfigCommon.initialDownlinkBWP.pdcch_ConfigCommon->choice.setup->commonSearchSpaceList->list,ss7); + + sib1->servingCellConfigCommon->downlinkConfigCommon.initialDownlinkBWP.pdcch_ConfigCommon->choice.setup->searchSpaceSIB1 = calloc(1,sizeof(NR_SearchSpaceId_t)); + *sib1->servingCellConfigCommon->downlinkConfigCommon.initialDownlinkBWP.pdcch_ConfigCommon->choice.setup->searchSpaceSIB1 = 0; + sib1->servingCellConfigCommon->downlinkConfigCommon.initialDownlinkBWP.pdcch_ConfigCommon->choice.setup->searchSpaceOtherSystemInformation = calloc(1,sizeof(NR_SearchSpaceId_t)); + *sib1->servingCellConfigCommon->downlinkConfigCommon.initialDownlinkBWP.pdcch_ConfigCommon->choice.setup->searchSpaceOtherSystemInformation = 7; + sib1->servingCellConfigCommon->downlinkConfigCommon.initialDownlinkBWP.pdcch_ConfigCommon->choice.setup->pagingSearchSpace = calloc(1,sizeof(NR_SearchSpaceId_t)); + *sib1->servingCellConfigCommon->downlinkConfigCommon.initialDownlinkBWP.pdcch_ConfigCommon->choice.setup->pagingSearchSpace = 5; + sib1->servingCellConfigCommon->downlinkConfigCommon.initialDownlinkBWP.pdcch_ConfigCommon->choice.setup->ra_SearchSpace = calloc(1,sizeof(NR_SearchSpaceId_t)); + *sib1->servingCellConfigCommon->downlinkConfigCommon.initialDownlinkBWP.pdcch_ConfigCommon->choice.setup->ra_SearchSpace = 1; + sib1->servingCellConfigCommon->downlinkConfigCommon.initialDownlinkBWP.pdsch_ConfigCommon = configuration->scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon; sib1->servingCellConfigCommon->downlinkConfigCommon.bcch_Config.modificationPeriodCoeff = NR_BCCH_Config__modificationPeriodCoeff_n2; - sib1->servingCellConfigCommon->downlinkConfigCommon.pcch_Config.defaultPagingCycle = 0; - sib1->servingCellConfigCommon->downlinkConfigCommon.pcch_Config.nAndPagingFrameOffset.present = NR_PCCH_Config__nAndPagingFrameOffset_PR_oneT; - sib1->servingCellConfigCommon->downlinkConfigCommon.pcch_Config.ns = NR_PCCH_Config__ns_four; + sib1->servingCellConfigCommon->downlinkConfigCommon.pcch_Config.defaultPagingCycle = NR_PagingCycle_rf256; + sib1->servingCellConfigCommon->downlinkConfigCommon.pcch_Config.nAndPagingFrameOffset.present = NR_PCCH_Config__nAndPagingFrameOffset_PR_quarterT; + sib1->servingCellConfigCommon->downlinkConfigCommon.pcch_Config.nAndPagingFrameOffset.choice.quarterT = 1; + sib1->servingCellConfigCommon->downlinkConfigCommon.pcch_Config.ns = NR_PCCH_Config__ns_one; + + sib1->servingCellConfigCommon->downlinkConfigCommon.pcch_Config.firstPDCCH_MonitoringOccasionOfPO = calloc(1,sizeof(struct NR_PCCH_Config__firstPDCCH_MonitoringOccasionOfPO)); + sib1->servingCellConfigCommon->downlinkConfigCommon.pcch_Config.firstPDCCH_MonitoringOccasionOfPO->present = NR_PCCH_Config__firstPDCCH_MonitoringOccasionOfPO_PR_sCS120KHZoneT_SCS60KHZhalfT_SCS30KHZquarterT_SCS15KHZoneEighthT; + + sib1->servingCellConfigCommon->downlinkConfigCommon.pcch_Config.firstPDCCH_MonitoringOccasionOfPO->choice.sCS120KHZoneT_SCS60KHZhalfT_SCS30KHZquarterT_SCS15KHZoneEighthT = CALLOC(1,sizeof(struct NR_PCCH_Config__firstPDCCH_MonitoringOccasionOfPO__sCS120KHZoneT_SCS60KHZhalfT_SCS30KHZquarterT_SCS15KHZoneEighthT)); + asn_set_empty(&sib1->servingCellConfigCommon->downlinkConfigCommon.pcch_Config.firstPDCCH_MonitoringOccasionOfPO->choice.sCS120KHZoneT_SCS60KHZhalfT_SCS30KHZquarterT_SCS15KHZoneEighthT->list); + + long *sCS120KHZoneT_SCS60KHZhalfT_SCS30KHZquarterT_SCS15KHZoneEighthT = calloc(1,sizeof(long)); + *sCS120KHZoneT_SCS60KHZhalfT_SCS30KHZquarterT_SCS15KHZoneEighthT = 0; + ASN_SEQUENCE_ADD(&sib1->servingCellConfigCommon->downlinkConfigCommon.pcch_Config.firstPDCCH_MonitoringOccasionOfPO->choice.sCS120KHZoneT_SCS60KHZhalfT_SCS30KHZquarterT_SCS15KHZoneEighthT->list,sCS120KHZoneT_SCS60KHZhalfT_SCS30KHZquarterT_SCS15KHZoneEighthT); sib1->servingCellConfigCommon->uplinkConfigCommon = CALLOC(1,sizeof(struct NR_UplinkConfigCommonSIB)); asn_set_empty(&sib1->servingCellConfigCommon->uplinkConfigCommon->frequencyInfoUL.scs_SpecificCarrierList.list); for(int i = 0; i< configuration->scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.count; i++) { ASN_SEQUENCE_ADD(&sib1->servingCellConfigCommon->uplinkConfigCommon->frequencyInfoUL.scs_SpecificCarrierList.list,configuration->scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[i]); } + + sib1->servingCellConfigCommon->uplinkConfigCommon->frequencyInfoUL.p_Max = CALLOC(1,sizeof(NR_P_Max_t)); + *sib1->servingCellConfigCommon->uplinkConfigCommon->frequencyInfoUL.p_Max = 23; + sib1->servingCellConfigCommon->uplinkConfigCommon->initialUplinkBWP.genericParameters = configuration->scc->uplinkConfigCommon->initialUplinkBWP->genericParameters; sib1->servingCellConfigCommon->uplinkConfigCommon->initialUplinkBWP.rach_ConfigCommon = configuration->scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon; + sib1->servingCellConfigCommon->uplinkConfigCommon->initialUplinkBWP.pusch_ConfigCommon = configuration->scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon; + sib1->servingCellConfigCommon->uplinkConfigCommon->initialUplinkBWP.pusch_ConfigCommon->choice.setup->groupHoppingEnabledTransformPrecoding = null; + sib1->servingCellConfigCommon->uplinkConfigCommon->initialUplinkBWP.pucch_ConfigCommon = configuration->scc->uplinkConfigCommon->initialUplinkBWP->pucch_ConfigCommon; + sib1->servingCellConfigCommon->uplinkConfigCommon->timeAlignmentTimerCommon = NR_TimeAlignmentTimer_infinity; + sib1->servingCellConfigCommon->n_TimingAdvanceOffset = configuration->scc->n_TimingAdvanceOffset; - sib1->servingCellConfigCommon->ssb_PositionsInBurst.inOneGroup = configuration->scc->ssb_PositionsInBurst->choice.shortBitmap; + + sib1->servingCellConfigCommon->ssb_PositionsInBurst.inOneGroup.buf = calloc(1, sizeof(uint8_t)); + uint8_t bitmap8,temp_bitmap=0; + switch (configuration->scc->ssb_PositionsInBurst->present) { + case NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_shortBitmap: + sib1->servingCellConfigCommon->ssb_PositionsInBurst.inOneGroup = configuration->scc->ssb_PositionsInBurst->choice.shortBitmap; + break; + case NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_mediumBitmap: + sib1->servingCellConfigCommon->ssb_PositionsInBurst.inOneGroup = configuration->scc->ssb_PositionsInBurst->choice.mediumBitmap; + break; + /* + groupPresence: This field is present when maximum number of SS/PBCH blocks per half frame equals to 64 as defined in TS 38.213 [13], clause 4.1. + The first/leftmost bit corresponds to the SS/PBCH index 0-7, the second bit corresponds to SS/PBCH block 8-15, and so on. + Value 0 in the bitmap indicates that the SSBs according to inOneGroup are absent. Value 1 indicates that the SS/PBCH blocks are transmitted in accordance with inOneGroup. + inOneGroup: When maximum number of SS/PBCH blocks per half frame equals to 64 as defined in TS 38.213 [13], clause 4.1, all 8 bit are valid; + The first/ leftmost bit corresponds to the first SS/PBCH block index in the group (i.e., to SSB index 0, 8, and so on); the second bit corresponds to the second SS/PBCH block index in the group + (i.e., to SSB index 1, 9, and so on), and so on. Value 0 in the bitmap indicates that the corresponding SS/PBCH block is not transmitted while value 1 indicates that the corresponding SS/PBCH block is transmitted. + */ + case NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_longBitmap: + sib1->servingCellConfigCommon->ssb_PositionsInBurst.inOneGroup.size = 1; + sib1->servingCellConfigCommon->ssb_PositionsInBurst.inOneGroup.bits_unused = 0; + sib1->servingCellConfigCommon->ssb_PositionsInBurst.groupPresence = calloc(1, sizeof(BIT_STRING_t)); + memset(sib1->servingCellConfigCommon->ssb_PositionsInBurst.groupPresence, 0, sizeof(BIT_STRING_t)); + sib1->servingCellConfigCommon->ssb_PositionsInBurst.groupPresence->size = 1; + sib1->servingCellConfigCommon->ssb_PositionsInBurst.groupPresence->bits_unused = 0; + sib1->servingCellConfigCommon->ssb_PositionsInBurst.groupPresence->buf = calloc(1, sizeof(uint8_t)); + sib1->servingCellConfigCommon->ssb_PositionsInBurst.groupPresence->buf[0] = 0; + for (int i=0; i<8; i++){ + bitmap8 = configuration->scc->ssb_PositionsInBurst->choice.longBitmap.buf[i]; + if (bitmap8!=0){ + if(temp_bitmap==0) + temp_bitmap = bitmap8; + else + AssertFatal(temp_bitmap==bitmap8,"For longBitmap the groups of 8 SSBs containing at least 1 transmitted SSB should be all the same\n"); + + sib1->servingCellConfigCommon->ssb_PositionsInBurst.inOneGroup.buf[0] = bitmap8; + sib1->servingCellConfigCommon->ssb_PositionsInBurst.groupPresence->buf[0] |= 1<<(7-i); + } + } + break; + default: + AssertFatal(false,"ssb_PositionsInBurst not present\n"); + break; + } + sib1->servingCellConfigCommon->ssb_PeriodicityServingCell = *configuration->scc->ssb_periodicityServingCell; sib1->servingCellConfigCommon->tdd_UL_DL_ConfigurationCommon = CALLOC(1,sizeof(struct NR_TDD_UL_DL_ConfigCommon)); sib1->servingCellConfigCommon->tdd_UL_DL_ConfigurationCommon->referenceSubcarrierSpacing = configuration->scc->tdd_UL_DL_ConfigurationCommon->referenceSubcarrierSpacing; @@ -437,7 +610,14 @@ uint8_t do_SIB1_NR(rrc_gNB_carrier_data_t *carrier, // TODO: add eCallOverIMS-Support // ue-TimersAndConstants - // TODO: add ue-TimersAndConstants + sib1->ue_TimersAndConstants = CALLOC(1,sizeof(struct NR_UE_TimersAndConstants)); + sib1->ue_TimersAndConstants->t300 = NR_UE_TimersAndConstants__t300_ms400; + sib1->ue_TimersAndConstants->t301 = NR_UE_TimersAndConstants__t301_ms400; + sib1->ue_TimersAndConstants->t310 = NR_UE_TimersAndConstants__t310_ms2000; + sib1->ue_TimersAndConstants->n310 = NR_UE_TimersAndConstants__n310_n10; + sib1->ue_TimersAndConstants->t311 = NR_UE_TimersAndConstants__t311_ms3000; + sib1->ue_TimersAndConstants->n311 = NR_UE_TimersAndConstants__n311_n1; + sib1->ue_TimersAndConstants->t319 = NR_UE_TimersAndConstants__t319_ms400; // uac-BarringInfo /*sib1->uac_BarringInfo = CALLOC(1, sizeof(struct NR_SIB1__uac_BarringInfo)); diff --git a/openair2/RRC/NR/nr_ngap_gNB.c b/openair2/RRC/NR/nr_ngap_gNB.c deleted file mode 100644 index 88c0762c99..0000000000 --- a/openair2/RRC/NR/nr_ngap_gNB.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.openairinterface.org/?page_id=698 - * - * Author and copyright: Laurent Thomas, open-cells.com - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ -#include -#include - -void rrc_gNB_process_NGAP_DOWNLINK_NAS (void ) { - do_DLInformationTransfer(0,NULL,0,0,NULL); - // send it as DL data -/* - rrc_data_req ( - &ctxt, - srb_id, - (*rrc_eNB_mui)++, - SDU_CONFIRM_NO, - length, - buffer, - PDCP_TRANSMISSION_MODE_CONTROL); -*/ - -} - -void rrc_gNB_send_NGAP_NAS_FIRST_REQ(void ) { - // We are noCore only now - // create message that should come from 5GC - - // send it dow - rrc_gNB_process_NGAP_DOWNLINK_NAS(); -} - -void nr_rrc_rx_tx(void) { - // check timers - - // check if UEs are lost, to remove them from upper layers - - // - -} diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h index 93a1b8da1c..c4f993e569 100644 --- a/openair2/RRC/NR/nr_rrc_defs.h +++ b/openair2/RRC/NR/nr_rrc_defs.h @@ -458,6 +458,15 @@ typedef struct { //--------------------------------------------------- +typedef struct { + /* nea0 = 0, nea1 = 1, ... */ + int ciphering_algorithms[4]; + int ciphering_algorithms_count; + + /* nia0 = 0, nia1 = 1, ... */ + int integrity_algorithms[4]; + int integrity_algorithms_count; +} nr_security_configuration_t; //---NR---(completely change)--------------------- typedef struct gNB_RRC_INST_s { @@ -503,6 +512,8 @@ typedef struct gNB_RRC_INST_s { int cell_info_configured; pthread_mutex_t cell_info_mutex; + // security configuration (preferred algorithms) + nr_security_configuration_t security; } gNB_RRC_INST; #include "nr_rrc_proto.h" //should be put here otherwise compilation error diff --git a/openair2/RRC/NR/nr_rrc_proto.h b/openair2/RRC/NR/nr_rrc_proto.h index cf92bac398..6d876a0eef 100644 --- a/openair2/RRC/NR/nr_rrc_proto.h +++ b/openair2/RRC/NR/nr_rrc_proto.h @@ -39,6 +39,7 @@ #include "LTE_UE-CapabilityRAT-ContainerList.h" #include "NR_CG-Config.h" #include "NR_CG-ConfigInfo.h" +#include "NR_SecurityConfig.h" int rrc_init_nr_global_param(void); @@ -65,7 +66,7 @@ void rrc_gNB_generate_SgNBAdditionRequestAcknowledge( struct rrc_gNB_ue_context_s *rrc_gNB_allocate_new_UE_context(gNB_RRC_INST *rrc_instance_pP); -void rrc_parse_ue_capabilities(gNB_RRC_INST *rrc,LTE_UE_CapabilityRAT_ContainerList_t *UE_CapabilityRAT_ContainerList, x2ap_ENDC_sgnb_addition_req_t *m, NR_CG_ConfigInfo_IEs_t * cg_config_info); +void rrc_parse_ue_capabilities(gNB_RRC_INST *rrc,NR_UE_CapabilityRAT_ContainerList_t *UE_CapabilityRAT_ContainerList, x2ap_ENDC_sgnb_addition_req_t *m, NR_CG_ConfigInfo_IEs_t * cg_config_info); void rrc_add_nsa_user(gNB_RRC_INST *rrc,struct rrc_gNB_ue_context_s *ue_context_p, x2ap_ENDC_sgnb_addition_req_t *m); @@ -90,7 +91,10 @@ void fill_default_reconfig(NR_ServingCellConfigCommon_t *servingcellconfigcommon int n_physical_antenna_ports, int initial_csi_index); -void fill_default_rbconfig(NR_RadioBearerConfig_t *rbconfig); +void fill_default_rbconfig(NR_RadioBearerConfig_t *rbconfig, + int eps_bearer_id, int rb_id, + e_NR_CipheringAlgorithm ciphering_algorithm, + e_NR_SecurityConfig__keyToUse key_to_use); int generate_CG_Config(gNB_RRC_INST *rrc, NR_CG_Config_t *cg_Config, diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c old mode 100644 new mode 100755 index 8ba463f199..17812636f1 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -104,7 +104,8 @@ extern boolean_t nr_rrc_pdcp_config_asn1_req( const uint8_t security_modeP, uint8_t *const kRRCenc, uint8_t *const kRRCint, - uint8_t *const kUPenc + uint8_t *const kUPenc, + uint8_t *const kUPint #if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0)) ,LTE_PMCH_InfoList_r9_t *pmch_InfoList_r9 #endif @@ -217,6 +218,9 @@ static void init_NR_SI(gNB_RRC_INST *rrc, gNB_RrcConfigurationReq *configuration rrc->carrier.MIB = (uint8_t *) malloc16(4); rrc->carrier.sizeof_MIB = do_MIB_NR(rrc,0); rrc->carrier.sizeof_SIB1 = do_SIB1_NR(&rrc->carrier,configuration); + if(get_softmodem_params()->sa) { + rrc->carrier.sizeof_SIB1 = do_SIB1_NR(&rrc->carrier,configuration); + } } @@ -227,6 +231,7 @@ static void init_NR_SI(gNB_RRC_INST *rrc, gNB_RrcConfigurationReq *configuration LOG_I(NR_RRC,"do_SIB23_NR, size %d \n ", rrc->carrier.sizeof_SIB23); AssertFatal(rrc->carrier.sizeof_SIB23 != 255,"FATAL, RC.nrrrc[mod].carrier[CC_id].sizeof_SIB23 == 255"); } + LOG_I(NR_RRC,"Done init_NR_SI\n"); if (NODE_IS_MONOLITHIC(rrc->node_type)){ rrc_mac_config_req_gNB(rrc->module_id, @@ -447,45 +452,11 @@ rrc_gNB_generate_RRCSetup( PROTOCOL_NR_RRC_CTXT_UE_FMT" [RAPROC] Logical Channel DL-CCCH, Generating RRCSetup (bytes %d)\n", PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP), ue_p->Srb0.Tx_buffer.payload_size); - uint8_t *message_buffer; - message_buffer = itti_malloc (TASK_RRC_GNB, TASK_RRC_UE_SIM, - ue_p->Srb0.Tx_buffer.payload_size); - memcpy (message_buffer, (uint8_t*)ue_p->Srb0.Tx_buffer.Payload, ue_p->Srb0.Tx_buffer.payload_size); - message_p = itti_alloc_new_message (TASK_RRC_GNB, 0, GNB_RRC_CCCH_DATA_IND); - GNB_RRC_CCCH_DATA_IND (message_p).sdu = message_buffer; - GNB_RRC_CCCH_DATA_IND (message_p).size = ue_p->Srb0.Tx_buffer.payload_size; - itti_send_msg_to_task (TASK_RRC_UE_SIM, ctxt_pP->instance, message_p); -#else - LOG_D(NR_RRC, - PROTOCOL_NR_RRC_CTXT_UE_FMT" RRC_gNB --- MAC_CONFIG_REQ (SRB1) ---> MAC_gNB\n", - PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP)); - MSC_LOG_TX_MESSAGE( - MSC_RRC_GNB, - MSC_RRC_UE, - ue_p->Srb0.Tx_buffer.Header, // LG WARNING - ue_p->Srb0.Tx_buffer.payload_size, - MSC_AS_TIME_FMT" RRCSetup UE %x size %u", - MSC_AS_TIME_ARGS(ctxt_pP), - ue_context_pP->ue_context.rnti, - ue_p->Srb0.Tx_buffer.payload_size); - LOG_I(NR_RRC, - PROTOCOL_NR_RRC_CTXT_UE_FMT" [RAPROC] Logical Channel DL-CCCH, Generating RRCSetup (bytes %d)\n", - PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP), - ue_p->Srb0.Tx_buffer.payload_size); - // activate release timer, if RRCSetupComplete not received after 100 frames, remove UE - ue_context_pP->ue_context.ue_release_timer = 1; - // remove UE after 10 frames after RRCConnectionRelease is triggered - ue_context_pP->ue_context.ue_release_timer_thres = 1000; - /* init timers */ - // ue_context_pP->ue_context.ue_rrc_inactivity_timer = 0; - - nr_rrc_data_req(ctxt_pP, - DCCH, - rrc_gNB_mui++, - SDU_CONFIRM_NO, - ue_p->Srb0.Tx_buffer.payload_size, - (uint8_t *)ue_p->Srb0.Tx_buffer.Payload, - PDCP_TRANSMISSION_MODE_CONTROL); + memcpy (message_buffer, (uint8_t*)ue_p->Srb0.Tx_buffer.Payload, ue_p->Srb0.Tx_buffer.payload_size); + message_p = itti_alloc_new_message (TASK_RRC_GNB, 0, GNB_RRC_CCCH_DATA_IND); + GNB_RRC_CCCH_DATA_IND (message_p).sdu = message_buffer; + GNB_RRC_CCCH_DATA_IND (message_p).size = ue_p->Srb0.Tx_buffer.payload_size; + itti_send_msg_to_task (TASK_RRC_UE_SIM, ctxt_pP->instance, message_p); #endif } break; @@ -628,14 +599,15 @@ rrc_gNB_generate_RRCReject( case ngran_gNB: { #ifdef ITTI_SIM - uint8_t *message_buffer; - message_buffer = itti_malloc (TASK_RRC_GNB, TASK_RRC_UE_SIM, - ue_p->Srb0.Tx_buffer.payload_size); - memcpy (message_buffer, (uint8_t*)ue_p->Srb0.Tx_buffer.Payload, ue_p->Srb0.Tx_buffer.payload_size); - message_p = itti_alloc_new_message (TASK_RRC_GNB, 0, GNB_RRC_CCCH_DATA_IND); - GNB_RRC_CCCH_DATA_IND (message_p).sdu = message_buffer; - GNB_RRC_CCCH_DATA_IND (message_p).size = ue_p->Srb0.Tx_buffer.payload_size; - itti_send_msg_to_task (TASK_RRC_UE_SIM, ctxt_pP->instance, message_p); + MessageDef *message_p; + uint8_t *message_buffer; + message_buffer = itti_malloc (TASK_RRC_GNB, TASK_RRC_UE_SIM, + ue_p->Srb0.Tx_buffer.payload_size); + memcpy (message_buffer, (uint8_t*)ue_p->Srb0.Tx_buffer.Payload, ue_p->Srb0.Tx_buffer.payload_size); + message_p = itti_alloc_new_message (TASK_RRC_GNB, 0, GNB_RRC_CCCH_DATA_IND); + GNB_RRC_CCCH_DATA_IND (message_p).sdu = message_buffer; + GNB_RRC_CCCH_DATA_IND (message_p).size = ue_p->Srb0.Tx_buffer.payload_size; + itti_send_msg_to_task (TASK_RRC_UE_SIM, ctxt_pP->instance, message_p); #endif // rrc_mac_config_req_gNB } @@ -840,14 +812,24 @@ rrc_gNB_generate_defaultRRCReconfiguration( ue_context_pP->ue_context.rnti, rrc_gNB_mui, size); - nr_rrc_data_req(ctxt_pP, - DCCH, - rrc_gNB_mui++, - SDU_CONFIRM_NO, - size, - buffer, - PDCP_TRANSMISSION_MODE_CONTROL); - // rrc_pdcp_config_asn1_req +#ifdef ITTI_SIM + MessageDef *message_p; + uint8_t *message_buffer; + message_buffer = itti_malloc (TASK_RRC_GNB, TASK_RRC_UE_SIM, size); + memcpy (message_buffer, buffer, size); + message_p = itti_alloc_new_message (TASK_RRC_GNB, 0, GNB_RRC_DCCH_DATA_IND); + GNB_RRC_DCCH_DATA_IND (message_p).rbid = DCCH; + GNB_RRC_DCCH_DATA_IND (message_p).sdu = message_buffer; + GNB_RRC_DCCH_DATA_IND (message_p).size = size; + itti_send_msg_to_task (TASK_RRC_UE_SIM, ctxt_pP->instance, message_p); +#else + nr_rrc_data_req(ctxt_pP, + DCCH, + rrc_gNB_mui++, + SDU_CONFIRM_NO, + size, + buffer, + PDCP_TRANSMISSION_MODE_CONTROL); #endif // rrc_rlc_config_asn1_req } @@ -1018,6 +1000,7 @@ rrc_gNB_process_RRCReconfigurationComplete( kUPenc, NULL, NULL, + NULL, NULL); /* Refresh SRBs/DRBs */ if (!NODE_IS_CU(RC.nrrrc[ctxt_pP->module_id]->node_type)) { @@ -1083,6 +1066,7 @@ rrc_gNB_process_RRCReconfigurationComplete( // rrc_mac_config_req_eNB } else { // remove LCHAN from MAC/PHY if (ue_context_pP->ue_context.DRB_active[drb_id] == 1) { + /* TODO : It may be needed if gNB goes into full stack working. */ // DRB has just been removed so remove RLC + PDCP for DRB /* rrc_pdcp_config_req (ctxt_pP->module_id, frameP, 1, CONFIG_ACTION_REMOVE, (ue_mod_idP * NB_RB_MAX) + DRB2LCHAN[i],UNDEF_SECURITY_MODE); @@ -1182,6 +1166,7 @@ rrc_gNB_generate_RRCReestablishment( PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP), ue_context->Srb0.Tx_buffer.payload_size); #if(0) + /* TODO : It may be needed if gNB goes into full stack working. */ UE_id = find_nr_UE_id(module_id, rnti); if (UE_id != -1) { /* Activate reject timer, if RRCComplete not received after 10 frames, reject UE */ @@ -1691,6 +1676,7 @@ int nr_rrc_gNB_decode_ccch(protocol_ctxt_t *const ctxt_pP, break; } #if(0) + /* TODO : It may be needed if gNB goes into full stack working. */ int UE_id = find_nr_UE_id(ctxt_pP->module_id, c_rnti); if(UE_id == -1) { @@ -1832,6 +1818,7 @@ int nr_rrc_gNB_decode_ccch(protocol_ctxt_t *const ctxt_pP, // NULL, // NULL, // NULL, + // NULL, // NULL); // if (!NODE_IS_CU(RC.nrrrc[ctxt_pP->module_id]->node_type)) { @@ -2339,6 +2326,7 @@ rrc_gNB_decode_dcch( } #if(0) + /* TODO : It may be needed if gNB goes into full stack working. */ //clear int UE_id = find_nr_UE_id(ctxt_pP->module_id, ctxt_pP->rnti); @@ -2533,19 +2521,18 @@ void *rrc_gnb_task(void *args_p) { /* Messages from MAC */ case NR_RRC_MAC_CCCH_DATA_IND: - PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, - NR_RRC_MAC_CCCH_DATA_IND(msg_p).gnb_index, - GNB_FLAG_YES, - NR_RRC_MAC_CCCH_DATA_IND(msg_p).rnti, - msg_p->ittiMsgHeader.lte_time.frame, - msg_p->ittiMsgHeader.lte_time.slot); - LOG_I(NR_RRC,"Decoding CCCH : ue %d, inst %ld, CC_id %d, ctxt %p, sib_info_p->Rx_buffer.payload_size %d\n", - ctxt.rnti, - instance, - NR_RRC_MAC_CCCH_DATA_IND(msg_p).CC_id, - &ctxt, - NR_RRC_MAC_CCCH_DATA_IND(msg_p).sdu_size); - + PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, + NR_RRC_MAC_CCCH_DATA_IND(msg_p).gnb_index, + GNB_FLAG_YES, + NR_RRC_MAC_CCCH_DATA_IND(msg_p).rnti, + msg_p->ittiMsgHeader.lte_time.frame, + msg_p->ittiMsgHeader.lte_time.slot); + LOG_I(NR_RRC,"Decoding CCCH : inst %ld, CC_id %d, ctxt %p, sib_info_p->Rx_buffer.payload_size %d\n", + instance, + NR_RRC_MAC_CCCH_DATA_IND(msg_p).CC_id, + &ctxt, + NR_RRC_MAC_CCCH_DATA_IND(msg_p).sdu_size); + if (NR_RRC_MAC_CCCH_DATA_IND(msg_p).sdu_size >= CCCH_SDU_SIZE) { LOG_I(NR_RRC, "CCCH message has size %d > %d\n", NR_RRC_MAC_CCCH_DATA_IND(msg_p).sdu_size,CCCH_SDU_SIZE); @@ -2777,15 +2764,15 @@ rrc_gNB_generate_SecurityModeCommand( rrc_gNB_mui, size); #ifdef ITTI_SIM - MessageDef *message_p; - uint8_t *message_buffer; - message_buffer = itti_malloc (TASK_RRC_GNB, TASK_RRC_UE_SIM,size); - memcpy (message_buffer, buffer, size); - message_p = itti_alloc_new_message (TASK_RRC_GNB, 0, GNB_RRC_DCCH_DATA_IND); - GNB_RRC_DCCH_DATA_IND (message_p).rbid = DCCH; - GNB_RRC_DCCH_DATA_IND (message_p).sdu = message_buffer; - GNB_RRC_DCCH_DATA_IND (message_p).size = size; - itti_send_msg_to_task (TASK_RRC_UE_SIM, ctxt_pP->instance, message_p); + MessageDef *message_p; + uint8_t *message_buffer; + message_buffer = itti_malloc (TASK_RRC_GNB, TASK_RRC_UE_SIM,size); + memcpy (message_buffer, buffer, size); + message_p = itti_alloc_new_message (TASK_RRC_GNB, 0, GNB_RRC_DCCH_DATA_IND); + GNB_RRC_DCCH_DATA_IND (message_p).rbid = DCCH; + GNB_RRC_DCCH_DATA_IND (message_p).sdu = message_buffer; + GNB_RRC_DCCH_DATA_IND (message_p).size = size; + itti_send_msg_to_task (TASK_RRC_UE_SIM, ctxt_pP->instance, message_p); #else LOG_I(NR_RRC,"calling rrc_data_req :securityModeCommand\n"); nr_rrc_data_req(ctxt_pP, @@ -2859,15 +2846,15 @@ rrc_gNB_generate_UECapabilityEnquiry( rrc_gNB_mui, size); #ifdef ITTI_SIM - MessageDef *message_p; - uint8_t *message_buffer; - message_buffer = itti_malloc (TASK_RRC_GNB, TASK_RRC_UE_SIM, size); - memcpy (message_buffer, buffer, size); - message_p = itti_alloc_new_message (TASK_RRC_GNB, 0, GNB_RRC_DCCH_DATA_IND); - GNB_RRC_DCCH_DATA_IND (message_p).rbid = DCCH; - GNB_RRC_DCCH_DATA_IND (message_p).sdu = message_buffer; - GNB_RRC_DCCH_DATA_IND (message_p).size = size; - itti_send_msg_to_task (TASK_RRC_UE_SIM, ctxt_pP->instance, message_p); + MessageDef *message_p; + uint8_t *message_buffer; + message_buffer = itti_malloc (TASK_RRC_GNB, TASK_RRC_UE_SIM, size); + memcpy (message_buffer, buffer, size); + message_p = itti_alloc_new_message (TASK_RRC_GNB, 0, GNB_RRC_DCCH_DATA_IND); + GNB_RRC_DCCH_DATA_IND (message_p).rbid = DCCH; + GNB_RRC_DCCH_DATA_IND (message_p).sdu = message_buffer; + GNB_RRC_DCCH_DATA_IND (message_p).size = size; + itti_send_msg_to_task (TASK_RRC_UE_SIM, ctxt_pP->instance, message_p); #else nr_rrc_data_req( ctxt_pP, diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index b4c5169e06..0c10dfbad1 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -450,32 +450,44 @@ rrc_gNB_send_NGAP_NAS_FIRST_REQ( /* TODO */ } - /* amf_Identifier */ - uint32_t amf_Id = BIT_STRING_to_uint32(&r_amf->amf_Identifier); - NGAP_NAS_FIRST_REQ(message_p).ue_identity.guami.amf_region_id = amf_Id >> 16; - NGAP_NAS_FIRST_REQ(message_p).ue_identity.guami.amf_set_id = ue_context_pP->ue_context.Initialue_identity_5g_s_TMSI.amf_set_id; - NGAP_NAS_FIRST_REQ(message_p).ue_identity.guami.amf_pointer = ue_context_pP->ue_context.Initialue_identity_5g_s_TMSI.amf_pointer; - - ue_context_pP->ue_context.ue_guami.mcc = NGAP_NAS_FIRST_REQ(message_p).ue_identity.guami.mcc; - ue_context_pP->ue_context.ue_guami.mnc = NGAP_NAS_FIRST_REQ(message_p).ue_identity.guami.mnc; - ue_context_pP->ue_context.ue_guami.mnc_len = NGAP_NAS_FIRST_REQ(message_p).ue_identity.guami.mnc_len; - ue_context_pP->ue_context.ue_guami.amf_region_id = NGAP_NAS_FIRST_REQ(message_p).ue_identity.guami.amf_region_id; - ue_context_pP->ue_context.ue_guami.amf_set_id = NGAP_NAS_FIRST_REQ(message_p).ue_identity.guami.amf_set_id; - ue_context_pP->ue_context.ue_guami.amf_pointer = NGAP_NAS_FIRST_REQ(message_p).ue_identity.guami.amf_pointer; - - MSC_LOG_TX_MESSAGE(MSC_NGAP_GNB, - MSC_NGAP_AMF, - (const char *)&message_p->ittiMsg.ngap_nas_first_req, - sizeof(ngap_nas_first_req_t), - MSC_AS_TIME_FMT" NGAP_NAS_FIRST_REQ gNB %u UE %x", - MSC_AS_TIME_ARGS(ctxt_pP), - ctxt_pP->module_id, - ctxt_pP->rnti); - LOG_I(NGAP, "[gNB %d] Build NGAP_NAS_FIRST_REQ adding in s_TMSI: GUAMI amf_set_id %u amf_region_id %u ue %x\n", + if (r_amf->plmn_Identity->mnc.list.count > 0) { + /* Use first indicated PLMN MNC if it is defined */ + NGAP_NAS_FIRST_REQ(message_p).ue_identity.guami.mnc = *r_amf->plmn_Identity->mnc.list.array[selected_plmn_identity]; + LOG_I(NGAP, "[gNB %d] Build NGAP_NAS_FIRST_REQ adding in s_TMSI: GUMMEI MNC %u ue %x\n", ctxt_pP->module_id, - NGAP_NAS_FIRST_REQ (message_p).ue_identity.guami.amf_set_id, - NGAP_NAS_FIRST_REQ (message_p).ue_identity.guami.amf_region_id, + NGAP_NAS_FIRST_REQ (message_p).ue_identity.guami.mnc, ue_context_pP->ue_context.rnti); + } + } else { + /* TODO */ + } + + /* amf_Identifier */ + uint32_t amf_Id = BIT_STRING_to_uint32(&r_amf->amf_Identifier); + NGAP_NAS_FIRST_REQ(message_p).ue_identity.guami.amf_region_id = amf_Id >> 16; + NGAP_NAS_FIRST_REQ(message_p).ue_identity.guami.amf_set_id = ue_context_pP->ue_context.Initialue_identity_5g_s_TMSI.amf_set_id; + NGAP_NAS_FIRST_REQ(message_p).ue_identity.guami.amf_pointer = ue_context_pP->ue_context.Initialue_identity_5g_s_TMSI.amf_pointer; + + ue_context_pP->ue_context.ue_guami.mcc = NGAP_NAS_FIRST_REQ(message_p).ue_identity.guami.mcc; + ue_context_pP->ue_context.ue_guami.mnc = NGAP_NAS_FIRST_REQ(message_p).ue_identity.guami.mnc; + ue_context_pP->ue_context.ue_guami.mnc_len = NGAP_NAS_FIRST_REQ(message_p).ue_identity.guami.mnc_len; + ue_context_pP->ue_context.ue_guami.amf_region_id = NGAP_NAS_FIRST_REQ(message_p).ue_identity.guami.amf_region_id; + ue_context_pP->ue_context.ue_guami.amf_set_id = NGAP_NAS_FIRST_REQ(message_p).ue_identity.guami.amf_set_id; + ue_context_pP->ue_context.ue_guami.amf_pointer = NGAP_NAS_FIRST_REQ(message_p).ue_identity.guami.amf_pointer; + + MSC_LOG_TX_MESSAGE(MSC_NGAP_GNB, + MSC_NGAP_AMF, + (const char *)&message_p->ittiMsg.ngap_nas_first_req, + sizeof(ngap_nas_first_req_t), + MSC_AS_TIME_FMT" NGAP_NAS_FIRST_REQ gNB %u UE %x", + MSC_AS_TIME_ARGS(ctxt_pP), + ctxt_pP->module_id, + ctxt_pP->rnti); + LOG_I(NGAP, "[gNB %d] Build NGAP_NAS_FIRST_REQ adding in s_TMSI: GUAMI amf_set_id %u amf_region_id %u ue %x\n", + ctxt_pP->module_id, + NGAP_NAS_FIRST_REQ (message_p).ue_identity.guami.amf_set_id, + NGAP_NAS_FIRST_REQ (message_p).ue_identity.guami.amf_region_id, + ue_context_pP->ue_context.rnti); } itti_send_msg_to_task (TASK_NGAP, ctxt_pP->instance, message_p); @@ -500,74 +512,74 @@ rrc_gNB_process_NGAP_INITIAL_CONTEXT_SETUP_REQ( gNB_ue_ngap_id = NGAP_INITIAL_CONTEXT_SETUP_REQ(msg_p).gNB_ue_ngap_id; ue_context_p = rrc_gNB_get_ue_context_from_ngap_ids(instance, ue_initial_id, gNB_ue_ngap_id); - LOG_I(NR_RRC, "[gNB %ld] Received %s: ue_initial_id %d, gNB_ue_ngap_id %d \n", + LOG_I(NR_RRC, "[gNB %ld] Received %s: ue_initial_id %d, gNB_ue_ngap_id %u \n", instance, msg_name, ue_initial_id, gNB_ue_ngap_id); if (ue_context_p == NULL) { - /* Can not associate this message to an UE index, send a failure to NGAP and discard it! */ - MessageDef *msg_fail_p = NULL; - LOG_W(NR_RRC, "[gNB %ld] In NGAP_INITIAL_CONTEXT_SETUP_REQ: unknown UE from NGAP ids (%d, %d)\n", instance, ue_initial_id, gNB_ue_ngap_id); - msg_fail_p = itti_alloc_new_message (TASK_RRC_GNB, 0, NGAP_INITIAL_CONTEXT_SETUP_FAIL); - NGAP_INITIAL_CONTEXT_SETUP_FAIL (msg_fail_p).gNB_ue_ngap_id = gNB_ue_ngap_id; - // TODO add failure cause when defined! - itti_send_msg_to_task (TASK_NGAP, instance, msg_fail_p); - return (-1); + /* Can not associate this message to an UE index, send a failure to NGAP and discard it! */ + MessageDef *msg_fail_p = NULL; + LOG_W(NR_RRC, "[gNB %ld] In NGAP_INITIAL_CONTEXT_SETUP_REQ: unknown UE from NGAP ids (%d, %u)\n", instance, ue_initial_id, gNB_ue_ngap_id); + msg_fail_p = itti_alloc_new_message (TASK_RRC_GNB, 0, NGAP_INITIAL_CONTEXT_SETUP_FAIL); + NGAP_INITIAL_CONTEXT_SETUP_FAIL (msg_fail_p).gNB_ue_ngap_id = gNB_ue_ngap_id; + // TODO add failure cause when defined! + itti_send_msg_to_task (TASK_NGAP, instance, msg_fail_p); + return (-1); } else { - PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, instance, GNB_FLAG_YES, ue_context_p->ue_context.rnti, 0, 0); - ue_context_p->ue_context.gNB_ue_ngap_id = NGAP_INITIAL_CONTEXT_SETUP_REQ (msg_p).gNB_ue_ngap_id; - ue_context_p->ue_context.amf_ue_ngap_id = NGAP_INITIAL_CONTEXT_SETUP_REQ (msg_p).amf_ue_ngap_id; - ue_context_p->ue_context.nas_pdu_flag = NGAP_INITIAL_CONTEXT_SETUP_REQ (msg_p).nas_pdu_flag; + PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, instance, GNB_FLAG_YES, ue_context_p->ue_context.rnti, 0, 0); + ue_context_p->ue_context.gNB_ue_ngap_id = NGAP_INITIAL_CONTEXT_SETUP_REQ (msg_p).gNB_ue_ngap_id; + ue_context_p->ue_context.amf_ue_ngap_id = NGAP_INITIAL_CONTEXT_SETUP_REQ (msg_p).amf_ue_ngap_id; + ue_context_p->ue_context.nas_pdu_flag = NGAP_INITIAL_CONTEXT_SETUP_REQ (msg_p).nas_pdu_flag; - if (NGAP_INITIAL_CONTEXT_SETUP_REQ(msg_p).nb_of_pdusessions != 0) { - ue_context_p->ue_context.nb_of_pdusessions = NGAP_INITIAL_CONTEXT_SETUP_REQ(msg_p).nb_of_pdusessions; - for (int i = 0; i < NR_NB_RB_MAX - 3; i++) { - if(ue_context_p->ue_context.pdusession[i].status >= PDU_SESSION_STATUS_DONE) - continue; - ue_context_p->ue_context.pdusession[i].status = PDU_SESSION_STATUS_NEW; - ue_context_p->ue_context.pdusession[i].param = NGAP_INITIAL_CONTEXT_SETUP_REQ (msg_p).pdusession_param[pdu_sessions_done]; - pdu_sessions_done++; + if (NGAP_INITIAL_CONTEXT_SETUP_REQ(msg_p).nb_of_pdusessions != 0) { + ue_context_p->ue_context.nb_of_pdusessions = NGAP_INITIAL_CONTEXT_SETUP_REQ(msg_p).nb_of_pdusessions; + for (int i = 0; i < NR_NB_RB_MAX - 3; i++) { + if(ue_context_p->ue_context.pdusession[i].status >= PDU_SESSION_STATUS_DONE) + continue; + ue_context_p->ue_context.pdusession[i].status = PDU_SESSION_STATUS_NEW; + ue_context_p->ue_context.pdusession[i].param = NGAP_INITIAL_CONTEXT_SETUP_REQ (msg_p).pdusession_param[pdu_sessions_done]; + pdu_sessions_done++; - // TODO establish PDU SESSION + // TODO establish PDU SESSION - if(pdu_sessions_done >= NGAP_INITIAL_CONTEXT_SETUP_REQ(msg_p).nb_of_pdusessions) { - break; - } - } + if(pdu_sessions_done >= NGAP_INITIAL_CONTEXT_SETUP_REQ(msg_p).nb_of_pdusessions) { + break; + } } + } - /* NAS PDU */ - ue_context_p->ue_context.nas_pdu_flag = NGAP_INITIAL_CONTEXT_SETUP_REQ(msg_p).nas_pdu_flag; - if (ue_context_p->ue_context.nas_pdu_flag == 1) { - ue_context_p->ue_context.nas_pdu.length = NGAP_INITIAL_CONTEXT_SETUP_REQ(msg_p).nas_pdu.length; - ue_context_p->ue_context.nas_pdu.buffer = NGAP_INITIAL_CONTEXT_SETUP_REQ(msg_p).nas_pdu.buffer; - } + /* NAS PDU */ + ue_context_p->ue_context.nas_pdu_flag = NGAP_INITIAL_CONTEXT_SETUP_REQ(msg_p).nas_pdu_flag; + if (ue_context_p->ue_context.nas_pdu_flag == 1) { + ue_context_p->ue_context.nas_pdu.length = NGAP_INITIAL_CONTEXT_SETUP_REQ(msg_p).nas_pdu.length; + ue_context_p->ue_context.nas_pdu.buffer = NGAP_INITIAL_CONTEXT_SETUP_REQ(msg_p).nas_pdu.buffer; + } - /* security */ - rrc_gNB_process_security(&ctxt, ue_context_p, &(NGAP_INITIAL_CONTEXT_SETUP_REQ(msg_p).security_capabilities)); - process_gNB_security_key ( + /* security */ + rrc_gNB_process_security(&ctxt, ue_context_p, &(NGAP_INITIAL_CONTEXT_SETUP_REQ(msg_p).security_capabilities)); + process_gNB_security_key ( + &ctxt, + ue_context_p, + NGAP_INITIAL_CONTEXT_SETUP_REQ(msg_p).security_key); + + uint8_t send_security_mode_command = TRUE; + + nr_rrc_pdcp_config_security( &ctxt, ue_context_p, - NGAP_INITIAL_CONTEXT_SETUP_REQ(msg_p).security_key); - - uint8_t send_security_mode_command = TRUE; + send_security_mode_command); - nr_rrc_pdcp_config_security( - &ctxt, - ue_context_p, - send_security_mode_command); + if (send_security_mode_command) { + rrc_gNB_generate_SecurityModeCommand (&ctxt, ue_context_p); + send_security_mode_command = FALSE; - if (send_security_mode_command) { - rrc_gNB_generate_SecurityModeCommand (&ctxt, ue_context_p); - send_security_mode_command = FALSE; - - nr_rrc_pdcp_config_security( - &ctxt, - ue_context_p, - send_security_mode_command); - } else { - /* rrc_gNB_generate_UECapabilityEnquiry */ - rrc_gNB_generate_UECapabilityEnquiry(&ctxt, ue_context_p); - } + nr_rrc_pdcp_config_security( + &ctxt, + ue_context_p, + send_security_mode_command); + } else { + /* rrc_gNB_generate_UECapabilityEnquiry */ + rrc_gNB_generate_UECapabilityEnquiry(&ctxt, ue_context_p); + } // in case, send the S1SP initial context response if it is not sent with the attach complete message if (ue_context_p->ue_context.Status == NR_RRC_RECONFIGURED) { @@ -737,7 +749,7 @@ rrc_gNB_process_NGAP_DOWNLINK_NAS( ue_initial_id = NGAP_DOWNLINK_NAS (msg_p).ue_initial_id; gNB_ue_ngap_id = NGAP_DOWNLINK_NAS (msg_p).gNB_ue_ngap_id; ue_context_p = rrc_gNB_get_ue_context_from_ngap_ids(instance, ue_initial_id, gNB_ue_ngap_id); - LOG_I(NR_RRC, "[gNB %ld] Received %s: ue_initial_id %d, gNB_ue_ngap_id %d\n", + LOG_I(NR_RRC, "[gNB %ld] Received %s: ue_initial_id %d, gNB_ue_ngap_id %u\n", instance, msg_name, ue_initial_id, @@ -755,7 +767,7 @@ rrc_gNB_process_NGAP_DOWNLINK_NAS( gNB_ue_ngap_id); /* Can not associate this message to an UE index, send a failure to NGAP and discard it! */ MessageDef *msg_fail_p; - LOG_W(NR_RRC, "[gNB %ld] In NGAP_DOWNLINK_NAS: unknown UE from NGAP ids (%d, %d)\n", instance, ue_initial_id, gNB_ue_ngap_id); + LOG_W(NR_RRC, "[gNB %ld] In NGAP_DOWNLINK_NAS: unknown UE from NGAP ids (%d, %u)\n", instance, ue_initial_id, gNB_ue_ngap_id); msg_fail_p = itti_alloc_new_message (TASK_RRC_GNB, 0, NGAP_NAS_NON_DELIVERY_IND); NGAP_NAS_NON_DELIVERY_IND (msg_fail_p).gNB_ue_ngap_id = gNB_ue_ngap_id; NGAP_NAS_NON_DELIVERY_IND (msg_fail_p).nas_pdu.length = NGAP_DOWNLINK_NAS (msg_p).nas_pdu.length; @@ -837,15 +849,16 @@ rrc_gNB_process_NGAP_DOWNLINK_NAS( { // rrc_mac_config_req_gNB #ifdef ITTI_SIM - uint8_t *message_buffer; - message_buffer = itti_malloc (TASK_RRC_GNB_SIM, TASK_RRC_UE_SIM, length); - memcpy (message_buffer, buffer, length); - message_p = itti_alloc_new_message (TASK_RRC_GNB_SIM, 0, GNB_RRC_DCCH_DATA_IND); - GNB_RRC_DCCH_DATA_IND (message_p).rbid = DCCH; - GNB_RRC_DCCH_DATA_IND (message_p).sdu = message_buffer; - GNB_RRC_DCCH_DATA_IND (message_p).size = length; - itti_send_msg_to_task (TASK_RRC_UE_SIM, instance, message_p); - LOG_I(NR_RRC, "Send DL NAS message \n"); + MessageDef *message_p; + uint8_t *message_buffer; + message_buffer = itti_malloc (TASK_RRC_GNB, TASK_RRC_UE_SIM, length); + memcpy (message_buffer, buffer, length); + message_p = itti_alloc_new_message (TASK_RRC_GNB, 0, GNB_RRC_DCCH_DATA_IND); + GNB_RRC_DCCH_DATA_IND (message_p).rbid = DCCH; + GNB_RRC_DCCH_DATA_IND (message_p).sdu = message_buffer; + GNB_RRC_DCCH_DATA_IND (message_p).size = length; + itti_send_msg_to_task (TASK_RRC_UE_SIM, instance, message_p); + LOG_I(NR_RRC, "Send DL NAS message \n"); #else #if(0) /* Transfer data to PDCP */ @@ -1006,12 +1019,12 @@ rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ( ue_initial_id = NGAP_PDUSESSION_SETUP_REQ(msg_p).ue_initial_id; gNB_ue_ngap_id = NGAP_PDUSESSION_SETUP_REQ(msg_p).gNB_ue_ngap_id; ue_context_p = rrc_gNB_get_ue_context_from_ngap_ids(instance, ue_initial_id, gNB_ue_ngap_id); - LOG_I(NR_RRC, "[gNB %ld] Received %s: ue_initial_id %d, gNB_ue_ngap_id %d \n", + LOG_I(NR_RRC, "[gNB %ld] Received %s: ue_initial_id %d, gNB_ue_ngap_id %u \n", instance, msg_name, ue_initial_id, gNB_ue_ngap_id); if (ue_context_p == NULL) { MessageDef *msg_fail_p = NULL; - LOG_W(NR_RRC, "[gNB %ld] In NGAP_PDUSESSION_SETUP_REQ: unknown UE from NGAP ids (%d, %d)\n", instance, ue_initial_id, gNB_ue_ngap_id); + LOG_W(NR_RRC, "[gNB %ld] In NGAP_PDUSESSION_SETUP_REQ: unknown UE from NGAP ids (%d, %u)\n", instance, ue_initial_id, gNB_ue_ngap_id); msg_fail_p = itti_alloc_new_message(TASK_RRC_GNB, 0, NGAP_PDUSESSION_SETUP_REQUEST_FAIL); NGAP_PDUSESSION_SETUP_REQ(msg_fail_p).gNB_ue_ngap_id = gNB_ue_ngap_id; // TODO add failure cause when defined! @@ -1124,7 +1137,7 @@ rrc_gNB_process_NGAP_UE_CONTEXT_RELEASE_REQ ( if (ue_context_p == NULL) { /* Can not associate this message to an UE index, send a failure to ngAP and discard it! */ MessageDef *msg_fail_p; - LOG_W(RRC, "[gNB %ld] In NGAP_UE_CONTEXT_RELEASE_REQ: unknown UE from gNB_ue_ngap_id (%d)\n", + LOG_W(RRC, "[gNB %ld] In NGAP_UE_CONTEXT_RELEASE_REQ: unknown UE from gNB_ue_ngap_id (%u)\n", instance, gNB_ue_ngap_id); msg_fail_p = itti_alloc_new_message(TASK_RRC_GNB, 0, NGAP_UE_CONTEXT_RELEASE_RESP); /* TODO change message ID. */ @@ -1166,7 +1179,7 @@ rrc_gNB_process_NGAP_UE_CONTEXT_RELEASE_COMMAND( if (ue_context_p == NULL) { /* Can not associate this message to an UE index */ MessageDef *msg_complete_p = NULL; - LOG_W(RRC, "[gNB %ld] In NGAP_UE_CONTEXT_RELEASE_COMMAND: unknown UE from gNB_ue_ngap_id (%d)\n", + LOG_W(NR_RRC, "[gNB %ld] In NGAP_UE_CONTEXT_RELEASE_COMMAND: unknown UE from gNB_ue_ngap_id (%u)\n", instance, gNB_ue_ngap_id); MSC_LOG_EVENT(MSC_RRC_GNB, "0 NGAP_UE_CONTEXT_RELEASE_COMPLETE gNB_ue_ngap_id 0x%06"PRIX32" context not found", @@ -1317,7 +1330,7 @@ rrc_gNB_send_NGAP_PDUSESSION_RELEASE_RESPONSE( memcpy(&(NGAP_PDUSESSION_RELEASE_RESPONSE (msg_p).pdusessions_failed[0]), &ue_context_pP->ue_context.pdusessions_release_failed[0], sizeof(pdusession_failed_t)*ue_context_pP->ue_context.nb_release_of_pdusessions); ue_context_pP->ue_context.setup_pdu_sessions -= pdu_sessions_released; - LOG_I(NR_RRC,"NGAP PDUSESSION RELEASE RESPONSE: GNB_UE_NGAP_ID %d release_pdu_sessions %d setup_pdu_sessions %d \n", + LOG_I(NR_RRC,"NGAP PDUSESSION RELEASE RESPONSE: GNB_UE_NGAP_ID %u release_pdu_sessions %d setup_pdu_sessions %d \n", NGAP_PDUSESSION_RELEASE_RESPONSE (msg_p).gNB_ue_ngap_id, pdu_sessions_released, ue_context_pP->ue_context.setup_pdu_sessions); itti_send_msg_to_task (TASK_NGAP, ctxt_pP->instance, msg_p); @@ -1360,12 +1373,12 @@ rrc_gNB_process_NGAP_PDUSESSION_RELEASE_COMMAND( return -1; } ue_context_p = rrc_gNB_get_ue_context_from_ngap_ids(instance, UE_INITIAL_ID_INVALID, gNB_ue_ngap_id); - LOG_I(NR_RRC, "[gNB %ld] Received %s: gNB_ue_ngap_id %d \n", instance, msg_name, gNB_ue_ngap_id); + LOG_I(NR_RRC, "[gNB %ld] Received %s: gNB_ue_ngap_id %u \n", instance, msg_name, gNB_ue_ngap_id); if (ue_context_p != NULL) { PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, instance, GNB_FLAG_YES, ue_context_p->ue_context.rnti, 0, 0); xid = rrc_gNB_get_next_transaction_identifier(ctxt.module_id); - LOG_I(NR_RRC,"PDU Session Release Command: AMF_UE_NGAP_ID %lu GNB_UE_NGAP_ID %d release_pdusessions %d \n", + LOG_I(NR_RRC,"PDU Session Release Command: AMF_UE_NGAP_ID %lu GNB_UE_NGAP_ID %u release_pdusessions %d \n", NGAP_PDUSESSION_RELEASE_COMMAND (msg_p).amf_ue_ngap_id&0x000000FFFFFFFFFF, gNB_ue_ngap_id, nb_pdusessions_torelease); for (pdusession = 0; pdusession < nb_pdusessions_torelease; pdusession++) { @@ -1443,10 +1456,20 @@ rrc_gNB_process_NGAP_PDUSESSION_RELEASE_COMMAND( LOG_I(NR_RRC, "Send PDU Session Release Response \n"); } } else { - LOG_E(NR_RRC, "PDU Session Release Command: AMF_UE_NGAP_ID %lu GNB_UE_NGAP_ID %d Error ue_context_p NULL \n", + LOG_E(NR_RRC, "PDU Session Release Command: AMF_UE_NGAP_ID %lu GNB_UE_NGAP_ID %u Error ue_context_p NULL \n", NGAP_PDUSESSION_RELEASE_COMMAND (msg_p).amf_ue_ngap_id&0x000000FFFFFFFFFF, NGAP_PDUSESSION_RELEASE_COMMAND(msg_p).gNB_ue_ngap_id); return -1; } return 0; } + +void nr_rrc_rx_tx(void) { + // check timers + + // check if UEs are lost, to remove them from upper layers + + // + +} + diff --git a/openair2/RRC/NR/rrc_gNB_internode.c b/openair2/RRC/NR/rrc_gNB_internode.c index abbb2ab984..c4cd41c5b4 100644 --- a/openair2/RRC/NR/rrc_gNB_internode.c +++ b/openair2/RRC/NR/rrc_gNB_internode.c @@ -47,10 +47,10 @@ int parse_CG_ConfigInfo(gNB_RRC_INST *rrc, NR_CG_ConfigInfo_t *CG_ConfigInfo, x2 if (cg_ConfigInfo->ue_CapabilityInfo) { // Decode UE-CapabilityRAT-ContainerList - LTE_UE_CapabilityRAT_ContainerList_t *UE_CapabilityRAT_ContainerList=NULL; - UE_CapabilityRAT_ContainerList = calloc(1,sizeof(LTE_UE_CapabilityRAT_ContainerList_t)); + NR_UE_CapabilityRAT_ContainerList_t *UE_CapabilityRAT_ContainerList=NULL; + UE_CapabilityRAT_ContainerList = calloc(1,sizeof(NR_UE_CapabilityRAT_ContainerList_t)); asn_dec_rval_t dec_rval = uper_decode(NULL, - &asn_DEF_LTE_UE_CapabilityRAT_ContainerList, + &asn_DEF_NR_UE_CapabilityRAT_ContainerList, (void **)&UE_CapabilityRAT_ContainerList, cg_ConfigInfo->ue_CapabilityInfo->buf, cg_ConfigInfo->ue_CapabilityInfo->size, 0, 0); diff --git a/openair2/RRC/NR/rrc_gNB_nsa.c b/openair2/RRC/NR/rrc_gNB_nsa.c index 74b8d458ad..5ea02c7832 100644 --- a/openair2/RRC/NR/rrc_gNB_nsa.c +++ b/openair2/RRC/NR/rrc_gNB_nsa.c @@ -39,6 +39,7 @@ #include "openair2/RRC/LTE/rrc_eNB_GTPV1U.h" #include "executables/softmodem-common.h" #include +#include "UTIL/OSA/osa_defs.h" extern boolean_t nr_rrc_pdcp_config_asn1_req( const protocol_ctxt_t *const ctxt_pP, @@ -48,7 +49,8 @@ extern boolean_t nr_rrc_pdcp_config_asn1_req( const uint8_t security_modeP, uint8_t *const kRRCenc, uint8_t *const kRRCint, - uint8_t *const kUPenc + uint8_t *const kUPenc, + uint8_t *const kUPint #if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0)) ,LTE_PMCH_InfoList_r9_t *pmch_InfoList_r9 #endif @@ -62,7 +64,7 @@ extern rlc_op_status_t nr_rrc_rlc_config_asn1_req (const protocol_ctxt_t * con const LTE_PMCH_InfoList_r9_t * const pmch_InfoList_r9_pP, struct NR_CellGroupConfig__rlc_BearerToAddModList *rlc_bearer2add_list); -void rrc_parse_ue_capabilities(gNB_RRC_INST *rrc, LTE_UE_CapabilityRAT_ContainerList_t *UE_CapabilityRAT_ContainerList, x2ap_ENDC_sgnb_addition_req_t *m, NR_CG_ConfigInfo_IEs_t *cg_config_info) { +void rrc_parse_ue_capabilities(gNB_RRC_INST *rrc, NR_UE_CapabilityRAT_ContainerList_t *UE_CapabilityRAT_ContainerList, x2ap_ENDC_sgnb_addition_req_t *m, NR_CG_ConfigInfo_IEs_t *cg_config_info) { struct rrc_gNB_ue_context_s *ue_context_p = NULL; OCTET_STRING_t *ueCapabilityRAT_Container_nr=NULL; @@ -74,8 +76,8 @@ void rrc_parse_ue_capabilities(gNB_RRC_INST *rrc, LTE_UE_CapabilityRAT_Container AssertFatal((list_size=UE_CapabilityRAT_ContainerList->list.count) >= 2, "UE_CapabilityRAT_ContainerList->list.size %d < 2\n",UE_CapabilityRAT_ContainerList->list.count); for (int i=0; ilist.array[i]->rat_Type == LTE_RAT_Type_nr) ueCapabilityRAT_Container_nr = &UE_CapabilityRAT_ContainerList->list.array[i]->ueCapabilityRAT_Container; - else if (UE_CapabilityRAT_ContainerList->list.array[i]->rat_Type == LTE_RAT_Type_eutra_nr) ueCapabilityRAT_Container_MRDC = &UE_CapabilityRAT_ContainerList->list.array[i]->ueCapabilityRAT_Container; + if (UE_CapabilityRAT_ContainerList->list.array[i]->rat_Type == NR_RAT_Type_nr) ueCapabilityRAT_Container_nr = &UE_CapabilityRAT_ContainerList->list.array[i]->ue_CapabilityRAT_Container; + else if (UE_CapabilityRAT_ContainerList->list.array[i]->rat_Type == NR_RAT_Type_eutra_nr) ueCapabilityRAT_Container_MRDC = &UE_CapabilityRAT_ContainerList->list.array[i]->ue_CapabilityRAT_Container; } // decode and store capabilities @@ -115,28 +117,14 @@ void rrc_parse_ue_capabilities(gNB_RRC_INST *rrc, LTE_UE_CapabilityRAT_Container // dump ue_capabilities - if ( LOG_DEBUGFLAG(DEBUG_ASN1 && ueCapabilityRAT_Container_nr != NULL) ) { + if ( LOG_DEBUGFLAG(DEBUG_ASN1) && ueCapabilityRAT_Container_nr != NULL ) { xer_fprint(stdout, &asn_DEF_NR_UE_NR_Capability, ue_context_p->ue_context.UE_Capability_nr); } - if ( LOG_DEBUGFLAG(DEBUG_ASN1 && ueCapabilityRAT_Container_MRDC != NULL) ) { + if ( LOG_DEBUGFLAG(DEBUG_ASN1) && ueCapabilityRAT_Container_MRDC != NULL ) { xer_fprint(stdout, &asn_DEF_NR_UE_MRDC_Capability, ue_context_p->ue_context.UE_Capability_MRDC); } - if(cg_config_info && cg_config_info->mcg_RB_Config) { - asn_dec_rval_t dec_rval = uper_decode(NULL, - &asn_DEF_NR_RadioBearerConfig, - (void **)&ue_context_p->ue_context.rb_config, - cg_config_info->mcg_RB_Config->buf, - cg_config_info->mcg_RB_Config->size, 0, 0); - - if((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) { - AssertFatal(1==0,"[InterNode] Failed to decode mcg_rb_config (%zu bits), size of OCTET_STRING %lu\n", - dec_rval.consumed, cg_config_info->mcg_RB_Config->size); - } - } - - xer_fprint(stdout, &asn_DEF_NR_RadioBearerConfig, (const void *)ue_context_p->ue_context.rb_config); rrc_add_nsa_user(rrc,ue_context_p, m); } @@ -152,6 +140,8 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc,struct rrc_gNB_ue_context_s *ue_context_ gtpv1u_enb_create_tunnel_req_t create_tunnel_req; gtpv1u_enb_create_tunnel_resp_t create_tunnel_resp; protocol_ctxt_t ctxt={0}; + unsigned char *kUPenc = NULL; + int i; // NR RRCReconfiguration AssertFatal(rrc->Nb_ue < MAX_NR_RRC_UE_CONTEXTS,"cannot add another UE\n"); ue_context_p->ue_context.reconfig = calloc(1,sizeof(NR_RRCReconfiguration_t)); @@ -162,9 +152,91 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc,struct rrc_gNB_ue_context_s *ue_context_ NR_RRCReconfiguration_IEs_t *reconfig_ies=calloc(1,sizeof(NR_RRCReconfiguration_IEs_t)); ue_context_p->ue_context.reconfig->criticalExtensions.choice.rrcReconfiguration = reconfig_ies; carrier->initial_csi_index[rrc->Nb_ue] = 0; + ue_context_p->ue_context.rb_config = calloc(1,sizeof(NR_RRCReconfiguration_t)); if (get_softmodem_params()->phy_test == 1 || get_softmodem_params()->do_ra == 1 || get_softmodem_params()->sa == 1){ - ue_context_p->ue_context.rb_config = calloc(1,sizeof(NR_RRCReconfiguration_t)); - fill_default_rbconfig(ue_context_p->ue_context.rb_config); + fill_default_rbconfig(ue_context_p->ue_context.rb_config, + 5 /* EPS bearer ID */, + 1 /* drb ID */, + NR_CipheringAlgorithm_nea0, + NR_SecurityConfig__keyToUse_master); + } else { + /* TODO: handle more than one bearer */ + if (m == NULL) { + LOG_E(RRC, "fatal: m==NULL\n"); + exit(1); + } + if (m->nb_e_rabs_tobeadded != 1) { + LOG_E(RRC, "fatal: m->nb_e_rabs_tobeadded = %d, should be 1\n", m->nb_e_rabs_tobeadded); + exit(1); + } + + /* store security key and security capabilities */ + memcpy(ue_context_p->ue_context.kgnb, m->kgnb, 32); + ue_context_p->ue_context.security_capabilities.nRencryption_algorithms = m->security_capabilities.encryption_algorithms; + ue_context_p->ue_context.security_capabilities.nRintegrity_algorithms = m->security_capabilities.integrity_algorithms; + + /* Select ciphering algorithm based on gNB configuration file and + * UE's supported algorithms. + * We take the first from the list that is supported by the UE. + * The ordering of the list comes from the configuration file. + */ + /* preset nea0 as fallback */ + ue_context_p->ue_context.ciphering_algorithm = 0; + for (i = 0; i < rrc->security.ciphering_algorithms_count; i++) { + int nea_mask[4] = { + 0, + 0x8000, /* nea1 */ + 0x4000, /* nea2 */ + 0x2000 /* nea3 */ + }; + if (rrc->security.ciphering_algorithms[i] == 0) { + /* nea0 already preselected */ + break; + } + if (ue_context_p->ue_context.security_capabilities.nRencryption_algorithms & nea_mask[rrc->security.ciphering_algorithms[i]]) { + ue_context_p->ue_context.ciphering_algorithm = rrc->security.ciphering_algorithms[i]; + break; + } + } + + LOG_I(RRC, "selecting ciphering algorithm %d\n", (int)ue_context_p->ue_context.ciphering_algorithm); + + /* integrity: no integrity protection for DRB in ENDC mode + * as written in 38.331: "If UE is connected to E-UTRA/EPC, this field + * indicates the integrity protection algorithm to be used for SRBs + * configured with NR PDCP, as specified in TS 33.501" + * So nothing for DRB. Plus a test with a COTS UE revealed that it + * did not apply integrity on the DRB. + */ + ue_context_p->ue_context.integrity_algorithm = 0; + + LOG_I(RRC, "selecting integrity algorithm %d\n", ue_context_p->ue_context.integrity_algorithm); + + /* derive UP security key */ + unsigned char *kUPenc_kdf; + nr_derive_key_up_enc(ue_context_p->ue_context.ciphering_algorithm, + ue_context_p->ue_context.kgnb, + &kUPenc_kdf); + /* kUPenc: last 128 bits of key derivation function which returns 256 bits */ + kUPenc = malloc(16); + if (kUPenc == NULL) exit(1); + memcpy(kUPenc, kUPenc_kdf+16, 16); + free(kUPenc_kdf); + + e_NR_CipheringAlgorithm cipher_algo; + switch (ue_context_p->ue_context.ciphering_algorithm) { + case 0: cipher_algo = NR_CipheringAlgorithm_nea0; break; + case 1: cipher_algo = NR_CipheringAlgorithm_nea1; break; + case 2: cipher_algo = NR_CipheringAlgorithm_nea2; break; + case 3: cipher_algo = NR_CipheringAlgorithm_nea3; break; + default: LOG_E(RRC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); exit(1); + } + + fill_default_rbconfig(ue_context_p->ue_context.rb_config, + m->e_rabs_tobeadded[0].e_rab_id, + m->e_rabs_tobeadded[0].drb_ID, + cipher_algo, + NR_SecurityConfig__keyToUse_secondary); } fill_default_reconfig(carrier->servingcellconfigcommon, reconfig_ies, @@ -285,10 +357,11 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc,struct rrc_gNB_ue_context_s *ue_context_ (NR_SRB_ToAddModList_t *) NULL, ue_context_p->ue_context.rb_config->drb_ToAddModList , ue_context_p->ue_context.rb_config->drb_ToReleaseList, - 0xff, - NULL, - NULL, - NULL, + (ue_context_p->ue_context.integrity_algorithm << 4) | ue_context_p->ue_context.ciphering_algorithm, + NULL, /* kRRCenc - unused */ + NULL, /* kRRCint - unused */ + kUPenc, /* kUPenc */ + NULL, /* kUPint - unused */ NULL, NULL, ue_context_p->ue_context.secondaryCellGroup->rlc_BearerToAddModList); diff --git a/openair2/RRC/NR/rrc_gNB_reconfig.c b/openair2/RRC/NR/rrc_gNB_reconfig.c index e87e2e6cc5..6aa05ce5f9 100644 --- a/openair2/RRC/NR/rrc_gNB_reconfig.c +++ b/openair2/RRC/NR/rrc_gNB_reconfig.c @@ -128,15 +128,15 @@ void fill_default_searchSpaceZero(NR_SearchSpace_t *ss0) { // should be '1100 0000 0000 00'B (LSB first!), first two symols in slot, adjust if needed ss0->monitoringSymbolsWithinSlot->buf[1] = 0; - ss0->monitoringSymbolsWithinSlot->buf[0] = (1<<7) | (1<<6); + ss0->monitoringSymbolsWithinSlot->buf[0] = (1<<7); ss0->monitoringSymbolsWithinSlot->size = 2; ss0->monitoringSymbolsWithinSlot->bits_unused = 2; // FIXME: update values from TS38.213 Section 10.1 Table 10.1-1: CCE aggregation levels and maximum number of PDCCH candidates per CCE aggregation level for CSS sets configured by searchSpaceSIB1 ss0->nrofCandidates->aggregationLevel1 = NR_SearchSpace__nrofCandidates__aggregationLevel1_n0; ss0->nrofCandidates->aggregationLevel2 = NR_SearchSpace__nrofCandidates__aggregationLevel2_n0; - ss0->nrofCandidates->aggregationLevel4 = NR_SearchSpace__nrofCandidates__aggregationLevel4_n0; - ss0->nrofCandidates->aggregationLevel8 = NR_SearchSpace__nrofCandidates__aggregationLevel8_n1; + ss0->nrofCandidates->aggregationLevel4 = NR_SearchSpace__nrofCandidates__aggregationLevel4_n1; + ss0->nrofCandidates->aggregationLevel8 = NR_SearchSpace__nrofCandidates__aggregationLevel8_n0; ss0->nrofCandidates->aggregationLevel16 = NR_SearchSpace__nrofCandidates__aggregationLevel16_n0; ss0->searchSpaceType->present = NR_SearchSpace__searchSpaceType_PR_common; @@ -1177,7 +1177,8 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco secondaryCellGroup->spCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig->choice.setup = pdsch_servingcellconfig; pdsch_servingcellconfig->codeBlockGroupTransmission = NULL; pdsch_servingcellconfig->xOverhead = NULL; - pdsch_servingcellconfig->nrofHARQ_ProcessesForPDSCH = NULL; + pdsch_servingcellconfig->nrofHARQ_ProcessesForPDSCH = calloc(1, sizeof(*pdsch_servingcellconfig->nrofHARQ_ProcessesForPDSCH)); + *pdsch_servingcellconfig->nrofHARQ_ProcessesForPDSCH = NR_PDSCH_ServingCellConfig__nrofHARQ_ProcessesForPDSCH_n16; pdsch_servingcellconfig->pucch_Cell= NULL; pdsch_servingcellconfig->ext1=calloc(1,sizeof(*pdsch_servingcellconfig->ext1)); pdsch_servingcellconfig->ext1->maxMIMO_Layers = calloc(1,sizeof(*pdsch_servingcellconfig->ext1->maxMIMO_Layers)); @@ -1328,7 +1329,10 @@ void fill_default_reconfig(NR_ServingCellConfigCommon_t *servingcellconfigcommon reconfig->nonCriticalExtension = NULL; } -void fill_default_rbconfig(NR_RadioBearerConfig_t *rbconfig) { +void fill_default_rbconfig(NR_RadioBearerConfig_t *rbconfig, + int eps_bearer_id, int rb_id, + e_NR_CipheringAlgorithm ciphering_algorithm, + e_NR_SecurityConfig__keyToUse key_to_use) { rbconfig->srb_ToAddModList = NULL; rbconfig->srb3_ToRelease = NULL; @@ -1336,8 +1340,8 @@ void fill_default_rbconfig(NR_RadioBearerConfig_t *rbconfig) { NR_DRB_ToAddMod_t *drb_ToAddMod = calloc(1,sizeof(*drb_ToAddMod)); drb_ToAddMod->cnAssociation = calloc(1,sizeof(*drb_ToAddMod->cnAssociation)); drb_ToAddMod->cnAssociation->present = NR_DRB_ToAddMod__cnAssociation_PR_eps_BearerIdentity; - drb_ToAddMod->cnAssociation->choice.eps_BearerIdentity= 5; - drb_ToAddMod->drb_Identity = 1; + drb_ToAddMod->cnAssociation->choice.eps_BearerIdentity= eps_bearer_id; + drb_ToAddMod->drb_Identity = rb_id; drb_ToAddMod->reestablishPDCP = NULL; drb_ToAddMod->recoverPDCP = NULL; drb_ToAddMod->pdcp_Config = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config)); @@ -1366,12 +1370,12 @@ void fill_default_rbconfig(NR_RadioBearerConfig_t *rbconfig) { rbconfig->securityConfig = calloc(1,sizeof(*rbconfig->securityConfig)); rbconfig->securityConfig->securityAlgorithmConfig = calloc(1,sizeof(*rbconfig->securityConfig->securityAlgorithmConfig)); - rbconfig->securityConfig->securityAlgorithmConfig->cipheringAlgorithm = NR_CipheringAlgorithm_nea0; + rbconfig->securityConfig->securityAlgorithmConfig->cipheringAlgorithm = ciphering_algorithm; rbconfig->securityConfig->securityAlgorithmConfig->integrityProtAlgorithm=NULL; rbconfig->securityConfig->keyToUse = calloc(1,sizeof(*rbconfig->securityConfig->keyToUse)); - *rbconfig->securityConfig->keyToUse = NR_SecurityConfig__keyToUse_master; + *rbconfig->securityConfig->keyToUse = key_to_use; - xer_fprint(stdout, &asn_DEF_NR_RadioBearerConfig, (const void*)rbconfig); +// xer_fprint(stdout, &asn_DEF_NR_RadioBearerConfig, (const void*)rbconfig); } /* Function to set or overwrite PTRS DL RRC parameters */ void rrc_config_dl_ptrs_params(NR_BWP_Downlink_t *bwp, int *ptrsNrb, int *ptrsMcs, int *epre_Ratio, int * reOffset) diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index 9d053aae91..735b5765db 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -186,7 +186,8 @@ extern boolean_t nr_rrc_pdcp_config_asn1_req( const uint8_t security_modeP, uint8_t *const kRRCenc, uint8_t *const kRRCint, - uint8_t *const kUPenc + uint8_t *const kUPenc, + uint8_t *const kUPint #if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0)) ,LTE_PMCH_InfoList_r9_t *pmch_InfoList_r9 #endif @@ -1510,8 +1511,9 @@ int8_t nr_rrc_ue_decode_NR_SIB1_Message(module_id_t module_id, uint8_t gNB_index } sib1 = bcch_message->message.choice.c1->choice.systemInformationBlockType1; if (*(int64_t*)sib1 != 1) { - LOG_D(RRC, "SIB1 address: %lx\n", *(int64_t*)sib1); - xer_fprint(stdout, &asn_DEF_NR_SIB1, (const void*)sib1); + LOG_I(RRC, "SIB1 decoded\n"); + if( g_log->log_component[RRC].level >= OAILOG_DEBUG ) + xer_fprint(stdout, &asn_DEF_NR_SIB1, (const void*)sib1); } else LOG_E(PHY, "sib1 is starting by 8 times 0\n"); @@ -2100,6 +2102,7 @@ nr_sa_rrc_ue_process_radioBearerConfig( // NULL, // NULL, // NULL, + // NULL, // NULL); // Refresh SRBs // nr_rrc_rlc_config_asn1_req(ctxt_pP, @@ -2191,6 +2194,7 @@ nr_sa_rrc_ue_process_radioBearerConfig( // NULL, // kUPenc, // NULL, + // NULL, // NR_UE_rrc_inst[ctxt_pP->module_id].defaultDRB, // NULL); // Refresh DRBs @@ -2845,6 +2849,8 @@ nr_rrc_ue_generate_rrcReestablishmentComplete( uint32_t length; uint8_t buffer[100]; length = do_RRCReestablishmentComplete(buffer, rrcReestablishment->rrc_TransactionIdentifier); + LOG_I(NR_RRC,"[UE %d][RAPROC] Frame %d : Logical Channel UL-DCCH (SRB1), Generating RRCReestablishmentComplete (bytes%d, gNB %d)\n", + ctxt_pP->module_id,ctxt_pP->frame, length, gNB_index); #ifdef ITTI_SIM MessageDef *message_p; uint8_t *message_buffer; diff --git a/openair2/RRC/NR_UE/rrc_defs.h b/openair2/RRC/NR_UE/rrc_defs.h index 310f9572c9..52bd6c564a 100644 --- a/openair2/RRC/NR_UE/rrc_defs.h +++ b/openair2/RRC/NR_UE/rrc_defs.h @@ -39,7 +39,6 @@ #include "platform_types.h" -#include "NR_MAC_UE/mac.h" #include "NR_MAC_COMMON/nr_mac.h" #include "rrc_list.h" #include "NR_asn_constant.h" diff --git a/openair2/SIMULATION/NR_RRC/itti_sim.c b/openair2/SIMULATION/NR_RRC/itti_sim.c index f4fdb58dd9..e11a92d691 100644 --- a/openair2/SIMULATION/NR_RRC/itti_sim.c +++ b/openair2/SIMULATION/NR_RRC/itti_sim.c @@ -369,7 +369,7 @@ void set_default_frame_parms(nfapi_nr_config_request_scf_t *config[MAX_NUM_CCs], void terminate_task(task_id_t task_id, module_id_t mod_id) { LOG_I(GNB_APP, "sending TERMINATE_MESSAGE to task %s (%d)\n", itti_get_task_name(task_id), task_id); MessageDef *msg; - msg = itti_alloc_new_message (ENB_APP, TERMINATE_MESSAGE); + msg = itti_alloc_new_message (ENB_APP, 0, TERMINATE_MESSAGE); itti_send_msg_to_task (task_id, ENB_MODULE_ID_TO_INSTANCE(mod_id), msg); } @@ -435,14 +435,14 @@ void *itti_sim_ue_rrc_task( void *args_p) { LOG_D(NR_RRC, "[UE %d] Received %s\n", ue_mod_id, ITTI_MSG_NAME (msg_p)); break; case GNB_RRC_BCCH_DATA_IND: - message_p = itti_alloc_new_message (TASK_RRC_UE_SIM, NR_RRC_MAC_BCCH_DATA_IND); + message_p = itti_alloc_new_message (TASK_RRC_UE_SIM, 0, NR_RRC_MAC_BCCH_DATA_IND); memset (NR_RRC_MAC_BCCH_DATA_IND (message_p).sdu, 0, BCCH_SDU_SIZE); NR_RRC_MAC_BCCH_DATA_IND (message_p).sdu_size = GNB_RRC_BCCH_DATA_IND(msg_p).size; memcpy (NR_RRC_MAC_BCCH_DATA_IND (message_p).sdu, GNB_RRC_BCCH_DATA_IND(msg_p).sdu, GNB_RRC_BCCH_DATA_IND(msg_p).size); itti_send_msg_to_task (TASK_RRC_NRUE, instance, message_p); break; case GNB_RRC_CCCH_DATA_IND: - message_p = itti_alloc_new_message (TASK_RRC_UE_SIM, NR_RRC_MAC_CCCH_DATA_IND); + message_p = itti_alloc_new_message (TASK_RRC_UE_SIM, 0, NR_RRC_MAC_CCCH_DATA_IND); printf("receive GNB_RRC_CCCH_DATA_IND\n"); memset (NR_RRC_MAC_CCCH_DATA_IND (message_p).sdu, 0, CCCH_SDU_SIZE); memcpy (NR_RRC_MAC_CCCH_DATA_IND (message_p).sdu, GNB_RRC_CCCH_DATA_IND(msg_p).sdu, GNB_RRC_CCCH_DATA_IND(msg_p).size); @@ -451,7 +451,7 @@ void *itti_sim_ue_rrc_task( void *args_p) { break; case GNB_RRC_DCCH_DATA_IND: printf("receive GNB_RRC_DCCH_DATA_IND\n"); - message_p = itti_alloc_new_message (TASK_RRC_UE_SIM, NR_RRC_DCCH_DATA_IND); + message_p = itti_alloc_new_message (TASK_RRC_UE_SIM, 0, NR_RRC_DCCH_DATA_IND); NR_RRC_DCCH_DATA_IND (message_p).dcch_index = GNB_RRC_DCCH_DATA_IND(msg_p).rbid; NR_RRC_DCCH_DATA_IND (message_p).sdu_size = GNB_RRC_DCCH_DATA_IND(msg_p).size; NR_RRC_DCCH_DATA_IND (message_p).sdu_p = GNB_RRC_DCCH_DATA_IND(msg_p).sdu; @@ -492,14 +492,14 @@ void *itti_sim_gnb_rrc_task( void *args_p) { LOG_D(NR_RRC, "[UE %d] Received %s\n", ue_mod_id, ITTI_MSG_NAME (msg_p)); break; case UE_RRC_CCCH_DATA_IND: - message_p = itti_alloc_new_message (TASK_RRC_GNB_SIM, NR_RRC_MAC_CCCH_DATA_IND); + message_p = itti_alloc_new_message (TASK_RRC_GNB_SIM, 0, NR_RRC_MAC_CCCH_DATA_IND); NR_RRC_MAC_CCCH_DATA_IND (message_p).sdu_size = UE_RRC_CCCH_DATA_IND(msg_p).size; memset (NR_RRC_MAC_CCCH_DATA_IND (message_p).sdu, 0, CCCH_SDU_SIZE); memcpy (NR_RRC_MAC_CCCH_DATA_IND (message_p).sdu, UE_RRC_CCCH_DATA_IND(msg_p).sdu, UE_RRC_CCCH_DATA_IND(msg_p).size); itti_send_msg_to_task (TASK_RRC_GNB, instance, message_p); break; case UE_RRC_DCCH_DATA_IND: - message_p = itti_alloc_new_message (TASK_RRC_GNB_SIM, NR_RRC_DCCH_DATA_IND); + message_p = itti_alloc_new_message (TASK_RRC_GNB_SIM, 0, NR_RRC_DCCH_DATA_IND); NR_RRC_DCCH_DATA_IND (message_p).sdu_size = UE_RRC_DCCH_DATA_IND(msg_p).size; NR_RRC_DCCH_DATA_IND (message_p).dcch_index = UE_RRC_DCCH_DATA_IND(msg_p).rbid; NR_RRC_DCCH_DATA_IND (message_p).sdu_p = UE_RRC_DCCH_DATA_IND(msg_p).sdu; diff --git a/openair2/UTIL/OSA/osa_defs.h b/openair2/UTIL/OSA/osa_defs.h index 304dd07042..6334658683 100644 --- a/openair2/UTIL/OSA/osa_defs.h +++ b/openair2/UTIL/OSA/osa_defs.h @@ -53,6 +53,8 @@ typedef enum { //int derive_keNB(const uint8_t kasme[32], const uint32_t nas_count, uint8_t **keNB); +int derive_skgNB(const uint8_t *keNB, const uint16_t sk_counter, uint8_t *skgNB); + int derive_key(algorithm_type_dist_t nas_alg_type, uint8_t nas_enc_alg_id, const uint8_t key[32], uint8_t **out); int nr_derive_key(algorithm_type_dist_t alg_type, uint8_t alg_id, diff --git a/openair2/UTIL/OSA/osa_key_deriver.c b/openair2/UTIL/OSA/osa_key_deriver.c index 71c7793fa0..159ee7f159 100644 --- a/openair2/UTIL/OSA/osa_key_deriver.c +++ b/openair2/UTIL/OSA/osa_key_deriver.c @@ -159,3 +159,27 @@ int derive_keNB(const uint8_t key[32], const uint32_t nas_count, uint8_t **keNB) return 0; } */ + +int derive_skgNB(const uint8_t *keNB, const uint16_t sk_counter, uint8_t *skgNB) +{ + uint8_t *out; + uint8_t s[5]; + + /* FC is 0x1c (see 3gpp 33.401 annex A.15) */ + s[0] = 0x1c; + + /* put sk_counter */ + s[1] = (sk_counter >> 8) & 0xff; + s[2] = sk_counter & 0xff; + + /* put length of sk_counter (2) */ + s[3] = 0x00; + s[4] = 0x02; + + kdf(s, 5, keNB, 32, &out, 32); + + memcpy(skgNB, out, 32); + free(out); + + return 0; +} diff --git a/openair2/X2AP/x2ap_eNB_generate_messages.c b/openair2/X2AP/x2ap_eNB_generate_messages.c index 23973328f2..fdce8678b0 100644 --- a/openair2/X2AP/x2ap_eNB_generate_messages.c +++ b/openair2/X2AP/x2ap_eNB_generate_messages.c @@ -1675,7 +1675,7 @@ int x2ap_eNB_generate_ENDC_x2_SgNB_addition_request( for (int i=0;iid = X2AP_ProtocolIE_ID_id_E_RABs_ToBeAdded_SgNBAddReq_Item; - e_RABS_ToBeAdded_SgNBAddReq_ItemIEs->criticality = X2AP_Criticality_ignore; + e_RABS_ToBeAdded_SgNBAddReq_ItemIEs->criticality = X2AP_Criticality_reject; e_RABS_ToBeAdded_SgNBAddReq_ItemIEs->value.present = X2AP_E_RABs_ToBeAdded_SgNBAddReq_ItemIEs__value_PR_E_RABs_ToBeAdded_SgNBAddReq_Item; e_RABS_ToBeAdded_SgNBAddReq_Item = &e_RABS_ToBeAdded_SgNBAddReq_ItemIEs->value.choice.E_RABs_ToBeAdded_SgNBAddReq_Item; { diff --git a/openair3/NAS/COMMON/EMM/MSG/FGSAuthenticationResponse.c b/openair3/NAS/COMMON/EMM/MSG/FGSAuthenticationResponse.c index 804f8e97ff..5e1ff25151 100644 --- a/openair3/NAS/COMMON/EMM/MSG/FGSAuthenticationResponse.c +++ b/openair3/NAS/COMMON/EMM/MSG/FGSAuthenticationResponse.c @@ -1,3 +1,24 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + /*! \file FGSAuthenticationResponse.c \brief authentication response procedures diff --git a/openair3/NAS/COMMON/EMM/MSG/FGSAuthenticationResponse.h b/openair3/NAS/COMMON/EMM/MSG/FGSAuthenticationResponse.h index 2e3ea248e4..0acee3382f 100644 --- a/openair3/NAS/COMMON/EMM/MSG/FGSAuthenticationResponse.h +++ b/openair3/NAS/COMMON/EMM/MSG/FGSAuthenticationResponse.h @@ -1,3 +1,24 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + /*! \file FGSAuthenticationResponse.h \brief authentication response procedures diff --git a/openair3/NAS/COMMON/EMM/MSG/FGSIdentityResponse.c b/openair3/NAS/COMMON/EMM/MSG/FGSIdentityResponse.c index 65aa2285e1..4f8f6dd321 100644 --- a/openair3/NAS/COMMON/EMM/MSG/FGSIdentityResponse.c +++ b/openair3/NAS/COMMON/EMM/MSG/FGSIdentityResponse.c @@ -1,3 +1,24 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + /*! \file FGSIdentityResponse.c \brief identity response procedures for gNB diff --git a/openair3/NAS/COMMON/EMM/MSG/FGSIdentityResponse.h b/openair3/NAS/COMMON/EMM/MSG/FGSIdentityResponse.h index aa68116462..431293e03e 100644 --- a/openair3/NAS/COMMON/EMM/MSG/FGSIdentityResponse.h +++ b/openair3/NAS/COMMON/EMM/MSG/FGSIdentityResponse.h @@ -1,3 +1,24 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + /*! \file FGSIdentityResponse.h \brief identity response procedures for gNB diff --git a/openair3/NAS/COMMON/EMM/MSG/FGSNASSecurityModeComplete.c b/openair3/NAS/COMMON/EMM/MSG/FGSNASSecurityModeComplete.c index 25e41b70a0..e0be56145f 100644 --- a/openair3/NAS/COMMON/EMM/MSG/FGSNASSecurityModeComplete.c +++ b/openair3/NAS/COMMON/EMM/MSG/FGSNASSecurityModeComplete.c @@ -1,3 +1,24 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + /*! \file FGSNASSecurityModeComplete.c \brief security mode complete procedures for gNB diff --git a/openair3/NAS/COMMON/EMM/MSG/FGSNASSecurityModeComplete.h b/openair3/NAS/COMMON/EMM/MSG/FGSNASSecurityModeComplete.h index 691130c1e8..702dca3dc5 100644 --- a/openair3/NAS/COMMON/EMM/MSG/FGSNASSecurityModeComplete.h +++ b/openair3/NAS/COMMON/EMM/MSG/FGSNASSecurityModeComplete.h @@ -1,3 +1,24 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + /*! \file FGSNASSecurityModeComplete.h \brief security mode complete procedures for gNB diff --git a/openair3/NAS/COMMON/EMM/MSG/FGSUplinkNasTransport.c b/openair3/NAS/COMMON/EMM/MSG/FGSUplinkNasTransport.c index 55c30d24c7..d94df434b2 100644 --- a/openair3/NAS/COMMON/EMM/MSG/FGSUplinkNasTransport.c +++ b/openair3/NAS/COMMON/EMM/MSG/FGSUplinkNasTransport.c @@ -1,3 +1,24 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + /*! \file FGSUplinkNasTransport.c \brief uplink nas transport procedures diff --git a/openair3/NAS/COMMON/EMM/MSG/FGSUplinkNasTransport.h b/openair3/NAS/COMMON/EMM/MSG/FGSUplinkNasTransport.h index f0debd79eb..5fabcea173 100644 --- a/openair3/NAS/COMMON/EMM/MSG/FGSUplinkNasTransport.h +++ b/openair3/NAS/COMMON/EMM/MSG/FGSUplinkNasTransport.h @@ -1,3 +1,24 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + /*! \file FGSUplinkNasTransport.h \brief uplink nas transport procedures diff --git a/openair3/NAS/COMMON/EMM/MSG/RegistrationAccept.c b/openair3/NAS/COMMON/EMM/MSG/RegistrationAccept.c index fb263e6b34..d8fde7e2cc 100644 --- a/openair3/NAS/COMMON/EMM/MSG/RegistrationAccept.c +++ b/openair3/NAS/COMMON/EMM/MSG/RegistrationAccept.c @@ -1,3 +1,24 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + /*! \file RegistrationAccept.c \brief 5GS registration accept procedures diff --git a/openair3/NAS/COMMON/EMM/MSG/RegistrationAccept.h b/openair3/NAS/COMMON/EMM/MSG/RegistrationAccept.h index f737496105..08daec2646 100644 --- a/openair3/NAS/COMMON/EMM/MSG/RegistrationAccept.h +++ b/openair3/NAS/COMMON/EMM/MSG/RegistrationAccept.h @@ -1,3 +1,24 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + /*! \file RegistrationAccept.h \brief 5GS registration accept procedures diff --git a/openair3/NAS/COMMON/EMM/MSG/RegistrationComplete.h b/openair3/NAS/COMMON/EMM/MSG/RegistrationComplete.h index bc69810ea9..0fbf2abde1 100644 --- a/openair3/NAS/COMMON/EMM/MSG/RegistrationComplete.h +++ b/openair3/NAS/COMMON/EMM/MSG/RegistrationComplete.h @@ -1,3 +1,24 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + /*! \file RegistrationRequest.h \brief registration request procedures for gNB diff --git a/openair3/NAS/COMMON/ESM/MSG/PduSessionEstablishRequest.c b/openair3/NAS/COMMON/ESM/MSG/PduSessionEstablishRequest.c index 369d6b83aa..bc4d34d650 100644 --- a/openair3/NAS/COMMON/ESM/MSG/PduSessionEstablishRequest.c +++ b/openair3/NAS/COMMON/ESM/MSG/PduSessionEstablishRequest.c @@ -1,3 +1,24 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + /*! \file PduSessionEstablishRequest.c \brief pdu session establishment request procedures diff --git a/openair3/NAS/COMMON/ESM/MSG/PduSessionEstablishRequest.h b/openair3/NAS/COMMON/ESM/MSG/PduSessionEstablishRequest.h index 6626e35cc6..ac5b250f66 100644 --- a/openair3/NAS/COMMON/ESM/MSG/PduSessionEstablishRequest.h +++ b/openair3/NAS/COMMON/ESM/MSG/PduSessionEstablishRequest.h @@ -1,3 +1,24 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + /*! \file PduSessionEstablishRequest.h \brief pdu session establishment request procedures diff --git a/openair3/NAS/COMMON/IES/FGCNasMessageContainer.c b/openair3/NAS/COMMON/IES/FGCNasMessageContainer.c index 13a5f167d2..874f61e7b3 100644 --- a/openair3/NAS/COMMON/IES/FGCNasMessageContainer.c +++ b/openair3/NAS/COMMON/IES/FGCNasMessageContainer.c @@ -1,3 +1,24 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + /*! \file FGCNasMessageContainer.c \brief security mode complete procedures for gNB diff --git a/openair3/NAS/COMMON/IES/FGCNasMessageContainer.h b/openair3/NAS/COMMON/IES/FGCNasMessageContainer.h index 1e00ff434c..19a1679b7e 100644 --- a/openair3/NAS/COMMON/IES/FGCNasMessageContainer.h +++ b/openair3/NAS/COMMON/IES/FGCNasMessageContainer.h @@ -1,3 +1,24 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + /*! \file FGCNasMessageContainer.h \brief security mode complete procedures for gNB diff --git a/openair3/NAS/COMMON/IES/FGSRegistrationResult.c b/openair3/NAS/COMMON/IES/FGSRegistrationResult.c index 3c70919c72..e580b14409 100644 --- a/openair3/NAS/COMMON/IES/FGSRegistrationResult.c +++ b/openair3/NAS/COMMON/IES/FGSRegistrationResult.c @@ -1,3 +1,24 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + /*! \file FGSRegistrationResult.c \brief 5GS Registration result for registration request procedures diff --git a/openair3/NAS/COMMON/IES/FGSRegistrationResult.h b/openair3/NAS/COMMON/IES/FGSRegistrationResult.h index f9a437eb1a..0a2dedc2e5 100644 --- a/openair3/NAS/COMMON/IES/FGSRegistrationResult.h +++ b/openair3/NAS/COMMON/IES/FGSRegistrationResult.h @@ -1,3 +1,24 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + /*! \file FGSRegistrationResult.h \brief 5GS Registration result for registration request procedures diff --git a/openair3/NGAP/ngap_gNB.c b/openair3/NGAP/ngap_gNB.c index 7c401c2508..a5dfc88b35 100644 --- a/openair3/NGAP/ngap_gNB.c +++ b/openair3/NGAP/ngap_gNB.c @@ -113,7 +113,7 @@ static void ngap_gNB_register_amf(ngap_gNB_instance_t *instance_p, memcpy(&sctp_new_association_req_p->local_address, local_ip_addr, sizeof(*local_ip_addr)); - NGAP_INFO("[gNB %d] check the amf registration state\n",instance_p->instance); + NGAP_INFO("[gNB %ld] check the amf registration state\n",instance_p->instance); /* Create new AMF descriptor */ ngap_amf_data_p = calloc(1, sizeof(*ngap_amf_data_p)); @@ -134,7 +134,7 @@ static void ngap_gNB_register_amf(ngap_gNB_instance_t *instance_p, * but not yet associated. */ RB_INSERT(ngap_amf_map, &instance_p->ngap_amf_head, ngap_amf_data_p); - ngap_amf_data_p->state = NGAP_GNB_STATE_WAITING; + ngap_amf_data_p->state = NGAP_GNB_STATE_DISCONNECTED; instance_p->ngap_amf_nb ++; instance_p->ngap_amf_pending_nb ++; diff --git a/openair3/NGAP/ngap_gNB_nas_procedures.c b/openair3/NGAP/ngap_gNB_nas_procedures.c index aa1481f0d0..ace7162c57 100644 --- a/openair3/NGAP/ngap_gNB_nas_procedures.c +++ b/openair3/NGAP/ngap_gNB_nas_procedures.c @@ -708,6 +708,7 @@ int ngap_gNB_initial_ctxt_resp( ie->value.present = NGAP_InitialContextSetupResponseIEs__value_PR_RAN_UE_NGAP_ID; ie->value.choice.RAN_UE_NGAP_ID = initial_ctxt_resp_p->gNB_ue_ngap_id; ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + /* optional */ if (initial_ctxt_resp_p->nb_of_pdusessions){ ie = (NGAP_InitialContextSetupResponseIEs_t *)calloc(1, sizeof(NGAP_InitialContextSetupResponseIEs_t)); diff --git a/openair3/S1AP/s1ap_eNB_handlers.c b/openair3/S1AP/s1ap_eNB_handlers.c index 7c233d9e14..370d34868b 100644 --- a/openair3/S1AP/s1ap_eNB_handlers.c +++ b/openair3/S1AP/s1ap_eNB_handlers.c @@ -864,22 +864,36 @@ int s1ap_eNB_handle_initial_context_request(uint32_t assoc_id, BIT_STRING_to_uint16(&ie->value.choice.UESecurityCapabilities.encryptionAlgorithms); S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).security_capabilities.integrity_algorithms = BIT_STRING_to_uint16(&ie->value.choice.UESecurityCapabilities.integrityProtectionAlgorithms); - /* id-SecurityKey : Copy the security key */ } else {/* ie != NULL */ return -1; } + /* id-SecurityKey : Copy the security key */ S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_InitialContextSetupRequestIEs_t, ie, container, S1AP_ProtocolIE_ID_id_SecurityKey, true); if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */ memcpy(&S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).security_key, ie->value.choice.SecurityKey.buf, ie->value.choice.SecurityKey.size); - itti_send_msg_to_task(TASK_RRC_ENB, ue_desc_p->eNB_instance->instance, message_p); } else {/* ie != NULL */ return -1; } + /* id-NRUESecurityCapabilities */ + S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_InitialContextSetupRequestIEs_t, ie, container, + S1AP_ProtocolIE_ID_id_NRUESecurityCapabilities, false); + if (ie != NULL) { + S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).nr_security_capabilities.encryption_algorithms = + BIT_STRING_to_uint16(&ie->value.choice.NRUESecurityCapabilities.nRencryptionAlgorithms); + S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).nr_security_capabilities.integrity_algorithms = + BIT_STRING_to_uint16(&ie->value.choice.NRUESecurityCapabilities.nRintegrityProtectionAlgorithms); + } else { + S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).nr_security_capabilities.encryption_algorithms = 0; + S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).nr_security_capabilities.integrity_algorithms = 0; + } + + itti_send_msg_to_task(TASK_RRC_ENB, ue_desc_p->eNB_instance->instance, message_p); + return 0; } diff --git a/targets/ARCH/COMMON/common_lib.h b/targets/ARCH/COMMON/common_lib.h index 85ee80ea7c..93e9ffb52f 100644 --- a/targets/ARCH/COMMON/common_lib.h +++ b/targets/ARCH/COMMON/common_lib.h @@ -105,9 +105,10 @@ typedef enum { ADRV9371_ZC706_DEV, /*!\brief device is UEDv2 */ UEDv2_DEV, + RFSIMULATOR, MAX_RF_DEV_TYPE } dev_type_t; -#define DEVTYPE_NAMES {"","EXMIMO","USRP B200","USRP X300","USRP N300","BLADERF","LMSSDR","IRIS","No HW","ADRV9371_ZC706","UEDv2"} +#define DEVTYPE_NAMES {"","EXMIMO","USRP B200","USRP X300","USRP N300","BLADERF","LMSSDR","IRIS","No HW","ADRV9371_ZC706","UEDv2", "RFSIMULATOR"} /*!\brief transport protocol types */ typedef enum { @@ -491,15 +492,11 @@ struct openair0_device_t { typedef int(*oai_device_initfunc_t)(openair0_device *device, openair0_config_t *openair0_cfg); /* type of transport init function, implemented in shared lib */ typedef int(*oai_transport_initfunc_t)(openair0_device *device, openair0_config_t *openair0_cfg, eth_params_t *eth_params); -#define UE_MAGICDL_FDD 0xA5A5A5A5A5A5A5A5 // UE DL FDD record -#define UE_MAGICUL_FDD 0x5A5A5A5A5A5A5A5A // UE UL FDD record -#define UE_MAGICDL_TDD 0xA6A6A6A6A6A6A6A6 // UE DL TDD record -#define UE_MAGICUL_TDD 0x6A6A6A6A6A6A6A6A // UE UL TDD record +#define UE_MAGICDL 0xA5A5A5A5A5A5A5A5 // UE DL FDD record +#define UE_MAGICUL 0x5A5A5A5A5A5A5A5A // UE UL FDD record -#define ENB_MAGICDL_FDD 0xB5B5B5B5B5B5B5B5 // eNB DL FDD record -#define ENB_MAGICUL_FDD 0x5B5B5B5B5B5B5B5B // eNB UL FDD record -#define ENB_MAGICDL_TDD 0xB6B6B6B6B6B6B6B6 // eNB DL TDD record -#define ENB_MAGICUL_TDD 0x6B6B6B6B6B6B6B6B // eNB UL TDD record +#define ENB_MAGICDL 0xB5B5B5B5B5B5B5B5 // eNB DL FDD record +#define ENB_MAGICUL 0x5B5B5B5B5B5B5B5B // eNB UL FDD record #define OPTION_LZ4 0x00000001 // LZ4 compression (option_value is set to compressed size) @@ -516,19 +513,6 @@ typedef struct { uint32_t option_flag; // Option flag } samplesBlockHeader_t; -#define UE_MAGICDL_FDD 0xA5A5A5A5A5A5A5A5 // UE DL FDD record -#define UE_MAGICUL_FDD 0x5A5A5A5A5A5A5A5A // UE UL FDD record -#define UE_MAGICDL_TDD 0xA6A6A6A6A6A6A6A6 // UE DL TDD record -#define UE_MAGICUL_TDD 0x6A6A6A6A6A6A6A6A // UE UL TDD record - -#define ENB_MAGICDL_FDD 0xB5B5B5B5B5B5B5B5 // eNB DL FDD record -#define ENB_MAGICUL_FDD 0x5B5B5B5B5B5B5B5B // eNB UL FDD record -#define ENB_MAGICDL_TDD 0xB6B6B6B6B6B6B6B6 // eNB DL TDD record -#define ENB_MAGICUL_TDD 0x6B6B6B6B6B6B6B6B // eNB UL TDD record - -#define OPTION_LZ4 0x00000001 // LZ4 compression (option_value is set to compressed size) - - #ifdef __cplusplus extern "C" { diff --git a/targets/ARCH/rfsimulator/simulator.c b/targets/ARCH/rfsimulator/simulator.c index 79bf3dd077..cd35c46a15 100644 --- a/targets/ARCH/rfsimulator/simulator.c +++ b/targets/ARCH/rfsimulator/simulator.c @@ -76,15 +76,16 @@ extern RAN_CONTEXT_t RC; /* configuration parameters for the rfsimulator device */ /* optname helpstr paramflags XXXptr defXXXval type numelt */ /*-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ -#define RFSIMULATOR_PARAMS_DESC {\ - {"serveraddr", "\n", 0, strptr:&(rfsimulator->ip), defstrval:"127.0.0.1", TYPE_STRING, 0 },\ - {"serverport", "\n", 0, u16ptr:&(rfsimulator->port), defuintval:PORT, TYPE_UINT16, 0 },\ - {RFSIMU_OPTIONS_PARAMNAME, RFSIM_CONFIG_HELP_OPTIONS, 0, strlistptr:NULL, defstrlistval:NULL, TYPE_STRINGLIST,0 },\ - {"IQfile", "\n", 0, strptr:&(saveF), defstrval:"/tmp/rfsimulator.iqs",TYPE_STRING, 0 },\ - {"modelname", "\n", 0, strptr:&(modelname), defstrval:"AWGN", TYPE_STRING, 0 },\ - {"ploss", "\n", 0, dblptr:&(rfsimulator->chan_pathloss), defdblval:0, TYPE_DOUBLE, 0 },\ - {"forgetfact", "\n", 0, dblptr:&(rfsimulator->chan_forgetfact), defdblval:0, TYPE_DOUBLE, 0 },\ - {"offset", "\n", 0, iptr:&(rfsimulator->chan_offset), defintval:0, TYPE_INT, 0 }\ +#define simOpt PARAMFLAG_NOFREE|PARAMFLAG_CMDLINE_NOPREFIXENABLED +#define RFSIMULATOR_PARAMS_DESC { \ + {"serveraddr", "\n", simOpt , strptr:&(rfsimulator->ip), defstrval:"127.0.0.1", TYPE_STRING, 0 },\ + {"serverport", "\n", simOpt, u16ptr:&(rfsimulator->port), defuintval:PORT, TYPE_UINT16, 0 },\ + {RFSIMU_OPTIONS_PARAMNAME, RFSIM_CONFIG_HELP_OPTIONS, 0, strlistptr:NULL, defstrlistval:NULL, TYPE_STRINGLIST,0 },\ + {"IQfile", "\n",simOpt, strptr:&(saveF), defstrval:"/tmp/rfsimulator.iqs",TYPE_STRING, 0 },\ + {"modelname", "\n", simOpt, strptr:&(modelname), defstrval:"AWGN", TYPE_STRING, 0 },\ + {"ploss", "\n", simOpt, dblptr:&(rfsimulator->chan_pathloss), defdblval:0, TYPE_DOUBLE, 0 },\ + {"forgetfact", "\n", simOpt, dblptr:&(rfsimulator->chan_forgetfact), defdblval:0, TYPE_DOUBLE, 0 },\ + {"offset", "\n", simOpt, iptr:&(rfsimulator->chan_offset), defintval:0, TYPE_INT, 0 }\ }; @@ -137,7 +138,7 @@ typedef struct { } rfsimulator_state_t; -void allocCirBuf(rfsimulator_state_t *bridge, int sock) { +static void allocCirBuf(rfsimulator_state_t *bridge, int sock) { buffer_t *ptr=&bridge->buf[sock]; AssertFatal ( (ptr->circularBuf=(sample_t *) malloc(sampleToByte(CirSize,1))) != NULL, ""); ptr->circularBufEnd=((char *)ptr->circularBuf)+sampleToByte(CirSize,1); @@ -195,7 +196,7 @@ void allocCirBuf(rfsimulator_state_t *bridge, int sock) { } } -void removeCirBuf(rfsimulator_state_t *bridge, int sock) { +static void removeCirBuf(rfsimulator_state_t *bridge, int sock) { AssertFatal( epoll_ctl(bridge->epollfd, EPOLL_CTL_DEL, sock, NULL) != -1, ""); close(sock); free(bridge->buf[sock].circularBuf); @@ -206,12 +207,12 @@ void removeCirBuf(rfsimulator_state_t *bridge, int sock) { bridge->buf[sock].conn_sock=-1; } -void socketError(rfsimulator_state_t *bridge, int sock) { +static void socketError(rfsimulator_state_t *bridge, int sock) { if (bridge->buf[sock].conn_sock!=-1) { LOG_W(HW,"Lost socket \n"); removeCirBuf(bridge, sock); - if (bridge->typeStamp==UE_MAGICDL_FDD) + if (bridge->typeStamp==UE_MAGICDL) exit(1); } } @@ -229,7 +230,7 @@ enum blocking_t { blocking }; -void setblocking(int sock, enum blocking_t active) { +static void setblocking(int sock, enum blocking_t active) { int opts; AssertFatal( (opts = fcntl(sock, F_GETFL)) >= 0,""); @@ -243,7 +244,7 @@ void setblocking(int sock, enum blocking_t active) { static bool flushInput(rfsimulator_state_t *t, int timeout, int nsamps); -void fullwrite(int fd, void *_buf, ssize_t count, rfsimulator_state_t *t) { +static void fullwrite(int fd, void *_buf, ssize_t count, rfsimulator_state_t *t) { if (t->saveIQfile != -1) { if (write(t->saveIQfile, _buf, count) != count ) LOG_E(HW,"write in save iq file failed (%s)\n",strerror(errno)); @@ -277,7 +278,7 @@ void fullwrite(int fd, void *_buf, ssize_t count, rfsimulator_state_t *t) { } } -void rfsimulator_readconfig(rfsimulator_state_t *rfsimulator) { +static void rfsimulator_readconfig(rfsimulator_state_t *rfsimulator) { char *saveF=NULL; char *modelname=NULL; paramdef_t rfsimu_params[] = RFSIMULATOR_PARAMS_DESC; @@ -312,9 +313,9 @@ void rfsimulator_readconfig(rfsimulator_state_t *rfsimulator) { if ( strncasecmp(rfsimulator->ip,"enb",3) == 0 || strncasecmp(rfsimulator->ip,"server",3) == 0 ) - rfsimulator->typeStamp = ENB_MAGICDL_FDD; + rfsimulator->typeStamp = ENB_MAGICDL; else - rfsimulator->typeStamp = UE_MAGICDL_FDD; + rfsimulator->typeStamp = UE_MAGICDL; } static int rfsimu_setchanmod_cmd(char *buff, int debug, telnet_printfunc_t prnt, void *arg) { @@ -358,9 +359,9 @@ static int rfsimu_setchanmod_cmd(char *buff, int debug, telnet_printfunc_t prnt, return CMDSTATUS_FOUND; } -int server_start(openair0_device *device) { +static int startServer(openair0_device *device) { rfsimulator_state_t *t = (rfsimulator_state_t *) device->priv; - t->typeStamp=ENB_MAGICDL_FDD; + t->typeStamp=ENB_MAGICDL; AssertFatal((t->listen_sock = socket(AF_INET, SOCK_STREAM, 0)) >= 0, ""); int enable = 1; AssertFatal(setsockopt(t->listen_sock, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) == 0, ""); @@ -381,9 +382,9 @@ sin_addr: return 0; } -int start_ue(openair0_device *device) { +static int startClient(openair0_device *device) { rfsimulator_state_t *t = device->priv; - t->typeStamp=UE_MAGICDL_FDD; + t->typeStamp=UE_MAGICDL; int sock; AssertFatal((sock = socket(AF_INET, SOCK_STREAM, 0)) >= 0, ""); struct sockaddr_in addr = { @@ -458,7 +459,7 @@ static int rfsimulator_write_internal(rfsimulator_state_t *t, openair0_timestamp return nsamps; } -int rfsimulator_write(openair0_device *device, openair0_timestamp timestamp, void **samplesVoid, int nsamps, int nbAnt, int flags) { +static int rfsimulator_write(openair0_device *device, openair0_timestamp timestamp, void **samplesVoid, int nsamps, int nbAnt, int flags) { return rfsimulator_write_internal(device->priv, timestamp, samplesVoid, nsamps, nbAnt, flags, false); } @@ -483,7 +484,7 @@ static bool flushInput(rfsimulator_state_t *t, int timeout, int nsamps_for_initi AssertFatal( (conn_sock = accept(t->listen_sock,NULL,NULL)) != -1, ""); setblocking(conn_sock, notBlocking); allocCirBuf(t, conn_sock); - LOG_I(HW,"A ue connected, sending the current time\n"); + LOG_I(HW,"A client connected, sending the current time\n"); struct complex16 v= {0}; void *samplesVoid[t->tx_num_channels]; @@ -534,8 +535,8 @@ static bool flushInput(rfsimulator_state_t *t, int timeout, int nsamps_for_initi // check the header and start block transfer if ( b->headerMode==true && b->remainToTransfer==0) { - AssertFatal( (t->typeStamp == UE_MAGICDL_FDD && b->th.magic==ENB_MAGICDL_FDD) || - (t->typeStamp == ENB_MAGICDL_FDD && b->th.magic==UE_MAGICDL_FDD), "Socket Error in protocol"); + AssertFatal( (t->typeStamp == UE_MAGICDL && b->th.magic==ENB_MAGICDL) || + (t->typeStamp == ENB_MAGICDL && b->th.magic==UE_MAGICDL), "Socket Error in protocol"); b->headerMode=false; if ( t->nextTimestamp == 0 ) { // First block in UE, resync with the eNB current TS @@ -606,7 +607,7 @@ static bool flushInput(rfsimulator_state_t *t, int timeout, int nsamps_for_initi return nfds>0; } -int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, void **samplesVoid, int nsamps, int nbAnt) { +static int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, void **samplesVoid, int nsamps, int nbAnt) { if (nbAnt != 1) { LOG_W(HW, "rfsimulator: only 1 antenna tested\n"); } @@ -748,31 +749,24 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo signal_energy(samplesVoid[0], nsamps)); return nsamps; } -int rfsimulator_request(openair0_device *device, void *msg, ssize_t msg_len) { - abort(); + +static int rfsimulator_get_stats(openair0_device *device) { return 0; } -int rfsimulator_reply(openair0_device *device, void *msg, ssize_t msg_len) { - abort(); +static int rfsimulator_reset_stats(openair0_device *device) { return 0; } -int rfsimulator_get_stats(openair0_device *device) { +static void rfsimulator_end(openair0_device *device) {} +static int rfsimulator_stop(openair0_device *device) { return 0; } -int rfsimulator_reset_stats(openair0_device *device) { +static int rfsimulator_set_freq(openair0_device *device, openair0_config_t *openair0_cfg,int exmimo_dump_config) { return 0; } -void rfsimulator_end(openair0_device *device) {} -int rfsimulator_stop(openair0_device *device) { +static int rfsimulator_set_gains(openair0_device *device, openair0_config_t *openair0_cfg) { return 0; } -int rfsimulator_set_freq(openair0_device *device, openair0_config_t *openair0_cfg,int exmimo_dump_config) { - return 0; -} -int rfsimulator_set_gains(openair0_device *device, openair0_config_t *openair0_cfg) { - return 0; -} -int rfsimulator_write_init(openair0_device *device) { +static int rfsimulator_write_init(openair0_device *device) { return 0; } __attribute__((__visibility__("default"))) @@ -782,10 +776,10 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) { rfsimulator_state_t *rfsimulator = (rfsimulator_state_t *)calloc(sizeof(rfsimulator_state_t),1); rfsimulator_readconfig(rfsimulator); pthread_mutex_init(&Sockmutex, NULL); - LOG_I(HW,"rfsimulator: running as %s\n", rfsimulator-> typeStamp == ENB_MAGICDL_FDD ? "(eg)NB" : "UE"); - device->trx_start_func = rfsimulator->typeStamp == ENB_MAGICDL_FDD ? - server_start : - start_ue; + LOG_I(HW,"rfsimulator: running as %s\n", rfsimulator-> typeStamp == ENB_MAGICDL ? "server waiting opposite rfsimulators to connect" : "client: will connect to a rfsimulator server side"); + device->trx_start_func = rfsimulator->typeStamp == ENB_MAGICDL ? + startServer : + startClient; device->trx_get_stats_func = rfsimulator_get_stats; device->trx_reset_stats_func = rfsimulator_reset_stats; device->trx_end_func = rfsimulator_end; @@ -795,7 +789,7 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) { device->trx_write_func = rfsimulator_write; device->trx_read_func = rfsimulator_read; /* let's pretend to be a b2x0 */ - device->type = USRP_B200_DEV; + device->type = RFSIMULATOR; device->openair0_cfg=&openair0_cfg[0]; device->priv = rfsimulator; device->trx_write_init = rfsimulator_write_init; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf index 1cd3b01b6c..760689f653 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf @@ -1,7 +1,6 @@ Active_gNBs = ( "gNB-Eurecom-5GNRBox"); # Asn1_verbosity, choice in: none, info, annoying Asn1_verbosity = "none"; -Num_Threads_PUSCH = 8; gNBs = ( @@ -234,6 +233,7 @@ L1s = ( { num_cc = 1; tr_n_preference = "local_mac"; + pusch_proc_threads = 8; } ); @@ -246,7 +246,7 @@ RUs = ( att_rx = 0; bands = [7]; max_pdschReferenceSignalPower = -27; - max_rxgain = 75; + max_rxgain = 50; eNB_instances = [0]; ##beamforming 1x2 matrix: 1 layer x 2 antennas bf_weights = [0x00007fff, 0x0000]; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpn300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpn300.conf index 0659641607..40361aaf4e 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpn300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpn300.conf @@ -33,7 +33,7 @@ gNBs = # downlinkConfigCommon #frequencyInfoDL # this is 3600 MHz + 84 PRBs@30kHz SCS (same as initial BWP) - absoluteFrequencySSB = 642364; + absoluteFrequencySSB = 642016;#642364; dl_frequencyBand = 78; # this is 3600 MHz dl_absoluteFrequencyPointA = 640000; @@ -130,16 +130,21 @@ gNBs = # 0=unrestricted, 1=restricted type A, 2=restricted type B restrictedSetConfig = 0, # pusch-ConfigCommon (up to 16 elements) - initialULBWPk2_0 = 2; + initialULBWPk2_0 = 6; #2; initialULBWPmappingType_0 = 1 # this is SS=0 L=11 initialULBWPstartSymbolAndLength_0 = 55; - initialULBWPk2_1 = 2; + initialULBWPk2_1 = 6; #2; initialULBWPmappingType_1 = 1; # this is SS=0 L=12 initialULBWPstartSymbolAndLength_1 = 69; + initialULBWPk2_2 = 7; + initialULBWPmappingType_2 = 1; + # this is SS=10 L=4 + initialULBWPstartSymbolAndLength_2 = 52; + msg3_DeltaPreamble = 1; p0_NominalWithGrant =-90; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.273PRB.usrpn300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.273PRB.usrpn300.conf index 0a6268f8a8..a899845cb8 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.273PRB.usrpn300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.273PRB.usrpn300.conf @@ -130,16 +130,21 @@ gNBs = # 0=unrestricted, 1=restricted type A, 2=restricted type B restrictedSetConfig = 0, # pusch-ConfigCommon (up to 16 elements) - initialULBWPk2_0 = 2; + initialULBWPk2_0 = 6;#2; initialULBWPmappingType_0 = 1 # this is SS=0 L=11 initialULBWPstartSymbolAndLength_0 = 55; - initialULBWPk2_1 = 2; + initialULBWPk2_1 = 6;#2; initialULBWPmappingType_1 = 1; # this is SS=0 L=12 initialULBWPstartSymbolAndLength_1 = 69; + initialULBWPk2_2 = 7; + initialULBWPmappingType_2 = 1; + # this is SS=10 L=4 + initialULBWPstartSymbolAndLength_2 = 52; + msg3_DeltaPreamble = 1; p0_NominalWithGrant =-90; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/oaiL1.nfapi.usrpx300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/oaiL1.nfapi.usrpx300.conf new file mode 100644 index 0000000000..5cfd4dc768 --- /dev/null +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/oaiL1.nfapi.usrpx300.conf @@ -0,0 +1,46 @@ +log_config = { + global_log_level ="debug"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="debug"; + mac_log_verbosity ="medium"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="debug"; + rrc_log_verbosity ="full"; +}; + + + +L1s = ( + { + num_cc = 1; + tr_n_preference = "nfapi"; + local_n_if_name = "lo"; + remote_n_address = "127.0.0.2"; // vnf addr + local_n_address = "127.0.0.1"; // pnf addr + local_n_portc = 50000; // pnf p5 port [!] + remote_n_portc = 50001; // vnf p5 port + local_n_portd = 50010; // pnf p7 port + remote_n_portd = 50011; // vnf p7 port + } +); + +RUs = ( + { + local_rf = "yes" + nb_tx = 1 + nb_rx = 1 + att_tx = 0 + att_rx = 0; + bands = [7]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 114; + sdr_addrs = "type=x300"; // USRP type + } +); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band78.tm1.106PRB.nfapi.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band78.tm1.106PRB.nfapi.conf new file mode 100644 index 0000000000..5f65a2c801 --- /dev/null +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band78.tm1.106PRB.nfapi.conf @@ -0,0 +1,290 @@ +Active_gNBs = ( "gNB-Eurecom-5GNRBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + + cell_type = "CELL_MACRO_GNB"; + + gNB_name = "gNB-Eurecom-5GNRBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + + plmn_list = ({mcc = 208; mnc = 93; mnc_length = 2;}); + + tr_s_preference = "local_mac" + + ////////// Physical parameters: + + ssb_SubcarrierOffset = 0; + pdsch_AntennaPorts = 1; + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # this is 3600 MHz + 43 PRBs@30kHz SCS (same as initial BWP) + absoluteFrequencySSB = 641032; + dl_frequencyBand = 78; + # this is 3600 MHz + dl_absoluteFrequencyPointA = 640000; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 106; + #initialDownlinkBWP + #genericParameters + # this is RBstart=41,L=24 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 6366; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 12; + initialDLBWPsearchSpaceZero = 0; + #pdsch-ConfigCommon + #pdschTimeDomainAllocationList (up to 16 entries) + initialDLBWPk0_0 = 0; + #initialULBWPmappingType + #0=typeA,1=typeB + initialDLBWPmappingType_0 = 0; + #this is SS=1,L=13 + initialDLBWPstartSymbolAndLength_0 = 40; + + initialDLBWPk0_1 = 0; + initialDLBWPmappingType_1 = 0; + #this is SS=2,L=12 + initialDLBWPstartSymbolAndLength_1 = 53; + + initialDLBWPk0_2 = 0; + initialDLBWPmappingType_2 = 0; + #this is SS=1,L=12 + initialDLBWPstartSymbolAndLength_2 = 54; + + initialDLBWPk0_3 = 0; + initialDLBWPmappingType_3 = 0; + #this is SS=1,L=5 + initialDLBWPstartSymbolAndLength_3 = 57; + + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 78; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 106; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 6366; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 98; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 13; + preambleReceivedTargetPower = -118; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; +#ra_ReponseWindow +#1,2,4,8,10,20,40,80 + ra_ResponseWindow = 4; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 1, +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + + # pusch-ConfigCommon (up to 16 elements) + initialULBWPk2_0 = 6; + initialULBWPmappingType_0 = 1 + # this is SS=0 L=11 + initialULBWPstartSymbolAndLength_0 = 55; + + initialULBWPk2_1 = 6; + initialULBWPmappingType_1 = 1; + # this is SS=0 L=12 + initialULBWPstartSymbolAndLength_1 = 69; + + initialULBWPk2_2 = 7; + initialULBWPmappingType_2 = 1; + # this is SS=10 L=4 + initialULBWPstartSymbolAndLength_2 = 52; + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant =-90; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -90; +# ssb_PositionsInBurs_BitmapPR +# 1=short, 2=medium, 3=long + ssb_PositionsInBurst_PR = 2; + ssb_PositionsInBurst_Bitmap = 1; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 1; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 1; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 6; + nrofDownlinkSlots = 7; + nrofDownlinkSymbols = 6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; + + ssPBCH_BlockPower = 10; + } + + + ); + + + + srb1_parameters : + { + # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] + timer_poll_retransmit = 80; + + # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] + timer_reordering = 35; + + # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] + timer_status_prohibit = 0; + + # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] + poll_pdu = 4; + + # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] + poll_byte = 99999; + + # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] + max_retx_threshold = 4; + } + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.12.26"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + GNB_INTERFACE_NAME_FOR_S1_MME = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.111/24"; + GNB_INTERFACE_NAME_FOR_S1U = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1U = "192.168.12.111/24"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + } +); + + +MACRLCs = ( + { + num_cc = 1; + local_s_if_name = "lo:"; + remote_s_address = "127.0.0.1"; // pnf addr [!] + local_s_address = "127.0.0.2"; // vnf addr + local_s_portc = 50001; // vnf p5 port + remote_s_portc = 50000; // pnf p5 port [!] + local_s_portd = 50011; // vnf p7 port [!] + remote_s_portd = 50010; // pnf p7 port [!] + tr_s_preference = "nfapi"; + tr_n_preference = "local_RRC"; + } +) + + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_ENABLE"; + } +); + +log_config = + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb.conf index e34b261500..c46ea98ec2 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb.conf @@ -1,7 +1,6 @@ Active_gNBs = ( "gNB-Eurecom-5GNRBox"); # Asn1_verbosity, choice in: none, info, annoying Asn1_verbosity = "none"; -Num_Threads_PUSCH = 8; gNBs = ( @@ -250,6 +249,7 @@ L1s = ( { num_cc = 1; tr_n_preference = "local_mac"; + pusch_proc_threads = 8; } ); @@ -278,6 +278,18 @@ THREAD_STRUCT = ( } ); +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0", "nea2" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia0" ); +}; + log_config : { global_log_level ="info"; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band41.fr1.106PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band41.fr1.106PRB.usrpb210.conf new file mode 100644 index 0000000000..108cf06033 --- /dev/null +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band41.fr1.106PRB.usrpb210.conf @@ -0,0 +1,316 @@ +Active_gNBs = ( "gNB-Eurecom-5GNRBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + + cell_type = "CELL_MACRO_GNB"; + gNB_name = "gNB-Eurecom-5GNRBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + plmn_list = ({mcc = 222; mnc = 93; mnc_length = 2;}); + + tr_s_preference = "local_mac" + + ////////// Physical parameters: + + ssb_SubcarrierOffset = 0; + pdsch_AntennaPorts = 1; + + pdcch_ConfigSIB1 = ( + { + controlResourceSetZero = 12; + searchSpaceZero = 0; + } + ); + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # this is 3600 MHz + 43 PRBs@30kHz SCS (same as initial BWP) + absoluteFrequencySSB = 518670; + dl_frequencyBand = 41; + # this is 3600 MHz + dl_absoluteFrequencyPointA = 514854; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 106; + #initialDownlinkBWP + #genericParameters + # this is RBstart=41,L=24 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 6366; # 6366 12925 12956 28875 +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 12; + initialDLBWPsearchSpaceZero = 0; + #pdsch-ConfigCommon + #pdschTimeDomainAllocationList (up to 16 entries) + initialDLBWPk0_0 = 0; + #initialULBWPmappingType + #0=typeA,1=typeB + initialDLBWPmappingType_0 = 0; + #this is SS=2,L=12 + initialDLBWPstartSymbolAndLength_0 = 53; + + initialDLBWPk0_1 = 0; + initialDLBWPmappingType_1 = 0; + #this is SS=2,L=10 + initialDLBWPstartSymbolAndLength_1 = 81; + + initialDLBWPk0_2 = 0; + initialDLBWPmappingType_2 = 0; + #this is SS=1,L=12 + initialDLBWPstartSymbolAndLength_2 = 95; + + initialDLBWPk0_3 = 0; + initialDLBWPmappingType_3 = 0; + #this is SS=2,L=7 + initialDLBWPstartSymbolAndLength_3 = 86; + + initialDLBWPk0_4 = 0; + initialDLBWPmappingType_4 = 0; + #this is SS=2,L=5 + initialDLBWPstartSymbolAndLength_4 = 58; + + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 41; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 106; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 6366; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 98; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 13; + preambleReceivedTargetPower = -100; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; +#ra_ReponseWindow +#1,2,4,8,10,20,40,80 + ra_ResponseWindow = 4; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 14; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 1, +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + + # pusch-ConfigCommon (up to 16 elements) + initialULBWPk2_0 = 6; + initialULBWPmappingType_0 = 1 + # this is SS=0 L=11 + initialULBWPstartSymbolAndLength_0 = 55; + + initialULBWPk2_1 = 6; + initialULBWPmappingType_1 = 1; + # this is SS=0 L=12 + initialULBWPstartSymbolAndLength_1 = 69; + + initialULBWPk2_2 = 7; + initialULBWPmappingType_2 = 1; + # this is SS=10 L=4 + initialULBWPstartSymbolAndLength_2 = 52; + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant =-90; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -90; +# ssb_PositionsInBurs_BitmapPR +# 1=short, 2=medium, 3=long + ssb_PositionsInBurst_PR = 2; + ssb_PositionsInBurst_Bitmap = 1; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 1; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 1; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 6; + nrofDownlinkSlots = 7; + nrofDownlinkSymbols = 6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; + + ssPBCH_BlockPower = 10; + } + + ); + + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.12.26"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + ///X2 + enable_x2 = "no"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; /* unit: millisecond */ + t_dc_overall = 2000; /* unit: millisecond */ + target_enb_x2_ip_address = ( + { ipv4 = "CI_FR1_CTL_ENB_IP_ADDR"; + ipv6 = "192:168:30::17"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + GNB_INTERFACE_NAME_FOR_S1_MME = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1_MME = "CI_GNB_IP_ADDR"; + GNB_INTERFACE_NAME_FOR_S1U = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1U = "CI_GNB_IP_ADDR"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + GNB_IPV4_ADDRESS_FOR_X2C = "CI_GNB_IP_ADDR"; + GNB_PORT_FOR_X2C = 36422; # Spec 36422 + }; + + } +); + +MACRLCs = ( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + } +); + +L1s = ( + { + num_cc = 1; + tr_n_preference = "local_mac"; + } +); + +RUs = ( + { + local_rf = "yes" + nb_tx = 1 + nb_rx = 1 + att_tx = 0 + att_rx = 0; + bands = [7]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 114; + eNB_instances = [0]; + #beamforming 1x4 matrix: + bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000]; + clock_src = "internal"; + } +); + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + parallel_config = "PARALLEL_SINGLE_THREAD"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_ENABLE"; + } +); + +rfsimulator : +{ + serveraddr = "server"; + serverport = "4043"; + options = (); #("saviq"); or/and "chanmod" + modelname = "AWGN"; + IQfile = "/tmp/rfsimulator.iqs"; +}; + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf index 3d4c3ff92e..4373f38e7b 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf @@ -38,10 +38,10 @@ gNBs = # downlinkConfigCommon #frequencyInfoDL # this is 3600 MHz + 43 PRBs@30kHz SCS (same as initial BWP) - absoluteFrequencySSB = 641272; + absoluteFrequencySSB = 641280; dl_frequencyBand = 78; # this is 3600 MHz - dl_absoluteFrequencyPointA = 640000; + dl_absoluteFrequencyPointA = 640008; #scs-SpecificCarrierList dl_offstToCarrier = 0; # subcarrierSpacing diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index a602e762f1..2e6f148e00 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -583,6 +583,7 @@ int main ( int argc, char **argv ) if (RC.nb_inst > 0) { /* Start the agent. If it is turned off in the configuration, it won't start */ for (i = 0; i < RC.nb_inst; i++) { + if(NFAPI_MODE != NFAPI_MODE_PNF) flexran_agent_start(i); } diff --git a/targets/RT/USER/lte-ue.c b/targets/RT/USER/lte-ue.c index d690b13c2c..407756e20f 100644 --- a/targets/RT/USER/lte-ue.c +++ b/targets/RT/USER/lte-ue.c @@ -787,10 +787,10 @@ static void *UE_thread_rxn_txnp4(void *arg) if ( (proc->sub_frame_start+1)%RX_NB_TH == 0 && threads.one != -1 ) CPU_SET(threads.one, &cpuset); - if ( (proc->sub_frame_start+1)%RX_NB_TH == 1 && threads.two != -1 ) + if ( RX_NB_TH > 1 && (proc->sub_frame_start+1)%RX_NB_TH == 1 && threads.two != -1 ) CPU_SET(threads.two, &cpuset); - if ( (proc->sub_frame_start+1)%RX_NB_TH == 2 && threads.three != -1 ) + if ( RX_NB_TH > 2 && (proc->sub_frame_start+1)%RX_NB_TH == 2 && threads.three != -1 ) CPU_SET(threads.three, &cpuset); //CPU_SET(threads.three, &cpuset);